> 技术文档 > HBuilderX(uniapp)实现微信小程序获取用户头像、昵称、授权登录、获取用户手机号_uniapp获取微信头像和昵称

HBuilderX(uniapp)实现微信小程序获取用户头像、昵称、授权登录、获取用户手机号_uniapp获取微信头像和昵称

前言:微信文档写的零零散散的,网上搜的教程,23年的教程还在教22年改版之前的东西,导致踩坑无数,所以自己写一下文档记录一下,帮助后来者,记录于2024.11.14

一.获取用户头像和昵称

首先阅读微信小程序官方文档,wx.getUserInfo接口开放接口 / 用户信息 / wx.getUserInfo (qq.com)

发现自2022年之后,开发的版本逐渐对用户信息接口更改,wx.getUserInfo接口已经基本弃用,之前老版本还能够使用,但是新版小程序调用此接口只能获取到一堆默认信息如下

​​​​​​
​   小程序登录、用户信息相关接口调整说明 | 微信开放社区 (qq.com)

所以要实现获取用户头像,不能像之前一样一键获取了,有的文档说会调起一个授权弹窗,然后用户手动授权之后就可以获取,亲测这个方法已经过时,即下图这个方法并不会弹出个人信息确认弹窗

目前唯一可行的方法就是:头像昵称填写能力

开放能力 / 用户信息 / 获取头像昵称 (qq.com)

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

需要将 input 组件 type 的值设置为 nickname,当用户在此input进行输入时,键盘上方会展示微信昵称。

其中有两个需要注意的点:

1.选择的微信头像是暂存到本地的路径,随时可能会失效,或者出现307重定向等一系列bug,所以要把头像上传的自己本地的服务器,或者本地的接口保存,就是把onChooseAvatar方法修改成如下

onChooseAvatar: function(e) {const {avatarUrl} = e.detaillet _this = thiswx.uploadFile({url: \'\', // 你自己本地上传图片的 完整 路径filePath: avatarUrl,name: \'file\', // 文件对应的 key,开发者在服务端可以通过这个 key 获取文件的二进制内容success(res) {console.log(\"data===>\",res.data)_this.setData({avatarUrl:\'\' // 你自己的完整图片路径})}})},

2.微信昵称选择的时候,输入框有值,并且绑定了v-model,并不会被监听到,即使修改了,值也还是空的,必须要用户手动再修改才会被v-model发现修改,这是一个bug吧,所以要手动用watch监听一下输入框绑定的值

获取头像昵称示例代码如下:

 const defaultAvatarUrl = \'https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQP6yfMxBgJ0F3YRqJCJ1aPAK2dQagdusBZg/0\'export default{ data(){ avatarUrl: defaultAvatarUrl, // 可以自行修改 }, methods:{ }} onChooseAvatar(e) { // 将这个方法修改为上面那个,注意变量名更改 const { avatarUrl } = e.detail this.setData({ avatarUrl, }) }})

二.微信授权登录

主要用到的接口就是wx.login接口,其功能如下:

调用接口获取登录凭证(code)。通过凭证进而换取用户登录态信息,包括用户在当前小程序的唯一标识(openid)、微信开放平台账号下的唯一标识(unionid,若当前小程序已绑定到微信开放平台账号)及本次登录的会话密钥(session_key)等。用户数据的加解密通讯需要依赖会话密钥完成。

很抽象,通俗来讲,就是调用wx.login接口,微信会给你返回一个code,通过这个code传给后端,后端会通过系列操作(这个系列操作后面会讲)返回给你一个openid,unionid和session_key,作用我都会一一介绍。然后上文说的解密通讯是交给后端完成的。

openid作用是用户在本小程序的唯一作用标识。

unionid是多个小程序之间,同一用户,不用重新授权即可直接登录的标识,此unionid需要注册微信开放平台认证才可获得,如果只是开发一个小程序则不需要这个id。

session_key:五分钟一次刷新,用来判断登录是否过期。

首先我们来阅读官方文档开放接口 / 登录 / wx.login (qq.com)

下图是从别的博客借鉴来的,三列,第一列是前端要做的,第二列是后端要做的

首先,在登录界面的onLoad函数中调用wx.login

onLoad: function(options) {let that = this;wx.login({success: res => {that.code = res.code}})},

把这个code保存下来。然后通过自己的wxLogin把这个code传给后端,后端阅读这个文档

小程序登录 / 小程序登录 (qq.com)

调用微信的服务

GET https://api.weixin.qq.com/sns/jscode2session

后端直接配置下面四个参数然后调用

appid和secret在微信小程序的平台内可以查看到,js_code就是前端传入的code,下一个参数直接填写authorization_code即可、然后微信服务器会返回openid等参数,然后把这个openid返回给前端,同时在这个login接口里面注册用户保存到数据库,把userId和openid一起返回给前端,到此登录流程就结束了。

三.获取用户手机号

阅读官方文档开放能力 / 用户信息 / 手机号快速验证组件 (qq.com)

注意,现在手机号快速验证需要收费了,如果你是个人appid,则需要完成微信小程序认证,300一年,如果不想认证还想用这个功能,就要用测试号,把appid和secret都换成测试号的。

而且现在这个获取用户手机号,不用wx.login也可以登录

使用方法

步骤1:需要将 button 组件 open-type 的值设置为 getPhoneNumber,当用户点击并同意之后,通过 bindgetphonenumber 事件获取回调信息;

步骤2:将 bindgetphonenumber 事件回调中的动态令牌code传到开发者后台,并在开发者后台调用微信后台提供的 phonenumber.getPhoneNumber 接口,消费code来换取用户手机号。每个code有效期为5分钟,且只能消费一次。

注:getPhoneNumber 返回的 code 与 wx.login 返回的 code 作用是不一样的,不能混用。这句话很重要!!在和授权登录一起写的时候很容易弄混。

我是直接全都在前端调用了,效果如下

!!!今天上线体验版的时候发现,https://api.weixin.qq.com这个域名不能配置为合法域名,微信直接把这个禁用了,即这一段代码全都必须只能放在后端运行,即后端写一个接口,接受code参数,然后把下面代码中的e.detail.code这个参数传给后端,下面的一系列post微信服务的接口都由后端来完成,直接返回电话号码即可、

文档:获取手机号 | 微信开放文档

后端操作:
先调用https://api.weixin.qq.com/cgi-bin/stable_token,post方法,传参grant_type: \'client_credential\', appid: config.appid, secret: config.secret

获取到token,这个token是获取手机号的token,不是登录的token

然后调用url: `https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=` + token,post方法,传参code,返回的数据就是包含手机号的数据
 

getPhoneNumber(e) {console.log(\"e=>\", e) // 这里会返回encryptedData和iv,用来加密和解密if (e.detail.errMsg === \'getPhoneNumber:ok\') {// this.encryptedData = e.detail.encryptedData// this.iv = e.detail.ivconst code = e.detail.code;let promise = new Promise((resolve, reject)=> { var params = { url: \'/login\', data: { principal: this.code, }, callBack: res => { http.loginSuccess(res) // 这是我自己外部文件保存登录token等信息 } } http.request(params) resolve();});promise.then((res)=>{uni.request({url: `https://api.weixin.qq.com/cgi-bin/stable_token`,method: \"POST\",data: {grant_type: \'client_credential\',appid: config.appid,secret: config.secret},success: res => { // 此token和code不是login的token和code,这一步可以放到后端写this.getPhone(res.data.access_token, code);},fail: err => {console.error(\"调用失败=>\", err);}});})} else {console.error(\'用户未授权手机号\');uni.showToast({title: \'用户未授权手机号\',icon: \'none\'});}}, getPhone(token, code) {// 获取手机号uni.request({url: `https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=` + token,method: \"POST\",data: {code: code},success: res => {console.log(\"获取到的用户手机号全部信息:\", res);// 获取到手机号this.phoneNumber = res.data.phone_info.purePhoneNumber;console.log(\"流程结束!!\")},fail: err => {console.error(\"获取手机号失败\", err);uni.showToast({title: \'获取手机号失败\',icon: \'none\'});}});},

手动删减的,有的地方花括号可能会有报错,请见谅,但大体流程就是上面那样,最后res.data.phone_info.purePhoneNumber就是最终的用户手机号。

获取手机号和微信授权登录可以写到同一个按钮里面,具体逻辑可以自己操作