Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle Purchase States with Purchase History Record in new Google In App Purchase

I am trying to create a restore purchase system. I want, the user can reach its bought products whichever device he/she logged in. So I use "queryPurchaseHistoryAsync()" method when app launches. My problem starts here.

With new implementation of Google, On contrary to the documentation, queryPurchaseHistoryAsync() parameters changed. Now it takes list of PurchaseHistoryRecord objects as parameter instead of list of Purchase objects.

Android studio can not resolve the method stated in the documentation. With new queryPurchaseHistoryAsync() I couldn't find anyway to check purchases state.( if it is purchased, canceled or pending). That I was able to do with Purchase object with "purchase.getPurchaseState()" method.

Documentation of 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.
            }
         }
    }
});

My implementation

implementation 'com.android.billingclient:billing:2.0.3'

queryPurchaseHistoryAsync() Method in my app

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());
                             }
                        }
                    }

Release Note of Google(05-2019):

"To minimize confusion, queryPurchaseHistoryAsync() now returns a PurchaseHistoryRecord object instead of a Purchase object. The PurchaseHistoryRecord object is the same as a Purchase object, except that it reflects only the values returned by queryPurchaseHistoryAsync() and does not contain the autoRenewing, orderId, and packageName fields. Note that nothing has changed with the returned data—queryPurchaseHistoryAsync() returns the same data as before."

But neither release note nor documentation state how to check Purchase State with PurchaseHistoryRecord.

Thank you for reading this, any help is appreciated.

like image 359
Eren Tüfekçi Avatar asked Sep 21 '19 08:09

Eren Tüfekçi


People also ask

How do I find my purchased apps on Google Play 2022?

When you're on your Android device, you can find your purchase history by opening the Play Store app and tapping on your profile picture. Once you're there, tap on Payments and subscriptions, followed by Budget and history. You'll see the history of all the apps you've subscribed to on the following page.


1 Answers

So far, I have been using queryPurchases() to restore purchase automatically as it does not require any networking.

Google play app's cache related to account is updating for all devices. In many cases you won't need call to queryPurchaseHistoryAsync call for restoration.

As stated in @bospehre comment. It has drawback as it depends on the cache. So we still need to check purchases situations and restore them with network call.

For queryPurchaseHistory Async call, we can get the purchase sku and token. If you are using server to hold subscription datas as Google recommends. You can check this subscription's situations via your server.

Here is an example for restoring the latest subscription of the user.

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")
            }
}
like image 98
Eren Tüfekçi Avatar answered Nov 13 '22 09:11

Eren Tüfekçi