Tutorial: How to Add "Restore Purchases" in App Store IOS

Hey GDevelop community!

I spent WEEKS struggling with Apple rejecting my app because of a missing “Restore Purchases” button. My app was rejected a lot of times before I finally figured out the solution. The frustration was real - Apple’s messages were vague, the documentation was confusing, and I couldn’t find any clear guide for GDevelop users.

After countless hours of trial and error, debugging, and reading through forums, I finally got my app approved! :tada:

I know many of you are facing the same issue (I’ve seen your posts!), so I decided to create this complete step-by-step guide. No more guessing, no more rejections - just follow these steps and you’ll have a working Restore Purchases button that Apple will approve.

This solution has been tested and confirmed working

:warning: The Problem

Apple REQUIRES a “Restore Purchases” button for all apps with in-app purchases. Without it, your app will be REJECTED during review.

:white_check_mark: Complete Solution Step by Step

Step 1: Prepare the Extension

  1. Open Project ManagerExtensions
  2. Find your InAppPurchase extension (or create new)
  3. Click “Add a new function”
  4. Name it: RestorePurchase

Step 2: Function Configuration

Set up the function:

  • Function type: Action
  • Full name displayed in editor: RestorePurchase
  • Description:
Restores previously purchased items from the App Store (required for iOS apps).
This action retrieves all previous purchases made by the user and reactivates them.
  • Sentence in Events Sheet: Restore purchases from App Store

:warning: IMPORTANT: The function has NO PARAMETERS! Don’t add any parameters.

Step 3: Add JavaScript Code

  1. In RestorePurchase function click “Add a new event”
  2. Choose Action (lightning icon)
  3. In the black code editor paste this code:
// iOS App Store Restore Purchases
// Check if store is available
if (!window.CdvPurchase || !window.CdvPurchase.store) {
    console.warn('Store not available for restore');
    return;
}

const store = window.CdvPurchase.store;

// Reset variable before restore
runtimeScene.getVariables().get("RestoreSuccess").setBoolean(false);

// Call restore
console.log('Starting restore purchases...');
store.restorePurchases();

// After 2 seconds check products
setTimeout(() => {
    // CHANGE "fullversion1" TO YOUR PRODUCT ID!
    const product = store.get("fullversion1"); 
    
    if (product && product.owned) {
        // Product is owned - unlock it
        console.log('Product restored successfully');
        
        // CHANGE "fullversion1_paid" TO YOUR VARIABLE NAME!
        runtimeScene.getVariables().get("fullversion1_paid").setBoolean(true);
        
        // Set success variable
        runtimeScene.getVariables().get("RestoreSuccess").setBoolean(true);
    } else {
        console.log('No products to restore');
    }
}, 2000);

:warning: REMEMBER: Change in code:

  • "fullversion1" → to your product ID (must be identical to RegisterItem!)
  • "fullversion1_paid" → to your variable name that unlocks the purchase

Step 4: Add Scene Variables

In every scene where you use IAP, add variables:

  • RestoreSuccess (Boolean) - whether restore succeeded
  • fullversion1_paid (Boolean) - whether full version is purchased (or your name)

Step 5: Create Button in Game

  1. Create a button object (Text or Sprite)
  2. Name it e.g. RestorePurchaseButton
  3. Set text: Restore Purchases
  4. Place it in a visible location (preferably next to purchase button)

Step 6: Event Sheet - Handle Button

In the “Store is ready” section add:

Event: The cursor/touch is on RestorePurchaseButton
       Touch or Left mouse button is down
Actions:
  → InAppPurchase::RestorePurchase()

Step 7: Success Message (optional but recommended)

Create a message object (e.g. Text named RestoreMessage) and add event:

Event: Variable RestoreSuccess is true
       Trigger once
Actions:
  → Show RestoreMessage
  → Change text of RestoreMessage: "Purchases restored!"
  → Wait 2 seconds
  → Hide RestoreMessage
  → Set variable RestoreSuccess to false

Step 8: Testing

  1. Export project for Cordova/iOS
  2. Build in Xcode
  3. Test with Sandbox account:
    • Buy product
    • Delete app
    • Reinstall
    • Click “Restore Purchases”
    • Product should unlock

:artist_palette: Button Design Tips

Apple pays attention to button visibility! Make sure:

  • :white_check_mark: Button has contrasting color (e.g. blue on light background)
  • :white_check_mark: Text clearly says: “Restore Purchases”
  • :white_check_mark: Button is easily visible (not hidden in submenu)
  • :white_check_mark: It’s large enough to tap easily

:warning: Common Mistakes

  1. Button not visible enough - too small or hidden
  2. Wrong product ID - must be identical to RegisterItem
  3. Missing variables - remember to add RestoreSuccess
  4. Restore outside “Store is ready” - always wait for store to be ready
  5. No user feedback - add success message

If this solution helped you get your app approved on the App Store, please support by downloading my educational app and leaving a positive review:

:bullseye: Learn Cursive Letters Game

An educational app that teaches children cursive writing in a fun, interactive way.

:mobile_phone_with_arrow: Download on App Store: [Learn Cursive Letters Game] by Andrzej Stec

:star: Your 5-star review helps other parents discover this educational tool!

Thank you for doing this. I’m saving it in case I ever create my app for iOS.

GDevelop definitely needs more extensions and documentation for mobile games, so posts like this are highly appreciated.

Hello,

We’ve recently pushed an update to the In App Purchase extension (0.0.8), including an action to restore purchases + a condition to check if a product is owned.
This should solve the issue you’re mentioning.
If you test it out, let us know if it works for you.