In-App Purchases

In-App Purchases (StoreKit)

Purchase in-app products with StoreKit 2 by requesting products, purchasing, and verifying transactions.


Product Types

  • Consumable: Can be bought multiple times (e.g., coins).
  • Non-Consumable: One-time unlock (e.g., premium upgrade).
  • Auto-Renewable Subscription: Recurring access.

StoreKit 2 Basics

Use StoreKit 2 to request products, purchase, and verify transactions with App Store-signed receipts.

Syntax: let products = try await Product.products(for:)try await product.purchase(), verify and transaction.finish().

Example

IAP.swift

import StoreKit

@MainActor
func buy(productID: String) async throws {
  let products = try await Product.products(for: [productID])
  guard let product = products.first else { return }
  let result = try await product.purchase()
  switch result {
  case .success(let verification):
let transaction = try verification.payloadValue
// unlock content
await transaction.finish()
default: break } }

This example requests a product, performs a purchase, verifies the transaction, unlocks content, and finishes the transaction.


Fetch Products

Fetch products once (e.g., on app start) and keep them in memory for your paywall/store UI.

Example

Fetch.swift

import StoreKit

@MainActor
func loadProducts(ids: [String]) async throws -> [Product] {
  let products = try await Product.products(for: ids)
  return products.sorted { $0.displayName < $1.displayName }
}

Purchase Flow & Results

Handle all outcomes and always verify before unlocking content.

Example

Purchase.swift

import StoreKit

@MainActor
func purchase(_ product: Product) async {
  do {
let result = try await product.purchase()
switch result {
case .success(let verification):
  let transaction = try verification.payloadValue
  // unlock content guarded by transaction.productID
  await transaction.finish()
case .userCancelled:
  // show nothing or restore UI state
  break
case .pending:
  // family approval or SCA; update UI accordingly
  break
@unknown default:
  break
}
} catch {
// network or App Store errors
} }

Listen for Transaction Updates

Receive purchases made outside your app UI (e.g., from the App Store or another device) and finish them.

Example

Updates.swift

import StoreKit

func startTransactionListener() {
  Task.detached {
for await update in Transaction.updates {
  do {
    let transaction = try update.payloadValue
    // update entitlements based on transaction.productID
    await transaction.finish()
  } catch {
    // handle verification failure
  }
}
} }

Restore Purchases

Query current entitlements to restore non-consumables and active subscriptions.

Example

Restore.swift

import StoreKit

@MainActor
func restore() async {
  for await result in Transaction.currentEntitlements {
if let transaction = try? result.payloadValue {
  // re-unlock features for transaction.productID
}
} }

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *