1,腾讯云短信实现优化,去除不必要VO;

2,增加腾讯云短信功能单测,和集成单测;
This commit is contained in:
scholar
2024-08-13 19:26:45 +08:00
parent 2f38261de8
commit 8242735d84
3 changed files with 284 additions and 310 deletions

View File

@@ -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.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.framework.common.core.KeyValue;
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.SmsSendRespDTO;
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.property.SmsChannelProperties;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.annotations.VisibleForTesting;
import lombok.Data;
import jakarta.xml.bind.DatatypeConverter;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
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;
/**
* 腾讯云短信功能实现
@@ -103,14 +96,15 @@ public class TencentSmsClient extends AbstractSmsClient {
body.put("TemplateId",apiTemplateId);
body.put("TemplateParamSet",ArrayUtils.toArray(templateParams, e -> String.valueOf(e.getValue())));
JSONObject JsonResponse = sendSmsRequest(body,"SendSms","2021-01-11","ap-guangzhou");
SmsResponse smsResponse = getSmsSendResponse(JsonResponse);
return new SmsSendRespDTO().setSuccess(smsResponse.success).setApiMsg(smsResponse.data.toString());
JSONObject JsonResponse = request(body,"SendSms","2021-01-11","ap-guangzhou");
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);
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-Region", region);
HttpResponse response = HttpRequest.post("https://"+host)
.addHeaders(headers)
.body(JSONUtil.toJsonStr(body))
.execute();
String responseBody = HttpUtils.post("https://"+host, headers, JSONUtil.toJsonStr(body));
return JSONUtil.parseObj(response.body());
return JSONUtil.parseObj(responseBody);
}
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));
}
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
public List<SmsReceiveRespDTO> parseSmsReceiveStatus(String text) {
List<SmsReceiveStatus> callback = JsonUtils.parseArray(text, SmsReceiveStatus.class);
return convertList(callback, status -> new SmsReceiveRespDTO()
.setSuccess(SmsReceiveStatus.SUCCESS_CODE.equalsIgnoreCase(status.getStatus()))
.setErrorCode(status.getErrCode()).setErrorMsg(status.getDescription())
.setMobile(status.getMobile()).setReceiveTime(status.getReceiveTime())
.setSerialNo(status.getSerialNo()).setLogId(status.getSessionContext().getLogId()));
JSONArray statuses = JSONUtil.parseArray(text);
// 字段参考
return convertList(statuses, status -> {
JSONObject statusObj = (JSONObject) status;
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
@@ -193,48 +182,22 @@ public class TencentSmsClient extends AbstractSmsClient {
// 构建请求
TreeMap<String, Object> body = new TreeMap<>();
body.put("International",0);
body.put("International",INTERNATIONAL_CHINA);
Integer[] templateIds = {Integer.valueOf(apiTemplateId)};
body.put("TemplateIdSet",templateIds);
JSONObject JsonResponse = sendSmsRequest(body,"DescribeSmsTemplateList","2021-01-11","ap-guangzhou");
QuerySmsTemplateResponse smsTemplateResponse = getSmsTemplateResponse(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();
JSONObject JsonResponse = request(body,"DescribeSmsTemplateList","2021-01-11","ap-guangzhou");
System.out.println("JsonResponse======"+JsonResponse);
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);
}
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
Integer convertSmsTemplateAuditStatus(int templateStatus) {
switch (templateStatus) {
@@ -244,113 +207,4 @@ public class TencentSmsClient extends AbstractSmsClient {
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;
}
}
}