小程序登录、授权

一、总结:

1 如何自定义组件
- 组件和页面一样,也是由四个文件组成,所以我们自定义组件的时候,模拟pages文件夹,把所有的所有的组件都放在一个文件夹中,每个组件又由一个文件夹包裹,方便管理,在对应目录右击,选择新建组件
- 如果页面中要使用我们定义好的组件,必须现在对应页面的json文件中进行引用:代码如下
{
    "usingComponents": {
      "com" : "/componentes/com/com" //形式 :组件名:组件路径
          }
}
在该页面的wxml文件中,就可以直接使用:
<com name = "{{name1}}" bind:jia1 ="jia"></com>
-页面向组件传值:要先在组件的js文件中的properties定义属性,在页面中就可以对这个组件的属性进行赋值了。
-组件向页面传递事件:组件要先捕获事件,然后事件的响应函数里面用triggerEvent来把事件抛出来,然后页面捕获,组件抛出的事件。

2 小程序路由跳转js版
- wx.switchTab 只能跳转到tabbar页面 ,并关闭所有非tabbar页面,而且路由不能传值
- wx.reLaunch 关闭所有的页面,并打开你要跳转的页面.路由是可以携带参数
- wx.redirectTO 关闭当前的页面,跳转到应用内的某个页面,但是不能跳转到tabbar页面,路由可以携带参数
- wx.navigateTo 保留当前的页面,跳转到应用内的某个页面,但是不能跳转到tabbar页面,路由也可以携带参数。如果使用他,就会出现回退按钮,并且也可以用wx.navigateBack来进行返回
- wx.navigateBack 里面有delta参数,他是用来表示回退多少个页面。

3 wx.request 相当于发送ajax请求
wx.request({
  url: //请求路径
  data:{} //请求发送的数据
  header:{} //请求头
  methond: "" //请求方法
  success(res){
      console.log(res.data)
  }
   
})

二、小程序的登入

1、搜微信小程序登录 文档

 

 

 

 

 

 2、小程序登录 流程图

 

 

 

 

 

 

 3、openid与unionid

openid:是用单个微信应用 表示用户的唯一标识。亚洲:饼哥小程序上openid :123,那该用户在张成的小程序上他的opendid不是123,是其他任意一个值。
上面的意思:同一用户在不同应用上的openid不同,但是在同一应用上唯一。

场景: 假设你们公司有2个小程序。但是你们老板想把用户做统一处理。比如新用户登入任意一个小程序,就发送礼包。但是只要在一个小程序上领过了,就不能再在另一个上面领取。
unionnid:一个用户在多个小程序有唯一的标识

4、小程序登录 步骤
1 小程序端执行wx.login()获取code

 

2 将1中的code发送到后端,并拿回token

后端
建文件

 配置路由

 

 视图类

 

小程序结果:

 后台结果

3、后端调用auth.code2Session这个接口,后台就能得到小程序的 openid和session_key,并把openid存入数据库

 

 

 openid 只能给一个APPID使用

 

 把openid 存进缓存数据库中,需要redis配置

 views文件夹中的user

from rest_framework.views import APIView
from rest_framework.response import Response
from app01.wx import wx_login
from django.core.cache import cache # 导入缓存数据库
import hashlib,time
from app01.models import Wxuser
class Login(APIView):
    # 接收从小程序发过来request中的code
    def post(self,request):
        param = request.data
        if not param.get("code"):  
            return Response({"status":1,"msg":"缺少参数"}) 
        else:
            code = param.get("code")
            # 调用wx_login文件中 get_login_info方法
            user_data = wx_login.get_login_info(code)
            if user_data:
               print(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 = md5.hexdigest()   # 生成随机字符串
               cache.set(key,val,86400)      # 把字符串key 和val 存进缓存数据库里. 86400有效期时间
               # 获取 微信用户对象
               has_user = Wxuser.objects.filter(openid=user_data['openid']).first()
               if not has_user:
                   # 把openid存如数据库,因为它是用户的唯一标识
                   Wxuser.objects.create(openid=user_data['openid'])
               return Response({
                   "status":0,
                   "msg":"ok",
                   "data":{"token":key}
               })
            else:
                return  Response({"status":2,"msg":"无效的code"})

 

 models

 
3 以上代码实现了:自定义登入状态,我们生成一个key与openid和session_key相绑定。把key返回到小程序中

4 小程序端保存,然后下次请求需要登入的接口的时候,把key带上。

三、小程序授权

去看 开发文档

1 因为部分功能需要用同意后才能使用。

2 wx.getSetting来判断该用户有没有对接口授权,判断哪个接口,就必须给wx.getSetting传对应的scope值
一个scope值对应这个一个或多个接口

3 如果从wx.getSetting中发现scope值是false,表示a没有授权,我们可以通过wx.authorize发起授权,对那个接口授权,就给wx.authorize传对应scope值就可以了。如果用用户同意授权,就可以直接使用对应的接口了。

4 但是scope.userInfo没有办法使用wx.authorize自动弹起弹框。必须要用户手动点击按钮唤起授权弹框。
代码格式:
<button open-type="getUserInfo" bindgetuserinfo="user1">用户信息</button>
我们可以再响应函数的参数中获取用户信息。e.detail,这个和直接调用wx.getUserInfo获取的内容一样。

 

 案例:

1、

 

 2

 

 3

// pages/test3/test3.js
Page({
  /*页面的初始数据*/
  data: {
  },
  click:function() {
    wx.navigateBack({
     delta:2
    })
  },
  lu:function(){
    wx.getSetting({//查是否授权
      success(res) {//结果
        if (!res.authSetting['scope.record']) {//scope相当于key 。 record(录音) 是值
          wx.authorize({// 表示授权
            scope: 'scope.record',
            success () {
              // 用户已经同意小程序使用录音功能,后续调用 wx.startRecord 接口不会弹窗询问
              wx.startRecord()
              //用户 不同意 就进行fail回调。再点击也不会弹出授权框了
            },fail(){
              console.log("你没有授权")
            }
          })
        }else{
          // 授权成功 据可以使用已授权的功能了
          wx.startRecord()
        }
      }
    })
    
  },
  user:function () {
    wx.getSetting({
      success(res) {
        if (!res.authSetting['scope.userInfo']) {

          wx.authorize({
            scope: 'scope.userInfo',
            success () {
              console.log("进来了")
            }
          })

        }else{
          console.log("已经授权")
        }
      }
    })
  },
  user1:function (e) {
    console.log("e",e.detail)  //查用户的信息
    wx.getSetting({//查是否授权
      success(res) {//结果
        if (res.authSetting['scope.userInfo']) {// r如果授权了
         
          wx.getUserInfo({//查用户的信息
            success: (res) => {
              console.log("res",res)
            },
          })
        }
      }
    })
    
  }
})
结果:如下图

 

 

 看开发文档

 

 开放数据校验与解密

 

 

 

 

 

 

 

 

 总结:

   后端,如何解析wx.getUserInfor中的用户信息。

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,才能保存表情包

看开发文档

 

总结的 案例 :

1、

//app.js
App({
  /* 当小程序初始话完成,会触发onlaunch(全局只触发一次)*/
  onLaunch: function () {
    // 登录
    this.my_login()
    //this 就是当前app对象
  },
  my_login: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/"
  
  }
})

2、

// pages/test3/test3.js
const app = getApp() //导入app.js
Page({
  /*页面的初始数据 */
  data: {
  },
  click:function() {
    wx.navigateBack({
     delta:2
    })
  },
  user1:function (e) {
    wx.getSetting({//检查是否授权
      success(res) {//结果
        if (res.authSetting['scope.userInfo']) {//如果授权了
          wx.checkSession({
            success () {//session_key 未过期,并且在本生命周期一直有效
              wx.getUserInfo({//获取信息
                success: (res) => {
                  console.log("res",res)//这个res里面就是用户信息
                  //在session_key没有过期的情况下,将iv、数据发送后端
                  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里面就是用户信息
                  ////这里是发送iv,encryptedData,还没写
                  wx.request({
                    url: 'url',
                  })
                },
              })

              
            }
          })

 后端

1、

2、

如官方的sdk没有Crypto包用下面的方法解决:

pip install pycryptodome 

 3、

 4、

uesr文件

from rest_framework.views import APIView
from rest_framework.response import Response
from app01.wx import wx_login
from django.core.cache import cache # 导入缓存数据库
import hashlib,time
from app01.models import Wxuser
from app01.wx import WXBizDataCrypt
from app01.my_ser import wx_user_ser

class Info(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'))
              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)
              user1 = Wxuser.objects.filter(openid=openid).first()
              user = wx_user_ser(instance=user1,many=False).data
              return  Response({
                  "status":0,
                  "msg":"ok",
                  "data":user
              })
          else:
              return Response({"code": 2, "msg": "无效的token"})
        else:
            return  Response({"code":1,"msg":"缺少参数"})

 

注意:弹框只弹一次,要想再弹,就先

 

 4、wx.authorize 表示授权,但是不能给 scope.userInfo授权

解决:主动手动授权

01、看开发文档

 

 

02、看上面的图2   3

scope 列表

scope对应接口描述
scope.userInfo wx.getUserInfo 用户信息
scope.userLocation wx.getLocation, wx.chooseLocation 地理位置
scope.userLocationBackground wx.startLocationUpdateBackground 后台定位
scope.address wx.chooseAddress 通讯地址
scope.invoiceTitle wx.chooseInvoiceTitle 发票抬头
scope.invoice wx.chooseInvoice 获取发票
scope.werun wx.getWeRunData 微信运动步数
scope.record wx.startRecord 录音功能
scope.writePhotosAlbum wx.saveImageToPhotosAlbum, wx.saveVideoToPhotosAlbum 保存到相册
scope.camera camera 组件 摄像头

 

 

 四、如何添加 django server

 

 

 

 Name 随便

 

 

 

 

 

 

posted @ 2020-03-12 22:45  薛定谔的猫66  阅读(1231)  评论(0)    收藏  举报