From d55a27ff6f0309ad13b614a98fe9c3d619ca73ec Mon Sep 17 00:00:00 2001 From: wind Date: Sun, 2 Apr 2023 01:17:59 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E5=8D=8E=E4=B8=BA=E4=BA=91?= =?UTF-8?q?=E5=9B=BD=E5=86=85=E7=9F=AD=E4=BF=A1=E6=8E=A5=E5=85=A5=20?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=9F=BA=E7=A1=80http=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E6=A1=86=E6=9E=B6=E4=B8=BAForest=20=E9=87=8D=E6=9E=84=E4=BA=91?= =?UTF-8?q?=E7=89=87=E7=9F=AD=E4=BF=A1=E8=AF=A5http=E6=A1=86=E6=9E=B6?= =?UTF-8?q?=E4=B8=BAForest=20=E9=87=8D=E6=9E=84=E6=A8=A1=E5=9D=97=EF=BC=8C?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=87=AA=E5=8A=A8=E9=85=8D=E7=BD=AE=E6=A8=A1?= =?UTF-8?q?=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 41 +- sms-aggregation-aliyun/pom.xml | 4 +- .../sms/aliyun/config/AlibabaSmsConfig.java | 16 +- .../sms/aliyun/service/AlibabaSmsImpl.java | 4 +- sms-aggregation-api/pom.xml | 4 +- .../wind/sms/autoimmit/aop}/AopAdvice.java | 26 +- .../autoimmit/config/SmsAutowiredConfig.java | 68 +++ .../wind/sms/autoimmit/config/SmsConfig.java | 43 ++ sms-aggregation-comm/pom.xml | 9 +- .../kim/wind/sms/comm/config/SmsBanner.java | 8 +- .../kim/wind/sms/comm/constant/Constant.java | 41 ++ .../kim/wind/sms/comm/entity/SmsResponse.java | 2 +- .../kim/wind/sms/comm/utils/HTTPUtils.java | 420 ------------------ .../kim/wind/sms/comm/utils/RedisUtils.java | 27 +- .../java/kim/wind/sms/comm/utils/SmsUtil.java | 14 + .../kim/wind/sms/comm/utils/SpringUtil.java | 22 + .../sms/comm/utils/TimeExpiredPoolCache.java | 19 +- .../sms/comm/utils/http/HttpJsonTool.java | 35 ++ sms-aggregation-huawei/pom.xml | 4 +- .../sms/huawei/config/HuaweiSmsConfig.java | 24 +- .../wind/sms/huawei/constant/Constant.java | 34 -- .../wind/sms/huawei/entity/HuaweiError.java | 2 +- .../sms/huawei/entity/HuaweiResponse.java | 2 +- .../sms/huawei/service/HuaweiSmsImpl.java | 119 +++-- .../{service => utils}/HuaweiBuilder.java | 19 +- sms-aggregation-spring-boot-starter/pom.xml | 46 +- .../sms/starter/config/SmsMainConfig.java | 132 +----- .../sms/starter/config/TaskPoolConfig.java | 19 - .../main/resources/META-INF/spring.factories | 8 +- sms-aggregation-tencent/pom.xml | 4 +- .../sms/tencent/config/TencentSmsConfig.java | 11 +- sms-aggregation-unisms/pom.xml | 4 +- .../wind/sms/unisms/config/UniSmsConfig.java | 11 +- .../wind/sms/unisms/service/UniSmsImpl.java | 6 +- sms-aggregation-yunpian/pom.xml | 4 +- .../sms/yunpian/config/YunPianSmsConfig.java | 44 +- .../sms/yunpian/service/YunPianSmsImpl.java | 162 ++++--- 37 files changed, 589 insertions(+), 869 deletions(-) rename {sms-aggregation-spring-boot-starter/src/main/java/kim/wind/sms/starter/config => sms-aggregation-autoimmit/src/main/java/kim/wind/sms/autoimmit/aop}/AopAdvice.java (86%) create mode 100644 sms-aggregation-autoimmit/src/main/java/kim/wind/sms/autoimmit/config/SmsAutowiredConfig.java create mode 100644 sms-aggregation-autoimmit/src/main/java/kim/wind/sms/autoimmit/config/SmsConfig.java create mode 100644 sms-aggregation-comm/src/main/java/kim/wind/sms/comm/constant/Constant.java delete mode 100644 sms-aggregation-comm/src/main/java/kim/wind/sms/comm/utils/HTTPUtils.java create mode 100644 sms-aggregation-comm/src/main/java/kim/wind/sms/comm/utils/http/HttpJsonTool.java delete mode 100644 sms-aggregation-huawei/src/main/java/kim/wind/sms/huawei/constant/Constant.java rename sms-aggregation-huawei/src/main/java/kim/wind/sms/huawei/{service => utils}/HuaweiBuilder.java (87%) delete mode 100644 sms-aggregation-spring-boot-starter/src/main/java/kim/wind/sms/starter/config/TaskPoolConfig.java diff --git a/pom.xml b/pom.xml index 87add821..59578d01 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 kim.wind sms_aggregation - 1.0.2 + 1.0.3 sms-aggregation pom sms_aggregation @@ -19,6 +19,7 @@ sms-aggregation-yunpian sms-aggregation-spring-boot-starter sms-aggregation-huawei + sms-aggregation-autoimmit @@ -49,7 +50,7 @@ 1.8 2.7.10 - 1.0.2 + 1.0.3 2.0.23 2.0.15 3.14.9 @@ -111,6 +112,12 @@ ${modules.version} + + kim.wind + sms-aggregation-autoimmit + ${modules.version} + + kim.wind @@ -130,12 +137,6 @@ com.aliyun dysmsapi20170525 ${aliyun.version} - - - okhttp - com.squareup.okhttp3 - - @@ -143,20 +144,8 @@ com.alibaba fastjson ${json.version} - - - com.squareup.okhttp3 - okhttp - - - - - com.squareup.okhttp3 - okhttp - ${okhttp.version} - com.dtflys.forest @@ -184,12 +173,6 @@ com.apistd.uni uni-sdk ${unisms.version} - - - okhttp - com.squareup.okhttp3 - - @@ -197,12 +180,6 @@ com.tencentcloudapi tencentcloud-sdk-java ${tencent.version} - - - okhttp - com.squareup.okhttp3 - - diff --git a/sms-aggregation-aliyun/pom.xml b/sms-aggregation-aliyun/pom.xml index f48ae40e..fab65767 100644 --- a/sms-aggregation-aliyun/pom.xml +++ b/sms-aggregation-aliyun/pom.xml @@ -5,13 +5,13 @@ kim.wind sms_aggregation - 1.0.2 + 1.0.3 ../pom.xml sms-aggregation-aliyun sms-aggregation-aliyun sms-aggregation-aliyun - 1.0.2 + 1.0.3 1.8 diff --git a/sms-aggregation-aliyun/src/main/java/kim/wind/sms/aliyun/config/AlibabaSmsConfig.java b/sms-aggregation-aliyun/src/main/java/kim/wind/sms/aliyun/config/AlibabaSmsConfig.java index 9b9f90db..7b83ce0d 100644 --- a/sms-aggregation-aliyun/src/main/java/kim/wind/sms/aliyun/config/AlibabaSmsConfig.java +++ b/sms-aggregation-aliyun/src/main/java/kim/wind/sms/aliyun/config/AlibabaSmsConfig.java @@ -5,16 +5,16 @@ import com.aliyun.teaopenapi.models.Config; import kim.wind.sms.aliyun.service.AlibabaSmsImpl; import kim.wind.sms.api.SmsBlend; import lombok.Data; -import org.springframework.boot.autoconfigure.AutoConfigureAfter; 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.Configuration; + +@Data @Configuration @ConfigurationProperties(prefix = "sms.alibaba") //指定配置文件注入属性前缀 -@Data -@ConditionalOnProperty(prefix = "sms", name = "supplier", havingValue = "alibaba") +@ConditionalOnProperty(name = "sms.supplier", havingValue = "alibaba") public class AlibabaSmsConfig { /** accessKey*/ @@ -32,7 +32,7 @@ public class AlibabaSmsConfig { @Bean - public Client config() throws Exception { + public Client client() throws Exception { Config config = new Config() // AccessKey ID .setAccessKeyId(accessKeyId) @@ -43,8 +43,8 @@ public class AlibabaSmsConfig { return new Client(config); } -// @Bean -// public SmsBlend smsBlend(){ -// return new AlibabaSmsImpl(); -// } + @Bean + public SmsBlend smsBlend(){ + return new AlibabaSmsImpl(); + } } diff --git a/sms-aggregation-aliyun/src/main/java/kim/wind/sms/aliyun/service/AlibabaSmsImpl.java b/sms-aggregation-aliyun/src/main/java/kim/wind/sms/aliyun/service/AlibabaSmsImpl.java index 0ec2c85d..cf2d6b4a 100644 --- a/sms-aggregation-aliyun/src/main/java/kim/wind/sms/aliyun/service/AlibabaSmsImpl.java +++ b/sms-aggregation-aliyun/src/main/java/kim/wind/sms/aliyun/service/AlibabaSmsImpl.java @@ -15,7 +15,7 @@ import kim.wind.sms.comm.annotation.Restricted; import kim.wind.sms.comm.delayedTime.DelayedTime; import kim.wind.sms.comm.entity.SmsResponse; 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 org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; @@ -111,7 +111,7 @@ public class AlibabaSmsImpl implements SmsBlend { try { SendBatchSmsResponse sendBatchSmsResponse = client.sendBatchSmsWithOptions(sendBatchSmsRequest, runtime); smsResponse.setBizId(sendBatchSmsResponse.body.getBizId()); - smsResponse.setData(HTTPUtils.getJSONObject(sendBatchSmsResponse.body)); + smsResponse.setData(HttpJsonTool.getJSONObject(sendBatchSmsResponse.body)); smsResponse.setCode(sendBatchSmsResponse.statusCode); if (!"OK".equals(sendBatchSmsResponse.body.code)) { smsResponse.setErrMessage((sendBatchSmsResponse.body.message)); diff --git a/sms-aggregation-api/pom.xml b/sms-aggregation-api/pom.xml index d1a81156..b1dccb3d 100644 --- a/sms-aggregation-api/pom.xml +++ b/sms-aggregation-api/pom.xml @@ -5,13 +5,13 @@ kim.wind sms_aggregation - 1.0.2 + 1.0.3 ../pom.xml sms-aggregation-api sms-aggregation-api sms-aggregation-api - 1.0.2 + 1.0.3 1.8 diff --git a/sms-aggregation-spring-boot-starter/src/main/java/kim/wind/sms/starter/config/AopAdvice.java b/sms-aggregation-autoimmit/src/main/java/kim/wind/sms/autoimmit/aop/AopAdvice.java similarity index 86% rename from sms-aggregation-spring-boot-starter/src/main/java/kim/wind/sms/starter/config/AopAdvice.java rename to sms-aggregation-autoimmit/src/main/java/kim/wind/sms/autoimmit/aop/AopAdvice.java index ed349577..3a30944c 100644 --- a/sms-aggregation-spring-boot-starter/src/main/java/kim/wind/sms/starter/config/AopAdvice.java +++ b/sms-aggregation-autoimmit/src/main/java/kim/wind/sms/autoimmit/aop/AopAdvice.java @@ -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.utils.RedisUtils; import kim.wind.sms.comm.utils.SmsUtil; @@ -23,7 +24,10 @@ public class AopAdvice { private static final String REDIS_KEY = "sms:restricted:"; @Autowired - private SmsMainConfig config; + private SmsConfig config; + + @Autowired + private SpringUtil springUtil; @Pointcut("@annotation(kim.wind.sms.comm.annotation.Restricted)") @@ -90,32 +94,36 @@ public class AopAdvice { } private SmsBlendException redisProcess(String args) throws Exception{ - RedisUtils redis = SpringUtil.getBean(RedisUtils.class); - if (redis == null || config.getRedisCache().equals("false")){ - return process(args); + if (config.getRedisCache().equals("false")){ + return process(args); } +// else { +// springUtil.createBean(RedisUtils.class.getName(),new RedisUtils()); +// } + RedisUtils redis = SpringUtil.getBean(RedisUtils.class); + Integer accountMax = config.getAccountMax();//每日最大发送量 Integer minuteMax = config.getMinuteMax();//每分钟最大发送量 if (SmsUtil.isNotEmpty(accountMax)) { //是否配置了每日限制 Integer i = (Integer) redis.getByKey(REDIS_KEY+args + "max"); if (SmsUtil.isEmpty(i)) { - redis.set(REDIS_KEY+args + "max", 1); + redis.setOrTime(REDIS_KEY+args + "max", 1,accTimer/1000); } else if (i > accountMax) { return new SmsBlendException("accountMax", args + "今日短信已达最大次数"); } else { - redis.set(REDIS_KEY+args + "max", i + 1); + redis.setOrTime(REDIS_KEY+args + "max", i + 1,accTimer/1000); } } if (SmsUtil.isNotEmpty(minuteMax)) { //是否配置了每分钟最大限制 Integer o = (Integer) redis.getByKey(REDIS_KEY+args); if (SmsUtil.isNotEmpty(o)) { if (o < minuteMax) { - redis.set(REDIS_KEY+args, o + 1); + redis.setOrTime(REDIS_KEY+args, o + 1,minTimer/1000); } else { return new SmsBlendException("minuteMax", args + "短信发送过于频繁!"); } } else { - redis.set(REDIS_KEY+args, 1); + redis.setOrTime(REDIS_KEY+args, 1,minTimer/1000); } } return null; diff --git a/sms-aggregation-autoimmit/src/main/java/kim/wind/sms/autoimmit/config/SmsAutowiredConfig.java b/sms-aggregation-autoimmit/src/main/java/kim/wind/sms/autoimmit/config/SmsAutowiredConfig.java new file mode 100644 index 00000000..3c2a1524 --- /dev/null +++ b/sms-aggregation-autoimmit/src/main/java/kim/wind/sms/autoimmit/config/SmsAutowiredConfig.java @@ -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; + } + + + +} diff --git a/sms-aggregation-autoimmit/src/main/java/kim/wind/sms/autoimmit/config/SmsConfig.java b/sms-aggregation-autoimmit/src/main/java/kim/wind/sms/autoimmit/config/SmsConfig.java new file mode 100644 index 00000000..643b6e50 --- /dev/null +++ b/sms-aggregation-autoimmit/src/main/java/kim/wind/sms/autoimmit/config/SmsConfig.java @@ -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; + + +} diff --git a/sms-aggregation-comm/pom.xml b/sms-aggregation-comm/pom.xml index 6147d1c3..1c44076b 100644 --- a/sms-aggregation-comm/pom.xml +++ b/sms-aggregation-comm/pom.xml @@ -5,13 +5,13 @@ kim.wind sms_aggregation - 1.0.2 + 1.0.3 ../pom.xml sms-aggregation-comm sms-aggregation-comm sms-aggregation-comm - 1.0.2 + 1.0.3 1.8 @@ -27,11 +27,6 @@ fastjson - - com.squareup.okhttp3 - okhttp - - org.springframework.boot spring-boot-starter-data-redis diff --git a/sms-aggregation-comm/src/main/java/kim/wind/sms/comm/config/SmsBanner.java b/sms-aggregation-comm/src/main/java/kim/wind/sms/comm/config/SmsBanner.java index eb23ee11..f1078a48 100644 --- a/sms-aggregation-comm/src/main/java/kim/wind/sms/comm/config/SmsBanner.java +++ b/sms-aggregation-comm/src/main/java/kim/wind/sms/comm/config/SmsBanner.java @@ -1,5 +1,7 @@ package kim.wind.sms.comm.config; +import kim.wind.sms.comm.constant.Constant; + public class SmsBanner { private static final String banner = @@ -10,8 +12,8 @@ public class SmsBanner { " ____) | | | | | ____) | / ____ \\ | |__| | | |__| | | | \\ \\ | |____ | |__| | / ____ \\ | | _| |_ | |__| | | |\\ |\n" + " |_____/ |_| |_| |_____/ /_/ \\_\\ \\_____| \\_____| |_| \\_\\ |______| \\_____| /_/ \\_\\ |_| |_____| \\____/ |_| \\_|\n" + " \n" + - " V1.0.2"; - public static void PrintBanner() { - System.out.println(banner); + " "; + public static void PrintBanner(String version) { + System.out.println(banner+version); } } diff --git a/sms-aggregation-comm/src/main/java/kim/wind/sms/comm/constant/Constant.java b/sms-aggregation-comm/src/main/java/kim/wind/sms/comm/constant/Constant.java new file mode 100644 index 00000000..5f84de38 --- /dev/null +++ b/sms-aggregation-comm/src/main/java/kim/wind/sms/comm/constant/Constant.java @@ -0,0 +1,41 @@ +package kim.wind.sms.comm.constant; + + +/** + * Constant + *

短信应用常量 + * + * @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() { + } +} diff --git a/sms-aggregation-comm/src/main/java/kim/wind/sms/comm/entity/SmsResponse.java b/sms-aggregation-comm/src/main/java/kim/wind/sms/comm/entity/SmsResponse.java index ae5853fb..47bd4828 100644 --- a/sms-aggregation-comm/src/main/java/kim/wind/sms/comm/entity/SmsResponse.java +++ b/sms-aggregation-comm/src/main/java/kim/wind/sms/comm/entity/SmsResponse.java @@ -11,7 +11,7 @@ import lombok.Data; @Data public class SmsResponse { /** 状态码*/ - private Integer code; + private String code; /** 返回消息*/ private String message; /** 错误码,没有错误信息则为空*/ diff --git a/sms-aggregation-comm/src/main/java/kim/wind/sms/comm/utils/HTTPUtils.java b/sms-aggregation-comm/src/main/java/kim/wind/sms/comm/utils/HTTPUtils.java deleted file mode 100644 index 39894f11..00000000 --- a/sms-aggregation-comm/src/main/java/kim/wind/sms/comm/utils/HTTPUtils.java +++ /dev/null @@ -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; - - -/** - *

类名: HTTPUtils - *

说明: 封装okhttp3,简单化请求创建流程,并且可以当做工具类进行自动装配使用 - *

构建请求只需要获得OKHTTPUtils的对象,然后逐步调用即可 - *

如: - *

http.setBaseURL("http://www.baidu.com").builder().get("/wenku").sync(); - *

构建一个post请求只需要: - *

http.setBaseURL("http://www.baidu.com").builder().post("/wenku",object).sync(); - *

如果在Spring Boot中作为组件自动装配使用,{@code baseURL}将读取配置文件中的{@code okhttp.url}获取默认的请求路径,则不需要再次调用 setBaseURL()方法进行设置 - *

依赖于 {@code okhttp3} {@code alibaba.fastjson} {@code lombok.slf4j} - *

{@code - * - * com.squareup.okhttp3 - * okhttp - * 3.14.9 - * } - *

{@code - * - * com.alibaba - * fastjson - * 1.2.74 - *} - * - * @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"); - - /** - *

说明:请求头类型标注 - * @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; - } - - /** - *

说明:设置一个通用的请求地址 - *

如果不设置该地址则以输入的地址作为请求地址,如设置了改地址,会自动拼接之后builder时设置的地址 - *

一旦设置该地址后,在重新获取对象或者调用{@link #defaultURL()}之前,配置文件中的默认地址将会被覆盖 - * - * @param baseURL 设置一个通用的请求地址 - * @name: setBaseURL - * @author :Wind - */ - public HTTPUtils setBaseURL(String baseURL) { - this.baseURL = baseURL; - return this; - } - - /** - *

说明:设置回默认的请求路径(配置文件中路径) - *

- * - * @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 map) { - for (Map.Entry 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 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; - } - - /** - *

说明:发送格式为application/x-www-form-urlencoded的post请求 - * @name: postOrBody - * @param - * @author :Wind - */ - public HTTPUtils postOrBody(String url, Map 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 data){ - FormBody.Builder builder1 = new FormBody.Builder(); - data.forEach(builder1::add); - return builder1.build(); - } - - /** - * 说明:post请求,第三个参数为true时则请求的参数在query中,此时只接受 Map 类型的参数 - * - * @param url 请求路径 - * @param query 在url中的参数 - * @param isQuery 参数是否在query中 - * @name: post - * @author :Wind - */ - public HTTPUtils post(String url, Map 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()); - } - - - /** - *

说明:使用异步形式发送请求 - *

该方法会启动一个高优先级子线程处理请求任务,但不会等待处理结果,直接返回调用对象,如需获取结果可以调用异步回调方法 - *

{@link #asyncCallback()} - *

回调方法将会始终阻塞线程直至子线程处理完成返回结果

- * - * @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; - } - - /** - *

说明:使用异步形式发送请求 - *

该方法会启动一个高优先级子线程处理请求任务,但不会等待处理结果,同时不会返回任何对象,处理完成的结果将会放置在调用对象的 {@link #okResponse}对象中

- *

回调方法将会始终阻塞线程直至子线程处理完成返回结果

- * - * @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 map) { - if (map != null) { - StringBuilder addBuilder = new StringBuilder(add); - addBuilder.append("?"); - for (Map.Entry 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("非法调用!未构建请求对象!"); - } - } - - /** - *

说明:将返回结果序列化到实体类中 - *

传入对象必须实现了getter和setter方法,否则将序列化失败 - * @name: getJSONBody - * @param t 要序列化的对象 - * @author :Wind - */ - public static T getJSONBody(OKResponse response, Class t) { - try { - return JSONObject.parseObject(response.getBody().string(), t); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - /** - *

说明:将返回结果序列化为一个json对象 - *

- * @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()); - } -} diff --git a/sms-aggregation-comm/src/main/java/kim/wind/sms/comm/utils/RedisUtils.java b/sms-aggregation-comm/src/main/java/kim/wind/sms/comm/utils/RedisUtils.java index c9f15b7e..92dab8a8 100644 --- a/sms-aggregation-comm/src/main/java/kim/wind/sms/comm/utils/RedisUtils.java +++ b/sms-aggregation-comm/src/main/java/kim/wind/sms/comm/utils/RedisUtils.java @@ -2,10 +2,12 @@ package kim.wind.sms.comm.utils; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.connection.RedisConnectionFactory; 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.concurrent.TimeUnit; @@ -13,9 +15,28 @@ import java.util.concurrent.TimeUnit; @Slf4j public class RedisUtils { - @Autowired private RedisTemplate 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 template = new RedisTemplate(); + template.setConnectionFactory(connectionFactory); + template.setKeySerializer(keySerializer); + template.setHashKeySerializer(keySerializer); + template.setValueSerializer(valueSerializer); + template.setHashValueSerializer(valueSerializer); + template.afterPropertiesSet(); + this.redisTemplate = template; + } + public RedisUtils() { } diff --git a/sms-aggregation-comm/src/main/java/kim/wind/sms/comm/utils/SmsUtil.java b/sms-aggregation-comm/src/main/java/kim/wind/sms/comm/utils/SmsUtil.java index 149c38b8..a610e44d 100644 --- a/sms-aggregation-comm/src/main/java/kim/wind/sms/comm/utils/SmsUtil.java +++ b/sms-aggregation-comm/src/main/java/kim/wind/sms/comm/utils/SmsUtil.java @@ -2,6 +2,7 @@ package kim.wind.sms.comm.utils; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; +import java.util.List; import java.util.Random; public class SmsUtil { @@ -81,4 +82,17 @@ public class SmsUtil { return !isEmpty(str); } + public static String listToString(List 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(); + } + } diff --git a/sms-aggregation-comm/src/main/java/kim/wind/sms/comm/utils/SpringUtil.java b/sms-aggregation-comm/src/main/java/kim/wind/sms/comm/utils/SpringUtil.java index d9d80827..c8d5ac22 100644 --- a/sms-aggregation-comm/src/main/java/kim/wind/sms/comm/utils/SpringUtil.java +++ b/sms-aggregation-comm/src/main/java/kim/wind/sms/comm/utils/SpringUtil.java @@ -1,6 +1,9 @@ package kim.wind.sms.comm.utils; 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.ApplicationContextAware; @@ -14,6 +17,9 @@ public class SpringUtil implements ApplicationContextAware { private static ApplicationContext applicationContext; + @Autowired + DefaultListableBeanFactory beanFactory; + @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { if(SpringUtil.applicationContext == null) { @@ -49,4 +55,20 @@ public class SpringUtil implements ApplicationContextAware { return null ; } } + + /** + *

说明:创建一个bean + * @name: createBean + * @param + * @author :Wind + */ + public void createBean(Classclazz){ + 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); + } } diff --git a/sms-aggregation-comm/src/main/java/kim/wind/sms/comm/utils/TimeExpiredPoolCache.java b/sms-aggregation-comm/src/main/java/kim/wind/sms/comm/utils/TimeExpiredPoolCache.java index 6f550b2a..0159baad 100644 --- a/sms-aggregation-comm/src/main/java/kim/wind/sms/comm/utils/TimeExpiredPoolCache.java +++ b/sms-aggregation-comm/src/main/java/kim/wind/sms/comm/utils/TimeExpiredPoolCache.java @@ -46,9 +46,7 @@ public class TimeExpiredPoolCache { private static synchronized void syncInit() { if (instance == null) { instance = new TimeExpiredPoolCache(); - if (!persistenceInit()){ - dataPool = new ConcurrentHashMap>(); - } + dataPool = new ConcurrentHashMap>(); initTimer(); } } @@ -60,12 +58,15 @@ public class TimeExpiredPoolCache { return instance; } - /** 读取持久化文件*/ + /** + * 读取持久化文件 + */ private static boolean persistenceInit() { String path = FileTool.getPath() + FILE_TYPE; 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; } } catch (IOException ignored) { @@ -79,7 +80,6 @@ public class TimeExpiredPoolCache { public void run() { try { clearExpiredCaches(); - persistence(); } catch (Exception e) { throw new SmsBlendException(e.getMessage()); } @@ -87,10 +87,11 @@ public class TimeExpiredPoolCache { }, timerMillis, timerMillis); } - private static void persistence(){ + /** 写入持久化文件*/ + private static void persistence() { String path = FileTool.getPath() + FILE_TYPE; FileTool.createFile(path); - FileTool.writeFile(new File(path),JSONObject.toJSONString(dataPool),false); + FileTool.writeFile(new File(path), JSONObject.toJSONString(dataPool), false); } /** diff --git a/sms-aggregation-comm/src/main/java/kim/wind/sms/comm/utils/http/HttpJsonTool.java b/sms-aggregation-comm/src/main/java/kim/wind/sms/comm/utils/http/HttpJsonTool.java new file mode 100644 index 00000000..e8fb93e6 --- /dev/null +++ b/sms-aggregation-comm/src/main/java/kim/wind/sms/comm/utils/http/HttpJsonTool.java @@ -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 getJSONBody(Object response,Classt){ + return JSONObject.parseObject(response.toString(), t); + } + + public static T getJSONBody(String response,Classt){ + return JSONObject.parseObject(response, t); + } + + /** + *

说明:将返回结果序列化为一个json对象 + *

+ * @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()); + } +} diff --git a/sms-aggregation-huawei/pom.xml b/sms-aggregation-huawei/pom.xml index 3bec5be1..ae9c8186 100644 --- a/sms-aggregation-huawei/pom.xml +++ b/sms-aggregation-huawei/pom.xml @@ -5,11 +5,11 @@ kim.wind sms_aggregation - 1.0.2 + 1.0.3 ../pom.xml sms-aggregation-huawei - 1.0.2 + 1.0.3 sms-aggregation-huawei sms-aggregation-huawei diff --git a/sms-aggregation-huawei/src/main/java/kim/wind/sms/huawei/config/HuaweiSmsConfig.java b/sms-aggregation-huawei/src/main/java/kim/wind/sms/huawei/config/HuaweiSmsConfig.java index 14b9375d..5fb80150 100644 --- a/sms-aggregation-huawei/src/main/java/kim/wind/sms/huawei/config/HuaweiSmsConfig.java +++ b/sms-aggregation-huawei/src/main/java/kim/wind/sms/huawei/config/HuaweiSmsConfig.java @@ -1,11 +1,19 @@ 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 org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; - -@ConfigurationProperties(prefix = "sms.huawei") //指定配置文件注入属性前缀 @Data +@Configuration +@ConfigurationProperties(prefix = "sms.huawei") //指定配置文件注入属性前缀 +@ConditionalOnProperty(name = "sms.supplier", havingValue = "huawei") public class HuaweiSmsConfig { /** appKey*/ @@ -22,5 +30,17 @@ public class HuaweiSmsConfig { private String statusCallBack; /** APP接入地址*/ 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(); + } } diff --git a/sms-aggregation-huawei/src/main/java/kim/wind/sms/huawei/constant/Constant.java b/sms-aggregation-huawei/src/main/java/kim/wind/sms/huawei/constant/Constant.java deleted file mode 100644 index 7a0a78a6..00000000 --- a/sms-aggregation-huawei/src/main/java/kim/wind/sms/huawei/constant/Constant.java +++ /dev/null @@ -1,34 +0,0 @@ -package kim.wind.sms.huawei.constant; - - -/** - * Constant - *

华为云短信应用常量 - * - * @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() { - } -} diff --git a/sms-aggregation-huawei/src/main/java/kim/wind/sms/huawei/entity/HuaweiError.java b/sms-aggregation-huawei/src/main/java/kim/wind/sms/huawei/entity/HuaweiError.java index 9110caa6..21f5206b 100644 --- a/sms-aggregation-huawei/src/main/java/kim/wind/sms/huawei/entity/HuaweiError.java +++ b/sms-aggregation-huawei/src/main/java/kim/wind/sms/huawei/entity/HuaweiError.java @@ -53,6 +53,6 @@ public enum HuaweiError { case "E200041": return E200041.getValue(); } - return ""; + return "服务异常,请查看官方异常码,异常码:"+code; } } diff --git a/sms-aggregation-huawei/src/main/java/kim/wind/sms/huawei/entity/HuaweiResponse.java b/sms-aggregation-huawei/src/main/java/kim/wind/sms/huawei/entity/HuaweiResponse.java index 490f3efe..6dd10224 100644 --- a/sms-aggregation-huawei/src/main/java/kim/wind/sms/huawei/entity/HuaweiResponse.java +++ b/sms-aggregation-huawei/src/main/java/kim/wind/sms/huawei/entity/HuaweiResponse.java @@ -22,5 +22,5 @@ public class HuaweiResponse { /** 短信ID列表,当目的号码存在多个时,每个号码都会返回一个SmsID。 当返回异常响应时不携带此字段*/ - private List smsId; + private List result; } diff --git a/sms-aggregation-huawei/src/main/java/kim/wind/sms/huawei/service/HuaweiSmsImpl.java b/sms-aggregation-huawei/src/main/java/kim/wind/sms/huawei/service/HuaweiSmsImpl.java index b4d8015a..6ec5ffa6 100644 --- a/sms-aggregation-huawei/src/main/java/kim/wind/sms/huawei/service/HuaweiSmsImpl.java +++ b/sms-aggregation-huawei/src/main/java/kim/wind/sms/huawei/service/HuaweiSmsImpl.java @@ -1,27 +1,25 @@ package kim.wind.sms.huawei.service; +import com.dtflys.forest.config.ForestConfiguration; import kim.wind.sms.api.SmsBlend; 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.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.constant.Constant; -import kim.wind.sms.huawei.entity.HuaweiError; 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 org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.context.properties.EnableConfigurationProperties; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.concurrent.Executor; +import static kim.wind.sms.comm.utils.SmsUtil.listToString; + @EnableConfigurationProperties({HuaweiSmsConfig.class}) @Slf4j public class HuaweiSmsImpl implements SmsBlend { @@ -37,17 +35,21 @@ public class HuaweiSmsImpl implements SmsBlend { private DelayedTime delayed; @Autowired - private HTTPUtils http ; + @Qualifier("forestConfiguration") + private ForestConfiguration http; @Override + @Restricted public SmsResponse sendMessage(String phone, String message) { - - - return null; + LinkedHashMap mes = new LinkedHashMap<>(); + mes.put(UUID.randomUUID().toString().replaceAll("-",""),message); + return sendMessage(phone,config.getTemplateId(),mes); } @Override + @Restricted public SmsResponse sendMessage(String phone, String templateId, LinkedHashMap messages) { + String url = config.getUrl() + Constant.HUAWEI_REQUEST_URL; List list = new ArrayList<>(); for (Map.Entry entry : messages.entrySet()) { list.add(entry.getValue()); @@ -55,73 +57,114 @@ public class HuaweiSmsImpl implements SmsBlend { String mess = HuaweiBuilder.listToString(list); String requestBody = HuaweiBuilder.buildRequestBody(config.getSender(), phone, config.getTemplateId(), mess, config.getStatusCallBack(), config.getSignature()); Map 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())); - OKResponse response = http.setBaseURL(config.getUrl()).builder() - .setMediaType(Constant.CONTENT_TYPE) - .headers(headers) - .post(Constant.REQUEST_URL, requestBody) - .sync(); - HuaweiResponse jsonBody = response.getJSONBody(HuaweiResponse.class); + headers.put("Content-Type",Constant.FROM_URLENCODED); SmsResponse smsResponse = new SmsResponse(); - smsResponse.setCode(response.getCode()); - smsResponse.setMessage(jsonBody.getDescription()); - SmsId smsId = jsonBody.getSmsId().get(0); - smsResponse.setBizId(smsId.getSmsMsgId()); - smsResponse.setData(jsonBody); - if (response.getCode() != 200){ - smsResponse.setErrMessage(HuaweiError.getValue(smsId.getStatus())); - } + 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.setBizId(jsonBody.getResult().get(0).getSmsMsgId()); + smsResponse.setData(jsonBody.getResult()); + })) + .onError((ex,req,res)->{ + HuaweiResponse huaweiResponse = res.get(HuaweiResponse.class); + smsResponse.setErrMessage(huaweiResponse.getDescription()); + smsResponse.setErrorCode(huaweiResponse.getCode()); + }) + .execute(); return smsResponse; } @Override + @Restricted public SmsResponse massTexting(List phones, String message) { - return null; + return sendMessage(listToString(phones),message); } @Override + @Restricted public SmsResponse massTexting(List phones, String templateId, LinkedHashMap messages) { - return null; + return sendMessage(listToString(phones), templateId, messages); } @Override + @Restricted public void sendMessageAsync(String phone, String message, CallBack callBack) { - + pool.execute(() -> { + SmsResponse smsResponse = sendMessage(phone, message); + callBack.callBack(smsResponse); + }); } @Override + @Restricted public void sendMessageAsync(String phone, String message) { - + pool.execute(() -> sendMessage(phone, message)); } @Override + @Restricted public void sendMessageAsync(String phone, String templateId, LinkedHashMap messages, CallBack callBack) { - + pool.execute(() -> { + SmsResponse smsResponse = sendMessage(phone, templateId, messages); + callBack.callBack(smsResponse); + }); } @Override + @Restricted public void sendMessageAsync(String phone, String templateId, LinkedHashMap messages) { - + pool.execute(() -> { + sendMessage(phone, templateId, messages); + }); } @Override + @Restricted public void delayedMessage(String phone, String message, Long delayedTime) { - + this.delayed.schedule(new TimerTask() { + @Override + public void run() { + sendMessage(phone, message); + } + }, delayedTime); } @Override + @Restricted public void delayedMessage(String phone, String templateId, LinkedHashMap messages, Long delayedTime) { - + this.delayed.schedule(new TimerTask() { + @Override + public void run() { + sendMessage(phone, templateId, messages); + } + }, delayedTime); } @Override + @Restricted public void delayMassTexting(List phones, String message, Long delayedTime) { - + this.delayed.schedule(new TimerTask() { + @Override + public void run() { + massTexting(phones, message); + } + }, delayedTime); } @Override + @Restricted public void delayMassTexting(List phones, String templateId, LinkedHashMap messages, Long delayedTime) { - + this.delayed.schedule(new TimerTask() { + @Override + public void run() { + massTexting(phones, templateId, messages); + } + }, delayedTime); } } diff --git a/sms-aggregation-huawei/src/main/java/kim/wind/sms/huawei/service/HuaweiBuilder.java b/sms-aggregation-huawei/src/main/java/kim/wind/sms/huawei/utils/HuaweiBuilder.java similarity index 87% rename from sms-aggregation-huawei/src/main/java/kim/wind/sms/huawei/service/HuaweiBuilder.java rename to sms-aggregation-huawei/src/main/java/kim/wind/sms/huawei/utils/HuaweiBuilder.java index aa7ecdec..28542f4f 100644 --- a/sms-aggregation-huawei/src/main/java/kim/wind/sms/huawei/service/HuaweiBuilder.java +++ b/sms-aggregation-huawei/src/main/java/kim/wind/sms/huawei/utils/HuaweiBuilder.java @@ -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.huawei.entity.HuaweiError; +import kim.wind.sms.comm.constant.Constant; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; @@ -25,7 +24,7 @@ public class HuaweiBuilder { *

构造X-WSSE参数值 * @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()) { System.out.println("buildWsseHeader(): appKey or appSecret is null."); return null; @@ -46,7 +45,7 @@ public class HuaweiBuilder { String passwordDigestBase64Str = Base64.getEncoder().encodeToString(passwordDigest); //PasswordDigest //若passwordDigestBase64Str中包含换行符,请执行如下代码进行修正 //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 { @@ -79,8 +78,8 @@ public class HuaweiBuilder { * @param signature | 签名名称,使用国内短信通用模板时填写 * @author :Wind */ - static String buildRequestBody(String sender, String receiver, String templateId, String templateParas, - String statusCallBack, String signature) { + public static String buildRequestBody(String sender, String receiver, String templateId, String templateParas, + String statusCallBack, String signature) { if (null == sender || null == receiver || null == templateId || sender.isEmpty() || receiver.isEmpty() || templateId.isEmpty()) { System.out.println("buildRequestBody(): sender, receiver or templateId is null."); @@ -116,7 +115,7 @@ public class HuaweiBuilder { return sb.deleteCharAt(sb.length()-1).toString(); } - static String listToString(List list){ + public static String listToString(List list){ StringBuilder stringBuffer = new StringBuilder(); stringBuffer.append("[\""); for (String s : list) { @@ -130,12 +129,12 @@ public class HuaweiBuilder { } static String dateFormat(Date date){ - SimpleDateFormat sdf = new SimpleDateFormat(Constant.JAVA_DATE); + SimpleDateFormat sdf = new SimpleDateFormat(Constant.HUAWEI_JAVA_DATE); return sdf.format(date); } static Date strForDate(String date){ - SimpleDateFormat sdf = new SimpleDateFormat(Constant.JAVA_DATE); + SimpleDateFormat sdf = new SimpleDateFormat(Constant.HUAWEI_JAVA_DATE); try { return sdf.parse(date); } catch (ParseException e) { diff --git a/sms-aggregation-spring-boot-starter/pom.xml b/sms-aggregation-spring-boot-starter/pom.xml index d4fb29ed..a2bcb191 100644 --- a/sms-aggregation-spring-boot-starter/pom.xml +++ b/sms-aggregation-spring-boot-starter/pom.xml @@ -5,13 +5,13 @@ kim.wind sms_aggregation - 1.0.2 + 1.0.3 ../pom.xml sms-aggregation-spring-boot-starter sms-aggregation-spring-boot-starter sms-aggregation-spring-boot-starter - 1.0.2 + 1.0.3 jar @@ -26,6 +26,11 @@ import + + kim.wind + sms-aggregation-autoimmit + + org.springframework.boot spring-boot-starter @@ -33,46 +38,13 @@ kim.wind - sms-aggregation-aliyun + sms-aggregation-autoimmit - - kim.wind - sms-aggregation-tencent - - - - kim.wind - sms-aggregation-unisms - - - - kim.wind - sms-aggregation-yunpian - - - - kim.wind - sms-aggregation-huawei - - - - - org.springframework.boot - spring-boot-starter-aop - - - - org.springframework.boot - spring-boot-starter-data-redis - - - org.springframework.boot - spring-boot-maven-plugin - + diff --git a/sms-aggregation-spring-boot-starter/src/main/java/kim/wind/sms/starter/config/SmsMainConfig.java b/sms-aggregation-spring-boot-starter/src/main/java/kim/wind/sms/starter/config/SmsMainConfig.java index f35b9259..c3c8c2fa 100644 --- a/sms-aggregation-spring-boot-starter/src/main/java/kim/wind/sms/starter/config/SmsMainConfig.java +++ b/sms-aggregation-spring-boot-starter/src/main/java/kim/wind/sms/starter/config/SmsMainConfig.java @@ -1,148 +1,26 @@ package kim.wind.sms.starter.config; -import kim.wind.sms.comm.utils.HTTPUtils; -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.autoimmit.config.SmsAutowiredConfig; 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 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.Configuration; import org.springframework.scheduling.annotation.EnableAsync; -import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; - -import java.util.concurrent.Executor; -import java.util.concurrent.ThreadPoolExecutor; @Configuration -@ConfigurationProperties(prefix = "sms") //指定配置文件注入属性前缀 @EnableAsync @Data 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 public SpringUtil springUtil(){ return new SpringUtil(); } - @Bean - @ConditionalOnProperty(prefix = "sms", name = "supplier", havingValue = "huawei") - public HuaweiSmsConfig huaweiSmsConfig(){ - return new HuaweiSmsConfig(); - } - - @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; + /** 主要配置注入*/ + @Bean(initMethod = "init") + public SmsAutowiredConfig smsAutowiredConfig(){ + return new SmsAutowiredConfig(); } } diff --git a/sms-aggregation-spring-boot-starter/src/main/java/kim/wind/sms/starter/config/TaskPoolConfig.java b/sms-aggregation-spring-boot-starter/src/main/java/kim/wind/sms/starter/config/TaskPoolConfig.java deleted file mode 100644 index a8cd6432..00000000 --- a/sms-aggregation-spring-boot-starter/src/main/java/kim/wind/sms/starter/config/TaskPoolConfig.java +++ /dev/null @@ -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 { - - - -} diff --git a/sms-aggregation-spring-boot-starter/src/main/resources/META-INF/spring.factories b/sms-aggregation-spring-boot-starter/src/main/resources/META-INF/spring.factories index 519aee3a..0d22489d 100644 --- a/sms-aggregation-spring-boot-starter/src/main/resources/META-INF/spring.factories +++ b/sms-aggregation-spring-boot-starter/src/main/resources/META-INF/spring.factories @@ -1,3 +1,9 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ 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 + diff --git a/sms-aggregation-tencent/pom.xml b/sms-aggregation-tencent/pom.xml index 25168c79..85d4924e 100644 --- a/sms-aggregation-tencent/pom.xml +++ b/sms-aggregation-tencent/pom.xml @@ -5,13 +5,13 @@ kim.wind sms_aggregation - 1.0.2 + 1.0.3 ../pom.xml sms-aggregation-tencent sms-aggregation-tencent sms-aggregation-tencent - 1.0.2 + 1.0.3 1.8 diff --git a/sms-aggregation-tencent/src/main/java/kim/wind/sms/tencent/config/TencentSmsConfig.java b/sms-aggregation-tencent/src/main/java/kim/wind/sms/tencent/config/TencentSmsConfig.java index ec12a74b..aa95dbf8 100644 --- a/sms-aggregation-tencent/src/main/java/kim/wind/sms/tencent/config/TencentSmsConfig.java +++ b/sms-aggregation-tencent/src/main/java/kim/wind/sms/tencent/config/TencentSmsConfig.java @@ -4,16 +4,18 @@ import com.tencentcloudapi.common.Credential; import com.tencentcloudapi.common.profile.ClientProfile; import com.tencentcloudapi.common.profile.HttpProfile; import com.tencentcloudapi.sms.v20210111.SmsClient; +import kim.wind.sms.api.SmsBlend; +import kim.wind.sms.tencent.service.TencentSmsImpl; 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.context.annotation.Configuration; +@Data @Configuration @ConfigurationProperties(prefix = "sms.tencent") //指定配置文件注入属性前缀 -@Data -@ConditionalOnProperty(prefix = "sms", name = "supplier", havingValue = "tencent") +@ConditionalOnProperty(name = "sms.supplier", havingValue = "tencent") public class TencentSmsConfig { /** 应用accessKey*/ @@ -49,4 +51,9 @@ public class TencentSmsConfig { clientProfile.setHttpProfile(httpProfile); return new SmsClient(cred, territory,clientProfile); } + + @Bean + public SmsBlend smsBlend(){ + return new TencentSmsImpl(); + } } diff --git a/sms-aggregation-unisms/pom.xml b/sms-aggregation-unisms/pom.xml index ba0e1c0b..924d099c 100644 --- a/sms-aggregation-unisms/pom.xml +++ b/sms-aggregation-unisms/pom.xml @@ -5,13 +5,13 @@ kim.wind sms_aggregation - 1.0.2 + 1.0.3 ../pom.xml sms-aggregation-unisms sms-aggregation-unisms sms-aggregation-unisms - 1.0.2 + 1.0.3 1.8 diff --git a/sms-aggregation-unisms/src/main/java/kim/wind/sms/unisms/config/UniSmsConfig.java b/sms-aggregation-unisms/src/main/java/kim/wind/sms/unisms/config/UniSmsConfig.java index a165133b..f28ba68f 100644 --- a/sms-aggregation-unisms/src/main/java/kim/wind/sms/unisms/config/UniSmsConfig.java +++ b/sms-aggregation-unisms/src/main/java/kim/wind/sms/unisms/config/UniSmsConfig.java @@ -1,16 +1,18 @@ package kim.wind.sms.unisms.config; import com.apistd.uni.Uni; +import kim.wind.sms.api.SmsBlend; +import kim.wind.sms.unisms.service.UniSmsImpl; 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.context.annotation.Configuration; +@Data @Configuration @ConfigurationProperties(prefix = "sms.uni-sms") //指定配置文件注入属性前缀 -@Data -@ConditionalOnProperty(prefix = "sms", name = "supplier", havingValue = "uni-sms") +@ConditionalOnProperty(name = "sms.supplier", havingValue = "uniSms") public class UniSmsConfig { /** 访问键标识*/ @@ -35,4 +37,9 @@ public class UniSmsConfig { Uni.init(accessKeyId,accessKeySecret); } } + + @Bean + public SmsBlend smsBlend(){ + return new UniSmsImpl(); + } } diff --git a/sms-aggregation-unisms/src/main/java/kim/wind/sms/unisms/service/UniSmsImpl.java b/sms-aggregation-unisms/src/main/java/kim/wind/sms/unisms/service/UniSmsImpl.java index a072949d..d4af1cdf 100644 --- a/sms-aggregation-unisms/src/main/java/kim/wind/sms/unisms/service/UniSmsImpl.java +++ b/sms-aggregation-unisms/src/main/java/kim/wind/sms/unisms/service/UniSmsImpl.java @@ -3,14 +3,14 @@ package kim.wind.sms.unisms.service; import com.apistd.uni.UniResponse; import com.apistd.uni.sms.UniMessage; import com.apistd.uni.sms.UniSMS; -import kim.wind.sms.unisms.config.UniSmsConfig; import kim.wind.sms.api.SmsBlend; import kim.wind.sms.api.callback.CallBack; import kim.wind.sms.comm.annotation.Restricted; import kim.wind.sms.comm.delayedTime.DelayedTime; import kim.wind.sms.comm.entity.SmsResponse; 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 org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; @@ -169,7 +169,7 @@ public class UniSmsImpl implements SmsBlend { smsResponse.setErrorCode(send.code); smsResponse.setMessage(send.message); smsResponse.setBizId(send.requestId); - smsResponse.setData(HTTPUtils.getJSONObject(send)); + smsResponse.setData(HttpJsonTool.getJSONObject(send)); }catch(Exception e){ smsResponse.setErrMessage(e.getMessage()); } diff --git a/sms-aggregation-yunpian/pom.xml b/sms-aggregation-yunpian/pom.xml index cf682365..e19a9efd 100644 --- a/sms-aggregation-yunpian/pom.xml +++ b/sms-aggregation-yunpian/pom.xml @@ -5,14 +5,14 @@ kim.wind sms_aggregation - 1.0.2 + 1.0.3 ../pom.xml sms-aggregation-yunpian sms-aggregation-yunpian sms-aggregation-yunpian - 1.0.2 + 1.0.3 1.8 diff --git a/sms-aggregation-yunpian/src/main/java/kim/wind/sms/yunpian/config/YunPianSmsConfig.java b/sms-aggregation-yunpian/src/main/java/kim/wind/sms/yunpian/config/YunPianSmsConfig.java index cb955634..9440c932 100644 --- a/sms-aggregation-yunpian/src/main/java/kim/wind/sms/yunpian/config/YunPianSmsConfig.java +++ b/sms-aggregation-yunpian/src/main/java/kim/wind/sms/yunpian/config/YunPianSmsConfig.java @@ -1,16 +1,52 @@ 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 org.springframework.boot.autoconfigure.AutoConfigureAfter; 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.Configuration; +@Data @Configuration @ConfigurationProperties(prefix = "sms.yunpian") //指定配置文件注入属性前缀 -@Data -@ConditionalOnProperty(prefix = "sms", name = "supplier", havingValue = "yunpian") +@ConditionalOnProperty(name = "sms.supplier", havingValue = "yunpian") public class YunPianSmsConfig { - /** 账号唯一标识*/ + /** + * 账号唯一标识 + */ 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(); + } } diff --git a/sms-aggregation-yunpian/src/main/java/kim/wind/sms/yunpian/service/YunPianSmsImpl.java b/sms-aggregation-yunpian/src/main/java/kim/wind/sms/yunpian/service/YunPianSmsImpl.java index 43d59fba..74868098 100644 --- a/sms-aggregation-yunpian/src/main/java/kim/wind/sms/yunpian/service/YunPianSmsImpl.java +++ b/sms-aggregation-yunpian/src/main/java/kim/wind/sms/yunpian/service/YunPianSmsImpl.java @@ -1,20 +1,24 @@ package kim.wind.sms.yunpian.service; import com.alibaba.fastjson.JSONObject; +import com.dtflys.forest.config.ForestConfiguration; import kim.wind.sms.api.SmsBlend; 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.entity.SmsResponse; 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 org.jetbrains.annotations.NotNull; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import java.util.*; 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 { @@ -26,75 +30,42 @@ public class YunPianSmsImpl implements SmsBlend { private DelayedTime delayed; @Autowired - private HTTPUtils http ; + private YunPianSmsConfig config; @Autowired - private YunPianSmsConfig config; + private ForestConfiguration http; @Override @Restricted public SmsResponse sendMessage(String phone, String message) { - Map body = new HashMap<>(); - body.put("apikey",config.getApikey()); - body.put("mobile",phone); - return getSmsResponse(message, body); + Map body = setBody(phone, message, null); + return getSendResponse(body); } @Override @Restricted public SmsResponse sendMessage(String phone, String templateId, LinkedHashMap messages) { - Map body = new HashMap<>(); - body.put("apikey",config.getApikey()); - body.put("mobile",phone); - body.put("tpl_id",templateId); - body.put("tpl_value",formattingMap(messages)); - Map 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; + Map body = setBody(phone, "", messages); + return getSendResponse(body); } + @Override @Restricted public SmsResponse massTexting(List phones, String message) { - if (phones.size()>1000){ + if (phones.size() > 1000) { throw new SmsBlendException("单次发送超过最大发送上限,建议每次群发短信人数低于1000"); } - Map body = new HashMap<>(); - body.put("apikey",config.getApikey()); - body.put("mobile",listToString(phones)); - return getSmsResponse(message, body); + return sendMessage(listToString(phones),message); } @Override @Restricted public SmsResponse massTexting(List phones, String templateId, LinkedHashMap messages) { - if (phones.size()>1000){ + if (phones.size() > 1000) { throw new SmsBlendException("单次发送超过最大发送上限,建议每次群发短信人数低于1000"); } - Map body = new HashMap<>(); - body.put("apikey",config.getApikey()); - body.put("mobile",listToString(phones)); - body.put("tpl_id",templateId); - body.put("tpl_value",formattingMap(messages)); - Map 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; + return sendMessage(listToString(phones), templateId, messages); } @Override @@ -115,8 +86,8 @@ public class YunPianSmsImpl implements SmsBlend { @Override @Restricted public void sendMessageAsync(String phone, String templateId, LinkedHashMap messages, CallBack callBack) { - pool.execute(()->{ - SmsResponse smsResponse = sendMessage(phone,templateId,messages); + pool.execute(() -> { + SmsResponse smsResponse = sendMessage(phone, templateId, messages); callBack.callBack(smsResponse); }); } @@ -124,8 +95,8 @@ public class YunPianSmsImpl implements SmsBlend { @Override @Restricted public void sendMessageAsync(String phone, String templateId, LinkedHashMap messages) { - pool.execute(()->{ - sendMessage(phone,templateId,messages); + pool.execute(() -> { + sendMessage(phone, templateId, messages); }); } @@ -135,9 +106,9 @@ public class YunPianSmsImpl implements SmsBlend { this.delayed.schedule(new TimerTask() { @Override public void run() { - sendMessage(phone,message); + sendMessage(phone, message); } - },delayedTime); + }, delayedTime); } @Override @@ -146,9 +117,9 @@ public class YunPianSmsImpl implements SmsBlend { this.delayed.schedule(new TimerTask() { @Override public void run() { - sendMessage(phone,templateId,messages); + sendMessage(phone, templateId, messages); } - },delayedTime); + }, delayedTime); } @Override @@ -157,9 +128,9 @@ public class YunPianSmsImpl implements SmsBlend { this.delayed.schedule(new TimerTask() { @Override public void run() { - massTexting(phones,message); + massTexting(phones, message); } - },delayedTime); + }, delayedTime); } @Override @@ -168,49 +139,76 @@ public class YunPianSmsImpl implements SmsBlend { this.delayed.schedule(new TimerTask() { @Override public void run() { - massTexting(phones,templateId,messages); + massTexting(phones, templateId, messages); } - },delayedTime); + }, delayedTime); } - private String formattingMap(Map messages){ + private String formattingMap(Map messages) { StringBuilder str = new StringBuilder(); - for (Map.Entry entry : messages.entrySet()) { + for (Map.Entry entry : messages.entrySet()) { str.append("#"); str.append(entry.getKey()); str.append("#="); str.append(entry.getValue()); str.append("&"); } - str.deleteCharAt(str.length()-1); + str.deleteCharAt(str.length() - 1); return str.toString(); } - private String listToString(List 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(","); - } + private Map setBody(String phone, String mes, LinkedHashMap messages) { + LinkedHashMap message = new LinkedHashMap<>(); + if (mes.isEmpty()) { + message = messages; + } else { + message.put(config.getTemplateName(), mes); } - return str.toString(); + Map body = new HashMap<>(); + 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 body) { - body.put("text",message); - Map map = new HashMap<>(); - map.put("Accept","application/json;charset=utf-8"); - OKResponse sync = http.setBaseURL("http://sms.yunpian.com/v2").builder() - .headers(map) - .postOrBody("/sms/single_send.json", body) - .sync(); + private Map getHeaders() { + Map headers = new HashMap<>(); + headers.put("Accept", "application/json;charset=utf-8"); + headers.put("Content-Type", Constant.FROM_URLENCODED); + return headers; + } + + @NotNull + private static SmsResponse getSmsResponse(JSONObject execute) { SmsResponse smsResponse = new SmsResponse(); - smsResponse.setCode(sync.getCode()); - JSONObject jsonObject = HTTPUtils.getJSONObject(sync); - smsResponse.setData(jsonObject); + smsResponse.setCode(execute.getString("code")); + smsResponse.setMessage(execute.getString("msg")); + smsResponse.setBizId(execute.getString("sid")); + if (execute.getInteger("code") != 0) { + smsResponse.setErrMessage(execute.getString("msg")); + } + smsResponse.setData(execute); return smsResponse; } + + private SmsResponse getSendResponse(Map body) { + Map headers = getHeaders(); + AtomicReference 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(); + } }