最新!最全!2023.6 uniapp实现微信登录,获取手机号,头像等方法

5,830 阅读4分钟

都知道之前的之前的获取用户信息的方法都获取不到真实的数据了 头像也是通用的灰色头像

提示:企业小程序才能获取到用户信息,个人的不行的哦

执行下面步骤之前,一定得先去吧微信小程序 微信认证 成功才能成功执行下面步骤 ,否则的话只能获取到微信临时头像

进入微信小程序首页 》 设置 》 基本信息填写完 》 通过之后点击基本设置里面有个微信认证

微信认证.png

最后会有完整代码展示

首先

首先要去先执行 uni.login 方法,可以在onloadonshow 里面执行,避免后续发生报错,在这里首先储存好后续所需的 code,这里的code 可以获取用户唯一标识openid以及会话密钥sessionkey用于解密获取手机的加密信息

uni.login({
        provider: 'weixin',
        success: res => {
                console.log(res)
                this.login_code = res.code // 获得的code
        }

});

以下操作最好交于后端操作,前端在开发阶段获取没问题,部署上去之后会报错,最后的全部代码里面我不会展示下面的代码操作

获取秘钥

通过 调用 https://api.weixin.qq.com/sns/jscode2session 微信接口获取到用户的信息,主要是要拿到openid 用户唯一标识session_key 秘钥,后续解密手机号和登录需要用到

// let that = this
	uni.request({
		url: 'https://api.weixin.qq.com/sns/jscode2session',// 请求微信服务器
                method:'GET',
		data: {
			appid: 'aaaaaaaaaaa' //你的小程序的APPID 
			secret: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', //你的小程序秘钥secret
			js_code: this.login_code,    //wx.login 登录成功后的code
			grant_type:'authorization_code'  // 固定写死的,不用变
		,
		success: (res) => {
			// console.log('获取信息',res);  // 换取成功后 暂存这些数据 留作后续操作
			this.openid=res.data.openid    //openid 用户唯一标识
			this.session_key=res.data.session_key    //session_key  会话密钥
                        
                  // 这个请求时后端接口,联系后端储存信息用的,显然存不了什么信息,保存上面的信息就行,然后接受储存返回的token
			this.$request({url:'/aa/aaaa/aaaaaaaaa',method:'post',data:{openid:this.openid,url:this.imgurl}}).then(res=>{
				// 存储token
				uni.setStorageSync('ACCESS_TOKEN',res.data.data.token)
				this.form =res.data.data.user
				that.$set(that,'form',res.data.data.user)
				console.log(that.form,111,this.form)
			})
		}
	});

获取手机号

利用getPhoneNumber方法获取手机号,通过 button 标签来实现,然后在methods方法里面来获取到数据,接受的参数是一个对象,对象里面的 detail 值就是后续解密之后的获取手机号的值,这里获取到的信息是最后必须得通过解密才能获取到的

<button type="warn" open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">授权登录</button>
getPhoneNumber(e){
    // 如果点击授权进行下一步
    if(e.detail.errMsg === 'getPhoneNumber:ok'){
            this.getloginPhone = e.detail  // 解密手机号所需的信息
            this.show = true
    }
}

手机号解密方法

下载引入解密文件地址 developers.weixin.qq.com/miniprogram…

微信解密手机号.png 使用uniapp的话 那就下载node 即可 使用里面的 WXBizDataCrypt.js 文件即可
使用方法,把文件粘贴到项目文件中,引入使用即可

import WXBizDataCrypt from "@/utils/WXBizDataCrypt.js";  // 引入文件
let pc = new WXBizDataCrypt('aaaaaaaaaaaaa',session_key) // 执行解密操作,参数是,小程序appid和上面获取到的session_key秘钥
let data = pc.decryptData(this.getloginPhone.encryptedData,this.getloginPhone.iv) // 这里面所需的参数就是上面获取到的了,照填就可以

就此 data.phoneNumber 就是用户的手机号了

获取头像

这步就是通过 chooseAvatar 方法获取到用户头像信息,同时也可以选取相册照片当头像,一切看用户选择进行,同样也是通过button来进行的操作,方法参数是一个对象 里面的.detail.avatarUrl就是微信头像的临时地址,这时候可以通过uni.uploadFile方法储存到服务器上,因为这个临时地址只能在微信小程序里面打开在别的地方看不了,上传服务器代码最后完整代码里有展示,上传图片之前一定要在小程序上配置上传域名哦

<button type="warn" open-type="chooseAvatar" @chooseavatar="onChooseAvatar">授权头像</button>
onChooseAvatar(e) {
        this.showing = true
        let that = this
        that.imgurl = e.detail.avatarUrl
}

获取用户昵称

这个方法其实就是弄个输入框,然后typename 填写 nickname 就行
还有一点就是选择微信昵称的时候会出现不自动赋值的情况,这个时候可以使用 change 方法获取到变化的值,然后赋值上去即可

<input class="nicknamestyle" @change="inputBlur" v-model="natkName" type="nickname" placeholder="请输入昵称,不填则随机" name="nickname" />
//change事件方法
inputBlur(e){
        this.natkName = e.detail.value
},

登录 把数据传给后端进行储存,并且接收返回的token存储下来用于后续请求操作

其实这一步骤在第一步的时候 获取秘钥的时候就有了,就是调接口然后返回token等用户数据,不过我的是自己的步骤进行的代码

let that = this
// 让后端处理,让后端向微信官方接口发送请求获取到用户数据,然后返回给我们
this.$request({url:'/aa/aaaaa/aaaaaaaaa',method:'post',data{js_code:this.login_code}}).then(res=>{
	// 解密电话号码
	let pc = new WXBizDataCrypt('aaaaaaaaaaaaaaaaaa',ress.data.data.session_key)
	let data = pc.decryptData(this.getloginPhone.encryptedData,this.getloginPhone.iv)
        //登录
		this.$request({url:'/aa/aaaa/aaaaaaaaa',method:'post',data:openid:ress.data.data.openid,url:this.imgurl,phone:data.phoneNumber}}).then(res=>{
				// 存储token和用户信息
				uni.setStorageSync('ACCESS_TOKEN',res.data.data.token)
                         uni.setStorageSync('ACCESS_userInfo',JSON.stringify(res.data.data.user))
						
                            uni.showToast({
                                    title:'登录成功',
                                    icon:'none',
                                    duration:1000
                            })
                            // 返回进来的地方
                            setTimeout(()=>{
                                    uni.navigateBack()
                            },1000)

                            }).catch((rej)=>{
                            uni.showToast({
                                    title:'获取信息失败,请重试',
                                    icon:'none',
                                    duration:1000
                            })
            })
                    }).catch((rej)=>{
                            uni.showToast({
                                    title:'获取信息失败,请重试',
                                    icon:'none',
                                    duration:1000
                            })
                    })

就此就结束了登录操作了

完整代码

<template>
	<view>
		<view class="box">
			<view class="box-item">
				<p class="item-title">授权</p>
				<p class="item-p">授权信息同步订单和会员优惠</p>
				
				<!-- <button :disabled="showing" class="btnstyle" style="width: 80%;border-radius: 40rpx;margin-top: 20rpx;" type="warn" open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">授权登录</button>
				<button class="btnstyle" style="width: 80%;border-radius: 40rpx;margin-top: 20rpx;" @click="backIndex">返回首页</button> -->
			</view>
			<view class="infobox">
				<view class="infoitem">
					<view class="item-info">
						<p class="info-p">昵称:</p>
						<input class="nicknamestyle" @change="inputBlur" v-model="natkName" type="nickname" placeholder="请输入昵称,不填则随机" name="nickname" />
					</view>
					<view class="item-info">
						<p class="info-p">头像:</p>
						<img style="width: 80rpx;height: 80rpx;border-radius: 50%;" :src="imgurl || morenimg" alt="">
						<button class="btnstyle" style="width: 180rpx;border-radius: 40rpx;height: 60rpx;font-size: 28rpx;margin: 0;"  type="warn" open-type="chooseAvatar" @chooseavatar="onChooseAvatar">授权头像</button>
					</view>
					<!-- <view class="item-info">
						<p class="info-p">手机号:</p>
						<button class="btnstyle" style="width: 220rpx;border-radius: 40rpx;height: 60rpx;font-size: 28rpx;margin: 0;" type="warn" open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">授权手机号</button>
					</view> -->
				</view>
			</view>
			<button :disabled="showing" class="btnstyle" style="width: 80%;border-radius: 40rpx;margin-top: 20rpx;" type="warn" open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">授权登录</button>
			<button class="btnstyle" style="width: 80%;border-radius: 40rpx;margin-top: 20rpx;" @click="backIndex">返回首页</button>
		</view>
		<!-- <u-popup :show="show" mode="center">
			<view style="background-color: rgba(127, 127, 127,0);">
				<input class="nicknamestyle" type="nickname" placeholder="请输入昵称" name="nickname" />
				<button class="btnstyle" style="width: 600rpx;border-radius: 40rpx;"  type="warn" open-type="chooseAvatar" @chooseavatar="onChooseAvatar">授权头像</button>
			</view>
		</u-popup> -->
		<!-- 加载动画 -->
		<u-loading-icon :show="showing"></u-loading-icon>
	</view>
</template>

<script>
	import WXBizDataCrypt from "@/utils/WXBizDataCrypt.js";
	export default {
		data() {
			return {
				getloginPhone:{}, // 登录手机号信息
				login_code:null, //登录code
				show:false, //微信头像授权弹窗
				imgurl:null, // 头像地址
				showing:false,
				loginIng:false,// 登录状态
				natkName:'',
				morenimg:'https://jockers.oss-cn-beijing.aliyuncs.com/20230618/6f29d9cf438c496f8c130df0f83ecaa2.png'
			};
		},
		onLoad() {
			this.$store.commit('changeStopReuse',false)
			this.login()
		},
		methods:{
			getPhoneNumber(e){
				// 如果点击授权进行下一步
				if(e.detail.errMsg === 'getPhoneNumber:ok'){
					if(!this.imgurl) return this.$showToast('请先获取头像')
					this.getloginPhone = e.detail
					this.showing = true
					this.get_miyao()
				}
			},
			inputBlur(e){
				this.natkName = e.detail.value
			},
			onChooseAvatar(e) {
				// this.showing = true
				let that = this
				// that.imgurl = e.detail.avatarUrl
				// 获取图片信息
				uni.getImageInfo({
					src:e.detail.avatarUrl,
					success(ress) {
						//  存储头像
						uni.uploadFile({
							url:that.$store.state.imgUploadUrl+'/pc/file/upload',
							filePath:ress.path,
							name:'multipartFile',
							header:{
								'Authorization':uni.getStorageSync('ACCESS_TOKEN') ? 'Bearer '+ uni.getStorageSync('ACCESS_TOKEN'):'',
							},
							success(res) {
								if(res.errMsg  ==='uploadFile:ok'){
									let img = JSON.parse(res.data).data
									that.imgurl = img
									// 清除token和用户信息
									uni.clearStorageSync('ACCESS_TOKEN')
									uni.clearStorageSync('ACCESS_userInfo')
									uni.setStorageSync('ACCESS_userimg',that.imgurl)
									return
								}
							},
							fail(rej) {
								// 如果报错也要执行
								that.imgurl = e.detail.avatarUrl
								// 清除token和用户信息
								uni.clearStorageSync('ACCESS_TOKEN')
								uni.clearStorageSync('ACCESS_userInfo')
								uni.setStorageSync('ACCESS_userimg',e.detail.avatarUrl)
							}
						})
					}
				})
			},
			login(){
				uni.login({
					provider: 'weixin',
					success: res => {
						this.login_code = res.code // 获得的code
					}
					
				});
				
			},
			get_miyao(){ // 获取密钥 === 需要登录才可以获取密钥
				
				let that = this
				this.$request({url:'/aa/aaaa/aaaaaa',method:'post',data:{js_code:this.login_code}}).then(ress=>{
					// 解密电话号码
					let pc = new WXBizDataCrypt('aaaaaaaaaaaaa',ress.data.data.session_key)
					let data = pc.decryptData(this.getloginPhone.encryptedData,this.getloginPhone.iv)
					this.$request({url:'/aaaa/aaa/aaaaaa',method:'post',data:{openid:ress.data.data.openid,url:this.imgurl,phone:data.phoneNumber,nickName:this.natkName}}).then(res=>{
						// 存储token
						uni.setStorageSync('ACCESS_TOKEN',res.data.data.token)
						uni.setStorageSync('ACCESS_userInfo',JSON.stringify(res.data.data.user))
						that.$store.commit('addUserInfo',res.data.data.user)
						uni.showToast({
							title:'登录成功',
							icon:'none',
							duration:1000
						})
						// 返回进来的地方
						setTimeout(()=>{
							uni.navigateBack()
						},1000)
						
					}).catch((rej)=>{
						uni.showToast({
							title:'获取信息失败,请重试',
							icon:'none',
							duration:1000
						})
						this.showing = false
					})
				}).catch((rej)=>{
					uni.showToast({
						title:'获取信息失败,请重试',
						icon:'none',
						duration:1000
					})
					this.showing = false
				})
			},
			backIndex(){
				uni.switchTab({
					url:'/pages/index/index'
				})
			}
		}
	}
</script>

<style lang="scss" scoped>
/deep/ .u-popup__content{
	background-color:rgba(127, 127, 127,0) !important;
}
.box{
	.box-item{
		margin-top: 40rpx;
		text-align: center;
		height: auto;
		.item-title{
			font-size: 36rpx;
			font-weight: 800;
		}
		.item-p{
			font-size: 36rpx;
			color: #ababab;
		}
		
	}
	.infobox{
		display: flex;
		justify-content: center;
		padding: 40rpx;
		.infoitem{
			width: 600rpx;
			.item-info{
				display: flex;
				align-items: center;
				justify-content: space-between;
				padding: 10rpx 0;
				.info-p{
					font-size: 28rpx;
					font-weight: 700;
				}
				.nicknamestyle{
					background-color: white;
					border: 1px solid #ccc;
					border-radius: 40rpx;
					flex: 1;
					text-align: center;
					margin: 0 10rpx;
				}
			}
		}
	}
	
	.btnstyle{
		height: 85rpx;
		display: flex;
		justify-content: center;
		align-items: center;
	}
}
</style>