欢迎点击关注-前端面试进阶指南:前端登顶之巅-最全面的前端知识点梳理总结
*分享一个使用比较久的🪜
小程序隐私保护授权弹窗组件
调用wx.getUserProfile进行授权时,返回错误信息:{errMsg: “getUserProfile:fail api scope is not declared in the privacy agreement”, errno: 112} 是因为微信小程序登录,增加了用户是否查看隐私协议的验证,不跳转到隐私协议,就不让用户登录。
微信 2023 年 8 月 10 日发布 关于小程序隐私保护指引设置的公告,9 月 15 日起所有隐私接口需用户点击同意并同步给微信之后才可以使用。
当前组件做了隐私保护指引弹窗界面,直接引用,需要授权时展示弹窗,当用户点击“拒绝”直接退出小程序,点击“同意”同步结果给微信且以后不再弹窗,之后可以正常使用隐私接口。
8 月 28 更新:今天才发现小程序可以使用页面的生命周期,对其进行了简化,只需要使用引入组件即可,不再需要任何其它代码
8 月 29 更新:采纳网页 Liu 的方案,解决多个 tabbar 情况下同意之后还有弹窗的问题
注意事项
- 2023 年 9 月 15 号之前,默认不会启用隐私相关功能,所以检测不到需要弹窗的情况,可以在 app.json 中配置
"__usePrivacyCheck__": true
之后,接口才可以检测到是否需要弹窗。个人实际情况:我在开发者工具中配置了"__usePrivacyCheck__": true
,needAuthorization
无论如何返回的都是false
,但在真机模拟的情况下可以返回true
- 自动打开隐私保护指引界面需在「小程序管理后台」配置《小程序用户隐私保护指引》,官方用户隐私保护指引填写说明。
效果
使用方法
-
拷贝
component
文件夹中的privacy
文件夹到小程序项目中的组件目录 -
在 page.json 中引入组件
{
"usingComponents": {
"Privacy": "/component/privacy/privacy"
}
}
- 在 page.wxml 中使用组件
<Privacy />
- 可以在所有使用了隐私接口的页面都加上该组件,授权一次之后使用所有隐私接口不再需要授权
取消授权
微信中「微信下拉-最近-最近使用的小程序」中删除小程序可取消授权。
开发者工具中「清除模拟器缓存-清除授权数据」可取消授权。
相关链接
官方:小程序隐私协议开发指南
代码模块
1、技术:taro + vue3 + ts
2、创建component组件Privacy文件,在需要授权的页面添加<Privacy />
就阔以
- wxml 原生微信写法
// 1. 微信wxml的写法
// component/privacy/privacy.wxml
<view class="privacy" wx:if="{{showPrivacy}}">
<view class="content">
<view class="title">隐私保护指引</view>
<view class="des">
在使用当前小程序服务之前,请仔细阅读<text class="link" bind:tap="openPrivacyContract">{{privacyContractName}}</text>。如你同意{{privacyContractName}},请点击“同意”开始使用。
</view>
<view class="btns">
<button class="item reject" bind:tap="exitMiniProgram">拒绝</button>
<button id="agree-btn" class="item agree" open-type="agreePrivacyAuthorization" bindagreeprivacyauthorization="handleAgreePrivacyAuthorization">同意</button>
</view>
</view>
</view>
// 2、js 文件
// component/privacy/privacy.js
Component({
/**
* 组件的初始数据
*/
data: {
privacyContractName: '',
showPrivacy: false
},
/**
* 组件的生命周期
*/
pageLifetimes: {
show() {
const _ = this
wx.getPrivacySetting({
success(res) {
if (res.errMsg == "getPrivacySetting:ok") {
_.setData({
privacyContractName: res.privacyContractName,
showPrivacy: res.needAuthorization
})
}
}
})
}
},
/**
* 组件的方法列表
*/
methods: {
// 打开隐私协议页面
openPrivacyContract() {
const _ = this
wx.openPrivacyContract({
fail: () => {
wx.showToast({
title: '遇到错误',
icon: 'error'
})
}
})
},
// 拒绝隐私协议
exitMiniProgram() {
// 直接退出小程序
wx.exitMiniProgram()
},
// 同意隐私协议
handleAgreePrivacyAuthorization() {
const _ = this
_.setData({
showPrivacy: false
})
},
},
})
// 3、样式
/* component/privacy/privacy.wxss */
.privacy {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: rgba(0, 0, 0, .5);
z-index: 9999999;
display: flex;
align-items: center;
justify-content: center;
}
.content {
width: 632rpx;
padding: 48rpx;
box-sizing: border-box;
background: #fff;
border-radius: 16rpx;
}
.content .title {
text-align: center;
color: #333;
font-weight: bold;
font-size: 32rpx;
}
.content .des {
font-size: 26rpx;
color: #666;
margin-top: 40rpx;
text-align: justify;
line-height: 1.6;
}
.content .des .link {
color: #07c160;
text-decoration: underline;
}
.btns {
margin-top: 48rpx;
display: flex;
}
.btns .item {
justify-content: space-between;
width: 244rpx;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: 16rpx;
box-sizing: border-box;
border: none;
}
.btns .reject {
background: #f4f4f5;
color: #909399;
}
.btns .agree {
background: #07c160;
color: #fff;
}
- taro框架vue版写法
// #### taro框架的写法
<template>
<view class="privacy_box" v-if="showPrivacy">
<view class="content">
<view class="title">隐私保护指引</view>
<view class="des">
在使用当前小程序服务之前,请仔细阅读
<text class="link" @click="openPrivacyContract">{{ privacyContractName }}</text>
。如你同意{{ privacyContractName }},请点击“同意”开始使用。
</view>
<view class="btns">
<button class="item reject" @click="exitMiniProgram">拒绝</button>
<button
id="agree-btn"
class="item agree"
open-type="agreePrivacyAuthorization"
@agreeprivacyauthorization="handleAgreePrivacyAuthorization"
>
同意
</button>
</view>
</view>
</view>
</template>
<script setup lang="ts">
import { ref } from "vue";
import Taro, { useDidShow } from "@tarojs/taro";
const showPrivacy = ref<boolean>(false);
const privacyContractName = ref<string>("");
// 打开隐私协议页面
const openPrivacyContract = () => {
Taro.openPrivacyContract({
fail: () => {
Taro.showToast({
title: "遇到错误",
icon: "error",
});
},
});
};
// 拒绝隐私协议
const exitMiniProgram = () => {
Taro.exitMiniProgram();
};
// 同意隐私协议
const handleAgreePrivacyAuthorization = () => {
showPrivacy.value = false;
};
useDidShow(() => {
Taro.getPrivacySetting({
success(res) {
if (res.errMsg == "getPrivacySetting:ok") {
privacyContractName.value = res.privacyContractName;
showPrivacy.value = res.needAuthorization;
}
},
});
});
</script>
<style lang="scss">
.privacy_box {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 9999999;
display: flex;
align-items: center;
justify-content: center;
.content {
width: 632rpx;
padding: 48rpx;
box-sizing: border-box;
background: #fff;
border-radius: 16rpx;
}
.content .title {
text-align: center;
color: #333;
font-weight: bold;
font-size: 32rpx;
}
.content .des {
font-size: 26rpx;
color: #666;
margin-top: 40rpx;
text-align: justify;
line-height: 1.6;
}
.content .des .link {
color: #07c160;
text-decoration: underline;
}
.btns {
margin-top: 48rpx;
display: flex;
}
.btns .item {
justify-content: space-between;
width: 244rpx;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: 16rpx;
box-sizing: border-box;
border: none;
}
.btns .item::after {
border: 0;
}
.btns .reject {
background: #f4f4f5;
color: #909399;
}
.btns .agree {
background: #07c160;
color: #fff;
}
}
</style>