微信小程序隐私协议接入

自2023年9月15日起,对于涉及处理用户个人信息的小程序开发者,微信要求,仅当开发者主动向平台同步用户已阅读并同意了小程序的隐私保护指引等信息处理规则后,方可调用微信提供的隐私接口。

相关公告见:关于小程序隐私保护指引设置的公告 | 微信开放社区

公告里已经介绍了相关流程,这里不再赘述。下面我们将着重谈一下代码实现。

触发式隐私协议

首先,我们要知道的一点是如果用户没有同意过隐私协议,调用某些API(具体参看:小程序用户隐私保护指引内容介绍 | 微信开放文档)是会触发隐私协议弹窗的,这种叫触发式隐私协议。如果用户同意,这个API调用还能继续执行,否则就会报失败。所以我们要做的是在这个时候,在当前页面弹出我们自定义的隐私协议alert,并且接收resolve。然后在用户同意和拒绝的时候调用这个resolve。具体代码如下:

// page.wxml
<view wx:if="{{showPrivacy}}">
  <view>隐私弹窗内容....</view>
  <button id="agree-btn" open-type="agreePrivacyAuthorization" bindagreeprivacyauthorization="handleAgreePrivacyAuthorization">同意</button>
</view>
// page.js
Page({
  data: {
    showPrivacy: false
  },
  onLoad() {
    wx.onNeedPrivacyAuthorization(resolve => {
      // 需要用户同意隐私授权时
      // 弹出开发者自定义的隐私授权弹窗
      this.setData({
        showPrivacy: true
      })
      this.resolvePrivacyAuthorization = resolve
    })

    wx.getUserProfile({
      success: console.log,
      fail: console.error
    })
  },
  handleAgreePrivacyAuthorization() {
    // 用户点击同意按钮后
    this.resolvePrivacyAuthorization({ buttonId: 'agree-btn', event: 'agree' })
    // 用户点击同意后,开发者调用 resolve({ buttonId: 'agree-btn', event: 'agree' })  告知平台用户已经同意,参数传同意按钮的id。为确保用户有同意的操作,基础库在 resolve 被调用后,会去检查对应的同意按钮有没有被点击过。检查通过后,相关隐私接口会继续调用
    // 用户点击拒绝后,开发者调用 resolve({ event:'disagree' }) 告知平台用户已经拒绝
  }
})

 这里同意的按钮必须使用系统提供的这个写法,需要指定一个id和回调方法。拒绝的按钮没有什么要求。这里务必要保存resolve,并且在同意和拒绝中调用它,否则触发隐私协议的API的成功和失败回调就不会走。这里有个问题,可能多个页面都有API会触发,但是onNeedPrivacyAuthorization只能注册一个,前面注册的会被后面的覆盖。所以,如果把注册方法写在load里可能造成,页面回来的时候就不会触发了。因此建议这个注册放在show的时候注册。关于这个API的更多内容可以查看:wx.onNeedPrivacyAuthorization(function listener) | 微信开放文档

隐私协议的弹窗是我们自定义的,里面的文本建议根据官方的例子来写,要获取指引的名字,可以通过wx.getPrivacySetting这个API。点击指引前往查看隐私协议的页面,可以我们自己写,也可以用微信官方提供的页面,只需要调用接口wx.openPrivacyContract就行。注意,阅读隐私协议不是必须的,所以你可以强制要求用户前往阅读,也可以什么都不做。

主动式隐私协议

前面我们讲的触发式隐私协议,相对比较麻烦,要去找到这些敏感接口调用的页面,然后全都处理一下。还有一种是主动式隐私协议。主动式隐私协议,就是你在关键入口,主动弹出这个协议窗口,让用户去同意或者拒绝。这时候就没有resolve了。但是这样做有个问题,如果用户点了同意,那么后续这些API都会调用成功,用户和开发者都很高兴。但是万一用户拒绝,如果你没有注册onNeedPrivacyAuthorization并进行适当处理,那后续调用都会失败。这时候偷懒的做法是,用户拒绝后就退出小程序,但是这种做法体验不佳。我们应该尽量让用户能使用其他功能,毕竟这些涉及的API可能我们并不太关心,譬如说用户只是不能上传下载图片,而这些并非我们小程序的核心功能。

组件实现

从用户体验上来讲,对于使用相关API比较多的小程序,为了避免遗漏和一些特殊场景,建议在入口主动弹出隐私协议。对于用量较少的小程序,可以采用触发式隐私协议。无论我们采取何种做法,我们都将其封装为一个组件。

UI部分没有什么特别的,我们找个写好的,类似微信风格的实现:

 相关页面代码:

<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="refusePrivacy">拒绝</button>
            <button id="agree-btn" class="item agree" open-type="agreePrivacyAuthorization" bindagreeprivacyauthorization="handleAgreePrivacyAuthorization">同意</button>
        </view>
    </view>
</view>
.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;
}

在组件实现里,我们声明了三个属性,forceShow用于主动式隐私协议,设置true的时候可以强制显示。false的时候,则组件显示由注册回调触发,是触发式隐式协议。forceRead控制用户是否需要强制阅读协议。exitOnRefuse指当用户拒绝的时候,是否需要强制退出小程序。我们在页面show的时候,注册隐私协议触发回调,调用getPrivacySetting获取协议的名称。这里用到了组件的pageLifetimes。后面就是实现打开协议,同意和拒绝的回调。同意和拒绝的回调里,我们要判断是否保存了resolve,有的话是触发式的,需要进行调用,调用完了立刻将其清空。因为我们能区分这两种隐私协议,因此我们在拒绝的时候,显示了不同的错误提示:对于主动式的,我们就说部分功能不可用。对于触发式的,我们就说该功能不可用。

完整的js代码如下:

Component({
  options: {
    pureDataPattern: /^_/ // 指定所有 _ 开头的数据字段为纯数据字段
  },
  /**
   * 组件的属性列表
   */
  properties: {
    forceShow: {
      type: Boolean,
      value: false
    },
    forceRead: {
      type: Boolean,
      value: false
    },
    exitOnRefuse: {
      type: Boolean,
      value: false
    }
  },

  /**
   * 组件的初始数据
   */
  data: {
    privacyContractName: '',
    showPrivacy: false,
    _isRead: false
  },
  /**
   * 组件的生命周期
   */
  pageLifetimes: {
    show() {
      const that = this
      wx.onNeedPrivacyAuthorization(resolve => {
        that.resolvePrivacyAuthorization = resolve
        that.setData({
          showPrivacy: true
        })
      })
      wx.getPrivacySetting({
        success(res) {
          that.setData({
            privacyContractName: res.privacyContractName,
            showPrivacy: that.data.forceShow
          })
        }
      })
    }
  },
  /**
   * 组件的方法列表
   */
  methods: {
    // 打开隐私协议页面
    openPrivacyContract() {
      const that = this
      wx.openPrivacyContract({
        success: () => {
          that.setData({
            _isRead: true
          })
        },
        fail: () => {
          wx.showToast({
            title: '指引打开失败',
            icon: 'error'
          })
        }
      })
    },
    // 拒绝隐私协议
    refusePrivacy() {
      if(this.data.exitOnRefuse){
        // 直接退出小程序
        wx.exitMiniProgram()
        return
      }
      let tips = ""
      if (this.resolvePrivacyAuthorization) {
        this.resolvePrivacyAuthorization({
          event: 'disagree'
        })
        this.resolvePrivacyAuthorization = null
        tips = '该功能不可用'
      } else {
        tips = '部分功能不可用'
      }
      this.setData({
        showPrivacy: false
      })
      wx.showToast({
        title: tips,
        icon: 'error'
      })
    },
    // 同意隐私协议
    handleAgreePrivacyAuthorization() {
      const {
        _isRead,
        forceRead
      } = this.data
      if (_isRead || !forceRead) {
        if (this.resolvePrivacyAuthorization) {
          this.resolvePrivacyAuthorization({
            buttonId: 'agree-btn',
            event: 'agree'
          })
          this.resolvePrivacyAuthorization = null
        }
        this.setData({
          showPrivacy: false
        })
      } else {
        wx.showToast({
          title: '请先阅读指引',
          icon: 'error'
        })
      }
    },
  },

  observers: {
    "forceShow": function (forceShow) {
      this.setData({
        showPrivacy: forceShow
      })
    }
  }
})

整个组件的使用非常简单,只需要在相关页面的json文件里引入。如果涉及的页面较多的话,也可以在小程序全局组件配置里引入:

{

  "usingComponents": {
    "Privacy": "/components/privacy/privacy"
  }
}

以及在所有相关wxml里引入:

<Privacy/>

这里效果图和部分代码参考了:GitHub - 94xy/miniprogram-privacy: 小程序用户隐私保护授权弹窗组件表示感谢。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/93610.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python实现T检验

今天来分享一下T检验的python实现方法。 01 先来上一波概念。 1.单样本t检验&#xff0c;又称单样本均数t检验&#xff0c;适用于来自正态分布的某个样本均数与已知总体均数的比较&#xff0c;其比较目的是检验样本均数所代表的总体均数是否与已知总体均数有差别。已知总体均数…

hiredis的安装与使用

hiredis的介绍 Hiredis 是一个用于 C 语言的轻量级、高性能的 Redis 客户端库。它提供了一组简单易用的 API&#xff0c;用于与 Redis 数据库进行交互。Hiredis 支持 Redis 的所有主要功能&#xff0c;包括字符串、哈希、列表、集合、有序集合等数据结构的读写操作&#xff0c…

【CSS 画个梯形】

使用clip-path: polygon画梯形 clip-path: polygon使用方式如下&#xff1a; 效果实现 clip-path: polygon 是CSS的属性之一&#xff0c;用于裁剪元素的形状。它可以通过定义一个具有多边形顶点坐标的值来创建一个多边形的裁剪区域&#xff0c;从而实现元素的非矩形裁剪效果。…

Python实现企业微信群告警

Python实现企业微信告警 1. 创建企业微信群机器人 1-1. 什么是企业微信群机器人&#xff1f; 企业微信群机器人是企业微信平台提供的一种功能&#xff0c;可以通过Webhook方式将消息发送到指定的企业微信群中。它可以用于自动化发送通知、告警等信息&#xff0c;实现监控和信…

设计模式之职责链模式(ChainOfResponsibility)的C++实现

1、职责链模式的提出 在软件开发过程中&#xff0c;发送者经常发送一个数据请求给特定的接收者对象&#xff0c;让其对请求数据进行处理&#xff08;一个数据请求只能有一个对象对其处理&#xff09;。如果发送的每个数据请求指定特定的接收者&#xff0c; 将带来发送者与接收…

elementUI moment 年月日转时间戳 时间限制

changeStartTime(val){debuggerthis.startT val// this.startTime parseInt(val.split(-).join())this.startTime moment(val).unix() * 1000 //开始时间毫秒if(this.endTime){this.endTime moment(this.endT).unix() * 1000 //结束时间毫秒if(this.startTime - this.endTi…

webassembly003 ggml GGML Tensor Library part-2 官方使用说明

https://github.com/ggerganov/whisper.cpp/tree/1.0.3 GGML Tensor Library 官方有一个函数使用说明&#xff0c;但是从初始版本就没修改过 : https://github1s.com/ggerganov/ggml/blob/master/include/ggml/ggml.h#L3-L173 This documentation is still a work in progres…

Windows用户如何安装Cpolar

目录 概述 什么是cpolar&#xff1f; cpolar可以用在哪些场景&#xff1f; 1. 注册cpolar帐号 1.1 访问官网站点 2. 下载Windows版本cpolar客户端 2.1 下载并安装 2.2 安装完验证 3. token认证 3.1 将token值保存到默认的配置文件中 3.2 创建一个随机url隧道&#x…

芯片 半导体 晶圆

芯片&#xff08;chip&#xff09;就是半导体元件产品的统称&#xff0c;是 集成电路&#xff08;IC&#xff0c; integrated circuit&#xff09;的载体&#xff0c;由晶圆分割而成。 半导体集成电路是将很多元件集成到一个芯片内, 以处理和储存各种功能的电子部件。由于半导…

【ES6】—【新特性】—Symbol详情

一、一种新的原始数据类型 定义&#xff1a;独一无二的字符串 二、 声明方式 1. 无描述声明 let s1 Symbol() let s2 Symbol() console.log(s1, s2) // Symbol() Symbol() console.log(s1 s2) // falsePS: Symbol 声明的值是独一无二的 2. 有描述的声明 let s1 Symb…

Linux系统编程系列之进程间通信(IPC)-信号

一、什么是信号 信号是进程间通信的一种方式&#xff0c;它是异步通信的。而异步的意思就是不同步&#xff0c;事件的发生和处理没有协同。 二、信号的特性 Linux/Unix系统下&#xff0c;信号总共分成两大类&#xff0c;一类是最常用的标准信号&#xff0c;另一类是后面的引入…

云服务器 宝塔(每次更新)

su root 输入密码 使用 root 权限 /etc/init.d/bt default 获取宝塔登录 位置和账号密码。进入宝塔 删除数据库 删除php前端站点 删除PM2后端项目 前端更改完配置打包dist文件 后端更改完配置项目打包 数据库结构导出 导入数据库 配置 PM2 后端 安装依赖

任务执行和调度----Spring线程池/Quartz

定时任务 在服务器中可能会有定时任务&#xff0c;但是不知道分布式系统下次会访问哪一个服务器&#xff0c;所以服务器中的任务就是相同的&#xff0c;这样会导致浪费。使用Quartz可以解决这个问题。 JDK线程池 RunWith(SpringRunner.class) SpringBootTest ContextConfi…

java开发之fastjson

依赖 <!-- fastjson依赖 --> <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.76</version> <…

数据分析基础-数据可视化学习笔记04-互动方式

交互方式 交互&#xff08;Interaction&#xff09;是指用户与系统、设备或其他用户之间的相互作用、传递信息和交流的过程。在计算机科学、人机交互和用户体验领域&#xff0c;交互是用户与技术之间的核心概念&#xff0c;它决定了用户如何与计算机系统或其他技术进行沟通、操…

【项目 计网6】 4.17 TCP三次握手 4.18滑动窗口 4.19TCP四次挥手

文章目录 4.17 TCP三次握手4.18滑动窗口4.19TCP四次挥手 4.17 TCP三次握手 TCP 是一种面向连接的单播协议&#xff0c;在发送数据前&#xff0c;通信双方必须在彼此间建立一条连接。所谓的“连接”&#xff0c;其实是客户端和服务器的内存里保存的一份关于对方的信息&#xff…

基于Visual studio创建API项目

API&#xff08;英文全称&#xff1a;Application Programming Interface,中文&#xff1a;应用程序编程接口&#xff09; 为什么要 通过API接口可以与其他软件实现数据相互通信&#xff0c;API这项技术能够提高开发效率。 本文是基于vs2017 .net平台搭建API。希望可以帮助到学…

从2023年世界机器人大会发现机器人新趋势

机器人零部件为何成2023年世界机器人大会关注热门&#xff1f; 在原先&#xff0c;机器人的三大核心零部件是控制系统中的控制器、驱动系统中的伺服电机和机械系统中的精密减速器。如今&#xff0c;机器人的主体框架结构已经落实&#xff0c;更多机器人已经开始深入到各类场景中…

mysql Left Join on条件 where条件的用法区别

数据准备 SELECT t1.id,t1.name,t2.local FROM t1 LEFT JOIN t2 ON t1.idt2.id; 执行结果 SELECT t1.id,t1.name,t2.local FROM t1 LEFT JOIN t2 ON t1.idt2.id and t2.localbeijing; SELECT t1.id,t1.name,t2.local FROM t1 LEFT JOIN t2 ON t1.idt2.id where t2.localbeijing…

设计模式--建造者模式(Builder Pattern)

一、什么是建造者模式 建造者模式&#xff08;Builder Pattern&#xff09;是一种创建型设计模式&#xff0c;它关注如何按照一定的步骤和规则创建复杂对象。建造者模式的主要目的是将一个复杂对象的构建过程与其表示分离&#xff0c;从而使同样的构建过程可以创建不同的表示。…