iOS-应用内购买看

2019-03-20  本文已影响0人  那C乱我心

第一步,准备工作

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
我过程中遇到原来设置的测试员一直不能用的问题,删除重新加入就行了。

最后,希望这篇文章能对各位带来帮助。

上一篇下一篇

猜你喜欢

热点阅读