申请短信服务
我使用的是阿里云的短信服务,然后就可以获得这两个值:
引入依赖
这个依赖包含一个短信服务客户端Client:
<!--阿里云短信服务-->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>dysmsapi20170525</artifactId>
<version>2.0.1</version>
</dependency>
将客户端Client整合到SpringBoot中【灵魂】
客户端自动配置类
/**
* @Author: xiang
* @Date: 2021/4/29 16:58
*
* 短信访问客户端
*/
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(SmsProperties.class) //指对应的明属性配置类
@AutoConfigureAfter(RedisAutoConfiguration.class) //短信功能依赖redis
public class SmsAutoConfiguration {
//短信客户端属性配置类
private final SmsProperties properties;
//从容器中拿到属性配置类
public SmsAutoConfiguration(SmsProperties properties) {
this.properties = properties;
}
/**
* 阿里云短信访问客户端对象注入IOC容器
* @return
* @throws Exception
*/
@Bean
public Client getSmsClient() throws Exception {
Config config = new Config()
.setAccessKeyId(properties.getAccessKeyId())
.setAccessKeySecret(properties.getAccessKeySecret());
// 访问的域名
config.endpoint = properties.getEndpoint();
return new Client(config);
}
}
自动配置类的属性类
/**
* @Author: xiang
* @Date: 2021/4/29 17:07
*
* 短信访问客户端属性配置类
*/
@ConfigurationProperties(prefix = "spring.redis.sms")
public class SmsProperties {
private String accessKeyId;
private String accessKeySecret;
// 短信发送请求访问的域名
private String endpoint = "dysmsapi.aliyuncs.com";
public String getAccessKeyId() {
return accessKeyId;
}
public void setAccessKeyId(String accessKeyId) {
this.accessKeyId = accessKeyId;
}
public String getAccessKeySecret() {
return accessKeySecret;
}
public void setAccessKeySecret(String accessKeySecret) {
this.accessKeySecret = accessKeySecret;
}
public String getEndpoint() {
return endpoint;
}
public void setEndpoint(String endpoint) {
this.endpoint = endpoint;
}
}
属性文件配置
以后直接属性配置文件中配置申请的AccessKeyId与AccessKeySecret就行
阿里云短信通知配置
spring:
redis:
sms:
access-key-id: xxxxxxxxxxxxxx #AccessKeyId
access-key-secret: yyyyyyyyyyyyyyyyyyyyyyy #AccessKeySecret
注: (想让属性配置文件有自定义属性配置类的提示就得引用依赖)
<!--自定义配置文件提示-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
实战使用
/**
* @Author: xiang
* @Date: 2021/4/28 13:35
*/
@RestController
public class PhoneCodeController {
//redis操作模板
private RedisTemplate redisTemplate;
//短信发送客户端
private Client smsClient;
@Autowired
public void setRedisTemplate(RedisTemplate redisTemplate) {
this.redisTemplate = redisTemplate;
}
@Autowired
public void setSmsClient(Client smsClient) {
this.smsClient = smsClient;
}
//发送验证码
@GetMapping("/phone")
public String sendPhoneCode(@RequestParam("phone") String phone) throws Exception {
//生成验证码
int code = (int)((Math.random() * 9 + 1) * 100000);
//同一个电话一天最多发送5次
//保存验证次数
String countKey = "verifyCode"+phone+":count";
Integer count = (Integer) redisTemplate.opsForValue().get(countKey);
if (count == null){
redisTemplate.opsForValue().set(countKey,1,1, TimeUnit.DAYS);
} else if (count < 6){
redisTemplate.opsForValue().increment(countKey);
}else {
return "今天验证次数已用完";
}
//阿里云短信服务发送短信
String resultCode = sendCode(phone, code);
if ("OK".equals(resultCode)){
//保存验证码(两分钟有效时间)
String codeKey = "verifyCode"+phone+":code";
redisTemplate.opsForValue().set(codeKey,code,2,TimeUnit.MINUTES);
return "发送成功";
}
return "发送失败";
}
//验证
@GetMapping("/phoneCode")
public Boolean verifyCode(@RequestParam("phone") String phone,@RequestParam("code") Integer code){
String codeKey = "verifyCode"+phone+":code";
Integer result = (Integer) redisTemplate.opsForValue().get(codeKey);
if (result.equals(code)) return true;
return false;//会直接返回错误页面
}
private String sendCode(String phone,int code) throws Exception {
SendSmsRequest smsRequest = new SendSmsRequest()
.setPhoneNumbers(phone)
.setSignName("[测试专用]阿里云通信")
.setTemplateCode("[测试专用]阿里云通信测试模版")
.setTemplateParam("{\"code\":"+code+"}"); //需要json样式
//发送请求
SendSmsResponse smsResponse = smsClient.sendSms(smsRequest);
//返回请求状态码
return smsResponse.body.code;
}
}