批量发送半成品
parent
c3372d4bd2
commit
767cd90279
@ -0,0 +1,27 @@
|
||||
package cn.iocoder.dashboard.common.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 通用状态枚举
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum DefaultBitFieldEnum {
|
||||
|
||||
NO(0, "否"),
|
||||
YES(1, "是");
|
||||
|
||||
/**
|
||||
* 状态值
|
||||
*/
|
||||
private final Integer val;
|
||||
/**
|
||||
* 状态名
|
||||
*/
|
||||
private final String name;
|
||||
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
package cn.iocoder.dashboard.framework.sms.client;
|
||||
|
||||
import cn.iocoder.dashboard.framework.sms.core.SmsResultDetail;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 需要发送请求获取短信发送结果的短信客户端
|
||||
*
|
||||
* @author zzf
|
||||
* @date 2021/3/4 17:20
|
||||
*/
|
||||
public interface HadCallbackSmsClient {
|
||||
|
||||
/**
|
||||
* 获取短信发送结果
|
||||
*
|
||||
* @param request 请求
|
||||
* @return 短信发送结果
|
||||
*/
|
||||
List<SmsResultDetail> getSmsSendResult(ServletRequest request) throws Exception;
|
||||
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
package cn.iocoder.dashboard.framework.sms.client;
|
||||
|
||||
import cn.iocoder.dashboard.framework.sms.core.SmsResultDetail;
|
||||
import com.aliyuncs.exceptions.ClientException;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 需要发送请求获取短信发送结果的短信客户端
|
||||
*
|
||||
* @author zzf
|
||||
* @date 2021/3/4 17:20
|
||||
*/
|
||||
public interface NeedQuerySendResultSmsClient {
|
||||
|
||||
/**
|
||||
* 获取短信发送结果
|
||||
*
|
||||
* @param param 参数
|
||||
* @return 短信发送结果
|
||||
*/
|
||||
List<SmsResultDetail> getSmsSendResult(String param) throws Exception;
|
||||
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
package cn.iocoder.dashboard.framework.sms.core;
|
||||
|
||||
/**
|
||||
* 短信相关常量类
|
||||
*
|
||||
* @author zzf
|
||||
* @date 2021/3/5 10:42
|
||||
*/
|
||||
public interface SmsConstants {
|
||||
|
||||
String OK = "OK";
|
||||
|
||||
String JING_HAO = "#";
|
||||
|
||||
String COMMA = ",";
|
||||
|
||||
String SUCCESS = "SUCCESS";
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
package cn.iocoder.dashboard.modules.system.controller.sms;
|
||||
|
||||
import cn.iocoder.dashboard.modules.system.service.sms.SysSmsService;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.ServletRequest;
|
||||
|
||||
/**
|
||||
* 短信默认回调接口
|
||||
*
|
||||
* @author zzf
|
||||
* @date 2021/3/5 8:59
|
||||
*/
|
||||
@RestController("/sms/callback")
|
||||
public class SmsDefaultCallbackController {
|
||||
|
||||
@Resource
|
||||
private SysSmsService smsService;
|
||||
|
||||
@RequestMapping("/sms-send")
|
||||
public Object sendSmsCallback(ServletRequest request){
|
||||
return smsService.smsSendCallbackHandle(request);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
package cn.iocoder.dashboard.modules.system.dal.mysql.dao.sms;
|
||||
|
||||
import cn.iocoder.dashboard.common.enums.DefaultBitFieldEnum;
|
||||
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.sms.SysSmsQueryLogDO;
|
||||
import cn.iocoder.dashboard.modules.system.enums.sms.SmsSendStatusEnum;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface SysSmsQueryLogMapper extends BaseMapper<SysSmsQueryLogDO> {
|
||||
|
||||
/**
|
||||
* 查询还没有获取发送结果的短信请求信息
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
default List<SysSmsQueryLogDO> selectNoResultQueryLogList() {
|
||||
return this.selectList(new LambdaQueryWrapper<SysSmsQueryLogDO>()
|
||||
.eq(SysSmsQueryLogDO::getSendStatus, SmsSendStatusEnum.QUERY_SUCCESS)
|
||||
.eq(SysSmsQueryLogDO::getGotResult, DefaultBitFieldEnum.NO)
|
||||
.eq(SysSmsQueryLogDO::getHadCallback, DefaultBitFieldEnum.NO)
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,10 +1,10 @@
|
||||
package cn.iocoder.dashboard.modules.system.dal.mysql.dao.sms;
|
||||
|
||||
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.sms.SysSmsLogDO;
|
||||
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.sms.SysSmsSendLogDO;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface SysSmsLogMapper extends BaseMapper<SysSmsLogDO> {
|
||||
public interface SysSmsSendLogMapper extends BaseMapper<SysSmsSendLogDO> {
|
||||
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
package cn.iocoder.dashboard.modules.system.service.sms;
|
||||
|
||||
/**
|
||||
* 短信发送日志服务接口
|
||||
*
|
||||
* @author zzf
|
||||
* @date 13:48 2021/3/2
|
||||
*/
|
||||
public interface SysSmsSendLogService {
|
||||
|
||||
void getAndSaveSmsSendLog();
|
||||
|
||||
}
|
||||
@ -1,77 +0,0 @@
|
||||
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.framework.sms.core.property.SmsChannelProperty;
|
||||
import cn.iocoder.dashboard.modules.system.dal.mysql.dao.sms.SysSmsLogMapper;
|
||||
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.sms.SysSmsLogDO;
|
||||
import cn.iocoder.dashboard.modules.system.enums.sms.SmsSendStatusEnum;
|
||||
import cn.iocoder.dashboard.modules.system.service.sms.SysSmsLogService;
|
||||
import cn.iocoder.dashboard.util.json.JsonUtils;
|
||||
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 SysSmsLogServiceImpl implements SysSmsLogService {
|
||||
|
||||
@Resource
|
||||
private SysSmsLogMapper logMapper;
|
||||
|
||||
@Override
|
||||
public Long beforeSendLog(SmsBody smsBody, List<String> targetPhones, AbstractSmsClient client, Boolean isAsync) {
|
||||
SysSmsLogDO smsLog = new SysSmsLogDO();
|
||||
if (smsBody.getSmsLogId() != null) {
|
||||
smsLog.setId(smsBody.getSmsLogId());
|
||||
smsLog.setSendStatus(SmsSendStatusEnum.SENDING.getStatus());
|
||||
logMapper.updateById(smsLog);
|
||||
return smsBody.getSmsLogId();
|
||||
} else {
|
||||
SmsChannelProperty property = client.getProperty();
|
||||
|
||||
smsLog.setChannelCode(property.getCode())
|
||||
.setChannelId(property.getId())
|
||||
.setTemplateCode(smsBody.getTemplateCode())
|
||||
.setPhones(JsonUtils.toJsonString(targetPhones))
|
||||
.setContent(smsBody.getParams().toString());
|
||||
|
||||
if (isAsync) {
|
||||
smsLog.setSendStatus(SmsSendStatusEnum.ASYNC.getStatus());
|
||||
} else {
|
||||
smsLog.setSendStatus(SmsSendStatusEnum.SENDING.getStatus());
|
||||
}
|
||||
logMapper.insert(smsLog);
|
||||
return smsLog.getId();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterSendLog(Long logId, SmsResult result) {
|
||||
SysSmsLogDO smsLog = new SysSmsLogDO();
|
||||
smsLog.setId(logId);
|
||||
if (result.getSuccess()) {
|
||||
smsLog.setSendStatus(SmsSendStatusEnum.SUCCESS.getStatus());
|
||||
SysSmsLogDO smsLogDO = logMapper.selectById(logId);
|
||||
result.getResult().forEach(s -> {
|
||||
smsLogDO.setPhones(s.getPhone());
|
||||
smsLogDO.setSendStatus(s.getStatus());
|
||||
smsLogDO.setRemark(s.getMessage());
|
||||
smsLogDO.setCreateTime(s.getCreateTime());
|
||||
logMapper.insert(smsLogDO);
|
||||
});
|
||||
} else {
|
||||
smsLog.setSendStatus(SmsSendStatusEnum.FAIL.getStatus());
|
||||
smsLog.setRemark(result.getMessage() + JsonUtils.toJsonString(result.getResult()));
|
||||
}
|
||||
logMapper.updateById(smsLog);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
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.framework.sms.core.property.SmsChannelProperty;
|
||||
import cn.iocoder.dashboard.modules.system.dal.mysql.dao.sms.SysSmsQueryLogMapper;
|
||||
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.sms.SysSmsQueryLogDO;
|
||||
import cn.iocoder.dashboard.modules.system.enums.sms.SmsSendStatusEnum;
|
||||
import cn.iocoder.dashboard.modules.system.service.sms.SysSmsQueryLogService;
|
||||
import cn.iocoder.dashboard.util.json.JsonUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 短信请求日志服务实现类
|
||||
*
|
||||
* @author zzf
|
||||
* @date 13:50 2021/3/2
|
||||
*/
|
||||
@Service
|
||||
public class SysSmsQueryLogServiceImpl implements SysSmsQueryLogService {
|
||||
|
||||
@Resource
|
||||
private SysSmsQueryLogMapper logMapper;
|
||||
|
||||
@Override
|
||||
public void beforeSendLog(SmsBody smsBody, List<String> targetPhones, AbstractSmsClient client) {
|
||||
SysSmsQueryLogDO smsLog = new SysSmsQueryLogDO();
|
||||
SmsChannelProperty property = client.getProperty();
|
||||
|
||||
smsLog.setChannelCode(property.getCode())
|
||||
.setChannelId(property.getId())
|
||||
.setTemplateCode(smsBody.getTemplateCode())
|
||||
.setPhones(targetPhones)
|
||||
.setContent(smsBody.getParams().toString());
|
||||
|
||||
smsLog.setSendStatus(SmsSendStatusEnum.ASYNC.getStatus());
|
||||
logMapper.insert(smsLog);
|
||||
smsBody.setSmsLogId(smsLog.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterSendLog(Long logId, SmsResult result) {
|
||||
SysSmsQueryLogDO smsLog = new SysSmsQueryLogDO();
|
||||
smsLog.setId(logId);
|
||||
if (result.getSuccess()) {
|
||||
smsLog.setSendStatus(SmsSendStatusEnum.QUERY_SUCCESS.getStatus());
|
||||
smsLog.setSendResultParam(result.getSendResultParam());
|
||||
} else {
|
||||
smsLog.setSendStatus(SmsSendStatusEnum.QUERY_FAIL.getStatus());
|
||||
smsLog.setRemark(result.getMessage());
|
||||
}
|
||||
logMapper.updateById(smsLog);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,109 @@
|
||||
package cn.iocoder.dashboard.modules.system.service.sms.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.iocoder.dashboard.framework.sms.client.AbstractSmsClient;
|
||||
import cn.iocoder.dashboard.framework.sms.client.NeedQuerySendResultSmsClient;
|
||||
import cn.iocoder.dashboard.framework.sms.core.SmsResultDetail;
|
||||
import cn.iocoder.dashboard.modules.system.dal.mysql.dao.sms.SysSmsQueryLogMapper;
|
||||
import cn.iocoder.dashboard.modules.system.dal.mysql.dao.sms.SysSmsSendLogMapper;
|
||||
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.sms.SysSmsQueryLogDO;
|
||||
import cn.iocoder.dashboard.modules.system.dal.mysql.dataobject.sms.SysSmsSendLogDO;
|
||||
import cn.iocoder.dashboard.modules.system.enums.sms.SmsSendStatusEnum;
|
||||
import cn.iocoder.dashboard.modules.system.service.sms.SysSmsChannelService;
|
||||
import cn.iocoder.dashboard.modules.system.service.sms.SysSmsSendLogService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 短信发送日志服务实现类
|
||||
*
|
||||
* @author zzf
|
||||
* @date 2021/1/25 9:25
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class SysSmsSendLogServiceImpl implements SysSmsSendLogService {
|
||||
|
||||
@Resource
|
||||
private SysSmsQueryLogMapper smsQueryLogMapper;
|
||||
|
||||
@Resource
|
||||
private SysSmsSendLogMapper smsSendLogMapper;
|
||||
|
||||
@Resource
|
||||
private SysSmsChannelService smsChannelService;
|
||||
|
||||
/**
|
||||
* 定时执行 {@link #getSmsSendResultJob()} 的周期
|
||||
*/
|
||||
private static final long SCHEDULER_PERIOD = 5 * 60 * 1000L;
|
||||
|
||||
|
||||
@Override
|
||||
public void getAndSaveSmsSendLog() {
|
||||
|
||||
List<SysSmsQueryLogDO> noResultQueryLogList = smsQueryLogMapper.selectNoResultQueryLogList();
|
||||
|
||||
if (CollectionUtil.isEmpty(noResultQueryLogList)) {
|
||||
return;
|
||||
}
|
||||
//用于添加的发送日志对象
|
||||
SysSmsSendLogDO insertSendLog = new SysSmsSendLogDO();
|
||||
//用于修改状态的请求日志对象
|
||||
SysSmsQueryLogDO updateQueryLog = new SysSmsQueryLogDO();
|
||||
|
||||
noResultQueryLogList.forEach(queryLog -> {
|
||||
AbstractSmsClient smsClient = smsChannelService.getSmsClient(queryLog.getTemplateCode());
|
||||
|
||||
updateQueryLog.setId(queryLog.getId());
|
||||
|
||||
// 只处理实现了获取发送结果方法的短信客户端,理论上这里都是满足条件的,以防万一加个判断。
|
||||
if (smsClient instanceof NeedQuerySendResultSmsClient) {
|
||||
//初始化点字段值
|
||||
queryLog2SendLong(insertSendLog, queryLog);
|
||||
|
||||
NeedQuerySendResultSmsClient querySendResultSmsClient = (NeedQuerySendResultSmsClient) smsClient;
|
||||
try {
|
||||
List<SmsResultDetail> smsSendResult = querySendResultSmsClient.getSmsSendResult(queryLog.getRemark());
|
||||
smsSendResult.forEach(resultDetail -> {
|
||||
insertSendLog.setPhone(resultDetail.getPhone());
|
||||
insertSendLog.setSendStatus(resultDetail.getSendStatus());
|
||||
insertSendLog.setSendTime(resultDetail.getSendTime());
|
||||
insertSendLog.setRemark(resultDetail.getMessage());
|
||||
smsSendLogMapper.insert(insertSendLog);
|
||||
});
|
||||
} catch (Exception e) {
|
||||
//exception handle
|
||||
log.error("query send result fail, exception: " + e.getMessage());
|
||||
|
||||
updateQueryLog.setSendStatus(SmsSendStatusEnum.QUERY_SEND_FAIL.getStatus());
|
||||
updateQueryLog.setRemark(e.getMessage());
|
||||
smsQueryLogMapper.updateById(updateQueryLog);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
//理论上这里都是满足条件的,以防万一加个判断。
|
||||
updateQueryLog.setSendStatus(SmsSendStatusEnum.QUERY_SEND_FAIL.getStatus());
|
||||
smsQueryLogMapper.updateById(updateQueryLog);
|
||||
}
|
||||
updateQueryLog.setSendStatus(SmsSendStatusEnum.SEND_SUCCESS.getStatus());
|
||||
updateQueryLog.setRemark(String.format("日志(id = %s)对应的客户端没有继承NeedQuerySendResultSmsClient, 不能获取短信结果。", queryLog.getId()));
|
||||
smsQueryLogMapper.updateById(updateQueryLog);
|
||||
});
|
||||
}
|
||||
|
||||
private void queryLog2SendLong(SysSmsSendLogDO insertSendLog, SysSmsQueryLogDO queryLog) {
|
||||
insertSendLog.setChannelCode(queryLog.getChannelCode());
|
||||
insertSendLog.setChannelId(queryLog.getChannelId());
|
||||
insertSendLog.setTemplateCode(queryLog.getTemplateCode());
|
||||
}
|
||||
|
||||
@Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD)
|
||||
public void getSmsSendResultJob() {
|
||||
getAndSaveSmsSendLog();
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue