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 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 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 params) throws Exception { // 移除sign参数 Map signParams = new HashMap<>(params); signParams.remove("sign"); // 过滤空值并排序 List keys = new ArrayList<>(); for (Map.Entry 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 params) throws Exception { // 构建参数字符串 StringBuilder postData = new StringBuilder(); for (Map.Entry 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 params) { try { String receivedSign = params.get("sign"); Map signParams = new HashMap<>(params); String calculatedSign = generateSign(signParams); return calculatedSign.equals(receivedSign); } catch (Exception e) { return false; } } }