短信提交 2021-03-28,增加发送日志
parent
46ed64ba40
commit
515fca5c41
@ -0,0 +1,21 @@
|
|||||||
|
package cn.iocoder.dashboard.framework.sms.config;
|
||||||
|
|
||||||
|
import cn.iocoder.dashboard.framework.sms.core.client.SmsClientFactory;
|
||||||
|
import cn.iocoder.dashboard.framework.sms.core.client.impl.SmsClientFactoryImpl;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 短信配置类
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class SmsConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public SmsClientFactory smsClientFactory() {
|
||||||
|
return new SmsClientFactoryImpl();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,38 +0,0 @@
|
|||||||
package cn.iocoder.dashboard.framework.sms.core;
|
|
||||||
|
|
||||||
import cn.iocoder.dashboard.util.json.JsonUtils;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 消息内容实体类
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
public class SmsBody {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 消息日志id
|
|
||||||
*/
|
|
||||||
private Long smsLogId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 模板编码
|
|
||||||
*/
|
|
||||||
private String templateCode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 模板编码
|
|
||||||
*/
|
|
||||||
private String templateContent;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 参数列表
|
|
||||||
*/
|
|
||||||
private Map<String, String> params;
|
|
||||||
|
|
||||||
public String getParamsStr() {
|
|
||||||
return JsonUtils.toJsonString(params);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
package cn.iocoder.dashboard.framework.sms.core.client;
|
||||||
|
|
||||||
|
import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 短信客户端工厂接口
|
||||||
|
*
|
||||||
|
* @author zzf
|
||||||
|
* @date 2021/1/28 14:01
|
||||||
|
*/
|
||||||
|
public interface SmsClientFactory {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得短信 Client
|
||||||
|
*
|
||||||
|
* @param channelId 渠道编号
|
||||||
|
* @return 短信 Client
|
||||||
|
*/
|
||||||
|
SmsClient getSmsClient(Long channelId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建短信 Client
|
||||||
|
*
|
||||||
|
* @param properties 配置对象
|
||||||
|
*/
|
||||||
|
void createOrUpdateSmsClient(SmsChannelProperties properties);
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,52 @@
|
|||||||
|
package cn.iocoder.dashboard.framework.sms.core.property;
|
||||||
|
|
||||||
|
import cn.iocoder.dashboard.framework.sms.core.enums.SmsChannelEnum;
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotEmpty;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 短信渠道配置类
|
||||||
|
*
|
||||||
|
* @author zzf
|
||||||
|
* @date 2021/1/25 17:01
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Validated
|
||||||
|
public class SmsChannelProperties {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 渠道编号
|
||||||
|
*/
|
||||||
|
@NotNull(message = "短信渠道 ID 不能为空")
|
||||||
|
private Long id;
|
||||||
|
/**
|
||||||
|
* 短信签名
|
||||||
|
*/
|
||||||
|
@NotEmpty(message = "短信签名不能为空")
|
||||||
|
private String signature;
|
||||||
|
/**
|
||||||
|
* 渠道编码
|
||||||
|
*
|
||||||
|
* 枚举 {@link SmsChannelEnum}
|
||||||
|
*/
|
||||||
|
@NotEmpty(message = "渠道编码不能为空")
|
||||||
|
private String code;
|
||||||
|
/**
|
||||||
|
* 短信 API 的账号
|
||||||
|
*/
|
||||||
|
@NotEmpty(message = "短信 API 的账号不能为空")
|
||||||
|
private String apiKey;
|
||||||
|
/**
|
||||||
|
* 短信 API 的秘钥
|
||||||
|
*/
|
||||||
|
@NotEmpty(message = "短信 API 的秘钥不能为空")
|
||||||
|
private String apiSecret;
|
||||||
|
/**
|
||||||
|
* 短信发送回调 URL
|
||||||
|
*/
|
||||||
|
private String callbackUrl;
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,47 +0,0 @@
|
|||||||
package cn.iocoder.dashboard.framework.sms.core.property;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
import javax.validation.constraints.NotEmpty;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 渠道模板VO类
|
|
||||||
*
|
|
||||||
* @author zzf
|
|
||||||
* @date 2021/1/25 17:03
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@EqualsAndHashCode
|
|
||||||
public class SmsTemplateProperty {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 渠道id
|
|
||||||
*/
|
|
||||||
@NotEmpty(message = "短信渠道编码不能为空")
|
|
||||||
private Long channelId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 业务编码(来自数据字典, 用户自定义业务场景 一个场景可以有多个模板)
|
|
||||||
*/
|
|
||||||
private String bizCode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 编码
|
|
||||||
*/
|
|
||||||
@NotEmpty(message = "短信模板编码不能为空")
|
|
||||||
private String code;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 实际渠道模板唯一标识
|
|
||||||
*/
|
|
||||||
@NotEmpty(message = "短信模板唯一标识不能为空")
|
|
||||||
private String apiTemplateId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 内容
|
|
||||||
*/
|
|
||||||
@NotEmpty(message = "短信模板内容不能为空")
|
|
||||||
private String content;
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,66 +0,0 @@
|
|||||||
package cn.iocoder.dashboard.modules.system.dal.dataobject.sms;
|
|
||||||
|
|
||||||
import cn.iocoder.dashboard.modules.system.enums.sms.SysSmsSendStatusEnum;
|
|
||||||
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_send_log", autoResultMap = true)
|
|
||||||
public class SysSmsSendLogDOX implements Serializable {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 自增编号
|
|
||||||
*/
|
|
||||||
private Long id;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 短信渠道编码(来自枚举类)
|
|
||||||
*/
|
|
||||||
private String channelCode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 短信渠道id
|
|
||||||
*/
|
|
||||||
private Long channelId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 模板id
|
|
||||||
*/
|
|
||||||
private String templateCode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 手机号
|
|
||||||
*/
|
|
||||||
private String phone;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 备注
|
|
||||||
*/
|
|
||||||
private String remark;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 发送状态
|
|
||||||
*
|
|
||||||
* @see SysSmsSendStatusEnum
|
|
||||||
*/
|
|
||||||
private Integer sendStatus;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 发送时间
|
|
||||||
*/
|
|
||||||
private Date sendTime;
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,31 +1,27 @@
|
|||||||
package cn.iocoder.dashboard.modules.system.dal.mysql.sms;
|
package cn.iocoder.dashboard.modules.system.dal.mysql.sms;
|
||||||
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.iocoder.dashboard.common.enums.CommonStatusEnum;
|
import cn.iocoder.dashboard.common.pojo.PageResult;
|
||||||
import cn.iocoder.dashboard.framework.mybatis.core.util.MyBatisUtils;
|
import cn.iocoder.dashboard.framework.mybatis.core.mapper.BaseMapperX;
|
||||||
import cn.iocoder.dashboard.modules.system.controller.sms.vo.req.SmsChannelPageReqVO;
|
import cn.iocoder.dashboard.modules.system.controller.sms.vo.req.SmsChannelPageReqVO;
|
||||||
import cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsChannelDO;
|
import cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsChannelDO;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Mapper
|
@Mapper
|
||||||
public interface SysSmsChannelMapper extends BaseMapper<SysSmsChannelDO> {
|
public interface SysSmsChannelMapper extends BaseMapperX<SysSmsChannelDO> {
|
||||||
|
|
||||||
default IPage<SysSmsChannelDO> selectChannelPage(SmsChannelPageReqVO reqVO) {
|
default PageResult<SysSmsChannelDO> selectChannelPage(SmsChannelPageReqVO reqVO) {
|
||||||
return selectPage(MyBatisUtils.buildPage(reqVO), new LambdaQueryWrapper<SysSmsChannelDO>()
|
return selectPage(reqVO, new LambdaQueryWrapper<SysSmsChannelDO>()
|
||||||
.like(StrUtil.isNotBlank(reqVO.getName()), SysSmsChannelDO::getName, reqVO.getName())
|
.like(StrUtil.isNotBlank(reqVO.getSignature()), SysSmsChannelDO::getSignature, reqVO.getSignature()));
|
||||||
.like(StrUtil.isNotBlank(reqVO.getSignature()), SysSmsChannelDO::getName, reqVO.getSignature())
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
default List<SysSmsChannelDO> selectEnabledList() {
|
default List<SysSmsChannelDO> selectListByStatus(Integer status) {
|
||||||
return selectList(new LambdaQueryWrapper<SysSmsChannelDO>()
|
return selectList(new LambdaQueryWrapper<SysSmsChannelDO>()
|
||||||
.eq(SysSmsChannelDO::getStatus, CommonStatusEnum.ENABLE.getStatus())
|
.eq(SysSmsChannelDO::getStatus, status)
|
||||||
.orderByAsc(SysSmsChannelDO::getId)
|
.orderByAsc(SysSmsChannelDO::getId));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,34 +0,0 @@
|
|||||||
package cn.iocoder.dashboard.modules.system.dal.mysql.sms;
|
|
||||||
|
|
||||||
import cn.iocoder.dashboard.common.enums.DefaultBitFieldEnum;
|
|
||||||
import cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsSendLogDO;
|
|
||||||
import cn.iocoder.dashboard.modules.system.enums.sms.SysSmsSendStatusEnum;
|
|
||||||
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<SysSmsSendLogDO> {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查询还没有获取发送结果的短信请求信息
|
|
||||||
*/
|
|
||||||
default List<SysSmsSendLogDO> selectNoResultQueryLogList() {
|
|
||||||
return this.selectList(new LambdaQueryWrapper<SysSmsSendLogDO>()
|
|
||||||
.eq(SysSmsSendLogDO::getSendStatus, SysSmsSendStatusEnum.QUERY_SUCCESS)
|
|
||||||
.eq(SysSmsSendLogDO::getGotResult, DefaultBitFieldEnum.NO)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据APIId修改对象
|
|
||||||
*/
|
|
||||||
default boolean updateByApiId(SysSmsSendLogDO queryLogDO, String apiId) {
|
|
||||||
return update(queryLogDO, new LambdaQueryWrapper<SysSmsSendLogDO>()
|
|
||||||
.eq(SysSmsSendLogDO::getApiId, apiId)
|
|
||||||
) > 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,10 +1,9 @@
|
|||||||
package cn.iocoder.dashboard.modules.system.dal.mysql.sms;
|
package cn.iocoder.dashboard.modules.system.dal.mysql.sms;
|
||||||
|
|
||||||
|
import cn.iocoder.dashboard.framework.mybatis.core.mapper.BaseMapperX;
|
||||||
import cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsSendLogDO;
|
import cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsSendLogDO;
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
@Mapper
|
@Mapper
|
||||||
public interface SysSmsSendLogMapper extends BaseMapper<SysSmsSendLogDO> {
|
public interface SysSmsSendLogMapper extends BaseMapperX<SysSmsSendLogDO> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,35 +0,0 @@
|
|||||||
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 cn.iocoder.dashboard.framework.sms.core.SmsResultDetail;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 短信请求日志服务接口
|
|
||||||
*
|
|
||||||
* @author zzf
|
|
||||||
* @date 2021/1/25 9:24
|
|
||||||
*/
|
|
||||||
public interface SysSmsQueryLogService {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 发送短信前的日志处理
|
|
||||||
*
|
|
||||||
* @param smsBody 短信内容
|
|
||||||
* @param targetPhone 发送对象手机号
|
|
||||||
* @param client 短信客户端
|
|
||||||
* @return 生成的日志id
|
|
||||||
*/
|
|
||||||
void beforeSendLog(SmsBody smsBody, String targetPhone, AbstractSmsClient client);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 发送消息后的日志处理
|
|
||||||
*
|
|
||||||
* @param logId 日志id
|
|
||||||
* @param result 消息结果
|
|
||||||
*/
|
|
||||||
void afterSendLog(Long logId, SmsResult result);
|
|
||||||
|
|
||||||
void updateSendLogByResultDetail(SmsResultDetail smsResultDetail);
|
|
||||||
}
|
|
||||||
@ -1,63 +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.SmsResultDetail;
|
|
||||||
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.dataobject.sms.SysSmsSendLogDO;
|
|
||||||
import cn.iocoder.dashboard.modules.system.enums.sms.SysSmsSendStatusEnum;
|
|
||||||
import cn.iocoder.dashboard.modules.system.service.sms.SysSmsQueryLogService;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 短信请求日志服务实现类
|
|
||||||
*
|
|
||||||
* @author zzf
|
|
||||||
* @date 13:50 2021/3/2
|
|
||||||
*/
|
|
||||||
@Service
|
|
||||||
public class SysSmsQueryLogServiceImpl implements SysSmsQueryLogService {
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private SysSmsQueryLogMapper logMapper;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void beforeSendLog(SmsBody smsBody, String targetPhone, AbstractSmsClient client) {
|
|
||||||
SysSmsSendLogDO smsLog = new SysSmsSendLogDO();
|
|
||||||
SmsChannelProperty property = client.getProperty();
|
|
||||||
|
|
||||||
smsLog.setChannelCode(property.getCode())
|
|
||||||
.setChannelId(property.getId())
|
|
||||||
.setTemplateCode(smsBody.getTemplateCode())
|
|
||||||
.setPhone(targetPhone)
|
|
||||||
.setContent(smsBody.getParams().toString());
|
|
||||||
|
|
||||||
smsLog.setSendStatus(SysSmsSendStatusEnum.ASYNC.getStatus());
|
|
||||||
logMapper.insert(smsLog);
|
|
||||||
smsBody.setSmsLogId(smsLog.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void afterSendLog(Long logId, SmsResult result) {
|
|
||||||
SysSmsSendLogDO smsLog = new SysSmsSendLogDO();
|
|
||||||
smsLog.setId(logId);
|
|
||||||
smsLog.setApiId(result.getApiId());
|
|
||||||
smsLog.setSendStatus(SysSmsSendStatusEnum.QUERY_FAIL.getStatus());
|
|
||||||
smsLog.setRemark(result.getCode() + ": " + result.getMessage());
|
|
||||||
logMapper.updateById(smsLog);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateSendLogByResultDetail(SmsResultDetail smsResultDetail) {
|
|
||||||
SysSmsSendLogDO queryLogDO = new SysSmsSendLogDO();
|
|
||||||
queryLogDO.setSendStatus(smsResultDetail.getSendStatus());
|
|
||||||
queryLogDO.setSendTime(smsResultDetail.getSendTime());
|
|
||||||
queryLogDO.setRemark(smsResultDetail.getMessage());
|
|
||||||
logMapper.updateByApiId(queryLogDO, smsResultDetail.getApiId());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue