1.IOS purchase 介绍
所谓的IOS 内支付就是在应用中内嵌Store,在iOS APP 中使用Store Kit framework来实现In-App Purchase,Store Kit会连接App Store,代替应用安全地完成用户支付的支付行为。Store Kit提示用户授权支付,然后通知应用“用户已经完成支付”,这样应用就可以提供用户购买的东西。
2.IOS内支付开发流程
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 返回的结果决定用户是否购买成功
上述两种模式的不同之处主要在于:交易的收据验证,内建模式没有专门去验证交易收据,而服务器模式会使用独立的服务器去验证交易收据。内建模式简单快捷,但容易被破解。服务器模式流程相对复杂,但相对安全。
上面介绍了IOS 内支付的基本流程。IOS内支付的流程并不复杂,但是在实际开发、提交苹果审核以及上线后出现了不少问题。下面就一一道出在上述过程中踩过的雷,进过的坑。
无尽的等待(开发)
开发之初,苹果方就很负责的告知:我们的服务器不稳定。真正开发之后,发现苹果方果然是很负责的,不仅是不稳定,而且足够慢。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,则表示当前的收据为沙盒环境下收据,需要调用https://sandbox.itunes.apple.com/verifyReceipt进行验证。
真假收据(上线)
解决了沙盒环境的问题后,历经三次终于通过了审核。但问题并没有因此结束,上线后,出现了大量支付失败的情况,这是始料未及的。虽然这些伪造收据均被我们的服务器识别出来,但是仍然遇到了一些麻烦:
1)由于国内越狱用户占比较大的比例,所以没有收据中有50%以上都是无效收据,但仍然需要去苹果服务器验证。
2)很多越狱用户都安装了iap free插件,对于这部分用户即便真心想购买会员的服务,但由于系统原有的IAP支付功能已经被破坏,也无法完成实际的支付。但部分越狱用户并不清楚这一点,上线后就收到用户的投诉,内容无非是我已经支付成功了,为什么没得到相应的服务。
正所谓知己知彼,百战不殆。所以有必要了解一下IAP破解插件的原理
IAP Cracker and IAP Free
IAP Cracker 原理
IAP Cracker之所以可以成功,是因为客户端收到app store server 返回的SKPaymentTransaction直接根据SKPaymentTransaction中的SKPaymentTransactionState来判断用户是否购买,而没有去验证收据。殊不知,IAP Cracker 能够模拟app store 返回的消息。
IAP Free 原理
有了 IAP Cracker 的经验教训,apple增加了receipt verify 流程,道高一尺魔高一丈,IAP Free应运而生。IAP Free基本原理:
1) 伪造成功的交易收据
2) 修改设备的DNS,将收据验证的服务器地址指向伪造的app store server地址。
通过IAP破解插件的原理,IAP破解插件主要利用了以下支付流程的漏洞:
验证流程的漏洞
1)仅仅根据app store 返回的交易状态SKPaymentTransactionState判断购买是否成功没有对收据进行验证。
2)客户端直接与app store进行交易收据的验证
验证收据的漏洞
仅仅根据receipt的状态 status为0判断收据的合法性。
通过上面的分析,我们知道了问题所在,下面就是解决问题
1)对于验证流程的漏洞,我们采用服务器模式,利用独立服务器验证交易收据
2)对于验证收据的漏洞,只要我们深入了解收据的结构就可以甄别出真假收据。
a.status=0
b.productid
c.purchase_date
d.expire_date
从以上四方面入手,基本就可以判断收据的真伪
3)通过对验证收据日志分析发现90%以上的伪造收据都是一样的。这样可以依此对收据进行过滤而不需要进行验证后方可发现收据的真伪。
收据的过滤可以是多维度的:
a. 根据productid
b. 根据transactionid,上线后发现很多伪造的收据transactionid构成中含有数字以外的其他字符。
c. 根据收据的唯一性
参考资料
1.http://www.dapps.net/dev/books/ios-dev-about-in-app-purchase.html
2.http://blog.csdn.net/lixuwen521/article/details/8103949
3.http://www.himigame.com/iphone-cocos2d/550.html
4.http://developer.apple.com/library/ios/#documentation/NetworkingInternet/Conceptual/StoreKitGuide/RenewableSubscriptions/RenewableSubscriptions.html
百度 iOS SDK支付:http://api.map.baidu.com/lbsapi/cloud/sdk-ios.htm