iOS StoreKit – 何时调用 – (void)restoreCompletedTransactions?

我的应用程序内有大量的1次购买IAP。 用户可以购买他们就好了。

我的问题是,我正在与Flurry进行整合,以跟踪实际购买,而不仅仅是购买的恢复,但是我的SKPaymentTransactiontransactionState总是作为SKPaymentTransactionStatePurchased返回,而不是SKPaymentTransactionStateRestored

显然SKPaymentTransactionStateRestored仅在- (void)restoreCompletedTransactions时调用,但是何时调用此方法?

我的思考过程是购买应该是这样的:1)用户select产品,2)询问用户是否想购买X数量的产品。 3)服务器检查用户之前是否购买过,以及是否通过设置SKPaymentTransactionStateRestored恢复它。 否则,处理事务并设置SKPaymentTransactionStatePurchased 。 显然这是错误的,我想调用- (void)restoreCompletedTransactions之间的某处?

谢谢,

编辑:

本来我已经发布了一个很长的,不需要的方法来得到我需要做的,但是正如你将在下面看到的,Matt帮我弄清了我正在寻找的variables。

例如,让我们想象一个用户先前购买了我的应用程序,购买了所有可用的非易损件IAP,然后删除了该应用程序。 当用户重新安装应用程序时,我希望能够确定他们何时再次“购买”产品,是原始(第一次)购买还是恢复购买?

我已经实现了“恢复所有购买”button,但是让我们说用户忽略/没有看到它,并试图select他们之前购买的产品。

与正常购买一样,我做了以下事情:

 if ([SKPaymentQueue canMakePayments]) { self.productRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObject:productID]]; self.productRequest.delegate = self; [self.productRequest start]; } else { //error message here } 

用户loginiTunes帐户后,应用程序会让他们知道他们已经购买了这个,现在将会恢复。 下面的委托方法将被调用:

  -(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions { for (SKPaymentTransaction *transaction in transactions) { switch (transaction.transactionState) { case SKPaymentTransactionStatePurchased: { [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; if(transaction.originalTransaction) { NSLog(@"Just restoring the transaction"); } else { NSLog(@"First time transaction"); } break; } default: break; } } } 

无论交易是恢复还是首次购买, transaction.transactionState将等于SKPaymentTransactionStatePurchased

现在从这个angular度来看,我们如何确定购买是原始还是恢复购买?

简单:如上所见,只要看看transaction.originalTransaction是否被初始化。 每苹果的说明:/ / 只有当状态是SKPaymentTransactionStateRestored有效。

如果SKPaymentTransactionoriginalTransaction被初始化,那意味着有一个以前的事务。 否则,这个交易是一个原始的!

再一次,感谢Matt指出我正确的方向,并使逻辑更清洁!

规范期望似乎是您提供了一个调用restoreCompletedTransactions的还原button。 至于如果用户忽略这一点,只是试图通过你的购买界面,以恢复他已经购买的function,会发生什么,你可能会不必要地担心自己; 文档说:

如果用户试图购买可恢复的产品(而不是使用您实施的恢复界面),则应用程序将接收该项目的常规事务,而不是恢复事务。 但是, 用户不会再为该产品付费。 您的应用程序应将这些交易视为与原始交易的交易完全相同。

商店会提供与用户进行交互的对话框(“您已经购买了这个,是否要再次免费下载?”),免费重新购买的通知将发生在您的paymentQueue:updatedTransactions: as通常情况下,您可以使用其originalTransaction.transactionIdentifier来识别原始购买。

如果您正在实施应用程序内购买,则需要在应用程序某处放置恢复button,否则这是拒绝原因。 你可以看看获得的产品列表,inApp购买iPhone的一个发生。

编辑2: 除了放一个button以避免拒绝,可能还有其他的方法。 马特在评论中提出的一个方法是在应用程序启动时恢复,这足以符合苹果的指导原则。

另外看看本教程的最后部分,它提到了同样的问题,并展示了一种简单的实现方法: http : //www.raywenderlich.com/21081/introduction-to-in-app-purchases-in-ios -6-教程

编辑:

 //Draft implementation of transaction observer delegate -(void) paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions { for (SKPaymentTransaction * transaction in transactions) { switch (transaction.transactionState) { case SKPaymentTransactionStatePurchased: ... case SKPaymentTransactionStateFailed: ... case SKPaymentTransactionStateRestored: ... default: break; } }; } 

Apple IOS SDK文档在这个问题上实际上是误导性的,因为它说:

 @property(nonatomic, readonly) SKPaymentTransaction *originalTransaction The contents of this property are undefined except when transactionState is set to SKPaymentTransactionStateRestored. 

问题是,当用户点击你的购买button,通过购买过程,最后得到一个消息,他已经支付,他可以免费重新下载,你的观察员不会给你发送一个SKPaymentTransactionStateRestored。 它实际上向您发送一个SKPaymentTransactionStatePurchased。

好消息是,尽pipe有文档,即使您的事务处理状态是SKPaymentTransactionStatePurchased,您也会获得属性originalTransaction。 只要testing看看这个属性是否为零,你就知道这个交易是新购买还是旧购买免费恢复。