django+微信小程序实现登录用户的信息授权认证

小结:

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)
    }
    
})

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


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

小程序的登入

1 小程序端执行wx.login()获取code
2 将1中的code发送到后端,后端调用auth.code2Session这个接口,得到openid和session_key
3 自定义登入状态,我们生成一个key与openid和session_key相绑定。把key返回到小程序中
4 小程序端保存,然后下次请求需要登入的接口的时候,把key带上。
//app.js
App({
  data: {
    iconRight: "../../image/icon/icon-right.png",
    iconReplace: "../../image/icon/icon-replace.png"
  },
  
  onLaunch: function () {
    let _this = this
    // 展示本地存储能力
    var logs = wx.getStorageSync('logs') || []
    logs.unshift(Date.now())
    wx.setStorageSync('logs', logs)
    // 登录
    wx.login({
      success: res => {
        // 发送 res.code 到后台换取 openId, sessionKey, unionId
        wx.request({
          url: _this.globalData.apiUrl + 'api/login',
          data: {'code': res.code},
          method: 'POST',
          success: function(res) {
            wx.setStorageSync('token', res.data.data.token)
            _this.globalData.token = res.data.data.token
            console.log(res.data.data.token)
            console.log(_this.globalData.token)
          }
        })
      }
    })
    // 获取用户信息
    wx.getSetting({
      success: res => {
        if (res.authSetting['scope.userInfo']) {
          // 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框
          wx.getUserInfo({
            success: res => {
              // 可以将 res 发送给后台解码出 unionId
              this.globalData.userInfo = res.userInfo
              this.globalData.token = res.token
              // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
              // 所以此处加入 callback 以防止这种情况
              if (this.userInfoReadyCallback) {
                this.userInfoReadyCallback(res)
              }
            }
          })
        }
      }
    })
  },
  globalData: {
    userInfo: null,       // 存储用户信息
    token: null,        // 存储用户token
    header: { 'Content-Type': 'application/x-www-form-urlencoded' },          // 请求头
    apiUrl: 'http://192.168.1.104:8888/',         // 测试环境
    apiImagesUrl: 'http://192.168.1.104:8888/books/books/images/',      // 图片地址
  }
})

django的settings

AppId = '***'                    # 写自己的小程序id
AppSecret = '***'                  #写自己小程序的密钥
code2Session = 'https://api.weixin.qq.com/sns/jscode2session?appid={}&secret={}&js_code={}&grant_type=authorization_code'       # 获取微信小程序code
# 设置django—redis缓存 需要你下载插件pip install django-redis
CACHES = {
    'default': {
        'BACKEND': 'django_redis.cache.RedisCache',
        'LOCATION': 'redis://127.0.0.1:6379',
        'OPTIONS': {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
            "PASSWORD": "123456",
        }
    }
}
# 2.操作cache模块直接操作缓存:views.py
from django.core.cache import cache  # 结合配置文件实现插拔式
# 存放token,可以直接设置过期时间
cache.set('token', 'header.payload.signature', 10)
# 取出token
token = cache.get('token')


DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': "books",
        'USER': "root",
        'PASSWORD': "123456",
        'HOST': "127.0.0.1",
        'PORT': 3306
    }
}


# 跨域增加忽略
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_ALLOW_ALL = True
CORS_ORIGIN_WHITELIST = (
    '*'
)

CORS_ALLOW_METHODS = (
    'GET',
    'OPTIONS',
    'PATCH',
    'POST',
    'PUT',
    'VIEW',
)

CORS_ALLOW_HEADERS = (
    'XMLHttpRequest',
    'X_FILENAME',
    'accept-encoding',
    'authorization',
    'content-type',
    'dnt',
    'origin',
    'user-agent',
    'x-csrftoken',
    'x-requested-with',
    'Pragma',
)

urls主路由

from django.urls import path
from . import views

app_name = 'user'
urlpatterns = [
    path('api/login', views.Login.as_view(), name='login')
]

 

自定义获取小程序的登录wx_login

from app01.wx import settings

import requests

def get_login_info(code):
    code_url = settings.code2Session.format(settings.AppId, settings.AppSecret, code)
    response = requests.get(code_url)
    json_response = response.json() # 把它变成json的字典
    if json_response.get("session_key"):
        return json_response
    else:
        return False

得到openid以及加密并返回小程序token

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):

    def post(self, request):
        param = request.data
        if not param.get('code'):
             return Response({'status':1, "msg":"缺少参数"})
        else:
            code = param.get('code')
            user_data = wx_login.get_login_info(code)
            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 = 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'])
                Wxuser.objects.update()
                return Response({
                    'status': 0,
                    'msg': 'ok',
                    'data': {'token':key}
                })
            else:
                return Response({'status':2, 'msg': "无效的code"})

models.py

from django.db import models

# Create your models here.
class Wxuser(models.Model):
    id = models.AutoField(primary_key=True)
    openid=models.CharField(max_length=255)
    name = models.CharField(max_length=50)
    avatar = models.CharField(max_length=200)
    language = models.CharField(max_length=50)
    province = models.CharField(max_length=50)
    city = models.CharField(max_length=50)
    country = models.CharField(max_length=50)
    #gender = models.CharField(max_length=50)
    creat_time = models.DateTimeField(auto_now_add=True)
    update_time = models.DateTimeField(auto_now=True)
    def __str__(self):
        return self.openid

小程序授权

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

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

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

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



scope 列表

scope对应接口描述
scope.userInfowx.getUserInfo用户信息
scope.userLocationwx.getLocationwx.chooseLocation地理位置
scope.userLocationBackgroundwx.startLocationUpdateBackground后台定位
scope.addresswx.chooseAddress通讯地址
scope.invoiceTitlewx.chooseInvoiceTitle发票抬头
scope.invoicewx.chooseInvoice获取发票
scope.werunwx.getWeRunData微信运动步数
scope.recordwx.startRecord录音功能
scope.writePhotosAlbumwx.saveImageToPhotosAlbumwx.saveVideoToPhotosAlbum保存到相册
scope.cameracamera 组件摄像头

小程序的页面的js文件

// pages/test3/test3.js
Page({

  /**
   * 页面的初始数据
   */
  data: {

  },

  click:function() {
    wx.navigateBack({
     delta:2
    })
  },
  luyin:function(){

    wx.getSetting({
      success(res) {
        if (!res.authSetting['scope.record']) { //录音的scope
          wx.authorize({
            scope: 'scope.record',
            success() {
              // 用户已经同意小程序使用录音功能,后续调用 wx.startRecord 接口不会弹窗询问
              wx.startRecord()
            },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']) { //用户信息的scope
          wx.getUserInfo({
            success: (res) =>{
              console.log("res", res)

            }
          })
        } 
      }
    })
  },
})

借鉴如下:

<!--pages/test3/test3.wxml--> <text>pages/test3/test3.wxml</text> <button bindtap="click">tiao</button> <button bindtap="luyin">录音</button> <button open-type="getUserInfo" bindgetuserinfo="user1">用户信息</button> <!--要想要将用户的信息授权时弹框,必须用一个button按钮,且open-type必须为getUserInfo以及给事件为bindgetuserinfo-->

 

 

 

如对你有帮助,但获取不到openid,可以加一下群,有什么问题都可以问欢迎大佬入住    QQ群1102727334

  • 3
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值