StoreKit优惠码兑换问题:SKPaymentQueue Observer未收到通知
问题解答
1. StoreKit 2中优惠码兑换是否存在已知问题导致观察者无法收到通知?
- 版本兼容问题:iOS 15.0-15.2的早期版本中,使用旧版
SKPaymentTransactionObserver监听优惠码兑换事件时,确实存在通知不触发的已知bug,苹果在iOS 15.3及以上版本修复了该问题。 - API适配差异:如果核心交易逻辑基于StoreKit 2的新API(如
Transaction、Product)实现,旧版SKPaymentTransactionObserver可能无法捕获StoreKit 2流程下的优惠码兑换事件——两者的交易跟踪机制是独立的。
2. 是否需要额外步骤或配置确保交易观察者收到优惠码兑换通知?
- 切换到StoreKit 2原生监听方式:放弃旧版
SKPaymentTransactionObserver,改用StoreKit 2的异步监听API,这是适配StoreKit 2的标准方案:import StoreKit class TransactionObserver: NSObject { private var transactionTask: Task<Void, Never>? override init() { super.init() startListening() } deinit { transactionTask?.cancel() } private func startListening() { transactionTask = Task { for await transaction in Transaction.updates { await handleTransaction(transaction) } } } private func handleTransaction(_ transaction: Transaction) async { switch transaction.transactionState { case .purchased, .restored: // 处理兑换成功逻辑,比如解锁内容 await transaction.finish() case .failed: // 处理兑换失败逻辑 await transaction.finish() default: break } } } - 确保观察者实例长期存活:检查观察者类的实例是否在兑换流程中被提前回收(比如被ARC释放),建议将其设置为单例,或挂载在AppDelegate、SceneDelegate等生命周期较长的对象中。
- 主动查询未处理交易:在调用
presentCodeRedemptionSheet前后,主动查询所有交易,避免遗漏未被通知的兑换事件:Task { let allTransactions = await Transaction.all() for transaction in allTransactions { if transaction.transactionState == .purchased && !transaction.isFinished { await handleTransaction(transaction) } } } - 校验优惠码配置:沙盒测试必须使用沙盒环境生成的优惠码,生产环境优惠码无法在沙盒中生效;同时确认App Store Connect中优惠码关联的内购产品配置正确。
3. 处理该问题有哪些常见误区或排查技巧?
- 常见误区:混用StoreKit 1和StoreKit 2的API,却只监听其中一种的交易事件,导致兑换事件被遗漏。
- 排查技巧:
- 确认iOS版本:测试设备需运行iOS 15.3及以上版本,规避早期版本的兼容bug。
- 验证观察者生命周期:在
init和deinit中添加打印日志,确认实例没有被提前释放。 - 检查官方交易记录:登录App Store Connect,进入「App内购买项目」-「交易记录」,确认优惠码兑换是否实际完成。
- 主动触发交易刷新:调用
Transaction.restore()(StoreKit 2)或SKPaymentQueue.default().restoreCompletedTransactions()(StoreKit 1),查看是否能触发交易通知。 - 沙盒环境校验:确保测试使用的是沙盒测试账号+沙盒优惠码,生产资源无法在沙盒中正常运作。
内容的提问来源于stack exchange,提问作者Pushpendra Singh
相关产品推荐
相关产品推荐

