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开发编码规范
Sep 08 Python
Python实现查找系统盘中需要找的字符
Jul 14 Python
Python代码解决RenderView窗口not found问题
Aug 28 Python
python中利用Future对象异步返回结果示例代码
Sep 07 Python
python使用sqlite3时游标使用方法
Mar 13 Python
Python3.4学习笔记之 idle 清屏扩展插件用法分析
Mar 01 Python
python对文件目录的操作方法实例总结
Jun 24 Python
在Python中画图(基于Jupyter notebook的魔法函数)
Oct 28 Python
在Python 的线程中运行协程的方法
Feb 24 Python
django queryset 去重 .distinct()说明
May 19 Python
python 利用toapi库自动生成api
Oct 19 Python
Django利用elasticsearch(搜索引擎)实现搜索功能
Nov 26 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入门教程 精简版
2009/12/13 PHP
php+html5实现无刷新图片上传教程
2016/01/22 PHP
PHP通过加锁实现并发情况下抢码功能
2016/08/10 PHP
php版微信自动获取收货地址api用法示例
2016/09/22 PHP
关于UTF-8的客户端用AJAX方式获取GB2312的服务器端乱码问题的解决办法
2010/11/30 Javascript
基于Jquery的表格隔行换色,移动换色,点击换色插件
2010/12/22 Javascript
Prototype源码浅析 Number部分
2012/01/16 Javascript
Jquery submit()无法提交问题
2013/04/21 Javascript
jquery实现的美女拼图游戏实例
2015/05/04 Javascript
Position属性之relative用法
2015/12/14 Javascript
使用AngularJS编写多选按钮选中时触发指定方法的指令代码详解
2017/07/24 Javascript
JavaScript 中的 this 简单规则
2017/09/19 Javascript
vue使用axios时关于this的指向问题详解
2017/12/22 Javascript
在Vue组件中使用 TypeScript的方法
2018/02/28 Javascript
Koa项目搭建过程详细记录
2018/04/12 Javascript
OpenLayers3实现图层控件功能
2020/09/25 Javascript
[01:50]WODOTA制作 DOTA2中文宣传片《HERO》
2013/04/28 DOTA
[45:59]完美世界DOTA2联赛PWL S2 FTD vs GXR 第二场 11.22
2020/11/24 DOTA
Python使用PIL库实现验证码图片的方法
2016/03/11 Python
Python实现的批量修改文件后缀名操作示例
2018/12/07 Python
Python 排序最长英文单词链(列表中前一个单词末字母是下一个单词的首字母)
2020/12/14 Python
socket.io 和canvas 实现的共享画板功能
2019/05/22 HTML / CSS
英国最大的线上保健品零售商之一:Vitamin Planet
2016/12/01 全球购物
Charlotte Tilbury英国官网:英国彩妆品牌
2017/05/26 全球购物
罗马尼亚在线杂货店:Pilulka.ro
2019/09/28 全球购物
毕业生自荐信的主要内容
2013/10/29 职场文书
小班重阳节活动方案
2014/02/08 职场文书
交通事故赔偿协议书
2014/04/15 职场文书
大学国际贸易专业自荐信
2014/06/05 职场文书
群众路线对照检查材料
2014/09/22 职场文书
司机岗位职责
2015/02/04 职场文书
个人先进事迹总结
2015/02/26 职场文书
公司奖励通知
2015/04/21 职场文书
公务员学习中国梦心得体会
2016/01/05 职场文书
QT与javascript交互数据的实现
2021/05/26 Javascript
MySQL的全局锁和表级锁的具体使用
2021/08/23 MySQL