我正在使用StoreKit进行应用内购买。当用户按下“取消”按钮时,我发现API的行为很古怪。
例如,如果我在“确认您的应用内购买”屏幕上按“取消”,我会收到SKPaymentTransactionStateFailed
与error.code == SKErrorPaymentCancelled
的交易。
但是,如果我按“购买”然后按“取消”,我会与Failed
进行error.code == 0
次交易。 error.localizedDescription
是“无法连接到iTunes Store”,这显然是个谎言。
将所有Failed
交易视为可忽略的取消很有诱惑力,但我也可以清楚地看到,如果设备在飞机模式下处于离线状态,我会收到Failed
交易但没有提醒警报;在这种情况下,我应该通知用户解释问题。
我注意到MKStoreKit假设所有失败都是取消。永远不会调用MKStoreManager
的{{3}}方法;对于所有MKStoreObserver
次交易,transactionCanceled
始终致电Failed
。 MKStoreManager.h
的{{1}}评论failedTransaction
,这是有道理的,但是谁将通知用户transactionCanceled
未取消的交易?
处理这些故障的最佳做法是什么?我应该吞下错误吗?总是显示错误,即使它是多余的?
答案 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];
}