潘志宝
5 天以前 2780e6717df31ee605dd8ce525afcb43914ca2de
提交 | 用户 | 时间
e7c126 1 package com.iailab.module.system.framework.sms.core.client.impl;
H 2
3 import cn.hutool.core.codec.Base64;
4 import cn.hutool.core.lang.Assert;
5 import cn.hutool.core.map.MapUtil;
6 import cn.hutool.core.util.StrUtil;
7 import cn.hutool.crypto.digest.DigestUtil;
8 import cn.hutool.crypto.digest.HmacAlgorithm;
9 import cn.hutool.http.HttpUtil;
10 import com.iailab.framework.common.core.KeyValue;
11 import com.iailab.framework.common.util.collection.MapUtils;
12 import com.iailab.framework.common.util.json.JsonUtils;
13 import com.iailab.module.system.framework.sms.core.client.dto.SmsReceiveRespDTO;
14 import com.iailab.module.system.framework.sms.core.client.dto.SmsSendRespDTO;
15 import com.iailab.module.system.framework.sms.core.client.dto.SmsTemplateRespDTO;
16 import com.iailab.module.system.framework.sms.core.client.impl.AbstractSmsClient;
17 import com.iailab.module.system.framework.sms.core.enums.SmsTemplateAuditStatusEnum;
18 import com.iailab.module.system.framework.sms.core.property.SmsChannelProperties;
19
20 import java.util.HashMap;
21 import java.util.List;
22 import java.util.Map;
23 import java.util.Objects;
24
25 /**
26  * 基于钉钉 WebHook 实现的调试的短信客户端实现类
27  *
28  * 考虑到省钱,我们使用钉钉 WebHook 模拟发送短信,方便调试。
29  *
30  * @author iailab
31  */
32 public class DebugDingTalkSmsClient extends AbstractSmsClient {
33
34     public DebugDingTalkSmsClient(SmsChannelProperties properties) {
35         super(properties);
36         Assert.notEmpty(properties.getApiKey(), "apiKey 不能为空");
37         Assert.notEmpty(properties.getApiSecret(), "apiSecret 不能为空");
38     }
39
40     @Override
41     protected void doInit() {
42     }
43
44     @Override
45     public SmsSendRespDTO sendSms(Long sendLogId, String mobile,
46                                   String apiTemplateId, List<KeyValue<String, Object>> templateParams) throws Throwable {
47         // 构建请求
48         String url = buildUrl("robot/send");
49         Map<String, Object> params = new HashMap<>();
50         params.put("msgtype", "text");
51         String content = String.format("【模拟短信】\n手机号:%s\n短信日志编号:%d\n模板参数:%s",
52                 mobile, sendLogId, MapUtils.convertMap(templateParams));
53         params.put("text", MapUtil.builder().put("content", content).build());
54         // 执行请求
55         String responseText = HttpUtil.post(url, JsonUtils.toJsonString(params));
56         // 解析结果
57         Map<?, ?> responseObj = JsonUtils.parseObject(responseText, Map.class);
58         String errorCode = MapUtil.getStr(responseObj, "errcode");
59         return new SmsSendRespDTO().setSuccess(Objects.equals(errorCode, "0")).setSerialNo(StrUtil.uuid())
60                 .setApiCode(errorCode).setApiMsg(MapUtil.getStr(responseObj, "errorMsg"));
61     }
62
63     /**
64      * 构建请求地址
65      *
66      * 参见 <a href="https://developers.dingtalk.com/document/app/custom-robot-access/title-nfv-794-g71">文档</a>
67      *
68      * @param path 请求路径
69      * @return 请求地址
70      */
71     @SuppressWarnings("SameParameterValue")
72     private String buildUrl(String path) {
73         // 生成 timestamp
74         long timestamp = System.currentTimeMillis();
75         // 生成 sign
76         String secret = properties.getApiSecret();
77         String stringToSign = timestamp + "\n" + secret;
78         byte[] signData = DigestUtil.hmac(HmacAlgorithm.HmacSHA256, StrUtil.bytes(secret)).digest(stringToSign);
79         String sign = Base64.encode(signData);
80         // 构建最终 URL
81         return String.format("https://oapi.dingtalk.com/%s?access_token=%s&timestamp=%d&sign=%s",
82                 path, properties.getApiKey(), timestamp, sign);
83     }
84
85     @Override
86     public List<SmsReceiveRespDTO> parseSmsReceiveStatus(String text) {
87         throw new UnsupportedOperationException("模拟短信客户端,暂时无需解析回调");
88     }
89
90     @Override
91     public SmsTemplateRespDTO getSmsTemplate(String apiTemplateId) {
92         return new SmsTemplateRespDTO().setId(apiTemplateId).setContent("")
93                 .setAuditStatus(SmsTemplateAuditStatusEnum.SUCCESS.getStatus()).setAuditReason("");
94     }
95
96 }