IOS In-App Purchases and Subscriptions
Jumping through Apple’s hoops to implement your IOS subscription business model
Your app is great, people love it. New users come every day. But what they desire is an ongoing flow of content. New content they haven’t seen, every day, week, month. They get tired of seeing the same static view. You want to provide it for them, but who will take care of the production costs that comes with the ongoing content creation? That’s where a subscription model comes into play. Make users support your app from within Apple’s own ecosystem.
There are 3 requirements when trying to implement your own subscription business model within Apple’s services: Provide Apple the required information and agreements, set up your app to allow for In-App Purchases (IAP), and finally create your product.
Setting up how to cash out
In order to upload a paid application or having any kind of IAP within your app, you must first sign Apple’s Paid Applications Agreement which comes with a 99 USD annual fee. In order to do this, gather your bank, contact and tax information and log into https://itunesconnect.apple.com/ with your apple account. Once there, look for the Agreement, Tax and Banking icon and proceed to set up all the forms under the Paid Application contract type.
This is a crucial step. Not until all information is set up, Apple’s API will not provide any type of response when testing your IAP, so doing this as early as possible is mandatory to start development.
Making your App purchase-friendly
Once the above has been taken care of, you will now have to set up the metadata needed in order to allow Apple to identify that your app will feature IAP. Proceed to login into https://developer.apple.com with your apple account, and look Certificates, Identifiers, and Profiles. Once there, Select the App IDs option under the Identifiers section on the left. Select the AppID you desire to add IAP (if you have not created one yet, this is the time to do so) and open up the list. If your Bundle Identifier does not contain any wildcards (“*”), the In-App Purchase option should be enabled by default, if not, go ahead and enable it. Make sure to refresh your certificate from Xcode after doing this.
Now head up to Xcode. In your project settings, selecting the correct target, under the Capabilities tab, you should find an In-App Purchase Capability. Turning this on will not only allow your AppID to make IAP requests but also import StoreKit into your project, a key framework we will discuss later in this post.
Creating the goodies
Now it’s time to create the actual product users will consume when it is all completed. Head to https://itunesconnect.apple.com/ and log in. Once there, look for your App and select the Features tab. If you click the plus icon next to In-App Purchases, a prompt will appear with 4 options to choose from.
Consumable: In order to use again you must make another purchase. Your usual gems/coins/rubies of any free-to-play game.
Non-Consumable: Once purchased, it is unlocked forever and no further payment is required. An additional level, a Pro version of the app, etc
Subscriptions (Auto-Renewable and non-Renewing): A payment that will unlock features of your app for a limited amount of time. Auto-Renewable subscriptions will be charged to the user automatically at the end of each period.
We will focus on Auto-renewable subscriptions, but following this guide, we will get you on the right track with any other IAP as well.
Each product must have a ProductID and It must be unique for the whole app. Input in a reference name and make sure that the cleared for sale option is enabled as it is necessary for testing.
If the auto-renewable option was chosen, the following step is to create a subscription group. Subscription Group is a set of auto-renewable subscriptions which users cannot subscribe to two or more of them at the same time. For example, a monthly subscription to a fishing magazine and a yearly subscription to that same magazine are mutually exclusive. But if the user wants to subscribe yearly to a hunting magazine, he should be able to without leaving his monthly fishing doses. Users can change between subscriptions on the same group at any moment they desire, as it should only change the payment method.
The doom of the In-App Purchase states
This section here is the one you will probably bump into walls more often than not because of Apple’s ambiguous reviewing methods. Your IAP must be validated by Apple, and we as IOS developers understand what that implicates. Some of the more common states you will face are:
Missing Metadata: The product is missing some information. Make sure all these are set up:
- Reference Name
- Localized description
- Review Notes
- Review ScreenShot
Ready to Submit: Ready to send to Apple for review
Rejected: Rejected by Apple review, you should now contact Apple through the Contact Us option and work it out with them
Developer Action Needed: The developer must edit the information in order to re-submit the IAP for review
Approved: Ready to test environment and production
Unless your IAP is in an approved state, you will not be able to fetch or test them in your app, so getting this to be approved should be your first move. However, that’s easier said than done. As an IOS developer, you should know by now Apple is quite picky when it comes to what they approve and what they reject. Luckily you can learn from my tedious process and know exactly what you need to reach this instance.
Getting that sweet approved state
The first step to have an IAP approved is to have a build approved. Apple will never approve and IAP unless it sees what it will be used for. The only way to proceed is to upload a build to Itunes Connect and make sure it passes the automatic review. Next step is making an Appstore review. Go ahead and add your build. Don’t worry if your app is not ready yet as you can make a review without releasing it, just make sure the “Manually release this version” option is set in before submitting. Scroll down to the In-App Purchases section and select all the IAP that qualifies for this build.
Now that you are all set, this should be all Apple needs. However, for AutoRenewable Subscriptions, Apple requires for you to express the Term of Services (ToS) inside your app description. If you fail to do so, the IAP will be rejected. An example of an approved description is as follows:
MyApp is a new way of perceiving the Universe
With MyApp you will get:
* A bunch of cool stuff
* A special stuff once a week
PRICE AND TERMS:
MyApp offers the following subscriptions options:
* 1 month: $2.99 (USD)
* 1 year: $29.99 (USD)
These prices apply to United States residents. Prices may vary in other countries respecting your local currency exchange rate. Your subscription will be charged to your iTunes account. At the end of the term, unless auto-renewables subscriptions are disabled, your subscription will automatically renew in your iTunes account. You will be charged for the regular price of your subscription within 24 hours prior to the end of the current term. You can turn off automatic renewal in your iTunes account settings at any time, but you must do so at least 24 hours before the end of the current term. Refunds will not be provided for the unused portion of any term.
Now everything is done, you should hear back from them in a few days with your IAP approved. If not, feel free to use the contact me option inside iTunes Connect to address the issue with them personally.
Finally some code
You know this is an Apple’s tutorial when it’s been over a thousand words and not a single line of code had been written. Let’s get down to work now. We will be using the StoreKit framework provided by Apple which is surprisingly easy to implement, although tricky to understand. Fundamentally, there is a PaymentQueue where all transactions will end up. You will have then to listen to this queue and act accordingly. The flow should look like this.
It is really simple. Take a look at the following code.
Let’s go over it. Some key concepts are:
SKPaymentQueue: Queue where all transactions are being held for further processing
SKProduct: Product declared in Itunes Connect with all the available information
SKPayment: Intent of purchase of a product
SKPaymentTransaction: Event regarding a SKProduct
SKProductRequest: Request to fetch information about SKProducts giving the products ID
SKProductResponse: Response containing the desired products. It consists of two lists: products and invalidProductIdentifiers. The first one will contain the successfully fetched SKProducts, the second one all the identifiers that fail to correlate to a SKProduct. If you are getting invalid identifiers, here is a troubleshooting list that could help you out.
- Make sure the Contracts, Tax and Banking Information is completed
- Make sure the ProductID is correctly spelled
- Make sure the AppID is explicit (no wildcards (*) )
- Make sure the Provisioning profile is the correct one
- Make sure the Cleared For Sale option is enabled in the Product Description
- Make sure the product is in the approved state
- Make sure the last App Review to the App Store is not rejected
Now, firstly, with the following lines, you can easily make a SKProductRequest.
let request = SKProductsRequest(productIdentifiers: productIDs)
request.delegate = self
Make sure you implement SKProductsRequestDelegate since the following method is the callback.
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse)
There you will get all the SKProducts available for your app. To make a purchase go ahead and create a SKPayment.
let payment = SKPayment(product: product)
Make sure you always fetch the products even before allowing the user to make a purchase. These SKProducts will have the price localized inside them so you should display it. This will make sure you always have the data in your app up to date, as having the wrong price in the app can cause Apple to remove it from the App Store.
You may also notice in the flow an External event section. Transactions can happen outside your App. Say your user changes their subscription type in the system settings, or your deferred transaction was approved by the user’s parents, you won’t be able to tell unless you are expecting them. For that reason, always, in the AppDelegate, at the start of your app, subscribe the app to the PaymentQueue. This way you will make sure you won’t miss any event.
Once a transaction is processed, always use the queue.finishTransaction method to stop it from appearing again.
Testing: Does it actually work?
Now I want to make sure this is working before going live with it, but I don’t feel like spending money every time I need to try it out. Besides, Apple will keep 30% of all revenue. For this, Apple has you covered. We will be creating testing accounts.
Go ahead and log into iTunes Connect, and pick the Users and Roles section. Select the Sandbox Testers tab and create a new account. You won’t have to verify it but it will have to be a new mail address (exampleTest@wolox.com.ar). Now log out from your account in the IOS device and attempt to make a purchase. When asked for email and password type the ones from the sandbox account. If you see this, congratulations, you’ve made it. Always make sure the Environment keyword is present or you will be charged.
Now sometimes the account will not work. Usually, after the first purchase, you will get an “Unable to connect to iTunes” error in your console. It seems like sporadically Apple will try to verify your account against the real iTunes, and failing to do so will completely invalidate your account. So to work around this, just go ahead and create a new one. Gotta love Apple!
On a side note, time moves faster inside the sandbox server, so you will only have to wait a couple of minutes to renew the subscription.
Wrapping it all up
If you follow through, you should be able to test your app. Once all the tedious work is done, all that’s left is for you to unlock the content inside the app and make sure you find the most suitable way to lure new users into trying out the service you are offering, as this is only half the battle. Getting subscriptions to work technically is not the same as them working in real-life. But that’s a topic for another post. Best of luck in your business!