• day80:luffy:短信sdk接入&点击获取验证码&注册功能的实现&Celery实现短信发送功能


    目录

    1.短信sdk接入

    2.前端点击获取验证码效果

    3.注册后端接口实现

    4.注册-前端

    5.Celery

    6.Celery完成短信发送功能

    1.短信sdk接入

    1.准备工作

    1.下载云通讯相关的文件  https://github.com/cloopen/python-sms-sdk

    2.在lyapi目录下创建一个lib文件夹,将ronglian_sms_sdk文件夹放入lib文件夹中

    3.文件夹下的目录结构如图所示

    4.登录 https://www.yuntongxun.com/ 获取一些相关信息

    ACCOUNT SID:8a216da863f8e6c20164139687e80c1b
    AUTH TOKEN : 6dd01b2b60104b3dbc88b2b74158bac6
    AppID(默认):8aaf0708697b6beb01699f4442e3177c

    2.使用容联云通讯发送短信

    sms.py

    from django.conf import settings
    from .SmsSDK import SmsSDK
    import json
    
    accId = settings.SMS_INFO.get('ACCID')
    accToken = settings.SMS_INFO.get('ACCTOKEN')
    appId = settings.SMS_INFO.get('APPID')
    
    
    def send_message(tid, mobile, datas):
        sdk = SmsSDK(accId, accToken, appId)
        resp = sdk.sendMessage(tid, mobile, datas)
        resp = json.loads(resp)
        print(resp)
        return resp.get('statusCode') == '000000'

    dev.py

    SMS_INFO = {
        'ACCID':'8a216da8754a45d5017563ac8e8406ff',
        'ACCTOKEN':'a2054f169cbf42c8b9ef2984419079da',
        'APPID':'8a216da8754a45d5017563ac8f910705',
    }

    views.py

    # views.py
    '''todo 发送验证码'''
    import logging
    logger = logging.getLogger('django')
    from lyapi.libs.ronglian_sms_sdk.sms import send_message
    from django.conf import settings
    class GetSMSCodeView(APIView):
        def get():
            ......
            
            # 发送验证码
             ret = send_message(settings.SMS_INFO.get('TID'),phone,(sms_code,constants.SMS_CODE_EXPIRE_TIME))
            if not ret:
                logger.error('{}手机号短信发送失败'.format(phone))
                return Response({'msg':'短信发送失败 ,请联系管理员!!'},status=status.HTTP_500_INTERNAL_SERVER_ERROR)
            
            return Response({'msg': 'ok'})
            

    3.drf后端接口测试

    访问users/sms_code/13015409856,可得到msg:ok 并且手机会接受到验证码信息

    2.前端点击获取验证码效果

    1.在register.vue中给获取验证码按钮绑定个点击事件

    <!-- html -->
    
    <div>
        <input v-model = "sms" type="text" placeholder="输入验证码" class="user" style=" 62%">
        <button style=" 34%;height: 41px;" @click="getSmsCode">{{ btn_msg }}</button>
    </div>
    // js
    <script>
    export default {
      name: 'Register',
      data(){
        return {
            ......
            interval_time:60, // 倒计时时间
            btn_msg:'点击获取验证码', // 按钮上面的信息
            flag:false // 判断定时器是否已经开启
        }
      },
      created(){
      },
      methods:{
        ......
        getSmsCode(){
            this.$axios.get(`${this.$settings.Host}/users/sms_code/${this.mobile}/`)
                .then(()=>{
                // 计时器
                this.flag = setInterval(()=>{
                    if(this.interval_time > 0){
                        this.interval_time--;
                        this.btn_msg=`${this.interval_time}秒后重新获取`;
                    }else{
                        this.interval_time=60;
                        this.btn_msg='点击发送验证码';
                        clearInterval(this.flag);
                        this.flag=false;
                    }
                },1000)
            })
                .catch(()=>{
    
            })
    
    
        }
    
    
      },
    
    };
    </script>

    这个时候 我们在注册页面点击获取验证码按钮 手机上就可以收到短信了

    2.效果:按钮变为不可点击

    未获取验证码时:按钮显示点击获取验证码 且按钮是可点击的

    ​获取验证码时,按钮显示倒计时,并且倒计时时按钮不可点击

    <!-- html -->
    <div>
        <input v-model = "sms" type="text" placeholder="输入验证码" class="user" style=" 62%">
        <button style=" 34%;height: 41px;" @click="getSmsCode" :disabled="this.flag">{{ btn_msg }}</button>
    </div>
    // js
    <script>
    export default {
      name: 'Register',
      data(){
        return {
            validateResult:false,
            interval_time:60,
            btn_msg:'点击获取验证码',
            flag:false,
        }
      },
      created(){
      },
      methods:{
        ......
        getSmsCode(){
          this.$axios.get(`${this.$settings.Host}/users/sms_code/${this.mobile}/`)
          .then((res)=>{
             this.flag = setInterval(()=>{
                if(this.interval_time > 0){
                  this.interval_time--;
                  this.btn_msg=`${this.interval_time}秒后重新获取`;
                  this.disabled = true; // 将按钮设置为不可点击
                }else{
                  this.interval_time=60;
                  this.btn_msg='点击发送验证码';
                  clearInterval(this.flag);
                  this.flag=false;
                  this.disabled = false // 将按钮设置为可点击
                }
              },1000)
          })
          .catch((error)=>{
            
          })

    3.效果:前端显示:60s已经发过了,别瞎搞

    register.vue

    // register.vue
    getSmsCode(){    this.$axios.get(`${this.$settings.Host}/users/sms_code/${this.mobile}/`)
          ......
          .catch((error)=>{
            this.$message.error(error.response.data.msg); // 打印错误信息
          })

    3.注册后端接口实现

    1.后端序列化器对验证码的校验

    serializers.py

    # serializers.py
    from rest_framework import serializers
    from django_redis import get_redis_connection
        ......
        # todo  校验验证码
    def validate(self, attrs):
        ......
        conn = get_redis_connection('sms_code') # 获取redis所存放验证码的那个库对象
        ret = conn.get('mobile_%s' % (phone_number)) # 获取到手机号对应的验证码
        if not ret: # 如果验证码不存在
            raise serializers.ValidationError('验证码已失效')
            if ret.decode() != sms: # 如果验证码不对
                raise serializers.ValidationError('验证码输入错误')
    
                return attrs
    
        ......

    2.当用户注册成功后,后端应该返回给前端一个真实的token值

    serializers.py

    # serializers.py
    def create(self, validated_data):
    
            ...... 
            # 通过jwt生成一个真实的token值返回给前端
            payload = jwt_payload_handler(user)
            token = jwt_encode_handler(payload)
            user.token = token
    
            return user

    这个时候我们测试接口 users/register

    提交手机号/密码/确认密码/验证码 看是否能拿到后端传给我们的id phone token值

    4.注册-前端

    用户点击注册按钮后

    如果校验通过,应该将后端发过来的id username token存到sessionStorage中  并跳转到首页界面

    如果校验失败,应该在前端展示对应的错误信息

    register.vue

    <script>
    export default {
      name: 'Register',
      data(){
        return {
            sms:"",
            mobile:"",
            password:"",
            r_password:"",
            validateResult:false,
            interval_time:60, // /倒计时时间
            btn_msg:'点击获取验证码',
            flag:false, // 判断定时是否已经开启
    
        }
      },
      created(){
      },
      methods:{
        ......
        registerHandler(){
          this.$axios.post(`${this.$settings.Host}/users/register/`,{
            sms:this.sms,
            phone:this.mobile,
            password:this.password,
            r_password:this.r_password,
          }).then((res)=>{
    // 注册成功 将id token username存储到前端 并跳转到首页 sessionStorage.token = res.data.token; sessionStorage.username = res.data.username; sessionStorage.id = res.data.id; this.$router.push('/') // 跳转到首页 }).catch((error)=>{
    // 注册失败 打印错误信息 console.log(error.response); }) }, getSmsCode(){ this.$axios.get(`${this.$settings.Host}/users/sms_code/${this.mobile}/`) .then((res)=>{ this.flag = setInterval(()=>{ if(this.interval_time > 0){ this.interval_time--; this.btn_msg=`${this.interval_time}秒后重新获取`; this.disabled = true; // 点击了获取验证码之后 按钮变为不可点击 }else{ //倒计时停止 允许用户发送短信 this.interval_time=60; this.btn_msg='点击发送验证码'; clearInterval(this.flag); this.flag=false; this.disabled = false } },1000) }) .catch((error)=>{ this.$message.error(error.response.data.msg); }) } }, }; </script>

    5.Celery

    1.Celery的简单使用

    Celery是一个功能完备即插即用的异步任务队列系统。它适用于异步处理问题,当发送邮件、或者文件上传, 图像处理等等一些比较耗时的操作,我们可将其异步执行,这样用户不需要等待很久,提高用户体验。

    文档:http://docs.jinkan.org/docs/celery/getting-started/index.html

    Celery的特点是:

    • 简单,易于使用和维护,有丰富的文档。

    • 高效,单个celery进程每分钟可以处理数百万个任务。

    • 灵活,celery中几乎每个部分都可以自定义扩展。

    2.Celery的架构图

    3.Celery的使用

    Celery的基本使用:传送门:Celery的基本使用

    6.Celery完成短信发送功能

    在最外层lyapi目录创建mycelery包

    文件目录结构

    # 文件结构目录
    lyapi/
    ├── mycelery/
        ├── config.py     # 配置文件
        ├── __init__.py   
        ├── main.py       # 主程序
        └── sms/          
            └── tasks.py  # 任务的文件,名称必须是这个!!!

    main.py

    # main.py
    
    from celery import Celery
    import os
    os.environ.setdefault('DJANGO_SETTINGS_MODULE','lyapi.settings.dev')
    import django
    django.setup()
    
    
    app = Celery()
    
    app.config_from_object('mycelery.config')
    
    app.autodiscover_tasks(['mycelery.sms',])

    config.py

    # config.py
    
    # 任务队列的链接地址(变量名必须叫这个)
    broker_url = 'redis://127.0.0.1:6379/14'
    # 结果队列的链接地址(变量名必须叫这个)
    result_backend = 'redis://127.0.0.1:6379/15'

    tasks.py

    # tasks.py
    
    from mycelery.main import app
    from lyapi.libs.ronglian_sms_sdk.sms import send_message
    from django.conf import settings
    from lyapi.settings import constants
    
    import logging
    logger = logging.getLogger('django')
    
    
    @app.task(name='smsCode')
    def sms_codes(phone,sms_code):
        ret2 = send_message(settings.SMS_INFO.get('TID'), phone, (sms_code, constants.SMS_CODE_EXPIRE_TIME // 60))
        if not ret2:
            logger.error('{}手机号短信发送失败'.format(phone))
        
        return '短信发送成功啦'
                       

    views.py

    # views.py
    
    # 发送验证码
    from mycelery.sms.tasks import sms_code
    sms_code.delay(phone,sms_code)
    
    return Response({'msg':'ok'})
  • 相关阅读:
    深拷贝和浅拷贝
    【.NET MVC分页】.NET MVC 使用pagelist 分页
    Win10开启IIS
    Win10开启IIS
    目前问题:plupload上传带参数到后台
    目前问题:plupload上传带参数到后台
    jquery怎样获取html页面中的data-xxx
    .Net MVC删除图片
    .Net MVC删除图片
    AlloyClip的简单使用
  • 原文地址:https://www.cnblogs.com/libolun/p/13922163.html
Copyright © 2020-2023  润新知