mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2024-11-26 17:21:53 +08:00
增加钉钉模拟短信的 smsClient 实现类
This commit is contained in:
parent
1740128dc3
commit
be8b892bf6
@ -3,6 +3,7 @@ package cn.iocoder.dashboard.framework.sms.core.client.impl;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.SmsClient;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.SmsClientFactory;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.impl.aliyun.AliyunSmsClient;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.impl.debug.DebugDingTalkSmsClient;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.impl.yunpian.YunpianSmsClient;
|
||||
import cn.iocoder.dashboard.framework.sms.core.enums.SmsChannelEnum;
|
||||
import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties;
|
||||
@ -77,35 +78,13 @@ public class SmsClientFactoryImpl implements SmsClientFactory {
|
||||
Assert.notNull(channelEnum, String.format("渠道类型(%s) 为空", channelEnum));
|
||||
// 创建客户端
|
||||
switch (channelEnum) {
|
||||
case ALIYUN:
|
||||
return new AliyunSmsClient(properties);
|
||||
case YUN_PIAN:
|
||||
return new YunpianSmsClient(properties);
|
||||
case ALIYUN: return new AliyunSmsClient(properties);
|
||||
case YUN_PIAN: return new YunpianSmsClient(properties);
|
||||
case DEBUG_DING_TALK: return new DebugDingTalkSmsClient(properties);
|
||||
}
|
||||
// 创建失败,错误日志 + 抛出异常
|
||||
log.error("[createSmsClient][配置({}) 找不到合适的客户端实现]", properties);
|
||||
throw new IllegalArgumentException(String.format("配置(%s) 找不到合适的客户端实现", properties));
|
||||
}
|
||||
|
||||
// /**
|
||||
// * 从短信发送回调函数请求中获取用于唯一确定一条send_lod的apiId
|
||||
// *
|
||||
// * @param callbackRequest 短信发送回调函数请求
|
||||
// * @return 第三方平台短信唯一标识
|
||||
// */
|
||||
// public SmsResultDetail getSmsResultDetailFromCallbackQuery(ServletRequest callbackRequest) {
|
||||
// for (Long channelId : clients.keySet()) {
|
||||
// AbstractSmsClient smsClient = clients.get(channelId);
|
||||
// try {
|
||||
// SmsResultDetail smsSendResult = smsClient.smsSendCallbackHandle(callbackRequest);
|
||||
// if (smsSendResult != null) {
|
||||
// return smsSendResult;
|
||||
// }
|
||||
// } catch (Exception ignored) {
|
||||
// }
|
||||
// }
|
||||
// throw new IllegalArgumentException("getSmsResultDetailFromCallbackQuery fail! don't match SmsClient by RequestParam: "
|
||||
// + JsonUtils.toJsonString(callbackRequest.getParameterMap()));
|
||||
// }
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,23 @@
|
||||
package cn.iocoder.dashboard.framework.sms.core.client.impl.debug;
|
||||
|
||||
import cn.iocoder.dashboard.common.exception.ErrorCode;
|
||||
import cn.iocoder.dashboard.common.exception.enums.GlobalErrorCodeConstants;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.SmsCodeMapping;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import static cn.iocoder.dashboard.framework.sms.core.enums.SmsFrameworkErrorCodeConstants.SMS_UNKNOWN;
|
||||
|
||||
/**
|
||||
* 钉钉的 SmsCodeMapping 实现类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public class DebugDingTalkCodeMapping implements SmsCodeMapping {
|
||||
|
||||
@Override
|
||||
public ErrorCode apply(String apiCode) {
|
||||
return Objects.equals(apiCode, "0") ? GlobalErrorCodeConstants.SUCCESS : SMS_UNKNOWN;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
package cn.iocoder.dashboard.framework.sms.core.client.impl.debug;
|
||||
|
||||
import cn.hutool.core.codec.Base64;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.crypto.digest.DigestUtil;
|
||||
import cn.hutool.crypto.digest.HmacAlgorithm;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import cn.iocoder.dashboard.common.core.KeyValue;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsReceiveRespDTO;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsTemplateRespDTO;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.impl.AbstractSmsClient;
|
||||
import cn.iocoder.dashboard.framework.sms.core.enums.SmsTemplateAuditStatusEnum;
|
||||
import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties;
|
||||
import cn.iocoder.dashboard.util.collection.MapUtils;
|
||||
import cn.iocoder.dashboard.util.json.JsonUtils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 基于钉钉 WebHook 实现的调试的短信客户端实现类
|
||||
*
|
||||
* 考虑到省钱,我们使用钉钉 WebHook 模拟发送短信,方便调试。
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public class DebugDingTalkSmsClient extends AbstractSmsClient {
|
||||
|
||||
public DebugDingTalkSmsClient(SmsChannelProperties properties) {
|
||||
super(properties, new DebugDingTalkCodeMapping());
|
||||
Assert.notEmpty(properties.getApiKey(), "apiKey 不能为空");
|
||||
Assert.notEmpty(properties.getApiSecret(), "apiSecret 不能为空");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doInit() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SmsCommonResult<SmsSendRespDTO> doSendSms(Long sendLogId, String mobile,
|
||||
String apiTemplateId, List<KeyValue<String, Object>> templateParams) throws Throwable {
|
||||
// 构建请求
|
||||
String url = buildUrl("robot/send");
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("msgtype", "text");
|
||||
String content = String.format("【模拟短信】\n手机号:%s\n短信日志编号:%d\n模板参数:%s",
|
||||
mobile, sendLogId, MapUtils.convertMap(templateParams));
|
||||
params.put("text", MapUtil.builder().put("content", content).build());
|
||||
// 执行请求
|
||||
String responseText = HttpUtil.post(url, JsonUtils.toJsonString(params));
|
||||
// 解析结果
|
||||
Map<?, ?> responseObj = JsonUtils.parseObject(responseText, Map.class);
|
||||
return SmsCommonResult.build(MapUtil.getStr(responseObj, "errcode"), MapUtil.getStr(responseObj, "errorMsg"),
|
||||
null, new SmsSendRespDTO().setSerialNo(StrUtil.uuid()), codeMapping);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建请求地址
|
||||
*
|
||||
* 参见 https://developers.dingtalk.com/document/app/custom-robot-access/title-nfv-794-g71 文档
|
||||
*
|
||||
* @param path 请求路径
|
||||
* @return 请求地址
|
||||
*/
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
private String buildUrl(String path) {
|
||||
// 生成 timestamp
|
||||
long timestamp = System.currentTimeMillis();
|
||||
// 生成 sign
|
||||
String secret = properties.getApiSecret();
|
||||
String stringToSign = timestamp + "\n" + secret;
|
||||
byte[] signData = DigestUtil.hmac(HmacAlgorithm.HmacSHA256, StrUtil.bytes(secret)).digest(stringToSign);
|
||||
String sign = Base64.encode(signData);
|
||||
// 构建最终 URL
|
||||
return String.format("https://oapi.dingtalk.com/%s?access_token=%s×tamp=%d&sign=%s",
|
||||
path, properties.getApiKey(), timestamp, sign);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<SmsReceiveRespDTO> doParseSmsReceiveStatus(String text) throws Throwable {
|
||||
throw new UnsupportedOperationException("模拟短信客户端,暂时无需解析回调");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SmsCommonResult<SmsTemplateRespDTO> doGetSmsTemplate(String apiTemplateId) {
|
||||
SmsTemplateRespDTO data = new SmsTemplateRespDTO().setId(apiTemplateId).setContent("")
|
||||
.setAuditStatus(SmsTemplateAuditStatusEnum.SUCCESS.getStatus()).setAuditReason("");
|
||||
return SmsCommonResult.build("0", "success", null, data, codeMapping);
|
||||
}
|
||||
|
||||
}
|
@ -14,6 +14,7 @@ import lombok.Getter;
|
||||
@AllArgsConstructor
|
||||
public enum SmsChannelEnum {
|
||||
|
||||
DEBUG_DING_TALK("DEBUG_DING_TALK", "调试(钉钉)"),
|
||||
YUN_PIAN("YUN_PIAN", "云片"),
|
||||
ALIYUN("ALIYUN", "阿里云"),
|
||||
// TENCENT("TENCENT", "腾讯云"),
|
||||
|
@ -0,0 +1,45 @@
|
||||
package cn.iocoder.dashboard.framework.sms.core.client.impl.debug;
|
||||
|
||||
import cn.iocoder.dashboard.common.core.KeyValue;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.SmsCommonResult;
|
||||
import cn.iocoder.dashboard.framework.sms.core.client.dto.SmsSendRespDTO;
|
||||
import cn.iocoder.dashboard.framework.sms.core.enums.SmsChannelEnum;
|
||||
import cn.iocoder.dashboard.framework.sms.core.property.SmsChannelProperties;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* {@link DebugDingTalkSmsClient} 的集成测试
|
||||
*/
|
||||
public class DebugDingTalkSmsClientIntegrationTest {
|
||||
|
||||
private static DebugDingTalkSmsClient smsClient;
|
||||
|
||||
@BeforeAll
|
||||
public static void init() {
|
||||
// 创建配置类
|
||||
SmsChannelProperties properties = new SmsChannelProperties();
|
||||
properties.setId(1L);
|
||||
properties.setSignature("芋道");
|
||||
properties.setCode(SmsChannelEnum.DEBUG_DING_TALK.getCode());
|
||||
properties.setApiKey("696b5d8ead48071237e4aa5861ff08dbadb2b4ded1c688a7b7c9afc615579859");
|
||||
properties.setApiSecret("SEC5c4e5ff888bc8a9923ae47f59e7ccd30af1f14d93c55b4e2c9cb094e35aeed67");
|
||||
// 创建客户端
|
||||
smsClient = new DebugDingTalkSmsClient(properties);
|
||||
smsClient.init();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendSms() {
|
||||
List<KeyValue<String, Object>> templateParams = new ArrayList<>();
|
||||
templateParams.add(new KeyValue<>("code", "1024"));
|
||||
templateParams.add(new KeyValue<>("operation", "嘿嘿"));
|
||||
// SmsResult result = smsClient.send(1L, "15601691399", "4372216", templateParams);
|
||||
SmsCommonResult<SmsSendRespDTO> result = smsClient.sendSms(1L, "15601691399", "4383920", templateParams);
|
||||
System.out.println(result);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user