Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
7.6 KiB
7.6 KiB
代理预充值功能
功能概述
代理商(店铺)余额钱包的在线充值系统,支持微信在线支付和线下转账两种充值方式,具备完整的 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 |
确认线下充值到账 | 仅平台 |
创建充值订单
请求体示例(在线充值)
{
"shop_id": 101,
"amount": 50000,
"payment_method": "wechat"
}
请求体示例(线下充值)
{
"shop_id": 101,
"amount": 200000,
"payment_method": "offline"
}
请求字段
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| shop_id | integer | 是 | 目标店铺 ID(代理只能填自己所属店铺) |
| amount | integer | 是 | 充值金额(单位:分),范围 10000~100000000 |
| payment_method | string | 是 | wechat(在线)/ offline(线下,仅平台) |
成功响应
{
"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"
}
线下充值确认
请求体
{
"operation_password": "Abc123456"
}
操作密码验证通过后,事务内同步完成:余额到账 + 钱包流水 + 审计日志。
权限控制矩阵
| 操作 | 平台账号 | 代理账号 | 企业账号 |
|---|---|---|---|
| 创建充值(在线) | ✅ 任意店铺 | ✅ 仅自己店铺 | ❌ |
| 创建充值(线下) | ✅ 任意店铺 | ❌ | ❌ |
| 线下充值确认 | ✅ | ❌ | ❌ |
| 查询充值列表 | ✅ 全部 | ✅ 仅自己店铺 | ❌ |
| 查询充值详情 | ✅ 全部 | ✅ 仅自己店铺 | ❌ |
越权统一响应:代理访问他人店铺充值记录时,返回 1121 CodeRechargeNotFound(不区分不存在与无权限)
数据模型
tb_agent_recharge_record 新增字段
| 字段 | 类型 | 可空 | 说明 |
|---|---|---|---|
payment_config_id |
bigint | 是 | 关联支付配置 ID(线下充值为 NULL,在线充值记录实际使用的配置) |
充值订单状态枚举
| 值 | 含义 |
|---|---|
| 1 | 待支付 |
| 2 | 已完成 |
| 3 | 已取消 |
支付方式与通道
| payment_method | payment_channel | 说明 |
|---|---|---|
| wechat_direct | 微信直连通道(provider_type=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 列 |
常量定义
// pkg/constants/wallet.go
AgentRechargeOrderPrefix = "ARCH" // 充值单号前缀
AgentRechargeMinAmount = 10000 // 最小充值:100 元(单位:分)
AgentRechargeMaxAmount = 100000000 // 最大充值:100 万元(单位:分)
已知限制(留桩)
客户端支付发起未实现:在线充值(payment_method=wechat)创建订单成功后,前端获取支付参数的接口本次未实现。充值回调处理已完整实现——等支付发起改造完成后,完整的充值支付闭环即可联通。