彭雪彬
2025-07-14 c1d20b425b10e8ba59f102dd1ab413055883eed0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package com.oying.modules.hwc.utils;
 
import com.oying.exception.BadRequestException;
import com.oying.modules.security.config.SwiftPassProperties;
import com.oying.utils.enums.PayTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
 
import java.nio.charset.StandardCharsets;
import java.util.Map;
 
/**
 * @author zeming.fan@swiftpass.cn
 */
@Slf4j
public class SignUtil {
 
    /**
     * 请求时根据不同签名方式去生成不同的sign
     */
    public static String getSign(String signType, String preStr, SwiftPassProperties properties, PayTypeEnum status) {
        if ("RSA_1_256".equals(signType)) {
            try {
                return SignUtil.sign(preStr, "RSA_1_256", properties.getMchPrivateKey());
            } catch (Exception e1) {
                log.error(e1.getMessage(), e1);
                throw new BadRequestException(e1.getMessage());
            }
        } else {
            switch (status) {
                case HWC:
                    return MD5.sign(preStr, "&key=" + properties.getKey(), "utf-8");
                case HWC2:
                    return MD5.sign(preStr, "&key=" + properties.getKey2(), "utf-8");
            }
            throw new BadRequestException("汇旺财类型错误");
        }
    }
 
    /**
     * 对返回参数的验证签名
     */
    public static boolean verifySign(String sign, String signType, Map<String, String> resultMap, SwiftPassProperties properties, PayTypeEnum status) throws Exception {
        if ("RSA_1_256".equals(signType)) {
            Map<String, String> params = SignUtils.paraFilter(resultMap);
            StringBuilder builder = new StringBuilder((params.size() + 1) * 10);
            SignUtils.buildPayParams(builder, params, false);
            String preStr = builder.toString();
            return !SignUtil.verifySign(preStr, sign, "RSA_1_256", properties.getPlatPublicKey());
        } else if ("MD5".equals(signType)) {
            switch (status) {
                case HWC:
                    return !SignUtils.checkParam(resultMap, properties.getKey());
                case HWC2:
                    return !SignUtils.checkParam(resultMap, properties.getKey2());
            }
            throw new BadRequestException("汇旺财类型错误");
        }
        return true;
    }
 
    /**
     * RSA_1_256 验证签名
     */
    public static boolean verifySign(String preStr, String sign, String signType, String platPublicKey) throws Exception {
        // 调用这个函数前需要先判断是MD5还是RSA
        // 商户的验签函数要同时支持MD5和RSA
        RSAUtil.SignatureSuite suite;
        if ("RSA_1_1".equals(signType)) {
            suite = RSAUtil.SignatureSuite.SHA1;
        } else if ("RSA_1_256".equals(signType)) {
            suite = RSAUtil.SignatureSuite.SHA256;
        } else {
            throw new Exception("不支持的签名方式");
        }
        return RSAUtil.verifySign(suite, preStr.getBytes(StandardCharsets.UTF_8), Base64.decodeBase64(sign.getBytes(StandardCharsets.UTF_8)),
                platPublicKey);
    }
 
    /**
     * RSA_1_256生成不同的sign
     */
    public static String sign(String preStr, String signType, String mchPrivateKey) throws Exception {
        RSAUtil.SignatureSuite suite;
        if ("RSA_1_1".equals(signType)) {
            suite = RSAUtil.SignatureSuite.SHA1;
        } else if ("RSA_1_256".equals(signType)) {
            suite = RSAUtil.SignatureSuite.SHA256;
        } else {
            throw new Exception("不支持的签名方式");
        }
        byte[] signBuf = RSAUtil.sign(suite, preStr.getBytes(StandardCharsets.UTF_8),
                mchPrivateKey);
        return new String(Base64.encodeBase64(signBuf), StandardCharsets.UTF_8);
    }
}