集成梦网科技短信发送服务 - 实现 config、factory、smsBlend 接口

This commit is contained in:
SU 2025-04-23 17:12:37 +08:00
parent dc607312e1
commit 9c30da1103
4 changed files with 303 additions and 0 deletions

View File

@ -0,0 +1,41 @@
package org.dromara.sms4j.montnets.config;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.sms4j.comm.constant.SupplierConstant;
import org.dromara.sms4j.provider.config.BaseConfig;
/**
* @author SU
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class MontnetsConfig extends BaseConfig {
/**
* 请求地址
*/
private String url;
/**
* 接口名称
*/
private String api;
/**
* 模板code
*/
private String templateId;
/**
* 模板变量名称
*/
private String templateParam;
/**
* 获取供应商
*/
@Override
public String getSupplier() {
return SupplierConstant.MONTNETS;
}
}

View File

@ -0,0 +1,48 @@
package org.dromara.sms4j.montnets.config;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.dromara.sms4j.comm.constant.SupplierConstant;
import org.dromara.sms4j.montnets.service.MontnetsSmsImpl;
import org.dromara.sms4j.provider.factory.AbstractProviderFactory;
/**
* MontnetsSmsConfig
* <p> 梦网对象建造者
*
* @author :SU
* 2025/4/23 10:32
**/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class MontnetsFactory extends AbstractProviderFactory<MontnetsSmsImpl, MontnetsConfig> {
private static final MontnetsFactory INSTANCE = new MontnetsFactory();
/**
* 获取建造者实例
* @return 建造者实例
*/
public static MontnetsFactory instance() {
return INSTANCE;
}
/**
* 创建短信实现对象
* @param montnetsConfig 短信配置对象
* @return 短信实现对象
*/
@Override
public MontnetsSmsImpl createSms(MontnetsConfig montnetsConfig) {
return new MontnetsSmsImpl(montnetsConfig);
}
/**
* 获取供应商
* @return 供应商
*/
@Override
public String getSupplier() {
return SupplierConstant.MONTNETS;
}
}

View File

@ -0,0 +1,152 @@
package org.dromara.sms4j.montnets.service;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.net.URLDecoder;
import cn.hutool.core.net.URLEncodeUtil;
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.comm.constant.Constant;
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.montnets.config.MontnetsConfig;
import org.dromara.sms4j.montnets.utils.MontnetsUtils;
import org.dromara.sms4j.provider.service.AbstractSmsBlend;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.Executor;
/**
* <p>类名: MontnetsSmsImpl
* <p>说明 梦网短信实现
*
* @author :SU
* 2025/4/23 10:32
**/
@Slf4j
public class MontnetsSmsImpl extends AbstractSmsBlend<MontnetsConfig> {
private int retry = 0;
/**
* MontnetsSmsImpl
* <p>构造器用于构造短信实现模块
*/
public MontnetsSmsImpl(MontnetsConfig config, Executor pool, DelayedTime delayedTime) {
super(config, pool, delayedTime);
}
/**
* MontnetsSmsImpl
* <p>构造器用于构造短信实现模块
*/
public MontnetsSmsImpl(MontnetsConfig config) {
super(config);
}
@Override
public String getSupplier() {
return SupplierConstant.MONTNETS;
}
@Override
public SmsResponse sendMessage(String phone, String message) {
LinkedHashMap<String, String> map = new LinkedHashMap<>(1);
map.put(getConfig().getTemplateParam(), message);
return sendMessage(phone, this.getConfig().getTemplateId(), map);
}
@Override
public SmsResponse sendMessage(String phone, LinkedHashMap<String, String> messages) {
if (Objects.isNull(messages)) {
messages = new LinkedHashMap<>();
}
return sendMessage(phone, getConfig().getTemplateId(), messages);
}
@Override
public SmsResponse sendMessage(String phone, String templateId, LinkedHashMap<String, String> messages) {
if (Objects.isNull(messages)) {
messages = new LinkedHashMap<>();
}
String messageStr = formatMessage(messages);
return getSmsResponse(phone, messageStr, templateId);
}
@Override
public SmsResponse massTexting(List<String> phones, String message) {
LinkedHashMap<String, String> map = new LinkedHashMap<>();
map.put(getConfig().getTemplateParam(), message);
return massTexting(phones, getConfig().getTemplateId(), map);
}
@Override
public SmsResponse massTexting(List<String> phones, String templateId, LinkedHashMap<String, String> messages) {
if (Objects.isNull(messages)) {
messages = new LinkedHashMap<>();
}
String messageStr = formatMessage(messages);
return getSmsResponse(SmsUtils.addCodePrefixIfNot(phones), messageStr, templateId);
}
private SmsResponse getSmsResponse(String phone, String message, String templateId) {
String requestUrl;
String paramStr;
try {
requestUrl = MontnetsUtils.generateSendSmsRequestUrl(this.getConfig());
paramStr = MontnetsUtils.generateParamBody(this.getConfig(), phone, message, templateId);
} catch (Exception e) {
log.error("montnets send message error", e);
throw new SmsBlendException(e.getMessage());
}
log.debug("requestUrl {}", requestUrl);
Map<String, String> headers = MapUtil.newHashMap(1, true);
headers.put(Constant.CONTENT_TYPE, Constant.APPLICATION_JSON_UTF8);
SmsResponse smsResponse;
try {
smsResponse = this.getResponse(this.http.postJson(requestUrl, headers, paramStr));
} catch (SmsBlendException e) {
smsResponse = this.errorResp(e.message);
}
if (!smsResponse.isSuccess() && this.retry != this.getConfig().getMaxRetries()) {
return this.requestRetry(phone, message, templateId);
} else {
this.retry = 0;
return smsResponse;
}
}
private SmsResponse requestRetry(String phone, String message, String templateId) {
this.http.safeSleep(this.getConfig().getRetryInterval());
++this.retry;
log.warn("短信第 {} 次重新发送", this.retry);
return this.getSmsResponse(phone, message, templateId);
}
private SmsResponse getResponse(JSONObject resJson) {
return SmsRespUtils.resp(URLDecoder.decode(resJson.getStr("desc"), StandardCharsets.UTF_8), "0".equals(resJson.getStr("result")), getConfigId());
}
/**
* <p>说明格式化消息
*
* @param messages 模板参数key-value集合
* @return 格式化后的消息 key1=urlEncode(value1)&key2=urlEncode(value2)
*/
private String formatMessage(LinkedHashMap<String, String> messages) {
StringJoiner joiner = new StringJoiner("&");
for (Map.Entry<String, String> entry : messages.entrySet()) {
joiner.add(entry.getKey() + "=" + URLEncodeUtil.encode(entry.getValue(), StandardCharsets.UTF_8));
}
return URLEncodeUtil.encode(joiner.toString());
}
}

View File

@ -0,0 +1,62 @@
package org.dromara.sms4j.montnets.utils;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.json.JSONUtil;
import org.dromara.sms4j.comm.utils.SmsDateUtils;
import org.dromara.sms4j.montnets.config.MontnetsConfig;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
/**
* @author SU
* 2025/4/23 10:32
*/
public class MontnetsUtils {
public static String generateSendSmsRequestUrl(MontnetsConfig montnetsConfig) {
String url = montnetsConfig.getUrl();
String api = montnetsConfig.getApi();
return url + api;
}
/**
* 生成请求body参数
*
* @param montnetsConfig 短信配置
* @param phone 手机号
* @param message 短信内容
* @param templateId 模板ID
*/
public static Map<String, String> generateParamMap(MontnetsConfig montnetsConfig, String phone, String message, String templateId) {
Map<String, String> paramMap = new HashMap<>();
String accessKeyId = montnetsConfig.getAccessKeyId();
String accessKeySecret = montnetsConfig.getAccessKeySecret();
String timeStamp = SmsDateUtils.formatDateToStr(new Date(), "MMddHHmmss", SmsDateUtils.gmt8());
paramMap.put("userid", accessKeyId);
paramMap.put("pwd", DigestUtil.md5Hex(accessKeyId.toUpperCase(Locale.ENGLISH) + "00000000" + accessKeySecret + timeStamp));
paramMap.put("timestamp", timeStamp);
paramMap.put("mobile", phone);
paramMap.put("content", message);
paramMap.put("tmplid", templateId);
return paramMap;
}
/**
* 生成请求参数body字符串
*
* @param montnetsConfig 短信配置
* @param phone 手机号
* @param message 短信内容
* @param templateId 模板ID
*/
public static String generateParamBody(MontnetsConfig montnetsConfig, String phone, String message, String templateId) {
Map<String, String> paramMap = generateParamMap(montnetsConfig, phone, message, templateId);
return JSONUtil.toJsonStr(paramMap);
}
}