添加华为云模块

添加Forest作为okhttp3替代品
正在开发的版本,因修改http依赖包需重构云片模块
This commit is contained in:
wind 2023-03-31 23:56:27 +08:00
parent 32b0b0285f
commit 1a561009d1
18 changed files with 673 additions and 99 deletions

32
pom.xml
View File

@ -18,6 +18,7 @@
<module>sms-aggregation-tencent</module>
<module>sms-aggregation-yunpian</module>
<module>sms-aggregation-spring-boot-starter</module>
<module>sms-aggregation-huawei</module>
</modules>
<!-- 开源协议 apache 2.0 -->
<licenses>
@ -54,6 +55,7 @@
<okhttp.version>3.14.9</okhttp.version>
<unisms.version>0.0.4</unisms.version>
<tencent.version>3.1.622</tencent.version>
<forest.version>1.5.30</forest.version>
</properties>
<dependencyManagement>
@ -97,6 +99,12 @@
<version>${modules.version}</version>
</dependency>
<dependency>
<groupId>kim.wind</groupId>
<artifactId>sms-aggregation-huawei</artifactId>
<version>${modules.version}</version>
</dependency>
<dependency>
<groupId>kim.wind</groupId>
<artifactId>sms-aggregation-spring-boot-starter</artifactId>
@ -122,6 +130,12 @@
<groupId>com.aliyun</groupId>
<artifactId>dysmsapi20170525</artifactId>
<version>${aliyun.version}</version>
<exclusions>
<exclusion>
<artifactId>okhttp</artifactId>
<groupId>com.squareup.okhttp3</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- 阿里JSON解析器 -->
@ -143,6 +157,12 @@
<artifactId>okhttp</artifactId>
<version>${okhttp.version}</version>
</dependency>
<!--Forest依赖 声明式HTTP客户端框架-->
<dependency>
<groupId>com.dtflys.forest</groupId>
<artifactId>forest-core</artifactId>
<version>${forest.version}</version>
</dependency>
<!--aop依赖-->
<dependency>
@ -164,6 +184,12 @@
<groupId>com.apistd.uni</groupId>
<artifactId>uni-sdk</artifactId>
<version>${unisms.version}</version>
<exclusions>
<exclusion>
<artifactId>okhttp</artifactId>
<groupId>com.squareup.okhttp3</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- 腾讯云短信-->
@ -171,6 +197,12 @@
<groupId>com.tencentcloudapi</groupId>
<artifactId>tencentcloud-sdk-java</artifactId>
<version>${tencent.version}</version>
<exclusions>
<exclusion>
<artifactId>okhttp</artifactId>
<groupId>com.squareup.okhttp3</groupId>
</exclusion>
</exclusions>
</dependency>
</dependencies>

View File

@ -36,6 +36,12 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>com.dtflys.forest</groupId>
<artifactId>forest-core</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -2,6 +2,7 @@ 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;
@ -416,81 +417,4 @@ public class HTTPUtils {
public static JSONObject getJSONObject(Object obj){
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 +
'}';
}
}
}

View File

@ -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 +
'}';
}
}

Binary file not shown.

View 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

View 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>

View File

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

View File

@ -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() {
}
}

View File

@ -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 "";
}
}

View File

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

View File

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

View File

@ -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);
}
}
}

View File

@ -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) {
}
}

View File

@ -51,6 +51,11 @@
<artifactId>sms-aggregation-yunpian</artifactId>
</dependency>
<dependency>
<groupId>kim.wind</groupId>
<artifactId>sms-aggregation-huawei</artifactId>
</dependency>
<!--aop依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>

View File

@ -1,5 +1,8 @@
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;
@ -69,6 +72,36 @@ public class SmsMainConfig {
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;
@ -85,6 +118,9 @@ public class SmsMainConfig {
case "tencent":
smsBlend = new TencentSmsImpl();
break;
case "huawei":
smsBlend = new HuaweiSmsImpl();
break;
}
if ("true".equals(isPrint)){
SmsBanner.PrintBanner();
@ -109,23 +145,4 @@ public class SmsMainConfig {
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();
}
}

View File

@ -8,6 +8,7 @@ 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.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
@ -49,7 +50,7 @@ public class YunPianSmsImpl implements SmsBlend {
body.put("tpl_value",formattingMap(messages));
Map<String,String> map = new HashMap<>();
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)
.postOrBody("/sms/tpl_single_send.json", body)
.sync();
@ -85,7 +86,7 @@ public class YunPianSmsImpl implements SmsBlend {
body.put("tpl_value",formattingMap(messages));
Map<String,String> map = new HashMap<>();
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)
.postOrBody("/tpl_batch_send.json", body)
.sync();
@ -202,7 +203,7 @@ public class YunPianSmsImpl implements SmsBlend {
body.put("text",message);
Map<String,String> map = new HashMap<>();
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)
.postOrBody("/sms/single_send.json", body)
.sync();