29 KiB
ADDED Requirements
Requirement: 微信参数配置 CRUD 管理
系统 SHALL 支持平台用户对微信支付参数配置的完整生命周期管理,包括创建、列表查询、详情查询、更新、删除。每个配置包含完整的支付身份信息(渠道凭证 + 公众号 OAuth 信息 + 小程序 OAuth 信息)。
Scenario: 创建微信直连支付配置
WHEN 平台用户调用 POST /api/admin/wechat-configs,provider_type 为 wechat,提供名称、公众号信息、小程序信息、商户号、API V3 密钥、证书内容(Base64)、私钥内容(Base64)、证书序列号、回调地址
THEN 系统创建配置记录,is_active 默认为 false,返回完整配置信息(敏感字段脱敏)
请求
POST /api/admin/wechat-configs
Authorization: Bearer {token}
Content-Type: application/json
{
"name": "微信直连主配置",
"description": "生产环境微信直连支付配置",
"provider_type": "wechat",
"oa_app_id": "wx1234567890abcdef",
"oa_app_secret": "abcdef1234567890abcdef1234567890",
"oa_token": "mytoken123",
"oa_aes_key": "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFG",
"oa_oauth_redirect_url": "https://example.com/oauth/callback",
"miniapp_app_id": "wx9876543210fedcba",
"miniapp_app_secret": "fedcba0987654321fedcba0987654321",
"wx_mch_id": "1234567890",
"wx_api_v3_key": "your32charv3keyhere1234567890abc",
"wx_api_v2_key": "your32charv2keyhere1234567890abc",
"wx_cert_content": "BASE64_ENCODED_CERT_CONTENT_HERE",
"wx_key_content": "BASE64_ENCODED_KEY_CONTENT_HERE",
"wx_serial_no": "ABCDEF1234567890ABCDEF1234567890ABCDEF12",
"wx_notify_url": "https://example.com/api/payment/wechat/notify"
}
请求字段说明
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| name | string | 是 | 配置名称,最长 100 字符 |
| description | string | 否 | 配置描述,最长 500 字符 |
| provider_type | string | 是 | 渠道类型,枚举值:wechat(微信直连)、fuiou(富友) |
| oa_app_id | string | 否 | 公众号 AppID |
| oa_app_secret | string | 否 | 公众号 AppSecret |
| oa_token | string | 否 | 公众号消息校验 Token |
| oa_aes_key | string | 否 | 公众号消息加解密 Key |
| oa_oauth_redirect_url | string | 否 | 公众号 OAuth 回调地址 |
| miniapp_app_id | string | 否 | 小程序 AppID |
| miniapp_app_secret | string | 否 | 小程序 AppSecret |
| wx_mch_id | string | provider_type=wechat 时必填 | 微信商户号 |
| wx_api_v3_key | string | provider_type=wechat 时必填 | API V3 密钥(32字符) |
| wx_api_v2_key | string | 否 | API V2 密钥(32字符) |
| wx_cert_content | string | provider_type=wechat 时必填 | 商户证书内容(Base64 编码) |
| wx_key_content | string | provider_type=wechat 时必填 | 商户私钥内容(Base64 编码) |
| wx_serial_no | string | provider_type=wechat 时必填 | 商户证书序列号 |
| wx_notify_url | string | provider_type=wechat 时必填 | 微信支付回调地址 |
成功响应
{
"code": 0,
"data": {
"id": 1,
"name": "微信直连主配置",
"description": "生产环境微信直连支付配置",
"provider_type": "wechat",
"is_active": false,
"oa_app_id": "wx1234567890abcdef",
"oa_app_secret": "abcd***7890",
"oa_token": "myto***n123",
"oa_aes_key": "[已配置]",
"oa_oauth_redirect_url": "https://example.com/oauth/callback",
"miniapp_app_id": "wx9876543210fedcba",
"miniapp_app_secret": "fedc***4321",
"wx_mch_id": "1234567890",
"wx_api_v3_key": "your***0abc",
"wx_api_v2_key": "your***0abc",
"wx_cert_content": "[已配置]",
"wx_key_content": "[已配置]",
"wx_serial_no": "ABCD***EF12",
"wx_notify_url": "https://example.com/api/payment/wechat/notify",
"fy_ins_cd": "",
"fy_mchnt_cd": "",
"fy_term_id": "",
"fy_private_key": "[未配置]",
"fy_public_key": "[未配置]",
"fy_api_url": "",
"fy_notify_url": "",
"created_at": "2026-03-16T10:00:00+08:00",
"updated_at": "2026-03-16T10:00:00+08:00"
},
"msg": "success",
"timestamp": "2026-03-16T10:00:00+08:00"
}
敏感字段脱敏规则
| 字段 | 脱敏规则 | 示例原值 | 脱敏后 |
|---|---|---|---|
| oa_app_secret | 前4位 + *** + 后4位 |
abcdef1234567890abcdef1234567890 |
abcd***7890 |
| oa_token | 前4位 + *** + 后4位 |
mytoken123 |
myto***n123 |
| oa_aes_key | [已配置] / [未配置] |
任意值 | [已配置] |
| miniapp_app_secret | 前4位 + *** + 后4位 |
fedcba0987654321fedcba0987654321 |
fedc***4321 |
| wx_api_v3_key | 前4位 + *** + 后4位 |
your32charv3keyhere1234567890abc |
your***0abc |
| wx_api_v2_key | 前4位 + *** + 后4位 |
your32charv2keyhere1234567890abc |
your***0abc |
| wx_cert_content | [已配置] / [未配置] |
Base64 内容 | [已配置] |
| wx_key_content | [已配置] / [未配置] |
Base64 内容 | [已配置] |
| wx_serial_no | 前4位 + *** + 后4位 |
ABCDEF1234567890ABCDEF1234567890ABCDEF12 |
ABCD***EF12 |
| fy_private_key | [已配置] / [未配置] |
Base64 内容 | [已配置] |
| fy_public_key | [已配置] / [未配置] |
Base64 内容 | [已配置] |
Scenario: 创建富友支付配置
WHEN 平台用户调用 POST /api/admin/wechat-configs,provider_type 为 fuiou,提供名称、公众号信息、小程序信息、机构号、商户号、终端号、商户私钥(Base64)、富友公钥(Base64)、API 地址、回调地址
THEN 系统创建配置记录,is_active 默认为 false
请求
POST /api/admin/wechat-configs
Authorization: Bearer {token}
Content-Type: application/json
{
"name": "富友支付配置",
"description": "富友聚合支付渠道配置",
"provider_type": "fuiou",
"oa_app_id": "wx1234567890abcdef",
"oa_app_secret": "abcdef1234567890abcdef1234567890",
"oa_oauth_redirect_url": "https://example.com/oauth/callback",
"miniapp_app_id": "wx9876543210fedcba",
"miniapp_app_secret": "fedcba0987654321fedcba0987654321",
"fy_ins_cd": "0000100",
"fy_mchnt_cd": "0000100002000001",
"fy_term_id": "00000001",
"fy_private_key": "BASE64_ENCODED_MERCHANT_PRIVATE_KEY",
"fy_public_key": "BASE64_ENCODED_FUIOU_PUBLIC_KEY",
"fy_api_url": "https://spay.fuiou.com",
"fy_notify_url": "https://example.com/api/payment/fuiou/notify"
}
请求字段说明
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| name | string | 是 | 配置名称,最长 100 字符 |
| description | string | 否 | 配置描述,最长 500 字符 |
| provider_type | string | 是 | 渠道类型,此处为 fuiou |
| oa_app_id | string | 否 | 公众号 AppID |
| oa_app_secret | string | 否 | 公众号 AppSecret |
| oa_token | string | 否 | 公众号消息校验 Token |
| oa_aes_key | string | 否 | 公众号消息加解密 Key |
| oa_oauth_redirect_url | string | 否 | 公众号 OAuth 回调地址 |
| miniapp_app_id | string | 否 | 小程序 AppID |
| miniapp_app_secret | string | 否 | 小程序 AppSecret |
| fy_ins_cd | string | provider_type=fuiou 时必填 | 富友机构号 |
| fy_mchnt_cd | string | provider_type=fuiou 时必填 | 富友商户号 |
| fy_term_id | string | provider_type=fuiou 时必填 | 富友终端号 |
| fy_private_key | string | provider_type=fuiou 时必填 | 商户私钥(Base64 编码) |
| fy_public_key | string | provider_type=fuiou 时必填 | 富友公钥(Base64 编码) |
| fy_api_url | string | provider_type=fuiou 时必填 | 富友 API 地址 |
| fy_notify_url | string | provider_type=fuiou 时必填 | 富友支付回调地址 |
成功响应
{
"code": 0,
"data": {
"id": 2,
"name": "富友支付配置",
"description": "富友聚合支付渠道配置",
"provider_type": "fuiou",
"is_active": false,
"oa_app_id": "wx1234567890abcdef",
"oa_app_secret": "abcd***7890",
"oa_token": "",
"oa_aes_key": "[未配置]",
"oa_oauth_redirect_url": "https://example.com/oauth/callback",
"miniapp_app_id": "wx9876543210fedcba",
"miniapp_app_secret": "fedc***4321",
"wx_mch_id": "",
"wx_api_v3_key": "",
"wx_api_v2_key": "",
"wx_cert_content": "[未配置]",
"wx_key_content": "[未配置]",
"wx_serial_no": "",
"wx_notify_url": "",
"fy_ins_cd": "0000100",
"fy_mchnt_cd": "0000100002000001",
"fy_term_id": "00000001",
"fy_private_key": "[已配置]",
"fy_public_key": "[已配置]",
"fy_api_url": "https://spay.fuiou.com",
"fy_notify_url": "https://example.com/api/payment/fuiou/notify",
"created_at": "2026-03-16T10:00:00+08:00",
"updated_at": "2026-03-16T10:00:00+08:00"
},
"msg": "success",
"timestamp": "2026-03-16T10:00:00+08:00"
}
Scenario: 创建配置参数校验失败
WHEN 平台用户创建配置时缺少必填字段(如 provider_type 为 wechat 但未提供 wx_mch_id)
THEN 系统返回错误码 1001,拒绝创建
请求示例(缺少 wx_mch_id)
POST /api/admin/wechat-configs
Authorization: Bearer {token}
Content-Type: application/json
{
"name": "微信直连配置",
"provider_type": "wechat",
"wx_api_v3_key": "your32charv3keyhere1234567890abc"
}
错误响应
{
"code": 1001,
"data": null,
"msg": "参数错误",
"timestamp": "2026-03-16T10:00:00+08:00"
}
Scenario: 查询配置列表
WHEN 平台用户调用 GET /api/admin/wechat-configs,支持按 provider_type 和 is_active 筛选,支持分页
THEN 系统返回配置列表,敏感字段脱敏
请求
GET /api/admin/wechat-configs?provider_type=wechat&is_active=false&page=1&page_size=20
Authorization: Bearer {token}
查询参数说明
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| provider_type | string | 否 | 按渠道类型筛选,枚举值:wechat、fuiou |
| is_active | boolean | 否 | 按激活状态筛选,true 或 false |
| page | integer | 否 | 页码,默认 1 |
| page_size | integer | 否 | 每页条数,默认 20,最大 100 |
成功响应
{
"code": 0,
"data": {
"list": [
{
"id": 1,
"name": "微信直连主配置",
"description": "生产环境微信直连支付配置",
"provider_type": "wechat",
"is_active": false,
"oa_app_id": "wx1234567890abcdef",
"oa_app_secret": "abcd***7890",
"oa_token": "myto***n123",
"oa_aes_key": "[已配置]",
"oa_oauth_redirect_url": "https://example.com/oauth/callback",
"miniapp_app_id": "wx9876543210fedcba",
"miniapp_app_secret": "fedc***4321",
"wx_mch_id": "1234567890",
"wx_api_v3_key": "your***0abc",
"wx_api_v2_key": "your***0abc",
"wx_cert_content": "[已配置]",
"wx_key_content": "[已配置]",
"wx_serial_no": "ABCD***EF12",
"wx_notify_url": "https://example.com/api/payment/wechat/notify",
"fy_ins_cd": "",
"fy_mchnt_cd": "",
"fy_term_id": "",
"fy_private_key": "[未配置]",
"fy_public_key": "[未配置]",
"fy_api_url": "",
"fy_notify_url": "",
"created_at": "2026-03-16T10:00:00+08:00",
"updated_at": "2026-03-16T10:00:00+08:00"
}
],
"total": 1,
"page": 1,
"page_size": 20
},
"msg": "success",
"timestamp": "2026-03-16T10:00:00+08:00"
}
Scenario: 查询配置详情
WHEN 平台用户调用 GET /api/admin/wechat-configs/:id
THEN 系统返回配置详情,敏感字段脱敏
请求
GET /api/admin/wechat-configs/1
Authorization: Bearer {token}
成功响应
{
"code": 0,
"data": {
"id": 1,
"name": "微信直连主配置",
"description": "生产环境微信直连支付配置",
"provider_type": "wechat",
"is_active": false,
"oa_app_id": "wx1234567890abcdef",
"oa_app_secret": "abcd***7890",
"oa_token": "myto***n123",
"oa_aes_key": "[已配置]",
"oa_oauth_redirect_url": "https://example.com/oauth/callback",
"miniapp_app_id": "wx9876543210fedcba",
"miniapp_app_secret": "fedc***4321",
"wx_mch_id": "1234567890",
"wx_api_v3_key": "your***0abc",
"wx_api_v2_key": "your***0abc",
"wx_cert_content": "[已配置]",
"wx_key_content": "[已配置]",
"wx_serial_no": "ABCD***EF12",
"wx_notify_url": "https://example.com/api/payment/wechat/notify",
"fy_ins_cd": "",
"fy_mchnt_cd": "",
"fy_term_id": "",
"fy_private_key": "[未配置]",
"fy_public_key": "[未配置]",
"fy_api_url": "",
"fy_notify_url": "",
"created_at": "2026-03-16T10:00:00+08:00",
"updated_at": "2026-03-16T10:00:00+08:00"
},
"msg": "success",
"timestamp": "2026-03-16T10:00:00+08:00"
}
配置不存在时的错误响应
{
"code": 1170,
"data": null,
"msg": "微信支付配置不存在",
"timestamp": "2026-03-16T10:00:00+08:00"
}
Scenario: 更新配置(非敏感字段)
WHEN 平台用户调用 PUT /api/admin/wechat-configs/:id,仅更新名称、描述、回调地址等非敏感字段
THEN 系统更新对应字段,敏感字段保持不变
请求
PUT /api/admin/wechat-configs/1
Authorization: Bearer {token}
Content-Type: application/json
{
"name": "微信直连主配置(已更新)",
"description": "更新后的描述",
"wx_notify_url": "https://new.example.com/api/payment/wechat/notify"
}
请求字段说明
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| name | string | 否 | 配置名称 |
| description | string | 否 | 配置描述 |
| oa_app_id | string | 否 | 公众号 AppID |
| oa_app_secret | string | 否 | 公众号 AppSecret;空字符串或不传 = 保留原值;传新值 = 替换 |
| oa_token | string | 否 | 公众号消息校验 Token;空字符串或不传 = 保留原值;传新值 = 替换 |
| oa_aes_key | string | 否 | 公众号消息加解密 Key;空字符串或不传 = 保留原值;传新值 = 替换 |
| oa_oauth_redirect_url | string | 否 | 公众号 OAuth 回调地址 |
| miniapp_app_id | string | 否 | 小程序 AppID |
| miniapp_app_secret | string | 否 | 小程序 AppSecret;空字符串或不传 = 保留原值;传新值 = 替换 |
| wx_mch_id | string | 否 | 微信商户号 |
| wx_api_v3_key | string | 否 | API V3 密钥;空字符串或不传 = 保留原值;传新值 = 替换 |
| wx_api_v2_key | string | 否 | API V2 密钥;空字符串或不传 = 保留原值;传新值 = 替换 |
| wx_cert_content | string | 否 | 商户证书内容(Base64);空字符串或不传 = 保留原值;传新值 = 替换 |
| wx_key_content | string | 否 | 商户私钥内容(Base64);空字符串或不传 = 保留原值;传新值 = 替换 |
| wx_serial_no | string | 否 | 商户证书序列号;空字符串或不传 = 保留原值;传新值 = 替换 |
| wx_notify_url | string | 否 | 微信支付回调地址 |
| fy_ins_cd | string | 否 | 富友机构号 |
| fy_mchnt_cd | string | 否 | 富友商户号 |
| fy_term_id | string | 否 | 富友终端号 |
| fy_private_key | string | 否 | 商户私钥(Base64);空字符串或不传 = 保留原值;传新值 = 替换 |
| fy_public_key | string | 否 | 富友公钥(Base64);空字符串或不传 = 保留原值;传新值 = 替换 |
| fy_api_url | string | 否 | 富友 API 地址 |
| fy_notify_url | string | 否 | 富友支付回调地址 |
成功响应
{
"code": 0,
"data": {
"id": 1,
"name": "微信直连主配置(已更新)",
"description": "更新后的描述",
"provider_type": "wechat",
"is_active": false,
"oa_app_id": "wx1234567890abcdef",
"oa_app_secret": "abcd***7890",
"oa_token": "myto***n123",
"oa_aes_key": "[已配置]",
"oa_oauth_redirect_url": "https://example.com/oauth/callback",
"miniapp_app_id": "wx9876543210fedcba",
"miniapp_app_secret": "fedc***4321",
"wx_mch_id": "1234567890",
"wx_api_v3_key": "your***0abc",
"wx_api_v2_key": "your***0abc",
"wx_cert_content": "[已配置]",
"wx_key_content": "[已配置]",
"wx_serial_no": "ABCD***EF12",
"wx_notify_url": "https://new.example.com/api/payment/wechat/notify",
"fy_ins_cd": "",
"fy_mchnt_cd": "",
"fy_term_id": "",
"fy_private_key": "[未配置]",
"fy_public_key": "[未配置]",
"fy_api_url": "",
"fy_notify_url": "",
"created_at": "2026-03-16T10:00:00+08:00",
"updated_at": "2026-03-16T10:30:00+08:00"
},
"msg": "success",
"timestamp": "2026-03-16T10:30:00+08:00"
}
Scenario: 更新当前生效配置时清除 Redis 缓存
WHEN 平台用户更新的配置 is_active=true(当前生效配置)
THEN 系统更新字段后,主动清除 Redis 缓存 wechat:config:active,使变更即时生效
THEN 响应格式与普通更新相同
Scenario: 更新配置时替换敏感字段
WHEN 平台用户更新配置时,对脱敏字段传入新的明文值(非空字符串、非脱敏格式)
THEN 系统将该字段替换为新值
请求示例(替换 API V3 密钥)
{
"wx_api_v3_key": "newkey32charsnewkey32charsnewkey"
}
THEN 系统将 wx_api_v3_key 更新为新值,响应中该字段显示脱敏后的新值 newk***ekey
Scenario: 删除未激活的配置
WHEN 平台用户调用 DELETE /api/admin/wechat-configs/:id,且该配置 is_active=false
THEN 系统软删除该配置记录,返回成功
请求
DELETE /api/admin/wechat-configs/1
Authorization: Bearer {token}
成功响应
{
"code": 0,
"data": null,
"msg": "success",
"timestamp": "2026-03-16T10:00:00+08:00"
}
Scenario: 禁止删除激活中的配置
WHEN 平台用户尝试删除 is_active=true 的配置
THEN 系统返回错误码 1171,拒绝删除
错误响应
{
"code": 1171,
"data": null,
"msg": "不能删除当前生效的支付配置,请先停用",
"timestamp": "2026-03-16T10:00:00+08:00"
}
Scenario: 禁止删除有在途订单的配置
WHEN 平台用户尝试删除某配置,且存在 payment_config_id 指向该配置的待支付订单
THEN 系统返回错误码 1172,拒绝删除
错误响应
{
"code": 1172,
"data": null,
"msg": "该配置存在未完成的支付订单,暂时无法删除",
"timestamp": "2026-03-16T10:00:00+08:00"
}
Requirement: 全局唯一激活约束
系统 SHALL 保证任意时刻最多一个支付配置处于激活状态。激活新配置时 MUST 自动停用旧配置。
Scenario: 激活配置
WHEN 平台用户调用 POST /api/admin/wechat-configs/:id/activate
THEN 系统在事务中执行:将所有 is_active=true 的配置设为 false,再将目标配置设为 true
THEN 系统清除 Redis 缓存 wechat:config:active
THEN 系统返回成功,新配置即时生效
请求
POST /api/admin/wechat-configs/1/activate
Authorization: Bearer {token}
成功响应
{
"code": 0,
"data": {
"id": 1,
"name": "微信直连主配置",
"description": "生产环境微信直连支付配置",
"provider_type": "wechat",
"is_active": true,
"oa_app_id": "wx1234567890abcdef",
"oa_app_secret": "abcd***7890",
"oa_token": "myto***n123",
"oa_aes_key": "[已配置]",
"oa_oauth_redirect_url": "https://example.com/oauth/callback",
"miniapp_app_id": "wx9876543210fedcba",
"miniapp_app_secret": "fedc***4321",
"wx_mch_id": "1234567890",
"wx_api_v3_key": "your***0abc",
"wx_api_v2_key": "your***0abc",
"wx_cert_content": "[已配置]",
"wx_key_content": "[已配置]",
"wx_serial_no": "ABCD***EF12",
"wx_notify_url": "https://example.com/api/payment/wechat/notify",
"fy_ins_cd": "",
"fy_mchnt_cd": "",
"fy_term_id": "",
"fy_private_key": "[未配置]",
"fy_public_key": "[未配置]",
"fy_api_url": "",
"fy_notify_url": "",
"created_at": "2026-03-16T10:00:00+08:00",
"updated_at": "2026-03-16T10:05:00+08:00"
},
"msg": "success",
"timestamp": "2026-03-16T10:05:00+08:00"
}
配置不存在时的错误响应
{
"code": 1170,
"data": null,
"msg": "微信支付配置不存在",
"timestamp": "2026-03-16T10:05:00+08:00"
}
Scenario: 停用配置
WHEN 平台用户调用 POST /api/admin/wechat-configs/:id/deactivate
THEN 系统将该配置 is_active 设为 false
THEN 系统清除 Redis 缓存 wechat:config:active
THEN 此后创建订单时仅支持钱包支付或线下支付
请求
POST /api/admin/wechat-configs/1/deactivate
Authorization: Bearer {token}
成功响应
{
"code": 0,
"data": {
"id": 1,
"name": "微信直连主配置",
"description": "生产环境微信直连支付配置",
"provider_type": "wechat",
"is_active": false,
"oa_app_id": "wx1234567890abcdef",
"oa_app_secret": "abcd***7890",
"oa_token": "myto***n123",
"oa_aes_key": "[已配置]",
"oa_oauth_redirect_url": "https://example.com/oauth/callback",
"miniapp_app_id": "wx9876543210fedcba",
"miniapp_app_secret": "fedc***4321",
"wx_mch_id": "1234567890",
"wx_api_v3_key": "your***0abc",
"wx_api_v2_key": "your***0abc",
"wx_cert_content": "[已配置]",
"wx_key_content": "[已配置]",
"wx_serial_no": "ABCD***EF12",
"wx_notify_url": "https://example.com/api/payment/wechat/notify",
"fy_ins_cd": "",
"fy_mchnt_cd": "",
"fy_term_id": "",
"fy_private_key": "[未配置]",
"fy_public_key": "[未配置]",
"fy_api_url": "",
"fy_notify_url": "",
"created_at": "2026-03-16T10:00:00+08:00",
"updated_at": "2026-03-16T10:10:00+08:00"
},
"msg": "success",
"timestamp": "2026-03-16T10:10:00+08:00"
}
配置不存在时的错误响应
{
"code": 1170,
"data": null,
"msg": "微信支付配置不存在",
"timestamp": "2026-03-16T10:10:00+08:00"
}
Scenario: 查询当前生效配置
WHEN 平台用户调用 GET /api/admin/wechat-configs/active
THEN 若有生效配置,返回该配置详情(脱敏)
THEN 若无生效配置,data 返回 null
请求
GET /api/admin/wechat-configs/active
Authorization: Bearer {token}
有生效配置时的成功响应
{
"code": 0,
"data": {
"id": 1,
"name": "微信直连主配置",
"description": "生产环境微信直连支付配置",
"provider_type": "wechat",
"is_active": true,
"oa_app_id": "wx1234567890abcdef",
"oa_app_secret": "abcd***7890",
"oa_token": "myto***n123",
"oa_aes_key": "[已配置]",
"oa_oauth_redirect_url": "https://example.com/oauth/callback",
"miniapp_app_id": "wx9876543210fedcba",
"miniapp_app_secret": "fedc***4321",
"wx_mch_id": "1234567890",
"wx_api_v3_key": "your***0abc",
"wx_api_v2_key": "your***0abc",
"wx_cert_content": "[已配置]",
"wx_key_content": "[已配置]",
"wx_serial_no": "ABCD***EF12",
"wx_notify_url": "https://example.com/api/payment/wechat/notify",
"fy_ins_cd": "",
"fy_mchnt_cd": "",
"fy_term_id": "",
"fy_private_key": "[未配置]",
"fy_public_key": "[未配置]",
"fy_api_url": "",
"fy_notify_url": "",
"created_at": "2026-03-16T10:00:00+08:00",
"updated_at": "2026-03-16T10:05:00+08:00"
},
"msg": "success",
"timestamp": "2026-03-16T10:15:00+08:00"
}
无生效配置时的响应
{
"code": 0,
"data": null,
"msg": "当前无生效的支付配置,仅支持钱包支付",
"timestamp": "2026-03-16T10:15:00+08:00"
}
Scenario: 配置切换不取消在途订单
WHEN 管理员激活新配置时,系统中存在使用旧配置创建的待支付订单
THEN 系统不取消这些订单
THEN 旧订单若支付成功,回调按订单关联的 payment_config_id 加载旧配置验签处理
THEN 旧订单若未支付,由现有 30 分钟超时机制自动取消
此场景无独立 API 接口,为激活接口的业务约束。
Requirement: 生效配置 Redis 缓存
系统 SHALL 将当前生效的支付配置缓存在 Redis 中,减少数据库查询。
Scenario: 缓存命中
WHEN 支付流程查询生效配置,Redis 缓存 wechat:config:active 存在
THEN 直接返回缓存数据,不查询数据库
此场景为内部实现约束,无独立 API 接口。
Scenario: 缓存未命中
WHEN 支付流程查询生效配置,Redis 缓存 wechat:config:active 不存在
THEN 查询数据库获取 is_active=true 的配置
THEN 将结果写入 Redis,TTL 为 5 分钟
THEN 返回配置数据
此场景为内部实现约束,无独立 API 接口。
Scenario: 无生效配置时缓存空标记
WHEN 数据库中无 is_active=true 的配置
THEN 在 Redis 写入空标记(值为 "none"),TTL 为 1 分钟
THEN 后续请求命中空标记后直接返回无配置,不穿透数据库
此场景为内部实现约束,无独立 API 接口。
Scenario: 配置变更主动清除缓存
WHEN 执行激活、停用、更新生效配置、删除配置操作
THEN 系统主动 DEL Redis 缓存 wechat:config:active
此场景为内部实现约束,体现在激活、停用、更新、删除接口的副作用中。
Requirement: 仅平台用户可操作
系统 SHALL 限制微信参数配置管理接口仅平台用户(user_type=1 超级管理员和 user_type=2 平台用户)可访问。路由层中间件统一拦截,无需在 Service 层重复校验。
Scenario: 平台用户访问成功
WHEN 超级管理员(user_type=1)或平台用户(user_type=2)请求微信参数配置管理接口
THEN 系统正常处理请求
Scenario: 非平台用户拒绝访问
WHEN 代理账号(user_type=3)或企业账号(user_type=4)请求微信参数配置管理接口
THEN 系统返回错误码 1005,消息"无权限访问支付配置管理功能"
错误响应
{
"code": 1005,
"data": null,
"msg": "无权限访问支付配置管理功能",
"timestamp": "2026-03-16T10:00:00+08:00"
}
Scenario: 未登录用户拒绝访问
WHEN 请求未携带有效 Token 或 Token 已过期
THEN 系统返回 HTTP 401,错误码 1002
错误响应
{
"code": 1002,
"data": null,
"msg": "无效或已过期的认证令牌",
"timestamp": "2026-03-16T10:00:00+08:00"
}
Requirement: 审计日志
系统 SHALL 对所有微信参数配置的写操作(创建、更新、删除、激活、停用)记录操作审计日志,便于追溯配置变更历史。
Scenario: 创建配置时记录审计日志
WHEN 平台用户成功创建微信参数配置
THEN 系统异步写入审计日志,记录以下信息:
| 字段 | 值 |
|---|---|
| operator_id | 当前操作人 ID |
| operator_type | 操作人用户类型 |
| operation_type | create |
| operation_desc | 创建微信支付配置:{配置名称} |
| after_data | 新建配置的完整数据(敏感字段脱敏后存储) |
| request_id | 当前请求 ID |
| ip_address | 操作人 IP |
| user_agent | 操作人 User-Agent |
THEN 审计日志写入失败不影响业务操作,失败时记录 Error 日志
Scenario: 更新配置时记录审计日志
WHEN 平台用户成功更新微信参数配置
THEN 系统异步写入审计日志,记录以下信息:
| 字段 | 值 |
|---|---|
| operator_id | 当前操作人 ID |
| operation_type | update |
| operation_desc | 更新微信支付配置:{配置名称} |
| before_data | 更新前的配置数据(敏感字段脱敏后存储) |
| after_data | 更新后的配置数据(敏感字段脱敏后存储) |
Scenario: 删除配置时记录审计日志
WHEN 平台用户成功删除微信参数配置
THEN 系统异步写入审计日志,记录以下信息:
| 字段 | 值 |
|---|---|
| operator_id | 当前操作人 ID |
| operation_type | delete |
| operation_desc | 删除微信支付配置:{配置名称} |
| before_data | 删除前的配置数据(敏感字段脱敏后存储) |
Scenario: 激活配置时记录审计日志
WHEN 平台用户成功激活微信参数配置
THEN 系统异步写入审计日志,记录以下信息:
| 字段 | 值 |
|---|---|
| operator_id | 当前操作人 ID |
| operation_type | activate |
| operation_desc | 激活微信支付配置:{配置名称},原生效配置:{旧配置名称或"无"} |
| before_data | 激活前的状态(旧生效配置 ID 和名称) |
| after_data | 激活后的状态(新生效配置 ID 和名称) |
Scenario: 停用配置时记录审计日志
WHEN 平台用户成功停用微信参数配置
THEN 系统异步写入审计日志,记录以下信息:
| 字段 | 值 |
|---|---|
| operator_id | 当前操作人 ID |
| operation_type | deactivate |
| operation_desc | 停用微信支付配置:{配置名称} |
| before_data | 停用前的配置状态 |
| after_data | 停用后的配置状态 |