Browse Source

确认微信模板信息是否发送

Yangzw 10 months ago
parent
commit
b6eee15bb4
33 changed files with 1325 additions and 699 deletions
  1. 14 0
      feifan-module-mall/feifan-module-trade-api/src/main/java/cn/newfeifan/mall/module/trade/enums/MessageTemplateConstants.java
  2. 20 0
      feifan-module-mall/feifan-module-trade-api/src/main/java/cn/newfeifan/mall/module/trade/enums/wxmessage/WcChatMessageTemplateIdEnum.java
  3. 0 1
      feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/controller/admin/messagelog/vo/MessageLogSaveReqVO.java
  4. 7 9
      feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/controller/admin/order/TradeOrderController.java
  5. 7 0
      feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/dal/mysql/order/TradeOrderItemMapper.java
  6. 2 0
      feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/service/delivery/DeliveryExpressService.java
  7. 5 0
      feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/service/delivery/DeliveryExpressServiceImpl.java
  8. 541 521
      feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/service/order/TradeOrderUpdateServiceImpl.java
  9. 95 10
      feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/utils/wechat/WcChatMessageUtils.java
  10. 1 0
      feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/service/user/MemberUserService.java
  11. 6 0
      feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/service/user/MemberUserServiceImpl.java
  12. 5 0
      feifan-module-system/feifan-module-system-api/src/main/java/cn/newfeifan/mall/module/system/constant/SystemConstants.java
  13. 1 0
      feifan-module-system/feifan-module-system-api/src/main/java/cn/newfeifan/mall/module/system/enums/ErrorCodeConstants.java
  14. 64 0
      feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/config/StartConfig.java
  15. 94 0
      feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/controller/admin/config/SystemConfigController.java
  16. 31 0
      feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/controller/admin/config/bo/SystemConfigBO.java
  17. 36 0
      feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/controller/admin/config/vo/ConfigPageReqVO.java
  18. 41 0
      feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/controller/admin/config/vo/ConfigRespVO.java
  19. 28 0
      feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/controller/admin/config/vo/ConfigSaveReqVO.java
  20. 17 0
      feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/controller/admin/wechatmsgtemplate/bo/WechatMsgTemplateBO.java
  21. 48 0
      feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/dal/dataobject/config/SystemConfigDO.java
  22. 29 0
      feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/dal/mysql/config/SystemConfigMapper.java
  23. 1 1
      feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/dal/mysql/social/SocialUserMapper.java
  24. 65 0
      feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/service/config/SystemConfigService.java
  25. 97 0
      feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/service/config/SystemConfigServiceImpl.java
  26. 1 1
      feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/service/social/SocialUserService.java
  27. 2 2
      feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/service/social/SocialUserServiceImpl.java
  28. 10 2
      feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/service/wechatmsgtemplate/WechatMsgTemplateService.java
  29. 27 2
      feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/service/wechatmsgtemplate/WechatMsgTemplateServiceImpl.java
  30. 12 0
      feifan-module-system/feifan-module-system-biz/src/main/resources/mapper/config/ConfigMapper.xml
  31. 2 2
      feifan-module-system/feifan-module-system-biz/src/main/resources/mapper/social/SocialUserMapper.xml
  32. 0 134
      feifan-module-system/feifan-module-system-biz/src/test/java/cn/newfeifan/mall/module/system/service/wechatmsgtemplate/WechatMsgTemplateServiceImplTest.java
  33. 16 14
      sql/mysql/建空库SQL/8_20240512.sql

+ 14 - 0
feifan-module-mall/feifan-module-trade-api/src/main/java/cn/newfeifan/mall/module/trade/enums/MessageTemplateConstants.java

@@ -1,6 +1,9 @@
 package cn.newfeifan.mall.module.trade.enums;
 
 // TODO @非繁人:枚举
+
+import java.util.Arrays;
+
 /**
  * 通知模板枚举类
  *
@@ -13,4 +16,15 @@ public interface MessageTemplateConstants {
     String BROKERAGE_WITHDRAW_AUDIT_APPROVE = "brokerage_withdraw_audit_approve"; // 佣金提现(审核通过)
     String BROKERAGE_WITHDRAW_AUDIT_REJECT = "brokerage_withdraw_audit_reject"; // 佣金提现(审核不通过)
 
+    /**
+     * 售后订单待审核通知需要的权限
+     */
+    String[] AFTER_SALE_NO_CHECK_List = Arrays.asList("trade:after-sale:query", "trade:after-sale:agree", "trade:after-sale:disagree"
+            , "trade:after-sale:receive", "trade:after-sale:receive", "trade:after-sale:refund").toArray(new String[0]);
+
+    /**
+     * 订单待发货通知需要的权限
+     */
+    String[] ORDER_NO_DELIVERY_List = Arrays.asList("trade:order:query", "trade:order:update", "trade:order:pick-up").toArray(new String[0]);
+
 }

+ 20 - 0
feifan-module-mall/feifan-module-trade-api/src/main/java/cn/newfeifan/mall/module/trade/enums/wxmessage/WcChatMessageTemplateIdEnum.java

@@ -0,0 +1,20 @@
+package cn.newfeifan.mall.module.trade.enums.wxmessage;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+/**
+ * 自定义的微信消息模板枚举
+ */
+@Getter
+@RequiredArgsConstructor
+public enum WcChatMessageTemplateIdEnum {
+
+    ORDER_DELIVERY("1","订单发货通知"),
+    AFTER_SALE_CHECK("2","售后订单审核通知"),
+    AFTER_SALE_NO_CHECK("3","售后订单待审核通知"),
+    ORDER_NO_DELIVERY("4","订单待发货通知");
+
+    private final String templateId;
+    private final String name;
+}

+ 0 - 1
feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/controller/admin/messagelog/vo/MessageLogSaveReqVO.java

@@ -22,7 +22,6 @@ public class MessageLogSaveReqVO {
     private Long memberUserId;
 
     @Schema(description = "系统用户ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "13077")
-    @NotNull(message = "系统用户ID不能为空")
     private Long systemUserId;
 
     @Schema(description = "微信消息模板ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "13313")

+ 7 - 9
feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/controller/admin/order/TradeOrderController.java

@@ -58,7 +58,6 @@ import static cn.newfeifan.mall.framework.common.util.collection.CollectionUtils
 import static cn.newfeifan.mall.framework.common.util.collection.CollectionUtils.convertSet;
 import static cn.newfeifan.mall.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
 import static cn.newfeifan.mall.module.trade.enums.ErrorCodeConstants.CALLBACK_PARAMETER_ERROR;
-import static cn.newfeifan.mall.module.trade.enums.ErrorCodeConstants.CREATE_TRADE_ORDER_LOGS_ERROR;
 
 @Tag(name = "管理后台 - 交易订单")
 @RestController
@@ -190,6 +189,7 @@ public class TradeOrderController {
         subscribeResp.setReturnCode("200");
         subscribeResp.setMessage("成功");
         //加密如果相等,属于快递100推送;否则可以忽略掉当前请求
+        ObjectMapper mapper = new ObjectMapper();
         if (ourSign.equals(sign)) {
             //判断订单状态是否是已签收
             if (state.equals(TradeOrderStateEnum.RECEIVED.getState())) {
@@ -201,16 +201,14 @@ public class TradeOrderController {
                 tradeOrderUpdateService.updateOrderById(order);
             }
 
-            //添加到日志
-            ObjectMapper mapper = new ObjectMapper();
-            try {
-                orderCallbackLogsService.create(orderId, param, mapper.writeValueAsString(lastResult), lastResult.get("status").toString());
-            } catch (JsonProcessingException e) {
-                throw exception(CREATE_TRADE_ORDER_LOGS_ERROR);
-            }
             return subscribeResp;
         }
-        orderCallbackLogsService.create(orderId, param, null, lastResult.get("status").toString());
+        //添加到日志
+        try {
+            orderCallbackLogsService.create(orderId, param, mapper.writeValueAsString(lastResult), lastResult.get("status").toString());
+        } catch (JsonProcessingException e) {
+            throw new RuntimeException(e);
+        }
         return null;
     }
 

+ 7 - 0
feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/dal/mysql/order/TradeOrderItemMapper.java

@@ -5,6 +5,7 @@ import cn.hutool.core.map.MapUtil;
 import cn.newfeifan.mall.framework.mybatis.core.mapper.BaseMapperX;
 import cn.newfeifan.mall.framework.mybatis.core.query.LambdaQueryWrapperX;
 import cn.newfeifan.mall.module.trade.dal.dataobject.order.TradeOrderItemDO;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import org.apache.ibatis.annotations.Mapper;
@@ -14,6 +15,7 @@ import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 @Mapper
 public interface TradeOrderItemMapper extends BaseMapperX<TradeOrderItemDO> {
@@ -53,4 +55,9 @@ public interface TradeOrderItemMapper extends BaseMapperX<TradeOrderItemDO> {
         return CollUtil.getFirst(result) != null ? MapUtil.getInt(result.get(0), "sumCount") : 0;
     }
 
+    default String getSupNameByOrderId(Long orderId){
+        List<TradeOrderItemDO> tradeOrderItemDOS = selectList(new LambdaQueryWrapper<TradeOrderItemDO>()
+                .eq(TradeOrderItemDO::getOrderId, orderId));
+        return tradeOrderItemDOS.stream().map(TradeOrderItemDO::getSpuName).collect(Collectors.joining(","));
+    }
 }

+ 2 - 0
feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/service/delivery/DeliveryExpressService.java

@@ -80,4 +80,6 @@ public interface DeliveryExpressService {
     List<DeliveryExpressDO> getDeliveryExpressListByStatus(Integer status);
 
     DeliveryExpressDO selectByCode(String code);
+
+    String getDeliveryNameById(Long id);
 }

+ 5 - 0
feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/service/delivery/DeliveryExpressServiceImpl.java

@@ -116,4 +116,9 @@ public class DeliveryExpressServiceImpl implements DeliveryExpressService {
         return deliveryExpressMapper.selectByCode(code);
     }
 
+    @Override
+    public String getDeliveryNameById(Long id) {
+        return deliveryExpressMapper.selectById(id).getName();
+    }
+
 }

+ 541 - 521
feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/service/order/TradeOrderUpdateServiceImpl.java

@@ -37,6 +37,7 @@ import cn.newfeifan.mall.module.trade.dal.mysql.order.TradeOrderMapper;
 import cn.newfeifan.mall.module.trade.dal.redis.no.TradeNoRedisDAO;
 import cn.newfeifan.mall.module.trade.enums.delivery.DeliveryTypeEnum;
 import cn.newfeifan.mall.module.trade.enums.order.*;
+import cn.newfeifan.mall.module.trade.enums.wxmessage.WcChatMessageTemplateIdEnum;
 import cn.newfeifan.mall.module.trade.framework.order.config.TradeOrderProperties;
 import cn.newfeifan.mall.module.trade.framework.order.core.annotations.TradeOrderLog;
 import cn.newfeifan.mall.module.trade.framework.order.core.utils.TradeOrderLogUtils;
@@ -49,6 +50,7 @@ import cn.newfeifan.mall.module.trade.service.price.TradePriceService;
 import cn.newfeifan.mall.module.trade.service.price.bo.TradePriceCalculateReqBO;
 import cn.newfeifan.mall.module.trade.service.price.bo.TradePriceCalculateRespBO;
 import cn.newfeifan.mall.module.trade.service.price.calculator.TradePriceCalculatorHelper;
+import cn.newfeifan.mall.module.trade.utils.wechat.WcChatMessageUtils;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.google.gson.Gson;
 import com.google.gson.JsonObject;
@@ -67,6 +69,7 @@ import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
 import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
@@ -117,6 +120,8 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
 
     @Resource
     private TradeOrderProperties tradeOrderProperties;
+    @Resource
+    private WcChatMessageUtils wcChatMessageUtils;
 
     @Value("${feifan.trade.express.kd100.key}")
     private String key;
@@ -289,6 +294,9 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
         // 4. 记录订单日志
         TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), TradeOrderStatusEnum.UNDELIVERED.getStatus());
         TradeOrderLogUtils.setUserInfo(order.getUserId(), UserTypeEnum.MEMBER.getValue());
+
+        // 5. 发送订单待发货消息
+
     }
 
     /**
@@ -391,614 +399,626 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
         // 4. 发送站内信
         tradeMessageService.sendMessageWhenDeliveryOrder(new TradeOrderMessageWhenDeliveryOrderReqBO()
                 .setOrderId(order.getId()).setUserId(order.getUserId()).setMessage(null));
+
+        //5.发送微信模板消息
+        List<String> params = new ArrayList<>();
+        params.add(order.getNo());
+        params.add(deliveryExpressService.getDeliveryNameById(order.getLogisticsId()));
+        params.add(order.getLogisticsNo());
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+        params.add(LocalDateTime.now().format(formatter));
+        params.add(tradeOrderItemMapper.getSupNameByOrderId(order.getId()));
+        wcChatMessageUtils.sendWcChatMessage(order.getUserId(), WcChatMessageTemplateIdEnum.ORDER_DELIVERY.getTemplateId(),
+                params, null,order.getUserId(), order.getId());
     }
 
-    /**
-     * 测试订阅物流信息
-     *
-     * @param order 交易订单对象,包含物流信息和接收人手机号
-     * @throws Exception 抛出异常,可能由于外部服务调用失败等原因
-     */
-    private void testSubscribe(TradeOrderDO order) throws Exception {
-        // 根据物流ID获取配送信息
-        DeliveryExpressDO deliveryExpress = deliveryExpressService.getDeliveryExpress(order.getLogisticsId());
-
-        // 设置订阅参数,包括回调URL和手机号
-        SubscribeParameters subscribeParameters = new SubscribeParameters();
-        subscribeParameters.setCallbackurl("http://47.107.28.221:8002/admin-api/trade/order/callBackUrl?orderId="+order.getId());
-        subscribeParameters.setPhone(order.getReceiverMobile());
-        //添加盐
-        subscribeParameters.setSalt(order.getLogisticsNo());
-
-        // 创建订阅参数实例,并设置相关公司代码、物流单号和密钥
-        SubscribeParam subscribeParam = new SubscribeParam();
-        subscribeParam.setParameters(subscribeParameters);
-        subscribeParam.setCompany(deliveryExpress.getCode());
-        subscribeParam.setNumber(order.getLogisticsNo());
-        subscribeParam.setKey(key);
-
-        // 构建订阅请求对象,设置请求模式和参数
-        SubscribeReq subscribeReq = new SubscribeReq();
-        subscribeReq.setSchema(ApiInfoConstant.SUBSCRIBE_SCHEMA);
-        subscribeReq.setParam(new Gson().toJson(subscribeParam));
-
-        // 调用订阅服务,并打印执行结果
-        IBaseClient subscribe = new Subscribe();
-        HttpResult execute = subscribe.execute(subscribeReq);
-
-        Gson gson = new Gson();
-        JsonObject jsonObject = gson.fromJson(execute.getBody(), JsonObject.class);
-        boolean result = jsonObject.get("result").getAsBoolean();
-        String returnCode = jsonObject.get("returnCode").getAsString();
-
-        if (result && returnCode.equals("200")) {
-            log.info("订单号:{}:订阅成功",order.getLogisticsNo());
-
-            order.setSubscriptionLogisticsInfo(TradeOrderSubscribeStatusEnum.SUBSCRIBE.getStatus());
-        } else if(returnCode.equals("600") || returnCode.equals("601")) {
-            throw exception(NOT_SUFFICIENT_FUNDS);
-        } else {
-            log.info("订单号:{}:订阅失败",order.getLogisticsNo());
+/**
+ * 订阅物流信息
+ *
+ * @param order 交易订单对象,包含物流信息和接收人手机号
+ * @throws Exception 抛出异常,可能由于外部服务调用失败等原因
+ */
+private void testSubscribe(TradeOrderDO order) throws Exception {
+    // 根据物流ID获取配送信息
+    DeliveryExpressDO deliveryExpress = deliveryExpressService.getDeliveryExpress(order.getLogisticsId());
+
+    // 设置订阅参数,包括回调URL和手机号
+    SubscribeParameters subscribeParameters = new SubscribeParameters();
+    subscribeParameters.setCallbackurl("http://47.107.28.221:8002/admin-api/trade/order/callBackUrl?orderId=" + order.getId());
+    subscribeParameters.setPhone(order.getReceiverMobile());
+    //添加盐
+    subscribeParameters.setSalt(order.getLogisticsNo());
+
+    // 创建订阅参数实例,并设置相关公司代码、物流单号和密钥
+    SubscribeParam subscribeParam = new SubscribeParam();
+    subscribeParam.setParameters(subscribeParameters);
+    subscribeParam.setCompany(deliveryExpress.getCode());
+    subscribeParam.setNumber(order.getLogisticsNo());
+    subscribeParam.setKey(key);
+
+    // 构建订阅请求对象,设置请求模式和参数
+    SubscribeReq subscribeReq = new SubscribeReq();
+    subscribeReq.setSchema(ApiInfoConstant.SUBSCRIBE_SCHEMA);
+    subscribeReq.setParam(new Gson().toJson(subscribeParam));
+
+    // 调用订阅服务,并打印执行结果
+    IBaseClient subscribe = new Subscribe();
+    HttpResult execute = subscribe.execute(subscribeReq);
+
+    Gson gson = new Gson();
+    JsonObject jsonObject = gson.fromJson(execute.getBody(), JsonObject.class);
+    boolean result = jsonObject.get("result").getAsBoolean();
+    String returnCode = jsonObject.get("returnCode").getAsString();
+
+    if (result && returnCode.equals("200")) {
+        log.info("订单号:{}:订阅成功", order.getLogisticsNo());
+
+        order.setSubscriptionLogisticsInfo(TradeOrderSubscribeStatusEnum.SUBSCRIBE.getStatus());
+    } else if (returnCode.equals("600") || returnCode.equals("601")) {
+        throw exception(NOT_SUFFICIENT_FUNDS);
+    } else {
+        log.info("订单号:{}:订阅失败", order.getLogisticsNo());
+
+        order.setSubscriptionLogisticsInfo(TradeOrderSubscribeStatusEnum.abnormal.getStatus());
+    }
+    tradeOrderMapper.updateById(order);
 
-            order.setSubscriptionLogisticsInfo(TradeOrderSubscribeStatusEnum.abnormal.getStatus());
-        }
-        tradeOrderMapper.updateById(order);
+}
 
+/**
+ * 校验交易订单满足被发货的条件
+ * <p>
+ * 1. 交易订单未发货
+ *
+ * @param id 交易订单编号
+ * @return 交易订单
+ */
+private TradeOrderDO validateOrderDeliverable(Long id) {
+    TradeOrderDO order = validateOrderExists(id);
+    // 1. 校验订单是否未发货
+    if (ObjectUtil.notEqual(TradeOrderRefundStatusEnum.NONE.getStatus(), order.getRefundStatus())) {
+        throw exception(ORDER_DELIVERY_FAIL_REFUND_STATUS_NOT_NONE);
     }
 
-    /**
-     * 校验交易订单满足被发货的条件
-     * <p>
-     * 1. 交易订单未发货
-     *
-     * @param id 交易订单编号
-     * @return 交易订单
-     */
-    private TradeOrderDO validateOrderDeliverable(Long id) {
-        TradeOrderDO order = validateOrderExists(id);
-        // 1. 校验订单是否未发货
-        if (ObjectUtil.notEqual(TradeOrderRefundStatusEnum.NONE.getStatus(), order.getRefundStatus())) {
-            throw exception(ORDER_DELIVERY_FAIL_REFUND_STATUS_NOT_NONE);
-        }
+    // 2. 执行 TradeOrderHandler 前置处理
+    tradeOrderHandlers.forEach(handler -> handler.beforeDeliveryOrder(order));
+    return order;
+}
 
-        // 2. 执行 TradeOrderHandler 前置处理
-        tradeOrderHandlers.forEach(handler -> handler.beforeDeliveryOrder(order));
-        return order;
+@NotNull
+private TradeOrderDO validateOrderExists(Long id) {
+    // 校验订单是否存在
+    TradeOrderDO order = tradeOrderMapper.selectById(id);
+    if (order == null) {
+        throw exception(ORDER_NOT_FOUND);
     }
+    return order;
+}
 
-    @NotNull
-    private TradeOrderDO validateOrderExists(Long id) {
-        // 校验订单是否存在
-        TradeOrderDO order = tradeOrderMapper.selectById(id);
-        if (order == null) {
-            throw exception(ORDER_NOT_FOUND);
-        }
-        return order;
-    }
+@Override
+@Transactional(rollbackFor = Exception.class)
+@TradeOrderLog(operateType = TradeOrderOperateTypeEnum.MEMBER_RECEIVE)
+public void receiveOrderByMember(Long userId, Long id) {
+    // 校验并获得交易订单(可收货)
+    TradeOrderDO order = validateOrderReceivable(userId, id);
 
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.MEMBER_RECEIVE)
-    public void receiveOrderByMember(Long userId, Long id) {
-        // 校验并获得交易订单(可收货)
-        TradeOrderDO order = validateOrderReceivable(userId, id);
+    // 收货订单
+    receiveOrder0(order);
+}
 
-        // 收货订单
-        receiveOrder0(order);
+@Override
+public int receiveOrderBySystem() {
+    // 1. 查询过期的待支付订单
+    LocalDateTime expireTime = minusTime(tradeOrderProperties.getReceiveExpireTime());
+    List<TradeOrderDO> orders = tradeOrderMapper.selectListByStatusAndDeliveryTimeLt(
+            TradeOrderStatusEnum.DELIVERED.getStatus(), expireTime);
+    if (CollUtil.isEmpty(orders)) {
+        return 0;
     }
 
-    @Override
-    public int receiveOrderBySystem() {
-        // 1. 查询过期的待支付订单
-        LocalDateTime expireTime = minusTime(tradeOrderProperties.getReceiveExpireTime());
-        List<TradeOrderDO> orders = tradeOrderMapper.selectListByStatusAndDeliveryTimeLt(
-                TradeOrderStatusEnum.DELIVERED.getStatus(), expireTime);
-        if (CollUtil.isEmpty(orders)) {
-            return 0;
-        }
-
-        // 2. 遍历执行,逐个取消
-        int count = 0;
-        for (TradeOrderDO order : orders) {
-            try {
-                getSelf().receiveOrderBySystem(order);
-                count++;
-            } catch (Throwable e) {
-                log.error("[receiveOrderBySystem][order({}) 自动收货订单异常]", order.getId(), e);
-            }
+    // 2. 遍历执行,逐个取消
+    int count = 0;
+    for (TradeOrderDO order : orders) {
+        try {
+            getSelf().receiveOrderBySystem(order);
+            count++;
+        } catch (Throwable e) {
+            log.error("[receiveOrderBySystem][order({}) 自动收货订单异常]", order.getId(), e);
         }
-        return count;
     }
+    return count;
+}
 
-    /**
-     * 自动收货单个订单
-     *
-     * @param order 订单
-     */
-    @Transactional(rollbackFor = Exception.class)
-    @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.SYSTEM_RECEIVE)
-    public void receiveOrderBySystem(TradeOrderDO order) {
-        receiveOrder0(order);
+/**
+ * 自动收货单个订单
+ *
+ * @param order 订单
+ */
+@Transactional(rollbackFor = Exception.class)
+@TradeOrderLog(operateType = TradeOrderOperateTypeEnum.SYSTEM_RECEIVE)
+public void receiveOrderBySystem(TradeOrderDO order) {
+    receiveOrder0(order);
+}
+
+/**
+ * 收货订单的核心实现
+ *
+ * @param order 订单
+ */
+private void receiveOrder0(TradeOrderDO order) {
+    // 更新 TradeOrderDO 状态为已完成
+    int updateCount = tradeOrderMapper.updateByIdAndStatus(order.getId(), order.getStatus(),
+            new TradeOrderDO().setStatus(TradeOrderStatusEnum.COMPLETED.getStatus()).setReceiveTime(LocalDateTime.now()));
+    if (updateCount == 0) {
+        throw exception(ORDER_RECEIVE_FAIL_STATUS_NOT_DELIVERED);
     }
 
-    /**
-     * 收货订单的核心实现
-     *
-     * @param order 订单
-     */
-    private void receiveOrder0(TradeOrderDO order) {
-        // 更新 TradeOrderDO 状态为已完成
-        int updateCount = tradeOrderMapper.updateByIdAndStatus(order.getId(), order.getStatus(),
-                new TradeOrderDO().setStatus(TradeOrderStatusEnum.COMPLETED.getStatus()).setReceiveTime(LocalDateTime.now()));
-        if (updateCount == 0) {
-            throw exception(ORDER_RECEIVE_FAIL_STATUS_NOT_DELIVERED);
-        }
+    // 插入订单日志
+    TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), TradeOrderStatusEnum.COMPLETED.getStatus());
+}
 
-        // 插入订单日志
-        TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), TradeOrderStatusEnum.COMPLETED.getStatus());
+/**
+ * 校验交易订单满足可售货的条件
+ * <p>
+ * 1. 交易订单待收货
+ *
+ * @param userId 用户编号
+ * @param id     交易订单编号
+ * @return 交易订单
+ */
+private TradeOrderDO validateOrderReceivable(Long userId, Long id) {
+    // 校验订单是否存在
+    TradeOrderDO order = tradeOrderMapper.selectByIdAndUserId(id, userId);
+    if (order == null) {
+        throw exception(ORDER_NOT_FOUND);
     }
+    // 校验订单是否是待收货状态
+    if (!TradeOrderStatusEnum.isDelivered(order.getStatus())) {
+        throw exception(ORDER_RECEIVE_FAIL_STATUS_NOT_DELIVERED);
+    }
+    return order;
+}
 
-    /**
-     * 校验交易订单满足可售货的条件
-     * <p>
-     * 1. 交易订单待收货
-     *
-     * @param userId 用户编号
-     * @param id     交易订单编号
-     * @return 交易订单
-     */
-    private TradeOrderDO validateOrderReceivable(Long userId, Long id) {
-        // 校验订单是否存在
-        TradeOrderDO order = tradeOrderMapper.selectByIdAndUserId(id, userId);
-        if (order == null) {
-            throw exception(ORDER_NOT_FOUND);
-        }
-        // 校验订单是否是待收货状态
-        if (!TradeOrderStatusEnum.isDelivered(order.getStatus())) {
-            throw exception(ORDER_RECEIVE_FAIL_STATUS_NOT_DELIVERED);
-        }
-        return order;
+@Override
+@Transactional(rollbackFor = Exception.class)
+@TradeOrderLog(operateType = TradeOrderOperateTypeEnum.MEMBER_CANCEL)
+public void cancelOrderByMember(Long userId, Long id) {
+    // 1.1 校验存在
+    TradeOrderDO order = tradeOrderMapper.selectOrderByIdAndUserId(id, userId);
+    if (order == null) {
+        throw exception(ORDER_NOT_FOUND);
+    }
+    // 1.2 校验状态
+    if (ObjectUtil.notEqual(order.getStatus(), TradeOrderStatusEnum.UNPAID.getStatus())) {
+        throw exception(ORDER_CANCEL_FAIL_STATUS_NOT_UNPAID);
     }
 
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.MEMBER_CANCEL)
-    public void cancelOrderByMember(Long userId, Long id) {
-        // 1.1 校验存在
-        TradeOrderDO order = tradeOrderMapper.selectOrderByIdAndUserId(id, userId);
-        if (order == null) {
-            throw exception(ORDER_NOT_FOUND);
-        }
-        // 1.2 校验状态
-        if (ObjectUtil.notEqual(order.getStatus(), TradeOrderStatusEnum.UNPAID.getStatus())) {
-            throw exception(ORDER_CANCEL_FAIL_STATUS_NOT_UNPAID);
-        }
+    // 2. 取消订单
+    cancelOrder0(order, TradeOrderCancelTypeEnum.MEMBER_CANCEL);
+}
 
-        // 2. 取消订单
-        cancelOrder0(order, TradeOrderCancelTypeEnum.MEMBER_CANCEL);
+@Override
+public int cancelOrderBySystem() {
+    // 1. 查询过期的待支付订单
+    LocalDateTime expireTime = minusTime(tradeOrderProperties.getPayExpireTime());
+    List<TradeOrderDO> orders = tradeOrderMapper.selectListByStatusAndCreateTimeLt(
+            TradeOrderStatusEnum.UNPAID.getStatus(), expireTime);
+    if (CollUtil.isEmpty(orders)) {
+        return 0;
     }
 
-    @Override
-    public int cancelOrderBySystem() {
-        // 1. 查询过期的待支付订单
-        LocalDateTime expireTime = minusTime(tradeOrderProperties.getPayExpireTime());
-        List<TradeOrderDO> orders = tradeOrderMapper.selectListByStatusAndCreateTimeLt(
-                TradeOrderStatusEnum.UNPAID.getStatus(), expireTime);
-        if (CollUtil.isEmpty(orders)) {
-            return 0;
-        }
-
-        // 2. 遍历执行,逐个取消
-        int count = 0;
-        for (TradeOrderDO order : orders) {
-            try {
-                getSelf().cancelOrderBySystem(order);
-                count++;
-            } catch (Throwable e) {
-                log.error("[cancelOrderBySystem][order({}) 过期订单异常]", order.getId(), e);
-            }
+    // 2. 遍历执行,逐个取消
+    int count = 0;
+    for (TradeOrderDO order : orders) {
+        try {
+            getSelf().cancelOrderBySystem(order);
+            count++;
+        } catch (Throwable e) {
+            log.error("[cancelOrderBySystem][order({}) 过期订单异常]", order.getId(), e);
         }
-        return count;
     }
+    return count;
+}
 
-    /**
-     * 自动取消单个订单
-     *
-     * @param order 订单
-     */
-    @Transactional(rollbackFor = Exception.class)
-    @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.SYSTEM_CANCEL)
-    public void cancelOrderBySystem(TradeOrderDO order) {
-        cancelOrder0(order, TradeOrderCancelTypeEnum.PAY_TIMEOUT);
+/**
+ * 自动取消单个订单
+ *
+ * @param order 订单
+ */
+@Transactional(rollbackFor = Exception.class)
+@TradeOrderLog(operateType = TradeOrderOperateTypeEnum.SYSTEM_CANCEL)
+public void cancelOrderBySystem(TradeOrderDO order) {
+    cancelOrder0(order, TradeOrderCancelTypeEnum.PAY_TIMEOUT);
+}
+
+/**
+ * 取消订单的核心实现
+ *
+ * @param order      订单
+ * @param cancelType 取消类型
+ */
+private void cancelOrder0(TradeOrderDO order, TradeOrderCancelTypeEnum cancelType) {
+    // 1. 更新 TradeOrderDO 状态为已取消
+    int updateCount = tradeOrderMapper.updateByIdAndStatus(order.getId(), order.getStatus(),
+            new TradeOrderDO().setStatus(TradeOrderStatusEnum.CANCELED.getStatus())
+                    .setCancelType(cancelType.getType()).setCancelTime(LocalDateTime.now()));
+    if (updateCount == 0) {
+        throw exception(ORDER_CANCEL_FAIL_STATUS_NOT_UNPAID);
     }
 
-    /**
-     * 取消订单的核心实现
-     *
-     * @param order      订单
-     * @param cancelType 取消类型
-     */
-    private void cancelOrder0(TradeOrderDO order, TradeOrderCancelTypeEnum cancelType) {
-        // 1. 更新 TradeOrderDO 状态为已取消
-        int updateCount = tradeOrderMapper.updateByIdAndStatus(order.getId(), order.getStatus(),
-                new TradeOrderDO().setStatus(TradeOrderStatusEnum.CANCELED.getStatus())
-                        .setCancelType(cancelType.getType()).setCancelTime(LocalDateTime.now()));
-        if (updateCount == 0) {
-            throw exception(ORDER_CANCEL_FAIL_STATUS_NOT_UNPAID);
-        }
+    // 2. 执行 TradeOrderHandler 的后置处理
+    List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(order.getId());
+    tradeOrderHandlers.forEach(handler -> handler.afterCancelOrder(order, orderItems));
 
-        // 2. 执行 TradeOrderHandler 的后置处理
-        List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(order.getId());
-        tradeOrderHandlers.forEach(handler -> handler.afterCancelOrder(order, orderItems));
+    // 3. 增加订单日志
+    TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), TradeOrderStatusEnum.CANCELED.getStatus());
+}
 
-        // 3. 增加订单日志
-        TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), TradeOrderStatusEnum.CANCELED.getStatus());
+/**
+ * 如果金额全部被退款,则取消订单
+ * 如果还有未被退款的金额,则无需取消订单
+ *
+ * @param order       订单
+ * @param refundPrice 退款金额
+ */
+@TradeOrderLog(operateType = TradeOrderOperateTypeEnum.ADMIN_CANCEL_AFTER_SALE)
+public void cancelOrderByAfterSale(TradeOrderDO order, Integer refundPrice) {
+    // 1. 更新订单
+    if (refundPrice < order.getPayPrice()) {
+        return;
     }
+    tradeOrderMapper.updateById(new TradeOrderDO().setId(order.getId())
+            .setStatus(TradeOrderStatusEnum.CANCELED.getStatus())
+            .setCancelType(TradeOrderCancelTypeEnum.AFTER_SALE_CLOSE.getType()).setCancelTime(LocalDateTime.now()));
 
-    /**
-     * 如果金额全部被退款,则取消订单
-     * 如果还有未被退款的金额,则无需取消订单
-     *
-     * @param order       订单
-     * @param refundPrice 退款金额
-     */
-    @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.ADMIN_CANCEL_AFTER_SALE)
-    public void cancelOrderByAfterSale(TradeOrderDO order, Integer refundPrice) {
-        // 1. 更新订单
-        if (refundPrice < order.getPayPrice()) {
-            return;
-        }
-        tradeOrderMapper.updateById(new TradeOrderDO().setId(order.getId())
-                .setStatus(TradeOrderStatusEnum.CANCELED.getStatus())
-                .setCancelType(TradeOrderCancelTypeEnum.AFTER_SALE_CLOSE.getType()).setCancelTime(LocalDateTime.now()));
+    // 2. 执行 TradeOrderHandler 的后置处理
+    List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(order.getId());
+    tradeOrderHandlers.forEach(handler -> handler.afterCancelOrder(order, orderItems));
+}
 
-        // 2. 执行 TradeOrderHandler 的后置处理
-        List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(order.getId());
-        tradeOrderHandlers.forEach(handler -> handler.afterCancelOrder(order, orderItems));
+@Override
+@Transactional(rollbackFor = Exception.class)
+@TradeOrderLog(operateType = TradeOrderOperateTypeEnum.MEMBER_DELETE)
+public void deleteOrder(Long userId, Long id) {
+    // 1.1 校验存在
+    TradeOrderDO order = tradeOrderMapper.selectOrderByIdAndUserId(id, userId);
+    if (order == null) {
+        throw exception(ORDER_NOT_FOUND);
     }
+    // 1.2 校验状态
+    if (ObjectUtil.notEqual(order.getStatus(), TradeOrderStatusEnum.CANCELED.getStatus())) {
+        throw exception(ORDER_DELETE_FAIL_STATUS_NOT_CANCEL);
+    }
+    // 2. 删除订单
+    tradeOrderMapper.deleteById(id);
 
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.MEMBER_DELETE)
-    public void deleteOrder(Long userId, Long id) {
-        // 1.1 校验存在
-        TradeOrderDO order = tradeOrderMapper.selectOrderByIdAndUserId(id, userId);
-        if (order == null) {
-            throw exception(ORDER_NOT_FOUND);
-        }
-        // 1.2 校验状态
-        if (ObjectUtil.notEqual(order.getStatus(), TradeOrderStatusEnum.CANCELED.getStatus())) {
-            throw exception(ORDER_DELETE_FAIL_STATUS_NOT_CANCEL);
-        }
-        // 2. 删除订单
-        tradeOrderMapper.deleteById(id);
+    // 3. 记录日志
+    TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), order.getStatus());
+}
 
-        // 3. 记录日志
-        TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), order.getStatus());
-    }
+@Override
+public void updateOrderRemark(TradeOrderRemarkReqVO reqVO) {
+    // 校验并获得交易订单
+    validateOrderExists(reqVO.getId());
 
-    @Override
-    public void updateOrderRemark(TradeOrderRemarkReqVO reqVO) {
-        // 校验并获得交易订单
-        validateOrderExists(reqVO.getId());
+    // 更新
+    TradeOrderDO order = TradeOrderConvert.INSTANCE.convert(reqVO);
+    tradeOrderMapper.updateById(order);
+}
 
-        // 更新
-        TradeOrderDO order = TradeOrderConvert.INSTANCE.convert(reqVO);
-        tradeOrderMapper.updateById(order);
+@Override
+@Transactional(rollbackFor = Exception.class)
+@TradeOrderLog(operateType = TradeOrderOperateTypeEnum.ADMIN_UPDATE_PRICE)
+public void updateOrderPrice(TradeOrderUpdatePriceReqVO reqVO) {
+    // 1.1 校验交易订单
+    TradeOrderDO order = validateOrderExists(reqVO.getId());
+    if (order.getPayStatus()) {
+        throw exception(ORDER_UPDATE_PRICE_FAIL_PAID);
+    }
+    // 1.2 校验调价金额是否变化
+    if (order.getAdjustPrice() > 0) {
+        throw exception(ORDER_UPDATE_PRICE_FAIL_ALREADY);
+    }
+    // 1.3 支付价格不能为 0
+    int newPayPrice = order.getPayPrice() + order.getAdjustPrice();
+    if (newPayPrice <= 0) {
+        throw exception(ORDER_UPDATE_PRICE_FAIL_PRICE_ERROR);
     }
 
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.ADMIN_UPDATE_PRICE)
-    public void updateOrderPrice(TradeOrderUpdatePriceReqVO reqVO) {
-        // 1.1 校验交易订单
-        TradeOrderDO order = validateOrderExists(reqVO.getId());
-        if (order.getPayStatus()) {
-            throw exception(ORDER_UPDATE_PRICE_FAIL_PAID);
-        }
-        // 1.2 校验调价金额是否变化
-        if (order.getAdjustPrice() > 0) {
-            throw exception(ORDER_UPDATE_PRICE_FAIL_ALREADY);
-        }
-        // 1.3 支付价格不能为 0
-        int newPayPrice = order.getPayPrice() + order.getAdjustPrice();
-        if (newPayPrice <= 0) {
-            throw exception(ORDER_UPDATE_PRICE_FAIL_PRICE_ERROR);
-        }
+    // 2. 更新订单
+    tradeOrderMapper.updateById(new TradeOrderDO().setId(order.getId())
+            .setAdjustPrice(reqVO.getAdjustPrice()).setPayPrice(newPayPrice));
+
+    // 3. 更新 TradeOrderItem,需要做 adjustPrice 的分摊
+    List<TradeOrderItemDO> orderOrderItems = tradeOrderItemMapper.selectListByOrderId(order.getId());
+    List<Integer> dividePrices = TradePriceCalculatorHelper.dividePrice2(orderOrderItems, newPayPrice);
+    List<TradeOrderItemDO> updateItems = new ArrayList<>();
+    for (int i = 0; i < orderOrderItems.size(); i++) {
+        TradeOrderItemDO item = orderOrderItems.get(i);
+        updateItems.add(new TradeOrderItemDO().setId(item.getId()).setAdjustPrice(dividePrices.get(i))
+                .setPayPrice(item.getPayPrice() + dividePrices.get(i)));
+    }
+    tradeOrderItemMapper.updateBatch(updateItems);
 
-        // 2. 更新订单
-        tradeOrderMapper.updateById(new TradeOrderDO().setId(order.getId())
-                .setAdjustPrice(reqVO.getAdjustPrice()).setPayPrice(newPayPrice));
-
-        // 3. 更新 TradeOrderItem,需要做 adjustPrice 的分摊
-        List<TradeOrderItemDO> orderOrderItems = tradeOrderItemMapper.selectListByOrderId(order.getId());
-        List<Integer> dividePrices = TradePriceCalculatorHelper.dividePrice2(orderOrderItems, newPayPrice);
-        List<TradeOrderItemDO> updateItems = new ArrayList<>();
-        for (int i = 0; i < orderOrderItems.size(); i++) {
-            TradeOrderItemDO item = orderOrderItems.get(i);
-            updateItems.add(new TradeOrderItemDO().setId(item.getId()).setAdjustPrice(dividePrices.get(i))
-                    .setPayPrice(item.getPayPrice() + dividePrices.get(i)));
-        }
-        tradeOrderItemMapper.updateBatch(updateItems);
+    // 4. 更新支付订单
+    payOrderApi.updatePayOrderPrice(order.getPayOrderId(), newPayPrice);
 
-        // 4. 更新支付订单
-        payOrderApi.updatePayOrderPrice(order.getPayOrderId(), newPayPrice);
+    // 5. 记录订单日志
+    TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), order.getStatus(),
+            MapUtil.<String, Object>builder().put("oldPayPrice", MoneyUtils.fenToYuanStr(order.getPayPrice()))
+                    .put("newPayPrice", MoneyUtils.fenToYuanStr(newPayPrice)).build());
+}
 
-        // 5. 记录订单日志
-        TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), order.getStatus(),
-                MapUtil.<String, Object>builder().put("oldPayPrice", MoneyUtils.fenToYuanStr(order.getPayPrice()))
-                        .put("newPayPrice", MoneyUtils.fenToYuanStr(newPayPrice)).build());
+@Override
+@TradeOrderLog(operateType = TradeOrderOperateTypeEnum.ADMIN_UPDATE_ADDRESS)
+public void updateOrderAddress(TradeOrderUpdateAddressReqVO reqVO) {
+    // 校验交易订单
+    TradeOrderDO order = validateOrderExists(reqVO.getId());
+    // 只有待发货状态,才可以修改订单收货地址;
+    if (!TradeOrderStatusEnum.isUndelivered(order.getStatus())) {
+        throw exception(ORDER_UPDATE_ADDRESS_FAIL_STATUS_NOT_DELIVERED);
     }
 
-    @Override
-    @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.ADMIN_UPDATE_ADDRESS)
-    public void updateOrderAddress(TradeOrderUpdateAddressReqVO reqVO) {
-        // 校验交易订单
-        TradeOrderDO order = validateOrderExists(reqVO.getId());
-        // 只有待发货状态,才可以修改订单收货地址;
-        if (!TradeOrderStatusEnum.isUndelivered(order.getStatus())) {
-            throw exception(ORDER_UPDATE_ADDRESS_FAIL_STATUS_NOT_DELIVERED);
-        }
+    // 更新
+    tradeOrderMapper.updateById(TradeOrderConvert.INSTANCE.convert(reqVO));
 
-        // 更新
-        tradeOrderMapper.updateById(TradeOrderConvert.INSTANCE.convert(reqVO));
+    // 记录订单日志
+    TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), order.getStatus());
+}
 
-        // 记录订单日志
-        TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), order.getStatus());
-    }
+@Override
+@TradeOrderLog(operateType = TradeOrderOperateTypeEnum.ADMIN_PICK_UP_RECEIVE)
+public void pickUpOrderByAdmin(Long id) {
+    getSelf().pickUpOrder(tradeOrderMapper.selectById(id));
+}
 
-    @Override
-    @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.ADMIN_PICK_UP_RECEIVE)
-    public void pickUpOrderByAdmin(Long id) {
-        getSelf().pickUpOrder(tradeOrderMapper.selectById(id));
-    }
+@Override
+@TradeOrderLog(operateType = TradeOrderOperateTypeEnum.ADMIN_PICK_UP_RECEIVE)
+public void pickUpOrderByAdmin(String pickUpVerifyCode) {
+    getSelf().pickUpOrder(tradeOrderMapper.selectOneByPickUpVerifyCode(pickUpVerifyCode));
+}
 
-    @Override
-    @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.ADMIN_PICK_UP_RECEIVE)
-    public void pickUpOrderByAdmin(String pickUpVerifyCode) {
-        getSelf().pickUpOrder(tradeOrderMapper.selectOneByPickUpVerifyCode(pickUpVerifyCode));
-    }
+@Override
+public TradeOrderDO getByPickUpVerifyCode(String pickUpVerifyCode) {
+    return tradeOrderMapper.selectOneByPickUpVerifyCode(pickUpVerifyCode);
+}
 
-    @Override
-    public TradeOrderDO getByPickUpVerifyCode(String pickUpVerifyCode) {
-        return tradeOrderMapper.selectOneByPickUpVerifyCode(pickUpVerifyCode);
+@Transactional(rollbackFor = Exception.class)
+public void pickUpOrder(TradeOrderDO order) {
+    if (order == null) {
+        throw exception(ORDER_NOT_FOUND);
     }
-
-    @Transactional(rollbackFor = Exception.class)
-    public void pickUpOrder(TradeOrderDO order) {
-        if (order == null) {
-            throw exception(ORDER_NOT_FOUND);
-        }
-        if (ObjUtil.notEqual(DeliveryTypeEnum.PICK_UP.getType(), order.getDeliveryType())) {
-            throw exception(ORDER_RECEIVE_FAIL_DELIVERY_TYPE_NOT_PICK_UP);
-        }
-        receiveOrder0(order);
+    if (ObjUtil.notEqual(DeliveryTypeEnum.PICK_UP.getType(), order.getDeliveryType())) {
+        throw exception(ORDER_RECEIVE_FAIL_DELIVERY_TYPE_NOT_PICK_UP);
     }
+    receiveOrder0(order);
+}
 
-    // =================== Order Item ===================
-
-    @Override
-    public void updateOrderItemWhenAfterSaleCreate(Long id, Long afterSaleId) {
-        // 更新订单项
-        updateOrderItemAfterSaleStatus(id, TradeOrderItemAfterSaleStatusEnum.NONE.getStatus(),
-                TradeOrderItemAfterSaleStatusEnum.APPLY.getStatus(), afterSaleId);
-    }
+// =================== Order Item ===================
 
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public void updateOrderItemWhenAfterSaleSuccess(Long id, Integer refundPrice) {
-        // 1.1 更新订单项
-        updateOrderItemAfterSaleStatus(id, TradeOrderItemAfterSaleStatusEnum.APPLY.getStatus(),
-                TradeOrderItemAfterSaleStatusEnum.SUCCESS.getStatus(), null);
-        // 1.2 执行 TradeOrderHandler 的后置处理
-        TradeOrderItemDO orderItem = tradeOrderItemMapper.selectById(id);
-        TradeOrderDO order = tradeOrderMapper.selectById(orderItem.getOrderId());
-        tradeOrderHandlers.forEach(handler -> handler.afterCancelOrderItem(order, orderItem));
-
-        // 2.1 更新订单的退款金额、积分
-        Integer orderRefundPrice = order.getRefundPrice() + refundPrice;
-        Integer orderRefundPoint = order.getRefundPoint() + orderItem.getUsePoint();
-        Integer refundStatus = isAllOrderItemAfterSaleSuccess(order.getId()) ?
-                TradeOrderRefundStatusEnum.ALL.getStatus() // 如果都售后成功,则需要取消订单
-                : TradeOrderRefundStatusEnum.PART.getStatus();
-        tradeOrderMapper.updateById(new TradeOrderDO().setId(order.getId())
-                .setRefundStatus(refundStatus)
-                .setRefundPrice(orderRefundPrice).setRefundPoint(orderRefundPoint));
-        // 2.2 如果全部退款,则进行取消订单
-        getSelf().cancelOrderByAfterSale(order, orderRefundPrice);
-    }
+@Override
+public void updateOrderItemWhenAfterSaleCreate(Long id, Long afterSaleId) {
+    // 更新订单项
+    updateOrderItemAfterSaleStatus(id, TradeOrderItemAfterSaleStatusEnum.NONE.getStatus(),
+            TradeOrderItemAfterSaleStatusEnum.APPLY.getStatus(), afterSaleId);
+}
 
-    @Override
-    public void updateOrderItemWhenAfterSaleCancel(Long id) {
-        // 更新订单项
-        updateOrderItemAfterSaleStatus(id, TradeOrderItemAfterSaleStatusEnum.APPLY.getStatus(),
-                TradeOrderItemAfterSaleStatusEnum.NONE.getStatus(), null);
-    }
-
-    private void updateOrderItemAfterSaleStatus(Long id, Integer oldAfterSaleStatus, Integer newAfterSaleStatus,
-                                                Long afterSaleId) {
-        // 更新订单项
-        int updateCount = tradeOrderItemMapper.updateAfterSaleStatus(id, oldAfterSaleStatus, newAfterSaleStatus, afterSaleId);
-        if (updateCount <= 0) {
-            throw exception(ORDER_ITEM_UPDATE_AFTER_SALE_STATUS_FAIL);
-        }
+@Override
+@Transactional(rollbackFor = Exception.class)
+public void updateOrderItemWhenAfterSaleSuccess(Long id, Integer refundPrice) {
+    // 1.1 更新订单项
+    updateOrderItemAfterSaleStatus(id, TradeOrderItemAfterSaleStatusEnum.APPLY.getStatus(),
+            TradeOrderItemAfterSaleStatusEnum.SUCCESS.getStatus(), null);
+    // 1.2 执行 TradeOrderHandler 的后置处理
+    TradeOrderItemDO orderItem = tradeOrderItemMapper.selectById(id);
+    TradeOrderDO order = tradeOrderMapper.selectById(orderItem.getOrderId());
+    tradeOrderHandlers.forEach(handler -> handler.afterCancelOrderItem(order, orderItem));
+
+    // 2.1 更新订单的退款金额、积分
+    Integer orderRefundPrice = order.getRefundPrice() + refundPrice;
+    Integer orderRefundPoint = order.getRefundPoint() + orderItem.getUsePoint();
+    Integer refundStatus = isAllOrderItemAfterSaleSuccess(order.getId()) ?
+            TradeOrderRefundStatusEnum.ALL.getStatus() // 如果都售后成功,则需要取消订单
+            : TradeOrderRefundStatusEnum.PART.getStatus();
+    tradeOrderMapper.updateById(new TradeOrderDO().setId(order.getId())
+            .setRefundStatus(refundStatus)
+            .setRefundPrice(orderRefundPrice).setRefundPoint(orderRefundPoint));
+    // 2.2 如果全部退款,则进行取消订单
+    getSelf().cancelOrderByAfterSale(order, orderRefundPrice);
+}
 
-    }
+@Override
+public void updateOrderItemWhenAfterSaleCancel(Long id) {
+    // 更新订单项
+    updateOrderItemAfterSaleStatus(id, TradeOrderItemAfterSaleStatusEnum.APPLY.getStatus(),
+            TradeOrderItemAfterSaleStatusEnum.NONE.getStatus(), null);
+}
 
-    /**
-     * 判断指定订单的所有订单项,是不是都售后成功
-     *
-     * @param id 订单编号
-     * @return 是否都售后成功
-     */
-    private boolean isAllOrderItemAfterSaleSuccess(Long id) {
-        List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(id);
-        return orderItems.stream().allMatch(orderItem -> Objects.equals(orderItem.getAfterSaleStatus(),
-                TradeOrderItemAfterSaleStatusEnum.SUCCESS.getStatus()));
+private void updateOrderItemAfterSaleStatus(Long id, Integer oldAfterSaleStatus, Integer newAfterSaleStatus,
+                                            Long afterSaleId) {
+    // 更新订单项
+    int updateCount = tradeOrderItemMapper.updateAfterSaleStatus(id, oldAfterSaleStatus, newAfterSaleStatus, afterSaleId);
+    if (updateCount <= 0) {
+        throw exception(ORDER_ITEM_UPDATE_AFTER_SALE_STATUS_FAIL);
     }
 
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.MEMBER_COMMENT)
-    public Long createOrderItemCommentByMember(Long userId, AppTradeOrderItemCommentCreateReqVO createReqVO) {
-        // 1.1 先通过订单项 ID,查询订单项是否存在
-        TradeOrderItemDO orderItem = tradeOrderItemMapper.selectByIdAndUserId(createReqVO.getOrderItemId(), userId);
-        if (orderItem == null) {
-            throw exception(ORDER_ITEM_NOT_FOUND);
-        }
-        // 1.2 校验订单相关状态
-        TradeOrderDO order = tradeOrderMapper.selectOrderByIdAndUserId(orderItem.getOrderId(), userId);
-        if (order == null) {
-            throw exception(ORDER_NOT_FOUND);
-        }
-        if (ObjectUtil.notEqual(order.getStatus(), TradeOrderStatusEnum.COMPLETED.getStatus())) {
-            throw exception(ORDER_COMMENT_FAIL_STATUS_NOT_COMPLETED);
-        }
-        if (ObjectUtil.notEqual(order.getCommentStatus(), Boolean.FALSE)) {
-            throw exception(ORDER_COMMENT_STATUS_NOT_FALSE);
-        }
+}
 
-        // 2. 创建评价
-        Long commentId = createOrderItemComment0(orderItem, createReqVO);
+/**
+ * 判断指定订单的所有订单项,是不是都售后成功
+ *
+ * @param id 订单编号
+ * @return 是否都售后成功
+ */
+private boolean isAllOrderItemAfterSaleSuccess(Long id) {
+    List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(id);
+    return orderItems.stream().allMatch(orderItem -> Objects.equals(orderItem.getAfterSaleStatus(),
+            TradeOrderItemAfterSaleStatusEnum.SUCCESS.getStatus()));
+}
 
-        // 3. 如果订单项都评论了,则更新订单评价状态
-        List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(order.getId());
-        if (!anyMatch(orderItems, item -> Objects.equals(item.getCommentStatus(), Boolean.FALSE))) {
-            tradeOrderMapper.updateById(new TradeOrderDO().setId(order.getId()).setCommentStatus(Boolean.TRUE)
-                    .setFinishTime(LocalDateTime.now()));
-            // 增加订单日志。注意:只有在所有订单项都评价后,才会增加
-            TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), order.getStatus());
-        }
-        return commentId;
+@Override
+@Transactional(rollbackFor = Exception.class)
+@TradeOrderLog(operateType = TradeOrderOperateTypeEnum.MEMBER_COMMENT)
+public Long createOrderItemCommentByMember(Long userId, AppTradeOrderItemCommentCreateReqVO createReqVO) {
+    // 1.1 先通过订单项 ID,查询订单项是否存在
+    TradeOrderItemDO orderItem = tradeOrderItemMapper.selectByIdAndUserId(createReqVO.getOrderItemId(), userId);
+    if (orderItem == null) {
+        throw exception(ORDER_ITEM_NOT_FOUND);
+    }
+    // 1.2 校验订单相关状态
+    TradeOrderDO order = tradeOrderMapper.selectOrderByIdAndUserId(orderItem.getOrderId(), userId);
+    if (order == null) {
+        throw exception(ORDER_NOT_FOUND);
+    }
+    if (ObjectUtil.notEqual(order.getStatus(), TradeOrderStatusEnum.COMPLETED.getStatus())) {
+        throw exception(ORDER_COMMENT_FAIL_STATUS_NOT_COMPLETED);
+    }
+    if (ObjectUtil.notEqual(order.getCommentStatus(), Boolean.FALSE)) {
+        throw exception(ORDER_COMMENT_STATUS_NOT_FALSE);
     }
 
-    @Override
-    public int createOrderItemCommentBySystem() {
-        // 1. 查询过期的待支付订单
-        LocalDateTime expireTime = minusTime(tradeOrderProperties.getCommentExpireTime());
-        List<TradeOrderDO> orders = tradeOrderMapper.selectListByStatusAndReceiveTimeLt(
-                TradeOrderStatusEnum.COMPLETED.getStatus(), expireTime, false);
-        if (CollUtil.isEmpty(orders)) {
-            return 0;
-        }
+    // 2. 创建评价
+    Long commentId = createOrderItemComment0(orderItem, createReqVO);
 
-        // 2. 遍历执行,逐个取消
-        int count = 0;
-        for (TradeOrderDO order : orders) {
-            try {
-                getSelf().createOrderItemCommentBySystemBySystem(order);
-                count++;
-            } catch (Throwable e) {
-                log.error("[createOrderItemCommentBySystem][order({}) 过期订单异常]", order.getId(), e);
-            }
-        }
-        return count;
+    // 3. 如果订单项都评论了,则更新订单评价状态
+    List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(order.getId());
+    if (!anyMatch(orderItems, item -> Objects.equals(item.getCommentStatus(), Boolean.FALSE))) {
+        tradeOrderMapper.updateById(new TradeOrderDO().setId(order.getId()).setCommentStatus(Boolean.TRUE)
+                .setFinishTime(LocalDateTime.now()));
+        // 增加订单日志。注意:只有在所有订单项都评价后,才会增加
+        TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), order.getStatus());
     }
+    return commentId;
+}
 
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public void updateOrderCombinationInfo(Long orderId, Long activityId, Long combinationRecordId, Long headId) {
-        tradeOrderMapper.updateById(
-                new TradeOrderDO().setId(orderId).setCombinationActivityId(activityId)
-                        .setCombinationRecordId(combinationRecordId).setCombinationHeadId(headId));
+@Override
+public int createOrderItemCommentBySystem() {
+    // 1. 查询过期的待支付订单
+    LocalDateTime expireTime = minusTime(tradeOrderProperties.getCommentExpireTime());
+    List<TradeOrderDO> orders = tradeOrderMapper.selectListByStatusAndReceiveTimeLt(
+            TradeOrderStatusEnum.COMPLETED.getStatus(), expireTime, false);
+    if (CollUtil.isEmpty(orders)) {
+        return 0;
     }
 
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public void cancelPaidOrder(Long userId, Long orderId) {
-        // TODO 非繁人:这里实现要优化下;
-        TradeOrderDO order = tradeOrderMapper.selectOrderByIdAndUserId(orderId, userId);
-        if (order == null) {
-            throw exception(ORDER_NOT_FOUND);
+    // 2. 遍历执行,逐个取消
+    int count = 0;
+    for (TradeOrderDO order : orders) {
+        try {
+            getSelf().createOrderItemCommentBySystemBySystem(order);
+            count++;
+        } catch (Throwable e) {
+            log.error("[createOrderItemCommentBySystem][order({}) 过期订单异常]", order.getId(), e);
         }
-        cancelOrder0(order, TradeOrderCancelTypeEnum.MEMBER_CANCEL);
     }
+    return count;
+}
 
-    /**
-     * 保存订单的签收时间
-     * @param com 快递公司编码
-     * @param nu 单号
-     */
-    public void updateOrder(String com, String nu, LocalDateTime time){
-        DeliveryExpressDO deliveryExpressDO = deliveryExpressService.selectByCode(com);
-        TradeOrderDO tradeOrderDO = tradeOrderMapper.selectOne(new LambdaQueryWrapper<TradeOrderDO>()
-                .eq(TradeOrderDO::getLogisticsNo, nu)
-                .eq(TradeOrderDO::getLogisticsId, deliveryExpressDO.getId())
-                .isNull(TradeOrderDO::getReceivingTime)
-        );
-        if(tradeOrderDO == null){
-            return;
-        }
-        tradeOrderDO.setReceivingTime(time);
+@Override
+@Transactional(rollbackFor = Exception.class)
+public void updateOrderCombinationInfo(Long orderId, Long activityId, Long combinationRecordId, Long headId) {
+    tradeOrderMapper.updateById(
+            new TradeOrderDO().setId(orderId).setCombinationActivityId(activityId)
+                    .setCombinationRecordId(combinationRecordId).setCombinationHeadId(headId));
+}
 
-        tradeOrderMapper.updateById(tradeOrderDO);
+@Override
+@Transactional(rollbackFor = Exception.class)
+public void cancelPaidOrder(Long userId, Long orderId) {
+    // TODO 非繁人:这里实现要优化下;
+    TradeOrderDO order = tradeOrderMapper.selectOrderByIdAndUserId(orderId, userId);
+    if (order == null) {
+        throw exception(ORDER_NOT_FOUND);
     }
+    cancelOrder0(order, TradeOrderCancelTypeEnum.MEMBER_CANCEL);
+}
 
-    @Override
-    public void updateOrderById(TradeOrderDO order) {
-        tradeOrderMapper.updateById(order);
+/**
+ * 保存订单的签收时间
+ *
+ * @param com 快递公司编码
+ * @param nu  单号
+ */
+public void updateOrder(String com, String nu, LocalDateTime time) {
+    DeliveryExpressDO deliveryExpressDO = deliveryExpressService.selectByCode(com);
+    TradeOrderDO tradeOrderDO = tradeOrderMapper.selectOne(new LambdaQueryWrapper<TradeOrderDO>()
+            .eq(TradeOrderDO::getLogisticsNo, nu)
+            .eq(TradeOrderDO::getLogisticsId, deliveryExpressDO.getId())
+            .isNull(TradeOrderDO::getReceivingTime)
+    );
+    if (tradeOrderDO == null) {
+        return;
     }
+    tradeOrderDO.setReceivingTime(time);
 
-    /**
-     * 创建单个订单的评论
-     *
-     * @param order 订单
-     */
-    @Transactional(rollbackFor = Exception.class)
-    @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.SYSTEM_COMMENT)
-    public void createOrderItemCommentBySystemBySystem(TradeOrderDO order) {
-        // 1. 查询未评论的订单项
-        List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderIdAndCommentStatus(
-                order.getId(), Boolean.FALSE);
-        if (CollUtil.isEmpty(orderItems)) {
-            return;
-        }
-
-        // 2. 逐个评论
-        for (TradeOrderItemDO orderItem : orderItems) {
-            // 2.1 创建评价
-            AppTradeOrderItemCommentCreateReqVO commentCreateReqVO = new AppTradeOrderItemCommentCreateReqVO()
-                    .setOrderItemId(orderItem.getId()).setAnonymous(false).setContent("")
-                    .setBenefitScores(5).setDescriptionScores(5);
-            createOrderItemComment0(orderItem, commentCreateReqVO);
+    tradeOrderMapper.updateById(tradeOrderDO);
+}
 
-            // 2.2 更新订单项评价状态
-            tradeOrderItemMapper.updateById(new TradeOrderItemDO().setId(orderItem.getId()).setCommentStatus(Boolean.TRUE));
-        }
+@Override
+public void updateOrderById(TradeOrderDO order) {
+    tradeOrderMapper.updateById(order);
+}
 
-        // 3. 所有订单项都评论了,则更新订单评价状态
-        tradeOrderMapper.updateById(new TradeOrderDO().setId(order.getId()).setCommentStatus(Boolean.TRUE)
-                .setFinishTime(LocalDateTime.now()));
-        // 增加订单日志。注意:只有在所有订单项都评价后,才会增加
-        TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), order.getStatus());
+/**
+ * 创建单个订单的评论
+ *
+ * @param order 订单
+ */
+@Transactional(rollbackFor = Exception.class)
+@TradeOrderLog(operateType = TradeOrderOperateTypeEnum.SYSTEM_COMMENT)
+public void createOrderItemCommentBySystemBySystem(TradeOrderDO order) {
+    // 1. 查询未评论的订单项
+    List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderIdAndCommentStatus(
+            order.getId(), Boolean.FALSE);
+    if (CollUtil.isEmpty(orderItems)) {
+        return;
     }
 
-    /**
-     * 创建订单项的评论的核心实现
-     *
-     * @param orderItem   订单项
-     * @param createReqVO 评论内容
-     * @return 评论编号
-     */
-    private Long createOrderItemComment0(TradeOrderItemDO orderItem, AppTradeOrderItemCommentCreateReqVO createReqVO) {
-        // 1. 创建评价
-        ProductCommentCreateReqDTO productCommentCreateReqDTO = TradeOrderConvert.INSTANCE.convert04(createReqVO, orderItem);
-        Long commentId = productCommentApi.createComment(productCommentCreateReqDTO);
+    // 2. 逐个评论
+    for (TradeOrderItemDO orderItem : orderItems) {
+        // 2.1 创建评价
+        AppTradeOrderItemCommentCreateReqVO commentCreateReqVO = new AppTradeOrderItemCommentCreateReqVO()
+                .setOrderItemId(orderItem.getId()).setAnonymous(false).setContent("")
+                .setBenefitScores(5).setDescriptionScores(5);
+        createOrderItemComment0(orderItem, commentCreateReqVO);
 
-        // 2. 更新订单项评价状态
+        // 2.2 更新订单项评价状态
         tradeOrderItemMapper.updateById(new TradeOrderItemDO().setId(orderItem.getId()).setCommentStatus(Boolean.TRUE));
-        return commentId;
     }
 
-    // =================== 营销相关的操作 ===================
+    // 3. 所有订单项都评论了,则更新订单评价状态
+    tradeOrderMapper.updateById(new TradeOrderDO().setId(order.getId()).setCommentStatus(Boolean.TRUE)
+            .setFinishTime(LocalDateTime.now()));
+    // 增加订单日志。注意:只有在所有订单项都评价后,才会增加
+    TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), order.getStatus());
+}
 
-    /**
-     * 获得自身的代理对象,解决 AOP 生效问题
-     *
-     * @return 自己
-     */
-    private TradeOrderUpdateServiceImpl getSelf() {
-        return SpringUtil.getBean(getClass());
-    }
+/**
+ * 创建订单项的评论的核心实现
+ *
+ * @param orderItem   订单项
+ * @param createReqVO 评论内容
+ * @return 评论编号
+ */
+private Long createOrderItemComment0(TradeOrderItemDO orderItem, AppTradeOrderItemCommentCreateReqVO createReqVO) {
+    // 1. 创建评价
+    ProductCommentCreateReqDTO productCommentCreateReqDTO = TradeOrderConvert.INSTANCE.convert04(createReqVO, orderItem);
+    Long commentId = productCommentApi.createComment(productCommentCreateReqDTO);
+
+    // 2. 更新订单项评价状态
+    tradeOrderItemMapper.updateById(new TradeOrderItemDO().setId(orderItem.getId()).setCommentStatus(Boolean.TRUE));
+    return commentId;
+}
+
+// =================== 营销相关的操作 ===================
+
+/**
+ * 获得自身的代理对象,解决 AOP 生效问题
+ *
+ * @return 自己
+ */
+private TradeOrderUpdateServiceImpl getSelf() {
+    return SpringUtil.getBean(getClass());
+}
 
 }

+ 95 - 10
feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/utils/wechat/WcChatMessageUtils.java

@@ -4,10 +4,15 @@ import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.http.HttpUtil;
 import cn.hutool.json.JSONUtil;
+import cn.newfeifan.mall.module.member.service.user.MemberUserService;
+import cn.newfeifan.mall.module.system.dal.dataobject.config.SystemConfigDO;
 import cn.newfeifan.mall.module.system.dal.dataobject.wechatmsgtemplate.WechatMsgTemplateDO;
+import cn.newfeifan.mall.module.system.service.config.SystemConfigService;
+import cn.newfeifan.mall.module.system.service.permission.PermissionService;
 import cn.newfeifan.mall.module.system.service.social.SocialUserService;
 import cn.newfeifan.mall.module.system.service.wechatmsgtemplate.WechatMsgTemplateService;
 import cn.newfeifan.mall.module.trade.controller.admin.messagelog.vo.MessageLogSaveReqVO;
+import cn.newfeifan.mall.module.trade.enums.wxmessage.WcChatMessageTemplateIdEnum;
 import cn.newfeifan.mall.module.trade.service.messagelog.MessageLogService;
 import com.google.gson.JsonObject;
 import lombok.Data;
@@ -23,6 +28,8 @@ import java.util.List;
 import java.util.UUID;
 
 import static cn.newfeifan.mall.module.system.constant.SystemConstants.SYSTEM_WX_ACCESS_TOKEN;
+import static cn.newfeifan.mall.module.trade.enums.MessageTemplateConstants.AFTER_SALE_NO_CHECK_List;
+import static cn.newfeifan.mall.module.trade.enums.MessageTemplateConstants.ORDER_NO_DELIVERY_List;
 
 /**
  * 发送微信消息的工具类
@@ -45,6 +52,12 @@ public class WcChatMessageUtils {
     private SocialUserService socialUserService;
     @Resource
     private MessageLogService messageLogService;
+    @Resource
+    private SystemConfigService configService;
+    @Resource
+    private PermissionService permissionService;
+    @Resource
+    private MemberUserService memberUserService;
 
     /**
      * 获取微信的accessToken
@@ -83,12 +96,24 @@ public class WcChatMessageUtils {
      * @param data                模板参数
      * @param wechatMsgTemplateId 自定义的消息模板id
      */
-    public void sendWxgMessage(Long userId, JsonObject data, Long wechatMsgTemplateId,Long systemUserId,Long memberUserId,Long objectId) {
+    private void sendWxgMessage(Long userId, JsonObject data, String wechatMsgTemplateId, Long systemUserId, Long memberUserId, Long objectId) {
 
         // 组装消息内容
-        String userOpenId = getOpenId(userId);
+        String userOpenId = null;
+        if (wechatMsgTemplateId.equals(WcChatMessageTemplateIdEnum.AFTER_SALE_NO_CHECK.getTemplateId()) ||
+                wechatMsgTemplateId.equals(WcChatMessageTemplateIdEnum.ORDER_NO_DELIVERY.getTemplateId())) {
+            userOpenId = getOpenIdBySysTemUserId(systemUserId);
+        } else {
+            userOpenId = getOpenId(userId);
+        }
+
+        //如果用户没有绑定微信,则不发送消息
+        if (userOpenId == null) {
+            return;
+        }
+
         String templateId = getTemplateId(wechatMsgTemplateId).getWechatMsgTemplateId(); // 模板id
-        String url = "https://letcgosh.newfeifan.cn/order";       // 跳转路径(小程序之外)
+        String url = getDoMain(String.valueOf(wechatMsgTemplateId), objectId);       // 跳转路径(小程序之外)
         String client_msg_id = UUID.randomUUID().toString();  // 防重入id
 
 
@@ -110,7 +135,7 @@ public class WcChatMessageUtils {
                 .memberUserId(userId)
                 .systemUserId(systemUserId)
                 .memberUserId(memberUserId)
-                .wechatMsgTemplateId(wechatMsgTemplateId)
+                .wechatMsgTemplateId(Long.valueOf(wechatMsgTemplateId))
                 .wechatMsgTemplateParams(message.toString())
                 .objectId(objectId)
                 .sendStatus(true)
@@ -147,7 +172,17 @@ public class WcChatMessageUtils {
         return data;
     }
 
-    public void getTemplateParams(Long userId, Long templateId, List<String> params,Long systemUserId,Long memberUserId,Long objectId) {
+    /**
+     * 发送微信信息
+     *
+     * @param userId       用户id
+     * @param templateId   自定义消息模板id
+     * @param params       消息参数
+     * @param systemUserId 系统用户id
+     * @param memberUserId 会员用户id
+     * @param objectId     对象id
+     */
+    public void sendWcChatMessage(Long userId, String templateId, List<String> params, Long systemUserId, Long memberUserId, Long objectId) {
         WechatMsgTemplateDO template = getTemplateId(templateId);
         String messageTemplateParameters = template.getMessageTemplateParameters();
 
@@ -161,8 +196,50 @@ public class WcChatMessageUtils {
         List<String> dataParams = Arrays.asList(parts);
         JsonObject templateData = getTemplateData(dataParams, params);
 
-        // 发送消息
-        sendWxgMessage(userId, templateData, templateId,systemUserId,memberUserId,objectId);
+        // 发送微信消息
+        sendWxgMessage(userId, templateData, templateId, systemUserId, memberUserId, objectId);
+    }
+
+    /**
+     * 判断用户是否有接收者调消息的权限
+     *
+     * @param userId     用户id
+     * @param templateId 自定义的模板id
+     * @return 是否有权限
+     */
+    public Boolean isHavePermission(Long userId, String templateId) {
+        if (templateId.equals(WcChatMessageTemplateIdEnum.AFTER_SALE_NO_CHECK.getTemplateId())) {
+            // 售后待审核
+            return permissionService.hasAnyPermissions(userId, AFTER_SALE_NO_CHECK_List);
+        } else if (templateId.equals(WcChatMessageTemplateIdEnum.ORDER_NO_DELIVERY.getTemplateId())) {
+            // 订单待发货
+            return permissionService.hasAnyPermissions(userId, ORDER_NO_DELIVERY_List);
+        }
+        return false;
+    }
+
+    /**
+     * 获取不同端域名(不同的端的代码略有不同)
+     *
+     * @param templateId 自定义模板id
+     * @return 域名加路径
+     */
+    public String getDoMain(String templateId, Long objectId) {
+        SystemConfigDO redisConfig = configService.getRedisConfig();
+        if (templateId.equals(WcChatMessageTemplateIdEnum.ORDER_DELIVERY.getTemplateId())) {
+            //订单已发货
+            return redisConfig.getMallDomain() + "/#/pages/order/detail?id=" + objectId;
+        } else if (templateId.equals(WcChatMessageTemplateIdEnum.AFTER_SALE_CHECK.getTemplateId())) {
+            //售后订单审核完成
+            return redisConfig.getMallDomain() + "/#/pages/order/aftersale/detail?id=" + objectId;
+        } else if (templateId.equals(WcChatMessageTemplateIdEnum.AFTER_SALE_NO_CHECK.getTemplateId())) {
+            //售后订单待审核
+            return redisConfig.getPlatformDomain() + "/after-sale";
+        } else if (templateId.equals(WcChatMessageTemplateIdEnum.ORDER_NO_DELIVERY.getTemplateId())) {
+            //订单待发货
+            return redisConfig.getMallDomain() + "/order";
+        }
+        return null;
     }
 
     /**
@@ -171,11 +248,19 @@ public class WcChatMessageUtils {
      * @param wechatMsgTemplateId 自己定义消息模板id
      * @return 微信第三方模板
      */
-    private WechatMsgTemplateDO getTemplateId(Long wechatMsgTemplateId) {
-        return wechatMsgTemplateService.getWechatSsgTemplateId(wechatMsgTemplateId);
+    private WechatMsgTemplateDO getTemplateId(String wechatMsgTemplateId) {
+        return wechatMsgTemplateService.getWechatSsgTemplate(Long.valueOf(wechatMsgTemplateId));
     }
 
     private String getOpenId(Long userId) {
-        return socialUserService.getOpenId(userId);
+        return socialUserService.getOpenIdByUserId(userId);
+    }
+
+    private String getOpenIdBySysTemUserId(Long systemUserId) {
+        Long memberUserId = memberUserService.getUserIdBySystemUserId(systemUserId);
+        if (memberUserId == null) {
+            return null;
+        }
+        return getOpenId(memberUserId);
     }
 }

+ 1 - 0
feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/service/user/MemberUserService.java

@@ -198,4 +198,5 @@ public interface MemberUserService {
     void updateUserByMobile(Long systemUserId, String mobile);
 
 
+    Long getUserIdBySystemUserId(Long systemUserId);
 }

+ 6 - 0
feifan-module-member/feifan-module-member-biz/src/main/java/cn/newfeifan/mall/module/member/service/user/MemberUserServiceImpl.java

@@ -330,4 +330,10 @@ public class MemberUserServiceImpl implements MemberUserService {
         memberUserMapper.updateById(memberUserDO);
     }
 
+    @Override
+    public Long getUserIdBySystemUserId(Long systemUserId) {
+        MemberUserDO memberUserDO = memberUserMapper.selectOne(MemberUserDO::getSystemUsersId, systemUserId);
+        return memberUserDO == null ? null : memberUserDO.getId();
+    }
+
 }

+ 5 - 0
feifan-module-system/feifan-module-system-api/src/main/java/cn/newfeifan/mall/module/system/constant/SystemConstants.java

@@ -2,4 +2,9 @@ package cn.newfeifan.mall.module.system.constant;
 
 public class SystemConstants {
     public static final String SYSTEM_WX_ACCESS_TOKEN = "system:wx:access_token";
+
+    public static final String SYSTEM_WX_MESSAGE_TEMPLATE = "system:wx:message:template:";
+
+    public static final String SYSTEM_CONFIG = "system:config";
+
 }

+ 1 - 0
feifan-module-system/feifan-module-system-api/src/main/java/cn/newfeifan/mall/module/system/enums/ErrorCodeConstants.java

@@ -171,5 +171,6 @@ public interface ErrorCodeConstants {
     // ========== 站内信发送 1-002-028-000 ==========
     ErrorCode NOTIFY_SEND_TEMPLATE_PARAM_MISS = new ErrorCode(1_002_028_000, "模板参数({})缺失");
     ErrorCode WECHAT_MSG_TEMPLATE_NOT_EXISTS = new ErrorCode(1_002_028_001, "微信消息模板不存在");
+    ErrorCode CONFIG_NOT_EXISTS = new ErrorCode(1_002_028_001, "系统配置不存在");
 
 }

+ 64 - 0
feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/config/StartConfig.java

@@ -0,0 +1,64 @@
+package cn.newfeifan.mall.module.system.config;
+
+import cn.newfeifan.mall.framework.common.util.json.JsonUtils;
+import cn.newfeifan.mall.module.system.dal.dataobject.config.SystemConfigDO;
+import cn.newfeifan.mall.module.system.dal.dataobject.wechatmsgtemplate.WechatMsgTemplateDO;
+import cn.newfeifan.mall.module.system.service.config.SystemConfigService;
+import cn.newfeifan.mall.module.system.service.wechatmsgtemplate.WechatMsgTemplateService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.Resource;
+import java.util.List;
+
+import static cn.newfeifan.mall.module.system.constant.SystemConstants.SYSTEM_CONFIG;
+import static cn.newfeifan.mall.module.system.constant.SystemConstants.SYSTEM_WX_MESSAGE_TEMPLATE;
+
+
+/**
+ * 启动配置类
+ */
+@Component
+@Slf4j
+public class StartConfig {
+
+    @Resource
+    private StringRedisTemplate stringRedisTemplate;
+
+    @Resource
+    private WechatMsgTemplateService wechatMsgTemplateService;
+
+    @Resource
+    private SystemConfigService configService;
+
+    @PostConstruct
+    public void init() {
+        initWechatMsgTemplate();
+
+        initSystemConfig();
+    }
+
+    /**
+     * 初始化微信模板配置
+     */
+    private void initWechatMsgTemplate() {
+        List<WechatMsgTemplateDO> wechatMsgTemplateDOS = wechatMsgTemplateService.selectList();
+        wechatMsgTemplateDOS.forEach(wechatMsgTemplateDO -> {
+            stringRedisTemplate.opsForValue().set(SYSTEM_WX_MESSAGE_TEMPLATE + wechatMsgTemplateDO.getId(), JsonUtils.toJsonString(wechatMsgTemplateDO));
+        });
+
+        log.info("======初始化微信模板配置成功======");
+    }
+
+    /**
+     * 初始化系统配置
+     */
+    private void initSystemConfig(){
+        SystemConfigDO config = configService.getConfig();
+        stringRedisTemplate.opsForValue().set(SYSTEM_CONFIG, JsonUtils.toJsonString(config));
+
+        log.info("======初始化系统配置成功======");
+    }
+}

+ 94 - 0
feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/controller/admin/config/SystemConfigController.java

@@ -0,0 +1,94 @@
+package cn.newfeifan.mall.module.system.controller.admin.config;
+
+import org.springframework.web.bind.annotation.*;
+import javax.annotation.Resource;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.security.access.prepost.PreAuthorize;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Operation;
+
+import javax.validation.*;
+import javax.servlet.http.*;
+import java.util.*;
+import java.io.IOException;
+
+import cn.newfeifan.mall.framework.common.pojo.PageParam;
+import cn.newfeifan.mall.framework.common.pojo.PageResult;
+import cn.newfeifan.mall.framework.common.pojo.CommonResult;
+import cn.newfeifan.mall.framework.common.util.object.BeanUtils;
+import static cn.newfeifan.mall.framework.common.pojo.CommonResult.success;
+
+import cn.newfeifan.mall.framework.excel.core.util.ExcelUtils;
+
+import cn.newfeifan.mall.framework.operatelog.core.annotations.OperateLog;
+import static cn.newfeifan.mall.framework.operatelog.core.enums.OperateTypeEnum.*;
+
+import cn.newfeifan.mall.module.system.controller.admin.config.vo.*;
+import cn.newfeifan.mall.module.system.dal.dataobject.config.SystemConfigDO;
+import cn.newfeifan.mall.module.system.service.config.SystemConfigService;
+
+@Tag(name = "管理后台 - 系统配置")
+@RestController
+@RequestMapping("/system/config")
+@Validated
+public class SystemConfigController {
+
+    @Resource
+    private SystemConfigService configService;
+
+    @PostMapping("/create")
+    @Operation(summary = "创建系统配置")
+    @PreAuthorize("@ss.hasPermission('system:config:create')")
+    public CommonResult<Long> createConfig(@Valid @RequestBody ConfigSaveReqVO createReqVO) {
+        return success(configService.createConfig(createReqVO));
+    }
+
+    @PutMapping("/update")
+    @Operation(summary = "更新系统配置")
+    @PreAuthorize("@ss.hasPermission('system:config:update')")
+    public CommonResult<Boolean> updateConfig(@Valid @RequestBody ConfigSaveReqVO updateReqVO) {
+        configService.updateConfig(updateReqVO);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete")
+    @Operation(summary = "删除系统配置")
+    @Parameter(name = "id", description = "编号", required = true)
+    @PreAuthorize("@ss.hasPermission('system:config:delete')")
+    public CommonResult<Boolean> deleteConfig(@RequestParam("id") Long id) {
+        configService.deleteConfig(id);
+        return success(true);
+    }
+
+    @GetMapping("/get")
+    @Operation(summary = "获得系统配置")
+    @Parameter(name = "id", description = "编号", required = true, example = "1024")
+    @PreAuthorize("@ss.hasPermission('system:config:query')")
+    public CommonResult<ConfigRespVO> getConfig(@RequestParam("id") Long id) {
+        SystemConfigDO config = configService.getConfig(id);
+        return success(BeanUtils.toBean(config, ConfigRespVO.class));
+    }
+
+    @GetMapping("/page")
+    @Operation(summary = "获得系统配置分页")
+    @PreAuthorize("@ss.hasPermission('system:config:query')")
+    public CommonResult<PageResult<ConfigRespVO>> getConfigPage(@Valid ConfigPageReqVO pageReqVO) {
+        PageResult<SystemConfigDO> pageResult = configService.getConfigPage(pageReqVO);
+        return success(BeanUtils.toBean(pageResult, ConfigRespVO.class));
+    }
+
+    @GetMapping("/export-excel")
+    @Operation(summary = "导出系统配置 Excel")
+    @PreAuthorize("@ss.hasPermission('system:config:export')")
+    @OperateLog(type = EXPORT)
+    public void exportConfigExcel(@Valid ConfigPageReqVO pageReqVO,
+              HttpServletResponse response) throws IOException {
+        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+        List<SystemConfigDO> list = configService.getConfigPage(pageReqVO).getList();
+        // 导出 Excel
+        ExcelUtils.write(response, "系统配置.xls", "数据", ConfigRespVO.class,
+                        BeanUtils.toBean(list, ConfigRespVO.class));
+    }
+
+}

+ 31 - 0
feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/controller/admin/config/bo/SystemConfigBO.java

@@ -0,0 +1,31 @@
+package cn.newfeifan.mall.module.system.controller.admin.config.bo;
+
+import lombok.Data;
+
+/**
+ * 用来接收redis缓存中的值
+ */
+@Data
+public class SystemConfigBO {
+    private Long id;
+    /**
+     * 微信服务号appid
+     */
+    private String wechatAppid;
+    /**
+     * 微信服务号秘钥
+     */
+    private String wechatSecretKey;
+    /**
+     * 平台端协议+域名+端口
+     */
+    private String platformDomain;
+    /**
+     * 商户端协议+域名+端口
+     */
+    private String merchantDomain;
+    /**
+     * 移动商城端协议+域名+端口
+     */
+    private String mallDomain;
+}

+ 36 - 0
feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/controller/admin/config/vo/ConfigPageReqVO.java

@@ -0,0 +1,36 @@
+package cn.newfeifan.mall.module.system.controller.admin.config.vo;
+
+import lombok.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+import cn.newfeifan.mall.framework.common.pojo.PageParam;
+import org.springframework.format.annotation.DateTimeFormat;
+import java.time.LocalDateTime;
+
+import static cn.newfeifan.mall.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - 系统配置分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class ConfigPageReqVO extends PageParam {
+
+    @Schema(description = "微信服务号appid", example = "31635")
+    private String wechatAppid;
+
+    @Schema(description = "微信服务号秘钥")
+    private String wechatSecretKey;
+
+    @Schema(description = "平台端协议+域名+端口")
+    private String platformDomain;
+
+    @Schema(description = "商户端协议+域名+端口")
+    private String merchantDomain;
+
+    @Schema(description = "移动商城端协议+域名+端口")
+    private String mallDomain;
+
+    @Schema(description = "创建时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] createTime;
+
+}

+ 41 - 0
feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/controller/admin/config/vo/ConfigRespVO.java

@@ -0,0 +1,41 @@
+package cn.newfeifan.mall.module.system.controller.admin.config.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+import java.time.LocalDateTime;
+import com.alibaba.excel.annotation.*;
+
+@Schema(description = "管理后台 - 系统配置 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class ConfigRespVO {
+
+    @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "18615")
+    @ExcelProperty("主键")
+    private Long id;
+
+    @Schema(description = "微信服务号appid", example = "31635")
+    @ExcelProperty("微信服务号appid")
+    private String wechatAppid;
+
+    @Schema(description = "微信服务号秘钥")
+    @ExcelProperty("微信服务号秘钥")
+    private String wechatSecretKey;
+
+    @Schema(description = "平台端协议+域名+端口")
+    @ExcelProperty("平台端协议+域名+端口")
+    private String platformDomain;
+
+    @Schema(description = "商户端协议+域名+端口")
+    @ExcelProperty("商户端协议+域名+端口")
+    private String merchantDomain;
+
+    @Schema(description = "移动商城端协议+域名+端口")
+    @ExcelProperty("移动商城端协议+域名+端口")
+    private String mallDomain;
+
+    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+    @ExcelProperty("创建时间")
+    private LocalDateTime createTime;
+
+}

+ 28 - 0
feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/controller/admin/config/vo/ConfigSaveReqVO.java

@@ -0,0 +1,28 @@
+package cn.newfeifan.mall.module.system.controller.admin.config.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+
+@Schema(description = "管理后台 - 系统配置新增/修改 Request VO")
+@Data
+public class ConfigSaveReqVO {
+
+    @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "18615")
+    private Long id;
+
+    @Schema(description = "微信服务号appid", example = "31635")
+    private String wechatAppid;
+
+    @Schema(description = "微信服务号秘钥")
+    private String wechatSecretKey;
+
+    @Schema(description = "平台端协议+域名+端口")
+    private String platformDomain;
+
+    @Schema(description = "商户端协议+域名+端口")
+    private String merchantDomain;
+
+    @Schema(description = "移动商城端协议+域名+端口")
+    private String mallDomain;
+
+}

+ 17 - 0
feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/controller/admin/wechatmsgtemplate/bo/WechatMsgTemplateBO.java

@@ -0,0 +1,17 @@
+package cn.newfeifan.mall.module.system.controller.admin.wechatmsgtemplate.bo;
+
+import lombok.Data;
+
+/**
+ * 用来接收redis缓存中的值
+ */
+@Data
+public class WechatMsgTemplateBO {
+    private Long id;
+
+    private String wechatMsgTemplateId;
+
+    private String remark;
+
+    private String messageTemplateParameters;
+}

+ 48 - 0
feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/dal/dataobject/config/SystemConfigDO.java

@@ -0,0 +1,48 @@
+package cn.newfeifan.mall.module.system.dal.dataobject.config;
+
+import lombok.*;
+import com.baomidou.mybatisplus.annotation.*;
+import cn.newfeifan.mall.framework.mybatis.core.dataobject.BaseDO;
+
+/**
+ * 系统配置 DO
+ *
+ * @author 非繁人
+ */
+@TableName("system_config")
+@KeySequence("system_config_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class SystemConfigDO extends BaseDO {
+
+    /**
+     * 主键
+     */
+    @TableId
+    private Long id;
+    /**
+     * 微信服务号appid
+     */
+    private String wechatAppid;
+    /**
+     * 微信服务号秘钥
+     */
+    private String wechatSecretKey;
+    /**
+     * 平台端协议+域名+端口
+     */
+    private String platformDomain;
+    /**
+     * 商户端协议+域名+端口
+     */
+    private String merchantDomain;
+    /**
+     * 移动商城端协议+域名+端口
+     */
+    private String mallDomain;
+
+}

+ 29 - 0
feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/dal/mysql/config/SystemConfigMapper.java

@@ -0,0 +1,29 @@
+package cn.newfeifan.mall.module.system.dal.mysql.config;
+
+import cn.newfeifan.mall.framework.common.pojo.PageResult;
+import cn.newfeifan.mall.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.newfeifan.mall.framework.mybatis.core.mapper.BaseMapperX;
+import cn.newfeifan.mall.module.system.dal.dataobject.config.SystemConfigDO;
+import org.apache.ibatis.annotations.Mapper;
+import cn.newfeifan.mall.module.system.controller.admin.config.vo.*;
+
+/**
+ * 系统配置 Mapper
+ *
+ * @author 非繁人
+ */
+@Mapper
+public interface SystemConfigMapper extends BaseMapperX<SystemConfigDO> {
+
+    default PageResult<SystemConfigDO> selectPage(ConfigPageReqVO reqVO) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<SystemConfigDO>()
+                .eqIfPresent(SystemConfigDO::getWechatAppid, reqVO.getWechatAppid())
+                .eqIfPresent(SystemConfigDO::getWechatSecretKey, reqVO.getWechatSecretKey())
+                .eqIfPresent(SystemConfigDO::getPlatformDomain, reqVO.getPlatformDomain())
+                .eqIfPresent(SystemConfigDO::getMerchantDomain, reqVO.getMerchantDomain())
+                .eqIfPresent(SystemConfigDO::getMallDomain, reqVO.getMallDomain())
+                .betweenIfPresent(SystemConfigDO::getCreateTime, reqVO.getCreateTime())
+                .orderByDesc(SystemConfigDO::getId));
+    }
+
+}

+ 1 - 1
feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/dal/mysql/social/SocialUserMapper.java

@@ -34,5 +34,5 @@ public interface SocialUserMapper extends BaseMapperX<SocialUserDO> {
                 .orderByDesc(SocialUserDO::getId));
     }
 
-    String getOpenId(@Param("userId") Long userId);
+    String getOpenIdByUserId(@Param("userId") Long userId);
 }

+ 65 - 0
feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/service/config/SystemConfigService.java

@@ -0,0 +1,65 @@
+package cn.newfeifan.mall.module.system.service.config;
+
+import javax.validation.*;
+import cn.newfeifan.mall.module.system.controller.admin.config.vo.*;
+import cn.newfeifan.mall.module.system.dal.dataobject.config.SystemConfigDO;
+import cn.newfeifan.mall.framework.common.pojo.PageResult;
+
+/**
+ * 系统配置 Service 接口
+ *
+ * @author 非繁人
+ */
+public interface SystemConfigService {
+
+    /**
+     * 创建系统配置
+     *
+     * @param createReqVO 创建信息
+     * @return 编号
+     */
+    Long createConfig(@Valid ConfigSaveReqVO createReqVO);
+
+    /**
+     * 更新系统配置
+     *
+     * @param updateReqVO 更新信息
+     */
+    void updateConfig(@Valid ConfigSaveReqVO updateReqVO);
+
+    /**
+     * 删除系统配置
+     *
+     * @param id 编号
+     */
+    void deleteConfig(Long id);
+
+    /**
+     * 获得系统配置
+     *
+     * @param id 编号
+     * @return 系统配置
+     */
+    SystemConfigDO getConfig(Long id);
+
+    /**
+     * 获取系统配置
+     * @return 系统配置
+     */
+    SystemConfigDO getConfig();
+
+    /**
+     * 获取常量系统配置
+     * @return 系统配置
+     */
+    SystemConfigDO getRedisConfig();
+
+    /**
+     * 获得系统配置分页
+     *
+     * @param pageReqVO 分页查询
+     * @return 系统配置分页
+     */
+    PageResult<SystemConfigDO> getConfigPage(ConfigPageReqVO pageReqVO);
+
+}

+ 97 - 0
feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/service/config/SystemConfigServiceImpl.java

@@ -0,0 +1,97 @@
+package cn.newfeifan.mall.module.system.service.config;
+
+import cn.newfeifan.mall.module.system.controller.admin.config.bo.SystemConfigBO;
+import com.alibaba.fastjson.JSONObject;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.stereotype.Service;
+import javax.annotation.Resource;
+import org.springframework.validation.annotation.Validated;
+
+import cn.newfeifan.mall.module.system.controller.admin.config.vo.*;
+import cn.newfeifan.mall.module.system.dal.dataobject.config.SystemConfigDO;
+import cn.newfeifan.mall.framework.common.pojo.PageResult;
+import cn.newfeifan.mall.framework.common.util.object.BeanUtils;
+
+import cn.newfeifan.mall.module.system.dal.mysql.config.SystemConfigMapper;
+
+import static cn.newfeifan.mall.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.newfeifan.mall.module.system.constant.SystemConstants.SYSTEM_CONFIG;
+import static cn.newfeifan.mall.module.system.enums.ErrorCodeConstants.*;
+
+/**
+ * 系统配置 Service 实现类
+ *
+ * @author 非繁人
+ */
+@Service
+@Validated
+public class SystemConfigServiceImpl implements SystemConfigService {
+
+    @Resource
+    private SystemConfigMapper systemConfigMapper;
+    @Resource
+    private StringRedisTemplate stringRedisTemplate;
+
+    @Override
+    public Long createConfig(ConfigSaveReqVO createReqVO) {
+        // 插入
+        SystemConfigDO config = BeanUtils.toBean(createReqVO, SystemConfigDO.class);
+        systemConfigMapper.insert(config);
+        // 返回
+        return config.getId();
+    }
+
+    @Override
+    public void updateConfig(ConfigSaveReqVO updateReqVO) {
+        // 校验存在
+        validateConfigExists(updateReqVO.getId());
+        // 更新
+        SystemConfigDO updateObj = BeanUtils.toBean(updateReqVO, SystemConfigDO.class);
+        systemConfigMapper.updateById(updateObj);
+    }
+
+    @Override
+    public void deleteConfig(Long id) {
+        // 校验存在
+        validateConfigExists(id);
+        // 删除
+        systemConfigMapper.deleteById(id);
+    }
+
+    private void validateConfigExists(Long id) {
+        if (systemConfigMapper.selectById(id) == null) {
+            throw exception(CONFIG_NOT_EXISTS);
+        }
+    }
+
+    @Override
+    public SystemConfigDO getConfig(Long id) {
+        return systemConfigMapper.selectById(id);
+    }
+
+    @Override
+    public SystemConfigDO getConfig() {
+        return systemConfigMapper.selectList().get(0);
+    }
+
+    @Override
+    public SystemConfigDO getRedisConfig() {
+        String s = stringRedisTemplate.opsForValue().get(SYSTEM_CONFIG);
+        if (s != null) {
+            SystemConfigBO systemConfigBO = JSONObject.parseObject(s, SystemConfigBO.class);
+            return SystemConfigDO.builder()
+                    .id(systemConfigBO.getId())
+                    .mallDomain(systemConfigBO.getMallDomain())
+                    .merchantDomain(systemConfigBO.getMerchantDomain())
+                    .platformDomain(systemConfigBO.getPlatformDomain())
+                    .build();
+        }
+        return getConfig();
+    }
+
+    @Override
+    public PageResult<SystemConfigDO> getConfigPage(ConfigPageReqVO pageReqVO) {
+        return systemConfigMapper.selectPage(pageReqVO);
+    }
+
+}

+ 1 - 1
feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/service/social/SocialUserService.java

@@ -86,6 +86,6 @@ public interface SocialUserService {
      */
     PageResult<SocialUserDO> getSocialUserPage(SocialUserPageReqVO pageReqVO);
 
-    String getOpenId(Long userId);
+    String getOpenIdByUserId(Long userId);
 
 }

+ 2 - 2
feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/service/social/SocialUserServiceImpl.java

@@ -171,8 +171,8 @@ public class SocialUserServiceImpl implements SocialUserService {
     }
 
     @Override
-    public String getOpenId(Long userId) {
-        return socialUserMapper.getOpenId(userId);
+    public String getOpenIdByUserId(Long userId) {
+        return socialUserMapper.getOpenIdByUserId(userId);
     }
 
 }

+ 10 - 2
feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/service/wechatmsgtemplate/WechatMsgTemplateService.java

@@ -5,6 +5,8 @@ import cn.newfeifan.mall.module.system.controller.admin.wechatmsgtemplate.vo.*;
 import cn.newfeifan.mall.module.system.dal.dataobject.wechatmsgtemplate.WechatMsgTemplateDO;
 import cn.newfeifan.mall.framework.common.pojo.PageResult;
 
+import java.util.List;
+
 /**
  * 微信消息模板 Service 接口
  *
@@ -52,9 +54,15 @@ public interface WechatMsgTemplateService {
 
     /**
      * 获取微信模板
-     * @param wechatMsg 自定义的模板id
+     * @param wechatMsgId 自定义的模板id
+     * @return 微信模板
+     */
+    WechatMsgTemplateDO getWechatSsgTemplate(Long wechatMsgId);
+
+    /**
+     * 获取微信模板
      * @return 微信模板
      */
-    WechatMsgTemplateDO getWechatSsgTemplateId(Long wechatMsg);
+    List<WechatMsgTemplateDO> selectList();
 
 }

+ 27 - 2
feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/service/wechatmsgtemplate/WechatMsgTemplateServiceImpl.java

@@ -1,5 +1,8 @@
 package cn.newfeifan.mall.module.system.service.wechatmsgtemplate;
 
+import cn.newfeifan.mall.module.system.controller.admin.wechatmsgtemplate.bo.WechatMsgTemplateBO;
+import com.alibaba.fastjson.JSONObject;
+import org.springframework.data.redis.core.StringRedisTemplate;
 import org.springframework.stereotype.Service;
 import javax.annotation.Resource;
 import org.springframework.validation.annotation.Validated;
@@ -10,7 +13,10 @@ import cn.newfeifan.mall.framework.common.util.object.BeanUtils;
 
 import cn.newfeifan.mall.module.system.dal.mysql.wechatmsgtemplate.WechatMsgTemplateMapper;
 
+import java.util.List;
+
 import static cn.newfeifan.mall.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.newfeifan.mall.module.system.constant.SystemConstants.SYSTEM_WX_MESSAGE_TEMPLATE;
 import static cn.newfeifan.mall.module.system.enums.ErrorCodeConstants.*;
 
 /**
@@ -25,6 +31,9 @@ public class WechatMsgTemplateServiceImpl implements WechatMsgTemplateService {
     @Resource
     private WechatMsgTemplateMapper wechatMsgTemplateMapper;
 
+    @Resource
+    private StringRedisTemplate stringRedisTemplate;
+
     @Override
     public Long createWechatMsgTemplate(WechatMsgTemplateSaveReqVO createReqVO) {
         // 插入
@@ -68,8 +77,24 @@ public class WechatMsgTemplateServiceImpl implements WechatMsgTemplateService {
     }
 
     @Override
-    public WechatMsgTemplateDO getWechatSsgTemplateId(Long wechatMsg) {
-        return wechatMsgTemplateMapper.selectById(wechatMsg);
+    public WechatMsgTemplateDO getWechatSsgTemplate(Long wechatMsgId) {
+        String s = stringRedisTemplate.opsForValue().get(SYSTEM_WX_MESSAGE_TEMPLATE + wechatMsgId);
+        if(s != null){
+            WechatMsgTemplateBO wechatMsgTemplateBO = JSONObject.parseObject(s, WechatMsgTemplateBO.class);
+            return WechatMsgTemplateDO.builder()
+                    .wechatMsgTemplateId(wechatMsgTemplateBO.getWechatMsgTemplateId())
+                    .messageTemplateParameters(wechatMsgTemplateBO.getMessageTemplateParameters())
+                    .remark(wechatMsgTemplateBO.getRemark())
+                    .id(wechatMsgTemplateBO.getId())
+                    .build();
+        }
+
+        return wechatMsgTemplateMapper.selectById(wechatMsgId);
+    }
+
+    @Override
+    public List<WechatMsgTemplateDO> selectList() {
+        return wechatMsgTemplateMapper.selectList();
     }
 
 }

+ 12 - 0
feifan-module-system/feifan-module-system-biz/src/main/resources/mapper/config/ConfigMapper.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="cn.newfeifan.mall.module.system.dal.mysql.config.SystemConfigMapper">
+
+    <!--
+        一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
+        无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
+        代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
+        文档可见:https://www.zhongxing.cn/MyBatis/x-plugins/
+     -->
+
+</mapper>

+ 2 - 2
feifan-module-mall/feifan-module-trade-biz/src/main/resources/mapper/social/SocialUserMapper.xml → feifan-module-system/feifan-module-system-biz/src/main/resources/mapper/social/SocialUserMapper.xml

@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="cn.newfeifan.mall.module.system.dal.mysql.socialuser.SocialUserMapper">
+<mapper namespace="cn.newfeifan.mall.module.system.dal.mysql.social.SocialUserMapper">
 
-    <select id="getOpenId" resultType="string" parameterType="long">
+    <select id="getOpenIdByUserId" resultType="string" parameterType="long">
         SELECT openid FROM `system_social_user` u
         left join system_social_user_bind b on u.id = b.social_user_id
         where b.user_id = #{userId}

+ 0 - 134
feifan-module-system/feifan-module-system-biz/src/test/java/cn/newfeifan/mall/module/system/service/wechatmsgtemplate/WechatMsgTemplateServiceImplTest.java

@@ -1,134 +0,0 @@
-package cn.newfeifan.mall.module.system.service.wechatmsgtemplate;
-
-import org.junit.jupiter.api.Disabled;
-import org.junit.jupiter.api.Test;
-
-import javax.annotation.Resource;
-
-import cn.newfeifan.mall.framework.test.core.ut.BaseDbUnitTest;
-
-import cn.newfeifan.mall.module.system.controller.admin.wechatmsgtemplate.vo.*;
-import cn.newfeifan.mall.module.system.dal.dataobject.wechatmsgtemplate.WechatMsgTemplateDO;
-import cn.newfeifan.mall.module.system.dal.mysql.wechatmsgtemplate.WechatMsgTemplateMapper;
-import cn.newfeifan.mall.framework.common.pojo.PageResult;
-
-import org.springframework.context.annotation.Import;
-import static cn.newfeifan.mall.module.system.enums.ErrorCodeConstants.*;
-import static cn.newfeifan.mall.framework.test.core.util.AssertUtils.*;
-import static cn.newfeifan.mall.framework.test.core.util.RandomUtils.*;
-import static cn.newfeifan.mall.framework.common.util.date.LocalDateTimeUtils.*;
-import static cn.newfeifan.mall.framework.common.util.object.ObjectUtils.*;
-import static org.junit.jupiter.api.Assertions.*;
-
-/**
- * {@link WechatMsgTemplateServiceImpl} 的单元测试类
- *
- * @author 非繁人
- */
-@Import(WechatMsgTemplateServiceImpl.class)
-public class WechatMsgTemplateServiceImplTest extends BaseDbUnitTest {
-
-    @Resource
-    private WechatMsgTemplateServiceImpl wechatMsgTemplateService;
-
-    @Resource
-    private WechatMsgTemplateMapper wechatMsgTemplateMapper;
-
-    @Test
-    public void testCreateWechatMsgTemplate_success() {
-        // 准备参数
-        WechatMsgTemplateSaveReqVO createReqVO = randomPojo(WechatMsgTemplateSaveReqVO.class).setId(null);
-
-        // 调用
-        Long wechatMsgTemplateId = wechatMsgTemplateService.createWechatMsgTemplate(createReqVO);
-        // 断言
-        assertNotNull(wechatMsgTemplateId);
-        // 校验记录的属性是否正确
-        WechatMsgTemplateDO wechatMsgTemplate = wechatMsgTemplateMapper.selectById(wechatMsgTemplateId);
-        assertPojoEquals(createReqVO, wechatMsgTemplate, "id");
-    }
-
-    @Test
-    public void testUpdateWechatMsgTemplate_success() {
-        // mock 数据
-        WechatMsgTemplateDO dbWechatMsgTemplate = randomPojo(WechatMsgTemplateDO.class);
-        wechatMsgTemplateMapper.insert(dbWechatMsgTemplate);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        WechatMsgTemplateSaveReqVO updateReqVO = randomPojo(WechatMsgTemplateSaveReqVO.class, o -> {
-            o.setId(dbWechatMsgTemplate.getId()); // 设置更新的 ID
-        });
-
-        // 调用
-        wechatMsgTemplateService.updateWechatMsgTemplate(updateReqVO);
-        // 校验是否更新正确
-        WechatMsgTemplateDO wechatMsgTemplate = wechatMsgTemplateMapper.selectById(updateReqVO.getId()); // 获取最新的
-        assertPojoEquals(updateReqVO, wechatMsgTemplate);
-    }
-
-    @Test
-    public void testUpdateWechatMsgTemplate_notExists() {
-        // 准备参数
-        WechatMsgTemplateSaveReqVO updateReqVO = randomPojo(WechatMsgTemplateSaveReqVO.class);
-
-        // 调用, 并断言异常
-        assertServiceException(() -> wechatMsgTemplateService.updateWechatMsgTemplate(updateReqVO), WECHAT_MSG_TEMPLATE_NOT_EXISTS);
-    }
-
-    @Test
-    public void testDeleteWechatMsgTemplate_success() {
-        // mock 数据
-        WechatMsgTemplateDO dbWechatMsgTemplate = randomPojo(WechatMsgTemplateDO.class);
-        wechatMsgTemplateMapper.insert(dbWechatMsgTemplate);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        Long id = dbWechatMsgTemplate.getId();
-
-        // 调用
-        wechatMsgTemplateService.deleteWechatMsgTemplate(id);
-       // 校验数据不存在了
-       assertNull(wechatMsgTemplateMapper.selectById(id));
-    }
-
-    @Test
-    public void testDeleteWechatMsgTemplate_notExists() {
-        // 准备参数
-        Long id = randomLongId();
-
-        // 调用, 并断言异常
-        assertServiceException(() -> wechatMsgTemplateService.deleteWechatMsgTemplate(id), WECHAT_MSG_TEMPLATE_NOT_EXISTS);
-    }
-
-    @Test
-    @Disabled  // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
-    public void testGetWechatMsgTemplatePage() {
-       // mock 数据
-       WechatMsgTemplateDO dbWechatMsgTemplate = randomPojo(WechatMsgTemplateDO.class, o -> { // 等会查询到
-           o.setWechatMsgTemplateId(null);
-           o.setRemark(null);
-           o.setMessageTemplateParameters(null);
-           o.setCreateTime(null);
-       });
-       wechatMsgTemplateMapper.insert(dbWechatMsgTemplate);
-       // 测试 wechatMsgTemplateId 不匹配
-       wechatMsgTemplateMapper.insert(cloneIgnoreId(dbWechatMsgTemplate, o -> o.setWechatMsgTemplateId(null)));
-       // 测试 remark 不匹配
-       wechatMsgTemplateMapper.insert(cloneIgnoreId(dbWechatMsgTemplate, o -> o.setRemark(null)));
-       // 测试 messageTemplateParameters 不匹配
-       wechatMsgTemplateMapper.insert(cloneIgnoreId(dbWechatMsgTemplate, o -> o.setMessageTemplateParameters(null)));
-       // 测试 createTime 不匹配
-       wechatMsgTemplateMapper.insert(cloneIgnoreId(dbWechatMsgTemplate, o -> o.setCreateTime(null)));
-       // 准备参数
-       WechatMsgTemplatePageReqVO reqVO = new WechatMsgTemplatePageReqVO();
-       reqVO.setWechatMsgTemplateId(null);
-       reqVO.setRemark(null);
-       reqVO.setMessageTemplateParameters(null);
-       reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
-
-       // 调用
-       PageResult<WechatMsgTemplateDO> pageResult = wechatMsgTemplateService.getWechatMsgTemplatePage(reqVO);
-       // 断言
-       assertEquals(1, pageResult.getTotal());
-       assertEquals(1, pageResult.getList().size());
-       assertPojoEquals(dbWechatMsgTemplate, pageResult.getList().get(0));
-    }
-
-}

+ 16 - 14
sql/mysql/建空库SQL/8_20240512.sql

@@ -6,18 +6,19 @@ ALTER TABLE `member_user`
 -- 增加数据表,记录微信服务号的appid、服务号秘钥、平台端域名、商户端域名、移动商城端域名。
 -- 本表只会有一条记录
 CREATE TABLE `system_config` (
-                                             `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
-                                             `wechat_appid` varchar(255) COMMENT '微信服务号appid',
-                                             `wechat_secret_key` varchar(255) COMMENT '微信服务号秘钥',
-                                             `platform_domain` varchar(255) COMMENT '平台端协议+域名+端口',
-                                             `merchant_domain` varchar(255) COMMENT '商户端协议+域名+端口',
-                                             `mall_domain` varchar(255) COMMENT '移动商城端协议+域名+端口',
-                                             `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者',
-                                             `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
-                                             `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者',
-                                             `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
-                                             PRIMARY KEY (`id`) USING BTREE
-) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='系统配置表';
+                                 `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
+                                 `wechat_appid` varchar(255) DEFAULT NULL COMMENT '微信服务号appid',
+                                 `wechat_secret_key` varchar(255) DEFAULT NULL COMMENT '微信服务号秘钥',
+                                 `platform_domain` varchar(255) DEFAULT NULL COMMENT '平台端协议+域名+端口',
+                                 `merchant_domain` varchar(255) DEFAULT NULL COMMENT '商户端协议+域名+端口',
+                                 `mall_domain` varchar(255) DEFAULT NULL COMMENT '移动商城端协议+域名+端口',
+                                 `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者',
+                                 `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+                                 `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者',
+                                 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+                                 `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
+                                 PRIMARY KEY (`id`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COMMENT='系统配置表';
 
 -- 微信消息模板表,因为不好直接把微信那边的消息模板id写死在java代码中,所以增加此表
 CREATE TABLE `system_wechat_msg_template` (
@@ -29,6 +30,7 @@ CREATE TABLE `system_wechat_msg_template` (
                                               `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
                                               `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者',
                                               `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+                                              `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
                                               PRIMARY KEY (`id`) USING BTREE
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='微信消息模板表';
 
@@ -37,7 +39,7 @@ CREATE TABLE `wechat_message_log` (
                                       `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '消息记录ID,自增主键',
                                       `openid` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '接收消息用户的openid',
                                       `member_user_id` bigint(20) NOT NULL COMMENT '会员用户ID',
-                                      `system_user_id` bigint(20) NOT NULL COMMENT '系统用户ID',
+                                      `system_user_id` bigint(20) DEFAULT NULL COMMENT '系统用户ID',
                                       `wechat_msg_template_id` bigint(20) NOT NULL COMMENT '微信消息模板ID',
                                       `wechat_msg_template_params` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT '微信消息模板参数',
                                       `object_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '对应的业务对象ID,如订单ID、售后订单ID',
@@ -50,4 +52,4 @@ CREATE TABLE `wechat_message_log` (
                                       `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
                                       `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
                                       PRIMARY KEY (`id`) USING BTREE
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='微信消息记录表';
+) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COMMENT='微信消息记录表';