Search code examples
androidin-app-purchasein-app-billingandroid-inapp-purchaseplay-billing-library

Does queryPurchases() from Play Billing Library guarantees retrieving a valid purchase?


I'm using the Google Play Billing Library and I read the documentation and all questions about validating the purchases on the server and how to inquiry the purchases.

However, some points are still not clear and I couldn't find answers to them here.

To retrieve purchases the next time the user launches the app, the documentation says we should use BillingClient.queryPurchases() and it says about the list obtained from this method:

As long as the in-app product is on this list, the user should have access to it.

What I understand from this is that queryPurchases() alone guarantees that the user really bought the item and he must get access to it.

Is this True?

  • If Yes, then why we don't just use this method right after the user makes a purchase as a validation instead of validating it on the server?
  • If No, how can I provide access for the user if I don't want to validate his purchase on my server each time he launches the app?
  • If I saved the purchase on a local database after the first validation and inquired it when the app launches to grant user access to his items, is this a secure approach or this database can be manipulated from a malicious user to grant himself access to the premium content?

Solution

  • Welcome to stackoverflow!

    queryPurchases() is totally safe if the signature of the received data is verified reliably.

    The problem is that there are some hacker apps that allow people to make fraudulent purchases and it also alter the device's code so it returns ok to any signature verification. This is only possible on rooted devices and it is unlikely to happen because Google is closely following the problem, but it is still possible!.

    A fraudulent purchase will never have a correct signature since it can only be generated with a key that the Play Console generated exclusively for your app.

    Many programmers unfortunately forget to verify the signatures in their code and for what has been said before it is much better that it is verified on an external server that can not be altered by the hacker app.

    When Google refers to server side verification it refers to verifying the signature on a server, not that you have to keep a parallel list of purchases.

    Here is an example of how to do it, the data to verify is that of purchase.getOriginalJson() and the signature is in purchase.getSignature() https://stackoverflow.com/a/48531877/7690376

    Hope it will help.

    Update: It is also convenient to provide another signature verification alternative in your code in case your server is down or there is no internet access.