1
zj
2025-10-09 df30c88c2c76da0cb607bcf129446f43c9a521da
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
package com.ruoyi.im.util;
 
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.util.*;
 
/**
 * 简化版支付工具类
 */
public class SimplePayUtil {
 
    private String mchId;        // 商户ID
    private String key;          // 商户密钥
    private String baseUrl;      // 支付系统基础URL
 
    public SimplePayUtil(String mchId, String key, String baseUrl) {
        this.mchId = mchId;
        this.key = key;
        this.baseUrl = baseUrl;
    }
 
    /**
     * 统一下单 - 最简单版本
     */
    public String createOrder(String productId, String orderNo, int amount, String notifyUrl) {
        try {
            // 构建参数
            Map<String, Object> params = new HashMap<>();
            params.put("mchId", mchId);
            params.put("productId", productId);
            params.put("mchOrderNo", orderNo);
            params.put("amount", amount);
            params.put("notifyUrl", notifyUrl);
 
            // 生成签名
            String sign = generateSign(params);
            params.put("sign", sign);
 
            // 发送请求
            String url = baseUrl + "/api/pay/create_order";
            String result = sendPost(url, params);
 
            return result;
 
        } catch (Exception e) {
            return "{\"retCode\":\"FAIL\",\"retMsg\":\"" + e.getMessage() + "\"}";
        }
    }
 
    /**
     * 查询订单 - 最简单版本
     */
    public String queryOrder(String orderNo) {
        try {
            // 构建参数
            Map<String, Object> params = new HashMap<>();
            params.put("mchId", mchId);
            params.put("mchOrderNo", orderNo);
 
            // 生成签名
            String sign = generateSign(params);
            params.put("sign", sign);
 
            // 发送请求
            String url = baseUrl + "/api/pay/query_order";
            String result = sendPost(url, params);
 
            return result;
 
        } catch (Exception e) {
            return "{\"retCode\":\"FAIL\",\"retMsg\":\"" + e.getMessage() + "\"}";
        }
    }
 
    /**
     * 生成签名
     */
    private String generateSign(Map<String, Object> params) throws Exception {
        // 移除sign参数
        Map<String, Object> signParams = new HashMap<>(params);
        signParams.remove("sign");
 
        // 过滤空值并排序
        List<String> keys = new ArrayList<>();
        for (Map.Entry<String, Object> entry : signParams.entrySet()) {
            if (entry.getValue() != null && !entry.getValue().toString().trim().isEmpty()) {
                keys.add(entry.getKey());
            }
        }
 
        // ASCII码排序
        Collections.sort(keys);
 
        // 拼接字符串
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < keys.size(); i++) {
            String key = keys.get(i);
            String value = signParams.get(key).toString();
            if (i > 0) {
                sb.append("&");
            }
            sb.append(key).append("=").append(value);
        }
 
        // 拼接key并MD5加密
        String stringSignTemp = sb.toString() + "&key=" + key;
        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] array = md.digest(stringSignTemp.getBytes("UTF-8"));
        StringBuilder result = new StringBuilder();
        for (byte item : array) {
            result.append(String.format("%02x", item));
        }
 
        return result.toString().toUpperCase();
    }
 
    /**
     * 发送POST请求
     */
    private String sendPost(String urlStr, Map<String, Object> params) throws Exception {
        // 构建参数字符串
        StringBuilder postData = new StringBuilder();
        for (Map.Entry<String, Object> param : params.entrySet()) {
            if (postData.length() != 0) postData.append('&');
            postData.append(URLEncoder.encode(param.getKey(), "UTF-8"));
            postData.append('=');
            postData.append(URLEncoder.encode(String.valueOf(param.getValue()), "UTF-8"));
        }
 
        byte[] postDataBytes = postData.toString().getBytes("UTF-8");
 
        URL url = new URL(urlStr);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("POST");
        conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        conn.setRequestProperty("Content-Length", String.valueOf(postDataBytes.length));
        conn.setDoOutput(true);
 
        // 发送数据
        OutputStream os = conn.getOutputStream();
        os.write(postDataBytes);
        os.flush();
        os.close();
 
        // 读取响应
        BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
        StringBuilder response = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            response.append(line);
        }
        reader.close();
 
        return response.toString();
    }
 
    /**
     * 验证回调签名
     */
    public boolean verifyNotifySign(Map<String, String> params) {
        try {
            String receivedSign = params.get("sign");
            Map<String, Object> signParams = new HashMap<>(params);
            String calculatedSign = generateSign(signParams);
            return calculatedSign.equals(receivedSign);
        } catch (Exception e) {
            return false;
        }
    }
}