国内安卓一般会接入支付宝或微信的 SDK 来拉起付费。苹果和海外安卓一样,大多数情况下虚拟物品和服务只能走系统的渠道, 也就是苹果的 App Store 和谷歌的 Google Play 来支付。两者都是和系统服务集成的,用户付款给苹果和谷歌, 再由其扣除税款后定期打到开发者的账户中。

本文简单总结接入时容易碰到的误区和阻碍,以供参考。

注:如果未指明是苹果或谷歌,则说明两者情况一致,均适用于说明。

开发者账户

在注册开发者账户时需要通过身份验证,将账户类型区分为个人和组织。组织一般就是企业。

对内购的影响在于付款资料,也就是给你打钱的银行账户,虽然目前没有限制,但最好与业务主体相一致。 因为国内银行接受海外跨国汇款,可能会向你要求相关的证明材料,平台会在你注册或开启付款时完成这些协议签订, 签订对象就是账户的注册方。

如果你的收款账户与协议签订人不一致,就可能需要授权书等一系列麻烦的证明。

另外,目前(2024 年 9 月)对于小企业的服务费都降低到了 15%,谷歌是自动开启,苹果需要在网页上申请一下。

内购类型

简单来说,如果购买的产品和服务是通过设备提供的,就必须走内购。具体政策可以看官网,但基本囊括了绝大部分虚拟商品, 各种会员,使用限制和游戏道具等都在其中。

内购按是否会周期性定期扣款分为订阅和一次性购买。月会员年会员这种就属于订阅,到期后如果没有取消就会自动扣款开启下一期, 一般要求能持续性的提供服务,否则不好过审核。

一次性购买就是用户的确认只产生一次付款,分为可重复购买和不可重复购买(又称为可消耗和非消耗性)两种。 高级功能的买断式解锁就是前者,游戏里可以消耗的道具则是后者。

接入前的设置

写代码之前,需要先在开发者后台完成应用内商品,以及测试账户相关的配置。

拉起购买时,需要从应用商店读取内购商品信息,因此要先去添加。一般会有延迟,添加后如果获取不到,可能需要等待几个小时。 苹果可以在 Xcode 中设置一个内购配置文件,能用来拉起支付验证的弹框,检测这个流程是否接入正确。但无法正常支付,因为没有连接到 App Store。

苹果的测试账户叫测试员,是添加一个没有注册过 Apple ID 的假账户,符合邮箱格式即可。 在真机的设置中,找到 App Store,里面有个沙盒账户的选项,用测试账户登录后,调试签名的 App 拉起支付就在测试环境了。

谷歌则需要真实的用户,将其添加到内测人员中,然后在封闭内测渠道中发布并审核通过一个版本。 这个版本可以没有支付相关的逻辑,但是必须要引入 Billing 依赖。 过审后用测试账户登录的 Google Play 下载内测渠道的应用,然后再插上电脑继续开发。 这时拉起支付时会忽略签名错误的异常,而是在弹出的支付界面中显示测试卡。

这一步中可能需要参考官方文档和大量的分享笔记,如果确认配置没有问题,但依然无法拉起支付,很有可能是配置数据没有更新, 建议等几个小时或者第二天再试。

开发测试

测试环境或沙盒环境的内购都是虚拟的,不会真正付款,所以可以放心的使用。

每次确认付款都会生成一笔订单。在触发后不一定立刻成功,所以都采用了回调的方式来处理。 回调结果有成功,失败,用户取消,验证失败,处理中,已恢复等状态。

其中处理中,也就是 Pending 状态,意味着还需要等待。在苹果上可能是用户没有同意 App Store 付款协议, 或者开启了家长控制,正在进行购买前询问。在谷歌则可能是信用卡扣款比较缓慢,需要等待银行的反馈。 不论是哪一种,最好都给用户明确的提示,告知可在商店中查询订单状态,以减少用户的不安。

除了正常的成功检查,还要注意退款的场景。交易的状态会随之发生变化, 用户付款后发放商品,检测到退款后同样要收回。这一点上苹果的交易记录查询 API 挺好,可以在设备上查询到实时变化, 但谷歌则一直无法查询到退款,即使卸载 App 后重新安装,或者清缓存重启都不行。

所以为了安全和稳妥,还是要有个后端来记录一下订单。

服务端验证

虽然在客户端就可以判断交易的结果,但如果用户 ROOT 了系统,这个结果就不那么可靠了。

谷歌官方文档上也认为,订单的状态更新应该放在安全的环境中,也就是服务端来更新。

处理流程为:

  1. 订单回调成功后,发送订单唯一编号(苹果是 transcationId,谷歌是 purchaseToken)到服务端
  2. 服务端向平台的订单查询接口进行查询,根据返回的结果保存订单状态。
  3. 客户端查询该订单状态,服务端返回当前结果。
  4. 服务端还要接受平台的回调通知,当退款等情况发生时,更新订单状态。

总之就是要自己维护订单状态,不相信客户端的返回结果,状态更新一律通过平台的查询接口或通知。

其中与平台的接口沟通需要验证凭据,就是一个生成的密钥。 后续在服务端验证订单时,向苹果或谷歌服务器发送的查询请求需要用此签名,验证回调数据时也用它。 两个平台都选择了 JWT 的形式,各主流语言都有封装好的库,传一下密钥文件就能直接用了。

苹果可以在后台直接生成,谷歌稍微麻烦一点,这部分要在 GCP 上配合完成,大概流程为:

  • GCP 新建项目,开启 Google Play Android Developer API
  • 在该项目上创建服务账号,创建密钥,并下载密钥文件
  • 在 GP 控制台的 用户和数据 中邀请新用户,即上一步中的服务账号
  • 该用户会自动加入,给他添加财务数据下的两个权限

有的教程中会出现让你到 API 权限 页面进行服务账号的绑定,目前控制台已经没有这个菜单项,也不需要绑定了。

订单号上报的接口,以及监听回调的接口,都可以在正常状况下只返回一个空 200,而非返回验证结果,防止被猜解。

其他

碎碎念几句,纯本地的 App 在安全方面其实不用特别下力气,因为总是能够被破解。

所有的东西都在本地,因此都可以被分析调试出来。就算你的支付验证在云端,也可以拦截后修改你的返回结果。 再进一步,返回结果也加密了,但由于解密也是在本地的,所以还是个时间和成本的问题,并没有本质的改变。

所以不要想完全的避免破解,而是要尽可能让其的成本扩大,以至于不可延续,还不如直接购买。 接受一点点损失,把精力放在更好的产品上吧。