- Paid applications
- In-App purchases
- Managed and non-managed subscriptions
It is fairly straightforward situation with the paid applications: you have to publish the application properly, set the prices and collect the money through the merchant service.
Subscriptions are slightly more complicated matters and we leave it to some other time. What i would like to talk about now is In-App purchases and explicitly the issue of testing them.
The Android developer's guide recommends two stage approach when testing the in-app purchases:
- Testing with the static responses
- Testing in the in-app billing sandbox
Developer's guide also provides quite comprehensive workable samples. The only problem is that there are number of things that are not mentioned in the developer's guide (or hidden that i could not find them).
First of all, let's take a look at the testing with the static responses. The developer's guide advises to use this approach to ensure that application correctly handles the responses from Google Play. The testing with the static responses uses predefined SKUs to test various scenarios where the Google Play sends the specific responses for each of the SKU.
First test scenario logically would be to test the purchase flow using the android.test.purchased product ID. It might even work for the first time when you try to initiate the purchase flow. But then when you code suppose to query the status of the purchases it will always fail.
The reason for such behavior that the sample's Security class attempts to validate if the data are signed with the correct key. The problem is that the static responses are not signing the data, i.e. the signature is empty, hence the Security.verifyPurchase and Security.verify methods will fail. In order to be able to test the code with the static responses the good idea is to include the following line at the beginning of each of the above methods:
if (BuildConfig.DEBUG) {
return true;
}
Essentially, it will skip validation phase if the code is built using debugging profile.
The other problem is that once the test purchase is completed it is not automatically disappears, i.e. it is not possible to re-test the scenario any time soon. The documentation suggests that it will automatically be released in 14 days but i never tried to wait that long.
In order to be able to re-test the application with the static responses the purchased product must be consumed.
In my case, i have created a menu option to consume the product which only visible when BuildConfig is not DEBUG. In order to be able to re-use the IabHelper.consumeAsync method i had to provide an additional constructor to the Purchase class that takes the SKU and item type only and also modified the IabHelper.consumeAsync method to build the purchaseToken if it is not set at the beginning of the method.
It could be done cleaner is suppose if first the code would query the purchases and then release them one by one but as a quick hack the proposed solution is ok.
In-app billing sandbox testing also did not go smooth. Well, the transaction was handled correctly but then, documentation states that in order to re-test the transaction must be cancelled, which is exactly what i have done, however the product is still shows up as purchased.
In order to be able to re-test the application with the static responses the purchased product must be consumed.
In my case, i have created a menu option to consume the product which only visible when BuildConfig is not DEBUG. In order to be able to re-use the IabHelper.consumeAsync method i had to provide an additional constructor to the Purchase class that takes the SKU and item type only and also modified the IabHelper.consumeAsync method to build the purchaseToken if it is not set at the beginning of the method.
It could be done cleaner is suppose if first the code would query the purchases and then release them one by one but as a quick hack the proposed solution is ok.
In-app billing sandbox testing also did not go smooth. Well, the transaction was handled correctly but then, documentation states that in order to re-test the transaction must be cancelled, which is exactly what i have done, however the product is still shows up as purchased.
ok, got it. So, the Google play service is caching the purchases data on the device. And Google only knows how the algorithm that decides when the cached in-app purchase should be queried again. This is why in my tests the cancelled purchase was still showing as active.
ReplyDeleteAs wise internet users are suggesting there are two ways to force the purchase status to get requested from the server:
- initialise the purchase flow
- reboot device
The second option works intermittently, i.e. it did not help me at lease on one occasion.