Files
huang 817d0d6e04
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 46s
更新openspec
2026-03-17 14:22:01 +08:00

5.2 KiB
Raw Blame History

MODIFIED Requirements

Requirement: 微信支付配置动态加载

微信支付配置 MUST 从数据库动态加载(通过 tb_wechat_config替代原有的环境变量静态配置。Payment 实例按需创建,支持请求级 AppID 覆盖(区分公众号和小程序)。

Scenario: 从数据库加载配置创建 Payment 实例

  • WHEN 支付流程需要使用微信支付
  • THEN 系统从 Redis 缓存或数据库加载当前生效的微信参数配置(is_active=trueprovider_type=wechat
  • THEN 系统使用配置中的 wx_mch_idwx_api_v3_keywx_cert_contentwx_key_contentwx_serial_no 创建 payment.Payment 实例
  • THEN 证书内容从 Base64 解码后写入临时文件供 PowerWeChat SDK 使用

本次留桩WechatPayJSAPI 和 WechatPayH5 方法保留现有 wechatPayment 单例调用,添加 TODO 注释标记后续替换点。

Scenario: 无生效微信支付配置时拒绝支付

  • WHEN 系统查询不到 is_active=true 的微信参数配置,或生效配置的 provider_typewechat
  • THEN 微信支付相关接口返回错误
{
  "code": 1175,
  "data": null,
  "msg": "当前无可用的支付渠道",
  "timestamp": "2026-03-16T10:00:00+08:00"
}

Scenario: 公众号 JSAPI 支付使用公众号 AppID

POST /api/h5/orders/:id/wechat-pay/jsapi
Authorization: Bearer {token}
Content-Type: application/json

请求体

{
  "openid": "oUpF8uMuAJO_M2pxb1Q9zNjWeS6o"
}
字段 类型 必填 说明
openid string 用户在公众号下的 OpenID
  • THEN 系统使用配置中的 oa_app_id(公众号 AppID创建支付订单
  • THEN Payer OpenID 为用户在该公众号下的 OpenID

成功响应 200 OK(本次留桩,返回结构不变)

{
  "code": 0,
  "data": {
    "prepay_id": "wx26112221580621e9b071c00d9e093b0000",
    "pay_config": {
      "appId": "wx1234567890abcdef",
      "timeStamp": "1711411341",
      "nonceStr": "abc123",
      "package": "prepay_id=wx26112221580621e9b071c00d9e093b0000",
      "signType": "RSA",
      "paySign": "..."
    }
  },
  "msg": "success",
  "timestamp": "2026-03-16T10:00:00+08:00"
}

Scenario: 小程序支付使用小程序 AppID

  • WHEN 用户在小程序中发起支付
  • THEN 系统在调用 JSAPITransaction 时将 AppID 覆盖为配置中的 miniapp_app_id
  • THEN Payer OpenID 为用户在该小程序下的 OpenID

Scenario: 微信 H5 支付

POST /api/h5/orders/:id/wechat-pay/h5
Authorization: Bearer {token}
Content-Type: application/json

请求体

{
  "scene_info": {
    "payer_client_ip": "14.23.150.211",
    "h5_info": {
      "type": "Wap"
    }
  }
}
字段 类型 必填 说明
scene_info.payer_client_ip string 用户终端 IP
scene_info.h5_info.type string 场景类型:iOS / Android / Wap

成功响应 200 OK

{
  "code": 0,
  "data": {
    "h5_url": "https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=wx..."
  },
  "msg": "success",
  "timestamp": "2026-03-16T10:00:00+08:00"
}

Scenario: 配置缺失时系统正常启动

  • WHEN 系统启动时数据库中无微信参数配置或配置不完整
  • THEN 系统正常启动,支付功能降级为仅支持钱包/线下
  • THEN 系统记录 WARN 日志"无可用微信参数配置,第三方支付功能不可用"

Requirement: 微信支付回调按配置验签

系统 SHALL 接收并处理微信支付成功通知。回调验签 MUST 使用订单关联的支付配置(而非当前生效配置)。

Scenario: 接收到合法的支付成功通知

POST /api/callback/wechat-pay
Content-Type: 由微信服务器决定
无需认证
  • WHEN 微信回调端点收到支付成功通知
  • THEN 系统解析通知中的商户订单号(out_trade_no
  • THEN 按订单号前缀分发(ORD → 套餐订单,CRCH → 资产充值,ARCH → 代理充值)
  • THEN 查询对应表记录,通过 payment_config_id 加载对应的微信参数配置
  • THEN 使用该配置的凭证通过 PowerWeChat SDK 验证回调签名
  • THEN 调用对应 Service 的 HandlePaymentCallback
  • THEN 返回成功响应

成功响应

{
  "code": 0,
  "data": {
    "return_code": "SUCCESS"
  },
  "msg": "success",
  "timestamp": "2026-03-16T10:00:00+08:00"
}

Scenario: 订单关联的配置已被软删除

  • WHEN 回调到达,但 payment_config_id 对应的配置已被软删除
  • THEN 系统使用 GetByIDUnscoped 加载该配置(软删除不影响回调处理)
  • THEN 正常完成验签和订单处理

Scenario: 重复回调幂等处理

  • WHEN 微信多次发送同一订单的支付成功通知
  • THEN 系统通过幂等检查识别已支付,直接返回成功响应

Scenario: 回调签名验证失败

  • WHEN 签名无效或被篡改
  • THEN PowerWeChat SDK 自动拒绝,系统记录 ERROR 日志,返回 HTTP 400

Scenario: 订单号不存在

  • WHEN 回调中的商户订单号在系统中不存在
  • THEN 系统记录 ERROR 日志,返回失败响应