文档信息#
沙箱/正式环境网关说明#
I. 基础规范#
沙盒环境对接#
沙盒环境接口参数,返回参数,签名规则,数据加密规则与生产一致。沙盒后台可以手动回调,用于帮助快速接入API认证#
本系统默认采用 App ID + App Secret 的 HMAC-SHA256 签名机制,并默认启用 aes-gcm-v1 请求体加密1.
App ID 认证:每个请求必须在 Header 中携带 App ID(用于标识商户编码)
2.
HMAC-SHA256 签名(默认):使用商户 App Secret 对请求进行签名,保证消息完整性、防止篡改
3.
AES-GCM-V1 加密:请求体默认使用 aes-gcm-v1(AES-256-GCM)算法加密,保障数据保密性,特殊场景可申请明文模式
设计要点#
传输层必须用 TLS(HTTPS):所有数据通过 HTTPS 传输,避免中间人窃听
App ID 用作标识(public):App ID 是公开的,用于标识商户编码
App Secret 只用于服务器端签名:App Secret 绝不放到客户端代码仓库或前端
签名(HMAC-SHA256):用于保证消息完整性与认证,防止篡改与伪造
请求体加密(AES-GCM-V1):保护敏感字段/整个请求体,可在双方确认后关闭
防重放攻击:在签名中包含 timestamp + nonce + 请求路径 + HTTP method + body
幂等与重试:在签名中包含请求ID或nonce,并在服务端记录短期nonce白名单/黑名单
| Header名称 | 必填 | 说明 | 示例 |
|---|
X-App-Id | 是 | 商户编码 | M20253504WTEX |
X-Ts | 是 | Unix时间戳(毫秒,13位数字),服务器允许 ±300秒 | 1699132800000 |
X-Nonce | 是 | 随机字符串(用于防重放) | abcd1234efgh |
X-Sign | 是 | HMAC-SHA256签名值(Base64编码) | a1b2c3d4e5f6... |
Content-Type | 是 | 请求体类型:application/json(明文)或 application/octet-stream(加密) | application/json |
X-Enc | 是 | 加密方式:aes-gcm-v1, none明文方式(默认), 平台默认按照商户配置加密方式,如果没有配置,就默认不加密,如果请求头传了加密,则会按照请求头方式解密 | none |
密钥获取与配置#
步骤1:获取App ID、App Secret 和 apiDataKey登录商户后台 → 系统设置 → 支付基础配置,获取:平台公钥:是apiDataKey用于 AES 加密
App Secret 和 apiDataKey 仅显示一次,请妥善保管
应存储在安全的位置(如 KMS/Vault),不要硬编码在代码中
浏览 器/移动端不应持久保存长期密钥,建议后端对接或使用短期 token(OAuth2、JWT)模式
请求签名#
签名原理#
HMAC-SHA256签名使用商户App Secret对请求进行HMAC-SHA256签名,流程如下:1.
构建待签名字符串:按照固定格式拼接 HTTP_METHOD + "\n" + REQUEST_PATH + "\n" + X-Ts + "\n" + X-Nonce + "\n" + Base64(body_bytes)
2.
REQUEST_PATH里的请求参数要按key升序排序,Nonce作为iv
3.
计算HMAC-SHA256:使用App Secret作为密钥,对待签名字符串进行HMAC-SHA256计算
4.
Base64编码:将HMAC结果进行Base64编码
5.
添加请求头:X-Ts、X-Nonce、X-Sign
签名算法规范#
signing_string = HTTP_METHOD + "\n" +
PATH?QUERY + "\n" + // 包括QUERY(按字典序排序)
X-Ts + "\n" +
X-Nonce + "\n" +
Base64(body_bytes) // 空 body 用空字符串
使用 HMAC-SHA256 算法(不要使用 MD5、SHA1 或可被 length-extension 攻击的方式)
签名结果使用 Base64 编码(统一使用 Base64)
重要:签名中的 body 始终使用加密前的原始 JSON 字符串,与 X-Enc 的值无关当 X-Enc = none 时:使用原始 JSON 字符串
当 X-Enc = aes-gcm-v1 时:仍然使用加密前的原始 JSON 字符串(不是加密后的 Base64)
平台验证签名(服务器端)#
平台使用商户App Secret验证签名,验证流程如下:1.
检查X-App-Id:验证App ID是否存在且有效,加载对应的App Secret(从安全存储,如KMS/Vault)
2.
验证X-Ts:检查时间戳是否在允许时间窗口内(例如±300秒)
3.
检查X-Nonce:验证nonce是否已短期使用(防重放),若已使用则拒绝。将nonce保存到缓存(如Redis)并设置短期过期(例如5分钟)
4.
解密请求体(如果 X-Enc = aes-gcm-v1):先解密请求体得到明文
5.
重新构建待签名字符串:使用解密后的明文 body按照与客户端相同的规则构建签名字符串
6.
验证签名:使用App Secret计 算HMAC-SHA256,与请求中的签名值进行常量时间比较(constant-time compare)
签名验证使用解密后的明文 body,而不是加密后的 body
客户端计算签名时也应该使用明文 body,即使请求体是加密的
消息体加密#
平台默认按照商户配置加密方式,如果没有配置,就默认不加密,如果请求头传了加密,则会按照请求头方式解密(AES-GCM-V1,默认不开启)加密数据格式#
[IV (12字节)] + [实际密文] + [authTag (16字节)]
authTag(认证标签):16 字节(128 位),由 AES-GCM 自动生成,用于验证数据完整性和真实性
IV 不需要单独传递,它包含在加密后的数据中(前 12 字节)
加密后的数据使用原始数据进行发送,不需要base64编码
Content-Type 设置为 application/octet-stream(二进制数据)
默认不加密;若双方确认使用明文,请将 X-Enc 设置为 none 并确保网络环境安全
加密/解密使用 aes-gcm-v1,关联数据(AAD)为 HMAC-SHA256(appId, Base64.encode(aesKey)) 的十六进制字符串
Content-Type:加密时使用 application/octet-stream,明文时使用 application/json
幂等性保证#
创建交易:通过 order_no(商户订单号)保证幂等性。相同 order_no 的重复请求返回相同结果,不会重复创建交易。
发起代付:通过 order_no(商户代付订单号)保证幂等性。相同 order_no 的重复请求返回相同结果,不会重复发起代付。
II. 代收代付流程#
Modified at 2026-03-03 18:04:01