SwiftUI中StoreKit 2消耗型内购中断交易追踪及车辆关联方案
解决方案
要实现消耗型内购fuel87与特定车辆的绑定追踪,同时处理交易中断场景,需要从购买请求关联车辆标识、中断交易恢复匹配、交付逻辑定向绑定三个核心环节入手:
1. 给购买函数添加车辆标识参数
修改原购买函数,让它接收选中车辆的唯一ID(比如vehicleId: String),在发起购买时就明确要绑定的目标车辆,同时临时存储交易与车辆的关联关系,避免中断后丢失对应信息:
func purchase(_ product: Product, forVehicleId vehicleId: String) async throws -> Transaction? { // 发起购买请求 let result = try await product.purchase() switch result { case .success(let verification): let transaction = try checkVerified(verification) // 交付前先绑定车辆 await deliverFuelToVehicle(transaction: transaction, vehicleId: vehicleId) await transaction.finish() return transaction case .pending(let transaction): // 存储pending交易与车辆的关联,用于后续恢复 if let transactionId = transaction.id { UserDefaults.standard.set(vehicleId, forKey: "PendingFuelTransaction_\(transactionId)") } return transaction case .userCancelled: return nil default: return nil } } // 定向交付燃料到指定车辆 private func deliverFuelToVehicle(transaction: Transaction, vehicleId: String) async { // 替换为你的业务逻辑:给vehicleId对应的车辆添加fuel87 // 示例: // if let vehicle = vehicleStore.getVehicleById(vehicleId) { // vehicle.addFuel(type: .fuel87) // vehicleStore.saveVehicles() // } }
2. 处理中断交易的恢复逻辑
交易中断(如APP关闭、来电)后,StoreKit会在APP重启或恢复活跃时推送未完成的交易更新。需要监听这些更新,并通过之前存储的关联关系找到对应的车辆:
监听交易更新
在你的StoreKit管理类中添加监听逻辑:
func startTransactionUpdates() { Task { for await update in Transaction.updates { do { let transaction = try checkVerified(update) // 仅处理fuel87的交易 guard transaction.productID == "fuel87" else { await transaction.finish() return } // 从存储中获取绑定的车辆ID if let vehicleId = UserDefaults.standard.string(forKey: "PendingFuelTransaction_\(transaction.id)") { await deliverFuelToVehicle(transaction: transaction, vehicleId: vehicleId) // 交付完成后删除临时存储 UserDefaults.standard.removeObject(forKey: "PendingFuelTransaction_\(transaction.id)") } await transaction.finish() } catch { // 处理验证失败的情况 await update.finish() } } } }
APP启动时恢复未完成交易
在APP启动时(比如App结构体的init或主页面onAppear),主动获取所有未完成的交易,确保不会遗漏中断的购买:
func restorePendingTransactions() async { for await transaction in Transaction.all { do { let verifiedTransaction = try checkVerified(transaction) guard verifiedTransaction.productID == "fuel87", !verifiedTransaction.isFinished else { continue } if let vehicleId = UserDefaults.standard.string(forKey: "PendingFuelTransaction_\(verifiedTransaction.id)") { await deliverFuelToVehicle(transaction: verifiedTransaction, vehicleId: vehicleId) UserDefaults.standard.removeObject(forKey: "PendingFuelTransaction_\(verifiedTransaction.id)") } await verifiedTransaction.finish() } catch { await transaction.finish() } } }
3. 关键注意事项
- 车辆标识唯一性:确保每个车辆有唯一的
vehicleId(比如UUID或服务器分配的ID),避免绑定错误。 - 临时存储清理:交易完成或失败后,务必删除UserDefaults中对应的关联记录,避免冗余数据。
- 云端同步(可选):如果你的APP有云端存储,建议将交易与车辆的绑定关系同步到服务器,防止本地数据丢失后无法恢复。
内容的提问来源于stack exchange,提问作者Jay Patel
相关产品推荐
相关产品推荐

