MaxPay 支付接口文档

本文档提供了MaxPay支付平台所有接口的详细说明和使用方法,包括代收、代付、订单查询及回调处理等核心功能。

7. 签名方式

参数签名用于保证参数一致性,避免被篡改。通过将参数按照规则组合,使用MD5 Hash算法得到签名。

具体步骤:

  1. 将所有POST的非空(空值字段不参与加签)参数按照字段名升序排序,且去除前后空格,进行URL编码(UTF-8)并转换为小写,组合成参数字符串:

    paramString = "aparam=xxx&bparam=yyy&cparam=zzz&..."

  2. 在参数字符串末尾,追加secret参数:

    strToHash = paramString + "&secret=[商户的secret]"

  3. 将第二步得到的结果进行MD5加密:

    sign = md5(strToHash)

Java 示例

Java 示例代码
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

public class SignatureGenerator  {


    /**
     * 生成API请求签名
     * @param params 请求参数Map
     * @param secret 商户密钥
     * @return 32位小写MD5签名
     */
    public static String generateSign(Map params, String secret) {
        // 1. 过滤空值参数并去除空格
        Map filteredParams = new TreeMap<>();
        for (Map.Entry entry : params.entrySet()) {
            if (entry.getValue() != null && !entry.getValue().trim().isEmpty()) {
                // 去除值的前后空格
                filteredParams.put(entry.getKey(), entry.getValue().trim());
            }
        }

        // 2. 按字段名升序排序(TreeMap已自动排序)
        // 3. 构建参数字符串
        StringBuilder paramBuilder = new StringBuilder();
        for (Map.Entry entry : filteredParams.entrySet()) {
            if (paramBuilder.length() > 0) {
                paramBuilder.append("&");
            }
            // URL编码并转换为小写
            String encodedValue = URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8)
                .toLowerCase();
            paramBuilder.append(entry.getKey())
                .append("=")
                .append(encodedValue);
        }

        // 4. 追加secret
        String paramString = paramBuilder.toString();
        String strToHash = paramString + "&secret=" + secret;

        // 5. 生成MD5签名
        return md5(strToHash);
    }

    /**
     * 生成MD5哈希值
     * @param input 输入字符串
     * @return 32位小写MD5
     */
    private static String md5(String input) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] hash = md.digest(input.getBytes(StandardCharsets.UTF_8));
            StringBuilder hexString = new StringBuilder();
            for (byte b : hash) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) hexString.append("0");
                hexString.append(hex);
            }
            return hexString.toString();
        } catch (Exception e) {
            throw new RuntimeException("MD5计算失败", e);
        }
    }

    // 测试示例
    public static void main(String[] args) {
        Map params = new HashMap<>();
        params.put("amount", "100.00");
        params.put("merchant", "MCH123456789");
        params.put("paytype", "1");
        params.put("outtradeno", "ORDER202312345");
        params.put("remark", "Test payment");
        params.put("emptyParam", ""); // 空值参数将被忽略

        String secret = "my_secret_key";
        String sign = generateSign(params, secret);

        System.out.println("生成的签名: " + sign);
        // 输出示例: 生成的签名: 2d9da9583ab81d3f1874162d517d672f

    }
}