The second time Apple's review team rejected my app they told me, they had an error with 21007 when testing the Auto-renewable subscription IAP. I thought them mean I hadn't handled the error and resubmitted the app. I thought it was OK, but today, I got the third rejection.
The reason is still error 21007, this time with the error message I showed to them.
What's Error `21007`
Error 21007 is the code returned from Apple's verification server, means `You are verifying a sandbox receipt with the product verification server`. Similarly, there is another error code 21008 which means `You are verifying a product receipt with sandbox verification server.`. Auto-renewable subscription IAP(In App Purchase) need to verify the receipt with Apple's verification server. And there is a status code returned from Apple's server. Any status code value is not equal to 0 means error.
Table 7-1 Status codes for auto-renewable subscriptions
- 21001The App Store could not read the JSON object you provided.
The data in the receipt-data property was malformed.
The receipt could not be authenticated.
The shared secret you provided does not match the shared secret on file for your account.
The receipt server is not currently available.
This receipt is valid but the subscription has expired. When this status code is returned to your server, the receipt data is also decoded and returned as part of the response.
This receipt is a sandbox receipt, but it was sent to the production service for verification.
This receipt is a production receipt, but it was sent to the sandbox service for verification.
You can also find this from Apple's DevCenter.
<Image is from http://www.phpriot.com/articles/verifying-app-store-receipts-php-curl>
Why does this Happen?
When we build the binary file for Apple to review, we need to define the server URL for production environment. But when we test the app in Debug/Release/AdHoc mode, we need to use the sandbox environment. So usually, we will have a piece of code like this:
Such kind of preprocessor can make sure you don't invoke the sandbox verification URL in real product build.
The server side will invoke different URL based on the request URL's parameter. So here comes the problem.
- You build the AppStore version and submit to review team to review
- The verification URL is pointing to the product server
- App review team using test iTunesConnect user to test IAP(See the FAQ#16 in TechNote 2259 from Apple)
- The reviewer got a 21007 from your server.
- BOOM! Your app got a rejection for could not complete the subscription.
How to resolve this?
To resolve this, we need to do something with our server. It's simple but tricky. We use the sandbox verification server no matter what the parameter is in the verification URL. Oh, simple, usually, modify 1 line, and everything is done.
There is always a "but". But what if we need to submit an update version to the review team, your tricky solution won't work! What should we do? Look like, adding a new version parameter to the verification server is simple and easy to resolve this. The new URL look like this:
OK, it's all done! Hope your app don't get rejection from Apple because error 21007
If this post helps you, please don't forget to leave your comment!;)