❥微信小程序❥----授权

    首先先说我们的 获取用户地址 wx.chooseAddress 获取用户收货地址。调起用户编辑收货地址原生界面,并在编辑完成后返回用户选择的地址。调用前需要用户授权

wx.authorize

  提前向用户发起授权请求。调用后会立刻弹窗询问用户是否同意授权小程序使用某项功能或获取用户的某些数据,但不会实际调用对应接口。如果用户之前已经同意授权,则不会出现弹窗,直接返回成功。更多用法详见 用户授权

  对就是这里用户的授权 唯一和 wx.chooseAddress不一样的是 有了一个参数 scope

scope 需要获取权限的 scope,详见 scope 列表

  示例代码:

 authorize:function(){
    // 通过getSetting来获取用户的授权
    wx.getSetting({
      success(res){
        console.log(res)
        // 判断用户的授权中有没有record 没有
        // 说明没有授权 那就启动我们的授权
        if(!res.authSetting['scope.record']){
          wx.authorize({
            // 这里的scope就是我们需要授权的功能
            scope: 'scope.record',
            // 如果成功说明用户已经点击授权了所以我们
            // 调用语音接口
            success(res){
              wx.startRecord()
            }
          })
          
        }
      }
    })
  }

   这里是我们的scope列表 ==点击==

wx.getUserInfo

  那么我们开始掉用户信息表 调用前需要 用户授权 scope.userInfo

withCredentials 是否带上登录态信息。当 withCredentials 为 true 时,要求此前有调用过 wx.login 且登录态尚未过期,此时返回的数据会包含 encryptedData, iv 等敏感信息;当 withCredentials 为 false 时,不要求有登录态,返回的数据不包含 encryptedData, iv 等敏感信息。
lang 显示用户信息的语言

  success回调函数的参数

userInfo 用户信息对象,不包含 openid 等敏感信息
rawData 不包括敏感信息的原始数据字符串,用于计算签名
signature
使用 sha1( rawData + sessionkey ) 得到字符串,用于校验用户信息,详见 用户数据的签名验证和加解密

encryptedData 包括敏感数据在内的完整用户信息的加密数据,详见 用户数据的签名验证和加解密
iv 加密算法的初始向量,详见 用户数据的签名验证和加解密
cloudID
敏感数据对应的云 ID,开通云开发的小程序才会返回,可通过云调用直接获取开放数据,详细见云调用直接获取开放数据

 

   但是我这里想说   所有的授权都可以使用wx.authorize 来调起 但是我们的 userinfo 不行 必须使用一个按钮来调起

   补充: wx.authorize 是用来调起弹框的 而 你的 startrecord 才是真正的授权

   也就是说 我把 startrecord注释了 他还是会调起 弹框 但是 不会 真正的授权

      想要调起用户信息必须open-type 指定为 getUserInfo 且 bindgetuserinfo

<button wx:if="{{canIUse}}" open-type="getUserInfo" bindgetuserinfo="bindGetUserInfo">授权登录</button>

 

   登陆授权

from rest_framework.views import APIView
from rest_framework.response import Response
from app01.wx import setting
import requests
import time, hashlib
from django.core.cache import cache
from app01 import models

# 获取login_key
def get_secret_key(data):
    now = time.time()
    key = str(now) + data
    md5 = hashlib.md5()
    md5.update(key.encode('utf-8'))
    return md5.hexdigest()

class Login(APIView):
    def post(self, request, *args, **kwargs):
        # 获取code
        code = request.data.get('code')
        # 发起获取openid session_key请求
        url = setting.URL.format(setting.APP_ID,setting.APP_SECRET,code)
        try:
            session_key, open_id = list(requests.get(url).json().values())
            # 拿到我们的session和open_id 后 本地保存 自定义登陆状态返回
        except:
            return Response({'status':404, 'msg':"登陆失败"})
        secret_key = get_secret_key(open_id)
        secret_value = f"{session_key}&{open_id}"
        # 保存redis数据库
        cache.set(secret_key, secret_value)
        # 判断用户是否是第一次登陆
        user_obj = models.Wxuser.objects.filter(openid=open_id).first()
        if not user_obj:
            # 没有就创建
            models.Wxuser.objects.create(openid=open_id)
        return Response({'status':200 , 'msg':'登陆成功', 'token':secret_key})

 

 用户数据获取接口

  全部写代码了哈, 都有注释的.

  下面是 微信小程序 获取到用户的头像带有表情包的设置 同时数据库也要是utf8mb4

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'userinfo_demo',
        'USER':'root',
        'PASSWORD':'123',
        'OPTIONS':{'charset':'utf8mb4'}
    }
}

 

   ==加密数据解密算法==

  getuser:function(res){
    console.log(res)
    // 校验用户的session是否过期
    // 如果过期的话那就 从新让用户授权
    wx.checkSession({
      success(){
        // 或者使用wx.getUserInfo来获取数据
        wx.getUserInfo({
          success(res){
            // 这里的 res 和上面的 res都是一样的
            console.log(res)
            // 然后把这些信息发送给后台
            wx.request({
              url: app.globalData.url+'/get_userinfo/',
              method:'POST',
              header:{'content-type':'application/json'},
              // 携带上我们的 login_key
              data: {
                'encryptedData':res.encryptedData,
                'iv': res.iv,
                'login_key':wx.getStorageSync('login_key')
              },
              success(res){
                console.log(res)
              },
              fail(res){
                console.log(res, '用户数据获取失败')
              }
            })
          }
          
        })
      },
      fail(){
        this.login()
      }
      
    })
from rest_framework.serializers import ModelSerializer
class GetUserInfoModelSerializer(ModelSerializer):
    class Meta:
        model = models.Wxuser
        fields = '__all__'

# 获取用户信息
class GetUserInfo(APIView):
    def post(self,request, *args, **kwargs):
        token = request.data.get('login_key')
        iv = request.data.get('iv')

        encryptedData = request.data.get('encryptedData')
        # 判断是否缺少参数
        if not (token and iv and encryptedData):
            return Response({"status":404,'msg':'缺少参数'})
        # 拿到我们的session和openid
        session_key, open_id = cache.get(token).split('&')
        # 解密用户数据
        data = WXBizDataCrypt.get_info(session_key,iv,encryptedData)
        save_data = {
            "name": data['nickName'],
            "avatar": data['avatarUrl'],
            "language": data['language'],
            "province": data['province'],
            "city": data['city'],
            "country": data['country'],
        }
        # 更新数据库
        models.Wxuser.objects.filter(openid=open_id).update(**save_data)
        user_obj = models.Wxuser.objects.filter(openid=open_id).first()
        data = GetUserInfoModelSerializer(instance=user_obj,many=False).data
        print(data)
        return Response({"status":200,'msg':'请求成功', 'data':data})
import base64
from . import setting
import json
from Crypto.Cipher import AES

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, session_key, iv, encryptedData):
        return WXBizDataCrypt(setting.APP_ID, session_key).decrypt(encryptedData, iv)

 

 

posted @ 2019-11-07 19:53  LD_Dragon  阅读(396)  评论(0编辑  收藏  举报