【问题标题】:"Restore Transactions" Button behavior when there is nothing to restore“恢复事务”按钮行为,当没有什么可以恢复
【发布时间】:2012-07-13 04:15:32
【问题描述】:

正如 in this question 和其他地方所讨论的,Apple 现在要求应用程序包含一种方法,供用户恢复已完成的应用内购买交易。

我完全赞成。我的应用程序的第一个版本在没有它的情况下通过了审查(当时我不知道这条规则,和/或它还没有被强制执行),但后来我开始收到很多来自用户的电子邮件询问丢失的内容(也有数据存储指南,并且没有备份大量可下载的内容)。

假设我在 UI 的某处包含一个“恢复”按钮,当点击该按钮时:

[[SKPaymentQueue defaultQueue] restoreCompletedTransactions];

到目前为止,一切都很好。系统会提示用户输入其 AppleID 和/或密码,然后开始恢复过程。

我遇到的问题是:如果没有要恢复的事务,在 AppleID 提示之后,我的应用中基本上 什么都没有发生,这可能会让用户感到困惑或使应用看起来没有响应或破碎的。

我希望能够显示“所有购买都是最新的”或其他内容的警报视图。

我可以在我的 Transaction Observer 代码中做些什么来检测这种情况吗?

在用户体验方面,有人认为这将是一个糟糕的设计吗?

【问题讨论】:

  • Benjamin 的回答提供了您所要求的更优雅的解决方案。您能否将他的答案标记为已接受的答案,以便所有人都能找到?
  • 嗨@NicolasMiari,你是怎么解决你的问题的

标签: ios itunes in-app-purchase


【解决方案1】:

我在正在开发的应用程序中遇到了同样的问题。我的解决方法是使用 X 秒计时器。当您点击“恢复购买”按钮时它开始,如果恢复的交易事件进入,它会重新启动。一旦它达到 X 秒标记,我会弹出一个显示“已恢复购买”的弹出窗口。因此,如果您没有交易,您应该只需要等待 X 秒。希望对您有所帮助。

【讨论】:

    【解决方案2】:

    您还可以实现以下委托函数:

    -(void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue
    -(void)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error
    

    然后您就会知道恢复过程何时完成或是否失败。 您可以在 paymentQueueRestoreCompletedTransactionsFinished 中混合使用 queue.transactions.count 来查看是否恢复了任何交易。

    记得在 SKPaymentTransactionStateRestored 中处理

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

    您可能还希望以与 SKPaymentTransactionStatePurchased 交易相同的方式处理恢复的交易。

    【讨论】:

    • 不会 queue.transactions.count 只返回待处理的交易 (link)?在这种情况下,总是返回 0(已经完成任何事务)?
    • 我保留一个标志 _didRestore,当我得到 paymentQueue:updatedTransactions: 调用时设置为 true,transactionState == SKPaymentTransactionStateRestored。然后在 paymentQueueRestoreCompletedTransactionsFinished: 我检查那个标志
    【解决方案3】:

    我对恢复购买的正确/最佳措辞感兴趣。

    我已经看到了足够多的“未知错误”警报,只需在 -(void)paymentQueue:restoreCompletedTransactionsFailedWithError: 中使用 [error localizedDescription]。 (待办事项:填充雷达)

    所以我看了一下 Apple 是如何做到的。目前,Apple 推出的唯一具有非消耗性应用内购买的应用是 GarageBand(2014 年 12 月)。

    而不是“恢复购买”、“恢复以前的购买”或......它们与"Already Purchased?" 一起使用。

    但是这里是我比较感兴趣的画面,在没有什么可以恢复的时候按"Already Purchased?"的结果:

    "There are no items available to restore at this time." 不是革命性的,但从“未知错误”中击败了地狱

    让我们看看-(void)paymentQueue:restoreCompletedTransactionsFailedWithError:

    iOS

    - (void)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error
    {
        if ([error.domain isEqual:SKErrorDomain] && error.code == SKErrorPaymentCancelled)
        {
            return;
        }
    
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"There are no items available to restore at this time.", @"")
                                                        message:nil
                                                       delegate:nil
                                              cancelButtonTitle:NSLocalizedString(@"OK", @"")
                                              otherButtonTitles:nil];
        [alert show];
    }
    

    OS X

    我对 OS X 上的相同文本不满意。只有 messageText 而没有 informationativeText 的 NSAlert 看起来是空的和错误的。

    我的一个选择是让用户知道他需要购买它,例如"To use it, you need to buy “%@”."

    我想出的另一个选择是让他们在那里浏览Purchase History。我发现你可以直接用itms://phobos.apple.com/purchaseHistory链接到它。老实说,iTunes Store 中的购买历史是一坨屎,它会让你永远找到一些东西。

    但也许它有助于向人们重新保证我们不会试图让他们重新购买某些东西。始终假设您的客户不知道或无法区分非消耗品和消耗品之间的区别。而且不知道他们不能为非消耗品收取两次费用。

    - (void)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error
        {
        if ([error.domain isEqual:SKErrorDomain] && error.code == SKErrorPaymentCancelled)
        {
            return;
        }
    
        NSAlert *alert = nil;
        alert = [NSAlert alertWithMessageText:NSLocalizedString(@"There are no items available to restore at this time.", @"")
                                defaultButton:NSLocalizedString(@"OK", @"")
                              alternateButton:NSLocalizedString(@"Purchase History", @"")
                                  otherButton:nil
                    informativeTextWithFormat:@"You can see your purchase history in the iTunes Store."];
        NSModalResponse returnCode = [alert runModal];
        if (returnCode == NSAlertAlternateReturn)
        {
            NSURL *purchaseHistory = [NSURL URLWithString:@"itms://phobos.apple.com/purchaseHistory"];
            [[NSWorkspace sharedWorkspace] openURL:purchaseHistory];
        }
    }
    

    OS X 上的示例

    测试说明(OS X,itunesconnect 沙盒用户):

    当用户点击取消时:

    - (void)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error
    Error Domain=SKErrorDomain Code=2 "The payment was canceled by the user" UserInfo=0x600000470a40 {NSLocalizedDescription=The payment was canceled by the user}
    

    当没有什么可以恢复时:

    - (void)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error
    Error Domain=SKErrorDomain Code=0 "Unknown Error." UserInfo=0x60800007fb80 {NSLocalizedDescription=Unknown Error.}
    

    【讨论】:

    • 感谢您的详细解答。真的加起来了。
    • @catlan,当用户点击恢复但之前从未进行过购买时,您真的看到 restoreCompletedTransactionsFailedWithError 被调用吗?因为在模拟器中,我看到 paymentQueueRestoreCompletedTransactionsFinished 被调用,队列中没有交易(即没有什么可恢复的)。
    【解决方案4】:

    这在最新的 SDK / xCode 8.0, Swift 3 中仍然是一个问题 - 如果尚未进行任何购买的用户尝试“恢复”,请使用以下方法:

    SKPaymentQueue.default().restoreCompletedTransactions()
    

    不会触发处理购买/恢复的常用委托方法:

    paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {...}
    

    有趣的是,可能应该捕获错误的方法也没有被调用:

    func paymentQueue(_ queue: SKPaymentQueue, restoreCompletedTransactionsFailedWithError error: Error){...}
    

    相反,触发了可选方法,就好像恢复工作正常:

    func paymentQueueRestoreCompletedTransactionsFinished()
    

    这可能会导致应用看起来像是挂起/没有做任何事情。

    正如其他答案中所讨论的,其原因是 SKPaymentQueue 不包含任何交易。

    在 Swift 中,这个问题可以通过以下方式解决:

    //Optional Method.
    func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue)
    {
    
        let transactionCount = queue.transactions.count
    
        if transactionCount == 0
        {
            print("No previous transactions found")
    
            //You can add some method to update your UI, indicating this is the problem e.g. use notification centre:
            NotificationCenter.default.post(name: "restoreFailedNoPrevIAP", object: nil)
    
        }
    
    }
    

    重要的是,如果用户之前进行过购买,交易队列不会为空,因此会调用 updateTransaction 委托方法,并正常处理恢复请求。

    【讨论】:

    • 委托行为也适用于使用 Xcode 8/最新 SDK 的 objc。对事务计数解决方法的相同检查。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多