This post is the first of a series dedicated to iOS development.They address to a rather technical audience, and present aspect or issues encountered when developing applications on Apple’s devices.
The first post deals with a frequent issue when implementing Apple’s In-App Purchases (IAP). It happens frequently that IAP transactions suddenly stop working, without any visible reason. There can be two steps of failure:
Here’s how to deal with it.
We won’t bother with obvious issues here (like prices not declared on iTunes Connect, wrong product identifiers, invalid test users): the interesting case is the one were everything used to work perfectly, but suddenly errors pop out from nowhere.
The first problem manifests when prices are not retrieved anymore from iTunes Connect. The SKProductsRequest fails with a generic error, although you’re sure your product identifiers and App ID are correct.
It seems that iTunes Connect services are very picky about the clean state of a request. A lot of authentication checks are performed, to be sure that the request is legit. If not, the request fails with a non-descriptive generic error.
So you need to convince iTunes Connect that your app is legit. How to do?
A good idea is to ensure that only a single development Provisioning Profile exists for the application. If your device contains several different Provisioning Profiles that match your application, chances are that iTunes Connect will reject your requests.
To ensure this, the easiest steps are to:
Removing the Provisioning Profiles is done in Settings / General / Profiles (see the screenshot below).
But why deleting the application? Because it contains an embedded Provisioning Profile, that can interfer with the profiles on the device. Plus the StoreKit seems to store some state in the application bundle (like the last logged AppleID for this app), and we want to clear these informations to get a fresh state.
This should do the trick, and your prices requests should work again. If they doesn’t, try any step you can think to make your app look legit: deconnect your device from the test account (Settings / Store), reboot the device, reset the settings… And don’t forget first to ensure you don’t miss something obvious (like no network, invalid product identifiers or mismatched App ID).
Now here is the case when your prices request works, but when you want to test the actual purchase of an item, the SKPaymentTransaction fails with a rather generic “Cannot connect to the iTunes Store” error. It used to work before, so what happened?
The first cause of troubles can be the iTunes Store Sandbox misbehaving. The Sandbox is not the iTunes Connect component with the best uptime: it frequently happens that some requests are dropped, or that the Sandbox fails to validate any request at all.
How can you be sure? Go have a look in the relevant section of the Apple Developers Forums (you need to be a registered Apple Developer for this). Usually, if the Sandbox is down, a lot of developers will be reporting the issue in a thread.
If the Sandbox seems up, it may be that your test user has expired. Apple recently started to invalidate test users after a specific number of transactions. In the best case, you get a message informing you that the user expired — in the worst case, just a generic error.
You may try to re-activate the test user, but it doesn’t always work. The shorter path is to create a new batch of test users, and use them one after another: we one expires, just switch to the next.
Generally speaking, testing with a freshly created test user is one of the best things you can do: it often works, and saves a lot of frustration when transactions refuse to work.
If prices requests fail, try to:
If transaction requests fail: