Step 1. 构造源串
源串是由3部分内容用“&”拼接起来的:
HTTP请求方式 & urlencode(uri) & urlencode(a=x&b=y&...)
源串构造步骤如下:
第1步:将请求的URI路径进行URL编码(URI不含host,URI示例:/v3/user/get_info)。
<font color="red">请开发者关注:URL编码注意事项,否则容易导致后面签名不能通过验证。</font>
第2步:<font color="red">将除“sig”外的所有参数</font>按key进行字典升序排列。
注:除非OpenAPI文档中特别标注了某参数不参与签名,否则除sig外的所有参数都要参与签名。
第3步:将第2步中排序后的参数(key=value)用&拼接起来,并进行URL编码。
<font color="red">请开发者关注:URL编码注意事项,否则容易导致后面签名不能通过验证。</font>
第4步:将HTTP请求方式(GET或者POST)以及第1步和第3步中的字符串用&拼接起来。
注:Java_SDK_V3.0.6仅支持POST方式,如果用GET可能导致一直计算sig不正确。
Step 2. 构造密钥
得到密钥的方式:在应用的appkey末尾加上一个字节的“&”,即appkey&,例如:228bf094169a40a3bd188ba37ebe8723&
Step 3. 生成签名值
使用HMAC-SHA1加密算法,使用Step2中得到的密钥对Step1中得到的源串加密。
(注:一般程序语言中会内置HMAC-SHA1加密算法的函数,例如PHP5.1.2之后的版本可直接调用hash_hmac函数。)然后将加密后的字符串经过Base64编码。
(注:一般程序语言中会内置Base64编码函数,例如PHP中可直接调用 base64_encode() 函数。)得到的签名值结果如下:
FdJkiDYwMj5Aj1UG2RUPc83iokk=
public class BasicParamsInterceptor implements Interceptor {
public static String TAG="BasicParamsInterceptor";
private BasicParamsInterceptor() {
}
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Request.Builder requestBuilder = request.newBuilder();
//===========给参数进行加密 start===================
String signParam="";
if("POST".equals(request.method())){
String url="你的请求url";
String encodeURL="";//URL编码后的请求url
String encodeSortParams="";//URL编码后的升序参数体
HashMap<String, String> paramsMap =new HashMap<String, String>();
//step1.1 将请求的URI路径进行URL编码
encodeURL=URLEncoder.encode(url,"utf-8");
Log.d(TAG,"url="+url);
Log.d(TAG,"encode_url="+ encodeURL);
StringBuilder sb = new StringBuilder();
if (request.body() instanceof FormBody) {
FormBody body = (FormBody) request.body();
int bodySize=body.size();
for (int i = 0; i < bodySize; i++) {
paramsMap.put(body.encodedName(i),body.encodedValue(i));
sb.append(body.encodedName(i) + "=" + body.encodedValue(i) + ",");
}
sb.delete(sb.length() - 1, sb.length());
Log.d(TAG, "║ RequestParams:{"+sb.toString()+"}");
Collection<String> keyset= paramsMap.keySet();
List<String> list = new ArrayList<String>(keyset);
//step1.2 对key键值按字典升序排序
Collections.sort(list);
StringBuilder sortParams = new StringBuilder();
int sortParamSize=list.size();
//step1.3 将第2步中排序后的参数(key=value)用&拼接起来,并进行URL编码。
for (int i = 0; i < sortParamSize; i++) {
sortParams.append(list.get(i)+"="+paramsMap.get(list.get(i)));
if(i!=sortParamSize-1){
sortParams.append("&");
}
}
Log.d(TAG,"数据字典升序后:key键值="+sortParams.toString());
encodeSortParams=URLEncoder.encode(sortParams.toString(),"utf-8");//进行URL编码的 key键值
Log.d(TAG,"数据字典升序并encode="+encodeSortParams);
//step1.4 将HTTP请求方式(GET或者POST)以及第1步和第3步中的字符串用&拼接起来。
StringBuilder bufferStep1=new StringBuilder();
bufferStep1.append(request.method());
bufferStep1.append("&");
bufferStep1.append(encodeURL);
bufferStep1.append("&");
bufferStep1.append(encodeSortParams);
Log.d(TAG,"拼接后的step1="+bufferStep1.toString());
try {
//step 2
String key="你的key"+"&"
//step3
signParam=Util.HMACSha1(bufferStep1.toString(),key);
Log.d(TAG,"signParam="+signParam);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
}
}
paramsMap.put("sign",signParam.trim());
//===========给参数进行加密 end===================
}
/**
* 获取 hmacSha1 并返回Base64编码后的字符串
*
* @param base
* @param key
* @return
* @throws NoSuchAlgorithmException
* @throws InvalidKeyException
*/
public static String HMACSha1(String base, String key) throws NoSuchAlgorithmException, InvalidKeyException {
if (TextUtils.isEmpty(base) || TextUtils.isEmpty(key)) {
return "";
}
String type = "HmacSHA1";
SecretKeySpec secret = new SecretKeySpec(key.getBytes(), type);
Mac mac = Mac.getInstance(type);
mac.init(secret);
byte[] digest = mac.doFinal(base.getBytes());
return Base64.encodeToString(digest, Base64.DEFAULT);
}