文章目录
准备阶段
获取secretId
和secretKey
获取签名内容(signName)
获取模板id(templateId)
获取应用id(smsSdkAppId)
代码阶段
该项目所用的依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.tencentcloudapi</groupId>
<artifactId>tencentcloud-sdk-java</artifactId>
<version>3.1.390</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>com.github.penggle</groupId>
<artifactId>kaptcha</artifactId>
<version>2.3.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
yaml
# 腾讯云
tencent:
sms:
account:
secretId: 你的秘钥id
secretKey: 你的秘钥密码
smsSdkAppId: 你的应用id
templateId: 你的模板id
signName: 你的签名内容
spring:
redis:
host: localhost
port: 6379
database: 0
TencentSmsProperties
获取yaml中的配置
@Data
@Configuration
@ConfigurationProperties(prefix = "tencent.sms.account")
public class TencentSmsProperties {
private String secretId;
private String secretKey;
private String smsSdkAppId;
private String templateId;
private String signName;
}
SmsConfig
@Configuration
public class SmsConfig {
private static String URL ="sms.tencentcloudapi.com";
private static final String REGION = "ap-guangzhou";
@Autowired
private TencentSmsProperties tencentSmsProperties;
@Bean
public SmsClient smsClient(){
Credential credential = new Credential(tencentSmsProperties.getSecretId(),tencentSmsProperties.getSecretKey());
HttpProfile httpProfile = new HttpProfile();
httpProfile.setReqMethod("POST");
httpProfile.setConnTimeout(60);
httpProfile.setEndpoint(URL);
// 实例化一个client选项,可选的,没有特殊需求可以跳过
ClientProfile clientProfile = new ClientProfile();
clientProfile.setSignMethod("HmacSHA256");
clientProfile.setHttpProfile(httpProfile);
//实例化 SMS 的 client 对象
return new SmsClient(credential, REGION, clientProfile);
}
}
RedisConfig
将验证码缓存到中间件
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory connectionFactory){
RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
//- 配置连接工厂
redisTemplate.setConnectionFactory(connectionFactory);
//- 使用Jackson2JsonRedisSerializer实现序列化以及反序列化
Jackson2JsonRedisSerializer jsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
//添加自定义序列化和反序列化机制
//SimpleModule simpleModule = new SimpleModule();
//simpleModule.addSerializer(DateTime.class,new JodaDateTime2JsonSerializer());
//simpleModule.addDeserializer(DateTime.class,new JodaDateTime2JsonDeserializer());
//objectMapper.registerModule(simpleModule);
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
//会生成字段类的信息
//objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,ObjectMapper.DefaultTyping.NON_FINAL);
jsonRedisSerializer.setObjectMapper(objectMapper);
//将String类型的key和value序列化
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(jsonRedisSerializer);
//将Hash类型的hashKey和hashValue序列化
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(jsonRedisSerializer);
return redisTemplate;
}
}
KaptchaConfig
生成验证码
@Configuration
public class KaptchaConfig {
@Bean
Producer producer(){
Properties properties = new Properties();
properties.setProperty("kapcha.image.width","150");
properties.setProperty("kapcha.image.height","50");
//文本集合,验证码值从此集合中获取
properties.setProperty("kaptcha.textproducer.char.string", "0123456789");
//验证码长度
properties.setProperty("kaptcha.textproducer.char.length", "4");
Config config = new Config(properties);
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
defaultKaptcha.setConfig(config);
return defaultKaptcha;
}
}
service层
public interface SmsService {
String sendSms(String phone);
boolean validateCode(String phone,String code);
}
System.out.println(response.getSendStatusSet()[0].getCode());
如果报错注意看报错的原因。
在页面ctrl+f
搜索你报错的code
我遇到两个坑:
@Service
@Slf4j
public class SmsServiceImpl implements SmsService{
@Autowired
private TencentSmsProperties smsProperties;
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private Producer producer;
@Autowired
private SmsClient smsClient;
@Override
public String sendSms(String phone) {
String[] phoneNumberSet = {"+86"+phone};
//生成随机验证码
String code = producer.createText();
//将code添加到参数数组(取决于你的短信模板有多少个参数),验证码只能纯数字
String[] templateParamSet = {code,"5"};
//实例请求,组装参数
SendSmsRequest req = new SendSmsRequest();
req.setTemplateID(smsProperties.getTemplateId());
req.setSmsSdkAppid(smsProperties.getSmsSdkAppId());
req.setSign(smsProperties.getSignName());
//yaml文件读取中文会乱码
//req.setSign("个人学习记录");
//发送的手机号
req.setPhoneNumberSet(phoneNumberSet);
//发送的内容(验证码)
req.setTemplateParamSet(templateParamSet);
try {
//发送短信
SendSmsResponse response = smsClient.SendSms(req);
// 输出json格式的字符串回包
System.out.println(SendSmsResponse.toJsonString(response));
// 也可以取出单个值,你可以通过官网接口文档或跳转到response对象的定义处查看返回字段的定义
System.out.println(response.getSendStatusSet()[0].getCode());
//存入redis
redisTemplate.opsForValue().set(phone,code,5, TimeUnit.MINUTES);
return "OK";
} catch (TencentCloudSDKException e) {
log.error("发送失败,或者剩余短信数量不足", e);
}
return "发送失败,或者剩余短信数量不足";
}
@Override
public boolean validateCode(String phone, String code) {
String data = (String) redisTemplate.opsForValue().get(phone);
return code.equals(data);
}
}
controller层
@RestController
@RequestMapping("/sms")
public class SmsController {
@Autowired
private SmsService smsService;
@GetMapping("/send")
public String sendSms(String phone){
return smsService.sendSms(phone);
}
@GetMapping("/validate")
public String validate(String phone,String code){
if (smsService.validateCode(phone, code)){
return "验证码正确";
}
return "验证码错误";
}
}