Logo for tanaschita.com

How to restore in-app purchases with StoreKit 2 for iOS

Learn how to restore in-app purchases proactively and with a restore purchases button.

09 Oct 2023 · 2 min read

When it comes to handling in-app-purchases in an app, we as developers need to make sure that as soon as users reinstall our iOS app or download it on a new device, all in-app purchases the user previously made are restored.

The best practice is to implement the following two options:

  1. Restoring in-app purchases proactively, without the user needing to take any actions.
  2. Providing a restore purchases button which users can use when they suspect that the app does not show all the transactions.

Let's look at how to do that.

If you need to refresh your knowledge on StoreKit 2, check out this article on getting started with StoreKit 2 for iOS.

Sponsorship logo
Preparing for a technical iOS job interview - updated for iOS 18
Check out my book on preparing for a technical iOS job interview with over 200 questions & answers. Test your knowledge on iOS topics such as Swift, SwiftUI, Combine, HTTP Networking, Authentication, SwiftData & Core Data, Concurrency with async/await, Security, Automated Testing, Machine Learning and more.
LEARN MORE

Restoring in-app purchases proactively

StoreKit automatically keeps up to date transaction information and subscription status available in our app, even when users reinstall it or download it on a new device.

This means that when our app launches, all transactions are automatically available so we can use current entitlements to restore all in-app purchases as follows:

func refreshPurchasedProducts() async {
for await result in Transaction.currentEntitlements {
guard case .verified(let transaction) = result else { continue }
if transaction.revocationDate == nil {
self.purchasedProductIDs.insert(transaction.productID)
} else {
self.purchasedProductIDs.remove(transaction.productID)
}
}
}

Providing a restore purchases button

In case that the in-app purchases cannot be automatically restored, for example because the user is not logged in with the App Store, we should provide a restore purchases button which calls AppStore.sync():

Button {
Task {
do {
try await AppStore.sync()
} catch {
print(error)
}
}
} label: {
Text("Restore purchases")
}

Calling AppStore.sync() forces the app to obtain transaction information and subscription status from the App Store. It may display a system prompt that asks users to authenticate with their App Store credentials. Apple advices to only call this function in response to an explicit user action, like tapping a button.

Sponsorship logo
Preparing for a technical iOS job interview - updated for iOS 18
Check out my book on preparing for a technical iOS job interview with over 200 questions & answers. Test your knowledge on iOS topics such as Swift, SwiftUI, Combine, HTTP Networking, Authentication, SwiftData & Core Data, Concurrency with async/await, Security, Automated Testing, Machine Learning and more.
LEARN MORE

Newsletter

Image of a reading marmot
Subscribe

Like to support my work?

Say hi

Related tags

Articles with related topics

storekit

swift

ios

Get started with auto‑renewable subscriptions for iOS

Learn how to implement in-app purchase subscriptions with StoreKit and SwiftUI.

11 Dec 2023 · 5 min read

Latest articles and tips

© 2024 tanaschita.com

Privacy policy

Impressum