5

我们有一个应用程序被苹果拒绝了几次,因为它无法完成自动更新 IAP 购买,并且如果尝试也无法恢复。我们终于通过添加一些额外的日志记录来缩小错误范围,并Payment added for transaction already in the SKPaymentQueue: ...在日志中注意到。

在尝试重现时,我们启动了一部我们有一段时间没有使用过的手机,并注意到它在队列中有27笔相同购买的交易,都在该SKPaymentTransactionState.purchased州。我们SKPaymentTransactionObserver收到了这些交易的通知,我们确实会打电话finishTransaction给他们。我假设有这么多交易,因为我们有一个每月订阅,在沙盒中每 5 分钟自动更新一次,而且我们在另一部手机上使用同一个 App Store 帐户购买了同一个 IAP 的许多额外购买 - 所以现在正在通知此手机所有更新。

奇怪的是,即使我们调用finishTransaction了这些交易,它们似乎仍未完成,这就是为什么我们在控制台中看到“为已在队列中的交易添加付款”消息的原因。

所以为了调试这个,我实现了paymentQueue(_:removedTransactions:)of SKPaymentTransactionObserver,并注意到即使我们调用finishTransaction了这么多事务,我们也只会看到一个被删除 - 似乎如果我们在应用程序中呆了很长时间,只是什么都不做更多会通过超过 10 分钟的时间。

在我的沮丧中,我继续做了这样的事情

    public func paymentQueue(_ queue: SKPaymentQueue, removedTransactions transactions: [SKPaymentTransaction]) {
        let remainingTransactions = queue.transactions
        let hasRemainingTransactions = !remainingTransactions.isEmpty
        
        if hasRemainingTransactions {
            paymentQueue(queue, updatedTransactions: remainingTransactions)
        }
    }

当然是超级粗暴的,但您不知道对于 n 笔交易中的每笔交易,它们都被一一删除 - 一次只删除一个。

所以我的第一个想法是,好吧,在现实世界的场景中,这可能不太可能,因为你一遍又一遍地购买,更新如此之快等等,所以也许 SDK 不希望一次完成这么多交易?我尝试了一些不那么粗糙的东西,并把我们paymentQueue(_:updatedTransactions:)的东西改成了这样

    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
            }
        }
        
    }

对于这样的事情

    public func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
        
        for transaction in transactions {
            DispatchQueue.main.async {
                switch transaction.transactionState {
                    
                case .purchased:
                    SKPaymentQueue.default().finishTransaction(transaction)
                    
                case .restored:
                    SKPaymentQueue.default().finishTransaction(transaction)
                    
                case .failed:
                    SKPaymentQueue.default().finishTransaction(transaction)
                    
                default:
                    break
                }
            }
        }
    
    }

相同的代码只是在同一个运行循环期间处理的每个事务都没有。这里发生的事情是paymentQueue(_:removedTransactions:)连续两次调用 1 个已删除的事务,然后在此测试中批量运行剩余的 5 个左右。所以这个“修复”/解决了这个问题 - 但为什么呢?

那么这里发生了什么?这是完成交易所需时间的沙盒怪癖吗?难道我们不希望在运行循环的同一运行中完成它们吗?我只是完全错过了一些核心概念吗?

环境方面,该应用程序是在 Xcode 11.3.1 中构建的,问题在 iOS 13.6.1 和其他 iOS 13 版本上重现性最强,似乎发生在 iOS 12.0 上,但在 iOS 12.0 上却很少发生,在 iOS 14 测试版上还没有看到。iOS SDK 目标是 11.0。我们只有一个 IAP,即自动续订的每月订阅。

虽然这项工作似乎解决了这个问题,但我们一直处于与 Apple 的拒绝循环中,并且希望对正在发生的事情有更扎实的理解或推理,然后再向他们抛出更多构建,希望有什么能坚持下去。

4

1 回答 1

1

我相信我有解决这个问题的办法。我遇到了完全相同的问题,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!)
于 2021-04-10T09:09:19.663 回答