目录
1.短信sdk接入
1.准备工作
1.下载云通讯相关的文件 https://github.com/cloopen/python-sms-sdk
2.在lyapi目录下创建一个lib文件夹,将ronglian_sms_sdk文件夹放入lib文件夹中
3.文件夹下的目录结构如图所示
4.登录
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
提交手机号/密码/确认密码/验证码 看是否能拿到后端传给我们的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的简单使用
文档: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'})