From f81d56eb8836297076c790b264bc2d0a7191125a Mon Sep 17 00:00:00 2001 From: scholar <1145227973@qq.com> Date: Thu, 18 Jul 2024 21:13:36 +0800 Subject: [PATCH 1/9] =?UTF-8?q?=E9=98=BF=E9=87=8C=E4=BA=91=E7=9F=AD?= =?UTF-8?q?=E4=BF=A1=EF=BC=8C=E5=87=8F=E5=B0=91=E4=B8=BASDK=E4=BE=9D?= =?UTF-8?q?=E8=B5=96=EF=BC=8C=E4=BF=AE=E6=94=B9=E4=B8=BA=E5=9F=BA=E4=BA=8E?= =?UTF-8?q?API=E6=96=B9=E5=BC=8F=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sms/core/client/impl/AliyunSmsClient.java | 265 ++++++++++++++---- 1 file changed, 216 insertions(+), 49 deletions(-) diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/AliyunSmsClient.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/AliyunSmsClient.java index 7d01e6cdf..708683b21 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/AliyunSmsClient.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/AliyunSmsClient.java @@ -1,6 +1,14 @@ package cn.iocoder.yudao.module.system.framework.sms.core.client.impl; import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.HexUtil; +import cn.hutool.core.util.URLUtil; +import cn.hutool.crypto.SecureUtil; +import cn.hutool.crypto.digest.DigestUtil; +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpResponse; +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.MapUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; @@ -9,27 +17,23 @@ import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsSendRespD 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.aliyuncs.DefaultAcsClient; -import com.aliyuncs.IAcsClient; -import com.aliyuncs.dysmsapi.model.v20170525.QuerySmsTemplateRequest; -import com.aliyuncs.dysmsapi.model.v20170525.QuerySmsTemplateResponse; -import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest; -import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse; -import com.aliyuncs.profile.DefaultProfile; -import com.aliyuncs.profile.IClientProfile; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.common.annotations.VisibleForTesting; import lombok.Data; import lombok.extern.slf4j.Slf4j; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URISyntaxException; +import java.net.URLEncoder; import java.time.LocalDateTime; -import java.util.List; -import java.util.Objects; +import java.util.*; 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; +import java.text.SimpleDateFormat; /** * 阿里短信客户端的实现类 @@ -40,21 +44,6 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DE @Slf4j public class AliyunSmsClient extends AbstractSmsClient { - /** - * 调用成功 code - */ - public static final String API_CODE_SUCCESS = "OK"; - - /** - * REGION, 使用杭州 - */ - private static final String ENDPOINT = "cn-hangzhou"; - - /** - * 阿里云客户端 - */ - private volatile IAcsClient client; - public AliyunSmsClient(SmsChannelProperties properties) { super(properties); Assert.notEmpty(properties.getApiKey(), "apiKey 不能为空"); @@ -63,24 +52,116 @@ public class AliyunSmsClient extends AbstractSmsClient { @Override protected void doInit() { - IClientProfile profile = DefaultProfile.getProfile(ENDPOINT, properties.getApiKey(), properties.getApiSecret()); - client = new DefaultAcsClient(profile); +// IClientProfile profile = DefaultProfile.getProfile(ENDPOINT, properties.getApiKey(), properties.getApiSecret()); +// client = new DefaultAcsClient(profile); } @Override public SmsSendRespDTO sendSms(Long sendLogId, String mobile, String apiTemplateId, List> templateParams) throws Throwable { - // 构建请求 - SendSmsRequest request = new SendSmsRequest(); - request.setPhoneNumbers(mobile); - request.setSignName(properties.getSignature()); - request.setTemplateCode(apiTemplateId); - request.setTemplateParam(JsonUtils.toJsonString(MapUtils.convertMap(templateParams))); - request.setOutId(String.valueOf(sendLogId)); - // 执行请求 - SendSmsResponse response = client.getAcsResponse(request); - return new SmsSendRespDTO().setSuccess(Objects.equals(response.getCode(), API_CODE_SUCCESS)).setSerialNo(response.getBizId()) - .setApiRequestId(response.getRequestId()).setApiCode(response.getCode()).setApiMsg(response.getMessage()); + + TreeMap queryParam = new TreeMap<>(); + queryParam.put("PhoneNumbers",mobile); + queryParam.put("SignName",properties.getSignature()); + queryParam.put("TemplateCode",apiTemplateId); + queryParam.put("TemplateParam",JsonUtils.toJsonString(MapUtils.convertMap(templateParams))); + + JSONObject response = sendSmsRequest(queryParam,"sendSms"); + SmsResponse smsResponse = getSmsSendResponse(response); + + return new SmsSendRespDTO().setSuccess(smsResponse.success).setApiMsg(smsResponse.data.toString()); + } + + JSONObject sendSmsRequest(TreeMap queryParam,String apiName) throws IOException, URISyntaxException { + + // ************* 步骤 1:拼接规范请求串 ************* + String url = "https://dysmsapi.aliyuncs.com"; //APP接入地址+接口访问URI + String httpMethod = "POST"; // 请求方式 + String canonicalUri = "/"; + // 请求参数,当请求的查询字符串为空时,使用空字符串作为规范化查询字符串 + StringBuilder canonicalQueryString = new StringBuilder(); + queryParam.entrySet().stream().map(entry -> percentCode(entry.getKey()) + "=" + percentCode(String.valueOf(entry.getValue()))).forEachOrdered(queryPart -> { + // 如果canonicalQueryString已经不是空的,则在查询参数前添加"&" + if (!canonicalQueryString.isEmpty()) { + canonicalQueryString.append("&"); + } + canonicalQueryString.append(queryPart); + System.out.println("canonicalQueryString=========>\n" + canonicalQueryString); + }); + + SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); + SDF.setTimeZone(new SimpleTimeZone(0, "GMT")); + String SdfTime = SDF.format(new Date()); + String randomUUID = UUID.randomUUID().toString(); + + TreeMap headers = new TreeMap<>(); + headers.put("host", "dysmsapi.aliyuncs.com"); + headers.put("x-acs-action", apiName); + headers.put("x-acs-version", "2017-05-25"); + headers.put("x-acs-date", SdfTime); + headers.put("x-acs-signature-nonce", randomUUID); +// headers.put("content-type", "application/json;charset=utf-8"); + + // 构造请求头,多个规范化消息头,按照消息头名称(小写)的字符代码顺序以升序排列后拼接在一起 + StringBuilder canonicalHeaders = new StringBuilder(); + // 已签名消息头列表,多个请求头名称(小写)按首字母升序排列并以英文分号(;)分隔 + StringBuilder signedHeadersSb = new StringBuilder(); + headers.entrySet().stream().filter(entry -> entry.getKey().toLowerCase().startsWith("x-acs-") || entry.getKey().equalsIgnoreCase("host") || entry.getKey().equalsIgnoreCase("content-type")).sorted(Map.Entry.comparingByKey()).forEach(entry -> { + String lowerKey = entry.getKey().toLowerCase(); + String value = String.valueOf(entry.getValue()).trim(); + canonicalHeaders.append(lowerKey).append(":").append(value).append("\n"); + signedHeadersSb.append(lowerKey).append(";"); + }); + String signedHeaders = signedHeadersSb.substring(0, signedHeadersSb.length() - 1); + + String body = "";//短信API为RPC接口,query parameters在uri中拼接,因此request body如果没有特殊要求,设置为空。 + String hashedRequestBody = HexUtil.encodeHexStr(DigestUtil.sha256(body)); + + + String canonicalRequest = httpMethod + "\n" + canonicalUri + "\n" + canonicalQueryString + "\n" + canonicalHeaders + "\n" + signedHeaders + "\n" + hashedRequestBody; + System.out.println("canonicalRequest=========>\n" + canonicalRequest); + + // ************* 步骤 2:拼接待签名字符串 ************* + String hashedCanonicalRequest = HexUtil.encodeHexStr(DigestUtil.sha256(canonicalRequest)); + String stringToSign = "ACS3-HMAC-SHA256" + "\n" + hashedCanonicalRequest; + + // ************* 步骤 3:计算签名 ************* + String signature = SecureUtil.hmacSha256(properties.getApiSecret()).digestHex(stringToSign); + + // ************* 步骤 4:拼接 Authorization ************* + String authorization = "ACS3-HMAC-SHA256" + " " + "Credential=" + properties.getApiKey() + ", " + + "SignedHeaders=" + signedHeaders + ", " + "Signature=" + signature; + headers.put("Authorization", authorization); + + // ************* 步骤 5:构造HttpRequest 并执行request请求,获得response ************* +// url = url + canonicalUri; + String urlWithParams = url + "?" + URLUtil.buildQuery(queryParam, null); + + HttpResponse response = HttpRequest.post(urlWithParams) + .addHeaders(headers) + .body(body) + .execute(); +// URIBuilder uriBuilder = new URIBuilder(url); +// // 添加请求参数 +// for (Map.Entry entry : queryParam.entrySet()) { +// uriBuilder.addParameter(entry.getKey(), String.valueOf(entry.getValue())); +// } +// HttpUriRequest httpRequest = new HttpPost(uriBuilder.build()); +//// HttpPost httpPost = new HttpPost(uriBuilder.build()); +//// httpRequest = httpPost; +// +// // 添加http请求头 +// for (Map.Entry entry : headers.entrySet()) { +// httpRequest.addHeader(entry.getKey(), String.valueOf(entry.getValue())); +// } +// +// // 发送请求 +// CloseableHttpClient httpClient = HttpClients.createDefault(); +// CloseableHttpResponse response = httpClient.execute(httpRequest); + System.out.println("getEntity====="+response.body()); + System.out.println("response====="+response); + + return JSONUtil.parseObj(response.body()); } @Override @@ -94,16 +175,15 @@ public class AliyunSmsClient extends AbstractSmsClient { @Override public SmsTemplateRespDTO getSmsTemplate(String apiTemplateId) throws Throwable { - // 构建请求 - QuerySmsTemplateRequest request = new QuerySmsTemplateRequest(); - request.setTemplateCode(apiTemplateId); - // 执行请求 - QuerySmsTemplateResponse response = client.getAcsResponse(request); - if (response.getTemplateStatus() == null) { - return null; - } - return new SmsTemplateRespDTO().setId(response.getTemplateCode()).setContent(response.getTemplateContent()) - .setAuditStatus(convertSmsTemplateAuditStatus(response.getTemplateStatus())).setAuditReason(response.getReason()); + + TreeMap queryParam = new TreeMap<>(); + queryParam.put("TemplateCode",apiTemplateId); + + JSONObject response = sendSmsRequest(queryParam,"QuerySmsTemplate"); + QuerySmsTemplateResponse smsTemplateResponse = getSmsTemplateResponse(response); + return new SmsTemplateRespDTO().setId(smsTemplateResponse.getTemplateCode()).setContent(smsTemplateResponse.getTemplateContent()) + .setAuditStatus(convertSmsTemplateAuditStatus(smsTemplateResponse.getTemplateStatus())).setAuditReason(smsTemplateResponse.getReason()); + } @VisibleForTesting @@ -116,12 +196,99 @@ public class AliyunSmsClient extends AbstractSmsClient { } } + + /** + * 对指定的字符串进行URL编码。 + * 使用UTF-8编码字符集对字符串进行编码,并对特定的字符进行替换,以符合URL编码规范。 + * + * @param str 需要进行URL编码的字符串。 + * @return 编码后的字符串。其中,加号"+"被替换为"%20",星号"*"被替换为"%2A",波浪号"%7E"被替换为"~"。 + */ + public static String percentCode(String str) { + if (str == null) { + throw new IllegalArgumentException("输入字符串不可为null"); + } + try { + return URLEncoder.encode(str, "UTF-8").replace("+", "%20").replace("*", "%2A").replace("%7E", "~"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException("UTF-8编码不被支持", e); + } + } + + private SmsResponse getSmsSendResponse(JSONObject resJson) { + SmsResponse smsResponse = new SmsResponse(); + smsResponse.setSuccess("OK".equals(resJson.getStr("Code"))); + smsResponse.setData(resJson); +// smsResponse.setConfigId(getConfigId()); + return smsResponse; + } + + private QuerySmsTemplateResponse getSmsTemplateResponse(JSONObject resJson) { + + QuerySmsTemplateResponse smsTemplateResponse = new QuerySmsTemplateResponse(); + + smsTemplateResponse.setRequestId(resJson.getStr("RequestId")); + smsTemplateResponse.setTemplateContent(resJson.getStr("TemplateContent")); + smsTemplateResponse.setReason(resJson.getStr("Reason")); + smsTemplateResponse.setTemplateStatus(resJson.getInt("TemplateStatus")); + + return smsTemplateResponse; + } + + /** + *

类名: SmsResponse + *

说明: 发送短信返回信息 + * + * @author :scholar + * 2024/07/17 0:25 + **/ + @Data + public static class SmsResponse { + + /** + * 是否成功 + */ + private boolean success; + + /** + * 厂商原返回体 + */ + private Object data; + + /** + * 配置标识名 如未配置取对应渠道名例如 Alibaba + */ + private String configId; + } + + + /** + *

类名: QuerySmsTemplateResponse + *

说明: sms模板查询返回信息 + * + * @author :scholar + * 2024/07/17 0:25 + **/ + @Data + public static class QuerySmsTemplateResponse { + private String requestId; + private String code; + private String message; + private Integer templateStatus; + private String reason; + private String templateCode; + private Integer templateType; + private String templateName; + private String templateContent; + private String createDate; + } + /** * 短信接收状态 * * 参见 文档 * - * @author 芋道源码 + * @author 润普源码 */ @Data public static class SmsReceiveStatus { From 22ff197f02fde92c7cceead31a1f06809282f2d9 Mon Sep 17 00:00:00 2001 From: scholar <1145227973@qq.com> Date: Fri, 26 Jul 2024 22:06:10 +0800 Subject: [PATCH 2/9] =?UTF-8?q?=E5=AE=8C=E6=88=90todo=E9=83=A8=E5=88=86?= =?UTF-8?q?=E7=9A=84=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sms/core/client/impl/HuaweiSmsClient.java | 117 ++++++++++-------- 1 file changed, 65 insertions(+), 52 deletions(-) diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/HuaweiSmsClient.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/HuaweiSmsClient.java index 84bc2645e..4df820861 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/HuaweiSmsClient.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/HuaweiSmsClient.java @@ -2,35 +2,29 @@ package cn.iocoder.yudao.module.system.framework.sms.core.client.impl; import cn.hutool.core.lang.Assert; -import cn.hutool.core.util.HexUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.crypto.SecureUtil; -import cn.hutool.crypto.digest.DigestUtil; -import cn.hutool.json.JSONArray; +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpResponse; +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.CollectionUtils; 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.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 org.apache.http.client.methods.*; -import org.apache.http.entity.StringEntity; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClientBuilder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpResponse; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; import java.text.SimpleDateFormat; import java.util.*; @@ -38,6 +32,7 @@ import java.util.*; import java.time.LocalDateTime; +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; @@ -55,88 +50,90 @@ public class HuaweiSmsClient extends AbstractSmsClient { /** * 调用成功 code */ - public static final String API_CODE_SUCCESS = "OK"; - private static final Logger LOGGER = LoggerFactory.getLogger(HuaweiSmsClient.class); + 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 SIGNEDHEADERS = "content-type;host;x-sdk-date"; + + @Override + protected void doInit() { + + } public HuaweiSmsClient(SmsChannelProperties properties) { super(properties); Assert.notEmpty(properties.getApiKey(), "apiKey 不能为空"); Assert.notEmpty(properties.getApiSecret(), "apiSecret 不能为空"); } - @Override - protected void doInit() { - } @Override public SmsSendRespDTO sendSms(Long sendLogId, String mobile, String apiTemplateId, List> templateParams) throws Throwable { - String url = "https://smsapi.cn-north-4.myhuaweicloud.com:443/sms/batchSendSms/v1"; //APP接入地址+接口访问URI // 相比较阿里短信,华为短信发送的时候需要额外的参数“通道号”,考虑到不破坏原有的的结构 // 所以将 通道号 拼接到 apiTemplateId 字段中,格式为 "apiTemplateId 通道号"。空格为分隔符。 String sender = StrUtil.subAfter(apiTemplateId, " ", true); //中国大陆短信签名通道号或全球短信通道号 String templateId = StrUtil.subBefore(apiTemplateId, " ", true); //模板ID - //必填,全局号码格式(包含国家码),示例:+86151****6789,多个号码之间用英文逗号分隔 - String receiver = mobile; //短信接收人号码 - //选填,短信状态报告接收地址,推荐使用域名,为空或者不填表示不接收状态报告 String statusCallBack = properties.getCallbackUrl(); + List templateParas = CollectionUtils.convertList(templateParams, kv -> String.valueOf(kv.getValue())); + + JSONObject JsonResponse = sendSmsRequest(sender,mobile,templateId,templateParas,statusCallBack); + SmsResponse smsResponse = getSmsSendResponse(JsonResponse); + + return new SmsSendRespDTO().setSuccess(smsResponse.success).setApiMsg(smsResponse.data.toString()); + } + + JSONObject sendSmsRequest(String sender,String mobile,String templateId,List templateParas,String statusCallBack) throws UnsupportedEncodingException { + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd'T'HHmmss'Z'", Locale.ENGLISH); sdf.setTimeZone(TimeZone.getTimeZone("UTC")); - String singerDate = sdf.format(new Date()); + String sdkDate = sdf.format(new Date()); // ************* 步骤 1:拼接规范请求串 ************* String httpRequestMethod = "POST"; String canonicalUri = "/sms/batchSendSms/v1/"; String canonicalQueryString = "";//查询参数为空 String canonicalHeaders = "content-type:application/x-www-form-urlencoded\n" - + "host:smsapi.cn-north-4.myhuaweicloud.com:443\n" - + "x-sdk-date:" + singerDate + "\n"; - String signedHeaders = "content-type;host;x-sdk-date"; - /** - * 选填,使用无变量模板时请赋空值 String templateParas = ""; - * 单变量模板示例:模板内容为"您的验证码是${NUM_6}"时,templateParas可填写为"[\"111111\"]" - * 双变量模板示例:模板内容为"您有${NUM_2}件快递请到${TXT_20}领取"时,templateParas可填写为"[\"3\",\"人民公园正门\"]" - */ - List templateParas = new ArrayList<>(); - for (KeyValue kv : templateParams) { - templateParas.add(String.valueOf(kv.getValue())); - } - + + "host:"+ HOST +"\n" + + "x-sdk-date:" + sdkDate + "\n"; //请求Body,不携带签名名称时,signature请填null - String body = buildRequestBody(sender, receiver, templateId, templateParas, statusCallBack, null); + String body = buildRequestBody(sender, mobile, templateId, templateParas, statusCallBack, null); if (null == body || body.isEmpty()) { return null; } - String hashedRequestBody = HexUtil.encodeHexStr(DigestUtil.sha256(body)); + String hashedRequestBody = sha256Hex(body); String canonicalRequest = httpRequestMethod + "\n" + canonicalUri + "\n" + canonicalQueryString + "\n" - + canonicalHeaders + "\n" + signedHeaders + "\n" + hashedRequestBody; + + canonicalHeaders + "\n" + SIGNEDHEADERS + "\n" + hashedRequestBody; // ************* 步骤 2:拼接待签名字符串 ************* - String hashedCanonicalRequest = HexUtil.encodeHexStr(DigestUtil.sha256(canonicalRequest)); - String stringToSign = "SDK-HMAC-SHA256" + "\n" + singerDate + "\n" + hashedCanonicalRequest; + String hashedCanonicalRequest = sha256Hex(canonicalRequest); + String stringToSign = "SDK-HMAC-SHA256" + "\n" + sdkDate + "\n" + hashedCanonicalRequest; // ************* 步骤 3:计算签名 ************* String signature = SecureUtil.hmacSha256(properties.getApiSecret()).digestHex(stringToSign); // ************* 步骤 4:拼接 Authorization ************* String authorization = "SDK-HMAC-SHA256" + " " + "Access=" + properties.getApiKey() + ", " - + "SignedHeaders=" + signedHeaders + ", " + "Signature=" + signature; + + "SignedHeaders=" + SIGNEDHEADERS + ", " + "Signature=" + signature; // ************* 步骤 5:构造HttpRequest 并执行request请求,获得response ************* - HttpUriRequest postMethod = RequestBuilder.post() - .setUri(url) - .setEntity(new StringEntity(body, StandardCharsets.UTF_8)) - .setHeader("Content-Type","application/x-www-form-urlencoded") - .setHeader("X-Sdk-Date",singerDate) - .setHeader("Authorization",authorization) - .build(); - CloseableHttpClient client = HttpClientBuilder.create().build(); - HttpResponse response = client.execute(postMethod); + HttpResponse response = HttpRequest.post(URL) + .header("Content-Type", "application/x-www-form-urlencoded") + .header("X-Sdk-Date", sdkDate) + .header("host",HOST) + .header("Authorization", authorization) + .body(body) + .execute(); - return new SmsSendRespDTO().setSuccess(Objects.equals(response.getStatusLine().getReasonPhrase(), API_CODE_SUCCESS)).setSerialNo(Integer.toString(response.getStatusLine().getStatusCode())) - .setApiRequestId(null).setApiCode(null).setApiMsg(null); + return JSONUtil.parseObj(response.body()); + } + + private SmsResponse getSmsSendResponse(JSONObject resJson) { + SmsResponse smsResponse = new SmsResponse(); + smsResponse.setSuccess("000000".equals(resJson.getStr("code"))); + smsResponse.setData(resJson); + return smsResponse; } static String buildRequestBody(String sender, String receiver, String templateId, List templateParas, @@ -151,7 +148,7 @@ public class HuaweiSmsClient extends AbstractSmsClient { appendToBody(body, "from=", sender); appendToBody(body, "&to=", receiver); appendToBody(body, "&templateId=", templateId); - appendToBody(body, "&templateParas=", new JSONArray(templateParas).toString()); + appendToBody(body, "&templateParas=", JsonUtils.toJsonString(templateParas)); appendToBody(body, "&statusCallback=", statusCallBack); appendToBody(body, "&signature=", signature); return body.toString(); @@ -179,6 +176,22 @@ public class HuaweiSmsClient extends AbstractSmsClient { } + @Data + public static class SmsResponse { + + /** + * 是否成功 + */ + private boolean success; + + /** + * 厂商原返回体 + */ + private Object data; + + } + + /** * 短信接收状态 * From ba187885172e42054231103760560dd8c8ddde0d Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 31 Jul 2024 19:48:02 +0800 Subject: [PATCH 3/9] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E3=80=91SYSTEM=EF=BC=9A=E5=BE=AE=E4=BF=A1=E5=B0=8F?= =?UTF-8?q?=E7=A8=8B=E5=BA=8F=E7=9A=84=E8=AE=A2=E9=98=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../promotion/enums/MessageTemplateConstants.java | 2 +- .../combination/CombinationRecordServiceImpl.java | 8 ++++---- .../module/trade/enums/MessageTemplateConstants.java | 12 ++++++------ .../brokerage/BrokerageWithdrawServiceImpl.java | 4 ++-- .../service/message/TradeMessageServiceImpl.java | 2 +- .../service/order/TradeOrderUpdateServiceImpl.java | 4 ++-- .../module/pay/enums/MessageTemplateConstants.java | 4 ++-- .../service/wallet/PayWalletRechargeServiceImpl.java | 4 ++-- .../service/social/SocialClientServiceImpl.java | 6 +++++- .../src/main/resources/application-local.yaml | 2 +- 10 files changed, 26 insertions(+), 22 deletions(-) diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/MessageTemplateConstants.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/MessageTemplateConstants.java index 83e6ecde8..9a6bdd41d 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/MessageTemplateConstants.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/MessageTemplateConstants.java @@ -9,6 +9,6 @@ public interface MessageTemplateConstants { //======================= 小程序订阅消息模版 ======================= - String COMBINATION_RESULT = "拼团结果通知"; + String COMBINATION_SUCCESS = "拼团结果通知"; } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java index 10022ad6c..1f7c9a073 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java @@ -44,7 +44,7 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.afterNow; import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.beforeNow; import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; -import static cn.iocoder.yudao.module.promotion.enums.MessageTemplateConstants.COMBINATION_RESULT; +import static cn.iocoder.yudao.module.promotion.enums.MessageTemplateConstants.COMBINATION_SUCCESS; // TODO 芋艿:等拼团记录做完,完整 review 下 @@ -212,10 +212,10 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { } updateRecords.add(updateRecord); }); - Boolean result = combinationRecordMapper.updateBatch(updateRecords); + Boolean updateSuccess = combinationRecordMapper.updateBatch(updateRecords); // 3. 拼团成功发送订阅消息 - if (result && isFull) { + if (updateSuccess && isFull) { records.forEach(item -> { getSelf().sendCombinationResultMessage(item); }); @@ -227,7 +227,7 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { // 构建并发送模版消息 socialClientApi.sendWxaSubscribeMessage(new SocialWxaSubscribeMessageSendReqDTO() .setUserId(record.getUserId()).setUserType(UserTypeEnum.MEMBER.getValue()) - .setTemplateTitle(COMBINATION_RESULT) + .setTemplateTitle(COMBINATION_SUCCESS) .setPage("pages/order/detail?id=" + record.getOrderId()) // 订单详情页 .addMessage("thing1", "商品拼团活动") // 活动标题 .addMessage("thing2", "恭喜您拼团成功!我们将尽快为您发货。")); // 温馨提示 diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/MessageTemplateConstants.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/MessageTemplateConstants.java index 195a9fde2..56c4c9005 100644 --- a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/MessageTemplateConstants.java +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/MessageTemplateConstants.java @@ -7,15 +7,15 @@ package cn.iocoder.yudao.module.trade.enums; */ public interface MessageTemplateConstants { - //======================= 短信消息模版 ======================= + // ======================= 短信消息模版 ======================= - String ORDER_DELIVERY = "order_delivery"; // 短信模版编号 + String SMS_ORDER_DELIVERY = "order_delivery"; // 短信模版编号 - String BROKERAGE_WITHDRAW_AUDIT_APPROVE = "brokerage_withdraw_audit_approve"; // 佣金提现(审核通过) - String BROKERAGE_WITHDRAW_AUDIT_REJECT = "brokerage_withdraw_audit_reject"; // 佣金提现(审核不通过) + String SMS_BROKERAGE_WITHDRAW_AUDIT_APPROVE = "brokerage_withdraw_audit_approve"; // 佣金提现(审核通过) + String SMS_BROKERAGE_WITHDRAW_AUDIT_REJECT = "brokerage_withdraw_audit_reject"; // 佣金提现(审核不通过) - //======================= 小程序订阅消息模版 ======================= + // ======================= 小程序订阅消息模版 ======================= - String DELIVERY_ORDER = "订单发货通知"; + String WXA_ORDER_DELIVERY = "订单发货通知"; } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageWithdrawServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageWithdrawServiceImpl.java index 0560c33d8..c735163a5 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageWithdrawServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageWithdrawServiceImpl.java @@ -77,14 +77,14 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService { String templateCode; if (BrokerageWithdrawStatusEnum.AUDIT_SUCCESS.equals(status)) { - templateCode = MessageTemplateConstants.BROKERAGE_WITHDRAW_AUDIT_APPROVE; + templateCode = MessageTemplateConstants.SMS_BROKERAGE_WITHDRAW_AUDIT_APPROVE; // 3.1 通过时佣金转余额 if (BrokerageWithdrawTypeEnum.WALLET.getType().equals(withdraw.getType())) { // todo 疯狂: } // TODO 疯狂:调用转账接口 } else if (BrokerageWithdrawStatusEnum.AUDIT_FAIL.equals(status)) { - templateCode = MessageTemplateConstants.BROKERAGE_WITHDRAW_AUDIT_REJECT; + templateCode = MessageTemplateConstants.SMS_BROKERAGE_WITHDRAW_AUDIT_REJECT; // 3.2 驳回时需要退还用户佣金 brokerageRecordService.addBrokerage(withdraw.getUserId(), BrokerageRecordBizTypeEnum.WITHDRAW_REJECT, String.valueOf(withdraw.getId()), withdraw.getPrice(), BrokerageRecordBizTypeEnum.WITHDRAW_REJECT.getTitle()); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/message/TradeMessageServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/message/TradeMessageServiceImpl.java index eefd26c6e..a06c06906 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/message/TradeMessageServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/message/TradeMessageServiceImpl.java @@ -37,7 +37,7 @@ public class TradeMessageServiceImpl implements TradeMessageService { notifyMessageSendApi.sendSingleMessageToMember( new NotifySendSingleToUserReqDTO() .setUserId(reqBO.getUserId()) - .setTemplateCode(MessageTemplateConstants.ORDER_DELIVERY) + .setTemplateCode(MessageTemplateConstants.SMS_ORDER_DELIVERY) .setTemplateParams(msgMap)); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java index 4bba58f4e..3c31d13b5 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java @@ -71,7 +71,7 @@ import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.min import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getTerminal; import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*; -import static cn.iocoder.yudao.module.trade.enums.MessageTemplateConstants.DELIVERY_ORDER; +import static cn.iocoder.yudao.module.trade.enums.MessageTemplateConstants.WXA_ORDER_DELIVERY; /** * 交易订单【写】Service 实现类 @@ -384,7 +384,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { Long orderId = order.getId(); socialClientApi.sendWxaSubscribeMessage(new SocialWxaSubscribeMessageSendReqDTO() .setUserId(order.getUserId()).setUserType(UserTypeEnum.MEMBER.getValue()) - .setTemplateTitle(DELIVERY_ORDER) + .setTemplateTitle(WXA_ORDER_DELIVERY) .setPage("pages/order/detail?id=" + orderId) // 订单详情页 .addMessage("character_string3", String.valueOf(orderId)) // 订单编号 .addMessage("phrase6", TradeOrderStatusEnum.DELIVERED.getName()) // 订单状态 diff --git a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/MessageTemplateConstants.java b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/MessageTemplateConstants.java index b25d7645d..9497d776b 100644 --- a/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/MessageTemplateConstants.java +++ b/yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/MessageTemplateConstants.java @@ -7,8 +7,8 @@ package cn.iocoder.yudao.module.pay.enums; */ public interface MessageTemplateConstants { - //======================= 小程序订阅消息 ======================= + // ======================= 小程序订阅消息 ======================= - String WALLET_RECHARGER_PAID = "充值成功通知"; + String WXA_WALLET_RECHARGER_PAID = "充值成功通知"; } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletRechargeServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletRechargeServiceImpl.java index 1d334d1b5..94c9fa611 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletRechargeServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletRechargeServiceImpl.java @@ -39,7 +39,7 @@ import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString import static cn.iocoder.yudao.framework.common.util.number.MoneyUtils.fenToYuanStr; import static cn.iocoder.yudao.module.pay.convert.wallet.PayWalletRechargeConvert.INSTANCE; import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*; -import static cn.iocoder.yudao.module.pay.enums.MessageTemplateConstants.WALLET_RECHARGER_PAID; +import static cn.iocoder.yudao.module.pay.enums.MessageTemplateConstants.WXA_WALLET_RECHARGER_PAID; import static cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum.*; /** @@ -147,7 +147,7 @@ public class PayWalletRechargeServiceImpl implements PayWalletRechargeService { // 2. 构建并发送模版消息 socialClientApi.sendWxaSubscribeMessage(new SocialWxaSubscribeMessageSendReqDTO() .setUserId(wallet.getUserId()).setUserType(wallet.getUserType()) - .setTemplateTitle(WALLET_RECHARGER_PAID) + .setTemplateTitle(WXA_WALLET_RECHARGER_PAID) .setPage("pages/user/wallet/money") // 钱包详情界面 .addMessage("character_string1", String.valueOf(payOrderId)) // 支付单编号 .addMessage("amount2", fenToYuanStr(walletRecharge.getTotalPrice())) // 充值金额 diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImpl.java index 46993b622..ba86165c3 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImpl.java @@ -82,7 +82,11 @@ public class SocialClientServiceImpl implements SocialClientService { @Value("${yudao.wxa-code.env-version:release}") public String envVersion; /** - * 订阅消息跳转小程序类型:developer为开发版;trial为体验版;formal为正式版; + * 订阅消息跳转小程序类型 + * + * 1. developer:开发版 + * 2. trial:体验版 + * 3. formal:正式版 */ @Value("${yudao.wxa-subscribe-message.miniprogram-state:formal}") public String miniprogramState; diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index bd33bd33b..0c27aeac8 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -224,7 +224,7 @@ yudao: wxa-code: env-version: develop # 小程序版本: 正式版为 "release";体验版为 "trial";开发版为 "develop" wxa-subscribe-message: - miniprogram-state: developer # 跳转小程序类型:developer为开发版;trial为体验版;formal为正式版; + miniprogram-state: developer # 跳转小程序类型:开发版为 “developer”;体验版为 “trial”为;正式版为 “formal” tencent-lbs-key: TVDBZ-TDILD-4ON4B-PFDZA-RNLKH-VVF6E # QQ 地图的密钥 https://lbs.qq.com/service/staticV2/staticGuide/staticDoc justauth: From 08e1c69d10a5c946ab9d32d7d605fe7ffc93c96f Mon Sep 17 00:00:00 2001 From: zhougang <921366807@qq.com> Date: Wed, 31 Jul 2024 22:43:48 +0800 Subject: [PATCH 4/9] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E8=84=B1=E6=95=8F=E6=94=AF=E6=8C=81=20Spring?= =?UTF-8?q?=20el=20=E8=A1=A8=E8=BE=BE=E5=BC=8F=EF=BC=8C=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E6=A0=B9=E6=8D=AE=E6=9D=83=E9=99=90=E6=8E=A7=E5=88=B6=E8=84=B1?= =?UTF-8?q?=E6=95=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../util/spring/SpringExpressionUtils.java | 21 +++++++++++++++++++ .../yudao-spring-boot-starter-web/pom.xml | 5 +++++ .../regex/annotation/EmailDesensitize.java | 6 ++++++ .../regex/annotation/RegexDesensitize.java | 6 ++++++ .../AbstractRegexDesensitizationHandler.java | 14 +++++++++++++ .../DefaultRegexDesensitizationHandler.java | 6 ++++++ .../handler/EmailDesensitizationHandler.java | 5 +++++ .../annotation/BankCardDesensitize.java | 5 +++++ .../annotation/CarLicenseDesensitize.java | 5 +++++ .../annotation/ChineseNameDesensitize.java | 5 +++++ .../annotation/FixedPhoneDesensitize.java | 5 +++++ .../slider/annotation/IdCardDesensitize.java | 5 +++++ .../slider/annotation/MobileDesensitize.java | 5 +++++ .../annotation/PasswordDesensitize.java | 5 +++++ .../slider/annotation/SliderDesensitize.java | 6 ++++++ .../AbstractSliderDesensitizationHandler.java | 14 +++++++++++++ .../handler/BankCardDesensitization.java | 5 +++++ .../handler/CarLicenseDesensitization.java | 6 ++++++ .../handler/ChineseNameDesensitization.java | 5 +++++ .../DefaultDesensitizationHandler.java | 6 ++++++ .../handler/FixedPhoneDesensitization.java | 6 ++++++ .../slider/handler/IdCardDesensitization.java | 6 ++++++ .../slider/handler/MobileDesensitization.java | 6 ++++++ .../handler/PasswordDesensitization.java | 6 ++++++ 24 files changed, 164 insertions(+) diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/spring/SpringExpressionUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/spring/SpringExpressionUtils.java index 9a7f8812b..e9670d88d 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/spring/SpringExpressionUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/spring/SpringExpressionUtils.java @@ -3,11 +3,15 @@ package cn.iocoder.yudao.framework.common.util.spring; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.StrUtil; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.context.expression.BeanFactoryResolver; import org.springframework.core.DefaultParameterNameDiscoverer; import org.springframework.core.ParameterNameDiscoverer; import org.springframework.expression.EvaluationContext; +import org.springframework.expression.Expression; import org.springframework.expression.ExpressionParser; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.expression.spel.support.StandardEvaluationContext; @@ -86,4 +90,21 @@ public class SpringExpressionUtils { return result; } + /** + * 从 Bean 工厂,解析 EL 表达式的结果 + * + * @param beanFactory Bean 工程 + * @param expressionString EL 表达式 + * @return 执行界面 + */ + public static Object parseExpression(BeanFactory beanFactory, String expressionString) { + if (StrUtil.isBlank(expressionString)) { + return null; + } + Expression expression = EXPRESSION_PARSER.parseExpression(expressionString); + StandardEvaluationContext context = new StandardEvaluationContext(); + context.setBeanResolver(new BeanFactoryResolver(beanFactory)); + return expression.getValue(context); + } + } diff --git a/yudao-framework/yudao-spring-boot-starter-web/pom.xml b/yudao-framework/yudao-spring-boot-starter-web/pom.xml index b5d0aa84d..5861f198f 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-web/pom.xml @@ -32,6 +32,11 @@ spring-boot-configuration-processor true + + org.aspectj + aspectjweaver + provided + com.github.xiaoymin diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/annotation/EmailDesensitize.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/annotation/EmailDesensitize.java index 227f25499..5485c194e 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/annotation/EmailDesensitize.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/annotation/EmailDesensitize.java @@ -33,4 +33,10 @@ public @interface EmailDesensitize { * 比如:example@gmail.com 脱敏之后为 e****@gmail.com */ String replacer() default "$1****$2"; + + /** + * el 表达式,当执行 condition 返回 true 的时候,跳过脱敏 + */ + String condition() default ""; + } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/annotation/RegexDesensitize.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/annotation/RegexDesensitize.java index 4ab7c7415..9b0a3fa38 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/annotation/RegexDesensitize.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/annotation/RegexDesensitize.java @@ -35,4 +35,10 @@ public @interface RegexDesensitize { * 脱敏后字符串 ******456789 */ String replacer() default "******"; + + /** + * el 表达式,当执行 condition 返回 true 的时候,跳过脱敏 + */ + String condition() default ""; + } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/AbstractRegexDesensitizationHandler.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/AbstractRegexDesensitizationHandler.java index f43431b1d..11d3dc23b 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/AbstractRegexDesensitizationHandler.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/AbstractRegexDesensitizationHandler.java @@ -1,5 +1,7 @@ package cn.iocoder.yudao.framework.desensitize.core.regex.handler; +import cn.hutool.extra.spring.SpringUtil; +import cn.iocoder.yudao.framework.common.util.spring.SpringExpressionUtils; import cn.iocoder.yudao.framework.desensitize.core.base.handler.DesensitizationHandler; import java.lang.annotation.Annotation; @@ -14,6 +16,10 @@ public abstract class AbstractRegexDesensitizationHandler @Override public String desensitize(String origin, T annotation) { + Object expressionResult = SpringExpressionUtils.parseExpression(SpringUtil.getApplicationContext(), getCondition(annotation)); + if (expressionResult instanceof Boolean && (Boolean) expressionResult) { + return origin; + } String regex = getRegex(annotation); String replacer = getReplacer(annotation); return origin.replaceAll(regex, replacer); @@ -35,4 +41,12 @@ public abstract class AbstractRegexDesensitizationHandler */ abstract String getReplacer(T annotation); + /** + * el 表达式 + * + * @param annotation 注解信息 + * @return el 表达式 + */ + abstract String getCondition(T annotation); + } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/DefaultRegexDesensitizationHandler.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/DefaultRegexDesensitizationHandler.java index f92414e0c..75fa8895d 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/DefaultRegexDesensitizationHandler.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/DefaultRegexDesensitizationHandler.java @@ -18,4 +18,10 @@ public class DefaultRegexDesensitizationHandler extends AbstractRegexDesensitiza String getReplacer(RegexDesensitize annotation) { return annotation.replacer(); } + + @Override + String getCondition(RegexDesensitize annotation) { + return annotation.condition(); + } + } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/EmailDesensitizationHandler.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/EmailDesensitizationHandler.java index 8d1867a64..fec46d449 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/EmailDesensitizationHandler.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/EmailDesensitizationHandler.java @@ -19,4 +19,9 @@ public class EmailDesensitizationHandler extends AbstractRegexDesensitizationHan return annotation.replacer(); } + @Override + String getCondition(EmailDesensitize annotation) { + return annotation.condition(); + } + } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/BankCardDesensitize.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/BankCardDesensitize.java index 19ad54e25..f512f4c9e 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/BankCardDesensitize.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/BankCardDesensitize.java @@ -37,4 +37,9 @@ public @interface BankCardDesensitize { */ String replacer() default "*"; + /** + * el 表达式,当执行 condition 返回 true 的时候,跳过脱敏 + */ + String condition() default ""; + } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/CarLicenseDesensitize.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/CarLicenseDesensitize.java index 9000e1ec4..93e895bf4 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/CarLicenseDesensitize.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/CarLicenseDesensitize.java @@ -37,4 +37,9 @@ public @interface CarLicenseDesensitize { */ String replacer() default "*"; + /** + * el 表达式,当执行 condition 返回 true 的时候,跳过脱敏 + */ + String condition() default ""; + } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/ChineseNameDesensitize.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/ChineseNameDesensitize.java index 73a0d0ee5..05c22dd77 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/ChineseNameDesensitize.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/ChineseNameDesensitize.java @@ -37,4 +37,9 @@ public @interface ChineseNameDesensitize { */ String replacer() default "*"; + /** + * el 表达式,当执行 condition 返回 true 的时候,跳过脱敏 + */ + String condition() default ""; + } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/FixedPhoneDesensitize.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/FixedPhoneDesensitize.java index 862235346..ade43793b 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/FixedPhoneDesensitize.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/FixedPhoneDesensitize.java @@ -37,4 +37,9 @@ public @interface FixedPhoneDesensitize { */ String replacer() default "*"; + /** + * el 表达式,当执行 condition 返回 true 的时候,跳过脱敏 + */ + String condition() default ""; + } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/IdCardDesensitize.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/IdCardDesensitize.java index 8a654c915..b3bbb45e8 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/IdCardDesensitize.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/IdCardDesensitize.java @@ -37,4 +37,9 @@ public @interface IdCardDesensitize { */ String replacer() default "*"; + /** + * el 表达式,当执行 condition 返回 true 的时候,跳过脱敏 + */ + String condition() default ""; + } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/MobileDesensitize.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/MobileDesensitize.java index f0c42f192..9a8c55708 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/MobileDesensitize.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/MobileDesensitize.java @@ -37,4 +37,9 @@ public @interface MobileDesensitize { */ String replacer() default "*"; + /** + * el 表达式,当执行 condition 返回 true 的时候,跳过脱敏 + */ + String condition() default ""; + } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/PasswordDesensitize.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/PasswordDesensitize.java index 6a3b2694f..f4c6bac98 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/PasswordDesensitize.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/PasswordDesensitize.java @@ -39,4 +39,9 @@ public @interface PasswordDesensitize { */ String replacer() default "*"; + /** + * el 表达式,当执行 condition 返回 true 的时候,跳过脱敏 + */ + String condition() default ""; + } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/SliderDesensitize.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/SliderDesensitize.java index ec79635b9..13a5becfa 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/SliderDesensitize.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/SliderDesensitize.java @@ -40,4 +40,10 @@ public @interface SliderDesensitize { * 前缀保留长度 */ int prefixKeep() default 0; + + /** + * el 表达式,当执行 condition 返回 true 的时候,跳过脱敏 + */ + String condition() default ""; + } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/AbstractSliderDesensitizationHandler.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/AbstractSliderDesensitizationHandler.java index 7dd2a7fd1..b3b076984 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/AbstractSliderDesensitizationHandler.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/AbstractSliderDesensitizationHandler.java @@ -1,5 +1,7 @@ package cn.iocoder.yudao.framework.desensitize.core.slider.handler; +import cn.hutool.extra.spring.SpringUtil; +import cn.iocoder.yudao.framework.common.util.spring.SpringExpressionUtils; import cn.iocoder.yudao.framework.desensitize.core.base.handler.DesensitizationHandler; import java.lang.annotation.Annotation; @@ -14,6 +16,10 @@ public abstract class AbstractSliderDesensitizationHandler @Override public String desensitize(String origin, T annotation) { + Object expressionResult = SpringExpressionUtils.parseExpression(SpringUtil.getApplicationContext(), getCondition(annotation)); + if (expressionResult instanceof Boolean && (Boolean) expressionResult) { + return origin; + } int prefixKeep = getPrefixKeep(annotation); int suffixKeep = getSuffixKeep(annotation); String replacer = getReplacer(annotation); @@ -75,4 +81,12 @@ public abstract class AbstractSliderDesensitizationHandler */ abstract String getReplacer(T annotation); + /** + * el 表达式 + * + * @param annotation 注解信息 + * @return el 表达式 + */ + abstract String getCondition(T annotation); + } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/BankCardDesensitization.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/BankCardDesensitization.java index e1d90ea6d..c56edc78d 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/BankCardDesensitization.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/BankCardDesensitization.java @@ -24,4 +24,9 @@ public class BankCardDesensitization extends AbstractSliderDesensitizationHandle return annotation.replacer(); } + @Override + String getCondition(BankCardDesensitize annotation) { + return annotation.condition(); + } + } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/CarLicenseDesensitization.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/CarLicenseDesensitization.java index 34b3e9a69..6829c0688 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/CarLicenseDesensitization.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/CarLicenseDesensitization.java @@ -22,4 +22,10 @@ public class CarLicenseDesensitization extends AbstractSliderDesensitizationHand String getReplacer(CarLicenseDesensitize annotation) { return annotation.replacer(); } + + @Override + String getCondition(CarLicenseDesensitize annotation) { + return annotation.condition(); + } + } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/ChineseNameDesensitization.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/ChineseNameDesensitization.java index f71dac0e0..e9be53176 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/ChineseNameDesensitization.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/ChineseNameDesensitization.java @@ -24,4 +24,9 @@ public class ChineseNameDesensitization extends AbstractSliderDesensitizationHan return annotation.replacer(); } + @Override + String getCondition(ChineseNameDesensitize annotation) { + return annotation.condition(); + } + } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/DefaultDesensitizationHandler.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/DefaultDesensitizationHandler.java index 8b0adaeab..4fdadf3b7 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/DefaultDesensitizationHandler.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/DefaultDesensitizationHandler.java @@ -22,4 +22,10 @@ public class DefaultDesensitizationHandler extends AbstractSliderDesensitization String getReplacer(SliderDesensitize annotation) { return annotation.replacer(); } + + @Override + String getCondition(SliderDesensitize annotation) { + return annotation.condition(); + } + } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/FixedPhoneDesensitization.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/FixedPhoneDesensitization.java index 6e2326171..6a566f4df 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/FixedPhoneDesensitization.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/FixedPhoneDesensitization.java @@ -22,4 +22,10 @@ public class FixedPhoneDesensitization extends AbstractSliderDesensitizationHand String getReplacer(FixedPhoneDesensitize annotation) { return annotation.replacer(); } + + @Override + String getCondition(FixedPhoneDesensitize annotation) { + return annotation.condition(); + } + } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/IdCardDesensitization.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/IdCardDesensitization.java index 9d525b34c..b85c9a16c 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/IdCardDesensitization.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/IdCardDesensitization.java @@ -22,4 +22,10 @@ public class IdCardDesensitization extends AbstractSliderDesensitizationHandler< String getReplacer(IdCardDesensitize annotation) { return annotation.replacer(); } + + @Override + String getCondition(IdCardDesensitize annotation) { + return annotation.condition(); + } + } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/MobileDesensitization.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/MobileDesensitization.java index 582900ad4..102d07e35 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/MobileDesensitization.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/MobileDesensitization.java @@ -23,4 +23,10 @@ public class MobileDesensitization extends AbstractSliderDesensitizationHandler< String getReplacer(MobileDesensitize annotation) { return annotation.replacer(); } + + @Override + String getCondition(MobileDesensitize annotation) { + return annotation.condition(); + } + } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/PasswordDesensitization.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/PasswordDesensitization.java index 1bccaa2a4..1ebaca2e9 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/PasswordDesensitization.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/PasswordDesensitization.java @@ -22,4 +22,10 @@ public class PasswordDesensitization extends AbstractSliderDesensitizationHandle String getReplacer(PasswordDesensitize annotation) { return annotation.replacer(); } + + @Override + String getCondition(PasswordDesensitize annotation) { + return annotation.condition(); + } + } From abe2f8580b3340e2064cca81696c02931b641c84 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 31 Jul 2024 23:47:02 +0800 Subject: [PATCH 5/9] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E3=80=91SYSTEM=EF=BC=9A=E5=BE=AE=E4=BF=A1=E5=B0=8F?= =?UTF-8?q?=E7=A8=8B=E5=BA=8F=E7=9A=84=E8=AE=A2=E9=98=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../trade/service/order/TradeOrderUpdateServiceImpl.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java index 3c31d13b5..7acba7dde 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java @@ -7,6 +7,7 @@ import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.RandomUtil; +import cn.hutool.core.util.StrUtil; import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.core.KeyValue; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; @@ -389,7 +390,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { .addMessage("character_string3", String.valueOf(orderId)) // 订单编号 .addMessage("phrase6", TradeOrderStatusEnum.DELIVERED.getName()) // 订单状态 .addMessage("date4", LocalDateTimeUtil.formatNormal(LocalDateTime.now()))// 发货时间 - .addMessage("character_string5", deliveryReqVO.getLogisticsNo()) // 快递单号 + .addMessage("character_string5", StrUtil.blankToDefault(deliveryReqVO.getLogisticsNo(), "-")) // 快递单号 .addMessage("thing9", order.getReceiverDetailAddress())); // 收货地址 } From 7de546385a2c09c59eb6e23d7cffb37fe4c0b1b9 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 1 Aug 2024 23:21:14 +0800 Subject: [PATCH 6/9] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E3=80=91SYSTEM=EF=BC=9A=E5=BE=AE=E4=BF=A1=E5=B0=8F?= =?UTF-8?q?=E7=A8=8B=E5=BA=8F=E7=9A=84=E8=AE=A2=E9=98=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/social/AppSocialUserController.java | 6 +++--- ...odeReqVO.java => AppSocialWxaQrcodeReqVO.java} | 2 +- ...a => AppSocialWxaSubscribeTemplateRespVO.java} | 2 +- .../system/api/social/SocialClientApiImpl.java | 15 ++++++++------- 4 files changed, 13 insertions(+), 12 deletions(-) rename yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/{AppSocialWxQrcodeReqVO.java => AppSocialWxaQrcodeReqVO.java} (97%) rename yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/{AppSocialWxSubscribeTemplateRespVO.java => AppSocialWxaSubscribeTemplateRespVO.java} (95%) diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java index e8de23c2b..f2de7efdc 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java @@ -63,16 +63,16 @@ public class AppSocialUserController { @PostMapping("/wxa-qrcode") @Operation(summary = "获得微信小程序码(base64 image)") - public CommonResult getWxaQrcode(@RequestBody @Valid AppSocialWxQrcodeReqVO reqVO) { + public CommonResult getWxaQrcode(@RequestBody @Valid AppSocialWxaQrcodeReqVO reqVO) { byte[] wxQrcode = socialClientApi.getWxaQrcode(BeanUtils.toBean(reqVO, SocialWxQrcodeReqDTO.class)); return success(Base64.encode(wxQrcode)); } @GetMapping("/get-subscribe-template-list") @Operation(summary = "获得微信小程订阅模板列表") - public CommonResult> getSubscribeTemplateList() { + public CommonResult> getSubscribeTemplateList() { List template = socialClientApi.getWxaSubscribeTemplateList(UserTypeEnum.MEMBER.getValue()); - return success(BeanUtils.toBean(template, AppSocialWxSubscribeTemplateRespVO.class)); + return success(BeanUtils.toBean(template, AppSocialWxaSubscribeTemplateRespVO.class)); } } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialWxQrcodeReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialWxaQrcodeReqVO.java similarity index 97% rename from yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialWxQrcodeReqVO.java rename to yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialWxaQrcodeReqVO.java index 8927a34c9..c12bfd700 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialWxQrcodeReqVO.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialWxaQrcodeReqVO.java @@ -7,7 +7,7 @@ import lombok.Data; @Schema(description = "用户 APP - 获得获取小程序码 Request VO") @Data -public class AppSocialWxQrcodeReqVO { +public class AppSocialWxaQrcodeReqVO { /** * 页面路径不能携带参数(参数请放在scene字段里) diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialWxSubscribeTemplateRespVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialWxaSubscribeTemplateRespVO.java similarity index 95% rename from yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialWxSubscribeTemplateRespVO.java rename to yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialWxaSubscribeTemplateRespVO.java index 3fdc38b69..445122d3f 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialWxSubscribeTemplateRespVO.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialWxaSubscribeTemplateRespVO.java @@ -5,7 +5,7 @@ import lombok.Data; @Schema(description = "用户 APP - 获得小程序订阅模版 Response VO") @Data -public class AppSocialWxSubscribeTemplateRespVO { +public class AppSocialWxaSubscribeTemplateRespVO { @Schema(description = "模版编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "9Aw5ZV1j9xdWTFEkqCpZ7mIBbSC34khK55OtzUPl0rU") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialClientApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialClientApiImpl.java index b69221a0c..08fa53b84 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialClientApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialClientApiImpl.java @@ -8,6 +8,7 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.api.social.dto.*; import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; import cn.iocoder.yudao.module.system.service.social.SocialClientService; +import cn.iocoder.yudao.module.system.service.social.SocialUserService; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import me.chanjar.weixin.common.bean.WxJsapiSignature; @@ -33,7 +34,7 @@ public class SocialClientApiImpl implements SocialClientApi { @Resource private SocialClientService socialClientService; @Resource - public SocialUserApi socialUserApi; + private SocialUserService socialUserService; @Override public String getAuthorizeUrl(Integer socialType, Integer userType, String redirectUri) { @@ -68,29 +69,29 @@ public class SocialClientApiImpl implements SocialClientApi { @Override public void sendWxaSubscribeMessage(SocialWxaSubscribeMessageSendReqDTO reqDTO) { // 1.1 获得订阅模版列表 - List templateList = getWxaSubscribeTemplateList(reqDTO.getUserType()); + List templateList = socialClientService.getSubscribeTemplateList(reqDTO.getUserType()); if (CollUtil.isEmpty(templateList)) { log.warn("[sendSubscribeMessage][reqDTO({}) 发送订阅消息失败,原因:没有找到订阅模板]", reqDTO); return; } // 1.2 获得需要使用的模版 - SocialWxaSubscribeTemplateRespDTO template = findOne(templateList, item -> + TemplateInfo template = findOne(templateList, item -> ObjUtil.equal(item.getTitle(), reqDTO.getTemplateTitle())); if (template == null) { - log.warn("[sendSubscribeMessage][reqDTO({}) 发送订阅消息失败,原因:没有找到订阅模板]", reqDTO); + log.warn("[sendWxaSubscribeMessage][reqDTO({}) 发送订阅消息失败,原因:没有找到订阅模板]", reqDTO); return; } // 2. 获得社交用户 - SocialUserRespDTO socialUser = socialUserApi.getSocialUserByUserId(reqDTO.getUserType(), reqDTO.getUserId(), + SocialUserRespDTO socialUser = socialUserService.getSocialUserByUserId(reqDTO.getUserType(), reqDTO.getUserId(), SocialTypeEnum.WECHAT_MINI_APP.getType()); if (StrUtil.isBlankIfStr(socialUser.getOpenid())) { - log.warn("[sendSubscribeMessage][reqDTO({}) 发送订阅消息失败,原因:会员 openid 缺失]", reqDTO); + log.warn("[sendWxaSubscribeMessage][reqDTO({}) 发送订阅消息失败,原因:会员 openid 缺失]", reqDTO); return; } // 3. 发送订阅消息 - socialClientService.sendSubscribeMessage(reqDTO, template.getId(), socialUser.getOpenid()); + socialClientService.sendSubscribeMessage(reqDTO, template.getPriTmplId(), socialUser.getOpenid()); } } From 1eb07b83894c8d11abf33d6d7df80a42dd254987 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 2 Aug 2024 23:11:13 +0800 Subject: [PATCH 7/9] =?UTF-8?q?V2.2.0=20=E7=89=88=E6=9C=AC=E5=8F=91?= =?UTF-8?q?=E5=B8=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- yudao-dependencies/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 528769bc9..86dfebcc3 100644 --- a/pom.xml +++ b/pom.xml @@ -31,7 +31,7 @@ https://github.com/YunaiV/ruoyi-vue-pro - 2.1.0-snapshot + 2.2.0-snapshot 17 ${java.version} diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml index badfc84f9..667258250 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -14,7 +14,7 @@ https://github.com/YunaiV/ruoyi-vue-pro - 2.1.0-snapshot + 2.2.0-snapshot 1.6.0 3.3.1 From 7ba3b123131bdd792bbca9e46e7a7497895e101e Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 3 Aug 2024 18:48:06 +0800 Subject: [PATCH 8/9] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E8=84=B1=E6=95=8F=E6=94=AF=E6=8C=81=20Spring?= =?UTF-8?q?=20el=20=E8=A1=A8=E8=BE=BE=E5=BC=8F=EF=BC=8C=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E6=A0=B9=E6=8D=AE=E6=9D=83=E9=99=90=E6=8E=A7=E5=88=B6=E8=84=B1?= =?UTF-8?q?=E6=95=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../util/spring/SpringExpressionUtils.java | 7 +++---- .../base/handler/DesensitizationHandler.java | 19 +++++++++++++++++++ .../regex/annotation/EmailDesensitize.java | 6 ++++-- .../regex/annotation/RegexDesensitize.java | 6 ++++-- .../AbstractRegexDesensitizationHandler.java | 16 +++++----------- .../DefaultRegexDesensitizationHandler.java | 4 ++-- .../handler/EmailDesensitizationHandler.java | 5 ----- .../annotation/BankCardDesensitize.java | 6 ++++-- .../annotation/CarLicenseDesensitize.java | 6 ++++-- .../annotation/ChineseNameDesensitize.java | 6 ++++-- .../annotation/FixedPhoneDesensitize.java | 6 ++++-- .../slider/annotation/IdCardDesensitize.java | 6 ++++-- .../slider/annotation/MobileDesensitize.java | 6 ++++-- .../annotation/PasswordDesensitize.java | 6 ++++-- .../slider/annotation/SliderDesensitize.java | 6 ++++-- .../AbstractSliderDesensitizationHandler.java | 16 +++++----------- .../handler/BankCardDesensitization.java | 4 ++-- .../handler/CarLicenseDesensitization.java | 5 +++-- .../handler/ChineseNameDesensitization.java | 5 ----- .../DefaultDesensitizationHandler.java | 6 +----- .../handler/FixedPhoneDesensitization.java | 6 +----- .../slider/handler/IdCardDesensitization.java | 5 ----- .../slider/handler/MobileDesensitization.java | 5 ----- .../handler/PasswordDesensitization.java | 5 ----- 24 files changed, 81 insertions(+), 87 deletions(-) diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/spring/SpringExpressionUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/spring/SpringExpressionUtils.java index e9670d88d..069e89db3 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/spring/SpringExpressionUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/spring/SpringExpressionUtils.java @@ -4,9 +4,9 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.StrUtil; +import cn.hutool.extra.spring.SpringUtil; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.reflect.MethodSignature; -import org.springframework.beans.factory.BeanFactory; import org.springframework.context.expression.BeanFactoryResolver; import org.springframework.core.DefaultParameterNameDiscoverer; import org.springframework.core.ParameterNameDiscoverer; @@ -93,17 +93,16 @@ public class SpringExpressionUtils { /** * 从 Bean 工厂,解析 EL 表达式的结果 * - * @param beanFactory Bean 工程 * @param expressionString EL 表达式 * @return 执行界面 */ - public static Object parseExpression(BeanFactory beanFactory, String expressionString) { + public static Object parseExpression(String expressionString) { if (StrUtil.isBlank(expressionString)) { return null; } Expression expression = EXPRESSION_PARSER.parseExpression(expressionString); StandardEvaluationContext context = new StandardEvaluationContext(); - context.setBeanResolver(new BeanFactoryResolver(beanFactory)); + context.setBeanResolver(new BeanFactoryResolver(SpringUtil.getApplicationContext())); return expression.getValue(context); } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/base/handler/DesensitizationHandler.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/base/handler/DesensitizationHandler.java index 470a0becf..b15e35623 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/base/handler/DesensitizationHandler.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/base/handler/DesensitizationHandler.java @@ -1,5 +1,7 @@ package cn.iocoder.yudao.framework.desensitize.core.base.handler; +import cn.hutool.core.util.ReflectUtil; + import java.lang.annotation.Annotation; /** @@ -18,4 +20,21 @@ public interface DesensitizationHandler { */ String desensitize(String origin, T annotation); + /** + * 是否禁用脱敏的 Spring EL 表达式 + * + * 如果返回 true 则跳过脱敏 + * + * @param annotation 注解信息 + * @return 是否禁用脱敏的 Spring EL 表达式 + */ + default String getDisable(T annotation) { + // 约定:默认就是 enable() 属性。如果不符合,子类重写 + try { + return (String) ReflectUtil.invoke(annotation, "disable"); + } catch (Exception ex) { + return ""; + } + } + } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/annotation/EmailDesensitize.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/annotation/EmailDesensitize.java index 5485c194e..cb838de93 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/annotation/EmailDesensitize.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/annotation/EmailDesensitize.java @@ -35,8 +35,10 @@ public @interface EmailDesensitize { String replacer() default "$1****$2"; /** - * el 表达式,当执行 condition 返回 true 的时候,跳过脱敏 + * 是否禁用脱敏 + * + * 支持 Spring EL 表达式,如果返回 true 则跳过脱敏 */ - String condition() default ""; + String disable() default ""; } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/annotation/RegexDesensitize.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/annotation/RegexDesensitize.java index 9b0a3fa38..49d002a26 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/annotation/RegexDesensitize.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/annotation/RegexDesensitize.java @@ -37,8 +37,10 @@ public @interface RegexDesensitize { String replacer() default "******"; /** - * el 表达式,当执行 condition 返回 true 的时候,跳过脱敏 + * 是否禁用脱敏 + * + * 支持 Spring EL 表达式,如果返回 true 则跳过脱敏 */ - String condition() default ""; + String disable() default ""; } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/AbstractRegexDesensitizationHandler.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/AbstractRegexDesensitizationHandler.java index 11d3dc23b..6ae1a50ff 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/AbstractRegexDesensitizationHandler.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/AbstractRegexDesensitizationHandler.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.framework.desensitize.core.regex.handler; -import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.util.spring.SpringExpressionUtils; import cn.iocoder.yudao.framework.desensitize.core.base.handler.DesensitizationHandler; @@ -16,10 +15,13 @@ public abstract class AbstractRegexDesensitizationHandler @Override public String desensitize(String origin, T annotation) { - Object expressionResult = SpringExpressionUtils.parseExpression(SpringUtil.getApplicationContext(), getCondition(annotation)); - if (expressionResult instanceof Boolean && (Boolean) expressionResult) { + // 1. 判断是否禁用脱敏 + Object disable = SpringExpressionUtils.parseExpression(getDisable(annotation)); + if (Boolean.TRUE.equals(disable)) { return origin; } + + // 2. 执行脱敏 String regex = getRegex(annotation); String replacer = getReplacer(annotation); return origin.replaceAll(regex, replacer); @@ -41,12 +43,4 @@ public abstract class AbstractRegexDesensitizationHandler */ abstract String getReplacer(T annotation); - /** - * el 表达式 - * - * @param annotation 注解信息 - * @return el 表达式 - */ - abstract String getCondition(T annotation); - } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/DefaultRegexDesensitizationHandler.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/DefaultRegexDesensitizationHandler.java index 75fa8895d..debbe636f 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/DefaultRegexDesensitizationHandler.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/DefaultRegexDesensitizationHandler.java @@ -20,8 +20,8 @@ public class DefaultRegexDesensitizationHandler extends AbstractRegexDesensitiza } @Override - String getCondition(RegexDesensitize annotation) { - return annotation.condition(); + public String getDisable(RegexDesensitize annotation) { + return annotation.disable(); } } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/EmailDesensitizationHandler.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/EmailDesensitizationHandler.java index fec46d449..8d1867a64 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/EmailDesensitizationHandler.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/EmailDesensitizationHandler.java @@ -19,9 +19,4 @@ public class EmailDesensitizationHandler extends AbstractRegexDesensitizationHan return annotation.replacer(); } - @Override - String getCondition(EmailDesensitize annotation) { - return annotation.condition(); - } - } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/BankCardDesensitize.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/BankCardDesensitize.java index f512f4c9e..7f08a4395 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/BankCardDesensitize.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/BankCardDesensitize.java @@ -38,8 +38,10 @@ public @interface BankCardDesensitize { String replacer() default "*"; /** - * el 表达式,当执行 condition 返回 true 的时候,跳过脱敏 + * 是否禁用脱敏 + * + * 支持 Spring EL 表达式,如果返回 true 则跳过脱敏 */ - String condition() default ""; + String disable() default ""; } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/CarLicenseDesensitize.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/CarLicenseDesensitize.java index 93e895bf4..91dae8617 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/CarLicenseDesensitize.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/CarLicenseDesensitize.java @@ -38,8 +38,10 @@ public @interface CarLicenseDesensitize { String replacer() default "*"; /** - * el 表达式,当执行 condition 返回 true 的时候,跳过脱敏 + * 是否禁用脱敏 + * + * 支持 Spring EL 表达式,如果返回 true 则跳过脱敏 */ - String condition() default ""; + String disable() default ""; } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/ChineseNameDesensitize.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/ChineseNameDesensitize.java index 05c22dd77..866ec22ec 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/ChineseNameDesensitize.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/ChineseNameDesensitize.java @@ -38,8 +38,10 @@ public @interface ChineseNameDesensitize { String replacer() default "*"; /** - * el 表达式,当执行 condition 返回 true 的时候,跳过脱敏 + * 是否禁用脱敏 + * + * 支持 Spring EL 表达式,如果返回 true 则跳过脱敏 */ - String condition() default ""; + String disable() default ""; } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/FixedPhoneDesensitize.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/FixedPhoneDesensitize.java index ade43793b..23273b873 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/FixedPhoneDesensitize.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/FixedPhoneDesensitize.java @@ -38,8 +38,10 @@ public @interface FixedPhoneDesensitize { String replacer() default "*"; /** - * el 表达式,当执行 condition 返回 true 的时候,跳过脱敏 + * 是否禁用脱敏 + * + * 支持 Spring EL 表达式,如果返回 true 则跳过脱敏 */ - String condition() default ""; + String disable() default ""; } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/IdCardDesensitize.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/IdCardDesensitize.java index b3bbb45e8..6d97e107a 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/IdCardDesensitize.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/IdCardDesensitize.java @@ -38,8 +38,10 @@ public @interface IdCardDesensitize { String replacer() default "*"; /** - * el 表达式,当执行 condition 返回 true 的时候,跳过脱敏 + * 是否禁用脱敏 + * + * 支持 Spring EL 表达式,如果返回 true 则跳过脱敏 */ - String condition() default ""; + String disable() default ""; } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/MobileDesensitize.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/MobileDesensitize.java index 9a8c55708..c0f5211c6 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/MobileDesensitize.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/MobileDesensitize.java @@ -38,8 +38,10 @@ public @interface MobileDesensitize { String replacer() default "*"; /** - * el 表达式,当执行 condition 返回 true 的时候,跳过脱敏 + * 是否禁用脱敏 + * + * 支持 Spring EL 表达式,如果返回 true 则跳过脱敏 */ - String condition() default ""; + String disable() default ""; } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/PasswordDesensitize.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/PasswordDesensitize.java index f4c6bac98..e37c473bd 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/PasswordDesensitize.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/PasswordDesensitize.java @@ -40,8 +40,10 @@ public @interface PasswordDesensitize { String replacer() default "*"; /** - * el 表达式,当执行 condition 返回 true 的时候,跳过脱敏 + * 是否禁用脱敏 + * + * 支持 Spring EL 表达式,如果返回 true 则跳过脱敏 */ - String condition() default ""; + String disable() default ""; } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/SliderDesensitize.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/SliderDesensitize.java index 13a5becfa..ee5d867ee 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/SliderDesensitize.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/SliderDesensitize.java @@ -42,8 +42,10 @@ public @interface SliderDesensitize { int prefixKeep() default 0; /** - * el 表达式,当执行 condition 返回 true 的时候,跳过脱敏 + * 是否禁用脱敏 + * + * 支持 Spring EL 表达式,如果返回 true 则跳过脱敏 */ - String condition() default ""; + String disable() default ""; } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/AbstractSliderDesensitizationHandler.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/AbstractSliderDesensitizationHandler.java index b3b076984..66933f7cd 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/AbstractSliderDesensitizationHandler.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/AbstractSliderDesensitizationHandler.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.framework.desensitize.core.slider.handler; -import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.util.spring.SpringExpressionUtils; import cn.iocoder.yudao.framework.desensitize.core.base.handler.DesensitizationHandler; @@ -16,10 +15,13 @@ public abstract class AbstractSliderDesensitizationHandler @Override public String desensitize(String origin, T annotation) { - Object expressionResult = SpringExpressionUtils.parseExpression(SpringUtil.getApplicationContext(), getCondition(annotation)); - if (expressionResult instanceof Boolean && (Boolean) expressionResult) { + // 1. 判断是否禁用脱敏 + Object disable = SpringExpressionUtils.parseExpression(getDisable(annotation)); + if (Boolean.FALSE.equals(disable)) { return origin; } + + // 2. 执行脱敏 int prefixKeep = getPrefixKeep(annotation); int suffixKeep = getSuffixKeep(annotation); String replacer = getReplacer(annotation); @@ -81,12 +83,4 @@ public abstract class AbstractSliderDesensitizationHandler */ abstract String getReplacer(T annotation); - /** - * el 表达式 - * - * @param annotation 注解信息 - * @return el 表达式 - */ - abstract String getCondition(T annotation); - } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/BankCardDesensitization.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/BankCardDesensitization.java index c56edc78d..79797e5fe 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/BankCardDesensitization.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/BankCardDesensitization.java @@ -25,8 +25,8 @@ public class BankCardDesensitization extends AbstractSliderDesensitizationHandle } @Override - String getCondition(BankCardDesensitize annotation) { - return annotation.condition(); + public String getDisable(BankCardDesensitize annotation) { + return ""; } } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/CarLicenseDesensitization.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/CarLicenseDesensitization.java index 6829c0688..1029ee259 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/CarLicenseDesensitization.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/CarLicenseDesensitization.java @@ -8,6 +8,7 @@ import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.CarLicenseD * @author gaibu */ public class CarLicenseDesensitization extends AbstractSliderDesensitizationHandler { + @Override Integer getPrefixKeep(CarLicenseDesensitize annotation) { return annotation.prefixKeep(); @@ -24,8 +25,8 @@ public class CarLicenseDesensitization extends AbstractSliderDesensitizationHand } @Override - String getCondition(CarLicenseDesensitize annotation) { - return annotation.condition(); + public String getDisable(CarLicenseDesensitize annotation) { + return annotation.disable(); } } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/ChineseNameDesensitization.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/ChineseNameDesensitization.java index e9be53176..f71dac0e0 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/ChineseNameDesensitization.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/ChineseNameDesensitization.java @@ -24,9 +24,4 @@ public class ChineseNameDesensitization extends AbstractSliderDesensitizationHan return annotation.replacer(); } - @Override - String getCondition(ChineseNameDesensitize annotation) { - return annotation.condition(); - } - } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/DefaultDesensitizationHandler.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/DefaultDesensitizationHandler.java index 4fdadf3b7..bdb282dc0 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/DefaultDesensitizationHandler.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/DefaultDesensitizationHandler.java @@ -8,6 +8,7 @@ import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.SliderDesen * @author gaibu */ public class DefaultDesensitizationHandler extends AbstractSliderDesensitizationHandler { + @Override Integer getPrefixKeep(SliderDesensitize annotation) { return annotation.prefixKeep(); @@ -23,9 +24,4 @@ public class DefaultDesensitizationHandler extends AbstractSliderDesensitization return annotation.replacer(); } - @Override - String getCondition(SliderDesensitize annotation) { - return annotation.condition(); - } - } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/FixedPhoneDesensitization.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/FixedPhoneDesensitization.java index 6a566f4df..53412e49a 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/FixedPhoneDesensitization.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/FixedPhoneDesensitization.java @@ -8,6 +8,7 @@ import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.FixedPhoneD * @author gaibu */ public class FixedPhoneDesensitization extends AbstractSliderDesensitizationHandler { + @Override Integer getPrefixKeep(FixedPhoneDesensitize annotation) { return annotation.prefixKeep(); @@ -23,9 +24,4 @@ public class FixedPhoneDesensitization extends AbstractSliderDesensitizationHand return annotation.replacer(); } - @Override - String getCondition(FixedPhoneDesensitize annotation) { - return annotation.condition(); - } - } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/IdCardDesensitization.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/IdCardDesensitization.java index b85c9a16c..4bb89157d 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/IdCardDesensitization.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/IdCardDesensitization.java @@ -23,9 +23,4 @@ public class IdCardDesensitization extends AbstractSliderDesensitizationHandler< return annotation.replacer(); } - @Override - String getCondition(IdCardDesensitize annotation) { - return annotation.condition(); - } - } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/MobileDesensitization.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/MobileDesensitization.java index 102d07e35..5796d13cd 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/MobileDesensitization.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/MobileDesensitization.java @@ -24,9 +24,4 @@ public class MobileDesensitization extends AbstractSliderDesensitizationHandler< return annotation.replacer(); } - @Override - String getCondition(MobileDesensitize annotation) { - return annotation.condition(); - } - } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/PasswordDesensitization.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/PasswordDesensitization.java index 1ebaca2e9..8c6d1204a 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/PasswordDesensitization.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/PasswordDesensitization.java @@ -23,9 +23,4 @@ public class PasswordDesensitization extends AbstractSliderDesensitizationHandle return annotation.replacer(); } - @Override - String getCondition(PasswordDesensitize annotation) { - return annotation.condition(); - } - } From 30c6f1eb7785871f87da8aa34d68063547836d5a Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 7 Aug 2024 13:03:42 +0800 Subject: [PATCH 9/9] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E3=80=91SYSTEM=EF=BC=9A=E5=8E=BB=E9=99=A4=E9=98=BF?= =?UTF-8?q?=E9=87=8C=E4=BA=91=E7=9F=AD=E4=BF=A1=E7=9A=84=20maven=20?= =?UTF-8?q?=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-dependencies/pom.xml | 22 - .../yudao-module-system-biz/pom.xml | 13 - .../framework/sms/core/client/SmsClient.java | 2 + .../sms/core/client/impl/AliyunSmsClient.java | 375 +++++------------- .../core/client/impl/AliyunSmsClient_old.java | 349 ++++++++++++++++ .../core/client/impl/AliyunSmsClientTest.java | 184 ++++----- .../sms/core/client/impl/SmsClientTests.java | 67 +++- 7 files changed, 609 insertions(+), 403 deletions(-) create mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/AliyunSmsClient_old.java diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml index 667258250..dfa925c8d 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -69,8 +69,6 @@ 4.11.0 2.15.1 8.5.7 - 4.6.4 - 2.2.1 3.1.880 2.0.5 1.7.8 @@ -548,26 +546,6 @@ - - com.aliyun - aliyun-java-sdk-core - ${aliyun-java-sdk-core.version} - - - opentracing-api - io.opentracing - - - opentracing-util - io.opentracing - - - - - com.aliyun - aliyun-java-sdk-dysmsapi - ${aliyun-java-sdk-dysmsapi.version} - com.tencentcloudapi tencentcloud-sdk-java-sms diff --git a/yudao-module-system/yudao-module-system-biz/pom.xml b/yudao-module-system/yudao-module-system-biz/pom.xml index 082b6b470..f12ca6271 100644 --- a/yudao-module-system/yudao-module-system-biz/pom.xml +++ b/yudao-module-system/yudao-module-system-biz/pom.xml @@ -110,19 +110,6 @@ wx-java-miniapp-spring-boot-starter - - com.aliyun - aliyun-java-sdk-core - - - com.aliyun - aliyun-java-sdk-dysmsapi - - - com.tencentcloudapi - tencentcloud-sdk-java-sms - - com.xingyuv spring-boot-starter-captcha-plus diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/SmsClient.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/SmsClient.java index 46224663c..5d7b80990 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/SmsClient.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/SmsClient.java @@ -46,6 +46,8 @@ public interface SmsClient { /** * 查询指定的短信模板 * + * 如果查询失败,则返回 null 空 + * * @param apiTemplateId 短信 API 的模板编号 * @return 短信模板 */ diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/AliyunSmsClient.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/AliyunSmsClient.java index 708683b21..61f8b753e 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/AliyunSmsClient.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/AliyunSmsClient.java @@ -1,12 +1,15 @@ package cn.iocoder.yudao.module.system.framework.sms.core.client.impl; +import cn.hutool.core.date.format.FastDateFormat; import cn.hutool.core.lang.Assert; -import cn.hutool.core.util.HexUtil; +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.URLUtil; import cn.hutool.crypto.SecureUtil; import cn.hutool.crypto.digest.DigestUtil; 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; @@ -17,23 +20,13 @@ import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsSendRespD 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 lombok.extern.slf4j.Slf4j; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.net.URISyntaxException; -import java.net.URLEncoder; -import java.time.LocalDateTime; import java.util.*; +import java.util.stream.Collectors; 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; -import java.text.SimpleDateFormat; /** * 阿里短信客户端的实现类 @@ -44,6 +37,12 @@ import java.text.SimpleDateFormat; @Slf4j public class AliyunSmsClient extends AbstractSmsClient { + private static final String URL = "https://dysmsapi.aliyuncs.com"; + private static final String HOST = "dysmsapi.aliyuncs.com"; + private static final String VERSION = "2017-05-25"; + + private static final String RESPONSE_CODE_SUCCESS = "OK"; + public AliyunSmsClient(SmsChannelProperties properties) { super(properties); Assert.notEmpty(properties.getApiKey(), "apiKey 不能为空"); @@ -52,138 +51,66 @@ public class AliyunSmsClient extends AbstractSmsClient { @Override protected void doInit() { -// IClientProfile profile = DefaultProfile.getProfile(ENDPOINT, properties.getApiKey(), properties.getApiSecret()); -// client = new DefaultAcsClient(profile); } @Override public SmsSendRespDTO sendSms(Long sendLogId, String mobile, String apiTemplateId, List> templateParams) throws Throwable { - + // 1. 执行请求 + // 参考链接 https://api.aliyun.com/document/Dysmsapi/2017-05-25/SendSms TreeMap queryParam = new TreeMap<>(); queryParam.put("PhoneNumbers",mobile); - queryParam.put("SignName",properties.getSignature()); - queryParam.put("TemplateCode",apiTemplateId); - queryParam.put("TemplateParam",JsonUtils.toJsonString(MapUtils.convertMap(templateParams))); + queryParam.put("SignName", properties.getSignature()); + queryParam.put("TemplateCode", apiTemplateId); + queryParam.put("TemplateParam", JsonUtils.toJsonString(MapUtils.convertMap(templateParams))); + queryParam.put("OutId", sendLogId); + JSONObject response = request("sendSms", queryParam); - JSONObject response = sendSmsRequest(queryParam,"sendSms"); - SmsResponse smsResponse = getSmsSendResponse(response); - - return new SmsSendRespDTO().setSuccess(smsResponse.success).setApiMsg(smsResponse.data.toString()); - } - - JSONObject sendSmsRequest(TreeMap queryParam,String apiName) throws IOException, URISyntaxException { - - // ************* 步骤 1:拼接规范请求串 ************* - String url = "https://dysmsapi.aliyuncs.com"; //APP接入地址+接口访问URI - String httpMethod = "POST"; // 请求方式 - String canonicalUri = "/"; - // 请求参数,当请求的查询字符串为空时,使用空字符串作为规范化查询字符串 - StringBuilder canonicalQueryString = new StringBuilder(); - queryParam.entrySet().stream().map(entry -> percentCode(entry.getKey()) + "=" + percentCode(String.valueOf(entry.getValue()))).forEachOrdered(queryPart -> { - // 如果canonicalQueryString已经不是空的,则在查询参数前添加"&" - if (!canonicalQueryString.isEmpty()) { - canonicalQueryString.append("&"); - } - canonicalQueryString.append(queryPart); - System.out.println("canonicalQueryString=========>\n" + canonicalQueryString); - }); - - SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); - SDF.setTimeZone(new SimpleTimeZone(0, "GMT")); - String SdfTime = SDF.format(new Date()); - String randomUUID = UUID.randomUUID().toString(); - - TreeMap headers = new TreeMap<>(); - headers.put("host", "dysmsapi.aliyuncs.com"); - headers.put("x-acs-action", apiName); - headers.put("x-acs-version", "2017-05-25"); - headers.put("x-acs-date", SdfTime); - headers.put("x-acs-signature-nonce", randomUUID); -// headers.put("content-type", "application/json;charset=utf-8"); - - // 构造请求头,多个规范化消息头,按照消息头名称(小写)的字符代码顺序以升序排列后拼接在一起 - StringBuilder canonicalHeaders = new StringBuilder(); - // 已签名消息头列表,多个请求头名称(小写)按首字母升序排列并以英文分号(;)分隔 - StringBuilder signedHeadersSb = new StringBuilder(); - headers.entrySet().stream().filter(entry -> entry.getKey().toLowerCase().startsWith("x-acs-") || entry.getKey().equalsIgnoreCase("host") || entry.getKey().equalsIgnoreCase("content-type")).sorted(Map.Entry.comparingByKey()).forEach(entry -> { - String lowerKey = entry.getKey().toLowerCase(); - String value = String.valueOf(entry.getValue()).trim(); - canonicalHeaders.append(lowerKey).append(":").append(value).append("\n"); - signedHeadersSb.append(lowerKey).append(";"); - }); - String signedHeaders = signedHeadersSb.substring(0, signedHeadersSb.length() - 1); - - String body = "";//短信API为RPC接口,query parameters在uri中拼接,因此request body如果没有特殊要求,设置为空。 - String hashedRequestBody = HexUtil.encodeHexStr(DigestUtil.sha256(body)); - - - String canonicalRequest = httpMethod + "\n" + canonicalUri + "\n" + canonicalQueryString + "\n" + canonicalHeaders + "\n" + signedHeaders + "\n" + hashedRequestBody; - System.out.println("canonicalRequest=========>\n" + canonicalRequest); - - // ************* 步骤 2:拼接待签名字符串 ************* - String hashedCanonicalRequest = HexUtil.encodeHexStr(DigestUtil.sha256(canonicalRequest)); - String stringToSign = "ACS3-HMAC-SHA256" + "\n" + hashedCanonicalRequest; - - // ************* 步骤 3:计算签名 ************* - String signature = SecureUtil.hmacSha256(properties.getApiSecret()).digestHex(stringToSign); - - // ************* 步骤 4:拼接 Authorization ************* - String authorization = "ACS3-HMAC-SHA256" + " " + "Credential=" + properties.getApiKey() + ", " - + "SignedHeaders=" + signedHeaders + ", " + "Signature=" + signature; - headers.put("Authorization", authorization); - - // ************* 步骤 5:构造HttpRequest 并执行request请求,获得response ************* -// url = url + canonicalUri; - String urlWithParams = url + "?" + URLUtil.buildQuery(queryParam, null); - - HttpResponse response = HttpRequest.post(urlWithParams) - .addHeaders(headers) - .body(body) - .execute(); -// URIBuilder uriBuilder = new URIBuilder(url); -// // 添加请求参数 -// for (Map.Entry entry : queryParam.entrySet()) { -// uriBuilder.addParameter(entry.getKey(), String.valueOf(entry.getValue())); -// } -// HttpUriRequest httpRequest = new HttpPost(uriBuilder.build()); -//// HttpPost httpPost = new HttpPost(uriBuilder.build()); -//// httpRequest = httpPost; -// -// // 添加http请求头 -// for (Map.Entry entry : headers.entrySet()) { -// httpRequest.addHeader(entry.getKey(), String.valueOf(entry.getValue())); -// } -// -// // 发送请求 -// CloseableHttpClient httpClient = HttpClients.createDefault(); -// CloseableHttpResponse response = httpClient.execute(httpRequest); - System.out.println("getEntity====="+response.body()); - System.out.println("response====="+response); - - return JSONUtil.parseObj(response.body()); + // 2. 解析请求 + return new SmsSendRespDTO() + .setSuccess(Objects.equals(response.getStr("Code"), RESPONSE_CODE_SUCCESS)) + .setSerialNo(response.getStr("BizId")) + .setApiRequestId(response.getStr("RequestId")) + .setApiCode(response.getStr("Code")) + .setApiMsg(response.getStr("Message")); } @Override public List parseSmsReceiveStatus(String text) { - List statuses = JsonUtils.parseArray(text, SmsReceiveStatus.class); - return convertList(statuses, status -> new SmsReceiveRespDTO().setSuccess(status.getSuccess()) - .setErrorCode(status.getErrCode()).setErrorMsg(status.getErrMsg()) - .setMobile(status.getPhoneNumber()).setReceiveTime(status.getReportTime()) - .setSerialNo(status.getBizId()).setLogId(Long.valueOf(status.getOutId()))); + JSONArray statuses = JSONUtil.parseArray(text); + // 字段参考 + return convertList(statuses, status -> { + JSONObject statusObj = (JSONObject) status; + return new SmsReceiveRespDTO() + .setSuccess(statusObj.getBool("success")) // 是否接收成功 + .setErrorCode(statusObj.getStr("err_code")) // 状态报告编码 + .setErrorMsg(statusObj.getStr("err_msg")) // 状态报告说明 + .setMobile(statusObj.getStr("phone_number")) // 手机号 + .setReceiveTime(statusObj.getLocalDateTime("report_time", null)) // 状态报告时间 + .setSerialNo(statusObj.getStr("biz_id")) // 发送序列号 + .setLogId(statusObj.getLong("out_id")); // 用户序列号 + }); } @Override public SmsTemplateRespDTO getSmsTemplate(String apiTemplateId) throws Throwable { - + // 1. 执行请求 + // 参考链接 https://api.aliyun.com/document/Dysmsapi/2017-05-25/QuerySmsTemplate TreeMap queryParam = new TreeMap<>(); - queryParam.put("TemplateCode",apiTemplateId); - - JSONObject response = sendSmsRequest(queryParam,"QuerySmsTemplate"); - QuerySmsTemplateResponse smsTemplateResponse = getSmsTemplateResponse(response); - return new SmsTemplateRespDTO().setId(smsTemplateResponse.getTemplateCode()).setContent(smsTemplateResponse.getTemplateContent()) - .setAuditStatus(convertSmsTemplateAuditStatus(smsTemplateResponse.getTemplateStatus())).setAuditReason(smsTemplateResponse.getReason()); + queryParam.put("TemplateCode", apiTemplateId); + JSONObject response = request("QuerySmsTemplate", queryParam); + // 2.1 请求失败 + String code = response.getStr("Code"); + if (ObjectUtil.notEqual(code, RESPONSE_CODE_SUCCESS)) { + log.error("[getSmsTemplate][模版编号({}) 响应不正确({})]", apiTemplateId, response); + return null; + } + // 2.2 请求成功 + return new SmsTemplateRespDTO().setId(apiTemplateId) + .setContent(response.getStr("TemplateContent")) + .setAuditStatus(convertSmsTemplateAuditStatus(response.getInt("TemplateStatus"))) + .setAuditReason(response.getStr("Reason")); } @VisibleForTesting @@ -196,154 +123,72 @@ public class AliyunSmsClient extends AbstractSmsClient { } } - /** - * 对指定的字符串进行URL编码。 - * 使用UTF-8编码字符集对字符串进行编码,并对特定的字符进行替换,以符合URL编码规范。 + * 请求阿里云短信 * - * @param str 需要进行URL编码的字符串。 - * @return 编码后的字符串。其中,加号"+"被替换为"%20",星号"*"被替换为"%2A",波浪号"%7E"被替换为"~"。 + * @see V3 版本请求体&签名机制 + * @param apiName 请求的 API 名称 + * @param queryParams 请求参数 + * @return 请求结果 */ - public static String percentCode(String str) { - if (str == null) { - throw new IllegalArgumentException("输入字符串不可为null"); - } - try { - return URLEncoder.encode(str, "UTF-8").replace("+", "%20").replace("*", "%2A").replace("%7E", "~"); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException("UTF-8编码不被支持", e); + private JSONObject request(String apiName, TreeMap queryParams) { + // 1. 请求参数 + String queryString = queryParams.entrySet().stream() + .map(entry -> percentCode(entry.getKey()) + "=" + percentCode(String.valueOf(entry.getValue()))) + .collect(Collectors.joining("&")); + + // 2.1 请求 Header + TreeMap headers = new TreeMap<>(); + headers.put("host", HOST); + headers.put("x-acs-version", VERSION); + headers.put("x-acs-action", apiName); + headers.put("x-acs-date", FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss'Z'", TimeZone.getTimeZone("GMT")).format(new Date())); + headers.put("x-acs-signature-nonce", IdUtil.randomUUID()); + // 2.2 构建签名 Header + StringBuilder canonicalHeaders = new StringBuilder(); // 构造请求头,多个规范化消息头,按照消息头名称(小写)的字符代码顺序以升序排列后拼接在一起 + StringBuilder signedHeadersBuilder = new StringBuilder(); // 已签名消息头列表,多个请求头名称(小写)按首字母升序排列并以英文分号(;)分隔 + headers.entrySet().stream().filter(entry -> entry.getKey().toLowerCase().startsWith("x-acs-") + || entry.getKey().equalsIgnoreCase("host") + || entry.getKey().equalsIgnoreCase("content-type")) + .sorted(Map.Entry.comparingByKey()).forEach(entry -> { + String lowerKey = entry.getKey().toLowerCase(); + canonicalHeaders.append(lowerKey).append(":").append(String.valueOf(entry.getValue()).trim()).append("\n"); + signedHeadersBuilder.append(lowerKey).append(";"); + }); + String signedHeaders = signedHeadersBuilder.substring(0, signedHeadersBuilder.length() - 1); + + // 3. 请求 Body + String requestBody = ""; // 短信 API 为 RPC 接口,query parameters 在 uri 中拼接,因此 request body 如果没有特殊要求,设置为空。 + String hashedRequestBody = DigestUtil.sha256Hex(requestBody); + + // 4. 构建 Authorization 签名 + String hashedCanonicalRequest = DigestUtil.sha256Hex("POST" // httpMethod + + "\n" + "/" // canonicalUri + + "\n" + queryString + "\n" + canonicalHeaders + "\n" + signedHeaders + "\n" + hashedRequestBody); + String stringToSign = "ACS3-HMAC-SHA256" + "\n" + hashedCanonicalRequest; + String signature = SecureUtil.hmacSha256(properties.getApiSecret()).digestHex(stringToSign); // 计算签名 + headers.put("Authorization", "ACS3-HMAC-SHA256" + " " + "Credential=" + properties.getApiKey() + + ", " + "SignedHeaders=" + signedHeaders + ", " + "Signature=" + signature); + + // 5. 发起请求 + String urlWithParams = URL + "?" + URLUtil.buildQuery(queryParams, null); + try (HttpResponse response = HttpRequest.post(urlWithParams).addHeaders(headers).body(requestBody).execute()) { + return JSONUtil.parseObj(response.body()); } } - private SmsResponse getSmsSendResponse(JSONObject resJson) { - SmsResponse smsResponse = new SmsResponse(); - smsResponse.setSuccess("OK".equals(resJson.getStr("Code"))); - smsResponse.setData(resJson); -// smsResponse.setConfigId(getConfigId()); - return smsResponse; - } - - private QuerySmsTemplateResponse getSmsTemplateResponse(JSONObject resJson) { - - QuerySmsTemplateResponse smsTemplateResponse = new QuerySmsTemplateResponse(); - - smsTemplateResponse.setRequestId(resJson.getStr("RequestId")); - smsTemplateResponse.setTemplateContent(resJson.getStr("TemplateContent")); - smsTemplateResponse.setReason(resJson.getStr("Reason")); - smsTemplateResponse.setTemplateStatus(resJson.getInt("TemplateStatus")); - - return smsTemplateResponse; - } - /** - *

类名: SmsResponse - *

说明: 发送短信返回信息 + * 对指定的字符串进行 URL 编码,并对特定的字符进行替换,以符合URL编码规范 * - * @author :scholar - * 2024/07/17 0:25 - **/ - @Data - public static class SmsResponse { - - /** - * 是否成功 - */ - private boolean success; - - /** - * 厂商原返回体 - */ - private Object data; - - /** - * 配置标识名 如未配置取对应渠道名例如 Alibaba - */ - private String configId; - } - - - /** - *

类名: QuerySmsTemplateResponse - *

说明: sms模板查询返回信息 - * - * @author :scholar - * 2024/07/17 0:25 - **/ - @Data - public static class QuerySmsTemplateResponse { - private String requestId; - private String code; - private String message; - private Integer templateStatus; - private String reason; - private String templateCode; - private Integer templateType; - private String templateName; - private String templateContent; - private String createDate; - } - - /** - * 短信接收状态 - * - * 参见 文档 - * - * @author 润普源码 + * @param str 需要进行URL编码的字符串 + * @return 编码后的字符串 */ - @Data - public static class SmsReceiveStatus { - - /** - * 手机号 - */ - @JsonProperty("phone_number") - private String phoneNumber; - /** - * 发送时间 - */ - @JsonProperty("send_time") - @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT) - private LocalDateTime sendTime; - /** - * 状态报告时间 - */ - @JsonProperty("report_time") - @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT) - private LocalDateTime reportTime; - /** - * 是否接收成功 - */ - private Boolean success; - /** - * 状态报告说明 - */ - @JsonProperty("err_msg") - private String errMsg; - /** - * 状态报告编码 - */ - @JsonProperty("err_code") - private String errCode; - /** - * 发送序列号 - */ - @JsonProperty("biz_id") - private String bizId; - /** - * 用户序列号 - * - * 这里我们传递的是 SysSmsLogDO 的日志编号 - */ - @JsonProperty("out_id") - private String outId; - /** - * 短信长度,例如说 1、2、3 - * - * 140 字节算一条短信,短信长度超过 140 字节时会拆分成多条短信发送 - */ - @JsonProperty("sms_size") - private Integer smsSize; - + private static String percentCode(String str) { + Assert.notNull(str, "str 不能为空"); + return URLUtil.encode(str) + .replace("+", "%20") // 加号 "+" 被替换为 "%20" + .replace("*", "%2A") // 星号 "*" 被替换为 "%2A" + .replace("%7E", "~"); // 波浪号 "%7E" 被替换为 "~" } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/AliyunSmsClient_old.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/AliyunSmsClient_old.java new file mode 100644 index 000000000..37edc284b --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/AliyunSmsClient_old.java @@ -0,0 +1,349 @@ +package cn.iocoder.yudao.module.system.framework.sms.core.client.impl; + +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.HexUtil; +import cn.hutool.core.util.URLUtil; +import cn.hutool.crypto.SecureUtil; +import cn.hutool.crypto.digest.DigestUtil; +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpResponse; +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.MapUtils; +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.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 lombok.extern.slf4j.Slf4j; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URISyntaxException; +import java.net.URLEncoder; +import java.text.SimpleDateFormat; +import java.time.LocalDateTime; +import java.util.*; + +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; + +/** + * 阿里短信客户端的实现类 + * + * @author zzf + * @since 2021/1/25 14:17 + */ +@Slf4j +public class AliyunSmsClient_old extends AbstractSmsClient { + + public AliyunSmsClient_old(SmsChannelProperties properties) { + super(properties); + Assert.notEmpty(properties.getApiKey(), "apiKey 不能为空"); + Assert.notEmpty(properties.getApiSecret(), "apiSecret 不能为空"); + } + + @Override + protected void doInit() { +// IClientProfile profile = DefaultProfile.getProfile(ENDPOINT, properties.getApiKey(), properties.getApiSecret()); +// client = new DefaultAcsClient(profile); + } + + @Override + public SmsSendRespDTO sendSms(Long sendLogId, String mobile, String apiTemplateId, + List> templateParams) throws Throwable { + + TreeMap queryParam = new TreeMap<>(); + queryParam.put("PhoneNumbers",mobile); + queryParam.put("SignName",properties.getSignature()); + queryParam.put("TemplateCode",apiTemplateId); + queryParam.put("TemplateParam",JsonUtils.toJsonString(MapUtils.convertMap(templateParams))); + + JSONObject response = sendSmsRequest(queryParam,"sendSms"); + SmsResponse smsResponse = getSmsSendResponse(response); + + return new SmsSendRespDTO().setSuccess(smsResponse.success).setApiMsg(smsResponse.data.toString()); + } + + JSONObject sendSmsRequest(TreeMap queryParam,String apiName) throws IOException, URISyntaxException { + + // ************* 步骤 1:拼接规范请求串 ************* + String url = "https://dysmsapi.aliyuncs.com"; //APP接入地址+接口访问URI + String httpMethod = "POST"; // 请求方式 + String canonicalUri = "/"; + // 请求参数,当请求的查询字符串为空时,使用空字符串作为规范化查询字符串 + StringBuilder canonicalQueryString = new StringBuilder(); + queryParam.entrySet().stream().map(entry -> percentCode(entry.getKey()) + "=" + percentCode(String.valueOf(entry.getValue()))).forEachOrdered(queryPart -> { + // 如果canonicalQueryString已经不是空的,则在查询参数前添加"&" + if (!canonicalQueryString.isEmpty()) { + canonicalQueryString.append("&"); + } + canonicalQueryString.append(queryPart); + System.out.println("canonicalQueryString=========>\n" + canonicalQueryString); + }); + + SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); + SDF.setTimeZone(new SimpleTimeZone(0, "GMT")); + String SdfTime = SDF.format(new Date()); + String randomUUID = UUID.randomUUID().toString(); + + TreeMap headers = new TreeMap<>(); + headers.put("host", "dysmsapi.aliyuncs.com"); + headers.put("x-acs-action", apiName); + headers.put("x-acs-version", "2017-05-25"); + headers.put("x-acs-date", SdfTime); + headers.put("x-acs-signature-nonce", randomUUID); +// headers.put("content-type", "application/json;charset=utf-8"); + + // 构造请求头,多个规范化消息头,按照消息头名称(小写)的字符代码顺序以升序排列后拼接在一起 + StringBuilder canonicalHeaders = new StringBuilder(); + // 已签名消息头列表,多个请求头名称(小写)按首字母升序排列并以英文分号(;)分隔 + StringBuilder signedHeadersSb = new StringBuilder(); + headers.entrySet().stream().filter(entry -> entry.getKey().toLowerCase().startsWith("x-acs-") || entry.getKey().equalsIgnoreCase("host") || entry.getKey().equalsIgnoreCase("content-type")).sorted(Map.Entry.comparingByKey()).forEach(entry -> { + String lowerKey = entry.getKey().toLowerCase(); + String value = String.valueOf(entry.getValue()).trim(); + canonicalHeaders.append(lowerKey).append(":").append(value).append("\n"); + signedHeadersSb.append(lowerKey).append(";"); + }); + String signedHeaders = signedHeadersSb.substring(0, signedHeadersSb.length() - 1); + + String body = "";//短信API为RPC接口,query parameters在uri中拼接,因此request body如果没有特殊要求,设置为空。 + String hashedRequestBody = HexUtil.encodeHexStr(DigestUtil.sha256(body)); + + + String canonicalRequest = httpMethod + "\n" + canonicalUri + "\n" + canonicalQueryString + "\n" + canonicalHeaders + "\n" + signedHeaders + "\n" + hashedRequestBody; + System.out.println("canonicalRequest=========>\n" + canonicalRequest); + + // ************* 步骤 2:拼接待签名字符串 ************* + String hashedCanonicalRequest = HexUtil.encodeHexStr(DigestUtil.sha256(canonicalRequest)); + String stringToSign = "ACS3-HMAC-SHA256" + "\n" + hashedCanonicalRequest; + + // ************* 步骤 3:计算签名 ************* + String signature = SecureUtil.hmacSha256(properties.getApiSecret()).digestHex(stringToSign); + + // ************* 步骤 4:拼接 Authorization ************* + String authorization = "ACS3-HMAC-SHA256" + " " + "Credential=" + properties.getApiKey() + ", " + + "SignedHeaders=" + signedHeaders + ", " + "Signature=" + signature; + headers.put("Authorization", authorization); + + // ************* 步骤 5:构造HttpRequest 并执行request请求,获得response ************* +// url = url + canonicalUri; + String urlWithParams = url + "?" + URLUtil.buildQuery(queryParam, null); + + HttpResponse response = HttpRequest.post(urlWithParams) + .addHeaders(headers) + .body(body) + .execute(); +// URIBuilder uriBuilder = new URIBuilder(url); +// // 添加请求参数 +// for (Map.Entry entry : queryParam.entrySet()) { +// uriBuilder.addParameter(entry.getKey(), String.valueOf(entry.getValue())); +// } +// HttpUriRequest httpRequest = new HttpPost(uriBuilder.build()); +//// HttpPost httpPost = new HttpPost(uriBuilder.build()); +//// httpRequest = httpPost; +// +// // 添加http请求头 +// for (Map.Entry entry : headers.entrySet()) { +// httpRequest.addHeader(entry.getKey(), String.valueOf(entry.getValue())); +// } +// +// // 发送请求 +// CloseableHttpClient httpClient = HttpClients.createDefault(); +// CloseableHttpResponse response = httpClient.execute(httpRequest); + System.out.println("getEntity====="+response.body()); + System.out.println("response====="+response); + + return JSONUtil.parseObj(response.body()); + } + + @Override + public List parseSmsReceiveStatus(String text) { + List statuses = JsonUtils.parseArray(text, SmsReceiveStatus.class); + return convertList(statuses, status -> new SmsReceiveRespDTO().setSuccess(status.getSuccess()) + .setErrorCode(status.getErrCode()).setErrorMsg(status.getErrMsg()) + .setMobile(status.getPhoneNumber()).setReceiveTime(status.getReportTime()) + .setSerialNo(status.getBizId()).setLogId(Long.valueOf(status.getOutId()))); + } + + @Override + public SmsTemplateRespDTO getSmsTemplate(String apiTemplateId) throws Throwable { + + TreeMap queryParam = new TreeMap<>(); + queryParam.put("TemplateCode",apiTemplateId); + + JSONObject response = sendSmsRequest(queryParam,"QuerySmsTemplate"); + QuerySmsTemplateResponse smsTemplateResponse = getSmsTemplateResponse(response); + return new SmsTemplateRespDTO().setId(smsTemplateResponse.getTemplateCode()).setContent(smsTemplateResponse.getTemplateContent()) + .setAuditStatus(convertSmsTemplateAuditStatus(smsTemplateResponse.getTemplateStatus())).setAuditReason(smsTemplateResponse.getReason()); + + } + + @VisibleForTesting + Integer convertSmsTemplateAuditStatus(Integer templateStatus) { + switch (templateStatus) { + case 0: return SmsTemplateAuditStatusEnum.CHECKING.getStatus(); + case 1: return SmsTemplateAuditStatusEnum.SUCCESS.getStatus(); + case 2: return SmsTemplateAuditStatusEnum.FAIL.getStatus(); + default: throw new IllegalArgumentException(String.format("未知审核状态(%d)", templateStatus)); + } + } + + + /** + * 对指定的字符串进行URL编码。 + * 使用UTF-8编码字符集对字符串进行编码,并对特定的字符进行替换,以符合URL编码规范。 + * + * @param str 需要进行URL编码的字符串。 + * @return 编码后的字符串。其中,加号"+"被替换为"%20",星号"*"被替换为"%2A",波浪号"%7E"被替换为"~"。 + */ + public static String percentCode(String str) { + if (str == null) { + throw new IllegalArgumentException("输入字符串不可为null"); + } + try { + return URLEncoder.encode(str, "UTF-8").replace("+", "%20").replace("*", "%2A").replace("%7E", "~"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException("UTF-8编码不被支持", e); + } + } + + private SmsResponse getSmsSendResponse(JSONObject resJson) { + SmsResponse smsResponse = new SmsResponse(); + smsResponse.setSuccess("OK".equals(resJson.getStr("Code"))); + smsResponse.setData(resJson); +// smsResponse.setConfigId(getConfigId()); + return smsResponse; + } + + private QuerySmsTemplateResponse getSmsTemplateResponse(JSONObject resJson) { + + QuerySmsTemplateResponse smsTemplateResponse = new QuerySmsTemplateResponse(); + + smsTemplateResponse.setRequestId(resJson.getStr("RequestId")); + smsTemplateResponse.setTemplateContent(resJson.getStr("TemplateContent")); + smsTemplateResponse.setReason(resJson.getStr("Reason")); + smsTemplateResponse.setTemplateStatus(resJson.getInt("TemplateStatus")); + + return smsTemplateResponse; + } + + /** + *

类名: SmsResponse + *

说明: 发送短信返回信息 + * + * @author :scholar + * 2024/07/17 0:25 + **/ + @Data + public static class SmsResponse { + + /** + * 是否成功 + */ + private boolean success; + + /** + * 厂商原返回体 + */ + private Object data; + + /** + * 配置标识名 如未配置取对应渠道名例如 Alibaba + */ + private String configId; + } + + + /** + *

类名: QuerySmsTemplateResponse + *

说明: sms模板查询返回信息 + * + * @author :scholar + * 2024/07/17 0:25 + **/ + @Data + public static class QuerySmsTemplateResponse { + private String requestId; + private String code; + private String message; + private Integer templateStatus; + private String reason; + private String templateCode; + private Integer templateType; + private String templateName; + private String templateContent; + private String createDate; + } + + /** + * 短信接收状态 + * + * 参见 文档 + * + * @author 润普源码 + */ + @Data + public static class SmsReceiveStatus { + + /** + * 手机号 + */ + @JsonProperty("phone_number") + private String phoneNumber; + /** + * 发送时间 + */ + @JsonProperty("send_time") + @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT) + private LocalDateTime sendTime; + /** + * 状态报告时间 + */ + @JsonProperty("report_time") + @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT) + private LocalDateTime reportTime; + /** + * 是否接收成功 + */ + private Boolean success; + /** + * 状态报告说明 + */ + @JsonProperty("err_msg") + private String errMsg; + /** + * 状态报告编码 + */ + @JsonProperty("err_code") + private String errCode; + /** + * 发送序列号 + */ + @JsonProperty("biz_id") + private String bizId; + /** + * 用户序列号 + * + * 这里我们传递的是 SysSmsLogDO 的日志编号 + */ + @JsonProperty("out_id") + private String outId; + /** + * 短信长度,例如说 1、2、3 + * + * 140 字节算一条短信,短信长度超过 140 字节时会拆分成多条短信发送 + */ + @JsonProperty("sms_size") + private Integer smsSize; + + } + +} diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/AliyunSmsClientTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/AliyunSmsClientTest.java index ac26d139b..bc5a47140 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/AliyunSmsClientTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/AliyunSmsClientTest.java @@ -1,36 +1,21 @@ 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.util.collection.MapUtils; 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.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.aliyuncs.IAcsClient; -import com.aliyuncs.dysmsapi.model.v20170525.QuerySmsTemplateRequest; -import com.aliyuncs.dysmsapi.model.v20170525.QuerySmsTemplateResponse; -import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest; -import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse; -import com.google.common.collect.Lists; import org.junit.jupiter.api.Test; -import org.mockito.ArgumentMatcher; import org.mockito.InjectMocks; -import org.mockito.Mock; import java.time.LocalDateTime; 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.randomString; import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.argThat; -import static org.mockito.Mockito.when; +// TODO 芋艿:需要优化 /** - * {@link AliyunSmsClient} 的单元测试 + * {@link cn.iocoder.yudao.module.system.framework.sms.core.client.impl.AliyunSmsClient_old} 的单元测试 * * @author 芋道源码 */ @@ -44,9 +29,6 @@ public class AliyunSmsClientTest extends BaseMockitoUnitTest { @InjectMocks private final AliyunSmsClient smsClient = new AliyunSmsClient(properties); - @Mock - private IAcsClient client; - @Test public void testDoInit() { // 准备参数 @@ -54,68 +36,66 @@ public class AliyunSmsClientTest extends BaseMockitoUnitTest { // 调用 smsClient.doInit(); - // 断言 - assertNotSame(client, ReflectUtil.getFieldValue(smsClient, "acsClient")); } - @Test - public void tesSendSms_success() throws Throwable { - // 准备参数 - Long sendLogId = randomLongId(); - String mobile = randomString(); - String apiTemplateId = randomString(); - List> templateParams = Lists.newArrayList( - new KeyValue<>("code", 1234), new KeyValue<>("op", "login")); - // mock 方法 - SendSmsResponse response = randomPojo(SendSmsResponse.class, o -> o.setCode("OK")); - when(client.getAcsResponse(argThat((ArgumentMatcher) acsRequest -> { - assertEquals(mobile, acsRequest.getPhoneNumbers()); - assertEquals(properties.getSignature(), acsRequest.getSignName()); - assertEquals(apiTemplateId, acsRequest.getTemplateCode()); - assertEquals(toJsonString(MapUtils.convertMap(templateParams)), acsRequest.getTemplateParam()); - assertEquals(sendLogId.toString(), acsRequest.getOutId()); - return true; - }))).thenReturn(response); +// @Test +// public void tesSendSms_success() throws Throwable { +// // 准备参数 +// Long sendLogId = randomLongId(); +// String mobile = randomString(); +// String apiTemplateId = randomString(); +// List> templateParams = Lists.newArrayList( +// new KeyValue<>("code", 1234), new KeyValue<>("op", "login")); +// // mock 方法 +// SendSmsResponse response = randomPojo(SendSmsResponse.class, o -> o.setCode("OK")); +// when(client.getAcsResponse(argThat((ArgumentMatcher) acsRequest -> { +// assertEquals(mobile, acsRequest.getPhoneNumbers()); +// assertEquals(properties.getSignature(), acsRequest.getSignName()); +// assertEquals(apiTemplateId, acsRequest.getTemplateCode()); +// assertEquals(toJsonString(MapUtils.convertMap(templateParams)), acsRequest.getTemplateParam()); +// assertEquals(sendLogId.toString(), acsRequest.getOutId()); +// return true; +// }))).thenReturn(response); +// +// // 调用 +// SmsSendRespDTO result = smsClient.sendSms(sendLogId, mobile, +// apiTemplateId, templateParams); +// // 断言 +// assertTrue(result.getSuccess()); +// assertEquals(response.getRequestId(), result.getApiRequestId()); +// assertEquals(response.getCode(), result.getApiCode()); +// assertEquals(response.getMessage(), result.getApiMsg()); +// assertEquals(response.getBizId(), result.getSerialNo()); +// } - // 调用 - SmsSendRespDTO result = smsClient.sendSms(sendLogId, mobile, - apiTemplateId, templateParams); - // 断言 - assertTrue(result.getSuccess()); - assertEquals(response.getRequestId(), result.getApiRequestId()); - assertEquals(response.getCode(), result.getApiCode()); - assertEquals(response.getMessage(), result.getApiMsg()); - assertEquals(response.getBizId(), result.getSerialNo()); - } - - @Test - public void tesSendSms_fail() throws Throwable { - // 准备参数 - Long sendLogId = randomLongId(); - String mobile = randomString(); - String apiTemplateId = randomString(); - List> templateParams = Lists.newArrayList( - new KeyValue<>("code", 1234), new KeyValue<>("op", "login")); - // mock 方法 - SendSmsResponse response = randomPojo(SendSmsResponse.class, o -> o.setCode("ERROR")); - when(client.getAcsResponse(argThat((ArgumentMatcher) acsRequest -> { - assertEquals(mobile, acsRequest.getPhoneNumbers()); - assertEquals(properties.getSignature(), acsRequest.getSignName()); - assertEquals(apiTemplateId, acsRequest.getTemplateCode()); - assertEquals(toJsonString(MapUtils.convertMap(templateParams)), acsRequest.getTemplateParam()); - assertEquals(sendLogId.toString(), acsRequest.getOutId()); - return true; - }))).thenReturn(response); - - // 调用 - SmsSendRespDTO result = smsClient.sendSms(sendLogId, mobile, apiTemplateId, templateParams); - // 断言 - assertFalse(result.getSuccess()); - assertEquals(response.getRequestId(), result.getApiRequestId()); - assertEquals(response.getCode(), result.getApiCode()); - assertEquals(response.getMessage(), result.getApiMsg()); - assertEquals(response.getBizId(), result.getSerialNo()); - } +// @Test +// public void tesSendSms_fail() throws Throwable { +// // 准备参数 +// Long sendLogId = randomLongId(); +// String mobile = randomString(); +// String apiTemplateId = randomString(); +// List> templateParams = Lists.newArrayList( +// new KeyValue<>("code", 1234), new KeyValue<>("op", "login")); +// // mock 方法 +// SendSmsResponse response = randomPojo(SendSmsResponse.class, o -> o.setCode("ERROR")); +// when(client.getAcsResponse(argThat((ArgumentMatcher) acsRequest -> { +// assertEquals(mobile, acsRequest.getPhoneNumbers()); +// assertEquals(properties.getSignature(), acsRequest.getSignName()); +// assertEquals(apiTemplateId, acsRequest.getTemplateCode()); +// assertEquals(toJsonString(MapUtils.convertMap(templateParams)), acsRequest.getTemplateParam()); +// assertEquals(sendLogId.toString(), acsRequest.getOutId()); +// return true; +// }))).thenReturn(response); +// +// // 调用 +// SmsSendRespDTO result = smsClient.sendSms(sendLogId, mobile, apiTemplateId, templateParams); +// // 断言 +// assertFalse(result.getSuccess()); +// assertEquals(response.getRequestId(), result.getApiRequestId()); +// assertEquals(response.getCode(), result.getApiCode()); +// assertEquals(response.getMessage(), result.getApiMsg()); +// assertEquals(response.getBizId(), result.getSerialNo()); +// } @Test public void testParseSmsReceiveStatus() { @@ -149,28 +129,28 @@ public class AliyunSmsClientTest extends BaseMockitoUnitTest { assertEquals(67890L, statuses.get(0).getLogId()); } - @Test - public void testGetSmsTemplate() throws Throwable { - // 准备参数 - String apiTemplateId = randomString(); - // mock 方法 - QuerySmsTemplateResponse response = randomPojo(QuerySmsTemplateResponse.class, o -> { - o.setCode("OK"); - o.setTemplateStatus(1); // 设置模板通过 - }); - when(client.getAcsResponse(argThat((ArgumentMatcher) acsRequest -> { - assertEquals(apiTemplateId, acsRequest.getTemplateCode()); - return true; - }))).thenReturn(response); - - // 调用 - SmsTemplateRespDTO result = smsClient.getSmsTemplate(apiTemplateId); - // 断言 - assertEquals(response.getTemplateCode(), result.getId()); - assertEquals(response.getTemplateContent(), result.getContent()); - assertEquals(SmsTemplateAuditStatusEnum.SUCCESS.getStatus(), result.getAuditStatus()); - assertEquals(response.getReason(), result.getAuditReason()); - } +// @Test +// public void testGetSmsTemplate() throws Throwable { +// // 准备参数 +// String apiTemplateId = randomString(); +// // mock 方法 +// QuerySmsTemplateResponse response = randomPojo(QuerySmsTemplateResponse.class, o -> { +// o.setCode("OK"); +// o.setTemplateStatus(1); // 设置模板通过 +// }); +// when(client.getAcsResponse(argThat((ArgumentMatcher) acsRequest -> { +// assertEquals(apiTemplateId, acsRequest.getTemplateCode()); +// return true; +// }))).thenReturn(response); +// +// // 调用 +// SmsTemplateRespDTO result = smsClient.getSmsTemplate(apiTemplateId); +// // 断言 +// assertEquals(response.getTemplateCode(), result.getId()); +// assertEquals(response.getTemplateContent(), result.getContent()); +// assertEquals(SmsTemplateAuditStatusEnum.SUCCESS.getStatus(), result.getAuditStatus()); +// assertEquals(response.getReason(), result.getAuditReason()); +// } @Test public void testConvertSmsTemplateAuditStatus() { diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/SmsClientTests.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/SmsClientTests.java index 677bf986e..13848d33c 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/SmsClientTests.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/SmsClientTests.java @@ -1,7 +1,9 @@ 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; @@ -17,7 +19,7 @@ public class SmsClientTests { @Test @Disabled - public void testHuaweiSmsClient() throws Throwable { + public void testHuaweiSmsClient_sendSms() throws Throwable { SmsChannelProperties properties = new SmsChannelProperties() .setApiKey("123") .setApiSecret("456"); @@ -33,4 +35,67 @@ public class SmsClientTests { 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"); + AliyunSmsClient client = new AliyunSmsClient(properties); + // 准备参数 + Long sendLogId = System.currentTimeMillis(); + String mobile = "17321315478"; + 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 statuses = client.parseSmsReceiveStatus(text); + // 打印结果 + System.out.println(statuses); + } + }