mirror of
https://gitee.com/dromara/sms4j.git
synced 2025-12-06 08:58:38 +08:00
添加华为云模块
添加Forest作为okhttp3替代品 正在开发的版本,因修改http依赖包需重构云片模块
This commit is contained in:
parent
32b0b0285f
commit
1a561009d1
32
pom.xml
32
pom.xml
@ -18,6 +18,7 @@
|
|||||||
<module>sms-aggregation-tencent</module>
|
<module>sms-aggregation-tencent</module>
|
||||||
<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>
|
||||||
</modules>
|
</modules>
|
||||||
<!-- 开源协议 apache 2.0 -->
|
<!-- 开源协议 apache 2.0 -->
|
||||||
<licenses>
|
<licenses>
|
||||||
@ -54,6 +55,7 @@
|
|||||||
<okhttp.version>3.14.9</okhttp.version>
|
<okhttp.version>3.14.9</okhttp.version>
|
||||||
<unisms.version>0.0.4</unisms.version>
|
<unisms.version>0.0.4</unisms.version>
|
||||||
<tencent.version>3.1.622</tencent.version>
|
<tencent.version>3.1.622</tencent.version>
|
||||||
|
<forest.version>1.5.30</forest.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
@ -97,6 +99,12 @@
|
|||||||
<version>${modules.version}</version>
|
<version>${modules.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>kim.wind</groupId>
|
||||||
|
<artifactId>sms-aggregation-huawei</artifactId>
|
||||||
|
<version>${modules.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>kim.wind</groupId>
|
<groupId>kim.wind</groupId>
|
||||||
<artifactId>sms-aggregation-spring-boot-starter</artifactId>
|
<artifactId>sms-aggregation-spring-boot-starter</artifactId>
|
||||||
@ -122,6 +130,12 @@
|
|||||||
<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,6 +157,12 @@
|
|||||||
<artifactId>okhttp</artifactId>
|
<artifactId>okhttp</artifactId>
|
||||||
<version>${okhttp.version}</version>
|
<version>${okhttp.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!--Forest依赖 声明式HTTP客户端框架-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.dtflys.forest</groupId>
|
||||||
|
<artifactId>forest-core</artifactId>
|
||||||
|
<version>${forest.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!--aop依赖-->
|
<!--aop依赖-->
|
||||||
<dependency>
|
<dependency>
|
||||||
@ -164,6 +184,12 @@
|
|||||||
<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>
|
||||||
|
|
||||||
<!-- 腾讯云短信-->
|
<!-- 腾讯云短信-->
|
||||||
@ -171,6 +197,12 @@
|
|||||||
<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>
|
||||||
|
|||||||
@ -36,6 +36,12 @@
|
|||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.dtflys.forest</groupId>
|
||||||
|
<artifactId>forest-core</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package kim.wind.sms.comm.utils;
|
|||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import kim.wind.sms.comm.utils.http.OKResponse;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import okhttp3.*;
|
import okhttp3.*;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
@ -416,81 +417,4 @@ public class HTTPUtils {
|
|||||||
public static JSONObject getJSONObject(Object obj){
|
public static JSONObject getJSONObject(Object obj){
|
||||||
return JSONObject.parseObject(obj.toString());
|
return JSONObject.parseObject(obj.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>类名: OkHTTPUtils
|
|
||||||
* <p>说明: 用于封装请求后返回的参数
|
|
||||||
*
|
|
||||||
* @author :Wind
|
|
||||||
* @date :2022/7/11 16:12
|
|
||||||
**/
|
|
||||||
public class OKResponse {
|
|
||||||
private ResponseBody body;
|
|
||||||
private Headers headers;
|
|
||||||
private Integer code;
|
|
||||||
|
|
||||||
public ResponseBody getBody() {
|
|
||||||
return body;
|
|
||||||
}
|
|
||||||
|
|
||||||
public OKResponse setBody(ResponseBody body) {
|
|
||||||
this.body = body;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Headers getHeaders() {
|
|
||||||
return headers;
|
|
||||||
}
|
|
||||||
|
|
||||||
public OKResponse setHeaders(Headers headers) {
|
|
||||||
this.headers = headers;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Integer getCode() {
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
public OKResponse setCode(Integer code) {
|
|
||||||
this.code = code;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>说明:将返回结果序列化到实体类中
|
|
||||||
* <p>传入对象必须实现了getter和setter方法,否则将序列化失败
|
|
||||||
* @name: getJSONBody
|
|
||||||
* @param t 要序列化的对象
|
|
||||||
* @author :Wind
|
|
||||||
*/
|
|
||||||
public<T> T getJSONBody(Class<T> t) {
|
|
||||||
try {
|
|
||||||
return JSONObject.parseObject(this.getBody().string(), t);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* <p>说明:将返回结果序列化为一个json对象
|
|
||||||
* <p>
|
|
||||||
* @name: getJSONObject
|
|
||||||
* @author :Wind
|
|
||||||
*/
|
|
||||||
public JSONObject getJSONObject(){
|
|
||||||
try {
|
|
||||||
return JSONObject.parseObject(this.getBody().string());
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "OKResponse{" +
|
|
||||||
"body=" + body +
|
|
||||||
", headers=" + headers +
|
|
||||||
", code=" + code +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,84 @@
|
|||||||
|
package kim.wind.sms.comm.utils.http;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import okhttp3.Headers;
|
||||||
|
import okhttp3.ResponseBody;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OKResponse
|
||||||
|
* <p> 用于封装请求后返回的参数
|
||||||
|
*
|
||||||
|
* @author :Wind
|
||||||
|
* 2023/3/31 23:52
|
||||||
|
**/
|
||||||
|
public class OKResponse {
|
||||||
|
private ResponseBody body;
|
||||||
|
private Headers headers;
|
||||||
|
private Integer code;
|
||||||
|
|
||||||
|
public ResponseBody getBody() {
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OKResponse setBody(ResponseBody body) {
|
||||||
|
this.body = body;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Headers getHeaders() {
|
||||||
|
return headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OKResponse setHeaders(Headers headers) {
|
||||||
|
this.headers = headers;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OKResponse setCode(Integer code) {
|
||||||
|
this.code = code;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>说明:将返回结果序列化到实体类中
|
||||||
|
* <p>传入对象必须实现了getter和setter方法,否则将序列化失败
|
||||||
|
* @name: getJSONBody
|
||||||
|
* @param t 要序列化的对象
|
||||||
|
* @author :Wind
|
||||||
|
*/
|
||||||
|
public <T> T getJSONBody(Class<T> t) {
|
||||||
|
try {
|
||||||
|
return JSONObject.parseObject(this.getBody().string(), t);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* <p>说明:将返回结果序列化为一个json对象
|
||||||
|
* <p>
|
||||||
|
* @name: getJSONObject
|
||||||
|
* @author :Wind
|
||||||
|
*/
|
||||||
|
public JSONObject getJSONObject(){
|
||||||
|
try {
|
||||||
|
return JSONObject.parseObject(this.getBody().string());
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "OKResponse{" +
|
||||||
|
"body=" + body +
|
||||||
|
", headers=" + headers +
|
||||||
|
", code=" + code +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
sms-aggregation-huawei/.mvn/wrapper/maven-wrapper.jar
vendored
Normal file
BIN
sms-aggregation-huawei/.mvn/wrapper/maven-wrapper.jar
vendored
Normal file
Binary file not shown.
18
sms-aggregation-huawei/.mvn/wrapper/maven-wrapper.properties
vendored
Normal file
18
sms-aggregation-huawei/.mvn/wrapper/maven-wrapper.properties
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
# or more contributor license agreements. See the NOTICE file
|
||||||
|
# distributed with this work for additional information
|
||||||
|
# regarding copyright ownership. The ASF licenses this file
|
||||||
|
# to you under the Apache License, Version 2.0 (the
|
||||||
|
# "License"); you may not use this file except in compliance
|
||||||
|
# with the License. You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing,
|
||||||
|
# software distributed under the License is distributed on an
|
||||||
|
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
# KIND, either express or implied. See the License for the
|
||||||
|
# specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.7/apache-maven-3.8.7-bin.zip
|
||||||
|
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar
|
||||||
37
sms-aggregation-huawei/pom.xml
Normal file
37
sms-aggregation-huawei/pom.xml
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>kim.wind</groupId>
|
||||||
|
<artifactId>sms_aggregation</artifactId>
|
||||||
|
<version>1.0.2</version>
|
||||||
|
<relativePath>../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
<artifactId>sms-aggregation-huawei</artifactId>
|
||||||
|
<version>1.0.2</version>
|
||||||
|
<name>sms-aggregation-huawei</name>
|
||||||
|
<description>sms-aggregation-huawei</description>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<java.version>1.8</java.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>kim.wind</groupId>
|
||||||
|
<artifactId>sms-aggregation-comm</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>kim.wind</groupId>
|
||||||
|
<artifactId>sms-aggregation-api</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
package kim.wind.sms.huawei.config;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
|
||||||
|
|
||||||
|
@ConfigurationProperties(prefix = "sms.huawei") //指定配置文件注入属性前缀
|
||||||
|
@Data
|
||||||
|
public class HuaweiSmsConfig {
|
||||||
|
|
||||||
|
/** appKey*/
|
||||||
|
private String appKey ;
|
||||||
|
/** appSecret */
|
||||||
|
private String appSecret ;
|
||||||
|
/** 短信签名*/
|
||||||
|
private String signature;
|
||||||
|
/** 国内短信签名通道号*/
|
||||||
|
private String sender;
|
||||||
|
/** 模板Id*/
|
||||||
|
private String templateId;
|
||||||
|
/** 短信状态报告接收地*/
|
||||||
|
private String statusCallBack;
|
||||||
|
/** APP接入地址*/
|
||||||
|
private String url;
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
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() {
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,58 @@
|
|||||||
|
package kim.wind.sms.huawei.entity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HuaweiError
|
||||||
|
* <p> 华为官方状态码枚举
|
||||||
|
*
|
||||||
|
* @author :Wind
|
||||||
|
* 2023/3/31 22:11
|
||||||
|
**/
|
||||||
|
public enum HuaweiError {
|
||||||
|
E000000("000000","短信平台处理请求成功"),
|
||||||
|
E200015("E200015","待发送短信数量太大"),
|
||||||
|
E200028("E200028","模板变量校验失败"),
|
||||||
|
E200029("E200029","E200029"),
|
||||||
|
E200030("E200030","模板未激活"),
|
||||||
|
E200031("E200031","协议校验失败"),
|
||||||
|
E200033("E200033","模板类型不正确"),
|
||||||
|
E200041("E200041","同一短信内容接收号码重复")
|
||||||
|
;
|
||||||
|
|
||||||
|
private final String value;
|
||||||
|
|
||||||
|
private final String code;
|
||||||
|
|
||||||
|
HuaweiError(String code, String value) {
|
||||||
|
this.value = value;
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
public static String getValue(String code){
|
||||||
|
switch (code){
|
||||||
|
case "000000":
|
||||||
|
return E000000.getValue();
|
||||||
|
case "E200015":
|
||||||
|
return E200015.getValue();
|
||||||
|
case "E200028":
|
||||||
|
return E200028.getValue();
|
||||||
|
case "E200029":
|
||||||
|
return E200029.getValue();
|
||||||
|
case "E200030":
|
||||||
|
return E200030.getValue();
|
||||||
|
case "E200031":
|
||||||
|
return E200031.getValue();
|
||||||
|
case "E200033":
|
||||||
|
return E200033.getValue();
|
||||||
|
case "E200041":
|
||||||
|
return E200041.getValue();
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
package kim.wind.sms.huawei.entity;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HuaweiResponse
|
||||||
|
* <p> 华为响应参数
|
||||||
|
*
|
||||||
|
* @author :Wind
|
||||||
|
* 2023/3/31 22:20
|
||||||
|
**/
|
||||||
|
@Data
|
||||||
|
public class HuaweiResponse {
|
||||||
|
|
||||||
|
/** 请求返回的结果码*/
|
||||||
|
private String code;
|
||||||
|
|
||||||
|
/** 请求返回的结果码描述*/
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
/** 短信ID列表,当目的号码存在多个时,每个号码都会返回一个SmsID。
|
||||||
|
当返回异常响应时不携带此字段*/
|
||||||
|
private List<SmsId> smsId;
|
||||||
|
}
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
package kim.wind.sms.huawei.entity;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SmsId
|
||||||
|
* <p> 短信ID列表
|
||||||
|
*
|
||||||
|
* @author :Wind
|
||||||
|
* 2023/3/31 21:55
|
||||||
|
**/
|
||||||
|
@Data
|
||||||
|
public class SmsId {
|
||||||
|
|
||||||
|
/** 短信的唯一标识*/
|
||||||
|
private String smsMsgId;
|
||||||
|
|
||||||
|
/** 短信发送方的号码*/
|
||||||
|
private String from;
|
||||||
|
|
||||||
|
/** 短信接收方的号码*/
|
||||||
|
private String originTo;
|
||||||
|
|
||||||
|
/** 短信状态码*/
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
/** 短信资源的创建时间,即短信平台接收到用户发送短信请求的时间,为UTC时间*/
|
||||||
|
private String createTime;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,145 @@
|
|||||||
|
package kim.wind.sms.huawei.service;
|
||||||
|
|
||||||
|
import kim.wind.sms.huawei.constant.Constant;
|
||||||
|
import kim.wind.sms.huawei.entity.HuaweiError;
|
||||||
|
|
||||||
|
import javax.net.ssl.HttpsURLConnection;
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
|
import javax.net.ssl.TrustManager;
|
||||||
|
import javax.net.ssl.X509TrustManager;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.cert.CertificateException;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class HuaweiBuilder {
|
||||||
|
private HuaweiBuilder(){}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* buildWsseHeader
|
||||||
|
* <p>构造X-WSSE参数值
|
||||||
|
* @author :Wind
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
String time = dateFormat(new Date());
|
||||||
|
String nonce = UUID.randomUUID().toString().replace("-", ""); //Nonce
|
||||||
|
MessageDigest md;
|
||||||
|
byte[] passwordDigest = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
md = MessageDigest.getInstance("SHA-256");
|
||||||
|
md.update((nonce + time + appSecret).getBytes());
|
||||||
|
passwordDigest = md.digest();
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void trustAllHttpsCertificates() throws Exception {
|
||||||
|
TrustManager[] trustAllCerts = new TrustManager[] {
|
||||||
|
new X509TrustManager() {
|
||||||
|
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
public X509Certificate[] getAcceptedIssuers() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
SSLContext sc = SSLContext.getInstance("SSL");
|
||||||
|
sc.init(null, trustAllCerts, null);
|
||||||
|
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* buildRequestBody
|
||||||
|
* <p>构造请求Body体
|
||||||
|
* @param sender
|
||||||
|
* @param receiver
|
||||||
|
* @param templateId
|
||||||
|
* @param templateParas
|
||||||
|
* @param statusCallBack
|
||||||
|
* @param signature | 签名名称,使用国内短信通用模板时填写
|
||||||
|
* @author :Wind
|
||||||
|
*/
|
||||||
|
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.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Map<String, String> map = new HashMap<String, String>();
|
||||||
|
|
||||||
|
map.put("from", sender);
|
||||||
|
map.put("to", receiver);
|
||||||
|
map.put("templateId", templateId);
|
||||||
|
if (null != templateParas && !templateParas.isEmpty()) {
|
||||||
|
map.put("templateParas", templateParas);
|
||||||
|
}
|
||||||
|
if (null != statusCallBack && !statusCallBack.isEmpty()) {
|
||||||
|
map.put("statusCallback", statusCallBack);
|
||||||
|
}
|
||||||
|
if (null != signature && !signature.isEmpty()) {
|
||||||
|
map.put("signature", signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
String temp = "";
|
||||||
|
|
||||||
|
for (String s : map.keySet()) {
|
||||||
|
try {
|
||||||
|
temp = URLEncoder.encode(map.get(s), "UTF-8");
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
sb.append(s).append("=").append(temp).append("&");
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.deleteCharAt(sb.length()-1).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
static String listToString(List<String> list){
|
||||||
|
StringBuilder stringBuffer = new StringBuilder();
|
||||||
|
stringBuffer.append("[\"");
|
||||||
|
for (String s : list) {
|
||||||
|
stringBuffer.append(s);
|
||||||
|
stringBuffer.append("\"");
|
||||||
|
stringBuffer.append(",");
|
||||||
|
}
|
||||||
|
stringBuffer.deleteCharAt(stringBuffer.length()-1);
|
||||||
|
stringBuffer.append("]");
|
||||||
|
return stringBuffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
static String dateFormat(Date date){
|
||||||
|
SimpleDateFormat sdf = new SimpleDateFormat(Constant.JAVA_DATE);
|
||||||
|
return sdf.format(date);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Date strForDate(String date){
|
||||||
|
SimpleDateFormat sdf = new SimpleDateFormat(Constant.JAVA_DATE);
|
||||||
|
try {
|
||||||
|
return sdf.parse(date);
|
||||||
|
} catch (ParseException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,127 @@
|
|||||||
|
package kim.wind.sms.huawei.service;
|
||||||
|
|
||||||
|
import kim.wind.sms.api.SmsBlend;
|
||||||
|
import kim.wind.sms.api.callback.CallBack;
|
||||||
|
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 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.concurrent.Executor;
|
||||||
|
|
||||||
|
@EnableConfigurationProperties({HuaweiSmsConfig.class})
|
||||||
|
@Slf4j
|
||||||
|
public class HuaweiSmsImpl implements SmsBlend {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private HuaweiSmsConfig config;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
@Qualifier("smsExecutor")
|
||||||
|
private Executor pool;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DelayedTime delayed;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private HTTPUtils http ;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SmsResponse sendMessage(String phone, String message) {
|
||||||
|
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SmsResponse sendMessage(String phone, String templateId, LinkedHashMap<String, String> messages) {
|
||||||
|
List<String> list = new ArrayList<>();
|
||||||
|
for (Map.Entry<String, String> entry : messages.entrySet()) {
|
||||||
|
list.add(entry.getValue());
|
||||||
|
}
|
||||||
|
String mess = HuaweiBuilder.listToString(list);
|
||||||
|
String requestBody = HuaweiBuilder.buildRequestBody(config.getSender(), phone, config.getTemplateId(), mess, config.getStatusCallBack(), config.getSignature());
|
||||||
|
Map<String,String> headers = new LinkedHashMap<>();
|
||||||
|
headers.put("Authorization",Constant.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);
|
||||||
|
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()));
|
||||||
|
}
|
||||||
|
return smsResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SmsResponse massTexting(List<String> phones, String message) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SmsResponse massTexting(List<String> phones, String templateId, LinkedHashMap<String, String> messages) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendMessageAsync(String phone, String message, CallBack callBack) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendMessageAsync(String phone, String message) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendMessageAsync(String phone, String templateId, LinkedHashMap<String, String> messages, CallBack callBack) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendMessageAsync(String phone, String templateId, LinkedHashMap<String, String> messages) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void delayedMessage(String phone, String message, Long delayedTime) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void delayedMessage(String phone, String templateId, LinkedHashMap<String, String> messages, Long delayedTime) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void delayMassTexting(List<String> phones, String message, Long delayedTime) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void delayMassTexting(List<String> phones, String templateId, LinkedHashMap<String, String> messages, Long delayedTime) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1 @@
|
|||||||
|
|
||||||
@ -51,6 +51,11 @@
|
|||||||
<artifactId>sms-aggregation-yunpian</artifactId>
|
<artifactId>sms-aggregation-yunpian</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>kim.wind</groupId>
|
||||||
|
<artifactId>sms-aggregation-huawei</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!--aop依赖-->
|
<!--aop依赖-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
|||||||
@ -1,5 +1,8 @@
|
|||||||
package kim.wind.sms.starter.config;
|
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.unisms.service.UniSmsImpl;
|
||||||
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;
|
||||||
@ -69,6 +72,36 @@ public class SmsMainConfig {
|
|||||||
return new 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
|
@Bean
|
||||||
public SmsBlend smsBlend(){
|
public SmsBlend smsBlend(){
|
||||||
SmsBlend smsBlend = null;
|
SmsBlend smsBlend = null;
|
||||||
@ -85,6 +118,9 @@ public class SmsMainConfig {
|
|||||||
case "tencent":
|
case "tencent":
|
||||||
smsBlend = new TencentSmsImpl();
|
smsBlend = new TencentSmsImpl();
|
||||||
break;
|
break;
|
||||||
|
case "huawei":
|
||||||
|
smsBlend = new HuaweiSmsImpl();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if ("true".equals(isPrint)){
|
if ("true".equals(isPrint)){
|
||||||
SmsBanner.PrintBanner();
|
SmsBanner.PrintBanner();
|
||||||
@ -109,23 +145,4 @@ public class SmsMainConfig {
|
|||||||
return executor;
|
return executor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@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();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,6 +8,7 @@ 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.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.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;
|
||||||
@ -49,7 +50,7 @@ public class YunPianSmsImpl implements SmsBlend {
|
|||||||
body.put("tpl_value",formattingMap(messages));
|
body.put("tpl_value",formattingMap(messages));
|
||||||
Map<String,String> map = new HashMap<>();
|
Map<String,String> map = new HashMap<>();
|
||||||
map.put("Accept","application/json;charset=utf-8");
|
map.put("Accept","application/json;charset=utf-8");
|
||||||
HTTPUtils.OKResponse sync = http.setBaseURL("https://sms.yunpian.com/v2").builder()
|
OKResponse sync = http.setBaseURL("https://sms.yunpian.com/v2").builder()
|
||||||
.headers(map)
|
.headers(map)
|
||||||
.postOrBody("/sms/tpl_single_send.json", body)
|
.postOrBody("/sms/tpl_single_send.json", body)
|
||||||
.sync();
|
.sync();
|
||||||
@ -85,7 +86,7 @@ public class YunPianSmsImpl implements SmsBlend {
|
|||||||
body.put("tpl_value",formattingMap(messages));
|
body.put("tpl_value",formattingMap(messages));
|
||||||
Map<String,String> map = new HashMap<>();
|
Map<String,String> map = new HashMap<>();
|
||||||
map.put("Accept","application/json;charset=utf-8");
|
map.put("Accept","application/json;charset=utf-8");
|
||||||
HTTPUtils.OKResponse sync = http.setBaseURL("https://sms.yunpian.com/v2").builder()
|
OKResponse sync = http.setBaseURL("https://sms.yunpian.com/v2").builder()
|
||||||
.headers(map)
|
.headers(map)
|
||||||
.postOrBody("/tpl_batch_send.json", body)
|
.postOrBody("/tpl_batch_send.json", body)
|
||||||
.sync();
|
.sync();
|
||||||
@ -202,7 +203,7 @@ public class YunPianSmsImpl implements SmsBlend {
|
|||||||
body.put("text",message);
|
body.put("text",message);
|
||||||
Map<String,String> map = new HashMap<>();
|
Map<String,String> map = new HashMap<>();
|
||||||
map.put("Accept","application/json;charset=utf-8");
|
map.put("Accept","application/json;charset=utf-8");
|
||||||
HTTPUtils.OKResponse sync = http.setBaseURL("http://sms.yunpian.com/v2").builder()
|
OKResponse sync = http.setBaseURL("http://sms.yunpian.com/v2").builder()
|
||||||
.headers(map)
|
.headers(map)
|
||||||
.postOrBody("/sms/single_send.json", body)
|
.postOrBody("/sms/single_send.json", body)
|
||||||
.sync();
|
.sync();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user