Swift StoreKit2:如何判断用户订阅了哪项订阅产品?
优化StoreKit2获取当前订阅产品的实现方式
你的当前实现已经能获取到订阅产品ID,但可以从有效性校验、结果准确性和可维护性三个方向优化:
1. 过滤活跃的有效订阅
Transaction.currentEntitlements会返回所有当前用户有权限的交易,但其中可能包含已过期、已取消的订阅(测试环境中这类情况更常见)。需要先校验交易的活跃状态,确保拿到的是当前有效的订阅:
func currentActiveSubscriptionProductID() async -> String? { var activeTransactions: [Transaction] = [] for await result in Transaction.currentEntitlements { guard case .verified(let transaction) = result else { continue } // 校验订阅是否处于活跃状态:未被撤销、未过期 guard transaction.revocationDate == nil, let expirationDate = transaction.expirationDate, expirationDate > Date() else { continue } activeTransactions.append(transaction) } // 同一订阅组内仅存在一个有效订阅,取最新的交易记录 return activeTransactions.sorted { $0.purchaseDate > $1.purchaseDate }.first?.productID }
2. 避免硬编码产品ID的维护问题
硬编码产品ID会增加后期迭代的维护成本,建议统一管理:
- 将产品ID存入单独的配置文件(比如
SubscriptionConstants.swift):enum SubscriptionProductID { static let basic = "com.yourapp.sub.basic" static let premium = "com.yourapp.sub.premium" static let family = "com.yourapp.sub.family" } - 如果需要展示订阅名称、价格等信息,可以提前通过
Product.products(for:)获取产品详情,关联产品ID与展示数据:func fetchSubscriptionProducts() async -> [Product]? { do { return try await Product.products(for: [ SubscriptionProductID.basic, SubscriptionProductID.premium, SubscriptionProductID.family ]) } catch { print("获取产品列表失败: \(error)") return nil } }
3. 结合RevenueCat简化实现
既然你已经参考RevenueCat的教程实现了PurchaseManager,完全可以利用其封装好的API直接获取当前订阅状态,无需手动处理StoreKit底层逻辑:
import RevenueCat func fetchCurrentSubscription() async -> String? { let customerInfo = try? await Purchases.shared.customerInfo() // 获取当前活跃的订阅权限(对应你在RevenueCat后台配置的Entitlement) guard let entitlement = customerInfo?.entitlements.active.values.first else { return nil } // 返回订阅对应的产品ID return entitlement.productIdentifier }
这种方式会自动处理订阅升级/降级、过期、退款等复杂场景,比手动处理StoreKit交易更可靠。
内容的提问来源于stack exchange,提问作者Kyra
相关产品推荐
相关产品推荐

