mirror of
https://gitee.com/dromara/sms4j.git
synced 2025-12-06 17:08:40 +08:00
完成华为云国内短信接入
修改基础http支持框架为Forest 重构云片短信该http框架为Forest 重构模块,添加自动配置模块
This commit is contained in:
parent
1a561009d1
commit
d55a27ff6f
41
pom.xml
41
pom.xml
@ -4,7 +4,7 @@
|
|||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>kim.wind</groupId>
|
<groupId>kim.wind</groupId>
|
||||||
<artifactId>sms_aggregation</artifactId>
|
<artifactId>sms_aggregation</artifactId>
|
||||||
<version>1.0.2</version>
|
<version>1.0.3</version>
|
||||||
<name>sms-aggregation</name>
|
<name>sms-aggregation</name>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
<description>sms_aggregation</description>
|
<description>sms_aggregation</description>
|
||||||
@ -19,6 +19,7 @@
|
|||||||
<module>sms-aggregation-yunpian</module>
|
<module>sms-aggregation-yunpian</module>
|
||||||
<module>sms-aggregation-spring-boot-starter</module>
|
<module>sms-aggregation-spring-boot-starter</module>
|
||||||
<module>sms-aggregation-huawei</module>
|
<module>sms-aggregation-huawei</module>
|
||||||
|
<module>sms-aggregation-autoimmit</module>
|
||||||
</modules>
|
</modules>
|
||||||
<!-- 开源协议 apache 2.0 -->
|
<!-- 开源协议 apache 2.0 -->
|
||||||
<licenses>
|
<licenses>
|
||||||
@ -49,7 +50,7 @@
|
|||||||
<properties>
|
<properties>
|
||||||
<java.version>1.8</java.version>
|
<java.version>1.8</java.version>
|
||||||
<spring.boot.version>2.7.10</spring.boot.version>
|
<spring.boot.version>2.7.10</spring.boot.version>
|
||||||
<modules.version>1.0.2</modules.version>
|
<modules.version>1.0.3</modules.version>
|
||||||
<aliyun.version>2.0.23</aliyun.version>
|
<aliyun.version>2.0.23</aliyun.version>
|
||||||
<json.version>2.0.15</json.version>
|
<json.version>2.0.15</json.version>
|
||||||
<okhttp.version>3.14.9</okhttp.version>
|
<okhttp.version>3.14.9</okhttp.version>
|
||||||
@ -111,6 +112,12 @@
|
|||||||
<version>${modules.version}</version>
|
<version>${modules.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>kim.wind</groupId>
|
||||||
|
<artifactId>sms-aggregation-autoimmit</artifactId>
|
||||||
|
<version>${modules.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!--通用模块-->
|
<!--通用模块-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>kim.wind</groupId>
|
<groupId>kim.wind</groupId>
|
||||||
@ -130,12 +137,6 @@
|
|||||||
<groupId>com.aliyun</groupId>
|
<groupId>com.aliyun</groupId>
|
||||||
<artifactId>dysmsapi20170525</artifactId>
|
<artifactId>dysmsapi20170525</artifactId>
|
||||||
<version>${aliyun.version}</version>
|
<version>${aliyun.version}</version>
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<artifactId>okhttp</artifactId>
|
|
||||||
<groupId>com.squareup.okhttp3</groupId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- 阿里JSON解析器 -->
|
<!-- 阿里JSON解析器 -->
|
||||||
@ -143,20 +144,8 @@
|
|||||||
<groupId>com.alibaba</groupId>
|
<groupId>com.alibaba</groupId>
|
||||||
<artifactId>fastjson</artifactId>
|
<artifactId>fastjson</artifactId>
|
||||||
<version>${json.version}</version>
|
<version>${json.version}</version>
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>com.squareup.okhttp3</groupId>
|
|
||||||
<artifactId>okhttp</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- okhttp依赖-->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.squareup.okhttp3</groupId>
|
|
||||||
<artifactId>okhttp</artifactId>
|
|
||||||
<version>${okhttp.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<!--Forest依赖 声明式HTTP客户端框架-->
|
<!--Forest依赖 声明式HTTP客户端框架-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.dtflys.forest</groupId>
|
<groupId>com.dtflys.forest</groupId>
|
||||||
@ -184,12 +173,6 @@
|
|||||||
<groupId>com.apistd.uni</groupId>
|
<groupId>com.apistd.uni</groupId>
|
||||||
<artifactId>uni-sdk</artifactId>
|
<artifactId>uni-sdk</artifactId>
|
||||||
<version>${unisms.version}</version>
|
<version>${unisms.version}</version>
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<artifactId>okhttp</artifactId>
|
|
||||||
<groupId>com.squareup.okhttp3</groupId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- 腾讯云短信-->
|
<!-- 腾讯云短信-->
|
||||||
@ -197,12 +180,6 @@
|
|||||||
<groupId>com.tencentcloudapi</groupId>
|
<groupId>com.tencentcloudapi</groupId>
|
||||||
<artifactId>tencentcloud-sdk-java</artifactId>
|
<artifactId>tencentcloud-sdk-java</artifactId>
|
||||||
<version>${tencent.version}</version>
|
<version>${tencent.version}</version>
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<artifactId>okhttp</artifactId>
|
|
||||||
<groupId>com.squareup.okhttp3</groupId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|||||||
@ -5,13 +5,13 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>kim.wind</groupId>
|
<groupId>kim.wind</groupId>
|
||||||
<artifactId>sms_aggregation</artifactId>
|
<artifactId>sms_aggregation</artifactId>
|
||||||
<version>1.0.2</version>
|
<version>1.0.3</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>sms-aggregation-aliyun</artifactId>
|
<artifactId>sms-aggregation-aliyun</artifactId>
|
||||||
<name>sms-aggregation-aliyun</name>
|
<name>sms-aggregation-aliyun</name>
|
||||||
<description>sms-aggregation-aliyun</description>
|
<description>sms-aggregation-aliyun</description>
|
||||||
<version>1.0.2</version>
|
<version>1.0.3</version>
|
||||||
<properties>
|
<properties>
|
||||||
<java.version>1.8</java.version>
|
<java.version>1.8</java.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|||||||
@ -5,16 +5,16 @@ import com.aliyun.teaopenapi.models.Config;
|
|||||||
import kim.wind.sms.aliyun.service.AlibabaSmsImpl;
|
import kim.wind.sms.aliyun.service.AlibabaSmsImpl;
|
||||||
import kim.wind.sms.api.SmsBlend;
|
import kim.wind.sms.api.SmsBlend;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
|
||||||
|
@Data
|
||||||
@Configuration
|
@Configuration
|
||||||
@ConfigurationProperties(prefix = "sms.alibaba") //指定配置文件注入属性前缀
|
@ConfigurationProperties(prefix = "sms.alibaba") //指定配置文件注入属性前缀
|
||||||
@Data
|
@ConditionalOnProperty(name = "sms.supplier", havingValue = "alibaba")
|
||||||
@ConditionalOnProperty(prefix = "sms", name = "supplier", havingValue = "alibaba")
|
|
||||||
public class AlibabaSmsConfig {
|
public class AlibabaSmsConfig {
|
||||||
|
|
||||||
/** accessKey*/
|
/** accessKey*/
|
||||||
@ -32,7 +32,7 @@ public class AlibabaSmsConfig {
|
|||||||
|
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public Client config() throws Exception {
|
public Client client() throws Exception {
|
||||||
Config config = new Config()
|
Config config = new Config()
|
||||||
// AccessKey ID
|
// AccessKey ID
|
||||||
.setAccessKeyId(accessKeyId)
|
.setAccessKeyId(accessKeyId)
|
||||||
@ -43,8 +43,8 @@ public class AlibabaSmsConfig {
|
|||||||
return new Client(config);
|
return new Client(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Bean
|
@Bean
|
||||||
// public SmsBlend smsBlend(){
|
public SmsBlend smsBlend(){
|
||||||
// return new AlibabaSmsImpl();
|
return new AlibabaSmsImpl();
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,7 +15,7 @@ import kim.wind.sms.comm.annotation.Restricted;
|
|||||||
import kim.wind.sms.comm.delayedTime.DelayedTime;
|
import kim.wind.sms.comm.delayedTime.DelayedTime;
|
||||||
import kim.wind.sms.comm.entity.SmsResponse;
|
import kim.wind.sms.comm.entity.SmsResponse;
|
||||||
import kim.wind.sms.comm.exception.SmsBlendException;
|
import kim.wind.sms.comm.exception.SmsBlendException;
|
||||||
import kim.wind.sms.comm.utils.HTTPUtils;
|
import kim.wind.sms.comm.utils.http.HttpJsonTool;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
@ -111,7 +111,7 @@ public class AlibabaSmsImpl implements SmsBlend {
|
|||||||
try {
|
try {
|
||||||
SendBatchSmsResponse sendBatchSmsResponse = client.sendBatchSmsWithOptions(sendBatchSmsRequest, runtime);
|
SendBatchSmsResponse sendBatchSmsResponse = client.sendBatchSmsWithOptions(sendBatchSmsRequest, runtime);
|
||||||
smsResponse.setBizId(sendBatchSmsResponse.body.getBizId());
|
smsResponse.setBizId(sendBatchSmsResponse.body.getBizId());
|
||||||
smsResponse.setData(HTTPUtils.getJSONObject(sendBatchSmsResponse.body));
|
smsResponse.setData(HttpJsonTool.getJSONObject(sendBatchSmsResponse.body));
|
||||||
smsResponse.setCode(sendBatchSmsResponse.statusCode);
|
smsResponse.setCode(sendBatchSmsResponse.statusCode);
|
||||||
if (!"OK".equals(sendBatchSmsResponse.body.code)) {
|
if (!"OK".equals(sendBatchSmsResponse.body.code)) {
|
||||||
smsResponse.setErrMessage((sendBatchSmsResponse.body.message));
|
smsResponse.setErrMessage((sendBatchSmsResponse.body.message));
|
||||||
|
|||||||
@ -5,13 +5,13 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>kim.wind</groupId>
|
<groupId>kim.wind</groupId>
|
||||||
<artifactId>sms_aggregation</artifactId>
|
<artifactId>sms_aggregation</artifactId>
|
||||||
<version>1.0.2</version>
|
<version>1.0.3</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>sms-aggregation-api</artifactId>
|
<artifactId>sms-aggregation-api</artifactId>
|
||||||
<name>sms-aggregation-api</name>
|
<name>sms-aggregation-api</name>
|
||||||
<description>sms-aggregation-api</description>
|
<description>sms-aggregation-api</description>
|
||||||
<version>1.0.2</version>
|
<version>1.0.3</version>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<java.version>1.8</java.version>
|
<java.version>1.8</java.version>
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package kim.wind.sms.starter.config;
|
package kim.wind.sms.autoimmit.aop;
|
||||||
|
|
||||||
|
|
||||||
|
import kim.wind.sms.autoimmit.config.SmsConfig;
|
||||||
import kim.wind.sms.comm.exception.SmsBlendException;
|
import kim.wind.sms.comm.exception.SmsBlendException;
|
||||||
import kim.wind.sms.comm.utils.RedisUtils;
|
import kim.wind.sms.comm.utils.RedisUtils;
|
||||||
import kim.wind.sms.comm.utils.SmsUtil;
|
import kim.wind.sms.comm.utils.SmsUtil;
|
||||||
@ -23,7 +24,10 @@ public class AopAdvice {
|
|||||||
private static final String REDIS_KEY = "sms:restricted:";
|
private static final String REDIS_KEY = "sms:restricted:";
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private SmsMainConfig config;
|
private SmsConfig config;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SpringUtil springUtil;
|
||||||
|
|
||||||
|
|
||||||
@Pointcut("@annotation(kim.wind.sms.comm.annotation.Restricted)")
|
@Pointcut("@annotation(kim.wind.sms.comm.annotation.Restricted)")
|
||||||
@ -90,32 +94,36 @@ public class AopAdvice {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private SmsBlendException redisProcess(String args) throws Exception{
|
private SmsBlendException redisProcess(String args) throws Exception{
|
||||||
RedisUtils redis = SpringUtil.getBean(RedisUtils.class);
|
if (config.getRedisCache().equals("false")){
|
||||||
if (redis == null || config.getRedisCache().equals("false")){
|
|
||||||
return process(args);
|
return process(args);
|
||||||
}
|
}
|
||||||
|
// else {
|
||||||
|
// springUtil.createBean(RedisUtils.class.getName(),new RedisUtils());
|
||||||
|
// }
|
||||||
|
RedisUtils redis = SpringUtil.getBean(RedisUtils.class);
|
||||||
|
|
||||||
Integer accountMax = config.getAccountMax();//每日最大发送量
|
Integer accountMax = config.getAccountMax();//每日最大发送量
|
||||||
Integer minuteMax = config.getMinuteMax();//每分钟最大发送量
|
Integer minuteMax = config.getMinuteMax();//每分钟最大发送量
|
||||||
if (SmsUtil.isNotEmpty(accountMax)) { //是否配置了每日限制
|
if (SmsUtil.isNotEmpty(accountMax)) { //是否配置了每日限制
|
||||||
Integer i = (Integer) redis.getByKey(REDIS_KEY+args + "max");
|
Integer i = (Integer) redis.getByKey(REDIS_KEY+args + "max");
|
||||||
if (SmsUtil.isEmpty(i)) {
|
if (SmsUtil.isEmpty(i)) {
|
||||||
redis.set(REDIS_KEY+args + "max", 1);
|
redis.setOrTime(REDIS_KEY+args + "max", 1,accTimer/1000);
|
||||||
} else if (i > accountMax) {
|
} else if (i > accountMax) {
|
||||||
return new SmsBlendException("accountMax", args + "今日短信已达最大次数");
|
return new SmsBlendException("accountMax", args + "今日短信已达最大次数");
|
||||||
} else {
|
} else {
|
||||||
redis.set(REDIS_KEY+args + "max", i + 1);
|
redis.setOrTime(REDIS_KEY+args + "max", i + 1,accTimer/1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (SmsUtil.isNotEmpty(minuteMax)) { //是否配置了每分钟最大限制
|
if (SmsUtil.isNotEmpty(minuteMax)) { //是否配置了每分钟最大限制
|
||||||
Integer o = (Integer) redis.getByKey(REDIS_KEY+args);
|
Integer o = (Integer) redis.getByKey(REDIS_KEY+args);
|
||||||
if (SmsUtil.isNotEmpty(o)) {
|
if (SmsUtil.isNotEmpty(o)) {
|
||||||
if (o < minuteMax) {
|
if (o < minuteMax) {
|
||||||
redis.set(REDIS_KEY+args, o + 1);
|
redis.setOrTime(REDIS_KEY+args, o + 1,minTimer/1000);
|
||||||
} else {
|
} else {
|
||||||
return new SmsBlendException("minuteMax", args + "短信发送过于频繁!");
|
return new SmsBlendException("minuteMax", args + "短信发送过于频繁!");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
redis.set(REDIS_KEY+args, 1);
|
redis.setOrTime(REDIS_KEY+args, 1,minTimer/1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -0,0 +1,68 @@
|
|||||||
|
package kim.wind.sms.autoimmit.config;
|
||||||
|
|
||||||
|
import kim.wind.sms.autoimmit.aop.AopAdvice;
|
||||||
|
import kim.wind.sms.comm.config.SmsBanner;
|
||||||
|
import kim.wind.sms.comm.delayedTime.DelayedTime;
|
||||||
|
import kim.wind.sms.comm.utils.RedisUtils;
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||||
|
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class SmsAutowiredConfig {
|
||||||
|
public void init(){
|
||||||
|
SmsBanner.PrintBanner("V1.0.3");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConfigurationProperties(prefix = "sms") //指定配置文件注入属性前缀
|
||||||
|
public SmsConfig smsConfig(){
|
||||||
|
return new SmsConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 注入一个定时器*/
|
||||||
|
@Bean
|
||||||
|
public DelayedTime delayedTime(){
|
||||||
|
return new DelayedTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 如果启用了短信限制,则注入Aop组件*/
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnProperty(prefix = "sms", name = "restricted", havingValue = "true")
|
||||||
|
public AopAdvice aopAdvice(){
|
||||||
|
return new AopAdvice();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 如果启用了redis作为缓存则注入redis工具类*/
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnProperty(prefix = "sms", name = "redis-cache", havingValue = "true")
|
||||||
|
public RedisUtils redisUtils(){
|
||||||
|
return new RedisUtils();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 注入线程池*/
|
||||||
|
@Bean("smsExecutor")
|
||||||
|
protected Executor taskExecutor(SmsConfig config){
|
||||||
|
// 创建一个线程池对象
|
||||||
|
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
||||||
|
executor.setCorePoolSize(config.getCorePoolSize());
|
||||||
|
executor.setMaxPoolSize(config.getMaxPoolSize());
|
||||||
|
executor.setQueueCapacity(config.getQueueCapacity());
|
||||||
|
executor.setKeepAliveSeconds(config.getKeepAliveSeconds());
|
||||||
|
executor.setThreadNamePrefix(config.getThreadNamePrefix());
|
||||||
|
executor.setWaitForTasksToCompleteOnShutdown(true);
|
||||||
|
// 线程池对拒绝任务的处理策略,当线程池没有处理能力的时候,该策略会直接在 execute 方法的调用线程中运行被拒绝的任务;如果执行程序已关闭,则会丢弃该任务
|
||||||
|
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
|
||||||
|
//初始化线程池
|
||||||
|
executor.initialize();
|
||||||
|
return executor;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
package kim.wind.sms.autoimmit.config;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class SmsConfig {
|
||||||
|
/** 短信服务商*/
|
||||||
|
private String supplier;
|
||||||
|
/** 打印banner*/
|
||||||
|
private String isPrint = "true";
|
||||||
|
|
||||||
|
/** 是否开启短信限制*/
|
||||||
|
private String restricted;
|
||||||
|
|
||||||
|
/** 是否使用redis进行缓存*/
|
||||||
|
private String redisCache = "false";
|
||||||
|
|
||||||
|
/** 单账号每日最大发送量*/
|
||||||
|
private Integer accountMax;
|
||||||
|
|
||||||
|
/** 单账号每分钟最大发送*/
|
||||||
|
private Integer minuteMax;
|
||||||
|
|
||||||
|
/**核心线程池大小*/
|
||||||
|
private Integer corePoolSize = 10;
|
||||||
|
|
||||||
|
/** 最大线程数*/
|
||||||
|
private Integer maxPoolSize = 30;
|
||||||
|
|
||||||
|
/** 队列容量*/
|
||||||
|
private Integer queueCapacity = 50;
|
||||||
|
|
||||||
|
/** 活跃时间*/
|
||||||
|
private Integer keepAliveSeconds = 60;
|
||||||
|
|
||||||
|
/** 线程名字前缀*/
|
||||||
|
private String threadNamePrefix = "sms-executor-";
|
||||||
|
|
||||||
|
/** 设置线程池关闭的时候等待所有任务都完成再继续销毁其他的Bean*/
|
||||||
|
private Boolean shutdownStrategy = true;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -5,13 +5,13 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>kim.wind</groupId>
|
<groupId>kim.wind</groupId>
|
||||||
<artifactId>sms_aggregation</artifactId>
|
<artifactId>sms_aggregation</artifactId>
|
||||||
<version>1.0.2</version>
|
<version>1.0.3</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>sms-aggregation-comm</artifactId>
|
<artifactId>sms-aggregation-comm</artifactId>
|
||||||
<name>sms-aggregation-comm</name>
|
<name>sms-aggregation-comm</name>
|
||||||
<description>sms-aggregation-comm</description>
|
<description>sms-aggregation-comm</description>
|
||||||
<version>1.0.2</version>
|
<version>1.0.3</version>
|
||||||
<properties>
|
<properties>
|
||||||
<java.version>1.8</java.version>
|
<java.version>1.8</java.version>
|
||||||
</properties>
|
</properties>
|
||||||
@ -27,11 +27,6 @@
|
|||||||
<artifactId>fastjson</artifactId>
|
<artifactId>fastjson</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.squareup.okhttp3</groupId>
|
|
||||||
<artifactId>okhttp</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
package kim.wind.sms.comm.config;
|
package kim.wind.sms.comm.config;
|
||||||
|
|
||||||
|
import kim.wind.sms.comm.constant.Constant;
|
||||||
|
|
||||||
public class SmsBanner {
|
public class SmsBanner {
|
||||||
|
|
||||||
private static final String banner =
|
private static final String banner =
|
||||||
@ -10,8 +12,8 @@ public class SmsBanner {
|
|||||||
" ____) | | | | | ____) | / ____ \\ | |__| | | |__| | | | \\ \\ | |____ | |__| | / ____ \\ | | _| |_ | |__| | | |\\ |\n" +
|
" ____) | | | | | ____) | / ____ \\ | |__| | | |__| | | | \\ \\ | |____ | |__| | / ____ \\ | | _| |_ | |__| | | |\\ |\n" +
|
||||||
" |_____/ |_| |_| |_____/ /_/ \\_\\ \\_____| \\_____| |_| \\_\\ |______| \\_____| /_/ \\_\\ |_| |_____| \\____/ |_| \\_|\n" +
|
" |_____/ |_| |_| |_____/ /_/ \\_\\ \\_____| \\_____| |_| \\_\\ |______| \\_____| /_/ \\_\\ |_| |_____| \\____/ |_| \\_|\n" +
|
||||||
" \n" +
|
" \n" +
|
||||||
" V1.0.2";
|
" ";
|
||||||
public static void PrintBanner() {
|
public static void PrintBanner(String version) {
|
||||||
System.out.println(banner);
|
System.out.println(banner+version);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,41 @@
|
|||||||
|
package kim.wind.sms.comm.constant;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constant
|
||||||
|
* <p> 短信应用常量
|
||||||
|
*
|
||||||
|
* @author :Wind
|
||||||
|
* 2023/3/31 19:33
|
||||||
|
**/
|
||||||
|
public abstract class Constant {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用于格式化鉴权头域,给"Authorization"参数赋值
|
||||||
|
*/
|
||||||
|
public static final String HUAWEI_AUTH_HEADER_VALUE = "WSSE realm=\"SDP\",profile=\"UsernameToken\",type=\"Appkey\"";
|
||||||
|
/**
|
||||||
|
* 用于格式化鉴权头域,给"X-WSSE"参数赋值
|
||||||
|
*/
|
||||||
|
public static final String HUAWEI_WSSE_HEADER_FORMAT = "UsernameToken Username=\"%s\",PasswordDigest=\"%s\",Nonce=\"%s\",Created=\"%s\"";
|
||||||
|
/**
|
||||||
|
* 华为云国内短信访问URI
|
||||||
|
*/
|
||||||
|
public static final String HUAWEI_REQUEST_URL = "/sms/batchSendSms/v1";
|
||||||
|
/**
|
||||||
|
* Content-Type
|
||||||
|
*/
|
||||||
|
public static final String FROM_URLENCODED = "application/x-www-form-urlencoded";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 华为云规定 java时间格式
|
||||||
|
*/
|
||||||
|
public static final String HUAWEI_JAVA_DATE = "yyyy-MM-dd'T'HH:mm:ss'Z'";
|
||||||
|
|
||||||
|
/** 云片短信国内短信请求地址*/
|
||||||
|
public static final String YUNPIAN_URL = "https://sms.yunpian.com/v2";
|
||||||
|
|
||||||
|
|
||||||
|
private Constant() {
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -11,7 +11,7 @@ import lombok.Data;
|
|||||||
@Data
|
@Data
|
||||||
public class SmsResponse {
|
public class SmsResponse {
|
||||||
/** 状态码*/
|
/** 状态码*/
|
||||||
private Integer code;
|
private String code;
|
||||||
/** 返回消息*/
|
/** 返回消息*/
|
||||||
private String message;
|
private String message;
|
||||||
/** 错误码,没有错误信息则为空*/
|
/** 错误码,没有错误信息则为空*/
|
||||||
|
|||||||
@ -1,420 +0,0 @@
|
|||||||
package kim.wind.sms.comm.utils;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
|
||||||
import kim.wind.sms.comm.utils.http.OKResponse;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import okhttp3.*;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>类名: HTTPUtils
|
|
||||||
* <p>说明: 封装okhttp3,简单化请求创建流程,并且可以当做工具类进行自动装配使用
|
|
||||||
* <p>构建请求只需要获得OKHTTPUtils的对象,然后逐步调用即可
|
|
||||||
* <p>如:
|
|
||||||
* <p>http.setBaseURL("http://www.baidu.com").builder().get("/wenku").sync();
|
|
||||||
* <p>构建一个post请求只需要:
|
|
||||||
* <p>http.setBaseURL("http://www.baidu.com").builder().post("/wenku",object).sync();
|
|
||||||
* <p>如果在Spring Boot中作为组件自动装配使用,{@code baseURL}将读取配置文件中的{@code okhttp.url}获取默认的请求路径,则不需要再次调用 setBaseURL()方法进行设置
|
|
||||||
* <p>依赖于 {@code okhttp3} {@code alibaba.fastjson} {@code lombok.slf4j}
|
|
||||||
* <p>{@code
|
|
||||||
* <dependency>
|
|
||||||
* <groupId>com.squareup.okhttp3</groupId>
|
|
||||||
* <artifactId>okhttp</artifactId>
|
|
||||||
* <version>3.14.9</version>
|
|
||||||
* </dependency>}
|
|
||||||
* <p>{@code
|
|
||||||
* <dependency>
|
|
||||||
* <groupId>com.alibaba</groupId>
|
|
||||||
* <artifactId>fastjson</artifactId>
|
|
||||||
* <version>1.2.74</version>
|
|
||||||
*</dependency>}
|
|
||||||
*
|
|
||||||
* @author :Wind
|
|
||||||
* @date :2022/11/07 14:10
|
|
||||||
**/
|
|
||||||
@Slf4j
|
|
||||||
public class HTTPUtils {
|
|
||||||
/**
|
|
||||||
* 默认路径
|
|
||||||
*/
|
|
||||||
|
|
||||||
private String baseURL;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 保存的默认地址
|
|
||||||
*/
|
|
||||||
|
|
||||||
private String defaultURL;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 请求对象
|
|
||||||
*/
|
|
||||||
private volatile Request request;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 请求构建对象
|
|
||||||
*/
|
|
||||||
private Request.Builder builder;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* okhttp客户端
|
|
||||||
*/
|
|
||||||
private volatile OkHttpClient client;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 最终返回的对象
|
|
||||||
*/
|
|
||||||
private OKResponse okResponse;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 最终请求的url
|
|
||||||
*/
|
|
||||||
private String url = "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 请求头类型标注
|
|
||||||
*/
|
|
||||||
public MediaType json = MediaType.parse("application/json;charset=utf-8");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>说明:请求头类型标注
|
|
||||||
* @name: setMediaType
|
|
||||||
* @param
|
|
||||||
* @author :Wind
|
|
||||||
*/
|
|
||||||
public HTTPUtils setMediaType(String json) {
|
|
||||||
this.json = MediaType.parse(json);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 标记子线程处理状态
|
|
||||||
*/
|
|
||||||
private boolean isOK = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 说明:构建一个请求对象,该方法将返回对象本身,可以连锁调用,只有调用该方法后才可以调用get post等方法
|
|
||||||
*
|
|
||||||
* @name: builder
|
|
||||||
* @author :Wind
|
|
||||||
*/
|
|
||||||
public HTTPUtils builder() {
|
|
||||||
this.builder = new Request.Builder();
|
|
||||||
this.client = new OkHttpClient();
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>说明:设置一个通用的请求地址
|
|
||||||
* <p>如果不设置该地址则以输入的地址作为请求地址,如设置了改地址,会自动拼接之后builder时设置的地址
|
|
||||||
* <p>一旦设置该地址后,在重新获取对象或者调用{@link #defaultURL()}之前,配置文件中的默认地址将会被覆盖
|
|
||||||
*
|
|
||||||
* @param baseURL 设置一个通用的请求地址
|
|
||||||
* @name: setBaseURL
|
|
||||||
* @author :Wind
|
|
||||||
*/
|
|
||||||
public HTTPUtils setBaseURL(String baseURL) {
|
|
||||||
this.baseURL = baseURL;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>说明:设置回默认的请求路径(配置文件中路径)
|
|
||||||
* <p>
|
|
||||||
*
|
|
||||||
* @name: defaultURL
|
|
||||||
* @author :Wind
|
|
||||||
*/
|
|
||||||
public HTTPUtils defaultURL() {
|
|
||||||
this.baseURL = this.defaultURL;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 说明:向请求中设置heard
|
|
||||||
*
|
|
||||||
* @param key header的名称
|
|
||||||
* @param value header的值
|
|
||||||
* @name: headers
|
|
||||||
* @author :Wind
|
|
||||||
*/
|
|
||||||
public HTTPUtils headers(String key, String value) {
|
|
||||||
this.builder = builder.header(key, value);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 说明:向请求中设置heard
|
|
||||||
*
|
|
||||||
* @param map Map形式的header
|
|
||||||
* @name: headers
|
|
||||||
* @author :Wind
|
|
||||||
*/
|
|
||||||
public HTTPUtils headers(Map<String, String> map) {
|
|
||||||
for (Map.Entry<String, String> entry : map.entrySet()) {
|
|
||||||
this.builder = builder.header(entry.getKey(), entry.getValue());
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 说明:发送get请求
|
|
||||||
*
|
|
||||||
* @param url 要发送请求的url
|
|
||||||
* @param data 请求的参数
|
|
||||||
* @name: get
|
|
||||||
* @author :Wind
|
|
||||||
*/
|
|
||||||
public HTTPUtils get(String url, Map<String, String> data) {
|
|
||||||
Response response;
|
|
||||||
url = extracted(url);
|
|
||||||
url = getString(url, data);
|
|
||||||
log.info("请求路径:" + url);
|
|
||||||
this.request = builder.url(url).get().build();
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 说明:发送get请求
|
|
||||||
*
|
|
||||||
* @param url 要发送请求的url
|
|
||||||
* @name: get
|
|
||||||
* @author :Wind
|
|
||||||
*/
|
|
||||||
public HTTPUtils get(String url) {
|
|
||||||
return get(url, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 说明:以json为参数发送post请求
|
|
||||||
* 该方法使用了JSON进行序列化,一定确保传入的data为可序列化的
|
|
||||||
*
|
|
||||||
* @param url 请求路径
|
|
||||||
* @param data 请求数据尽量使用Map、Array、或实体类
|
|
||||||
* @name: post
|
|
||||||
* @author :Wind
|
|
||||||
*/
|
|
||||||
public HTTPUtils post(String url, Object data) {
|
|
||||||
url = extracted(url);
|
|
||||||
log.info("请求路径:" + url);
|
|
||||||
String s = JSON.toJSONString(data);
|
|
||||||
//将数据封装到RequestBody中
|
|
||||||
RequestBody fromBody = RequestBody.create(json, s);
|
|
||||||
this.request = builder.post(fromBody).url(url).build();
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>说明:发送格式为application/x-www-form-urlencoded的post请求
|
|
||||||
* @name: postOrBody
|
|
||||||
* @param
|
|
||||||
* @author :Wind
|
|
||||||
*/
|
|
||||||
public HTTPUtils postOrBody(String url, Map<String,String> data) {
|
|
||||||
url = extracted(url);
|
|
||||||
log.info("请求路径:" + url);
|
|
||||||
//将数据封装到RequestBody中
|
|
||||||
RequestBody fromBody = getPostRequestBody(data);
|
|
||||||
this.request = builder.post(fromBody).url(url).build();
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private RequestBody getPostRequestBody(Map<String,String> data){
|
|
||||||
FormBody.Builder builder1 = new FormBody.Builder();
|
|
||||||
data.forEach(builder1::add);
|
|
||||||
return builder1.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 说明:post请求,第三个参数为true时则请求的参数在query中,此时只接受 Map<String,String> 类型的参数
|
|
||||||
*
|
|
||||||
* @param url 请求路径
|
|
||||||
* @param query 在url中的参数
|
|
||||||
* @param isQuery 参数是否在query中
|
|
||||||
* @name: post
|
|
||||||
* @author :Wind
|
|
||||||
*/
|
|
||||||
public HTTPUtils post(String url, Map<String, String> query, boolean isQuery) {
|
|
||||||
if (isQuery) {
|
|
||||||
url = extracted(url);
|
|
||||||
String string = getString(url, query);
|
|
||||||
log.info("请求参数:" + string);
|
|
||||||
RequestBody fromBody = RequestBody.create(json, "");
|
|
||||||
this.request = builder.post(fromBody).url(url).build();
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
return post(url, query);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 说明:使用同步形式发送请求
|
|
||||||
*
|
|
||||||
* @return OKResponse 返回参数
|
|
||||||
* @name: sync
|
|
||||||
* @author :Wind
|
|
||||||
*/
|
|
||||||
public OKResponse sync() {
|
|
||||||
isBuild();
|
|
||||||
Response response;
|
|
||||||
try {
|
|
||||||
response = client.newCall(this.request).execute();
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
} finally {
|
|
||||||
url = "";
|
|
||||||
okResponse = null;
|
|
||||||
}
|
|
||||||
return new OKResponse().setBody(response.body()).setCode(response.code()).setHeaders(response.headers());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>说明:使用异步形式发送请求
|
|
||||||
* <p>该方法会启动一个高优先级子线程处理请求任务,但不会等待处理结果,直接返回调用对象,如需获取结果可以调用异步回调方法
|
|
||||||
* <p>{@link #asyncCallback()}
|
|
||||||
* <p>回调方法将会始终阻塞线程直至子线程处理完成返回结果</p>
|
|
||||||
*
|
|
||||||
* @return {@code OKResponse}
|
|
||||||
* @name: async
|
|
||||||
* @author :Wind
|
|
||||||
*/
|
|
||||||
public HTTPUtils async() {
|
|
||||||
HTTPUtils that = this;
|
|
||||||
Thread t = new Thread(() -> {
|
|
||||||
log.info("子线程开始执行");
|
|
||||||
that.okResponse = sync();
|
|
||||||
that.isOK = true;
|
|
||||||
log.info("子线程请求任务结束");
|
|
||||||
});
|
|
||||||
t.setPriority(Thread.MAX_PRIORITY);
|
|
||||||
t.start();
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>说明:使用异步形式发送请求
|
|
||||||
* <p>该方法会启动一个高优先级子线程处理请求任务,但不会等待处理结果,同时不会返回任何对象,处理完成的结果将会放置在调用对象的 {@link #okResponse}对象中</p>
|
|
||||||
* <p>回调方法将会始终阻塞线程直至子线程处理完成返回结果</p>
|
|
||||||
*
|
|
||||||
* @param NotWait
|
|
||||||
* @name: async
|
|
||||||
* @author :Wind
|
|
||||||
*/
|
|
||||||
public void async(boolean NotWait) {
|
|
||||||
async();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 说明:每200毫秒检测一次异步线程是否处理完成,否则将阻塞至此,直至尝试100次后抛出{@code RuntimeException("等待超时!")}
|
|
||||||
*
|
|
||||||
* @param
|
|
||||||
* @name: asyncCallback
|
|
||||||
* @author :Wind
|
|
||||||
*/
|
|
||||||
public OKResponse asyncCallback() {
|
|
||||||
OKResponse okResponse1 = null;
|
|
||||||
for (int i = 0; i <= 100; i++) {
|
|
||||||
if (isOK) break;
|
|
||||||
if (i == 100){
|
|
||||||
throw new RuntimeException("等待超时!");
|
|
||||||
}
|
|
||||||
log.info("第"+i+"次尝试获取数据");
|
|
||||||
try {
|
|
||||||
Thread.sleep(200);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
okResponse1 = getOkResponse();
|
|
||||||
} finally {
|
|
||||||
isOK = false;
|
|
||||||
okResponse = null;
|
|
||||||
url = "";
|
|
||||||
}
|
|
||||||
return okResponse1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 说明:将map中的数据拼接到请求地址之后
|
|
||||||
*
|
|
||||||
* @param add 地址
|
|
||||||
* @param map 请求参数
|
|
||||||
* @name: getString
|
|
||||||
* @author :Wind
|
|
||||||
*/
|
|
||||||
private String getString(String add, Map<String, String> map) {
|
|
||||||
if (map != null) {
|
|
||||||
StringBuilder addBuilder = new StringBuilder(add);
|
|
||||||
addBuilder.append("?");
|
|
||||||
for (Map.Entry<String, String> entry : map.entrySet()) {
|
|
||||||
addBuilder.append("&").append(entry.getKey()).append("=").append(entry.getValue());
|
|
||||||
}
|
|
||||||
add = addBuilder.toString();
|
|
||||||
}
|
|
||||||
return add;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 说明:拼接验证url地址
|
|
||||||
*
|
|
||||||
* @param url URL地址
|
|
||||||
* @name: extracted
|
|
||||||
* @author :Wind
|
|
||||||
*/
|
|
||||||
private String extracted(String url) {
|
|
||||||
this.url = "";
|
|
||||||
if (StringUtils.isEmpty(baseURL)) {
|
|
||||||
return this.url = url;
|
|
||||||
}
|
|
||||||
return this.url = baseURL + url;
|
|
||||||
}
|
|
||||||
|
|
||||||
public OKResponse getOkResponse() {
|
|
||||||
return this.okResponse;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void isBuild(){
|
|
||||||
if(this.builder == null){
|
|
||||||
throw new RuntimeException("非法调用!未构建请求对象!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>说明:将返回结果序列化到实体类中
|
|
||||||
* <p>传入对象必须实现了getter和setter方法,否则将序列化失败
|
|
||||||
* @name: getJSONBody
|
|
||||||
* @param t 要序列化的对象
|
|
||||||
* @author :Wind
|
|
||||||
*/
|
|
||||||
public static<T> T getJSONBody(OKResponse response, Class<T> t) {
|
|
||||||
try {
|
|
||||||
return JSONObject.parseObject(response.getBody().string(), t);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>说明:将返回结果序列化为一个json对象
|
|
||||||
* <p>
|
|
||||||
* @name: getJSONObject
|
|
||||||
* @param response
|
|
||||||
* @author :Wind
|
|
||||||
*/
|
|
||||||
public static JSONObject getJSONObject(OKResponse response){
|
|
||||||
try {
|
|
||||||
return JSONObject.parseObject(response.getBody().string());
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public static JSONObject getJSONObject(Object obj){
|
|
||||||
return JSONObject.parseObject(obj.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -2,10 +2,12 @@ package kim.wind.sms.comm.utils;
|
|||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||||
|
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
|
||||||
|
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@ -13,9 +15,28 @@ import java.util.concurrent.TimeUnit;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public class RedisUtils {
|
public class RedisUtils {
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private RedisTemplate<String, Object> redisTemplate;
|
private RedisTemplate<String, Object> redisTemplate;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public void init(RedisConnectionFactory connectionFactory){
|
||||||
|
// 指定相应的序列化方案
|
||||||
|
StringRedisSerializer keySerializer = new StringRedisSerializer();
|
||||||
|
JdkSerializationRedisSerializer valueSerializer = new JdkSerializationRedisSerializer();
|
||||||
|
// 构建StringRedisTemplate
|
||||||
|
StringRedisTemplate stringTemplate = new StringRedisTemplate();
|
||||||
|
stringTemplate.setConnectionFactory(connectionFactory);
|
||||||
|
stringTemplate.afterPropertiesSet();
|
||||||
|
// 构建RedisTemplate
|
||||||
|
RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
|
||||||
|
template.setConnectionFactory(connectionFactory);
|
||||||
|
template.setKeySerializer(keySerializer);
|
||||||
|
template.setHashKeySerializer(keySerializer);
|
||||||
|
template.setValueSerializer(valueSerializer);
|
||||||
|
template.setHashValueSerializer(valueSerializer);
|
||||||
|
template.afterPropertiesSet();
|
||||||
|
this.redisTemplate = template;
|
||||||
|
}
|
||||||
|
|
||||||
public RedisUtils() {
|
public RedisUtils() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package kim.wind.sms.comm.utils;
|
|||||||
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
public class SmsUtil {
|
public class SmsUtil {
|
||||||
@ -81,4 +82,17 @@ public class SmsUtil {
|
|||||||
return !isEmpty(str);
|
return !isEmpty(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String listToString(List<String> list) {
|
||||||
|
StringBuilder str = new StringBuilder();
|
||||||
|
for (int i = 0; i < list.size(); i++) {
|
||||||
|
if (i == list.size() - 1) {
|
||||||
|
str.append(list.get(i));
|
||||||
|
} else {
|
||||||
|
str.append(list.get(i));
|
||||||
|
str.append(",");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return str.toString();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,9 @@
|
|||||||
package kim.wind.sms.comm.utils;
|
package kim.wind.sms.comm.utils;
|
||||||
|
|
||||||
import org.springframework.beans.BeansException;
|
import org.springframework.beans.BeansException;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||||
|
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.context.ApplicationContextAware;
|
import org.springframework.context.ApplicationContextAware;
|
||||||
|
|
||||||
@ -14,6 +17,9 @@ public class SpringUtil implements ApplicationContextAware {
|
|||||||
|
|
||||||
private static ApplicationContext applicationContext;
|
private static ApplicationContext applicationContext;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
DefaultListableBeanFactory beanFactory;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||||
if(SpringUtil.applicationContext == null) {
|
if(SpringUtil.applicationContext == null) {
|
||||||
@ -49,4 +55,20 @@ public class SpringUtil implements ApplicationContextAware {
|
|||||||
return null ;
|
return null ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>说明:创建一个bean
|
||||||
|
* @name: createBean
|
||||||
|
* @param
|
||||||
|
* @author :Wind
|
||||||
|
*/
|
||||||
|
public void createBean(Class<?>clazz){
|
||||||
|
String name = clazz.getName();
|
||||||
|
beanFactory.createBean(clazz);
|
||||||
|
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
|
||||||
|
beanFactory.registerBeanDefinition(name, beanDefinitionBuilder.getBeanDefinition());
|
||||||
|
}
|
||||||
|
public void createBean(String name,Object o){
|
||||||
|
beanFactory.registerSingleton(name,o);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -46,9 +46,7 @@ public class TimeExpiredPoolCache {
|
|||||||
private static synchronized void syncInit() {
|
private static synchronized void syncInit() {
|
||||||
if (instance == null) {
|
if (instance == null) {
|
||||||
instance = new TimeExpiredPoolCache();
|
instance = new TimeExpiredPoolCache();
|
||||||
if (!persistenceInit()){
|
|
||||||
dataPool = new ConcurrentHashMap<String, DataWrapper<?>>();
|
dataPool = new ConcurrentHashMap<String, DataWrapper<?>>();
|
||||||
}
|
|
||||||
initTimer();
|
initTimer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -60,12 +58,15 @@ public class TimeExpiredPoolCache {
|
|||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 读取持久化文件*/
|
/**
|
||||||
|
* 读取持久化文件
|
||||||
|
*/
|
||||||
private static boolean persistenceInit() {
|
private static boolean persistenceInit() {
|
||||||
String path = FileTool.getPath() + FILE_TYPE;
|
String path = FileTool.getPath() + FILE_TYPE;
|
||||||
try {
|
try {
|
||||||
dataPool = JSONObject.parseObject(FileTool.readFile(path), ConcurrentHashMap.class);
|
|
||||||
if (dataPool != null){
|
DataWrapper d = JSONObject.parseObject(FileTool.readFile(path), DataWrapper.class);
|
||||||
|
if (dataPool != null) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} catch (IOException ignored) {
|
} catch (IOException ignored) {
|
||||||
@ -79,7 +80,6 @@ public class TimeExpiredPoolCache {
|
|||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
clearExpiredCaches();
|
clearExpiredCaches();
|
||||||
persistence();
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new SmsBlendException(e.getMessage());
|
throw new SmsBlendException(e.getMessage());
|
||||||
}
|
}
|
||||||
@ -87,10 +87,11 @@ public class TimeExpiredPoolCache {
|
|||||||
}, timerMillis, timerMillis);
|
}, timerMillis, timerMillis);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void persistence(){
|
/** 写入持久化文件*/
|
||||||
|
private static void persistence() {
|
||||||
String path = FileTool.getPath() + FILE_TYPE;
|
String path = FileTool.getPath() + FILE_TYPE;
|
||||||
FileTool.createFile(path);
|
FileTool.createFile(path);
|
||||||
FileTool.writeFile(new File(path),JSONObject.toJSONString(dataPool),false);
|
FileTool.writeFile(new File(path), JSONObject.toJSONString(dataPool), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -0,0 +1,35 @@
|
|||||||
|
package kim.wind.sms.comm.utils.http;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class HttpJsonTool {
|
||||||
|
|
||||||
|
|
||||||
|
public static <T> T getJSONBody(Object response,Class<T>t){
|
||||||
|
return JSONObject.parseObject(response.toString(), t);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> T getJSONBody(String response,Class<T>t){
|
||||||
|
return JSONObject.parseObject(response, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>说明:将返回结果序列化为一个json对象
|
||||||
|
* <p>
|
||||||
|
* @name: getJSONObject
|
||||||
|
* @param response
|
||||||
|
* @author :Wind
|
||||||
|
*/
|
||||||
|
public static JSONObject getJSONObject(OKResponse response){
|
||||||
|
try {
|
||||||
|
return JSONObject.parseObject(response.getBody().string());
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static JSONObject getJSONObject(Object obj){
|
||||||
|
return JSONObject.parseObject(obj.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -5,11 +5,11 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>kim.wind</groupId>
|
<groupId>kim.wind</groupId>
|
||||||
<artifactId>sms_aggregation</artifactId>
|
<artifactId>sms_aggregation</artifactId>
|
||||||
<version>1.0.2</version>
|
<version>1.0.3</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>sms-aggregation-huawei</artifactId>
|
<artifactId>sms-aggregation-huawei</artifactId>
|
||||||
<version>1.0.2</version>
|
<version>1.0.3</version>
|
||||||
<name>sms-aggregation-huawei</name>
|
<name>sms-aggregation-huawei</name>
|
||||||
<description>sms-aggregation-huawei</description>
|
<description>sms-aggregation-huawei</description>
|
||||||
|
|
||||||
|
|||||||
@ -1,11 +1,19 @@
|
|||||||
package kim.wind.sms.huawei.config;
|
package kim.wind.sms.huawei.config;
|
||||||
|
|
||||||
|
import com.dtflys.forest.Forest;
|
||||||
|
import com.dtflys.forest.config.ForestConfiguration;
|
||||||
|
import kim.wind.sms.api.SmsBlend;
|
||||||
|
import kim.wind.sms.huawei.service.HuaweiSmsImpl;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
|
||||||
@ConfigurationProperties(prefix = "sms.huawei") //指定配置文件注入属性前缀
|
|
||||||
@Data
|
@Data
|
||||||
|
@Configuration
|
||||||
|
@ConfigurationProperties(prefix = "sms.huawei") //指定配置文件注入属性前缀
|
||||||
|
@ConditionalOnProperty(name = "sms.supplier", havingValue = "huawei")
|
||||||
public class HuaweiSmsConfig {
|
public class HuaweiSmsConfig {
|
||||||
|
|
||||||
/** appKey*/
|
/** appKey*/
|
||||||
@ -22,5 +30,17 @@ public class HuaweiSmsConfig {
|
|||||||
private String statusCallBack;
|
private String statusCallBack;
|
||||||
/** APP接入地址*/
|
/** APP接入地址*/
|
||||||
private String url;
|
private String url;
|
||||||
|
/** 是否打印http请求日志*/
|
||||||
|
private Boolean httpLog = false;
|
||||||
|
|
||||||
|
@Bean("forestConfiguration")
|
||||||
|
public ForestConfiguration forestConfiguration(){
|
||||||
|
return Forest.config().setBackendName("httpclient").setLogEnabled(httpLog);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public SmsBlend smsBlend (){
|
||||||
|
return new HuaweiSmsImpl();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,34 +0,0 @@
|
|||||||
package kim.wind.sms.huawei.constant;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constant
|
|
||||||
* <p> 华为云短信应用常量
|
|
||||||
*
|
|
||||||
* @author :Wind
|
|
||||||
* 2023/3/31 19:33
|
|
||||||
**/
|
|
||||||
public abstract class Constant {
|
|
||||||
/**
|
|
||||||
* 用于格式化鉴权头域,给"Authorization"参数赋值
|
|
||||||
*/
|
|
||||||
public static final String AUTH_HEADER_VALUE = "WSSE realm=\"SDP\",profile=\"UsernameToken\",type=\"Appkey\"";
|
|
||||||
/**
|
|
||||||
* 用于格式化鉴权头域,给"X-WSSE"参数赋值
|
|
||||||
*/
|
|
||||||
public static final String WSSE_HEADER_FORMAT = "UsernameToken Username=\"%s\",PasswordDigest=\"%s\",Nonce=\"%s\",Created=\"%s\"";
|
|
||||||
/**
|
|
||||||
* 访问URI
|
|
||||||
*/
|
|
||||||
public static final String REQUEST_URL = "/sms/batchSendSms/v1";
|
|
||||||
/**
|
|
||||||
* Content-Type
|
|
||||||
*/
|
|
||||||
public static final String CONTENT_TYPE = "application/x-www-form-urlencoded";
|
|
||||||
/**
|
|
||||||
* 华为云规定 java时间格式
|
|
||||||
*/
|
|
||||||
public static final String JAVA_DATE = "yyyy-MM-dd'T'HH:mm:ss'Z'";
|
|
||||||
private Constant() {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -53,6 +53,6 @@ public enum HuaweiError {
|
|||||||
case "E200041":
|
case "E200041":
|
||||||
return E200041.getValue();
|
return E200041.getValue();
|
||||||
}
|
}
|
||||||
return "";
|
return "服务异常,请查看官方异常码,异常码:"+code;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,5 +22,5 @@ public class HuaweiResponse {
|
|||||||
|
|
||||||
/** 短信ID列表,当目的号码存在多个时,每个号码都会返回一个SmsID。
|
/** 短信ID列表,当目的号码存在多个时,每个号码都会返回一个SmsID。
|
||||||
当返回异常响应时不携带此字段*/
|
当返回异常响应时不携带此字段*/
|
||||||
private List<SmsId> smsId;
|
private List<SmsId> result;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,27 +1,25 @@
|
|||||||
package kim.wind.sms.huawei.service;
|
package kim.wind.sms.huawei.service;
|
||||||
|
|
||||||
|
import com.dtflys.forest.config.ForestConfiguration;
|
||||||
import kim.wind.sms.api.SmsBlend;
|
import kim.wind.sms.api.SmsBlend;
|
||||||
import kim.wind.sms.api.callback.CallBack;
|
import kim.wind.sms.api.callback.CallBack;
|
||||||
|
import kim.wind.sms.comm.annotation.Restricted;
|
||||||
|
import kim.wind.sms.comm.constant.Constant;
|
||||||
import kim.wind.sms.comm.delayedTime.DelayedTime;
|
import kim.wind.sms.comm.delayedTime.DelayedTime;
|
||||||
import kim.wind.sms.comm.entity.SmsResponse;
|
import kim.wind.sms.comm.entity.SmsResponse;
|
||||||
import kim.wind.sms.comm.utils.HTTPUtils;
|
|
||||||
import kim.wind.sms.comm.utils.http.OKResponse;
|
|
||||||
import kim.wind.sms.huawei.config.HuaweiSmsConfig;
|
import kim.wind.sms.huawei.config.HuaweiSmsConfig;
|
||||||
import kim.wind.sms.huawei.constant.Constant;
|
|
||||||
import kim.wind.sms.huawei.entity.HuaweiError;
|
|
||||||
import kim.wind.sms.huawei.entity.HuaweiResponse;
|
import kim.wind.sms.huawei.entity.HuaweiResponse;
|
||||||
import kim.wind.sms.huawei.entity.SmsId;
|
import kim.wind.sms.huawei.utils.HuaweiBuilder;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
|
import static kim.wind.sms.comm.utils.SmsUtil.listToString;
|
||||||
|
|
||||||
@EnableConfigurationProperties({HuaweiSmsConfig.class})
|
@EnableConfigurationProperties({HuaweiSmsConfig.class})
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class HuaweiSmsImpl implements SmsBlend {
|
public class HuaweiSmsImpl implements SmsBlend {
|
||||||
@ -37,17 +35,21 @@ public class HuaweiSmsImpl implements SmsBlend {
|
|||||||
private DelayedTime delayed;
|
private DelayedTime delayed;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private HTTPUtils http ;
|
@Qualifier("forestConfiguration")
|
||||||
|
private ForestConfiguration http;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Restricted
|
||||||
public SmsResponse sendMessage(String phone, String message) {
|
public SmsResponse sendMessage(String phone, String message) {
|
||||||
|
LinkedHashMap<String,String> mes = new LinkedHashMap<>();
|
||||||
|
mes.put(UUID.randomUUID().toString().replaceAll("-",""),message);
|
||||||
return null;
|
return sendMessage(phone,config.getTemplateId(),mes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Restricted
|
||||||
public SmsResponse sendMessage(String phone, String templateId, LinkedHashMap<String, String> messages) {
|
public SmsResponse sendMessage(String phone, String templateId, LinkedHashMap<String, String> messages) {
|
||||||
|
String url = config.getUrl() + Constant.HUAWEI_REQUEST_URL;
|
||||||
List<String> list = new ArrayList<>();
|
List<String> list = new ArrayList<>();
|
||||||
for (Map.Entry<String, String> entry : messages.entrySet()) {
|
for (Map.Entry<String, String> entry : messages.entrySet()) {
|
||||||
list.add(entry.getValue());
|
list.add(entry.getValue());
|
||||||
@ -55,73 +57,114 @@ public class HuaweiSmsImpl implements SmsBlend {
|
|||||||
String mess = HuaweiBuilder.listToString(list);
|
String mess = HuaweiBuilder.listToString(list);
|
||||||
String requestBody = HuaweiBuilder.buildRequestBody(config.getSender(), phone, config.getTemplateId(), mess, config.getStatusCallBack(), config.getSignature());
|
String requestBody = HuaweiBuilder.buildRequestBody(config.getSender(), phone, config.getTemplateId(), mess, config.getStatusCallBack(), config.getSignature());
|
||||||
Map<String,String> headers = new LinkedHashMap<>();
|
Map<String,String> headers = new LinkedHashMap<>();
|
||||||
headers.put("Authorization",Constant.AUTH_HEADER_VALUE);
|
headers.put("Authorization",Constant.HUAWEI_AUTH_HEADER_VALUE);
|
||||||
headers.put("X-WSSE",HuaweiBuilder.buildWsseHeader(config.getAppKey(), config.getAppSecret()));
|
headers.put("X-WSSE",HuaweiBuilder.buildWsseHeader(config.getAppKey(), config.getAppSecret()));
|
||||||
OKResponse response = http.setBaseURL(config.getUrl()).builder()
|
headers.put("Content-Type",Constant.FROM_URLENCODED);
|
||||||
.setMediaType(Constant.CONTENT_TYPE)
|
|
||||||
.headers(headers)
|
|
||||||
.post(Constant.REQUEST_URL, requestBody)
|
|
||||||
.sync();
|
|
||||||
HuaweiResponse jsonBody = response.getJSONBody(HuaweiResponse.class);
|
|
||||||
SmsResponse smsResponse = new SmsResponse();
|
SmsResponse smsResponse = new SmsResponse();
|
||||||
smsResponse.setCode(response.getCode());
|
http.post(url)
|
||||||
|
.addHeader(headers)
|
||||||
|
.addBody(requestBody)
|
||||||
|
.onSuccess(((data,req,res)->{
|
||||||
|
HuaweiResponse jsonBody = res.get(HuaweiResponse.class);
|
||||||
|
smsResponse.setCode(jsonBody.getCode());
|
||||||
smsResponse.setMessage(jsonBody.getDescription());
|
smsResponse.setMessage(jsonBody.getDescription());
|
||||||
SmsId smsId = jsonBody.getSmsId().get(0);
|
smsResponse.setBizId(jsonBody.getResult().get(0).getSmsMsgId());
|
||||||
smsResponse.setBizId(smsId.getSmsMsgId());
|
smsResponse.setData(jsonBody.getResult());
|
||||||
smsResponse.setData(jsonBody);
|
}))
|
||||||
if (response.getCode() != 200){
|
.onError((ex,req,res)->{
|
||||||
smsResponse.setErrMessage(HuaweiError.getValue(smsId.getStatus()));
|
HuaweiResponse huaweiResponse = res.get(HuaweiResponse.class);
|
||||||
}
|
smsResponse.setErrMessage(huaweiResponse.getDescription());
|
||||||
|
smsResponse.setErrorCode(huaweiResponse.getCode());
|
||||||
|
})
|
||||||
|
.execute();
|
||||||
return smsResponse;
|
return smsResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Restricted
|
||||||
public SmsResponse massTexting(List<String> phones, String message) {
|
public SmsResponse massTexting(List<String> phones, String message) {
|
||||||
return null;
|
return sendMessage(listToString(phones),message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Restricted
|
||||||
public SmsResponse massTexting(List<String> phones, String templateId, LinkedHashMap<String, String> messages) {
|
public SmsResponse massTexting(List<String> phones, String templateId, LinkedHashMap<String, String> messages) {
|
||||||
return null;
|
return sendMessage(listToString(phones), templateId, messages);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Restricted
|
||||||
public void sendMessageAsync(String phone, String message, CallBack callBack) {
|
public void sendMessageAsync(String phone, String message, CallBack callBack) {
|
||||||
|
pool.execute(() -> {
|
||||||
|
SmsResponse smsResponse = sendMessage(phone, message);
|
||||||
|
callBack.callBack(smsResponse);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Restricted
|
||||||
public void sendMessageAsync(String phone, String message) {
|
public void sendMessageAsync(String phone, String message) {
|
||||||
|
pool.execute(() -> sendMessage(phone, message));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Restricted
|
||||||
public void sendMessageAsync(String phone, String templateId, LinkedHashMap<String, String> messages, CallBack callBack) {
|
public void sendMessageAsync(String phone, String templateId, LinkedHashMap<String, String> messages, CallBack callBack) {
|
||||||
|
pool.execute(() -> {
|
||||||
|
SmsResponse smsResponse = sendMessage(phone, templateId, messages);
|
||||||
|
callBack.callBack(smsResponse);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Restricted
|
||||||
public void sendMessageAsync(String phone, String templateId, LinkedHashMap<String, String> messages) {
|
public void sendMessageAsync(String phone, String templateId, LinkedHashMap<String, String> messages) {
|
||||||
|
pool.execute(() -> {
|
||||||
|
sendMessage(phone, templateId, messages);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Restricted
|
||||||
public void delayedMessage(String phone, String message, Long delayedTime) {
|
public void delayedMessage(String phone, String message, Long delayedTime) {
|
||||||
|
this.delayed.schedule(new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
sendMessage(phone, message);
|
||||||
|
}
|
||||||
|
}, delayedTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Restricted
|
||||||
public void delayedMessage(String phone, String templateId, LinkedHashMap<String, String> messages, Long delayedTime) {
|
public void delayedMessage(String phone, String templateId, LinkedHashMap<String, String> messages, Long delayedTime) {
|
||||||
|
this.delayed.schedule(new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
sendMessage(phone, templateId, messages);
|
||||||
|
}
|
||||||
|
}, delayedTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Restricted
|
||||||
public void delayMassTexting(List<String> phones, String message, Long delayedTime) {
|
public void delayMassTexting(List<String> phones, String message, Long delayedTime) {
|
||||||
|
this.delayed.schedule(new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
massTexting(phones, message);
|
||||||
|
}
|
||||||
|
}, delayedTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Restricted
|
||||||
public void delayMassTexting(List<String> phones, String templateId, LinkedHashMap<String, String> messages, Long delayedTime) {
|
public void delayMassTexting(List<String> phones, String templateId, LinkedHashMap<String, String> messages, Long delayedTime) {
|
||||||
|
this.delayed.schedule(new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
massTexting(phones, templateId, messages);
|
||||||
|
}
|
||||||
|
}, delayedTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
package kim.wind.sms.huawei.service;
|
package kim.wind.sms.huawei.utils;
|
||||||
|
|
||||||
import kim.wind.sms.huawei.constant.Constant;
|
import kim.wind.sms.comm.constant.Constant;
|
||||||
import kim.wind.sms.huawei.entity.HuaweiError;
|
|
||||||
|
|
||||||
import javax.net.ssl.HttpsURLConnection;
|
import javax.net.ssl.HttpsURLConnection;
|
||||||
import javax.net.ssl.SSLContext;
|
import javax.net.ssl.SSLContext;
|
||||||
@ -25,7 +24,7 @@ public class HuaweiBuilder {
|
|||||||
* <p>构造X-WSSE参数值
|
* <p>构造X-WSSE参数值
|
||||||
* @author :Wind
|
* @author :Wind
|
||||||
*/
|
*/
|
||||||
static String buildWsseHeader(String appKey, String appSecret) {
|
public static String buildWsseHeader(String appKey, String appSecret) {
|
||||||
if (null == appKey || null == appSecret || appKey.isEmpty() || appSecret.isEmpty()) {
|
if (null == appKey || null == appSecret || appKey.isEmpty() || appSecret.isEmpty()) {
|
||||||
System.out.println("buildWsseHeader(): appKey or appSecret is null.");
|
System.out.println("buildWsseHeader(): appKey or appSecret is null.");
|
||||||
return null;
|
return null;
|
||||||
@ -46,7 +45,7 @@ public class HuaweiBuilder {
|
|||||||
String passwordDigestBase64Str = Base64.getEncoder().encodeToString(passwordDigest); //PasswordDigest
|
String passwordDigestBase64Str = Base64.getEncoder().encodeToString(passwordDigest); //PasswordDigest
|
||||||
//若passwordDigestBase64Str中包含换行符,请执行如下代码进行修正
|
//若passwordDigestBase64Str中包含换行符,请执行如下代码进行修正
|
||||||
//passwordDigestBase64Str = passwordDigestBase64Str.replaceAll("[\\s*\t\n\r]", "");
|
//passwordDigestBase64Str = passwordDigestBase64Str.replaceAll("[\\s*\t\n\r]", "");
|
||||||
return String.format(Constant.WSSE_HEADER_FORMAT, appKey, passwordDigestBase64Str, nonce, time);
|
return String.format(Constant.HUAWEI_WSSE_HEADER_FORMAT, appKey, passwordDigestBase64Str, nonce, time);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void trustAllHttpsCertificates() throws Exception {
|
static void trustAllHttpsCertificates() throws Exception {
|
||||||
@ -79,7 +78,7 @@ public class HuaweiBuilder {
|
|||||||
* @param signature | 签名名称,使用国内短信通用模板时填写
|
* @param signature | 签名名称,使用国内短信通用模板时填写
|
||||||
* @author :Wind
|
* @author :Wind
|
||||||
*/
|
*/
|
||||||
static String buildRequestBody(String sender, String receiver, String templateId, String templateParas,
|
public static String buildRequestBody(String sender, String receiver, String templateId, String templateParas,
|
||||||
String statusCallBack, String signature) {
|
String statusCallBack, String signature) {
|
||||||
if (null == sender || null == receiver || null == templateId || sender.isEmpty() || receiver.isEmpty()
|
if (null == sender || null == receiver || null == templateId || sender.isEmpty() || receiver.isEmpty()
|
||||||
|| templateId.isEmpty()) {
|
|| templateId.isEmpty()) {
|
||||||
@ -116,7 +115,7 @@ public class HuaweiBuilder {
|
|||||||
return sb.deleteCharAt(sb.length()-1).toString();
|
return sb.deleteCharAt(sb.length()-1).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
static String listToString(List<String> list){
|
public static String listToString(List<String> list){
|
||||||
StringBuilder stringBuffer = new StringBuilder();
|
StringBuilder stringBuffer = new StringBuilder();
|
||||||
stringBuffer.append("[\"");
|
stringBuffer.append("[\"");
|
||||||
for (String s : list) {
|
for (String s : list) {
|
||||||
@ -130,12 +129,12 @@ public class HuaweiBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static String dateFormat(Date date){
|
static String dateFormat(Date date){
|
||||||
SimpleDateFormat sdf = new SimpleDateFormat(Constant.JAVA_DATE);
|
SimpleDateFormat sdf = new SimpleDateFormat(Constant.HUAWEI_JAVA_DATE);
|
||||||
return sdf.format(date);
|
return sdf.format(date);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Date strForDate(String date){
|
static Date strForDate(String date){
|
||||||
SimpleDateFormat sdf = new SimpleDateFormat(Constant.JAVA_DATE);
|
SimpleDateFormat sdf = new SimpleDateFormat(Constant.HUAWEI_JAVA_DATE);
|
||||||
try {
|
try {
|
||||||
return sdf.parse(date);
|
return sdf.parse(date);
|
||||||
} catch (ParseException e) {
|
} catch (ParseException e) {
|
||||||
@ -5,13 +5,13 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>kim.wind</groupId>
|
<groupId>kim.wind</groupId>
|
||||||
<artifactId>sms_aggregation</artifactId>
|
<artifactId>sms_aggregation</artifactId>
|
||||||
<version>1.0.2</version>
|
<version>1.0.3</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>sms-aggregation-spring-boot-starter</artifactId>
|
<artifactId>sms-aggregation-spring-boot-starter</artifactId>
|
||||||
<name>sms-aggregation-spring-boot-starter</name>
|
<name>sms-aggregation-spring-boot-starter</name>
|
||||||
<description>sms-aggregation-spring-boot-starter</description>
|
<description>sms-aggregation-spring-boot-starter</description>
|
||||||
<version>1.0.2</version>
|
<version>1.0.3</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
@ -26,6 +26,11 @@
|
|||||||
<scope>import</scope>
|
<scope>import</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>kim.wind</groupId>
|
||||||
|
<artifactId>sms-aggregation-autoimmit</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter</artifactId>
|
<artifactId>spring-boot-starter</artifactId>
|
||||||
@ -33,46 +38,13 @@
|
|||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>kim.wind</groupId>
|
<groupId>kim.wind</groupId>
|
||||||
<artifactId>sms-aggregation-aliyun</artifactId>
|
<artifactId>sms-aggregation-autoimmit</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>kim.wind</groupId>
|
|
||||||
<artifactId>sms-aggregation-tencent</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>kim.wind</groupId>
|
|
||||||
<artifactId>sms-aggregation-unisms</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>kim.wind</groupId>
|
|
||||||
<artifactId>sms-aggregation-yunpian</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>kim.wind</groupId>
|
|
||||||
<artifactId>sms-aggregation-huawei</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!--aop依赖-->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-aop</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@ -1,148 +1,26 @@
|
|||||||
package kim.wind.sms.starter.config;
|
package kim.wind.sms.starter.config;
|
||||||
|
|
||||||
import kim.wind.sms.comm.utils.HTTPUtils;
|
import kim.wind.sms.autoimmit.config.SmsAutowiredConfig;
|
||||||
import kim.wind.sms.huawei.config.HuaweiSmsConfig;
|
|
||||||
import kim.wind.sms.huawei.service.HuaweiSmsImpl;
|
|
||||||
import kim.wind.sms.unisms.service.UniSmsImpl;
|
|
||||||
import kim.wind.sms.aliyun.service.AlibabaSmsImpl;
|
|
||||||
import kim.wind.sms.api.SmsBlend;
|
|
||||||
import kim.wind.sms.comm.config.SmsBanner;
|
|
||||||
import kim.wind.sms.comm.delayedTime.DelayedTime;
|
|
||||||
import kim.wind.sms.comm.utils.RedisUtils;
|
|
||||||
import kim.wind.sms.comm.utils.SpringUtil;
|
import kim.wind.sms.comm.utils.SpringUtil;
|
||||||
import kim.wind.sms.tencent.service.TencentSmsImpl;
|
|
||||||
import kim.wind.sms.yunpian.service.YunPianSmsImpl;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.scheduling.annotation.EnableAsync;
|
import org.springframework.scheduling.annotation.EnableAsync;
|
||||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
|
||||||
|
|
||||||
import java.util.concurrent.Executor;
|
|
||||||
import java.util.concurrent.ThreadPoolExecutor;
|
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@ConfigurationProperties(prefix = "sms") //指定配置文件注入属性前缀
|
|
||||||
@EnableAsync
|
@EnableAsync
|
||||||
@Data
|
@Data
|
||||||
public class SmsMainConfig {
|
public class SmsMainConfig {
|
||||||
|
|
||||||
/** 短信服务商*/
|
|
||||||
@Value("${sms.supplier}")
|
|
||||||
private String supplier;
|
|
||||||
/** 打印banner*/
|
|
||||||
private String isPrint = "true";
|
|
||||||
|
|
||||||
/** 是否开启短信限制*/
|
|
||||||
private String restricted;
|
|
||||||
|
|
||||||
/** 是否使用redis进行缓存*/
|
|
||||||
private String redisCache = "false";
|
|
||||||
|
|
||||||
/** 单账号每日最大发送量*/
|
|
||||||
private Integer accountMax;
|
|
||||||
|
|
||||||
/** 单账号每分钟最大发送*/
|
|
||||||
private Integer minuteMax;
|
|
||||||
|
|
||||||
/**核心线程池大小*/
|
|
||||||
private Integer corePoolSize = 10;
|
|
||||||
|
|
||||||
/** 最大线程数*/
|
|
||||||
private Integer maxPoolSize = 30;
|
|
||||||
|
|
||||||
/** 队列容量*/
|
|
||||||
private Integer queueCapacity = 50;
|
|
||||||
|
|
||||||
/** 活跃时间*/
|
|
||||||
private Integer keepAliveSeconds = 60;
|
|
||||||
|
|
||||||
/** 线程名字前缀*/
|
|
||||||
private String threadNamePrefix = "sms-executor-";
|
|
||||||
|
|
||||||
/** 设置线程池关闭的时候等待所有任务都完成再继续销毁其他的Bean*/
|
|
||||||
private Boolean shutdownStrategy = true;
|
|
||||||
|
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public SpringUtil springUtil(){
|
public SpringUtil springUtil(){
|
||||||
return new SpringUtil();
|
return new SpringUtil();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
/** 主要配置注入*/
|
||||||
@ConditionalOnProperty(prefix = "sms", name = "supplier", havingValue = "huawei")
|
@Bean(initMethod = "init")
|
||||||
public HuaweiSmsConfig huaweiSmsConfig(){
|
public SmsAutowiredConfig smsAutowiredConfig(){
|
||||||
return new HuaweiSmsConfig();
|
return new SmsAutowiredConfig();
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public HTTPUtils okhttpBean(){
|
|
||||||
return new HTTPUtils();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
@ConditionalOnProperty(prefix = "sms", name = "restricted", havingValue = "true")
|
|
||||||
public AopAdvice aopAdvice(){
|
|
||||||
return new AopAdvice();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 如果启用了redis作为缓存则注入redis工具类*/
|
|
||||||
@Bean
|
|
||||||
@ConditionalOnProperty(prefix = "sms", name = "redisCache", havingValue = "true")
|
|
||||||
public RedisUtils redisUtils(){
|
|
||||||
return new RedisUtils();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 注入一个定时器*/
|
|
||||||
@Bean
|
|
||||||
public DelayedTime delayedTime(){
|
|
||||||
return new DelayedTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public SmsBlend smsBlend(){
|
|
||||||
SmsBlend smsBlend = null;
|
|
||||||
switch (supplier){
|
|
||||||
case "alibaba":
|
|
||||||
smsBlend = new AlibabaSmsImpl();
|
|
||||||
break;
|
|
||||||
case "uniSms":
|
|
||||||
smsBlend = new UniSmsImpl();
|
|
||||||
break;
|
|
||||||
case "yunpian":
|
|
||||||
smsBlend = new YunPianSmsImpl();
|
|
||||||
break;
|
|
||||||
case "tencent":
|
|
||||||
smsBlend = new TencentSmsImpl();
|
|
||||||
break;
|
|
||||||
case "huawei":
|
|
||||||
smsBlend = new HuaweiSmsImpl();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ("true".equals(isPrint)){
|
|
||||||
SmsBanner.PrintBanner();
|
|
||||||
}
|
|
||||||
return smsBlend;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean("smsExecutor")
|
|
||||||
protected Executor taskExecutor(){
|
|
||||||
// 创建一个线程池对象
|
|
||||||
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
|
||||||
executor.setCorePoolSize(corePoolSize);
|
|
||||||
executor.setMaxPoolSize(maxPoolSize);
|
|
||||||
executor.setQueueCapacity(queueCapacity);
|
|
||||||
executor.setKeepAliveSeconds(keepAliveSeconds);
|
|
||||||
executor.setThreadNamePrefix(threadNamePrefix);
|
|
||||||
executor.setWaitForTasksToCompleteOnShutdown(true);
|
|
||||||
// 线程池对拒绝任务的处理策略,当线程池没有处理能力的时候,该策略会直接在 execute 方法的调用线程中运行被拒绝的任务;如果执行程序已关闭,则会丢弃该任务
|
|
||||||
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
|
|
||||||
//初始化线程池
|
|
||||||
executor.initialize();
|
|
||||||
return executor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,19 +0,0 @@
|
|||||||
package kim.wind.sms.starter.config;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.scheduling.annotation.EnableAsync;
|
|
||||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
|
||||||
|
|
||||||
import java.util.concurrent.Executor;
|
|
||||||
import java.util.concurrent.ThreadPoolExecutor;
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
@Data
|
|
||||||
public class TaskPoolConfig {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,3 +1,9 @@
|
|||||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||||
kim.wind.sms.starter.config.SmsMainConfig,\
|
kim.wind.sms.starter.config.SmsMainConfig,\
|
||||||
kim.wind.sms.aliyun.config.AlibabaSmsConfig
|
kim.wind.sms.autoimmit.config.SmsAutowiredConfig,\
|
||||||
|
kim.wind.sms.aliyun.config.AlibabaSmsConfig,\
|
||||||
|
kim.wind.sms.huawei.config.HuaweiSmsConfig,\
|
||||||
|
kim.wind.sms.tencent.config.TencentSmsConfig,\
|
||||||
|
kim.wind.sms.unisms.config.UniSmsConfig,\
|
||||||
|
kim.wind.sms.yunpian.config.YunPianSmsConfig
|
||||||
|
|
||||||
|
|||||||
@ -5,13 +5,13 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>kim.wind</groupId>
|
<groupId>kim.wind</groupId>
|
||||||
<artifactId>sms_aggregation</artifactId>
|
<artifactId>sms_aggregation</artifactId>
|
||||||
<version>1.0.2</version>
|
<version>1.0.3</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>sms-aggregation-tencent</artifactId>
|
<artifactId>sms-aggregation-tencent</artifactId>
|
||||||
<name>sms-aggregation-tencent</name>
|
<name>sms-aggregation-tencent</name>
|
||||||
<description>sms-aggregation-tencent</description>
|
<description>sms-aggregation-tencent</description>
|
||||||
<version>1.0.2</version>
|
<version>1.0.3</version>
|
||||||
<properties>
|
<properties>
|
||||||
<java.version>1.8</java.version>
|
<java.version>1.8</java.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|||||||
@ -4,16 +4,18 @@ import com.tencentcloudapi.common.Credential;
|
|||||||
import com.tencentcloudapi.common.profile.ClientProfile;
|
import com.tencentcloudapi.common.profile.ClientProfile;
|
||||||
import com.tencentcloudapi.common.profile.HttpProfile;
|
import com.tencentcloudapi.common.profile.HttpProfile;
|
||||||
import com.tencentcloudapi.sms.v20210111.SmsClient;
|
import com.tencentcloudapi.sms.v20210111.SmsClient;
|
||||||
|
import kim.wind.sms.api.SmsBlend;
|
||||||
|
import kim.wind.sms.tencent.service.TencentSmsImpl;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@Data
|
||||||
@Configuration
|
@Configuration
|
||||||
@ConfigurationProperties(prefix = "sms.tencent") //指定配置文件注入属性前缀
|
@ConfigurationProperties(prefix = "sms.tencent") //指定配置文件注入属性前缀
|
||||||
@Data
|
@ConditionalOnProperty(name = "sms.supplier", havingValue = "tencent")
|
||||||
@ConditionalOnProperty(prefix = "sms", name = "supplier", havingValue = "tencent")
|
|
||||||
public class TencentSmsConfig {
|
public class TencentSmsConfig {
|
||||||
|
|
||||||
/** 应用accessKey*/
|
/** 应用accessKey*/
|
||||||
@ -49,4 +51,9 @@ public class TencentSmsConfig {
|
|||||||
clientProfile.setHttpProfile(httpProfile);
|
clientProfile.setHttpProfile(httpProfile);
|
||||||
return new SmsClient(cred, territory,clientProfile);
|
return new SmsClient(cred, territory,clientProfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public SmsBlend smsBlend(){
|
||||||
|
return new TencentSmsImpl();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,13 +5,13 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>kim.wind</groupId>
|
<groupId>kim.wind</groupId>
|
||||||
<artifactId>sms_aggregation</artifactId>
|
<artifactId>sms_aggregation</artifactId>
|
||||||
<version>1.0.2</version>
|
<version>1.0.3</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>sms-aggregation-unisms</artifactId>
|
<artifactId>sms-aggregation-unisms</artifactId>
|
||||||
<name>sms-aggregation-unisms</name>
|
<name>sms-aggregation-unisms</name>
|
||||||
<description>sms-aggregation-unisms</description>
|
<description>sms-aggregation-unisms</description>
|
||||||
<version>1.0.2</version>
|
<version>1.0.3</version>
|
||||||
<properties>
|
<properties>
|
||||||
<java.version>1.8</java.version>
|
<java.version>1.8</java.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|||||||
@ -1,16 +1,18 @@
|
|||||||
package kim.wind.sms.unisms.config;
|
package kim.wind.sms.unisms.config;
|
||||||
|
|
||||||
import com.apistd.uni.Uni;
|
import com.apistd.uni.Uni;
|
||||||
|
import kim.wind.sms.api.SmsBlend;
|
||||||
|
import kim.wind.sms.unisms.service.UniSmsImpl;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@Data
|
||||||
@Configuration
|
@Configuration
|
||||||
@ConfigurationProperties(prefix = "sms.uni-sms") //指定配置文件注入属性前缀
|
@ConfigurationProperties(prefix = "sms.uni-sms") //指定配置文件注入属性前缀
|
||||||
@Data
|
@ConditionalOnProperty(name = "sms.supplier", havingValue = "uniSms")
|
||||||
@ConditionalOnProperty(prefix = "sms", name = "supplier", havingValue = "uni-sms")
|
|
||||||
public class UniSmsConfig {
|
public class UniSmsConfig {
|
||||||
|
|
||||||
/** 访问键标识*/
|
/** 访问键标识*/
|
||||||
@ -35,4 +37,9 @@ public class UniSmsConfig {
|
|||||||
Uni.init(accessKeyId,accessKeySecret);
|
Uni.init(accessKeyId,accessKeySecret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public SmsBlend smsBlend(){
|
||||||
|
return new UniSmsImpl();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,14 +3,14 @@ package kim.wind.sms.unisms.service;
|
|||||||
import com.apistd.uni.UniResponse;
|
import com.apistd.uni.UniResponse;
|
||||||
import com.apistd.uni.sms.UniMessage;
|
import com.apistd.uni.sms.UniMessage;
|
||||||
import com.apistd.uni.sms.UniSMS;
|
import com.apistd.uni.sms.UniSMS;
|
||||||
import kim.wind.sms.unisms.config.UniSmsConfig;
|
|
||||||
import kim.wind.sms.api.SmsBlend;
|
import kim.wind.sms.api.SmsBlend;
|
||||||
import kim.wind.sms.api.callback.CallBack;
|
import kim.wind.sms.api.callback.CallBack;
|
||||||
import kim.wind.sms.comm.annotation.Restricted;
|
import kim.wind.sms.comm.annotation.Restricted;
|
||||||
import kim.wind.sms.comm.delayedTime.DelayedTime;
|
import kim.wind.sms.comm.delayedTime.DelayedTime;
|
||||||
import kim.wind.sms.comm.entity.SmsResponse;
|
import kim.wind.sms.comm.entity.SmsResponse;
|
||||||
import kim.wind.sms.comm.exception.SmsBlendException;
|
import kim.wind.sms.comm.exception.SmsBlendException;
|
||||||
import kim.wind.sms.comm.utils.HTTPUtils;
|
import kim.wind.sms.comm.utils.http.HttpJsonTool;
|
||||||
|
import kim.wind.sms.unisms.config.UniSmsConfig;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
@ -169,7 +169,7 @@ public class UniSmsImpl implements SmsBlend {
|
|||||||
smsResponse.setErrorCode(send.code);
|
smsResponse.setErrorCode(send.code);
|
||||||
smsResponse.setMessage(send.message);
|
smsResponse.setMessage(send.message);
|
||||||
smsResponse.setBizId(send.requestId);
|
smsResponse.setBizId(send.requestId);
|
||||||
smsResponse.setData(HTTPUtils.getJSONObject(send));
|
smsResponse.setData(HttpJsonTool.getJSONObject(send));
|
||||||
}catch(Exception e){
|
}catch(Exception e){
|
||||||
smsResponse.setErrMessage(e.getMessage());
|
smsResponse.setErrMessage(e.getMessage());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,14 +5,14 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>kim.wind</groupId>
|
<groupId>kim.wind</groupId>
|
||||||
<artifactId>sms_aggregation</artifactId>
|
<artifactId>sms_aggregation</artifactId>
|
||||||
<version>1.0.2</version>
|
<version>1.0.3</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>sms-aggregation-yunpian</artifactId>
|
<artifactId>sms-aggregation-yunpian</artifactId>
|
||||||
<name>sms-aggregation-yunpian</name>
|
<name>sms-aggregation-yunpian</name>
|
||||||
<description>sms-aggregation-yunpian</description>
|
<description>sms-aggregation-yunpian</description>
|
||||||
<version>1.0.2</version>
|
<version>1.0.3</version>
|
||||||
<properties>
|
<properties>
|
||||||
<java.version>1.8</java.version>
|
<java.version>1.8</java.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|||||||
@ -1,16 +1,52 @@
|
|||||||
package kim.wind.sms.yunpian.config;
|
package kim.wind.sms.yunpian.config;
|
||||||
|
|
||||||
|
import com.dtflys.forest.Forest;
|
||||||
|
import com.dtflys.forest.config.ForestConfiguration;
|
||||||
|
import kim.wind.sms.api.SmsBlend;
|
||||||
|
import kim.wind.sms.yunpian.service.YunPianSmsImpl;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@Data
|
||||||
@Configuration
|
@Configuration
|
||||||
@ConfigurationProperties(prefix = "sms.yunpian") //指定配置文件注入属性前缀
|
@ConfigurationProperties(prefix = "sms.yunpian") //指定配置文件注入属性前缀
|
||||||
@Data
|
@ConditionalOnProperty(name = "sms.supplier", havingValue = "yunpian")
|
||||||
@ConditionalOnProperty(prefix = "sms", name = "supplier", havingValue = "yunpian")
|
|
||||||
public class YunPianSmsConfig {
|
public class YunPianSmsConfig {
|
||||||
/** 账号唯一标识*/
|
/**
|
||||||
|
* 账号唯一标识
|
||||||
|
*/
|
||||||
private String apikey;
|
private String apikey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 短信发送后将向这个地址推送(运营商返回的)发送报告
|
||||||
|
*/
|
||||||
|
private String callbackUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模板Id
|
||||||
|
*/
|
||||||
|
private String templateId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模板变量名称
|
||||||
|
*/
|
||||||
|
private String templateName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否打印http请求日志
|
||||||
|
*/
|
||||||
|
private Boolean httpLog = false;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ForestConfiguration forestConfiguration() {
|
||||||
|
return Forest.config().setBackendName("httpclient").setLogEnabled(httpLog);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public SmsBlend smsBlend() {
|
||||||
|
return new YunPianSmsImpl();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,20 +1,24 @@
|
|||||||
package kim.wind.sms.yunpian.service;
|
package kim.wind.sms.yunpian.service;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.dtflys.forest.config.ForestConfiguration;
|
||||||
import kim.wind.sms.api.SmsBlend;
|
import kim.wind.sms.api.SmsBlend;
|
||||||
import kim.wind.sms.api.callback.CallBack;
|
import kim.wind.sms.api.callback.CallBack;
|
||||||
import kim.wind.sms.comm.annotation.Restricted;
|
import kim.wind.sms.comm.annotation.Restricted;
|
||||||
|
import kim.wind.sms.comm.constant.Constant;
|
||||||
import kim.wind.sms.comm.delayedTime.DelayedTime;
|
import kim.wind.sms.comm.delayedTime.DelayedTime;
|
||||||
import kim.wind.sms.comm.entity.SmsResponse;
|
import kim.wind.sms.comm.entity.SmsResponse;
|
||||||
import kim.wind.sms.comm.exception.SmsBlendException;
|
import kim.wind.sms.comm.exception.SmsBlendException;
|
||||||
import kim.wind.sms.comm.utils.HTTPUtils;
|
|
||||||
import kim.wind.sms.comm.utils.http.OKResponse;
|
|
||||||
import kim.wind.sms.yunpian.config.YunPianSmsConfig;
|
import kim.wind.sms.yunpian.config.YunPianSmsConfig;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
|
import static kim.wind.sms.comm.utils.SmsUtil.listToString;
|
||||||
|
|
||||||
public class YunPianSmsImpl implements SmsBlend {
|
public class YunPianSmsImpl implements SmsBlend {
|
||||||
|
|
||||||
@ -26,75 +30,42 @@ public class YunPianSmsImpl implements SmsBlend {
|
|||||||
private DelayedTime delayed;
|
private DelayedTime delayed;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private HTTPUtils http ;
|
private YunPianSmsConfig config;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private YunPianSmsConfig config;
|
private ForestConfiguration http;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Restricted
|
@Restricted
|
||||||
public SmsResponse sendMessage(String phone, String message) {
|
public SmsResponse sendMessage(String phone, String message) {
|
||||||
Map<String,String> body = new HashMap<>();
|
Map<String, String> body = setBody(phone, message, null);
|
||||||
body.put("apikey",config.getApikey());
|
return getSendResponse(body);
|
||||||
body.put("mobile",phone);
|
|
||||||
return getSmsResponse(message, body);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Restricted
|
@Restricted
|
||||||
public SmsResponse sendMessage(String phone, String templateId, LinkedHashMap<String, String> messages) {
|
public SmsResponse sendMessage(String phone, String templateId, LinkedHashMap<String, String> messages) {
|
||||||
Map<String,String> body = new HashMap<>();
|
Map<String, String> body = setBody(phone, "", messages);
|
||||||
body.put("apikey",config.getApikey());
|
return getSendResponse(body);
|
||||||
body.put("mobile",phone);
|
|
||||||
body.put("tpl_id",templateId);
|
|
||||||
body.put("tpl_value",formattingMap(messages));
|
|
||||||
Map<String,String> map = new HashMap<>();
|
|
||||||
map.put("Accept","application/json;charset=utf-8");
|
|
||||||
OKResponse sync = http.setBaseURL("https://sms.yunpian.com/v2").builder()
|
|
||||||
.headers(map)
|
|
||||||
.postOrBody("/sms/tpl_single_send.json", body)
|
|
||||||
.sync();
|
|
||||||
SmsResponse smsResponse = new SmsResponse();
|
|
||||||
smsResponse.setCode(sync.getCode());
|
|
||||||
JSONObject jsonObject = HTTPUtils.getJSONObject(sync);
|
|
||||||
smsResponse.setData(jsonObject);
|
|
||||||
return smsResponse;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Restricted
|
@Restricted
|
||||||
public SmsResponse massTexting(List<String> phones, String message) {
|
public SmsResponse massTexting(List<String> phones, String message) {
|
||||||
if (phones.size()>1000){
|
if (phones.size() > 1000) {
|
||||||
throw new SmsBlendException("单次发送超过最大发送上限,建议每次群发短信人数低于1000");
|
throw new SmsBlendException("单次发送超过最大发送上限,建议每次群发短信人数低于1000");
|
||||||
}
|
}
|
||||||
Map<String,String> body = new HashMap<>();
|
return sendMessage(listToString(phones),message);
|
||||||
body.put("apikey",config.getApikey());
|
|
||||||
body.put("mobile",listToString(phones));
|
|
||||||
return getSmsResponse(message, body);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Restricted
|
@Restricted
|
||||||
public SmsResponse massTexting(List<String> phones, String templateId, LinkedHashMap<String, String> messages) {
|
public SmsResponse massTexting(List<String> phones, String templateId, LinkedHashMap<String, String> messages) {
|
||||||
if (phones.size()>1000){
|
if (phones.size() > 1000) {
|
||||||
throw new SmsBlendException("单次发送超过最大发送上限,建议每次群发短信人数低于1000");
|
throw new SmsBlendException("单次发送超过最大发送上限,建议每次群发短信人数低于1000");
|
||||||
}
|
}
|
||||||
Map<String,String> body = new HashMap<>();
|
return sendMessage(listToString(phones), templateId, messages);
|
||||||
body.put("apikey",config.getApikey());
|
|
||||||
body.put("mobile",listToString(phones));
|
|
||||||
body.put("tpl_id",templateId);
|
|
||||||
body.put("tpl_value",formattingMap(messages));
|
|
||||||
Map<String,String> map = new HashMap<>();
|
|
||||||
map.put("Accept","application/json;charset=utf-8");
|
|
||||||
OKResponse sync = http.setBaseURL("https://sms.yunpian.com/v2").builder()
|
|
||||||
.headers(map)
|
|
||||||
.postOrBody("/tpl_batch_send.json", body)
|
|
||||||
.sync();
|
|
||||||
SmsResponse smsResponse = new SmsResponse();
|
|
||||||
smsResponse.setCode(sync.getCode());
|
|
||||||
JSONObject jsonObject = HTTPUtils.getJSONObject(sync);
|
|
||||||
smsResponse.setData(jsonObject);
|
|
||||||
return smsResponse;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -115,8 +86,8 @@ public class YunPianSmsImpl implements SmsBlend {
|
|||||||
@Override
|
@Override
|
||||||
@Restricted
|
@Restricted
|
||||||
public void sendMessageAsync(String phone, String templateId, LinkedHashMap<String, String> messages, CallBack callBack) {
|
public void sendMessageAsync(String phone, String templateId, LinkedHashMap<String, String> messages, CallBack callBack) {
|
||||||
pool.execute(()->{
|
pool.execute(() -> {
|
||||||
SmsResponse smsResponse = sendMessage(phone,templateId,messages);
|
SmsResponse smsResponse = sendMessage(phone, templateId, messages);
|
||||||
callBack.callBack(smsResponse);
|
callBack.callBack(smsResponse);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -124,8 +95,8 @@ public class YunPianSmsImpl implements SmsBlend {
|
|||||||
@Override
|
@Override
|
||||||
@Restricted
|
@Restricted
|
||||||
public void sendMessageAsync(String phone, String templateId, LinkedHashMap<String, String> messages) {
|
public void sendMessageAsync(String phone, String templateId, LinkedHashMap<String, String> messages) {
|
||||||
pool.execute(()->{
|
pool.execute(() -> {
|
||||||
sendMessage(phone,templateId,messages);
|
sendMessage(phone, templateId, messages);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,9 +106,9 @@ public class YunPianSmsImpl implements SmsBlend {
|
|||||||
this.delayed.schedule(new TimerTask() {
|
this.delayed.schedule(new TimerTask() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
sendMessage(phone,message);
|
sendMessage(phone, message);
|
||||||
}
|
}
|
||||||
},delayedTime);
|
}, delayedTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -146,9 +117,9 @@ public class YunPianSmsImpl implements SmsBlend {
|
|||||||
this.delayed.schedule(new TimerTask() {
|
this.delayed.schedule(new TimerTask() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
sendMessage(phone,templateId,messages);
|
sendMessage(phone, templateId, messages);
|
||||||
}
|
}
|
||||||
},delayedTime);
|
}, delayedTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -157,9 +128,9 @@ public class YunPianSmsImpl implements SmsBlend {
|
|||||||
this.delayed.schedule(new TimerTask() {
|
this.delayed.schedule(new TimerTask() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
massTexting(phones,message);
|
massTexting(phones, message);
|
||||||
}
|
}
|
||||||
},delayedTime);
|
}, delayedTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -168,49 +139,76 @@ public class YunPianSmsImpl implements SmsBlend {
|
|||||||
this.delayed.schedule(new TimerTask() {
|
this.delayed.schedule(new TimerTask() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
massTexting(phones,templateId,messages);
|
massTexting(phones, templateId, messages);
|
||||||
}
|
}
|
||||||
},delayedTime);
|
}, delayedTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String formattingMap(Map<String,String> messages){
|
private String formattingMap(Map<String, String> messages) {
|
||||||
StringBuilder str = new StringBuilder();
|
StringBuilder str = new StringBuilder();
|
||||||
for (Map.Entry<String,String> entry : messages.entrySet()) {
|
for (Map.Entry<String, String> entry : messages.entrySet()) {
|
||||||
str.append("#");
|
str.append("#");
|
||||||
str.append(entry.getKey());
|
str.append(entry.getKey());
|
||||||
str.append("#=");
|
str.append("#=");
|
||||||
str.append(entry.getValue());
|
str.append(entry.getValue());
|
||||||
str.append("&");
|
str.append("&");
|
||||||
}
|
}
|
||||||
str.deleteCharAt(str.length()-1);
|
str.deleteCharAt(str.length() - 1);
|
||||||
return str.toString();
|
return str.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String listToString(List<String> list){
|
private Map<String, String> setBody(String phone, String mes, LinkedHashMap<String, String> messages) {
|
||||||
StringBuilder str = new StringBuilder();
|
LinkedHashMap<String, String> message = new LinkedHashMap<>();
|
||||||
for (int i = 0; i < list.size(); i++) {
|
if (mes.isEmpty()) {
|
||||||
if (i == list.size() - 1) {
|
message = messages;
|
||||||
str.append(list.get(i));
|
|
||||||
} else {
|
} else {
|
||||||
str.append(list.get(i));
|
message.put(config.getTemplateName(), mes);
|
||||||
str.append(",");
|
|
||||||
}
|
}
|
||||||
}
|
Map<String, String> body = new HashMap<>();
|
||||||
return str.toString();
|
body.put("apikey", config.getApikey());
|
||||||
|
body.put("mobile", phone);
|
||||||
|
body.put("tpl_id", config.getTemplateId());
|
||||||
|
body.put("tpl_value", formattingMap(message));
|
||||||
|
if (!config.getCallbackUrl().isEmpty()) body.put("callback_url", config.getCallbackUrl());
|
||||||
|
return body;
|
||||||
}
|
}
|
||||||
|
|
||||||
private SmsResponse getSmsResponse(String message, Map<String, String> body) {
|
private Map<String, String> getHeaders() {
|
||||||
body.put("text",message);
|
Map<String, String> headers = new HashMap<>();
|
||||||
Map<String,String> map = new HashMap<>();
|
headers.put("Accept", "application/json;charset=utf-8");
|
||||||
map.put("Accept","application/json;charset=utf-8");
|
headers.put("Content-Type", Constant.FROM_URLENCODED);
|
||||||
OKResponse sync = http.setBaseURL("http://sms.yunpian.com/v2").builder()
|
return headers;
|
||||||
.headers(map)
|
}
|
||||||
.postOrBody("/sms/single_send.json", body)
|
|
||||||
.sync();
|
@NotNull
|
||||||
|
private static SmsResponse getSmsResponse(JSONObject execute) {
|
||||||
SmsResponse smsResponse = new SmsResponse();
|
SmsResponse smsResponse = new SmsResponse();
|
||||||
smsResponse.setCode(sync.getCode());
|
smsResponse.setCode(execute.getString("code"));
|
||||||
JSONObject jsonObject = HTTPUtils.getJSONObject(sync);
|
smsResponse.setMessage(execute.getString("msg"));
|
||||||
smsResponse.setData(jsonObject);
|
smsResponse.setBizId(execute.getString("sid"));
|
||||||
|
if (execute.getInteger("code") != 0) {
|
||||||
|
smsResponse.setErrMessage(execute.getString("msg"));
|
||||||
|
}
|
||||||
|
smsResponse.setData(execute);
|
||||||
return smsResponse;
|
return smsResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private SmsResponse getSendResponse(Map<String, String> body) {
|
||||||
|
Map<String, String> headers = getHeaders();
|
||||||
|
AtomicReference<SmsResponse> smsResponse = null;
|
||||||
|
http.post(Constant.YUNPIAN_URL + "/sms/tpl_single_send.json")
|
||||||
|
.addHeader(headers)
|
||||||
|
.addBody(body)
|
||||||
|
.onSuccess(((data,req,res)->{
|
||||||
|
JSONObject jsonBody = res.get(JSONObject.class);
|
||||||
|
smsResponse.set(getSmsResponse(jsonBody));
|
||||||
|
}))
|
||||||
|
.onError((ex,req,res)->{
|
||||||
|
JSONObject jsonBody = res.get(JSONObject.class);
|
||||||
|
smsResponse.set(getSmsResponse(jsonBody));
|
||||||
|
})
|
||||||
|
.execute();
|
||||||
|
|
||||||
|
return smsResponse.get();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user