Skip to main content
Question

How to test restore purchase scenario

  • August 15, 2025
  • 5 replies
  • 84 views

Forum|alt.badge.img+3

I haven’t found any good resource/answers for this, if there is something please point me to it.

My app keeps getting rejected (has been in the store for years and the purchase of ad removal has been in for over a year now) with my latest update. They tell me that I need to have a dedicated “restore”, which I do. I check for the entitlement being active and if it is I then check to see if I am supposed to showing ads. Basically if showAds==true and entitlement==false show “Remove”, if showAds==true and entitlement==true show “Restore” else show nothing.

 

I’ve done some basic logging and testing but what I can’t seem to figure out how to test is the restore scenario. I have a sandbox account setup as well as the simulator with the storekit setup.  

I can install the app from XCode, run it, make the test purchase and all works as expected. How do I test the restore though? That requires removing and reinstalling app, which appears to also reset my purchase history to appear that I have not purchased anything.  Am I missing something obvious?

This post has been closed for comments

5 replies

guilherme
RevenueCat Staff
Forum|alt.badge.img+6
  • RevenueCat Staff
  • August 19, 2025

Hey ​@john-wiese ,

During review, it is expected a clearly discoverable “Restore Purchases” entry point. Keep it easy to find on your paywall and in your Settings too - don’t hide it behind entitlement checks; reviewers need a stable “go here to tap” path every time.

As to reliable restore test (iOS):

  1. Use a real device signed into a Sandbox Apple ID.

  2. Make the purchase → delete the app → reinstall.

  3. Open your paywall or Settings and tap Restore Purchases (call restorePurchases, not syncPurchases).

  4. Verify your entitlement becomes active again and that your UI hides ads.

One extra thing to also consider is Renewal timings (but only subscriptions). Sandbox renews/expires quickly and can make an entitlement flip on/off during testing, but that doesn’t replace the UI requirement. If “Remove Ads” is non-consumable, renewals don’t apply, but if it’s a subscription, just be aware the entitlement may expire fast in sandbox, that’s normal.

Best,


Forum|alt.badge.img+3
  • Author
  • New Member
  • August 20, 2025

Thanks, there is a clear “Restore Purchases” option in the app but it’s only shown when that makes sense (when the user has the entitlement but it’s a new install).  I don’t think it makes sense to show both a “remove ads” and a “restore purchases”, just the appropriate one so it’s not confusing.  

In my Flutter/dart code I have this:

var showAds = prefs.getBool('showAds') ?? true;
var adCustomerInfo = await Purchases.getCustomerInfo();
var hasPurchasedAdRemoval = adCustomerInfo.entitlements.all['NO ADS'].isActive ?? false;

Then something like this:

if (showAds && !hasPuchasedAdRemoval)
{
// They have not purchased before so show the "remove ads" button
}
else if (showAds && hasPurchasedAdRemoval)
{
// They have purchased before so show the "restore purchase" button
}

When I deply this in my app via TestFlight I get the following values:

Initial install and launch: 
  * I see ads on my pages
  * Tap on my menu and I see:  showAds==true, hasPurchasedAdRemoval==false
  * I see the “Remove Ads” button and I click 

  * Nothing happens (Should get the UI for purchasing)

  * I tap the menu and I see: showAds ==false, hasPurchasedAdRemoval==true

So, it knew I had purchased the removal previously, but the isActive is returning false initially for some reason???

I did this on a device I’ve been using, and then also on a device with a brand new tester account that has never used the app, same results.  There is something going on with retrieving the entitlements on the initial run. I also went back and added the anonymousId and the entitlement list to the output I am showing in my pop-up (for testing only).  And I can see that the entitlements come back blank even though trying to purchase results in it doing nothing (I believe the fallback is that your api sees the user already has the entitlement being purchased  and simply does a restore).

 


guilherme
RevenueCat Staff
Forum|alt.badge.img+6
  • RevenueCat Staff
  • August 21, 2025

Hey ​@john-wiese ,

Thanks for that follow up! Just to confirm a few things (for my understanding):

Regarding your identity state on first launch, are you starting the SDK anonymously (no logIn before paywall right)? If so, a clean install creates a new anonymous user and usually has no receipt yet, so the first CustomerInfo often shows no entitlements. That matches your “false at first, then true after a tap,” I believe.

On the Restore entry point, I understand your goal, but it is expected to have a predictable Restore Purchases place to tap (paywall and Settings would be our suggestion). We recommend not hiding it behind entitlement checks and it should be fine to show both “Remove Ads” (primary) and a smaller “Restore Purchases” link for fallback, alongside the Settings entry (but that’s up to you of course).

As for the case of “nothing happened → active” you saw, if the item is already owned, iOS can suppress the purchase sheet and treat the tap like a restore; CustomerInfo refreshes and the entitlement turns active, which is expected.

On your “Remove Ads” button though, when tapped, what exactly is it wired to do (which product, and is it a non-consumable or a subscription)? Do you handle the “already owned” outcome from the store and update UI based on the next CustomerInfo? A brief outline of that tap flow plus logs around it will help confirm we’re seeing the expected behavior.

If you can share debug logs from a clean install (initial app_user_id + first Customer Info, then the events after tapping Remove/Restore), we can confirm this is the anonymous-first-run + receipt refresh pattern or spot anything else, feel free to send them here or via our support form and reference this thread for context.

Best,


Forum|alt.badge.img+3
  • Author
  • New Member
  • August 21, 2025

ok, I think I understand at this point. I have only one item for purchase, it is a non-consumable (remove ads).  I guess because I’m trying to make it a better user experience by showing only 1 (or no) option to the user I am making it harder on me :) So I  need to do a few things since I can’t use your paywall feature as of yet (long story, but I don’t have enough time to update the app to a post Nul Safety version which limits what I can use). 

  1. I implement my own paywall screen that shows both Purchase and Restore options
  2. or I modify my menu to show both Purchase and Restore options

No matter which I guess I also need to add more code to tell the user “looks like you already own this, restoring your purchase” when they try and buy and it’s already owned. Also add code for the Restore to tell them they have no purchase to restore and point them to Purchase.


guilherme
RevenueCat Staff
Forum|alt.badge.img+6
  • RevenueCat Staff
  • August 22, 2025

Sounds good!

Let us know if you have any more questions or if we can help further when the timing is right.