docs: 新增微信参数配置管理和代理预充值功能总结文档

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
2026-03-16 23:30:56 +08:00
parent f3297f0529
commit 060d8fd65e
2 changed files with 466 additions and 0 deletions

View File

@@ -0,0 +1,227 @@
# 代理预充值功能
## 功能概述
代理商(店铺)余额钱包的在线充值系统,支持微信在线支付和线下转账两种充值方式,具备完整的 Service/Handler/回调处理链路。充值仅针对余额钱包(`wallet_type=main`),佣金钱包通过分佣自动入账。
### 背景与动机
原有 `tb_agent_recharge_record` 表和 Store 层骨架已存在,但缺少 Service 层和 Handler 层,无法通过 API 发起充值。本次补全完整实现,并集成至支付配置管理体系(按 `payment_config_id` 动态路由至微信直连或富友通道)。
## 核心流程
### 在线充值流程(微信)
```
代理/平台 → POST /api/admin/agent-recharges
├─ 验证权限:代理只能充自己店铺,平台可指定任意店铺
├─ 验证金额范围100 元~100 万元)
├─ 查找目标店铺的 main 钱包
├─ 查询 active 支付配置 → 无配置则拒绝(返回 1175
├─ 记录 payment_config_id
└─ 创建充值订单status=1 待支付)
└─ 返回订单信息(客户端支付发起【留桩】)
支付成功 → POST /api/callback/wechat-pay 或 /api/callback/fuiou-pay
├─ 按订单号前缀 "ARCH" 识别为代理充值
├─ 查询充值记录,取 payment_config_id
├─ 按配置验签
└─ agentRechargeService.HandlePaymentCallback()
├─ 幂等检查WHERE status = 1
├─ 更新充值记录状态 → 2已完成
├─ 代理主钱包余额增加(乐观锁防并发)
└─ 创建钱包流水记录
```
### 线下充值流程(仅平台)
```
平台 → POST /api/admin/agent-recharges
└─ payment_method = "offline"
└─ 创建充值订单status=1 待支付)
平台确认 → POST /api/admin/agent-recharges/:id/offline-pay
├─ 验证操作密码(二次鉴权)
└─ 事务内:
├─ 更新充值记录状态 → 2已完成
├─ 记录 paid_at、completed_at
├─ 代理主钱包余额增加(乐观锁 version 字段)
├─ 创建钱包流水记录
└─ 记录审计日志
```
## 接口说明
### 基础路径
`/api/admin/agent-recharges`
**权限要求**:企业账号(`user_type=4`)在路由层被拦截,返回 `1005`
### 接口列表
| 方法 | 路径 | 说明 | 权限 |
|------|------|------|------|
| POST | `/api/admin/agent-recharges` | 创建充值订单 | 代理(自己店铺)/ 平台(任意店铺)|
| GET | `/api/admin/agent-recharges` | 查询充值记录列表 | 代理(自己店铺)/ 平台(全部)|
| GET | `/api/admin/agent-recharges/:id` | 查询充值记录详情 | 代理(自己店铺)/ 平台(全部)|
| POST | `/api/admin/agent-recharges/:id/offline-pay` | 确认线下充值到账 | 仅平台 |
### 创建充值订单
**请求体示例(在线充值)**
```json
{
"shop_id": 101,
"amount": 50000,
"payment_method": "wechat"
}
```
**请求体示例(线下充值)**
```json
{
"shop_id": 101,
"amount": 200000,
"payment_method": "offline"
}
```
**请求字段**
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| shop_id | integer | 是 | 目标店铺 ID代理只能填自己所属店铺|
| amount | integer | 是 | 充值金额(单位:分),范围 10000~100000000 |
| payment_method | string | 是 | `wechat`(在线)/ `offline`(线下,仅平台)|
**成功响应**
```json
{
"code": 0,
"msg": "success",
"data": {
"id": 88,
"recharge_no": "ARCH20260316100001",
"shop_id": 101,
"amount": 50000,
"payment_method": "wechat",
"payment_channel": "wechat_direct",
"payment_config_id": 3,
"status": 1,
"created_at": "2026-03-16T10:00:00+08:00"
},
"timestamp": "2026-03-16T10:00:00+08:00"
}
```
### 线下充值确认
**请求体**
```json
{
"operation_password": "Abc123456"
}
```
操作密码验证通过后,事务内同步完成:余额到账 + 钱包流水 + 审计日志。
## 权限控制矩阵
| 操作 | 平台账号 | 代理账号 | 企业账号 |
|------|----------|----------|----------|
| 创建充值(在线) | ✅ 任意店铺 | ✅ 仅自己店铺 | ❌ |
| 创建充值(线下) | ✅ 任意店铺 | ❌ | ❌ |
| 线下充值确认 | ✅ | ❌ | ❌ |
| 查询充值列表 | ✅ 全部 | ✅ 仅自己店铺 | ❌ |
| 查询充值详情 | ✅ 全部 | ✅ 仅自己店铺 | ❌ |
**越权统一响应**:代理访问他人店铺充值记录时,返回 `1121 CodeRechargeNotFound`(不区分不存在与无权限)
## 数据模型
### `tb_agent_recharge_record` 新增字段
| 字段 | 类型 | 可空 | 说明 |
|------|------|------|------|
| `payment_config_id` | bigint | 是 | 关联支付配置 ID线下充值为 NULL在线充值记录实际使用的配置|
### 充值订单状态枚举
| 值 | 含义 |
|----|------|
| 1 | 待支付 |
| 2 | 已完成 |
| 3 | 已取消 |
### 支付方式与通道
| payment_method | payment_channel | 说明 |
|---------------|----------------|------|
| wechat | wechat_direct | 微信直连通道provider_type=wechat|
| wechat | fuyou | 富友通道provider_type=fuiou|
| offline | offline | 线下转账 |
> 前端统一显示"微信支付",后端根据生效配置的 `provider_type` 自动路由,前端不感知具体通道。
### 充值单号规则
前缀 `ARCH`,全局唯一,用于回调时识别订单类型。
## 幂等性设计
- 回调处理使用状态条件更新:`WHERE status = 1`
- `RowsAffected == 0` 时说明已被处理,直接返回成功,不重复入账
- 钱包余额更新使用乐观锁(`version` 字段),并发冲突时最多重试 3 次
## 审计日志
线下充值确认(`OfflinePay`)操作记录审计日志,字段包括:
| 字段 | 值 |
|------|-----|
| `operator_id` | 当前操作人 ID |
| `operation_type` | `offline_recharge` |
| `operation_desc` | `确认代理充值到账:充值单号 {recharge_no},金额 {amount} 分` |
| `before_data` | 操作前余额和充值记录状态 |
| `after_data` | 操作后余额和充值记录状态 |
## 涉及文件
### 新增文件
| 层级 | 文件 | 说明 |
|------|------|------|
| DTO | `internal/model/dto/agent_recharge_dto.go` | 请求/响应 DTO |
| Service | `internal/service/agent_recharge/service.go` | 充值业务逻辑 |
| Handler | `internal/handler/admin/agent_recharge.go` | 4 个 Handler 方法 |
| 路由 | `internal/routes/agent_recharge.go` | 路由注册 |
### 修改文件
| 文件 | 变更说明 |
|------|---------|
| `internal/model/agent_wallet.go` | 新增 `PaymentConfigID *uint` 字段 |
| `internal/handler/callback/payment.go` | 新增 "ARCH" 前缀分发 → agentRechargeService.HandlePaymentCallback() |
| `internal/bootstrap/` 系列 | 注册 AgentRechargeService、AgentRechargeHandler |
| `cmd/api/docs.go` / `cmd/gendocs/main.go` | 注册 AgentRechargeHandler |
| `migrations/000081_add_payment_config_id_to_agent_recharge.up.sql` | tb_agent_recharge_record 新增 payment_config_id 列 |
## 常量定义
```go
// pkg/constants/wallet.go
AgentRechargeOrderPrefix = "ARCH" // 充值单号前缀
AgentRechargeMinAmount = 10000 // 最小充值100 元(单位:分)
AgentRechargeMaxAmount = 100000000 // 最大充值100 万元(单位:分)
```
## 已知限制(留桩)
**客户端支付发起未实现**:在线充值(`payment_method=wechat`)创建订单成功后,前端获取支付参数的接口本次未实现。充值回调处理已完整实现——等支付发起改造完成后,完整的充值支付闭环即可联通。