文章目录
前言
一、发送验证码的使用
短信发送是电信运营商提供的服务,需要访问对应的接口,不同运营商提供的接口地址肯定不一样,如果直接访问这些接口就需要判断收信息的手机号属于哪个运营商,关键在于这些接口不对个人开放,还要考虑调用短信服务的费用问题
因此目前调用短信业务都是使用第三方企业的短信服务,他们与运营商合作,封装了短信接口,调用方法,而且费用相对便宜
短信服务(推荐)
注册购买
第一步:云市场搜索短信服务
点击购买,有5条免费使用,测试也会消耗使用次数,用完了在付费购买即可
找到自己购买的云服务
可以看到已购买的服务
这里有几项重要信息:AppKey AppSecret AppCode 调用购买的这个短信服务接口时候需要用到,用于确认使用者身份
接口 : 调用该服务时访问的接口
参考API,编写发送短信工具类
import cn.hutool.http.Header;
import cn.hutool.http.HttpRequest;
import java.util.HashMap;
import java.util.Map;
/**
* 测试短信
*/
public class SmsUtilTest {
public static void main(String[] args) {
//手机号码
String mobile = "";
//验证码
String code = "";
//签名ID。(联系客服申请。测试请用:2e65b1bb3d054466b82f0c9d125465e2)
String smsSignId="";
//模板ID。(联系客服申请。测试ID请用:908e94ccf08b4476ba6c876d13f084ad,短信内容为 { 验证码:**code**,**minute**分钟内有效,请勿泄漏于他人!})
String templateId="";
//应用code https://market.console.aliyun.com/imageconsole/index.htm?#/bizlist?_k=r5f9m0 查找
String appCode="";
//请求连接
String host = "https://gyytz.market.alicloudapi.com/sms/smsSend";
//拼装请求体
Map<String, Object> querys = new HashMap<String, Object>();
querys.put("mobile", mobile);
querys.put("param", "**code**:"+code+",**minute**:5");
querys.put("smsSignId", smsSignId);
querys.put("templateId", templateId);
try {
String result = HttpRequest.post(host)
.header(Header.AUTHORIZATION, "APPCODE " + appCode)//头信息,多个头信息多次调用此方法即可
.form(querys)//表单内容
.timeout(20000)//超时,毫秒
.execute().body();
System.out.println(result);
} catch (Exception e) {
e.printStackTrace();
}
}
}
二、实例
前端Vue
<template>
<div style="text-align:left">
用户名:<input type="text" class="txt" v-model="user.username" name="username" />3-20位字符,可由中文、字母、数字和下划线组成<br>
密码 :<input type="password" class="txt" name="password" v-model="user.password"/>6-20位字符,可使用字母、数字和符号的组合,不建议使用纯数字、纯字母、纯符号<br>
确认密码:<input type="password" class="txt" name="password" v-model="user.repassword"/><br>
手机号码:<input type="text" class="txt" name="mobile" v-model="user.mobile" />
<button @click.prevent="sendSMS" :disabled="smsBtnDisabled">点击发送短信验证码<span v-if="smsBtnDisabled">{{second}}秒</span></button>
<br>
验证码:<input type="text" name="user.code" v-model="user.code"/><br>
<input type="submit" value="注册" @click="regist()"/>
</div>
</template>
<script>
export default {
data() {
return {
user:{},
smsBtnDisabled:false,// true 禁用按钮 false不禁用
second:5,//倒计时秒数
timer:null//倒计时对象
}
},
methods: {
async sendSMS(){
let res = await this.$http.get("http://localhost:10010/user/sendSms?phone="+this.user.mobile)
// let res = await this.$http.get("/user/sendSms",{params:user.mobile})
if(res.data.code==0){
//发送成功
alert("发送成功")
//按钮禁用
this.smsBtnDisabled = true
//倒计时:每个1s执行某个函数
this.timer = setInterval(this.daojishi,1000)
}
},
daojishi(){
//如果second大于0,那second--
//否则停止倒计时,按钮生效
if(this.second>0){
this.second--
}else{
//停止倒计时
clearInterval(this.timer)
//恢复秒数。给下次使用
this.second=5
//按钮恢复
this.smsBtnDisabled = false
}
},
async regist(){
try {
let res = await this.$http.post("http://localhost:10010/user/reg",this.user)
if(res.data.code==0){
alert("注册成功")
console.log(res)
this.$router.push("登录页")
}else{
alert("注册失败")
}
}catch (error) {
alert("res.msg")
}
}
},
}
</script>
后端
启动类
UserController
@RestController
@RequestMapping("/user")
public class UserController {
// @Autowired
// private HttpServletRequest request;
@Autowired
private RabbitTemplate rabbitTemplate;
// RabbitTemplate rabbitTemplate;
@Autowired
private StringRedisTemplate redisTemplate;
@PostMapping
public BaseResult addUser(@RequestBody User user,
@RequestHeader("Authorization") String authorization){
// String token = request.getHeader("authorization");
Claims claims = JWTUtil.parseToken(authorization, "user");
Object userId = claims.get("userId");
System.out.println("新增的用户信息:"+user);
return BaseResult.success(null);
}
/**
* 1 产生随机码6位
* 2 保存到rabbitMQ中
* 3 保存到redis中
* 4 返回发送成功
* @param phone
* @return
*/
//
@GetMapping("/sendSms")
public BaseResult sendSMS(String phone){
// 1 产生随机码6位
String code = RandomUtil.code();
//拼接消息内容
String msg = phone + "%%%%%%" + code;
// 2 保存到rabbitMQ中
rabbitTemplate.convertAndSend("sms.queue",msg);
// 3 保存到redis中
redisTemplate.opsForValue().set(phone,code,1, TimeUnit.MINUTES);
// 4 返回发送成功
return BaseResult.success("成功");
}
@PostMapping("/reg")
public BaseResult reg(@RequestBody User user){
String s2 = user.getMobile();
String s = redisTemplate.opsForValue().get(s2);
System.out.println(s);
if (s==null){
return BaseResult.fail();
}
if (user.getCode().equals(s)){
System.out.println("注册成功,"+user);
redisTemplate.delete(user.getMobile());
return BaseResult.success("成功"+user);
}
return BaseResult.fail();
}
}
配置文件bootstrap.yaml
spring:
datasource:
url: jdbc:mysql://localhost/数据库表名?useSSL=false
username: 账户名
password: 密码
driver-class-name: com.mysql.jdbc.Driver
application:
//服务名
name: userservice
profiles:
active: dev
cloud:
nacos:
server-addr: localhost:8848
config:
file-extension: yaml
# rabbitmq:
# host:# 主机名
# port: 5672 # 端口
# virtual-host: / # 虚拟主机
# username: # 用户名
# password: # 密码
redis:
host: localhost
port: 6379
database: 0
jedis:
pool:
max-idle: 8
min-idle: 0
max-active: 8
server:
port: 8000
SmsListener同步redis中的值
@Component
public class SmsListener {
@RabbitListener(queues = "sms.queue")
public void listenerWorkQueue1(String msg) throws Exception{
String[] vals = msg.split("%%%%%%");
//这里调用短信接口
AliyunSendSmsUtil.send(vals[0],vals[1]);
System.out.println("sms接收到的消息:【"+msg+"】发送成功");
}
}
短信接口类
public class AliyunSendSmsUtil {
/**
*
* @param to 手机号码
* @param code 验证码
*/
public static void send(String to, String code) {
String accessKeyId="";
String accessSecret = "";
DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessSecret);
IAcsClient client = new DefaultAcsClient(profile);
CommonRequest request = new CommonRequest();
request.setSysMethod(MethodType.POST);
request.setSysDomain("dysmsapi.aliyuncs.com");
request.setSysVersion("2017-05-25");
request.setSysAction("SendSms");
request.putQueryParameter("RegionId", "cn-hangzhou");
request.putQueryParameter("PhoneNumbers", to);
request.putQueryParameter("SignName", "");
request.putQueryParameter("TemplateCode", "SMS_85550034");
request.putQueryParameter("TemplateParam", "{\"code\":\""+code+"\"}");
try {
CommonResponse response = client.getCommonResponse(request);
System.out.println(response.getData());
} catch (ServerException e) {
e.printStackTrace();
} catch (ClientException e) {
e.printStackTrace();
}
}
}
启动类
@SpringBootApplication
public class SmsConsumerApplication {
@Bean
public Queue createSmsQueue(){
return new Queue("sms.queue");
}
public static void main(String[] args) {
SpringApplication.run(SmsConsumerApplication.class, args);
}
}
配置文件application.yml
server:
port: 20000
spring:
rabbitmq:
host: # 主机名
port: 5672 # 端口
virtual-host: / # 虚拟主机
username: # 用户名
password: # 密码
2.项目结构及pom
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.example</groupId>
<artifactId>jwt-common03</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--nacos配置管理依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!--AMQP依赖,包含RabbitMQ-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
</dependencies>