wlzboy
2025-12-04 4f2925f1974844b66225ac70ae35065b8262b315
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
package com.ruoyi.payment.infrastructure.channel.wechat;
 
import com.ruoyi.payment.infrastructure.config.WechatPayConfig;
import com.ruoyi.payment.infrastructure.util.SignUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
 
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.*;
 
/**
 * 微信支付工具类
 * 
 * @author ruoyi
 */
@Slf4j
@Component
public class WxPayUtil {
 
    @Autowired
    private WechatPayConfig wechatPayConfig;
 
    /**
     * XML转Map
     */
    public Map<String, String> xmlToMap(String xml) throws Exception {
        Map<String, String> data = new HashMap<>();
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        InputStream is = new ByteArrayInputStream(xml.getBytes("UTF-8"));
        Document doc = builder.parse(is);
        doc.getDocumentElement().normalize();
        NodeList nodeList = doc.getDocumentElement().getChildNodes();
        
        for (int i = 0; i < nodeList.getLength(); i++) {
            Node node = nodeList.item(i);
            if (node.getNodeType() == Node.ELEMENT_NODE) {
                data.put(node.getNodeName(), node.getTextContent());
            }
        }
        return data;
    }
 
    /**
     * Map转XML
     */
    public String mapToXml(Map<String, String> data) {
        StringBuilder xml = new StringBuilder("<xml>");
        for (Map.Entry<String, String> entry : data.entrySet()) {
            xml.append("<").append(entry.getKey()).append(">");
            xml.append("<![CDATA[").append(entry.getValue()).append("]]>");
            xml.append("</").append(entry.getKey()).append(">");
        }
        xml.append("</xml>");
        return xml.toString();
    }
 
    /**
     * 生成签名
     */
    public String generateSign(Map<String, String> data) {
        // 1. 参数名ASCII码从小到大排序
        Set<String> keySet = data.keySet();
        String[] keyArray = keySet.toArray(new String[0]);
        Arrays.sort(keyArray);
        
        // 2. 拼接参数
        StringBuilder sb = new StringBuilder();
        for (String k : keyArray) {
            if ("sign".equals(k)) {
                continue;
            }
            String value = data.get(k);
            if (value != null && value.trim().length() > 0) {
                sb.append(k).append("=").append(value).append("&");
            }
        }
        
        // 3. 拼接密钥
        sb.append("key=").append(wechatPayConfig.getMchKey());
        
        // 4. MD5加密并转大写
        return SignUtil.md5(sb.toString());
    }
 
    /**
     * 验证签名
     */
    public boolean verifySign(Map<String, String> data) {
        if(!wechatPayConfig.getCheckSign()){
            log.info("微信回调不检测验证签名");
            return true;
        }
        String sign = data.get("sign");
        if (sign == null || sign.isEmpty()) {
            return false;
        }
        
        String calculatedSign = generateSign(data);
        return sign.equals(calculatedSign);
    }
 
    /**
     * 构造成功应答
     */
    public String buildSuccessResponse() {
        Map<String, String> response = new HashMap<>();
        response.put("return_code", "SUCCESS");
        response.put("return_msg", "OK");
        return mapToXml(response);
    }
 
    /**
     * 构造失败应答
     */
    public String buildFailResponse(String msg) {
        Map<String, String> response = new HashMap<>();
        response.put("return_code", "FAIL");
        response.put("return_msg", msg);
        return mapToXml(response);
    }
}