版权声明:本文为博主原创文章,遵循 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 }