【google play】使用Java接入谷歌支付流程
整体流程
- 客户端向Java服务端发起支付,生成预订单,将生成的订单号返回给客户端;
- 客户端向Google发起支付(传入本地服务器生成的订单号);
- Google服务器将支付结果返回给客户端;
- 客户端向Java服务端发送支付结果以及订单号,服务端首先进行验签,通过后更新订单状态以及支付信息。
准备工作
- 应用包名(package_name)
- 密钥文件
密钥内部结构:
{
"type": "",
"project_id": "",
"private_key_id": "",
"private_key": "",
"client_email": "",
"client_id": "",
"auth_uri": "",
"token_uri": "",
"auth_provider_x509_cert_url": "",
"client_x509_cert_url": "",
"universe_domain": ""
}
密钥获取方法:
-
登录Google Cloud Console
访问 Google Cloud Console 并使用Google账号登录。 -
创建项目或选择已有项目
在Google Cloud Console的顶部导航栏中选择一个项目,或者创建一个新项目(点击项目下拉菜单 -> “新建项目”)。 -
启用Google Play Android Developer API
选择项目后,进入“APIs & Services” > “Library”。
搜索 Google Play Android Developer API并启用它。如果项目中没有这个API,就无法进行Google支付相关的操作。 -
创建服务账号密钥(用于后台验证)
在“API和服务” > “凭据”页面,点击 “创建凭据”,选择 服务账号。
为服务账号命名,并为其分配适当的角色(例如角色:Viewer或者Billing Account User)。
服务账号创建后,进入它的详情页面,点击 “密钥” > “添加密钥” > “创建新密钥”。
选择 JSON 格式,系统将自动下载包含Google支付密钥的JSON文件。
注意:这个JSON文件要妥善保管,不能二次获取。 -
安全保存密钥
下载的JSON文件包含敏感的支付密钥信息。请将它保存在安全的地方,并确保在代码库中使用适当的保护措施(如环境变量、加密等)来存储密钥。 -
测试配置
在应用中集成密钥后,可以通过沙盒环境测试Google支付功能,确保支付流程正常运行。
Java实现
- 引入google的pom依赖
<!-- google支付-->
<dependency>
<groupId>com.google.auth</groupId>
<artifactId>google-auth-library-oauth2-http</artifactId>
<version>1.11.0</version>
</dependency>
<dependency>
<groupId>com.google.apis</groupId>
<artifactId>google-api-services-androidpublisher</artifactId>
<version>v3-rev142-1.25.0</version>
</dependency>
- 创建google支付验签用的密钥文件,可以放在Resources下。
- 创建GooglePlayClient类
package com.lensung.sd.api.external.google;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpRequestInitializer;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.androidpublisher.AndroidPublisher;
import com.google.api.services.androidpublisher.AndroidPublisherScopes;
import com.google.api.services.androidpublisher.model.ProductPurchase;
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.GoogleCredentials;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.GeneralSecurityException;
import java.util.Collections;
/**
* @Description
* @ClassName GooglePlayClient
* @Author SunHui
* @Date 2024/11/4 16:21
*/
@Slf4j
@Component
public class GooglePlayClient {
@Value("${google.play.service-account-key}")
private String serviceAccountKeyPath;
private AndroidPublisher getPublisherService() throws GeneralSecurityException, IOException {
GoogleCredentials credentials = GoogleCredentials
.fromStream(Files.newInputStream(Paths.get(serviceAccountKeyPath)))
.createScoped(Collections.singleton(AndroidPublisherScopes.ANDROIDPUBLISHER));
// 使用 HttpCredentialsAdapter 包装 credentials
HttpRequestInitializer requestInitializer = new HttpCredentialsAdapter(credentials);
return new AndroidPublisher.Builder(
GoogleNetHttpTransport.newTrustedTransport(),
JacksonFactory.getDefaultInstance(),
requestInitializer
).setApplicationName("com.lensung.aiyunhua (unreviewed)").build();
}
public ProductPurchase getPurchaseProductInfo(String packageName, String productId, String purchaseToken) {
try {
AndroidPublisher publisher = getPublisherService();
AndroidPublisher.Purchases.Products products = publisher.purchases().products();
return products.get(packageName, productId, purchaseToken).execute();
} catch (Exception e) {
log.error("getPurchaseProductInfo error", e);
return null;
}
}
}
- 业务逻辑service实现类
@Override
public Boolean verifyGooglePayReceipt(AppGooglePayReceiptVerifyParam param) {
String purchaseToken = param.getPurchaseToken();
String productId = param.getProductId();
String orderNo = param.getOrderNo();
ProductPurchase productPurchase = googlePlayClient.getPurchaseProductInfo(GooglePlayConstant.PACKAGE_NAME, productId, purchaseToken);
if (productPurchase == null) {
log.error("[ verify receipt error ] purchaseToken:{}, productId:{}, orderNo:{}", purchaseToken, productId, orderNo);
return false;
}
//0: 购买完成(已支付)。
//1: 购买被取消。
//2: 购买被退款。 通过检查这个字段,后端可以知道购买是否完成或取消。
Integer purchaseState = productPurchase.getPurchaseState();
String googlePlayOrderId = productPurchase.getOrderId();
LocalDateTime purchaseTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(productPurchase.getPurchaseTimeMillis()), ZoneId.systemDefault());
Orders orders = ordersRepository.getByOrderNo(orderNo);
if (Objects.isNull(orders)) {
log.error("[ verify receipt error ] orderNo:{}", orderNo);
return false;
}
// 验证product_id,看返回的product_id与实际的充值金额是不是一致,防止骗单
// ...
if (0 == purchaseState) {
// 支付成功
// 1、更新订单状态
// ...
// 2、发放权益
// ...
return true;
} else {
// 支付失败,打印日志,更新订单信息
// ...
return false;
}
}
- 参数AppGooglePayReceiptVerifyParam
package com.lensung.sd.api.resource.model.param;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* @Description
* @ClassName AppGooglePayReceiptVerifyParam
* @Author SunHui
* @Date 2024/11/4 16:41
*/
@Data
public class AppGooglePayReceiptVerifyParam {
/**
* google支付票据
*/
@NotNull(message = "purchaseToken不能为空")
private String purchaseToken;
/**
* 商品id
*/
@NotNull(message = "productId不能为空")
private String productId;
/**
* 商家自定义订单号
*/
@NotNull(message = "orderNo不能为空")
private String orderNo;
}
原文地址:https://blog.csdn.net/qq_37896194/article/details/143509273
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!