Is there support for proactive in-app purchase restore?

Badge +2

At WWDC 22, Apple released a session video about proactive in-app purchase restore. From what I understand, this is a way for an app to automatically restore a user’s purchase (e.g. after a re-installation) without them having to use a “Restore Purchases” button.

I’m not sure if this is new or if this was supported all along, so my question is: Does the RevenueCat iOS SDK have support for this? I already found the syncPurchases function but I’m not sure whether it is the right API for the task.


Best answer by Nic Deane 22 July 2022, 07:07

View original

11 replies

Badge +6

Hi Rapha,


Did you figure this out? I’m interested in this as well.

Badge +2

No, unfortunately not. I can’t test my in-app purchase in a sandbox environment yet because I can’t sign the “Paid Applications Agreement” yet (legal reasons). As soon as that’s done, I can test whether proactive restore works out of the box with RevenueCat. I’ll do my best to report back.

Badge +6

I just did some testing and can confirm  syncPurchases does act like a proactive restore function. I check if it is the apps first launch and if so run it in the App file in .onAppear.. works perfectly!


Badge +5

RevenueCat staff: we would very much want to confirm that this is actually implemented.

In our sandbox tests (testflight) with syncPurchases (Unity SDK), we’re not getting the proper entitlement until a renewal comes in. Here’s what we’re testing:

1 - Install app from testflight

2 - start subscription

3 - uninstall app

4 - reinstall same version from testflight

expected: for the entitlement to contains the subscription as it is active. syncPurchases once the app is started, as we detect it’s a new install.

actual: the entitlement isn’t visible after syncPurchases (we poll the value since syncPurchases doesn’t have a callback). It becomes visible only if we wait for the first renewal to come in between steps 3 and 4, then open the app.

This could be just because we’re using testflight, as I’m seeing this in the logs:

default  [Purchases] - DEBUG: ℹ️ Unable to load receipt, ensure you are logged in to a valid Apple account.

default  [Purchases] - WARN: 🍎‼️ App running in sandbox without a receipt file. Restoring transactions won't work until a purchase is made to generate a receipt. This should not happen in production unless user is logged out of Apple account.

[Purchases] - ERROR: 🍎‼️ The receipt is missing.

received syncPurchases response: customerInfo: (null) error:<RCErrorContainer: 0x2810ad740>

Badge +5

An additional question for this one: assuming our issue is because of testflight, what’s the recommended way to test this functionality on iOS before going to production?

Badge +6

I’ve been using syncPurchases in production since it became available both with UIKit and SwiftUI. It’s fantastic and we have never had any issues. If you have a version already in production you can do the final test we ran:

  • Download production version from AppStore
  • Subscribe
  • Delete app
  • Run your Xcode version with new syncPurchases capability on the physical device
  • Receipt from production version found, syncPurchases is called successfully 

We don’t run syncPurchases every launch, just when it is a fresh install.

Badge +5

Thanks for the reply @Nic Deane. We’re also planning on running syncPurchases on fresh installs.

I am confused however by your testing suggestion. My understanding is that purchases and receipts created in production are different than the ones you see in sandbox mode (both from xcode and testflight). Getting xcode to run again will take me some time locally, but after testing on testflight I can confirm that syncPurchases only seems to see sandbox purchases.

Am I missing something?

Userlevel 6
Badge +8

Hey @Ululab, wanted to follow up here with the info we discussed in the support ticket.

Your expected behavior is what should be happening. In production, there is always a receipt available, but in TestFlight/Sandbox, it doesn't always happen in a way that allows syncing/restoring right away. I understand this makes for difficulty when testing, unfortunately seems like a sandbox environment issue.

Badge +5

Understood @cody , thanks. Does this mean that RevenueCat implements proactive in-app purchase restore as explained in the Apple video posted here? Is this supported both on storekit 1 and 2, or only if we use storekit 2? I couldn’t find anything about this in the documentation, and we weren’t able to find the answer by testing because of the environment issue you mentioned.


Userlevel 6
Badge +8

Hey @Ululab!

In general, we won’t proactively restore purchases - that being said, there are cases where there is a transaction in the queue that needs to be handled (from an outside purchase, etc.) and as soon as the SDK is configured, we would sync that receipt which would effectively restore the purchases to the currently identified user ID.

I’d recommend always including a restore purchases button, so that users can manually invoke a restore when they believe they are missing a purchase.

Badge +5

@cody thanks for the definitive answer - it’d be good to update the answer on this thread, as the answer to the original question is not the chosen answer. If I understand your answer correctly, this feature is not planned for RevenueCat.

I’d like to also make a case for RC to implement this feature as it seems critical for a SDK that specializes in handling subscriptions. In our specific case it would be quite useful, but Apple implemented this because it can lead to better customer experience in other scenarios as well.

Our specific case: we’re an app for kids, and it is frequent for parents to setup the account / payment on their phone, and then install the app on their iPad. Implementing this iOS feature would make it painless for parents, as the app on the iPad would recognize the active subscription and lead to the login page right away.

I think this could also be useful in an uninstall / reinstall scenario. I’m not sure if the receipt is processed when reinstalling on the same device.