You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

切换iOS沙盒用户测试自动续期订阅后收据含双交易ID问题咨询

iOS沙盒订阅切换账户后收据残留问题的解决方案

我之前测试Auto Renewable Subscription时也碰到过一模一样的问题,不少开发者在切换沙盒账户测试订阅时都会遇到这种收据包含前用户交易记录的情况,给你整理几个实用的排查和解决思路:

  • 彻底清理沙盒缓存与本地数据

    • 退出沙盒账户后,务必重启设备——iOS有时候会在后台保留沙盒账户的缓存,重启能强制清除这些残留
    • 卸载重装App,彻底清除本地存储的收据文件(iOS会把收据存在App的容器里,切换账户后旧收据不会自动删除)
    • 手动删除沙盒订阅记录:进入设置 > [你的名字] > 媒体与购买项目 > 查看账户 > 购买记录,找到沙盒环境下的订阅,手动取消并移除(沙盒订阅过期后会自动清除,但手动操作更稳妥)
  • 优化收据验证逻辑

    • 苹果返回的收据会包含该设备上所有的历史交易记录(哪怕是不同沙盒用户的),所以服务器端必须做过滤:在客户端提交收据时,附带当前登录用户的唯一标识(比如你们自己的用户ID),服务器只处理和该用户绑定的交易,忽略其他无关的original transaction ids
    • 切换用户后,主动调用SKReceiptRefreshRequest刷新收据,确保拿到的是当前账户的最新收据,而不是本地缓存的旧数据:
      let refreshRequest = SKReceiptRefreshRequest(receiptProperties: nil)
      refreshRequest.delegate = self
      refreshRequest.start()
      
  • 完善事务处理流程

    • 你的代码里已经处理了事务的finish,但建议在App启动时调用SKPaymentQueue.default().restoreCompletedTransactions(),检查并处理所有未完成的事务,避免队列中残留旧交易
    • 沙盒环境本身存在一定的同步延迟,切换账户后不要立刻测试购买,等待2-3分钟让苹果服务器同步数据后再操作

附上你提供的事务处理代码:

func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
    for transaction: AnyObject in transactions {
        if let trans = transaction as? SKPaymentTransaction {
            switch trans.transactionState {
            case .purchased:
                SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
                if let completion = self.purchaseProductcompletion {
                    completion(PurchaseHandlerStatus.purchased, self.productToPurchase, trans)
                }
            case .failed:
                SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
                let errorCode = (trans.error as? SKError)?.code
                if (errorCode == .paymentCancelled) {
                    if let completion = self.purchaseProductcompletion {
                        completion(PurchaseHandlerStatus.purchaseCancelled, self.productToPurchase, trans)
                    }
                } else {
                    if let completion = self.purchaseProductcompletion {
                        completion(PurchaseHandlerStatus.purchaseFailed, self.productToPurchase, trans)
                    }
                }
            case .restored:
                SKPaymentQueue.default().finishTransaction(transaction as! SKPaymentTransaction)
                totalRestoredPurchases += 1
            default:
                break
            }
        }
    }
}

内容的提问来源于stack exchange,提问作者Dinithi De Silva

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 18:48:13