代理在线充值
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 8m6s

This commit is contained in:
2026-07-27 16:02:55 +08:00
parent a2166c8011
commit cbf909b878
42 changed files with 3121 additions and 195 deletions

View File

@@ -490,6 +490,91 @@ components:
description: 总记录数
type: integer
type: object
DtoAgentRechargeOnlineResponse:
properties:
amount:
description: 在线充值金额范围10000分~100000000分
type: integer
payment_method:
description: 支付方式 (wechat:微信, alipay:支付宝)
type: string
payment_no:
description: 支付单号PAY前缀
type: string
qr_content:
description: 支付渠道原始扫码付款内容,由前端渲染二维码
type: string
recharge_id:
description: 充值记录ID
minimum: 0
type: integer
recharge_no:
description: 充值单号ARCH前缀
type: string
recharge_source:
description: 充值来源 (agent_online:代理在线自充)
type: string
recharge_source_name:
description: 充值来源名称(中文)
type: string
status:
description: 状态 (1:待支付, 2:已支付, 3:已完成, 4:已关闭, 5:已退款, 6:已驳回)
type: integer
status_name:
description: 状态名称(中文)
type: string
type: object
DtoAgentRechargePaymentMethodsResponse:
properties:
max_amount:
description: 在线充值最大金额固定为100000000
type: integer
methods:
description: 可用支付方式,固定顺序 (wechat:微信, alipay:支付宝)
items:
type: string
nullable: true
type: array
min_amount:
description: 在线充值最小金额固定为10000
type: integer
type: object
DtoAgentRechargePaymentStatusResponse:
properties:
completed_at:
description: 钱包入账完成时间
nullable: true
type: string
paid_at:
description: 第三方支付确认时间
nullable: true
type: string
payment_status:
description: 支付状态 (0:待支付, 1:已支付, 2:已失败, 3:已退款)
type: integer
payment_status_name:
description: 支付状态名称(中文)
type: string
recharge_id:
description: 充值记录ID
minimum: 0
type: integer
recharge_no:
description: 充值单号ARCH前缀
type: string
recharge_source:
description: 充值来源 (platform_offline:平台线下代充, agent_online:代理在线自充)
type: string
recharge_source_name:
description: 充值来源名称(中文)
type: string
status:
description: 充值状态 (1:待支付, 2:已支付, 3:已完成, 4:已关闭, 5:已退款, 6:已驳回)
type: integer
status_name:
description: 充值状态名称(中文)
type: string
type: object
DtoAgentRechargeRejectParams:
properties:
rejection_reason:
@@ -546,7 +631,7 @@ components:
nullable: true
type: integer
payment_method:
description: 支付方式 (wechat:微信在线支付, offline:线下转账)
description: 支付方式 (wechat:微信在线支付, alipay:支付宝在线支付, offline:线下转账)
type: string
payment_transaction_id:
description: 第三方支付流水号
@@ -560,6 +645,12 @@ components:
recharge_no:
description: 充值单号(ARCH前缀)
type: string
recharge_source:
description: 充值来源 (platform_offline:平台线下代充, agent_online:代理在线自充)
type: string
recharge_source_name:
description: 充值来源名称(中文)
type: string
rejection_reason:
description: 驳回原因,仅 status=6 时有值
nullable: true
@@ -3580,7 +3671,7 @@ components:
minimum: 1
type: integer
payment_method:
description: 支付方式 (wechat:微信在线支付, offline:线下转账仅平台可用)
description: 支付方式 (wechat:微信在线支付, alipay:支付宝在线支付, offline:线下转账仅平台可用)
type: string
payment_voucher_key:
description: 支付凭证对象存储Key列表payment_method=offline 时至少1个最多5个微信支付时忽略
@@ -3593,12 +3684,16 @@ components:
description: 运营备注(可选,创建后只读)
maxLength: 1000
type: string
request_id:
description: 在线充值幂等请求标识,微信或支付宝支付时必填
maxLength: 64
type: string
shop_id:
description: 目标店铺ID代理只能填自己店铺
description: 目标店铺ID仅平台线下代充可填;代理在线充值禁止传入
minimum: 0
nullable: true
type: integer
required:
- shop_id
- amount
- payment_method
type: object
@@ -12194,6 +12289,12 @@ paths:
description: 按状态过滤 (1:待支付, 2:已支付, 3:已完成, 4:已关闭, 5:已退款, 6:已驳回)
nullable: true
type: integer
- description: 按充值来源过滤 (platform_offline:平台线下代充, agent_online:代理在线自充)
in: query
name: recharge_source
schema:
description: 按充值来源过滤 (platform_offline:平台线下代充, agent_online:代理在线自充)
type: string
- description: 创建时间起始日期(YYYY-MM-DD)
in: query
name: start_date
@@ -12279,7 +12380,7 @@ paths:
example: 0
type: integer
data:
$ref: '#/components/schemas/DtoAgentRechargeResponse'
$ref: '#/components/schemas/DtoAgentRechargeOnlineResponse'
msg:
description: 响应消息
example: success
@@ -12463,6 +12564,73 @@ paths:
summary: 确认线下充值
tags:
- 代理预充值
/api/admin/agent-recharges/{id}/payment-status:
get:
parameters:
- description: ID
in: path
name: id
required: true
schema:
description: ID
minimum: 0
type: integer
responses:
"200":
content:
application/json:
schema:
properties:
code:
description: 响应码
example: 0
type: integer
data:
$ref: '#/components/schemas/DtoAgentRechargePaymentStatusResponse'
msg:
description: 响应消息
example: success
type: string
timestamp:
description: 时间戳
format: date-time
type: string
required:
- code
- msg
- data
- timestamp
type: object
description: 成功
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: 请求参数错误
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: 未认证或认证已过期
"403":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: 无权访问
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: 服务器内部错误
security:
- BearerAuth: []
summary: 查询代理充值本地支付与到账状态
tags:
- 代理预充值
/api/admin/agent-recharges/{id}/reject:
post:
parameters:
@@ -12509,6 +12677,64 @@ paths:
summary: 驳回代理充值订单
tags:
- 代理预充值
/api/admin/agent-recharges/payment-methods:
get:
responses:
"200":
content:
application/json:
schema:
properties:
code:
description: 响应码
example: 0
type: integer
data:
$ref: '#/components/schemas/DtoAgentRechargePaymentMethodsResponse'
msg:
description: 响应消息
example: success
type: string
timestamp:
description: 时间戳
format: date-time
type: string
required:
- code
- msg
- data
- timestamp
type: object
description: 成功
"400":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: 请求参数错误
"401":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: 未认证或认证已过期
"403":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: 无权访问
"500":
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
description: 服务器内部错误
security:
- BearerAuth: []
summary: 查询代理在线充值可用支付方式
tags:
- 代理预充值
/api/admin/asset-allocation-records:
get:
parameters:

View File

@@ -0,0 +1,327 @@
# 代理钱包扫码充值实现与接口对接说明
> 面向:产品、前端和联调人员
> 范围:代理微信/支付宝桌面扫码自充、平台线下代充来源区分、支付状态轮询
> 接口细节:以 [`docs/admin-openapi.yaml`](../../admin-openapi.yaml) 为准,本文说明前端调用顺序、字段口径和页面状态。
## 一、先看这几个关键结论
1. **同一个创建接口有两条业务路径**:代理账号使用 `wechat|alipay` 在线自充;平台或超级管理员使用 `offline` 线下代充。
2. **前端必须使用 `recharge_source` 区分来源**`platform_offline` 是平台线下代充,`agent_online` 是代理在线自充;不要根据账号名称、备注或审批字段猜测。
3. **代理不能选择充值店铺**:在线充值的店铺和主钱包由登录上下文确定,请求不得发送 `shop_id`、支付凭证或备注。
4. **二维码由前端渲染**:后端返回支付渠道原始 `qr_content`,不返回二维码图片。
5. **网络重试不能创建新请求 ID**:同一次提交重试复用原 `request_id`;用户主动发起下一笔充值时生成新的 `request_id`
6. **支付和钱包到账是两个阶段**`status=2` 表示第三方已收款、钱包入账处理中;只有 `status=3` 才表示钱包到账完成。
7. **页面轮询只调用本地状态接口**:前端不得直接调用微信、支付宝查单,也不要反复调用创建接口查询状态。
8. **在线金额单位为分**:最低 `10000`100 元),最高 `100000000`100 万元);不要提交浮点元金额。
## 二、本次需求怎么实现
| 能力 | 后端实现 | 前端要做什么 |
| --- | --- | --- |
| 可用支付方式 | 根据当前有效支付配置返回真正可用的 `wechat``alipay` | 打开充值弹窗时先查询;只展示返回数组中的方式 |
| 代理在线自充 | 从登录账号取得当前店铺和主钱包,创建充值单、支付单并向第三方预下单 | 只提交金额、支付方式和请求 ID`qr_content` 渲染二维码 |
| 平台线下代充 | 保留既有目标店铺、凭证和企业微信审批流程 | 平台页面继续提交 `offline` 请求并只读展示审批状态 |
| 充值来源 | 根据受控创建方式返回稳定来源枚举 | 列表、详情和支付状态统一展示 `recharge_source_name` |
| 支付确认 | 微信/支付宝回调确认第三方收款事实 | 前端无需调用回调接口 |
| 钱包入账 | Outbox/Worker 幂等增加代理主钱包余额 | `status=2` 展示“入账处理中”,`status=3` 展示“已到账” |
| 回调丢失恢复 | Worker 使用原支付单号主动查单并收敛状态 | 页面继续轮询本地状态,无需提供“重新查单”按钮 |
## 三、接口对接表
| 页面动作 | 接口 | 前端调用说明 |
| --- | --- | --- |
| 打开代理在线充值弹窗 | `GET /api/admin/agent-recharges/payment-methods` | 仅代理账号调用;返回支付方式和金额上下限 |
| 创建在线扫码充值 | `POST /api/admin/agent-recharges` | 代理只传 `amount + payment_method + request_id` |
| 创建平台线下代充 | `POST /api/admin/agent-recharges` | 平台/超级管理员传 `shop_id + amount + payment_method=offline + payment_voucher_key + remark` |
| 查询充值列表 | `GET /api/admin/agent-recharges` | 支持 `recharge_source=platform_offline|agent_online` 筛选 |
| 查询充值详情 | `GET /api/admin/agent-recharges/:id` | 使用返回的来源、充值状态和审批状态展示 |
| 轮询在线支付状态 | `GET /api/admin/agent-recharges/:id/payment-status` | 仅在线单使用;页面可见时每 3 秒调用,终态停止 |
| 支付回调 | 微信/支付宝既有回调地址 | 只由支付渠道调用,前端禁止调用 |
所有接口都使用 Bearer Token成功响应统一为
```json
{
"code": 0,
"msg": "success",
"data": {},
"timestamp": "2026-07-27T16:00:00+08:00"
}
```
前端应同时检查 HTTP 状态和响应体 `code`,失败时优先展示后端返回的 `msg`
## 四、代理在线扫码充值调用流程
### 4.1 查询可用支付方式
```http
GET /api/admin/agent-recharges/payment-methods
Authorization: Bearer {token}
```
响应示例:
```json
{
"code": 0,
"msg": "success",
"data": {
"methods": ["wechat", "alipay"],
"min_amount": 10000,
"max_amount": 100000000
},
"timestamp": "2026-07-27T16:00:00+08:00"
}
```
前端处理规则:
- `methods=[]`:隐藏或禁用提交按钮,提示“当前暂无可用在线支付方式”。
- 只显示返回的支付方式,不自行补充微信或支付宝。
- 金额校验直接使用返回的 `min_amount``max_amount`,提交值仍为整数分。
- 平台、超级管理员和企业账号不调用此接口。
### 4.2 创建在线充值单
```http
POST /api/admin/agent-recharges
Authorization: Bearer {token}
Content-Type: application/json
```
微信请求示例:
```json
{
"amount": 10000,
"payment_method": "wechat",
"request_id": "recharge-20260727-8f73d95d"
}
```
支付宝只需将 `payment_method` 改为 `alipay`
在线请求禁止发送:
- `shop_id`
- `payment_voucher_key`
- `remark`
- 商户号、应用 ID、密钥、支付配置 ID
成功响应示例:
```json
{
"code": 0,
"msg": "success",
"data": {
"recharge_id": 101,
"recharge_no": "ARCH20260727160000123456",
"payment_no": "PAY20260727160000987654",
"payment_method": "wechat",
"recharge_source": "agent_online",
"recharge_source_name": "代理在线自充",
"amount": 10000,
"qr_content": "weixin://wxpay/bizpayurl?pr=...",
"status": 1,
"status_name": "待支付"
},
"timestamp": "2026-07-27T16:00:00+08:00"
}
```
前端处理规则:
1.`qr_content` 原样交给二维码组件,不解析、不改写、不拼接。
2. 二维码页面保存 `recharge_id`,后续轮询使用该 ID不使用 `payment_no` 查询。
3. 同一次请求超时或网络断开时,重试必须复用原 `request_id`;后端会返回原充值单和原二维码内容。
4. 用户关闭弹窗后重新点击“立即充值”,视为新一笔主动提交,必须生成新的 `request_id`
5. 相同 `request_id` 改变金额或支付方式会返回冲突,前端不得自动覆盖原请求。
### 4.3 轮询支付和到账状态
```http
GET /api/admin/agent-recharges/101/payment-status
Authorization: Bearer {token}
```
响应示例:
```json
{
"code": 0,
"msg": "success",
"data": {
"recharge_id": 101,
"recharge_no": "ARCH20260727160000123456",
"recharge_source": "agent_online",
"recharge_source_name": "代理在线自充",
"status": 2,
"status_name": "已支付",
"payment_status": 1,
"payment_status_name": "已支付",
"paid_at": "2026-07-27 16:01:20",
"completed_at": null
},
"timestamp": "2026-07-27T16:01:21+08:00"
}
```
页面建议每 3 秒轮询一次,仅在二维码弹窗可见时执行。按以下状态展示:
| `status` | 含义 | 页面展示 | 是否继续轮询 |
| --- | --- | --- | --- |
| `1` | 待支付 | 等待用户扫码付款 | 是 |
| `2` | 已支付 | 支付成功,钱包入账处理中 | 是 |
| `3` | 已完成 | 充值成功,钱包已到账 | 否 |
| `4` | 已关闭 | 订单已关闭,请重新发起充值 | 否 |
| `5` | 已退款 | 已退款 | 否 |
| `6` | 已驳回 | 已驳回 | 否 |
`payment_status` 的值为:`0=待支付``1=已支付``2=已失败``3=已退款`。页面主流程优先根据充值 `status` 判断;`payment_status` 用于补充支付阶段文案。
进入 `status=3` 后,前端刷新钱包余额和充值列表。不要在 `status=2` 时提前增加页面余额。
## 五、平台线下代充调用流程
平台或超级管理员继续调用同一个创建接口:
```json
{
"shop_id": 20,
"amount": 50000,
"payment_method": "offline",
"payment_voucher_key": ["recharge-voucher/20260727/abc.png"],
"remark": "银行转账"
}
```
线下代充响应和后续列表/详情会返回:
```json
{
"recharge_source": "platform_offline",
"recharge_source_name": "平台线下代充",
"approval_provider": "wecom",
"approval_status": 1,
"approval_status_name": "审批中"
}
```
前端处理规则:
- 代理账号不得展示线下代充表单。
- 平台线下单展示凭证、备注和企微审批状态,不展示扫码二维码。
- 存在 `approval_instance_id``approval_provider=wecom` 时,只读展示审批进度,不显示旧的本地确认/驳回按钮。
- 在线充值的 `approval_instance_id``null`,不要显示企微审批区域。
- `/:id/payment-status` 是在线支付状态接口,线下代充详情使用 `GET /:id`,不要轮询支付状态接口。
## 六、列表和详情对接
列表请求示例:
```http
GET /api/admin/agent-recharges?page=1&page_size=20&recharge_source=agent_online&status=1
```
可用筛选参数:
| 参数 | 说明 |
| --- | --- |
| `page` | 页码,默认 1 |
| `page_size` | 每页条数,默认 20最大 100 |
| `shop_id` | 店铺 ID按既有数据权限生效 |
| `status` | 充值状态 `16` |
| `recharge_source` | `platform_offline``agent_online` |
| `start_date` | 开始日期,格式 `YYYY-MM-DD` |
| `end_date` | 结束日期,格式 `YYYY-MM-DD` |
列表成功响应的分页数据位于:
```json
{
"data": {
"items": [],
"total": 0,
"page": 1,
"size": 20
}
}
```
建议列表至少展示:充值单号、店铺、金额、`recharge_source_name`、支付方式、`status_name`、提交人和创建时间。
详情接口:
```http
GET /api/admin/agent-recharges/{id}
```
页面分支必须以 `recharge_source` 为准:
- `agent_online`:展示支付方式、第三方流水号、支付时间、完成时间;隐藏凭证和企微审批操作。
- `platform_offline`:展示支付凭证、备注、提交人和企微审批状态;隐藏二维码和在线轮询区域。
## 七、充值来源与状态字段
### 7.1 充值来源
| 字段值 | 中文名 | 创建人和路径 |
| --- | --- | --- |
| `platform_offline` | 平台线下代充 | 平台/超级管理员提交 `payment_method=offline` |
| `agent_online` | 代理在线自充 | 代理提交 `payment_method=wechat|alipay` |
前端展示中文时优先使用后端返回的 `recharge_source_name`,业务分支使用稳定枚举 `recharge_source`
### 7.2 充值状态
| 状态 | 名称 | 说明 |
| --- | --- | --- |
| `1` | 待支付 | 在线单等待扫码;线下单等待审批 |
| `2` | 已支付 | 第三方收款已确认,钱包可能仍在入账 |
| `3` | 已完成 | 钱包余额和唯一流水已提交 |
| `4` | 已关闭 | 在线支付关闭或预下单失败 |
| `5` | 已退款 | 充值已退款 |
| `6` | 已驳回 | 线下代充审批驳回 |
## 八、权限和错误处理
| 操作 | 平台/超级管理员 | 代理账号 | 企业账号 |
| --- | --- | --- | --- |
| 创建在线扫码充值 | 禁止 | 仅当前店铺主钱包 | 禁止 |
| 创建线下代充 | 允许 | 禁止 | 禁止 |
| 查询在线支付方式 | 禁止 | 允许 | 禁止 |
| 查询列表/详情 | 按既有数据范围 | 按店铺层级数据范围 | 禁止 |
| 查询在线支付状态 | 按既有数据范围 | 按店铺层级数据范围 | 禁止 |
前端不要根据错误文案判断资源是否存在。无权限或资源不可见时,后端可能统一返回“无权限操作该资源或资源不存在”。常见处理:
- `400`:保留表单输入并展示参数错误,不自动重试。
- `401`:按现有登录失效流程处理。
- `403`:关闭无权限操作入口,不尝试换账号类型绕过。
- `409` 或业务冲突码:检查是否错误复用了 `request_id`
- `500`/超时:在线创建可使用原 `request_id` 重试一次;不要生成新 ID否则可能创建第二张充值单。
## 九、前端本期最容易漏掉的工作
- 在线充值表单不要复用线下表单对象后整体序列化,避免携带 `shop_id`、凭证或备注。
- 支付方式必须来自 `/payment-methods`,不要写死微信和支付宝都可用。
- 金额显示元、提交分;禁止使用浮点数直接乘除后提交。
- 二维码内容原样渲染,不记录到埋点、错误日志或浏览器持久化缓存。
- 同一次网络重试复用 `request_id`,新一笔主动充值换新 ID。
- `status=2` 只表示已收款、入账中,不能提前刷新成“钱包已到账”。
- 列表、详情的页面分支使用 `recharge_source`,不要用 `payment_method` 或审批字段猜来源。
- 线下单不调用支付状态接口;在线单不展示企微审批按钮。
- 页面隐藏或浏览器切到后台时停止轮询,恢复可见后再继续。
- 进入终态后停止轮询并刷新钱包余额、充值列表。
## 十、联调和验收边界
- OpenAPI 已包含 `/payment-methods`、在线创建、列表来源筛选、详情来源字段和 `/payment-status`
- 后端已完成微信 Native、支付宝 PreCreate、支付确认、异步钱包入账和回调丢失恢复的代码装配。
- 当前交付已通过 `go build ./...``go vet ./...` 和 OpenSpec 严格校验。
- 按需求方要求,本次未启动 API/Worker未连接 PostgreSQL/Redis未调用真实支付渠道未发送真实回调也未运行自动化测试。
- 前端联调环境需具备完整支付配置;至少确认微信和支付宝创建响应分别返回非空 `qr_content`
- 本需求不支持 JSAPI、H5、WAP、同设备拉起支付、主动取消、支付方式切换、二维码图片接口或在线退款。

View File

@@ -0,0 +1,85 @@
# 代理钱包桌面扫码充值
前端调用顺序、请求示例和页面状态详见 [`代理钱包扫码充值接口对接说明.md`](代理钱包扫码充值接口对接说明.md)。
## 功能范围
代理账号可在后台为当前所属店铺主钱包创建微信 Native 或支付宝当面付扫码充值。平台与超级管理员继续使用既有线下代充和企业微信审批,两个创建路径不共用权限。
充值订单相关响应统一返回:
- `recharge_source=platform_offline``recharge_source_name=平台线下代充`
- `recharge_source=agent_online``recharge_source_name=代理在线自充`
来源由受控支付方式推导:`offline` 为平台线下代充,`wechat|alipay` 为代理在线自充。列表支持 `recharge_source` 筛选,不新增重复数据库列。
## API 对接
### 查询可用支付方式
`GET /api/admin/agent-recharges/payment-methods`
仅代理账号可用,返回当前真正可预下单、验签和查单的 `wechat``alipay`,以及在线充值金额范围 `10000100000000` 分。
### 创建充值订单
`POST /api/admin/agent-recharges`
代理在线自充请求仅允许:
```json
{
"amount": 10000,
"payment_method": "wechat",
"request_id": "客户端生成的唯一请求标识"
}
```
响应包含 `recharge_id``payment_no``qr_content``recharge_source` 和充值状态。前端直接使用 `qr_content` 渲染二维码,不展示或记录支付配置、商户身份和密钥。
平台线下代充使用 `payment_method=offline`,并按既有契约提交目标 `shop_id`、支付凭证和备注;响应来源为 `platform_offline`
### 列表、详情与支付状态
- `GET /api/admin/agent-recharges?recharge_source=agent_online`
- `GET /api/admin/agent-recharges/:id`
- `GET /api/admin/agent-recharges/:id/payment-status`
列表和详情均返回充值来源。支付状态接口仅用于在线充值,只读取本地充值单和支付单,返回支付确认时间与钱包完成时间,不返回 `qr_content`、内部重试错误或其他钱包余额,也不调用第三方渠道。
前端在页面可见时可每 3 秒轮询;进入已完成、已关闭、已退款或已驳回终态后停止轮询。
## 支付与到账
第三方收款成功后,回调只确认支付事实并写入 `agent_recharge.payment_confirmed.v1` Outbox。Worker 在独立事务中复用主钱包入账能力,以充值记录 ID 的唯一流水保证最多入账一次,并将充值状态从已支付推进为已完成。
支付单保存创建时的 `payment_config_id``merchant_identity`:微信记录商户号,支付宝记录应用 ID供未来导出按实际收款身份核对。该内部字段不在创建、列表、详情或支付状态响应中暴露。
## 异常恢复
Worker 每分钟调度一次恢复任务,并使用唯一任务约束避免并发重复扫描。任务固定扫描最多 50 张创建超过 2 分钟的代理在线待支付单:
- 尚无付款内容:使用原 `payment_no` 重试预下单。
- 已有付款内容:按创建时的支付方式与配置主动查单。
- 渠道确认成功:复用统一支付确认用例。
- 渠道明确关闭:条件关闭仍待支付的本地单。
- 超时、未知或渠道异常:保持原状态,等待后续重试。
微信、支付宝每次预下单和查单均写 Integration Log其中包含耗时和安全摘要不保存密钥或完整二维码内容。
## 部署与回滚
推荐顺序:
1. 执行 `000197``000198` 数据库迁移。
2. 确认微信商户号、证书、APIv3 Key、回调地址或支付宝应用 ID、私钥、公钥、回调地址完整。
3. 同时发布 API 与 Worker确认回调路由、Outbox Relay、代理充值消费者和恢复任务均已装配。
4. 最后开放前端扫码充值入口。
回滚时先关闭前端入口和在线支付方式停止创建新单回调、恢复任务、Outbox Relay 和钱包消费者必须继续处理已收款订单。不得删除待支付、已支付或待入账的支付事实。确认资金单全部收敛后,才可回滚应用与数据库迁移。
## 静态验收与未验证边界
本次按用户要求不启动 API/Worker不连接 PostgreSQL/Redis不调用真实支付不发送回调也不运行自动化测试。交付仅执行格式化、差异检查、编译、静态分析、OpenAPI 生成和 OpenSpec 严格校验。
上线前由发布方核对支付配置与回调公网可达性,并使用一笔微信和一笔支付宝订单确认渠道能返回非空 `qr_content`。回调丢失、重复回调与 Worker 重放可在需要时按上述状态和唯一流水口径人工核对。