接口签名
签名说明
1. 签名机制
采用 RSA 签名保证数据安全。开发者生成密钥对并与开放平台交换公钥,通讯时请求方使用己方私钥签名,响应方使用对方公钥验签。
2. 生成签名密钥
代码生成版:推荐使用命令行方式生成 RSA 公私钥,示例如下:
输入 openssl 进入 OpenSSL>模式 #生成私钥,2048 是密钥长度
OpenSSL> genrsa -out rsa_private_key.pem 2048 #将私钥转换成 PKCS8 格式(C#对应 PKCS1 格式)
OpenSSL> pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt -out rsa_private_key_pkcs8.pem #根据生成的私钥生成公钥
OpenSSL> rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem #退出
OpenSSL> exit #在当前目录下可以找到对应的公钥和私钥文件
提示
生成的私钥贵司自行保存好;公钥发到群里,相关同事会给贵司配置参数,方便后续的交易操作。
3. 请求参数加签步骤
(1)步骤:
步骤一:待签名的请求参数,设为数据 D;
步骤二:对请求参数 D,进行参数名 ASCII 码从小到大排序,得到排序后的字符(去前后空格);
步骤三:加签——签名=RSA 签名方法("排序后字符串","自己生成私钥");
步骤四:得到签名后的报文。
请求域名
请联系技术人员获取
请求方式
POST
签名示例
假设传送的参数如下:
| 字段名 | 变量名 | 必填 | 类型 | 示例值 |
|---|---|---|---|---|
| appId | 是 | String(32) | 开发者Id | mf20190821aq1tzmv65j |
| version | 是 | String(32) | 版本号,目前固定为1.0 | 1.0 |
| nonceStr | 是 | String(32) | 请求随机串 | 3BEC0C930BF1AFEB40B4A08C8FB |
| timestamp | 是 | String(32) | Unix时间戳 | 1573428705 |
| signType | 是 | String(32) | 加密方式 | RSA | MD5 |
| bizContent | 是 | JSON | 业务参数 | {"merchant_no":"001001F888888"} |
| sign | 是 | String(32) | 签名 |
MD5 签名
第一步: 将请求参数中除 sign 外的多个键值对,按照 key的ASCII码表顺序排序后,拼接成key=value 的格式,并在最后拼接key
stringA ="appId=fy20190821aq1tzmv65j&bizContent={"merchant_no":"001001F888888"}&nonceStr=3BEC0C930BF1AFEB40B4A08C8FB&signType=RSA×tamp=1573428705&version=1.0&key=1234567890";
第二步: 进行MD5签名计算,然后全部转成大写
sign = md5(stringA).toUpperCase();
第三步: 得到最终发送的数据:
{
"appId": "fy20190821aq1tzmv65j",
"nonceStr": "3BEC0C930BF1AFEB40B4A08C8FB",
"timestamp": "1573428705",
"version": "1.0",
"signType": "MD5",
"bizContent": { "merchant_no": "001001F888888" },
"sign": "AAAAAAAAAAAAAAAAAAAAAAAA"
}
RSA 签名
第一步: 将请求参数中除 sign 外的多个键值对,按照 key=value 的格式,并按照参数名 ASCII 字典序排序如下:
stringA =
"appId=fy20190821aq1tzmv65j&bizContent={"merchant_no":"001001F888888"}&nonceStr=3BEC0C930BF1AFEB40B4A08C8FB&signType=RSA×tamp=1573428705&version=1.0";
第二步: 使用私钥进行签名计算
openssl_sign($data, $stringA, $privateKey, OPENSSL_ALGO_SHA256);
return base64_encode($signature); // 将签名编码为 Base64
第三步: 得到最终发送的数据:
{
"appId": "fy20190821aq1tzmv65j",
"nonceStr": "3BEC0C930BF1AFEB40B4A08C8FB",
"timestamp": "1573428705",
"version": "1.0",
"signType": "RSA",
"bizContent": { "merchant_no": "001001F888888" },
"sign": "hASzWUheJyT9q0Ikd+pjdZ+ee4ZG2umKdbY7JSttZs5+64TQTOvHuiGEfdqpFEmwoPUVy2yuwy6+9FzesjWG5lERqogpRtjiHFfznBUYSaDv2GBQIWUMejB0y+3EveNRqIuHbYZvqYXAjpmQc+dSQPBcJwC/X6D53nQfU/uUI3rKujatl6bDyNeVcomhael0nyulh++SY1g9TQPw1deg5VQ1ai2mgs5uGvIrX8grJQbRuNQuf/Dh0TXPvJAoUSqxHIemiC2Hwfo+MOhxlkvNYrnYVW4WvLIl4km7mZqKnVAHVVgN1G9LnqAFgxh1eObqwfz0hw+d79ypjjBJBEAd5Q=="
}
第三步: 发送请求,请求成功,得到响应数据包,开发者需要使用开放平台提供的公钥进行验签。
{
"code": 200101,
"message": "等待用户输入密码",
"data": { "merchant_no": "001001F888888" },
"sign": "hASzWUheJyT9q0Ikd+pjdZ+ee4ZG2umKdbY7JSttZs5+64TQTOvHuiGEfdqpFEmwoPUVy2yuwy6+9FzesjWG5lERqogpRtjiHFfznBUYSaDv2GBQIWUMejB0y+3EveNRqIuHbYZ"
}
| 变量名 | 必填 | 类型 | 说明 |
|---|---|---|---|
| code | 是 | String(64) | 000000 支付成功 否则为错误码 |
| message | 否 | String(256) | 如非空,为错误原因 |
| data | 是 | JSON | 返回的业务参数 |
| sign | 是 | String | 响应签名 |