在完成finishTransaction调用

问题描述

我们有一个应用程序因无法完成自动续订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!)