A lightweight Swift framework for in-app purchases using StoreKit 2
with full support for Swift Concurrency, async/await, and SPM.
Add this URL to your Xcode project:
https://github.com/Ramiz69/PurchaseKit.git
In Package.swift:
.package(url: "https://github.com/Ramiz69/PurchaseKit.git", from: "3.0.0")
- async/await API
- actor-based PurchasesManager
- DocC documentation
- Static linking support (type: .static)
- Support for iOS, macOS, tvOS, watchOS, visionOS (26 and later)
From 2.0 — one change affects you:
purchase(productID:)returns aStoreTransactioninstead of a rawStoreKit.Transaction. The fields you were reading are on it under the same names, and the raw value is still available as.transaction.StoreKit.Transactionhas no public initializer, so whilepurchasereturned one, a stand-in implementation could only throw and never represent a successful purchase — which defeated the point of having a protocol to mock.
From 1.x — everything in 2.0 applies as well:
- Platforms now start at iOS/macOS/tvOS/watchOS/visionOS 26. Earlier releases are no longer supported; stay on 1.0.6 if you need them.
StoreProduct.productis now optional. It isnilon values you build yourself, becauseStoreKit.Productcannot be constructed outside StoreKit. There is now a public initializer taking the fields directly, soPurchasesProtocolcan be mocked in tests and previews.ProductTypegainedunknownandPurchasesErrorgainedunhandledPurchaseResult. Exhaustiveswitchstatements over either need a new branch. A StoreKit product type this SDK does not recognise now reportsunknowninstead of silently passing asnonConsumable.purchasedProductsno longer replays past events. Every access returns a fresh stream, so several observers can watch at once — previously twofor awaitloops split the events between them and each missed the rest. Read current state withhasEntitlement(for:)orrequestProducts(includingCache:)when a subscriber starts.requestProducts()with no arguments is now a distinct overload onPurchasesProtocol. Calls are unchanged; only a conformer that relied on the default implementation is affected, and that case no longer compiles rather than recursing forever at runtime.PurchasesErrornow conforms toEquatableandLocalizedError, andPurchasesManager.resolved()returns the singleton by throwingnotConfiguredinstead of trapping likeshared.
- 🧭 Online documentation →
- 🛠 In Xcode:
Product > Build Documentation
MIT © Ramiz Kichibekov