resultBody);
+
+ /**
+ * 排序值,拦截器根据order值顺序执行
+ *
+ * 值越小,越早执行
+ *
+ * @return 排序值
+ */
+ int getOrder();
+}
diff --git a/src/main/java/cn/iocoder/dashboard/framework/msg/sms/intercepter/SmsLogIntercepter.java b/src/main/java/cn/iocoder/dashboard/framework/msg/sms/intercepter/SmsLogIntercepter.java
new file mode 100644
index 000000000..9a7effd95
--- /dev/null
+++ b/src/main/java/cn/iocoder/dashboard/framework/msg/sms/intercepter/SmsLogIntercepter.java
@@ -0,0 +1,46 @@
+package cn.iocoder.dashboard.framework.msg.sms.intercepter;
+
+import cn.iocoder.dashboard.framework.msg.sms.SmsBody;
+import cn.iocoder.dashboard.framework.msg.sms.SmsResult;
+import cn.iocoder.dashboard.modules.msg.dal.mysql.dao.sms.SmsLogMapper;
+import cn.iocoder.dashboard.util.json.JsonUtils;
+import lombok.Setter;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.Collection;
+
+/**
+ * 短信日志拦截器
+ *
+ * @author zzf
+ * @date 2021/1/22 15:46
+ */
+@Slf4j
+public class SmsLogIntercepter implements SmsIntercepter {
+
+
+ @Override
+ public void beforeSender(SmsBody msgBody, Collection targets) {
+ log.debug("ready send sms, body: {}, target: {}", JsonUtils.toJsonString(msgBody), targets);
+
+ }
+
+ @Override
+ public void afterSender(SmsBody msgBody, Collection targets, SmsResult resultBody) {
+ if (resultBody.getSuccess()) {
+ //
+ } else {
+ log.warn("send sms fail, body: {}, target: {}, resultBody: {}",
+ JsonUtils.toJsonString(msgBody),
+ targets,
+ JsonUtils.toJsonString(resultBody)
+ );
+ }
+
+ }
+
+ @Override
+ public int getOrder() {
+ return 0;
+ }
+}
diff --git a/src/main/java/cn/iocoder/dashboard/framework/msg/sms/proxy/DefaultSmsSenderProxy.java b/src/main/java/cn/iocoder/dashboard/framework/msg/sms/proxy/DefaultSmsSenderProxy.java
new file mode 100644
index 000000000..f9d7e566f
--- /dev/null
+++ b/src/main/java/cn/iocoder/dashboard/framework/msg/sms/proxy/DefaultSmsSenderProxy.java
@@ -0,0 +1,41 @@
+package cn.iocoder.dashboard.framework.msg.sms.proxy;
+
+import cn.hutool.core.util.ObjectUtil;
+import cn.iocoder.dashboard.framework.msg.sms.SmsBody;
+import cn.iocoder.dashboard.framework.msg.sms.SmsResult;
+import cn.iocoder.dashboard.framework.msg.sms.SmsSender;
+import cn.iocoder.dashboard.framework.msg.sms.intercepter.AbstractSmsIntercepterChain;
+
+import java.util.Collection;
+
+/**
+ * 消息父接口
+ *
+ * @author zzf
+ * @date 2021/1/22 15:46
+ */
+public class DefaultSmsSenderProxy implements SmsSender {
+
+ private final SmsSender smsSender;
+ private final AbstractSmsIntercepterChain chain;
+
+ @Override
+ public SmsResult send(SmsBody msgBody, Collection targets) {
+ if (ObjectUtil.isNotNull(chain) && ObjectUtil.isNotEmpty(chain.getIntercepterList())) {
+ chain.getIntercepterList().forEach(s -> s.beforeSender(msgBody, targets));
+ }
+
+ SmsResult resultBody = smsSender.send(msgBody, targets);
+
+ if (ObjectUtil.isNotNull(chain) && ObjectUtil.isNotEmpty(chain.getIntercepterList())) {
+ chain.getIntercepterList().forEach(s -> s.afterSender(msgBody, targets, resultBody));
+ }
+ return resultBody;
+ }
+
+ public DefaultSmsSenderProxy(SmsSender smsSender,
+ AbstractSmsIntercepterChain chain) {
+ this.smsSender = smsSender;
+ this.chain = chain;
+ }
+}
diff --git a/src/main/java/cn/iocoder/dashboard/framework/msg/sms/proxy/SmsSenderProxy.java b/src/main/java/cn/iocoder/dashboard/framework/msg/sms/proxy/SmsSenderProxy.java
new file mode 100644
index 000000000..069916e2a
--- /dev/null
+++ b/src/main/java/cn/iocoder/dashboard/framework/msg/sms/proxy/SmsSenderProxy.java
@@ -0,0 +1,34 @@
+package cn.iocoder.dashboard.framework.msg.sms.proxy;
+
+import cn.iocoder.dashboard.framework.msg.sms.SmsSender;
+import cn.iocoder.dashboard.framework.msg.sms.intercepter.SmsIntercepter;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * 消息父接口
+ *
+ * @author zzf
+ * @date 2021/1/22 15:46
+ */
+public interface SmsSenderProxy extends SmsSender {
+
+ /**
+ * 添加短信拦截器
+ *
+ * @param smsIntercepter 短信拦截器
+ */
+ default void addSmsIntercepter(SmsIntercepter smsIntercepter) {
+ addSmsIntercepter(Collections.singletonList(smsIntercepter));
+ }
+
+ /**
+ * 添加短信拦截器
+ *
+ * @param smsIntercepterList 短信拦截器数组
+ */
+ void addSmsIntercepter(List smsIntercepterList);
+
+
+}
diff --git a/src/main/java/cn/iocoder/dashboard/framework/redis/core/RedisKeyDefine.java b/src/main/java/cn/iocoder/dashboard/framework/redis/core/RedisKeyDefine.java
index b9adcc3f1..ee3a342a0 100644
--- a/src/main/java/cn/iocoder/dashboard/framework/redis/core/RedisKeyDefine.java
+++ b/src/main/java/cn/iocoder/dashboard/framework/redis/core/RedisKeyDefine.java
@@ -1,8 +1,6 @@
package cn.iocoder.dashboard.framework.redis.core;
-import lombok.AllArgsConstructor;
import lombok.Data;
-import lombok.Getter;
import java.time.Duration;
@@ -26,20 +24,15 @@ public class RedisKeyDefine {
}
- @Getter
- @AllArgsConstructor
- public enum TimeoutTypeEnum {
+ /**
+ * 过期时间 - 永不过期
+ */
+ public static final Duration TIMEOUT_FOREVER = null;
- FOREVER(1), // 永不超时
- DYNAMIC(2), // 动态超时
- FIXED(3); // 固定超时
-
- /**
- * 类型
- */
- private final Integer type;
-
- }
+ /**
+ * 过期时间 - 动态,通过参数传入
+ */
+ public static final Duration TIMEOUT_DYNAMIC = null;
/**
* Key 模板
@@ -55,12 +48,10 @@ public class RedisKeyDefine {
* 如果是使用分布式锁,设置为 {@link java.util.concurrent.locks.Lock} 类型
*/
private final Class> valueType;
- /**
- * 超时类型
- */
- private final TimeoutTypeEnum timeoutType;
/**
* 过期时间
+ *
+ * 为空时,表示永不过期 {@link #TIMEOUT_FOREVER}
*/
private final Duration timeout;
@@ -68,20 +59,7 @@ public class RedisKeyDefine {
this.keyTemplate = keyTemplate;
this.keyType = keyType;
this.valueType = valueType;
- this.timeoutType = TimeoutTypeEnum.FIXED;
this.timeout = timeout;
- // 添加注册表
- RedisKeyRegistry.add(this);
- }
-
- public RedisKeyDefine(String keyTemplate, KeyTypeEnum keyType, Class> valueType, TimeoutTypeEnum timeoutType) {
- this.keyTemplate = keyTemplate;
- this.keyType = keyType;
- this.valueType = valueType;
- this.timeoutType = timeoutType;
- this.timeout = Duration.ZERO;
- // 添加注册表
- RedisKeyRegistry.add(this);
}
}
diff --git a/src/main/java/cn/iocoder/dashboard/framework/redis/core/RedisKeyRegistry.java b/src/main/java/cn/iocoder/dashboard/framework/redis/core/RedisKeyRegistry.java
deleted file mode 100644
index 4a220fbd0..000000000
--- a/src/main/java/cn/iocoder/dashboard/framework/redis/core/RedisKeyRegistry.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package cn.iocoder.dashboard.framework.redis.core;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * {@link RedisKeyDefine} 注册表
- */
-public class RedisKeyRegistry {
-
- private static final List defines = new ArrayList<>();
-
- public static void add(RedisKeyDefine define) {
- defines.add(define);
- }
-
- public static List list() {
- return defines;
- }
-
- public static int size() {
- return defines.size();
- }
-
-}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/SmsChannelController.java b/src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/SmsChannelController.java
new file mode 100644
index 000000000..c28d9b862
--- /dev/null
+++ b/src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/SmsChannelController.java
@@ -0,0 +1,54 @@
+package cn.iocoder.dashboard.modules.msg.controller.sms;
+
+import cn.iocoder.dashboard.common.pojo.CommonResult;
+import cn.iocoder.dashboard.common.pojo.PageResult;
+import cn.iocoder.dashboard.modules.msg.controller.sms.vo.req.SmsChannelCreateReqVO;
+import cn.iocoder.dashboard.modules.msg.controller.sms.vo.req.SmsChannelPageReqVO;
+import cn.iocoder.dashboard.modules.msg.controller.sms.vo.resp.SmsChannelEnumRespVO;
+import cn.iocoder.dashboard.modules.msg.dal.mysql.daoobject.sms.SmsChannelDO;
+import cn.iocoder.dashboard.modules.msg.service.sms.SmsChannelService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+import static cn.iocoder.dashboard.common.pojo.CommonResult.success;
+
+@Api("短信 渠道/签名 API")
+@RestController
+@RequestMapping("/sms/channel")
+public class SmsChannelController {
+
+ @Resource
+ private SmsChannelService service;
+
+ @ApiOperation("获取渠道/签名分页")
+ @GetMapping("/page")
+ public CommonResult> getPermissionInfo(@Validated SmsChannelPageReqVO reqVO) {
+ return success(service.pageChannels(reqVO));
+ }
+
+ @ApiOperation("获取渠道枚举")
+ @GetMapping("/list/channel-enum")
+ public CommonResult> getChannelEnums() {
+ return success(service.getChannelEnums());
+ }
+
+
+ @ApiOperation("添加消息渠道")
+ @PostMapping("/create")
+ public CommonResult add(@Validated @RequestBody SmsChannelCreateReqVO reqVO) {
+ return success(service.createChannel(reqVO));
+ }
+
+ @ApiOperation("刷新消息渠道信息")
+ @PutMapping("/flush")
+ public CommonResult flushChannel() {
+ return success(service.flushChannel());
+ }
+
+
+}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/SmsTemplateController.java b/src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/SmsTemplateController.java
new file mode 100644
index 000000000..8bd73b12e
--- /dev/null
+++ b/src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/SmsTemplateController.java
@@ -0,0 +1,84 @@
+package cn.iocoder.dashboard.modules.msg.controller.sms;
+
+import cn.iocoder.dashboard.common.enums.CommonStatusEnum;
+import cn.iocoder.dashboard.common.pojo.CommonResult;
+import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog;
+import cn.iocoder.dashboard.modules.system.controller.auth.vo.SysAuthLoginReqVO;
+import cn.iocoder.dashboard.modules.system.controller.auth.vo.SysAuthLoginRespVO;
+import cn.iocoder.dashboard.modules.system.controller.auth.vo.SysAuthMenuRespVO;
+import cn.iocoder.dashboard.modules.system.controller.auth.vo.SysAuthPermissionInfoRespVO;
+import cn.iocoder.dashboard.modules.system.convert.auth.SysAuthConvert;
+import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysMenuDO;
+import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysRoleDO;
+import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO;
+import cn.iocoder.dashboard.modules.system.enums.permission.MenuTypeEnum;
+import cn.iocoder.dashboard.modules.system.service.auth.SysAuthService;
+import cn.iocoder.dashboard.modules.system.service.permission.SysPermissionService;
+import cn.iocoder.dashboard.modules.system.service.permission.SysRoleService;
+import cn.iocoder.dashboard.modules.system.service.user.SysUserService;
+import cn.iocoder.dashboard.util.collection.SetUtils;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.validation.Valid;
+import java.util.List;
+
+import static cn.iocoder.dashboard.common.pojo.CommonResult.success;
+import static cn.iocoder.dashboard.framework.security.core.util.SecurityUtils.getLoginUserId;
+import static cn.iocoder.dashboard.framework.security.core.util.SecurityUtils.getLoginUserRoleIds;
+
+@Api("认证 API")
+@RestController
+@RequestMapping("/sms/template")
+public class SmsTemplateController {
+
+ @Resource
+ private SysAuthService authService;
+ @Resource
+ private SysUserService userService;
+ @Resource
+ private SysRoleService roleService;
+ @Resource
+ private SysPermissionService permissionService;
+
+ @ApiOperation("使用账号密码登录")
+ @PostMapping("/login")
+ @OperateLog(enable = false) // 避免 Post 请求被记录操作日志
+ public CommonResult login(@RequestBody @Valid SysAuthLoginReqVO reqVO) {
+ String token = authService.login(reqVO.getUsername(), reqVO.getPassword(), reqVO.getUuid(), reqVO.getCode());
+ // 返回结果
+ return success(SysAuthLoginRespVO.builder().token(token).build());
+ }
+
+ @ApiOperation("获取登陆用户的权限信息")
+ @GetMapping("/get-permission-info")
+ public CommonResult getPermissionInfo() {
+ // 获得用户信息
+ SysUserDO user = userService.getUser(getLoginUserId());
+ if (user == null) {
+ return null;
+ }
+ // 获得角色列表
+ List roleList = roleService.listRolesFromCache(getLoginUserRoleIds());
+ // 获得菜单列表
+ List menuList = permissionService.listRoleMenusFromCache(getLoginUserRoleIds(),
+ SetUtils.asSet(MenuTypeEnum.DIR.getType(), MenuTypeEnum.MENU.getType(), MenuTypeEnum.BUTTON.getType()),
+ SetUtils.asSet(CommonStatusEnum.ENABLE.getStatus()));
+ // 拼接结果返回
+ return success(SysAuthConvert.INSTANCE.convert(user, roleList, menuList));
+ }
+
+ @ApiOperation("获得登陆用户的菜单列表")
+ @GetMapping("list-menus")
+ public CommonResult> listMenus() {
+ // 获得用户拥有的菜单列表
+ List menuList = permissionService.listRoleMenusFromCache(getLoginUserRoleIds(),
+ SetUtils.asSet(MenuTypeEnum.DIR.getType(), MenuTypeEnum.MENU.getType()), // 只要目录和菜单类型
+ SetUtils.asSet(CommonStatusEnum.ENABLE.getStatus())); // 只要开启的
+ // 转换成 Tree 结构返回
+ return success(SysAuthConvert.INSTANCE.buildMenuTree(menuList));
+ }
+
+}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/vo/SmsChannelAllVO.java b/src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/vo/SmsChannelAllVO.java
new file mode 100644
index 000000000..bac72c959
--- /dev/null
+++ b/src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/vo/SmsChannelAllVO.java
@@ -0,0 +1,58 @@
+package cn.iocoder.dashboard.modules.msg.controller.sms.vo;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 渠道(包含模板)信息VO类
+ *
+ * @author zzf
+ * @date 2021/1/25 17:01
+ */
+@Data
+@EqualsAndHashCode
+public class SmsChannelAllVO implements Serializable {
+
+ /**
+ * id
+ */
+ private Long id;
+
+ /**
+ * 编码(来自枚举类 阿里、华为、七牛等)
+ */
+ private String code;
+
+ /**
+ * 渠道账号id
+ */
+ private String apiKey;
+
+ /**
+ * 渠道账号秘钥
+ */
+ private String apiSecret;
+
+ /**
+ * 实际渠道签名唯一标识
+ */
+ private String apiSignatureId;
+
+ /**
+ * 签名值
+ */
+ private String signature;
+
+ /**
+ * 该渠道名下的短信模板集合
+ */
+ private List templateList;
+
+ public SmsTemplateVO getTemplateByTemplateCode(String tempCode) {
+ return templateList.stream().filter(s -> s.getCode().equals(tempCode)).findFirst().get();
+ }
+
+}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/vo/SmsTemplateVO.java b/src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/vo/SmsTemplateVO.java
new file mode 100644
index 000000000..04bfe9a62
--- /dev/null
+++ b/src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/vo/SmsTemplateVO.java
@@ -0,0 +1,30 @@
+package cn.iocoder.dashboard.modules.msg.controller.sms.vo;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 渠道模板VO类
+ *
+ * @author zzf
+ * @date 2021/1/25 17:03
+ */
+@Data
+@EqualsAndHashCode
+public class SmsTemplateVO {
+
+ /**
+ * 业务编码(来自数据字典, 用户自定义业务场景 一个场景可以有多个模板)
+ */
+ private String bizCode;
+ /**
+ * 编码
+ */
+ private String code;
+
+ /**
+ * 实际渠道模板唯一标识
+ */
+ private String apiTemplateId;
+
+}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/vo/req/SmsChannelCreateReqVO.java b/src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/vo/req/SmsChannelCreateReqVO.java
new file mode 100644
index 000000000..729088b65
--- /dev/null
+++ b/src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/vo/req/SmsChannelCreateReqVO.java
@@ -0,0 +1,44 @@
+package cn.iocoder.dashboard.modules.msg.controller.sms.vo.req;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+
+@ApiModel("消息渠道创建 Request VO")
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@EqualsAndHashCode
+public class SmsChannelCreateReqVO implements Serializable {
+
+ @ApiModelProperty("编码(来自枚举类 阿里、华为、七牛等)")
+ private String code;
+
+ @ApiModelProperty("渠道账号id")
+ private String apiKey;
+
+ @ApiModelProperty("渠道账号秘钥")
+ private String apiSecret;
+
+ @ApiModelProperty("优先级(存在多个签名时,选择值最小的,渠道不可用时,按优先级从小到大切换)")
+ private Integer priority;
+
+ @ApiModelProperty("名称")
+ private String name;
+
+ @ApiModelProperty("签名值")
+ private String signature;
+
+ @ApiModelProperty("备注")
+ private String remark;
+
+ @ApiModelProperty("启用状态(0正常 1停用)")
+ private Integer status;
+
+}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/vo/req/SmsChannelPageReqVO.java b/src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/vo/req/SmsChannelPageReqVO.java
new file mode 100644
index 000000000..dd2df146e
--- /dev/null
+++ b/src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/vo/req/SmsChannelPageReqVO.java
@@ -0,0 +1,29 @@
+package cn.iocoder.dashboard.modules.msg.controller.sms.vo.req;
+
+import cn.iocoder.dashboard.common.pojo.PageParam;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.util.Date;
+
+import static cn.iocoder.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@ApiModel("消息渠道分页 Request VO")
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class SmsChannelPageReqVO extends PageParam {
+
+ @ApiModelProperty(value = "渠道名", example = "阿里", notes = "模糊匹配")
+ private String name;
+
+ @ApiModelProperty(value = "签名值", example = "源码", notes = "模糊匹配")
+ private String signature;
+
+}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/vo/resp/SmsChannelEnumRespVO.java b/src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/vo/resp/SmsChannelEnumRespVO.java
new file mode 100644
index 000000000..a3e56e0ca
--- /dev/null
+++ b/src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/vo/resp/SmsChannelEnumRespVO.java
@@ -0,0 +1,21 @@
+package cn.iocoder.dashboard.modules.msg.controller.sms.vo.resp;
+
+import io.swagger.annotations.ApiModel;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+
+@ApiModel("用户分页 Request VO")
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode
+public class SmsChannelEnumRespVO implements Serializable {
+
+ private String code;
+
+ private String name;
+
+}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/vo/resp/SmsChannelPageRespVO.java b/src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/vo/resp/SmsChannelPageRespVO.java
new file mode 100644
index 000000000..603f13e07
--- /dev/null
+++ b/src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/vo/resp/SmsChannelPageRespVO.java
@@ -0,0 +1,43 @@
+package cn.iocoder.dashboard.modules.msg.controller.sms.vo.resp;
+
+import cn.iocoder.dashboard.common.pojo.PageParam;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.util.Date;
+
+import static cn.iocoder.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@ApiModel("用户分页 Request VO")
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class SmsChannelPageRespVO extends PageParam {
+
+ @ApiModelProperty(value = "用户账号", example = "yudao", notes = "模糊匹配")
+ private String username;
+
+ @ApiModelProperty(value = "手机号码", example = "yudao", notes = "模糊匹配")
+ private String mobile;
+
+ @ApiModelProperty(value = "展示状态", example = "1", notes = "参见 SysCommonStatusEnum 枚举类")
+ private Integer status;
+
+ @ApiModelProperty(value = "开始时间", example = "2020-10-24")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private Date beginTime;
+
+ @ApiModelProperty(value = "结束时间", example = "2020-10-24")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private Date endTime;
+
+ @ApiModelProperty(value = "部门编号", example = "1024", notes = "同时筛选子部门")
+ private Long deptId;
+
+}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/msg/convert/sms/SmsChannelConvert.java b/src/main/java/cn/iocoder/dashboard/modules/msg/convert/sms/SmsChannelConvert.java
new file mode 100644
index 000000000..4728586a3
--- /dev/null
+++ b/src/main/java/cn/iocoder/dashboard/modules/msg/convert/sms/SmsChannelConvert.java
@@ -0,0 +1,34 @@
+package cn.iocoder.dashboard.modules.msg.convert.sms;
+
+import cn.iocoder.dashboard.common.enums.SmsChannelEnum;
+import cn.iocoder.dashboard.common.pojo.PageResult;
+import cn.iocoder.dashboard.modules.msg.controller.sms.vo.SmsChannelAllVO;
+import cn.iocoder.dashboard.modules.msg.controller.sms.vo.req.SmsChannelCreateReqVO;
+import cn.iocoder.dashboard.modules.msg.controller.sms.vo.resp.SmsChannelEnumRespVO;
+import cn.iocoder.dashboard.modules.msg.dal.mysql.daoobject.sms.SmsChannelDO;
+import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserUpdateReqVO;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+import org.mapstruct.factory.Mappers;
+
+import java.util.List;
+
+@Mapper
+public interface SmsChannelConvert {
+
+ SmsChannelConvert INSTANCE = Mappers.getMapper(SmsChannelConvert.class);
+
+ @Mapping(source = "records", target = "list")
+ PageResult convertPage(IPage page);
+
+ SmsChannelDO convert(SmsChannelCreateReqVO bean);
+
+ SmsChannelDO convert(SysUserUpdateReqVO bean);
+
+ List convertEnum(List bean);
+
+ List convert(List bean);
+
+
+}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/msg/convert/sms/SmsTemplateConvert.java b/src/main/java/cn/iocoder/dashboard/modules/msg/convert/sms/SmsTemplateConvert.java
new file mode 100644
index 000000000..313e06c92
--- /dev/null
+++ b/src/main/java/cn/iocoder/dashboard/modules/msg/convert/sms/SmsTemplateConvert.java
@@ -0,0 +1,26 @@
+package cn.iocoder.dashboard.modules.msg.convert.sms;
+
+import cn.iocoder.dashboard.common.pojo.PageResult;
+import cn.iocoder.dashboard.modules.msg.controller.sms.vo.SmsTemplateVO;
+import cn.iocoder.dashboard.modules.msg.dal.mysql.daoobject.sms.SmsChannelDO;
+import cn.iocoder.dashboard.modules.msg.dal.mysql.daoobject.sms.SmsTemplateDO;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+import org.mapstruct.factory.Mappers;
+
+import java.util.List;
+
+@Mapper
+public interface SmsTemplateConvert {
+
+ SmsTemplateConvert INSTANCE = Mappers.getMapper(SmsTemplateConvert.class);
+
+ @Mapping(source = "records", target = "list")
+ PageResult convertPage(IPage page);
+
+ List convert(List bean);
+
+ SmsTemplateVO convert(SmsTemplateDO bean);
+
+}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/msg/dal/mysql/dao/sms/SmsChannelMapper.java b/src/main/java/cn/iocoder/dashboard/modules/msg/dal/mysql/dao/sms/SmsChannelMapper.java
new file mode 100644
index 000000000..f7ede3502
--- /dev/null
+++ b/src/main/java/cn/iocoder/dashboard/modules/msg/dal/mysql/dao/sms/SmsChannelMapper.java
@@ -0,0 +1,31 @@
+package cn.iocoder.dashboard.modules.msg.dal.mysql.dao.sms;
+
+import cn.hutool.core.util.StrUtil;
+import cn.iocoder.dashboard.common.enums.CommonStatusEnum;
+import cn.iocoder.dashboard.framework.mybatis.core.util.MyBatisUtils;
+import cn.iocoder.dashboard.modules.msg.controller.sms.vo.req.SmsChannelPageReqVO;
+import cn.iocoder.dashboard.modules.msg.dal.mysql.daoobject.sms.SmsChannelDO;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+@Mapper
+public interface SmsChannelMapper extends BaseMapper {
+
+ default IPage selectChannelPage(SmsChannelPageReqVO reqVO) {
+ return selectPage(MyBatisUtils.buildPage(reqVO), new LambdaQueryWrapper()
+ .like(StrUtil.isNotBlank(reqVO.getName()), SmsChannelDO::getName, reqVO.getName())
+ .like(StrUtil.isNotBlank(reqVO.getSignature()), SmsChannelDO::getName, reqVO.getSignature())
+ );
+ }
+
+ default List selectEnabledList() {
+ return selectList(new LambdaQueryWrapper()
+ .eq(SmsChannelDO::getStatus, CommonStatusEnum.ENABLE.getStatus())
+ .orderByAsc(SmsChannelDO::getId)
+ );
+ }
+}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/msg/dal/mysql/dao/sms/SmsLogMapper.java b/src/main/java/cn/iocoder/dashboard/modules/msg/dal/mysql/dao/sms/SmsLogMapper.java
new file mode 100644
index 000000000..263783b47
--- /dev/null
+++ b/src/main/java/cn/iocoder/dashboard/modules/msg/dal/mysql/dao/sms/SmsLogMapper.java
@@ -0,0 +1,10 @@
+package cn.iocoder.dashboard.modules.msg.dal.mysql.dao.sms;
+
+import cn.iocoder.dashboard.modules.msg.dal.mysql.daoobject.sms.SmsLog;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface SmsLogMapper extends BaseMapper {
+
+}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/msg/dal/mysql/dao/sms/SmsTemplateMapper.java b/src/main/java/cn/iocoder/dashboard/modules/msg/dal/mysql/dao/sms/SmsTemplateMapper.java
new file mode 100644
index 000000000..f2d2fb21b
--- /dev/null
+++ b/src/main/java/cn/iocoder/dashboard/modules/msg/dal/mysql/dao/sms/SmsTemplateMapper.java
@@ -0,0 +1,39 @@
+package cn.iocoder.dashboard.modules.msg.dal.mysql.dao.sms;
+
+import cn.iocoder.dashboard.common.enums.CommonStatusEnum;
+import cn.iocoder.dashboard.modules.msg.dal.mysql.daoobject.sms.SmsTemplateDO;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+@Mapper
+public interface SmsTemplateMapper extends BaseMapper {
+
+ /**
+ * 根据短信渠道id查询短信模板集合
+ *
+ * @param channelId 渠道id
+ * @return 模板集合
+ */
+ default List selectListByChannelId(Long channelId) {
+ return selectList(new LambdaQueryWrapper()
+ .eq(SmsTemplateDO::getChannelId, channelId)
+ .eq(SmsTemplateDO::getStatus, CommonStatusEnum.ENABLE.getStatus())
+ .orderByAsc(SmsTemplateDO::getId)
+ );
+ }
+
+ /**
+ * 查询有效短信模板集合
+ *
+ * @return 有效短信模板集合
+ */
+ default List selectEnabledList() {
+ return selectList(new LambdaQueryWrapper()
+ .eq(SmsTemplateDO::getStatus, CommonStatusEnum.ENABLE.getStatus())
+ .orderByAsc(SmsTemplateDO::getId)
+ );
+ }
+}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/msg/dal/mysql/daoobject/sms/SmsChannelDO.java b/src/main/java/cn/iocoder/dashboard/modules/msg/dal/mysql/daoobject/sms/SmsChannelDO.java
new file mode 100644
index 000000000..3c0b5f396
--- /dev/null
+++ b/src/main/java/cn/iocoder/dashboard/modules/msg/dal/mysql/daoobject/sms/SmsChannelDO.java
@@ -0,0 +1,65 @@
+package cn.iocoder.dashboard.modules.msg.dal.mysql.daoobject.sms;
+
+import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+
+/**
+ * 短信渠道
+ *
+ * @author zzf
+ * @since 2021-01-25
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName(value = "sms_channel", autoResultMap = true)
+public class SmsChannelDO extends BaseDO {
+
+ /**
+ * 自增编号
+ */
+ private Long id;
+
+ /**
+ * 编码(来自枚举类 阿里、华为、七牛等)
+ */
+ private String code;
+
+ /**
+ * 渠道账号id
+ */
+ private String apiKey;
+
+ /**
+ * 渠道账号秘钥
+ */
+ private String apiSecret;
+
+ /**
+ * 实际渠道签名唯一标识
+ */
+ private String apiSignatureId;
+
+ /**
+ * 名称
+ */
+ private String name;
+
+ /**
+ * 签名值
+ */
+ private String signature;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+ /**
+ * 启用状态(0正常 1停用)
+ */
+ private Integer status;
+
+}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/msg/dal/mysql/daoobject/sms/SmsLog.java b/src/main/java/cn/iocoder/dashboard/modules/msg/dal/mysql/daoobject/sms/SmsLog.java
new file mode 100644
index 000000000..e5af0471e
--- /dev/null
+++ b/src/main/java/cn/iocoder/dashboard/modules/msg/dal/mysql/daoobject/sms/SmsLog.java
@@ -0,0 +1,71 @@
+package cn.iocoder.dashboard.modules.msg.dal.mysql.daoobject.sms;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 短信日志
+ *
+ * @author zzf
+ * @since 2021-01-25
+ */
+@Data
+@EqualsAndHashCode
+@TableName(value = "sms_log", autoResultMap = true)
+public class SmsLog implements Serializable {
+
+ /**
+ * 自增编号
+ */
+ private Long id;
+
+ /**
+ * 短信渠道编码(来自枚举类)
+ */
+ private String channelCode;
+
+ /**
+ * 实际渠道短信唯一标识
+ */
+ private String apiSmsId;
+
+ /**
+ * 模板id
+ */
+ private Long templateId;
+
+ /**
+ * 手机号
+ */
+ private String phone;
+
+ /**
+ * 内容
+ */
+ private String content;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+ /**
+ * 发送状态(0发送中 1成功 2失败)
+ */
+ private Integer sendStatus;
+
+ /**
+ * 创建者
+ */
+ private String createBy;
+
+ /**
+ * 创建时间
+ */
+ private Date createTime;
+
+}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/msg/dal/mysql/daoobject/sms/SmsTemplateDO.java b/src/main/java/cn/iocoder/dashboard/modules/msg/dal/mysql/daoobject/sms/SmsTemplateDO.java
new file mode 100644
index 000000000..39257a71d
--- /dev/null
+++ b/src/main/java/cn/iocoder/dashboard/modules/msg/dal/mysql/daoobject/sms/SmsTemplateDO.java
@@ -0,0 +1,81 @@
+package cn.iocoder.dashboard.modules.msg.dal.mysql.daoobject.sms;
+
+import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.Date;
+
+/**
+ * 短信模板
+ *
+ * @author zzf
+ * @since 2021-01-25
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName(value = "sms_template", autoResultMap = true)
+public class SmsTemplateDO extends BaseDO {
+
+ /**
+ * 自增编号
+ */
+ private Long id;
+
+ /**
+ * 短信渠道编码(来自枚举类)
+ */
+ private String channelCode;
+
+ /**
+ * 短信渠道id (对于前端来说就是绑定一个签名)
+ */
+ private Long channelId;
+
+ /**
+ * 消息类型 [0验证码 1短信通知 2推广短信 3国际/港澳台消息]
+ */
+ private Integer type;
+
+ /**
+ * 业务编码(来自数据字典, 用户自定义业务场景 一个场景可以有多个模板)
+ */
+ private String bizCode;
+
+ /**
+ * 编码
+ */
+ private String code;
+
+ /**
+ * 名称
+ */
+ private String name;
+
+ /**
+ * 实际渠道模板唯一标识
+ */
+ private String apiTemplateId;
+
+ /**
+ * 内容
+ */
+ private String content;
+
+ /**
+ * 参数数组(自动根据内容生成)
+ */
+ private String params;
+
+ /**
+ * 备注
+ */
+ private String remark;
+
+ /**
+ * 启用状态(0正常 1停用)
+ */
+ private Integer status;
+
+}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/msg/package-info.java b/src/main/java/cn/iocoder/dashboard/modules/msg/package-info.java
new file mode 100644
index 000000000..3a0e7635c
--- /dev/null
+++ b/src/main/java/cn/iocoder/dashboard/modules/msg/package-info.java
@@ -0,0 +1,6 @@
+/**
+ * msg 包,专门专门用于发送消息的功能,支撑上层的通用与核心业务。
+ * 例如说:短信、邮件、app通知等等
+ *
+ */
+package cn.iocoder.dashboard.modules.msg;
diff --git a/src/main/java/cn/iocoder/dashboard/modules/msg/service/sms/SmsChannelService.java b/src/main/java/cn/iocoder/dashboard/modules/msg/service/sms/SmsChannelService.java
new file mode 100644
index 000000000..ed2c047e8
--- /dev/null
+++ b/src/main/java/cn/iocoder/dashboard/modules/msg/service/sms/SmsChannelService.java
@@ -0,0 +1,34 @@
+package cn.iocoder.dashboard.modules.msg.service.sms;
+
+import cn.iocoder.dashboard.common.pojo.PageResult;
+import cn.iocoder.dashboard.modules.msg.controller.sms.vo.SmsChannelAllVO;
+import cn.iocoder.dashboard.modules.msg.controller.sms.vo.req.SmsChannelCreateReqVO;
+import cn.iocoder.dashboard.modules.msg.controller.sms.vo.req.SmsChannelPageReqVO;
+import cn.iocoder.dashboard.modules.msg.controller.sms.vo.resp.SmsChannelEnumRespVO;
+import cn.iocoder.dashboard.modules.msg.dal.mysql.daoobject.sms.SmsChannelDO;
+
+import java.util.List;
+
+/**
+ * 短信渠道Service接口
+ *
+ * @author zzf
+ * @date 2021/1/25 9:24
+ */
+public interface SmsChannelService {
+
+ PageResult pageChannels(SmsChannelPageReqVO reqVO);
+
+ Long createChannel(SmsChannelCreateReqVO reqVO);
+
+ List getChannelEnums();
+
+ /**
+ * 查询渠道(包含名下模块)信息集合
+ *
+ * @return 渠道(包含名下模块)信息集合
+ */
+ List listChannelAllEnabledInfo();
+
+ boolean flushChannel();
+}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/msg/service/sms/SmsLogService.java b/src/main/java/cn/iocoder/dashboard/modules/msg/service/sms/SmsLogService.java
new file mode 100644
index 000000000..70f4d9eeb
--- /dev/null
+++ b/src/main/java/cn/iocoder/dashboard/modules/msg/service/sms/SmsLogService.java
@@ -0,0 +1,10 @@
+package cn.iocoder.dashboard.modules.msg.service.sms;
+
+/**
+ * 短信渠道Service接口
+ *
+ * @author zzf
+ * @date 2021/1/25 9:24
+ */
+public interface SmsLogService {
+}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/msg/service/sms/SmsTemplateService.java b/src/main/java/cn/iocoder/dashboard/modules/msg/service/sms/SmsTemplateService.java
new file mode 100644
index 000000000..2c1364934
--- /dev/null
+++ b/src/main/java/cn/iocoder/dashboard/modules/msg/service/sms/SmsTemplateService.java
@@ -0,0 +1,10 @@
+package cn.iocoder.dashboard.modules.msg.service.sms;
+
+/**
+ * 短信渠道Service接口
+ *
+ * @author zzf
+ * @date 2021/1/25 9:24
+ */
+public interface SmsTemplateService {
+}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/msg/service/sms/impl/SmsChannelServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/msg/service/sms/impl/SmsChannelServiceImpl.java
new file mode 100644
index 000000000..e5202f491
--- /dev/null
+++ b/src/main/java/cn/iocoder/dashboard/modules/msg/service/sms/impl/SmsChannelServiceImpl.java
@@ -0,0 +1,88 @@
+package cn.iocoder.dashboard.modules.msg.service.sms.impl;
+
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.extra.spring.SpringUtil;
+import cn.iocoder.dashboard.common.enums.SmsChannelEnum;
+import cn.iocoder.dashboard.common.pojo.PageResult;
+import cn.iocoder.dashboard.framework.msg.sms.factory.AbstractSmsSenderFactory;
+import cn.iocoder.dashboard.modules.msg.controller.sms.vo.SmsChannelAllVO;
+import cn.iocoder.dashboard.modules.msg.controller.sms.vo.req.SmsChannelCreateReqVO;
+import cn.iocoder.dashboard.modules.msg.controller.sms.vo.req.SmsChannelPageReqVO;
+import cn.iocoder.dashboard.modules.msg.controller.sms.vo.resp.SmsChannelEnumRespVO;
+import cn.iocoder.dashboard.modules.msg.convert.sms.SmsChannelConvert;
+import cn.iocoder.dashboard.modules.msg.convert.sms.SmsTemplateConvert;
+import cn.iocoder.dashboard.modules.msg.dal.mysql.dao.sms.SmsChannelMapper;
+import cn.iocoder.dashboard.modules.msg.dal.mysql.dao.sms.SmsTemplateMapper;
+import cn.iocoder.dashboard.modules.msg.dal.mysql.daoobject.sms.SmsChannelDO;
+import cn.iocoder.dashboard.modules.msg.dal.mysql.daoobject.sms.SmsTemplateDO;
+import cn.iocoder.dashboard.modules.msg.service.sms.SmsChannelService;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * 短信渠道Service实现类
+ *
+ * @author zzf
+ * @date 2021/1/25 9:25
+ */
+@Service
+public class SmsChannelServiceImpl implements SmsChannelService {
+
+ @Resource
+ private SmsChannelMapper mapper;
+
+ @Resource
+ private SmsTemplateMapper templateMapper;
+
+ @Override
+ public PageResult pageChannels(SmsChannelPageReqVO reqVO) {
+ return SmsChannelConvert.INSTANCE.convertPage(mapper.selectChannelPage(reqVO));
+ }
+
+ @Override
+ public Long createChannel(SmsChannelCreateReqVO reqVO) {
+ SmsChannelDO channelDO = SmsChannelConvert.INSTANCE.convert(reqVO);
+ mapper.insert(channelDO);
+ return channelDO.getId();
+ }
+
+ @Override
+ public List getChannelEnums() {
+ return SmsChannelConvert.INSTANCE.convertEnum(Arrays.asList(SmsChannelEnum.values()));
+ }
+
+ @Override
+ public List listChannelAllEnabledInfo() {
+ List channelDOList = mapper.selectEnabledList();
+ if (ObjectUtil.isNull(channelDOList)) {
+ return null;
+ }
+ List channelAllVOList = SmsChannelConvert.INSTANCE.convert(channelDOList);
+
+ channelAllVOList.forEach(smsChannelDO -> {
+
+ List templateDOList = templateMapper.selectListByChannelId(smsChannelDO.getId());
+ if (ObjectUtil.isNull(templateDOList)) {
+ templateDOList = new ArrayList<>();
+ }
+ smsChannelDO.setTemplateList(SmsTemplateConvert.INSTANCE.convert(templateDOList));
+ });
+ return channelAllVOList;
+ }
+
+ @Override
+ public boolean flushChannel() {
+ AbstractSmsSenderFactory smsSenderFactory = SpringUtil.getBean(AbstractSmsSenderFactory.class);
+ if (smsSenderFactory == null) {
+ return false;
+ }
+
+ smsSenderFactory.flush(listChannelAllEnabledInfo());
+
+ return true;
+ }
+}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/msg/service/sms/impl/SmsLogServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/msg/service/sms/impl/SmsLogServiceImpl.java
new file mode 100644
index 000000000..f7e348a4d
--- /dev/null
+++ b/src/main/java/cn/iocoder/dashboard/modules/msg/service/sms/impl/SmsLogServiceImpl.java
@@ -0,0 +1,15 @@
+package cn.iocoder.dashboard.modules.msg.service.sms.impl;
+
+import cn.iocoder.dashboard.modules.msg.service.sms.SmsLogService;
+import org.springframework.stereotype.Service;
+
+/**
+ * 短信日志Service实现类
+ *
+ * @author zzf
+ * @date 2021/1/25 9:25
+ */
+@Service
+public class SmsLogServiceImpl implements SmsLogService {
+
+}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/msg/service/sms/impl/SmsTemplateServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/msg/service/sms/impl/SmsTemplateServiceImpl.java
new file mode 100644
index 000000000..caf6d8e1c
--- /dev/null
+++ b/src/main/java/cn/iocoder/dashboard/modules/msg/service/sms/impl/SmsTemplateServiceImpl.java
@@ -0,0 +1,14 @@
+package cn.iocoder.dashboard.modules.msg.service.sms.impl;
+
+import cn.iocoder.dashboard.modules.msg.service.sms.SmsTemplateService;
+import org.springframework.stereotype.Service;
+
+/**
+ * 短信模板Service实现类
+ *
+ * @author zzf
+ * @date 2021/1/25 9:25
+ */
+@Service
+public class SmsTemplateServiceImpl implements SmsTemplateService {
+}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/enums/SysErrorCodeConstants.java b/src/main/java/cn/iocoder/dashboard/modules/system/enums/SysErrorCodeConstants.java
index 1bbde5784..5aa257a97 100644
--- a/src/main/java/cn/iocoder/dashboard/modules/system/enums/SysErrorCodeConstants.java
+++ b/src/main/java/cn/iocoder/dashboard/modules/system/enums/SysErrorCodeConstants.java
@@ -75,4 +75,11 @@ public interface SysErrorCodeConstants {
// ========== 文件 1002009000 ==========
ErrorCode FILE_PATH_EXISTS = new ErrorCode(1002009001, "文件路径已经存在");
+
+ // ========== 消息 1003001000 ==========
+ ErrorCode SMS_CHANNEL_NOT_FOUND = new ErrorCode(1003001001, "没有短信渠道信息, 请初始化sms_channel表数据。");
+ ErrorCode SMS_TEMPLATE_NOT_FOUND = new ErrorCode(1003001002, "没有短信模板信息, 请初始化sms_template表数据。");
+ ErrorCode SMS_SENDER_NOT_FOUND = new ErrorCode(1003001003, "没有找到对应的短信发送对象,请检查sms_channel表和sms_template表数据");
+ ErrorCode INVALID_CHANNEL_CODE = new ErrorCode(1003001004, "非法的短信渠道code,请检查sms_channel表的code值是否与SmsChannelEnum中的code值一致。");
+
}
From 37c39365ec4e0e7a5f043943d6ea854da6f7d6f6 Mon Sep 17 00:00:00 2001
From: zengzefeng <986510453@qq.com>
Date: Thu, 28 Jan 2021 16:45:25 +0800
Subject: [PATCH 02/54] =?UTF-8?q?=E9=87=8D=E6=9E=84=E7=9F=AD=E4=BF=A1?=
=?UTF-8?q?=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
sql/ruoyi-vue-pro.sql | 12 +-
.../framework/msg/sms/SmsSender.java | 67 --------
.../msg/sms/config/SmsConfiguration.java | 48 ------
.../sms/factory/DefaultSmsSenderFactory.java | 137 -----------------
.../AbstractSmsIntercepterChain.java | 38 -----
.../DefaultSmsIntercepterChain.java | 20 ---
.../msg/sms/intercepter/SmsIntercepter.java | 41 -----
.../sms/intercepter/SmsLogIntercepter.java | 46 ------
.../msg/sms/proxy/DefaultSmsSenderProxy.java | 41 -----
.../msg/sms/proxy/SmsSenderProxy.java | 34 -----
.../framework/{msg => }/sms/SmsBody.java | 2 +-
.../dashboard/framework/sms/SmsClient.java | 107 +++++++++++++
.../framework/sms/SmsClientAdapter.java | 42 +++++
.../framework/{msg => }/sms/SmsResult.java | 2 +-
.../dashboard/modules/msg/package-info.java | 6 -
.../controller/sms/SmsChannelController.java | 12 +-
.../controller/sms/SmsTemplateController.java | 2 +-
.../controller/sms/vo/SmsChannelAllVO.java | 2 +-
.../controller/sms/vo/SmsTemplateVO.java | 2 +-
.../sms/vo/req/SmsChannelCreateReqVO.java | 2 +-
.../sms/vo/req/SmsChannelPageReqVO.java | 7 +-
.../sms/vo/resp/SmsChannelEnumRespVO.java | 2 +-
.../sms/vo/resp/SmsChannelPageRespVO.java | 2 +-
.../convert/sms/SmsChannelConvert.java | 10 +-
.../convert/sms/SmsTemplateConvert.java | 8 +-
.../dal/mysql/dao/sms/SmsChannelMapper.java | 6 +-
.../dal/mysql/dao/sms/SmsLogMapper.java | 4 +-
.../dal/mysql/dao/sms/SmsTemplateMapper.java | 4 +-
.../mysql/dataobject}/sms/SmsChannelDO.java | 2 +-
.../dal/mysql/dataobject}/sms/SmsLog.java | 2 +-
.../mysql/dataobject}/sms/SmsTemplateDO.java | 2 +-
.../system/enums/SysErrorCodeConstants.java | 10 +-
.../service/sms/SmsChannelService.java | 12 +-
.../service/sms/SmsLogService.java | 2 +-
.../service/sms/SmsTemplateService.java | 2 +-
.../sms/impl/SmsChannelServiceImpl.java | 32 ++--
.../service/sms/impl/SmsLogServiceImpl.java | 4 +-
.../sms/impl/SmsTemplateServiceImpl.java | 4 +-
.../modules/system/sms/SmsConfiguration.java | 34 +++++
.../modules/system/sms/SmsSenderUtils.java | 143 ++++++++++++++++++
.../system/sms/client/AliSmsClient.java} | 19 ++-
.../system/sms/proxy/SmsClientLogProxy.java | 48 ++++++
42 files changed, 455 insertions(+), 567 deletions(-)
delete mode 100644 src/main/java/cn/iocoder/dashboard/framework/msg/sms/SmsSender.java
delete mode 100644 src/main/java/cn/iocoder/dashboard/framework/msg/sms/config/SmsConfiguration.java
delete mode 100644 src/main/java/cn/iocoder/dashboard/framework/msg/sms/factory/DefaultSmsSenderFactory.java
delete mode 100644 src/main/java/cn/iocoder/dashboard/framework/msg/sms/intercepter/AbstractSmsIntercepterChain.java
delete mode 100644 src/main/java/cn/iocoder/dashboard/framework/msg/sms/intercepter/DefaultSmsIntercepterChain.java
delete mode 100644 src/main/java/cn/iocoder/dashboard/framework/msg/sms/intercepter/SmsIntercepter.java
delete mode 100644 src/main/java/cn/iocoder/dashboard/framework/msg/sms/intercepter/SmsLogIntercepter.java
delete mode 100644 src/main/java/cn/iocoder/dashboard/framework/msg/sms/proxy/DefaultSmsSenderProxy.java
delete mode 100644 src/main/java/cn/iocoder/dashboard/framework/msg/sms/proxy/SmsSenderProxy.java
rename src/main/java/cn/iocoder/dashboard/framework/{msg => }/sms/SmsBody.java (88%)
create mode 100644 src/main/java/cn/iocoder/dashboard/framework/sms/SmsClient.java
create mode 100644 src/main/java/cn/iocoder/dashboard/framework/sms/SmsClientAdapter.java
rename src/main/java/cn/iocoder/dashboard/framework/{msg => }/sms/SmsResult.java (87%)
delete mode 100644 src/main/java/cn/iocoder/dashboard/modules/msg/package-info.java
rename src/main/java/cn/iocoder/dashboard/modules/{msg => system}/controller/sms/SmsChannelController.java (75%)
rename src/main/java/cn/iocoder/dashboard/modules/{msg => system}/controller/sms/SmsTemplateController.java (98%)
rename src/main/java/cn/iocoder/dashboard/modules/{msg => system}/controller/sms/vo/SmsChannelAllVO.java (94%)
rename src/main/java/cn/iocoder/dashboard/modules/{msg => system}/controller/sms/vo/SmsTemplateVO.java (88%)
rename src/main/java/cn/iocoder/dashboard/modules/{msg => system}/controller/sms/vo/req/SmsChannelCreateReqVO.java (94%)
rename src/main/java/cn/iocoder/dashboard/modules/{msg => system}/controller/sms/vo/req/SmsChannelPageReqVO.java (73%)
rename src/main/java/cn/iocoder/dashboard/modules/{msg => system}/controller/sms/vo/resp/SmsChannelEnumRespVO.java (83%)
rename src/main/java/cn/iocoder/dashboard/modules/{msg => system}/controller/sms/vo/resp/SmsChannelPageRespVO.java (95%)
rename src/main/java/cn/iocoder/dashboard/modules/{msg => system}/convert/sms/SmsChannelConvert.java (68%)
rename src/main/java/cn/iocoder/dashboard/modules/{msg => system}/convert/sms/SmsTemplateConvert.java (66%)
rename src/main/java/cn/iocoder/dashboard/modules/{msg => system}/dal/mysql/dao/sms/SmsChannelMapper.java (83%)
rename src/main/java/cn/iocoder/dashboard/modules/{msg => system}/dal/mysql/dao/sms/SmsLogMapper.java (55%)
rename src/main/java/cn/iocoder/dashboard/modules/{msg => system}/dal/mysql/dao/sms/SmsTemplateMapper.java (89%)
rename src/main/java/cn/iocoder/dashboard/modules/{msg/dal/mysql/daoobject => system/dal/mysql/dataobject}/sms/SmsChannelDO.java (93%)
rename src/main/java/cn/iocoder/dashboard/modules/{msg/dal/mysql/daoobject => system/dal/mysql/dataobject}/sms/SmsLog.java (93%)
rename src/main/java/cn/iocoder/dashboard/modules/{msg/dal/mysql/daoobject => system/dal/mysql/dataobject}/sms/SmsTemplateDO.java (95%)
rename src/main/java/cn/iocoder/dashboard/modules/{msg => system}/service/sms/SmsChannelService.java (55%)
rename src/main/java/cn/iocoder/dashboard/modules/{msg => system}/service/sms/SmsLogService.java (66%)
rename src/main/java/cn/iocoder/dashboard/modules/{msg => system}/service/sms/SmsTemplateService.java (67%)
rename src/main/java/cn/iocoder/dashboard/modules/{msg => system}/service/sms/impl/SmsChannelServiceImpl.java (61%)
rename src/main/java/cn/iocoder/dashboard/modules/{msg => system}/service/sms/impl/SmsLogServiceImpl.java (60%)
rename src/main/java/cn/iocoder/dashboard/modules/{msg => system}/service/sms/impl/SmsTemplateServiceImpl.java (60%)
create mode 100644 src/main/java/cn/iocoder/dashboard/modules/system/sms/SmsConfiguration.java
create mode 100644 src/main/java/cn/iocoder/dashboard/modules/system/sms/SmsSenderUtils.java
rename src/main/java/cn/iocoder/dashboard/{framework/msg/sms/impl/ali/AliSmsSender.java => modules/system/sms/client/AliSmsClient.java} (81%)
create mode 100644 src/main/java/cn/iocoder/dashboard/modules/system/sms/proxy/SmsClientLogProxy.java
diff --git a/sql/ruoyi-vue-pro.sql b/sql/ruoyi-vue-pro.sql
index edba4204c..9355fab64 100644
--- a/sql/ruoyi-vue-pro.sql
+++ b/sql/ruoyi-vue-pro.sql
@@ -892,9 +892,8 @@ DROP TABLE IF EXISTS `sms_channel`;
CREATE TABLE `sms_channel` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增编号',
`code` varchar(50) not null COMMENT '编码(来自枚举类 阿里、华为、七牛等)',
- `api_key` varchar(100) NOT NULL COMMENT '账号id', -- add
- `api_secret` varchar(100) NOT NULL COMMENT '账号秘钥', -- add
- `priority` tinyint(8) NOT NULL default 1 COMMENT '优先级(存在多个签名时,选择值最小的,渠道不可用时,按优先级从小到大切换)', -- add
+ `api_key` varchar(100) NOT NULL COMMENT '账号id',
+ `api_secret` varchar(100) NOT NULL COMMENT '账号秘钥',
`api_signature_id` varchar(100) NOT NULL COMMENT '实际渠道签名唯一标识',
`name` varchar(50) not null COMMENT '名称',
`signature` varchar(50) not null COMMENT '签名值',
@@ -919,15 +918,14 @@ DROP TABLE IF EXISTS `sms_template`;
CREATE TABLE `sms_template` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增编号',
`channel_code` varchar(50) not null COMMENT '短信渠道编码(来自枚举类)',
- `channel_id` bigint(20) not null COMMENT '短信渠道id (对于前端来说就是绑定一个签名)', -- add
+ `channel_id` bigint(20) not null COMMENT '短信渠道id (对于前端来说就是绑定一个签名)',
`type` tinyint(4) NOT NULL default 1 COMMENT '消息类型 [0验证码 1短信通知 2推广短信 3国际/港澳台消息]',
- `biz_code` varchar(50) not null COMMENT '业务编码(来自数据字典, 用户自定义业务场景 一个场景可以有多个模板)', -- add
- `priority` tinyint(8) NOT NULL default 1 COMMENT '优先级(默认直接继承渠道表的,逻辑也与渠道表的一致,可以针对每个biz_code进行修改)',-- add
+ `biz_code` varchar(50) not null COMMENT '业务编码(来自数据字典, 用户自定义业务场景 一个场景可以有多个模板)',
`code` varchar(50) not null COMMENT '编码',
`name` varchar(50) not null COMMENT '名称',
`api_template_id` varchar(100) NOT NULL COMMENT '实际渠道模板唯一标识',
`content` varchar(1000) NOT NULL DEFAULT '' COMMENT '内容',
- `params` varchar(200) NOT NULL DEFAULT '' COMMENT '参数数组(自动根据内容生成)', -- add
+ `params` varchar(200) NOT NULL DEFAULT '' COMMENT '参数数组(自动根据内容生成)',
`remark` varchar(200) NOT NULL COMMENT '备注',
`status` tinyint(4) NOT NULL default 0 COMMENT '启用状态(0正常 1停用)',
diff --git a/src/main/java/cn/iocoder/dashboard/framework/msg/sms/SmsSender.java b/src/main/java/cn/iocoder/dashboard/framework/msg/sms/SmsSender.java
deleted file mode 100644
index 30b10df61..000000000
--- a/src/main/java/cn/iocoder/dashboard/framework/msg/sms/SmsSender.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package cn.iocoder.dashboard.framework.msg.sms;
-
-import org.apache.commons.lang3.StringUtils;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-
-/**
- * 短信父接口
- *
- * @author zzf
- * @date 2021/1/25 14:14
- */
-public interface SmsSender {
-
- /**
- * 发送通知
- *
- * @param msgBody 通知内容
- * @param targets 发送对象列表
- * @return 是否发送成功
- */
- SmsResult send(SmsBody msgBody, Collection targets);
-
- /**
- * 发送通知
- *
- * @param msgBody 通知内容
- * @param target 发送对象列表
- * @return 是否发送成功
- */
- default SmsResult send(SmsBody msgBody, String target) {
- if (StringUtils.isBlank(target)) {
- return failResult();
- }
-
- return send(msgBody, Collections.singletonList(target));
- }
-
- /**
- * 发送通知
- *
- * @param msgBody 通知内容
- * @param targets 发送对象列表
- * @return 是否发送成功
- */
- default SmsResult send(SmsBody msgBody, String... targets) {
- if (targets == null) {
- return failResult();
- }
-
- return send(msgBody, Arrays.asList(targets));
- }
-
- default SmsResult failResult() {
- SmsResult resultBody = new SmsResult<>();
- resultBody.setSuccess(false);
- return resultBody;
- }
-
- default SmsResult failResult(String message) {
- SmsResult resultBody = failResult();
- resultBody.setMessage(message);
- return resultBody;
- }
-}
\ No newline at end of file
diff --git a/src/main/java/cn/iocoder/dashboard/framework/msg/sms/config/SmsConfiguration.java b/src/main/java/cn/iocoder/dashboard/framework/msg/sms/config/SmsConfiguration.java
deleted file mode 100644
index 7b5b26a5b..000000000
--- a/src/main/java/cn/iocoder/dashboard/framework/msg/sms/config/SmsConfiguration.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package cn.iocoder.dashboard.framework.msg.sms.config;
-
-import cn.iocoder.dashboard.framework.msg.sms.factory.DefaultSmsSenderFactory;
-import cn.iocoder.dashboard.framework.msg.sms.intercepter.AbstractSmsIntercepterChain;
-import cn.iocoder.dashboard.framework.msg.sms.intercepter.DefaultSmsIntercepterChain;
-import cn.iocoder.dashboard.framework.msg.sms.intercepter.SmsLogIntercepter;
-import cn.iocoder.dashboard.modules.msg.controller.sms.vo.SmsChannelAllVO;
-import cn.iocoder.dashboard.modules.msg.service.sms.SmsChannelService;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-import javax.annotation.Resource;
-import java.util.List;
-
-/**
- * 短信服务配置
- *
- * @author guer
- */
-@Configuration
-@ConditionalOnProperty("sms.enabled")
-public class SmsConfiguration {
-
- @Resource
- private SmsChannelService channelService;
-
-
- @Bean
- public AbstractSmsIntercepterChain smsIntercepterChain() {
- DefaultSmsIntercepterChain intercepterChain = new DefaultSmsIntercepterChain();
- //添加拦截器
- intercepterChain.addSmsIntercepter(new SmsLogIntercepter());
- return intercepterChain;
- }
-
- @Bean
- public DefaultSmsSenderFactory smsSenderFactory(AbstractSmsIntercepterChain intercepterChain) {
- DefaultSmsSenderFactory defaultSmsSenderFactory = new DefaultSmsSenderFactory();
- List smsChannelAllVOList = channelService.listChannelAllEnabledInfo();
- //初始化渠道、模板信息
- defaultSmsSenderFactory.init(smsChannelAllVOList);
- //注入拦截器链
- defaultSmsSenderFactory.setIntercepterChain(intercepterChain);
- return defaultSmsSenderFactory;
- }
-
-}
diff --git a/src/main/java/cn/iocoder/dashboard/framework/msg/sms/factory/DefaultSmsSenderFactory.java b/src/main/java/cn/iocoder/dashboard/framework/msg/sms/factory/DefaultSmsSenderFactory.java
deleted file mode 100644
index 123943a3d..000000000
--- a/src/main/java/cn/iocoder/dashboard/framework/msg/sms/factory/DefaultSmsSenderFactory.java
+++ /dev/null
@@ -1,137 +0,0 @@
-package cn.iocoder.dashboard.framework.msg.sms.factory;
-
-import cn.hutool.core.util.ObjectUtil;
-import cn.iocoder.dashboard.common.enums.SmsChannelEnum;
-import cn.iocoder.dashboard.common.exception.ServiceException;
-import cn.iocoder.dashboard.framework.msg.sms.SmsSender;
-import cn.iocoder.dashboard.framework.msg.sms.impl.ali.AliSmsSender;
-import cn.iocoder.dashboard.framework.msg.sms.intercepter.AbstractSmsIntercepterChain;
-import cn.iocoder.dashboard.framework.msg.sms.proxy.DefaultSmsSenderProxy;
-import cn.iocoder.dashboard.modules.msg.controller.sms.vo.SmsChannelAllVO;
-import cn.iocoder.dashboard.modules.msg.controller.sms.vo.SmsTemplateVO;
-import lombok.Setter;
-
-import java.util.List;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReadWriteLock;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-
-import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.*;
-
-/**
- * 短信发送者工厂
- *
- * @author zzf
- * @date 2021/1/25 16:18
- */
-public class DefaultSmsSenderFactory {
-
- /**
- * sender索引
- * key: {@link SmsTemplateVO#getBizCode()}
- * value: {@link SmsSender}
- */
- private final ConcurrentHashMap> bizCode2SenderMap = new ConcurrentHashMap<>(8);
-
- /**
- * sender索引
- * key: {@link SmsTemplateVO#getCode()}
- * value: {@link SmsSender}
- */
- private final ConcurrentHashMap> templateCode2SenderMap = new ConcurrentHashMap<>(8);
-
-
- @Setter
- private AbstractSmsIntercepterChain intercepterChain;
-
- /**
- * 读写锁
- */
- private final ReadWriteLock lock = new ReentrantReadWriteLock();
- private final Lock readLock = lock.readLock();
- private final Lock writeLock = lock.writeLock();
-
-
- public void init(List smsChannelAllVOList) {
- if (ObjectUtil.isEmpty(smsChannelAllVOList)) {
- throw new ServiceException(SMS_CHANNEL_NOT_FOUND);
- }
- try {
- writeLock.lock();
- addSender(smsChannelAllVOList);
- } finally {
- writeLock.unlock();
- }
- }
-
- public SmsSender> getSenderByBizCode(String bizCode) {
- return getSmsSender(bizCode, bizCode2SenderMap);
- }
-
- public SmsSender> getSenderByTemplateCode(String templateCode) {
- return getSmsSender(templateCode, templateCode2SenderMap);
- }
-
- private SmsSender> getSmsSender(String templateCode, ConcurrentHashMap> cacheMap) {
- try {
- readLock.lock();
- SmsSender> smsSender = cacheMap.get(templateCode);
- if (smsSender == null) {
- throw new ServiceException(SMS_SENDER_NOT_FOUND);
- }
- return smsSender;
- } finally {
- readLock.unlock();
- }
- }
-
- public void flush(List smsChannelAllVOList) {
- try {
- writeLock.lock();
- bizCode2SenderMap.clear();
- templateCode2SenderMap.clear();
- addSender(smsChannelAllVOList);
- } finally {
- writeLock.unlock();
- }
- }
-
-
- private void addSender(List smsChannelAllVOList) {
- smsChannelAllVOList.forEach(channelAllVO -> addSender(SmsChannelEnum.getByCode(channelAllVO.getCode()), channelAllVO));
- }
-
- private void addSender(SmsChannelEnum channelEnum, SmsChannelAllVO channelAllVO) {
- if (channelEnum == null) {
- throw new ServiceException(INVALID_CHANNEL_CODE);
- }
- List templateList = channelAllVO.getTemplateList();
- if (ObjectUtil.isEmpty(templateList)) {
- throw new ServiceException(SMS_TEMPLATE_NOT_FOUND);
- }
-
- SmsSender> aliSmsSender = getSender(channelEnum, channelAllVO);
-
-
- templateList.forEach(smsTemplateVO -> {
- bizCode2SenderMap.put(smsTemplateVO.getBizCode(), aliSmsSender);
- templateCode2SenderMap.put(smsTemplateVO.getCode(), aliSmsSender);
- });
- }
-
- private SmsSender> getSender(SmsChannelEnum channelEnum, SmsChannelAllVO channelAllVO) {
- switch (channelEnum) {
- case ALI:
- return new DefaultSmsSenderProxy<>(new AliSmsSender(channelAllVO), intercepterChain);
- // TODO fill more channel
- default:
- break;
- }
- throw new ServiceException(SMS_SENDER_NOT_FOUND);
- }
-
-
-
-
-}
diff --git a/src/main/java/cn/iocoder/dashboard/framework/msg/sms/intercepter/AbstractSmsIntercepterChain.java b/src/main/java/cn/iocoder/dashboard/framework/msg/sms/intercepter/AbstractSmsIntercepterChain.java
deleted file mode 100644
index f95de7128..000000000
--- a/src/main/java/cn/iocoder/dashboard/framework/msg/sms/intercepter/AbstractSmsIntercepterChain.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package cn.iocoder.dashboard.framework.msg.sms.intercepter;
-
-import lombok.Getter;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * 消息父接口
- *
- * @author zzf
- * @date 2021/1/22 15:46
- */
-public abstract class AbstractSmsIntercepterChain {
-
- @Getter
- protected final List intercepterList = new ArrayList<>(8);
-
-
- /**
- * 添加短信拦截器
- *
- * @param smsIntercepter 短信拦截器
- */
- public void addSmsIntercepter(SmsIntercepter smsIntercepter) {
- addSmsIntercepter(Collections.singletonList(smsIntercepter));
- }
-
- /**
- * 添加短信拦截器
- *
- * @param smsIntercepterList 短信拦截器数组
- */
- abstract void addSmsIntercepter(List smsIntercepterList);
-
-
-}
diff --git a/src/main/java/cn/iocoder/dashboard/framework/msg/sms/intercepter/DefaultSmsIntercepterChain.java b/src/main/java/cn/iocoder/dashboard/framework/msg/sms/intercepter/DefaultSmsIntercepterChain.java
deleted file mode 100644
index 76d31906d..000000000
--- a/src/main/java/cn/iocoder/dashboard/framework/msg/sms/intercepter/DefaultSmsIntercepterChain.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package cn.iocoder.dashboard.framework.msg.sms.intercepter;
-
-import java.util.Comparator;
-import java.util.List;
-
-/**
- * 消息父接口
- *
- * @author zzf
- * @date 2021/1/22 15:46
- */
-public class DefaultSmsIntercepterChain extends AbstractSmsIntercepterChain {
-
- @Override
- public void addSmsIntercepter(List smsIntercepterList) {
- intercepterList.addAll(smsIntercepterList);
- //排序
- intercepterList.sort(Comparator.comparingInt(SmsIntercepter::getOrder));
- }
-}
diff --git a/src/main/java/cn/iocoder/dashboard/framework/msg/sms/intercepter/SmsIntercepter.java b/src/main/java/cn/iocoder/dashboard/framework/msg/sms/intercepter/SmsIntercepter.java
deleted file mode 100644
index df83c8d6a..000000000
--- a/src/main/java/cn/iocoder/dashboard/framework/msg/sms/intercepter/SmsIntercepter.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package cn.iocoder.dashboard.framework.msg.sms.intercepter;
-
-import cn.iocoder.dashboard.framework.msg.sms.SmsBody;
-import cn.iocoder.dashboard.framework.msg.sms.SmsResult;
-
-import java.util.Collection;
-
-/**
- * 消息父接口
- *
- * @author zzf
- * @date 2021/1/22 15:46
- */
-public interface SmsIntercepter {
-
- /**
- * 监听发送前
- *
- * @param msgBody 消息体
- * @param targets 发送对象数组
- */
- void beforeSender(SmsBody msgBody, Collection targets);
-
- /**
- * 监听发送后
- *
- * @param msgBody 消息体
- * @param targets 发送对象数组
- * @param resultBody 返回对象
- */
- void afterSender(SmsBody msgBody, Collection targets, SmsResult resultBody);
-
- /**
- * 排序值,拦截器根据order值顺序执行
- *
- * 值越小,越早执行
- *
- * @return 排序值
- */
- int getOrder();
-}
diff --git a/src/main/java/cn/iocoder/dashboard/framework/msg/sms/intercepter/SmsLogIntercepter.java b/src/main/java/cn/iocoder/dashboard/framework/msg/sms/intercepter/SmsLogIntercepter.java
deleted file mode 100644
index 9a7effd95..000000000
--- a/src/main/java/cn/iocoder/dashboard/framework/msg/sms/intercepter/SmsLogIntercepter.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package cn.iocoder.dashboard.framework.msg.sms.intercepter;
-
-import cn.iocoder.dashboard.framework.msg.sms.SmsBody;
-import cn.iocoder.dashboard.framework.msg.sms.SmsResult;
-import cn.iocoder.dashboard.modules.msg.dal.mysql.dao.sms.SmsLogMapper;
-import cn.iocoder.dashboard.util.json.JsonUtils;
-import lombok.Setter;
-import lombok.extern.slf4j.Slf4j;
-
-import java.util.Collection;
-
-/**
- * 短信日志拦截器
- *
- * @author zzf
- * @date 2021/1/22 15:46
- */
-@Slf4j
-public class SmsLogIntercepter implements SmsIntercepter {
-
-
- @Override
- public void beforeSender(SmsBody msgBody, Collection targets) {
- log.debug("ready send sms, body: {}, target: {}", JsonUtils.toJsonString(msgBody), targets);
-
- }
-
- @Override
- public void afterSender(SmsBody msgBody, Collection targets, SmsResult resultBody) {
- if (resultBody.getSuccess()) {
- //
- } else {
- log.warn("send sms fail, body: {}, target: {}, resultBody: {}",
- JsonUtils.toJsonString(msgBody),
- targets,
- JsonUtils.toJsonString(resultBody)
- );
- }
-
- }
-
- @Override
- public int getOrder() {
- return 0;
- }
-}
diff --git a/src/main/java/cn/iocoder/dashboard/framework/msg/sms/proxy/DefaultSmsSenderProxy.java b/src/main/java/cn/iocoder/dashboard/framework/msg/sms/proxy/DefaultSmsSenderProxy.java
deleted file mode 100644
index f9d7e566f..000000000
--- a/src/main/java/cn/iocoder/dashboard/framework/msg/sms/proxy/DefaultSmsSenderProxy.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package cn.iocoder.dashboard.framework.msg.sms.proxy;
-
-import cn.hutool.core.util.ObjectUtil;
-import cn.iocoder.dashboard.framework.msg.sms.SmsBody;
-import cn.iocoder.dashboard.framework.msg.sms.SmsResult;
-import cn.iocoder.dashboard.framework.msg.sms.SmsSender;
-import cn.iocoder.dashboard.framework.msg.sms.intercepter.AbstractSmsIntercepterChain;
-
-import java.util.Collection;
-
-/**
- * 消息父接口
- *
- * @author zzf
- * @date 2021/1/22 15:46
- */
-public class DefaultSmsSenderProxy implements SmsSender {
-
- private final SmsSender smsSender;
- private final AbstractSmsIntercepterChain chain;
-
- @Override
- public SmsResult send(SmsBody msgBody, Collection targets) {
- if (ObjectUtil.isNotNull(chain) && ObjectUtil.isNotEmpty(chain.getIntercepterList())) {
- chain.getIntercepterList().forEach(s -> s.beforeSender(msgBody, targets));
- }
-
- SmsResult resultBody = smsSender.send(msgBody, targets);
-
- if (ObjectUtil.isNotNull(chain) && ObjectUtil.isNotEmpty(chain.getIntercepterList())) {
- chain.getIntercepterList().forEach(s -> s.afterSender(msgBody, targets, resultBody));
- }
- return resultBody;
- }
-
- public DefaultSmsSenderProxy(SmsSender smsSender,
- AbstractSmsIntercepterChain chain) {
- this.smsSender = smsSender;
- this.chain = chain;
- }
-}
diff --git a/src/main/java/cn/iocoder/dashboard/framework/msg/sms/proxy/SmsSenderProxy.java b/src/main/java/cn/iocoder/dashboard/framework/msg/sms/proxy/SmsSenderProxy.java
deleted file mode 100644
index 069916e2a..000000000
--- a/src/main/java/cn/iocoder/dashboard/framework/msg/sms/proxy/SmsSenderProxy.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package cn.iocoder.dashboard.framework.msg.sms.proxy;
-
-import cn.iocoder.dashboard.framework.msg.sms.SmsSender;
-import cn.iocoder.dashboard.framework.msg.sms.intercepter.SmsIntercepter;
-
-import java.util.Collections;
-import java.util.List;
-
-/**
- * 消息父接口
- *
- * @author zzf
- * @date 2021/1/22 15:46
- */
-public interface SmsSenderProxy extends SmsSender {
-
- /**
- * 添加短信拦截器
- *
- * @param smsIntercepter 短信拦截器
- */
- default void addSmsIntercepter(SmsIntercepter smsIntercepter) {
- addSmsIntercepter(Collections.singletonList(smsIntercepter));
- }
-
- /**
- * 添加短信拦截器
- *
- * @param smsIntercepterList 短信拦截器数组
- */
- void addSmsIntercepter(List smsIntercepterList);
-
-
-}
diff --git a/src/main/java/cn/iocoder/dashboard/framework/msg/sms/SmsBody.java b/src/main/java/cn/iocoder/dashboard/framework/sms/SmsBody.java
similarity index 88%
rename from src/main/java/cn/iocoder/dashboard/framework/msg/sms/SmsBody.java
rename to src/main/java/cn/iocoder/dashboard/framework/sms/SmsBody.java
index 693838d4a..48fb2253b 100644
--- a/src/main/java/cn/iocoder/dashboard/framework/msg/sms/SmsBody.java
+++ b/src/main/java/cn/iocoder/dashboard/framework/sms/SmsBody.java
@@ -1,4 +1,4 @@
-package cn.iocoder.dashboard.framework.msg.sms;
+package cn.iocoder.dashboard.framework.sms;
import cn.iocoder.dashboard.util.json.JsonUtils;
import lombok.Data;
diff --git a/src/main/java/cn/iocoder/dashboard/framework/sms/SmsClient.java b/src/main/java/cn/iocoder/dashboard/framework/sms/SmsClient.java
new file mode 100644
index 000000000..bf1a44f57
--- /dev/null
+++ b/src/main/java/cn/iocoder/dashboard/framework/sms/SmsClient.java
@@ -0,0 +1,107 @@
+package cn.iocoder.dashboard.framework.sms;
+
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * 短信父接口
+ *
+ * @author zzf
+ * @date 2021/1/25 14:14
+ */
+public interface SmsClient {
+
+ /**
+ * 发送消息
+ *
+ * @param msgBody 消息内容
+ * @param targets 发送对象列表
+ * @return 是否发送成功
+ */
+ SmsResult send(SmsBody msgBody, Collection targets);
+
+ /**
+ * 发送消息
+ *
+ * @param msgBody 消息内容
+ * @param target 发送对象
+ * @return 是否发送成功
+ */
+ default SmsResult send(SmsBody msgBody, String target) {
+ if (StringUtils.isBlank(target)) {
+ return failResult();
+ }
+
+ return send(msgBody, Collections.singletonList(target));
+ }
+
+ /**
+ * 发送消息
+ *
+ * @param msgBody 消息内容
+ * @param targets 发送对象列表
+ * @return 是否发送成功
+ */
+ default SmsResult send(SmsBody msgBody, String... targets) {
+ if (targets == null) {
+ return failResult();
+ }
+
+ return send(msgBody, Arrays.asList(targets));
+ }
+
+
+ /**
+ * 异步发送消息
+ *
+ * @param msgBody 消息内容
+ * @param targets 发送对象列表
+ * @return 是否发送成功
+ */
+ SmsResult sendAsync(SmsBody msgBody, Collection targets);
+
+ /**
+ * 异步发送消息
+ *
+ * @param msgBody 消息内容
+ * @param target 发送对象
+ * @return 是否发送成功
+ */
+ default SmsResult sendAsync(SmsBody msgBody, String target) {
+ if (StringUtils.isBlank(target)) {
+ return failResult("target must not null.");
+ }
+
+ return sendAsync(msgBody, Collections.singletonList(target));
+ }
+
+ /**
+ * 异步发送消息
+ *
+ * @param msgBody 消息内容
+ * @param targets 发送对象列表
+ * @return 是否发送成功
+ */
+ default SmsResult sendAsync(SmsBody msgBody, String... targets) {
+ if (targets == null) {
+ return failResult("targets must not null.");
+ }
+
+ return sendAsync(msgBody, Arrays.asList(targets));
+ }
+
+ default SmsResult failResult() {
+ SmsResult resultBody = new SmsResult<>();
+ resultBody.setSuccess(false);
+ return resultBody;
+ }
+
+ default SmsResult failResult(String message) {
+ SmsResult resultBody = failResult();
+ resultBody.setMessage(message);
+ return resultBody;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/cn/iocoder/dashboard/framework/sms/SmsClientAdapter.java b/src/main/java/cn/iocoder/dashboard/framework/sms/SmsClientAdapter.java
new file mode 100644
index 000000000..6edf7646f
--- /dev/null
+++ b/src/main/java/cn/iocoder/dashboard/framework/sms/SmsClientAdapter.java
@@ -0,0 +1,42 @@
+package cn.iocoder.dashboard.framework.sms;
+
+import cn.hutool.core.util.ObjectUtil;
+import cn.iocoder.dashboard.common.exception.ServiceException;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+
+import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.SMS_CHANNEL_NOT_INIT;
+
+/**
+ * 抽象短信客户端工厂
+ *
+ * @author zzf
+ * @date 2021/1/28 14:01
+ */
+public class SmsClientAdapter {
+
+ private final Map> smsSenderMap;
+
+ public SmsClientAdapter(Map> smsSenderMap) {
+ if (ObjectUtil.isEmpty(smsSenderMap)) {
+ throw new ServiceException(SMS_CHANNEL_NOT_INIT);
+ }
+ this.smsSenderMap = smsSenderMap;
+ }
+
+ public void flushClient(Map> smsSenderMap) {
+ this.smsSenderMap.clear();
+ smsSenderMap.putAll(Collections.unmodifiableMap(smsSenderMap));
+ }
+
+ public SmsResult> send(Long channelId, SmsBody smsBody, Collection targetPhone) {
+ SmsClient> smsClient = getSmsSender(channelId);
+ return smsClient.send(smsBody, targetPhone);
+ }
+
+ private SmsClient> getSmsSender(Long channelId) {
+ return smsSenderMap.get(channelId);
+ }
+}
diff --git a/src/main/java/cn/iocoder/dashboard/framework/msg/sms/SmsResult.java b/src/main/java/cn/iocoder/dashboard/framework/sms/SmsResult.java
similarity index 87%
rename from src/main/java/cn/iocoder/dashboard/framework/msg/sms/SmsResult.java
rename to src/main/java/cn/iocoder/dashboard/framework/sms/SmsResult.java
index 8a8741839..b994514b6 100644
--- a/src/main/java/cn/iocoder/dashboard/framework/msg/sms/SmsResult.java
+++ b/src/main/java/cn/iocoder/dashboard/framework/sms/SmsResult.java
@@ -1,4 +1,4 @@
-package cn.iocoder.dashboard.framework.msg.sms;
+package cn.iocoder.dashboard.framework.sms;
import lombok.Data;
diff --git a/src/main/java/cn/iocoder/dashboard/modules/msg/package-info.java b/src/main/java/cn/iocoder/dashboard/modules/msg/package-info.java
deleted file mode 100644
index 3a0e7635c..000000000
--- a/src/main/java/cn/iocoder/dashboard/modules/msg/package-info.java
+++ /dev/null
@@ -1,6 +0,0 @@
-/**
- * msg 包,专门专门用于发送消息的功能,支撑上层的通用与核心业务。
- * 例如说:短信、邮件、app通知等等
- *
- */
-package cn.iocoder.dashboard.modules.msg;
diff --git a/src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/SmsChannelController.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SmsChannelController.java
similarity index 75%
rename from src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/SmsChannelController.java
rename to src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SmsChannelController.java
index c28d9b862..a75f9e2eb 100644
--- a/src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/SmsChannelController.java
+++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SmsChannelController.java
@@ -1,12 +1,12 @@
-package cn.iocoder.dashboard.modules.msg.controller.sms;
+package cn.iocoder.dashboard.modules.system.controller.sms;
import cn.iocoder.dashboard.common.pojo.CommonResult;
import cn.iocoder.dashboard.common.pojo.PageResult;
-import cn.iocoder.dashboard.modules.msg.controller.sms.vo.req.SmsChannelCreateReqVO;
-import cn.iocoder.dashboard.modules.msg.controller.sms.vo.req.SmsChannelPageReqVO;
-import cn.iocoder.dashboard.modules.msg.controller.sms.vo.resp.SmsChannelEnumRespVO;
-import cn.iocoder.dashboard.modules.msg.dal.mysql.daoobject.sms.SmsChannelDO;
-import cn.iocoder.dashboard.modules.msg.service.sms.SmsChannelService;
+import cn.iocoder.dashboard.modules.system.controller.sms.vo.req.SmsChannelCreateReqVO;
+import cn.iocoder.dashboard.modules.system.controller.sms.vo.req.SmsChannelPageReqVO;
+import cn.iocoder.dashboard.modules.system.controller.sms.vo.resp.SmsChannelEnumRespVO;
+import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.sms.SmsChannelDO;
+import cn.iocoder.dashboard.modules.system.service.sms.SmsChannelService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.validation.annotation.Validated;
diff --git a/src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/SmsTemplateController.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SmsTemplateController.java
similarity index 98%
rename from src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/SmsTemplateController.java
rename to src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SmsTemplateController.java
index 8bd73b12e..9fdf98440 100644
--- a/src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/SmsTemplateController.java
+++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SmsTemplateController.java
@@ -1,4 +1,4 @@
-package cn.iocoder.dashboard.modules.msg.controller.sms;
+package cn.iocoder.dashboard.modules.system.controller.sms;
import cn.iocoder.dashboard.common.enums.CommonStatusEnum;
import cn.iocoder.dashboard.common.pojo.CommonResult;
diff --git a/src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/vo/SmsChannelAllVO.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/SmsChannelAllVO.java
similarity index 94%
rename from src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/vo/SmsChannelAllVO.java
rename to src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/SmsChannelAllVO.java
index bac72c959..042cddaa2 100644
--- a/src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/vo/SmsChannelAllVO.java
+++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/SmsChannelAllVO.java
@@ -1,4 +1,4 @@
-package cn.iocoder.dashboard.modules.msg.controller.sms.vo;
+package cn.iocoder.dashboard.modules.system.controller.sms.vo;
import lombok.Data;
import lombok.EqualsAndHashCode;
diff --git a/src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/vo/SmsTemplateVO.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/SmsTemplateVO.java
similarity index 88%
rename from src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/vo/SmsTemplateVO.java
rename to src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/SmsTemplateVO.java
index 04bfe9a62..c5156a6ae 100644
--- a/src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/vo/SmsTemplateVO.java
+++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/SmsTemplateVO.java
@@ -1,4 +1,4 @@
-package cn.iocoder.dashboard.modules.msg.controller.sms.vo;
+package cn.iocoder.dashboard.modules.system.controller.sms.vo;
import lombok.Data;
import lombok.EqualsAndHashCode;
diff --git a/src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/vo/req/SmsChannelCreateReqVO.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/req/SmsChannelCreateReqVO.java
similarity index 94%
rename from src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/vo/req/SmsChannelCreateReqVO.java
rename to src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/req/SmsChannelCreateReqVO.java
index 729088b65..b38f7c832 100644
--- a/src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/vo/req/SmsChannelCreateReqVO.java
+++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/req/SmsChannelCreateReqVO.java
@@ -1,4 +1,4 @@
-package cn.iocoder.dashboard.modules.msg.controller.sms.vo.req;
+package cn.iocoder.dashboard.modules.system.controller.sms.vo.req;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
diff --git a/src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/vo/req/SmsChannelPageReqVO.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/req/SmsChannelPageReqVO.java
similarity index 73%
rename from src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/vo/req/SmsChannelPageReqVO.java
rename to src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/req/SmsChannelPageReqVO.java
index dd2df146e..19e2987fe 100644
--- a/src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/vo/req/SmsChannelPageReqVO.java
+++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/req/SmsChannelPageReqVO.java
@@ -1,4 +1,4 @@
-package cn.iocoder.dashboard.modules.msg.controller.sms.vo.req;
+package cn.iocoder.dashboard.modules.system.controller.sms.vo.req;
import cn.iocoder.dashboard.common.pojo.PageParam;
import io.swagger.annotations.ApiModel;
@@ -7,11 +7,6 @@ import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import java.util.Date;
-
-import static cn.iocoder.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@ApiModel("消息渠道分页 Request VO")
@Data
diff --git a/src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/vo/resp/SmsChannelEnumRespVO.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/resp/SmsChannelEnumRespVO.java
similarity index 83%
rename from src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/vo/resp/SmsChannelEnumRespVO.java
rename to src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/resp/SmsChannelEnumRespVO.java
index a3e56e0ca..cb156781d 100644
--- a/src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/vo/resp/SmsChannelEnumRespVO.java
+++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/resp/SmsChannelEnumRespVO.java
@@ -1,4 +1,4 @@
-package cn.iocoder.dashboard.modules.msg.controller.sms.vo.resp;
+package cn.iocoder.dashboard.modules.system.controller.sms.vo.resp;
import io.swagger.annotations.ApiModel;
import lombok.Data;
diff --git a/src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/vo/resp/SmsChannelPageRespVO.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/resp/SmsChannelPageRespVO.java
similarity index 95%
rename from src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/vo/resp/SmsChannelPageRespVO.java
rename to src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/resp/SmsChannelPageRespVO.java
index 603f13e07..2ad1ce357 100644
--- a/src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/vo/resp/SmsChannelPageRespVO.java
+++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/resp/SmsChannelPageRespVO.java
@@ -1,4 +1,4 @@
-package cn.iocoder.dashboard.modules.msg.controller.sms.vo.resp;
+package cn.iocoder.dashboard.modules.system.controller.sms.vo.resp;
import cn.iocoder.dashboard.common.pojo.PageParam;
import io.swagger.annotations.ApiModel;
diff --git a/src/main/java/cn/iocoder/dashboard/modules/msg/convert/sms/SmsChannelConvert.java b/src/main/java/cn/iocoder/dashboard/modules/system/convert/sms/SmsChannelConvert.java
similarity index 68%
rename from src/main/java/cn/iocoder/dashboard/modules/msg/convert/sms/SmsChannelConvert.java
rename to src/main/java/cn/iocoder/dashboard/modules/system/convert/sms/SmsChannelConvert.java
index 4728586a3..af87d2253 100644
--- a/src/main/java/cn/iocoder/dashboard/modules/msg/convert/sms/SmsChannelConvert.java
+++ b/src/main/java/cn/iocoder/dashboard/modules/system/convert/sms/SmsChannelConvert.java
@@ -1,11 +1,11 @@
-package cn.iocoder.dashboard.modules.msg.convert.sms;
+package cn.iocoder.dashboard.modules.system.convert.sms;
import cn.iocoder.dashboard.common.enums.SmsChannelEnum;
import cn.iocoder.dashboard.common.pojo.PageResult;
-import cn.iocoder.dashboard.modules.msg.controller.sms.vo.SmsChannelAllVO;
-import cn.iocoder.dashboard.modules.msg.controller.sms.vo.req.SmsChannelCreateReqVO;
-import cn.iocoder.dashboard.modules.msg.controller.sms.vo.resp.SmsChannelEnumRespVO;
-import cn.iocoder.dashboard.modules.msg.dal.mysql.daoobject.sms.SmsChannelDO;
+import cn.iocoder.dashboard.modules.system.controller.sms.vo.SmsChannelAllVO;
+import cn.iocoder.dashboard.modules.system.controller.sms.vo.req.SmsChannelCreateReqVO;
+import cn.iocoder.dashboard.modules.system.controller.sms.vo.resp.SmsChannelEnumRespVO;
+import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.sms.SmsChannelDO;
import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserUpdateReqVO;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.mapstruct.Mapper;
diff --git a/src/main/java/cn/iocoder/dashboard/modules/msg/convert/sms/SmsTemplateConvert.java b/src/main/java/cn/iocoder/dashboard/modules/system/convert/sms/SmsTemplateConvert.java
similarity index 66%
rename from src/main/java/cn/iocoder/dashboard/modules/msg/convert/sms/SmsTemplateConvert.java
rename to src/main/java/cn/iocoder/dashboard/modules/system/convert/sms/SmsTemplateConvert.java
index 313e06c92..476b96e0e 100644
--- a/src/main/java/cn/iocoder/dashboard/modules/msg/convert/sms/SmsTemplateConvert.java
+++ b/src/main/java/cn/iocoder/dashboard/modules/system/convert/sms/SmsTemplateConvert.java
@@ -1,9 +1,9 @@
-package cn.iocoder.dashboard.modules.msg.convert.sms;
+package cn.iocoder.dashboard.modules.system.convert.sms;
import cn.iocoder.dashboard.common.pojo.PageResult;
-import cn.iocoder.dashboard.modules.msg.controller.sms.vo.SmsTemplateVO;
-import cn.iocoder.dashboard.modules.msg.dal.mysql.daoobject.sms.SmsChannelDO;
-import cn.iocoder.dashboard.modules.msg.dal.mysql.daoobject.sms.SmsTemplateDO;
+import cn.iocoder.dashboard.modules.system.controller.sms.vo.SmsTemplateVO;
+import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.sms.SmsChannelDO;
+import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.sms.SmsTemplateDO;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
diff --git a/src/main/java/cn/iocoder/dashboard/modules/msg/dal/mysql/dao/sms/SmsChannelMapper.java b/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/sms/SmsChannelMapper.java
similarity index 83%
rename from src/main/java/cn/iocoder/dashboard/modules/msg/dal/mysql/dao/sms/SmsChannelMapper.java
rename to src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/sms/SmsChannelMapper.java
index f7ede3502..d1ce95c62 100644
--- a/src/main/java/cn/iocoder/dashboard/modules/msg/dal/mysql/dao/sms/SmsChannelMapper.java
+++ b/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/sms/SmsChannelMapper.java
@@ -1,10 +1,10 @@
-package cn.iocoder.dashboard.modules.msg.dal.mysql.dao.sms;
+package cn.iocoder.dashboard.modules.system.dal.mysql.dao.sms;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.dashboard.common.enums.CommonStatusEnum;
import cn.iocoder.dashboard.framework.mybatis.core.util.MyBatisUtils;
-import cn.iocoder.dashboard.modules.msg.controller.sms.vo.req.SmsChannelPageReqVO;
-import cn.iocoder.dashboard.modules.msg.dal.mysql.daoobject.sms.SmsChannelDO;
+import cn.iocoder.dashboard.modules.system.controller.sms.vo.req.SmsChannelPageReqVO;
+import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.sms.SmsChannelDO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
diff --git a/src/main/java/cn/iocoder/dashboard/modules/msg/dal/mysql/dao/sms/SmsLogMapper.java b/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/sms/SmsLogMapper.java
similarity index 55%
rename from src/main/java/cn/iocoder/dashboard/modules/msg/dal/mysql/dao/sms/SmsLogMapper.java
rename to src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/sms/SmsLogMapper.java
index 263783b47..a5dce01de 100644
--- a/src/main/java/cn/iocoder/dashboard/modules/msg/dal/mysql/dao/sms/SmsLogMapper.java
+++ b/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/sms/SmsLogMapper.java
@@ -1,6 +1,6 @@
-package cn.iocoder.dashboard.modules.msg.dal.mysql.dao.sms;
+package cn.iocoder.dashboard.modules.system.dal.mysql.dao.sms;
-import cn.iocoder.dashboard.modules.msg.dal.mysql.daoobject.sms.SmsLog;
+import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.sms.SmsLog;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
diff --git a/src/main/java/cn/iocoder/dashboard/modules/msg/dal/mysql/dao/sms/SmsTemplateMapper.java b/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/sms/SmsTemplateMapper.java
similarity index 89%
rename from src/main/java/cn/iocoder/dashboard/modules/msg/dal/mysql/dao/sms/SmsTemplateMapper.java
rename to src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/sms/SmsTemplateMapper.java
index f2d2fb21b..fd941ae7a 100644
--- a/src/main/java/cn/iocoder/dashboard/modules/msg/dal/mysql/dao/sms/SmsTemplateMapper.java
+++ b/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/sms/SmsTemplateMapper.java
@@ -1,7 +1,7 @@
-package cn.iocoder.dashboard.modules.msg.dal.mysql.dao.sms;
+package cn.iocoder.dashboard.modules.system.dal.mysql.dao.sms;
import cn.iocoder.dashboard.common.enums.CommonStatusEnum;
-import cn.iocoder.dashboard.modules.msg.dal.mysql.daoobject.sms.SmsTemplateDO;
+import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.sms.SmsTemplateDO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
diff --git a/src/main/java/cn/iocoder/dashboard/modules/msg/dal/mysql/daoobject/sms/SmsChannelDO.java b/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/sms/SmsChannelDO.java
similarity index 93%
rename from src/main/java/cn/iocoder/dashboard/modules/msg/dal/mysql/daoobject/sms/SmsChannelDO.java
rename to src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/sms/SmsChannelDO.java
index 3c0b5f396..5cce2ffa4 100644
--- a/src/main/java/cn/iocoder/dashboard/modules/msg/dal/mysql/daoobject/sms/SmsChannelDO.java
+++ b/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/sms/SmsChannelDO.java
@@ -1,4 +1,4 @@
-package cn.iocoder.dashboard.modules.msg.dal.mysql.daoobject.sms;
+package cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.sms;
import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.TableName;
diff --git a/src/main/java/cn/iocoder/dashboard/modules/msg/dal/mysql/daoobject/sms/SmsLog.java b/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/sms/SmsLog.java
similarity index 93%
rename from src/main/java/cn/iocoder/dashboard/modules/msg/dal/mysql/daoobject/sms/SmsLog.java
rename to src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/sms/SmsLog.java
index e5af0471e..169369b1e 100644
--- a/src/main/java/cn/iocoder/dashboard/modules/msg/dal/mysql/daoobject/sms/SmsLog.java
+++ b/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/sms/SmsLog.java
@@ -1,4 +1,4 @@
-package cn.iocoder.dashboard.modules.msg.dal.mysql.daoobject.sms;
+package cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.sms;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
diff --git a/src/main/java/cn/iocoder/dashboard/modules/msg/dal/mysql/daoobject/sms/SmsTemplateDO.java b/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/sms/SmsTemplateDO.java
similarity index 95%
rename from src/main/java/cn/iocoder/dashboard/modules/msg/dal/mysql/daoobject/sms/SmsTemplateDO.java
rename to src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/sms/SmsTemplateDO.java
index 39257a71d..360999838 100644
--- a/src/main/java/cn/iocoder/dashboard/modules/msg/dal/mysql/daoobject/sms/SmsTemplateDO.java
+++ b/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/sms/SmsTemplateDO.java
@@ -1,4 +1,4 @@
-package cn.iocoder.dashboard.modules.msg.dal.mysql.daoobject.sms;
+package cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.sms;
import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.TableName;
diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/enums/SysErrorCodeConstants.java b/src/main/java/cn/iocoder/dashboard/modules/system/enums/SysErrorCodeConstants.java
index 5aa257a97..05e9e6393 100644
--- a/src/main/java/cn/iocoder/dashboard/modules/system/enums/SysErrorCodeConstants.java
+++ b/src/main/java/cn/iocoder/dashboard/modules/system/enums/SysErrorCodeConstants.java
@@ -77,9 +77,11 @@ public interface SysErrorCodeConstants {
// ========== 消息 1003001000 ==========
- ErrorCode SMS_CHANNEL_NOT_FOUND = new ErrorCode(1003001001, "没有短信渠道信息, 请初始化sms_channel表数据。");
- ErrorCode SMS_TEMPLATE_NOT_FOUND = new ErrorCode(1003001002, "没有短信模板信息, 请初始化sms_template表数据。");
- ErrorCode SMS_SENDER_NOT_FOUND = new ErrorCode(1003001003, "没有找到对应的短信发送对象,请检查sms_channel表和sms_template表数据");
- ErrorCode INVALID_CHANNEL_CODE = new ErrorCode(1003001004, "非法的短信渠道code,请检查sms_channel表的code值是否与SmsChannelEnum中的code值一致。");
+ ErrorCode SMS_CHANNEL_NOT_INIT = new ErrorCode(1003001001,
+ "短信渠道没有初始化, 请调用SmsClientWrapper#initSmsClient()或SmsClientWrapper#addSmsClient");
+ ErrorCode SMS_CHANNEL_NOT_FOUND = new ErrorCode(1003001002, "没有短信渠道信息, 请初始化sms_channel表数据。");
+ ErrorCode SMS_TEMPLATE_NOT_FOUND = new ErrorCode(1003001003, "没有短信模板信息, 请初始化sms_template表数据。");
+ ErrorCode SMS_SENDER_NOT_FOUND = new ErrorCode(1003001004, "没有找到对应的短信发送对象,请检查sms_channel表和sms_template表数据");
+ ErrorCode INVALID_CHANNEL_CODE = new ErrorCode(1003001005, "非法的短信渠道code,请检查sms_channel表的code值是否与SmsChannelEnum中的code值一致。");
}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/msg/service/sms/SmsChannelService.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SmsChannelService.java
similarity index 55%
rename from src/main/java/cn/iocoder/dashboard/modules/msg/service/sms/SmsChannelService.java
rename to src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SmsChannelService.java
index ed2c047e8..3040f3bdb 100644
--- a/src/main/java/cn/iocoder/dashboard/modules/msg/service/sms/SmsChannelService.java
+++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SmsChannelService.java
@@ -1,11 +1,11 @@
-package cn.iocoder.dashboard.modules.msg.service.sms;
+package cn.iocoder.dashboard.modules.system.service.sms;
import cn.iocoder.dashboard.common.pojo.PageResult;
-import cn.iocoder.dashboard.modules.msg.controller.sms.vo.SmsChannelAllVO;
-import cn.iocoder.dashboard.modules.msg.controller.sms.vo.req.SmsChannelCreateReqVO;
-import cn.iocoder.dashboard.modules.msg.controller.sms.vo.req.SmsChannelPageReqVO;
-import cn.iocoder.dashboard.modules.msg.controller.sms.vo.resp.SmsChannelEnumRespVO;
-import cn.iocoder.dashboard.modules.msg.dal.mysql.daoobject.sms.SmsChannelDO;
+import cn.iocoder.dashboard.modules.system.controller.sms.vo.SmsChannelAllVO;
+import cn.iocoder.dashboard.modules.system.controller.sms.vo.req.SmsChannelCreateReqVO;
+import cn.iocoder.dashboard.modules.system.controller.sms.vo.req.SmsChannelPageReqVO;
+import cn.iocoder.dashboard.modules.system.controller.sms.vo.resp.SmsChannelEnumRespVO;
+import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.sms.SmsChannelDO;
import java.util.List;
diff --git a/src/main/java/cn/iocoder/dashboard/modules/msg/service/sms/SmsLogService.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SmsLogService.java
similarity index 66%
rename from src/main/java/cn/iocoder/dashboard/modules/msg/service/sms/SmsLogService.java
rename to src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SmsLogService.java
index 70f4d9eeb..d29d7f884 100644
--- a/src/main/java/cn/iocoder/dashboard/modules/msg/service/sms/SmsLogService.java
+++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SmsLogService.java
@@ -1,4 +1,4 @@
-package cn.iocoder.dashboard.modules.msg.service.sms;
+package cn.iocoder.dashboard.modules.system.service.sms;
/**
* 短信渠道Service接口
diff --git a/src/main/java/cn/iocoder/dashboard/modules/msg/service/sms/SmsTemplateService.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SmsTemplateService.java
similarity index 67%
rename from src/main/java/cn/iocoder/dashboard/modules/msg/service/sms/SmsTemplateService.java
rename to src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SmsTemplateService.java
index 2c1364934..585a22a57 100644
--- a/src/main/java/cn/iocoder/dashboard/modules/msg/service/sms/SmsTemplateService.java
+++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SmsTemplateService.java
@@ -1,4 +1,4 @@
-package cn.iocoder.dashboard.modules.msg.service.sms;
+package cn.iocoder.dashboard.modules.system.service.sms;
/**
* 短信渠道Service接口
diff --git a/src/main/java/cn/iocoder/dashboard/modules/msg/service/sms/impl/SmsChannelServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SmsChannelServiceImpl.java
similarity index 61%
rename from src/main/java/cn/iocoder/dashboard/modules/msg/service/sms/impl/SmsChannelServiceImpl.java
rename to src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SmsChannelServiceImpl.java
index e5202f491..ccc47af3c 100644
--- a/src/main/java/cn/iocoder/dashboard/modules/msg/service/sms/impl/SmsChannelServiceImpl.java
+++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SmsChannelServiceImpl.java
@@ -1,21 +1,19 @@
-package cn.iocoder.dashboard.modules.msg.service.sms.impl;
+package cn.iocoder.dashboard.modules.system.service.sms.impl;
import cn.hutool.core.util.ObjectUtil;
-import cn.hutool.extra.spring.SpringUtil;
import cn.iocoder.dashboard.common.enums.SmsChannelEnum;
import cn.iocoder.dashboard.common.pojo.PageResult;
-import cn.iocoder.dashboard.framework.msg.sms.factory.AbstractSmsSenderFactory;
-import cn.iocoder.dashboard.modules.msg.controller.sms.vo.SmsChannelAllVO;
-import cn.iocoder.dashboard.modules.msg.controller.sms.vo.req.SmsChannelCreateReqVO;
-import cn.iocoder.dashboard.modules.msg.controller.sms.vo.req.SmsChannelPageReqVO;
-import cn.iocoder.dashboard.modules.msg.controller.sms.vo.resp.SmsChannelEnumRespVO;
-import cn.iocoder.dashboard.modules.msg.convert.sms.SmsChannelConvert;
-import cn.iocoder.dashboard.modules.msg.convert.sms.SmsTemplateConvert;
-import cn.iocoder.dashboard.modules.msg.dal.mysql.dao.sms.SmsChannelMapper;
-import cn.iocoder.dashboard.modules.msg.dal.mysql.dao.sms.SmsTemplateMapper;
-import cn.iocoder.dashboard.modules.msg.dal.mysql.daoobject.sms.SmsChannelDO;
-import cn.iocoder.dashboard.modules.msg.dal.mysql.daoobject.sms.SmsTemplateDO;
-import cn.iocoder.dashboard.modules.msg.service.sms.SmsChannelService;
+import cn.iocoder.dashboard.modules.system.controller.sms.vo.SmsChannelAllVO;
+import cn.iocoder.dashboard.modules.system.controller.sms.vo.req.SmsChannelCreateReqVO;
+import cn.iocoder.dashboard.modules.system.controller.sms.vo.req.SmsChannelPageReqVO;
+import cn.iocoder.dashboard.modules.system.controller.sms.vo.resp.SmsChannelEnumRespVO;
+import cn.iocoder.dashboard.modules.system.convert.sms.SmsChannelConvert;
+import cn.iocoder.dashboard.modules.system.convert.sms.SmsTemplateConvert;
+import cn.iocoder.dashboard.modules.system.dal.mysql.dao.sms.SmsChannelMapper;
+import cn.iocoder.dashboard.modules.system.dal.mysql.dao.sms.SmsTemplateMapper;
+import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.sms.SmsChannelDO;
+import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.sms.SmsTemplateDO;
+import cn.iocoder.dashboard.modules.system.service.sms.SmsChannelService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@@ -76,12 +74,6 @@ public class SmsChannelServiceImpl implements SmsChannelService {
@Override
public boolean flushChannel() {
- AbstractSmsSenderFactory smsSenderFactory = SpringUtil.getBean(AbstractSmsSenderFactory.class);
- if (smsSenderFactory == null) {
- return false;
- }
-
- smsSenderFactory.flush(listChannelAllEnabledInfo());
return true;
}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/msg/service/sms/impl/SmsLogServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SmsLogServiceImpl.java
similarity index 60%
rename from src/main/java/cn/iocoder/dashboard/modules/msg/service/sms/impl/SmsLogServiceImpl.java
rename to src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SmsLogServiceImpl.java
index f7e348a4d..e54d265c6 100644
--- a/src/main/java/cn/iocoder/dashboard/modules/msg/service/sms/impl/SmsLogServiceImpl.java
+++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SmsLogServiceImpl.java
@@ -1,6 +1,6 @@
-package cn.iocoder.dashboard.modules.msg.service.sms.impl;
+package cn.iocoder.dashboard.modules.system.service.sms.impl;
-import cn.iocoder.dashboard.modules.msg.service.sms.SmsLogService;
+import cn.iocoder.dashboard.modules.system.service.sms.SmsLogService;
import org.springframework.stereotype.Service;
/**
diff --git a/src/main/java/cn/iocoder/dashboard/modules/msg/service/sms/impl/SmsTemplateServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SmsTemplateServiceImpl.java
similarity index 60%
rename from src/main/java/cn/iocoder/dashboard/modules/msg/service/sms/impl/SmsTemplateServiceImpl.java
rename to src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SmsTemplateServiceImpl.java
index caf6d8e1c..2826d7fca 100644
--- a/src/main/java/cn/iocoder/dashboard/modules/msg/service/sms/impl/SmsTemplateServiceImpl.java
+++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SmsTemplateServiceImpl.java
@@ -1,6 +1,6 @@
-package cn.iocoder.dashboard.modules.msg.service.sms.impl;
+package cn.iocoder.dashboard.modules.system.service.sms.impl;
-import cn.iocoder.dashboard.modules.msg.service.sms.SmsTemplateService;
+import cn.iocoder.dashboard.modules.system.service.sms.SmsTemplateService;
import org.springframework.stereotype.Service;
/**
diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/sms/SmsConfiguration.java b/src/main/java/cn/iocoder/dashboard/modules/system/sms/SmsConfiguration.java
new file mode 100644
index 000000000..ffb5887bd
--- /dev/null
+++ b/src/main/java/cn/iocoder/dashboard/modules/system/sms/SmsConfiguration.java
@@ -0,0 +1,34 @@
+package cn.iocoder.dashboard.modules.system.sms;
+
+import cn.iocoder.dashboard.framework.sms.SmsClient;
+import cn.iocoder.dashboard.framework.sms.SmsClientAdapter;
+import cn.iocoder.dashboard.modules.system.controller.sms.vo.SmsChannelAllVO;
+import cn.iocoder.dashboard.modules.system.service.sms.SmsChannelService;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.annotation.Resource;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 短信服务配置
+ *
+ * @author guer
+ */
+@Configuration
+@ConditionalOnProperty("sms.enabled")
+public class SmsConfiguration {
+
+ @Resource
+ private SmsChannelService channelService;
+
+ @Bean
+ public SmsClientAdapter smsClientWrapper() {
+ List smsChannelAllVOList = channelService.listChannelAllEnabledInfo();
+ Map> channelId2SmsClientMap = SmsSenderUtils.init(smsChannelAllVOList);
+ return new SmsClientAdapter(channelId2SmsClientMap);
+ }
+
+}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/sms/SmsSenderUtils.java b/src/main/java/cn/iocoder/dashboard/modules/system/sms/SmsSenderUtils.java
new file mode 100644
index 000000000..ea9c24489
--- /dev/null
+++ b/src/main/java/cn/iocoder/dashboard/modules/system/sms/SmsSenderUtils.java
@@ -0,0 +1,143 @@
+package cn.iocoder.dashboard.modules.system.sms;
+
+import cn.hutool.core.util.ObjectUtil;
+import cn.iocoder.dashboard.common.enums.SmsChannelEnum;
+import cn.iocoder.dashboard.common.exception.ServiceException;
+import cn.iocoder.dashboard.framework.sms.SmsBody;
+import cn.iocoder.dashboard.framework.sms.SmsClient;
+import cn.iocoder.dashboard.framework.sms.SmsClientAdapter;
+import cn.iocoder.dashboard.framework.sms.SmsResult;
+import cn.iocoder.dashboard.modules.system.controller.sms.vo.SmsChannelAllVO;
+import cn.iocoder.dashboard.modules.system.controller.sms.vo.SmsTemplateVO;
+import cn.iocoder.dashboard.modules.system.sms.client.AliSmsClient;
+import cn.iocoder.dashboard.modules.system.sms.proxy.SmsClientLogProxy;
+
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+
+import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.*;
+
+/**
+ * 短信发送者工厂
+ *
+ * @author zzf
+ * @date 2021/1/25 16:18
+ */
+public class SmsSenderUtils {
+
+ /**
+ * 短信渠道id:短信客户端map
+ * key: channelId
+ * val: SmsClient
+ */
+ private static final Map> smsSenderMap = new ConcurrentHashMap<>(8);
+
+ /**
+ * 短信模板code: 短信渠道id map
+ * key: templateCode
+ * val: channelId
+ */
+ private static final Map templateCode2ChannelIdMap = new HashMap<>();
+
+ /**
+ * 将短信渠道信息初始化成短信客户端
+ *
+ * @param smsChannelAllVOList 短信渠道信息
+ * @return 短信渠道id:短信客户端map
+ */
+ public synchronized static Map> init(List smsChannelAllVOList) {
+ if (ObjectUtil.isEmpty(smsChannelAllVOList)) {
+ throw new ServiceException(SMS_CHANNEL_NOT_FOUND);
+ }
+ addSender(smsChannelAllVOList);
+ return smsSenderMap;
+ }
+
+ /**
+ * 重置短信客户端信息
+ *
+ * @param smsClientAdapter 短信客户端适配器
+ * @param smsChannelAllVOList 短信渠道信息集合
+ */
+ public synchronized static void flush(SmsClientAdapter smsClientAdapter, List smsChannelAllVOList) {
+ smsSenderMap.clear();
+ smsClientAdapter.flushClient(init(smsChannelAllVOList));
+ }
+
+ /**
+ * 发送短信
+ *
+ * @param smsClientAdapter 短信客户端适配器
+ * @param smsBody 短信内容
+ * @param targetPhones 对象手机集合
+ * @return 短信发送结果
+ */
+ public static SmsResult> send(SmsClientAdapter smsClientAdapter, SmsBody smsBody, Collection targetPhones) {
+ Long channelId = templateCode2ChannelIdMap.get(smsBody.getCode());
+ if (channelId == null) {
+ throw new ServiceException(SMS_SENDER_NOT_FOUND);
+ }
+ return smsClientAdapter.send(channelId, smsBody, targetPhones);
+ }
+
+ /**
+ * 发送短信
+ *
+ * @param smsClientAdapter 短信客户端适配器
+ * @param smsBody 短信内容
+ * @param targetPhone 对象手机
+ * @return 短信发送结果
+ */
+ public static SmsResult> send(SmsClientAdapter smsClientAdapter, SmsBody smsBody, String targetPhone) {
+ Long channelId = templateCode2ChannelIdMap.get(smsBody.getCode());
+ if (channelId == null) {
+ throw new ServiceException(SMS_SENDER_NOT_FOUND);
+ }
+ return smsClientAdapter.send(channelId, smsBody, Collections.singletonList(targetPhone));
+ }
+
+ /**
+ * 发送短信
+ *
+ * @param smsClientAdapter 短信客户端适配器
+ * @param smsBody 短信内容
+ * @param targetPhones 对象手机数组
+ * @return 短信发送结果
+ */
+ public static SmsResult> send(SmsClientAdapter smsClientAdapter, SmsBody smsBody, String... targetPhones) {
+ Long channelId = templateCode2ChannelIdMap.get(smsBody.getCode());
+ if (channelId == null) {
+ throw new ServiceException(SMS_SENDER_NOT_FOUND);
+ }
+ return smsClientAdapter.send(channelId, smsBody, Arrays.asList(targetPhones));
+ }
+
+
+ private static void addSender(List smsChannelAllVOList) {
+ smsChannelAllVOList.forEach(channelAllVO -> addSender(SmsChannelEnum.getByCode(channelAllVO.getCode()), channelAllVO));
+ }
+
+ private static void addSender(SmsChannelEnum channelEnum, SmsChannelAllVO channelAllVO) {
+ if (channelEnum == null) {
+ throw new ServiceException(INVALID_CHANNEL_CODE);
+ }
+ List templateList = channelAllVO.getTemplateList();
+ if (ObjectUtil.isEmpty(templateList)) {
+ throw new ServiceException(SMS_TEMPLATE_NOT_FOUND);
+ }
+ SmsClient> aliSmsClient = getSender(channelEnum, channelAllVO);
+ templateList.forEach(smsTemplateVO -> templateCode2ChannelIdMap.put(smsTemplateVO.getCode(), channelAllVO.getId()));
+ smsSenderMap.put(channelAllVO.getId(), aliSmsClient);
+ }
+
+ private static SmsClient> getSender(SmsChannelEnum channelEnum, SmsChannelAllVO channelAllVO) {
+ switch (channelEnum) {
+ case ALI:
+ return new SmsClientLogProxy<>(new AliSmsClient(channelAllVO));
+ // TODO fill more channel
+ default:
+ break;
+ }
+ throw new ServiceException(SMS_SENDER_NOT_FOUND);
+ }
+}
diff --git a/src/main/java/cn/iocoder/dashboard/framework/msg/sms/impl/ali/AliSmsSender.java b/src/main/java/cn/iocoder/dashboard/modules/system/sms/client/AliSmsClient.java
similarity index 81%
rename from src/main/java/cn/iocoder/dashboard/framework/msg/sms/impl/ali/AliSmsSender.java
rename to src/main/java/cn/iocoder/dashboard/modules/system/sms/client/AliSmsClient.java
index fbf6aeceb..f144ec380 100644
--- a/src/main/java/cn/iocoder/dashboard/framework/msg/sms/impl/ali/AliSmsSender.java
+++ b/src/main/java/cn/iocoder/dashboard/modules/system/sms/client/AliSmsClient.java
@@ -1,9 +1,9 @@
-package cn.iocoder.dashboard.framework.msg.sms.impl.ali;
+package cn.iocoder.dashboard.modules.system.sms.client;
-import cn.iocoder.dashboard.framework.msg.sms.SmsBody;
-import cn.iocoder.dashboard.framework.msg.sms.SmsResult;
-import cn.iocoder.dashboard.framework.msg.sms.SmsSender;
-import cn.iocoder.dashboard.modules.msg.controller.sms.vo.SmsChannelAllVO;
+import cn.iocoder.dashboard.framework.sms.SmsBody;
+import cn.iocoder.dashboard.framework.sms.SmsClient;
+import cn.iocoder.dashboard.framework.sms.SmsResult;
+import cn.iocoder.dashboard.modules.system.controller.sms.vo.SmsChannelAllVO;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
@@ -23,7 +23,7 @@ import java.util.Collection;
* @date 2021/1/25 14:17
*/
@Slf4j
-public class AliSmsSender implements SmsSender {
+public class AliSmsClient implements SmsClient {
private static final String OK = "OK";
@@ -42,7 +42,7 @@ public class AliSmsSender implements SmsSender {
*
* @param channelVO 阿里云短信配置
*/
- public AliSmsSender(SmsChannelAllVO channelVO) {
+ public AliSmsClient(SmsChannelAllVO channelVO) {
this.channelVO = channelVO;
@@ -83,4 +83,9 @@ public class AliSmsSender implements SmsSender {
return failResult();
}
+ @Override
+ public SmsResult sendAsync(SmsBody msgBody, Collection targets) {
+ return null;
+ }
+
}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/sms/proxy/SmsClientLogProxy.java b/src/main/java/cn/iocoder/dashboard/modules/system/sms/proxy/SmsClientLogProxy.java
new file mode 100644
index 000000000..a7d201e6f
--- /dev/null
+++ b/src/main/java/cn/iocoder/dashboard/modules/system/sms/proxy/SmsClientLogProxy.java
@@ -0,0 +1,48 @@
+package cn.iocoder.dashboard.modules.system.sms.proxy;
+
+import cn.iocoder.dashboard.framework.sms.SmsBody;
+import cn.iocoder.dashboard.framework.sms.SmsClient;
+import cn.iocoder.dashboard.framework.sms.SmsResult;
+import cn.iocoder.dashboard.util.json.JsonUtils;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.Collection;
+
+/**
+ * 消息父接口
+ *
+ * @author zzf
+ * @date 2021/1/22 15:46
+ */
+@Slf4j
+public class SmsClientLogProxy implements SmsClient {
+
+ private final SmsClient smsClient;
+
+ @Override
+ public SmsResult send(SmsBody msgBody, Collection targets) {
+ log.debug("ready send sms, body: {}, target: {}", JsonUtils.toJsonString(msgBody), targets);
+
+ SmsResult resultBody = smsClient.send(msgBody, targets);
+
+ if (resultBody.getSuccess()) {
+ //
+ } else {
+ log.warn("send sms fail, body: {}, target: {}, resultBody: {}",
+ JsonUtils.toJsonString(msgBody),
+ targets,
+ JsonUtils.toJsonString(resultBody)
+ );
+ }
+ return resultBody;
+ }
+
+ @Override
+ public SmsResult sendAsync(SmsBody msgBody, Collection targets) {
+ return send(msgBody, targets);
+ }
+
+ public SmsClientLogProxy(SmsClient smsClient) {
+ this.smsClient = smsClient;
+ }
+}
From 009f33210680bb77a727636732ce23ab5c8c5fb5 Mon Sep 17 00:00:00 2001
From: zengzefeng <986510453@qq.com>
Date: Mon, 1 Feb 2021 14:25:22 +0800
Subject: [PATCH 03/54] =?UTF-8?q?=E9=87=8D=E6=9E=84=E7=9F=AD=E4=BF=A1?=
=?UTF-8?q?=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
sql/ruoyi-vue-pro.sql | 71 ---------
sql/sms.sql | 82 ++++++++++
.../dashboard/framework/sms/SmsClient.java | 107 -------------
.../framework/sms/SmsClientAdapter.java | 42 -----
.../sms/client/AbstractSmsClient.java | 32 ++++
.../sms/client/AliyunSmsClient.java} | 35 ++---
.../framework/sms/client/SmsClient.java | 25 +++
.../framework/sms/{ => core}/SmsBody.java | 10 +-
.../framework/sms/core/SmsClientFactory.java | 71 +++++++++
.../framework/sms/{ => core}/SmsResult.java | 2 +-
.../controller/sms/SmsChannelController.java | 6 -
...elAllVO.java => SmsChannelPropertyVO.java} | 2 +-
.../controller/sms/vo/SmsTemplateVO.java | 8 +
.../system/convert/sms/SmsChannelConvert.java | 4 +-
.../dal/mysql/dao/sms/SmsLogMapper.java | 4 +-
.../sms/{SmsLog.java => SmsLogDO.java} | 16 +-
.../system/enums/SysErrorCodeConstants.java | 1 +
.../system/enums/sms/SmsSendStatusEnum.java | 30 ++++
.../mq/consumer/sms/SmsSendConsumer.java | 31 ++++
.../system/mq/message/sms/SmsSendMessage.java | 25 +++
.../system/mq/producer/sms/SmsProducer.java | 31 ++++
.../system/service/sms/SmsChannelService.java | 37 ++++-
.../system/service/sms/SmsLogService.java | 25 +++
.../system/service/sms/SmsService.java | 101 +++++++++++++
.../sms/impl/SmsChannelServiceImpl.java | 47 ++++--
.../service/sms/impl/SmsLogServiceImpl.java | 57 +++++++
.../service/sms/impl/SmsServiceImpl.java | 51 +++++++
.../modules/system/sms/SmsConfiguration.java | 34 -----
.../modules/system/sms/SmsSenderUtils.java | 143 ------------------
.../system/sms/proxy/SmsClientLogProxy.java | 48 ------
.../dashboard/util/string/StrUtils.java | 21 +++
31 files changed, 701 insertions(+), 498 deletions(-)
create mode 100644 sql/sms.sql
delete mode 100644 src/main/java/cn/iocoder/dashboard/framework/sms/SmsClient.java
delete mode 100644 src/main/java/cn/iocoder/dashboard/framework/sms/SmsClientAdapter.java
create mode 100644 src/main/java/cn/iocoder/dashboard/framework/sms/client/AbstractSmsClient.java
rename src/main/java/cn/iocoder/dashboard/{modules/system/sms/client/AliSmsClient.java => framework/sms/client/AliyunSmsClient.java} (73%)
create mode 100644 src/main/java/cn/iocoder/dashboard/framework/sms/client/SmsClient.java
rename src/main/java/cn/iocoder/dashboard/framework/sms/{ => core}/SmsBody.java (67%)
create mode 100644 src/main/java/cn/iocoder/dashboard/framework/sms/core/SmsClientFactory.java
rename src/main/java/cn/iocoder/dashboard/framework/sms/{ => core}/SmsResult.java (86%)
rename src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/{SmsChannelAllVO.java => SmsChannelPropertyVO.java} (94%)
rename src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/sms/{SmsLog.java => SmsLogDO.java} (73%)
create mode 100644 src/main/java/cn/iocoder/dashboard/modules/system/enums/sms/SmsSendStatusEnum.java
create mode 100644 src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/sms/SmsSendConsumer.java
create mode 100644 src/main/java/cn/iocoder/dashboard/modules/system/mq/message/sms/SmsSendMessage.java
create mode 100644 src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/sms/SmsProducer.java
create mode 100644 src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SmsService.java
create mode 100644 src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SmsServiceImpl.java
delete mode 100644 src/main/java/cn/iocoder/dashboard/modules/system/sms/SmsConfiguration.java
delete mode 100644 src/main/java/cn/iocoder/dashboard/modules/system/sms/SmsSenderUtils.java
delete mode 100644 src/main/java/cn/iocoder/dashboard/modules/system/sms/proxy/SmsClientLogProxy.java
diff --git a/sql/ruoyi-vue-pro.sql b/sql/ruoyi-vue-pro.sql
index 9355fab64..af7f492f9 100644
--- a/sql/ruoyi-vue-pro.sql
+++ b/sql/ruoyi-vue-pro.sql
@@ -884,75 +884,4 @@ INSERT INTO `sys_user_role` VALUES (5, 100, 1, '', NULL, '', NULL, b'0');
INSERT INTO `sys_user_role` VALUES (6, 100, 2, '', NULL, '', NULL, b'0');
COMMIT;
-
--- ----------------------------
--- Table structure for sms_channel
--- ----------------------------
-DROP TABLE IF EXISTS `sms_channel`;
-CREATE TABLE `sms_channel` (
- `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增编号',
- `code` varchar(50) not null COMMENT '编码(来自枚举类 阿里、华为、七牛等)',
- `api_key` varchar(100) NOT NULL COMMENT '账号id',
- `api_secret` varchar(100) NOT NULL COMMENT '账号秘钥',
- `api_signature_id` varchar(100) NOT NULL COMMENT '实际渠道签名唯一标识',
- `name` varchar(50) not null COMMENT '名称',
- `signature` varchar(50) not null COMMENT '签名值',
- `remark` varchar(200) NOT NULL COMMENT '备注',
-
- `status` tinyint(4) NOT NULL default 0 COMMENT '启用状态(0正常 1停用)',
- `create_by` varchar(64) not null DEFAULT '' COMMENT '创建者',
- `create_time` datetime DEFAULT NULL COMMENT '创建时间',
- `update_by` varchar(64) DEFAULT '' COMMENT '更新者',
- `update_time` datetime DEFAULT NULL COMMENT '更新时间',
- `deleted` bit(1) DEFAULT b'0' COMMENT '是否删除',
- PRIMARY KEY (`id`) USING BTREE
-) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='短信渠道';
-/*
- 优先级值一样时,按照id顺序取值
-*/
-
--- ----------------------------
--- Table structure for sms_template
--- ----------------------------
-DROP TABLE IF EXISTS `sms_template`;
-CREATE TABLE `sms_template` (
- `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增编号',
- `channel_code` varchar(50) not null COMMENT '短信渠道编码(来自枚举类)',
- `channel_id` bigint(20) not null COMMENT '短信渠道id (对于前端来说就是绑定一个签名)',
- `type` tinyint(4) NOT NULL default 1 COMMENT '消息类型 [0验证码 1短信通知 2推广短信 3国际/港澳台消息]',
- `biz_code` varchar(50) not null COMMENT '业务编码(来自数据字典, 用户自定义业务场景 一个场景可以有多个模板)',
- `code` varchar(50) not null COMMENT '编码',
- `name` varchar(50) not null COMMENT '名称',
- `api_template_id` varchar(100) NOT NULL COMMENT '实际渠道模板唯一标识',
- `content` varchar(1000) NOT NULL DEFAULT '' COMMENT '内容',
- `params` varchar(200) NOT NULL DEFAULT '' COMMENT '参数数组(自动根据内容生成)',
- `remark` varchar(200) NOT NULL COMMENT '备注',
-
- `status` tinyint(4) NOT NULL default 0 COMMENT '启用状态(0正常 1停用)',
- `create_by` varchar(64) not null DEFAULT '' COMMENT '创建者',
- `create_time` datetime DEFAULT NULL COMMENT '创建时间',
- `update_by` varchar(64) DEFAULT '' COMMENT '更新者',
- `update_time` datetime DEFAULT NULL COMMENT '更新时间',
- `deleted` bit(1) DEFAULT b'0' COMMENT '是否删除',
- PRIMARY KEY (`id`) USING BTREE
-) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='短信模板';
-
--- ----------------------------
--- Table structure for sms_log
--- ----------------------------
-DROP TABLE IF EXISTS `sms_log`;
-CREATE TABLE `sms_log` (
- `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增编号',
- `channel_code` varchar(50) not null COMMENT '短信渠道编码(来自枚举类)',
- `api_sms_id` varchar(50) not null COMMENT '实际渠道短信唯一标识',
- `template_id` bigint(20) NOT NULL COMMENT '模板id',
- `phone` char(11) not null COMMENT '手机号',
- `content` varchar(1000) NOT NULL DEFAULT '' COMMENT '内容',
- `remark` varchar(200) NOT NULL COMMENT '备注',
- `send_status` tinyint(4) NOT NULL default 0 COMMENT '发送状态(0发送中 1成功 2失败)',
- `create_by` varchar(64) not null DEFAULT '' COMMENT '创建者',
- `create_time` datetime DEFAULT NULL COMMENT '创建时间',
- PRIMARY KEY (`id`) USING BTREE
-) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='短信日志';
-
SET FOREIGN_KEY_CHECKS = 1;
diff --git a/sql/sms.sql b/sql/sms.sql
new file mode 100644
index 000000000..82d854155
--- /dev/null
+++ b/sql/sms.sql
@@ -0,0 +1,82 @@
+/*
+ --2021.02.01 by fight, sms about table info
+*/
+
+-- ----------------------------
+-- Table structure for sms_channel
+-- ----------------------------
+DROP TABLE IF EXISTS `sms_channel`;
+CREATE TABLE `sms_channel`
+(
+ `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增编号',
+ `code` varchar(50) NOT NULL COMMENT '编码(来自枚举类 阿里、华为、七牛等)',
+ `api_key` varchar(100) NOT NULL COMMENT '账号id',
+ `api_secret` varchar(100) NOT NULL COMMENT '账号秘钥',
+ `api_signature_id` varchar(100) NOT NULL COMMENT '实际渠道签名唯一标识',
+ `name` varchar(50) NOT NULL COMMENT '名称',
+ `signature` varchar(50) NOT NULL COMMENT '签名值',
+ `remark` varchar(200) NOT NULL COMMENT '备注',
+
+ `status` tinyint(4) NOT NULL DEFAULT 0 COMMENT '启用状态(0正常 1停用)',
+ `create_by` varchar(64) NOT NULL DEFAULT '' COMMENT '创建者',
+ `create_time` datetime DEFAULT NULL COMMENT '创建时间',
+ `update_by` varchar(64) DEFAULT '' COMMENT '更新者',
+ `update_time` datetime DEFAULT NULL COMMENT '更新时间',
+ `deleted` bit(1) DEFAULT b'0' COMMENT '是否删除',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB
+ AUTO_INCREMENT = 1
+ DEFAULT CHARSET = utf8mb4 COMMENT ='短信渠道';
+/*
+ 优先级值一样时,按照id顺序取值
+*/
+
+-- ----------------------------
+-- Table structure for sms_template
+-- ----------------------------
+DROP TABLE IF EXISTS `sms_template`;
+CREATE TABLE `sms_template`
+(
+ `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增编号',
+ `channel_code` varchar(50) NOT NULL COMMENT '短信渠道编码(来自枚举类)',
+ `channel_id` bigint(20) NOT NULL COMMENT '短信渠道id (对于前端来说就是绑定一个签名)',
+ `type` tinyint(4) NOT NULL DEFAULT 1 COMMENT '消息类型 [0验证码 1短信通知 2推广短信 3国际/港澳台消息]',
+ `biz_code` varchar(50) NOT NULL COMMENT '业务编码(来自数据字典, 用户自定义业务场景 一个场景可以有多个模板)',
+ `code` varchar(50) NOT NULL COMMENT '编码',
+ `name` varchar(50) NOT NULL COMMENT '名称',
+ `api_template_id` varchar(100) NOT NULL COMMENT '实际渠道模板唯一标识',
+ `content` varchar(1000) NOT NULL DEFAULT '' COMMENT '内容',
+ `params` varchar(200) NOT NULL DEFAULT '' COMMENT '参数数组(自动根据内容生成)',
+ `remark` varchar(200) NOT NULL COMMENT '备注',
+
+ `status` tinyint(4) NOT NULL DEFAULT 0 COMMENT '启用状态(0正常 1停用)',
+ `create_by` varchar(64) NOT NULL DEFAULT '' COMMENT '创建者',
+ `create_time` datetime DEFAULT NULL COMMENT '创建时间',
+ `update_by` varchar(64) DEFAULT '' COMMENT '更新者',
+ `update_time` datetime DEFAULT NULL COMMENT '更新时间',
+ `deleted` bit(1) DEFAULT b'0' COMMENT '是否删除',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB
+ AUTO_INCREMENT = 1
+ DEFAULT CHARSET = utf8mb4 COMMENT ='短信模板';
+
+-- ----------------------------
+-- Table structure for sms_log
+-- ----------------------------
+DROP TABLE IF EXISTS `sms_log`;
+CREATE TABLE `sms_log`
+(
+ `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增编号',
+ `channel_code` varchar(50) NOT NULL COMMENT '短信渠道编码(来自枚举类)',
+ `channel_id` bigint(20) NOT NULL COMMENT '短信渠道id',
+ `template_code` varchar(50) NOT NULL COMMENT '渠道编码',
+ `phones` char(11) NOT NULL COMMENT '手机号(数组json字符串)',
+ `content` varchar(1000) NOT NULL DEFAULT '' COMMENT '内容',
+ `remark` varchar(200) DEFAULT NULL COMMENT '备注',
+ `send_status` tinyint(4) NOT NULL DEFAULT 2 COMMENT '发送状态(1异步推送中 2发送中 3失败 4成功)',
+ `create_by` varchar(64) NOT NULL DEFAULT '' COMMENT '创建者',
+ `create_time` datetime DEFAULT NULL COMMENT '创建时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB
+ AUTO_INCREMENT = 1
+ DEFAULT CHARSET = utf8mb4 COMMENT ='短信日志';
diff --git a/src/main/java/cn/iocoder/dashboard/framework/sms/SmsClient.java b/src/main/java/cn/iocoder/dashboard/framework/sms/SmsClient.java
deleted file mode 100644
index bf1a44f57..000000000
--- a/src/main/java/cn/iocoder/dashboard/framework/sms/SmsClient.java
+++ /dev/null
@@ -1,107 +0,0 @@
-package cn.iocoder.dashboard.framework.sms;
-
-import org.apache.commons.lang3.StringUtils;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-
-/**
- * 短信父接口
- *
- * @author zzf
- * @date 2021/1/25 14:14
- */
-public interface SmsClient {
-
- /**
- * 发送消息
- *
- * @param msgBody 消息内容
- * @param targets 发送对象列表
- * @return 是否发送成功
- */
- SmsResult send(SmsBody msgBody, Collection targets);
-
- /**
- * 发送消息
- *
- * @param msgBody 消息内容
- * @param target 发送对象
- * @return 是否发送成功
- */
- default SmsResult send(SmsBody msgBody, String target) {
- if (StringUtils.isBlank(target)) {
- return failResult();
- }
-
- return send(msgBody, Collections.singletonList(target));
- }
-
- /**
- * 发送消息
- *
- * @param msgBody 消息内容
- * @param targets 发送对象列表
- * @return 是否发送成功
- */
- default SmsResult send(SmsBody msgBody, String... targets) {
- if (targets == null) {
- return failResult();
- }
-
- return send(msgBody, Arrays.asList(targets));
- }
-
-
- /**
- * 异步发送消息
- *
- * @param msgBody 消息内容
- * @param targets 发送对象列表
- * @return 是否发送成功
- */
- SmsResult sendAsync(SmsBody msgBody, Collection targets);
-
- /**
- * 异步发送消息
- *
- * @param msgBody 消息内容
- * @param target 发送对象
- * @return 是否发送成功
- */
- default SmsResult sendAsync(SmsBody msgBody, String target) {
- if (StringUtils.isBlank(target)) {
- return failResult("target must not null.");
- }
-
- return sendAsync(msgBody, Collections.singletonList(target));
- }
-
- /**
- * 异步发送消息
- *
- * @param msgBody 消息内容
- * @param targets 发送对象列表
- * @return 是否发送成功
- */
- default SmsResult sendAsync(SmsBody msgBody, String... targets) {
- if (targets == null) {
- return failResult("targets must not null.");
- }
-
- return sendAsync(msgBody, Arrays.asList(targets));
- }
-
- default SmsResult failResult() {
- SmsResult resultBody = new SmsResult<>();
- resultBody.setSuccess(false);
- return resultBody;
- }
-
- default SmsResult failResult(String message) {
- SmsResult resultBody = failResult();
- resultBody.setMessage(message);
- return resultBody;
- }
-}
\ No newline at end of file
diff --git a/src/main/java/cn/iocoder/dashboard/framework/sms/SmsClientAdapter.java b/src/main/java/cn/iocoder/dashboard/framework/sms/SmsClientAdapter.java
deleted file mode 100644
index 6edf7646f..000000000
--- a/src/main/java/cn/iocoder/dashboard/framework/sms/SmsClientAdapter.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package cn.iocoder.dashboard.framework.sms;
-
-import cn.hutool.core.util.ObjectUtil;
-import cn.iocoder.dashboard.common.exception.ServiceException;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Map;
-
-import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.SMS_CHANNEL_NOT_INIT;
-
-/**
- * 抽象短信客户端工厂
- *
- * @author zzf
- * @date 2021/1/28 14:01
- */
-public class SmsClientAdapter {
-
- private final Map> smsSenderMap;
-
- public SmsClientAdapter(Map> smsSenderMap) {
- if (ObjectUtil.isEmpty(smsSenderMap)) {
- throw new ServiceException(SMS_CHANNEL_NOT_INIT);
- }
- this.smsSenderMap = smsSenderMap;
- }
-
- public void flushClient(Map> smsSenderMap) {
- this.smsSenderMap.clear();
- smsSenderMap.putAll(Collections.unmodifiableMap(smsSenderMap));
- }
-
- public SmsResult> send(Long channelId, SmsBody smsBody, Collection targetPhone) {
- SmsClient> smsClient = getSmsSender(channelId);
- return smsClient.send(smsBody, targetPhone);
- }
-
- private SmsClient> getSmsSender(Long channelId) {
- return smsSenderMap.get(channelId);
- }
-}
diff --git a/src/main/java/cn/iocoder/dashboard/framework/sms/client/AbstractSmsClient.java b/src/main/java/cn/iocoder/dashboard/framework/sms/client/AbstractSmsClient.java
new file mode 100644
index 000000000..043dd2a50
--- /dev/null
+++ b/src/main/java/cn/iocoder/dashboard/framework/sms/client/AbstractSmsClient.java
@@ -0,0 +1,32 @@
+package cn.iocoder.dashboard.framework.sms.client;
+
+import cn.iocoder.dashboard.modules.system.controller.sms.vo.SmsChannelPropertyVO;
+
+/**
+ * 抽象短息客户端
+ *
+ * @author zzf
+ * @date 2021/2/1 9:28
+ */
+public abstract class AbstractSmsClient implements SmsClient {
+
+ /**
+ * 短信渠道参数
+ */
+ protected final SmsChannelPropertyVO channelVO;
+
+ /**
+ * 构造阿里云短信发送处理
+ *
+ * @param channelVO 阿里云短信配置
+ */
+ public AbstractSmsClient(SmsChannelPropertyVO channelVO) {
+ this.channelVO = channelVO;
+ }
+
+
+ public SmsChannelPropertyVO getProperty() {
+ return channelVO;
+ }
+
+}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/sms/client/AliSmsClient.java b/src/main/java/cn/iocoder/dashboard/framework/sms/client/AliyunSmsClient.java
similarity index 73%
rename from src/main/java/cn/iocoder/dashboard/modules/system/sms/client/AliSmsClient.java
rename to src/main/java/cn/iocoder/dashboard/framework/sms/client/AliyunSmsClient.java
index f144ec380..39d359449 100644
--- a/src/main/java/cn/iocoder/dashboard/modules/system/sms/client/AliSmsClient.java
+++ b/src/main/java/cn/iocoder/dashboard/framework/sms/client/AliyunSmsClient.java
@@ -1,9 +1,8 @@
-package cn.iocoder.dashboard.modules.system.sms.client;
+package cn.iocoder.dashboard.framework.sms.client;
-import cn.iocoder.dashboard.framework.sms.SmsBody;
-import cn.iocoder.dashboard.framework.sms.SmsClient;
-import cn.iocoder.dashboard.framework.sms.SmsResult;
-import cn.iocoder.dashboard.modules.system.controller.sms.vo.SmsChannelAllVO;
+import cn.iocoder.dashboard.framework.sms.core.SmsBody;
+import cn.iocoder.dashboard.framework.sms.core.SmsResult;
+import cn.iocoder.dashboard.modules.system.controller.sms.vo.SmsChannelPropertyVO;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
@@ -23,7 +22,7 @@ import java.util.Collection;
* @date 2021/1/25 14:17
*/
@Slf4j
-public class AliSmsClient implements SmsClient {
+public class AliyunSmsClient extends AbstractSmsClient {
private static final String OK = "OK";
@@ -33,8 +32,6 @@ public class AliSmsClient implements SmsClient {
private static final String ENDPOINT = "cn-hangzhou";
- private final SmsChannelAllVO channelVO;
-
private final IAcsClient acsClient;
/**
@@ -42,9 +39,8 @@ public class AliSmsClient implements SmsClient {
*
* @param channelVO 阿里云短信配置
*/
- public AliSmsClient(SmsChannelAllVO channelVO) {
-
- this.channelVO = channelVO;
+ public AliyunSmsClient(SmsChannelPropertyVO channelVO) {
+ super(channelVO);
String accessKeyId = channelVO.getApiKey();
String accessKeySecret = channelVO.getApiSecret();
@@ -57,13 +53,13 @@ public class AliSmsClient implements SmsClient {
@Override
- public SmsResult send(SmsBody msgBody, Collection targets) {
+ public SmsResult send(SmsBody smsBody, Collection targets) {
SendSmsRequest request = new SendSmsRequest();
request.setSysMethod(MethodType.POST);
request.setPhoneNumbers(StringUtils.join(targets, ","));
request.setSignName(channelVO.getApiSignatureId());
- request.setTemplateCode(channelVO.getTemplateByTemplateCode(msgBody.getCode()).getApiTemplateId());
- request.setTemplateParam(msgBody.getParamsStr());
+ request.setTemplateCode(channelVO.getTemplateByTemplateCode(smsBody.getTemplateCode()).getApiTemplateId());
+ request.setTemplateParam(smsBody.getParamsStr());
try {
SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);
@@ -78,14 +74,15 @@ public class AliSmsClient implements SmsClient {
return resultBody;
} catch (Exception e) {
log.debug(e.getMessage(), e);
+ return failResult("发送异常: " + e.getMessage());
}
-
- return failResult();
}
- @Override
- public SmsResult sendAsync(SmsBody msgBody, Collection targets) {
- return null;
+ SmsResult failResult(String message) {
+ SmsResult resultBody = new SmsResult<>();
+ resultBody.setSuccess(false);
+ resultBody.setMessage(message);
+ return resultBody;
}
}
diff --git a/src/main/java/cn/iocoder/dashboard/framework/sms/client/SmsClient.java b/src/main/java/cn/iocoder/dashboard/framework/sms/client/SmsClient.java
new file mode 100644
index 000000000..290d21712
--- /dev/null
+++ b/src/main/java/cn/iocoder/dashboard/framework/sms/client/SmsClient.java
@@ -0,0 +1,25 @@
+package cn.iocoder.dashboard.framework.sms.client;
+
+import cn.iocoder.dashboard.framework.sms.core.SmsBody;
+import cn.iocoder.dashboard.framework.sms.core.SmsResult;
+
+import java.util.Collection;
+
+/**
+ * 短信父接口
+ *
+ * @author zzf
+ * @date 2021/1/25 14:14
+ */
+public interface SmsClient {
+
+ /**
+ * 发送消息
+ *
+ * @param smsBody 消息内容
+ * @param targets 发送对象列表
+ * @return 是否发送成功
+ */
+ SmsResult send(SmsBody smsBody, Collection targets);
+
+}
\ No newline at end of file
diff --git a/src/main/java/cn/iocoder/dashboard/framework/sms/SmsBody.java b/src/main/java/cn/iocoder/dashboard/framework/sms/core/SmsBody.java
similarity index 67%
rename from src/main/java/cn/iocoder/dashboard/framework/sms/SmsBody.java
rename to src/main/java/cn/iocoder/dashboard/framework/sms/core/SmsBody.java
index 48fb2253b..9b132431e 100644
--- a/src/main/java/cn/iocoder/dashboard/framework/sms/SmsBody.java
+++ b/src/main/java/cn/iocoder/dashboard/framework/sms/core/SmsBody.java
@@ -1,9 +1,10 @@
-package cn.iocoder.dashboard.framework.sms;
+package cn.iocoder.dashboard.framework.sms.core;
import cn.iocoder.dashboard.util.json.JsonUtils;
import lombok.Data;
import java.util.Map;
+import java.util.UUID;
/**
* 消息内容实体类
@@ -11,10 +12,15 @@ import java.util.Map;
@Data
public class SmsBody {
+ /**
+ * 消息日志id
+ */
+ private Long smsLogId;
+
/**
* 模板编码
*/
- private String code;
+ private String templateCode;
/**
* 参数列表
diff --git a/src/main/java/cn/iocoder/dashboard/framework/sms/core/SmsClientFactory.java b/src/main/java/cn/iocoder/dashboard/framework/sms/core/SmsClientFactory.java
new file mode 100644
index 000000000..6c1eaf07c
--- /dev/null
+++ b/src/main/java/cn/iocoder/dashboard/framework/sms/core/SmsClientFactory.java
@@ -0,0 +1,71 @@
+package cn.iocoder.dashboard.framework.sms.core;
+
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.iocoder.dashboard.common.enums.SmsChannelEnum;
+import cn.iocoder.dashboard.common.exception.ServiceException;
+import cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil;
+import cn.iocoder.dashboard.framework.sms.client.AbstractSmsClient;
+import cn.iocoder.dashboard.framework.sms.client.AliyunSmsClient;
+import cn.iocoder.dashboard.modules.system.controller.sms.vo.SmsChannelPropertyVO;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.*;
+
+/**
+ * 短信客户端工厂
+ *
+ * @author zzf
+ * @date 2021/1/28 14:01
+ */
+@Component
+public class SmsClientFactory {
+
+ private final Map> smsSenderMap = new ConcurrentHashMap<>(8);
+
+ /**
+ * 创建短信客户端
+ *
+ * @param propertyVO 参数对象
+ * @return 客户端id(默认channelId)
+ */
+ public Long createClient(SmsChannelPropertyVO propertyVO) {
+ if (StrUtil.isBlank(propertyVO.getCode())) {
+ throw ServiceExceptionUtil.exception(PARAM_VALUE_IS_NULL, "短信渠道编码");
+ }
+ if (ObjectUtil.isNull(propertyVO.getId())) {
+ throw ServiceExceptionUtil.exception(PARAM_VALUE_IS_NULL, "短信渠道ID");
+ }
+
+ AbstractSmsClient> sender = createClient(SmsChannelEnum.getByCode(propertyVO.getCode()), propertyVO);
+ smsSenderMap.put(propertyVO.getId(), sender);
+ return propertyVO.getId();
+ }
+
+ private AbstractSmsClient> createClient(SmsChannelEnum channelEnum, SmsChannelPropertyVO channelVO) {
+ if (channelEnum == null) {
+ throw new ServiceException(INVALID_CHANNEL_CODE);
+ }
+ switch (channelEnum) {
+ case ALI:
+ return new AliyunSmsClient(channelVO);
+ // TODO fill more channel
+ default:
+ break;
+ }
+ throw new ServiceException(SMS_SENDER_NOT_FOUND);
+ }
+
+ /**
+ * 获取短信客户端
+ *
+ * @param channelId 渠道id
+ * @return 短信id
+ */
+ public AbstractSmsClient> getClient(Long channelId) {
+ return smsSenderMap.get(channelId);
+ }
+}
diff --git a/src/main/java/cn/iocoder/dashboard/framework/sms/SmsResult.java b/src/main/java/cn/iocoder/dashboard/framework/sms/core/SmsResult.java
similarity index 86%
rename from src/main/java/cn/iocoder/dashboard/framework/sms/SmsResult.java
rename to src/main/java/cn/iocoder/dashboard/framework/sms/core/SmsResult.java
index b994514b6..a626bb759 100644
--- a/src/main/java/cn/iocoder/dashboard/framework/sms/SmsResult.java
+++ b/src/main/java/cn/iocoder/dashboard/framework/sms/core/SmsResult.java
@@ -1,4 +1,4 @@
-package cn.iocoder.dashboard.framework.sms;
+package cn.iocoder.dashboard.framework.sms.core;
import lombok.Data;
diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SmsChannelController.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SmsChannelController.java
index a75f9e2eb..932097514 100644
--- a/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SmsChannelController.java
+++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SmsChannelController.java
@@ -44,11 +44,5 @@ public class SmsChannelController {
return success(service.createChannel(reqVO));
}
- @ApiOperation("刷新消息渠道信息")
- @PutMapping("/flush")
- public CommonResult flushChannel() {
- return success(service.flushChannel());
- }
-
}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/SmsChannelAllVO.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/SmsChannelPropertyVO.java
similarity index 94%
rename from src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/SmsChannelAllVO.java
rename to src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/SmsChannelPropertyVO.java
index 042cddaa2..ab4d73594 100644
--- a/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/SmsChannelAllVO.java
+++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/SmsChannelPropertyVO.java
@@ -14,7 +14,7 @@ import java.util.List;
*/
@Data
@EqualsAndHashCode
-public class SmsChannelAllVO implements Serializable {
+public class SmsChannelPropertyVO implements Serializable {
/**
* id
diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/SmsTemplateVO.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/SmsTemplateVO.java
index c5156a6ae..d9daf7578 100644
--- a/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/SmsTemplateVO.java
+++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/SmsTemplateVO.java
@@ -17,6 +17,7 @@ public class SmsTemplateVO {
* 业务编码(来自数据字典, 用户自定义业务场景 一个场景可以有多个模板)
*/
private String bizCode;
+
/**
* 编码
*/
@@ -27,4 +28,11 @@ public class SmsTemplateVO {
*/
private String apiTemplateId;
+ /**
+ * 内容
+ */
+ private String content;
+
+
+
}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/convert/sms/SmsChannelConvert.java b/src/main/java/cn/iocoder/dashboard/modules/system/convert/sms/SmsChannelConvert.java
index af87d2253..985de7576 100644
--- a/src/main/java/cn/iocoder/dashboard/modules/system/convert/sms/SmsChannelConvert.java
+++ b/src/main/java/cn/iocoder/dashboard/modules/system/convert/sms/SmsChannelConvert.java
@@ -2,7 +2,7 @@ package cn.iocoder.dashboard.modules.system.convert.sms;
import cn.iocoder.dashboard.common.enums.SmsChannelEnum;
import cn.iocoder.dashboard.common.pojo.PageResult;
-import cn.iocoder.dashboard.modules.system.controller.sms.vo.SmsChannelAllVO;
+import cn.iocoder.dashboard.modules.system.controller.sms.vo.SmsChannelPropertyVO;
import cn.iocoder.dashboard.modules.system.controller.sms.vo.req.SmsChannelCreateReqVO;
import cn.iocoder.dashboard.modules.system.controller.sms.vo.resp.SmsChannelEnumRespVO;
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.sms.SmsChannelDO;
@@ -28,7 +28,7 @@ public interface SmsChannelConvert {
List convertEnum(List bean);
- List convert(List bean);
+ List convert(List bean);
}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/sms/SmsLogMapper.java b/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/sms/SmsLogMapper.java
index a5dce01de..2e52b070e 100644
--- a/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/sms/SmsLogMapper.java
+++ b/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/sms/SmsLogMapper.java
@@ -1,10 +1,10 @@
package cn.iocoder.dashboard.modules.system.dal.mysql.dao.sms;
-import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.sms.SmsLog;
+import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.sms.SmsLogDO;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
-public interface SmsLogMapper extends BaseMapper {
+public interface SmsLogMapper extends BaseMapper {
}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/sms/SmsLog.java b/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/sms/SmsLogDO.java
similarity index 73%
rename from src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/sms/SmsLog.java
rename to src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/sms/SmsLogDO.java
index 169369b1e..10ffef478 100644
--- a/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/sms/SmsLog.java
+++ b/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/sms/SmsLogDO.java
@@ -3,6 +3,7 @@ package cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.sms;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
@@ -15,8 +16,9 @@ import java.util.Date;
*/
@Data
@EqualsAndHashCode
+@Accessors(chain = true)
@TableName(value = "sms_log", autoResultMap = true)
-public class SmsLog implements Serializable {
+public class SmsLogDO implements Serializable {
/**
* 自增编号
@@ -29,19 +31,19 @@ public class SmsLog implements Serializable {
private String channelCode;
/**
- * 实际渠道短信唯一标识
+ * 短信渠道id
*/
- private String apiSmsId;
+ private Long channelId;
/**
* 模板id
*/
- private Long templateId;
+ private String templateCode;
/**
- * 手机号
+ * 手机号(数组json字符串)
*/
- private String phone;
+ private String phones;
/**
* 内容
@@ -54,7 +56,7 @@ public class SmsLog implements Serializable {
private String remark;
/**
- * 发送状态(0发送中 1成功 2失败)
+ * 发送状态(1异步推送中 2发送中 3失败 4成功)
*/
private Integer sendStatus;
diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/enums/SysErrorCodeConstants.java b/src/main/java/cn/iocoder/dashboard/modules/system/enums/SysErrorCodeConstants.java
index 05e9e6393..a1fc081c5 100644
--- a/src/main/java/cn/iocoder/dashboard/modules/system/enums/SysErrorCodeConstants.java
+++ b/src/main/java/cn/iocoder/dashboard/modules/system/enums/SysErrorCodeConstants.java
@@ -83,5 +83,6 @@ public interface SysErrorCodeConstants {
ErrorCode SMS_TEMPLATE_NOT_FOUND = new ErrorCode(1003001003, "没有短信模板信息, 请初始化sms_template表数据。");
ErrorCode SMS_SENDER_NOT_FOUND = new ErrorCode(1003001004, "没有找到对应的短信发送对象,请检查sms_channel表和sms_template表数据");
ErrorCode INVALID_CHANNEL_CODE = new ErrorCode(1003001005, "非法的短信渠道code,请检查sms_channel表的code值是否与SmsChannelEnum中的code值一致。");
+ ErrorCode PARAM_VALUE_IS_NULL = new ErrorCode(1003001006, "参数【{}】不能为空");
}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/enums/sms/SmsSendStatusEnum.java b/src/main/java/cn/iocoder/dashboard/modules/system/enums/sms/SmsSendStatusEnum.java
new file mode 100644
index 000000000..426e4cb80
--- /dev/null
+++ b/src/main/java/cn/iocoder/dashboard/modules/system/enums/sms/SmsSendStatusEnum.java
@@ -0,0 +1,30 @@
+package cn.iocoder.dashboard.modules.system.enums.sms;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 短信发送状态
+ *
+ * @author zzf
+ * @date 2021/2/1 13:39
+ */
+@Getter
+@AllArgsConstructor
+public enum SmsSendStatusEnum {
+
+ //异步转发中
+ ASYNC(1),
+
+ //发送中
+ SENDING(2),
+
+ //失败
+ FAIL(3),
+
+ //成功
+ SUCCESS(4);
+
+ private final int status;
+
+}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/sms/SmsSendConsumer.java b/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/sms/SmsSendConsumer.java
new file mode 100644
index 000000000..5da9703ca
--- /dev/null
+++ b/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/sms/SmsSendConsumer.java
@@ -0,0 +1,31 @@
+package cn.iocoder.dashboard.modules.system.mq.consumer.sms;
+
+import cn.iocoder.dashboard.framework.redis.core.pubsub.AbstractChannelMessageListener;
+import cn.iocoder.dashboard.framework.sms.core.SmsResult;
+import cn.iocoder.dashboard.modules.system.mq.message.dept.SysDeptRefreshMessage;
+import cn.iocoder.dashboard.modules.system.mq.message.sms.SmsSendMessage;
+import cn.iocoder.dashboard.modules.system.service.sms.SmsService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+
+/**
+ * 针对 {@link SysDeptRefreshMessage} 的消费者
+ *
+ * @author 芋道源码
+ */
+@Component
+@Slf4j
+public class SmsSendConsumer extends AbstractChannelMessageListener {
+
+ @Resource
+ private SmsService smsService;
+
+ @Override
+ public void onMessage(SmsSendMessage message) {
+ log.info("[onMessage][收到 发送短信 消息]");
+ SmsResult> send = smsService.send(message.getSmsBody(), message.getTargetPhones());
+ }
+
+}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/sms/SmsSendMessage.java b/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/sms/SmsSendMessage.java
new file mode 100644
index 000000000..8ca1207fa
--- /dev/null
+++ b/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/sms/SmsSendMessage.java
@@ -0,0 +1,25 @@
+package cn.iocoder.dashboard.modules.system.mq.message.sms;
+
+import cn.iocoder.dashboard.framework.redis.core.pubsub.ChannelMessage;
+import cn.iocoder.dashboard.framework.sms.core.SmsBody;
+import lombok.Data;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 部门数据刷新 Message
+ */
+@Data
+public class SmsSendMessage implements ChannelMessage {
+
+ private SmsBody smsBody;
+
+ private List targetPhones;
+
+ @Override
+ public String getChannel() {
+ return "sms.send";
+ }
+
+}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/sms/SmsProducer.java b/src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/sms/SmsProducer.java
new file mode 100644
index 000000000..892b333cf
--- /dev/null
+++ b/src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/sms/SmsProducer.java
@@ -0,0 +1,31 @@
+package cn.iocoder.dashboard.modules.system.mq.producer.sms;
+
+import cn.iocoder.dashboard.framework.redis.core.util.RedisMessageUtils;
+import cn.iocoder.dashboard.framework.sms.core.SmsBody;
+import cn.iocoder.dashboard.modules.system.mq.message.sms.SmsSendMessage;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+/**
+ * 短信的 Producer
+ */
+@Component
+public class SmsProducer {
+
+ @Resource
+ private StringRedisTemplate stringRedisTemplate;
+
+ /**
+ * 发送 {@link SmsSendMessage} 消息
+ */
+ public void sendSmsSendMessage(SmsBody smsBody, List targetPhoneList) {
+ SmsSendMessage message = new SmsSendMessage();
+ message.setSmsBody(smsBody);
+ message.setTargetPhones(targetPhoneList);
+ RedisMessageUtils.sendChannelMessage(stringRedisTemplate, message);
+ }
+
+}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SmsChannelService.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SmsChannelService.java
index 3040f3bdb..5fd39c2cf 100644
--- a/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SmsChannelService.java
+++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SmsChannelService.java
@@ -1,7 +1,8 @@
package cn.iocoder.dashboard.modules.system.service.sms;
import cn.iocoder.dashboard.common.pojo.PageResult;
-import cn.iocoder.dashboard.modules.system.controller.sms.vo.SmsChannelAllVO;
+import cn.iocoder.dashboard.framework.sms.client.AbstractSmsClient;
+import cn.iocoder.dashboard.modules.system.controller.sms.vo.SmsChannelPropertyVO;
import cn.iocoder.dashboard.modules.system.controller.sms.vo.req.SmsChannelCreateReqVO;
import cn.iocoder.dashboard.modules.system.controller.sms.vo.req.SmsChannelPageReqVO;
import cn.iocoder.dashboard.modules.system.controller.sms.vo.resp.SmsChannelEnumRespVO;
@@ -17,18 +18,46 @@ import java.util.List;
*/
public interface SmsChannelService {
+ /**
+ * 初始化短信渠道
+ */
+ void initSmsClient();
+
+ /**
+ * 分页查询短信渠道信息
+ *
+ * @param reqVO 参数对象
+ * @return 短信渠道分页对象
+ */
PageResult pageChannels(SmsChannelPageReqVO reqVO);
+ /**
+ * 创建新的渠道信息
+ *
+ * @param reqVO 参数对象
+ * @return 渠道id
+ */
Long createChannel(SmsChannelCreateReqVO reqVO);
+ /**
+ * 获取短信渠道枚举/渠道编码
+ *
+ * @return 短信渠道枚举/渠道编码
+ */
List getChannelEnums();
+ /**
+ * 根据短信模板编码获取短信客户端
+ *
+ * @param templateCode 短信模板编码
+ * @return 短信客户端
+ */
+ AbstractSmsClient> getClient(String templateCode);
+
/**
* 查询渠道(包含名下模块)信息集合
*
* @return 渠道(包含名下模块)信息集合
*/
- List listChannelAllEnabledInfo();
-
- boolean flushChannel();
+ List listChannelAllEnabledInfo();
}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SmsLogService.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SmsLogService.java
index d29d7f884..2646dcbfa 100644
--- a/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SmsLogService.java
+++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SmsLogService.java
@@ -1,5 +1,11 @@
package cn.iocoder.dashboard.modules.system.service.sms;
+import cn.iocoder.dashboard.framework.sms.client.AbstractSmsClient;
+import cn.iocoder.dashboard.framework.sms.core.SmsBody;
+import cn.iocoder.dashboard.framework.sms.core.SmsResult;
+
+import java.util.List;
+
/**
* 短信渠道Service接口
*
@@ -7,4 +13,23 @@ package cn.iocoder.dashboard.modules.system.service.sms;
* @date 2021/1/25 9:24
*/
public interface SmsLogService {
+ /**
+ * 发送短信前的日志处理
+ *
+ * @param smsBody 短信内容
+ * @param targetPhones 发送对象手机号集合
+ * @param client 短信客户端
+ * @param isAsync 是否异步发送
+ * @return 生成的日志id
+ */
+ Long beforeSendLog(SmsBody smsBody, List targetPhones, AbstractSmsClient> client, Boolean isAsync);
+
+ /**
+ * 发送消息后的日志处理
+ *
+ * @param logId 日志id
+ * @param result 消息结果
+ */
+ void afterSendLog(Long logId, SmsResult> result);
+
}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SmsService.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SmsService.java
new file mode 100644
index 000000000..56dc2dfa9
--- /dev/null
+++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SmsService.java
@@ -0,0 +1,101 @@
+package cn.iocoder.dashboard.modules.system.service.sms;
+
+import cn.iocoder.dashboard.framework.sms.core.SmsBody;
+import cn.iocoder.dashboard.framework.sms.core.SmsResult;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * 短信Service接口
+ *
+ * @author zzf
+ * @date 2021/1/25 9:24
+ */
+public interface SmsService {
+
+ /**
+ * 发送消息
+ *
+ * @param smsBody 消息内容
+ * @param targetPhones 发送对象手机号列表
+ * @return 是否发送成功
+ */
+ SmsResult> send(SmsBody smsBody, List targetPhones);
+
+ /**
+ * 发送消息
+ *
+ * @param smsBody 消息内容
+ * @param targetPhone 发送对象手机号
+ * @return 是否发送成功
+ */
+ default SmsResult> send(SmsBody smsBody, String targetPhone) {
+ if (StringUtils.isBlank(targetPhone)) {
+ return failResult("targetPhone must not null.");
+ }
+
+ return send(smsBody, Collections.singletonList(targetPhone));
+ }
+
+ /**
+ * 发送消息
+ *
+ * @param smsBody 消息内容
+ * @param targetPhones 发送对象手机号数组
+ * @return 是否发送成功
+ */
+ default SmsResult> send(SmsBody smsBody, String... targetPhones) {
+ if (targetPhones == null) {
+ return failResult("targetPhones must not null.");
+ }
+
+ return send(smsBody, Arrays.asList(targetPhones));
+ }
+
+
+ /**
+ * 异步发送消息
+ *
+ * @param msgBody 消息内容
+ * @param targetPhones 发送对象列表
+ */
+ void sendAsync(SmsBody msgBody, List targetPhones);
+
+ /**
+ * 异步发送消息
+ *
+ * @param msgBody 消息内容
+ * @param targetPhone 发送对象
+ */
+ default void sendAsync(SmsBody msgBody, String targetPhone) {
+ if (StringUtils.isBlank(targetPhone)) {
+ return;
+ }
+ sendAsync(msgBody, Collections.singletonList(targetPhone));
+ }
+
+ /**
+ * 异步发送消息
+ *
+ * @param msgBody 消息内容
+ * @param targetPhones 发送对象列表
+ */
+ default void sendAsync(SmsBody msgBody, String... targetPhones) {
+ if (targetPhones == null) {
+ return;
+ }
+ sendAsync(msgBody, Arrays.asList(targetPhones));
+ }
+
+
+ default SmsResult> failResult(String message) {
+ SmsResult> resultBody = new SmsResult<>();
+ resultBody.setSuccess(false);
+ resultBody.setMessage(message);
+ return resultBody;
+ }
+
+}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SmsChannelServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SmsChannelServiceImpl.java
index ccc47af3c..044a4e561 100644
--- a/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SmsChannelServiceImpl.java
+++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SmsChannelServiceImpl.java
@@ -3,7 +3,9 @@ package cn.iocoder.dashboard.modules.system.service.sms.impl;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.dashboard.common.enums.SmsChannelEnum;
import cn.iocoder.dashboard.common.pojo.PageResult;
-import cn.iocoder.dashboard.modules.system.controller.sms.vo.SmsChannelAllVO;
+import cn.iocoder.dashboard.framework.sms.client.AbstractSmsClient;
+import cn.iocoder.dashboard.framework.sms.core.SmsClientFactory;
+import cn.iocoder.dashboard.modules.system.controller.sms.vo.SmsChannelPropertyVO;
import cn.iocoder.dashboard.modules.system.controller.sms.vo.req.SmsChannelCreateReqVO;
import cn.iocoder.dashboard.modules.system.controller.sms.vo.req.SmsChannelPageReqVO;
import cn.iocoder.dashboard.modules.system.controller.sms.vo.resp.SmsChannelEnumRespVO;
@@ -14,12 +16,16 @@ import cn.iocoder.dashboard.modules.system.dal.mysql.dao.sms.SmsTemplateMapper;
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.sms.SmsChannelDO;
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.sms.SmsTemplateDO;
import cn.iocoder.dashboard.modules.system.service.sms.SmsChannelService;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
+import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
/**
* 短信渠道Service实现类
@@ -30,6 +36,30 @@ import java.util.List;
@Service
public class SmsChannelServiceImpl implements SmsChannelService {
+ private final Map templateCode2ChannelIdMap = new ConcurrentHashMap<>(32);
+
+ @Autowired
+ private SmsClientFactory smsClientFactory;
+
+ /**
+ * 初始化短信客户端
+ */
+ @PostConstruct
+ @Override
+ public void initSmsClient() {
+ List smsChannelPropertyVOList = listChannelAllEnabledInfo();
+ if (ObjectUtil.isEmpty(smsChannelPropertyVOList)) {
+ return;
+ }
+ smsChannelPropertyVOList.forEach(smsChannelPropertyVO -> {
+ Long clientId = smsClientFactory.createClient(smsChannelPropertyVO);
+ smsChannelPropertyVO.getTemplateList().forEach(smsTemplateVO -> {
+ templateCode2ChannelIdMap.put(smsTemplateVO.getCode(), clientId);
+ });
+ });
+ }
+
+
@Resource
private SmsChannelMapper mapper;
@@ -54,12 +84,17 @@ public class SmsChannelServiceImpl implements SmsChannelService {
}
@Override
- public List listChannelAllEnabledInfo() {
+ public AbstractSmsClient> getClient(String templateCode) {
+ return smsClientFactory.getClient(templateCode2ChannelIdMap.get(templateCode));
+ }
+
+ @Override
+ public List listChannelAllEnabledInfo() {
List channelDOList = mapper.selectEnabledList();
if (ObjectUtil.isNull(channelDOList)) {
return null;
}
- List channelAllVOList = SmsChannelConvert.INSTANCE.convert(channelDOList);
+ List channelAllVOList = SmsChannelConvert.INSTANCE.convert(channelDOList);
channelAllVOList.forEach(smsChannelDO -> {
@@ -71,10 +106,4 @@ public class SmsChannelServiceImpl implements SmsChannelService {
});
return channelAllVOList;
}
-
- @Override
- public boolean flushChannel() {
-
- return true;
- }
}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SmsLogServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SmsLogServiceImpl.java
index e54d265c6..651917259 100644
--- a/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SmsLogServiceImpl.java
+++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SmsLogServiceImpl.java
@@ -1,8 +1,21 @@
package cn.iocoder.dashboard.modules.system.service.sms.impl;
+import cn.iocoder.dashboard.framework.sms.client.AbstractSmsClient;
+import cn.iocoder.dashboard.framework.sms.core.SmsBody;
+import cn.iocoder.dashboard.framework.sms.core.SmsResult;
+import cn.iocoder.dashboard.modules.system.controller.sms.vo.SmsChannelPropertyVO;
+import cn.iocoder.dashboard.modules.system.controller.sms.vo.SmsTemplateVO;
+import cn.iocoder.dashboard.modules.system.dal.mysql.dao.sms.SmsLogMapper;
+import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.sms.SmsLogDO;
+import cn.iocoder.dashboard.modules.system.enums.sms.SmsSendStatusEnum;
import cn.iocoder.dashboard.modules.system.service.sms.SmsLogService;
+import cn.iocoder.dashboard.util.json.JsonUtils;
+import cn.iocoder.dashboard.util.string.StrUtils;
import org.springframework.stereotype.Service;
+import javax.annotation.Resource;
+import java.util.List;
+
/**
* 短信日志Service实现类
*
@@ -12,4 +25,48 @@ import org.springframework.stereotype.Service;
@Service
public class SmsLogServiceImpl implements SmsLogService {
+ @Resource
+ private SmsLogMapper smsLogMapper;
+
+ @Override
+ public Long beforeSendLog(SmsBody smsBody, List targetPhones, AbstractSmsClient> client, Boolean isAsync) {
+ SmsLogDO smsLog = new SmsLogDO();
+ if (smsBody.getSmsLogId() != null) {
+ smsLog.setId(smsBody.getSmsLogId());
+ smsLog.setSendStatus(SmsSendStatusEnum.SENDING.getStatus());
+ smsLogMapper.updateById(smsLog);
+ return smsBody.getSmsLogId();
+ } else {
+ SmsChannelPropertyVO property = client.getProperty();
+ SmsTemplateVO smsTemplate = property.getTemplateByTemplateCode(smsBody.getTemplateCode());
+
+ smsLog.setChannelCode(property.getCode())
+ .setChannelId(property.getId())
+ .setTemplateCode(smsTemplate.getCode())
+ .setPhones(JsonUtils.toJsonString(targetPhones))
+ .setContent(StrUtils.replace(smsTemplate.getContent(), smsBody.getParams()));
+
+ if (isAsync) {
+ smsLog.setSendStatus(SmsSendStatusEnum.ASYNC.getStatus());
+ } else {
+ smsLog.setSendStatus(SmsSendStatusEnum.SENDING.getStatus());
+ }
+ smsLogMapper.insert(smsLog);
+ return smsLog.getId();
+ }
+ }
+
+ @Override
+ public void afterSendLog(Long logId, SmsResult> result) {
+ SmsLogDO smsLog = new SmsLogDO();
+ smsLog.setId(logId);
+ if (result.getSuccess()) {
+ smsLog.setSendStatus(SmsSendStatusEnum.SUCCESS.getStatus());
+ } else {
+ smsLog.setSendStatus(SmsSendStatusEnum.FAIL.getStatus());
+ smsLog.setRemark(result.getMessage() + JsonUtils.toJsonString(result.getResult()));
+ }
+ smsLogMapper.updateById(smsLog);
+ }
+
}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SmsServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SmsServiceImpl.java
new file mode 100644
index 000000000..4dc090242
--- /dev/null
+++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SmsServiceImpl.java
@@ -0,0 +1,51 @@
+package cn.iocoder.dashboard.modules.system.service.sms.impl;
+
+import cn.iocoder.dashboard.framework.sms.client.AbstractSmsClient;
+import cn.iocoder.dashboard.framework.sms.core.SmsBody;
+import cn.iocoder.dashboard.framework.sms.core.SmsResult;
+import cn.iocoder.dashboard.modules.system.mq.producer.sms.SmsProducer;
+import cn.iocoder.dashboard.modules.system.service.sms.SmsChannelService;
+import cn.iocoder.dashboard.modules.system.service.sms.SmsLogService;
+import cn.iocoder.dashboard.modules.system.service.sms.SmsService;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+/**
+ * 短信日志Service实现类
+ *
+ * @author zzf
+ * @date 2021/1/25 9:25
+ */
+@Service
+public class SmsServiceImpl implements SmsService {
+
+ @Resource
+ private SmsChannelService channelService;
+
+ @Resource
+ private SmsLogService smsLogService;
+
+ @Resource
+ private SmsProducer smsProducer;
+
+ @Override
+ public SmsResult> send(SmsBody smsBody, List targetPhones) {
+ AbstractSmsClient> client = channelService.getClient(smsBody.getTemplateCode());
+ Long logId = smsLogService.beforeSendLog(smsBody, targetPhones, client, false);
+
+ SmsResult> result = client.send(smsBody, targetPhones);
+
+ smsLogService.afterSendLog(logId, result);
+
+ return result;
+ }
+
+ @Override
+ public void sendAsync(SmsBody smsBody, List targetPhones) {
+ AbstractSmsClient> client = channelService.getClient(smsBody.getTemplateCode());
+ smsLogService.beforeSendLog(smsBody, targetPhones, client, true);
+ smsProducer.sendSmsSendMessage(smsBody, targetPhones);
+ }
+}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/sms/SmsConfiguration.java b/src/main/java/cn/iocoder/dashboard/modules/system/sms/SmsConfiguration.java
deleted file mode 100644
index ffb5887bd..000000000
--- a/src/main/java/cn/iocoder/dashboard/modules/system/sms/SmsConfiguration.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package cn.iocoder.dashboard.modules.system.sms;
-
-import cn.iocoder.dashboard.framework.sms.SmsClient;
-import cn.iocoder.dashboard.framework.sms.SmsClientAdapter;
-import cn.iocoder.dashboard.modules.system.controller.sms.vo.SmsChannelAllVO;
-import cn.iocoder.dashboard.modules.system.service.sms.SmsChannelService;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-import javax.annotation.Resource;
-import java.util.List;
-import java.util.Map;
-
-/**
- * 短信服务配置
- *
- * @author guer
- */
-@Configuration
-@ConditionalOnProperty("sms.enabled")
-public class SmsConfiguration {
-
- @Resource
- private SmsChannelService channelService;
-
- @Bean
- public SmsClientAdapter smsClientWrapper() {
- List smsChannelAllVOList = channelService.listChannelAllEnabledInfo();
- Map> channelId2SmsClientMap = SmsSenderUtils.init(smsChannelAllVOList);
- return new SmsClientAdapter(channelId2SmsClientMap);
- }
-
-}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/sms/SmsSenderUtils.java b/src/main/java/cn/iocoder/dashboard/modules/system/sms/SmsSenderUtils.java
deleted file mode 100644
index ea9c24489..000000000
--- a/src/main/java/cn/iocoder/dashboard/modules/system/sms/SmsSenderUtils.java
+++ /dev/null
@@ -1,143 +0,0 @@
-package cn.iocoder.dashboard.modules.system.sms;
-
-import cn.hutool.core.util.ObjectUtil;
-import cn.iocoder.dashboard.common.enums.SmsChannelEnum;
-import cn.iocoder.dashboard.common.exception.ServiceException;
-import cn.iocoder.dashboard.framework.sms.SmsBody;
-import cn.iocoder.dashboard.framework.sms.SmsClient;
-import cn.iocoder.dashboard.framework.sms.SmsClientAdapter;
-import cn.iocoder.dashboard.framework.sms.SmsResult;
-import cn.iocoder.dashboard.modules.system.controller.sms.vo.SmsChannelAllVO;
-import cn.iocoder.dashboard.modules.system.controller.sms.vo.SmsTemplateVO;
-import cn.iocoder.dashboard.modules.system.sms.client.AliSmsClient;
-import cn.iocoder.dashboard.modules.system.sms.proxy.SmsClientLogProxy;
-
-import java.util.*;
-import java.util.concurrent.ConcurrentHashMap;
-
-import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.*;
-
-/**
- * 短信发送者工厂
- *
- * @author zzf
- * @date 2021/1/25 16:18
- */
-public class SmsSenderUtils {
-
- /**
- * 短信渠道id:短信客户端map
- * key: channelId
- * val: SmsClient
- */
- private static final Map> smsSenderMap = new ConcurrentHashMap<>(8);
-
- /**
- * 短信模板code: 短信渠道id map
- * key: templateCode
- * val: channelId
- */
- private static final Map templateCode2ChannelIdMap = new HashMap<>();
-
- /**
- * 将短信渠道信息初始化成短信客户端
- *
- * @param smsChannelAllVOList 短信渠道信息
- * @return 短信渠道id:短信客户端map
- */
- public synchronized static Map> init(List smsChannelAllVOList) {
- if (ObjectUtil.isEmpty(smsChannelAllVOList)) {
- throw new ServiceException(SMS_CHANNEL_NOT_FOUND);
- }
- addSender(smsChannelAllVOList);
- return smsSenderMap;
- }
-
- /**
- * 重置短信客户端信息
- *
- * @param smsClientAdapter 短信客户端适配器
- * @param smsChannelAllVOList 短信渠道信息集合
- */
- public synchronized static void flush(SmsClientAdapter smsClientAdapter, List smsChannelAllVOList) {
- smsSenderMap.clear();
- smsClientAdapter.flushClient(init(smsChannelAllVOList));
- }
-
- /**
- * 发送短信
- *
- * @param smsClientAdapter 短信客户端适配器
- * @param smsBody 短信内容
- * @param targetPhones 对象手机集合
- * @return 短信发送结果
- */
- public static SmsResult> send(SmsClientAdapter smsClientAdapter, SmsBody smsBody, Collection targetPhones) {
- Long channelId = templateCode2ChannelIdMap.get(smsBody.getCode());
- if (channelId == null) {
- throw new ServiceException(SMS_SENDER_NOT_FOUND);
- }
- return smsClientAdapter.send(channelId, smsBody, targetPhones);
- }
-
- /**
- * 发送短信
- *
- * @param smsClientAdapter 短信客户端适配器
- * @param smsBody 短信内容
- * @param targetPhone 对象手机
- * @return 短信发送结果
- */
- public static SmsResult> send(SmsClientAdapter smsClientAdapter, SmsBody smsBody, String targetPhone) {
- Long channelId = templateCode2ChannelIdMap.get(smsBody.getCode());
- if (channelId == null) {
- throw new ServiceException(SMS_SENDER_NOT_FOUND);
- }
- return smsClientAdapter.send(channelId, smsBody, Collections.singletonList(targetPhone));
- }
-
- /**
- * 发送短信
- *
- * @param smsClientAdapter 短信客户端适配器
- * @param smsBody 短信内容
- * @param targetPhones 对象手机数组
- * @return 短信发送结果
- */
- public static SmsResult> send(SmsClientAdapter smsClientAdapter, SmsBody smsBody, String... targetPhones) {
- Long channelId = templateCode2ChannelIdMap.get(smsBody.getCode());
- if (channelId == null) {
- throw new ServiceException(SMS_SENDER_NOT_FOUND);
- }
- return smsClientAdapter.send(channelId, smsBody, Arrays.asList(targetPhones));
- }
-
-
- private static void addSender(List smsChannelAllVOList) {
- smsChannelAllVOList.forEach(channelAllVO -> addSender(SmsChannelEnum.getByCode(channelAllVO.getCode()), channelAllVO));
- }
-
- private static void addSender(SmsChannelEnum channelEnum, SmsChannelAllVO channelAllVO) {
- if (channelEnum == null) {
- throw new ServiceException(INVALID_CHANNEL_CODE);
- }
- List templateList = channelAllVO.getTemplateList();
- if (ObjectUtil.isEmpty(templateList)) {
- throw new ServiceException(SMS_TEMPLATE_NOT_FOUND);
- }
- SmsClient> aliSmsClient = getSender(channelEnum, channelAllVO);
- templateList.forEach(smsTemplateVO -> templateCode2ChannelIdMap.put(smsTemplateVO.getCode(), channelAllVO.getId()));
- smsSenderMap.put(channelAllVO.getId(), aliSmsClient);
- }
-
- private static SmsClient> getSender(SmsChannelEnum channelEnum, SmsChannelAllVO channelAllVO) {
- switch (channelEnum) {
- case ALI:
- return new SmsClientLogProxy<>(new AliSmsClient(channelAllVO));
- // TODO fill more channel
- default:
- break;
- }
- throw new ServiceException(SMS_SENDER_NOT_FOUND);
- }
-}
diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/sms/proxy/SmsClientLogProxy.java b/src/main/java/cn/iocoder/dashboard/modules/system/sms/proxy/SmsClientLogProxy.java
deleted file mode 100644
index a7d201e6f..000000000
--- a/src/main/java/cn/iocoder/dashboard/modules/system/sms/proxy/SmsClientLogProxy.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package cn.iocoder.dashboard.modules.system.sms.proxy;
-
-import cn.iocoder.dashboard.framework.sms.SmsBody;
-import cn.iocoder.dashboard.framework.sms.SmsClient;
-import cn.iocoder.dashboard.framework.sms.SmsResult;
-import cn.iocoder.dashboard.util.json.JsonUtils;
-import lombok.extern.slf4j.Slf4j;
-
-import java.util.Collection;
-
-/**
- * 消息父接口
- *
- * @author zzf
- * @date 2021/1/22 15:46
- */
-@Slf4j
-public class SmsClientLogProxy implements SmsClient {
-
- private final SmsClient smsClient;
-
- @Override
- public SmsResult send(SmsBody msgBody, Collection targets) {
- log.debug("ready send sms, body: {}, target: {}", JsonUtils.toJsonString(msgBody), targets);
-
- SmsResult resultBody = smsClient.send(msgBody, targets);
-
- if (resultBody.getSuccess()) {
- //
- } else {
- log.warn("send sms fail, body: {}, target: {}, resultBody: {}",
- JsonUtils.toJsonString(msgBody),
- targets,
- JsonUtils.toJsonString(resultBody)
- );
- }
- return resultBody;
- }
-
- @Override
- public SmsResult sendAsync(SmsBody msgBody, Collection targets) {
- return send(msgBody, targets);
- }
-
- public SmsClientLogProxy(SmsClient smsClient) {
- this.smsClient = smsClient;
- }
-}
diff --git a/src/main/java/cn/iocoder/dashboard/util/string/StrUtils.java b/src/main/java/cn/iocoder/dashboard/util/string/StrUtils.java
index 5e98d915b..e0ca605a4 100644
--- a/src/main/java/cn/iocoder/dashboard/util/string/StrUtils.java
+++ b/src/main/java/cn/iocoder/dashboard/util/string/StrUtils.java
@@ -1,7 +1,10 @@
package cn.iocoder.dashboard.util.string;
+import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
+import java.util.Map;
+
/**
* 字符串工具类
*
@@ -13,4 +16,22 @@ public class StrUtils {
return StrUtil.maxLength(str, maxLength - 3); // -3 的原因,是该方法会补充 ... 恰好
}
+ /**
+ * 指定字符串的
+ * @param str
+ * @param replaceMap
+ * @return
+ */
+ public static String replace(String str, Map