shikeying
2024-01-11 3b67e947e36133e2a40eb2737b15ea375e157ea0
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
package com.walker.pay.wechat.v2;
 
import com.walker.infrastructure.core.domx.JaxbDomParser;
import com.walker.infrastructure.utils.KeyValue;
import com.walker.infrastructure.utils.MD5;
import com.walker.infrastructure.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
 
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
 
public class SignUtils {
 
    protected static final Logger logger = LoggerFactory.getLogger(SignUtils.class);
 
    private static final JaxbDomParser domParser = new JaxbDomParser();
 
    /**
     * 返回xml字符串,该方法用来告诉微信,通知处理结果
     * @param status 状态
     * @param msg 描述
     * @return
     * @date 2023-02-17
     */
    public static String toXmlNotifyStatus(String status, String msg){
        List<KeyValue<String, String>> params = new ArrayList<>(2);
        params.add(new KeyValue<>("return_code", status));
        params.add(new KeyValue<>("return_msg", msg));
        return toXml(params);
    }
 
    public static Map<String,String> decodeXml(String content) {
        Map<String, String> xml = new HashMap<String, String>();
        Document doc = domParser.getDocumentFromXml(content);
 
        Node node = doc.getFirstChild(); // 获取根节点
        for(Node childNode = node.getFirstChild(); childNode != null; childNode = childNode.getNextSibling()){
            if(childNode.getNodeType() == Node.ELEMENT_NODE){
                xml.put(childNode.getNodeName(), childNode.getTextContent());
            }
        }
        return xml;
    }
 
    public static String toXml(List<KeyValue<String, String>> params) {
        StringBuilder sb = new StringBuilder();
        sb.append("<xml>");
        for (int i = 0; i < params.size(); i++) {
            sb.append("<"+params.get(i).getKey()+">");
            sb.append(params.get(i).getValue());
            sb.append("</"+params.get(i).getKey()+">");
        }
        sb.append("</xml>");
        return sb.toString();
    }
 
    /**
     * 与genPackageSign方法唯一的区别就是,没有转成大写字母。不知道这帮微信咋弄文档
     * @param params
     * @param wxApiKey
     * @return
     */
    public static final String getAppSign(List<KeyValue<String, String>> params, String wxApiKey){
        return getSign(params, wxApiKey, false);
    }
 
    public static final String getPackageSign(List<KeyValue<String, String>> params, String wxApiKey){
        return getSign(params, wxApiKey, true);
    }
 
    public static final String getSign(List<KeyValue<String, String>> params, String wxApiKey, boolean upperCase){
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < params.size(); i++) {
            sb.append(params.get(i).getKey());
            sb.append(StringUtils.CHAR_EQUALS);
            sb.append(params.get(i).getValue());
            sb.append(StringUtils.CHAR_AND);
        }
        sb.append("key=");
        sb.append(wxApiKey);
        logger.debug("sign = {}", sb);
 
        String packageSign;
        try {
            if(upperCase){
                packageSign = MD5.getMessageDigest(sb.toString().getBytes(StringUtils.DEFAULT_CHARSET_UTF8)).toUpperCase();
            } else {
                packageSign = MD5.getMessageDigest(sb.toString().getBytes(StringUtils.DEFAULT_CHARSET_UTF8));
            }
//            logger.debug("摘要信息:" + packageSign);
//            String result = new String(packageSign.toString().getBytes(), "utf-8");
//            logger.debug("第二次转:" + result);
//            return result;
            return packageSign;
 
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            throw new RuntimeException("签名不支持的字符集utf8");
        }
    }
 
    /**
     * 获取sign
     * @param map      待签名数据
     * @param signKey 微信签名key
     * @return String
     */
    public static String getSign(Map<String, String> map, String signKey) throws Exception{
        // map排序
        Set<String> keySet = map.keySet();
        String[] keyArray = keySet.toArray(new String[keySet.size()]);
        Arrays.sort(keyArray);
        StringBuilder sb = new StringBuilder();
        for (String k : keyArray) {
            if (k.equals(MD5.NAME_SIGN_2)) {
                continue;
            }
            if (StringUtils.isNotEmpty(map.get(k)) && map.get(k).trim().length() > 0) // 参数值为空,则不参与签名
                sb.append(k).append(StringUtils.CHAR_EQUALS).append(map.get(k).trim()).append(StringUtils.CHAR_AND);
        }
        sb.append("key=").append(signKey);
//        String sign = SecureUtil.md5(sb.toString()).toUpperCase();
        String sign = MD5.getMessageDigest(sb.toString().getBytes(StringUtils.DEFAULT_CHARSET_UTF8)).toUpperCase();
//        System.out.println("sign ========== " + sign);
        return sign;
    }
 
}