后端解析用户信息

后端解析 wx.getUserInfo 中的用户信息

  1. 我们用encryptedData和iv,进行解密,必须要用到session_key,所以用必须是登入状态。
  2. 但是session_key是有有效期。而且session_key的有效期,不是一个固定值,他是通过用户行为来决定,session_key的有效期时间。
  3. 但是我们可以通过 wx.checkSession 来判断有没有过期。
  4. 保证 session_key 没有过期的情况下。我们将 iv, encryptedData, token (登入凭证)发送到后端
  5. 后端使用官方提供的sdk,进行解密。
  6. 解密成功以后保存到数据,数据库的字符集一定要是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()),

下载官方提供的 SDK

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 
原文地址:https://www.cnblogs.com/kai-/p/12488332.html