I have an app that we have sold for many years as a one-time purchase. There are no in-app products of any kind.
We are working on an update that will offer subscription products. I would like to offer users who previously purchased the app outright an incentive to switch to our subscription plan. In order to do this, I'd like to allow the user to send their purchase token to our server for us to verify.
I can see where Google exposes an API method to verify subscriptions:
https://developers.google.com/android-publisher/api-ref/rest/v3/purchases.subscriptions/get
...and one to verify in-app products:
https://developers.google.com/android-publisher/api-ref/rest/v3/purchases.products/get
But I'm not seeing anywhere where it's possible to verify that the actual app itself has been purchased.
Any pointers would be greatly appreciated!
Probably because the verification of app purchases, particularly for apps sold as a one-time purchase without in-app items or subscriptions, would involve a different approach.
Google's Licensing API is designed to help you enforce licensing policies for apps that are published on Google Play. While the Licensing API is primarily aimed at preventing unauthorized use, it can also be utilized to check if the app has been purchased by the user. You would need to integrate the Licensing API into your app, and set up your server to validate the license status.
Since you want to introduce a subscription model, consider converting your app to a free download with an IAP option for the full features.
For existing users who have already purchased the app, you can grant them the full features via an in-app purchase entitlement. This migration would allow you to use the existing in-app purchase verification APIs for both old and new users.
To identify previous purchasers:
SharedPreferences.The latter: neither SharedPreferences nor DataStore come pre-populated with purchase information or have a built-in way to directly check for app purchases. They are general-purpose storage solutions meant to save app data across sessions.
The idea remains to use them as a mechanism to track the app's state or specific conditions set by your logic, especially after manually handling the migration process for existing users to the new subscription model.
Meaning:
Upon app launch (or at the relevant point in your app), check the SharedPreferences or DataStore for the presence of this entitlement flag. If the flag is set, treat the user as having full access to the app's features. That is a manual process you implement as part of transitioning your app's monetization model.
That does not involve verifying the app purchase directly at the time of the check. Instead, it relies on you having correctly identified and flagged users as having previously purchased the app at the time of the app update. You might have to securely verify the user's purchase status before the app update, and then securely set the flag during the app's first launch post-update.
The LVL can indeed be used to check if the app has been legitimately purchased from Google Play. That verification includes sending the license check response from Google Play to your server for further verification if needed. However, LVL does not directly provide information about the purchase price or the purchase date.
Directly verifying that the app was purchased for a price greater than $0, or before a specific date, using LVL or Google Play's API, is not straightforward because these APIs are not designed to return historical purchase data or pricing information.
If you wish to verify purchase details such as the price paid or the purchase date, you might need to maintain records of the original purchase transactions on your server. That could involve storing transaction details at the time of purchase, which can then be queried during the migration process.
True: the local storage solutions like DataStore or SharedPreferences will not retain information once the app is uninstalled. That necessitates a solution that can persist outside of the local device storage.
You would need a server-side verification with user accounts: implement user accounts in your app where users can register and login. When a user purchases the app (while it is still a one-time purchase), record this transaction against their user account on your server.
Upon reinstalling the app, regardless of the device, the user can log in to their account, allowing your server to verify their purchase history and restore the appropriate access rights. That would require a reliable backend system to manage user accounts and transaction records but offers a seamless experience for users across devices and reinstallation scenarios.
Another option would be to use Google Play's capabilities to query a user's purchase history for your app. That is more complex than working with the LVL, but can be achieved by integrating Google Play's billing library and querying for past purchases when the app is reinstalled. You would need to implement logic in your app to query for these transactions and, based on the response, restore access to the full features of the app.
You might consider a combination of the above strategies for a robust solution: use server-side verification with user accounts as the primary method for maintaining purchase records and restoring access. Supplement this with Google Play receipts and order history checks for users who might not have created an account but can prove purchase via Google Play.
But, as Brian Rak mentions in the comments:
And it seems that there is indeed no supported way to verify that a given user installing the (now free) app previously paid for it.