Commit 5f6bcc4a351d9079a8223e8b53c235532f750995

Authored by YunaiV
2 parents 7288e6c9 8242735d

Merge branch 'develop' of https://gitee.com/scholarli/ruoyi-vue-pro_1 into develop

# Conflicts:
#	yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/TencentSmsClient.java
#	yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/SmsClientTests.java
#	yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/TencentSmsClientTest.java
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/TencentSmsClient.java
... ... @@ -2,38 +2,30 @@ package cn.iocoder.yudao.module.system.framework.sms.core.client.impl;
2 2  
3 3 import cn.hutool.core.lang.Assert;
4 4 import cn.hutool.core.util.StrUtil;
5   -import cn.hutool.http.HttpRequest;
6   -import cn.hutool.http.HttpResponse;
7 5 import cn.hutool.json.JSONArray;
8 6 import cn.hutool.json.JSONObject;
9 7 import cn.hutool.json.JSONUtil;
10 8 import cn.iocoder.yudao.framework.common.core.KeyValue;
11 9 import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils;
12   -import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
  10 +import cn.iocoder.yudao.framework.common.util.http.HttpUtils;
13 11 import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsReceiveRespDTO;
14 12 import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsSendRespDTO;
15 13 import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsTemplateRespDTO;
16 14 import cn.iocoder.yudao.module.system.framework.sms.core.enums.SmsTemplateAuditStatusEnum;
17 15 import cn.iocoder.yudao.module.system.framework.sms.core.property.SmsChannelProperties;
18   -import com.fasterxml.jackson.annotation.JsonFormat;
19   -import com.fasterxml.jackson.annotation.JsonProperty;
20 16 import com.google.common.annotations.VisibleForTesting;
21 17 import jakarta.xml.bind.DatatypeConverter;
22   -import lombok.Data;
23 18  
24 19 import javax.crypto.Mac;
25 20 import javax.crypto.spec.SecretKeySpec;
26 21 import java.nio.charset.StandardCharsets;
27 22 import java.text.SimpleDateFormat;
28   -import java.time.LocalDateTime;
29 23 import java.util.*;
30 24  
31 25 import static cn.hutool.crypto.digest.DigestUtil.sha256Hex;
32 26 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
33   -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
34   -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT;
35 27  
36   -// TODO @scholar 建议参考 AliyunSmsClient 优化下
  28 +
37 29 /**
38 30 * 腾讯云短信功能实现
39 31 *
... ... @@ -104,14 +96,15 @@ public class TencentSmsClient extends AbstractSmsClient {
104 96 body.put("TemplateId",apiTemplateId);
105 97 body.put("TemplateParamSet",ArrayUtils.toArray(templateParams, e -> String.valueOf(e.getValue())));
106 98  
107   - JSONObject JsonResponse = sendSmsRequest(body,"SendSms","2021-01-11","ap-guangzhou");
108   - SmsResponse smsResponse = getSmsSendResponse(JsonResponse);
109   -
110   - return new SmsSendRespDTO().setSuccess(smsResponse.success).setApiMsg(smsResponse.data.toString());
  99 + JSONObject JsonResponse = request(body,"SendSms","2021-01-11","ap-guangzhou");
111 100  
  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"));
112 105 }
113 106  
114   - JSONObject sendSmsRequest(TreeMap<String, Object> body,String action,String version,String region) throws Exception {
  107 + JSONObject request(TreeMap<String, Object> body,String action,String version,String region) throws Exception {
115 108  
116 109 String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
117 110 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
... ... @@ -156,12 +149,9 @@ public class TencentSmsClient extends AbstractSmsClient {
156 149 headers.put("X-TC-Version", version);
157 150 headers.put("X-TC-Region", region);
158 151  
159   - HttpResponse response = HttpRequest.post("https://"+host)
160   - .addHeaders(headers)
161   - .body(JSONUtil.toJsonStr(body))
162   - .execute();
  152 + String responseBody = HttpUtils.post("https://"+host, headers, JSONUtil.toJsonStr(body));
163 153  
164   - return JSONUtil.parseObj(response.body());
  154 + return JSONUtil.parseObj(responseBody);
165 155 }
166 156  
167 157 public static byte[] hmac256(byte[] key, String msg) throws Exception {
... ... @@ -171,22 +161,20 @@ public class TencentSmsClient extends AbstractSmsClient {
171 161 return mac.doFinal(msg.getBytes(StandardCharsets.UTF_8));
172 162 }
173 163  
174   - private SmsResponse getSmsSendResponse(JSONObject resJson) {
175   - SmsResponse smsResponse = new SmsResponse();
176   - JSONArray statusJson =resJson.getJSONObject("Response").getJSONArray("SendStatusSet");
177   - smsResponse.setSuccess("Ok".equals(statusJson.getJSONObject(0).getStr("Code")));
178   - smsResponse.setData(resJson);
179   - return smsResponse;
180   - }
181   -
182 164 @Override
183 165 public List<SmsReceiveRespDTO> parseSmsReceiveStatus(String text) {
184   - List<SmsReceiveStatus> callback = JsonUtils.parseArray(text, SmsReceiveStatus.class);
185   - return convertList(callback, status -> new SmsReceiveRespDTO()
186   - .setSuccess(SmsReceiveStatus.SUCCESS_CODE.equalsIgnoreCase(status.getStatus()))
187   - .setErrorCode(status.getErrCode()).setErrorMsg(status.getDescription())
188   - .setMobile(status.getMobile()).setReceiveTime(status.getReceiveTime())
189   - .setSerialNo(status.getSerialNo()).setLogId(status.getSessionContext().getLogId()));
  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 + });
190 178 }
191 179  
192 180 @Override
... ... @@ -194,46 +182,20 @@ public class TencentSmsClient extends AbstractSmsClient {
194 182  
195 183 // 构建请求
196 184 TreeMap<String, Object> body = new TreeMap<>();
197   - body.put("International",0);
  185 + body.put("International",INTERNATIONAL_CHINA);
198 186 Integer[] templateIds = {Integer.valueOf(apiTemplateId)};
199 187 body.put("TemplateIdSet",templateIds);
200 188  
201   - JSONObject JsonResponse = sendSmsRequest(body,"DescribeSmsTemplateList","2021-01-11","ap-guangzhou");
202   - QuerySmsTemplateResponse smsTemplateResponse = getSmsTemplateResponse(JsonResponse);
203   - String templateId = Integer.toString(smsTemplateResponse.getDescribeTemplateStatusSet().get(0).getTemplateId());
204   - String content = smsTemplateResponse.getDescribeTemplateStatusSet().get(0).getTemplateContent();
205   - Integer templateStatus = smsTemplateResponse.getDescribeTemplateStatusSet().get(0).getStatusCode();
206   - String auditReason = smsTemplateResponse.getDescribeTemplateStatusSet().get(0).getReviewReply();
207   -
208   - return new SmsTemplateRespDTO().setId(templateId).setContent(content)
209   - .setAuditStatus(convertSmsTemplateAuditStatus(templateStatus)).setAuditReason(auditReason);
210   - }
211   -
212   - private QuerySmsTemplateResponse getSmsTemplateResponse(JSONObject resJson) {
213   -
214   - QuerySmsTemplateResponse smsTemplateResponse = new QuerySmsTemplateResponse();
  189 + JSONObject JsonResponse = request(body,"DescribeSmsTemplateList","2021-01-11","ap-guangzhou");
  190 + System.out.println("JsonResponse======"+JsonResponse);
215 191  
216   - smsTemplateResponse.setRequestId(resJson.getJSONObject("Response").getStr("RequestId"));
  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();
217 196  
218   - smsTemplateResponse.setDescribeTemplateStatusSet(new ArrayList<>());
219   -
220   - QuerySmsTemplateResponse.TemplateInfo templateInfo = new QuerySmsTemplateResponse.TemplateInfo();
221   -
222   - Object statusObject = resJson.getJSONObject("Response").getJSONArray("DescribeTemplateStatusSet").get(0);
223   -
224   - JSONObject statusJSON = new JSONObject(statusObject);
225   -
226   - templateInfo.setTemplateContent(statusJSON.get("TemplateContent").toString());
227   -
228   - templateInfo.setStatusCode(Integer.parseInt(statusJSON.get("StatusCode").toString()));
229   -
230   - templateInfo.setReviewReply(statusJSON.get("ReviewReply").toString());
231   -
232   - templateInfo.setTemplateId(Integer.parseInt(statusJSON.get("TemplateId").toString()));
233   -
234   - smsTemplateResponse.getDescribeTemplateStatusSet().add(templateInfo);
235   -
236   - return smsTemplateResponse;
  197 + return new SmsTemplateRespDTO().setId(apiTemplateId).setContent(content)
  198 + .setAuditStatus(convertSmsTemplateAuditStatus(templateStatus)).setAuditReason(auditReason);
237 199 }
238 200  
239 201 @VisibleForTesting
... ... @@ -245,113 +207,4 @@ public class TencentSmsClient extends AbstractSmsClient {
245 207 default: throw new IllegalArgumentException(String.format("未知审核状态(%d)", templateStatus));
246 208 }
247 209 }
248   -
249   - @Data
250   - public static class SmsResponse {
251   -
252   - /**
253   - * 是否成功
254   - */
255   - private boolean success;
256   -
257   - /**
258   - * 厂商原返回体
259   - */
260   - private Object data;
261   -
262   - }
263   -
264   -
265   - /**
266   - * <p>类名: QuerySmsTemplateResponse
267   - * <p>说明: sms模板查询返回信息
268   - *
269   - * @author :scholar
270   - * 2024/07/17 0:25
271   - **/
272   - @Data
273   - public static class QuerySmsTemplateResponse {
274   - private List<TemplateInfo> DescribeTemplateStatusSet;
275   - private String RequestId;
276   - @Data
277   - static class TemplateInfo {
278   - private String TemplateName;
279   - private Integer TemplateId;
280   - private Integer International;
281   - private String ReviewReply;
282   - private long CreateTime;
283   - private String TemplateContent;
284   - private Integer StatusCode;
285   - }
286   - }
287   -
288   - @Data
289   - private static class SmsReceiveStatus {
290   -
291   - /**
292   - * 短信接受成功 code
293   - */
294   - public static final String SUCCESS_CODE = "SUCCESS";
295   -
296   - /**
297   - * 用户实际接收到短信的时间
298   - */
299   - @JsonProperty("user_receive_time")
300   - @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)
301   - private LocalDateTime receiveTime;
302   -
303   - /**
304   - * 国家(或地区)码
305   - */
306   - @JsonProperty("nationcode")
307   - private String nationCode;
308   -
309   - /**
310   - * 手机号码
311   - */
312   - private String mobile;
313   -
314   - /**
315   - * 实际是否收到短信接收状态,SUCCESS(成功)、FAIL(失败)
316   - */
317   - @JsonProperty("report_status")
318   - private String status;
319   -
320   - /**
321   - * 用户接收短信状态码错误信息
322   - */
323   - @JsonProperty("errmsg")
324   - private String errCode;
325   -
326   - /**
327   - * 用户接收短信状态描述
328   - */
329   - @JsonProperty("description")
330   - private String description;
331   -
332   - /**
333   - * 本次发送标识 ID(与发送接口返回的SerialNo对应)
334   - */
335   - @JsonProperty("sid")
336   - private String serialNo;
337   -
338   - /**
339   - * 用户的 session 内容(与发送接口的请求参数 SessionContext 一致)
340   - */
341   - @JsonProperty("ext")
342   - private SessionContext sessionContext;
343   -
344   - }
345   -
346   - @VisibleForTesting
347   - @Data
348   - static class SessionContext {
349   -
350   - /**
351   - * 发送短信记录id
352   - */
353   - private Long logId;
354   -
355   - }
356   -
357   -}
  210 +}
358 211 \ 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/SmsClientTests.java
... ... @@ -22,7 +22,8 @@ public class SmsClientTests {
22 22 public void testHuaweiSmsClient_sendSms() throws Throwable {
23 23 SmsChannelProperties properties = new SmsChannelProperties()
24 24 .setApiKey("123")
25   - .setApiSecret("456");
  25 + .setApiSecret("456")
  26 + .setSignature("runpu");
26 27 HuaweiSmsClient client = new HuaweiSmsClient(properties);
27 28 // 准备参数
28 29 Long sendLogId = System.currentTimeMillis();
... ... @@ -58,11 +59,11 @@ public class SmsClientTests {
58 59 SmsChannelProperties properties = new SmsChannelProperties()
59 60 .setApiKey("LTAI5tAicJAxaSFiZuGGeXHR")
60 61 .setApiSecret("Fdr9vadxnDvS6GJU0W1tijQ0VmLhYz")
61   - .setSignature("Ballcat");
  62 + .setSignature("runpu");
62 63 AliyunSmsClient client = new AliyunSmsClient(properties);
63 64 // 准备参数
64 65 Long sendLogId = System.currentTimeMillis();
65   - String mobile = "173213154791";
  66 + String mobile = "15601691323";
66 67 String apiTemplateId = "SMS_207945135";
67 68 // 调用
68 69 SmsSendRespDTO sendRespDTO = client.sendSms(sendLogId, mobile, apiTemplateId, List.of(new KeyValue<>("code", "1024")));
... ... @@ -99,4 +100,40 @@ public class SmsClientTests {
99 100 System.out.println(statuses);
100 101 }
101 102  
  103 + // ========== 腾讯云 ==========
  104 +
  105 + @Test
  106 + @Disabled
  107 + public void testTencentSmsClient_sendSms() throws Throwable {
  108 + SmsChannelProperties properties = new SmsChannelProperties()
  109 + .setApiKey("LTAI5tAicJAxaSFiZuGGeXHR 1428926523")
  110 + .setApiSecret("Fdr9vadxnDvS6GJU0W1tijQ0VmLhYz")
  111 + .setSignature("芋道源码");
  112 + TencentSmsClient client = new TencentSmsClient(properties);
  113 + // 准备参数
  114 + Long sendLogId = System.currentTimeMillis();
  115 + String mobile = "15601691323";
  116 + String apiTemplateId = "2136358";
  117 + // 调用
  118 + SmsSendRespDTO sendRespDTO = client.sendSms(sendLogId, mobile, apiTemplateId, List.of(new KeyValue<>("code", "1024")));
  119 + // 打印结果
  120 + System.out.println(sendRespDTO);
  121 + }
  122 +
  123 + @Test
  124 + @Disabled
  125 + public void testTencentSmsClient_getSmsTemplate() throws Throwable {
  126 + SmsChannelProperties properties = new SmsChannelProperties()
  127 + .setApiKey("LTAI5tAicJAxaSFiZuGGeXHR 1428926523")
  128 + .setApiSecret("Fdr9vadxnDvS6GJU0W1tijQ0VmLhYz")
  129 + .setSignature("芋道源码");
  130 + TencentSmsClient client = new TencentSmsClient(properties);
  131 + // 准备参数
  132 + String apiTemplateId = "2136358";
  133 + // 调用
  134 + SmsTemplateRespDTO template = client.getSmsTemplate(apiTemplateId);
  135 + // 打印结果
  136 + System.out.println(template);
  137 + }
102 138 }
  139 +
... ...
yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/TencentSmsClientTest.java
1 1 package cn.iocoder.yudao.module.system.framework.sms.core.client.impl;
2 2  
3   -import cn.hutool.core.util.ReflectUtil;
  3 +import cn.iocoder.yudao.framework.common.core.KeyValue;
  4 +import cn.iocoder.yudao.framework.common.util.http.HttpUtils;
4 5 import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
5   -import cn.iocoder.yudao.module.system.framework.sms.core.client.SmsClient;
6 6 import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsReceiveRespDTO;
  7 +import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsSendRespDTO;
  8 +import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsTemplateRespDTO;
7 9 import cn.iocoder.yudao.module.system.framework.sms.core.enums.SmsTemplateAuditStatusEnum;
8 10 import cn.iocoder.yudao.module.system.framework.sms.core.property.SmsChannelProperties;
  11 +import com.google.common.collect.Lists;
  12 +
9 13 import org.junit.jupiter.api.Test;
10 14 import org.mockito.InjectMocks;
11   -import org.mockito.Mock;
  15 +import org.mockito.MockedStatic;
12 16  
13 17 import java.time.LocalDateTime;
14 18 import java.util.List;
15 19  
16   -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString;
  20 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
17 21 import static org.junit.jupiter.api.Assertions.*;
  22 +import static org.mockito.ArgumentMatchers.*;
  23 +import static org.mockito.ArgumentMatchers.anyString;
  24 +import static org.mockito.Mockito.mockStatic;
18 25  
19   -// TODO @芋艿:补全单测
20 26 /**
21 27 * {@link TencentSmsClient} 的单元测试
22 28 *
... ... @@ -32,9 +38,6 @@ public class TencentSmsClientTest extends BaseMockitoUnitTest {
32 38 @InjectMocks
33 39 private TencentSmsClient smsClient = new TencentSmsClient(properties);
34 40  
35   - @Mock
36   - private SmsClient client;
37   -
38 41 @Test
39 42 public void testDoInit() {
40 43 // 准备参数
... ... @@ -42,104 +45,93 @@ public class TencentSmsClientTest extends BaseMockitoUnitTest {
42 45  
43 46 // 调用
44 47 smsClient.doInit();
45   - // 断言
46   - assertNotSame(client, ReflectUtil.getFieldValue(smsClient, "client"));
47 48 }
48 49  
49 50 @Test
50   - public void testRefresh() {
51   - // 准备参数
52   - SmsChannelProperties p = new SmsChannelProperties()
53   - .setApiKey(randomString() + " " + randomString()) // 随机一个 apiKey,避免构建报错
54   - .setApiSecret(randomString()) // 随机一个 apiSecret,避免构建报错
55   - .setSignature("芋道源码");
56   - // 调用
57   - smsClient.refresh(p);
58   - // 断言
59   - assertNotSame(client, ReflectUtil.getFieldValue(smsClient, "client"));
  51 + public void testDoSendSms_success() throws Throwable {
  52 +
  53 + try (MockedStatic<HttpUtils> httpUtilsMockedStatic = mockStatic(HttpUtils.class)) {
  54 + // 准备参数
  55 + Long sendLogId = randomLongId();
  56 + String mobile = randomString();
  57 + String apiTemplateId = randomString();
  58 + List<KeyValue<String, Object>> templateParams = Lists.newArrayList(
  59 + new KeyValue<>("1", 1234), new KeyValue<>("2", "login"));
  60 +
  61 + // mock 方法
  62 + httpUtilsMockedStatic.when(() -> HttpUtils.post(anyString(), anyMap(), anyString()))
  63 + .thenReturn(
  64 + "{\n" +
  65 + " \"Response\": {\n" +
  66 + " \"SendStatusSet\": [\n" +
  67 + " {\n" +
  68 + " \"SerialNo\": \"5000:1045710669157053657849499619\",\n" +
  69 + " \"PhoneNumber\": \"+8618511122233\",\n" +
  70 + " \"Fee\": 1,\n" +
  71 + " \"SessionContext\": \"test\",\n" +
  72 + " \"Code\": \"Ok\",\n" +
  73 + " \"Message\": \"send success\",\n" +
  74 + " \"IsoCode\": \"CN\"\n" +
  75 + " },\n" +
  76 + " ],\n" +
  77 + " \"RequestId\": \"a0aabda6-cf91-4f3e-a81f-9198114a2279\"\n" +
  78 + " }\n" +
  79 + "}"
  80 + );
  81 +
  82 + // 调用
  83 + SmsSendRespDTO result = smsClient.sendSms(sendLogId, mobile,
  84 + apiTemplateId, templateParams);
  85 + // 断言
  86 + assertTrue(result.getSuccess());
  87 + assertEquals("5000:1045710669157053657849499619", result.getSerialNo());
  88 + assertEquals("a0aabda6-cf91-4f3e-a81f-9198114a2279", result.getApiRequestId());
  89 + assertEquals("send success", result.getApiMsg());
  90 +
  91 + }
60 92 }
61 93  
62   -// @Test
63   -// public void testDoSendSms_success() throws Throwable {
64   -// // 准备参数
65   -// Long sendLogId = randomLongId();
66   -// String mobile = randomString();
67   -// String apiTemplateId = randomString();
68   -// List<KeyValue<String, Object>> templateParams = Lists.newArrayList(
69   -// new KeyValue<>("1", 1234), new KeyValue<>("2", "login"));
70   -// String requestId = randomString();
71   -// String serialNo = randomString();
72   -// // mock 方法
73   -// SendSmsResponse response = randomPojo(SendSmsResponse.class, o -> {
74   -// o.setRequestId(requestId);
75   -// SendStatus[] sendStatuses = new SendStatus[1];
76   -// o.setSendStatusSet(sendStatuses);
77   -// SendStatus sendStatus = new SendStatus();
78   -// sendStatuses[0] = sendStatus;
79   -// sendStatus.setCode(TencentSmsClient.API_CODE_SUCCESS);
80   -// sendStatus.setMessage("send success");
81   -// sendStatus.setSerialNo(serialNo);
82   -// });
83   -// when(client.SendSms(argThat(request -> {
84   -// assertEquals(mobile, request.getPhoneNumberSet()[0]);
85   -// assertEquals(properties.getSignature(), request.getSignName());
86   -// assertEquals(apiTemplateId, request.getTemplateId());
87   -// assertEquals(toJsonString(ArrayUtils.toArray(new ArrayList<>(MapUtils.convertMap(templateParams).values()), String::valueOf)),
88   -// toJsonString(request.getTemplateParamSet()));
89   -// assertEquals(sendLogId, ReflectUtil.getFieldValue(JsonUtils.parseObject(request.getSessionContext(), TencentSmsClient.SessionContext.class), "logId"));
90   -// return true;
91   -// }))).thenReturn(response);
92   -//
93   -// // 调用
94   -// SmsSendRespDTO result = smsClient.sendSms(sendLogId, mobile, apiTemplateId, templateParams);
95   -// // 断言
96   -// assertTrue(result.getSuccess());
97   -// assertEquals(response.getRequestId(), result.getApiRequestId());
98   -// assertEquals(response.getSendStatusSet()[0].getCode(), result.getApiCode());
99   -// assertEquals(response.getSendStatusSet()[0].getMessage(), result.getApiMsg());
100   -// assertEquals(response.getSendStatusSet()[0].getSerialNo(), result.getSerialNo());
101   -// }
102   -
103   -// @Test
104   -// public void testDoSendSms_fail() throws Throwable {
105   -// // 准备参数
106   -// Long sendLogId = randomLongId();
107   -// String mobile = randomString();
108   -// String apiTemplateId = randomString();
109   -// List<KeyValue<String, Object>> templateParams = Lists.newArrayList(
110   -// new KeyValue<>("1", 1234), new KeyValue<>("2", "login"));
111   -// String requestId = randomString();
112   -// String serialNo = randomString();
113   -// // mock 方法
114   -// SendSmsResponse response = randomPojo(SendSmsResponse.class, o -> {
115   -// o.setRequestId(requestId);
116   -// SendStatus[] sendStatuses = new SendStatus[1];
117   -// o.setSendStatusSet(sendStatuses);
118   -// SendStatus sendStatus = new SendStatus();
119   -// sendStatuses[0] = sendStatus;
120   -// sendStatus.setCode("ERROR");
121   -// sendStatus.setMessage("send success");
122   -// sendStatus.setSerialNo(serialNo);
123   -// });
124   -// when(client.SendSms(argThat(request -> {
125   -// assertEquals(mobile, request.getPhoneNumberSet()[0]);
126   -// assertEquals(properties.getSignature(), request.getSignName());
127   -// assertEquals(apiTemplateId, request.getTemplateId());
128   -// assertEquals(toJsonString(ArrayUtils.toArray(new ArrayList<>(MapUtils.convertMap(templateParams).values()), String::valueOf)),
129   -// toJsonString(request.getTemplateParamSet()));
130   -// assertEquals(sendLogId, ReflectUtil.getFieldValue(JsonUtils.parseObject(request.getSessionContext(), TencentSmsClient.SessionContext.class), "logId"));
131   -// return true;
132   -// }))).thenReturn(response);
133   -//
134   -// // 调用
135   -// SmsSendRespDTO result = smsClient.sendSms(sendLogId, mobile, apiTemplateId, templateParams);
136   -// // 断言
137   -// assertFalse(result.getSuccess());
138   -// assertEquals(response.getRequestId(), result.getApiRequestId());
139   -// assertEquals(response.getSendStatusSet()[0].getCode(), result.getApiCode());
140   -// assertEquals(response.getSendStatusSet()[0].getMessage(), result.getApiMsg());
141   -// assertEquals(response.getSendStatusSet()[0].getSerialNo(), result.getSerialNo());
142   -// }
  94 + @Test
  95 + public void testDoSendSms_fail() throws Throwable {
  96 + try (MockedStatic<HttpUtils> httpUtilsMockedStatic = mockStatic(HttpUtils.class)) {
  97 + // 准备参数
  98 + Long sendLogId = randomLongId();
  99 + String mobile = randomString();
  100 + String apiTemplateId = randomString();
  101 + List<KeyValue<String, Object>> templateParams = Lists.newArrayList(
  102 + new KeyValue<>("1", 1234), new KeyValue<>("2", "login"));
  103 +
  104 + // mock 方法
  105 + httpUtilsMockedStatic.when(() -> HttpUtils.post(anyString(), anyMap(), anyString()))
  106 + .thenReturn(
  107 + "{\n" +
  108 + " \"Response\": {\n" +
  109 + " \"SendStatusSet\": [\n" +
  110 + " {\n" +
  111 + " \"SerialNo\": \"5000:1045710669157053657849499619\",\n" +
  112 + " \"PhoneNumber\": \"+8618511122233\",\n" +
  113 + " \"Fee\": 1,\n" +
  114 + " \"SessionContext\": \"test\",\n" +
  115 + " \"Code\": \"ERROR\",\n" +
  116 + " \"Message\": \"send success\",\n" +
  117 + " \"IsoCode\": \"CN\"\n" +
  118 + " },\n" +
  119 + " ],\n" +
  120 + " \"RequestId\": \"a0aabda6-cf91-4f3e-a81f-9198114a2279\"\n" +
  121 + " }\n" +
  122 + "}"
  123 + );
  124 +
  125 + // 调用
  126 + SmsSendRespDTO result = smsClient.sendSms(sendLogId, mobile,
  127 + apiTemplateId, templateParams);
  128 + // 断言
  129 + assertFalse(result.getSuccess());
  130 + assertEquals("5000:1045710669157053657849499619", result.getSerialNo());
  131 + assertEquals("a0aabda6-cf91-4f3e-a81f-9198114a2279", result.getApiRequestId());
  132 + assertEquals("send success", result.getApiMsg());
  133 + }
  134 + }
143 135  
144 136 @Test
145 137 public void testParseSmsReceiveStatus() {
... ... @@ -156,7 +148,6 @@ public class TencentSmsClientTest extends BaseMockitoUnitTest {
156 148 " \"ext\": {\"logId\":\"67890\"}\n" +
157 149 " }\n" +
158 150 "]";
159   - // mock 方法
160 151  
161 152 // 调用
162 153 List<SmsReceiveRespDTO> statuses = smsClient.parseSmsReceiveStatus(text);
... ... @@ -164,42 +155,46 @@ public class TencentSmsClientTest extends BaseMockitoUnitTest {
164 155 assertEquals(1, statuses.size());
165 156 assertTrue(statuses.get(0).getSuccess());
166 157 assertEquals("DELIVRD", statuses.get(0).getErrorCode());
167   - assertEquals("用户短信送达成功", statuses.get(0).getErrorMsg());
168 158 assertEquals("13900000001", statuses.get(0).getMobile());
169 159 assertEquals(LocalDateTime.of(2015, 10, 17, 8, 3, 4), statuses.get(0).getReceiveTime());
170 160 assertEquals("12345", statuses.get(0).getSerialNo());
171   - assertEquals(67890L, statuses.get(0).getLogId());
172 161 }
173 162  
174   -// @Test
175   -// public void testGetSmsTemplate() throws Throwable {
176   -// // 准备参数
177   -// Long apiTemplateId = randomLongId();
178   -// String requestId = randomString();
179   -//
180   -// // mock 方法
181   -// DescribeSmsTemplateListResponse response = randomPojo(DescribeSmsTemplateListResponse.class, o -> {
182   -// DescribeTemplateListStatus[] describeTemplateListStatuses = new DescribeTemplateListStatus[1];
183   -// DescribeTemplateListStatus templateStatus = new DescribeTemplateListStatus();
184   -// templateStatus.setTemplateId(apiTemplateId);
185   -// templateStatus.setStatusCode(0L);// 设置模板通过
186   -// describeTemplateListStatuses[0] = templateStatus;
187   -// o.setDescribeTemplateStatusSet(describeTemplateListStatuses);
188   -// o.setRequestId(requestId);
189   -// });
190   -// when(client.DescribeSmsTemplateList(argThat(request -> {
191   -// assertEquals(apiTemplateId, request.getTemplateIdSet()[0]);
192   -// return true;
193   -// }))).thenReturn(response);
194   -//
195   -// // 调用
196   -// SmsTemplateRespDTO result = smsClient.getSmsTemplate(apiTemplateId.toString());
197   -// // 断言
198   -// assertEquals(response.getDescribeTemplateStatusSet()[0].getTemplateId().toString(), result.getId());
199   -// assertEquals(response.getDescribeTemplateStatusSet()[0].getTemplateContent(), result.getContent());
200   -// assertEquals(SmsTemplateAuditStatusEnum.SUCCESS.getStatus(), result.getAuditStatus());
201   -// assertEquals(response.getDescribeTemplateStatusSet()[0].getReviewReply(), result.getAuditReason());
202   -// }
  163 + @Test
  164 + public void testGetSmsTemplate() throws Throwable {
  165 +
  166 + try (MockedStatic<HttpUtils> httpUtilsMockedStatic = mockStatic(HttpUtils.class)) {
  167 +
  168 + // 准备参数
  169 + String apiTemplateId = "1122";
  170 +
  171 + // mock 方法
  172 + httpUtilsMockedStatic.when(() -> HttpUtils.post(anyString(), anyMap(), anyString()))
  173 + .thenReturn("{ \"Response\": {\n" +
  174 + " \"DescribeTemplateStatusSet\": [\n" +
  175 + " {\n" +
  176 + " \"TemplateName\": \"验证码\",\n" +
  177 + " \"TemplateId\": 1122,\n" +
  178 + " \"International\": 0,\n" +
  179 + " \"ReviewReply\": \"审批备注\",\n" +
  180 + " \"CreateTime\": 1617379200,\n" +
  181 + " \"TemplateContent\": \"您的验证码是{1}\",\n" +
  182 + " \"StatusCode\": 0\n" +
  183 + " },\n" +
  184 + " \n" +
  185 + " ],\n" +
  186 + " \"RequestId\": \"f36e4f00-605e-49b1-ad0d-bfaba81c7325\"\n" +
  187 + " }}");
  188 +
  189 + // 调用
  190 + SmsTemplateRespDTO result = smsClient.getSmsTemplate(apiTemplateId);
  191 + // 断言
  192 + assertEquals("1122", result.getId());
  193 + assertEquals("您的验证码是{1}", result.getContent());
  194 + assertEquals(SmsTemplateAuditStatusEnum.SUCCESS.getStatus(), result.getAuditStatus());
  195 + assertEquals("审批备注", result.getAuditReason());
  196 + }
  197 + }
203 198  
204 199 @Test
205 200 public void testConvertSmsTemplateAuditStatus() {
... ...