WeChat Mini Program Privacy Agreement introduces development tutorials and the best implementation method of uniapp


Preface

Starting from September 15, 2023, WeChat mini programs will require developers of mini programs that handle users’ personal information to remind users to read the privacy policy and other collection and use rules through obvious means such as pop-ups. In order to standardize developers' handling of user personal information and protect users' legitimate rights and interests, WeChat requires developers to actively synchronize WeChat's current users to have read and agree to the Mini Program's privacy policy and other collection and use rules before they can call the privacy interface provided by WeChat. In short, a privacy policy notification needs to pop up before calling certain APIs (privacy interfaces) that involve user privacy, such as obtaining user location (wx.getLocation), selecting address (wx.chooseAddress), selecting photos (wx.chooseImage), etc. Users can use functions normally only after obtaining consent.

需要注意的是所有涉及到隐私接口整个小程序只要同意一次隐私保护后所有api都能正常使用,本地也有相应生成缓存记录,如果删除小程序就需要重新同意。

Insert image description here

1. Related articles

You can check the official instructions of WeChat:
User Privacy Protection Guidelines Filling Instructions
Mini Program Privacy Agreement Development Guide Privacy Interface
(API) that requires a privacy agreement

2. Functional design

  对于弹窗时机设计可以分为两种,第一中比较暴力做法就是在首页进入立即弹出隐私同意窗口,
 不同意直接退出小程序。第二种比较友好方式在每次需要调用隐私api前检查根据需要弹窗。

ps: This article will mainly use the second method for development, and use uniapp development as an example.

3. Preparation before development

step one

It needs to be updated and filled in the mini program background-Settings-Service Content Statement-User Privacy Protection Guidelines. For details, please check the relevant article above-User Privacy Protection Guidelines filling instructions. It can be used normally after submission and review.
Insert image description here

Step 2

Before October 17, 2023, after configuring usePrivacyCheck : true in app.json, privacy-related functions will be enabled. If they are not configured or configured to false, they will not be enabled. After October 17, 2023, privacy-related features will be enabled regardless of whether usePrivacyCheck is configured in app.json.

If you are developing uniapp, switch to the source code in manifest.json and try to add " usePrivacyCheck ": true in the mp-weixin field.

 "mp-weixin" : {
		"__usePrivacyCheck__": true
    },

Step 3

相关api介绍

1. wx.getPrivacySetting(Object object)
queries the privacy authorization status. The successful callback parameter needAuthorization field indicates whether the user is required to authorize the privacy agreement.

wx.getPrivacySetting({
    
    
      success: res => {
    
    
        console.log(res) // 返回结果为: res = { needAuthorization: true/false, privacyContractName: '《xxx隐私保护指引》' }
        if (res.needAuthorization) {
    
    
          // 需要弹出隐私协议
        } else {
    
    
          // 用户已经同意过隐私协议,所以不需要再弹出隐私协议,也能调用隐私接口
        }
      },
      fail: () => {
    
    },
      complete: () => {
    
    }
    })

2. wx.openPrivacyContract(Object object)
jumps to the privacy agreement page

wx.openPrivacyContract({
    
    
  success: () => {
    
    }, // 打开成功
  fail: () => {
    
    }, // 打开失败
  complete: () => {
    
    }
})

3. <button open-type="agreePrivacyAuthorization>"
User agrees to the privacy agreement button. After the user clicks this button once, all declared privacy interfaces can be called normally. User consent to privacy agreement events can be monitored through bindagreeprivacyauthorization

4. Pre-development analysis

For privacy pop-ups, a global component needs to be encapsulated and introduced on the required page. Before calling the privacy api, determine whether a pop-up window is required based on the needAuthorization of wx.getPrivacySetting. If the value is false, no pop-up window is required, and true, a pop-up window is required to wait for the user's consent. The privacy api logic is implemented after the bindagreeprivacyauthorization callback of the consent button.

If many pages need to use the privacy API, and each page needs to introduce component tags separately, is there any way to introduce them globally without writing them separately? The answer is - vue-template-compiler. There are many articles about vue-template-compiler. You can check it out by yourself and will not go into details here.

The problem of component introduction has been solved, but the logic of each page needs to be written repeatedly. Is there a better and more convenient way to call it? So we thought of using something like loading components. uni.showToast() can control whether to display it through the global API.

So our final packaging goals are as follows:

this.$privacyCheck({
    
    
	 agree:()=>{
    
    },//已同意回调
	 disAgree:()=>{
    
    },//不同意回调
	 complete:()=>{
    
    }//完成回调
 })

It is very convenient to call this.$privacyCheck() on each page.

5. Code implementation

1. Privacy pop-up component

components/privacyDialog/index.vue

<!-- 隐私授权对话框 -->
<template>
	<view class="comp-container" v-if="visible">
		<view class="dialog">
			<view class="title">用户隐私保护提示</view>
			<view class="desc">
				感谢您使用本小程序,在使用前您应当阅读并同意<text class="privacy"
					@click="handleOpenPrivacyContract">《用户隐私保护指引》</text>,当点击同意,即表示您已理解并同意该条款内容,该条款将对您产生法律约束力;如您不同意,将无法继续使用小程序相关功能。
			</view>
			<view class="footer">
				<button type="default" class="btn disagree" @click="handleDisagree">不同意</button>
				<button type="default" open-type="agreePrivacyAuthorization" class="btn agree"
					@agreeprivacyauthorization="handleAgree">同意</button>

			</view>
		</view>
	</view>
</template>
<script>
	export default {
    
    
		data() {
    
    
			return {
    
    
				visible: false,
				agreeCallBack: null, //同意回调函数
				disAgreeCallBack: null, //不同意回调函数
				completeCallBack: null //完成回调函数
			}
		},
		methods: {
    
    
			//检查根据是否需要并弹出隐私窗口
			check(options = {
     
     }) {
    
    
				let {
    
    
					agree,
					disAgree,
					complete
				} = options
				if (uni.getPrivacySetting) {
    
    
					if (typeof complete === 'function') {
    
    
						this.completeCallBack = complete
					}
					uni.getPrivacySetting({
    
    
						success: res => {
    
    
							if (typeof agree === 'function') {
    
    
								this.agreeCallBack = agree
							}
							if (typeof disAgree === 'function') {
    
    
								this.disAgreeCallBack = disAgree
							}
							//需要隐私同意显示对话框
							if (res.needAuthorization) {
    
    
								this.visible = true
							} else {
    
    
								this.handleAgree()
							}
						},
						fail: () => {
    
    
							this.handleComplete()
						}
					})
				}

			},
			//隐藏对话框
			hide() {
    
    
				this.visible = false
			},
			//不同意
			handleDisagree() {
    
    
				this.visible = false
				if (typeof this.disAgreeCallBack === 'function') {
    
    
					this.disAgreeCallBack()
				}
				this.handleComplete()
			},
			//同意
			handleAgree() {
    
    
				this.visible = false;
				if (typeof this.agreeCallBack === 'function') {
    
    
					this.agreeCallBack()
				}
				this.handleComplete()

			},
			//完成
			handleComplete() {
    
    
				if (typeof this.completeCallBack === 'function') {
    
    
					this.completeCallBack()
				}
			},
			//打开隐私政策页面
			handleOpenPrivacyContract() {
    
    
				uni.openPrivacyContract()
			}
		}


	};
</script>
<style lang="scss" scoped>
	.comp-container {
    
    
		position: fixed;
		top: 0;
		right: 0;
		left: 0;
		bottom: 0;
		background-color: rgba(0, 0, 0, 0.6);
		z-index: 999;
	}

	.dialog {
    
    
		color: #333;
		position: absolute;
		top: 50%;
		left: 50%;
		transform: translate(-50%, -50%);
		background-color: #fff;
		border-radius: 20rpx;
		padding: 50rpx 40rpx;
		width: 560rpx;
		box-sizing: border-box;

		.title {
    
    
			width: 100%;
			color: #000;
			text-align: center;
			font-size: 32rpx;
			font-weight: 650;
			box-sizing: border-box;
		}

		.desc {
    
    
			line-height: 40rpx;
			box-sizing: border-box;
			margin-top: 50rpx;
			font-size: 26rpx;

			.privacy {
    
    
				color: #2f80ed;
			}
		}

		.footer {
    
    
			width: 100%;
			display: flex;
			align-items: center;
			justify-content: space-between;
			margin-top: 30rpx;

			.btn {
    
    
				display: flex;
				align-items: center;
				color: #FFF;
				font-size: 28rpx;
				font-weight: 500;
				line-height: 80rpx;
				text-align: center;
				height: 80rpx;
				border-radius: 10rpx;
				border: none;
				background: #07c160;
				flex: 1;
				justify-content: center;

				&:nth-last-child(1) {
    
    
					margin-left: 30rpx;
				}

				&.disagree {
    
    
					color: #333;
					background: #f2f2f2;
				}
			}
		}

	}
</style>

2.privacyCheck.js

components/privacyDialog/privacyCheck.js
detects whether a privacy pop-up window is required

/**隐私授权弹窗全局调用,agree同意或者已同意过(不需要弹窗)回调,disagree不同意回调,complete:所有情况都走该回调
 * this.$privacyCheck({
	 agree:()=>{},
	 disAgree:()=>{},
	 complete:()=>{}
 })
 */
const privacyCheck = (options = {
     
     }) => {
    
    
	const pages = getCurrentPages();
	let curPage = pages[pages.length - 1];//当前页面
	curPage.$vm.$refs.privacyDialog.check(options)

}

export default privacyCheck

3.main.js

import privacyCheck from '@/components/privacyDialog/privacyCheck.js'
import privacyDialog from '@/components/privacyDialog/index.vue'
Vue.component('privacyDialog',privacyDialog)
Vue.prototype.$privacyCheck=privacyCheck

4.vue.config.js

This is processed by vue-template-compiler, and a privacy pop-up component tag is added to each page template. If there is no such file, create a new one and write the following code:

module.exports = {
    
    
  chainWebpack: config => {
    
    
    config.module.rule('vue').use('vue-loader').loader('vue-loader').tap(options => {
    
    
      const compile = options.compiler.compile
      options.compiler.compile = (template, ...args) => {
    
    
        if (args[0].resourcePath.match(/^pages/)) {
    
    
          template = template.replace(/[\s\S]+?<[\d\D]+?>/, _ => `${
      
      _}
	        <privacyDialog ref="privacyDialog" />
	  `)
        }
        return compile(template, ...args)
      }
      return options
    })
  }
}

5. Page usage

manifest.json

 /* 小程序特有相关 */
    "mp-weixin" : {
    
    
		"requiredPrivateInfos" : [ "chooseAddress", "getLocation" ],
		"permission" : {
    
    
		    "scope.userLocation" : {
    
    
		        "desc" : "你的位置信息将用于小程序位置接口的效果展示"
		    }
		},
		"__usePrivacyCheck__": true
    },

index.vue

<template>
	<view class="content">
		<button @click="handleChoseAddress">选择地址</button>
	</view>
	
</template>

<script>
	export default {
    
    
		data() {
    
    
			return {
    
    

			}
		},
		mounted(){
    
    
			//定位
            this.handleLocation()
		},
		methods: {
    
    
			//定位
			handleLocation() {
    
    
				this.$privacyCheck({
    
    
					//已同意
					agree:()=>{
    
    
						uni.getLocation({
    
    
							success(e) {
    
    
								console.log(e)
							}
						})
					},
					//不同意
					disAgree:()=>{
    
    
						console.log('不同意')
					}
				})
			},
			//选择地址
			handleChoseAddress(){
    
    
				this.$privacyCheck({
    
    
					//已同意
					agree:()=>{
    
    
						uni.chooseAddress({
    
    
							success(e) {
    
    
								console.log(e)
							}
						})
					},
					//不同意
					disAgree:()=>{
    
    
						console.log('不同意')
					}
				})
			}
		}
	}
</script>

注意:this.$privacyCheck必须在mounted周期函数后(组件渲染完成)使用
Insert image description here

5. Summary

Through the above encapsulation, it is very convenient and quick to call the privacy pop-up window on the page. Currently, the privacy pop-up window component needs to be implemented by itself. According to the official instructions, subsequent updates may provide official components, and then there will be another option.

Guess you like

Origin blog.csdn.net/sd1sd2/article/details/133418393