python dajngo+vue 钉钉三方登录群机器人验证码

django+vue实现钉钉群机器人验证码

​ 又是忙碌的一天,今天给大家带来的教程是使用钉钉群机器人发送随机验证码

在vue中输入然后在后端进行判断并返回相应的返回值,首先我们去看官方文档

然后开始操作
我们需要django+vue跨域 点击查看

一、创建钉钉群机器人

首先明确一点,钉钉自定义机器人早就不支持在手机端创建了,所以打开你的pc端或者mac端的钉钉客户端,在需要机器人的聊天群界面,点击智能群助手

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

需要注意的是,在安全设置一栏里,我们选择加签的方式来验证,在此说明一下,钉钉机器人的安全策略有三种,第一种是使用关键字,就是说你推送的消息里必须包含你创建机器人时定义的关键字,如果不包含就推送不了消息,第二种就是使用加密签名,第三种是定义几个ip源,非这些源的请求会被拒绝,综合来看还是第二种又安全又灵活。
在这里插入图片描述

创建成功后,系统会分配给你一个webhook地址,这个地址需要保存一下,地址中有唯一的accesstoken

在这里插入图片描述
ok,那么怎么利用这个地址让你的机器人推送消息呢?查看官方文档

二、测试发送信息

发现文档居然还是python2.0的版本,好吧,我们自己来翻译成3.0

  • 在项目下新建包utils/dindin.py

    import time
    import hmac
    import hashlib
    import base64
    import urllib.parse
    import requests, json  # 导入依赖库
    
    # https://oapi.dingtalk.com/robot/send?access_token=e2e7db9c547beff2f8f93ee06fec87c1a354594045d49fbf30669d7e05b23c38
    
    timestamp = str(round(time.time() * 1000))
    #这里的secret是我们cp备份的
    secret = 'SECc96a44d409036efafe8645c659a551e3ad3ad15bdfd8a408b6254927a2d0d1ca'
    secret_enc = secret.encode('utf-8')
    string_to_sign = '{}\n{}'.format(timestamp, secret)
    string_to_sign_enc = string_to_sign.encode('utf-8')
    hmac_code = hmac.new(secret_enc, string_to_sign_enc, digestmod=hashlib.sha256).digest()
    sign = urllib.parse.quote(base64.b64encode(hmac_code))
    print(sign)  # eu4Q16kFubncXuZprXxwRuvDx3Yh/roFWEPn0T5MRPo%3D
    # print(timestamp)
    # print(sign)
    
    
    headers = {'Content-Type': 'application/json'}  # 定义数据类型
    #这里webhook是我们创建成功后 webhook地址
    webhook = 'https://oapi.dingtalk.com/robot/send?access_token=e2e7db9c547beff2f8f93ee06fec87c1a354594045d49fbf30669d7e05b23c38&timestamp=' + timestamp + "&sign=" + sign
    
    
    # 定义要发送的数据
    # "at": {"atMobiles": "['"+ mobile + "']"
    def dindin_post(text):
        data = {
            "msgtype": "text",
            "text": {"content": text},
            "isAtAll": True}
        res = requests.post(webhook, data=json.dumps(data), headers=headers)  # 发送post请求
    
        print(res.text)
    
    dindin_post(134235)
    
  • 测试发送成功
    在这里插入图片描述

三、创建user(app)

  1. user/models.py

    from django.contrib.auth.models import AbstractUser
    from django.db import models
    from utils.basemodel import Base
    
    
    # Create your models here.
    
    # 用户表
    class User(AbstractUser):
        username = models.CharField(max_length=32, unique=True)
        password = models.CharField(max_length=132)
        email = models.CharField(max_length=32, null=True, blank=True)
    
        class Meta:
            db_table = "用户"
    
        def __str__(self):
            return self.username
    
    
  2. 我们这里重写了django自带的用户表,所以要在settings中重新定义

    AUTH_USER_MODEL = 'user.User'
    
  3. user/views.py

    # 解密
    from django.contrib.auth.hashers import check_password, make_password
    # 返回HttpResponse
    from django.http import HttpResponse
    # 解码
    from django.utils.baseconv import base64
    # 返回Response
    from rest_framework.response import Response
    #
    from rest_framework.views import APIView
    from .models import *
    import time
    import hmac
    import base64
    from hashlib import sha256
    import urllib
    import json
    import requests
    from utils.dindin import dindin_post
    import random
    from rest_framework.permissions import AllowAny
    import jwt
    from mydjango import settings
    
    
    # 注册
    class RegisterAPIView(APIView):
        permission_classes = (AllowAny,)
    
        def post(self, request):
            # 获取信息
            username = request.data.get("username")
            password = request.data.get("password")
    
            try:
                # 存储数据
                User.objects.create(username=username, password=make_password(password))
                return Response({"msg": "ok", "code": 200})
            except Exception as e:
                print("user.view--16", e)
                return Response({"msg": "no", "code": 400})
    
    
    # 登录
    class LoginAPIView(APIView):
        permission_classes = (AllowAny,)
    
        def post(self, request):
            # 获取信息
            username = request.data.get("username")
            password = request.data.get("password")
            user_obj = User.objects.filter(username=username).first()
            # 判断密码
            if user_obj:
                if check_password(password, user_obj.password):
                    # jwt加密
                    encode_jwt = jwt.encode({"uid": user_obj.id}, settings.SECRET_KEY, algorithm='HS256')
                    print(encode_jwt)
                    return Response({"msg": "ok", "code": 200, "token": encode_jwt})
                else:
                    return Response({"msg": "no", "code": 400})
            else:
                return Response({"msg": "no", "code": 400})
    
    
    # 发送验证码
    class VerificationAPIView(APIView):
        permission_classes = (AllowAny,)
    
        def get(self, request):
            # 生成随机验证码6位
            code = '%06d' % random.randint(0, 999999)
            # 存储到session
            request.session["code"] = code  # 存储的也是 key-value 键值对
            request.session.set_expiry(120)  # 设置 session 存活期 单位是秒
            # 调用钉钉接口 发送验证码
            dindin_post(code)
            return Response({"msg": "ok", "code": 200})
    
    
    # 校验验证码
    class IsVerificationAPIView(APIView):
        permission_classes = (AllowAny,)
    
        def get(self, request):
            verification = request.GET.get("verification")
            code = request.session.get("code")
            print(code)
            if verification == code:
                return Response({"msg": "ok", "code": 200})
            else:
                return Response({"msg": "no", "code": 400})
    
    
  4. 配置子路由user/urls.py

    from django.urls import path
    from django.contrib.staticfiles.urls import staticfiles_urlpatterns
    from .views import *
    from rest_framework.routers import SimpleRouter, DefaultRouter
    from rest_framework_jwt.views import obtain_jwt_token, refresh_jwt_token
    
    # ... the rest of your URLconf goes here ...
    urlpatterns = [
        # 定义超链接路由
        # re_path('^static/upload/(?P<path>.*)$',serve,{'document_root':'/static/upload/'}),
        path('register/', RegisterAPIView.as_view()),  # 注册
        path('mylogin/', LoginAPIView.as_view()),  # 登录自定义token
        path('dindin_url/', DingDingAPIView.as_view()),  # 钉钉三方登录路由
        path('dindin_back/', DingBackApiView.as_view()),  # 三方登录回调地址
        path('verification/', VerificationAPIView.as_view()),  # 发送验证码接口
        path('isverification/', IsVerificationAPIView.as_view()),  # 判断验证码接口
        path('login/', obtain_jwt_token),  # 全局token,登录视图 使用djangorestframework-jwt==1.11.0
    
    ]
    
    
    
  5. 配置主路由django/urls.py

    from django.urls import path, re_path, include
    
    urlpatterns = [
        path('user/', include('user.urls'))
    ]
    

三、前端vue构建登录注册页面

在这里插入图片描述
在这里插入图片描述

  1. src/http/apis.js

    /* eslint-disable */
    // 用户登录
    import {get, post, put, del} from './index'
    export const postRegister = (params, headers) => post("/user/register/", params, headers)
    export const getVerification = (params, headers) => get("/user/verification/", params, headers)
    export const getisVerification = (params, headers) => get("/user/isverification/", params, headers)
    export const postLogin = (params, headers) => post("/user/login/", params, headers)
    export const postDinDin = (params, headers) => post("/user/dindin_url/", params, headers)
    
  2. 注册页面src/components/register.vue

    <template>
      <div>
        <center><h1>用户注册</h1></center>
    
        <a-form-item label="用户名" v-bind="formlayout">
          <a-input ref="userNameInput" v-model="username" placeholder="Basic usage">
            <a-icon slot="prefix" type="user"/>
            <a-tooltip slot="suffix" title="Extra information">
              <a-icon type="info-circle" style="color: rgba(0,0,0,.45)"/>
            </a-tooltip>
          </a-input>
    
        </a-form-item>
        <a-form-item label="密码" v-bind="formlayout">
          <a-input prefix="*" suffix="" v-model="password"/>
        </a-form-item>
    
    
        <a-form-item v-bind="buttonlayout">
    
          <a-button type="primary" @click="submit">注册</a-button>
    
        </a-form-item>
    
    
      </div>
    </template>
    
    <script type="text/javascript">
    
    import {postRegister} from "../http/apis";
    
    export default {
    
      data() {
    
        return {
    
          username: "",
          password: "",
          //表单样式
          formlayout: {
            //标签
            labelCol: {
              xs: {span: 10},
              sm: {span: 8}
            },
            //文本框
            wrapperCol: {
              xs: {span: 10},
              sm: {span: 3}
            }
          },
          //按钮样式
          buttonlayout: {
            //按钮
            wrapperCol: {
              xs: {
                span: 24,
                offset: 0
              },
              sm: {span: 16, offset: 8}
            }
          }
        }
    
      },
      //自定义方法
      methods: {
        submit: function () {
          let params = {
            username: this.username,
            password: this.password,
          }
          postRegister(params).then(res => {
            console.log(res)
            if (res.code == 200) {
              this.$router.push('/login')
            } else {
              alert("失败")
            }
          }).catch(err => {
            console.log(err)
          })
        }
      }
    
    
    };
    
    
    </script>
    
    <style type="text/css">
    
    
    </style>
    
  3. 登录页面src/components/login.vue

    <template>
      <div>
    
        <center><h1>用户登录</h1></center>
    
        <a-form-item label="用户名" v-bind="formlayout">
          <a-input ref="userNameInput" v-model="username" placeholder="Basic usage">
            <a-icon slot="prefix" type="user"/>
            <a-tooltip slot="suffix" title="Extra information">
              <a-icon type="info-circle" style="color: rgba(0,0,0,.45)"/>
            </a-tooltip>
          </a-input>
    
        </a-form-item>
        <a-form-item label="密码" v-bind="formlayout">
          <a-input prefix="*" suffix="" v-model="password"/>
        </a-form-item>
        <a-form-item label="验证码" v-bind="formlayout">
          <a-input v-model="verification" @blur="isVerification"/>
          <span v-if="isverification">验证码错误</span>
          <a-button type="primary" @click="clickVerification">点击发送验证码</a-button>
        </a-form-item>
    
        <a-form-item v-bind="buttonlayout">
          <a-button type="primary" @click="submit">登录</a-button>
          <img style="margin-left:20px;cursor:pointer;" @click="dingding" src="http://localhost:8000/static/dingding.png"/>
        </a-form-item>
    
      </div>
    </template>
    
    <script type="text/javascript">
    
    import {getisVerification, getVerification, postDinDin, postLogin} from "../http/apis";
    
    export default {
    
      data() {
        return {
          selected: "",
          startdate: "",
          dinDinUrl: "",
          username: "",
          password: "",
          verification: "",
          isverification: false,
          //表单样式
          formlayout: {
            //标签
            labelCol: {
              xs: {span: 24},
              sm: {span: 8}
            },
            //文本框
            wrapperCol: {
              xs: {span: 24},
              sm: {span: 3}
            }
          },
          //按钮样式
          buttonlayout: {
            //按钮
            wrapperCol: {
              xs: {
                span: 24,
                offset: 0
              },
              sm: {span: 16, offset: 8}
            }
          }
        }
    
      },
      //自定义方法
      methods: {
        //判断验证码
        isVerification() {
    
          getisVerification({verification: this.verification}).then(res => {
            console.log(res)
            if (res.code == 200) {
              this.isverification = false
            } else {
              this.isverification = true
            }
          }).catch(err => {
            console.log(err)
          })
    
        },
        //发送钉钉验证码
        clickVerification() {
          getVerification().then(res => {
            console.log(res)
          }).catch(err => {
            console.log(err)
          })
        },
        //钉钉登录
        dingding: function () {
          postDinDin().then(res => {
            console.log(res)
            this.dinDinUrl = res.dindin_url
            //打开新窗口跳转到此地址
            window.open(res.dindin_url)
          })
    
        },
        submit: function () {
          // let just = true;
          // just = this.isVerification() & just;
          if (this.isverification === false) {
            let params = {
              username: this.username,
              password: this.password,
            }
            //登录
            postLogin(params).then(res => {
              console.log(res)
              if (res.token) {
                localStorage.setItem("token", res.token)
                localStorage.setItem("username", res.username)
                localStorage.setItem("id", res.id)
              } else {
                alert("登录失败")
              }
            }).catch(err => {
              console.log(err)
            })
          }
    };
    
    
    </script>
    
    <style type="text/css">
    
    </style>
    
  4. src/router/index.js

    import Vue from 'vue'
    import Router from 'vue-router'
    import register from '@/components/register'
    import login from '@/components/login'
    
    Vue.use(Router)
    
    var routes = [
            {
              path:'/register',
              name:'register',
              component:register
            },
            {
              path:'/login',
              name:'login',
              component:login
            },
            
    ]
    
    export default new Router({
      routes:routes,
      mode:'history'   /*hash*/
    })
    
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
公众号、小程序、H5多端合一,多种营销功能强大稳定,满足企业零售、批发、分销等多种业务需求,高性价比商城系统。 一、营销活动 拼团、秒杀、砍价活动,拥有多风格主题,预售、抽奖、虚拟商品、积分商城 1.后台可一键复制活动商品; 2.拼团虚拟成团功能; 3.秒杀活动的后台时间段配置修改,设置的时间区间不能重叠; 4.砍价去除最大、最小砍价金额设置,改为砍价人数设置; 5.砍价列表; 优惠券 优惠券添加时增加会员优惠券; 平台发布新优惠券时,用户进入首页时弹窗提醒用户领取; 后台优惠券功能调整 1.去除优惠券模板; 2.订单支付之后赠送优惠券,商品添加时可选择优惠券关联;去除优惠券消费满赠,改为赠送券; 3.优惠券列表新增“复制”功能,可将当前的优惠券内容快速复制; 二、客服功能 1.新增PC端客服功能模块 2.移动端客服功能模块 三、用户管理 1.用户列表页可手动添加用户; 2.用户列表页增加“同步用户“按钮,可同步微信粉丝用户及更新用户信息; 3.用户标签添加一级分类 四、付费会员 1.商城付费会员功能,该功能与当前会员成长体系并行;后台可设置付费会员开启开关 2.付费会员:月费会员、季度会员、年度会员、终身会员 3.免费会员:后台可设置试用天数 4.实体卡会员:后台可设置会员卡,并有导出功能,方便线下印制实体会员卡 5.会员权益:(1)会员价(2)积分翻倍(3)运费折扣(4)会员优惠券(5)收银二维码付款折扣及返X倍积分 五、线下收银二维码 1.线下收银二维码,用户扫码后可选择余额支付/微信支付 2.付款后可获得积分 六、订单管理 1.新增电子面单打印 2.新增发票管理,用户下单时可选择开发票 3.发货扫码快递单号功能:手机端订单发货,填写单号时,可扫描快递的一维码 4.订单的抵扣上限 5.虚拟发货新增备注信息填写,发货之后用户订单详情页面增加备注信息展示 七、一号通 短信、商品采集、物流查询、面单打印多账户合一 八、商品 商品口令 1.增加复制商品口令功能,仅公众号商城(H5)自动复制; 2.后台添加口令,用户点击进去商品时自动复制该口令; 3.可自由添加淘宝口令、抖音口令等; 微信好物圈 对接微信好物圈功能,可分享移动端商品详情到微信圈子 九、数据统计 1.商品统计分析 2.用户统计分析 3.交易统计分析 十、短信签名 1.后台可修改短信签名,提交后需审核 2.短信验证码过期时间设置 备注:本源码为官方正版源码,非破解版,仅供下载研究学习,商业使用请联系购买授权!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值