网上有很多In-App Purchase(简称IAP)的文章,苹果的教程也比较丰富(https://developer.apple.com/in-app-purchase/ 和 https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/StoreKitGuide/Introduction.html)。
但遇到一个问题始终没有找到答案。
IAP的基本思路就是:
查询产品,获取SKProduct的数组。
发起支付请求。
SKMutablePayment *payment = [SKMutablePayment paymentWithProduct:product];
payment.quantity = 1;
payment.applicationUsername = [self hashedValueForAccountName:accountName];
[[SKPaymentQueue defaultQueue]addPayment:payment];
注意:这里发起支付请求,我无法添加(或者说没找到)能在票据(receipt)中返回的数据。applicationUserName只是辅助苹果做一些恶意检测,但最终票据中没有包含。
等待支付结果
-(void)paymentQueue:(SKPaymentQueue )queue updatedTransactions:(NSArray )transactions
{
for (SKPaymentTransaction *transaction in transactions) {
switch (transaction.transactionState) {
// Call the appropriate custom method for the transaction state.
case SKPaymentTransactionStatePurchasing:
[self showTransactionAsInProgress:transaction deferred:NO];
break;
case SKPaymentTransactionStateDeferred:
[self showTransactionAsInProgress:transaction deferred:YES];
break;
case SKPaymentTransactionStateFailed:
[self failedTransaction:transaction];
break;
case SKPaymentTransactionStatePurchased:
[self completeTransaction:transaction];
break;
case SKPaymentTransactionStateRestored:
[self restoreTransaction:transaction];
break;
default:
// For debugging
NSLog(@"Unexpected transaction state %@", @(transaction.transactionState));
break;
}
}
}
发送凭据到自己的服务器,并验证凭据,客户端完成支付。【关键这里有疑问】
SKPaymentTransaction *transaction = <# The current payment #>;
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
如果按照正常流程,肯定没有问题。但苹果文档有句话:
if your app fails to mark a transaction as finished, Store Kit calls the observer every time your app is launched until the transaction is properly finished.
如果我没有主动完成交易,苹果会在下次启动App(或者说添加Observer)时,再次通知。
这里本地会有把票据持久化的操作。但有个很关键的问题,票据中不能带有自定义的信息。也就是返回的票据是不能知道哪个账号发起的支付请求(或许有,但我确实没有找到。如果有的话,就能解决这个问题了。)
我公司的App类似QQ(以下假设是QQ),QQ可以支持多个账号在一台手机上登录(比如有两个账号A和B)。
问题来了:
如果账号A使用IAP购买Q币,苹果服务器已经扣款,但
-(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
还没有来得及调用。(实际测试中出现过这种情况。或者说在交易中的恰当时机主动断网,也能出现)
下次如果使用账号A登录,苹果会再次通知交易。这时把这次交易购买的产品算作账号A的,是没有问题。
但,如果下次使用账号B登录,由于返回的交易票据中没有包含账号的信息,我就不知道该把Q币充值给账号A还是账号B了。
找了好久,没有找到解决办法,请求大家帮忙。
谢谢!
After iOS7.0, SKPayment has added the applicationUsername attribute, which can be used to set user information. Users can be judged based on this value