Mobile Development 10 min read

Migrating In‑App Purchase Integration from StoreKit 1 to StoreKit 2 on iOS

This article explains the transition from StoreKit 1 to StoreKit 2 for iOS in‑app purchases, detailing the limitations of applicationUsername, the new appAccountToken mechanism, updated purchase and order‑recovery flows, enhanced notification handling, and references to Apple’s server APIs.

Liulishuo Tech Team
Liulishuo Tech Team
Liulishuo Tech Team
Migrating In‑App Purchase Integration from StoreKit 1 to StoreKit 2 on iOS

Background

Apple introduced StoreKit 2 at WWDC 2021 (iOS 15) as a brand‑new set of Swift APIs that fully leverage Swift language features. After a year, StoreKit 2 was updated at WWDC 2022, adding improvements to receipts, transactions, and new APIs.

Because StoreKit 2 provides a more robust payment chain and code design than StoreKit 1, we decided to upgrade our iOS 16 implementation to use StoreKit 2.

StoreKit 1 Status

In StoreKit 1 we used applicationUsername to associate an app order with an IAP order. The client first requests a pre‑payment order from the server, encodes userId and orderId into applicationUsername , and passes it through the entire IAP flow.

After a successful IAP, the client sends applicationUsername and the receipt to the server, which validates the receipt and uses applicationUsername to locate the corresponding order for fulfillment.

The receipt data does not contain applicationUsername , so the client‑side value must be reliable. Unfortunately, applicationUsername can be lost during transmission, leading to “lost order” problems where the server cannot match the order and creates a new one for the current user.

If a user has multiple accounts, an order purchased under account A may become un‑verified, then the user switches to account B and re‑triggers verification; the missing applicationUsername causes the server to bind the order to B, effectively losing the order for A. In our scenario (course purchases) this is acceptable because the same Apple ID is used.

StoreKit 1 offers no good solution for this issue. StoreKit 2 introduces a new field appAccountToken that appears in Apple’s transaction data and never gets lost, solving the order‑association problem and motivating our upgrade.

Meet StoreKit 2

StoreKit 2 focuses on five areas:

Products : information about in‑app purchase items configured in App Store Connect.

Purchases : optional parameters for purchase APIs, allowing a user ID to be bound.

Transaction info : updated format of transaction data.

Transaction history : API to query a user’s transaction history.

Subscription status : API to query the status of subscription items.

Based on these, we redesigned the payment and order‑recovery flows.

Purchase Payment

The old verification relied on applicationUsername + receipts. In StoreKit 2 we can call the Get Transaction History API to obtain historical transactions and use appAccountToken to link IAP orders with our internal orders. The new payment flow is illustrated below.

Apple also made applicationUsername compatible: if a UUID is passed, it is forwarded to the receipt’s app_account_token field, but only for auto‑renewable subscriptions and it is not fully reliable.

Our existing applicationUsername format is not a UUID. Converting to UUID would require extensive changes on both client and server and would need to support both formats for a long transition period, which outweighs the benefits. Therefore we keep the original logic and let the client decide at runtime: if iOS > 15, call the new verification API; otherwise, fall back to the old one.

Order Recovery

Order recovery helps users retrieve successfully paid but undelivered orders, reducing customer complaints. Previously the client reported receipts, the backend iterated through each transaction, matched by TransactionId , and created a new order if none was found. If the receipt belonged to a different account, the recovered order could be bound to the wrong user, causing another lost‑order scenario.

StoreKit 2’s appAccountToken now reliably determines order ownership, and the new transaction‑history API provides all user transactions. Combining these, we upgraded the order‑recovery process for higher precision.

The App Store Server also offers an Order Lookup API that requires the OrderId from the Apple notification email. We treat this as “precise order recovery” to help users retrieve orders with exact matching.

Message Notification V2

The notification service was updated: some old notifications were removed and new ones added, mainly for subscription scenarios.

If the developer’s service fails, App Store Server Notifications are retried. V1 retries three times (6 h, 24 h, 48 h after the last attempt). V2 retries five times (1 h, 12 h, 24 h, 48 h, 72 h after the last attempt). If the service is still down, the notification is lost, but developers can fetch historical notifications (up to six months) via the Get Notification History API.

Among all notifications, refund notifications must be handled; other types can be processed according to business needs.

Outlook

The current IAP flow differs from Alipay or WeChat Pay, which provide server‑side notifications with exponential‑backoff retries. IAP relies on client reporting, so the probability of a successful payment without fulfillment is relatively higher. Apple continues to iterate on the App Store, and our team will keep following these improvements to deliver a better purchase experience.

References

[1] Get Transaction History: https://developer.apple.com/documentation/appstoreserverapi/get_transaction_history [2] Order Lookup API: https://developer.apple.com/documentation/appstoreserverapi/look_up_order_id [3] Get Notification History: https://developer.apple.com/documentation/appstoreserverapi/get_notification_history

Mobile DevelopmentiOSSwiftIn-App PurchaseStoreKitApp Store Server API
Liulishuo Tech Team
Written by

Liulishuo Tech Team

Help everyone become a global citizen!

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.