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之玩转字符串(2)
Sep 14 Python
Python函数参数类型*、**的区别
Apr 11 Python
详解Python中列表和元祖的使用方法
Apr 25 Python
Python快速排序算法实例分析
Nov 29 Python
Python获取当前公网ip并自动断开宽带连接实例代码
Jan 12 Python
Python 12306抢火车票脚本
Feb 07 Python
python调用tcpdump抓包过滤的方法
Jul 18 Python
深入理解Python异常处理的哲学
Feb 01 Python
Python内置数据类型list各方法的性能测试过程解析
Jan 07 Python
解决Tensorflow 使用时cpu编译不支持警告的问题
Feb 03 Python
基于pytorch中的Sequential用法说明
Jun 24 Python
为2021年的第一场雪锦上添花:用matplotlib绘制雪花和雪景
Jan 05 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,ajax实现分页
2008/03/27 PHP
php数组函数序列之prev() - 移动数组内部指针到上一个元素的位置,并返回该元素值
2011/10/31 PHP
PHP调用Mailgun发送邮件的方法
2017/05/04 PHP
基于CI(CodeIgniter)框架实现购物车功能的方法
2018/04/09 PHP
JavaScript 异步调用框架 (Part 3 - 代码实现)
2009/08/04 Javascript
左右悬浮可分组的网站QQ在线客服代码(可谓经典)
2012/12/21 Javascript
Javascript全局变量var与不var的区别深入解析
2013/12/09 Javascript
JS中prototype的用法实例分析
2015/03/19 Javascript
浅谈Nodejs观察者模式
2015/10/13 NodeJs
微信小程序 页面跳转传递值几种方法详解
2017/01/12 Javascript
详谈for循环里面的break和continue语句
2017/07/20 Javascript
vue 自定义 select内置组件
2018/04/10 Javascript
vue .sync修饰符的使用详解
2018/06/15 Javascript
浅谈在react中如何实现扫码枪输入
2018/07/04 Javascript
vue头部导航动态点击处理方法
2018/11/02 Javascript
利用vue重构有赞商城的思路以及总结整理
2019/02/21 Javascript
微信小程序自定义弹窗实现详解(可通用)
2019/07/04 Javascript
layui点击弹框页面 表单请求的方法
2019/09/21 Javascript
微信小程序实现上传多个文件 超过10个
2020/03/30 Javascript
JS+CSS实现3D切割轮播图
2020/03/21 Javascript
Ant Design的Table组件去除
2020/10/24 Javascript
解决Vue keep-alive 调用 $destory() 页面不再被缓存的情况
2020/10/30 Javascript
vue中使用echarts的示例
2021/01/03 Vue.js
python装饰器与递归算法详解
2016/02/18 Python
Scrapy框架CrawlSpiders的介绍以及使用详解
2017/11/29 Python
python list数据等间隔抽取并新建list存储的例子
2019/11/27 Python
美国时尚孕妇装品牌:A Pea in the Pod
2017/07/16 全球购物
Pat McGrath Labs官网:世界上最有影响力的化妆师推出的彩妆品牌
2018/01/07 全球购物
美国宠物美容和宠物用品购物网站:Cherrybrook
2018/12/07 全球购物
俄罗斯茶和咖啡网上商店:Tea.ru
2021/01/26 全球购物
在Java开发中如何选择使用哪种集合类
2016/08/09 面试题
如何提高SQL Server的安全性
2016/07/25 面试题
通信工程专业毕业生推荐信
2013/12/25 职场文书
素食餐饮项目创业计划书
2014/02/02 职场文书
自强自立美德少年事迹材料
2014/08/16 职场文书
师德师风自查总结
2014/10/14 职场文书