Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
448 views
in Technique[技术] by (71.8m points)

android - Honouring in-app purchases offline + removing cancelled purchases

The approach involved with the two items in the title of this post appear to conflict with one another and are very hard to test, and it's these edge cases that result in unhappy customers when their purchased product stops working.

A lot of the discussions on Stack Overflow are 2+ years old, inconclusive and reference the deprecated AIDL library rather than Google Play Billing Service.

I want to make sure a user has offline access to a premium version of my Android App which is purchased via a one-time non-consumable in-app product on Google Play. I also want to protect against a customer purchasing the upgrade within the App, activating it then cancelling/requesting a refund of the purchase and retaining access to the premium feature.

The documentation states that we can trust the getPurchasesList() to always return the products the customer has access to: https://developer.android.com/google/play/billing/billing_library_overview

However I am also seeing conflicting reports that when the customer goes offline (for example on a long plane journey) the Google cache behind getPurchasesList() eventually expires, which would cause the customer to lose access to the premium content. Some people claim the Google cache expires after around 12 hours, however I put my phone in flight mode for 14 hours and was still getting responses from getPurchasesList(), so maybe those claims are outdated.

When the google billing cache does expire, what is the structure of the response? Is it discernible from a response where the customer has not made any purchases or had a purchase refunded. Let's say we get an empty response from Google when the cache expires, how do we know for sure the difference between:

  • getPurchasesList() contains no purchases, because the customer never made any purchases.
  • getPurchasesList() contains no purchases, because the customer got a refund.
  • getPurchasesList() contains no purchases, because the cache expired, BUT the customer did purchase and owns the product.

There seems to be very little official documentation about this important scenario, the cache lifetime, how to test it, etc. unless I am missing something, somewhere.

I can of course maintain my own cache of the product the customer purchased, eg. store a token that must be updated at least once every 3 days from Google Billing or you lose access, but is this really the correct way to do it?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

IMHO, locally storing the getPurchasesList() response is absolutely fine. I'll elaborate a little bit more.

It all depends what's your threat model: for me, the user can't alter the app code itself nor access the private storage of the app. If a user could do that, then everything falls apart as the user can happily remove or skip the code that limits the app features.

So, given a threat model of an user unable to alter the app nor access the app private storage, you can easily cache the getPurchasesList() response token and use it when the device is offline.

Obviously, any update to the token must be reflected to the cache as well. (e.g. expired or refunded states)

I also agree with you that Google doesn't provide enough information on how to deal with edge cases, they just show the happy case where everything perfectly works.

I must admit I didn't thoroughly look at the sample apps they provide: https://github.com/android/play-billing-samples


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...