用户登录场景下StoreKit 2 Transaction.updates处理最佳实践咨询
StoreKit 2:延迟交易处理至用户登录后的最佳实践
你的核心思路可行且符合StoreKit 2的设计规范,但需要调整代码细节并补充关键逻辑,确保覆盖所有场景:
为什么你的方案能覆盖遗漏交易
StoreKit 2的Transaction.unfinished是系统维护的全局未完成交易集合:
- 它会先返回当前所有未完成的交易(包括应用启动到用户登录这段时间产生的交易)
- 之后会持续监听并返回新产生的未完成交易
- 对比
Transaction.updates:后者仅能获取订阅之后的交易更新,无法覆盖登录前的遗漏,但Transaction.unfinished刚好补上了这个缺口
代码调整与优化建议
你当前的代码存在变量名错误,且缺少交易完成标记、幂等处理等关键逻辑,以下是优化后的实现:
// 用户登录成功后调用 func processTransactionUpdates() { Task.detached { // 遍历所有未完成交易(含登录前产生的),并持续监听新交易 for await transaction in Transaction.unfinished { // 跳过已消耗的交易,避免重复处理 guard !transaction.isConsumed else { await transaction.finish() continue } // 验证当前用户状态,确保交易与用户绑定 guard let currentUserID = AuthManager.shared.currentUserID else { continue } // 发送交易到后端验证并授予权益 let validationSuccess = await self.validateTransactionWithBackend(transaction, userID: currentUserID) if validationSuccess { // 标记交易为完成,避免重复出现在未完成列表中 await transaction.finish() } } } // 额外监听全量交易更新,处理退款、撤销等特殊状态 Task.detached { for await transaction in Transaction.updates { switch transaction.transactionState { case .failed: // 记录失败日志,清理无效交易 await transaction.finish() case .refunded, .revoked: // 通知后端撤销对应用户的权益 await self.handleRefundOrRevocation(transaction) await transaction.finish() default: // 未完成交易已由Transaction.unfinished处理,此处跳过 break } } } } // 后端交易验证逻辑示例 private func validateTransactionWithBackend(_ transaction: Transaction, userID: String) async -> Bool { let jwsToken = transaction.jwsRepresentation // 构造请求并发送到后端验证 let request = PurchaseValidationRequest(userID: userID, jwsToken: jwsToken) let response = await BackendClient.send(request: request) return response.isValid } // 退款/权益撤销处理示例 private func handleRefundOrRevocation(_ transaction: Transaction) async { guard let userID = AuthManager.shared.currentUserID else { return } await BackendClient.revokeBenefits(userID: userID, transactionID: transaction.id) }
关键注意事项
- 必须标记交易完成:处理完交易后一定要调用
await transaction.finish(),否则系统会持续将该交易视为未完成,每次启动都会重复返回 - 后端幂等处理:后端需记录已处理的
transactionID,防止同一交易因重复触发处理逻辑而多次授予权益 - 未登录用户的交易留存:即使用户始终不登录,StoreKit会自动保留未完成交易,直到用户后续登录后通过
Transaction.unfinished获取处理,无需额外本地缓存 - 用户绑定校验:处理交易时必须携带当前登录用户ID,避免切换账号后权益分配混乱
内容的提问来源于stack exchange,提问作者user17895655
相关产品推荐
相关产品推荐

