6.7 KiB
6.7 KiB
支付流程文档
1. 概述
本文档描述 Android 项目(Flutter)的完整支付流程,包括商品获取、支付方式选择、订单创建、Google Play 内购以及补单机制。
2. 支付流程总览
用户点击 Buy
│
├─ enableThirdPartyPayment === true 且已登录
│ │
│ ├─ getPaymentMethods(activityId) 获取支付方式
│ ├─ 弹窗选择支付方式(_PaymentMethodDialog)
│ ├─ createPayment 创建订单
│ │
│ ├─ 若选中的是 Google Pay(resource/ceremony == "GooglePay")
│ │ ├─ 调起 Google Play 内购
│ │ ├─ 拿到 serverVerificationData
│ │ └─ POST /v1/payment/googlepay 回调验证
│ │
│ └─ 否则(其他支付方式)
│ └─ 打开 payUrl 在外部浏览器完成支付
│
└─ enableThirdPartyPayment !== true 或未登录
└─ 仅 Android:直接调起 Google Play 内购
3. 支付分支依据
| 条件 | 说明 |
|---|---|
UserState.enableThirdPartyPayment |
登录后由 AuthService 从 /v1/user/common_info 响应写入 |
UserState.userId |
用户登录后存储的用户 ID |
| 第三方支付 | enableThirdPartyPayment == true 且 userId 非空 |
| 直接谷歌支付 | 其他情况(未开第三方支付或未登录) |
4. 商品展示与获取
4.1 接口
- Android:
GET /v1/payment/getGooglePayActivities - iOS:
GET /v1/payment/getApplePayActivities
4.2 商品字段映射
| 字段(API) | 字段(客户端映射) | 说明 |
|---|---|---|
| helm | code / productId | Google Play 商品 ID |
| warrior | activityId | 活动 ID,用于创建订单 |
| guardian | actualAmount | 实际金额 |
| curriculum | originAmount | 原价(带划线) |
| forge | bonus | 赠送积分 |
| glossary | title | 标题 |
4.3 代码入口
文件:lib/features/recharge/recharge_screen.dart
_fetchActivities(): 获取商品列表_onBuy(): 用户点击购买入口
5. 第三方支付流程
5.1 步骤
-
获取支付方式:
POST /v1/payment/get-payment-methods- 参数:
warrior(activityId),vambrace(可选,国家)
- 参数:
-
弹窗选择: 展示支付方式列表(
_PaymentMethodSheet),包含:resource: 支付方式(如 GOOGLEPAY)ceremony: 子支付方式name: 显示名称icon: 图标 URLrecommend: 是否推荐
-
创建订单:
POST /v1/payment/createPayment- 参数:
sentinel,asset(userId),warrior(activityId),resource,ceremony - 返回:
federation(订单ID),convert(支付URL)
- 参数:
-
支付方式分支:
- Google Pay: 调用
GooglePlayPurchaseService.launchPurchaseAndReturnData()→ 调起内购 → 调用PaymentApi.googlepay()回调验证 - 其他方式: 使用
url_launcher打开convert支付链接
- Google Pay: 调用
5.2 代码位置
- 入口:
recharge_screen.dart→_runThirdPartyPayment() - 创建订单:
_createOrderAndOpenUrl() - Google Pay 判断:
_isGooglePay()
6. 直接谷歌支付流程
仅 Android,且不经过 getPaymentMethods 和 createPayment(三方支付关闭时):
- 调用
createPayment(resource=GooglePay, ceremony=GooglePay) - 调起 Google Play 内购
- 回调验证
代码位置
recharge_screen.dart→_runGooglePay()
7. Google Play 内购统一入口
7.1 核心方法
GooglePlayPurchaseService.launchPurchaseAndReturnData(productId)
- 调起 Google Play 内购
- 返回
GooglePayPurchaseResult包含:orderId: Google 订单号payload.purchaseData: purchaseData(用于 merchant)payload.signature: 签名(用于 sample)purchaseDetails: PurchaseDetails 对象
7.2 回调验证
PaymentApi.googlepay(sample, merchant, federation, asset)
sample: 签名merchant: purchaseDatafederation: 订单IDasset: userId
7.3 核销
GooglePlayPurchaseService.completeAndConsumePurchase(purchaseDetails)
- 执行
completePurchase - 执行
consumePurchase(Android)
8. 补单机制
8.1 触发时机
- 进入充值页时调用
GooglePlayPurchaseService.runOrderRecovery()
8.2 补单流程
-
获取未核销订单:
getUnacknowledgedPurchases()- 合并
queryPastPurchases和purchaseStream的待处理订单
- 合并
-
对每笔订单:
- 查询本地存储的
federation映射 - 若存在 federation: 调用
googlepay回调 → 成功后 consume - 若无 federation: 仅执行 consume 解除「已拥有此内容」
- 查询本地存储的
-
补单成功后刷新账户
8.3 存储映射
使用 SharedPreferences 存储 googleOrderId → federation 映射:
saveFederationForGoogleOrderId()getFederationForGoogleOrderId()removeFederationForGoogleOrderId()
9. API 汇总
| 接口 | 方法 | 说明 |
|---|---|---|
/v1/payment/getGooglePayActivities |
GET | 获取 Android 商品列表 |
/v1/payment/getApplePayActivities |
GET | 获取 iOS 商品列表 |
/v1/payment/get-payment-methods |
POST | 获取支付方式列表 |
/v1/payment/createPayment |
POST | 创建支付订单 |
/v1/payment/getOrderDetail |
GET | 查询订单状态(轮询) |
/v1/payment/googlepay |
POST | Google Pay 回调验证 |
10. 代码文件位置
| 功能 | 文件路径 |
|---|---|
| 充值页面 | lib/features/recharge/recharge_screen.dart |
| 支付 API | lib/core/api/services/payment_api.dart |
| Google Play 内购服务 | lib/features/recharge/google_play_purchase_service.dart |
| 支付方式模型 | lib/features/recharge/models/payment_method_item.dart |
| 商品模型 | lib/features/recharge/models/activity_item.dart |
| 购买结果模型 | lib/features/recharge/models/google_pay_purchase_result.dart |
| WebView 支付页 | lib/features/recharge/payment_webview_screen.dart |
11. 常见问题
11.1 商品未找到
- 原因: 客户端
helm(productId) 与 Google Play 后台「产品 ID」不一致 - 排查: 检查
docs/google_pay_product_not_found.md
11.2 补单
- 未确认订单可能不会出现在
queryPastPurchases中 - 应用启动时订阅
purchaseStream接收重新下发 - 补单会合并两者的待处理订单
12. 注意事项
- 所有 Google Play 内购统一使用
launchPurchaseAndReturnData()方法 - 回调验证成功后必须调用
completePurchase+consumePurchase - 支付 URL 打开方式取决于
createPayment返回的convert字段 - 订单状态轮询: 间隔 1/3/7/15/31/63 秒