一、腾讯云短信简介
腾讯云短信(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;
@ConfigurationProperties(prefix = "tencent.sms")
@Configuration
@Data
public class SmsConfig {
private String secretId;
private String secretKey;
private String appId;
private String sign;
private String templateId;
private String expireTime;
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;
@Configuration
public class RedisConfig {
@Resource
private RedisConnectionFactory redisConnectionFactory;
@Bean
public RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
initRedisTemplate(redisTemplate, redisConnectionFactory);
return redisTemplate;
}
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.1
port: 6379
# 自定义腾讯云短信配置
tencent:
sms:
# 配置腾讯云API密钥的SecretId
secretId: 这里填腾讯云API密钥的SecretId
# 配置腾讯云API密钥的SecretKey
secretKey: 这里填腾讯云API密钥的SecretKey
# 配置短信应用的SDKAppID
appId: 这里填短信应用的SDKAppID
# 配置签名内容
sign: "这里填签名内容"
# 配置模板ID
templateId: 这里填模板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;
public class SmsUtil {
private static final Logger LOGGER = LoggerFactory.getLogger(SmsUtil.class);
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在[短信控制台]添加应用后生成的实际SdkAppId
req.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;
@Component
public class RedisUtil {
@Resource
private RedisTemplate<String, Object> redisTemplate;
public void setCacheObject(String key, Object value, long expire) {
redisTemplate.opsForValue().set(key, value);
if (expire > 0) {
redisTemplate.expire(key, expire, TimeUnit.MINUTES);
}
}
public Object getCacheObject(String key) {
return redisTemplate.opsForValue().get(key);
}
public boolean hasKey(String key) {
return redisTemplate.hasKey(key) && getExpire(key) > 0 ? true : false;
}
public long getExpire(String key) {
return redisTemplate.getExpire(key, TimeUnit.MINUTES);
}
public void delete(String key) {
redisTemplate.delete(key);
}
public static String createCacheKey(String prefix, String phoneNumber) {
return prefix + phoneNumber;
}
}
用于生成随机验证码的工具类:
package com.rtxtitanv.util;
import java.util.Random;
public class RandomUtil {
private static final Random RANDOM = new Random();
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;
@RequestMapping("/sms")
@RestController
public class SmsController {
@Resource
private 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;
public interface SmsService {
String sendSmsCode(String phoneNumber);
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;
@Service
public class SmsServiceImpl implements SmsService {
@Resource
private SmsConfig smsConfig;
@Resource
private RedisUtil redisUtil;
@Override
public 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())) {
// 创建缓存的key
String key = RedisUtil.createCacheKey(smsConfig.getPhonePrefix(), phoneNumber);
// 将验证码缓存到redis并设置过期时间
redisUtil.setCacheObject(key, smsCode, Long.parseLong(smsConfig.getExpireTime()));
return "验证码发送成功";
} else {
return "验证码发送失败:" + sendStatuses[0].getMessage();
}
}
@Override
public String verifySmsCode(String phoneNumber, String smsCode) {
// 创建key
String 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腾讯云短信内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!