API请求签名生成文档

概述


大众点评API需要通过签名来访问,签名的过程是将请求参数串以及APP密钥根据一定签名算法生成的签名值,作为新的请求参数从而提高访问过程中的防篡改性。签名值的生成详见下面的描述。

 

URL签名生成规则


所有大众点评API的有效访问URL包括以下三个部分:
1. 资源访问路径,如/v1/deal/find_deals;
2. 请求参数:即API对应所需的参数名和参数值param=value,多个请求参数间用&连接
   如deal_id=1-85462&appkey=00000;
3. 签名串,由签名算法生成

 

签名算法如下:
1. 对除appkey以外的所有请求参数进行字典升序排列;
2. 将以上排序后的参数表进行字符串连接,如key1value1key2value2key3value3...keyNvalueN;
3. 将app key作为前缀,将app secret作为后缀,对该字符串进行SHA-1计算,并转换成16进制编码;
4. 转换为全大写形式后即获得签名串

 

签名串获得后,将其作为sign参数附加到对应的URL中,即可正常访问API。

 

  • 注意:请保证HTTP请求数据编码务必为UTF-8格式,URL也务必为UTF-8编码格式。
  • 具体调用示例请参见https://github.com/dianping/dianping-open-sdk,包括Java/Python/PHP/Javascript/iOS/Android/C#。
  • Java生成签名示例(Android请另行参考这里

    				     // 定义申请获得的appKey和appSecret
    				     String appkey = "XXXXXXXX";
    				     String secret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
    				     String apiUrl = "http://api.dianping.com/v1/business/find_businesses";
    				     
    				     // 创建参数表
    				     Map<String, String> paramMap = new HashMap<String, String>();
    				     paramMap.put("format", "json");
    				     paramMap.put("city", "上海");
    				     paramMap.put("latitude", "31.21524");
    				     paramMap.put("longitude", "121.420033");
    				     paramMap.put("category", "美食");
    				     paramMap.put("region", "长宁区");
    				     paramMap.put("limit", "20");
    				     paramMap.put("radius", "2000");
    				     paramMap.put("offset_type", "0");
    				     paramMap.put("has_coupon", "1");
    				     paramMap.put("has_deal", "1");
    				     paramMap.put("keyword", "泰国菜");
    				     paramMap.put("sort", "7");
    				 
    				     // 对参数名进行字典排序
    				     String[] keyArray = paramMap.keySet().toArray(new String[0]);
    				     Arrays.sort(keyArray);
    				 
    				     // 拼接有序的参数名-值串
    				     StringBuilder stringBuilder = new StringBuilder();
    				     stringBuilder.append(appkey);
    				     for (String key : keyArray)
    				     {
    				         stringBuilder.append(key).append(paramMap.get(key));
    				     }
    				     
    				     stringBuilder.append(secret);
    				     String codes = stringBuilder.toString();
    				     
    				     // 字符串连接示例
    				     // XXXXXXXXcategory美食city上海formatjsonhas_coupon1has_deal1keyword泰国菜latitude31.21524limit20longitude121.420033offset_type0radius2000region长宁区sort7XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    				     
    				     // SHA-1编码, 这里使用的是Apache codec,即可获得签名(shaHex()会首先将中文转换为UTF8编码然后进行sha1计算,使用其他的工具包请注意UTF8编码转换)
    				     /*
    				      * 以下sha1签名代码效果等同
    				      * byte[] sha = org.apache.commons.codec.digest.DigestUtils.sha(org.apache.commons.codec.binary.StringUtils.getBytesUtf8(codes));
    				      *  String sign = org.apache.commons.codec.binary.Hex.encodeHexString(sha).toUpperCase(); 
    				      */
    				     String sign = org.apache.commons.codec.digest.DigestUtils.shaHex(codes).toUpperCase();
    				     
    				     //签名示例 
    				     //7D78381BC58E1DB1DBA4BD965916FE6B4D5DC892
    					

    JavaScript生成签名示例

    			     // 定义申请获得的appKey和appSecret
    			     var appkey = "XXXXXXXX";
    			     var secret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
    			 
    			     // 创建参数表
    			     var param = {};
    			     param["city"]="上海";
    			     param["latitude"]="31.21524";
    			     param["longitude"]="121.420033";
    			     param["category"]="美食";
    			     param["region"]="长宁区";
    			     param["limit"]="20";
    			     param["radius"]="2000";
    			     param["offset_type"]="2";
    			     param["has_coupon"]="1";
    			     param["has_deal"]="1";
    			     param["keyword"]="泰国菜";
    			     param["sort"]="7";
    				 
    			     // 对参数名进行字典排序
    			     var array = new Array();
    			     for(var key in param)
    			     {
    			    	 array.push(key);
    			     }
    			     array.sort();
    			     
    			     // 拼接有序的参数名-值串
    			     var paramArray = new Array();
    			     paramArray.push(appkey);
    			     for(var index in array)
    			     {
    				    var key = array[index];
    				    paramArray.push(key + param[key]);
    			     }
    			     paramArray.push(secret);
    			     
    			     // 字符串连接示例
    			    // XXXXXXXXcategory美食city上海formatjsonhas_coupon1has_deal1keyword泰国菜latitude31.21524limit20longitude121.420033offset_type0radius2000region长宁区sort7XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    			     
    			     
    			     // SHA-1编码,并转换成大写,即可获得签名
    			     var shaSource = paramArray.join("");
    			     var sign = new String(toSHA1(shaSource)).toUpperCase();
    			     
    			     //签名示例 
    			    //7D78381BC58E1DB1DBA4BD965916FE6B4D5DC892
    			    
    						
    注意:若访问API过程中出现“Invalid sign. (sign签名参数值无效)”错误提示,常见原因如下:

    1、 App Key与App Secret不匹配

    2、 SHA1方法有误,Java推荐使用common-codec 1.6版本

    3、 生成sign签名时,中文的参数值没有先转换为UTF8编码

    4、 对服务器发起HTTP Get请求时,所有请求参数必须先转为UTF8编码,否则会报错