Contents

Xcode StoreKit Configuration: Complete Guide to Local In-App Purchase and Subscription Testing

Xcode StoreKit Configuration: Complete Guide to Local In-App Purchase and Subscription Testing

During app development, using a StoreKit configuration file (.storekit) allows local simulation of payment flows without network or sandbox accounts. This article details setup, testing, and related code to help you efficiently develop and debug IAP.


Why StoreKit Configuration?

A StoreKit configuration file acts like a “virtual store” to simulate various purchase and subscription scenarios locally, speeding iteration and avoiding frequent sandbox account switching or App Store review waiting.


Setup Steps

1. Create a StoreKit Configuration File

  1. In Xcode Project Navigator, right-click the project folder → New File...
  2. Search “StoreKit” → select “StoreKit Configuration File” → Next
  3. Name it (e.g., Test.storekit) → Create

2. Add Products in .storekit

  • Open the .storekit file → click “+” → choose type (consumable, non-consumable, subscription, etc.)
  • Configure product IDs, prices, subscription periods

3. Associate .storekit to Scheme

  1. Menu: Product > Scheme > Edit Scheme...
  2. Left: Run > Options
  3. Right: set StoreKit Configuration to your .storekit
  4. Save

4. Run and Test

  • Run the app; Xcode will use the StoreKit configuration to simulate purchases
  • Works on simulator and devices, no network or sandbox login needed

Swift Example (StoreKit 2)

import StoreKit

@MainActor
class StoreKitManager: ObservableObject {
    @Published var products: [Product] = []

    // Load products
    func fetchProducts() async {
        do {
            let storeProducts = try await Product.products(for: ["com.example.test.coin100", "com.example.test.vip"])
            self.products = storeProducts
        } catch {
            print("Failed to fetch products: \(error)")
        }
    }

    // Purchase
    func purchase(product: Product) async {
        do {
            let result = try await product.purchase()
            switch result {
            case .success(let verification):
                switch verification {
                case .verified(let transaction):
                    print("Purchase success: \(transaction.productID)")
                    await transaction.finish()
                case .unverified(_, let error):
                    print("Unverified purchase: \(error)")
                }
            case .userCancelled:
                print("User cancelled")
            case .pending:
                print("Pending")
            @unknown default:
                break
            }
        } catch {
            print("Purchase error: \(error)")
        }
    }
}

Common Test Scenarios

  • Consumable and non-consumable purchases
  • Subscriptions and renewals
  • Restore purchases
  • Failures, cancellations, refunds
  • Upgrade/downgrade/crossgrade

Notes

  • .storekit only affects local testing; not sandbox or production
  • Modify product parameters anytime; changes take effect immediately
  • Configure complex scenarios (time acceleration, subscription upgrades) directly in .storekit

References

  • Apple: Testing at all stages of development with Xcode and the sandbox
  • Apple: StoreKit testing in Xcode