All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 46s
5.4 KiB
5.4 KiB
ADDED Requirements
Requirement: 富友支付公众号 JSAPI 下单
系统 SHALL 支持通过富友支付 wxPreCreate 接口发起微信公众号 JSAPI 支付。
本次留桩:
FuiouPayJSAPI方法在 Service 层定义,但实际调用第三方获取支付参数的逻辑暂不实现,返回"富友支付发起暂未实现"错误。pkg/fuiou/SDK 包完整实现。
Scenario: 公众号 JSAPI 下单成功
- WHEN 系统调用富友
wxPreCreate接口trade_type=JSAPIsub_appid=公众号AppID(从tb_wechat_config.oa_app_id读取)sub_openid=用户公众号OpenID- 传入订单号、金额(分)、商品描述、终端 IP、回调地址
- THEN 富友返回
result_code=000000,包含支付参数
富友返回支付参数结构
{
"sdk_appid": "wx1234567890abcdef",
"sdk_timestamp": "1711411341",
"sdk_noncestr": "abc123def456",
"sdk_prepayid": "wx26112221580621e9b071c00d9e093b0000",
"sdk_package": "Sign=WXPay",
"sdk_signtype": "RSA",
"sdk_paysign": "..."
}
- THEN 系统将支付参数返回给前端,前端调用
WeixinJSBridge.invoke('getBrandWCPayRequest', ...)拉起支付
Scenario: 公众号 JSAPI 下单失败
- WHEN 富友返回
result_code非000000 - THEN 系统记录 ERROR 日志(订单号、错误码、错误消息)
- THEN 系统返回错误
{
"code": 1173,
"data": null,
"msg": "支付发起失败,请重试",
"timestamp": "2026-03-16T10:00:00+08:00"
}
Requirement: 富友支付小程序下单
系统 SHALL 支持通过富友支付 wxPreCreate 接口发起微信小程序支付。
Scenario: 小程序下单成功
- WHEN 系统调用富友
wxPreCreate接口trade_type=LETPAYsub_appid=小程序AppID(从tb_wechat_config.miniapp_app_id读取)sub_openid=用户小程序OpenID
- THEN 富友返回
result_code=000000,包含支付参数 - THEN 系统将支付参数返回给前端,前端调用
wx.requestPayment(...)拉起支付
Scenario: 小程序下单缺少 OpenID
- WHEN 系统发起小程序支付但未传入
sub_openid - THEN 系统返回错误
{
"code": 1001,
"data": null,
"msg": "小程序支付必须提供用户 OpenID",
"timestamp": "2026-03-16T10:00:00+08:00"
}
Requirement: 富友支付回调处理
系统 SHALL 接收并处理富友支付成功回调通知,验证签名后更新订单/充值状态。
Scenario: 接收到合法的支付成功回调
POST /api/callback/fuiou-pay
Content-Type: application/x-www-form-urlencoded
无需认证
请求体格式:req=<双重URL编码的GBK XML>
- THEN 系统将请求体从 GBK 转换为 UTF-8
- THEN 系统解析 XML 格式的回调数据
- THEN 系统根据
mchnt_order_no判断订单类型:ORD开头 → 套餐订单 → 查询tb_orderCRCH开头 → 资产充值 → 查询tb_asset_recharge_recordARCH开头 → 代理充值 → 查询tb_agent_recharge_record
- THEN 通过记录的
payment_config_id加载对应的富友配置 - THEN 使用该配置的富友公钥验证 RSA 签名
- THEN 验证
result_code=000000且金额匹配 - THEN 调用对应 Service 的 HandlePaymentCallback
- THEN 返回成功 XML 响应(GBK 编码)
成功响应
<?xml version="1.0" encoding="GBK"?>
<xml>
<result_code>000000</result_code>
<result_msg>success</result_msg>
</xml>
Scenario: 回调签名验证失败
- WHEN 富友回调的 RSA 签名与本地计算不匹配
- THEN 系统记录 ERROR 日志
- THEN 返回失败 XML 响应
<?xml version="1.0" encoding="GBK"?>
<xml>
<result_code>999999</result_code>
<result_msg>signature verification failed</result_msg>
</xml>
Scenario: 回调订单号不存在
- WHEN
mchnt_order_no在系统中不存在 - THEN 系统记录 ERROR 日志,返回失败 XML 响应
Scenario: 重复回调幂等处理
- WHEN 富友对同一订单多次发送支付成功回调
- THEN 系统识别已支付,直接返回成功 XML 响应
Requirement: 富友 XML 通信协议
系统 SHALL 正确处理富友支付的 XML + GBK 编码通信协议。
Scenario: 请求编码
- WHEN 系统向富友发送请求
- THEN 请求体为 XML 格式,GBK 编码声明
- THEN XML 内容经 GBK 编码后进行两次 URL 编码
- THEN 以
req=<encoded_xml>的 form 格式发送
Scenario: 响应解码
- WHEN 系统接收富友响应
- THEN 先进行 URL 解码
- THEN 将 GBK 内容转换为 UTF-8
- THEN 替换 XML 声明中的
encoding="GBK"为encoding="UTF-8" - THEN 解析 XML 到结构体
Requirement: 富友 RSA 签名算法
系统 SHALL 实现富友支付的 RSA + MD5 签名验签算法。
Scenario: 生成请求签名
- WHEN 系统需要对富友请求签名
- THEN 提取所有非空字段(排除
sign和reserved_开头字段) - THEN 按字典序排列为
key=value&key=value格式 - THEN 将签名原文转换为 GBK 编码
- THEN 计算 MD5 哈希
- THEN 使用商户私钥对 MD5 哈希进行 RSA PKCS1v15 签名
- THEN 对签名结果进行 Base64 编码
Scenario: 验证回调签名
- WHEN 系统需要验证富友回调签名
- THEN 使用相同算法计算签名原文的 MD5 哈希
- THEN 使用富友公钥对回调中的
sign字段进行 RSA PKCS1v15 验签