python+小程序实现手机号验证

前言:

使用Python的Django框架来完成后端接口

使用微信开发者工具来进行小程序编写

使用腾讯云进行发送短信的服务

使用django-redis进行验证码和手机号的存储,以进行验证码校验

使用Redis数据库进行存储(这里我用的是阿里云服务器,使用云服务器安装启动Redis)

1.环境准备

  • 微信小程序APPID

  • python虚拟环境

    • conda create -n django python==3.7
    • conda activate django
    • conda insatll django
    • pip install djangorestframework
  • 之后pycharm新建一个Django工程 interpreter选择刚刚创建的虚拟环境

  • Redis安装和基本使用

    1668833642145

2.小程序

  • 新建一个Page

  • 在wxml中搭建好页面结构

    这里写了一个简单的示例

    1
    2
    3
    4
    5
    6
    7
    <view>手机号:</view>
    <input value="{{phone}}" bindinput="bindPhone" placeholder="请输入手机号"></input>

    <view>验证码:<view bindtap="messageCode">点击获取验证码</view></view>
    <input value="{{code}}" bindinput="bindCode" placeholder="请输入验证码"></input>

    <button bindtap="login">登录</button>
  • 在js中编写逻辑

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    Page({
    /**
    * 页面的初始数据
    */
    data: {
    phone:"",
    code:""
    },
    bindPhone:function (e) {
    this.setData({phone: e.detail.value})
    },
    bindCode:function (e) {
    this.setData({code: e.detail.value})
    },
    messageCode: function(){
    // 手机号长度校验
    if(this.data.phone.length != 11){
    //弹窗
    wx.showToast({
    title: '手机号长度错误',
    icon: 'none'
    })
    return;
    }
    // 手机号格式校验
    var reg = /^(1[3|4|5|6|7|8|9])\d{9}$/
    if(!reg.test(this.data.phone)){
    wx.showToast({
    title: '手机号格式错误',
    icon: 'none'
    })
    return
    }
    wx.request({
    url: 'http://127.0.0.1:8000/api/message',
    data: {phone: this.data.phone},
    method: 'GET',
    success: function(res) {
    console.log(res);
    }
    })
    },
    login:function () {
    console.log(this.data.phone, this.data.code);
    // 将手机号和验证码发送到后端,后端进行登录
    wx.request({
    url: 'http://127.0.0.1:8000/api/login/',
    data: {phone: this.data.phone, code: this.data.code},
    method: 'POST',
    success: function (res) {
    console.log(res);
    }
    })
    }
    })

3.后端接口(基础实现)

  • pycharm中打开Terminal 输入 python manage.py startapp api 创建一个名字为api的app

  • 在settings.py中配置入口

    1
    2
    3
    4
    5
    6
    7
    8
    9
    INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework' # 加上这一行
    ]
  • 在主app的urls中配置接口前缀

    1
    2
    3
    4
    urlpatterns = [
    url(r'^admin/',admin.site.urls),
    url(r'^api/',include('api.urls')) # 所有api.urls中都加一个api/的前缀
    ]
  • 在api下的view中编写接口方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    class LoginView(APIView):
    def post(self,request,*args,**kwargs):
    print(request.data)
    return Response({'status': True})

    class MessageView(APIView):
    def get(self,request,*args,**kwargs):
    print(request.query_params)
    return Response({"status": True})
  • 在api下的urls中编写路径

    1
    2
    3
    4
    urlpatterns = [
    url(r'^login/', views.LoginView.as_view()),
    url(r'^message/', views.MessageView.as_view())
    ]

这个时候,启动Django,就可以访问http://127.0.0.1:8000/api/login/http://127.0.0.1:8000/api/message

4.最后一步

浏览器已经可以访问接口地址,但是启动小程序,会有报错

这是由于小程序中有校验机制

解决方法:在开发者工具的右上角,点击详情,勾选上不校验合法域名

5.完善后端手机号校验逻辑

  • 在api下的view中编写接口方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class MessageView(APIView):
    def get(self,request,*args,**kwargs):
    # 1.获取手机号
    phone = request.query_params.get('phone')
    # 2.手机号格式校验
    import re
    if not re.match(r"^(1[3|4|5|6|7|8|9])\d{9}$",phone):
    return Response('手机号格式错误')
    # 3.生成随机验证码
    # 4.验证码发送到手机
    # 5.将验证码+手机号保留(30s过期)
    print(request.query_params)
    return Response({"status": True})
    • 手机号格式校验,还可以通过序列化的方式

      序列化的方式有两个优点:1.自动序列化 2.自带不能为空的校验

      **校验优先顺序为:先校验不能为空--》之后校验validators中的规则--》最后校验validate_phone钩子函数**

      序列化写法如下:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      from rest_framework import serializers
      from rest_framework.exceptions import ValidationError
      import re

      def phone_validator(value):
      if not re.match(r"^(1[3|4|5|6|7|8|9])\d{9}$",value):
      raise ValidationError('手机格式错误')

      class MessageSerializer(serializers.Serializer):
      phone = serializers.CharField(label='手机号',validators=[phone_validator,])

      def validate_phone(self, value):
      pass
      # MessageView的里
      # 2.手机号格式校验
      ser = MessageSerializer(data=request.query_params.get('phone'))
      if ser.is_valid():
      print(ser.validated_data)
      else:
      print(ser.errors)

6.完善验证码+手机号存储(使用Redis)

  • Redis安装,启动。见链接

    • 运行,redis-server /usr/local/redis/etc/redis.conf 启动服务端 将daemonize no 改成daemonize yes 配置后台启动

    • 之后redis-cli启动客户端,尝试了python连接,连接成功

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      import redis

      conn = redis.Redis(host='123.57.138.63', port=6379, password='123Suyufan^')
      conn.set('foo','Bar')
      result = conn.get('foo')
      print(result)
      print(conn.keys())

      # 配置了setting.py
      # 运行test-redis.py

      • 如果出现端口占用的报错:Creating Ser,ver TCP listening socket *:6379: bind: Address already in use
      • 运行ps -ef | grep -i redis,查看任务进程
      • 执行kill -9 进程号,终止进程
      • 重新启动
  • 在setting中配置,加上以下代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    CACHES = {
    "default": {
    "BACKEND": "django_redis.cache.RedisCache",
    "LOCATION": "redis://127.0.0.1:6379",
    "OPTIONS": {
    "CLIENT_CLASS": "django_redis.client.DefaultClient",
    "CONNECTION_POOL_KWARGS": {"max_connections": 100}
    # "PASSWORD": "密码",
    }
    }
    }
  • pip install django-redis

  • 在api下的view中编写接口方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    # 3.生成随机验证码
    import random
    random_code = random.randint(1000,9999)
    # 4.验证码发送到手机,购买服务器进行短息发送:腾讯云
    # TODO tencent.send_message(phone,random_code)
    # 5.将验证码+手机号保留(30s过期)
    # 5.1 搭建redis服务器(云redis)
    # 5.2 django中方便使用redis的模块 django-redis
    # 配置 settings,操作Redis
    from django_redis import get_redis_connection
    conn = get_redis_connection()
    conn.set(phone,random_code,ex=30)
    return Response({"status": True,'message':'发送成功'})

7.腾讯云发短信

7.1 准备工作

1.注册腾讯云,开通腾讯短信

2.创建应用

​ SDK AppID

3.申请签名(个人:微信公众号)

​ ID 名称

4.申请模板

​ ID 名称

5.申请腾讯云API

​ SecretId SecretKey

7.2 调用接口

使用腾讯云写好的SDK

  • 安装pip install tencentcloud-sdk-python

具体用法见帮助文档,有手就行