评论

隐私协议授权的一种解决思路

非弹窗解决隐私协议授权

现状

登录页使用了获取手机号接口,登录页为单独的页面(非弹窗),所有登录需求都会跳转到此页。

分析

小程序提供两种接入方式:一种是主动查询授权状态,如果状态为未授权则进入授权流程,已授权则无需处理;另一种是被动监听何时需要授权,触发事件后进入授权流程,未触发则表示已授权。在登录的流程中,主动查询就是先发起授权后点击登录按钮,被动监听就是先点击登录按钮后发起授权。个人感觉,主动查询的方式先告知用户需要采集隐私数据,比较符合用户习惯,而被动监听的方式事前未告知用户需要授权,且打断了登录的流程,用户体验不佳,因此采取主动查询的方式。
官方的示例采用了弹窗授权的方式,但无论是在页面上覆盖一个模拟弹窗组件,还是使用page-container,控制弹窗都不能像VUE那样优雅,复用也不方便。鉴于登录页也是单独的页面,考虑到以后可能还有其它页面需要授权,因此授权页也采用单独的页面(PS.skyline的自定义路由可以很优雅地实现弹窗,但目前还没有适配,暂不考虑,之后对授权页进行改造即可)。

思路

在登录页的onLoad中主动查询授权状态,如果状态为未授权则调用授权接口跳转到授权页,授权页回调授权状态,如果授权失败则登录也失败。

实现

// 封装的登录接口
function requestLogin() {
    return new Promise(async (resolve, reject) => {
        wx.navigateTo({
            url: '/pages/user/user-login/user-login', // 登录页
            events: {
                login: (loginStatus) => {
                    // 登录状态回调
                    if (loginStatus) {
                        // 成功
                        resolve()
                    } else {
                        // 失败
                        reject(new Error('login fail'))
                    }
                } 
            },
            fail: () => reject(new Error('navigate fail'))
        })
    })
}

// 封装的授权接口
function requestProvicy() {
    return new Promise(async (resolve, reject) => {
        wx.getPrivacySetting({
            success: (res) => {
                if (res.needAuthorization) {
                    // 需要授权
                    wx.navigateTo({
                        url: '/pages/user/user-login/user-login', // 登录页
                        events: {
                            privacy: (privacyStatus) => {
                                // 授权状态回调
                                if (loginStatus) {
                                    // 成功
                                    resolve()
                                } else {
                                    // 失败
                                    reject(new Error('privacy fail'))
                                }
                            } 
                        },
                        fail: () => reject(new Error('navigate fail'))
                    })
                } else {
                    // 无需授权
                    resolve()
                }
            },
            fail: () => reject(new Error('get privacy fail'))
        })
    })
}

// 第一步:调用封装的登录接口
// 需要登录才能进入的页面
Page({
    onLoad: async function(options) {
        try {
            await wx.$auth.requestLogin() // 登录失败抛出错误
        } catch {
            return wx.$router.back() // 返回上一页
        }
        
        // 业务代码
    }
})

// 第二步:获取手机号登录
// 登录页
<!-- wxml >
<button open-type="getPhoneNumber" bindgetphonenumber="handleGetPhoneNumber">获取手机号</button>

Page({
    handleGetPhoneNumber: async function(e) {
        const code = e.detail.code // 手机号code
        
        // 调用自己后台的登录接口
        
        this._loginStatus = true // 登录成功状态,在onUnload回调
        wx.$router.back() // 返回上一页
    },
    
    onLoad: async function() {
        try {
            await wx.$auth.requestProvicy() // 授权失败抛出错误
        } catch {
            return wx.$router.back() // 返回上一页
        }
    }
    
    onUnload: function() {
        const eventChannel = this.getOpenerEventChannel()
        if (!eventChannel) return
        eventChannel.emit('login', !!this._loginStatus) // 回调登录结果
    }
})

// 第三步:授权
// 授权页
<!-- wxml >
<button id="agree-btn" open-type="agreePrivacyAuthorization" bindagreeprivacyauthorization="handleAgreePrivacyAuthorization">我已阅读并同意隐私协议</button>

Page({
    handleAgreePrivacyAuthorization: async function() {
        this._privacyStatus = true // 授权成功状态,在onUnload回调
        wx.$router.back() // 返回上一页
    },
    
    onUnload: function() {
        const eventChannel = this.getOpenerEventChannel()
        if (!eventChannel) return
        eventChannel.emit('privacy', !!this._privacyStatus) // 回调登录结果
    }
})

最终效果

未登录的状态下打开一个需要登录才能使用的页面

可以进入小程序实际体验一下,欢迎各位一起讨论

最后一次编辑于  2023-09-01  
点赞 0
收藏
评论

2 个评论

  • run&
    run&
    2023-09-01

    请问你onload里调用 返回的话back onload还是之前的执行的一次 你们是要再次点击按钮才会触发隐私调用吧? 我们要一进页面就触发调用 然后进行页面跳转 跳转完在返回 我感觉我得放在onshow里了

    2023-09-01
    赞同
    回复 3
    • Larry
      Larry
      2023-09-01
      不需要点击按钮,进入登录页onLoad就会检查授权状态,未授权的话跳转授权页,等待授权结果,如果没完成授权会报错,执行catch里面的返回。如果按我们的逻辑放onShow的话,如果没有完成授权,只要一从授权页返回登录页就会再次打开授权页,退不出去了
      2023-09-01
      回复
    • run&
      run&
      2023-09-01
      我才看到还有events,我记得以前没有的呀
      2023-09-01
      回复
    • Larry
      Larry
      2023-09-01回复run&
      用得比较少吧,页面间通信用的,可以看下文档https://developers.weixin.qq.com/miniprogram/dev/api/route/wx.navigateTo.html
      2023-09-01
      回复
  • 阿巴阿巴
    阿巴阿巴
    2023-09-01

    你这样审核过了吗

    2023-09-01
    赞同
    回复 6
    • Larry
      Larry
      2023-09-01
      过了呀,线上版本就是这样实现的
      2023-09-01
      回复
    • 阿巴阿巴
      阿巴阿巴
      2023-09-01回复Larry
      来来回回的返回,返回的统一你咋弄的呢 这个方案下
      2023-09-01
      回复
    • Larry
      Larry
      2023-09-01回复阿巴阿巴
      调用的顺序是 业务页>登录页>授权页,返回的话也是逐级返回。在授权页请求授权后返回登录页,已授权则停留在登录页继续获取手机号,未授权则继续返回到业务页
      2023-09-01
      回复
    • 杨飘飘🐱
      杨飘飘🐱
      2023-09-04
      隐私授权同意后,获取手机号还会出现询问用户是否同意授权的组件吗
      2023-09-04
      回复
    • 阿巴阿巴
      阿巴阿巴
      2023-09-05回复杨飘飘🐱
      我的现在还会
      2023-09-05
      回复
    查看更多(1)
登录 后发表内容