签名算法

在调用接口进行编码前,开发者需先计算签名,计算方式如下:
  • 把所有参数按照参数名首字母进行升序排序。(参数sign不参与签名)
  • 对排序后的参数按照’key1=value1&key2=value2&key3=value3…’排列,生成字符串A。
  • 将字符串A全部转化成小写字母,生成字符串B
  • 在字符串B末尾拼接商户接口密钥(app_key),生成字符串C。
  • 对字符串C进行MD5计算,结果以小写表示。
将得到的签名赋给sign作为请求参数(空字符串也参与签名,如 key1=&key2=&key2=value2&... )
签名代码如下(仅供参考):
  • 签名代码示例(PHP):
    -------------------------------------------------------
        $post['customerId'] = 8000000;
        $post['page'] = 1;
        $post['pageSize'] = 20;
        $secret = "E36BC06C************3DBB33465";
        ksort($post);  //排序
        $sign_string = urldecode(http_build_query($post));
        $back_sign = md5(strtolower($sign_string) . $secret);
        $post['sign'] = $back_sign;
                            
  • 签名代码示例(JAVA):
    -------------------------------------------------------
        import java.security.MessageDigest;
        import java.security.NoSuchAlgorithmException;
        import java.util.HashMap;
        import java.util.Map;
        import java.util.TreeMap;
        import java.net.URLDecoder;
        import java.io.UnsupportedEncodingException;
        import java.util.stream.Collectors;
    
        public class SignGenerator {
            public static void main(String[] args) {
                Map post = new HashMap<>();
                post.put("customerId", 8000000);
                post.put("page", 1);
                post.put("pageSize", 20);
                String secret = "E36BC06C************3DBB33465";
    
                // Sort the parameters by key
                Map sortedPost = new TreeMap<>(post);
    
                // Build the query string
                String signString = sortedPost.entrySet().stream()
                        .map(entry -> entry.getKey() + "=" + entry.getValue())
                        .collect(Collectors.joining("&"));
    
                try {
                    // URL decode the string (similar to urldecode in PHP)
                    signString = URLDecoder.decode(signString, "UTF-8");
    
                    // Append the secret and convert to lowercase
                    String stringToSign = signString.toLowerCase() + secret;
    
                    // Calculate MD5 hash
                    String backSign = md5(stringToSign);
    
                    // Add the signature to the post data
                    post.put("sign", backSign);
    
                    System.out.println("Generated sign: " + backSign);
                    System.out.println("Final post data: " + post);
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
            }
    
            private static String md5(String input) {
                try {
                    MessageDigest md = MessageDigest.getInstance("MD5");
                    byte[] messageDigest = md.digest(input.getBytes());
    
                    // Convert byte array to hex string
                    StringBuilder hexString = new StringBuilder();
                    for (byte b : messageDigest) {
                        String hex = Integer.toHexString(0xff & b);
                        if (hex.length() == 1) {
                            hexString.append('0');
                        }
                        hexString.append(hex);
                    }
                    return hexString.toString();
                } catch (NoSuchAlgorithmException e) {
                    throw new RuntimeException(e);
                }
            }
        }