iPhone应用内购买队列无法清空

11

我在我的应用中设置了应用内购买。然而,我遇到了一些奇怪的行为。每次启动应用时,我都会调用以下代码:

[[SKPaymentQueue defaultQueue] addTransactionObserver:self];

设置初始观察者。 但这会立即触发。

- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions

使用完整的所有交易数组。我尝试过仅仅调用

[[SKPaymentQueue defaultQueue] finishTransaction: transaction];

我每次重启应用程序后,都会在每个交易上触发paymentQueue,但只要我调用addTransactionObserver就会触发。 我现在的主要目标就是清空交易队列并重新开始。 我不知道自己是如何进入这个状态的,也不知道如何摆脱它。

5个回答

6
请确保您已经实现了这个方法:
-(void)paymentQueue:(SKPaymentQueue *)queue removedTransactions:(NSArray *)transactions;

1
你能建议一下什么是一个好的实践实现吗? - Ziv Levy
@ZivLevy 我只是记录了transactions中的所有交易,这样我就知道它们被删除了。 - DDPWNAGE

4

SKPaymentTransactionObserver:PaymentQueue.. 调用:

SKPaymentQueue.default().finishTransaction(transaction)

请注意,您不能调用所有类型。对于购买(.purchasing),调用finishTransaction将崩溃并出现错误。因此,遍历所有交易的for循环不是完整的解决方案。
当您为购买(.purchasing)调用finishTransaction时:
 *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Cannot finish a purchasing transaction'

3

将以下内容放置在某处以清除队列(可能是您的负载方法,但在最终应用中请删除它):

for (SKPaymentTransaction* transaction in [[SKPaymentQueue defaultQueue] transactions]) {
     [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}

当调用finishTransaction时,每个事务被移动时都会调用观察者的removeTransaction方法。

我的队列中有30个,在结束时该方法被调用了30次。


1
必须使用SKPaymentTransaction而不是SKTransaction,第二行缺少分号。 - Rilakkuma

2
我觉得你的问题与iTunes Connect中的沙盒用户账户有关。如果你没有任何沙盒用户,这篇指南对帮助你设置沙盒用户非常有用:
https://support.magplus.com/hc/en-us/articles/203809008-iOS-How-to-Test-In-App-Purchases-in-Your-App 如果你已经有了沙盒用户:
你可以尝试调用finishTransaction:,但是你需要确保交易的SKPaymentTransactionState是可接受的。
根据finishTransaction的文档:
// Asynchronous.  
// Remove a finished (i.e. failed or completed) transaction from the queue.
// Attempting to finish a purchasing transaction will throw an exception.

因此,要安全地删除已完成的交易:

for transaction in SKPaymentQueue.default().transactions {
    guard 
        transaction.transactionState != .purchasing, 
        transaction.transactionState != .deferred 
    else { 
        //Optionally provide user feedback for pending or processing transactions
        return
    }

    //Transaction can now be safely finished
    SKPaymentQueue.default().finishTransaction(transaction)   
}

.purchasing.deferred的文档说明相当模糊:

case purchasing // Transaction is being added to the server queue.

case deferred  // The transaction is in the queue, but its final status is pending external action.

据我所知,处理待处理和/或正在处理的交易应该是相当被动的。应用程序已经完成了它需要做的一切,并正在等待来自iTunes Store服务器或其他依赖项(即付款授权)的响应。
当交易更新时,paymentQueue: updatedTransactions:将在队列的SKPaymentTransactionObserver上调用。
至于您的事务队列如何陷入僵局,我敢打赌,队列中的所有交易都处于状态.purchasing。这很可能是iTunes Connect / Sandbox用户/生产iTunes帐户内部的错误。其他人,包括我自己,也遇到了这个问题。有一个错误报告已经提交了。尝试重新创建/更改沙盒用户的密码,或创建一个新的沙盒用户进行测试。
更多信息请参见:https://forums.developer.apple.com/thread/70418

1
每次购买或恢复产品时,您必须确保完成交易。如果遇到此问题,应清理队列,然后适当开发逻辑。在Swift 3中可以通过运行类似于以下内容的内容来快速清理(与先前的答案相同)。但这不应该出现在您的真实应用程序中。
func cleanUp() {

    for transaction in SKPaymentQueue.default().transactions {

        SKPaymentQueue.default().finishTransaction(transaction)   
    }
}

此外,您需要在 appDelegate 中添加和删除观察者。这是最佳建议,也是避免问题的最佳方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接