package com.ruoyi.database.service; import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest; import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult; import com.github.binarywang.wxpay.service.WxPayService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import javax.servlet.http.HttpServletRequest; import java.security.MessageDigest; import java.util.*; @Service public class WechatMiniProgramPayService { @Autowired private WxPayService wxPayService; @Value("${wx.pay.notifyUrl}") private String notifyUrl; /** * 创建小程序支付订单 */ public Map createJsapiOrder(String openid, String orderId, Integer amount, String description, String clientIp) { try { System.out.println("开始创建支付订单: " + orderId + ", openid: " + openid + ", 金额: " + amount + "分"); // 构建支付请求 WxPayUnifiedOrderRequest request = WxPayUnifiedOrderRequest.newBuilder() .outTradeNo(orderId) // 商户订单号 .totalFee(amount) // 金额(分) .body(description) // 商品描述 .tradeType("JSAPI") // 交易类型:小程序支付 .openid(openid) // 用户openid .spbillCreateIp(clientIp) // 终端IP .notifyUrl(notifyUrl) // 支付结果通知地址 .build(); System.out.println("调用微信支付统一下单API..."); // 调用微信支付API WxPayUnifiedOrderResult result = wxPayService.unifiedOrder(request); // 生成小程序支付参数 Map paymentParams = createPaymentParams(result); System.out.println("支付订单创建成功: " + orderId + ", prepay_id: " + result.getPrepayId()); // 返回结果 Map response = new HashMap<>(); response.put("success", true); response.put("paymentParams", paymentParams); response.put("prepayId", result.getPrepayId()); return response; } catch (Exception e) { System.err.println("创建支付订单失败: " + orderId + ", 错误: " + e.getMessage()); e.printStackTrace(); Map response = new HashMap<>(); response.put("success", false); response.put("message", "创建支付订单失败: " + e.getMessage()); return response; } } /** * 生成小程序支付参数 */ private Map createPaymentParams(WxPayUnifiedOrderResult result) { Map paymentParams = new HashMap<>(); // 小程序支付必需的参数 paymentParams.put("appId", result.getAppid()); paymentParams.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000)); paymentParams.put("nonceStr", result.getNonceStr()); paymentParams.put("package", "prepay_id=" + result.getPrepayId()); paymentParams.put("signType", "MD5"); // 生成签名 String sign = generateSign(paymentParams); paymentParams.put("paySign", sign); System.out.println("生成支付参数: " + paymentParams); return paymentParams; } /** * 生成支付签名 */ private String generateSign(Map params) { try { // 按照参数名ASCII字典序排序 List keys = new ArrayList<>(params.keySet()); Collections.sort(keys); // 拼接字符串 StringBuilder sb = new StringBuilder(); for (String key : keys) { if ("sign".equals(key) || key.isEmpty() || params.get(key) == null) { continue; } sb.append(key).append("=").append(params.get(key)).append("&"); } // 加上API密钥 sb.append("key=").append(wxPayService.getConfig().getMchKey()); String signStr = sb.toString(); System.out.println("签名原串: " + signStr); // MD5加密并转大写 String sign = md5(signStr).toUpperCase(); System.out.println("生成签名: " + sign); return sign; } catch (Exception e) { throw new RuntimeException("生成签名失败", e); } } /** * MD5加密 */ private String md5(String data) throws Exception { MessageDigest md = MessageDigest.getInstance("MD5"); byte[] array = md.digest(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(); } /** * 获取客户端IP地址 */ public String getClientIpAddress(HttpServletRequest request) { String ip = request.getHeader("X-Forwarded-For"); if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("WL-Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("HTTP_CLIENT_IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("HTTP_X_FORWARDED_FOR"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); } // 如果是多级代理,取第一个IP if (ip != null && ip.contains(",")) { ip = ip.substring(0, ip.indexOf(",")).trim(); } // 本地开发环境处理 if ("0:0:0:0:0:0:0:1".equals(ip) || "127.0.0.1".equals(ip)) { ip = "123.123.123.123"; // 替换为你的服务器公网IP } System.out.println("获取到客户端IP: " + ip); return ip; } /** * 获取WxPayService实例 */ public WxPayService getWxPayService() { return wxPayService; } }