iOS沙箱中断购买场景下paymentQueue代理方法未触发问题求解
沙箱自动续期订阅中断支付场景代理不触发问题说明与解决方案
问题背景
使用沙箱测试用户测试自动续期订阅购买功能时,在AppStoreConnect针对指定沙箱用户勾选「中断所有支付」复选框,支付流程中开启该设置后预期流程为:
- 支付失败
- 系统弹出提示要求用户接受App Store新的条款与条件
- 随后PaymentQueue中会新增一条对应同一商品的新交易
实际出现的异常如下:
上述流程完成后,代理方法public func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction])始终不会被触发。
主动发起交易时代理可以正常触发;用户接受条款与条件后生成的新交易确实被加入队列,但只有主动新增一笔交易、或是将App最小化再重新打开时,该代理才会被触发并开始处理交易,且这类中断交易始终返回SKErrorCode为「unknown」的错误。
Apple官方文档说明:
StoreKit可在App恢复运行或运行过程中,支付队列内容发生变化时,自动向你的SKPaymentTransactionObserver实例发送通知。
可行解决方案
- 尽早注册支付队列观察者:全局持有SKPaymentTransactionObserver实例,确保在App启动的最早阶段(如
application(_:didFinishLaunchingWithOptions:)执行时)就调用SKPaymentQueue.default().add(_:)注册观察者,不要延迟到进入购买页面才注册,避免队列中已有未处理交易无法被监听到。 - 监听App前台切换事件主动触发队列扫描:注册
UIApplication.didBecomeActiveNotification通知,每次App切换到前台激活时,主动调用SKPaymentQueue.default().restoreCompletedTransactions(),该操作会强制系统重新枚举所有未完成的交易,触发updatedTransactions代理回调,不需要用户重启App。 - 优化unknown错误处理逻辑:针对返回SKErrorCode.unknown的失败交易,不要直接当做异常抛出,优先校验交易的
transactionState属性,若确认是用户同意条款后重试的有效交易,正常走后续的票据校验、权益发放逻辑即可;若确认为无效失败交易,及时调用SKPaymentQueue.default().finishTransaction(_:)清理队列,避免交易残留。 - 沙箱环境特殊兼容:部分该类异常仅在沙箱测试环境出现,生产环境不会复现,你可以针对沙箱环境做单独的逻辑适配,生产环境保持原有逻辑即可,不会影响线上用户体验。
内容的提问来源于stack exchange,提问作者Paweł Zgoda-Ferchmin
相关产品推荐
相关产品推荐

