服务器签名文件,服务端签名

目标

签名方案只验证 服务端签名前的支付数据 和 tt.pay 发送到字节跳动后端的支付数据 的一致性(因而,具体字段有哪些,以及字段的值是否正确并不由签名验证)

生成签名规则

Key 筛选

去掉请求参数中的字节类型字段(如文件、字节流)、sign 与 risk_info 字段、value 为空的字段(某些接口请求参数中特殊标明不参与签名的字段也需要去掉)。

K-V 排序和拼接

把筛选后的 k-v 集合按照 key 的 ASCII 码升序排序,例如:a, a1, abc, abcd, abce, abd, b1, ba

k-v 按照 key=value 的格式链接,并且按照 key 排序使用 & 连接成一个字符串,生成待签名字符串

MD5 加签MD5(待签名字符串 + app_secret); // 待签名字符串 + app_secret 是字符串直接拼接,待签名字符串在前,中间没有连接符。

完整流程

例如下面是我们待验签的 orderInfo:{

app_id: '800000000001',

merchant_id: '1900000001',

timestamp: 1570694312,

sign_type: 'MD5',

out_order_no: '201900000000000001',

total_amount: 1,

product_code: 'pay',

payment_type: 'direct',

trade_type: 'H5',

version: '2.0',

currency: 'CNY',

subject: '测试订单',

body: '测试订单',

uid: '0000000000000001',

trade_time: 1570585744,

valid_time: 300,

notify_url: '',

risk_info: '{"ip":"120.230.0.0"}',

wx_type: 'MWEB',

wx_url: 'https://wx.tenpay.com/xxx',

alipay_url: 'app_id=2019000000000006&biz_content=xxxx'

}

则待签名字符串 unsigned_str 为:alipay_url=app_id=2019000000000006&biz_content=xxxx&app_id=800000000001&body=测试订单&currency=CNY&merchant_id=1900000001&out_order_no=201900000000000001&payment_type=direct&product_code=pay&sign_type=MD5&subject=测试订单&timestamp=1570694312&total_amount=1&trade_time=1570585744&trade_type=H5&uid=0000000000000001&valid_time=300&version=2.0&wx_type=MWEB&wx_url=https://wx.tenpay.com/xxx

若你的 app_secret 是 'a',那么带入上述 unsigned_str,最终 MD5(unsigned_str + app_secret) 后签名字符串 signed_str 应为:0f1e3358a9898d7c4c6c23740251808a验证:你可以在你的验签方法里用上面的 orderInfo 和 app_secret 数据测试,验证与我们给出的 unsigned_str 和 signed_str 是否一致保持一致:通过上述方式生成签名 sign 之后,将该 sign 字段挂在 orderInfo 上并最终透传至前端 tt.pay,传递过程中请不要增删或修改任何字段(保持服务端签名前的支付数据和 tt.pay 发送到字节跳动后端的支付数据一致),否则会导致签名检验不通过

签名代码示例(以 Node 为例)const crypto = require("crypto");

const createSign = (params, appSecret) => {

const paramKeys = Object.keys(params).sort();

let signStr = "";

paramKeys.forEach(key => {

let value = params[key];

// 空值,risk_info, sign 不参与签名

if (!value || ["risk_info", "sign"].indexOf(key) >= 0) {

return;

}

if (signStr.length > 0) {

signStr += "&";

}

if (typeof value === "object") {

value = JSON.stringify(value);

}

signStr += key + "=" + value;

});

signStr += `${appSecret}`;

console.log("signStr:", signStr);

const md5 = crypto.createHash("md5");

const sign = md5.update(signStr).digest("hex");

return sign;

};

签名验证失败排查方案服务端:服务端生成签名方式可能有误,请参考上方「完整流程」中的 orderInfo 与 app_secret 代入你的签名方法,验证与我们给出的预期 unsigned_str 和 signed_str 是否一致,不一致将导致签名验证失败

小程序端:请保证带有 sign 签名的 orderInfo 由服务端返回且与 tt.pay 中传入的 orderInfo 完全一致,不一致将导致签名验证失败

反馈:若上面两者已经确认无误,但签名验证依然无法通过,请在开发者社区反馈,反馈中请提供线上报 CD0025 失败订单的 unsigned_str

各语言签名实现

可参考以下语言 Demo 中签名的实现

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值