1
votes

I am trying to implement in-app billing (V3) into an application. The item that will be purchased will make the application ad-free. This item will be a non-consumable item.

I have implemented the code according to Google documentation but I have some trouble understanding the payload parameter. I am confused as to why it is better that the payload string will be stored on a private server and if so, how it will bind the user with the purchase. What I want is that once the user buys the ad-free version of the application, he can use it on another device (where he is using the email that he used to make the initial purchase). If I use a random or empty payload string, will the user be able to use the ad-free version on another device? From what I understood, the purchase information is kept on Google, so normally the user will be able to do this. If so, why is it better that the payload is saved on another server (maintained by me)? Here is the related text from Google documentation:

You should pass in a string token that helps your application to identify the user who made the purchase, so that you can later verify that this is a legitimate purchase by that user. For consumable items, you can use a randomly generated string, but for non-consumable items you should use a string that uniquely identifies the user. When you get back the response from Google Play, make sure to verify that the developer payload string matches the token that you sent previously with the purchase request. As a further security precaution, you should perform the verification on your own secure server.

Does the above mean that I should use the user's email address as the payload string? If this is the case, the verification will be that the payload returned by the purchase process matches the user's email. Why should this be performed on a secure server?

1
It should be on a secure server so that a malicious user can't reverse engineer your app and use an edited version that doesn't check the payload for validity. Whether avoiding that risk is worth setting up a server to do it is up to you.nasch
But if a user can reverse engineer the application, can't he also change the code that does the validation on the server and make it always return true? I also do not understand the validation process. Isn't it just a simple comparison of the email address returned by Google to the actual email on the device?a.p.
Great point, and I'm actually not sure of the answer. Obviously there are plenty of free/paid apps out there, but having never made one I'm not sure if this can be done securely all in one app, or if it's necessary to have one app free and a separate app paid. That is certainly a simple way to do it for you, though a little more complicated for the user. Sorry I can't be more help. Have you done some research on how people are tackling the free trial for a paid app issue?nasch
Yes, I have. I guess that having two separate versions of the application (free and premium) is safer but requires double the work (you basically have to maintain two separate versions and do everything twice). Keeping a single version and making it premium using in-app purchases is much simpler for the developer but I guess it has its risks.a.p.
It doesn't really require double the work. Use Android Studio if you're not already, and look into using flavors. One flavor for free and one for paid, and then nothing will be duplicated.nasch

1 Answers

0
votes

After reading some more relevant posts, I have come to the following conclusion/solution:

On use purchase, I generate a random unique string. I save this string in preferences and use it as a payload. On getting the response from Google Play, I check and make sure that the payload matches the one saved in preferences (or a local variable). On activity start, I just check with Google server if the user has purchased the specific item - here I will not use the payload since it will be lost in case the user changes a device or resets the application.

This should work well for a non-consumable item - it is not the best solution but for my case, it is good enough. The best solution would be to generate a random string and pass it together with the current user's email to a private, secure server as well as to the Google server as the payload. This was, one can check the payload returned by Google after the purchase as well as on Activity start, to verify that the user purchase is valid.