diff --git a/pom.xml b/pom.xml
index cdbb910..d430497 100644
--- a/pom.xml
+++ b/pom.xml
@@ -194,6 +194,28 @@
1.15
+
+
+
+ org.apache.httpcomponents
+ httpclient
+ 4.5.13
+
+
+
+
+ org.apache.httpcomponents
+ httpcore
+ 4.4.14
+
+
+
+
+ org.apache.httpcomponents
+ httpmime
+ 4.5.13
+
+
diff --git a/sczx_singlepay.iml b/sczx_singlepay.iml
deleted file mode 100644
index 988da39..0000000
--- a/sczx_singlepay.iml
+++ /dev/null
@@ -1,173 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/main/java/com/sczx/pay/mapper/OrderPayMapper.java b/src/main/java/com/sczx/pay/mapper/OrderPayMapper.java
index b8e9fce..c720162 100644
--- a/src/main/java/com/sczx/pay/mapper/OrderPayMapper.java
+++ b/src/main/java/com/sczx/pay/mapper/OrderPayMapper.java
@@ -47,7 +47,7 @@ public interface OrderPayMapper {
"where payment_id = #{paymentId} and del_flag = '0')")
OrderMain getOrderStatusByOrderNo(@Param("paymentId") String paymentId);
- @Update("update zc_order_main as om,zc_order_sub as os set os.transaction_id = #{refundId},os.pay_status = #{payStatus} os.amount = #{refundFee},os.update_time = #{updateTime}" +
+ @Update("update zc_order_main as om,zc_order_sub as os set os.transaction_id = #{refundId},os.pay_status = #{payStatus}, os.amount = #{refundFee},os.update_time = #{updateTime}" +
" where om.order_id = os.order_id and os.payment_id = #{outTradeNo} and os.suborder_type = 'FD_DEPOSIT'" )
int updateSubOrderRefundStatus(@Param("outTradeNo") String outTradeNo,
@Param("payStatus") String payStatus,
diff --git a/src/main/java/com/sczx/pay/sdk/WXPay.java b/src/main/java/com/sczx/pay/sdk/WXPay.java
index 6579de4..db46bf3 100644
--- a/src/main/java/com/sczx/pay/sdk/WXPay.java
+++ b/src/main/java/com/sczx/pay/sdk/WXPay.java
@@ -1,11 +1,27 @@
package com.sczx.pay.sdk;
import com.sczx.pay.utils.WXPayUtil;
+import org.apache.http.HttpEntity;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.ssl.SSLContexts;
+import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.io.File;
+import java.io.FileInputStream;
+import java.security.KeyStore;
import java.util.Map;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+
+import javax.net.ssl.SSLContext;
+
+
/**
* 微信支付接口
*/
@@ -180,7 +196,7 @@ public class WXPay {
String xml = WXPayUtil.mapToXml(reqData);
logger.info("微信支付请求URL: {}, 请求数据: {}", url, xml);
- String response = httpRequest(url, xml, connectTimeoutMs, readTimeoutMs);
+ String response = httpsRequestWithCert(url, xml, connectTimeoutMs, readTimeoutMs);
logger.info("微信支付响应数据: {}", response);
return response;
@@ -230,6 +246,59 @@ public class WXPay {
}
}
+ /**
+ * 带证书的HTTPS请求
+ */
+ private String httpsRequestWithCert(String url, String requestData, int connectTimeoutMs, int readTimeoutMs) throws Exception {
+ // 加载证书
+ KeyStore keyStore = KeyStore.getInstance("PKCS12");
+ FileInputStream instream = new FileInputStream(new File(this.config.getCertPath()));
+ try {
+ keyStore.load(instream, this.config.getMchID().toCharArray());
+ } finally {
+ instream.close();
+ }
+
+ // 创建SSL上下文
+ SSLContext sslcontext = SSLContexts.custom()
+ .loadKeyMaterial(keyStore, this.config.getMchID().toCharArray())
+ .build();
+
+ // 创建SSL连接工厂
+ SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
+ sslcontext,
+ new String[]{"TLSv1", "TLSv1.1", "TLSv1.2"},
+ null,
+ (hostname, session) -> true);
+
+ // 创建HTTP客户端
+ CloseableHttpClient httpclient = HttpClients.custom()
+ .setSSLSocketFactory(sslsf)
+ .build();
+
+ try {
+ // 创建POST请求
+ HttpPost httpost = new HttpPost(url);
+ httpost.addHeader("Content-Type", "application/xml;charset=UTF-8");
+ httpost.setEntity(new StringEntity(requestData, "UTF-8"));
+
+ // 执行请求
+ CloseableHttpResponse response = httpclient.execute(httpost);
+ try {
+ HttpEntity entity = response.getEntity();
+ String result = EntityUtils.toString(response.getEntity(), "UTF-8");
+ EntityUtils.consume(entity);
+ return result;
+ } finally {
+ response.close();
+ }
+ } finally {
+ httpclient.close();
+ }
+ }
+
+
+
/**
* 判断支付结果
*/
@@ -241,4 +310,6 @@ public class WXPay {
return false;
}
}
+
+
}
diff --git a/src/main/java/com/sczx/pay/sdk/WXPayConfig.java b/src/main/java/com/sczx/pay/sdk/WXPayConfig.java
index 8c446f9..95fc7b2 100644
--- a/src/main/java/com/sczx/pay/sdk/WXPayConfig.java
+++ b/src/main/java/com/sczx/pay/sdk/WXPayConfig.java
@@ -21,6 +21,8 @@ public abstract class WXPayConfig {
* 获取 API 密钥
*/
public abstract String getKey();
+
+ private String certPath;
/**
* 获取证书内容
@@ -40,4 +42,13 @@ public abstract class WXPayConfig {
public int getHttpReadTimeoutMs() {
return 8*1000;
}
+
+
+ public String getCertPath() {
+ return certPath;
+ }
+
+ public void setCertPath(String certPath) {
+ this.certPath = certPath;
+ }
}
diff --git a/src/main/java/com/sczx/pay/service/WechatPayService.java b/src/main/java/com/sczx/pay/service/WechatPayService.java
index b49eb17..355cf35 100644
--- a/src/main/java/com/sczx/pay/service/WechatPayService.java
+++ b/src/main/java/com/sczx/pay/service/WechatPayService.java
@@ -20,6 +20,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.PostConstruct;
+import java.io.File;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
@@ -248,27 +249,35 @@ public class WechatPayService {
return errorResult;
}
+ Map reqData = new HashMap<>();
+ reqData.put("transaction_id",String.valueOf(paymentRecord.getTransactionId()));
+ reqData.put("out_trade_no", request.getOutTradeNo());
+ reqData.put("out_refund_no", request.getOutRefundNo());
+ reqData.put("total_fee", String.valueOf(paymentRecord.getTotalFee()));
+ reqData.put("refund_fee", String.valueOf(request.getRefundFee()));
+ reqData.put("notify_url",refundNotifyUrl);
+
+
// 创建动态配置
DynamicWXPayConfig wxPayConfig = new DynamicWXPayConfig(
appId,
companyConfig.getMchId(),
companyConfig.getApikey(),
- notifyUrl
+ refundNotifyUrl
);
+ String certPath = "classpath*:cert/"+companyConfig.getMchId()+".p12";
+ String certAbsolutePath = getCertAbsolutePath(certPath);
+ wxPayConfig.setCertPath(certAbsolutePath);
+
+
+
WXPay wxPay = new WXPay(wxPayConfig);
- Map reqData = new HashMap<>();
- reqData.put("out_trade_no", request.getOutTradeNo());
- reqData.put("out_refund_no", request.getOutRefundNo());
- reqData.put("total_fee", String.valueOf(paymentRecord.getTotalFee()));
- reqData.put("refund_fee", String.valueOf(request.getRefundFee()));
- reqData.put("notify_url", refundNotifyUrl);
- if (request.getRefundDesc() != null) {
- reqData.put("refund_desc", request.getRefundDesc());
- }
+
+
// 退款需要证书,这里调用带证书的接口
Map result = wxPay.refund(reqData);
@@ -509,4 +518,43 @@ public class WechatPayService {
}
}
+
+ /**
+ * 获取证书文件的绝对路径
+ */
+ private String getCertAbsolutePath(String certPath) {
+ try {
+ // 如果certPath是绝对路径,直接返回
+ if (new File(certPath).isAbsolute()) {
+ return certPath;
+ }
+
+ // 如果是相对路径,则从classpath下获取
+ ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+ java.net.URL resource = classLoader.getResource(certPath);
+
+ if (resource != null) {
+ return resource.getPath();
+ } else {
+ // 如果在classpath中找不到,则尝试从当前类的classpath下获取
+ resource = WechatPayService.class.getClassLoader().getResource(certPath);
+ if (resource != null) {
+ return resource.getPath();
+ } else {
+ // 如果还找不到,则使用默认路径
+ String defaultPath = "cert/1679965261.p12";
+ resource = classLoader.getResource(defaultPath);
+ if (resource != null) {
+ return resource.getPath();
+ } else {
+ throw new RuntimeException("无法找到证书文件: " + certPath);
+ }
+ }
+ }
+ } catch (Exception e) {
+ logger.error("获取证书路径失败", e);
+ throw new RuntimeException("获取证书路径失败: " + e.getMessage(), e);
+ }
+ }
+
}
diff --git a/src/main/resources/cert/1679965261.p12 b/src/main/resources/cert/1679965261.p12
new file mode 100644
index 0000000..1c638a1
Binary files /dev/null and b/src/main/resources/cert/1679965261.p12 differ
diff --git a/src/main/resources/cert/1685128771.p12 b/src/main/resources/cert/1685128771.p12
new file mode 100644
index 0000000..475779e
Binary files /dev/null and b/src/main/resources/cert/1685128771.p12 differ
diff --git a/src/main/resources/cert/1699979689.p12 b/src/main/resources/cert/1699979689.p12
new file mode 100644
index 0000000..ac52436
Binary files /dev/null and b/src/main/resources/cert/1699979689.p12 differ
diff --git a/src/main/resources/cert/1702736781.p12 b/src/main/resources/cert/1702736781.p12
new file mode 100644
index 0000000..5caa54b
Binary files /dev/null and b/src/main/resources/cert/1702736781.p12 differ
diff --git a/src/main/resources/cert/1704580401.p12 b/src/main/resources/cert/1704580401.p12
new file mode 100644
index 0000000..9578b62
Binary files /dev/null and b/src/main/resources/cert/1704580401.p12 differ