diff --git a/pom.xml b/pom.xml
index aa98b54e..688ea769 100644
--- a/pom.xml
+++ b/pom.xml
@@ -17,8 +17,9 @@
sms4j-provider
sms4j-core
sms4j-spring-boot-starter
- sms4j-solon-plugin
sms4j-spring-boot-example
+ sms4j-solon-plugin
+ sms4j-solon-plugin-example
sms4j-javase-plugin
sms4j-Email-plugin
sms4j-oa-plugin
diff --git a/sms4j-solon-plugin-example/pom.xml b/sms4j-solon-plugin-example/pom.xml
new file mode 100644
index 00000000..2f3ff314
--- /dev/null
+++ b/sms4j-solon-plugin-example/pom.xml
@@ -0,0 +1,52 @@
+
+
+ 4.0.0
+
+
+ org.dromara.sms4j
+ sms4j
+ ${revision}
+ ../pom.xml
+
+
+ sms4j-solon-plugin-example
+
+
+ true
+ true
+
+
+
+
+ org.noear
+ solon-web
+ ${solon.version}
+
+
+
+ org.noear
+ solon-test-junit5
+ ${solon.version}
+ test
+
+
+ org.dromara.sms4j
+ sms4j-oa-core
+ ${revision}
+
+
+ org.dromara.sms4j
+ sms4j-solon-plugin
+ ${revision}
+
+
+
+ com.jdcloud.sdk
+ sms
+ ${jdcloud.version}
+
+
+
+
\ No newline at end of file
diff --git a/sms4j-solon-plugin-example/src/main/java/org/dromara/sms4j/example/Sms4jApp.java b/sms4j-solon-plugin-example/src/main/java/org/dromara/sms4j/example/Sms4jApp.java
new file mode 100644
index 00000000..c1a9ca95
--- /dev/null
+++ b/sms4j-solon-plugin-example/src/main/java/org/dromara/sms4j/example/Sms4jApp.java
@@ -0,0 +1,15 @@
+package org.dromara.sms4j.example;
+
+import org.noear.solon.Solon;
+
+/**
+ * 主类
+ *
+ * @author handy
+ */
+public class Sms4jApp {
+
+ public static void main(String[] args) {
+ Solon.start(Sms4jApp.class, args);
+ }
+}
diff --git a/sms4j-solon-plugin-example/src/main/java/org/dromara/sms4j/example/zhangjun/ZhangJunApp.java b/sms4j-solon-plugin-example/src/main/java/org/dromara/sms4j/example/zhangjun/ZhangJunApp.java
new file mode 100644
index 00000000..a50d0669
--- /dev/null
+++ b/sms4j-solon-plugin-example/src/main/java/org/dromara/sms4j/example/zhangjun/ZhangJunApp.java
@@ -0,0 +1,18 @@
+package org.dromara.sms4j.example.zhangjun;
+
+import org.dromara.sms4j.core.factory.SmsFactory;
+import org.noear.solon.Solon;
+
+/**
+ * 自定义广州掌骏短信实现
+ *
+ * @author 4n
+ */
+public class ZhangJunApp {
+
+ public static void main(String[] args) {
+ Solon.start(ZhangJunApp.class, args);
+ SmsFactory.getBySupplier("zhangjun").sendMessage("17*****598", "154468");
+ }
+
+}
diff --git a/sms4j-solon-plugin-example/src/main/java/org/dromara/sms4j/example/zhangjun/ZhangJunConfig.java b/sms4j-solon-plugin-example/src/main/java/org/dromara/sms4j/example/zhangjun/ZhangJunConfig.java
new file mode 100644
index 00000000..ecef072c
--- /dev/null
+++ b/sms4j-solon-plugin-example/src/main/java/org/dromara/sms4j/example/zhangjun/ZhangJunConfig.java
@@ -0,0 +1,22 @@
+package org.dromara.sms4j.example.zhangjun;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.dromara.sms4j.provider.config.BaseConfig;
+
+/**
+ * @author 4n
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class ZhangJunConfig extends BaseConfig {
+ private String appId;
+ private String sid;
+ private String url;
+
+ @Override
+ public String getSupplier() {
+ return "zhangjun";
+ }
+
+}
diff --git a/sms4j-solon-plugin-example/src/main/java/org/dromara/sms4j/example/zhangjun/ZhangJunFactory.java b/sms4j-solon-plugin-example/src/main/java/org/dromara/sms4j/example/zhangjun/ZhangJunFactory.java
new file mode 100644
index 00000000..b982d70b
--- /dev/null
+++ b/sms4j-solon-plugin-example/src/main/java/org/dromara/sms4j/example/zhangjun/ZhangJunFactory.java
@@ -0,0 +1,26 @@
+package org.dromara.sms4j.example.zhangjun;
+
+import lombok.NoArgsConstructor;
+import org.dromara.sms4j.provider.factory.AbstractProviderFactory;
+
+/**
+ *
+ *
掌骏短信
+ *
+ * @author :4n
+ * 2023/10/31 14:54
+ **/
+@NoArgsConstructor
+public class ZhangJunFactory extends AbstractProviderFactory {
+
+ @Override
+ public ZhangJunSmsImpl createSms(ZhangJunConfig ZhangJunConfig) {
+ return new ZhangJunSmsImpl(ZhangJunConfig);
+ }
+
+ @Override
+ public String getSupplier() {
+ return "zhangjun";
+ }
+
+}
diff --git a/sms4j-solon-plugin-example/src/main/java/org/dromara/sms4j/example/zhangjun/ZhangJunSmsImpl.java b/sms4j-solon-plugin-example/src/main/java/org/dromara/sms4j/example/zhangjun/ZhangJunSmsImpl.java
new file mode 100644
index 00000000..55f9192b
--- /dev/null
+++ b/sms4j-solon-plugin-example/src/main/java/org/dromara/sms4j/example/zhangjun/ZhangJunSmsImpl.java
@@ -0,0 +1,119 @@
+package org.dromara.sms4j.example.zhangjun;
+
+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.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 java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Executor;
+
+/**
+ * @author :4n
+ **/
+@Slf4j
+public class ZhangJunSmsImpl extends AbstractSmsBlend {
+
+ private int retry = 0;
+
+ /**
+ * ZhangJunSmsImpl
+ * 构造器,用于构造短信实现模块
+ *
+ * @author :Wind
+ */
+ public ZhangJunSmsImpl(ZhangJunConfig config, Executor pool, DelayedTime delayedTime) {
+ super(config, pool, delayedTime);
+ }
+
+ /**
+ * ZhangJunSmsImpl
+ *
构造器,用于构造短信实现模块
+ */
+ public ZhangJunSmsImpl(ZhangJunConfig config) {
+ super(config);
+ }
+
+ @Override
+ public String getSupplier() {
+ return "zhangjun";
+ }
+ private LinkedHashMap buildBody(String phone, String message){
+ LinkedHashMap map = new LinkedHashMap<>();
+ map.put("appId", getConfig().getAppId());
+ map.put("sid", getConfig().getSid());
+ map.put("templateId", getConfig().getTemplateId());
+ map.put("phone", phone);
+ Map data = new HashMap<>();
+ data.put("code", message);
+ map.put("data", JSONUtil.toJsonStr(data));
+ return map;
+ }
+ @Override
+ public SmsResponse sendMessage(String phone, String message) {
+ return sendMessage(phone, getConfig().getTemplateId(), buildBody(phone,message));
+ }
+
+ @Override
+ public SmsResponse sendMessage(String phone, LinkedHashMap messages) {
+ return sendMessage(phone, getConfig().getTemplateId(), messages);
+ }
+
+ @Override
+ public SmsResponse sendMessage(String phone, String templateId, LinkedHashMap messages) {
+ String messageStr = JSONUtil.toJsonStr(messages);
+ return getSmsResponse(phone, messageStr, templateId);
+ }
+
+ @Override
+ public SmsResponse massTexting(List phones, String message) {
+ LinkedHashMap map = new LinkedHashMap<>();
+// map.put(getConfig().getTemplateName(), message);
+ return massTexting(phones, getConfig().getTemplateId(), map);
+ }
+
+ @Override
+ public SmsResponse massTexting(List phones, String templateId, LinkedHashMap messages) {
+ String messageStr = JSONUtil.toJsonStr(messages);
+ return getSmsResponse(SmsUtils.arrayToString(phones), messageStr, templateId);
+ }
+
+ private SmsResponse getSmsResponse(String phone, String message, String templateId) {
+ SmsResponse smsResponse;
+ try {
+ smsResponse = getResponse(http.postJson(getConfig().getUrl(), null, message));
+ } catch (SmsBlendException e) {
+ smsResponse = new SmsResponse();
+ smsResponse.setSuccess(false);
+ smsResponse.setData(e.getMessage());
+ }
+ if (smsResponse.isSuccess() || retry == getConfig().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("短信第 {} 次重新发送", retry);
+ return getSmsResponse(phone, message, templateId);
+ }
+
+ private SmsResponse getResponse(JSONObject resJson) {
+ SmsResponse smsResponse = new SmsResponse();
+ smsResponse.setSuccess("OK".equals(resJson.getStr("Code")));
+ smsResponse.setData(resJson);
+ smsResponse.setConfigId(getConfigId());
+ return smsResponse;
+ }
+
+}
\ No newline at end of file
diff --git a/sms4j-solon-plugin-example/src/main/resources/app.yml b/sms4j-solon-plugin-example/src/main/resources/app.yml
new file mode 100644
index 00000000..7bfc48a3
--- /dev/null
+++ b/sms4j-solon-plugin-example/src/main/resources/app.yml
@@ -0,0 +1,144 @@
+sms:
+ # 标注从yml读取配置
+ config-type: yaml
+ # 账户上限
+ account-max: 1
+ blends:
+ # 阿里短信例子
+ ali:
+ #厂商标识,标定此配置是哪个厂商,详细请看厂商标识介绍部分
+ supplier: alibaba
+ #您的accessKey
+ access-key-id: 您的accessKey
+ #您的accessKeySecret
+ access-key-secret: 您的accessKeySecret
+ #您的短信签名
+ signature: 测试签名
+ #模板ID 非必须配置,如果使用sendMessage的快速发送需此配置
+ template-id: SMS_272470496
+ # 模版名称
+ templateName: code
+ # 腾讯短信例子
+ tx:
+ #厂商标识
+ supplier: tencent
+ #您的accessKey
+ access-key-id: 您的accessKey
+ #您的accessKeySecret
+ access-key-secret: 您的accessKeySecret
+ #您的短信签名
+ signature: 测试签名
+ #模板ID
+ template-id: 1603670
+ #您的sdkAppId
+ sdk-app-id: 1400761645
+ # 华为短信例子
+ hw:
+ #厂商标识
+ supplier: huawei
+ #您的accessKey
+ access-key-id: 您的accessKey
+ #您的accessKeySecret
+ access-key-secret: 您的accessKeySecret
+ #您的短信签名
+ signature: 测试签名
+ #模板ID
+ template-id: ac4888205c274b2a8263479b954c1ab5
+ # APP接入地址
+ url: https://smsapi.cn-north-4.myhuaweicloud.com:443
+ # 模版名称
+ templateName: code
+ # 通道号
+ sender: 8823040504797
+ # 合一短信例子
+ uni:
+ #厂商标识
+ supplier: unisms
+ #您的accessKey
+ access-key-id: 您的accessKey
+ #您的短信签名
+ signature: 测试签名
+ #模板ID
+ template-id: pub_verif_short
+ # 模版名称
+ templateName: code
+ # 渠道上限
+ maximum: 2
+ lianlu:
+ supplier: lianlu
+ templateId: 模板id
+ appId: 100116
+ appKey: d42d7
+ mchId: 100
+ signName: 【test】
+ cloopen:
+ # 短信厂商
+ supplier: cloopen
+ base-url: https://app.cloopen.com:8883/2013-12-26
+ access-key-id: 你的Access Key
+ access-key-secret: 你的Access Key Secret
+ sdkAppId: 你的应用ID
+ #自定义广州掌骏短信,添加factory全路径。config,factory,SmsImpl复制其他默认实现即可,修改对应的supplier和发送核心逻辑即可
+# zhangjun:
+# supplier: zhangjun
+# factory: org.dromara.sms4j.example.zhangjun.ZhangJunFactory
+# templateId: d2a****777
+# appId: 64c52d2a****77775fe72e3
+# sid: d2a****777
+# url: https://sms.idowe.com/**/**/**/send
+ qiniu:
+ access-key-id: EQcDflLTCYnU1******CmqIYLhog1lkWHb2
+ access-key-secret: NeS2ptvZQoIy*****err2DdLe7wxFfQvji1
+ templateId: 1752130****15859456
+ signatureId: 175185*****1624960
+ templateName: code
+ # 中国移动 云MAS
+ mas:
+ supplier: mas
+ # 请求方式默认为 HTTP
+ # 请求方法 默认为 HTTP模式下的 tmpsubmit
+ # norsubmit 无模板接口 不需要配置templateId
+ # tmpsubmit 有模板接口 需要配置templateId
+ # HTTPS 模式下 请求方法有 submit tmpsubmit
+ action: tmpsubmit
+ # 请求地址 HTTP模式下可不配置 默认为 http://112.35.1.155:1992/sms/
+ # HTTPS模式下 请设置 https://****:****/sms/
+ request-url: http://112.35.1.155:1992/sms/
+ sdk-app-id: 接口账号用户名
+ access-key-secret: 用户密码
+ ec-name: 企业名称
+ signature: 签名编码
+ # 当请求方法为 tmpsubmit 时 需要配置templateId
+ template-id:
+ # 可为空 不为空时请遵守中国移动云MAS开发文档中的描述[服务代码加扩展码总长度不能超过20位。]
+ add-serial:
+ # 中百度智能云 sms
+ baidu:
+ access-key-id: 访问密钥ID
+ access-key-secret: 用户密钥
+ ec-name: 企业名称
+ signature: 签名编码
+ template-id: 模板ID
+ # 模板变量名称
+ template-name: code
+ custom: 用户自定义参数,格式为字符串,状态回调时会回传该值 可不传
+ user-ext-id: 通道自定义扩展码 可不传
+
+sms-oa:
+ config-type: yaml
+ oas:
+ oaDingTalkByYaml: # configId
+ isEnable: true # 表示该配置是否生效(默认生效,false表示不生效)
+ supplier: dingding # 厂商标识
+ tokenId: 您的accessKey
+ sign: 您的sign
+ oaByteTalkByYaml: # configId
+ supplier: feishu # 厂商标识
+ tokenId: 您的accessKey
+ sign: 您的sign
+ oaWeTalkByYaml:
+ supplier: wetalk # 厂商标识
+ tokenId: 您的sign
+ core-pool-size: 20
+ queue-capacity: 20
+ max-pool-size: 20
\ No newline at end of file
diff --git a/sms4j-solon-plugin-example/src/test/java/org/dromara/sms4j/example/Sms4jTest.java b/sms4j-solon-plugin-example/src/test/java/org/dromara/sms4j/example/Sms4jTest.java
new file mode 100644
index 00000000..dfe796b7
--- /dev/null
+++ b/sms4j-solon-plugin-example/src/test/java/org/dromara/sms4j/example/Sms4jTest.java
@@ -0,0 +1,363 @@
+package org.dromara.sms4j.example;
+
+import cn.hutool.core.collection.ListUtil;
+import cn.hutool.core.lang.Assert;
+import cn.hutool.core.lang.UUID;
+import cn.hutool.core.map.MapUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.json.JSONUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.sms4j.api.SmsBlend;
+import org.dromara.sms4j.api.entity.SmsResponse;
+import org.dromara.sms4j.baidu.service.BaiduSmsImpl;
+import org.dromara.sms4j.comm.constant.SupplierConstant;
+import org.dromara.sms4j.comm.utils.SmsUtils;
+import org.dromara.sms4j.core.factory.SmsFactory;
+import org.dromara.sms4j.lianlu.service.LianLuSmsImpl;
+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;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+@Slf4j
+@ExtendWith(SolonJUnit5Extension.class)
+@SolonTest
+public class Sms4jTest {
+
+ /**
+ * 填测试手机号
+ */
+ private static final String PHONE = "";
+
+ @Test
+ public void byLoadTest() {
+ if (StrUtil.isBlank(PHONE)) {
+ return;
+ }
+ // 通过负载均衡服务获取短信服务对象
+ SmsResponse smsResponse = SmsFactory.getSmsBlend().sendMessage(PHONE, SmsUtils.getRandomInt(6));
+ Assert.isTrue(smsResponse.isSuccess());
+ }
+
+ @Test
+ public void alibabaSmsTest() {
+ // 阿里
+ SmsResponse smsResponse = SmsFactory.getBySupplier(SupplierConstant.ALIBABA).sendMessage(PHONE, SmsUtils.getRandomInt(6));
+ Assert.isTrue(smsResponse.isSuccess());
+ }
+
+ @Test
+ public void huaweiSmsTest() {
+ if (StrUtil.isBlank(PHONE)) {
+ return;
+ }
+ // 华为
+ SmsResponse smsResponse = SmsFactory.getBySupplier(SupplierConstant.HUAWEI).sendMessage(PHONE, SmsUtils.getRandomInt(6));
+ log.info(JSONUtil.toJsonStr(smsResponse));
+ Assert.isTrue(smsResponse.isSuccess());
+ }
+
+ @Test
+ public void cloopenSmsTest() {
+ if (StrUtil.isBlank(PHONE)) {
+ return;
+ }
+ // 容联云
+ Map messageMap = MapUtil.newHashMap(2, true);
+ messageMap.put("captcha", SmsUtils.getRandomInt(4));
+ messageMap.put("expirationInMinutes", "5");
+ SmsResponse smsResponse = SmsFactory.getBySupplier(SupplierConstant.CLOOPEN)
+ .sendMessage(PHONE, "1", (LinkedHashMap) messageMap);
+ log.info(JSONUtil.toJsonStr(smsResponse));
+ Assert.isTrue(smsResponse.isSuccess());
+ }
+
+ @Test
+ public void emaySmsTest() {
+ if (StrUtil.isBlank(PHONE)) {
+ return;
+ }
+ // 亿美软通
+ SmsResponse smsResponse = SmsFactory.getBySupplier(SupplierConstant.EMAY).sendMessage(PHONE, SmsUtils.getRandomInt(6));
+ log.info(JSONUtil.toJsonStr(smsResponse));
+ Assert.isTrue(smsResponse.isSuccess());
+ }
+
+ @Test
+ public void jdCloudSmsTest() {
+ if (StrUtil.isBlank(PHONE)) {
+ return;
+ }
+ // 京东云
+ SmsResponse smsResponse = SmsFactory.getBySupplier(SupplierConstant.JDCLOUD).sendMessage(PHONE, SmsUtils.getRandomInt(6));
+ log.info(JSONUtil.toJsonStr(smsResponse));
+ Assert.isTrue(smsResponse.isSuccess());
+ }
+
+ @Test
+ public void yunPianSmsTest() {
+ if (StrUtil.isBlank(PHONE)) {
+ return;
+ }
+ // 云片
+ SmsResponse smsResponse = SmsFactory.getBySupplier(SupplierConstant.YUNPIAN).sendMessage(PHONE, SmsUtils.getRandomInt(6));
+ log.info(JSONUtil.toJsonStr(smsResponse));
+ Assert.isTrue(smsResponse.isSuccess());
+ }
+
+ @Test
+ public void tencentSmsTest() {
+ if (StrUtil.isBlank(PHONE)) {
+ return;
+ }
+ LinkedHashMap newMap = SmsUtils.getNewMap();
+ // 验证码
+ newMap.put("1", SmsUtils.getRandomInt(4));
+ // 有效时间
+ newMap.put("2", "2");
+ SmsResponse smsResponse = SmsFactory.getBySupplier(SupplierConstant.TENCENT)
+ .sendMessage(PHONE, "1603670", newMap);
+ log.info(JSONUtil.toJsonStr(smsResponse));
+ Assert.isTrue(smsResponse.isSuccess());
+ }
+
+ @Test
+ public void uniSmsTest() {
+ if (StrUtil.isBlank(PHONE)) {
+ return;
+ }
+ // 合一
+ SmsResponse smsResponse = SmsFactory.getBySupplier(SupplierConstant.UNISMS).sendMessage(PHONE, SmsUtils.getRandomInt(6));
+ log.info(JSONUtil.toJsonStr(smsResponse));
+ Assert.isTrue(smsResponse.isSuccess());
+ }
+
+ @Test
+ public void cyYunSmsTest() {
+ if (StrUtil.isBlank(PHONE)) {
+ return;
+ }
+ // 天翼云
+ SmsResponse smsResponse = SmsFactory.getBySupplier(SupplierConstant.CTYUN).sendMessage(PHONE, SmsUtils.getRandomInt(6));
+ log.info(JSONUtil.toJsonStr(smsResponse));
+ Assert.isTrue(smsResponse.isSuccess());
+ }
+
+ @Test
+ public void neteaseSmsTest() {
+ if (StrUtil.isBlank(PHONE)) {
+ return;
+ }
+ // 网易云短信
+ SmsResponse smsResponse = SmsFactory.getBySupplier(SupplierConstant.NETEASE).sendMessage(PHONE, SmsUtils.getRandomInt(6));
+ log.info(JSONUtil.toJsonStr(smsResponse));
+ Assert.isTrue(smsResponse.isSuccess());
+ }
+
+ /**
+ * 助通短信测试1:无模板
+ */
+ @Test
+ public void zhutongSms1Test() {
+ if (StrUtil.isBlank(PHONE)) {
+ return;
+ }
+ // 助通短信短信
+ String msg = StrUtil.format("【图书商城】您好,你的验证码是{}:(5分钟失效)", SmsUtils.getRandomInt(6));
+ SmsResponse smsResponse = SmsFactory.getBySupplier(SupplierConstant.ZHUTONG).sendMessage(PHONE, msg);
+ log.info(JSONUtil.toJsonStr(smsResponse));
+ Assert.isTrue(smsResponse.isSuccess());
+ }
+
+ /**
+ * 助通短信测试2:有模板
+ */
+ @Test
+ public void zhutongSmsTest2Template() {
+ if (StrUtil.isBlank(PHONE)) {
+ return;
+ }
+ // 助通短信短信
+ LinkedHashMap messages = new LinkedHashMap<>(1);
+ messages.put("code", SmsUtils.getRandomInt(6));
+ SmsResponse smsResponse = SmsFactory.getBySupplier(SupplierConstant.ZHUTONG).sendMessage(PHONE, "59264", messages);
+ log.info(JSONUtil.toJsonStr(smsResponse));
+ Assert.isTrue(smsResponse.isSuccess());
+ }
+
+ /**
+ * 助通短信测试3:无模板群发
+ */
+ @Test
+ public void zhutongSms3MoreTest() {
+ if (StrUtil.isBlank(PHONE)) {
+ return;
+ }
+ // 助通短信短信
+ String msg = StrUtil.format("【图书商城】您好,你的验证码是{}:(5分钟失效)", SmsUtils.getRandomInt(6));
+ SmsResponse smsResponse = SmsFactory.getBySupplier(SupplierConstant.ZHUTONG).massTexting(ListUtil.of(PHONE, "180****1111"), msg);
+ log.info(JSONUtil.toJsonStr(smsResponse));
+ Assert.isTrue(smsResponse.isSuccess());
+ }
+
+ /**
+ * 助通短信测试4:有模板 多人群发
+ */
+ @Test
+ public void zhutongSms4TemplateTest() {
+ if (StrUtil.isBlank(PHONE)) {
+ return;
+ }
+ // 助通短信短信
+ LinkedHashMap messages = new LinkedHashMap<>(1);
+ messages.put("code", SmsUtils.getRandomInt(6));
+ SmsResponse smsResponse = SmsFactory.getBySupplier(SupplierConstant.ZHUTONG).massTexting(ListUtil.of(PHONE, "180****1111"), "59264", messages);
+ log.info(JSONUtil.toJsonStr(smsResponse));
+ Assert.isTrue(smsResponse.isSuccess());
+ }
+
+ /**
+ * 联麓模板短信
+ */
+ @Test
+ public void lianLuTemplateSmsTest() {
+ if (StrUtil.isBlank(PHONE)) {
+ return;
+ }
+ SmsResponse smsResponse = SmsFactory.getBySupplier(SupplierConstant.LIANLU)
+ .sendMessage(PHONE, SmsUtils.getRandomInt(6));
+ log.info(JSONUtil.toJsonStr(smsResponse));
+ Assert.isTrue(smsResponse.isSuccess());
+ }
+
+ /**
+ * 联麓普通短信
+ */
+ @Test
+ public void lianLuNormalSmsTest() {
+ if (StrUtil.isBlank(PHONE)) {
+ return;
+ }
+ LianLuSmsImpl lianLuSms = (LianLuSmsImpl) SmsFactory.getBySupplier(SupplierConstant.LIANLU);
+ SmsResponse smsResponse = lianLuSms.sendNormalMessage(PHONE, "测试短信" + SmsUtils.getRandomInt(6));
+ log.info(JSONUtil.toJsonStr(smsResponse));
+ Assert.isTrue(smsResponse.isSuccess());
+ }
+
+ /**
+ * 鼎众普通短信
+ */
+ @Test
+ public void dingZhongSmsTest() {
+ if (StrUtil.isBlank(PHONE)) {
+ return;
+ }
+ SmsBlend dz = SmsFactory.getBySupplier(SupplierConstant.DINGZHONG);
+
+ LinkedHashMap messages = new LinkedHashMap<>();
+ messages.put("code", SmsUtils.getRandomInt(6));
+
+ ArrayList phones = new ArrayList<>();
+ phones.add(PHONE);
+ phones.add(PHONE);
+
+ SmsResponse smsResponse = dz.sendMessage(PHONE, "测试短信" + SmsUtils.getRandomInt(6));
+ log.info(JSONUtil.toJsonStr(smsResponse));
+ Assert.isTrue(smsResponse.isSuccess());
+
+ SmsResponse smsResponse1 = dz.sendMessage(PHONE, messages);
+ log.info(JSONUtil.toJsonStr(smsResponse1));
+ Assert.isTrue(smsResponse1.isSuccess());
+
+ SmsResponse smsResponse3 = dz.massTexting(phones, "测试短信" + SmsUtils.getRandomInt(6));
+ log.info(JSONUtil.toJsonStr(smsResponse3));
+ Assert.isTrue(smsResponse3.isSuccess());
+
+ SmsResponse smsResponse4 = dz.massTexting(phones, "" ,messages);
+ log.info(JSONUtil.toJsonStr(smsResponse4));
+ Assert.isTrue(smsResponse4.isSuccess());
+
+ }
+
+ /**
+ * 中国移动 云MAS
+ */
+ @Test
+ public void masSmsTest() {
+ if (StrUtil.isBlank(PHONE)) {
+ return;
+ }
+ // 发送一对一/一对多普通短信
+ // HTTP模式下 action请配置为 norsubmit
+ // HTTPS模式下 action请配置为 submit
+ SmsResponse oneToMany = SmsFactory.getBySupplier(SupplierConstant.MAS)
+ .sendMessage(PHONE, "测试短信" + SmsUtils.getRandomInt(6));
+ log.info(JSONUtil.toJsonStr(oneToMany));
+
+ // 发送多对多普通短信
+ // HTTP模式下 action请配置为 norsubmit
+ // HTTPS模式下 action请配置为 submit
+ LinkedHashMap content = new LinkedHashMap<>();
+ content.put("18***1", "测试短信1");
+ content.put("18***2", "测试短信2");
+ content.put("18***3", "测试短信3");
+ content.put("18***4", "测试短信4");
+ SmsResponse manyToMany1 = SmsFactory.getBySupplier(SupplierConstant.MAS)
+ .sendMessage(PHONE, content);
+ log.info(JSONUtil.toJsonStr(manyToMany1));
+
+ // 或者
+ SmsResponse manyToMany2 = SmsFactory.getBySupplier(SupplierConstant.MAS)
+ .sendMessage(PHONE, JSONUtil.toJsonStr(content));
+ log.info(JSONUtil.toJsonStr(manyToMany2));
+
+ // 发送模板短信
+ // HTTP模式下或者HTTPS模式下 action请都配置为 tmpsubmit
+ // 无参数
+ SmsResponse strRes = SmsFactory.getBySupplier(SupplierConstant.MAS)
+ .sendMessage(PHONE, StrUtil.EMPTY);
+ log.info(JSONUtil.toJsonStr(strRes));
+
+ //数组格式
+ String[] paramsArr = {"param1", "param2"};
+ SmsResponse arrRes = SmsFactory.getBySupplier(SupplierConstant.MAS)
+ .sendMessage(PHONE, JSONUtil.toJsonStr(paramsArr));
+ log.info(JSONUtil.toJsonStr(arrRes));
+
+ //list格式
+ List paramsList = new ArrayList<>();
+ paramsList.add("param1");
+ paramsList.add("param2");
+ SmsResponse listRes = SmsFactory.getBySupplier(SupplierConstant.MAS)
+ .sendMessage(PHONE, JSONUtil.toJsonStr(paramsList));
+ log.info(JSONUtil.toJsonStr(listRes));
+ }
+
+ /**
+ * 百度短信
+ */
+ @Test
+ public void baiduSmsTest() {
+ if (StrUtil.isBlank(PHONE)) {
+ return;
+ }
+
+ // 发送短信
+ SmsResponse resp = SmsFactory.getBySupplier(SupplierConstant.BAIDU)
+ .sendMessage(PHONE, SmsUtils.getRandomInt(6));
+ log.info(JSONUtil.toJsonStr(resp));
+
+ // 发送携带幂等性参数短信
+ BaiduSmsImpl sendWithClientToken = (BaiduSmsImpl) SmsFactory.getBySupplier(SupplierConstant.BAIDU);
+ String clientToken = UUID.fastUUID().toString(true);
+ SmsResponse respWithClientToken = sendWithClientToken.sendMessageWithClientToken(PHONE,
+ SmsUtils.getRandomInt(6),
+ clientToken);
+ log.info(JSONUtil.toJsonStr(respWithClientToken));
+ }
+}
\ No newline at end of file
diff --git a/sms4j-solon-plugin-example/src/test/java/org/dromara/sms4j/example/SmsOaTest.java b/sms4j-solon-plugin-example/src/test/java/org/dromara/sms4j/example/SmsOaTest.java
new file mode 100644
index 00000000..f1c1d76d
--- /dev/null
+++ b/sms4j-solon-plugin-example/src/test/java/org/dromara/sms4j/example/SmsOaTest.java
@@ -0,0 +1,444 @@
+package org.dromara.sms4j.example;
+
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.oa.api.OaSender;
+import org.dromara.oa.comm.entity.Request;
+import org.dromara.oa.comm.entity.WeTalkRequestArticle;
+import org.dromara.oa.comm.enums.MessageType;
+import org.dromara.oa.core.byteTalk.config.ByteTalkConfig;
+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;
+import java.util.Random;
+import java.util.concurrent.CountDownLatch;
+
+
+@Slf4j
+@ExtendWith(SolonJUnit5Extension.class)
+@SolonTest
+public class SmsOaTest {
+ //***********************DingTalk-Test************************//
+ /**
+ * 填测试手机号
+ */
+ private static final String DingTalkPHONE = "";
+ /**
+ * 填access_token
+ */
+ private static final String DingTalkTOKENID = "";
+ /**
+ * 填secret
+ */
+ private static final String DingTalkSIGN = "";
+
+
+ /**
+ * DingTalk的Text测试
+ */
+ @Test
+ public void oaDingTalkText() {
+ String key = "oaDingTalk";
+ DingTalkConfig dingTalkConfig = new DingTalkConfig();
+ dingTalkConfig.setConfigId(key);
+ dingTalkConfig.setSign(DingTalkSIGN);
+ dingTalkConfig.setTokenId(DingTalkTOKENID);
+
+ // 根据配置创建服务实例并注册
+ OaFactory.createAndRegisterOaSender(dingTalkConfig);
+ OaSender alarm = OaFactory.getSmsOaBlend(key);
+
+ Request request = new Request();
+ ArrayList phones = new ArrayList<>();
+ phones.add(DingTalkPHONE);
+ // 支持通过手机号@
+ request.setPhoneList(phones);
+ // 支持@all
+// request.setIsNoticeAll(true);
+ request.setContent("测试消息");
+
+ alarm.sender(request, MessageType.DING_TALK_TEXT);
+
+ }
+
+ /**
+ * DingTalk的Markdown测试
+ */
+ @Test
+ public void oaDingTalkMarkdown() {
+ String key = "oaDingTalk";
+ DingTalkConfig dingTalkConfig = new DingTalkConfig();
+ dingTalkConfig.setConfigId(key);
+ dingTalkConfig.setSign(DingTalkSIGN);
+ dingTalkConfig.setTokenId(DingTalkTOKENID);
+
+ // 根据配置创建服务实例并注册
+ OaFactory.createAndRegisterOaSender(dingTalkConfig);
+ OaSender alarm = OaFactory.getSmsOaBlend(key);
+
+ Request request = new Request();
+ // 支持@all
+ request.setIsNoticeAll(true);
+ request.setContent("#### 杭州天气 @150XXXXXXXX \n > 9度,西北风1级,空气良89,相对温度73%\n > \n > ###### 10点20分发布 [天气](https://www.dingtalk.com) \n");
+ request.setTitle("标题");
+ alarm.sender(request, MessageType.DING_TALK_MARKDOWN);
+
+ }
+
+ /**
+ * DingTalk的Link测试
+ */
+ @Test
+ public void oaDingTalkLink() {
+ String key = "oaDingTalk";
+ DingTalkConfig dingTalkConfig = new DingTalkConfig();
+ dingTalkConfig.setConfigId(key);
+ dingTalkConfig.setSign(DingTalkSIGN);
+ dingTalkConfig.setTokenId(DingTalkTOKENID);
+
+ // 根据配置创建服务实例并注册
+ OaFactory.createAndRegisterOaSender(dingTalkConfig);
+ OaSender alarm = OaFactory.getSmsOaBlend(key);
+
+ Request request = new Request();
+ request.setContent("这个即将发布的新版本,创始人xx称它为红树林。而在此之前,每当面临重大升级,产品经理们都会取一个应景的代号,这一次,为什么是红树林");
+ request.setTitle("点击跳转到钉钉");
+ request.setMessageUrl("https://www.dingtalk.com/s?__biz=MzA4NjMwMTA2Ng==&mid=2650316842&idx=1&sn=60da3ea2b29f1dcc43a7c8e4a7c97a16&scene=2&srcid=09189AnRJEdIiWVaKltFzNTw&from=timeline&isappinstalled=0&key=&ascene=2&uin=&devicetype=android-23&version=26031933&nettype=WIFI");
+ request.setPicUrl("https://img.alicdn.com/tfs/TB1NwmBEL9TBuNjy1zbXXXpepXa-2400-1218.png");
+ alarm.sender(request, MessageType.DING_TALK_LINK);
+
+
+ }
+
+ /**
+ * DingTalk的异步消息发送
+ */
+ @Test
+ public void oaDingTalkAsyncTest() {
+ String key = "oaDingTalk";
+ DingTalkConfig dingTalkConfig = new DingTalkConfig();
+ dingTalkConfig.setConfigId(key);
+ dingTalkConfig.setSign(DingTalkSIGN);
+ dingTalkConfig.setTokenId(DingTalkTOKENID);
+
+ // 根据配置创建服务实例并注册
+ OaFactory.createAndRegisterOaSender(dingTalkConfig);
+ OaSender alarm = OaFactory.getSmsOaBlend(key);
+
+
+ Request request = new Request();
+ ArrayList phones = new ArrayList<>();
+ phones.add(DingTalkPHONE);
+ // 支持通过手机号@
+ request.setPhoneList(phones);
+ // 支持@all
+// request.setIsNoticeAll(true);
+ request.setContent("测试消息");
+
+ // 异步发送方式
+ alarm.senderAsync(request, MessageType.DING_TALK_TEXT);
+ alarm.senderAsync(request, MessageType.DING_TALK_TEXT, smsResponse -> System.out.println("ConfigId为" + smsResponse.getOaConfigId() + "的异步任务发送成功"));
+
+ try {
+ Thread.sleep(3000L);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ /**
+ * 异步优先级尽可能优先级高的消息先发送,但是获取响应会受网络影响
+ */
+ @Test
+ public void oaDingTalkAsyncByPriority() {
+ String key = "oaDingTalk";
+ DingTalkConfig dingTalkConfig = new DingTalkConfig();
+ dingTalkConfig.setConfigId(key);
+ dingTalkConfig.setSign(DingTalkSIGN);
+ dingTalkConfig.setTokenId(DingTalkTOKENID);
+
+ // 根据配置创建服务实例并注册
+ OaFactory.createAndRegisterOaSender(dingTalkConfig);
+ OaSender alarm = OaFactory.getSmsOaBlend(key);
+ CountDownLatch user = new CountDownLatch(1);
+ // 模拟10条不同优先级的消息
+ for (int i = 0; i < 3; i++) {
+ Random random = new Random();
+ new Thread(() -> {
+ int priority = random.nextInt(10);
+ try {
+ // 等待十个请求
+ System.out.println(priority + "等待");
+ user.await();
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+
+ Request request = new Request();
+ ArrayList phones = new ArrayList<>();
+ phones.add(DingTalkPHONE);
+ request.setPhoneList(phones);
+ request.setIsNoticeAll(false);
+ request.setPriority(priority);
+ //测试-1-TEXT
+ request.setContent("该消息优先级为" + priority);
+ alarm.senderAsyncByPriority(request, MessageType.DING_TALK_TEXT);
+ System.out.println("优先级为" + priority + "的异步任务已提交");
+
+ }).start();
+ }
+ System.out.println("开始模拟");
+ user.countDown();
+ // 防止主线程挂掉
+ try {
+ Thread.sleep(2000L);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Test
+ public void oaDingTalkByYamlTest() {
+ String configId = "oaDingTalkByYaml";
+ OaSender alarm = OaFactory.getSmsOaBlend(configId);
+ Request request = new Request();
+ ArrayList phones = new ArrayList<>();
+ phones.add(DingTalkPHONE);
+ // 支持通过手机号@
+ request.setPhoneList(phones);
+ // 支持@all
+// request.setIsNoticeAll(true);
+ request.setContent("测试消息");
+ alarm.sender(request, MessageType.DING_TALK_TEXT);
+ }
+ //***********************ByteTalk-Test************************//
+ /**
+ * 填测试手机号
+ */
+ private static final String ByteTalkUSERID = "";
+ /**
+ * 填access_token
+ */
+ private static final String ByteTalkTOKENID = "";
+ /**
+ * 填secret
+ */
+ private static final String ByteTalkSIGN = "";
+
+ /**
+ * ByteTalk的Text测试
+ */
+ @Test
+ public void oaByteTalkText() {
+ String key = "oaByteTalk";
+ ByteTalkConfig byteTalkConfig = new ByteTalkConfig();
+ byteTalkConfig.setConfigId(key);
+ byteTalkConfig.setTokenId(ByteTalkTOKENID);
+ byteTalkConfig.setSign(ByteTalkSIGN);
+ // 根据配置创建服务实例并注册
+ OaFactory.createAndRegisterOaSender(byteTalkConfig);
+ OaSender alarm = OaFactory.getSmsOaBlend(key);
+
+ Request request = new Request();
+ ArrayList userIds = new ArrayList<>();
+ userIds.add(ByteTalkUSERID);
+ //测试text
+ request.setUserIdList(userIds);
+ request.setIsNoticeAll(true);
+ request.setContent("测试消息");
+ alarm.sender(request, MessageType.BYTE_TALK_TEXT);
+ }
+
+
+ /**
+ * ByteTalk的异步消息发送
+ */
+ @Test
+ public void oaByteTalkAsyncText() {
+ String key = "oaByteTalk";
+ ByteTalkConfig byteTalkConfig = new ByteTalkConfig();
+ byteTalkConfig.setConfigId(key);
+ byteTalkConfig.setTokenId(ByteTalkTOKENID);
+ byteTalkConfig.setSign(ByteTalkSIGN);
+ // 根据配置创建服务实例并注册
+ OaFactory.createAndRegisterOaSender(byteTalkConfig);
+ OaSender alarm = OaFactory.getSmsOaBlend(key);
+
+ Request request = new Request();
+ ArrayList userIds = new ArrayList<>();
+ userIds.add(ByteTalkUSERID);
+ //测试text
+ request.setUserIdList(userIds);
+ request.setIsNoticeAll(true);
+ request.setContent("测试消息");
+
+ alarm.senderAsync(request, MessageType.BYTE_TALK_TEXT);
+ alarm.senderAsync(request, MessageType.BYTE_TALK_TEXT, smsResponse -> System.out.println("ConfigId为" + smsResponse.getOaConfigId() + "的异步任务发送成功"));
+
+ // 防止主线程挂掉
+ try {
+ Thread.sleep(3000L);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ @Test
+ public void oaByteTalkByYamlTest() {
+ String configId = "oaByteTalkByYaml";
+ OaSender alarm = OaFactory.getSmsOaBlend(configId);
+ Request request = new Request();
+ ArrayList userIds = new ArrayList<>();
+ userIds.add(ByteTalkUSERID);
+ //测试text
+ request.setUserIdList(userIds);
+ request.setIsNoticeAll(true);
+ request.setContent("测试消息");
+ alarm.sender(request, MessageType.BYTE_TALK_TEXT);
+ }
+ //***********************WeTalk-Test************************//
+ /**
+ * 填测试手机号
+ */
+ private static final String WeTalkPHONE = "";
+ /**
+ * 填测试UserId
+ */
+ private static final String WeTalkUSERID = "";
+ /**
+ * 填access_token
+ */
+ private static final String WeTalkTOKENID = "";
+
+ /**
+ * WeTalk的Text测试
+ */
+ @Test
+ public void oaWeTalkText() {
+ String key = "oaWeTalk";
+ WeTalkConfig WeTalkConfig = new WeTalkConfig();
+ WeTalkConfig.setConfigId(key);
+ WeTalkConfig.setTokenId(WeTalkTOKENID);
+
+ // 根据配置创建服务实例并注册
+ OaFactory.createAndRegisterOaSender(WeTalkConfig);
+ OaSender alarm = OaFactory.getSmsOaBlend(key);
+
+ Request request = new Request();
+ ArrayList phones = new ArrayList<>();
+ phones.add(WeTalkPHONE);
+ //测试text
+ request.setPhoneList(phones);
+ request.setIsNoticeAll(true);
+ request.setContent("测试消息");
+
+ alarm.sender(request, MessageType.WE_TALK_TEXT);
+
+ }
+
+ /**
+ * WeTalk的Markdown测试--不支持@all,只能通过userId进行
+ */
+ @Test
+ public void oaWeTalkMarkdown() {
+ String key = "oaWeTalk";
+ WeTalkConfig WeTalkConfig = new WeTalkConfig();
+ WeTalkConfig.setConfigId(key);
+ WeTalkConfig.setTokenId(WeTalkTOKENID);
+
+ // 根据配置创建服务实例并注册
+ OaFactory.createAndRegisterOaSender(WeTalkConfig);
+ OaSender alarm = OaFactory.getSmsOaBlend(key);
+
+ Request request = new Request();
+ // 管理后台-通讯录 账号就是userid,或者通过接口获取部门列表 再获取部门成员详情获取userid
+ ArrayList userIdList = new ArrayList<>();
+ userIdList.add(WeTalkUSERID);
+ request.setUserIdList(userIdList);
+
+ request.setContent(
+ "实时新增用户反馈132例,请相关同事注意。\n" +
+ ">类型:用户反馈" +
+ ">普通用户反馈:117例" +
+ ">VIP用户反馈:15例");
+
+ alarm.sender(request, MessageType.WE_TALK_MARKDOWN);
+
+
+ }
+
+ /**
+ * WeTalk的News测试
+ */
+ @Test
+ public void oaWeTalkNews() {
+ String key = "oaWeTalk";
+ WeTalkConfig WeTalkConfig = new WeTalkConfig();
+ WeTalkConfig.setConfigId(key);
+ WeTalkConfig.setTokenId(WeTalkTOKENID);
+
+ // 根据配置创建服务实例并注册
+ OaFactory.createAndRegisterOaSender(WeTalkConfig);
+ OaSender alarm = OaFactory.getSmsOaBlend(key);
+
+ Request request = new Request();
+ ArrayList articles = new ArrayList<>();
+ articles.add(new WeTalkRequestArticle("中秋节礼品领取", "今年中秋节公司有豪礼相送", "www.qq.com", "http://res.mail.qq.com/node/ww/wwopenmng/images/independent/doc/test_pic_msg1.png"));
+ request.setArticleList(articles);
+
+ alarm.sender(request, MessageType.WE_TALK_NEWS);
+ }
+
+ /**
+ * WeTalk的异步消息发送
+ */
+ @Test
+ public void oaWeTalkAsyncText() {
+ String key = "oaWeTalk";
+ WeTalkConfig WeTalkConfig = new WeTalkConfig();
+ WeTalkConfig.setConfigId(key);
+ WeTalkConfig.setTokenId(WeTalkTOKENID);
+
+ // 根据配置创建服务实例并注册
+ OaFactory.createAndRegisterOaSender(WeTalkConfig);
+ OaSender alarm = OaFactory.getSmsOaBlend(key);
+
+ Request request = new Request();
+ ArrayList phones = new ArrayList<>();
+ phones.add(WeTalkPHONE);
+ //测试text
+ request.setPhoneList(phones);
+ request.setIsNoticeAll(true);
+ request.setContent("测试消息");
+
+ // 异步发送方式
+ alarm.senderAsync(request, MessageType.WE_TALK_TEXT);
+ alarm.senderAsync(request, MessageType.WE_TALK_TEXT, smsResponse -> System.out.println("ConfigId为" + smsResponse.getOaConfigId() + "的异步任务发送成功"));
+
+ // 防止主线程挂掉
+ try {
+ Thread.sleep(3000L);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Test
+ public void oaWeTalkByYamlTest() {
+ String configId = "oaWeTalkByYaml";
+ OaSender alarm = OaFactory.getSmsOaBlend(configId);
+ Request request = new Request();
+ ArrayList phones = new ArrayList<>();
+ phones.add(WeTalkPHONE);
+ request.setPhoneList(phones);
+ request.setIsNoticeAll(true);
+ request.setContent("SMS4JContent");
+ alarm.sender(request, MessageType.WE_TALK_TEXT);
+ }
+}
+
+
+
diff --git a/sms4j-solon-plugin-example/src/test/java/org/dromara/sms4j/example/SmsProcessorTest.java b/sms4j-solon-plugin-example/src/test/java/org/dromara/sms4j/example/SmsProcessorTest.java
new file mode 100644
index 00000000..c5f28537
--- /dev/null
+++ b/sms4j-solon-plugin-example/src/test/java/org/dromara/sms4j/example/SmsProcessorTest.java
@@ -0,0 +1,192 @@
+package org.dromara.sms4j.example;
+
+import cn.hutool.core.lang.Assert;
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.sms4j.api.SmsBlend;
+import org.dromara.sms4j.api.entity.SmsResponse;
+import org.dromara.sms4j.comm.constant.SupplierConstant;
+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;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+
+/**
+ * @author sh1yu
+ */
+@Slf4j
+@ExtendWith(SolonJUnit5Extension.class)
+@SolonTest
+public class SmsProcessorTest {
+ /**
+ * 填测试手机号
+ */
+ private static final String PHONE = "11111111111";
+ private static final String PHONE1 = "22222222222";
+
+ //基础发送测试,即黑名单、账户限制、渠道限制都不预设直接发送(新增参数全为空)
+ @Test
+ public void test1() {
+ System.out.println("------------");
+ SmsBlend smsBlend = SmsFactory.getBySupplier(SupplierConstant.UNISMS);
+ SmsResponse smsResponse = smsBlend.sendMessage(PHONE, SmsUtils.getRandomInt(6));
+ Assert.isTrue(smsResponse.isSuccess());
+ System.out.println(smsResponse.getData());
+
+
+ }
+
+ //第二个账号的测试
+ @Test
+ public void test2() {
+ System.out.println("------------");
+
+ SmsBlend smsBlend = SmsFactory.getBySupplier(SupplierConstant.HUAWEI);
+ SmsResponse smsResponse = smsBlend.sendMessage(PHONE1, SmsUtils.getRandomInt(6));
+ Assert.isTrue(smsResponse.isSuccess());
+ System.out.println(smsResponse.getData());
+
+ }
+
+ //参数校验测试
+ @Test
+ public void test3() {
+ System.out.println("------------");
+
+ SmsBlendException knowEx = null;
+ try {
+ SmsFactory.getBySupplier(SupplierConstant.UNISMS).sendMessage(PHONE, new LinkedHashMap<>());
+ } catch (SmsBlendException e) {
+ knowEx = e;
+ System.out.println(knowEx.getMessage());
+ }
+ Assert.notNull(knowEx);
+ knowEx = null;
+ try {
+ SmsFactory.getBySupplier(SupplierConstant.UNISMS).sendMessage("", SmsUtils.getRandomInt(6));
+ } catch (SmsBlendException e) {
+ knowEx = e;
+ System.out.println(knowEx.getMessage());
+ }
+ Assert.notNull(knowEx);
+ knowEx = null;
+ try {
+ SmsFactory.getBySupplier(SupplierConstant.UNISMS).sendMessage(PHONE, "");
+ } catch (SmsBlendException e) {
+ knowEx = e;
+ System.out.println(knowEx.getMessage());
+ }
+ Assert.notNull(knowEx);
+ knowEx = null;
+ try {
+ SmsFactory.getBySupplier(SupplierConstant.UNISMS).sendMessage(PHONE, "111", new LinkedHashMap<>());
+ } catch (SmsBlendException e) {
+ knowEx = e;
+ System.out.println(knowEx.getMessage());
+ }
+ Assert.notNull(knowEx);
+ knowEx = null;
+ try {
+ SmsFactory.getBySupplier(SupplierConstant.UNISMS).massTexting(Collections.singletonList(PHONE), "");
+ } catch (SmsBlendException e) {
+ knowEx = e;
+ System.out.println(knowEx.getMessage());
+ }
+ Assert.notNull(knowEx);
+ knowEx = null;
+ try {
+ SmsFactory.getBySupplier(SupplierConstant.UNISMS).massTexting(Collections.singletonList(PHONE), "2222", new LinkedHashMap<>());
+ } catch (SmsBlendException e) {
+ knowEx = e;
+ System.out.println(knowEx.getMessage());
+ }
+ Assert.notNull(knowEx);
+ knowEx = null;
+ try {
+ SmsFactory.getBySupplier(SupplierConstant.UNISMS).massTexting(new ArrayList<>(), "321321");
+ } catch (SmsBlendException e) {
+ knowEx = e;
+ System.out.println(knowEx.getMessage());
+ }
+ Assert.notNull(knowEx);
+ }
+
+ //黑名单测试
+ @Test
+ public void test4() {
+ System.out.println("------------");
+
+ SmsBlend smsBlend = SmsFactory.getBySupplier(SupplierConstant.UNISMS);
+ //单黑名单添加
+ smsBlend.joinInBlacklist(PHONE);
+ SmsBlendException knowEx = null;
+ try {
+ smsBlend.sendMessage(PHONE, SmsUtils.getRandomInt(6));
+ } catch (SmsBlendException e) {
+ knowEx = e;
+ System.out.println(knowEx.getMessage());
+ }
+ Assert.notNull(knowEx);
+ //单黑名单移除
+ smsBlend.removeFromBlacklist(PHONE);
+ SmsResponse smsResponse = smsBlend.sendMessage(PHONE, SmsUtils.getRandomInt(6));
+ Assert.isTrue(smsResponse.isSuccess());
+ //批量黑名单添加
+ smsBlend.batchJoinBlacklist(Collections.singletonList(PHONE));
+ knowEx = null;
+ try {
+ smsBlend.sendMessage(PHONE, SmsUtils.getRandomInt(6));
+ } catch (SmsBlendException e) {
+ knowEx = e;
+ System.out.println(knowEx.getMessage());
+ }
+ Assert.notNull(knowEx);
+ //批量黑名单添加
+ smsBlend.batchRemovalFromBlacklist(Collections.singletonList(PHONE));
+ smsResponse = smsBlend.sendMessage(PHONE, SmsUtils.getRandomInt(6));
+ Assert.isTrue(smsResponse.isSuccess());
+
+ }
+
+ //账号级上限测试、需成功发送4笔,再发就会报错 参数配置 4
+ @Test
+ public void test5() {
+ System.out.println("------------");
+
+ SmsResponse smsResponse = SmsFactory.getBySupplier(SupplierConstant.UNISMS).sendMessage(PHONE, SmsUtils.getRandomInt(6));
+ Assert.isTrue(smsResponse.isSuccess());
+ SmsBlendException knowEx = null;
+ try {
+ SmsFactory.getBySupplier(SupplierConstant.UNISMS).sendMessage(PHONE, SmsUtils.getRandomInt(6));
+ } catch (SmsBlendException e) {
+ knowEx = e;
+ System.out.println(knowEx.getMessage());
+ }
+ Assert.notNull(knowEx);
+ }
+
+ //渠道级上限测试、需成功发送6笔,再发就会报错 参数配置 6
+ @Test
+ public void test6() {
+ System.out.println("------------");
+
+ SmsResponse smsResponse = SmsFactory.getBySupplier(SupplierConstant.UNISMS).sendMessage(PHONE1, SmsUtils.getRandomInt(6));
+ Assert.isTrue(smsResponse.isSuccess());
+
+ SmsBlendException knowEx = null;
+ try {
+ SmsFactory.getBySupplier(SupplierConstant.UNISMS).sendMessage(PHONE1, SmsUtils.getRandomInt(6));
+ } catch (SmsBlendException e) {
+ knowEx = e;
+ System.out.println(knowEx.getMessage());
+ }
+ Assert.notNull(knowEx);
+ }
+
+}
diff --git a/sms4j-solon-plugin-example/src/test/java/org/dromara/sms4j/example/SmsUtilsTest.java b/sms4j-solon-plugin-example/src/test/java/org/dromara/sms4j/example/SmsUtilsTest.java
new file mode 100644
index 00000000..c7a2a78a
--- /dev/null
+++ b/sms4j-solon-plugin-example/src/test/java/org/dromara/sms4j/example/SmsUtilsTest.java
@@ -0,0 +1,102 @@
+package org.dromara.sms4j.example;
+
+import cn.hutool.core.lang.Assert;
+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;
+import java.util.List;
+
+/**
+ * @author handy
+ */
+@Slf4j
+@ExtendWith(SolonJUnit5Extension.class)
+@SolonTest
+public class SmsUtilsTest {
+
+ @Test
+ public void getRandomString() {
+ String randomString = SmsUtils.getRandomString();
+ log.info(randomString);
+ Assert.isTrue(randomString.length() == 6);
+ }
+
+ @Test
+ public void testGetRandomString() {
+ String randomString = SmsUtils.getRandomString(4);
+ log.info(randomString);
+ Assert.isTrue(randomString.length() == 4);
+ }
+
+ @Test
+ public void getRandomInt() {
+ String randomInt = SmsUtils.getRandomInt(4);
+ log.info(randomInt);
+ Assert.isTrue(randomInt.length() == 4);
+ }
+
+ @Test
+ public void isEmpty() {
+ Assert.isTrue(SmsUtils.isEmpty(""));
+ }
+
+ @Test
+ public void isNotEmpty() {
+ Assert.isTrue(SmsUtils.isNotEmpty("not"));
+ }
+
+ @Test
+ public void jsonForObject() {
+ AlibabaConfig alibabaConfig = SmsUtils.jsonForObject("{'templateName':'Test'}", AlibabaConfig.class);
+ Assert.isTrue(alibabaConfig.getTemplateName().equals("Test"));
+ }
+
+ @Test
+ public void copyBean() {
+ AlibabaConfig alibabaConfig = SmsUtils.jsonForObject("{'templateName':'Test'}", AlibabaConfig.class);
+ AlibabaConfig alibabaConfig1 = new AlibabaConfig();
+ SmsUtils.copyBean(alibabaConfig, alibabaConfig1);
+ Assert.isTrue(alibabaConfig1.getTemplateName().equals("Test"));
+ }
+
+ @Test
+ public void getNewMap() {
+ SmsUtils.getNewMap();
+ }
+
+ @Test
+ public void listToString() {
+ List list = new ArrayList<>();
+ list.add("12312341234");
+ list.add("12312341235");
+ String str = SmsUtils.listToString(list);
+ log.info(str);
+ Assert.isTrue(str.equals("12312341234,12312341235"));
+ }
+
+ @Test
+ public void arrayToString() {
+ List list = new ArrayList<>();
+ list.add("12312341234");
+ list.add("12312341235");
+ String str = SmsUtils.arrayToString(list);
+ log.info(str);
+ Assert.isTrue(str.equals("+8612312341234,+8612312341235"));
+ }
+
+ @Test
+ public void listToArray() {
+ List list = new ArrayList<>();
+ list.add("12312341234");
+ list.add("12312341235");
+ String[] str = SmsUtils.listToArray(list);
+ Assert.isTrue(str[0].equals("+8612312341234") && str[1].equals("+8612312341235"));
+ }
+
+}