客户端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];
}
} }
}
客户端IAP二次验证的更多相关文章
- In-App Purchase iap 内付费 二次验证代码 (java 服务器端)
参考网址:https://blog.csdn.net/a351945755/article/details/22919533 package com.yichangmao.buyVerify.Comm ...
- ios IAP 内购验证
参考我之前的笔记 苹果内购笔记,在客户端向苹果购买成功之后,我们需要进行二次验证. 二次验证 IOS在沙箱环境下购买成功之后,向苹果进行二次验证,确认用户是否购买成功. 当应用向Apple服务器请求购 ...
- PHP设置谷歌验证器(Google Authenticator)实现操作二步验证
使用说明:开启Google的登陆二步验证(即Google Authenticator服务)后用户登陆时需要输入额外由手机客户端生成的一次性密码.实现Google Authenticator功能需要服务 ...
- Force.com微信企业号开发系列(一) - 启用二次验证
微信于9月份推出企业号后引起了业界不小的反响,许多企业都在思索企业号将如何影响企业的运营,从本文开始,我将详细阐述微信企业号开发的相关知识,而本文将着重介绍如何实现更高安全机制的二次验证. 申请企业体 ...
- jQuery.qrcode.js客户端生成二维码,支持中文并且可以生成LOGO
描述: jquery.qrcode.js 是一个能够在客户端生成矩阵二维码QRCode 的jquery插件 ,使用它可以很方便的在页面上生成二维条码.此插件是能够独立使用的,体积也比较 ...
- destoon 深度整合discuz x2 UC 之免邮箱二次验证
destoon中member/my.php,信息发布入口处判断是否已在dx中做了验证,如果已经验证,则不再提示验证,否则其中dt的验证页面. 在home.php.php. group.php. for ...
- 【转】Android手机客户端关于二维码扫描的源码--不错
原文网址:https://github.com/SkillCollege/QrCodeScan QrCodeScan 这是Android手机客户端关于二维码扫描的源码,使用了高效的ZBar解码库,并修 ...
- 基于RSA securID的Radius二次验证java实现(PAP验证方式)
基于rsa SecurID的二次验证.RSA server自身可以作为Radius服务器,RSA也可以和其他的软件集合,使用其他的server作为Radius服务器. radius的验证的一般流程如下 ...
- 【HELLO WAKA】WAKA iOS客户端 之二 架构设计与实现篇
上一篇主要做了MAKA APP的需求分析,功能结构分解,架构分析,API分析,API数据结构分析. 这篇主要讲如何从零做iOS应用架构. 全系列 [HELLO WAKA]WAKA iOS客户端 之一 ...
随机推荐
- vbs 之 excel 使用VBScript 操作excel
打开excel及新建工作薄 '' 2. Method ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' 2.1 CreateO ...
- vue-router 路由配置
前提: 项目由 vue-cli 脚手架创建. 首先,先下载 vue-router npm install vue-router 安装完成后,运行项目 npm run dev 打开 main.js , ...
- certbot免费证书
yum install python-certbot-nginx 开启防火墙443端口 firewall-cmd --add-port=443/tcp --permanent 别忘了重启 firewa ...
- maven管理工具配置
1.登录maven.apache.org,下载maven.,选择apache-maven-3.6.2-bin.zip,并解压到所需目录. 2.进行环境配置,计算机右击--属性---高级系统配置---环 ...
- 一起感受HTML5和CSS3
Web设计师可以使用HTML4和CSS2.1完成一些很酷的东西.我们可以在不使用陈旧的基于table布局的基础上完成文档逻辑结构并创建内容丰富的网站.我们可以在不使用内联<font>和&l ...
- 2019-9-25-如何让-USB-设备不显示安全删除硬件弹出选项
title author date CreateTime categories 如何让 USB 设备不显示安全删除硬件弹出选项 lindexi 2019-09-25 11:58:19 +0800 20 ...
- wkhtmltopdf linux下html转pdf
https://blog.csdn.net/wujunlei1595848/article/details/91129197 https://github.com/wkhtmltopdf/wkhtml ...
- JAVA错误:Exception in thread "main" java.lang.NullPointerException
JAVA错误:Exception in thread "main" java.lang.NullPointerException例如: Exception in thread &q ...
- CSS盒模型及应用
其实,CSS就三个大模块: 盒子模型 . 浮动 . 定位,其余的都是细节.要求这三部分,无论如何也要学的非常精通. 所谓盒子模型就是把HTML页面中的元素看作是一个矩形的盒子,也就是一个盛装内容的容器 ...
- PHP headers_sent() 函数
定义和用法 headers_sent() 函数检查 HTTP 报头是否发送/已发送到何处. 如果报头已发送,该函数返回 TRUE,否则返回 FALSE. 语法 headers_sent(file,li ...