package com.hdl.linkpm.sdk.core.interceptor; import android.net.Uri; import android.text.TextUtils; import androidx.annotation.NonNull; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.google.gson.reflect.TypeToken; import com.hdl.hdlhttp.utils.GsonConvert; import com.hdl.linkpm.sdk.HDLLinkPMSdk; import com.hdl.linkpm.sdk.core.interceptor.HDLSmartHeader; import com.hdl.linkpm.sdk.utils.HDLMD5Utils; import com.hdl.linkpm.sdk.utils.HDLSDKLog; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import okhttp3.FormBody; import okhttp3.Headers; import okhttp3.Interceptor; import okhttp3.MediaType; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; import okio.Buffer; /** * Created by Tong on 2021/11/4. * 加密并自动补充参数,appKey、timestamp * 只支持表单、json * 最终json方式提交 */ public class HDLEncryptInterceptor implements Interceptor { @NonNull @Override public Response intercept(@NonNull Chain chain) throws IOException { Request request = chain.request(); Headers headers = request.headers(); if (!isIgnoreSignHeader(headers)) { return chain.proceed(encrypt(request)); } return chain.proceed(request); } /** * 添加sign字段 */ private Request encrypt(Request request) { final String timestamp = String.valueOf(System.currentTimeMillis()); final String appKey = HDLLinkPMSdk.getAppKey(); final String appSecret = HDLLinkPMSdk.getAppSecret(); final JsonObject json = getBodyJson(request); if (json != null) { json.addProperty("appKey", appKey); json.addProperty("timestamp", timestamp); json.addProperty("sign", getSign(json, appSecret)); final RequestBody requestBody = RequestBody.create(json.toString(), MediaType.parse("application/json;charset=UTF-8")); return request.newBuilder().post(requestBody) .build(); } return request; } /** * 是否忽略自定义的加密头 */ private boolean isIgnoreSignHeader(Headers headers) { String signHeader = headers.get(HDLSmartHeader.IGNORE_SIGN_HEADER); return !TextUtils.isEmpty(signHeader); } private JsonObject getBodyJson(Request request) { RequestBody body = request.body(); if (body instanceof FormBody) { JsonObject object = new JsonObject(); FormBody formBody = (FormBody) body; for (int i = 0; i < formBody.size(); i++) { object.addProperty(formBody.encodedName(i), formBody.value(i)); } return object; } else { //json格式 try { String bodyString = getBodyString(request); if (!TextUtils.isEmpty(bodyString)) { final JsonElement parseString = JsonParser.parseString(bodyString); return parseString.getAsJsonObject(); } } catch (Exception e) { e.printStackTrace(); } } return null; } private String getBodyString(Request request) { try { RequestBody body = request.body(); if (body != null) { Buffer buffer = new Buffer(); body.writeTo(buffer); Charset charset = StandardCharsets.UTF_8; MediaType contentType = body.contentType(); charset = contentType.charset(charset); return buffer.readString(charset); } } catch (IOException e) { e.printStackTrace(); } return ""; } /** * 需要按字母排序 * * @param json 所有字段使用urlParameter拼接,除了appSecret */ private String getSign(JsonObject json, String appSecret) { String builder = jsonToUrlParameter(json) + appSecret; return HDLMD5Utils.encodeMD5(builder); } private String jsonToUrlParameter(JsonObject object) { final Map map = GsonConvert.getGson().fromJson(object, new TypeToken>() { }.getType()); final Uri.Builder builder = new Uri.Builder(); List list = new ArrayList<>(map.keySet()); Collections.sort(list); for (String key : list) { //判断当前值是否需要参与签名,保持跟云端一致 if (IfValueNeedSign(map.get(key))) { builder.appendQueryParameter(key, map.get(key)); // HDLSDKLog.e("要签名:" + key + " :" + map.get(key)); } else { // HDLSDKLog.e("不需要签名:" + key + " :" + map.get(key)); } } return builder.build().getQuery(); } /** * 判断当前值是否需要参与签名,保持跟云端一致 * 空字符串不参与 * 数组,集合,对象不参与 * * @param valueStr * @return */ private static boolean IfValueNeedSign(String valueStr) { if (TextUtils.isEmpty(valueStr)) return false; final char[] strChar = valueStr.substring(0, 1).toCharArray(); final char firstChar = strChar[0]; //System.out.println("getJSONType firstChar = "+firstChar); if (firstChar != '{' && firstChar != '[') return true; return false; } // /** // * 判断当前值是否需要参与签名,保持跟云端一致 // * 空字符串不参与 // * 数组,集合,对象不参与 // * // * @param inputValueStr // * @return // */ // private static boolean IfValueNeedSign(String inputValueStr) { // if (TextUtils.isEmpty(inputValueStr)) // return false; // try { // //先解码 // String valueStr = URLDecoder.decode(inputValueStr, "utf-8"); // final char[] strChar = valueStr.substring(0, 1).toCharArray(); // final char firstChar = strChar[0]; // //System.out.println("getJSONType firstChar = "+firstChar); // if (firstChar != '{' && firstChar != '[') { // return true; // } // return false; // } catch (UnsupportedEncodingException e) { // e.printStackTrace(); // return false; // } // // } }