第三方应用开发 服务端API 收银台 收款工具 签名算法
签名算法
最后更新:2023/03/20
可联系渠道经理采购或代理智慧硬件接口已支持设备 联系渠道经理
签名算法
最后更新:2023/03/20

为保证调用者不可伪造,数据不可被篡改、重放等,支付相关接口需要做签名处理。

部分语言签名算法代码下载


签名生成的通用步骤如下:
第一步, 将所有非空参数构造成键值对(即key=value)集合,按照ASCII码从小到大排序(字典序),最后拼接成字符串stringA。以下重要规则:

将“键值对”整体按照ASCII码从小到大排序(字典序);
如果参数的值为空不参与签名;
传送的sig参数不参与签名,将生成的签名与该sig值作校验;
区分大小写;
接口可能增加字段,验证签名时必须支持增加的扩展字段;

第二步, 对stringA以服务商的支付密钥为key进行HMAC-SHA256运算(支付密钥获取方法:工作台->企业微信服务商助手->工具->收银台->收银台API调用密钥),并进行base64编码,得到sig。
第三步, 将计算得到的sig与请求中的sig对比,如果不相同,表示该请求可能被篡改。


示例1: (适用于简单JSON结构的API请求)

假设服务商的支付密钥为:

secret = "at23pxnPBNQY3JiA8N5U1gabiQqxZwqH_Gihg7a_wrULmlOPVP-iiRjv9JWYPrDk"

需要POST的参数如下:

{
        "orderid" : "ord7",
        "buyer_corpid": "ww66302cfadbdd3c64",
        "buyer_userid" : "invitetest",
        "product_id": "product_id_xxx",
        "product_name": "product_name_xxx",
        "product_detail": "product_detail_xxx",
        "unit_name": "台",
        "unit_price": 1,
        "num": 3,
        "nonce_str" : "129031823",
        "ts": 1548302135,
        "sig": "mPOwVW/vQ74xN+b+Yu1KMa9RrmhKJaJjAtXHTof+EpU="
}

第一步: 参数按照key=value的格式构造"键值对"集合:

orderid=ord7
buyer_corpid=ww66302cfadbdd3c64
buyer_userid=invitetest
product_id=product_id_xxx
product_name=product_name_xxx
product_detail=product_detail_xxx
unit_name=
unit_price=1
num=3
nonce_str=129031823
ts=1548302135
注意: sig不参与签名。

第二步 将集合按照字典序排序:

buyer_corpid=ww66302cfadbdd3c64
buyer_userid=invitetest
nonce_str=129031823
num=3
orderid=ord7
product_detail=product_detail_xxx
product_id=product_id_xxx
product_name=product_name_xxx
ts=1548302135
unit_name=
unit_price=1

第三步: 拼接字符串:

stringA = "buyer_corpid=ww66302cfadbdd3c64&buyer_userid=invitetest&nonce_str=129031823&num=3&orderid=ord7&product_detail=product_detail_xxx&product_id=product_id_xxx&product_name=product_name_xxx&ts=1548302135&unit_name=台&unit_price=1"

第四步: 以secret为key做hash并base64编码得到签名:

sig = base64_encode(hash_hmac("sha256", stringA, secret))

最终得到签名: sig = "/WTXl/L2kJCYKJE5yY2JZvPq3rUjFf/pf39UhyJ2GUo="

而接收到的签名为 "sig": "mPOwVW/vQ74xN+b+Yu1KMa9RrmhKJaJjAtXHTof+EpU=",两者不一致,那么很有可能是被第三者篡改数据了 !


举例2: (适用于复杂JSON结构的API请求)

如果节点是元组,那么不直接参与签名,而是递归地用其子节点进行签名,此处简单举例说明。
假设需要POST的参数如下:

{
	"orderid": "i3khJ4dMv3",
	"order_type": 1,
	"credit_order_list": [
		{
			"credit_orderid": "CREDIT_ORDERID_1",
			"unit_price": 100000,
			"num": 1
		},
		{
			"credit_orderid": "CREDIT_ORDERID_2",
			"unit_price": 90000,
			"num": 2
		}
	],
	"appid": 2,
	"buyer_corpid": "wwfedd7e5292d63a35",
	"buyer_userid": "zhangsan",
	"product_id": "xxxxxxxxxxx",
	"product_name": "xxxxxxxxxxxxx",
	"product_detail": "xxxxxxxxxxxx",
	"unit_name": "台",
	"nonce_str": "1287319372",
	"ts": 1547719184,
	"sig": "xxxxxxxxxxxxxxxxxxxxxxxxxxx"
}

第一步: 参数按照key=value的格式构造"键值对"集合。

orderid=i3khJ4dMv3
order_type=1
credit_orderid=CREDIT_ORDERID_1
unit_price=100000
num=1
credit_orderid=CREDIT_ORDERID_2
unit_price=90000
num=2
appid=2
buyer_corpid=wwfedd7e5292d63a35
buyer_userid=zhangsan
product_id=xxxxxxxxxxx
product_name=xxxxxxxxxxxxx
product_detail=xxxxxxxxxxxx
unit_name=
nonce_str=1287319372
ts=1547719184
sig=xxxxxxxxxxxxxxxxxxxxxxxxxxx

注意: credit_order_list 是一个元组,应该以他的子节点(多个unit_price/num)签名

第二步 将集合按照字典序排序

appid=2
buyer_corpid=wwfedd7e5292d63a35
buyer_userid=zhangsan
credit_orderid=CREDIT_ORDERID_1
credit_orderid=CREDIT_ORDERID_2
nonce_str=1287319372
num=1
num=2
order_type=1
orderid=i3khJ4dMv3
product_detail=xxxxxxxxxxxx
product_id=xxxxxxxxxxx
product_name=xxxxxxxxxxxxx
ts=1547719184
unit_name=
unit_price=100000
unit_price=90000

第三步,第四步与上述示例1一致,此处不做说明。


随机字符串生成算法

部分API接口协议中包含字段nonce_str,主要保证签名不可预测及防重放攻击。我们推荐生成随机字符串算法如下:调用随机数函数生成,将得到的值转换为字符串。

上一篇
获取收款订单详情
下一篇
获取发票列表