Skip to content

Commit e4828bf

Browse files
authored
feat(system/sms): 短信渠道支持数据字典配置 (#159)
1 parent c9d5810 commit e4828bf

File tree

13 files changed

+220
-21
lines changed

13 files changed

+220
-21
lines changed

continew-common/src/main/java/top/continew/admin/common/config/properties/CaptchaProperties.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,5 +88,22 @@ public static class CaptchaSms {
8888
* 模板 ID
8989
*/
9090
private String templateId;
91+
92+
/**
93+
* 供应商渠道
94+
*
95+
* @see top.continew.admin.system.model.resp.SmsConfigResp#supplier
96+
*/
97+
private String supplier;
98+
99+
/**
100+
* 验证码字段模版键名
101+
*/
102+
private String codeKey = "code";
103+
104+
/**
105+
* 失效时间字段模版键名
106+
*/
107+
private String timeKey = "expirationInMinutes";
91108
}
92109
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package top.continew.admin.system.config.sms;
18+
19+
import java.util.HashMap;
20+
import java.util.Map;
21+
import java.util.Objects;
22+
23+
import org.dromara.sms4j.provider.config.BaseConfig;
24+
import org.dromara.sms4j.provider.factory.BaseProviderFactory;
25+
import org.dromara.sms4j.provider.factory.ProviderFactoryHolder;
26+
27+
import com.fasterxml.jackson.core.type.TypeReference;
28+
import com.fasterxml.jackson.databind.DeserializationFeature;
29+
import com.fasterxml.jackson.databind.ObjectMapper;
30+
31+
import lombok.AccessLevel;
32+
import lombok.NoArgsConstructor;
33+
import top.continew.admin.system.model.resp.SmsConfigResp;
34+
35+
/**
36+
* 短信配置工具类
37+
*
38+
* @author Top2Hub
39+
* @since 2025/04/21 14:00
40+
*/
41+
42+
@NoArgsConstructor(access = AccessLevel.PRIVATE)
43+
public class SmsConfigUtil {
44+
45+
private static final TypeReference<Map<String, Object>> CONFIG_MAP_TYPE = new TypeReference<Map<String, Object>>() {};
46+
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper()
47+
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
48+
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
49+
50+
/**
51+
* 将本地配置对象转换为 BaseConfig
52+
*
53+
* @param smsConfig 本地配置对象
54+
* @return SMS4j 配置基类
55+
*/
56+
public static BaseConfig from(SmsConfigResp smsConfig) {
57+
if (Objects.isNull(smsConfig))
58+
return null;
59+
60+
String supplierName = smsConfig.getSupplier();
61+
BaseProviderFactory<?, ?> providerFactory = ProviderFactoryHolder.requireForSupplier(supplierName);
62+
if (Objects.isNull(providerFactory))
63+
return null;
64+
65+
Map<String, Object> configInfo = new HashMap<>();
66+
configInfo.put("configId", smsConfig.getId().toString());
67+
configInfo.put("accessKeyId", smsConfig.getAccessKey());
68+
configInfo.put("accessKeySecret", smsConfig.getSecretKey());
69+
configInfo.put("signature", smsConfig.getSignature());
70+
configInfo.put("templateId", smsConfig.getTemplateId());
71+
if (Objects.nonNull(smsConfig.getWeight()))
72+
configInfo.put("weight", smsConfig.getWeight());
73+
if (Objects.nonNull(smsConfig.getRetryInterval()))
74+
configInfo.put("retryInterval", smsConfig.getRetryInterval());
75+
if (Objects.nonNull(smsConfig.getMaxRetries()))
76+
configInfo.put("maxRetries", smsConfig.getMaxRetries());
77+
78+
if (Objects.nonNull(smsConfig.getSupplierConfig())) {
79+
Map<String, Object> supplierInfo = OBJECT_MAPPER.convertValue(smsConfig
80+
.getSupplierConfig(), CONFIG_MAP_TYPE);
81+
configInfo.putAll(supplierInfo);
82+
}
83+
84+
BaseConfig config = (BaseConfig)OBJECT_MAPPER.convertValue(configInfo, providerFactory.getConfigClass());
85+
return config;
86+
}
87+
88+
}

continew-module-system/src/main/java/top/continew/admin/system/config/sms/SmsReadConfigDatabaseImpl.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@
1818

1919
import cn.hutool.core.collection.CollUtil;
2020
import lombok.RequiredArgsConstructor;
21+
2122
import org.dromara.sms4j.core.datainterface.SmsReadConfig;
2223
import org.dromara.sms4j.provider.config.BaseConfig;
2324
import org.springframework.stereotype.Component;
25+
2426
import top.continew.admin.common.enums.DisEnableStatusEnum;
2527
import top.continew.admin.system.model.query.SmsConfigQuery;
2628
import top.continew.admin.system.model.resp.SmsConfigResp;
@@ -48,7 +50,7 @@ public BaseConfig getSupplierConfig(String configId) {
4850
if (DisEnableStatusEnum.DISABLE.equals(smsConfig.getStatus())) {
4951
return null;
5052
}
51-
return smsConfig.getSupplier().toBaseConfig(smsConfig);
53+
return SmsConfigUtil.from(smsConfig);
5254
}
5355

5456
@Override
@@ -59,6 +61,6 @@ public List<BaseConfig> getSupplierConfigList() {
5961
if (CollUtil.isEmpty(list)) {
6062
return List.of();
6163
}
62-
return list.stream().map(smsConfig -> smsConfig.getSupplier().toBaseConfig(smsConfig)).toList();
64+
return list.stream().map(smsConfig -> SmsConfigUtil.from(smsConfig)).toList();
6365
}
6466
}

continew-module-system/src/main/java/top/continew/admin/system/enums/SmsSupplierEnum.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,10 @@
3232
* @author luoqiz
3333
* @author Charles7c
3434
* @since 2025/03/15 22:15
35+
*
36+
* @deprecated 使用数据字典`sms_supplier_type`动态维护
3537
*/
38+
@Deprecated
3639
@Getter
3740
@RequiredArgsConstructor
3841
public enum SmsSupplierEnum implements BaseEnum<String> {

continew-module-system/src/main/java/top/continew/admin/system/model/entity/SmsConfigDO.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import lombok.Data;
2121
import top.continew.admin.common.enums.DisEnableStatusEnum;
2222
import top.continew.admin.common.model.entity.BaseDO;
23-
import top.continew.admin.system.enums.SmsSupplierEnum;
2423
import top.continew.starter.security.crypto.annotation.FieldEncrypt;
2524

2625
import java.io.Serial;
@@ -47,7 +46,7 @@ public class SmsConfigDO extends BaseDO {
4746
/**
4847
* 厂商
4948
*/
50-
private SmsSupplierEnum supplier;
49+
private String supplier;
5150

5251
/**
5352
* Access Key

continew-module-system/src/main/java/top/continew/admin/system/model/query/SmsConfigQuery.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import io.swagger.v3.oas.annotations.media.Schema;
2020
import lombok.Data;
2121
import top.continew.admin.common.enums.DisEnableStatusEnum;
22-
import top.continew.admin.system.enums.SmsSupplierEnum;
2322
import top.continew.starter.data.core.annotation.Query;
2423
import top.continew.starter.data.core.enums.QueryType;
2524

@@ -52,7 +51,7 @@ public class SmsConfigQuery implements Serializable {
5251
*/
5352
@Schema(description = "厂商", example = "cloopen")
5453
@Query
55-
private SmsSupplierEnum supplier;
54+
private String supplier;
5655

5756
/**
5857
* Access Key

continew-module-system/src/main/java/top/continew/admin/system/model/req/SmsConfigReq.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424

2525
import org.hibernate.validator.constraints.Length;
2626
import top.continew.admin.common.enums.DisEnableStatusEnum;
27-
import top.continew.admin.system.enums.SmsSupplierEnum;
2827

2928
import java.io.Serial;
3029
import java.io.Serializable;
@@ -56,7 +55,7 @@ public class SmsConfigReq implements Serializable {
5655
*/
5756
@Schema(description = "厂商", example = "cloopen")
5857
@NotNull(message = "厂商无效")
59-
private SmsSupplierEnum supplier;
58+
private String supplier;
6059

6160
/**
6261
* Access Key

continew-module-system/src/main/java/top/continew/admin/system/model/resp/SmsConfigResp.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,10 @@
2020
import com.alibaba.excel.annotation.ExcelProperty;
2121
import io.swagger.v3.oas.annotations.media.Schema;
2222
import lombok.Data;
23+
import top.continew.admin.common.config.excel.DictExcelProperty;
24+
import top.continew.admin.common.config.excel.ExcelDictConverter;
2325
import top.continew.admin.common.enums.DisEnableStatusEnum;
2426
import top.continew.admin.common.model.resp.BaseDetailResp;
25-
import top.continew.admin.system.enums.SmsSupplierEnum;
2627
import top.continew.starter.file.excel.converter.ExcelBaseEnumConverter;
2728
import top.continew.starter.security.mask.annotation.JsonMask;
2829

@@ -52,10 +53,14 @@ public class SmsConfigResp extends BaseDetailResp {
5253

5354
/**
5455
* 厂商
56+
* 对齐 sms4j 短信服务商常量类
57+
*
58+
* @see org.dromara.sms4j.comm.constant.SupplierConstant
5559
*/
5660
@Schema(description = "厂商", example = "cloopen")
57-
@ExcelProperty(value = "厂商")
58-
private SmsSupplierEnum supplier;
61+
@ExcelProperty(value = "厂商", converter = ExcelDictConverter.class)
62+
@DictExcelProperty("sms_supplier_type")
63+
private String supplier;
5964

6065
/**
6166
* Access Key

continew-module-system/src/main/java/top/continew/admin/system/service/impl/SmsConfigServiceImpl.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,13 @@
1616

1717
package top.continew.admin.system.service.impl;
1818

19-
import cn.hutool.core.bean.BeanUtil;
2019
import lombok.RequiredArgsConstructor;
20+
2121
import org.dromara.sms4j.core.factory.SmsFactory;
2222
import org.dromara.sms4j.provider.config.BaseConfig;
2323
import org.springframework.stereotype.Service;
24-
import top.continew.admin.system.enums.SmsSupplierEnum;
24+
25+
import top.continew.admin.system.config.sms.SmsConfigUtil;
2526
import top.continew.admin.system.mapper.SmsConfigMapper;
2627
import top.continew.admin.system.model.entity.SmsConfigDO;
2728
import top.continew.admin.system.model.query.SmsConfigQuery;
@@ -31,6 +32,7 @@
3132
import top.continew.starter.extension.crud.service.BaseServiceImpl;
3233

3334
import java.util.List;
35+
import java.util.Objects;
3436

3537
/**
3638
* 短信配置业务实现
@@ -69,9 +71,11 @@ public void afterDelete(List<Long> ids) {
6971
* @param entity 配置信息
7072
*/
7173
private void load(SmsConfigDO entity) {
72-
SmsSupplierEnum supplier = entity.getSupplier();
73-
BaseConfig config = supplier.toBaseConfig(BeanUtil.toBean(entity, SmsConfigResp.class));
74-
SmsFactory.createSmsBlend(config);
74+
SmsConfigResp smsConfig = this.get(entity.getId());
75+
76+
BaseConfig config = SmsConfigUtil.from(smsConfig);
77+
if (Objects.nonNull(config))
78+
SmsFactory.createSmsBlend(config);
7579
}
7680

7781
/**

continew-webapi/src/main/java/top/continew/admin/controller/common/CaptchaController.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
import lombok.RequiredArgsConstructor;
3939
import org.dromara.sms4j.api.SmsBlend;
4040
import org.dromara.sms4j.api.entity.SmsResponse;
41-
import org.dromara.sms4j.comm.constant.SupplierConstant;
4241
import org.dromara.sms4j.core.factory.SmsFactory;
4342
import org.springframework.http.HttpHeaders;
4443
import org.springframework.validation.annotation.Validated;
@@ -204,12 +203,16 @@ public R getSmsCaptcha(@NotBlank(message = "手机号不能为空") @Mobile Stri
204203
String captcha = RandomUtil.randomNumbers(captchaSms.getLength());
205204
// 发送验证码
206205
Long expirationInMinutes = captchaSms.getExpirationInMinutes();
207-
SmsBlend smsBlend = SmsFactory.getBySupplier(SupplierConstant.CLOOPEN);
206+
207+
SmsBlend smsBlend = SmsFactory.getBySupplier(captchaSms.getSupplier());
208+
208209
Map<String, String> messageMap = MapUtil.newHashMap(2, true);
209-
messageMap.put("captcha", captcha);
210-
messageMap.put("expirationInMinutes", String.valueOf(expirationInMinutes));
210+
messageMap.put(captchaSms.getCodeKey(), captcha);
211+
messageMap.put(captchaSms.getTimeKey(), String.valueOf(expirationInMinutes));
212+
211213
SmsResponse smsResponse = smsBlend.sendMessage(phone, captchaSms
212214
.getTemplateId(), (LinkedHashMap<String, String>)messageMap);
215+
213216
CheckUtils.throwIf(!smsResponse.isSuccess(), "验证码发送失败");
214217
// 保存验证码
215218
String captchaKey = CacheConstants.CAPTCHA_KEY_PREFIX + phone;

0 commit comments

Comments
 (0)