In App Purchases don't work during Apple review - ios

In App Purchases work in Sandbox environment but don't work during Apple review which results in the app rejection:
I can't find the problem as In App purchases work well on the test device with Sandbox accounts. I did send the IAPs for review as well and I don't do any kind of receipt validation.
Any ideas where I can find the problem roots?

Always verify your receipt first with the production URL; proceed to verify with the sandbox URL if you receive a 21007 status code. Following this approach ensures that you do not have to switch between URLs while your application is being tested or reviewed in the sandbox or is live in the App Store.
The 21007 status code indicates that this receipt is a sandbox receipt, but it was sent to the production service for verification. A status of 0 indicates that the receipt was properly verified.
Look here: https://developer.apple.com/library/content/technotes/tn2413/_index.html#//apple_ref/doc/uid/DTS40016228-CH1-RECEIPTURL
https://developer.apple.com/library/content/releasenotes/General/ValidateAppStoreReceipt/Chapters/ValidateRemotely.html
How do I verify my receipt (iOS)?
Always verify your receipt first with the production URL; proceed to verify with the sandbox URL if you receive a 21007 status code. Following this approach ensures that you do not have to switch between URLs while your application is being tested or reviewed in the sandbox or is live in the App Store.
https://developer.apple.com/library/content/technotes/tn2259/_index.html

Add some sort of logging that you can see remotely. I suspect they're hitting one of the SKErrorDomain errors because of the weird environment they operate in (app store signed builds, but sandbox accounts).
Do you refresh the receipt in your purchase flow? That's a step where they typically encounter an error.

Related

When should I switch back from sandbox url to the production url for verifying App Store Receipts

Apple says in their documentation here:
Verify your receipt first with the production URL; then verify with the sandbox URL if you receive a 21007 status code. This approach ensures you don’t have to switch between URLs while your application is tested, reviewed by App Review, or live in the App Store.
And I did exactly that. Used the production url, got 21007 status code, then started using the sandbox Url, tested my purchase flow, and submitted the app for a review, got the review approved and am now ready for launch.
What doesn't make sense is that Apple says above "you don’t have to switch between URLs while your application is tested, reviewed by App Review, or live in the App Store." Does that mean that after I release my app, my servers are to continue using the sandbox url after I have released the app? That doesn't make sense. I would expect to start using the production url to validate receipts on my server.
Assuming I am correct, and you DO have to switch to the production url when the app is live - what happens in the future when I want to submit my app for review when I update the app, do I have to take care and put the sandbox url back?
You don't need to change your code after release. It should automatically switch between production and sandbox urls, based on the receipt and the response from the production endpoint.
Apple's documentation says:
Verify your receipt first with the production URL; then verify with the sandbox URL if you receive a 21007 status code.
You will never receive a 21007 status code from the production endpoint when your app is live. A 21007 status means that you have a sandbox receipt in release mode. This only occurs with TestFlight and App Store Review.
You can safely leave the sandbox receipt validation code in place since the code path of checking against the sandbox url will not be used in the normal case.
When you submit a new version for review, and Apple tests it, you will once again get a 21007 response from the production endpoint and your code will attempt validation against the sandbox url.

iOS in app-purchase receipt validation - sandbox vs production url?

I followed Ray Wenderlich's tutorial to implement receipt validation in my app. The code connects to Apple's validation server directly from my app rather than going through my own server.
After I submitted my first binary to the AppStore, I tested my app and the in-app purchasing didn't work because I had switched it over from the sandbox URL to the production URL.
Will this also fail when they AppStore reviewers test it and therefore be rejected? I've read this post but I'm still very confused about whether that applies to me if I'm not using my own server.
The solution is quite simple and it was explained on session 308 of WWDC 2012 (the video is available for registered developers). The session was related to subscriptions but you can extend it for in app purchases.
What happens is that when you develop you hard code your app to validate the receipt with the sandbox. Then you send the app to review, you clearly hard coded your app to validate the receipt with the production server.
But nothing prevents you from doing the validation in two steps:
always validate the receipt with the production server first, this will apply for 99% of your app life. If the receipt is validated, you're done.
if previous validation failed, just validate the receipt with the sandbox server. This should cover your development needs and of course fake receipts will fail validation too.
By the way, and this is officially stated in the documentation ONLY for subscriptions, if you try to validate a sandbox receipt with the production server you will get a specific status code; there is another status code that covers the case of production receipt validated with the sandbox server. In all cases the two worlds, sandbox and production, are always separated.
Don't forget also that with iOS7 added a new safer way to manage receipt validation directly from the device: consider in fact that receipt validation directly from the client (that you don't fully control, e.g. with jailbroken devices) is less secure than receipt validation done through a server you control.
Always verify your receipt first with the production URL; proceed to verify with the sandbox URL if you receive a 21007 status code. Following this approach ensures that you do not have to switch between URLs while your application is being tested or reviewed in the sandbox or is live in the App Store.
Note: The 21007 status code indicates that this receipt is a sandbox receipt, but it was sent to the production service for verification.
There is no public API to call to distinguish the production and sandbox environments so that you can decide which server to use ahead of time. If you have implemented the recommended receipt validation process, the fix can be implemented at your server which contacts the StoreKit server. If the status code for the validation attempt is 21007, then try again at the sandbox server.
It could fail. I had an app with in app purchases (but not based on my server, straight apple code) that work in development but crashed once released by Apple. It crashed because I had not done all the proper steps in iTunes Connect.
The surprising thing was that the reviewers didn't catch this, presumably since they were also working in a sandboxed environment.
I'm not sure this helps you, hope it does.

How do I know if an in-app-purchase receipt comes from the sandbox?

The iOS IAP documentation states, that if you want to test a store you should log out from you itunes account in the settings application. When doing an in-app-purchase, you are then asked for username and password. However, inside the app, I don't know if the user is logged in or if he is using a sandbox account.
In fact, I don't really care if it is a sandbox transaction, but: on the server I have to verify real receipts via the URL https://buy.itunes.apple.com/verifyReceipt and sandbox receipts via the URL https://sandbox.itunes.apple.com/verifyReceipt . How do I know on the server, if the receipt is a sandbox receipt or a real receipt?
Or how does the app know if the receipt is real or sandbox, because I have no problem with passing an additional parameter from the app to my server.
What does not work: You cannot just say that the DEBUG version of the app uses the sandbox environment and the ADHOC or RELEASE version of the app uses the production environment. With an ADHOC-version it is perfectly possible to use iTunes Test Accounts to do in-app-purchases.
When you verify the receipt, if you receive a status code 21007 it means its a sandbox receipt. Look here: https://developer.apple.com/library/content/technotes/tn2413/_index.html#//apple_ref/doc/uid/DTS40016228-CH1-RECEIPTURL
What url should I use to verify my receipt?
Always verify your receipt first with the production URL; proceed to verify with the sandbox URL if you receive a 21007 status code. Following this approach ensures that you do not have to switch between URLs while your application is being tested or reviewed in the sandbox or is live in the App Store.
The 21007 status code indicates that this receipt is a sandbox receipt, but it was sent to the production service for verification. A status of 0 indicates that the receipt was properly verified. See WWDC 2012: Managing Subscriptions with In-App Purchase for more information.

iOS Subscription Verification

I have an interesting problem... (for me at least)
I have developed an app that uses an auto-renewing subscription. They way I have it set up, the app saves the subscription receipt then each time the subscription needs to be verified, the app sends the receipt info to my server, which verifies the receipt is still valid.
In my app I have an app-wide constant called "testMode". Among other things, this causes the app to query my server with either a Sandbox, or Production flag. So if I am testing the app in test mode, the app will query a file on my server that checks the sandbox Apple server. If the app is not in test mode (like when I submit it to Apple) it queries the production file on my server which checks the data against Apple's production server.
My app was rejected because it produced an error when subscribing. That error was 21007 which means a sandbox receipt was sent to the production verification server.
So my question is: How can I submit an app that users the production server verification, if the Apple testers use the sandbox environment?
I ran into similar issues. This is the best way to handle it:
Whenever your server receives a new receipt from the app, first verify it with the production server. Then if you get error 21007, try the same receipt with the sandbox server. This is what I do and it has worked well. Apple should recommend this, but they don't.
Using this method, you should be able to get rid of your testMode in the app (unless you use it for other purposes).

Is verifying receipts against the sandbox URL in a production app safe?

Apple's Technical Note TN2259 "Adding In-App Purchase to your iOS and Mac Applications" mentions the following:
Always verify your receipt first with the production URL; proceed to verify with the sandbox URL if you receive a 21007 status code. Following this approach ensures that you do not have to switch between URLs while your application is being tested or reviewed in the sandbox or is live in the App Store.
But isn't this a security threat? I mean, can someone use a test account to create a sandbox receipt that will allow them to make a purchase without the actual payment?
Sandbox receipts and test accounts are not valid for production apps so your concern is unfounded.

Resources