Commit b5d2fcc1 authored by honghy's avatar honghy

新增短信日志穿梭、节点国家多选、模板预览

parent 471a32e1
......@@ -29,8 +29,8 @@ create table system_sms_node
is_transport tinyint not null comment '是否匹配运输方式(0:否,1:是)',
transport_id tinyint not null comment '运输方式ID',
is_orders tinyint not null comment '多订单(0:否,1:是)',
country_id bigint not null comment '国家区号id',
country_code varchar(30) not null comment '国家区号,和订单中国家区号保持一致',
country_id varchar(600) not null comment '国家区号id',
country_code varchar(600) not null comment '国家区号,和订单中国家区号保持一致',
status tinyint not null comment '启用状态(0:开启,1:关闭)',
template_id_one bigint not null comment '模板1',
template_id_two bigint comment '模板2',
......
......@@ -70,7 +70,23 @@ public class SmsNodeController {
@PreAuthorize("@ss.hasPermission('system:sms-node:query')")
public CommonResult<SmsNodeBackVO> getSmsNode(@RequestParam("id") Long id) {
SmsNodeDO smsNode = smsNodeService.getSmsNode(id);
return success(SmsNodeConvert.INSTANCE.convert(smsNode));
SmsNodeBackVO convert = SmsNodeConvert.INSTANCE.convert(smsNode);
String countryId = convert.getCountryId();
if (countryId == null || countryId.isEmpty()) {
convert.setCountryIds(new int[0]);
} else {
String[] countryIdsStr = countryId.split(",");
int[] countryIdsInt = new int[countryIdsStr.length];
for (int i = 0; i < countryIdsStr.length; i++) {
try {
countryIdsInt[i] = Integer.parseInt(countryIdsStr[i].trim());
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Invalid country ID: " + countryIdsStr[i], e);
}
}
convert.setCountryIds(countryIdsInt);
}
return success(convert);
}
@GetMapping("/list")
......@@ -95,7 +111,7 @@ public class SmsNodeController {
@PreAuthorize("@ss.hasPermission('system:sms-node:export')")
@OperateLog(type = EXPORT)
public void exportSmsNodeExcel(@Valid SmsNodeQueryVO query,
HttpServletResponse response) throws IOException {
HttpServletResponse response) throws IOException {
List<SmsNodeDO> list = smsNodeService.getSmsNodeList(query);
// 导出 Excel
List<SmsNodeBackVO> datas = SmsNodeConvert.INSTANCE.convertList(list);
......@@ -107,7 +123,7 @@ public class SmsNodeController {
public CommonResult<Boolean> test(@Valid @RequestBody SmsNodeTestVO smsNodeTestVO) {
smsSendService.sendSingleSmsV2(smsNodeTestVO.getMobile(), SecurityFrameworkUtils.getLoginUserId(), UserTypeEnum.ADMIN.getValue(), smsNodeTestVO.getNodeValue(),
smsNodeTestVO.getCountryCode(), smsNodeTestVO.getIsOrders(), smsNodeTestVO.getIsTransport(), smsNodeTestVO.getTransportId(),
smsNodeTestVO.getMessageType(), smsNodeTestVO.getTemplateParams(), null, smsNodeTestVO.getNodeTemplateSn());
smsNodeTestVO.getMessageType(), smsNodeTestVO.getTemplateParams(), null, smsNodeTestVO.getNodeTemplateSn(),null);
return success(true);
}
}
package cn.iocoder.yudao.module.system.controller.admin.sms.vo.smsNode;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import com.alibaba.excel.annotation.ExcelProperty;
import cn.iocoder.yudao.framework.excel.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.convert.DictConvert;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
/**
......@@ -36,12 +36,16 @@ public class SmsNodeBackVO {
@ExcelProperty("国家区号")
@ApiModelProperty(value = "国家区号", required = true)
private Long countryId;
private String countryId;
@ExcelProperty("国家区号")
@ApiModelProperty(value = "国家区号,和订单中国家区号保持一致", required = true)
private String countryCode;
@ExcelProperty("国家区号")
@ApiModelProperty(value = "国家区号,和订单中国家区号保持一致", required = true)
private int[] countryIds;
@ExcelProperty("启用状态")
@ApiModelProperty(value = "启用状态(0:启用,1:关闭)", required = true)
private Integer status;
......
package cn.iocoder.yudao.module.system.controller.admin.sms.vo.smsNode;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import javax.validation.constraints.*;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* 短信节点 Base VO,提供给添加、修改、详细的子 VO 使用
......@@ -23,7 +22,7 @@ public class SmsNodeBaseVO {
@ApiModelProperty(value = "国家区号id", required = true)
@NotNull(message = "国家区号id不能为空")
private Long countryId;
private String countryId;
@ApiModelProperty(value = "国家区号,和订单中国家区号保持一致", required = true)
@NotNull(message = "国家区号,和订单中国家区号保持一致不能为空")
......
......@@ -21,7 +21,7 @@ public class SmsNodeQueryVO extends PageParam{
private Long transportId;
@ApiModelProperty(value = "国家区号id")
private Long countryId;
private String countryId;
@ApiModelProperty(value = "国家区号,和订单中国家区号保持一致")
private String countryCode;
......
......@@ -15,6 +15,9 @@ import java.util.Map;
@Data
public class SmsNodeTestVO {
@ApiModelProperty(value = "id")
private Long id;
@ApiModelProperty(value = "节点", required = true)
@NotNull(message = "节点不能为空")
private String nodeValue;
......
package cn.iocoder.yudao.module.system.dal.dataobject.sms;
import lombok.*;
import java.util.*;
import com.baomidou.mybatisplus.annotation.*;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.FieldStrategy;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
/**
* 短信节点 DO
......@@ -36,7 +38,7 @@ public class SmsNodeDO extends BaseDO {
/**
* 国家区号id
*/
private Long countryId;
private String countryId;
/**
* 国家区号,和订单中国家区号保持一致
*/
......
......@@ -41,7 +41,7 @@ public class SmsCodeServiceImpl implements SmsCodeService {
String code = createSmsCode(reqDTO.getMobile(), reqDTO.getNodeValue(), reqDTO.getCreateIp());
// 发送验证码
smsSendService.sendSingleSmsV2(reqDTO.getAreaCode() + reqDTO.getMobile(), null, null, reqDTO.getNodeValue(), reqDTO.getAreaCode(), reqDTO.getIsOrders(), reqDTO.getIsTransport(),
reqDTO.getTransportId(), reqDTO.getMessageType(), MapUtil.of("code", code), null, 1);
reqDTO.getTransportId(), reqDTO.getMessageType(), MapUtil.of("code", code), null, 1,null);
}
private String createSmsCode(String mobile, String nodeValue, String ip) {
......
......@@ -24,8 +24,7 @@ import org.springframework.validation.annotation.Validated;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;
import java.util.*;
import static cn.iocoder.yudao.framework.apollo.core.constants.CacheConstants.SYSTEM_SMS_NODE_KEY;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
......@@ -74,15 +73,7 @@ public class SmsNodeServiceImpl extends AbstractService<SmsNodeMapper, SmsNodeDO
// 从数据库中选择所有短信节点数据对象
List<SmsNodeDO> smsNodeDOList = smsNodeMapper.selectList();
for (SmsNodeDO smsNodeDO : smsNodeDOList) {
// 构建缓存键
String key = buildCacheKey(smsNodeDO);
// 将对象转换为JSON字符串作为缓存值
String value = JSON.toJSONString(smsNodeDO);
// 将键值对存入Redis缓存
redisHelper.set(key, value);
redisHelper.set(SYSTEM_SMS_NODE_KEY + smsNodeDO.getId(), value);
// 记录日志信息
// log.info("Cache key: {}, value: {}", key, value);
createCache(smsNodeDO);
}
} catch (Exception e) {
// 记录错误日志信息
......@@ -164,7 +155,7 @@ public class SmsNodeServiceImpl extends AbstractService<SmsNodeMapper, SmsNodeDO
// 调用短信发送服务重新发送短信
smsSendService.sendSingleSmsV2(smsLog.getMobile(), smsLog.getUserId(), smsLog.getUserType(), smsNodeDO.getNodeValue(),
smsNodeDO.getCountryCode(), smsNodeDO.getIsOrders(), smsNodeDO.getIsTransport(), smsNodeDO.getTransportId(),
smsLog.getMessageType(), smsLog.getTemplateParams(), smsLog.getId(), smsLog.getNodeTemplateSn() + 1);
smsLog.getMessageType(), smsLog.getTemplateParams(), smsLog.getId(), smsLog.getNodeTemplateSn() + 1, smsNodeDO);
}
}
......@@ -192,13 +183,48 @@ public class SmsNodeServiceImpl extends AbstractService<SmsNodeMapper, SmsNodeDO
// 插入新的短信节点到数据库
smsNodeMapper.insert(smsNode);
// 设置新的缓存
redisHelper.set(buildCacheKey(smsNode), JSON.toJSONString(smsNode));
redisHelper.set(SYSTEM_SMS_NODE_KEY + smsNode.getId(), JSON.toJSONString(smsNode));
createCache(smsNode);
// 返回新创建的短信节点的ID
return smsNode.getId();
}
/**
* 创建缓存
*/
public void createCache(SmsNodeDO smsNode) {
String[] countryCodesStr = smsNode.getCountryCode().split(",");
Map<String, String> maps = new HashMap<>();
for (String s : countryCodesStr) {
smsNode.setCountryCode(s);
// 构建缓存键
String key = buildCacheKey(smsNode);
// 将对象转换为JSON字符串作为缓存值
String value = JSON.toJSONString(smsNode);
maps.put(key, value);
}
// 将键值对存入Redis缓存
redisHelper.multiSet(maps);
redisHelper.set(SYSTEM_SMS_NODE_KEY + smsNode.getId(), JSON.toJSONString(smsNode));
}
/**
* 删除缓存
*/
public void deleteCache(SmsNodeDO smsNode) {
String[] countryCodesStr = smsNode.getCountryCode().split(",");
Collection<String> keys = new ArrayList<>();
for (String s : countryCodesStr) {
smsNode.setCountryCode(s);
// 构建缓存键
String key = buildCacheKey(smsNode);
keys.add(key);
}
// 将键值对存入Redis缓存
redisHelper.delete(keys);
redisHelper.delete(SYSTEM_SMS_NODE_KEY + smsNode.getId());
}
/**
* 更新短信节点信息
*
......@@ -220,10 +246,9 @@ public class SmsNodeServiceImpl extends AbstractService<SmsNodeMapper, SmsNodeDO
// 更新数据库中的短信节点信息
smsNodeMapper.updateById(updateObj);
// 删除旧的缓存
redisHelper.delete(buildCacheKey(smsNodeDO));
// 设置新的缓存
redisHelper.set(buildCacheKey(updateObj), JSON.toJSONString(updateObj));
redisHelper.set(SYSTEM_SMS_NODE_KEY + updateObj.getId(), JSON.toJSONString(updateObj));
deleteCache(smsNodeDO);
// 创建新的缓存
createCache(updateObj);
}
@Override
......@@ -233,8 +258,7 @@ public class SmsNodeServiceImpl extends AbstractService<SmsNodeMapper, SmsNodeDO
// 删除
smsNodeMapper.deleteById(id);
// 删除缓存中的短信节点信息
redisHelper.delete(buildCacheKey(smsNodeDO));
redisHelper.delete(SYSTEM_SMS_NODE_KEY + id);
deleteCache(smsNodeDO);
}
private SmsNodeDO validateSmsNodeExists(Long id) {
......
package cn.iocoder.yudao.module.system.service.sms;
import cn.iocoder.yudao.framework.common.validation.Mobile;
import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsNodeDO;
import cn.iocoder.yudao.module.system.mq.message.sms.SmsSendMessage;
import cn.iocoder.yudao.module.system.mq.message.sms.SmsSendMessageV2;
......@@ -112,11 +113,12 @@ public interface SmsSendService {
* @param messageType 发送类型
* @param templateParams 短信模板参数
* @param smsLogId 重发短信时的原短信日志id
* @param nodeTemplateSn 模板序号
* @param nodeTemplateSn 模板序号
* @param smsNode 节点对象
*/
Long sendSingleSmsV2(@Mobile @NotEmpty(message = "手机号不能为空") String mobile, Long userId, Integer userType, @NotNull(message = "业务节点不能为空") String nodeValue,
@NotNull(message = "国家区号不能为空") String areaCode, @NotNull(message = "是否多订单不能为空") Integer isOrders, @NotNull(message = "是否匹配运输方式不能为空") Integer isTransport,
@NotNull(message = "运输方式不能空") Integer transportId, @NotNull(message = "发送类型不能为空") Integer messageType, Map<String, Object> templateParams, Long smsLogId, Integer nodeTemplateSn);
@NotNull(message = "运输方式不能空") Integer transportId, @NotNull(message = "发送类型不能为空") Integer messageType, Map<String, Object> templateParams, Long smsLogId, Integer nodeTemplateSn, SmsNodeDO smsNode);
void resendSingleSmsBySmsLogIds(Collection<Long> smsLogIds);
......
......@@ -102,7 +102,7 @@ public class SmsSendServiceImpl implements SmsSendService {
}
}
// 执行发送
return this.sendSingleSmsV2(areaCode + mobile, userId, UserTypeEnum.ADMIN.getValue(), nodeValue, areaCode, isOrders, isTransport, transportId, messageType, templateParams, null, 1);
return this.sendSingleSmsV2(areaCode + mobile, userId, UserTypeEnum.ADMIN.getValue(), nodeValue, areaCode, isOrders, isTransport, transportId, messageType, templateParams, null, 1, null);
}
@Override
......@@ -131,7 +131,7 @@ public class SmsSendServiceImpl implements SmsSendService {
}
}
// 执行发送
return this.sendSingleSmsV2(areaCode + mobile, userId, UserTypeEnum.MEMBER.getValue(), nodeValue, areaCode, isOrders, isTransport, transportId, messageType, templateParams, null, 1);
return this.sendSingleSmsV2(areaCode + mobile, userId, UserTypeEnum.MEMBER.getValue(), nodeValue, areaCode, isOrders, isTransport, transportId, messageType, templateParams, null, 1, null);
}
@Override
......@@ -314,44 +314,47 @@ public class SmsSendServiceImpl implements SmsSendService {
* @param templateParams 短信模板参数
* @param smsLogId 重发短信时的原短信日志id
* @param nodeTemplateSn 模板序号
* @param smsNode 节点对象
*/
@Override
public Long sendSingleSmsV2(String mobile, Long userId, Integer userType, String nodeValue, String areaCode,
Integer isOrders, Integer isTransport, Integer transportId, Integer messageType, Map<String, Object> templateParams, Long smsLogId, Integer nodeTemplateSn) {
// 创建SmsNodeDO对象并设置相关属性
SmsNodeDO smsNodeDO = new SmsNodeDO()
.setNodeValue(nodeValue)
.setIsTransport(isTransport)
.setTransportId(transportId)
.setIsOrders(isOrders)
.setCountryCode(areaCode)
.setStatus(SystemStatusEnum.SYSTEM_STATUS_0.getValue());
// 构建缓存键,用于查询短信节点缓存
String cacheKey = smsNodeService.buildCacheKey(smsNodeDO);
String smsNodeCache = redisHelper.get(cacheKey);
// 第一次找不到,则在全部国家里面找
if (smsNodeCache == null) {
smsNodeDO.setCountryCode(SmsCountryCodeEnum.SMS_COUNTRY_CODE_0.getValue());
cacheKey = smsNodeService.buildCacheKey(smsNodeDO);
smsNodeCache = redisHelper.get(cacheKey);
// 第二次找不到,则在其他国家里面找
Integer isOrders, Integer isTransport, Integer transportId, Integer messageType, Map<String, Object> templateParams, Long smsLogId, Integer nodeTemplateSn, SmsNodeDO smsNode) {
//首次发送
if (smsNode == null) {
// 创建SmsNodeDO对象并设置相关属性
SmsNodeDO smsNodeDO = new SmsNodeDO()
.setNodeValue(nodeValue)
.setIsTransport(isTransport)
.setTransportId(transportId)
.setIsOrders(isOrders)
.setCountryCode(areaCode)
.setStatus(SystemStatusEnum.SYSTEM_STATUS_0.getValue());
// 构建缓存键,用于查询短信节点缓存
String cacheKey = smsNodeService.buildCacheKey(smsNodeDO);
String smsNodeCache = redisHelper.get(cacheKey);
// 第一次找不到,则在全部国家里面找
if (smsNodeCache == null) {
smsNodeDO.setCountryCode(SmsCountryCodeEnum.SMS_COUNTRY_CODE_1.getValue());
smsNodeDO.setCountryCode(SmsCountryCodeEnum.SMS_COUNTRY_CODE_0.getValue());
cacheKey = smsNodeService.buildCacheKey(smsNodeDO);
smsNodeCache = redisHelper.get(cacheKey);
// 第二次找不到,则在其他国家里面找
if (smsNodeCache == null) {
smsNodeDO.setCountryCode(SmsCountryCodeEnum.SMS_COUNTRY_CODE_1.getValue());
cacheKey = smsNodeService.buildCacheKey(smsNodeDO);
smsNodeCache = redisHelper.get(cacheKey);
}
}
}
// 如果 still null, throw exception
if (smsNodeCache == null) {
throw exception(SMS_SEND_TEMPLATE_NOT_EXISTS);
// 如果 still null, throw exception
if (smsNodeCache == null) {
throw exception(SMS_SEND_TEMPLATE_NOT_EXISTS);
}
// 解析缓存获取短信节点信息
smsNode = JSON.parseObject(smsNodeCache, SmsNodeDO.class);
}
// 解析缓存获取短信节点信息
SmsNodeDO smsNode = JSON.parseObject(smsNodeCache, SmsNodeDO.class);
String smsTemplateDO = null;
// 从缓存中获取短信模板信息
for (int i = nodeTemplateSn; i <= 4; i++) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment