zoukankan      html  css  js  c++  java
  • 美多商城项目之短信验证码

    目前市面上可以发送短信验证码的平台有很多,此项目中使用的容联云通讯进行短信验证码的发送。

    首先,我们先来进行手机验证码的逻辑分析,

    通过这张图片,我们基本确定了发送短信验证码的基本逻辑,并且在业务逻辑中,我们不能让短信验证码任务阻塞了响应结果,所以我们需要采用celery方式进行异步发送短信验证码且不会阻塞响应。

    容联云通讯网址:https://www.yuntongxun.com/

    既然确定了,核心逻辑和解决方案,那么接下来我们就进行代码实现了。

    1.模板短信SDK下载

    https://www.yuntongxun.com/doc/ready/demo/1_4_1_2.html

    2.模板短信SDK使用说明

    http://doc.yuntongxun.com/p/5a533e0c3b8496dd00dce08c

    1. 定义相关视图

    # 编写短信验证码视图
    class SmsVerVerifications(View):
        def get(self, request, mobile):
            pass

    2. 配置相关路由

    url(r'^sms_codes/(?P<mobile>1[3-9]d{9})/$',views.SmsVerVerifications.as_view(),name='SMS')

    3. 创建celery程序

    在项目中,创建一个celery包。

    注意:

      celery是一个独立程序,他不属于Django程序。

    4. 编写celery程序入口

    # celery启动文件
    from celery import Celery
    
    
    # 为celery使用django配置文件进行设置
    import os
    if not os.getenv('DJANGO_SETTINGS_MODULE'):
        os.environ['DJANGO_SETTINGS_MODULE'] = 'meiduo_mall.settings.dev'
    
    # 创建celery实例
    celery_app = Celery('meiduo')
    
    # 加载celery配置
    celery_app.config_from_object('celery_tasks.config')
    
    # 自动注册celery任务
    celery_app.autodiscover_tasks(['celery_tasks.sms_task'])

    5. 编写celery程序配置文件

    # 指定消息队列的位置
    broker_url = "redis://127.0.0.1/10"

    注意:

      celery程序遵守的是生产者消费者设计模式,这种设计模式需要一个队列容器来保存任务。

    举个例子:

      生产者就相当于LOL官方,

      而这个容器就相当于LOL的道具城,

      消费者就相当于我们玩家,

    生产者生产任务,然后放到队列容器中,也就相当于LOL出了个新皮肤,并且上架到了LOL道具城;

    消费者从队列容器获取任务并完成任务,就相当于我们玩家发现新出了的皮肤,然后买了这么个过程。

    6. 创建celery任务

    # 定义任务的文件,文件名必须叫tasks.py
    # celery的任务就是函数
    from celery_tasks.sms_task.yuntongxun.ccp_sms import sendTemplateSMS
    from celery_tasks.sms_task import constants
    from celery_tasks.main import celery_app
    
    
    @celery_app.task(name='ccp_send_sms_code') # name是任务的别名,可以通过name参数自定义任务名字
    def ccp_send_sms_code(mobile, sms_code):
        """
        发送短信验证码的异步任务
        :param mobile: 手机号
        :param sms_code: 短信验证码
        :return: None
        """
        sendTemplateSMS(mobile, [sms_code, constants.SMS_CODE_REDIS_EXPIRES // 60], constants.SEND_SMS_TEMPLATE_ID)

    注意:

      celery任务的文件名字必须是tasks.py

    想要完成发送短信验证码的任务,在调用之前我们还需要配置容联云通讯的配置文件。

    找到容联云配置文件,并修改以下配置项。

    # 说明:主账号,登陆云通讯网站后,可在"控制台-应用"中看到开发者主账号ACCOUNT SID
    _accountSid = '你的账号ACCOUNT SID'
    
    # 说明:主账号Token,登陆云通讯网站后,可在控制台-应用中看到开发者主账号AUTH TOKEN
    _accountToken = '你的账号AUTH TOKEN'
    
    # 请使用管理控制台首页的APPID或自己创建应用的APPID
    _appId = '你的APPID'

    7. 启动celery并且调用celery任务完成,异步发送短信验证码。

    # 使用celery完成异步发送短信验证码
    ccp_send_sms_code.delay(mobile, sms_code)

    注意:

      celery任务必须使用.delay方法调用,否则无法调用celery任务。

    整体代码如下:

    from . import constants
    from meiduo_mall.utils.response_code import RETCODE
    from celery_tasks.sms_task.tasks import ccp_send_sms_code
    
    # 创建日志输出器
    logger = logging.getLogger('django')
    
    # 编写短信验证码视图
    class SmsVerVerifications(View):
        def get(self, request, mobile):
            redis_conn = get_redis_connection('verify_code')
    
            # 获取手机验证码标记
            send_flag = redis_conn.get('send_flag_%s' % mobile)
            # 判断标记是否存在,存在则发送频繁
            if send_flag:
                return http.JsonResponse({'code':RETCODE.THROTTLINGERR,'errmsg':'验证发送过与频繁'})
    
            # 接收参数
            image_code_client = request.GET.get('image_code')
            uuid = request.GET.get('uuid')
    
            # 校验参数
            # 创建redis链接,并提取image_code_server
            # redis_conn = get_redis_connection('verify_code')
            image_code_server = redis_conn.get('img_%s' % uuid)
    
            # 判断图形验证码是否过期
            if not image_code_server:
                return http.JsonResponse({'code':RETCODE.IMAGECODEERR,'errmsg':'图形验证码失效'})
    
            # 删除图形验证码
            redis_conn.delete('img_%s' % uuid)
    
            # 实现核心逻辑
            # 对比图形验证码
            if image_code_client.lower() != image_code_server.decode().lower():
                return http.JsonResponse({'code':RETCODE.IMAGECODEERR,'errmsg':'图形验证码错误'})
    
            # 生成短信验证码
            sms_code = '%06d' % random.randint(0,1000000)
            logger.info(sms_code)
    
            # 保存短信验证码并设置有效期
            # redis_conn.setex('sms_%s' % mobile,constants.SMS_CODE_REDIS_EXPIRES,sms_code)
    
            # 避免重复发送短信验证码,需要设置一个标记,用来标记短信验证码是否重复
            # redis_conn.setex('send_flag_%s' % mobile, constants.SEND_SMS_CODE_INTERVAL,'send_flag')
    
            # 优化redis数据库操作
            # 创建管道
            pl = redis_conn.pipeline()
            # 将命令添加到管道内
            pl.setex('sms_%s' % mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code)
            pl.setex('send_flag_%s' % mobile, constants.SEND_SMS_CODE_INTERVAL, 'send_flag')
            # 执行命令
            pl.execute()
    
            # 发送短信验证码
            # sendTemplateSMS(mobile,[sms_code,constants.SMS_CODE_REDIS_EXPIRES // 60],constants.SEND_SMS_TEMPLATE_ID)
    
            # 使用celery完成异步发送短信验证码
            ccp_send_sms_code.delay(mobile, sms_code)
    
            # 返回相应结果
            return http.JsonResponse({'code':RETCODE.OK,'errmsg':'发送短信验证码成功'})
    该花的钱要花,该吃的饭要吃。
  • 相关阅读:
    Gym 100818F Irrational Roots (数学)
    学习总结 for循环--冒泡排序
    学习总结 for循环语句的应用
    学习总结 条件语句的应用
    学习总结 运算符了解与应用
    学习记录 彻底搞清 C#中a++与++a的区别
    学习总结 数据类型的应用与转换
    学习总结 数据类型
    学习总结 二进制转换与应用
    学习总结 vs软件简单了解
  • 原文地址:https://www.cnblogs.com/chao666/p/12187445.html
Copyright © 2011-2022 走看看