From 4e124926ee6ee682084466067ae37550fca475fa Mon Sep 17 00:00:00 2001
From: 无关风月 <443237572@qq.com>
Date: 星期二, 05 八月 2025 11:39:48 +0800
Subject: [PATCH] 代码提交 世界杯修改支付宝资金结算功能

---
 cloud-server-competition/src/main/java/com/dsh/competition/util/wx/Create.java                                      |  292 +++++++++++
 cloud-server-communityWorldCup/src/main/java/com/dsh/communityWorldCup/service/impl/WorldCupServiceImpl.java        |   32 
 cloud-server-other/src/main/java/com/dsh/other/util/PayMoneyUtil.java                                               |   43 +
 cloud-server-communityWorldCup/src/main/java/com/dsh/communityWorldCup/service/impl/WorldCupPaymentServiceImpl.java |   48 +
 cloud-server-other/src/main/java/com/dsh/other/util/wx/Create.java                                                  |  300 ++++++++++++
 cloud-server-activity/src/main/resources/logback-spring.xml                                                         |    2 
 cloud-server-communityWorldCup/src/main/java/com/dsh/communityWorldCup/service/IWorldCupPaymentService.java         |    2 
 cloud-server-other/src/main/java/com/dsh/other/controller/SiteController.java                                       |   53 ++
 cloud-server-communityWorldCup/src/main/resources/sharding-jdbc.properties                                          |   23 
 cloud-server-account/src/main/java/com/dsh/account/util/PayMoneyUtil.java                                           |   26 
 cloud-server-communityWorldCup/src/main/java/com/dsh/communityWorldCup/service/IWorldCupService.java                |    2 
 cloud-server-communityWorldCup/src/main/java/com/dsh/communityWorldCup/controller/WorldCupController.java           |   53 ++
 cloud-server-activity/src/main/resources/sharding-jdbc.properties                                                   |    2 
 cloud-server-communityWorldCup/src/main/java/com/dsh/communityWorldCup/util/wx/Create.java                          |  292 +++++++++++
 cloud-server-other/src/main/java/com/dsh/other/service/impl/SiteServiceImpl.java                                    |   65 +-
 cloud-server-communityWorldCup/src/main/java/com/dsh/communityWorldCup/util/PayMoneyUtil.java                       |   38 +
 cloud-server-competition/src/main/java/com/dsh/competition/service/impl/PaymentCompetitionServiceImpl.java          |   52 -
 cloud-server-competition/src/main/java/com/dsh/competition/util/PayMoneyUtil.java                                   |   38 +
 cloud-server-competition/src/main/java/com/dsh/competition/controller/CompetitionController.java                    |  115 +++-
 19 files changed, 1,310 insertions(+), 168 deletions(-)

diff --git a/cloud-server-account/src/main/java/com/dsh/account/util/PayMoneyUtil.java b/cloud-server-account/src/main/java/com/dsh/account/util/PayMoneyUtil.java
index 9397dea..2fb7d51 100644
--- a/cloud-server-account/src/main/java/com/dsh/account/util/PayMoneyUtil.java
+++ b/cloud-server-account/src/main/java/com/dsh/account/util/PayMoneyUtil.java
@@ -377,19 +377,19 @@
         }
         return ResultUtil.success(response.getBody());
     }
-    public static void main(String[] args) throws AlipayApiException {
-        confirm9("2088670241691219", "20250706132544057730", "2025070622001467281419691745", "0.1");
-        confirm9("2088670241691219", "20250706132448647822", "2025070622001467281421616221", "0.1");
-        confirm9("2088670241691219", "20250706132703365228", "2025070622001467281418986854", "0.1");
-        confirm9("2088670241691219", "20250706132812692528", "2025070622001467281421628990", "0.1");
-        confirm9("2088670241691219", "20250706133122769531", "2025070622001467281421682297", "0.1");
-        confirm9("2088670241691219", "20250706155632714326", "2025070622001423881412880254", "0.01");
-        confirm9("2088670241691219", "20250707124157706846", "2025070722001479841407246616", "0.01");
-        confirm9("2088670241691219", "20250709182513843937", "2025070922001467281434141170", "0.01");
-        confirm9("2088670241691219", "20250709183148107861", "2025070922001467281433375653", "0.01");
-        confirm9("2088670241691219", "20250715203444033496", "2025071522001457851416341513", "5");
-
-    }
+//    public static void main(String[] args) throws AlipayApiException {
+//        confirm9("2088670241691219", "20250706132544057730", "2025070622001467281419691745", "0.1");
+//        confirm9("2088670241691219", "20250706132448647822", "2025070622001467281421616221", "0.1");
+//        confirm9("2088670241691219", "20250706132703365228", "2025070622001467281418986854", "0.1");
+//        confirm9("2088670241691219", "20250706132812692528", "2025070622001467281421628990", "0.1");
+//        confirm9("2088670241691219", "20250706133122769531", "2025070622001467281421682297", "0.1");
+//        confirm9("2088670241691219", "20250706155632714326", "2025070622001423881412880254", "0.01");
+//        confirm9("2088670241691219", "20250707124157706846", "2025070722001479841407246616", "0.01");
+//        confirm9("2088670241691219", "20250709182513843937", "2025070922001467281434141170", "0.01");
+//        confirm9("2088670241691219", "20250709183148107861", "2025070922001467281433375653", "0.01");
+//        confirm9("2088670241691219", "20250715203444033496", "2025071522001457851416341513", "5");
+//
+//    }
     private static AlipayConfig getAlipayConfig() {
         String privateKey  = "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCi5i9nW/hGLJ3A06cZxTQdviFC7THpdSihoTYGLr9q006hu0V26ecBMY/o4w5bvIX0Ok/yofmZsVcCJpAPvbXL/uqVrIjnRRxXiaeBFThlxoBUTdunvbUSDYfzlEhJr5NvUKI6H6lz2niXlQGx4qy8Hau4ccWit9kM8jwUvsBVQoFgJA+xrjMvooA7YLopQtpOD+UJr5thApTSf1xrnr1W12yolTLEH15JmNV372cqXrYUuqnY0QsaPtxeqJUGAOcGdVLllQ7easEznP8DFBvDdHATcmp2SHNQDUEWN6MCVPbMgY06NQVqAXxqjTAYSVh+6TRu6bofPmpYC3TZB003AgMBAAECggEBAJAcR2+PA3NBYUYHeFrqBRMS8uX8ZR19kjZ7IgoSLTFaQsP9opRylPSPXhrPVBKAE5leRQAHn4MCSlESwHvMfxo7KFjFTFAc6dffZZpipYQUOc9bGampwJh58/3e/pyBgVMG6J23CPf/HJQtNFSkjd/V9+ayb/9l2dUEL3bC0fAZ/dbx8HsxdLw8wn3fLlWLj68hOMqa2deCZe3JdSVsPbeWqkh56FFsMLug0Nd+Ar4TgRl9/jnhXF0JWiD0LmPUYLhboY7EfUBzN4w1iYbDi1P+3zvoOYsiVKAXox9GMhQ2VzOO2UcSTuizSza2e98mGpabl/GpKmCz+RDFjtkX6eECgYEA2MyCij65eO3aGIm3FUe93DULRBYTfX8qJQSJq2WOWA3mmQlEW6L3O2B5/lG2h+8WmN6iLEs9eHpgycGYp7vAqgrANEn16ACVcuyx0scFtrZfZ+kmHMzFfiUWxJjVYk/6YngsGVBLdw6ueM42C8TTP67X9tU5TdVGoGWuqEj4W98CgYEAwFqwprXOch5Pqk/RPbb49r0Ou03K/UbciWnWWKzUhFFNS8MdlQPoDvQZbMwHLeWsa2VhaKITK3x5biLQb3U+0GLOn6lTvEyrEUH+ucREyLgVYTRAvwBPtnvlrzpyxPk2HnslQjju8WrvvLLBMKWUjlTrTOzhaHT21gz3pHMiOakCgYEAhLmfaXdBITGshb054sNLDtdCkGpbgEcrzAHdLps769iGxkYQHXHFngpQZUwtTUcoNGqIKknd1jZFrv7gsD+XkgKG7PwimehRlkwmCX5ilxtLiVgJRzRt6+5U5AMVD90a0tHzXYP0z2yjj73fBJF5KtGl0a10KZxaYrQdm1UhB00CgYBZZgzx/k9rtHC8LAqIj1CYhHejT92G53c6Gkl3vyOqN4sgKhfGmSEySfrDGPRBPZxr8ZtbIPCd5mUdberH0osWGMYFaJI1UsCy7aQwvGpniz7MhZeN7dweaOjwDs8mgtjHQ96mL4XGCDhR0BZ/wIURvZ/6iaGdhbbu9unlsWj3uQKBgQCmZYdsbbZkd3ev6f8rwyvMz+DrCQyYpY44cegBYuJgrZiQnL2fJioeN7ixX0UM48SfwsZEIrzshP/LGAwnc2MdjxKUl4jLN8SEe0NAjXOnz9Zaw740+aOmLpXcLWdP4uM2gIhWsvW1tEkQZCXmm7c9s/RsU8Pmzv+YL3+fSijOzA==";
         String alipayPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmu8n/4yTHWbn7VOrNc9OsLtDL1bEQ8gC1dHkj8Wy5z0mkaOsjJRIG/28ze12M0V8jdCKuuDr5Z1OPKiqf+XO3ypguEh+mYUVMBM/cZodDFQfTY1TKLWjvQCuaqlA+QUTCK6f7T7stsgyQ1o9Jj0rXZDz6PM4QHSTzjrLIBaeqM5WIBvH+fy/X+QG5Utd+/UT0kc0JyvuKhZ65yVUd/C9VcwJJAPliRsAQNrqYterwAJ9zvw9tF11wj9W0XgJ8Ccu4x3gR1vrlLRJJo/OA97RmxPQ+5hSacWQZCUd1dwiBq+YCrKVHGTj14izRHXrLc0yBlRXo7tBOIqcy3IsvKVthQIDAQAB";
diff --git a/cloud-server-activity/src/main/resources/logback-spring.xml b/cloud-server-activity/src/main/resources/logback-spring.xml
index 37d854d..4a781fa 100644
--- a/cloud-server-activity/src/main/resources/logback-spring.xml
+++ b/cloud-server-activity/src/main/resources/logback-spring.xml
@@ -24,7 +24,7 @@
     <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
         <!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
         <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
-            <level>debug</level>
+            <level>info</level>
         </filter>
         <encoder>
             <Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
diff --git a/cloud-server-activity/src/main/resources/sharding-jdbc.properties b/cloud-server-activity/src/main/resources/sharding-jdbc.properties
index 7f8645e..13de04c 100644
--- a/cloud-server-activity/src/main/resources/sharding-jdbc.properties
+++ b/cloud-server-activity/src/main/resources/sharding-jdbc.properties
@@ -14,7 +14,7 @@
 datasource.names=master0
 datasource.master0.type=com.alibaba.druid.pool.DruidDataSource
 datasource.master0.driverClassName=com.mysql.cj.jdbc.Driver
-datasource.master0.url=jdbc:mysql://127.0.0.1:3306/playpai_activity?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai
+datasource.master0.url=jdbc:mysql://127.0.0.1/playpai_activity?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai
 datasource.master0.username=root
 datasource.master0.password=playpai2023!
 datasource.master0.maxActive=20
diff --git a/cloud-server-communityWorldCup/src/main/java/com/dsh/communityWorldCup/controller/WorldCupController.java b/cloud-server-communityWorldCup/src/main/java/com/dsh/communityWorldCup/controller/WorldCupController.java
index 0ade7ca..cae4036 100644
--- a/cloud-server-communityWorldCup/src/main/java/com/dsh/communityWorldCup/controller/WorldCupController.java
+++ b/cloud-server-communityWorldCup/src/main/java/com/dsh/communityWorldCup/controller/WorldCupController.java
@@ -106,7 +106,6 @@
 
     /**
      * 查询社区世界杯收入--管理后台
-     * @param storeId
      * @return
      */
     @ResponseBody
@@ -654,7 +653,7 @@
             @ApiImplicitParam(name = "id", value = "列表中的id", required = true, dataType = "Long"),
             @ApiImplicitParam(name = "Authorization", value = "用户token(Bearer +token)", required = true, dataType = "String", paramType = "header", defaultValue = "Bearer eyJhbGciOiJIUzUxMiJ9.....")
     })
-    public ResultUtil cancelMyWorldCup(Long id){
+    public ResultUtil cancelMyWorldCup(Long id) throws Exception {
         return worldCupPaymentService.cancelMyWorldCup(id);
     }
 
@@ -942,7 +941,7 @@
      */
     @ResponseBody
     @PostMapping("/worldCup/cancelWorldCupRefund")
-    public void cancelWorldCupRefund(@RequestBody Integer id){
+    public void cancelWorldCupRefund(@RequestBody Integer id) throws Exception {
         worldCupService.cancelWorldCupRefund(id);
     }
 
@@ -988,6 +987,54 @@
             out.close();
         }
     }
+    /**
+     * 取消赛事后微信退款回调微信V3回调
+     * @param request
+     * @param response
+     */
+    @ResponseBody
+    @PostMapping("/base/worldCup/wxRefundWorldCupCallback1")
+    public void wxRefundWorldCupCallback1(HttpServletRequest request, HttpServletResponse response){
+        try {
+            System.err.println("微信回调");
+            System.err.println("请求" + request);
+            BufferedReader reader = request.getReader();
+            String string1 = reader.toString();
+            System.err.println("请求reader" + string1);
+            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 code = jsonInfo.getString("out_trade_no");
+            String transaction_id = jsonInfo.getString("transaction_id");
+            String refund_status = jsonInfo.getString("refund_status");
+            String out_refund_no = jsonInfo.getString("out_refund_no");
+            if (refund_status.equals("SUCCESS")) {
+                WorldCupPayment worldCupPayment = worldCupPaymentService.getOne(new QueryWrapper<WorldCupPayment>().eq("code", out_refund_no));
+                worldCupPayment.setRefundOrderNo(code);
+                worldCupPayment.setRefundTime(new Date());
+                worldCupPayment.setPayStatus(3);
+                worldCupPayment.setWorldCupId(null);
+                worldCupPaymentService.updateById(worldCupPayment);
+                PrintWriter out = response.getWriter();
+                out.write("SUCCESS");
+                out.flush();
+                out.close();
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
 
 
     /**
diff --git a/cloud-server-communityWorldCup/src/main/java/com/dsh/communityWorldCup/service/IWorldCupPaymentService.java b/cloud-server-communityWorldCup/src/main/java/com/dsh/communityWorldCup/service/IWorldCupPaymentService.java
index 2bd7b9a..36ab6f5 100644
--- a/cloud-server-communityWorldCup/src/main/java/com/dsh/communityWorldCup/service/IWorldCupPaymentService.java
+++ b/cloud-server-communityWorldCup/src/main/java/com/dsh/communityWorldCup/service/IWorldCupPaymentService.java
@@ -16,5 +16,5 @@
      * @param id
      * @return
      */
-    ResultUtil cancelMyWorldCup(Long id);
+    ResultUtil cancelMyWorldCup(Long id) throws Exception;
 }
diff --git a/cloud-server-communityWorldCup/src/main/java/com/dsh/communityWorldCup/service/IWorldCupService.java b/cloud-server-communityWorldCup/src/main/java/com/dsh/communityWorldCup/service/IWorldCupService.java
index 83f799a..4bcb1e9 100644
--- a/cloud-server-communityWorldCup/src/main/java/com/dsh/communityWorldCup/service/IWorldCupService.java
+++ b/cloud-server-communityWorldCup/src/main/java/com/dsh/communityWorldCup/service/IWorldCupService.java
@@ -85,7 +85,7 @@
      * 取消赛事后退还费用
      * @param id
      */
-    void cancelWorldCupRefund(Integer id);
+    void cancelWorldCupRefund(Integer id) throws Exception;
 
 
     /**
diff --git a/cloud-server-communityWorldCup/src/main/java/com/dsh/communityWorldCup/service/impl/WorldCupPaymentServiceImpl.java b/cloud-server-communityWorldCup/src/main/java/com/dsh/communityWorldCup/service/impl/WorldCupPaymentServiceImpl.java
index 183f065..4f3d5d3 100644
--- a/cloud-server-communityWorldCup/src/main/java/com/dsh/communityWorldCup/service/impl/WorldCupPaymentServiceImpl.java
+++ b/cloud-server-communityWorldCup/src/main/java/com/dsh/communityWorldCup/service/impl/WorldCupPaymentServiceImpl.java
@@ -7,23 +7,30 @@
 import com.dsh.communityWorldCup.entity.WorldCup;
 import com.dsh.communityWorldCup.entity.WorldCupPayment;
 import com.dsh.communityWorldCup.entity.WorldCupPaymentParticipant;
+import com.dsh.communityWorldCup.entity.WorldCupStore;
 import com.dsh.communityWorldCup.feignclient.account.AppUserClient;
 import com.dsh.communityWorldCup.feignclient.account.model.AppUser;
 import com.dsh.communityWorldCup.feignclient.course.CoursePackageOrderStudentClient;
 import com.dsh.communityWorldCup.feignclient.course.model.CoursePackageOrderStudent;
+import com.dsh.communityWorldCup.feignclient.other.StoreClient;
+import com.dsh.communityWorldCup.feignclient.other.model.Store;
 import com.dsh.communityWorldCup.mapper.WorldCupPaymentMapper;
 import com.dsh.communityWorldCup.model.DeductionClassHourList;
 import com.dsh.communityWorldCup.service.IWorldCupPaymentParticipantService;
 import com.dsh.communityWorldCup.service.IWorldCupPaymentService;
 import com.dsh.communityWorldCup.service.IWorldCupService;
+import com.dsh.communityWorldCup.service.IWorldCupStoreService;
 import com.dsh.communityWorldCup.util.PayMoneyUtil;
 import com.dsh.communityWorldCup.util.ResultUtil;
+import com.dsh.communityWorldCup.util.UUIDUtil;
 import net.bytebuddy.asm.Advice;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
 
 import javax.annotation.Resource;
 import java.math.BigDecimal;
+import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
@@ -37,6 +44,8 @@
 
     @Autowired
     private IWorldCupPaymentParticipantService worldCupPaymentParticipantService;
+    @Autowired
+    private IWorldCupStoreService worldCupStoreService;
 
     @Autowired
     private IWorldCupService worldCupService;
@@ -46,6 +55,8 @@
 
     @Resource
     private AppUserClient appUserClient;
+    @Resource
+    private StoreClient storeClient;
 
     @Resource
     private CoursePackageOrderStudentClient coursePackageOrderStudentClient;
@@ -59,7 +70,7 @@
      * @return
      */
     @Override
-    public ResultUtil cancelMyWorldCup(Long id) {
+    public ResultUtil cancelMyWorldCup(Long id) throws Exception {
         WorldCupPaymentParticipant worldCupPaymentParticipant = worldCupPaymentParticipantService.getById(id);
         WorldCupPayment worldCupPayment = this.getById(worldCupPaymentParticipant.getWorldCupPaymentId());
         WorldCup worldCup = worldCupService.getById(worldCupPayment.getWorldCupId());
@@ -82,17 +93,32 @@
         //总排款金额(排除已经参加比赛的数据)
         BigDecimal multiply = worldCupPayment.getUnitPrice().multiply(new BigDecimal(list1.size()));
         //微信支付
+
+        List<WorldCupStore> list = worldCupStoreService.lambdaQuery().eq(WorldCupStore::getWorldCupId, worldCup.getId()).list();
+        Integer storeId = list.get(0).getStoreId();
+        Store store = storeClient.queryStoreById(storeId);
         if(worldCupPayment.getPayType() == 1){
-            Map<String, String> map = payMoneyUtil.wxRefund(worldCupPayment.getPayOrderNo(), worldCupPayment.getCode(),
-                    worldCupPayment.getAmount().toString(), multiply.toString(), "/base/worldCup/wxRefundWorldCupCallback");
-            if(!"SUCCESS".equals(map.get("return_code"))){
-                System.err.println("-------------微信退款失败---------");
-                System.err.println(map.get("return_msg"));
-                return ResultUtil.error("微信退款失败");
-            }else{
-                worldCupPayment.setRefundAmount(multiply);
-                worldCupPayment.setWorldCupId(null);
-                this.updateById(worldCupPayment);
+            if (store.getOperatorId()!=null && store.getOperatorId()!=0){
+                String smidVx= storeClient.getmerchantNumberByOperatorId(store.getOperatorId());
+                if (!StringUtils.hasLength(smidVx)){
+                    System.err.println("运营商未配置微信商户号,获取支付失败!");
+                }
+                SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
+                String codeRefund = sdf.format(new Date()) + UUIDUtil.getNumberRandom(5);// 退款单号
+                // 运营商退款
+                payMoneyUtil.weixinRefundV3(smidVx, codeRefund, worldCupPayment.getPayOrderNo(), worldCupPayment.getAmount().toString(), "/base/worldCup/wxRefundWorldCupCallback1");
+            }else {
+                Map<String, String> map = payMoneyUtil.wxRefund(worldCupPayment.getPayOrderNo(), worldCupPayment.getCode(),
+                        worldCupPayment.getAmount().toString(), multiply.toString(), "/base/worldCup/wxRefundWorldCupCallback");
+                if (!"SUCCESS".equals(map.get("return_code"))) {
+                    System.err.println("-------------微信退款失败---------");
+                    System.err.println(map.get("return_msg"));
+                    return ResultUtil.error("微信退款失败");
+                } else {
+                    worldCupPayment.setRefundAmount(multiply);
+                    worldCupPayment.setWorldCupId(null);
+                    this.updateById(worldCupPayment);
+                }
             }
         }
         //支付宝支付
diff --git a/cloud-server-communityWorldCup/src/main/java/com/dsh/communityWorldCup/service/impl/WorldCupServiceImpl.java b/cloud-server-communityWorldCup/src/main/java/com/dsh/communityWorldCup/service/impl/WorldCupServiceImpl.java
index dc89dab..635b821 100644
--- a/cloud-server-communityWorldCup/src/main/java/com/dsh/communityWorldCup/service/impl/WorldCupServiceImpl.java
+++ b/cloud-server-communityWorldCup/src/main/java/com/dsh/communityWorldCup/service/impl/WorldCupServiceImpl.java
@@ -849,10 +849,13 @@
      * @param id
      */
     @Override
-    public void cancelWorldCupRefund(Integer id) {
+    public void cancelWorldCupRefund(Integer id) throws Exception {
         //免费除外
         List<WorldCupPayment> list2 = worldCupPaymentService.list(new QueryWrapper<WorldCupPayment>().eq("worldCupId", id)
                 .ne("payType", 0).eq("payStatus", 2).eq("state", 1));
+        List<WorldCupStore> list = worldCupStoreService.lambdaQuery().eq(WorldCupStore::getWorldCupId, id).list();
+        Integer storeId = list.get(0).getStoreId();
+        Store store = storeClient.queryStoreById(storeId);
         for (WorldCupPayment worldCupPayment : list2) {
             List<WorldCupPaymentParticipant> list1 = worldCupPaymentParticipantService.list(new QueryWrapper<WorldCupPaymentParticipant>()
                     .eq("worldCupId", id).eq("worldCupPaymentId", worldCupPayment.getId()).eq("alreadyEntered", 0));
@@ -860,14 +863,25 @@
             BigDecimal multiply = worldCupPayment.getUnitPrice().multiply(new BigDecimal(list1.size()));
             //微信支付
             if(worldCupPayment.getPayType() == 1){
-                Map<String, String> map = payMoneyUtil.wxRefund(worldCupPayment.getPayOrderNo(), worldCupPayment.getCode(),
-                        worldCupPayment.getAmount().toString(), multiply.toString(), "/base/worldCup/wxRefundWorldCupCallback");
-                if(!"SUCCESS".equals(map.get("return_code"))){
-                    System.err.println("-------------微信退款失败---------");
-                    System.err.println(map.get("return_msg"));
-                }else{
-                    worldCupPayment.setRefundAmount(multiply);
-                    worldCupPaymentService.updateById(worldCupPayment);
+                if (store.getOperatorId()!=null && store.getOperatorId()!=0){
+                    String smidVx= storeClient.getmerchantNumberByOperatorId(store.getOperatorId());
+                    if (!StringUtils.hasLength(smidVx)){
+                        System.err.println("运营商未配置微信商户号,获取支付失败!");
+                    }
+                    SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
+                    String codeRefund = sdf.format(new Date()) + UUIDUtil.getNumberRandom(5);// 退款单号
+                    // 运营商退款
+                    payMoneyUtil.weixinRefundV3(smidVx, codeRefund, worldCupPayment.getPayOrderNo(), worldCupPayment.getAmount().toString(), "/base/worldCup/wxRefundWorldCupCallback1");
+                }else {
+                    Map<String, String> map = payMoneyUtil.wxRefund(worldCupPayment.getPayOrderNo(), worldCupPayment.getCode(),
+                            worldCupPayment.getAmount().toString(), multiply.toString(), "/base/worldCup/wxRefundWorldCupCallback");
+                    if (!"SUCCESS".equals(map.get("return_code"))) {
+                        System.err.println("-------------微信退款失败---------");
+                        System.err.println(map.get("return_msg"));
+                    } else {
+                        worldCupPayment.setRefundAmount(multiply);
+                        worldCupPaymentService.updateById(worldCupPayment);
+                    }
                 }
             }
             //支付宝支付
diff --git a/cloud-server-communityWorldCup/src/main/java/com/dsh/communityWorldCup/util/PayMoneyUtil.java b/cloud-server-communityWorldCup/src/main/java/com/dsh/communityWorldCup/util/PayMoneyUtil.java
index 6c342bc..d2fbb60 100644
--- a/cloud-server-communityWorldCup/src/main/java/com/dsh/communityWorldCup/util/PayMoneyUtil.java
+++ b/cloud-server-communityWorldCup/src/main/java/com/dsh/communityWorldCup/util/PayMoneyUtil.java
@@ -7,10 +7,7 @@
 import com.alipay.api.request.*;
 import com.alipay.api.response.*;
 import com.dsh.communityWorldCup.util.httpClinet.HttpClientUtil;
-import com.dsh.communityWorldCup.util.wx.PartnerAppPrepay;
-import com.dsh.communityWorldCup.util.wx.WXPayUtility;
-import com.dsh.communityWorldCup.util.wx.WeChatV3SignUtil;
-import com.dsh.communityWorldCup.util.wx.WxV3PayConfig;
+import com.dsh.communityWorldCup.util.wx.*;
 import org.apache.commons.collections.map.HashedMap;
 import org.bouncycastle.jce.provider.BouncyCastleProvider;
 import org.dom4j.Document;
@@ -729,6 +726,39 @@
         }
     }
 
+    public ResultUtil weixinRefundV3(String subMchid,String outRefundNo, String transactionId, String totalFee, String notifyUrl) throws Exception {
+        BigDecimal bigDecimal = new BigDecimal(totalFee);
+        int i = bigDecimal.multiply(new BigDecimal("100")).intValue();
+        // TODO: 请准备商户开发必要参数,参考:https://pay.weixin.qq.com/doc/v3/partner/4013080340
+        Create client = new Create(
+                "1681873607",                    // 商户号,是由微信支付系统生成并分配给每个商户的唯一标识符,商户号获取方式参考 https://pay.weixin.qq.com/doc/v3/merchant/4013070756
+                "55714944F7A7E52526F708280B176DCC838F371A",         // 商户API证书序列号,如何获取请参考 https://pay.weixin.qq.com/doc/v3/merchant/4013053053
+                "/usr/playpai/server/wxV3/1681873607_20250424_cert/apiclient_key.pem",    // 商户API证书私钥文件路径,本地文件路径
+                "PUB_KEY_ID_0116818736072025042400351694002605",      // 微信支付公钥ID,如何获取请参考 https://pay.weixin.qq.com/doc/v3/merchant/4013038816
+                "/usr/playpai/server/wxV3/pub_key.pem"        // 微信支付公钥文件路径,本地文件路径
+        );
+
+        Create.CreateRequest request = new Create.CreateRequest();
+        request.subMchid = subMchid;
+        request.transactionId = transactionId;
+        request.outRefundNo = outRefundNo;
+        request.reason = "退款";
+        request.notifyUrl = callbackPath+notifyUrl;
+        request.amount = new Create.AmountReq();
+        request.amount.refund = (long) i;
+        request.amount.total = (long) i;
+        request.amount.currency = "CNY";
+        try {
+            Create.Refund response = client.run(request);
+
+            // TODO: 请求成功,继续业务逻辑
+            System.out.println(response);
+        } catch (WXPayUtility.ApiException e) {
+            // TODO: 请求失败,根据状态码执行不同的逻辑
+            e.printStackTrace();
+        }
+        return ResultUtil.success();
+    }
 
     /**
      * 微信退款成功后的回调处理
diff --git a/cloud-server-communityWorldCup/src/main/java/com/dsh/communityWorldCup/util/wx/Create.java b/cloud-server-communityWorldCup/src/main/java/com/dsh/communityWorldCup/util/wx/Create.java
new file mode 100644
index 0000000..e1f6045
--- /dev/null
+++ b/cloud-server-communityWorldCup/src/main/java/com/dsh/communityWorldCup/util/wx/Create.java
@@ -0,0 +1,292 @@
+package com.dsh.communityWorldCup.util.wx;
+
+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;
+
+/**
+ * 退款申请
+ */
+public class Create {
+  private static String HOST = "https://api.mch.weixin.qq.com";
+  private static String METHOD = "POST";
+  private static String PATH = "/v3/refund/domestic/refunds";
+
+
+  public Refund run(CreateRequest 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, Refund.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 Create(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 enum Status {
+    @SerializedName("SUCCESS")
+    SUCCESS,
+    @SerializedName("CLOSED")
+    CLOSED,
+    @SerializedName("PROCESSING")
+    PROCESSING,
+    @SerializedName("ABNORMAL")
+    ABNORMAL
+  }
+
+  public enum Account {
+    @SerializedName("AVAILABLE")
+    AVAILABLE,
+    @SerializedName("UNAVAILABLE")
+    UNAVAILABLE
+  }
+
+  public enum PromotionType {
+    @SerializedName("COUPON")
+    COUPON,
+    @SerializedName("DISCOUNT")
+    DISCOUNT
+  }
+
+  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("unit_price")
+    public Long unitPrice;
+
+    @SerializedName("refund_amount")
+    public Long refundAmount;
+
+    @SerializedName("refund_quantity")
+    public Integer refundQuantity;
+  }
+
+  public static class CreateRequest {
+    @SerializedName("sub_mchid")
+    public String subMchid;
+
+    @SerializedName("transaction_id")
+    public String transactionId;
+
+    @SerializedName("out_trade_no")
+    public String outTradeNo;
+
+    @SerializedName("out_refund_no")
+    public String outRefundNo;
+
+    @SerializedName("reason")
+    public String reason;
+
+    @SerializedName("notify_url")
+    public String notifyUrl;
+
+    @SerializedName("funds_account")
+    public ReqFundsAccount fundsAccount;
+
+    @SerializedName("amount")
+    public AmountReq amount;
+
+    @SerializedName("goods_detail")
+    public List<GoodsDetail> goodsDetail;
+  }
+
+  public enum Channel {
+    @SerializedName("ORIGINAL")
+    ORIGINAL,
+    @SerializedName("BALANCE")
+    BALANCE,
+    @SerializedName("OTHER_BALANCE")
+    OTHER_BALANCE,
+    @SerializedName("OTHER_BANKCARD")
+    OTHER_BANKCARD
+  }
+
+  public static class Amount {
+    @SerializedName("total")
+    public Long total;
+
+    @SerializedName("refund")
+    public Long refund;
+
+    @SerializedName("from")
+    public List<FundsFromItem> from;
+
+    @SerializedName("payer_total")
+    public Long payerTotal;
+
+    @SerializedName("payer_refund")
+    public Long payerRefund;
+
+    @SerializedName("settlement_refund")
+    public Long settlementRefund;
+
+    @SerializedName("settlement_total")
+    public Long settlementTotal;
+
+    @SerializedName("discount_refund")
+    public Long discountRefund;
+
+    @SerializedName("currency")
+    public String currency;
+
+    @SerializedName("refund_fee")
+    public Long refundFee;
+  }
+
+  public enum ReqFundsAccount {
+    @SerializedName("AVAILABLE")
+    AVAILABLE,
+    @SerializedName("UNSETTLED")
+    UNSETTLED
+  }
+
+  public enum FundsAccount {
+    @SerializedName("UNSETTLED")
+    UNSETTLED,
+    @SerializedName("AVAILABLE")
+    AVAILABLE,
+    @SerializedName("UNAVAILABLE")
+    UNAVAILABLE,
+    @SerializedName("OPERATION")
+    OPERATION,
+    @SerializedName("BASIC")
+    BASIC,
+    @SerializedName("ECNY_BASIC")
+    ECNY_BASIC
+  }
+
+  public static class Promotion {
+    @SerializedName("promotion_id")
+    public String promotionId;
+
+    @SerializedName("scope")
+    public PromotionScope scope;
+
+    @SerializedName("type")
+    public PromotionType type;
+
+    @SerializedName("amount")
+    public Long amount;
+
+    @SerializedName("refund_amount")
+    public Long refundAmount;
+
+    @SerializedName("goods_detail")
+    public List<GoodsDetail> goodsDetail;
+  }
+
+  public static class Refund {
+    @SerializedName("refund_id")
+    public String refundId;
+
+    @SerializedName("out_refund_no")
+    public String outRefundNo;
+
+    @SerializedName("transaction_id")
+    public String transactionId;
+
+    @SerializedName("out_trade_no")
+    public String outTradeNo;
+
+    @SerializedName("channel")
+    public Channel channel;
+
+    @SerializedName("user_received_account")
+    public String userReceivedAccount;
+
+    @SerializedName("success_time")
+    public String successTime;
+
+    @SerializedName("create_time")
+    public String createTime;
+
+    @SerializedName("status")
+    public Status status;
+
+    @SerializedName("funds_account")
+    public FundsAccount fundsAccount;
+
+    @SerializedName("amount")
+    public Amount amount;
+
+    @SerializedName("promotion_detail")
+    public List<Promotion> promotionDetail;
+  }
+
+  public static class FundsFromItem {
+    @SerializedName("account")
+    public Account account;
+
+    @SerializedName("amount")
+    public Long amount;
+  }
+
+  public static class AmountReq {
+    @SerializedName("refund")
+    public Long refund;
+
+    @SerializedName("from")
+    public List<FundsFromItem> from;
+
+    @SerializedName("total")
+    public Long total;
+
+    @SerializedName("currency")
+    public String currency;
+  }
+
+  public enum PromotionScope {
+    @SerializedName("GLOBAL")
+    GLOBAL,
+    @SerializedName("SINGLE")
+    SINGLE
+  }
+}
\ No newline at end of file
diff --git a/cloud-server-communityWorldCup/src/main/resources/sharding-jdbc.properties b/cloud-server-communityWorldCup/src/main/resources/sharding-jdbc.properties
index 9156bff..1007165 100644
--- a/cloud-server-communityWorldCup/src/main/resources/sharding-jdbc.properties
+++ b/cloud-server-communityWorldCup/src/main/resources/sharding-jdbc.properties
@@ -1,15 +1,3 @@
-datasource.names=master0
-datasource.master0.type=com.alibaba.druid.pool.DruidDataSource
-datasource.master0.driverClassName=com.mysql.cj.jdbc.Driver
-datasource.master0.url=jdbc:mysql://8.137.22.229:3306/playpai_community_world_cup?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai
-datasource.master0.username=root
-datasource.master0.password=playpai2023!
-datasource.master0.maxActive=20
-datasource.master0.maxWait=60000
-datasource.master0.minIdle=5
-datasource.master0.initialSize=2
-
-
 
 #datasource.names=master0
 #datasource.master0.type=com.alibaba.druid.pool.DruidDataSource
@@ -23,4 +11,13 @@
 #datasource.master0.initialSize=2
 
 
-
+datasource.names=master0
+datasource.master0.type=com.alibaba.druid.pool.DruidDataSource
+datasource.master0.driverClassName=com.mysql.cj.jdbc.Driver
+datasource.master0.url=jdbc:mysql://127.0.0.1:3306/playpai_community_world_cup?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai
+datasource.master0.username=root
+datasource.master0.password=playpai2023!
+datasource.master0.maxActive=20
+datasource.master0.maxWait=60000
+datasource.master0.minIdle=5
+datasource.master0.initialSize=2
diff --git a/cloud-server-competition/src/main/java/com/dsh/competition/controller/CompetitionController.java b/cloud-server-competition/src/main/java/com/dsh/competition/controller/CompetitionController.java
index b52f889..208c8bc 100644
--- a/cloud-server-competition/src/main/java/com/dsh/competition/controller/CompetitionController.java
+++ b/cloud-server-competition/src/main/java/com/dsh/competition/controller/CompetitionController.java
@@ -21,6 +21,7 @@
 import com.dsh.competition.feignclient.course.model.PaymentDeductionClassHour;
 import com.dsh.competition.feignclient.model.*;
 import com.dsh.competition.feignclient.other.StoreClient;
+import com.dsh.competition.feignclient.other.model.Store;
 import com.dsh.competition.model.*;
 import com.dsh.competition.service.CompetitionService;
 import com.dsh.competition.service.IParticipantService;
@@ -667,6 +668,64 @@
             e.printStackTrace();
         }
     }
+    /**
+     * 取消已报名赛事后微信回退金额回调微信V3服务商版本
+     *
+     * @param request
+     * @param response
+     */
+    @ResponseBody
+    @PostMapping("/base/competition/weChatCancelPaymentCompetitionCallback1")
+    public void weChatCancelPaymentCompetitionCallback1(HttpServletRequest request, HttpServletResponse response) {
+        try {
+            System.err.println("微信回调");
+            System.err.println("请求" + request);
+            BufferedReader reader = request.getReader();
+            String string1 = reader.toString();
+            System.err.println("请求reader" + string1);
+            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 code = jsonInfo.getString("out_trade_no");
+            String transaction_id = jsonInfo.getString("transaction_id");
+            String refund_status = jsonInfo.getString("refund_status");
+            String out_refund_no = jsonInfo.getString("out_refund_no");
+            if (refund_status.equals("SUCCESS")) {
+                PaymentCompetition paymentCompetition = paymentCompetitionService.getOne(new QueryWrapper<PaymentCompetition>()
+                        .eq("code", code).eq("payType", 1));
+                if (paymentCompetition.getPayStatus() == 2) {
+                    paymentCompetition.setPayStatus(3);
+                    paymentCompetition.setRefundTime(new Date());
+                    paymentCompetition.setRefundOrderNo(out_refund_no);
+                    paymentCompetition.setAppUserId(null);
+                    paymentCompetitionService.updateById(paymentCompetition);
+
+                    Competition competition = cttService.getById(paymentCompetition.getCompetitionId());
+                    competition.setApplicantsNumber(competition.getApplicantsNumber() - 1);
+                    cttService.updateById(competition);
+                    storeClient.addBackRecord(paymentCompetition.getAmount() + "_" + paymentCompetition.getAppUserId());
+
+                }
+                PrintWriter out = response.getWriter();
+                out.write("SUCCESS");
+                out.flush();
+                out.close();
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
 
 
     @PostMapping("/base/competition/queryById")
@@ -859,46 +918,32 @@
                 String code = paymentCompetition.getCode();
                 Double amount = paymentCompetition.getAmount();
                 Competition competition = competitionService.getById(paymentCompetition.getCompetitionId());
-
-
+                Store store = storeClient.queryStoreById(Integer.valueOf(competition.getStoreId().split(",")[0]));
                 String payOrderNo = paymentCompetition.getPayOrderNo();
                 if (paymentCompetition.getPayType() == 1) {//微信支付
-                    if (StringUtils.hasLength(paymentCompetition.getFenzhangNo())){
-                        // 是分账订单 如果分账金额不为0 那么回退分账金额
-                        if (paymentCompetition.getFenzhangAmount()!=null && paymentCompetition.getFenzhangAmount().compareTo(BigDecimal.ZERO)>0){
-                            String randomCode = UUIDUtil.getRandomCode(16);
-                            String randomCode1 = UUIDUtil.getRandomCode(16);
-                            if (competition.getOperatorId()!=null && competition.getOperatorId()!=0){
-                                // 微信商户号
-                                String s2 =storeClient.getmerchantNumberByOperatorId(competition.getOperatorId());
-                                ResultUtil resultUtil = payMoneyUtil.fenzhangRefund(paymentCompetition.getFenzhangNo(), paymentCompetition.getFenzhangAmount(), s2, randomCode, randomCode1);
-                                if (!resultUtil.getCode().equals(200)){
-                                    System.err.println("分账回退失败 原因是:"+resultUtil.getMsg());
-                                }else{
-                                    paymentCompetition.setFenzhangRefundNo(resultUtil.getData().toString());
-                                    paymentCompetitionService.updateById(paymentCompetition);
-                                }
-
-                            }
+                    if (store.getOperatorId()!=null && store.getOperatorId()!=0){
+                        String smidVx= storeClient.getmerchantNumberByOperatorId(store.getOperatorId());
+                        if (!StringUtils.hasLength(smidVx)){
+                            System.err.println("运营商未配置微信商户号,获取支付失败!");
                         }
-                    }
-
-
-
-
-                    Map<String, String> map = payMoneyUtil.wxRefund(payOrderNo, code, amount.toString(), amount.toString(),
-                            "/base/competition/weChatCancelPaymentCompetitionCallback");
-                    String return_code = map.get("return_code");
-                    if (!"SUCCESS".equals(return_code)) {
+                        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
+                        String codeRefund = sdf.format(new Date()) + UUIDUtil.getNumberRandom(5);// 退款单号
+                        // 运营商退款
+                        payMoneyUtil.weixinRefundV3(smidVx, codeRefund, pay.getPayOrderNo(), pay.getAmount().toString(), "/base/competition/weChatCancelPaymentCompetitionCallback1");
+                    }else {
+                        Map<String, String> map = payMoneyUtil.wxRefund(payOrderNo, code, amount.toString(), amount.toString(),
+                                "/base/competition/weChatCancelPaymentCompetitionCallback");
+                        String return_code = map.get("return_code");
+                        if (!"SUCCESS".equals(return_code)) {
 //                        return ResultUtil.error(map.get("return_msg"));
-                        continue;
+                            continue;
+                        }
+                        String refund_id = map.get("refund_id");
+                        paymentCompetition.setRefundOrderNo(refund_id);
+                        paymentCompetition.setAppUserId(null);
+                        paymentCompetitionService.updateById(paymentCompetition);
+                        storeClient.addBackRecord(paymentCompetition.getAmount() + "_" + paymentCompetition.getAppUserId());
                     }
-                    String refund_id = map.get("refund_id");
-                    paymentCompetition.setRefundOrderNo(refund_id);
-                    paymentCompetition.setAppUserId(null);
-                    paymentCompetitionService.updateById(paymentCompetition);
-                    storeClient.addBackRecord(paymentCompetition.getAmount() + "_" + paymentCompetition.getAppUserId());
-
                 }
                 if (paymentCompetition.getPayType() == 2) {//支付宝支付
                     Map<String, String> map = payMoneyUtil.aliRefund(payOrderNo, amount.toString());
diff --git a/cloud-server-competition/src/main/java/com/dsh/competition/service/impl/PaymentCompetitionServiceImpl.java b/cloud-server-competition/src/main/java/com/dsh/competition/service/impl/PaymentCompetitionServiceImpl.java
index 81b6967..f7914ad 100644
--- a/cloud-server-competition/src/main/java/com/dsh/competition/service/impl/PaymentCompetitionServiceImpl.java
+++ b/cloud-server-competition/src/main/java/com/dsh/competition/service/impl/PaymentCompetitionServiceImpl.java
@@ -248,38 +248,32 @@
         }
 
         String payOrderNo = paymentCompetition.getPayOrderNo();
+        Store store = storeClient.queryStoreById(Integer.valueOf(competition.getStoreId().split(",")[0]));
+
         if (paymentCompetition.getPayType() == 1) {//微信支付
-            if (StringUtils.hasLength(paymentCompetition.getFenzhangNo())){
-                // 是分账订单 如果分账金额不为0 那么回退分账金额
-                if (paymentCompetition.getFenzhangAmount()!=null && paymentCompetition.getFenzhangAmount().compareTo(BigDecimal.ZERO)>0){
-                    String randomCode = UUIDUtil.getRandomCode(16);
-                    String randomCode1 = UUIDUtil.getRandomCode(16);
-                    if (competition.getOperatorId()!=null && competition.getOperatorId()!=0){
-                        // 微信商户号
-                        String s2 =storeClient.getmerchantNumberByOperatorId(competition.getOperatorId());
-                        ResultUtil resultUtil = payMoneyUtil.fenzhangRefund(paymentCompetition.getFenzhangNo(), paymentCompetition.getFenzhangAmount(), s2, randomCode, randomCode1);
-                        if (!resultUtil.getCode().equals(200)){
-                            System.err.println("分账回退失败 原因是:"+resultUtil.getData().toString());
-                        }else{
-                            paymentCompetition.setFenzhangRefundNo(resultUtil.getData().toString());
-                            paymentCompetitionMapper.updateById(paymentCompetition);
-                        }
-
-                    }
+            if (store.getOperatorId()!=null && store.getOperatorId()!=0){
+                String smidVx= storeClient.getmerchantNumberByOperatorId(store.getOperatorId());
+                if (!StringUtils.hasLength(smidVx)){
+                    System.err.println("运营商未配置微信商户号,获取支付失败!");
                 }
-            }
-            Map<String, String> map = payMoneyUtil.wxRefund(payOrderNo, code, amount.toString(), amount.toString(),
-                    "/base/competition/weChatCancelPaymentCompetitionCallback");
-            String return_code = map.get("return_code");
-            if (!"SUCCESS".equals(return_code)) {
-                return ResultUtil.error(map.get("return_msg"));
-            }
-            String refund_id = map.get("refund_id");
-            paymentCompetition.setRefundOrderNo(refund_id);
-            paymentCompetition.setAppUserId(null);
-            this.updateById(paymentCompetition);
+                SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
+                String codeRefund = sdf.format(new Date()) + UUIDUtil.getNumberRandom(5);// 退款单号
+                // 运营商退款
+                payMoneyUtil.weixinRefundV3(smidVx, codeRefund, paymentCompetition.getPayOrderNo(), paymentCompetition.getAmount().toString(), "/base/competition/weChatCancelPaymentCompetitionCallback1");
+            }else {
+                Map<String, String> map = payMoneyUtil.wxRefund(payOrderNo, code, amount.toString(), amount.toString(),
+                        "/base/competition/weChatCancelPaymentCompetitionCallback");
+                String return_code = map.get("return_code");
+                if (!"SUCCESS".equals(return_code)) {
+                    return ResultUtil.error(map.get("return_msg"));
+                }
+                String refund_id = map.get("refund_id");
+                paymentCompetition.setRefundOrderNo(refund_id);
+                paymentCompetition.setAppUserId(null);
+                this.updateById(paymentCompetition);
 
-            storeClient.addBackRecord(paymentCompetition.getAmount() + "_" + paymentCompetition.getAppUserId());
+                storeClient.addBackRecord(paymentCompetition.getAmount() + "_" + paymentCompetition.getAppUserId());
+            }
         }
         if (paymentCompetition.getPayType() == 2) {//支付宝支付
             Map<String, String> map = payMoneyUtil.aliRefund(payOrderNo, amount.toString());
diff --git a/cloud-server-competition/src/main/java/com/dsh/competition/util/PayMoneyUtil.java b/cloud-server-competition/src/main/java/com/dsh/competition/util/PayMoneyUtil.java
index 7f95b70..fa7103f 100644
--- a/cloud-server-competition/src/main/java/com/dsh/competition/util/PayMoneyUtil.java
+++ b/cloud-server-competition/src/main/java/com/dsh/competition/util/PayMoneyUtil.java
@@ -8,10 +8,7 @@
 import com.alipay.api.request.*;
 import com.alipay.api.response.*;
 import com.dsh.competition.util.httpClinet.HttpClientUtil;
-import com.dsh.competition.util.wx.PartnerAppPrepay;
-import com.dsh.competition.util.wx.WXPayUtility;
-import com.dsh.competition.util.wx.WeChatV3SignUtil;
-import com.dsh.competition.util.wx.WxV3PayConfig;
+import com.dsh.competition.util.wx.*;
 import org.apache.commons.collections.map.HashedMap;
 import org.bouncycastle.jce.provider.BouncyCastleProvider;
 import org.dom4j.Document;
@@ -848,6 +845,39 @@
             return map2;
         }
     }
+    public ResultUtil weixinRefundV3(String subMchid,String outRefundNo, String transactionId, String totalFee, String notifyUrl) throws Exception {
+        BigDecimal bigDecimal = new BigDecimal(totalFee);
+        int i = bigDecimal.multiply(new BigDecimal("100")).intValue();
+        // TODO: 请准备商户开发必要参数,参考:https://pay.weixin.qq.com/doc/v3/partner/4013080340
+        Create client = new Create(
+                "1681873607",                    // 商户号,是由微信支付系统生成并分配给每个商户的唯一标识符,商户号获取方式参考 https://pay.weixin.qq.com/doc/v3/merchant/4013070756
+                "55714944F7A7E52526F708280B176DCC838F371A",         // 商户API证书序列号,如何获取请参考 https://pay.weixin.qq.com/doc/v3/merchant/4013053053
+                "/usr/playpai/server/wxV3/1681873607_20250424_cert/apiclient_key.pem",    // 商户API证书私钥文件路径,本地文件路径
+                "PUB_KEY_ID_0116818736072025042400351694002605",      // 微信支付公钥ID,如何获取请参考 https://pay.weixin.qq.com/doc/v3/merchant/4013038816
+                "/usr/playpai/server/wxV3/pub_key.pem"        // 微信支付公钥文件路径,本地文件路径
+        );
+
+        Create.CreateRequest request = new Create.CreateRequest();
+        request.subMchid = subMchid;
+        request.transactionId = transactionId;
+        request.outRefundNo = outRefundNo;
+        request.reason = "退款";
+        request.notifyUrl = callbackPath+notifyUrl;
+        request.amount = new Create.AmountReq();
+        request.amount.refund = (long) i;
+        request.amount.total = (long) i;
+        request.amount.currency = "CNY";
+        try {
+            Create.Refund response = client.run(request);
+
+            // TODO: 请求成功,继续业务逻辑
+            System.out.println(response);
+        } catch (WXPayUtility.ApiException e) {
+            // TODO: 请求失败,根据状态码执行不同的逻辑
+            e.printStackTrace();
+        }
+        return ResultUtil.success();
+    }
     /**
      * 发起分账回退
      * @param order 微信订单号
diff --git a/cloud-server-competition/src/main/java/com/dsh/competition/util/wx/Create.java b/cloud-server-competition/src/main/java/com/dsh/competition/util/wx/Create.java
new file mode 100644
index 0000000..7f6af48
--- /dev/null
+++ b/cloud-server-competition/src/main/java/com/dsh/competition/util/wx/Create.java
@@ -0,0 +1,292 @@
+package com.dsh.competition.util.wx;
+
+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;
+
+/**
+ * 退款申请
+ */
+public class Create {
+  private static String HOST = "https://api.mch.weixin.qq.com";
+  private static String METHOD = "POST";
+  private static String PATH = "/v3/refund/domestic/refunds";
+
+
+  public Refund run(CreateRequest 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, Refund.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 Create(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 enum Status {
+    @SerializedName("SUCCESS")
+    SUCCESS,
+    @SerializedName("CLOSED")
+    CLOSED,
+    @SerializedName("PROCESSING")
+    PROCESSING,
+    @SerializedName("ABNORMAL")
+    ABNORMAL
+  }
+
+  public enum Account {
+    @SerializedName("AVAILABLE")
+    AVAILABLE,
+    @SerializedName("UNAVAILABLE")
+    UNAVAILABLE
+  }
+
+  public enum PromotionType {
+    @SerializedName("COUPON")
+    COUPON,
+    @SerializedName("DISCOUNT")
+    DISCOUNT
+  }
+
+  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("unit_price")
+    public Long unitPrice;
+
+    @SerializedName("refund_amount")
+    public Long refundAmount;
+
+    @SerializedName("refund_quantity")
+    public Integer refundQuantity;
+  }
+
+  public static class CreateRequest {
+    @SerializedName("sub_mchid")
+    public String subMchid;
+
+    @SerializedName("transaction_id")
+    public String transactionId;
+
+    @SerializedName("out_trade_no")
+    public String outTradeNo;
+
+    @SerializedName("out_refund_no")
+    public String outRefundNo;
+
+    @SerializedName("reason")
+    public String reason;
+
+    @SerializedName("notify_url")
+    public String notifyUrl;
+
+    @SerializedName("funds_account")
+    public ReqFundsAccount fundsAccount;
+
+    @SerializedName("amount")
+    public AmountReq amount;
+
+    @SerializedName("goods_detail")
+    public List<GoodsDetail> goodsDetail;
+  }
+
+  public enum Channel {
+    @SerializedName("ORIGINAL")
+    ORIGINAL,
+    @SerializedName("BALANCE")
+    BALANCE,
+    @SerializedName("OTHER_BALANCE")
+    OTHER_BALANCE,
+    @SerializedName("OTHER_BANKCARD")
+    OTHER_BANKCARD
+  }
+
+  public static class Amount {
+    @SerializedName("total")
+    public Long total;
+
+    @SerializedName("refund")
+    public Long refund;
+
+    @SerializedName("from")
+    public List<FundsFromItem> from;
+
+    @SerializedName("payer_total")
+    public Long payerTotal;
+
+    @SerializedName("payer_refund")
+    public Long payerRefund;
+
+    @SerializedName("settlement_refund")
+    public Long settlementRefund;
+
+    @SerializedName("settlement_total")
+    public Long settlementTotal;
+
+    @SerializedName("discount_refund")
+    public Long discountRefund;
+
+    @SerializedName("currency")
+    public String currency;
+
+    @SerializedName("refund_fee")
+    public Long refundFee;
+  }
+
+  public enum ReqFundsAccount {
+    @SerializedName("AVAILABLE")
+    AVAILABLE,
+    @SerializedName("UNSETTLED")
+    UNSETTLED
+  }
+
+  public enum FundsAccount {
+    @SerializedName("UNSETTLED")
+    UNSETTLED,
+    @SerializedName("AVAILABLE")
+    AVAILABLE,
+    @SerializedName("UNAVAILABLE")
+    UNAVAILABLE,
+    @SerializedName("OPERATION")
+    OPERATION,
+    @SerializedName("BASIC")
+    BASIC,
+    @SerializedName("ECNY_BASIC")
+    ECNY_BASIC
+  }
+
+  public static class Promotion {
+    @SerializedName("promotion_id")
+    public String promotionId;
+
+    @SerializedName("scope")
+    public PromotionScope scope;
+
+    @SerializedName("type")
+    public PromotionType type;
+
+    @SerializedName("amount")
+    public Long amount;
+
+    @SerializedName("refund_amount")
+    public Long refundAmount;
+
+    @SerializedName("goods_detail")
+    public List<GoodsDetail> goodsDetail;
+  }
+
+  public static class Refund {
+    @SerializedName("refund_id")
+    public String refundId;
+
+    @SerializedName("out_refund_no")
+    public String outRefundNo;
+
+    @SerializedName("transaction_id")
+    public String transactionId;
+
+    @SerializedName("out_trade_no")
+    public String outTradeNo;
+
+    @SerializedName("channel")
+    public Channel channel;
+
+    @SerializedName("user_received_account")
+    public String userReceivedAccount;
+
+    @SerializedName("success_time")
+    public String successTime;
+
+    @SerializedName("create_time")
+    public String createTime;
+
+    @SerializedName("status")
+    public Status status;
+
+    @SerializedName("funds_account")
+    public FundsAccount fundsAccount;
+
+    @SerializedName("amount")
+    public Amount amount;
+
+    @SerializedName("promotion_detail")
+    public List<Promotion> promotionDetail;
+  }
+
+  public static class FundsFromItem {
+    @SerializedName("account")
+    public Account account;
+
+    @SerializedName("amount")
+    public Long amount;
+  }
+
+  public static class AmountReq {
+    @SerializedName("refund")
+    public Long refund;
+
+    @SerializedName("from")
+    public List<FundsFromItem> from;
+
+    @SerializedName("total")
+    public Long total;
+
+    @SerializedName("currency")
+    public String currency;
+  }
+
+  public enum PromotionScope {
+    @SerializedName("GLOBAL")
+    GLOBAL,
+    @SerializedName("SINGLE")
+    SINGLE
+  }
+}
\ No newline at end of file
diff --git a/cloud-server-other/src/main/java/com/dsh/other/controller/SiteController.java b/cloud-server-other/src/main/java/com/dsh/other/controller/SiteController.java
index ca5439a..3a637db 100644
--- a/cloud-server-other/src/main/java/com/dsh/other/controller/SiteController.java
+++ b/cloud-server-other/src/main/java/com/dsh/other/controller/SiteController.java
@@ -709,6 +709,7 @@
     })
     public ResultUtil cancelMySite(Integer id) {
         try {
+            System.err.println("预约数据id");
             Integer uid = tokenUtil.getUserIdFormRedis();
             if (null == uid) {
                 return ResultUtil.tokenErr();
@@ -756,7 +757,59 @@
             e.printStackTrace();
         }
     }
+    /**
+     * 微信退款回调V3服务商版本
+     *
+     * @param request
+     * @param response
+     */
+    @ResponseBody
+    @PostMapping("/base/site/cancelMySiteCallback1")
+    public void cancelMySiteCallback1(HttpServletRequest request, HttpServletResponse response) {
+        try {
+            System.err.println("微信回调");
+            System.err.println("请求" + request);
+            BufferedReader reader = request.getReader();
+            String string1 = reader.toString();
+            System.err.println("请求reader" + string1);
+            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 code = jsonInfo.getString("out_trade_no");
+            String transaction_id = jsonInfo.getString("transaction_id");
+            String refund_status = jsonInfo.getString("refund_status");
+            String out_refund_no = jsonInfo.getString("out_refund_no");
+            if (refund_status.equals("SUCCESS")) {
+                SiteBooking siteBooking = siteBookingService.getOne(new QueryWrapper<SiteBooking>().eq("orderNo", code).eq("state", 1));
+                siteBooking.setStatus(5);
+                siteBooking.setCancelTime(new Date());
+                siteBooking.setRefundOrderNo(out_refund_no);
+                siteBookingService.updateById(siteBooking);
+                if (null != siteBooking.getUserCouponId()) {
+                    UserCoupon userCoupon = userCouponClient.queryUserCouponById(new QueryUserCouponByIdAndUserId(siteBooking.getUserCouponId(), siteBooking.getAppUserId()));
+                    userCoupon.setStatus(1);
+                    userCouponClient.updateUserCoupon(userCoupon);
+                }
+                    PrintWriter out = response.getWriter();
+                    out.write("SUCCESS");
+                    out.flush();
+                    out.close();
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
 
     @ResponseBody
     @PostMapping("/api/site/continuePaymentMySite")
diff --git a/cloud-server-other/src/main/java/com/dsh/other/service/impl/SiteServiceImpl.java b/cloud-server-other/src/main/java/com/dsh/other/service/impl/SiteServiceImpl.java
index 95a170c..f0ca39a 100644
--- a/cloud-server-other/src/main/java/com/dsh/other/service/impl/SiteServiceImpl.java
+++ b/cloud-server-other/src/main/java/com/dsh/other/service/impl/SiteServiceImpl.java
@@ -65,6 +65,7 @@
     @Resource
     private UserCouponClient userCouponClient;
 
+
     @Resource
     private CouponClient couponClient;
 
@@ -708,43 +709,39 @@
         if (siteBooking.getStatus() != 1 && siteBooking.getStatus() != 2) {
             return ResultUtil.error("不能进行取消操作");
         }
+        Integer storeId = siteBooking.getStoreId();
+        Store store = storeService.getById(storeId);
+
         if (siteBooking.getPayType() == 1) {//微信支付
-            if (StringUtils.hasLength(siteBooking.getFenzhangNo())){
-                // 是分账订单 如果分账金额不为0 那么回退分账金额
-                if (siteBooking.getFenzhangAmount()!=null && siteBooking.getFenzhangAmount().compareTo(BigDecimal.ZERO)>0){
-                    String randomCode = UUIDUtil.getRandomCode(16);
-                    String randomCode1 = UUIDUtil.getRandomCode(16);
-                    if (byId.getOperatorId()!=null && byId.getOperatorId()!=0){
-                        // 微信商户号
-                        String s2 =siteService.getmerchantNumberByOperatorId(byId.getOperatorId());
-                        ResultUtil resultUtil = payMoneyUtil.fenzhangRefund(siteBooking.getFenzhangNo(), siteBooking.getFenzhangAmount().multiply(new BigDecimal("100")), s2, randomCode, randomCode1);
-                        if (!resultUtil.getCode().equals(200)){
-                            System.err.println("分账回退失败 原因是:"+resultUtil.getMsg()+resultUtil.getData());
-                        }else{
-                            siteBooking.setFenzhangRefundNo(resultUtil.getMsg());
-                            siteBookingService.updateById(siteBooking);
-                        }
-
-                    }
+            if (store.getOperatorId()!=null && store.getOperatorId()!=0){
+                String smidVx= operatorUserService.getmerchantNumberByOperatorId(store.getOperatorId());
+                if (!StringUtils.hasLength(smidVx)){
+                    return ResultUtil.error("运营商未配置微信商户号,获取支付失败!");
                 }
-            }
-            Map<String, String> map = payMoneyUtil.wxRefund(siteBooking.getPayOrderNo(), siteBooking.getOrderNo(), siteBooking.getPayMoney().toString(),
-                    siteBooking.getPayMoney().toString(), "/base/site/cancelMySiteCallback");
-            if (null == map) {
-                return ResultUtil.error("取消退款异常");
-            }
-            String return_code = map.get("return_code");
-            if (!"SUCCESS".equals(return_code)) {
-                return ResultUtil.error(map.get("return_msg"));
-            }
-            siteBooking.setCancelUserId(uid);
-            siteBookingService.updateById(siteBooking);
+                SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
+                String code = sdf.format(new Date()) + UUIDUtil.getNumberRandom(5);// 退款单号
+                // 运营商退款
+                payMoneyUtil.weixinRefundV3(smidVx, code, siteBooking.getPayOrderNo(), siteBooking.getPayMoney().toString(), "/base/site/cancelMySiteCallback1");
+            }else{
+                Map<String, String> map = payMoneyUtil.wxRefund(siteBooking.getPayOrderNo(), siteBooking.getOrderNo(), siteBooking.getPayMoney().toString(),
+                        siteBooking.getPayMoney().toString(), "/base/site/cancelMySiteCallback");
+                if (null == map) {
+                    return ResultUtil.error("取消退款异常");
+                }
+                String return_code = map.get("return_code");
+                if (!"SUCCESS".equals(return_code)) {
+                    return ResultUtil.error(map.get("return_msg"));
+                }
+                siteBooking.setCancelUserId(uid);
+                siteBookingService.updateById(siteBooking);
 
-            TBackRecord tBackRecord = new TBackRecord();
-            tBackRecord.setMoney(siteBooking.getPayMoney());
-            tBackRecord.setUserId(siteBooking.getAppUserId());
-            tBackRecord.setTime(new Date());
-            backRecordService.save(tBackRecord);
+                TBackRecord tBackRecord = new TBackRecord();
+                tBackRecord.setMoney(siteBooking.getPayMoney());
+                tBackRecord.setUserId(siteBooking.getAppUserId());
+                tBackRecord.setTime(new Date());
+                backRecordService.save(tBackRecord);
+            }
+
 
         }
         if (siteBooking.getPayType() == 2) {//支付宝
diff --git a/cloud-server-other/src/main/java/com/dsh/other/util/PayMoneyUtil.java b/cloud-server-other/src/main/java/com/dsh/other/util/PayMoneyUtil.java
index 1d7e21d..f36d263 100644
--- a/cloud-server-other/src/main/java/com/dsh/other/util/PayMoneyUtil.java
+++ b/cloud-server-other/src/main/java/com/dsh/other/util/PayMoneyUtil.java
@@ -5,15 +5,9 @@
 import com.alibaba.fastjson.JSONObject;
 import com.alipay.api.*;
 import com.alipay.api.domain.*;
-import com.alipay.api.msg.AlipayMsgClient;
-import com.alipay.api.msg.MsgHandler;
 import com.alipay.api.request.*;
 import com.alipay.api.response.*;
-import com.dsh.other.util.wx.PartnerAppPrepay;
-import com.dsh.other.util.wx.WXPayUtility;
-import com.dsh.other.util.wx.WeChatV3SignUtil;
-import com.dsh.other.util.wx.WxV3PayConfig;
-import lombok.Synchronized;
+import com.dsh.other.util.wx.*;
 import org.apache.commons.collections.map.HashedMap;
 import org.bouncycastle.jce.provider.BouncyCastleProvider;
 import org.dom4j.Document;
@@ -23,9 +17,7 @@
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.MediaType;
 import org.springframework.stereotype.Component;
-import org.springframework.util.StringUtils;
 
-import javax.annotation.Resource;
 import javax.crypto.*;
 import javax.crypto.spec.SecretKeySpec;
 import javax.servlet.http.HttpServletRequest;
@@ -575,6 +567,39 @@
         System.err.println(map3);
         return ResultUtil.success(map3);
     }
+    public ResultUtil weixinRefundV3(String subMchid,String outRefundNo, String transactionId, String totalFee, String notifyUrl) throws Exception {
+        BigDecimal bigDecimal = new BigDecimal(totalFee);
+        int i = bigDecimal.multiply(new BigDecimal("100")).intValue();
+        // TODO: 请准备商户开发必要参数,参考:https://pay.weixin.qq.com/doc/v3/partner/4013080340
+        Create client = new Create(
+                "1681873607",                    // 商户号,是由微信支付系统生成并分配给每个商户的唯一标识符,商户号获取方式参考 https://pay.weixin.qq.com/doc/v3/merchant/4013070756
+                "55714944F7A7E52526F708280B176DCC838F371A",         // 商户API证书序列号,如何获取请参考 https://pay.weixin.qq.com/doc/v3/merchant/4013053053
+                "/usr/playpai/server/wxV3/1681873607_20250424_cert/apiclient_key.pem",    // 商户API证书私钥文件路径,本地文件路径
+                "PUB_KEY_ID_0116818736072025042400351694002605",      // 微信支付公钥ID,如何获取请参考 https://pay.weixin.qq.com/doc/v3/merchant/4013038816
+                "/usr/playpai/server/wxV3/pub_key.pem"        // 微信支付公钥文件路径,本地文件路径
+        );
+
+        Create.CreateRequest request = new Create.CreateRequest();
+        request.subMchid = subMchid;
+        request.transactionId = transactionId;
+        request.outRefundNo = outRefundNo;
+        request.reason = "退款";
+        request.notifyUrl = callbackPath+notifyUrl;
+        request.amount = new Create.AmountReq();
+        request.amount.refund = (long) i;
+        request.amount.total = (long) i;
+        request.amount.currency = "CNY";
+        try {
+            Create.Refund response = client.run(request);
+
+            // TODO: 请求成功,继续业务逻辑
+            System.out.println(response);
+        } catch (WXPayUtility.ApiException e) {
+            // TODO: 请求失败,根据状态码执行不同的逻辑
+            e.printStackTrace();
+        }
+        return ResultUtil.success();
+    }
 
     /**
      * 发起分账
diff --git a/cloud-server-other/src/main/java/com/dsh/other/util/wx/Create.java b/cloud-server-other/src/main/java/com/dsh/other/util/wx/Create.java
new file mode 100644
index 0000000..f693fc7
--- /dev/null
+++ b/cloud-server-other/src/main/java/com/dsh/other/util/wx/Create.java
@@ -0,0 +1,300 @@
+package com.dsh.other.util.wx;
+
+import com.dsh.other.util.wx.WXPayUtility;
+import com.google.gson.annotations.Expose;
+import com.google.gson.annotations.SerializedName;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import okhttp3.MediaType;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.RequestBody;
+import okhttp3.Response;
+
+/**
+ * 退款申请
+ */
+public class Create {
+  private static String HOST = "https://api.mch.weixin.qq.com";
+  private static String METHOD = "POST";
+  private static String PATH = "/v3/refund/domestic/refunds";
+
+
+  public Refund run(CreateRequest 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, Refund.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 Create(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 enum Status {
+    @SerializedName("SUCCESS")
+    SUCCESS,
+    @SerializedName("CLOSED")
+    CLOSED,
+    @SerializedName("PROCESSING")
+    PROCESSING,
+    @SerializedName("ABNORMAL")
+    ABNORMAL
+  }
+
+  public enum Account {
+    @SerializedName("AVAILABLE")
+    AVAILABLE,
+    @SerializedName("UNAVAILABLE")
+    UNAVAILABLE
+  }
+
+  public enum PromotionType {
+    @SerializedName("COUPON")
+    COUPON,
+    @SerializedName("DISCOUNT")
+    DISCOUNT
+  }
+
+  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("unit_price")
+    public Long unitPrice;
+
+    @SerializedName("refund_amount")
+    public Long refundAmount;
+
+    @SerializedName("refund_quantity")
+    public Integer refundQuantity;
+  }
+
+  public static class CreateRequest {
+    @SerializedName("sub_mchid")
+    public String subMchid;
+
+    @SerializedName("transaction_id")
+    public String transactionId;
+
+    @SerializedName("out_trade_no")
+    public String outTradeNo;
+
+    @SerializedName("out_refund_no")
+    public String outRefundNo;
+
+    @SerializedName("reason")
+    public String reason;
+
+    @SerializedName("notify_url")
+    public String notifyUrl;
+
+    @SerializedName("funds_account")
+    public ReqFundsAccount fundsAccount;
+
+    @SerializedName("amount")
+    public AmountReq amount;
+
+    @SerializedName("goods_detail")
+    public List<GoodsDetail> goodsDetail;
+  }
+
+  public enum Channel {
+    @SerializedName("ORIGINAL")
+    ORIGINAL,
+    @SerializedName("BALANCE")
+    BALANCE,
+    @SerializedName("OTHER_BALANCE")
+    OTHER_BALANCE,
+    @SerializedName("OTHER_BANKCARD")
+    OTHER_BANKCARD
+  }
+
+  public static class Amount {
+    @SerializedName("total")
+    public Long total;
+
+    @SerializedName("refund")
+    public Long refund;
+
+    @SerializedName("from")
+    public List<FundsFromItem> from;
+
+    @SerializedName("payer_total")
+    public Long payerTotal;
+
+    @SerializedName("payer_refund")
+    public Long payerRefund;
+
+    @SerializedName("settlement_refund")
+    public Long settlementRefund;
+
+    @SerializedName("settlement_total")
+    public Long settlementTotal;
+
+    @SerializedName("discount_refund")
+    public Long discountRefund;
+
+    @SerializedName("currency")
+    public String currency;
+
+    @SerializedName("refund_fee")
+    public Long refundFee;
+  }
+
+  public enum ReqFundsAccount {
+    @SerializedName("AVAILABLE")
+    AVAILABLE,
+    @SerializedName("UNSETTLED")
+    UNSETTLED
+  }
+
+  public enum FundsAccount {
+    @SerializedName("UNSETTLED")
+    UNSETTLED,
+    @SerializedName("AVAILABLE")
+    AVAILABLE,
+    @SerializedName("UNAVAILABLE")
+    UNAVAILABLE,
+    @SerializedName("OPERATION")
+    OPERATION,
+    @SerializedName("BASIC")
+    BASIC,
+    @SerializedName("ECNY_BASIC")
+    ECNY_BASIC
+  }
+
+  public static class Promotion {
+    @SerializedName("promotion_id")
+    public String promotionId;
+
+    @SerializedName("scope")
+    public PromotionScope scope;
+
+    @SerializedName("type")
+    public PromotionType type;
+
+    @SerializedName("amount")
+    public Long amount;
+
+    @SerializedName("refund_amount")
+    public Long refundAmount;
+
+    @SerializedName("goods_detail")
+    public List<GoodsDetail> goodsDetail;
+  }
+
+  public static class Refund {
+    @SerializedName("refund_id")
+    public String refundId;
+
+    @SerializedName("out_refund_no")
+    public String outRefundNo;
+
+    @SerializedName("transaction_id")
+    public String transactionId;
+
+    @SerializedName("out_trade_no")
+    public String outTradeNo;
+
+    @SerializedName("channel")
+    public Channel channel;
+
+    @SerializedName("user_received_account")
+    public String userReceivedAccount;
+
+    @SerializedName("success_time")
+    public String successTime;
+
+    @SerializedName("create_time")
+    public String createTime;
+
+    @SerializedName("status")
+    public Status status;
+
+    @SerializedName("funds_account")
+    public FundsAccount fundsAccount;
+
+    @SerializedName("amount")
+    public Amount amount;
+
+    @SerializedName("promotion_detail")
+    public List<Promotion> promotionDetail;
+  }
+
+  public static class FundsFromItem {
+    @SerializedName("account")
+    public Account account;
+
+    @SerializedName("amount")
+    public Long amount;
+  }
+
+  public static class AmountReq {
+    @SerializedName("refund")
+    public Long refund;
+
+    @SerializedName("from")
+    public List<FundsFromItem> from;
+
+    @SerializedName("total")
+    public Long total;
+
+    @SerializedName("currency")
+    public String currency;
+  }
+
+  public enum PromotionScope {
+    @SerializedName("GLOBAL")
+    GLOBAL,
+    @SerializedName("SINGLE")
+    SINGLE
+  }
+}
\ No newline at end of file

--
Gitblit v1.7.1