Ver código fonte

fix(app):
1.支付相关配置
2.bug修复
feat(pay): 实现微信支付回调解密功能

- 新增 AesUtil 工具类,用于微信支付回调数据解密- 修改 wechatPayNotify 方法,增加数据解密逻辑
- 更新 AppOrderInfoDTO,添加 gameAddress 字段
- 调整 AppSiteServiceImpl 中的 editSite 方法
- 修改 OrderController 中的 wechatPayNotify 接口

wzq 2 semanas atrás
pai
commit
9ae0dede58
29 arquivos alterados com 786 adições e 498 exclusões
  1. 1 0
      national-motion-base-core/src/main/java/org/jeecg/config/shiro/ShiroConfig.java
  2. 3 2
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/controller/OrderController.java
  3. 3 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/dto/AppOrderInfoDTO.java
  4. 2 1
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/service/IOrderService.java
  5. 1 1
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/service/WeChatPayService.java
  6. 0 1
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/service/impl/AppIsinServiceImpl.java
  7. 68 26
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/service/impl/OrderServiceImpl.java
  8. 35 35
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/pay/config/WechatConstants.java
  9. 2 3
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/pay/config/WechatPayV3Utils.java
  10. 5 20
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/pay/config/WechatUrlConstants.java
  11. 121 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/pay/entity/TransactionInfo.java
  12. 52 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/pay/paytest/AesUtil.java
  13. 143 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/pay/paytest/PayMerchantUtil.java
  14. 56 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/pay/paytest/ServiceProvider.java
  15. 24 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/pay/paytest/payController.java
  16. 0 182
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/pay/serverPay/PartnerAppPrepay.java
  17. 185 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/pay/serverPay/PartnerJsApiPrepay.java
  18. 4 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/pay/serverPay/TelAnonymousController.java
  19. 0 107
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/pay/serverPay/WechatSignUtil.java
  20. 0 40
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/pay/serverPay/WxPayConfiguration.java
  21. 19 17
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/pay/serverPay/WxV3PayConfig.java
  22. 3 1
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/service/impl/AppCoureseServiceImpl.java
  23. 1 1
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/service/impl/AppOrderServiceImpl.java
  24. 6 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/service/impl/AppSiteServiceImpl.java
  25. BIN
      national-motion-module-system/national-motion-system-biz/src/main/resources/cert/apiclient_cert.p12
  26. 21 21
      national-motion-module-system/national-motion-system-biz/src/main/resources/cert/apiclient_cert.pem
  27. 26 26
      national-motion-module-system/national-motion-system-biz/src/main/resources/cert/apiclient_key.pem
  28. 0 9
      national-motion-module-system/national-motion-system-biz/src/main/resources/cert/pub_key.pem
  29. 5 5
      national-motion-module-system/national-motion-system-start/src/main/resources/application-dev.yml

+ 1 - 0
national-motion-base-core/src/main/java/org/jeecg/config/shiro/ShiroConfig.java

@@ -109,6 +109,7 @@ public class ShiroConfig {
 
         filterChainDefinitionMap.put("/app/order/wechatPayNotify", "anon");//支付回调
         filterChainDefinitionMap.put("/app/order/refundOrderNotify", "anon");//退款回调
+        filterChainDefinitionMap.put("/test/**", "anon");//测试
 
 
 //        filterChainDefinitionMap.put("/app/user/**", "anon");//小程序相关

+ 3 - 2
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/controller/OrderController.java

@@ -22,6 +22,7 @@ import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.util.Date;
 import java.util.List;
@@ -139,9 +140,9 @@ public class OrderController {
     @Operation(summary = "支付回调")
     @RepeatSubmit(serviceId = "createOrder", limitType = RepeatSubmit.Type.PARAM, lockTime = 10)
     @RequestMapping("/wechatPayNotify")
-    public Map<String, String> wechatPayNotify(HttpServletRequest request) throws InterruptedException {
+    public Map<String, String> wechatPayNotify(HttpServletRequest request, HttpServletResponse  response) throws InterruptedException {
         sleep(10000);
-        return appOrderService.wechatPayNotify(request);
+        return appOrderService.wechatPayNotify(request, response);
     }
 
     /**

+ 3 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/dto/AppOrderInfoDTO.java

@@ -97,6 +97,9 @@ public class AppOrderInfoDTO implements Serializable {
     @Schema(description = "体育馆包场提前退款时间;单位:分钟")
     private Integer earlyRefundTime;
 
+    @Schema(description = "赛事地址")
+    private String gameAddress;
+
     @Schema(description = "纬度")
     private BigDecimal latitude;
 

+ 2 - 1
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/service/IOrderService.java

@@ -10,6 +10,7 @@ import org.jeecg.modules.app.vo.PageOrdersVO;
 import org.jeecg.modules.app.vo.QueryOrderVerifyRecordsVO;
 
 import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.util.Date;
 import java.util.List;
@@ -94,5 +95,5 @@ public interface IOrderService {
 
     String refundOrder(String orderCode);
 
-    Map<String, String> wechatPayNotify(HttpServletRequest request);
+    Map<String, String> wechatPayNotify(HttpServletRequest request, HttpServletResponse response);
 }

+ 1 - 1
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/service/WeChatPayService.java

@@ -9,8 +9,8 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.RandomStringUtils;
 import org.jeecg.modules.pay.config.WechatConstants;
+import org.jeecg.modules.pay.config.WechatPayV3Utils;
 import org.jeecg.modules.pay.config.WechatUrlConstants;
-import org.jeecg.modules.pay.util.WechatPayV3Utils;
 import org.jeecg.modules.system.app.entity.AppOrder;
 import org.jeecg.modules.system.app.mapper.AppOrderMapper;
 import org.springframework.stereotype.Service;

+ 0 - 1
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/service/impl/AppIsinServiceImpl.java

@@ -81,7 +81,6 @@ public class AppIsinServiceImpl extends ServiceImpl<AppIsinMapper, AppIsin> impl
             appOrder.setOrderStatus(CommonConstant.ORDER_STATUS_1);
             appOrderMapper.updateById(appOrder);
         }
-
         return "撤销成功!";
     }
 

+ 68 - 26
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/service/impl/OrderServiceImpl.java

@@ -17,6 +17,7 @@ import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.gson.JsonObject;
 import com.google.gson.JsonParser;
+import com.wechat.pay.contrib.apache.httpclient.util.AesUtil;
 import lombok.extern.log4j.Log4j2;
 import org.apache.commons.lang3.ObjectUtils;
 import org.apache.commons.lang3.StringUtils;
@@ -38,6 +39,7 @@ import org.jeecg.modules.app.vo.PageOrdersVO;
 import org.jeecg.modules.app.vo.QueryOrderVerifyRecordsVO;
 import org.jeecg.modules.pay.config.WechatConstants;
 import org.jeecg.modules.pay.config.WechatUrlConstants;
+import org.jeecg.modules.pay.serverPay.WxV3PayConfig;
 import org.jeecg.modules.redission.RedissonDelayQueue;
 import org.jeecg.modules.system.app.dto.receiptPaymentDetails.ReceiptPaymentDetailsInfoVo;
 import org.jeecg.modules.system.app.entity.*;
@@ -54,9 +56,13 @@ import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.BufferedReader;
 import java.io.IOException;
+import java.io.PrintWriter;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
+import java.nio.charset.StandardCharsets;
 import java.text.SimpleDateFormat;
 import java.time.LocalDate;
 import java.time.LocalTime;
@@ -890,15 +896,15 @@ public class OrderServiceImpl implements IOrderService {
                             .eq(AppOrderProInfo::getProductId, appCourse.getId())
                             .eq(AppOrderProInfo::getFamilyUserId, familyUserId));
                     List<AppOrderProInfo> infoList = infos.stream().filter(info -> Objects.equals(info.getOrFreePro(), CommonConstant.STATUS_0_INT)).collect(Collectors.toList());
-                    if (ObjectUtil.isNotEmpty(infoList)) {
-                        throw new JeecgBootException("当前课程已下过单,请勿重复下单");
-                    }
-                    if (Objects.equals(createOrderForm.getOrFreeOrder(), CommonConstant.STATUS_1_INT)){
-                        List<AppOrderProInfo> freeProList = infos.stream().filter(info -> Objects.equals(info.getOrFreePro(), CommonConstant.STATUS_0_INT)).collect(Collectors.toList());
-                        if (ObjectUtil.isNotEmpty(freeProList)) {
-                            throw new JeecgBootException("当前试听课课程已下过单,请勿重复下单");
-                        }
-                    }
+//                    if (ObjectUtil.isNotEmpty(infoList)) {
+//                        throw new JeecgBootException("当前课程已下过单,请勿重复下单");
+//                    }
+//                    if (Objects.equals(createOrderForm.getOrFreeOrder(), CommonConstant.STATUS_1_INT)){
+//                        List<AppOrderProInfo> freeProList = infos.stream().filter(info -> Objects.equals(info.getOrFreePro(), CommonConstant.STATUS_0_INT)).collect(Collectors.toList());
+//                        if (ObjectUtil.isNotEmpty(freeProList)) {
+//                            throw new JeecgBootException("当前试听课课程已下过单,请勿重复下单");
+//                        }
+//                    }
                     AppOrderProInfo appOrderProInfo = new AppOrderProInfo();
                     appOrderProInfo.setProductId(createOrderForm.getProductIds());
                     appOrderProInfo.setProductName(appCourse.getName());
@@ -1150,13 +1156,13 @@ public class OrderServiceImpl implements IOrderService {
             params.put("attach", appOrder.getOrderCode()); //附加数据 选填
             // 在查询API和支付通知中原样返回 可作为自定义参数使用
             params.put("notify_url", WechatUrlConstants.PAY_V3_NOTIFY); //支付结果异步通知接口
-            params.put("trade_type", WechatConstants.WECHAT_TRADE_TYPE);//JSAPI
+//            params.put("trade_type", WechatConstants.WECHAT_TRADE_TYPE);//JSAPI
             //分账必传参数
             JSONObject settleInfo = new JSONObject();
             settleInfo.put("profit_sharing", Boolean.TRUE);
             params.put("settle_info", settleInfo);
             //电子发票入口
-            params.put("support_fapiao ", Boolean.TRUE);
+//            params.put("support_fapiao ", Boolean.TRUE);
 
             //订单金额信息
             JSONObject amount_json = new JSONObject();
@@ -1169,12 +1175,12 @@ public class OrderServiceImpl implements IOrderService {
             //支付者信息
             JSONObject payer = new JSONObject();
             //用户在小程序侧的openid
-            payer.put("openid", sysUser.getOpenid());
+            payer.put("sub_openid", "oObyf7Z4-Y9P5w6_8YIKEiKSAD6I");
             params.put("payer", payer);
 
             //拉起支付-返回JSAPI参数
-//            Map<String, String> result = weChatPayService.wechatPay(params);
-//            payForm.setParams(result);
+            Map<String, String> result = weChatPayService.wechatPay(params);
+            payForm.setParams(result);
 
             //发布任务到redission延迟队列
             String task = CommonConstant.ORDER_TIME_OUT_TASK_PREFIX + appOrder.getId();
@@ -1426,11 +1432,7 @@ public class OrderServiceImpl implements IOrderService {
         if (appOrder.getType().equals(CommonConstant.ORDER_TYPE_1)) {
             //商品信息
             String productIds = appOrder.getProductIds();
-            AppGamePriceRules appGamePriceRules = appGamePriceRulesMapper.selectById(productIds);
-            AppGame appGame = appGameMapper.selectById(appGamePriceRules.getGameId());
-
-            //门店信息
-            AppSite site = appSiteMapper.selectById(appGame.getSiteId());
+            AppGame appGame = appGameMapper.findByPriceRules(productIds);
             //退改规则、
             appOrderInfoDTO.setReminder(appGame.getReminder());
             //开始时间
@@ -1443,11 +1445,17 @@ public class OrderServiceImpl implements IOrderService {
             //赛程数
             appOrderInfoDTO.setGameScheduleNum(appGameScheduleVOList.size());
             //地址信息
-            appOrderInfoDTO.setSchoolAddress(site.getAddress());
-            appOrderInfoDTO.setLatitude(site.getLatitude());
-            appOrderInfoDTO.setLongitude(site.getLongitude());
-            appOrderInfoDTO.setPhone(site.getPhone());
-            appOrderInfoDTO.setAddressSiteId(site.getId());
+            appOrderInfoDTO.setGameAddress(appGame.getSiteAddress());
+            appOrderInfoDTO.setLatitude(appGame.getLatitude());
+            appOrderInfoDTO.setLongitude(appGame.getLongitude());
+            if (appGame.getSiteType().equals(CommonConstant.STATUS_1_INT)) {
+                //门店信息
+                AppSite site = appSiteMapper.selectById(appGame.getSiteId());
+                if (ObjectUtils.isNotEmpty(site)){
+                    appOrderInfoDTO.setPhone(site.getPhone());
+                    appOrderInfoDTO.setAddressSiteId(site.getId());
+                }
+            }
         }
 
         //课程
@@ -1713,8 +1721,42 @@ public class OrderServiceImpl implements IOrderService {
         return "退款失败!";
     }
 
-    @Override
-    public Map<String, String> wechatPayNotify(HttpServletRequest request) {
+    public Map<String, String> wechatPayNotify(HttpServletRequest request, HttpServletResponse response) {
+
+        try {
+            System.err.println("微信回调");
+            BufferedReader reader = request.getReader();
+            String string1 = reader.toString();
+            StringBuilder requestBody = new StringBuilder();
+            String line;
+            while ((line = reader.readLine()) != null) {
+                requestBody.append(line);
+            }
+            System.err.println("全部请求体" + requestBody);
+            JSONObject jsonObject = JSONObject.parseObject(requestBody.toString());
+            JSONObject resource = jsonObject.getJSONObject("resource");
+            AesUtil aesUtil = new AesUtil(WxV3PayConfig.apiV3Key.getBytes(StandardCharsets.UTF_8));
+            String decryptedData = aesUtil.decryptToString(resource.getString("associated_data").getBytes(StandardCharsets.UTF_8), resource.getString("nonce").getBytes(StandardCharsets.UTF_8),
+                    resource.getString("ciphertext"));
+            System.err.println("微信解密的字符串信息" + decryptedData);
+            JSONObject jsonInfo = (JSONObject) JSONObject.parse(decryptedData);
+            String out_trade_no = jsonInfo.getString("out_trade_no");// 下单时传给微信的订单号
+            String transaction_id = jsonInfo.getString("transaction_id");// 返回的微信订单号
+            String trade_state = jsonInfo.getString("trade_state");// 交易状态     /*SUCCESS:支付成功 REFUND:转入退款 NOTPAY:未支付 CLOSED:已关闭 REVOKED:已撤销(仅付款码支付会返回)USERPAYING:用户支付中(仅付款码支付会返回)PAYERROR:支付失败(仅付款码支付会返回*/
+
+
+            if (trade_state.equals("SUCCESS")) {
+                // 支付成功,执行相应的代码逻辑即可
+                PrintWriter out = response.getWriter();
+                out.write("SUCCESS");
+                out.flush();
+                out.close();
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
         Map<String, String> stringStringMap = weChatPayService.wechatPayNotify(request);
         //对订单进行封账金额统计
         if (stringStringMap != null

+ 35 - 35
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/pay/config/WechatConstants.java

@@ -2,58 +2,58 @@ package org.jeecg.modules.pay.config;
 
 /**
  * @author wangzhiqiang
- * @Date 2022/12/22
+ * @Date 2025/9/9
  * @Desc 微信支付相关配置
  */
 public class WechatConstants {
 
     //微信支付服务商商户号
-    public static final String WECHAT_SP_MCH_ID = "1726394481";
+    public static final String WECHAT_SP_MCH_ID = "1725845681";
 
-    public static final String WECHAT_SP_APPID = "wx6260718c6fd46efb";
+    public static final String WECHAT_SP_APPID = "wx43b5b906cc30ed0b";
 
-    public static final String WECHAT_SUB_MCH_ID = "1726610149";
+    public static final String WECHAT_SUB_MCH_ID = "1726971843";
 
-    public static final String WECHAT_SUB_APPID = "wx6260718c6fd46efb";
+    public static final String WECHAT_SUB_APPID = "wxc032a09413289004";
 
     //微信商户平台v2密钥
-    public static final String WECHAT_MCH_SECRET_V2 = "dkrxaNfksjhDFxg1pGVuraIBahNwp1zX";
+    public static final String WECHAT_MCH_SECRET_V2 = "4b64e17419689527b256f07cdf6bd60c";
 
     //微信商户平台v3密钥
-    public static final String WECHAT_MCH_SECRET_V3 = "dkrxaNfksjhDFxg1pGVuraIBahNwp1zX";
+    public static final String WECHAT_MCH_SECRET_V3 = "4b64e17419689527b256f07cdf6bd60c";
 
     //微信商户平台服务商证书序列号
-    public static final String WECHAT_MCH_SERIAL_NUM = "491DF89D133A1562A0AF2C98E8536823CB9B9D3D";
+    public static final String WECHAT_MCH_SERIAL_NUM = "65E9559D81ADA0BDA0CD3CF484A59A8DFB5610BE";
 
     //微信商户平台证书私钥 即证书中的apiclient_key.pem文件中的内容 可以直接写在这里 也可以用流读取文件
     public static final String WECHAT_MCH_PRIVATE_KEY = "-----BEGIN PRIVATE KEY-----\n" +
-            "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDozU6RJZN43U1m\n" +
-            "IYSNg20ukw4dGhmZgs8q082VLl0pY43IRlndQMLcyDh7ZsAwHt1R0YaqM9RvRuBH\n" +
-            "tQcwKHgxiNzXxADx/XoGMAUJz8TiAcv/xbGK8C74Cjq5YUJIlE0f2UH2vQMvihi1\n" +
-            "fPwSsxXJGLgu3/UajXe/zc+YrmhWnpAHU46mVJ/BLEwzBVmfcgGXAPJ/sh57zcSo\n" +
-            "ayWLYLj7nUZ8KI22DEYHDjeZD0i8wcfCVpwfsnqSO3bd2HgXSrDA5UiObXPPypM3\n" +
-            "5Qknf06sXCYa0G2Ui4YlGsC2DTBu0d7p8b/hOe7vyVzXw72uJDQ4GGd8wDiXxnGk\n" +
-            "vnEKTka3AgMBAAECggEBAIeWm/3Znsy0R9IGD4fEViDcMUot218XWsWc2o3alRP4\n" +
-            "Eanln41HnLauPodQzvq33zs6B262BTJSW2ooO2mHCIoBJm7cj5hhg2J7MVQHmKnx\n" +
-            "VflAESnUveZlPtKdnNdc2JaGGO82ItbbXYzGoKHbgALBzPQwKDcw0d/6ZMCOQ+K+\n" +
-            "FrwLi+93HXlW6jGrPAgJ09kcim6efZOHvxFdZq8zMBFoZeiGnGj6G0peHI5PGb8V\n" +
-            "YKjBXiuxHs96w079R3eID1ViiNnGonm6M9AWT2mxMYMt/VPTr0TZUUet6DmKRs+0\n" +
-            "T3XuqoIunpju5RwWDN9CRdIysc5Ylo9U5rnLjBv6ygECgYEA+ipaz9mvqGo9+EQ2\n" +
-            "30VVGpY1W8r4oOZu8pSnmm9FXZFLVznnq0CB22F7fp1WLr3Yr0XoL2NOHZFVtzT8\n" +
-            "5ww9//o/OUgY3uVC9UoosUtSPowAZeldRc2JaFABusQw34/E96BVeuqTZgFxyvo2\n" +
-            "sAmtBfDXHCOjEmwZlaumKNxw3YECgYEA7jtIBTAE70nPTh7s3Kb81L2k0BT2JVki\n" +
-            "VZdBRPqj/mMxu6MEJ5UjzNhZEH3FXHxxC4Oe8v/r1opxs6ES5RnqQ+agtL5mUBn/\n" +
-            "B0327/96DKZWaKFCaoieCUamY/3jqguoIdK80kjGX6xuQISw5tCCJVrnEuxW+CmI\n" +
-            "XDrcOsTGsDcCgYBck+IJe1i7LZ4DS1M3KxREg4P5lVKPUNeMJCEmULlN2CAWhpJK\n" +
-            "WNP1mMy33YfwQkd3DZrQNqLI5GjhJNXWtzwWh8hv7VNu4U73MVt/yQ0Foo/fJw5i\n" +
-            "b57DIKCTOlmP0kelEAuyMi8cF7rBz/j/CoWiZi9k9Xc6sRCCyAP0qSeHgQKBgBpl\n" +
-            "2z8n6QQS67O+XYS9xDpWoVKlX/kXfWR6lDLuiwl/OF2QXL9+GS9zsbrQFPSAnY4n\n" +
-            "EY/fp+RoBt1etddJHdpUTe55QqERoF7Q1tIVPxLzw5NoexGO/eQNPhbKZVXMYN8O\n" +
-            "mPm8Mq8bTkQ779ZDuIgnIH/KTIDHKWL+6rRgZZvVAoGALZn4IpUhcRe7v/+pnYSQ\n" +
-            "6AhmUmTM3OdAA+XJDMuZzDM+5DNmuhZx4Y9sw/Xg1+kejR0W48aFNZ4xhSz89XC6\n" +
-            "rusYJfTda1iqqlaH453yJti98u2EkESJMdY2YlT7H75VjD/A1o1Fn3qnGStn9CKt\n" +
-            "DOukDtlOzybCJFsjG5uBwcg=\n" +
-            "-----END PRIVATE KEY-----\n";
+            "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC7aKXAWrNy4W9N\n" +
+            "Mv2Ah9zp1VQDZk68nWX3EfACgHdCXhqF2mhzUqQJHGjumqkSBKdTwDTzgXCcs7EK\n" +
+            "PSIeWXSajfbyn8f5cYupRYESFvrIpiHaRh3aUTNVmfRiXLN6zMSiAUkgPp3mZXzZ\n" +
+            "lp38wPZS1Vl+S8lesETEqnE/qFK6A2MKCjOFbtCNQIsPc4q70JzgAwNx20giHNMm\n" +
+            "h6TN41as1Qu6PVpamvNLgLp4U2GBInURpHLUqVJfQOezCOHUEkDxtcdY30Nb4aIF\n" +
+            "FzSLzGssczduovhm8b57Wy0dD5crGKZVGsix3m9CXd+BshJDYIB/EAivU+npK4Tz\n" +
+            "inA7K0wdAgMBAAECggEASTeFKjVFTmiMl1iIeaKayDAz9nAN6tqDb5ducUvHTAJ/\n" +
+            "0jOWAxgSRgz3YeDClOuEg8/f4BJ98HqzfBCON9UzHP7Br+CEvAuESMmCt5KKv8FI\n" +
+            "EIK8PwLiT1sqgxM8e4lseO6Ppy1PeyfDMy8I4ipxEcOQhysMrRWoiD0eqYQVbd4g\n" +
+            "YfOEsq8EbSHr+sDHgFJM5hEEHEWNvSUUSjifuo861SkYEtjQcg5AKflPce9Fz7Ze\n" +
+            "UNxHEh+gAOvDzkFTlVSnqhUR3G2EeoFSwALwNMNJW4vBiQ16InhAlsUPh5zByPBS\n" +
+            "HAbfiNYNUgYQM5PUy2YSamMXwUAAvNvcrbNUN6PrgQKBgQD4OtObOKB60zZYuRfa\n" +
+            "6lpfIxT4EeaP7aGFc+vL20ZFTEhueWAHw8opznrRwWa3zok1T+PhJHJ0BeLsU+m1\n" +
+            "Y4BVDHNw7rfKxMaw63LL2AGnx2wmeDDm1bliPvnQrc7KVqQsgu31+xuOKcgL5brg\n" +
+            "YdxfXPyHP7vAfI8RaanGHS3luQKBgQDBRm+FAELD/O0Hsn8Eyz6tehTG0AqyLdCE\n" +
+            "DmKjC1cQnQVDWReFRcLjFQZLd3eajNe9L1liyqnKERnJCgsyxaygmZVnt4xdwRSm\n" +
+            "dV76SFV6+kXs9dDILeRNhybyfAIdrijv60gF8uVfUMhbQGtpuEs9e+1UhP5TcvbS\n" +
+            "Y10Q3xQLhQKBgQDTcrjiVkBNoDGBLlolvs+wjt/D2Ou/2rpmRbKsemLHkQ16HaYx\n" +
+            "txQ0vJBesRJgrGywnxcMp9FfB8yfZ3ODcfjVeb+0iYTCExD1j/q/rYbrdrKnqmZt\n" +
+            "m81I5UBEBGpMbbV3vSgbCwYT+X9QsyaXEIV6LmlmhGHYu8HbIVjfS+fW8QKBgQCn\n" +
+            "083Ko+tV3C7G3ExHkWUfpj6cVNK03euOgB9OjO5RUsfbL2WpKGaOYRdSOK722Q4N\n" +
+            "DSyFCI5fFHJbjAklUVkRK8v8f/m2/4467PhIRL9VRjWqCdn9uTvhxlYfgWck9rI9\n" +
+            "gwTLhZt/JNqVwl6DMrDC9vWiysk9FTsWfYm2uL7jMQKBgQDy2kud6Ct2wvN6AakJ\n" +
+            "PrXwvW0FVrI5ieGS4eG0cUWiK/7S1TjyyuF/dJYabxVtXnYXCLTztFigPCVNWeog\n" +
+            "R9FQITYKducHCS/Gjz53ksEeX9LuUB78gyrqiGvq5iyKKOsYvh9j3YmLpZgeQ1CE\n" +
+            "be6f9A6UjSGKP4qEvgJhIy09bw==\n" +
+            "-----END PRIVATE KEY-----";
 
     //微信小程序支付类型
     public static final String WECHAT_TRADE_TYPE = "JSAPI";

+ 2 - 3
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/pay/util/WechatPayV3Utils.java → national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/pay/config/WechatPayV3Utils.java

@@ -1,4 +1,4 @@
-package org.jeecg.modules.pay.util;
+package org.jeecg.modules.pay.config;
 
 import com.alibaba.fastjson2.JSONObject;
 import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
@@ -18,7 +18,6 @@ import org.apache.http.client.utils.URIBuilder;
 import org.apache.http.entity.StringEntity;
 import org.apache.http.impl.client.CloseableHttpClient;
 import org.apache.http.util.EntityUtils;
-import org.jeecg.modules.pay.config.WechatConstants;
 import org.springframework.stereotype.Component;
 
 import javax.servlet.http.HttpServletRequest;
@@ -49,7 +48,7 @@ public class WechatPayV3Utils {
      * 获取商户证书私钥
      */
     private void setMerchantPrivateKey() throws Exception {
-//        ClassPathResource classPathResource = new ClassPathResource("cer/apiclient_key.pem");
+//        ClassPathResource classPathResource = new ClassPathResource("cert/apiclient_key.pem");
 //        InputStream certStream = classPathResource.getInputStream();
 //        //读取文件形式加载商户私钥
 //        merchantPrivateKey = PemUtil.loadPrivateKey(certStream);

+ 5 - 20
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/pay/config/WechatUrlConstants.java

@@ -3,38 +3,23 @@ package org.jeecg.modules.pay.config;
 /**
  * @author wangzhiqiang
  * @Date 2025/08/21
- * @Desc 微信相关接口请求地址 其中最后四个通知接口地址,是自己服务器的接口地址,必须为外网可访问的url,不能携带参数。 公网域名必须为https,如果是走专线接入,使用专线NAT IP或者私有回调域名可使用http。
+ * @Desc 微信相关接口请求地址
  */
 public class WechatUrlConstants {
 
-    //小程序code获取openid
-    public final static String CODE_2_SESSION = "https://api.weixin.qq.com/sns/jscode2session";
-
     //微信支付v3 jsapi下单
-    public final static String PAY_V3_JSAPI = "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi";
-
-    //微信支付v3 H5下单
-    public final static String PAY_V3_H5 = "https://api.mch.weixin.qq.com/v3/pay/transactions/h5";
+    public final static String PAY_V3_JSAPI = "https://api.mch.weixin.qq.com/v3/pay/partner/transactions/jsapi";
 
     //微信支付v3 申请退款
-    public final static String PAY_V3_REFUND = "https://api.mch.weixin.qq.com/v3/refund/domestic/refunds";
+    public final static String PAY_V3_REFUND = "https://api.mch.weixin.qq.com/v3/pay/partner/transactions/out-trade-no/{out_trade_no}";
 
     //微信支付v3 通过商户订单号查询订单
     public final static String PAY_V3_QUERY_OUT = "https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/%s?mchid=%s";
 
-    //微信支付v3 查询单笔退款
-    public final static String PAY_V3_QUERY_REFUND = "https://api.mch.weixin.qq.com/v3/refund/domestic/refunds/%s";
-
-    //微信支付v2 支付通知接口地址
-    public final static String PAY_V2_NOTIFY = "https://xxx.com/api/wechatPay/wechatPayNotify";
-
-    //微信支付v2 退款通知接口地址
-    public final static String PAY_V2_REFUND_NOTIFY = "https://xxx.com/api/wechatPay/wechatRefundNotify";
-
     //微信支付v3 支付通知接口地址
-    public final static String PAY_V3_NOTIFY = "https://610cfedc.r28.cpolar.top/jeecg-boot/app/order/wechatPayNotify";
+    public final static String PAY_V3_NOTIFY = "https://1caa0b6f.r28.cpolar.top/jeecg-boot/app/order/wechatPayNotify";
 
     //微信支付v3 退款通知接口地址
-    public final static String PAY_V3_REFUND_NOTIFY = "https://610cfedc.r28.cpolar.top/jeecg-boot/app/order/refundOrderNotify";
+    public final static String PAY_V3_REFUND_NOTIFY = "https://1caa0b6f.r28.cpolar.top/jeecg-boot/app/order/refundOrderNotify";
 
 }

+ 121 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/pay/entity/TransactionInfo.java

@@ -0,0 +1,121 @@
+package org.jeecg.modules.pay.entity;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+import java.util.Date;
+import java.util.List;
+
+@Data
+public class TransactionInfo {
+ 
+    @JsonProperty("transaction_id")
+    private String transactionId;
+ 
+    private Amount amount;
+ 
+    @JsonProperty("sub_mchid")
+    private String subMchId;
+ 
+    @JsonProperty("trade_state")
+    private String tradeState;
+ 
+    @JsonProperty("bank_type")
+    private String bankType;
+ 
+    @JsonProperty("promotion_detail")
+    private List<PromotionDetail> promotionDetail;
+ 
+    @JsonProperty("success_time")
+    @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ssXXX")
+    private Date successTime;
+ 
+    private Payer payer;
+ 
+    @JsonProperty("out_trade_no")
+    private String outTradeNo;
+ 
+    private String appid;
+ 
+    @JsonProperty("trade_state_desc")
+    private String tradeStateDesc;
+ 
+    @JsonProperty("trade_type")
+    private String tradeType;
+ 
+    private String attach;
+ 
+    @JsonProperty("scene_info")
+    private SceneInfo sceneInfo;
+ 
+    @Data
+    public static class Amount {
+        @JsonProperty("payer_total")
+        private Integer payerTotal;
+ 
+        private Integer total;
+ 
+        private String currency;
+ 
+        @JsonProperty("payer_currency")
+        private String payerCurrency;
+    }
+ 
+    @Data
+    public static class PromotionDetail {
+        private Integer amount;
+ 
+        @JsonProperty("wechatpay_contribute")
+        private Integer wechatpayContribute;
+ 
+        @JsonProperty("coupon_id")
+        private String couponId;
+ 
+        private String scope;
+ 
+        @JsonProperty("merchant_contribute")
+        private Integer merchantContribute;
+ 
+        private String name;
+ 
+        @JsonProperty("other_contribute")
+        private Integer otherContribute;
+ 
+        private String currency;
+ 
+        @JsonProperty("stock_id")
+        private String stockId;
+ 
+        @JsonProperty("goods_detail")
+        private List<GoodsDetail> goodsDetail;
+    }
+ 
+    @Data
+    public static class GoodsDetail {
+        @JsonProperty("goods_remark")
+        private String goodsRemark;
+ 
+        private Integer quantity;
+ 
+        @JsonProperty("discount_amount")
+        private Integer discountAmount;
+ 
+        @JsonProperty("goods_id")
+        private String goodsId;
+ 
+        @JsonProperty("unit_price")
+        private Integer unitPrice;
+    }
+ 
+    @Data
+    public static class Payer {
+        private String openid;
+    }
+ 
+    @Data
+    public static class SceneInfo {
+        @JsonProperty("device_id")
+        private String deviceId;
+    }
+}

+ 52 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/pay/paytest/AesUtil.java

@@ -0,0 +1,52 @@
+package org.jeecg.modules.pay.paytest;
+ 
+/**
+ * @Description:
+ * @Author sk
+ * @Date: 2023/7/5 14:31
+ */
+ 
+import javax.crypto.Cipher;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.spec.GCMParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.util.Base64;
+ 
+/**
+ * 回调签名配置
+ * @author liaozan8888@163.com
+ */
+public class AesUtil {
+    static final int KEY_LENGTH_BYTE = 32;
+    static final int TAG_LENGTH_BIT = 128;
+    private final byte[] aesKey;
+ 
+    public AesUtil(byte[] key) {
+        if (key.length != KEY_LENGTH_BYTE) {
+            throw new IllegalArgumentException("无效的ApiV3Key,长度必须为32个字节");
+        }
+        this.aesKey = key;
+    }
+    public String decryptToString(byte[] associatedData, byte[] nonce, String ciphertext) throws GeneralSecurityException, IOException {
+        try {
+            Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
+ 
+            SecretKeySpec key = new SecretKeySpec(aesKey, "AES");
+            GCMParameterSpec spec = new GCMParameterSpec(TAG_LENGTH_BIT, nonce);
+ 
+            cipher.init(Cipher.DECRYPT_MODE, key, spec);
+            cipher.updateAAD(associatedData);
+ 
+            return new String(cipher.doFinal(Base64.getDecoder().decode(ciphertext)), "utf-8");
+        } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
+            throw new IllegalStateException(e);
+        } catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
+            throw new IllegalArgumentException(e);
+        }
+    }
+}

+ 143 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/pay/paytest/PayMerchantUtil.java

@@ -0,0 +1,143 @@
+package org.jeecg.modules.pay.paytest;
+
+import cn.hutool.core.util.RandomUtil;
+import com.alibaba.fastjson2.JSONObject;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
+import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
+import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
+import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
+import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
+import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager;
+import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
+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.util.EntityUtils;
+ 
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.nio.charset.StandardCharsets;
+import java.security.*;
+import java.util.Base64;
+ 
+/**
+ * 服务商的下单工具类
+ * @author liaozan8888@163.com
+ */
+public class PayMerchantUtil {
+    private CloseableHttpClient httpClient;
+    private CertificatesManager certificatesManager;
+    private Verifier verifier;
+
+    /**
+     * JsApi下单  具体下单场景查看官方文档
+     *
+     * @param total
+     * @param description
+     * @return
+     * @throws Exception
+     */
+    public String requestwxChatPay(String orderSn, int total, String description, String openid) throws Exception {
+
+        PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(new ByteArrayInputStream(ServiceProvider.privateKey.getBytes("utf-8")));
+        // 获取证书管理器实例
+        certificatesManager = CertificatesManager.getInstance();
+        // 向证书管理器增加需要自动更新平台证书的商户信息
+        PrivateKeySigner privateKeySigner = new PrivateKeySigner(ServiceProvider.MCH_SERIAL_NO, merchantPrivateKey);
+        WechatPay2Credentials wechatPay2Credentials = new WechatPay2Credentials(ServiceProvider.sp_mchid, privateKeySigner);
+        certificatesManager.putMerchant(ServiceProvider.sp_mchid, wechatPay2Credentials, ServiceProvider.API_3KEY.getBytes(StandardCharsets.UTF_8));
+        // 从证书管理器中获取verifier
+        verifier = certificatesManager.getVerifier(ServiceProvider.sp_mchid);
+        httpClient = WechatPayHttpClientBuilder.create()
+                .withMerchant(ServiceProvider.sp_mchid, ServiceProvider.MCH_SERIAL_NO, merchantPrivateKey)
+                .withValidator(new WechatPay2Validator(verifier))
+                .build();
+
+        HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/partner/transactions/jsapi");
+        httpPost.addHeader("Accept", "application/json");
+        httpPost.addHeader("Content-type", "application/json; charset=utf-8");
+
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        ObjectMapper objectMapper = new ObjectMapper();
+        //组合请求参数JSON格式
+        ObjectNode rootNode = objectMapper.createObjectNode();
+        rootNode.put("sp_appid", ServiceProvider.sp_appid)
+                .put("sp_mchid", ServiceProvider.sp_mchid)
+                .put("sub_mchid", ServiceProvider.sub_mchid)
+                .put("sub_appid", ServiceProvider.sub_appid)
+                // 回调地址
+                .put("notify_url", ServiceProvider.NOTIFY_URL + "jeecg-boot/app/order/refundOrderNotify")
+                .put("description", description)
+                .put("out_trade_no", orderSn);
+        rootNode.putObject("amount")
+                // total:金额,以分为单位,假如是10块钱,那就要写 1000
+                .put("total", total)
+                .put("currency", "CNY");
+        rootNode.putObject("payer")
+                .put("sp_openid", openid);// openid
+        try {
+            objectMapper.writeValue(bos, rootNode);
+            httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
+            //获取预支付ID
+            CloseableHttpResponse response = httpClient.execute(httpPost);
+            String bodyAsString = EntityUtils.toString(response.getEntity());
+            //微信成功响应
+            int statusCode = response.getStatusLine().getStatusCode();
+            if (statusCode == 200) {
+                //时间戳
+                String timestamp = System.currentTimeMillis() / 1000 + "";
+                //随机字符串
+                String nonce = RandomUtil.randomString(32);
+                StringBuilder builder = new StringBuilder();
+
+                // Appid
+                builder.append(ServiceProvider.sp_appid).append("\n");
+                // 时间戳
+                builder.append(timestamp).append("\n");
+                // 随机字符串
+                builder.append(nonce).append("\n");
+                JsonNode jsonNode = objectMapper.readTree(bodyAsString);
+                // 预支付会话ID
+                builder.append("prepay_id=").append(jsonNode.get("prepay_id").textValue()).append("\n");
+                //获取签名
+                String sign = this.sign(builder.toString().getBytes("utf-8"), merchantPrivateKey);
+
+                JSONObject jsonMap = new JSONObject();
+                jsonMap.put("noncestr", nonce);
+                jsonMap.put("timestamp", timestamp);
+                jsonMap.put("prepayid", jsonNode.get("prepay_id").textValue());
+                jsonMap.put("sign", sign);
+                jsonMap.put("appid", ServiceProvider.sp_appid);
+                jsonMap.put("partnerid", ServiceProvider.sp_mchid);
+
+                return jsonMap.toJSONString();//响应签名数据,前端拿着响应数据调起微信SDK
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    /**
+     * 计算签名
+     *
+     * @param message
+     * @param yourPrivateKey
+     * @return
+     */
+    private String sign(byte[] message, PrivateKey yourPrivateKey) {
+        try {
+            Signature sign = Signature.getInstance("SHA256withRSA");
+            sign.initSign(yourPrivateKey);
+            sign.update(message);
+            return Base64.getEncoder().encodeToString(sign.sign());
+        } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) {
+            e.printStackTrace();
+        }
+        return "";
+    }
+}

+ 56 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/pay/paytest/ServiceProvider.java

@@ -0,0 +1,56 @@
+package org.jeecg.modules.pay.paytest;
+ 
+/**
+ * @Description:
+ * @Author sk
+ * @Date: 2023/7/5 14:31
+ */
+ 
+/**
+ * 服务商模式
+ */
+public interface ServiceProvider {
+    //服务商的商户号
+    String sp_mchid = "1725845681";
+    // ApId
+    String sp_appid = "wx43b5b906cc30ed0b";
+    // 子商户号
+    String sub_mchid = "1726971843";
+    // ApId
+    String sub_appid = "wxbcba29ef4f698074";
+    // 服务商的商户证书序列号
+    String MCH_SERIAL_NO = "65E9559D81ADA0BDA0CD3CF484A59A8DFB5610BE";
+    // 服务商的V3的密钥
+    String API_3KEY = "4b64e17419689527b256f07cdf6bd60c";
+    // 回调地址
+    String NOTIFY_URL = "https://1caa0b6f.r28.cpolar.top/";
+ 
+    String privateKey = "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC7aKXAWrNy4W9N\n" +
+            "Mv2Ah9zp1VQDZk68nWX3EfACgHdCXhqF2mhzUqQJHGjumqkSBKdTwDTzgXCcs7EK\n" +
+            "PSIeWXSajfbyn8f5cYupRYESFvrIpiHaRh3aUTNVmfRiXLN6zMSiAUkgPp3mZXzZ\n" +
+            "lp38wPZS1Vl+S8lesETEqnE/qFK6A2MKCjOFbtCNQIsPc4q70JzgAwNx20giHNMm\n" +
+            "h6TN41as1Qu6PVpamvNLgLp4U2GBInURpHLUqVJfQOezCOHUEkDxtcdY30Nb4aIF\n" +
+            "FzSLzGssczduovhm8b57Wy0dD5crGKZVGsix3m9CXd+BshJDYIB/EAivU+npK4Tz\n" +
+            "inA7K0wdAgMBAAECggEASTeFKjVFTmiMl1iIeaKayDAz9nAN6tqDb5ducUvHTAJ/\n" +
+            "0jOWAxgSRgz3YeDClOuEg8/f4BJ98HqzfBCON9UzHP7Br+CEvAuESMmCt5KKv8FI\n" +
+            "EIK8PwLiT1sqgxM8e4lseO6Ppy1PeyfDMy8I4ipxEcOQhysMrRWoiD0eqYQVbd4g\n" +
+            "YfOEsq8EbSHr+sDHgFJM5hEEHEWNvSUUSjifuo861SkYEtjQcg5AKflPce9Fz7Ze\n" +
+            "UNxHEh+gAOvDzkFTlVSnqhUR3G2EeoFSwALwNMNJW4vBiQ16InhAlsUPh5zByPBS\n" +
+            "HAbfiNYNUgYQM5PUy2YSamMXwUAAvNvcrbNUN6PrgQKBgQD4OtObOKB60zZYuRfa\n" +
+            "6lpfIxT4EeaP7aGFc+vL20ZFTEhueWAHw8opznrRwWa3zok1T+PhJHJ0BeLsU+m1\n" +
+            "Y4BVDHNw7rfKxMaw63LL2AGnx2wmeDDm1bliPvnQrc7KVqQsgu31+xuOKcgL5brg\n" +
+            "YdxfXPyHP7vAfI8RaanGHS3luQKBgQDBRm+FAELD/O0Hsn8Eyz6tehTG0AqyLdCE\n" +
+            "DmKjC1cQnQVDWReFRcLjFQZLd3eajNe9L1liyqnKERnJCgsyxaygmZVnt4xdwRSm\n" +
+            "dV76SFV6+kXs9dDILeRNhybyfAIdrijv60gF8uVfUMhbQGtpuEs9e+1UhP5TcvbS\n" +
+            "Y10Q3xQLhQKBgQDTcrjiVkBNoDGBLlolvs+wjt/D2Ou/2rpmRbKsemLHkQ16HaYx\n" +
+            "txQ0vJBesRJgrGywnxcMp9FfB8yfZ3ODcfjVeb+0iYTCExD1j/q/rYbrdrKnqmZt\n" +
+            "m81I5UBEBGpMbbV3vSgbCwYT+X9QsyaXEIV6LmlmhGHYu8HbIVjfS+fW8QKBgQCn\n" +
+            "083Ko+tV3C7G3ExHkWUfpj6cVNK03euOgB9OjO5RUsfbL2WpKGaOYRdSOK722Q4N\n" +
+            "DSyFCI5fFHJbjAklUVkRK8v8f/m2/4467PhIRL9VRjWqCdn9uTvhxlYfgWck9rI9\n" +
+            "gwTLhZt/JNqVwl6DMrDC9vWiysk9FTsWfYm2uL7jMQKBgQDy2kud6Ct2wvN6AakJ\n" +
+            "PrXwvW0FVrI5ieGS4eG0cUWiK/7S1TjyyuF/dJYabxVtXnYXCLTztFigPCVNWeog\n" +
+            "R9FQITYKducHCS/Gjz53ksEeX9LuUB78gyrqiGvq5iyKKOsYvh9j3YmLpZgeQ1CE\n" +
+            "be6f9A6UjSGKP4qEvgJhIy09bw==";
+ 
+}
+ 

+ 24 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/pay/paytest/payController.java

@@ -0,0 +1,24 @@
+package org.jeecg.modules.pay.paytest;
+
+
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+ 
+
+@RestController
+@RequestMapping(value = "/test")
+public class payController {
+
+    @GetMapping(value = "/getPay")
+    public String getPay(String orderSn,int total , String description) {
+        PayMerchantUtil payMerchantUtil = new PayMerchantUtil();
+        try {
+            return payMerchantUtil.requestwxChatPay(orderSn, total, description, "oYgFI91D00GpCwccdnKDR4KNxI4k");
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+ 
+}
+ 

+ 0 - 182
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/pay/serverPay/PartnerAppPrepay.java

@@ -1,182 +0,0 @@
-package org.jeecg.modules.pay.serverPay;
- 
-import com.google.gson.annotations.SerializedName;
-import okhttp3.*;
- 
-import java.io.IOException;
-import java.io.UncheckedIOException;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.util.List;
- 
-/**
- * App下单
- */
-public class PartnerAppPrepay {
-  private static String HOST = "https://api.mch.weixin.qq.com";
-  private static String METHOD = "POST";
-  private static String PATH = "/v3/pay/partner/transactions/app";
- 
-  public PartnerAPIv3AppPrepayResponse run(PartnerAPIv3CommonPrepayRequest request) {
-    String uri = PATH;
-    String reqBody = WXPayUtility.toJson(request);
- 
-    Request.Builder reqBuilder = new Request.Builder().url(HOST + uri);
-    reqBuilder.addHeader("Accept", "application/json");
-    reqBuilder.addHeader("Wechatpay-Serial", wechatPayPublicKeyId);
-    reqBuilder.addHeader("Authorization", WXPayUtility.buildAuthorization(mchid, certificateSerialNo, privateKey, METHOD, uri, reqBody));
-    reqBuilder.addHeader("Content-Type", "application/json");
-    RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), reqBody);
-    reqBuilder.method(METHOD, requestBody);
-    Request httpRequest = reqBuilder.build();
- 
-    // 发送HTTP请求
-    OkHttpClient client = new OkHttpClient.Builder().build();
-    try (Response httpResponse = client.newCall(httpRequest).execute()) {
-      String respBody = WXPayUtility.extractBody(httpResponse);
-      if (httpResponse.code() >= 200 && httpResponse.code() < 300) {
-        // 2XX 成功,验证应答签名
-        WXPayUtility.validateResponse(this.wechatPayPublicKeyId, this.wechatPayPublicKey,
-                                      httpResponse.headers(), respBody);
-        // 从HTTP应答报文构建返回数据
-        return WXPayUtility.fromJson(respBody, PartnerAPIv3AppPrepayResponse.class);
-      } else {
-        throw new WXPayUtility.ApiException(httpResponse.code(), respBody, httpResponse.headers());
-      }
-    } catch (IOException e) {
-      throw new UncheckedIOException("Sending request to " + uri + " failed.", e);
-    }
-  }
- 
-  private final String mchid;
-  private final String certificateSerialNo;
-  private final PrivateKey privateKey;
-  private final String wechatPayPublicKeyId;
-  private final PublicKey wechatPayPublicKey;
- 
-  public PartnerAppPrepay(String mchid, String certificateSerialNo, String privateKeyFilePath, String wechatPayPublicKeyId, String wechatPayPublicKeyFilePath) {
-    this.mchid = mchid;
-    this.certificateSerialNo = certificateSerialNo;
-    this.privateKey = WXPayUtility.loadPrivateKeyFromPath(privateKeyFilePath);
-    this.wechatPayPublicKeyId = wechatPayPublicKeyId;
-    this.wechatPayPublicKey = WXPayUtility.loadPublicKeyFromPath(wechatPayPublicKeyFilePath);
-  }
- 
-  public static class PartnerSettleInfo {
-    @SerializedName("profit_sharing")
-    public Boolean profitSharing;
-  }
- 
-  public static class CommonAmountInfo {
-    @SerializedName("total")
-    public Long total;
- 
-    @SerializedName("currency")
-    public String currency;
-  }
- 
-  public static class CommonSceneInfo {
-    @SerializedName("payer_client_ip")
-    public String payerClientIp;
- 
-    @SerializedName("device_id")
-    public String deviceId;
- 
-    @SerializedName("store_info")
-    public StoreInfo storeInfo;
-  }
- 
-  public static class GoodsDetail {
-    @SerializedName("merchant_goods_id")
-    public String merchantGoodsId;
- 
-    @SerializedName("wechatpay_goods_id")
-    public String wechatpayGoodsId;
- 
-    @SerializedName("goods_name")
-    public String goodsName;
- 
-    @SerializedName("quantity")
-    public Long quantity;
- 
-    @SerializedName("unit_price")
-    public Long unitPrice;
-  }
- 
-  public static class PartnerAPIv3AppPrepayResponse {
-    @SerializedName("prepay_id")
-    public String prepayId;
-  }
- 
-  public static class PartnerAPIv3CommonPrepayRequest {
-    @SerializedName("sp_appid")
-    public String spAppid;
- 
-    @SerializedName("sp_mchid")
-    public String spMchid;
- 
-    @SerializedName("sub_appid")
-    public String subAppid;
- 
-    @SerializedName("sub_mchid")
-    public String subMchid;
- 
-    @SerializedName("description")
-    public String description;
- 
-    @SerializedName("out_trade_no")
-    public String outTradeNo;
- 
-    @SerializedName("time_expire")
-    public String timeExpire;
- 
-    @SerializedName("attach")
-    public String attach;
- 
-    @SerializedName("notify_url")
-    public String notifyUrl;
- 
-    @SerializedName("goods_tag")
-    public String goodsTag;
- 
-    @SerializedName("settle_info")
-    public PartnerSettleInfo settleInfo;
- 
-    @SerializedName("support_fapiao")
-    public Boolean supportFapiao;
- 
-    @SerializedName("amount")
-    public CommonAmountInfo amount;
- 
-    @SerializedName("detail")
-    public CouponInfo detail;
- 
-    @SerializedName("scene_info")
-    public CommonSceneInfo sceneInfo;
-  }
- 
-  public static class CouponInfo {
-    @SerializedName("cost_price")
-    public Long costPrice;
- 
-    @SerializedName("invoice_id")
-    public String invoiceId;
- 
-    @SerializedName("goods_detail")
-    public List<GoodsDetail> goodsDetail;
-  }
- 
-  public static class StoreInfo {
-    @SerializedName("id")
-    public String id;
- 
-    @SerializedName("name")
-    public String name;
- 
-    @SerializedName("area_code")
-    public String areaCode;
- 
-    @SerializedName("address")
-    public String address;
-  }
-}

+ 185 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/pay/serverPay/PartnerJsApiPrepay.java

@@ -0,0 +1,185 @@
+package org.jeecg.modules.pay.serverPay;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.extern.slf4j.Slf4j;
+import okhttp3.*;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.util.List;
+
+/**
+ * JsApi下单
+ */
+@Slf4j
+public class PartnerJsApiPrepay {
+    private static String HOST = "https://api.mch.weixin.qq.com";
+    private static String METHOD = "POST";
+    private static String PATH = "/v3/pay/partner/transactions/jsapi";
+
+    public PartnerAPIv3AppPrepayResponse run(PartnerAPIv3CommonPrepayRequest request) {
+        String uri = PATH;
+        String reqBody = WXPayUtility.toJson(request);
+
+        Request.Builder reqBuilder = new Request.Builder().url(HOST + uri);
+        reqBuilder.addHeader("Accept", "application/json");
+        reqBuilder.addHeader("Wechatpay-Serial", wechatPayPublicKeyId);
+        reqBuilder.addHeader("Authorization", WXPayUtility.buildAuthorization(mchid, certificateSerialNo, privateKey, METHOD, uri, reqBody));
+        reqBuilder.addHeader("Content-Type", "application/json");
+        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), reqBody);
+        reqBuilder.method(METHOD, requestBody);
+        Request httpRequest = reqBuilder.build();
+
+        // 发送HTTP请求
+        OkHttpClient client = new OkHttpClient.Builder().build();
+        try (Response httpResponse = client.newCall(httpRequest).execute()) {
+            String respBody = WXPayUtility.extractBody(httpResponse);
+            if (httpResponse.code() >= 200 && httpResponse.code() < 300) {
+                // 2XX 成功,验证应答签名
+                WXPayUtility.validateResponse(this.wechatPayPublicKeyId, this.wechatPayPublicKey,
+                        httpResponse.headers(), respBody);
+                // 从HTTP应答报文构建返回数据
+                return WXPayUtility.fromJson(respBody, PartnerAPIv3AppPrepayResponse.class);
+            } else {
+                throw new WXPayUtility.ApiException(httpResponse.code(), respBody, httpResponse.headers());
+            }
+        } catch (IOException e) {
+            log.error("发送请求至{} 失败。", uri);
+            throw new UncheckedIOException("Sending request to " + uri + " failed.", e);
+        }
+    }
+
+    private final String mchid;
+    private final String certificateSerialNo;
+    private final PrivateKey privateKey;
+    private final String wechatPayPublicKeyId;
+    private final PublicKey wechatPayPublicKey;
+
+    public PartnerJsApiPrepay(String mchid, String certificateSerialNo, String privateKeyFilePath, String wechatPayPublicKeyId, String wechatPayPublicKeyFilePath) {
+        this.mchid = mchid;
+        this.certificateSerialNo = certificateSerialNo;
+        this.privateKey = WXPayUtility.loadPrivateKeyFromPath(privateKeyFilePath);
+        this.wechatPayPublicKeyId = wechatPayPublicKeyId;
+        this.wechatPayPublicKey = WXPayUtility.loadPublicKeyFromPath(wechatPayPublicKeyFilePath);
+    }
+
+    public static class PartnerSettleInfo {
+        @SerializedName("profit_sharing")
+        public Boolean profitSharing;
+    }
+
+    public static class CommonAmountInfo {
+        @SerializedName("total")
+        public Long total;
+
+        @SerializedName("currency")
+        public String currency;
+    }
+
+    public static class CommonSceneInfo {
+        @SerializedName("payer_client_ip")
+        public String payerClientIp;
+
+        @SerializedName("device_id")
+        public String deviceId;
+
+        @SerializedName("store_info")
+        public StoreInfo storeInfo;
+    }
+
+    public static class GoodsDetail {
+        @SerializedName("merchant_goods_id")
+        public String merchantGoodsId;
+
+        @SerializedName("wechatpay_goods_id")
+        public String wechatpayGoodsId;
+
+        @SerializedName("goods_name")
+        public String goodsName;
+
+        @SerializedName("quantity")
+        public Long quantity;
+
+        @SerializedName("unit_price")
+        public Long unitPrice;
+    }
+
+    public static class PartnerAPIv3AppPrepayResponse {
+        @SerializedName("prepay_id")
+        public String prepayId;
+    }
+
+    public static class PartnerAPIv3CommonPrepayRequest {
+        @SerializedName("sp_appid")
+        public String spAppid;
+
+        @SerializedName("sp_mchid")
+        public String spMchid;
+
+        @SerializedName("sub_appid")
+        public String subAppid;
+
+        @SerializedName("sub_mchid")
+        public String subMchid;
+
+        @SerializedName("description")
+        public String description;
+
+        @SerializedName("out_trade_no")
+        public String outTradeNo;
+
+        @SerializedName("time_expire")
+        public String timeExpire;
+
+        @SerializedName("attach")
+        public String attach;
+
+        @SerializedName("notify_url")
+        public String notifyUrl;
+
+        @SerializedName("goods_tag")
+        public String goodsTag;
+
+        @SerializedName("settle_info")
+        public PartnerSettleInfo settleInfo;
+
+        @SerializedName("support_fapiao")
+        public Boolean supportFapiao;
+
+        @SerializedName("amount")
+        public CommonAmountInfo amount;
+
+        @SerializedName("detail")
+        public CouponInfo detail;
+
+        @SerializedName("scene_info")
+        public CommonSceneInfo sceneInfo;
+    }
+
+    public static class CouponInfo {
+        @SerializedName("cost_price")
+        public Long costPrice;
+
+        @SerializedName("invoice_id")
+        public String invoiceId;
+
+        @SerializedName("goods_detail")
+        public List<GoodsDetail> goodsDetail;
+    }
+
+    public static class StoreInfo {
+        @SerializedName("id")
+        public String id;
+
+        @SerializedName("name")
+        public String name;
+
+        @SerializedName("area_code")
+        public String areaCode;
+
+        @SerializedName("address")
+        public String address;
+    }
+}

+ 4 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/pay/serverPay/TelAnonymousController.java

@@ -1,9 +1,13 @@
 package org.jeecg.modules.pay.serverPay;
 
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
+import java.text.SimpleDateFormat;
+
 @RestController
 @RequestMapping("/anonymous")
 @Slf4j

+ 0 - 107
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/pay/serverPay/WechatSignUtil.java

@@ -1,107 +0,0 @@
-package org.jeecg.modules.pay.serverPay;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.security.*;
-import java.security.spec.InvalidKeySpecException;
-import java.security.spec.PKCS8EncodedKeySpec;
-import java.util.Base64;
-import java.util.UUID;
-
-public class WechatSignUtil {
-
-    /**
-     * 参考网站 https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_5_4.shtml
-     * 计算签名值
-     *
-     * @param appId
-     * @param prepay_id
-     * @return
-     * @throws IOException
-     * @throws SignatureException
-     * @throws NoSuchAlgorithmException
-     * @throws InvalidKeyException
-     */
-    public static WxUnifiedOrderVo getTokenJSAPI(String appId, String prepay_id, String privateKey) throws IOException, SignatureException, NoSuchAlgorithmException, InvalidKeyException {
-        // 获取随机字符串
-        String nonceStr = getNonceStr();
-        // 获取微信小程序支付package
-        String packagestr = "prepay_id=" + prepay_id;
-        long timestamp = System.currentTimeMillis() / 1000;
-        //签名,使用字段appId、timeStamp、nonceStr、package计算得出的签名值
-        String message = buildMessageTwo(appId, timestamp, nonceStr, packagestr);
-        //获取对应的签名
-        String signature = sign(message.getBytes("utf-8"),privateKey);
-        // 组装返回
-        WxUnifiedOrderVo vo = new WxUnifiedOrderVo();
-        vo.setAppId(appId);
-        vo.setTimeStamp(String.valueOf(timestamp));
-        vo.setNonceStr(nonceStr);
-        vo.setPackageStr(packagestr);
-        vo.setSignType("RSA");
-        vo.setPaySign(signature);
-        return vo;
-    }
-
-    /**
-     * 生成随机数
-     * @return
-     */
-    public static String getNonceStr(){
-        return UUID.randomUUID().toString()
-                .replaceAll("-", "")
-                .substring(0, 32);
-    }
-    /**
-     * 拼接参数
-     *
-     * @return
-     */
-
-    public static String buildMessageTwo(String appId, long timestamp, String nonceStr, String packag) {
-        return appId + "\n"
-                + timestamp + "\n"
-                + nonceStr + "\n"
-                + packag + "\n";
-    }
-    /**
-     * 生成签名
-     *
-     * @return
-     */
-    public static String sign(byte[] message,String privateKey) throws NoSuchAlgorithmException, SignatureException, IOException, InvalidKeyException {
-        Signature sign = Signature.getInstance("SHA256withRSA"); //SHA256withRSA
-        sign.initSign(getPrivateKey(privateKey));
-        sign.update(message);
-        return Base64.getEncoder().encodeToString(sign.sign());
-    }
-    /**
-     * 获取私钥
-     * @param filename 私钥文件路径  (required)
-     * @return 私钥对象
-     */
-    public static PrivateKey getPrivateKey(String filename) throws IOException {
-        System.out.println("filename:" + filename);
-        filename = filename.replace("classpath:", "");
-        WechatSignUtil wechatSignUtil = new WechatSignUtil();
-        InputStream resourceAsStream = wechatSignUtil.getClass().getClassLoader().getResourceAsStream(filename);
-        byte[] bytes = new byte[0];
-        bytes = new byte[resourceAsStream.available()];
-        resourceAsStream.read(bytes);
-        String content = new String(bytes);
-//        String content = new String(Files.readAllBytes(Paths.get(resource.getPath())), "utf-8");
-        try {
-            String privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "")
-                    .replace("-----END PRIVATE KEY-----", "")
-                    .replaceAll("\\s+", "");
-
-            KeyFactory kf = KeyFactory.getInstance("RSA");
-            return kf.generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));
-        } catch (NoSuchAlgorithmException e) {
-            throw new RuntimeException("当前Java环境不支持RSA", e);
-        } catch (InvalidKeySpecException e) {
-            throw new RuntimeException("无效的密钥格式");
-        }
-    }
-}
-

+ 0 - 40
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/pay/serverPay/WxPayConfiguration.java

@@ -1,40 +0,0 @@
-package org.jeecg.modules.pay.serverPay;
-//
-//
-//import lombok.AllArgsConstructor;
-//import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
-//import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
-//import org.springframework.boot.context.properties.EnableConfigurationProperties;
-//import org.springframework.context.annotation.Bean;
-//import org.springframework.context.annotation.Configuration;
-//
-///**
-// * @author Binary Wang
-// */
-//@Configuration
-//@ConditionalOnClass(WxPayService.class)
-//@EnableConfigurationProperties(WxPayProperties.class)
-//@AllArgsConstructor
-//public class WxPayConfiguration {
-//  private WxPayProperties properties;
-//
-//  @Bean("wxPayService")
-//  @ConditionalOnMissingBean
-//  public WxPayService wxService() {
-//    WxPayConfig payConfig = new WxPayConfig();
-//    payConfig.setAppId(StringUtils.trimToNull(this.properties.getAppId()));
-//    payConfig.setMchId(StringUtils.trimToNull(this.properties.getMchId()));
-//    payConfig.setApiV3Key(StringUtils.trimToNull(this.properties.getApiV3Key()));
-//    payConfig.setCertSerialNo(StringUtils.trimToNull(this.properties.getCertSerialNo()));
-//    payConfig.setPrivateKeyPath(StringUtils.trimToNull(this.properties.getPrivateKeyPath()));
-//    payConfig.setPrivateCertPath(StringUtils.trimToNull(this.properties.getPrivateCertPath()));
-//    payConfig.setNotifyUrl(StringUtils.trimToNull(this.properties.getNotifyUrl()));
-//    payConfig.setTradeType("JSAPI");
-//    payConfig.setSignType("MD5");
-//    WxPayService wxPayService = new WxPayServiceImpl();
-//    wxPayService.setConfig(payConfig);
-//    return wxPayService;
-//  }
-//
-//}
-

+ 19 - 17
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/pay/serverPay/WxV3PayConfig.java

@@ -1,33 +1,36 @@
 package org.jeecg.modules.pay.serverPay;
  
+import lombok.extern.slf4j.Slf4j;
+import org.jeecg.common.exception.JeecgBootException;
 import org.springframework.stereotype.Component;
  
 import javax.annotation.PostConstruct;
- 
+
+@Slf4j
 @Component
 public class WxV3PayConfig {
     // 服务商AppId
-    private String appIdValue = "wxXXXXXXXXXXX";
-    public static String APP_ID= "wxXXXXXXXXXX";
+    private String appIdValue = "wx43b5b906cc30ed0b";
+    public static String APP_ID= "wx43b5b906cc30ed0b";
  
     // 服务商商户号
-    private String mchIdValue= "168XXXXXXX";
-    public static String Mch_ID= "168XXXXXX";
+    private String mchIdValue= "1649629687";
+    public static String Mch_ID= "1649629687";
  
     // 平台收款商户号
-    public static String smidVx= "208XXXXXXXXXXXX";
-    private  String smidVxValue= "2088XXXXXXXXXXX";
+    public static String smidVx= "";
+    private  String smidVxValue= "";
  
     // 服务商商户私钥
-    private String apiV3KeyValue= "1skiujhXXXXXXXXXXXXXXXXXXX";
-    public static String apiV3Key= "1skiujhXXXXXXXXXXXXXXXXXX";
+    private String apiV3KeyValue= "4b64e17419689527b256f07cdf6bd60c";
+    public static String apiV3Key= "4b64e17419689527b256f07cdf6bd60c";
+
     // 证书序列号
+    private String mchSerialNoValue= "5EB65CC0F912EA2ADD3363EA3DA0230DF6DA90BC";
+    public static String mchSerialNo= "5EB65CC0F912EA2ADD3363EA3DA0230DF6DA90BC";
  
-    private String mchSerialNoValue= "5571XXXXXXXXXXXXXXXXXX";
-    public static String mchSerialNo= "5571XXXXXXXXXXXXXXXXXXXXX";
- 
-    private String privateKeyPathValue= "/XXXXXXXXXXXXXX/apiclient_key.pem";
-    public static String privateKeyPath= "/XXXXXXXXXXXXX/apiclient_key.pem";
+    private String privateKeyPathValue= "/cert/apiclient_key.pem";
+    public static String privateKeyPath= "/cert/apiclient_key.pem";
  
     // 如果需要静态访问,可以使用 @PostConstruct 初始化静态变量
     @PostConstruct
@@ -42,10 +45,9 @@ public class WxV3PayConfig {
  
         // 可以在这里加一些非空检查
         if (APP_ID == null || Mch_ID == null || apiV3Key == null || mchSerialNo == null || privateKeyPath == null) {
-             System.err.println("微信支付V3配置加载不完整,请检查配置文件!");
-             // 在实际应用中,这里可能需要抛出异常或采取其他错误处理措施
+             throw new JeecgBootException("微信支付V3配置加载不完整,请检查配置文件!");
         } else {
-             System.out.println("微信支付V3配置加载完成。");
+             log.info("微信支付V3配置加载完成。");
         }
     }
  

+ 3 - 1
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/service/impl/AppCoureseServiceImpl.java

@@ -403,7 +403,9 @@ public class AppCoureseServiceImpl extends ServiceImpl<AppCoursesMapper, AppCour
     public List<FamilyUserVO> getClassPostponeUsers(String coursePriceRulesId) {
 
         List<AppCoursesVerificationRecord> verificationRecordList = appCoursesVerificationRecordMapper.selectList(Wrappers.<AppCoursesVerificationRecord>lambdaQuery()
-                .eq(AppCoursesVerificationRecord::getCoursesPriceRuleId, coursePriceRulesId).eq(AppCoursesVerificationRecord::getOrPostpone, 0));
+                .eq(AppCoursesVerificationRecord::getCoursesPriceRuleId, coursePriceRulesId)
+                        .eq(AppCoursesVerificationRecord::getVerifyStatus, CommonConstant.STATUS_0_INT)
+                .eq(AppCoursesVerificationRecord::getOrPostpone, CommonConstant.STATUS_0_INT));
         List<FamilyUserVO> list = verificationRecordList.stream()
                 .collect(Collectors.collectingAndThen(
                         Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(AppCoursesVerificationRecord::getUseUserId))),

+ 1 - 1
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/service/impl/AppOrderServiceImpl.java

@@ -321,7 +321,7 @@ public class AppOrderServiceImpl extends ServiceImpl<AppOrderMapper, AppOrder> i
             if (ObjectUtil.isNotEmpty(appOrder)){
                 List<AppOrderProInfo> proInfoList = appOrderProInfoMapper.selectList(Wrappers.<AppOrderProInfo>lambdaQuery().eq(AppOrderProInfo::getOrderId, orderId).eq(AppOrderProInfo::getType, CommonConstant.ORDER_PRO_INFO_TYPE_5));
                 long count = proInfoList.stream().filter(info -> Objects.equals(info.getOrderStatus(), CommonConstant.ORDER_STATUS_2)).count();
-                if(count == proInfoList.size()){
+                if(count >= 1 && !Objects.equals(appOrder.getOrderStatus(), CommonConstant.ORDER_STATUS_2)){
                     appOrder.setOrderStatus(CommonConstant.ORDER_STATUS_2);
                     appOrderMapper.updateById(appOrder);
                 }

+ 6 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/service/impl/AppSiteServiceImpl.java

@@ -70,6 +70,12 @@ public class AppSiteServiceImpl extends ServiceImpl<AppSiteMapper, AppSite> impl
     @Override
     @Transactional(rollbackFor = Exception.class)
     public Boolean editSite(AppSiteDTO siteCuDTO) {
+        String id = siteCuDTO.getId();
+        AppSite oldSite = baseMapper.selectById(id);
+        //比较运动类目,做新增删除修改
+        if (!oldSite.getCategoryId().equals(siteCuDTO.getCategoryId())){
+
+        }
         AppSite site = new AppSite();
         BeanUtils.copyProperties(siteCuDTO, site);
         LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();

BIN
national-motion-module-system/national-motion-system-biz/src/main/resources/cert/apiclient_cert.p12


+ 21 - 21
national-motion-module-system/national-motion-system-biz/src/main/resources/cert/apiclient_cert.pem

@@ -1,25 +1,25 @@
 -----BEGIN CERTIFICATE-----
-MIIEKzCCAxOgAwIBAgIUQ1h+Z6zzKt6Fsxj5PFb9wbI4jt4wDQYJKoZIhvcNAQEL
+MIIENDCCAxygAwIBAgIUZelVnYGtoL2gzTz0hKWajftWEL4wDQYJKoZIhvcNAQEL
 BQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT
 FFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg
-Q0EwHhcNMjUwOTAzMDI1NDQ2WhcNMzAwOTAyMDI1NDQ2WjCBhDETMBEGA1UEAwwK
-MTcyNjM5NDQ4MTEbMBkGA1UECgwS5b6u5L+h5ZWG5oi357O757ufMTAwLgYDVQQL
-DCfotLXpmLPop4LlsbHmuZbpkavpmLPkuqfkuJrmnInpmZDlhazlj7gxCzAJBgNV
-BAYTAkNOMREwDwYDVQQHDAhTaGVuWmhlbjCCASIwDQYJKoZIhvcNAQEBBQADggEP
-ADCCAQoCggEBAOjNTpElk3jdTWYhhI2DbS6TDh0aGZmCzyrTzZUuXSljjchGWd1A
-wtzIOHtmwDAe3VHRhqoz1G9G4Ee1BzAoeDGI3NfEAPH9egYwBQnPxOIBy//FsYrw
-LvgKOrlhQkiUTR/ZQfa9Ay+KGLV8/BKzFckYuC7f9RqNd7/Nz5iuaFaekAdTjqZU
-n8EsTDMFWZ9yAZcA8n+yHnvNxKhrJYtguPudRnwojbYMRgcON5kPSLzBx8JWnB+y
-epI7dt3YeBdKsMDlSI5tc8/KkzflCSd/TqxcJhrQbZSLhiUawLYNMG7R3unxv+E5
-7u/JXNfDva4kNDgYZ3zAOJfGcaS+cQpORrcCAwEAAaOBuTCBtjAJBgNVHRMEAjAA
-MAsGA1UdDwQEAwID+DCBmwYDVR0fBIGTMIGQMIGNoIGKoIGHhoGEaHR0cDovL2V2
-Y2EuaXRydXMuY29tLmNuL3B1YmxpYy9pdHJ1c2NybD9DQT0xQkQ0MjIwRTUwREJD
-MDRCMDZBRDM5NzU0OTg0NkMwMUMzRThFQkQyJnNnPUhBQ0M0NzFCNjU0MjJFMTJC
-MjdBOUQzM0E4N0FEMUNERjU5MjZFMTQwMzcxMA0GCSqGSIb3DQEBCwUAA4IBAQAj
-wIp02IkmFpfX1Icbwr9VE+eGKjwVNhp05BczqquZDWiVjmWytG1n1PjveueGd9zD
-Fa/VMhR+bqZdpzFcWsfkwYMm9hUX86cx/tHbgj+p2hYV+gWAdgkUg+6iW5LvNSBS
-u952qPud5Dmelx48sMWfgGEytGlDvAKnufvXWOSmk8pFCOXzpYuJPd5Z61pIQ0no
-esoVMnGSvUYCm8VPPjANXQfm4FPbmQS5iOyts8iP8eDuWIOOx0cBm71jFQm9gAvy
-1rFvjfqe/n0TAxXz7I4CIvTwUeduc65p+/p4me7jurtZPWJ2S5L8Pp+MAt7GE63e
-zl0Fzkd6MZUvH9zybyve
+Q0EwHhcNMjUwOTA1MDE0MTEwWhcNMzAwOTA0MDE0MTEwWjCBjTETMBEGA1UEAwwK
+MTcyNTg0NTY4MTEbMBkGA1UECgwS5b6u5L+h5ZWG5oi357O757ufMTkwNwYDVQQL
+DDDkuK3mlbDmnKrmnaXvvIjmtbfljZfvvInns7vnu5/pm4bmiJDmnInpmZDlhazl
+j7gxCzAJBgNVBAYTAkNOMREwDwYDVQQHDAhTaGVuWmhlbjCCASIwDQYJKoZIhvcN
+AQEBBQADggEPADCCAQoCggEBALtopcBas3Lhb00y/YCH3OnVVANmTrydZfcR8AKA
+d0JeGoXaaHNSpAkcaO6aqRIEp1PANPOBcJyzsQo9Ih5ZdJqN9vKfx/lxi6lFgRIW
++simIdpGHdpRM1WZ9GJcs3rMxKIBSSA+neZlfNmWnfzA9lLVWX5LyV6wRMSqcT+o
+UroDYwoKM4Vu0I1Aiw9zirvQnOADA3HbSCIc0yaHpM3jVqzVC7o9Wlqa80uAunhT
+YYEidRGkctSpUl9A57MI4dQSQPG1x1jfQ1vhogUXNIvMayxzN26i+GbxvntbLR0P
+lysYplUayLHeb0Jd34GyEkNggH8QCK9T6ekrhPOKcDsrTB0CAwEAAaOBuTCBtjAJ
+BgNVHRMEAjAAMAsGA1UdDwQEAwID+DCBmwYDVR0fBIGTMIGQMIGNoIGKoIGHhoGE
+aHR0cDovL2V2Y2EuaXRydXMuY29tLmNuL3B1YmxpYy9pdHJ1c2NybD9DQT0xQkQ0
+MjIwRTUwREJDMDRCMDZBRDM5NzU0OTg0NkMwMUMzRThFQkQyJnNnPUhBQ0M0NzFC
+NjU0MjJFMTJCMjdBOUQzM0E4N0FEMUNERjU5MjZFMTQwMzcxMA0GCSqGSIb3DQEB
+CwUAA4IBAQAM4AlxykqJA/0HK3T4dU5CB02BIGEygu0HH1X2tPrl0kLIVu9J7jfq
+i9PddQ8sjiUP6UjcegkEfvM3kIg66zREJzjFaWFJBdxBYW8ooab3yOO1o80c9cRm
+NoSLNwiumc72xEeARAsjwNiMcYsK3kLRvMOp1zqH99JNWCvDq4oZNVYvnHJH6nPi
+dda8XLswTvUvEJQq0JDDTxgOzIK1BGzLXbaN0fsdsHLrfQ+QnqkIZYyWzLe6WkMR
+V+n0aiZmt5SCu/XMG7hjQpX0Ob8oUmMENcy6bIv/fMwpV+6VD29Gy1l/ykyroxy4
+cNLOIZ6DorRnq/gVKGPhOpfUMHGJTwF8
 -----END CERTIFICATE-----

+ 26 - 26
national-motion-module-system/national-motion-system-biz/src/main/resources/cert/apiclient_key.pem

@@ -1,28 +1,28 @@
 -----BEGIN PRIVATE KEY-----
-MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDozU6RJZN43U1m
-IYSNg20ukw4dGhmZgs8q082VLl0pY43IRlndQMLcyDh7ZsAwHt1R0YaqM9RvRuBH
-tQcwKHgxiNzXxADx/XoGMAUJz8TiAcv/xbGK8C74Cjq5YUJIlE0f2UH2vQMvihi1
-fPwSsxXJGLgu3/UajXe/zc+YrmhWnpAHU46mVJ/BLEwzBVmfcgGXAPJ/sh57zcSo
-ayWLYLj7nUZ8KI22DEYHDjeZD0i8wcfCVpwfsnqSO3bd2HgXSrDA5UiObXPPypM3
-5Qknf06sXCYa0G2Ui4YlGsC2DTBu0d7p8b/hOe7vyVzXw72uJDQ4GGd8wDiXxnGk
-vnEKTka3AgMBAAECggEBAIeWm/3Znsy0R9IGD4fEViDcMUot218XWsWc2o3alRP4
-Eanln41HnLauPodQzvq33zs6B262BTJSW2ooO2mHCIoBJm7cj5hhg2J7MVQHmKnx
-VflAESnUveZlPtKdnNdc2JaGGO82ItbbXYzGoKHbgALBzPQwKDcw0d/6ZMCOQ+K+
-FrwLi+93HXlW6jGrPAgJ09kcim6efZOHvxFdZq8zMBFoZeiGnGj6G0peHI5PGb8V
-YKjBXiuxHs96w079R3eID1ViiNnGonm6M9AWT2mxMYMt/VPTr0TZUUet6DmKRs+0
-T3XuqoIunpju5RwWDN9CRdIysc5Ylo9U5rnLjBv6ygECgYEA+ipaz9mvqGo9+EQ2
-30VVGpY1W8r4oOZu8pSnmm9FXZFLVznnq0CB22F7fp1WLr3Yr0XoL2NOHZFVtzT8
-5ww9//o/OUgY3uVC9UoosUtSPowAZeldRc2JaFABusQw34/E96BVeuqTZgFxyvo2
-sAmtBfDXHCOjEmwZlaumKNxw3YECgYEA7jtIBTAE70nPTh7s3Kb81L2k0BT2JVki
-VZdBRPqj/mMxu6MEJ5UjzNhZEH3FXHxxC4Oe8v/r1opxs6ES5RnqQ+agtL5mUBn/
-B0327/96DKZWaKFCaoieCUamY/3jqguoIdK80kjGX6xuQISw5tCCJVrnEuxW+CmI
-XDrcOsTGsDcCgYBck+IJe1i7LZ4DS1M3KxREg4P5lVKPUNeMJCEmULlN2CAWhpJK
-WNP1mMy33YfwQkd3DZrQNqLI5GjhJNXWtzwWh8hv7VNu4U73MVt/yQ0Foo/fJw5i
-b57DIKCTOlmP0kelEAuyMi8cF7rBz/j/CoWiZi9k9Xc6sRCCyAP0qSeHgQKBgBpl
-2z8n6QQS67O+XYS9xDpWoVKlX/kXfWR6lDLuiwl/OF2QXL9+GS9zsbrQFPSAnY4n
-EY/fp+RoBt1etddJHdpUTe55QqERoF7Q1tIVPxLzw5NoexGO/eQNPhbKZVXMYN8O
-mPm8Mq8bTkQ779ZDuIgnIH/KTIDHKWL+6rRgZZvVAoGALZn4IpUhcRe7v/+pnYSQ
-6AhmUmTM3OdAA+XJDMuZzDM+5DNmuhZx4Y9sw/Xg1+kejR0W48aFNZ4xhSz89XC6
-rusYJfTda1iqqlaH453yJti98u2EkESJMdY2YlT7H75VjD/A1o1Fn3qnGStn9CKt
-DOukDtlOzybCJFsjG5uBwcg=
+MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC7aKXAWrNy4W9N
+Mv2Ah9zp1VQDZk68nWX3EfACgHdCXhqF2mhzUqQJHGjumqkSBKdTwDTzgXCcs7EK
+PSIeWXSajfbyn8f5cYupRYESFvrIpiHaRh3aUTNVmfRiXLN6zMSiAUkgPp3mZXzZ
+lp38wPZS1Vl+S8lesETEqnE/qFK6A2MKCjOFbtCNQIsPc4q70JzgAwNx20giHNMm
+h6TN41as1Qu6PVpamvNLgLp4U2GBInURpHLUqVJfQOezCOHUEkDxtcdY30Nb4aIF
+FzSLzGssczduovhm8b57Wy0dD5crGKZVGsix3m9CXd+BshJDYIB/EAivU+npK4Tz
+inA7K0wdAgMBAAECggEASTeFKjVFTmiMl1iIeaKayDAz9nAN6tqDb5ducUvHTAJ/
+0jOWAxgSRgz3YeDClOuEg8/f4BJ98HqzfBCON9UzHP7Br+CEvAuESMmCt5KKv8FI
+EIK8PwLiT1sqgxM8e4lseO6Ppy1PeyfDMy8I4ipxEcOQhysMrRWoiD0eqYQVbd4g
+YfOEsq8EbSHr+sDHgFJM5hEEHEWNvSUUSjifuo861SkYEtjQcg5AKflPce9Fz7Ze
+UNxHEh+gAOvDzkFTlVSnqhUR3G2EeoFSwALwNMNJW4vBiQ16InhAlsUPh5zByPBS
+HAbfiNYNUgYQM5PUy2YSamMXwUAAvNvcrbNUN6PrgQKBgQD4OtObOKB60zZYuRfa
+6lpfIxT4EeaP7aGFc+vL20ZFTEhueWAHw8opznrRwWa3zok1T+PhJHJ0BeLsU+m1
+Y4BVDHNw7rfKxMaw63LL2AGnx2wmeDDm1bliPvnQrc7KVqQsgu31+xuOKcgL5brg
+YdxfXPyHP7vAfI8RaanGHS3luQKBgQDBRm+FAELD/O0Hsn8Eyz6tehTG0AqyLdCE
+DmKjC1cQnQVDWReFRcLjFQZLd3eajNe9L1liyqnKERnJCgsyxaygmZVnt4xdwRSm
+dV76SFV6+kXs9dDILeRNhybyfAIdrijv60gF8uVfUMhbQGtpuEs9e+1UhP5TcvbS
+Y10Q3xQLhQKBgQDTcrjiVkBNoDGBLlolvs+wjt/D2Ou/2rpmRbKsemLHkQ16HaYx
+txQ0vJBesRJgrGywnxcMp9FfB8yfZ3ODcfjVeb+0iYTCExD1j/q/rYbrdrKnqmZt
+m81I5UBEBGpMbbV3vSgbCwYT+X9QsyaXEIV6LmlmhGHYu8HbIVjfS+fW8QKBgQCn
+083Ko+tV3C7G3ExHkWUfpj6cVNK03euOgB9OjO5RUsfbL2WpKGaOYRdSOK722Q4N
+DSyFCI5fFHJbjAklUVkRK8v8f/m2/4467PhIRL9VRjWqCdn9uTvhxlYfgWck9rI9
+gwTLhZt/JNqVwl6DMrDC9vWiysk9FTsWfYm2uL7jMQKBgQDy2kud6Ct2wvN6AakJ
+PrXwvW0FVrI5ieGS4eG0cUWiK/7S1TjyyuF/dJYabxVtXnYXCLTztFigPCVNWeog
+R9FQITYKducHCS/Gjz53ksEeX9LuUB78gyrqiGvq5iyKKOsYvh9j3YmLpZgeQ1CE
+be6f9A6UjSGKP4qEvgJhIy09bw==
 -----END PRIVATE KEY-----

+ 0 - 9
national-motion-module-system/national-motion-system-biz/src/main/resources/cert/pub_key.pem

@@ -1,9 +0,0 @@
------BEGIN PUBLIC KEY-----
-MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqSqeCl7ab3f/n44mdbuy
-pKwGXxrZM221aOed+5rjTUZzOaUqyKaLychg3u0vIOxQoghetQXnXmC+wApqgnx0
-odyXCoQk92a4zFO0NwYl3vJdVXTjVNDL23GQB9M6AKcSPpds2zMGonUuBWqFvg1O
-H1EQqrf1ak2GF8wewNwqO/bAL5yBOFHy7DWWCJqoThte+5leH6UGWLm/4fCZyjF6
-3umM5bNb4hSzZtq6M2Sy0VPVmZA76liDWcsk6gkVNqt7oXyHv8tD8+8t41tf6vxL
-oZaoNt4qxvXlkikVgOQ9Br87Gbe4r5hpuw+URjoXadGjYVWqJA0gCs6lcu3lRYU6
-6QIDAQAB
------END PUBLIC KEY-----

+ 5 - 5
national-motion-module-system/national-motion-system-start/src/main/resources/application-dev.yml

@@ -345,11 +345,11 @@ wx:
 # 微信支付配置
   pay:
     #服务商微信支付商户号
-    mchId:
+    mchId: 1649629687
     #证书
-    keyPath: apiclient_cert.p12
+    keyPath: classpath:cert/apiclient_cert.p12
     #服务商微信公众号或者小程序等的appid
-    appId:
+    appId: wx43b5b906cc30ed0b
     #支付回调通知地址
     notifyUrl:
     #服务商key的密钥
@@ -357,9 +357,9 @@ wx:
     #特约商户微信公众号或者小程序等的appid
     subAppId:
     #apiV3秘钥
-    apiV3Key:
+    apiV3Key: 4b64e17419689527b256f07cdf6bd60c
     #证书号
-    certSerialNo:
+    certSerialNo: 5EB65CC0F912EA2ADD3363EA3DA0230DF6DA90BC
     #apiclient_key.pem证书文件的绝对路径或者以classpath:开头的类路径
     privateKeyPath: classpath:cert/apiclient_key.pem
     #apiclient_cert.pem证书文件的绝对路径或者以classpath:开头的类路径