如何在新的 Google In App Purchase 中使用购买历史记录处理购买状态

Ere*_*kçi 10 android in-app-purchase in-app-billing play-billing-library

我正在尝试创建一个恢复购买系统。我希望,用户可以通过他/她登录的任何设备访问其购买的产品。所以我在应用程序启动时使用“queryPurchaseHistoryAsync()”方法。我的问题从这里开始。

随着 Google 的新实现,与文档相反,queryPurchaseHistoryAsync() 参数发生了变化。现在它将 PurchaseHistoryRecord 对象列表作为参数而不是 Purchase 对象列表。

Android studio 无法解析文档中所述的方法。使用新的 queryPurchaseHistoryAsync() 无论如何我都找不到检查购买状态。(如果它已购买、取消或待处理)。我能够使用“purchase.getPurchaseState()”方法处理 Purchase 对象。

queryPurchaseHistoryAsync() 的文档

billingClient.queryPurchaseHistoryAsync(SkuType.INAPP,
                                         new PurchaseHistoryResponseListener() {
    @Override
    public void onPurchaseHistoryResponse(BillingResult billingResult,
                                          List<Purchase> purchasesList) {
        if (billingResult.getResponseCode() == BillingResponse.OK
                && purchasesList != null) {
            for (Purchase purchase : purchasesList) {
                // Process the result.
            }
         }
    }
});
Run Code Online (Sandbox Code Playgroud)

我的实现

implementation 'com.android.billingclient:billing:2.0.3'
Run Code Online (Sandbox Code Playgroud)

我的应用程序中的 queryPurchaseHistoryAsync() 方法

billingClient.queryPurchaseHistoryAsync(BillingClient.SkuType.INAPP,
                new PurchaseHistoryResponseListener() {
                    @Override
                    public void onPurchaseHistoryResponse(BillingResult billingResult, List<PurchaseHistoryRecord> purchaseHistoryRecordList) {

                        if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK
                                && purchaseHistoryRecordList != null) {

                            for (PurchaseHistoryRecord purchaseHistoryRecord : purchaseHistoryRecordList) {

                                HandleOldGetting(purchaseHistoryRecord.getSku());
                             }
                        }
                    }
Run Code Online (Sandbox Code Playgroud)

谷歌发布说明(05-2019):

“为了尽量减少混淆,queryPurchaseHistoryAsync() 现在返回一个 PurchaseHistoryRecord 对象而不是 Purchase 对象。PurchaseHistoryRecord 对象与 Purchase 对象相同,除了它只反映 queryPurchaseHistoryAsync() 返回的值并且不包含 autoRenewing、orderId ,和 packageName 字段。请注意,返回的数据没有任何变化——queryPurchaseHistoryAsync() 返回与以前相同的数据。”

但是发行说明和文档都没有说明如何使用 PurchaseHistoryRecord 检查购买状态。

感谢您阅读本文,任何帮助表示赞赏。

Ere*_*kçi 2

到目前为止,我一直在使用 queryPurchases() 自动恢复购买,因为它不需要任何网络。

正在为所有设备更新与帐户相关的 Google Play 应用缓存。在许多情况下,您不需要调用 queryPurchaseHistoryAsync 调用来进行恢复。

正如@bospehre 评论中所述。它有一个缺点,因为它依赖于缓存。所以我们还是需要检查购买情况,并通过网络调用来恢复。

对于 queryPurchaseHistory 异步调用,我们可以获得购买 sku 和令牌。如果您按照 Google 的建议使用服务器来保存订阅数据。您可以通过您的服务器查看该订阅的情况。

以下是恢复用户最新订阅的示例。

billingManager.billingClient.queryPurchaseHistoryAsync(BillingClient.SkuType.SUBS) { billingResult, purchaseHistoryRecords ->
      
           if (purchaseHistoryRecords != null) {
                var activePurchaseRecord : PurchaseHistoryRecord? = null
                if (purchaseHistoryRecords.size > 0) {
    
    // Get the latest subscription. It may differ for developer needs.
    
                    for (purchaseHistoryRecord in purchaseHistoryRecords) {
                        Log.d(billingLogs, "Purchase History Record : $purchaseHistoryRecord")
        
                        if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
                            if (subSkuListHelper.getSkuList().contains(purchaseHistoryRecord.sku)
                            ) {
        
                                if (activePurchaseRecord == null) {
                                    activePurchaseRecord = purchaseHistoryRecord
                                } else {
                                    if (purchaseHistoryRecord.purchaseTime > activePurchaseRecord.purchaseTime) {
                                        activePurchaseRecord = purchaseHistoryRecord
                                    }
                                }
        
                            }
                        }
        
                    }
                    
        
                        Toast.makeText(
                            this,
                            "Subscription Purchases found, Checking validity...",
                            Toast.LENGTH_SHORT
                        ).show()
        
        
        // Make a network call with sku and purchaseToken to get subscription info
        
        //Subscription Data Fetch is a class that handling the networking
                        activePurchaseRecord?.let { SubscriptionDataFetch(
                            this,
                            billingManager.billingClient
                        )
                            .executeNetWorkCall(
                                getString(R.string.ubscription_check_endpoint),
                                it.sku,
                                it.purchaseToken
                            )
                        }
                    
                }
                else {
                    Log.d(billingLogs, "Purchase History Record not found size 0") }
        
            }
            else {
                Toast.makeText(
                    this,
                    "Purchase not found",
                    Toast.LENGTH_SHORT
                ).show()
        
                Log.d(billingLogs, "Purchase History Record not found null")
            }
}
Run Code Online (Sandbox Code Playgroud)

  • 使用“queryPurchases()”有一个固有的缺点,即它不是实时的。在其他设备上进行的购买可能需要几天时间才能正确同步,甚至更长时间才会出现。因此,我被用户的抱怨淹没了。 (13认同)