瀏覽代碼

Merge branch 'refs/heads/master_feat_multi_tracking_20250317'

xdd 1 月之前
父節點
當前提交
daccdcc92e
共有 35 個文件被更改,包括 1576 次插入289 次删除
  1. 1 0
      fs-admin/src/main/java/com/fs/api/controller/CompanyAPIController.java
  2. 55 0
      fs-admin/src/main/java/com/fs/express/FsStoreDeliversController.java
  3. 14 0
      fs-admin/src/main/java/com/fs/store/controller/FsExpressController.java
  4. 1 1
      fs-admin/src/main/java/com/fs/store/controller/FsStoreCouponIssueController.java
  5. 16 17
      fs-admin/src/main/java/com/fs/store/controller/FsStoreOrderController.java
  6. 38 0
      fs-admin/src/main/java/com/fs/task/ExpressTask.java
  7. 150 141
      fs-admin/src/main/java/com/fs/task/StoreTask.java
  8. 1 1
      fs-admin/src/main/resources/application.yml
  9. 4 1
      fs-api/src/main/java/com/fs/app/controller/CommonController.java
  10. 2 2
      fs-api/src/main/resources/application.yml
  11. 14 0
      fs-common/src/main/java/com/fs/common/utils/PhoneUtils.java
  12. 70 0
      fs-company/src/main/java/com/fs/express/FsStoreDeliversController.java
  13. 1 1
      fs-company/src/main/java/com/fs/qw/config/SocketConfig.java
  14. 3 0
      fs-company/src/main/java/com/fs/store/controller/FsStoreOrderController.java
  15. 62 0
      fs-service-system/src/main/java/com/fs/express/FsStoreDeliversService.java
  16. 5 0
      fs-service-system/src/main/java/com/fs/express/IExpressService.java
  17. 18 0
      fs-service-system/src/main/java/com/fs/express/dto/DeliveryDTO.java
  18. 40 0
      fs-service-system/src/main/java/com/fs/express/dto/ExpressPushRespDTO.java
  19. 87 0
      fs-service-system/src/main/java/com/fs/express/enums/TaskStatusEnum.java
  20. 205 0
      fs-service-system/src/main/java/com/fs/express/http/KdniaoSubscribeHttp.java
  21. 51 0
      fs-service-system/src/main/java/com/fs/express/http/dto/LogisticsInfoDTO.java
  22. 71 0
      fs-service-system/src/main/java/com/fs/express/impl/ExpressServiceImpl.java
  23. 160 0
      fs-service-system/src/main/java/com/fs/express/impl/FsStoreDeliversServiceImpl.java
  24. 32 0
      fs-service-system/src/main/java/com/fs/store/domain/FsOrderExpressPush.java
  25. 100 0
      fs-service-system/src/main/java/com/fs/store/domain/FsStoreDelivers.java
  26. 30 0
      fs-service-system/src/main/java/com/fs/store/mapper/FsOrderExpressPushMapper.java
  27. 105 0
      fs-service-system/src/main/java/com/fs/store/mapper/FsStoreDeliversMapper.java
  28. 5 1
      fs-service-system/src/main/java/com/fs/store/param/FsStoreOrderExpressParam.java
  29. 10 7
      fs-service-system/src/main/java/com/fs/store/service/IFsExpressService.java
  30. 2 0
      fs-service-system/src/main/java/com/fs/store/service/IFsStoreOrderService.java
  31. 71 3
      fs-service-system/src/main/java/com/fs/store/service/impl/FsExpressServiceImpl.java
  32. 131 112
      fs-service-system/src/main/java/com/fs/store/service/impl/FsStoreOrderServiceImpl.java
  33. 2 2
      fs-service-system/src/main/resources/application-config.yml
  34. 18 0
      fs-user-app/src/main/java/com/fs/app/controller/StoreOrderController.java
  35. 1 0
      fs-user-app/src/main/resources/static/S8Zw463cFc.txt

+ 1 - 0
fs-admin/src/main/java/com/fs/api/controller/CompanyAPIController.java

@@ -60,6 +60,7 @@ public class CompanyAPIController extends BaseController
 
 
     @GetMapping("/getExpressInfo")
+    @Deprecated
     public R getExpressInfo(ExpressParam param, HttpServletRequest request) {
         Company company=checkCompany(request);
         List<ExpressVO> list = expressService.getExpressInfoAPI(param);

+ 55 - 0
fs-admin/src/main/java/com/fs/express/FsStoreDeliversController.java

@@ -0,0 +1,55 @@
+package com.fs.express;
+
+import com.fs.common.core.domain.R;
+import com.fs.store.domain.FsStoreDelivers;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 物流信息管理
+ * @author xdd
+ */
+@RestController
+@RequestMapping("/fsStoreDelivers")
+public class FsStoreDeliversController {
+
+    @Autowired
+    private FsStoreDeliversService fsStoreDeliversService;
+
+    /**
+     * 根据ID查询
+     */
+    @GetMapping("/{id}")
+    public R getById(@PathVariable Integer id) {
+        FsStoreDelivers fsStoreDelivers = fsStoreDeliversService.findById(id);
+        return R.ok();
+    }
+    /**
+     * 根据orderId查询
+     */
+    @GetMapping("/getByOrderId/{orderId}")
+    public R getByOrderId(@PathVariable Long orderId) {
+        List<FsStoreDelivers> byOrderId = fsStoreDeliversService.findByOrderId(orderId);
+        return R.ok().put("data",byOrderId);
+    }
+
+    /**
+     * 新增
+     */
+    @PostMapping
+    public R create(@RequestBody FsStoreDelivers fsStoreDelivers) {
+        FsStoreDelivers savedFsStoreDelivers = fsStoreDeliversService.save(fsStoreDelivers);
+        return R.ok().put("data",savedFsStoreDelivers);
+    }
+     /**
+     *全部更新
+     */
+    @PutMapping("/{id}")
+    public R update(@PathVariable Long id, @RequestBody FsStoreDelivers fsStoreDelivers) {
+        fsStoreDelivers.setId(id); // Ensure ID is set for update
+        boolean updated = fsStoreDeliversService.update(fsStoreDelivers);
+        return R.ok();
+    }
+}

+ 14 - 0
fs-admin/src/main/java/com/fs/store/controller/FsExpressController.java

@@ -5,8 +5,11 @@ import java.util.List;
 import com.fs.common.core.domain.R;
 import com.fs.company.domain.Company;
 import com.fs.company.service.ICompanyService;
+import com.fs.store.param.FsStoreOrderExpressParam;
+import io.swagger.annotations.ApiOperation;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.PutMapping;
@@ -24,6 +27,8 @@ import com.fs.store.service.IFsExpressService;
 import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.common.core.page.TableDataInfo;
 
+import javax.servlet.http.HttpServletRequest;
+
 /**
  * 快递公司Controller
  *
@@ -40,6 +45,15 @@ public class FsExpressController extends BaseController
     @Autowired
     private ICompanyService companyService;
 
+
+
+    @ApiOperation("物流查询")
+    @PostMapping("/getExpressByDeliverId")
+    public R getExpressByDeliverId(@Validated @RequestBody FsStoreOrderExpressParam param, HttpServletRequest request){
+        return fsExpressService.getExpressByDeliverId(param);
+    }
+
+
     /**
      * 查询快递公司列表
      */

+ 1 - 1
fs-admin/src/main/java/com/fs/store/controller/FsStoreCouponIssueController.java

@@ -42,7 +42,7 @@ public class FsStoreCouponIssueController extends BaseController
      * @return 套餐券列表
      */
     @GetMapping("/listAllAvailable")
-    @PreAuthorize("@ss.hasPermi('store:storeCoupon:listAllAvailable')")
+    @PreAuthorize("@ss.hasPermi('store:storeCouponIssue:list')")
     public AjaxResult listAllAvailable(){
         List<FsStoreCouponIssueVO> fsStoreCouponIssueVOS = fsStoreCouponIssueService.listAllAvailable();
         return AjaxResult.success(fsStoreCouponIssueVOS);

+ 16 - 17
fs-admin/src/main/java/com/fs/store/controller/FsStoreOrderController.java

@@ -1,34 +1,26 @@
 package com.fs.store.controller;
 
-import java.math.BigDecimal;
 import java.util.ArrayList;
-import java.util.Date;
 import java.util.List;
-import java.util.Objects;
 
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.util.StrUtil;
-import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSONObject;
 import com.fs.common.core.domain.R;
-import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.ParseUtils;
 import com.fs.common.utils.StringUtils;
-import com.fs.company.domain.CompanyMoneyLogs;
 import com.fs.company.param.CompanyStoreOrderMoneyLogsListParam;
 import com.fs.company.service.ICompanyMoneyLogsService;
-import com.fs.company.vo.CompanyMoneyLogsVO;
 import com.fs.company.vo.CompanyStoreOrderMoneyLogsVO;
 import com.fs.erp.domain.ErpDeliverys;
 import com.fs.erp.domain.ErpOrderQuery;
 import com.fs.erp.dto.ErpOrderQueryRequert;
 import com.fs.erp.dto.ErpOrderQueryResponse;
 import com.fs.erp.service.IErpOrderService;
+import com.fs.express.FsStoreDeliversService;
+import com.fs.express.dto.DeliveryDTO;
 import com.fs.store.domain.*;
-import com.fs.store.dto.ExpressInfoDTO;
-import com.fs.store.dto.FsStoreCartDTO;
-import com.fs.store.dto.StoreOrderExpressExportDTO;
-import com.fs.store.dto.StoreOrderProductDTO;
+import com.fs.store.dto.*;
 import com.fs.store.enums.ShipperCodeEnum;
 import com.fs.store.param.*;
 import com.fs.store.service.*;
@@ -48,8 +40,6 @@ import org.springframework.web.multipart.MultipartFile;
 
 import javax.servlet.http.HttpServletRequest;
 
-import static com.fs.store.constants.StoreConstants.DELIVERY;
-
 /**
  * 订单Controller
  *
@@ -80,6 +70,8 @@ public class FsStoreOrderController extends BaseController {
     @Autowired
     private ICompanyMoneyLogsService moneyLogsService;
 
+    @Autowired
+    private FsStoreDeliversService fsStoreDeliversService;
     /**
      * 查询订单列表
      */
@@ -342,7 +334,10 @@ public class FsStoreOrderController extends BaseController {
 
     @PreAuthorize("@ss.hasPermi('store:storeOrder:express')")
     @GetMapping(value = "/getExpress/{id}")
+    @Deprecated
     public R getExpress(@PathVariable("id") Long id) {
+        logger.warn("该接口已经停止使用!");
+
         FsStoreOrder order = fsStoreOrderService.selectFsStoreOrderById(id);
         ExpressInfoDTO expressInfoDTO = null;
         if (StringUtils.isNotEmpty(order.getDeliveryId())) {
@@ -380,14 +375,18 @@ public class FsStoreOrderController extends BaseController {
 
     /**
      * 修改物流
-     * @param fsStoreOrder
-     * @return
+     * @param deliveryDTO
+     * @return AjaxResult
      */
     @Log(title = "修改物流", businessType = BusinessType.UPDATE)
     @PreAuthorize("@ss.hasPermi('store:storeOrder:editDeliveryId')")
     @PutMapping("/editDeliveryId")
-    public AjaxResult editDeliveryId(@RequestBody FsStoreOrder fsStoreOrder) {
-        return toAjax(fsStoreOrderService.updateFsStoreOrder(fsStoreOrder));
+    public AjaxResult editDeliveryId(@RequestBody FsStoreDelivers deliveryDTO) {
+
+        fsStoreDeliversService.editDeliveryId(deliveryDTO);
+        fsStoreDeliversService.syncDeliverInfo(deliveryDTO.getOrderId());
+        fsStoreDeliversService.finishOrder(deliveryDTO.getOrderId());
+        return AjaxResult.success();
     }
 
     @Log(title = "同步管易物流单号", businessType = BusinessType.UPDATE)

+ 38 - 0
fs-admin/src/main/java/com/fs/task/ExpressTask.java

@@ -0,0 +1,38 @@
+package com.fs.task;
+
+import com.fs.express.IExpressService;
+import com.fs.store.service.IFsStoreOrderService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * 物流信息定时任务
+ */
+@Slf4j
+@Component("expressTask")
+public class ExpressTask {
+
+    @Autowired
+    private IExpressService expressService;
+    /**
+     * 推送物流信息到快递鸟定时任务
+     */
+    public void subscribeExpress(){
+        long startTime = System.currentTimeMillis();
+        log.info("定时任务【推送物流信息到快递鸟】开始执行, 开始时间: {}", startTime);
+
+        try {
+            expressService.subscribeExpress();
+            log.info("定时任务【推送物流信息到快递鸟】执行成功");
+        } catch (Exception e) {
+            log.error("定时任务【推送物流信息到快递鸟】执行失败, 异常信息: {}", e.getMessage(), e);
+            throw e;
+        } finally {
+            long endTime = System.currentTimeMillis();
+            long costTime = endTime - startTime;
+            log.info("定时任务【推送物流信息到快递鸟】执行结束, 结束时间: {}, 耗时: {}ms", endTime, costTime);
+        }
+    }
+
+}

+ 150 - 141
fs-admin/src/main/java/com/fs/task/StoreTask.java

@@ -50,6 +50,8 @@ import com.fs.store.vo.FsStoreOrderVO;
 import com.fs.store.vo.FsUserShareVO;
 import com.fs.system.service.ISysConfigService;
 import com.sun.media.sound.SF2GlobalRegion;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang.ObjectUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.ibatis.annotations.Param;
 import org.slf4j.Logger;
@@ -75,9 +77,8 @@ import static com.fs.store.constants.StoreConstants.DELIVERY;
  * @author fs
  */
 @Component("storeTask")
-public class StoreTask
-{
-    Logger logger =  LoggerFactory.getLogger(StoreTask.class);
+public class StoreTask {
+    Logger logger = LoggerFactory.getLogger(StoreTask.class);
     @Autowired
     private RedisTemplate redisTemplate;
     @Autowired
@@ -115,11 +116,10 @@ public class StoreTask
     @Autowired
     private ApplicationEventPublisher publisher;
 
-    public void tt()
-    {
-        ErpGoodsStockQueryRequert request=new ErpGoodsStockQueryRequert();
+    public void tt() {
+        ErpGoodsStockQueryRequert request = new ErpGoodsStockQueryRequert();
         request.setBarcode("105201");
-        ErpGoodsStockQueryResponse response=goodsService.getGoodsStock(request);
+        ErpGoodsStockQueryResponse response = goodsService.getGoodsStock(request);
         ErpGoodsQueryRequert erpGoodsQueryRequert = new ErpGoodsQueryRequert();
         erpGoodsQueryRequert.setCode("105201");
         ErpGoodsQueryResponse goods = goodsService.getGoods(erpGoodsQueryRequert);
@@ -129,26 +129,33 @@ public class StoreTask
     }
 
     //每5分钟执行一次
-    public void deliveryOp()
-    {
-        Set<String> orders=redisTemplate.keys(DELIVERY+":*");
-        for(String extndOrderId:orders){
-            String orderCode=(String)redisTemplate.opsForValue().get(extndOrderId);
-            ErpOrderQueryRequert request=new ErpOrderQueryRequert();
-            String[] extendOrder=extndOrderId.split(":");
+    public void deliveryOp() {
+        Set<String> orders = redisTemplate.keys(DELIVERY + ":*");
+        for (String extndOrderId : orders) {
+            String orderCode = (String) redisTemplate.opsForValue().get(extndOrderId);
+            ErpOrderQueryRequert request = new ErpOrderQueryRequert();
+            String[] extendOrder = extndOrderId.split(":");
             request.setCode(extendOrder[1]);
-            ErpOrderQueryResponse response=erpOrderService.getOrder(request);
-            if(response.getOrders()!=null&&response.getOrders().size()>0){
-                for(ErpOrderQuery orderQuery : response.getOrders()){
-                    if(orderQuery.getDeliverys()!=null&&orderQuery.getDeliverys().size()>0){
-                        for(ErpDeliverys delivery:orderQuery.getDeliverys()){
-                            if(delivery.getDelivery()&&StringUtils.isNotEmpty(delivery.getMail_no())){
-                                //更新商订单状态 删除REDIS
-                                orderService.deliveryOrder(orderCode,delivery.getMail_no(),delivery.getExpress_code(),delivery.getExpress_name());
-                                redisCache.deleteObject(DELIVERY+":"+extendOrder[1]);
+            ErpOrderQueryResponse response = erpOrderService.getOrder(request);
+            if (CollectionUtils.isNotEmpty(response.getOrders())) {
+                for (ErpOrderQuery orderQuery : response.getOrders()) {
+                    if (CollectionUtils.isNotEmpty(orderQuery.getDeliverys())) {
+                        // 部分发货或者全部发货
+                        if (ObjectUtils.equals(orderQuery.getDelivery_state(), 1) || ObjectUtils.equals(orderQuery.getDelivery_state(), 2)) {
+                            // 订单状态变更
+                            FsStoreOrder order = fsStoreOrderMapper.selectFsStoreOrderByOrderCode(orderCode);
+                            orderStatusService.create(order.getId(), OrderLogEnum.DELIVERY_GOODS.getValue(),
+                                    OrderLogEnum.DELIVERY_GOODS.getDesc());
+                            //更新商订单状态 删除REDIS
+                            redisCache.deleteObject(DELIVERY + ":" + extendOrder[1]);
+
+                            for (ErpDeliverys delivery : orderQuery.getDeliverys()) {
+                                if (delivery.getDelivery()) {
+                                    orderService.deliveryOrder(orderCode, delivery.getMail_no(),
+                                            delivery.getExpress_code(), delivery.getExpress_name());
+                                }
                             }
                         }
-
                     }
                 }
             }
@@ -160,11 +167,12 @@ public class StoreTask
     FsUserTuiMoneyRankMapper fsUserTuiMoneyRankMapper;
 
     private FsUserAddressMapper addressMapper;
-    public void addUserTuiMoneyRank(){
+
+    public void addUserTuiMoneyRank() {
         List<FsUserShareVO> fsUserShareVOS1 = fsUserTuiMoneyRankMapper.selectFsUserTuiMoneyRankByType(1);
         fsUserTuiMoneyRankMapper.deleteFsUserTuiMoneyRankByType(1);
-        Long id=1L;
-        int rank=1;
+        Long id = 1L;
+        int rank = 1;
         for (FsUserShareVO vo : fsUserShareVOS1) {
             FsUserTuiMoneyRank userRank = new FsUserTuiMoneyRank();
             userRank.setAvatar(vo.getAvatar());
@@ -183,7 +191,7 @@ public class StoreTask
 
         List<FsUserShareVO> fsUserShareVOS2 = fsUserTuiMoneyRankMapper.selectFsUserTuiMoneyRankByType(2);
         fsUserTuiMoneyRankMapper.deleteFsUserTuiMoneyRankByType(2);
-        rank=1;
+        rank = 1;
         for (FsUserShareVO vo : fsUserShareVOS2) {
             FsUserTuiMoneyRank userRank = new FsUserTuiMoneyRank();
             userRank.setAvatar(vo.getAvatar());
@@ -200,7 +208,7 @@ public class StoreTask
         }
         List<FsUserShareVO> fsUserShareVOS3 = fsUserTuiMoneyRankMapper.selectFsUserTuiMoneyRankByType(3);
         fsUserTuiMoneyRankMapper.deleteFsUserTuiMoneyRankByType(3);
-        rank=1;
+        rank = 1;
         for (FsUserShareVO vo : fsUserShareVOS3) {
             FsUserTuiMoneyRank userRank = new FsUserTuiMoneyRank();
             userRank.setAvatar(vo.getAvatar());
@@ -227,25 +235,24 @@ public class StoreTask
     @Autowired
     private IFsStoreProductGroupService storeProductGroupService;
 
-    public void storeProdUpdateCostPrice()
-    {
-        String json=configService.selectConfigByKey("store.config");
-        StoreConfig config=JSONUtil.toBean(json,StoreConfig.class);
+    public void storeProdUpdateCostPrice() {
+        String json = configService.selectConfigByKey("store.config");
+        StoreConfig config = JSONUtil.toBean(json, StoreConfig.class);
         List<FsStoreProductAttrValue> values = fsStoreProductAttrValueMapper.selectFsStoreProductAttrValueList(new FsStoreProductAttrValue());
-        int i=0;
+        int i = 0;
         for (FsStoreProductAttrValue value : values) {
             try {
-                if (StringUtils.isNotEmpty(value.getBarCode())){
+                if (StringUtils.isNotEmpty(value.getBarCode())) {
                     ErpGoodsQueryRequert query = new ErpGoodsQueryRequert();
                     query.setCode(value.getBarCode());
                     ErpGoodsQueryResponse goods = erpGoodsService.getGoods(query);
                     List<ErpGoods> items = goods.getItems();
-                    if (items!=null&&items.size()>0){
+                    if (items != null && items.size() > 0) {
                         ErpGoods erpGoods = items.get(0);
                         BigDecimal salesPrice = erpGoods.getSales_price();
-                        if (salesPrice!=null&&salesPrice.compareTo(BigDecimal.ZERO) != 0){
+                        if (salesPrice != null && salesPrice.compareTo(BigDecimal.ZERO) != 0) {
                             BigDecimal divide = salesPrice.multiply(new BigDecimal(config.getSalesPriceRate())).divide(new BigDecimal("100"));
-                            logger.info("商品id"+value.getId()+"商品成本:"+salesPrice+"代理价"+divide);
+                            logger.info("商品id" + value.getId() + "商品成本:" + salesPrice + "代理价" + divide);
                             FsStoreProductAttrValue va = new FsStoreProductAttrValue();
                             va.setCost(salesPrice);
                             va.setPrice(divide);
@@ -254,28 +261,27 @@ public class StoreTask
                             i++;
                         }
                     }
-                }else
-                if(StringUtils.isNotEmpty(value.getGroupBarCode())){
-                    FsStoreProductGroup group=storeProductGroupService.selectFsStoreProductGroupByBarCode(value.getGroupBarCode());
-                    if(group!=null){
-                        JSONArray jsonArray=JSONUtil.parseArray(group.getProducts());
-                        List<StoreProductGroupDTO> productGroupDTOS=JSONUtil.toList(jsonArray, StoreProductGroupDTO.class);
-                        if(productGroupDTOS!=null){
-                            for(StoreProductGroupDTO dto:productGroupDTOS){
-                                FsStoreProductAttrValue attrValue=fsStoreProductAttrValueMapper.selectFsStoreProductAttrValueById(dto.getId());
+                } else if (StringUtils.isNotEmpty(value.getGroupBarCode())) {
+                    FsStoreProductGroup group = storeProductGroupService.selectFsStoreProductGroupByBarCode(value.getGroupBarCode());
+                    if (group != null) {
+                        JSONArray jsonArray = JSONUtil.parseArray(group.getProducts());
+                        List<StoreProductGroupDTO> productGroupDTOS = JSONUtil.toList(jsonArray, StoreProductGroupDTO.class);
+                        if (productGroupDTOS != null) {
+                            for (StoreProductGroupDTO dto : productGroupDTOS) {
+                                FsStoreProductAttrValue attrValue = fsStoreProductAttrValueMapper.selectFsStoreProductAttrValueById(dto.getId());
                                 Integer count = dto.getCount();
                                 String barCode = attrValue.getBarCode();
                                 ErpGoodsQueryRequert query = new ErpGoodsQueryRequert();
                                 query.setCode(barCode);
                                 ErpGoodsQueryResponse goods = erpGoodsService.getGoods(query);
                                 List<ErpGoods> items = goods.getItems();
-                                if (items!=null&&items.size()>0){
+                                if (items != null && items.size() > 0) {
                                     ErpGoods erpGoods = items.get(0);
                                     BigDecimal salesPrice = erpGoods.getSales_price();
-                                    if (salesPrice!=null&&salesPrice.compareTo(BigDecimal.ZERO) != 0){
-                                        salesPrice=salesPrice.multiply(new BigDecimal(count));
+                                    if (salesPrice != null && salesPrice.compareTo(BigDecimal.ZERO) != 0) {
+                                        salesPrice = salesPrice.multiply(new BigDecimal(count));
                                         BigDecimal divide = salesPrice.multiply(new BigDecimal(config.getSalesPriceRate())).divide(new BigDecimal("100"));
-                                        logger.info("商品id"+value.getId()+"商品成本:"+salesPrice+"代理价"+salesPrice);
+                                        logger.info("商品id" + value.getId() + "商品成本:" + salesPrice + "代理价" + salesPrice);
                                         FsStoreProductAttrValue va = new FsStoreProductAttrValue();
                                         va.setCost(salesPrice);
                                         va.setAgentPrice(divide);
@@ -290,34 +296,32 @@ public class StoreTask
                     }
 
                 }
-            }catch (Exception e){
-                logger.info("商品更新成本价错误:"+value.getId());
+            } catch (Exception e) {
+                logger.info("商品更新成本价错误:" + value.getId());
             }
 
 
-
         }
-        logger.info("更新商品成本价:"+i);
+        logger.info("更新商品成本价:" + i);
 
 
     }
-    public void couponOp()
-    {
+
+    public void couponOp() {
         couponUserService.updateFsCouponByExpire();
 
     }
 
 
     //退款自动处理 24小时未审核自动审核通过 每小时执行一次
-    public void refundOp()
-    {
+    public void refundOp() {
         //获取所有退款申请
-        List<FsStoreAfterSales> list=afterSalesService.selectFsStoreAfterSalesByDoAudit();
-        if(list!=null){
-            for(FsStoreAfterSales afterSales:list){
+        List<FsStoreAfterSales> list = afterSalesService.selectFsStoreAfterSalesByDoAudit();
+        if (list != null) {
+            for (FsStoreAfterSales afterSales : list) {
                 //仅退款
-                if(afterSales.getServiceType().equals(0)){
-                    FsStoreAfterSalesAudit1Param audit1Param=new FsStoreAfterSalesAudit1Param();
+                if (afterSales.getServiceType().equals(0)) {
+                    FsStoreAfterSalesAudit1Param audit1Param = new FsStoreAfterSalesAudit1Param();
                     audit1Param.setSalesId(afterSales.getId());
                     audit1Param.setOperator("平台");
                     afterSalesService.audit1(audit1Param);
@@ -328,11 +332,10 @@ public class StoreTask
 
 
     //每天执行一次
-    public void userMoneyOp()
-    {
-        List<FsStoreOrder> list=orderService.selectFsStoreOrderListByFinish7Day();
-        if(list!=null){
-            for(FsStoreOrder order:list){
+    public void userMoneyOp() {
+        List<FsStoreOrder> list = orderService.selectFsStoreOrderListByFinish7Day();
+        if (list != null) {
+            for (FsStoreOrder order : list) {
                 userService.addMoney(order);
             }
         }
@@ -340,52 +343,54 @@ public class StoreTask
 
 
     //每30秒执行一次
-    public void orderItemSyncOp(){
+    public void orderItemSyncOp() {
         List<FsStoreOrder> list = fsStoreOrderService.selectFsStoreOrderItemJson();
-        for(FsStoreOrder storeOrder:list){
-            FsStoreOrderItem parmOrderItem=new FsStoreOrderItem();
+        for (FsStoreOrder storeOrder : list) {
+            FsStoreOrderItem parmOrderItem = new FsStoreOrderItem();
             parmOrderItem.setOrderId(storeOrder.getId());
-            List<FsStoreOrderItem> listOrderItem=storeOrderItemService.selectFsStoreOrderItemList(parmOrderItem);
-            if(listOrderItem.size()>0){
-                String itemJson= JSONUtil.toJsonStr(listOrderItem);
+            List<FsStoreOrderItem> listOrderItem = storeOrderItemService.selectFsStoreOrderItemList(parmOrderItem);
+            if (listOrderItem.size() > 0) {
+                String itemJson = JSONUtil.toJsonStr(listOrderItem);
                 storeOrder.setItemJson(itemJson);
                 fsStoreOrderMapper.uploadItemJson(storeOrder);
             }
         }
     }
 
-    public void returnDeliveryId(){
+    public void returnDeliveryId() {
         List<String> list = fsStoreOrderMapper.selectErpCode();
         for (String s : list) {
             ErpOrderQueryRequert request = new ErpOrderQueryRequert();
             request.setCode(s);
             ErpOrderQueryResponse response = erpOrderService.getOrder(request);
-            if(response.getOrders()!=null&&response.getOrders().size()>0){
-                    for(ErpOrderQuery orderQuery : response.getOrders()){
-                        if(orderQuery.getDeliverys()!=null&&orderQuery.getDeliverys().size()>0){
-                            for(ErpDeliverys delivery:orderQuery.getDeliverys()){
-                                if(delivery.getDelivery()&&StringUtils.isNotEmpty(delivery.getMail_no())){
-                                    FsStoreOrder order = new FsStoreOrder();
-                                    order.setExtendOrderId(s);
-                                    order.setDeliveryId(delivery.getMail_no());
-                                    order.setStatus(2);
-                                    fsStoreOrderMapper.updateDelivery(order);
-                                }
+            if (response.getOrders() != null && response.getOrders().size() > 0) {
+                for (ErpOrderQuery orderQuery : response.getOrders()) {
+                    if (orderQuery.getDeliverys() != null && orderQuery.getDeliverys().size() > 0) {
+                        for (ErpDeliverys delivery : orderQuery.getDeliverys()) {
+                            if (delivery.getDelivery() && StringUtils.isNotEmpty(delivery.getMail_no())) {
+                                FsStoreOrder order = new FsStoreOrder();
+                                order.setExtendOrderId(s);
+                                order.setDeliveryId(delivery.getMail_no());
+                                order.setStatus(2);
+                                fsStoreOrderMapper.updateDelivery(order);
                             }
                         }
                     }
                 }
+            }
 
 
         }
 
     }
+
     @Autowired
     private IFsExpressService expressService;
 
-    public void changeStatus(){
-        List<Long> list  = fsStoreOrderMapper.selectOrderId();
-        for (Long orderId : list){
+    @Deprecated
+    public void changeStatus() {
+        List<Long> list = fsStoreOrderMapper.selectOrderId();
+        for (Long orderId : list) {
             FsStoreOrder order = fsStoreOrderMapper.selectFsStoreOrderById(orderId);
             String lastFourNumber = "";
             if (order.getDeliverySn().equals(ShipperCodeEnum.SF.getValue())) {
@@ -394,8 +399,8 @@ public class StoreTask
                     lastFourNumber = StrUtil.sub(lastFourNumber, lastFourNumber.length(), -4);
                 }
             }
-            ExpressInfoDTO dto=expressService.getExpressInfo(order.getOrderCode(),order.getDeliverySn(),order.getDeliveryId(),lastFourNumber);
-            FsStoreOrder map=new FsStoreOrder();
+            ExpressInfoDTO dto = expressService.getExpressInfo(order.getOrderCode(), order.getDeliverySn(), order.getDeliveryId(), lastFourNumber);
+            FsStoreOrder map = new FsStoreOrder();
             map.setDeliveryStatus(Integer.parseInt(dto.getState()));
             map.setId(order.getId());
             map.setDeliveryType(dto.getStateEx());
@@ -410,11 +415,11 @@ public class StoreTask
     @Autowired
     private ICompanyService companyService;
 
-    public void subCompanyMoney(){
+    public void subCompanyMoney() {
         List<Long> list = paymentMapper.selectPaymentIds();
-        for (Long paymentId : list){
-            FsStorePayment payment=fsStorePaymentService.selectFsStorePaymentById(paymentId);
-            if(payment.getCompanyId()!=null&&payment.getCompanyId()>0){
+        for (Long paymentId : list) {
+            FsStorePayment payment = fsStorePaymentService.selectFsStorePaymentById(paymentId);
+            if (payment.getCompanyId() != null && payment.getCompanyId() > 0) {
                 companyService.subCompanyPaymentMoney(payment);
             }
         }
@@ -424,21 +429,19 @@ public class StoreTask
     private FsStoreOrderItemMapper itemMapper;
 
     public void updateOrderItem() throws ParseException {
-        List <Long> ids = itemMapper.selectOrderIdByNoErp();
-        for (Long id:ids){
+        List<Long> ids = itemMapper.selectOrderIdByNoErp();
+        for (Long id : ids) {
             fsStoreOrderService.createOmsOrder(id);
         }
     }
 
 
-
     //每天执行一次
-    public void syncExpress()
-    {
-        List<Long> ids =fsStoreOrderMapper.selectSyncExpressIds();
+    public void syncExpress() {
+        List<Long> ids = fsStoreOrderMapper.selectSyncExpressIds();
 
         for (Long id : ids) {
-            FsStoreOrderExpressEditParam param =new FsStoreOrderExpressEditParam();
+            FsStoreOrderExpressEditParam param = new FsStoreOrderExpressEditParam();
             param.setOrderId(id);
             fsStoreOrderService.syncExpress(param);
         }
@@ -446,21 +449,21 @@ public class StoreTask
     }
 
     public void returnPayStatus() {
-        List<String> ids =fsStorePaymentMapper.selectPayStatusIds();
+        List<String> ids = fsStorePaymentMapper.selectPayStatusIds();
         for (String id : ids) {
             OrderQueryDTO o = new OrderQueryDTO();
             o.setUpOrderId(id);
             OrderResult orderResult = ybPayService.getOrder(o);
-            if ("0".equals(orderResult.getState())){
-                String[] order=orderResult.getLowOrderId().split("-");
-                if(orderResult.getStatus().equals("100")){
+            if ("0".equals(orderResult.getState())) {
+                String[] order = orderResult.getLowOrderId().split("-");
+                if (orderResult.getStatus().equals("100")) {
                     switch (order[0]) {
                         case "store":
-                            orderService.payConfirm(1,null,order[1], o.getUpOrderId(),orderResult.getBankTrxId(),orderResult.getBankOrderId());
+                            orderService.payConfirm(1, null, order[1], o.getUpOrderId(), orderResult.getBankTrxId(), orderResult.getBankOrderId());
                         case "store_remain":
-                            orderService.payRemainConfirm( order[1], o.getUpOrderId(),orderResult.getBankTrxId(),orderResult.getBankOrderId());
+                            orderService.payRemainConfirm(order[1], o.getUpOrderId(), orderResult.getBankTrxId(), orderResult.getBankOrderId());
                         case "payment":
-                            fsStorePaymentService.payConfirm(order[1],o.getUpOrderId(),orderResult.getBankTrxId(),orderResult.getBankOrderId());
+                            fsStorePaymentService.payConfirm(order[1], o.getUpOrderId(), orderResult.getBankTrxId(), orderResult.getBankOrderId());
                     }
 
                 }
@@ -470,9 +473,8 @@ public class StoreTask
 
     }
 
-    public void AddTuiMoney()
-    {
-        List<Long> ids =fsStoreOrderMapper.selectAddTuiMoney();
+    public void AddTuiMoney() {
+        List<Long> ids = fsStoreOrderMapper.selectAddTuiMoney();
         for (Long id : ids) {
             FsStoreOrderAddTuiMoneyParam param = new FsStoreOrderAddTuiMoneyParam();
             param.setOrderId(id);
@@ -484,76 +486,83 @@ public class StoreTask
     @Autowired
     private IFsStoreAfterSalesService fsStoreAfterSalesService;
 
-    public void selectPayMoneyLessOne(){
+    public void selectPayMoneyLessOne() {
         List<FsStoreOrder> list = fsStoreOrderMapper.selectPayMoneyLessOne();
-        for (FsStoreOrder order : list){
+        for (FsStoreOrder order : list) {
             FsStoreAfterSalesParam param = new FsStoreAfterSalesParam();
             param.setOrderCode(order.getOrderCode());
             param.setServiceType(0);
             param.setRefundAmount(order.getPayMoney());
             param.setReasons("超时未处理,自动申请退款");
             List<FsStoreAfterSalesProductParam> productParams = new ArrayList<>();
-            List <FsStoreOrderItem> items = fsStoreOrderMapper.selectOrderItem(order.getId());
-            for (FsStoreOrderItem item : items){
+            List<FsStoreOrderItem> items = fsStoreOrderMapper.selectOrderItem(order.getId());
+            for (FsStoreOrderItem item : items) {
                 FsStoreAfterSalesProductParam param1 = new FsStoreAfterSalesProductParam();
                 param1.setProductId(item.getProductId());
                 param1.setNum(item.getNum());
                 productParams.add(param1);
             }
             param.setProductList(productParams);
-            fsStoreAfterSalesService.autoApplyForAfterSales(order.getUserId(),param);
+            fsStoreAfterSalesService.autoApplyForAfterSales(order.getUserId(), param);
         }
     }
 
 
-
     @Autowired
     private CompanyUserMapper companyUserMapper;
-    public void updateCompanyUserStatus()
-    {
+
+    public void updateCompanyUserStatus() {
         CompanyUser user = new CompanyUser();
         user.setStatus("0");
         user.setDelFlag("0");
         List<CompanyUser> companyUsers = companyUserMapper.selectCompanyUserList(user);
         for (CompanyUser companyUser : companyUsers) {
-            if(SecurityUtils.matchesPassword("123456", companyUser.getPassword())){
+            if (SecurityUtils.matchesPassword("123456", companyUser.getPassword())) {
                 companyUser.setStatus("1");
                 companyUserMapper.updateCompanyUser(companyUser);
-                logger.info("密码为123456 停用账号:"+companyUser.getUserId()+":"+companyUser.getNickName());
+                logger.info("密码为123456 停用账号:" + companyUser.getUserId() + ":" + companyUser.getNickName());
             }
         }
     }
 
-    public  void deleteCustomer(){
+    public void deleteCustomer() {
 
     }
+
     @Autowired
     private IFsStoreOrderStatusService orderStatusService;
-    public  void updateExpress(){
+
+    public void updateExpress() {
         List<FsStoreOrder> list = fsStoreOrderMapper.selectUpdateExpress();
-        for (FsStoreOrder order : list){
-                ErpOrderQueryRequert request = new ErpOrderQueryRequert();
-                request.setCode(order.getExtendOrderId());
-                ErpOrderQueryResponse response = erpOrderService.getOrder(request);
-                if(response.getOrders()!=null&&response.getOrders().size()>0){
-                    for(ErpOrderQuery orderQuery : response.getOrders()){
-                        if(orderQuery.getDeliverys()!=null&&orderQuery.getDeliverys().size()>0){
-                            for(ErpDeliverys delivery:orderQuery.getDeliverys()){
-                                if(delivery.getDelivery()&&StringUtils.isNotEmpty(delivery.getMail_no())){
-                                    //更新商订单状态 删除REDIS
-                                    orderService.deliveryOrder(order.getOrderCode(),delivery.getMail_no(),delivery.getExpress_code(),delivery.getExpress_name());
-                                    redisCache.deleteObject(DELIVERY+":"+order.getExtendOrderId());
-                                }
+        for (FsStoreOrder order : list) {
+            ErpOrderQueryRequert request = new ErpOrderQueryRequert();
+            request.setCode(order.getExtendOrderId());
+            ErpOrderQueryResponse response = erpOrderService.getOrder(request);
+            if (CollectionUtils.isNotEmpty(response.getOrders())) {
+                for (ErpOrderQuery orderQuery : response.getOrders()) {
+                    // 部分发货或者全部发货
+                    if (ObjectUtils.equals(orderQuery.getDelivery_state(), 1) || ObjectUtils.equals(orderQuery.getDelivery_state(), 2)) {
+                        // 订单状态变更
+                        orderStatusService.create(order.getId(), OrderLogEnum.DELIVERY_GOODS.getValue(),
+                                OrderLogEnum.DELIVERY_GOODS.getDesc());
+
+                        redisCache.deleteObject(DELIVERY+":"+order.getExtendOrderId());
+
+                        for (ErpDeliverys delivery : orderQuery.getDeliverys()) {
+                            if (delivery.getDelivery()) {
+                                orderService.deliveryOrder(order.getOrderCode(), delivery.getMail_no(),
+                                        delivery.getExpress_code(), delivery.getExpress_name());
                             }
-
                         }
                     }
-
+                }
             }
-
         }
     }
 
 
 
+
+
+
 }

+ 1 - 1
fs-admin/src/main/resources/application.yml

@@ -19,7 +19,7 @@ fs:
 # 开发环境配置
 server:
   # 服务器的HTTP端口,默认为 7011  store 7111
-  port: 7011
+  port: 7015
   servlet:
     # 应用的访问路径
     context-path: /

+ 4 - 1
fs-api/src/main/java/com/fs/app/controller/CommonController.java

@@ -45,8 +45,12 @@ import org.springframework.web.multipart.MultipartFile;
 import java.math.BigDecimal;
 import java.nio.charset.Charset;
 import java.sql.*;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 
 @Api("公共接口")
@@ -571,5 +575,4 @@ public class CommonController extends AppBaseController {
 		return orderService.updateDeliveryItem(notifyDTO);
 	}
 
-
 }

+ 2 - 2
fs-api/src/main/resources/application.yml

@@ -25,7 +25,7 @@ fs:
 # 开发环境配置
 server:
   # 服务器的HTTP端口,默认为 7014  store 7114
-  port: 7014
+  port: 7011
   servlet:
     # 应用的访问路径
     context-path: /
@@ -70,7 +70,7 @@ spring:
     # 国际化资源文件路径
     basename: i18n/messages
   profiles:
-    active: druid
+    active: dev
     include: config
   # 文件上传
   servlet:

+ 14 - 0
fs-common/src/main/java/com/fs/common/utils/PhoneUtils.java

@@ -0,0 +1,14 @@
+package com.fs.common.utils;
+
+import cn.hutool.core.util.StrUtil;
+
+public class PhoneUtils {
+    public static String getLastFourNum(String phone) {
+
+            String lastFourNumber = phone;
+            if (lastFourNumber.length() == 11) {
+                lastFourNumber = StrUtil.sub(lastFourNumber, lastFourNumber.length(), -4);
+            }
+            return lastFourNumber;
+    }
+}

+ 70 - 0
fs-company/src/main/java/com/fs/express/FsStoreDeliversController.java

@@ -0,0 +1,70 @@
+package com.fs.express;
+
+import com.fs.common.core.domain.R;
+import com.fs.store.domain.FsStoreDelivers;
+import com.fs.store.param.FsStoreOrderExpressParam;
+import com.fs.store.service.IFsExpressService;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.List;
+
+/**
+ * 物流信息管理
+ * @author xdd
+ */
+@RestController
+@RequestMapping("/fsStoreDelivers")
+public class FsStoreDeliversController {
+
+    @Autowired
+    private FsStoreDeliversService fsStoreDeliversService;
+
+    @Autowired
+    private IFsExpressService fsExpressService;
+
+
+    /**
+     * 根据ID查询
+     */
+    @GetMapping("/{id}")
+    public R getById(@PathVariable Integer id) {
+        FsStoreDelivers fsStoreDelivers = fsStoreDeliversService.findById(id);
+        return R.ok();
+    }
+    /**
+     * 根据orderId查询
+     */
+    @GetMapping("/getByOrderId/{orderId}")
+    public R getByOrderId(@PathVariable Long orderId) {
+        List<FsStoreDelivers> byOrderId = fsStoreDeliversService.findByOrderId(orderId);
+        return R.ok().put("data",byOrderId);
+    }
+
+    @ApiOperation("物流查询")
+    @PostMapping("/getExpressByDeliverId")
+    public R getExpressByDeliverId(@Validated @RequestBody FsStoreOrderExpressParam param, HttpServletRequest request){
+        return fsExpressService.getExpressByDeliverId(param);
+    }
+
+    /**
+     * 新增
+     */
+    @PostMapping
+    public R create(@RequestBody FsStoreDelivers fsStoreDelivers) {
+        FsStoreDelivers savedFsStoreDelivers = fsStoreDeliversService.save(fsStoreDelivers);
+        return R.ok().put("data",savedFsStoreDelivers);
+    }
+     /**
+     *全部更新
+     */
+    @PutMapping("/{id}")
+    public R update(@PathVariable Long id, @RequestBody FsStoreDelivers fsStoreDelivers) {
+        fsStoreDelivers.setId(id); // Ensure ID is set for update
+        boolean updated = fsStoreDeliversService.update(fsStoreDelivers);
+        return R.ok();
+    }
+}

+ 1 - 1
fs-company/src/main/java/com/fs/qw/config/SocketConfig.java

@@ -5,7 +5,7 @@ import org.springframework.context.annotation.Configuration;
 
 @Configuration
 public class SocketConfig {
-    @Value("${socket.url}")
+//    @Value("${socket.url}")
     private String socketUrl;
     public String getSocketUrl() {
         return socketUrl;

+ 3 - 0
fs-company/src/main/java/com/fs/store/controller/FsStoreOrderController.java

@@ -229,8 +229,11 @@ public class FsStoreOrderController extends BaseController
 
     @PreAuthorize("@ss.hasPermi('store:storeOrder:express')")
     @GetMapping(value = "/getExpress/{id}")
+    @Deprecated
     public R getExpress(@PathVariable("id") Long id)
     {
+        logger.warn("该接口已经停止使用!");
+
         FsStoreOrder order=fsStoreOrderService.selectFsStoreOrderById(id);
         ExpressInfoDTO expressInfoDTO=null;
         if(StringUtils.isNotEmpty(order.getDeliveryId())){

+ 62 - 0
fs-service-system/src/main/java/com/fs/express/FsStoreDeliversService.java

@@ -0,0 +1,62 @@
+package com.fs.express;
+
+
+import com.fs.express.dto.DeliveryDTO;
+import com.fs.store.domain.FsStoreDelivers;
+
+import java.util.List;
+
+/**
+ * 物流信息查询类
+ * @author xdd
+ */
+public interface FsStoreDeliversService {
+
+    /**
+     * 根据ID查询发货信息
+     *
+     * @param id 主键ID
+     * @return 发货信息
+     */
+    FsStoreDelivers findById(Integer id);
+
+    /**
+     * 保存发货信息
+     *
+     * @param fsStoreDelivers 发货信息对象
+     * @return 插入后的发货信息对象(包含自动生成的主键)
+     */
+    FsStoreDelivers save(FsStoreDelivers fsStoreDelivers);
+
+    /**
+     * 更新发货信息
+     *
+     * @param fsStoreDelivers 发货信息对象
+     * @return 更新是否成功
+     */
+    boolean update(FsStoreDelivers fsStoreDelivers);
+     /**
+     * 根据orderId查询
+     * @param orderId 订单id
+     * @return List<FsStoreDelivers>
+     */
+    List<FsStoreDelivers> findByOrderId(Long orderId);
+
+    /**
+     * 签收订单
+     * 获取当前订单下面的所有物流信息,如果都是已签收就更新订单状态
+     * @param orderId 订单id
+     */
+    void finishOrder(Long orderId);
+
+    /**
+     * 同步物流信息
+     * @param orderId 订单号
+     */
+    void syncDeliverInfo(Long orderId);
+
+    FsStoreDelivers findByOrderCodeAndDeliverId(String orderCode, String deliverId);
+
+    void editDeliveryId(FsStoreDelivers deliveryDTO);
+
+}

+ 5 - 0
fs-service-system/src/main/java/com/fs/express/IExpressService.java

@@ -0,0 +1,5 @@
+package com.fs.express;
+
+public interface IExpressService {
+    void subscribeExpress();
+}

+ 18 - 0
fs-service-system/src/main/java/com/fs/express/dto/DeliveryDTO.java

@@ -0,0 +1,18 @@
+package com.fs.express.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class DeliveryDTO implements Serializable {
+
+    /**
+     * 订单id
+     */
+    private Long id;
+    private String deliverySn;
+    private String deliveryId;
+
+}
+

+ 40 - 0
fs-service-system/src/main/java/com/fs/express/dto/ExpressPushRespDTO.java

@@ -0,0 +1,40 @@
+package com.fs.express.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 业务响应结果DTO类
+ * <p>
+ * 该类用于表示业务操作的响应结果,包括更新时间、业务ID、操作是否成功以及失败原因。
+ * </p>
+ *
+ * @author xdd
+ * @version 1.0
+ * @since 2023-10-10
+ */
+@Data
+public class ExpressPushRespDTO implements Serializable {
+
+    /**
+     * 更新时间,格式为 "yyyy-MM-dd HH:mm:ss"
+     */
+    private Date UpdateTime;
+
+    /**
+     * 业务ID
+     */
+    private String EBusinessID;
+
+    /**
+     * 操作是否成功
+     */
+    private Boolean Success;
+
+    /**
+     * 失败原因
+     */
+    private String Reason;
+}

+ 87 - 0
fs-service-system/src/main/java/com/fs/express/enums/TaskStatusEnum.java

@@ -0,0 +1,87 @@
+package com.fs.express.enums;
+
+/**
+ * 任务状态枚举
+ */
+public enum TaskStatusEnum {
+
+    /**
+     * 待处理
+     */
+    PENDING(0, "待处理"),
+
+    /**
+     * 成功
+     */
+    SUCCESS(1, "成功"),
+
+    /**
+     * 失败
+     */
+    FAILED(2, "失败"),
+
+    /**
+     * 正在处理
+     */
+    PROCESSING(3, "正在处理"),
+
+    /**
+     * 已取消
+     */
+    CANCELLED(4, "已取消");
+
+    private final Integer code; // 状态码
+    private final String description; // 状态描述
+
+    /**
+     * 构造方法
+     *
+     * @param code        状态码
+     * @param description 状态描述
+     */
+    TaskStatusEnum(Integer code, String description) {
+        this.code = code;
+        this.description = description;
+    }
+
+    /**
+     * 根据状态码获取枚举值
+     *
+     * @param code 状态码
+     * @return 对应的枚举值,如果没有匹配的则返回 null
+     */
+    public static TaskStatusEnum getByCode(Integer code) {
+        for (TaskStatusEnum status : TaskStatusEnum.values()) {
+            if (status.getCode().equals(code)) {
+                return status;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * 获取状态码
+     *
+     * @return 状态码
+     */
+    public Integer getCode() {
+        return code;
+    }
+
+    /**
+     * 获取状态描述
+     *
+     * @return 状态描述
+     */
+    public String getDescription() {
+        return description;
+    }
+
+    @Override
+    public String toString() {
+        return "TaskStatusEnum{" +
+                "code=" + code +
+                ", description='" + description + '\'' +
+                '}';
+    }
+}

+ 205 - 0
fs-service-system/src/main/java/com/fs/express/http/KdniaoSubscribeHttp.java

@@ -0,0 +1,205 @@
+package com.fs.express.http;
+
+import cn.hutool.http.HttpRequest;
+import cn.hutool.http.HttpResponse;
+import com.alibaba.fastjson.JSON;
+import com.fs.common.config.FSSysConfig;
+import com.fs.express.dto.ExpressPushRespDTO;
+import com.fs.express.http.dto.LogisticsInfoDTO;
+import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.security.MessageDigest;
+import java.util.HashMap;
+import java.util.Map;
+
+
+/**
+ * @技术QQ群: 可登录官网https://www.kdniao.com/右侧查看技术群号
+ * @see: https://kdniao.com/api-follow
+ * @copyright: 深圳市快金数据技术服务有限公司
+ * ID和Key请到官网申请:https://kdniao.com/reg
+ * <p>
+ * <p>
+ * <p>
+ * 轨迹订阅接口
+ * 此接口用于向快递鸟订阅物流轨迹信息。由轨迹订阅接口(RequestType1008)和轨迹推送接口(RequestType101)组成,接入时需要对接二个接口。该功能支持情况需查看技术文档。
+ * 正式地址:https://api.kdniao.com/api/dist
+ * <p>
+ * <p>
+ * 系统级参数
+ * RequestData	   String	R	请求内容为JSON格式 详情可参考接口技术文档:https://www.kdniao.com/documents
+ * EBusinessID	   String	R	用户ID
+ * RequestType	   String	R	请求接口指令
+ * DataSign	       String	R	数据内容签名,加密方法为:把(请求内容(未编码)+ApiKey)进行MD5加密--32位小写,然后Base64编码,最后进行URL(utf-8)编码
+ * DataType	       String	R	DataType=2,请求、返回数据类型均为JSON格式
+ * <p>
+ * <p>
+ * 应用级参数
+ * R-必填(Required),O-可选(Optional),C-报文中该参数在一定条件下可选(Conditional)
+ * Callback	                String(50)	O	用户自定义回传字段
+ * ShipperCode	            String(10)	R	快递公司编码 详细编码参考《快递鸟接口支持快递公司编码.xlsx》
+ * LogisticCode	            String(30)	R	快递单号
+ * CustomerName	            String(50)	C	ShipperCode为SF时必填,对应寄件人/收件人手机号后四位;ShipperCode为其他快递时,可不填或保留字段,不可传值
+ */
+@Component
+@Slf4j
+public class KdniaoSubscribeHttp {
+
+    /**
+     * 用户ID,快递鸟提供,注意保管,不要泄漏
+     * 即用户ID,登录快递鸟官网会员中心获取 https://www.kdniao.com/UserCenter/v4/UserHome.aspx
+     */
+
+    private String EBusinessID;
+    /**
+     * API key,快递鸟提供,注意保管,不要泄漏
+     * 即API key,登录快递鸟官网会员中心获取 https://www.kdniao.com/UserCenter/v4/UserHome.aspx
+     */
+    private String ApiKey;
+    /**
+     * 请求url, 正式环境地址
+     */
+    private String ReqURL;
+
+
+    @Autowired
+    public void setSysConfig(FSSysConfig sysConfig) {
+        this.EBusinessID = sysConfig.getKdnId();
+        this.ApiKey = sysConfig.getKdnKeyId();
+        this.ReqURL = sysConfig.getKdnUrl();
+    }
+
+
+//    public static void main(String[] args) {
+//        try {
+//            KdniaoSubscribeHttp api = new KdniaoSubscribeHttp();
+//            LogisticsInfoDTO payload = new LogisticsInfoDTO();
+//            payload.setCallback("#");
+//            payload.setCustomerName("3432");
+//            payload.setLogisticCode("SF1395044177288");
+//            payload.setShipperCode("SF");
+//            System.out.println(api.subscribeLogistic(payload));
+//        } catch (Exception e) {
+//            e.printStackTrace();
+//        }
+//    }
+
+    /**
+     * 轨迹订阅接口
+     * @param payload
+     * @return
+     * @throws Exception
+     */
+    public ExpressPushRespDTO subscribeLogistic(LogisticsInfoDTO payload) throws Exception {
+        // 组装应用级参数
+//        String RequestData = "{" +
+//                "'Callback':'#'," +
+//                "'ShipperCode':'SF'," +
+//                "'LogisticCode':'SF1395044177288'," +
+//                "'CustomerName':'3432'," +
+//                "}";
+        String RequestData = JSON.toJSONString(payload);
+        // 组装系统级参数
+        Map<String, Object> params = new HashMap<>();
+        params.put("RequestData", urlEncoder(RequestData, "UTF-8"));
+        params.put("EBusinessID", EBusinessID);
+        //免费订阅接口指令1008/在途监控订阅接口指令8008/地图版订阅接口指令8005
+        params.put("RequestType", "8008");
+        String dataSign = encrypt(RequestData, ApiKey, "UTF-8");
+        params.put("DataSign", urlEncoder(dataSign, "UTF-8"));
+        params.put("DataType", "2");
+        // 以form表单形式提交post请求,post请求体中包含了应用级参数和系统级参数
+        String result = sendPost(ReqURL, params);
+        return JSON.parseObject(result, ExpressPushRespDTO.class);
+    }
+
+
+    /**
+     * MD5加密
+     * str 内容
+     * charset 编码方式
+     *
+     * @throws Exception
+     */
+    @SuppressWarnings("unused")
+    private String MD5(String str, String charset) throws Exception {
+        MessageDigest md = MessageDigest.getInstance("MD5");
+        md.update(str.getBytes(charset));
+        byte[] result = md.digest();
+        StringBuffer sb = new StringBuffer(32);
+        for (int i = 0; i < result.length; i++) {
+            int val = result[i] & 0xff;
+            if (val <= 0xf) {
+                sb.append("0");
+            }
+            sb.append(Integer.toHexString(val));
+        }
+        return sb.toString().toLowerCase();
+    }
+
+    /**
+     * base64编码
+     * str 内容
+     * charset 编码方式
+     *
+     * @throws UnsupportedEncodingException
+     */
+    private String base64(String str, String charset) throws UnsupportedEncodingException {
+        String encoded = Base64.encode(str.getBytes(charset));
+        return encoded;
+    }
+
+    @SuppressWarnings("unused")
+    private String urlEncoder(String str, String charset) throws UnsupportedEncodingException {
+        String result = URLEncoder.encode(str, charset);
+        return result;
+    }
+
+    /**
+     * 电商Sign签名生成
+     * content 内容
+     * keyValue ApiKey
+     * charset 编码方式
+     *
+     * @return DataSign签名
+     * @throws UnsupportedEncodingException ,Exception
+     */
+    @SuppressWarnings("unused")
+    private String encrypt(String content, String keyValue, String charset) throws UnsupportedEncodingException, Exception {
+        if (keyValue != null) {
+            return base64(MD5(content + keyValue, charset), charset);
+        }
+        return base64(MD5(content, charset), charset);
+    }
+
+    /**
+     * 使用 Hutool 的 HttpRequest 发送 POST 请求
+     *
+     * @param url    请求的 URL
+     * @param params 请求参数
+     * @return 响应结果
+     */
+    public static String sendPost(String url, Map<String, Object> params) {
+        log.info("开始发送POST请求,URL: {},请求参数: {}", url, params);
+
+        HttpRequest request = HttpRequest.post(url)
+                .header("Content-Type", "application/x-www-form-urlencoded")
+                .header("accept", "*/*")
+                .header("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
+
+        log.info("请求头信息 - ContentType: {},Accept: {},UserAgent: {}",
+                "application/x-www-form-urlencoded", "*/*", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
+
+        HttpResponse response = request.form(params).execute();
+        String responseBody = response.body();
+        log.info("请求完成,URL: {},响应状态码: {},响应内容: {}", url, response.getStatus(), responseBody);
+
+        return responseBody;
+    }
+}
+

+ 51 - 0
fs-service-system/src/main/java/com/fs/express/http/dto/LogisticsInfoDTO.java

@@ -0,0 +1,51 @@
+package com.fs.express.http.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 物流信息订阅快递鸟
+ * <p>
+ * 该类用于表示物流信息的DTO(Data Transfer Object),包含物流相关的核心信息。
+ * </p>
+ *
+ * @author xdd
+ * @version 1.0
+ * @since 2025-02-27
+ */
+@Data
+public class LogisticsInfoDTO implements Serializable {
+
+    /**
+     * 回调地址
+     * <p>
+     * 该字段用于存储回调地址,通常是一个URL,用于接收物流状态的更新。
+     * </p>
+     */
+    private String Callback;
+
+    /**
+     * 快递公司编码
+     * <p>
+     * 该字段用于存储快递公司的唯一编码,例如顺丰快递的编码为SF。
+     * </p>
+     */
+    private String ShipperCode;
+
+    /**
+     * 物流单号
+     * <p>
+     * 该字段用于存储物流单号,是快递公司提供的唯一标识符,用于追踪物流状态。
+     * </p>
+     */
+    private String LogisticCode;
+
+    /**
+     * 客户名称
+     * <p>
+     * 手机号后4位
+     * </p>
+     */
+    private String CustomerName;
+}

+ 71 - 0
fs-service-system/src/main/java/com/fs/express/impl/ExpressServiceImpl.java

@@ -0,0 +1,71 @@
+package com.fs.express.impl;
+
+import com.alibaba.fastjson.JSON;
+import com.fs.express.IExpressService;
+import com.fs.express.dto.ExpressPushRespDTO;
+import com.fs.express.enums.TaskStatusEnum;
+import com.fs.express.http.KdniaoSubscribeHttp;
+import com.fs.express.http.dto.LogisticsInfoDTO;
+import com.fs.store.domain.FsOrderExpressPush;
+import com.fs.store.mapper.FsOrderExpressPushMapper;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.net.URLDecoder;
+import java.util.List;
+
+/**
+ * 物流相关处理
+ */
+@Service
+@Slf4j
+public class ExpressServiceImpl implements IExpressService {
+    @Autowired
+    private FsOrderExpressPushMapper fsOrderExpressPushMapper;
+
+    @Autowired
+    private KdniaoSubscribeHttp kdniaoSubscribeHttp;
+
+    /**
+     * 推送物流信息到快递鸟
+     */
+    @Override
+    public void subscribeExpress() {
+        log.info("开始处理待订阅的物流信息");
+
+        List<FsOrderExpressPush> fsOrderExpressPushes = fsOrderExpressPushMapper.queryPendingData();
+        log.info("查询到待处理的物流信息数量: {}", fsOrderExpressPushes.size());
+
+        for (FsOrderExpressPush fsOrderExpressPush : fsOrderExpressPushes) {
+            log.info("处理物流单号: {}", fsOrderExpressPush.getOrderId());
+            String params = fsOrderExpressPush.getParams();
+            ExpressPushRespDTO expressPushRespDTO = null;
+            try {
+                params = URLDecoder.decode(params, "UTF-8");
+                LogisticsInfoDTO payload = JSON.parseObject(params, LogisticsInfoDTO.class);
+                expressPushRespDTO = kdniaoSubscribeHttp.subscribeLogistic(payload);
+            } catch (Throwable e) {
+                log.error("物流订阅发生异常 - 单号: {}, 错误信息: {}", fsOrderExpressPush.getOrderId(), JSON.toJSONString(e));
+                expressPushRespDTO = new ExpressPushRespDTO();
+                expressPushRespDTO.setSuccess(false);
+                expressPushRespDTO.setReason(JSON.toJSONString(e));
+            }
+
+            fsOrderExpressPush.setResult(JSON.toJSONString(expressPushRespDTO));
+            if(expressPushRespDTO.getSuccess()) {
+                fsOrderExpressPush.setTaskStatus(TaskStatusEnum.SUCCESS.getCode());
+                log.info("物流订阅成功 - 单号: {}", fsOrderExpressPush.getOrderId());
+            } else {
+                fsOrderExpressPush.setTaskStatus(TaskStatusEnum.FAILED.getCode());
+                fsOrderExpressPush.setRetryCount(fsOrderExpressPush.getRetryCount()+1);
+                log.warn("物流订阅失败 - 单号: {}, 重试次数: {}", fsOrderExpressPush.getOrderId(), fsOrderExpressPush.getRetryCount());
+
+            }
+            fsOrderExpressPushMapper.update(fsOrderExpressPush);
+            log.info("更新物流信息 - 单号: {}, 处理结果: {}", fsOrderExpressPush.getOrderId(), JSON.toJSONString(expressPushRespDTO));
+        }
+
+        log.info("物流订阅处理完成");
+    }
+}

+ 160 - 0
fs-service-system/src/main/java/com/fs/express/impl/FsStoreDeliversServiceImpl.java

@@ -0,0 +1,160 @@
+package com.fs.express.impl;
+
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
+import com.fs.common.utils.PhoneUtils;
+import com.fs.express.FsStoreDeliversService;
+import com.fs.express.IExpressService;
+import com.fs.express.dto.DeliveryDTO;
+import com.fs.store.domain.FsStoreDelivers;
+import com.fs.store.domain.FsStoreOrder;
+import com.fs.store.dto.ExpressInfoDTO;
+import com.fs.store.enums.ShipperCodeEnum;
+import com.fs.store.mapper.FsStoreDeliversMapper;
+import com.fs.store.service.IFsExpressService;
+import com.fs.store.service.IFsStoreOrderService;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.LocalDateTime;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * 物流信息查询类
+ * @author xdd
+ */
+@Service
+public class FsStoreDeliversServiceImpl implements FsStoreDeliversService {
+    private static final Logger logger = LoggerFactory.getLogger(FsStoreDeliversServiceImpl.class);
+
+    @Autowired
+    private FsStoreDeliversMapper fsStoreDeliversMapper;
+
+    @Autowired
+    private IFsStoreOrderService orderService;
+
+    @Autowired
+    private IFsExpressService expressService;
+    @Override
+    public FsStoreDelivers findById(Integer id) {
+        return fsStoreDeliversMapper.findById(id);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public FsStoreDelivers save(FsStoreDelivers fsStoreDelivers) {
+        if (fsStoreDelivers.getId() == null) {
+            fsStoreDelivers.setCreateTime(LocalDateTime.now());
+            fsStoreDeliversMapper.insert(fsStoreDelivers);
+
+        }
+        return fsStoreDelivers;
+    }
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean update(FsStoreDelivers fsStoreDelivers)
+    {
+        fsStoreDelivers.setUpdateTime(LocalDateTime.now());
+       return fsStoreDeliversMapper.update(fsStoreDelivers) > 0;
+
+    }
+
+    @Override
+    public List<FsStoreDelivers> findByOrderId(Long orderId) {
+        return fsStoreDeliversMapper.findByOrderId(orderId);
+    }
+
+    @Override
+    public void finishOrder(Long orderId) {
+        List<FsStoreDelivers> byOrderId = fsStoreDeliversMapper.findByOrderId(orderId);
+        Set<Integer> orderStatusSet = byOrderId.stream().map(FsStoreDelivers::getStatus)
+                .collect(Collectors.toSet());
+
+
+        Set<Integer> orderStateExSet = byOrderId.stream().map(FsStoreDelivers::getStateEx)
+                .collect(Collectors.toSet());
+
+        // 如果订单都是已经签收
+        Set<Integer> finishStatusExSet = new HashSet<>();
+        finishStatusExSet.add(301);
+        finishStatusExSet.add(302);
+        finishStatusExSet.add(304);
+        finishStatusExSet.add(311);
+
+        // orderStatusSet 必须都为3
+        if (orderStatusSet.size() == 1 && orderStatusSet.contains(3) && finishStatusExSet.containsAll(orderStateExSet)) {
+            // 订单完成
+            orderService.finishOrder(orderId);
+        }
+    }
+
+    @Override
+    public void syncDeliverInfo(Long orderId) {
+        logger.info("开始同步订单发货信息, 订单ID: {}", orderId);
+        FsStoreOrder order = orderService.selectFsStoreOrderById(orderId);
+
+        if (order == null) {
+            logger.warn("订单不存在,订单ID: {}", orderId);
+            return;
+        }
+        logger.info("查询到订单信息, 订单号: {}", order.getOrderCode());
+        List<FsStoreDelivers> byOrderId = fsStoreDeliversMapper.findByOrderId(orderId);
+        if (byOrderId.isEmpty()) {
+            logger.info("订单没有发货信息, 订单ID: {}", orderId);
+            return;
+        }
+        for (FsStoreDelivers fsStoreDelivers : byOrderId) {
+            if (ObjectUtil.isNotEmpty(fsStoreDelivers.getDeliverId())) {
+                logger.info("开始处理发货单, 发货单ID: {}, 快递单号: {}", fsStoreDelivers.getDeliverId(), fsStoreDelivers.getDeliverSn());
+                String lastFourNumber = "";
+                if (StringUtils.equals(fsStoreDelivers.getDeliverSn(), ShipperCodeEnum.SF.getValue())) {
+                    lastFourNumber = PhoneUtils.getLastFourNum(order.getUserPhone());
+                    logger.info("顺丰快递,获取手机号后四位: {}", lastFourNumber);
+                }
+                ExpressInfoDTO dto = null;
+                try {
+                    // 记录HTTP请求前的信息
+                    logger.info("开始调用快递查询接口, 订单号: {}, 快递公司编码: {}, 快递单号: {}, 手机号后四位: {}",
+                            order.getOrderCode(), fsStoreDelivers.getDeliverId(), fsStoreDelivers.getDeliverSn(), lastFourNumber);
+                    dto = expressService.getExpressInfo(order.getOrderCode(),
+                            fsStoreDelivers.getDeliverSn(), fsStoreDelivers.getDeliverId(), lastFourNumber);
+                    // 假设expressService.getExpressInfo内部进行了HTTP请求,你需要在expressService内部打印更详细的日志
+                    // 这里只记录返回结果
+                    if (ObjectUtil.isNotNull(dto)) {
+                        logger.info("快递查询接口调用成功, 订单号: {}, 快递状态: {}, 扩展状态: {}",
+                                order.getOrderCode(), dto.getState(), dto.getStateEx());
+                        fsStoreDelivers.setStatus(Integer.valueOf(dto.getState()));
+                        fsStoreDelivers.setStateEx(Integer.valueOf(dto.getStateEx()));
+                    } else {
+                        logger.warn("快递查询接口调用成功,但返回结果为空, 订单号: {}", order.getOrderCode());
+                    }
+                } catch (Exception e) {
+                    logger.error("快递查询接口调用失败, 订单号: {}, 快递单号: {}, 错误信息: {}", order.getOrderCode(), fsStoreDelivers.getDeliverSn(), e.getMessage(), e);
+                }
+            } else {
+                logger.info("发货单信息中快递ID为空, 跳过处理, 发货单ID: {}", fsStoreDelivers.getId());
+            }
+        }
+
+        fsStoreDeliversMapper.updateBatch(byOrderId);
+        logger.info("同步订单发货信息完成, 订单ID: {}", orderId);
+    }
+
+    @Override
+    public FsStoreDelivers findByOrderCodeAndDeliverId(String orderCode, String deliverId) {
+        return fsStoreDeliversMapper.findByOrderCodeAndDeliverId(orderCode,deliverId);
+    }
+
+    @Override
+    public void editDeliveryId(FsStoreDelivers deliveryDTO) {
+        fsStoreDeliversMapper.update(deliveryDTO);
+    }
+}

+ 32 - 0
fs-service-system/src/main/java/com/fs/store/domain/FsOrderExpressPush.java

@@ -0,0 +1,32 @@
+package com.fs.store.domain;
+
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+/***
+ * 订阅物流
+ */
+@Data
+public class FsOrderExpressPush {
+    /*** 主键,自增 */
+    private Long id;
+    /*** 订单号,唯一标识订单 */
+    private String orderId;
+    /*** 任务状态:0-待处理,1-成功,2-失败,3-正在处理,4-已取消 */
+    private Integer taskStatus;
+    /*** 重试次数,默认为 0 */
+    private Integer retryCount;
+    /*** 上次执行时间,用于记录任务执行的最后时间 */
+    private LocalDateTime lastExecuteTime;
+    /*** 记录创建时间 */
+    private LocalDateTime createTime;
+    /*** 记录更新时间 */
+    private LocalDateTime updateTime;
+    /*** 调用接口时传入的参数(JSON 格式) */
+    private String params;
+    /*** 调用接口返回的结果(JSON 格式) */
+    private String result;
+    /*** 错误信息(记录失败原因) */
+    private String errorMessage;
+}

+ 100 - 0
fs-service-system/src/main/java/com/fs/store/domain/FsStoreDelivers.java

@@ -0,0 +1,100 @@
+package com.fs.store.domain;
+
+import lombok.Data;
+
+import java.time.LocalDateTime;
+import java.util.Date;
+
+/**
+ * 发货信息表
+ * @author
+ */
+@Data
+public class FsStoreDelivers {
+
+    /**
+     * 主键
+     */
+    private Long id;
+
+    /**
+     * 订单id
+     */
+    private Long orderId;
+
+    /**
+     * 订单号
+     */
+    private String orderCode;
+
+    /**
+     * 快递类型
+     */
+    private String deliverSn;
+
+    /**
+     * 快递名称
+     */
+    private String deliverName;
+
+    /**
+     * 快递号
+     */
+    private String deliverId;
+
+    /**
+     * 发货时间
+     */
+    private LocalDateTime deliverSendTime;
+
+    /**
+     * 创建时间
+     */
+    private LocalDateTime createTime;
+
+    /**
+     * 更新时间
+     */
+    private LocalDateTime updateTime;
+
+    /**
+     * 创建人
+     */
+    private String createBy;
+
+    /**
+     * 更新人
+     */
+    private String updateBy;
+
+    /**
+     * 状态
+     */
+    private Integer status;
+
+    /**
+     *     //增值物流状态:
+     *     //0-暂无轨迹信息
+     *     //1-已揽收
+     *     //2-在途中
+     *     // 201-到达派件城市
+     *     // 202-派件中
+     *     //211-已放入快递柜或驿站
+     *     //3-已签收
+     *     // 301-正常签收
+     *     // 302-派件异常后最终签收
+     *     // 304-代收签收
+     *     // 311-快递柜或驿站签收
+     *     //4-问题件
+     *     // 401-发货无信息
+     *     // 402-超时未签收
+     *     // 403-超时未更新
+     *     // 404-拒收(退件)
+     *     // 405-派件异常
+     *     // 406-退货签收
+     *     // 407-退货未签收
+     *     //412-快递柜或驿站超时未取
+     *     //10-待揽件
+     */
+    private Integer stateEx;
+}

+ 30 - 0
fs-service-system/src/main/java/com/fs/store/mapper/FsOrderExpressPushMapper.java

@@ -0,0 +1,30 @@
+package com.fs.store.mapper;
+
+import com.fs.store.domain.FsOrderExpressPush;
+import org.apache.ibatis.annotations.*;
+
+import java.util.List;
+
+@Mapper
+public interface FsOrderExpressPushMapper {
+
+    @Select("SELECT * FROM fs_order_express_push WHERE id = #{id}")
+    FsOrderExpressPush selectById(Long id);
+
+    @Insert("INSERT INTO fs_order_express_push (order_id, task_status, retry_count, last_execute_time, create_time, update_time, params, result, error_message) " +
+            "VALUES (#{orderId}, #{taskStatus}, #{retryCount}, #{lastExecuteTime}, #{createTime}, #{updateTime}, #{params}, #{result}, #{errorMessage})")
+    @Options(useGeneratedKeys = true, keyProperty = "id")
+    int insert(FsOrderExpressPush fsOrderExpressPush);
+
+    @Update("UPDATE fs_order_express_push SET order_id = #{orderId}, task_status = #{taskStatus}, retry_count = #{retryCount}, " +
+            "last_execute_time = #{lastExecuteTime}, create_time = #{createTime}, update_time = #{updateTime}, " +
+            "params = #{params}, result = #{result}, error_message = #{errorMessage} WHERE id = #{id}")
+    int update(FsOrderExpressPush fsOrderExpressPush);
+
+    @Delete("DELETE FROM fs_order_express_push WHERE id = #{id}")
+    int deleteById(Long id);
+
+    @Select("SELECT * FROM fs_order_express_push where task_status in (0,2) and retry_count < 3")
+    List<FsOrderExpressPush> queryPendingData();
+
+}

+ 105 - 0
fs-service-system/src/main/java/com/fs/store/mapper/FsStoreDeliversMapper.java

@@ -0,0 +1,105 @@
+package com.fs.store.mapper;
+
+import com.fs.store.domain.FsStoreDelivers;
+import org.apache.ibatis.annotations.*;
+
+import java.util.List;
+
+/**
+ * 发货信息Mapper接口
+ *
+ * @date 2022-07-28
+ * @author xdd
+ */
+@Mapper
+public interface FsStoreDeliversMapper {
+
+    /**
+     * 根据ID查询发货信息
+     * @param id 主键ID
+     * @return 发货信息
+     */
+    @Select("SELECT * FROM fs_store_delivers WHERE id = #{id}")
+    FsStoreDelivers findById(@Param("id") Integer id);
+
+    /**
+     * 插入发货信息
+     * @param fsStoreDelivers 发货信息对象
+     * @return 插入影响的行数
+     */
+    @Insert("INSERT INTO fs_store_delivers (order_id, order_code, deliver_sn, deliver_name, deliver_id, deliver_send_time, create_time, update_time, create_by, update_by) " +
+            "VALUES (#{orderId}, #{orderCode}, #{deliverSn}, #{deliverName}, #{deliverId}, #{deliverSendTime}, #{createTime}, #{updateTime}, #{createBy}, #{updateBy})")
+    @Options(useGeneratedKeys = true, keyProperty = "id")
+    int insert(FsStoreDelivers fsStoreDelivers);
+
+    /**
+     * 更新发货信息
+     * @param fsStoreDelivers 发货信息对象
+     * @return 更新影响的行数
+     */
+    @Update("<script>" +
+            "UPDATE fs_store_delivers " +
+            "<set>" +
+            "   <if test='orderId != null'>order_id = #{orderId},</if>" +
+            "   <if test='orderCode != null'>order_code = #{orderCode},</if>" +
+            "   <if test='deliverSn != null'>deliver_sn = #{deliverSn},</if>" +
+            "   <if test='deliverName != null'>deliver_name = #{deliverName},</if>" +
+            "   <if test='deliverId != null'>deliver_id = #{deliverId},</if>" +
+            "   <if test='deliverSendTime != null'>deliver_send_time = #{deliverSendTime},</if>" +
+            "   <if test='updateTime != null'>update_time = #{updateTime},</if>" +
+            "   <if test='updateBy != null'>update_by = #{updateBy},</if>" +
+            "</set>" +
+            "WHERE id = #{id}" +
+            "</script>")
+    int update(FsStoreDelivers fsStoreDelivers);
+      /**
+     * 根据orderId查询发货信息
+     * @param orderId 订单ID
+     * @return 发货信息
+     */
+    @Select("SELECT * FROM fs_store_delivers WHERE order_id = #{orderId}")
+    List<FsStoreDelivers> findByOrderId(@Param("orderId") Long orderId);
+
+    /**
+     * 通过订单号和快递号查询物流信息
+     * @param orderId 订单号
+     * @param deliverId 物流号
+     * @return FsStoreDelivers
+     */
+    @Select("SELECT * FROM fs_store_delivers WHERE order_id = #{orderId} and deliver_id=#{deliverId}")
+    FsStoreDelivers findByOrderIdAndDeliverId(Long orderId, String deliverId);
+    /**
+     * 批量更新发货信息
+     * @param byOrderId 发货信息对象列表
+     * @return 更新影响的行数
+     */
+    @Update("<script>" +
+            "<foreach collection='list' item='item' separator=';'>" +
+            "UPDATE fs_store_delivers " +
+            "<set>" +
+            "   <if test='item.orderId != null'>order_id = #{item.orderId},</if>" +
+            "   <if test='item.orderCode != null'>order_code = #{item.orderCode},</if>" +
+            "   <if test='item.deliverSn != null'>deliver_sn = #{item.deliverSn},</if>" +
+            "   <if test='item.deliverName != null'>deliver_name = #{item.deliverName},</if>" +
+            "   <if test='item.deliverId != null'>deliver_id = #{item.deliverId},</if>" +
+            "   <if test='item.status != null'>status = #{item.status},</if>" +
+            "   <if test='item.stateEx != null'>state_ex = #{item.stateEx},</if>" +
+            "   <if test='item.deliverSendTime != null'>deliver_send_time = #{item.deliverSendTime},</if>" +
+            "   <if test='item.updateTime != null'>update_time = #{item.updateTime},</if>" +
+            "   <if test='item.updateBy != null'>update_by = #{item.updateBy},</if>" +
+            "</set>" +
+            "WHERE id = #{item.id}" +
+            "</foreach>" +
+            "</script>")
+    void updateBatch(List<FsStoreDelivers> byOrderId);
+
+
+    /**
+     * 查询订单号和快递号查询物流信息
+     * @param orderCode 订单号
+     * @param deliverId 物流Id
+     * @return FsStoreDelivers
+     */
+    @Select("SELECT * FROM fs_store_delivers WHERE order_code = #{orderCode} and deliver_id=#{deliverId}")
+    FsStoreDelivers findByOrderCodeAndDeliverId(String orderCode, String deliverId);
+}

+ 5 - 1
fs-service-system/src/main/java/com/fs/store/param/FsStoreOrderExpressParam.java

@@ -6,10 +6,14 @@ import lombok.Data;
 import java.io.Serializable;
 
 @Data
-public class    FsStoreOrderExpressParam implements Serializable
+public class FsStoreOrderExpressParam implements Serializable
 {
     @ApiModelProperty(value = "orderId")
     private Long orderId;
 
+    private String deliverId;
+
+    private String deliverSn;
+
 
 }

+ 10 - 7
fs-service-system/src/main/java/com/fs/store/service/IFsExpressService.java

@@ -7,18 +7,19 @@ import com.fs.api.vo.ExpressVO;
 import com.fs.common.core.domain.R;
 import com.fs.store.domain.FsExpress;
 import com.fs.store.dto.ExpressInfoDTO;
+import com.fs.store.param.FsStoreOrderExpressParam;
 
 /**
  * 快递公司Service接口
- * 
+ *
  * @author fs
  * @date 2022-03-15
  */
-public interface IFsExpressService 
+public interface IFsExpressService
 {
     /**
      * 查询快递公司
-     * 
+     *
      * @param id 快递公司ID
      * @return 快递公司
      */
@@ -26,7 +27,7 @@ public interface IFsExpressService
 
     /**
      * 查询快递公司列表
-     * 
+     *
      * @param fsExpress 快递公司
      * @return 快递公司集合
      */
@@ -34,7 +35,7 @@ public interface IFsExpressService
 
     /**
      * 新增快递公司
-     * 
+     *
      * @param fsExpress 快递公司
      * @return 结果
      */
@@ -42,7 +43,7 @@ public interface IFsExpressService
 
     /**
      * 修改快递公司
-     * 
+     *
      * @param fsExpress 快递公司
      * @return 结果
      */
@@ -50,7 +51,7 @@ public interface IFsExpressService
 
     /**
      * 批量删除快递公司
-     * 
+     *
      * @param ids 需要删除的快递公司ID
      * @return 结果
      */
@@ -78,4 +79,6 @@ public interface IFsExpressService
 
 
     List<ExpressVO> getExpressInfoAPI(ExpressParam param);
+
+    R getExpressByDeliverId(FsStoreOrderExpressParam param);
 }

+ 2 - 0
fs-service-system/src/main/java/com/fs/store/service/IFsStoreOrderService.java

@@ -105,6 +105,7 @@ public interface IFsStoreOrderService
     FsStoreOrder selectFsStoreOrderByOrderCode(String orderCode);
 
     R getExpress(FsStoreOrder order);
+    R getExpressMulti(FsStoreOrder order);
 
     R createUserOrder(FsStoreOrderCreateUserParam param);
 
@@ -195,4 +196,5 @@ public interface IFsStoreOrderService
     int uploadItemJson(FsStoreOrder order);
 
     ExpressResultDTO updateDeliveryItem(ExpressNotifyDTO notifyDTO);
+
 }

+ 71 - 3
fs-service-system/src/main/java/com/fs/store/service/impl/FsExpressServiceImpl.java

@@ -2,27 +2,40 @@ package com.fs.store.service.impl;
 
 import java.net.URLEncoder;
 import java.security.MessageDigest;
+import java.time.LocalDateTime;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.http.HttpUtil;
 import cn.hutool.json.JSONUtil;
+import com.alibaba.fastjson.JSON;
 import com.fs.api.param.ExpressParam;
 import com.fs.api.vo.ExpressVO;
 import com.fs.common.config.FSSysConfig;
 import com.fs.common.core.domain.R;
 import com.fs.common.exception.CustomException;
 import com.fs.common.utils.DateUtils;
+import com.fs.common.utils.PhoneUtils;
+import com.fs.express.enums.TaskStatusEnum;
+import com.fs.store.domain.FsOrderExpressPush;
+import com.fs.store.domain.FsStoreDelivers;
 import com.fs.store.domain.FsStoreOrder;
 import com.fs.store.dto.ExpressAddressDTO;
 import com.fs.store.dto.ExpressAddressDataDTO;
 import com.fs.store.dto.ExpressInfoDTO;
 import com.fs.store.dto.TracesDTO;
 import com.fs.store.enums.ShipperCodeEnum;
+import com.fs.store.mapper.FsOrderExpressPushMapper;
+import com.fs.store.mapper.FsStoreDeliversMapper;
 import com.fs.store.mapper.FsStoreOrderMapper;
+import com.fs.store.param.FsStoreOrderExpressParam;
+import com.fs.store.service.IFsStoreOrderService;
+import com.hc.openapi.tool.util.ObjectUtils;
+import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -30,6 +43,8 @@ import org.springframework.stereotype.Service;
 import com.fs.store.mapper.FsExpressMapper;
 import com.fs.store.domain.FsExpress;
 import com.fs.store.service.IFsExpressService;
+import org.springframework.transaction.annotation.Propagation;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.Base64Utils;
 
 /**
@@ -50,6 +65,19 @@ public class FsExpressServiceImpl implements IFsExpressService
     private FsStoreOrderMapper fsStoreOrderMapper;
     @Autowired
     private FSSysConfig sysConfig;
+
+    @Autowired
+    private FsOrderExpressPushMapper fsOrderExpressPushMapper;
+
+    @Autowired
+    private IFsStoreOrderService orderService;
+
+    @Autowired
+    private IFsExpressService expressService;
+    @Autowired
+    private FsStoreDeliversMapper fsStoreDeliversMapper;
+
+
     /**
      * 查询快递公司
      *
@@ -171,10 +199,11 @@ public class FsExpressServiceImpl implements IFsExpressService
     }
 
     @Override
+    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
     public void subscribeEspress(String orderCode, String deliverySn, String deliveryId, String userPhone) {
         //处理顺丰查询轨迹需手机号码后4位
         String requestData;
-        if (deliverySn.equals(ShipperCodeEnum.SF.getValue())) {
+        if (ObjectUtils.equals(deliverySn,ShipperCodeEnum.SF.getValue())) {
             requestData = "{'OrderCode':'" + orderCode + "','ShipperCode':'" + deliverySn + "','LogisticCode':'" + deliveryId + "','CustomerName':'" + userPhone + "'}";
         } else {
             requestData = "{'OrderCode':'" + orderCode + "','ShipperCode':'" + deliverySn + "','LogisticCode':'" + deliveryId + "'}";
@@ -188,9 +217,15 @@ public class FsExpressServiceImpl implements IFsExpressService
             String dataSign = encrypt(requestData, sysConfig.getKdnKeyId().trim(), "UTF-8");
             params.put("DataSign", URLEncoder.encode(dataSign, "UTF-8"));
             params.put("DataType", "2");
-            String result = HttpUtil.post(sysConfig.getKdnSubscribeUrl().trim(), params);
-            logger.info("订阅物流:"+result);
 
+            FsOrderExpressPush fsOrderExpressPush = new FsOrderExpressPush();
+            fsOrderExpressPush.setOrderId(orderCode);
+            fsOrderExpressPush.setParams(JSON.toJSONString(params));
+            fsOrderExpressPush.setCreateTime(LocalDateTime.now());
+            fsOrderExpressPush.setUpdateTime(LocalDateTime.now());
+            fsOrderExpressPush.setRetryCount(0);
+            fsOrderExpressPush.setTaskStatus(TaskStatusEnum.PENDING.getCode());
+            fsOrderExpressPushMapper.insert(fsOrderExpressPush);
         } catch (Exception e) {
             throw  new CustomException(e.getMessage());
         }
@@ -231,6 +266,7 @@ public class FsExpressServiceImpl implements IFsExpressService
 
     @Override
     public List<ExpressVO> getExpressInfoAPI(ExpressParam param) {
+        //TODO 需要修改
         FsStoreOrder order=fsStoreOrderMapper.selectFsStoreOrderByDeliveryId(param.getPackageno());
         if(order!=null){
 
@@ -282,6 +318,38 @@ public class FsExpressServiceImpl implements IFsExpressService
         return null;
 
     }
+    @Override
+    public R getExpressByDeliverId(FsStoreOrderExpressParam param) {
+        // 添加日志 - 开始
+        Logger logger = LoggerFactory.getLogger(this.getClass());
+        logger.info("查询物流信息开始,参数:{}", param);
+        FsStoreOrder fsStoreOrder = orderService.selectFsStoreOrderById(param.getOrderId());
+        // 添加日志 - 订单信息
+        logger.info("查询到订单信息:{}", fsStoreOrder);
+        //顺丰轨迹查询处理
+        String lastFourNumber = "";
+        if (StringUtils.equals(param.getDeliverSn(),ShipperCodeEnum.SF.getValue())) {
+            lastFourNumber = PhoneUtils.getLastFourNum(fsStoreOrder.getUserPhone());
+            // 添加日志 - 顺丰单号
+            logger.info("顺丰单号处理,获取用户手机号后四位:{}", lastFourNumber);
+        }
+        ExpressInfoDTO dto = null;
+        try {
+            dto = expressService.getExpressInfo(fsStoreOrder.getOrderCode(),
+                    param.getDeliverSn(),
+                    param.getDeliverId(),
+                    lastFourNumber);
+            // 添加日志 - 成功获取物流信息
+            logger.info("成功获取物流信息,订单号:{},物流单号:{}, 快递公司ID:{}, 返回数据:{}", fsStoreOrder.getOrderCode(), param.getDeliverSn(),param.getDeliverId(), dto);
+        } catch (Exception e) {
+            // 添加日志 - 异常
+            logger.error("获取物流信息异常,订单号:{},物流单号:{},快递公司ID:{}", fsStoreOrder.getOrderCode(), param.getDeliverSn(), param.getDeliverId(), e);
+        }
+        // 添加日志 - 结束
+        logger.info("查询物流信息结束,订单号:{}", param.getOrderId());
+
+        return R.ok().put("data",dto);
+    }
 
     /**
      * Sign签名生成

+ 131 - 112
fs-service-system/src/main/java/com/fs/store/service/impl/FsStoreOrderServiceImpl.java

@@ -32,6 +32,7 @@ import com.fs.common.event.TemplateEvent;
 import com.fs.common.event.TemplateListenEnum;
 import com.fs.common.exception.CustomException;
 import com.fs.common.utils.DateUtils;
+import com.fs.common.utils.PhoneUtils;
 import com.fs.common.utils.StringUtils;
 import com.fs.company.domain.Company;
 import com.fs.company.domain.CompanyDept;
@@ -44,6 +45,7 @@ import com.fs.company.service.ICompanyUserService;
 import com.fs.erp.domain.*;
 import com.fs.erp.dto.*;
 import com.fs.erp.service.IErpOrderService;
+import com.fs.express.FsStoreDeliversService;
 import com.fs.huifuPay.domain.HuiFuRefundResult;
 import com.fs.huifuPay.dto.*;
 import com.fs.huifuPay.sdk.opps.core.request.V2TradePaymentScanpayRefundRequest;
@@ -56,9 +58,7 @@ import com.fs.store.constants.StoreConstants;
 import com.fs.store.domain.*;
 import com.fs.store.dto.*;
 import com.fs.store.enums.*;
-import com.fs.store.mapper.FsStoreCartMapper;
-import com.fs.store.mapper.FsStoreOrderItemMapper;
-import com.fs.store.mapper.FsUserAddressMapper;
+import com.fs.store.mapper.*;
 import com.fs.store.param.*;
 import com.fs.store.service.*;
 import com.fs.store.vo.*;
@@ -70,6 +70,7 @@ import com.fs.tzBank.TzBankService;
 import com.fs.tzBank.utils.TzConfigUtils;
 import com.hc.openapi.tool.util.Ids;
 import lombok.Synchronized;
+import org.apache.commons.collections4.CollectionUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.BeanUtils;
@@ -77,7 +78,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.ApplicationEventPublisher;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
-import com.fs.store.mapper.FsStoreOrderMapper;
+import org.springframework.transaction.annotation.Propagation;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.transaction.interceptor.TransactionAspectSupport;
 
@@ -187,6 +188,16 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
 
     @Autowired
     private IFsCouponScheduleService fsCouponScheduleService;
+
+    @Autowired
+    private FsStoreDeliversMapper fsStoreDeliversMapper;
+
+    @Autowired
+    private IFsStoreOrderService orderService;
+
+    @Autowired
+    private FsStoreDeliversService fsStoreDeliversService;
+
     /**
      * 查询订单
      *
@@ -869,65 +880,74 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
     }
 
     @Override
+    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
     public void deliveryOrder(String orderCode,String deliveryId,String deliverCode,String deliverName) {
         FsStoreOrder order= fsStoreOrderMapper.selectFsStoreOrderByOrderCode(orderCode);
-        if(order!=null&&order.getStatus()==OrderInfoEnum.STATUS_1.getValue()){
-            FsExpress express=expressService.selectFsExpressByOmsCode(deliverCode);
-            if(express!=null){
-                order.setDeliveryName(deliverName);
-                order.setDeliverySn(express.getCode());
-            }
+        if(order!=null&& Objects.equals(order.getStatus(), OrderInfoEnum.STATUS_1.getValue())){
+            // 更新订单状态
             order.setStatus(OrderInfoEnum.STATUS_2.getValue());
-            order.setDeliveryId(deliveryId);
             order.setDeliverySendTime(new Date());
-
             fsStoreOrderMapper.updateFsStoreOrder(order);
-            orderStatusService.create(order.getId(), OrderLogEnum.DELIVERY_GOODS.getValue(),
-                    OrderLogEnum.DELIVERY_GOODS.getDesc());
-            //订阅物流回调
-            String lastFourNumber = "";
-            if (order.getDeliverySn().equals(ShipperCodeEnum.SF.getValue())) {
-                lastFourNumber = order.getUserPhone();
-                if (lastFourNumber.length() == 11) {
-                    lastFourNumber = StrUtil.sub(lastFourNumber, lastFourNumber.length(), -4);
-                }
-            }
-            expressService.subscribeEspress(order.getOrderCode(),order.getDeliverySn(),order.getDeliveryId(),lastFourNumber);
 
+
+            // 多运单号适配
+            FsExpress express=expressService.selectFsExpressByOmsCode(deliverCode);
+            if(ObjectUtil.isNotNull(express)) {
+                FsStoreDelivers fsStoreDeliver = new FsStoreDelivers();
+                fsStoreDeliver.setOrderId(order.getId());
+                fsStoreDeliver.setOrderCode(orderCode);
+                fsStoreDeliver.setDeliverId(deliveryId);
+                fsStoreDeliver.setDeliverSn(express.getCode());
+                fsStoreDeliver.setDeliverName(express.getName());
+                fsStoreDeliver.setCreateTime(LocalDateTime.now());
+                fsStoreDeliver.setUpdateTime(LocalDateTime.now());
+                fsStoreDeliver.setCreateBy("admin");
+                fsStoreDeliver.setUpdateBy("admin");
+                fsStoreDeliversMapper.insert(fsStoreDeliver);
+            }
+
+
+            // 微信消息通知
             TemplateBean templateBean = TemplateBean.builder()
                     .orderId(order.getId().toString())
-                    .orderCode(order.getOrderCode().toString())
-                    .deliveryId(order.getDeliveryId())
-                    .deliveryName(order.getDeliveryName())
+                    .orderCode(order.getOrderCode())
+                    .deliveryId(deliveryId)
+                    .deliveryName(express.getName())
                     .userId(order.getUserId())
                     .templateType(TemplateListenEnum.TYPE_2.getValue())
                     .build();
             publisher.publishEvent(new TemplateEvent(this, templateBean));
-        }
-    }
 
-    @Override
-    public void updateDeliveryOrder(Long id,String deliveryId,String deliverCode,String deliverName) {
-        FsStoreOrder order= fsStoreOrderMapper.selectFsStoreOrderById(id);
-        if(order!=null){
-            FsExpress express=expressService.selectFsExpressByOmsCode(deliverCode);
-            if(express!=null){
-            order.setDeliveryName(deliverName);
-            order.setDeliverySn(express.getCode());
-            order.setDeliveryId(deliveryId);
-            order.setDeliverySendTime(new Date());
-            fsStoreOrderMapper.updateFsStoreOrder(order);
-            orderStatusService.create(order.getId(), OrderLogEnum.DELIVERY_GOODS.getValue(),
-                    OrderLogEnum.DELIVERY_GOODS.getDesc());
             //订阅物流回调
             String lastFourNumber = "";
-            if (express.getCode().equals(ShipperCodeEnum.SF.getValue())) {
-                lastFourNumber = order.getUserPhone();
-                if (lastFourNumber.length() == 11) {
-                    lastFourNumber = StrUtil.sub(lastFourNumber, lastFourNumber.length(), -4);
-                }
+            if (StringUtils.equals(express.getCode(),ShipperCodeEnum.SF.getValue())) {
+                lastFourNumber = PhoneUtils.getLastFourNum(order.getUserPhone());
             }
             expressService.subscribeEspress(order.getOrderCode(),express.getCode(),deliveryId,lastFourNumber);
+        }
+    }
+
+    @Override
+    public void updateDeliveryOrder(Long id, String deliveryId, String deliverCode, String deliverName) {
+        FsStoreOrder order = fsStoreOrderMapper.selectFsStoreOrderById(id);
+        if (order != null) {
+            FsExpress express = expressService.selectFsExpressByOmsCode(deliverCode);
+            if (express != null) {
+                order.setDeliveryName(deliverName);
+                order.setDeliverySn(express.getCode());
+                order.setDeliveryId(deliveryId);
+                order.setDeliverySendTime(new Date());
+                fsStoreOrderMapper.updateFsStoreOrder(order);
+                orderStatusService.create(order.getId(), OrderLogEnum.DELIVERY_GOODS.getValue(),
+                        OrderLogEnum.DELIVERY_GOODS.getDesc());
+                //订阅物流回调
+                String lastFourNumber = "";
+                if (express.getCode().equals(ShipperCodeEnum.SF.getValue())) {
+                    if (StringUtils.equals(express.getCode(), ShipperCodeEnum.SF.getValue())) {
+                        lastFourNumber = PhoneUtils.getLastFourNum(order.getUserPhone());
+                    }
+                }
+                expressService.subscribeEspress(order.getOrderCode(), express.getCode(), deliveryId, lastFourNumber);
             }
         }
     }
@@ -982,10 +1002,7 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
         //顺丰轨迹查询处理
         String lastFourNumber = "";
         if (order.getDeliverySn().equals(ShipperCodeEnum.SF.getValue())) {
-            lastFourNumber = order.getUserPhone();
-            if (lastFourNumber.length() == 11) {
-                lastFourNumber = StrUtil.sub(lastFourNumber, lastFourNumber.length(), -4);
-            }
+            lastFourNumber = PhoneUtils.getLastFourNum(order.getUserPhone());
         }
         ExpressInfoDTO dto=expressService.getExpressInfo(order.getOrderCode(),order.getDeliverySn(),order.getDeliveryId(),lastFourNumber);
         dto.setShipperName(order.getDeliveryName());
@@ -993,6 +1010,28 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
         return R.ok().put("data", dto).put("express",express).put("deliveryId",order.getDeliveryId());
     }
 
+    @Override
+    public R getExpressMulti(FsStoreOrder order) {
+        //顺丰轨迹查询处理
+        String lastFourNumber = PhoneUtils.getLastFourNum(order.getUserPhone());
+        // 获取该订单关联的物流信息
+        List<FsStoreDelivers> fsStoreDelivers = fsStoreDeliversMapper.findByOrderId(order.getId());
+        if(CollectionUtils.isEmpty(fsStoreDelivers)){
+            return R.ok("当前订单号暂无物流信息");
+        }
+
+        List<ExpressInfoDTO> result = new ArrayList<>();
+        for (FsStoreDelivers fsStoreDeliver : fsStoreDelivers) {
+            ExpressInfoDTO dto=expressService.getExpressInfo(order.getOrderCode(),
+                    fsStoreDeliver.getDeliverSn(),
+                    fsStoreDeliver.getDeliverId(),
+                    lastFourNumber);
+            result.add(dto);
+        }
+
+        return R.ok().put("data",result);
+    }
+
     @Override
     @Transactional
     public R createUserOrder(FsStoreOrderCreateUserParam param) {
@@ -1040,12 +1079,10 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
     public List<FsMyStoreOrderListQueryVO> selectFsCompanyStoreOrderListVO(FsMyStoreOrderQueryParam param) {
         List<FsMyStoreOrderListQueryVO> list=fsStoreOrderMapper.selectFsCompanyStoreOrderListVO(param);
         for(FsMyStoreOrderListQueryVO vo:list){
-//          List<FsStoreOrderItemVO> items=fsStoreOrderItemMapper.selectMyFsStoreOrderItemListByOrderId(vo.getId());
-//          vo.setItems(items);
             if(StringUtils.isNotEmpty(vo.getItemJson())){
                 JSONArray jsonArray=JSONUtil.parseArray(vo.getItemJson());
                 List<FsStoreOrderItemVO> items=JSONUtil.toList(jsonArray, FsStoreOrderItemVO.class);
-                if(items.size()>0){
+                if(CollectionUtils.isNotEmpty(items)){
                     vo.setItems(items);
                 }
             }
@@ -2042,25 +2079,11 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
     @Override
     @Transactional
     public R syncExpress(FsStoreOrderExpressEditParam param) {
-        FsStoreOrder order = fsStoreOrderMapper.selectFsStoreOrderById(param.getOrderId());
-        String lastFourNumber = "";
-        if (order.getDeliverySn().equals(ShipperCodeEnum.SF.getValue())) {
-            lastFourNumber = order.getUserPhone();
-            if (lastFourNumber.length() == 11) {
-                lastFourNumber = StrUtil.sub(lastFourNumber, lastFourNumber.length(), -4);
-            }
-        }
-        ExpressInfoDTO dto=expressService.getExpressInfo(order.getOrderCode(),order.getDeliverySn(),order.getDeliveryId(),lastFourNumber);
-        FsStoreOrder map=new FsStoreOrder();
-        map.setDeliveryStatus(Integer.parseInt(dto.getState()));
-        map.setId(order.getId());
-        map.setDeliveryType(dto.getStateEx());
-        fsStoreOrderMapper.updateFsStoreOrder(map);
-        //如果是正常签收,更新订单状态
-        if(dto.getState().equals("3")&&(dto.getStateEx().equals("301")||dto.getStateEx().equals("302")||dto.getStateEx().equals("304")||dto.getStateEx().equals("311"))){
-            finishOrder(order.getId());
-        }
-        return null;
+
+        fsStoreDeliversService.syncDeliverInfo(param.getOrderId());
+        fsStoreDeliversService.finishOrder(param.getOrderId());
+
+        return R.ok();
     }
 
     @Override
@@ -2662,53 +2685,49 @@ public class FsStoreOrderServiceImpl implements IFsStoreOrderService
         //https://api.hospital.ifeiyu100.com/app/common/expressNotify
         String data= URLDecoder.decode(notifyDTO.getRequestData(), Charset.forName("UTF-8"));
         //ExpressInfoDTO
-        logger.info("快递根踪回调:"+data);
+        logger.info("快递跟踪回调: {}",data);
         ExpressDataDTO expressDataDTO=JSONUtil.toBean(data,ExpressDataDTO.class);
-        if(expressDataDTO!=null&&expressDataDTO.getData()!=null){
-            for(ExpressInfoDTO dto:expressDataDTO.getData()){
-                List<FsStoreOrder> orders=this.selectFsStoreOrderListByDeliveryId(dto.getLogisticCode());
-                if(orders!=null){
-                    for(FsStoreOrder order:orders){
-                        logger.info("订单信息:"+JSONUtil.toJsonStr(order));
-                        logger.info("运单号:"+dto.getLogisticCode());
-                        if(order!=null && (order.getDeliveryStatus()==null||order.getDeliveryStatus()!=3)){
-                            if (dto.getState()!=null&&dto.getStateEx()!=null) {
-                                FsStoreOrder map = new FsStoreOrder();
-                                map.setDeliveryStatus(Integer.parseInt(dto.getState()));
-                                map.setId(order.getId());
-                                map.setDeliveryType(dto.getStateEx());
-                                this.updateFsStoreOrder(map);
-                                //如果是正常签收,更新订单状态
-                                if (dto.getState().equals("3") && (dto.getStateEx().equals("301") || dto.getStateEx().equals("302") || dto.getStateEx().equals("304") || dto.getStateEx().equals("311"))) {
-                                    this.finishOrder(order.getId());
-                                }
-                            }
-                            if (!dto.isSuccess()){
-                                logger.info("物流状态异常:{}",dto);
-                            }
-                            //如果无轨迹重新订阅
-                            if ((!dto.isSuccess()&&dto.getReason().equals("三天无轨迹"))||(!dto.isSuccess()&&dto.getReason().equals("七天内无轨迹变化"))){
-                                //订阅物流回调
-                                String lastFourNumber = "";
-                                if (order.getDeliverySn().equals(ShipperCodeEnum.SF.getValue())) {
-                                    lastFourNumber = order.getUserPhone();
-                                    if (lastFourNumber.length() == 11) {
-                                        lastFourNumber = StrUtil.sub(lastFourNumber, lastFourNumber.length(), -4);
-                                    }
-                                }
-                                logger.info("物流重新订阅:{}",order.getDeliveryId());
-                                expressService.subscribeEspress(order.getOrderCode(),order.getDeliverySn(),order.getDeliveryId(),lastFourNumber);
-                            }
 
-                        }
+        if(ObjectUtil.isNotNull(expressDataDTO)){
+            List<ExpressInfoDTO> expressInfoDTOList = expressDataDTO.getData();
+            List<FsStoreDelivers> delivers = new ArrayList<>();
+            for (ExpressInfoDTO express : expressInfoDTOList) {
+                FsStoreDelivers deliver = fsStoreDeliversService
+                        .findByOrderCodeAndDeliverId(express.getOrderCode(), express.getLogisticCode());
+                if(ObjectUtil.isNotNull(express) && express.isSuccess()){
+                    if(ObjectUtil.isNotNull(deliver)){
+                        deliver.setStatus(Integer.valueOf(express.getState()));
+                        deliver.setStateEx(Integer.valueOf(express.getStateEx()));
+
+                        delivers.add(deliver);
                     }
                 }
 
+                //如果无轨迹重新订阅
+                if ((!express.isSuccess()&&express.getReason().equals("三天无轨迹"))||(!express.isSuccess()&&express.getReason().equals("七天内无轨迹变化"))){
+                    FsStoreOrder fsStoreOrder = orderService.selectFsStoreOrderByOrderCode(express.getOrderCode());
+                    String lastFourNumber = "";
+                    if(StringUtils.equals(deliver.getDeliverSn(), ShipperCodeEnum.SF.getValue())){
+                        lastFourNumber = PhoneUtils.getLastFourNum(fsStoreOrder.getUserPhone());
+                    }
+                    logger.info("物流重新订阅:{}",fsStoreOrder.getDeliveryId());
+                    if(ObjectUtil.isNotNull(deliver)){
+                        expressService.subscribeEspress(fsStoreOrder.getOrderCode(),deliver.getDeliverSn(),deliver.getDeliverId(),lastFourNumber);
+                    }
+                }
+            }
+            // 更新物流状态
+            fsStoreDeliversMapper.updateBatch(delivers);
+            List<Long> collect = delivers.stream().map(FsStoreDelivers::getOrderId)
+                    .filter(ObjectUtil::isNotNull)
+                    .collect(Collectors.toList());
+
+            for (Long orderId : collect) {
+                fsStoreDeliversService.finishOrder(orderId);
             }
-            return ExpressResultDTO.success(sysConfig.getKdnId().trim());
+
         }
-        return ExpressResultDTO.error(sysConfig.getKdnId().trim(),"物流详情数据为null");
+        return ExpressResultDTO.success(sysConfig.getKdnId().trim());
     }
 
-
 }

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

@@ -1,8 +1,8 @@
 #配置
 fsConfig:
   #快递鸟
-  kdnId: 1762981
-  kdnKeyId: 024e89b1-25c7-4725-8a3c-1bf1ca3ddcab
+  kdnId: 1881217
+  kdnKeyId: a43fee18-3ea9-4eff-99c0-7e94618d7a57
   kdnUrl: http://api.kdniao.com/Ebusiness/EbusinessOrderHandle.aspx
   kdnSubscribeUrl: https://api.kdniao.com/api/dist
   kdnAddressUrl: https://api.kdniao.com/api/dist

+ 18 - 0
fs-user-app/src/main/java/com/fs/app/controller/StoreOrderController.java

@@ -8,6 +8,8 @@ import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
 import com.fs.app.annotation.Login;
 import com.fs.common.annotation.RepeatSubmit;
 
@@ -1321,10 +1323,26 @@ public class StoreOrderController extends  AppBaseController {
         if (order.getStatus() <2) {
             throw new CustomException("未发货订单不能查询");
         }
+
         return orderService.getExpress(order);
     }
 
 
+    @Login
+    @ApiOperation("物流查询多运单号")
+    @PostMapping("/getExpressMulti")
+    public R getExpressMulti( @Validated @RequestBody FsStoreOrderExpressParam param, HttpServletRequest request){
+        FsStoreOrder order=orderService.selectFsStoreOrderById(param.getOrderId());
+        if (ObjectUtil.isNull(order)) {
+            throw new CustomException("订单不存在");
+        }
+        if (order.getStatus() <2) {
+            throw new CustomException("未发货订单不能查询");
+        }
+        return orderService.getExpressMulti(order);
+    }
+
+
     @Login
     @ApiOperation("确认套餐订单")
     @PostMapping("/confirmPackageOrder")

+ 1 - 0
fs-user-app/src/main/resources/static/S8Zw463cFc.txt

@@ -0,0 +1 @@
+641273d9479c4e0133bfacb9f669d39f