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

This commit is contained in:
疯狂的狮子Li 2024-01-18 18:33:47 +08:00
parent 928e418f3f
commit b628c9b027
8 changed files with 185 additions and 71 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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:");
}
}

View File

@ -1,11 +1,11 @@
package org.dromara.demo.controller; package org.dromara.demo.controller;
import cn.dev33.satoken.annotation.SaIgnore;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R; import org.dromara.common.core.domain.R;
import org.dromara.sms4j.api.SmsBlend; import org.dromara.sms4j.api.SmsBlend;
import org.dromara.sms4j.api.entity.SmsResponse; import org.dromara.sms4j.api.entity.SmsResponse;
import org.dromara.sms4j.core.factory.SmsFactory; import org.dromara.sms4j.core.factory.SmsFactory;
import org.dromara.sms4j.provider.enumerate.SupplierType;
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;
@ -20,12 +20,12 @@ import java.util.LinkedHashMap;
* @author Lion Li * @author Lion Li
* @version 4.2.0 * @version 4.2.0
*/ */
@SaIgnore
@Validated @Validated
@RequiredArgsConstructor @RequiredArgsConstructor
@RestController @RestController
@RequestMapping("/demo/sms") @RequestMapping("/demo/sms")
public class SmsController { public class SmsController {
/** /**
* 发送短信Aliyun * 发送短信Aliyun
* *
@ -36,7 +36,7 @@ public class SmsController {
public R<Object> sendAliyun(String phones, String templateId) { public R<Object> sendAliyun(String phones, String templateId) {
LinkedHashMap<String, String> map = new LinkedHashMap<>(1); LinkedHashMap<String, String> map = new LinkedHashMap<>(1);
map.put("code", "1234"); map.put("code", "1234");
SmsBlend smsBlend = SmsFactory.createSmsBlend(SupplierType.ALIBABA); SmsBlend smsBlend = SmsFactory.getSmsBlend("config1");
SmsResponse smsResponse = smsBlend.sendMessage(phones, templateId, map); SmsResponse smsResponse = smsBlend.sendMessage(phones, templateId, map);
return R.ok(smsResponse); return R.ok(smsResponse);
} }
@ -52,9 +52,33 @@ public class SmsController {
LinkedHashMap<String, String> map = new LinkedHashMap<>(1); LinkedHashMap<String, String> map = new LinkedHashMap<>(1);
// map.put("2", "测试测试"); // map.put("2", "测试测试");
map.put("1", "1234"); map.put("1", "1234");
SmsBlend smsBlend = SmsFactory.createSmsBlend(SupplierType.TENCENT); SmsBlend smsBlend = SmsFactory.getSmsBlend("config2");
SmsResponse smsResponse = smsBlend.sendMessage(phones, templateId, map); SmsResponse smsResponse = smsBlend.sendMessage(phones, templateId, map);
return R.ok(smsResponse); 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();
}
} }