|
@@ -18,6 +18,13 @@ import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsTemplateR
|
|
|
import cn.iocoder.yudao.module.system.framework.sms.core.enums.SmsTemplateAuditStatusEnum;
|
|
|
import cn.iocoder.yudao.module.system.framework.sms.core.property.SmsChannelProperties;
|
|
|
import com.google.common.annotations.VisibleForTesting;
|
|
|
+import com.tencentcloudapi.common.Credential;
|
|
|
+import com.tencentcloudapi.common.profile.ClientProfile;
|
|
|
+import com.tencentcloudapi.common.profile.HttpProfile;
|
|
|
+import com.tencentcloudapi.sms.v20210111.SmsClient;
|
|
|
+import com.tencentcloudapi.sms.v20210111.models.SendSmsRequest;
|
|
|
+import com.tencentcloudapi.sms.v20210111.models.SendSmsResponse;
|
|
|
+import com.tencentcloudapi.sms.v20210111.models.SendStatus;
|
|
|
|
|
|
import java.nio.charset.StandardCharsets;
|
|
|
import java.util.*;
|
|
@@ -33,16 +40,14 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.
|
|
|
* @author shiwp
|
|
|
*/
|
|
|
public class TencentSmsClient extends AbstractSmsClient {
|
|
|
-
|
|
|
- private static final String HOST = "sms.tencentcloudapi.com";
|
|
|
- private static final String VERSION = "2021-01-11";
|
|
|
- private static final String REGION = "ap-guangzhou";
|
|
|
-
|
|
|
+
|
|
|
/**
|
|
|
* 调用成功 code
|
|
|
*/
|
|
|
public static final String API_CODE_SUCCESS = "Ok";
|
|
|
-
|
|
|
+ private static final String HOST = "sms.tencentcloudapi.com";
|
|
|
+ private static final String VERSION = "2021-01-11";
|
|
|
+ private static final String REGION = "ap-guangzhou";
|
|
|
/**
|
|
|
* 是否国际/港澳台短信:
|
|
|
*
|
|
@@ -72,42 +77,106 @@ public class TencentSmsClient extends AbstractSmsClient {
|
|
|
String[] keys = combineKey.trim().split(" ");
|
|
|
Assert.isTrue(keys.length == 2, "腾讯云短信 apiKey 配置格式错误,请配置 为[secretId sdkAppId]");
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
+ private static byte[] hmac256(byte[] key, String msg) {
|
|
|
+ return DigestUtil.hmac(HmacAlgorithm.HmacSHA256, key).digest(msg);
|
|
|
+ }
|
|
|
+
|
|
|
private String getSdkAppId() {
|
|
|
return StrUtil.subAfter(properties.getApiKey(), " ", true);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
private String getApiKey() {
|
|
|
return StrUtil.subBefore(properties.getApiKey(), " ", true);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
+ // @Override
|
|
|
+// public SmsSendRespDTO sendSms(Long sendLogId, String mobile,
|
|
|
+// String apiTemplateId, List<KeyValue<String, Object>> templateParams) throws
|
|
|
+// Throwable {
|
|
|
+// // 1. 执行请求
|
|
|
+// // 参考链接 https://cloud.tencent.com/document/product/382/55981
|
|
|
+// TreeMap<String, Object> body = new TreeMap<>();
|
|
|
+// body.put("PhoneNumberSet", new String[]{mobile});
|
|
|
+// body.put("SmsSdkAppId", getSdkAppId());
|
|
|
+// body.put("SignName", properties.getSignature());
|
|
|
+// body.put("TemplateId", apiTemplateId);
|
|
|
+// body.put("TemplateParamSet", ArrayUtils.toArray(templateParams, param -> String.valueOf(param.getValue())));
|
|
|
+// JSONObject response = request("SendSms", body);
|
|
|
+//
|
|
|
+// // 2. 解析请求
|
|
|
+// JSONObject responseResult = response.getJSONObject("Response");
|
|
|
+// JSONObject error = responseResult.getJSONObject("Error");
|
|
|
+// if (error != null) {
|
|
|
+// return new SmsSendRespDTO().setSuccess(false)
|
|
|
+// .setApiRequestId(responseResult.getStr("RequestId"))
|
|
|
+// .setApiCode(error.getStr("Code"))
|
|
|
+// .setApiMsg(error.getStr("Message"));
|
|
|
+// }
|
|
|
+// JSONObject sendResult = responseResult.getJSONArray("SendStatusSet").getJSONObject(0);
|
|
|
+// return new SmsSendRespDTO().setSuccess(Objects.equals(API_CODE_SUCCESS, sendResult.getStr("Code")))
|
|
|
+// .setApiRequestId(responseResult.getStr("RequestId"))
|
|
|
+// .setSerialNo(sendResult.getStr("SerialNo"))
|
|
|
+// .setApiMsg(sendResult.getStr("Message"));
|
|
|
+// }
|
|
|
@Override
|
|
|
public SmsSendRespDTO sendSms(Long sendLogId, String mobile,
|
|
|
String apiTemplateId, List<KeyValue<String, Object>> templateParams) throws Throwable {
|
|
|
// 1. 执行请求
|
|
|
- // 参考链接 https://cloud.tencent.com/document/product/382/55981
|
|
|
- TreeMap<String, Object> body = new TreeMap<>();
|
|
|
- body.put("PhoneNumberSet", new String[]{mobile});
|
|
|
- body.put("SmsSdkAppId", getSdkAppId());
|
|
|
- body.put("SignName", properties.getSignature());
|
|
|
- body.put("TemplateId", apiTemplateId);
|
|
|
- body.put("TemplateParamSet", ArrayUtils.toArray(templateParams, param -> String.valueOf(param.getValue())));
|
|
|
- JSONObject response = request("SendSms", body);
|
|
|
-
|
|
|
- // 2. 解析请求
|
|
|
- JSONObject responseResult = response.getJSONObject("Response");
|
|
|
- JSONObject error = responseResult.getJSONObject("Error");
|
|
|
- if (error != null) {
|
|
|
- return new SmsSendRespDTO().setSuccess(false)
|
|
|
- .setApiRequestId(responseResult.getStr("RequestId"))
|
|
|
- .setApiCode(error.getStr("Code"))
|
|
|
- .setApiMsg(error.getStr("Message"));
|
|
|
+ Credential cred = new Credential(
|
|
|
+ getApiKey(),
|
|
|
+ properties.getApiSecret()
|
|
|
+ );
|
|
|
+
|
|
|
+ // 实例化一个http选项,可选的,没有特殊需求可以跳过
|
|
|
+ HttpProfile httpProfile = new HttpProfile();
|
|
|
+ httpProfile.setEndpoint("sms.tencentcloudapi.com");
|
|
|
+
|
|
|
+ // 实例化一个client选项,可选的,没有特殊需求可以跳过
|
|
|
+ ClientProfile clientProfile = new ClientProfile();
|
|
|
+ clientProfile.setHttpProfile(httpProfile);
|
|
|
+
|
|
|
+ // 实例化要请求产品的client对象,clientProfile是可选的
|
|
|
+ SmsClient client = new SmsClient(cred, "ap-guangzhou", clientProfile);
|
|
|
+
|
|
|
+ // 实例化一个请求对象,每个接口都会对应一个request对象
|
|
|
+ SendSmsRequest req = new SendSmsRequest();
|
|
|
+
|
|
|
+ // 设置请求参数
|
|
|
+ String[] phoneNumberSet = {"+86" + mobile};
|
|
|
+ req.setPhoneNumberSet(phoneNumberSet);
|
|
|
+
|
|
|
+ // 短信应用ID
|
|
|
+ req.setSmsSdkAppId(getSdkAppId());
|
|
|
+
|
|
|
+ // 短信签名内容
|
|
|
+ req.setSignName(properties.getSignature());
|
|
|
+
|
|
|
+ // 模板ID
|
|
|
+ req.setTemplateId(apiTemplateId);
|
|
|
+
|
|
|
+ // 模板参数
|
|
|
+ req.setTemplateParamSet(ArrayUtils.toArray(templateParams, param -> String.valueOf(param.getValue())));
|
|
|
+
|
|
|
+ // 返回的resp是一个SendSmsResponse的实例,与请求对象对应
|
|
|
+ SendSmsResponse resp = client.SendSms(req);
|
|
|
+ SmsSendRespDTO smsSendRespDTO = new SmsSendRespDTO();
|
|
|
+ SendStatus[] status = resp.getSendStatusSet();
|
|
|
+ if (status.length > 0) {
|
|
|
+ SendStatus firstStatus = status[0];
|
|
|
+ // 使用firstStatus做后续处理
|
|
|
+ smsSendRespDTO.setSuccess(Objects.equals(API_CODE_SUCCESS, firstStatus.getCode()));
|
|
|
+ smsSendRespDTO.setApiRequestId(resp.getRequestId());
|
|
|
+ smsSendRespDTO.setSerialNo(firstStatus.getSerialNo());
|
|
|
+ smsSendRespDTO.setApiCode(firstStatus.getIsoCode());
|
|
|
+ smsSendRespDTO.setApiMsg(firstStatus.getMessage());
|
|
|
+
|
|
|
+ return smsSendRespDTO;
|
|
|
+ } else {
|
|
|
+ // 处理数组为空的情况,避免ArrayIndexOutOfBoundsException
|
|
|
+ return null;
|
|
|
}
|
|
|
- JSONObject sendResult = responseResult.getJSONArray("SendStatusSet").getJSONObject(0);
|
|
|
- return new SmsSendRespDTO().setSuccess(Objects.equals(API_CODE_SUCCESS, sendResult.getStr("Code")))
|
|
|
- .setApiRequestId(responseResult.getStr("RequestId"))
|
|
|
- .setSerialNo(sendResult.getStr("SerialNo"))
|
|
|
- .setApiMsg(sendResult.getStr("Message"));
|
|
|
+
|
|
|
}
|
|
|
|
|
|
@Override
|
|
@@ -194,8 +263,4 @@ public class TencentSmsClient extends AbstractSmsClient {
|
|
|
return JSONUtil.parseObj(responseBody);
|
|
|
}
|
|
|
|
|
|
- private static byte[] hmac256(byte[] key, String msg) {
|
|
|
- return DigestUtil.hmac(HmacAlgorithm.HmacSHA256, key).digest(msg);
|
|
|
- }
|
|
|
-
|
|
|
}
|