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

版权声明:本文为博主原创文章,遵循 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"  bindgetuserinfo="bindGetUserInfo">
        允许授权
    </button>
</view>
 
<view class="box" wx:else>请升级微信版本</view>

  authorize.wxss

/* pages/authorize/authorize.wxss */
page{
  height:100%;
  width: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%;
  width: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
}