It seems like we were just blogging about Google I/O, and now WWDC has wrapped up with huge changes to the in-app subscription landscape. After digging into the docs and testing out the code, we’re excited about StoreKit 2 and how it enables RevenueCat to better serve our customers and make in-app subscriptions even simpler.
We’ve already started incorporating and building in these new features, so you can focus on what really matters: building the best app experience for your users.
Here’s a breakdown of the updates you can expect to see in the next few months:
A cleaner API
The new API includes some new goodies like async/await support, as well as a JSON backingValue that will enable devs to use new features before new OS versions come out. You can even validate purchases now!
No more transaction queue
The dreaded SKPaymentTransactionQueue has been replaced with Transaction.listener. This change is mostly cosmetic, but definitely welcome. The most interesting part is that changes to transactions should now be reflected in real time on all devices, which is a huge UX win. And when a customer installs an app for the first time, their transactions will already be loaded, so they won’t have to restore their purchases right after installing.
Receipt verification improvements
Apple has announced that receipts can now be verified using StoreKit, so you don’t have to perform the validation yourself. This is another welcome change, since writing the code to parse and verify receipts can get complicated. You can still perform the validation yourself if you want to, using the new receipt format (more on that in a moment).
An awkward transition
As excited as we are to use StoreKit 2, it’s only supported in iOS 15+. That means most developers won’t be able to ship StoreKit 2-only versions of their apps. Instead, they’ll need to have two separate implementations (one for the original StoreKit and one for StoreKit 2), or keep using the original StoreKit until they’re ready to drop support for iOS 14.
If you’re a RevenueCat customer, you won’t have to worry about supporting Storekit 1 and StoreKit 2 simultaneously—we’ll do it for you, and we’ll use the new system wherever it’s available. We’re getting to work on these features right away so we’ll be able to provide support as soon as they’re ready.
We’re also going to provide a new set of APIs that’ll make your code look nicer in RevenueCat, including much-anticipated async/await support and Combine extensions.
New Server API and App Server Notifications V2
New server API and Receipts format
There’s a new server API, which marks the end of /verifyReceipt. The new API breaks the calls into two smaller endpoints: one to fetch the latest transactions and one to get the full, paginated history. Now you no longer need to send the receipt back and forth, just the originalTransactionId.
The receipts themselves have a new format: JSON Web Signatures. And instead of a single receipt containing the whole history, it’s now broken up into Signed Transactions, a bit like it was in pre-iOS 7 days.
App Server notifications V2
If you’re a RevenueCat customer, you’ve been somewhat protected from the confusing mess that is Apple’s server-to-server notification system. The new system looks more reliable and complete than the previous one, allowing devs to account for all changes in subscriptions in almost real time. It might not mean the end of polling altogether, as your server might still miss a notification during downtime, but it’s a welcome improvement.
New Support APIs
Refunds and Consumption APIs
Finally... a refunds API! However, it’s not exactly what most devs were hoping for—you can’t use it to actually grant refunds.
What you can do with it is offer customers a way to initiate the refund process. This means that you can have a “Request a refund” button in your app, which will take users to a window where they can specify the reason for the refund and initiate it. Apple will inform them of the refunding decision within 48 hours.
But that’s not all. Apple has also added a Consumption API that you can use to help with the refund decision process. When a customer gets refunded, the App Store will send a new server-to-server notification called CONSUMPTION_REQUEST. The server can then reply in the next 12 hours and provide more information about the customer, like whether the content has been delivered to the customer, how long they’ve been a customer, how much money they’ve already been refunded for in the past, and so on.
There’s also a Manage Subscriptions API that can be used to trigger the Manage Subscriptions flow that’s already available in iOS Settings.
Invoice Lookup API and Refunds Lookup API
Another one we’re super excited about: you can now look up a customer’s transaction history based on the invoice order ID. (This can be found in the invoice email the customer receives from Apple after making a purchase.)
You can send that customer_order_id to the invoice lookup API to get the information for that particular purchase in the new JWS format.
Similarly, you can use the new Refunds Lookup API to find all the refunds a user has ever requested.
Renewal Extension API
The new Renewal Extension API solves a problem that’s been around forever: how to extend a user’s subscription for free. The API allows for extensions of up to 90 days, twice a year. This can be useful when you want to make up for a service outage or some other frustration a customer may have experienced.
Last but not least, there are a few nice improvements to the sandbox environment: You can set up a sandbox URL for notifications, which should make it easier to migrate to the new system.
And for sandbox users, you can now clear the purchase history, change the account region and adjust renewal rates. I don’t know about you, but we’re excited to gain back hours of our lives NOT creating a new sandbox account for every.single.test. :party:
And those are only the highlights! With all these new toys to play with, it feels like Christmas morning here at RevenueCat.
This year, it seems like Apple finally listened and made an effort to relieve a lot of the biggest pain points for developers who use StoreKit—with a new set of modern APIs, a complete overhaul of the receipts format, a more robust set of notifications, and fantastic improvements to the customer support experience. We didn’t quite get the refunds API we were hoping for, and the transition to StoreKit 2 will make things trickier to maintain (unless you’re using RevenueCat, of course), but overall it feels like a win.
Keep an eye out for big SDK releases in the next few months!