客户端IAP二次验证

 

1、首先苹果IAP把每次购买抽象成了一个事务(SKPaymentTransaction),

 

- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response;
每次在上述方法中收到反馈信息之后添加的[[SKPaymentQueue defaultQueue] addPayment:payment];
就相当于在事务管理中添加了一个事务,只有事务被正常结束(finishTransaction:)该次支付行为才算完成。
即使一次支付中途被中断,这次事务也并没有丢失。假设支付没有完成App就退出了(比如突然崩溃了),那么当下次App重启之后(调用了addTransactionObserver:),之前被中断的事务会接着进行。
这个的缺点就是中间等待重启的时间可能会很长,影响用户体验。

 

2、在购买成功后的客户端二次验证。

每次购买成功之后都会把encodeStr存到本地,验证成功再进行删除。以后每次打开应用或打开充值会先查看是否有未完成的验证

//交易结果
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions{
    NSLog(@"5.交易结果");
    for (SKPaymentTransaction *transaction in transactions){
        switch (transaction.transactionState){
            case SKPaymentTransactionStatePurchased:{//交易完成
                NSLog(@"交易完成");
                [self completeTransaction:transaction];
            } break;
            case SKPaymentTransactionStateFailed://交易失败
            { [self failedTransaction:transaction];
                NSLog(@"-----交易失败 --------");
                [SVProgressHUD dismiss];
                UIAlertView *alerView2 =  [[UIAlertView alloc] initWithTitle:@"提示"
                                                                     message:@"购买失败,请重新尝试购买"
                                                                    delegate:nil cancelButtonTitle:NSLocalizedString(@"关闭",nil) otherButtonTitles:nil];
                [alerView2 show];
                
            }break;
            case SKPaymentTransactionStateRestored://已经购买过该商品
                [self restoreTransaction:transaction];
                NSLog(@"-----已经购买过该商品 --------");
            case SKPaymentTransactionStatePurchasing:      //商品添加进列表
                NSLog(@"-----商品添加进列表 --------");
                break;
            default:
                break;
        }
    }
}
- (void)completeTransaction: (SKPaymentTransaction *)transaction{
    NSString * productIdentifier = transaction.payment.productIdentifier;
    if ([productIdentifier length] > 0) {
        [SVProgressHUD dismiss];
        //添加IAPModel到本地
        //获取验证凭证
        NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
        //从沙盒中获取购买凭证
        NSData *receiptData = [NSData dataWithContentsOfURL:receiptURL];
        //进行Base64加密
        NSString *encodeStr = [receiptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
        WekeIAPModel *model = [[WekeIAPModel alloc]initWithReceiptStr:encodeStr user_id:[AppSingle sharedAppSingle].user_id];
        [[AppSingle sharedAppSingle].IAPArray addObject:model];
        [SaveCachesFile saveDataList:[AppSingle sharedAppSingle].IAPArray fileName:WekeIAP];
        [self verifyPruchaseWithEncodeStr:encodeStr];
        [[SKPaymentQueue defaultQueue] finishTransaction: transaction];
    }else{
        [SVProgressHUD dismiss];
        UIAlertView *alerView2 =  [[UIAlertView alloc] initWithTitle:@"提示"
                                                             message:@"购买失败,未能连接到苹果服务器"
                                                            delegate:nil cancelButtonTitle:NSLocalizedString(@"关闭",nil) otherButtonTitles:nil];
        [alerView2 show];
    }
}
//验证购买凭证
- (void)verifyPruchaseWithEncodeStr :(NSString *)encodeStr{
    //验证URL POST请求
    NSURL *url = [NSURL URLWithString:Buy_Verify_Receipt_Url];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:20.0f];
    request.HTTPMethod = @"POST";
    NSString *payload = [NSString stringWithFormat:@"{\"receipt-data\" : \"%@\"}", encodeStr];
    NSData *payloadData = [payload dataUsingEncoding:NSUTF8StringEncoding];
    request.HTTPBody = payloadData;
    // 提交验证请求,并获得官方的验证JSON结果
    NSData *result = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
    // 官方验证结果为空
    if (result == nil) {
        NSLog(@"验证失败");
    }else{
        NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:result options:NSJSONReadingAllowFragments error:nil];
        NSLog(@"线上环境验证结果%@",dict);
        if ([[dict objectForKey:@"status"] integerValue] == 21007) {
            //如果是沙盒环境
            [self verifyPruchaseInSANDBOXWithEncodeStr:encodeStr];
        }else if ([[dict objectForKey:@"status"] integerValue] == 0){
            NSLog(@"线上环境验证成功,进行增加积分等操作");
            //验证成功 删除IAP数组中的该Model
            for (WekeIAPModel *model in self.IAPArray) {
                if ([model.encodeStr isEqualToString:encodeStr]) {
                    [[AppSingle sharedAppSingle].IAPArray removeObject:model];
                    [self.IAPArray removeObject:model];
                    [SaveCachesFile saveDataList:[AppSingle sharedAppSingle].IAPArray fileName:WekeIAP];
                }
            }
            [self postGrede];
            
        }else{
            NSLog(@"线上环境验证失败");
            UIAlertController *alertCT = [UIAlertController alertControllerWithTitle:@"提示" message:@"充值验证失败,请重试" preferredStyle:(UIAlertControllerStyleAlert)];
            UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"取消"style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
            }];
            UIAlertAction *care = [UIAlertAction actionWithTitle:@"重试"style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
                [self verifyPruchaseWithEncodeStr:encodeStr];
            }];
            [alertCT addAction:cancel];
            [alertCT addAction:care];
            [self presentViewController:alertCT animated:YES completion:nil];
        }
    }
}

//在沙盒中验证
- (void)verifyPruchaseInSANDBOXWithEncodeStr:(NSString *)encodeStr{

    //验证URL POST请求
    NSURL *url = [NSURL URLWithString:SANDBOX_VERIFY_RECEIPT_URL];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:20.0f];
    request.HTTPMethod = @"POST";
    NSString *payload = [NSString stringWithFormat:@"{\"receipt-data\" : \"%@\"}", encodeStr];
    NSData *payloadData = [payload dataUsingEncoding:NSUTF8StringEncoding];
    request.HTTPBody = payloadData;
    // 提交验证请求,并获得官方的验证JSON结果
    NSData *result = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
    if (result== nil) {
        NSLog(@"沙盒验证失败");
        UIAlertController *alertCT = [UIAlertController alertControllerWithTitle:@"提示" message:@"充值验证失败,请重试" preferredStyle:(UIAlertControllerStyleAlert)];
        UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"取消"style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
        }];
        UIAlertAction *care = [UIAlertAction actionWithTitle:@"重试"style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            [self verifyPruchaseInSANDBOXWithEncodeStr:encodeStr];
        }];
        [alertCT addAction:cancel];
        [alertCT addAction:care];
        [self presentViewController:alertCT animated:YES completion:nil];
    }else{
        NSLog(@"沙盒验证成功");
        [self postGrede];
        //验证成功 删除IAP数组中的该Model
        for (WekeIAPModel *model in self.IAPArray) {
            if ([model.encodeStr isEqualToString:encodeStr]) {
                [[AppSingle sharedAppSingle].IAPArray removeObject:model];
                [self.IAPArray removeObject:model];
                [SaveCachesFile saveDataList:[AppSingle sharedAppSingle].IAPArray fileName:WekeIAP];
            }
        }
        
    }
}

 

posted @ 2018-03-20 15:39  小师傅啊小师傅  阅读(472)  评论(0编辑  收藏  举报