mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-11-01 02:38:43 +08:00 
			
		
		
		
	完成todo部分
1,华为云短信实现优化,去除不必要VO; 2,增加华为云短信功能单测; 3,fix华为云短信接收状态回调的bug;
This commit is contained in:
		| @@ -5,16 +5,17 @@ import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; | |||||||
| import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; | import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; | ||||||
| import cn.iocoder.yudao.module.system.framework.sms.core.enums.SmsChannelEnum; | import cn.iocoder.yudao.module.system.framework.sms.core.enums.SmsChannelEnum; | ||||||
| import cn.iocoder.yudao.module.system.service.sms.SmsSendService; | import cn.iocoder.yudao.module.system.service.sms.SmsSendService; | ||||||
|  | import com.xingyuv.captcha.util.StreamUtils; | ||||||
| import io.swagger.v3.oas.annotations.Operation; | import io.swagger.v3.oas.annotations.Operation; | ||||||
| import io.swagger.v3.oas.annotations.tags.Tag; | import io.swagger.v3.oas.annotations.tags.Tag; | ||||||
| import org.springframework.web.bind.annotation.PostMapping; | import org.springframework.web.bind.annotation.*; | ||||||
| import org.springframework.web.bind.annotation.RequestMapping; |  | ||||||
| import org.springframework.web.bind.annotation.RestController; |  | ||||||
|  |  | ||||||
| import jakarta.annotation.Resource; | import jakarta.annotation.Resource; | ||||||
| import jakarta.annotation.security.PermitAll; | import jakarta.annotation.security.PermitAll; | ||||||
| import jakarta.servlet.http.HttpServletRequest; | import jakarta.servlet.http.HttpServletRequest; | ||||||
|  |  | ||||||
|  | import java.nio.charset.Charset; | ||||||
|  |  | ||||||
| import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||||||
|  |  | ||||||
| @Tag(name = "管理后台 - 短信回调") | @Tag(name = "管理后台 - 短信回调") | ||||||
| @@ -50,10 +51,8 @@ public class SmsCallbackController { | |||||||
|     @PermitAll |     @PermitAll | ||||||
|     @Operation(summary = "华为云短信的回调", description = "参见 https://support.huaweicloud.com/api-msgsms/sms_05_0003.html 文档") |     @Operation(summary = "华为云短信的回调", description = "参见 https://support.huaweicloud.com/api-msgsms/sms_05_0003.html 文档") | ||||||
|     @OperateLog(enable = false) |     @OperateLog(enable = false) | ||||||
|     public CommonResult<Boolean> receiveHuaweiSmsStatus(HttpServletRequest request) throws Throwable { |     public CommonResult<Boolean> receiveHuaweiSmsStatus(@RequestBody String requestBody) throws Throwable { | ||||||
|         String text = ServletUtils.getBody(request); |         smsSendService.receiveSmsStatus(SmsChannelEnum.HUAWEI.getCode(), requestBody); | ||||||
|         smsSendService.receiveSmsStatus(SmsChannelEnum.HUAWEI.getCode(), text); |  | ||||||
|         return success(true); |         return success(true); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -5,12 +5,11 @@ import cn.hutool.core.lang.Assert; | |||||||
| import cn.hutool.core.util.StrUtil; | import cn.hutool.core.util.StrUtil; | ||||||
|  |  | ||||||
| import cn.hutool.crypto.SecureUtil; | import cn.hutool.crypto.SecureUtil; | ||||||
| import cn.hutool.http.HttpRequest; |  | ||||||
| import cn.hutool.http.HttpResponse; |  | ||||||
| import cn.hutool.json.JSONObject; | import cn.hutool.json.JSONObject; | ||||||
| import cn.hutool.json.JSONUtil; | import cn.hutool.json.JSONUtil; | ||||||
| import cn.iocoder.yudao.framework.common.core.KeyValue; | import cn.iocoder.yudao.framework.common.core.KeyValue; | ||||||
| import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | ||||||
|  | import cn.iocoder.yudao.framework.common.util.http.HttpUtils; | ||||||
| import cn.iocoder.yudao.framework.common.util.json.JsonUtils; | import cn.iocoder.yudao.framework.common.util.json.JsonUtils; | ||||||
| import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsReceiveRespDTO; | import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsReceiveRespDTO; | ||||||
| import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsSendRespDTO; | import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsSendRespDTO; | ||||||
| @@ -18,14 +17,14 @@ import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsTemplateR | |||||||
| import cn.iocoder.yudao.module.system.framework.sms.core.enums.SmsTemplateAuditStatusEnum; | import cn.iocoder.yudao.module.system.framework.sms.core.enums.SmsTemplateAuditStatusEnum; | ||||||
| import cn.iocoder.yudao.module.system.framework.sms.core.property.SmsChannelProperties; | import cn.iocoder.yudao.module.system.framework.sms.core.property.SmsChannelProperties; | ||||||
|  |  | ||||||
| import com.fasterxml.jackson.annotation.JsonFormat; |  | ||||||
| import com.fasterxml.jackson.annotation.JsonProperty; |  | ||||||
| import lombok.Data; |  | ||||||
| import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||||
|  |  | ||||||
| import java.io.UnsupportedEncodingException; | import java.io.UnsupportedEncodingException; | ||||||
|  | import java.net.URLDecoder; | ||||||
| import java.net.URLEncoder; | import java.net.URLEncoder; | ||||||
| import java.text.SimpleDateFormat; | import java.text.SimpleDateFormat; | ||||||
|  | import java.time.Instant; | ||||||
|  | import java.time.ZoneId; | ||||||
| import java.util.*; | import java.util.*; | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -33,9 +32,6 @@ import java.time.LocalDateTime; | |||||||
|  |  | ||||||
|  |  | ||||||
| import static cn.hutool.crypto.digest.DigestUtil.sha256Hex; | import static cn.hutool.crypto.digest.DigestUtil.sha256Hex; | ||||||
| import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; |  | ||||||
| import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; |  | ||||||
| import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT; |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /** | /** | ||||||
| @@ -47,9 +43,6 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DE | |||||||
| @Slf4j | @Slf4j | ||||||
| public class HuaweiSmsClient extends AbstractSmsClient { | public class HuaweiSmsClient extends AbstractSmsClient { | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 调用成功 code |  | ||||||
|      */ |  | ||||||
|     public static final String URL = "https://smsapi.cn-north-4.myhuaweicloud.com:443/sms/batchSendSms/v1";//APP接入地址+接口访问URI |     public static final String URL = "https://smsapi.cn-north-4.myhuaweicloud.com:443/sms/batchSendSms/v1";//APP接入地址+接口访问URI | ||||||
|     public static final String HOST = "smsapi.cn-north-4.myhuaweicloud.com:443"; |     public static final String HOST = "smsapi.cn-north-4.myhuaweicloud.com:443"; | ||||||
|     public static final String SIGNEDHEADERS = "content-type;host;x-sdk-date"; |     public static final String SIGNEDHEADERS = "content-type;host;x-sdk-date"; | ||||||
| @@ -78,13 +71,14 @@ public class HuaweiSmsClient extends AbstractSmsClient { | |||||||
|  |  | ||||||
|         List<String> templateParas = CollectionUtils.convertList(templateParams, kv -> String.valueOf(kv.getValue())); |         List<String> templateParas = CollectionUtils.convertList(templateParams, kv -> String.valueOf(kv.getValue())); | ||||||
|  |  | ||||||
|         JSONObject JsonResponse = sendSmsRequest(sender,mobile,templateId,templateParas,statusCallBack); |         JSONObject JsonResponse = request(sendLogId,sender,mobile,templateId,templateParas,statusCallBack); | ||||||
|         SmsResponse smsResponse = getSmsSendResponse(JsonResponse); |  | ||||||
|  |  | ||||||
|         return new SmsSendRespDTO().setSuccess(smsResponse.success).setApiMsg(smsResponse.data.toString()); |         return new SmsSendRespDTO().setSuccess("000000".equals(JsonResponse.getStr("code"))) | ||||||
|  |                 .setSerialNo(JsonResponse.getJSONArray("result").getJSONObject(0).getStr("smsMsgId")) | ||||||
|  |                 .setApiCode(JsonResponse.getJSONArray("result").getJSONObject(0).getStr("status")); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     JSONObject sendSmsRequest(String sender,String mobile,String templateId,List<String> templateParas,String statusCallBack) throws UnsupportedEncodingException { |     JSONObject request(Long sendLogId,String sender,String mobile,String templateId,List<String> templateParas,String statusCallBack) throws UnsupportedEncodingException { | ||||||
|  |  | ||||||
|         SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd'T'HHmmss'Z'", Locale.ENGLISH); |         SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd'T'HHmmss'Z'", Locale.ENGLISH); | ||||||
|         sdf.setTimeZone(TimeZone.getTimeZone("UTC")); |         sdf.setTimeZone(TimeZone.getTimeZone("UTC")); | ||||||
| @@ -97,8 +91,7 @@ public class HuaweiSmsClient extends AbstractSmsClient { | |||||||
|         String canonicalHeaders = "content-type:application/x-www-form-urlencoded\n" |         String canonicalHeaders = "content-type:application/x-www-form-urlencoded\n" | ||||||
|                 + "host:"+ HOST +"\n" |                 + "host:"+ HOST +"\n" | ||||||
|                 + "x-sdk-date:" + sdkDate + "\n"; |                 + "x-sdk-date:" + sdkDate + "\n"; | ||||||
|         //请求Body,不携带签名名称时,signature请填null |         String body = buildRequestBody(sender, mobile, templateId, templateParas, statusCallBack, sendLogId); | ||||||
|         String body = buildRequestBody(sender, mobile, templateId, templateParas, statusCallBack, null); |  | ||||||
|         if (null == body || body.isEmpty()) { |         if (null == body || body.isEmpty()) { | ||||||
|             return null; |             return null; | ||||||
|         } |         } | ||||||
| @@ -118,26 +111,29 @@ public class HuaweiSmsClient extends AbstractSmsClient { | |||||||
|                 + "SignedHeaders=" + SIGNEDHEADERS + ", " + "Signature=" + signature; |                 + "SignedHeaders=" + SIGNEDHEADERS + ", " + "Signature=" + signature; | ||||||
|  |  | ||||||
|         // ************* 步骤 5:构造HttpRequest 并执行request请求,获得response ************* |         // ************* 步骤 5:构造HttpRequest 并执行request请求,获得response ************* | ||||||
|         HttpResponse response = HttpRequest.post(URL) |         TreeMap<String, String> headers = new TreeMap<>(); | ||||||
|                 .header("Content-Type", "application/x-www-form-urlencoded") |         headers.put("Content-Type", "application/x-www-form-urlencoded"); | ||||||
|                 .header("X-Sdk-Date", sdkDate) |         headers.put("X-Sdk-Date", sdkDate); | ||||||
|                 .header("host",HOST) |         headers.put("host", HOST); | ||||||
|                 .header("Authorization", authorization) |         headers.put("Authorization", authorization); | ||||||
|                 .body(body) |  | ||||||
|                 .execute(); |  | ||||||
|  |  | ||||||
|         return JSONUtil.parseObj(response.body()); |         String responseBody = HttpUtils.post(URL, headers, body); | ||||||
|     } |         return JSONUtil.parseObj(responseBody); | ||||||
|  | // | ||||||
|     private SmsResponse getSmsSendResponse(JSONObject resJson) { | // | ||||||
|         SmsResponse smsResponse = new SmsResponse(); | //        HttpResponse response = HttpRequest.post(URL) | ||||||
|         smsResponse.setSuccess("000000".equals(resJson.getStr("code"))); | //                .header("Content-Type", "application/x-www-form-urlencoded") | ||||||
|         smsResponse.setData(resJson); | //                .header("X-Sdk-Date", sdkDate) | ||||||
|         return smsResponse; | //                .header("host",HOST) | ||||||
|  | //                .header("Authorization", authorization) | ||||||
|  | //                .body(body) | ||||||
|  | //                .execute(); | ||||||
|  | // | ||||||
|  | //        return JSONUtil.parseObj(response.body()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     static String buildRequestBody(String sender, String receiver, String templateId, List<String> templateParas, |     static String buildRequestBody(String sender, String receiver, String templateId, List<String> templateParas, | ||||||
|                                    String statusCallBack, String signature) throws UnsupportedEncodingException { |                                    String statusCallBack, Long sendLogId) throws UnsupportedEncodingException { | ||||||
|         if (null == sender || null == receiver || null == templateId || sender.isEmpty() || receiver.isEmpty() |         if (null == sender || null == receiver || null == templateId || sender.isEmpty() || receiver.isEmpty() | ||||||
|                 || templateId.isEmpty()) { |                 || templateId.isEmpty()) { | ||||||
|             System.out.println("buildRequestBody(): sender, receiver or templateId is null."); |             System.out.println("buildRequestBody(): sender, receiver or templateId is null."); | ||||||
| @@ -150,7 +146,9 @@ public class HuaweiSmsClient extends AbstractSmsClient { | |||||||
|         appendToBody(body, "&templateId=", templateId); |         appendToBody(body, "&templateId=", templateId); | ||||||
|         appendToBody(body, "&templateParas=", JsonUtils.toJsonString(templateParas)); |         appendToBody(body, "&templateParas=", JsonUtils.toJsonString(templateParas)); | ||||||
|         appendToBody(body, "&statusCallback=", statusCallBack); |         appendToBody(body, "&statusCallback=", statusCallBack); | ||||||
|         appendToBody(body, "&signature=", signature); |         appendToBody(body, "&signature=", null); | ||||||
|  |         appendToBody(body, "&extend=", String.valueOf(sendLogId)); | ||||||
|  |  | ||||||
|         return body.toString(); |         return body.toString(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -160,12 +158,35 @@ public class HuaweiSmsClient extends AbstractSmsClient { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     @Override |     @Override | ||||||
|     public List<SmsReceiveRespDTO> parseSmsReceiveStatus(String text) { |     public List<SmsReceiveRespDTO> parseSmsReceiveStatus(String requestBody) { | ||||||
|         List<SmsReceiveStatus> statuses = JsonUtils.parseArray(text, SmsReceiveStatus.class); |  | ||||||
|         return convertList(statuses, status -> new SmsReceiveRespDTO().setSuccess(Objects.equals(status.getStatus(),"DELIVRD")) |         System.out.println("text in parseSmsReceiveStatus===== " + requestBody); | ||||||
|                 .setErrorCode(status.getStatus()).setErrorMsg(status.getStatus()) |  | ||||||
|                 .setMobile(status.getPhoneNumber()).setReceiveTime(status.getUpdateTime()) |         Map<String, String> params = new HashMap<>(); | ||||||
|                 .setSerialNo(status.getSmsMsgId())); |         try { | ||||||
|  |             String[] pairs = requestBody.split("&"); | ||||||
|  |             for (String pair : pairs) { | ||||||
|  |                 int idx = pair.indexOf("="); | ||||||
|  |                 String key = URLDecoder.decode(pair.substring(0, idx), "UTF-8"); | ||||||
|  |                 String value = URLDecoder.decode(pair.substring(idx + 1), "UTF-8"); | ||||||
|  |                 params.put(key, value); | ||||||
|  |             } | ||||||
|  |         } catch (Exception e) { | ||||||
|  |             e.printStackTrace(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         List<SmsReceiveRespDTO> respDTOS = new ArrayList<>(); | ||||||
|  |         respDTOS.add(new SmsReceiveRespDTO() | ||||||
|  |                         .setSuccess("DELIVRD".equals(params.get("status"))) // 是否接收成功 | ||||||
|  |                         .setErrorCode(params.get("status")) // 状态报告编码 | ||||||
|  |                         .setErrorMsg(params.get("statusDesc")) | ||||||
|  |                         .setMobile(params.get("to")) // 手机号 | ||||||
|  |                         .setReceiveTime(LocalDateTime.ofInstant(Instant.parse(params.get("updateTime")), ZoneId.of("UTC"))) // 状态报告时间 | ||||||
|  |                         .setSerialNo(params.get("smsMsgId")) // 发送序列号 | ||||||
|  |                         .setLogId(Long.valueOf(params.get("extend")))//logId | ||||||
|  |         ); | ||||||
|  |  | ||||||
|  |         return respDTOS; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
| @@ -173,56 +194,5 @@ public class HuaweiSmsClient extends AbstractSmsClient { | |||||||
|         //华为短信模板查询和发送短信,是不同的两套key和secret,与阿里、腾讯的区别较大,这里模板查询校验暂不实现。 |         //华为短信模板查询和发送短信,是不同的两套key和secret,与阿里、腾讯的区别较大,这里模板查询校验暂不实现。 | ||||||
|         return new SmsTemplateRespDTO().setId(null).setContent(null) |         return new SmsTemplateRespDTO().setId(null).setContent(null) | ||||||
|                 .setAuditStatus(SmsTemplateAuditStatusEnum.SUCCESS.getStatus()).setAuditReason(null); |                 .setAuditStatus(SmsTemplateAuditStatusEnum.SUCCESS.getStatus()).setAuditReason(null); | ||||||
|  |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Data |  | ||||||
|     public static class SmsResponse { |  | ||||||
|  |  | ||||||
|         /** |  | ||||||
|          * 是否成功 |  | ||||||
|          */ |  | ||||||
|         private boolean success; |  | ||||||
|  |  | ||||||
|         /** |  | ||||||
|          * 厂商原返回体 |  | ||||||
|          */ |  | ||||||
|         private Object data; |  | ||||||
|  |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 短信接收状态 |  | ||||||
|      * |  | ||||||
|      * 参见 <a href="https://support.huaweicloud.com/api-msgsms/sms_05_0003.html">文档</a> |  | ||||||
|      * |  | ||||||
|      * @author scholar |  | ||||||
|      */ |  | ||||||
|     @Data |  | ||||||
|     public static class SmsReceiveStatus { |  | ||||||
|  |  | ||||||
|         /** |  | ||||||
|          * 本条状态报告对应的短信的接收方号码,仅当状态报告中携带了extend参数时才会同时携带该参数 |  | ||||||
|          */ |  | ||||||
|         @JsonProperty("to") |  | ||||||
|         private String phoneNumber; |  | ||||||
|  |  | ||||||
|         /** |  | ||||||
|          * 短信资源的更新时间,通常为短信平台接收短信状态报告的时间 |  | ||||||
|          */ |  | ||||||
|         @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT) |  | ||||||
|         private LocalDateTime updateTime; |  | ||||||
|  |  | ||||||
|         /** |  | ||||||
|          * 短信状态报告枚举值 |  | ||||||
|          */ |  | ||||||
|         private String status; |  | ||||||
|  |  | ||||||
|         /** |  | ||||||
|          * 发送短信成功时返回的短信唯一标识。 |  | ||||||
|          */ |  | ||||||
|         private String smsMsgId; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| } | } | ||||||
| @@ -0,0 +1,114 @@ | |||||||
|  | package cn.iocoder.yudao.module.system.framework.sms.core.client.impl; | ||||||
|  |  | ||||||
|  | import cn.iocoder.yudao.framework.common.core.KeyValue; | ||||||
|  | import cn.iocoder.yudao.framework.common.util.http.HttpUtils; | ||||||
|  | import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; | ||||||
|  | import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsReceiveRespDTO; | ||||||
|  | import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsSendRespDTO; | ||||||
|  | import cn.iocoder.yudao.module.system.framework.sms.core.property.SmsChannelProperties; | ||||||
|  | import com.google.common.collect.Lists; | ||||||
|  |  | ||||||
|  | import org.junit.jupiter.api.Test; | ||||||
|  | import org.mockito.InjectMocks; | ||||||
|  | import org.mockito.MockedStatic; | ||||||
|  |  | ||||||
|  | import java.time.LocalDateTime; | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
|  | import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; | ||||||
|  | import static org.junit.jupiter.api.Assertions.*; | ||||||
|  | import static org.mockito.ArgumentMatchers.*; | ||||||
|  | import static org.mockito.ArgumentMatchers.anyString; | ||||||
|  | import static org.mockito.Mockito.mockStatic; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * {@link HuaweiSmsClient} 的单元测试 | ||||||
|  |  * | ||||||
|  |  * @author scholar | ||||||
|  |  */ | ||||||
|  | public class HuaweiSmsClientTest extends BaseMockitoUnitTest { | ||||||
|  |  | ||||||
|  |     private final SmsChannelProperties properties = new SmsChannelProperties() | ||||||
|  |             .setApiKey(randomString())// 随机一个 apiKey,避免构建报错 | ||||||
|  |             .setApiSecret(randomString()) // 随机一个 apiSecret,避免构建报错 | ||||||
|  |             .setSignature("芋道源码"); | ||||||
|  |  | ||||||
|  |     @InjectMocks | ||||||
|  |     private HuaweiSmsClient smsClient = new HuaweiSmsClient(properties); | ||||||
|  |  | ||||||
|  |     @Test | ||||||
|  |     public void testDoInit() { | ||||||
|  |         // 调用 | ||||||
|  |         smsClient.doInit(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Test | ||||||
|  |     public void testDoSendSms_success() throws Throwable { | ||||||
|  |  | ||||||
|  |         try (MockedStatic<HttpUtils> httpUtilsMockedStatic = mockStatic(HttpUtils.class)) { | ||||||
|  |             // 准备参数 | ||||||
|  |             Long sendLogId = randomLongId(); | ||||||
|  |             String mobile = randomString(); | ||||||
|  |             String apiTemplateId = randomString() + " " + 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( | ||||||
|  |                             "{\"result\":[{\"originTo\":\"+86155****5678\",\"createTime\":\"2018-05-25T16:34:34Z\",\"from\":\"1069********0012\",\"smsMsgId\":\"d6e3cdd0-522b-4692-8304-a07553cdf591_8539659\",\"status\":\"000000\",\"countryId\":\"CN\",\"total\":2}],\"code\":\"000000\",\"description\":\"Success\"}\n" | ||||||
|  |                     ); | ||||||
|  |  | ||||||
|  |             // 调用 | ||||||
|  |             SmsSendRespDTO result = smsClient.sendSms(sendLogId, mobile, | ||||||
|  |                     apiTemplateId, templateParams); | ||||||
|  |             // 断言 | ||||||
|  |             assertTrue(result.getSuccess()); | ||||||
|  |             assertEquals("d6e3cdd0-522b-4692-8304-a07553cdf591_8539659", result.getSerialNo()); | ||||||
|  |             assertEquals("000000", result.getApiCode()); | ||||||
|  |  | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Test | ||||||
|  |     public void testDoSendSms_fail() throws Throwable { | ||||||
|  |         try (MockedStatic<HttpUtils> httpUtilsMockedStatic = mockStatic(HttpUtils.class)) { | ||||||
|  |             // 准备参数 | ||||||
|  |             Long sendLogId = randomLongId(); | ||||||
|  |             String mobile = randomString(); | ||||||
|  |             String apiTemplateId = randomString() + " " + 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( | ||||||
|  |                             "{\"result\":[{\"originTo\":\"+86155****5678\",\"createTime\":\"2018-05-25T16:34:34Z\",\"from\":\"1069********0012\",\"smsMsgId\":\"d6e3cdd0-522b-4692-8304-a07553cdf591_8539659\",\"status\":\"E200015\",\"countryId\":\"CN\",\"total\":2}],\"code\":\"E000000\",\"description\":\"Success\"}\n" | ||||||
|  |                     ); | ||||||
|  |  | ||||||
|  |             // 调用 | ||||||
|  |             SmsSendRespDTO result = smsClient.sendSms(sendLogId, mobile, | ||||||
|  |                     apiTemplateId, templateParams); | ||||||
|  |             // 断言 | ||||||
|  |             assertFalse(result.getSuccess()); | ||||||
|  |             assertEquals("d6e3cdd0-522b-4692-8304-a07553cdf591_8539659", result.getSerialNo()); | ||||||
|  |             assertEquals("E200015", result.getApiCode()); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Test | ||||||
|  |     public void testParseSmsReceiveStatus() { | ||||||
|  |         // 准备参数 | ||||||
|  |         String text = "sequence=1&total=1&statusDesc=%E7%94%A8%E6%88%B7%E5%B7%B2%E6%88%90%E5%8A%9F%E6%94%B6%E5%88%B0%E7%9F%AD%E4%BF%A1&updateTime=2024-08-15T03%3A00%3A34Z&source=2&smsMsgId=70207ed7-1d02-41b0-8537-bb25fd1c2364_143684459&status=DELIVRD&extend=176"; | ||||||
|  |  | ||||||
|  |         // 调用 | ||||||
|  |         List<SmsReceiveRespDTO> statuses = smsClient.parseSmsReceiveStatus(text); | ||||||
|  |         // 断言 | ||||||
|  |         assertEquals(1, statuses.size()); | ||||||
|  |         assertTrue(statuses.getFirst().getSuccess()); | ||||||
|  |         assertEquals("DELIVRD", statuses.getFirst().getErrorCode()); | ||||||
|  |         assertEquals(LocalDateTime.of(2024, 8, 15, 3, 0, 34), statuses.getFirst().getReceiveTime()); | ||||||
|  |         assertEquals("70207ed7-1d02-41b0-8537-bb25fd1c2364_143684459", statuses.getFirst().getSerialNo()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user
	 scholar
					scholar