很久之前的微信小程序授权流程记录

  • 技术栈:React、Taro、TS

在微信小程序中,打开摄像头、麦克风,获取地理位置等接口,都需要经过授权才能调用,详见微信官方文档

既然每次都需要授权,那我每次使用前调用一次 wx.authorize不就得了?

js 复制代码
 Taro.authorize({
    scope: 'scope.camera',
    success: (res) => {
         // 用户已经同意小程序使用摄像头功能,可以进行下一步操作了(如调用扫码)
         // Taro.scanCode()
    },
    fail: (err) => {
      // 拒绝授权了
    },

第一次调用时,出现了令人激动的绿色弹框!

手抖点了拒绝,尝试再次点击(调用wx.authorize时),发现没反应了???

仔细阅读了官方文档,发现了这句话

如果用户之前已经同意授权,则不会出现弹窗,直接返回成功。

那么如果之前拒绝授权呢?没说,但实操发现也不会出现弹框。

寻找思路:

官方文档的示例中,wx.getSettingwx.authorize搭配使用,其作用是查询授权信息。

wx.getSetting调用成功返回的信息打印出来

发现authSetting中记录了用户授权结果,刚才拒绝了授权,所以scope.camera是false

那么,可以得到上次授权结果了,需要做的是在上次拒绝之后还能重新询问授权。wx.openSetting)可以满足这一需求

调起客户端小程序设置界面,返回用户设置的操作结果。设置界面只会出现小程序已经向用户请求过的权限

梳理一下整个流程

进一步调试wx.openSetting,总结出其与操作流程的对应关系

wx.getSetting查看的权限情况 说明 所需操作
res.authSetting['scope.record']===true 之前询问过这个权限,并且用户已经同意了 已经有这个权限了,调用api即可
res.authSetting['scope.record']===false 之前询问过这个权限,但是用户拒绝了 需要跳到小程序的设置界面(openSetting)
res.authSetting['scope.record']不存在 还没有询问过这个权限 用wx.authorize这个api询问用户获取权限

(注:这里借用了一个大佬的思路,但是文章链接现在找不到了)

打开小程序的设置页面需要用户主动主动点击触发,所以这里加一个modal,用户点击确定时调用openSetting

上代码

可以封装为异步函数便于使用

js 复制代码
import Taro from "@tarojs/taro"

/**
 *
 * @param {*} scopeStr // 'scope.record' // 权限列表 https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/authorize.html
 * @returns
 */
export const checkPermisson = (scopeStr) => {
  return new Promise((resolve, reject) => {
    Taro.getSetting({
      success: async (res) => {
        const authSettingObj = res.authSetting
        if (authSettingObj[scopeStr] === true) {
          // 当前已经有权限了
          return resolve()
        } else if (authSettingObj[scopeStr] === false) {
          // 之前问过权限,但是拒绝了
          try {
            await openSetting(scopeStr)
            return resolve()
          } catch {
            return reject()
          }
        } else {
          // 还没问过权限
          // 去请求授权
          Taro.authorize({
            scope: scopeStr,
            success: (res) => {
              return resolve()
            },
            fail: async (err) => {
              // 拒绝授权了
              // 打开setting
              try {
                await openSetting(scopeStr)
                return resolve()
              } catch {
                return reject()
              }
            },
          })
        }
      },
    })
  })
}

// 打开设置权限的页面 去设置权限 通过showModal去触发点击
export const openSetting = (scopeStr) => {
  return new Promise((resolve, reject) => {
    Taro.showModal({
      title: '温馨提示',
      content: '请授权微信小程序相关权限,以使用更多功能',
      success: (res) => {
        if (res.confirm) {
          Taro.openSetting({
            success: function (res) {
              console.log('打开权限设置页面', res)
              const authSettingObj = res.authSetting
              if (scopeStr) {
                // 有指定去获取的权限
                if (authSettingObj[scopeStr] === true) {
                  return resolve()
                } else {
                  return reject()
                }
              } else {
                // 没有指定去获取的权限
                return resolve()
              }
            },
          })
        } else {
          return reject()
        }
      },
      fail: (err) => {
        return reject()
      },
    })
  })
}

使用示例:

js 复制代码
onScan = async () => {
    try {
      await checkPermisson('scope.camera');
      Taro.scanCode({
        scanType: ['qrCode'],
        success: (res) => {
          console.log(res);
          
        },
        fail: (res) => {}
      })
    } catch (e) {
      console.log(e, '获取权限失败');
    }
  }

其他问题

在使用getLocation获取地址时报错 {"errMsg":"getLocation:fail the api need to be declared in the requiredPrivateInfos field in app.json/ext.json"}

报错信息很明确,需要在app.json加requiredPrivateInfos

解决方法:在app.config.ts加入

js 复制代码
 permission: {
  "scope.userLocation": {
    "desc": "你的位置信息将用于小程序位置接口的坐标展示" 
  }
},
requiredPrivateInfos: [
  "getLocation"
],

微信官方文档提到:

自 2022 年 7 月 14 日后发布的小程序,使用以下8个地理位置相关接口时,需要声明该字段,否则将无法正常使用。2022 年 7 月 14 日前发布的小程序不受影响。

...

注:若使用以上接口,均需在小程序管理后台,「开发」-「开发管理」-「接口设置」中自助开通该接口权限。

相关推荐
理想不理想v6 分钟前
vue经典前端面试题
前端·javascript·vue.js
不收藏找不到我7 分钟前
浏览器交互事件汇总
前端·交互
YBN娜20 分钟前
Vue实现登录功能
前端·javascript·vue.js
阳光开朗大男孩 = ̄ω ̄=21 分钟前
CSS——选择器、PxCook软件、盒子模型
前端·javascript·css
minDuck25 分钟前
ruoyi-vue集成tianai-captcha验证码
java·前端·vue.js
小政爱学习!1 小时前
封装axios、环境变量、api解耦、解决跨域、全局组件注入
开发语言·前端·javascript
魏大帅。1 小时前
Axios 的 responseType 属性详解及 Blob 与 ArrayBuffer 解析
前端·javascript·ajax
花花鱼1 小时前
vue3 基于element-plus进行的一个可拖动改变导航与内容区域大小的简单方法
前端·javascript·elementui
k09331 小时前
sourceTree回滚版本到某次提交
开发语言·前端·javascript
EricWang13581 小时前
[OS] 项目三-2-proc.c: exit(int status)
服务器·c语言·前端