适合 GP 和 App Store 的内购系统¶
为什么要构建自己的订单系统¶
以 ios app-store 为例来说明必要性。
支付流程¶
- 客户端向Appstore请求购买产品(假设产品信息已经取得),Appstore验证产品成功后,从用户的Apple账户余额中扣费。
- Appstore向客户端返回一段receipt-data,里面记录了本次交易的证书和签名信息。
- 客户端向我们可以信任的服务器提供receipt-data
- 服务器对receipt-data进行一次base64编码
- 把编码后的receipt-data发往itunes.appstore进行验证
- itunes.appstore返回验证结果给服务器
- 服务器对商品购买状态以及商品类型,向客户端发放相应的道具与推送数据更新通知
两个常规问题¶
一、重复验证收据¶
客户端由于网络不稳定或者恶意而会重复验证同一个收据,如果没有自己的订单系统,则会导致服务端重复发送奖励
二、漏单¶
客户端由于网络不稳定,付款成功了,没有把收据发给服务端,会导致用户损失奖励,并且会向客服投诉,如果没有自己的订单系统,则会无法定位用户这笔交易的信息,无法补发奖励
总结¶
我们必须有一个自建的订单系统,并且能够涵盖一笔交易的整个生命周期。
用户购买主流程分析¶
后端验证
sequenceDiagram
participant C as 客户端
participant S as 游戏服
participant AG as Apple/Google
Note left of C: 检查配置
C->>+S: 请求生成订单
S->>-C: 返回订单ID
Note left of C: 缓存订单ID,调用支付SDK
C->>+AG: 付款
AG->>-C: 返回收据🧾
Note left of C: 付款失败需要请求游戏服关闭订单
C->>+S: 验证订单: 订单ID和收据
S-->>+AG: 验证订单
Note right of S: 信任的用户异步验证,不信任用户同步验证
AG-->>-S: 注意防止重复收据
S->>-C: 返回该订单包含的奖励
Note left of C: 不管是否验证通过,都需要消耗订单,防止阻塞后续付款
C->>AG: 消耗订单
C->>+S: 请求发货
S->>-C: 发货并完成订单
订单状态机¶
stateDiagram-v2
Pending --> Verified
note right of Verified: 已经付款.
Verified --> Finished
note right of Finished: 已经发货.
Pending --> Closed
note right of Closed: 用户没有付款.
信任机制¶
- 初始化状态:IOS用户信任,安卓用户不信任
- 信任->不信任:出现一笔无效或者重复的收据
- 不信任->信任:连续验证成功3笔订单
自动补救流程¶
- 客户端登录时异步获取Verified状态的订单列表(用户瞎JB操作或者网络不佳或者客户端崩溃或者服务端错误导致)
- Finish订单
详细错误分析¶
- 配置错误:策划紧急修复配置
- 生成订单错误,客户端重试即可
- 付款错误(不包含用户主动取消):对客户端来说只能等待
- 验证收据错误
- 客户端丢失订单ID,记录足够的信息,运营处理
- 第三方临时错误,IOS信任,依旧验证通过,Android抛错,客户端稍后重试
- 客户端网络错误,重试即可
- 订单状态错误,关闭/消耗该订单
- 收据重复使用,关闭/消耗该订单
- 无效的收据(可能是作弊),关闭/消耗该订单
- 消耗订单错误,重新验证即可
特殊情况分析¶
- 客户端拿不到订单ID的情况;玩家必须删包或者清缓存才会出现,交由运营处理,否则后续细节太多
- 单设备多账户的情况;A用户购买,未验证,B用户又在这台设备登录,按照客户端流程,B用户也会收到支付回调,但是需求上B用户不能Finish这笔订单,同时又不能阻塞B用户的接下来的付款,所以B用户必须验证并消耗这笔订单,这样就如同A用户验证了一样(未Finish),然后B用户不回被阻塞,A用户重新上线之后走补救流程即可。