Yangzw пре 10 месеци
родитељ
комит
4bba0b2d20
20 измењених фајлова са 775 додато и 8 уклоњено
  1. 13 0
      feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/utils/wechat/WcChatMessageDto.java
  2. 164 0
      feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/utils/wechat/WcChatMessageUtils.java
  3. 36 0
      feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/utils/wechat/WeChatTemplateMessage.java
  4. 10 0
      feifan-module-mall/feifan-module-trade-biz/src/main/resources/mapper/social/SocialUserMapper.xml
  5. 5 0
      feifan-module-system/feifan-module-system-api/src/main/java/cn/newfeifan/mall/module/system/constant/SystemConstants.java
  6. 1 0
      feifan-module-system/feifan-module-system-api/src/main/java/cn/newfeifan/mall/module/system/enums/ErrorCodeConstants.java
  7. 94 0
      feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/controller/admin/wechatmsgtemplate/WechatMsgTemplateController.java
  8. 30 0
      feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/controller/admin/wechatmsgtemplate/vo/WechatMsgTemplatePageReqVO.java
  9. 33 0
      feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/controller/admin/wechatmsgtemplate/vo/WechatMsgTemplateRespVO.java
  10. 22 0
      feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/controller/admin/wechatmsgtemplate/vo/WechatMsgTemplateSaveReqVO.java
  11. 40 0
      feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/dal/dataobject/wechatmsgtemplate/WechatMsgTemplateDO.java
  12. 2 0
      feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/dal/mysql/social/SocialUserMapper.java
  13. 28 0
      feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/dal/mysql/wechatmsgtemplate/WechatMsgTemplateMapper.java
  14. 2 0
      feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/service/social/SocialUserService.java
  15. 5 0
      feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/service/social/SocialUserServiceImpl.java
  16. 60 0
      feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/service/wechatmsgtemplate/WechatMsgTemplateService.java
  17. 75 0
      feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/service/wechatmsgtemplate/WechatMsgTemplateServiceImpl.java
  18. 12 0
      feifan-module-system/feifan-module-system-biz/src/main/resources/mapper/wechatmsgtemplate/WechatMsgTemplateMapper.xml
  19. 134 0
      feifan-module-system/feifan-module-system-biz/src/test/java/cn/newfeifan/mall/module/system/service/wechatmsgtemplate/WechatMsgTemplateServiceImplTest.java
  20. 9 8
      sql/mysql/建空库SQL/8_20240512.sql

+ 13 - 0
feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/utils/wechat/WcChatMessageDto.java

@@ -0,0 +1,13 @@
+package cn.newfeifan.mall.module.trade.utils.wechat;
+
+import lombok.Data;
+
+/**
+ * 调用微信消息的模板参数类
+ */
+@Data
+public class WcChatMessageDto {
+    private Long userId;
+    private Long wechatMsgTemplateId;
+
+}

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

@@ -0,0 +1,164 @@
+package cn.newfeifan.mall.module.trade.utils.wechat;
+
+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.system.dal.dataobject.wechatmsgtemplate.WechatMsgTemplateDO;
+import cn.newfeifan.mall.module.system.service.social.SocialUserService;
+import cn.newfeifan.mall.module.system.service.wechatmsgtemplate.WechatMsgTemplateService;
+import com.google.gson.JsonObject;
+import lombok.Data;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Arrays;
+import java.util.List;
+import java.util.UUID;
+
+import static cn.newfeifan.mall.module.system.constant.SystemConstants.SYSTEM_WX_ACCESS_TOKEN;
+
+/**
+ * 发送微信消息的工具类
+ */
+@Data
+@Component
+public class WcChatMessageUtils {
+
+    @Value("${wx.mp.app-id}")
+    private String appid;
+    @Value("${wx.mp.secret}")
+    private String Wxgsecret;
+
+    @Resource
+    private StringRedisTemplate stringRedisTemplate;
+    @Resource
+    private WechatMsgTemplateService wechatMsgTemplateService;
+    @Resource
+    private SocialUserService socialUserService;
+
+    /**
+     * 获取微信的accessToken
+     *
+     * @return accessToken
+     */
+    public String getAccessToken() {
+
+        String accessToken = stringRedisTemplate.opsForValue().get(SYSTEM_WX_ACCESS_TOKEN);
+
+        if (StrUtil.isEmpty(accessToken)) {
+            // 服务号的appid以及秘钥
+            String requestUrl = StrUtil.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={}&secret={}", appid, Wxgsecret);
+            String returnMsg = HttpUtil.get(requestUrl);
+            cn.hutool.json.JSONObject responseJsonObject = JSONUtil.parseObj(returnMsg);
+            if (ObjectUtil.isNull(responseJsonObject)) try {
+                throw new Exception("响应异常:获取信息为空!");
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+            accessToken = responseJsonObject.getStr("access_token");
+
+            //微信的accessToken的失效时间是两个小时,这里改为一小时五十五分钟,怕双方的时间误差导致accessToken失效
+            long expireTime = 60 * 60 + 55 * 60; // 1小时55分钟转换为秒
+            stringRedisTemplate.opsForValue().set(SYSTEM_WX_ACCESS_TOKEN, accessToken, expireTime, java.util.concurrent.TimeUnit.SECONDS);
+        }
+
+
+        return accessToken;
+    }
+
+    /**
+     * 发送微信消息
+     *
+     * @param userId 接口消息的用户id
+     * @param wechatMsgTemplateId 自定义的消息模板id
+     */
+    public void sendWxgMessage(Long userId, Long wechatMsgTemplateId,JsonObject data) {
+
+
+        // 组装消息内容
+        String userOpenId = getOpenId(userId);
+        String templateId = getTemplateId(wechatMsgTemplateId).getWechatMsgTemplateId(); // 模板id
+        String url = "https://letcgosh.newfeifan.cn/order";       // 跳转路径(小程序之外)
+        String client_msg_id = UUID.randomUUID().toString();  // 防重入id
+
+
+
+        WeChatTemplateMessage message = new WeChatTemplateMessage();
+        message.setTouser(userOpenId);
+        message.setTemplate_id(templateId);
+        message.setUrl(url);
+        message.setClient_msg_id(client_msg_id);
+        message.setData(data);
+
+        // 发送消息
+        String returnMsg = HttpUtil.post(StrUtil.format("https://api.weixin.qq.com/cgi-bin/message/template/send?access_token={}", getAccessToken()), message.toString());
+        cn.hutool.json.JSONObject jsonObject2 = JSONUtil.parseObj(returnMsg);
+        String errmsg = jsonObject2.getStr("errmsg");
+        if (!StrUtil.equals("ok", errmsg)) System.out.println("消息发送失败!");
+    }
+
+    /**
+     * 获取模板参数
+     * @param orderNo 订单号
+     * @param logisticsName 快递公司名称
+     * @param logisticsNo 快递单号
+     * @param spuName 商品名称
+     * @return 模板参数
+     */
+    public JsonObject consignmentTemplate(String orderNo,String logisticsName,Long logisticsNo,String spuName){
+        WechatMsgTemplateDO template = getTemplateId(1L);
+        String messageTemplateParameters = template.getMessageTemplateParameters();
+
+        // 去除首尾的括号,并去除空格
+        messageTemplateParameters = messageTemplateParameters.substring(1, messageTemplateParameters.length() - 1).trim();
+
+        // 使用逗号分割字符串,并去除空格
+        String[] parts = messageTemplateParameters.split(",\\s*");
+
+        // 创建集合并将数组转换为集合
+        List<String> list = Arrays.asList(parts);
+
+        JsonObject data = new JsonObject();
+
+        // 添加字段及其值
+        JsonObject character_string2 = new JsonObject();
+        character_string2.addProperty("value", orderNo);
+        data.add(list.get(0), character_string2);
+
+        JsonObject thing6 = new JsonObject();
+        thing6.addProperty("value", logisticsName);
+        data.add(list.get(1), thing6);
+
+        JsonObject character_string7 = new JsonObject();
+        character_string7.addProperty("value", logisticsNo);
+        data.add(list.get(2), character_string7);
+        JsonObject time1 = new JsonObject();
+        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+        String format = LocalDateTime.now().format(dateTimeFormatter);
+        time1.addProperty("value", format);
+        data.add(list.get(3), time1);
+        JsonObject thing8 = new JsonObject();
+        thing8.addProperty("value", spuName);
+        data.add(list.get(4), character_string7);
+
+        return data;
+    }
+
+    /**
+     * 通过自己定义消息模板id获取微信第三方模板
+     * @param wechatMsgTemplateId 自己定义消息模板id
+     * @return 微信第三方模板
+     */
+    private WechatMsgTemplateDO getTemplateId(Long wechatMsgTemplateId){
+        return wechatMsgTemplateService.getWechatSsgTemplateId(wechatMsgTemplateId);
+    }
+
+    private String getOpenId(Long userId){
+        return socialUserService.getOpenId(userId);
+    }
+}

+ 36 - 0
feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/utils/wechat/WeChatTemplateMessage.java

@@ -0,0 +1,36 @@
+package cn.newfeifan.mall.module.trade.utils.wechat;
+
+import com.google.gson.JsonObject;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+/**
+ * 微信模板消息
+ */
+@Data
+public class WeChatTemplateMessage {
+    private String touser;
+
+    private String template_id;
+
+    private String url;
+
+    private MiniProgram miniprogram;
+
+    private String client_msg_id;
+
+    private JsonObject data;
+
+    // Inner classes
+    @lombok.Data
+    @AllArgsConstructor
+    public static class MiniProgram {
+        private String appid;
+        private String pagepath;
+    }
+
+
+    public String toString(){
+        return "{\"touser\":\"" + touser + "\",\"template_id\":\"" + template_id + "\",\"url\":\"" + url + "\",\"client_msg_id\":\"" + client_msg_id + "\",\"data\":" + data.toString() + "}";
+    }
+}

+ 10 - 0
feifan-module-mall/feifan-module-trade-biz/src/main/resources/mapper/social/SocialUserMapper.xml

@@ -0,0 +1,10 @@
+<?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">
+
+    <select id="getOpenId" 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}
+    </select>
+</mapper>

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

@@ -0,0 +1,5 @@
+package cn.newfeifan.mall.module.system.constant;
+
+public class SystemConstants {
+    public static final String SYSTEM_WX_ACCESS_TOKEN = "system:wx:access_token";
+}

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

@@ -170,5 +170,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, "微信消息模板不存在");
 
 }

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

@@ -0,0 +1,94 @@
+package cn.newfeifan.mall.module.system.controller.admin.wechatmsgtemplate;
+
+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.wechatmsgtemplate.vo.*;
+import cn.newfeifan.mall.module.system.dal.dataobject.wechatmsgtemplate.WechatMsgTemplateDO;
+import cn.newfeifan.mall.module.system.service.wechatmsgtemplate.WechatMsgTemplateService;
+
+@Tag(name = "管理后台 - 微信消息模板")
+@RestController
+@RequestMapping("/system/wechat-msg-template")
+@Validated
+public class WechatMsgTemplateController {
+
+    @Resource
+    private WechatMsgTemplateService wechatMsgTemplateService;
+
+    @PostMapping("/create")
+    @Operation(summary = "创建微信消息模板")
+    @PreAuthorize("@ss.hasPermission('system:wechat-msg-template:create')")
+    public CommonResult<Long> createWechatMsgTemplate(@Valid @RequestBody WechatMsgTemplateSaveReqVO createReqVO) {
+        return success(wechatMsgTemplateService.createWechatMsgTemplate(createReqVO));
+    }
+
+    @PutMapping("/update")
+    @Operation(summary = "更新微信消息模板")
+    @PreAuthorize("@ss.hasPermission('system:wechat-msg-template:update')")
+    public CommonResult<Boolean> updateWechatMsgTemplate(@Valid @RequestBody WechatMsgTemplateSaveReqVO updateReqVO) {
+        wechatMsgTemplateService.updateWechatMsgTemplate(updateReqVO);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete")
+    @Operation(summary = "删除微信消息模板")
+    @Parameter(name = "id", description = "编号", required = true)
+    @PreAuthorize("@ss.hasPermission('system:wechat-msg-template:delete')")
+    public CommonResult<Boolean> deleteWechatMsgTemplate(@RequestParam("id") Long id) {
+        wechatMsgTemplateService.deleteWechatMsgTemplate(id);
+        return success(true);
+    }
+
+    @GetMapping("/get")
+    @Operation(summary = "获得微信消息模板")
+    @Parameter(name = "id", description = "编号", required = true, example = "1024")
+    @PreAuthorize("@ss.hasPermission('system:wechat-msg-template:query')")
+    public CommonResult<WechatMsgTemplateRespVO> getWechatMsgTemplate(@RequestParam("id") Long id) {
+        WechatMsgTemplateDO wechatMsgTemplate = wechatMsgTemplateService.getWechatMsgTemplate(id);
+        return success(BeanUtils.toBean(wechatMsgTemplate, WechatMsgTemplateRespVO.class));
+    }
+
+    @GetMapping("/page")
+    @Operation(summary = "获得微信消息模板分页")
+    @PreAuthorize("@ss.hasPermission('system:wechat-msg-template:query')")
+    public CommonResult<PageResult<WechatMsgTemplateRespVO>> getWechatMsgTemplatePage(@Valid WechatMsgTemplatePageReqVO pageReqVO) {
+        PageResult<WechatMsgTemplateDO> pageResult = wechatMsgTemplateService.getWechatMsgTemplatePage(pageReqVO);
+        return success(BeanUtils.toBean(pageResult, WechatMsgTemplateRespVO.class));
+    }
+
+    @GetMapping("/export-excel")
+    @Operation(summary = "导出微信消息模板 Excel")
+    @PreAuthorize("@ss.hasPermission('system:wechat-msg-template:export')")
+    @OperateLog(type = EXPORT)
+    public void exportWechatMsgTemplateExcel(@Valid WechatMsgTemplatePageReqVO pageReqVO,
+              HttpServletResponse response) throws IOException {
+        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+        List<WechatMsgTemplateDO> list = wechatMsgTemplateService.getWechatMsgTemplatePage(pageReqVO).getList();
+        // 导出 Excel
+        ExcelUtils.write(response, "微信消息模板.xls", "数据", WechatMsgTemplateRespVO.class,
+                        BeanUtils.toBean(list, WechatMsgTemplateRespVO.class));
+    }
+
+}

+ 30 - 0
feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/controller/admin/wechatmsgtemplate/vo/WechatMsgTemplatePageReqVO.java

@@ -0,0 +1,30 @@
+package cn.newfeifan.mall.module.system.controller.admin.wechatmsgtemplate.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 WechatMsgTemplatePageReqVO extends PageParam {
+
+    @Schema(description = "微信消息模板id", example = "29466")
+    private String wechatMsgTemplateId;
+
+    @Schema(description = "备注、说明", example = "随便")
+    private String remark;
+
+    @Schema(description = "消息模板参数")
+    private String messageTemplateParameters;
+
+    @Schema(description = "创建时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] createTime;
+
+}

+ 33 - 0
feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/controller/admin/wechatmsgtemplate/vo/WechatMsgTemplateRespVO.java

@@ -0,0 +1,33 @@
+package cn.newfeifan.mall.module.system.controller.admin.wechatmsgtemplate.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 WechatMsgTemplateRespVO {
+
+    @Schema(description = "模板id,非自增,由开发人员编号,对应java中的常量", requiredMode = Schema.RequiredMode.REQUIRED, example = "13788")
+    @ExcelProperty("模板id,非自增,由开发人员编号,对应java中的常量")
+    private Long id;
+
+    @Schema(description = "微信消息模板id", example = "29466")
+    @ExcelProperty("微信消息模板id")
+    private String wechatMsgTemplateId;
+
+    @Schema(description = "备注、说明", example = "随便")
+    @ExcelProperty("备注、说明")
+    private String remark;
+
+    @Schema(description = "消息模板参数")
+    @ExcelProperty("消息模板参数")
+    private String messageTemplateParameters;
+
+    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+    @ExcelProperty("创建时间")
+    private LocalDateTime createTime;
+
+}

+ 22 - 0
feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/controller/admin/wechatmsgtemplate/vo/WechatMsgTemplateSaveReqVO.java

@@ -0,0 +1,22 @@
+package cn.newfeifan.mall.module.system.controller.admin.wechatmsgtemplate.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+
+@Schema(description = "管理后台 - 微信消息模板新增/修改 Request VO")
+@Data
+public class WechatMsgTemplateSaveReqVO {
+
+    @Schema(description = "模板id,非自增,由开发人员编号,对应java中的常量", requiredMode = Schema.RequiredMode.REQUIRED, example = "13788")
+    private Long id;
+
+    @Schema(description = "微信消息模板id", example = "29466")
+    private String wechatMsgTemplateId;
+
+    @Schema(description = "备注、说明", example = "随便")
+    private String remark;
+
+    @Schema(description = "消息模板参数")
+    private String messageTemplateParameters;
+
+}

+ 40 - 0
feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/dal/dataobject/wechatmsgtemplate/WechatMsgTemplateDO.java

@@ -0,0 +1,40 @@
+package cn.newfeifan.mall.module.system.dal.dataobject.wechatmsgtemplate;
+
+import lombok.*;
+import com.baomidou.mybatisplus.annotation.*;
+import cn.newfeifan.mall.framework.mybatis.core.dataobject.BaseDO;
+
+/**
+ * 微信消息模板 DO
+ *
+ * @author 非繁人
+ */
+@TableName("system_wechat_msg_template")
+@KeySequence("system_wechat_msg_template_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class WechatMsgTemplateDO extends BaseDO {
+
+    /**
+     * 模板id,非自增,由开发人员编号,对应java中的常量
+     */
+    @TableId
+    private Long id;
+    /**
+     * 微信消息模板id
+     */
+    private String wechatMsgTemplateId;
+    /**
+     * 备注、说明
+     */
+    private String remark;
+    /**
+     * 消息模板参数
+     */
+    private String messageTemplateParameters;
+
+}

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

@@ -7,6 +7,7 @@ import cn.newfeifan.mall.module.system.controller.admin.socail.vo.user.SocialUse
 import cn.newfeifan.mall.module.system.dal.dataobject.social.SocialUserDO;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
 
 @Mapper
 public interface SocialUserMapper extends BaseMapperX<SocialUserDO> {
@@ -33,4 +34,5 @@ public interface SocialUserMapper extends BaseMapperX<SocialUserDO> {
                 .orderByDesc(SocialUserDO::getId));
     }
 
+    String getOpenId(@Param("userId") Long userId);
 }

+ 28 - 0
feifan-module-system/feifan-module-system-biz/src/main/java/cn/newfeifan/mall/module/system/dal/mysql/wechatmsgtemplate/WechatMsgTemplateMapper.java

@@ -0,0 +1,28 @@
+package cn.newfeifan.mall.module.system.dal.mysql.wechatmsgtemplate;
+
+
+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.wechatmsgtemplate.WechatMsgTemplateDO;
+import org.apache.ibatis.annotations.Mapper;
+import cn.newfeifan.mall.module.system.controller.admin.wechatmsgtemplate.vo.*;
+
+/**
+ * 微信消息模板 Mapper
+ *
+ * @author 非繁人
+ */
+@Mapper
+public interface WechatMsgTemplateMapper extends BaseMapperX<WechatMsgTemplateDO> {
+
+    default PageResult<WechatMsgTemplateDO> selectPage(WechatMsgTemplatePageReqVO reqVO) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<WechatMsgTemplateDO>()
+                .eqIfPresent(WechatMsgTemplateDO::getWechatMsgTemplateId, reqVO.getWechatMsgTemplateId())
+                .eqIfPresent(WechatMsgTemplateDO::getRemark, reqVO.getRemark())
+                .eqIfPresent(WechatMsgTemplateDO::getMessageTemplateParameters, reqVO.getMessageTemplateParameters())
+                .betweenIfPresent(WechatMsgTemplateDO::getCreateTime, reqVO.getCreateTime())
+                .orderByDesc(WechatMsgTemplateDO::getId));
+    }
+
+}

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

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

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

@@ -170,4 +170,9 @@ public class SocialUserServiceImpl implements SocialUserService {
         return socialUserMapper.selectPage(pageReqVO);
     }
 
+    @Override
+    public String getOpenId(Long userId) {
+        return socialUserMapper.getOpenId(userId);
+    }
+
 }

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

@@ -0,0 +1,60 @@
+package cn.newfeifan.mall.module.system.service.wechatmsgtemplate;
+
+import javax.validation.*;
+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;
+
+/**
+ * 微信消息模板 Service 接口
+ *
+ * @author 非繁人
+ */
+public interface WechatMsgTemplateService {
+
+    /**
+     * 创建微信消息模板
+     *
+     * @param createReqVO 创建信息
+     * @return 编号
+     */
+    Long createWechatMsgTemplate(@Valid WechatMsgTemplateSaveReqVO createReqVO);
+
+    /**
+     * 更新微信消息模板
+     *
+     * @param updateReqVO 更新信息
+     */
+    void updateWechatMsgTemplate(@Valid WechatMsgTemplateSaveReqVO updateReqVO);
+
+    /**
+     * 删除微信消息模板
+     *
+     * @param id 编号
+     */
+    void deleteWechatMsgTemplate(Long id);
+
+    /**
+     * 获得微信消息模板
+     *
+     * @param id 编号
+     * @return 微信消息模板
+     */
+    WechatMsgTemplateDO getWechatMsgTemplate(Long id);
+
+    /**
+     * 获得微信消息模板分页
+     *
+     * @param pageReqVO 分页查询
+     * @return 微信消息模板分页
+     */
+    PageResult<WechatMsgTemplateDO> getWechatMsgTemplatePage(WechatMsgTemplatePageReqVO pageReqVO);
+
+    /**
+     * 获取微信模板
+     * @param wechatMsg 自定义的模板id
+     * @return 微信模板
+     */
+    WechatMsgTemplateDO getWechatSsgTemplateId(Long wechatMsg);
+
+}

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

@@ -0,0 +1,75 @@
+package cn.newfeifan.mall.module.system.service.wechatmsgtemplate;
+
+import org.springframework.stereotype.Service;
+import javax.annotation.Resource;
+import org.springframework.validation.annotation.Validated;
+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 cn.newfeifan.mall.framework.common.util.object.BeanUtils;
+
+import cn.newfeifan.mall.module.system.dal.mysql.wechatmsgtemplate.WechatMsgTemplateMapper;
+
+import static cn.newfeifan.mall.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.newfeifan.mall.module.system.enums.ErrorCodeConstants.*;
+
+/**
+ * 微信消息模板 Service 实现类
+ *
+ * @author 非繁人
+ */
+@Service
+@Validated
+public class WechatMsgTemplateServiceImpl implements WechatMsgTemplateService {
+
+    @Resource
+    private WechatMsgTemplateMapper wechatMsgTemplateMapper;
+
+    @Override
+    public Long createWechatMsgTemplate(WechatMsgTemplateSaveReqVO createReqVO) {
+        // 插入
+        WechatMsgTemplateDO wechatMsgTemplate = BeanUtils.toBean(createReqVO, WechatMsgTemplateDO.class);
+        wechatMsgTemplateMapper.insert(wechatMsgTemplate);
+        // 返回
+        return wechatMsgTemplate.getId();
+    }
+
+    @Override
+    public void updateWechatMsgTemplate(WechatMsgTemplateSaveReqVO updateReqVO) {
+        // 校验存在
+        validateWechatMsgTemplateExists(updateReqVO.getId());
+        // 更新
+        WechatMsgTemplateDO updateObj = BeanUtils.toBean(updateReqVO, WechatMsgTemplateDO.class);
+        wechatMsgTemplateMapper.updateById(updateObj);
+    }
+
+    @Override
+    public void deleteWechatMsgTemplate(Long id) {
+        // 校验存在
+        validateWechatMsgTemplateExists(id);
+        // 删除
+        wechatMsgTemplateMapper.deleteById(id);
+    }
+
+    private void validateWechatMsgTemplateExists(Long id) {
+        if (wechatMsgTemplateMapper.selectById(id) == null) {
+            throw exception(WECHAT_MSG_TEMPLATE_NOT_EXISTS);
+        }
+    }
+
+    @Override
+    public WechatMsgTemplateDO getWechatMsgTemplate(Long id) {
+        return wechatMsgTemplateMapper.selectById(id);
+    }
+
+    @Override
+    public PageResult<WechatMsgTemplateDO> getWechatMsgTemplatePage(WechatMsgTemplatePageReqVO pageReqVO) {
+        return wechatMsgTemplateMapper.selectPage(pageReqVO);
+    }
+
+    @Override
+    public WechatMsgTemplateDO getWechatSsgTemplateId(Long wechatMsg) {
+        return wechatMsgTemplateMapper.selectById(wechatMsg);
+    }
+
+}

+ 12 - 0
feifan-module-system/feifan-module-system-biz/src/main/resources/mapper/wechatmsgtemplate/WechatMsgTemplateMapper.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.wechatmsgtemplate.WechatMsgTemplateMapper">
+
+    <!--
+        一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
+        无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
+        代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
+        文档可见:https://www.zhongxing.cn/MyBatis/x-plugins/
+     -->
+
+</mapper>

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

@@ -0,0 +1,134 @@
+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));
+    }
+
+}

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

@@ -21,14 +21,15 @@ CREATE TABLE `system_config` (
 
 -- 微信消息模板表,因为不好直接把微信那边的消息模板id写死在java代码中,所以增加此表
 CREATE TABLE `system_wechat_msg_template` (
-                                 `id` bigint(20) NOT NULL COMMENT '模板id,非自增,由开发人员编号,对应java中的常量',
-                                 `wechat_msg_template_id` varchar(255) COMMENT '微信消息模板id',
-                                 `remark` 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
+                                              `id` bigint(20) NOT NULL COMMENT '模板id,非自增,由开发人员编号,对应java中的常量',
+                                              `wechat_msg_template_id` varchar(255) DEFAULT NULL COMMENT '微信消息模板id',
+                                              `remark` varchar(255) DEFAULT NULL COMMENT '备注、说明',
+                                              `message_template_parameters` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci 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 DEFAULT CHARSET=utf8mb4 COMMENT='微信消息模板表';