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

  • 技术栈: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 日前发布的小程序不受影响。

...

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

相关推荐
fs哆哆11 分钟前
ExcelVBA运用Excel的【条件格式】(二)
linux·运维·服务器·前端·excel
安冬的码畜日常25 分钟前
【CSS in Depth 2精译】2.5 无单位的数值与行高
前端·css
ilisi_26 分钟前
导航栏样式,盒子模型
前端·javascript·css
吉吉安34 分钟前
grid布局下的展开/收缩过渡效果【vue/已验证可正常运行】
前端·javascript·vue.js
梦凡尘40 分钟前
Vue3 对跳转 同一路由传入不同参数的页面分别进行缓存
前端·javascript·vue.js
攒了一袋星辰40 分钟前
Webpack安装以及快速入门
前端·webpack·node.js
吃饱很舒服1 小时前
kotlin distinctBy 使用
android·java·开发语言·前端·kotlin
勤劳兔码农1 小时前
从IE到Edge:微软浏览器的演变与未来展望
前端·microsoft·edge
web守墓人1 小时前
【前端】解决element-ui两层dialog嵌套,遮罩层消失的问题。
前端·ui
茶卡盐佑星_1 小时前
vue如何解决跨域?原理?
前端·javascript·vue.js