From e57d11d55a95ceafc793f714710d488bb1afc585 Mon Sep 17 00:00:00 2001 From: 疯狂的狮子li <15040126243@163.com> Date: 星期五, 06 五月 2022 18:07:00 +0800 Subject: [PATCH] add 增加 ruoyi-sms 短信模块 整合 阿里云、腾讯云 短信功能 --- ruoyi-sms/src/main/java/com/ruoyi/sms/entity/SmsResult.java | 29 ++++ ruoyi-sms/src/main/java/com/ruoyi/sms/config/SmsConfig.java | 44 ++++++ ruoyi-sms/src/main/java/com/ruoyi/sms/core/SmsTemplate.java | 26 +++ ruoyi-admin/src/main/resources/application-prod.yml | 12 + ruoyi-sms/src/main/java/com/ruoyi/sms/core/AliyunSmsTemplate.java | 65 +++++++++ ruoyi-sms/src/main/java/com/ruoyi/sms/exception/SmsException.java | 16 ++ ruoyi-sms/src/main/java/com/ruoyi/sms/core/TencentSmsTemplate.java | 80 +++++++++++ pom.xml | 24 +++ ruoyi-sms/src/main/java/com/ruoyi/sms/config/properties/SmsProperties.java | 47 ++++++ ruoyi-admin/src/main/resources/application-dev.yml | 12 + ruoyi-sms/pom.xml | 40 +++++ 11 files changed, 395 insertions(+), 0 deletions(-) diff --git a/pom.xml b/pom.xml index 4fc098f..bd82267 100644 --- a/pom.xml +++ b/pom.xml @@ -50,6 +50,10 @@ <qcloud.cos.version>5.6.72</qcloud.cos.version> <minio.version>8.3.8</minio.version> + <!-- SMS 閰嶇疆 --> + <aliyun.sms.version>2.0.9</aliyun.sms.version> + <tencent.sms.version>3.1.500</tencent.sms.version> + <!-- docker 閰嶇疆 --> <docker.registry.url>localhost</docker.registry.url> <docker.registry.host>http://${docker.registry.url}:2375</docker.registry.host> @@ -193,6 +197,18 @@ </dependency> <dependency> + <groupId>com.aliyun</groupId> + <artifactId>dysmsapi20170525</artifactId> + <version>${aliyun.sms.version}</version> + </dependency> + + <dependency> + <groupId>com.tencentcloudapi</groupId> + <artifactId>tencentcloud-sdk-java</artifactId> + <version>${tencent.sms.version}</version> + </dependency> + + <dependency> <groupId>de.codecentric</groupId> <artifactId>spring-boot-admin-starter-server</artifactId> <version>${spring-boot-admin.version}</version> @@ -297,6 +313,13 @@ <version>${ruoyi-vue-plus.version}</version> </dependency> + <!-- SMS鐭俊妯″潡 --> + <dependency> + <groupId>com.ruoyi</groupId> + <artifactId>ruoyi-sms</artifactId> + <version>${ruoyi-vue-plus.version}</version> + </dependency> + <!-- demo妯″潡 --> <dependency> <groupId>com.ruoyi</groupId> @@ -317,6 +340,7 @@ <module>ruoyi-demo</module> <module>ruoyi-extend</module> <module>ruoyi-oss</module> + <module>ruoyi-sms</module> </modules> <packaging>pom</packaging> diff --git a/ruoyi-admin/src/main/resources/application-dev.yml b/ruoyi-admin/src/main/resources/application-dev.yml index 6be268b..d14047f 100644 --- a/ruoyi-admin/src/main/resources/application-dev.yml +++ b/ruoyi-admin/src/main/resources/application-dev.yml @@ -178,3 +178,15 @@ timeout: 0 # Socket杩炴帴瓒呮椂鍊硷紝鍗曚綅姣锛岀己鐪佸�间笉瓒呮椂 connectionTimeout: 0 + +--- # sms 鐭俊 +sms: + enabled: false + # 闃块噷浜� dysmsapi.aliyuncs.com + # 鑵捐浜� sms.tencentcloudapi.com + endpoint: "dysmsapi.aliyuncs.com" + accessKeyId: xxxxxxx + accessKeySecret: xxxxxx + signName: 娴嬭瘯 + # 鑵捐涓撶敤 + sdkAppId: diff --git a/ruoyi-admin/src/main/resources/application-prod.yml b/ruoyi-admin/src/main/resources/application-prod.yml index 4966a41..6619e05 100644 --- a/ruoyi-admin/src/main/resources/application-prod.yml +++ b/ruoyi-admin/src/main/resources/application-prod.yml @@ -181,3 +181,15 @@ timeout: 0 # Socket杩炴帴瓒呮椂鍊硷紝鍗曚綅姣锛岀己鐪佸�间笉瓒呮椂 connectionTimeout: 0 + +--- # sms 鐭俊 +sms: + enabled: false + # 闃块噷浜� dysmsapi.aliyuncs.com + # 鑵捐浜� sms.tencentcloudapi.com + endpoint: "dysmsapi.aliyuncs.com" + accessKeyId: xxxxxxx + accessKeySecret: xxxxxx + signName: 娴嬭瘯 + # 鑵捐涓撶敤 + sdkAppId: diff --git a/ruoyi-sms/pom.xml b/ruoyi-sms/pom.xml new file mode 100644 index 0000000..8550e8c --- /dev/null +++ b/ruoyi-sms/pom.xml @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <parent> + <artifactId>ruoyi-vue-plus</artifactId> + <groupId>com.ruoyi</groupId> + <version>4.1.0</version> + </parent> + <modelVersion>4.0.0</modelVersion> + + <artifactId>ruoyi-sms</artifactId> + + <description> + SMS鐭俊妯″潡 + </description> + + <dependencies> + + <!-- 閫氱敤宸ュ叿--> + <dependency> + <groupId>com.ruoyi</groupId> + <artifactId>ruoyi-common</artifactId> + </dependency> + + <dependency> + <groupId>com.aliyun</groupId> + <artifactId>dysmsapi20170525</artifactId> + <optional>true</optional> + </dependency> + + <dependency> + <groupId>com.tencentcloudapi</groupId> + <artifactId>tencentcloud-sdk-java</artifactId> + <optional>true</optional> + </dependency> + + </dependencies> + +</project> diff --git a/ruoyi-sms/src/main/java/com/ruoyi/sms/config/SmsConfig.java b/ruoyi-sms/src/main/java/com/ruoyi/sms/config/SmsConfig.java new file mode 100644 index 0000000..abc4bb9 --- /dev/null +++ b/ruoyi-sms/src/main/java/com/ruoyi/sms/config/SmsConfig.java @@ -0,0 +1,44 @@ +package com.ruoyi.sms.config; + +import com.ruoyi.sms.config.properties.SmsProperties; +import com.ruoyi.sms.core.AliyunSmsTemplate; +import com.ruoyi.sms.core.SmsTemplate; +import com.ruoyi.sms.core.TencentSmsTemplate; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * 鐭俊閰嶇疆绫� + * + * @author Lion Li + * @version 4.2.0 + */ +@Configuration +@ConditionalOnProperty(value = "sms.enabled", havingValue = "true") +public class SmsConfig { + + @Configuration + @ConditionalOnClass(com.aliyun.dysmsapi20170525.Client.class) + static class AliyunSmsConfig { + + @Bean + public SmsTemplate aliyunSmsTemplate(SmsProperties smsProperties) { + return new AliyunSmsTemplate(smsProperties); + } + + } + + @Configuration + @ConditionalOnClass(com.tencentcloudapi.sms.v20190711.SmsClient.class) + static class TencentSmsConfig { + + @Bean + public SmsTemplate tencentSmsTemplate(SmsProperties smsProperties) { + return new TencentSmsTemplate(smsProperties); + } + + } + +} diff --git a/ruoyi-sms/src/main/java/com/ruoyi/sms/config/properties/SmsProperties.java b/ruoyi-sms/src/main/java/com/ruoyi/sms/config/properties/SmsProperties.java new file mode 100644 index 0000000..39359cd --- /dev/null +++ b/ruoyi-sms/src/main/java/com/ruoyi/sms/config/properties/SmsProperties.java @@ -0,0 +1,47 @@ +package com.ruoyi.sms.config.properties; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * SMS鐭俊 閰嶇疆灞炴�� + * + * @author Lion Li + * @version 4.2.0 + */ +@Data +@Component +@ConfigurationProperties(prefix = "sms") +public class SmsProperties { + + private Boolean enabled; + + /** + * 閰嶇疆鑺傜偣 + * 闃块噷浜� dysmsapi.aliyuncs.com + * 鑵捐浜� sms.tencentcloudapi.com + */ + private String endpoint; + + /** + * key + */ + private String accessKeyId; + + /** + * 瀵嗗寵 + */ + private String accessKeySecret; + + /* + * 鐭俊绛惧悕 + */ + private String signName; + + /** + * 鐭俊搴旂敤ID (鑵捐涓撳睘) + */ + private String sdkAppId; + +} diff --git a/ruoyi-sms/src/main/java/com/ruoyi/sms/core/AliyunSmsTemplate.java b/ruoyi-sms/src/main/java/com/ruoyi/sms/core/AliyunSmsTemplate.java new file mode 100644 index 0000000..87c3f3b --- /dev/null +++ b/ruoyi-sms/src/main/java/com/ruoyi/sms/core/AliyunSmsTemplate.java @@ -0,0 +1,65 @@ +package com.ruoyi.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 com.ruoyi.common.utils.JsonUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.sms.config.properties.SmsProperties; +import com.ruoyi.sms.entity.SmsResult; +import com.ruoyi.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); + } + + 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(resp) + .build(); + } catch (Exception e) { + throw new SmsException(e.getMessage()); + } + } + +} diff --git a/ruoyi-sms/src/main/java/com/ruoyi/sms/core/SmsTemplate.java b/ruoyi-sms/src/main/java/com/ruoyi/sms/core/SmsTemplate.java new file mode 100644 index 0000000..0aec3dd --- /dev/null +++ b/ruoyi-sms/src/main/java/com/ruoyi/sms/core/SmsTemplate.java @@ -0,0 +1,26 @@ +package com.ruoyi.sms.core; + +import com.ruoyi.sms.entity.SmsResult; + +import java.util.Map; + +/** + * 鐭俊妯℃澘 + * + * @author Lion Li + * @version 4.2.0 + */ +public interface SmsTemplate { + + /** + * 鍙戦�佺煭淇� + * + * @param phones 鐢佃瘽鍙�(澶氫釜閫楀彿鍒嗗壊) + * @param templateId 妯℃澘id + * @param param 妯℃澘瀵瑰簲鍙傛暟 + * 闃块噷 闇�浣跨敤 妯℃澘鍙橀噺鍚嶇О瀵瑰簲鍐呭 渚嬪: code=1234 + * 鑵捐 闇�浣跨敤 妯℃澘鍙橀噺椤哄簭瀵瑰簲鍐呭 渚嬪: 1=1234, 1涓烘ā鏉垮唴绗竴涓弬鏁� + */ + SmsResult send(String phones, String templateId, Map<String, String> param); + +} diff --git a/ruoyi-sms/src/main/java/com/ruoyi/sms/core/TencentSmsTemplate.java b/ruoyi-sms/src/main/java/com/ruoyi/sms/core/TencentSmsTemplate.java new file mode 100644 index 0000000..ce82c3c --- /dev/null +++ b/ruoyi-sms/src/main/java/com/ruoyi/sms/core/TencentSmsTemplate.java @@ -0,0 +1,80 @@ +package com.ruoyi.sms.core; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ArrayUtil; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.sms.config.properties.SmsProperties; +import com.ruoyi.sms.entity.SmsResult; +import com.ruoyi.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); + } + + 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(",")).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(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()); + } + } + +} diff --git a/ruoyi-sms/src/main/java/com/ruoyi/sms/entity/SmsResult.java b/ruoyi-sms/src/main/java/com/ruoyi/sms/entity/SmsResult.java new file mode 100644 index 0000000..3f13b27 --- /dev/null +++ b/ruoyi-sms/src/main/java/com/ruoyi/sms/entity/SmsResult.java @@ -0,0 +1,29 @@ +package com.ruoyi.sms.entity; + +import lombok.Builder; +import lombok.Data; + +/** + * 涓婁紶杩斿洖浣� + * + * @author Lion Li + */ +@Data +@Builder +public class SmsResult { + + /** + * 鏄惁鎴愬姛 + */ + private boolean isSuccess; + + /** + * 鍝嶅簲娑堟伅 + */ + private String message; + + /** + * 瀹為檯鍝嶅簲浣� + */ + private Object response; +} diff --git a/ruoyi-sms/src/main/java/com/ruoyi/sms/exception/SmsException.java b/ruoyi-sms/src/main/java/com/ruoyi/sms/exception/SmsException.java new file mode 100644 index 0000000..28632a3 --- /dev/null +++ b/ruoyi-sms/src/main/java/com/ruoyi/sms/exception/SmsException.java @@ -0,0 +1,16 @@ +package com.ruoyi.sms.exception; + +/** + * Sms寮傚父绫� + * + * @author Lion Li + */ +public class SmsException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + public SmsException(String msg) { + super(msg); + } + +} -- Gitblit v1.9.3