文章目录
前言
在日常的开发中,我们经常会有发送验证码的需求,这时候就需要借助第三方服务了。腾讯云为我们提供了短信服务,我们只需要在springboot中整合便可。
一、在腾讯云注册短信服务
这里不做过多的介绍,提示:这里如果只是作测试用,那么可以申请一个微信公众号,申请签名会方便很多。
二、具体使用步骤
(1)引入pom文件
<dependency>
<groupId>com.github.qcloudsms</groupId>
<artifactId>qcloudsms</artifactId>
<version>1.0.6</version>
</dependency>
(2)配置yaml文件(短信发送参数)
txsms:
AppId: 0000000000 # 你的系统默认应用SDK AppID
AppKey: "0000000000000000000000000" # 你的系统默认应用App Key
TemplateIdLogin: 00000000 # 登陆正文模板ID
TemplateIdRegister: 00000000 # 注册正文模板ID
signName: "顾娜拉黑暗之神公众号" # 你的签名内容
(3)编写参数配置类
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**腾讯云发送短信
* 参数配置类
* @author: 顾壮壮
* @version:v1.0
* @date: 2023/7/6 14:21
*/
@Data
// 读取application.yml中的txsms的属性
@ConfigurationProperties(prefix = "txsms")
public class TxProperties {
// AppId
private int AppId;
// 短信应用SDK AppKey
private String AppKey;
// 登陆短信模板ID
private int TemplateIdLogin;
// 注册短信模板ID
private int TemplateIdRegister;
// 签名
private String signName;
}
(4)编写TxSmsTemplate类
编写内置功能模板:登录
import com.example.springbootmessage.pojo.SMS;
import com.example.springbootmessage.pojo.TxProperties;
import com.example.springbootmessage.utils.RedisCache;
import com.github.qcloudsms.SmsSingleSender;
import com.github.qcloudsms.SmsSingleSenderResult;
import com.github.qcloudsms.httpclient.HTTPException;
import lombok.extern.slf4j.Slf4j;
import org.json.JSONException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
/**
* @description:腾讯云发送短信模板对象,封装了发送短信的api
* @author: 顾壮壮
* @date: 2023/7/6 14:26
*/
@Slf4j
@Component
public class TxSmsTemplate {
private TxProperties txProperties;
public TxSmsTemplate(TxProperties txProperties) {
this.txProperties = txProperties;
}
//引入redis缓存验证码
@Autowired
private RedisCache redisCache;
/**
* 登陆验证
* @param phoneNumber 手机号
* @param code 验证码
* @return
*/
public boolean loginSmsSend(String phoneNumber,String code){
try {
// 模板参数
String[] params = {code};
// 构建短信发送器
SmsSingleSender ssender = new SmsSingleSender(txProperties.getAppId(), txProperties.getAppKey());
//sendWithParm: 传入国家码 电话号码 模板id 模板参数 签名 扩展码为空 返回参数为空
SmsSingleSenderResult result = ssender.sendWithParam("86", phoneNumber,
txProperties.getTemplateIdLogin(), params, txProperties.getSignName(), "", ""); // 签名参数未提供或者为空时,会使用默认签名发送短信
if(result.result==0){
//将登陆的手机号存入redis中
redisCache.setCacheObject("loginPhone",new SMS(phoneNumber,code),5, TimeUnit.MINUTES);
return true;
}else{
System.out.println("短信发送失败,原因:"+result.errMsg);
}
} catch (HTTPException e) {
// HTTP响应码错误
log.info("短信发送失败,HTTP响应码错误!");
// e.printStackTrace();
} catch (JSONException e) {
// json解析错误
log.info("短信发送失败,json解析错误!");
//e.printStackTrace();
} catch (IOException e) {
// 网络IO错误
log.info("短信发送失败,网络IO错误!");
// e.printStackTrace();
}
return false;
}
}
- 其中封装了一个SMS pojo类用于存储电话号码和验证码
- 还封装了一个redis工具类RedisCache
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* @description:封装一个实体类对象用于存储电话号码和验证码
* @author: 顾壮壮
* @date: 2023/7/6 15:14
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class SMS implements Serializable {
//存入的电话号码
private String phone;
//存入redis的验证码
private String code;
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundSetOperations;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
* spring redis 工具类
*
* @author ruoyi
**/
@SuppressWarnings(value = {"unchecked", "rawtypes"})
@Component
public class RedisCache {
@Autowired
public RedisTemplate redisTemplate;
/**
* 缓存基本的对象,Integer、String、实体类等
*
* @param key 缓存的键值
* @param value 缓存的值
* @param timeout 时间
* @param timeUnit 时间颗粒度
*/
public <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit) {
redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
}
/**
* 设置有效时间
*
* @param key Redis键
* @param timeout 超时时间
* @param unit 时间单位
* @return true=设置成功;false=设置失败
*/
public boolean expire(final String key, final long timeout, final TimeUnit unit) {
return redisTemplate.expire(key, timeout, unit);
}
/**
* 获得缓存的基本对象。
*
* @param key 缓存键值
* @return 缓存键值对应的数据
*/
public <T> T getCacheObject(final String key) {
ValueOperations<String, T> operation = redisTemplate.opsForValue();
return operation.get(key);
}
}
(5)编写配置类
目的是将TxSmsTemplate模板类和TxProperties实体类注入容器中,交给springboot管理,这样,也是为了使yaml配置文件的数据赋值到TxProperties实体类,使模板类可以使用数据
import com.example.springbootmessage.pojo.TxProperties;
import com.example.springbootmessage.service.TxSmsTemplate;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 自动配置类
* 配置工具类 template
*/
@Configuration
@EnableConfigurationProperties({TxProperties.class})
public class CommonsAutoConfiguration {
/*
* @description:创建发送短信的工具类将TxProperties对象注入到容器中
* @author: 顾壮壮
* @date: 2023/7/6 14:29
* @param txProperties
* @return: com.example.springbootmessage.service.TxSmsTemplate
*/
//这里其实有可以不用@Bean注入容器,直接在TxProperties类和TxSmsTemplate类上标注@Component注解,
//直接便可以注入容器中,我这里使用有参构造,将TxProperties和TxSmsTemplate都注入到容器中
@Bean
public TxSmsTemplate txSmsTemplate(TxProperties txProperties) {
return new TxSmsTemplate(txProperties);
}
}
三、测试
@Slf4j
@SpringBootTest
class SpringbootMessageApplicationTests { ;
@Autowired
private TxSmsTemplate txSmsTemplate;
@Autowired
private RedisCache redisCache;
/**
* 腾讯云发送短信测试
*/
@Test
public void TxSmsTest(){
boolean Msg = txSmsTemplate.loginSmsSend("测试的电话号码", ValidateCodeUtils.generateValidateCode(6));
//返回true 或者 false
System.out.println(Msg);
//取出验证码
Object loginPhone = redisCache.getCacheObject("loginPhone");
SMS sms=new ObjectMapper().convertValue(loginPhone, SMS.class);
//判断是否超过了五分钟,超过返回null
if (sms!=null)System.out.println(sms.getCode());
else log.info("loginPhone对象不存在或超过了五分钟!");
}
}
这里编写了一个ValidateCodeUtils类,用于随机生成验证码
import java.util.Random;
/**
* @description:
* @author: 顾壮壮
* @date: 2023/6/29 14:59
*/
public class ValidateCodeUtils {
/**
* 随机生成验证码
* @param length 长度为4位或者6位
* @return
*/
public static String generateValidateCode(int length){
Integer code =null;
// 长度为4
if(length == 4){
code = new Random().nextInt(9999);//生成随机数,最大为9999
if(code < 1000){
code = code + 1000;//保证随机数为4位数字
}
// 长度为6
}else if(length == 6){
code = new Random().nextInt(999999);//生成随机数,最大为999999
if(code < 100000){
code = code + 100000;//保证随机数为6位数字
}
// 其他情况
}else{
throw new RuntimeException("只能生成4位或6位数字验证码");
}
return Integer.toString(code);
}
/**
* 随机生成指定长度字符串验证码
* @param length 长度
* @return
*/
public static String generateValidateCode4String(int length){
Random rdm = new Random();
String hash1 = Integer.toHexString(rdm.nextInt());
String capstr = hash1.substring(0, length);
return capstr;
}
}
总结
本篇文章是个人对使用腾讯云短信的总结,之前走过一点弯路,希望大家看完这篇文章,不会走错路,谢谢。