Django+Taro项目实现企业微信登录
前言 还是最近在做的一个小项目,后端用的是Django搭配RestFramework做接口,前端第一次尝试用京东开源的Taro框架来做多端(目前需要做用于企业微信的H5端和微信小程序) 本文记录一下企业微信登录的流程,上周看文档看得头晕晕的,其实很简单,封装好了就几行代码的事~ 两种方式 一种是先拼接好登录要用的地址authorize_url,回调地址设置成h5应用的网页入口,然后把authori
目录7 个章节
前言
还是最近在做的一个小项目,后端用的是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)
return Response({
'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
各个参数的意义看企业微信官方文档就行,我们不用细究
企业微信应用配置
接下来我们把这个地址设置成企业微信应用的主页
如图

同时还得设置一下「可信域名」,在同个页面的最下方「开发者接口」处,把前端应用部署所在的服务器域名和端口(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都有了,后面就不用多说了~
参考资料
_EOF_
Django+Taro项目实现企业微信登录
- 本文作者:
- 程序设计实验室
- 版权声明:
- 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
相关文章
使用django-treebeard实现树类型存储与编辑
无非继承MP_Node配置TreeAdmin,拖拽编辑树节点。可视化?也就django-treebeard能用,其他要么停更要么功能拉胯。初始化数据?手动导入,否则admin连按钮都没有,bug。接口输出无非path和depth,自己实现更舒服。
2024-08-11 · Django · 约 1 分钟
使用easy_thumbnails轻松为图片创建缩略图
关于Django的缩略图 我在Django的官方文档里看了一下,没有找到有关缩略图的官方库,不过在Django的Wiki里头倒是看到了一篇关于使用缩略图的介绍,请参考:https://code.djangoproject.com/wiki/ThumbNails 关于Problem的描述 The majority of applications that have images, probably
2022-08-26 · Django · 约 1 分钟
Django的信号机制入门
概念 django自带一套信号机制来帮助我们在框架的不同位置之间传递信息。也就是说,当某一事件发生时,信号系统可以允许一个或多个发送者(senders)将通知或信号(signals)发送给一组接受者(receivers)。 (感觉就很像Qt的信号与槽机制) 信号系统包含以下三要素: 发送者-信号的发出方 信号-信号本身 接收者-信号的接受者 Django内置了一整套信号,下面是一些比较常用的: 在
2022-08-26 · Django · 约 1 分钟
DjangoAdmin使用合集
DjangoAdmin DjangoAdmin本身就是一套大而全的系统,官方文档中介绍了很多配置方法,但仍然有大量的骚操作是文档中没有的,所以遇到特殊需求的时候,求助文档不一定有用。 在我看来 DjangoAdmin 虽然能快速生成一套管理后台,但如果要做大量特殊需求的定制,其成本不亚于用 Vue/React 重新开发一套,简单的使用成本不高,但深入定制的话需要对 DjangoAdmin 的工作流
2023-04-09 · Django · 约 1 分钟
讨论
共 0 条加载评论中…