November 3, 2022
34 min read
We continue our series of articles about the implementation of in-app purchases in a Google Play app. For more posts visit these links:
An example of how we passed errors to our callbacks can be found in this article. We’ve already considered one of the errors in previous articles — this is USER_CANCELED when a user closes the purchase dialog without buying anything. Let’s get to know the others.
Let’s start with the errors called ERROR (responseCode 6) and DEVELOPER_ERROR (responseCode 5). For the first case, Google writes in the documentation “Fatal error during the API action”, for the second one – “Invalid arguments provided to the API”. For example, I was able to get a DEVELOPER_ERROR when I passed an empty string to the builder in setType() for the querySkuDetailsAsync() request.
But it is not that simple. I went further and in the launchBillingFlow() method I used the modified SkuDetails (pulled the json from the SkuDetails of the real product, changed the productID in it and passed it to the new SkuDetails constructor). In fact, this is an invalid argument, and I expected to get a DEVELOPER_ERROR, but … I got an ERROR.
This, of course, was an artificial example. The case when Google rejected the payment is much closer to reality. If you select “test card, always declined” in the purchase dialog when testing purchases from a test card, what we will tell you about at the end of the article, the ERROR will also return, but with a proper text.
In the third article, where the subscription change was described, we increased the price of an annual subscription almost 3 times for one of the proration modes, but did not say what mistake should have been there if we had not done that. We are making amends.
Since it turns out that the wrong proration mode is specified there, we should logically get the same DEVELOPER_ERROR. Instead, we get SERVICE_UNAVAILABLE (responseCode 2). We also get it if we enter any inappropriate number as proration mode (this is int, not enum, no one will stop us), and if we specify the wrong purchaseToken. We look at the documentation about SERVICE_UNAVAILABLE and … wait, what?! We see that the “Network connection is down.”.
At the same time, we also see a weird dialog:
Another interesting thing in the case of ERROR is that when closing the dialog NOT through the “OK” button (namely, by means that are interpreted as “navigate back”), the ERROR comes to onPurchasesUpdated(), and in the case of SERVICE_UNAVAILABLE in a similar situation comes USER_CANCELED (but if you click “OK” in the dialog, we will receive SERVICE_UNAVAILABLE, as expected).
And in the case of lost internet connection there indeed comes SERVICE_UNAVAILABLE.
Here are some more error codes with small comments, so to speak, honorable mentions.
The last and probably the most popular error at the beginning of the in-app purchases implementation path is ITEM_UNAVAILABLE (responseCode 4). It says that the product is not available for purchase, but does not explain why. The reasons can be very different: from testing on the wrong account or device to buying an inactive product.
Here is a checklist of what you need to do to avoid this error while testing:
1. Send an app with the Billing Library to your test track. This is a mandatory condition; at the same time, you can also test on debug builds with the same applicationId, but it is important that the app with the Billing Library is uploaded to the Play Console at least once.
2. Add Google accounts of testers to this test track, which is especially important for internal testing or closed alpha/beta. There will also be a link in the How testers join your test section, where the testers should accept the invitation.
3. You can buy only an activated product. After creating a product, there is an activate button in the Play Console. We described the process of creating a product in more detail in the first article.
4. Make sure that the testing on the device takes place from a tester’s Google account (which means that it must be enrolled as a tester in this test track and must have all the necessary technical access). This point seems to be obvious but things happen, and you also need to check this if you have received such an error.
5. The applicationId of the build which is used for purchase testing must completely match the applicationId from the Play Console. This is especially important for those who have a suffix added in their debug builds.
6. Add the email addresses of testers to the Setup → License Testing section in the left menu of the account (not the application), so that they buy products for free from a test card, not from a real one. Another advantage is that subscriptions in this case will have a test duration. It is not related to this error, but it is also useful knowledge.
Errors can greatly complicate the work, so it is always important to understand how they can occur. Considering how many steps you need to go through to get access to products, the easiest way is to catch ITEM_UNAVAILABLE. Therefore, I hope that my checklist will help you.
The Adapty SDK will facilitate error handling and provide a lot of other advantages: basic subscription analytics, cohort analysis, simple testing of paywalls, integration with analytics services, server error validation. Try it now!
November 3, 2022
34 min read
August 26, 2021
38 min read
April 9, 2021
17 min read