• 微信小程序开发记录(七)新版授权登录的实现


    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
    本文链接:https://blog.csdn.net/wh_xmy/article/details/86475859

    背景:由于微信官方修改了 getUserInfo、authorize 接口,无法弹出授权窗口,所以现在无法实现一进入微信小程序就弹出授权窗口,只能通过 button 去触发,这样就需要我们加一个授权页面去搞定了。

    前提:微信授权登录仅适用于使用微信用户信息的用户,如果自己的项目有完善的用户信息(一套式开发项目),可不使用微信用户信息;如果仅为微信小程序,则要授权、获取用户信息。

    实现思路:自己写一个微信授权登录页面让用户实现点击的功能,也就是实现了通过 button 组件去触发 getUserInof 接口。在用户进入微 信小程序的时候,判断用户是否授权了,如果没有授权的话就显示“授权页面”,让用户去执行授权的操作。如果已经授了,则直接跳过这个页面,进入首页。

    授权页面的代码:

    authorize.wxml

    <!--pages/authorize/authorize.wxml-->
    <view class="box" wx:if="{{canIUse}}">
        <button class='bottom' open-type="getUserInfo" lang="zh_CN" bindgetuserinfo="bindGetUserInfo">
            允许授权
        </button>
    </view>
     
    <view class="box" wx:else>请升级微信版本</view>
    

      authorize.wxss

    /* pages/authorize/authorize.wxss */
    page{
      height:100%;
      100%;
      background: url(https://www.toread.com.cn/Public/sg/images/authorize.png) no-repeat 0 0;
      background-size:100% 100%;
      overflow: hidden;
      overflow-y: hidden;
    }
    .box{
      height:100%;
      100%;
      padding-top:530rpx;
      box-sizing: border-box;
    }
    .bottom {
        box-sizing: border-box;
        border-radius: 8rpx;
        margin:0 34rpx;
        font-size: 36rpx;
        height:90rpx;
        font-family: PingFangHK-Regular;
        background:#ffffff;
        color:#000000;
    }

    authorize.json

    {
      "navigationBarTitleText": "微信授权"
    }
    

    authorize.js

    // pages/authorize/authorize.js
    // import util from './utils/util.js';
    var app = getApp();
    Page({
      /**
       * 页面的初始数据
       */
      data: {
        //判断小程序的API,回调,参数,组件等是否在当前版本可用。
        canIUse: wx.canIUse('button.open-type.getUserInfo')
      },
     
      /**
       * 生命周期函数--监听页面加载
       */
      onLoad: function (options) {
        wx.hideShareMenu();//禁用分享功能
        var that = this;
        // 查看是否授权
        wx.getSetting({
          success: function (res) {
            if (res.authSetting['scope.userInfo']) {
              wx.getUserInfo({
                success: function (res) {
                  //从数据库获取用户信息
                  // console.log(res);
                  // that.queryUsreInfo();
                  //用户已经授权过
                  wx.switchTab({
                    url: '/pages/index/index'
                  })
                }
              });
            }
          }
        })
      },
      // post请求
      requestData:function(url, data0, successCallback, errorCallback) {
        wx.request({
          url: app.globalData.rootApi + url,
          data: data0,
          method: "POST",
          success: function (res) {
            successCallback(res);
          },
          error: function (res) {
            errorCallback(res);
          },
        });
      },
      // 授权登录
      login: function (data0, successCallback, errorCallback){
        this.requestData('Login/check', data0, successCallback, errorCallback);
      },
      //点击授权按钮
      bindGetUserInfo: function (e) {
        if (e.detail.userInfo) {
          //用户按了允许授权按钮
          var that = this;
          // 登录
          wx.login({
            success: res => {
              // console.log(res);
              const code = res.code;
              // console.log(code);
              // 获取用户信息
              wx.getSetting({
                success: res => {
                  if (res.authSetting['scope.userInfo']) {
                    // 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框
                    wx.getUserInfo({
                      success: res => {
                        // 可以将 res 发送给后台解码出 
                        // console.log(res);
                        this.userInfo = res.userInfo;
                        var nickName = res.userInfo.nickName;
                        var avatarUrl = res.userInfo.avatarUrl;
                        // 存储用户名和头像
                        wx.setStorageSync('nickName', nickName);
                        wx.setStorageSync('avatarUrl', avatarUrl);
                        var iv = res.iv;
                        var encryptedData = res.encryptedData;
                        var postData = {};
                        postData.code = code;
                        postData.iv = res.iv;
                        postData.encryptedData = res.encryptedData;
                        // console.log("postdata");
                        // console.log(postData);
                        app.globalData.userInfo = res.rawData;
                        //后台服务器授权登录接口
                        this.login(postData,
                          (res) => {
                            // console.log("login----")
                            if (res.data.code == 1) {//获取成功 
                              // console.log("后台服务器授权登录成功!");
                              var utoken = res.data.utoken;
                              // 先移除可能需要更改的storage
                              // wx.removeStorageSync('utoken');
                              //设置本地缓存
                              wx.setStorage({
                                key: 'utoken',
                                data: utoken,
                              });
                              //用户已经授权过
                              wx.reLaunch({
                                url: '/pages/index/index'
                              });
                            }
                       else {
                              wx.showModal({
                                title: '温馨提示',
                                content: res.data.msg
                              })
                            }
                          }
                        )
                        // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
                        // 所以此处加入 callback 以防止这种情况
                        if (this.userInfoReadyCallback) {
                          this.userInfoReadyCallback(res)
                        }
                      }
                    })
                  }
                }
              })
            }
          })
        } else {
          //用户按了拒绝按钮
          wx.showModal({
            title: '警告',
            content: '您点击了拒绝授权,将无法进入小程序,请授权之后再进入!!!',
            showCancel: false,
            confirmText: '返回授权',
            success: function (res) {
              if (res.confirm) {
                // console.log('用户点击了“返回授权”')
              }
            }
          })
        }
      },
     
      /**
       * 生命周期函数--监听页面初次渲染完成
       */
      onReady: function () {
     
      },
     
      /**
       * 生命周期函数--监听页面显示
       */
      onShow: function () {
     
      },
     
      /**
       * 生命周期函数--监听页面隐藏
       */
      onHide: function () {
     
      },
     
      /**
       * 生命周期函数--监听页面卸载
       */
      onUnload: function () {
     
      },
     
      /**
       * 页面相关事件处理函数--监听用户下拉动作
       */
      onPullDownRefresh: function () {
     
      },
     
      /**
       * 页面上拉触底事件的处理函数
       */
      onReachBottom: function () {
     
      },
     
      /**
       * 用户点击右上角分享
       */
      onShareAppMessage: function () {
     
      }
    })
    

    以上代码可以解决新版小程序授权登录问题,可能有部分方法需要使用app.js和util.js,下面附上部分代码:

    app.js

    //app.js
    import util from './utils/util.js';
    var loginStatus = true;
    App({
      onLaunch: function () {
        //获取微信顶部导航栏高度
        wx.getSystemInfo({
          success: res => {
            //导航高度
            this.globalData.navHeight = res.statusBarHeight + 46;
            console.log(res.statusBarHeight + 46)
          }, fail(err) {
            console.log(err);
          }
        })
        // 展示本地存储能力
        var logs = wx.getStorageSync('logs') || []
        logs.unshift(Date.now())
        wx.setStorageSync('logs', logs)
        //检查登录是否过期
        wx.checkSession({
          success: function (e) {   //登录态未过期
            console.log("没过期");
          },
          fail: function () {   //登录态过期了
            console.log("过期了");
            //重新调取授权登录接口
            util.checkLogin();
          }
        });
      },
      globalData: {
        userInfo: null,
        code:'',
        rootApi: 'https://www.toread.com.cn/index.php/sg/'
      }
    })
    util.js
    
    var app = getApp();
     
    // const rootApi = 'https://xxx/index.php/sg/';//测试环境
    const rootApi = 'https://xxx/index.php/sg/';//线上环境
    // 微信自定义格式化时间方法,传入new Date()
    const formatTime = date => {
      const year = date.getFullYear()
      const month = date.getMonth() + 1
      const day = date.getDate()
      const hour = date.getHours()
      const minute = date.getMinutes()
      const second = date.getSeconds()
     
      return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':')
    }
    /**
     * 时间格式化为 时 分 秒(传入时间为毫秒)
     */
    function MillisecondToDate(msd) {
      var time = parseFloat(msd) / 1000;
      if (null != time && "" != time) {
        if (time > 60 && time < 60 * 60) {
          time = parseInt(time / 60.0) + "分钟" + parseInt((parseFloat(time / 60.0) -
            parseInt(time / 60.0)) * 60) + "秒";
        }
        else if (time >= 60 * 60 && time < 60 * 60 * 24) {
          time = parseInt(time / 3600.0) + "小时" + parseInt((parseFloat(time / 3600.0) -
            parseInt(time / 3600.0)) * 60) + "分钟" +
            parseInt((parseFloat((parseFloat(time / 3600.0) - parseInt(time / 3600.0)) * 60) -
              parseInt((parseFloat(time / 3600.0) - parseInt(time / 3600.0)) * 60)) * 60) + "秒";
        }
        else {
          time = parseInt(time) + "秒";
        }
      }
      return time;
    }
    /**
     * 时间戳转化为年 月 日 时 分 秒
     * number: 传入时间戳
     * format:返回格式,支持自定义,但参数必须与formateArr里保持一致
    */
    function zformatTime(number, format) {
     
      var formateArr = ['Y', 'M', 'D', 'h', 'm', 's'];
      var returnArr = [];
     
      var date = new Date(number * 1000);
      returnArr.push(date.getFullYear());
      returnArr.push(formatNumber(date.getMonth() + 1));
      returnArr.push(formatNumber(date.getDate()));
     
      returnArr.push(formatNumber(date.getHours()));
      returnArr.push(formatNumber(date.getMinutes()));
      returnArr.push(formatNumber(date.getSeconds()));
     
      for (var i in returnArr) {
        format = format.replace(formateArr[i], returnArr[i]);
      }
      return format;
    }
     
    const formatNumber = n => {
      n = n.toString()
      return n[1] ? n : '0' + n
    }
    // post请求
    function requestData(url, data0, successCallback, errorCallback) {
      wx.request({
        url: rootApi+url,
        data: data0,
        method: "POST",
        success: function (res) {
          successCallback(res);
        },
        error: function (res) {
          errorCallback(res);
        },
      });
    }
     
    // get请求
    function getRequestData(url, data0, successCallback, errorCallback) {
      wx.request({
        url: rootApi+url,
        data: data0,
        method: "GET",
        success: function (res) {
          successCallback(res);
        },
        error: function (res) {
          errorCallback(res);
        },
      });
    }
     
    // 授权登录
    function login(data0, successCallback, errorCallback) {
      requestData('Login/check', data0, successCallback, errorCallback);
    }
     
    // 用户登陆过期重新登录
    function checkLogin() {
      wx.login({
        success: res => {
          const code = res.code;
          // 获取用户信息
          wx.getSetting({
            success: res => {
              if (res.authSetting['scope.userInfo']) {
                // 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框
                wx.getUserInfo({
                  success: res => {
                    console.log(res);
                    // 可以将 res 发送给后台解码出 
                    this.userInfo = res.userInfo;
                    var iv = res.iv;
                    var encryptedData = res.encryptedData;
                    var postData = {};
                    postData.code = code;
                    postData.iv = res.iv;
                    postData.encryptedData = res.encryptedData;
                    //后台服务器授权登录接口
                    this.login(postData,
                      (res) => {
                        console.log("login----")
                        if (res.data.code == 1) {//获取成功 
                          console.log("检测登陆过期后再次登录成功!");
                          var utoken = res.data.utoken;
                          // 先移除可能需要更改的storage
                          // wx.removeStorageSync('utoken');
                          //设置本地缓存
                          wx.setStorage({
                            key: 'utoken',
                            data: utoken,
                          });
                          //用户已经授权过
                          wx.reLaunch({
                            url: '/pages/index/index',
                          })
                        }
                        else {
                          wx.showModal({
                            title: '温馨提示',
                            content: res.data.msg
                          })
                        }
                      }
                    )
                    // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
                    // 所以此处加入 callback 以防止这种情况
                    if (this.userInfoReadyCallback) {
                      this.userInfoReadyCallback(res)
                    }
                  }
                })
              }
            }
          })
        }
      })
    }
     
    // 去前后空格  
    function trim(str) {
      return str.replace(/(^s*)|(s*$)/g, "");
    }
     
    // 提示错误信息  
    function isError(msg, that) {
      that.setData({
        showTopTips: true,
        errorMsg: msg
      })
    }
     
    // 清空错误信息  
    function clearError(that) {
      that.setData({
        showTopTips: false,
        errorMsg: ""
      })
    }
    //判断字符串中是否含有表情符号
    function isEmojiCharacter(substring) {
      for (var i = 0; i < substring.length; i++) {
        var hs = substring.charCodeAt(i);
        if (0xd800 <= hs && hs <= 0xdbff) {
          if (substring.length > 1) {
            var ls = substring.charCodeAt(i + 1);
            var uc = ((hs - 0xd800) * 0x400) + (ls - 0xdc00) + 0x10000;
            if (0x1d000 <= uc && uc <= 0x1f77f) {
              return true;
            }
          }
        } else if (substring.length > 1) {
          var ls = substring.charCodeAt(i + 1);
          if (ls == 0x20e3) {
            return true;
          }
        } else {
          if (0x2100 <= hs && hs <= 0x27ff) {
            return true;
          } else if (0x2B05 <= hs && hs <= 0x2b07) {
            return true;
          } else if (0x2934 <= hs && hs <= 0x2935) {
            return true;
          } else if (0x3297 <= hs && hs <= 0x3299) {
            return true;
          } else if (hs == 0xa9 || hs == 0xae || hs == 0x303d || hs == 0x3030
            || hs == 0x2b55 || hs == 0x2b1c || hs == 0x2b1b
            || hs == 0x2b50) {
            return true;
          }
        }
      }
    }  
     
    module.exports = {
      formatTime: formatTime,
      zformatTime: zformatTime,
      requestData: requestData,
      trim: trim,
      isError: isError,
      clearError: clearError,
      getRequestData: getRequestData,
      checkLogin: checkLogin,
      login:login,
      formatDuring:formatDuring,
      MillisecondToDate: MillisecondToDate,
      isEmojiCharacter: isEmojiCharacter
    }
    

      

    爱生活、爱编程!
  • 相关阅读:
    RTX Server license update
    Dell Raid[转载]
    Dell2950 server OS Installation
    Paragon Partition Manager 9.0 Professional管理磁盘分区
    Upgrade Backup Exec License
    C# 3.0将偷懒进行到底
    hibernate学习笔记
    开发c#插件
    Socket简单通讯
    .NET牛人应该知道些什么(转)?
  • 原文地址:https://www.cnblogs.com/liliuyu/p/11633937.html
Copyright © 2020-2023  润新知