Skip to content

📱 短信服务设计

1. 模块概述

短信服务模块是系统的核心功能之一,基于策略模式和工厂模式实现,支持多种短信服务商(阿里云、腾讯云等)。该模块采用数据库存储配置(JSON格式),提供了短信发送、模板管理、记录管理等功能,适用于各种业务场景下的短信发送需求。

2. 设计目标

目标描述
🎯 多服务商支持支持阿里云、腾讯云等多种短信服务商
🔧 易于扩展基于策略模式和工厂模式,易于扩展新的短信服务商
� 数据库配置配置信息存储在数据库中,使用JSON格式管理
�📊 完整的功能提供短信发送、模板管理、记录管理等功能
🚀 高性能支持异步发送短信,提高系统响应速度
🔐 安全性完善的异常处理机制,确保系统稳定性
📋 可追溯性记录短信发送状态和内容,便于查询和统计

3. 目录结构

zs-sms/
├── zs-sms-api/                  # 短信API定义
├── zs-sms-service/              # 短信服务实现
│   ├── src/main/java/com/zs/sms/
│   │   ├── controller/          # 控制器
│   │   ├── domain/              # 数据模型
│   │   │   ├── entity/          # 实体类
│   │   │   ├── excel/           # Excel导出模型
│   │   │   ├── params/          # 请求参数
│   │   │   └── vo/              # 响应VO
│   │   ├── factory/             # 工厂类
│   │   ├── mapper/              # Mapper接口
│   │   ├── service/             # 服务层
│   │   └── strategy/            # 短信发送策略
│   └── resources/               # 资源文件
└── pom.xml                      # Maven依赖

4. 核心设计

4.1 设计模式

4.1.1 策略模式

短信服务采用策略模式实现,定义了统一的短信发送接口 SendSmsStrategy,不同的短信服务商实现该接口,提供不同的发送逻辑。

优点

  • ✅ 易于扩展新的短信服务商
  • ✅ 便于切换不同的短信服务商
  • ✅ 符合开闭原则,对扩展开放,对修改关闭

4.1.2 工厂模式

提供 SmsFactory 工厂类,用于创建不同的短信发送策略实例。

优点

  • ✅ 封装了策略的创建逻辑
  • ✅ 客户端无需直接依赖具体的策略实现
  • ✅ 便于统一管理和配置

4.2 核心接口和类

4.2.1 SendSmsStrategy 接口

java
/**
 * 📱 短信发送策略接口
 * 定义统一的短信发送方法,不同短信服务商实现该接口
 */
public interface SendSmsStrategy {
    /**
     * 发送短信
     * @param params 短信参数
     * @return 发送结果
     */
    boolean sendSms(SysSmsParams params);
}

4.2.2 SmsFactory 工厂类

java
/**
 * 📱 短信工厂类
 * 用于创建不同的短信发送策略实例
 */
public class SmsFactory {
    /**
     * 创建短信发送策略
     * @param type 短信服务商类型
     * @return 短信发送策略实例
     */
    public static SendSmsStrategy createStrategy(String type) {
        switch (type) {
            case "aliyun":
                return new AliyunSendSmsStrategy();
            case "tencent":
                return new TencentSendSmsStrategy();
            default:
                throw new IllegalArgumentException("Unsupported sms provider type: " + type);
        }
    }
}

4.2.3 策略实现类

类名描述
AliyunSendSmsStrategy阿里云短信发送策略
TencentSendSmsStrategy腾讯云短信发送策略

4.3 数据模型

4.3.1 SysSmsRecordEntity

短信发送记录实体类,记录短信发送状态和内容。

字段名类型描述
idLong记录ID
mobileString手机号
templateIdString模板ID
templateParamsString模板参数
contentString短信内容
statusInteger发送状态(0:失败,1:成功)
errorMsgString错误信息
sendTimeDate发送时间
createTimeDate创建时间

4.3.2 SysSmsTemplateEntity

短信模板实体类,记录短信模板信息。

字段名类型描述
idLong模板ID
templateCodeString模板编码
templateContentString模板内容
templateTypeString模板类型
statusInteger状态(0:禁用,1:启用)
createTimeDate创建时间
updateTimeDate更新时间

4.3.3 SysSmsConfigEntity

数据库存储配置信息,使用JSON格式,记录短信服务商配置。

字段名类型描述
idLong配置ID
providerTypeString服务商类型(aliyun、tencent等)
configString配置信息(JSON格式)
statusInteger状态(0:禁用,1:启用)
createTimeDate创建时间
updateTimeDate更新时间
remarkString备注信息

4.3.4 SysSmsParams

短信发送参数类,用于封装短信发送所需的参数。

字段名类型描述
mobileString手机号
templateIdString模板ID
templateParamsMap<String, String>模板参数
signNameString签名名称

5. 核心流程

5.1 短信发送流程

mermaid
sequenceDiagram
    participant Client as 客户端
    participant Controller as 控制器
    participant SmsService as 短信服务
    participant ConfigService as 配置服务
    participant SmsFactory as 短信工厂
    participant Strategy as 短信策略
    participant DB as 数据库

    Client->>Controller: 调用短信发送接口
    Controller->>SmsService: 调用sendSms方法
    SmsService->>SmsService: 验证模板是否存在且启用
    SmsService->>ConfigService: 查询数据库获取短信配置
    ConfigService->>DB: 查询配置信息
    DB-->>ConfigService: 返回配置(JSON格式)
    ConfigService-->>SmsService: 返回解析后的配置对象
    SmsService->>SmsFactory: 创建短信发送策略
    SmsFactory->>Strategy: 创建具体策略实例
    SmsService->>Strategy: 调用sendSms方法
    Strategy-->>SmsService: 返回发送结果
    SmsService->>DB: 保存发送记录
    SmsService-->>Controller: 返回发送结果
    Controller-->>Client: 返回响应

5.2 模板管理流程

mermaid
sequenceDiagram
    participant Admin as 管理员
    participant Controller as 控制器
    participant TemplateService as 模板服务
    participant DB as 数据库

    Admin->>Controller: 添加短信模板
    Controller->>TemplateService: 调用addTemplate方法
    TemplateService->>DB: 保存模板信息
    TemplateService-->>Controller: 返回添加结果
    Controller-->>Admin: 返回响应
    
    Admin->>Controller: 审核短信模板
    Controller->>TemplateService: 调用auditTemplate方法
    TemplateService->>DB: 更新模板状态
    TemplateService-->>Controller: 返回审核结果
    Controller-->>Admin: 返回响应
    
    Admin->>Controller: 启用短信模板
    Controller->>TemplateService: 调用enableTemplate方法
    TemplateService->>DB: 更新模板状态
    TemplateService-->>Controller: 返回启用结果
    Controller-->>Admin: 返回响应

6. 使用示例

6.1 短信发送示例

java
@Service
public class SmsServiceImpl implements SmsService {

    @Autowired
    private SysSmsTemplateService sysSmsTemplateService;
    
    @Autowired
    private SysSmsRecordService sysSmsRecordService;
    
    @Autowired
    private SysSmsConfigService sysSmsConfigService;

    @Override
    public boolean sendSms(SysSmsParams params) {
        // 1. 验证模板是否存在且启用
        SysSmsTemplateVO template = sysSmsTemplateService.getByCode(params.getTemplateId());
        if (template == null || template.getStatus() != 1) {
            throw new IllegalArgumentException("Template not found or disabled");
        }
        
        // 2. 从数据库获取短信服务商配置(JSON格式)
        SysSmsConfigVO config = sysSmsConfigService.getEnabledConfig();
        if (config == null) {
            throw new IllegalStateException("No enabled SMS provider config found");
        }
        
        // 3. 创建短信发送策略
        SendSmsStrategy strategy = SmsFactory.createStrategy(config.getProviderType());
        
        // 4. 发送短信
        boolean success = strategy.sendSms(params);
        
        // 5. 保存发送记录
        SysSmsRecordAddParams recordParams = new SysSmsRecordAddParams();
        recordParams.setMobile(params.getMobile());
        recordParams.setTemplateId(params.getTemplateId());
        recordParams.setTemplateParams(JSONUtil.toJsonStr(params.getTemplateParams()));
        recordParams.setContent(generateContent(template, params.getTemplateParams()));
        recordParams.setStatus(success ? 1 : 0);
        recordParams.setSendTime(new Date());
        sysSmsRecordService.save(recordParams);
        
        return success;
    }
    
    private String generateContent(SysSmsTemplateVO template, Map<String, String> params) {
        // 根据模板和参数生成短信内容
        String content = template.getTemplateContent();
        for (Map.Entry<String, String> entry : params.entrySet()) {
            content = content.replace("{" + entry.getKey() + "}", entry.getValue());
        }
        return content;
    }
}

6.2 配置管理示例

java
@Service
public class SysSmsConfigServiceImpl implements SysSmsConfigService {
    
    @Autowired
    private SysSmsConfigMapper sysSmsConfigMapper;
    
    @Override
    public SysSmsConfigVO getEnabledConfig() {
        // 查询启用的配置
        SysSmsConfigEntity configEntity = sysSmsConfigMapper.selectEnabledConfig();
        if (configEntity == null) {
            return null;
        }
        
        // 解析JSON配置
        SysSmsConfigVO configVO = new SysSmsConfigVO();
        configVO.setId(configEntity.getId());
        configVO.setProviderType(configEntity.getProviderType());
        configVO.setConfig(JSONUtil.parseObj(configEntity.getConfig()));
        configVO.setStatus(configEntity.getStatus());
        configVO.setRemark(configEntity.getRemark());
        
        return configVO;
    }
    
    @Override
    public void saveConfig(SysSmsConfigAddParams params) {
        // 保存配置到数据库
        SysSmsConfigEntity entity = new SysSmsConfigEntity();
        entity.setProviderType(params.getProviderType());
        entity.setConfig(JSONUtil.toJsonStr(params.getConfig()));
        entity.setStatus(params.getStatus());
        entity.setRemark(params.getRemark());
        
        if (params.getId() != null) {
            entity.setId(params.getId());
            sysSmsConfigMapper.updateById(entity);
        } else {
            sysSmsConfigMapper.insert(entity);
        }
    }
}

6.3 控制器示例

java
@RestController
@RequestMapping("/sms")
public class SysSmsController {

    @Autowired
    private SmsService smsService;
    
    @Autowired
    private SysSmsConfigService sysSmsConfigService;

    @PostMapping("/send")
    public Result<Boolean> sendSms(@RequestBody SysSmsParams params) {
        try {
            boolean success = smsService.sendSms(params);
            return Result.ok(success, success ? "短信发送成功" : "短信发送失败");
        } catch (Exception e) {
            return Result.error("短信发送失败:" + e.getMessage());
        }
    }
    
    @PostMapping("/config")
    public Result<Boolean> saveConfig(@RequestBody SysSmsConfigAddParams params) {
        try {
            sysSmsConfigService.saveConfig(params);
            return Result.ok(true, "配置保存成功");
        } catch (Exception e) {
            return Result.error("配置保存失败:" + e.getMessage());
        }
    }
    
    @GetMapping("/config")
    public Result<SysSmsConfigVO> getConfig() {
        try {
            SysSmsConfigVO config = sysSmsConfigService.getEnabledConfig();
            return Result.ok(config, "配置获取成功");
        } catch (Exception e) {
            return Result.error("配置获取失败:" + e.getMessage());
        }
    }
}

7. 配置说明

7.1 阿里云短信配置(JSON格式)

配置项类型描述
accessKeyIdString阿里云AccessKey ID
accessKeySecretString阿里云AccessKey Secret
signNameString短信签名
endpointString阿里云短信服务端点
regionIdString阿里云区域ID,默认cn-hangzhou

配置示例

json
{
  "accessKeyId": "your_access_key_id",
  "accessKeySecret": "your_access_key_secret",
  "signName": "your_sign_name",
  "endpoint": "dysmsapi.aliyuncs.com",
  "regionId": "cn-hangzhou"
}

7.2 腾讯云短信配置(JSON格式)

配置项类型描述
secretIdString腾讯云SecretId
secretKeyString腾讯云SecretKey
signNameString短信签名
endpointString腾讯云短信服务端点
regionString腾讯云区域,默认ap-guangzhou

配置示例

json
{
  "secretId": "your_secret_id",
  "secretKey": "your_secret_key",
  "signName": "your_sign_name",
  "endpoint": "sms.tencentcloudapi.com",
  "region": "ap-guangzhou"
}

8. 注意事项

  1. 模板审核:短信模板需要经过短信服务商审核才能使用
  2. 发送频率限制:避免频繁发送短信,防止被短信服务商拉黑
  3. 异常处理:短信发送可能失败,需做好异常处理和重试机制
  4. 签名配置:确保已在短信服务商平台配置了正确的签名
  5. 参数验证:严格验证短信发送参数,防止恶意调用
  6. 记录保存:保存短信发送记录,便于调试和审计
  7. 配置安全:妥善保管短信服务商的密钥信息,建议使用加密存储
  8. 数据库配置:配置信息存储在数据库中,使用JSON格式管理,便于动态修改

9. 扩展建议

  1. 添加更多服务商:支持更多短信服务商,如百度云、华为云等
  2. 添加短信队列:实现异步发送短信,提高系统响应速度
  3. 添加短信统计:统计短信发送量、成功率等指标
  4. 支持批量发送:支持一次性发送多条短信
  5. 添加短信模板变量验证:验证模板参数是否与模板匹配
  6. 支持短信状态回调:接收短信服务商的状态回调,更新发送状态
  7. 添加短信黑名单:支持配置短信黑名单,防止恶意发送
  8. 添加短信模板版本管理:支持模板的版本管理和回滚

10. 常见问题排查

10.1 短信发送失败

问题:调用短信发送接口后返回失败

可能原因

  • 数据库中短信服务商配置错误
  • 模板ID或签名配置错误
  • 手机号格式错误
  • 短信内容包含敏感词
  • 网络连接问题

解决方案

  • 检查数据库中的配置信息
  • 验证模板ID和签名
  • 验证手机号格式
  • 检查短信内容
  • 检查网络连接

10.2 短信发送成功但接收者未收到

问题:短信发送接口返回成功,但接收者未收到短信

可能原因

  • 手机号错误
  • 短信被运营商拦截
  • 短信服务商延迟
  • 接收者手机问题

解决方案

  • 验证手机号
  • 检查短信内容是否包含敏感词
  • 等待一段时间后再次检查
  • 尝试发送到其他手机号

10.3 模板审核不通过

问题:短信模板审核不通过

可能原因

  • 模板内容不符合要求
  • 模板用途描述不清晰
  • 缺少必要的资质证明

解决方案

  • 调整模板内容,确保符合短信服务商要求
  • 清晰描述模板用途
  • 提供必要的资质证明

10.4 发送频率超限

问题:发送短信时提示频率超限

可能原因

  • 短时间内发送短信次数过多
  • 超过了短信服务商的频率限制

解决方案

  • 减少短信发送频率
  • 联系短信服务商调整频率限制
  • 实现短信发送队列,控制发送速度

11. 总结

短信服务模块基于策略模式和工厂模式实现,支持多种短信服务商,采用数据库存储配置(JSON格式),具有良好的扩展性和灵活性。该模块提供了短信发送、模板管理、记录管理等功能,适用于各种业务场景下的短信发送需求。

通过合理配置和使用,可以避免常见问题,提高短信发送的可靠性和安全性。同时,该模块具有良好的扩展性,可以根据业务需求进行功能扩展和优化。