# Conflicts:
#	pom.xml
#	sms4j-comm/src/main/java/org/dromara/sms4j/comm/constant/Constant.java
This commit is contained in:
wind 2025-03-07 19:55:56 +08:00
commit bfdc75d538
68 changed files with 940 additions and 312 deletions

View File

@ -53,12 +53,12 @@
</scm>
<properties>
<revision>3.3.3</revision>
<revision>3.3.4</revision>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring.boot.version>2.7.18</spring.boot.version>
<solon.version>2.6.5</solon.version>
<solon.version>3.0.1</solon.version>
<redisson.version>3.17.0</redisson.version>
<jdcloud.version>1.3.3</jdcloud.version>
<hutool.version>5.8.28</hutool.version>

View File

@ -0,0 +1,27 @@
package org.dromara.sms4j.api.universal;
import lombok.Data;
import java.io.Serializable;
/**
* 短信代理配置类
*/
@Data
public class ProxyConfig implements Serializable {
/**
* 是否启用代理 默认不启用
*/
private Boolean enable = false;
/**
* 代理服务器地址
*/
private String host;
/**
* 代理服务器端口
*/
private Integer port;
}

View File

@ -22,4 +22,9 @@ public interface SupplierConfig {
*/
String getSupplier();
/**
* 获取代理配置
*
*/
ProxyConfig getProxy();
}

View File

@ -11,7 +11,7 @@ public abstract class Constant {
/**
* 项目版本号
*/
public static final String VERSION = "V 3.3.3";
public static final String VERSION = "V 3.3.4";
/**
* 用于格式化鉴权头域,"Authorization"参数赋值

View File

@ -93,4 +93,8 @@ public abstract class SupplierConstant {
* danmi sms
*/
public static final String DAN_MI = "danmi";
/**
* 联通一信通 sms
*/
public static final String YIXINTONG = "yixintong";
}

View File

@ -1,9 +1,11 @@
package org.dromara.sms4j.comm.utils;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.Method;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import org.dromara.sms4j.comm.exception.SmsBlendException;
@ -12,15 +14,108 @@ import java.util.Map;
public class SmsHttpUtils {
/**
* 是否启用代理 默认不启用
*/
private final Boolean enable;
/**
* 代理服务器地址
*/
private final String host;
/**
* 代理服务器端口
*/
private final Integer port;
// 无代理单例饿汉式加载
private static final SmsHttpUtils NON_PROXY_INSTANCE = new SmsHttpUtils();
// 代理单例双重校验锁延迟加载
private static volatile SmsHttpUtils PROXY_INSTANCE;
// 无代理构造方法
private SmsHttpUtils() {
this.enable = false;
this.host = null;
this.port = null;
}
private static class SmsHttpHolder {
private static final SmsHttpUtils INSTANCE = new SmsHttpUtils();
// 代理构造方法
private SmsHttpUtils(String host, Integer port) {
this.enable = true;
this.host = host;
this.port = port;
}
/**
* 获取无代理单例
*/
public static SmsHttpUtils instance() {
return SmsHttpHolder.INSTANCE;
return NON_PROXY_INSTANCE;
}
/**
* 获取代理单例线程安全 + 参数校验
*/
public static SmsHttpUtils instance(String host, Integer port) {
if (PROXY_INSTANCE == null) {
synchronized (SmsHttpUtils.class) {
if (PROXY_INSTANCE == null) {
validateProxyParams(host, port);
PROXY_INSTANCE = new SmsHttpUtils(host, port);
}
}
} else {
// 二次调用时校验参数一致性
if (!PROXY_INSTANCE.host.equals(host) || !PROXY_INSTANCE.port.equals(port)) {
throw new IllegalStateException("Proxy parameters cannot be modified after initialization");
}
}
return PROXY_INSTANCE;
}
// 代理参数校验
private static void validateProxyParams(String host, Integer port) {
if (StrUtil.isBlank(host) || port == null || port <= 0) {
throw new IllegalArgumentException("Invalid proxy host or port");
}
}
/**
* 配置请求 是否走代理
* @param url 请求地址
* @return HttpRequest
*/
private HttpRequest request(String url){
HttpRequest request = HttpRequest.of(url);
if (enable){
request.setHttpProxy(host, port);
}
return request;
}
/**
* 构造post请求
* @param url 请求地址
* @return HttpRequest
*/
private HttpRequest post(String url){
HttpRequest post = request(url);
post.setMethod(Method.POST);
return post;
}
/**
* 构造get请求
* @param url 请求地址
* @return HttpRequest
*/
private HttpRequest get(String url){
HttpRequest get = request(url);
get.setMethod(Method.GET);
return get;
}
/**
@ -32,7 +127,7 @@ public class SmsHttpUtils {
* @return 返回体
*/
public JSONObject postJson(String url, Map<String, String> headers, String body) {
try (HttpResponse response = HttpRequest.post(url)
try (HttpResponse response = post(url)
.addHeaders(headers)
.body(body)
.execute()) {
@ -63,7 +158,7 @@ public class SmsHttpUtils {
* @return 返回体
*/
public JSONObject postFrom(String url, Map<String, String> headers, Map<String, Object> body) {
try (HttpResponse response = HttpRequest.post(url)
try (HttpResponse response = post(url)
.addHeaders(headers)
.form(body)
.execute()) {
@ -84,7 +179,7 @@ public class SmsHttpUtils {
* @return 返回体
*/
public JSONObject postBasicFrom(String url, Map<String, String> headers, String username, String password, Map<String, Object> body) {
try (HttpResponse response = HttpRequest.post(url)
try (HttpResponse response = post(url)
.addHeaders(headers)
.basicAuth(username, password)
.form(body)
@ -105,7 +200,7 @@ public class SmsHttpUtils {
*/
public JSONObject postUrl(String url, Map<String, String> headers, Map<String, Object> params) {
String urlWithParams = url + "?" + URLUtil.buildQuery(params, null);
try (HttpResponse response = HttpRequest.post(urlWithParams)
try (HttpResponse response = post(urlWithParams)
.addHeaders(headers)
.execute()) {
return JSONUtil.parseObj(response.body());
@ -121,7 +216,7 @@ public class SmsHttpUtils {
* @return 返回体
*/
public JSONObject getBasic(String url, String username, String password) {
try (HttpResponse response = HttpRequest.get(url)
try (HttpResponse response = get(url)
.basicAuth(username, password)
.execute()) {
return JSONUtil.parseObj(response.body());
@ -137,7 +232,7 @@ public class SmsHttpUtils {
* @return 返回体
*/
public JSONObject getUrl(String url) {
try (HttpResponse response = HttpRequest.get(url)
try (HttpResponse response = get(url)
.execute()) {
return JSONUtil.parseObj(response.body());
} catch (Exception e) {

View File

@ -10,7 +10,12 @@ import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import java.util.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Predicate;

View File

@ -10,6 +10,8 @@ import org.dromara.sms4j.comm.utils.SmsUtils;
import org.dromara.sms4j.provider.config.SmsConfig;
import org.dromara.sms4j.provider.factory.BeanFactory;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
@ -26,7 +28,6 @@ import java.util.Objects;
@Slf4j
public class RestrictedProcessor implements CoreMethodProcessor, SmsDaoAware {
static Long minTimer = 60 * 1000L;
static Long accTimer = 24 * 60 * 60 * 1000L;
private static final String REDIS_KEY = "sms:restricted:";
/**
@ -59,6 +60,13 @@ public class RestrictedProcessor implements CoreMethodProcessor, SmsDaoAware {
doRestricted(phones);
}
private long calculateExpiryTime() {
LocalDateTime now = LocalDateTime.now();
LocalDateTime tomorrowMidnight = now.toLocalDate().plusDays(1).atStartOfDay();
Duration duration = Duration.between(now, tomorrowMidnight);
return duration.getSeconds();
}
public void doRestricted(List<String> phones) {
if (Objects.isNull(smsDao)) {
throw new SmsBlendException("The smsDao tool could not be found");
@ -86,12 +94,12 @@ public class RestrictedProcessor implements CoreMethodProcessor, SmsDaoAware {
if (dailyMaxLimitExists) {
Integer dailyCount = (Integer) smsDao.get(accountMaxKey);
if (SmsUtils.isEmpty(dailyCount)) {
smsDao.set(accountMaxKey, 1, accTimer / 1000);
smsDao.set(accountMaxKey, 1, calculateExpiryTime());
} else if (dailyCount >= accountMax) {
log.info("The phone: {},number of short messages reached the maximum today", phone);
throw new SmsBlendException("The phone: {},number of short messages reached the maximum today", phone);
} else {
smsDao.set(accountMaxKey, dailyCount + 1, accTimer / 1000);
smsDao.set(accountMaxKey, dailyCount + 1, calculateExpiryTime());
}
}
// 是否配置了每分钟最大限制
@ -105,7 +113,7 @@ public class RestrictedProcessor implements CoreMethodProcessor, SmsDaoAware {
if (dailyMaxLimitExists) {
Integer dailyCount = (Integer) smsDao.get(accountMaxKey);
if (dailyCount > 1) {
smsDao.set(accountMaxKey, dailyCount - 1, accTimer / 1000);
smsDao.set(accountMaxKey, dailyCount - 1, calculateExpiryTime());
} else {
smsDao.remove(accountMaxKey);
}

View File

@ -0,0 +1,6 @@
/**
* <p> 邮件插件api模块
* @author :Wind
* 2024/10/23 10:58
**/
package org.dromara.email.jakarta.api;

View File

@ -3,6 +3,7 @@ package org.dromara.email.jakarta.comm.entity;
import lombok.Getter;
import org.dromara.email.jakarta.comm.utils.ReflectUtil;
import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
@ -27,6 +28,12 @@ public class MailMessage {
/** html模板文件的输入流可来自任意可读取位置*/
private InputStream htmlInputStream;
/** html内容可以存在模板变量*/
private String htmlContent;
/** html 模板文件的File对象*/
private File htmlFile;
/** html 模板参数*/
private Map<String,String> htmlValues;
@ -141,6 +148,18 @@ public class MailMessage {
return this;
}
/** html模板文件的File对象*/
public MailsBuilder html(File htmlFile){
mailMessage.htmlFile = htmlFile;
return this;
}
/** html内容直接输入*/
public MailsBuilder htmlContent(String htmlContent){
mailMessage.htmlContent = htmlContent;
return this;
}
/** html 模板参数*/
public MailsBuilder htmlValues(String key, String value){
if (mailMessage.htmlValues == null){

View File

@ -0,0 +1,6 @@
/**
* <p> 邮件插件通用模块
* @author :Wind
* 2024/10/23 10:58
**/
package org.dromara.email.jakarta.comm;

View File

@ -32,8 +32,8 @@ public final class HtmlUtil {
* @param name 模板文件名
* @author :Wind
*/
public static List<String> readHtml(String name) throws MailException {
try (InputStream is = HtmlUtil.class.getResourceAsStream("/template/" + name)) {
public static List<String> readHtml(String name,Class<?> clazz) throws MailException {
try (InputStream is = clazz.getResourceAsStream("/template/" + name)) {
return readHtml(is);
} catch (IOException e) {
throw new MailException(e);
@ -75,6 +75,12 @@ public final class HtmlUtil {
}
} catch (IOException e) {
throw new MailException(e);
} finally {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return data;
}

View File

@ -26,6 +26,7 @@ import org.dromara.email.jakarta.comm.utils.ZipUtils;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@ -51,7 +52,13 @@ public class MailService implements MailClient {
html = HtmlUtil.readHtml(mailMessage.getHtmlInputStream());
}
if (StrUtil.isNotBlank(mailMessage.getHtmlPath())) {
html = HtmlUtil.readHtml(mailMessage.getHtmlPath());
html = HtmlUtil.readHtml(mailMessage.getHtmlPath(), MailService.class);
}
if (mailMessage.getHtmlFile() != null) {
html = HtmlUtil.readHtml(mailMessage.getHtmlFile());
}
if (StrUtil.isNotBlank(mailMessage.getHtmlContent())) {
html = Arrays.asList(mailMessage.getHtmlContent().split("\n"));
}
send(mailMessage.getMailAddress(),
mailMessage.getTitle(),
@ -186,11 +193,17 @@ public class MailService implements MailClient {
message.setSubject(title);
Multipart multipart = new MimeMultipart("alternative");
if (CollUtil.isNotEmpty(html) && MapUtil.isNotEmpty(parameter)) {
if (CollUtil.isNotEmpty(html)) {
String htmlData;
List<String> strings;
if (MapUtil.isNotEmpty(parameter)) {
//读取模板并进行变量替换
List<String> strings = HtmlUtil.replacePlaceholder(html, parameter);
strings = HtmlUtil.replacePlaceholder(html, parameter);
//拼合HTML数据
String htmlData = HtmlUtil.pieceHtml(strings);
htmlData = HtmlUtil.pieceHtml(strings);
}else {
htmlData = HtmlUtil.pieceHtml(html);
}
MimeBodyPart htmlPart = new MimeBodyPart();
htmlPart.setContent(htmlData, "text/html;charset=UTF-8");
multipart.addBodyPart(htmlPart);

View File

@ -18,6 +18,7 @@ import org.dromara.sms4j.api.universal.SupplierConfig;
import org.dromara.sms4j.api.verify.PhoneVerify;
import org.dromara.sms4j.baidu.config.BaiduFactory;
import org.dromara.sms4j.budingyun.config.BudingV2Factory;
import org.dromara.sms4j.chuanglan.config.ChuangLanFactory;
import org.dromara.sms4j.cloopen.config.CloopenFactory;
import org.dromara.sms4j.comm.constant.Constant;
import org.dromara.sms4j.comm.exception.SmsBlendException;
@ -36,7 +37,6 @@ import org.dromara.sms4j.emay.config.EmayFactory;
import org.dromara.sms4j.huawei.config.HuaweiFactory;
import org.dromara.sms4j.javase.util.YamlUtils;
import org.dromara.sms4j.jdcloud.config.JdCloudFactory;
import org.dromara.sms4j.chuanglan.config.ChuangLanFactory;
import org.dromara.sms4j.jg.config.JgFactory;
import org.dromara.sms4j.lianlu.config.LianLuFactory;
import org.dromara.sms4j.luosimao.config.LuoSiMaoFactory;
@ -50,6 +50,7 @@ import org.dromara.sms4j.qiniu.config.QiNiuFactory;
import org.dromara.sms4j.submail.config.SubMailFactory;
import org.dromara.sms4j.tencent.config.TencentFactory;
import org.dromara.sms4j.unisms.config.UniFactory;
import org.dromara.sms4j.yixintong.config.YiXintongFactory;
import org.dromara.sms4j.yunpian.config.YunPianFactory;
import org.dromara.sms4j.zhutong.config.ZhutongFactory;
@ -144,9 +145,7 @@ public class SEInitializer {
//如果手机号校验器存在实现则注册手机号校验器
ServiceLoader<PhoneVerify> loader = ServiceLoader.load(PhoneVerify.class);
if (loader.iterator().hasNext()) {
loader.forEach(f -> {
SmsProxyFactory.addPreProcessor(new CoreMethodParamValidateProcessor(f));
});
loader.forEach(f -> SmsProxyFactory.addPreProcessor(new CoreMethodParamValidateProcessor(f)));
} else {
SmsProxyFactory.addPreProcessor(new CoreMethodParamValidateProcessor(null));
}
@ -217,9 +216,7 @@ public class SEInitializer {
//如果手机号校验器存在实现则注册手机号校验器
ServiceLoader<PhoneVerify> loader = ServiceLoader.load(PhoneVerify.class);
if (loader.iterator().hasNext()) {
loader.forEach(f -> {
SmsProxyFactory.addPreProcessor(new CoreMethodParamValidateProcessor(f));
});
loader.forEach(f -> SmsProxyFactory.addPreProcessor(new CoreMethodParamValidateProcessor(f)));
} else {
SmsProxyFactory.addPreProcessor(new CoreMethodParamValidateProcessor(null));
}
@ -266,6 +263,7 @@ public class SEInitializer {
ProviderFactoryHolder.registerFactory(LuoSiMaoFactory.instance());
ProviderFactoryHolder.registerFactory(SubMailFactory.instance());
ProviderFactoryHolder.registerFactory(DanMiFactory.instance());
ProviderFactoryHolder.registerFactory(YiXintongFactory.instance());
if (SmsUtils.isClassExists("com.jdcloud.sdk.auth.CredentialsProvider")) {
ProviderFactoryHolder.registerFactory(JdCloudFactory.instance());
}

View File

@ -3,6 +3,7 @@ package org.dromara.oa.core.config;
import org.dromara.oa.api.OaSender;
import org.dromara.oa.core.provider.config.OaConfig;
import org.dromara.oa.core.provider.factory.OaBaseProviderFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
@ -31,7 +32,7 @@ public class OaSupplierConfig {
protected OaBlendsInitializer smsOasInitializer(
List<OaBaseProviderFactory<? extends OaSender, ? extends org.dromara.oa.comm.config.OaSupplierConfig>> factoryList,
OaConfig oaConfig,
Map<String, Map<String, Object>> oas) {
@Qualifier("oas") Map<String, Map<String, Object>> oas) {
return new OaBlendsInitializer(factoryList,oaConfig,oas);
}
}

View File

@ -2,6 +2,7 @@ package org.dromara.oa.core.provider.service;
import cn.hutool.core.util.StrUtil;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.dromara.oa.api.OaCallBack;
import org.dromara.oa.api.OaSender;
import org.dromara.oa.comm.config.OaSupplierConfig;
@ -19,6 +20,7 @@ import java.util.concurrent.PriorityBlockingQueue;
* @author dongfeng
* 2023-10-22 21:03
*/
@Slf4j
public abstract class AbstractOaBlend<C extends OaSupplierConfig> implements OaSender {
@Getter
@ -57,12 +59,16 @@ public abstract class AbstractOaBlend<C extends OaSupplierConfig> implements OaS
pool.execute(() -> {
Thread.currentThread().setName("oa-priorityQueueMap-thread");
while (!Thread.currentThread().isInterrupted()) {
Request request = priorityQueueMap.poll();
if (!Objects.isNull(request)) {
try{
Request request = priorityQueueMap.take() ;
pool.execute(() -> {
System.out.println("优先级为"+request.getPriority()+"已发送");
log.info("优先级为"+request.getPriority()+"已发送");
sender(request, request.getMessageType());
});
}catch (InterruptedException e){
log.info("[Dispatcher]-priorityQueueMap-task-dispatcher has been interrupt to close.");
Thread.currentThread().interrupt();
break;
}
}
});

View File

@ -116,7 +116,7 @@ public class AlibabaSmsImpl extends AbstractSmsBlend<AlibabaConfig> {
} catch (SmsBlendException e) {
smsResponse = errorResp(e.message);
}
if (smsResponse.isSuccess() || retry == getConfig().getMaxRetries()) {
if (smsResponse.isSuccess() || retry >= getConfig().getMaxRetries()) {
retry = 0;
return smsResponse;
}

View File

@ -2,8 +2,8 @@ package org.dromara.sms4j.baidu.config;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.dromara.sms4j.comm.constant.SupplierConstant;
import org.dromara.sms4j.baidu.service.BaiduSmsImpl;
import org.dromara.sms4j.comm.constant.SupplierConstant;
import org.dromara.sms4j.provider.factory.AbstractProviderFactory;
/**

View File

@ -6,12 +6,12 @@ import cn.hutool.json.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.dromara.sms4j.api.entity.SmsResponse;
import org.dromara.sms4j.api.utils.SmsRespUtils;
import org.dromara.sms4j.baidu.config.BaiduConfig;
import org.dromara.sms4j.baidu.utils.BaiduUtils;
import org.dromara.sms4j.comm.constant.SupplierConstant;
import org.dromara.sms4j.comm.delayedTime.DelayedTime;
import org.dromara.sms4j.comm.exception.SmsBlendException;
import org.dromara.sms4j.comm.utils.SmsUtils;
import org.dromara.sms4j.baidu.config.BaiduConfig;
import org.dromara.sms4j.baidu.utils.BaiduUtils;
import org.dromara.sms4j.provider.service.AbstractSmsBlend;
import java.util.LinkedHashMap;

View File

@ -12,7 +12,10 @@ import org.dromara.sms4j.comm.constant.Constant;
import org.dromara.sms4j.comm.utils.SmsDateUtils;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@ -98,6 +101,7 @@ public class BaiduUtils {
Map<String, String> headers = new HashMap<>(2);
headers.put(Constant.AUTHORIZATION, authorization);
headers.put("host", config.getHost());
headers.put("x-bce-date", SmsDateUtils.normDateGmt8(new Date()));
return headers;
}

View File

@ -11,6 +11,7 @@ import org.dromara.sms4j.comm.delayedTime.DelayedTime;
import org.dromara.sms4j.comm.exception.SmsBlendException;
import org.dromara.sms4j.provider.service.AbstractSmsBlend;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
@ -72,7 +73,7 @@ public class BudingV2SmsImpl extends AbstractSmsBlend<BudingV2Config> {
} catch (SmsBlendException e) {
smsResponse = errorResp(e.message);
}
if (smsResponse.isSuccess() || retry == getConfig().getMaxRetries()) {
if (smsResponse.isSuccess() || retry >= getConfig().getMaxRetries()) {
retry = 0;
return smsResponse;
}
@ -150,7 +151,12 @@ public class BudingV2SmsImpl extends AbstractSmsBlend<BudingV2Config> {
*/
@Override
public SmsResponse massTexting(List<String> phones, String templateId, LinkedHashMap<String, String> messages) {
throw new SmsBlendException("布丁云V2暂不支持多条短信发送");
List<SmsResponse> list = new ArrayList<>();
for (String phone : phones) {
SmsResponse smsResponse = sendMessage(phone, templateId, messages);
list.add(smsResponse);
}
return SmsRespUtils.resp(list, true, getConfigId());
}
private Map<String, String> getHeaders() {

View File

@ -107,7 +107,7 @@ public class ChuangLanSmsImpl extends AbstractSmsBlend<ChuangLanConfig> {
}catch (SmsBlendException e) {
smsResponse = errorResp(e.message);
}
if (smsResponse.isSuccess() || retry == getConfig().getMaxRetries()) {
if (smsResponse.isSuccess() || retry >= getConfig().getMaxRetries()) {
retry = 0;
return smsResponse;
}

View File

@ -2,7 +2,6 @@ package org.dromara.sms4j.danmi.service;
import cn.hutool.core.util.StrUtil;
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.utils.SmsRespUtils;
@ -17,7 +16,6 @@ import org.dromara.sms4j.provider.service.AbstractSmsBlend;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Executor;
/**

View File

@ -21,13 +21,14 @@ import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicInteger;
import static org.dromara.sms4j.huawei.utils.HuaweiBuilder.listToString;
@Slf4j
public class HuaweiSmsImpl extends AbstractSmsBlend<HuaweiConfig> {
private int retry = 0;
private volatile int retry = 0;
public HuaweiSmsImpl(HuaweiConfig config, Executor pool, DelayedTime delayed) {
super(config, pool, delayed);
@ -80,7 +81,7 @@ public class HuaweiSmsImpl extends AbstractSmsBlend<HuaweiConfig> {
} catch (SmsBlendException e) {
smsResponse = errorResp(e.message);
}
if (smsResponse.isSuccess() || retry == getConfig().getMaxRetries()) {
if (smsResponse.isSuccess() || retry >= getConfig().getMaxRetries()) {
retry = 0;
return smsResponse;
}

View File

@ -99,7 +99,7 @@ public class JdCloudSmsImpl extends AbstractSmsBlend<JdCloudConfig> {
} catch (SmsBlendException e) {
smsResponse = errorResp(e.message);
}
if (smsResponse.isSuccess() || retry == getConfig().getMaxRetries()) {
if (smsResponse.isSuccess() || retry >= getConfig().getMaxRetries()) {
retry = 0;
return smsResponse;
}

View File

@ -119,7 +119,7 @@ public class JgSmsImpl extends AbstractSmsBlend<JgConfig> {
smsResponse = errorResp(e.message);
}
if (smsResponse.isSuccess() || retry == getConfig().getMaxRetries()) {
if (smsResponse.isSuccess() || retry >= getConfig().getMaxRetries()) {
retry = 0;
return smsResponse;
}

View File

@ -9,7 +9,12 @@ import org.dromara.sms4j.comm.utils.SmsUtils;
import org.dromara.sms4j.jg.config.JgConfig;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
/**

View File

@ -13,7 +13,11 @@ import org.dromara.sms4j.luosimao.config.LuoSiMaoConfig;
import org.dromara.sms4j.luosimao.utils.LuoSiMaoUtils;
import org.dromara.sms4j.provider.service.AbstractSmsBlend;
import java.util.*;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Executor;
/**

View File

@ -1,6 +1,5 @@
package org.dromara.sms4j.luosimao.utils;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.dromara.sms4j.comm.constant.Constant;
import org.dromara.sms4j.comm.utils.SmsDateUtils;
@ -21,14 +20,14 @@ public class LuoSiMaoUtils {
public static LinkedHashMap<String, Object> buildBody(String phone, String message) {
LinkedHashMap<String, Object> body = new LinkedHashMap<>(2);
body.put("mobile", StrUtil.addPrefixIfNot(phone, "+86"));
body.put("mobile", phone);
body.put("message", message);
return body;
}
public static LinkedHashMap<String, Object> buildBody(List<String> phones, String message, Date date) {
LinkedHashMap<String, Object> body = new LinkedHashMap<>(2);
body.put("mobile", SmsUtils.addCodePrefixIfNot(phones));
body.put("mobile", SmsUtils.joinComma(phones));
body.put("message", message);
if (date != null) {
body.put("time", SmsDateUtils.normDatetimeGmt8(date));

View File

@ -97,7 +97,7 @@ public class MasSmsImpl extends AbstractSmsBlend<MasConfig> {
} catch (SmsBlendException e) {
smsResponse = errorResp(e.message);
}
if (smsResponse.isSuccess() || retry == getConfig().getMaxRetries()) {
if (smsResponse.isSuccess() || retry >= getConfig().getMaxRetries()) {
retry = 0;
return smsResponse;
}

View File

@ -65,6 +65,8 @@ public class MasUtils {
if (StrUtil.isNotEmpty(config.getAddSerial())){
map.put("addSerial", config.getAddSerial().trim());
sb.append(config.getAddSerial().trim());
}else {
map.put("addSerial", "");
}
map.put("mac", DigestUtil.md5Hex(sb.toString(), StandardCharsets.UTF_8));

View File

@ -145,7 +145,7 @@ public class NeteaseSmsImpl extends AbstractSmsBlend<NeteaseConfig> {
} catch (SmsBlendException e) {
smsResponse = errorResp(e.message);
}
if (smsResponse.isSuccess() || retry == getConfig().getMaxRetries()) {
if (smsResponse.isSuccess() || retry >= getConfig().getMaxRetries()) {
retry = 0;
return smsResponse;
}

View File

@ -1,6 +1,7 @@
package org.dromara.sms4j.provider.config;
import lombok.Data;
import org.dromara.sms4j.api.universal.ProxyConfig;
import org.dromara.sms4j.api.universal.SupplierConfig;
import org.dromara.sms4j.comm.exception.SmsBlendException;
@ -56,6 +57,12 @@ public abstract class BaseConfig implements SupplierConfig {
*/
private String configId;
/**
* 代理配置
*
*/
private ProxyConfig proxy;
/**
* 重试间隔单位默认为5秒
*/

View File

@ -5,6 +5,7 @@ import lombok.Getter;
import org.dromara.sms4j.api.SmsBlend;
import org.dromara.sms4j.api.callback.CallBack;
import org.dromara.sms4j.api.entity.SmsResponse;
import org.dromara.sms4j.api.universal.ProxyConfig;
import org.dromara.sms4j.api.universal.SupplierConfig;
import org.dromara.sms4j.api.utils.SmsRespUtils;
import org.dromara.sms4j.comm.delayedTime.DelayedTime;
@ -32,13 +33,19 @@ public abstract class AbstractSmsBlend<C extends SupplierConfig> implements SmsB
protected final DelayedTime delayed;
protected final SmsHttpUtils http = SmsHttpUtils.instance();
protected final SmsHttpUtils http;
protected AbstractSmsBlend(C config, Executor pool, DelayedTime delayed) {
this.configId = StrUtil.isEmpty(config.getConfigId()) ? getSupplier() : config.getConfigId();
this.config = config;
this.pool = pool;
this.delayed = delayed;
ProxyConfig proxy = config.getProxy();
if (proxy != null && proxy.getEnable()){
this.http = SmsHttpUtils.instance(proxy.getHost(), proxy.getPort());
}else {
this.http = SmsHttpUtils.instance();
}
}
protected AbstractSmsBlend(C config) {
@ -46,6 +53,12 @@ public abstract class AbstractSmsBlend<C extends SupplierConfig> implements SmsB
this.config = config;
this.pool = BeanFactory.getExecutor();
this.delayed = BeanFactory.getDelayedTime();
ProxyConfig proxy = config.getProxy();
if (proxy != null && proxy.getEnable()){
this.http = SmsHttpUtils.instance(proxy.getHost(), proxy.getPort());
}else {
this.http = SmsHttpUtils.instance();
}
}
protected C getConfig() {

View File

@ -88,7 +88,7 @@ public class QiNiuSmsImpl extends AbstractSmsBlend<QiNiuConfig> {
}catch (SmsBlendException e){
smsResponse = errorResp(e.message);
}
if (smsResponse.isSuccess() || retry == getConfig().getMaxRetries()) {
if (smsResponse.isSuccess() || retry >= getConfig().getMaxRetries()) {
retry = 0;
return smsResponse;
}

View File

@ -17,7 +17,10 @@ import org.dromara.sms4j.provider.service.AbstractSmsBlend;
import org.dromara.sms4j.submail.config.SubMailConfig;
import org.dromara.sms4j.submail.utils.SubMailUtils;
import java.util.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.concurrent.Executor;
/**
@ -360,6 +363,6 @@ public class SubMailSmsImpl extends AbstractSmsBlend<SubMailConfig> {
private String timestamp(){
JSONObject resp = http.getUrl("https://api-v4.mysubmail.com/service/timestamp");
return resp.getStr("resp");
return resp.getStr("timestamp");
}
}

View File

@ -87,7 +87,7 @@ public class TencentSmsImpl extends AbstractSmsBlend<TencentConfig> {
} catch (SmsBlendException e) {
smsResponse = errorResp(e.message);
}
if (smsResponse.isSuccess() || retry == getConfig().getMaxRetries()) {
if (smsResponse.isSuccess() || retry >= getConfig().getMaxRetries()) {
retry = 0;
return smsResponse;
}

View File

@ -0,0 +1,48 @@
package org.dromara.sms4j.yixintong.config;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.sms4j.comm.constant.SupplierConstant;
import org.dromara.sms4j.provider.config.BaseConfig;
/**
* <p>类名: YiXintongConfig
* <p>说明联通一信通平台配置类
* <p>所用到配置项spCodefaccessKeyId(用户名)accessKeySecret接口密钥signCodetemplateIdretryIntervalmaxRetries
*
* @author moat
* @create 2024-07-30 16:50
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class YiXintongConfig extends BaseConfig {
/**
* 短信发送请求地址
*/
private String requestUrl = "https://api.ums86.com:9600/sms/Api/Send.do";
/**
* 企业编号
*/
private String spCode;
/**
* 签名编号
*/
private String signCode;
/**
* 提交时检测方式
* 1 --- 提交号码中有效的号码仍正常发出短信无效的号码在返回参数faillist中列出
*
* 不为1 或该参数不存在 --- 提交号码中只要有无效的号码那么所有的号码都不发出短信无效号码在返回参数faillist中列出
*/
private String f = "1";
@Override
public String getSupplier() {
return SupplierConstant.YIXINTONG;
}
}

View File

@ -0,0 +1,46 @@
package org.dromara.sms4j.yixintong.config;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.dromara.sms4j.comm.constant.SupplierConstant;
import org.dromara.sms4j.provider.factory.AbstractProviderFactory;
import org.dromara.sms4j.yixintong.service.YiXintongSmsImpl;
/**
* <p>类名: YiXintongFactory
* <p>说明联通一信通平台短信对象建造
*
* @author moat
* @create 2024-07-30 17:10
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class YiXintongFactory extends AbstractProviderFactory<YiXintongSmsImpl, YiXintongConfig> {
private static final YiXintongFactory INSTANCE = new YiXintongFactory();
/**
* 获取建造者实例
* @return 建造者实例
*/
public static YiXintongFactory instance() {
return INSTANCE;
}
/**
* createSms
* <p> 建造一个短信实现对像
*/
@Override
public YiXintongSmsImpl createSms(YiXintongConfig yiXintongConfig) {
return new YiXintongSmsImpl(yiXintongConfig);
}
/**
* 获取供应商
* @return 供应商
*/
@Override
public String getSupplier() {
return SupplierConstant.YIXINTONG;
}
}

View File

@ -0,0 +1,129 @@
package org.dromara.sms4j.yixintong.service;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.dromara.sms4j.api.entity.SmsResponse;
import org.dromara.sms4j.api.utils.SmsRespUtils;
import org.dromara.sms4j.comm.constant.SupplierConstant;
import org.dromara.sms4j.comm.delayedTime.DelayedTime;
import org.dromara.sms4j.comm.exception.SmsBlendException;
import org.dromara.sms4j.comm.utils.SmsUtils;
import org.dromara.sms4j.provider.service.AbstractSmsBlend;
import org.dromara.sms4j.yixintong.config.YiXintongConfig;
import org.dromara.sms4j.yixintong.utils.YiXintongUtils;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;
/**
* <p>类名: YiXintongSmsImpl
* <p>说明联通一信通 sms
*
* @author moat
* @create 2024-07-30 16:59
*/
@Slf4j
public class YiXintongSmsImpl extends AbstractSmsBlend<YiXintongConfig> {
private int retry = 0;
public YiXintongSmsImpl(YiXintongConfig config, Executor pool, DelayedTime delayedTime) {
super(config, pool, delayedTime);
}
public YiXintongSmsImpl(YiXintongConfig config) {
super(config);
}
@Override
public String getSupplier() {
return SupplierConstant.YIXINTONG;
}
@Override
public SmsResponse sendMessage(String phone, String message) {
return getSmsResponse(phone, message, getConfig().getTemplateId());
}
@Override
public SmsResponse massTexting(List<String> phones, String message) {
return getSmsResponse(SmsUtils.joinComma(phones), message, getConfig().getTemplateId());
}
@Override
public SmsResponse sendMessage(String phone, LinkedHashMap<String, String> messages) {
throw new SmsBlendException("不支持此方法");
}
@Override
public SmsResponse sendMessage(String phone, String templateId, LinkedHashMap<String, String> messages) {
throw new SmsBlendException("不支持此方法");
}
@Override
public SmsResponse massTexting(List<String> phones, String templateId, LinkedHashMap<String, String> messages) {
throw new SmsBlendException("不支持此方法");
}
private SmsResponse getSmsResponse(String phone, String message, String templateId) {
final YiXintongConfig config = getConfig();
if (StrUtil.isBlank(phone)){
log.error("phone is required.");
throw new SmsBlendException("phone is required.");
}
if (StrUtil.isBlank(message)){
log.error("message is required.");
throw new SmsBlendException("message is required.");
}
// 生成20位流水号
String serialNumber = SmsUtils.getRandomInt(20);
Map<String, Object> forms = new HashMap<>();
forms.put("SpCode", config.getSpCode());
forms.put("LoginName", config.getAccessKeyId());
forms.put("Password", config.getAccessKeySecret());
forms.put("MessageContent", message);
forms.put("UserNumber", phone);
forms.put("templateId", templateId);
forms.put("SerialNumber", serialNumber);
forms.put("ScheduleTime", ""); // 立即发送
forms.put("f", config.getF());
forms.put("signCode", config.getSignCode());
SmsResponse smsResponse;
try {
smsResponse = getResponse(YiXintongUtils.postForm(config.getRequestUrl(), forms));
} catch (SmsBlendException e) {
smsResponse = errorResp(e.message);
}
if (smsResponse.isSuccess() || retry == config.getMaxRetries()) {
retry = 0;
return smsResponse;
}
return requestRetry(phone, message, templateId);
}
private SmsResponse requestRetry(String phone, String message, String templateId) {
http.safeSleep(getConfig().getRetryInterval());
retry ++;
log.warn("The SMS has been resent for the {}th time.", retry);
return getSmsResponse(phone, message, templateId);
}
/**
* 构造统一短信返回信息
* @param body 原始响应信息
* @return 短信返回信息
*/
private SmsResponse getResponse(String body) {
return SmsRespUtils.resp(body, StrUtil.contains(body, "result=0&"), getConfigId());
}
}

View File

@ -0,0 +1,54 @@
package org.dromara.sms4j.yixintong.utils;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import org.dromara.sms4j.comm.exception.SmsBlendException;
import java.util.Map;
/**
* <p>类名: YiXintongUtils
* <p>说明联通一信通工具类
*
* @author moat
* @create 2024-07-31 9:55
*/
public class YiXintongUtils {
/**
* 发送post form请求
*
* @param url 请求地址
* @param forms 表单参数
* @return 返回体
*/
public static String postForm(String url, Map<String, Object> forms) {
return postForm(url, null, forms, "gbk");
}
/**
* 发送post form请求
*
* @param url 请求地址
* @param headers 请求头
* @param forms 表单参数
* @param charset 字符集编码
* @return 返回体
*/
public static String postForm(String url, Map<String, String> headers, Map<String, Object> forms, String charset) {
try (HttpResponse response = HttpRequest.post(url)
.addHeaders(headers)
.form(forms)
.charset(charset)
.execute()) {
return response.body();
} catch (Exception e) {
throw new SmsBlendException(e.getMessage());
}
}
}

View File

@ -58,7 +58,7 @@ public class YunPianSmsImpl extends AbstractSmsBlend<YunpianConfig> {
} catch (SmsBlendException e) {
smsResponse = errorResp(e.message);
}
if (smsResponse.isSuccess() || retry == getConfig().getMaxRetries()) {
if (smsResponse.isSuccess() || retry >= getConfig().getMaxRetries()) {
retry = 0;
return smsResponse;
}
@ -92,9 +92,9 @@ public class YunPianSmsImpl extends AbstractSmsBlend<YunpianConfig> {
try {
smsResponse = getResponse(http.postFrom(Constant.YUNPIAN_URL + "/sms/tpl_single_send.json", headers, body));
} catch (SmsBlendException e) {
return requestRetry(phone, templateId, messages);
smsResponse = errorResp(e.message);
}
if (smsResponse.isSuccess() || retry == getConfig().getMaxRetries()) {
if (smsResponse.isSuccess() || retry >= getConfig().getMaxRetries()) {
retry = 0;
return smsResponse;
}

View File

@ -155,7 +155,7 @@ public class ZhutongSmsImpl extends AbstractSmsBlend<ZhutongConfig> {
} catch (SmsBlendException e) {
smsResponse = errorResp(e.message);
}
if (smsResponse.isSuccess() || retry == getConfig().getMaxRetries()) {
if (smsResponse.isSuccess() || retry >= getConfig().getMaxRetries()) {
retry = 0;
return smsResponse;
}
@ -241,7 +241,7 @@ public class ZhutongSmsImpl extends AbstractSmsBlend<ZhutongConfig> {
} catch (SmsBlendException e) {
smsResponse = errorResp(e.message);
}
if (smsResponse.isSuccess() || retry == getConfig().getMaxRetries()) {
if (smsResponse.isSuccess() || retry >= getConfig().getMaxRetries()) {
retry = 0;
return smsResponse;
}

View File

@ -4,6 +4,7 @@ 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.utils.SmsRespUtils;
import org.dromara.sms4j.comm.delayedTime.DelayedTime;
import org.dromara.sms4j.comm.exception.SmsBlendException;
import org.dromara.sms4j.comm.utils.SmsUtils;
@ -90,11 +91,9 @@ public class ZhangJunSmsImpl extends AbstractSmsBlend<ZhangJunConfig> {
try {
smsResponse = getResponse(http.postJson(getConfig().getUrl(), null, message));
} catch (SmsBlendException e) {
smsResponse = new SmsResponse();
smsResponse.setSuccess(false);
smsResponse.setData(e.getMessage());
smsResponse = errorResp(e.message);
}
if (smsResponse.isSuccess() || retry == getConfig().getMaxRetries()) {
if (smsResponse.isSuccess() || retry >= getConfig().getMaxRetries()) {
retry = 0;
return smsResponse;
}
@ -109,11 +108,7 @@ public class ZhangJunSmsImpl extends AbstractSmsBlend<ZhangJunConfig> {
}
private SmsResponse getResponse(JSONObject resJson) {
SmsResponse smsResponse = new SmsResponse();
smsResponse.setSuccess("OK".equals(resJson.getStr("Code")));
smsResponse.setData(resJson);
smsResponse.setConfigId(getConfigId());
return smsResponse;
return SmsRespUtils.resp(resJson, "OK".equals(resJson.getStr("Code")), getConfigId());
}
}

View File

@ -155,21 +155,29 @@ sms:
accessKeyId: ACCOUNT SID
accessKeySecret: AUTH TOKEN
action: 默认请求方法 distributor/sendSMS
# 一信通
yixintong:
sp-code: xxxxxx #(必填)企业编号
access-key-id: xxxxxx #(必填)用户名
access-key-secret: 324gaxxxxxxxxxxxxxxxxx9sdf89 #(必填)接口密钥(正式帐户需要登陆平台,接口业务-接口申请右侧钥匙状图标查看或获取,接口密钥获取后十分钟生效)
template-id: #(可选)模板编号(若配置此参数,则会默认使用该模板,以便提高服务方性能)
sign-code: #(可选)短信前置签名编号(登陆平台-接口业务-我的签名查看)
f: 1 #(可选)默认为1提交时检测方式
sms-oa:
config-type: yaml
oas:
oaDingTalkByYaml: # configId
isEnable: true # 表示该配置是否生效(默认生效,false表示不生效)
supplier: dingding # 厂商标识
supplier: ding_ding # 厂商标识
tokenId: 您的accessKey
sign: 您的sign
oaByteTalkByYaml: # configId
supplier: feishu # 厂商标识
supplier: byte_talk # 厂商标识
tokenId: 您的accessKey
sign: 您的sign
oaWeTalkByYaml:
supplier: wetalk # 厂商标识
supplier: we_talk # 厂商标识
tokenId: 您的sign
core-pool-size: 20
queue-capacity: 20

View File

@ -1,5 +1,6 @@
package org.dromara.sms4j.example;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.UUID;
@ -18,14 +19,16 @@ import org.dromara.sms4j.jg.service.JgSmsImpl;
import org.dromara.sms4j.lianlu.service.LianLuSmsImpl;
import org.dromara.sms4j.luosimao.service.LuoSiMaoSmsImpl;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.noear.solon.test.SolonJUnit5Extension;
import org.noear.solon.test.SolonTest;
import java.util.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@Slf4j
@ExtendWith(SolonJUnit5Extension.class)
@SolonTest
public class Sms4jTest {
@ -528,4 +531,31 @@ public class Sms4jTest {
SmsResponse smsResponse5 = danMiSms.voiceTemplate(PHONE, "opipedlqza", "111,222,333");
Assert.isTrue(smsResponse5.isSuccess());
}
/**
* 联通一信通模板
*/
@Test
public void yixintongSmsTest() {
if (StrUtil.isBlank(PHONE)) {
return;
}
//短信发送模板你有一项编号为{xxxxxxxxx}的事务需要处理{x}
//其中的{xxxxxx}代表短信模板中的变量部分可变化一个x代表一个字或者字符{}为变量标识在发送时不用传实发变量字数小于等于x的个数
// 单发
String message1 = StrUtil.format("你有一项编号为{}的事务需要处理。", SmsUtils.getRandomInt(6));
SmsResponse smsResponse1 = SmsFactory.getBySupplier(SupplierConstant.YIXINTONG).sendMessage(PHONE, message1);
log.info(JSONUtil.toJsonStr(smsResponse1));
Assert.isTrue(smsResponse1.isSuccess());
// 群发
List<String> phones = CollectionUtil.toList(PHONE);
String message2 = StrUtil.format("你有一项编号为{}的事务需要处理。", SmsUtils.getRandomInt(6));
SmsResponse smsResponse2 = SmsFactory.getBySupplier(SupplierConstant.YIXINTONG).massTexting(phones, message2);
log.info(JSONUtil.toJsonStr(smsResponse2));
Assert.isTrue(smsResponse2.isSuccess());
}
}

View File

@ -10,8 +10,6 @@ import org.dromara.oa.core.dingTalk.config.DingTalkConfig;
import org.dromara.oa.core.provider.factory.OaFactory;
import org.dromara.oa.core.weTalk.config.WeTalkConfig;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.noear.solon.test.SolonJUnit5Extension;
import org.noear.solon.test.SolonTest;
import java.util.ArrayList;
@ -20,7 +18,6 @@ import java.util.concurrent.CountDownLatch;
@Slf4j
@ExtendWith(SolonJUnit5Extension.class)
@SolonTest
public class SmsOaTest {
//***********************DingTalk-Test************************//

View File

@ -9,8 +9,6 @@ import org.dromara.sms4j.comm.exception.SmsBlendException;
import org.dromara.sms4j.comm.utils.SmsUtils;
import org.dromara.sms4j.core.factory.SmsFactory;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.noear.solon.test.SolonJUnit5Extension;
import org.noear.solon.test.SolonTest;
import java.util.ArrayList;
@ -21,7 +19,6 @@ import java.util.LinkedHashMap;
* @author sh1yu
*/
@Slf4j
@ExtendWith(SolonJUnit5Extension.class)
@SolonTest
public class SmsProcessorTest {
/**

View File

@ -5,8 +5,6 @@ import lombok.extern.slf4j.Slf4j;
import org.dromara.sms4j.aliyun.config.AlibabaConfig;
import org.dromara.sms4j.comm.utils.SmsUtils;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.noear.solon.test.SolonJUnit5Extension;
import org.noear.solon.test.SolonTest;
import java.util.ArrayList;
@ -16,7 +14,6 @@ import java.util.List;
* @author handy
*/
@Slf4j
@ExtendWith(SolonJUnit5Extension.class)
@SolonTest
public class SmsUtilsTest {

View File

@ -0,0 +1,17 @@
package org.dromara.sms4j.solon;
import org.dromara.sms4j.solon.config.SmsMainConfigure;
import org.dromara.sms4j.solon.config.SupplierConfigure;
import org.noear.solon.core.AppContext;
import org.noear.solon.core.Plugin;
/**
* @author noear 2023/5/16 created
*/
public class Sms4jPlugin implements Plugin {
@Override
public void start(AppContext context) {
context.beanMake(SmsMainConfigure.class);
context.beanMake(SupplierConfigure.class);
}
}

View File

@ -1,17 +0,0 @@
package org.dromara.sms4j.solon;
import org.dromara.sms4j.solon.config.SmsAutowiredConfig;
import org.dromara.sms4j.solon.config.SupplierConfig;
import org.noear.solon.core.AppContext;
import org.noear.solon.core.Plugin;
/**
* @author noear 2023/5/16 created
*/
public class XPluginImpl implements Plugin {
@Override
public void start(AppContext context) {
context.beanMake(SmsAutowiredConfig.class);
context.beanMake(SupplierConfig.class);
}
}

View File

@ -0,0 +1,40 @@
package org.dromara.sms4j.solon.adaptor;
import cn.hutool.core.bean.BeanUtil;
import org.dromara.sms4j.core.datainterface.SmsReadConfig;
import org.dromara.sms4j.provider.config.BaseConfig;
import java.util.*;
public class ConfigCombineMapAdaptor<S, M> extends HashMap {
@Override
public M get(Object key) {
Object o = super.get(key);
if (null == o){
Set configKeySet = this.keySet();
for (Object insideMapKey : configKeySet) {
if (((String)insideMapKey).startsWith(SmsReadConfig.class.getSimpleName())){
Map smsBlendsConfigInsideMap = (Map) this.get(insideMapKey);
SmsReadConfig config = (SmsReadConfig) smsBlendsConfigInsideMap.get(insideMapKey);
BaseConfig supplierConfig = config.getSupplierConfig((String)key);
List<BaseConfig> supplierConfigList = config.getSupplierConfigList();
if (null == supplierConfigList){
supplierConfigList = new ArrayList<>();
}
if (null != supplierConfig){
supplierConfigList.add(supplierConfig);
}
for (BaseConfig baseConfig : supplierConfigList) {
if (key.equals(baseConfig.getConfigId())){
Map<String, Object> configMap = BeanUtil.beanToMap(baseConfig);
this.put(baseConfig.getConfigId(),configMap);
return (M)configMap;
}
}
}
}
return null;
}
return (M)o;
}
}

View File

@ -1,60 +0,0 @@
package org.dromara.sms4j.solon.config;
import lombok.extern.slf4j.Slf4j;
import org.dromara.sms4j.comm.constant.Constant;
import org.dromara.sms4j.comm.delayedTime.DelayedTime;
import org.dromara.sms4j.provider.config.SmsBanner;
import org.dromara.sms4j.provider.config.SmsConfig;
import org.dromara.sms4j.provider.factory.BeanFactory;
import org.noear.solon.annotation.Bean;
import org.noear.solon.annotation.Configuration;
import org.noear.solon.annotation.Inject;
import org.noear.solon.core.AppContext;
import org.noear.solon.core.bean.LifecycleBean;
import java.util.concurrent.Executor;
@Slf4j
@Configuration
public class SmsAutowiredConfig implements LifecycleBean {
@Inject
AppContext context;
private <T> T injectObj(String prefix, T obj) {
//@Inject 只支持在字段参数类型上注入
context.cfg().getProp(prefix).bindTo(obj);
return obj;
}
@Bean
public SmsConfig smsConfig() {
return injectObj("sms", BeanFactory.getSmsConfig());
}
/**
* 注入一个定时器
*/
@Bean
public DelayedTime delayedTime() {
return BeanFactory.getDelayedTime();
}
/**
* 注入线程池
*/
@Bean("smsExecutor")
public Executor taskExecutor(@Inject SmsConfig config) {
return BeanFactory.setExecutor(config);
}
//是在 solon 容器扫描完成之后执行的
@Override
public void start() {
//打印banner
if (BeanFactory.getSmsConfig().getIsPrint()) {
SmsBanner.PrintBanner(Constant.VERSION);
}
}
}

View File

@ -10,9 +10,12 @@ import org.dromara.sms4j.api.universal.SupplierConfig;
import org.dromara.sms4j.api.verify.PhoneVerify;
import org.dromara.sms4j.baidu.config.BaiduFactory;
import org.dromara.sms4j.budingyun.config.BudingV2Factory;
import org.dromara.sms4j.chuanglan.config.ChuangLanFactory;
import org.dromara.sms4j.cloopen.config.CloopenFactory;
import org.dromara.sms4j.comm.constant.Constant;
import org.dromara.sms4j.comm.enums.ConfigType;
import org.dromara.sms4j.comm.utils.SmsUtils;
import org.dromara.sms4j.core.datainterface.SmsReadConfig;
import org.dromara.sms4j.core.factory.SmsFactory;
import org.dromara.sms4j.core.proxy.EnvirmentHolder;
import org.dromara.sms4j.core.proxy.SmsProxyFactory;
@ -26,7 +29,6 @@ import org.dromara.sms4j.dingzhong.config.DingZhongFactory;
import org.dromara.sms4j.emay.config.EmayFactory;
import org.dromara.sms4j.huawei.config.HuaweiFactory;
import org.dromara.sms4j.jdcloud.config.JdCloudFactory;
import org.dromara.sms4j.chuanglan.config.ChuangLanFactory;
import org.dromara.sms4j.jg.config.JgFactory;
import org.dromara.sms4j.lianlu.config.LianLuFactory;
import org.dromara.sms4j.luosimao.config.LuoSiMaoFactory;
@ -36,14 +38,15 @@ import org.dromara.sms4j.provider.config.SmsConfig;
import org.dromara.sms4j.provider.factory.BaseProviderFactory;
import org.dromara.sms4j.provider.factory.ProviderFactoryHolder;
import org.dromara.sms4j.qiniu.config.QiNiuFactory;
import org.dromara.sms4j.solon.holder.SolonSmsDaoHolder;
import org.dromara.sms4j.solon.adaptor.ConfigCombineMapAdaptor;
import org.dromara.sms4j.submail.config.SubMailFactory;
import org.dromara.sms4j.tencent.config.TencentFactory;
import org.dromara.sms4j.unisms.config.UniFactory;
import org.dromara.sms4j.yixintong.config.YiXintongFactory;
import org.dromara.sms4j.yunpian.config.YunPianFactory;
import org.dromara.sms4j.zhutong.config.ZhutongFactory;
import org.noear.solon.core.AppContext;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.ServiceLoader;
@ -55,48 +58,57 @@ public class SmsBlendsInitializer {
private final SmsConfig smsConfig;
private final Map<String, Map<String, Object>> blends;
private final AppContext context;
private final List<SmsReadConfig> extendsSmsConfigs;
public SmsBlendsInitializer(List<BaseProviderFactory<? extends SmsBlend, ? extends SupplierConfig>> factoryList,
SmsConfig smsConfig,
Map<String, Map<String, Object>> blends,
AppContext context
){
List<SmsReadConfig> extendsSmsConfigs){
this.factoryList = factoryList;
this.smsConfig = smsConfig;
this.blends = blends;
this.context = context;
onApplicationEvent();
this.extendsSmsConfigs = extendsSmsConfigs;
this.initDo();
}
public void onApplicationEvent() {
private void initDo() {
this.registerDefaultFactory();
// 注册短信对象工厂
ProviderFactoryHolder.registerFactory(factoryList);
//持有初始化配置信息
EnvirmentHolder.frozenEnvirmet(smsConfig, blends);
//框架依赖持有缓存扩展
new SolonSmsDaoHolder(context);
//注册执行器实现
SmsProxyFactory.addPreProcessor(new RestrictedProcessor());
SmsProxyFactory.addPreProcessor(new BlackListProcessor());
SmsProxyFactory.addPreProcessor(new BlackListRecordingProcessor());
//如果手机号校验器存在实现则注册手机号校验器
//如果手机号校验器存在实现则注册手机号校验器暂不可用
ServiceLoader<PhoneVerify> loader = ServiceLoader.load(PhoneVerify.class);
if (loader.iterator().hasNext()) {
loader.forEach(f -> {
SmsProxyFactory.addPreProcessor(new CoreMethodParamValidateProcessor(f));
});
loader.forEach(f -> SmsProxyFactory.addPreProcessor(new CoreMethodParamValidateProcessor(f)));
} else {
SmsProxyFactory.addPreProcessor(new CoreMethodParamValidateProcessor(null));
}
//注册执行器实现
if(this.smsConfig.getRestricted()){
SmsProxyFactory.addPreProcessor(new RestrictedProcessor());
SmsProxyFactory.addPreProcessor(new BlackListProcessor());
SmsProxyFactory.addPreProcessor(new BlackListRecordingProcessor());
}
if (ConfigType.YAML.equals(this.smsConfig.getConfigType())) {
//持有初始化配置信息
Map<String, Map<String, Object>> blendsInclude = new ConfigCombineMapAdaptor<String, Map<String, Object>>();
blendsInclude.putAll(this.blends);
int num = 0;
for (SmsReadConfig smsReadConfig : extendsSmsConfigs) {
String key = SmsReadConfig.class.getSimpleName() + num;
Map<String, Object> insideMap = new HashMap<>();
insideMap.put(key, smsReadConfig);
blendsInclude.put(key, insideMap);
num++;
}
EnvirmentHolder.frozenEnvirmet(smsConfig, blendsInclude);
// 解析供应商配置
for (String configId : blends.keySet()) {
Map<String, Object> configMap = blends.get(configId);
Object supplierObj = configMap.get(Constant.SUPPLIER_KEY);
String supplier = supplierObj == null ? "" : String.valueOf(supplierObj);
supplier = StrUtil.isEmpty(supplier) ? configId : supplier;
BaseProviderFactory<SmsBlend, SupplierConfig> providerFactory = (BaseProviderFactory<SmsBlend, SupplierConfig>) ProviderFactoryHolder.requireForSupplier(supplier);
BaseProviderFactory<SmsBlend, SupplierConfig> providerFactory = (BaseProviderFactory<SmsBlend, org.dromara.sms4j.api.universal.SupplierConfig>) ProviderFactoryHolder.requireForSupplier(supplier);
if (providerFactory == null) {
log.warn("创建\"{}\"的短信服务失败,未找到供应商为\"{}\"的服务", configId, supplier);
continue;
@ -104,9 +116,11 @@ public class SmsBlendsInitializer {
configMap.put("config-id", configId);
SmsUtils.replaceKeysSeparator(configMap, "-", "_");
JSONObject configJson = new JSONObject(configMap);
SupplierConfig supplierConfig = JSONUtil.toBean(configJson, providerFactory.getConfigClass());
org.dromara.sms4j.api.universal.SupplierConfig supplierConfig = JSONUtil.toBean(configJson, providerFactory.getConfigClass());
SmsFactory.createSmsBlend(supplierConfig);
}
}
}
@ -135,9 +149,13 @@ public class SmsBlendsInitializer {
ProviderFactoryHolder.registerFactory(LuoSiMaoFactory.instance());
ProviderFactoryHolder.registerFactory(SubMailFactory.instance());
ProviderFactoryHolder.registerFactory(DanMiFactory.instance());
ProviderFactoryHolder.registerFactory(YiXintongFactory.instance());
if (SmsUtils.isClassExists("com.jdcloud.sdk.auth.CredentialsProvider")) {
if (SmsUtils.isClassExists("com.jdcloud.sdk.auth.CredentialsProvider")) {
ProviderFactoryHolder.registerFactory(JdCloudFactory.instance());
}
log.debug("加载内置运营商完成!");
}
}
}

View File

@ -0,0 +1,34 @@
package org.dromara.sms4j.solon.config;
import lombok.extern.slf4j.Slf4j;
import org.dromara.sms4j.comm.constant.Constant;
import org.dromara.sms4j.provider.config.SmsBanner;
import org.dromara.sms4j.provider.config.SmsConfig;
import org.dromara.sms4j.provider.factory.BeanFactory;
import org.noear.solon.annotation.Bean;
import org.noear.solon.annotation.Configuration;
import org.noear.solon.annotation.Init;
import org.noear.solon.annotation.Inject;
import org.noear.solon.core.AppContext;
@Slf4j
@Configuration
public class SmsMainConfigure {
@Inject
AppContext context;
@Bean
public SmsConfig smsConfig() {
return context.cfg().getProp("sms")
.bindTo(BeanFactory.getSmsConfig());
}
//是在 solon 容器扫描完成之后执行的
@Init
public void init() {
//打印banner
if (BeanFactory.getSmsConfig().getIsPrint()) {
SmsBanner.PrintBanner(Constant.VERSION);
}
}
}

View File

@ -1,52 +0,0 @@
package org.dromara.sms4j.solon.config;
import org.dromara.sms4j.api.SmsBlend;
import org.dromara.sms4j.provider.config.SmsConfig;
import org.dromara.sms4j.provider.factory.BaseProviderFactory;
import org.noear.solon.annotation.Bean;
import org.noear.solon.annotation.Condition;
import org.noear.solon.annotation.Configuration;
import org.noear.solon.annotation.Inject;
import org.noear.solon.core.AppContext;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* smsConfig参数意义为确保注入时smsConfig已经存在
*/
@Condition(onProperty = "${sms.configType}=yaml")
@Configuration
public class SupplierConfig {
@Inject
AppContext context;
private <T> T injectObj(String prefix, T obj) {
//@Inject 只支持在字段参数类型上注入
context.cfg().getProp(prefix).bindTo(obj);
return obj;
}
@Bean
protected Map<String, Map<String, Object>> blends() {
return injectObj("sms.blends", new LinkedHashMap<>());
}
@Bean
protected SmsBlendsInitializer smsBlendsInitializer(List<BaseProviderFactory> factoryList,
SmsConfig smsConfig,
Map<String, Map<String, Object>> blends) {
//todo: solon 不支持泛型的 List[Bean] 注入
List<BaseProviderFactory<? extends SmsBlend, ? extends org.dromara.sms4j.api.universal.SupplierConfig>> factoryList2 = new ArrayList<>(factoryList.size());
for (BaseProviderFactory factory : factoryList) {
factoryList2.add((BaseProviderFactory<? extends SmsBlend, ? extends org.dromara.sms4j.api.universal.SupplierConfig>) factory);
}
return new SmsBlendsInitializer(factoryList2, smsConfig, blends, context);
}
}

View File

@ -0,0 +1,72 @@
package org.dromara.sms4j.solon.config;
import cn.hutool.core.util.ObjectUtil;
import org.dromara.sms4j.api.SmsBlend;
import org.dromara.sms4j.api.universal.SupplierConfig;
import org.dromara.sms4j.comm.constant.Constant;
import org.dromara.sms4j.comm.enums.ConfigType;
import org.dromara.sms4j.core.datainterface.SmsReadConfig;
import org.dromara.sms4j.provider.config.SmsConfig;
import org.dromara.sms4j.provider.factory.BaseProviderFactory;
import org.noear.solon.annotation.Bean;
import org.noear.solon.annotation.Condition;
import org.noear.solon.annotation.Configuration;
import org.noear.solon.annotation.Inject;
import org.noear.solon.core.AppContext;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* smsConfig 参数意义为确保注入时 smsConfig 已经存在
*/
@Configuration
public class SupplierConfigure {
@Inject
AppContext context;
private <T> T injectObj(String prefix, T obj) {
//@Inject 只支持在字段参数类型上注入
context.cfg().getProp(prefix).bindTo(obj);
return obj;
}
@Bean("blends")
public Map<String, Map<String, Object>> blends() {
//确保能产生给下面用//springboot 就算没产生也会给个默认
return context.cfg().getProp("sms.blends").bindTo(new LinkedHashMap<>());
}
@Bean
@Condition(onBean = SmsConfig.class)
public List<BaseProviderFactory<? extends SmsBlend, ? extends SupplierConfig>> factoryList(
@Inject("blends") Map<String, Map<String, Object>> blends,
SmsConfig smsConfig) throws Exception {
//注入自定义实现工厂
List<BaseProviderFactory<? extends SmsBlend, ? extends SupplierConfig>> factoryList = new ArrayList<>();
if (ConfigType.YAML.equals(smsConfig.getConfigType())) {
for (String configId : blends.keySet()) {
Map<String, Object> configMap = blends.get(configId);
Object factoryPath = configMap.get(Constant.FACTORY_PATH);
if (ObjectUtil.isNotEmpty(factoryPath)) {
//反射创建实例
Class<BaseProviderFactory<? extends SmsBlend, ? extends SupplierConfig>> newClass = (Class<BaseProviderFactory<? extends SmsBlend, ? extends SupplierConfig>>) Class.forName(factoryPath.toString());
BaseProviderFactory<? extends SmsBlend, ? extends SupplierConfig> factory = newClass.newInstance();
factoryList.add(factory);
}
}
}
return factoryList;
}
@Bean
public SmsBlendsInitializer smsBlendsInitializer(List<BaseProviderFactory<? extends SmsBlend, ? extends SupplierConfig>> factoryList,
SmsConfig smsConfig,
@Inject("blends") Map<String, Map<String, Object>> blends,
List<SmsReadConfig> extendsSmsConfigs) {
return new SmsBlendsInitializer(factoryList, smsConfig, blends, extendsSmsConfigs);
}
}

View File

@ -1,22 +1,10 @@
package org.dromara.sms4j.solon.holder;
import org.dromara.sms4j.api.dao.SmsDao;
import org.dromara.sms4j.api.dao.SmsDaoDefaultImpl;
import org.dromara.sms4j.comm.utils.SmsUtils;
import org.noear.solon.core.AppContext;
import org.noear.solon.Solon;
public class SolonSmsDaoHolder {
private static SmsDao smsDao;
public SolonSmsDaoHolder(AppContext context) {
context.getBeanAsync(SmsDao.class, bean -> smsDao = bean);
}
public static SmsDao getSmsDao() {
if (SmsUtils.isEmpty(smsDao)){
smsDao = SmsDaoDefaultImpl.getInstance();
}
return smsDao;
return Solon.context().getBean(SmsDao.class);
}
}

View File

@ -1,4 +1,2 @@
#???????
solon.plugin=org.dromara.sms4j.solon.XPluginImpl
#?????????????????0
solon.plugin=org.dromara.sms4j.solon.Sms4jPlugin
solon.plugin.priority=1

View File

@ -93,7 +93,7 @@ public class ZhangJunSmsImpl extends AbstractSmsBlend<ZhangJunConfig> {
} catch (SmsBlendException e) {
smsResponse = errorResp(e.message);
}
if (smsResponse.isSuccess() || retry == getConfig().getMaxRetries()) {
if (smsResponse.isSuccess() || retry >= getConfig().getMaxRetries()) {
retry = 0;
return smsResponse;
}

View File

@ -18,6 +18,12 @@ sms:
template-id: SMS_272470496
# 模版名称
templateName: code
# 代理
proxy:
# 是否启用代理 默认关闭 需手动开启
enable: true
host: 127.0.0.1
port: 8080
# 腾讯短信例子
tx:
#厂商标识
@ -155,21 +161,29 @@ sms:
accessKeyId: ACCOUNT SID
accessKeySecret: AUTH TOKEN
action: 默认请求方法 distributor/sendSMS
# 一信通
yixintong:
sp-code: xxxxxx #(必填)企业编号
access-key-id: xxxxxx #(必填)用户名
access-key-secret: 324gaxxxxxxxxxxxxxxxxx9sdf89 #(必填)接口密钥(正式帐户需要登陆平台,接口业务-接口申请右侧钥匙状图标查看或获取,接口密钥获取后十分钟生效)
template-id: #(可选)模板编号(若配置此参数,则会默认使用该模板,以便提高服务方性能)
sign-code: #(可选)短信前置签名编号(登陆平台-接口业务-我的签名查看)
f: 1 #(可选)默认为1提交时检测方式
sms-oa:
config-type: yaml
oas:
oaDingTalkByYaml: # configId
isEnable: true # 表示该配置是否生效(默认生效,false表示不生效)
supplier: dingding # 厂商标识
supplier: ding_ding # 厂商标识
tokenId: 您的accessKey
sign: 您的sign
oaByteTalkByYaml: # configId
supplier: feishu # 厂商标识
supplier: byte_talk # 厂商标识
tokenId: 您的accessKey
sign: 您的sign
oaWeTalkByYaml:
supplier: wetalk # 厂商标识
supplier: we_talk # 厂商标识
tokenId: 您的sign
core-pool-size: 20
queue-capacity: 20

View File

@ -1,5 +1,6 @@
package org.dromara.sms4j.example;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.UUID;
@ -20,7 +21,12 @@ import org.dromara.sms4j.luosimao.service.LuoSiMaoSmsImpl;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@Slf4j
@SpringBootTest
@ -526,4 +532,31 @@ public class Sms4jTest {
Assert.isTrue(smsResponse5.isSuccess());
}
/**
* 联通一信通模板
*/
@Test
public void yixintongSmsTest() {
if (StrUtil.isBlank(PHONE)) {
return;
}
//短信发送模板你有一项编号为{xxxxxxxxx}的事务需要处理{x}
//其中的{xxxxxx}代表短信模板中的变量部分可变化一个x代表一个字或者字符{}为变量标识在发送时不用传实发变量字数小于等于x的个数
// 单发
String message1 = StrUtil.format("你有一项编号为{}的事务需要处理。", SmsUtils.getRandomInt(6));
SmsResponse smsResponse1 = SmsFactory.getBySupplier(SupplierConstant.YIXINTONG).sendMessage(PHONE, message1);
log.info(JSONUtil.toJsonStr(smsResponse1));
Assert.isTrue(smsResponse1.isSuccess());
// 群发
List<String> phones = CollectionUtil.toList(PHONE);
String message2 = StrUtil.format("你有一项编号为{}的事务需要处理。", SmsUtils.getRandomInt(6));
SmsResponse smsResponse2 = SmsFactory.getBySupplier(SupplierConstant.YIXINTONG).massTexting(phones, message2);
log.info(JSONUtil.toJsonStr(smsResponse2));
Assert.isTrue(smsResponse2.isSuccess());
}
}

View File

@ -1,4 +1,4 @@
package org.dromara.sms4j.starter.adepter;
package org.dromara.sms4j.starter.adaptor;
import cn.hutool.core.bean.BeanUtil;
import org.dromara.sms4j.core.datainterface.SmsReadConfig;

View File

@ -38,10 +38,11 @@ import org.dromara.sms4j.provider.config.SmsConfig;
import org.dromara.sms4j.provider.factory.BaseProviderFactory;
import org.dromara.sms4j.provider.factory.ProviderFactoryHolder;
import org.dromara.sms4j.qiniu.config.QiNiuFactory;
import org.dromara.sms4j.starter.adepter.ConfigCombineMapAdaptor;
import org.dromara.sms4j.starter.adaptor.ConfigCombineMapAdaptor;
import org.dromara.sms4j.submail.config.SubMailFactory;
import org.dromara.sms4j.tencent.config.TencentFactory;
import org.dromara.sms4j.unisms.config.UniFactory;
import org.dromara.sms4j.yixintong.config.YiXintongFactory;
import org.dromara.sms4j.yunpian.config.YunPianFactory;
import org.dromara.sms4j.zhutong.config.ZhutongFactory;
import org.springframework.beans.factory.ObjectProvider;
@ -78,9 +79,7 @@ public class SmsBlendsInitializer {
//如果手机号校验器存在实现则注册手机号校验器暂不可用
ServiceLoader<PhoneVerify> loader = ServiceLoader.load(PhoneVerify.class);
if (loader.iterator().hasNext()) {
loader.forEach(f -> {
SmsProxyFactory.addPreProcessor(new CoreMethodParamValidateProcessor(f));
});
loader.forEach(f -> SmsProxyFactory.addPreProcessor(new CoreMethodParamValidateProcessor(f)));
} else {
SmsProxyFactory.addPreProcessor(new CoreMethodParamValidateProcessor(null));
}
@ -150,6 +149,7 @@ public class SmsBlendsInitializer {
ProviderFactoryHolder.registerFactory(LuoSiMaoFactory.instance());
ProviderFactoryHolder.registerFactory(SubMailFactory.instance());
ProviderFactoryHolder.registerFactory(DanMiFactory.instance());
ProviderFactoryHolder.registerFactory(YiXintongFactory.instance());
if (SmsUtils.isClassExists("com.jdcloud.sdk.auth.CredentialsProvider")) {
if (SmsUtils.isClassExists("com.jdcloud.sdk.auth.CredentialsProvider")) {
ProviderFactoryHolder.registerFactory(JdCloudFactory.instance());

View File

@ -9,6 +9,7 @@ import org.dromara.sms4j.core.datainterface.SmsReadConfig;
import org.dromara.sms4j.provider.config.SmsConfig;
import org.dromara.sms4j.provider.factory.BaseProviderFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ -34,7 +35,7 @@ public class SupplierConfig {
@Bean
@ConditionalOnBean({SmsConfig.class})
@SneakyThrows
protected List<BaseProviderFactory<? extends SmsBlend, ? extends org.dromara.sms4j.api.universal.SupplierConfig>> factoryList(Map<String, Map<String, Object>> blends, SmsConfig smsConfig) {
protected List<BaseProviderFactory<? extends SmsBlend, ? extends org.dromara.sms4j.api.universal.SupplierConfig>> factoryList(@Qualifier("blends") Map<String, Map<String, Object>> blends, SmsConfig smsConfig) {
//注入自定义实现工厂
List<BaseProviderFactory<? extends SmsBlend, ? extends org.dromara.sms4j.api.universal.SupplierConfig>> factoryList = new ArrayList<>();
if (ConfigType.YAML.equals(smsConfig.getConfigType())) {
@ -55,7 +56,7 @@ public class SupplierConfig {
@Bean
protected SmsBlendsInitializer smsBlendsInitializer(List<BaseProviderFactory<? extends SmsBlend, ? extends org.dromara.sms4j.api.universal.SupplierConfig>> factoryList,
SmsConfig smsConfig,
Map<String, Map<String, Object>> blends,
@Qualifier("blends") Map<String, Map<String, Object>> blends,
ObjectProvider<SmsReadConfig> extendsSmsConfigs) {
return new SmsBlendsInitializer(factoryList, smsConfig, blends, extendsSmsConfigs);
}