SpringBoot2.x 集成 腾讯云短信
本文主要对SpringBoot2.x集成腾讯云短信进行简单总结,其中SpringBoot使用的2.4.5
版本。
一、腾讯云短信简介
腾讯云短信(Short Message Service,SMS)沉淀腾讯十多年短信服务技术和经验,为QQ、微信等亿级平台和10万+客户提供快速灵活接入的高质量的国内短信与国际/港澳台短信服务。
- 国内短信验证秒级触达,99%到达率。
- 国际/港澳台短信覆盖全球200+国家/地区,稳定可靠。
单次短信的业务请求流程如下所示:
短信由签名和正文内容组成,发送短信前需要申请短信签名和正文内容模板。短信签名是位于短信正文前【】中的署名,用于标识公司或业务。短信签名需要审核通过后才可使用。短信模板即具体发送的短信正文内容,短信模板支持验证码模板、通知类短信模板和营销短信模板。短信内容可以通过模板参数实现个性化定制。短信模板申请前需要先申请短信签名,短信模板需要审核通过后才可使用。
二、准备工作
1.开通短信服务
如果没有腾讯云账号,需要注册腾讯云账号,并完成实名认证,可以个人认证和企业认证,不能进行企业认证的话也可以进行个人认证。然后进入腾讯云短信控制台,开通短信服务,开通短信和个人认证之后分别都会赠送包含100条短信的国内套餐包,用来测试足够:
2.创建签名
这里创建国内短信签名,创建完成后等到状态变为已通过就可以使用了:
创建签名时签名类型可以选网站、APP、公众号和小程序,可以根据需要创建:
3.创建正文模板
创建模板,创建完成之后状态变为已通过就可以使用了:
模板内容可以使用标准模板也可以自定义:
4.创建短信应用
在应用列表下可以创建短信应用,获取短信应用的SDKAppID:
点击应用可以查看应用信息:
5.腾讯云API密钥
在访问管理菜单的访问密钥下的API密钥管理中可以新建和查看API密钥,在请求腾讯云短信服务发送短信时需要传入该密钥:
三、集成腾讯云短信
通过Maven新建一个名为springboot-tencent-sms
的项目。
1.引入依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 腾讯云 Java SDK 依赖 -->
<dependency><groupId>com.tencentcloudapi</groupId><artifactId>tencentcloud-sdk-java</artifactId><version>3.1.297</version>
</dependency>
<!-- Spring Data Redis 起步依赖 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- lombok插件 -->
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.8</version>
</dependency>
2.编写配置类
用于读取配置文件中的自定义腾讯云短信配置的配置类:
package com.rtxtitanv.config;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;/*** @author rtxtitanv* @version 1.0.0* @name com.rtxtitanv.config.SmsConfig* @description 腾讯云短信配置类* @date 2021/6/25 16:21*/
@ConfigurationProperties(prefix = "tencent.sms")
@Configuration
@Data
public class SmsConfig {/*** 腾讯云API密钥的SecretId*/private String secretId;/*** 腾讯云API密钥的SecretKey*/private String secretKey;/*** 短信应用的SDKAppID*/private String appId;/*** 签名内容*/private String sign;/*** 模板ID*/private String templateId;/*** 过期时间*/private String expireTime;/*** redis存储的key的前缀*/private String phonePrefix;
}
Redis配置类:
package com.rtxtitanv.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;import javax.annotation.Resource;/*** @author rtxtitanv* @version 1.0.0* @name com.rtxtitanv.config.RedisConfig* @description Redis配置类* @date 2021/6/26 12:24*/
@Configuration
public class RedisConfig {@Resourceprivate RedisConnectionFactory redisConnectionFactory;/*** RedisTemplate实例** @return RedisTemplate实例*/@Beanpublic RedisTemplate<String, Object> redisTemplate() {RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();initRedisTemplate(redisTemplate, redisConnectionFactory);return redisTemplate;}/*** 设置数据存入redis的序列化方式** @param redisTemplate RedisTemplate对象* @param factory RedisConnectionFactory对象*/private void initRedisTemplate(RedisTemplate<String, Object> redisTemplate, RedisConnectionFactory factory) {redisTemplate.setKeySerializer(new StringRedisSerializer());redisTemplate.setValueSerializer(new StringRedisSerializer());redisTemplate.setHashKeySerializer(new GenericJackson2JsonRedisSerializer());redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());redisTemplate.setConnectionFactory(factory);}
}
3.编写配置文件
spring:redis:host: 127.0.0.1port: 6379# 自定义腾讯云短信配置
tencent:sms:# 配置腾讯云API密钥的SecretIdsecretId: 这里填腾讯云API密钥的SecretId# 配置腾讯云API密钥的SecretKeysecretKey: 这里填腾讯云API密钥的SecretKey# 配置短信应用的SDKAppIDappId: 这里填短信应用的SDKAppID# 配置签名内容sign: "这里填签名内容"# 配置模板IDtemplateId: 这里填模板ID# 配置过期时间expireTime: 5# 配置redis存储的key的前缀phonePrefix: REGIST
4.编写工具类
腾讯云短信工具类:
package com.rtxtitanv.util;import com.rtxtitanv.config.SmsConfig;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.sms.v20210111.SmsClient;
import com.tencentcloudapi.sms.v20210111.models.SendSmsRequest;
import com.tencentcloudapi.sms.v20210111.models.SendSmsResponse;
import com.tencentcloudapi.sms.v20210111.models.SendStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;/*** @author rtxtitanv* @version 1.0.0* @name com.rtxtitanv.util.SmsUtil* @description 腾讯云短信工具类* @date 2021/6/25 16:21*/
public class SmsUtil {private static final Logger LOGGER = LoggerFactory.getLogger(SmsUtil.class);/*** 发送短信** @param smsConfig 腾讯云短信配置对象* @param templateParams 模板参数* @param phoneNumbers 手机号数组* @return SendStatus[],短信发送状态*/public static SendStatus[] sendSms(SmsConfig smsConfig, String[] templateParams, String[] phoneNumbers) {try {// 实例化一个认证对象,入参需要传入腾讯云账户密钥对secretId,secretKey。Credential cred = new Credential(smsConfig.getSecretId(), smsConfig.getSecretKey());// 实例化一个http选项,可选,没有特殊需求可以跳过HttpProfile httpProfile = new HttpProfile();// SDK默认使用POST方法httpProfile.setReqMethod("POST");// SDK有默认的超时时间,非必要请不要进行调整httpProfile.setConnTimeout(60);// 非必要步骤:实例化一个客户端配置对象,可以指定超时时间等配置ClientProfile clientProfile = new ClientProfile();// SDK默认用TC3-HMAC-SHA256进行签名,非必要请不要修改这个字段clientProfile.setSignMethod("HmacSHA256");clientProfile.setHttpProfile(httpProfile);// 实例化要请求产品(以sms为例)的client对象,第二个参数是地域信息,可以直接填写字符串ap-guangzhou,或者引用预设的常量SmsClient smsClient = new SmsClient(cred, "ap-guangzhou", clientProfile);// 实例化一个请求对象SendSmsRequest req = new SendSmsRequest();// 设置短信应用ID:短信SdkAppId在[短信控制台]添加应用后生成的实际SdkAppIdreq.setSmsSdkAppId(smsConfig.getAppId());// 设置短信签名内容:使用UTF-8编码,必须填写已审核通过的签名,签名信息可登录[短信控制台]查看req.setSignName(smsConfig.getSign());// 设置国际/港澳台短信SenderId:国内短信填空,默认未开通req.setSenderId("");// 设置模板ID:必须填写已审核通过的模板ID。模板ID可登录[短信控制台]查看req.setTemplateId(smsConfig.getTemplateId());// 设置下发手机号码,采用E.164标准,+[国家或地区码][手机号]req.setPhoneNumberSet(phoneNumbers);// 设置模板参数:若无模板参数,则设置为空req.setTemplateParamSet(templateParams);// 通过client对象调用SendSms方法发起请求。注意请求方法名与请求对象是对应的,返回的res是一个SendSmsResponse类的实例,与请求对象对应SendSmsResponse res = smsClient.SendSms(req);// 控制台打印日志输出json格式的字符串回包LOGGER.info(SendSmsResponse.toJsonString(res));return res.getSendStatusSet();} catch (TencentCloudSDKException e) {e.printStackTrace();throw new RuntimeException(e.getMessage());}}
}
Redis工具类:
package com.rtxtitanv.util;import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;/*** @author rtxtitanv* @version 1.0.0* @name com.rtxtitanv.util.RedisUtil* @description Redis工具类* @date 2021/6/26 12:24*/
@Component
public class RedisUtil {@Resourceprivate RedisTemplate<String, Object> redisTemplate;/*** 缓存基本对象** @param key 键* @param value 值* @param expire 键的过期时间*/public void setCacheObject(String key, Object value, long expire) {redisTemplate.opsForValue().set(key, value);if (expire > 0) {redisTemplate.expire(key, expire, TimeUnit.MINUTES);}}/*** 获取指定键的缓存对象** @param key 键* @return 缓存对象*/public Object getCacheObject(String key) {return redisTemplate.opsForValue().get(key);}/*** 判断键是否存在并且未过期** @param key 键* @return true,键存在并且未过期;false,键不存在或存在但过期*/public boolean hasKey(String key) {return redisTemplate.hasKey(key) && getExpire(key) > 0 ? true : false;}/*** 获取键的过期时间** @param key 键* @return 过期时间*/public long getExpire(String key) {return redisTemplate.getExpire(key, TimeUnit.MINUTES);}/*** 删除指定键的缓存** @param key 键*/public void delete(String key) {redisTemplate.delete(key);}/*** 创建缓存的键** @param prefix 前缀* @param phoneNumber 手机号* @return 键*/public static String createCacheKey(String prefix, String phoneNumber) {return prefix + phoneNumber;}
}
用于生成随机验证码的工具类:
package com.rtxtitanv.util;import java.util.Random;/*** @author rtxtitanv* @version 1.0.0* @name com.rtxtitanv.util.RandomUtil* @description Random工具类* @date 2021/6/26 11:39*/
public class RandomUtil {private static final Random RANDOM = new Random();/*** 生成指定位数的随机数字字符串** @param length 字符串长度* @return 随机数字字符串*/public static String randomNumbers(int length) {StringBuilder randomNumbers = new StringBuilder();for (int i = 0; i < length; i++) {randomNumbers.append(RANDOM.nextInt(10));}return randomNumbers.toString();}
}
5.Controller层
package com.rtxtitanv.controller;import com.rtxtitanv.service.SmsService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;/*** @author rtxtitanv* @version 1.0.0* @name com.rtxtitanv.controller.SmsController* @description SmsController* @date 2021/6/25 16:20*/
@RequestMapping("/sms")
@RestController
public class SmsController {@Resourceprivate SmsService smsService;@PostMapping("/send")public String sendSmsCode(@RequestParam(value = "phoneNumber") String phoneNumber) {return smsService.sendSmsCode(phoneNumber);}@PostMapping("/verify")public String verifySmsCode(@RequestParam(value = "phoneNumber") String phoneNumber,@RequestParam(value = "smsCode") String smsCode) {return smsService.verifySmsCode(phoneNumber, smsCode);}
}
6.Service层
package com.rtxtitanv.service;/*** @author rtxtitanv* @version 1.0.0* @name com.rtxtitanv.service.SmsService* @description SmsService* @date 2021/6/25 16:20*/
public interface SmsService {/*** 发送短信验证码** @param phoneNumber 手机号* @return*/String sendSmsCode(String phoneNumber);/*** 验证短信验证码** @param phoneNumber 手机号* @param smsCode 短信验证码* @return*/String verifySmsCode(String phoneNumber, String smsCode);
}
package com.rtxtitanv.service.impl;import com.rtxtitanv.config.SmsConfig;
import com.rtxtitanv.service.SmsService;
import com.rtxtitanv.util.RandomUtil;
import com.rtxtitanv.util.RedisUtil;
import com.rtxtitanv.util.SmsUtil;
import com.tencentcloudapi.sms.v20210111.models.SendStatus;
import org.springframework.stereotype.Service;import javax.annotation.Resource;/*** @author rtxtitanv* @version 1.0.0* @name com.rtxtitanv.service.impl.SmsServiceImpl* @description SmsService实现类* @date 2021/6/25 16:20*/
@Service
public class SmsServiceImpl implements SmsService {@Resourceprivate SmsConfig smsConfig;@Resourceprivate RedisUtil redisUtil;@Overridepublic String sendSmsCode(String phoneNumber) {// 下发手机号码,采用e.164标准,+[国家或地区码][手机号]String[] phoneNumbers = {"+86" + phoneNumber};// 生成6位随机数字字符串String smsCode = RandomUtil.randomNumbers(6);// 模板参数:若无模板参数,则设置为空(参数1为随机验证码,参数2为有效时间)String[] templateParams = {smsCode, smsConfig.getExpireTime()};// 发送短信验证码SendStatus[] sendStatuses = SmsUtil.sendSms(smsConfig, templateParams, phoneNumbers);if ("Ok".equals(sendStatuses[0].getCode())) {// 创建缓存的keyString key = RedisUtil.createCacheKey(smsConfig.getPhonePrefix(), phoneNumber);// 将验证码缓存到redis并设置过期时间redisUtil.setCacheObject(key, smsCode, Long.parseLong(smsConfig.getExpireTime()));return "验证码发送成功";} else {return "验证码发送失败:" + sendStatuses[0].getMessage();}}@Overridepublic String verifySmsCode(String phoneNumber, String smsCode) {// 创建keyString key = RedisUtil.createCacheKey(smsConfig.getPhonePrefix(), phoneNumber);// 判断指定key是否存在并且未过期if (redisUtil.hasKey(key)) {// 验证输入的验证码是否正确if (smsCode.equals(redisUtil.getCacheObject(key))) {// 验证成功后删除验证码缓存redisUtil.delete(key);return "验证成功";} else {return "验证码错误";}} else {return "验证码已失效";}}
}
四、腾讯云短信测试
运行项目,使用Postman进行接口测试。
1.发送短信验证码
发送如下POST请求以请求腾讯云短信服务向指定手机号发送短信验证码,请求地址为http://localhost:8080/sms/send
:
Redis客户端查看发现验证码已经存到了Redis中:
手机上也成功收到了验证码,说明发送短信成功:
2.验证短信验证码
发送如下POST请求验证短信验证码,请求地址为http://localhost:8080/sms/verify
,这里将验证码参数smscode
设为不同于之前发送到手机的验证码来模拟验证码输入错误:
再次发送如下POST请求验证短信验证码,这里输入正确的验证码:
Redis客户端刷新发现验证码缓存已经删除:
再次发送如下POST请求验证短信验证码,发现验证码已失效,满足短信验证码验证成功后就失效的业务需求:
代码示例
- Github:https://github.com/RtxTitanV/springboot-learning/tree/master/springboot2.x-learning/springboot-tencent-sms
- Gitee:https://gitee.com/RtxTitanV/springboot-learning/tree/master/springboot2.x-learning/springboot-tencent-sms
SpringBoot2.x 集成 腾讯云短信相关推荐
- 使用springboot集成腾讯云短信服务,解决配置文件读取乱码问题
使用springboot集成腾讯云短信服务,解决配置文件读取乱码问题 参考文章: (1)使用springboot集成腾讯云短信服务,解决配置文件读取乱码问题 (2)https://www.cnblog ...
- springboot+sms 集成腾讯云短信平台
springboot+sms 集成腾讯云短信平台实现发送短信功能 一.申请短信功能 到腾讯云管理平台申请短信功能(https://console.cloud.tencent.com/) 1.1 创建短 ...
- 快速集成腾讯云短信实现短信发送(Spring Boot)
前言 腾讯云活动白嫖 1.地址 地址:https://cloud.tencent.com/act/free?from=14600 2.创建签名(根据实际情况选择) 我的是网站 3.创建模板 选择模板内 ...
- SpringBoot集成腾讯云短信实现注册/登录功能
前言 笔记参考 Duktig丶 JavaSDK地址:短信 Java SDK - SDK 文档 - 文档中心 - 腾讯云 1.导入依赖 <dependency><groupId> ...
- 轻松集成腾讯云短信服务实现短信发送(Java实现)
不论是阿里云还是腾讯云,要想在网站上实现短信发送功能,首先得保证你的网站域名是通过备案的,因为短信签名是需要用到备案过的域名截图,所以域名通过了,申请很快就会审批成功了. (至于备案的话,需要你先购买 ...
- SpringBoot工程接入腾讯云短信服务平台
由于业务需要,需要使用第三方短信平台,进行验证码的发送.网上的短信服务平台主要由:百度.腾讯.阿里云:采用官方提供的SDK,调用接口即可. 腾讯云短信服务平台和阿里云短信服务平台,一般步骤为:注册-- ...
- 接入腾讯云短信服务(史上最详细+该短信服务如何申请成功+发送短信验证码API讲解+相关错误分析)
2021/8/17/23:01{2021/8/17/23:01}2021/8/17/23:01 文章目录 前言 一.如何成功申请到腾讯云短信服务 1.签名申请 2.正文模板申请 二.发送短信API开发 ...
- SpringBoot腾讯云短信实现验证码
SpringBoot腾讯云短信实现验证码 在学习过程中偶然遇见需要实现验证码功能的需求,于是寻思着将功能抽取出来用于分享学习 业务功能:实现验证码60s,且要求防止用户高频刷验证码(即1min一次不多 ...
- 普歌-腾讯云短信+使用node发送短信(3种方法API、SDK)、封装工具、搭建web服务、写接口、调用接口发送短信、时效性判断、验证验证码的正确性(下)
普歌-结合腾讯云短信服务+node搭建一个简单的发送短信web小项目 涉及技术: 腾讯云服务 后端服务:node+express 前端搭建:html+js 前言:本来这篇博客应该很早就发了,中间有一些 ...
- Spring Boot腾讯云短信申请
1.在pom.xml文件中添加依赖 <dependency><groupId>com.tencentcloudapi</groupId><artifactId ...
最新文章
- jQuery中的插件机制
- 人脸特征值能存放在sql server中吗_钥匙丢了进不了门,Out了!只要自己没丢就能进门...
- 分解得到的时频域特征_【推荐文章】基于变分模态分解和广义Warblet变换的齿轮故障诊断...
- Linux系统安全审计工具Lynis
- mysql 数值类型 长度_mysql中的数据类型的长度
- 数据中心布线系统的整体规划
- LiveVideoStackCon 一次全新的尝试,错过了就是一辈子
- Django创建项目后,项目文件夹下的组成部分
- android内置t卡中预制资源,[FAQ17514][Recovery]Recovery mode FAQ搜寻指南
- 好吧,你说简单就简单,但简单的事,不要变成本能,要常思常变
- java.lang.NoClassDefFoundError: org/aopalliance/aop/Advice
- shell中的重定向(21)
- MYSQL 最大连接数设置
- linux更改445端口,windows连接非445端口(nginx转发)的samba服务卡顿
- 抖音短视频怎么吸粉 手把手教你快速抖音养号吸粉引流
- windows 搭建Web服务器和连接局域网打印机
- 如何注册腾讯云个人账号(图文教程)
- 上海跃兔网络科技有限公司简介
- 新式单片机视频教程下载
- spring IOC和DI区别
热门文章
- 小程序服务器装rsshub,RssHub 部署
- amd支持服务器内存,AMD专用内存为什么只能在AMD平台使用?与普通内存有什么区别?...
- 新版标准日本语初级_第四十五课
- 计算摄影 | 摄像机成像原理及参数解析
- 操作系统的概念(定义)
- java判断名字是否为张三_现有5个学生{张三,李四,王五,那六,小七}的数组,输入一个姓名,检查姓名是否存在,如果java啊...
- openlayers学习——13、openlayers比例尺
- 【python】使用python绘制地图时手动添加比例尺
- 保温杯市场前景分析及行业研究报告
- 抖音小程序是什么_如何开发抖音小程序