Browse Source

update sms4j 2.2.0 => 3.1.1 大升级 支持自定义配置key 可用于多厂商多租户等

疯狂的狮子Li 1 year ago
parent
commit
b628c9b027

+ 1 - 1
pom.xml

@@ -47,7 +47,7 @@
         <aws.sdk.version>2.23.0</aws.sdk.version>
         <aws.crt.version>0.29.6</aws.crt.version>
         <!-- SMS 配置 -->
-        <sms4j.version>2.2.0</sms4j.version>
+        <sms4j.version>3.1.1</sms4j.version>
         <!-- 限制框架中的fastjson版本 -->
         <fastjson.version>1.2.83</fastjson.version>
 

+ 6 - 7
ruoyi-admin/src/main/java/org/dromara/web/controller/CaptchaController.java

@@ -5,6 +5,9 @@ import cn.hutool.captcha.AbstractCaptcha;
 import cn.hutool.captcha.generator.CodeGenerator;
 import cn.hutool.core.util.IdUtil;
 import cn.hutool.core.util.RandomUtil;
+import jakarta.validation.constraints.NotBlank;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
 import org.dromara.common.core.constant.Constants;
 import org.dromara.common.core.constant.GlobalConstants;
 import org.dromara.common.core.domain.R;
@@ -21,11 +24,7 @@ import org.dromara.common.web.enums.CaptchaType;
 import org.dromara.sms4j.api.SmsBlend;
 import org.dromara.sms4j.api.entity.SmsResponse;
 import org.dromara.sms4j.core.factory.SmsFactory;
-import org.dromara.sms4j.provider.enumerate.SupplierType;
 import org.dromara.web.domain.vo.CaptchaVo;
-import jakarta.validation.constraints.NotBlank;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
 import org.springframework.expression.Expression;
 import org.springframework.expression.ExpressionParser;
 import org.springframework.expression.spel.standard.SpelExpressionParser;
@@ -66,11 +65,11 @@ public class CaptchaController {
         String templateId = "";
         LinkedHashMap<String, String> map = new LinkedHashMap<>(1);
         map.put("code", code);
-        SmsBlend smsBlend = SmsFactory.createSmsBlend(SupplierType.ALIBABA);
+        SmsBlend smsBlend = SmsFactory.getSmsBlend("config1");
         SmsResponse smsResponse = smsBlend.sendMessage(phonenumber, templateId, map);
-        if (!"OK".equals(smsResponse.getCode())) {
+        if (!smsResponse.isSuccess()) {
             log.error("验证码短信发送异常 => {}", smsResponse);
-            return R.fail(smsResponse.getMessage());
+            return R.fail(smsResponse.getData().toString());
         }
         return R.ok();
     }

+ 29 - 24
ruoyi-admin/src/main/resources/application-dev.yml

@@ -149,31 +149,36 @@ mail:
   connectionTimeout: 0
 
 --- # sms 短信 支持 阿里云 腾讯云 云片 等等各式各样的短信服务商
-# https://wind.kim/doc/start 文档地址 各个厂商可同时使用
+# https://sms4j.com/doc3/ 差异配置文档地址 支持单厂商多配置,可以配置多个同时使用
 sms:
-  # 阿里云 dysmsapi.aliyuncs.com
-  alibaba:
-    #请求地址 默认为 dysmsapi.aliyuncs.com 如无特殊改变可以不用设置
-    requestUrl: dysmsapi.aliyuncs.com
-    #阿里云的accessKey
-    accessKeyId: xxxxxxx
-    #阿里云的accessKeySecret
-    accessKeySecret: xxxxxxx
-    #短信签名
-    signature: 测试
-  tencent:
-    #请求地址默认为 sms.tencentcloudapi.com 如无特殊改变可不用设置
-    requestUrl: sms.tencentcloudapi.com
-    #腾讯云的accessKey
-    accessKeyId: xxxxxxx
-    #腾讯云的accessKeySecret
-    accessKeySecret: xxxxxxx
-    #短信签名
-    signature: 测试
-    #短信sdkAppId
-    sdkAppId: appid
-    #地域信息默认为 ap-guangzhou 如无特殊改变可不用设置
-    territory: ap-guangzhou
+  # 配置源类型用于标定配置来源(interface,yaml)
+  config-type: yaml
+  # 用于标定yml中的配置是否开启短信拦截,接口配置不受此限制
+  restricted: true
+  # 短信拦截限制单手机号每分钟最大发送,只对开启了拦截的配置有效
+  minute-max: 1
+  # 短信拦截限制单手机号每日最大发送量,只对开启了拦截的配置有效
+  account-max: 30
+  # 以下配置来自于 org.dromara.sms4j.provider.config.BaseConfig类中
+  blends:
+    # 唯一ID 用于发送短信寻找具体配置 随便定义别用中文即可
+    # 可以同时存在两个相同厂商 例如: ali1 ali2 两个不同的阿里短信账号 也可用于区分租户
+    config1:
+      # 框架定义的厂商名称标识,标定此配置是哪个厂商,详细请看厂商标识介绍部分
+      supplier: alibaba
+      # 有些称为accessKey有些称之为apiKey,也有称为sdkKey或者appId。
+      access-key-id: 您的accessKey
+      # 称为accessSecret有些称之为apiSecret
+      access-key-secret: 您的accessKeySecret
+      signature: 您的短信签名
+      sdk-app-id: 您的sdkAppId
+    config2:
+      # 厂商标识,标定此配置是哪个厂商,详细请看厂商标识介绍部分
+      supplier: tencent
+      access-key-id: 您的accessKey
+      access-key-secret: 您的accessKeySecret
+      signature: 您的短信签名
+      sdk-app-id: 您的sdkAppId
 
 
 --- # 三方授权

+ 29 - 24
ruoyi-admin/src/main/resources/application-prod.yml

@@ -152,31 +152,36 @@ mail:
   connectionTimeout: 0
 
 --- # sms 短信 支持 阿里云 腾讯云 云片 等等各式各样的短信服务商
-# https://wind.kim/doc/start 文档地址 各个厂商可同时使用
+# https://sms4j.com/doc3/ 差异配置文档地址 支持单厂商多配置,可以配置多个同时使用
 sms:
-  # 阿里云 dysmsapi.aliyuncs.com
-  alibaba:
-    #请求地址 默认为 dysmsapi.aliyuncs.com 如无特殊改变可以不用设置
-    requestUrl: dysmsapi.aliyuncs.com
-    #阿里云的accessKey
-    accessKeyId: xxxxxxx
-    #阿里云的accessKeySecret
-    accessKeySecret: xxxxxxx
-    #短信签名
-    signature: 测试
-  tencent:
-    #请求地址默认为 sms.tencentcloudapi.com 如无特殊改变可不用设置
-    requestUrl: sms.tencentcloudapi.com
-    #腾讯云的accessKey
-    accessKeyId: xxxxxxx
-    #腾讯云的accessKeySecret
-    accessKeySecret: xxxxxxx
-    #短信签名
-    signature: 测试
-    #短信sdkAppId
-    sdkAppId: appid
-    #地域信息默认为 ap-guangzhou 如无特殊改变可不用设置
-    territory: ap-guangzhou
+  # 配置源类型用于标定配置来源(interface,yaml)
+  config-type: yaml
+  # 用于标定yml中的配置是否开启短信拦截,接口配置不受此限制
+  restricted: true
+  # 短信拦截限制单手机号每分钟最大发送,只对开启了拦截的配置有效
+  minute-max: 1
+  # 短信拦截限制单手机号每日最大发送量,只对开启了拦截的配置有效
+  account-max: 30
+  # 以下配置来自于 org.dromara.sms4j.provider.config.BaseConfig类中
+  blends:
+    # 唯一ID 用于发送短信寻找具体配置 随便定义别用中文即可
+    # 可以同时存在两个相同厂商 例如: ali1 ali2 两个不同的阿里短信账号 也可用于区分租户
+    config1:
+      # 框架定义的厂商名称标识,标定此配置是哪个厂商,详细请看厂商标识介绍部分
+      supplier: alibaba
+      # 有些称为accessKey有些称之为apiKey,也有称为sdkKey或者appId。
+      access-key-id: 您的accessKey
+      # 称为accessSecret有些称之为apiSecret
+      access-key-secret: 您的accessKeySecret
+      signature: 您的短信签名
+      sdk-app-id: 您的sdkAppId
+    config2:
+      # 厂商标识,标定此配置是哪个厂商,详细请看厂商标识介绍部分
+      supplier: tencent
+      access-key-id: 您的accessKey
+      access-key-secret: 您的accessKeySecret
+      signature: 您的短信签名
+      sdk-app-id: 您的sdkAppId
 
 --- # 三方授权
 justauth:

+ 6 - 7
ruoyi-common/ruoyi-common-sms/pom.xml

@@ -20,13 +20,12 @@
         <dependency>
             <groupId>org.dromara.sms4j</groupId>
             <artifactId>sms4j-spring-boot-starter</artifactId>
-            <exclusions>
-                <!-- 排除京东短信内存在的fastjson等待作者后续修复 -->
-                <exclusion>
-                    <groupId>com.alibaba</groupId>
-                    <artifactId>fastjson</artifactId>
-                </exclusion>
-            </exclusions>
+        </dependency>
+
+        <!-- RuoYi Common Redis-->
+        <dependency>
+            <groupId>org.dromara</groupId>
+            <artifactId>ruoyi-common-redis</artifactId>
         </dependency>
 
     </dependencies>

+ 14 - 4
ruoyi-common/ruoyi-common-sms/src/main/java/org/dromara/common/sms/config/SmsAutoConfiguration.java

@@ -1,14 +1,24 @@
 package org.dromara.common.sms.config;
 
+import org.dromara.common.sms.core.dao.PlusSmsDao;
+import org.dromara.sms4j.api.dao.SmsDao;
 import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Primary;
 
 /**
- * 短信配置类(暂时没用 预留扩展)
+ * 短信配置类
  *
- * @author Lion Li
- * @version 4.2.0
+ * @author Feng
  */
-@AutoConfiguration
+@AutoConfiguration(after = {RedisAutoConfiguration.class})
 public class SmsAutoConfiguration {
 
+    @Primary
+    @Bean
+    public SmsDao smsDao() {
+        return new PlusSmsDao();
+    }
+
 }

+ 72 - 0
ruoyi-common/ruoyi-common-sms/src/main/java/org/dromara/common/sms/core/dao/PlusSmsDao.java

@@ -0,0 +1,72 @@
+package org.dromara.common.sms.core.dao;
+
+import org.dromara.common.core.constant.GlobalConstants;
+import org.dromara.common.redis.utils.RedisUtils;
+import org.dromara.sms4j.api.dao.SmsDao;
+
+import java.time.Duration;
+
+/**
+ * SmsDao缓存配置 (使用框架自带RedisUtils实现 协议统一)
+ * <p>主要用于短信重试和拦截的缓存
+ *
+ * @author Feng
+ */
+public class PlusSmsDao implements SmsDao {
+
+    /**
+     * 存储
+     *
+     * @param key       键
+     * @param value     值
+     * @param cacheTime 缓存时间(单位:秒)
+     */
+    @Override
+    public void set(String key, Object value, long cacheTime) {
+        RedisUtils.setCacheObject(GlobalConstants.GLOBAL_REDIS_KEY + key, value, Duration.ofSeconds(cacheTime));
+    }
+
+    /**
+     * 存储
+     *
+     * @param key   键
+     * @param value 值
+     */
+    @Override
+    public void set(String key, Object value) {
+        RedisUtils.setCacheObject(GlobalConstants.GLOBAL_REDIS_KEY + key, value, true);
+    }
+
+    /**
+     * 读取
+     *
+     * @param key 键
+     * @return 值
+     */
+    @Override
+    public Object get(String key) {
+        return RedisUtils.getCacheObject(GlobalConstants.GLOBAL_REDIS_KEY + key);
+    }
+
+    /**
+     * remove
+     * <p> 根据key移除缓存
+     *
+     * @param key 缓存键
+     * @return 被删除的value
+     * @author :Wind
+     */
+    @Override
+    public Object remove(String key) {
+        return RedisUtils.deleteObject(GlobalConstants.GLOBAL_REDIS_KEY + key);
+    }
+
+    /**
+     * 清空
+     */
+    @Override
+    public void clean() {
+        RedisUtils.deleteObject(GlobalConstants.GLOBAL_REDIS_KEY + "sms:");
+    }
+
+}

+ 28 - 4
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/SmsController.java

@@ -1,11 +1,11 @@
 package org.dromara.demo.controller;
 
+import cn.dev33.satoken.annotation.SaIgnore;
 import lombok.RequiredArgsConstructor;
 import org.dromara.common.core.domain.R;
 import org.dromara.sms4j.api.SmsBlend;
 import org.dromara.sms4j.api.entity.SmsResponse;
 import org.dromara.sms4j.core.factory.SmsFactory;
-import org.dromara.sms4j.provider.enumerate.SupplierType;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -20,12 +20,12 @@ import java.util.LinkedHashMap;
  * @author Lion Li
  * @version 4.2.0
  */
+@SaIgnore
 @Validated
 @RequiredArgsConstructor
 @RestController
 @RequestMapping("/demo/sms")
 public class SmsController {
-
     /**
      * 发送短信Aliyun
      *
@@ -36,7 +36,7 @@ public class SmsController {
     public R<Object> sendAliyun(String phones, String templateId) {
         LinkedHashMap<String, String> map = new LinkedHashMap<>(1);
         map.put("code", "1234");
-        SmsBlend smsBlend = SmsFactory.createSmsBlend(SupplierType.ALIBABA);
+        SmsBlend smsBlend = SmsFactory.getSmsBlend("config1");
         SmsResponse smsResponse = smsBlend.sendMessage(phones, templateId, map);
         return R.ok(smsResponse);
     }
@@ -52,9 +52,33 @@ public class SmsController {
         LinkedHashMap<String, String> map = new LinkedHashMap<>(1);
 //        map.put("2", "测试测试");
         map.put("1", "1234");
-        SmsBlend smsBlend = SmsFactory.createSmsBlend(SupplierType.TENCENT);
+        SmsBlend smsBlend = SmsFactory.getSmsBlend("config2");
         SmsResponse smsResponse = smsBlend.sendMessage(phones, templateId, map);
         return R.ok(smsResponse);
     }
 
+    /**
+     * 添加黑名单
+     *
+     * @param phone 手机号
+     */
+    @GetMapping("/addBlacklist")
+    public R<Object> addBlacklist(String phone){
+        SmsBlend smsBlend = SmsFactory.getSmsBlend("config1");
+        smsBlend.joinInBlacklist(phone);
+        return R.ok();
+    }
+
+    /**
+     * 移除黑名单
+     *
+     * @param phone 手机号
+     */
+    @GetMapping("/removeBlacklist")
+    public R<Object> removeBlacklist(String phone){
+        SmsBlend smsBlend = SmsFactory.getSmsBlend("config1");
+        smsBlend.removeFromBlacklist(phone);
+        return R.ok();
+    }
+
 }