本文主要分享了如何设计一个发送短信功能。
一、总结简述
1.梳理多个平台短信API的发送参数,集成封装提供统一的API,支持多个短信平台(阿里云、腾讯云、百度云、京东云、七牛云)灵活切换
2.提供存储方案,表结构设计
3.提供真实生产项目代码案例,实现异步机制、定时发送、超时取消发送等功能
4.文末提供代码仓库,有兴趣的小伙伴可以fork代码
二、架构图
三、代码实现(渠道SDK封装)
1.短信抽象核心代码(项目:sms-sender-core)
1)抽象短信发送器,定义一个接口
2)以阿里云短信对接实现类为demo的代码展示,其他渠道代码类似,当然也可以增加自定义渠道实现,实现SmsSender的接口即可(可通过gitee查看源码)
3)阿里云短信封装SmsClient核心代码
2.简化项目sms-sender-core的引用,springboot自动装配(项目:sms-sender-spring-boot-starter)
1)这里就只展示SmsSenderAutoConfiguration的代码,其他的可以通过gitee查看源码
简单的短信代码SDK封装到此结束,但在我们实际项目开发是远不够的。实际项目中还需要考虑存储方案、异步机制、定时发送、超时取消发送、失败重试机制、渠道切换等。
四、代码实现(项目实际应用)
1.数据库表结构设计
CREATE TABLE `sms_type_template_config` (`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',`type` varchar(16) NOT NULL COMMENT '业务类型(verifycode:验证码,market:营销活动,tips:提示信息)',`channel` varchar(16) NOT NULL COMMENT '发送渠道(log:打印日志(测试),ali:阿里云,tencent:腾讯云)',`template_code` varchar(32) NOT NULL COMMENT '模板编码',`remark` varchar(255) DEFAULT NULL COMMENT '备注',`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',PRIMARY KEY (`id`) USING BTREE,UNIQUE KEY `uniq_type_channel` (`type`,`channel`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='短信业务-模板配置';CREATE TABLE `sms_template` (`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',`channel` varchar(16) NOT NULL COMMENT '发送渠道(log:打印日志(测试),ali:阿里云,tencent:腾讯云)',`template_code` varchar(32) NOT NULL COMMENT '模板编码',`template_content` varchar(255) DEFAULT NULL COMMENT '模板内容',`remark` varchar(255) DEFAULT NULL COMMENT '备注',`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',PRIMARY KEY (`id`) USING BTREE,UNIQUE KEY `uniq_channel_templatecode` (`channel`,`template_code`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='短信模板';CREATE TABLE `sms_task` (`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',`type` varchar(16) NOT NULL COMMENT '业务类型(verifycode:验证码,market:营销活动,tips:提示信息)',`plan_send_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '计划发送时间',`over_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '超时取消发送时间',`remark` varchar(255) DEFAULT NULL COMMENT '备注',`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',PRIMARY KEY (`id`) USING BTREE,KEY `idx_type` (`type`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='短信发送任务';CREATE TABLE `sms_task_detail` (`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',`task_id` int(11) unsigned NOT NULL COMMENT 'sms_task.id',`mobile` varchar(11) NOT NULL COMMENT '手机号码',`template_param_json` varchar(255) DEFAULT NULL COMMENT '模板参数json',`plan_send_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '计划发送时间',`actual_send_time` datetime DEFAULT NULL COMMENT '实际发送时间',`status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '状态(1:待发送,2:待定时发送,11:发送MQ成功,12:MQ消费成功,21:请求成功,22:请求失败,31:取消发送)',`content` varchar(255) DEFAULT NULL COMMENT '短信内容',`remark` varchar(255) DEFAULT NULL COMMENT '备注',`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',PRIMARY KEY (`id`) USING BTREE,KEY `idx_taskid` (`task_id`),KEY `idx_mobile` (`mobile`),KEY `idx_plansendtime_status` (plan_send_time,`status`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='短信发送任务明细';CREATE TABLE `sms_record` (`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',`channel` varchar(16) NOT NULL COMMENT '发送渠道(log:打印日志(测试),ali:阿里云,tencent:腾讯云)',`mobile` varchar(11) NOT NULL COMMENT '手机号码',`sign_name` varchar(12) NOT NULL COMMENT '短信签名(2~12个字符),如:【XX公司】,【】不用填写',`template_code` varchar(32) NOT NULL COMMENT '模板编码',`template_param_json` varchar(255) DEFAULT NULL COMMENT '模板参数json',`content` varchar(255) DEFAULT NULL COMMENT '短信内容',`result` varchar(8) NOT NULL COMMENT '结果(success:成功,fail:失败)',`message` varchar(255) DEFAULT NULL COMMENT '信息',`request_id` varchar(64) DEFAULT NULL COMMENT '请求ID',`remark` varchar(255) DEFAULT NULL COMMENT '备注',`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',PRIMARY KEY (`id`) USING BTREE,KEY `idx_mobile` (`mobile`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='短信发送记录';
表说明:
sms_type_template_config:主要是记录业务类型与模板编码的关系,这样可以避免在代码中写死模板编码,因为不同的渠道模板编码也会不一致
sms_template:配置不同渠道的短信模板
sms_task、sms_task_detail:短信任务,可以理解为每次发送短信都是1个短信任务,每个短信任务可以给多个用户发送短信,营销短信常用,支持即时发送和定时发送
sms_record:短信发送记录,最终调用完发送短信API记录(不代表一定发送成功,部分渠道平台还提供了查询发送状态的API,如果需要了解最终状态需要增加状态API的查询)
数据样例说明:
短信业务-模板配置
1)代码中会写死type,跟据type+channel查询到template_code
短信模板
1)跟据channel+template_code查询到template_content
为什么要记录模板内容?
1)其实template_content一般是不需要传递给第三方API的,大部分都是通过“模板编码+短信参数”的方式来发送短信,但也有部分渠道API有特殊情况,直接通过“短信内容”来发送
2)运营人员在发送营销短信时需要在管理后台能看到短信模板
3)短信的实际内容是需要保留存储的,而渠道API一般都不会返回实际发送内容,只能由程序拼凑
短信发送记录
2.将sms_type_template_config、sms_template都做成后台配置功能,这里就不细讲了
3.核心代码展示
1)项目结构
2)生产者核心代码
3)消费者核心代码
补充:失败重试机制(可利用template-tool下的innercallback代码实现)、渠道切换尚未实现,后续有时间再补充!!!
怎么样?如果你觉得有用的话,还不快快收藏起来!!!
附:涉及的代码目录
github: GitHub – 897665787/sms-sender: 一个封装了短信发送的框架,支持阿里云短信、腾讯云短信等。、GitHub – 897665787/springcloud-template: 一个基于springcloud netflix微服务框架,记录了关于微服务开发的一些最佳应用,欢迎大家学习指导。
gitee:sms-sender: 一个封装了短信发送的框架,支持阿里云短信、腾讯云短信等。、springcloud-template: 一个基于springcloud netflix微服务框架,记录了关于微服务开发的一些最佳应用,欢迎大家学习指导。
sms-sender├── sms-sender-core -- 核心代码 └── ali -- 阿里云 └── baidu -- 百度云 └── jingdong -- 京东云 └── log -- 测试渠道(一般用于测试环境不想真正的发送短信,短信可是要收费的) └── qiniu-- 七牛云 └── tencent -- 腾讯云└── sms-sender-boot-starter -- 整合springboot代码└── sms-sender-jdbc-spring-boot-starter -- 整合springboot代码,增加了jdbc存储方案,自动创建表短信模板(sms_template)、短信发送记录(sms_record)2张表 └── processor└── SqlSendPostProcessor -- jdbc存储实现└── sms-sender-springboot-demo -- 在springboot中使用sms-sender的demo代码springcloud-template└── template-tool └──controller└── SmsController -- 短信任务轮询API└── VerifyCodeController -- 验证码短信发送demo └── sms└── AsyncSmsSender -- 异步发送短信,MQ生产者逻辑└── MysqlSendPostProcessor -- 记录短信发送记录└── SmsSenderConsumer -- 异步发送短信,MQ消费者逻辑└── sql └── tool└── 短信设计相关表.sql