扫小程序码登陆网站方案的 . 微信小程序部分代码和逻辑.

 

读取二维码传入值

前面已经说了整体流程.

 

网站提供一个扫码登陆的二维码.

二维码传入一个scene(场景)值.

 

做小程序开发的时候, 新建一个  "编译模式", 启动参数 填写scene=xxxxxxxxxxxxxxxxxxxxxxxx

 

 

 

 

 

这样开发的时候,就能模拟小程序扫码后的情况.

 

 

index页面接收scene

 

代码主要是onLoad,当index页面运行后,自动执行onLoad

参数需要decodeURIComponent解码.

 

  onLoad: function (options) {
    var _this = this;

    console.log(options);

    var scene = decodeURIComponent(options.scene);

    console.log(scene);
    if (scene != 'undefined') {
      wx.reLaunch({
        url: '../login/login?scene=' + scene 
      }) ;

      return;     
    }
    //.............其他逻辑

}

如果检测到有参数传入小程序.那么直接wx.reLaunch跳转到login登陆页面.

 

 

Login页面wxml代码

也就是视图文件.

代码基本是官方文档直接改了下的.

非常简单.

 

表现就是下图.

 

 

 

未登陆的情况

 

 

已登陆的情况

 

 

 

 

 

如果用户未登陆  : 一个空白头像 + "尚未登陆"提示  + 一个按钮

如果用户已登陆  :  用户头像 + 用户名提示

 

无论登陆不登陆,底部有个文字提示.

 

 

主要是授权登陆按钮的

open-type="getUserInfo" bindgetuserinfo="getUserInfo"

open-type="getUserInfo"是小程序调用登陆接口用的视图文件接口名,

不但按钮可以用这个,还可以图片/文字块/链接  用这个.

这是按钮,也就是点了按钮就调用 bindgetuserinfo对应的JS函数(我这里是getUserInfo).

 

相关官方介绍 -- > < 获取用户信息方案介绍 >

 

Login页面js逻辑

 

页面变量

  data: {
    motto: '点击[授权登录] 进行登录',
    userInfo: {},
    hasUserInfo: false,
    scene: '',
    code: '',
    encryptedData: '',
    iv: '',
    rawData: '',
    signature: '',
    host: 'https://api.getce.cn',
    canIUse: wx.canIUse('button.open-type.getUserInfo')
  }

 

 

 

getUserInfo

 

  getUserInfo: function (e) {

    console.log("点按钮,传入参数 e: ");
    console.log(e);


    var _this = this;

    console.log("点按钮, 获取 e.detail.userInfo: ");
    console.log(e.detail.userInfo);


    var errcode = e.detail.errMsg;

    console.log(e.detail.errMsg);

    if (errcode == "getUserInfo:ok") {
      //授权登陆的用户

      app.globalData.userInfo = e.detail.userInfo;

      _this.setData({
        userInfo: e.detail.userInfo,
        hasUserInfo: true
      });

      //_this.postLogin();

    } else {


      //如果用户不授权
      wx.showToast({
        title: '您没有授权登陆哦.',
        duration: 2000,
        icon: 'none'
      })


    }


  }

 

当用户点了 "授权登陆" 按钮后,微信小程序弹出授权提示.

 

(这是个同步函数,在用户点了拒绝或者允许前,控制台不会看到结果)

 

 

 

e.detail.errMsg  ==  "getUserInfo:ok"  也就是用户点了允许.

如果点了拒绝那么弹出一个2秒的提示.然后退出函数.

 

再看下点了允许的情况.

      app.globalData.userInfo = e.detail.userInfo;

      _this.setData({
        userInfo: e.detail.userInfo,
        hasUserInfo: true
      });

 

setData函数

就是更新页面变量.

这里有两个

  1. 标记已经登陆
  2. 并记录登陆用户信息.

将这个两个保存起来后,页面会自动更新.变成已登陆状态.

不需要自己逻辑处理.这是小程序JS更新视图页面的更新模式.

 

实际上,iv,rawData,encryptedData 这里都可以得到.都可以存起来.我代码就不写了,自己加上去即可.

 

 

postLogin

注意上面的登陆还注释掉了一个_this.postLogin();

我实际用的时候是不注释的.

用户点了 "授权登陆" 按钮后  --> 点 允许 授权,会自动post数据登陆.

 

postLogin: function () {


    var _this = this;

    wx.showToast({
      title: '自动登陆中.',
      icon: 'loading',
      duration: 2000
    })

    //读取页面变量
    var cc = {
      'code': _this .data.code,
      'scene': _this.data.scene,
      'iv': _this.data.iv,
      'encryptedData': _this.data.encryptedData,
    }


    console.log(" 获取 post 信息 cc: ");
    console.log(cc);


    //拼接post的url
    var pushcodeurl = _this .data.host + '/v1/login/pushcode.html';




    util.post(pushcodeurl, cc).then(e => {

      //登录成功.
      console.log(" 获取 post 页面返回信息 e: ");
      console.log(e);


      if (e.data.code == '1') {
        //成功了

        wx.reLaunch({
          url: '../ok/ok'
        })

      } else {

        wx.reLaunch({
          url: '../error/error?msg=' + encodeURIComponent('登录失败,原因:' + e.data.msg)
        })


      }
    })
  }

 

post了根据跳转ok页面或者error页面.当然可以不需要跳转直接弹出一个提示也行.

 

举例,我小程序上一个错误提示.

 

onLoad

这个也就是页面载入的时候自动执行的函数.

前面说了,读取index传入的scene就是这个.

 

1.接收scene

接收方法和index中转传入的scene一样.

ps :如果和我一样用的数字+英文 不包括标点的组合,可以无需decodeURIComponent解码.

  onLoad: function (query) {
    var _this = this;

    var scene = query.scene;


      _this.setData({
        scene : query.scene,
      });

     ///...
  }


2.获取code

 

      //获取code,没有就同步一次
      var t_code = wx.getStorageSync('code') || "";


      //如果code空,那么还得触发login一次.
      if (!t_code) {


        wx.login({
          success: res => {
            // 记录code
            console.log("获取code 1");


            _this.setData({
               code: res.code,
            });

            //永久储存,app.js中判断code过期,这里肯定是有效的.
            wx.setStorageSync('code', res.code);

            resolve(2);
          }
        })
      }

 

3,自动登陆逻辑

 

     //获取用户信息,通过app.js页面回调
      if (app.globalData.userInfo) {
        //用户已经登陆
        console.log("onLoad:用户已经登陆");


        _this.setData({
          motto: '如果没有自动登陆,请点击 头像 进行登录',
          userInfo: app.globalData.userInfo,
          hasUserInfo: true
        });


        //_this.postLogin();

      } else if (_this.data.canIUse) {
        // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
        // 所以此处加入 callback 以防止这种情况
        console.log("onLoad:用户未登陆,定义回调函数,userInfoReadyCallback");


        app.userInfoReadyCallback = res => {
          console.log("onLoad:用户未登陆,定义回调函数,userInfoReadyCallback,内部res : ");
          console.log(res);

          app.globalData.userInfo = res.userInfo



          _this.setData({
            motto: '如果没有自动登陆,请点击 头像 进行登录',
            userInfo: res.userInfo,
            hasUserInfo: true
          });

          //_this.postLogin();

        }
      } else {
        // 在没有 open-type=getUserInfo 版本的兼容处理
        console.log("onLoad:老设备兼容处理");

        wx.getUserInfo({
          success: res => {

            app.globalData.userInfo = res.userInfo


            _this.setData({
              motto: '如果没有自动登陆,请点击 头像 进行登录',
              userInfo: res.userInfo,
              hasUserInfo: true
            });


            //_this.postLogin();
          }
        })
      }

 

这里有3种情况.

1,app全局变量有用户信息.将全局变量的用户信息同步到login页面. (这部实际可以省略)

 

2,全局变量没有用户信息,然后去调用app.js的userInfoReadyCallback 回调函数.异步获取.

如果用户有登陆授权过,那么会自动获取并更新用户信息,并异步返回.

如果用户没有登陆,那么不返回.

 

 

3,兼容低版本微信APP用户.

 

 

 

 

 

 

App.js逻辑

 

app.js是一个全局js.

 

 

全局变量

  globalData: {
    userInfo: null,
    iv:'',
    signature:'',
    encryptedData:'',
    rawData:''
  }

主要是用户信息.

 

onLoad

它的执行仅晚于index.js 的onload

 

主要逻辑有两部分

 

1.测试code有效期

    wx.checkSession({
      success: function (res) {
        console.log("处于登录态");

        var t_code = wx.getStorageSync('code') || "";


        //如果缓存是空的
        //那么重新换取登陆code
        if (!t_code) {

          wx.login({
            success: res => {
              // 发送 res.code 到后台换取 openId, sessionKey, unionId
              getApp().globalData.code = res.code
              wx.setStorageSync('code', res.code);

            }
          })

        } else {
          getApp().globalData.code = t_code;
        }


      },
      fail: function (res) {

        console.log("需要重新登录");

        wx.login({

          success: res => {
            // 发送 res.code 到后台换取 openId, sessionKey, unionId
            getApp().globalData.code = res.code
            wx.setStorageSync('code', res.code);

          }
        })
      }
    })

如果code失效了就更新.反正保证code是能用的.

code是用永久存储存起来.

 

2,获取用户信息

 

    // 获取用户信息
    wx.getSetting({
      success: res => {
        if (res.authSetting['scope.userInfo']) {

          // 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框
          console.log('已授权:scope.userInfo');

          wx.getUserInfo({
            success: res => {
              
              this.globalData.userInfo = res.userInfo;

              //this.globalData.signature = res.signature;
              //this.globalData.iv = res.iv;
              //this.globalData.encryptedData = res.encryptedData;

              
              console.log('app.js页 获取wx.getUserInfo:' );
              console.log(res);

              // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
              // 所以此处加入 callback 以防止这种情况
              if (this.userInfoReadyCallback) {
                this.userInfoReadyCallback(res)
              }
            }
          })
        }
      }
    }

 

 

 

 

 

 

 

 

 

调试/开发小技巧

 

 

回到未登陆状态

 

测试的时候,有个清理缓存的功能.全部清除,可以恢复到未登陆状态.测试代码需要.

 

 

 

调试特定页面

 

开发的时候,我们有些页面要调试某个页面/做某个页面开发

可以新建一个编译模式,将启动页面设置你要调试的页面.