Android 如何在新的Google应用内购买中处理具有购买历史记录的购买状态

Android 如何在新的Google应用内购买中处理具有购买历史记录的购买状态,android,in-app-purchase,in-app-billing,play-billing-library,Android,In App Purchase,In App Billing,Play Billing Library,我正在尝试创建一个恢复购买系统。我想,用户可以访问其购买的产品,无论他/她登录哪个设备。所以我在应用程序启动时使用“queryPurchaseHistoryAsync()”方法。我的问题从这里开始 与文档相反,Google的新实现改变了queryPurchaseHistoryAsync()参数。现在它将PurchaseHistoryRecord对象列表作为参数,而不是PurchaseHistoryRecord对象列表 Android studio无法解析文档中所述的方法。使用新的queryPur

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

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

Android studio无法解析文档中所述的方法。使用新的queryPurchaseHistoryAsync()时,我找不到任何检查购买状态的方法。(如果是已购买、已取消或挂起)。我可以通过“Purchase.getPurchaseState()”方法处理Purchase对象

queryPurchaseHistoryAsync()的文档

我的应用程序中的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());
                             }
                        }
                    }
billingClient.queryPurchaseHistoryAsync(billingClient.SkuType.INAPP,
新的PurchaseHistoryResponseListener(){
@凌驾
PurchaseHistoryResponse(BillingResult BillingResult,List purchaseHistoryRecordList)上的公共无效{
如果(billingResult.getResponseCode()==BillingClient.BillingResponseCode.OK
&&purchaseHistoryRecordList!=空){
用于(PurchaseHistoryRecord PurchaseHistoryRecord:purchaseHistoryRecordList){
HandleOldGetting(purchaseHistoryRecord.getSku());
}
}
}
谷歌发布说明(2019年5月):

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

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


感谢您阅读本文,非常感谢您的帮助。

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

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

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

对于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")
            }
}

使用“queryPurchases()”它有一个固有的缺点,即它不是实时的。在其他设备上进行的购买可能需要几天才能显示出来,然后才能进行适当的同步,甚至更长时间。因此,我被用户的抱怨淹没了。这个答案是非常错误的,建议进行queryPurchase是的,如果您的internet连接处于活动状态,我将此设置为:ConnectionManagercm=(ConnectionManager)context.getSystemService(context.CONNECTIVITY_SERVICE);NetworkInfo-activeNetwork=cm.getActiveNetworkInfo();
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());
                             }
                        }
                    }
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")
            }
}