问题描述
我们有一个应用程序因无法完成自动续订IAP购买,并且无法还原而被苹果拒绝了几次。我们终于通过添加一些额外的日志记录来缩小错误的范围,并在日志中注意到Payment added for transaction already in the SKPaymentQueue: ...
。
在尝试进行复制时,我们启动了一段时间未使用的手机,并发现队列中同一笔购买交易有 27 笔交易,所有交易都在{{1}中}状态。我们的SKPaymentTransactionState.purchased
已收到这些交易的通知,我们的确致电了SKPaymentTransactionObserver
。我假设有这么多交易,因为我们有一个按月订阅,可在沙盒中每5分钟自动续订一次,而且我们已经用另一部手机上的同一App Store帐户多次购买了同一IAP。现在会通知此手机所有更新。
奇怪的是,即使我们在这些事务上调用finishTransaction
,它们似乎仍未完成,这就是为什么我们在控制台中看到“为已在队列中的事务添加了付款”消息的原因。
因此,为了进行调试,我实现了finishTransaction
的{{1}},并注意到,即使我们在如此多的事务上调用paymentQueue(_:removedTransactions:)
,我们也只会看到其中一个被删除-看来,如果我们在该应用程序中呆了很长时间,那么在10分钟以上的时间里,如果再不做任何事情,就会花费更多的时间。
在沮丧中,我继续做这样的事情
SKPaymentTransactionObserver
当然 是超级毛笔的,但您不知道n次交易中的每笔交易一次一次被删除了吗?
所以我的第一个想法是,在现实世界中,这种情况在您一次又一次地购买,更新如此快等情况下不太可能发生,因此,SDK不会期望在一旦?我尝试了一些不太重要的尝试,并从这样的方式更改了finishTransaction
public func paymentQueue(_ queue: SKPaymentQueue,removedTransactions transactions: [SKPaymentTransaction]) {
let remainingTransactions = queue.transactions
let hasRemainingTransactions = !remainingTransactions.isEmpty
if hasRemainingTransactions {
paymentQueue(queue,updatedTransactions: remainingTransactions)
}
}
像这样
paymentQueue(_:updatedTransactions:)
相同的代码只是每个事务都在同一Runloop中处理。发生的情况是 public func paymentQueue(_ queue: SKPaymentQueue,updatedTransactions transactions: [SKPaymentTransaction]) {
for transaction in transactions {
switch transaction.transactionState {
case .purchased:
SKPaymentQueue.default().finishTransaction(transaction)
case .restored:
SKPaymentQueue.default().finishTransaction(transaction)
case .Failed:
SKPaymentQueue.default().finishTransaction(transaction)
default:
break
}
}
}
连续两次被删除的事务被调用两次,然后在测试期间我剩下的大约5个被批量运行。因此,此“修复” /解决了该问题-但是为什么呢?
那么这是怎么回事?这是完成交易所需时间的沙盒怪癖吗?我们是否应该在运行循环的同一运行中完成它们?我只是完全缺少一些核心概念吗?
明智地在Xcode 11.3.1中构建了该应用程序,该问题在iOS 13.6.1和其他iOS 13版本上的再现性最高,似乎发生了,但在iOS 12.0上却很少,在iOS 14 beta上还没有看到。 iOS SDK目标是11.0。我们只有一个IAP,即自动续订的每月订阅。
虽然这种解决方法似乎可以解决问题,但我们一直与Apple处于拒绝循环中,希望在对他们提出更多建议之前,对它们发生的事情有更扎实的了解或推理,
>解决方法
我相信我有这个问题的解决方案。我遇到了完全相同的问题,Apple 一直拒绝我的应用程序,而我的 Sandbox 环境中已经进行了 32 笔交易;)
我在其他地方看到你可以实现这个方法:'removedTransactions'。在这种方法中,我发现它实际上删除了所有 32 个事务,但一次一个,而且速度非常慢,比如 1 秒。每笔交易。如果我在完成新购买之前没有等待,那么它总是卡住并且从未正确开始我的新购买!这是方法和我的日志:
func paymentQueue(_ queue: SKPaymentQueue,removedTransactions transactions: [SKPaymentTransaction]) {
DLog("Removed transactions: \(transactions.count)")
DLog("Unfinished transaction: \(queue.transactions.count)")
}
所以一旦我想通了这一点,我就知道我必须等到队列为空后才能开始新的购买。所以这是我使用的代码:
DLog("Initiating purchase...")
while self.paymentQueue.transactions.count > 0 {
DLog("Still busy removing previous transactions: \(self.paymentQueue.transactions.count)")
sleep(2)
}
DLog("Payment queue is empty,let's buy!")
self.payment = SKPayment(product: product)
self.paymentQueue.add(self.payment!)