Appearance
签名与安全
亿付通建议把签名能力封装成独立模块,避免每个接口重复实现。
通用规则
- 请求和响应统一使用
UTF-8编码。 - 参与签名的字段应去掉空值与签名字段本身。
- 按参数名 ASCII 码升序排序后再拼接签名串。
- 如果接口返回
data,建议同时对data和顶层状态码做验签校验。 - 通知接口必须先验签,再做业务处理,最后返回结果。
MD5 签名思路
参考网关类文档的常见规则,MD5 模式一般按以下方式处理:
- 对非空字段按 ASCII 升序排序。
- 按
key=value形式用&拼接。 - 在末尾追加
&key=商户密钥。 - 对结果做 MD5 并转成大写。
Node.js 示例
js
import crypto from 'node:crypto'
function buildSign(params, apiKey) {
const content = Object.keys(params)
.filter((key) => key !== 'sign' && params[key] !== '' && params[key] !== undefined && params[key] !== null)
.sort()
.map((key) => `${key}=${params[key]}`)
.join('&')
return crypto.createHash('md5').update(`${content}&key=${apiKey}`, 'utf8').digest('hex').toUpperCase()
}RSA2 签名思路
若商户后台启用了 RSA2,建议使用私钥做签名、公钥做验签。签名串仍然建议沿用“字段过滤 + ASCII 升序 + key=value 拼接”的基础规则。
js
import crypto from 'node:crypto'
function buildRsa2Sign(params, privateKey) {
const content = Object.keys(params)
.filter((key) => key !== 'sign' && params[key] !== '' && params[key] !== undefined && params[key] !== null)
.sort()
.map((key) => `${key}=${params[key]}`)
.join('&')
const signer = crypto.createSign('RSA-SHA256')
signer.update(content, 'utf8')
signer.end()
return signer.sign(privateKey, 'base64')
}验签建议
- 业务网关响应时,优先检查
code、msg、data是否完整。 - 对通知参数使用与请求相同的签名算法重新计算签名。
- 当签名不一致时直接记录日志并返回失败,不进入业务逻辑。
- 对所有通知单号建立幂等锁或唯一键,避免重复处理。
安全建议
- 生产环境优先使用
HTTPS。 - 商户密钥不要写死在前端。
- 对回调来源做 IP 白名单或网关层鉴权。
- 记录完整请求日志时,注意脱敏账号、姓名、银行卡号等敏感字段。
注意
不同平台实例可能会在以下项上略有差异,投产前需以商户后台和正式接口规范为准:
reqTime使用秒级还是毫秒级时间戳- 仅支持
MD5,还是同时支持RSA2 - 顶层字段参与签名还是仅业务字段参与签名
- 响应是否对
data再次单独签名