微信小程序登入流程
前言:openid与unionid
openid:是用单个微信应用表示用户的唯一标识。亚洲:饼哥小程序上openid :123,那该用户再张成的小程序上他的opendid不是123,是其他任意一个值,上面的意思:同一用户再不用不同应用上的openid不同,但是再同一应用上唯一。
场景: 假设你们公司有2个小程序。但是你们老板想把用户做统一处理。比如新用户登入任意一个小程序,就发送发送礼包。但是只要再一个小程序上另过了,就不能再另一个上面领取。
unionnid:一个用户在多个小程序有唯一的标识
小程序的登入
1、小程序端执行wx.login()获取code
2、将code通过wx.request发送到后端,后端调用auth.code2Session接口得到openid和session_key
3、后端得到openid和session_key,进行存储,并自定义登入状态,我们生成一个key与openid和session_key相绑定。key相当于token把token返回到小程序中
4、小程序端保存token,然后下次请求如果需要登录状态,就把token带上。
一.首先前端先传code去后端
App({
onLaunch: function () {
let that = this
// 登录
wx.login({
success: res => {
// 发送 res.code 到后台换取 openId, sessionKey, unionId
console.log(res.code)
wx.request({
url: that.globalData.baseurl+"/login/",
data:{"code":res.code},
method:"POST",
success(e){
console.log(e)
}
})
}
}),
globalData: {
userInfo: null,
baseurl:"http://127.0.0.1:8000"
}
})
二.后端接受到请求中的code
class Login(APIView):
def post(self,request):
code = request.data.get('code')
print(code,type(code)) #061j8by70sZPPC1yynx70kCuy70j8byp <class 'str'>
三.后端获得code之后向微信官方发起请求获得相关参数
发起的链接
GET https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code
请求参数
属性 | 类型 | 默认值 | 必填 | 说明 |
---|---|---|---|---|
appid | string | 是 | 小程序 appId | |
secret | string | 是 | 小程序 appSecret | |
js_code | string | 是 | 登录时获取的 code | |
grant_type | string | 是 | 授权类型,此处只需填写 authorization_code |
返回值
返回的 JSON 数据包
属性 | 类型 | 说明 |
---|---|---|
openid | string | 用户唯一标识 |
session_key | string | 会话密钥 |
unionid | string | 用户在开放平台的唯一标识符,在满足 UnionID 下发条件的情况下会返回,详见 UnionID 机制说明。 |
errcode | number | 错误码 |
errmsg | string | 错误信息 |
errcode 的合法值
值 | 说明 | 最低版本 |
---|---|---|
-1 | 系统繁忙,此时请开发者稍候再试 | |
请求成功 | ||
40029 | code 无效 | |
45011 | 频率限制,每个用户每分钟100次 |
接着上述我们对于路径进行拼接成他需要的内容
wx_login.py
from . import settings
import requests
def get_login_info(code):
# https://api.weixin.qq.com/sns/jscode2session?appid={}&secret={}&js_code={}&grant_type=authorization_code
code_url = settings.code2Session.format(settings.AppId,settings.AppSecret,code)
response = requests.get(code_url)
json_response = response.json()
print("json_response",json_response)
if json_response.get("session_key"):
return json_response
else:
return False
settings.py
AppId="wxc35e10f7101fafa"
AppSecret="1479996b514da2428a89352717ae7c"
code2Session="https://api.weixin.qq.com/sns/jscode2session?appid={}&secret={}&js_code={}&grant_type=authorization_code"
四.加密并返回给前端一个标识方便后续操作
from rest_framework.views import APIView
from rest_framework.response import Response
from app01.wx import wx_login
from django.core.cache import cache
from .models import Wxuser
import time
import hashlib
class Login(APIView):
def post(self,request):
code = request.data.get('code')
print(code,type(code)) #061j8by70sZPPC1yynx70kCuy70j8byp <class 'str'>
if not code:
return Response({"status":1,"msg":"缺少参数"})
else:
user_data = wx_login.get_login_info(code)
# print(user_data)
if user_data:
val = user_data['session_key'] + "&" + user_data['openid']
md5 = hashlib.md5()
md5.update(str(time.clock()).encode("utf-8"))
md5.update(user_data["session_key"].encode("utf-8"))
# 生成一个唯一标识的key,用来给前台
key = md5.hexdigest()
# 设置缓存减少数据库的压力
cache.set(key,val)
has_user = Wxuser.objects.filter(openid=user_data['openid']).first()
if not has_user:
Wxuser.objects.create(openid=user_data['openid']) #将唯一标识存储到数据库
return Response({
"status":0,
"msg":"ok",
"data":{"token":key}
})
else:
return Response({"status":2,"msg":"缺少参数"})
五.前端在前没有任何问题的情况下对于标识信息进行接收
App({
onLaunch: function () {
let that = this
// 登录
wx.login({
success: res => {
// 发送 res.code 到后台换取 openId, sessionKey, unionId
console.log(res.code)
wx.request({
url: that.globalData.baseurl+"/login/",
data:{"code":res.code},
method:"POST",
success(e){
wx.setStorageSync("token", e.data.data.token)
}
})
}
}),
globalData: {
userInfo: null,
baseurl:"http://127.0.0.1:8000"
}
})