无法恢复时的“恢复事务”按钮行为

时间:2012-07-13 10:05:25

标签: ios itunes in-app-purchase

正如in this question和其他地方所讨论的那样,Apple现在要求应用程序为用户提供一种方法来恢复In App Purchase的已完成交易。

我全力以赴。我的应用程序的第一个版本以某种方式让它在没有它的情况下进行了审核(当时我还没有意识到这个规则,和/或它还没有被强制执行),但后来我开始接收来自用户的大量电子邮件询问缺少的内容(也有数据存储指南,并且不会备份繁重的可下载内容)。

因此,假设我在用户界面的某个位置添加了一个“恢复”按钮,以便点按调用时:

[[SKPaymentQueue defaultQueue] restoreCompletedTransactions];

到目前为止,这么好。系统会提示用户输入AppleID和/或密码,恢复过程开始。

我遇到的问题是:如果没有要恢复的事务,AppleID提示在我的应用程序中基本上没有任何反应,这可能会让用户感到困惑或使应用看起来没有响应或破碎。

我希望能够按照“所有购买都是最新的”等方式显示提醒视图。

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

有人认为这是一个糟糕的设计吗?UX-wise?

4 个答案:

答案 0 :(得分:9)

您还可以实现以下委托功能:

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

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

请记住在

中处理SKPaymentTransactionStateRestored
-(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions

您可能还希望以与使用SKPaymentTransactionState执行交易相同的方式处理已恢复的交易。

答案 1 :(得分:9)

在最新的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委托方法,并将正常处理恢复请求。

答案 2 :(得分:8)

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

我已经看到了足够的"未知错误"警报,只需使用[error localizedDescription]内的-(void)paymentQueue:restoreCompletedTransactionsFailedWithError:即可。 (todo:填充雷达)

所以我看看Apple是如何做到的。 Apple现在购买非消费类应用程序的唯一应用程序是GarageBand(2014年12月)。

取代"恢复购买","恢复以前的购买"或者......他们选择"Already Purchased?"

Purchase Screen 1

但是这里是我更感兴趣的屏幕,当没有任何内容需要恢复时按下"Already Purchased?"的结果:

Purchase Screen 2

"There are no items available to restore at this time."不是革命性的,但是打败了#34;未知错误"

让我们看一下-(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和没有informativeText的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上的示例

Example on 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.}

答案 3 :(得分:0)

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