8.0 KiB
8.0 KiB
支付流程(多客户端通用)
1. 概述
本文档描述换皮应用可复用的支付全流程,覆盖:商品获取、支付方式选择、订单创建、平台内购回调、订单核销、补单与账户刷新。
文档以“能力与流程”表达,不绑定具体客户端项目、目录路径或某一语言实现。
2. 支付流程总览
用户点击充值 / Buy
│
├─ 已登录 且 开启第三方支付
│ │
│ ├─ 拉取支付方式(基于商品/活动)
│ ├─ 用户选择支付方式
│ ├─ 创建订单(服务端生成业务订单)
│ │
│ ├─ 若为平台内购(如 Google Play)
│ │ ├─ 调起商店购买
│ │ ├─ 获取 purchaseData + signature + storeOrderId
│ │ └─ 回调服务端校验与入账
│ │
│ └─ 若为外部支付
│ └─ 打开 payUrl 在 Web/外部浏览器完成支付
│
└─ 未登录 或 未开启第三方支付
└─ 可走平台内购直购分支(由业务策略决定)
3. 支付分支依据(通用)
| 条件 | 说明 |
|---|---|
| 是否登录 | 通常需要用户身份用于订单归属与回调入账 |
| 是否开启第三方支付 | 由服务端用户配置或渠道策略控制 |
| 当前平台能力 | Android / iOS 对内购与外部支付支持差异 |
| 商品配置 | 某些商品只允许特定支付方式 |
建议将分支判断集中在统一策略层,避免同一逻辑散落在多个页面。
4. 商品展示与获取
4.1 获取时机
- 进入充值页时拉取一次;
- 下拉刷新或切换国家/渠道后重新拉取;
- 支付成功后建议刷新,确保档位与余额展示一致。
4.2 商品字段(通用语义)
| 字段语义 | 说明 |
|---|---|
productId |
商店商品 ID(内购必填) |
activityId |
服务端活动/档位 ID(建单常用) |
actualAmount |
实付金额 |
originAmount |
原价(可用于划线价) |
bonus / bonusCredits |
赠送积分 |
credits |
到账积分(如与赠送分开展示) |
title |
商品文案(可能由服务端直接下发) |
5. 第三方支付流程(通用)
5.1 拉取支付方式
以商品或活动为上下文请求支付方式列表,常见字段包括:
paymentMethod:主支付方式(例如平台内购、钱包、卡支付等)subPaymentMethod:子方式(可选)name/icon:展示信息recommend:是否推荐
5.2 创建订单
创建订单请求通常包含(逻辑字段名):
- 应用标识(
app) - 用户标识(
userId) - 商品或活动标识(
activityId/productId) - 支付主方式(
paymentMethod) - 支付类型(
paymentType,按渠道语义填写) - 子支付方式(
subPaymentMethod,如卡种/钱包子通道)
关键点:
subPaymentMethod是独立语义字段。
仅传paymentType不会自动补出subPaymentMethod。
5.2.1 推荐入参组合(避免丢子支付方式)
- 卡支付场景(示例):
paymentMethod = MIFAPAYpaymentType = MIFAPAY(或按后端约定值)subPaymentMethod = CreditCard
- 若传成
paymentType = CreditCard且未传subPaymentMethod,常见结果是:- 有
paymentMethod - 有
paymentType - 缺少
subPaymentMethod
- 有
响应通常返回:
orderId(业务订单号)payUrl(外部支付链接;仅外部支付场景)status(订单状态)- 可选
federation(用于与商店订单映射)
5.3 分支执行
- 平台内购:拉起商店购买 -> 取回凭据 -> 回调服务端核验 -> 成功后完成/消费交易。
- 外部支付:打开
payUrl完成支付 -> 回前台后查询订单状态或拉取账户余额。
6. 平台内购标准链路(Android/iOS 可类比)
- 用
productId调起商店支付; - 拿到商店返回的交易凭据(如
purchaseData、signature、storeOrderId); - 调服务端回调接口完成验签与入账;
- 服务端成功后,客户端执行“完成交易/消费交易”(防止重复拥有问题);
- 刷新账户余额与订单状态。
关键原则:先服务端验单成功,再本地完成/消费交易,避免凭据丢失导致资产不一致。
7. 补单机制(订单恢复)
7.1 触发时机
- 应用启动后;
- 进入充值页时;
- 支付异常返回时(例如网络中断、回调超时)。
7.2 恢复流程
- 拉取未完成/未核销的商店订单(历史订单 + 监听流中的待处理订单);
- 对每笔订单尝试找到业务订单映射(如
federation/orderId); - 若可映射:再次走服务端回调核验,成功后完成/消费交易;
- 若不可映射:按产品策略处理(仅完成/消费以解除占用,或进入人工排查队列);
- 恢复结束后刷新账户与充值记录。
8. API 能力清单(通用命名)
| 能力 | 典型方法 | 说明 |
|---|---|---|
| 获取商品列表 | GET |
Android/iOS 可分端点 |
| 获取支付方式 | POST/GET |
入参通常含 activityId |
| 创建订单 | POST |
返回 orderId、payUrl 等 |
| 平台内购回调 | POST |
提交 purchaseData、signature 等 |
| 订单列表 | GET |
历史支付记录 |
| 订单详情 | GET |
查询单笔订单状态 |
9. 核心字段对照(通用)
| 业务含义 | 常见请求字段 | 常见响应字段 |
|---|---|---|
| 应用标识 | app |
- |
| 用户标识 | userId |
- |
| 活动/档位 | activityId |
- |
| 支付方式 | paymentMethod |
- |
| 子支付方式 | paymentType |
- |
| 订单标识 | orderId / id |
orderId |
| 购买签名 | signature |
- |
| 购买数据 | purchaseData |
- |
| 商品 ID | - | productId |
| 实付金额 | - | actualAmount |
| 原价 | - | originAmount |
| 赠送积分 | - | bonus / bonusCredits |
| 支付链接 | - | payUrl |
| 订单状态 | - | status |
10. 常见问题
10.1 商品未找到
- 现象:发起内购时提示商品不存在;
- 常见原因:客户端
productId与商店后台配置不一致,或商品未上架到当前测试轨道; - 排查建议:核对包名/应用 ID、商品 ID、地区、测试账号与轨道配置。
10.2 回调成功但积分未更新
- 现象:支付侧显示成功,账户余额未变;
- 常见原因:回调后未刷新账户、订单状态未落库、幂等冲突;
- 排查建议:检查回调响应、订单状态接口与账户刷新链路。
10.3 重复购买被拦截(已拥有此内容)
- 现象:商店提示已拥有,无法再次购买;
- 常见原因:上一笔交易未完成/未消费;
- 排查建议:执行补单恢复流程并确保完成/消费逻辑成功。
10.4 创建订单请求缺少子支付方式字段
- 现象:抓包中
createPayment入参有paymentMethod,但缺少subPaymentMethod; - 常见原因:只传了
paymentType,没有传subPaymentMethod; - 排查建议:
- 检查应用侧建单调用是否显式传入
subPaymentMethod; - 对照请求日志逐项核对三元组:
paymentMethod/paymentType/subPaymentMethod; - 若项目启用了字段映射,再额外确认映射配置与服务端契约一致。
- 检查应用侧建单调用是否显式传入
11. 实施建议(多客户端复用)
- 以“流程能力层”封装支付,不把分支逻辑写死在页面;
- 页面只关心:档位展示、用户选择、状态反馈;
- 建单、回调、补单、轮询统一由支付服务层负责;
- 统一错误码与文案映射,避免各端提示不一致;
- 对关键节点埋点:拉起支付、建单成功、回调成功、补单成功、入账成功;
- 保持接口字段可映射,支持不同换皮应用的字段命名差异。