@Override
    public SmsSendRespDTO sendSms(Long sendLogId, String mobile,
                                  String apiTemplateId, List<KeyValue<String, Object>> templateParams) throws Throwable {
        // 1. 执行请求
        // 参考链接 https://cloud.tencent.com/document/product/382/55981
        TreeMap<String, Object> body = new TreeMap<>();
        body.put("PhoneNumberSet", new String[]{mobile});
        body.put("SmsSdkAppId", getSdkAppId());
        body.put("SignName", properties.getSignature());
        body.put("TemplateId",apiTemplateId);
        body.put("TemplateParamSet", ArrayUtils.toArray(templateParams, param -> String.valueOf(param.getValue())));
        JSONObject response = request("SendSms", body);

        // 2. 解析请求
        JSONObject responseResult = response.getJSONObject("Response");
        JSONObject error = responseResult.getJSONObject("Error");
        if (error != null) {
            return new SmsSendRespDTO().setSuccess(false)
                    .setApiRequestId(responseResult.getStr("RequestId"))
                    .setApiCode(error.getStr("Code"))
                    .setApiMsg(error.getStr("Message"));
        }
        JSONObject responseData = responseResult.getJSONArray("SendStatusSet").getJSONObject(0);
        return new SmsSendRespDTO().setSuccess(Objects.equals(API_CODE_SUCCESS, responseData.getStr("Code")))
                .setApiRequestId(responseResult.getStr("RequestId"))
                .setSerialNo(responseData.getStr("SerialNo"))
                .setApiMsg(responseData.getStr("Message"));
    }
@Test
    public void testDoSendSms_success() throws Throwable {
        try (MockedStatic<HttpUtils> httpUtilsMockedStatic = mockStatic(HttpUtils.class)) {
            // 准备参数
            Long sendLogId = randomLongId();
            String mobile = randomString();
            String apiTemplateId = randomString();
            List<KeyValue<String, Object>> templateParams = Lists.newArrayList(
                    new KeyValue<>("1", 1234), new KeyValue<>("2", "login"));
            // mock 方法
            httpUtilsMockedStatic.when(() -> HttpUtils.post(anyString(), anyMap(), anyString()))
                    .thenReturn("{\n" +
                                    "    \"Response\": {\n" +
                                    "        \"SendStatusSet\": [\n" +
                                    "            {\n" +
                                    "                \"SerialNo\": \"5000:1045710669157053657849499619\",\n" +
                                    "                \"PhoneNumber\": \"+8618511122233\",\n" +
                                    "                \"Fee\": 1,\n" +
                                    "                \"SessionContext\": \"test\",\n" +
                                    "                \"Code\": \"Ok\",\n" +
                                    "                \"Message\": \"send success\",\n" +
                                    "                \"IsoCode\": \"CN\"\n" +
                                    "            },\n" +
                                    "        ],\n" +
                                    "        \"RequestId\": \"a0aabda6-cf91-4f3e-a81f-9198114a2279\"\n" +
                                    "    }\n" +
                                    "}");

            // 调用
            SmsSendRespDTO result = smsClient.sendSms(sendLogId, mobile,
                    apiTemplateId, templateParams);
            // 断言
            assertTrue(result.getSuccess());
            assertEquals("5000:1045710669157053657849499619", result.getSerialNo());
            assertEquals("a0aabda6-cf91-4f3e-a81f-9198114a2279", result.getApiRequestId());
            assertEquals("send success", result.getApiMsg());
        }
    }