RevenueCat SDK 5.0 – The StoreKit 2 Update

The new major version of the RevenueCat iOS SDK makes StoreKit 2 the default

Charlie Chapman

Today RevenueCat released 5.0 of the iOS SDK. In this update, the SDK uses new StoreKit 2 APIs on the client app SDK and the RevenueCat backend by default for users running iOS 16+. This change should be transparent for most developers, but there are a few things you may want to be aware of. Let’s dig into the details.

What is StoreKit 2?

StoreKit 2 (also referred to as “Swift-based In-App Purchase API”) is a modern Swift-only reimplementation of the original StoreKit framework. It comes with support for modern Swift concurrency via async/await, access to the underlying JSON backing values so you can backport new features to versions of iOS that didn’t support them, and built-in local transaction verification.

Apple recently announced the deprecation of the original StoreKit 1 APIs, so it’s important that all developers eventually migrate to StoreKit 2 to continue receiving bug fixes and updates from Apple.

On the backend, StoreKit 2 introduced a new suite of APIs called the App Store Server API that provides access to transaction data from app store purchases. Moving away from the previously single entity of Receipt, StoreKit 2 has broken up Receipt into two entities – Transaction and AppTransaction, which are now signed in JSON Web Signature (JWS) format. 

With the new entities also come with many new API endpoints, and rather than having a single verifyReceipt, StoreKit 2 allows developers to query into:

  • A Transaction
  • Transaction History 
  • Subscription Statuses 
  • Refund History 
  • Notification History

StoreKit 2 also includes pricing information in its Transaction entity which was not previously available in a Receipt.

So what is RevenueCat doing about it?

Since Apple’s release of StoreKit 2, the RevenueCat team has been hard at work understanding and updating our client SDKs and backend systems to work with Apple’s new APIs. We’ve taken a careful approach to ensure our customers aren’t disrupted by these changes.

On the SDK, we reimplemented most features on top of StoreKit 2, from listing and purchasing products, to checking for free trial, introductory price and promo offer eligibility, using StoreKit Config files to test purchases on Xcode. We even updated Observer Mode to work with StoreKit 2. But most importantly, we said goodbye to receipt files and embraced the new JWS tokens to validate purchases.

For our backend, we’ve been comparing the performance of the StoreKit 2 APIs against the existing StoreKit 1 APIs, and reporting bugs and performance issues to Apple as we find them. We’re now confident in the new StoreKit 2 APIs, so we’ve migrated customers to the new StoreKit 2 APIs behind the scenes. This should be a seamless experience for all of our customers that requires almost no action from you other than ensuring your in-app purchase key is configured in the RevenueCat dashboard.

Behind the scenes we mapped the StoreKit 2 entities to the Receipt entity so that we could maintain a seamless transition between the two versions. Doing this has allowed us to fallback to StoreKit 1 seamlessly if needed, which we have had to do when StoreKit 2 had an incident with missing information. We also added support for StoreKit 2 config files so developers could easily test their application without connecting to the App Store. 

Fewer unexpected errors than StoreKit 1

The now deprecated StoreKit 1 APIs sometimes threw unexpected errors related to missing receipts or products missing in the receipt, usually when developing in the sandbox. Because StoreKit 2 no longer relies on the old receipt object, you should no longer see these inconsistent errors appear. This should hopefully make in-app purchase testing more reliable.

What do developers need to do?

Our approach has been to make these changes as transparent to our customers as possible. So most of these changes will happen automatically without any action from you. There is, however, one important thing you need to do to make sure we’re able to migrate your project to using the new StoreKit 2 APIs.

Add your in-app purchase key configuration file

Going forward, all iOS apps in RevenueCat will require you to upload your in-app purchase key configuration file. This should take you less than 5 minutes to complete. You can find instructions for where to find this file in our documentation.

Screenshot of the section of the RevenueCat dashboard to upload your in-app purchase key configuration.
Figure 1: Section of the RevenueCat dashboard to upload your in-app purchase key configuration.

If you have an existing project without this file, you can upload it by:

  1. Going to the RevenueCat dashboard
  2. Opening your project’s settings
  3. Selecting your iOS app under “Apps”. Here you’ll find a section called “In-app purchase key configuration where you can add your .p8 file from App Store Connect and fill in your Key ID and Issuer ID.

Once you’ve done that, you’re good to go! We’ll have everything we need to use the new StoreKit 2 APIs and retrieve more accurate data from App Store Connect.

Changes to Observer Mode

For apps configured to use the RevenueCat observer mode, there are a few notable changes.

In version 5.0 of the SDK we’ve removed the term “Observer Mode” and updated the APIs to more clearly reflect what is happening. Previously, you could configure the SDK like this if you only wanted the RevenueCat SDK to observe purchases so that you could complete them yourself in your own code:

1Purchases.configure(with: .builder(withAPIKey: apiKey)  .with(observerMode: true)  .build())

Version 4.0 and earlier

In version 5.0 of the SDK, you need to update to this:

1Purchases.configure(with: .builder(withAPIKey: apiKey)  .with(purchasesAreCompletedBy: .myApp, storeKitVersion: .storeKit2)  .build())

Version 5.0

Note that this is functionally the same, but more clearly represents that the SDK is configured to allow you to complete purchases yourself.

On macOS, when purchases are completed by your app using StoreKit 2, the SDK does not detect a customer’s purchase until after the user foregrounds the app after a purchase has been made. If you want the RevenueCat SDK to immediately detect a user’s purchase there is a new API called Purchases.shared.recordPurchase(purchaseResult) that you can call immediately after completing a purchase.

1let product = try await StoreKit.Product.products(for: ["my_product_id"]).first
3let result = try await product?.purchase()
5_ = try await Purchases.shared.recordPurchase(result)

This will ensure that RevenueCat always has immediate access to your user’s purchase data. Note this only applies when the RevenueCat SDK is configured with purchasesAreCompletedBy: .myApp.

If purchases are still completed by your app using StoreKit 1, you will need to explicitly configure the RevenueCat SDK to use StoreKit 1 like so:

1Purchases.configure(with: .builder(withAPIKey: apiKey)
3  .with(purchasesAreCompletedBy: .myApp, storeKitVersion: .storeKit1)
5  .build()

You may notice some changes to your historical transaction data

On the backend, we’ve already migrated customers over to use the StoreKit 2 APIs automatically. There’s absolutely nothing you need to do here as long as you’ve added your in-app purchase key configuration file to the RevenueCat dashboard.

There are a few changes you might notice with your historical transaction data however. Because we now have access to more accurate pricing and country information, we’ve gone back and corrected some historical data. More details about this can be found here.

Send us your feedback

Major version changes to our SDKs are usually reserved for big changes with breaking changes for our customers to fix before integrating into their apps. Today’s SDK updates are a bit different. We made large changes under the hood to switch all of our customers over to using StoreKit 2 APIs without developers having much work to do on their end. 

We’ve been testing this for quite a while, but because these changes are so foundational you may notice some slight changes. This is why we’ve decided to mark these updates as a major version change.

Today’s update is for our native iOS SDK. StoreKit 2 support in our cross-platform SDKs (eg. React Native, Flutter) is coming soon.

Check out the migration guide for full details on everything that’s changed in this SDK update. And as always, please reach out if you have any questions or feedback for the team! 

You might also like

Share this post

Want to see how RevenueCat can help?

RevenueCat enables us to have one single source of truth for subscriptions and revenue data.

Olivier Lemarié, PhotoroomOlivier Lemarié, Photoroom
Read Case Study