小程序隐私协议弹窗|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

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

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

相关推荐
.生产的驴11 小时前
SpringBoot 对接第三方登录 手机号登录 手机号验证 微信小程序登录 结合Redis SaToken
java·spring boot·redis·后端·缓存·微信小程序·maven
汤姆yu16 小时前
基于微信小程序的乡村旅游系统
微信小程序·旅游·乡村旅游
曲辒净17 小时前
微信小程序实现二维码海报保存分享功能
微信小程序·小程序
oil欧哟1 天前
🤔认真投入一个月做的小程序,能做成什么样子?有人用吗?
前端·vue.js·微信小程序
汤姆yu1 天前
基于微信小程序的消防隐患在线举报系统
微信小程序·小程序·消防隐患
郏国上1 天前
微信小程序的消息头增加的字段不能有下滑线,字段大写字母自动转换消息字母
微信小程序·小程序·
從南走到北2 天前
JAVA数字人创作文案视频链接提取数字人源码小程序+公众号+APP+H5
微信小程序·小程序·微信公众平台
FZUGO2 天前
EE308FZ_Sixth Assignment_Beta Sprint_Sprint Essay 3
java·微信小程序·sprint
V+zmm101342 天前
高校教师成果管理小程序的设计与实现springboot+论文源码调试讲解
java·微信小程序·小程序·毕业设计·ssm
蜂鸟视图fengmap2 天前
蜂鸟云平台2024年1月重大更新:JavaScript SDK v3.1.4 & 微信小程序SDK v0.9.4 亮点解析
开发语言·前端·javascript·微信小程序·ecmascript·主题编辑器·蜂鸟视图