背景:由于微信官方修改了 getUserInfo、authorize 接口,无法弹出授权窗口,所以现在无法实现一进入微信小程序就弹出授权窗口,只能通过 button 去触发,这样就需要我们加一个授权页面去搞定了。
前提:微信授权登录仅适用于使用微信用户信息的用户,如果自己的项目有完善的用户信息(一套式开发项目),可不使用微信用户信息;如果仅为微信小程序,则要授权、获取用户信息。
实现思路:自己写一个微信授权登录页面让用户实现点击的功能,也就是实现了通过 button 组件去触发 getUserInof 接口。在用户进入微 信小程序的时候,判断用户是否授权了,如果没有授权的话就显示“授权页面”,让用户去执行授权的操作。如果已经授了,则直接跳过这个页面,进入首页。
授权页面的代码:
authorize.wxml
请升级微信版本
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
}
如有疑问可以随时提问,或者哪位大神有更好的方法可以分享一下。