Commit 46ed64ba4048e5e6bf24b791b6af5addf10b996a

Authored by YunaiV
1 parent f3b6783c

短信提交 2021-03-28,增加发送日志

src/main/java/cn/iocoder/dashboard/framework/sms/core/SmsClientFactory.java
... ... @@ -55,7 +55,7 @@ public class SmsClientFactory {
55 55 throw new ServiceException(INVALID_CHANNEL_CODE);
56 56 }
57 57 switch (channelEnum) {
58   - case ALI:
  58 + case ALIYUN:
59 59 return new AliyunSmsClient(channelVO);
60 60 case YUN_PIAN:
61 61 return new YunpianSmsClient(channelVO);
... ...
src/main/java/cn/iocoder/dashboard/framework/sms/core/enums/SmsChannelEnum.java
1 1 package cn.iocoder.dashboard.framework.sms.core.enums;
2 2  
  3 +import cn.hutool.core.util.ArrayUtil;
3 4 import lombok.AllArgsConstructor;
4 5 import lombok.Getter;
5 6  
... ... @@ -13,22 +14,22 @@ import lombok.Getter;
13 14 @AllArgsConstructor
14 15 public enum SmsChannelEnum {
15 16  
16   - ALI("ALI", "阿里"),
17 17 YUN_PIAN("YUN_PIAN", "云片"),
18   - HUA_WEI("HUA_WEI", "华为"),
19   - TENCENT("TENCENT", "腾讯");
  18 + ALIYUN("ALIYUN", "阿里云"),
  19 + TENCENT("TENCENT", "腾讯云"),
  20 + HUA_WEI("HUA_WEI", "华为云"),;
20 21  
  22 + /**
  23 + * 编码
  24 + */
21 25 private final String code;
22   -
  26 + /**
  27 + * 名字
  28 + */
23 29 private final String name;
24 30  
25 31 public static SmsChannelEnum getByCode(String code) {
26   - for (SmsChannelEnum value : SmsChannelEnum.values()) {
27   - if (value.getCode().equals(code)) {
28   - return value;
29   - }
30   - }
31   - return null;
  32 + return ArrayUtil.firstMatch(o -> o.getCode().equals(code), values());
32 33 }
33 34  
34 35 }
... ...
src/main/java/cn/iocoder/dashboard/modules/system/enums/sms/SysSmsSendFailureTypeEnum.java renamed to src/main/java/cn/iocoder/dashboard/framework/sms/core/enums/SmsSendFailureTypeEnum.java
1   -package cn.iocoder.dashboard.modules.system.enums.sms;
  1 +package cn.iocoder.dashboard.framework.sms.core.enums;
2 2  
3 3 import lombok.AllArgsConstructor;
4 4 import lombok.Getter;
... ... @@ -10,10 +10,17 @@ import lombok.Getter;
10 10 */
11 11 @Getter
12 12 @AllArgsConstructor
13   -public enum SysSmsSendFailureTypeEnum {
  13 +public enum SmsSendFailureTypeEnum {
14 14  
  15 + // ========== 模板相关(100 开头) ==========
  16 + SMS_TEMPLATE_DISABLE(100), // 短信模板被禁用
  17 +
  18 + // ========== 其它相关 ==========
15 19 ;
16 20  
  21 + /**
  22 + * 失败类型
  23 + */
17 24 private final int type;
18 25  
19 26 }
... ...
src/main/java/cn/iocoder/dashboard/modules/system/dal/dataobject/sms/SysSmsSendLogDO.java
... ... @@ -2,7 +2,7 @@ package cn.iocoder.dashboard.modules.system.dal.dataobject.sms;
2 2  
3 3 import cn.iocoder.dashboard.common.enums.UserTypeEnum;
4 4 import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO;
5   -import cn.iocoder.dashboard.modules.system.enums.sms.SysSmsSendFailureTypeEnum;
  5 +import cn.iocoder.dashboard.framework.sms.core.enums.SmsSendFailureTypeEnum;
6 6 import cn.iocoder.dashboard.modules.system.enums.sms.SysSmsSendStatusEnum;
7 7 import com.baomidou.mybatisplus.annotation.TableName;
8 8 import lombok.*;
... ... @@ -108,7 +108,7 @@ public class SysSmsSendLogDO extends BaseDO {
108 108 /**
109 109 * 发送失败的类型
110 110 *
111   - * 枚举 {@link SysSmsSendFailureTypeEnum}
  111 + * 枚举 {@link SmsSendFailureTypeEnum}
112 112 */
113 113 private Integer sendFailureType;
114 114 /**
... ...
src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/sms/SmsSendStreamConsumer.java renamed to src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/sms/SmsSendConsumer.java
1 1 package cn.iocoder.dashboard.modules.system.mq.consumer.sms;
2 2  
  3 +import cn.iocoder.dashboard.framework.redis.core.stream.AbstractStreamMessageListener;
3 4 import cn.iocoder.dashboard.framework.sms.client.AbstractSmsClient;
4 5 import cn.iocoder.dashboard.framework.sms.core.SmsBody;
5 6 import cn.iocoder.dashboard.framework.sms.core.SmsResult;
  7 +import cn.iocoder.dashboard.modules.system.mq.message.sms.SysSmsSendMessage;
6 8 import cn.iocoder.dashboard.modules.system.service.sms.SysSmsChannelService;
7 9 import cn.iocoder.dashboard.modules.system.service.sms.SysSmsQueryLogService;
  10 +import cn.iocoder.dashboard.modules.system.service.sms.SysSmsService;
8 11 import cn.iocoder.dashboard.util.json.JsonUtils;
9 12 import lombok.extern.slf4j.Slf4j;
10 13 import org.springframework.data.redis.connection.stream.ObjectRecord;
... ... @@ -14,14 +17,14 @@ import org.springframework.stereotype.Component;
14 17 import javax.annotation.Resource;
15 18  
16 19 /**
17   - * 短信发送流消息监听器
  20 + * 针对 {@link SysSmsSendMessage} 的消费者
18 21 *
19 22 * @author zzf
20 23 * @date 2021/3/9 16:35
21 24 */
22   -@Slf4j
23 25 @Component
24   -public class SmsSendStreamConsumer implements StreamListener<String, ObjectRecord<String, SmsSendMessage>> {
  26 +@Slf4j
  27 +public class SmsSendConsumer extends AbstractStreamMessageListener<SysSmsSendMessage> {
25 28  
26 29 @Resource
27 30 private SysSmsChannelService smsChannelService;
... ... @@ -29,15 +32,22 @@ public class SmsSendStreamConsumer implements StreamListener&lt;String, ObjectRecor
29 32 @Resource
30 33 private SysSmsQueryLogService smsQueryLogService;
31 34  
  35 + @Resource
  36 + private SysSmsService smsService;
  37 +
32 38 @Override
33 39 public void onMessage(ObjectRecord<String, SmsSendMessage> record) {
34   - SmsSendMessage message = record.getValue();
35   - SmsBody body = message.getSmsBody();
36   - log.info("[onMessage][收到 发送短信 消息], content: " + JsonUtils.toJsonString(body));
37 40 AbstractSmsClient smsClient = smsChannelService.getSmsClient(body.getTemplateCode());
38 41 String templateApiId = smsChannelService.getSmsTemplateApiIdByCode(body.getTemplateCode());
39 42  
40 43 SmsResult result = smsClient.send(templateApiId, body, message.getTargetPhone());
41 44 smsQueryLogService.afterSendLog(body.getSmsLogId(), result);
42 45 }
  46 +
  47 + @Override
  48 + public void onMessage(SysSmsSendMessage message) {
  49 + log.info("[onMessage][消息内容({})]", message);
  50 + smsService.doSendSms(message);
  51 + }
  52 +
43 53 }
... ...
src/main/java/cn/iocoder/dashboard/modules/system/mq/consumer/sms/SysSmsSendConsumer.java deleted
1   -package cn.iocoder.dashboard.modules.system.mq.consumer.sms;
2   -
3   -import cn.iocoder.dashboard.framework.redis.core.stream.AbstractStreamMessageListener;
4   -import cn.iocoder.dashboard.modules.system.mq.message.sms.SysSmsSendMessage;
5   -import lombok.extern.slf4j.Slf4j;
6   -import org.springframework.stereotype.Component;
7   -
8   -@Component
9   -@Slf4j
10   -public class SysSmsSendConsumer extends AbstractStreamMessageListener<SysSmsSendMessage> {
11   -
12   - @Override
13   - public void onMessage(SysSmsSendMessage message) {
14   - log.info("[onMessage][消息内容({})]", message);
15   - }
16   -
17   -}
src/main/java/cn/iocoder/dashboard/modules/system/mq/message/sms/SysSmsSendMessage.java
... ... @@ -15,28 +15,29 @@ import java.util.Map;
15 15 public class SysSmsSendMessage implements StreamMessage {
16 16  
17 17 /**
  18 + * 发送日志编号
  19 + */
  20 + @NotNull(message = "发送日志编号不能为空")
  21 + private Long sendLogId;
  22 + /**
18 23 * 手机号
19 24 */
20 25 @NotNull(message = "手机号不能为空")
21 26 private String mobile;
22 27 /**
23   - * 短信模板编号
  28 + * 短信渠道编号
24 29 */
25   - @NotNull(message = "短信模板编号不能为空")
26   - private String templateCode;
  30 + @NotNull(message = "短信渠道编号不能为空")
  31 + private Long channelId;
27 32 /**
28   - * 短信模板参数
  33 + * 短信 API 的模板编号
29 34 */
30   - private Map<String, Object> templateParams;
31   -
  35 + @NotNull(message = "短信 API 的模板编号不能为空")
  36 + private String apiTemplateId;
32 37 /**
33   - * 用户编号,允许空
34   - */
35   - private Integer userId;
36   - /**
37   - * 用户类型,允许空
  38 + * 短信模板参数
38 39 */
39   - private Integer userType;
  40 + private Map<String, Object> templateParams;
40 41  
41 42 @Override
42 43 public String getStreamKey() {
... ...
src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/sms/SmsSendStreamProducer.java renamed to src/main/java/cn/iocoder/dashboard/modules/system/mq/producer/sms/SysSmsProducer.java
... ... @@ -17,7 +17,7 @@ import java.util.Map;
17 17 */
18 18 @Slf4j
19 19 @Component
20   -public class SmsSendStreamProducer {
  20 +public class SysSmsProducer {
21 21  
22 22 @Resource
23 23 private StringRedisTemplate stringRedisTemplate;
... ... @@ -25,17 +25,17 @@ public class SmsSendStreamProducer {
25 25 /**
26 26 * 发送短信 Message
27 27 *
  28 + * @param sendLogId 发送日志编号
28 29 * @param mobile 手机号
29   - * @param templateCode 短信模板编号
  30 + * @param channelId 渠道编号
  31 + * @param apiTemplateId 短信模板编号
30 32 * @param templateParams 短信模板参数
31   - * @param userId 用户编号
32   - * @param userType 用户类型
  33 + * @param sendLogId 发送日志编号
33 34 */
34   - public void sendSmsSendMessage(String mobile, String templateCode, Map<String, Object> templateParams,
35   - Integer userId, Integer userType) {
36   - SysSmsSendMessage message = new SysSmsSendMessage();
37   - message.setMobile(mobile).setTemplateCode(templateCode).setTemplateParams(templateParams);
38   - message.setUserId(userId).setUserType(userType);
  35 + public void sendSmsSendMessage(Long sendLogId, String mobile,
  36 + Long channelId, String apiTemplateId, Map<String, Object> templateParams) {
  37 + SysSmsSendMessage message = new SysSmsSendMessage().setSendLogId(sendLogId).setMobile(mobile);
  38 + message.setChannelId(channelId).setApiTemplateId(apiTemplateId).setTemplateParams(templateParams);
39 39 RedisMessageUtils.sendStreamMessage(stringRedisTemplate, message);
40 40 }
41 41  
... ...
src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsSendLogService.java
... ... @@ -15,6 +15,14 @@ public interface SysSmsSendLogService {
15 15 Long createSmsSendLog(String mobile, Long userId, Integer userType,
16 16 SysSmsTemplateDO template, String templateContent, Map<String, Object> templateParams);
17 17  
  18 + /**
  19 + * 更新发送日志为失败
  20 + *
  21 + * @param id 发送日志编号
  22 + * @param sendFailureType 失败类型
  23 + */
  24 + void updateSmsSendLogFailure(Long id, Integer sendFailureType);
  25 +
18 26 void getAndSaveSmsSendLog();
19 27  
20 28 }
... ...
src/main/java/cn/iocoder/dashboard/modules/system/service/sms/SysSmsService.java
1 1 package cn.iocoder.dashboard.modules.system.service.sms;
2 2  
  3 +import cn.iocoder.dashboard.modules.system.mq.message.sms.SysSmsSendMessage;
  4 +
3 5 import javax.servlet.ServletRequest;
4 6 import java.util.List;
5 7 import java.util.Map;
... ... @@ -19,7 +21,7 @@ public interface SysSmsService {
19 21 void sendBatchSms(List<String> mobiles, List<Long> userIds, Integer userType,
20 22 String templateCode, Map<String, Object> templateParams);
21 23  
22   - void doSendSms();
  24 + void doSendSms(SysSmsSendMessage message);
23 25  
24 26 /**
25 27 * 处理短信发送回调函数
... ...
src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SysSmsSendLogServiceImpl.java
... ... @@ -42,7 +42,6 @@ public class SysSmsSendLogServiceImpl implements SysSmsSendLogService {
42 42 */
43 43 private static final long SCHEDULER_PERIOD = 5 * 60 * 1000L;
44 44  
45   -
46 45 @Override
47 46 public Long createSmsSendLog(String mobile, Long userId, Integer userType,
48 47 SysSmsTemplateDO template, String templateContent, Map<String, Object> templateParams) {
... ... @@ -62,6 +61,11 @@ public class SysSmsSendLogServiceImpl implements SysSmsSendLogService {
62 61 }
63 62  
64 63 @Override
  64 + public void updateSmsSendLogFailure(Long id, Integer sendFailureType) {
  65 + smsSendLogMapper.updateById(new SysSmsSendLogDO().setId(id).setSendFailureType(sendFailureType));
  66 + }
  67 +
  68 + @Override
65 69 public void getAndSaveSmsSendLog() {
66 70  
67 71 List<SysSmsSendLogDO> noResultQueryLogList = smsQueryLogMapper.selectNoResultQueryLogList();
... ...
src/main/java/cn/iocoder/dashboard/modules/system/service/sms/impl/SysSmsServiceImpl.java
1 1 package cn.iocoder.dashboard.modules.system.service.sms.impl;
2 2  
3 3 import cn.hutool.core.collection.CollUtil;
4   -import cn.hutool.core.map.MapUtil;
5 4 import cn.hutool.core.util.StrUtil;
  5 +import cn.iocoder.dashboard.common.enums.CommonStatusEnum;
6 6 import cn.iocoder.dashboard.common.enums.UserTypeEnum;
7   -import cn.iocoder.dashboard.framework.sms.client.AbstractSmsClient;
8   -import cn.iocoder.dashboard.framework.sms.core.SmsBody;
9 7 import cn.iocoder.dashboard.framework.sms.core.SmsClientFactory;
10 8 import cn.iocoder.dashboard.framework.sms.core.SmsResultDetail;
  9 +import cn.iocoder.dashboard.framework.sms.core.enums.SmsSendFailureTypeEnum;
11 10 import cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsTemplateDO;
12 11 import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO;
13   -import cn.iocoder.dashboard.modules.system.mq.producer.sms.SmsSendStreamProducer;
  12 +import cn.iocoder.dashboard.modules.system.mq.message.sms.SysSmsSendMessage;
  13 +import cn.iocoder.dashboard.modules.system.mq.producer.sms.SysSmsProducer;
14 14 import cn.iocoder.dashboard.modules.system.service.sms.*;
15 15 import cn.iocoder.dashboard.modules.system.service.user.SysUserService;
16 16 import org.springframework.stereotype.Service;
... ... @@ -20,8 +20,6 @@ import javax.servlet.ServletRequest;
20 20 import java.util.List;
21 21 import java.util.Map;
22 22 import java.util.Objects;
23   -import java.util.function.Consumer;
24   -import java.util.function.Predicate;
25 23  
26 24 import static cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil.exception;
27 25 import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.*;
... ... @@ -51,7 +49,7 @@ public class SysSmsServiceImpl implements SysSmsService {
51 49 private SysSmsQueryLogService logService;
52 50  
53 51 @Resource
54   - private SmsSendStreamProducer smsProducer;
  52 + private SysSmsProducer smsProducer;
55 53  
56 54 @Resource
57 55 private SmsClientFactory smsClientFactory;
... ... @@ -68,8 +66,13 @@ public class SysSmsServiceImpl implements SysSmsService {
68 66 String content = smsTemplateService.formatSmsTemplateContent(template.getContent(), templateParams);
69 67 Long sendLogId = smsSendLogService.createSmsSendLog(mobile, userId, userType, template, content, templateParams);
70 68  
71   - // 发送 MQ 消息
72   -
  69 + // 如果模板被禁用,则直接标记发送失败。也就说,不发短信,嘿嘿。
  70 + if (CommonStatusEnum.DISABLE.getStatus().equals(template.getStatus())) {
  71 + smsSendLogService.updateSmsSendLogFailure(sendLogId, SmsSendFailureTypeEnum.SMS_TEMPLATE_DISABLE.getType());
  72 + return;
  73 + }
  74 + // 如果模板未禁用,发送 MQ 消息。目的是,异步化调用短信平台
  75 + smsProducer.sendSmsSendMessage(sendLogId, mobile, template.getChannelId(), template.getApiTemplateId(), templateParams);
73 76 }
74 77  
75 78 @Override
... ... @@ -79,11 +82,6 @@ public class SysSmsServiceImpl implements SysSmsService {
79 82 SysSmsTemplateDO template = this.checkSmsTemplateValid(templateCode, templateParams);
80 83 }
81 84  
82   - @Override
83   - public void doSendSms() {
84   -
85   - }
86   -
87 85 private SysSmsTemplateDO checkSmsTemplateValid(String templateCode, Map<String, Object> templateParams) {
88 86 // 短信模板不存在
89 87 SysSmsTemplateDO template = smsTemplateService.getSmsTemplateByCode(templateCode);
... ... @@ -132,10 +130,8 @@ public class SysSmsServiceImpl implements SysSmsService {
132 130 }
133 131  
134 132 @Override
135   - public void send(SmsBody smsBody, String targetPhone) {
136   - AbstractSmsClient client = channelService.getSmsClient(smsBody.getTemplateCode());
137   - logService.beforeSendLog(smsBody, targetPhone, client);
138   - smsProducer.sendSmsSendMessage(smsBody, targetPhone);
  133 + public void doSendSms(SysSmsSendMessage message) {
  134 +
139 135 }
140 136  
141 137 @Override
... ...