From c1d20b425b10e8ba59f102dd1ab413055883eed0 Mon Sep 17 00:00:00 2001
From: 彭雪彬 <1724387007@qq.com>
Date: Mon, 14 Jul 2025 16:57:11 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/xin' into pxb

---
 oying-system/src/main/java/com/oying/modules/hwc/service/impl/SwiftPassServiceImpl.java |  340 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 340 insertions(+), 0 deletions(-)

diff --git a/oying-system/src/main/java/com/oying/modules/hwc/service/impl/SwiftPassServiceImpl.java b/oying-system/src/main/java/com/oying/modules/hwc/service/impl/SwiftPassServiceImpl.java
new file mode 100644
index 0000000..e0a7063
--- /dev/null
+++ b/oying-system/src/main/java/com/oying/modules/hwc/service/impl/SwiftPassServiceImpl.java
@@ -0,0 +1,340 @@
+package com.oying.modules.hwc.service.impl;
+
+import com.alibaba.fastjson2.JSONObject;
+import com.oying.exception.BadRequestException;
+import com.oying.modules.hwc.domain.HwcResponse;
+import com.oying.modules.hwc.service.SwiftPassService;
+import com.oying.modules.hwc.utils.SignUtil;
+import com.oying.modules.hwc.utils.SignUtils;
+import com.oying.modules.hwc.utils.XmlUtils;
+import com.oying.modules.security.config.SwiftPassProperties;
+import com.oying.modules.security.config.WeiXinProperties;
+import com.oying.utils.CloseUtil;
+import com.oying.utils.enums.PayTypeEnum;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+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.util.EntityUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.*;
+
+/**
+ * @author xin
+ * @description
+ * @date 2025/1/23 下午4:01
+ */
+@SuppressWarnings({"unchecked", "all"})
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class SwiftPassServiceImpl implements SwiftPassService {
+
+    private final static String version = "2.0";
+    private final static String charset = "UTF-8";
+    private final static String service_pay = "pay.weixin.jspay";
+    private final static String service_query = "unified.trade.query";
+    private final static String service_refund = "unified.trade.refund";
+    private final static String service_close = "unified.trade.close";
+
+    private final SwiftPassProperties properties;
+    private final WeiXinProperties weiXinProperties;
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public HwcResponse pay(String ip, String total, String timeExpire, String description, String openId,
+                           String orderNum, PayTypeEnum status) {
+        SortedMap<String, String> map = new TreeMap<>();
+        map.put("service", service_pay);
+        map.put("version", version);
+        map.put("charset", charset);
+        map.put("sign_type", properties.getSignType());
+        map.put("is_raw", properties.getIsRaw());
+        map.put("is_minipg", properties.getIsMinipg());
+        map.put("out_trade_no", orderNum);
+        map.put("body", description);
+        map.put("sub_openid", openId);
+        map.put("sub_appid", weiXinProperties.getAppId());
+        map.put("total_fee", total);
+        map.put("mch_create_ip", ip);
+        map.put("notify_url", properties.getNotifyUrl());
+        map.put("time_expire", timeExpire);
+        map.put("nonce_str", String.valueOf(new Date().getTime()));
+        switch (status) {
+            case HWC:
+                map.put("mch_id", properties.getMchId());
+                break;
+            case HWC2:
+                map.put("mch_id", properties.getMchId2());
+                break;
+            default:
+                throw new BadRequestException("汇旺财类型错误");
+        }
+        Map<String, String> params = SignUtils.paraFilter(map);
+        StringBuilder buf = new StringBuilder((params.size() + 1) * 10);
+        SignUtils.buildPayParams(buf, params, false);
+        String preStr = buf.toString();
+        String sign_type = map.get("sign_type");
+
+        map.put("sign", SignUtil.getSign(sign_type, preStr, properties, status));
+
+        String reqUrl = properties.getReqUrl();
+        CloseableHttpResponse response = null;
+        CloseableHttpClient client = null;
+        Map<String, String> resultMap = new HashMap<>();
+        try {
+            HttpPost httpPost = new HttpPost(reqUrl);
+            StringEntity entityParams = new StringEntity(XmlUtils.parseXML(map), "utf-8");
+            httpPost.setEntity(entityParams);
+            httpPost.setHeader("Content-Type", "text/xml;utf-8");
+            client = HttpClients.createDefault();
+            response = client.execute(httpPost);
+            if (response != null && response.getEntity() != null) {
+                resultMap = XmlUtils.toMap(EntityUtils.toByteArray(response.getEntity()), "utf-8");
+                String reSign = resultMap.get("sign");
+                sign_type = resultMap.get("sign_type");
+                if (resultMap.containsKey("sign") && SignUtil.verifySign(reSign, sign_type, resultMap, properties, status)) {
+                    throw new BadRequestException("验证签名错误");
+                } else {
+                    if ("0".equals(resultMap.get("status")) && "0".equals(resultMap.get("result_code"))) {
+                        return JSONObject.parseObject(resultMap.get("pay_info"), HwcResponse.class);
+                    } else {
+                        throw new BadRequestException(resultMap.get("err_code") + " : " + resultMap.get("err_msg") + "\n" +
+                                resultMap.get("status") + " : " + resultMap.get("message"));
+                    }
+                }
+            } else {
+                throw new BadRequestException("操作失败");
+            }
+        } catch (Exception e) {
+            log.error("汇旺财下单错误请求参数:{}", params);
+            log.error("汇旺财下单错误返回参数:{}", resultMap);
+            throw new BadRequestException("汇旺财下单错误:" + e.getMessage());
+        } finally {
+            if (response != null) {
+                CloseUtil.close(response);
+            }
+            if (client != null) {
+                CloseUtil.close(client);
+            }
+        }
+    }
+
+    @Override
+    public JSONObject query(String orderNum, PayTypeEnum status) {
+        // 参数
+        SortedMap<String, String> map = new TreeMap<>();
+        map.put("service", service_query);
+        map.put("version", version);
+        map.put("charset", charset);
+        map.put("out_trade_no", orderNum);
+        map.put("sign_type", properties.getSignType());
+        switch (status) {
+            case HWC:
+                map.put("mch_id", properties.getMchId());
+                break;
+            case HWC2:
+                map.put("mch_id", properties.getMchId2());
+                break;
+            default:
+                throw new BadRequestException("汇旺财类型错误");
+        }
+        map.put("nonce_str", String.valueOf(new Date().getTime()));
+        // 签名
+        Map<String, String> params = SignUtils.paraFilter(map);
+        StringBuilder buf = new StringBuilder((params.size() + 1) * 10);
+        SignUtils.buildPayParams(buf, params, false);
+        String preStr = buf.toString();
+        String sign_type = map.get("sign_type");
+        map.put("sign", SignUtil.getSign(sign_type, preStr, properties, status));
+        // 请求
+        CloseableHttpResponse response = null;
+        CloseableHttpClient client = null;
+        Map<String, String> resultMap = new HashMap<>();
+        try {
+            HttpPost httpPost = new HttpPost(properties.getReqUrl());
+            StringEntity entityParams = new StringEntity(XmlUtils.parseXML(map), "utf-8");
+            httpPost.setEntity(entityParams);
+            httpPost.setHeader("Content-Type", "text/xml;utf-8");
+            client = HttpClients.createDefault();
+            response = client.execute(httpPost);
+            if (response != null && response.getEntity() != null) {
+                resultMap = XmlUtils.toMap(EntityUtils.toByteArray(response.getEntity()), "utf-8");
+                String reSign = resultMap.get("sign");
+                sign_type = resultMap.get("sign_type");
+                if (resultMap.containsKey("sign") && SignUtil.verifySign(reSign, sign_type, resultMap, properties, status)) {
+                    throw new BadRequestException("验证签名错误");
+                } else {
+                    if ("0".equals(resultMap.get("status"))) {
+                        return JSONObject.parseObject(JSONObject.toJSONString(resultMap));
+                    } else {
+
+                        throw new BadRequestException(resultMap.get("err_code") + " : " + resultMap.get("err_msg") + "\n" +
+                                resultMap.get("status") + " : " + resultMap.get("message"));
+                    }
+                }
+            } else {
+                throw new BadRequestException("操作失败!");
+            }
+        } catch (Exception e) {
+            log.error("请求参数:{}", params);
+            log.error("返回参数:{}", resultMap);
+            throw new BadRequestException("操作失败,原因:" + e.getMessage());
+        } finally {
+            if (response != null) {
+                CloseUtil.close(response);
+            }
+            if (client != null) {
+                CloseUtil.close(client);
+            }
+        }
+    }
+
+    @Override
+    public void closeOrder(String outTradeNo, PayTypeEnum status) {
+        // 参数
+        SortedMap<String, String> map = new TreeMap<>();
+        map.put("service", service_close);
+        map.put("version", version);
+        map.put("charset", charset);
+        map.put("out_trade_no", outTradeNo);
+        map.put("sign_type", properties.getSignType());
+        switch (status) {
+            case HWC:
+                map.put("mch_id", properties.getMchId());
+                break;
+            case HWC2:
+                map.put("mch_id", properties.getMchId2());
+                break;
+            default:
+                throw new BadRequestException("汇旺财类型错误");
+        }
+        map.put("nonce_str", String.valueOf(new Date().getTime()));
+        // 签名
+        Map<String, String> params = SignUtils.paraFilter(map);
+        StringBuilder buf = new StringBuilder((params.size() + 1) * 10);
+        SignUtils.buildPayParams(buf, params, false);
+        String preStr = buf.toString();
+        String sign_type = map.get("sign_type");
+        map.put("sign", SignUtil.getSign(sign_type, preStr, properties, status));
+        // 请求
+        CloseableHttpResponse response = null;
+        CloseableHttpClient client = null;
+        Map<String, String> resultMap = new HashMap<>();
+        try {
+            HttpPost httpPost = new HttpPost(properties.getReqUrl());
+            StringEntity entityParams = new StringEntity(XmlUtils.parseXML(map), "utf-8");
+            httpPost.setEntity(entityParams);
+            httpPost.setHeader("Content-Type", "text/xml;utf-8");
+            client = HttpClients.createDefault();
+            response = client.execute(httpPost);
+            if (response != null && response.getEntity() != null) {
+                resultMap = XmlUtils.toMap(EntityUtils.toByteArray(response.getEntity()), "utf-8");
+                String reSign = resultMap.get("sign");
+                sign_type = resultMap.get("sign_type");
+                if (resultMap.containsKey("sign") && SignUtil.verifySign(reSign, sign_type, resultMap, properties, status)) {
+                    throw new BadRequestException("验证签名错误");
+                } else {
+                    if (!("0".equals(resultMap.get("status")))) {
+                        throw new BadRequestException(resultMap.get("err_code") + " : " + resultMap.get("err_msg") + "\n" +
+                                resultMap.get("status") + " : " + resultMap.get("message"));
+                    }
+                }
+            } else {
+                throw new BadRequestException("操作失败!");
+            }
+        } catch (Exception e) {
+            log.error("请求参数:{}", params);
+            log.error("返回参数:{}", resultMap);
+            throw new BadRequestException("操作失败,原因:" + e.getMessage());
+        } finally {
+            if (response != null) {
+                CloseUtil.close(response);
+            }
+            if (client != null) {
+                CloseUtil.close(client);
+            }
+        }
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Map<String, String> refund(String returnNum, String orderNum, String reason, long refund,
+                                      long total, PayTypeEnum payType) {
+        // 参数
+        SortedMap<String, String> map = new TreeMap<>();
+        map.put("service", service_refund);
+        map.put("version", version);
+        map.put("charset", charset);
+        map.put("sign_type", properties.getSignType());
+        map.put("out_trade_no", orderNum);
+        map.put("out_refund_no", returnNum);
+        map.put("total_fee", String.valueOf(total));
+        map.put("refund_fee", String.valueOf(refund));
+        map.put("nonce_str", String.valueOf(new Date().getTime()));
+        switch (payType) {
+            case HWC:
+                map.put("mch_id", properties.getMchId());
+                map.put("op_user_id", properties.getMchId());
+                break;
+            case HWC2:
+                map.put("mch_id", properties.getMchId2());
+                map.put("op_user_id", properties.getMchId2());
+                break;
+            default:
+                throw new BadRequestException("汇旺财类型错误");
+        }
+        // 签名
+        Map<String, String> params = SignUtils.paraFilter(map);
+        StringBuilder buf = new StringBuilder((params.size() + 1) * 10);
+        SignUtils.buildPayParams(buf, params, false);
+        String preStr = buf.toString();
+        String sign_type = map.get("sign_type");
+        map.put("sign", SignUtil.getSign(sign_type, preStr, properties, payType));
+        // 参数
+        CloseableHttpResponse response = null;
+        CloseableHttpClient client = null;
+        Map<String, String> resultMap = new HashMap<>();
+        try {
+            HttpPost httpPost = new HttpPost(properties.getReqUrl());
+            StringEntity entityParams = new StringEntity(XmlUtils.parseXML(map), "utf-8");
+            httpPost.setEntity(entityParams);
+            httpPost.setHeader("Content-Type", "text/xml;utf-8");
+            client = HttpClients.createDefault();
+            response = client.execute(httpPost);
+            if (response != null && response.getEntity() != null) {
+                resultMap = XmlUtils.toMap(EntityUtils.toByteArray(response.getEntity()), "utf-8");
+                if (resultMap.containsKey("sign") && SignUtil.verifySign(resultMap.get("sign"), resultMap.get("sign_type"), resultMap, properties, payType)) {
+                    throw new BadRequestException("验证签名错误");
+                } else {
+                    if ("0".equals(resultMap.get("status"))) {
+                        return resultMap;
+                    } else {
+                        throw new BadRequestException(resultMap.get("err_code") + " : " + resultMap.get("err_msg") + "\n" +
+                                resultMap.get("status") + " : " + resultMap.get("message"));
+                    }
+                }
+            } else {
+                throw new BadRequestException("操作失败!");
+            }
+        } catch (Exception e) {
+            log.error("请求参数:{}", params);
+            log.error("返回参数:{}", resultMap);
+            throw new BadRequestException("操作失败,原因:" + e);
+        } finally {
+            if (response != null) {
+                CloseUtil.close(response);
+            }
+            if (client != null) {
+                CloseUtil.close(client);
+            }
+        }
+    }
+
+
+}

--
Gitblit v1.9.3