Parcourir la source

需求代码提交

yuhongqi il y a 3 semaines
Parent
commit
ccfe94c666
20 fichiers modifiés avec 338 ajouts et 87 suppressions
  1. 62 32
      fs-admin/src/main/java/com/fs/core/interceptor/impl/SameUrlDataInterceptor.java
  2. 81 1
      fs-admin/src/main/java/com/fs/live/controller/LiveOrderController.java
  3. 4 1
      fs-admin/src/main/java/com/fs/task/LiveTask.java
  4. 21 2
      fs-live-socket/src/main/java/com/fs/live/websocket/service/WebSocketServer.java
  5. 12 12
      fs-live-socket/src/main/resources/application.yml
  6. 1 1
      fs-service-system/src/main/java/com/fs/live/mapper/LiveOrderMapper.java
  7. 2 0
      fs-service-system/src/main/java/com/fs/live/mapper/LiveOrderPaymentMapper.java
  8. 3 0
      fs-service-system/src/main/java/com/fs/live/service/ILiveOrderPaymentService.java
  9. 1 0
      fs-service-system/src/main/java/com/fs/live/service/impl/LiveMsgServiceImpl.java
  10. 5 0
      fs-service-system/src/main/java/com/fs/live/service/impl/LiveOrderPaymentServiceImpl.java
  11. 79 26
      fs-service-system/src/main/java/com/fs/live/service/impl/LiveOrderServiceImpl.java
  12. 1 1
      fs-service-system/src/main/java/com/fs/store/mapper/FsStoreCartMapper.java
  13. 3 0
      fs-service-system/src/main/java/com/fs/store/mapper/FsStoreDeliversMapper.java
  14. 9 1
      fs-service-system/src/main/java/com/fs/store/service/impl/FsExpressServiceImpl.java
  15. 10 0
      fs-service-system/src/main/java/com/fs/store/service/impl/FsUserServiceImpl.java
  16. 6 0
      fs-service-system/src/main/java/com/fs/store/vo/FsStoreCartVO.java
  17. 19 0
      fs-user-app/src/main/java/com/fs/app/controller/LiveCartController.java
  18. 2 0
      fs-user-app/src/main/java/com/fs/app/controller/LiveMsgController.java
  19. 11 4
      fs-user-app/src/main/java/com/fs/app/controller/live/LiveCompletionPointsController.java
  20. 6 6
      fs-user-app/src/main/resources/application.yml

+ 62 - 32
fs-admin/src/main/java/com/fs/core/interceptor/impl/SameUrlDataInterceptor.java

@@ -1,18 +1,15 @@
 package com.fs.core.interceptor.impl;
 
-import java.util.Arrays;
-import java.util.List;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
 import javax.servlet.http.HttpServletRequest;
-
-import com.alibaba.fastjson.JSON;
-import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.beans.factory.annotation.Value;
-import org.springframework.data.redis.core.RedisTemplate;
-import org.springframework.data.redis.core.script.DefaultRedisScript;
 import org.springframework.stereotype.Component;
+import com.alibaba.fastjson.JSONObject;
 import com.fs.common.constant.Constants;
+import com.fs.common.core.redis.RedisCache;
 import com.fs.common.filter.RepeatedlyRequestWrapper;
 import com.fs.common.utils.StringUtils;
 import com.fs.common.utils.http.HttpHelper;
@@ -21,21 +18,21 @@ import com.fs.core.interceptor.RepeatSubmitInterceptor;
 /**
  * 判断请求url和数据是否和上一次相同,
  * 如果和上次相同,则是重复提交表单。 有效时间为10秒内。
+ *
  */
-@Slf4j
 @Component
 public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
 {
+    public final String REPEAT_PARAMS = "repeatParams";
+
+    public final String REPEAT_TIME = "repeatTime";
 
     // 令牌自定义标识
     @Value("${token.header}")
     private String header;
-    @Autowired
-    private RedisTemplate redisTemplate;
 
     @Autowired
-    @Qualifier("prevent-resubmit")
-    private DefaultRedisScript<Boolean> preventResubmitScript;
+    private RedisCache redisCache;
 
     /**
      * 间隔时间,单位:秒 默认10秒
@@ -44,16 +41,15 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
      */
     private int intervalTime = 10;
 
+    public void setIntervalTime(int intervalTime)
+    {
+        this.intervalTime = intervalTime;
+    }
 
     @SuppressWarnings("unchecked")
     @Override
     public boolean isRepeatSubmit(HttpServletRequest request)
     {
-       return this.isRepeatSubmit(request,this.intervalTime);
-    }
-
-    @Override
-    public boolean isRepeatSubmit(HttpServletRequest request, Integer intervalTime) {
         String nowParams = "";
         if (request instanceof RepeatedlyRequestWrapper)
         {
@@ -64,8 +60,12 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
         // body参数为空,获取Parameter的数据
         if (StringUtils.isEmpty(nowParams))
         {
-            nowParams = JSON.toJSONString(request.getParameterMap());
+            nowParams = JSONObject.toJSONString(request.getParameterMap());
         }
+        Map<String, Object> nowDataMap = new HashMap<String, Object>();
+        nowDataMap.put(REPEAT_PARAMS, nowParams);
+        nowDataMap.put(REPEAT_TIME, System.currentTimeMillis());
+
         // 请求地址(作为存放cache的key值)
         String url = request.getRequestURI();
 
@@ -78,22 +78,52 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
 
         // 唯一标识(指定key + 消息头)
         String cache_repeat_key = Constants.REPEAT_SUBMIT_KEY + submitKey;
-        // 当前时间戳
-        long currentTimeMillis = System.currentTimeMillis();
 
-        // 执行Lua脚本
-        List<String> keys = Arrays.asList(cache_repeat_key, url);
+        Object sessionObj = redisCache.getCacheObject(cache_repeat_key);
+        if (sessionObj != null)
+        {
+            Map<String, Object> sessionMap = (Map<String, Object>) sessionObj;
+            if (sessionMap.containsKey(url))
+            {
+                Map<String, Object> preDataMap = (Map<String, Object>) sessionMap.get(url);
+                if (compareParams(nowDataMap, preDataMap) && compareTime(nowDataMap, preDataMap))
+                {
+                    return true;
+                }
+            }
+        }
+        Map<String, Object> cacheMap = new HashMap<String, Object>();
+        cacheMap.put(url, nowDataMap);
+        redisCache.setCacheObject(cache_repeat_key, cacheMap, intervalTime, TimeUnit.SECONDS);
+        return false;
+    }
 
-        log.info("调用lua参数: {} {} {} {} {}",preventResubmitScript,keys,nowParams,currentTimeMillis,intervalTime);
+    @Override
+    public boolean isRepeatSubmit(HttpServletRequest request, Integer time) {
+        return false;
+    }
 
-        Boolean result = (Boolean) redisTemplate.execute(
-                preventResubmitScript,
-                keys,
-                nowParams,
-                currentTimeMillis,
-                intervalTime
-        );
+    /**
+     * 判断参数是否相同
+     */
+    private boolean compareParams(Map<String, Object> nowMap, Map<String, Object> preMap)
+    {
+        String nowParams = (String) nowMap.get(REPEAT_PARAMS);
+        String preParams = (String) preMap.get(REPEAT_PARAMS);
+        return nowParams.equals(preParams);
+    }
 
-        return result != null && result;
+    /**
+     * 判断两次间隔时间
+     */
+    private boolean compareTime(Map<String, Object> nowMap, Map<String, Object> preMap)
+    {
+        long time1 = (Long) nowMap.get(REPEAT_TIME);
+        long time2 = (Long) preMap.get(REPEAT_TIME);
+        if ((time1 - time2) < (this.intervalTime * 1000))
+        {
+            return true;
+        }
+        return false;
     }
 }

+ 81 - 1
fs-admin/src/main/java/com/fs/live/controller/LiveOrderController.java

@@ -39,14 +39,22 @@ import com.fs.live.vo.LiveGoodsVo;
 import com.fs.live.vo.LiveOrderPaymentVo;
 import com.fs.live.vo.LiveOrderQueryVO;
 import com.fs.live.vo.LiveOrderVo;
+import com.fs.huifuPay.domain.HuiFuQueryOrderResult;
+import com.fs.huifuPay.sdk.opps.core.request.V2TradePaymentScanpayQueryRequest;
+import com.fs.huifuPay.service.HuiFuService;
+import com.fs.pay.pay.domain.OrderResult;
+import com.fs.pay.pay.dto.OrderQueryDTO;
+import com.fs.pay.pay.service.PayService;
 import com.fs.store.domain.FsStoreDelivers;
 import com.fs.store.domain.FsStoreOrder;
+import com.fs.store.domain.FsStorePayment;
 import com.fs.store.domain.FsStoreOrderStatus;
 import com.fs.store.domain.FsUser;
 import com.fs.store.mapper.FsStoreDeliversMapper;
 import com.fs.store.mapper.FsStoreProductMapper;
 import com.fs.store.mapper.FsWarehousesMapper;
 import com.fs.store.param.*;
+import com.fs.store.service.IFsStorePaymentService;
 import com.fs.store.service.IFsExpressService;
 import com.fs.store.service.IFsUserService;
 import com.fs.task.LiveTask;
@@ -62,6 +70,7 @@ import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletRequest;
+import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
@@ -99,6 +108,12 @@ public class LiveOrderController extends BaseController
     IErpOrderService erpOrderService;
     @Autowired
     private LiveTask liveTask;
+    @Autowired
+    private IFsStorePaymentService fsStorePaymentService;
+    @Autowired
+    private HuiFuService huiFuService;
+    @Autowired
+    private PayService ybPayService;
 
     /**
      * 查询订单列表
@@ -464,6 +479,71 @@ public class LiveOrderController extends BaseController
         return R.error("未查询到快递信息");
     }
 
-
+    /**
+     * 同步直播订单支付状态
+     * 仿照 FsStorePaymentController.returnPayStatus,仅处理直播订单
+     */
+    @Log(title = "同步直播订单状态", businessType = BusinessType.UPDATE)
+    @PreAuthorize("@ss.hasPermi('store:storePayment:payNotify')")
+    @PostMapping("/syncPayStatus")
+    public R syncPayStatus(@RequestBody FsStorePayment fsStorePayment) throws Exception {
+        LiveOrderPayment payment = orderPaymentService.selectLiveOrderPaymentByOrderCode(fsStorePayment.getTradeNo());
+        if (payment == null) {
+            return R.error("该付款记录没有查询到!");
+        }
+        if (payment.getBusinessType() != null && payment.getBusinessType() == 5) {
+            // 可提前校验为直播订单
+        }
+        String payMode = payment.getPayMode();
+        logger.info("同步直播订单状态 手动查询: {}", payment);
+
+        if ("hf".equals(payMode)) {
+            V2TradePaymentScanpayQueryRequest request = new V2TradePaymentScanpayQueryRequest();
+            request.setOrgReqDate(new SimpleDateFormat("yyyyMMdd").format(payment.getCreateTime()));
+            request.setOrgHfSeqId(payment.getTradeNo());
+            HuiFuQueryOrderResult o;
+            try {
+                o = huiFuService.queryOrder(request);
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+            logger.info("汇付返回: {}", o);
+            if ("00000000".equals(o.getResp_code()) && "S".equals(o.getTrans_stat())) {
+                String[] order = o.getOrg_req_seq_id().split("-");
+                if ("live".equals(order[0])) {
+                    liveOrderService.payConfirm(1, null, order[1], o.getOrg_hf_seq_id(), o.getOut_trans_id(), o.getParty_order_id());
+                    return R.ok();
+                }
+                return R.error("该交易单号不是直播订单,请使用同步订单状态功能");
+            }
+        } else if ("yb".equals(payMode)) {
+            OrderQueryDTO o = new OrderQueryDTO();
+            o.setUpOrderId(payment.getTradeNo());
+            OrderResult orderResult = ybPayService.getOrder(o);
+            if (orderResult != null) {
+                if ("4".equals(orderResult.getState())) {
+                    return R.error("订单未支付");
+                }
+                if ("5".equals(orderResult.getState())) {
+                    return R.error("订单已退款");
+                }
+                if ("0".equals(orderResult.getState())) {
+                    String[] order = orderResult.getLowOrderId().split("-");
+                    if ("100".equals(orderResult.getStatus())) {
+                        if ("live".equals(order[0])) {
+                            liveOrderService.payConfirm(1, null, order[1], o.getUpOrderId(), orderResult.getBankTrxId(), orderResult.getBankOrderId());
+                            return R.ok();
+                        }
+                        return R.error("该交易单号不是直播订单,请使用同步订单状态功能");
+                    }
+                    return R.error("请检查外部订单号");
+                }
+                return R.error("订单支付状态异常,联系财务检查");
+            }
+        } else if ("tzbk".equals(payMode)) {
+            return R.error("台州银行支付暂不支持直播订单同步");
+        }
+        return R.error("请检查外部订单号");
+    }
 
 }

+ 4 - 1
fs-admin/src/main/java/com/fs/task/LiveTask.java

@@ -8,6 +8,7 @@ import com.fs.erp.dto.ErpOrderQueryResponse;
 import com.fs.erp.service.FsJstAftersalePushService;
 import com.fs.erp.service.IErpOrderService;
 import com.fs.erp.utils.ErpContextHolder;
+import com.fs.express.FsStoreDeliversService;
 import com.fs.live.utils.redis.RedisBatchHandler;
 import com.fs.live.domain.LiveAfterSales;
 import com.fs.live.domain.LiveOrder;
@@ -166,7 +167,8 @@ public class LiveTask {
         }
     }
 
-
+    @Autowired
+    FsStoreDeliversService fsStoreDeliverService;
     /**
      * 同步物流状态
      */
@@ -175,6 +177,7 @@ public class LiveTask {
         List<Long> ids = liveOrderService.selectSyncExpressIds();
         for (Long id : ids) {
             liveOrderService.syncExpress(id);
+            fsStoreDeliverService.finishOrder(id,1);
         }
     }
 

+ 21 - 2
fs-live-socket/src/main/java/com/fs/live/websocket/service/WebSocketServer.java

@@ -123,6 +123,7 @@ public class WebSocketServer {
     private final static long LIVE_MSG_BATCH_INTERVAL = 10000; // 10秒
     // Redis key:被禁言用户Set(按直播间)
     private final static String BLOCKED_USERS_KEY = "live:blocked:users:%s";
+    private final static String MUTED_USERS_KEY = "live:muted:users:%s";
 
     private final RedisCache redisCache = SpringUtils.getBean(RedisCache.class);
     private final StringRedisTemplate stringRedisTemplate = SpringUtils.getBean(StringRedisTemplate.class);
@@ -386,7 +387,7 @@ public class WebSocketServer {
 
                     if (userType == 0) {
                         // 使用Redis Set检查用户是否被禁言
-                        String blockedUsersKey = String.format(BLOCKED_USERS_KEY, msg.getLiveId());
+                        String blockedUsersKey = String.format(MUTED_USERS_KEY, msg.getLiveId());
                         boolean isBlocked = redisCache.redisTemplate.opsForSet().isMember(blockedUsersKey, String.valueOf(msg.getUserId()));
                         if (isBlocked) {
                             sendMessage(session, JSONObject.toJSONString(R.error("你已被禁言")));
@@ -450,6 +451,9 @@ public class WebSocketServer {
                 case "blockUser":
                     sendBlockMessage(liveId, msg.getUserId());
                     break;
+                case "mutedUser":
+                    handleMutedUser(msg.getLiveId(), msg.getUserId(), msg.getStatus());
+                    break;
                 case "goods":
                     sendGoodsMessage(msg);
                     break;
@@ -723,11 +727,26 @@ public class WebSocketServer {
         sendWithRetry(session, JSONObject.toJSONString(R.ok().put("data", sendMsgVo)), 1);
     }
 
+    /**
+     * 处理禁言/解禁:将用户ID加入或移出直播间禁言 Redis Set,发送消息时据此判断是否允许发言
+     */
+    private void handleMutedUser(Long liveId, Long userId, Integer status) {
+        if (liveId == null || userId == null) {
+            return;
+        }
+        String mutedUsersKey = String.format(MUTED_USERS_KEY, liveId);
+        if (status != null && status == 1) {
+            redisCache.redisTemplate.opsForSet().add(mutedUsersKey, String.valueOf(userId));
+        } else {
+            redisCache.redisTemplate.opsForSet().remove(mutedUsersKey, String.valueOf(userId));
+        }
+    }
+
     private void sendBlockMessage(Long liveId, Long userId) {
         // 将被禁言用户添加到Redis Set中
         String blockedUsersKey = String.format(BLOCKED_USERS_KEY, liveId);
         redisCache.redisTemplate.opsForSet().add(blockedUsersKey, String.valueOf(userId));
-        
+
         SendMsgVo sendMsgVo = new SendMsgVo();
         sendMsgVo.setLiveId(liveId);
         sendMsgVo.setUserId(userId);

+ 12 - 12
fs-live-socket/src/main/resources/application.yml

@@ -41,19 +41,19 @@ server:
     # tomcat的URI编码
     uri-encoding: UTF-8
     # tomcat最大线程数,默认为200
-    max-threads: 128
+    max-threads: 2000
     # Tomcat启动初始化的线程数,默认值25
-    min-spare-threads: 64
-    # 服务器在任何给定时间接受和处理的最大连接数。一旦达到限制,操作系统仍然可以接受基于“acceptCount”属性的连接。
-    max-connections: 50000
-    # 当所有可能的请求处理线程都在使用中时,传入连接请求的最大队列长度
-    accept-count: 2000
-    # 连接器在接受连接后等待显示请求 URI 行的时间。
-    connection-timeout: 20000
-    # 在关闭连接之前等待另一个 HTTP 请求的时间。如果未设置,则使用 connectionTimeout。设置为 -1 时不会超时。
-    keep-alive-timeout: 300000
-    # 在连接关闭之前可以进行流水线处理的最大HTTP请求数量。当设置为0或1时,禁用keep-alive和流水线处理。当设置为-1时,允许无限数量的流水线处理或keep-alive请求。
-    max-keep-alive-requests: 10000
+    min-spare-threads: 2000
+    #    # 服务器在任何给定时间接受和处理的最大连接数。一旦达到限制,操作系统仍然可以接受基于“acceptCount”属性的连接。
+    max-connections: 10000
+    #    # 当所有可能的请求处理线程都在使用中时,传入连接请求的最大队列长度
+    accept-count: 1000
+#    # 连接器在接受连接后等待显示请求 URI 行的时间。
+#    connection-timeout: 20000
+#    # 在关闭连接之前等待另一个 HTTP 请求的时间。如果未设置,则使用 connectionTimeout。设置为 -1 时不会超时。
+#    keep-alive-timeout: 300000
+#    # 在连接关闭之前可以进行流水线处理的最大HTTP请求数量。当设置为0或1时,禁用keep-alive和流水线处理。当设置为-1时,允许无限数量的流水线处理或keep-alive请求。
+#    max-keep-alive-requests: 10000
 
 # 日志配置
 logging:

+ 1 - 1
fs-service-system/src/main/java/com/fs/live/mapper/LiveOrderMapper.java

@@ -111,7 +111,7 @@ public interface LiveOrderMapper {
     @DataSource(DataSourceType.SLAVE)
     List<LiveOrder> selectUpdateExpress();
 
-    @Select("select order_id from live_order where `status` = 2")
+    @Select("select order_id from live_order where `status` = 3")
     List<Long> selectSyncExpressIds();
 
     @Select("select order_id from live_order where `status` = 2 and extend_order_id is null ")

+ 2 - 0
fs-service-system/src/main/java/com/fs/live/mapper/LiveOrderPaymentMapper.java

@@ -92,4 +92,6 @@ public interface LiveOrderPaymentMapper {
     @Select("select business_id,bank_transaction_id from live_order_payment where bank_transaction_id is not null")
     Map<String, LiveOrderPayment> selectAllPayments();
 
+    @Select("select * from live_order_payment where business_code = #{orderCode} and status = 0 limit 1 ")
+    LiveOrderPayment selectByBusinessCode(@Param("orderCode") String orderCode);
 }

+ 3 - 0
fs-service-system/src/main/java/com/fs/live/service/ILiveOrderPaymentService.java

@@ -4,6 +4,7 @@ import java.util.List;
 
 import com.fs.live.domain.LiveOrderPayment;
 import com.fs.live.vo.LiveOrderPaymentVo;
+import com.fs.store.domain.FsStorePayment;
 
 /**
  * 支付明细Service接口
@@ -67,4 +68,6 @@ public interface ILiveOrderPaymentService {
     List<LiveOrderPayment> selectLiveOrderPaymentByOrderId(Long id);
 
     boolean queryHf(LiveOrderPayment liveOrderPayment);
+
+    LiveOrderPayment selectLiveOrderPaymentByOrderCode(String tradeNo);
 }

+ 1 - 0
fs-service-system/src/main/java/com/fs/live/service/impl/LiveMsgServiceImpl.java

@@ -136,6 +136,7 @@ public class LiveMsgServiceImpl implements ILiveMsgService
                 // 时间未超过5s,直接返回缓存
                 return getCachedMsgList(cacheKey);
             }
+
         } catch (Exception e) {
             log.error("查询直播间消息列表异常,liveId: {}", liveId, e);
             // 异常情况下,直接查询数据库

+ 5 - 0
fs-service-system/src/main/java/com/fs/live/service/impl/LiveOrderPaymentServiceImpl.java

@@ -124,6 +124,11 @@ public class LiveOrderPaymentServiceImpl implements ILiveOrderPaymentService {
         return false;
     }
 
+    @Override
+    public LiveOrderPayment selectLiveOrderPaymentByOrderCode(String orderCode) {
+        return baseMapper.selectByBusinessCode(orderCode);
+    }
+
     /**
      * 新增支付明细
      *

+ 79 - 26
fs-service-system/src/main/java/com/fs/live/service/impl/LiveOrderServiceImpl.java

@@ -747,10 +747,10 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
         Asserts.notNull(deliveryDTO.getDeliverId(), "快递号不能为空!");
         Asserts.notNull(deliveryDTO.getDeliverSn(), "快递类型不能为空!");
 
-        liveOrder.setDeliverySn(deliveryDTO.getDeliverId());
-        liveOrder.setDeliveryCode(deliveryDTO.getDeliverSn());
-        liveOrder.setStatus(3);
-        liveOrderService.updateLiveOrder(liveOrder);
+//        liveOrder.setDeliverySn(deliveryDTO.getDeliverId());
+//        liveOrder.setDeliveryCode(deliveryDTO.getDeliverSn());
+//        liveOrder.setStatus(3);
+//        liveOrderService.updateLiveOrder(liveOrder);
 
 
         fsStoreDeliversService.editDeliveryId(deliveryDTO);
@@ -830,7 +830,17 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
                 order.setDeliveryStatus(null);
                 order.setDeliveryType(null);
             }
+
+            // 商品合计 = totalPrice + discountMoney - payDelivery (全部转为Double再相加减,保留两位小数)
+            Double totalPrice = order.getTotalPrice() != null ? Double.parseDouble(order.getTotalPrice().toString()) : 0d;
+            Double discountMoney = order.getDiscountMoney() != null ? Double.parseDouble(order.getDiscountMoney().toString()) : 0d;
+            double payDelivery = order.getPayDelivery() != null ? Double.parseDouble(order.getPayDelivery().toString()) : 0d;
+            double goodsAmount = totalPrice + discountMoney - payDelivery;
+            // 保留两位小数,进行四舍五入
+            goodsAmount = new java.math.BigDecimal(goodsAmount).setScale(2, java.math.RoundingMode.HALF_UP).doubleValue();
+
             order.setPayPrice(order.getTotalPrice());
+            order.setTotalPrice(BigDecimal.valueOf(goodsAmount));
 
             LiveOrderPayment liveOrderPayment = paymentMap.get(String.valueOf(order.getOrderId()));
             if (ObjectUtil.isNotNull(liveOrderPayment)) {
@@ -1184,6 +1194,8 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
                 // 部分发货或者全部发货
                 if (ObjectUtils.equals(orderQuery.getDelivery_state(), 1) || ObjectUtils.equals(orderQuery.getDelivery_state(), 2)) {
 
+                    liveOrderLogsService.create(order.getOrderId(), OrderLogEnum.DELIVERY_GOODS.getValue(),
+                            OrderLogEnum.DELIVERY_GOODS.getDesc());
                     for (ErpDeliverys delivery : orderQuery.getDeliverys()) {
                         if (delivery.getDelivery()) {
                             this.deliveryOrder(order.getOrderCode(), delivery.getMail_no(),
@@ -2311,32 +2323,73 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
         if (byOrderId.isEmpty()) {
             return R.error("当前账号没有快递记录!");
         }
-        FsStoreDelivers delivers = byOrderId.get(0);
+        String orderCode = order.getOrderCode();
 
-        ExpressInfoDTO dto = expressService.getExpressInfo(order.getOrderCode(), delivers.getDeliverSn(), delivers.getDeliverId(), lastFourNumber);
-        log.info("快递鸟查询dto:{}", JSONUtil.toJsonStr(dto));
-        if (!dto.isSuccess()) {
-            return R.error(dto.getReason());
-        }
-        if ("0".equals(dto.getStateEx()) && "0".equals(dto.getState())) {
-            lastFourNumber = "19923690275";
-            if (order.getDeliveryCode().equals(ShipperCodeEnum.SF.getValue()) || order.getDeliveryCode().equals(ShipperCodeEnum.ZTO.getValue())) {
-                lastFourNumber = order.getUserPhone();
-                if (lastFourNumber.length() == 11) {
-                    lastFourNumber = StrUtil.sub(lastFourNumber, lastFourNumber.length(), -4);
+        for (FsStoreDelivers fsStoreDelivers : byOrderId) {
+            if (ObjectUtil.isNotEmpty(fsStoreDelivers.getDeliverId())) {
+
+                ExpressInfoDTO dto = null;
+                try {
+                    // 记录HTTP请求前的信息
+                    log.info("开始调用快递查询接口, 订单号: {}, 快递公司编码: {}, 快递单号: {}, 手机号后四位: {}",
+                            orderCode, fsStoreDelivers.getDeliverId(), fsStoreDelivers.getDeliverSn(), lastFourNumber);
+                    dto = expressService.getExpressInfo(orderCode,
+                            fsStoreDelivers.getDeliverSn(), fsStoreDelivers.getDeliverId(), lastFourNumber);
+                    // 假设expressService.getExpressInfo内部进行了HTTP请求,你需要在expressService内部打印更详细的日志
+                    // 这里只记录返回结果
+                    if (ObjectUtil.isNotNull(dto)) {
+                        log.info("快递查询接口调用成功, 订单号: {}, 快递状态: {}, 扩展状态: {}",
+                                orderCode, dto.getState(), dto.getStateEx());
+                        fsStoreDelivers.setStatus(Integer.valueOf(dto.getState()));
+                        fsStoreDelivers.setStateEx(Integer.valueOf(dto.getStateEx()));
+                    } else {
+                        log.warn("快递查询接口调用成功,但返回结果为空, 订单号: {}", orderCode);
+                    }
+                } catch (Exception e) {
+                    log.error("快递查询接口调用失败, 订单号: {}, 快递单号: {}, 错误信息: {}", orderCode, fsStoreDelivers.getDeliverSn(), e.getMessage(), e);
                 }
+            } else {
+                log.info("发货单信息中快递ID为空, 跳过处理, 发货单ID: {}", fsStoreDelivers.getId());
             }
-            dto = expressService.getExpressInfo(order.getOrderCode(), delivers.getDeliverSn(), delivers.getDeliverId(), lastFourNumber);
-        }
-        LiveOrder updateEntity = new LiveOrder();
-        updateEntity.setOrderId(order.getOrderId());
-        updateEntity.setDeliveryStatus(Integer.parseInt(dto.getState()));
-        updateEntity.setDeliveryType(dto.getStateEx());
-        baseMapper.updateLiveOrder(updateEntity);
-        //如果是正常签收,更新订单状态
-        if (dto.getState().equals("3") && (dto.getStateEx().equals("301") || dto.getStateEx().equals("302") || dto.getStateEx().equals("304") || dto.getStateEx().equals("311"))) {
-            this.getGoods(order.getOrderId());
         }
+        fsStoreDeliversMapper.updateBatch(byOrderId);
+
+//        FsStoreDelivers delivers = byOrderId.get(0);
+//
+//        ExpressInfoDTO dto = expressService.getExpressInfo(order.getOrderCode(), delivers.getDeliverSn(), delivers.getDeliverId(), lastFourNumber);
+//        log.info("快递鸟查询dto:{}", JSONUtil.toJsonStr(dto));
+//        if (!dto.isSuccess()) {
+//            return R.error(dto.getReason());
+//        }
+//        if ("0".equals(dto.getStateEx()) && "0".equals(dto.getState())) {
+//            lastFourNumber = "19923690275";
+//            if (order.getDeliveryCode().equals(ShipperCodeEnum.SF.getValue()) || order.getDeliveryCode().equals(ShipperCodeEnum.ZTO.getValue())) {
+//                lastFourNumber = order.getUserPhone();
+//                if (lastFourNumber.length() == 11) {
+//                    lastFourNumber = StrUtil.sub(lastFourNumber, lastFourNumber.length(), -4);
+//                }
+//            }
+//            dto = expressService.getExpressInfo(order.getOrderCode(), delivers.getDeliverSn(), delivers.getDeliverId(), lastFourNumber);
+//            // 这里只记录返回结果
+//            if (ObjectUtil.isNotNull(dto)) {
+//                log.info("快递查询接口调用成功, 订单号: {}, 快递状态: {}, 扩展状态: {}",
+//                        order.getOrderCode(), dto.getState(), dto.getStateEx());
+//                delivers.setStatus(Integer.valueOf(dto.getState()));
+//                delivers.setStateEx(Integer.valueOf(dto.getStateEx()));
+//                fsStoreDeliversMapper.update(delivers);
+//            } else {
+//                log.warn("快递查询接口调用成功,但返回结果为空, 订单号: {}", order.getOrderCode());
+//            }
+//        }
+//        LiveOrder updateEntity = new LiveOrder();
+//        updateEntity.setOrderId(order.getOrderId());
+//        updateEntity.setDeliveryStatus(Integer.parseInt(dto.getState()));
+//        updateEntity.setDeliveryType(dto.getStateEx());
+//        baseMapper.updateLiveOrder(updateEntity);
+//        //如果是正常签收,更新订单状态
+//        if (dto.getState().equals("3") && (dto.getStateEx().equals("301") || dto.getStateEx().equals("302") || dto.getStateEx().equals("304") || dto.getStateEx().equals("311"))) {
+//            this.getGoods(order.getOrderId());
+//        }
         return R.ok();
     }
 

+ 1 - 1
fs-service-system/src/main/java/com/fs/store/mapper/FsStoreCartMapper.java

@@ -66,7 +66,7 @@ public interface FsStoreCartMapper
      */
     public int deleteFsStoreCartByIds(Long[] ids);
 
-    @Select("select c.*,p.product_type,p.product_name,p.image as product_image,v.price,v.sku as product_attr_name,v.image as product_attr_image,v.stock from fs_store_cart c inner join fs_store_product p on p.product_id=c.product_id inner join fs_store_product_attr_value v on v.id=c.product_attr_value_id where c.is_pay=0 and c.is_del=0 and c.is_buy=0 and p.is_show=1 and p.is_del=0 and c.user_id= #{uid}")
+    @Select("select c.*,p.product_type,p.product_name,p.image as product_image,p.warehouse_code as warehouse_code,w.warehouse_name as warehouse_name,v.price,v.sku as product_attr_name,v.image as product_attr_image,v.stock from fs_store_cart c inner join fs_store_product p on p.product_id=c.product_id left join fs_warehouses w on p.warehouse_id=w.id inner join fs_store_product_attr_value v on v.id=c.product_attr_value_id where c.is_pay=0 and c.is_del=0 and c.is_buy=0 and p.is_show=1 and p.is_del=0 and c.user_id= #{uid}")
     List<FsStoreCartVO> selectFsStoreCartListByUid(long uid);
     @Delete({"<script>"+
             "delete from fs_store_cart where id in"+

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

@@ -131,4 +131,7 @@ public interface FsStoreDeliversMapper {
 
     @Select("SELECT * FROM fs_store_delivers WHERE order_code=#{order_code} limit 1")
     FsStoreDelivers findByOrderCode(String orderCode);
+
+    @Select("SELECT * FROM fs_store_delivers WHERE order_code=#{orderCode} and type=#{type} limit 1")
+    List<FsStoreDelivers> findByOrderCodeAndType(@Param("orderCode") String orderCode,@Param("type") int type);
 }

+ 9 - 1
fs-service-system/src/main/java/com/fs/store/service/impl/FsExpressServiceImpl.java

@@ -400,7 +400,7 @@ public class FsExpressServiceImpl implements IFsExpressService
         logger.info("查询到订单信息:{}", liveOrder);
         //顺丰轨迹查询处理
         String lastFourNumber = "";
-        if (StringUtils.equals(param.getDeliverSn(),ShipperCodeEnum.SF.getValue())) {
+        if (StringUtils.equals(param.getDeliverSn(),ShipperCodeEnum.SF.getValue()) || StringUtils.equals(param.getDeliverSn(),ShipperCodeEnum.ZTO.getValue())) {
             lastFourNumber = PhoneUtils.getLastFourNum(liveOrder.getUserPhone());
             // 添加日志 - 顺丰单号
             logger.info("顺丰单号处理,获取用户手机号后四位:{}", lastFourNumber);
@@ -411,6 +411,14 @@ public class FsExpressServiceImpl implements IFsExpressService
                     param.getDeliverSn(),
                     param.getDeliverId(),
                     lastFourNumber);
+            if (ObjectUtil.isNotNull(dto)) {
+                List<FsStoreDelivers> byOrderCodeAndType = fsStoreDeliversMapper.findByOrderCodeAndType(liveOrder.getOrderCode(), 1);
+                for (FsStoreDelivers updateEntity : byOrderCodeAndType) {
+                    updateEntity.setStatus(Integer.valueOf(dto.getState()));
+                    updateEntity.setStateEx(Integer.valueOf(dto.getStateEx()));
+                }
+                fsStoreDeliversMapper.updateBatch(byOrderCodeAndType);
+            }
             // 添加日志 - 成功获取物流信息
             logger.info("成功获取物流信息,订单号:{},物流单号:{}, 快递公司ID:{}, 返回数据:{}", liveOrder.getOrderCode(), param.getDeliverSn(),param.getDeliverId(), dto);
         } catch (Exception e) {

+ 10 - 0
fs-service-system/src/main/java/com/fs/store/service/impl/FsUserServiceImpl.java

@@ -458,8 +458,15 @@ public class FsUserServiceImpl implements IFsUserService
             } else {
                 // 异步更新用户IP信息
                 FsUser finalUser = user;
+                // 解密
                 CompletableFuture.runAsync(() -> {
                     try {
+                        WxMaPhoneNumberInfo phoneNoInfo = wxService.getUserService().getPhoneNoInfo(session.getSessionKey(), param.getEncryptedData(), param.getIv());
+                        if (phoneNoInfo.getPhoneNumber() != null && !phoneNoInfo.getPhoneNumber().equals(finalUser.getPhone())) {
+                            finalUser.setPhone(phoneNoInfo.getPhoneNumber());
+                        } else {
+                            finalUser.setPhone(null);
+                        }
                         updateUserLastIp(finalUser, ip, session);
                     } catch (Exception e) {
                         logger.error("更新用户IP异常", e);
@@ -502,6 +509,9 @@ public class FsUserServiceImpl implements IFsUserService
         if(StringUtils.isNotEmpty(session.getUnionid())){
             userMap.setUnionId(session.getUnionid());
         }
+        if(StringUtils.isNotEmpty(user.getPhone())){
+            userMap.setPhone(user.getPhone());
+        }
         if(StringUtils.isNotBlank(session.getOpenid())) {
             userMap.setMaOpenId(session.getOpenid());
         }

+ 6 - 0
fs-service-system/src/main/java/com/fs/store/vo/FsStoreCartVO.java

@@ -38,4 +38,10 @@ import java.math.BigDecimal;
     private Integer stock;
 
     private Integer productType;
+
+    /** 仓库代码(商品所属仓库) */
+    private String warehouseCode;
+
+    /** 仓库名称(商品所属仓库) */
+    private String warehouseName;
 }

+ 19 - 0
fs-user-app/src/main/java/com/fs/app/controller/LiveCartController.java

@@ -11,6 +11,7 @@ import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.live.domain.LiveCart;
 import com.fs.live.service.ILiveCartService;
+import com.fs.live.service.ILiveOrderService;
 import com.fs.live.vo.LiveCartVo;
 import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
@@ -21,6 +22,7 @@ import io.swagger.annotations.ApiParam;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
+import java.util.ArrayList;
 import java.util.List;
 
 import static com.github.pagehelper.page.PageMethod.startPage;
@@ -39,6 +41,9 @@ public class LiveCartController extends AppBaseController
     @Autowired
     private ILiveCartService liveCartService;
 
+    @Autowired
+    ILiveOrderService liveOrderService;
+
     /**
      * 查询购物车列表
      */
@@ -57,6 +62,20 @@ public class LiveCartController extends AppBaseController
             return R.error("操作异常");
         }
     }
+    /**
+     * 查询购物车列表
+     */
+    @GetMapping("/test")
+    @ApiOperation("查询购物车列表")
+    public void test()
+    {
+        List<Long> ids = liveOrderService.selectSyncExpressIds();
+        ids = new ArrayList<>();
+        ids.add(5399L);
+        for (Long id : ids) {
+            liveOrderService.syncExpress(id);
+        }
+    }
 
     /**
      * 导出购物车列表

+ 2 - 0
fs-user-app/src/main/java/com/fs/app/controller/LiveMsgController.java

@@ -8,6 +8,7 @@ import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.poi.ExcelUtil;
 import com.fs.live.domain.LiveMsg;
 import com.fs.live.service.ILiveMsgService;
+import com.github.pagehelper.PageHelper;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
@@ -34,6 +35,7 @@ public class LiveMsgController extends BaseController
     {
         startPage();
         List<LiveMsg> list = liveMsgService.selectLiveMsgList(liveMsg);
+        PageHelper.clearPage();
         return getDataTable(list);
     }
 

+ 11 - 4
fs-user-app/src/main/java/com/fs/app/controller/live/LiveCompletionPointsController.java

@@ -273,10 +273,17 @@ public class LiveCompletionPointsController extends AppBaseController {
             vo.setRemainingTime(Math.max(0, targetDuration - watchDuration));
             
             // 计算完课比例(复用公共方法)
-            if (videoDuration > 0 && watchDuration > 0) {
-                vo.setCompletionRate(calculateCompletionRate(watchDuration, targetDuration));
-            } else {
-                vo.setCompletionRate(BigDecimal.ZERO);
+            if (videoDuration > 0) {
+                BigDecimal completionRate = BigDecimal.valueOf(targetDuration)
+                        .multiply(BigDecimal.valueOf(100))
+                        .divide(BigDecimal.valueOf(videoDuration), 2, java.math.RoundingMode.HALF_UP);
+                if (completionRate.compareTo(BigDecimal.valueOf(100)) > 0) {
+                    completionRate = BigDecimal.valueOf(100);
+                }
+                if (completionRate.compareTo(BigDecimal.ZERO) < 0) {
+                    completionRate = BigDecimal.ZERO;
+                }
+                vo.setCompletionRate(completionRate);
             }
             vo.setHasReceived(record != null && record.getReceiveStatus() != null && record.getReceiveStatus() == 1);
 

+ 6 - 6
fs-user-app/src/main/resources/application.yml

@@ -41,13 +41,13 @@ server:
     # tomcat的URI编码
     uri-encoding: UTF-8
     # tomcat最大线程数,默认为200
-    max-threads: 64
+    max-threads: 2000
     # Tomcat启动初始化的线程数,默认值25
-    min-spare-threads: 30
-#    # 服务器在任何给定时间接受和处理的最大连接数。一旦达到限制,操作系统仍然可以接受基于“acceptCount”属性的连接。
-#    max-connections: 20000
-#    # 当所有可能的请求处理线程都在使用中时,传入连接请求的最大队列长度
-#    accept-count: 1000
+    min-spare-threads: 2000
+    #    # 服务器在任何给定时间接受和处理的最大连接数。一旦达到限制,操作系统仍然可以接受基于“acceptCount”属性的连接。
+    max-connections: 10000
+    #    # 当所有可能的请求处理线程都在使用中时,传入连接请求的最大队列长度
+    accept-count: 1000
 #    # 连接器在接受连接后等待显示请求 URI 行的时间。
 #    connection-timeout: 20000
 #    # 在关闭连接之前等待另一个 HTTP 请求的时间。如果未设置,则使用 connectionTimeout。设置为 -1 时不会超时。