一、前言
关于小程序隐私保护指引设置的公告:
为规范开发者的用户个人信息处理行为,保障用户的合法权益,自2023年9月15日起,对于涉及处理用户个人信息的小程序开发者,微信要求,仅当开发者主动向平台同步用户已阅读并同意了小程序的隐私保护指引等信息处理规则后,方可调用微信提供的隐私接口。
开发者首先需确定小程序是否涉及处理用户个人信息,如涉及,则需配置用户隐私授权弹窗,且仅有在平台《小程序用户隐私保护指引》中声明了所处理的用户个人信息,才可以调用平台提供的对应接口或组件。(隐私相关接口)
- 在 2023年9月15日之前,在 app.json 中配置 usePrivacyCheck: true 后,会启用隐私相关功能,如果不配置或者配置为 false 则不会启用。
- 在 2023年9月15日之后,不论 app.json 中是否有配置 usePrivacyCheck,隐私相关功能都会启用。

由于微信官网的隐私保护指引更新,在需要用户授权时,需要弹出隐私授权弹窗才可正常使用;在官网提供了多种示例demo可以参考:示例demo
在实际开发中,大多数的开发者会选用uniapp进行快速开发多端小程序,所以在这里为大家提供最新支持vue3+uniapp+uview-plus的隐私弹窗组件,无需导入 直接使用
二、组件自行封装
组件封装思路:
- 在访问需要授权的API时,比如业务需求需要在登录时通过号码授权登录,在点击登录时,可通过wx.onNeedPrivacyAuthorization监听隐私接口需要用户授权事件(Tips:onNeedPrivacyAuthorization首个回调参数resolve是一个接口函数,后续会用到),然后改变控制弹窗显隐的变量,显示授权弹窗(弹窗有同意和拒绝的按钮),
- 同意按钮(<button open-type="agreePrivacyAuthorization" @agreeprivacyauthorization="handleAgree">)触发同意按钮的dagreeprivacyauthorization事件中调用
resolve({ buttonId: 'agree-btn', event:'agree' })
)则同意授权进行下一步; - 拒绝按钮,触发同意按钮的dagreeprivacyauthorization事件中调用resolve({ event: 'disagree' })则拒绝授权并返回
API:fail privacy permission is not authorized
的错误信息; - 为了弹窗按钮方便调用resolve回调函数,在监听授权时我们可以创建一个变量将resolve添加进去;
详细代码
html
<template>
<up-popup
:show="show"
@close="show = false"
:safeAreaInsetBottom="false"
mode="center"
:closeOnClickOverlay="false"
:round="16"
>
<view class="uu-privacy-popup">
<view class="uu-privacy-popup__header">
<view class="uu-picker__title">隐私保护指引</view>
</view>
<view class="uu-privacy-popup__container">
<view>
感谢选择我们的小程序,我们非常重视您的个人信息安全和隐私保护。根据最新法律要求,使用我们的产品前,请仔细阅读“
<text
class="uu-privacy-popup__container-protocol"
@click="openPrivacyContract"
:style="{
color: color,
}"
>{{ `《${appName}挂号平台小程序隐私保护指引》` }}</text
>”,以便我们向您提供更优质的服务!
</view>
<text>我们将尽全力保护您的个人信息及合法权益,感谢您的信任!</text>
</view>
<view class="uu-privacy-popup__footer">
<button class="is-disagree" id="disagree-btn" @click="handleDisagree">
拒绝
</button>
<button
:style="{
background: color,
}"
class="is-agree"
id="agree-btn"
open-type="agreePrivacyAuthorization"
@agreeprivacyauthorization="handleAgree"
>
同意
</button>
</view>
</view>
</up-popup>
</template>
TS
<script setup lang="ts">
import { nextTick, onMounted, ref } from "vue";
/**
* @property {String} appName 必传|小程序名
* @property {Boolean} manual 是否手动监听需要授权,true-执行情况一,false执行情况二
* @property {Boolean} isExit 拒绝授权是否直接退出小程序
* @property {String} color 主题色(默认#5685ff)
*/
const $props = withDefaults(
defineProps<{
manual?: boolean;
isExit?: boolean;
color?: string;
appName: "";
}>(),
{
isExit: false,
color: "#5685ff",
}
);
/**
* @event disagree 拒绝授权执行事件
* @event agree 同意授权执行事件
*/
const $emit = defineEmits<{
(e: "disagree"): void;
(e: "agree"): void;
}>();
const privacyResolves = new Set();
let privacyHandler: any = null;
const show = ref(false);
/**
* @description 情况一.注册监听需要授权
* 一般在需要点击授权的按钮时自动弹出隐私协议(比如登录)
*/
if (wx.onNeedPrivacyAuthorization) {
wx.onNeedPrivacyAuthorization((resolve: any) => {
console.log(resolve, "resolve");
if (typeof privacyHandler === "function") {
privacyHandler(resolve);
}
});
}
/**
* @description 情况二.查询隐私授权情况
* 一般在小程序启动时自动弹出隐私协议(比如启动时需要授权获取定位等,授权后登录等则不需要再次授权)
*/
/**可在DCloud下载完整实例查看*/
//查看隐私协议
const openPrivacyContract = () => {
wx.openPrivacyContract({
success: (res: any) => {
console.log("openPrivacyContract success");
},
fail: (res: any) => {
console.error("openPrivacyContract fail", res);
},
});
};
// 拒绝
const handleDisagree = () => {
show.value = false;
if ($props.manual) {
privacyResolves.forEach((resolve: any) => {
resolve({
event: "disagree",
});
});
privacyResolves.clear();
$emit("disagree");
}
// #ifdef MP
if ($props.isExit) wx.exitMiniProgram(); //拒绝授权直接退出小程序
// #endif
};
// 同意
const handleAgree = () => {
show.value = false;
if ($props.manual) {
privacyResolves.forEach((resolve: any) => {
resolve({
event: "agree",
buttonId: "agree-btn",
});
});
privacyResolves.clear();
}
$emit("agree");
};
// 获取页面栈
const getPrevPage = (num = 1) => {
let pages = getCurrentPages();
let currentPage = pages[pages.length - num];
return new Promise((resolve, reject) => {
if (currentPage) {
resolve(currentPage);
} else {
reject("页面不存在");
}
});
};
// 通过弹窗组件ID获取组件实例
const getComponent = (context, selector) => {
let component = null;
// #ifdef MP
component =
context.selectComponent &&
context.selectComponent(selector) &&
context.selectComponent(selector).$vm;
// #endif
return component;
};
onMounted(() => {
privacyHandler = async (resolve: any) => {
const context = await getPrevPage();
const privacyPopup = getComponent(context, "#uu-privacy");
if (privacyPopup) {
nextTick(() => {
show.value = true;
});
}
privacyResolves.add(resolve);
};
});
</script>
三、组件如何使用
在需要弹窗授权弹窗的页面引入组件使用;例如登录页面:
<button
class="btn mobile"
data-eventsync="true"
open-type="getPhoneNumber"
@getphonenumber="getPhonenumber"
>
手机号快捷登录
</button>
<!-- #ifdef MP -->
<uu-privacy manual id="uu-privacy" appName="测试" />
<!-- #endif -->
四、DCloud插件下载
如果有小伙伴不想自己封装组件,我也已经封装好插件,发布到DCloud市场,大家也可以在插件市场直接下载使用即可,也有完整demo下载调试查看,当前插件市场有各种丰富的授权弹窗组件,大家可以自由选择。
接下来为大家介绍如果进行下载:
点击下方链接进入到插件页面:微信隐私协议弹窗、授权弹窗、授权协议弹窗、vue3+uview-plus - DCloud 插件市场
- 点击右方绿色按钮下载插件并导入HBuilderX,(如果是用vscode,用vue-cli创建的项目也可以使用,将项目先导入到HBuilderX,再点击下载即可)
- 点击下载后,在HBuilderX会显示一个弹窗,选择对应项目导入该插件;
- 导入后,在项目中会多一个uni_modules文件夹,里面存在uu-privacy插件;
五、插件如何使用
在需要弹窗授权弹窗的页面直接使用,不需要单独引入组件;例如登录页面:
<button
class="btn mobile"
data-eventsync="true"
open-type="getPhoneNumber"
@getphonenumber="getPhonenumber"
>
手机号快捷登录
</button>
<!-- #ifdef MP -->
<uu-privacy manual id="uu-privacy" appName="测试" />
<!-- #endif -->
在使用中如果有问题,欢迎各位大佬提供建议,我会及时进行修复和改正,也欢迎各位大佬讨论、补充…
如果有需要自己搭建uniapp+vue3+vite小程序框架的小伙伴们,可以参考文章哦:
uniapp+vue3+vite+ts+uview-plus 最完整最详细搭建项目步骤_uviewplus-CSDN博客