小谈微信小程序的静默授权登录

5,412 阅读1分钟

众所周知,微信的新版API已经明确指明,当用户首次进入小程序时,倘若用户尚未进入小程序时,就直接唤起微信授权,或者自定义一个登录入口页让用户先授权登录才能浏览小程序的内容。那么毫无疑问,你所开发的小程序因为直接与微信的建议相违背,所以审核结果当然是Failed...

小程序的主入口页授权配置

当小程序处于挂载后台退出的状态再唤醒时,倘若中间间隔的时间过长,那再次唤醒进入小程序时会造成token失效的问题,当然就会造成所有接口无法正常显示,因此在app.vue主入口的生命周期onShow()中(mpVue框架),需要加入获取微信授权信息,以及获取后台需要的token。

1.先定义一个获取微信授权返回的code值的promise方法

const getWxCode = () => {
  return new Promise((resolve, reject) => {
    wx.login({
      timeout: 3000,
      success: res => {
        resolve(res.code);
      },
      fail: err => {
        reject(err);
      }
    });
  })
}
export default getWxCode;

2.判断用户是否授权操作

wx.getSetting({ // 判断是否已经授权
	success: res => {
		if (res.authSetting["scope.userInfo"]) { //用户未授权
			... 
		}
	}
});

2.调用原生按钮发起授权

<button open-type="getUserInfo" @getuserinfo="onGetUserInfo">授权</button>

onGetUserInfo(e) {
	if (e.target.errMsg === "getUserInfo:fail auth deny") {
		return; //授权弹框时点击取消
	}
	let {
		target: { encryptedData, iv }
	} = e;
	getWxCode().then(code => {
		const params = {
			code: code,
			encryptedData: encryptedData,
			iv: iv
		};
		this.onLogin(params);
	});
}

onLogin(params) {
	API.login(params).then(//后台获取token的API
		res => {
			console.log(`登陆成功,token为${res}`);
			wx.setStorageSync("AUTH_TOKEN", res.token);
		},
		fail => {
		}
	);
}

3.咋一看应该没有啥问题,但是这样做其实是错误的,错在第二步骤的onGetUserInfo方法中,如果后台API接口需要微信返回的encryptedData、iv两个参数,那么就证明用户必须要授权才能进入小程序内页。因此,当联调时必须通知后端去除掉这两个参数,只传一个code即可。这样我们就能达到新用户首次进入小程序时不用授权就能进入小程序中浏览信息,但有交互操作(比如分享...)在唤起授权操作。

在此,为了避免每个加静默授权的交互位置都判断一遍用户是否授权,抽离了一个基于系统button的授权组件userInfoBtn。 2.判断用户是否授权操作

<template>
    <div class="user-info-container">
        <button class="user-info-btn" open-type="getUserInfo" @getuserinfo="mpGetUserInfo" @click.stop>
            <slot></slot>
        </button>
    </div>
</template>

<script>
  import API from "@/servers/API";
  import getWxCode from "@/utils/getWxCode";


  export default {
    name: 'userInfoBtn',
    data() {
      return {
        userInfo: {}
      }
    },
    methods: {
      mpGetUserInfo(result) {
        const self = this;
        if (result.mp.detail.errMsg !== 'getUserInfo:ok') {
          wx.showToast({
            title: '取消授权',
            icon: 'none',
            duration: 2000
          })
          wx.setStorageSync('hasUserInfo', false)
          return;
        }
        wx.checkSession({//校验当前用户的session_key是否有效
          success() {//处于登录状态
            self.getLoginData()
          },
          fail() {//需要重新登录
            self.getLoginData()
          }
        })
      },
      getLoginData() {
        getWxCode().then(code => {
          API.login({ code })
            .then(res =>
            {
              wx.setStorageSync('hasUserInfo', true)
              this.$emit('onClickGetUserInfoBtn')
            })
            .catch(err =>
            {
              console.log(err)
            })
        });
      }
    }
  }
</script>

<style scoped>
    .user-info-btn::after {//去除系统按钮默认样式
        border: 0;
    }

    .user-info-btn {
        background-color: transparent;
        padding: 0;
        font-size: 0;
    }
</style>

/** 调用 **/
<user-info-btn @onClickGetUserInfoBtn="doAction">
</user-info-btn>