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โ
- iOS
- Android
- Flutter
- React Native
// 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)
}
Coming Soon
Android SDK is currently in development.
Coming Soon
Flutter SDK is currently in development.
Coming Soon
React Native SDK is currently in development.
What Happens During Restoreโ
- The SDK calls
AppStore.sync()to sync the device with Apple's servers - All verified transactions are re-processed
- Entitlements are rebuilt from the current transaction state
- Updated
CustomerInfois returned
In payment mode, the restore flow also sends all transactions to the AppActor backend:
SwiftUI Exampleโ
- iOS
- Android
- Flutter
- React Native
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)
}
}
}
Coming Soon
Android SDK is currently in development.
Coming Soon
Flutter SDK is currently in development.
Coming Soon
React Native SDK is currently in development.
Next Stepsโ
- Subscription Status โ Check active subscriptions
- Checking Entitlements โ Verify feature access