Currently app store like Apple limited payment method and force developer use their in-app purchase (IAP) in some specific cases:
👉️ Subscription, unlock premium feature, buy money in-game or buy premium, ... [reference 1]
**So app has to share money with Apple
👉️ Subscription, unlock premium feature, buy money in-game or buy premium, ... [reference 1]
**So app has to share money with Apple
1. Overview how IAP apple works.
Before working on IAP we need an apple account and set up 1 app for IAP.
In this app we create renewable group, products to sell.
Base on each cases we have different config and Apple will handle it accordingly. Usually mobile app developer will handle this. But if we need to use some specific value that generated by Apple (For example: original_transaction_id) we have to work with mobile app developer so we can config the app properly.
After config app, each time user buy a subscription or products, Apple will add 1 transaction to receipt. In mobile app, we can push this receipt to BE server to verify. If receipt valid then the BE server will unlock premium feature, subscription.
In this app we create renewable group, products to sell.
Base on each cases we have different config and Apple will handle it accordingly. Usually mobile app developer will handle this. But if we need to use some specific value that generated by Apple (For example: original_transaction_id) we have to work with mobile app developer so we can config the app properly.
After config app, each time user buy a subscription or products, Apple will add 1 transaction to receipt. In mobile app, we can push this receipt to BE server to verify. If receipt valid then the BE server will unlock premium feature, subscription.
2. Things need to handle in server side.
Base on each specific app we can add or reduce some step we handle in server, however the process may contains these step:
- First we need to create tables to save subscriptions / purchases data in order to check expired_date and renew.

Purchases will save new subscription / purchases. In case subscription is renew or upgrade, downgrade purchase will not create new record. The attributes in purchases is:
- start_date: the day user buy content
- expired_date: the day purchase expired (use when user buy subscriptions or items that have expire date)
- original_transaction_id: This id is generated by Apple, original_transaction_id will change when user buy different products / subscription. I will use this field to distinguish which renew transaction is for which purchase.
- user_id: id of user who handle this purchase
purchase_products will store product that user bought for their purchase. This is a association table between purchase and a polymorphic association that can attach with many different product tables or user table (if it's subscription).
- In order to handle IAP we need to handle 4 different basic cases:
1. New purchase / subscription
2. Renew purchase subscription
3. Upgrade downgrade subscription
4. Expire subscription
See the picture below:
2.1. New purchase / subscription.
We need 1 api for user buy new subscription. This api will receive 2 params
- receipt that mobile side get from apple after user purchased successfully.
- 1 list of items that user want to buy.
This api will use the receipt and call to apple's server, Apple will return an object with a list of transaction and we will check expire date and validate if user paid for the item or not. [reference 2]
If receipt is valid then we can create a record in purchase, purchase_products and unlock / active products that user bought.
2.2. Renew purchase subscription
For subscription, Apple will automatically charge user after the last expired date.
After this transaction done, Apple will add that transaction's info to receipt. However, just like I said earlier, new transaction will has original_transaction_id like the first purchase transaction.
We will create new api that we will be called in app dashboard or will call each time user open their app and login.
This api need only newest receipt. This api will also call to Apple's api to get list of transactions and after that it will find transaction which has furthest expires_date by each original_transaction_id and check if those transaction is expired or not. If transaction is renewed then update expires_date to purchases table and active it's product. If it's expired then deactive / lock product that user purchase (purchase_products). Howerver we can not ensure that the products will expire in exactly expires_date, we need handle further to achieve that, I will write about that in 2.4.
2.3. Upgrade downgrade subscription
I do not use new api but I will use the same api in 2.1. Check if original_transaction_id is present in database, if it not it will be new purchase otherwise it will be update purchases and purchase_products.
The verify handle is the same as 2.1 after that we update purchase_products then active / unlock those product.
2.4. Expire subscription
We need to create a cronjob that run at 1 AM everyday, this job will check if any purchases expired in yesterday then if it does we will deactive / lock all its purchase_products until user comeback to the app and prove that they paid through api in step 2.2.
- First we need to create tables to save subscriptions / purchases data in order to check expired_date and renew.

Purchases will save new subscription / purchases. In case subscription is renew or upgrade, downgrade purchase will not create new record. The attributes in purchases is:
- start_date: the day user buy content
- expired_date: the day purchase expired (use when user buy subscriptions or items that have expire date)
- original_transaction_id: This id is generated by Apple, original_transaction_id will change when user buy different products / subscription. I will use this field to distinguish which renew transaction is for which purchase.
- user_id: id of user who handle this purchase
purchase_products will store product that user bought for their purchase. This is a association table between purchase and a polymorphic association that can attach with many different product tables or user table (if it's subscription).
- In order to handle IAP we need to handle 4 different basic cases:
1. New purchase / subscription
2. Renew purchase subscription
3. Upgrade downgrade subscription
4. Expire subscription
See the picture below:

2.1. New purchase / subscription.
We need 1 api for user buy new subscription. This api will receive 2 params
- receipt that mobile side get from apple after user purchased successfully.
- 1 list of items that user want to buy.
This api will use the receipt and call to apple's server, Apple will return an object with a list of transaction and we will check expire date and validate if user paid for the item or not. [reference 2]
If receipt is valid then we can create a record in purchase, purchase_products and unlock / active products that user bought.
2.2. Renew purchase subscription
For subscription, Apple will automatically charge user after the last expired date.
After this transaction done, Apple will add that transaction's info to receipt. However, just like I said earlier, new transaction will has original_transaction_id like the first purchase transaction.
We will create new api that we will be called in app dashboard or will call each time user open their app and login.
This api need only newest receipt. This api will also call to Apple's api to get list of transactions and after that it will find transaction which has furthest expires_date by each original_transaction_id and check if those transaction is expired or not. If transaction is renewed then update expires_date to purchases table and active it's product. If it's expired then deactive / lock product that user purchase (purchase_products). Howerver we can not ensure that the products will expire in exactly expires_date, we need handle further to achieve that, I will write about that in 2.4.
2.3. Upgrade downgrade subscription
I do not use new api but I will use the same api in 2.1. Check if original_transaction_id is present in database, if it not it will be new purchase otherwise it will be update purchases and purchase_products.
The verify handle is the same as 2.1 after that we update purchase_products then active / unlock those product.
2.4. Expire subscription
We need to create a cronjob that run at 1 AM everyday, this job will check if any purchases expired in yesterday then if it does we will deactive / lock all its purchase_products until user comeback to the app and prove that they paid through api in step 2.2.
3. Summary.
There are different cases base on each app so we can't use one solution for all IAP handling, in the most case we will have to change the way we handle it base on each app requirements.
The code maybe far more complicated than what I describe above.
Config apple app is very important so we will need 1 experience mobile developer and talk a lot with him/her.
The code maybe far more complicated than what I describe above.
Config apple app is very important so we will need 1 experience mobile developer and talk a lot with him/her.