安卓集成Google Play支付(谷歌支付)最新版本

Google Play 支付文档:https://developer.android.com/google/play/billing/integrate

Google Play 支付库已经升级到5.0了,相对之前的版本有不少的变化,现在记录下!

接入Google Play 流程还是和之前一样:

1.去Google console 申请开发者账号  https://play.google.com/console/  

2.创建项目,上传APK

3.去Google console项目后台开始设置商品:点击左侧Products---->In-app products(内购商品)或者Subscription(订阅商品)

 4.等Google Pay Console 后台创建好商品后,客户端和后端就可以开始集成了:

  4.1:将 Google Play 结算库依赖项添加到应用的

dependencies {
    val billing_version = "5.0.0"

    implementation("com.android.billingclient:billing:$billing_version")
}

4.2:初始化支付SDK(也就是初始化BillingClient):支付过程中BillingClient用的比较多,一般项目中只创建一个BillingClient

private BillingClient billingClient = BillingClient.newBuilder(context)
    .setListener(purchasesUpdatedListener)
    .enablePendingPurchases()
    .build();

初始化的时候需要一个:PurchasesUpdatedListener,PurchasesUpdatedListener是监听应用中所有购买交易的更新,这个listener非常重要,当用户购买或者订阅后都会走这个回调

private PurchasesUpdatedListener purchasesUpdatedListener = new PurchasesUpdatedListener() {
    @Override
    public void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {
        // To be implemented in a later section.
    }
};

4.3初始化SDK后,需要与 Google Play 建立连接,使用startConnection()方法,startConnection是异步进行,这个时候需要一个BillingClientStateListener进行回调连接的结果,当连接完成会走onBillingSetupFinished()回调,通过返回的billingResult.getResponseCode()去判断是否真正的链接成功,这个code 有下面几个值,这个BillingClientStateListener还有一个Google Play 失去连接的回调,这个时候我们需要实现重试逻辑,就是再次调用startConnection()函数。

    @Retention(RetentionPolicy.SOURCE)
    public @interface BillingResponseCode {
        int SERVICE_TIMEOUT = -3;
        int FEATURE_NOT_SUPPORTED = -2;
        int SERVICE_DISCONNECTED = -1;
        int OK = 0;
        int USER_CANCELED = 1;
        int SERVICE_UNAVAILABLE = 2;
        int BILLING_UNAVAILABLE = 3;
        int ITEM_UNAVAILABLE = 4;
        int DEVELOPER_ERROR = 5;
        int ERROR = 6;
        int ITEM_ALREADY_OWNED = 7;
        int ITEM_NOT_OWNED = 8;
    }
  public void startConnection() {
        mBillingClient.startConnection(new BillingClientStateListener() {
            @Override
            public void onBillingSetupFinished(BillingResult billingResult) {
                if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                    // The BillingClient is ready. You can query purchases here.
                    queryProductDetailsParams();
                    queryOldOrder();
                }
            }

            @Override
            public void onBillingServiceDisconnected() {
                // Try to restart the connection on the next request to
                // Google Play by calling the startConnection() method.
            }
        });
    }

 4.4 获取商品

      当startConnection()回调成功时,这个时候我们就可以根据ProductId去Google Play获取具体的商品了,这个时候一般会通过API去自己的Server 获取一个ProductIdList,然后根据后台返回的productId去Google Play 获取商品详情。

查询内购的商品:

  List<String> skuList = new ArrayList<>();
        skuList.add("ProductId01");
        skuList.add("ProductId02");
        skuList.add("ProductId03");
        skuList.add("ProductId04");
        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) {
                // Process the result.
                Log.i(TAG, "querySkuDetailsAsync 1 onSkuDetailsResponse billingResult.getResponseCode : " + billingResult.getResponseCode() + " skuDetailsList :" + skuDetailsList);
                mInAppSkuDetailsHashMap.clear();
                if (skuDetailsList != null && skuDetailsList.size() > 0) {
                    for (SkuDetails skuDetails : skuDetailsList) {
                        mInAppSkuDetailsHashMap.put(skuDetails.getSku(), skuDetails);
                    }
                }
            }
        });

查询订阅的商品:

 // The BillingClient is ready. You can query purchases here.
        List<String> subscribeSkuList = new ArrayList<>();
        subscribeSkuList.add("Subscribe01");
        subscribeSkuList.add("Subscribe01");
        subscribeSkuList.add("Subscribe01");
        SkuDetailsParams.Builder subscribeParams = SkuDetailsParams.newBuilder();
        subscribeParams.setSkusList(subscribeSkuList).setType(BillingClient.SkuType.SUBS);
        mBillingClient.querySkuDetailsAsync(subscribeParams.build(), new SkuDetailsResponseListener() {
            @Override
            public void onSkuDetailsResponse(BillingResult billingResult, List<SkuDetails> skuDetailsList) {
                // Process the result.
                Log.i(TAG, "querySkuDetailsAsync 2 onSkuDetailsResponse billingResult.getResponseCode : " + billingResult.getResponseCode() + " skuDetailsList :" + skuDetailsList);
                mSubscribeSkuDetailsHashMap.clear();
                if (skuDetailsList != null && skuDetailsList.size() > 0) {
                    for (SkuDetails skuDetails : skuDetailsList) {
                        mSubscribeSkuDetailsHashMap.put(skuDetails.getSku(), skuDetails);
                    }
                }
            }
        });

当商品查询成功后就可以结合Server返回的商品信息给用户展示商品列表了

注意:有些 Android 设备安装的可能是旧版 Google Play 商店应用,不支持订阅等某些商品类型。在您的应用进入结算流程之前,您可以调用 isFeatureSupported() 以确定设备是否支持您要销售的商品。如需查看可支持的商品类型的列表,请参阅 BillingClient.FeatureType

4.5.启动购买流程(开始购买)

   当用户点击某个商品时,从应用发起购买请求,请从应用的主线程调用 launchBillingFlow() 方法。此方法接受对 BillingFlowParams 对象的引用,该对象包含通过调用 queryProductDetailsAsync() 获取的相关 ProductDetails 对象。如需创建 BillingFlowParams 对象,请使用 BillingFlowParams.Builder 类。

购买内购的商品:

    public void buyInAppProduct(SkuDetails skuDetails) {
        if (skuDetails == null) {
            return;
        }
        BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
                .setSkuDetails(skuDetails)
                .build();
        mBillingClient.launchBillingFlow(ActivityUtils.getTopActivity(), billingFlowParams).getResponseCode();
    }

购买订阅的商品:

  public void buySubscribeProduct(SkuDetails skuDetails) {
        if (skuDetails == null) {
            return;
        }
        BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
                .setSkuDetails(skuDetails)
                .build();
        mBillingClient.launchBillingFlow(ActivityUtils.getTopActivity(), billingFlowParams).getResponseCode();
    }
// An activity reference from which the billing flow will be launched.
Activity activity = ...;

ImmutableList productDetailsParamsList =
    ImmutableList.of(
        ProductDetailsParams.newBuilder()
             // retrieve a value for "productDetails" by calling queryProductDetailsAsync()
            .setProductDetails(productDetails)
            // to get an offer token, call ProductDetails.getSubscriptionOfferDetails()
            // for a list of offers that are available to the user
            .setOfferToken(selectedOfferToken)
            .build()
    );

BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
    .setProductDetailsParamsList(productDetailsParamsList)
    .build();

// Launch the billing flow
BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams);

4.6购买成功的回调

 在咱们4.2初始化SDK的时候添加了一个PurchasesUpdatedListener,当用户购买成功后Google Play 会调用 onPurchasesUpdated(),我们根据responseCode去区分用户购买成功与否.

如果成功购买商品,系统还会生成一个token,它是一个唯一标识符,表示用户及其所购应用内商品的商品 ID。可以在本地存储token,可以将令牌传递到安全的后端服务器(推荐用该方法)

    private PurchasesUpdatedListener purchasesUpdatedListener = new PurchasesUpdatedListener() {
        @Override
        public void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {
            if (billingResult == null) {
                return;
            }
            int responseCode = billingResult.getResponseCode();
            switch (responseCode) {
                case BillingClient.BillingResponseCode.OK:
                    for (Purchase purchase : purchases) {
                        SkuDetails skuDetails = null;
                        String json = purchase.getOriginalJson();
                        if (!TextUtils.isEmpty(json)) {
                            PurchaseData purchaseData = GsonConverter.fromJson(json, PurchaseData.class);
                            if (purchaseData != null) {
                                skuDetails = getSkuDetailsDependProductId(purchaseData.getProductId());
                            }
                        }
                        handlePurchase(purchase, (skuDetails != null && (BillingClient.SkuType.SUBS.equals(skuDetails.getType()))), "onPurchasesUpdated");
                    }
                    break;
                case BillingClient.BillingResponseCode.USER_CANCELED:
                    Log.i(TAG, "purchasesUpdatedListener 3 user cancel ");
                    break;
                default:
                    Log.i(TAG, "purchasesUpdatedListener 4 error  " + responseCode);
                    break;
            }
        }
    };
@Override
void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {
    if (billingResult.getResponseCode() == BillingResponseCode.OK
        && purchases != null) {
        for (Purchase purchase : purchases) {
            handlePurchase(purchase);
        }
    } else if (billingResult.getResponseCode() == BillingResponseCode.USER_CANCELED) {
        // Handle an error caused by a user cancelling the purchase flow.
    } else {
        // Handle any other error codes.
    }
}

4.7.处理购买交易(消费订单)

当用户购买成功后,订单必须消费,如果不消费,三天后Google会自动退款,撤销购买交易。
消费内购的商品:

void handlePurchase(Purchase purchase) {
    // Purchase retrieved from BillingClient#queryPurchasesAsync or your PurchasesUpdatedListener.
    Purchase purchase = ...;

    // Verify the purchase.
    // Ensure entitlement was not already granted for this purchaseToken.
    // Grant entitlement to the user.

    ConsumeParams consumeParams =
        ConsumeParams.newBuilder()
            .setPurchaseToken(purchase.getPurchaseToken())
            .build();

    ConsumeResponseListener listener = new ConsumeResponseListener() {
        @Override
        public void onConsumeResponse(BillingResult billingResult, String purchaseToken) {
            if (billingResult.getResponseCode() == BillingResponseCode.OK) {
                // Handle the success of the consume operation.
            }
        }
    };

    billingClient.consumeAsync(consumeParams, listener);
}

  消费订阅商品:订阅的处理方式与非消耗型商品类似。您可以使用 Google Play 结算库中的 BillingClient.acknowledgePurchase() 或 Google Play Developer API 中的 Purchases.Subscriptions.Acknowledge 确认订阅。所有初始订阅购买交易都需要确认。订阅续订不需要确认

BillingClient client = ...
AcknowledgePurchaseResponseListener acknowledgePurchaseResponseListener = ...

void handlePurchase(Purchase purchase) {
    if (purchase.getPurchaseState() == PurchaseState.PURCHASED) {
        if (!purchase.isAcknowledged()) {
            AcknowledgePurchaseParams acknowledgePurchaseParams =
                AcknowledgePurchaseParams.newBuilder()
                    .setPurchaseToken(purchase.getPurchaseToken())
                    .build();
            client.acknowledgePurchase(acknowledgePurchaseParams, acknowledgePurchaseResponseListener);
        }
    }
}

4.8 查询历史订单,消费待处理的交易

    public void queryOldOrder() {
        mBillingClient.queryPurchasesAsync(BillingClient.SkuType.INAPP, new PurchasesResponseListener() {
            @Override
            public void onQueryPurchasesResponse(@NonNull BillingResult billingResult, @NonNull List<Purchase> list) {
                if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                    onHandlerQueryPurchases(list, false);
                }
            }
        });

        mBillingClient.queryPurchasesAsync(BillingClient.SkuType.SUBS, new PurchasesResponseListener() {
            @Override
            public void onQueryPurchasesResponse(@NonNull BillingResult billingResult, @NonNull List<Purchase> list) {
                if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                    onHandlerQueryPurchases(list, true);
                }
            }
        });

4.9 处理多件购买交易:

Google Play 允许客户在一笔交易中购买多件相同的应用内商品,只需在购物车中指定商品数量即可(4.0 及更高版本的 Google Play 结算库支持该功能)。应用应根据指定购买数量来处理多件购买并授予权利。注意:多件购买适用于消耗型应用内商品,即可以购买、消耗及再次购买的产品。请勿为不支持重复购买的商品启用该功能。

为了实现多件购买,应用的配置逻辑需要检查商品数量。可以从以下 API 访问 quantity 字段:

添加用于处理多件购买的逻辑后,需要在 Google Play 管理中心的应用内商品管理页面上为相应的商品启用多件购买功能。

注意:请确保应用接受多件购买,然后再在 Play 管理中心启用该功能。您能需要强制更新到提供支持的应用版本,然后才能对商品启用该功能。

猜你喜欢

转载自blog.csdn.net/Jason_HD/article/details/126979555
今日推荐