From 2c9f5b8a5a1fec970546f30966d8c5d4351a1f83 Mon Sep 17 00:00:00 2001 From: eric <465889110@qq.com> Date: Tue, 26 Aug 2025 00:57:06 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A4=84=E7=90=86=E9=80=80=E6=AC=BE=E5=B8=A6?= =?UTF-8?q?=E8=AF=81=E4=B9=A6=E8=AF=B7=E6=B1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 22 +++ sczx_singlepay.iml | 173 ------------------ .../com/sczx/pay/mapper/OrderPayMapper.java | 2 +- src/main/java/com/sczx/pay/sdk/WXPay.java | 73 +++++++- .../java/com/sczx/pay/sdk/WXPayConfig.java | 11 ++ .../sczx/pay/service/WechatPayService.java | 68 ++++++- src/main/resources/cert/1679965261.p12 | Bin 0 -> 2766 bytes src/main/resources/cert/1685128771.p12 | Bin 0 -> 2766 bytes src/main/resources/cert/1699979689.p12 | Bin 0 -> 2766 bytes src/main/resources/cert/1702736781.p12 | Bin 0 -> 2774 bytes src/main/resources/cert/1704580401.p12 | Bin 0 -> 2766 bytes 11 files changed, 164 insertions(+), 185 deletions(-) delete mode 100644 sczx_singlepay.iml create mode 100644 src/main/resources/cert/1679965261.p12 create mode 100644 src/main/resources/cert/1685128771.p12 create mode 100644 src/main/resources/cert/1699979689.p12 create mode 100644 src/main/resources/cert/1702736781.p12 create mode 100644 src/main/resources/cert/1704580401.p12 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 0000000000000000000000000000000000000000..1c638a19694c51f28b052d9c43ec57f350c81701 GIT binary patch literal 2766 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 Ijq7~>0%rCJ`~Uy| literal 0 HcmV?d00001 diff --git a/src/main/resources/cert/1699979689.p12 b/src/main/resources/cert/1699979689.p12 new file mode 100644 index 0000000000000000000000000000000000000000..ac524362d11ca726e4cf0015330358ec3be71df9 GIT binary patch literal 2766 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 GwEPQKA{6-m literal 0 HcmV?d00001 diff --git a/src/main/resources/cert/1702736781.p12 b/src/main/resources/cert/1702736781.p12 new file mode 100644 index 0000000000000000000000000000000000000000..5caa54b17b9d985e849344ef6be6c3db22237e26 GIT binary patch literal 2774 zcmY+^c{~(~76A7pI*FyPIH{aQ_6M`|YEC6qVgz3`nFN!Q zYun#DR|5cC4!olZL~hyFhZG%Ait-b|Ho}xoX}_4Rd#1%6=o|e|AhJL>t=i^NZLx8R-@)kvk_WRqy}CaGJap9^XH#$xQ%#%rs2M{nYcVCZ9flFSIXtTYFD& zuAVT)kb69RwE)>BPVeBzGtls6eE|Aag>%)|nk~K_I&7r2e@Ehyzw|VKNVpgo<5XJa zLdSnrDNxMOzxyQM@^)yME)R~H!f`u-wHv)y;bV7V$WOlqZ+J=^YEI!0Z=^=lZMg7e zk%K98;&c9nb(vp`c77LD+?B~KJ;q3j^w#9ZON6O@Y5h)XS}#S`EGM@)b%0fP<>@wo z-gwNJHio?Bc1yt0udFEC_0#(vTfLq7k;dHY6dC8lo})6Fgh;4+ci4_^XT0gB=bZVi z5JK^R-eTY=8?*2$(S24~;Z@)u!a7bi*gD$Zeek~1z_;_A@3zR1@foxR-r?Bf64^pj zSnd79h*^QAF67R!ZM=`7du(Ka3xtDL@|+}ThJxSE%&`PJl6d&e5vI-Z@xF)+hM^c% zS9E{k%{v*sI@ee$f8sC{c*VyZb{F2BE*!^e_E9=@R$~}Tvoo^t$&)5{?JQGKPoonR ze@oVX|8>bpD$ss<%b&~`ezEl3ob_>M0wkvd#xy%a*%%SIizV`hWH$g16-S_!9#Xkf zCs?#2l2K&?dQZB&DGMv&-$GBpB#+XZ1@^#)HcWA9@Tk=1g^~*ISNaoqmYhdLUMAkO zo;mBM>f7j2^jcO9k!dV1$GLyaN<8O`%_)VU{{tQl1M&u9Kpv;@-P3XepZO1e5GLkR zCpS-lT>C#2S^icLX>OFm!MHh2TY8kUX{^YvM3dY#lV0rbBCecn zAjMUarjocKP4Bc9hUsq>x9W47-y_bWjgrm@_^#U%NEvyT*jHzR!xz4QZWYoFAR*t& zd6aDyQ2dI!nJJ>ns)uqjse>CgZ{Az26H;b9VbvL%Uu9z>{dox<20LM10I*uPN;74{ z@D^c|QM)0x&T62ER6@B-rKL`MMlqsJVqm*kzVS*i(q3>^)@V(nEcHY1l3_LR52wN^ z7kzU-_bFd47ZXJ(4=fLQqWhgjHry|NDNnF5djGL?i~YM`&w0ke`5NvUP#Eqdv2%HK<@xjDE^8d8k< zidN;Z3M+%$&EN;Jl*24?j;QWfplMG zzB6TTMg2)YytHvue=3=QQ_vo>>UOD2UO3S9MLn}@JT6O?ow%F-)jK1IRaM)Ck-lHG z_)F{EnV|=}pTf<&c}=6njtfBTmrE6MHKV)xwnSaKCO^>e`pu|-fY}FqI(4u)av1(R zw03pb{Tr~FkH59hJ3cd_#DZOjW2@ySGSk>>0wr#$Awpm4Ky~(h$hU$ryXg1=@O77>TbP=dFrrR*UUmzNZC%I)fI z1q?F}$pgIen-|CCQ|QC@d}K6|?gtjNdGvBdTH-@N@Q0=YTkieO1TM921?MKMNhq4*c(f`rtVRY#Y#L>%G7<-?5eiH{)PF= zM3>$zgU^+A8eh!T zTfq41DCs5FuI$jFipVl8QY|wXt|3Jn`LDIlPGKQDBzVG)SNm;}(;OwSSIaDstj7fZG61fIr|Nzzq-qkN_B* zPC)=Pzz5)US{|n<8sG_6f=j~L!5{@r7G@C;00^t6`F1I@pd`q5g}vv$Rpw5D&fEa9 N@#tWuI&kJ1e*w~-C@ug1 literal 0 HcmV?d00001 diff --git a/src/main/resources/cert/1704580401.p12 b/src/main/resources/cert/1704580401.p12 new file mode 100644 index 0000000000000000000000000000000000000000..9578b62a54ee4d0e4058b7d67bf9495a74edba56 GIT binary patch literal 2766 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 G;C}&#JSK|( literal 0 HcmV?d00001