Skip to main content

Restoring Purchases

Apple requires all apps with in-app purchases to include a "Restore Purchases" button. This lets users recover their purchases on a new device or after reinstalling the app.

Why Restore?โ€‹

  • New device โ€” User upgrades their phone and installs your app
  • Reinstall โ€” User deletes and re-downloads your app
  • App Review โ€” Apple reviewers test the restore flow during review
App Store Requirement

Apple will reject your app if it doesn't have a visible "Restore Purchases" mechanism. This is typically a button on your paywall or settings screen.

Implementationโ€‹

// On "Restore Purchases" button tap
do {
let customerInfo = try await AppActor.shared.restorePurchases()

if customerInfo.hasActiveEntitlement("premium") {
showAlert("Purchases Restored", message: "Your premium access has been restored.")
} else {
showAlert("No Purchases Found", message: "We couldn't find any previous purchases.")
}
} catch {
showAlert("Restore Failed", message: error.localizedDescription)
}

What Happens During Restoreโ€‹

  1. The SDK calls AppStore.sync() to sync the device with Apple's servers
  2. All verified transactions are re-processed
  3. Entitlements are rebuilt from the current transaction state
  4. Updated CustomerInfo is returned

In payment mode, the restore flow also sends all transactions to the AppActor backend:

SwiftUI Exampleโ€‹

struct SettingsView: View {
@State private var isRestoring = false
@State private var showAlert = false
@State private var alertMessage = ""

var body: some View {
List {
Section("Purchases") {
Button(isRestoring ? "Restoring..." : "Restore Purchases") {
Task {
isRestoring = true
defer { isRestoring = false }

do {
let info = try await AppActor.shared.restorePurchases()
if info.hasActiveEntitlement("premium") {
alertMessage = "Your purchases have been restored!"
} else {
alertMessage = "No active purchases found."
}
} catch {
alertMessage = "Restore failed: \(error.localizedDescription)"
}
showAlert = true
}
}
.disabled(isRestoring)
}
}
.alert("Restore Purchases", isPresented: $showAlert) {
Button("OK") {}
} message: {
Text(alertMessage)
}
}
}

Next Stepsโ€‹