云联一号 3 週間 前
コミット
033b708ebe
30 ファイル変更1504 行追加37 行削除
  1. 164 8
      fs-admin/src/main/java/com/fs/his/task/Task.java
  2. 208 0
      fs-admin/src/main/java/com/fs/his/task/test.java
  3. 7 0
      fs-service/src/main/java/com/fs/his/mapper/FsStoreOrderMapper.java
  4. 3 0
      fs-service/src/main/java/com/fs/his/service/IFsStorePaymentService.java
  5. 28 3
      fs-service/src/main/java/com/fs/his/service/impl/FsStoreOrderServiceImpl.java
  6. 9 0
      fs-service/src/main/java/com/fs/his/service/impl/FsStorePaymentServiceImpl.java
  7. 4 0
      fs-service/src/main/java/com/fs/hisStore/mapper/FsStorePaymentScrmMapper.java
  8. 3 0
      fs-service/src/main/java/com/fs/hisStore/service/IFsStorePaymentScrmService.java
  9. 5 0
      fs-service/src/main/java/com/fs/hisStore/service/impl/FsStorePaymentScrmServiceImpl.java
  10. 0 13
      fs-service/src/main/java/com/fs/huifuPay/service/impl/HuiFuServiceImpl.java
  11. 10 10
      fs-service/src/main/java/com/fs/huifuPay/service/test.java
  12. 97 0
      fs-service/src/main/java/com/fs/wx/domain/FsWxExpressTask.java
  13. 21 0
      fs-service/src/main/java/com/fs/wx/dto/Contact.java
  14. 27 0
      fs-service/src/main/java/com/fs/wx/dto/OrderKey.java
  15. 77 0
      fs-service/src/main/java/com/fs/wx/dto/OrderQueryRequest.java
  16. 236 0
      fs-service/src/main/java/com/fs/wx/dto/OrderQueryResponse.java
  17. 17 0
      fs-service/src/main/java/com/fs/wx/dto/Payer.java
  18. 26 0
      fs-service/src/main/java/com/fs/wx/dto/ShippingItem.java
  19. 38 0
      fs-service/src/main/java/com/fs/wx/dto/UploadShippingInfoRequest.java
  20. 21 0
      fs-service/src/main/java/com/fs/wx/dto/WeChatApiConfig.java
  21. 20 0
      fs-service/src/main/java/com/fs/wx/dto/WeChatApiResponse.java
  22. 116 0
      fs-service/src/main/java/com/fs/wx/mapper/FsWxExpressTaskMapper.java
  23. 20 0
      fs-service/src/main/java/com/fs/wx/service/OrderQueryService.java
  24. 130 0
      fs-service/src/main/java/com/fs/wx/service/ShippingService.java
  25. 22 0
      fs-service/src/main/java/com/fs/wx/service/WeChatAuthService.java
  26. 118 0
      fs-service/src/main/java/com/fs/wx/service/impl/InMemoryWeChatAuthServiceImpl.java
  27. 71 0
      fs-service/src/main/java/com/fs/wx/service/impl/OrderQueryServiceImpl.java
  28. 1 1
      fs-service/src/main/resources/application-common.yml
  29. 2 2
      fs-service/src/main/resources/application-config-druid-syysy.yml
  30. 3 0
      fs-service/src/main/resources/application.properties

+ 164 - 8
fs-admin/src/main/java/com/fs/his/task/Task.java

@@ -1,8 +1,12 @@
 package com.fs.his.task;
 
 import cn.hutool.core.date.DateTime;
+import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.baidu.dev2.api.sdk.payment.api.PaymentService;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.fs.common.core.redis.RedisCache;
 import com.fs.common.service.impl.SmsServiceImpl;
 import com.fs.common.utils.DateUtils;
@@ -20,13 +24,9 @@ import com.fs.course.mapper.FsCourseRedPacketLogMapper;
 import com.fs.course.service.IFsCourseWatchLogService;
 import com.fs.course.service.ITencentCloudCosService;
 import com.fs.erp.domain.ErpDeliverys;
-import com.fs.erp.domain.ErpOrder;
 import com.fs.erp.domain.ErpOrderQuery;
-import com.fs.erp.domain.FsErpFinishPush;
 import com.fs.erp.dto.ErpOrderQueryRequert;
 import com.fs.erp.dto.ErpOrderQueryResponse;
-import com.fs.erp.dto.ErpOrderResponse;
-import com.fs.erp.mapper.FsErpFinishPushMapper;
 import com.fs.erp.service.IErpOrderService;
 import com.fs.fastGpt.domain.FastGptEventTokenLog;
 import com.fs.fastGpt.domain.FastgptEventLogTotal;
@@ -34,10 +34,7 @@ import com.fs.fastGpt.mapper.FastGptChatSessionMapper;
 import com.fs.fastGpt.service.IFastgptEventLogTotalService;
 import com.fs.his.config.FsSysConfig;
 import com.fs.his.config.StoreConfig;
-import com.fs.his.domain.FsInquiryOrder;
-import com.fs.his.domain.FsStoreAfterSales;
-import com.fs.his.domain.FsStoreOrder;
-import com.fs.his.domain.FsUser;
+import com.fs.his.domain.*;
 import com.fs.his.dto.FsInquiryOrderPatientDTO;
 import com.fs.his.enums.FsStoreOrderLogEnum;
 import com.fs.his.enums.FsStoreOrderStatusEnum;
@@ -48,6 +45,8 @@ import com.fs.his.service.impl.FsPackageOrderServiceImpl;
 import com.fs.his.utils.ConfigUtil;
 import com.fs.his.vo.FsSubOrderResultVO;
 import com.fs.hisStore.domain.FsStoreOrderScrm;
+import com.fs.hisStore.domain.FsStorePaymentScrm;
+import com.fs.hisStore.service.IFsStorePaymentScrmService;
 import com.fs.im.dto.*;
 import com.fs.im.service.IImService;
 import com.fs.im.service.OpenIMService;
@@ -56,6 +55,10 @@ import com.fs.qw.service.*;
 import com.fs.qwApi.service.QwApiService;
 import com.fs.system.domain.SysConfig;
 import com.fs.system.mapper.SysConfigMapper;
+import com.fs.wx.domain.FsWxExpressTask;
+import com.fs.wx.dto.*;
+import com.fs.wx.mapper.FsWxExpressTaskMapper;
+import com.fs.wx.service.ShippingService;
 import com.google.gson.Gson;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
@@ -65,6 +68,9 @@ import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Component;
 
+import java.time.LocalDateTime;
+import java.time.OffsetDateTime;
+import java.time.format.DateTimeFormatter;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -173,6 +179,122 @@ public class Task {
     @Autowired
     private IFastgptEventLogTotalService fastgptEventLogTotalService;
 
+    @Autowired
+    private FsWxExpressTaskMapper fsWxExpressTaskMapper;
+
+    @Autowired
+    private IFsStorePaymentService paymentScrmService;
+    @Autowired
+    ShippingService shippingService;
+    public void syncExpressToWx() {
+        List<FsWxExpressTask> fsWxExpressTasks = fsWxExpressTaskMapper.selectPendingData();
+        if (CollectionUtils.isEmpty(fsWxExpressTasks)) {
+            logger.info("当前没有待同步的数据!已取消");
+            return;
+        }
+
+        for (FsWxExpressTask fsWxExpressTask : fsWxExpressTasks) {
+
+            try{
+                UploadShippingInfoRequest request = new UploadShippingInfoRequest();
+
+                OrderKey orderKey = new OrderKey();
+                orderKey.setOrderNumberType(2);
+
+
+                FsUser fsUser = fsUserMapper.selectFsUserById(fsWxExpressTask.getUserId());
+                FsStoreOrderScrm fsStoreOrder = fsStoreOrderMapper.selectFsStoreOrderByOrderCodeScrm(fsWxExpressTask.getOrderCode());
+
+
+                if(ObjectUtil.isNotNull(fsStoreOrder)){
+                    List<FsStorePaymentScrm> fsStorePayments = paymentScrmService.selectFsStorePaymentByOrderScrm(fsStoreOrder.getId());
+
+
+                    if(CollectionUtils.isNotEmpty(fsStorePayments)){
+                        FsStorePaymentScrm fsStorePayment = fsStorePayments.get(0);
+                        orderKey.setTransactionId(fsStorePayment.getBankTransactionId());
+                    }
+                }
+
+                String userPhone = "";
+                String orderGoodsInfo = "商品";
+                if(fsStoreOrder != null){
+                    userPhone = fsStoreOrder.getUserPhone();
+                    orderGoodsInfo = getOrderGoodsInfo(fsStoreOrder);
+                }
+
+                Payer payer = new Payer();
+                if(StringUtils.isNotBlank(fsUser.getMaOpenId())){
+                    payer.setOpenid(fsUser.getMaOpenId());
+                }
+                request.setPayer(payer);
+                request.setOrderKey(orderKey);
+
+                request.setLogisticsType(1);
+                request.setDeliveryMode(1);
+
+                request.setShippingList(Collections.singletonList(ShippingItem.builder()
+                        .itemDesc(orderGoodsInfo)
+                        .expressCompany(fsWxExpressTask.getExpressCompany())
+                        .trackingNo(fsWxExpressTask.getExpressNo())
+                        .contact(Contact.builder().consignorContact(userPhone).build())
+                        .build()));
+
+                OffsetDateTime now = OffsetDateTime.now();
+                DateTimeFormatter formatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
+                String formattedTimestamp = now.format(formatter);
+                request.setUploadTime(formattedTimestamp);
+
+
+                WeChatApiResponse response = shippingService.uploadShippingInfo(request);
+                if(ObjectUtil.equal(response.getErrcode(),0)){
+                    fsWxExpressTask.setStatus(2);
+                } else {
+                    fsWxExpressTask.setRetryCount(fsWxExpressTask.getRetryCount() +1);
+                    fsWxExpressTask.setStatus(3);
+                    fsWxExpressTask.setData(JSON.toJSONString(request));
+                    fsWxExpressTask.setRequestBody(JSON.toJSONString(request));
+                    fsWxExpressTask.setResponseBody(JSON.toJSONString(response));
+                }
+            }catch (Exception e){
+                logger.info("该单 {} 推送到物流失败!",fsWxExpressTask);
+                fsWxExpressTask.setRetryCount(fsWxExpressTask.getRetryCount() +1);
+                fsWxExpressTask.setStatus(3);
+
+
+            }
+        }
+        for (FsWxExpressTask fsWxExpressTask : fsWxExpressTasks) {
+            fsWxExpressTaskMapper.updateById(fsWxExpressTask);
+        }
+//        fsWxExpressTaskMapper.batchUpdate(fsWxExpressTasks);
+
+    }
+
+    /**
+     * 获取订单商品信息
+     * @return
+     */
+    private String getOrderGoodsInfo(FsStoreOrderScrm order){
+        StringBuilder title = new StringBuilder();
+        // 如果是套餐
+        if(ObjectUtil.equal(order.getIsPackage(),1)){
+            String packageJson = order.getPackageJson();
+            JSONObject jsonObject = JSON.parseObject(packageJson);
+            title = new StringBuilder(jsonObject.getString("title"));
+        } else {
+            String itemJson = order.getItemJson();
+            com.alibaba.fastjson.JSONArray arrays = JSON.parseArray(itemJson);
+            for(int i=0;i<arrays.size();i++){
+                JSONObject jsonObject = arrays.getJSONObject(i);
+                String jsonInfo = jsonObject.getString("jsonInfo");
+                JSONObject jsonObject1 = JSON.parseObject(jsonInfo);
+                String productName = jsonObject1.getString("productName");
+                title.append(productName).append("\n");
+            }
+        }
+        return title.toString();
+    }
     //统计ai事件埋点
     public void eventLogTotals() {
         // 判断是否是凌晨 00:00 - 00:59
@@ -566,7 +688,11 @@ public class Task {
 
                 } catch (Exception e) {
                     logger.error("调用ERP接口异常:",e);
+                    try {
+                        Thread.sleep(1000); // 1000毫秒 = 1秒
+                    } catch (Exception ex) {
 
+                    }
                     continue;
                     //throw new RuntimeException(e);
                 }
@@ -589,6 +715,36 @@ public class Task {
             }
         }
     }
+    @Autowired
+    IFsStorePaymentScrmService fsStorePaymentScrmService;
+    public void test()
+    {
+        List<FsStoreOrderScrm> orders = fsStoreOrderMapper.selectOrdersBy2();
+        for (FsStoreOrderScrm order : orders) {
+            try{
+                FsWxExpressTask fsWxExpressTask = new FsWxExpressTask();
+                fsWxExpressTask.setUserId(order.getUserId());
+                fsWxExpressTask.setStatus(0);
+                fsWxExpressTask.setRetryCount(0);
+                fsWxExpressTask.setCreateTime(LocalDateTime.now());
+                fsWxExpressTask.setUpdateTime(LocalDateTime.now());
+                fsWxExpressTask.setOrderCode(order.getOrderCode());
+                fsWxExpressTask.setExpressCompany("SF");
+                fsWxExpressTask.setExpressNo(order.getDeliveryId());
+                List<FsStorePaymentScrm> fsStorePayments = fsStorePaymentScrmService.selectFsStorePaymentByOrderIdNew(order.getId());
+                if(fsStorePayments!=null&&!fsStorePayments.isEmpty()){
+                    FsStorePaymentScrm  fsStorePayment = fsStorePayments.get(0);
+                    fsWxExpressTask.setPayCode(fsStorePayment.getPayCode());
+                }
+                fsWxExpressTaskMapper.insert(fsWxExpressTask);
+            }catch (Exception e){
+                logger.info("添加expressTask失败:"+order.getOrderCode());
+            }
+        }
+
+    }
+
+
     public void getOrderDeliveryStatus()
     {
         IErpOrderService erpOrderService = getErpService();

+ 208 - 0
fs-admin/src/main/java/com/fs/his/task/test.java

@@ -0,0 +1,208 @@
+package com.fs.his.task;
+
+import com.baidu.dev2.thirdparty.http.client.config.RequestConfig;
+import com.baidu.dev2.thirdparty.http.client.methods.CloseableHttpResponse;
+import com.baidu.dev2.thirdparty.http.client.methods.HttpPost;
+import com.baidu.dev2.thirdparty.http.entity.StringEntity;
+import com.baidu.dev2.thirdparty.http.impl.client.CloseableHttpClient;
+import com.baidu.dev2.thirdparty.http.impl.client.HttpClients;
+import com.baidu.dev2.thirdparty.http.util.EntityUtils;
+
+import java.util.concurrent.ExecutorService;
+
+public class test {
+    public static void main(String[] args) {
+        String serverIps =
+
+        "36.139.196.24\n" +
+
+                "36.133.123.121\n" +
+        "36.138.74.128\n" +
+        "36.138.189.121\n" +
+                "36.133.111.16\n" +
+                "36.134.89.160\n" +
+                "36.137.112.221\n" +
+                "36.137.78.8\n" +
+                "36.133.234.196\n" +
+                "36.138.235.99\n" +
+                "36.139.194.82\n" +
+                "36.212.75.53\n" +
+                        "36.138.78.48\n"    +
+                        "36.140.149.45\n"    +
+                        "36.137.210.86\n"    +
+
+
+                "36.137.210.86\n" +
+                "36.134.190.202\n" +
+                "36.213.76.167\n" +
+                "36.213.32.117\n" +
+                "36.133.254.163\n" +
+                "36.212.143.138\n" +
+                "36.137.133.18\n" +
+//                "36.137.245.74\n" +
+                "36.212.197.10\n" +
+                "36.139.126.96\n" +
+                "36.133.202.18\n" +
+//                "36.212.229.176\n" +
+                "36.134.194.196\n" +
+                "36.134.229.127\n" +
+                "36.134.229.234\n" +
+                "36.134.93.148\n" +
+                "36.134.229.238\n" +
+                "36.137.129.254\n" +
+                "36.139.196.24\n" +
+                "36.134.29.183\n" +
+                "36.137.79.19\n" +
+                "36.133.115.33\n" +
+                "36.138.185.103\n" +
+                "36.134.194.92\n" +
+                "36.138.183.50\n" +
+                "36.137.134.5\n" +
+                "36.137.141.84\n" +
+                "36.134.71.77\n" +
+                "36.137.154.144\n" +
+                "36.134.27.99\n" +
+                "36.139.140.228\n" +
+                "36.133.97.149\n" +
+                "36.138.229.144\n" +
+                "36.138.74.26\n" +
+                "36.133.128.234\n" +
+                "36.138.74.128\n" +
+                "36.137.78.243\n" +
+                "36.137.79.31\n" +
+                "36.134.89.4\n" +
+                "36.137.79.188" +
+                "36.134.93.6\n" +
+                "36.134.229.127\n" +
+                "36.134.229.234\n" +
+                "36.134.93.148\n" +
+                "36.134.229.238";
+        String[] ips = serverIps.split("\n");
+while (true){
+    for (String ip : ips) {
+        ip = ip.trim();
+        if (ip.isEmpty()) continue;
+
+        System.out.println("调用: " + ip);
+        callSingleServer(ip);
+    }
+}
+
+    }
+
+    private static void callSingleServer(String ip) {
+        long startTime = System.currentTimeMillis();
+        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
+            String url = "http://" + ip + ":8083/wxwork/initConfig";
+            HttpPost request = new HttpPost(url);
+
+            // 设置超时配置(连接超时5秒,读取超时10秒)
+            RequestConfig requestConfig = RequestConfig.custom()
+                    .setConnectTimeout(5000)
+                    .setSocketTimeout(10000)
+                    .setConnectionRequestTimeout(3000)
+                    .build();
+            request.setConfig(requestConfig);
+
+            // 设置POST请求体
+            String jsonBody = "{}";
+            StringEntity entity = new StringEntity(jsonBody, "UTF-8");
+            entity.setContentType("application/json");
+            request.setEntity(entity);
+
+            try (CloseableHttpResponse response = httpClient.execute(request)) {
+                long responseTime = System.currentTimeMillis() - startTime;
+                int statusCode = response.getStatusLine().getStatusCode();
+                String responseBody = EntityUtils.toString(response.getEntity());
+
+                boolean success = statusCode >= 200 && statusCode < 300;
+                String message = responseBody.length() > 50 ? responseBody.substring(0, 50) + "..." : responseBody;
+
+                System.out.println(success ? "✅ 成功" : "❌ 失败");
+                System.out.println("状态码: " + statusCode + ", 响应时间: " + responseTime + "ms");
+                System.out.println("响应: " + message);
+            }
+
+        } catch (Exception e) {
+            long responseTime = System.currentTimeMillis() - startTime;
+            System.out.println("❌ 失败");
+            System.out.println("错误: " + e.getMessage() + ", 响应时间: " + responseTime + "ms");
+        }
+
+        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
+            String url = "http://" + ip + ":8084/wxwork/initConfig";
+            HttpPost request = new HttpPost(url);
+
+            // 设置超时配置(连接超时5秒,读取超时10秒)
+            RequestConfig requestConfig = RequestConfig.custom()
+                    .setConnectTimeout(5000)
+                    .setSocketTimeout(10000)
+                    .setConnectionRequestTimeout(3000)
+                    .build();
+            request.setConfig(requestConfig);
+
+            // 设置POST请求体
+            String jsonBody = "{}";
+            StringEntity entity = new StringEntity(jsonBody, "UTF-8");
+            entity.setContentType("application/json");
+            request.setEntity(entity);
+
+            try (CloseableHttpResponse response = httpClient.execute(request)) {
+                long responseTime = System.currentTimeMillis() - startTime;
+                int statusCode = response.getStatusLine().getStatusCode();
+                String responseBody = EntityUtils.toString(response.getEntity());
+
+                boolean success = statusCode >= 200 && statusCode < 300;
+                String message = responseBody.length() > 50 ? responseBody.substring(0, 50) + "..." : responseBody;
+
+                System.out.println(success ? "✅ 成功" : "❌ 失败");
+                System.out.println("状态码: " + statusCode + ", 响应时间: " + responseTime + "ms");
+                System.out.println("响应: " + message);
+            }
+
+        } catch (Exception e) {
+            long responseTime = System.currentTimeMillis() - startTime;
+            System.out.println("❌ 失败");
+            System.out.println("错误: " + e.getMessage() + ", 响应时间: " + responseTime + "ms");
+        }
+
+        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
+            String url = "http://" + ip + ":8085/wxwork/initConfig";
+            HttpPost request = new HttpPost(url);
+
+            // 设置超时配置(连接超时5秒,读取超时10秒)
+            RequestConfig requestConfig = RequestConfig.custom()
+                    .setConnectTimeout(5000)
+                    .setSocketTimeout(10000)
+                    .setConnectionRequestTimeout(3000)
+                    .build();
+            request.setConfig(requestConfig);
+
+            // 设置POST请求体
+            String jsonBody = "{}";
+            StringEntity entity = new StringEntity(jsonBody, "UTF-8");
+            entity.setContentType("application/json");
+            request.setEntity(entity);
+
+            try (CloseableHttpResponse response = httpClient.execute(request)) {
+                long responseTime = System.currentTimeMillis() - startTime;
+                int statusCode = response.getStatusLine().getStatusCode();
+                String responseBody = EntityUtils.toString(response.getEntity());
+
+                boolean success = statusCode >= 200 && statusCode < 300;
+                String message = responseBody.length() > 50 ? responseBody.substring(0, 50) + "..." : responseBody;
+
+                System.out.println(success ? "✅ 成功" : "❌ 失败");
+                System.out.println("状态码: " + statusCode + ", 响应时间: " + responseTime + "ms");
+                System.out.println("响应: " + message);
+            }
+
+        } catch (Exception e) {
+            long responseTime = System.currentTimeMillis() - startTime;
+            System.out.println("❌ 失败");
+            System.out.println("错误: " + e.getMessage() + ", 响应时间: " + responseTime + "ms");
+        }
+
+        System.out.println("-------------------");
+    }
+}

+ 7 - 0
fs-service/src/main/java/com/fs/his/mapper/FsStoreOrderMapper.java

@@ -355,6 +355,9 @@ public interface FsStoreOrderMapper
     @Select("SELECT * FROM fs_store_order WHERE order_code =#{orderCode}")
     FsStoreOrder selectFsStoreOrderByOrderCode(String orderCode);
 
+    @Select("SELECT * FROM fs_store_order_scrm WHERE order_code =#{orderCode}")
+    FsStoreOrderScrm selectFsStoreOrderByOrderCodeScrm(String orderCode);
+
     @Select("SELECT * FROM fs_store_order_scrm WHERE order_code =#{orderCode}")
     FsStoreOrderScrm selectFsStoreOrderScrmByOrderCode(String orderCode);
 
@@ -1181,4 +1184,8 @@ public interface FsStoreOrderMapper
 
 
     List<Report> selectOrderByCustomerIds(@Param("map") ReportParam param);
+
+    @Select("select * from fs_store_order_scrm where status=2")
+    List<FsStoreOrderScrm> selectOrdersBy2();
+
 }

+ 3 - 0
fs-service/src/main/java/com/fs/his/service/IFsStorePaymentService.java

@@ -13,6 +13,7 @@ import com.fs.his.param.PayOrderParam;
 import com.fs.his.param.WxSendRedPacketParam;
 import com.fs.his.vo.FsStorePaymentExcelVO;
 import com.fs.his.vo.FsStorePaymentVO;
+import com.fs.hisStore.domain.FsStorePaymentScrm;
 import com.fs.hisStore.param.FsStorePaymentGetWxaCodeParam;
 import com.fs.hisStore.param.FsStorePaymentPayParam;
 import me.chanjar.weixin.common.error.WxErrorException;
@@ -120,4 +121,6 @@ public interface IFsStorePaymentService
     R paymentByWxaCode(FsStorePaymentPayParam payment);
 
     R getWxaCodeByPayment(FsStorePaymentGetWxaCodeParam param);
+
+    List<FsStorePaymentScrm> selectFsStorePaymentByOrderScrm(Long id);
 }

+ 28 - 3
fs-service/src/main/java/com/fs/his/service/impl/FsStoreOrderServiceImpl.java

@@ -51,6 +51,7 @@ import com.fs.hisStore.mapper.FsStoreOrderScrmMapper;
 import com.fs.hisStore.mapper.FsStorePaymentScrmMapper;
 import com.fs.hisStore.service.IFsStoreOrderLogsScrmService;
 import com.fs.hisStore.service.IFsStoreOrderScrmService;
+import com.fs.hisStore.service.IFsStorePaymentScrmService;
 import com.fs.hisapi.domain.ApiResponse;
 import com.fs.hisapi.param.CreateOrderParam;
 import com.fs.hisapi.param.RecipeDetailParam;
@@ -66,6 +67,8 @@ import com.fs.qw.mapper.QwExternalContactMapper;
 import com.fs.qw.service.impl.QwUserServiceImpl;
 import com.fs.system.domain.SysConfig;
 import com.fs.tzBankPay.doman.*;
+import com.fs.wx.domain.FsWxExpressTask;
+import com.fs.wx.mapper.FsWxExpressTaskMapper;
 import com.fs.ybPay.domain.CreateWxOrderResult;
 import com.fs.ybPay.domain.OrderResult;
 import com.fs.ybPay.dto.OrderQueryDTO;
@@ -111,6 +114,7 @@ import java.nio.charset.Charset;
 import java.sql.Timestamp;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
+import java.time.LocalDateTime;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -1598,7 +1602,10 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService {
     }
     @Autowired
     FsStoreOrderScrmMapper storeOrderScrmMapper;
-
+    @Autowired
+    IFsStorePaymentScrmService fsStorePaymentScrmService;
+    @Autowired
+    FsWxExpressTaskMapper fsWxExpressTaskMapper;
 
     @Autowired
     IFsStoreOrderLogsScrmService iFsStoreOrderLogsScrmService;
@@ -1643,7 +1650,25 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService {
                 }
             }
             expressService.subscribeEspress(order.getOrderCode(), order.getDeliverySn(), deliveryId, lastFourNumber);
-
+            try{
+                FsWxExpressTask fsWxExpressTask = new FsWxExpressTask();
+                fsWxExpressTask.setUserId(order.getUserId());
+                fsWxExpressTask.setStatus(0);
+                fsWxExpressTask.setRetryCount(0);
+                fsWxExpressTask.setCreateTime(LocalDateTime.now());
+                fsWxExpressTask.setUpdateTime(LocalDateTime.now());
+                fsWxExpressTask.setOrderCode(order.getOrderCode());
+                fsWxExpressTask.setExpressCompany(express.getCode());
+                fsWxExpressTask.setExpressNo(deliveryId);
+                List<FsStorePaymentScrm> fsStorePayments = fsStorePaymentScrmService.selectFsStorePaymentByOrderIdNew(order.getId());
+                if(fsStorePayments!=null&&!fsStorePayments.isEmpty()){
+                    FsStorePaymentScrm  fsStorePayment = fsStorePayments.get(0);
+                    fsWxExpressTask.setPayCode(fsStorePayment.getPayCode());
+                }
+                fsWxExpressTaskMapper.insert(fsWxExpressTask);
+            }catch (Exception e){
+                logger.info("添加expressTask失败:"+order.getOrderCode());
+            }
 
         }
 
@@ -2338,7 +2363,7 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService {
                     for (FsStoreOrderScrm order : orders2) {
                         logger.info("订单信息:" + JSONUtil.toJsonStr(order));
                         logger.info("运单号:" + dto.getLogisticCode());
-                        if (order != null && order.getDeliveryStatus() != 3) {
+                        if (order != null && (order.getDeliveryStatus()==null|| order.getDeliveryStatus()!= 3)) {
                             FsStoreOrderScrm map = new FsStoreOrderScrm();
                             map.setDeliveryStatus(Integer.parseInt(dto.getState()));
                             map.setId(order.getId());

+ 9 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsStorePaymentServiceImpl.java

@@ -61,6 +61,8 @@ import com.fs.his.service.IFsStorePaymentService;
 import com.fs.his.utils.PhoneUtil;
 import com.fs.his.vo.FsStorePaymentExcelVO;
 import com.fs.his.vo.FsStorePaymentVO;
+import com.fs.hisStore.domain.FsStorePaymentScrm;
+import com.fs.hisStore.mapper.FsStorePaymentScrmMapper;
 import com.fs.hisStore.param.FsStorePaymentGetWxaCodeParam;
 import com.fs.hisStore.param.FsStorePaymentPayParam;
 import com.fs.huifuPay.domain.HuiFuCreateOrder;
@@ -133,6 +135,9 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
     Logger logger = LoggerFactory.getLogger(getClass());
     @Autowired
     private FsStorePaymentMapper fsStorePaymentMapper;
+    @Autowired
+    private FsStorePaymentScrmMapper fsStorePaymentScrmMapper;
+
     @Autowired
     private TzBankService tzBankService;
     @Autowired
@@ -1226,6 +1231,10 @@ public class FsStorePaymentServiceImpl implements IFsStorePaymentService {
         }
     }
 
+    @Override
+    public List<FsStorePaymentScrm> selectFsStorePaymentByOrderScrm(Long id) {
+        return fsStorePaymentScrmMapper.selectFsStorePaymentByOrderScrm(id);
+    }
 
 
     @Override

+ 4 - 0
fs-service/src/main/java/com/fs/hisStore/mapper/FsStorePaymentScrmMapper.java

@@ -352,4 +352,8 @@ public interface FsStorePaymentScrmMapper
 
     @Select("select * from fs_store_payment_scrm where pay_code=#{payCode}")
     FsStorePaymentScrm selectFsStorePaymentByPaymentCode(String payCode);
+    @Select("select * from fs_store_payment_scrm where business_type=2 and order_id=#{orderId} ")
+    List<FsStorePaymentScrm> selectFsStorePaymentByOrderScrm(Long orderId);
+    @Select("select * from fs_store_payment_scrm where business_type=2 and order_id=#{orderId} limit 1")
+    List<FsStorePaymentScrm> selectFsStorePaymentByOrderIdNew();
 }

+ 3 - 0
fs-service/src/main/java/com/fs/hisStore/service/IFsStorePaymentScrmService.java

@@ -5,6 +5,7 @@ import java.util.Map;
 
 import com.alibaba.fastjson.JSONObject;
 import com.fs.common.core.domain.R;
+import com.fs.his.domain.FsStorePayment;
 import com.fs.hisStore.domain.FsStorePaymentScrm;
 import com.fs.hisStore.param.*;
 import com.fs.hisStore.vo.FsStorePaymentStatisticsVO;
@@ -116,4 +117,6 @@ public interface IFsStorePaymentScrmService
     R getWxaCodeByPayment(FsStorePaymentGetWxaCodeParam param);
 
     R paymentByWxaCode(FsStorePaymentPayParam param);
+
+    List<FsStorePaymentScrm> selectFsStorePaymentByOrderIdNew(Long id);
 }

+ 5 - 0
fs-service/src/main/java/com/fs/hisStore/service/impl/FsStorePaymentScrmServiceImpl.java

@@ -896,4 +896,9 @@ public class FsStorePaymentScrmServiceImpl implements IFsStorePaymentScrmService
             return R.error(result.getResp_desc());
         }
     }
+
+    @Override
+    public List<FsStorePaymentScrm> selectFsStorePaymentByOrderIdNew(Long id) {
+        return fsStorePaymentMapper.selectFsStorePaymentByOrderIdNew();
+    }
 }

+ 0 - 13
fs-service/src/main/java/com/fs/huifuPay/service/impl/HuiFuServiceImpl.java

@@ -275,7 +275,6 @@ public class HuiFuServiceImpl implements HuiFuService {
         SysConfigMapper sysConfigMapper= SpringUtils.getBean(SysConfigMapper.class);
         SysConfig sysConfig = sysConfigMapper.selectConfigByConfigKey("his.pay");
         FsPayConfig fsPayConfig = new Gson().fromJson(sysConfig.getConfigValue(), FsPayConfig.class);
-
 //        FsPayConfig fsPayConfig = new FsPayConfig();
 //        fsPayConfig.setAppId("wxc3f0a952b7bc2b94");
 //        fsPayConfig.setHfProductId("KAZX");
@@ -286,18 +285,6 @@ public class HuiFuServiceImpl implements HuiFuService {
 //        fsPayConfig.setHfRsaPrivateKey("MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCijLcYLMJEe16TS6BtEG9hUezZyYvp2qgpPVGWaaBbb6lud89ILMUC7jyTWufCo2fUQ0nJzYhVlNeMzmGFtg/zFwhkjJIkuCOW+/Koy1ow66Rom8/sNQLb82szHoeklbv17AnD7WJis7cGyy1+3E6jzfaPOB7PTzidK6KyfCWDByOt0JcGe3+6+9+loQFbFRXJ2RpWPQeN72n9FVtSKSvgkGtJNUzh/qBwMPN6ol6xcU/Z2o1sYrRfKC4tcMqccRi/DvvZFJPVlN+YqkJ6lhgAmJg7eZ2fhIgrmzqc96UKp2YUNm+1v8XHCflD9Wv94E6D2JgL4VbF4Zyf+fKYuR7pAgMBAAECggEAfy5UL6ENmuFgHSVF7y+1xdKA2+IbC60ed63XgTVB12jli15Im3MT7ngSg0TUIvERUv4W5MNgkX10rWHo4eKSViPGWE24JuzAQ+j7cuAwwCgPKh4HMAxGIWwyivuvK7JQL1kwRtEccpekc7dS8HhVO0rySBqj2JZmeGrk0HvcKciSWuMjhjT4dJUwSntD07REV6rVjrpQXuvmY40vH88uvHLdH1IcjmJs2yJRNawUNtd+8FvpOCjami7zpB+er+AQ6S2fvpljNqfE5Kadm3MvzBngDdMS3xRvMHfjCifVwFpLP0rLDP6cSn6PJWbkNYQVZi12w8+wb5f7AVlaKXnfdQKBgQDh7VC5+MOqfcUr9h/n2vhFFhQOaGAZCOBc65n8VBj9aRht8ViXFvRrIRmM+QvUbV9/7taFbtAnZXIzu+12T4vnlZv9DTsy6kKloV5923xZ4CpzIVG8crlwJz1wdALeO6M485RtRLjz6nlNKn2m2VJ1d5XFBDhIz5rWUzagPwwpwwKBgQC4L8Eyu6Yn/zQmv8l6rfAsEfUJzfYtojf1PerPYilARtgFuD20cppcOP5oAk2TTX3qaz0Y9atCfL2z2qxtrgKtw2etfhDBmT6l6+pg04SLuyTrVeZ5dxXHt+LRLJnvBbGgnvAM6rSRKdHXT0gfqiRIMw2qIUtndgRr4RK5hqcd4wKBgBYBFh620t/VFhIdC6h6VDnuV4+7rLhje+6w57OCwVhVFxMGMZmtm6qfc6yeSP+sk2OTcINYcp+TqtbNE+i1AKxSjvnLgxuHY2xcViat7OOYCKpj8WEIT3VT7RD5y5m3d0NBvhASZG0lRiE05T4N5pEYT5b7vTuiNLNxMV3UJiwfAoGBAIb2/1QEqwmN+RIX4TSTNnWkpvELSkRAJU8Akwpp/J5MC0mNqzGJ9NB1Nv7SCTRSSV04PaoHgvoSXBPpvgYUx4O6t0MrKG4ktAJzL+jJtcuKU9Bavqrs9znE5mCulRHQE0wGixJ7/dqNUWW7g7coPrPlLTMoeI+UrEK8x7LJF7ZPAoGALHvtu6zzWVeCdELIPUTersVQrH1R3yZuf6rgubg4XFw3meFcd4W8BvXm4EKGRZxdiyZvCtKlkV9u110Rx3RNSbZCOb3MClmkcow8vPIhmyGWIGymAIxr9JcD0p6HogzPvbjRsLh1nFg/+95OL2E353Bp4/oPIgYIfnYNUfD+0gA=");
 //        fsPayConfig.setHfRsaPublicKey("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjbkiiy2ewzuPsM5uZbAFMJOBWCRRQ2RtH7Dbr9Evbow6IEyvGoen8XKpiuXzapeps3b2eogETHVFQtLooqRHpVRppFKtU1AHZXA7C6wPocfMldJbTykDCowyJwOSYEaFPBjr9cw6dQcBJMIEHj0YWjBPR1dPVzf+y4sUohbrkS/FANBpp24j+Mu0qEqh8TuVuKlvig7jbmXJiJkAmUJ+Tb3Caj20fFTen6juPd3zR/KM3twki06wZZbb4KyCiM/NwozEqJ9PkWSs6rG7aW+BEfzlo3m1a7MlL0vpKNR3f0lbywq09rFAwtA7R2lssWwLMma4LOqtMMqo3yZdv4vObQIDAQAB");
 //        fsPayConfig.setHfPayOnlineNotifyUrl("https://userapp.his.cdwjyyh.com//app/hfPay/payNotifyUrl");
-
-//        FsPayConfig fsPayConfig = new FsPayConfig();
-//        fsPayConfig.setAppId("wxb48fe0acfdc70a92");
-//        fsPayConfig.setHfProductId("KAZX");
-//        fsPayConfig.setHfSysId("6666000173104153");
-//        fsPayConfig.setHuifuId("6666000173104153");
-//        fsPayConfig.setHfRsaPrivateKey("MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCYzLmE2qBlRQbAosIjPxTZwRItgMgOTT99bRYxa3xQhiq2+YPj2R5lOKu5Y74Po43cg5UG8+7z7r4hV2q+sS3DwvnifHrkytXrnwDuW4ijagiMhr0Am9cEP6WqmuCyy8cMS+MtZ8eBCFefXjDsO4zXDk9/jxpywZ59i85q5Ka03S6lJOW+cq7RToEGJoxF1E98UtewbcPL2FxU5eQnte51RiGGly3drAQh+Tbdt8brjycnfR1SAhEFe/cFAOG6zC1XyJwkCfFynpvihA7SGSrTozBvIxg5ylGTx+HiRPDlYBABzWZkZgtvSGF0V7DQy5Tia/kuksOuePXb59MrUyIBAgMBAAECggEALWH44/2vUAS9aa+tq5xLzBUtGfi68ox9A/rHcaw0AxKmUywuwRi2j2fSkUCPrcNtGga215bR7P+G1w5ItRSYvCEH6P4B3jxkZxQVybXEEo0mtt45+plOtoNU6CQSAujFWOCdO9osBiX9KGdobnGNdj5Y3FEbkOPy9+TzTQpWfTcSWXi3qwsWz05jb04NpqV+xAPDIotAGvDIKJ99kH7/ewlyADvI7axj4JJaHnQOU/UcNHX8gtFgPTxf4e+UGLoPz3TRqFkVM9UIgejFilUUbIcwoCl1sLo3tjdoomYzEYxHPVrtk/8YRRUnzcvThSgydDhO+0GLa8qMCYk+XYrPAQKBgQDaTg+AQqRVQHH2KxYwUmfZXj+RfgBbR1L/v0j5NuxKSdxytBZA6K4I4fX8D/o2PXpkKiGaqyLnf5/wQsmj3fxIzXKyZWcU3lgHE7L18NWl6wPqpz5zJwgKstFcZqJ4HXZgSZw9/iNktIS5K6PZUgsGy+QJ0e4SFqKUED/zRoVKUQKBgQCzLxMsA2rl1n9q93PGOLE9bS0uahtpTePKVLn+ceQ/acDdokCf0MtM3uWJd5ti8BWTMECg4JVXIBUrYeLHwVlZMKvijGZRDYGJUF8hfjWU2pTDI6b2+vSQSVWLkyOdznvzUxrhKDbj21lQNPrKqL/nDfWKH/5QfScfjHviEQ7AsQKBgFXQTaObjsG8XY/pDAXevtfhhpeIslcvSF8kMGlWv7fMJQ4p4H2PeaogOPPmy/K6Y/wv25nTIBtkPdjSSDVUM7HioO2jksvPQ0c05Spsi293XMjHCXN2qmCaPlZWOhOBcWEUTojH993EYE/x6ayp5Y+8Yl3B2hXeM/aEFL9qv0ahAoGADaa7fjHwdfxGjt61aletYTGtLIkW94ngneygkvsYWaBz+i6/X62nn36n3DZJl1sVObaGZftWRWIDWt/FSFS5uurTXZo2vVwbD1wZM1MLQAD7LnbL5Ksv8MI1i0G1h/NQTDR7qsXGkMuIXWz74m7C2BafK1vOo1E1ptisI4gLKLECgYBdCCxkf/jCXcsQEs+hmYWm4gvHahvPIDVI5s2qX/hrJsFx6LaorC1iSmwwJQ7zM/AFqwc/NlCGo2NE44MKFPqIp/08fM4Tx2i8BFQQF3G1Y8oAr/xusqJVSI3CHvw2yD6DDgwTOeQ2TD1v3lnOEB6g0JaamTQQ6NQ0iUNRsDXAPQ==");
-//        fsPayConfig.setHfRsaPublicKey("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuziAvRIul3mwBlEDSMMvi3v83HEebLpEWoBhcqL/Vlg90tjT51lEO4OksGDU08ypESMaby+Rpvw9rRTFBbdm9oZiiKyKrYChoW9s/Tu5gDIt6k1+YP3204/lOz4Pat9hlRetIhDcgbAiChwDWS/+shfdi6vMX31fO5m5oyo1XlwL477pZYykwxalxgXjWHUkyDRvYGDFquLTELSEq+vpQthYwZ0ghamIkxQV7syjNp06bCMzLmnB9jVEilQuDGqRrlDJpLjKqZkkTwp5JJJRJPLIJag0iLZMJjfdHKmTojcd+y9KRUU+KW0OMUeC2T8SBKpz918ioBKJtuzmUD6YNwIDAQAB");
-//        //fsPayConfig.setHfRsaPrivateKey("MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCijLcYLMJEe16TS6BtEG9hUezZyYvp2qgpPVGWaaBbb6lud89ILMUC7jyTWufCo2fUQ0nJzYhVlNeMzmGFtg/zFwhkjJIkuCOW+/Koy1ow66Rom8/sNQLb82szHoeklbv17AnD7WJis7cGyy1+3E6jzfaPOB7PTzidK6KyfCWDByOt0JcGe3+6+9+loQFbFRXJ2RpWPQeN72n9FVtSKSvgkGtJNUzh/qBwMPN6ol6xcU/Z2o1sYrRfKC4tcMqccRi/DvvZFJPVlN+YqkJ6lhgAmJg7eZ2fhIgrmzqc96UKp2YUNm+1v8XHCflD9Wv94E6D2JgL4VbF4Zyf+fKYuR7pAgMBAAECggEAfy5UL6ENmuFgHSVF7y+1xdKA2+IbC60ed63XgTVB12jli15Im3MT7ngSg0TUIvERUv4W5MNgkX10rWHo4eKSViPGWE24JuzAQ+j7cuAwwCgPKh4HMAxGIWwyivuvK7JQL1kwRtEccpekc7dS8HhVO0rySBqj2JZmeGrk0HvcKciSWuMjhjT4dJUwSntD07REV6rVjrpQXuvmY40vH88uvHLdH1IcjmJs2yJRNawUNtd+8FvpOCjami7zpB+er+AQ6S2fvpljNqfE5Kadm3MvzBngDdMS3xRvMHfjCifVwFpLP0rLDP6cSn6PJWbkNYQVZi12w8+wb5f7AVlaKXnfdQKBgQDh7VC5+MOqfcUr9h/n2vhFFhQOaGAZCOBc65n8VBj9aRht8ViXFvRrIRmM+QvUbV9/7taFbtAnZXIzu+12T4vnlZv9DTsy6kKloV5923xZ4CpzIVG8crlwJz1wdALeO6M485RtRLjz6nlNKn2m2VJ1d5XFBDhIz5rWUzagPwwpwwKBgQC4L8Eyu6Yn/zQmv8l6rfAsEfUJzfYtojf1PerPYilARtgFuD20cppcOP5oAk2TTX3qaz0Y9atCfL2z2qxtrgKtw2etfhDBmT6l6+pg04SLuyTrVeZ5dxXHt+LRLJnvBbGgnvAM6rSRKdHXT0gfqiRIMw2qIUtndgRr4RK5hqcd4wKBgBYBFh620t/VFhIdC6h6VDnuV4+7rLhje+6w57OCwVhVFxMGMZmtm6qfc6yeSP+sk2OTcINYcp+TqtbNE+i1AKxSjvnLgxuHY2xcViat7OOYCKpj8WEIT3VT7RD5y5m3d0NBvhASZG0lRiE05T4N5pEYT5b7vTuiNLNxMV3UJiwfAoGBAIb2/1QEqwmN+RIX4TSTNnWkpvELSkRAJU8Akwpp/J5MC0mNqzGJ9NB1Nv7SCTRSSV04PaoHgvoSXBPpvgYUx4O6t0MrKG4ktAJzL+jJtcuKU9Bavqrs9znE5mCulRHQE0wGixJ7/dqNUWW7g7coPrPlLTMoeI+UrEK8x7LJF7ZPAoGALHvtu6zzWVeCdELIPUTersVQrH1R3yZuf6rgubg4XFw3meFcd4W8BvXm4EKGRZxdiyZvCtKlkV9u110Rx3RNSbZCOb3MClmkcow8vPIhmyGWIGymAIxr9JcD0p6HogzPvbjRsLh1nFg/+95OL2E353Bp4/oPIgYIfnYNUfD+0gA=");
-//        //fsPayConfig.setHfRsaPublicKey("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjbkiiy2ewzuPsM5uZbAFMJOBWCRRQ2RtH7Dbr9Evbow6IEyvGoen8XKpiuXzapeps3b2eogETHVFQtLooqRHpVRppFKtU1AHZXA7C6wPocfMldJbTykDCowyJwOSYEaFPBjr9cw6dQcBJMIEHj0YWjBPR1dPVzf+y4sUohbrkS/FANBpp24j+Mu0qEqh8TuVuKlvig7jbmXJiJkAmUJ+Tb3Caj20fFTen6juPd3zR/KM3twki06wZZbb4KyCiM/NwozEqJ9PkWSs6rG7aW+BEfzlo3m1a7MlL0vpKNR3f0lbywq09rFAwtA7R2lssWwLMma4LOqtMMqo3yZdv4vObQIDAQAB");
-//        fsPayConfig.setHfPayNotifyUrl("https://userapp.baohetangjinyue.cn//app/hfPay/payNotifyUrl");
-
         config=fsPayConfig;
         MerConfig merConfig = new MerConfig();
         merConfig.setProcutId(fsPayConfig.getHfProductId());

+ 10 - 10
fs-service/src/main/java/com/fs/huifuPay/service/test.java

@@ -12,7 +12,7 @@ public class test {
     static HuiFuServiceImpl huiFuService = new HuiFuServiceImpl();
     public static void main(String[] args)throws Exception {
 //        onlinePay();
-        createOrder();
+        refund();
     }
     public static void  createOrder()throws Exception {
         HuiFuCreateOrder order = new HuiFuCreateOrder();
@@ -30,10 +30,10 @@ public class test {
     public static void  queryOrder()throws Exception {
         V2TradePaymentScanpayQueryRequest request = new V2TradePaymentScanpayQueryRequest();
         //日期必须正确
-         request.setOrgReqDate("20240419");
+         request.setOrgReqDate("20251001");
         //选其一
-        // request.setOrgHfSeqId("002900TOP1A240417114227P471ac139c3f00000");
-         request.setOrgReqSeqId("inquiry-117");
+         request.setOrgHfSeqId("002900TOP2B251001170536P200ac139d2c00000");
+       //  request.setOrgReqSeqId("store-1973313179081506816");
         HuiFuQueryOrderResult result = huiFuService.queryOrder(request);
         System.out.println(result);
     }
@@ -50,13 +50,13 @@ public class test {
 
     public static void  refund()throws Exception {
         V2TradePaymentScanpayRefundRequest request = new V2TradePaymentScanpayRefundRequest();
-        request.setOrdAmt("0.01");
+        request.setOrdAmt("490.00");
         //订单创建日期
-        request.setOrgReqDate("20240419");
+        request.setOrgReqDate("20251001");
         //退款单号
-        request.setReqSeqId("refund-117");
+        request.setReqSeqId("package-1973323805363273728");
         Map<String, Object> extendInfoMap = new HashMap<>();
-        extendInfoMap.put("org_req_seq_id", "inquiry-117");
+        extendInfoMap.put("org_req_seq_id", "package-1973323805363273728");
         request.setExtendInfo(extendInfoMap);
         HuiFuRefundResult refund = huiFuService.refund(request);
         System.out.println(refund);
@@ -65,9 +65,9 @@ public class test {
     public static void  queryRefund()throws Exception {
         V2TradePaymentScanpayRefundqueryRequest request = new V2TradePaymentScanpayRefundqueryRequest();
         // 退款请求日期
-        request.setOrgReqDate("20240419");
+        request.setOrgReqDate("20251001");
         //自己传的
-        request.setOrgReqSeqId("refund-117");
+        request.setOrgReqSeqId("refund-1973293669121261568");
       //  request.setOrgHfSeqId("003100TOP1A240417140920P850ac139c3b00000");
         HuiFuRefundResult huiFuRefundResult = huiFuService.queryRefundOrder(request);
         System.out.println(huiFuRefundResult);

+ 97 - 0
fs-service/src/main/java/com/fs/wx/domain/FsWxExpressTask.java

@@ -0,0 +1,97 @@
+package com.fs.wx.domain;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDateTime;
+
+/**
+ * 微信同步发货信息定时任务表
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class FsWxExpressTask {
+
+    /**
+     * 任务ID,唯一标识
+     */
+    private Long id;
+
+    /**
+     * 订单code
+     */
+    private String orderCode;
+
+    /**
+     * 支付单号
+     */
+    private String payCode;
+
+    /**
+     * 用户id
+     */
+    private Long userId;
+
+    /**
+     * 消息内容,JSON格式。
+     */
+    private String data;
+
+    /**
+     * 任务状态:0=待执行, 1=执行中, 2=执行成功, 3=执行失败, 4=已取消
+     */
+    private Integer status;
+
+    /**
+     * 当前重试次数
+     */
+    private Integer retryCount;
+
+    /**
+     * 最大重试次数
+     */
+    private Integer maxRetries;
+
+    /**
+     * 请求参数(JSON格式,主要记录 access_token 获取方式)
+     */
+    private String requestParams;
+
+    /**
+     * 完整的请求体 (JSON格式)
+     */
+    private String requestBody;
+
+    /**
+     * API 响应结果 (JSON格式)
+     */
+    private String responseBody;
+
+    /**
+     * 错误信息 (如果执行失败)
+     */
+    private String errorMessage;
+
+    /**
+     * 任务创建时间
+     */
+    private LocalDateTime createTime; // 使用LocalDateTime对应timestamp
+
+    /**
+     * 最后更新时间
+     */
+    private LocalDateTime updateTime; // 使用LocalDateTime对应timestamp
+
+
+    /**
+     * 快递公司
+     */
+    private String expressCompany;
+
+    /**
+     * 快递编号
+     */
+    private String expressNo;
+}

+ 21 - 0
fs-service/src/main/java/com/fs/wx/dto/Contact.java

@@ -0,0 +1,21 @@
+package com.fs.wx.dto;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class Contact {
+    // 根据实际需要添加更多联系人字段
+    @JsonProperty("consignor_contact")
+    private String consignorContact; // 发货人联系方式 (示例字段)
+
+    // 可以添加收货人联系方式等
+    // @JsonProperty("receiver_contact")
+    // private String receiverContact;
+}

+ 27 - 0
fs-service/src/main/java/com/fs/wx/dto/OrderKey.java

@@ -0,0 +1,27 @@
+package com.fs.wx.dto;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class OrderKey {
+
+    @JsonProperty("order_number_type")
+    private Integer orderNumberType;
+
+    @JsonProperty("transaction_id")
+    private String transactionId;
+
+    @JsonProperty("mchid")
+    private String mchId;
+
+    @JsonProperty("out_trade_no")
+    private String outTradeNo;
+}

+ 77 - 0
fs-service/src/main/java/com/fs/wx/dto/OrderQueryRequest.java

@@ -0,0 +1,77 @@
+package com.fs.wx.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class OrderQueryRequest {
+
+    /**
+     * 聚合账户 (Required)
+     */
+    private String account;
+
+    /**
+     * 下游订单号 (Required if upOrderId is null)
+     */
+    private String lowOrderId;
+
+    /**
+     * 通莞订单号 (Required if lowOrderId is null)
+     */
+    private String upOrderId;
+
+    /**
+     * 值为"Y"时,接口返回优惠信息字段 (Optional)
+     */
+    private String extendInfo;
+
+    /**
+     * 值为"1"时,接口返回易宝专业版分账订单详情 (Optional)
+     */
+    private String isExtend;
+
+    /**
+     * 值为"1"时,接口返回SAAS分账订单详情 (Optional)
+     */
+    private String isNeedUpInfo;
+
+    /**
+     * 值为"1"时,接口返回渠道商户订单号字段 (Optional)
+     */
+    private String isNeedChannelMchOrderId;
+
+    /**
+     * 值为"1"时,返回因公付金额信息,仅支付宝服务商渠道支持 (Optional)
+     */
+    private String isNeedEnterprisePayInfo;
+
+    /**
+     * 签名 (Required)
+     * Note: This will be calculated and set by the service.
+     */
+    private String sign;
+
+    /**
+     * Helper method to get parameters for signing.
+     * Excludes the 'sign' field itself.
+     * Returns sorted map to ensure consistent order for signing.
+     *
+     * @return A map of non-null parameters sorted by key.
+     */
+    public Map<String, String> toSignMap() {
+       Map<String,String> sign = new HashMap<>();
+        sign.put("account",account);
+        sign.put("upOrderId",upOrderId);
+        sign.put("isNeedUpInfo", isNeedUpInfo);
+        return sign;
+    }
+}

+ 236 - 0
fs-service/src/main/java/com/fs/wx/dto/OrderQueryResponse.java

@@ -0,0 +1,236 @@
+package com.fs.wx.dto;
+
+import cn.hutool.core.annotation.Alias;
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+public class OrderQueryResponse {
+
+    /**
+     * 100:成功,101:失败 (Required)
+     */
+    private Integer status;
+
+    /**
+     * 消息描述 (Required)
+     */
+    private String message;
+
+    /**
+     * 上游订单号 (Required)
+     */
+    private String channelOrderId;
+
+    /**
+     * 通莞订单号 (Required)
+     */
+    private String upOrderId;
+
+    /**
+     * 默认传null (Required) - Although API doc says required, it seems informational.
+     */
+    private String payoffType;
+
+    /**
+     * 支付时间 (Required)
+     */
+    private String payTime;
+
+    /**
+     * WX: openid; Alipay: account name (Required)
+     * Mapped from both "openId" and "openid" in JSON
+     */
+    @Alias("openid") // Instruct Hutool to map "openid" to this field as well
+    private String openId;
+
+    /**
+     * 签名 (Required) - For response validation
+     */
+    private String sign;
+
+    /**
+     * 结算渠道编号 (Required)
+     */
+    private String settlementChannel;
+
+    /**
+     * 下游订单号 (Required)
+     */
+    private String lowOrderId;
+
+    /**
+     * 支付金额,单位元 (Required)
+     */
+    private String payMoney; // Keep as String as per API doc, can be converted later
+
+    /**
+     * 支付方式 0:WX, 1:ZFB, 2:UnionPay QR, 6:LongPay, 8:BestPay, H:Digital Currency (Required)
+     */
+    private String payType;
+
+    /**
+     * 0:Success, 1:Fail, 2:Revoked, 4:Pending, 5:Refunded, 6:Partial Refund (Required)
+     */
+    private String state;
+
+    /**
+     * 订单备注 (Optional)
+     */
+    private String attach;
+
+    /**
+     * 聚合账户 (Required)
+     */
+    private String account;
+
+    /**
+     * 支付方式例:WX、ZFB、YZF、LZF、YLZF (Required)
+     */
+    private String channelId;
+
+    /**
+     * 渠道优惠金额 JSON String, e.g., {"discountAmt":"100"} (Unit: Fen) (Optional)
+     */
+    private String discountInfo;
+
+    /**
+     * 扩展信息 JSON String (Optional, if requested)
+     * Need to be parsed into an object if needed.
+     */
+    private String extendInfo; // Raw JSON string
+
+    /**
+     * 易宝/SAAS分账详情 JSON Object (Optional, if requested)
+     */
+    private JSONObject extend; // Parsed JSON Object
+
+    /**
+     * SAAS分账订单详情 JSON Object (Optional, if requested)
+     */
+    private JSONObject upInfo; // Parsed JSON Object
+
+    /**
+     * 渠道商户订单号 (Optional, if requested)
+     */
+    private String channelMchOrderId;
+
+    /**
+     * 订单管控状态 FROZEN/UN_FROZEN (Optional, if requested via isNeedUpInfo=1)
+     */
+    private String fundControlCsStatus;
+
+    /**
+     * 管控订单解冻时间 yyyy-mm-dd hh:mm:ss (Optional, if requested via isNeedUpInfo=1 and status is UN_FROZEN)
+     */
+    private String csUnFrozenCompleteDate;
+
+    /**
+     * 因公付金额信息 JSON String, e.g., {"invoiceAmount":"0.01","isUseEnterprisePay":false} (Optional, if requested)
+     */
+    private String enterprisePayInfo; // Raw JSON String
+
+    // --- Helper methods to access parsed nested JSON data ---
+
+    /**
+     * Gets parsed DiscountInfo object from discountInfo string.
+     * @return DiscountInfo object or null if parsing fails or discountInfo is null/empty.
+     */
+    public DiscountInfo getParsedDiscountInfo() {
+        if (JSONUtil.isJson(this.discountInfo)) {
+            try {
+                return JSONUtil.toBean(this.discountInfo, DiscountInfo.class);
+            } catch (Exception e) {
+                // Log parsing error if needed
+                return null;
+            }
+        }
+        return null;
+    }
+
+     /**
+     * Gets parsed EnterprisePayInfo object from enterprisePayInfo string.
+     * @return EnterprisePayInfo object or null if parsing fails or enterprisePayInfo is null/empty.
+     */
+    public EnterprisePayInfo getParsedEnterprisePayInfo() {
+         if (JSONUtil.isJson(this.enterprisePayInfo)) {
+            try {
+                return JSONUtil.toBean(this.enterprisePayInfo, EnterprisePayInfo.class);
+            } catch (Exception e) {
+                 // Log parsing error if needed
+                return null;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Gets parsed ExtendInfo object from extendInfo string.
+     * @return JSONObject or null if parsing fails or extendInfo is null/empty.
+     */
+    public JSONObject getParsedExtendInfo() {
+        if (JSONUtil.isJson(this.extendInfo)) {
+            try {
+                return JSONUtil.parseObj(this.extendInfo);
+            } catch (Exception e) {
+                 // Log parsing error if needed
+                return null;
+            }
+        }
+        return null;
+    }
+
+    // --- Nested DTOs for parsed JSON strings ---
+
+    @Data
+    public static class DiscountInfo {
+        /**
+         * Discount amount in Fen (分)
+         */
+        private String discountAmt; // Keep as String as per API, or use Integer/Long
+
+        public BigDecimal getDiscountAmtYuan() {
+            if (discountAmt != null) {
+                try {
+                    // Assuming discountAmt is in Fen (cents)
+                    return new BigDecimal(discountAmt).divide(new BigDecimal("100"));
+                } catch (NumberFormatException e) {
+                    return null; // Or handle error appropriately
+                }
+            }
+            return null;
+        }
+    }
+
+    @Data
+    public static class EnterprisePayInfo {
+        private String invoiceAmount; // Amount in Yuan (元)
+        private Boolean isUseEnterprisePay;
+
+        public BigDecimal getInvoiceAmountValue() {
+             if (invoiceAmount != null) {
+                 try {
+                     return new BigDecimal(invoiceAmount);
+                 } catch (NumberFormatException e) {
+                     return null; // Or handle error appropriately
+                 }
+             }
+             return null;
+         }
+    }
+
+    /**
+     * Validates the response signature.
+     * IMPORTANT: Implement the actual signature validation logic based on Tongguan's specification.
+     * @param secretKey The secret key.
+     * @return true if the signature is valid, false otherwise.
+     */
+    public boolean isResponseSignValid(String secretKey) {
+
+        System.err.println("WARN: Response signature validation is not implemented!");
+        return true;
+    }
+}

+ 17 - 0
fs-service/src/main/java/com/fs/wx/dto/Payer.java

@@ -0,0 +1,17 @@
+package com.fs.wx.dto;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class Payer {
+
+    @JsonProperty("openid")
+    private String openid;
+}

+ 26 - 0
fs-service/src/main/java/com/fs/wx/dto/ShippingItem.java

@@ -0,0 +1,26 @@
+package com.fs.wx.dto;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class ShippingItem {
+
+    @JsonProperty("tracking_no")
+    private String trackingNo;
+
+    @JsonProperty("express_company")
+    private String expressCompany;
+
+    @JsonProperty("item_desc")
+    private String itemDesc;
+
+    @JsonProperty("contact")
+    private Contact contact;
+}

+ 38 - 0
fs-service/src/main/java/com/fs/wx/dto/UploadShippingInfoRequest.java

@@ -0,0 +1,38 @@
+package com.fs.wx.dto;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class UploadShippingInfoRequest {
+
+    @JsonProperty("order_key")
+    private OrderKey orderKey;
+
+    @JsonProperty("logistics_type")
+    private Integer logisticsType;
+
+    @JsonProperty("delivery_mode")
+    private Integer deliveryMode;
+
+    @JsonProperty("is_all_delivered")
+    private Boolean isAllDelivered;
+
+    @JsonProperty("shipping_list")
+    private List<ShippingItem> shippingList;
+
+    @JsonProperty("upload_time")
+    private String uploadTime;
+
+    @JsonProperty("payer")
+    private Payer payer;
+
+}

+ 21 - 0
fs-service/src/main/java/com/fs/wx/dto/WeChatApiConfig.java

@@ -0,0 +1,21 @@
+package com.fs.wx.dto;
+
+import lombok.Getter;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@Getter
+public class WeChatApiConfig {
+
+    @Value("${wechat.api.base-url}")
+    private String baseUrl;
+
+    @Value("${wechat.api.upload-shipping-info}")
+    private String uploadShippingInfoPath;
+
+
+    public String getUploadShippingInfoUrl() {
+        return baseUrl + uploadShippingInfoPath;
+    }
+}

+ 20 - 0
fs-service/src/main/java/com/fs/wx/dto/WeChatApiResponse.java

@@ -0,0 +1,20 @@
+package com.fs.wx.dto;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+public class WeChatApiResponse {
+
+    @JsonProperty("errcode")
+    private Integer errcode;
+
+    @JsonProperty("errmsg")
+    private String errmsg;
+
+    public boolean isSuccess() {
+        return errcode != null && errcode == 0;
+    }
+}

+ 116 - 0
fs-service/src/main/java/com/fs/wx/mapper/FsWxExpressTaskMapper.java

@@ -0,0 +1,116 @@
+package com.fs.wx.mapper;
+
+import com.fs.wx.domain.FsWxExpressTask;
+import org.apache.ibatis.annotations.*;
+
+import java.util.List;
+
+/**
+ * 微信同步发货信息定时任务表 Mapper 接口
+ */
+@Mapper
+public interface FsWxExpressTaskMapper {
+
+    /**
+     * 根据ID查询任务
+     * @param id 任务ID
+     * @return FsWxExpressTask 任务实体
+     */
+    @Select("SELECT * FROM fs_wx_express_task WHERE id = #{id}")
+    FsWxExpressTask selectById(@Param("id") Long id);
+
+    /**
+     * 插入新任务
+     * @param task 任务实体
+     * @return 影响行数
+     */
+    @Insert("INSERT INTO fs_wx_express_task (order_code, user_id, data, status, retry_count, max_retries, request_params, request_body, response_body, error_message, create_time, update_time,express_company,express_no) " +
+            "VALUES (#{orderCode}, #{userId}, #{data}, #{status}, #{retryCount}, #{maxRetries}, #{requestParams}, #{requestBody}, #{responseBody}, #{errorMessage}, #{createTime}, #{updateTime},#{expressCompany},#{expressNo})")
+    @Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
+    int insert(FsWxExpressTask task);
+
+    /**
+     * 根据ID更新任务信息
+     * @param task 任务实体
+     * @return 影响行数
+     */
+    @Update("<script>" +
+            "UPDATE fs_wx_express_task " +
+            "<set>" +
+            "  <if test='orderCode != null'>order_code = #{orderCode},</if>" +
+            "  <if test='userId != null'>user_id = #{userId},</if>" +
+            "  <if test='data != null'>data = #{data},</if>" +
+            "  <if test='status != null'>status = #{status},</if>" +
+            "  <if test='retryCount != null'>retry_count = #{retryCount},</if>" +
+            "  <if test='maxRetries != null'>max_retries = #{maxRetries},</if>" +
+            "  <if test='requestParams != null'>request_params = #{requestParams},</if>" +
+            "  <if test='requestBody != null'>request_body = #{requestBody},</if>" +
+            "  <if test='responseBody != null'>response_body = #{responseBody},</if>" +
+            "  <if test='errorMessage != null'>error_message = #{errorMessage},</if>" +
+            "</set>" +
+            "WHERE id = #{id}" +
+            "</script>")
+    int updateById(FsWxExpressTask task);
+
+    /**
+     * 根据ID删除任务
+     * @param id 任务ID
+     * @return 影响行数
+     */
+    @Delete("DELETE FROM fs_wx_express_task WHERE id = #{id}")
+    int deleteById(@Param("id") Long id);
+
+    /**
+     * 根据状态查询任务列表
+     * @param status 任务状态
+     * @return List<FsWxExpressTask> 任务列表
+     */
+    @Select("SELECT * FROM fs_wx_express_task WHERE status = #{status}")
+    List<FsWxExpressTask> selectByStatus(@Param("status") Integer status);
+
+
+    /**
+     * 查询待处理数据
+     * @return
+     */
+    @Select("SELECT * FROM fs_wx_express_task WHERE retry_count < 3 AND status in (0,3)")
+    List<FsWxExpressTask> selectPendingData();
+    @Update("<script>" +
+            "<foreach collection='list' item='task' separator=';'>" +
+            " UPDATE fs_wx_express_task" +
+            " SET" +
+            "  order_code = #{task.orderCode}," +
+            "  user_id = #{task.userId}," +
+            "  data = #{task.data}," +
+            "  status = #{task.status}," +
+            "  retry_count = #{task.retryCount}," +
+            "  max_retries = #{task.maxRetries}," +
+            "  request_params = #{task.requestParams}," +
+            "  request_body = #{task.requestBody}," +
+            "  response_body = #{task.responseBody}," +
+            "  error_message = #{task.errorMessage}," +
+            "  update_time = now()" +
+            " WHERE id = #{task.id}" +
+            "</foreach>" +
+            "</script>")
+    void batchUpdate(List<FsWxExpressTask> fsWxExpressTasks);
+
+    /**
+     * 批量插入新任务
+     * @param tasks 任务实体列表
+     * @return 影响行数 (Optional: change void to int if needed)
+     */
+    @Insert("<script>" +
+            "INSERT INTO fs_wx_express_task " +
+            "(order_code, user_id, data, status, retry_count, max_retries, request_params, request_body, response_body, error_message, create_time, update_time, pay_code) " +
+            "VALUES " +
+            "<foreach collection='tasks' item='task' separator=','>" +
+            "(" +
+            "#{task.orderCode}, #{task.userId}, #{task.data}, #{task.status}, #{task.retryCount}, #{task.maxRetries}, " + // Keep ::json if PostgreSQL
+            "#{task.requestParams}, #{task.requestBody}, #{task.responseBody}, #{task.errorMessage}, " +
+            "#{task.createTime}, #{task.updateTime},#{task.payCode}" +
+            ")" +
+            "</foreach>" +
+            "</script>")
+    void insertBatch(List<FsWxExpressTask> tasks);
+}

+ 20 - 0
fs-service/src/main/java/com/fs/wx/service/OrderQueryService.java

@@ -0,0 +1,20 @@
+package com.fs.wx.service;
+
+
+import com.fs.wx.dto.OrderQueryRequest;
+import com.fs.wx.dto.OrderQueryResponse;
+
+public interface OrderQueryService {
+
+    /**
+     * Queries an order using either lowOrderId or upOrderId.
+     *
+     * @param request The request object containing query parameters.
+     *                The 'sign' field will be calculated internally.
+     * @return The order query response.
+     * @throws IllegalArgumentException if required parameters are missing.
+     * @throws RuntimeException if the API call fails or returns an error status.
+     */
+    OrderQueryResponse queryOrder(OrderQueryRequest request);
+
+}

+ 130 - 0
fs-service/src/main/java/com/fs/wx/service/ShippingService.java

@@ -0,0 +1,130 @@
+package com.fs.wx.service;
+
+import cn.hutool.core.exceptions.ExceptionUtil;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.http.*;
+import cn.hutool.json.JSONUtil;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fs.wx.dto.UploadShippingInfoRequest;
+import com.fs.wx.dto.WeChatApiConfig;
+import com.fs.wx.dto.WeChatApiResponse;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+import org.springframework.web.util.UriComponentsBuilder;
+
+@Service
+public class ShippingService {
+
+    private static final Logger log = LoggerFactory.getLogger(ShippingService.class);
+
+    private final WeChatApiConfig weChatApiConfig;
+    private final WeChatAuthService weChatAuthService;
+
+    public ShippingService(WeChatApiConfig weChatApiConfig, WeChatAuthService weChatAuthService) {
+        this.weChatApiConfig = weChatApiConfig;
+        this.weChatAuthService = weChatAuthService;
+    }
+
+    /**
+     * 调用微信 API 上传发货信息 (使用 Hutool HttpUtil)
+     * @param request 发货信息请求体
+     * @return 微信 API 的响应
+     */
+    public WeChatApiResponse uploadShippingInfo(UploadShippingInfoRequest request) {
+        String accessToken = weChatAuthService.getAccessToken(false);
+        if (accessToken == null) {
+            log.error("获取微信 Access Token 失败");
+            WeChatApiResponse errorResponse = new WeChatApiResponse();
+            errorResponse.setErrcode(-3); // 自定义错误码,表示获取Token失败
+            errorResponse.setErrmsg("获取微信 Access Token 失败");
+            return errorResponse;
+        }
+
+        String url = UriComponentsBuilder.fromHttpUrl(weChatApiConfig.getUploadShippingInfoUrl())
+                .queryParam("access_token", accessToken)
+                .toUriString();
+
+        log.debug("请求微信上传发货接口 URL: {}", url);
+
+        ObjectMapper objectMapper = new ObjectMapper();
+        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+        String requestBodyJson = null;
+        try {
+            requestBodyJson = objectMapper.writeValueAsString(request);
+        } catch (JsonProcessingException e) {
+            throw new RuntimeException(e);
+        }
+
+        log.debug("请求体 JSON: {}", requestBodyJson);
+
+
+        HttpResponse httpResponse = null;
+        try {
+            HttpRequest httpRequest = HttpUtil.createPost(url)
+                    .header(Header.CONTENT_TYPE, ContentType.JSON.getValue())
+                    .body(requestBodyJson)
+                    .timeout(10000);
+
+            httpResponse = httpRequest.execute();
+
+            int statusCode = httpResponse.getStatus();
+            String responseBodyString = httpResponse.body();
+
+            log.info("微信接口响应状态: {}", statusCode);
+            log.info("微信接口响应体: {}", responseBodyString);
+
+            if (httpResponse.isOk()) {
+                WeChatApiResponse weChatApiResponse = JSONUtil.toBean(responseBodyString, WeChatApiResponse.class);
+
+                if (!weChatApiResponse.isSuccess()) {
+                    log.warn("微信接口返回业务错误: code={}, message={}", weChatApiResponse.getErrcode(), weChatApiResponse.getErrmsg());
+                    if(ObjectUtil.equal(weChatApiResponse.getErrcode(),40001)) {
+                        log.info("token缓存失效,清除token,等待下次执行...");
+                        weChatAuthService.clearToken();
+                    }
+                }
+                return weChatApiResponse;
+
+            } else {
+                log.error("调用微信接口收到非成功状态码: {}", statusCode);
+                try {
+                    WeChatApiResponse errorResponse = JSONUtil.toBean(responseBodyString, WeChatApiResponse.class);
+                    if (errorResponse.getErrcode() == null) {
+                        errorResponse.setErrcode(statusCode);
+                        errorResponse.setErrmsg("微信接口HTTP错误,状态码: " + statusCode + ", 响应体: " + responseBodyString);
+                    }
+                    return errorResponse;
+                } catch (Exception parseEx) {
+                    log.warn("无法将微信错误响应体解析为JSON: {}", responseBodyString, parseEx);
+                    WeChatApiResponse errorResponse = new WeChatApiResponse();
+                    errorResponse.setErrcode(statusCode);
+                    errorResponse.setErrmsg("调用微信接口失败,状态码: " + statusCode + ", 原始响应体: " + responseBodyString);
+                    return errorResponse;
+                }
+            }
+        } catch (HttpException e) {
+            log.error("调用微信接口发生HTTP异常: {}", e.getMessage(), e);
+            WeChatApiResponse errorResponse = new WeChatApiResponse();
+            errorResponse.setErrcode(-1);
+            String detailedMessage = ExceptionUtil.getMessage(e);
+            errorResponse.setErrmsg("调用微信接口时发生HTTP异常: " + detailedMessage);
+            if (httpResponse != null) {
+                errorResponse.setErrmsg(errorResponse.getErrmsg() + ", HTTP状态码: " + httpResponse.getStatus());
+            }
+            return errorResponse;
+        } catch (Exception e) {
+            log.error("调用微信接口时发生意外错误", e);
+            WeChatApiResponse errorResponse = new WeChatApiResponse();
+            errorResponse.setErrcode(-2);
+            errorResponse.setErrmsg("调用微信接口时发生内部服务器错误: " + e.getMessage());
+            return errorResponse;
+        }finally {
+            if(httpResponse != null) {
+                httpResponse.close();
+            }
+        }
+    }
+}

+ 22 - 0
fs-service/src/main/java/com/fs/wx/service/WeChatAuthService.java

@@ -0,0 +1,22 @@
+package com.fs.wx.service;
+
+public interface WeChatAuthService {
+    void clearToken();
+
+    /**
+     * 获取有效的微信小程序 Access Token
+     * @param forceRefresh 是否强制刷新,忽略缓存
+     * @return Access Token
+     * @throws RuntimeException 如果获取失败
+     */
+    String getAccessToken(boolean forceRefresh);
+
+    /**
+     * 获取有效的微信小程序 Access Token (优先使用缓存)
+     * @return Access Token
+     * @throws RuntimeException 如果获取失败
+     */
+    default String getAccessToken() {
+        return getAccessToken(true);
+    }
+}

+ 118 - 0
fs-service/src/main/java/com/fs/wx/service/impl/InMemoryWeChatAuthServiceImpl.java

@@ -0,0 +1,118 @@
+package com.fs.wx.service.impl;
+
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.http.HttpRequest;
+import cn.hutool.http.HttpResponse;
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
+import com.fs.wx.service.WeChatAuthService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+@Service
+public class InMemoryWeChatAuthServiceImpl implements WeChatAuthService {
+
+    private static final Logger log = LoggerFactory.getLogger(InMemoryWeChatAuthServiceImpl.class);
+    private String cachedToken = null;
+    private long expiryTime = 0; // Token 过期时间戳 (ms)
+
+    @Value("${wx.miniapp.configs[0].appid}")
+    private String appId;
+
+    @Value("${wx.miniapp.configs[0].secret}")
+    private String appSecret;
+
+    private final String tokenUrlFormat = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";
+
+    public InMemoryWeChatAuthServiceImpl() {
+    }
+
+
+    @Override
+    public synchronized void clearToken(){
+        log.info("清除token缓存...");
+        cachedToken = null;
+        expiryTime = 0;
+    }
+
+    @Override
+    public synchronized String getAccessToken(boolean forceRefresh) {
+        long now = System.currentTimeMillis();
+        if (!forceRefresh && cachedToken != null && now < expiryTime) {
+            log.debug("Using cached access token.");
+            return cachedToken;
+        }
+
+        if (StrUtil.hasBlank(appId, appSecret)) {
+            log.error("appId或者appSecret不存在!");
+            throw new RuntimeException("appId或者appSecret不存在!");
+        }
+
+
+        String url = String.format(tokenUrlFormat, appId, appSecret);
+        log.info(url);
+        HttpResponse httpResponse = null;
+        String body = null;
+
+        try {
+            httpResponse = HttpRequest.get(url)
+                    .timeout(5000)
+                    .execute();
+
+            body = httpResponse.body();
+
+            if (!httpResponse.isOk()) {
+                log.error("获取accessToken失败!. Status: {}, Body: {}", httpResponse.getStatus(), body);
+                String errorMsg = parseErrorMsg(body);
+                throw new RuntimeException("获取accessToken失败! Status: " + httpResponse.getStatus() + ", Message: " + errorMsg);
+            }
+
+            if (StrUtil.isBlank(body)) {
+                log.error("获取accessToken失败!.  URL: {}", url);
+                throw new RuntimeException("获取accessToken失败!");
+            }
+
+            JSONObject responseJson = JSONUtil.parseObj(body);
+
+            if (responseJson.containsKey("access_token")) {
+                cachedToken = responseJson.getStr("access_token");
+                if(StrUtil.isBlank(cachedToken)){
+                    log.error("获取accessToken失败!response: {}", body);
+                    throw new RuntimeException("获取accessToken失败!");
+                }
+
+                long expiresInSeconds = responseJson.getLong("expires_in", 7200L);
+                expiryTime = now + (expiresInSeconds - 120) * 1000;
+                log.info("获取accessToken获取成功 {}",cachedToken);
+                return cachedToken;
+            } else {
+                String errorMsg = responseJson.getStr("errmsg", "Unknown error: access_token missing in response");
+                log.error("Failed to fetch access token, 'access_token' key missing. Response: {}", body);
+                throw new RuntimeException("Failed to fetch access token: " + errorMsg);
+            }
+        } catch (Exception e) {
+            cachedToken = null;
+            expiryTime = 0;
+            log.error("Error fetching access token from URL: {}", url, e);
+            throw new RuntimeException("Error fetching access token: " + e.getMessage(), e);
+        }finally {
+            if(httpResponse != null) {
+                httpResponse.close();
+            }
+        }
+    }
+
+    private String parseErrorMsg(String jsonBody) {
+        if (StrUtil.isBlank(jsonBody)) {
+            return "返回为空!";
+        }
+        try {
+            JSONObject json = JSONUtil.parseObj(jsonBody);
+            return json.getStr("errmsg", "Unknown error in response body");
+        } catch (Exception e) {
+            return "返回解析失败!";
+        }
+    }
+}

+ 71 - 0
fs-service/src/main/java/com/fs/wx/service/impl/OrderQueryServiceImpl.java

@@ -0,0 +1,71 @@
+package com.fs.wx.service.impl;
+
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.http.Header;
+import cn.hutool.http.HttpRequest;
+import cn.hutool.http.HttpResponse;
+import cn.hutool.json.JSONUtil;
+import com.fs.wx.dto.OrderQueryRequest;
+import com.fs.wx.dto.OrderQueryResponse;
+import com.fs.wx.service.OrderQueryService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+@Service
+public class OrderQueryServiceImpl implements OrderQueryService {
+
+    private static final Logger log = LoggerFactory.getLogger(OrderQueryServiceImpl.class);
+
+    private String apiBaseUrl = "https://tgpay.833006.net";
+
+    private String secretKey = "YOUR_SECRET_KEY";
+
+    private static final String ORDER_QUERY_PATH = "/tgPosp/services/payApi/orderQuery";
+    private static final int SUCCESS_STATUS = 100;
+
+    @Override
+    public OrderQueryResponse queryOrder(OrderQueryRequest request) {
+        String apiUrl = apiBaseUrl + ORDER_QUERY_PATH;
+        String requestBody = JSONUtil.toJsonStr(request);
+
+        log.info("Sending Order Query request to {}: {}", apiUrl, requestBody);
+
+        HttpResponse response = null;
+        try {
+            response = HttpRequest.post(apiUrl)
+                    .header(Header.CONTENT_TYPE, "application/json;charset=utf-8")
+                    .body(requestBody)
+                    .timeout(10000)
+                    .execute();
+
+            String responseBody = response.body();
+            log.info("Received Order Query response ({}): {}", response.getStatus(), responseBody);
+
+            if (!response.isOk()) {
+                throw new RuntimeException(String.format("API request failed with HTTP status %d: %s",
+                        response.getStatus(), responseBody));
+            }
+
+            if (StrUtil.isBlank(responseBody)) {
+                throw new RuntimeException("API response body is empty.");
+            }
+
+            OrderQueryResponse queryResponse = JSONUtil.toBean(responseBody, OrderQueryResponse.class, true); // Use lenient parsing for openId/openid
+
+
+            if (queryResponse.getStatus() == null || queryResponse.getStatus() != SUCCESS_STATUS) {
+                 log.error("API returned failure status [{}]: {}", queryResponse.getStatus(), queryResponse.getMessage());
+                 throw new RuntimeException(String.format("API error [%d]: %s",
+                         queryResponse.getStatus() != null ? queryResponse.getStatus() : -1,
+                         queryResponse.getMessage()));
+            }
+
+            return queryResponse;
+
+        } catch (Exception e) {
+            log.error("Error during Order Query API call", e);
+            throw new RuntimeException("Failed to query order: " + e.getMessage(), e);
+        }
+    }
+}

+ 1 - 1
fs-service/src/main/resources/application-common.yml

@@ -36,7 +36,7 @@ server:
 # 日志配置
 logging:
   level:
-    com.fs: info
+    com.fs: debug
     org.springframework: warn
 
 express:

+ 2 - 2
fs-service/src/main/resources/application-config-druid-syysy.yml

@@ -10,8 +10,8 @@ logging:
 wx:
   miniapp:
     configs:
-      - appid: w   #中康智慧
-        secret: 5
+      - appid: wx0d1a3dd485268521   #中康智慧
+        secret: 6f04fdc097f20142f684a796982a7983
         token: Ncbnd7lJvkripVOpyTFAna6NAWCxCrvC
         aesKey: HlEiBB55eaWUaeBVAQO3cWKWPYv1vOVQSq7nFNICw4E
         msgDataFormat: JSON

+ 3 - 0
fs-service/src/main/resources/application.properties

@@ -0,0 +1,3 @@
+# application.properties
+wechat.api.base-url=https://api.weixin.qq.com
+wechat.api.upload-shipping-info=/wxa/sec/order/upload_shipping_info