后端解析 wx.getUserInfo 中的用户信息
- 我们用encryptedData和iv,进行解密,必须要用到session_key,所以用必须是登入状态。
- 但是session_key是有有效期。而且session_key的有效期,不是一个固定值,他是通过用户行为来决定,session_key的有效期时间。
- 但是我们可以通过 wx.checkSession 来判断有没有过期。
- 保证 session_key 没有过期的情况下。我们将 iv, encryptedData, token (登入凭证)发送到后端
- 后端使用官方提供的sdk,进行解密。
- 解密成功以后保存到数据,数据库的字符集一定要是utf8mb4,才能保存表情包
wxml
<button bindgetuserinfo="user1" open-type="getUserInfo">用户信息</button>
js
// pages/test/test.js
const app = getApp()
Page({
user1: function () {
// 可以通过 wx.getSetting 先查询一下用户是否授权了 "scope.record" 这个 scope
wx.getSetting({
success(res) {
if (res.authSetting['scope.userInfo']) {
wx.checkSession({
success() {
//session_key 未过期,并且在本生命周期一直有效
wx.getUserInfo({
success: (res) => {
console.log("res", res)//这个res里面就是用户信息
//将数据发送后端
wx.request({
//这里是发送iv,encryptedData,还没写
url: app.globalData.baseurl + "getinfo/",
data: {
iv: res.iv,
encryptedData: res.encryptedData,
token: wx.getStorageSync('token')
},
method: "POST",
success: (e) => {
console.log("后台返回的数据", e)
}
})
},
})
},
fail() {
// session_key 已经失效,需要重新执行登录流程
// 要重新执行登录流程
app.my_login()
wx.getUserInfo({
success: (res) => {
console.log("res", res) // 这个 res 里面就是用户信息
// 将数据发送后端
wx.request({
url: ''
})
},
})
}
})
}
}
})
},
})
后端
urls.py
url(r'^getinfo/', views.GetInfo.as_view()),
WXBizDataCrypt.py
import base64
import json
from Crypto.Cipher import AES
from app01.wx.settings import AppId
class WXBizDataCrypt:
def __init__(self, appId, sessionKey):
self.appId = appId
self.sessionKey = sessionKey
def decrypt(self, encryptedData, iv):
# base64 decode
sessionKey = base64.b64decode(self.sessionKey)
encryptedData = base64.b64decode(encryptedData)
iv = base64.b64decode(iv)
cipher = AES.new(sessionKey, AES.MODE_CBC, iv)
decrypted = json.loads(self._unpad(cipher.decrypt(encryptedData)))
if decrypted['watermark']['appid'] != self.appId:
raise Exception('Invalid Buffer')
return decrypted
def _unpad(self, s):
return s[:-ord(s[len(s)-1:])]
@classmethod
def get_info(cls,sessionKey,encryptedData,iv):
return cls(AppId, sessionKey).decrypt(encryptedData, iv)
views.py
from app01.wx import WXBizDataCrypt
class GetInfo(APIView):
def post(self, request):
param = request.data
if param.get('iv') and param.get('token') and param.get('encryptedData'):
session_key_openid = cache.get(param.get("token"))
if session_key_openid:
session_key, openid = session_key_openid.split("&")
# 解密
user_info = WXBizDataCrypt.WXBizDataCrypt.get_info(session_key, param.get('encryptedData'),
param.get('iv'))
# 解密成功,得到用户信息
# print(user_info)
save_data = {
"name": user_info['nickName'],
"avatar": user_info['avatarUrl'],
"language": user_info['language'],
"province": user_info['province'],
"city": user_info['city'],
"country": user_info['country'],
}
Wxuser.objects.filter(openid=openid).update(**save_data)
return Response({
"status": 0,
"msg": "ok",
"data": save_data
})
else:
return Response({"code": 2, "msg": "无效的token"})
else:
return Response({"code": 1, "msg": "缺少参数"})
解密成功以后保存到数据,数据库的字符集一定要是 utf8mb4,才能保存表情包
settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'xcx',
'HOST': '127.0.0.1',
'PORT': 3306,
'USER': 'root',
'PASSWORD': '123123',
'OPTIONS': {'charset': 'utf8mb4'},
}
}
如官方的 sdk 没有 Crypto 包用下面的方法解决:
pip install pycryptodome