mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2024-11-22 15:21:53 +08:00
1,腾讯云短信实现优化,去除不必要VO;
2,增加腾讯云短信功能单测,和集成单测;
This commit is contained in:
parent
2f38261de8
commit
8242735d84
@ -2,36 +2,29 @@ package cn.iocoder.yudao.module.system.framework.sms.core.client.impl;
|
|||||||
|
|
||||||
import cn.hutool.core.lang.Assert;
|
import cn.hutool.core.lang.Assert;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.hutool.http.HttpRequest;
|
|
||||||
import cn.hutool.http.HttpResponse;
|
|
||||||
import cn.hutool.json.JSONArray;
|
import cn.hutool.json.JSONArray;
|
||||||
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.ArrayUtils;
|
import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils;
|
||||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
import cn.iocoder.yudao.framework.common.util.http.HttpUtils;
|
||||||
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;
|
||||||
import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsTemplateRespDTO;
|
import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsTemplateRespDTO;
|
||||||
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 com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import lombok.Data;
|
import jakarta.xml.bind.DatatypeConverter;
|
||||||
|
|
||||||
import javax.crypto.Mac;
|
import javax.crypto.Mac;
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
import javax.xml.bind.DatatypeConverter;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
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.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;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 腾讯云短信功能实现
|
* 腾讯云短信功能实现
|
||||||
@ -103,14 +96,15 @@ public class TencentSmsClient extends AbstractSmsClient {
|
|||||||
body.put("TemplateId",apiTemplateId);
|
body.put("TemplateId",apiTemplateId);
|
||||||
body.put("TemplateParamSet",ArrayUtils.toArray(templateParams, e -> String.valueOf(e.getValue())));
|
body.put("TemplateParamSet",ArrayUtils.toArray(templateParams, e -> String.valueOf(e.getValue())));
|
||||||
|
|
||||||
JSONObject JsonResponse = sendSmsRequest(body,"SendSms","2021-01-11","ap-guangzhou");
|
JSONObject JsonResponse = request(body,"SendSms","2021-01-11","ap-guangzhou");
|
||||||
SmsResponse smsResponse = getSmsSendResponse(JsonResponse);
|
|
||||||
|
|
||||||
return new SmsSendRespDTO().setSuccess(smsResponse.success).setApiMsg(smsResponse.data.toString());
|
|
||||||
|
|
||||||
|
return new SmsSendRespDTO().setSuccess(API_CODE_SUCCESS.equals(JsonResponse.getJSONObject("Response").getJSONArray("SendStatusSet").getJSONObject(0).getStr("Code")))
|
||||||
|
.setApiRequestId(JsonResponse.getJSONObject("Response").getStr("RequestId"))
|
||||||
|
.setSerialNo(JsonResponse.getJSONObject("Response").getJSONArray("SendStatusSet").getJSONObject(0).getStr("SerialNo"))
|
||||||
|
.setApiMsg(JsonResponse.getJSONObject("Response").getJSONArray("SendStatusSet").getJSONObject(0).getStr("Message"));
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONObject sendSmsRequest(TreeMap<String, Object> body,String action,String version,String region) throws Exception {
|
JSONObject request(TreeMap<String, Object> body,String action,String version,String region) throws Exception {
|
||||||
|
|
||||||
String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
|
String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
|
||||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
|
||||||
@ -155,12 +149,9 @@ public class TencentSmsClient extends AbstractSmsClient {
|
|||||||
headers.put("X-TC-Version", version);
|
headers.put("X-TC-Version", version);
|
||||||
headers.put("X-TC-Region", region);
|
headers.put("X-TC-Region", region);
|
||||||
|
|
||||||
HttpResponse response = HttpRequest.post("https://"+host)
|
String responseBody = HttpUtils.post("https://"+host, headers, JSONUtil.toJsonStr(body));
|
||||||
.addHeaders(headers)
|
|
||||||
.body(JSONUtil.toJsonStr(body))
|
|
||||||
.execute();
|
|
||||||
|
|
||||||
return JSONUtil.parseObj(response.body());
|
return JSONUtil.parseObj(responseBody);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] hmac256(byte[] key, String msg) throws Exception {
|
public static byte[] hmac256(byte[] key, String msg) throws Exception {
|
||||||
@ -170,22 +161,20 @@ public class TencentSmsClient extends AbstractSmsClient {
|
|||||||
return mac.doFinal(msg.getBytes(StandardCharsets.UTF_8));
|
return mac.doFinal(msg.getBytes(StandardCharsets.UTF_8));
|
||||||
}
|
}
|
||||||
|
|
||||||
private SmsResponse getSmsSendResponse(JSONObject resJson) {
|
|
||||||
SmsResponse smsResponse = new SmsResponse();
|
|
||||||
JSONArray statusJson =resJson.getJSONObject("Response").getJSONArray("SendStatusSet");
|
|
||||||
smsResponse.setSuccess("Ok".equals(statusJson.getJSONObject(0).getStr("Code")));
|
|
||||||
smsResponse.setData(resJson);
|
|
||||||
return smsResponse;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<SmsReceiveRespDTO> parseSmsReceiveStatus(String text) {
|
public List<SmsReceiveRespDTO> parseSmsReceiveStatus(String text) {
|
||||||
List<SmsReceiveStatus> callback = JsonUtils.parseArray(text, SmsReceiveStatus.class);
|
|
||||||
return convertList(callback, status -> new SmsReceiveRespDTO()
|
JSONArray statuses = JSONUtil.parseArray(text);
|
||||||
.setSuccess(SmsReceiveStatus.SUCCESS_CODE.equalsIgnoreCase(status.getStatus()))
|
// 字段参考
|
||||||
.setErrorCode(status.getErrCode()).setErrorMsg(status.getDescription())
|
return convertList(statuses, status -> {
|
||||||
.setMobile(status.getMobile()).setReceiveTime(status.getReceiveTime())
|
JSONObject statusObj = (JSONObject) status;
|
||||||
.setSerialNo(status.getSerialNo()).setLogId(status.getSessionContext().getLogId()));
|
return new SmsReceiveRespDTO()
|
||||||
|
.setSuccess("SUCCESS".equals(statusObj.getStr("report_status"))) // 是否接收成功
|
||||||
|
.setErrorCode(statusObj.getStr("errmsg")) // 状态报告编码
|
||||||
|
.setMobile(statusObj.getStr("mobile")) // 手机号
|
||||||
|
.setReceiveTime(statusObj.getLocalDateTime("user_receive_time", null)) // 状态报告时间
|
||||||
|
.setSerialNo(statusObj.getStr("sid")); // 发送序列号
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -193,48 +182,22 @@ public class TencentSmsClient extends AbstractSmsClient {
|
|||||||
|
|
||||||
// 构建请求
|
// 构建请求
|
||||||
TreeMap<String, Object> body = new TreeMap<>();
|
TreeMap<String, Object> body = new TreeMap<>();
|
||||||
body.put("International",0);
|
body.put("International",INTERNATIONAL_CHINA);
|
||||||
Integer[] templateIds = {Integer.valueOf(apiTemplateId)};
|
Integer[] templateIds = {Integer.valueOf(apiTemplateId)};
|
||||||
body.put("TemplateIdSet",templateIds);
|
body.put("TemplateIdSet",templateIds);
|
||||||
|
|
||||||
JSONObject JsonResponse = sendSmsRequest(body,"DescribeSmsTemplateList","2021-01-11","ap-guangzhou");
|
JSONObject JsonResponse = request(body,"DescribeSmsTemplateList","2021-01-11","ap-guangzhou");
|
||||||
QuerySmsTemplateResponse smsTemplateResponse = getSmsTemplateResponse(JsonResponse);
|
System.out.println("JsonResponse======"+JsonResponse);
|
||||||
String templateId = Integer.toString(smsTemplateResponse.getDescribeTemplateStatusSet().get(0).getTemplateId());
|
|
||||||
String content = smsTemplateResponse.getDescribeTemplateStatusSet().get(0).getTemplateContent();
|
|
||||||
Integer templateStatus = smsTemplateResponse.getDescribeTemplateStatusSet().get(0).getStatusCode();
|
|
||||||
String auditReason = smsTemplateResponse.getDescribeTemplateStatusSet().get(0).getReviewReply();
|
|
||||||
|
|
||||||
return new SmsTemplateRespDTO().setId(templateId).setContent(content)
|
JSONObject TemplateStatusSet = JsonResponse.getJSONObject("Response").getJSONArray("DescribeTemplateStatusSet").getJSONObject(0);
|
||||||
|
String content = TemplateStatusSet.get("TemplateContent").toString();
|
||||||
|
int templateStatus = Integer.parseInt(TemplateStatusSet.get("StatusCode").toString());
|
||||||
|
String auditReason = TemplateStatusSet.get("ReviewReply").toString();
|
||||||
|
|
||||||
|
return new SmsTemplateRespDTO().setId(apiTemplateId).setContent(content)
|
||||||
.setAuditStatus(convertSmsTemplateAuditStatus(templateStatus)).setAuditReason(auditReason);
|
.setAuditStatus(convertSmsTemplateAuditStatus(templateStatus)).setAuditReason(auditReason);
|
||||||
}
|
}
|
||||||
|
|
||||||
private QuerySmsTemplateResponse getSmsTemplateResponse(JSONObject resJson) {
|
|
||||||
|
|
||||||
QuerySmsTemplateResponse smsTemplateResponse = new QuerySmsTemplateResponse();
|
|
||||||
|
|
||||||
smsTemplateResponse.setRequestId(resJson.getJSONObject("Response").getStr("RequestId"));
|
|
||||||
|
|
||||||
smsTemplateResponse.setDescribeTemplateStatusSet(new ArrayList<>());
|
|
||||||
|
|
||||||
QuerySmsTemplateResponse.TemplateInfo templateInfo = new QuerySmsTemplateResponse.TemplateInfo();
|
|
||||||
|
|
||||||
Object statusObject = resJson.getJSONObject("Response").getJSONArray("DescribeTemplateStatusSet").getFirst();
|
|
||||||
|
|
||||||
JSONObject statusJSON = new JSONObject(statusObject);
|
|
||||||
|
|
||||||
templateInfo.setTemplateContent(statusJSON.get("TemplateContent").toString());
|
|
||||||
|
|
||||||
templateInfo.setStatusCode(Integer.parseInt(statusJSON.get("StatusCode").toString()));
|
|
||||||
|
|
||||||
templateInfo.setReviewReply(statusJSON.get("ReviewReply").toString());
|
|
||||||
|
|
||||||
templateInfo.setTemplateId(Integer.parseInt(statusJSON.get("TemplateId").toString()));
|
|
||||||
|
|
||||||
smsTemplateResponse.getDescribeTemplateStatusSet().add(templateInfo);
|
|
||||||
|
|
||||||
return smsTemplateResponse;
|
|
||||||
}
|
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
Integer convertSmsTemplateAuditStatus(int templateStatus) {
|
Integer convertSmsTemplateAuditStatus(int templateStatus) {
|
||||||
switch (templateStatus) {
|
switch (templateStatus) {
|
||||||
@ -244,113 +207,4 @@ public class TencentSmsClient extends AbstractSmsClient {
|
|||||||
default: throw new IllegalArgumentException(String.format("未知审核状态(%d)", templateStatus));
|
default: throw new IllegalArgumentException(String.format("未知审核状态(%d)", templateStatus));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Data
|
|
||||||
public static class SmsResponse {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否成功
|
|
||||||
*/
|
|
||||||
private boolean success;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 厂商原返回体
|
|
||||||
*/
|
|
||||||
private Object data;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>类名: QuerySmsTemplateResponse
|
|
||||||
* <p>说明: sms模板查询返回信息
|
|
||||||
*
|
|
||||||
* @author :scholar
|
|
||||||
* 2024/07/17 0:25
|
|
||||||
**/
|
|
||||||
@Data
|
|
||||||
public static class QuerySmsTemplateResponse {
|
|
||||||
private List<TemplateInfo> DescribeTemplateStatusSet;
|
|
||||||
private String RequestId;
|
|
||||||
@Data
|
|
||||||
static class TemplateInfo {
|
|
||||||
private String TemplateName;
|
|
||||||
private Integer TemplateId;
|
|
||||||
private Integer International;
|
|
||||||
private String ReviewReply;
|
|
||||||
private long CreateTime;
|
|
||||||
private String TemplateContent;
|
|
||||||
private Integer StatusCode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Data
|
|
||||||
private static class SmsReceiveStatus {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 短信接受成功 code
|
|
||||||
*/
|
|
||||||
public static final String SUCCESS_CODE = "SUCCESS";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用户实际接收到短信的时间
|
|
||||||
*/
|
|
||||||
@JsonProperty("user_receive_time")
|
|
||||||
@JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)
|
|
||||||
private LocalDateTime receiveTime;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 国家(或地区)码
|
|
||||||
*/
|
|
||||||
@JsonProperty("nationcode")
|
|
||||||
private String nationCode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 手机号码
|
|
||||||
*/
|
|
||||||
private String mobile;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 实际是否收到短信接收状态,SUCCESS(成功)、FAIL(失败)
|
|
||||||
*/
|
|
||||||
@JsonProperty("report_status")
|
|
||||||
private String status;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用户接收短信状态码错误信息
|
|
||||||
*/
|
|
||||||
@JsonProperty("errmsg")
|
|
||||||
private String errCode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用户接收短信状态描述
|
|
||||||
*/
|
|
||||||
@JsonProperty("description")
|
|
||||||
private String description;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 本次发送标识 ID(与发送接口返回的SerialNo对应)
|
|
||||||
*/
|
|
||||||
@JsonProperty("sid")
|
|
||||||
private String serialNo;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用户的 session 内容(与发送接口的请求参数 SessionContext 一致)
|
|
||||||
*/
|
|
||||||
@JsonProperty("ext")
|
|
||||||
private SessionContext sessionContext;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
@Data
|
|
||||||
static class SessionContext {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 发送短信记录id
|
|
||||||
*/
|
|
||||||
private Long logId;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,139 @@
|
|||||||
|
package cn.iocoder.yudao.module.system.framework.sms.core.client.impl;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.core.KeyValue;
|
||||||
|
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.SmsTemplateRespDTO;
|
||||||
|
import cn.iocoder.yudao.module.system.framework.sms.core.property.SmsChannelProperties;
|
||||||
|
import org.junit.jupiter.api.Disabled;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 各种 {@link SmsClientTests 集成测试
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
public class SmsClientTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Disabled
|
||||||
|
public void testHuaweiSmsClient_sendSms() throws Throwable {
|
||||||
|
SmsChannelProperties properties = new SmsChannelProperties()
|
||||||
|
.setApiKey("123")
|
||||||
|
.setApiSecret("456")
|
||||||
|
.setSignature("runpu");
|
||||||
|
HuaweiSmsClient client = new HuaweiSmsClient(properties);
|
||||||
|
// 准备参数
|
||||||
|
Long sendLogId = System.currentTimeMillis();
|
||||||
|
String mobile = "15601691323";
|
||||||
|
String apiTemplateId = "xx test01";
|
||||||
|
List<KeyValue<String, Object>> templateParams = List.of(new KeyValue<>("code", "1024"));
|
||||||
|
// 调用
|
||||||
|
SmsSendRespDTO smsSendRespDTO = client.sendSms(sendLogId, mobile, apiTemplateId, templateParams);
|
||||||
|
// 打印结果
|
||||||
|
System.out.println(smsSendRespDTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== 阿里云 ==========
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Disabled
|
||||||
|
public void testAliyunSmsClient_getSmsTemplate() throws Throwable {
|
||||||
|
SmsChannelProperties properties = new SmsChannelProperties()
|
||||||
|
.setApiKey("LTAI5tAicJAxaSFiZuGGeXHR")
|
||||||
|
.setApiSecret("Fdr9vadxnDvS6GJU0W1tijQ0VmLhYz");
|
||||||
|
AliyunSmsClient client = new AliyunSmsClient(properties);
|
||||||
|
// 准备参数
|
||||||
|
String apiTemplateId = "SMS_207945135";
|
||||||
|
// 调用
|
||||||
|
SmsTemplateRespDTO template = client.getSmsTemplate(apiTemplateId);
|
||||||
|
// 打印结果
|
||||||
|
System.out.println(template);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Disabled
|
||||||
|
public void testAliyunSmsClient_sendSms() throws Throwable {
|
||||||
|
SmsChannelProperties properties = new SmsChannelProperties()
|
||||||
|
.setApiKey("LTAI5tAicJAxaSFiZuGGeXHR")
|
||||||
|
.setApiSecret("Fdr9vadxnDvS6GJU0W1tijQ0VmLhYz")
|
||||||
|
.setSignature("runpu");
|
||||||
|
AliyunSmsClient client = new AliyunSmsClient(properties);
|
||||||
|
// 准备参数
|
||||||
|
Long sendLogId = System.currentTimeMillis();
|
||||||
|
String mobile = "15601691323";
|
||||||
|
String apiTemplateId = "SMS_207945135";
|
||||||
|
// 调用
|
||||||
|
SmsSendRespDTO sendRespDTO = client.sendSms(sendLogId, mobile, apiTemplateId, List.of(new KeyValue<>("code", "1024")));
|
||||||
|
// 打印结果
|
||||||
|
System.out.println(sendRespDTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Disabled
|
||||||
|
public void testAliyunSmsClient_parseSmsReceiveStatus() {
|
||||||
|
SmsChannelProperties properties = new SmsChannelProperties()
|
||||||
|
.setApiKey("LTAI5tAicJAxaSFiZuGGeXHR")
|
||||||
|
.setApiSecret("Fdr9vadxnDvS6GJU0W1tijQ0VmLhYz");
|
||||||
|
AliyunSmsClient client = new AliyunSmsClient(properties);
|
||||||
|
// 准备参数
|
||||||
|
String text = "[\n" +
|
||||||
|
" {\n" +
|
||||||
|
" \"phone_number\" : \"13900000001\",\n" +
|
||||||
|
" \"send_time\" : \"2017-01-01 11:12:13\",\n" +
|
||||||
|
" \"report_time\" : \"2017-02-02 22:23:24\",\n" +
|
||||||
|
" \"success\" : true,\n" +
|
||||||
|
" \"err_code\" : \"DELIVERED\",\n" +
|
||||||
|
" \"err_msg\" : \"用户接收成功\",\n" +
|
||||||
|
" \"sms_size\" : \"1\",\n" +
|
||||||
|
" \"biz_id\" : \"12345\",\n" +
|
||||||
|
" \"out_id\" : \"67890\"\n" +
|
||||||
|
" }\n" +
|
||||||
|
"]";
|
||||||
|
// mock 方法
|
||||||
|
|
||||||
|
// 调用
|
||||||
|
List<SmsReceiveRespDTO> statuses = client.parseSmsReceiveStatus(text);
|
||||||
|
// 打印结果
|
||||||
|
System.out.println(statuses);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== 腾讯云 ==========
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Disabled
|
||||||
|
public void testTencentSmsClient_sendSms() throws Throwable {
|
||||||
|
SmsChannelProperties properties = new SmsChannelProperties()
|
||||||
|
.setApiKey("LTAI5tAicJAxaSFiZuGGeXHR 1428926523")
|
||||||
|
.setApiSecret("Fdr9vadxnDvS6GJU0W1tijQ0VmLhYz")
|
||||||
|
.setSignature("芋道源码");
|
||||||
|
TencentSmsClient client = new TencentSmsClient(properties);
|
||||||
|
// 准备参数
|
||||||
|
Long sendLogId = System.currentTimeMillis();
|
||||||
|
String mobile = "15601691323";
|
||||||
|
String apiTemplateId = "2136358";
|
||||||
|
// 调用
|
||||||
|
SmsSendRespDTO sendRespDTO = client.sendSms(sendLogId, mobile, apiTemplateId, List.of(new KeyValue<>("code", "1024")));
|
||||||
|
// 打印结果
|
||||||
|
System.out.println(sendRespDTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Disabled
|
||||||
|
public void testTencentSmsClient_getSmsTemplate() throws Throwable {
|
||||||
|
SmsChannelProperties properties = new SmsChannelProperties()
|
||||||
|
.setApiKey("LTAI5tAicJAxaSFiZuGGeXHR 1428926523")
|
||||||
|
.setApiSecret("Fdr9vadxnDvS6GJU0W1tijQ0VmLhYz")
|
||||||
|
.setSignature("芋道源码");
|
||||||
|
TencentSmsClient client = new TencentSmsClient(properties);
|
||||||
|
// 准备参数
|
||||||
|
String apiTemplateId = "2136358";
|
||||||
|
// 调用
|
||||||
|
SmsTemplateRespDTO template = client.getSmsTemplate(apiTemplateId);
|
||||||
|
// 打印结果
|
||||||
|
System.out.println(template);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,10 +1,7 @@
|
|||||||
package cn.iocoder.yudao.module.system.framework.sms.core.client.impl;
|
package cn.iocoder.yudao.module.system.framework.sms.core.client.impl;
|
||||||
|
|
||||||
import cn.hutool.core.util.ReflectUtil;
|
|
||||||
import cn.iocoder.yudao.framework.common.core.KeyValue;
|
import cn.iocoder.yudao.framework.common.core.KeyValue;
|
||||||
import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils;
|
import cn.iocoder.yudao.framework.common.util.http.HttpUtils;
|
||||||
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
|
|
||||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
|
||||||
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
|
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.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;
|
||||||
@ -12,24 +9,19 @@ 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.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.tencentcloudapi.sms.v20210111.SmsClient;
|
|
||||||
import com.tencentcloudapi.sms.v20210111.models.DescribeSmsTemplateListResponse;
|
|
||||||
import com.tencentcloudapi.sms.v20210111.models.DescribeTemplateListStatus;
|
|
||||||
import com.tencentcloudapi.sms.v20210111.models.SendSmsResponse;
|
|
||||||
import com.tencentcloudapi.sms.v20210111.models.SendStatus;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.mockito.InjectMocks;
|
import org.mockito.InjectMocks;
|
||||||
import org.mockito.Mock;
|
import org.mockito.MockedStatic;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
|
|
||||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
|
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
import static org.mockito.ArgumentMatchers.argThat;
|
import static org.mockito.ArgumentMatchers.*;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
|
import static org.mockito.Mockito.mockStatic;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link TencentSmsClient} 的单元测试
|
* {@link TencentSmsClient} 的单元测试
|
||||||
@ -46,9 +38,6 @@ public class TencentSmsClientTest extends BaseMockitoUnitTest {
|
|||||||
@InjectMocks
|
@InjectMocks
|
||||||
private TencentSmsClient smsClient = new TencentSmsClient(properties);
|
private TencentSmsClient smsClient = new TencentSmsClient(properties);
|
||||||
|
|
||||||
@Mock
|
|
||||||
private SmsClient client;
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDoInit() {
|
public void testDoInit() {
|
||||||
// 准备参数
|
// 准备参数
|
||||||
@ -56,103 +45,92 @@ public class TencentSmsClientTest extends BaseMockitoUnitTest {
|
|||||||
|
|
||||||
// 调用
|
// 调用
|
||||||
smsClient.doInit();
|
smsClient.doInit();
|
||||||
// 断言
|
|
||||||
assertNotSame(client, ReflectUtil.getFieldValue(smsClient, "client"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testRefresh() {
|
|
||||||
// 准备参数
|
|
||||||
SmsChannelProperties p = new SmsChannelProperties()
|
|
||||||
.setApiKey(randomString() + " " + randomString()) // 随机一个 apiKey,避免构建报错
|
|
||||||
.setApiSecret(randomString()) // 随机一个 apiSecret,避免构建报错
|
|
||||||
.setSignature("芋道源码");
|
|
||||||
// 调用
|
|
||||||
smsClient.refresh(p);
|
|
||||||
// 断言
|
|
||||||
assertNotSame(client, ReflectUtil.getFieldValue(smsClient, "client"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDoSendSms_success() throws Throwable {
|
public void testDoSendSms_success() throws Throwable {
|
||||||
|
|
||||||
|
try (MockedStatic<HttpUtils> httpUtilsMockedStatic = mockStatic(HttpUtils.class)) {
|
||||||
// 准备参数
|
// 准备参数
|
||||||
Long sendLogId = randomLongId();
|
Long sendLogId = randomLongId();
|
||||||
String mobile = randomString();
|
String mobile = randomString();
|
||||||
String apiTemplateId = randomString();
|
String apiTemplateId = randomString();
|
||||||
List<KeyValue<String, Object>> templateParams = Lists.newArrayList(
|
List<KeyValue<String, Object>> templateParams = Lists.newArrayList(
|
||||||
new KeyValue<>("1", 1234), new KeyValue<>("2", "login"));
|
new KeyValue<>("1", 1234), new KeyValue<>("2", "login"));
|
||||||
String requestId = randomString();
|
|
||||||
String serialNo = randomString();
|
|
||||||
// mock 方法
|
// mock 方法
|
||||||
SendSmsResponse response = randomPojo(SendSmsResponse.class, o -> {
|
httpUtilsMockedStatic.when(() -> HttpUtils.post(anyString(), anyMap(), anyString()))
|
||||||
o.setRequestId(requestId);
|
.thenReturn(
|
||||||
SendStatus[] sendStatuses = new SendStatus[1];
|
"{\n" +
|
||||||
o.setSendStatusSet(sendStatuses);
|
" \"Response\": {\n" +
|
||||||
SendStatus sendStatus = new SendStatus();
|
" \"SendStatusSet\": [\n" +
|
||||||
sendStatuses[0] = sendStatus;
|
" {\n" +
|
||||||
sendStatus.setCode(TencentSmsClient.API_CODE_SUCCESS);
|
" \"SerialNo\": \"5000:1045710669157053657849499619\",\n" +
|
||||||
sendStatus.setMessage("send success");
|
" \"PhoneNumber\": \"+8618511122233\",\n" +
|
||||||
sendStatus.setSerialNo(serialNo);
|
" \"Fee\": 1,\n" +
|
||||||
});
|
" \"SessionContext\": \"test\",\n" +
|
||||||
when(client.SendSms(argThat(request -> {
|
" \"Code\": \"Ok\",\n" +
|
||||||
assertEquals(mobile, request.getPhoneNumberSet()[0]);
|
" \"Message\": \"send success\",\n" +
|
||||||
assertEquals(properties.getSignature(), request.getSignName());
|
" \"IsoCode\": \"CN\"\n" +
|
||||||
assertEquals(apiTemplateId, request.getTemplateId());
|
" },\n" +
|
||||||
assertEquals(toJsonString(ArrayUtils.toArray(new ArrayList<>(MapUtils.convertMap(templateParams).values()), String::valueOf)),
|
" ],\n" +
|
||||||
toJsonString(request.getTemplateParamSet()));
|
" \"RequestId\": \"a0aabda6-cf91-4f3e-a81f-9198114a2279\"\n" +
|
||||||
assertEquals(sendLogId, ReflectUtil.getFieldValue(JsonUtils.parseObject(request.getSessionContext(), TencentSmsClient.SessionContext.class), "logId"));
|
" }\n" +
|
||||||
return true;
|
"}"
|
||||||
}))).thenReturn(response);
|
);
|
||||||
|
|
||||||
// 调用
|
// 调用
|
||||||
SmsSendRespDTO result = smsClient.sendSms(sendLogId, mobile, apiTemplateId, templateParams);
|
SmsSendRespDTO result = smsClient.sendSms(sendLogId, mobile,
|
||||||
|
apiTemplateId, templateParams);
|
||||||
// 断言
|
// 断言
|
||||||
assertTrue(result.getSuccess());
|
assertTrue(result.getSuccess());
|
||||||
assertEquals(response.getRequestId(), result.getApiRequestId());
|
assertEquals("5000:1045710669157053657849499619", result.getSerialNo());
|
||||||
assertEquals(response.getSendStatusSet()[0].getCode(), result.getApiCode());
|
assertEquals("a0aabda6-cf91-4f3e-a81f-9198114a2279", result.getApiRequestId());
|
||||||
assertEquals(response.getSendStatusSet()[0].getMessage(), result.getApiMsg());
|
assertEquals("send success", result.getApiMsg());
|
||||||
assertEquals(response.getSendStatusSet()[0].getSerialNo(), result.getSerialNo());
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDoSendSms_fail() throws Throwable {
|
public void testDoSendSms_fail() throws Throwable {
|
||||||
|
try (MockedStatic<HttpUtils> httpUtilsMockedStatic = mockStatic(HttpUtils.class)) {
|
||||||
// 准备参数
|
// 准备参数
|
||||||
Long sendLogId = randomLongId();
|
Long sendLogId = randomLongId();
|
||||||
String mobile = randomString();
|
String mobile = randomString();
|
||||||
String apiTemplateId = randomString();
|
String apiTemplateId = randomString();
|
||||||
List<KeyValue<String, Object>> templateParams = Lists.newArrayList(
|
List<KeyValue<String, Object>> templateParams = Lists.newArrayList(
|
||||||
new KeyValue<>("1", 1234), new KeyValue<>("2", "login"));
|
new KeyValue<>("1", 1234), new KeyValue<>("2", "login"));
|
||||||
String requestId = randomString();
|
|
||||||
String serialNo = randomString();
|
|
||||||
// mock 方法
|
// mock 方法
|
||||||
SendSmsResponse response = randomPojo(SendSmsResponse.class, o -> {
|
httpUtilsMockedStatic.when(() -> HttpUtils.post(anyString(), anyMap(), anyString()))
|
||||||
o.setRequestId(requestId);
|
.thenReturn(
|
||||||
SendStatus[] sendStatuses = new SendStatus[1];
|
"{\n" +
|
||||||
o.setSendStatusSet(sendStatuses);
|
" \"Response\": {\n" +
|
||||||
SendStatus sendStatus = new SendStatus();
|
" \"SendStatusSet\": [\n" +
|
||||||
sendStatuses[0] = sendStatus;
|
" {\n" +
|
||||||
sendStatus.setCode("ERROR");
|
" \"SerialNo\": \"5000:1045710669157053657849499619\",\n" +
|
||||||
sendStatus.setMessage("send success");
|
" \"PhoneNumber\": \"+8618511122233\",\n" +
|
||||||
sendStatus.setSerialNo(serialNo);
|
" \"Fee\": 1,\n" +
|
||||||
});
|
" \"SessionContext\": \"test\",\n" +
|
||||||
when(client.SendSms(argThat(request -> {
|
" \"Code\": \"ERROR\",\n" +
|
||||||
assertEquals(mobile, request.getPhoneNumberSet()[0]);
|
" \"Message\": \"send success\",\n" +
|
||||||
assertEquals(properties.getSignature(), request.getSignName());
|
" \"IsoCode\": \"CN\"\n" +
|
||||||
assertEquals(apiTemplateId, request.getTemplateId());
|
" },\n" +
|
||||||
assertEquals(toJsonString(ArrayUtils.toArray(new ArrayList<>(MapUtils.convertMap(templateParams).values()), String::valueOf)),
|
" ],\n" +
|
||||||
toJsonString(request.getTemplateParamSet()));
|
" \"RequestId\": \"a0aabda6-cf91-4f3e-a81f-9198114a2279\"\n" +
|
||||||
assertEquals(sendLogId, ReflectUtil.getFieldValue(JsonUtils.parseObject(request.getSessionContext(), TencentSmsClient.SessionContext.class), "logId"));
|
" }\n" +
|
||||||
return true;
|
"}"
|
||||||
}))).thenReturn(response);
|
);
|
||||||
|
|
||||||
// 调用
|
// 调用
|
||||||
SmsSendRespDTO result = smsClient.sendSms(sendLogId, mobile, apiTemplateId, templateParams);
|
SmsSendRespDTO result = smsClient.sendSms(sendLogId, mobile,
|
||||||
|
apiTemplateId, templateParams);
|
||||||
// 断言
|
// 断言
|
||||||
assertFalse(result.getSuccess());
|
assertFalse(result.getSuccess());
|
||||||
assertEquals(response.getRequestId(), result.getApiRequestId());
|
assertEquals("5000:1045710669157053657849499619", result.getSerialNo());
|
||||||
assertEquals(response.getSendStatusSet()[0].getCode(), result.getApiCode());
|
assertEquals("a0aabda6-cf91-4f3e-a81f-9198114a2279", result.getApiRequestId());
|
||||||
assertEquals(response.getSendStatusSet()[0].getMessage(), result.getApiMsg());
|
assertEquals("send success", result.getApiMsg());
|
||||||
assertEquals(response.getSendStatusSet()[0].getSerialNo(), result.getSerialNo());
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -170,7 +148,6 @@ public class TencentSmsClientTest extends BaseMockitoUnitTest {
|
|||||||
" \"ext\": {\"logId\":\"67890\"}\n" +
|
" \"ext\": {\"logId\":\"67890\"}\n" +
|
||||||
" }\n" +
|
" }\n" +
|
||||||
"]";
|
"]";
|
||||||
// mock 方法
|
|
||||||
|
|
||||||
// 调用
|
// 调用
|
||||||
List<SmsReceiveRespDTO> statuses = smsClient.parseSmsReceiveStatus(text);
|
List<SmsReceiveRespDTO> statuses = smsClient.parseSmsReceiveStatus(text);
|
||||||
@ -178,41 +155,45 @@ public class TencentSmsClientTest extends BaseMockitoUnitTest {
|
|||||||
assertEquals(1, statuses.size());
|
assertEquals(1, statuses.size());
|
||||||
assertTrue(statuses.get(0).getSuccess());
|
assertTrue(statuses.get(0).getSuccess());
|
||||||
assertEquals("DELIVRD", statuses.get(0).getErrorCode());
|
assertEquals("DELIVRD", statuses.get(0).getErrorCode());
|
||||||
assertEquals("用户短信送达成功", statuses.get(0).getErrorMsg());
|
|
||||||
assertEquals("13900000001", statuses.get(0).getMobile());
|
assertEquals("13900000001", statuses.get(0).getMobile());
|
||||||
assertEquals(LocalDateTime.of(2015, 10, 17, 8, 3, 4), statuses.get(0).getReceiveTime());
|
assertEquals(LocalDateTime.of(2015, 10, 17, 8, 3, 4), statuses.get(0).getReceiveTime());
|
||||||
assertEquals("12345", statuses.get(0).getSerialNo());
|
assertEquals("12345", statuses.get(0).getSerialNo());
|
||||||
assertEquals(67890L, statuses.get(0).getLogId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetSmsTemplate() throws Throwable {
|
public void testGetSmsTemplate() throws Throwable {
|
||||||
|
|
||||||
|
try (MockedStatic<HttpUtils> httpUtilsMockedStatic = mockStatic(HttpUtils.class)) {
|
||||||
|
|
||||||
// 准备参数
|
// 准备参数
|
||||||
Long apiTemplateId = randomLongId();
|
String apiTemplateId = "1122";
|
||||||
String requestId = randomString();
|
|
||||||
|
|
||||||
// mock 方法
|
// mock 方法
|
||||||
DescribeSmsTemplateListResponse response = randomPojo(DescribeSmsTemplateListResponse.class, o -> {
|
httpUtilsMockedStatic.when(() -> HttpUtils.post(anyString(), anyMap(), anyString()))
|
||||||
DescribeTemplateListStatus[] describeTemplateListStatuses = new DescribeTemplateListStatus[1];
|
.thenReturn("{ \"Response\": {\n" +
|
||||||
DescribeTemplateListStatus templateStatus = new DescribeTemplateListStatus();
|
" \"DescribeTemplateStatusSet\": [\n" +
|
||||||
templateStatus.setTemplateId(apiTemplateId);
|
" {\n" +
|
||||||
templateStatus.setStatusCode(0L);// 设置模板通过
|
" \"TemplateName\": \"验证码\",\n" +
|
||||||
describeTemplateListStatuses[0] = templateStatus;
|
" \"TemplateId\": 1122,\n" +
|
||||||
o.setDescribeTemplateStatusSet(describeTemplateListStatuses);
|
" \"International\": 0,\n" +
|
||||||
o.setRequestId(requestId);
|
" \"ReviewReply\": \"审批备注\",\n" +
|
||||||
});
|
" \"CreateTime\": 1617379200,\n" +
|
||||||
when(client.DescribeSmsTemplateList(argThat(request -> {
|
" \"TemplateContent\": \"您的验证码是{1}\",\n" +
|
||||||
assertEquals(apiTemplateId, request.getTemplateIdSet()[0]);
|
" \"StatusCode\": 0\n" +
|
||||||
return true;
|
" },\n" +
|
||||||
}))).thenReturn(response);
|
" \n" +
|
||||||
|
" ],\n" +
|
||||||
|
" \"RequestId\": \"f36e4f00-605e-49b1-ad0d-bfaba81c7325\"\n" +
|
||||||
|
" }}");
|
||||||
|
|
||||||
// 调用
|
// 调用
|
||||||
SmsTemplateRespDTO result = smsClient.getSmsTemplate(apiTemplateId.toString());
|
SmsTemplateRespDTO result = smsClient.getSmsTemplate(apiTemplateId);
|
||||||
// 断言
|
// 断言
|
||||||
assertEquals(response.getDescribeTemplateStatusSet()[0].getTemplateId().toString(), result.getId());
|
assertEquals("1122", result.getId());
|
||||||
assertEquals(response.getDescribeTemplateStatusSet()[0].getTemplateContent(), result.getContent());
|
assertEquals("您的验证码是{1}", result.getContent());
|
||||||
assertEquals(SmsTemplateAuditStatusEnum.SUCCESS.getStatus(), result.getAuditStatus());
|
assertEquals(SmsTemplateAuditStatusEnum.SUCCESS.getStatus(), result.getAuditStatus());
|
||||||
assertEquals(response.getDescribeTemplateStatusSet()[0].getReviewReply(), result.getAuditReason());
|
assertEquals("审批备注", result.getAuditReason());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
Loading…
Reference in New Issue
Block a user