Pre Merge pull request !365 from PeterChina/5.X-sms4j

This commit is contained in:
PeterChina 2023-06-08 10:44:32 +00:00 committed by Gitee
commit e1fa497733
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
11 changed files with 129 additions and 261 deletions

15
pom.xml
View File

@ -48,8 +48,7 @@
<!-- OSS 配置 --> <!-- OSS 配置 -->
<aws-java-sdk-s3.version>1.12.400</aws-java-sdk-s3.version> <aws-java-sdk-s3.version>1.12.400</aws-java-sdk-s3.version>
<!-- SMS 配置 --> <!-- SMS 配置 -->
<aliyun.sms.version>2.0.23</aliyun.sms.version> <sms4j.sms.version>2.1.0</sms4j.sms.version>
<tencent.sms.version>3.1.687</tencent.sms.version>
<!-- 插件版本 --> <!-- 插件版本 -->
<maven-jar-plugin.version>3.2.2</maven-jar-plugin.version> <maven-jar-plugin.version>3.2.2</maven-jar-plugin.version>
@ -236,15 +235,9 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.aliyun</groupId> <groupId>org.dromara.sms4j</groupId>
<artifactId>dysmsapi20170525</artifactId> <artifactId>sms4j-autoimmit</artifactId>
<version>${aliyun.sms.version}</version> <version>${sms4j.sms.version}</version>
</dependency>
<dependency>
<groupId>com.tencentcloudapi</groupId>
<artifactId>tencentcloud-sdk-java-sms</artifactId>
<version>${tencent.sms.version}</version>
</dependency> </dependency>
<dependency> <dependency>

View File

@ -160,12 +160,22 @@ mail:
--- # sms 短信 --- # sms 短信
sms: sms:
# 是否启用短信
enabled: false enabled: false
# 阿里云 dysmsapi.aliyuncs.com # SupplierType中枚举
# 腾讯云 sms.tencentcloudapi.com # ALIBABA 阿里云短信/ HUAWEI 华为云短信/ YUNPIAN 云片短信/ TENCENT 腾讯云短信/ UNI_SMS 合一短信/ JD_CLOUD 京东云短信/ CLOOPEN 容联云短信/ EMAY 亿美软通/ CTYUN 天翼云短信
endpoint: "dysmsapi.aliyuncs.com" supplierType: ALIBABA
accessKeyId: xxxxxxx # supplierType 对应的配置
accessKeySecret: xxxxxx alibaba:
signName: 测试 #阿里云的accessKey
# 腾讯专用 accessKeyId: 您的accessKey
sdkAppId: #阿里云的accessKeySecret
accessKeySecret: 您的accessKeySecret
#短信签名
signature: 测试签名
#模板ID 用于发送固定模板短信使用
templateId: SMS_215125134
#模板变量 上述模板的变量
templateName: code
#请求地址 默认为dysmsapi.aliyuncs.com 如无特殊改变可以不用设置
requestUrl: dysmsapi.aliyuncs.com

View File

@ -163,12 +163,22 @@ mail:
--- # sms 短信 --- # sms 短信
sms: sms:
# 是否启用短信
enabled: false enabled: false
# 阿里云 dysmsapi.aliyuncs.com # SupplierType中枚举
# 腾讯云 sms.tencentcloudapi.com # ALIBABA 阿里云短信/ HUAWEI 华为云短信/ YUNPIAN 云片短信/ TENCENT 腾讯云短信/ UNI_SMS 合一短信/ JD_CLOUD 京东云短信/ CLOOPEN 容联云短信/ EMAY 亿美软通/ CTYUN 天翼云短信
endpoint: "dysmsapi.aliyuncs.com" supplierType: ALIBABA
accessKeyId: xxxxxxx # supplierType 对应的配置
accessKeySecret: xxxxxx alibaba:
signName: 测试 #阿里云的accessKey
# 腾讯专用 accessKeyId: 您的accessKey
sdkAppId: #阿里云的accessKeySecret
accessKeySecret: 您的accessKeySecret
#短信签名
signature: 测试签名
#模板ID 用于发送固定模板短信使用
templateId: SMS_215125134
#模板变量 上述模板的变量
templateName: code
#请求地址 默认为dysmsapi.aliyuncs.com 如无特殊改变可以不用设置
requestUrl: dysmsapi.aliyuncs.com

View File

@ -22,15 +22,8 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.aliyun</groupId> <groupId>org.dromara.sms4j</groupId>
<artifactId>dysmsapi20170525</artifactId> <artifactId>sms4j-autoimmit</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.tencentcloudapi</groupId>
<artifactId>tencentcloud-sdk-java-sms</artifactId>
<optional>true</optional>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@ -1,15 +1,16 @@
package org.dromara.common.sms.config; package org.dromara.common.sms.config;
import org.dromara.common.sms.config.properties.SmsProperties; import org.dromara.common.sms.config.properties.SmsProperties;
import org.dromara.common.sms.core.AliyunSmsTemplate; import org.dromara.common.sms.core.Sms4jSmsTemplate;
import org.dromara.common.sms.core.SmsTemplate; import org.dromara.common.sms.core.SmsTemplate;
import org.dromara.common.sms.core.TencentSmsTemplate; import org.dromara.sms4j.autoimmit.config.SmsAutowiredConfig;
import org.dromara.sms4j.autoimmit.utils.SpringUtil;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/** /**
* 短信配置类 * 短信配置类
@ -19,30 +20,26 @@ import org.springframework.context.annotation.Configuration;
*/ */
@AutoConfiguration @AutoConfiguration
@EnableConfigurationProperties(SmsProperties.class) @EnableConfigurationProperties(SmsProperties.class)
@ConditionalOnProperty(value = "sms.enabled", havingValue = "true")
@ConditionalOnClass(org.dromara.sms4j.autoimmit.config.SmsAutowiredConfig.class)
public class SmsConfig { public class SmsConfig {
@Configuration @Bean
@ConditionalOnProperty(value = "sms.enabled", havingValue = "true") public SpringUtil springUtil(DefaultListableBeanFactory defaultListableBeanFactory) {
@ConditionalOnClass(com.aliyun.dysmsapi20170525.Client.class) return new SpringUtil(defaultListableBeanFactory);
static class AliyunSmsConfig { }
/**
* 主要配置注入 确保springUtil注入后再注入
*/
@Bean(initMethod = "init")
public SmsAutowiredConfig smsAutowiredConfig(SpringUtil springUtil) {
return new SmsAutowiredConfig(springUtil);
}
@Bean @Bean
public SmsTemplate aliyunSmsTemplate(SmsProperties smsProperties) { public SmsTemplate sms4jSmsTemplate(SmsProperties smsProperties) {
return new AliyunSmsTemplate(smsProperties); return new Sms4jSmsTemplate(smsProperties);
}
}
@Configuration
@ConditionalOnProperty(value = "sms.enabled", havingValue = "true")
@ConditionalOnClass(com.tencentcloudapi.sms.v20190711.SmsClient.class)
static class TencentSmsConfig {
@Bean
public SmsTemplate tencentSmsTemplate(SmsProperties smsProperties) {
return new TencentSmsTemplate(smsProperties);
}
} }
} }

View File

@ -1,6 +1,7 @@
package org.dromara.common.sms.config.properties; package org.dromara.common.sms.config.properties;
import lombok.Data; import lombok.Data;
import org.dromara.sms4j.provider.enumerate.SupplierType;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
/** /**
@ -15,31 +16,6 @@ public class SmsProperties {
private Boolean enabled; private Boolean enabled;
/** private SupplierType supplierType;
* 配置节点
* 阿里云 dysmsapi.aliyuncs.com
* 腾讯云 sms.tencentcloudapi.com
*/
private String endpoint;
/**
* key
*/
private String accessKeyId;
/**
* 密匙
*/
private String accessKeySecret;
/*
* 短信签名
*/
private String signName;
/**
* 短信应用ID (腾讯专属)
*/
private String sdkAppId;
} }

View File

@ -1,66 +0,0 @@
package org.dromara.common.sms.core;
import com.aliyun.dysmsapi20170525.Client;
import com.aliyun.dysmsapi20170525.models.SendSmsRequest;
import com.aliyun.dysmsapi20170525.models.SendSmsResponse;
import com.aliyun.teaopenapi.models.Config;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.json.utils.JsonUtils;
import org.dromara.common.sms.config.properties.SmsProperties;
import org.dromara.common.sms.entity.SmsResult;
import org.dromara.common.sms.exception.SmsException;
import lombok.SneakyThrows;
import java.util.Map;
/**
* Aliyun 短信模板
*
* @author Lion Li
* @version 4.2.0
*/
public class AliyunSmsTemplate implements SmsTemplate {
private SmsProperties properties;
private Client client;
@SneakyThrows(Exception.class)
public AliyunSmsTemplate(SmsProperties smsProperties) {
this.properties = smsProperties;
Config config = new Config()
// 您的AccessKey ID
.setAccessKeyId(smsProperties.getAccessKeyId())
// 您的AccessKey Secret
.setAccessKeySecret(smsProperties.getAccessKeySecret())
// 访问的域名
.setEndpoint(smsProperties.getEndpoint());
this.client = new Client(config);
}
@Override
public SmsResult send(String phones, String templateId, Map<String, String> param) {
if (StringUtils.isBlank(phones)) {
throw new SmsException("手机号不能为空");
}
if (StringUtils.isBlank(templateId)) {
throw new SmsException("模板ID不能为空");
}
SendSmsRequest req = new SendSmsRequest()
.setPhoneNumbers(phones)
.setSignName(properties.getSignName())
.setTemplateCode(templateId)
.setTemplateParam(JsonUtils.toJsonString(param));
try {
SendSmsResponse resp = client.sendSms(req);
return SmsResult.builder()
.isSuccess("OK".equals(resp.getBody().getCode()))
.message(resp.getBody().getMessage())
.response(JsonUtils.toJsonString(resp))
.build();
} catch (Exception e) {
throw new SmsException(e.getMessage());
}
}
}

View File

@ -0,0 +1,58 @@
package org.dromara.common.sms.core;
import cn.hutool.json.JSONUtil;
import lombok.SneakyThrows;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.json.utils.JsonUtils;
import org.dromara.common.sms.config.properties.SmsProperties;
import org.dromara.common.sms.entity.SmsResult;
import org.dromara.common.sms.exception.SmsException;
import org.dromara.sms4j.api.entity.SmsResponse;
import org.dromara.sms4j.core.factory.SmsFactory;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Tencent 短信模板
*
* @author Lion Li
* @version 4.2.0
*/
public class Sms4jSmsTemplate implements SmsTemplate {
private SmsProperties properties;
@SneakyThrows(Exception.class)
public Sms4jSmsTemplate(SmsProperties smsProperties) {
this.properties = smsProperties;
}
@Override
public SmsResult send(String phones, String templateId, Map<String, String> param) {
if (StringUtils.isBlank(phones)) {
throw new SmsException("手机号不能为空");
}
try {
SmsResponse resp;
if (StringUtils.isBlank(templateId)) {
String message = JSONUtil.toJsonStr(param);
resp = SmsFactory.createSmsBlend(properties.getSupplierType()).sendMessage(phones, message);
} else {
LinkedHashMap<String, String> messages = new LinkedHashMap<>(param);
resp = SmsFactory.createSmsBlend(properties.getSupplierType()).sendMessage(phones, templateId, messages);
}
SmsResult.SmsResultBuilder builder = SmsResult.builder();
if ("OK".equals(resp.getCode())) {
builder.isSuccess(true).message(resp.getMessage()).response(JsonUtils.toJsonString(resp));
} else {
builder.isSuccess(false).message(resp.getErrMessage()).response(JsonUtils.toJsonString(resp));
}
return builder.build();
} catch (Exception e) {
throw new SmsException(e.getMessage());
}
}
}

View File

@ -1,82 +0,0 @@
package org.dromara.common.sms.core;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.json.utils.JsonUtils;
import org.dromara.common.sms.config.properties.SmsProperties;
import org.dromara.common.sms.entity.SmsResult;
import org.dromara.common.sms.exception.SmsException;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.sms.v20190711.SmsClient;
import com.tencentcloudapi.sms.v20190711.models.SendSmsRequest;
import com.tencentcloudapi.sms.v20190711.models.SendSmsResponse;
import com.tencentcloudapi.sms.v20190711.models.SendStatus;
import lombok.SneakyThrows;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
/**
* Tencent 短信模板
*
* @author Lion Li
* @version 4.2.0
*/
public class TencentSmsTemplate implements SmsTemplate {
private SmsProperties properties;
private SmsClient client;
@SneakyThrows(Exception.class)
public TencentSmsTemplate(SmsProperties smsProperties) {
this.properties = smsProperties;
Credential credential = new Credential(smsProperties.getAccessKeyId(), smsProperties.getAccessKeySecret());
HttpProfile httpProfile = new HttpProfile();
httpProfile.setEndpoint(smsProperties.getEndpoint());
ClientProfile clientProfile = new ClientProfile();
clientProfile.setHttpProfile(httpProfile);
this.client = new SmsClient(credential, "", clientProfile);
}
@Override
public SmsResult send(String phones, String templateId, Map<String, String> param) {
if (StringUtils.isBlank(phones)) {
throw new SmsException("手机号不能为空");
}
if (StringUtils.isBlank(templateId)) {
throw new SmsException("模板ID不能为空");
}
SendSmsRequest req = new SendSmsRequest();
Set<String> set = Arrays.stream(phones.split(StringUtils.SEPARATOR)).map(p -> "+86" + p).collect(Collectors.toSet());
req.setPhoneNumberSet(ArrayUtil.toArray(set, String.class));
if (CollUtil.isNotEmpty(param)) {
req.setTemplateParamSet(ArrayUtil.toArray(param.values(), String.class));
}
req.setTemplateID(templateId);
req.setSign(properties.getSignName());
req.setSmsSdkAppid(properties.getSdkAppId());
try {
SendSmsResponse resp = client.SendSms(req);
SmsResult.SmsResultBuilder builder = SmsResult.builder()
.isSuccess(true)
.message("send success")
.response(JsonUtils.toJsonString(resp));
for (SendStatus sendStatus : resp.getSendStatusSet()) {
if (!"Ok".equals(sendStatus.getCode())) {
builder.isSuccess(false).message(sendStatus.getMessage());
break;
}
}
return builder.build();
} catch (Exception e) {
throw new SmsException(e.getMessage());
}
}
}

View File

@ -1 +1,3 @@
org.dromara.common.sms.config.SmsConfig org.dromara.common.sms.config.SmsConfig
org.dromara.sms4j.autoimmit.config.SmsAutowiredConfig
org.dromara.sms4j.autoimmit.config.SupplierConfig

View File

@ -1,10 +1,10 @@
package org.dromara.demo.controller; package org.dromara.demo.controller;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R; import org.dromara.common.core.domain.R;
import org.dromara.common.core.utils.SpringUtils; import org.dromara.common.core.utils.SpringUtils;
import org.dromara.common.sms.config.properties.SmsProperties; import org.dromara.common.sms.config.properties.SmsProperties;
import org.dromara.common.sms.core.SmsTemplate; import org.dromara.common.sms.core.SmsTemplate;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
@ -27,29 +27,6 @@ import java.util.Map;
public class SmsController { public class SmsController {
private final SmsProperties smsProperties; private final SmsProperties smsProperties;
// private final SmsTemplate smsTemplate; // 可以使用spring注入
// private final AliyunSmsTemplate smsTemplate; // 也可以注入某个厂家的模板工具
/**
* 发送短信Aliyun
*
* @param phones 电话号
* @param templateId 模板ID
*/
@GetMapping("/sendAliyun")
public R<Object> sendAliyun(String phones, String templateId) {
if (!smsProperties.getEnabled()) {
return R.fail("当前系统没有开启短信功能!");
}
if (!SpringUtils.containsBean("aliyunSmsTemplate")) {
return R.fail("阿里云依赖未引入!");
}
SmsTemplate smsTemplate = SpringUtils.getBean(SmsTemplate.class);
Map<String, String> map = new HashMap<>(1);
map.put("code", "1234");
Object send = smsTemplate.send(phones, templateId, map);
return R.ok(send);
}
/** /**
* 发送短信Tencent * 发送短信Tencent
@ -57,18 +34,18 @@ public class SmsController {
* @param phones 电话号 * @param phones 电话号
* @param templateId 模板ID * @param templateId 模板ID
*/ */
@GetMapping("/sendTencent") @GetMapping("/sendSms4j")
public R<Object> sendTencent(String phones, String templateId) { public R<Object> sendSms4j(String phones, String templateId) {
if (!smsProperties.getEnabled()) { if (!smsProperties.getEnabled()) {
return R.fail("当前系统没有开启短信功能!"); return R.fail("当前系统没有开启短信功能!");
} }
if (!SpringUtils.containsBean("tencentSmsTemplate")) { if (!SpringUtils.containsBean("sms4jSmsTemplate")) {
return R.fail("腾讯云依赖未引入!"); return R.fail("Sms4j依赖未引入!");
} }
SmsTemplate smsTemplate = SpringUtils.getBean(SmsTemplate.class); SmsTemplate smsTemplate = SpringUtils.getBean(SmsTemplate.class);
Map<String, String> map = new HashMap<>(1); Map<String, String> map = new HashMap<>(1);
// map.put("2", "测试测试"); // map.put("2", "测试测试");
map.put("1", "1234"); map.put("code", "123456");
Object send = smsTemplate.send(phones, templateId, map); Object send = smsTemplate.send(phones, templateId, map);
return R.ok(send); return R.ok(send);
} }