update 短信失败重试

This commit is contained in:
bleachtred 2023-08-12 21:01:40 +08:00
parent 7011849d57
commit 79108f7d1d
21 changed files with 424 additions and 166 deletions

View File

@ -19,10 +19,5 @@
<groupId>org.dromara.sms4j</groupId> <groupId>org.dromara.sms4j</groupId>
<artifactId>sms4j-comm</artifactId> <artifactId>sms4j-comm</artifactId>
</dependency> </dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-http</artifactId>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -25,5 +25,11 @@
<groupId>cn.hutool</groupId> <groupId>cn.hutool</groupId>
<artifactId>hutool-json</artifactId> <artifactId>hutool-json</artifactId>
</dependency> </dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-http</artifactId>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -28,6 +28,8 @@ public abstract class Constant {
*/ */
public static final String FROM_URLENCODED = "application/x-www-form-urlencoded"; public static final String FROM_URLENCODED = "application/x-www-form-urlencoded";
public static final String ACCEPT = "application/json";
public static final String APPLICATION_JSON_UTF8 = "application/json; charset=utf-8"; public static final String APPLICATION_JSON_UTF8 = "application/json; charset=utf-8";
/** /**

View File

@ -0,0 +1,79 @@
package org.dromara.sms4j.comm.utils;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import org.dromara.sms4j.comm.exception.SmsBlendException;
import java.util.Map;
public class SmsHttpUtil {
private SmsHttpUtil() {
}
private static class SmsHttpHolder {
private static final SmsHttpUtil INSTANCE = new SmsHttpUtil();
}
public static SmsHttpUtil instance() {
return SmsHttpHolder.INSTANCE;
}
/**
* 发送post json请求
* @param url 请求地址
* @param headers 请求头
* @param body 请求体(json格式字符串)
* @return 返回体
*/
public JSONObject postJson(String url, Map<String, String> headers, String body){
try(HttpResponse response = HttpRequest.post(url)
.addHeaders(headers)
.body(body)
.execute()){
return JSONUtil.parseObj(response.body());
}catch (Exception e){
throw new SmsBlendException(e.getMessage());
}
}
/**
* 发送post json请求
* @param url 请求地址
* @param headers 请求头
* @param body 请求体(map格式请求体)
* @return 返回体
*/
public JSONObject postJson(String url, Map<String, String> headers, Map<String, Object> body){
return postJson(url, headers, JSONUtil.toJsonStr(body));
}
/**
* 发送post form 请求
* @param url 请求地址
* @param headers 请求头
* @param body 请求体(map格式请求体)
* @return 返回体
*/
public JSONObject postFrom(String url, Map<String, String> headers, Map<String, Object> body){
try(HttpResponse response = HttpRequest.post(url)
.addHeaders(headers)
.form(body)
.execute()){
return JSONUtil.parseObj(response.body());
}catch (Exception e){
throw new SmsBlendException(e.getMessage());
}
}
/**
* 线程睡眠
* @param retryInterval
*/
public void safeSleep(int retryInterval){
ThreadUtil.safeSleep(retryInterval * 1000L);
}
}

View File

@ -1,13 +1,12 @@
package org.dromara.sms4j.aliyun.service; package org.dromara.sms4j.aliyun.service;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONObject; import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil; import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.dromara.sms4j.aliyun.config.AlibabaConfig; import org.dromara.sms4j.aliyun.config.AlibabaConfig;
import org.dromara.sms4j.aliyun.utils.AliyunUtils; import org.dromara.sms4j.aliyun.utils.AliyunUtils;
import org.dromara.sms4j.api.entity.SmsResponse; import org.dromara.sms4j.api.entity.SmsResponse;
import org.dromara.sms4j.comm.constant.Constant;
import org.dromara.sms4j.comm.delayedTime.DelayedTime; import org.dromara.sms4j.comm.delayedTime.DelayedTime;
import org.dromara.sms4j.comm.exception.SmsBlendException; import org.dromara.sms4j.comm.exception.SmsBlendException;
import org.dromara.sms4j.comm.utils.SmsUtil; import org.dromara.sms4j.comm.utils.SmsUtil;
@ -15,6 +14,7 @@ import org.dromara.sms4j.provider.service.AbstractSmsBlend;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
/** /**
@ -28,6 +28,7 @@ import java.util.concurrent.Executor;
public class AlibabaSmsImpl extends AbstractSmsBlend<AlibabaConfig> { public class AlibabaSmsImpl extends AbstractSmsBlend<AlibabaConfig> {
public static final String SUPPLIER = "alibaba"; public static final String SUPPLIER = "alibaba";
private int retry = 0;
/** /**
* AlibabaSmsImpl * AlibabaSmsImpl
@ -89,15 +90,27 @@ public class AlibabaSmsImpl extends AbstractSmsBlend<AlibabaConfig> {
throw new SmsBlendException(e.getMessage()); throw new SmsBlendException(e.getMessage());
} }
log.debug("requestUrl {}", requestUrl); log.debug("requestUrl {}", requestUrl);
try(HttpResponse response = HttpRequest.post(requestUrl) try {
.header("Content-Type", "application/x-www-form-urlencoded") Map<String, String> headers = new LinkedHashMap<>(1);
.body(paramStr) headers.put("Content-Type", Constant.FROM_URLENCODED);
.execute()){ SmsResponse smsResponse = getResponse(http.postJson(requestUrl, headers, paramStr));
JSONObject body = JSONUtil.parseObj(response.body()); if(smsResponse.isSuccess() || retry == getConfig().getMaxRetries()){
return this.getResponse(body); retry = 0;
return smsResponse;
}
return requestRetry(phone, message, templateId);
}catch (SmsBlendException e){
return requestRetry(phone, message, templateId);
} }
} }
private SmsResponse requestRetry(String phone, String message, String templateId) {
http.safeSleep(getConfig().getRetryInterval());
retry++;
log.warn("短信第 {" + retry + "} 次重新发送");
return getSmsResponse(phone, message, templateId);
}
private SmsResponse getResponse(JSONObject resJson) { private SmsResponse getResponse(JSONObject resJson) {
SmsResponse smsResponse = new SmsResponse(); SmsResponse smsResponse = new SmsResponse();
smsResponse.setSuccess("OK".equals(resJson.getStr("Code"))); smsResponse.setSuccess("OK".equals(resJson.getStr("Code")));

View File

@ -1,6 +1,5 @@
package org.dromara.sms4j.cloopen.service; package org.dromara.sms4j.cloopen.service;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.IdUtil;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.dromara.sms4j.api.entity.SmsResponse; import org.dromara.sms4j.api.entity.SmsResponse;
@ -51,15 +50,15 @@ public class CloopenSmsImpl extends AbstractSmsBlend<CloopenConfig> {
@Override @Override
public SmsResponse massTexting(List<String> phones, String message) { public SmsResponse massTexting(List<String> phones, String message) {
LinkedHashMap<String, String> map = new LinkedHashMap<>(); LinkedHashMap<String, String> map = new LinkedHashMap<>(1);
map.put(IdUtil.fastSimpleUUID(), message); map.put(IdUtil.fastSimpleUUID(), message);
return massTexting(phones, getConfig().getTemplateId(), map); return massTexting(phones, getConfig().getTemplateId(), map);
} }
@Override @Override
public SmsResponse massTexting(List<String> phones, String templateId, LinkedHashMap<String, String> messages) { public SmsResponse massTexting(List<String> phones, String templateId, LinkedHashMap<String, String> messages) {
CloopenHelper helper = new CloopenHelper(getConfig()); CloopenHelper helper = new CloopenHelper(getConfig(), http);
Map<String, Object> paramMap = MapUtil.newHashMap(4); Map<String, Object> paramMap = new LinkedHashMap<>(4);
paramMap.put("to", String.join(",", phones)); paramMap.put("to", String.join(",", phones));
paramMap.put("appId", getConfig().getAppId()); paramMap.put("appId", getConfig().getAppId());
paramMap.put("templateId", templateId); paramMap.put("templateId", templateId);

View File

@ -4,14 +4,16 @@ import cn.hutool.core.codec.Base64;
import cn.hutool.core.date.DatePattern; import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.DateUtil;
import cn.hutool.crypto.SecureUtil; import cn.hutool.crypto.SecureUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONObject; import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil; import lombok.extern.slf4j.Slf4j;
import org.dromara.sms4j.api.entity.SmsResponse; import org.dromara.sms4j.api.entity.SmsResponse;
import org.dromara.sms4j.cloopen.config.CloopenConfig; import org.dromara.sms4j.cloopen.config.CloopenConfig;
import org.dromara.sms4j.comm.constant.Constant;
import org.dromara.sms4j.comm.exception.SmsBlendException;
import org.dromara.sms4j.comm.utils.SmsHttpUtil;
import java.util.Date; import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
/** /**
@ -20,33 +22,48 @@ import java.util.Map;
* @author Charles7c * @author Charles7c
* @since 2023/4/17 20:57 * @since 2023/4/17 20:57
*/ */
@Slf4j
public class CloopenHelper { public class CloopenHelper {
private final CloopenConfig config; private final CloopenConfig config;
private final SmsHttpUtil http;
private int retry = 0;
public CloopenHelper(CloopenConfig config) { public CloopenHelper(CloopenConfig config, SmsHttpUtil http) {
this.config = config; this.config = config;
this.http = http;
} }
public SmsResponse smsResponse(Map<String, Object> paramMap){ public SmsResponse smsResponse(Map<String, Object> paramMap){
String timestamp = DateUtil.format(new Date(), DatePattern.PURE_DATETIME_PATTERN); try {
String timestamp = DateUtil.format(new Date(), DatePattern.PURE_DATETIME_PATTERN);
String url = String.format("%s/Accounts/%s/SMS/TemplateSMS?sig=%s", String url = String.format("%s/Accounts/%s/SMS/TemplateSMS?sig=%s",
config.getBaseUrl(), config.getBaseUrl(),
config.getAccessKeyId(), config.getAccessKeyId(),
this.generateSign(config.getAccessKeyId(), config.getAccessKeySecret(), timestamp)); this.generateSign(config.getAccessKeyId(), config.getAccessKeySecret(), timestamp));
Map<String, String> headers = new LinkedHashMap<>(3);
try(HttpResponse response = HttpRequest.post(url) headers.put("Accept", Constant.ACCEPT);
.header("Accept", "application/json") headers.put("Content-Type", Constant.APPLICATION_JSON_UTF8);
.header("Content-Type", "application/json;charset=utf-8") headers.put("Authorization", this.generateAuthorization(config.getAccessKeyId(), timestamp));
.header("Authorization", this.generateAuthorization(config.getAccessKeyId(), timestamp)) SmsResponse smsResponse = getResponse(http.postJson(url, headers, paramMap));
.body(JSONUtil.toJsonStr(paramMap)) if(smsResponse.isSuccess() || retry == config.getMaxRetries()){
.execute()){ retry = 0;
JSONObject body = JSONUtil.parseObj(response.body()); return smsResponse;
return this.getResponse(body); }
return requestRetry(paramMap);
}catch (SmsBlendException e){
return requestRetry(paramMap);
} }
} }
private SmsResponse requestRetry(Map<String, Object> paramMap) {
http.safeSleep(config.getRetryInterval());
retry++;
log.warn("短信第 {" + retry + "} 次重新发送");
return smsResponse(paramMap);
}
private SmsResponse getResponse(JSONObject resJson) { private SmsResponse getResponse(JSONObject resJson) {
SmsResponse smsResponse = new SmsResponse(); SmsResponse smsResponse = new SmsResponse();
smsResponse.setSuccess("000000".equals(resJson.getStr("statusCode"))); smsResponse.setSuccess("000000".equals(resJson.getStr("statusCode")));

View File

@ -1,7 +1,5 @@
package org.dromara.sms4j.ctyun.service; package org.dromara.sms4j.ctyun.service;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONObject; import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil; import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -29,6 +27,8 @@ public class CtyunSmsImpl extends AbstractSmsBlend<CtyunConfig> {
public static final String SUPPLIER = "ctyun"; public static final String SUPPLIER = "ctyun";
private int retry = 0;
public CtyunSmsImpl(CtyunConfig config, Executor pool, DelayedTime delayedTime) { public CtyunSmsImpl(CtyunConfig config, Executor pool, DelayedTime delayedTime) {
super(config, pool, delayedTime); super(config, pool, delayedTime);
} }
@ -44,7 +44,7 @@ public class CtyunSmsImpl extends AbstractSmsBlend<CtyunConfig> {
@Override @Override
public SmsResponse sendMessage(String phone, String message) { public SmsResponse sendMessage(String phone, String message) {
LinkedHashMap<String, String> map = new LinkedHashMap<>(); LinkedHashMap<String, String> map = new LinkedHashMap<>(1);
map.put(getConfig().getTemplateName(), message); map.put(getConfig().getTemplateName(), message);
return sendMessage(phone, getConfig().getTemplateId(), map); return sendMessage(phone, getConfig().getTemplateId(), map);
} }
@ -57,7 +57,7 @@ public class CtyunSmsImpl extends AbstractSmsBlend<CtyunConfig> {
@Override @Override
public SmsResponse massTexting(List<String> phones, String message) { public SmsResponse massTexting(List<String> phones, String message) {
LinkedHashMap<String, String> map = new LinkedHashMap<>(); LinkedHashMap<String, String> map = new LinkedHashMap<>(1);
map.put(getConfig().getTemplateName(), message); map.put(getConfig().getTemplateName(), message);
return massTexting(phones, getConfig().getTemplateId(), map); return massTexting(phones, getConfig().getTemplateId(), map);
} }
@ -79,15 +79,27 @@ public class CtyunSmsImpl extends AbstractSmsBlend<CtyunConfig> {
throw new SmsBlendException(e.getMessage()); throw new SmsBlendException(e.getMessage());
} }
log.debug("requestUrl {}", requestUrl); log.debug("requestUrl {}", requestUrl);
try(HttpResponse response = HttpRequest.post(requestUrl) try {
.addHeaders(CtyunUtils.signHeader(paramStr, getConfig().getAccessKeyId(), getConfig().getAccessKeySecret())) SmsResponse smsResponse = getResponse(http.postJson(requestUrl,
.body(paramStr) CtyunUtils.signHeader(paramStr, getConfig().getAccessKeyId(), getConfig().getAccessKeySecret()),
.execute()){ paramStr));
JSONObject body = JSONUtil.parseObj(response.body()); if(smsResponse.isSuccess() || retry == getConfig().getMaxRetries()){
return this.getResponse(body); retry = 0;
return smsResponse;
}
return requestRetry(phone, message, templateId);
}catch (SmsBlendException e){
return requestRetry(phone, message, templateId);
} }
} }
private SmsResponse requestRetry(String phone, String message, String templateId) {
http.safeSleep(getConfig().getRetryInterval());
retry ++;
log.warn("短信第 {" + retry + "} 次重新发送");
return getSmsResponse(phone, message, templateId);
}
private SmsResponse getResponse(JSONObject resJson) { private SmsResponse getResponse(JSONObject resJson) {
SmsResponse smsResponse = new SmsResponse(); SmsResponse smsResponse = new SmsResponse();
smsResponse.setSuccess("OK".equals(resJson.getStr("code"))); smsResponse.setSuccess("OK".equals(resJson.getStr("code")));

View File

@ -6,6 +6,7 @@ import cn.hutool.crypto.digest.HmacAlgorithm;
import cn.hutool.json.JSONUtil; import cn.hutool.json.JSONUtil;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import org.dromara.sms4j.comm.constant.Constant;
import org.dromara.sms4j.comm.exception.SmsBlendException; import org.dromara.sms4j.comm.exception.SmsBlendException;
import org.dromara.sms4j.ctyun.config.CtyunConfig; import org.dromara.sms4j.ctyun.config.CtyunConfig;
@ -35,7 +36,7 @@ public class CtyunUtils {
* 获取签名请求头 * 获取签名请求头
*/ */
public static Map<String, String> signHeader(String body, String key, String secret){ public static Map<String, String> signHeader(String body, String key, String secret){
Map<String, String> map = new ConcurrentHashMap<>(); Map<String, String> map = new ConcurrentHashMap<>(4);
// 构造时间戳 // 构造时间戳
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd"); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
@ -58,7 +59,7 @@ public class CtyunUtils {
// 构造签名 // 构造签名
String signature = Base64.encode(hmacSHA256(signatureStr.getBytes(StandardCharsets.UTF_8), kDate)); String signature = Base64.encode(hmacSHA256(signatureStr.getBytes(StandardCharsets.UTF_8), kDate));
String signHeader = String.format("%s Headers=ctyun-eop-request-id;eop-date Signature=%s", key, signature); String signHeader = String.format("%s Headers=ctyun-eop-request-id;eop-date Signature=%s", key, signature);
map.put("Content-Type", "application/json;charset=UTF-8"); map.put("Content-Type", Constant.APPLICATION_JSON_UTF8);
map.put("ctyun-eop-request-id", uuid); map.put("ctyun-eop-request-id", uuid);
map.put("Eop-date", signatureTime); map.put("Eop-date", signatureTime);
map.put("Eop-Authorization", signHeader); map.put("Eop-Authorization", signHeader);
@ -74,7 +75,7 @@ public class CtyunUtils {
* @param templateId 模板id * @param templateId 模板id
*/ */
public static String generateParamJsonStr(CtyunConfig ctyunConfig, String phone, String message, String templateId) { public static String generateParamJsonStr(CtyunConfig ctyunConfig, String phone, String message, String templateId) {
Map<String, String> paramMap = new HashMap<>(); Map<String, String> paramMap = new HashMap<>(5);
paramMap.put("action", ctyunConfig.getAction()); paramMap.put("action", ctyunConfig.getAction());
paramMap.put("phoneNumber", phone); paramMap.put("phoneNumber", phone);
paramMap.put("signName", ctyunConfig.getSignature()); paramMap.put("signName", ctyunConfig.getSignature());

View File

@ -1,11 +1,9 @@
package org.dromara.sms4j.emay.service; package org.dromara.sms4j.emay.service;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONObject; import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.dromara.sms4j.api.entity.SmsResponse; import org.dromara.sms4j.api.entity.SmsResponse;
import org.dromara.sms4j.comm.constant.Constant;
import org.dromara.sms4j.comm.delayedTime.DelayedTime; import org.dromara.sms4j.comm.delayedTime.DelayedTime;
import org.dromara.sms4j.comm.exception.SmsBlendException; import org.dromara.sms4j.comm.exception.SmsBlendException;
import org.dromara.sms4j.comm.utils.SmsUtil; import org.dromara.sms4j.comm.utils.SmsUtil;
@ -27,6 +25,7 @@ import java.util.concurrent.Executor;
public class EmaySmsImpl extends AbstractSmsBlend<EmayConfig> { public class EmaySmsImpl extends AbstractSmsBlend<EmayConfig> {
public static final String SUPPLIER = "emay"; public static final String SUPPLIER = "emay";
private int retry = 0;
public EmaySmsImpl(EmayConfig config, Executor pool, DelayedTime delayed) { public EmaySmsImpl(EmayConfig config, Executor pool, DelayedTime delayed) {
super(config, pool, delayed); super(config, pool, delayed);
@ -44,17 +43,29 @@ public class EmaySmsImpl extends AbstractSmsBlend<EmayConfig> {
@Override @Override
public SmsResponse sendMessage(String phone, String message) { public SmsResponse sendMessage(String phone, String message) {
String url = getConfig().getRequestUrl(); String url = getConfig().getRequestUrl();
Map<String, Object> params; Map<String, Object> params = EmayBuilder.buildRequestBody(getConfig().getAccessKeyId(), getConfig().getAccessKeySecret(), phone, message);
try { try {
params = EmayBuilder.buildRequestBody(getConfig().getAccessKeyId(), getConfig().getAccessKeySecret(), phone, message); Map<String, String> headers = new LinkedHashMap<>(1);
} catch (SmsBlendException e) { headers.put("Content-Type", Constant.FROM_URLENCODED);
SmsResponse smsResponse = new SmsResponse(); SmsResponse smsResponse = getResponse(http.postJson(url, headers, params));
smsResponse.setSuccess(false); if(smsResponse.isSuccess() || retry == getConfig().getMaxRetries()){
return smsResponse; retry = 0;
return smsResponse;
}
return requestRetry(phone, message);
}catch (SmsBlendException e){
return requestRetry(phone, message);
} }
return getSendResponse(params, url);
} }
private SmsResponse requestRetry(String phone, String message) {
http.safeSleep(getConfig().getRetryInterval());
retry++;
log.warn("短信第 {" + retry + "} 次重新发送");
return sendMessage(phone, message);
}
@Override @Override
public SmsResponse sendMessage(String phone, String templateId, LinkedHashMap<String, String> messages) { public SmsResponse sendMessage(String phone, String templateId, LinkedHashMap<String, String> messages) {
List<String> list = new ArrayList<>(); List<String> list = new ArrayList<>();
@ -84,16 +95,6 @@ public class EmaySmsImpl extends AbstractSmsBlend<EmayConfig> {
return sendMessage(SmsUtil.listToString(phones), EmayBuilder.listToString(list)); return sendMessage(SmsUtil.listToString(phones), EmayBuilder.listToString(list));
} }
private SmsResponse getSendResponse(Map<String, Object> body, String requestUrl) {
try(HttpResponse response = HttpRequest.post(requestUrl)
.header("Content-Type", "application/x-www-form-urlencoded")
.body(JSONUtil.toJsonStr(body))
.execute()){
JSONObject res = JSONUtil.parseObj(response.body());
return this.getResponse(res);
}
}
private SmsResponse getResponse(JSONObject resJson) { private SmsResponse getResponse(JSONObject resJson) {
SmsResponse smsResponse = new SmsResponse(); SmsResponse smsResponse = new SmsResponse();
smsResponse.setSuccess("success".equalsIgnoreCase(resJson.getStr("code"))); smsResponse.setSuccess("success".equalsIgnoreCase(resJson.getStr("code")));

View File

@ -1,13 +1,11 @@
package org.dromara.sms4j.huawei.service; package org.dromara.sms4j.huawei.service;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONObject; import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.dromara.sms4j.api.entity.SmsResponse; import org.dromara.sms4j.api.entity.SmsResponse;
import org.dromara.sms4j.comm.constant.Constant; import org.dromara.sms4j.comm.constant.Constant;
import org.dromara.sms4j.comm.delayedTime.DelayedTime; import org.dromara.sms4j.comm.delayedTime.DelayedTime;
import org.dromara.sms4j.comm.exception.SmsBlendException;
import org.dromara.sms4j.huawei.config.HuaweiConfig; import org.dromara.sms4j.huawei.config.HuaweiConfig;
import org.dromara.sms4j.huawei.utils.HuaweiBuilder; import org.dromara.sms4j.huawei.utils.HuaweiBuilder;
import org.dromara.sms4j.provider.service.AbstractSmsBlend; import org.dromara.sms4j.provider.service.AbstractSmsBlend;
@ -21,6 +19,7 @@ import static org.dromara.sms4j.huawei.utils.HuaweiBuilder.listToString;
public class HuaweiSmsImpl extends AbstractSmsBlend<HuaweiConfig> { public class HuaweiSmsImpl extends AbstractSmsBlend<HuaweiConfig> {
public static final String SUPPLIER = "huawei"; public static final String SUPPLIER = "huawei";
private int retry = 0;
public HuaweiSmsImpl(HuaweiConfig config, Executor pool, DelayedTime delayed) { public HuaweiSmsImpl(HuaweiConfig config, Executor pool, DelayedTime delayed) {
super(config, pool, delayed); super(config, pool, delayed);
@ -51,19 +50,29 @@ public class HuaweiSmsImpl extends AbstractSmsBlend<HuaweiConfig> {
} }
String mess = listToString(list); String mess = listToString(list);
String requestBody = HuaweiBuilder.buildRequestBody(getConfig().getSender(), phone, templateId, mess, getConfig().getStatusCallBack(), getConfig().getSignature()); String requestBody = HuaweiBuilder.buildRequestBody(getConfig().getSender(), phone, templateId, mess, getConfig().getStatusCallBack(), getConfig().getSignature());
Map<String, String> headers = new LinkedHashMap<>(); try {
headers.put("Authorization", Constant.HUAWEI_AUTH_HEADER_VALUE); Map<String, String> headers = new LinkedHashMap<>(3);
headers.put("X-WSSE", HuaweiBuilder.buildWsseHeader(getConfig().getAccessKeyId(), getConfig().getAccessKeySecret())); headers.put("Authorization", Constant.HUAWEI_AUTH_HEADER_VALUE);
headers.put("Content-Type", Constant.FROM_URLENCODED); headers.put("X-WSSE", HuaweiBuilder.buildWsseHeader(getConfig().getAccessKeyId(), getConfig().getAccessKeySecret()));
try(HttpResponse response = HttpRequest.post(url) headers.put("Content-Type", Constant.FROM_URLENCODED);
.addHeaders(headers) SmsResponse smsResponse = getResponse(http.postJson(url, headers, requestBody));
.body(requestBody) if(smsResponse.isSuccess() || retry == getConfig().getMaxRetries()){
.execute()){ retry = 0;
JSONObject body = JSONUtil.parseObj(response.body()); return smsResponse;
return this.getResponse(body); }
return requestRetry(phone, templateId, messages);
}catch (SmsBlendException e){
return requestRetry(phone, templateId, messages);
} }
} }
private SmsResponse requestRetry(String phone, String templateId, LinkedHashMap<String, String> messages) {
http.safeSleep(getConfig().getRetryInterval());
retry++;
log.warn("短信第 {" + retry + "} 次重新发送");
return sendMessage(phone, templateId, messages);
}
@Override @Override
public SmsResponse massTexting(List<String> phones, String message) { public SmsResponse massTexting(List<String> phones, String message) {
return sendMessage(listToString(phones), message); return sendMessage(listToString(phones), message);

View File

@ -2,13 +2,11 @@ package org.dromara.sms4j.netease.service;
import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.IdUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONArray; import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject; import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.dromara.sms4j.api.entity.SmsResponse; import org.dromara.sms4j.api.entity.SmsResponse;
import org.dromara.sms4j.comm.constant.Constant;
import org.dromara.sms4j.comm.delayedTime.DelayedTime; import org.dromara.sms4j.comm.delayedTime.DelayedTime;
import org.dromara.sms4j.comm.exception.SmsBlendException; import org.dromara.sms4j.comm.exception.SmsBlendException;
import org.dromara.sms4j.netease.config.NeteaseConfig; import org.dromara.sms4j.netease.config.NeteaseConfig;
@ -29,6 +27,7 @@ import java.util.concurrent.Executor;
public class NeteaseSmsImpl extends AbstractSmsBlend<NeteaseConfig> { public class NeteaseSmsImpl extends AbstractSmsBlend<NeteaseConfig> {
public static final String SUPPLIER = "netease"; public static final String SUPPLIER = "netease";
private int retry = 0;
public NeteaseSmsImpl(NeteaseConfig config, Executor pool, DelayedTime delayed) { public NeteaseSmsImpl(NeteaseConfig config, Executor pool, DelayedTime delayed) {
super(config, pool, delayed); super(config, pool, delayed);
@ -98,24 +97,37 @@ public class NeteaseSmsImpl extends AbstractSmsBlend<NeteaseConfig> {
String checkSum = NeteaseUtils.getCheckSum(getConfig().getAccessKeySecret(), nonce, curTime); String checkSum = NeteaseUtils.getCheckSum(getConfig().getAccessKeySecret(), nonce, curTime);
Map<String, Object> body = new LinkedHashMap<>(4); Map<String, Object> body = new LinkedHashMap<>(4);
body.put("templateid", templateId); body.put("templateid", templateId);
JSONArray jsonArray = JSONUtil.createArray(); JSONArray jsonArray = new JSONArray();
jsonArray.addAll(phones); jsonArray.addAll(phones);
body.put("mobiles", jsonArray.toString()); body.put("mobiles", jsonArray.toString());
body.put("params", message); body.put("params", message);
body.put("needUp", getConfig().getNeedUp()); body.put("needUp", getConfig().getNeedUp());
try(HttpResponse response = HttpRequest.post(requestUrl)
.header("Content-Type", "application/x-www-form-urlencoded") try {
.header("AppKey", getConfig().getAccessKeyId()) Map<String, String> headers = new LinkedHashMap<>(5);
.header("Nonce", nonce) headers.put("Content-Type", Constant.FROM_URLENCODED);
.header("CurTime", curTime) headers.put("AppKey", getConfig().getAccessKeyId());
.header("CheckSum", checkSum) headers.put("Nonce", nonce);
.body(JSONUtil.toJsonStr(body)) headers.put("CurTime", curTime);
.execute()){ headers.put("CheckSum", checkSum);
JSONObject res = JSONUtil.parseObj(response.body()); SmsResponse smsResponse = getResponse(http.postJson(requestUrl, headers, body));
return this.getResponse(res); if(smsResponse.isSuccess() || retry == getConfig().getMaxRetries()){
retry = 0;
return smsResponse;
}
return requestRetry(requestUrl, phones, message, templateId);
}catch (SmsBlendException e){
return requestRetry(requestUrl, phones, message, templateId);
} }
} }
private SmsResponse requestRetry(String requestUrl, List<String> phones, String message, String templateId) {
http.safeSleep(getConfig().getRetryInterval());
retry++;
log.warn("短信第 {" + retry + "} 次重新发送");
return getSmsResponse(requestUrl, phones, message, templateId);
}
private SmsResponse getResponse(JSONObject jsonObject) { private SmsResponse getResponse(JSONObject jsonObject) {
SmsResponse smsResponse = new SmsResponse(); SmsResponse smsResponse = new SmsResponse();
smsResponse.setSuccess(jsonObject.getInt("code") <= 200); smsResponse.setSuccess(jsonObject.getInt("code") <= 200);

View File

@ -1,10 +1,8 @@
package org.dromara.sms4j.provider.config; package org.dromara.sms4j.provider.config;
import lombok.Builder;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import org.dromara.sms4j.api.universal.SupplierConfig; import org.dromara.sms4j.api.universal.SupplierConfig;
import org.dromara.sms4j.comm.exception.SmsBlendException;
/** /**
* 短信配置属性基类 * 短信配置属性基类
@ -48,4 +46,27 @@ public abstract class BaseConfig implements SupplierConfig {
*/ */
private String configId; private String configId;
/**
* 重试间隔单位默认为5秒
*/
private int retryInterval = 5;
public void setRetryInterval(int retryInterval) {
if (retryInterval <= 0){
throw new SmsBlendException("重试间隔必须大于0秒");
}
this.retryInterval = retryInterval;
}
/**
* 重试次数默认为0次
*/
private int maxRetries = 0;
public void setMaxRetries(int maxRetries) {
if (maxRetries < 0){
throw new SmsBlendException("重试次数不能小于0次");
}
this.maxRetries = maxRetries;
}
} }

View File

@ -8,6 +8,7 @@ import org.dromara.sms4j.api.entity.SmsResponse;
import org.dromara.sms4j.api.universal.SupplierConfig; import org.dromara.sms4j.api.universal.SupplierConfig;
import org.dromara.sms4j.comm.delayedTime.DelayedTime; import org.dromara.sms4j.comm.delayedTime.DelayedTime;
import org.dromara.sms4j.comm.factory.BeanFactory; import org.dromara.sms4j.comm.factory.BeanFactory;
import org.dromara.sms4j.comm.utils.SmsHttpUtil;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
@ -26,6 +27,8 @@ public abstract class AbstractSmsBlend<C extends SupplierConfig> implements SmsB
protected final DelayedTime delayed; protected final DelayedTime delayed;
protected final SmsHttpUtil http = SmsHttpUtil.instance();
protected AbstractSmsBlend(C config, Executor pool, DelayedTime delayed) { protected AbstractSmsBlend(C config, Executor pool, DelayedTime delayed) {
this.configId = StrUtil.isEmpty(config.getConfigId()) ? getSupplier() : config.getConfigId(); this.configId = StrUtil.isEmpty(config.getConfigId()) ? getSupplier() : config.getConfigId();
this.config = config; this.config = config;

View File

@ -1,9 +1,6 @@
package org.dromara.sms4j.tencent.service; package org.dromara.sms4j.tencent.service;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONObject; import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.jdcloud.sdk.utils.StringUtils; import com.jdcloud.sdk.utils.StringUtils;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.dromara.sms4j.api.entity.SmsResponse; import org.dromara.sms4j.api.entity.SmsResponse;
@ -28,6 +25,7 @@ import java.util.concurrent.Executor;
public class TencentSmsImpl extends AbstractSmsBlend<TencentConfig> { public class TencentSmsImpl extends AbstractSmsBlend<TencentConfig> {
public static final String SUPPLIER = "alibaba"; public static final String SUPPLIER = "alibaba";
private int retry = 0;
public TencentSmsImpl(TencentConfig tencentSmsConfig, Executor pool, DelayedTime delayed) { public TencentSmsImpl(TencentConfig tencentSmsConfig, Executor pool, DelayedTime delayed) {
super(tencentSmsConfig, pool, delayed); super(tencentSmsConfig, pool, delayed);
@ -96,15 +94,26 @@ public class TencentSmsImpl extends AbstractSmsBlend<TencentConfig> {
Map<String, Object> requestBody = TencentUtils.generateRequestBody(phones, getConfig().getSdkAppId(), Map<String, Object> requestBody = TencentUtils.generateRequestBody(phones, getConfig().getSdkAppId(),
getConfig().getSignature(), templateId, messages); getConfig().getSignature(), templateId, messages);
String url = Constant.HTTPS_PREFIX + getConfig().getRequestUrl(); String url = Constant.HTTPS_PREFIX + getConfig().getRequestUrl();
try(HttpResponse response = HttpRequest.post(url)
.addHeaders(headsMap) try {
.body(JSONUtil.toJsonStr(requestBody)) SmsResponse smsResponse = getResponse(http.postJson(url, headsMap, requestBody));
.execute()){ if(smsResponse.isSuccess() || retry == getConfig().getMaxRetries()){
JSONObject body = JSONUtil.parseObj(response.body()); retry = 0;
return this.getResponse(body); return smsResponse;
}
return requestRetry(phones, messages, templateId);
}catch (SmsBlendException e){
return requestRetry(phones, messages, templateId);
} }
} }
private SmsResponse requestRetry(String[] phones, String[] messages, String templateId) {
http.safeSleep(getConfig().getRetryInterval());
retry++;
log.warn("短信第 {" + retry + "} 次重新发送");
return getSmsResponse(phones, messages, templateId);
}
private SmsResponse getResponse(JSONObject resJson) { private SmsResponse getResponse(JSONObject resJson) {
SmsResponse smsResponse = new SmsResponse(); SmsResponse smsResponse = new SmsResponse();
JSONObject response = resJson.getJSONObject("Response"); JSONObject response = resJson.getJSONObject("Response");

View File

@ -61,11 +61,11 @@ public class Uni {
* @return the Uni Client * @return the Uni Client
* @author :Wind * @author :Wind
*/ */
public static UniClient getClient() { public static UniClient getClient(int retryInterval, int maxRetries) {
if (Uni.client == null) { if (Uni.client == null) {
synchronized (Uni.class) { synchronized (Uni.class) {
if (Uni.client == null) { if (Uni.client == null) {
Uni.client = buildClient(); Uni.client = buildClient(retryInterval, maxRetries);
} }
} }
} }
@ -78,7 +78,7 @@ public class Uni {
} }
} }
private static UniClient buildClient() { private static UniClient buildClient(int retryInterval, int maxRetries) {
UniClient.Builder builder = new UniClient.Builder(Uni.accessKeyId); UniClient.Builder builder = new UniClient.Builder(Uni.accessKeyId);
if (Uni.accessKeySecret != null) { if (Uni.accessKeySecret != null) {
@ -87,7 +87,8 @@ public class Uni {
builder.endpoint(Uni.endpoint); builder.endpoint(Uni.endpoint);
builder.signingAlgorithm(Uni.signingAlgorithm); builder.signingAlgorithm(Uni.signingAlgorithm);
builder.setRetryInterval(retryInterval);
builder.setMaxRetries(maxRetries);
return builder.build(); return builder.build();
} }
} }

View File

@ -3,10 +3,10 @@ package org.dromara.sms4j.unisms.core;
import cn.hutool.core.codec.Base64; import cn.hutool.core.codec.Base64;
import cn.hutool.crypto.digest.HMac; import cn.hutool.crypto.digest.HMac;
import cn.hutool.crypto.digest.HmacAlgorithm; import cn.hutool.crypto.digest.HmacAlgorithm;
import cn.hutool.http.HttpRequest; import lombok.extern.slf4j.Slf4j;
import cn.hutool.http.HttpResponse; import org.dromara.sms4j.comm.constant.Constant;
import cn.hutool.json.JSONUtil;
import org.dromara.sms4j.comm.exception.SmsBlendException; import org.dromara.sms4j.comm.exception.SmsBlendException;
import org.dromara.sms4j.comm.utils.SmsHttpUtil;
import java.util.Comparator; import java.util.Comparator;
import java.util.Date; import java.util.Date;
@ -17,6 +17,7 @@ import java.util.Map.Entry;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.UUID; import java.util.UUID;
@Slf4j
public class UniClient { public class UniClient {
public static final String USER_AGENT = "uni-java-sdk" + "/" + Uni.VERSION; public static final String USER_AGENT = "uni-java-sdk" + "/" + Uni.VERSION;
@ -24,12 +25,18 @@ public class UniClient {
private final String accessKeySecret; private final String accessKeySecret;
private final String endpoint; private final String endpoint;
private final String signingAlgorithm; private final String signingAlgorithm;
private final int retryInterval;
private final int maxRetries;
private int retry = 0;
private final SmsHttpUtil http = SmsHttpUtil.instance();
protected UniClient(Builder b) { protected UniClient(Builder b) {
this.accessKeyId = b.accessKeyId; this.accessKeyId = b.accessKeyId;
this.accessKeySecret = b.accessKeySecret; this.accessKeySecret = b.accessKeySecret;
this.endpoint = b.endpoint; this.endpoint = b.endpoint;
this.signingAlgorithm = b.signingAlgorithm; this.signingAlgorithm = b.signingAlgorithm;
this.retryInterval = b.retryInterval;
this.maxRetries = b.maxRetries;
} }
private static String getSignature(final String message, final String secretKey) { private static String getSignature(final String message, final String secretKey) {
@ -81,23 +88,37 @@ public class UniClient {
public UniResponse request(final String action, final Map<String, Object> data) throws SmsBlendException { public UniResponse request(final String action, final Map<String, Object> data) throws SmsBlendException {
Map<String, String> headers = new HashMap<>(); Map<String, String> headers = new HashMap<>();
headers.put("User-Agent", USER_AGENT); headers.put("User-Agent", USER_AGENT);
headers.put("Content-Type", "application/json;charset=utf-8"); headers.put("Content-Type", Constant.APPLICATION_JSON_UTF8);
headers.put("Accept", "application/json"); headers.put("Accept", Constant.ACCEPT);
String url = this.endpoint + "?action=" + action + "&accessKeyId=" + this.accessKeyId; String url = this.endpoint + "?action=" + action + "&accessKeyId=" + this.accessKeyId;
try(HttpResponse response = HttpRequest.post(url)
.addHeaders(headers) try {
.body(JSONUtil.toJsonStr(data)) UniResponse smsResponse = new UniResponse(http.postJson(url, headers, data));
.execute()){ if("Success".equals(smsResponse.message) || retry == maxRetries){
return new UniResponse(JSONUtil.parseObj(response.body())); retry = 0;
return smsResponse;
}
return requestRetry(action, data);
}catch (SmsBlendException e){
return requestRetry(action, data);
} }
} }
private UniResponse requestRetry(String action, Map<String, Object> data) {
http.safeSleep(retryInterval);
retry++;
log.warn("短信第 {" + retry + "} 次重新发送");
return request(action, data);
}
public static class Builder { public static class Builder {
private String accessKeyId; private String accessKeyId;
private String accessKeySecret; private String accessKeySecret;
private String endpoint; private String endpoint;
private String signingAlgorithm; private String signingAlgorithm;
private int retryInterval;
private int maxRetries;
public Builder(final String accessKeyId) { public Builder(final String accessKeyId) {
this.accessKeyId = accessKeyId; this.accessKeyId = accessKeyId;
@ -123,6 +144,16 @@ public class UniClient {
return this; return this;
} }
public Builder setRetryInterval(int retryInterval) {
this.retryInterval = retryInterval;
return this;
}
public Builder setMaxRetries(int maxRetries) {
this.maxRetries = maxRetries;
return this;
}
public UniClient build() { public UniClient build() {
return new UniClient(this); return new UniClient(this);
} }

View File

@ -27,7 +27,7 @@ public class UniResponse {
this.raw = body; this.raw = body;
this.data = body; this.data = body;
} }
if (this.status != "400") { if (!"400".equals(this.status)) {
String code = response.getStr("code"); String code = response.getStr("code");
if (!"0".equals(code)) { if (!"0".equals(code)) {
this.message = response.getStr("message"); this.message = response.getStr("message");

View File

@ -42,14 +42,14 @@ public class UniSmsImpl extends AbstractSmsBlend<UniConfig> {
if ("".equals(getConfig().getTemplateId()) && "".equals(getConfig().getTemplateName())) { if ("".equals(getConfig().getTemplateId()) && "".equals(getConfig().getTemplateName())) {
throw new SmsBlendException("配置文件模板id和模板变量不能为空"); throw new SmsBlendException("配置文件模板id和模板变量不能为空");
} }
LinkedHashMap<String, String> map = new LinkedHashMap<>(); LinkedHashMap<String, String> map = new LinkedHashMap<>(1);
map.put(getConfig().getTemplateName(), message); map.put(getConfig().getTemplateName(), message);
return sendMessage(phone, getConfig().getTemplateId(), map); return sendMessage(phone, getConfig().getTemplateId(), map);
} }
@Override @Override
public SmsResponse sendMessage(String phone, String templateId, LinkedHashMap<String, String> messages) { public SmsResponse sendMessage(String phone, String templateId, LinkedHashMap<String, String> messages) {
Map<String, Object> data = new HashMap<>(); Map<String, Object> data = new LinkedHashMap<>(4);
data.put("to", Collections.singletonList(phone)); data.put("to", Collections.singletonList(phone));
data.put("signature", getConfig().getSignature()); data.put("signature", getConfig().getSignature());
data.put("templateId", templateId); data.put("templateId", templateId);
@ -62,7 +62,7 @@ public class UniSmsImpl extends AbstractSmsBlend<UniConfig> {
if ("".equals(getConfig().getTemplateId()) && "".equals(getConfig().getTemplateName())) { if ("".equals(getConfig().getTemplateId()) && "".equals(getConfig().getTemplateName())) {
throw new SmsBlendException("配置文件模板id和模板变量不能为空"); throw new SmsBlendException("配置文件模板id和模板变量不能为空");
} }
LinkedHashMap<String, String> map = new LinkedHashMap<>(); LinkedHashMap<String, String> map = new LinkedHashMap<>(1);
map.put(getConfig().getTemplateName(), message); map.put(getConfig().getTemplateName(), message);
return massTexting(phones, getConfig().getTemplateId(), map); return massTexting(phones, getConfig().getTemplateId(), map);
} }
@ -72,7 +72,7 @@ public class UniSmsImpl extends AbstractSmsBlend<UniConfig> {
if (phones.size() > 1000) { if (phones.size() > 1000) {
throw new SmsBlendException("单次发送超过最大发送上限建议每次群发短信人数低于1000"); throw new SmsBlendException("单次发送超过最大发送上限建议每次群发短信人数低于1000");
} }
Map<String, Object> data = new HashMap<>(); Map<String, Object> data = new LinkedHashMap<>(4);
data.put("to", phones); data.put("to", phones);
data.put("signature", getConfig().getSignature()); data.put("signature", getConfig().getSignature());
data.put("templateId", templateId); data.put("templateId", templateId);
@ -83,7 +83,7 @@ public class UniSmsImpl extends AbstractSmsBlend<UniConfig> {
private SmsResponse getSmsResponse(Map<String, Object> data) { private SmsResponse getSmsResponse(Map<String, Object> data) {
SmsResponse smsResponse = new SmsResponse(); SmsResponse smsResponse = new SmsResponse();
try { try {
UniResponse send = Uni.getClient().request("sms.message.send", data); UniResponse send = Uni.getClient(getConfig().getRetryInterval(), getConfig().getMaxRetries()).request("sms.message.send", data);
smsResponse.setSuccess("Success".equals(send.message)); smsResponse.setSuccess("Success".equals(send.message));
smsResponse.setData(send); smsResponse.setData(send);
smsResponse.setConfigId(getConfigId()); smsResponse.setConfigId(getConfigId());

View File

@ -1,9 +1,7 @@
package org.dromara.sms4j.yunpian.service; package org.dromara.sms4j.yunpian.service;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONObject; import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil; import lombok.extern.slf4j.Slf4j;
import org.dromara.sms4j.api.entity.SmsResponse; import org.dromara.sms4j.api.entity.SmsResponse;
import org.dromara.sms4j.comm.constant.Constant; import org.dromara.sms4j.comm.constant.Constant;
import org.dromara.sms4j.comm.delayedTime.DelayedTime; import org.dromara.sms4j.comm.delayedTime.DelayedTime;
@ -21,9 +19,11 @@ import java.util.concurrent.Executor;
/** /**
* @author wind * @author wind
*/ */
@Slf4j
public class YunPianSmsImpl extends AbstractSmsBlend<YunpianConfig> { public class YunPianSmsImpl extends AbstractSmsBlend<YunpianConfig> {
public static final String SUPPLIER = "yunpian"; public static final String SUPPLIER = "yunpian";
private int retry = 0;
public YunPianSmsImpl(YunpianConfig config, Executor pool, DelayedTime delayed) { public YunPianSmsImpl(YunpianConfig config, Executor pool, DelayedTime delayed) {
super(config, pool, delayed); super(config, pool, delayed);
@ -52,14 +52,50 @@ public class YunPianSmsImpl extends AbstractSmsBlend<YunpianConfig> {
@Override @Override
public SmsResponse sendMessage(String phone, String message) { public SmsResponse sendMessage(String phone, String message) {
Map<String, String> body = setBody(phone, message, null, getConfig().getTemplateId()); Map<String, Object> body = setBody(phone, message, null, getConfig().getTemplateId());
return getSendResponse(body); Map<String, String> headers = getHeaders();
try {
SmsResponse smsResponse = getResponse(http.postJson(Constant.YUNPIAN_URL + "/sms/tpl_single_send.json", headers, body));
if(smsResponse.isSuccess() || retry == getConfig().getMaxRetries()){
retry = 0;
return smsResponse;
}
return requestRetry(phone, message);
}catch (SmsBlendException e){
return requestRetry(phone, message);
}
}
private SmsResponse requestRetry(String phone, String message) {
http.safeSleep(getConfig().getRetryInterval());
retry++;
log.warn("短信第 {" + retry + "} 次重新发送");
return sendMessage(phone, message);
} }
@Override @Override
public SmsResponse sendMessage(String phone, String templateId, LinkedHashMap<String, String> messages) { public SmsResponse sendMessage(String phone, String templateId, LinkedHashMap<String, String> messages) {
Map<String, String> body = setBody(phone, "", messages, templateId); Map<String, Object> body = setBody(phone, "", messages, templateId);
return getSendResponse(body); Map<String, String> headers = getHeaders();
try {
SmsResponse smsResponse = getResponse(http.postJson(Constant.YUNPIAN_URL + "/sms/tpl_single_send.json", headers, body));
if(smsResponse.isSuccess() || retry == getConfig().getMaxRetries()){
retry = 0;
return smsResponse;
}
return requestRetry(phone, templateId, messages);
}catch (SmsBlendException e){
return requestRetry(phone, templateId, messages);
}
}
private SmsResponse requestRetry(String phone, String templateId, LinkedHashMap<String, String> messages) {
http.safeSleep(getConfig().getRetryInterval());
retry++;
log.warn("短信第 {" + retry + "} 次重新发送");
return sendMessage(phone, templateId, messages);
} }
@Override @Override
@ -91,14 +127,14 @@ public class YunPianSmsImpl extends AbstractSmsBlend<YunpianConfig> {
return str.toString(); return str.toString();
} }
private Map<String, String> setBody(String phone, String mes, LinkedHashMap<String, String> messages, String tplId) { private Map<String, Object> setBody(String phone, String mes, LinkedHashMap<String, String> messages, String tplId) {
LinkedHashMap<String, String> message = new LinkedHashMap<>(); LinkedHashMap<String, String> message = new LinkedHashMap<>();
if (mes.isEmpty()) { if (mes.isEmpty()) {
message = messages; message = messages;
} else { } else {
message.put(getConfig().getTemplateName(), mes); message.put(getConfig().getTemplateName(), mes);
} }
Map<String, String> body = new HashMap<>(); Map<String, Object> body = new HashMap<>();
body.put("apikey", getConfig().getAccessKeyId()); body.put("apikey", getConfig().getAccessKeyId());
body.put("mobile", phone); body.put("mobile", phone);
body.put("tpl_id", tplId); body.put("tpl_id", tplId);
@ -110,19 +146,8 @@ public class YunPianSmsImpl extends AbstractSmsBlend<YunpianConfig> {
private Map<String, String> getHeaders() { private Map<String, String> getHeaders() {
Map<String, String> headers = new HashMap<>(); Map<String, String> headers = new HashMap<>();
headers.put("Accept", "application/json;charset=utf-8"); headers.put("Accept", Constant.APPLICATION_JSON_UTF8);
headers.put("Content-Type", Constant.FROM_URLENCODED); headers.put("Content-Type", Constant.FROM_URLENCODED);
return headers; return headers;
} }
private SmsResponse getSendResponse(Map<String, String> body) {
Map<String, String> headers = getHeaders();
try(HttpResponse response = HttpRequest.post(Constant.YUNPIAN_URL + "/sms/tpl_single_send.json")
.addHeaders(headers)
.body(JSONUtil.toJsonStr(body))
.execute()){
JSONObject res = JSONUtil.parseObj(response.body());
return getResponse(res);
}
}
} }

View File

@ -5,11 +5,8 @@ import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.text.StrPool; import cn.hutool.core.text.StrPool;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil; import cn.hutool.crypto.SecureUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONArray; import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject; import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.dromara.sms4j.api.entity.SmsResponse; import org.dromara.sms4j.api.entity.SmsResponse;
import org.dromara.sms4j.comm.constant.Constant; import org.dromara.sms4j.comm.constant.Constant;
@ -33,6 +30,7 @@ import java.util.concurrent.Executor;
public class ZhutongSmsImpl extends AbstractSmsBlend<ZhutongConfig> { public class ZhutongSmsImpl extends AbstractSmsBlend<ZhutongConfig> {
public static final String SUPPLIER = "zhutong"; public static final String SUPPLIER = "zhutong";
private int retry = 0;
/** /**
* ZhutongSmsImpl * ZhutongSmsImpl
@ -63,7 +61,7 @@ public class ZhutongSmsImpl extends AbstractSmsBlend<ZhutongConfig> {
return getSmsResponse(phone, message); return getSmsResponse(phone, message);
} }
LinkedHashMap<String, String> map = new LinkedHashMap<>(); LinkedHashMap<String, String> map = new LinkedHashMap<>(1);
map.put(config.getTemplateName(), message); map.put(config.getTemplateName(), message);
return sendMessage(phone, config.getTemplateId(), map); return sendMessage(phone, config.getTemplateId(), map);
} }
@ -81,7 +79,7 @@ public class ZhutongSmsImpl extends AbstractSmsBlend<ZhutongConfig> {
return getSmsResponse(phones, message); return getSmsResponse(phones, message);
} }
LinkedHashMap<String, String> map = new LinkedHashMap<>(); LinkedHashMap<String, String> map = new LinkedHashMap<>(1);
map.put(config.getTemplateName(), message); map.put(config.getTemplateName(), message);
return massTexting(phones, config.getTemplateId(), map); return massTexting(phones, config.getTemplateId(), map);
} }
@ -120,7 +118,7 @@ public class ZhutongSmsImpl extends AbstractSmsBlend<ZhutongConfig> {
String url = requestUrl + "v2/sendSms"; String url = requestUrl + "v2/sendSms";
long tKey = System.currentTimeMillis() / 1000; long tKey = System.currentTimeMillis() / 1000;
Map<String, String> json = new HashMap<>(5); Map<String, Object> json = new HashMap<>(5);
//账号 //账号
json.put("username", username); json.put("username", username);
//密码 //密码
@ -132,15 +130,27 @@ public class ZhutongSmsImpl extends AbstractSmsBlend<ZhutongConfig> {
//内容 //内容
json.put("content", content); json.put("content", content);
try(HttpResponse response = HttpRequest.post(url) try {
.header("Content-Type", Constant.APPLICATION_JSON_UTF8) Map<String, String> headers = new LinkedHashMap<>(1);
.body(JSONUtil.toJsonStr(json)) headers.put("Content-Type", Constant.APPLICATION_JSON_UTF8);
.execute()){ SmsResponse smsResponse = getResponse(http.postJson(requestUrl, headers, json));
JSONObject body = JSONUtil.parseObj(response.body()); if(smsResponse.isSuccess() || retry == getConfig().getMaxRetries()){
return this.getResponse(body); retry = 0;
return smsResponse;
}
return requestRetry(phones, content);
}catch (SmsBlendException e){
return requestRetry(phones, content);
} }
} }
private SmsResponse requestRetry(List<String> phones, String content) {
http.safeSleep(getConfig().getRetryInterval());
retry++;
log.warn("短信第 {" + retry + "} 次重新发送");
return getSmsResponse(phones, content);
}
protected SmsResponse getSmsResponse(String mobile, String content) { protected SmsResponse getSmsResponse(String mobile, String content) {
return getSmsResponse(ListUtil.of(mobile), content); return getSmsResponse(ListUtil.of(mobile), content);
} }
@ -205,15 +215,27 @@ public class ZhutongSmsImpl extends AbstractSmsBlend<ZhutongConfig> {
} }
requestJson.set("records", records); requestJson.set("records", records);
try(HttpResponse response = HttpRequest.post(url) try {
.header("Content-Type", Constant.APPLICATION_JSON_UTF8) Map<String, String> headers = new LinkedHashMap<>(1);
.body(requestJson.toString()) headers.put("Content-Type", Constant.APPLICATION_JSON_UTF8);
.execute()){ SmsResponse smsResponse = getResponse(http.postJson(requestUrl, headers, requestJson.toString()));
JSONObject body = JSONUtil.parseObj(response.body()); if(smsResponse.isSuccess() || retry == getConfig().getMaxRetries()){
return this.getResponse(body); retry = 0;
return smsResponse;
}
return requestRetry(templateId, phones, messages);
}catch (SmsBlendException e){
return requestRetry(templateId, phones, messages);
} }
} }
private SmsResponse requestRetry(String templateId, List<String> phones, LinkedHashMap<String, String> messages) {
http.safeSleep(getConfig().getRetryInterval());
retry++;
log.warn("短信第 {" + retry + "} 次重新发送");
return getSmsResponseTemplate(templateId, phones, messages);
}
protected SmsResponse getSmsResponseTemplate(String templateId, String mobile, LinkedHashMap<String, String> content) { protected SmsResponse getSmsResponseTemplate(String templateId, String mobile, LinkedHashMap<String, String> content) {
return getSmsResponseTemplate(templateId, ListUtil.of(mobile), content); return getSmsResponseTemplate(templateId, ListUtil.of(mobile), content);
} }