Commit df8bda53e867f5c4d5b8b55157ca5b8163d661a6
1 parent
842496a5
增加短信功能实现
Showing
42 changed files
with
1660 additions
and
72 deletions
pom.xml
| @@ -222,6 +222,18 @@ | @@ -222,6 +222,18 @@ | ||
| 222 | <version>${easyexcel.verion}</version> | 222 | <version>${easyexcel.verion}</version> |
| 223 | </dependency> | 223 | </dependency> |
| 224 | 224 | ||
| 225 | + <dependency> | ||
| 226 | + <groupId>com.aliyun</groupId> | ||
| 227 | + <artifactId>aliyun-java-sdk-core</artifactId> | ||
| 228 | + <version>4.5.18</version> | ||
| 229 | + </dependency> | ||
| 230 | + | ||
| 231 | + <dependency> | ||
| 232 | + <groupId>com.aliyun</groupId> | ||
| 233 | + <artifactId>aliyun-java-sdk-dysmsapi</artifactId> | ||
| 234 | + <version>2.1.0</version> | ||
| 235 | + </dependency> | ||
| 236 | + | ||
| 225 | </dependencies> | 237 | </dependencies> |
| 226 | 238 | ||
| 227 | 239 |
sql/ruoyi-vue-pro.sql
| @@ -884,4 +884,77 @@ INSERT INTO `sys_user_role` VALUES (5, 100, 1, '', NULL, '', NULL, b'0'); | @@ -884,4 +884,77 @@ INSERT INTO `sys_user_role` VALUES (5, 100, 1, '', NULL, '', NULL, b'0'); | ||
| 884 | INSERT INTO `sys_user_role` VALUES (6, 100, 2, '', NULL, '', NULL, b'0'); | 884 | INSERT INTO `sys_user_role` VALUES (6, 100, 2, '', NULL, '', NULL, b'0'); |
| 885 | COMMIT; | 885 | COMMIT; |
| 886 | 886 | ||
| 887 | + | ||
| 888 | +-- ---------------------------- | ||
| 889 | +-- Table structure for sms_channel | ||
| 890 | +-- ---------------------------- | ||
| 891 | +DROP TABLE IF EXISTS `sms_channel`; | ||
| 892 | +CREATE TABLE `sms_channel` ( | ||
| 893 | + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增编号', | ||
| 894 | + `code` varchar(50) not null COMMENT '编码(来自枚举类 阿里、华为、七牛等)', | ||
| 895 | + `api_key` varchar(100) NOT NULL COMMENT '账号id', -- add | ||
| 896 | + `api_secret` varchar(100) NOT NULL COMMENT '账号秘钥', -- add | ||
| 897 | + `priority` tinyint(8) NOT NULL default 1 COMMENT '优先级(存在多个签名时,选择值最小的,渠道不可用时,按优先级从小到大切换)', -- add | ||
| 898 | + `api_signature_id` varchar(100) NOT NULL COMMENT '实际渠道签名唯一标识', | ||
| 899 | + `name` varchar(50) not null COMMENT '名称', | ||
| 900 | + `signature` varchar(50) not null COMMENT '签名值', | ||
| 901 | + `remark` varchar(200) NOT NULL COMMENT '备注', | ||
| 902 | + | ||
| 903 | + `status` tinyint(4) NOT NULL default 0 COMMENT '启用状态(0正常 1停用)', | ||
| 904 | + `create_by` varchar(64) not null DEFAULT '' COMMENT '创建者', | ||
| 905 | + `create_time` datetime DEFAULT NULL COMMENT '创建时间', | ||
| 906 | + `update_by` varchar(64) DEFAULT '' COMMENT '更新者', | ||
| 907 | + `update_time` datetime DEFAULT NULL COMMENT '更新时间', | ||
| 908 | + `deleted` bit(1) DEFAULT b'0' COMMENT '是否删除', | ||
| 909 | + PRIMARY KEY (`id`) USING BTREE | ||
| 910 | +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='短信渠道'; | ||
| 911 | +/* | ||
| 912 | + 优先级值一样时,按照id顺序取值 | ||
| 913 | +*/ | ||
| 914 | + | ||
| 915 | +-- ---------------------------- | ||
| 916 | +-- Table structure for sms_template | ||
| 917 | +-- ---------------------------- | ||
| 918 | +DROP TABLE IF EXISTS `sms_template`; | ||
| 919 | +CREATE TABLE `sms_template` ( | ||
| 920 | + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增编号', | ||
| 921 | + `channel_code` varchar(50) not null COMMENT '短信渠道编码(来自枚举类)', | ||
| 922 | + `channel_id` bigint(20) not null COMMENT '短信渠道id (对于前端来说就是绑定一个签名)', -- add | ||
| 923 | + `type` tinyint(4) NOT NULL default 1 COMMENT '消息类型 [0验证码 1短信通知 2推广短信 3国际/港澳台消息]', | ||
| 924 | + `biz_code` varchar(50) not null COMMENT '业务编码(来自数据字典, 用户自定义业务场景 一个场景可以有多个模板)', -- add | ||
| 925 | + `priority` tinyint(8) NOT NULL default 1 COMMENT '优先级(默认直接继承渠道表的,逻辑也与渠道表的一致,可以针对每个biz_code进行修改)',-- add | ||
| 926 | + `code` varchar(50) not null COMMENT '编码', | ||
| 927 | + `name` varchar(50) not null COMMENT '名称', | ||
| 928 | + `api_template_id` varchar(100) NOT NULL COMMENT '实际渠道模板唯一标识', | ||
| 929 | + `content` varchar(1000) NOT NULL DEFAULT '' COMMENT '内容', | ||
| 930 | + `params` varchar(200) NOT NULL DEFAULT '' COMMENT '参数数组(自动根据内容生成)', -- add | ||
| 931 | + `remark` varchar(200) NOT NULL COMMENT '备注', | ||
| 932 | + | ||
| 933 | + `status` tinyint(4) NOT NULL default 0 COMMENT '启用状态(0正常 1停用)', | ||
| 934 | + `create_by` varchar(64) not null DEFAULT '' COMMENT '创建者', | ||
| 935 | + `create_time` datetime DEFAULT NULL COMMENT '创建时间', | ||
| 936 | + `update_by` varchar(64) DEFAULT '' COMMENT '更新者', | ||
| 937 | + `update_time` datetime DEFAULT NULL COMMENT '更新时间', | ||
| 938 | + `deleted` bit(1) DEFAULT b'0' COMMENT '是否删除', | ||
| 939 | + PRIMARY KEY (`id`) USING BTREE | ||
| 940 | +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='短信模板'; | ||
| 941 | + | ||
| 942 | +-- ---------------------------- | ||
| 943 | +-- Table structure for sms_log | ||
| 944 | +-- ---------------------------- | ||
| 945 | +DROP TABLE IF EXISTS `sms_log`; | ||
| 946 | +CREATE TABLE `sms_log` ( | ||
| 947 | + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增编号', | ||
| 948 | + `channel_code` varchar(50) not null COMMENT '短信渠道编码(来自枚举类)', | ||
| 949 | + `api_sms_id` varchar(50) not null COMMENT '实际渠道短信唯一标识', | ||
| 950 | + `template_id` bigint(20) NOT NULL COMMENT '模板id', | ||
| 951 | + `phone` char(11) not null COMMENT '手机号', | ||
| 952 | + `content` varchar(1000) NOT NULL DEFAULT '' COMMENT '内容', | ||
| 953 | + `remark` varchar(200) NOT NULL COMMENT '备注', | ||
| 954 | + `send_status` tinyint(4) NOT NULL default 0 COMMENT '发送状态(0发送中 1成功 2失败)', | ||
| 955 | + `create_by` varchar(64) not null DEFAULT '' COMMENT '创建者', | ||
| 956 | + `create_time` datetime DEFAULT NULL COMMENT '创建时间', | ||
| 957 | + PRIMARY KEY (`id`) USING BTREE | ||
| 958 | +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='短信日志'; | ||
| 959 | + | ||
| 887 | SET FOREIGN_KEY_CHECKS = 1; | 960 | SET FOREIGN_KEY_CHECKS = 1; |
src/main/java/cn/iocoder/dashboard/DashboardApplication.java
| 1 | -package cn.iocoder.dashboard; | ||
| 2 | - | ||
| 3 | -import de.codecentric.boot.admin.server.config.EnableAdminServer; | ||
| 4 | -import org.springframework.boot.SpringApplication; | ||
| 5 | -import org.springframework.boot.autoconfigure.SpringBootApplication; | ||
| 6 | - | ||
| 7 | -@SpringBootApplication | ||
| 8 | -@EnableAdminServer | ||
| 9 | -public class DashboardApplication { | ||
| 10 | - | ||
| 11 | - public static void main(String[] args) { | ||
| 12 | - SpringApplication.run(DashboardApplication.class, args); | ||
| 13 | - } | ||
| 14 | - | ||
| 15 | -} | 1 | +//package cn.iocoder.dashboard; |
| 2 | +// | ||
| 3 | +//import de.codecentric.boot.admin.server.config.EnableAdminServer; | ||
| 4 | +//import org.springframework.boot.SpringApplication; | ||
| 5 | +//import org.springframework.boot.autoconfigure.SpringBootApplication; | ||
| 6 | +// | ||
| 7 | +//@SpringBootApplication | ||
| 8 | +//@EnableAdminServer | ||
| 9 | +//public class DashboardApplication { | ||
| 10 | +// | ||
| 11 | +// public static void main(String[] args) { | ||
| 12 | +// SpringApplication.run(DashboardApplication.class, args); | ||
| 13 | +// } | ||
| 14 | +// | ||
| 15 | +//} |
src/main/java/cn/iocoder/dashboard/common/enums/SmsChannelEnum.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.common.enums; | ||
| 2 | + | ||
| 3 | +import lombok.AllArgsConstructor; | ||
| 4 | +import lombok.Getter; | ||
| 5 | + | ||
| 6 | +/** | ||
| 7 | + * 短信渠道枚举 | ||
| 8 | + * | ||
| 9 | + * @author zzf | ||
| 10 | + * @date 2021/1/25 10:56 | ||
| 11 | + */ | ||
| 12 | +@Getter | ||
| 13 | +@AllArgsConstructor | ||
| 14 | +public enum SmsChannelEnum { | ||
| 15 | + | ||
| 16 | + ALI("ALI", "阿里"), | ||
| 17 | + HUA_WEI("HUA_WEI", "华为"), | ||
| 18 | + QI_NIU("QI_NIU", "七牛"), | ||
| 19 | + TEN_XUN("TEN_XUN", "腾讯"); | ||
| 20 | + | ||
| 21 | + private final String code; | ||
| 22 | + | ||
| 23 | + private final String name; | ||
| 24 | + | ||
| 25 | + public static SmsChannelEnum getByCode(String code) { | ||
| 26 | + for (SmsChannelEnum value : SmsChannelEnum.values()) { | ||
| 27 | + if (value.getCode().equals(code)) { | ||
| 28 | + return value; | ||
| 29 | + } | ||
| 30 | + } | ||
| 31 | + return null; | ||
| 32 | + } | ||
| 33 | +} |
src/main/java/cn/iocoder/dashboard/framework/msg/sms/SmsBody.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.framework.msg.sms; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.dashboard.util.json.JsonUtils; | ||
| 4 | +import lombok.Data; | ||
| 5 | + | ||
| 6 | +import java.util.Map; | ||
| 7 | + | ||
| 8 | +/** | ||
| 9 | + * 消息内容实体类 | ||
| 10 | + */ | ||
| 11 | +@Data | ||
| 12 | +public class SmsBody { | ||
| 13 | + | ||
| 14 | + /** | ||
| 15 | + * 模板编码 | ||
| 16 | + */ | ||
| 17 | + private String code; | ||
| 18 | + | ||
| 19 | + /** | ||
| 20 | + * 参数列表 | ||
| 21 | + */ | ||
| 22 | + private Map<String, String> params; | ||
| 23 | + | ||
| 24 | + public String getParamsStr() { | ||
| 25 | + return JsonUtils.toJsonString(params); | ||
| 26 | + } | ||
| 27 | + | ||
| 28 | +} |
src/main/java/cn/iocoder/dashboard/framework/msg/sms/SmsResult.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.framework.msg.sms; | ||
| 2 | + | ||
| 3 | +import lombok.Data; | ||
| 4 | + | ||
| 5 | +import java.io.Serializable; | ||
| 6 | + | ||
| 7 | +/** | ||
| 8 | + * 消息内容实体类 | ||
| 9 | + */ | ||
| 10 | +@Data | ||
| 11 | +public class SmsResult<T> implements Serializable { | ||
| 12 | + | ||
| 13 | + /** | ||
| 14 | + * 是否成功 | ||
| 15 | + */ | ||
| 16 | + private Boolean success; | ||
| 17 | + | ||
| 18 | + /** | ||
| 19 | + * 提示 | ||
| 20 | + */ | ||
| 21 | + private String message; | ||
| 22 | + | ||
| 23 | + /** | ||
| 24 | + * 返回值 | ||
| 25 | + */ | ||
| 26 | + private T result; | ||
| 27 | +} |
src/main/java/cn/iocoder/dashboard/framework/msg/sms/SmsSender.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.framework.msg.sms; | ||
| 2 | + | ||
| 3 | +import org.apache.commons.lang3.StringUtils; | ||
| 4 | + | ||
| 5 | +import java.util.Arrays; | ||
| 6 | +import java.util.Collection; | ||
| 7 | +import java.util.Collections; | ||
| 8 | + | ||
| 9 | +/** | ||
| 10 | + * 短信父接口 | ||
| 11 | + * | ||
| 12 | + * @author zzf | ||
| 13 | + * @date 2021/1/25 14:14 | ||
| 14 | + */ | ||
| 15 | +public interface SmsSender<R> { | ||
| 16 | + | ||
| 17 | + /** | ||
| 18 | + * 发送通知 | ||
| 19 | + * | ||
| 20 | + * @param msgBody 通知内容 | ||
| 21 | + * @param targets 发送对象列表 | ||
| 22 | + * @return 是否发送成功 | ||
| 23 | + */ | ||
| 24 | + SmsResult<R> send(SmsBody msgBody, Collection<String> targets); | ||
| 25 | + | ||
| 26 | + /** | ||
| 27 | + * 发送通知 | ||
| 28 | + * | ||
| 29 | + * @param msgBody 通知内容 | ||
| 30 | + * @param target 发送对象列表 | ||
| 31 | + * @return 是否发送成功 | ||
| 32 | + */ | ||
| 33 | + default SmsResult<R> send(SmsBody msgBody, String target) { | ||
| 34 | + if (StringUtils.isBlank(target)) { | ||
| 35 | + return failResult(); | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + return send(msgBody, Collections.singletonList(target)); | ||
| 39 | + } | ||
| 40 | + | ||
| 41 | + /** | ||
| 42 | + * 发送通知 | ||
| 43 | + * | ||
| 44 | + * @param msgBody 通知内容 | ||
| 45 | + * @param targets 发送对象列表 | ||
| 46 | + * @return 是否发送成功 | ||
| 47 | + */ | ||
| 48 | + default SmsResult<R> send(SmsBody msgBody, String... targets) { | ||
| 49 | + if (targets == null) { | ||
| 50 | + return failResult(); | ||
| 51 | + } | ||
| 52 | + | ||
| 53 | + return send(msgBody, Arrays.asList(targets)); | ||
| 54 | + } | ||
| 55 | + | ||
| 56 | + default SmsResult<R> failResult() { | ||
| 57 | + SmsResult<R> resultBody = new SmsResult<>(); | ||
| 58 | + resultBody.setSuccess(false); | ||
| 59 | + return resultBody; | ||
| 60 | + } | ||
| 61 | + | ||
| 62 | + default SmsResult<R> failResult(String message) { | ||
| 63 | + SmsResult<R> resultBody = failResult(); | ||
| 64 | + resultBody.setMessage(message); | ||
| 65 | + return resultBody; | ||
| 66 | + } | ||
| 67 | +} | ||
| 0 | \ No newline at end of file | 68 | \ No newline at end of file |
src/main/java/cn/iocoder/dashboard/framework/msg/sms/config/SmsConfiguration.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.framework.msg.sms.config; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.dashboard.framework.msg.sms.factory.DefaultSmsSenderFactory; | ||
| 4 | +import cn.iocoder.dashboard.framework.msg.sms.intercepter.AbstractSmsIntercepterChain; | ||
| 5 | +import cn.iocoder.dashboard.framework.msg.sms.intercepter.DefaultSmsIntercepterChain; | ||
| 6 | +import cn.iocoder.dashboard.framework.msg.sms.intercepter.SmsLogIntercepter; | ||
| 7 | +import cn.iocoder.dashboard.modules.msg.controller.sms.vo.SmsChannelAllVO; | ||
| 8 | +import cn.iocoder.dashboard.modules.msg.service.sms.SmsChannelService; | ||
| 9 | +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | ||
| 10 | +import org.springframework.context.annotation.Bean; | ||
| 11 | +import org.springframework.context.annotation.Configuration; | ||
| 12 | + | ||
| 13 | +import javax.annotation.Resource; | ||
| 14 | +import java.util.List; | ||
| 15 | + | ||
| 16 | +/** | ||
| 17 | + * 短信服务配置 | ||
| 18 | + * | ||
| 19 | + * @author guer | ||
| 20 | + */ | ||
| 21 | +@Configuration | ||
| 22 | +@ConditionalOnProperty("sms.enabled") | ||
| 23 | +public class SmsConfiguration { | ||
| 24 | + | ||
| 25 | + @Resource | ||
| 26 | + private SmsChannelService channelService; | ||
| 27 | + | ||
| 28 | + | ||
| 29 | + @Bean | ||
| 30 | + public AbstractSmsIntercepterChain smsIntercepterChain() { | ||
| 31 | + DefaultSmsIntercepterChain intercepterChain = new DefaultSmsIntercepterChain(); | ||
| 32 | + //添加拦截器 | ||
| 33 | + intercepterChain.addSmsIntercepter(new SmsLogIntercepter()); | ||
| 34 | + return intercepterChain; | ||
| 35 | + } | ||
| 36 | + | ||
| 37 | + @Bean | ||
| 38 | + public DefaultSmsSenderFactory smsSenderFactory(AbstractSmsIntercepterChain intercepterChain) { | ||
| 39 | + DefaultSmsSenderFactory defaultSmsSenderFactory = new DefaultSmsSenderFactory(); | ||
| 40 | + List<SmsChannelAllVO> smsChannelAllVOList = channelService.listChannelAllEnabledInfo(); | ||
| 41 | + //初始化渠道、模板信息 | ||
| 42 | + defaultSmsSenderFactory.init(smsChannelAllVOList); | ||
| 43 | + //注入拦截器链 | ||
| 44 | + defaultSmsSenderFactory.setIntercepterChain(intercepterChain); | ||
| 45 | + return defaultSmsSenderFactory; | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | +} |
src/main/java/cn/iocoder/dashboard/framework/msg/sms/factory/DefaultSmsSenderFactory.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.framework.msg.sms.factory; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.util.ObjectUtil; | ||
| 4 | +import cn.iocoder.dashboard.common.enums.SmsChannelEnum; | ||
| 5 | +import cn.iocoder.dashboard.common.exception.ServiceException; | ||
| 6 | +import cn.iocoder.dashboard.framework.msg.sms.SmsSender; | ||
| 7 | +import cn.iocoder.dashboard.framework.msg.sms.impl.ali.AliSmsSender; | ||
| 8 | +import cn.iocoder.dashboard.framework.msg.sms.intercepter.AbstractSmsIntercepterChain; | ||
| 9 | +import cn.iocoder.dashboard.framework.msg.sms.proxy.DefaultSmsSenderProxy; | ||
| 10 | +import cn.iocoder.dashboard.modules.msg.controller.sms.vo.SmsChannelAllVO; | ||
| 11 | +import cn.iocoder.dashboard.modules.msg.controller.sms.vo.SmsTemplateVO; | ||
| 12 | +import lombok.Setter; | ||
| 13 | + | ||
| 14 | +import java.util.List; | ||
| 15 | +import java.util.concurrent.ConcurrentHashMap; | ||
| 16 | +import java.util.concurrent.locks.Lock; | ||
| 17 | +import java.util.concurrent.locks.ReadWriteLock; | ||
| 18 | +import java.util.concurrent.locks.ReentrantReadWriteLock; | ||
| 19 | + | ||
| 20 | +import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.*; | ||
| 21 | + | ||
| 22 | +/** | ||
| 23 | + * 短信发送者工厂 | ||
| 24 | + * | ||
| 25 | + * @author zzf | ||
| 26 | + * @date 2021/1/25 16:18 | ||
| 27 | + */ | ||
| 28 | +public class DefaultSmsSenderFactory { | ||
| 29 | + | ||
| 30 | + /** | ||
| 31 | + * sender索引 | ||
| 32 | + * key: {@link SmsTemplateVO#getBizCode()} | ||
| 33 | + * value: {@link SmsSender} | ||
| 34 | + */ | ||
| 35 | + private final ConcurrentHashMap<String, SmsSender<?>> bizCode2SenderMap = new ConcurrentHashMap<>(8); | ||
| 36 | + | ||
| 37 | + /** | ||
| 38 | + * sender索引 | ||
| 39 | + * key: {@link SmsTemplateVO#getCode()} | ||
| 40 | + * value: {@link SmsSender} | ||
| 41 | + */ | ||
| 42 | + private final ConcurrentHashMap<String, SmsSender<?>> templateCode2SenderMap = new ConcurrentHashMap<>(8); | ||
| 43 | + | ||
| 44 | + | ||
| 45 | + @Setter | ||
| 46 | + private AbstractSmsIntercepterChain intercepterChain; | ||
| 47 | + | ||
| 48 | + /** | ||
| 49 | + * 读写锁 | ||
| 50 | + */ | ||
| 51 | + private final ReadWriteLock lock = new ReentrantReadWriteLock(); | ||
| 52 | + private final Lock readLock = lock.readLock(); | ||
| 53 | + private final Lock writeLock = lock.writeLock(); | ||
| 54 | + | ||
| 55 | + | ||
| 56 | + public void init(List<SmsChannelAllVO> smsChannelAllVOList) { | ||
| 57 | + if (ObjectUtil.isEmpty(smsChannelAllVOList)) { | ||
| 58 | + throw new ServiceException(SMS_CHANNEL_NOT_FOUND); | ||
| 59 | + } | ||
| 60 | + try { | ||
| 61 | + writeLock.lock(); | ||
| 62 | + addSender(smsChannelAllVOList); | ||
| 63 | + } finally { | ||
| 64 | + writeLock.unlock(); | ||
| 65 | + } | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | + public SmsSender<?> getSenderByBizCode(String bizCode) { | ||
| 69 | + return getSmsSender(bizCode, bizCode2SenderMap); | ||
| 70 | + } | ||
| 71 | + | ||
| 72 | + public SmsSender<?> getSenderByTemplateCode(String templateCode) { | ||
| 73 | + return getSmsSender(templateCode, templateCode2SenderMap); | ||
| 74 | + } | ||
| 75 | + | ||
| 76 | + private SmsSender<?> getSmsSender(String templateCode, ConcurrentHashMap<String, SmsSender<?>> cacheMap) { | ||
| 77 | + try { | ||
| 78 | + readLock.lock(); | ||
| 79 | + SmsSender<?> smsSender = cacheMap.get(templateCode); | ||
| 80 | + if (smsSender == null) { | ||
| 81 | + throw new ServiceException(SMS_SENDER_NOT_FOUND); | ||
| 82 | + } | ||
| 83 | + return smsSender; | ||
| 84 | + } finally { | ||
| 85 | + readLock.unlock(); | ||
| 86 | + } | ||
| 87 | + } | ||
| 88 | + | ||
| 89 | + public void flush(List<SmsChannelAllVO> smsChannelAllVOList) { | ||
| 90 | + try { | ||
| 91 | + writeLock.lock(); | ||
| 92 | + bizCode2SenderMap.clear(); | ||
| 93 | + templateCode2SenderMap.clear(); | ||
| 94 | + addSender(smsChannelAllVOList); | ||
| 95 | + } finally { | ||
| 96 | + writeLock.unlock(); | ||
| 97 | + } | ||
| 98 | + } | ||
| 99 | + | ||
| 100 | + | ||
| 101 | + private void addSender(List<SmsChannelAllVO> smsChannelAllVOList) { | ||
| 102 | + smsChannelAllVOList.forEach(channelAllVO -> addSender(SmsChannelEnum.getByCode(channelAllVO.getCode()), channelAllVO)); | ||
| 103 | + } | ||
| 104 | + | ||
| 105 | + private void addSender(SmsChannelEnum channelEnum, SmsChannelAllVO channelAllVO) { | ||
| 106 | + if (channelEnum == null) { | ||
| 107 | + throw new ServiceException(INVALID_CHANNEL_CODE); | ||
| 108 | + } | ||
| 109 | + List<SmsTemplateVO> templateList = channelAllVO.getTemplateList(); | ||
| 110 | + if (ObjectUtil.isEmpty(templateList)) { | ||
| 111 | + throw new ServiceException(SMS_TEMPLATE_NOT_FOUND); | ||
| 112 | + } | ||
| 113 | + | ||
| 114 | + SmsSender<?> aliSmsSender = getSender(channelEnum, channelAllVO); | ||
| 115 | + | ||
| 116 | + | ||
| 117 | + templateList.forEach(smsTemplateVO -> { | ||
| 118 | + bizCode2SenderMap.put(smsTemplateVO.getBizCode(), aliSmsSender); | ||
| 119 | + templateCode2SenderMap.put(smsTemplateVO.getCode(), aliSmsSender); | ||
| 120 | + }); | ||
| 121 | + } | ||
| 122 | + | ||
| 123 | + private SmsSender<?> getSender(SmsChannelEnum channelEnum, SmsChannelAllVO channelAllVO) { | ||
| 124 | + switch (channelEnum) { | ||
| 125 | + case ALI: | ||
| 126 | + return new DefaultSmsSenderProxy<>(new AliSmsSender(channelAllVO), intercepterChain); | ||
| 127 | + // TODO fill more channel | ||
| 128 | + default: | ||
| 129 | + break; | ||
| 130 | + } | ||
| 131 | + throw new ServiceException(SMS_SENDER_NOT_FOUND); | ||
| 132 | + } | ||
| 133 | + | ||
| 134 | + | ||
| 135 | + | ||
| 136 | + | ||
| 137 | +} |
src/main/java/cn/iocoder/dashboard/framework/msg/sms/impl/ali/AliSmsSender.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.framework.msg.sms.impl.ali; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.dashboard.framework.msg.sms.SmsBody; | ||
| 4 | +import cn.iocoder.dashboard.framework.msg.sms.SmsResult; | ||
| 5 | +import cn.iocoder.dashboard.framework.msg.sms.SmsSender; | ||
| 6 | +import cn.iocoder.dashboard.modules.msg.controller.sms.vo.SmsChannelAllVO; | ||
| 7 | +import com.aliyuncs.DefaultAcsClient; | ||
| 8 | +import com.aliyuncs.IAcsClient; | ||
| 9 | +import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest; | ||
| 10 | +import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse; | ||
| 11 | +import com.aliyuncs.http.MethodType; | ||
| 12 | +import com.aliyuncs.profile.DefaultProfile; | ||
| 13 | +import com.aliyuncs.profile.IClientProfile; | ||
| 14 | +import lombok.extern.slf4j.Slf4j; | ||
| 15 | +import org.apache.commons.lang3.StringUtils; | ||
| 16 | + | ||
| 17 | +import java.util.Collection; | ||
| 18 | + | ||
| 19 | +/** | ||
| 20 | + * 阿里短信实现类 | ||
| 21 | + * | ||
| 22 | + * @author zzf | ||
| 23 | + * @date 2021/1/25 14:17 | ||
| 24 | + */ | ||
| 25 | +@Slf4j | ||
| 26 | +public class AliSmsSender implements SmsSender<SendSmsResponse> { | ||
| 27 | + | ||
| 28 | + private static final String OK = "OK"; | ||
| 29 | + | ||
| 30 | + private static final String PRODUCT = "Dysmsapi"; | ||
| 31 | + | ||
| 32 | + private static final String DOMAIN = "dysmsapi.aliyuncs.com"; | ||
| 33 | + | ||
| 34 | + private static final String ENDPOINT = "cn-hangzhou"; | ||
| 35 | + | ||
| 36 | + private final SmsChannelAllVO channelVO; | ||
| 37 | + | ||
| 38 | + private final IAcsClient acsClient; | ||
| 39 | + | ||
| 40 | + /** | ||
| 41 | + * 构造阿里云短信发送处理 | ||
| 42 | + * | ||
| 43 | + * @param channelVO 阿里云短信配置 | ||
| 44 | + */ | ||
| 45 | + public AliSmsSender(SmsChannelAllVO channelVO) { | ||
| 46 | + | ||
| 47 | + this.channelVO = channelVO; | ||
| 48 | + | ||
| 49 | + String accessKeyId = channelVO.getApiKey(); | ||
| 50 | + String accessKeySecret = channelVO.getApiSecret(); | ||
| 51 | + | ||
| 52 | + IClientProfile profile = DefaultProfile.getProfile(ENDPOINT, accessKeyId, accessKeySecret); | ||
| 53 | + DefaultProfile.addEndpoint(ENDPOINT, PRODUCT, DOMAIN); | ||
| 54 | + | ||
| 55 | + acsClient = new DefaultAcsClient(profile); | ||
| 56 | + } | ||
| 57 | + | ||
| 58 | + | ||
| 59 | + @Override | ||
| 60 | + public SmsResult<SendSmsResponse> send(SmsBody msgBody, Collection<String> targets) { | ||
| 61 | + SendSmsRequest request = new SendSmsRequest(); | ||
| 62 | + request.setSysMethod(MethodType.POST); | ||
| 63 | + request.setPhoneNumbers(StringUtils.join(targets, ",")); | ||
| 64 | + request.setSignName(channelVO.getApiSignatureId()); | ||
| 65 | + request.setTemplateCode(channelVO.getTemplateByTemplateCode(msgBody.getCode()).getApiTemplateId()); | ||
| 66 | + request.setTemplateParam(msgBody.getParamsStr()); | ||
| 67 | + | ||
| 68 | + try { | ||
| 69 | + SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request); | ||
| 70 | + | ||
| 71 | + boolean result = OK.equals(sendSmsResponse.getCode()); | ||
| 72 | + if (!result) { | ||
| 73 | + log.debug("send fail[code={}, message={}]", sendSmsResponse.getCode(), sendSmsResponse.getMessage()); | ||
| 74 | + } | ||
| 75 | + SmsResult<SendSmsResponse> resultBody = new SmsResult<>(); | ||
| 76 | + resultBody.setSuccess(result); | ||
| 77 | + resultBody.setResult(sendSmsResponse); | ||
| 78 | + return resultBody; | ||
| 79 | + } catch (Exception e) { | ||
| 80 | + log.debug(e.getMessage(), e); | ||
| 81 | + } | ||
| 82 | + | ||
| 83 | + return failResult(); | ||
| 84 | + } | ||
| 85 | + | ||
| 86 | +} |
src/main/java/cn/iocoder/dashboard/framework/msg/sms/intercepter/AbstractSmsIntercepterChain.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.framework.msg.sms.intercepter; | ||
| 2 | + | ||
| 3 | +import lombok.Getter; | ||
| 4 | + | ||
| 5 | +import java.util.ArrayList; | ||
| 6 | +import java.util.Collections; | ||
| 7 | +import java.util.List; | ||
| 8 | + | ||
| 9 | +/** | ||
| 10 | + * 消息父接口 | ||
| 11 | + * | ||
| 12 | + * @author zzf | ||
| 13 | + * @date 2021/1/22 15:46 | ||
| 14 | + */ | ||
| 15 | +public abstract class AbstractSmsIntercepterChain { | ||
| 16 | + | ||
| 17 | + @Getter | ||
| 18 | + protected final List<SmsIntercepter> intercepterList = new ArrayList<>(8); | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + /** | ||
| 22 | + * 添加短信拦截器 | ||
| 23 | + * | ||
| 24 | + * @param smsIntercepter 短信拦截器 | ||
| 25 | + */ | ||
| 26 | + public void addSmsIntercepter(SmsIntercepter smsIntercepter) { | ||
| 27 | + addSmsIntercepter(Collections.singletonList(smsIntercepter)); | ||
| 28 | + } | ||
| 29 | + | ||
| 30 | + /** | ||
| 31 | + * 添加短信拦截器 | ||
| 32 | + * | ||
| 33 | + * @param smsIntercepterList 短信拦截器数组 | ||
| 34 | + */ | ||
| 35 | + abstract void addSmsIntercepter(List<SmsIntercepter> smsIntercepterList); | ||
| 36 | + | ||
| 37 | + | ||
| 38 | +} |
src/main/java/cn/iocoder/dashboard/framework/msg/sms/intercepter/DefaultSmsIntercepterChain.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.framework.msg.sms.intercepter; | ||
| 2 | + | ||
| 3 | +import java.util.Comparator; | ||
| 4 | +import java.util.List; | ||
| 5 | + | ||
| 6 | +/** | ||
| 7 | + * 消息父接口 | ||
| 8 | + * | ||
| 9 | + * @author zzf | ||
| 10 | + * @date 2021/1/22 15:46 | ||
| 11 | + */ | ||
| 12 | +public class DefaultSmsIntercepterChain extends AbstractSmsIntercepterChain { | ||
| 13 | + | ||
| 14 | + @Override | ||
| 15 | + public void addSmsIntercepter(List<SmsIntercepter> smsIntercepterList) { | ||
| 16 | + intercepterList.addAll(smsIntercepterList); | ||
| 17 | + //排序 | ||
| 18 | + intercepterList.sort(Comparator.comparingInt(SmsIntercepter::getOrder)); | ||
| 19 | + } | ||
| 20 | +} |
src/main/java/cn/iocoder/dashboard/framework/msg/sms/intercepter/SmsIntercepter.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.framework.msg.sms.intercepter; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.dashboard.framework.msg.sms.SmsBody; | ||
| 4 | +import cn.iocoder.dashboard.framework.msg.sms.SmsResult; | ||
| 5 | + | ||
| 6 | +import java.util.Collection; | ||
| 7 | + | ||
| 8 | +/** | ||
| 9 | + * 消息父接口 | ||
| 10 | + * | ||
| 11 | + * @author zzf | ||
| 12 | + * @date 2021/1/22 15:46 | ||
| 13 | + */ | ||
| 14 | +public interface SmsIntercepter { | ||
| 15 | + | ||
| 16 | + /** | ||
| 17 | + * 监听发送前 | ||
| 18 | + * | ||
| 19 | + * @param msgBody 消息体 | ||
| 20 | + * @param targets 发送对象数组 | ||
| 21 | + */ | ||
| 22 | + void beforeSender(SmsBody msgBody, Collection<String> targets); | ||
| 23 | + | ||
| 24 | + /** | ||
| 25 | + * 监听发送后 | ||
| 26 | + * | ||
| 27 | + * @param msgBody 消息体 | ||
| 28 | + * @param targets 发送对象数组 | ||
| 29 | + * @param resultBody 返回对象 | ||
| 30 | + */ | ||
| 31 | + <T> void afterSender(SmsBody msgBody, Collection<String> targets, SmsResult<T> resultBody); | ||
| 32 | + | ||
| 33 | + /** | ||
| 34 | + * 排序值,拦截器根据order值顺序执行 | ||
| 35 | + * <p> | ||
| 36 | + * 值越小,越早执行 | ||
| 37 | + * | ||
| 38 | + * @return 排序值 | ||
| 39 | + */ | ||
| 40 | + int getOrder(); | ||
| 41 | +} |
src/main/java/cn/iocoder/dashboard/framework/msg/sms/intercepter/SmsLogIntercepter.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.framework.msg.sms.intercepter; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.dashboard.framework.msg.sms.SmsBody; | ||
| 4 | +import cn.iocoder.dashboard.framework.msg.sms.SmsResult; | ||
| 5 | +import cn.iocoder.dashboard.modules.msg.dal.mysql.dao.sms.SmsLogMapper; | ||
| 6 | +import cn.iocoder.dashboard.util.json.JsonUtils; | ||
| 7 | +import lombok.Setter; | ||
| 8 | +import lombok.extern.slf4j.Slf4j; | ||
| 9 | + | ||
| 10 | +import java.util.Collection; | ||
| 11 | + | ||
| 12 | +/** | ||
| 13 | + * 短信日志拦截器 | ||
| 14 | + * | ||
| 15 | + * @author zzf | ||
| 16 | + * @date 2021/1/22 15:46 | ||
| 17 | + */ | ||
| 18 | +@Slf4j | ||
| 19 | +public class SmsLogIntercepter implements SmsIntercepter { | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + @Override | ||
| 23 | + public void beforeSender(SmsBody msgBody, Collection<String> targets) { | ||
| 24 | + log.debug("ready send sms, body: {}, target: {}", JsonUtils.toJsonString(msgBody), targets); | ||
| 25 | + | ||
| 26 | + } | ||
| 27 | + | ||
| 28 | + @Override | ||
| 29 | + public <T> void afterSender(SmsBody msgBody, Collection<String> targets, SmsResult<T> resultBody) { | ||
| 30 | + if (resultBody.getSuccess()) { | ||
| 31 | + // | ||
| 32 | + } else { | ||
| 33 | + log.warn("send sms fail, body: {}, target: {}, resultBody: {}", | ||
| 34 | + JsonUtils.toJsonString(msgBody), | ||
| 35 | + targets, | ||
| 36 | + JsonUtils.toJsonString(resultBody) | ||
| 37 | + ); | ||
| 38 | + } | ||
| 39 | + | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | + @Override | ||
| 43 | + public int getOrder() { | ||
| 44 | + return 0; | ||
| 45 | + } | ||
| 46 | +} |
src/main/java/cn/iocoder/dashboard/framework/msg/sms/proxy/DefaultSmsSenderProxy.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.framework.msg.sms.proxy; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.util.ObjectUtil; | ||
| 4 | +import cn.iocoder.dashboard.framework.msg.sms.SmsBody; | ||
| 5 | +import cn.iocoder.dashboard.framework.msg.sms.SmsResult; | ||
| 6 | +import cn.iocoder.dashboard.framework.msg.sms.SmsSender; | ||
| 7 | +import cn.iocoder.dashboard.framework.msg.sms.intercepter.AbstractSmsIntercepterChain; | ||
| 8 | + | ||
| 9 | +import java.util.Collection; | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | + * 消息父接口 | ||
| 13 | + * | ||
| 14 | + * @author zzf | ||
| 15 | + * @date 2021/1/22 15:46 | ||
| 16 | + */ | ||
| 17 | +public class DefaultSmsSenderProxy<R> implements SmsSender<R> { | ||
| 18 | + | ||
| 19 | + private final SmsSender<R> smsSender; | ||
| 20 | + private final AbstractSmsIntercepterChain chain; | ||
| 21 | + | ||
| 22 | + @Override | ||
| 23 | + public SmsResult<R> send(SmsBody msgBody, Collection<String> targets) { | ||
| 24 | + if (ObjectUtil.isNotNull(chain) && ObjectUtil.isNotEmpty(chain.getIntercepterList())) { | ||
| 25 | + chain.getIntercepterList().forEach(s -> s.beforeSender(msgBody, targets)); | ||
| 26 | + } | ||
| 27 | + | ||
| 28 | + SmsResult<R> resultBody = smsSender.send(msgBody, targets); | ||
| 29 | + | ||
| 30 | + if (ObjectUtil.isNotNull(chain) && ObjectUtil.isNotEmpty(chain.getIntercepterList())) { | ||
| 31 | + chain.getIntercepterList().forEach(s -> s.afterSender(msgBody, targets, resultBody)); | ||
| 32 | + } | ||
| 33 | + return resultBody; | ||
| 34 | + } | ||
| 35 | + | ||
| 36 | + public DefaultSmsSenderProxy(SmsSender<R> smsSender, | ||
| 37 | + AbstractSmsIntercepterChain chain) { | ||
| 38 | + this.smsSender = smsSender; | ||
| 39 | + this.chain = chain; | ||
| 40 | + } | ||
| 41 | +} |
src/main/java/cn/iocoder/dashboard/framework/msg/sms/proxy/SmsSenderProxy.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.framework.msg.sms.proxy; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.dashboard.framework.msg.sms.SmsSender; | ||
| 4 | +import cn.iocoder.dashboard.framework.msg.sms.intercepter.SmsIntercepter; | ||
| 5 | + | ||
| 6 | +import java.util.Collections; | ||
| 7 | +import java.util.List; | ||
| 8 | + | ||
| 9 | +/** | ||
| 10 | + * 消息父接口 | ||
| 11 | + * | ||
| 12 | + * @author zzf | ||
| 13 | + * @date 2021/1/22 15:46 | ||
| 14 | + */ | ||
| 15 | +public interface SmsSenderProxy<R> extends SmsSender<R> { | ||
| 16 | + | ||
| 17 | + /** | ||
| 18 | + * 添加短信拦截器 | ||
| 19 | + * | ||
| 20 | + * @param smsIntercepter 短信拦截器 | ||
| 21 | + */ | ||
| 22 | + default void addSmsIntercepter(SmsIntercepter smsIntercepter) { | ||
| 23 | + addSmsIntercepter(Collections.singletonList(smsIntercepter)); | ||
| 24 | + } | ||
| 25 | + | ||
| 26 | + /** | ||
| 27 | + * 添加短信拦截器 | ||
| 28 | + * | ||
| 29 | + * @param smsIntercepterList 短信拦截器数组 | ||
| 30 | + */ | ||
| 31 | + void addSmsIntercepter(List<SmsIntercepter> smsIntercepterList); | ||
| 32 | + | ||
| 33 | + | ||
| 34 | +} |
src/main/java/cn/iocoder/dashboard/framework/redis/core/RedisKeyDefine.java
| 1 | package cn.iocoder.dashboard.framework.redis.core; | 1 | package cn.iocoder.dashboard.framework.redis.core; |
| 2 | 2 | ||
| 3 | -import lombok.AllArgsConstructor; | ||
| 4 | import lombok.Data; | 3 | import lombok.Data; |
| 5 | -import lombok.Getter; | ||
| 6 | 4 | ||
| 7 | import java.time.Duration; | 5 | import java.time.Duration; |
| 8 | 6 | ||
| @@ -26,20 +24,15 @@ public class RedisKeyDefine { | @@ -26,20 +24,15 @@ public class RedisKeyDefine { | ||
| 26 | 24 | ||
| 27 | } | 25 | } |
| 28 | 26 | ||
| 29 | - @Getter | ||
| 30 | - @AllArgsConstructor | ||
| 31 | - public enum TimeoutTypeEnum { | ||
| 32 | - | ||
| 33 | - FOREVER(1), // 永不超时 | ||
| 34 | - DYNAMIC(2), // 动态超时 | ||
| 35 | - FIXED(3); // 固定超时 | ||
| 36 | - | ||
| 37 | - /** | ||
| 38 | - * 类型 | ||
| 39 | - */ | ||
| 40 | - private final Integer type; | 27 | + /** |
| 28 | + * 过期时间 - 永不过期 | ||
| 29 | + */ | ||
| 30 | + public static final Duration TIMEOUT_FOREVER = null; | ||
| 41 | 31 | ||
| 42 | - } | 32 | + /** |
| 33 | + * 过期时间 - 动态,通过参数传入 | ||
| 34 | + */ | ||
| 35 | + public static final Duration TIMEOUT_DYNAMIC = null; | ||
| 43 | 36 | ||
| 44 | /** | 37 | /** |
| 45 | * Key 模板 | 38 | * Key 模板 |
| @@ -56,11 +49,9 @@ public class RedisKeyDefine { | @@ -56,11 +49,9 @@ public class RedisKeyDefine { | ||
| 56 | */ | 49 | */ |
| 57 | private final Class<?> valueType; | 50 | private final Class<?> valueType; |
| 58 | /** | 51 | /** |
| 59 | - * 超时类型 | ||
| 60 | - */ | ||
| 61 | - private final TimeoutTypeEnum timeoutType; | ||
| 62 | - /** | ||
| 63 | * 过期时间 | 52 | * 过期时间 |
| 53 | + * | ||
| 54 | + * 为空时,表示永不过期 {@link #TIMEOUT_FOREVER} | ||
| 64 | */ | 55 | */ |
| 65 | private final Duration timeout; | 56 | private final Duration timeout; |
| 66 | 57 | ||
| @@ -68,20 +59,7 @@ public class RedisKeyDefine { | @@ -68,20 +59,7 @@ public class RedisKeyDefine { | ||
| 68 | this.keyTemplate = keyTemplate; | 59 | this.keyTemplate = keyTemplate; |
| 69 | this.keyType = keyType; | 60 | this.keyType = keyType; |
| 70 | this.valueType = valueType; | 61 | this.valueType = valueType; |
| 71 | - this.timeoutType = TimeoutTypeEnum.FIXED; | ||
| 72 | this.timeout = timeout; | 62 | this.timeout = timeout; |
| 73 | - // 添加注册表 | ||
| 74 | - RedisKeyRegistry.add(this); | ||
| 75 | - } | ||
| 76 | - | ||
| 77 | - public RedisKeyDefine(String keyTemplate, KeyTypeEnum keyType, Class<?> valueType, TimeoutTypeEnum timeoutType) { | ||
| 78 | - this.keyTemplate = keyTemplate; | ||
| 79 | - this.keyType = keyType; | ||
| 80 | - this.valueType = valueType; | ||
| 81 | - this.timeoutType = timeoutType; | ||
| 82 | - this.timeout = Duration.ZERO; | ||
| 83 | - // 添加注册表 | ||
| 84 | - RedisKeyRegistry.add(this); | ||
| 85 | } | 63 | } |
| 86 | 64 | ||
| 87 | } | 65 | } |
src/main/java/cn/iocoder/dashboard/framework/redis/core/RedisKeyRegistry.java deleted
| 1 | -package cn.iocoder.dashboard.framework.redis.core; | ||
| 2 | - | ||
| 3 | -import java.util.ArrayList; | ||
| 4 | -import java.util.List; | ||
| 5 | - | ||
| 6 | -/** | ||
| 7 | - * {@link RedisKeyDefine} 注册表 | ||
| 8 | - */ | ||
| 9 | -public class RedisKeyRegistry { | ||
| 10 | - | ||
| 11 | - private static final List<RedisKeyDefine> defines = new ArrayList<>(); | ||
| 12 | - | ||
| 13 | - public static void add(RedisKeyDefine define) { | ||
| 14 | - defines.add(define); | ||
| 15 | - } | ||
| 16 | - | ||
| 17 | - public static List<RedisKeyDefine> list() { | ||
| 18 | - return defines; | ||
| 19 | - } | ||
| 20 | - | ||
| 21 | - public static int size() { | ||
| 22 | - return defines.size(); | ||
| 23 | - } | ||
| 24 | - | ||
| 25 | -} |
src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/SmsChannelController.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.msg.controller.sms; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.dashboard.common.pojo.CommonResult; | ||
| 4 | +import cn.iocoder.dashboard.common.pojo.PageResult; | ||
| 5 | +import cn.iocoder.dashboard.modules.msg.controller.sms.vo.req.SmsChannelCreateReqVO; | ||
| 6 | +import cn.iocoder.dashboard.modules.msg.controller.sms.vo.req.SmsChannelPageReqVO; | ||
| 7 | +import cn.iocoder.dashboard.modules.msg.controller.sms.vo.resp.SmsChannelEnumRespVO; | ||
| 8 | +import cn.iocoder.dashboard.modules.msg.dal.mysql.daoobject.sms.SmsChannelDO; | ||
| 9 | +import cn.iocoder.dashboard.modules.msg.service.sms.SmsChannelService; | ||
| 10 | +import io.swagger.annotations.Api; | ||
| 11 | +import io.swagger.annotations.ApiOperation; | ||
| 12 | +import org.springframework.validation.annotation.Validated; | ||
| 13 | +import org.springframework.web.bind.annotation.*; | ||
| 14 | + | ||
| 15 | +import javax.annotation.Resource; | ||
| 16 | +import java.util.List; | ||
| 17 | + | ||
| 18 | +import static cn.iocoder.dashboard.common.pojo.CommonResult.success; | ||
| 19 | + | ||
| 20 | +@Api("短信 渠道/签名 API") | ||
| 21 | +@RestController | ||
| 22 | +@RequestMapping("/sms/channel") | ||
| 23 | +public class SmsChannelController { | ||
| 24 | + | ||
| 25 | + @Resource | ||
| 26 | + private SmsChannelService service; | ||
| 27 | + | ||
| 28 | + @ApiOperation("获取渠道/签名分页") | ||
| 29 | + @GetMapping("/page") | ||
| 30 | + public CommonResult<PageResult<SmsChannelDO>> getPermissionInfo(@Validated SmsChannelPageReqVO reqVO) { | ||
| 31 | + return success(service.pageChannels(reqVO)); | ||
| 32 | + } | ||
| 33 | + | ||
| 34 | + @ApiOperation("获取渠道枚举") | ||
| 35 | + @GetMapping("/list/channel-enum") | ||
| 36 | + public CommonResult<List<SmsChannelEnumRespVO>> getChannelEnums() { | ||
| 37 | + return success(service.getChannelEnums()); | ||
| 38 | + } | ||
| 39 | + | ||
| 40 | + | ||
| 41 | + @ApiOperation("添加消息渠道") | ||
| 42 | + @PostMapping("/create") | ||
| 43 | + public CommonResult<Long> add(@Validated @RequestBody SmsChannelCreateReqVO reqVO) { | ||
| 44 | + return success(service.createChannel(reqVO)); | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + @ApiOperation("刷新消息渠道信息") | ||
| 48 | + @PutMapping("/flush") | ||
| 49 | + public CommonResult<Boolean> flushChannel() { | ||
| 50 | + return success(service.flushChannel()); | ||
| 51 | + } | ||
| 52 | + | ||
| 53 | + | ||
| 54 | +} |
src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/SmsTemplateController.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.msg.controller.sms; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.dashboard.common.enums.CommonStatusEnum; | ||
| 4 | +import cn.iocoder.dashboard.common.pojo.CommonResult; | ||
| 5 | +import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog; | ||
| 6 | +import cn.iocoder.dashboard.modules.system.controller.auth.vo.SysAuthLoginReqVO; | ||
| 7 | +import cn.iocoder.dashboard.modules.system.controller.auth.vo.SysAuthLoginRespVO; | ||
| 8 | +import cn.iocoder.dashboard.modules.system.controller.auth.vo.SysAuthMenuRespVO; | ||
| 9 | +import cn.iocoder.dashboard.modules.system.controller.auth.vo.SysAuthPermissionInfoRespVO; | ||
| 10 | +import cn.iocoder.dashboard.modules.system.convert.auth.SysAuthConvert; | ||
| 11 | +import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysMenuDO; | ||
| 12 | +import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.permission.SysRoleDO; | ||
| 13 | +import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.user.SysUserDO; | ||
| 14 | +import cn.iocoder.dashboard.modules.system.enums.permission.MenuTypeEnum; | ||
| 15 | +import cn.iocoder.dashboard.modules.system.service.auth.SysAuthService; | ||
| 16 | +import cn.iocoder.dashboard.modules.system.service.permission.SysPermissionService; | ||
| 17 | +import cn.iocoder.dashboard.modules.system.service.permission.SysRoleService; | ||
| 18 | +import cn.iocoder.dashboard.modules.system.service.user.SysUserService; | ||
| 19 | +import cn.iocoder.dashboard.util.collection.SetUtils; | ||
| 20 | +import io.swagger.annotations.Api; | ||
| 21 | +import io.swagger.annotations.ApiOperation; | ||
| 22 | +import org.springframework.web.bind.annotation.*; | ||
| 23 | + | ||
| 24 | +import javax.annotation.Resource; | ||
| 25 | +import javax.validation.Valid; | ||
| 26 | +import java.util.List; | ||
| 27 | + | ||
| 28 | +import static cn.iocoder.dashboard.common.pojo.CommonResult.success; | ||
| 29 | +import static cn.iocoder.dashboard.framework.security.core.util.SecurityUtils.getLoginUserId; | ||
| 30 | +import static cn.iocoder.dashboard.framework.security.core.util.SecurityUtils.getLoginUserRoleIds; | ||
| 31 | + | ||
| 32 | +@Api("认证 API") | ||
| 33 | +@RestController | ||
| 34 | +@RequestMapping("/sms/template") | ||
| 35 | +public class SmsTemplateController { | ||
| 36 | + | ||
| 37 | + @Resource | ||
| 38 | + private SysAuthService authService; | ||
| 39 | + @Resource | ||
| 40 | + private SysUserService userService; | ||
| 41 | + @Resource | ||
| 42 | + private SysRoleService roleService; | ||
| 43 | + @Resource | ||
| 44 | + private SysPermissionService permissionService; | ||
| 45 | + | ||
| 46 | + @ApiOperation("使用账号密码登录") | ||
| 47 | + @PostMapping("/login") | ||
| 48 | + @OperateLog(enable = false) // 避免 Post 请求被记录操作日志 | ||
| 49 | + public CommonResult<SysAuthLoginRespVO> login(@RequestBody @Valid SysAuthLoginReqVO reqVO) { | ||
| 50 | + String token = authService.login(reqVO.getUsername(), reqVO.getPassword(), reqVO.getUuid(), reqVO.getCode()); | ||
| 51 | + // 返回结果 | ||
| 52 | + return success(SysAuthLoginRespVO.builder().token(token).build()); | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + @ApiOperation("获取登陆用户的权限信息") | ||
| 56 | + @GetMapping("/get-permission-info") | ||
| 57 | + public CommonResult<SysAuthPermissionInfoRespVO> getPermissionInfo() { | ||
| 58 | + // 获得用户信息 | ||
| 59 | + SysUserDO user = userService.getUser(getLoginUserId()); | ||
| 60 | + if (user == null) { | ||
| 61 | + return null; | ||
| 62 | + } | ||
| 63 | + // 获得角色列表 | ||
| 64 | + List<SysRoleDO> roleList = roleService.listRolesFromCache(getLoginUserRoleIds()); | ||
| 65 | + // 获得菜单列表 | ||
| 66 | + List<SysMenuDO> menuList = permissionService.listRoleMenusFromCache(getLoginUserRoleIds(), | ||
| 67 | + SetUtils.asSet(MenuTypeEnum.DIR.getType(), MenuTypeEnum.MENU.getType(), MenuTypeEnum.BUTTON.getType()), | ||
| 68 | + SetUtils.asSet(CommonStatusEnum.ENABLE.getStatus())); | ||
| 69 | + // 拼接结果返回 | ||
| 70 | + return success(SysAuthConvert.INSTANCE.convert(user, roleList, menuList)); | ||
| 71 | + } | ||
| 72 | + | ||
| 73 | + @ApiOperation("获得登陆用户的菜单列表") | ||
| 74 | + @GetMapping("list-menus") | ||
| 75 | + public CommonResult<List<SysAuthMenuRespVO>> listMenus() { | ||
| 76 | + // 获得用户拥有的菜单列表 | ||
| 77 | + List<SysMenuDO> menuList = permissionService.listRoleMenusFromCache(getLoginUserRoleIds(), | ||
| 78 | + SetUtils.asSet(MenuTypeEnum.DIR.getType(), MenuTypeEnum.MENU.getType()), // 只要目录和菜单类型 | ||
| 79 | + SetUtils.asSet(CommonStatusEnum.ENABLE.getStatus())); // 只要开启的 | ||
| 80 | + // 转换成 Tree 结构返回 | ||
| 81 | + return success(SysAuthConvert.INSTANCE.buildMenuTree(menuList)); | ||
| 82 | + } | ||
| 83 | + | ||
| 84 | +} |
src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/vo/SmsChannelAllVO.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.msg.controller.sms.vo; | ||
| 2 | + | ||
| 3 | +import lombok.Data; | ||
| 4 | +import lombok.EqualsAndHashCode; | ||
| 5 | + | ||
| 6 | +import java.io.Serializable; | ||
| 7 | +import java.util.List; | ||
| 8 | + | ||
| 9 | +/** | ||
| 10 | + * 渠道(包含模板)信息VO类 | ||
| 11 | + * | ||
| 12 | + * @author zzf | ||
| 13 | + * @date 2021/1/25 17:01 | ||
| 14 | + */ | ||
| 15 | +@Data | ||
| 16 | +@EqualsAndHashCode | ||
| 17 | +public class SmsChannelAllVO implements Serializable { | ||
| 18 | + | ||
| 19 | + /** | ||
| 20 | + * id | ||
| 21 | + */ | ||
| 22 | + private Long id; | ||
| 23 | + | ||
| 24 | + /** | ||
| 25 | + * 编码(来自枚举类 阿里、华为、七牛等) | ||
| 26 | + */ | ||
| 27 | + private String code; | ||
| 28 | + | ||
| 29 | + /** | ||
| 30 | + * 渠道账号id | ||
| 31 | + */ | ||
| 32 | + private String apiKey; | ||
| 33 | + | ||
| 34 | + /** | ||
| 35 | + * 渠道账号秘钥 | ||
| 36 | + */ | ||
| 37 | + private String apiSecret; | ||
| 38 | + | ||
| 39 | + /** | ||
| 40 | + * 实际渠道签名唯一标识 | ||
| 41 | + */ | ||
| 42 | + private String apiSignatureId; | ||
| 43 | + | ||
| 44 | + /** | ||
| 45 | + * 签名值 | ||
| 46 | + */ | ||
| 47 | + private String signature; | ||
| 48 | + | ||
| 49 | + /** | ||
| 50 | + * 该渠道名下的短信模板集合 | ||
| 51 | + */ | ||
| 52 | + private List<SmsTemplateVO> templateList; | ||
| 53 | + | ||
| 54 | + public SmsTemplateVO getTemplateByTemplateCode(String tempCode) { | ||
| 55 | + return templateList.stream().filter(s -> s.getCode().equals(tempCode)).findFirst().get(); | ||
| 56 | + } | ||
| 57 | + | ||
| 58 | +} |
src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/vo/SmsTemplateVO.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.msg.controller.sms.vo; | ||
| 2 | + | ||
| 3 | +import lombok.Data; | ||
| 4 | +import lombok.EqualsAndHashCode; | ||
| 5 | + | ||
| 6 | +/** | ||
| 7 | + * 渠道模板VO类 | ||
| 8 | + * | ||
| 9 | + * @author zzf | ||
| 10 | + * @date 2021/1/25 17:03 | ||
| 11 | + */ | ||
| 12 | +@Data | ||
| 13 | +@EqualsAndHashCode | ||
| 14 | +public class SmsTemplateVO { | ||
| 15 | + | ||
| 16 | + /** | ||
| 17 | + * 业务编码(来自数据字典, 用户自定义业务场景 一个场景可以有多个模板) | ||
| 18 | + */ | ||
| 19 | + private String bizCode; | ||
| 20 | + /** | ||
| 21 | + * 编码 | ||
| 22 | + */ | ||
| 23 | + private String code; | ||
| 24 | + | ||
| 25 | + /** | ||
| 26 | + * 实际渠道模板唯一标识 | ||
| 27 | + */ | ||
| 28 | + private String apiTemplateId; | ||
| 29 | + | ||
| 30 | +} |
src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/vo/req/SmsChannelCreateReqVO.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.msg.controller.sms.vo.req; | ||
| 2 | + | ||
| 3 | +import io.swagger.annotations.ApiModel; | ||
| 4 | +import io.swagger.annotations.ApiModelProperty; | ||
| 5 | +import lombok.AllArgsConstructor; | ||
| 6 | +import lombok.Data; | ||
| 7 | +import lombok.EqualsAndHashCode; | ||
| 8 | +import lombok.NoArgsConstructor; | ||
| 9 | + | ||
| 10 | +import java.io.Serializable; | ||
| 11 | + | ||
| 12 | + | ||
| 13 | +@ApiModel("消息渠道创建 Request VO") | ||
| 14 | +@Data | ||
| 15 | +@NoArgsConstructor | ||
| 16 | +@AllArgsConstructor | ||
| 17 | +@EqualsAndHashCode | ||
| 18 | +public class SmsChannelCreateReqVO implements Serializable { | ||
| 19 | + | ||
| 20 | + @ApiModelProperty("编码(来自枚举类 阿里、华为、七牛等)") | ||
| 21 | + private String code; | ||
| 22 | + | ||
| 23 | + @ApiModelProperty("渠道账号id") | ||
| 24 | + private String apiKey; | ||
| 25 | + | ||
| 26 | + @ApiModelProperty("渠道账号秘钥") | ||
| 27 | + private String apiSecret; | ||
| 28 | + | ||
| 29 | + @ApiModelProperty("优先级(存在多个签名时,选择值最小的,渠道不可用时,按优先级从小到大切换)") | ||
| 30 | + private Integer priority; | ||
| 31 | + | ||
| 32 | + @ApiModelProperty("名称") | ||
| 33 | + private String name; | ||
| 34 | + | ||
| 35 | + @ApiModelProperty("签名值") | ||
| 36 | + private String signature; | ||
| 37 | + | ||
| 38 | + @ApiModelProperty("备注") | ||
| 39 | + private String remark; | ||
| 40 | + | ||
| 41 | + @ApiModelProperty("启用状态(0正常 1停用)") | ||
| 42 | + private Integer status; | ||
| 43 | + | ||
| 44 | +} |
src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/vo/req/SmsChannelPageReqVO.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.msg.controller.sms.vo.req; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.dashboard.common.pojo.PageParam; | ||
| 4 | +import io.swagger.annotations.ApiModel; | ||
| 5 | +import io.swagger.annotations.ApiModelProperty; | ||
| 6 | +import lombok.AllArgsConstructor; | ||
| 7 | +import lombok.Data; | ||
| 8 | +import lombok.EqualsAndHashCode; | ||
| 9 | +import lombok.NoArgsConstructor; | ||
| 10 | +import org.springframework.format.annotation.DateTimeFormat; | ||
| 11 | + | ||
| 12 | +import java.util.Date; | ||
| 13 | + | ||
| 14 | +import static cn.iocoder.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | ||
| 15 | + | ||
| 16 | +@ApiModel("消息渠道分页 Request VO") | ||
| 17 | +@Data | ||
| 18 | +@NoArgsConstructor | ||
| 19 | +@AllArgsConstructor | ||
| 20 | +@EqualsAndHashCode(callSuper = true) | ||
| 21 | +public class SmsChannelPageReqVO extends PageParam { | ||
| 22 | + | ||
| 23 | + @ApiModelProperty(value = "渠道名", example = "阿里", notes = "模糊匹配") | ||
| 24 | + private String name; | ||
| 25 | + | ||
| 26 | + @ApiModelProperty(value = "签名值", example = "源码", notes = "模糊匹配") | ||
| 27 | + private String signature; | ||
| 28 | + | ||
| 29 | +} |
src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/vo/resp/SmsChannelEnumRespVO.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.msg.controller.sms.vo.resp; | ||
| 2 | + | ||
| 3 | +import io.swagger.annotations.ApiModel; | ||
| 4 | +import lombok.Data; | ||
| 5 | +import lombok.EqualsAndHashCode; | ||
| 6 | +import lombok.NoArgsConstructor; | ||
| 7 | + | ||
| 8 | +import java.io.Serializable; | ||
| 9 | + | ||
| 10 | + | ||
| 11 | +@ApiModel("用户分页 Request VO") | ||
| 12 | +@Data | ||
| 13 | +@NoArgsConstructor | ||
| 14 | +@EqualsAndHashCode | ||
| 15 | +public class SmsChannelEnumRespVO implements Serializable { | ||
| 16 | + | ||
| 17 | + private String code; | ||
| 18 | + | ||
| 19 | + private String name; | ||
| 20 | + | ||
| 21 | +} |
src/main/java/cn/iocoder/dashboard/modules/msg/controller/sms/vo/resp/SmsChannelPageRespVO.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.msg.controller.sms.vo.resp; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.dashboard.common.pojo.PageParam; | ||
| 4 | +import io.swagger.annotations.ApiModel; | ||
| 5 | +import io.swagger.annotations.ApiModelProperty; | ||
| 6 | +import lombok.AllArgsConstructor; | ||
| 7 | +import lombok.Data; | ||
| 8 | +import lombok.EqualsAndHashCode; | ||
| 9 | +import lombok.NoArgsConstructor; | ||
| 10 | +import org.springframework.format.annotation.DateTimeFormat; | ||
| 11 | + | ||
| 12 | +import java.util.Date; | ||
| 13 | + | ||
| 14 | +import static cn.iocoder.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | ||
| 15 | + | ||
| 16 | +@ApiModel("用户分页 Request VO") | ||
| 17 | +@Data | ||
| 18 | +@NoArgsConstructor | ||
| 19 | +@AllArgsConstructor | ||
| 20 | +@EqualsAndHashCode(callSuper = true) | ||
| 21 | +public class SmsChannelPageRespVO extends PageParam { | ||
| 22 | + | ||
| 23 | + @ApiModelProperty(value = "用户账号", example = "yudao", notes = "模糊匹配") | ||
| 24 | + private String username; | ||
| 25 | + | ||
| 26 | + @ApiModelProperty(value = "手机号码", example = "yudao", notes = "模糊匹配") | ||
| 27 | + private String mobile; | ||
| 28 | + | ||
| 29 | + @ApiModelProperty(value = "展示状态", example = "1", notes = "参见 SysCommonStatusEnum 枚举类") | ||
| 30 | + private Integer status; | ||
| 31 | + | ||
| 32 | + @ApiModelProperty(value = "开始时间", example = "2020-10-24") | ||
| 33 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | ||
| 34 | + private Date beginTime; | ||
| 35 | + | ||
| 36 | + @ApiModelProperty(value = "结束时间", example = "2020-10-24") | ||
| 37 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | ||
| 38 | + private Date endTime; | ||
| 39 | + | ||
| 40 | + @ApiModelProperty(value = "部门编号", example = "1024", notes = "同时筛选子部门") | ||
| 41 | + private Long deptId; | ||
| 42 | + | ||
| 43 | +} |
src/main/java/cn/iocoder/dashboard/modules/msg/convert/sms/SmsChannelConvert.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.msg.convert.sms; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.dashboard.common.enums.SmsChannelEnum; | ||
| 4 | +import cn.iocoder.dashboard.common.pojo.PageResult; | ||
| 5 | +import cn.iocoder.dashboard.modules.msg.controller.sms.vo.SmsChannelAllVO; | ||
| 6 | +import cn.iocoder.dashboard.modules.msg.controller.sms.vo.req.SmsChannelCreateReqVO; | ||
| 7 | +import cn.iocoder.dashboard.modules.msg.controller.sms.vo.resp.SmsChannelEnumRespVO; | ||
| 8 | +import cn.iocoder.dashboard.modules.msg.dal.mysql.daoobject.sms.SmsChannelDO; | ||
| 9 | +import cn.iocoder.dashboard.modules.system.controller.user.vo.user.SysUserUpdateReqVO; | ||
| 10 | +import com.baomidou.mybatisplus.core.metadata.IPage; | ||
| 11 | +import org.mapstruct.Mapper; | ||
| 12 | +import org.mapstruct.Mapping; | ||
| 13 | +import org.mapstruct.factory.Mappers; | ||
| 14 | + | ||
| 15 | +import java.util.List; | ||
| 16 | + | ||
| 17 | +@Mapper | ||
| 18 | +public interface SmsChannelConvert { | ||
| 19 | + | ||
| 20 | + SmsChannelConvert INSTANCE = Mappers.getMapper(SmsChannelConvert.class); | ||
| 21 | + | ||
| 22 | + @Mapping(source = "records", target = "list") | ||
| 23 | + PageResult<SmsChannelDO> convertPage(IPage<SmsChannelDO> page); | ||
| 24 | + | ||
| 25 | + SmsChannelDO convert(SmsChannelCreateReqVO bean); | ||
| 26 | + | ||
| 27 | + SmsChannelDO convert(SysUserUpdateReqVO bean); | ||
| 28 | + | ||
| 29 | + List<SmsChannelEnumRespVO> convertEnum(List<SmsChannelEnum> bean); | ||
| 30 | + | ||
| 31 | + List<SmsChannelAllVO> convert(List<SmsChannelDO> bean); | ||
| 32 | + | ||
| 33 | + | ||
| 34 | +} |
src/main/java/cn/iocoder/dashboard/modules/msg/convert/sms/SmsTemplateConvert.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.msg.convert.sms; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.dashboard.common.pojo.PageResult; | ||
| 4 | +import cn.iocoder.dashboard.modules.msg.controller.sms.vo.SmsTemplateVO; | ||
| 5 | +import cn.iocoder.dashboard.modules.msg.dal.mysql.daoobject.sms.SmsChannelDO; | ||
| 6 | +import cn.iocoder.dashboard.modules.msg.dal.mysql.daoobject.sms.SmsTemplateDO; | ||
| 7 | +import com.baomidou.mybatisplus.core.metadata.IPage; | ||
| 8 | +import org.mapstruct.Mapper; | ||
| 9 | +import org.mapstruct.Mapping; | ||
| 10 | +import org.mapstruct.factory.Mappers; | ||
| 11 | + | ||
| 12 | +import java.util.List; | ||
| 13 | + | ||
| 14 | +@Mapper | ||
| 15 | +public interface SmsTemplateConvert { | ||
| 16 | + | ||
| 17 | + SmsTemplateConvert INSTANCE = Mappers.getMapper(SmsTemplateConvert.class); | ||
| 18 | + | ||
| 19 | + @Mapping(source = "records", target = "list") | ||
| 20 | + PageResult<SmsChannelDO> convertPage(IPage<SmsChannelDO> page); | ||
| 21 | + | ||
| 22 | + List<SmsTemplateVO> convert(List<SmsTemplateDO> bean); | ||
| 23 | + | ||
| 24 | + SmsTemplateVO convert(SmsTemplateDO bean); | ||
| 25 | + | ||
| 26 | +} |
src/main/java/cn/iocoder/dashboard/modules/msg/dal/mysql/dao/sms/SmsChannelMapper.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.msg.dal.mysql.dao.sms; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.util.StrUtil; | ||
| 4 | +import cn.iocoder.dashboard.common.enums.CommonStatusEnum; | ||
| 5 | +import cn.iocoder.dashboard.framework.mybatis.core.util.MyBatisUtils; | ||
| 6 | +import cn.iocoder.dashboard.modules.msg.controller.sms.vo.req.SmsChannelPageReqVO; | ||
| 7 | +import cn.iocoder.dashboard.modules.msg.dal.mysql.daoobject.sms.SmsChannelDO; | ||
| 8 | +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | ||
| 9 | +import com.baomidou.mybatisplus.core.mapper.BaseMapper; | ||
| 10 | +import com.baomidou.mybatisplus.core.metadata.IPage; | ||
| 11 | +import org.apache.ibatis.annotations.Mapper; | ||
| 12 | + | ||
| 13 | +import java.util.List; | ||
| 14 | + | ||
| 15 | +@Mapper | ||
| 16 | +public interface SmsChannelMapper extends BaseMapper<SmsChannelDO> { | ||
| 17 | + | ||
| 18 | + default IPage<SmsChannelDO> selectChannelPage(SmsChannelPageReqVO reqVO) { | ||
| 19 | + return selectPage(MyBatisUtils.buildPage(reqVO), new LambdaQueryWrapper<SmsChannelDO>() | ||
| 20 | + .like(StrUtil.isNotBlank(reqVO.getName()), SmsChannelDO::getName, reqVO.getName()) | ||
| 21 | + .like(StrUtil.isNotBlank(reqVO.getSignature()), SmsChannelDO::getName, reqVO.getSignature()) | ||
| 22 | + ); | ||
| 23 | + } | ||
| 24 | + | ||
| 25 | + default List<SmsChannelDO> selectEnabledList() { | ||
| 26 | + return selectList(new LambdaQueryWrapper<SmsChannelDO>() | ||
| 27 | + .eq(SmsChannelDO::getStatus, CommonStatusEnum.ENABLE.getStatus()) | ||
| 28 | + .orderByAsc(SmsChannelDO::getId) | ||
| 29 | + ); | ||
| 30 | + } | ||
| 31 | +} |
src/main/java/cn/iocoder/dashboard/modules/msg/dal/mysql/dao/sms/SmsLogMapper.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.msg.dal.mysql.dao.sms; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.dashboard.modules.msg.dal.mysql.daoobject.sms.SmsLog; | ||
| 4 | +import com.baomidou.mybatisplus.core.mapper.BaseMapper; | ||
| 5 | +import org.apache.ibatis.annotations.Mapper; | ||
| 6 | + | ||
| 7 | +@Mapper | ||
| 8 | +public interface SmsLogMapper extends BaseMapper<SmsLog> { | ||
| 9 | + | ||
| 10 | +} |
src/main/java/cn/iocoder/dashboard/modules/msg/dal/mysql/dao/sms/SmsTemplateMapper.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.msg.dal.mysql.dao.sms; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.dashboard.common.enums.CommonStatusEnum; | ||
| 4 | +import cn.iocoder.dashboard.modules.msg.dal.mysql.daoobject.sms.SmsTemplateDO; | ||
| 5 | +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | ||
| 6 | +import com.baomidou.mybatisplus.core.mapper.BaseMapper; | ||
| 7 | +import org.apache.ibatis.annotations.Mapper; | ||
| 8 | + | ||
| 9 | +import java.util.List; | ||
| 10 | + | ||
| 11 | +@Mapper | ||
| 12 | +public interface SmsTemplateMapper extends BaseMapper<SmsTemplateDO> { | ||
| 13 | + | ||
| 14 | + /** | ||
| 15 | + * 根据短信渠道id查询短信模板集合 | ||
| 16 | + * | ||
| 17 | + * @param channelId 渠道id | ||
| 18 | + * @return 模板集合 | ||
| 19 | + */ | ||
| 20 | + default List<SmsTemplateDO> selectListByChannelId(Long channelId) { | ||
| 21 | + return selectList(new LambdaQueryWrapper<SmsTemplateDO>() | ||
| 22 | + .eq(SmsTemplateDO::getChannelId, channelId) | ||
| 23 | + .eq(SmsTemplateDO::getStatus, CommonStatusEnum.ENABLE.getStatus()) | ||
| 24 | + .orderByAsc(SmsTemplateDO::getId) | ||
| 25 | + ); | ||
| 26 | + } | ||
| 27 | + | ||
| 28 | + /** | ||
| 29 | + * 查询有效短信模板集合 | ||
| 30 | + * | ||
| 31 | + * @return 有效短信模板集合 | ||
| 32 | + */ | ||
| 33 | + default List<SmsTemplateDO> selectEnabledList() { | ||
| 34 | + return selectList(new LambdaQueryWrapper<SmsTemplateDO>() | ||
| 35 | + .eq(SmsTemplateDO::getStatus, CommonStatusEnum.ENABLE.getStatus()) | ||
| 36 | + .orderByAsc(SmsTemplateDO::getId) | ||
| 37 | + ); | ||
| 38 | + } | ||
| 39 | +} |
src/main/java/cn/iocoder/dashboard/modules/msg/dal/mysql/daoobject/sms/SmsChannelDO.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.msg.dal.mysql.daoobject.sms; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO; | ||
| 4 | +import com.baomidou.mybatisplus.annotation.TableName; | ||
| 5 | +import lombok.Data; | ||
| 6 | +import lombok.EqualsAndHashCode; | ||
| 7 | + | ||
| 8 | + | ||
| 9 | +/** | ||
| 10 | + * 短信渠道 | ||
| 11 | + * | ||
| 12 | + * @author zzf | ||
| 13 | + * @since 2021-01-25 | ||
| 14 | + */ | ||
| 15 | +@Data | ||
| 16 | +@EqualsAndHashCode(callSuper = true) | ||
| 17 | +@TableName(value = "sms_channel", autoResultMap = true) | ||
| 18 | +public class SmsChannelDO extends BaseDO { | ||
| 19 | + | ||
| 20 | + /** | ||
| 21 | + * 自增编号 | ||
| 22 | + */ | ||
| 23 | + private Long id; | ||
| 24 | + | ||
| 25 | + /** | ||
| 26 | + * 编码(来自枚举类 阿里、华为、七牛等) | ||
| 27 | + */ | ||
| 28 | + private String code; | ||
| 29 | + | ||
| 30 | + /** | ||
| 31 | + * 渠道账号id | ||
| 32 | + */ | ||
| 33 | + private String apiKey; | ||
| 34 | + | ||
| 35 | + /** | ||
| 36 | + * 渠道账号秘钥 | ||
| 37 | + */ | ||
| 38 | + private String apiSecret; | ||
| 39 | + | ||
| 40 | + /** | ||
| 41 | + * 实际渠道签名唯一标识 | ||
| 42 | + */ | ||
| 43 | + private String apiSignatureId; | ||
| 44 | + | ||
| 45 | + /** | ||
| 46 | + * 名称 | ||
| 47 | + */ | ||
| 48 | + private String name; | ||
| 49 | + | ||
| 50 | + /** | ||
| 51 | + * 签名值 | ||
| 52 | + */ | ||
| 53 | + private String signature; | ||
| 54 | + | ||
| 55 | + /** | ||
| 56 | + * 备注 | ||
| 57 | + */ | ||
| 58 | + private String remark; | ||
| 59 | + | ||
| 60 | + /** | ||
| 61 | + * 启用状态(0正常 1停用) | ||
| 62 | + */ | ||
| 63 | + private Integer status; | ||
| 64 | + | ||
| 65 | +} |
src/main/java/cn/iocoder/dashboard/modules/msg/dal/mysql/daoobject/sms/SmsLog.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.msg.dal.mysql.daoobject.sms; | ||
| 2 | + | ||
| 3 | +import com.baomidou.mybatisplus.annotation.TableName; | ||
| 4 | +import lombok.Data; | ||
| 5 | +import lombok.EqualsAndHashCode; | ||
| 6 | + | ||
| 7 | +import java.io.Serializable; | ||
| 8 | +import java.util.Date; | ||
| 9 | + | ||
| 10 | +/** | ||
| 11 | + * 短信日志 | ||
| 12 | + * | ||
| 13 | + * @author zzf | ||
| 14 | + * @since 2021-01-25 | ||
| 15 | + */ | ||
| 16 | +@Data | ||
| 17 | +@EqualsAndHashCode | ||
| 18 | +@TableName(value = "sms_log", autoResultMap = true) | ||
| 19 | +public class SmsLog implements Serializable { | ||
| 20 | + | ||
| 21 | + /** | ||
| 22 | + * 自增编号 | ||
| 23 | + */ | ||
| 24 | + private Long id; | ||
| 25 | + | ||
| 26 | + /** | ||
| 27 | + * 短信渠道编码(来自枚举类) | ||
| 28 | + */ | ||
| 29 | + private String channelCode; | ||
| 30 | + | ||
| 31 | + /** | ||
| 32 | + * 实际渠道短信唯一标识 | ||
| 33 | + */ | ||
| 34 | + private String apiSmsId; | ||
| 35 | + | ||
| 36 | + /** | ||
| 37 | + * 模板id | ||
| 38 | + */ | ||
| 39 | + private Long templateId; | ||
| 40 | + | ||
| 41 | + /** | ||
| 42 | + * 手机号 | ||
| 43 | + */ | ||
| 44 | + private String phone; | ||
| 45 | + | ||
| 46 | + /** | ||
| 47 | + * 内容 | ||
| 48 | + */ | ||
| 49 | + private String content; | ||
| 50 | + | ||
| 51 | + /** | ||
| 52 | + * 备注 | ||
| 53 | + */ | ||
| 54 | + private String remark; | ||
| 55 | + | ||
| 56 | + /** | ||
| 57 | + * 发送状态(0发送中 1成功 2失败) | ||
| 58 | + */ | ||
| 59 | + private Integer sendStatus; | ||
| 60 | + | ||
| 61 | + /** | ||
| 62 | + * 创建者 | ||
| 63 | + */ | ||
| 64 | + private String createBy; | ||
| 65 | + | ||
| 66 | + /** | ||
| 67 | + * 创建时间 | ||
| 68 | + */ | ||
| 69 | + private Date createTime; | ||
| 70 | + | ||
| 71 | +} |
src/main/java/cn/iocoder/dashboard/modules/msg/dal/mysql/daoobject/sms/SmsTemplateDO.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.msg.dal.mysql.daoobject.sms; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO; | ||
| 4 | +import com.baomidou.mybatisplus.annotation.TableName; | ||
| 5 | +import lombok.Data; | ||
| 6 | +import lombok.EqualsAndHashCode; | ||
| 7 | + | ||
| 8 | +import java.util.Date; | ||
| 9 | + | ||
| 10 | +/** | ||
| 11 | + * 短信模板 | ||
| 12 | + * | ||
| 13 | + * @author zzf | ||
| 14 | + * @since 2021-01-25 | ||
| 15 | + */ | ||
| 16 | +@Data | ||
| 17 | +@EqualsAndHashCode(callSuper = true) | ||
| 18 | +@TableName(value = "sms_template", autoResultMap = true) | ||
| 19 | +public class SmsTemplateDO extends BaseDO { | ||
| 20 | + | ||
| 21 | + /** | ||
| 22 | + * 自增编号 | ||
| 23 | + */ | ||
| 24 | + private Long id; | ||
| 25 | + | ||
| 26 | + /** | ||
| 27 | + * 短信渠道编码(来自枚举类) | ||
| 28 | + */ | ||
| 29 | + private String channelCode; | ||
| 30 | + | ||
| 31 | + /** | ||
| 32 | + * 短信渠道id (对于前端来说就是绑定一个签名) | ||
| 33 | + */ | ||
| 34 | + private Long channelId; | ||
| 35 | + | ||
| 36 | + /** | ||
| 37 | + * 消息类型 [0验证码 1短信通知 2推广短信 3国际/港澳台消息] | ||
| 38 | + */ | ||
| 39 | + private Integer type; | ||
| 40 | + | ||
| 41 | + /** | ||
| 42 | + * 业务编码(来自数据字典, 用户自定义业务场景 一个场景可以有多个模板) | ||
| 43 | + */ | ||
| 44 | + private String bizCode; | ||
| 45 | + | ||
| 46 | + /** | ||
| 47 | + * 编码 | ||
| 48 | + */ | ||
| 49 | + private String code; | ||
| 50 | + | ||
| 51 | + /** | ||
| 52 | + * 名称 | ||
| 53 | + */ | ||
| 54 | + private String name; | ||
| 55 | + | ||
| 56 | + /** | ||
| 57 | + * 实际渠道模板唯一标识 | ||
| 58 | + */ | ||
| 59 | + private String apiTemplateId; | ||
| 60 | + | ||
| 61 | + /** | ||
| 62 | + * 内容 | ||
| 63 | + */ | ||
| 64 | + private String content; | ||
| 65 | + | ||
| 66 | + /** | ||
| 67 | + * 参数数组(自动根据内容生成) | ||
| 68 | + */ | ||
| 69 | + private String params; | ||
| 70 | + | ||
| 71 | + /** | ||
| 72 | + * 备注 | ||
| 73 | + */ | ||
| 74 | + private String remark; | ||
| 75 | + | ||
| 76 | + /** | ||
| 77 | + * 启用状态(0正常 1停用) | ||
| 78 | + */ | ||
| 79 | + private Integer status; | ||
| 80 | + | ||
| 81 | +} |
src/main/java/cn/iocoder/dashboard/modules/msg/package-info.java
0 → 100644
src/main/java/cn/iocoder/dashboard/modules/msg/service/sms/SmsChannelService.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.msg.service.sms; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.dashboard.common.pojo.PageResult; | ||
| 4 | +import cn.iocoder.dashboard.modules.msg.controller.sms.vo.SmsChannelAllVO; | ||
| 5 | +import cn.iocoder.dashboard.modules.msg.controller.sms.vo.req.SmsChannelCreateReqVO; | ||
| 6 | +import cn.iocoder.dashboard.modules.msg.controller.sms.vo.req.SmsChannelPageReqVO; | ||
| 7 | +import cn.iocoder.dashboard.modules.msg.controller.sms.vo.resp.SmsChannelEnumRespVO; | ||
| 8 | +import cn.iocoder.dashboard.modules.msg.dal.mysql.daoobject.sms.SmsChannelDO; | ||
| 9 | + | ||
| 10 | +import java.util.List; | ||
| 11 | + | ||
| 12 | +/** | ||
| 13 | + * 短信渠道Service接口 | ||
| 14 | + * | ||
| 15 | + * @author zzf | ||
| 16 | + * @date 2021/1/25 9:24 | ||
| 17 | + */ | ||
| 18 | +public interface SmsChannelService { | ||
| 19 | + | ||
| 20 | + PageResult<SmsChannelDO> pageChannels(SmsChannelPageReqVO reqVO); | ||
| 21 | + | ||
| 22 | + Long createChannel(SmsChannelCreateReqVO reqVO); | ||
| 23 | + | ||
| 24 | + List<SmsChannelEnumRespVO> getChannelEnums(); | ||
| 25 | + | ||
| 26 | + /** | ||
| 27 | + * 查询渠道(包含名下模块)信息集合 | ||
| 28 | + * | ||
| 29 | + * @return 渠道(包含名下模块)信息集合 | ||
| 30 | + */ | ||
| 31 | + List<SmsChannelAllVO> listChannelAllEnabledInfo(); | ||
| 32 | + | ||
| 33 | + boolean flushChannel(); | ||
| 34 | +} |
src/main/java/cn/iocoder/dashboard/modules/msg/service/sms/SmsLogService.java
0 → 100644
src/main/java/cn/iocoder/dashboard/modules/msg/service/sms/SmsTemplateService.java
0 → 100644
src/main/java/cn/iocoder/dashboard/modules/msg/service/sms/impl/SmsChannelServiceImpl.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.msg.service.sms.impl; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.util.ObjectUtil; | ||
| 4 | +import cn.hutool.extra.spring.SpringUtil; | ||
| 5 | +import cn.iocoder.dashboard.common.enums.SmsChannelEnum; | ||
| 6 | +import cn.iocoder.dashboard.common.pojo.PageResult; | ||
| 7 | +import cn.iocoder.dashboard.framework.msg.sms.factory.AbstractSmsSenderFactory; | ||
| 8 | +import cn.iocoder.dashboard.modules.msg.controller.sms.vo.SmsChannelAllVO; | ||
| 9 | +import cn.iocoder.dashboard.modules.msg.controller.sms.vo.req.SmsChannelCreateReqVO; | ||
| 10 | +import cn.iocoder.dashboard.modules.msg.controller.sms.vo.req.SmsChannelPageReqVO; | ||
| 11 | +import cn.iocoder.dashboard.modules.msg.controller.sms.vo.resp.SmsChannelEnumRespVO; | ||
| 12 | +import cn.iocoder.dashboard.modules.msg.convert.sms.SmsChannelConvert; | ||
| 13 | +import cn.iocoder.dashboard.modules.msg.convert.sms.SmsTemplateConvert; | ||
| 14 | +import cn.iocoder.dashboard.modules.msg.dal.mysql.dao.sms.SmsChannelMapper; | ||
| 15 | +import cn.iocoder.dashboard.modules.msg.dal.mysql.dao.sms.SmsTemplateMapper; | ||
| 16 | +import cn.iocoder.dashboard.modules.msg.dal.mysql.daoobject.sms.SmsChannelDO; | ||
| 17 | +import cn.iocoder.dashboard.modules.msg.dal.mysql.daoobject.sms.SmsTemplateDO; | ||
| 18 | +import cn.iocoder.dashboard.modules.msg.service.sms.SmsChannelService; | ||
| 19 | +import org.springframework.stereotype.Service; | ||
| 20 | + | ||
| 21 | +import javax.annotation.Resource; | ||
| 22 | +import java.util.ArrayList; | ||
| 23 | +import java.util.Arrays; | ||
| 24 | +import java.util.List; | ||
| 25 | + | ||
| 26 | +/** | ||
| 27 | + * 短信渠道Service实现类 | ||
| 28 | + * | ||
| 29 | + * @author zzf | ||
| 30 | + * @date 2021/1/25 9:25 | ||
| 31 | + */ | ||
| 32 | +@Service | ||
| 33 | +public class SmsChannelServiceImpl implements SmsChannelService { | ||
| 34 | + | ||
| 35 | + @Resource | ||
| 36 | + private SmsChannelMapper mapper; | ||
| 37 | + | ||
| 38 | + @Resource | ||
| 39 | + private SmsTemplateMapper templateMapper; | ||
| 40 | + | ||
| 41 | + @Override | ||
| 42 | + public PageResult<SmsChannelDO> pageChannels(SmsChannelPageReqVO reqVO) { | ||
| 43 | + return SmsChannelConvert.INSTANCE.convertPage(mapper.selectChannelPage(reqVO)); | ||
| 44 | + } | ||
| 45 | + | ||
| 46 | + @Override | ||
| 47 | + public Long createChannel(SmsChannelCreateReqVO reqVO) { | ||
| 48 | + SmsChannelDO channelDO = SmsChannelConvert.INSTANCE.convert(reqVO); | ||
| 49 | + mapper.insert(channelDO); | ||
| 50 | + return channelDO.getId(); | ||
| 51 | + } | ||
| 52 | + | ||
| 53 | + @Override | ||
| 54 | + public List<SmsChannelEnumRespVO> getChannelEnums() { | ||
| 55 | + return SmsChannelConvert.INSTANCE.convertEnum(Arrays.asList(SmsChannelEnum.values())); | ||
| 56 | + } | ||
| 57 | + | ||
| 58 | + @Override | ||
| 59 | + public List<SmsChannelAllVO> listChannelAllEnabledInfo() { | ||
| 60 | + List<SmsChannelDO> channelDOList = mapper.selectEnabledList(); | ||
| 61 | + if (ObjectUtil.isNull(channelDOList)) { | ||
| 62 | + return null; | ||
| 63 | + } | ||
| 64 | + List<SmsChannelAllVO> channelAllVOList = SmsChannelConvert.INSTANCE.convert(channelDOList); | ||
| 65 | + | ||
| 66 | + channelAllVOList.forEach(smsChannelDO -> { | ||
| 67 | + | ||
| 68 | + List<SmsTemplateDO> templateDOList = templateMapper.selectListByChannelId(smsChannelDO.getId()); | ||
| 69 | + if (ObjectUtil.isNull(templateDOList)) { | ||
| 70 | + templateDOList = new ArrayList<>(); | ||
| 71 | + } | ||
| 72 | + smsChannelDO.setTemplateList(SmsTemplateConvert.INSTANCE.convert(templateDOList)); | ||
| 73 | + }); | ||
| 74 | + return channelAllVOList; | ||
| 75 | + } | ||
| 76 | + | ||
| 77 | + @Override | ||
| 78 | + public boolean flushChannel() { | ||
| 79 | + AbstractSmsSenderFactory smsSenderFactory = SpringUtil.getBean(AbstractSmsSenderFactory.class); | ||
| 80 | + if (smsSenderFactory == null) { | ||
| 81 | + return false; | ||
| 82 | + } | ||
| 83 | + | ||
| 84 | + smsSenderFactory.flush(listChannelAllEnabledInfo()); | ||
| 85 | + | ||
| 86 | + return true; | ||
| 87 | + } | ||
| 88 | +} |
src/main/java/cn/iocoder/dashboard/modules/msg/service/sms/impl/SmsLogServiceImpl.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.msg.service.sms.impl; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.dashboard.modules.msg.service.sms.SmsLogService; | ||
| 4 | +import org.springframework.stereotype.Service; | ||
| 5 | + | ||
| 6 | +/** | ||
| 7 | + * 短信日志Service实现类 | ||
| 8 | + * | ||
| 9 | + * @author zzf | ||
| 10 | + * @date 2021/1/25 9:25 | ||
| 11 | + */ | ||
| 12 | +@Service | ||
| 13 | +public class SmsLogServiceImpl implements SmsLogService { | ||
| 14 | + | ||
| 15 | +} |
src/main/java/cn/iocoder/dashboard/modules/msg/service/sms/impl/SmsTemplateServiceImpl.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.modules.msg.service.sms.impl; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.dashboard.modules.msg.service.sms.SmsTemplateService; | ||
| 4 | +import org.springframework.stereotype.Service; | ||
| 5 | + | ||
| 6 | +/** | ||
| 7 | + * 短信模板Service实现类 | ||
| 8 | + * | ||
| 9 | + * @author zzf | ||
| 10 | + * @date 2021/1/25 9:25 | ||
| 11 | + */ | ||
| 12 | +@Service | ||
| 13 | +public class SmsTemplateServiceImpl implements SmsTemplateService { | ||
| 14 | +} |
src/main/java/cn/iocoder/dashboard/modules/system/enums/SysErrorCodeConstants.java
| @@ -75,4 +75,11 @@ public interface SysErrorCodeConstants { | @@ -75,4 +75,11 @@ public interface SysErrorCodeConstants { | ||
| 75 | // ========== 文件 1002009000 ========== | 75 | // ========== 文件 1002009000 ========== |
| 76 | ErrorCode FILE_PATH_EXISTS = new ErrorCode(1002009001, "文件路径已经存在"); | 76 | ErrorCode FILE_PATH_EXISTS = new ErrorCode(1002009001, "文件路径已经存在"); |
| 77 | 77 | ||
| 78 | + | ||
| 79 | + // ========== 消息 1003001000 ========== | ||
| 80 | + ErrorCode SMS_CHANNEL_NOT_FOUND = new ErrorCode(1003001001, "没有短信渠道信息, 请初始化sms_channel表数据。"); | ||
| 81 | + ErrorCode SMS_TEMPLATE_NOT_FOUND = new ErrorCode(1003001002, "没有短信模板信息, 请初始化sms_template表数据。"); | ||
| 82 | + ErrorCode SMS_SENDER_NOT_FOUND = new ErrorCode(1003001003, "没有找到对应的短信发送对象,请检查sms_channel表和sms_template表数据"); | ||
| 83 | + ErrorCode INVALID_CHANNEL_CODE = new ErrorCode(1003001004, "非法的短信渠道code,请检查sms_channel表的code值是否与SmsChannelEnum中的code值一致。"); | ||
| 84 | + | ||
| 78 | } | 85 | } |