In-app purchases (IAP) are a key revenue driver for mobile apps, but even minor issues in the purchase flow can frustrate users, lead to lost revenue, and risk App Store rejection. Common pain points include failed transactions, incorrect entitlements, security vulnerabilities, and inconsistent behavior across devices.
Testing IAP on iOS ensures that purchases process correctly, subscriptions renew as expected, users receive the right access, and errors are handled gracefully. It also involves verifying compliance with Apple’s guidelines, sandbox testing, and simulating real-world purchase scenarios to catch issues before release.
This guide will help effectively test IAP for iOS apps at scale, ensuring a smooth user experience and compliance with Apple’s policies.
Why are In-App Purchases Popular?
It is always a win-win if any app provides premium or add-ons for monetary benefits. Here are a few valid reasons why developers work towards making their apps relevant and engaging:
- Encourages App Installs: If a developer offers their app for free, it is evident that more users will download and install it. It opens the door for users to try out an app since they are more willing to download a free app than a paid one. Depending on the app experience, users will eventually be willing to pay for extra features.
- Ad Revenue: Developers can also choose to display ads in their apps, and for this, they get paid too. Online giants like Twitter and Linkedin display ads that promote specific products/services, a huge revenue source.
- Monetary Benefits: For initial app releases, developers prefer to offer it for free download. Once the traction picks up, in-app purchases boost profits and make the app highly engaging, popular, and successful.
- Encourages better apps: As more and more users download an app, it encourages developers to add more content and features to provide the best experience to users.
In-app Purchases: Market size
The global in-app purchase market was valued at $76.43 billion in 2019 and is projected to reach $340.76 billion by 2027, growing at a CAGR of 19.8% from 2020 to 2027.
A few well-known ways to serve in-app purchases are:
- Consumables: These are primarily for power-ups, in-game currency, and extra health prevalent in gaming apps. They are immediately available after purchase and can be purchased multiple times.
- Non-Consumables: Once purchased, app users have permanent access to these features.
- Auto-renewed Subscriptions: They are subscriptions to apps like Netflix, where the service renews every month with an automatic amount deduction.
- Non-renewed subscriptions: They are manual subscriptions that provide premium content for a limited time.
As per the below graph, it is clear that the subscription models are more popular than the other types of in-app purchases.
In-App Purchase Testing (IAP) Flow on a Remote iOS Device
Since in-app purchases are the primary monetization factor, app developers should ensure that the purchase flow is easy for their user base. It is straightforward to test in-app purchases using BrowserStack App Live. It allows developers to test their applications on real iPhones and iOS devices with test-dev environments, real-time debugging, and other features.
Step 1 – Open BrowserStack App Live and log in to your account.
Step 2 – Once you’re logged in you can choose the iOS device you want to test on.
- Device: iPhone 12 Pro
- App to test: Coursera
Step 3 – Open the App store on the device
Step 4 – Search for the Coursera app in the app store
Step 5 – Download the app and log in to Coursera.
Step 6 – There are a lot of courses available on Coursera to purchase. Select and enroll to any course of your choosing
Step 7 – Click on subscribe to start the purchase.
Step 8 – Click on continue to start the payment process
Step 9 – Enter your payment details to proceed with the purchase
This is how users can test the whole in-app purchase flow on BrowserStack and look for any improvements.
The chances are that your app is already in good health since you’re considering in-app purchases. However, you can always count on testing natural gestures, battery consumption, and simulated GPS & IP geolocation to eliminate any errors.
Your QA team can share bugs via JIRA, Trello, and Slack, and developers can easily replicate these bugs and fix them. You can also integrate CI/CD plugins with tools like Jenkins, CircleCI, etc.
In-app purchases Testing in Xcode vs Sandbox
iOS provides two ways to test in-app purchases (IAP): Sandbox testing and Xcode StoreKit local testing. It supports Sandbox Testing for full end-to-end testing on real devices and Xcode StoreKit Local Testing for faster, automated testing in the simulator.
Feature | Sandbox testing | Xcode StoreKit Local Testing |
---|---|---|
Where It Runs | Real devices only | Xcode Simulator & real devices |
Setup Requirement | Requires a Sandbox account & real Apple ID | No extra accounts needed |
End-to-End Testing | Supports full end-to-end testing (refunds, Ask to Buy, etc.) | Limited to local validation only |
Receipt Validation | Uses App Store validation | Developer handles validation manually |
Currency Conversion | Fully supported | Not supported |
Purchase Speed | Slower, requires manual steps | Faster, automated testing possible |
Automation Support | Limited, mainly manual testing | Supports automation for IAP testing |
Best For | Real-world testing before release | Early-stage testing & faster iteration |
How to Test iOS In-App Purchases with Sandbox
Testing iOS in-app purchases with Sandbox is essential to ensure that the purchasing flow works smoothly without involving real money transactions. The Sandbox environment simulates purchases, allowing developers to test different scenarios in a controlled setting, ensuring a seamless user experience before launching the app to the public.
1. Prerequisites
To test in-app purchases, the Sandbox testing environment provided by Apple is needed. It simulates purchases without real money transactions.
Some things to consider before testing:
- The app must be a developer build in Xcode.
- In-app purchases can be tested without App Review approval.
- Device provisioning is limited to prevent distribution outside the App Store.
- Subscription renewals are faster in the sandbox (eg., 1 month = 5 minutes).
- Receipts are generated only after a purchase.
Read More: Xcode vs VSCode: Everything you need to know
2. Add a Testing Account to App Store Connect
Before testing in-app purchases in Sandbox, a Sandbox testing account needs to be created in App Store Connect:
- From the App Store Connect homepage, go to Users and Access.
- In the top navigation, select Sandbox, then click the add (+) button. If adding testers for the first time, click Create Test Accounts.
Source: Apple Developer
- On the Test Accounts page, click the add (+) icon next to the Test Accounts header.
- Enter the tester’s first and last name. (Note that once created, the name, email, and password cannot be edited.)
- Enter a unique email address. Use an email that hasn’t been used for an Apple account or iTunes/App Store purchases.
- Set a strong password for the tester account. Password requirements will be shown if it doesn’t meet the standards.
- Choose the tester’s App Store country or region. This can be edited later to test on different storefronts with the same account.
- Click Create to finalize the setup.
3. Testing iOS Subscriptions with Sandbox
After setting up the Sandbox account, the subscription renewal speed can be set for each tester. By default, subscriptions renew every 5 minutes, simulating one month of usage.
Sandbox Subscription Durations:
- Subscriptions renew and expire quickly (e.g., a monthly subscription renews/expires every 5 minutes, a weekly one every 1 minute).
- Subscriptions auto-renew up to 12 times, with the actual number of renewals typically being up to 6.
- Grace Periods are shorter than in production, lasting only a few minutes instead of days. If payment issues are resolved within this time, the subscription remains active; otherwise, it expires.
Now, testing iOS subscriptions can begin:
- On the testing device, go to Settings > App Store and sign in with the Sandbox account.
- Open the app and initiate a subscription purchase.
- If prompted, enter the Sandbox account credentials again.
- Wait for the confirmation message from Apple, indicating that the purchase was successful.
- The subscription should now be active, and the functionality, such as upgrades, downgrades, and cancellations, can be tested.
Read More: What is Browser Sandboxing?
4. Testing Subscription Cancellation on iOS
To test subscription cancellations:
- Go to Settings > App Store on the testing device.
- Under the Sandbox Account section, tap the Sandbox Apple ID.
- Tap Manage and choose the subscription to cancel.
- Tap the Cancel Subscription button.
How to Test In-App Purchases via Xcode
StoreKit Testing in Xcode provides a local environment for simulating in-app purchases without connecting to App Store servers. In this environment, in-app purchases are configured using a StoreKit configuration file, which can be created directly in the Xcode project or synced from App Store Connect. Once enabled, the test environment uses the local configuration data when StoreKit APIs are called during testing.
1. Setting up Xcode
Before starting testing in Xcode, the basic setup requires creating a StoreKit configuration file and enabling StoreKit testing.
Create a StoreKit Configuration File:
- In Xcode, go to File > New > File and search for “storekit“.
- Select StoreKit Configuration File and enter a name.
- For synced configuration, check the box and select your team/app, then click Next. For local configuration, leave the box unchecked and click Next.
- Choose a location and click Create.
Enable StoreKit Testing in Xcode:
- Open the Scheme menu and choose Edit Scheme.
- In the scheme editor, select the Run action and click the Options tab.
- Under StoreKit Configuration, select your configuration file and click Close.
2. Testing a receipt in the test environment
Testing receipts is an important step when testing in-app purchases. In the test environment, Xcode’s StoreKit generates receipts that are only valid within that environment. These receipts can be validated locally using a certificate provided by Xcode. These cannot be validated using verifyReceipt because they are not signed by the App Store, causing verification to fail.
The certificate in the test environment is a root certificate, so there is no certificate chain to validate when checking the receipt signature. Here’s an example (in swift) of how to retrieve the local receipt:
// Get the receipt if it's available. if let appStoreReceiptURL = Bundle.main.appStoreReceiptURL, FileManager.default.fileExists(atPath: appStoreReceiptURL.path) { do { let receiptData = try Data(contentsOf: appStoreReceiptURL, options: .alwaysMapped) let receiptString = receiptData.base64EncodedString(options: []) // Add code to read the receipt data. } catch { print("Couldn't read receipt data: " + error.localizedDescription) } }
3. Test an interrupted purchase
An interrupted purchase occurs when a transaction requires user action outside the app, such as updating a payment method. In Xcode, this interruption can be simulated to test how the app handles it.
- In Xcode, select the StoreKit configuration file and go to Editor > Enable Interrupted Purchases.
- Run the app in the simulator or on a device.
- Make an in-app purchase and observe the payment sheet.
- In the code, check that SKPaymentTransactionObserver receives a transaction in the purchasing state.
- Tap Confirm. The payment should fail, and the transaction should move to the failed state.
- Ensure finishTransaction(_:) is called to remove the failed transaction.
- Go to Debug > StoreKit > Manage Transactions, select the failed transaction, and click Resolve.
- Verify the transaction moves to the purchased state and receipt validation occurs.
Read More: All about Working with Xcode Previews
4. Test restoring purchases without existing purchases
To test how an app handles restore purchase requests when no previous purchases exist, includes at least one non-consumable product, auto-renewable subscription, or non-renewable subscription in the StoreKit configuration file.
- In Xcode, go to Debug > StoreKit > Manage Transactions, select all transactions, and click Delete to remove any existing purchases.
- In the app, select the restore purchases option.
- Verify that restoreCompletedTransactions() or restoreCompletedTransactions(withApplicationUsername:) is called.
- Ensure that StoreKit notifies the observer by calling paymentQueueRestoreCompletedTransactionsFinished(_). No transactions will be restored.
5. Test cancellation of a subscription
To test how an app handles subscription cancellations, the app presents an App Store sheet for managing subscriptions.
- In the app, add a “Manage Subscriptions” button that triggers the showManageSubscriptions(in:) or manageSubscriptionsSheet(isPresented:) method.
- Tap the “Manage Subscriptions” button in the app.
- Observe that the App Store sheet for managing subscriptions appears.
- Verify if the test user is subscribed to a subscription.
- Cancel the subscription and confirm the cancellation in the dialog.
- Verify that the user is no longer subscribed to any subscription.
6. Test an offer code
To test redeeming an offer code for a subscription, the app allows users to redeem pre-configured subscription offer codes.
- In the app, add a “Redeem Offer Code” button that calls the presentCodeRedemptionSheet() method.
- Tap the “Redeem Offer Code” button in the app.
- Ensure the Redeem Offer Code sheet appears.
- Select and redeem the configured offer code.
- Verify that the payment sheet appears with the applied offer.
- Tap Confirm on the payment sheet.
- In the code, check that the SKPaymentTransactionObserver receives a transaction in the SKPaymentTransactionState.purchased state via paymentQueue(_:updatedTransactions:).
- Confirm that the app provides the service or product and calls finishTransaction(_).
Conclusion
With iOS devices being the fancy choice amongst many, the monetization of apps will only continue to grow. Developers see great potential in this ecosystem, and if dealt with smartly, in-app purchases can become a revenue engine.
When spending money, users will be cautious and expect flawless experiences, and BrowserStack App Live ensures just that. Providing a wide range of real iOS devices for app testing ensures that the process is robust to keep iOS fragmentation at bay.