处理取消的IAP交易

时间:2011-04-26 09:37:45

标签: iphone in-app-purchase storekit

我正在使用StoreKit进行应用内购买。当用户按下“取消”按钮时,我发现API的行为很古怪。

例如,如果我在“确认您的应用内购买”屏幕上按“取消”,我会收到SKPaymentTransactionStateFailederror.code == SKErrorPaymentCancelled的交易。

但是,如果我按“购买”然后按“取消”,我会与Failed进行error.code == 0次交易。 error.localizedDescription是“无法连接到iTunes Store”,这显然是个谎言。

将所有Failed交易视为可忽略的取消很有诱惑力,但我也可以清楚地看到,如果设备在飞机模式下处于离线状态,我会收到Failed交易但没有提醒警报;在这种情况下,我应该通知用户解释问题。

我注意到MKStoreKit假设所有失败都是取消。永远不会调用MKStoreManager的{​​{3}}方法;对于所有MKStoreObserver次交易,transactionCanceled始终致电FailedMKStoreManager.h的{​​{1}}评论failedTransaction,这是有道理的,但是谁将通知用户transactionCanceled未取消的交易?

处理这些故障的最佳做法是什么?我应该吞下错误吗?总是显示错误,即使它是多余的?

5 个答案:

答案 0 :(得分:11)

我们有相当庞大的用户群通过移动连接购买东西,只显示

的提醒
code != SKErrorPaymentCancelled && code != SKErrorPaymentNotAllowed

显然,这是你能做的最好的事情。我还看到了你提到的取消的奇怪行为,据我所知,这是一个框架错误。

答案 1 :(得分:3)

之前的答案非常接近。 MKStoreKit可以自动显示有效错误条件的错误消息,如父母控制打开等等。

尽管如此,为了处理购买取消,我还在MKStoreKitDelegate中提供了一个名为transactionCanceled的委托(从v3.5开始)。

处理并停止任何活动微调器或进行购买呼叫的视图控制器上的进度...

答案 2 :(得分:0)

我只是想补充一点,因为没有互联网连接的错误应该在使用Apple的Reachability类IMO进行任何交易之前被捕获。这样您就不需要依赖Apple的API来解决直接和常见的错误。

答案 3 :(得分:0)

我认为您的责任和决定是在哪里显示已取消交易的警报。但你绝对应该完成它,否则它会一直下降到失败状态。所以应该是这样的:

if (transaction.error.code == SKErrorPaymentCancelled) {
    [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
} else {
    [self notifyError:transaction.error];
}

更新: 由于The Business of iPhone App Development: Making and Marketing Apps that Succeed我们应该在更新失败状态后完成交易。知道是否存在我们不应该的情况会很有趣。

答案 4 :(得分:-1)

还有一个问题...... 点击“购买”按钮后,它将显示另一个“警报”视图,并询问有关帐户信息的信息。

如果我确实取消那么它将进入案例SKErrorUnknown: 然后 我无法显示这样的信息 “您的购买无法完成。请检查您的网络设置,稍后再试。”

- (void) failedTransaction: (SKPaymentTransaction *)transaction
{   
    switch (transaction.error.code) {
        case SKErrorUnknown:
            NSLog(@"SKErrorUnknown");
            break;
        case SKErrorClientInvalid:
            NSLog(@"SKErrorClientInvalid");
            break;
        case SKErrorPaymentCancelled:
            NSLog(@"SKErrorPaymentCancelled");
        break;
        case SKErrorPaymentInvalid:
            NSLog(@"SKErrorPaymentInvalid");
            break;
        case SKErrorPaymentNotAllowed:
            NSLog(@"SKErrorPaymentNotAllowed");
        break;
        default:
            NSLog(@"No Match Found for error");
            break;
    }
    NSLog(@"transaction.error.code %@",[transaction.error description]);
    if (transaction.error.code == SKErrorPaymentCancelled) {
        [[MKStoreManager sharedManager] transactionCanceled:transaction];
    } else {
        [[MKStoreManager sharedManager] failedTransaction:transaction];
    }
    [[SKPaymentQueue defaultQueue] finishTransaction: transaction]; 
}