侧边栏壁纸
博主头像
神的孩子都在跳舞博主等级

HARD WORK PAYS OFF

  • 累计撰写 22 篇文章
  • 累计创建 64 个标签
  • 累计收到 0 条评论

微信小程序获取用户头像和昵称

神的孩子都在跳舞
2022-12-26 / 0 评论 / 0 点赞 / 5,068 阅读 / 3,438 字 / 正在检测是否收录...

由于微信小程序在2022年11月8日24时调整了获取用户信息的接口,导致wx.getUserProfile()这个方法返回的用户头像和用户昵称都变成匿名的状态,如果想要获取用户的头像和昵称,必须让用户自己去填写。相关链接

调整背景

在小程序内,开发者可以通过 wx.login 接口直接获取用户的 openId 与 unionId 信息,实现微信身份登录,支持开发者在多个小程序或其它应用间匿名关联同一用户。

同时,为了满足部分小程序业务中需要创建用户的昵称与头像的诉求,平台提供了 wx.getUserProfile 接口,支持在用户授权的前提下,快速使用自己的微信昵称头像。

但实践中发现有部分小程序,在用户刚打开小程序时就要求收集用户的微信昵称头像,或者在支付前等不合理路径上要求授权。如果用户拒绝授权,则无法使用小程序或相关功能。在已经获取用户的 openId 与 unionId 信息情况下,用户的微信昵称与头像并不是用户使用小程序的必要条件。为减少此类不合理的强迫授权情况,作出如下调整。

代码调整

如果开发还是想要用户的昵称和头像作为友好的展示,就不得不改动现有的逻辑。

image.png

基本操作示例

以下代码是使用uni-app框架来开发,用的是vue3 typescript的语法,其中也用到了几个云函数

getSessionKey

这个云函数用来call 微信的restful API获取用户的sessionKey和openId

// getSessionKey
'use strict';
const appid = 'your app id'
const secret = 'your app secret'

exports.main = async (event, context) => {
	const url = `https://api.weixin.qq.com/sns/jscode2session?appid=${appid}&secret=${secret}&js_code=${event.code}&grant_type=authorization_code`
	const { data } = await uniCloud.httpclient.request(url)
	return data
};

arrayBufferToString

上一个API返回的数据是以buffer的形式传回的,所以需要把数据转换成对象去保存。这个函数是把获得的数据转变成string。

export function arrayBufferToString(buffer: ArrayBuffer): string {
  const view = new Uint8Array(buffer);
  let str = '';
  for (let i = 0; i < view.length; i++) {
    str += String.fromCharCode(view[i]);
  }
  return str;
}

业务流程

  uni.login({
    provider: 'weixin',
    success: async (res) => {
      // get session_key
      const { result } = await database.callFunction({
        name: 'getSessionKey',
        data: {
          code: res.code
        }
      })

      // transform buffer to json
      const data = arrayBufferToString(result.data)
      const { openid, session_key } = JSON.parse(data)

      // save openid and session_key
      // ...
    }
  })

额外操作

不满足只有openId的小程序就需要使用以下的方法继续获取用户的信息。实现方式是用户主动去填写的。

头像选择

需要将 button 组件 open-type 的值设置为 chooseAvatar,当用户选择需要使用的头像之后,可以通过 bindchooseavatar 事件回调获取到头像信息的临时路径。文档链接

getAuthorization方法是promise版的判断用户照相簿权限的函数,具体实现如下:

async function getAuthorization() {
    return new Promise((resolve, reject) => {
        uni.getSetting({
            success(res) {
                if (!res.authSetting[`scope.writePhotosAlbum`]) {
		    	// user have writePhotosAlbum scope
                    uni.authorize({
		    	// let user to authorize this scope
                        scope: `scope.writePhotosAlbum`,
                        success(e) {
                            resolve(true);
                        },
                        fail() {
                            reject(false);
                        }
                    });
                } else {
                    resolve(true);
                }
            },
            fail() {
                reject(false);
            }
        });
    });
}

头像云端保存

uploadFile云函数是把用户头像保存在云端用户数据库中,注意的是当使用fileSystemManager.readFileSync返回的是数据是buffer形式,需要转换后才能传入云函数,这里把数据指定为base64的格式后上传。然后使用unicloud.uploadFile来上传到云端。这里还要注意的一点就是这个函数需要的fileContent的类型是Buffer,就是需要再把base64的数据再转回来。

<template>
        <button class="avatar-wrapper" open-type="chooseAvatar" @chooseavatar="onChooseAvatar">
            <image class="avatar" :src="avatarUrl"></image>
        </button>
<template>

<script lang="ts" setup>
const onChooseAvatar = async (e: any) => {
    const isauth = await getAuthorization()
    if (isauth) {
        const fileSystemManager = uni.getFileSystemManager()
        const fileContent = fileSystemManager.readFileSync(e.target.avatarUrl, 'base64')  
        // save avatar to database
        const { result } = await database.callFunction({
            name: 'uploadFile',
            data: {
                fileName: 'avatar',
                fileContent: fileContent,
                type: e.type
            }
        })
        console.log(result)
	// ...
    }
    else {
        // ...
    }
}
<script>
// uploadFile
'use strict';

exports.main = async (event, context) => {
	// base64 to buffer 
	const fileData = Buffer.from(event.fileContent, 'base64')
	try {
		const res = await uniCloud.uploadFile({
			fileContent: fileData,
			cloudPath: event.fileName + '.jpg'
		});
		return {
			success: true,
			data: res,
			errorMsg: ''
		}
	} catch (error) {
		return {
			success: false,
			data: fileData,
			errorMsg: error
		}
	}
};

昵称保存

这里获取昵称的方法没什么特别的,就是用个<input>组件让用户输入,然后和之前的头像一起上传处理就行了。

总结

随着时代的进步,用户数据变得越来越重要,相信微信的这次改动也是由于信息的滥用不得已而为之的,数据安全是开发者不得不考虑的问题,作为开发者自身必须要确保数据安全的前提下,同时要具备有对数据使用的道德准则。

0
博主关闭了所有页面的评论