Back to Swift Reference
💳 StoreKit 2IntermediateiOS 15+

Products & Purchases

Load products, buy them and verify transactions with modern async StoreKit 2.

Product.products(for:) loads localized prices from the App Store. product.purchase() returns a result you must verify before unlocking content.

Listen to Transaction.updates at launch to catch renewals, refunds and purchases made on other devices.

storekit-products.swift
1import StoreKit
2
3@MainActor
4@Observable
5final class Store {
6    var products: [Product] = []
7    var purchasedIDs: Set<String> = []
8
9    func load() async throws {
10        products = try await Product.products(for: ["pro.monthly", "pro.yearly"])
11    }
12
13    func buy(_ product: Product) async throws {
14        let result = try await product.purchase()
15        guard case .success(let verification) = result,
16              case .verified(let transaction) = verification else { return }
17        purchasedIDs.insert(transaction.productID)
18        await transaction.finish()
19    }
20
21    func listenForTransactions() -> Task<Void, Never> {
22        Task {
23            for await update in Transaction.updates {
24                if case .verified(let transaction) = update {
25                    purchasedIDs.insert(transaction.productID)
26                    await transaction.finish()
27                }
28            }
29        }
30    }
31}

Common pitfalls

  • Always call transaction.finish() — unfinished transactions are redelivered on every launch.
  • Test with a StoreKit Configuration file in Xcode before touching App Store Connect.

Still unclear? Ask BeeAI about Products & Purchases.

Get a tailored explanation, or paste your own code for a Swift 6 review. Free members get daily questions — Pro is unlimited.

Ask BeeAI

Become a Founding Pro member: unlimited BeeAI, upcoming Swift paths and every new reference entry first.

See Pro Plans