网站中接入手机验证码和定时任务(含源码)

这篇具有很好参考价值的文章主要介绍了网站中接入手机验证码和定时任务(含源码)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

页面预览

绑定手机号

未绑定手机号

已绑定手机号

第01章-短信发送

1、云市场-短信API

1.1、开通三网106短信

在阿里云云市场搜索“短信”,一般都可用,选择一个即可,例如如下:点击“立即购买”开通

这里开通的是【短信验证码- 快速报备签名】

1.2、获取开发参数

登录云市场控制台,在已购买的服务中可以查看到所有购买成功的API商品情况,下图红框中的就是AppKey/AppSecret,AppCode的信息。

1.3、API方式使用云市场服务

将工具类放入service-yun微服务的utils包中:资料:资料>短信发送>工具类

参考如下例子,复制代码在test目录进行测试

2、发送短息

2.1、Controller

创建FrontSmsController

package com.atguigu.syt.yun.controller.front;

@Api(tags = "短信接口")
@RestController
@RequestMapping("/front/yun/sms")
public class FrontSmsController {

    @Resource
    private SmsService smsService;

    @Resource
    private RedisTemplate redisTemplate;

    @ApiOperation("发送短信")
    @ApiImplicitParam(name = "phone",value = "手机号")
    @PostMapping("/send/{phone}")
    public Result send(@PathVariable String phone) {

        //生成验证码
        int minutes = 5; //验证码5分钟有效
        String code = RandomUtil.getFourBitRandom();

        //创建短信发送对象
        SmsVo smsVo = new SmsVo();
        smsVo.setPhone(phone);
        smsVo.setTemplateCode("CST_qozfh101");
        Map<String,Object> paramsMap = new HashMap<String, Object>(){{
            put("code", code);
            put("expire_at", 5);
        }};
        smsVo.setParam(paramsMap);

        //发送短信
        smsService.send(smsVo);

        //验证码存入redis
        redisTemplate.opsForValue().set("code:" + phone, code, minutes, TimeUnit.MINUTES);

        return Result.ok().message("短信发送成功");
    }
}

2.2、Service

接口:SmsService

package com.atguigu.syt.yun.service;

public interface SmsService {
    /**
     * 发送短信
     * @param smsVo
     */
    void send(SmsVo smsVo);
}

实现:SmsServiceImpl

package com.atguigu.syt.yun.service.impl;

@Service
@Slf4j
public class SmsServiceImpl implements SmsService {

    @Override
    public void send(SmsVo smsVo) {

        String host = "https://dfsns.market.alicloudapi.com";
        String path = "/data/send_sms";
        String method = "POST";
        String appcode = "你的appcode";
        Map<String, String> headers = new HashMap<>();
        //最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105
        headers.put("Authorization", "APPCODE " + appcode);
        //根据API的要求,定义相对应的Content-Type
        headers.put("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
        Map<String, String> querys = new HashMap<>();
        Map<String, String> bodys = new HashMap<>();

        StringBuffer contentBuffer = new StringBuffer();
        smsVo.getParam().entrySet().forEach( item -> {
            contentBuffer.append(item.getKey()).append(":").append(item.getValue()).append(",");
        });
        String content = contentBuffer.substring(0, contentBuffer.length() - 1);

        bodys.put("content", content);
        bodys.put("phone_number", smsVo.getPhone());
        bodys.put("template_id", smsVo.getTemplateCode());

        try {
            /**
             * 重要提示如下:
             * HttpUtils请从
             * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/src/main/java/com/aliyun/api/gateway/demo/util/HttpUtils.java
             * 下载
             *
             * 相应的依赖请参照
             * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/pom.xml
             */
            HttpResponse response = HttpUtils.doPost(host, path, method, headers, querys, bodys);

            //获取response的body
            String data = EntityUtils.toString(response.getEntity());

            HashMap<String, String> resultMap = JSONObject.parseObject(data, HashMap.class);
            String status = resultMap.get("status");

            if(!"OK".equals(status)){
                String reason = resultMap.get("reason");
                log.error("短信发送失败:status = " + status + ", reason = " + reason);
                throw new GuiguException(ResultCodeEnum.FAIL.getCode(), "短信发送失败");
            }

        } catch (Exception e) {
            log.error(ExceptionUtils.getStackTrace(e));
            throw new GuiguException(ResultCodeEnum.FAIL.getCode(), "短信发送失败");
        }
    }
}

3、绑定手机号

3.1、Controller

service-user微服务FrontUserInfoController中添加接口方法

@ApiOperation("绑定手机号")
@ApiImplicitParams({
    @ApiImplicitParam(name = "phone",value = "手机号", required = true),
    @ApiImplicitParam(name = "code",value = "验证码", required = true)})
@PostMapping("/auth/bindPhone/{phone}/{code}")
public Result bindPhone(@PathVariable String phone, @PathVariable String code, HttpServletRequest request, HttpServletResponse response) {

    Long userId = authContextHolder.checkAuth(request, resposne);
    userInfoService.bindPhone(userId, phone, code);
    return Result.ok().message("绑定成功");
}

3.2、Service

接口:UserInfoService

/**
     * 绑定当前用户的手机号
     * @param userId
     * @param phone
     * @param code
     */
void bindPhone(Long userId, String phone, String code);

实现:UserInfoServiceImpl

@Resource
private RedisTemplate redisTemplate;

@Override
public void bindPhone(Long userId, String phone, String code) {

    //校验参数
    if(StringUtils.isEmpty(phone) || StringUtils.isEmpty(code)) {
        throw new GuiguException(ResultCodeEnum.PARAM_ERROR);
    }

    //校验验证码
    String phoneCode = (String)redisTemplate.opsForValue().get("code:" + phone);
    if(!code.equals(phoneCode)) {
        throw new GuiguException(ResultCodeEnum.CODE_ERROR);
    }

    //根据手机号查找会员
    LambdaQueryWrapper<UserInfo> queryWrapper = new LambdaQueryWrapper<>();
    //手机号没有被其他人绑定过
    queryWrapper.eq(UserInfo::getPhone, phone).ne(UserInfo::getId, userId);
    UserInfo userInfo = baseMapper.selectOne(queryWrapper);

    //手机号已存在
    if(userInfo != null) {
        throw new GuiguException(ResultCodeEnum.REGISTER_MOBILE_ERROR);
    }
    //设置绑定手机号
    userInfo = new UserInfo();
    userInfo.setId(userId);
    userInfo.setPhone(phone);
    baseMapper.updateById(userInfo);
}

4、前端整合

4.1、api

创建sms.js

import request from '~/utils/request'

export default {

  sendCode(phone) {
    return request({
      url: `/front/yun/sms/send/${phone}`,
      method: `post`
    })
  }
}

在userInfo.js中添加方法

bindPhone(phone, code) {
    return request({
        url: `/front/user/userInfo/auth/bindPhone/${phone}/${code}`,
        method: `post`
    })
},

4.2、页面组件

复制页面到项目pages目录中

资料:资料>手机号绑定页面

第02章-引入MQ

预约或取消预约成功后我们要 更新预约数 以及 发送短信提醒,为了实现用户下单和取消订单的快速响应,这部分逻辑我们就交给MQ完成。

1、引入RabbitMQ

1.1、安装RabbitMQ

#拉取镜像
docker pull rabbitmq:3.8-management
#创建容器启动
docker run -d --restart=always -p 5672:5672 -p 15672:15672 --name rabbitmq rabbitmq:3.8-management

1.2、访问管理后台

http://192.168.100.101:15672

登录:guest / guest

1.3、创建rabbit-utils模块

在common模块中创建rabbit-utils模块

1.4、引入依赖

在rabbit-utils中引入依赖

<dependencies>
    <!--rabbitmq消息队列-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-amqp</artifactId>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
</dependencies>

1.5、创建RabbitService类

添加sendMessage方法

package com.atguigu.syt.rabbit;

@Service
@Slf4j
public class RabbitService {

    @Resource
    private RabbitTemplate rabbitTemplate;
    
    /**
     *  发送消息
     * @param exchange 交换机
     * @param routingKey 路由
     * @param message 消息
     */
    public boolean sendMessage(String exchange, String routingKey, Object message) {
        log.info("发送消息...........");
        rabbitTemplate.convertAndSend(exchange, routingKey, message);
        return true;
    }
}

1.6、配置MQ消息转换器

package com.atguigu.syt.rabbit.config;

@Configuration
public class MQConfig {

    @Bean
    public MessageConverter messageConverter(){
        //配置json字符串转换器,默认使用SimpleMessageConverter
        return new Jackson2JsonMessageConverter();
    }
}

1.7、添加常量类

package com.atguigu.syt.rabbit.config;
public class MQConst {

    /**
     * 预约/取消订单
     */
    public static final String EXCHANGE_DIRECT_ORDER = "exchange.direct.order";
    public static final String ROUTING_ORDER = "routing.order";
    public static final String QUEUE_ORDER  = "queue.order";

    /**
     * 短信
     */
    public static final String EXCHANGE_DIRECT_SMS = "exchange.direct.sms";
    public static final String ROUTING_SMS = "routing.sms";
    public static final String QUEUE_SMS  = "queue.sms";
}

2、service-yun中发送短信

2.1、引入依赖

<!--MQ-->
<dependency>
    <groupId>com.atguigu</groupId>
    <artifactId>rabbit-utils</artifactId>
    <version>1.0</version>
</dependency>

2.2、添加MQ配置

spring:
  rabbitmq:
    host: 192.168.100.101
    port: 5672
    username: guest
    password: guest

2.3、封装MQ监听器

在监听器中发送短信:

package com.atguigu.syt.yun.receiver;

@Component
@Slf4j
public class SmsReceiver {

    @Resource
    private SmsService smsService;

    /**
     * 监听MQ中的消息
     * @param smsVo
     */
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MQConst.QUEUE_SMS, durable = "true"), //消息队列,并持久化
            exchange = @Exchange(value = MQConst.EXCHANGE_DIRECT_SMS), //交换机
            key = {MQConst.ROUTING_SMS} //路由
    ))
    public void receive(SmsVo smsVo){
        log.info("SmsReceiver 监听器监听到消息......");
        smsService.send(smsVo);
    }
}

3、service-hosp中更新排班数量

3.1、引入依赖

<!--MQ-->
<dependency>
    <groupId>com.atguigu</groupId>
    <artifactId>rabbit-utils</artifactId>
    <version>1.0</version>
</dependency>

3.2、添加MQ配置

spring:
  rabbitmq:
    host: 192.168.100.101
    port: 5672
    username: guest
    password: guest

3.3、封装MQ监听器

在监听器中更新排班数量:

package com.atguigu.syt.hosp.receiver;

@Component
@Slf4j
public class HospReceiver {

    @Resource
    private ScheduleService scheduleService;

    /**
     * 监听MQ中的消息
     * @param orderMqVo
     */
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MQConst.QUEUE_ORDER, durable = "true"), //消息队列,并持久化
            exchange = @Exchange(value = MQConst.EXCHANGE_DIRECT_ORDER), //交换机
            key = {MQConst.ROUTING_ORDER} //路由
    ))
    public void receive(OrderMqVo orderMqVo){
        //修改排班信息
        log.info("HospReceiver 监听器监听到消息......");
        scheduleService.updateByOrderMqVo(orderMqVo);
    }
}

接口:ScheduleService

/**
     * 更新排班数量
     * @param orderMqVo
     */
void updateByOrderMqVo(OrderMqVo orderMqVo);

实现:ScheduleServiceImpl

@Override
public void updateByOrderMqVo(OrderMqVo orderMqVo) {
    //下单成功更新预约数
    ObjectId objectId = new ObjectId(orderMqVo.getScheduleId());
    //id是objectId
    Schedule schedule = scheduleRepository.findById(objectId).get();
    //id是string
    //      Schedule schedule = scheduleRepository.findById(orderMqVo.getScheduleId()).get();
    schedule.setReservedNumber(orderMqVo.getReservedNumber());
    schedule.setAvailableNumber(orderMqVo.getAvailableNumber());

    //主键一致就是更新
    scheduleRepository.save(schedule);
}

4、完善service-orde订单接口

4.1、引入依赖

<!--MQ-->
<dependency>
    <groupId>com.atguigu</groupId>
    <artifactId>rabbit-utils</artifactId>
    <version>1.0</version>
</dependency>

4.2、添加MQ配置

spring:
  rabbitmq:
    host: 192.168.100.101
    port: 5672
    username: guest
    password: guest

4.3、修改下单方法

OrderInfoServiceImpl类:

@Resource
private RabbitService rabbitService;

submitOrder方法中添加发送消息的业务逻辑:

//使用这两个数据更新平台端的最新的排班数量
Integer reservedNumber = data.getInteger("reservedNumber");
Integer availableNumber = data.getInteger("availableNumber");

//目的1:更新mongodb数据库中的排班数量
//组装数据同步消息对象
OrderMqVo orderMqVo = new OrderMqVo();
orderMqVo.setAvailableNumber(availableNumber);
orderMqVo.setReservedNumber(reservedNumber);
orderMqVo.setScheduleId(scheduleId);
//发消息
rabbitService.sendMessage(MQConst.EXCHANGE_DIRECT_ORDER, MQConst.ROUTING_ORDER, orderMqVo);

//目的2:给就诊人发短信
//组装短信消息对象
SmsVo smsVo = new SmsVo();
smsVo.setPhone(orderInfo.getPatientPhone());
//亲爱的用户:您已预约%{hosname}%{hosdepname}%{date}就诊
//请您于%{time}至%{address}取号,
//您的就诊号码是%{number},请您及时就诊
smsVo.setTemplateCode("和客服申请模板编号");
Map<String,Object> paramsSms = new HashMap<String, Object>(){{
    put("hosname", orderInfo.getHosname());
    put("hosdepname", orderInfo.getDepname());
    put("date", new DateTime(orderInfo.getReserveDate()).toString("yyyy-MM-dd"));
    put("time", orderInfo.getFetchTime());
    put("address", orderInfo.getFetchAddress());
    put("number", orderInfo.getNumber());
}};
smsVo.setParam(paramsSms);
//向MQ发消息
rabbitService.sendMessage(MQConst.EXCHANGE_DIRECT_SMS, MQConst.ROUTING_SMS, smsVo);

4.4、修改取消订单方法

cancelOrder方法中添加发送消息的业务逻辑:

 //获取返回数据
JSONObject jsonObject = jsonResult.getJSONObject("data");
Integer reservedNumber = jsonObject.getInteger("reservedNumber");
Integer availableNumber = jsonObject.getInteger("availableNumber");

//目的1:更新mongodb数据库中的排班数量
//组装数据同步消息对象
OrderMqVo orderMqVo = new OrderMqVo();
orderMqVo.setAvailableNumber(availableNumber);
orderMqVo.setReservedNumber(reservedNumber);
orderMqVo.setScheduleId(orderInfo.getScheduleId());
//发消息
rabbitService.sendMessage(MQConst.EXCHANGE_DIRECT_ORDER, MQConst.ROUTING_ORDER, orderMqVo);

//目的2:给就诊人发短信
//组装短信消息对象
SmsVo smsVo = new SmsVo();
smsVo.setPhone(orderInfo.getPatientPhone());
//亲爱的用户:您已取消%{hosname}%{hosdepname}%{date}就诊
smsVo.setTemplateCode("和客服申请模板编号");
Map<String,Object> paramsSms = new HashMap<String, Object>(){{
    put("hosname", orderInfo.getHosname());
    put("hosdepname", orderInfo.getDepname());
    put("date", new DateTime(orderInfo.getReserveDate()).toString("yyyy-MM-dd"));
}};
smsVo.setParam(paramsSms);
//向MQ发消息
rabbitService.sendMessage(MQConst.EXCHANGE_DIRECT_SMS, MQConst.ROUTING_SMS, smsVo);

5、就诊人提醒

5.1、添加定时任务

在service-order微服务中添加定时任务:创建ScheduledTask类

cron表达式参考:https://qqe2.com/cron

package com.atguigu.syt.order.schedule;

@Component
@EnableScheduling  //开启定时任务
@Slf4j
public class ScheduledTask {
    /**
     * 测试
     * (cron="秒 分 时 日 月 周")
     * *:每隔一秒执行
     * 0/3:从第0秒开始,每隔3秒执行一次
     * 1-3: 从第1秒开始执行,到第3秒结束执行
     * 1,2,3:第1、2、3秒执行
     * ?:不指定,若指定日期,则不指定周,反之同理
     */
    @Scheduled(cron="0/3 * * * * ?")
    public void task1() {
        log.info("task1 执行");
    }
}

5.2、添加就诊人提醒定时任务

@Resource
private OrderInfoService orderInfoService;

@Scheduled(cron = "0 0 18 * * ?")
public void patientAdviceTask(){

    log.info("执行定时任务");
    orderInfoService.patientAdvice();
}

5.3、Service

需求:就诊前一天晚六点向用户发送就医提醒短信

接口:OrderInfoService

/**
     * 就诊人提醒
     */
void patientAdvice();

实现:OrderInfoServiceImpl

@Override
public void patientAdvice() {

    //查询明天的预约信息
    LambdaQueryWrapper<OrderInfo> queryWrapper = new LambdaQueryWrapper<>();

    //明天
    String tomorrow = new DateTime().plusDays(1).toString("yyyy-MM-dd");
    queryWrapper.eq(OrderInfo::getReserveDate, tomorrow);
    //未取消
    queryWrapper.ne(OrderInfo::getOrderStatus, OrderStatusEnum.CANCLE.getStatus());
    List<OrderInfo> orderInfoList = baseMapper.selectList(queryWrapper);

    for (OrderInfo orderInfo : orderInfoList) {
        //短信对象
        SmsVo smsVo = new SmsVo();
        smsVo.setPhone(orderInfo.getPatientPhone());
        //就诊提醒:您已预约%{hosname}%{depname}的号源,就诊时间:%{date},就诊人%{name},请您合理安排出行时间
        smsVo.setTemplateCode("和客服申请模板编号");
        Map<String,Object> paramsSms = new HashMap<String, Object>(){{
            put("hosname", orderInfo.getHosname());
            put("hosdepname", orderInfo.getDepname());
            put("date", new DateTime(orderInfo.getReserveDate()).toString("yyyy-MM-dd"));
            put("name", orderInfo.getPatientName());
        }};
        smsVo.setParam(paramsSms);
        //发消息
        rabbitService.sendMessage(MQConst.EXCHANGE_DIRECT_SMS, MQConst.ROUTING_SMS, smsVo);
    }
}

源码:https://gitee.com/dengyaojava/guigu-syt-parent文章来源地址https://www.toymoban.com/news/detail-499173.html

到了这里,关于网站中接入手机验证码和定时任务(含源码)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【手机号验证/前端】Vue2+elementUI编写一个手机号验证码登录页面,路由式开发(附完整代码)

    目录 效果图: 一、template部分 二、style样式 三、script部分 1.先对手机号的格式进行一个判断 2.接下来就是表单验证规则rules 3.最后就是methods了 (1)首先我们给获取验证码绑定一个方法 (2)然后封装一个axios接口,方便后面测试联调(这部分每个人封装的都不一样) (3)然

    2024年02月17日
    浏览(55)
  • reggie优化01-缓存短信验证码和菜品数据

    在config包下,创建Redis配置类RedisConfig: 纳入Git管理: 之前的短信验证码存放在session中,是存在一定的时间有效期,现在要将短信验证码存放到Redis中。 1、注入RedisTemplate对象: 2、在sendMsg方法中,将生成的验证码缓存到Redis中,并且设置有效期为5分钟: 其中:redisTemplate.

    2024年02月16日
    浏览(41)
  • Spring Boot进阶(69):轻松实现定时任务持久化!SpringBoot集成quartz带你玩转定时任务删除、暂停、获取等操作!【附项目源码】

            现如今,随着市场竞争加剧,各个企业都在不断寻求提高效率、降低成本的方法,此时使用自动化工具已成为必不可少的选择。而在众多的自动化工具中,定时任务已经成为一项必备工具,而Quartz就是一个非常好用的定时任务框架,它的轻量级、高可靠性、易于使

    2024年02月09日
    浏览(60)
  • 在线输入密码访问网站单页,密码验证跳转网站源码

    源码介绍 密码访问单页自定义跳转页面源码 密码访问单页自定义跳转页面,修改了的密码访问单页,添加了js自定义密码跳转页面,需要正确输入密码才能跳转目标网址。

    2024年01月25日
    浏览(109)
  • 国开电大《WEB开发基础》形考任务【答案】实验1-5:电商网站前端页面内容编写

    国开电大《WEB开发基础》形考任务1 国开电大《WEB开发基础》形考任务1 国开电大《WEB开发基础》形考任务3 国开电大《WEB开发基础》形考任务4 国开电大《WEB开发基础》形考任务5 作业答案 联系QQ:1603277115 【目标】 根据素材中的设计图,编写网站首页,查询列表页和详情页三

    2024年02月03日
    浏览(72)
  • 分布式定时任务系列8:XXL-job源码分析之远程调用

    分布式定时任务系列1:XXL-job安装 分布式定时任务系列2:XXL-job使用 分布式定时任务系列3:任务执行引擎设计 分布式定时任务系列4:任务执行引擎设计续 分布式定时任务系列5:XXL-job中blockingQueue的应用 分布式定时任务系列6:XXL-job触发日志过大引发的CPU告警 分布式定时任

    2024年01月21日
    浏览(51)
  • IDEA Android用户登录页面、登录验证、页面跳转演示示例全部源码

    开发工具: IDEA 2022.3.2,未连接数据库。验证用的用户名和密码为内置硬编码 演示程序运行效果:     设计器中的用户登录页面布局:  登录验证容错提示如下: 1,用户名不能为空: 2,密码不能为空:     3,用户名不存在: 4,用户密码错误    5,登录验证成功跳转到用户

    2024年02月11日
    浏览(52)
  • Spring Boot进阶(68):如何用SpringBoot轻松实现定时任务?集成Quartz来帮你!(附源码)

            Quartz是一个非常流行的开源调度框架,它提供了许多强大的功能,如定时任务调度、作业管理、任务持久化等。而SpringBoot是目前Java开发中非常流行的框架之一,其对各种开源框架集成非常方便。本篇文章将介绍如何在SpringBoot中集成Quartz,以便于更好的管理和调度

    2024年02月07日
    浏览(54)
  • 手机商城网站的分析与设计(论文+源码)_kaic

    目录 摘   要    1 1 绪论    2 1.1选题背景意义    2 1.2国内外研究现状    2 1.2.1国内研究现状    2 1.2.2国外研究现状    3 1.3研究内容    3 2 网上手机商城网站相关技术    4 2.1.NET框架    4 2.2Access数据库    4 2.3 JavaScript技术    4 3网上手机商城网站分析与设计 

    2024年02月12日
    浏览(31)
  • 号卡推广管理系统源码 手机卡流量卡推广网站源码 带后台版本

    网盘源码   密码:3lev 管理后台演示 最近在做号卡代理,前几天发布了一个只有前台页面的号卡产品推广页面,但是考虑到每次修改产品都要在源文件修改就抽空用PHP搞了个后台,非常简单哈,不过满足正常使用。

    2024年02月04日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包