A comprehensive iOS In-App Purchase library following the OpenIAP specification. Simplifies the integration of in-app purchases in iOS applications with a clean, modern API.
- ✅ StoreKit 2 support (iOS 15+)
- ✅ Legacy StoreKit support (iOS 13-14)
- ✅ Product fetching and caching
- ✅ Purchase handling
- ✅ Receipt validation
- ✅ Subscription management
- ✅ Restore purchases
- ✅ Transaction observation
- ✅ Swift Package Manager support
- ✅ CocoaPods support
- iOS 13.0+
- macOS 10.15+
- tvOS 13.0+
- watchOS 6.0+
- Swift 5.9+
Add the following to your Package.swift
file:
dependencies: [
.package(url: "https://github.com/hyochan/ios-iap.git", from: "1.0.0")
]
Or add it through Xcode:
- File → Add Package Dependencies
- Enter the repository URL:
https://github.com/hyochan/ios-iap.git
- Select the version and add to your target
Add the following to your Podfile
:
pod 'IosIAP', '~> 1.0.0'
Then run:
pod install
import IosIAP
// For iOS 15+
if #available(iOS 15.0, *) {
try await IAPManager.shared.initialize()
}
let productIds: Set<String> = ["com.example.premium", "com.example.coins"]
let products = try await IAPManager.shared.getProducts(productIds: productIds)
for product in products {
print("\(product.localizedTitle): \(product.localizedPrice)")
}
do {
let purchase = try await IAPManager.shared.purchase(productId: "com.example.premium")
print("Purchase successful: \(purchase.transactionId)")
} catch {
print("Purchase failed: \(error)")
}
let restoredPurchases = try await IAPManager.shared.restorePurchases()
print("Restored \(restoredPurchases.count) purchases")
Task {
for await update in IAPManager.shared.observeTransactions() {
switch update.event {
case .purchased:
print("New purchase: \(update.transaction.productId)")
case .restored:
print("Restored: \(update.transaction.productId)")
case .failed(let error):
print("Transaction failed: \(error)")
case .pending:
print("Transaction pending")
case .revoked:
print("Transaction revoked")
}
}
}
let purchases = try await IAPManager.shared.getPurchaseHistory()
for purchase in purchases {
print("Product: \(purchase.productId), Date: \(purchase.purchaseTime)")
}
let receipt = try await IAPManager.shared.verifyReceipt(receiptData: nil)
print("Bundle ID: \(receipt.bundleId)")
print("Purchases: \(receipt.inAppPurchases.count)")
struct IAPProduct {
let productId: String
let productType: ProductType
let localizedTitle: String
let localizedDescription: String
let price: Decimal
let localizedPrice: String
let currencyCode: String?
let countryCode: String?
let subscriptionPeriod: SubscriptionPeriod?
let introductoryPrice: IntroductoryOffer?
let discounts: [Discount]?
}
struct IAPPurchase {
let productId: String
let purchaseToken: String
let transactionId: String
let originalTransactionId: String?
let purchaseTime: Date
let originalPurchaseTime: Date?
let expiryTime: Date?
let isAutoRenewing: Bool
let purchaseState: PurchaseState
let developerPayload: String?
let acknowledgementState: AcknowledgementState
let quantity: Int
}
The library provides comprehensive error handling through the IAPError
enum:
enum IAPError: LocalizedError {
case productNotFound(productId: String)
case purchaseFailed(reason: String)
case purchaseCancelled
case purchaseDeferred
case paymentNotAllowed
case storeKitError(error: Error)
case invalidReceipt
case networkError(error: Error)
case verificationFailed(reason: String)
case restoreFailed(reason: String)
case unknownError
}
Check the Example
folder for a complete SwiftUI example application demonstrating all features.
Run the tests using:
swift test
Or through Xcode:
- Product → Test (⌘U)
This project is licensed under the MIT License - see the LICENSE file for details.
Contributions are welcome! Please feel free to submit a Pull Request.
For issues and feature requests, please use the GitHub Issues page.