mirror of
https://gitee.com/dromara/sms4j.git
synced 2025-12-08 01:48:38 +08:00
集成梦网科技短信发送服务 - 实现 config、factory、smsBlend 接口
This commit is contained in:
parent
dc607312e1
commit
9c30da1103
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user