功能:在保险、规则、交易、积分和短信模块中实现初始功能和基础组件。

This commit is contained in:
abcv7
2026-03-03 04:04:22 +08:00
parent e050eb3317
commit e156d625bf
1999 changed files with 146080 additions and 63 deletions
+21
View File
@@ -0,0 +1,21 @@
FROM openjdk:11-jdk
LABEL maintainer="研究院研发组 <research@itcast.cn>"
# 时区修改为东八区
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
WORKDIR /sms-web
ARG PACKAGE_PATH=./target/sms-web.jar
ADD ${PACKAGE_PATH:-./} sms-web.jar
EXPOSE 8080
ENV JAVA_OPTS="\
-server \
-Xms256m \
-Xmx512m \
-XX:MetaspaceSize=256m \
-XX:MaxMetaspaceSize=512m\
-Dspring.profiles.active=test"
ENTRYPOINT ["sh","-c","java -Djava.security.egd=file:/dev/./urandom -jar $JAVA_OPTS sms-web.jar"]
+126
View File
@@ -0,0 +1,126 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.itheima.sfbx</groupId>
<artifactId>sfbx-sms</artifactId>
<version>2.0-SNAPSHOT</version>
</parent>
<artifactId>sms-web</artifactId>
<name>sms-web</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<dependency>
<groupId>com.itheima.sfbx</groupId>
<artifactId>framework-mybatis-plus</artifactId>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
</dependency>
<dependency>
<groupId>com.itheima.sfbx</groupId>
<artifactId>file-interface</artifactId>
</dependency>
<dependency>
<groupId>com.itheima.sfbx</groupId>
<artifactId>framework-task-executor</artifactId>
</dependency>
<dependency>
<groupId>com.itheima.sfbx</groupId>
<artifactId>framework-redis</artifactId>
</dependency>
<dependency>
<groupId>com.itheima.sfbx</groupId>
<artifactId>framework-seata</artifactId>
</dependency>
<dependency>
<groupId>com.itheima.sfbx</groupId>
<artifactId>framework-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>com.itheima.sfbx</groupId>
<artifactId>framework-knife4j-web</artifactId>
</dependency>
<dependency>
<groupId>com.itheima.sfbx</groupId>
<artifactId>framework-rabbitmq</artifactId>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>dysmsapi20170525</artifactId>
</dependency>
<dependency>
<groupId>com.tencentcloudapi</groupId>
<artifactId>tencentcloud-sdk-java</artifactId>
<exclusions>
<exclusion>
<artifactId>logging-interceptor</artifactId>
<groupId>com.squareup.okhttp</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.baidubce</groupId>
<artifactId>bce-java-sdk</artifactId>
<exclusions>
<exclusion>
<artifactId>jdk.tools</artifactId>
<groupId>jdk.tools</groupId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.yml</include>
<include>**/*.properties</include>
<include>**/*.xml</include>
<include>**/*.yaml</include>
<include>**/*.txt</include>
</includes>
</resource>
</resources>
<finalName>sms-web</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
@@ -0,0 +1,15 @@
package com.itheima.sfbx.sms;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* 短信微服务启动类
*/
@SpringBootApplication(scanBasePackages = "com.itheima.sfbx")
public class SmsWebStart {
public static void main(String[] args) {
SpringApplication.run(SmsWebStart.class, args);
}
}
@@ -0,0 +1,42 @@
package com.itheima.sfbx.sms.adapter;
import com.itheima.sfbx.sms.pojo.SmsSendRecord;
import java.util.LinkedHashMap;
import java.util.Set;
/**
* @ClassName SmsSendAdapter.java
* @Description 邮件发送适配器
*/
public interface SmsSendAdapter {
/***
* @description 发送短信接口
* @param templateNo 应用模板编号
* @param sginNo 应用签名编号
* @param loadBalancerType 通道负载均衡策略
* @param mobiles 手机号
* @param templateParam 模板动态参数
*/
Boolean SendSms(
String templateNo,
String sginNo,
String loadBalancerType,
Set<String> mobiles,
LinkedHashMap<String, String> templateParam);
/***
* @description 查询短信接受情况
* @param smsSendRecord 发送记录
* @return
*/
Boolean querySendSms(SmsSendRecord smsSendRecord);
/***
* @description 重试发送
* @param smsSendRecord
* @return
*/
Boolean retrySendSms(SmsSendRecord smsSendRecord);
}
@@ -0,0 +1,40 @@
package com.itheima.sfbx.sms.adapter;
import com.itheima.sfbx.framework.commons.dto.sms.SmsSignVO;
/**
* @ClassName SmsSignAdapter.java
* @Description 签名适配器接口
*/
public interface SmsSignAdapter {
/***
* @description 申请签名
* @param smsSign 签名
* @return 请求成功
*/
SmsSignVO addSmsSign(SmsSignVO smsSign);
/***
* @description 删除签名
* @param checkedIds 签名ids
* @return 请求成功
*/
Boolean deleteSmsSign(String[] checkedIds);
/***
* @description 修改签名
* @param smsSign 签名
* @return 请求成功
*/
SmsSignVO modifySmsSign(SmsSignVO smsSign);
/***
* @description 查询签名审核状态
* @param smsSign 签名
* @return 请求成功
*/
SmsSignVO querySmsSign(SmsSignVO smsSign);
}
@@ -0,0 +1,40 @@
package com.itheima.sfbx.sms.adapter;
import com.itheima.sfbx.framework.commons.dto.sms.SmsTemplateVO;
/**
* @ClassName SmsTemplateVOAdapter.java
* @Description 模板适配器接口
*/
public interface SmsTemplateAdapter {
/***
* @description 申请模板
* @param smsTemplateVO 模板信息
* @return
*/
SmsTemplateVO addSmsTemplate(SmsTemplateVO smsTemplateVO);
/***
* @description 删除模板
* @param checkedIds 模板信息
* @return
*/
Boolean deleteSmsTemplate(String[] checkedIds);
/***
* @description 修改模板
* @param smsTemplateVO 模板信息
* @return
*/
SmsTemplateVO modifySmsTemplate(SmsTemplateVO smsTemplateVO);
/***
* @description 查询模板审核状态
* @param smsTemplateVO 模板信息
* @return
*/
SmsTemplateVO querySmsTemplate(SmsTemplateVO smsTemplateVO);
}
@@ -0,0 +1,142 @@
package com.itheima.sfbx.sms.adapter.impl;
import com.alibaba.fastjson.JSONArray;
import com.itheima.sfbx.framework.commons.constant.sms.SmsConstant;
import com.itheima.sfbx.framework.commons.dto.basic.OtherConfigVO;
import com.itheima.sfbx.framework.commons.dto.sms.SmsChannelVO;
import com.itheima.sfbx.framework.commons.dto.sms.SmsSignVO;
import com.itheima.sfbx.framework.commons.dto.sms.SmsTemplateVO;
import com.itheima.sfbx.framework.commons.utils.EmptyUtil;
import com.itheima.sfbx.framework.commons.utils.RegisterBeanHandler;
import com.itheima.sfbx.sms.adapter.SmsSendAdapter;
import com.itheima.sfbx.sms.balancer.SendLoadBalancer;
import com.itheima.sfbx.sms.handler.SmsSendHandler;
import com.itheima.sfbx.sms.pojo.SmsBlacklist;
import com.itheima.sfbx.sms.pojo.SmsSendRecord;
import com.itheima.sfbx.sms.service.ISmsBlacklistService;
import com.itheima.sfbx.sms.service.ISmsChannelService;
import com.itheima.sfbx.sms.service.ISmsSignService;
import com.itheima.sfbx.sms.service.ISmsTemplateService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.*;
import java.util.stream.Collectors;
/**
* @ClassName SmsSendAdapterImpl.java
* @Description 短信适配器实现
*/
@Slf4j
@Component
public class SmsSendAdapterImpl implements SmsSendAdapter {
@Autowired
ISmsBlacklistService smsBlacklistService;
@Autowired
ISmsTemplateService smsTemplateService;
@Autowired
ISmsChannelService smsChannelService;
@Autowired
ISmsSignService smsSignService;
@Autowired
RegisterBeanHandler registerBeanHandler;
private static Map<String,String> sendHandlers =new HashMap<>();
private static Map<String,String> loadBalancers =new HashMap<>();
static {
sendHandlers.put(SmsConstant.ALIYUN_SMS,"aliyunSmsSendHandler");
sendHandlers.put(SmsConstant.TENCENT_SMS,"tencentSmsSendHandler");
sendHandlers.put(SmsConstant.BAIDU_SMS,"baiduSmsSendHandler");
loadBalancers.put(SmsConstant.HASH,"hashSend");
loadBalancers.put(SmsConstant.RANDOM,"randomSend");
loadBalancers.put(SmsConstant.ROUND_ROBIN,"roundRobinSend");
loadBalancers.put(SmsConstant.WEIGHT_RANDOM,"weightRandomSend");
loadBalancers.put(SmsConstant.WEIGHT_ROUND_ROBIN,"weightRoundRobinSend");
}
@Override
public Boolean SendSms(
String templateNo,
String sginNo,
String loadBalancerType,
Set<String> mobiles,
LinkedHashMap<String, String> templateParam) {
//过滤黑名单中电话号码
List<SmsBlacklist> smsBlacklists = smsBlacklistService.list();
if (!EmptyUtil.isNullOrEmpty(smsBlacklists)){
Set<String> smsBlackMobiles= smsBlacklists.stream()
.map(SmsBlacklist::getMobile)
.collect(Collectors.toSet());
mobiles.removeAll(smsBlackMobiles);
}
Boolean flag = false;
//获得审核通过模板模板
List<SmsTemplateVO> smsTemplateVOs = smsTemplateService.findSmsTemplateByTemplateNo(templateNo);
if (EmptyUtil.isNullOrEmpty(smsTemplateVOs)){
log.warn("模板templateNo{},不能使用",templateNo);
return flag;
}
//负载均衡器选择对应通道
String loadBalancersName = loadBalancers.get(loadBalancerType);
SendLoadBalancer sendLoadBalancer = registerBeanHandler.getBean(loadBalancersName, SendLoadBalancer.class);
String channelLabel = sendLoadBalancer.chooseChannel(smsTemplateVOs,mobiles);;
if (EmptyUtil.isNullOrEmpty(channelLabel)){
log.error("模板templateNo:{},负载均衡器未找到对应通道",templateNo);
return flag;
}
//查询渠道
SmsChannelVO smsChannelVO= smsChannelService.findChannelByChannelLabel(channelLabel);
//选择模板
SmsTemplateVO smsTemplateVO = smsTemplateVOs.stream()
.filter(n->n.getChannelLabel().equals(smsChannelVO.getChannelLabel()))
.findFirst().get();
//查询签名
SmsSignVO smsSignVO = smsSignService.findSmsSignBySignNoAndChannelLabel(sginNo, channelLabel);
if (EmptyUtil.isNullOrEmpty(smsSignVO)){
log.warn("渠道smsChannel{},签名:{},不能使用",channelLabel,sginNo);
return flag;
}
//应用:应用模板变量转换服务模板参数
List <OtherConfigVO> otherConfigVos = JSONArray.parseArray(smsTemplateVO.getOtherConfig(), OtherConfigVO.class);
LinkedHashMap<String,String> otherConfigVoMap = new LinkedHashMap<>();
for (OtherConfigVO otherConfigVo : otherConfigVos) {
otherConfigVoMap.put(otherConfigVo.getConfigKey(),otherConfigVo.getConfigValue());
}
LinkedHashMap<String,String> templateParamHandler = new LinkedHashMap<>();
for (Map.Entry<String, String> entry : templateParam.entrySet()) {
String value = otherConfigVoMap.get(entry.getKey());
if(!EmptyUtil.isNullOrEmpty(value)){
templateParamHandler.put(value,entry.getValue());
}
}
//发送短信
String stringSendHandler = sendHandlers.get(channelLabel);
SmsSendHandler smsSendHandler =registerBeanHandler.getBean(stringSendHandler,SmsSendHandler.class);
return smsSendHandler.SendSms(smsTemplateVO,smsChannelVO,smsSignVO,mobiles,templateParamHandler);
}
@Override
public Boolean querySendSms(SmsSendRecord smsSendRecord) {
String channelLabel = smsSendRecord.getChannelLabel();
String stringSendHandler = sendHandlers.get(channelLabel);
SmsSendHandler smsSendHandler =registerBeanHandler.getBean(stringSendHandler,SmsSendHandler.class);
return smsSendHandler.querySendSms(smsSendRecord);
}
@Override
public Boolean retrySendSms(SmsSendRecord smsSendRecord) {
String channelLabel = smsSendRecord.getChannelLabel();
String stringSendHandler = sendHandlers.get(channelLabel);
SmsSendHandler smsSendHandler =registerBeanHandler.getBean(stringSendHandler,SmsSendHandler.class);
return smsSendHandler.retrySendSms(smsSendRecord);
}
}
@@ -0,0 +1,76 @@
package com.itheima.sfbx.sms.adapter.impl;
import com.itheima.sfbx.framework.commons.constant.sms.SmsConstant;
import com.itheima.sfbx.framework.commons.dto.sms.SmsSignVO;
import com.itheima.sfbx.framework.commons.utils.BeanConv;
import com.itheima.sfbx.framework.commons.utils.RegisterBeanHandler;
import com.itheima.sfbx.sms.adapter.SmsSignAdapter;
import com.itheima.sfbx.sms.handler.SmsSignHandler;
import com.itheima.sfbx.sms.service.ISmsSignService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.HashMap;
import java.util.Map;
/**
* @ClassName SmsSignAdapterImpl.java
* @Description 签名适配器实现
*/
@Service("smsSignAdapter")
public class SmsSignAdapterImpl implements SmsSignAdapter {
@Autowired
ISmsSignService smsSignService;
@Autowired
RegisterBeanHandler registerBeanHandler;
//处理类map容器定义
private static Map<String,String> SmsSignHandlers =new HashMap<>();
//把SmsSignHandler所有的实现类都维护起来,项目启动时加载
static {
SmsSignHandlers.put(SmsConstant.ALIYUN_SMS,"aliyunSmsSignHandler");
SmsSignHandlers.put(SmsConstant.TENCENT_SMS,"tencentSmsSignHandler");
SmsSignHandlers.put(SmsConstant.BAIDU_SMS,"baiduSmsSignHandler");
}
@Override
public SmsSignVO addSmsSign(SmsSignVO smsSignVO) {
String channelLabel = smsSignVO.getChannelLabel();
String stringSmsSignHandler = SmsSignHandlers.get(channelLabel);
SmsSignHandler smsSignHandler =registerBeanHandler.getBean(stringSmsSignHandler,SmsSignHandler.class);
return BeanConv.toBean(smsSignHandler.addSmsSign(smsSignVO),SmsSignVO.class);
}
@Override
@Transactional
public Boolean deleteSmsSign(String[] checkedIds) {
for (String checkedId : checkedIds) {
SmsSignVO smsSignVO = BeanConv.toBean(smsSignService.getById(checkedId), SmsSignVO.class);
String channelLabel = smsSignVO.getChannelLabel();
String stringSmsSignHandler = SmsSignHandlers.get(channelLabel);
SmsSignHandler smsSignHandler =registerBeanHandler.getBean(stringSmsSignHandler,SmsSignHandler.class);
smsSignHandler.deleteSmsSign(smsSignVO);
}
return true;
}
@Override
public SmsSignVO modifySmsSign(SmsSignVO smsSignVO) {
String channelLabel = smsSignVO.getChannelLabel();
String stringSmsSignHandler = SmsSignHandlers.get(channelLabel);
SmsSignHandler smsSignHandler =registerBeanHandler.getBean(stringSmsSignHandler,SmsSignHandler.class);
return BeanConv.toBean(smsSignHandler.modifySmsSign(smsSignVO),SmsSignVO.class);
}
@Override
public SmsSignVO querySmsSign(SmsSignVO smsSignVO) {
String channelLabel = smsSignVO.getChannelLabel();
String stringSmsSignHandler = SmsSignHandlers.get(channelLabel);
SmsSignHandler smsSignHandler =registerBeanHandler.getBean(stringSmsSignHandler,SmsSignHandler.class);
return BeanConv.toBean(smsSignHandler.querySmsSign(smsSignVO),SmsSignVO.class);
}
}
@@ -0,0 +1,76 @@
package com.itheima.sfbx.sms.adapter.impl;
import com.itheima.sfbx.framework.commons.constant.sms.SmsConstant;
import com.itheima.sfbx.framework.commons.dto.sms.SmsTemplateVO;
import com.itheima.sfbx.framework.commons.utils.BeanConv;
import com.itheima.sfbx.framework.commons.utils.RegisterBeanHandler;
import com.itheima.sfbx.sms.adapter.SmsTemplateAdapter;
import com.itheima.sfbx.sms.handler.SmsTemplateHandler;
import com.itheima.sfbx.sms.service.ISmsTemplateService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
/**
* @ClassName SmsTemplateAdapterImpl.java
* @Description 模板适配器实现
*/
@Service("smsTemplateAdapter")
public class SmsTemplateAdapterImpl implements SmsTemplateAdapter {
@Autowired
RegisterBeanHandler registerBeanHandler;
@Autowired
ISmsTemplateService smsTemplateService;
private static Map<String,String> smsTemplateHandlers =new HashMap<>();
static {
smsTemplateHandlers.put(SmsConstant.ALIYUN_SMS,"aliyunTemplateHandler");
smsTemplateHandlers.put(SmsConstant.TENCENT_SMS,"tencentTemplateHandler");
smsTemplateHandlers.put(SmsConstant.BAIDU_SMS,"baiduTemplateHandler");
}
@Override
public SmsTemplateVO addSmsTemplate(SmsTemplateVO smsTemplateVO) {
String channelLabel = smsTemplateVO.getChannelLabel();
String stringSmsTemplateHandler = smsTemplateHandlers.get(channelLabel);
SmsTemplateHandler smsTemplateHandler =registerBeanHandler
.getBean(stringSmsTemplateHandler,SmsTemplateHandler.class);
return BeanConv.toBean(smsTemplateHandler.addSmsTemplate(smsTemplateVO),SmsTemplateVO.class);
}
@Override
public Boolean deleteSmsTemplate(String[] checkedIds) {
for (String checkedId : checkedIds) {
SmsTemplateVO smsTemplateVO = BeanConv.toBean(smsTemplateService.getById(checkedId), SmsTemplateVO.class);
String channelLabel = smsTemplateVO.getChannelLabel();
String stringSmsTemplateHandler = smsTemplateHandlers.get(channelLabel);
SmsTemplateHandler smsTemplateHandler = registerBeanHandler
.getBean(stringSmsTemplateHandler, SmsTemplateHandler.class);
smsTemplateHandler.deleteSmsTemplate(smsTemplateVO);
}
return true;
}
@Override
public SmsTemplateVO modifySmsTemplate(SmsTemplateVO smsTemplateVO) {
String channelLabel = smsTemplateVO.getChannelLabel();
String stringSmsTemplateHandler = smsTemplateHandlers.get(channelLabel);
SmsTemplateHandler smsTemplateHandler =registerBeanHandler
.getBean(stringSmsTemplateHandler,SmsTemplateHandler.class);
return BeanConv.toBean(smsTemplateHandler.modifySmsTemplate(smsTemplateVO),SmsTemplateVO.class);
}
@Override
public SmsTemplateVO querySmsTemplate(SmsTemplateVO smsTemplateVO) {
String channelLabel = smsTemplateVO.getChannelLabel();
String stringSmsTemplateHandler = smsTemplateHandlers.get(channelLabel);
SmsTemplateHandler smsTemplateHandler =registerBeanHandler
.getBean(stringSmsTemplateHandler,SmsTemplateHandler.class);
return BeanConv.toBean(smsTemplateHandler.querySmsTemplate(smsTemplateVO),SmsTemplateVO.class);
}
}
@@ -0,0 +1,47 @@
package com.itheima.sfbx.sms.balancer;
import com.itheima.sfbx.framework.commons.dto.sms.SmsChannelVO;
import com.itheima.sfbx.framework.commons.dto.sms.SmsTemplateVO;
import com.itheima.sfbx.framework.commons.utils.EmptyUtil;
import com.itheima.sfbx.sms.service.ISmsChannelService;
import com.itheima.sfbx.sms.service.ISmsTemplateService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
/**
* @ClassName abSendLoadBalancer.java
* @Description TODO
*/
@Component
public class BaseSendLoadBalancer implements SendLoadBalancer {
@Autowired
ISmsTemplateService smsTemplateService;
@Autowired
ISmsChannelService smsChannelService;
@Override
public String chooseChannel(List<SmsTemplateVO> SmsTemplates, Set<String> mobile) {
return null;
}
@Override
public Map<String, String> getChannelList(List<SmsTemplateVO> SmsTemplates) {
//处理模板
Set<String> channelLabelList = SmsTemplates.stream()
.map(SmsTemplateVO::getChannelLabel).collect(Collectors.toSet());
//查询模板对应的渠道
List<SmsChannelVO> smsChannels =smsChannelService.findChannelInChannelLabel(channelLabelList);
if (!EmptyUtil.isNullOrEmpty(smsChannels)){
return smsChannels.stream()
.collect(Collectors.toMap(SmsChannelVO::getChannelLabel, SmsChannelVO::getLevel));
}
return null;
}
}
@@ -0,0 +1,29 @@
package com.itheima.sfbx.sms.balancer;
import com.itheima.sfbx.framework.commons.dto.sms.SmsTemplateVO;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @ClassName ChannelLoadBalancing.java
* @Description 短信发送负载均衡算法
*/
public interface SendLoadBalancer {
/***
* @description 根据模板、电话负载均衡发送
* @param SmsTemplates 模板列表
* @param mobile 电话号码
* @return 通道类型
*/
String chooseChannel(List<SmsTemplateVO> SmsTemplates, Set<String> mobile);
/***
* @description 查询拥有当前模板,活跃状态的通道
* @param SmsTemplates 模板列表
* @return 通道类型
*/
Map<String, String> getChannelList(List<SmsTemplateVO> SmsTemplates);
}
@@ -0,0 +1,35 @@
package com.itheima.sfbx.sms.balancer.impl;
import com.itheima.sfbx.framework.commons.dto.sms.SmsTemplateVO;
import com.itheima.sfbx.sms.balancer.BaseSendLoadBalancer;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @ClassName HashSend.java
* @Description mobile哈希(Hash)法
*/
@Component
public class HashSend extends BaseSendLoadBalancer {
@Override
public String chooseChannel(List<SmsTemplateVO> SmsTemplates, Set<String> mobile) {
//获得当前模板对应的渠道
Map<String, String> channelMap = super.getChannelList(SmsTemplates);
//取得channel地址List
Set<String> keySet = channelMap.keySet();
ArrayList<String> keyList = new ArrayList<String>();
keyList.addAll(keySet);
// 使用mobile取余
int hashCode = mobile.hashCode();
int serverListSize = keyList.size();
int serverPos = hashCode % serverListSize;
return keyList.get(serverPos);
}
}
@@ -0,0 +1,31 @@
package com.itheima.sfbx.sms.balancer.impl;
import com.itheima.sfbx.framework.commons.dto.sms.SmsTemplateVO;
import com.itheima.sfbx.sms.balancer.BaseSendLoadBalancer;
import org.springframework.stereotype.Component;
import java.util.*;
/**
* @ClassName Random.java
* @Description 随机(Random)法
*/
@Component
public class RandomSend extends BaseSendLoadBalancer {
@Override
public String chooseChannel(List<SmsTemplateVO> SmsTemplates, Set<String> mobile) {
//获得当前模板对应的渠道
Map<String, String> channelMap = super.getChannelList(SmsTemplates);
// 取得channel地址List
Set<String> keySet = channelMap.keySet();
ArrayList<String> keyList = new ArrayList<String>();
keyList.addAll(keySet);
Random random = new Random();
int randomPos = random.nextInt(keyList.size());
return keyList.get(randomPos);
}
}
@@ -0,0 +1,41 @@
package com.itheima.sfbx.sms.balancer.impl;
import com.itheima.sfbx.framework.commons.dto.sms.SmsTemplateVO;
import com.itheima.sfbx.sms.balancer.BaseSendLoadBalancer;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @ClassName RoundRobin.java
* @Description 轮询(Round Robin)法
*/
@Component
public class RoundRobinSend extends BaseSendLoadBalancer {
private static Integer pos = 0;
@Override
public String chooseChannel(List<SmsTemplateVO> SmsTemplates, Set<String> mobile) {
//获得当前模板对应的渠道
Map<String, String> channelMap = super.getChannelList(SmsTemplates);
// 取得通道地址List
Set<String> keySet = channelMap.keySet();
ArrayList<String> keyList = new ArrayList<String>();
keyList.addAll(keySet);
String channelName = null;
synchronized (pos) {
if (pos >= keySet.size())
pos = 0;
channelName = keyList.get(pos);
pos ++;
}
return channelName;
}
}
@@ -0,0 +1,38 @@
package com.itheima.sfbx.sms.balancer.impl;
import com.itheima.sfbx.framework.commons.dto.sms.SmsTemplateVO;
import com.itheima.sfbx.sms.balancer.BaseSendLoadBalancer;
import org.springframework.stereotype.Component;
import java.util.*;
/**
* @ClassName WeightRandomSend.java
* @Description 加权随机算法
*/
@Component
public class WeightRandomSend extends BaseSendLoadBalancer {
@Override
public String chooseChannel(List<SmsTemplateVO> SmsTemplates, Set<String> mobile) {
//获得当前模板对应的渠道
Map<String, String> channelMap = super.getChannelList(SmsTemplates);
// 取得channel地址List
Set<String> keySet = channelMap.keySet();
Iterator<String> iterator = keySet.iterator();
List<String> serverList = new ArrayList<String>();
while (iterator.hasNext()) {
String channel = iterator.next();
int weight = Integer.valueOf(channelMap.get(channel));
for (int i = 0; i < weight; i++)
serverList.add(channel);
}
Random random = new Random();
int randomPos = random.nextInt(serverList.size());
return serverList.get(randomPos);
}
}
@@ -0,0 +1,46 @@
package com.itheima.sfbx.sms.balancer.impl;
import com.itheima.sfbx.framework.commons.dto.sms.SmsTemplateVO;
import com.itheima.sfbx.sms.balancer.BaseSendLoadBalancer;
import org.springframework.stereotype.Component;
import java.util.*;
/**
* @ClassName WeightRoundRobinSend.java
* @Description 加权轮询(Weight Round Robin)法
* 与轮询法类似,只是在获取通道之前增加了一段权重计算的代码,根据权重的大小,
* 将通道重复地增加到服务器地址列表中,权重越大,该服务器每轮所获得的请求数量越多。
*/
@Component
public class WeightRoundRobinSend extends BaseSendLoadBalancer {
private static Integer pos;
@Override
public String chooseChannel(List<SmsTemplateVO> SmsTemplates, Set<String> mobile) {
//获得当前模板对应的渠道
Map<String, String> channelMap = super.getChannelList(SmsTemplates);
// 取得channel地址List
Set<String> keySet = channelMap.keySet();
Iterator<String> iterator = keySet.iterator();
List<String> channelListHandler = new ArrayList<String>();
while (iterator.hasNext()) {
String server = iterator.next();
Integer weight = Integer.valueOf(channelMap.get(server));
for (int i = 0; i < weight; i++)
channelListHandler.add(server);
}
String channelName = null;
synchronized (pos) {
if (pos > keySet.size())
pos = 0;
channelName = channelListHandler.get(pos);
pos++;
}
return channelName;
}
}
@@ -0,0 +1,12 @@
package com.itheima.sfbx.sms.binding;
import com.itheima.sfbx.framework.rabbitmq.source.SmsSource;
import org.springframework.cloud.stream.annotation.EnableBinding;
/**
* @ClassName Binding.java
* @Description 绑定声明
*/
@EnableBinding({SmsSource.class})
public class SourceBinding {
}
@@ -0,0 +1,74 @@
package com.itheima.sfbx.sms.feign;
import com.itheima.sfbx.framework.commons.dto.sms.SendMessageVO;
import com.itheima.sfbx.framework.commons.dto.sms.SmsSendRecordVO;
import com.itheima.sfbx.sms.service.ISmsSendService;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @ClassName SmsSendController.java
* @Description 短信发送controller
*/
@RestController
@RequestMapping("sms-send-feign")
public class SmsSendFeignController {
@Autowired
ISmsSendService smsSendService;
/***
* @description 发送短信:削峰方式
* @param sendMessageVO 发送对象
*/
@PostMapping("send-sms-mq")
@ApiOperation(value = "发送短信:削峰方式",notes = "发送短信:削峰方式")
@ApiImplicitParam(name = "sendMessageVO",value = "短信发送对象",required = true,dataType = "SendMessageVO")
Boolean sendSmsForMq(@RequestBody SendMessageVO sendMessageVO){
Boolean flag = smsSendService.sendSmsForMq(sendMessageVO);
return flag;
}
/***
* @description 发送短信:非削峰方式
* @param sendMessageVO 发送对象
*/
@PostMapping("send-sms")
@ApiOperation(value = "发送短信:非削峰方式",notes = "发送短信:非削峰方式")
@ApiImplicitParam(name = "sendMessageVO",value = "短信发送对象",required = true,dataType = "SendMessageVO")
Boolean sendSms(@RequestBody SendMessageVO sendMessageVO){
Boolean flag = smsSendService.sendSms(sendMessageVO);
return flag;
}
/***
* @description 查询短信发送情况
* @param smsSendRecordVO 发送记录
* @return
*/
@PostMapping("query-send-sms")
@ApiOperation(value = "查询短信发送情况",notes = "查询短信发送情况")
@ApiImplicitParam(name = "smsSendRecordVO",value = "短信发送记录",required = true,dataType = "SmsSendRecordVO")
Boolean querySendSms(@RequestBody SmsSendRecordVO smsSendRecordVO){
Boolean flag = smsSendService.querySendSms(smsSendRecordVO);
return flag;
}
/***
* @description 重试发送
* @param smsSendRecordVO
* @return
*/
@PostMapping("retry-send-sms")
@ApiOperation(value = "重试发送",notes = "重试发送")
@ApiImplicitParam(name = "smsSendRecordVO",value = "短信发送记录",required = true,dataType = "SmsSendRecordVO")
Boolean retrySendSms(@RequestBody SmsSendRecordVO smsSendRecordVO){
Boolean flag = smsSendService.retrySendSms(smsSendRecordVO);
return flag;
}
}
@@ -0,0 +1,35 @@
package com.itheima.sfbx.sms.feign;
import com.itheima.sfbx.framework.commons.dto.sms.SmsSendRecordVO;
import com.itheima.sfbx.sms.service.ISmsSendRecordService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* @ClassName SmsSendRecordController.java
* @Description 发送记录Controller
*/
@RestController
@RequestMapping("sms-send-record-feign")
@Slf4j
@Api(tags = "发送记录fegin-controller")
public class SmsSendRecordFeignController {
@Autowired
ISmsSendRecordService smsSendRecordService;
@PostMapping("call-back-sms-send-records")
@ApiOperation(value = "查询需要查询的短信发送",notes = "查询需要查询的短信发送")
List<SmsSendRecordVO> callBackSmsSendRecords(){
List<SmsSendRecordVO> smsSendRecords = smsSendRecordService.callBackSmsSendRecords();
return smsSendRecords;
}
}
@@ -0,0 +1,45 @@
package com.itheima.sfbx.sms.handler;
import com.itheima.sfbx.framework.commons.dto.sms.SmsChannelVO;
import com.itheima.sfbx.framework.commons.dto.sms.SmsSignVO;
import com.itheima.sfbx.framework.commons.dto.sms.SmsTemplateVO;
import com.itheima.sfbx.sms.pojo.SmsSendRecord;
import java.util.LinkedHashMap;
import java.util.Set;
/**
* @ClassName SmsSendHandler.java
* @Description 邮件发送处理器
*/
public interface SmsSendHandler {
/***
* @description 发送短信接口
* @param smsTemplateVO 模板
* @param smsChannelVO 渠道
* @param smsSignVO 签名
* @param mobiles 手机号
* @param templateParam 模板动态参数
*/
Boolean SendSms(
SmsTemplateVO smsTemplateVO,
SmsChannelVO smsChannelVO,
SmsSignVO smsSignVO,
Set<String> mobiles,
LinkedHashMap<String, String> templateParam);
/***
* @description 查询短信接受情况
* @param smsSendRecord 发送记录
* @return
*/
Boolean querySendSms(SmsSendRecord smsSendRecord);
/***
* @description 重试发送
* @param smsSendRecord
* @return
*/
Boolean retrySendSms(SmsSendRecord smsSendRecord);
}
@@ -0,0 +1,41 @@
package com.itheima.sfbx.sms.handler;
import com.itheima.sfbx.sms.pojo.SmsSign;
import com.itheima.sfbx.framework.commons.dto.sms.SmsSignVO;
/**
* @ClassName SmsSignHandler.java
* @Description 签名处理器接口
*/
public interface SmsSignHandler {
/***
* @description 申请签名
* @param smsSignVO 签名
* @return 请求成功
*/
SmsSign addSmsSign(SmsSignVO smsSignVO);
/***
* @description 删除签名
* @param smsSignVO 签名
* @return 请求成功
*/
Boolean deleteSmsSign(SmsSignVO smsSignVO);
/***
* @description 修改签名
* @param smsSignVO 签名
* @return 请求成功
*/
SmsSign modifySmsSign(SmsSignVO smsSignVO);
/***
* @description 查询签名审核状态
* @param smsSignVO 签名
* @return 请求成功
*/
SmsSign querySmsSign(SmsSignVO smsSignVO);
}
@@ -0,0 +1,41 @@
package com.itheima.sfbx.sms.handler;
import com.itheima.sfbx.framework.commons.dto.sms.SmsTemplateVO;
import com.itheima.sfbx.sms.pojo.SmsTemplate;
/**
* @ClassName SmsTemplateHandler.java
* @Description 模板处理器接口
*/
public interface SmsTemplateHandler {
/***
* @description 申请模板
* @param smsTemplateVO 模板信息
* @return
*/
SmsTemplate addSmsTemplate(SmsTemplateVO smsTemplateVO);
/***
* @description 删除模板
* @param smsTemplateVO 模板信息
* @return
*/
Boolean deleteSmsTemplate(SmsTemplateVO smsTemplateVO);
/***
* @description 修改模板
* @param smsTemplateVO 模板信息
* @return
*/
SmsTemplate modifySmsTemplate(SmsTemplateVO smsTemplateVO);
/***
* @description 查询模板审核状态
* @param smsTemplateVO 模板信息
* @return
*/
SmsTemplate querySmsTemplate(SmsTemplateVO smsTemplateVO);
}
@@ -0,0 +1,202 @@
package com.itheima.sfbx.sms.handler.aliyun;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.dysmsapi20170525.Client;
import com.aliyun.dysmsapi20170525.models.*;
import com.itheima.sfbx.framework.commons.constant.sms.SmsConstant;
import com.itheima.sfbx.framework.commons.dto.sms.SmsChannelVO;
import com.itheima.sfbx.framework.commons.dto.sms.SmsSignVO;
import com.itheima.sfbx.framework.commons.dto.sms.SmsTemplateVO;
import com.itheima.sfbx.framework.commons.enums.sms.SmsSendEnum;
import com.itheima.sfbx.framework.commons.exception.ProjectException;
import com.itheima.sfbx.framework.commons.utils.BeanConv;
import com.itheima.sfbx.sms.handler.aliyun.config.AliyunSmsConfig;
import com.itheima.sfbx.sms.pojo.SmsSendRecord;
import com.itheima.sfbx.sms.service.ISmsChannelService;
import com.itheima.sfbx.sms.service.ISmsSendRecordService;
import com.itheima.sfbx.sms.service.ISmsSignService;
import com.itheima.sfbx.sms.service.ISmsTemplateService;
import com.itheima.sfbx.sms.handler.SmsSendHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* @ClassName SmsSendAdapter.java
* @Description 阿里云邮件发送处理器接口
*/
@Slf4j
@Service("aliyunSmsSendHandler")
public class AliyunSmsSendHandlerImpl implements SmsSendHandler {
@Autowired
AliyunSmsConfig aliyunSmsConfig;
@Autowired
ISmsSendRecordService smsSendRecordService;
@Autowired
ISmsTemplateService smsTemplateService;
@Autowired
ISmsChannelService smsChannelService;
@Autowired
ISmsSignService smsSignService;
@Override
public Boolean SendSms(SmsTemplateVO smsTemplate,
SmsChannelVO smsChannel,
SmsSignVO smsSign,
Set<String> mobiles,
LinkedHashMap<String, String> templateParam) throws ProjectException {
//超过发送上限
if (mobiles.size()>1000){
throw new ProjectException(SmsSendEnum.PEXCEED_THE_LIMIT);
}
SendBatchSmsRequest request = new SendBatchSmsRequest();
//接收短信的手机号码,JSON数组格式。
request.setPhoneNumberJson(JSONObject.toJSONString(mobiles));
//签名处理
String signCode = smsSign.getSignCode();
List<String> signNames = new ArrayList<>();
for (String mobile : mobiles) {
signNames.add(signCode);
}
request.setSignNameJson(JSONObject.toJSONString(signNames));
//模板处理
request.setTemplateCode(smsTemplate.getTemplateCode());
//模板参数
List<Map<String, String>> templateParams = new ArrayList<>();
for (String mobile : mobiles) {
templateParams.add(templateParam);
}
request.setTemplateParamJson(JSONObject.toJSONString(templateParams));
//发送短信
Client client =aliyunSmsConfig.queryClient();
SendBatchSmsResponse response = null;
try {
response = client.sendBatchSms(request);
} catch (Exception e) {
log.error("阿里云发送短信:{},失败",request.toString());
throw new ProjectException(SmsSendEnum.SEND_FAIL);
}
//三方结果
String code = response.getBody().getCode();
String acceptStatus = null;
String acceptMsg = null;
String sendStatus = null;
String sendMsg = null;
if ("OK".equals(code)){
//受理成功
acceptStatus = SmsConstant.STATUS_ACCEPT_0;
acceptMsg = "受理成功";
sendStatus = SmsConstant.STATUS_SEND_2;
sendMsg = "发送中";
}else {
//受理失败
acceptStatus=SmsConstant.STATUS_ACCEPT_1;
acceptMsg = response.getBody().getMessage();
sendStatus = SmsConstant.STATUS_SEND_1;
sendMsg = "发送失败";
}
//构建发送记录
String message = response.getBody().getMessage();
String bizId = response.getBody().getBizId();
String content = smsTemplate.getContent();
for (Map.Entry<String, String> entry : templateParam.entrySet()) {
content = content.replace(entry.getKey(), entry.getValue());
}
List<SmsSendRecord> sendRecords = new ArrayList<>();
for (String mobile : mobiles) {
SmsSendRecord smsSendRecord = SmsSendRecord.builder()
.sendContent(content)
.channelLabel(smsChannel.getChannelLabel())
.channelName(smsChannel.getChannelName())
.acceptStatus(acceptStatus)
.acceptMsg(acceptMsg)
.sendStatus(sendStatus)
.sendMsg(sendMsg)
.mobile(mobile)
.signCode(smsSign.getSignCode())
.signName(smsSign.getSignName())
.templateNo(smsTemplate.getTemplateNo())
.templateCode(smsTemplate.getTemplateCode())
.templateId(smsTemplate.getId())
.templateType(smsTemplate.getSmsType())
.serialNo(bizId)
.templateParams(JSONObject.toJSONString(templateParam))
.build();
sendRecords.add(smsSendRecord);
}
return smsSendRecordService.saveBatch(sendRecords);
}
@Override
public Boolean querySendSms(SmsSendRecord smsSendRecord) throws ProjectException {
QuerySendDetailsRequest request = new QuerySendDetailsRequest();
request.setBizId(smsSendRecord.getSerialNo());
request.setPhoneNumber(smsSendRecord.getMobile());
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
request.setSendDate(simpleDateFormat.format(smsSendRecord.getCreateTime()));
request.setPageSize(50L);
request.setCurrentPage(1L);
// 复制代码运行请自行打印 API 的返回值
Client client =aliyunSmsConfig.queryClient();
QuerySendDetailsResponse response = null;
try {
response = client.querySendDetails(request);
} catch (Exception e) {
log.error("阿里云查询短信发送状态:{},失败",request.toString());
throw new ProjectException(SmsSendEnum.QUERY_FAIL);
}
String code = response.getBody().getCode();
//处理结果
if ("OK".equals(code)){
QuerySendDetailsResponseBody.QuerySendDetailsResponseBodySmsSendDetailDTOsSmsSendDetailDTO result =
response.getBody().getSmsSendDetailDTOs().getSmsSendDetailDTO().stream()
.filter(n -> n.getPhoneNum().equals(smsSendRecord.getMobile())
&& n.getTemplateCode().equals(smsSendRecord.getTemplateCode()))
.findFirst().get();
if (result.getSendStatus()==3){
smsSendRecord.setSendStatus(SmsConstant.STATUS_SEND_0);
smsSendRecord.setSendMsg("发送成功");
return smsSendRecordService.updateById(smsSendRecord);
}else if (result.getSendStatus()==2){
smsSendRecord.setSendStatus(SmsConstant.STATUS_SEND_1);
smsSendRecord.setSendMsg("发送失败");
return smsSendRecordService.updateById(smsSendRecord);
}else {
log.info("短信:{},等待回执!",smsSendRecord.toString());
}
}
return true;
}
@Override
public Boolean retrySendSms(SmsSendRecord smsSendRecord) throws ProjectException {
//已发送,发送中的短信不处理
if (smsSendRecord.getSendStatus().equals(SmsConstant.STATUS_SEND_0)||
smsSendRecord.getSendStatus().equals(SmsConstant.STATUS_SEND_2)) {
throw new ProjectException(SmsSendEnum.SEND_SUCCEED);
}
SmsTemplateVO smsTemplate = BeanConv.toBean(smsTemplateService.getById(smsSendRecord.getTemplateId()),SmsTemplateVO.class);
SmsChannelVO smsChannel = smsChannelService.findChannelByChannelLabel(smsSendRecord.getChannelLabel());
SmsSignVO smsSign = smsSignService.findSmsSignBySignCodeAndChannelLabel(
smsSendRecord.getSignCode(),
smsSendRecord.getChannelLabel());
Set<String> mobiles = new HashSet<>();
mobiles.add(smsSendRecord.getMobile());
LinkedHashMap<String, String> templateParam = JSON.parseObject(smsSendRecord.getTemplateParams(), LinkedHashMap.class);
Boolean flag = SendSms(smsTemplate, smsChannel, smsSign, mobiles, templateParam);
if (flag){
flag = smsSendRecordService.removeById(smsSendRecord.getId());
}
return flag;
}
}
@@ -0,0 +1,240 @@
package com.itheima.sfbx.sms.handler.aliyun;
import com.aliyun.dysmsapi20170525.Client;
import com.aliyun.dysmsapi20170525.models.*;
import com.itheima.sfbx.framework.commons.constant.sms.SmsConstant;
import com.itheima.sfbx.framework.commons.dto.sms.SmsSignVO;
import com.itheima.sfbx.framework.commons.enums.sms.SmsSignEnum;
import com.itheima.sfbx.framework.commons.exception.ProjectException;
import com.itheima.sfbx.framework.commons.utils.BeanConv;
import com.itheima.sfbx.framework.commons.utils.EmptyUtil;
import com.itheima.sfbx.framework.commons.utils.ExceptionsUtil;
import com.itheima.sfbx.sms.handler.SmsSignHandler;
import com.itheima.sfbx.sms.handler.aliyun.config.AliyunSmsConfig;
import com.itheima.sfbx.sms.pojo.SmsSign;
import com.itheima.sfbx.sms.service.ISmsSignService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
/**
* @ClassName SmsSignAdapter.java
* @Description 阿里云签名处理器接口
*/
@Slf4j
@Service("aliyunSmsSignHandler")
public class AliyunSmsSignHandlerImpl implements SmsSignHandler {
@Autowired
ISmsSignService smsSignService;
@Autowired
AliyunSmsConfig aliyunSmsConfig;
@Override
public SmsSign addSmsSign(SmsSignVO smsSignVO){
//查询当前签名是否保存过
SmsSignVO smsSignHandler = smsSignService.findSmsSignBySignNameAndChannelLabel
(smsSignVO.getSignName(),smsSignVO.getChannelLabel());
//保存过则同步远程数据
if (!EmptyUtil.isNullOrEmpty(smsSignHandler)){
smsSignVO = BeanConv.toBean(smsSignHandler,SmsSignVO.class);
//查询当前签名在远程的是否存在
QuerySmsSignResponse querySmsSignResponse = query(smsSignVO);
String codeQuery = querySmsSignResponse.getBody().getCode();
if ("OK".equals(codeQuery)){
Integer SignStatus =querySmsSignResponse.getBody().getSignStatus();
//受理成功
smsSignVO.setAcceptStatus(SmsConstant.STATUS_ACCEPT_0);
smsSignVO.setAcceptMsg("受理成功");
smsSignVO.setSignCode(smsSignVO.getSignName());
//审核通过
if (SignStatus==1){
smsSignVO.setAuditStatus(SmsConstant.STATUS_AUDIT_0);
smsSignVO.setAuditMsg("审核通过");
//审核失败
}else if (SignStatus==2){
smsSignVO.setAuditStatus(SmsConstant.STATUS_AUDIT_1);
smsSignVO.setAuditMsg(querySmsSignResponse.getBody().getReason());
}else {
smsSignVO.setAuditStatus(SmsConstant.STATUS_AUDIT_2);
smsSignVO.setAuditMsg(querySmsSignResponse.getBody().getReason());
}
SmsSign smsSign = BeanConv.toBean(smsSignVO, SmsSign.class);
boolean flag = smsSignService.saveOrUpdate(smsSign);
if (flag){
return smsSign;
}
throw new ProjectException(SmsSignEnum.CREATE_FAIL);
}
}
//构建请求对象
AddSmsSignRequest addSmsSignRequest = new AddSmsSignRequest();
//签名名称
addSmsSignRequest.setSignName(smsSignVO.getSignName());
//签名来源
addSmsSignRequest.setSignSource(Integer.valueOf(smsSignVO.getSignType()));
//申请说明
addSmsSignRequest.setRemark(smsSignVO.getRemark());
//证明材料SignFileList
List<AddSmsSignRequest.AddSmsSignRequestSignFileList> signFileList = new ArrayList<>();
String[] proofTypes = smsSignVO.getProofType().split("@");
String[] proofImages = smsSignVO.getProofImage().split("@");
for (int i = 0 ; i<proofImages.length;i++) {
AddSmsSignRequest.AddSmsSignRequestSignFileList signFile = new AddSmsSignRequest.AddSmsSignRequestSignFileList();
signFile.setFileContents(proofImages[i]);
signFile.setFileSuffix(proofTypes[i]);
signFileList.add(signFile);
}
addSmsSignRequest.setSignFileList(signFileList);
//获得客户端
Client client =aliyunSmsConfig.queryClient();
//发起三方请求
AddSmsSignResponse response = null;
try {
response = client.addSmsSign(addSmsSignRequest);
} catch (Exception e) {
log.error("请求添加阿里云签名出错:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsSignEnum.CREATE_FAIL);
}
//同步结果并保存
String code = response.getBody().getCode();
String message = response.getBody().getMessage();
if ("OK".equals(code)){
//受理成功
smsSignVO.setAcceptStatus(SmsConstant.STATUS_ACCEPT_0);
smsSignVO.setAcceptMsg("受理成功");
smsSignVO.setSignCode(smsSignVO.getSignName());
//审核中
smsSignVO.setAuditStatus(SmsConstant.STATUS_AUDIT_2);
smsSignVO.setAuditMsg("审核中");
smsSignVO.setSignCode(smsSignVO.getSignName());
}else {
smsSignVO.setAcceptStatus(SmsConstant.STATUS_ACCEPT_1);
smsSignVO.setAcceptMsg(message);
}
SmsSign smsSign = BeanConv.toBean(smsSignVO, SmsSign.class);
boolean flag = smsSignService.save(smsSign);
if (flag){
return smsSign;
}
throw new ProjectException(SmsSignEnum.CREATE_FAIL);
}
@Override
public Boolean deleteSmsSign(SmsSignVO smsSignVO){
DeleteSmsSignRequest deleteSmsSignRequest = new DeleteSmsSignRequest();;
deleteSmsSignRequest.setSignName(smsSignVO.getSignName());
Client client =aliyunSmsConfig.queryClient();
DeleteSmsSignResponse response = null;
try {
response = client.deleteSmsSign(deleteSmsSignRequest);
} catch (Exception e) {
log.error("请求删除阿里云签名出错:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsSignEnum.DELETE_FAIL);
}
return smsSignService.removeById(smsSignVO.getId());
}
@Override
public SmsSign modifySmsSign(SmsSignVO smsSignVO){
ModifySmsSignRequest modifySmsSignRequest = new ModifySmsSignRequest();
//签名名称
modifySmsSignRequest.setSignName(smsSignVO.getSignName());
//签名来源。取值:
modifySmsSignRequest.setSignSource(Integer.valueOf(smsSignVO.getSignType()));
//申请说明
modifySmsSignRequest.setRemark(smsSignVO.getRemark());
//证明材料SignFileList
List<ModifySmsSignRequest.ModifySmsSignRequestSignFileList> signFileList = new ArrayList<>();
String[] proofTypes = smsSignVO.getProofType().split("@");
String[] proofImages = smsSignVO.getProofImage().split("@");
for (int i = 0 ; i<proofImages.length;i++) {
ModifySmsSignRequest.ModifySmsSignRequestSignFileList signFile = new ModifySmsSignRequest.ModifySmsSignRequestSignFileList();
signFile.setFileContents(proofImages[i]);
signFile.setFileSuffix(proofTypes[i]);
signFileList.add(signFile);
}
modifySmsSignRequest.setSignFileList(signFileList);
//同步结果并保存
Client client =aliyunSmsConfig.queryClient();
ModifySmsSignResponse response = null;
try {
response = client.modifySmsSign(modifySmsSignRequest);
} catch (Exception e) {
log.error("请求修改阿里云签名出错:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsSignEnum.UPDATE_FAIL);
}
//处理结果
String code = response.getBody().getCode();
String message = response.getBody().getMessage();
if ("OK".equals(code)){
//受理成功
smsSignVO.setAcceptStatus(SmsConstant.STATUS_ACCEPT_0);
smsSignVO.setAcceptMsg("受理成功");
//审核中
smsSignVO.setAuditStatus(SmsConstant.STATUS_ACCEPT_2);
smsSignVO.setAuditMsg("审核中");
smsSignVO.setSignCode(smsSignVO.getSignName());
}else {
//受理失败
smsSignVO.setAcceptStatus(SmsConstant.STATUS_ACCEPT_1);
smsSignVO.setAcceptMsg(message);
//重置审核状态
smsSignVO.setAuditStatus(null);
smsSignVO.setAuditMsg(null);
smsSignVO.setSignCode(null);
}
SmsSign smsSign = BeanConv.toBean(smsSignVO, SmsSign.class);
smsSignService.updateById(smsSign);
return smsSign;
}
private QuerySmsSignResponse query(SmsSignVO smsSignVO) {
QuerySmsSignRequest querySmsSignRequest = new QuerySmsSignRequest();
querySmsSignRequest.setSignName(smsSignVO.getSignName());
// 复制代码运行请自行打印 API 的返回值
Client client =aliyunSmsConfig.queryClient();
QuerySmsSignResponse response = null;
try {
response = client.querySmsSign(querySmsSignRequest);
} catch (Exception e) {
log.error("请求查询阿里云签名出错:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsSignEnum.SELECT_FAIL);
}
return response;
}
@Override
public SmsSign querySmsSign(SmsSignVO smsSignVO){
QuerySmsSignResponse response =query(smsSignVO);
//受理状态
String code = response.getBody().getCode();
String message = response.getBody().getMessage();
SmsSign smsSign = BeanConv.toBean(smsSignVO, SmsSign.class);
if ("OK".equals(code)){
Integer SignStatus =response.getBody().getSignStatus();
//审核通过
if (SignStatus==1){
smsSignVO.setAuditStatus(SmsConstant.STATUS_AUDIT_0);
smsSignVO.setAuditMsg("审核通过");
smsSignService.updateById(smsSign);
//审核失败
}else if (SignStatus==2){
smsSignVO.setAuditStatus(SmsConstant.STATUS_AUDIT_1);
smsSignVO.setAuditMsg(response.getBody().getReason());
smsSignService.updateById(smsSign);
}else {
log.info("阿里云签名:{},审核中", response.getBody().getSignName());
}
}else {
log.warn("受理查询阿里云签名出错:{}", message);
throw new ProjectException(SmsSignEnum.SELECT_FAIL);
}
return smsSign;
}
}
@@ -0,0 +1,231 @@
package com.itheima.sfbx.sms.handler.aliyun;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.dysmsapi20170525.Client;
import com.aliyun.dysmsapi20170525.models.*;
import com.itheima.sfbx.framework.commons.constant.basic.SuperConstant;
import com.itheima.sfbx.framework.commons.constant.sms.SmsConstant;
import com.itheima.sfbx.framework.commons.dto.sms.SmsTemplateVO;
import com.itheima.sfbx.framework.commons.enums.sms.SmsTemplateEnum;
import com.itheima.sfbx.framework.commons.exception.ProjectException;
import com.itheima.sfbx.framework.commons.utils.BeanConv;
import com.itheima.sfbx.framework.commons.utils.EmptyUtil;
import com.itheima.sfbx.framework.commons.utils.ExceptionsUtil;
import com.itheima.sfbx.sms.handler.SmsTemplateHandler;
import com.itheima.sfbx.sms.handler.aliyun.config.AliyunSmsConfig;
import com.itheima.sfbx.sms.pojo.SmsTemplate;
import com.itheima.sfbx.sms.service.ISmsTemplateService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @ClassName SmsTemplateAdapter.java
* @Description 阿里云模板处理器接口
*/
@Slf4j
@Service("aliyunTemplateHandler")
public class AliyunTemplateHandlerImpl implements SmsTemplateHandler {
@Autowired
AliyunSmsConfig aliyunSmsConfig;
@Autowired
ISmsTemplateService smsTemplateService;
@Override
public SmsTemplate addSmsTemplate(SmsTemplateVO smsTemplateVO) {
//查询是否添加过模板
SmsTemplateVO smsTemplateHandler = smsTemplateService.findSmsTemplateByTemplateNameAndChannelLabel(
smsTemplateVO.getTemplateName(),
smsTemplateVO.getChannelLabel());
//保存过则同步远程数据
if (!EmptyUtil.isNullOrEmpty(smsTemplateHandler)){
smsTemplateVO = BeanConv.toBean(smsTemplateHandler,SmsTemplateVO.class);
QuerySmsTemplateResponse response = query(smsTemplateVO);
//受理状态
String code = response.getBody().getCode();
String message = response.getBody().getMessage();
if ("OK".equals(code)){
Integer templateStatus =response.getBody().getTemplateStatus();
smsTemplateVO.setTemplateCode(response.getBody().getTemplateCode());
//审核通过
if (templateStatus == 1) {
smsTemplateVO.setAuditStatus(SmsConstant.STATUS_AUDIT_0);
smsTemplateVO.setAuditMsg("审核通过");
//审核失败
} else if (templateStatus == 2) {
smsTemplateVO.setAuditStatus(SmsConstant.STATUS_AUDIT_1);
smsTemplateVO.setAuditMsg(response.getBody().getReason());
} else {
log.info("阿里云模板:{},审核中", response.getBody().getTemplateCode());
smsTemplateVO.setAuditStatus(SmsConstant.STATUS_AUDIT_2);
smsTemplateVO.setAuditMsg(response.getBody().getReason());
}
SmsTemplate smsTemplate = BeanConv.toBean(smsTemplateVO, SmsTemplate.class);
boolean flag = smsTemplateService.saveOrUpdate(smsTemplate);
if (flag){
return smsTemplate;
}
throw new ProjectException(SmsTemplateEnum.CREATE_FAIL);
}
}
//构建请求对象
AddSmsTemplateRequest request = new AddSmsTemplateRequest();
//模板类型
request.setTemplateType(Integer.valueOf(smsTemplateVO.getSmsType()));
//模板名称
request.setTemplateName(smsTemplateVO.getTemplateName());
//模板内容
request.setTemplateContent(smsTemplateVO.getContent());
//模板说明
request.setRemark(smsTemplateVO.getRemark());
//获得客户端
Client client =aliyunSmsConfig.queryClient();
//发起三方请求
AddSmsTemplateResponse response = null;
try {
response = client.addSmsTemplate(request);
} catch (Exception e) {
log.error("请求添加阿里云模板出错:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsTemplateEnum.CREATE_FAIL);
}
//同步结果并保存
String code = response.getBody().getCode();
String message = response.getBody().getMessage();
if ("OK".equals(code)){
//受理成功
smsTemplateVO.setAcceptStatus(SmsConstant.STATUS_ACCEPT_0);
smsTemplateVO.setAcceptMsg("受理成功");
//审核中
smsTemplateVO.setAuditStatus(SmsConstant.STATUS_AUDIT_2);
smsTemplateVO.setAuditMsg("审核中");
//短信模板CODE。
//您可以使用模板CODE通过
//QuerySmsTemplate接口或短信服务控制台查看模板申请状态和结果。
smsTemplateVO.setTemplateCode(response.getBody().getTemplateCode());
}else {
//受理失败
smsTemplateVO.setAcceptStatus(SmsConstant.STATUS_AUDIT_1);
smsTemplateVO.setAcceptMsg(message);
}
SmsTemplate smsTemplate = BeanConv.toBean(smsTemplateVO, SmsTemplate.class);
smsTemplate.setOtherConfig(JSONObject.toJSONString(smsTemplateVO.getOtherConfigs()));
boolean flag = smsTemplateService.save(smsTemplate);
if (flag){
return smsTemplate;
}
throw new ProjectException(SmsTemplateEnum.CREATE_FAIL);
}
@Override
public Boolean deleteSmsTemplate(SmsTemplateVO smsTemplateVO) {
DeleteSmsTemplateRequest request = new DeleteSmsTemplateRequest();
request.setTemplateCode(smsTemplateVO.getTemplateCode());
Client client =aliyunSmsConfig.queryClient();
DeleteSmsTemplateResponse response = null;
try {
response = client.deleteSmsTemplate(request);
} catch (Exception e) {
log.error("请求删除阿里云模板出错:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsTemplateEnum.DELETE_FAIL);
}
//受理状态
String code = response.getBody().getCode();
String message = response.getBody().getMessage();
return smsTemplateService.removeById(smsTemplateVO.getId());
}
@Override
public SmsTemplate modifySmsTemplate(SmsTemplateVO smsTemplateVO) {
//构建请求对象
ModifySmsTemplateRequest request = new ModifySmsTemplateRequest();
//模板类型
request.setTemplateType(Integer.valueOf(smsTemplateVO.getSmsType()));
//模板名称
request.setTemplateName(smsTemplateVO.getTemplateName());
//模板内容
request.setTemplateContent(smsTemplateVO.getContent());
//模板说明
request.setRemark(smsTemplateVO.getRemark());
//获得客户端
Client client =aliyunSmsConfig.queryClient();
ModifySmsTemplateResponse response = null;
try {
response = client.modifySmsTemplate(request);
} catch (Exception e) {
log.error("请求修改阿里云模板出错:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsTemplateEnum.UPDATE_FAIL);
}
//同步结果并保存
String code = response.getBody().getCode();
String message = response.getBody().getMessage();
if ("OK".equals(code)){
//受理成功
smsTemplateVO.setAcceptStatus(SmsConstant.STATUS_ACCEPT_0);
smsTemplateVO.setAcceptMsg("受理成功");
//审核中
smsTemplateVO.setAuditStatus(SmsConstant.STATUS_AUDIT_2);
smsTemplateVO.setAuditMsg("审核中");
//短信模板CODE。
//您可以使用模板CODE通过
//QuerySmsTemplate接口或短信服务控制台查看模板申请状态和结果。
smsTemplateVO.setTemplateCode(response.getBody().getTemplateCode());
}else {
//受理失败
smsTemplateVO.setAcceptStatus(SmsConstant.STATUS_AUDIT_1);
smsTemplateVO.setAcceptMsg( message);
smsTemplateVO.setAuditStatus(null);
smsTemplateVO.setAuditMsg(null);
smsTemplateVO.setTemplateCode(null);
}
//本地持久化
SmsTemplate smsTemplate = BeanConv.toBean(smsTemplateVO, SmsTemplate.class);
smsTemplate.setOtherConfig(JSONObject.toJSONString(smsTemplateVO.getOtherConfigs()));
smsTemplateService.updateById(smsTemplate);
return smsTemplate;
}
private QuerySmsTemplateResponse query(SmsTemplateVO smsTemplateVO) {
QuerySmsTemplateRequest request = new QuerySmsTemplateRequest();
request.setTemplateCode(smsTemplateVO.getTemplateCode());
Client client =aliyunSmsConfig.queryClient();
QuerySmsTemplateResponse response = null;
try {
response = client.querySmsTemplate(request);
} catch (Exception e) {
log.error("请求查询阿里云模板出错:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsTemplateEnum.SELECT_FAIL);
}
return response;
}
@Override
public SmsTemplate querySmsTemplate(SmsTemplateVO smsTemplateVO) {
QuerySmsTemplateResponse response =query(smsTemplateVO);
//受理状态
String code = response.getBody().getCode();
String message = response.getBody().getMessage();
SmsTemplate smsTemplate = BeanConv.toBean(smsTemplateVO, SmsTemplate.class);
if ("OK".equals(code)){
Integer templateStatus =response.getBody().getTemplateStatus();
//审核通过
if (templateStatus == 1) {
smsTemplateVO.setAuditStatus(SmsConstant.STATUS_AUDIT_0);
smsTemplateVO.setAuditMsg("审核通过");
smsTemplateService.updateById(smsTemplate);
//审核失败
} else if (templateStatus == 2) {
smsTemplateVO.setAuditStatus(SmsConstant.STATUS_AUDIT_1);
smsTemplateVO.setAuditMsg(response.getBody().getReason());
smsTemplateService.updateById(smsTemplate);
} else {
log.info("阿里云模板:{},审核中", response.getBody().getTemplateCode());
}
}else {
log.warn("受理查询阿里云模板出错:{}", message);
throw new ProjectException(SmsTemplateEnum.SELECT_FAIL);
}
return smsTemplate;
}
}
@@ -0,0 +1,45 @@
package com.itheima.sfbx.sms.handler.aliyun.config;
import com.aliyun.dysmsapi20170525.Client;
import com.aliyun.teaopenapi.models.Config;
import com.itheima.sfbx.framework.commons.constant.sms.SmsConstant;
import com.itheima.sfbx.framework.commons.dto.sms.SmsChannelVO;
import com.itheima.sfbx.framework.commons.utils.ExceptionsUtil;
import com.itheima.sfbx.sms.service.ISmsChannelService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
/**
* @ClassName AlipayConfig.java
* @Description 支付宝配置类
*/
@Slf4j
@Configuration
public class AliyunSmsConfig {
@Autowired
ISmsChannelService smsChannelService;
/***
* @description 获得配置
* @return
*/
public Client queryClient(){
SmsChannelVO smsChannelVO = smsChannelService.findSmsChannelByChannelLabel(SmsConstant.ALIYUN_SMS);
Config config = new Config()
// 阿里云AccessKey ID
.setAccessKeyId(smsChannelVO.getAccessKeyId())
// 阿里云AccessKey Secret
.setAccessKeySecret(smsChannelVO.getAccessKeySecret());
// 访问的域名
config.endpoint = smsChannelVO.getDomain();
try {
return new Client(config);
} catch (Exception e) {
log.error("阿里云SMS的配置信息出错:{}", ExceptionsUtil.getStackTraceAsString(e));
return null;
}
}
}
@@ -0,0 +1,149 @@
package com.itheima.sfbx.sms.handler.baidu;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baidubce.services.sms.SmsClient;
import com.baidubce.services.sms.model.SendMessageItem;
import com.baidubce.services.sms.model.SendMessageV3Request;
import com.baidubce.services.sms.model.SendMessageV3Response;
import com.itheima.sfbx.framework.commons.constant.sms.SmsConstant;
import com.itheima.sfbx.framework.commons.dto.sms.SmsChannelVO;
import com.itheima.sfbx.framework.commons.dto.sms.SmsSignVO;
import com.itheima.sfbx.framework.commons.dto.sms.SmsTemplateVO;
import com.itheima.sfbx.framework.commons.enums.sms.SmsSendEnum;
import com.itheima.sfbx.framework.commons.exception.ProjectException;
import com.itheima.sfbx.framework.commons.utils.BeanConv;
import com.itheima.sfbx.sms.handler.baidu.config.BaiduSmsConfig;
import com.itheima.sfbx.sms.pojo.SmsSendRecord;
import com.itheima.sfbx.sms.service.ISmsChannelService;
import com.itheima.sfbx.sms.service.ISmsSendRecordService;
import com.itheima.sfbx.sms.service.ISmsSignService;
import com.itheima.sfbx.sms.service.ISmsTemplateService;
import com.itheima.sfbx.sms.handler.SmsSendHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
/**
* @ClassName BaiduSmsSendHandlerImpl.java
* @Description 百度短信发送
*/
@Slf4j
@Service("baiduSmsSendHandler")
public class BaiduSmsSendHandlerImpl implements SmsSendHandler {
@Autowired
BaiduSmsConfig baiduSmsConfig;
@Autowired
ISmsSendRecordService smsSendRecordService;
@Autowired
ISmsTemplateService smsTemplateService;
@Autowired
ISmsChannelService smsChannelService;
@Autowired
ISmsSignService smsSignService;
@Override
public Boolean SendSms(SmsTemplateVO smsTemplateVO,
SmsChannelVO smsChannelVO,
SmsSignVO smsSignVO,
Set<String> mobiles,
LinkedHashMap<String, String> templateParam) {
//超过发送上限
if (mobiles.size() > 200) {
throw new ProjectException(SmsSendEnum.PEXCEED_THE_LIMIT);
}
//实例化请求对象
SendMessageV3Request request = new SendMessageV3Request();
//手机号码,支持单个或多个手机号,多个手机号之间以英文逗号分隔,
// 一次请求最多支持200个手机号。国际/港澳台号码请按照E.164规范表示,
// 例如台湾手机号以+886开头,”+“不能省略。
request.setMobile(JSONObject.toJSONString(mobiles)
.replace("\"","")
.replace("[","")
.replace("]",""));
//模板id
request.setTemplate(smsTemplateVO.getTemplateCode());
//签名Id
request.setSignatureId(smsSignVO.getSignCode());
request.setContentVar(templateParam);
SmsClient client = baiduSmsConfig.queryClient();
SendMessageV3Response response = client.sendMessage(request);
//处理返回结果
String content = smsTemplateVO.getContent();
for (Map.Entry<String, String> entry : templateParam.entrySet()) {
content = content.replace(entry.getKey(), entry.getValue());
}
List<SmsSendRecord> sendRecords = new ArrayList<>();
List<SendMessageItem> sendMessageItems = response.getData();
for (SendMessageItem sendMessageItem : sendMessageItems) {
String acceptStatus = null;
String acceptMsg = null;
String sendStatus = null;
String sendMsg = null;
if ("1000".equals(sendMessageItem.getCode())){
//受理成功
acceptStatus = SmsConstant.STATUS_ACCEPT_0;
acceptMsg = "受理成功";
sendStatus = SmsConstant.STATUS_SEND_2;
sendMsg = "发送中";
}else {
//受理失败
acceptStatus=SmsConstant.STATUS_ACCEPT_1;
acceptMsg = response.getMessage();
}
SmsSendRecord smsSendRecord = SmsSendRecord.builder()
.sendContent(content)
.channelLabel(smsChannelVO.getChannelLabel())
.channelName(smsChannelVO.getChannelName())
.acceptStatus(acceptStatus)
.acceptMsg(acceptMsg)
.sendStatus(sendStatus)
.sendMsg(sendMsg)
.mobile(sendMessageItem.getMobile())
.signCode(smsSignVO.getSignCode())
.signName(smsSignVO.getSignName())
.templateNo(smsTemplateVO.getTemplateNo())
.templateCode(smsTemplateVO.getTemplateCode())
.templateId(smsTemplateVO.getId())
.templateType(smsTemplateVO.getSmsType())
.templateParams(JSONObject.toJSONString(templateParam))
.build();
sendRecords.add(smsSendRecord);
}
return smsSendRecordService.saveBatch(sendRecords);
}
@Override
public Boolean querySendSms(SmsSendRecord smsSendRecord)throws ProjectException {
log.warn("百度简单短信无主动轮询接口");
return false;
}
@Override
public Boolean retrySendSms(SmsSendRecord smsSendRecord) {
//已发送,发送中的短信不处理
if (smsSendRecord.getSendStatus().equals(SmsConstant.STATUS_SEND_2)||
smsSendRecord.getSendStatus().equals(SmsConstant.STATUS_SEND_0)) {
throw new ProjectException(SmsSendEnum.SEND_SUCCEED);
}
SmsTemplateVO smsTemplateVO = BeanConv.toBean(smsTemplateService.getById(smsSendRecord.getTemplateId()), SmsTemplateVO.class);
SmsChannelVO smsChannelVO = smsChannelService.findChannelByChannelLabel(smsSendRecord.getChannelLabel());
SmsSignVO smsSignVO = smsSignService.findSmsSignBySignCodeAndChannelLabel(smsSendRecord.getSignCode(), smsSendRecord.getChannelLabel());
Set<String> mobiles = new HashSet<>();
mobiles.add(smsSendRecord.getMobile());
LinkedHashMap<String, String> templateParam =
JSON.parseObject(smsSendRecord.getTemplateParams(), LinkedHashMap.class);
Boolean flag = SendSms(smsTemplateVO, smsChannelVO, smsSignVO, mobiles, templateParam);
if (flag){
flag = smsTemplateService.removeById(smsSendRecord.getTemplateId());
}
return flag;
}
}
@@ -0,0 +1,190 @@
package com.itheima.sfbx.sms.handler.baidu;
import com.baidubce.services.sms.SmsClient;
import com.baidubce.services.sms.model.v3.*;
import com.itheima.sfbx.framework.commons.constant.sms.SmsConstant;
import com.itheima.sfbx.framework.commons.dto.sms.SmsSignVO;
import com.itheima.sfbx.framework.commons.enums.sms.SmsSignEnum;
import com.itheima.sfbx.framework.commons.exception.ProjectException;
import com.itheima.sfbx.framework.commons.utils.BeanConv;
import com.itheima.sfbx.framework.commons.utils.EmptyUtil;
import com.itheima.sfbx.sms.handler.SmsSignHandler;
import com.itheima.sfbx.sms.handler.baidu.config.BaiduSmsConfig;
import com.itheima.sfbx.sms.pojo.SmsSign;
import com.itheima.sfbx.sms.service.ISmsSignService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @ClassName BaiduSmsSignHandlerImpl.java
* @Description 百度签名审核
*/
@Slf4j
@Service("baiduSmsSignHandler")
public class BaiduSmsSignHandlerImpl implements SmsSignHandler {
@Autowired
BaiduSmsConfig baiduSmsConfig;
@Autowired
ISmsSignService smsSignService;
@Override
public SmsSign addSmsSign(SmsSignVO smsSignVO) {
//查询当前签名是否保存过
SmsSignVO smsSignHandler = smsSignService.findSmsSignBySignNameAndChannelLabel
(smsSignVO.getSignName(),smsSignVO.getChannelLabel());
if (!EmptyUtil.isNullOrEmpty(smsSignHandler)){
smsSignVO = BeanConv.toBean(smsSignHandler,SmsSignVO.class);
//查询当前签名在远程的信息
GetSignatureResponse getSignatureResponse = query(smsSignVO);
//处理返回结果
String getSignatureStatus = getSignatureResponse.getStatus();
//审核通过
if ("READY".equals(getSignatureStatus)) {
smsSignVO.setAuditStatus(SmsConstant.STATUS_AUDIT_0);
smsSignVO.setAuditMsg("审核通过");
//审核失败
} else if ("REJECTED".equals(getSignatureStatus) || "ABORTED".equals(getSignatureStatus)) {
smsSignVO.setAuditStatus(SmsConstant.STATUS_AUDIT_1);
smsSignVO.setAuditMsg(getSignatureResponse.getReview());
} else {
smsSignVO.setAuditStatus(SmsConstant.STATUS_AUDIT_2);
smsSignVO.setAuditMsg(getSignatureResponse.getReview());
}
SmsSign smsSign = BeanConv.toBean(smsSignVO, SmsSign.class);
boolean flag = smsSignService.saveOrUpdate(smsSign);
if (flag){
return smsSign;
}
throw new ProjectException(SmsSignEnum.CREATE_FAIL);
}
CreateSignatureRequest request = new CreateSignatureRequest()
//签名内容
.withContent(smsSignVO.getSignName())
//签名类型。
//Enterprise:企业
//MobileApp:移动应用名称
//Web:工信部备案的网站名称
//WeChatPublic:微信公众号名称
//Brand:商标名称
//Else:其他
.withContentType(smsSignVO.getSignType())
//签名适用的国家类型
//DOMESTIC:国内
//INTERNATIONAL:国际/港澳台
//GLOBAL:全球均适用
//默认为DOMESTIC
.withCountryType(smsSignVO.getInternational())
//对于签名的描述
.withDescription(smsSignVO.getRemark())
//签名的证明文件经过base64编码后的字符串。文件大小不超过2MB。
.withSignatureFileBase64(smsSignVO.getProofImage())
//签名证明文件的格式,目前支持JPG、PNG、JPEG三种格式
.withSignatureFileFormat(smsSignVO.getProofType().replace(".",""));
SmsClient client = baiduSmsConfig.queryClient();
CreateSignatureResponse response = client.createSignature(request);
String status = response.getStatus();
if ("SUBMITTED".equals(status)) {
//受理成功
smsSignVO.setAcceptStatus(SmsConstant.STATUS_ACCEPT_0);
smsSignVO.setAcceptMsg("受理成功");
//审核中
smsSignVO.setAuditStatus(SmsConstant.STATUS_ACCEPT_2);
smsSignVO.setAuditMsg("审核中");
smsSignVO.setSignCode(response.getSignatureId());
} else {
smsSignVO.setAcceptStatus(SmsConstant.STATUS_ACCEPT_1);
smsSignVO.setAcceptMsg(response.getStatus());
}
//本地持久化
SmsSign smsSign = BeanConv.toBean(smsSignVO, SmsSign.class);
boolean flag = smsSignService.save(smsSign);
if (flag){
return smsSign;
}
throw new ProjectException(SmsSignEnum.CREATE_FAIL);
}
@Override
public Boolean deleteSmsSign(SmsSignVO smsSignVO) {
DeleteSignatureRequest request = new DeleteSignatureRequest()
//短信模板唯一识别码
.withSignatureId(smsSignVO.getSignCode());
SmsClient client = baiduSmsConfig.queryClient();
client.deleteSignature(request);
return smsSignService.removeById(smsSignVO.getId());
}
@Override
public SmsSign modifySmsSign(SmsSignVO smsSignVO) {
ModifySignatureRequest request = new ModifySignatureRequest()
.withSignatureId(smsSignVO.getSignCode())
//签名内容
.withContent(smsSignVO.getSignName())
//签名类型。
//Enterprise:企业
//MobileApp:移动应用名称
//Web:工信部备案的网站名称
//WeChatPublic:微信公众号名称
//Brand:商标名称
//Else:其他
.withContentType(smsSignVO.getSignType())
//签名适用的国家类型
//DOMESTIC:国内
//INTERNATIONAL:国际/港澳台
//GLOBAL:全球均适用
//默认为DOMESTIC
.withCountryType(smsSignVO.getInternational())
//对于签名的描述
.withDescription(smsSignVO.getRemark())
//签名的证明文件经过base64编码后的字符串。文件大小不超过2MB。
.withSignatureFileBase64(smsSignVO.getProofImage())
//签名证明文件的格式,目前支持JPG、PNG、JPEG三种格式
.withSignatureFileFmt(smsSignVO.getProofType().replace(",",""));
SmsClient client = baiduSmsConfig.queryClient();
client.modifySignature(request);
//受理成功
smsSignVO.setAcceptStatus(SmsConstant.STATUS_ACCEPT_0);
smsSignVO.setAcceptMsg("受理成功");
//审核中
smsSignVO.setAuditStatus(SmsConstant.STATUS_ACCEPT_2);
smsSignVO.setAuditMsg("审核中");
//本地持久化
SmsSign smsSign = BeanConv.toBean(smsSignVO, SmsSign.class);
smsSignService.updateById(smsSign);
return smsSign;
}
private GetSignatureResponse query(SmsSignVO smsSignVO) {
GetSignatureRequest request = new GetSignatureRequest();
//查询
request.setSignatureId(smsSignVO.getSignCode());
SmsClient client = baiduSmsConfig.queryClient();
return client.getSignature(request);
}
@Override
public SmsSign querySmsSign(SmsSignVO smsSignVO) {
GetSignatureResponse response = query(smsSignVO);
//处理返回结果
String status = response.getStatus();
SmsSign smsSign = BeanConv.toBean(smsSignVO, SmsSign.class);
//审核通过
if ("READY".equals(status)) {
smsSignVO.setAuditStatus(SmsConstant.STATUS_ACCEPT_0);
smsSignVO.setAuditMsg("审核通过");
smsSignService.updateById(smsSign);
//审核失败
} else if ("REJECTED".equals(status) || "ABORTED".equals(status)) {
smsSignVO.setAuditStatus(SmsConstant.STATUS_ACCEPT_1);
smsSignVO.setAuditMsg(response.getReview());
smsSignService.updateById(smsSign);
} else {
log.info("百度云签名:{},审核中", response.getSignatureId());
}
return smsSign;
}
}
@@ -0,0 +1,175 @@
package com.itheima.sfbx.sms.handler.baidu;
import com.alibaba.fastjson.JSONObject;
import com.baidubce.services.sms.SmsClient;
import com.baidubce.services.sms.model.v3.*;
import com.itheima.sfbx.framework.commons.constant.sms.SmsConstant;
import com.itheima.sfbx.framework.commons.dto.sms.SmsTemplateVO;
import com.itheima.sfbx.framework.commons.enums.sms.SmsTemplateEnum;
import com.itheima.sfbx.framework.commons.exception.ProjectException;
import com.itheima.sfbx.framework.commons.utils.BeanConv;
import com.itheima.sfbx.framework.commons.utils.EmptyUtil;
import com.itheima.sfbx.sms.handler.SmsTemplateHandler;
import com.itheima.sfbx.sms.handler.baidu.config.BaiduSmsConfig;
import com.itheima.sfbx.sms.pojo.SmsTemplate;
import com.itheima.sfbx.sms.service.ISmsTemplateService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @ClassName BaiduTemplateHandlerImpl.java
* @Description 百度模板审核
*/
@Slf4j
@Service("baiduTemplateHandler")
public class BaiduTemplateHandlerImpl implements SmsTemplateHandler {
@Autowired
BaiduSmsConfig baiduSmsConfig;
@Autowired
ISmsTemplateService smsTemplateService;
@Override
public SmsTemplate addSmsTemplate(SmsTemplateVO smsTemplateVO) {
//查询是否添加过模板
SmsTemplateVO smsTemplateHandler = smsTemplateService.findSmsTemplateByTemplateNameAndChannelLabel(
smsTemplateVO.getTemplateName(),
smsTemplateVO.getChannelLabel());
if (!EmptyUtil.isNullOrEmpty(smsTemplateHandler)){
smsTemplateVO = BeanConv.toBean(smsTemplateHandler,SmsTemplateVO.class);
GetTemplateResponse response = query(smsTemplateVO);
//处理返回结果
String status = response.getStatus();
//审核通过
if ("READY".equals(status)) {
smsTemplateVO.setAuditStatus(SmsConstant.STATUS_AUDIT_0);
smsTemplateVO.setAuditMsg("审核通过");
//审核失败
} else if ("REJECTED".equals(status) || "ABORTED".equals(status)) {
smsTemplateVO.setAuditStatus(SmsConstant.STATUS_AUDIT_1);
smsTemplateVO.setAuditMsg(response.getReview());
} else {
log.info("百度云模板:{},审核中", response.getTemplateId());
smsTemplateVO.setAuditStatus(SmsConstant.STATUS_AUDIT_2);
smsTemplateVO.setAuditMsg(response.getReview());
}
SmsTemplate smsTemplate = BeanConv.toBean(smsTemplateVO, SmsTemplate.class);
boolean flag = smsTemplateService.saveOrUpdate(smsTemplate);
if (flag){
return smsTemplate;
}
throw new ProjectException(SmsTemplateEnum.CREATE_FAIL);
}
CreateTemplateRequest request = new CreateTemplateRequest()
//模板名称
.withName(smsTemplateVO.getTemplateName())
//模板内容
.withContent(smsTemplateVO.getContent())
//短信类型
.withSmsType(smsTemplateVO.getSmsType())
//适用国家类型
//DOMESTIC:国内
//INTERNATIONAL:国际/港澳台
//GLOBAL:全球
.withCountryType(smsTemplateVO.getInternational())
//模板描述
.withDescription(smsTemplateVO.getRemark());
SmsClient client = baiduSmsConfig.queryClient();
CreateTemplateResponse response = client.createTemplate(request);
String status = response.getStatus();
if ("SUBMITTED".equals(status)) {
//受理成功
smsTemplateVO.setAcceptStatus(SmsConstant.STATUS_ACCEPT_0);
smsTemplateVO.setAcceptMsg("受理成功");
//审核中
smsTemplateVO.setAuditStatus(SmsConstant.STATUS_AUDIT_2);
smsTemplateVO.setAuditMsg("审核中");
smsTemplateVO.setTemplateCode(response.getTemplateId());
} else {
smsTemplateVO.setAcceptStatus(SmsConstant.STATUS_ACCEPT_1);
smsTemplateVO.setAcceptMsg(response.getStatus());
}
//本地持久化
SmsTemplate smsTemplate = BeanConv.toBean(smsTemplateVO, SmsTemplate.class);
smsTemplate.setOtherConfig(JSONObject.toJSONString(smsTemplateVO.getOtherConfigs()));
boolean flag = smsTemplateService.save(smsTemplate);
if (flag){
return smsTemplate;
}
return null;
}
@Override
public Boolean deleteSmsTemplate(SmsTemplateVO smsTemplateVO) {
DeleteTemplateRequest request =new DeleteTemplateRequest()
.withTemplateId(smsTemplateVO.getTemplateCode());
SmsClient client = baiduSmsConfig.queryClient();
client.deleteTemplate(request);
return smsTemplateService.removeById(smsTemplateVO.getId());
}
@Override
public SmsTemplate modifySmsTemplate(SmsTemplateVO smsTemplateVO) {
ModifyTemplateRequest request = new ModifyTemplateRequest()
//模板id
.withTemplateId(smsTemplateVO.getTemplateCode())
//模板名称
.withName(smsTemplateVO.getTemplateName())
//模板内容
.withContent(smsTemplateVO.getContent())
//短信类型
.withSmsType(smsTemplateVO.getSmsType())
//适用国家类型
//DOMESTIC:国内
//INTERNATIONAL:国际/港澳台
//GLOBAL:全球
.withCountryType(smsTemplateVO.getInternational())
//模板描述
.withDescription(smsTemplateVO.getRemark());
SmsClient client = baiduSmsConfig.queryClient();
client.modifyTemplate(request);
//受理成功
smsTemplateVO.setAcceptStatus(SmsConstant.STATUS_ACCEPT_0);
smsTemplateVO.setAcceptMsg("受理成功");
//审核中
smsTemplateVO.setAuditStatus(SmsConstant.STATUS_AUDIT_2);
smsTemplateVO.setAuditMsg("审核中");
//本地持久化
SmsTemplate smsTemplate = BeanConv.toBean(smsTemplateVO, SmsTemplate.class);
smsTemplate.setOtherConfig(JSONObject.toJSONString(smsTemplateVO.getOtherConfigs()));
smsTemplateService.updateById(smsTemplate);
return smsTemplate;
}
private GetTemplateResponse query(SmsTemplateVO smsTemplateVO){
GetTemplateRequest request = new GetTemplateRequest()
.withTemplateId(smsTemplateVO.getTemplateCode());
SmsClient client = baiduSmsConfig.queryClient();
return client.getTemplate(request);
}
@Override
public SmsTemplate querySmsTemplate(SmsTemplateVO smsTemplateVO) {
GetTemplateResponse response = query(smsTemplateVO);
//处理返回结果
String status = response.getStatus();
SmsTemplate smsTemplate = BeanConv.toBean(smsTemplateVO, SmsTemplate.class);
//审核通过
if ("READY".equals(status)) {
smsTemplateVO.setAuditStatus(SmsConstant.STATUS_AUDIT_0);
smsTemplateVO.setAuditMsg("审核通过");
smsTemplateService.updateById(smsTemplate);
//审核失败
} else if ("REJECTED".equals(status) || "ABORTED".equals(status)) {
smsTemplateVO.setAuditStatus(SmsConstant.STATUS_AUDIT_1);
smsTemplateVO.setAuditMsg(response.getReview());
smsTemplateService.updateById(smsTemplate);
} else {
log.info("阿里云模板:{},审核中", response.getTemplateId());
}
return smsTemplate;
}
}
@@ -0,0 +1,53 @@
package com.itheima.sfbx.sms.handler.baidu.config;
import com.baidubce.auth.DefaultBceCredentials;
import com.baidubce.http.DefaultRetryPolicy;
import com.baidubce.services.sms.SmsClient;
import com.baidubce.services.sms.SmsClientConfiguration;
import com.itheima.sfbx.framework.commons.constant.sms.SmsConstant;
import com.itheima.sfbx.framework.commons.dto.sms.SmsChannelVO;
import com.itheima.sfbx.sms.service.ISmsChannelService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.Async;
import javax.annotation.PostConstruct;
import java.util.Timer;
import java.util.TimerTask;
/**
* @ClassName BaiduSmsConfig.java
* @Description 百度短信配置类
*/
@Slf4j
@Configuration
public class BaiduSmsConfig {
@Autowired
ISmsChannelService smsChannelService;
/***
* @description 获得配置
* @return
*/
public SmsClient queryClient(){
SmsChannelVO smsChannelVO = smsChannelService.findSmsChannelByChannelLabel(SmsConstant.BAIDU_SMS);
//百度云配置
SmsClientConfiguration config = new SmsClientConfiguration()
//站点
.withEndpoint(smsChannelVO.getDomain())
//百度云密钥
.withCredentials(new DefaultBceCredentials(smsChannelVO.getAccessKeyId(), smsChannelVO.getAccessKeySecret()))
// 设置HTTP最大连接数为10
.withMaxConnections(10)
// 设置TCP连接超时为5000毫秒
.withConnectionTimeoutInMillis(5000)
// 设置默重试最大的重试次数为3
.withRetryPolicy(new DefaultRetryPolicy())
//设置Socket传输数据超时的时间为2000毫秒
.withSocketTimeoutInMillis(2000);
return new SmsClient(config);
}
}
@@ -0,0 +1,224 @@
package com.itheima.sfbx.sms.handler.tencent;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.itheima.sfbx.framework.commons.constant.sms.SmsConstant;
import com.itheima.sfbx.framework.commons.dto.basic.OtherConfigVO;
import com.itheima.sfbx.framework.commons.dto.sms.SmsChannelVO;
import com.itheima.sfbx.framework.commons.dto.sms.SmsSignVO;
import com.itheima.sfbx.framework.commons.dto.sms.SmsTemplateVO;
import com.itheima.sfbx.framework.commons.enums.sms.SmsSendEnum;
import com.itheima.sfbx.framework.commons.exception.ProjectException;
import com.itheima.sfbx.framework.commons.utils.BeanConv;
import com.itheima.sfbx.framework.commons.utils.EmptyUtil;
import com.itheima.sfbx.framework.commons.utils.ExceptionsUtil;
import com.itheima.sfbx.sms.handler.tencent.config.TencentSmsConfig;
import com.itheima.sfbx.sms.pojo.SmsSendRecord;
import com.itheima.sfbx.sms.service.ISmsChannelService;
import com.itheima.sfbx.sms.service.ISmsSendRecordService;
import com.itheima.sfbx.sms.service.ISmsSignService;
import com.itheima.sfbx.sms.service.ISmsTemplateService;
import com.itheima.sfbx.sms.handler.SmsSendHandler;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.sms.v20210111.SmsClient;
import com.tencentcloudapi.sms.v20210111.models.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import java.sql.Timestamp;
import java.util.*;
/**
* @ClassName TencentSmsSendHandlerImpl.java
* @Description 腾讯云邮件发送处理器接口
*/
@Slf4j
@Service("tencentSmsSendHandler")
public class TencentSmsSendHandlerImpl implements SmsSendHandler {
@Lazy
@Autowired
TencentSmsConfig tencentSmsConfig;
@Autowired
ISmsSendRecordService smsSendRecordService;
@Autowired
ISmsTemplateService smsTemplateService;
@Autowired
ISmsChannelService smsChannelService;
@Autowired
ISmsSignService smsSignService;
@Override
public Boolean SendSms(SmsTemplateVO smsTemplateVO,
SmsChannelVO smsChannelVO,
SmsSignVO smsSignVO,
Set<String> mobiles,
LinkedHashMap<String, String> templateParam) {
//超过发送上限
if (mobiles.size() > 200) {
throw new ProjectException(SmsSendEnum.PEXCEED_THE_LIMIT);
}
// 实例化一个请求对象,每个接口都会对应一个request对象
SendSmsRequest request = new SendSmsRequest();
//接收短信的手机号码,Array of String数组格式。
request.setPhoneNumberSet(mobiles.stream().toArray(String[]::new));
//短信SdkAppId在短信控制台 添加应用后生成的实际 SdkAppId,
List <OtherConfigVO> otherConfigVoList = JSONArray.parseArray(smsChannelVO.getOtherConfig(),OtherConfigVO.class);
for (OtherConfigVO otherConfigVo : otherConfigVoList) {
if ("smsSdkAppId".equals(otherConfigVo.getConfigKey())){
request.setSmsSdkAppId(otherConfigVo.getConfigValue());
break;
}
}
//模板ID必须填写已审核通过的模板 ID
request.setTemplateId(smsTemplateVO.getTemplateCode());
//短信签名内容,使用 UTF-8 编码,必须填写已审核通过的签名
request.setSignName(smsSignVO.getSignName());
//模板参数,若无模板参数,则设置为空。
if (!EmptyUtil.isNullOrEmpty(templateParam)){
LinkedList<String> templateParamList = new LinkedList<>();
for (Map.Entry<String,String> result:templateParam.entrySet()){
templateParamList.add(result.getValue());
}
request.setTemplateParamSet(templateParamList.stream().toArray(String[]::new));
}
//返回的resp是一个SendSmsResponse的实例,与请求对象对应
SmsClient smsClient = tencentSmsConfig.queryClient();
SendSmsResponse response = null;
try {
response = smsClient.SendSms(request);
} catch (TencentCloudSDKException e) {
log.error("腾讯云发送短信:{},失败:{}",request.toString(), ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsSendEnum.SEND_FAIL);
}
SendStatus[] sendStatusSet = response.getSendStatusSet();
String content = smsTemplateVO.getContent();
for (Map.Entry<String, String> entry : templateParam.entrySet()) {
content = content.replace(entry.getKey(), entry.getValue());
}
List<SmsSendRecord> sendRecords = new ArrayList<>();
for (SendStatus sendStatusHandler : sendStatusSet) {
String code = sendStatusHandler.getCode();
String acceptStatus = null;
String acceptMsg = null;
String sendStatus = null;
String sendMsg = null;
if ("Ok".equals(code)){
//受理成功
acceptStatus = SmsConstant.STATUS_ACCEPT_0;
acceptMsg = "受理成功";
sendStatus = SmsConstant.STATUS_SEND_2;
sendMsg = "发送中";
}else {
//受理失败
acceptStatus=SmsConstant.STATUS_ACCEPT_1;
acceptMsg = sendStatusHandler.getMessage();
sendStatus = SmsConstant.STATUS_SEND_1;
sendMsg = "发送失败";
}
SmsSendRecord smsSendRecord = SmsSendRecord.builder()
.sendContent(content)
.channelLabel(smsChannelVO.getChannelLabel())
.channelName(smsChannelVO.getChannelName())
.acceptStatus(acceptStatus)
.acceptMsg(acceptMsg)
.sendStatus(sendStatus)
.sendMsg(sendMsg)
.mobile(sendStatusHandler.getPhoneNumber())
.signCode(smsSignVO.getSignCode())
.signName(smsSignVO.getSignName())
.templateNo(smsTemplateVO.getTemplateNo())
.templateNo(smsTemplateVO.getTemplateNo())
.templateCode(smsTemplateVO.getTemplateCode())
.templateId(smsTemplateVO.getId())
.templateType(smsTemplateVO.getSmsType())
.serialNo(sendStatusHandler.getSerialNo())
.templateParams(JSONObject.toJSONString(templateParam))
.build();
sendRecords.add(smsSendRecord);
}
return smsSendRecordService.saveBatch(sendRecords);
}
@Override
public Boolean querySendSms(SmsSendRecord smsSendRecord) {
// 实例化一个请求对象,每个接口都会对应一个request对象
PullSmsSendStatusByPhoneNumberRequest request = new PullSmsSendStatusByPhoneNumberRequest();
//拉取起始时间,UNIX 时间戳(时间:秒)。
//注:最大可拉取当前时期前7天的数据。
request.setBeginTime(Timestamp.valueOf(smsSendRecord.getCreateTime()).getTime()/1000);
//偏移量。
//注:目前固定设置为0。
request.setOffset(0L);
//拉取最大条数,最多 100。
request.setLimit(100L);
//短信SdkAppId在短信控制台 添加应用后生成的实际 SdkAppId,
SmsChannelVO smsChannelVO = smsChannelService.findChannelByChannelLabel(smsSendRecord.getChannelLabel());
List <OtherConfigVO> otherConfigVoList = JSONArray.parseArray(smsChannelVO.getOtherConfig(),OtherConfigVO.class);
for (OtherConfigVO otherConfigVo : otherConfigVoList) {
if ("smsSdkAppId".equals(otherConfigVo.getConfigKey())){
request.setSmsSdkAppId(otherConfigVo.getConfigValue());
break;
}
}
//下发目的手机号码
request.setPhoneNumber(smsSendRecord.getMobile());
//拉取截止时间,UNIX 时间戳(时间:秒)。
request.setEndTime(new Date().getTime()/1000);
// 返回的resp是一个PullSmsSendStatusByPhoneNumberResponse的实例,与请求对象对应
SmsClient smsClient = tencentSmsConfig.queryClient();
PullSmsSendStatusByPhoneNumberResponse response = null;
try {
response = smsClient.PullSmsSendStatusByPhoneNumber(request);
} catch (TencentCloudSDKException e) {
log.error("腾讯云查询短信发送状态:{},失败",request.toString());
throw new ProjectException(SmsSendEnum.QUERY_FAIL);
}
PullSmsSendStatus[] pullSmsSendStatusSet = response.getPullSmsSendStatusSet();
for (PullSmsSendStatus pullSmsSendStatus : pullSmsSendStatusSet) {
if (pullSmsSendStatus.getSerialNo().equals(smsSendRecord.getSerialNo())){
if ("SUCCESS".equals(pullSmsSendStatus.getReportStatus())){
smsSendRecord.setSendStatus(SmsConstant.STATUS_SEND_0);
smsSendRecord.setSendMsg("发送成功");
return smsSendRecordService.updateById(smsSendRecord);
}else if ("FAIL".equals(pullSmsSendStatus.getReportStatus())){
smsSendRecord.setSendStatus(SmsConstant.STATUS_SEND_1);
smsSendRecord.setSendMsg("发送失败");
return smsSendRecordService.updateById(smsSendRecord);
}else {
log.info("短信:{},等待回执!",smsSendRecord.toString());
}
break;
}
}
return true;
}
@Override
public Boolean retrySendSms(SmsSendRecord smsSendRecord) {
//已发送,发送中的短信不处理
if (smsSendRecord.getSendStatus().equals(SmsConstant.STATUS_SEND_2)||
smsSendRecord.getSendStatus().equals(SmsConstant.STATUS_SEND_0)) {
throw new ProjectException(SmsSendEnum.SEND_SUCCEED);
}
SmsTemplateVO smsTemplateVO = BeanConv.toBean(smsTemplateService.getById(smsSendRecord.getTemplateId()),SmsTemplateVO.class);
SmsChannelVO smsChannelVO = smsChannelService.findChannelByChannelLabel(smsSendRecord.getChannelLabel());
SmsSignVO smsSignVO = smsSignService.findSmsSignBySignCodeAndChannelLabel(smsSendRecord.getSignCode(), smsSendRecord.getChannelLabel());
Set<String> mobiles = new HashSet<>();
mobiles.add(smsSendRecord.getMobile());
LinkedHashMap<String, String> templateParam =
JSON.parseObject(smsSendRecord.getTemplateParams(), LinkedHashMap.class);
Boolean flag = SendSms(smsTemplateVO, smsChannelVO, smsSignVO, mobiles, templateParam);
if (flag){
flag = smsTemplateService.removeById(smsSendRecord.getTemplateId());
}
return flag;
}
}
@@ -0,0 +1,273 @@
package com.itheima.sfbx.sms.handler.tencent;
import com.itheima.sfbx.framework.commons.constant.sms.SmsConstant;
import com.itheima.sfbx.framework.commons.dto.sms.SmsSignVO;
import com.itheima.sfbx.framework.commons.enums.sms.SmsSignEnum;
import com.itheima.sfbx.framework.commons.exception.ProjectException;
import com.itheima.sfbx.framework.commons.utils.BeanConv;
import com.itheima.sfbx.framework.commons.utils.EmptyUtil;
import com.itheima.sfbx.framework.commons.utils.ExceptionsUtil;
import com.itheima.sfbx.sms.handler.SmsSignHandler;
import com.itheima.sfbx.sms.handler.tencent.config.TencentSmsConfig;
import com.itheima.sfbx.sms.pojo.SmsSign;
import com.itheima.sfbx.sms.service.ISmsSignService;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.sms.v20210111.SmsClient;
import com.tencentcloudapi.sms.v20210111.models.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
/**
* @ClassName TencentSmsSignHandlerImpl.java
* @Description 阿里云签名处理器接口
*/
@Slf4j
@Service("tencentSmsSignHandler")
public class TencentSmsSignHandlerImpl implements SmsSignHandler {
@Autowired
TencentSmsConfig tencentSmsConfig;
@Autowired
ISmsSignService smsSignService;
@Override
public SmsSign addSmsSign(SmsSignVO smsSignVO) {
//查询当前签名是否保存过
SmsSignVO smsSignHandler = smsSignService.findSmsSignBySignNameAndChannelLabel
(smsSignVO.getSignName(),smsSignVO.getChannelLabel());
if (!EmptyUtil.isNullOrEmpty(smsSignHandler)){
smsSignVO = BeanConv.toBean(smsSignHandler,SmsSignVO.class);
//查询当前签名在远程的信息
DescribeSmsSignListResponse querySmsSignResponse = query(smsSignVO);
//处理结果
DescribeSignListStatus[] describeSignListStatusSet = querySmsSignResponse.getDescribeSignListStatusSet();
if (!EmptyUtil.isNullOrEmpty(describeSignListStatusSet)){
DescribeSignListStatus describeSignListStatus = describeSignListStatusSet[0];
Long statusCode = describeSignListStatus.getStatusCode();
//审核通过
if (statusCode==0){
smsSignVO.setAuditStatus(SmsConstant.STATUS_AUDIT_0);
smsSignVO.setAuditMsg("审核通过");
//审核失败
}else if (statusCode==-1){
smsSignVO.setAuditStatus(SmsConstant.STATUS_AUDIT_1);
smsSignVO.setAuditMsg(describeSignListStatus.getReviewReply());
}else {
smsSignVO.setAuditStatus(SmsConstant.STATUS_AUDIT_2);
smsSignVO.setAuditMsg(describeSignListStatus.getReviewReply());
}
SmsSign smsSign = BeanConv.toBean(smsSignVO, SmsSign.class);
boolean flag = smsSignService.saveOrUpdate(smsSign);
if (flag){
return smsSign;
}
throw new ProjectException(SmsSignEnum.CREATE_FAIL);
}
}
// 实例化一个请求对象,每个接口都会对应一个request对象
AddSmsSignRequest request = new AddSmsSignRequest();
//签名名称
request.setSignName(smsSignVO.getSignName());
//签名类型。其中每种类型后面标注了其可选的 DocumentType(证明类型):
//0:公司,可选 DocumentType 有(0123)。
//1APP,可选 DocumentType 有(01234
//2:网站,可选 DocumentType 有(01235)。
//3:公众号或者小程序,可选 DocumentType 有(01236)。
//4:商标,可选 DocumentType 有(7)。
//5:政府/机关事业单位/其他机构,可选 DocumentType 有(23)。
request.setSignType(Long.valueOf(smsSignVO.getSignType()));
//证明类型:
//0:三证合一。
//1:企业营业执照。
//2:组织机构代码证书。
//3:社会信用代码证书。
//4:应用后台管理截图(个人开发APP)。
//5:网站备案后台截图(个人开发网站)。
//6:小程序设置页面截图(个人认证小程序)。
//7:商标注册书
request.setDocumentType(Long.valueOf(smsSignVO.getDocumentType()));
//是否国际/港澳台短信:
//0:表示国内短信。
//1:表示国际/港澳台短信。
request.setInternational(Long.valueOf(smsSignVO.getInternational()));
//签名用途:0:自用。1:他用。
request.setSignPurpose(Long.valueOf(smsSignVO.getSignPurpose()));
//签名对应的资质证明图片需先进行 base64 编码格式转换
request.setProofImage(smsSignVO.getProofImage());
//签名的申请备注。
request.setRemark(smsSignVO.getRemark());
// 返回的resp是一个AddSmsSignResponse的实例,与请求对象对应
SmsClient smsClient = tencentSmsConfig.queryClient();
AddSmsSignResponse response = null;
try {
response = smsClient.AddSmsSign(request);
} catch (TencentCloudSDKException e) {
log.error("请求添加腾讯云签名出错:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsSignEnum.CREATE_FAIL);
}
Long signId = response.getAddSignStatus().getSignId();
if (!EmptyUtil.isNullOrEmpty(signId)){
//受理成功
smsSignVO.setAcceptStatus(SmsConstant.STATUS_ACCEPT_0);
smsSignVO.setAcceptMsg("受理成功");
//审核中
smsSignVO.setAuditStatus(SmsConstant.STATUS_AUDIT_2);
smsSignVO.setAuditMsg("审核中");
smsSignVO.setSignCode(String.valueOf(signId));
}else {
smsSignVO.setAcceptStatus(SmsConstant.STATUS_ACCEPT_1);
smsSignVO.setAcceptMsg("受理失败");
}
//本地持久化
SmsSign smsSign = BeanConv.toBean(smsSignVO, SmsSign.class);
boolean flag = smsSignService.save(smsSign);
if (flag){
return smsSign;
}
throw new ProjectException(SmsSignEnum.CREATE_FAIL);
}
@Override
public Boolean deleteSmsSign(SmsSignVO smsSignVO) {
// 实例化一个请求对象,每个接口都会对应一个request对象
DeleteSmsSignRequest request = new DeleteSmsSignRequest();
request.setSignId(Long.valueOf(smsSignVO.getSignCode()));
// 返回的resp是一个DeleteSmsSignResponse的实例,与请求对象对应
SmsClient smsClient = tencentSmsConfig.queryClient();
DeleteSmsSignResponse response = null;
try {
response = smsClient.DeleteSmsSign(request);
} catch (TencentCloudSDKException e) {
log.error("请求删除腾讯云签名出错:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsSignEnum.DELETE_FAIL);
}
response.getDeleteSignStatus().getDeleteStatus();
return smsSignService.removeById(smsSignVO.getId());
}
@Override
public SmsSign modifySmsSign(SmsSignVO smsSignVO) {
// 实例化一个请求对象,每个接口都会对应一个request对象
ModifySmsSignRequest request = new ModifySmsSignRequest();
//签名编号
request.setSignId(Long.valueOf(smsSignVO.getSignCode()));
//签名名称
request.setSignName(smsSignVO.getSignName());
//签名类型。其中每种类型后面标注了其可选的 DocumentType(证明类型):
//0:公司,可选 DocumentType 有(0123)。
//1APP,可选 DocumentType 有(01234
//2:网站,可选 DocumentType 有(01235)。
//3:公众号或者小程序,可选 DocumentType 有(01236)。
//4:商标,可选 DocumentType 有(7)。
//5:政府/机关事业单位/其他机构,可选 DocumentType 有(23)。
request.setSignType(Long.valueOf(smsSignVO.getSignType()));
//证明类型:
//0:三证合一。
//1:企业营业执照。
//2:组织机构代码证书。
//3:社会信用代码证书。
//4:应用后台管理截图(个人开发APP)。
//5:网站备案后台截图(个人开发网站)。
//6:小程序设置页面截图(个人认证小程序)。
//7:商标注册书
request.setDocumentType(Long.valueOf(smsSignVO.getDocumentType()));
//是否国际/港澳台短信:
//0:表示国内短信。
//1:表示国际/港澳台短信。
request.setInternational(Long.valueOf(smsSignVO.getInternational()));
//签名用途:
//0:自用。
//1:他用。
request.setSignPurpose(Long.valueOf(smsSignVO.getSignPurpose()));
//签名对应的资质证明图片需先进行 base64 编码格式转换
request.setProofImage(smsSignVO.getProofImage());
//签名的申请备注。
request.setRemark(smsSignVO.getRemark());
// 返回的resp是一个ModifySmsSignResponse的实例,与请求对象对应
SmsClient smsClient = tencentSmsConfig.queryClient();
ModifySmsSignResponse response = null;
try {
response = smsClient.ModifySmsSign(request);
} catch (TencentCloudSDKException e) {
log.error("请求修改腾讯云签名出错:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsSignEnum.UPDATE_FAIL);
}
Long signId = response.getModifySignStatus().getSignId();
if (!EmptyUtil.isNullOrEmpty(signId)){
//受理成功
smsSignVO.setAcceptStatus(SmsConstant.STATUS_ACCEPT_0);
smsSignVO.setAcceptMsg("受理成功");
//审核中
smsSignVO.setAuditStatus(SmsConstant.STATUS_AUDIT_2);
smsSignVO.setAuditMsg("审核中");
smsSignVO.setSignCode(String.valueOf(signId));
}else {
//受理失败
smsSignVO.setAcceptStatus(SmsConstant.STATUS_ACCEPT_1);
smsSignVO.setAcceptMsg("受理失败");
//重置审核状态
smsSignVO.setAuditStatus(null);
smsSignVO.setAuditMsg(null);
smsSignVO.setSignCode(null);
}
//本地持久化
SmsSign smsSign = BeanConv.toBean(smsSignVO, SmsSign.class);
smsSignService.updateById(smsSign);
return smsSign;
}
private DescribeSmsSignListResponse query(SmsSignVO smsSignVO) {
//实例化一个请求对象,每个接口都会对应一个request对象
DescribeSmsSignListRequest request = new DescribeSmsSignListRequest();
//是否国际/港澳台短信: 0:表示国内短信。 1:表示国际/港澳台短信。
request.setInternational(Long.valueOf(smsSignVO.getInternational()));
//签名ID数组。 注:默认数组最大长度100。
List<Long> signCodes = new ArrayList<>();
signCodes.add(Long.valueOf(smsSignVO.getSignCode()));
request.setSignIdSet(signCodes.stream().toArray(Long[]::new));
//返回的resp是一个DescribeSmsSignListResponse的实例与请求对象对应
SmsClient smsClient = tencentSmsConfig.queryClient();
DescribeSmsSignListResponse response = null;
try {
response = smsClient.DescribeSmsSignList(request);
} catch (TencentCloudSDKException e) {
log.error("请求查询腾讯云签名出错:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsSignEnum.SELECT_FAIL);
}
return response;
}
@Override
public SmsSign querySmsSign(SmsSignVO smsSignVO) {
DescribeSmsSignListResponse response = query(smsSignVO);
//处理结果
DescribeSignListStatus[] describeSignListStatusSet = response.getDescribeSignListStatusSet();
SmsSign smsSign = BeanConv.toBean(smsSignVO,SmsSign.class);
if (!EmptyUtil.isNullOrEmpty(describeSignListStatusSet)){
DescribeSignListStatus describeSignListStatus = describeSignListStatusSet[0];
Long statusCode = describeSignListStatus.getStatusCode();
//审核通过
if (statusCode==0){
smsSignVO.setAuditStatus(SmsConstant.STATUS_AUDIT_0);
smsSignVO.setAuditMsg("审核通过");
smsSignService.updateById(smsSign);
//审核失败
}else if (statusCode==-1){
smsSignVO.setAuditStatus(SmsConstant.STATUS_AUDIT_1);
smsSignVO.setAuditMsg(describeSignListStatus.getReviewReply());
smsSignService.updateById(smsSign);
}else {
log.info("腾讯云签名:{},审核中",describeSignListStatus.getSignName());
}
}else {
log.warn("受理查询腾讯签名出错");
throw new ProjectException(SmsSignEnum.SELECT_FAIL);
}
return smsSign;
}
}
@@ -0,0 +1,243 @@
package com.itheima.sfbx.sms.handler.tencent;
import com.alibaba.fastjson.JSONObject;
import com.itheima.sfbx.framework.commons.constant.sms.SmsConstant;
import com.itheima.sfbx.framework.commons.dto.sms.SmsTemplateVO;
import com.itheima.sfbx.framework.commons.enums.sms.SmsTemplateEnum;
import com.itheima.sfbx.framework.commons.exception.ProjectException;
import com.itheima.sfbx.framework.commons.utils.BeanConv;
import com.itheima.sfbx.framework.commons.utils.EmptyUtil;
import com.itheima.sfbx.framework.commons.utils.ExceptionsUtil;
import com.itheima.sfbx.sms.handler.SmsTemplateHandler;
import com.itheima.sfbx.sms.handler.tencent.config.TencentSmsConfig;
import com.itheima.sfbx.sms.pojo.SmsTemplate;
import com.itheima.sfbx.sms.service.ISmsTemplateService;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.sms.v20210111.SmsClient;
import com.tencentcloudapi.sms.v20210111.models.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
/**
* @ClassName TencentTemplateHandlerImpl.java
* @Description 腾讯云模板处理器接口
*/
@Slf4j
@Service("tencentTemplateHandler")
public class TencentTemplateHandlerImpl implements SmsTemplateHandler {
@Autowired
TencentSmsConfig tencentSmsConfig;
@Autowired
ISmsTemplateService smsTemplateService;
@Override
public SmsTemplate addSmsTemplate(SmsTemplateVO smsTemplateVO) {
//查询是否添加过模板
SmsTemplateVO smsTemplateHandler = smsTemplateService.findSmsTemplateByTemplateNameAndChannelLabel(
smsTemplateVO.getTemplateName(),
smsTemplateVO.getChannelLabel());
if (!EmptyUtil.isNullOrEmpty(smsTemplateHandler)){
smsTemplateVO = BeanConv.toBean(smsTemplateHandler,SmsTemplateVO.class);
DescribeSmsTemplateListResponse response = query(smsTemplateVO);
//处理结果
DescribeTemplateListStatus[] describeTemplateStatusSet = response.getDescribeTemplateStatusSet();
response.getDescribeTemplateStatusSet();
if (!EmptyUtil.isNullOrEmpty(describeTemplateStatusSet)){
DescribeTemplateListStatus describeTemplateListStatus = describeTemplateStatusSet[0];
Long statusCode = describeTemplateListStatus.getStatusCode();
//审核通过
if (statusCode == 0) {
smsTemplateVO.setAuditStatus(SmsConstant.STATUS_AUDIT_0);
smsTemplateVO.setAuditMsg("审核通过");
//审核失败
} else if (statusCode == -1) {
smsTemplateVO.setAuditStatus(SmsConstant.STATUS_AUDIT_1);
smsTemplateVO.setAuditMsg(describeTemplateListStatus.getReviewReply());
} else {
log.info("腾讯云模板:{},审核中", describeTemplateListStatus.getTemplateId());
smsTemplateVO.setAuditStatus(SmsConstant.STATUS_AUDIT_2);
smsTemplateVO.setAuditMsg(describeTemplateListStatus.getReviewReply());
}
SmsTemplate smsTemplate = BeanConv.toBean(smsTemplateVO, SmsTemplate.class);
smsTemplate.setOtherConfig(JSONObject.toJSONString(smsTemplateVO.getOtherConfigs()));
boolean flag = smsTemplateService.saveOrUpdate(smsTemplate);
if (flag){
return smsTemplate;
}
throw new ProjectException(SmsTemplateEnum.CREATE_FAIL);
}
}
// 实例化一个请求对象,每个接口都会对应一个request对象
AddSmsTemplateRequest request = new AddSmsTemplateRequest();
//模板名称
request.setTemplateName(smsTemplateVO.getTemplateName());
//模板内容
request.setTemplateContent(smsTemplateVO.getContent());
//短信类型,0表示普通短信, 1表示营销短信。
request.setSmsType(Long.valueOf(smsTemplateVO.getSmsType()));
//是否国际/港澳台短信:
//0:表示国内短信。
//1:表示国际/港澳台短信。
request.setInternational(Long.valueOf(smsTemplateVO.getInternational()));
//模板备注,例如申请原因,使用场景等
request.setRemark(smsTemplateVO.getRemark());
// 返回的resp是一个AddSmsTemplateResponse的实例,与请求对象对应
SmsClient smsClient = tencentSmsConfig.queryClient();
AddSmsTemplateResponse response = null;
try {
response = smsClient.AddSmsTemplate(request);
} catch (TencentCloudSDKException e) {
log.error("请求添加腾讯云模板出错:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsTemplateEnum.CREATE_FAIL);
}
//受理状态
String templateId = response.getAddTemplateStatus().getTemplateId();
if (!EmptyUtil.isNullOrEmpty(templateId)) {
//受理成功
smsTemplateVO.setAcceptStatus(SmsConstant.STATUS_ACCEPT_0);
smsTemplateVO.setAcceptMsg("受理成功");
//审核中
smsTemplateVO.setAuditStatus(SmsConstant.STATUS_AUDIT_2);
smsTemplateVO.setAuditMsg("审核中");
//短信模板CODE。
//您可以使用模板CODE通过
smsTemplateVO.setTemplateCode(templateId);
//QuerySmsTemplate接口或短信服务控制台查看模板申请状态和结果。
} else {
//受理失败
smsTemplateVO.setAcceptStatus(SmsConstant.STATUS_ACCEPT_1);
smsTemplateVO.setAcceptMsg("受理失败");
}
SmsTemplate smsTemplate = BeanConv.toBean(smsTemplateVO, SmsTemplate.class);
boolean flag = smsTemplateService.save(smsTemplate);
if (flag){
return smsTemplate;
}
throw new ProjectException(SmsTemplateEnum.CREATE_FAIL);
}
@Override
public Boolean deleteSmsTemplate(SmsTemplateVO smsTemplateVO) {
// 实例化一个请求对象,每个接口都会对应一个request对象
DeleteSmsTemplateRequest request = new DeleteSmsTemplateRequest();
request.setTemplateId(Long.valueOf(smsTemplateVO.getTemplateCode()));
// 返回的resp是一个DeleteSmsTemplateResponse的实例,与请求对象对应
SmsClient smsClient = tencentSmsConfig.queryClient();
DeleteSmsTemplateResponse response = null;
try {
response = smsClient.DeleteSmsTemplate(request);
} catch (TencentCloudSDKException e) {
log.error("请求删除腾讯云模板出错:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsTemplateEnum.DELETE_FAIL);
}
return smsTemplateService.removeById(smsTemplateVO.getId());
}
@Override
public SmsTemplate modifySmsTemplate(SmsTemplateVO smsTemplateVO) {
// 实例化一个请求对象,每个接口都会对应一个request对象
ModifySmsTemplateRequest request = new ModifySmsTemplateRequest();
//模板名称
request.setTemplateName(smsTemplateVO.getTemplateName());
//模板code
request.setTemplateId(Long.valueOf(smsTemplateVO.getTemplateCode()));
//模板内容
request.setTemplateContent(smsTemplateVO.getContent());
//短信类型,0表示普通短信, 1表示营销短信。
request.setSmsType(Long.valueOf(smsTemplateVO.getSmsType()));
//是否国际/港澳台短信:
//0:表示国内短信。
//1:表示国际/港澳台短信。
request.setInternational(Long.valueOf(smsTemplateVO.getInternational()));
//模板备注,例如申请原因,使用场景等
request.setRemark(smsTemplateVO.getRemark());
// 返回的resp是一个ModifySmsTemplateResponse的实例,与请求对象对应
SmsClient smsClient = tencentSmsConfig.queryClient();
ModifySmsTemplateResponse response = null;
try {
response = smsClient.ModifySmsTemplate(request);
} catch (TencentCloudSDKException e) {
log.error("请求修改腾讯云模板出错:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsTemplateEnum.UPDATE_FAIL);
}
Long templateId = response.getModifyTemplateStatus().getTemplateId();
if (!EmptyUtil.isNullOrEmpty(templateId)) {
//受理成功
smsTemplateVO.setAcceptStatus(SmsConstant.STATUS_ACCEPT_0);
smsTemplateVO.setAcceptMsg("受理成功");
//审核中
smsTemplateVO.setAuditStatus(SmsConstant.STATUS_AUDIT_2);
smsTemplateVO.setAuditMsg("审核中");
smsTemplateVO.setTemplateCode(String.valueOf(templateId));
}else {
//受理失败
smsTemplateVO.setAcceptStatus(SmsConstant.STATUS_ACCEPT_1);
smsTemplateVO.setAcceptMsg("受理失败");
//重置审核状态
smsTemplateVO.setAuditStatus(null);
smsTemplateVO.setAuditMsg(null);
smsTemplateVO.setTemplateCode(null);
}
//本地持久化
SmsTemplate smsTemplate = BeanConv.toBean(smsTemplateVO, SmsTemplate.class);
smsTemplate.setOtherConfig(JSONObject.toJSONString(smsTemplateVO.getOtherConfigs()));
smsTemplateService.updateById(smsTemplate);
return smsTemplate;
}
private DescribeSmsTemplateListResponse query(SmsTemplateVO smsTemplateVO) {
// 实例化一个请求对象,每个接口都会对应一个request对象
DescribeSmsTemplateListRequest request = new DescribeSmsTemplateListRequest();
//模板 ID 数组。 注:默认数组最大长度100。
List<Long> templateCodes = new ArrayList<>();
templateCodes.add(Long.valueOf(smsTemplateVO.getTemplateCode()));
request.setTemplateIdSet(templateCodes.stream().toArray(Long[]::new));
request.setInternational(Long.valueOf(smsTemplateVO.getInternational()));
// 返回的resp是一个DescribeSmsTemplateListResponse的实例,与请求对象对应
SmsClient smsClient = tencentSmsConfig.queryClient();
DescribeSmsTemplateListResponse response = null;
try {
response = smsClient.DescribeSmsTemplateList(request);
} catch (TencentCloudSDKException e) {
log.error("请求查询腾讯云模板出错:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsTemplateEnum.SELECT_FAIL);
}
return response;
}
@Override
public SmsTemplate querySmsTemplate(SmsTemplateVO smsTemplateVO) {
DescribeSmsTemplateListResponse response = query(smsTemplateVO);
//处理结果
DescribeTemplateListStatus[] describeTemplateStatusSet = response.getDescribeTemplateStatusSet();
response.getDescribeTemplateStatusSet();
SmsTemplate smsTemplate = BeanConv.toBean(smsTemplateVO, SmsTemplate.class);
if (!EmptyUtil.isNullOrEmpty(describeTemplateStatusSet)){
DescribeTemplateListStatus describeTemplateListStatus = describeTemplateStatusSet[0];
Long statusCode = describeTemplateListStatus.getStatusCode();
//审核通过
if (statusCode == 0) {
smsTemplateVO.setAuditStatus(SmsConstant.STATUS_AUDIT_0);
smsTemplateVO.setAuditMsg("审核通过");
smsTemplateService.updateById(smsTemplate);
//审核失败
} else if (statusCode == -1) {
smsTemplateVO.setAuditStatus(SmsConstant.STATUS_AUDIT_1);
smsTemplateVO.setAuditMsg(describeTemplateListStatus.getReviewReply());
smsTemplateService.updateById(smsTemplate);
} else {
log.info("腾讯云模板:{},审核中", describeTemplateListStatus.getTemplateId());
}
}else {
log.warn("受理查询腾讯云签名出错");
throw new ProjectException(SmsTemplateEnum.SELECT_FAIL);
}
return smsTemplate;
}
}
@@ -0,0 +1,68 @@
package com.itheima.sfbx.sms.handler.tencent.config;
import com.itheima.sfbx.framework.commons.constant.sms.SmsConstant;
import com.itheima.sfbx.framework.commons.dto.sms.SmsChannelVO;
import com.itheima.sfbx.sms.service.ISmsChannelService;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.sms.v20210111.SmsClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.Async;
import javax.annotation.PostConstruct;
import java.util.Timer;
import java.util.TimerTask;
/**
* @ClassName TencentSmsConfig.java
* @Description 腾讯短信配置类
*/
@Slf4j
@Configuration
public class TencentSmsConfig {
@Autowired
ISmsChannelService smsChannelService;
/***
* @description 获得配置
* @return
*/
public SmsClient queryClient(){
SmsChannelVO smsChannelVO = smsChannelService.findSmsChannelByChannelLabel(SmsConstant.TENCENT_SMS);
/* 必要步骤:
* 实例化一个认证对象,入参需要传入腾讯云账户密钥对secretIdsecretKey。
* 这里采用的是从环境变量读取的方式,需要在环境变量中先设置这两个值。
* 你也可以直接在代码中写死密钥对,但是小心不要将代码复制、上传或者分享给他人,
* 以免泄露密钥对危及你的财产安全。
* CAM密匙查询: https://console.cloud.tencent.com/cam/capi*/
Credential cred = new Credential(smsChannelVO.getAccessKeyId(), smsChannelVO.getAccessKeySecret());
// 实例化一个http选项,可选,没有特殊需求可以跳过
HttpProfile httpProfile = new HttpProfile();
// 设置代理
// httpProfile.setProxyHost("真实代理ip");
// httpProfile.setProxyPort(真实代理端口);
/* SDK默认使用POST方法。
* 如果你一定要使用GET方法,可以在这里设置。GET方法无法处理一些较大的请求 */
httpProfile.setReqMethod("POST");
/* SDK有默认的超时时间,非必要请不要进行调整
* 如有需要请在代码中查阅以获取最新的默认值 */
httpProfile.setConnTimeout(60);
/* SDK会自动指定域名。通常是不需要特地指定域名的,但是如果你访问的是金融区的服务
* 则必须手动指定域名,例如sms的上海金融区域名: sms.ap-shanghai-fsi.tencentcloudapi.com */
httpProfile.setEndpoint(smsChannelVO.getDomain());
/* 非必要步骤:
* 实例化一个客户端配置对象,可以指定超时时间等配置 */
ClientProfile clientProfile = new ClientProfile();
/* SDK默认用TC3-HMAC-SHA256进行签名
* 非必要请不要修改这个字段 */
clientProfile.setSignMethod("HmacSHA256");
clientProfile.setHttpProfile(httpProfile);
/* 实例化要请求产品(以sms为例)的client对象
* 第二个参数是地域信息,可以直接填写字符串ap-guangzhou,或者引用预设的常量 */
return new SmsClient(cred, "ap-guangzhou", clientProfile);
}
}
@@ -0,0 +1,13 @@
package com.itheima.sfbx.sms.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.itheima.sfbx.sms.pojo.SmsBlacklist;
import org.apache.ibatis.annotations.Mapper;
/**
* @Description:黑名单表Mapper接口
*/
@Mapper
public interface SmsBlacklistMapper extends BaseMapper<SmsBlacklist> {
}
@@ -0,0 +1,13 @@
package com.itheima.sfbx.sms.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.itheima.sfbx.sms.pojo.SmsChannel;
import org.apache.ibatis.annotations.Mapper;
/**
* @Description:短信渠道Mapper接口
*/
@Mapper
public interface SmsChannelMapper extends BaseMapper<SmsChannel> {
}
@@ -0,0 +1,13 @@
package com.itheima.sfbx.sms.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.itheima.sfbx.sms.pojo.SmsSendRecord;
import org.apache.ibatis.annotations.Mapper;
/**
* @Description:发送记录表Mapper接口
*/
@Mapper
public interface SmsSendRecordMapper extends BaseMapper<SmsSendRecord> {
}
@@ -0,0 +1,13 @@
package com.itheima.sfbx.sms.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.itheima.sfbx.sms.pojo.SmsSign;
import org.apache.ibatis.annotations.Mapper;
/**
* @Description:短信签名Mapper接口
*/
@Mapper
public interface SmsSignMapper extends BaseMapper<SmsSign> {
}
@@ -0,0 +1,13 @@
package com.itheima.sfbx.sms.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.itheima.sfbx.sms.pojo.SmsTemplate;
import org.apache.ibatis.annotations.Mapper;
/**
* @Description:模板表Mapper接口
*/
@Mapper
public interface SmsTemplateMapper extends BaseMapper<SmsTemplate> {
}
@@ -0,0 +1,38 @@
package com.itheima.sfbx.sms.pojo;
import com.baomidou.mybatisplus.annotation.TableName;
import com.itheima.sfbx.framework.mybatisplus.basic.BasePojo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
/**
* @Description:黑名单表
*/
@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
@TableName("tab_sms_blacklist")
@ApiModel(value="SmsBlacklist对象", description="黑名单表")
public class SmsBlacklist extends BasePojo {
private static final long serialVersionUID = 1L;
@Builder
public SmsBlacklist(Long id, String dataState, String mobile,String companyNo) {
super(id, dataState);
this.mobile = mobile;
this.companyNo = companyNo;
}
@ApiModelProperty(value = "手机号码")
private String mobile;
@ApiModelProperty(value = "企业编号")
private String companyNo;
}
@@ -0,0 +1,71 @@
package com.itheima.sfbx.sms.pojo;
import com.baomidou.mybatisplus.annotation.TableName;
import com.itheima.sfbx.framework.mybatisplus.basic.BasePojo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
/**
* @Description:短信渠道
*/
@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
@TableName("tab_sms_channel")
@ApiModel(value="SmsChannel对象", description="短信渠道")
public class SmsChannel extends BasePojo {
private static final long serialVersionUID = 1L;
@Builder
public SmsChannel(Long id, String dataState, String channelName, String channelLabel, String channelType,
String domain, String accessKeyId, String accessKeySecret, String otherConfig, String level,
String remark,String companyNo) {
super(id, dataState);
this.channelName = channelName;
this.channelLabel = channelLabel;
this.channelType = channelType;
this.domain = domain;
this.accessKeyId = accessKeyId;
this.accessKeySecret = accessKeySecret;
this.otherConfig = otherConfig;
this.level = level;
this.remark = remark;
this.companyNo = companyNo;
}
@ApiModelProperty(value = "通道名称")
private String channelName;
@ApiModelProperty(value = "通道唯一标记")
private String channelLabel;
@ApiModelProperty(value = "通道类型,1:文字,2:语音,3:推送")
private String channelType;
@ApiModelProperty(value = "域名")
private String domain;
@ApiModelProperty(value = "秘钥id")
private String accessKeyId;
@ApiModelProperty(value = "秘钥值")
private String accessKeySecret;
@ApiModelProperty(value = "其他配置")
private String otherConfig;
@ApiModelProperty(value = "优先级")
private String level;
@ApiModelProperty(value = "说明")
private String remark;
@ApiModelProperty(value = "企业编号")
private String companyNo;
}
@@ -0,0 +1,100 @@
package com.itheima.sfbx.sms.pojo;
import com.baomidou.mybatisplus.annotation.TableName;
import com.itheima.sfbx.framework.mybatisplus.basic.BasePojo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
/**
* @Description:发送记录表
*/
@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
@TableName("tab_sms_send_record")
@ApiModel(value="SmsSendRecord对象", description="发送记录表")
public class SmsSendRecord extends BasePojo {
private static final long serialVersionUID = 1L;
@Builder
public SmsSendRecord(Long id, String dataState, String channelName, String channelLabel, Long templateId,
String templateNo, String templateCode, String templateType, String signCode, String signName,
String mobile, String sendContent, String sendStatus, String sendMsg, String acceptStatus,
String acceptMsg, String serialNo, String templateParams,String companyNo) {
super(id, dataState);
this.channelName = channelName;
this.channelLabel = channelLabel;
this.templateId = templateId;
this.templateNo = templateNo;
this.templateCode = templateCode;
this.templateType = templateType;
this.signCode = signCode;
this.signName = signName;
this.mobile = mobile;
this.sendContent = sendContent;
this.sendStatus = sendStatus;
this.sendMsg = sendMsg;
this.acceptStatus = acceptStatus;
this.acceptMsg = acceptMsg;
this.serialNo = serialNo;
this.templateParams = templateParams;
this.companyNo = companyNo;
}
@ApiModelProperty(value = "通道名称")
private String channelName;
@ApiModelProperty(value = "通道唯一标识")
private String channelLabel;
@ApiModelProperty(value = "模板表主键ID")
private Long templateId;
@ApiModelProperty(value = "应用模板编号:多通道编号相同则认为是一个模板多个通道公用")
private String templateNo;
@ApiModelProperty(value = "三方应用模板code")
private String templateCode;
@ApiModelProperty(value = "短信类型: 0、通知 1、营销")
private String templateType;
@ApiModelProperty(value = "三方签名code:发送短信可能用到")
private String signCode;
@ApiModelProperty(value = "签名名称")
private String signName;
@ApiModelProperty(value = "手机号码")
private String mobile;
@ApiModelProperty(value = "发生内容")
private String sendContent;
@ApiModelProperty(value = "发送状态")
private String sendStatus;
@ApiModelProperty(value = "发送返回信息")
private String sendMsg;
@ApiModelProperty(value = "是否受理成功")
private String acceptStatus;
@ApiModelProperty(value = "受理返回信息")
private String acceptMsg;
@ApiModelProperty(value = "发送流水")
private String serialNo;
@ApiModelProperty(value = "模板参数")
private String templateParams;
@ApiModelProperty(value = "企业编号")
private String companyNo;
}
@@ -0,0 +1,88 @@
package com.itheima.sfbx.sms.pojo;
import com.baomidou.mybatisplus.annotation.TableName;
import com.itheima.sfbx.framework.mybatisplus.basic.BasePojo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
/**
* @Description:短信签名
*/
@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
@TableName("tab_sms_sign")
@ApiModel(value="SmsSign对象", description="短信签名")
public class SmsSign extends BasePojo {
private static final long serialVersionUID = 1L;
@Builder
public SmsSign(Long id, String dataState, String channelLabel, String signName, String signCode, String signType,
String documentType, String international, String signPurpose, String remark, String acceptStatus,
String acceptMsg, String auditStatus, String auditMsg, String signNo,String companyNo) {
super(id, dataState);
this.channelLabel = channelLabel;
this.signName = signName;
this.signCode = signCode;
this.signType = signType;
this.documentType = documentType;
this.international = international;
this.signPurpose = signPurpose;
this.remark = remark;
this.acceptStatus = acceptStatus;
this.acceptMsg = acceptMsg;
this.auditStatus = auditStatus;
this.auditMsg = auditMsg;
this.signNo = signNo;
this.companyNo = companyNo;
}
@ApiModelProperty(value = "通道唯一标识")
private String channelLabel;
@ApiModelProperty(value = "签名名称")
private String signName;
@ApiModelProperty(value = "三方签名code:发送短信需要用到")
private String signCode;
@ApiModelProperty(value = "签名类型")
private String signType;
@ApiModelProperty(value = "证明类型")
private String documentType;
@ApiModelProperty(value = "是否国际/港澳台短信")
private String international;
@ApiModelProperty(value = "签名用途:0:自用。1:他用。")
private String signPurpose;
@ApiModelProperty(value = "短信申请说明")
private String remark;
@ApiModelProperty(value = "是否受理成功")
private String acceptStatus;
@ApiModelProperty(value = "受理返回信息")
private String acceptMsg;
@ApiModelProperty(value = "审核状态")
private String auditStatus;
@ApiModelProperty(value = "审核信息")
private String auditMsg;
@ApiModelProperty(value = "应用签名编号:签名编号相同则认为是一个签名多个通道公用")
private String signNo;
@ApiModelProperty(value = "企业编号")
private String companyNo;
}
@@ -0,0 +1,87 @@
package com.itheima.sfbx.sms.pojo;
import com.baomidou.mybatisplus.annotation.TableName;
import com.itheima.sfbx.framework.mybatisplus.basic.BasePojo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
/**
* @Description:模板表
*/
@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
@TableName("tab_sms_template")
@ApiModel(value="SmsTemplate对象", description="模板表")
public class SmsTemplate extends BasePojo {
private static final long serialVersionUID = 1L;
@Builder
public SmsTemplate(Long id, String dataState, String channelLabel, String templateName, String smsType,
String templateNo, String templateCode, String content, String otherConfig,
String international, String remark, String acceptStatus, String acceptMsg,
String auditStatus, String auditMsg,String companyNo) {
super(id, dataState);
this.channelLabel = channelLabel;
this.templateName = templateName;
this.smsType = smsType;
this.templateNo = templateNo;
this.templateCode = templateCode;
this.content = content;
this.otherConfig = otherConfig;
this.international = international;
this.remark = remark;
this.acceptStatus = acceptStatus;
this.acceptMsg = acceptMsg;
this.auditStatus = auditStatus;
this.auditMsg = auditMsg;
this.companyNo = companyNo;
}
@ApiModelProperty(value = "通道唯一标识")
private String channelLabel;
@ApiModelProperty(value = "魔板名称")
private String templateName;
@ApiModelProperty(value = "短信类型")
private String smsType;
@ApiModelProperty(value = "应用模板编号:多通道编号相同则认为是一个模板多个通道公用")
private String templateNo;
@ApiModelProperty(value = "三方应用模板code")
private String templateCode;
@ApiModelProperty(value = "模板内容")
private String content;
@ApiModelProperty(value = "变量配置")
private String otherConfig;
@ApiModelProperty(value = "是否国际/港澳台短信")
private String international;
@ApiModelProperty(value = "短信申请说明")
private String remark;
@ApiModelProperty(value = "是否受理成功")
private String acceptStatus;
@ApiModelProperty(value = "受理返回信息")
private String acceptMsg;
@ApiModelProperty(value = "审核状态")
private String auditStatus;
@ApiModelProperty(value = "审核信息")
private String auditMsg;
@ApiModelProperty(value = "企业编号")
private String companyNo;
}
@@ -0,0 +1,46 @@
package com.itheima.sfbx.sms.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.itheima.sfbx.framework.commons.dto.sms.SmsBlacklistVO;
import com.itheima.sfbx.sms.pojo.SmsBlacklist;
/**
* @Description:黑名单表 服务类
*/
public interface ISmsBlacklistService extends IService<SmsBlacklist> {
/**
* @Description 黑名单列表
* @param smsBlacklistVO 查询条件
* @param pageNum 当前页
* @param pageSize 当前页
* @return Page<SmsBlacklist>
*/
Page<SmsBlacklistVO> findSmsBlacklistVOPage(
SmsBlacklistVO smsBlacklistVO,
int pageNum,
int pageSize);
/**
* @Description 创建黑名单
* @param smsBlacklistVO 对象信息
* @return SmsBlacklist
*/
SmsBlacklistVO createSmsBlacklist(SmsBlacklistVO smsBlacklistVO);
/**
* @Description 修改黑名单
* @param smsBlacklistVO 对象信息
* @return Boolean
*/
Boolean updateSmsBlacklist(SmsBlacklistVO smsBlacklistVO);
/**
* @Description 删除黑名单
* @param checkedIds 选择的黑名单ID
* @return Boolean
*/
Boolean deleteSmsBlacklist(String[] checkedIds);
}
@@ -0,0 +1,72 @@
package com.itheima.sfbx.sms.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.itheima.sfbx.framework.commons.dto.sms.SmsChannelVO;
import com.itheima.sfbx.sms.pojo.SmsChannel;
import java.util.List;
import java.util.Set;
/**
* @Description 短信通道服务类
*/
public interface ISmsChannelService extends IService<SmsChannel> {
/***
* @description 查询通道配置
* @param channelLabel 通道标识
* @return 通道
*/
SmsChannelVO findChannelByChannelLabel(String channelLabel);
/***
* @description 查询通道配置
* @param channelLabels 通道标识
* @return 通道
*/
List<SmsChannelVO> findChannelInChannelLabel(Set<String> channelLabels);
/**
* @Description 通道列表
* @param smsChannelVO 查询条件
* @param pageNum 当前页
* @param pageSize 当前页
* @return Page<SmsChannel>
*/
Page<SmsChannelVO> findSmsChannelVOPage(SmsChannelVO smsChannelVO, int pageNum, int pageSize);
/**
* @Description 创建通道
* @param smsChannelVO 对象信息
* @return SmsChannel
*/
SmsChannelVO createSmsChannel(SmsChannelVO smsChannelVO);
/**
* @Description 修改通道
* @param smsChannelVO 对象信息
* @return Boolean
*/
SmsChannelVO updateSmsChannel(SmsChannelVO smsChannelVO);
/**
* @Description 删除通道
* @param checkedIds 选择的通道ID
* @return Boolean
*/
Boolean deleteSmsChannel(String[] checkedIds);
/***
* @description 查询通道下拉框
* @return: List<SmsChannel>
*/
List<SmsChannelVO> findSmsChannelVOList();
/**
* @Description 按渠道标识查找渠道
* @param channelLabel
* @return SmsChannelVO
*/
SmsChannelVO findSmsChannelByChannelLabel(String channelLabel);
}
@@ -0,0 +1,68 @@
package com.itheima.sfbx.sms.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.itheima.sfbx.framework.commons.dto.sms.SmsSendRecordVO;
import com.itheima.sfbx.sms.pojo.SmsSendRecord;
import java.util.List;
/**
* @Description:发送记录表 服务类
*/
public interface ISmsSendRecordService extends IService<SmsSendRecord> {
/**
* @Description 发送记录列表
* @param smsSendRecordVO 查询条件
* @param pageNum 当前页
* @param pageSize 当前页
* @return Page<SmsSendRecord>
*/
Page<SmsSendRecordVO> findSmsSendRecordVOPage(
SmsSendRecordVO smsSendRecordVO,
int pageNum,
int pageSize);
/**
* @Description 创建发送记录
* @param smsSendRecordVO 对象信息
* @return SmsSendRecord
*/
SmsSendRecordVO createSmsSendRecord(SmsSendRecordVO smsSendRecordVO);
/**
* @Description 修改发送记录
* @param smsSendRecordVO 对象信息
* @return Boolean
*/
Boolean updateSmsSendRecord(SmsSendRecordVO smsSendRecordVO);
/**
* @Description 删除发送记录
* @param checkedIds 选择的发送记录ID
* @return Boolean
*/
Boolean deleteSmsSendRecord(String[] checkedIds);
/**
* @Description 查找发送记录
* @param smsSendRecordId 选择对象信息Id
* @return SmsSendRecordVO
*/
SmsSendRecordVO findSmsSendRecordBySmsSendRecordId(Long smsSendRecordId);
/**
* @Description 重发
* @param smsSendRecordVO 重发记录
* @return SmsSendRecordVO
*/
Boolean retrySendSms(SmsSendRecordVO smsSendRecordVO);
/***
* @description 查询受理成功发送中状态的前20条短信
* @return
* @return: java.util.List<com.itheima.restkeeper.pojo.SmsSendRecord>
*/
List<SmsSendRecordVO> callBackSmsSendRecords();
}
@@ -0,0 +1,39 @@
package com.itheima.sfbx.sms.service;
import com.itheima.sfbx.framework.commons.dto.sms.SendMessageVO;
import com.itheima.sfbx.framework.commons.dto.sms.SmsSendRecordVO;
/**
* @ClassName SmsSendFace.java
* @Description 邮件发送Face接口
*/
public interface ISmsSendService {
/***
* @description 发送短信接口:削峰方式
* @param sendMessageVO 发送对象
*/
Boolean sendSmsForMq(SendMessageVO sendMessageVO) ;
/***
* @description 发送短信接口:非削峰方式
* @param sendMessageVO 发送对象
*/
Boolean sendSms(SendMessageVO sendMessageVO) ;
/***
* @description 查询短信接受情况
* @param smsSendRecordVO 发送记录
* @return
*/
Boolean querySendSms(SmsSendRecordVO smsSendRecordVO) ;
/***
* @description 重试发送
* @param smsSendRecordVO
* @return
*/
Boolean retrySendSms(SmsSendRecordVO smsSendRecordVO) ;
}
@@ -0,0 +1,89 @@
package com.itheima.sfbx.sms.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.itheima.sfbx.framework.commons.dto.sms.SmsSignVO;
import com.itheima.sfbx.sms.pojo.SmsSign;
import java.util.List;
/**
* @Description 签名服务类
*/
public interface ISmsSignService extends IService<SmsSign> {
/**
* @Description 签名列表
* @param smsSignVO 查询条件
* @param pageNum 页码
* @param pageSize 每页条数
* @return Page<SmsSignVO>
*/
Page<SmsSignVO> findSmsSignVOPage(SmsSignVO smsSignVO, int pageNum, int pageSize);
/***
* @description 申请签名
* @param smsSignVO 签名
* @return 请求成功
*/
SmsSignVO addSmsSign(SmsSignVO smsSignVO) ;
/***
* @description 删除签名
* @param checkedIds 签名ids
* @return 请求成功
*/
Boolean deleteSmsSign(String[] checkedIds);
/***
* @description 修改签名
* @param smsSignVO 签名
* @return 请求成功
*/
SmsSignVO modifySmsSign(SmsSignVO smsSignVO);
/***
* @description 禁用启用
* @param smsSignVO 签名
* @return 请求成功
*/
SmsSignVO disableEnable(SmsSignVO smsSignVO);
/***
* @description 查询签名审核状态
* @param smsSignVO 签名
* @return 请求成功
*/
SmsSignVO querySmsSign(SmsSignVO smsSignVO) ;
/***
* @description 查询签名下拉框
* @return
*/
List<SmsSignVO> findSmsSignVOList();
/***
* @description 按签名和渠道查询签名信息
* @param signName
* @param channelLabel
* @return
*/
SmsSignVO findSmsSignBySignNameAndChannelLabel(String signName, String channelLabel);
/***
* @description 按签名No和渠道查询签名信息
* @param signNo
* @param channelLabel
* @return
*/
SmsSignVO findSmsSignBySignNoAndChannelLabel(String signNo, String channelLabel);
/***
* @description 按签名Code和渠道查询签名信息
* @param signCode
* @param channelLabel
* @return
*/
SmsSignVO findSmsSignBySignCodeAndChannelLabel(String signCode, String channelLabel);
}
@@ -0,0 +1,73 @@
package com.itheima.sfbx.sms.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.itheima.sfbx.framework.commons.dto.sms.SmsTemplateVO;
import com.itheima.sfbx.sms.pojo.SmsTemplate;
import java.util.List;
/**
* @Description:模板表 服务类
*/
public interface ISmsTemplateService extends IService<SmsTemplate> {
/***
* @description 查询相同模板code审核通过模板模板
* @param templateNo 模板编号
* @return
*/
List<SmsTemplateVO> findSmsTemplateByTemplateNo(String templateNo);
/**
* @Description 模板列表
* @param smsTemplateVO 查询条件
* @param pageNum 页码
* @param pageSize 每页条数
* @return Page<SmsSignVO>
*/
Page<SmsTemplateVO> findSmsTemplateVOPage(SmsTemplateVO smsTemplateVO, int pageNum, int pageSize);
/***
* @description 按照模板名称和通道查询模板
* @param templateName 模板名称
* @param channelLabel 通道表示
* @return
*/
SmsTemplateVO findSmsTemplateByTemplateNameAndChannelLabel(String templateName, String channelLabel);
/***
* @description 申请模板
* @param smsTemplate 模板信息
* @return
*/
SmsTemplateVO addSmsTemplate(SmsTemplateVO smsTemplate) ;
/***
* @description 删除模板
* @param checkedIds 模板信息id
* @return
*/
Boolean deleteSmsTemplate(String[] checkedIds) ;
/***
* @description 修改模板
* @param smsTemplate 模板信息
* @return
*/
SmsTemplateVO modifySmsTemplate(SmsTemplateVO smsTemplate) ;
/***
* @description 查询模板审核状态
* @param smsTemplate 模板信息
* @return
*/
SmsTemplateVO querySmsTemplate(SmsTemplateVO smsTemplate) ;
/***
* @description 禁用启用
* @param smsTemplateVO 模板信息
* @return
*/
SmsTemplateVO disableEnable(SmsTemplateVO smsTemplateVO);
}
@@ -0,0 +1,107 @@
package com.itheima.sfbx.sms.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.sfbx.framework.commons.constant.sms.SmsCacheConstant;
import com.itheima.sfbx.framework.commons.dto.sms.SmsBlacklistVO;
import com.itheima.sfbx.framework.commons.enums.sms.SmsBlacklistEnum;
import com.itheima.sfbx.framework.commons.exception.ProjectException;
import com.itheima.sfbx.framework.commons.utils.BeanConv;
import com.itheima.sfbx.framework.commons.utils.EmptyUtil;
import com.itheima.sfbx.framework.commons.utils.ExceptionsUtil;
import com.itheima.sfbx.sms.mapper.SmsBlacklistMapper;
import com.itheima.sfbx.sms.pojo.SmsBlacklist;
import com.itheima.sfbx.sms.service.ISmsBlacklistService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @Description:黑名单表 服务实现类
*/
@Slf4j
@Service
public class SmsBlacklistServiceImpl extends ServiceImpl<SmsBlacklistMapper, SmsBlacklist> implements ISmsBlacklistService {
@Override
@Cacheable(value = SmsCacheConstant.PAGE_BLACKLIST,key ="#pageNum+'-'+#pageSize+'-'+#smsBlacklistVO.hashCode()")
public Page<SmsBlacklistVO> findSmsBlacklistVOPage(SmsBlacklistVO smsBlacklistVO, int pageNum, int pageSize) {
try {
Page<SmsBlacklist> page = new Page<>(pageNum,pageSize);
QueryWrapper<SmsBlacklist> queryWrapper = new QueryWrapper<>();
if (!EmptyUtil.isNullOrEmpty(smsBlacklistVO.getMobile())) {
queryWrapper.lambda().eq(SmsBlacklist::getMobile,smsBlacklistVO.getMobile());
}
if (!EmptyUtil.isNullOrEmpty(smsBlacklistVO.getDataState())) {
queryWrapper.lambda().eq(SmsBlacklist::getDataState,smsBlacklistVO.getDataState());
}
queryWrapper.lambda().orderByAsc(SmsBlacklist::getCreateTime);
return BeanConv.toPage(page(page, queryWrapper),SmsBlacklistVO.class);
} catch (Exception e) {
log.error("查询黑名单列表异常:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsBlacklistEnum.PAGE_FAIL);
}
}
@Override
@Transactional
@Caching(evict = {@CacheEvict(value = SmsCacheConstant.PAGE_BLACKLIST,allEntries = true)},
put={@CachePut(value =SmsCacheConstant.PREFIX_BLACKLIST,key = "#result.id")})
public SmsBlacklistVO createSmsBlacklist(SmsBlacklistVO smsBlacklistVO) {
try {
SmsBlacklist smsBlacklist = BeanConv.toBean(smsBlacklistVO, SmsBlacklist.class);
boolean flag = save(smsBlacklist);
if (flag){
return BeanConv.toBean(smsBlacklist,SmsBlacklistVO.class);
}
return null;
} catch (Exception e) {
log.error("保存黑名单异常:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsBlacklistEnum.CREATE_FAIL);
}
}
@Override
@Transactional
@Caching(evict = {@CacheEvict(value = SmsCacheConstant.PAGE_BLACKLIST,allEntries = true),
@CacheEvict(value =SmsCacheConstant.PREFIX_BLACKLIST,key = "#smsBlacklistVO.id")})
public Boolean updateSmsBlacklist(SmsBlacklistVO smsBlacklistVO) {
try {
SmsBlacklist smsBlacklist = BeanConv.toBean(smsBlacklistVO, SmsBlacklist.class);
return updateById(smsBlacklist);
} catch (Exception e) {
log.error("保存黑名单异常:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsBlacklistEnum.UPDATE_FAIL);
}
}
@Override
@Transactional
@Caching(evict = {@CacheEvict(value = SmsCacheConstant.PAGE_BLACKLIST,allEntries = true),
@CacheEvict(value = SmsCacheConstant.PREFIX_BLACKLIST,allEntries = true)})
public Boolean deleteSmsBlacklist(String[] checkedIds) {
try {
List<String> ids = Arrays.asList(checkedIds);
List<Long> idsLong = new ArrayList<>();
ids.forEach(n->{
idsLong.add(Long.valueOf(n));
});
return removeByIds(idsLong);
} catch (Exception e) {
log.error("删除黑名单异常:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsBlacklistEnum.DELETE_FAIL);
}
}
}
@@ -0,0 +1,190 @@
package com.itheima.sfbx.sms.service.impl;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.sfbx.framework.commons.constant.basic.SuperConstant;
import com.itheima.sfbx.framework.commons.constant.sms.SmsCacheConstant;
import com.itheima.sfbx.framework.commons.dto.basic.OtherConfigVO;
import com.itheima.sfbx.framework.commons.dto.sms.SmsChannelVO;
import com.itheima.sfbx.framework.commons.enums.sms.SmsChannelEnum;
import com.itheima.sfbx.framework.commons.exception.ProjectException;
import com.itheima.sfbx.framework.commons.utils.BeanConv;
import com.itheima.sfbx.framework.commons.utils.EmptyUtil;
import com.itheima.sfbx.framework.commons.utils.ExceptionsUtil;
import com.itheima.sfbx.sms.handler.baidu.config.BaiduSmsConfig;
import com.itheima.sfbx.sms.handler.aliyun.config.AliyunSmsConfig;
import com.itheima.sfbx.sms.handler.tencent.config.TencentSmsConfig;
import com.itheima.sfbx.sms.mapper.SmsChannelMapper;
import com.itheima.sfbx.sms.pojo.SmsChannel;
import com.itheima.sfbx.sms.service.ISmsChannelService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
/**
* @Description 服务实现类
*/
@Slf4j
@Service
public class SmsChannelServiceImpl extends ServiceImpl<SmsChannelMapper, SmsChannel> implements ISmsChannelService {
@Override
@Cacheable(value = SmsCacheConstant.PAGE_CHANNEL,key ="#pageNum+'-'+#pageSize+'-'+#smsChannelVO.hashCode()")
public Page<SmsChannelVO> findSmsChannelVOPage(SmsChannelVO smsChannelVO, int pageNum, int pageSize) {
try {
Page<SmsChannel> page = new Page<>(pageNum,pageSize);
QueryWrapper<SmsChannel> queryWrapper = new QueryWrapper<>();
if (!EmptyUtil.isNullOrEmpty(smsChannelVO.getChannelLabel())) {
queryWrapper.lambda().eq(SmsChannel::getChannelLabel,smsChannelVO.getChannelLabel());
}
if (!EmptyUtil.isNullOrEmpty(smsChannelVO.getChannelName())) {
queryWrapper.lambda().likeRight(SmsChannel::getChannelName,smsChannelVO.getChannelName());
}
if (!EmptyUtil.isNullOrEmpty(smsChannelVO.getDataState())) {
queryWrapper.lambda().eq(SmsChannel::getDataState,smsChannelVO.getDataState());
}
queryWrapper.lambda().orderByAsc(SmsChannel::getCreateTime);
Page<SmsChannelVO> pageVo = BeanConv.toPage(page(page, queryWrapper),SmsChannelVO.class);
//结果集转换
List<SmsChannelVO> smsChannelVOs =pageVo.getRecords();
if (!EmptyUtil.isNullOrEmpty(smsChannelVOs)){
smsChannelVOs.forEach(n->{
List <OtherConfigVO> list = JSONArray.parseArray(n.getOtherConfig(),OtherConfigVO.class);
n.setOtherConfigs(list);
});
}
return pageVo;
} catch (Exception e) {
log.error("查询通道列表异常:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsChannelEnum.PAGE_FAIL);
}
}
@Override
@Transactional
@Caching(evict = {@CacheEvict(value = SmsCacheConstant.PAGE_CHANNEL,allEntries = true),
@CacheEvict(value = SmsCacheConstant.CHANNEL_LIST,allEntries = true),
@CacheEvict(value = SmsCacheConstant.CHANNEL_LABEL,key = "#smsChannelVO.channelLabel")},
put={@CachePut(value =SmsCacheConstant.PREFIX_CHANNEL,key = "#result.channelLabel")})
public SmsChannelVO createSmsChannel(SmsChannelVO smsChannelVO) {
try {
SmsChannel smsChannel = BeanConv.toBean(smsChannelVO, SmsChannel.class);
smsChannel.setOtherConfig(JSONObject.toJSONString(smsChannelVO.getOtherConfigs()));
boolean flag = save(smsChannel);
return BeanConv.toBean( smsChannel, SmsChannelVO.class);
} catch (Exception e) {
log.error("保存通道异常:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsChannelEnum.CREATE_FAIL);
}
}
@Override
@Transactional
@Caching(evict = {@CacheEvict(value = SmsCacheConstant.PAGE_CHANNEL,allEntries = true),
@CacheEvict(value = SmsCacheConstant.CHANNEL_LIST,allEntries = true),
@CacheEvict(value = SmsCacheConstant.CHANNEL_LABEL,key = "#smsChannelVO.channelLabel"),
@CacheEvict(value = SmsCacheConstant.PREFIX_CHANNEL,key = "#smsChannelVO.channelLabel")})
public SmsChannelVO updateSmsChannel(SmsChannelVO smsChannelVO) {
try {
SmsChannel smsChannel = BeanConv.toBean(smsChannelVO, SmsChannel.class);
smsChannel.setOtherConfig(JSONObject.toJSONString(smsChannelVO.getOtherConfigs()));
updateById(smsChannel);
return BeanConv.toBean(smsChannel,smsChannelVO.getClass());
} catch (Exception e) {
log.error("保存通道异常:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsChannelEnum.UPDATE_FAIL);
}
}
@Override
public SmsChannelVO findChannelByChannelLabel(String channelLabel) {
try {
QueryWrapper<SmsChannel> queryWrapper = new QueryWrapper<>();
queryWrapper.lambda()
.eq(SmsChannel::getDataState, SuperConstant.DATA_STATE_0)
.eq(SmsChannel::getChannelLabel,channelLabel);
return BeanConv.toBean(getOne(queryWrapper),SmsChannelVO.class);
} catch (Exception e) {
log.error("保存通道异常:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsChannelEnum.UPDATE_FAIL);
}
}
@Override
@Cacheable(value = SmsCacheConstant.CHANNEL_LIST,key = "#channelLabels.hashCode()")
public List<SmsChannelVO> findChannelInChannelLabel(Set<String> channelLabels) {
try {
QueryWrapper<SmsChannel> queryWrapper = new QueryWrapper<>();
queryWrapper.lambda().eq(SmsChannel::getDataState, SuperConstant.DATA_STATE_0)
.in(SmsChannel::getChannelLabel,channelLabels);
return BeanConv.toBeanList(list(queryWrapper),SmsChannelVO.class);
} catch (Exception e) {
log.error("保存通道异常:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsChannelEnum.UPDATE_FAIL);
}
}
@Override
@Transactional
@Caching(evict = {@CacheEvict(value = SmsCacheConstant.PAGE_CHANNEL,allEntries = true),
@CacheEvict(value = SmsCacheConstant.CHANNEL_LIST,allEntries = true),
@CacheEvict(value = SmsCacheConstant.CHANNEL_LABEL,allEntries = true),
@CacheEvict(value = SmsCacheConstant.PREFIX_CHANNEL,allEntries = true)})
public Boolean deleteSmsChannel(String[] checkedIds) {
try {
List<String> ids = Arrays.asList(checkedIds);
for (String id : ids) {
SmsChannel smsChannel = getById(id);
removeById(id);
}
return true;
} catch (Exception e) {
log.error("删除通道异常:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsChannelEnum.DELETE_FAIL);
}
}
@Override
@Cacheable(value =SmsCacheConstant.CHANNEL_LIST)
public List<SmsChannelVO> findSmsChannelVOList() {
try {
QueryWrapper<SmsChannel> queryWrapper = new QueryWrapper<>();
queryWrapper.lambda().eq(SmsChannel::getDataState, SuperConstant.DATA_STATE_0);
return BeanConv.toBeanList(list(queryWrapper),SmsChannelVO.class);
} catch (Exception e) {
log.error("查找所有通道异常:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsChannelEnum.SELECT_FAIL);
}
}
@Override
@Cacheable(value =SmsCacheConstant.CHANNEL_LABEL,key = "#channelLabel")
public SmsChannelVO findSmsChannelByChannelLabel(String channelLabel) {
try {
QueryWrapper<SmsChannel> queryWrapper = new QueryWrapper<>();
queryWrapper.lambda().eq(SmsChannel::getDataState, SuperConstant.DATA_STATE_0)
.eq(SmsChannel::getChannelLabel,channelLabel);
return BeanConv.toBean(getOne(queryWrapper),SmsChannelVO.class);
} catch (Exception e) {
log.error("查找通道异常:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsChannelEnum.SELECT_FAIL);
}
}
}
@@ -0,0 +1,164 @@
package com.itheima.sfbx.sms.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.sfbx.framework.commons.constant.sms.SmsCacheConstant;
import com.itheima.sfbx.framework.commons.constant.sms.SmsConstant;
import com.itheima.sfbx.framework.commons.dto.sms.SmsSendRecordVO;
import com.itheima.sfbx.framework.commons.enums.sms.SmsSendRecordEnum;
import com.itheima.sfbx.framework.commons.exception.ProjectException;
import com.itheima.sfbx.framework.commons.utils.BeanConv;
import com.itheima.sfbx.framework.commons.utils.EmptyUtil;
import com.itheima.sfbx.framework.commons.utils.ExceptionsUtil;
import com.itheima.sfbx.sms.adapter.SmsSendAdapter;
import com.itheima.sfbx.sms.mapper.SmsSendRecordMapper;
import com.itheima.sfbx.sms.service.ISmsSendRecordService;
import com.itheima.sfbx.sms.pojo.SmsSendRecord;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @Description:发送记录表 服务实现类
*/
@Slf4j
@Service
public class SmsSendRecordServiceImpl extends ServiceImpl<SmsSendRecordMapper, SmsSendRecord> implements ISmsSendRecordService {
@Autowired
SmsSendAdapter smsSendAdapter;
@Override
@Cacheable(value = SmsCacheConstant.PAGE_SEND_RECORD,key ="#pageNum+'-'+#pageSize+'-'+#smsSendRecordVO.hashCode()")
public Page<SmsSendRecordVO> findSmsSendRecordVOPage(SmsSendRecordVO smsSendRecordVO, int pageNum, int pageSize) {
try {
Page<SmsSendRecord> page = new Page<>(pageNum,pageSize);
QueryWrapper<SmsSendRecord> queryWrapper = new QueryWrapper<>();
if (!EmptyUtil.isNullOrEmpty(smsSendRecordVO.getMobile())) {
queryWrapper.lambda().eq(SmsSendRecord::getMobile,smsSendRecordVO.getMobile());
}
if (!EmptyUtil.isNullOrEmpty(smsSendRecordVO.getChannelLabel())) {
queryWrapper.lambda().eq(SmsSendRecord::getChannelLabel,smsSendRecordVO.getChannelLabel());
}
if (!EmptyUtil.isNullOrEmpty(smsSendRecordVO.getAcceptStatus())) {
queryWrapper.lambda().eq(SmsSendRecord::getAcceptStatus,smsSendRecordVO.getAcceptStatus());
}
if (!EmptyUtil.isNullOrEmpty(smsSendRecordVO.getSendStatus())) {
queryWrapper.lambda().eq(SmsSendRecord::getSendStatus,smsSendRecordVO.getSendStatus());
}
if (!EmptyUtil.isNullOrEmpty(smsSendRecordVO.getDataState())) {
queryWrapper.lambda().eq(SmsSendRecord::getDataState,smsSendRecordVO.getDataState());
}
queryWrapper.lambda().orderByDesc(SmsSendRecord::getCreateTime);
return BeanConv.toPage(page(page, queryWrapper),SmsSendRecordVO.class);
} catch (Exception e) {
log.error("查询发送记录列表异常:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsSendRecordEnum.PAGE_FAIL);
}
}
@Override
@Transactional
@Caching(evict = {@CacheEvict(value = SmsCacheConstant.PAGE_SEND_RECORD,allEntries = true)},
put={@CachePut(value =SmsCacheConstant.PREFIX_SEND_RECORD,key = "#result.id")})
public SmsSendRecordVO createSmsSendRecord(SmsSendRecordVO smsSendRecordVO) {
try {
SmsSendRecord smsSendRecord = BeanConv.toBean(smsSendRecordVO, SmsSendRecord.class);
boolean flag = save(smsSendRecord);
if (flag){
return BeanConv.toBean(smsSendRecord, SmsSendRecordVO.class);
}
} catch (Exception e) {
log.error("保存发送记录异常:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsSendRecordEnum.CREATE_FAIL);
}
return null;
}
@Override
@Transactional
@Caching(evict = {@CacheEvict(value = SmsCacheConstant.PAGE_SEND_RECORD,allEntries = true),
@CacheEvict(value = SmsCacheConstant.PREFIX_SEND_RECORD,allEntries = true)})
public Boolean updateSmsSendRecord(SmsSendRecordVO smsSendRecordVO) {
try {
SmsSendRecord smsSendRecord = BeanConv.toBean(smsSendRecordVO, SmsSendRecord.class);
return updateById(smsSendRecord);
} catch (Exception e) {
log.error("保存发送记录异常:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsSendRecordEnum.CREATE_FAIL);
}
}
@Override
@Transactional
@Caching(evict = {@CacheEvict(value = SmsCacheConstant.PAGE_SEND_RECORD,allEntries = true),
@CacheEvict(value = SmsCacheConstant.PREFIX_SEND_RECORD,allEntries = true)})
public Boolean deleteSmsSendRecord(String[] checkedIds) {
try {
List<String> ids = Arrays.asList(checkedIds);
List<Long> idsLong = new ArrayList<>();
ids.forEach(n->{
idsLong.add(Long.valueOf(n));
});
return removeByIds(idsLong);
} catch (Exception e) {
log.error("删除发送记录异常:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsSendRecordEnum.DELETE_FAIL);
}
}
@Override
@Cacheable(value = SmsCacheConstant.PREFIX_SEND_RECORD,key = "#smsSendRecordId")
public SmsSendRecordVO findSmsSendRecordBySmsSendRecordId(Long smsSendRecordId)throws ProjectException {
try {
SmsSendRecord smsSendRecord = getById(smsSendRecordId);
if (!EmptyUtil.isNullOrEmpty(smsSendRecord)){
return BeanConv.toBean(smsSendRecord,SmsSendRecordVO.class);
}
return null;
} catch (Exception e) {
log.error("查找发送记录异常:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsSendRecordEnum.SELECT_FAIL);
}
}
@Override
@CacheEvict(value = SmsCacheConstant.PREFIX_SEND_RECORD,key = "#smsSendRecordVO.id")
@Transactional
public Boolean retrySendSms(SmsSendRecordVO smsSendRecordVO) {
try {
return smsSendAdapter.retrySendSms(BeanConv.toBean(smsSendRecordVO,SmsSendRecord.class));
} catch (Exception e) {
log.error("查找发送记录异常:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsSendRecordEnum.SEND_RECORD_FAIL);
}
}
@Override
public List<SmsSendRecordVO> callBackSmsSendRecords() {
try {
QueryWrapper<SmsSendRecord> queryWrapper = new QueryWrapper<>();
queryWrapper.lambda().eq(SmsSendRecord::getAcceptStatus, SmsConstant.STATUS_ACCEPT_0)
.eq(SmsSendRecord::getSendStatus, SmsConstant.STATUS_SEND_2)
.last("limit 0 , 20");;
return BeanConv.toBeanList(list(queryWrapper),SmsSendRecordVO.class);
} catch (Exception e) {
log.error("查找发送记录异常:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsSendRecordEnum.SEND_RECORD_FAIL);
}
}
}
@@ -0,0 +1,90 @@
package com.itheima.sfbx.sms.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
import com.itheima.sfbx.framework.commons.dto.sms.SendMessageVO;
import com.itheima.sfbx.framework.commons.dto.sms.SmsSendRecordVO;
import com.itheima.sfbx.framework.commons.utils.BeanConv;
import com.itheima.sfbx.framework.rabbitmq.pojo.MqMessage;
import com.itheima.sfbx.framework.rabbitmq.source.SmsSource;
import com.itheima.sfbx.sms.adapter.SmsSendAdapter;
import com.itheima.sfbx.sms.pojo.SmsSendRecord;
import com.itheima.sfbx.sms.service.ISmsSendService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.sql.Timestamp;
import java.time.LocalDateTime;
/**
* @ClassName SmsSendFace.java
* @Description dubbo短信发送接口
*/
@Slf4j
@Component
public class SmsSendServiceImpl implements ISmsSendService {
@Autowired
SmsSendAdapter smsSendAdapter;
@Autowired
SmsSource smsSource;
@Autowired
IdentifierGenerator identifierGenerator;
@Value("${spring.application.name}")
private String applicationName;
@Value("${server.port}")
private String port;
@Override
public Boolean sendSmsForMq(SendMessageVO sendMessageVO) {
String sendMessageVOstring = JSONObject.toJSONString(sendMessageVO);
//发送队列信息
MqMessage mqMessage = MqMessage.builder()
.id((Long)identifierGenerator.nextId(sendMessageVO))
.title("sms-message")
.content(sendMessageVOstring)
.messageType("sms-request")
.produceTime(Timestamp.valueOf(LocalDateTime.now()))
.sender(applicationName+":"+port)
.build();
Message<MqMessage> message = MessageBuilder.withPayload(mqMessage)
.setHeader("type", "sms-key")
.build();
Boolean flag = smsSource.smsOutput().send(message);
log.info("发送:{}结果:{}",mqMessage.toString(),flag);
return flag;
}
@Override
@Transactional
public Boolean sendSms(SendMessageVO sendMessageVO) {
return smsSendAdapter.SendSms(sendMessageVO.getTemplateNo(),
sendMessageVO.getSginNo(),
sendMessageVO.getLoadBalancerType(),
sendMessageVO.getMobiles(),
sendMessageVO.getTemplateParam());
}
@Override
@Transactional
public Boolean querySendSms(SmsSendRecordVO smsSendRecordVO) {
SmsSendRecord smsSendRecord = BeanConv.toBean(smsSendRecordVO, SmsSendRecord.class);
return smsSendAdapter.querySendSms(smsSendRecord);
}
@Override
@Transactional
public Boolean retrySendSms(SmsSendRecordVO smsSendRecordVO) {
SmsSendRecord smsSendRecord = BeanConv.toBean(smsSendRecordVO, SmsSendRecord.class);
return smsSendAdapter.retrySendSms(smsSendRecord);
}
}
@@ -0,0 +1,284 @@
package com.itheima.sfbx.sms.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.itheima.sfbx.file.feign.FileBusinessFeign;
import com.itheima.sfbx.file.feign.FileDownLoadFeign;
import com.itheima.sfbx.framework.commons.constant.basic.SuperConstant;
import com.itheima.sfbx.framework.commons.constant.sms.SmsCacheConstant;
import com.itheima.sfbx.framework.commons.constant.sms.SmsConstant;
import com.itheima.sfbx.framework.commons.dto.file.FileVO;
import com.itheima.sfbx.framework.commons.dto.sms.SmsSignVO;
import com.itheima.sfbx.framework.commons.enums.sms.SmsSignEnum;
import com.itheima.sfbx.framework.commons.exception.ProjectException;
import com.itheima.sfbx.framework.commons.utils.BeanConv;
import com.itheima.sfbx.framework.commons.utils.EmptyUtil;
import com.itheima.sfbx.framework.commons.utils.ExceptionsUtil;
import com.itheima.sfbx.sms.adapter.SmsSignAdapter;
import com.itheima.sfbx.sms.mapper.SmsSignMapper;
import com.itheima.sfbx.sms.pojo.SmsSign;
import com.itheima.sfbx.sms.service.ISmsSignService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;
/**
* @Description 签名服务实现类
*/
@Slf4j
@Service
public class SmsSignServiceImpl extends ServiceImpl<SmsSignMapper, SmsSign> implements ISmsSignService {
@Autowired
FileBusinessFeign fileBusinessFeign;
@Autowired
FileDownLoadFeign fileDownLoadFeign;
@Autowired
SmsSignAdapter smsSignAdapter;
private QueryWrapper<SmsSign> queryWrapper(SmsSignVO smsSignVO){
//构建查询条件
QueryWrapper<SmsSign> queryWrapper = new QueryWrapper<>();
//按签名名称查询
if (!EmptyUtil.isNullOrEmpty(smsSignVO.getSignName())) {
queryWrapper.lambda().likeRight(SmsSign::getSignName,smsSignVO.getSignName());
}
//按签名通道查询
if (!EmptyUtil.isNullOrEmpty(smsSignVO.getChannelLabel())) {
queryWrapper.lambda().eq(SmsSign::getChannelLabel,smsSignVO.getChannelLabel());
}
//按签名发送状态查询
if (!EmptyUtil.isNullOrEmpty(smsSignVO.getAcceptStatus())) {
queryWrapper.lambda().eq(SmsSign::getAcceptStatus,smsSignVO.getAcceptStatus());
}
//按签名审核状态查询
if (!EmptyUtil.isNullOrEmpty(smsSignVO.getAuditStatus())) {
queryWrapper.lambda().eq(SmsSign::getAuditStatus,smsSignVO.getAuditStatus());
}
//按签名状态查询
if (!EmptyUtil.isNullOrEmpty(smsSignVO.getDataState())) {
queryWrapper.lambda().eq(SmsSign::getDataState,smsSignVO.getDataState());
}
//按创建时间降序
queryWrapper.lambda().orderByDesc(SmsSign::getCreateTime);
return queryWrapper;
}
@Override
@Cacheable(value = SmsCacheConstant.PAGE_SIGN,key ="#pageNum+'-'+#pageSize+'-'+#smsSignVO.hashCode()")
public Page<SmsSignVO> findSmsSignVOPage(SmsSignVO smsSignVO, int pageNum, int pageSize) {
//构建分页对象
Page<SmsSign> page = new Page<>(pageNum,pageSize);
QueryWrapper<SmsSign> queryWrapper = this.queryWrapper(smsSignVO);
//执行分页查询
Page<SmsSignVO> pageVO = BeanConv.toPage(page(page, queryWrapper),SmsSignVO.class);
if (!EmptyUtil.isNullOrEmpty(pageVO)&&!EmptyUtil.isNullOrEmpty(pageVO.getRecords())){
List<Long> SmsSignIds = pageVO.getRecords().stream().map(SmsSignVO::getId).collect(Collectors.toList());
List<FileVO> fileVos = fileBusinessFeign.findInBusinessIds(Lists.newArrayList(SmsSignIds));
pageVO.getRecords().forEach(n->{
LinkedList<FileVO> list = Lists.newLinkedList();
fileVos.forEach(flieVo->{
if (flieVo.getBusinessId().equals(n.getId()))
list.add(flieVo);
});
n.setFileVOs(list);
});
}
return pageVO;
}
@Override
@Transactional
@Caching(evict = {@CacheEvict(value = SmsCacheConstant.PAGE_SIGN,allEntries = true),
@CacheEvict(value = SmsCacheConstant.SIGN_LIST,allEntries = true)},
put={@CachePut(value =SmsCacheConstant.PREFIX_SIGN,key = "#result.id")})
public SmsSignVO addSmsSign(SmsSignVO smsSignVO) throws ProjectException{
try {
//获取证明资料相关
LinkedList<FileVO> fileVos = smsSignVO.getFileVOs();
StringBuffer base64Image =new StringBuffer();
StringBuffer suffix =new StringBuffer();
for (FileVO fileVO : fileVos) {
FileVO fileVOHandler = fileDownLoadFeign.downLoad(fileVO.getId());
if (!EmptyUtil.isNullOrEmpty(fileVOHandler)){
base64Image.append(fileVOHandler.getBase64Image()).append("@");
suffix.append(fileVOHandler.getSuffix()).append("@");
}
}
//填充签名文件属性
if (!EmptyUtil.isNullOrEmpty(base64Image)&&!EmptyUtil.isNullOrEmpty(suffix)){
String base64ImageString = base64Image.toString();
String suffixString = suffix.toString();
smsSignVO.setProofImage(base64ImageString.substring(0,base64ImageString.length()-1));
smsSignVO.setProofType(suffixString.substring(0,suffixString.length()-1));
}
//调用签名三方API
SmsSignVO smsSignVOHandler = smsSignAdapter.addSmsSign(smsSignVO);
//签名业务附件关联
if (!EmptyUtil.isNullOrEmpty(smsSignVOHandler)){
List<FileVO> fileVosHandler = fileVos.stream()
.map(n -> FileVO.builder().id(n.getId()).businessId(smsSignVOHandler.getId()).build())
.collect(Collectors.toList());
fileBusinessFeign.bindBatchFile(Lists.newArrayList(fileVosHandler));
}
return smsSignVOHandler;
} catch (Exception e) {
log.error("添加签名异常:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsSignEnum.CREATE_FAIL);
}
}
@Override
@Transactional
@Caching(evict = {@CacheEvict(value = SmsCacheConstant.PAGE_SIGN,allEntries = true),
@CacheEvict(value = SmsCacheConstant.SIGN_LIST,allEntries = true),
@CacheEvict(value = SmsCacheConstant.PREFIX_SIGN,allEntries = true)})
public Boolean deleteSmsSign(String[] checkedIds)throws ProjectException {
try {
Boolean flag = smsSignAdapter.deleteSmsSign(checkedIds);
if (flag){
List<String> list = Arrays.asList(checkedIds);
ArrayList<Long> listHandler = Lists.newArrayList();
list.forEach(n->{listHandler.add(Long.valueOf(n)); });
fileBusinessFeign.deleteByBusinessIds(listHandler);
}
return flag;
} catch (Exception e) {
log.error("删除签名异常:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsSignEnum.DELETE_FAIL);
}
}
@Override
@Transactional
@Caching(evict = {@CacheEvict(value = SmsCacheConstant.PAGE_SIGN,allEntries = true),
@CacheEvict(value = SmsCacheConstant.SIGN_LIST,allEntries = true),
@CacheEvict(value = SmsCacheConstant.PREFIX_SIGN,key = "#smsSignVO.getId()")})
public SmsSignVO modifySmsSign(SmsSignVO smsSignVO)throws ProjectException {
try {
//获取证明资料相关
LinkedList<FileVO> fileVos = smsSignVO.getFileVOs();
StringBuffer base64Image =new StringBuffer();
StringBuffer suffix =new StringBuffer();
for (FileVO fileVO : fileVos) {
FileVO fileVOHandler = fileDownLoadFeign.downLoad(fileVO.getId());
if (!EmptyUtil.isNullOrEmpty(fileVOHandler)){
base64Image.append(fileVOHandler.getBase64Image()).append("@");
suffix.append(fileVOHandler.getSuffix()).append("@");
}
}
//填充签名文件属性
if (!EmptyUtil.isNullOrEmpty(base64Image)&&!EmptyUtil.isNullOrEmpty(suffix)){
String base64ImageString = base64Image.toString();
String suffixString = suffix.toString();
smsSignVO.setProofImage(base64ImageString.substring(0,base64ImageString.length()-1));
smsSignVO.setProofType(suffixString.substring(0,suffixString.length()-1));
}
//调用签名三方API
SmsSignVO smsSignVOHandler = smsSignAdapter.modifySmsSign(smsSignVO);
//替换签名附件相关
if (!EmptyUtil.isNullOrEmpty(smsSignVOHandler)){
fileBusinessFeign.replaceBindBatchFile(Lists.newArrayList(fileVos));
}
return smsSignVO;
} catch (Exception e) {
log.error("修改签名异常:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsSignEnum.UPDATE_FAIL);
}
}
@Override
public SmsSignVO disableEnable(SmsSignVO smsSignVO) {
try {
SmsSign smsSign = BeanConv.toBean(smsSignVO, SmsSign.class);
updateById(smsSign);
return BeanConv.toBean(smsSign, SmsSignVO.class);
} catch (Exception e) {
log.error("修改签名状态异常:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsSignEnum.UPDATE_FAIL);
}
}
@Override
@Cacheable(value =SmsCacheConstant.PREFIX_SIGN,key = "#smsSignVO.id")
@Transactional
public SmsSignVO querySmsSign(SmsSignVO smsSignVO) throws ProjectException{
try {
return smsSignAdapter.querySmsSign(smsSignVO);
} catch (Exception e) {
log.error("查询签名状态异常:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsSignEnum.SELECT_FAIL);
}
}
@Override
@Cacheable(value =SmsCacheConstant.SIGN_LIST)
public List<SmsSignVO> findSmsSignVOList() {
try {
QueryWrapper<SmsSign> queryWrapper = new QueryWrapper<>();
queryWrapper.lambda().eq(SmsSign::getDataState, SuperConstant.DATA_STATE_0);
return BeanConv.toBeanList(list(queryWrapper),SmsSignVO.class);
} catch (Exception e) {
log.error("查找所有签名异常:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsSignEnum.SELECT_FAIL);
}
}
@Override
public SmsSignVO findSmsSignBySignNameAndChannelLabel(String signName, String channelLabel) {
try {
QueryWrapper<SmsSign> queryWrapper = new QueryWrapper<>();
queryWrapper.lambda().eq(SmsSign::getSignName, signName)
.eq(SmsSign::getChannelLabel, channelLabel);
return BeanConv.toBean(getOne(queryWrapper),SmsSignVO.class);
} catch (Exception e) {
log.error("查找签名异常:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsSignEnum.SELECT_FAIL);
}
}
@Override
public SmsSignVO findSmsSignBySignNoAndChannelLabel(String signNo, String channelLabel) {
try {
QueryWrapper<SmsSign> queryWrapper = new QueryWrapper<>();
queryWrapper.lambda().eq(SmsSign::getSignNo, signNo)
.eq(SmsSign::getChannelLabel, channelLabel)
.eq(SmsSign::getAuditStatus, SmsConstant.STATUS_AUDIT_0);
return BeanConv.toBean(getOne(queryWrapper),SmsSignVO.class);
} catch (Exception e) {
log.error("查找签名异常:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsSignEnum.SELECT_FAIL);
}
}
@Override
public SmsSignVO findSmsSignBySignCodeAndChannelLabel(String signCode, String channelLabel) {
try {
QueryWrapper<SmsSign> queryWrapper = new QueryWrapper<>();
queryWrapper.lambda().eq(SmsSign::getSignCode, signCode)
.eq(SmsSign::getChannelLabel, channelLabel)
.eq(SmsSign::getAuditStatus,SmsConstant.STATUS_AUDIT_0);
return BeanConv.toBean(getOne(queryWrapper),SmsSignVO.class);
} catch (Exception e) {
log.error("查找签名异常:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsSignEnum.SELECT_FAIL);
}
}
}
@@ -0,0 +1,171 @@
package com.itheima.sfbx.sms.service.impl;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.sfbx.framework.commons.constant.basic.SuperConstant;
import com.itheima.sfbx.framework.commons.constant.sms.SmsCacheConstant;
import com.itheima.sfbx.framework.commons.constant.sms.SmsConstant;
import com.itheima.sfbx.framework.commons.dto.basic.OtherConfigVO;
import com.itheima.sfbx.framework.commons.dto.sms.SmsTemplateVO;
import com.itheima.sfbx.framework.commons.enums.sms.SmsSignEnum;
import com.itheima.sfbx.framework.commons.enums.sms.SmsTemplateEnum;
import com.itheima.sfbx.framework.commons.exception.ProjectException;
import com.itheima.sfbx.framework.commons.utils.BeanConv;
import com.itheima.sfbx.framework.commons.utils.EmptyUtil;
import com.itheima.sfbx.framework.commons.utils.ExceptionsUtil;
import com.itheima.sfbx.sms.adapter.SmsTemplateAdapter;
import com.itheima.sfbx.sms.mapper.SmsTemplateMapper;
import com.itheima.sfbx.sms.pojo.SmsTemplate;
import com.itheima.sfbx.sms.service.ISmsTemplateService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* @Description:模板表 服务实现类
*/
@Slf4j
@Service
public class SmsTemplateServiceImpl extends ServiceImpl<SmsTemplateMapper, SmsTemplate> implements ISmsTemplateService {
@Autowired
SmsTemplateAdapter smsTemplateAdapter;
@Override
public List<SmsTemplateVO> findSmsTemplateByTemplateNo(String templateNo) {
try {
QueryWrapper<SmsTemplate> queryWrapper = new QueryWrapper<>();
queryWrapper.lambda().eq(SmsTemplate::getTemplateNo,templateNo)
.eq(SmsTemplate::getDataState, SuperConstant.DATA_STATE_0)
.eq(SmsTemplate::getAuditStatus, SmsConstant.STATUS_AUDIT_0);
return BeanConv.toBeanList(list(queryWrapper),SmsTemplateVO.class);
} catch (Exception e) {
log.error("查询签名状态异常:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsTemplateEnum.SELECT_FAIL);
}
}
@Override
public Page<SmsTemplateVO> findSmsTemplateVOPage(SmsTemplateVO smsTemplateVO, int pageNum, int pageSize) {
//构建分页对象
Page<SmsTemplate> page = new Page<>(pageNum,pageSize);
//构建查询条件
QueryWrapper<SmsTemplate> queryWrapper = new QueryWrapper<>();
//按模板名称查询
if (!EmptyUtil.isNullOrEmpty(smsTemplateVO.getTemplateName())) {
queryWrapper.lambda().likeRight(SmsTemplate::getTemplateName,smsTemplateVO.getTemplateName());
}
//按模板名称查询
if (!EmptyUtil.isNullOrEmpty(smsTemplateVO.getChannelLabel())) {
queryWrapper.lambda().eq(SmsTemplate::getChannelLabel,smsTemplateVO.getChannelLabel());
}
//按模板发送状态查询
if (!EmptyUtil.isNullOrEmpty(smsTemplateVO.getAcceptStatus())) {
queryWrapper.lambda().eq(SmsTemplate::getAcceptStatus,smsTemplateVO.getAcceptStatus());
}
//按模板审核状态查询
if (!EmptyUtil.isNullOrEmpty(smsTemplateVO.getAuditStatus())) {
queryWrapper.lambda().eq(SmsTemplate::getAuditStatus,smsTemplateVO.getAuditStatus());
}
//按模板状态查询
if (!EmptyUtil.isNullOrEmpty(smsTemplateVO.getDataState())) {
queryWrapper.lambda().eq(SmsTemplate::getDataState,smsTemplateVO.getDataState());
}
//按创建时间降序
queryWrapper.lambda().orderByDesc(SmsTemplate::getCreateTime);
//执行分页查询
Page<SmsTemplateVO> smsTemplateVOPage = BeanConv.toPage(page(page, queryWrapper), SmsTemplateVO.class);
if (!EmptyUtil.isNullOrEmpty(smsTemplateVOPage.getRecords())){
smsTemplateVOPage.getRecords().forEach(n->{
List <OtherConfigVO> list = JSONArray.parseArray(n.getOtherConfig(), OtherConfigVO.class);
n.setOtherConfigs(list);
});
}
//返回结果
return smsTemplateVOPage;
}
@Override
public SmsTemplateVO findSmsTemplateByTemplateNameAndChannelLabel(String templateName, String channelLabel) {
try {
QueryWrapper<SmsTemplate> queryWrapper = new QueryWrapper<>();
queryWrapper.lambda().eq(SmsTemplate::getTemplateName,templateName)
.eq(SmsTemplate::getChannelLabel, channelLabel);
return BeanConv.toBean(getOne(queryWrapper),SmsTemplateVO.class);
}catch (Exception e){
log.error("查询签名异常:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsSignEnum.SELECT_FAIL);
}
}
@Override
@Transactional
@Caching(evict = {@CacheEvict(value = SmsCacheConstant.PAGE_TEMPLATE,allEntries = true)},
put={@CachePut(value =SmsCacheConstant.PREFIX_TEMPLATE,key = "#result.id")})
public SmsTemplateVO addSmsTemplate(SmsTemplateVO smsTemplateVO) throws ProjectException {
try {
return smsTemplateAdapter.addSmsTemplate(smsTemplateVO);
} catch (Exception e) {
log.error("添加签名异常:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsTemplateEnum.CREATE_FAIL);
}
}
@Override
@Transactional
@Caching(evict = {@CacheEvict(value = SmsCacheConstant.PAGE_TEMPLATE,allEntries = true),
@CacheEvict(value = SmsCacheConstant.PREFIX_TEMPLATE,allEntries = true)})
public Boolean deleteSmsTemplate(String[] checkedIds) throws ProjectException {
try {
return smsTemplateAdapter.deleteSmsTemplate(checkedIds);
} catch (Exception e) {
log.error("删除签名异常:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsTemplateEnum.DELETE_FAIL);
}
}
@Override
@Transactional
@Caching(evict = {@CacheEvict(value = SmsCacheConstant.PAGE_TEMPLATE,allEntries = true),
@CacheEvict(value = SmsCacheConstant.PREFIX_TEMPLATE,key = "#smsTemplateVO.id")})
public SmsTemplateVO modifySmsTemplate(SmsTemplateVO smsTemplateVO) throws ProjectException {
try {
return smsTemplateAdapter.modifySmsTemplate(smsTemplateVO);
} catch (Exception e) {
log.error("修改签名异常:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsTemplateEnum.UPDATE_FAIL);
}
}
@Override
@Transactional
@Cacheable(value =SmsCacheConstant.PREFIX_TEMPLATE,key = "#smsTemplateVO.id")
public SmsTemplateVO querySmsTemplate(SmsTemplateVO smsTemplateVO) throws ProjectException {
try {
return smsTemplateAdapter.querySmsTemplate(smsTemplateVO);
} catch (Exception e) {
log.error("查询签名状态异常:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsTemplateEnum.SELECT_FAIL);
}
}
@Override
public SmsTemplateVO disableEnable(SmsTemplateVO smsTemplateVO) {
try {
SmsTemplate smsTemplate = BeanConv.toBean(smsTemplateVO, SmsTemplate.class);
updateById(smsTemplate);
return BeanConv.toBean(smsTemplate, SmsTemplateVO.class);
} catch (Exception e) {
log.error("修改签名状态异常:{}", ExceptionsUtil.getStackTraceAsString(e));
throw new ProjectException(SmsTemplateEnum.UPDATE_FAIL);
}
}
}
@@ -0,0 +1,115 @@
package com.itheima.sfbx.sms.web;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.sfbx.framework.commons.basic.ResponseResult;
import com.itheima.sfbx.framework.commons.dto.sms.SmsChannelVO;
import com.itheima.sfbx.framework.commons.utils.ResponseResultBuild;
import com.itheima.sfbx.sms.service.ISmsChannelService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* @ClassName SmsChannelController.java
* @Description 短信通道controller
*/
@RestController
@RequestMapping("smsChannel")
@Slf4j
@Api(tags = "通道controller")
public class SmsChannelController {
@Autowired
ISmsChannelService smsChannelService;
/**
* @Description 通道列表
* @param smsChannelVO 查询条件
* @return
*/
@PostMapping("page/{pageNum}/{pageSize}")
@ApiOperation(value = "查询通道分页",notes = "查询通道分页")
@ApiImplicitParams({
@ApiImplicitParam(name = "smsChannelVO",value = "通道查询对象",required = true,dataType = "SmsChannelVO"),
@ApiImplicitParam(paramType = "path",name = "pageNum",value = "页码",dataType = "Integer"),
@ApiImplicitParam(paramType = "path",name = "pageSize",value = "每页条数",dataType = "Integer")
})
public ResponseResult<Page<SmsChannelVO>> findSmsChannelVOPage(
@RequestBody SmsChannelVO smsChannelVO,
@PathVariable("pageNum") int pageNum,
@PathVariable("pageSize") int pageSize) {
Page<SmsChannelVO> smsChannelVOPage = smsChannelService.findSmsChannelVOPage(smsChannelVO, pageNum, pageSize);
return ResponseResultBuild.successBuild(smsChannelVOPage);
}
/**
* @Description 添加通道
* @param smsChannelVO 对象信息
* @return
*/
@PostMapping
@ApiOperation(value = "添加通道",notes = "添加通道")
@ApiImplicitParam(name = "smsChannelVO",value = "通道对象",required = true,dataType = "SmsChannelVO")
ResponseResult<SmsChannelVO> createSmsChannel(@RequestBody SmsChannelVO smsChannelVO) {
SmsChannelVO smsChannelVOResult = smsChannelService.createSmsChannel(smsChannelVO);
return ResponseResultBuild.successBuild(smsChannelVOResult);
}
/**
* @Description 修改通道
* @param smsChannelVO 对象信息
* @return
*/
@PatchMapping
@ApiOperation(value = "修改通道",notes = "修改通道")
@ApiImplicitParam(name = "smsChannelVO",value = "通道对象",required = true,dataType = "SmsChannelVO")
ResponseResult<SmsChannelVO> updateSmsChannel(@RequestBody SmsChannelVO smsChannelVO) {
SmsChannelVO smsChannelVOResult = smsChannelService.updateSmsChannel(smsChannelVO);
return ResponseResultBuild.successBuild(smsChannelVOResult);
}
/**
* @Description 删除通道
* @param smsChannelVO 查询对象
* @return
*/
@DeleteMapping
@ApiOperation(value = "删除通道",notes = "删除通道")
@ApiImplicitParam(name = "smsChannelVO",value = "通道查询对象",required = true,dataType = "SmsChannelVO")
ResponseResult<Boolean> deleteSmsChannel(@RequestBody SmsChannelVO smsChannelVO ) {
String[] checkedIds = smsChannelVO.getCheckedIds();
Boolean flag = smsChannelService.deleteSmsChannel(checkedIds);
return ResponseResultBuild.successBuild(flag);
}
/**
* @Description 修改通道状态
* @param smsChannelVO 查询对象
* @return
*/
@PostMapping("update-smsChannel-enableFlag")
@ApiOperation(value = "修改通道状态",notes = "修改通道状态")
@ApiImplicitParam(name = "smsChannelVO",value = "通道查询对象",required = true,dataType = "SmsChannelVO")
ResponseResult<SmsChannelVO> updateSmsChannelEnableFlag(@RequestBody SmsChannelVO smsChannelVO) {
SmsChannelVO smsChannelVOResult = smsChannelService.updateSmsChannel(smsChannelVO);
return ResponseResultBuild.successBuild(smsChannelVOResult);
}
/**
* @Description 查询通道下拉框
* @return
*/
@PostMapping("list")
@ApiOperation(value = "查询通道下拉框",notes = "查询通道下拉框")
public ResponseResult<List<SmsChannelVO>> findSmsChannelVOList() {
List<SmsChannelVO> smsChannelVOs = smsChannelService.findSmsChannelVOList();
return ResponseResultBuild.successBuild(smsChannelVOs);
}
}
@@ -0,0 +1,71 @@
package com.itheima.sfbx.sms.web;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.sfbx.framework.commons.basic.ResponseResult;
import com.itheima.sfbx.framework.commons.dto.sms.SmsSendRecordVO;
import com.itheima.sfbx.framework.commons.utils.ResponseResultBuild;
import com.itheima.sfbx.sms.service.ISmsSendRecordService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
* @ClassName SmsSendRecordController.java
* @Description 发送记录Controller
*/
@RestController
@RequestMapping("sms-send-record")
@Slf4j
@Api(tags = "发送记录controller")
public class SmsSendRecordController {
@Autowired
ISmsSendRecordService smsSendRecordService;
/**
* @Description 发送记录列表
* @param smsSendRecordVO 查询条件
* @return
*/
@PostMapping("page/{pageNum}/{pageSize}")
@ApiOperation(value = "查询发送记录分页",notes = "查询发送记录分页")
@ApiImplicitParams({
@ApiImplicitParam(name = "smsSendRecordVO",value = "发送记录查询对象",required = true,dataType = "SmsSendRecordVO"),
@ApiImplicitParam(paramType = "path",name = "pageNum",value = "页码",dataType = "Integer"),
@ApiImplicitParam(paramType = "path",name = "pageSize",value = "每页条数",dataType = "Integer")
})
public ResponseResult<Page<SmsSendRecordVO>> findSmsSendRecordVOPage(
@RequestBody SmsSendRecordVO smsSendRecordVO,
@PathVariable("pageNum") int pageNum,
@PathVariable("pageSize") int pageSize) {
Page<SmsSendRecordVO> smsSendRecordVOPage =
smsSendRecordService.findSmsSendRecordVOPage(smsSendRecordVO, pageNum, pageSize);
return ResponseResultBuild.successBuild(smsSendRecordVOPage);
}
/**
* @Description 查找发送记录
* @param smsSendRecordId 登录名
* @return
*/
@PostMapping("{smsSendRecordId}")
@ApiOperation(value = "查找发送记录",notes = "查找发送记录")
@ApiImplicitParam(paramType = "path",name = "smsSendRecordId",value = "发送记录Id",dataType = "Long")
ResponseResult<SmsSendRecordVO> findSmsSendRecordBySmsSendRecordId(@PathVariable("smsSendRecordId") Long smsSendRecordId) {
SmsSendRecordVO smsSendRecordVO = smsSendRecordService.findSmsSendRecordBySmsSendRecordId(smsSendRecordId);
return ResponseResultBuild.successBuild(smsSendRecordVO);
}
@PostMapping("retrySendSms")
@ApiOperation(value = "重发",notes = "重发")
@ApiImplicitParam(name = "smsSendRecordVO",value = "发送记录查询对象",required = true,dataType = "SmsSendRecordVO")
ResponseResult<Boolean> retrySendSms(@RequestBody SmsSendRecordVO smsSendRecordVO) {
Boolean flag = smsSendRecordService.retrySendSms(smsSendRecordVO);
return ResponseResultBuild.successBuild(flag);
}
}
@@ -0,0 +1,96 @@
package com.itheima.sfbx.sms.web;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.sfbx.framework.commons.basic.ResponseResult;
import com.itheima.sfbx.framework.commons.dto.sms.SmsSignVO;
import com.itheima.sfbx.framework.commons.utils.ResponseResultBuild;
import com.itheima.sfbx.sms.service.ISmsSignService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* @ClassName SmsSignController.java
* @Description 短信签名controller
*/
@RestController
@RequestMapping("smsSign")
@Slf4j
@Api(tags = "签名controller")
public class SmsSignController {
@Autowired
ISmsSignService smsSignService;
/**
* @Description 签名列表
* @param smsSignVO 查询条件
* @return
*/
@PostMapping("page/{pageNum}/{pageSize}")
@ApiOperation(value = "查询签名分页",notes = "查询签名分页")
@ApiImplicitParams({
@ApiImplicitParam(name = "smsSignVO",value = "签名查询对象",required = true,dataType = "SmsSignVO"),
@ApiImplicitParam(paramType = "path",name = "pageNum",value = "页码",dataType = "Integer"),
@ApiImplicitParam(paramType = "path",name = "pageSize",value = "每页条数",dataType = "Integer")
})
public ResponseResult<Page<SmsSignVO>> findSmsSignVOPage(
@RequestBody SmsSignVO smsSignVO,
@PathVariable("pageNum") int pageNum,
@PathVariable("pageSize") int pageSize) {
Page<SmsSignVO> smsSignVOPage = smsSignService.findSmsSignVOPage(smsSignVO, pageNum, pageSize);
return ResponseResultBuild.successBuild(smsSignVOPage);
}
/**
* @Description 查询签名下拉框
* @return
*/
@PostMapping("list")
@ApiOperation(value = "查询签名下拉框",notes = "查询签名下拉框")
public ResponseResult<List<SmsSignVO>> findSmsSignVOList() {
List<SmsSignVO> smsSignVOPage = smsSignService.findSmsSignVOList();
return ResponseResultBuild.successBuild(smsSignVOPage);
}
/**
* @Description 添加签名
* @param smsSignVO 对象信息
* @return
*/
@PostMapping
@ApiOperation(value = "添加签名",notes = "添加签名")
@ApiImplicitParam(name = "smsSignVO",value = "签名对象",required = true,dataType = "SmsSignVO")
ResponseResult<SmsSignVO> createSmsSign(@RequestBody SmsSignVO smsSignVO) {
SmsSignVO smsSignVOResult = smsSignService.addSmsSign(smsSignVO);
return ResponseResultBuild.successBuild(smsSignVOResult);
}
/**
* @Description 修改签名
* @param smsSignVO 对象信息
* @return
*/
@PatchMapping
@ApiOperation(value = "修改签名",notes = "修改签名")
@ApiImplicitParam(name = "smsSignVO",value = "签名对象",required = true,dataType = "SmsSignVO")
ResponseResult<SmsSignVO> updateSmsSign(@RequestBody SmsSignVO smsSignVO) {
SmsSignVO smsSignVOResult = smsSignService.modifySmsSign(smsSignVO);
return ResponseResultBuild.successBuild(smsSignVOResult);
}
@PostMapping("disable-enable")
@ApiOperation(value = "禁用启用",notes = "禁用启用")
@ApiImplicitParam(name = "smsSignVO",value = "签名查询对象",required = true,dataType = "SmsSignVO")
ResponseResult<SmsSignVO> disableEnable(@RequestBody SmsSignVO smsSignVO) {
SmsSignVO smsSignVoResult = smsSignService.disableEnable(smsSignVO);
return ResponseResultBuild.successBuild(smsSignVoResult);
}
}
@@ -0,0 +1,83 @@
package com.itheima.sfbx.sms.web;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.sfbx.framework.commons.basic.ResponseResult;
import com.itheima.sfbx.framework.commons.dto.sms.SmsTemplateVO;
import com.itheima.sfbx.framework.commons.utils.ResponseResultBuild;
import com.itheima.sfbx.sms.service.ISmsTemplateService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
* @ClassName SmsTemplateController.java
* @Description 短信模板controller
*/
@RestController
@RequestMapping("smsTemplate")
@Slf4j
@Api(tags = "模板controller")
public class SmsTemplateController {
@Autowired
ISmsTemplateService smsTemplateService;
/**
* @Description 模板列表
* @param smsTemplateVO 查询条件
* @return
*/
@PostMapping("page/{pageNum}/{pageSize}")
@ApiOperation(value = "查询模板分页",notes = "查询模板分页")
@ApiImplicitParams({
@ApiImplicitParam(name = "smsTemplateVO",value = "模板查询对象",required = true,dataType = "SmsTemplateVO"),
@ApiImplicitParam(paramType = "path",name = "pageNum",value = "页码",dataType = "Integer"),
@ApiImplicitParam(paramType = "path",name = "pageSize",value = "每页条数",dataType = "Integer")
})
public ResponseResult<Page<SmsTemplateVO>> findSmsTemplateVOPage(
@RequestBody SmsTemplateVO smsTemplateVO,
@PathVariable("pageNum") int pageNum,
@PathVariable("pageSize") int pageSize) {
Page<SmsTemplateVO> smsTemplateVOPage = smsTemplateService.findSmsTemplateVOPage(smsTemplateVO, pageNum, pageSize);
return ResponseResultBuild.successBuild(smsTemplateVOPage);
}
/**
* @Description 添加模板
* @param smsTemplateVO 对象信息
* @return
*/
@PostMapping
@ApiOperation(value = "添加模板",notes = "添加模板")
@ApiImplicitParam(name = "smsTemplateVO",value = "模板对象",required = true,dataType = "SmsTemplateVO")
ResponseResult<SmsTemplateVO> createSmsTemplate(@RequestBody SmsTemplateVO smsTemplateVO) {
SmsTemplateVO smsTemplateVOResult = smsTemplateService.addSmsTemplate(smsTemplateVO);
return ResponseResultBuild.successBuild(smsTemplateVOResult);
}
/**
* @Description 修改模板
* @param smsTemplateVO 对象信息
* @return
*/
@PatchMapping
@ApiOperation(value = "修改模板",notes = "修改模板")
@ApiImplicitParam(name = "smsTemplateVO",value = "模板对象",required = true,dataType = "SmsTemplateVO")
ResponseResult<SmsTemplateVO> updateSmsTemplate(@RequestBody SmsTemplateVO smsTemplateVO) {
SmsTemplateVO smsTemplateVOResult = smsTemplateService.modifySmsTemplate(smsTemplateVO);
return ResponseResultBuild.successBuild(smsTemplateVOResult);
}
@PostMapping("disable-enable")
@ApiOperation(value = "禁用启用",notes = "禁用启用")
@ApiImplicitParam(name = "smsTemplateVO",value = "模板查询对象",required = true,dataType = "SmsTemplateVO")
ResponseResult<SmsTemplateVO> disableEnable(@RequestBody SmsTemplateVO smsTemplateVO) {
SmsTemplateVO smsTemplateVOResult = smsTemplateService.disableEnable(smsTemplateVO);
return ResponseResultBuild.successBuild(smsTemplateVOResult);
}
}
@@ -0,0 +1,10 @@
_ __ __
(_) /__________ ______/ /_
/ / __/ ___/ __ `/ ___/ __/
/ / /_/ /__/ /_/ (__ ) /_
/_/\__/\___/\__,_/____/\__/
:: Spring Boot :: (v-2.7.10)
:: Spring Cloud :: (v-2021.0.6)
:: Spring Cloud Alibaba :: (v-2021.0.1.0)
:: sfbx Cloud :: (v-2.0-SNAPSHOT)
:: 献给可爱的传智人 ::
@@ -0,0 +1,57 @@
#服务配置
server:
#端口
port: 7073
#服务编码
tomcat:
uri-encoding: UTF-8
spring:
config:
activate:
on-profile:
- test
main:
allow-bean-definition-overriding: true
allow-circular-references: true
mvc:
pathmatch:
matching-strategy: ant_path_matcher
#应用配置
application:
#应用名称
name: sms-web
cloud:
nacos:
discovery:
server-addr: ${NACOS_ADDRESS:nacos-service.yjy-public-sfbx-java.svc.cluster.local:20015} # nacos注册中心
group: SEATA_GROUP
service: ${spring.application.name}
username: ${NACOS_USERNAME:nacos}
password: ${NACOS_PASSWORD:PKsf*bxQ4;yP3a+}
config:
server-addr: ${NACOS_ADDRESS:nacos-service.yjy-public-sfbx-java.svc.cluster.local:20015} # nacos注册中心
group: SEATA_GROUP
file-extension: yml
shared-configs: # 共享配置
- data-id: shared-spring-seata.yml #配置文件名-DataId
group: SEATA_GROUP
refresh: false
- data-id: shared-spring-task.yml #配置文件名-DataId
group: SEATA_GROUP
refresh: false
- data-id: shared-redisson.yml #配置文件名-DataId
group: SEATA_GROUP
refresh: false
- data-id: shared-mybatis-plus.yml #配置文件名-DataId
group: SEATA_GROUP
refresh: false
- data-id: shared-stream-rabbit-basic.yml #配置文件名-DataId
group: SEATA_GROUP
refresh: false
- data-id: shared-stream-rabbit-source-sms.yml #配置文件名-DataId
group: SEATA_GROUP
refresh: false
username: ${NACOS_USERNAME:nacos}
password: ${NACOS_PASSWORD:PKsf*bxQ4;yP3a+}
logging:
config: classpath:logback.xml
@@ -0,0 +1,51 @@
#服务配置
server:
#端口
port: 7073
#服务编码
tomcat:
uri-encoding: UTF-8
spring:
profiles:
active: dev
main:
allow-bean-definition-overriding: true
allow-circular-references: true
mvc:
pathmatch:
matching-strategy: ant_path_matcher
#应用配置
application:
#应用名称
name: sms-web
cloud:
nacos:
discovery:
server-addr: 192.168.12.129:8848 # nacos注册中心
group: SEATA_GROUP
service: ${spring.application.name}
config:
server-addr: 192.168.12.129:8848 # nacos配置中心地址
group: SEATA_GROUP
file-extension: yml
shared-configs: # 共享配置
- data-id: shared-spring-seata.yml #配置文件名-DataId
group: SEATA_GROUP
refresh: false
- data-id: shared-spring-task.yml #配置文件名-DataId
group: SEATA_GROUP
refresh: false
- data-id: shared-redisson.yml #配置文件名-DataId
group: SEATA_GROUP
refresh: false
- data-id: shared-mybatis-plus.yml #配置文件名-DataId
group: SEATA_GROUP
refresh: false
- data-id: shared-stream-rabbit-basic.yml #配置文件名-DataId
group: SEATA_GROUP
refresh: false
- data-id: shared-stream-rabbit-source-sms.yml #配置文件名-DataId
group: SEATA_GROUP
refresh: false
logging:
config: classpath:logback.xml
@@ -0,0 +1,33 @@
#\u6570\u636E\u5E93\u5730\u5740
url=jdbc:mysql://192.168.12.129:3306/restkeeper-sms?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&tinyInt1isBit=false
#\u6570\u636E\u5E93\u8D26\u53F7
userName=root
#\u6570\u636E\u5E93\u5BC6\u7801
password=pass
#\u6B64\u5904\u4E3A\u672C\u9879\u76EEsrc\u6240\u5728\u8DEF\u5F84\uFF08\u4EE3\u7801\u751F\u6210\u5668\u8F93\u51FA\u8DEF\u5F84\uFF09
serviceProjectPath=E:/itheima-project-parent/itheima-project-cloud/itheima-module-sms/module-sms-web
#\u8BBE\u7F6E\u4F5C\u8005
author=Admin
#\u81EA\u5B9A\u4E49\u5305\u8DEF\u5F84
parent=com.itheima
#\u88C5\u4EE3\u7801\u7684\u6587\u4EF6\u5939\u540D
moduleName=project
#\u8BBE\u7F6E\u8868\u524D\u7F00\uFF0C\u4E0D\u8BBE\u7F6E\u5219\u9ED8\u8BA4\u65E0\u524D\u7F00
tablePrefix =tab_
#\u6570\u636E\u5E93\u8868\u540D(\u6B64\u5904\u5207\u4E0D\u53EF\u4E3A\u7A7A\uFF0C\u5982\u679C\u4E3A\u7A7A\uFF0C\u5219\u9ED8\u8BA4\u8BFB\u53D6\u6570\u636E\u5E93\u7684\u6240\u6709\u8868\u540D)
tableName=tab_sms_blacklist,tab_sms_channel,tab_sms_send_record,tab_sms_sign,tab_sms_template
#pojo\u7684\u8D85\u7C7B
SuperEntityClass = com.itheima.easy.basic.BasicPojo
#pojo\u7684\u8D85\u7C7B\u516C\u7528\u5B57\u6BB5
superEntityColumns = id,created_time,updated_time,sharding_id,enable_flag
#\u751F\u6210\u7684\u5C42\u7EA7
entity=true
entity.ftl.path=/templates/entity.java
mapper=true
mapper.ftl.path=/templates/mapper.java
service=true
service.ftl.path=/templates/service.java
serviceImpl=true
serviceImpl.ftl.path=/templates/serviceImpl.java
controller=false
controller.ftl.path=/templates/controller.java
@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
<!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径 -->
<property name="LOG_HOME" value="/data/logs/sms-web" />
<!-- 控制台输出 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}-%msg%n</pattern>
</encoder>
</appender>
<!-- 按照每天生成日志文件 -->
<appender name="FILE"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志文件输出的文件名 -->
<FileNamePattern>${LOG_HOME}/sms-web-01.log.%d{yyyy-MM-dd}.log
</FileNamePattern>
<!--日志文件保留天数 -->
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}-%msg%n</pattern>
</encoder>
<!--日志文件最大的大小 -->
<triggeringPolicy
class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>10MB</MaxFileSize>
</triggeringPolicy>
</appender>
<!-- show parameters for hibernate sql 专为 Hibernate 定制 -->
<logger name="org.hibernate.type.descriptor.sql.BasicBinder"
level="TRACE" />
<logger name="org.hibernate.type.descriptor.sql.BasicExtractor"
level="DEBUG" />
<logger name="org.hibernate.SQL" level="DEBUG" />
<logger name="org.hibernate.engine.QueryParameters" level="DEBUG" />
<logger name="org.hibernate.engine.query.HQLQueryPlan" level="DEBUG" />
<!--myibatis log configure -->
<logger name="com.apache.ibatis" level="TRACE" />
<logger name="java.sql.Connection" level="DEBUG" />
<logger name="java.sql.Statement" level="DEBUG" />
<logger name="java.sql.PreparedStatement" level="DEBUG" />
<!-- 日志输出级别 -->
<root level="INFO">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
</root>
<!--日志异步到数据库 -->
</configuration>
@@ -0,0 +1,34 @@
package ${package.Controller};
import org.springframework.web.bind.annotation.RequestMapping;
<#if restControllerStyle>
import org.springframework.web.bind.annotation.RestController;
<#else>
import org.springframework.stereotype.Controller;
</#if>
<#if superControllerClassPackage??>
import ${superControllerClassPackage};
</#if>
/**
* @Description${table.comment!} 前端控制器
*/
<#if restControllerStyle>
@RestController
<#else>
@Controller
</#if>
@RequestMapping("<#if package.ModuleName??>/${package.ModuleName}</#if>/<#if controllerMappingHyphenStyle??>${controllerMappingHyphen}<#else>${table.entityPath}</#if>")
<#if kotlin>
class ${table.controllerName}<#if superControllerClass??> : ${superControllerClass}()</#if>
<#else>
<#if superControllerClass??>
public class ${table.controllerName} extends ${superControllerClass} {
<#else>
public class ${table.controllerName} {
</#if>
}
</#if>
@@ -0,0 +1,156 @@
package ${package.Entity};
<#list table.importPackages as pkg>
import ${pkg};
</#list>
<#if swagger2>
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
</#if>
<#if entityLombokModel>
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.EqualsAndHashCode;
</#if>
/**
* @Description${table.comment!}
*/
<#if entityLombokModel>
@Data
@NoArgsConstructor
<#if superEntityClass??>
@EqualsAndHashCode(callSuper = true)
<#else>
@EqualsAndHashCode(callSuper = false)
</#if>
</#if>
<#if table.convert>
@TableName("${table.name}")
</#if>
<#if swagger2>
@ApiModel(value="${entity}对象", description="${table.comment!}")
</#if>
<#if superEntityClass??>
public class ${entity} extends ${superEntityClass}<#if activeRecord><${entity}></#if> {
<#elseif activeRecord>
public class ${entity} extends Model<${entity}> {
<#else>
public class ${entity} implements Serializable {
</#if>
<#if entitySerialVersionUID>
private static final long serialVersionUID = 1L;
</#if>
@Builder
public ${entity}(Long id,<#list table.fields as field>${field.propertyType} ${field.propertyName}<#if field_has_next>,</#if></#list>){
super(id);
<#list table.fields as field>
this.${field.propertyName}=${field.propertyName};
</#list>
}
<#-- ---------- BEGIN 字段循环遍历 ---------->
<#list table.fields as field>
<#if field.keyFlag>
<#assign keyPropertyName="${field.propertyName}"/>
</#if>
<#if field.comment!?length gt 0>
<#if swagger2>
@ApiModelProperty(value = "${field.comment}")
<#else>
/**
* ${field.comment}
*/
</#if>
</#if>
<#if field.keyFlag>
<#-- 主键 -->
<#if field.keyIdentityFlag>
@TableId(value = "${field.name}", type = IdType.AUTO)
<#elseif idType??>
@TableId(value = "${field.name}", type = IdType.${idType})
<#elseif field.convert>
@TableId("${field.name}")
</#if>
<#-- 普通字段 -->
<#elseif field.fill??>
<#-- ----- 存在字段填充设置 ----->
<#if field.convert>
@TableField(value = "${field.name}", fill = FieldFill.${field.fill})
<#else>
@TableField(fill = FieldFill.${field.fill})
</#if>
<#elseif field.convert>
@TableField("${field.name}")
</#if>
<#-- 乐观锁注解 -->
<#if (versionFieldName!"") == field.name>
@Version
</#if>
<#-- 逻辑删除注解 -->
<#if (logicDeleteFieldName!"") == field.name>
@TableLogic
</#if>
private ${field.propertyType} ${field.propertyName};
</#list>
<#------------ END 字段循环遍历 ---------->
<#if !entityLombokModel>
<#list table.fields as field>
<#if field.propertyType == "boolean">
<#assign getprefix="is"/>
<#else>
<#assign getprefix="get"/>
</#if>
public ${field.propertyType} ${getprefix}${field.capitalName}() {
return ${field.propertyName};
}
<#if entityBuilderModel>
public ${entity} set${field.capitalName}(${field.propertyType} ${field.propertyName}) {
<#else>
public void set${field.capitalName}(${field.propertyType} ${field.propertyName}) {
</#if>
this.${field.propertyName} = ${field.propertyName};
<#if entityBuilderModel>
return this;
</#if>
}
</#list>
</#if>
<#if entityColumnConstant>
<#list table.fields as field>
public static final String ${field.name?upper_case} = "${field.name}";
</#list>
</#if>
<#if activeRecord>
@Override
protected Serializable pkVal() {
<#if keyPropertyName??>
return this.${keyPropertyName};
<#else>
return null;
</#if>
}
</#if>
<#if !entityLombokModel>
@Override
public String toString() {
return "${entity}{" +
<#list table.fields as field>
<#if field_index==0>
"${field.propertyName}=" + ${field.propertyName} +
<#else>
", ${field.propertyName}=" + ${field.propertyName} +
</#if>
</#list>
"}";
}
</#if>
}
@@ -0,0 +1,15 @@
package ${package.Mapper};
import ${package.Entity}.${entity};
import ${superMapperClassPackage};
/**
* @Description${table.comment!}Mapper接口
*/
<#if kotlin>
interface ${table.mapperName} : ${superMapperClass}<${entity}>
<#else>
public interface ${table.mapperName} extends ${superMapperClass}<${entity}> {
}
</#if>
@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="${package.Mapper}.${table.mapperName}">
<#if enableCache>
<!-- 开启二级缓存 -->
<cache type="org.mybatis.caches.ehcache.LoggingEhcache"/>
</#if>
<#if baseResultMap>
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="${package.Entity}.${entity}">
<#list table.fields as field>
<#if field.keyFlag><#--生成主键排在第一位-->
<id column="${field.name}" property="${field.propertyName}" />
</#if>
</#list>
<#list table.commonFields as field><#--生成公共字段 -->
<result column="${field.name}" property="${field.propertyName}" />
</#list>
<#list table.fields as field>
<#if !field.keyFlag><#--生成普通字段 -->
<result column="${field.name}" property="${field.propertyName}" />
</#if>
</#list>
</resultMap>
</#if>
<#if baseColumnList>
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
<#list table.commonFields as field>
${field.name},
</#list>
${table.fieldNames}
</sql>
</#if>
</mapper>
@@ -0,0 +1,15 @@
package ${package.Service};
import ${package.Entity}.${entity};
import ${superServiceClassPackage};
/**
* @Description${table.comment!} 服务类
*/
<#if kotlin>
interface ${table.serviceName} : ${superServiceClass}<${entity}>
<#else>
public interface ${table.serviceName} extends ${superServiceClass}<${entity}> {
}
</#if>
@@ -0,0 +1,21 @@
package ${package.ServiceImpl};
import ${package.Entity}.${entity};
import ${package.Mapper}.${table.mapperName};
import ${package.Service}.${table.serviceName};
import ${superServiceImplClassPackage};
import org.springframework.stereotype.Service;
/**
* @Description${table.comment!} 服务实现类
*/
@Service
<#if kotlin>
open class ${table.serviceImplName} : ${superServiceImplClass}<${table.mapperName}, ${entity}>(), ${table.serviceName} {
}
<#else>
public class ${table.serviceImplName} extends ${superServiceImplClass}<${table.mapperName}, ${entity}> implements ${table.serviceName} {
}
</#if>