diff --git a/pom.xml b/pom.xml index b071a4f4..2c905845 100644 --- a/pom.xml +++ b/pom.xml @@ -23,6 +23,7 @@ sms-aggregation-huawei sms-aggregation-jdcloud sms-aggregation-cloopen + sms-aggregation-emay @@ -157,6 +158,12 @@ ${revision} + + kim.wind + sms-aggregation-emay + ${revision} + + com.aliyun diff --git a/sms-aggregation-autoimmit/src/main/java/org/dromara/sms/autoimmit/config/SupplierConfig.java b/sms-aggregation-autoimmit/src/main/java/org/dromara/sms/autoimmit/config/SupplierConfig.java index 06f89db0..01238d04 100644 --- a/sms-aggregation-autoimmit/src/main/java/org/dromara/sms/autoimmit/config/SupplierConfig.java +++ b/sms-aggregation-autoimmit/src/main/java/org/dromara/sms/autoimmit/config/SupplierConfig.java @@ -1,5 +1,6 @@ package org.dromara.sms.autoimmit.config; +import kim.wind.emay.config.EmayConfig; import org.dromara.sms.aliyun.config.AlibabaConfig; import org.dromara.sms.cloopen.config.CloopenConfig; import org.dromara.sms.core.config.SupplierFactory; @@ -61,6 +62,15 @@ public class SupplierConfig { return SupplierFactory.getCloopenConfig(); } + /** + * 亿美软通短信差异化配置 + */ + @Bean + @ConfigurationProperties(prefix = "sms.emay") + protected EmayConfig emayConfig(){ + return SupplierFactory.getEmayConfig(); + } + /** 为的是延后执行*/ protected void init(){ diff --git a/sms-aggregation-comm/src/main/java/org/dromara/sms/comm/enumerate/SupplierType.java b/sms-aggregation-comm/src/main/java/org/dromara/sms/comm/enumerate/SupplierType.java index 2b5e49d4..b6c1b46e 100644 --- a/sms-aggregation-comm/src/main/java/org/dromara/sms/comm/enumerate/SupplierType.java +++ b/sms-aggregation-comm/src/main/java/org/dromara/sms/comm/enumerate/SupplierType.java @@ -21,6 +21,11 @@ public enum SupplierType { JD_CLOUD("京东云短信"), /** 容联云 */ CLOOPEN("容联云短信"), + + /** + * 亿美软通 + */ + EMAY("亿美软通"), ; diff --git a/sms-aggregation-core/pom.xml b/sms-aggregation-core/pom.xml index 0d42b94c..2f27a4af 100644 --- a/sms-aggregation-core/pom.xml +++ b/sms-aggregation-core/pom.xml @@ -46,6 +46,11 @@ sms-aggregation-jdcloud + + kim.wind + sms-aggregation-emay + + kim.wind sms-aggregation-cloopen diff --git a/sms-aggregation-core/src/main/java/org/dromara/sms/core/config/SupplierFactory.java b/sms-aggregation-core/src/main/java/org/dromara/sms/core/config/SupplierFactory.java index 35d29e21..e54c223d 100644 --- a/sms-aggregation-core/src/main/java/org/dromara/sms/core/config/SupplierFactory.java +++ b/sms-aggregation-core/src/main/java/org/dromara/sms/core/config/SupplierFactory.java @@ -1,5 +1,6 @@ package org.dromara.sms.core.config; +import kim.wind.emay.config.EmayConfig; import org.dromara.sms.aliyun.config.AlibabaConfig; import org.dromara.sms.cloopen.config.CloopenConfig; import org.dromara.sms.huawei.config.HuaweiConfig; @@ -39,6 +40,11 @@ public class SupplierFactory { /** 容联云短信差异配置 */ private static CloopenConfig cloopenConfig; + /** + * 亿美软通短信差异配置 + */ + private static EmayConfig emayConfig; + /** 阿里云配置获取*/ public static AlibabaConfig getAlibabaConfig() { if (alibabaConfig == null){ @@ -94,4 +100,14 @@ public class SupplierFactory { } return cloopenConfig; } + + /** + * 亿美软通配置获取 + */ + public static EmayConfig getEmayConfig() { + if (emayConfig == null) { + emayConfig = new EmayConfig(); + } + return emayConfig; + } } diff --git a/sms-aggregation-core/src/main/java/org/dromara/sms/core/factory/SmsFactory.java b/sms-aggregation-core/src/main/java/org/dromara/sms/core/factory/SmsFactory.java index f6fb4135..5f25c5ea 100644 --- a/sms-aggregation-core/src/main/java/org/dromara/sms/core/factory/SmsFactory.java +++ b/sms-aggregation-core/src/main/java/org/dromara/sms/core/factory/SmsFactory.java @@ -1,5 +1,6 @@ package org.dromara.sms.core.factory; +import kim.wind.emay.config.EmaySmsConfig; import org.dromara.sms.aliyun.config.AlibabaSmsConfig; import org.dromara.sms.api.SmsBlend; import org.dromara.sms.cloopen.config.CloopenSmsConfig; @@ -14,20 +15,25 @@ import org.dromara.sms.unisms.config.UniSmsConfig; /** * SmsFactory *

+ * * @author :Wind * 2023/4/8 15:55 **/ public class SmsFactory { - private SmsFactory(){}; + private SmsFactory() { + } + + ; /** - * createSmsBlend + * createSmsBlend *

获取各个厂商的实现类 + * * @param supplierType 厂商枚举 * @author :Wind - */ - public static SmsBlend createSmsBlend(SupplierType supplierType){ - switch (supplierType){ + */ + public static SmsBlend createSmsBlend(SupplierType supplierType) { + switch (supplierType) { case ALIBABA: return AlibabaSmsConfig.createAlibabaSms(SupplierFactory.getAlibabaConfig()); case HUAWEI: @@ -40,6 +46,8 @@ public class SmsFactory { return JdCloudSmsConfig.createJdCloudSms(SupplierFactory.getJdCloudConfig()); case CLOOPEN: return CloopenSmsConfig.createCloopenSms(SupplierFactory.getCloopenConfig()); + case EMAY: + return EmaySmsConfig.createEmaySms(SupplierFactory.getEmayConfig()); } throw new SmsBlendException("An attempt to construct a SmsBlend object failed. Please check that the enumeration is valid"); } diff --git a/sms-aggregation-emay/.flattened-pom.xml b/sms-aggregation-emay/.flattened-pom.xml new file mode 100644 index 00000000..06687730 --- /dev/null +++ b/sms-aggregation-emay/.flattened-pom.xml @@ -0,0 +1,34 @@ + + + 4.0.0 + + kim.wind + sms_aggregation + 1.0.5 + + kim.wind + sms-aggregation-emay + 1.0.5 + sms-aggregation-emay + sms-aggregation-emay + + + Apache 2 + http://www.apache.org/licenses/LICENSE-2.0.txt + repo + A business-friendly OSS license + + + + + kim.wind + sms-aggregation-comm + + + kim.wind + sms-aggregation-api + + + + diff --git a/sms-aggregation-emay/.mvn/wrapper/maven-wrapper.jar b/sms-aggregation-emay/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 00000000..bf82ff01 Binary files /dev/null and b/sms-aggregation-emay/.mvn/wrapper/maven-wrapper.jar differ diff --git a/sms-aggregation-emay/.mvn/wrapper/maven-wrapper.properties b/sms-aggregation-emay/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 00000000..ca5ab4ba --- /dev/null +++ b/sms-aggregation-emay/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.7/apache-maven-3.8.7-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar diff --git a/sms-aggregation-emay/pom.xml b/sms-aggregation-emay/pom.xml new file mode 100644 index 00000000..0228d4aa --- /dev/null +++ b/sms-aggregation-emay/pom.xml @@ -0,0 +1,37 @@ + + + 4.0.0 + + kim.wind + sms_aggregation + ${revision} + ../pom.xml + + sms-aggregation-emay + ${revision} + sms-aggregation-emay + sms-aggregation-emay + + + + + + + + + kim.wind + sms-aggregation-comm + + + + kim.wind + sms-aggregation-api + + + + + + + + diff --git a/sms-aggregation-emay/src/main/java/kim/wind/emay/config/EmayConfig.java b/sms-aggregation-emay/src/main/java/kim/wind/emay/config/EmayConfig.java new file mode 100644 index 00000000..a2b27ed4 --- /dev/null +++ b/sms-aggregation-emay/src/main/java/kim/wind/emay/config/EmayConfig.java @@ -0,0 +1,17 @@ +package kim.wind.emay.config; + +import lombok.Data; + +/** + * @author Richard + * @date 2023-04-11 12:00 + */ +@Data +public class EmayConfig { + /** appKey*/ + private String appId ; + /** appSecret */ + private String secretKey ; + /** APP接入地址*/ + private String requestUrl; +} diff --git a/sms-aggregation-emay/src/main/java/kim/wind/emay/config/EmaySmsConfig.java b/sms-aggregation-emay/src/main/java/kim/wind/emay/config/EmaySmsConfig.java new file mode 100644 index 00000000..5e3b065f --- /dev/null +++ b/sms-aggregation-emay/src/main/java/kim/wind/emay/config/EmaySmsConfig.java @@ -0,0 +1,40 @@ +package kim.wind.emay.config; + +import kim.wind.emay.service.EmaySmsImpl; +import org.dromara.sms.comm.factory.BeanFactory; + +/** + * EmaySmsConfig + *

Emay短信对象建造 + * + * @author Richard + * @date 2023/04/11 12:00 + * */ +public class EmaySmsConfig { + private static EmaySmsImpl emaySms; + private static EmaySmsConfig emaySmsConfig; + + private EmaySmsConfig() { + } + + /** 建造一个亿美软通短信实现*/ + public static EmaySmsImpl createEmaySms(EmayConfig emayConfig) { + if (emaySmsConfig == null){ + emaySmsConfig = new EmaySmsConfig(); + } + if (emaySms == null){ + emaySms = new EmaySmsImpl(emayConfig, BeanFactory.getExecutor(),BeanFactory.getDelayedTime()); + } + return emaySms; + } + + /** 刷新对象*/ + public static EmaySmsImpl refresh(EmayConfig emayConfig){ + if (emaySmsConfig == null){ + emaySmsConfig = new EmaySmsConfig(); + } + emaySms = new EmaySmsImpl(emayConfig, BeanFactory.getExecutor(),BeanFactory.getDelayedTime()); + return emaySms; + } + +} diff --git a/sms-aggregation-emay/src/main/java/kim/wind/emay/service/EmaySmsImpl.java b/sms-aggregation-emay/src/main/java/kim/wind/emay/service/EmaySmsImpl.java new file mode 100644 index 00000000..d925233e --- /dev/null +++ b/sms-aggregation-emay/src/main/java/kim/wind/emay/service/EmaySmsImpl.java @@ -0,0 +1,193 @@ +package kim.wind.emay.service; + +import com.alibaba.fastjson.JSONObject; +import com.dtflys.forest.config.ForestConfiguration; +import kim.wind.emay.config.EmayConfig; +import kim.wind.emay.util.EmayBuilder; +import lombok.extern.slf4j.Slf4j; +import org.dromara.sms.api.SmsBlend; +import org.dromara.sms.api.callback.CallBack; +import org.dromara.sms.api.entity.SmsResponse; +import org.dromara.sms.comm.annotation.Restricted; +import org.dromara.sms.comm.delayedTime.DelayedTime; +import org.dromara.sms.comm.exception.SmsBlendException; +import org.dromara.sms.comm.factory.BeanFactory; + +import java.util.*; +import java.util.concurrent.Executor; +import java.util.concurrent.atomic.AtomicReference; + +import static org.dromara.sms.comm.utils.SmsUtil.listToString; + +/** + * @author Richard + * @date 2023-04-11 12:00 + */ +@Slf4j +public class EmaySmsImpl implements SmsBlend { + public EmaySmsImpl(EmayConfig config, Executor pool, DelayedTime delayed) { + this.config = config; + this.pool = pool; + this.delayed = delayed; + } + + private EmayConfig config; + + private Executor pool; + + private DelayedTime delayed; + + private final ForestConfiguration http = BeanFactory.getForestConfiguration(); + + @Override + @Restricted + public SmsResponse sendMessage(String phone, String message) { + String url = config.getRequestUrl(); + Map params; + try { + params = EmayBuilder.buildRequestBody(config.getAppId(), config.getSecretKey(), phone, message); + } catch (SmsBlendException e) { + SmsResponse smsResponse = new SmsResponse(); + smsResponse.setErrMessage(e.getMessage()); + return smsResponse; + } + return getSendResponse(params, url); + } + + @Override + @Restricted + public SmsResponse sendMessage(String phone, String templateId, LinkedHashMap messages) { + List list = new ArrayList<>(); + for (Map.Entry entry : messages.entrySet()) { + list.add(entry.getValue()); + } + return sendMessage(phone, EmayBuilder.listToString(list)); + } + + @Override + @Restricted + public SmsResponse massTexting(List phones, String message) { + if (phones.size() > 500) { + throw new SmsBlendException("单次发送超过最大发送上限,建议每次群发短信人数低于500"); + } + return sendMessage(listToString(phones), message); + } + + @Override + @Restricted + public SmsResponse massTexting(List phones, String templateId, LinkedHashMap messages) { + if (phones.size() > 500) { + throw new SmsBlendException("单次发送超过最大发送上限,建议每次群发短信人数低于500"); + } + List list = new ArrayList<>(); + for (Map.Entry entry : messages.entrySet()) { + list.add(entry.getValue()); + } + return sendMessage(listToString(phones), EmayBuilder.listToString(list)); + } + + @Override + @Restricted + public void sendMessageAsync(String phone, String message, CallBack callBack) { + pool.execute(() -> { + SmsResponse smsResponse = sendMessage(phone, message); + callBack.callBack(smsResponse); + }); + } + + @Override + @Restricted + public void sendMessageAsync(String phone, String message) { + pool.execute(() -> sendMessage(phone, message)); + } + + @Override + @Restricted + public void sendMessageAsync(String phone, String templateId, LinkedHashMap messages, CallBack callBack) { + pool.execute(() -> { + SmsResponse smsResponse = sendMessage(phone, templateId, messages); + callBack.callBack(smsResponse); + }); + } + + @Override + @Restricted + public void sendMessageAsync(String phone, String templateId, LinkedHashMap messages) { + pool.execute(() -> sendMessage(phone, templateId, messages)); + } + + @Override + @Restricted + public void delayedMessage(String phone, String message, Long delayedTime) { + this.delayed.schedule(new TimerTask() { + @Override + public void run() { + sendMessage(phone, message); + } + }, delayedTime); + } + + @Override + @Restricted + public void delayedMessage(String phone, String templateId, LinkedHashMap messages, Long delayedTime) { + this.delayed.schedule(new TimerTask() { + @Override + public void run() { + sendMessage(phone, templateId, messages); + } + }, delayedTime); + } + + @Override + @Restricted + public void delayMassTexting(List phones, String message, Long delayedTime) { + this.delayed.schedule(new TimerTask() { + @Override + public void run() { + massTexting(phones, message); + } + }, delayedTime); + } + + @Override + @Restricted + public void delayMassTexting(List phones, String templateId, LinkedHashMap messages, Long delayedTime) { + this.delayed.schedule(new TimerTask() { + @Override + public void run() { + massTexting(phones, templateId, messages); + } + }, delayedTime); + } + + private SmsResponse getSendResponse(Map body, String requestUrl) { + AtomicReference smsResponse = new AtomicReference<>(); + http.post(requestUrl) + .addBody(body) + .onSuccess(((data, req, res) -> { + JSONObject jsonBody = res.get(JSONObject.class); + smsResponse.set(getSmsResponse(jsonBody)); + })) + .onError((ex, req, res) -> { + JSONObject jsonBody = res.get(JSONObject.class); + smsResponse.set(getSmsResponse(jsonBody)); + }) + .execute(); + + return smsResponse.get(); + } + + + private static SmsResponse getSmsResponse(JSONObject execute) { + SmsResponse smsResponse = new SmsResponse(); + String code = execute.getString("code"); + smsResponse.setCode(code); + if ("success".equalsIgnoreCase(code)) { + JSONObject data = execute.getJSONObject("data"); + String smsId = data.getString("smsId"); + smsResponse.setBizId(smsId); + } + smsResponse.setData(execute); + return smsResponse; + } +} diff --git a/sms-aggregation-emay/src/main/java/kim/wind/emay/util/EmayBuilder.java b/sms-aggregation-emay/src/main/java/kim/wind/emay/util/EmayBuilder.java new file mode 100644 index 00000000..ae49bb8e --- /dev/null +++ b/sms-aggregation-emay/src/main/java/kim/wind/emay/util/EmayBuilder.java @@ -0,0 +1,77 @@ +package kim.wind.emay.util; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.crypto.SecureUtil; +import lombok.extern.slf4j.Slf4j; +import org.dromara.sms.comm.exception.SmsBlendException; + +import java.net.URLEncoder; +import java.time.format.DateTimeFormatter; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author Richard + * @version 1.0 + * @date 2023/4/11 15:11 + */ +@Slf4j +public class EmayBuilder { + + + public static Map buildRequestBody(String appId, String secretKey, String phone, + String message) throws SmsBlendException { + return getParamsMap(appId, secretKey, phone, message); + } + + + /** + * @param appId 用户Appid(必填) + * @param secretKey 加密key + * @param phone + * @param message + * @param customSmsId 自定义消息ID(选填) 最长64位 + * @return + * @throws SmsBlendException + */ + public static Map buildRequestBody(String appId, String secretKey, String phone, + String message, String customSmsId) throws SmsBlendException { + Map params = getParamsMap(appId, secretKey, phone, message); + params.put("customSmsId", customSmsId); + return params; + } + + private static Map getParamsMap(String appId, String secretKey, String phone, String message) { + Map params = new HashMap<>(); + // 时间戳(必填) 格式:yyyyMMddHHmmss + String timestamp = DateUtil.format(new Date(), DateTimeFormatter.ofPattern("yyyyMMddHHmmss")); + String sign = SecureUtil.md5(appId + secretKey + timestamp); + params.put("appId", appId); + params.put("timestamp", timestamp); + params.put("sign", sign); + params.put("mobiles", phone); + try { + params.put("content", URLEncoder.encode(message, "utf-8")); + } catch (Exception e) { + log.error("EmaySmsImpl urlEncode content error", e); + throw new SmsBlendException(e.getMessage()); + } + return params; + } + + public static String listToString(List list) { + StringBuilder stringBuffer = new StringBuilder(); + stringBuffer.append("[\""); + for (String s : list) { + stringBuffer.append(s); + stringBuffer.append("\""); + stringBuffer.append(","); + } + stringBuffer.deleteCharAt(stringBuffer.length() - 1); + stringBuffer.append("]"); + return stringBuffer.toString(); + } + +} diff --git a/sms-aggregation-emay/src/main/resources/application.properties b/sms-aggregation-emay/src/main/resources/application.properties new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/sms-aggregation-emay/src/main/resources/application.properties @@ -0,0 +1 @@ +