This commit is contained in:
wanggeng 2023-01-07 16:01:28 +08:00
commit 900fec8ee4
26 changed files with 1242 additions and 0 deletions

36
.gitignore vendored Normal file
View File

@ -0,0 +1,36 @@
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
.mvn/*
mvnw*

145
pom.xml Normal file
View File

@ -0,0 +1,145 @@
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.com.tenlion</groupId>
<artifactId>sms-sender</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>sms-sender</name>
<description>sms-sender</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.3.1</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.15</version>
</dependency>
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.20</version>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.12.1</version>
</dependency>
<dependency>
<groupId>ink.wgink</groupId>
<artifactId>basic-rpc-rest</artifactId>
<version>2.0-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<!-- 打包时去除第三方依赖 -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<layout>ZIP</layout>
<includes>
<include>
<groupId>non-exists</groupId>
<artifactId>non-exists</artifactId>
</include>
</includes>
</configuration>
</plugin>
<!-- 拷贝第三方依赖文件到指定目录 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<!-- target/lib 是依赖jar包的输出目录根据自己喜好配置 -->
<outputDirectory>target/lib</outputDirectory>
<excludeTransitive>false</excludeTransitive>
<stripVersion>false</stripVersion>
<includeScope>runtime</includeScope>
</configuration>
</execution>
</executions>
</plugin>
<!-- 排除静态资源,静态资源自行拷贝 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<excludes>
<exclude>**/*.properties</exclude>
<exclude>**/*.xml</exclude>
<exclude>**/*.yml</exclude>
<exclude>static/**</exclude>
<exclude>templates/**</exclude>
<exclude>mybatis/**</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>

2
readme.md Normal file
View File

@ -0,0 +1,2 @@
alter table m_smessage_short_message
add short_message_uuid char(50) null comment '调用这记录ID' after short_message_uid;

View File

@ -0,0 +1,15 @@
package cn.com.tenlion.smssender;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@MapperScan(basePackages = {"cn.com.tenlion.**.dao"})
@SpringBootApplication(scanBasePackages={"cn.com.tenlion", "ink.wgink"})
public class SmsSenderApplication {
public static void main(String[] args) {
SpringApplication.run(SmsSenderApplication.class, args);
}
}

View File

@ -0,0 +1,62 @@
package cn.com.tenlion.smssender.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* @ClassName: HuaChuangSmsConfig
* @Description:
* @Author: wanggeng
* @Date: 2022/12/6 21:38
* @Version: 1.0
*/
@Configuration
@ConfigurationProperties(prefix = "sms.hua-chuang")
public class HuaChuangSmsProperties {
private Boolean active;
private String url;
private String username;
private String password;
private String extno;
public Boolean getActive() {
return active != null && active;
}
public void setActive(Boolean active) {
this.active = active;
}
public String getUrl() {
return url == null ? "" : url.trim();
}
public void setUrl(String url) {
this.url = url;
}
public String getUsername() {
return username == null ? "" : username.trim();
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password == null ? "" : password.trim();
}
public void setPassword(String password) {
this.password = password;
}
public String getExtno() {
return extno == null ? "" : extno.trim();
}
public void setExtno(String extno) {
this.extno = extno;
}
}

View File

@ -0,0 +1,75 @@
package cn.com.tenlion.smssender.controller;
import cn.com.tenlion.smssender.pojo.bos.HuaChuangSmsBO;
import cn.com.tenlion.smssender.pojo.vos.SmsP2PSendVO;
import cn.com.tenlion.smssender.pojo.vos.SmsSendVO;
import cn.com.tenlion.smssender.service.ISmsSendService;
import com.alibaba.fastjson2.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.kafka.support.SendResult;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.ListenableFutureCallback;
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
/**
* @ClassName: TestController
* @Description:
* @Author: wanggeng
* @Date: 2022/12/6 22:09
* @Version: 1.0
*/
@RestController
@RequestMapping("sms")
public class SmsController {
@Autowired
private ISmsSendService smsSendService;
@Autowired
private KafkaTemplate<String, Object> kafkaTemplate;
@PostMapping("send")
public void send(@RequestBody SmsSendVO smsSendVO) {
HuaChuangSmsBO huaChuangSmsBO = new HuaChuangSmsBO();
huaChuangSmsBO.setShortMessageNo(smsSendVO.getShortMessageNo());
huaChuangSmsBO.setMobiles(smsSendVO.getMobiles());
huaChuangSmsBO.setContent(smsSendVO.getContent());
smsSendService.send(huaChuangSmsBO);
}
@PostMapping("send-p2p")
public void sendP2P(@RequestBody SmsP2PSendVO smsP2PSendVO) {
HuaChuangSmsBO huaChuangSmsBO = new HuaChuangSmsBO();
huaChuangSmsBO.setShortMessageNo(smsP2PSendVO.getShortMessageNo());
huaChuangSmsBO.setMobileContents(smsP2PSendVO.getMobileContents());
smsSendService.sendP2P(huaChuangSmsBO);
}
@GetMapping("kafka-test/{count}")
public void sendP2P(@PathVariable("count") Integer count) {
SmsSendVO smsSendVO = new SmsSendVO();
smsSendVO.setShortMessageNo("test-short-message-uuid");
smsSendVO.setMobiles(Arrays.asList("18634604067", "19147182823"));
smsSendVO.setContent("测试");
for (int i = 0; i < count; i++) {
ListenableFuture<SendResult<String, Object>> smsSendListenableFuture = kafkaTemplate.send("sms_send", JSON.toJSONString(smsSendVO));
smsSendListenableFuture.addCallback(new ListenableFutureCallback<SendResult<String, Object>>() {
@Override
public void onFailure(Throwable ex) {
System.out.println("发送失败");
ex.printStackTrace();
}
@Override
public void onSuccess(SendResult<String, Object> result) {
System.out.println("发送成功");
System.out.println(result.toString());
}
});
}
}
}

View File

@ -0,0 +1,19 @@
package cn.com.tenlion.smssender.dao;
import org.springframework.stereotype.Repository;
import java.util.Map;
/**
* @ClassName: ISmsDao
* @Description: 短信
* @Author: wanggeng
* @Date: 2022/12/7 14:54
* @Version: 1.0
*/
@Repository
public interface ISmsDao {
void updateStatus(Map<String, Object> params);
}

View File

@ -0,0 +1,31 @@
package cn.com.tenlion.smssender.enums;
/**
* @ClassName: SmsSendStatus
* @Description: 发送状态
* @Author: wanggeng
* @Date: 2022/12/7 15:23
* @Version: 1.0
*/
public enum SmsSendStatus {
WAIT(0, "待发送"),
SEND(1, "已发送|已接收"),
CONFIRM(2, "确认送达|确认通知厂家"),
ERROR(-1, "送达失败|通知失败");
private Integer value;
private String text;
SmsSendStatus(Integer value, String text) {
this.value = value;
this.text = text;
}
public Integer getValue() {
return value == null ? 0 : value;
}
public String getText() {
return text == null ? "" : text.trim();
}
}

View File

@ -0,0 +1,68 @@
package cn.com.tenlion.smssender.kafka;
import cn.com.tenlion.smssender.pojo.bos.HuaChuangSmsBO;
import cn.com.tenlion.smssender.pojo.vos.SmsP2PSendVO;
import cn.com.tenlion.smssender.pojo.vos.SmsSendVO;
import cn.com.tenlion.smssender.service.ISmsSendService;
import com.alibaba.fastjson2.JSONObject;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.kafka.support.Acknowledgment;
import org.springframework.kafka.support.KafkaHeaders;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;
import java.util.Optional;
/**
* @ClassName: KafkaConsumer
* @Description: 消费者
* @Author: wanggeng
* @Date: 2022/12/7 09:50
* @Version: 1.0
*/
@Component
public class KafkaConsumer {
private static final Logger LOG = LoggerFactory.getLogger(KafkaConsumer.class);
@Autowired
private ISmsSendService smsSendService;
@KafkaListener(topics = "sms_send", groupId = "sms")
public void smsSend(ConsumerRecord<?, ?> record, Acknowledgment ack, @Header(KafkaHeaders.RECEIVED_TOPIC) String topic) {
Optional<?> message = Optional.ofNullable(record.value());
if (message.isPresent()) {
Object msg = message.get();
LOG.info("消费了: Topic:" + topic + ",Message:" + msg);
SmsSendVO smsSendVO = JSONObject.parseObject(msg.toString(), SmsSendVO.class);
HuaChuangSmsBO huaChuangSmsBO = new HuaChuangSmsBO();
huaChuangSmsBO.setShortMessageNo(smsSendVO.getShortMessageNo());
huaChuangSmsBO.setMobiles(smsSendVO.getMobiles());
huaChuangSmsBO.setContent(smsSendVO.getContent());
huaChuangSmsBO.setExNo(smsSendVO.getExNo());
smsSendService.send(huaChuangSmsBO);
ack.acknowledge();
}
}
@KafkaListener(topics = "sms_p2p_send", groupId = "sms")
public void smsP2PSend(ConsumerRecord<?, ?> record, Acknowledgment ack, @Header(KafkaHeaders.RECEIVED_TOPIC) String topic) {
Optional<?> message = Optional.ofNullable(record.value());
if (message.isPresent()) {
Object msg = message.get();
LOG.info("消费了: Topic:" + topic + ",Message:" + msg);
SmsP2PSendVO smsP2PSendVO = JSONObject.parseObject(msg.toString(), SmsP2PSendVO.class);
HuaChuangSmsBO huaChuangSmsBO = new HuaChuangSmsBO();
huaChuangSmsBO.setShortMessageNo(smsP2PSendVO.getShortMessageNo());
huaChuangSmsBO.setMobileContents(smsP2PSendVO.getMobileContents());
huaChuangSmsBO.setExNo(smsP2PSendVO.getExNo());
smsSendService.sendP2P(huaChuangSmsBO);
ack.acknowledge();
}
}
}

View File

@ -0,0 +1,108 @@
package cn.com.tenlion.smssender.pojo;
import java.util.ArrayList;
import java.util.List;
/**
* @ClassName: SmsSendResult
* @Description: 短信发送结果
* @Author: wanggeng
* @Date: 2022/12/6 21:09
* @Version: 1.0
*/
public class HuaChuangSmsSendResult {
private Integer status;
private Integer balance;
private List<PhoneResult> list;
private String message;
public Integer getStatus() {
return status == null ? 0 : status;
}
public void setStatus(Integer status) {
this.status = status;
}
public Integer getBalance() {
return balance == null ? 0 : balance;
}
public void setBalance(Integer balance) {
this.balance = balance;
}
public List<PhoneResult> getList() {
return list == null ? new ArrayList<>() : list;
}
public void setList(List<PhoneResult> list) {
this.list = list;
}
public String getMessage() {
return message == null ? "" : message.trim();
}
public void setMessage(String message) {
this.message = message;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("{");
sb.append("\"status\":")
.append(status);
sb.append(",\"balance\":")
.append(balance);
sb.append(",\"list\":")
.append(list);
sb.append('}');
return sb.toString();
}
public static class PhoneResult {
private String mid;
private String mobile;
private Integer result;
public String getMid() {
return mid == null ? "" : mid.trim();
}
public void setMid(String mid) {
this.mid = mid;
}
public String getMobile() {
return mobile == null ? "" : mobile.trim();
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public Integer getResult() {
return result == null ? 0 : result;
}
public void setResult(Integer result) {
this.result = result;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("{");
sb.append("\"mid\":\"")
.append(mid).append('\"');
sb.append(",\"mobile\":\"")
.append(mobile).append('\"');
sb.append(",\"result\":")
.append(result);
sb.append('}');
return sb.toString();
}
}
}

View File

@ -0,0 +1,42 @@
package cn.com.tenlion.smssender.pojo;
/**
* @ClassName: MobileContent
* @Description:
* @Author: wanggeng
* @Date: 2022/12/7 16:15
* @Version: 1.0
*/
public class MobileContent {
private String mobile;
private String content;
public String getMobile() {
return mobile == null ? "" : mobile.trim();
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public String getContent() {
return content == null ? "" : content.trim();
}
public void setContent(String content) {
this.content = content;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("{");
sb.append("\"mobile\":\"")
.append(mobile).append('\"');
sb.append(",\"content\":\"")
.append(content).append('\"');
sb.append('}');
return sb.toString();
}
}

View File

@ -0,0 +1,79 @@
package cn.com.tenlion.smssender.pojo.bos;
import cn.com.tenlion.smssender.pojo.MobileContent;
import java.util.ArrayList;
import java.util.List;
/**
* @ClassName: HuaChuangSmsBO
* @Description: 华创短信
* @Author: wanggeng
* @Date: 2022/12/6 21:36
* @Version: 1.0
*/
public class HuaChuangSmsBO {
private String shortMessageNo;
private String exNo;
private List<String> mobiles;
private String content;
private List<MobileContent> mobileContents;
public String getShortMessageNo() {
return shortMessageNo == null ? "" : shortMessageNo.trim();
}
public void setShortMessageNo(String shortMessageNo) {
this.shortMessageNo = shortMessageNo;
}
public String getExNo() {
return exNo == null ? "" : exNo.trim();
}
public void setExNo(String exNo) {
this.exNo = exNo;
}
public List<String> getMobiles() {
return mobiles;
}
public void setMobiles(List<String> mobiles) {
this.mobiles = mobiles;
}
public String getContent() {
return content == null ? "" : content.trim();
}
public void setContent(String content) {
this.content = content;
}
public List<MobileContent> getMobileContents() {
return mobileContents == null ? new ArrayList<>() : mobileContents;
}
public void setMobileContents(List<MobileContent> mobileContents) {
this.mobileContents = mobileContents;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("{");
sb.append("\"shortMessageNo\":\"")
.append(shortMessageNo).append('\"');
sb.append(",\"exNo\":\"")
.append(exNo).append('\"');
sb.append(",\"mobiles\":")
.append(mobiles);
sb.append(",\"content\":\"")
.append(content).append('\"');
sb.append(",\"mobileContents\":")
.append(mobileContents);
sb.append('}');
return sb.toString();
}
}

View File

@ -0,0 +1,40 @@
package cn.com.tenlion.smssender.pojo.vos;
/**
* @ClassName: SmsSendVO
* @Description: 短信发送
* @Author: wanggeng
* @Date: 2022/12/7 16:04
* @Version: 1.0
*/
public class BaseSmsSendVO {
private String shortMessageNo;
private String exNo;
public String getShortMessageNo() {
return shortMessageNo == null ? "" : shortMessageNo.trim();
}
public void setShortMessageNo(String shortMessageNo) {
this.shortMessageNo = shortMessageNo;
}
public String getExNo() {
return exNo == null ? "" : exNo.trim();
}
public void setExNo(String exNo) {
this.exNo = exNo;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("{");
sb.append("\"shortMessageNo\":\"")
.append(shortMessageNo).append('\"');
sb.append(",\"exNo\":\"")
.append(exNo).append('\"');
sb.append('}');
return sb.toString();
}
}

View File

@ -0,0 +1,27 @@
package cn.com.tenlion.smssender.pojo.vos;
import cn.com.tenlion.smssender.pojo.MobileContent;
import java.util.ArrayList;
import java.util.List;
/**
* @ClassName: SmsSendVO
* @Description: 短信发送
* @Author: wanggeng
* @Date: 2022/12/7 16:04
* @Version: 1.0
*/
public class SmsP2PSendVO extends BaseSmsSendVO {
private List<MobileContent> mobileContents;
public List<MobileContent> getMobileContents() {
return mobileContents == null ? new ArrayList<>() : mobileContents;
}
public void setMobileContents(List<MobileContent> mobileContents) {
this.mobileContents = mobileContents;
}
}

View File

@ -0,0 +1,44 @@
package cn.com.tenlion.smssender.pojo.vos;
import java.util.ArrayList;
import java.util.List;
/**
* @ClassName: SmsSendVO
* @Description: 短信发送
* @Author: wanggeng
* @Date: 2022/12/7 16:04
* @Version: 1.0
*/
public class SmsSendVO extends BaseSmsSendVO {
private List<String> mobiles;
private String content;
public List<String> getMobiles() {
return mobiles == null ? new ArrayList<>() : mobiles;
}
public void setMobiles(List<String> mobiles) {
this.mobiles = mobiles;
}
public String getContent() {
return content == null ? "" : content.trim();
}
public void setContent(String content) {
this.content = content;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("{");
sb.append("\"mobiles\":")
.append(mobiles);
sb.append(",\"content\":\"")
.append(content).append('\"');
sb.append('}');
return sb.toString();
}
}

View File

@ -0,0 +1,30 @@
package cn.com.tenlion.smssender.remote;
import cn.com.tenlion.smssender.pojo.HuaChuangSmsSendResult;
import ink.wgink.annotation.rpc.rest.RemoteService;
import ink.wgink.annotation.rpc.rest.method.RemotePostMethod;
import ink.wgink.annotation.rpc.rest.params.RemoteFormParams;
import ink.wgink.annotation.rpc.rest.params.RemoteServerParams;
/**
* @ClassName: IHuaChuangSmsSendRemoteService
* @Description: 华创短信发送接口
* @Author: wanggeng
* @Date: 2022/12/6 21:08
* @Version: 1.0
*/
@RemoteService
public interface IHuaChuangSmsSendRemoteService {
@RemotePostMethod("sms")
HuaChuangSmsSendResult send(@RemoteServerParams String server,
@RemoteFormParams("action") String action,
@RemoteFormParams("account") String account,
@RemoteFormParams("password") String password,
@RemoteFormParams("mobile") String mobile,
@RemoteFormParams("content") String content,
@RemoteFormParams("mobileContentList") String mobileContents,
@RemoteFormParams("extno") String extno,
@RemoteFormParams("rt") String rt);
}

View File

@ -0,0 +1,45 @@
package cn.com.tenlion.smssender.service;
import cn.com.tenlion.smssender.dao.ISmsDao;
import cn.com.tenlion.smssender.enums.SmsSendStatus;
import cn.com.tenlion.smssender.pojo.HuaChuangSmsSendResult;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import java.util.HashMap;
import java.util.Map;
/**
* @ClassName: BaseSmsSendService
* @Description:
* @Author: wanggeng
* @Date: 2022/12/7 15:18
* @Version: 1.0
*/
public class BaseSmsSendService {
/**
* 修改状态
*
* @param smsDao
* @param shortMessageNo
* @param exNo
* @param sendResult
*/
protected void updateStatus(ISmsDao smsDao, String shortMessageNo, String exNo, HuaChuangSmsSendResult sendResult) {
String shortMessageTime = DateTime.now().toString(DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss"));
for (HuaChuangSmsSendResult.PhoneResult phoneResult : sendResult.getList()) {
Map<String, Object> params = new HashMap<>();
params.put("shortMessageUid", phoneResult.getMid());
params.put("shortMessageStatus", sendResult.getStatus() == 0 ? SmsSendStatus.SEND.getValue() : SmsSendStatus.ERROR.getValue());
params.put("shortMessageTime", shortMessageTime);
params.put("shortMessageRemark", sendResult.getMessage());
params.put("shortMessagePhone", phoneResult.getMobile());
params.put("shortMessageNo", shortMessageNo);
params.put("shortMessageExno", exNo);
smsDao.updateStatus(params);
}
}
}

View File

@ -0,0 +1,28 @@
package cn.com.tenlion.smssender.service;
import cn.com.tenlion.smssender.pojo.bos.HuaChuangSmsBO;
/**
* @ClassName: IHuaChuangSmsSendService
* @Description: 华创短信发送
* @Author: wanggeng
* @Date: 2022/12/6 21:34
* @Version: 1.0
*/
public interface IHuaChuangSmsSendService {
/**
* 发送短信
*
* @param huaChuangSmsBO
*/
void send(HuaChuangSmsBO huaChuangSmsBO);
/**
* 点对点发送短信
*
* @param huaChuangSmsBO
*/
void sendP2P(HuaChuangSmsBO huaChuangSmsBO);
}

View File

@ -0,0 +1,28 @@
package cn.com.tenlion.smssender.service;
import cn.com.tenlion.smssender.pojo.bos.HuaChuangSmsBO;
/**
* @ClassName: ISmsSendService
* @Description: 短信发送接口
* @Author: wanggeng
* @Date: 2022/12/7 15:44
* @Version: 1.0
*/
public interface ISmsSendService {
/**
* 发送短信
*
* @param huaChuangSmsBO
*/
void send(HuaChuangSmsBO huaChuangSmsBO);
/**
* 短信点对点发送
*
* @param huaChuangSmsBO
*/
void sendP2P(HuaChuangSmsBO huaChuangSmsBO);
}

View File

@ -0,0 +1,122 @@
package cn.com.tenlion.smssender.service.impl;
import cn.com.tenlion.smssender.config.HuaChuangSmsProperties;
import cn.com.tenlion.smssender.dao.ISmsDao;
import cn.com.tenlion.smssender.pojo.HuaChuangSmsSendResult;
import cn.com.tenlion.smssender.pojo.bos.HuaChuangSmsBO;
import cn.com.tenlion.smssender.remote.IHuaChuangSmsSendRemoteService;
import cn.com.tenlion.smssender.service.BaseSmsSendService;
import cn.com.tenlion.smssender.service.IHuaChuangSmsSendService;
import cn.com.tenlion.smssender.util.SmsUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
/**
* @ClassName: HuaChuangSmsSendServiceImpl
* @Description: 华创短信发送
* @Author: wanggeng
* @Date: 2022/12/6 21:37
* @Version: 1.0
*/
@Service
public class HuaChuangSmsSendServiceImpl extends BaseSmsSendService implements IHuaChuangSmsSendService {
private static final Logger LOG = LoggerFactory.getLogger(HuaChuangSmsSendServiceImpl.class);
@Autowired
private HuaChuangSmsProperties huaChuangSmsProperties;
@Autowired
private IHuaChuangSmsSendRemoteService huaChuangSmsSendRemoteService;
@Autowired
private ISmsDao smsDao;
@Override
@Transactional(rollbackFor = Exception.class)
public void send(HuaChuangSmsBO huaChuangSmsBO) {
if (StringUtils.isBlank(huaChuangSmsBO.getShortMessageNo())) {
LOG.error("Short message no is empty");
return;
}
if (huaChuangSmsBO.getMobiles().isEmpty()) {
LOG.error("Mobiles list emptyshortMessageNo{}", huaChuangSmsBO.getShortMessageNo());
return;
}
if (huaChuangSmsBO.getContent().isEmpty()) {
LOG.error("Content emptyshortMessageNo{}", huaChuangSmsBO.getShortMessageNo());
return;
}
LOG.debug("sms: {}", huaChuangSmsBO);
if (!huaChuangSmsProperties.getActive()) {
LOG.info("HuaChuang sms inactive");
return;
}
String exNo = huaChuangSmsProperties.getExtno() + huaChuangSmsBO.getExNo();
// 发送短信
HuaChuangSmsSendResult sendResult = huaChuangSmsSendRemoteService.send(
huaChuangSmsProperties.getUrl(),
"send",
huaChuangSmsProperties.getUsername(),
huaChuangSmsProperties.getPassword(),
SmsUtil.list2Str(huaChuangSmsBO.getMobiles(), ","),
huaChuangSmsBO.getContent(),
null,
exNo,
"json"
);
// 更新状态
LOG.debug("send result: {}", sendResult);
updateStatus(smsDao, huaChuangSmsBO.getShortMessageNo(), exNo, sendResult);
}
@Override
public void sendP2P(HuaChuangSmsBO huaChuangSmsBO) {
if (StringUtils.isBlank(huaChuangSmsBO.getShortMessageNo())) {
LOG.error("Short message no is empty");
return;
}
if (huaChuangSmsBO.getMobileContents().isEmpty()) {
LOG.error("Mobile content emptyshortMessageNo{}", huaChuangSmsBO.getShortMessageNo());
return;
}
LOG.debug("sms: {}", huaChuangSmsBO);
if (!huaChuangSmsProperties.getActive()) {
LOG.info("HuaChuang sms inactive");
return;
}
List<String> mobileContents = new ArrayList<>();
huaChuangSmsBO.getMobileContents().forEach(mobileContent -> {
if (StringUtils.isBlank(mobileContent.getMobile())) {
LOG.info("mobile is nullshortMessageNo: {}", huaChuangSmsBO.getShortMessageNo());
return;
}
if (StringUtils.isBlank(mobileContent.getContent())) {
LOG.info("content is nullshortMessageNo: {}, mobile: {}", huaChuangSmsBO.getShortMessageNo(), mobileContent.getMobile());
return;
}
mobileContents.add(mobileContent.getMobile() + "#" + mobileContent.getContent());
});
String exNo = huaChuangSmsProperties.getExtno() + huaChuangSmsBO.getExNo();
// 发送短信
HuaChuangSmsSendResult sendResult = huaChuangSmsSendRemoteService.send(
huaChuangSmsProperties.getUrl(),
"p2p",
huaChuangSmsProperties.getUsername(),
huaChuangSmsProperties.getPassword(),
null,
null,
SmsUtil.list2Str(mobileContents, "\n"),
exNo,
"json"
);
// 更新状态
LOG.debug("send result: {}", sendResult);
updateStatus(smsDao, huaChuangSmsBO.getShortMessageNo(), exNo, sendResult);
}
}

View File

@ -0,0 +1,31 @@
package cn.com.tenlion.smssender.service.impl;
import cn.com.tenlion.smssender.pojo.bos.HuaChuangSmsBO;
import cn.com.tenlion.smssender.service.IHuaChuangSmsSendService;
import cn.com.tenlion.smssender.service.ISmsSendService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @ClassName: SmsSendServiceImpl
* @Description: 短信发送
* @Author: wanggeng
* @Date: 2022/12/7 15:44
* @Version: 1.0
*/
@Service
public class SmsSendServiceImpl implements ISmsSendService {
@Autowired
private IHuaChuangSmsSendService huaChuangSmsSendService;
@Override
public void send(HuaChuangSmsBO huaChuangSmsBO) {
huaChuangSmsSendService.send(huaChuangSmsBO);
}
@Override
public void sendP2P(HuaChuangSmsBO huaChuangSmsBO) {
huaChuangSmsSendService.sendP2P(huaChuangSmsBO);
}
}

View File

@ -0,0 +1,28 @@
package cn.com.tenlion.smssender.util;
import java.util.List;
/**
* @ClassName: SmsUtil
* @Description:
* @Author: wanggeng
* @Date: 2022/12/6 22:59
* @Version: 1.0
*/
public class SmsUtil {
public static String list2Str(List<String> list, String split) {
if (list == null || list.isEmpty()) {
return null;
}
StringBuilder sb = new StringBuilder();
list.forEach(s -> {
if (sb.length() > 0) {
sb.append(split);
}
sb.append(s);
});
return sb.toString();
}
}

View File

@ -0,0 +1,85 @@
server:
port: 7777
servlet:
context-path: /sms
spring:
datasource:
druid:
url: jdbc:mysql://121.36.71.250:58082/db_cloud_smessage?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8&autoReconnect=true&failOverReadOnly=false&useSSL=false&serverTimezone=UTC&nullCatalogMeansCurrent=true
db-type: mysql
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: admin
initial-size: 2
min-idle: 2
max-active: 5
max-wait: 60000
time-between-eviction-runs-millis: 60000
min-evictable-idle-time-millis: 300000
validation-query: SELECT 1 FROM DUAL
test-while-idle: true
test-on-borrow: false
test-on-return: false
pool-prepared-statements: true
max-pool-prepared-statement-per-connection-size: 10
filter:
commons-log:
connection-logger-name: stat,wall,log4j
stat:
log-slow-sql: true
slow-sql-millis: 2000
connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
use-global-data-source-stat: true
kafka:
bootstrap-servers: 121.36.71.250:58030
producer:
# 发生错误后,消息重发的次数。
retries: 0
#当有多个消息需要被发送到同一个分区时,生产者会把它们放在同一个批次里。该参数指定了一个批次可以使用的内存大小,按照字节数计算。
batch-size: 16384
# 设置生产者内存缓冲区的大小。
buffer-memory: 33554432
# 键的序列化方式
key-serializer: org.apache.kafka.common.serialization.StringSerializer
# 值的序列化方式
value-serializer: org.apache.kafka.common.serialization.StringSerializer
# acks=0 生产者在成功写入消息之前不会等待任何来自服务器的响应。
# acks=1 只要集群的首领节点收到消息,生产者就会收到一个来自服务器成功响应。
# acks=all :只有当所有参与复制的节点全部收到消息时,生产者才会收到一个来自服务器的成功响应。
acks: 1
consumer:
# 自动提交的时间间隔 在spring boot 2.X 版本中这里采用的是值的类型为Duration 需要符合特定的格式如1S,1M,2H,5D
auto-commit-interval: 1S
# 该属性指定了消费者在读取一个没有偏移量的分区或者偏移量无效的情况下该作何处理:
# latest默认值在偏移量无效的情况下消费者将从最新的记录开始读取数据在消费者启动之后生成的记录
# earliest :在偏移量无效的情况下,消费者将从起始位置读取分区的记录
auto-offset-reset: earliest
# 是否自动提交偏移量默认值是true,为了避免出现重复数据和数据丢失可以把它设置为false,然后手动提交偏移量
enable-auto-commit: false
# 键的反序列化方式
key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
# 值的反序列化方式
value-deserializer: org.apache.kafka.common.serialization.StringDeserializer
listener:
# 在侦听器容器中运行的线程数。
concurrency: 5
#listner负责ack每调用一次就立即commit
ack-mode: manual_immediate
missing-topics-fatal: false
mybatis:
config-location: classpath:mybatis/mybatis-config.xml
mapper-locations: classpath*:mybatis/mapper/**/*.xml
sms:
hua-chuang:
active: true
url: https://124.239.153.233:8014
username: 922402
password: WT@6usGwKiantk
extno: 10690402
logging:
level:
ink.wgink: debug

View File

@ -0,0 +1,24 @@
<?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="cn.com.tenlion.smssender.dao.ISmsDao">
<!-- 修改状态 -->
<update id="updateStatus" parameterType="map">
UPDATE
m_smessage_short_message
SET
short_message_uid = #{shortMessageUid},
short_message_status = #{shortMessageStatus},
short_message_remark = #{shortMessageRemark},
short_message_time = #{shortMessageTime},
short_message_exno = #{shortMessageExno},
short_message_send_count = short_message_send_count + 1
WHERE
is_delete = 0
AND
short_message_phone = #{shortMessagePhone}
AND
short_message_no = #{shortMessageNo}
</update>
</mapper>

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<!-- 二级缓存默认false -->
<setting name="cacheEnabled" value="false"/>
</settings>
<typeAliases>
<typeAlias type="java.util.Map" alias="map"/>
<typeAlias type="java.util.List" alias="list"/>
</typeAliases>
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor"/>
</plugins>
</configuration>

View File

@ -0,0 +1,13 @@
package cn.com.tenlion.smssender;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class SmsSenderApplicationTests {
@Test
void contextLoads() {
}
}