IAP流程
介绍
这里介绍的IAP使用服务器模式:
- 调用服务器接口创建一个商品的订单
- 请求Apple的商品列表
- 选取商品调用苹果支付
- 支付成功(会返回凭证)
- 把支付成功的返回凭证上传到APP服务器(带上订单的ID,有利于后台判断是哪个订单支付成功)
- APP服务器保存该凭证等数据并像苹果服务器发起凭证验证,验证成功则发送商品
配置
iTunesConnect上创建内购项目。
开发流程
客户端流程
1.初始化,添加一个交易队列观察者
[[SKPaymentQueue defaultQueue] addTransactionObserver:xxxx];
IAP支付的机制,每次支付行为或每笔交易被认为是一个SKPaymentTransation,只有当SKPaymentTransation被finishTransaction:,这次支付(交易)行为才算是正常结束了。即使这次支付途中被中断,其实也并没有丢失。假设支付没有完成 App 就退出了(比如崩溃),那么当下次 App 重启之后,只要设置了监听addTransactionObserver:,之前被中断的支付就会接着进行。
2.去苹果服务器请求产品信息
NSSet* set = [NSSet setWithObjects:productId, nil];
SKProductsRequest* skr = [[SKProductsRequest alloc] initWithProductIdentifiers:set];
self.skProductsRequest = skr;
self.skProductsRequest.delegate = self;
[self.skProductsRequest start];
3.请求回调
请求到IAP产品信息,发起购买
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
if (response.products.count == self.arrayFromatProducts.count) {
[self parseFromattingPriceData:response.products];
}else{
SKPayment* p = [SKPayment paymentWithProduct:[response.products objectAtIndex:0]];
[[SKPaymentQueue defaultQueue] addPayment:p];
}
}
请求失败:
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error
{
if (self.requestProductFailure) {
self.requestProductFailure(error);
}
}
购买结果:
#pragma mark SKPaymentTransactionObserver
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions{
for (SKPaymentTransaction *transaction in transactions){
switch (transaction.transactionState){
case SKPaymentTransactionStatePurchased:{
NSLog(@"transaction.payment.productIdentifier:%@",transaction.payment.productIdentifier);
[self verifyPuschase:transaction];
break;
}
case SKPaymentTransactionStateRestored:{//已经购买过该商品
[self verifyPuschase:transaction];
break;
}
case SKPaymentTransactionStateFailed:{
[[SKPaymentQueue defaultQueue]finishTransaction:tran];
if(transaction.error.code != SKErrorPaymentCancelled) {
NSLog(@"购买失败");
} else {
NSLog(@"用户取消交易");
}
break;
}
default:
break;
}
}
}
购买结果发送到服务端。服务端再到苹果服务器验证凭证
收到
- (void)verifyPurchase:(SKPaymentTransaction *)transaction {
//先发服务端验证
//收到服务端验证成功后,完成苹果订单。
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}
退出时移除观察者
- (void)dealloc {
[[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
}
服务端流程
服务端收到购买成功,发送到苹果服务器验证。
//沙盒测试环境验证
#define SANDBOX @"https://sandbox.itunes.apple.com/verifyReceipt"
//正式环境验证
#define AppStore @"https://buy.itunes.apple.com/verifyReceipt"
沙盒测试
-
在用户与职能中添加沙箱测试账号。
xcode配置项目的bundleid与Apple后台配置的bundleid一致。打开In App Purchase
退出iPhone的App Store账号(因为我们需要使用沙盒账号登录)
xcode运行App,购买商品,系统会让你进行登录,这里我们点击“使用现有的AppleID”就可以沙盒测试账号进行登录了。
重试机制
IAP在实际使用中会有用户返回内购丢单的情况。分析在整个流程中会有两个环节失败的情况。
- Apple支付成功后,客户端没有收到Apple支付的回调,无法发起服务端验证。
【解决办法】:App启动后要注册对Apple支付结果回调的观察。这样Apple还会恢复支付状态更新的回调。
- 收到Apple支付成功后,发起服务端验证失败。这样在Apple那里已经支付完成了,但是用户却没有收到购买的商品。
【解决办法】:增加重试, 延迟对苹果订单的确认。
- 1、发起服务端验证接口失败(网络错误或者业务错误时),立即间隔一段时间重试
- 2、延迟对苹果订单的确认,充值完成才确认苹果订单。App启动的时候,对于未验证成功的支付,再次发起服务端验证。