要求

    1. 首先,排除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
    2. 在上述拼装之后的字符串后面直接拼装accesskey的值。
      a)比如,上述参数return_code=0&version=1.0.0,假设accesskey是123456789ABCDEF,拼装以后,成为下述字符串:
      b)return_code=0&version=1.0.0123456789ABCDEF
    3. 对上述第2步得到的字符串,进行MD5运算(32位大写),得到sign
    1. package cn.hkrt.haipay.common.utils;
    2. import net.sf.json.JSONArray;
    3. import net.sf.json.JSONObject;
    4. import org.bouncycastle.jce.provider.BouncyCastleProvider;
    5. import java.security.MessageDigest;
    6. import java.util.*;
    7. /**
    8. * 签名工具类,按字母升序排列,拼接key
    9. * @author zhaoyilong
    10. *
    11. */
    12. public class SignUtils {
    13. private static BouncyCastleProvider provider = new BouncyCastleProvider();
    14. /**
    15. * 直接拼接key在最后面
    16. * 例:key=123456789的时候待签名的字符串为,aa=3&bb=1&cc=1&dd=20160426999123456789
    17. * @param partnerKey
    18. * @param params
    19. * @return
    20. */
    21. public static String signParams(String partnerKey,Map params){
    22. //直接拼接key
    23. String tobesign = getToBeSign(params) + partnerKey;
    24. return md5dataToSign(tobesign);
    25. }
    26. public static String md5dataToSign(String data){
    27. String algorithm = "MD5";
    28. try {
    29. //BouncyCastleProvider provider = new BouncyCastleProvider();
    30. MessageDigest md = MessageDigest.getInstance(algorithm, provider);
    31. byte[] rtn = md.digest(data.getBytes("UTF-8"));
    32. return byte2Hex(rtn).toUpperCase();
    33. } catch (Exception e) {
    34. e.printStackTrace();
    35. throw new RuntimeException("不支持的算法:"+algorithm);
    36. }
    37. }
    38. public static String getToBeSign(Map params){
    39. TreeMap tm = new TreeMap();
    40. tm.putAll(params); //参数排序
    41. Set set = tm.entrySet();
    42. StringBuffer sb = new StringBuffer();
    43. int i = 0;
    44. for (Iterator iterator = set.iterator(); iterator.hasNext();) {
    45. Map.Entry e = (Map.Entry) iterator.next();
    46. String k = (String)e.getKey();
    47. //String v = (String)e.getValue();
    48. if(e.getValue() == null || "".equals(e.getValue()) || "sign".equals(k) || "mac".equals(k)){
    49. continue;
    50. }
    51. String v = "";
    52. if(e.getValue() instanceof JSONArray){
    53. v = getJsonArrayStr((JSONArray)e.getValue());
    54. }else if(e.getValue() instanceof JSONObject){
    55. v = getToBeSign((JSONObject)e.getValue());
    56. }else{
    57. v = e.getValue().toString();
    58. }
    59. if(i != 0){
    60. sb.append("&");
    61. }
    62. sb.append(k+"="+v);
    63. i = i + 1;
    64. }
    65. return sb.toString();
    66. }
    67. public static String getJsonArrayStr(JSONArray a){
    68. String r = "";
    69. for(int j=0; j < a.size() ; j++){
    70. Object b = (Object) a.get(j);
    71. String v = "";
    72. if(b instanceof JSONArray){
    73. v = getJsonArrayStr((JSONArray)b);
    74. }else if(b instanceof JSONObject){
    75. v = getToBeSign((JSONObject)b);
    76. }else{
    77. v = b.toString();
    78. }
    79. if(j ==0){
    80. r = v;
    81. }else{
    82. r += "&" + v;
    83. }
    84. }
    85. return r;
    86. }
    87. public static String byte2Hex(byte[] b) {
    88. StringBuilder sb = new StringBuilder();
    89. String stmp = "";
    90. for (int n = 0; n < b.length; n++) {
    91. stmp = (Integer.toHexString(b[n] & 0XFF));
    92. if (stmp.length() == 1) {
    93. sb.append("0").append(stmp);
    94. } else {
    95. sb.append(stmp);
    96. }
    97. }
    98. return sb.toString().toUpperCase();
    99. }
    100. }