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.
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.
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")
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With