签名

计算post请求的sign参数

1.待签名字符串

请求数据者,post的参数(除apiKey、 *可选参数不参与签名), 将用来计算sign

对于如下的参数数组:

string[] parameters={
        "productId=1",
        "quantity=1", 
        "tel=135****2667",
        "collectedRemark="
	}

对数组里的每一个值从a 到z 的顺序排序,若遇到相同首字母,则看第二个字母, 以此类推。排序完成之后,再把所有数组值以“&”字符连接起来,如:

collectedremark=&productid=1&quantity=1&tel=135****2667

这串字符串便是待签名字符串

注意:

1.没有值的参数需传递空值,也需包含到待签名数据中,如上例中的collectedRemark;

2.根据HTTP协议要求,传递参数的值中如果存在特殊字符(如:&、@等),那么该值需要做URL Encoding,这样请求接收方才能接收到正确的参数值。待签名数据应该是原生值而不是encoding 之后的值。例如:调用某接口需要对请求参数email 进行数字签名,那么待签名数据应该是email=test@msn.com,而不是email=test%40msn.com;

3.待签名字符串全部字母转换为小写字母

2.签名运算

将待签名字符串后,需要把apiSecret直接拼接到待签名字符串前面,形成新的字符串,利用MD5的签名函数对这个新的字符串进行签名运算,并将签名结果字符串全部字母转换为大写字母。得到的字符串赋值给sign。

3.范例:PHP 签名
//调用此函数提供接口所有参数,将生成用于post的参数串$parmstring,同时生成签名字符串$sign,并进行远程请求返回输出内容
//type 1:json 2:txt
function build_parm_sign($parms, $typ=1, $reqURI="", $formMethod = "GET")
{
    //$parms格式为 array("s"=>是否参与签名true/false,"v"=>值)
    $parms["apiKey"] = array("s"=>false,"v"=>$this->apiKey);

    ksort($parms);
    $this->parmstring = '';
		
    $reqParams = array();
    $signParams = array();
		
    foreach($parms as $key => $value){
        $reqParams["$key"] = urlencode($value["v"]);
			
        if(!$value["s"]) continue;
        $signParams[] = "$key=$value[v]";
    }
		
    $signstring = $this->apiSecret . strtolower(implode("&",$signParams));
    $sign = strtoupper(md5($signstring));
		
    $reqParams["sign"] = "$sign";
		
    $t = new transport(-1,5,-1,true);
    $realUrl = empty($reqURI) ? $this->api_url : $reqURI;
    $respon = $t->request($realUrl, $reqParams, $formMethod);
		
    if($respon)
    {
        switch ($typ)
        {
            case 1: return json_decode($respon["body"],true);
            case 2: return $respon["body"];
        }
			
    }
    else
        return array('ErrorCode'=>'999','Success'=>false,'Message'=>'服务器调用失败API级错误,'.$realUrl);
}
            
4.范例:C# 签名
/// <summary>
/// 制造签名
/// </summary>
/// <param name="parms"></param>
/// <param name="queryString"></param>
/// <returns>签名后字符串</returns>
private string BuildSign(NameValueCollection parms, out string queryString)
{
    queryString = "";
    string[] keys = parms.AllKeys;
    ArrayList al = new ArrayList();
    Array.Sort(keys);

    foreach (string a in keys)
    {
        if (!string.IsNullOrEmpty(queryString)) queryString += "&";
        queryString += $"{a}=" + (string.IsNullOrEmpty(parms[a]) ? "" : HttpUtility.UrlEncode(parms[a]));
        al.Add($"{a}={parms[a]}");
    }

    return EncryptHelper.MD5Encode(ApiSecret + string.Join("&", al.ToArray()).ToLower());
}