mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2024-11-22 15:21:53 +08:00
增加短信功能实现
This commit is contained in:
parent
842496a534
commit
df8bda53e8
12
pom.xml
12
pom.xml
@ -222,6 +222,18 @@
|
||||
<version>${easyexcel.verion}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.aliyun</groupId>
|
||||
<artifactId>aliyun-java-sdk-core</artifactId>
|
||||
<version>4.5.18</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.aliyun</groupId>
|
||||
<artifactId>aliyun-java-sdk-dysmsapi</artifactId>
|
||||
<version>2.1.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
||||
|
@ -884,4 +884,77 @@ 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', -- add
|
||||
`api_secret` varchar(100) NOT NULL COMMENT '账号秘钥', -- add
|
||||
`priority` tinyint(8) NOT NULL default 1 COMMENT '优先级(存在多个签名时,选择值最小的,渠道不可用时,按优先级从小到大切换)', -- add
|
||||
`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 (对于前端来说就是绑定一个签名)', -- add
|
||||
`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
|
||||
`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
|
||||
`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;
|
||||
|
@ -1,15 +1,15 @@
|
||||
package cn.iocoder.dashboard;
|
||||
|
||||
import de.codecentric.boot.admin.server.config.EnableAdminServer;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableAdminServer
|
||||
public class DashboardApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(DashboardApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
//package cn.iocoder.dashboard;
|
||||
//
|
||||
//import de.codecentric.boot.admin.server.config.EnableAdminServer;
|
||||
//import org.springframework.boot.SpringApplication;
|
||||
//import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
//
|
||||
//@SpringBootApplication
|
||||
//@EnableAdminServer
|
||||
//public class DashboardApplication {
|
||||
//
|
||||
// public static void main(String[] args) {
|
||||
// SpringApplication.run(DashboardApplication.class, args);
|
||||
// }
|
||||
//
|
||||
//}
|
||||
|
@ -0,0 +1,33 @@
|
||||
package cn.iocoder.dashboard.common.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 短信渠道枚举
|
||||
*
|
||||
* @author zzf
|
||||
* @date 2021/1/25 10:56
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum SmsChannelEnum {
|
||||
|
||||
ALI("ALI", "阿里"),
|
||||
HUA_WEI("HUA_WEI", "华为"),
|
||||
QI_NIU("QI_NIU", "七牛"),
|
||||
TEN_XUN("TEN_XUN", "腾讯");
|
||||
|
||||
private final String code;
|
||||
|
||||
private final String name;
|
||||
|
||||
public static SmsChannelEnum getByCode(String code) {
|
||||
for (SmsChannelEnum value : SmsChannelEnum.values()) {
|
||||
if (value.getCode().equals(code)) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package cn.iocoder.dashboard.framework.msg.sms;
|
||||
|
||||
import cn.iocoder.dashboard.util.json.JsonUtils;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 消息内容实体类
|
||||
*/
|
||||
@Data
|
||||
public class SmsBody {
|
||||
|
||||
/**
|
||||
* 模板编码
|
||||
*/
|
||||
private String code;
|
||||
|
||||
/**
|
||||
* 参数列表
|
||||
*/
|
||||
private Map<String, String> params;
|
||||
|
||||
public String getParamsStr() {
|
||||
return JsonUtils.toJsonString(params);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package cn.iocoder.dashboard.framework.msg.sms;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 消息内容实体类
|
||||
*/
|
||||
@Data
|
||||
public class SmsResult<T> implements Serializable {
|
||||
|
||||
/**
|
||||
* 是否成功
|
||||
*/
|
||||
private Boolean success;
|
||||
|
||||
/**
|
||||
* 提示
|
||||
*/
|
||||
private String message;
|
||||
|
||||
/**
|
||||
* 返回值
|
||||
*/
|
||||
private T result;
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
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<R> {
|
||||
|
||||
/**
|
||||
* 发送通知
|
||||
*
|
||||
* @param msgBody 通知内容
|
||||
* @param targets 发送对象列表
|
||||
* @return 是否发送成功
|
||||
*/
|
||||
SmsResult<R> send(SmsBody msgBody, Collection<String> targets);
|
||||
|
||||
/**
|
||||
* 发送通知
|
||||
*
|
||||
* @param msgBody 通知内容
|
||||
* @param target 发送对象列表
|
||||
* @return 是否发送成功
|
||||
*/
|
||||
default SmsResult<R> send(SmsBody msgBody, String target) {
|
||||
if (StringUtils.isBlank(target)) {
|
||||
return failResult();
|
||||
}
|
||||
|
||||
return send(msgBody, Collections.singletonList(target));
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送通知
|
||||
*
|
||||
* @param msgBody 通知内容
|
||||
* @param targets 发送对象列表
|
||||
* @return 是否发送成功
|
||||
*/
|
||||
default SmsResult<R> send(SmsBody msgBody, String... targets) {
|
||||
if (targets == null) {
|
||||
return failResult();
|
||||
}
|
||||
|
||||
return send(msgBody, Arrays.asList(targets));
|
||||
}
|
||||
|
||||
default SmsResult<R> failResult() {
|
||||
SmsResult<R> resultBody = new SmsResult<>();
|
||||
resultBody.setSuccess(false);
|
||||
return resultBody;
|
||||
}
|
||||
|
||||
default SmsResult<R> failResult(String message) {
|
||||
SmsResult<R> resultBody = failResult();
|
||||
resultBody.setMessage(message);
|
||||
return resultBody;
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
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<SmsChannelAllVO> smsChannelAllVOList = channelService.listChannelAllEnabledInfo();
|
||||
//初始化渠道、模板信息
|
||||
defaultSmsSenderFactory.init(smsChannelAllVOList);
|
||||
//注入拦截器链
|
||||
defaultSmsSenderFactory.setIntercepterChain(intercepterChain);
|
||||
return defaultSmsSenderFactory;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,137 @@
|
||||
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<String, SmsSender<?>> bizCode2SenderMap = new ConcurrentHashMap<>(8);
|
||||
|
||||
/**
|
||||
* sender索引
|
||||
* key: {@link SmsTemplateVO#getCode()}
|
||||
* value: {@link SmsSender}
|
||||
*/
|
||||
private final ConcurrentHashMap<String, SmsSender<?>> 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<SmsChannelAllVO> 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<String, SmsSender<?>> 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<SmsChannelAllVO> smsChannelAllVOList) {
|
||||
try {
|
||||
writeLock.lock();
|
||||
bizCode2SenderMap.clear();
|
||||
templateCode2SenderMap.clear();
|
||||
addSender(smsChannelAllVOList);
|
||||
} finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void addSender(List<SmsChannelAllVO> 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<SmsTemplateVO> 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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
package cn.iocoder.dashboard.framework.msg.sms.impl.ali;
|
||||
|
||||
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 com.aliyuncs.DefaultAcsClient;
|
||||
import com.aliyuncs.IAcsClient;
|
||||
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
|
||||
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
|
||||
import com.aliyuncs.http.MethodType;
|
||||
import com.aliyuncs.profile.DefaultProfile;
|
||||
import com.aliyuncs.profile.IClientProfile;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* 阿里短信实现类
|
||||
*
|
||||
* @author zzf
|
||||
* @date 2021/1/25 14:17
|
||||
*/
|
||||
@Slf4j
|
||||
public class AliSmsSender implements SmsSender<SendSmsResponse> {
|
||||
|
||||
private static final String OK = "OK";
|
||||
|
||||
private static final String PRODUCT = "Dysmsapi";
|
||||
|
||||
private static final String DOMAIN = "dysmsapi.aliyuncs.com";
|
||||
|
||||
private static final String ENDPOINT = "cn-hangzhou";
|
||||
|
||||
private final SmsChannelAllVO channelVO;
|
||||
|
||||
private final IAcsClient acsClient;
|
||||
|
||||
/**
|
||||
* 构造阿里云短信发送处理
|
||||
*
|
||||
* @param channelVO 阿里云短信配置
|
||||
*/
|
||||
public AliSmsSender(SmsChannelAllVO channelVO) {
|
||||
|
||||
this.channelVO = channelVO;
|
||||
|
||||
String accessKeyId = channelVO.getApiKey();
|
||||
String accessKeySecret = channelVO.getApiSecret();
|
||||
|
||||
IClientProfile profile = DefaultProfile.getProfile(ENDPOINT, accessKeyId, accessKeySecret);
|
||||
DefaultProfile.addEndpoint(ENDPOINT, PRODUCT, DOMAIN);
|
||||
|
||||
acsClient = new DefaultAcsClient(profile);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SmsResult<SendSmsResponse> send(SmsBody msgBody, Collection<String> 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());
|
||||
|
||||
try {
|
||||
SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);
|
||||
|
||||
boolean result = OK.equals(sendSmsResponse.getCode());
|
||||
if (!result) {
|
||||
log.debug("send fail[code={}, message={}]", sendSmsResponse.getCode(), sendSmsResponse.getMessage());
|
||||
}
|
||||
SmsResult<SendSmsResponse> resultBody = new SmsResult<>();
|
||||
resultBody.setSuccess(result);
|
||||
resultBody.setResult(sendSmsResponse);
|
||||
return resultBody;
|
||||
} catch (Exception e) {
|
||||
log.debug(e.getMessage(), e);
|
||||
}
|
||||
|
||||
return failResult();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
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<SmsIntercepter> intercepterList = new ArrayList<>(8);
|
||||
|
||||
|
||||
/**
|
||||
* 添加短信拦截器
|
||||
*
|
||||
* @param smsIntercepter 短信拦截器
|
||||
*/
|
||||
public void addSmsIntercepter(SmsIntercepter smsIntercepter) {
|
||||
addSmsIntercepter(Collections.singletonList(smsIntercepter));
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加短信拦截器
|
||||
*
|
||||
* @param smsIntercepterList 短信拦截器数组
|
||||
*/
|
||||
abstract void addSmsIntercepter(List<SmsIntercepter> smsIntercepterList);
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
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<SmsIntercepter> smsIntercepterList) {
|
||||
intercepterList.addAll(smsIntercepterList);
|
||||
//排序
|
||||
intercepterList.sort(Comparator.comparingInt(SmsIntercepter::getOrder));
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
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<String> targets);
|
||||
|
||||
/**
|
||||
* 监听发送后
|
||||
*
|
||||
* @param msgBody 消息体
|
||||
* @param targets 发送对象数组
|
||||
* @param resultBody 返回对象
|
||||
*/
|
||||
<T> void afterSender(SmsBody msgBody, Collection<String> targets, SmsResult<T> resultBody);
|
||||
|
||||
/**
|
||||
* 排序值,拦截器根据order值顺序执行
|
||||
* <p>
|
||||
* 值越小,越早执行
|
||||
*
|
||||
* @return 排序值
|
||||
*/
|
||||
int getOrder();
|
||||
}
|
@ -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<String> targets) {
|
||||
log.debug("ready send sms, body: {}, target: {}", JsonUtils.toJsonString(msgBody), targets);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void afterSender(SmsBody msgBody, Collection<String> targets, SmsResult<T> 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;
|
||||
}
|
||||
}
|
@ -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<R> implements SmsSender<R> {
|
||||
|
||||
private final SmsSender<R> smsSender;
|
||||
private final AbstractSmsIntercepterChain chain;
|
||||
|
||||
@Override
|
||||
public SmsResult<R> send(SmsBody msgBody, Collection<String> targets) {
|
||||
if (ObjectUtil.isNotNull(chain) && ObjectUtil.isNotEmpty(chain.getIntercepterList())) {
|
||||
chain.getIntercepterList().forEach(s -> s.beforeSender(msgBody, targets));
|
||||
}
|
||||
|
||||
SmsResult<R> 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<R> smsSender,
|
||||
AbstractSmsIntercepterChain chain) {
|
||||
this.smsSender = smsSender;
|
||||
this.chain = chain;
|
||||
}
|
||||
}
|
@ -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<R> extends SmsSender<R> {
|
||||
|
||||
/**
|
||||
* 添加短信拦截器
|
||||
*
|
||||
* @param smsIntercepter 短信拦截器
|
||||
*/
|
||||
default void addSmsIntercepter(SmsIntercepter smsIntercepter) {
|
||||
addSmsIntercepter(Collections.singletonList(smsIntercepter));
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加短信拦截器
|
||||
*
|
||||
* @param smsIntercepterList 短信拦截器数组
|
||||
*/
|
||||
void addSmsIntercepter(List<SmsIntercepter> smsIntercepterList);
|
||||
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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<RedisKeyDefine> defines = new ArrayList<>();
|
||||
|
||||
public static void add(RedisKeyDefine define) {
|
||||
defines.add(define);
|
||||
}
|
||||
|
||||
public static List<RedisKeyDefine> list() {
|
||||
return defines;
|
||||
}
|
||||
|
||||
public static int size() {
|
||||
return defines.size();
|
||||
}
|
||||
|
||||
}
|
@ -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<PageResult<SmsChannelDO>> getPermissionInfo(@Validated SmsChannelPageReqVO reqVO) {
|
||||
return success(service.pageChannels(reqVO));
|
||||
}
|
||||
|
||||
@ApiOperation("获取渠道枚举")
|
||||
@GetMapping("/list/channel-enum")
|
||||
public CommonResult<List<SmsChannelEnumRespVO>> getChannelEnums() {
|
||||
return success(service.getChannelEnums());
|
||||
}
|
||||
|
||||
|
||||
@ApiOperation("添加消息渠道")
|
||||
@PostMapping("/create")
|
||||
public CommonResult<Long> add(@Validated @RequestBody SmsChannelCreateReqVO reqVO) {
|
||||
return success(service.createChannel(reqVO));
|
||||
}
|
||||
|
||||
@ApiOperation("刷新消息渠道信息")
|
||||
@PutMapping("/flush")
|
||||
public CommonResult<Boolean> flushChannel() {
|
||||
return success(service.flushChannel());
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -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<SysAuthLoginRespVO> 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<SysAuthPermissionInfoRespVO> getPermissionInfo() {
|
||||
// 获得用户信息
|
||||
SysUserDO user = userService.getUser(getLoginUserId());
|
||||
if (user == null) {
|
||||
return null;
|
||||
}
|
||||
// 获得角色列表
|
||||
List<SysRoleDO> roleList = roleService.listRolesFromCache(getLoginUserRoleIds());
|
||||
// 获得菜单列表
|
||||
List<SysMenuDO> 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<List<SysAuthMenuRespVO>> listMenus() {
|
||||
// 获得用户拥有的菜单列表
|
||||
List<SysMenuDO> menuList = permissionService.listRoleMenusFromCache(getLoginUserRoleIds(),
|
||||
SetUtils.asSet(MenuTypeEnum.DIR.getType(), MenuTypeEnum.MENU.getType()), // 只要目录和菜单类型
|
||||
SetUtils.asSet(CommonStatusEnum.ENABLE.getStatus())); // 只要开启的
|
||||
// 转换成 Tree 结构返回
|
||||
return success(SysAuthConvert.INSTANCE.buildMenuTree(menuList));
|
||||
}
|
||||
|
||||
}
|
@ -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<SmsTemplateVO> templateList;
|
||||
|
||||
public SmsTemplateVO getTemplateByTemplateCode(String tempCode) {
|
||||
return templateList.stream().filter(s -> s.getCode().equals(tempCode)).findFirst().get();
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
}
|
@ -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<SmsChannelDO> convertPage(IPage<SmsChannelDO> page);
|
||||
|
||||
SmsChannelDO convert(SmsChannelCreateReqVO bean);
|
||||
|
||||
SmsChannelDO convert(SysUserUpdateReqVO bean);
|
||||
|
||||
List<SmsChannelEnumRespVO> convertEnum(List<SmsChannelEnum> bean);
|
||||
|
||||
List<SmsChannelAllVO> convert(List<SmsChannelDO> bean);
|
||||
|
||||
|
||||
}
|
@ -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<SmsChannelDO> convertPage(IPage<SmsChannelDO> page);
|
||||
|
||||
List<SmsTemplateVO> convert(List<SmsTemplateDO> bean);
|
||||
|
||||
SmsTemplateVO convert(SmsTemplateDO bean);
|
||||
|
||||
}
|
@ -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<SmsChannelDO> {
|
||||
|
||||
default IPage<SmsChannelDO> selectChannelPage(SmsChannelPageReqVO reqVO) {
|
||||
return selectPage(MyBatisUtils.buildPage(reqVO), new LambdaQueryWrapper<SmsChannelDO>()
|
||||
.like(StrUtil.isNotBlank(reqVO.getName()), SmsChannelDO::getName, reqVO.getName())
|
||||
.like(StrUtil.isNotBlank(reqVO.getSignature()), SmsChannelDO::getName, reqVO.getSignature())
|
||||
);
|
||||
}
|
||||
|
||||
default List<SmsChannelDO> selectEnabledList() {
|
||||
return selectList(new LambdaQueryWrapper<SmsChannelDO>()
|
||||
.eq(SmsChannelDO::getStatus, CommonStatusEnum.ENABLE.getStatus())
|
||||
.orderByAsc(SmsChannelDO::getId)
|
||||
);
|
||||
}
|
||||
}
|
@ -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<SmsLog> {
|
||||
|
||||
}
|
@ -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<SmsTemplateDO> {
|
||||
|
||||
/**
|
||||
* 根据短信渠道id查询短信模板集合
|
||||
*
|
||||
* @param channelId 渠道id
|
||||
* @return 模板集合
|
||||
*/
|
||||
default List<SmsTemplateDO> selectListByChannelId(Long channelId) {
|
||||
return selectList(new LambdaQueryWrapper<SmsTemplateDO>()
|
||||
.eq(SmsTemplateDO::getChannelId, channelId)
|
||||
.eq(SmsTemplateDO::getStatus, CommonStatusEnum.ENABLE.getStatus())
|
||||
.orderByAsc(SmsTemplateDO::getId)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询有效短信模板集合
|
||||
*
|
||||
* @return 有效短信模板集合
|
||||
*/
|
||||
default List<SmsTemplateDO> selectEnabledList() {
|
||||
return selectList(new LambdaQueryWrapper<SmsTemplateDO>()
|
||||
.eq(SmsTemplateDO::getStatus, CommonStatusEnum.ENABLE.getStatus())
|
||||
.orderByAsc(SmsTemplateDO::getId)
|
||||
);
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
/**
|
||||
* msg 包,专门专门用于发送消息的功能,支撑上层的通用与核心业务。
|
||||
* 例如说:短信、邮件、app通知等等
|
||||
*
|
||||
*/
|
||||
package cn.iocoder.dashboard.modules.msg;
|
@ -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<SmsChannelDO> pageChannels(SmsChannelPageReqVO reqVO);
|
||||
|
||||
Long createChannel(SmsChannelCreateReqVO reqVO);
|
||||
|
||||
List<SmsChannelEnumRespVO> getChannelEnums();
|
||||
|
||||
/**
|
||||
* 查询渠道(包含名下模块)信息集合
|
||||
*
|
||||
* @return 渠道(包含名下模块)信息集合
|
||||
*/
|
||||
List<SmsChannelAllVO> listChannelAllEnabledInfo();
|
||||
|
||||
boolean flushChannel();
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
package cn.iocoder.dashboard.modules.msg.service.sms;
|
||||
|
||||
/**
|
||||
* 短信渠道Service接口
|
||||
*
|
||||
* @author zzf
|
||||
* @date 2021/1/25 9:24
|
||||
*/
|
||||
public interface SmsLogService {
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
package cn.iocoder.dashboard.modules.msg.service.sms;
|
||||
|
||||
/**
|
||||
* 短信渠道Service接口
|
||||
*
|
||||
* @author zzf
|
||||
* @date 2021/1/25 9:24
|
||||
*/
|
||||
public interface SmsTemplateService {
|
||||
}
|
@ -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<SmsChannelDO> 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<SmsChannelEnumRespVO> getChannelEnums() {
|
||||
return SmsChannelConvert.INSTANCE.convertEnum(Arrays.asList(SmsChannelEnum.values()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SmsChannelAllVO> listChannelAllEnabledInfo() {
|
||||
List<SmsChannelDO> channelDOList = mapper.selectEnabledList();
|
||||
if (ObjectUtil.isNull(channelDOList)) {
|
||||
return null;
|
||||
}
|
||||
List<SmsChannelAllVO> channelAllVOList = SmsChannelConvert.INSTANCE.convert(channelDOList);
|
||||
|
||||
channelAllVOList.forEach(smsChannelDO -> {
|
||||
|
||||
List<SmsTemplateDO> 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;
|
||||
}
|
||||
}
|
@ -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 {
|
||||
|
||||
}
|
@ -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 {
|
||||
}
|
@ -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值一致。");
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user