前言
为规范开发者的用户个人信息处理行为,保障用户合法权益,微信官方要求自2023年9月15号之后,开发者需要主动同步微信当前用户已阅读并同意小程序的隐私政策等收集使用规则,方可调用微信提供的隐私接口。
微信官方文档
开发小细节
1、调试基础库>= 3.0.0才可使用
2、每次清除缓存后,已授权状态便会丢失,可以反复进行调试
3、2023年9月15号之前,记得在app.json中加入 "usePrivacyCheck": true
4、记得在小程序后台更新项目中用到的隐私接口,否则项目中调用未配置的隐私接口,会直接失败,并且不会触发wx.onNeedPrivacyAuthorization
需求
1、当用户调用涉及隐私的接口时,需要弹出弹窗,引导用户同意隐私协议
2、点击取消,提示用户必须授权,否则无法使用(tip:可根据实际情况进行调整)
隐私组件实现
wxml实现
wxml实现并不复杂,主要涉及wx.openPrivacyContract 打开微信官方隐私协议页面(不需要自己额外提供),图片中《用户隐私政策》便绑定了该Api,点击后跳转微信官方隐私协议页面。
图片中"同意并继续"按钮,使用了微信官方提供的隐私协议同意button
python
<button id="agree-btn" open-type="agreePrivacyAuthorization" bindagreeprivacyauthorization="handleAgreePrivacyAuthorization">同意</button>
点击后就相当于同意了隐私协议,状态会保留到微信,不需要后台介入。
js实现
wx.onNeedPrivacyAuthorization用于监听隐私接口需要用户授权事件,每当调用隐私接口时,便会触发该方法,该方法返回一个resolve函数,隐私接口处于pending状态,当用户同意隐私授权后,通过如下调用,隐私接口继续执行。
js
resolve({ buttonId: 'agree-btn', event: 'agree' })
1.声明privacyResolves集合,用于收集当前页面调用的多个隐私接口的resolve函数,用于用户点击同意后,解除pending,继续执行。
js
const privacyResolves = new Set()
let privacyHandler
if (wx.onNeedPrivacyAuthorization) {
wx.onNeedPrivacyAuthorization((resolve, e) => {
console.log('触发 onNeedPrivacyAuthorization', e)
if (typeof privacyHandler === 'function') {
privacyHandler(resolve)
}
})
}
2.收集resolve的同时,会去打开弹窗,并通过closePopUpHooks集合收集关闭弹窗的方法,用户同意授权后,统一关闭弹窗。(可能会在多个页面打开多个授权弹窗)
js
const closePopUpHooks = new Set()
Component({
lifetimes: {
attached() {
// 判断鉴权
// this.getPrivacySetting()
const closePopup = () => {
this.resolveConfirm()
}
privacyHandler = resolve => {
privacyResolves.add(resolve)
this.changeVisible(true)
}
this.closePopup = closePopup
closePopUpHooks.add(closePopup)
},
detached() {
closePopUpHooks.delete(this.closePopup)
}
},
methods: {
resolveConfirm() {
const { onConfirm } = this.data
this.changeVisible(false)
onConfirm && onConfirm()
}
}
})
3.用户同意授权后,调用resolve方法,并关闭所有弹窗,清空集合
js
Component({
methods: {
// 同意隐私协议
handleAgreePrivacyAuthorization() {
console.log('同意隐私协议')
this.handleConfirm()
},
handleConfirm () {
privacyResolves.forEach(resolve => resolve({ buttonId: 'agree-btn', event: 'agree' }))
privacyResolves.clear()
closePopUpHooks.forEach(hook => hook())
closePopUpHooks.clear()
}
}
})
用法
在需要的页面引入组件即可(个人觉得做成一个单独页面会更好,但扛不住产品要求)
js
<!-- 隐私协议 -->
<privacy-popup id="privacyPopup" safeAreaInsetBottom="{{ false }}"></privacy-popup>
js源码
js
const closePopUpHooks = new Set()
const privacyResolves = new Set()
let privacyHandler
if (wx.onNeedPrivacyAuthorization) {
wx.onNeedPrivacyAuthorization((resolve, e) => {
console.log('触发 onNeedPrivacyAuthorization', e)
if (typeof privacyHandler === 'function') {
privacyHandler(resolve)
}
})
}
Component({
properties: {
visible: {
type: Boolean,
value: false
},
onConfirm: {
type: Function
},
onClose: {
type: Function
},
safeAreaInsetBottom: {
type: Boolean,
value: true
}
},
lifetimes: {
attached() {
// 判断鉴权
// this.getPrivacySetting()
const closePopup = () => {
this.resolveConfirm()
}
privacyHandler = resolve => {
privacyResolves.add(resolve)
this.changeVisible(true)
}
this.closePopup = closePopup
closePopUpHooks.add(closePopup)
},
detached() {
closePopUpHooks.delete(this.closePopup)
}
},
methods: {
// 打卡用户隐私
handleOpenPrivacyContract() {
wx.openPrivacyContract({
success(res) {
console.log(res)
},
fail(err) {
console.log(err)
}
})
},
// 点击取消
handleCancel() {
showToast('需同意后才可继续使用')
},
// 同意隐私协议
handleAgreePrivacyAuthorization() {
console.log('同意隐私协议')
this.handleConfirm()
},
handleConfirm () {
privacyResolves.forEach(resolve => resolve({ buttonId: 'agree-btn', event: 'agree' }))
privacyResolves.clear()
closePopUpHooks.forEach(hook => hook())
closePopUpHooks.clear()
},
resolveConfirm() {
const { onConfirm } = this.data
this.changeVisible(false)
onConfirm && onConfirm()
},
handleClose () {
const { onClose } = this.data
this.changeVisible(false)
onClose && onClose()
},
changeVisible (bool) {
this.setData({
visible: bool
})
},
/**
* 判断隐私鉴权
*/
getPrivacySetting() {
wx.getPrivacySetting({
success: res => {
// 返回结果为: res = { needAuthorization: true/false, privacyContractName: '《xxx隐私保护指引》' }
if (res.needAuthorization) {
this.changeVisible(true)
}
},
fail: (err) => {
console.log(err)
}
})
}
}
})