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

This commit is contained in:
YunaiV 2021-03-28 18:07:55 +08:00
parent f3b6783cc3
commit 46ed64ba40
13 changed files with 108 additions and 96 deletions

View File

@ -55,7 +55,7 @@ public class SmsClientFactory {
throw new ServiceException(INVALID_CHANNEL_CODE); throw new ServiceException(INVALID_CHANNEL_CODE);
} }
switch (channelEnum) { switch (channelEnum) {
case ALI: case ALIYUN:
return new AliyunSmsClient(channelVO); return new AliyunSmsClient(channelVO);
case YUN_PIAN: case YUN_PIAN:
return new YunpianSmsClient(channelVO); return new YunpianSmsClient(channelVO);

View File

@ -1,5 +1,6 @@
package cn.iocoder.dashboard.framework.sms.core.enums; package cn.iocoder.dashboard.framework.sms.core.enums;
import cn.hutool.core.util.ArrayUtil;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
@ -13,22 +14,22 @@ import lombok.Getter;
@AllArgsConstructor @AllArgsConstructor
public enum SmsChannelEnum { public enum SmsChannelEnum {
ALI("ALI", "阿里"),
YUN_PIAN("YUN_PIAN", "云片"), YUN_PIAN("YUN_PIAN", "云片"),
HUA_WEI("HUA_WEI", "华为"), ALIYUN("ALIYUN", "阿里云"),
TENCENT("TENCENT", "腾讯"); TENCENT("TENCENT", "腾讯云"),
HUA_WEI("HUA_WEI", "华为云"),;
/**
* 编码
*/
private final String code; private final String code;
/**
* 名字
*/
private final String name; private final String name;
public static SmsChannelEnum getByCode(String code) { public static SmsChannelEnum getByCode(String code) {
for (SmsChannelEnum value : SmsChannelEnum.values()) { return ArrayUtil.firstMatch(o -> o.getCode().equals(code), values());
if (value.getCode().equals(code)) {
return value;
}
}
return null;
} }
} }

View File

@ -0,0 +1,26 @@
package cn.iocoder.dashboard.framework.sms.core.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 短信的发送失败类型的枚举
*
* @author 芋道源码
*/
@Getter
@AllArgsConstructor
public enum SmsSendFailureTypeEnum {
// ========== 模板相关(100 开头) ==========
SMS_TEMPLATE_DISABLE(100), // 短信模板被禁用
// ========== 其它相关 ==========
;
/**
* 失败类型
*/
private final int type;
}

View File

@ -2,7 +2,7 @@ package cn.iocoder.dashboard.modules.system.dal.dataobject.sms;
import cn.iocoder.dashboard.common.enums.UserTypeEnum; import cn.iocoder.dashboard.common.enums.UserTypeEnum;
import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.dashboard.modules.system.enums.sms.SysSmsSendFailureTypeEnum; import cn.iocoder.dashboard.framework.sms.core.enums.SmsSendFailureTypeEnum;
import cn.iocoder.dashboard.modules.system.enums.sms.SysSmsSendStatusEnum; import cn.iocoder.dashboard.modules.system.enums.sms.SysSmsSendStatusEnum;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*; import lombok.*;
@ -108,7 +108,7 @@ public class SysSmsSendLogDO extends BaseDO {
/** /**
* 发送失败的类型 * 发送失败的类型
* *
* 枚举 {@link SysSmsSendFailureTypeEnum} * 枚举 {@link SmsSendFailureTypeEnum}
*/ */
private Integer sendFailureType; private Integer sendFailureType;
/** /**

View File

@ -1,19 +0,0 @@
package cn.iocoder.dashboard.modules.system.enums.sms;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 短信的发送失败类型的枚举
*
* @author 芋道源码
*/
@Getter
@AllArgsConstructor
public enum SysSmsSendFailureTypeEnum {
;
private final int type;
}

View File

@ -1,10 +1,13 @@
package cn.iocoder.dashboard.modules.system.mq.consumer.sms; package cn.iocoder.dashboard.modules.system.mq.consumer.sms;
import cn.iocoder.dashboard.framework.redis.core.stream.AbstractStreamMessageListener;
import cn.iocoder.dashboard.framework.sms.client.AbstractSmsClient; import cn.iocoder.dashboard.framework.sms.client.AbstractSmsClient;
import cn.iocoder.dashboard.framework.sms.core.SmsBody; import cn.iocoder.dashboard.framework.sms.core.SmsBody;
import cn.iocoder.dashboard.framework.sms.core.SmsResult; import cn.iocoder.dashboard.framework.sms.core.SmsResult;
import cn.iocoder.dashboard.modules.system.mq.message.sms.SysSmsSendMessage;
import cn.iocoder.dashboard.modules.system.service.sms.SysSmsChannelService; import cn.iocoder.dashboard.modules.system.service.sms.SysSmsChannelService;
import cn.iocoder.dashboard.modules.system.service.sms.SysSmsQueryLogService; import cn.iocoder.dashboard.modules.system.service.sms.SysSmsQueryLogService;
import cn.iocoder.dashboard.modules.system.service.sms.SysSmsService;
import cn.iocoder.dashboard.util.json.JsonUtils; import cn.iocoder.dashboard.util.json.JsonUtils;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.connection.stream.ObjectRecord; import org.springframework.data.redis.connection.stream.ObjectRecord;
@ -14,14 +17,14 @@ import org.springframework.stereotype.Component;
import javax.annotation.Resource; import javax.annotation.Resource;
/** /**
* 短信发送流消息监听器 * 针对 {@link SysSmsSendMessage} 的消费者
* *
* @author zzf * @author zzf
* @date 2021/3/9 16:35 * @date 2021/3/9 16:35
*/ */
@Slf4j
@Component @Component
public class SmsSendStreamConsumer implements StreamListener<String, ObjectRecord<String, SmsSendMessage>> { @Slf4j
public class SmsSendConsumer extends AbstractStreamMessageListener<SysSmsSendMessage> {
@Resource @Resource
private SysSmsChannelService smsChannelService; private SysSmsChannelService smsChannelService;
@ -29,15 +32,22 @@ public class SmsSendStreamConsumer implements StreamListener<String, ObjectRecor
@Resource @Resource
private SysSmsQueryLogService smsQueryLogService; private SysSmsQueryLogService smsQueryLogService;
@Resource
private SysSmsService smsService;
@Override @Override
public void onMessage(ObjectRecord<String, SmsSendMessage> record) { public void onMessage(ObjectRecord<String, SmsSendMessage> record) {
SmsSendMessage message = record.getValue();
SmsBody body = message.getSmsBody();
log.info("[onMessage][收到 发送短信 消息], content: " + JsonUtils.toJsonString(body));
AbstractSmsClient smsClient = smsChannelService.getSmsClient(body.getTemplateCode()); AbstractSmsClient smsClient = smsChannelService.getSmsClient(body.getTemplateCode());
String templateApiId = smsChannelService.getSmsTemplateApiIdByCode(body.getTemplateCode()); String templateApiId = smsChannelService.getSmsTemplateApiIdByCode(body.getTemplateCode());
SmsResult result = smsClient.send(templateApiId, body, message.getTargetPhone()); SmsResult result = smsClient.send(templateApiId, body, message.getTargetPhone());
smsQueryLogService.afterSendLog(body.getSmsLogId(), result); smsQueryLogService.afterSendLog(body.getSmsLogId(), result);
} }
@Override
public void onMessage(SysSmsSendMessage message) {
log.info("[onMessage][消息内容({})]", message);
smsService.doSendSms(message);
}
} }

View File

@ -1,17 +0,0 @@
package cn.iocoder.dashboard.modules.system.mq.consumer.sms;
import cn.iocoder.dashboard.framework.redis.core.stream.AbstractStreamMessageListener;
import cn.iocoder.dashboard.modules.system.mq.message.sms.SysSmsSendMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class SysSmsSendConsumer extends AbstractStreamMessageListener<SysSmsSendMessage> {
@Override
public void onMessage(SysSmsSendMessage message) {
log.info("[onMessage][消息内容({})]", message);
}
}

View File

@ -14,30 +14,31 @@ import java.util.Map;
@Data @Data
public class SysSmsSendMessage implements StreamMessage { public class SysSmsSendMessage implements StreamMessage {
/**
* 发送日志编号
*/
@NotNull(message = "发送日志编号不能为空")
private Long sendLogId;
/** /**
* 手机号 * 手机号
*/ */
@NotNull(message = "手机号不能为空") @NotNull(message = "手机号不能为空")
private String mobile; private String mobile;
/** /**
* 短信模板编号 * 短信渠道编号
*/ */
@NotNull(message = "短信模板编号不能为空") @NotNull(message = "短信渠道编号不能为空")
private String templateCode; private Long channelId;
/**
* 短信 API 的模板编号
*/
@NotNull(message = "短信 API 的模板编号不能为空")
private String apiTemplateId;
/** /**
* 短信模板参数 * 短信模板参数
*/ */
private Map<String, Object> templateParams; private Map<String, Object> templateParams;
/**
* 用户编号允许空
*/
private Integer userId;
/**
* 用户类型允许空
*/
private Integer userType;
@Override @Override
public String getStreamKey() { public String getStreamKey() {
return "system.sms.send"; return "system.sms.send";

View File

@ -17,7 +17,7 @@ import java.util.Map;
*/ */
@Slf4j @Slf4j
@Component @Component
public class SmsSendStreamProducer { public class SysSmsProducer {
@Resource @Resource
private StringRedisTemplate stringRedisTemplate; private StringRedisTemplate stringRedisTemplate;
@ -25,17 +25,17 @@ public class SmsSendStreamProducer {
/** /**
* 发送短信 Message * 发送短信 Message
* *
* @param sendLogId 发送日志编号
* @param mobile 手机号 * @param mobile 手机号
* @param templateCode 短信模板编号 * @param channelId 渠道编号
* @param apiTemplateId 短信模板编号
* @param templateParams 短信模板参数 * @param templateParams 短信模板参数
* @param userId 用户编号 * @param sendLogId 发送日志编号
* @param userType 用户类型
*/ */
public void sendSmsSendMessage(String mobile, String templateCode, Map<String, Object> templateParams, public void sendSmsSendMessage(Long sendLogId, String mobile,
Integer userId, Integer userType) { Long channelId, String apiTemplateId, Map<String, Object> templateParams) {
SysSmsSendMessage message = new SysSmsSendMessage(); SysSmsSendMessage message = new SysSmsSendMessage().setSendLogId(sendLogId).setMobile(mobile);
message.setMobile(mobile).setTemplateCode(templateCode).setTemplateParams(templateParams); message.setChannelId(channelId).setApiTemplateId(apiTemplateId).setTemplateParams(templateParams);
message.setUserId(userId).setUserType(userType);
RedisMessageUtils.sendStreamMessage(stringRedisTemplate, message); RedisMessageUtils.sendStreamMessage(stringRedisTemplate, message);
} }

View File

@ -15,6 +15,14 @@ public interface SysSmsSendLogService {
Long createSmsSendLog(String mobile, Long userId, Integer userType, Long createSmsSendLog(String mobile, Long userId, Integer userType,
SysSmsTemplateDO template, String templateContent, Map<String, Object> templateParams); SysSmsTemplateDO template, String templateContent, Map<String, Object> templateParams);
/**
* 更新发送日志为失败
*
* @param id 发送日志编号
* @param sendFailureType 失败类型
*/
void updateSmsSendLogFailure(Long id, Integer sendFailureType);
void getAndSaveSmsSendLog(); void getAndSaveSmsSendLog();
} }

View File

@ -1,5 +1,7 @@
package cn.iocoder.dashboard.modules.system.service.sms; package cn.iocoder.dashboard.modules.system.service.sms;
import cn.iocoder.dashboard.modules.system.mq.message.sms.SysSmsSendMessage;
import javax.servlet.ServletRequest; import javax.servlet.ServletRequest;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -19,7 +21,7 @@ public interface SysSmsService {
void sendBatchSms(List<String> mobiles, List<Long> userIds, Integer userType, void sendBatchSms(List<String> mobiles, List<Long> userIds, Integer userType,
String templateCode, Map<String, Object> templateParams); String templateCode, Map<String, Object> templateParams);
void doSendSms(); void doSendSms(SysSmsSendMessage message);
/** /**
* 处理短信发送回调函数 * 处理短信发送回调函数

View File

@ -42,7 +42,6 @@ public class SysSmsSendLogServiceImpl implements SysSmsSendLogService {
*/ */
private static final long SCHEDULER_PERIOD = 5 * 60 * 1000L; private static final long SCHEDULER_PERIOD = 5 * 60 * 1000L;
@Override @Override
public Long createSmsSendLog(String mobile, Long userId, Integer userType, public Long createSmsSendLog(String mobile, Long userId, Integer userType,
SysSmsTemplateDO template, String templateContent, Map<String, Object> templateParams) { SysSmsTemplateDO template, String templateContent, Map<String, Object> templateParams) {
@ -61,6 +60,11 @@ public class SysSmsSendLogServiceImpl implements SysSmsSendLogService {
return logDO.getId(); return logDO.getId();
} }
@Override
public void updateSmsSendLogFailure(Long id, Integer sendFailureType) {
smsSendLogMapper.updateById(new SysSmsSendLogDO().setId(id).setSendFailureType(sendFailureType));
}
@Override @Override
public void getAndSaveSmsSendLog() { public void getAndSaveSmsSendLog() {

View File

@ -1,16 +1,16 @@
package cn.iocoder.dashboard.modules.system.service.sms.impl; package cn.iocoder.dashboard.modules.system.service.sms.impl;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.iocoder.dashboard.common.enums.CommonStatusEnum;
import cn.iocoder.dashboard.common.enums.UserTypeEnum; import cn.iocoder.dashboard.common.enums.UserTypeEnum;
import cn.iocoder.dashboard.framework.sms.client.AbstractSmsClient;
import cn.iocoder.dashboard.framework.sms.core.SmsBody;
import cn.iocoder.dashboard.framework.sms.core.SmsClientFactory; import cn.iocoder.dashboard.framework.sms.core.SmsClientFactory;
import cn.iocoder.dashboard.framework.sms.core.SmsResultDetail; import cn.iocoder.dashboard.framework.sms.core.SmsResultDetail;
import cn.iocoder.dashboard.framework.sms.core.enums.SmsSendFailureTypeEnum;
import cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsTemplateDO; import cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsTemplateDO;
import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO; import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO;
import cn.iocoder.dashboard.modules.system.mq.producer.sms.SmsSendStreamProducer; import cn.iocoder.dashboard.modules.system.mq.message.sms.SysSmsSendMessage;
import cn.iocoder.dashboard.modules.system.mq.producer.sms.SysSmsProducer;
import cn.iocoder.dashboard.modules.system.service.sms.*; import cn.iocoder.dashboard.modules.system.service.sms.*;
import cn.iocoder.dashboard.modules.system.service.user.SysUserService; import cn.iocoder.dashboard.modules.system.service.user.SysUserService;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -20,8 +20,6 @@ import javax.servlet.ServletRequest;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Predicate;
import static cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.*; import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.*;
@ -51,7 +49,7 @@ public class SysSmsServiceImpl implements SysSmsService {
private SysSmsQueryLogService logService; private SysSmsQueryLogService logService;
@Resource @Resource
private SmsSendStreamProducer smsProducer; private SysSmsProducer smsProducer;
@Resource @Resource
private SmsClientFactory smsClientFactory; private SmsClientFactory smsClientFactory;
@ -68,8 +66,13 @@ public class SysSmsServiceImpl implements SysSmsService {
String content = smsTemplateService.formatSmsTemplateContent(template.getContent(), templateParams); String content = smsTemplateService.formatSmsTemplateContent(template.getContent(), templateParams);
Long sendLogId = smsSendLogService.createSmsSendLog(mobile, userId, userType, template, content, templateParams); Long sendLogId = smsSendLogService.createSmsSendLog(mobile, userId, userType, template, content, templateParams);
// 发送 MQ 消息 // 如果模板被禁用则直接标记发送失败也就说不发短信嘿嘿
if (CommonStatusEnum.DISABLE.getStatus().equals(template.getStatus())) {
smsSendLogService.updateSmsSendLogFailure(sendLogId, SmsSendFailureTypeEnum.SMS_TEMPLATE_DISABLE.getType());
return;
}
// 如果模板未禁用发送 MQ 消息目的是异步化调用短信平台
smsProducer.sendSmsSendMessage(sendLogId, mobile, template.getChannelId(), template.getApiTemplateId(), templateParams);
} }
@Override @Override
@ -79,11 +82,6 @@ public class SysSmsServiceImpl implements SysSmsService {
SysSmsTemplateDO template = this.checkSmsTemplateValid(templateCode, templateParams); SysSmsTemplateDO template = this.checkSmsTemplateValid(templateCode, templateParams);
} }
@Override
public void doSendSms() {
}
private SysSmsTemplateDO checkSmsTemplateValid(String templateCode, Map<String, Object> templateParams) { private SysSmsTemplateDO checkSmsTemplateValid(String templateCode, Map<String, Object> templateParams) {
// 短信模板不存在 // 短信模板不存在
SysSmsTemplateDO template = smsTemplateService.getSmsTemplateByCode(templateCode); SysSmsTemplateDO template = smsTemplateService.getSmsTemplateByCode(templateCode);
@ -132,10 +130,8 @@ public class SysSmsServiceImpl implements SysSmsService {
} }
@Override @Override
public void send(SmsBody smsBody, String targetPhone) { public void doSendSms(SysSmsSendMessage message) {
AbstractSmsClient client = channelService.getSmsClient(smsBody.getTemplateCode());
logService.beforeSendLog(smsBody, targetPhone, client);
smsProducer.sendSmsSendMessage(smsBody, targetPhone);
} }
@Override @Override