要求
- 首先,排除sign参数之外,将其它参数(空值除外)按名称进行字母排序,并和它的取值一起组成name=value样式的字符串,然后用&把它们拼装为一个大字符串,对于嵌套的参数,嵌套的参数列表也需按照字母排序进行拼装。
a) 比如,要传递下列参数
i.version=1.0.0
ii.return_code=0
iii.拼装之后的字符串为:return_code=0&version=1.0.0
b) 比如,要传递下列参数
i.a=1
ii.b={“d”:”3”,”c”:”2”}
iii.拼装之后的字符串为:a=1&b=c=2&d=3
c)比如,要传递下列参数
i.a=1
ii.b=[{“d”:”3”,”c”:”2”},{“d”:”5”,”c”:”4”}]
iii.拼装之后的字符串为:a=1&b=c=2&d=3&c=4&d=5
d)比如,要传递下列参数
i.a=1
ii.b=[“2”,”3”]
iii.拼装之后的字符串为:a=1&b=2&3
e)比如,要传递下列参数
i.a=1
ii.b=[[{“d1”:”1”,”c1”:”2”},{“d2”:”3”,”c2”:”4”}],[{“d3”:”5”,”c3”:”6”},{“d4”:”7”,”c4”:”8”}]]
iii.拼装之后的字符串为:a=1&b=c1=2&d1=1&c2=4&d2=3&c3=6&d3=5&c4=8&d4=7- 在上述拼装之后的字符串后面直接拼装accesskey的值。
a)比如,上述参数return_code=0&version=1.0.0,假设accesskey是123456789ABCDEF,拼装以后,成为下述字符串:
b)return_code=0&version=1.0.0123456789ABCDEF- 对上述第2步得到的字符串,进行MD5运算(32位大写),得到sign
package cn.hkrt.haipay.common.utils;import net.sf.json.JSONArray;import net.sf.json.JSONObject;import org.bouncycastle.jce.provider.BouncyCastleProvider;import java.security.MessageDigest;import java.util.*;/*** 签名工具类,按字母升序排列,拼接key* @author zhaoyilong**/public class SignUtils {private static BouncyCastleProvider provider = new BouncyCastleProvider();/*** 直接拼接key在最后面* 例:key=123456789的时候待签名的字符串为,aa=3&bb=1&cc=1&dd=20160426999123456789* @param partnerKey* @param params* @return*/public static String signParams(String partnerKey,Map params){//直接拼接keyString tobesign = getToBeSign(params) + partnerKey;return md5dataToSign(tobesign);}public static String md5dataToSign(String data){String algorithm = "MD5";try {//BouncyCastleProvider provider = new BouncyCastleProvider();MessageDigest md = MessageDigest.getInstance(algorithm, provider);byte[] rtn = md.digest(data.getBytes("UTF-8"));return byte2Hex(rtn).toUpperCase();} catch (Exception e) {e.printStackTrace();throw new RuntimeException("不支持的算法:"+algorithm);}}public static String getToBeSign(Map params){TreeMap tm = new TreeMap();tm.putAll(params); //参数排序Set set = tm.entrySet();StringBuffer sb = new StringBuffer();int i = 0;for (Iterator iterator = set.iterator(); iterator.hasNext();) {Map.Entry e = (Map.Entry) iterator.next();String k = (String)e.getKey();//String v = (String)e.getValue();if(e.getValue() == null || "".equals(e.getValue()) || "sign".equals(k) || "mac".equals(k)){continue;}String v = "";if(e.getValue() instanceof JSONArray){v = getJsonArrayStr((JSONArray)e.getValue());}else if(e.getValue() instanceof JSONObject){v = getToBeSign((JSONObject)e.getValue());}else{v = e.getValue().toString();}if(i != 0){sb.append("&");}sb.append(k+"="+v);i = i + 1;}return sb.toString();}public static String getJsonArrayStr(JSONArray a){String r = "";for(int j=0; j < a.size() ; j++){Object b = (Object) a.get(j);String v = "";if(b instanceof JSONArray){v = getJsonArrayStr((JSONArray)b);}else if(b instanceof JSONObject){v = getToBeSign((JSONObject)b);}else{v = b.toString();}if(j ==0){r = v;}else{r += "&" + v;}}return r;}public static String byte2Hex(byte[] b) {StringBuilder sb = new StringBuilder();String stmp = "";for (int n = 0; n < b.length; n++) {stmp = (Integer.toHexString(b[n] & 0XFF));if (stmp.length() == 1) {sb.append("0").append(stmp);} else {sb.append(stmp);}}return sb.toString().toUpperCase();}}
