小程序隐私协议弹窗|Taro项目

离9月16只剩最后一周了,还有多少小伙伴和我一样还没上线微信要求的 小程序隐私协议。趁今天不忙赶紧把这个开发了。

新提供的四个API

  • wx.onNeedPrivacyAuthorization 监听隐私接口需要用户授权事件。
  • wx.openPrivacyContract 跳转至隐私协议页面。
  • wx.getPrivacySetting 查询隐私授权情况。
  • wx.requirePrivacyAuthorize 模拟隐私接口调用,并触发隐私弹窗逻辑。

其中后面两个不是必须要用,看业务逻辑。一般我们用wx.onNeedPrivacyAuthorizationwx.openPrivacyContract 就可以。微信社区有更多文章介绍。在这里就说明常见流程:

用户触发隐私接口 --> wx.onNeedPrivacyAuthorization的回调函数能监听到了,开发者弹出隐私窗口 --> 弹窗提供隐私协议链接,通过 wx.openPrivacyContract 调用跳转 --> 用户可选择性看完后点 同意按钮:<button id="agree-btn" open-type="agreePrivacyAuthorization" bindagreeprivacyauthorization="handleAgree">同意</button> --> 触发按钮事件即成功。

Taro项目中使用

Taro项目中使用 openType 为 agreePrivacyAuthorization 的 Button 组件在新版本可以直接用 ,如果旧版需要做一些处理,github上有 issue

先安装 @tarojs/plugin-inject

bash 复制代码
npm i @tarojs/plugin-inject -D

然后 config/index.js 中增加 plugins 配置:

javascript 复制代码
{
   // ...
   plugins:[
      [
        "@tarojs/plugin-inject",
        {
          
          components: {
            Button: {
              bindagreeprivacyauthorization: ""
            }
          }
        }
      ]
    ]
}

最后 Button 组件就可正常使用。

jsx 复制代码
<Button
  // @ts-ignore
  openType="agreePrivacyAuthorization"
  // @ts-ignore
  onAgreePrivacyAuthorization={handleOnAgreePrivacyAuthorization}
>
  我同意
</Button>

组件封装

代码示例在官网文档已提供了demo。拿来修改下,改成React组件,效果图如下

下面贴下弹窗代码,只需要在页面中引入即可。

jsx

jsx 复制代码
import React, { memo, useEffect, useState } from 'react';
import { View, Text, Button } from '@tarojs/components';
import './index.less';

let privacyHandler;
let privacyResolves = new Set<Function>();

if (wx?.onNeedPrivacyAuthorization) {
  wx?.onNeedPrivacyAuthorization(resolve => {
    privacyHandler?.(resolve);
  });
}

const PrivacyPopup: React.FC = () => {
  const [visible, setVisible] = useState<boolean>(false);

  const handleDisagree = () => {
    setVisible(false);
    privacyResolves.forEach(resolve => {
      resolve({
        event: 'disagree'
      });
    });
    privacyResolves.clear();
  };

  const handleAgree = () => {
    setVisible(false);
    // 额外处理:例如有可能弹出授权弹窗,但是用户没点击 同意/拒绝 就回退页面,导致没有resolve,这里让所有pending中的wx隐私接口继续执行
    privacyResolves.forEach(resolve => {
      resolve({
        event: 'agree',
        buttonId: 'agree-btn'
      });
    });
    privacyResolves.clear();
  };

  useEffect(() => {
    privacyHandler = resolve => {
      privacyResolves.add(resolve);
      setVisible(true);
    };
  }, []);

  const openPrivacyContract = () => {
    wx?.openPrivacyContract({
      success: () => {
        console.log('openPrivacyContract success');
      },
      fail: res => {
        console.error('openPrivacyContract fail', res);
      }
    });
  };

  return (
    <View className="pp-container">
      {visible && <View className="pp-mask" />}
      {visible && (
        <View className="pp-wrap">
          <View className="pp-head">
            <View className="pp-head-title">用户隐私保护提示</View>
          </View>
          <View className="pp-content">
            感谢您使用xxx服务,您在使用该服务前,请仔细阅读
            <Text className="pp-link" onClick={openPrivacyContract}>
              {' '}
              用户隐私保护指引{' '}
            </Text>
            。当您点击同意并开始使用该服务时,即表示您已理解并同意该条款内容。
          </View>
          <View className="pp-footer">
            <Button id="disagree-btn" className="pp-btn pp-btn_refuse" onClick={handleDisagree}>
              拒绝
            </Button>
            <Button
              id="agree-btn"
              className="pp-btn"
              openType="agreePrivacyAuthorization"
              onAgreePrivacyAuthorization={handleAgree}
            >
              同意
            </Button>
          </View>
          <View className="pp-safearea" />
        </View>
      )}
    </View>
  );
};

export default memo(PrivacyPopup);

样式

less 复制代码
.pp {
  &-container {
    position: fixed;
    z-index: 10;
  }

  &-mask {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    opacity: 0;
    animation: ppFadeIn 0.2s cubic-bezier(0.55, 0, 0.55, 0.2) forwards;
    background: rgba(4, 8, 18, 0.4);
  }

  &-wrap {
    max-height: 80vh;
    display: flex;
    flex-direction: column;
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    padding: 36px 36px 0;
    border-radius: 40px 40px 0 0;
    animation: ppSlideUpIn 0.2s cubic-bezier(0.55, 0, 0.55, 0.2);
    background: #fff;
  }

  &-head {
    flex-shrink: 0;

    &-title {
      font-weight: 500;
      font-size: 40px;
      line-height: 48px;
      color: #1f242e;
    }
  }

  &-link {
    color: #3098ff;
  }

  &-content {
    margin: 28px 0;
    font-size: 32px;
    line-height: 48px;
    color: #4d535c;

  }

  &-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 16px 0;
  }

  &-btn {
    display: block;
    width: 280px;
    padding: 28px;
    border: none;
    box-shadow: 0 4px 16px rgba(46, 87, 234, 0.2);
    background: radial-gradient(
          94.86% 3821.12% at 91.96% 50%,
          rgba(63, 220, 255, 0.38) 0%,
          rgba(26, 241, 255, 0) 100%
        ),
        linear-gradient(262.71deg, #3098ff 5.67%, #3c70ff 94.33%);
    border-radius: 16px;
    color: #fff;
    font-size: 36px;
    line-height: 42px;
    font-weight: 600;
    box-sizing: border-box;
    margin: 0 auto;
    
   &::after {
    border: none;
   }

    &_refuse {
      background: #fff;
      border: 1px solid #e9e9e9;
      color: #4d535c;
      box-shadow: none;
    }
  }
  
  &-safearea {
    display: block;
    width: 100%;
    padding-bottom: env(safe-area-inset-bottom);
  }

  @keyframes ppSlideUpIn {
    0% {
      transform: translate(0, 100%);
    }

    100% {
      transform: translate(0, 0);
    }
  }

  @keyframes ppFadeIn {
    0% {
      opacity: 0;
    }

    100% {
      opacity: 1;
    }
  }
}

官方演示的弹窗没有蒙层,弹窗显示时可以随意点击页面,所以官方演示代码里做了弹窗保持单例的逻辑。上面的封装的组件有蒙层,弹窗关闭前不能点击其他,就不做这处理了。

调试

代码写好后,开始调试。我们先去微信后台的 设置-基本设置-服务内容声明-用户隐私保护指引 填写你的小程序用到的隐私接口,例如

Taro项目中 app.config.ts 加上 __usePrivacyCheck__: true

另外,微信开发者工具的调试基础库最好设置成3.0.0

然后在需要的页面引入组件即可。

其他

最近微信又更新了,隐私同意按钮支持与手机号快速验证组件手机号实时验证组件耦合使用。

html 复制代码
<button id="agree-btn1" open-type="getPhoneNumber|agreePrivacyAuthorization" bindgetphonenumber="handleGetPhoneNumber" bindagreeprivacyauthorization="handleAgreePrivacyAuthorization">同意隐私协议并授权手机号</button>

<button id="agree-btn2" open-type="getRealtimePhoneNumber|agreePrivacyAuthorization" bindgetrealtimephonenumber="handleGetRealtimePhoneNumber" bindagreeprivacyauthorization="handleAgreePrivacyAuthorization">同意隐私协议并授权手机号</button>

<button id="agree-btn3" open-type="getUserInfo|agreePrivacyAuthorization" bindgetuserinfo="handleGetUserInfo" bindagreeprivacyauthorization="handleAgreePrivacyAuthorization">同意隐私协议并获取头像昵称信息</button>

就是说获取手机号和同意隐私同一个按钮,点同意后即可调通隐私接口。

我们可以另外封装个弹窗组件

jsx 复制代码
import React, { memo } from 'react';

import { View, Text, Button } from '@tarojs/components';

import './index.less';

interface PrivacyPopupProps {
  visible: boolean;
  onClose: () => void;
}

const PrivacyUserPopup: React.FC<PrivacyPopupProps> = ({ visible, onClose }) => {
  const handleGetPhone = (e: any) => {
    onClose();
    if (e.detail.errMsg !== 'getPhoneNumber:ok') {
      return;
    }
    // 下面写登录等逻辑
  };

  const handleAgree = () => {
    console.log('同意');
  };

  const openPrivacyContract = () => {
    wx?.openPrivacyContract({
      success: () => {
        console.log('openPrivacyContract success');
      },
      fail: res => {
        console.error('openPrivacyContract fail', res);
      }
    });
  };

  return (
    <View className="pp-container">
      {visible && <View className="pp-mask" />}
      {visible && (
        <View className="pp-wrap">
          <View className="pp-head">
            <View className="pp-head-title">用户隐私保护提示</View>
          </View>
          <View className="pp-content">
            感谢您使用xxx服务,您在使用该服务前,请仔细阅读
            <Text className="pp-link" onClick={openPrivacyContract}>
              {' '}
              用户隐私保护指引{' '}
            </Text>
            。当您点击同意并开始使用该服务时,即表示您已理解并同意该条款内容。
          </View>
          <View className="pp-footer">
            <Button id="disagree-btn" className="pp-btn pp-btn_refuse" onClick={onClose}>
              拒绝
            </Button>
            <Button
              id="agree-btn"
              className="pp-btn"
              // @ts-ignore
              openType="getPhoneNumber|agreePrivacyAuthorization"
              onAgreePrivacyAuthorization={handleAgree}
              onGetPhoneNumber={handleGetPhone}
            >
              同意隐私协议并授权手机号
            </Button>
          </View>
          <View className="pp-safearea" />
        </View>
      )}
    </View>
  );
};

export default memo(PrivacyUserPopup);

效果图如下,注意调试时 开发者工具基础库要 3.0.1

如果你的小程序只需要获取手机号/用户信息的隐私接口,或者说只有获取手机号/用户信息后才会用到其他隐私接口,那么用这个弹窗最好了。

但是作者开发的小程序还涉及粘贴板、获取位置信息等隐私接口,假设用户先使用了粘贴板隐私接口,还是得用第一个用法才能隐私授权。所以懒得分开处理,为方便统一,还是用第一个弹窗组件吧。

相关推荐
中云DDoS CC防护蔡蔡2 小时前
微信小程序被攻击怎么选择高防产品
服务器·网络安全·微信小程序·小程序·ddos
井眼6 小时前
微信小程序-prettier 格式化
微信小程序·小程序
qq_17448285758 小时前
springboot基于微信小程序的旧衣回收系统的设计与实现
spring boot·后端·微信小程序
wqq_9922502778 小时前
springboot基于微信小程序的食堂预约点餐系统
数据库·微信小程序·小程序
licy__15 小时前
微信小程序登录注册页面设计(小程序项目)
微信小程序·小程序
wqq_9922502771 天前
springboot基于微信小程序的农产品交易平台
spring boot·后端·微信小程序
guanpinkeji2 天前
二手手机回收小程序,一键便捷高效回收
微信小程序·小程序·软件开发·手机回收小程序·二手手机回收
尘浮生2 天前
Java项目实战II基于微信小程序的私家车位共享系统(开发文档+数据库+源码)
java·开发语言·数据库·学习·微信小程序·小程序·maven
十幺卜入2 天前
基于xr-frame实现微信小程序的手部、手势识别3D模型叠加和石头剪刀布游戏功能
游戏·微信小程序·xr·手势识别·人手跟踪
坠入暮云间x2 天前
Nodejs开发仿马蜂窝旅游小程序API接口,服务器端开发,商家后台 Vue3+微信小程序+koa+mongodb+node.js
微信小程序·小程序·旅游