All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 43s
9.5 KiB
9.5 KiB
#微信支付能力规格说明
ADDED Requirements
Requirement: 系统必须支持 JSAPI 支付
系统 MUST 支持在微信内网页发起 JSAPI 支付,用户在微信客户端内完成支付。
Scenario: 用户在微信内成功发起支付
- WHEN 用户在微信内选择订单并点击"微信支付",前端调用
/api/h5/orders/:id/wechat-pay/jsapi端点,传入用户 OpenID - THEN 系统验证订单状态为
pending(待支付) - THEN 系统调用 PowerWeChat SDK 的
Order.JSAPITransaction()创建支付订单 - THEN 系统生成 JSSDK 支付配置(包含 prepay_id、timestamp、nonceStr、paySign)
- THEN 系统返回支付配置给前端
- THEN 前端调用
wx.requestPayment()唤起微信支付
Scenario: 订单不存在或状态不正确
- WHEN 用户提交的订单 ID 不存在,或订单状态不是
pending - THEN 系统返回错误码 1000(参数错误)和中文错误消息"订单不存在或不可支付"
Scenario: 订单金额为 0
- WHEN 订单金额为 0 元
- THEN 系统跳过微信支付,直接更新订单状态为
paid - THEN 系统触发套餐激活和分佣计算
Scenario: 微信支付 API 调用失败
- WHEN 调用 PowerWeChat SDK 创建支付订单时失败(网络超时、参数错误等)
- THEN 系统记录详细的错误日志(Request ID、错误码、错误消息)
- THEN 系统返回错误码 1042(微信支付发起失败)和中文错误消息"支付发起失败,请重试"
Requirement: 系统必须支持 H5 支付
系统 MUST 支持在移动端浏览器外发起 H5 支付,用户可唤起微信 APP 完成支付。
Scenario: 用户在浏览器中成功发起 H5 支付
- WHEN 用户在移动端浏览器选择订单并点击"微信支付",前端调用
/api/h5/orders/:id/wechat-pay/h5端点,传入用户终端 IP 和场景信息 - THEN 系统验证订单状态为
pending - THEN 系统调用 PowerWeChat SDK 的
Order.TransactionH5()创建 H5 支付订单 - THEN 系统返回微信支付跳转 URL(h5_url)
- THEN 前端跳转到该 URL,用户在微信 H5 页面完成支付
Scenario: 缺少必填参数
- WHEN 请求缺少
payer_client_ip或scene_info参数 - THEN 系统返回错误码 1000(参数错误)和中文错误消息"缺少必填参数"
Scenario: 订单已支付
- WHEN 用户提交的订单状态已是
paid - THEN 系统返回错误码 1000(参数错误)和中文错误消息"订单已支付"
Requirement: 系统必须支持微信支付回调
系统 SHALL 接收并处理微信支付成功通知,更新订单状态并触发后续业务逻辑。
Scenario: 接收到合法的支付成功通知
- WHEN 微信回调
/api/callback/wechat-pay端点,传入支付成功通知 - THEN PowerWeChat SDK 自动验证回调签名
- THEN 系统解析通知内容,提取商户订单号(out_trade_no)
- THEN 系统调用
orderService.HandlePaymentCallback()更新订单状态为paid(幂等处理) - THEN 系统触发套餐激活和分佣计算
- THEN 系统返回 HTTP 200 和
{"return_code": "SUCCESS"}给微信
Scenario: 接收到重复的支付通知
- WHEN 微信多次发送同一订单的支付成功通知
- THEN 系统通过幂等检查识别订单已支付
- THEN 系统直接返回成功响应,不重复处理业务逻辑
Scenario: 回调签名验证失败
- WHEN 微信回调的签名无效或被篡改
- THEN PowerWeChat SDK 自动拒绝该请求
- THEN 系统记录 ERROR 级别日志(Request ID、签名验证失败详情)
- THEN 系统返回 HTTP 400 错误
Scenario: 订单号不存在
- WHEN 微信回调中的商户订单号在系统中不存在
- THEN 系统记录 ERROR 级别日志
- THEN 系统返回失败响应给微信(让微信稍后重试)
Scenario: 支付回调处理失败
- WHEN 系统在处理支付回调时发生数据库错误或其他异常
- THEN 系统记录 ERROR 级别日志(Request ID、错误详情)
- THEN 系统返回失败响应给微信(让微信稍后重试)
Requirement: 支付回调处理必须幂等
系统 MUST 确保多次接收到同一支付通知时,业务逻辑只执行一次。
Scenario: 订单状态条件更新
- WHEN 系统更新订单状态为
paid - THEN 系统使用条件更新:
UPDATE ... WHERE id = ? AND payment_status = ?(只更新状态为 pending 的订单) - THEN 如果更新影响行数为 0,系统检查当前订单状态:
- 如果已支付,返回成功(幂等)
- 如果已取消/已退款,返回错误
Scenario: 套餐激活幂等性
- WHEN 订单支付成功后触发套餐激活
- THEN 系统检查
tb_package_usage表是否已存在该订单的激活记录 - THEN 如果已存在,跳过激活逻辑(幂等)
Requirement: 系统必须支持查询微信支付订单
系统 SHALL 支持根据商户订单号查询微信支付订单状态。
Scenario: 查询到支付成功的订单
- WHEN 调用
PaymentService.Order.QueryByOutTradeNumber()查询订单 - THEN 系统返回订单详情,包含:
- 订单号(out_trade_no)
- 微信支付单号(transaction_id)
- 支付状态(trade_state: SUCCESS)
- 支付时间(success_time)
- 支付金额(total)
Scenario: 查询到待支付的订单
- WHEN 查询的订单尚未支付
- THEN 系统返回订单详情,支付状态为
NOTPAY
Scenario: 查询不存在的订单
- WHEN 查询的商户订单号在微信侧不存在
- THEN PowerWeChat SDK 返回错误
- THEN 系统记录日志并返回错误码 1042
Requirement: 系统必须支持关闭未支付订单
系统 SHALL 支持关闭超时未支付的微信订单。
Scenario: 成功关闭未支付订单
- WHEN 调用
PaymentService.Order.Close()关闭订单,传入商户订单号 - THEN 系统调用微信 API 关闭订单
- THEN 系统返回成功响应
Scenario: 尝试关闭已支付订单
- WHEN 调用关闭接口,但订单已支付
- THEN 微信 API 返回错误(订单已支付,无法关闭)
- THEN 系统记录日志并返回错误
Scenario: 订单创建后 5 分钟内关闭
- WHEN 订单创建后不足 5 分钟就调用关闭接口
- THEN 系统可能因订单状态同步不及时而关闭失败
- THEN 系统建议在创建 5 分钟后再关闭
Requirement: 系统必须支持配置管理
微信支付相关配置 MUST 通过 Viper + 环境变量管理。
Scenario: 从环境变量读取配置
- WHEN 系统启动时
- THEN 系统从环境变量读取以下配置:
JUNHONG_WECHAT_PAYMENT_APP_ID(支付 AppID)JUNHONG_WECHAT_PAYMENT_MCH_ID(商户号)JUNHONG_WECHAT_PAYMENT_API_V3_KEY(API V3 密钥)JUNHONG_WECHAT_PAYMENT_API_V2_KEY(API V2 密钥)JUNHONG_WECHAT_PAYMENT_CERT_PATH(商户证书路径)JUNHONG_WECHAT_PAYMENT_KEY_PATH(商户私钥路径)JUNHONG_WECHAT_PAYMENT_SERIAL_NO(证书序列号)JUNHONG_WECHAT_PAYMENT_NOTIFY_URL(支付回调地址)
Scenario: 证书文件不存在时启动失败
- WHEN 配置的证书路径指向的文件不存在或无读取权限
- THEN 系统记录 FATAL 级别日志
- THEN 系统启动失败并退出
Scenario: 必填配置缺失时启动失败
- WHEN 必填配置项(AppID、商户号、API 密钥)缺失
- THEN 系统记录 FATAL 级别日志
- THEN 系统启动失败并退出
Requirement: API 必须遵循统一响应格式
所有微信支付相关 API MUST 返回统一的 JSON 响应格式(同微信公众号规范)。
Scenario: 支付发起成功响应
- WHEN JSAPI 支付发起成功
- THEN 系统返回 HTTP 200 和以下格式:
{ "code": 0, "message": "success", "data": { "prepay_id": "wx...", "pay_config": { "appId": "...", "timeStamp": "...", "nonceStr": "...", "package": "prepay_id=...", "signType": "RSA", "paySign": "..." } }, "timestamp": 1706789012345 }
Scenario: H5 支付发起成功响应
- WHEN H5 支付发起成功
- THEN 系统返回 HTTP 200 和以下格式:
{ "code": 0, "message": "success", "data": { "h5_url": "https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?..." }, "timestamp": 1706789012345 }
Requirement: 系统必须记录完整的日志
所有微信支付 API 调用 MUST 记录完整的日志。
Scenario: 记录支付发起日志
- WHEN 系统调用微信支付 API 创建订单
- THEN 系统记录 INFO 级别日志,包含:Request ID、订单号、支付类型(JSAPI/H5)、订单金额
Scenario: 记录支付回调日志
- WHEN 系统收到微信支付回调
- THEN 系统记录 INFO 级别日志,包含:Request ID、订单号、微信支付单号、支付时间
Scenario: 记录支付错误日志
- WHEN 微信支付 API 调用失败
- THEN 系统记录 ERROR 级别日志,包含:Request ID、订单号、错误码、错误消息、完整的错误详情
Requirement: 系统必须支持 Redis 缓存
微信支付的 Access Token MUST 使用 Redis 缓存(与微信公众号共享同一缓存机制)。
Scenario: Token 缓存与公众号共享
- WHEN 微信支付和公众号使用相同的 AppID
- THEN 系统复用同一个 Redis Cache 实例
- THEN Token 缓存 Key 相同,避免重复获取