179 lines
6.5 KiB
Java
179 lines
6.5 KiB
Java
|
|
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<String, Object> 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<String, String> paymentParams = createPaymentParams(result);
|
|||
|
|
|
|||
|
|
System.out.println("支付订单创建成功: " + orderId + ", prepay_id: " + result.getPrepayId());
|
|||
|
|
|
|||
|
|
// 返回结果
|
|||
|
|
Map<String, Object> 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<String, Object> response = new HashMap<>();
|
|||
|
|
response.put("success", false);
|
|||
|
|
response.put("message", "创建支付订单失败: " + e.getMessage());
|
|||
|
|
return response;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 生成小程序支付参数
|
|||
|
|
*/
|
|||
|
|
private Map<String, String> createPaymentParams(WxPayUnifiedOrderResult result) {
|
|||
|
|
Map<String, String> 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<String, String> params) {
|
|||
|
|
try {
|
|||
|
|
// 按照参数名ASCII字典序排序
|
|||
|
|
List<String> 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;
|
|||
|
|
}
|
|||
|
|
}
|