一.接入前准备
#
#
#
#
https://play.google.com/apps/testing/xxx xxx是你应用的包名
#
##注:一定要等你的应用为Published状态之后,在app里面才能查到商品id,执行支付等操作,否则怎么样都查不到
二.集成步骤
#
1.添加依赖
implementation 'com.android.billingclient:billing:2.0.1'
2.添加权限
<uses-permission android:name="com.android.vending.BILLING" />
3.建立连接
mBillingClient = BillingClient.newBuilder(this.mActivity).enablePendingPurchases().setListener(this).build();
mBillingClient.startConnection(new BillingClientStateListener() {
@Override
public void onBillingSetupFinished(BillingResult billingResult) {
Log.e(TAG, "onBillingSetupFinished code = " + billingResult.getResponseCode() + " , msg = " + billingResult.getDebugMessage());
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
@Override
public void onBillingServiceDisconnected() {
4.查询商品信息
private void queryPurchases(@NonNull final String purchaseId) {
if (!isClientInit()) {
if (mListener != null) {
mListener.onError();
return;
List<String> skuList = new ArrayList<>();
skuList.add(purchaseId);
skuList.add("xxx");
SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
params.setSkusList(skuList).setType(BillingClient.SkuType.INAPP);
mBillingClient.querySkuDetailsAsync(params.build(),
new SkuDetailsResponseListener() {
@Override
public void onSkuDetailsResponse(BillingResult billingResult,
List<SkuDetails> skuDetailsList) {
Log.e(TAG, "onSkuDetailsResponse code = " + billingResult.getResponseCode() + " , msg = " + billingResult.getDebugMessage() + " , skuDetailsList = " + skuDetailsList);
if (skuDetailsList == null || skuDetailsList.isEmpty()) {
if (mListener != null) {
mListener.onError();
return;
SkuDetails skuDetails = null;
for (SkuDetails details : skuDetailsList) {
Log.e(TAG, "onSkuDetailsResponse skuDetails = " + details.toString());
if (purchaseId.equals(details.getSku())) {
skuDetails = details;
if (skuDetails != null) {
pay(skuDetails);
} else {
if (mListener != null) {
mListener.onError();
5.执行真正的pay操作
BillingFlowParams flowParams = BillingFlowParams.newBuilder()
.setSkuDetails(details)
.build()
int code = mBillingClient.launchBillingFlow(mActivity, flowParams).getResponseCode()
6.支付回调
还记得前面mBillingClient = BillingClient.newBuilder(this.mActivity).enablePendingPurchases().setListener(this)这个操作吗,这个this也是一个监听器,代表的是支付的回调:
@Override
public void onPurchasesUpdated(BillingResult billingResult, @Nullable List<Purchase> purchases) {
Log.e(TAG, "onPurchasesUpdated code = " + billingResult.getResponseCode() + " , msg = " + billingResult.getDebugMessage());
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK
&& purchases != null) {
if (mListener != null) {
mListener.onSuccess();
for (Purchase purchase : purchases) {
handlePurchase(purchase, true);
} else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.USER_CANCELED) {
if (mListener != null) {
mListener.onCancel();
} else {
if (mListener != null) {
mListener.onError();
7.支付成功之后需要处理订购信息
mBillingClient.consumeAsync(ConsumeParams.newBuilder()
.setDeveloperPayload(purchase.getDeveloperPayload())
.setPurchaseToken(purchase.getPurchaseToken()).build(),
new ConsumeResponseListener() {
@Override
public void onConsumeResponse(BillingResult billingResult, String purchaseToken) {
Log.e(TAG, "onConsumeResponse code = " + billingResult.getResponseCode() + " , msg = " + billingResult.getDebugMessage() + " , purchaseToken = " + purchaseToken);
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
PurchaseHistoryBean purchaseHistory = new PurchaseHistoryBean();
purchaseHistory.uid = NumberParserUtil.parseLong(UserInfoManager.create().getUserId(), -1);
purchaseHistory.orderId = purchase.getOrderId();
purchaseHistory.purchaseToken = purchase.getPurchaseToken();
purchaseHistory.developerPayload = purchase.getDeveloperPayload();
purchaseHistory.productId = purchase.getSku();
purchaseHistory.purchaseTime = purchase.getPurchaseTime();
savePurchaseHistory(purchaseHistory, needToast);
} else {
8.为了保证消费成功之后一定能通知到服务器,我自己处理了一下,先存数据库:
* 保存数据到数据库(已消费的数据)
* @param purchaseHistory 购买记录
private void savePurchaseHistory(final PurchaseHistoryBean purchaseHistory, final boolean needToast) {
PurchaseHistoryResponstory.insert(purchaseHistory, new DBExecuteCallback() {
@Override
public void onSuccess() {
reportServer(purchaseHistory, needToast);
@Override
public void onError() {
reportServer(purchaseHistory, needToast);
9.最后一步,通知服务器,我已经支付成功了,把orderId,productId,purchaseToken等信息上报给服务器。
注:前面mBillingClient. d的操作都建立在连接成功的情况下。但是这几步存在异常的情况,比如说支付成功了,但是没有消费成功(consumeAsync),消费成功了,但是上报服务器失败了,所以需要一些机制保证最后一定能上报给服务器。
三.解决问题
1.支付成功了,但是没有消费成功(consumeAsync),可以在某一个时机查询以前的账号发起的订单信息
* 查询最近的购买交易
* 使用 Google Play 商店应用的缓存,而不发起网络请求
* 建议在应用启动时和 onResume() 方法中调用 至少调用两次
private void queryPurchase() {
if (!isClientInit()) {
return;
Purchase.PurchasesResult purchasesResult = mBillingClient.queryPurchases(BillingClient.SkuType.INAPP);
Log.e(TAG, "queryPurchase code = " + purchasesResult.getResponseCode() + " getPurchasesList = " + purchasesResult.getPurchasesList());
if (purchasesResult.getResponseCode() == BillingClient.BillingResponseCode.OK && !purchasesResult.getPurchasesList().isEmpty()) {
for (Purchase purchase : purchasesResult.getPurchasesList()) {
handlePurchase(purchase, false);
执行成功之后再次处理消费流程handlePurchase(purchase, false);
2.消费成功了,但是通知服务器失败了,还记得之前存入数据库的操作吗savePurchaseHistory,这个时候派上用场了
* 查询列表,上传服务器
private void queryPurchaseHistory() {
PurchaseHistoryResponstory.queryList(new DefaultDBResultCallback<PurchaseHistoryBean>() {
@Override
public void onSuccess(List<PurchaseHistoryBean> purchaseHistoryBeans) {
super.onSuccess(purchaseHistoryBeans);
for (PurchaseHistoryBean purchaseHistory : purchaseHistoryBeans) {
reportServer(purchaseHistory, false);
四.整体流程
五.填坑之路
#
1.应用内无法查询商品id,无法吊起支付窗口:
一定要等你的应用为**Published**状态之后,在app里面才能查到商品id,执行支付等操作,否则怎么样都查不到
2.应用已经发布了,但是还是吊不起支付窗口:
首先app需要安装google三件套,不知道怎么安装的,可以安装一个YouTube,进入app后会自动提示你需要安装google play,需要vpn,然后一定注意了,需要在权限设置里面,把google play的
3.当一切准备就绪之后,报:目前还无法在您所在的国家/地区购买Google Play中的内容。这个因为在中国不允许。解决办法:
网页登录你的google账户:在设置里面,把你的地址改成美国或其他支持的国家,然后清除app内google play的数据,重新进入,重新选择地区(刚才你修改的地区),选完之后会提示你切换到美国的商店,然后再添加付款信息(中国的卡就行,我用的是招商银行的信用卡),这样就万事大吉了,之后就可以正常支付了。
六.测试支付,无需真正付款
整体步骤如下:
1.发布alpha/beta版本,保证应用是已发布状态
2.在alpha/beta版本添加测试人员,并勾选保存
3.把链接发给测试人员,让其点击链接加入测试
4.在账户详细信息里面,添加许可测试的邮箱账号,许可测试响应改为 “RESPOND_NORMALLY/LICENSED”,点击保存,需要一两分钟生效
注:测试支付时遇到一个特别奇葩的问题,刚开始一两次支付显示的是“测试支付,无需付款”,后面再次支付居然要求用信用卡支付。然后,我在“许可测试” 这里,RESPOND_NORMALLY/LICENSED,切换一下就又好了(有时候需要支付时点击一下“税费另计”才会显示是测试支付),以此反复。 这里还没有想明白是那个环节出了问题。
来来回回折腾了几天时间,主要是填写google play上的信息,审核,以及填坑占大部分,接入还是比较简单的,这里主要是做记录,方便以后查看。复制代码