Commit c2a50c4d9c00b760aeef35063d0a20bc8302d5f1
1 parent
5f6bcc4a
【代码评审】SYSTEM:腾讯云短信客户端的 review
Showing
6 changed files
with
113 additions
and
123 deletions
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/AliyunSmsClient.java
| @@ -102,8 +102,6 @@ public class AliyunSmsClient extends AbstractSmsClient { | @@ -102,8 +102,6 @@ public class AliyunSmsClient extends AbstractSmsClient { | ||
| 102 | queryParam.put("TemplateCode", apiTemplateId); | 102 | queryParam.put("TemplateCode", apiTemplateId); |
| 103 | JSONObject response = request("QuerySmsTemplate", queryParam); | 103 | JSONObject response = request("QuerySmsTemplate", queryParam); |
| 104 | 104 | ||
| 105 | - System.out.println("getSmsTemplate response is =====" + response.toString()); | ||
| 106 | - | ||
| 107 | // 2.1 请求失败 | 105 | // 2.1 请求失败 |
| 108 | String code = response.getStr("Code"); | 106 | String code = response.getStr("Code"); |
| 109 | if (ObjectUtil.notEqual(code, RESPONSE_CODE_SUCCESS)) { | 107 | if (ObjectUtil.notEqual(code, RESPONSE_CODE_SUCCESS)) { |
| @@ -170,7 +168,6 @@ public class AliyunSmsClient extends AbstractSmsClient { | @@ -170,7 +168,6 @@ public class AliyunSmsClient extends AbstractSmsClient { | ||
| 170 | // 4. 构建 Authorization 签名 | 168 | // 4. 构建 Authorization 签名 |
| 171 | String canonicalRequest = "POST" + "\n" + "/" + "\n" + queryString + "\n" + canonicalHeaders + "\n" + signedHeaders + "\n" + hashedRequestBody; | 169 | String canonicalRequest = "POST" + "\n" + "/" + "\n" + queryString + "\n" + canonicalHeaders + "\n" + signedHeaders + "\n" + hashedRequestBody; |
| 172 | String hashedCanonicalRequest = DigestUtil.sha256Hex(canonicalRequest); | 170 | String hashedCanonicalRequest = DigestUtil.sha256Hex(canonicalRequest); |
| 173 | - | ||
| 174 | String stringToSign = "ACS3-HMAC-SHA256" + "\n" + hashedCanonicalRequest; | 171 | String stringToSign = "ACS3-HMAC-SHA256" + "\n" + hashedCanonicalRequest; |
| 175 | String signature = SecureUtil.hmacSha256(properties.getApiSecret()).digestHex(stringToSign); // 计算签名 | 172 | String signature = SecureUtil.hmacSha256(properties.getApiSecret()).digestHex(stringToSign); // 计算签名 |
| 176 | headers.put("Authorization", "ACS3-HMAC-SHA256" + " " + "Credential=" + properties.getApiKey() | 173 | headers.put("Authorization", "ACS3-HMAC-SHA256" + " " + "Credential=" + properties.getApiKey() |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/HuaweiSmsClient.java
| 1 | package cn.iocoder.yudao.module.system.framework.sms.core.client.impl; | 1 | package cn.iocoder.yudao.module.system.framework.sms.core.client.impl; |
| 2 | 2 | ||
| 3 | - | ||
| 4 | import cn.hutool.core.lang.Assert; | 3 | import cn.hutool.core.lang.Assert; |
| 5 | import cn.hutool.core.util.StrUtil; | 4 | import cn.hutool.core.util.StrUtil; |
| 6 | 5 | ||
| @@ -31,13 +30,12 @@ import java.util.*; | @@ -31,13 +30,12 @@ import java.util.*; | ||
| 31 | 30 | ||
| 32 | import java.time.LocalDateTime; | 31 | import java.time.LocalDateTime; |
| 33 | 32 | ||
| 34 | - | ||
| 35 | import static cn.hutool.crypto.digest.DigestUtil.sha256Hex; | 33 | import static cn.hutool.crypto.digest.DigestUtil.sha256Hex; |
| 36 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | 34 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; |
| 37 | import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | 35 | import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; |
| 38 | import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT; | 36 | import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT; |
| 39 | 37 | ||
| 40 | - | 38 | +// todo @scholar:参考阿里云在优化下 |
| 41 | /** | 39 | /** |
| 42 | * 华为短信客户端的实现类 | 40 | * 华为短信客户端的实现类 |
| 43 | * | 41 | * |
| @@ -56,7 +54,6 @@ public class HuaweiSmsClient extends AbstractSmsClient { | @@ -56,7 +54,6 @@ public class HuaweiSmsClient extends AbstractSmsClient { | ||
| 56 | 54 | ||
| 57 | @Override | 55 | @Override |
| 58 | protected void doInit() { | 56 | protected void doInit() { |
| 59 | - | ||
| 60 | } | 57 | } |
| 61 | 58 | ||
| 62 | public HuaweiSmsClient(SmsChannelProperties properties) { | 59 | public HuaweiSmsClient(SmsChannelProperties properties) { |
| @@ -68,6 +65,7 @@ public class HuaweiSmsClient extends AbstractSmsClient { | @@ -68,6 +65,7 @@ public class HuaweiSmsClient extends AbstractSmsClient { | ||
| 68 | @Override | 65 | @Override |
| 69 | public SmsSendRespDTO sendSms(Long sendLogId, String mobile, String apiTemplateId, | 66 | public SmsSendRespDTO sendSms(Long sendLogId, String mobile, String apiTemplateId, |
| 70 | List<KeyValue<String, Object>> templateParams) throws Throwable { | 67 | List<KeyValue<String, Object>> templateParams) throws Throwable { |
| 68 | + // 参考链接 https://support.huaweicloud.com/api-msgsms/sms_05_0001.html | ||
| 71 | // 相比较阿里短信,华为短信发送的时候需要额外的参数“通道号”,考虑到不破坏原有的的结构 | 69 | // 相比较阿里短信,华为短信发送的时候需要额外的参数“通道号”,考虑到不破坏原有的的结构 |
| 72 | // 所以将 通道号 拼接到 apiTemplateId 字段中,格式为 "apiTemplateId 通道号"。空格为分隔符。 | 70 | // 所以将 通道号 拼接到 apiTemplateId 字段中,格式为 "apiTemplateId 通道号"。空格为分隔符。 |
| 73 | String sender = StrUtil.subAfter(apiTemplateId, " ", true); //中国大陆短信签名通道号或全球短信通道号 | 71 | String sender = StrUtil.subAfter(apiTemplateId, " ", true); //中国大陆短信签名通道号或全球短信通道号 |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/TencentSmsClient.java
| @@ -25,7 +25,6 @@ import java.util.*; | @@ -25,7 +25,6 @@ import java.util.*; | ||
| 25 | import static cn.hutool.crypto.digest.DigestUtil.sha256Hex; | 25 | import static cn.hutool.crypto.digest.DigestUtil.sha256Hex; |
| 26 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | 26 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; |
| 27 | 27 | ||
| 28 | - | ||
| 29 | /** | 28 | /** |
| 30 | * 腾讯云短信功能实现 | 29 | * 腾讯云短信功能实现 |
| 31 | * | 30 | * |
| @@ -35,6 +34,9 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. | @@ -35,6 +34,9 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. | ||
| 35 | */ | 34 | */ |
| 36 | public class TencentSmsClient extends AbstractSmsClient { | 35 | public class TencentSmsClient extends AbstractSmsClient { |
| 37 | 36 | ||
| 37 | + private static final String VERSION = "2021-01-11"; | ||
| 38 | + private static final String REGION = "ap-guangzhou"; | ||
| 39 | + | ||
| 38 | /** | 40 | /** |
| 39 | * 调用成功 code | 41 | * 调用成功 code |
| 40 | */ | 42 | */ |
| @@ -48,7 +50,6 @@ public class TencentSmsClient extends AbstractSmsClient { | @@ -48,7 +50,6 @@ public class TencentSmsClient extends AbstractSmsClient { | ||
| 48 | */ | 50 | */ |
| 49 | private static final long INTERNATIONAL_CHINA = 0L; | 51 | private static final long INTERNATIONAL_CHINA = 0L; |
| 50 | 52 | ||
| 51 | - | ||
| 52 | public TencentSmsClient(SmsChannelProperties properties) { | 53 | public TencentSmsClient(SmsChannelProperties properties) { |
| 53 | super(properties); | 54 | super(properties); |
| 54 | Assert.notEmpty(properties.getApiSecret(), "apiSecret 不能为空"); | 55 | Assert.notEmpty(properties.getApiSecret(), "apiSecret 不能为空"); |
| @@ -57,7 +58,6 @@ public class TencentSmsClient extends AbstractSmsClient { | @@ -57,7 +58,6 @@ public class TencentSmsClient extends AbstractSmsClient { | ||
| 57 | 58 | ||
| 58 | @Override | 59 | @Override |
| 59 | protected void doInit() { | 60 | protected void doInit() { |
| 60 | - | ||
| 61 | } | 61 | } |
| 62 | 62 | ||
| 63 | /** | 63 | /** |
| @@ -87,32 +87,96 @@ public class TencentSmsClient extends AbstractSmsClient { | @@ -87,32 +87,96 @@ public class TencentSmsClient extends AbstractSmsClient { | ||
| 87 | @Override | 87 | @Override |
| 88 | public SmsSendRespDTO sendSms(Long sendLogId, String mobile, | 88 | public SmsSendRespDTO sendSms(Long sendLogId, String mobile, |
| 89 | String apiTemplateId, List<KeyValue<String, Object>> templateParams) throws Throwable { | 89 | String apiTemplateId, List<KeyValue<String, Object>> templateParams) throws Throwable { |
| 90 | - // 构建请求 | 90 | + // 1. 执行请求 |
| 91 | + // 参考链接 https://cloud.tencent.com/document/product/382/55981 | ||
| 91 | TreeMap<String, Object> body = new TreeMap<>(); | 92 | TreeMap<String, Object> body = new TreeMap<>(); |
| 92 | - String[] phones = {mobile}; | ||
| 93 | - body.put("PhoneNumberSet",phones); | ||
| 94 | - body.put("SmsSdkAppId",getSdkAppId()); | ||
| 95 | - body.put("SignName",properties.getSignature()); | 93 | + body.put("PhoneNumberSet", new String[]{mobile}); |
| 94 | + body.put("SmsSdkAppId", getSdkAppId()); | ||
| 95 | + body.put("SignName", properties.getSignature()); | ||
| 96 | body.put("TemplateId",apiTemplateId); | 96 | body.put("TemplateId",apiTemplateId); |
| 97 | - body.put("TemplateParamSet",ArrayUtils.toArray(templateParams, e -> String.valueOf(e.getValue()))); | 97 | + body.put("TemplateParamSet", ArrayUtils.toArray(templateParams, param -> String.valueOf(param.getValue()))); |
| 98 | + JSONObject response = request("SendSms", body); | ||
| 99 | + | ||
| 100 | + // 2. 解析请求 | ||
| 101 | + JSONObject responseResult = response.getJSONObject("Response"); | ||
| 102 | + JSONObject error = responseResult.getJSONObject("Error"); | ||
| 103 | + if (error != null) { | ||
| 104 | + return new SmsSendRespDTO().setSuccess(false) | ||
| 105 | + .setApiRequestId(responseResult.getStr("RequestId")) | ||
| 106 | + .setApiCode(error.getStr("Code")) | ||
| 107 | + .setApiMsg(error.getStr("Message")); | ||
| 108 | + } | ||
| 109 | + JSONObject responseData = responseResult.getJSONArray("SendStatusSet").getJSONObject(0); | ||
| 110 | + return new SmsSendRespDTO().setSuccess(Objects.equals(API_CODE_SUCCESS, responseData.getStr("Code"))) | ||
| 111 | + .setApiRequestId(responseResult.getStr("RequestId")) | ||
| 112 | + .setSerialNo(responseData.getStr("SerialNo")) | ||
| 113 | + .setApiMsg(responseData.getStr("Message")); | ||
| 114 | + } | ||
| 115 | + | ||
| 116 | + @Override | ||
| 117 | + public List<SmsReceiveRespDTO> parseSmsReceiveStatus(String text) { | ||
| 118 | + JSONArray statuses = JSONUtil.parseArray(text); | ||
| 119 | + // 字段参考 | ||
| 120 | + return convertList(statuses, status -> { | ||
| 121 | + JSONObject statusObj = (JSONObject) status; | ||
| 122 | + return new SmsReceiveRespDTO() | ||
| 123 | + .setSuccess("SUCCESS".equals(statusObj.getStr("report_status"))) // 是否接收成功 | ||
| 124 | + .setErrorCode(statusObj.getStr("errmsg")) // 状态报告编码 | ||
| 125 | + .setMobile(statusObj.getStr("mobile")) // 手机号 | ||
| 126 | + .setReceiveTime(statusObj.getLocalDateTime("user_receive_time", null)) // 状态报告时间 | ||
| 127 | + .setSerialNo(statusObj.getStr("sid")); // 发送序列号 | ||
| 128 | + }); | ||
| 129 | + } | ||
| 98 | 130 | ||
| 99 | - JSONObject JsonResponse = request(body,"SendSms","2021-01-11","ap-guangzhou"); | 131 | + @Override |
| 132 | + public SmsTemplateRespDTO getSmsTemplate(String apiTemplateId) throws Throwable { | ||
| 133 | + // 1. 构建请求 | ||
| 134 | + // 参考链接 https://cloud.tencent.com/document/product/382/52067 | ||
| 135 | + TreeMap<String, Object> body = new TreeMap<>(); | ||
| 136 | + body.put("International", INTERNATIONAL_CHINA); | ||
| 137 | + body.put("TemplateIdSet", new Integer[]{Integer.valueOf(apiTemplateId)}); | ||
| 138 | + JSONObject response = request("DescribeSmsTemplateList", body); | ||
| 100 | 139 | ||
| 101 | - return new SmsSendRespDTO().setSuccess(API_CODE_SUCCESS.equals(JsonResponse.getJSONObject("Response").getJSONArray("SendStatusSet").getJSONObject(0).getStr("Code"))) | ||
| 102 | - .setApiRequestId(JsonResponse.getJSONObject("Response").getStr("RequestId")) | ||
| 103 | - .setSerialNo(JsonResponse.getJSONObject("Response").getJSONArray("SendStatusSet").getJSONObject(0).getStr("SerialNo")) | ||
| 104 | - .setApiMsg(JsonResponse.getJSONObject("Response").getJSONArray("SendStatusSet").getJSONObject(0).getStr("Message")); | 140 | + // TODO @scholar:会有请求失败的情况么?类似发送的(那块逻辑我补充了) |
| 141 | + JSONObject TemplateStatusSet = response.getJSONObject("Response").getJSONArray("DescribeTemplateStatusSet").getJSONObject(0); | ||
| 142 | + String content = TemplateStatusSet.get("TemplateContent").toString(); | ||
| 143 | + int templateStatus = Integer.parseInt(TemplateStatusSet.get("StatusCode").toString()); | ||
| 144 | + String auditReason = TemplateStatusSet.get("ReviewReply").toString(); | ||
| 145 | + | ||
| 146 | + return new SmsTemplateRespDTO().setId(apiTemplateId).setContent(content) | ||
| 147 | + .setAuditStatus(convertSmsTemplateAuditStatus(templateStatus)).setAuditReason(auditReason); | ||
| 105 | } | 148 | } |
| 106 | 149 | ||
| 107 | - JSONObject request(TreeMap<String, Object> body,String action,String version,String region) throws Exception { | 150 | + @VisibleForTesting |
| 151 | + Integer convertSmsTemplateAuditStatus(int templateStatus) { | ||
| 152 | + switch (templateStatus) { | ||
| 153 | + case 1: return SmsTemplateAuditStatusEnum.CHECKING.getStatus(); | ||
| 154 | + case 0: return SmsTemplateAuditStatusEnum.SUCCESS.getStatus(); | ||
| 155 | + case -1: return SmsTemplateAuditStatusEnum.FAIL.getStatus(); | ||
| 156 | + default: throw new IllegalArgumentException(String.format("未知审核状态(%d)", templateStatus)); | ||
| 157 | + } | ||
| 158 | + } | ||
| 108 | 159 | ||
| 160 | + /** | ||
| 161 | + * 请求腾讯云短信 | ||
| 162 | + * | ||
| 163 | + * @see <a href="https://cloud.tencent.com/document/product/382/52072">签名方法 v3</a> | ||
| 164 | + * | ||
| 165 | + * @param action 请求的 API 名称 | ||
| 166 | + * @param body 请求参数 | ||
| 167 | + * @return 请求结果 | ||
| 168 | + */ | ||
| 169 | + private JSONObject request(String action, TreeMap<String, Object> body) throws Exception { | ||
| 109 | String timestamp = String.valueOf(System.currentTimeMillis() / 1000); | 170 | String timestamp = String.valueOf(System.currentTimeMillis() / 1000); |
| 171 | + // TODO @scholar:这个 format,看看怎么写的可以简化点 | ||
| 110 | SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); | 172 | SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); |
| 111 | // 注意时区,否则容易出错 | 173 | // 注意时区,否则容易出错 |
| 112 | sdf.setTimeZone(TimeZone.getTimeZone("UTC")); | 174 | sdf.setTimeZone(TimeZone.getTimeZone("UTC")); |
| 113 | String date = sdf.format(new Date(Long.valueOf(timestamp + "000"))); | 175 | String date = sdf.format(new Date(Long.valueOf(timestamp + "000"))); |
| 114 | 176 | ||
| 177 | + // TODO @scholar:这个步骤,看看怎么参考阿里云 client,归类下;1. 2.1 2.2 这种 | ||
| 115 | // ************* 步骤 1:拼接规范请求串 ************* | 178 | // ************* 步骤 1:拼接规范请求串 ************* |
| 179 | + // TODO @scholar:这个 hsot 枚举下; | ||
| 116 | String host = "sms.tencentcloudapi.com"; //APP接入地址+接口访问URI | 180 | String host = "sms.tencentcloudapi.com"; //APP接入地址+接口访问URI |
| 117 | String httpMethod = "POST"; // 请求方式 | 181 | String httpMethod = "POST"; // 请求方式 |
| 118 | String canonicalUri = "/"; | 182 | String canonicalUri = "/"; |
| @@ -122,6 +186,7 @@ public class TencentSmsClient extends AbstractSmsClient { | @@ -122,6 +186,7 @@ public class TencentSmsClient extends AbstractSmsClient { | ||
| 122 | + "host:" + host + "\n" + "x-tc-action:" + action.toLowerCase() + "\n"; | 186 | + "host:" + host + "\n" + "x-tc-action:" + action.toLowerCase() + "\n"; |
| 123 | String signedHeaders = "content-type;host;x-tc-action"; | 187 | String signedHeaders = "content-type;host;x-tc-action"; |
| 124 | String hashedRequestBody = sha256Hex(JSONUtil.toJsonStr(body)); | 188 | String hashedRequestBody = sha256Hex(JSONUtil.toJsonStr(body)); |
| 189 | + // TODO @scholar:换行下,不然单行太长了 | ||
| 125 | String canonicalRequest = httpMethod + "\n" + canonicalUri + "\n" + canonicalQueryString + "\n" + canonicalHeaders + "\n" + signedHeaders + "\n" + hashedRequestBody; | 190 | String canonicalRequest = httpMethod + "\n" + canonicalUri + "\n" + canonicalQueryString + "\n" + canonicalHeaders + "\n" + signedHeaders + "\n" + hashedRequestBody; |
| 126 | 191 | ||
| 127 | // ************* 步骤 2:拼接待签名字符串 ************* | 192 | // ************* 步骤 2:拼接待签名字符串 ************* |
| @@ -146,65 +211,19 @@ public class TencentSmsClient extends AbstractSmsClient { | @@ -146,65 +211,19 @@ public class TencentSmsClient extends AbstractSmsClient { | ||
| 146 | headers.put("Host", host); | 211 | headers.put("Host", host); |
| 147 | headers.put("X-TC-Action", action); | 212 | headers.put("X-TC-Action", action); |
| 148 | headers.put("X-TC-Timestamp", timestamp); | 213 | headers.put("X-TC-Timestamp", timestamp); |
| 149 | - headers.put("X-TC-Version", version); | ||
| 150 | - headers.put("X-TC-Region", region); | 214 | + headers.put("X-TC-Version", VERSION); |
| 215 | + headers.put("X-TC-Region", REGION); | ||
| 151 | 216 | ||
| 152 | - String responseBody = HttpUtils.post("https://"+host, headers, JSONUtil.toJsonStr(body)); | 217 | + String responseBody = HttpUtils.post("https://" + host, headers, JSONUtil.toJsonStr(body)); |
| 153 | 218 | ||
| 154 | return JSONUtil.parseObj(responseBody); | 219 | return JSONUtil.parseObj(responseBody); |
| 155 | } | 220 | } |
| 156 | 221 | ||
| 157 | - public static byte[] hmac256(byte[] key, String msg) throws Exception { | 222 | + // TODO @scholar:使用 hutool 简化下 |
| 223 | + private static byte[] hmac256(byte[] key, String msg) throws Exception { | ||
| 158 | Mac mac = Mac.getInstance("HmacSHA256"); | 224 | Mac mac = Mac.getInstance("HmacSHA256"); |
| 159 | SecretKeySpec secretKeySpec = new SecretKeySpec(key, mac.getAlgorithm()); | 225 | SecretKeySpec secretKeySpec = new SecretKeySpec(key, mac.getAlgorithm()); |
| 160 | mac.init(secretKeySpec); | 226 | mac.init(secretKeySpec); |
| 161 | return mac.doFinal(msg.getBytes(StandardCharsets.UTF_8)); | 227 | return mac.doFinal(msg.getBytes(StandardCharsets.UTF_8)); |
| 162 | } | 228 | } |
| 163 | - | ||
| 164 | - @Override | ||
| 165 | - public List<SmsReceiveRespDTO> parseSmsReceiveStatus(String text) { | ||
| 166 | - | ||
| 167 | - JSONArray statuses = JSONUtil.parseArray(text); | ||
| 168 | - // 字段参考 | ||
| 169 | - return convertList(statuses, status -> { | ||
| 170 | - JSONObject statusObj = (JSONObject) status; | ||
| 171 | - return new SmsReceiveRespDTO() | ||
| 172 | - .setSuccess("SUCCESS".equals(statusObj.getStr("report_status"))) // 是否接收成功 | ||
| 173 | - .setErrorCode(statusObj.getStr("errmsg")) // 状态报告编码 | ||
| 174 | - .setMobile(statusObj.getStr("mobile")) // 手机号 | ||
| 175 | - .setReceiveTime(statusObj.getLocalDateTime("user_receive_time", null)) // 状态报告时间 | ||
| 176 | - .setSerialNo(statusObj.getStr("sid")); // 发送序列号 | ||
| 177 | - }); | ||
| 178 | - } | ||
| 179 | - | ||
| 180 | - @Override | ||
| 181 | - public SmsTemplateRespDTO getSmsTemplate(String apiTemplateId) throws Throwable { | ||
| 182 | - | ||
| 183 | - // 构建请求 | ||
| 184 | - TreeMap<String, Object> body = new TreeMap<>(); | ||
| 185 | - body.put("International",INTERNATIONAL_CHINA); | ||
| 186 | - Integer[] templateIds = {Integer.valueOf(apiTemplateId)}; | ||
| 187 | - body.put("TemplateIdSet",templateIds); | ||
| 188 | - | ||
| 189 | - JSONObject JsonResponse = request(body,"DescribeSmsTemplateList","2021-01-11","ap-guangzhou"); | ||
| 190 | - System.out.println("JsonResponse======"+JsonResponse); | ||
| 191 | - | ||
| 192 | - JSONObject TemplateStatusSet = JsonResponse.getJSONObject("Response").getJSONArray("DescribeTemplateStatusSet").getJSONObject(0); | ||
| 193 | - String content = TemplateStatusSet.get("TemplateContent").toString(); | ||
| 194 | - int templateStatus = Integer.parseInt(TemplateStatusSet.get("StatusCode").toString()); | ||
| 195 | - String auditReason = TemplateStatusSet.get("ReviewReply").toString(); | ||
| 196 | - | ||
| 197 | - return new SmsTemplateRespDTO().setId(apiTemplateId).setContent(content) | ||
| 198 | - .setAuditStatus(convertSmsTemplateAuditStatus(templateStatus)).setAuditReason(auditReason); | ||
| 199 | - } | ||
| 200 | - | ||
| 201 | - @VisibleForTesting | ||
| 202 | - Integer convertSmsTemplateAuditStatus(int templateStatus) { | ||
| 203 | - switch (templateStatus) { | ||
| 204 | - case 1: return SmsTemplateAuditStatusEnum.CHECKING.getStatus(); | ||
| 205 | - case 0: return SmsTemplateAuditStatusEnum.SUCCESS.getStatus(); | ||
| 206 | - case -1: return SmsTemplateAuditStatusEnum.FAIL.getStatus(); | ||
| 207 | - default: throw new IllegalArgumentException(String.format("未知审核状态(%d)", templateStatus)); | ||
| 208 | - } | ||
| 209 | - } | ||
| 210 | } | 229 | } |
| 211 | \ No newline at end of file | 230 | \ No newline at end of file |
yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/AliyunSmsClientTest.java
| @@ -39,15 +39,6 @@ public class AliyunSmsClientTest extends BaseMockitoUnitTest { | @@ -39,15 +39,6 @@ public class AliyunSmsClientTest extends BaseMockitoUnitTest { | ||
| 39 | private final AliyunSmsClient smsClient = new AliyunSmsClient(properties); | 39 | private final AliyunSmsClient smsClient = new AliyunSmsClient(properties); |
| 40 | 40 | ||
| 41 | @Test | 41 | @Test |
| 42 | - public void testDoInit() { | ||
| 43 | - // 准备参数 | ||
| 44 | - // mock 方法 | ||
| 45 | - | ||
| 46 | - // 调用 | ||
| 47 | - smsClient.doInit(); | ||
| 48 | - } | ||
| 49 | - | ||
| 50 | - @Test | ||
| 51 | public void tesSendSms_success() throws Throwable { | 42 | public void tesSendSms_success() throws Throwable { |
| 52 | try (MockedStatic<HttpUtils> httpUtilsMockedStatic = mockStatic(HttpUtils.class)) { | 43 | try (MockedStatic<HttpUtils> httpUtilsMockedStatic = mockStatic(HttpUtils.class)) { |
| 53 | // 准备参数 | 44 | // 准备参数 |
yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/SmsClientTests.java
| @@ -17,25 +17,6 @@ import java.util.List; | @@ -17,25 +17,6 @@ import java.util.List; | ||
| 17 | */ | 17 | */ |
| 18 | public class SmsClientTests { | 18 | public class SmsClientTests { |
| 19 | 19 | ||
| 20 | - @Test | ||
| 21 | - @Disabled | ||
| 22 | - public void testHuaweiSmsClient_sendSms() throws Throwable { | ||
| 23 | - SmsChannelProperties properties = new SmsChannelProperties() | ||
| 24 | - .setApiKey("123") | ||
| 25 | - .setApiSecret("456") | ||
| 26 | - .setSignature("runpu"); | ||
| 27 | - HuaweiSmsClient client = new HuaweiSmsClient(properties); | ||
| 28 | - // 准备参数 | ||
| 29 | - Long sendLogId = System.currentTimeMillis(); | ||
| 30 | - String mobile = "15601691323"; | ||
| 31 | - String apiTemplateId = "xx test01"; | ||
| 32 | - List<KeyValue<String, Object>> templateParams = List.of(new KeyValue<>("code", "1024")); | ||
| 33 | - // 调用 | ||
| 34 | - SmsSendRespDTO smsSendRespDTO = client.sendSms(sendLogId, mobile, apiTemplateId, templateParams); | ||
| 35 | - // 打印结果 | ||
| 36 | - System.out.println(smsSendRespDTO); | ||
| 37 | - } | ||
| 38 | - | ||
| 39 | // ========== 阿里云 ========== | 20 | // ========== 阿里云 ========== |
| 40 | 21 | ||
| 41 | @Test | 22 | @Test |
| @@ -135,5 +116,27 @@ public class SmsClientTests { | @@ -135,5 +116,27 @@ public class SmsClientTests { | ||
| 135 | // 打印结果 | 116 | // 打印结果 |
| 136 | System.out.println(template); | 117 | System.out.println(template); |
| 137 | } | 118 | } |
| 119 | + | ||
| 120 | + // ========== 华为云 ========== | ||
| 121 | + | ||
| 122 | + @Test | ||
| 123 | + @Disabled | ||
| 124 | + public void testHuaweiSmsClient_sendSms() throws Throwable { | ||
| 125 | + SmsChannelProperties properties = new SmsChannelProperties() | ||
| 126 | + .setApiKey("123") | ||
| 127 | + .setApiSecret("456") | ||
| 128 | + .setSignature("runpu"); | ||
| 129 | + HuaweiSmsClient client = new HuaweiSmsClient(properties); | ||
| 130 | + // 准备参数 | ||
| 131 | + Long sendLogId = System.currentTimeMillis(); | ||
| 132 | + String mobile = "15601691323"; | ||
| 133 | + String apiTemplateId = "xx test01"; | ||
| 134 | + List<KeyValue<String, Object>> templateParams = List.of(new KeyValue<>("code", "1024")); | ||
| 135 | + // 调用 | ||
| 136 | + SmsSendRespDTO smsSendRespDTO = client.sendSms(sendLogId, mobile, apiTemplateId, templateParams); | ||
| 137 | + // 打印结果 | ||
| 138 | + System.out.println(smsSendRespDTO); | ||
| 139 | + } | ||
| 140 | + | ||
| 138 | } | 141 | } |
| 139 | 142 |
yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/TencentSmsClientTest.java
| @@ -39,17 +39,7 @@ public class TencentSmsClientTest extends BaseMockitoUnitTest { | @@ -39,17 +39,7 @@ public class TencentSmsClientTest extends BaseMockitoUnitTest { | ||
| 39 | private TencentSmsClient smsClient = new TencentSmsClient(properties); | 39 | private TencentSmsClient smsClient = new TencentSmsClient(properties); |
| 40 | 40 | ||
| 41 | @Test | 41 | @Test |
| 42 | - public void testDoInit() { | ||
| 43 | - // 准备参数 | ||
| 44 | - // mock 方法 | ||
| 45 | - | ||
| 46 | - // 调用 | ||
| 47 | - smsClient.doInit(); | ||
| 48 | - } | ||
| 49 | - | ||
| 50 | - @Test | ||
| 51 | public void testDoSendSms_success() throws Throwable { | 42 | public void testDoSendSms_success() throws Throwable { |
| 52 | - | ||
| 53 | try (MockedStatic<HttpUtils> httpUtilsMockedStatic = mockStatic(HttpUtils.class)) { | 43 | try (MockedStatic<HttpUtils> httpUtilsMockedStatic = mockStatic(HttpUtils.class)) { |
| 54 | // 准备参数 | 44 | // 准备参数 |
| 55 | Long sendLogId = randomLongId(); | 45 | Long sendLogId = randomLongId(); |
| @@ -57,11 +47,9 @@ public class TencentSmsClientTest extends BaseMockitoUnitTest { | @@ -57,11 +47,9 @@ public class TencentSmsClientTest extends BaseMockitoUnitTest { | ||
| 57 | String apiTemplateId = randomString(); | 47 | String apiTemplateId = randomString(); |
| 58 | List<KeyValue<String, Object>> templateParams = Lists.newArrayList( | 48 | List<KeyValue<String, Object>> templateParams = Lists.newArrayList( |
| 59 | new KeyValue<>("1", 1234), new KeyValue<>("2", "login")); | 49 | new KeyValue<>("1", 1234), new KeyValue<>("2", "login")); |
| 60 | - | ||
| 61 | // mock 方法 | 50 | // mock 方法 |
| 62 | httpUtilsMockedStatic.when(() -> HttpUtils.post(anyString(), anyMap(), anyString())) | 51 | httpUtilsMockedStatic.when(() -> HttpUtils.post(anyString(), anyMap(), anyString())) |
| 63 | - .thenReturn( | ||
| 64 | - "{\n" + | 52 | + .thenReturn("{\n" + |
| 65 | " \"Response\": {\n" + | 53 | " \"Response\": {\n" + |
| 66 | " \"SendStatusSet\": [\n" + | 54 | " \"SendStatusSet\": [\n" + |
| 67 | " {\n" + | 55 | " {\n" + |
| @@ -76,8 +64,7 @@ public class TencentSmsClientTest extends BaseMockitoUnitTest { | @@ -76,8 +64,7 @@ public class TencentSmsClientTest extends BaseMockitoUnitTest { | ||
| 76 | " ],\n" + | 64 | " ],\n" + |
| 77 | " \"RequestId\": \"a0aabda6-cf91-4f3e-a81f-9198114a2279\"\n" + | 65 | " \"RequestId\": \"a0aabda6-cf91-4f3e-a81f-9198114a2279\"\n" + |
| 78 | " }\n" + | 66 | " }\n" + |
| 79 | - "}" | ||
| 80 | - ); | 67 | + "}"); |
| 81 | 68 | ||
| 82 | // 调用 | 69 | // 调用 |
| 83 | SmsSendRespDTO result = smsClient.sendSms(sendLogId, mobile, | 70 | SmsSendRespDTO result = smsClient.sendSms(sendLogId, mobile, |
| @@ -87,7 +74,6 @@ public class TencentSmsClientTest extends BaseMockitoUnitTest { | @@ -87,7 +74,6 @@ public class TencentSmsClientTest extends BaseMockitoUnitTest { | ||
| 87 | assertEquals("5000:1045710669157053657849499619", result.getSerialNo()); | 74 | assertEquals("5000:1045710669157053657849499619", result.getSerialNo()); |
| 88 | assertEquals("a0aabda6-cf91-4f3e-a81f-9198114a2279", result.getApiRequestId()); | 75 | assertEquals("a0aabda6-cf91-4f3e-a81f-9198114a2279", result.getApiRequestId()); |
| 89 | assertEquals("send success", result.getApiMsg()); | 76 | assertEquals("send success", result.getApiMsg()); |
| 90 | - | ||
| 91 | } | 77 | } |
| 92 | } | 78 | } |
| 93 | 79 | ||
| @@ -103,8 +89,7 @@ public class TencentSmsClientTest extends BaseMockitoUnitTest { | @@ -103,8 +89,7 @@ public class TencentSmsClientTest extends BaseMockitoUnitTest { | ||
| 103 | 89 | ||
| 104 | // mock 方法 | 90 | // mock 方法 |
| 105 | httpUtilsMockedStatic.when(() -> HttpUtils.post(anyString(), anyMap(), anyString())) | 91 | httpUtilsMockedStatic.when(() -> HttpUtils.post(anyString(), anyMap(), anyString())) |
| 106 | - .thenReturn( | ||
| 107 | - "{\n" + | 92 | + .thenReturn("{\n" + |
| 108 | " \"Response\": {\n" + | 93 | " \"Response\": {\n" + |
| 109 | " \"SendStatusSet\": [\n" + | 94 | " \"SendStatusSet\": [\n" + |
| 110 | " {\n" + | 95 | " {\n" + |
| @@ -119,8 +104,7 @@ public class TencentSmsClientTest extends BaseMockitoUnitTest { | @@ -119,8 +104,7 @@ public class TencentSmsClientTest extends BaseMockitoUnitTest { | ||
| 119 | " ],\n" + | 104 | " ],\n" + |
| 120 | " \"RequestId\": \"a0aabda6-cf91-4f3e-a81f-9198114a2279\"\n" + | 105 | " \"RequestId\": \"a0aabda6-cf91-4f3e-a81f-9198114a2279\"\n" + |
| 121 | " }\n" + | 106 | " }\n" + |
| 122 | - "}" | ||
| 123 | - ); | 107 | + "}"); |
| 124 | 108 | ||
| 125 | // 调用 | 109 | // 调用 |
| 126 | SmsSendRespDTO result = smsClient.sendSms(sendLogId, mobile, | 110 | SmsSendRespDTO result = smsClient.sendSms(sendLogId, mobile, |
| @@ -162,9 +146,7 @@ public class TencentSmsClientTest extends BaseMockitoUnitTest { | @@ -162,9 +146,7 @@ public class TencentSmsClientTest extends BaseMockitoUnitTest { | ||
| 162 | 146 | ||
| 163 | @Test | 147 | @Test |
| 164 | public void testGetSmsTemplate() throws Throwable { | 148 | public void testGetSmsTemplate() throws Throwable { |
| 165 | - | ||
| 166 | try (MockedStatic<HttpUtils> httpUtilsMockedStatic = mockStatic(HttpUtils.class)) { | 149 | try (MockedStatic<HttpUtils> httpUtilsMockedStatic = mockStatic(HttpUtils.class)) { |
| 167 | - | ||
| 168 | // 准备参数 | 150 | // 准备参数 |
| 169 | String apiTemplateId = "1122"; | 151 | String apiTemplateId = "1122"; |
| 170 | 152 |