⟵ Back to blog

iOS in-app purchases, part 3: testing purchases in Xcode

8 min

Share

After adding purchases to the app, you need to make sure that they work correctly and run smoothly for your users. To do this, it is important to test them.

This is the third in a series on implementing in-app purchases on iOS. In this series, we try to cover all questions about the implementation and customization of purchases. All other articles are available at the links:

  1. iOS in-app purchases: configuration and adding to the project.
  2. iOS in-app purchases: initialization and purchases processing.
  3. iOS in-app purchases: testing purchases in Xcode.
  4. iOS in-app purchases: server-side receipt validation.
  5. iOS in-app purchases, part 5: the list of SKError codes and how to handle them.

Purchases testing in Xcode vs Sandbox

There are two testing options on iOS: the classic one, through Sandbox purchases, and the new way to test purchases locally through Xcode (StoreKit local testing).

Sandbox testing is a bit tedious process and runs only on a real device. To test in Sandbox, firstly you need to create a Sandbox account on the portal, link it in your device’s settings, and after that run through the testing flow. Some scenarios require a very large amount of manipulation (refund, ask to buy, lifetime non-consumable purchases).

Testing in Xcode has become available since Xcode 12 (iOS 14) was released and has greatly simplified the testing process. First of all, you can test purchases in Xcode at an early stage when your app is not connected to App Store Connect. Secondly, there is no need to create additional accounts in the AppStore for Xcode, which significantly speeds up the process of configuring tests, especially for lifetime non-consumable purchases. Third, local testing can be automated, which potentially reduces the chance of errors occurring in the code. Moreover, you can even write UI tests for paywalls and other interfaces where purchases appear.

However, some things are available only in Sandbox. For instance, a pricing table with automatic conversion to different currencies can be used only in the AppStore. Also, receipt validation in the usual form no longer works – local purchases are validated through Xcode, and this mechanism falls on the shoulders of the developer.

Otherwise, Xcode covers most of the testing scenarios and tasks. In this article, we will consider the configuration and basic scenarios for working with the new tool.

How to create configuration files and fill them with products

To test local purchases in Xcode, you need to add to the project a file with product configuration that you want to test.

To do this, in Xcode, select File → New → File, select the StoreKit Configuration file template, specify a name and save.

Next, at the bottom of the created file, click “+” and select the desired product depending on purchases that you plan to test: subscriptions, non-renewable subscriptions, consumable or non-consumable purchases:

For example, let's select “Auto-renewable subscriptions” and create a subscription group.

Subscription groups are the subscriptions of the same product, but they differ in price, period and level of access to the application. Within one group, a user can have only one subscription, but there is a possibility to switch between them.

Indicate the name of the group and set up a subscription:

  1. Subscription name. This is how the subscription will be displayed in the list on the left. This is not used anywhere else, so the most important thing in the name is to make it understandable for yourself.
  2. The product ID – a required field. The product ID will then be used when making a purchase. Yet again, it's important to make it clear: for example, monthly, annual, premium.
  3. The price – a required field.
  4.  The subscription duration – a required field.
  5. Enable or disable family sharing. This feature has appeared since iOS 14, an optional field.
  6. Introductory offer — initial subscription price. You can specify the desired one or leave it blank, it’s an optional field.
  7. Рromotional offers. You can specify the desired one or leave it blank, it’s an optional field.
  8. Localization: title and description. This is how the in-app purchase will be named and described in the App Store of different regions.

How to enable and disable local purchase testing 

Now, when the products have been added, you can start testing.

In Xcode select Edit scheme → Options

In the StoreKit Configuration menu, you will see a list of configuration files available for testing. In our case, this is the Configuration.storekit that we created in the first step. To disable testing, “none” should be selected.

Before moving further onto the next step of the testing process, let me remind you that Adapty SDK makes implementing in-app purchases on iOS much easier and provides many benefits like advanced subscription analytics, paywalls a/b tests, cohort analysis, and server-side receipt validation. Check it out!

Example of a purchase with a test transaction

Then we test the purchase. To do this,  make a purchase in Xcode, for the product that you specified in the configuration file. We have already written about making purchases in one of the articles in our series.

Starting with Xcode 12, it became possible to manage test purchases. You can track all test purchases and transactions, reject and confirm purchases, make refunds, and more right in the Xcode interface.

To start working on test purchases, you should run the application. Then select Debug → StoreKit → Manage Transactions from the menu. In the window that appears, you will see a list of test transactions performed locally:

Settings for test purchases

Recently, a new menu has been added to Xcode to manage settings for test purchases:

To enter it, you need to select your StoreKit file and click on the Editor menu. It has the following options:

  1. Default Storefront. Allows you to select and switch countries and currencies, respectively.
  2. Default Localization. Switching localization for products, that allows you to test different languages for names and prices.
  3. Time Rate. Allows you to adjust the subscription period. In Xcode you set the interval, for which the purchase will be tested, by yourself: an annual subscription can be tested in an hour or a minute. This allows you to control many complex purchases scenarios.
  4. Enable interrupted purchases. Allows you to test interrupted purchases that require some additional action from the user during the purchase. For example, for users from Europe, additional confirmation is requested for transactions over €30.
  5.  Fail transactions – allows you to explicitly call for certain errors.
  6.  Enable ask to buy. Enablement of an additional request for purchase authorization.
  7.  Subscription Offers Key. Key for signing promo offers.
  8. Save Public Certificate. Used for local validation of the user's receipt (confirmation of information about his purchases)

“Ask to buy” for purchases with Family Sharing / Deferred purchases

StoreKit local testing allows you to test interrupted purchases that require confirmation by an adult family member.

To do this, select Editor → Enable Ask to Buy, restart the application and try to buy something. You will see an alert with the option to request permission to purchase.


ios in-app purchases tutorial: testing purchases in XCode

In the window with the transaction lists there will appear your purchase, which can be confirmed by clicking the corresponding button. After that, your operation will complete successfully in the application.

Managing the local subscriptions: delete, refund

With the new tool, you can delete purchases in order to retest them (for example, non-consumable), as well as emulate refunds.

To receive notifications when a subscription has been canceled or a non-consumable transaction has been deleted, a method has been added to StoreKit that notifies of such changes.

func paymentQueue(_ queue: SKPaymentQueue, didRevokeEntitlementsForProductIdentifiers productIdentifiers: [String]) {
    syncTransactionsHistory()
}

You can delete or cancel a subscription through the new subscription management menu, just select the desired purchase and click on the right mouse button.

When canceling or deleting, a notification with the product id of the cancelled subscription will be sent to the delegate method

Conclusion

These were the main scenarios for managing purchases and testing them in Xcode. As you can see, Xcode has a lot of features, and testing in is easier than in Sandbox. In the following articles, we will talk about the rest of the aspects of connecting purchases on iOS: server-side receipt validation, promo offers, error handling, and how to add purchases to the app using the Adapty SDK (spoiler alert: much easier than without it).

Andrey Kyashkin
August 19, 2021