Django + Taro 前后端分离项目实现企业微信登录功能


Posted in Python onApril 07, 2022

前言

还是最近在做的一个小项目,后端用的是Django搭配RestFramework做接口,前端第一次尝试用京东开源的Taro框架来做多端(目前需要做用于企业微信的H5端和微信小程序)

本文记录一下企业微信登录的流程,上周看文档看得头晕晕的,其实很简单,封装好了就几行代码的事~

两种方式

  • 一种是先拼接好登录要用的地址authorize_url,回调地址设置成h5应用的网页入口,然后把authorize_url设置为企业微信里的应用主页就行,然后直接提取链接里的code
  • 另一种是在应用里拼接authorize_url地址,回调地址同样设置成h5应用的网页入口,然后应用里去请求authorize_url,然后提取链接里的code用来登录就行

说是两种,其实流程都是一样的,只不过第一种少去了前端拼接authorize_url以及首次请求的操作,为了方便起见,本文推荐使用第一种

思路

假设前端地址是http://xxx.com,那么我们用后端生成的企业微信登录地址中会把前端地址作为回调地址传入,在企业微信中访问登录地址之后,回跳转到我们的前端地址,并在路径中附上参数code,形式如下:

http://xxx.com?code=dkwawen123j13bk1

所以前端要做的就是拿到这串code,并提交给后端,让后端拿code去微信服务器换用户信息,就这样~

后端代码

企业微信登录的接口已经集成在我的「DjangoStarter」项目模板中,可以直接食用~

后端使用的是wechatpy这个库,非常好用,封装了微信开发的常用功能~

下面写一下两个关键的方法

from django.conf import settings
from django.contrib.auth import login
from django.contrib.auth.models import User
from rest_framework.authtoken.models import Token
from drf_yasg2.utils import swagger_auto_schema
from drf_yasg2 import openapi
from rest_framework.exceptions import APIException
from rest_framework import viewsets
from rest_framework.response import Response
from rest_framework.request import HttpRequest
from rest_framework.decorators import action
from wechatpy.enterprise import WeChatClient
from apps.core.serializers import UserSerializer
class WechatWork(viewsets.ViewSet):
    """微信企业号相关认证服务"""
    client = WeChatClient(
        settings.WECHAT_WORK_CONFIG['CORP_ID'],
        settings.WECHAT_WORK_CONFIG['SECRET'],
    )
    @swagger_auto_schema(operation_summary='获取微信企业号登录链接')
    @action(detail=False)
    def get_authorize_url(self, request):
        return Response({
            # todo 这里要写上前端应用入口地址
            'url': self.client.oauth.authorize_url('http://xxx.com')
        })
    @swagger_auto_schema(
        operation_summary='通过code登录',
        manual_parameters=[
            openapi.Parameter(
                name='code', in_=openapi.IN_QUERY,
                description='从微信企业号服务器获取到的code',
                type=openapi.TYPE_STRING)
        ])
    @action(detail=False, methods=['POST'])
    def login_by_code(self, request: HttpRequest):
        code = request.GET.get('code', None)
        try:
            user_info = self.client.oauth.get_user_info(code)
        except Exception as e:
            raise APIException(detail=e)
        phone = user_info['UserId']
        is_created_user = False
        if User.objects.filter(username=phone).exists():
            user_obj: User = User.objects.get(username=phone)
        else:
            is_created_user = True
            user_obj: User = User.objects.create_user(username=phone, password=phone)
        # 记录Django登录状态
        login(request, user_obj)
        # 生成drf token
        token, created = Token.objects.get_or_create(user=user_obj)
            'user': UserSerializer(user_obj).data,
            'user_info': user_info,
            'successful': True,
            'is_created_user': is_created_user,
            'token': token.key,
            'message': '企业微信登录成功',

写完接口配置一下路由(这里就不重复了)

然后请求这个get_authorize_url接口,得到一个地址

{
  "message": "请求成功",
  "code": 200,
  "data": {
    "url": "https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx386...&redirect_uri=http%3A%2F%2Fxxx.com&response_type=code&scope=snsapi_base#wechat_redirect"
  }
}

比如我上面写的应用入口地址是http://xxx.com,那么得到的企业微信登录地址就是

https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx386...&redirect_uri=http%3A%2F%2Fxxx.com&response_type=code&scope=snsapi_base#wechat_redirect

各个参数的意义看企业微信官方文档就行,我们不用细究

企业微信应用配置

接下来我们把这个地址设置成企业微信应用的主页

如图

Django + Taro 前后端分离项目实现企业微信登录功能

同时还得设置一下「可信域名」,在同个页面的最下方「开发者接口」处,把前端应用部署所在的服务器域名和端口(80就不用)填上去就行~

这样应用配置就好了

前端代码

前端用的是京东开源的Taro框架,我前一篇文章写到我终于用上了React,说的就是在Taro开发里用React+TypeScript,开发体验非常好 (除了这个框架有一些让人无语的坑之外)

前端要实现的就是从路径参数里取出code

我们看到,Taro官方文档就有关于路由参数的处理

所以可以这样写来获取code(函数式组件写法)

import { getCurrentInstance } from '@tarojs/taro'
let code getCurrentInstance().router?.params['code']

然而!这样在普通页面跳转是可以的

比如这种形式

http://xxx.com/#/pages/index/index?code=abc

但人家微信登录回调跳转的地址形式是这样

http://xxx.com?code=abc&state=#/pages/index/index

这根本就拿不到code啊 o(´^`)o

所以得自己用js封装一个

直接上代码了

// 解析微信redirect_uri地址中的code
export const getCodeFromUrl = (url: string) => {
  let code = ''
  let index = url.indexOf('?')
  let paramStr = url.substring(index + 1, url.length);
  let params = paramStr.split('&')
  params.forEach(element => {
    if (element.indexOf('code') >= 0) {
      code = element.substring(element.indexOf('=') + 1, element.length)
    }
  });
  return code
}

使用的时候

let code = getCodeFromUrl(window.location.href)

就可以拿到code了

code都有了,后面就不用多说了~

参考资料

wechatpy库文档:http://docs.wechatpy.org/zh_CN/stable/oauth.html

企业微信文档:https://developer.work.weixin.qq.com/document/path/91335

Taro框架文档:https://taro-docs.jd.com/taro/docs/router 

到此这篇关于Django + Taro 前后端分离项目实现企业微信登录 功能的文章就介绍到这了,更多相关Django前后端分离登录内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
用Python中的__slots__缓存资源以节省内存开销的方法
Apr 02 Python
Python批量转换文件编码格式
May 17 Python
20个常用Python运维库和模块
Feb 12 Python
PyQt5每天必学之事件与信号
Apr 20 Python
使用python中的in ,not in来检查元素是不是在列表中的方法
Jul 06 Python
kaggle+mnist实现手写字体识别
Jul 26 Python
python利用re,bs4,requests模块获取股票数据
Jul 29 Python
基于python操作ES实例详解
Nov 16 Python
2020最新pycharm汉化安装(python工程狮亲测有效)
Apr 26 Python
python使用QQ邮箱实现自动发送邮件
Jun 22 Python
PyTorch安装与基本使用详解
Aug 31 Python
如何利用Python实现n*n螺旋矩阵
Jan 18 Python
Python OpenCV实现图像模板匹配详解
Python实现日志实时监测的示例详解
Python使用PyYAML库读写yaml文件的方法
Apr 06 #Python
python+pytest接口自动化之token关联登录的实现
Python图像处理库PIL详细使用说明
Apr 06 #Python
Python可变与不可变数据和深拷贝与浅拷贝
Apr 06 #Python
Python 全局空间和局部空间
Apr 06 #Python
You might like
php高级编程-函数-郑阿奇
2011/07/04 PHP
LotusPhp笔记之:基于ObjectUtil组件的使用分析
2013/05/06 PHP
深入理解PHP几个算法:PHP冒泡、PHP二分法、PHP求素数、PHP乘法表
2013/06/06 PHP
php 使用html5实现多文件上传实例
2016/10/24 PHP
ThinkPHP实现图片上传操作的方法详解
2017/05/08 PHP
javascript KeyDown、KeyPress和KeyUp事件的区别与联系
2009/12/03 Javascript
jquery如何实现锚点链接之间的平滑滚动
2013/12/02 Javascript
JavaScript执行顺序详细介绍
2013/12/04 Javascript
jQuery的animate函数学习记录
2014/08/08 Javascript
javascript中if和switch,==和===详解
2015/07/30 Javascript
javascript作用域、作用域链(菜鸟必看)
2016/06/16 Javascript
js原生Ajax的封装和原理详解
2017/03/11 Javascript
js字符串处理之绝妙的代码
2019/04/05 Javascript
jQuery事件委托代码实践详解
2019/06/21 jQuery
python获取网页状态码示例
2014/03/30 Python
Python中使用items()方法返回字典元素对的教程
2015/05/21 Python
python获取指定路径下所有指定后缀文件的方法
2015/05/26 Python
Python字符串拼接六种方法介绍
2017/12/18 Python
python发送告警邮件脚本
2018/09/17 Python
Python Scapy随心所欲研究TCP协议栈
2018/11/20 Python
Pycharm保存不能自动同步到远程服务器的解决方法
2019/06/27 Python
PyCharm-错误-找不到指定文件python.exe的解决方法
2019/07/01 Python
pytorch打印网络结构的实例
2019/08/19 Python
Python.append()与Python.expand()用法详解
2019/12/18 Python
Python流程控制常用工具详解
2020/02/24 Python
python烟花效果的代码实例
2020/02/25 Python
Python并发concurrent.futures和asyncio实例
2020/05/04 Python
Python 获取异常(Exception)信息的几种方法
2020/12/29 Python
CSS3 animation实现逐帧动画效果
2016/06/02 HTML / CSS
台湾网友喜爱的综合型网路购物商城:Yahoo! 奇摩购物中心
2018/03/10 全球购物
德国高品质男装及配饰商城:Cultizm(Raw Denim原色牛仔裤)
2018/04/16 全球购物
爱晚亭导游词
2015/02/09 职场文书
幼儿园重阳节活动总结
2015/05/05 职场文书
社区志愿者服务心得体会
2016/01/22 职场文书
MyBatis自定义SQL拦截器示例详解
2021/10/24 Java/Android
Python使用BeautifulSoup4修改网页内容
2022/05/20 Python