14

I have users that have purchased items (SkuType.INAPP) from my application.

In the previously recommended implementation of in app billing the IabHelper.QueryInventoryFinishedListener would return an Inventory that contained no items that they owned.

In the new Play Billing Library I use the following method:

Purchase.PurchasesResult purchasesResult = mBillingClient.queryPurchases(BillingClient.SkuType.INAPP);

Assuming the response code is successful, I query:

purchasesResult.getPurchasesList()

For this small percentage of users, the list is empty.

As a fail-safe, for negative results above, I continue to try:

mBillingClient.queryPurchaseHistoryAsync(BillingClient.SkuType.INAPP, this);

The onPurchaseHistoryResponse(final int responseCode, final List<Purchase> purchasesList)

successfully details the purchase.

Perplexed by this, I asked the affected users running both implementations to confirm the following:

  • They only had one Google account on the device
  • The one account received the purchase confirmation email
  • This is the only account option in the Google Play Store app
  • The Google Play Store app 'order history' detailed the purchase

Taking suggestions from this thread, I asked them to:

  • Clear data & cache from the Google Play Store app
  • Reboot
  • Log back into the Google Play Store
  • Open my app again

Despite the above, still, only queryPurchaseHistoryAsync correctly identified that their account owned items.

Question: Why?

The Billing Library implementation states:

queryPurchaseHistoryAsync() returns the most recent purchase made by the user for each SKU, even if that purchase is expired, canceled, or consumed. Use the queryPurchases() method whenever possible as it uses the local cache, in preference to the queryPurchaseHistoryAsync() method.

I have confirmed in my Order Management, that the purchases are valid and have not been cancelled. I do not consume them, therefore they cannot expire.

Now I have a problem

Given that for these users I can only identify their purchases in the above way, I am forced to implement this fail-safe for all.

Apart from being frustrated by the necessity of having to do this, it wouldn't seem like too much of a problem, until you read again:

queryPurchaseHistoryAsync() returns the most recent purchase made by the user for each SKU, even if that purchase is expired, canceled, or consumed

Therefore, in my standard implementation, I need to check that this purchase remains valid.

Unfortunately, the Purchase object has no such method to check its validity.

So, I probably need to perform an external check.


All when my app starts and my logic decides whether or not to show ads.


Help. Please.

brandall
  • 6,094
  • 4
  • 49
  • 103
  • What was common amongst all users experiencing this issue? Something like a specific version of Android (E.g. Older than API 21) or specific Google Play Services Versions ( E.g. Older than 11.3.x). Also is the results list always empty or does it become empty viz. from No ads after purchase to suddenly getting ads? – Karan Modi Feb 24 '18 at 06:16
  • @KaranModi there is no obvious commonality. The users reported that initially, the ads disappeared, so the purchase was correctly identified. After an arbitrary period of usage, the ads appeared again. – brandall Feb 24 '18 at 07:07
  • Seems related to this https://github.com/googlesamples/android-play-billing/issues/92 – Karan Modi Feb 25 '18 at 03:42
  • @KaranModi I would expect the list to be empty (maybe even null, which I'm checking for) for users with no purchases. That bug seems like a code issue, rather than a 'missing purchase' issue. – brandall Feb 25 '18 at 06:40
  • I always used the IInAppBillingService with the AIDL file, without listeners, and never had problems, getPurchases() returns the bought item immediately after the purchase ...the only drawback is that getPurchases() should be called in a separate thread. – from56 Feb 28 '18 at 12:56

0 Answers0