我在应用程序中有很多1次购买IAP。用户可以很好地购买它们。
我的问题是,我正在与Flurry整合以跟踪实际购买情况,而不仅仅是恢复购买,但我的SKPaymentTransaction
transactionState
始终以SKPaymentTransactionStatePurchased
而不是SKPaymentTransactionStateRestored
返回{1}}。
显然SKPaymentTransactionStateRestored
仅在- (void)restoreCompletedTransactions
时调用,但我什么时候调用此方法?
我的思维过程是购买应该是这样的:1)用户选择产品,2)询问用户是否愿意购买X数量的产品。 3)服务器检查用户之前是否已购买,以及是否已通过设置SKPaymentTransactionStateRestored
进行恢复。否则,处理事务并设置SKPaymentTransactionStatePurchased
。显然这是错误的,我想在{... 1}之间的某处调用???
谢谢,
威尔
答案 0 :(得分:8)
修改强>
最初我发布了一个非常长的,不需要的方法来获得我需要的东西,但正如你将在下面看到的,Matt帮助我找出了我想要的变量。
举个例子,假设用户以前购买了我的应用程序,购买了所有可用的非消耗性IAP,然后删除了应用程序。当用户重新安装应用程序时,我希望能够确定他们何时再次“购买”产品,是原始(第一次)购买还是恢复购买?
我已经实施了“恢复所有购买”按钮,但是假设用户忽略/看不到它,并尝试选择之前购买的产品。
与正常购买一样,我会执行以下操作:
if ([SKPaymentQueue canMakePayments])
{
self.productRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObject:productID]];
self.productRequest.delegate = self;
[self.productRequest start];
}
else
{
//error message here
}
用户登录iTunes帐户后,应用程序会让他们知道他们已经购买了这个帐户,现在它将被恢复。将调用以下委托方法:
-(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
。
现在,我们如何确定购买是原始购买还是恢复购买?
简单:如上所示,只需查看transaction.originalTransaction
是否已初始化。根据Apple的说明: //仅在状态为SKPaymentTransactionStateRestored时才有效。
如果SKPaymentTransaction
的{{1}}已初始化,则表示之前有交易。否则,此交易是原创交易!
再次感谢Matt指出我正确的方向,并使逻辑变得更加清洁!
答案 1 :(得分:7)
规范期望似乎是您提供了一个调用restoreCompletedTransactions
的恢复按钮。至于如果用户忽略了这一点并且只是试图通过你的购买界面来恢复他已经购买的功能会发生什么,你可能会不必要地担心自己; docs说:
如果用户尝试购买可恢复产品(而不是使用您实施的恢复界面),则应用程序将收到该项目的常规事务,而不是恢复事务。但是,用户不会再次为该产品付费。您的应用程序应将这些交易视为与原始交易的交易相同。
商店会设置与用户互动的对话框(“你已经购买了这个,你想再免费下载吗?”),免费重新购买的通知将在你的{{ 1}}像往常一样,您可以使用其paymentQueue:updatedTransactions:
来识别原始购买。
答案 2 :(得分:2)
如果您要实施应用内购买,您需要在应用中的某个位置放置恢复按钮,否则这是拒绝原因。您可以查看Get list of purchased products, inApp Purchase iPhone的一个事件。
编辑2:除了按钮以避免拒绝之外,可能还有其他方法。亚光在评论中建议的一种方法是在应用程序启动时恢复,这似乎足以符合苹果的指导方针。
另请参阅本教程的最后一部分,它提到了同样的问题,并展示了一种实现它的简单方法: http://www.raywenderlich.com/21081/introduction-to-in-app-purchases-in-ios-6-tutorial
编辑:
//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;
}
};
}
答案 3 :(得分:0)
Apple IOS SDK文档实际上误导了这个问题,因为它说:
@property(nonatomic, readonly) SKPaymentTransaction *originalTransaction
The contents of this property are undefined except when transactionState is set to SKPaymentTransactionStateRestored.
问题在于,当用户点击您的购买按钮时,完成购买过程,最后得到一条他已经付款的消息,并且他可以免费重新下载,您的观察者不会向您发送SKPaymentTransactionStateRestored。它实际上会向您发送SKPaymentTransactionStatePurchased。
好消息是,尽管有文档,但即使您的交易状态为SKPaymentTransactionStatePurchased,您实际上也会获得属性originalTransaction。只需测试一下此属性是否为零,您就会知道该交易是新购买还是旧购买的免费恢复。
答案 4 :(得分:0)
据我观察,在两种可能的情况下,用户可能必须致电恢复购买,
如果您不在后端服务器中维护购买信息:如果用户卸载应用程序或任何此类应用程序数据丢失的情况,则可能会丢失购买信息。在这种情况下,用户可以致电restore,Storekit会再次提供购买收据,您可以通过该收据来确定用户是否较早购买了该购买以及现在是否处于激活状态。
如果您将购买信息存储在支持的情况下(支持的api决定用户是否具有订阅功能的特权):在某些情况下,您可以从Apple购买商品,但由于某种原因无法更新到服务器,在这种情况下,用户可以恢复购买,这将在您的后端服务器上更新购买信息,此后,用户可以跨多个设备/平台/重新安装使用应用程序,但仍然有权获得特权访问。
因此,始终建议在与购买相同的页面上显示还原选项。 如果用户在进行有效订阅时无意中尝试购买而未选择还原, 1.如果他选择了与当前活动者相同的计划,则将被告知现有和订阅的计划 2.如果他选择了除当前订阅之外的其他计划,则将通知他/她当前订阅以及根据最近选择的计划进行升级/降级的选项。