xuhy
2025-01-09 712f70b2936079a131ecb1e63c6d337171618cad
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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
package com.stylefeng.guns.modular.account.unionpay;
 
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.StringUtils;
 
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.*;
 
 
public class NotifyDemo {
 
 
    /**
     * 支付通知模块,用于:在支付成功后 接受银商平台发送的支付结果通知
     */
//    @RequestMapping(value = "/notify.do", method = RequestMethod.POST)
    public String getNotify(String md5key,HttpServletRequest request, HttpServletResponse response) throws Exception {
 
        /*接收参数*/
        Map<String, String> params = getRequestParams(request);
        System.out.println("params:" + params);
        String sign = params.get("sign");
        System.out.println(sign);
 
        /*验签*/
        //对通知内容生成sign
        String strSign = makeSign(md5key, params);
        //System.out.println("strSign="+strSign);
        //判断签名是否相等
        if (sign.equals(strSign)) {
            // 收到通知后记得返回SUCCESS
            System.out.println("验签通过");
            PrintWriter writer = response.getWriter();
            writer.print("SUCCESS");
            writer.flush();
        } else {
            System.out.println("验签未通过");
        }
        //更新商户系统的订单
        //跳转支付完成页面
        return "/WEB-INF/views/jsp/payResult.jsp";
    }
 
 
    // 获取HttpServletRequest里面的参数
    public static Map<String, String> getRequestParams(HttpServletRequest request) {
        Map<String, String[]> params = request.getParameterMap();
        Map<String, String> params2 = new HashMap<>();
        for (String key : params.keySet()) {
            String[] values = params.get(key);
            if (values.length > 0) {
                params2.put(key, request.getParameter(key));
            }
        }
        return params2;
    }
 
 
    public static String makeSign(String md5Key, Map<String, String> params) {
 
        String preStr = buildSignString(params); // 把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串
        String text = preStr + md5Key;
        System.out.println("待签名字符串:" + text);
        return DigestUtils.md5Hex(getContentBytes(text)).toUpperCase();
    }
 
    public static String makeSign256Hex(String md5Key, Map<String, String> params) {
 
        String preStr = buildSignString(params); // 把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串
        String text = preStr + md5Key;
        System.out.println("待签名字符串:" + text);
        return DigestUtils.sha256Hex(getContentBytes(text)).toUpperCase();
    }
 
    /**
     * 生成签名. 注意,若含有sign_type字段,必须和signType参数保持一致。
     *
     * @param data     待签名数据
     * @param key      API密钥
     * @param signType 签名方式
     * @return 签名
     */
    public static String generateSignature(final Map<String, String> data, String key, String signType) throws Exception {
        Set<String> keySet = data.keySet();
        String[] keyArray = keySet.toArray(new String[keySet.size()]);
        Arrays.sort(keyArray);
        StringBuilder sb = new StringBuilder();
        for (String k : keyArray) {
            if (k.equals("sign")) {
                continue;
            }
            if (data.get(k).trim().length() > 0) {
                // 参数值为空,则不参与签名
                sb.append(k).append("=").append(data.get(k).trim()).append("&");
            }
        }
        sb.append("key=").append(key);
        if ("HMAC-SHA256".equals(signType)) {
            return HMACSHA256(sb.toString(), key);
        } else {
            throw new Exception(String.format("Invalid sign_type: %s", signType));
        }
    }
 
    /**
     * 生成 HMACSHA256
     *
     * @param data 待处理数据
     * @param key  密钥
     * @return 加密结果
     * @throws Exception
     */
    public static String HMACSHA256(String data, String key) throws Exception {
        Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
        SecretKeySpec secret_key = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256");
        sha256_HMAC.init(secret_key);
        byte[] array = sha256_HMAC.doFinal(data.getBytes("UTF-8"));
        StringBuilder sb = new StringBuilder();
        for (byte item : array) {
            sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
        }
        return sb.toString().toUpperCase();
    }
 
 
    // 构建签名字符串
    public static String buildSignString(Map<String, String> params) {
 
        // params.put("Zm","test_test");
 
        if (params == null || params.size() == 0) {
            return "";
        }
 
        List<String> keys = new ArrayList<>(params.size());
 
        for (String key : params.keySet()) {
            if ("sign".equals(key))
                continue;
            if (StringUtils.isEmpty(params.get(key)))
                continue;
            keys.add(key);
        }
        //System.out.println(listToString(keys));
 
        Collections.sort(keys);
 
        StringBuilder buf = new StringBuilder();
 
        for (int i = 0; i < keys.size(); i++) {
            String key = keys.get(i);
            String value = params.get(key);
 
            if (i == keys.size() - 1) {// 拼接时,不包括最后一个&字符
                buf.append(key + "=" + value);
            } else {
                buf.append(key + "=" + value + "&");
            }
        }
 
        return buf.toString();
    }
 
    // 根据编码类型获得签名内容byte[]
    public static byte[] getContentBytes(String content) {
        try {
            return content.getBytes("UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("签名过程中出现错误");
        }
    }
}