最近面试过程中,被面试官多次问到苹果内购相关的实现及遇到的问题,这里梳理以下,做个总结吧。
内购关键流程
1、客户端发起支付
2、客户端监听购买流程
3、苹果回调订单购买成功时,客户端把苹果给的receipt_data和一些订单信息上报给服务器
4、服务器拿到receipt_data向苹果服务器校验
5、苹果服务器返回status为0则表示发回成功
其他返回值也记录总结一下
21000 :App Store无法读取你提供的JSON数据
21002 :收据数据不符合格式
21003 :收据无法被验证
21004 :你提供的共享密钥和账户的共享密钥不一致
21005 :收据服务器当前不可用
21006 :收据是有效的,但订阅服务已经过期。当收到这个信息时,解码后的收据信息也包含在返回内容中
21007 :收据信息是测试用(sandbox),但却被发送到产品环境中验证
21008 :收据信息是产品环境中使用,但却被发送到测试环境中验证
6、服务器监发现订单校验成功之后,把该笔订单存起来,保存到数据库,可以防止同一笔订单多次发放商品
遇到的问题
1、丢单
2、双重验证
3、多次发放商品
解决方案
丢单问题大多分两种: 1、没有拿到凭证,支付成功,由于网络原因或各种原因没有返回transaction;
可以去查询苹果默认的[SKPaymentQueue defaultQueue]队列里面查询订单状态
2、支付成功后,拿到receipt凭证,上传服务器由于网络原因丢失
可以在支付之前让服务器创建订单,并把交易成功之后的交易凭证和订单保持数据库,用户下次登录之后验证
做双重验证的目的:
我们平时测试以及苹果审核的时候都要用沙盒账号测试,如何识别App端发过来的收据是沙盒测试还是正式环境用户的购买呢?这里可以用两种方案,即双重验证。
先把收据拿到正式环境的验证地址去验证,如果苹果的正式环境验证服务器返回的状态码 status 为 21007,说明当前收据是沙盒环境下产生,则再连接一次沙盒环境服务器进行验证,这样不管是我们自己采用沙盒账号测试还是苹果审核人员采用沙盒账号进行审核、或者用户购买都可以保证收据正常的验证成功。
判重方案解决多次发放商品:收到客户端上报的 transaction_id 后,直接MD5后去数据库查,能查到说明是重复订单,返回相应错误码给客户端,如果查不到,去苹果那边校验。服务器拿到苹果的校验结果之后,判断订单状态是不是成功,如果成功再发放内购商品。