签名参数sign生成说明
签名生成的通用步骤如下:
第一步,设所有发送或者接收到的数据为集合M,将集合M内非空参数值的参数按照参数名ASCII码从小到大排序(字典序),使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串stringA。
特别注意以下重要规则:
参数名按ASCII码从小到大排序(字典序);
如果参数的值为空不参与传参和签名;
参数名区分大小写;
get 和 post 参数均参与签名(注意不要对 get 和 post 的参数进行urlencode);
sign 参数不参与签名;
根据HTTP协议要求,传递参数的值中如果存在特殊字符(如:&、@等),那么该值需要做URL Encoding,这样请求接收方才能接收到正确的参数值。这种情况下,待签名数据应该是原始值而不是encoding之后的值。例如:调用某接口需要对请求参数email进行数字签名,那么待签名数据应该是email=test@msn.com,而不是email=test%40msn.com。
第二步,在stringA最后拼接上“&key=KEY”得到stringSignTemp字符串,并对stringSignTemp进行MD5运算,再将得到的字符串所有字符转换为大写,得到sign值。
第三步,拼接sign签名,得到最终请求字符串。
签名算法示例:
假设传送的参数如下:
{
"corpid":"2s97120599f5",
"timestamp":1442401156,
"StudentInfo":{
"name": "张三",
"user_no": "xxx0001",
"gender": "1"
}
}
第一步:对参数按照key=value的格式,并按照参数名ASCII字典序排序如下:
$stringA = "StudentInfo[gender]=1&StudentInfo[name]=张三&StudentInfo[user_no]=xxx0001&corpid=2s97120599f5×tamp=1442401156";
第二步:拼接API密钥:
$stringSignTemp = "stringA&key=testtoken123456";
$sign = strtoupper(md5($stringSignTemp));
即$sign为:"F52D07BF1B237698D775C152C7BC2E36"
第三步:对请求的数据进行urlencode,并拼接sign签名:
$stringB = urlencode($stringA);
$param = $stringB . '&sign=F52D07BF1B237698D775C152C7BC2E36;
即完整的请求字符串为:
timestamp=1442401156&corpid=2s97120599f5&StudentInfo%5Bname%5D=%E5%BC%A0%E4%B8%89 &StudentInfo%5Buser_no%5D=xxx0001&StudentInfo%5Bgender%5D=1 &sign=F52D07BF1B237698D775C152C7BC2E36
注:学校key 仅作加密使用,为了保证数据安全请不要在请求参数中使用,并对学校key进行保密。
附:PHP签名算法
/**
* 生成签名
* @param array||string $signData 待签名的参数数组||经过urlencode后的参数字符串,可以使用http_build_query($array)函数将数组转成这样的请求字符串,不包含sign参数和key参数
* @param string $key
* @param int $type
* @return string
*/
function buildSign($signData, $key) {
//把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串
$arg = '';
$strSign = 'sign';
if (empty($signData) || empty($key)) {
return false;
}
if (is_string($signData)) {
$urlstr = urldecode($signData);
$urlarr = explode('&', $urlstr);
foreach($urlarr as $k => $v){
if (strpos($v, $strSign) !== false) {
unset($urlarr[$k]);
}
}
}
if (is_array($signData)) {
if (isset($signData[$strSign])) {
unset($signData[$strSign]);
}
$urlstr = urldecode(http_build_query($signData));
$urlarr = explode('&', $urlstr);
}
sort($urlarr, SORT_STRING);
$arg = implode('&', $urlarr);
$sign = strtoupper(md5($arg . '&key=' . $key));//把最终的字符串签名,获得签名结果
return $sign;
}