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爬虫抓取豆瓣电影TOP100及用户头像的方法
Jan 20 Python
python版本的读写锁操作方法
Apr 25 Python
python设计模式大全
Jun 27 Python
基于python的七种经典排序算法(推荐)
Dec 08 Python
Python数据拟合与广义线性回归算法学习
Dec 22 Python
celery4+django2定时任务的实现代码
Dec 23 Python
python多线程共享变量的使用和效率方法
Jul 16 Python
python+openCV调用摄像头拍摄和处理图片的实现
Aug 06 Python
Python 单例设计模式用法实例分析
Sep 23 Python
Python3实现监控新型冠状病毒肺炎疫情的示例代码
Feb 13 Python
基于pytorch padding=SAME的解决方式
Feb 18 Python
Django rest framework如何自定义用户表
Jun 09 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/12/29 PHP
PHP中计算字符串相似度的函数代码
2012/12/29 PHP
php中怎么搜索相关联数组键值及获取之
2013/10/17 PHP
php格式化电话号码的方法
2015/04/24 PHP
详解PHP匿名函数与注意事项
2016/03/29 PHP
浅析PHP类的反射来实现依赖注入过程
2018/02/06 PHP
JavaScript 滚轮事件使用说明
2010/03/07 Javascript
基于jQuery的图片剪切插件
2011/08/03 Javascript
轻松创建nodejs服务器(9):实现非阻塞操作
2014/12/18 NodeJs
JS实现的自定义右键菜单实例二则
2015/09/01 Javascript
JS回调函数简单用法示例
2017/02/09 Javascript
canvas实现弧形可拖动进度条效果
2017/05/11 Javascript
JS 组件系列之Bootstrap Table的冻结列功能彻底解决高度问题
2017/06/30 Javascript
JS实现数组深拷贝的方法分析
2019/03/06 Javascript
vue-cli3中vue.config.js配置教程详解
2019/05/29 Javascript
JS桶排序的简单理解与实现方法示例
2019/11/25 Javascript
vue滑动吸顶及锚点定位的示例代码
2020/05/10 Javascript
JavaScript实现刮刮乐效果
2020/11/01 Javascript
[02:02]特效爆炸!DOTA2珍宝之瓶待你开启
2018/08/21 DOTA
Python合并多个装饰器小技巧
2015/04/28 Python
Python正则表达式使用经典实例
2016/06/21 Python
深入理解Python单元测试unittest的使用示例
2017/11/18 Python
Python图像滤波处理操作示例【基于ImageFilter类】
2019/01/03 Python
Python3爬虫之自动查询天气并实现语音播报
2019/02/21 Python
Python----数据预处理代码实例
2019/03/20 Python
Django 过滤器汇总及自定义过滤器使用详解
2019/07/19 Python
django使用haystack调用Elasticsearch实现索引搜索
2019/07/24 Python
Python使用matplotlib实现交换式图形显示功能示例
2019/09/06 Python
python小项目之五子棋游戏
2019/12/26 Python
如何通过安装HomeBrew来安装Python3
2020/12/23 Python
CSS3区域模块region相关编写示例
2015/08/28 HTML / CSS
美国高档帽子网上商店:Hats.com
2018/08/09 全球购物
大学生就业自荐信
2013/10/26 职场文书
作风建设年活动总结
2014/08/27 职场文书
2015团员个人年度总结
2015/11/24 职场文书
Oracle数据库中通用的函数实例详解
2022/03/25 Oracle