第一步,准备工作
1、写代码之前,一定要阅读苹果的《APP内购买项目》文档
2、在iTunes connect后台配置项目的内容,这里就不在多写了。
第二步,代码部分
1.判断用户是否开启内购,代码如下
//有支付行为的时候开启,监听支付结果
[[SKPaymentQueue defaultQueue]addTransactionObserver:self];
if ([SKPaymentQueue canMakePayments]) {
[SVProgressHUDManager showLoding:@"创建订单中"];
//在这里找服务器创建订单
}else{
[SVProgressHUDManager showToast:@"购买失败"];
}
3.拿到订单号后去苹果那里查询商品ID,商品ID在iTunes Connect里设置过了
//productID为iTunes Connect里的商品ID
NSArray *product = [[NSArray alloc] initWithObjects:self.productID,nil];
NSSet *nsset = [NSSet setWithArray:product];
SKProductsRequest *request = [[SKProductsRequest alloc]initWithProductIdentifiers:nsset];
request.delegate = self;
[request start];
查询的结果将通过SKProductsRequestDelegate得到查询的结果,代理方法如下:
//查询成功返回
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
NSArray *product = response.products;
if (product.count == 0) {
[SVProgressHUDManager dismissHUD];
[SVProgressHUDManager showToast:@"购买失败"];
return;
}
SKProduct *prod = nil;
for (SKProduct *pro in product) {
if ([pro.productIdentifier isEqualToString:self.productID]) {
prod = pro;
}
}
//查询成功发送购买请求
if (prod != nil) {
SKPayment *payment = [SKPayment paymentWithProduct:prod];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
}
// 请求失败回调,如果请求失败,在这里处理一下
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error{
[SVProgressHUDManager dismissHUD];
[SVProgressHUDManager showToast:@"购买失败"];
}
// 请求成功回调
- (void)requestDidFinish:(SKRequest *)request{
[SVProgressHUDManager dismissHUD];
}
4、监听支付成功或者失败的方法
// 监听购买结果
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions{
for (SKPaymentTransaction *tran in transactions) {
switch (tran.transactionState) {
case SKPaymentTransactionStatePurchased:
NSLog(@"购买成功");
//本地进行进行校验
//[self verifyPurchaseWithPaymentTransactionWith:tran];
//服务端进行校验
[self requestWithApplePay];
[[SKPaymentQueue defaultQueue] finishTransaction:tran];
break;
case SKPaymentTransactionStatePurchasing:
NSLog(@"商品添加进列表");
break;
case SKPaymentTransactionStateRestored:
NSLog(@"已经购买过商品");
[[SKPaymentQueue defaultQueue] finishTransaction:tran];
break;
case SKPaymentTransactionStateFailed:
NSLog(@"购买失败");
[[SKPaymentQueue defaultQueue] finishTransaction:tran];
[SVProgressHUDManager showToast:@"购买失败"];
break;
default:
[[SKPaymentQueue defaultQueue] finishTransaction:tran];
break;
}
}
}
5、校验
当SKPaymentTransactionStatePurchased时,也就是支付成功的时候,要进行订单校验,这个一般都放在服务器,我们支付成功,告诉服务器,服务器去校验的同时也能更新服务器端用户数据
服务器校验就不在多说,这里说下本地校验
本地校验这里要多说一句:
进行网络检验的时候,开始的时候用的程序里封装的AF进行网络校验,一直反馈21002,后来发现可以通过设置
[AFHTTPSessionManager manager].responseSerializer.acceptableContentTypes 解决,但是要改全局设置,不方便
直接用下面代码块的请求就解决了
#ifdef DEBUG //测试阶段
#define ApplePay_Check @"https://sandbox.itunes.apple.com/verifyReceipt"
#else //发布阶段
#define ApplePay_Check @"https://buy.itunes.apple.com/verifyReceipt"
#endif
//购买成功,本地校验
-(void)verifyPurchaseWithPaymentTransactionWith:(SKPaymentTransaction *)tran{
//从沙盒中获取交易凭证并且拼接成请求体数据
NSURL *receiptUrl=[[NSBundle mainBundle] appStoreReceiptURL];
NSData *receiptData=[NSData dataWithContentsOfURL:receiptUrl];
NSString *receiptString = [receiptData base64EncodedStringWithOptions:0];
if ([CommonTools isNullWithString:receiptString]) {
return;
}
NSError *error;
NSDictionary *requestContents = @{
@"receipt-data":receiptString
};
NSData *requestData = [NSJSONSerialization dataWithJSONObject:requestContents
options:0
error:&error];
// Create a POST request with the receipt data.
NSURL *storeURL = [NSURL URLWithString:ApplePay_Check];
NSMutableURLRequest *storeRequest = [NSMutableURLRequest requestWithURL:storeURL];
[storeRequest setHTTPMethod:@"POST"];
[storeRequest setHTTPBody:requestData];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:storeRequest queue:queue
completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
if (connectionError) {
/* ... Handle error ... */
} else {
NSError *error;
NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
if (!jsonResponse) { /* ... Handle error ...*/ }
/* ... Send a response back to the device ... */
}
}];
}
5、最后一步
- (void)dealloc {
[[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
}
最后,杂谈
关于沙盒账号的问题,推荐一篇
https://www.jianshu.com/p/1ef61a785508
我过程中遇到原来设置的测试员一直不能用的问题,删除重新加入就行了。
最后,希望这篇文章能对各位带来帮助。
网友评论