in-app purchase教程:

http://www.appcoda.com/in-app-purchase-tutorial/

3.后台服务器验证收据的正确性

IOS 内支付有两种模式:

1) 内置模式

2) 服务器模式

内置模式的流程可以简单的总结为以下几步:

1) app从app store 获取产品信息

2) 用户选择需要购买的产品

3) app发送支付请求到app store

4) app store 处理支付请求,并返回transaction信息

5) app将购买的内容展示给用户

服务器模式的主要流程如下所示:

1) app从服务器获取产品标识列表

2) app从app store 获取产品信息

3) 用户选择需要购买的产品

4) app 发送 支付请求到app store

5) app store 处理支付请求,返回transaction信息

6) app 将transaction receipt 发送到服务器

7) 服务器收到收据后发送到app stroe验证收据的有效性

8) app store 返回收据的验证结果

9) 根据app store 返回的结果决定用户是否购买成功

上述两种模式的不同之处主要在于:交易的收据验证,内建模式没有专门去验证交易收据,而服务器模式会使用独立的服务器去验证交易收据。内建模式简单快捷,但容易被破解。服务器模式流程相对复杂,但相对安全。

开发之初,苹果方就很负责的告知:我们的服务器不稳定。真正开发之后,发现苹果方果然是很负责的,不仅是不稳定,而且足够慢。app store server验证一个收据需要3-6s时间。

1.用户能否忍受3-6s的等待时间

2.如果app store server 宕机,如何确保成功付费的用户能够得到正常服务。

对于第一个问题,我们有理由相信用户完全无法忍受,所以采用异步验证的方式,服务器收到客户端的请求后,就将请求放到MCQ中去处理。

对于第二个问题,由于苹果人员很负责人的告知:我们的服务器不稳定,所以不排除收据验证超时的情况。对于验证超时的收据,保存到数据库中并标记为验证超时,定时任务每隔一定的时间去app store验证,确保能够获取收据的验证结果。

在开发过程中,需要测试应用是否能够正常的进行支付,但是又不能进行实际的支付,因此需要使用苹果提供的sandbox Store测试。Store Kit不能在iOS模拟器中使用,测试Store必须在真机上进行。

在sandbox中验证receipt

https://sandbox.itunes.apple.com/verifyReceipt

在生产环境中验证receipt

https://buy.itunes.apple.com/verifyReceipt

在实际开发过程中,服务器端通过issandbox字段标识客户端传递的收据是沙盒环境中的收据还是生产环境中的收据。在提交苹果审核前,沙盒测试均无问题。提交苹果审核后,被告知购买失败,审核未通过。通过查询日志发现,客户端发送的交易收据为沙盒收据,但是issandbox字段却标识为生产环境。

结论:苹果审核app时,仍然在沙盒环境下测试。但是客户端同事在app提交苹果审核时,将issandbox字段写死,设置为生产环境。这样就导致沙盒收据发送到https://buy.itunes.apple.com/verifyReceipt去验证。

那么如何自动的识别收据是否是sandbox receipt呢?

识别沙盒环境下收据的方法有两种:

1.根据收据字段 environment = sandbox。

2.根据收据验证接口返回的状态码

如果status=21007,则表示当前的收据为沙盒环境下收据, t进行验证。

苹果反馈的状态码;

21000App Store无法读取你提供的JSON数据
21002 收据数据不符合格式
21003 收据无法被验证
21004 你提供的共享密钥和账户的共享密钥不一致
21005 收据服务器当前不可用
21006 收据是有效的,但订阅服务已经过期。当收到这个信息时,解码后的收据信息也包含在返回内容中
21007 收据信息是测试用(sandbox),但却被发送到产品环境中验证
21008 收据信息是产品环境中使用,但却被发送到测试环境中验证

先生产验证后测试验证,可以避免来回切换接口的麻烦。测试验证只要用你自己申请的测试appid的时候才会用到,用户不会拥有测试appid,所以不会走到测试验证这一步。即使生产验证出错,应该也不回返回21007状态吗。测试验证通过的用户名,和充值金额最好用数据库记录下来,方便公司资金核对。

-(void)verifyFinishedTransaction:(SKPaymentTransaction *)transaction{

    if(transaction.transactionState == SKPaymentTransactionStatePurchased){
NSString *transactionIdentifier = transaction.transactionIdentifier;
NSData *transactionReceipt = transaction.transactionReceipt;
//将transactionIdentifer和加密后的transactionReceipt数据发送给server端 NSString* receipent = [NSString stringWithFormat:@"%s", transactionReceipt.bytes]; NSLog(@"receipent = %@", receipent); // 在app上做验证, 仅用于测试
NSString *payload = [NSString stringWithFormat:@"{\"receipt-data\" : "%@", "password" : "%@"}",
receipent, transactionIdentifier];
NSData *payloadData = [payload dataUsingEncoding:NSUTF8StringEncoding];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:ITMS_SANDBOX_VERIFY_RECEIPT_URL]];
[request setHTTPMethod:@"POST"];
[request setHTTPBody:payloadData];
NSError* err;
NSURLResponse *theResponse = nil;
NSData *data=[NSURLConnection sendSynchronousRequest:request
returningResponse:&theResponse
error:&err];
NSError *jsonParsingError = nil;
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&jsonParsingError];
NSLog(@"%@", dict);
NSLog(@"done");
}
}
唐巧-iOS应用内支付(IAP)的那些坑:http://blog.jobbole.com/38032/
项目已购买问题:http://www.cnblogs.com/meteoric_cry/p/4598304.html
参考链接:http://blog.csdn.net/jiisd/article/details/50527426

iOS in-app purchase详解的更多相关文章

  1. ASP.NET MVC Filters 4种默认过滤器的使用【附示例】 数据库常见死锁原因及处理 .NET源码中的链表 多线程下C#如何保证线程安全? .net实现支付宝在线支付 彻头彻尾理解单例模式与多线程 App.Config详解及读写操作 判断客户端是iOS还是Android,判断是不是在微信浏览器打开

    ASP.NET MVC Filters 4种默认过滤器的使用[附示例]   过滤器(Filters)的出现使得我们可以在ASP.NET MVC程序里更好的控制浏览器请求过来的URL,不是每个请求都会响 ...

  2. iOS 单元测试之XCTest详解(一)

    iOS 单元测试之XCTest详解(一) http://blog.csdn.net/hello_hwc/article/details/46671053 原创blog,转载请注明出处 blog.csd ...

  3. ios新特征 ARC详解

    IOS ARC 分类: IOS ARC2013-01-17 09:16 2069人阅读 评论(0) 收藏 举报   目录(?)[+]   关闭工程的ARC(Automatic Reference Co ...

  4. App.Config详解及读写操作

    App.Config详解及读写操作   App.Config详解 应用程序配置文件是标准的 XML 文件,XML 标记和属性是区分大小写的.它是可以按需要更改的,开发人员可以使用配置文件来更改设置,而 ...

  5. Cordova 打包 Android release app 过程详解

    Cordova 打包 Android release app 过程详解 时间 -- :: SegmentFault 原文 https://segmentfault.com/a/119000000517 ...

  6. iOS学习之UINavigationController详解与使用(一)添加UIBarButtonItem

    http://blog.csdn.net/totogo2010/article/details/7681879 1.UINavigationController导航控制器如何使用 UINavigati ...

  7. IOS—UITextFiled控件详解

    IOS—UITextFiled控件详解 //初始化textfield并设置位置及大小 UITextField *text = [[UITextField alloc]initWithFrame:CGR ...

  8. [转]iOS学习之UINavigationController详解与使用(三)ToolBar

    转载地址:http://blog.csdn.net/totogo2010/article/details/7682641 iOS学习之UINavigationController详解与使用(二)页面切 ...

  9. App.Config详解

    App.Config详解 应用程序配置文件是标准的 XML 文件,XML 标记和属性是区分大小写的.它是可以按需要更改的,开发人员可以使用配置文件来更改设置,而不必重编译应用程序.配置文件的根节点是c ...

  10. IOS 友盟使用详解

    IOS 友盟使用详解 这篇博客将会详细介绍友盟的使用,希望对博友们有所帮助. 首先我们在浏览器上搜索友盟. 在这里我们选择官网这个,进去友盟官网后我们按照下图进行选择. 接下来选择如下图 Next 这 ...

随机推荐

  1. 在springmvc中无法使用@value()注解

    折腾了一下午,试了很多解决办法,就是死活不能扫描到properties文件.本来打算使用软编码的,尝试更改了全部jar包版本,还是无法解决. 后面想到了,spring和springmvc容器的加载顺序 ...

  2. redis连接超时问题排查

    连接池无法获取到连接或获取连接超时redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource f ...

  3. python获取上一个月第一天0点的unix时间戳

    这两天做统计,需要用到当月第一天0点0分0秒的unix timestamp,上个月第一天0点的unix时间戳,三个月前月第一天的0点的Unix时间戳,六个月前当月第一天的0点的Unix时间戳,现在整理 ...

  4. dplyr包

    是Hadley Wickham的新作,主要用于数据清洗和整理,该包专注dataframe数据格式,从而大幅提高了数据处理速度,并且提供了与其它数据库的接口:tidyr包的作者是Hadley Wickh ...

  5. python 搜索引擎Whoosh中文文档和代码 以及jieba的使用

    注意, 数据库的表最好别有下划线 中文文档链接: https://mr-zhao.gitbooks.io/whoosh/content/%E5%A6%82%E4%BD%95%E7%B4%A2%E5%B ...

  6. c++ 的makefile文件实例

    首先声明, 感谢九哥的帮助,因为从来没写过makefile, 所以一直是手动编译, 然后有一次写了三个文件, 需要编译, 而我只编译了一个文件, 所以一直出错, 九哥告诉我用makefile更方便, ...

  7. android设置主mic/副mic录音

    //添加MIC设置参数 /hal/audio_extn/audio_extn.c @@ -75,6 +75,7 @@ struct audio_extn_module { bool ras_enabl ...

  8. Maven POM

    POM代表项目对象模型.它是 Maven 中工作的基本单位,这是一个 XML 文件.它始终保存在该项目基本目录中的 pom.xml 文件.POM 包含的项目是使用 Maven 来构建的,它用来包含各种 ...

  9. 使用Camera功能 AREA的理解

    转至 http://blog.csdn.net/think_soft/article/details/7998478 使用Camera功能 大多数的Camera功能都是使用Camera.Paramet ...

  10. 利用CA私钥和证书创建中间CA

    本文借助实验环境下创建的root CA私钥和证书进一步创建中间CA.为了便于区分,我们将创建中间CA(intermediate CA)的CA称为根CA(root CA). 关于如何使用OpenSSL创 ...