<tfoot id="ouu4w"><rt id="ouu4w"></rt></tfoot>
  • 
    
  • <bdo id="ouu4w"></bdo>
        <cite id="ouu4w"><table id="ouu4w"></table></cite>
      • 您當前的位置: 首頁-云計算-詳情

        網站中接入手機驗證碼和定時任務(含源碼)

        2023-06-25 08:19:27來源:博客園
        頁面預覽綁定手機號未綁定手機號已綁定手機號第01章-短信發送1、云市場-短信API1.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 paramsMap = new HashMap(){{            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@Slf4jpublic 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 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 querys = new HashMap<>();        Map 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 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

        @Resourceprivate RedisTemplate redisTemplate;@Overridepublic 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 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、引入RabbitMQ1.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中引入依賴

                        org.springframework.boot        spring-boot-starter-amqp                org.projectlombok        lombok    
        1.5、創建RabbitService類

        添加sendMessage方法

        package com.atguigu.syt.rabbit;@Service@Slf4jpublic 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;@Configurationpublic 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、引入依賴
            com.atguigu    rabbit-utils    1.0
        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@Slf4jpublic 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、引入依賴
            com.atguigu    rabbit-utils    1.0
        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@Slf4jpublic 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

        @Overridepublic 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、引入依賴
            com.atguigu    rabbit-utils    1.0
        4.2、添加MQ配置
        spring:  rabbitmq:    host: 192.168.100.101    port: 5672    username: guest    password: guest
        4.3、修改下單方法

        OrderInfoServiceImpl類:

        @Resourceprivate 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 paramsSms = new HashMap(){{    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 paramsSms = new HashMap(){{    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  //開啟定時任務@Slf4jpublic 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、添加就診人提醒定時任務
        @Resourceprivate OrderInfoService orderInfoService;@Scheduled(cron = "0 0 18 * * ?")public void patientAdviceTask(){    log.info("執行定時任務");    orderInfoService.patientAdvice();}
        5.3、Service

        需求:就診前一天晚六點向用戶發送就醫提醒短信

        接口:OrderInfoService

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

        實現:OrderInfoServiceImpl

        @Overridepublic void patientAdvice() {    //查詢明天的預約信息    LambdaQueryWrapper 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 orderInfoList = baseMapper.selectList(queryWrapper);    for (OrderInfo orderInfo : orderInfoList) {        //短信對象        SmsVo smsVo = new SmsVo();        smsVo.setPhone(orderInfo.getPatientPhone());        //就診提醒:您已預約%{hosname}%{depname}的號源,就診時間:%{date},就診人%{name},請您合理安排出行時間        smsVo.setTemplateCode("和客服申請模板編號");        Map paramsSms = new HashMap(){{            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

        標簽:

        上一篇:精彩看點:俄媒:全俄聯邦公路交通管制措施均被取消
        下一篇:最后一頁