内购漏单
有一说一,苹果内购真的很坑。
苹果内购和国内大部分第三方支付的最大不同,就是它是由客户端去驱动服务器或本地校验支付结果,而移动端网络情况复杂,再加上苹果的机制本身就设计的很不方便开发者,还有苹果的 iap 服务器不在国内,导致很多时候,iap 的校验延迟或很久都不能成功.
关于 iap 服务器,可以在下面这里查询状态:
上面的几个原因,造成了苹果内购的漏单问题。
几种内购处理方案
先服务器创建订单,再本地或服务器校验
先本地或服务器校验,再服务器创建订单
上面这两种方案,下面还可细分两种方案:
依赖 iap 的机制
不依赖 iap 的机制
解释一下,依赖和不依赖,主要说的就是 finishTransaction 的时机,事实上,苹果有个专门的 iap 队列用来管理内购交易事物,所以所谓依赖,就是到底要不要依赖于苹果提供的这个机制。
具体如何抉择,看场景,看需求,无论那种方案,都不能保证万无一失。
一些奇怪的坑
真实的支付环境中,如果用户 apple id 没有绑定银行卡等支付方式,会导致第一次确认付款的时候,代理回调到交易 fail 状态,而事实上,等用户绑定完了,跳转回来还可以能继续支付。
沙盒测试的时候,如果操作系统是未在 app store 里提供沙盒登录选项的版本,有可能会触发两次登录,都需要输入密码,但是我用 iOS14 之后的系统测试了一下,没有这个问题,不过,最好还是在设置的 app store 中提前登录好。
在某些情况下,可能会出现凭证没有及时刷新。
如何解决
一定要自己做订单的本地存储,并将订单和苹果的交易信息做绑定和映射,不要完全信赖苹果的 iap 机制,存储方案,简单说,就是在发生购买之前,开始存储,直到购买并校验成功,,再从漏单列表移除订单。
在应用启动时,检查漏单列表,自动校验未校验成功的订单。
最好在失败的时候,手动 finishTransaction ,可以避免一些不必要的麻烦,尤其是服务器端开发人员没那么配合的时候。
关于得到交易成功的回调后,要不要第一时间 finishTransaction,这个见仁见智。
但必须承认,以上所有方案都是在尽量避免和弥补漏单的发生,在苹果没有修改或优化内购架构的情况下,好像还没有万无一失的方案。
好用的第三方
经过寻找,SwiftyStoreKit 是一个挺不错的内购第三方,如果想偷个懒,可以使用这个第三方来处理内购。