From 009f33210680bb77a727636732ce23ab5c8c5fb5 Mon Sep 17 00:00:00 2001 From: zengzefeng <986510453@qq.com> Date: Mon, 1 Feb 2021 14:25:22 +0800 Subject: [PATCH] 重构短信功能 --- sql/ruoyi-vue-pro.sql | 71 ----------------------------------------------------------------------- sql/sms.sql | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/cn/iocoder/dashboard/framework/sms/SmsBody.java | 28 ---------------------------- src/main/java/cn/iocoder/dashboard/framework/sms/SmsClient.java | 107 ----------------------------------------------------------------------------------------------------------- src/main/java/cn/iocoder/dashboard/framework/sms/SmsClientAdapter.java | 42 ------------------------------------------ src/main/java/cn/iocoder/dashboard/framework/sms/SmsResult.java | 27 --------------------------- src/main/java/cn/iocoder/dashboard/framework/sms/client/AbstractSmsClient.java | 32 ++++++++++++++++++++++++++++++++ src/main/java/cn/iocoder/dashboard/framework/sms/client/AliyunSmsClient.java | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/cn/iocoder/dashboard/framework/sms/client/SmsClient.java | 25 +++++++++++++++++++++++++ src/main/java/cn/iocoder/dashboard/framework/sms/core/SmsBody.java | 34 ++++++++++++++++++++++++++++++++++ src/main/java/cn/iocoder/dashboard/framework/sms/core/SmsClientFactory.java | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/cn/iocoder/dashboard/framework/sms/core/SmsResult.java | 27 +++++++++++++++++++++++++++ src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SmsChannelController.java | 6 ------ src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/SmsChannelAllVO.java | 58 ---------------------------------------------------------- src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/SmsChannelPropertyVO.java | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/SmsTemplateVO.java | 8 ++++++++ src/main/java/cn/iocoder/dashboard/modules/system/convert/sms/SmsChannelConvert.java | 4 ++-- src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/sms/SmsLogMapper.java | 4 ++-- src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/sms/SmsLog.java | 71 ----------------------------------------------------------------------- src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/sms/SmsLogDO.java | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/cn/iocoder/dashboard/modules/system/enums/SysErrorCodeConstants.java | 1 + src/main/java/cn/iocoder/dashboard/modules/system/enums/sms/SmsSendStatusEnum.java | 30 ++++++++++++++++++++++++++++++ src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/sms/SmsSendConsumer.java | 31 +++++++++++++++++++++++++++++++ src/main/java/cn/iocoder/dashboard/modules/system/mq/message/sms/SmsSendMessage.java | 25 +++++++++++++++++++++++++ src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/sms/SmsProducer.java | 31 +++++++++++++++++++++++++++++++ src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SmsChannelService.java | 37 +++++++++++++++++++++++++++++++++---- src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SmsLogService.java | 25 +++++++++++++++++++++++++ src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SmsService.java | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SmsChannelServiceImpl.java | 47 ++++++++++++++++++++++++++++++++++++++--------- src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SmsLogServiceImpl.java | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SmsServiceImpl.java | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/cn/iocoder/dashboard/modules/system/sms/SmsConfiguration.java | 34 ---------------------------------- src/main/java/cn/iocoder/dashboard/modules/system/sms/SmsSenderUtils.java | 143 ----------------------------------------------------------------------------------------------------------------------------------------------- src/main/java/cn/iocoder/dashboard/modules/system/sms/client/AliSmsClient.java | 91 ------------------------------------------------------------------------------------------- src/main/java/cn/iocoder/dashboard/modules/system/sms/proxy/SmsClientLogProxy.java | 48 ------------------------------------------------ src/main/java/cn/iocoder/dashboard/util/string/StrUtils.java | 21 +++++++++++++++++++++ 36 files changed, 946 insertions(+), 743 deletions(-) create mode 100644 sql/sms.sql delete mode 100644 src/main/java/cn/iocoder/dashboard/framework/sms/SmsBody.java delete mode 100644 src/main/java/cn/iocoder/dashboard/framework/sms/SmsClient.java delete mode 100644 src/main/java/cn/iocoder/dashboard/framework/sms/SmsClientAdapter.java delete mode 100644 src/main/java/cn/iocoder/dashboard/framework/sms/SmsResult.java create mode 100644 src/main/java/cn/iocoder/dashboard/framework/sms/client/AbstractSmsClient.java create mode 100644 src/main/java/cn/iocoder/dashboard/framework/sms/client/AliyunSmsClient.java create mode 100644 src/main/java/cn/iocoder/dashboard/framework/sms/client/SmsClient.java create mode 100644 src/main/java/cn/iocoder/dashboard/framework/sms/core/SmsBody.java create mode 100644 src/main/java/cn/iocoder/dashboard/framework/sms/core/SmsClientFactory.java create mode 100644 src/main/java/cn/iocoder/dashboard/framework/sms/core/SmsResult.java delete mode 100644 src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/SmsChannelAllVO.java create mode 100644 src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/SmsChannelPropertyVO.java delete mode 100644 src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/sms/SmsLog.java create mode 100644 src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/sms/SmsLogDO.java create mode 100644 src/main/java/cn/iocoder/dashboard/modules/system/enums/sms/SmsSendStatusEnum.java create mode 100644 src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/sms/SmsSendConsumer.java create mode 100644 src/main/java/cn/iocoder/dashboard/modules/system/mq/message/sms/SmsSendMessage.java create mode 100644 src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/sms/SmsProducer.java create mode 100644 src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SmsService.java create mode 100644 src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SmsServiceImpl.java delete mode 100644 src/main/java/cn/iocoder/dashboard/modules/system/sms/SmsConfiguration.java delete mode 100644 src/main/java/cn/iocoder/dashboard/modules/system/sms/SmsSenderUtils.java delete mode 100644 src/main/java/cn/iocoder/dashboard/modules/system/sms/client/AliSmsClient.java delete mode 100644 src/main/java/cn/iocoder/dashboard/modules/system/sms/proxy/SmsClientLogProxy.java diff --git a/sql/ruoyi-vue-pro.sql b/sql/ruoyi-vue-pro.sql index 9355fab..af7f492 100644 --- a/sql/ruoyi-vue-pro.sql +++ b/sql/ruoyi-vue-pro.sql @@ -884,75 +884,4 @@ INSERT INTO `sys_user_role` VALUES (5, 100, 1, '', NULL, '', NULL, b'0'); INSERT INTO `sys_user_role` VALUES (6, 100, 2, '', NULL, '', NULL, b'0'); COMMIT; - --- ---------------------------- --- Table structure for sms_channel --- ---------------------------- -DROP TABLE IF EXISTS `sms_channel`; -CREATE TABLE `sms_channel` ( - `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增编号', - `code` varchar(50) not null COMMENT '编码(来自枚举类 阿里、华为、七牛等)', - `api_key` varchar(100) NOT NULL COMMENT '账号id', - `api_secret` varchar(100) NOT NULL COMMENT '账号秘钥', - `api_signature_id` varchar(100) NOT NULL COMMENT '实际渠道签名唯一标识', - `name` varchar(50) not null COMMENT '名称', - `signature` varchar(50) not null COMMENT '签名值', - `remark` varchar(200) NOT NULL COMMENT '备注', - - `status` tinyint(4) NOT NULL default 0 COMMENT '启用状态(0正常 1停用)', - `create_by` varchar(64) not null DEFAULT '' COMMENT '创建者', - `create_time` datetime DEFAULT NULL COMMENT '创建时间', - `update_by` varchar(64) DEFAULT '' COMMENT '更新者', - `update_time` datetime DEFAULT NULL COMMENT '更新时间', - `deleted` bit(1) DEFAULT b'0' COMMENT '是否删除', - PRIMARY KEY (`id`) USING BTREE -) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='短信渠道'; -/* - 优先级值一样时,按照id顺序取值 -*/ - --- ---------------------------- --- Table structure for sms_template --- ---------------------------- -DROP TABLE IF EXISTS `sms_template`; -CREATE TABLE `sms_template` ( - `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增编号', - `channel_code` varchar(50) not null COMMENT '短信渠道编码(来自枚举类)', - `channel_id` bigint(20) not null COMMENT '短信渠道id (对于前端来说就是绑定一个签名)', - `type` tinyint(4) NOT NULL default 1 COMMENT '消息类型 [0验证码 1短信通知 2推广短信 3国际/港澳台消息]', - `biz_code` varchar(50) not null COMMENT '业务编码(来自数据字典, 用户自定义业务场景 一个场景可以有多个模板)', - `code` varchar(50) not null COMMENT '编码', - `name` varchar(50) not null COMMENT '名称', - `api_template_id` varchar(100) NOT NULL COMMENT '实际渠道模板唯一标识', - `content` varchar(1000) NOT NULL DEFAULT '' COMMENT '内容', - `params` varchar(200) NOT NULL DEFAULT '' COMMENT '参数数组(自动根据内容生成)', - `remark` varchar(200) NOT NULL COMMENT '备注', - - `status` tinyint(4) NOT NULL default 0 COMMENT '启用状态(0正常 1停用)', - `create_by` varchar(64) not null DEFAULT '' COMMENT '创建者', - `create_time` datetime DEFAULT NULL COMMENT '创建时间', - `update_by` varchar(64) DEFAULT '' COMMENT '更新者', - `update_time` datetime DEFAULT NULL COMMENT '更新时间', - `deleted` bit(1) DEFAULT b'0' COMMENT '是否删除', - PRIMARY KEY (`id`) USING BTREE -) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='短信模板'; - --- ---------------------------- --- Table structure for sms_log --- ---------------------------- -DROP TABLE IF EXISTS `sms_log`; -CREATE TABLE `sms_log` ( - `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增编号', - `channel_code` varchar(50) not null COMMENT '短信渠道编码(来自枚举类)', - `api_sms_id` varchar(50) not null COMMENT '实际渠道短信唯一标识', - `template_id` bigint(20) NOT NULL COMMENT '模板id', - `phone` char(11) not null COMMENT '手机号', - `content` varchar(1000) NOT NULL DEFAULT '' COMMENT '内容', - `remark` varchar(200) NOT NULL COMMENT '备注', - `send_status` tinyint(4) NOT NULL default 0 COMMENT '发送状态(0发送中 1成功 2失败)', - `create_by` varchar(64) not null DEFAULT '' COMMENT '创建者', - `create_time` datetime DEFAULT NULL COMMENT '创建时间', - PRIMARY KEY (`id`) USING BTREE -) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='短信日志'; - SET FOREIGN_KEY_CHECKS = 1; diff --git a/sql/sms.sql b/sql/sms.sql new file mode 100644 index 0000000..82d8541 --- /dev/null +++ b/sql/sms.sql @@ -0,0 +1,82 @@ +/* + --2021.02.01 by fight, sms about table info +*/ + +-- ---------------------------- +-- Table structure for sms_channel +-- ---------------------------- +DROP TABLE IF EXISTS `sms_channel`; +CREATE TABLE `sms_channel` +( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增编号', + `code` varchar(50) NOT NULL COMMENT '编码(来自枚举类 阿里、华为、七牛等)', + `api_key` varchar(100) NOT NULL COMMENT '账号id', + `api_secret` varchar(100) NOT NULL COMMENT '账号秘钥', + `api_signature_id` varchar(100) NOT NULL COMMENT '实际渠道签名唯一标识', + `name` varchar(50) NOT NULL COMMENT '名称', + `signature` varchar(50) NOT NULL COMMENT '签名值', + `remark` varchar(200) NOT NULL COMMENT '备注', + + `status` tinyint(4) NOT NULL DEFAULT 0 COMMENT '启用状态(0正常 1停用)', + `create_by` varchar(64) NOT NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + `deleted` bit(1) DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB + AUTO_INCREMENT = 1 + DEFAULT CHARSET = utf8mb4 COMMENT ='短信渠道'; +/* + 优先级值一样时,按照id顺序取值 +*/ + +-- ---------------------------- +-- Table structure for sms_template +-- ---------------------------- +DROP TABLE IF EXISTS `sms_template`; +CREATE TABLE `sms_template` +( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增编号', + `channel_code` varchar(50) NOT NULL COMMENT '短信渠道编码(来自枚举类)', + `channel_id` bigint(20) NOT NULL COMMENT '短信渠道id (对于前端来说就是绑定一个签名)', + `type` tinyint(4) NOT NULL DEFAULT 1 COMMENT '消息类型 [0验证码 1短信通知 2推广短信 3国际/港澳台消息]', + `biz_code` varchar(50) NOT NULL COMMENT '业务编码(来自数据字典, 用户自定义业务场景 一个场景可以有多个模板)', + `code` varchar(50) NOT NULL COMMENT '编码', + `name` varchar(50) NOT NULL COMMENT '名称', + `api_template_id` varchar(100) NOT NULL COMMENT '实际渠道模板唯一标识', + `content` varchar(1000) NOT NULL DEFAULT '' COMMENT '内容', + `params` varchar(200) NOT NULL DEFAULT '' COMMENT '参数数组(自动根据内容生成)', + `remark` varchar(200) NOT NULL COMMENT '备注', + + `status` tinyint(4) NOT NULL DEFAULT 0 COMMENT '启用状态(0正常 1停用)', + `create_by` varchar(64) NOT NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime DEFAULT NULL COMMENT '更新时间', + `deleted` bit(1) DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB + AUTO_INCREMENT = 1 + DEFAULT CHARSET = utf8mb4 COMMENT ='短信模板'; + +-- ---------------------------- +-- Table structure for sms_log +-- ---------------------------- +DROP TABLE IF EXISTS `sms_log`; +CREATE TABLE `sms_log` +( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增编号', + `channel_code` varchar(50) NOT NULL COMMENT '短信渠道编码(来自枚举类)', + `channel_id` bigint(20) NOT NULL COMMENT '短信渠道id', + `template_code` varchar(50) NOT NULL COMMENT '渠道编码', + `phones` char(11) NOT NULL COMMENT '手机号(数组json字符串)', + `content` varchar(1000) NOT NULL DEFAULT '' COMMENT '内容', + `remark` varchar(200) DEFAULT NULL COMMENT '备注', + `send_status` tinyint(4) NOT NULL DEFAULT 2 COMMENT '发送状态(1异步推送中 2发送中 3失败 4成功)', + `create_by` varchar(64) NOT NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime DEFAULT NULL COMMENT '创建时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB + AUTO_INCREMENT = 1 + DEFAULT CHARSET = utf8mb4 COMMENT ='短信日志'; diff --git a/src/main/java/cn/iocoder/dashboard/framework/sms/SmsBody.java b/src/main/java/cn/iocoder/dashboard/framework/sms/SmsBody.java deleted file mode 100644 index 48fb225..0000000 --- a/src/main/java/cn/iocoder/dashboard/framework/sms/SmsBody.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.dashboard.framework.sms; - -import cn.iocoder.dashboard.util.json.JsonUtils; -import lombok.Data; - -import java.util.Map; - -/** - * 消息内容实体类 - */ -@Data -public class SmsBody { - - /** - * 模板编码 - */ - private String code; - - /** - * 参数列表 - */ - private Map params; - - public String getParamsStr() { - return JsonUtils.toJsonString(params); - } - -} diff --git a/src/main/java/cn/iocoder/dashboard/framework/sms/SmsClient.java b/src/main/java/cn/iocoder/dashboard/framework/sms/SmsClient.java deleted file mode 100644 index bf1a44f..0000000 --- a/src/main/java/cn/iocoder/dashboard/framework/sms/SmsClient.java +++ /dev/null @@ -1,107 +0,0 @@ -package cn.iocoder.dashboard.framework.sms; - -import org.apache.commons.lang3.StringUtils; - -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; - -/** - * 短信父接口 - * - * @author zzf - * @date 2021/1/25 14:14 - */ -public interface SmsClient { - - /** - * 发送消息 - * - * @param msgBody 消息内容 - * @param targets 发送对象列表 - * @return 是否发送成功 - */ - SmsResult send(SmsBody msgBody, Collection targets); - - /** - * 发送消息 - * - * @param msgBody 消息内容 - * @param target 发送对象 - * @return 是否发送成功 - */ - default SmsResult send(SmsBody msgBody, String target) { - if (StringUtils.isBlank(target)) { - return failResult(); - } - - return send(msgBody, Collections.singletonList(target)); - } - - /** - * 发送消息 - * - * @param msgBody 消息内容 - * @param targets 发送对象列表 - * @return 是否发送成功 - */ - default SmsResult send(SmsBody msgBody, String... targets) { - if (targets == null) { - return failResult(); - } - - return send(msgBody, Arrays.asList(targets)); - } - - - /** - * 异步发送消息 - * - * @param msgBody 消息内容 - * @param targets 发送对象列表 - * @return 是否发送成功 - */ - SmsResult sendAsync(SmsBody msgBody, Collection targets); - - /** - * 异步发送消息 - * - * @param msgBody 消息内容 - * @param target 发送对象 - * @return 是否发送成功 - */ - default SmsResult sendAsync(SmsBody msgBody, String target) { - if (StringUtils.isBlank(target)) { - return failResult("target must not null."); - } - - return sendAsync(msgBody, Collections.singletonList(target)); - } - - /** - * 异步发送消息 - * - * @param msgBody 消息内容 - * @param targets 发送对象列表 - * @return 是否发送成功 - */ - default SmsResult sendAsync(SmsBody msgBody, String... targets) { - if (targets == null) { - return failResult("targets must not null."); - } - - return sendAsync(msgBody, Arrays.asList(targets)); - } - - default SmsResult failResult() { - SmsResult resultBody = new SmsResult<>(); - resultBody.setSuccess(false); - return resultBody; - } - - default SmsResult failResult(String message) { - SmsResult resultBody = failResult(); - resultBody.setMessage(message); - return resultBody; - } -} \ No newline at end of file diff --git a/src/main/java/cn/iocoder/dashboard/framework/sms/SmsClientAdapter.java b/src/main/java/cn/iocoder/dashboard/framework/sms/SmsClientAdapter.java deleted file mode 100644 index 6edf764..0000000 --- a/src/main/java/cn/iocoder/dashboard/framework/sms/SmsClientAdapter.java +++ /dev/null @@ -1,42 +0,0 @@ -package cn.iocoder.dashboard.framework.sms; - -import cn.hutool.core.util.ObjectUtil; -import cn.iocoder.dashboard.common.exception.ServiceException; - -import java.util.Collection; -import java.util.Collections; -import java.util.Map; - -import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.SMS_CHANNEL_NOT_INIT; - -/** - * 抽象短信客户端工厂 - * - * @author zzf - * @date 2021/1/28 14:01 - */ -public class SmsClientAdapter { - - private final Map> smsSenderMap; - - public SmsClientAdapter(Map> smsSenderMap) { - if (ObjectUtil.isEmpty(smsSenderMap)) { - throw new ServiceException(SMS_CHANNEL_NOT_INIT); - } - this.smsSenderMap = smsSenderMap; - } - - public void flushClient(Map> smsSenderMap) { - this.smsSenderMap.clear(); - smsSenderMap.putAll(Collections.unmodifiableMap(smsSenderMap)); - } - - public SmsResult send(Long channelId, SmsBody smsBody, Collection targetPhone) { - SmsClient smsClient = getSmsSender(channelId); - return smsClient.send(smsBody, targetPhone); - } - - private SmsClient getSmsSender(Long channelId) { - return smsSenderMap.get(channelId); - } -} diff --git a/src/main/java/cn/iocoder/dashboard/framework/sms/SmsResult.java b/src/main/java/cn/iocoder/dashboard/framework/sms/SmsResult.java deleted file mode 100644 index b994514..0000000 --- a/src/main/java/cn/iocoder/dashboard/framework/sms/SmsResult.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.iocoder.dashboard.framework.sms; - -import lombok.Data; - -import java.io.Serializable; - -/** - * 消息内容实体类 - */ -@Data -public class SmsResult implements Serializable { - - /** - * 是否成功 - */ - private Boolean success; - - /** - * 提示 - */ - private String message; - - /** - * 返回值 - */ - private T result; -} diff --git a/src/main/java/cn/iocoder/dashboard/framework/sms/client/AbstractSmsClient.java b/src/main/java/cn/iocoder/dashboard/framework/sms/client/AbstractSmsClient.java new file mode 100644 index 0000000..043dd2a --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/framework/sms/client/AbstractSmsClient.java @@ -0,0 +1,32 @@ +package cn.iocoder.dashboard.framework.sms.client; + +import cn.iocoder.dashboard.modules.system.controller.sms.vo.SmsChannelPropertyVO; + +/** + * 抽象短息客户端 + * + * @author zzf + * @date 2021/2/1 9:28 + */ +public abstract class AbstractSmsClient implements SmsClient { + + /** + * 短信渠道参数 + */ + protected final SmsChannelPropertyVO channelVO; + + /** + * 构造阿里云短信发送处理 + * + * @param channelVO 阿里云短信配置 + */ + public AbstractSmsClient(SmsChannelPropertyVO channelVO) { + this.channelVO = channelVO; + } + + + public SmsChannelPropertyVO getProperty() { + return channelVO; + } + +} diff --git a/src/main/java/cn/iocoder/dashboard/framework/sms/client/AliyunSmsClient.java b/src/main/java/cn/iocoder/dashboard/framework/sms/client/AliyunSmsClient.java new file mode 100644 index 0000000..39d3594 --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/framework/sms/client/AliyunSmsClient.java @@ -0,0 +1,88 @@ +package cn.iocoder.dashboard.framework.sms.client; + +import cn.iocoder.dashboard.framework.sms.core.SmsBody; +import cn.iocoder.dashboard.framework.sms.core.SmsResult; +import cn.iocoder.dashboard.modules.system.controller.sms.vo.SmsChannelPropertyVO; +import com.aliyuncs.DefaultAcsClient; +import com.aliyuncs.IAcsClient; +import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest; +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 AliyunSmsClient extends AbstractSmsClient { + + 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 IAcsClient acsClient; + + /** + * 构造阿里云短信发送处理 + * + * @param channelVO 阿里云短信配置 + */ + public AliyunSmsClient(SmsChannelPropertyVO channelVO) { + super(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 send(SmsBody smsBody, Collection targets) { + SendSmsRequest request = new SendSmsRequest(); + request.setSysMethod(MethodType.POST); + request.setPhoneNumbers(StringUtils.join(targets, ",")); + request.setSignName(channelVO.getApiSignatureId()); + request.setTemplateCode(channelVO.getTemplateByTemplateCode(smsBody.getTemplateCode()).getApiTemplateId()); + request.setTemplateParam(smsBody.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 resultBody = new SmsResult<>(); + resultBody.setSuccess(result); + resultBody.setResult(sendSmsResponse); + return resultBody; + } catch (Exception e) { + log.debug(e.getMessage(), e); + return failResult("发送异常: " + e.getMessage()); + } + } + + SmsResult failResult(String message) { + SmsResult resultBody = new SmsResult<>(); + resultBody.setSuccess(false); + resultBody.setMessage(message); + return resultBody; + } + +} diff --git a/src/main/java/cn/iocoder/dashboard/framework/sms/client/SmsClient.java b/src/main/java/cn/iocoder/dashboard/framework/sms/client/SmsClient.java new file mode 100644 index 0000000..290d217 --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/framework/sms/client/SmsClient.java @@ -0,0 +1,25 @@ +package cn.iocoder.dashboard.framework.sms.client; + +import cn.iocoder.dashboard.framework.sms.core.SmsBody; +import cn.iocoder.dashboard.framework.sms.core.SmsResult; + +import java.util.Collection; + +/** + * 短信父接口 + * + * @author zzf + * @date 2021/1/25 14:14 + */ +public interface SmsClient { + + /** + * 发送消息 + * + * @param smsBody 消息内容 + * @param targets 发送对象列表 + * @return 是否发送成功 + */ + SmsResult send(SmsBody smsBody, Collection targets); + +} \ No newline at end of file diff --git a/src/main/java/cn/iocoder/dashboard/framework/sms/core/SmsBody.java b/src/main/java/cn/iocoder/dashboard/framework/sms/core/SmsBody.java new file mode 100644 index 0000000..9b13243 --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/framework/sms/core/SmsBody.java @@ -0,0 +1,34 @@ +package cn.iocoder.dashboard.framework.sms.core; + +import cn.iocoder.dashboard.util.json.JsonUtils; +import lombok.Data; + +import java.util.Map; +import java.util.UUID; + +/** + * 消息内容实体类 + */ +@Data +public class SmsBody { + + /** + * 消息日志id + */ + private Long smsLogId; + + /** + * 模板编码 + */ + private String templateCode; + + /** + * 参数列表 + */ + private Map params; + + public String getParamsStr() { + return JsonUtils.toJsonString(params); + } + +} diff --git a/src/main/java/cn/iocoder/dashboard/framework/sms/core/SmsClientFactory.java b/src/main/java/cn/iocoder/dashboard/framework/sms/core/SmsClientFactory.java new file mode 100644 index 0000000..6c1eaf0 --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/framework/sms/core/SmsClientFactory.java @@ -0,0 +1,71 @@ +package cn.iocoder.dashboard.framework.sms.core; + +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.dashboard.common.enums.SmsChannelEnum; +import cn.iocoder.dashboard.common.exception.ServiceException; +import cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil; +import cn.iocoder.dashboard.framework.sms.client.AbstractSmsClient; +import cn.iocoder.dashboard.framework.sms.client.AliyunSmsClient; +import cn.iocoder.dashboard.modules.system.controller.sms.vo.SmsChannelPropertyVO; +import org.springframework.stereotype.Component; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.*; + +/** + * 短信客户端工厂 + * + * @author zzf + * @date 2021/1/28 14:01 + */ +@Component +public class SmsClientFactory { + + private final Map> smsSenderMap = new ConcurrentHashMap<>(8); + + /** + * 创建短信客户端 + * + * @param propertyVO 参数对象 + * @return 客户端id(默认channelId) + */ + public Long createClient(SmsChannelPropertyVO propertyVO) { + if (StrUtil.isBlank(propertyVO.getCode())) { + throw ServiceExceptionUtil.exception(PARAM_VALUE_IS_NULL, "短信渠道编码"); + } + if (ObjectUtil.isNull(propertyVO.getId())) { + throw ServiceExceptionUtil.exception(PARAM_VALUE_IS_NULL, "短信渠道ID"); + } + + AbstractSmsClient sender = createClient(SmsChannelEnum.getByCode(propertyVO.getCode()), propertyVO); + smsSenderMap.put(propertyVO.getId(), sender); + return propertyVO.getId(); + } + + private AbstractSmsClient createClient(SmsChannelEnum channelEnum, SmsChannelPropertyVO channelVO) { + if (channelEnum == null) { + throw new ServiceException(INVALID_CHANNEL_CODE); + } + switch (channelEnum) { + case ALI: + return new AliyunSmsClient(channelVO); + // TODO fill more channel + default: + break; + } + throw new ServiceException(SMS_SENDER_NOT_FOUND); + } + + /** + * 获取短信客户端 + * + * @param channelId 渠道id + * @return 短信id + */ + public AbstractSmsClient getClient(Long channelId) { + return smsSenderMap.get(channelId); + } +} diff --git a/src/main/java/cn/iocoder/dashboard/framework/sms/core/SmsResult.java b/src/main/java/cn/iocoder/dashboard/framework/sms/core/SmsResult.java new file mode 100644 index 0000000..a626bb7 --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/framework/sms/core/SmsResult.java @@ -0,0 +1,27 @@ +package cn.iocoder.dashboard.framework.sms.core; + +import lombok.Data; + +import java.io.Serializable; + +/** + * 消息内容实体类 + */ +@Data +public class SmsResult implements Serializable { + + /** + * 是否成功 + */ + private Boolean success; + + /** + * 提示 + */ + private String message; + + /** + * 返回值 + */ + private T result; +} diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SmsChannelController.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SmsChannelController.java index a75f9e2..9320975 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SmsChannelController.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/SmsChannelController.java @@ -44,11 +44,5 @@ public class SmsChannelController { return success(service.createChannel(reqVO)); } - @ApiOperation("刷新消息渠道信息") - @PutMapping("/flush") - public CommonResult flushChannel() { - return success(service.flushChannel()); - } - } diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/SmsChannelAllVO.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/SmsChannelAllVO.java deleted file mode 100644 index 042cdda..0000000 --- a/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/SmsChannelAllVO.java +++ /dev/null @@ -1,58 +0,0 @@ -package cn.iocoder.dashboard.modules.system.controller.sms.vo; - -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.io.Serializable; -import java.util.List; - -/** - * 渠道(包含模板)信息VO类 - * - * @author zzf - * @date 2021/1/25 17:01 - */ -@Data -@EqualsAndHashCode -public class SmsChannelAllVO implements Serializable { - - /** - * id - */ - private Long id; - - /** - * 编码(来自枚举类 阿里、华为、七牛等) - */ - private String code; - - /** - * 渠道账号id - */ - private String apiKey; - - /** - * 渠道账号秘钥 - */ - private String apiSecret; - - /** - * 实际渠道签名唯一标识 - */ - private String apiSignatureId; - - /** - * 签名值 - */ - private String signature; - - /** - * 该渠道名下的短信模板集合 - */ - private List templateList; - - public SmsTemplateVO getTemplateByTemplateCode(String tempCode) { - return templateList.stream().filter(s -> s.getCode().equals(tempCode)).findFirst().get(); - } - -} diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/SmsChannelPropertyVO.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/SmsChannelPropertyVO.java new file mode 100644 index 0000000..ab4d735 --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/SmsChannelPropertyVO.java @@ -0,0 +1,58 @@ +package cn.iocoder.dashboard.modules.system.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 SmsChannelPropertyVO implements Serializable { + + /** + * id + */ + private Long id; + + /** + * 编码(来自枚举类 阿里、华为、七牛等) + */ + private String code; + + /** + * 渠道账号id + */ + private String apiKey; + + /** + * 渠道账号秘钥 + */ + private String apiSecret; + + /** + * 实际渠道签名唯一标识 + */ + private String apiSignatureId; + + /** + * 签名值 + */ + private String signature; + + /** + * 该渠道名下的短信模板集合 + */ + private List templateList; + + public SmsTemplateVO getTemplateByTemplateCode(String tempCode) { + return templateList.stream().filter(s -> s.getCode().equals(tempCode)).findFirst().get(); + } + +} diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/SmsTemplateVO.java b/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/SmsTemplateVO.java index c5156a6..d9daf75 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/SmsTemplateVO.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/controller/sms/vo/SmsTemplateVO.java @@ -17,6 +17,7 @@ public class SmsTemplateVO { * 业务编码(来自数据字典, 用户自定义业务场景 一个场景可以有多个模板) */ private String bizCode; + /** * 编码 */ @@ -27,4 +28,11 @@ public class SmsTemplateVO { */ private String apiTemplateId; + /** + * 内容 + */ + private String content; + + + } diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/convert/sms/SmsChannelConvert.java b/src/main/java/cn/iocoder/dashboard/modules/system/convert/sms/SmsChannelConvert.java index af87d22..985de75 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/convert/sms/SmsChannelConvert.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/convert/sms/SmsChannelConvert.java @@ -2,7 +2,7 @@ package cn.iocoder.dashboard.modules.system.convert.sms; import cn.iocoder.dashboard.common.enums.SmsChannelEnum; import cn.iocoder.dashboard.common.pojo.PageResult; -import cn.iocoder.dashboard.modules.system.controller.sms.vo.SmsChannelAllVO; +import cn.iocoder.dashboard.modules.system.controller.sms.vo.SmsChannelPropertyVO; import cn.iocoder.dashboard.modules.system.controller.sms.vo.req.SmsChannelCreateReqVO; import cn.iocoder.dashboard.modules.system.controller.sms.vo.resp.SmsChannelEnumRespVO; import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.sms.SmsChannelDO; @@ -28,7 +28,7 @@ public interface SmsChannelConvert { List convertEnum(List bean); - List convert(List bean); + List convert(List bean); } diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/sms/SmsLogMapper.java b/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/sms/SmsLogMapper.java index a5dce01..2e52b07 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/sms/SmsLogMapper.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dao/sms/SmsLogMapper.java @@ -1,10 +1,10 @@ package cn.iocoder.dashboard.modules.system.dal.mysql.dao.sms; -import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.sms.SmsLog; +import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.sms.SmsLogDO; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.apache.ibatis.annotations.Mapper; @Mapper -public interface SmsLogMapper extends BaseMapper { +public interface SmsLogMapper extends BaseMapper { } diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/sms/SmsLog.java b/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/sms/SmsLog.java deleted file mode 100644 index 169369b..0000000 --- a/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/sms/SmsLog.java +++ /dev/null @@ -1,71 +0,0 @@ -package cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.sms; - -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.io.Serializable; -import java.util.Date; - -/** - * 短信日志 - * - * @author zzf - * @since 2021-01-25 - */ -@Data -@EqualsAndHashCode -@TableName(value = "sms_log", autoResultMap = true) -public class SmsLog implements Serializable { - - /** - * 自增编号 - */ - private Long id; - - /** - * 短信渠道编码(来自枚举类) - */ - private String channelCode; - - /** - * 实际渠道短信唯一标识 - */ - private String apiSmsId; - - /** - * 模板id - */ - private Long templateId; - - /** - * 手机号 - */ - private String phone; - - /** - * 内容 - */ - private String content; - - /** - * 备注 - */ - private String remark; - - /** - * 发送状态(0发送中 1成功 2失败) - */ - private Integer sendStatus; - - /** - * 创建者 - */ - private String createBy; - - /** - * 创建时间 - */ - private Date createTime; - -} diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/sms/SmsLogDO.java b/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/sms/SmsLogDO.java new file mode 100644 index 0000000..10ffef4 --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dataobject/sms/SmsLogDO.java @@ -0,0 +1,73 @@ +package cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.sms; + +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.Date; + +/** + * 短信日志 + * + * @author zzf + * @since 2021-01-25 + */ +@Data +@EqualsAndHashCode +@Accessors(chain = true) +@TableName(value = "sms_log", autoResultMap = true) +public class SmsLogDO implements Serializable { + + /** + * 自增编号 + */ + private Long id; + + /** + * 短信渠道编码(来自枚举类) + */ + private String channelCode; + + /** + * 短信渠道id + */ + private Long channelId; + + /** + * 模板id + */ + private String templateCode; + + /** + * 手机号(数组json字符串) + */ + private String phones; + + /** + * 内容 + */ + private String content; + + /** + * 备注 + */ + private String remark; + + /** + * 发送状态(1异步推送中 2发送中 3失败 4成功) + */ + private Integer sendStatus; + + /** + * 创建者 + */ + private String createBy; + + /** + * 创建时间 + */ + private Date createTime; + +} diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/enums/SysErrorCodeConstants.java b/src/main/java/cn/iocoder/dashboard/modules/system/enums/SysErrorCodeConstants.java index 05e9e63..a1fc081 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/enums/SysErrorCodeConstants.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/enums/SysErrorCodeConstants.java @@ -83,5 +83,6 @@ public interface SysErrorCodeConstants { ErrorCode SMS_TEMPLATE_NOT_FOUND = new ErrorCode(1003001003, "没有短信模板信息, 请初始化sms_template表数据。"); ErrorCode SMS_SENDER_NOT_FOUND = new ErrorCode(1003001004, "没有找到对应的短信发送对象,请检查sms_channel表和sms_template表数据"); ErrorCode INVALID_CHANNEL_CODE = new ErrorCode(1003001005, "非法的短信渠道code,请检查sms_channel表的code值是否与SmsChannelEnum中的code值一致。"); + ErrorCode PARAM_VALUE_IS_NULL = new ErrorCode(1003001006, "参数【{}】不能为空"); } diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/enums/sms/SmsSendStatusEnum.java b/src/main/java/cn/iocoder/dashboard/modules/system/enums/sms/SmsSendStatusEnum.java new file mode 100644 index 0000000..426e4cb --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/modules/system/enums/sms/SmsSendStatusEnum.java @@ -0,0 +1,30 @@ +package cn.iocoder.dashboard.modules.system.enums.sms; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 短信发送状态 + * + * @author zzf + * @date 2021/2/1 13:39 + */ +@Getter +@AllArgsConstructor +public enum SmsSendStatusEnum { + + //异步转发中 + ASYNC(1), + + //发送中 + SENDING(2), + + //失败 + FAIL(3), + + //成功 + SUCCESS(4); + + private final int status; + +} diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/sms/SmsSendConsumer.java b/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/sms/SmsSendConsumer.java new file mode 100644 index 0000000..5da9703 --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/sms/SmsSendConsumer.java @@ -0,0 +1,31 @@ +package cn.iocoder.dashboard.modules.system.mq.consumer.sms; + +import cn.iocoder.dashboard.framework.redis.core.pubsub.AbstractChannelMessageListener; +import cn.iocoder.dashboard.framework.sms.core.SmsResult; +import cn.iocoder.dashboard.modules.system.mq.message.dept.SysDeptRefreshMessage; +import cn.iocoder.dashboard.modules.system.mq.message.sms.SmsSendMessage; +import cn.iocoder.dashboard.modules.system.service.sms.SmsService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; + +/** + * 针对 {@link SysDeptRefreshMessage} 的消费者 + * + * @author 芋道源码 + */ +@Component +@Slf4j +public class SmsSendConsumer extends AbstractChannelMessageListener { + + @Resource + private SmsService smsService; + + @Override + public void onMessage(SmsSendMessage message) { + log.info("[onMessage][收到 发送短信 消息]"); + SmsResult send = smsService.send(message.getSmsBody(), message.getTargetPhones()); + } + +} diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/sms/SmsSendMessage.java b/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/sms/SmsSendMessage.java new file mode 100644 index 0000000..8ca1207 --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/modules/system/mq/message/sms/SmsSendMessage.java @@ -0,0 +1,25 @@ +package cn.iocoder.dashboard.modules.system.mq.message.sms; + +import cn.iocoder.dashboard.framework.redis.core.pubsub.ChannelMessage; +import cn.iocoder.dashboard.framework.sms.core.SmsBody; +import lombok.Data; + +import java.util.Collection; +import java.util.List; + +/** + * 部门数据刷新 Message + */ +@Data +public class SmsSendMessage implements ChannelMessage { + + private SmsBody smsBody; + + private List targetPhones; + + @Override + public String getChannel() { + return "sms.send"; + } + +} diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/sms/SmsProducer.java b/src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/sms/SmsProducer.java new file mode 100644 index 0000000..892b333 --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/sms/SmsProducer.java @@ -0,0 +1,31 @@ +package cn.iocoder.dashboard.modules.system.mq.producer.sms; + +import cn.iocoder.dashboard.framework.redis.core.util.RedisMessageUtils; +import cn.iocoder.dashboard.framework.sms.core.SmsBody; +import cn.iocoder.dashboard.modules.system.mq.message.sms.SmsSendMessage; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 短信的 Producer + */ +@Component +public class SmsProducer { + + @Resource + private StringRedisTemplate stringRedisTemplate; + + /** + * 发送 {@link SmsSendMessage} 消息 + */ + public void sendSmsSendMessage(SmsBody smsBody, List targetPhoneList) { + SmsSendMessage message = new SmsSendMessage(); + message.setSmsBody(smsBody); + message.setTargetPhones(targetPhoneList); + RedisMessageUtils.sendChannelMessage(stringRedisTemplate, message); + } + +} diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SmsChannelService.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SmsChannelService.java index 3040f3b..5fd39c2 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SmsChannelService.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SmsChannelService.java @@ -1,7 +1,8 @@ package cn.iocoder.dashboard.modules.system.service.sms; import cn.iocoder.dashboard.common.pojo.PageResult; -import cn.iocoder.dashboard.modules.system.controller.sms.vo.SmsChannelAllVO; +import cn.iocoder.dashboard.framework.sms.client.AbstractSmsClient; +import cn.iocoder.dashboard.modules.system.controller.sms.vo.SmsChannelPropertyVO; import cn.iocoder.dashboard.modules.system.controller.sms.vo.req.SmsChannelCreateReqVO; import cn.iocoder.dashboard.modules.system.controller.sms.vo.req.SmsChannelPageReqVO; import cn.iocoder.dashboard.modules.system.controller.sms.vo.resp.SmsChannelEnumRespVO; @@ -17,18 +18,46 @@ import java.util.List; */ public interface SmsChannelService { + /** + * 初始化短信渠道 + */ + void initSmsClient(); + + /** + * 分页查询短信渠道信息 + * + * @param reqVO 参数对象 + * @return 短信渠道分页对象 + */ PageResult pageChannels(SmsChannelPageReqVO reqVO); + /** + * 创建新的渠道信息 + * + * @param reqVO 参数对象 + * @return 渠道id + */ Long createChannel(SmsChannelCreateReqVO reqVO); + /** + * 获取短信渠道枚举/渠道编码 + * + * @return 短信渠道枚举/渠道编码 + */ List getChannelEnums(); /** + * 根据短信模板编码获取短信客户端 + * + * @param templateCode 短信模板编码 + * @return 短信客户端 + */ + AbstractSmsClient getClient(String templateCode); + + /** * 查询渠道(包含名下模块)信息集合 * * @return 渠道(包含名下模块)信息集合 */ - List listChannelAllEnabledInfo(); - - boolean flushChannel(); + List listChannelAllEnabledInfo(); } diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SmsLogService.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SmsLogService.java index d29d7f8..2646dcb 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SmsLogService.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SmsLogService.java @@ -1,5 +1,11 @@ package cn.iocoder.dashboard.modules.system.service.sms; +import cn.iocoder.dashboard.framework.sms.client.AbstractSmsClient; +import cn.iocoder.dashboard.framework.sms.core.SmsBody; +import cn.iocoder.dashboard.framework.sms.core.SmsResult; + +import java.util.List; + /** * 短信渠道Service接口 * @@ -7,4 +13,23 @@ package cn.iocoder.dashboard.modules.system.service.sms; * @date 2021/1/25 9:24 */ public interface SmsLogService { + /** + * 发送短信前的日志处理 + * + * @param smsBody 短信内容 + * @param targetPhones 发送对象手机号集合 + * @param client 短信客户端 + * @param isAsync 是否异步发送 + * @return 生成的日志id + */ + Long beforeSendLog(SmsBody smsBody, List targetPhones, AbstractSmsClient client, Boolean isAsync); + + /** + * 发送消息后的日志处理 + * + * @param logId 日志id + * @param result 消息结果 + */ + void afterSendLog(Long logId, SmsResult result); + } diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SmsService.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SmsService.java new file mode 100644 index 0000000..56dc2df --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SmsService.java @@ -0,0 +1,101 @@ +package cn.iocoder.dashboard.modules.system.service.sms; + +import cn.iocoder.dashboard.framework.sms.core.SmsBody; +import cn.iocoder.dashboard.framework.sms.core.SmsResult; +import org.apache.commons.lang3.StringUtils; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** + * 短信Service接口 + * + * @author zzf + * @date 2021/1/25 9:24 + */ +public interface SmsService { + + /** + * 发送消息 + * + * @param smsBody 消息内容 + * @param targetPhones 发送对象手机号列表 + * @return 是否发送成功 + */ + SmsResult send(SmsBody smsBody, List targetPhones); + + /** + * 发送消息 + * + * @param smsBody 消息内容 + * @param targetPhone 发送对象手机号 + * @return 是否发送成功 + */ + default SmsResult send(SmsBody smsBody, String targetPhone) { + if (StringUtils.isBlank(targetPhone)) { + return failResult("targetPhone must not null."); + } + + return send(smsBody, Collections.singletonList(targetPhone)); + } + + /** + * 发送消息 + * + * @param smsBody 消息内容 + * @param targetPhones 发送对象手机号数组 + * @return 是否发送成功 + */ + default SmsResult send(SmsBody smsBody, String... targetPhones) { + if (targetPhones == null) { + return failResult("targetPhones must not null."); + } + + return send(smsBody, Arrays.asList(targetPhones)); + } + + + /** + * 异步发送消息 + * + * @param msgBody 消息内容 + * @param targetPhones 发送对象列表 + */ + void sendAsync(SmsBody msgBody, List targetPhones); + + /** + * 异步发送消息 + * + * @param msgBody 消息内容 + * @param targetPhone 发送对象 + */ + default void sendAsync(SmsBody msgBody, String targetPhone) { + if (StringUtils.isBlank(targetPhone)) { + return; + } + sendAsync(msgBody, Collections.singletonList(targetPhone)); + } + + /** + * 异步发送消息 + * + * @param msgBody 消息内容 + * @param targetPhones 发送对象列表 + */ + default void sendAsync(SmsBody msgBody, String... targetPhones) { + if (targetPhones == null) { + return; + } + sendAsync(msgBody, Arrays.asList(targetPhones)); + } + + + default SmsResult failResult(String message) { + SmsResult resultBody = new SmsResult<>(); + resultBody.setSuccess(false); + resultBody.setMessage(message); + return resultBody; + } + +} diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SmsChannelServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SmsChannelServiceImpl.java index ccc47af..044a4e5 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SmsChannelServiceImpl.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SmsChannelServiceImpl.java @@ -3,7 +3,9 @@ package cn.iocoder.dashboard.modules.system.service.sms.impl; import cn.hutool.core.util.ObjectUtil; import cn.iocoder.dashboard.common.enums.SmsChannelEnum; import cn.iocoder.dashboard.common.pojo.PageResult; -import cn.iocoder.dashboard.modules.system.controller.sms.vo.SmsChannelAllVO; +import cn.iocoder.dashboard.framework.sms.client.AbstractSmsClient; +import cn.iocoder.dashboard.framework.sms.core.SmsClientFactory; +import cn.iocoder.dashboard.modules.system.controller.sms.vo.SmsChannelPropertyVO; import cn.iocoder.dashboard.modules.system.controller.sms.vo.req.SmsChannelCreateReqVO; import cn.iocoder.dashboard.modules.system.controller.sms.vo.req.SmsChannelPageReqVO; import cn.iocoder.dashboard.modules.system.controller.sms.vo.resp.SmsChannelEnumRespVO; @@ -14,12 +16,16 @@ import cn.iocoder.dashboard.modules.system.dal.mysql.dao.sms.SmsTemplateMapper; import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.sms.SmsChannelDO; import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.sms.SmsTemplateDO; import cn.iocoder.dashboard.modules.system.service.sms.SmsChannelService; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import javax.annotation.PostConstruct; import javax.annotation.Resource; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; /** * 短信渠道Service实现类 @@ -30,6 +36,30 @@ import java.util.List; @Service public class SmsChannelServiceImpl implements SmsChannelService { + private final Map templateCode2ChannelIdMap = new ConcurrentHashMap<>(32); + + @Autowired + private SmsClientFactory smsClientFactory; + + /** + * 初始化短信客户端 + */ + @PostConstruct + @Override + public void initSmsClient() { + List smsChannelPropertyVOList = listChannelAllEnabledInfo(); + if (ObjectUtil.isEmpty(smsChannelPropertyVOList)) { + return; + } + smsChannelPropertyVOList.forEach(smsChannelPropertyVO -> { + Long clientId = smsClientFactory.createClient(smsChannelPropertyVO); + smsChannelPropertyVO.getTemplateList().forEach(smsTemplateVO -> { + templateCode2ChannelIdMap.put(smsTemplateVO.getCode(), clientId); + }); + }); + } + + @Resource private SmsChannelMapper mapper; @@ -54,12 +84,17 @@ public class SmsChannelServiceImpl implements SmsChannelService { } @Override - public List listChannelAllEnabledInfo() { + public AbstractSmsClient getClient(String templateCode) { + return smsClientFactory.getClient(templateCode2ChannelIdMap.get(templateCode)); + } + + @Override + public List listChannelAllEnabledInfo() { List channelDOList = mapper.selectEnabledList(); if (ObjectUtil.isNull(channelDOList)) { return null; } - List channelAllVOList = SmsChannelConvert.INSTANCE.convert(channelDOList); + List channelAllVOList = SmsChannelConvert.INSTANCE.convert(channelDOList); channelAllVOList.forEach(smsChannelDO -> { @@ -71,10 +106,4 @@ public class SmsChannelServiceImpl implements SmsChannelService { }); return channelAllVOList; } - - @Override - public boolean flushChannel() { - - return true; - } } diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SmsLogServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SmsLogServiceImpl.java index e54d265..6519172 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SmsLogServiceImpl.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SmsLogServiceImpl.java @@ -1,8 +1,21 @@ package cn.iocoder.dashboard.modules.system.service.sms.impl; +import cn.iocoder.dashboard.framework.sms.client.AbstractSmsClient; +import cn.iocoder.dashboard.framework.sms.core.SmsBody; +import cn.iocoder.dashboard.framework.sms.core.SmsResult; +import cn.iocoder.dashboard.modules.system.controller.sms.vo.SmsChannelPropertyVO; +import cn.iocoder.dashboard.modules.system.controller.sms.vo.SmsTemplateVO; +import cn.iocoder.dashboard.modules.system.dal.mysql.dao.sms.SmsLogMapper; +import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.sms.SmsLogDO; +import cn.iocoder.dashboard.modules.system.enums.sms.SmsSendStatusEnum; import cn.iocoder.dashboard.modules.system.service.sms.SmsLogService; +import cn.iocoder.dashboard.util.json.JsonUtils; +import cn.iocoder.dashboard.util.string.StrUtils; import org.springframework.stereotype.Service; +import javax.annotation.Resource; +import java.util.List; + /** * 短信日志Service实现类 * @@ -12,4 +25,48 @@ import org.springframework.stereotype.Service; @Service public class SmsLogServiceImpl implements SmsLogService { + @Resource + private SmsLogMapper smsLogMapper; + + @Override + public Long beforeSendLog(SmsBody smsBody, List targetPhones, AbstractSmsClient client, Boolean isAsync) { + SmsLogDO smsLog = new SmsLogDO(); + if (smsBody.getSmsLogId() != null) { + smsLog.setId(smsBody.getSmsLogId()); + smsLog.setSendStatus(SmsSendStatusEnum.SENDING.getStatus()); + smsLogMapper.updateById(smsLog); + return smsBody.getSmsLogId(); + } else { + SmsChannelPropertyVO property = client.getProperty(); + SmsTemplateVO smsTemplate = property.getTemplateByTemplateCode(smsBody.getTemplateCode()); + + smsLog.setChannelCode(property.getCode()) + .setChannelId(property.getId()) + .setTemplateCode(smsTemplate.getCode()) + .setPhones(JsonUtils.toJsonString(targetPhones)) + .setContent(StrUtils.replace(smsTemplate.getContent(), smsBody.getParams())); + + if (isAsync) { + smsLog.setSendStatus(SmsSendStatusEnum.ASYNC.getStatus()); + } else { + smsLog.setSendStatus(SmsSendStatusEnum.SENDING.getStatus()); + } + smsLogMapper.insert(smsLog); + return smsLog.getId(); + } + } + + @Override + public void afterSendLog(Long logId, SmsResult result) { + SmsLogDO smsLog = new SmsLogDO(); + smsLog.setId(logId); + if (result.getSuccess()) { + smsLog.setSendStatus(SmsSendStatusEnum.SUCCESS.getStatus()); + } else { + smsLog.setSendStatus(SmsSendStatusEnum.FAIL.getStatus()); + smsLog.setRemark(result.getMessage() + JsonUtils.toJsonString(result.getResult())); + } + smsLogMapper.updateById(smsLog); + } + } diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SmsServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SmsServiceImpl.java new file mode 100644 index 0000000..4dc0902 --- /dev/null +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SmsServiceImpl.java @@ -0,0 +1,51 @@ +package cn.iocoder.dashboard.modules.system.service.sms.impl; + +import cn.iocoder.dashboard.framework.sms.client.AbstractSmsClient; +import cn.iocoder.dashboard.framework.sms.core.SmsBody; +import cn.iocoder.dashboard.framework.sms.core.SmsResult; +import cn.iocoder.dashboard.modules.system.mq.producer.sms.SmsProducer; +import cn.iocoder.dashboard.modules.system.service.sms.SmsChannelService; +import cn.iocoder.dashboard.modules.system.service.sms.SmsLogService; +import cn.iocoder.dashboard.modules.system.service.sms.SmsService; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 短信日志Service实现类 + * + * @author zzf + * @date 2021/1/25 9:25 + */ +@Service +public class SmsServiceImpl implements SmsService { + + @Resource + private SmsChannelService channelService; + + @Resource + private SmsLogService smsLogService; + + @Resource + private SmsProducer smsProducer; + + @Override + public SmsResult send(SmsBody smsBody, List targetPhones) { + AbstractSmsClient client = channelService.getClient(smsBody.getTemplateCode()); + Long logId = smsLogService.beforeSendLog(smsBody, targetPhones, client, false); + + SmsResult result = client.send(smsBody, targetPhones); + + smsLogService.afterSendLog(logId, result); + + return result; + } + + @Override + public void sendAsync(SmsBody smsBody, List targetPhones) { + AbstractSmsClient client = channelService.getClient(smsBody.getTemplateCode()); + smsLogService.beforeSendLog(smsBody, targetPhones, client, true); + smsProducer.sendSmsSendMessage(smsBody, targetPhones); + } +} diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/sms/SmsConfiguration.java b/src/main/java/cn/iocoder/dashboard/modules/system/sms/SmsConfiguration.java deleted file mode 100644 index ffb5887..0000000 --- a/src/main/java/cn/iocoder/dashboard/modules/system/sms/SmsConfiguration.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.iocoder.dashboard.modules.system.sms; - -import cn.iocoder.dashboard.framework.sms.SmsClient; -import cn.iocoder.dashboard.framework.sms.SmsClientAdapter; -import cn.iocoder.dashboard.modules.system.controller.sms.vo.SmsChannelAllVO; -import cn.iocoder.dashboard.modules.system.service.sms.SmsChannelService; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import javax.annotation.Resource; -import java.util.List; -import java.util.Map; - -/** - * 短信服务配置 - * - * @author guer - */ -@Configuration -@ConditionalOnProperty("sms.enabled") -public class SmsConfiguration { - - @Resource - private SmsChannelService channelService; - - @Bean - public SmsClientAdapter smsClientWrapper() { - List smsChannelAllVOList = channelService.listChannelAllEnabledInfo(); - Map> channelId2SmsClientMap = SmsSenderUtils.init(smsChannelAllVOList); - return new SmsClientAdapter(channelId2SmsClientMap); - } - -} diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/sms/SmsSenderUtils.java b/src/main/java/cn/iocoder/dashboard/modules/system/sms/SmsSenderUtils.java deleted file mode 100644 index ea9c244..0000000 --- a/src/main/java/cn/iocoder/dashboard/modules/system/sms/SmsSenderUtils.java +++ /dev/null @@ -1,143 +0,0 @@ -package cn.iocoder.dashboard.modules.system.sms; - -import cn.hutool.core.util.ObjectUtil; -import cn.iocoder.dashboard.common.enums.SmsChannelEnum; -import cn.iocoder.dashboard.common.exception.ServiceException; -import cn.iocoder.dashboard.framework.sms.SmsBody; -import cn.iocoder.dashboard.framework.sms.SmsClient; -import cn.iocoder.dashboard.framework.sms.SmsClientAdapter; -import cn.iocoder.dashboard.framework.sms.SmsResult; -import cn.iocoder.dashboard.modules.system.controller.sms.vo.SmsChannelAllVO; -import cn.iocoder.dashboard.modules.system.controller.sms.vo.SmsTemplateVO; -import cn.iocoder.dashboard.modules.system.sms.client.AliSmsClient; -import cn.iocoder.dashboard.modules.system.sms.proxy.SmsClientLogProxy; - -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; - -import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.*; - -/** - * 短信发送者工厂 - * - * @author zzf - * @date 2021/1/25 16:18 - */ -public class SmsSenderUtils { - - /** - * 短信渠道id:短信客户端map - * key: channelId - * val: SmsClient - */ - private static final Map> smsSenderMap = new ConcurrentHashMap<>(8); - - /** - * 短信模板code: 短信渠道id map - * key: templateCode - * val: channelId - */ - private static final Map templateCode2ChannelIdMap = new HashMap<>(); - - /** - * 将短信渠道信息初始化成短信客户端 - * - * @param smsChannelAllVOList 短信渠道信息 - * @return 短信渠道id:短信客户端map - */ - public synchronized static Map> init(List smsChannelAllVOList) { - if (ObjectUtil.isEmpty(smsChannelAllVOList)) { - throw new ServiceException(SMS_CHANNEL_NOT_FOUND); - } - addSender(smsChannelAllVOList); - return smsSenderMap; - } - - /** - * 重置短信客户端信息 - * - * @param smsClientAdapter 短信客户端适配器 - * @param smsChannelAllVOList 短信渠道信息集合 - */ - public synchronized static void flush(SmsClientAdapter smsClientAdapter, List smsChannelAllVOList) { - smsSenderMap.clear(); - smsClientAdapter.flushClient(init(smsChannelAllVOList)); - } - - /** - * 发送短信 - * - * @param smsClientAdapter 短信客户端适配器 - * @param smsBody 短信内容 - * @param targetPhones 对象手机集合 - * @return 短信发送结果 - */ - public static SmsResult send(SmsClientAdapter smsClientAdapter, SmsBody smsBody, Collection targetPhones) { - Long channelId = templateCode2ChannelIdMap.get(smsBody.getCode()); - if (channelId == null) { - throw new ServiceException(SMS_SENDER_NOT_FOUND); - } - return smsClientAdapter.send(channelId, smsBody, targetPhones); - } - - /** - * 发送短信 - * - * @param smsClientAdapter 短信客户端适配器 - * @param smsBody 短信内容 - * @param targetPhone 对象手机 - * @return 短信发送结果 - */ - public static SmsResult send(SmsClientAdapter smsClientAdapter, SmsBody smsBody, String targetPhone) { - Long channelId = templateCode2ChannelIdMap.get(smsBody.getCode()); - if (channelId == null) { - throw new ServiceException(SMS_SENDER_NOT_FOUND); - } - return smsClientAdapter.send(channelId, smsBody, Collections.singletonList(targetPhone)); - } - - /** - * 发送短信 - * - * @param smsClientAdapter 短信客户端适配器 - * @param smsBody 短信内容 - * @param targetPhones 对象手机数组 - * @return 短信发送结果 - */ - public static SmsResult send(SmsClientAdapter smsClientAdapter, SmsBody smsBody, String... targetPhones) { - Long channelId = templateCode2ChannelIdMap.get(smsBody.getCode()); - if (channelId == null) { - throw new ServiceException(SMS_SENDER_NOT_FOUND); - } - return smsClientAdapter.send(channelId, smsBody, Arrays.asList(targetPhones)); - } - - - private static void addSender(List smsChannelAllVOList) { - smsChannelAllVOList.forEach(channelAllVO -> addSender(SmsChannelEnum.getByCode(channelAllVO.getCode()), channelAllVO)); - } - - private static void addSender(SmsChannelEnum channelEnum, SmsChannelAllVO channelAllVO) { - if (channelEnum == null) { - throw new ServiceException(INVALID_CHANNEL_CODE); - } - List templateList = channelAllVO.getTemplateList(); - if (ObjectUtil.isEmpty(templateList)) { - throw new ServiceException(SMS_TEMPLATE_NOT_FOUND); - } - SmsClient aliSmsClient = getSender(channelEnum, channelAllVO); - templateList.forEach(smsTemplateVO -> templateCode2ChannelIdMap.put(smsTemplateVO.getCode(), channelAllVO.getId())); - smsSenderMap.put(channelAllVO.getId(), aliSmsClient); - } - - private static SmsClient getSender(SmsChannelEnum channelEnum, SmsChannelAllVO channelAllVO) { - switch (channelEnum) { - case ALI: - return new SmsClientLogProxy<>(new AliSmsClient(channelAllVO)); - // TODO fill more channel - default: - break; - } - throw new ServiceException(SMS_SENDER_NOT_FOUND); - } -} diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/sms/client/AliSmsClient.java b/src/main/java/cn/iocoder/dashboard/modules/system/sms/client/AliSmsClient.java deleted file mode 100644 index f144ec3..0000000 --- a/src/main/java/cn/iocoder/dashboard/modules/system/sms/client/AliSmsClient.java +++ /dev/null @@ -1,91 +0,0 @@ -package cn.iocoder.dashboard.modules.system.sms.client; - -import cn.iocoder.dashboard.framework.sms.SmsBody; -import cn.iocoder.dashboard.framework.sms.SmsClient; -import cn.iocoder.dashboard.framework.sms.SmsResult; -import cn.iocoder.dashboard.modules.system.controller.sms.vo.SmsChannelAllVO; -import 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 AliSmsClient implements SmsClient { - - 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 AliSmsClient(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 send(SmsBody msgBody, Collection targets) { - SendSmsRequest request = new SendSmsRequest(); - request.setSysMethod(MethodType.POST); - request.setPhoneNumbers(StringUtils.join(targets, ",")); - request.setSignName(channelVO.getApiSignatureId()); - request.setTemplateCode(channelVO.getTemplateByTemplateCode(msgBody.getCode()).getApiTemplateId()); - request.setTemplateParam(msgBody.getParamsStr()); - - 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 resultBody = new SmsResult<>(); - resultBody.setSuccess(result); - resultBody.setResult(sendSmsResponse); - return resultBody; - } catch (Exception e) { - log.debug(e.getMessage(), e); - } - - return failResult(); - } - - @Override - public SmsResult sendAsync(SmsBody msgBody, Collection targets) { - return null; - } - -} diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/sms/proxy/SmsClientLogProxy.java b/src/main/java/cn/iocoder/dashboard/modules/system/sms/proxy/SmsClientLogProxy.java deleted file mode 100644 index a7d201e..0000000 --- a/src/main/java/cn/iocoder/dashboard/modules/system/sms/proxy/SmsClientLogProxy.java +++ /dev/null @@ -1,48 +0,0 @@ -package cn.iocoder.dashboard.modules.system.sms.proxy; - -import cn.iocoder.dashboard.framework.sms.SmsBody; -import cn.iocoder.dashboard.framework.sms.SmsClient; -import cn.iocoder.dashboard.framework.sms.SmsResult; -import cn.iocoder.dashboard.util.json.JsonUtils; -import lombok.extern.slf4j.Slf4j; - -import java.util.Collection; - -/** - * 消息父接口 - * - * @author zzf - * @date 2021/1/22 15:46 - */ -@Slf4j -public class SmsClientLogProxy implements SmsClient { - - private final SmsClient smsClient; - - @Override - public SmsResult send(SmsBody msgBody, Collection targets) { - log.debug("ready send sms, body: {}, target: {}", JsonUtils.toJsonString(msgBody), targets); - - SmsResult resultBody = smsClient.send(msgBody, targets); - - if (resultBody.getSuccess()) { - // - } else { - log.warn("send sms fail, body: {}, target: {}, resultBody: {}", - JsonUtils.toJsonString(msgBody), - targets, - JsonUtils.toJsonString(resultBody) - ); - } - return resultBody; - } - - @Override - public SmsResult sendAsync(SmsBody msgBody, Collection targets) { - return send(msgBody, targets); - } - - public SmsClientLogProxy(SmsClient smsClient) { - this.smsClient = smsClient; - } -} diff --git a/src/main/java/cn/iocoder/dashboard/util/string/StrUtils.java b/src/main/java/cn/iocoder/dashboard/util/string/StrUtils.java index 5e98d91..e0ca605 100644 --- a/src/main/java/cn/iocoder/dashboard/util/string/StrUtils.java +++ b/src/main/java/cn/iocoder/dashboard/util/string/StrUtils.java @@ -1,7 +1,10 @@ package cn.iocoder.dashboard.util.string; +import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; +import java.util.Map; + /** * 字符串工具类 * @@ -13,4 +16,22 @@ public class StrUtils { return StrUtil.maxLength(str, maxLength - 3); // -3 的原因,是该方法会补充 ... 恰好 } + /** + * 指定字符串的 + * @param str + * @param replaceMap + * @return + */ + public static String replace(String str, Map replaceMap) { + assert StrUtil.isNotBlank(str); + if (ObjectUtil.isEmpty(replaceMap)) { + return str; + } + String result = null; + for (String key : replaceMap.keySet()) { + result = str.replace(key, replaceMap.get(key)); + } + return result; + } + } -- libgit2 0.21.4