uniapp + vue3微信小程序开发(3)微信授权登录

整体思路:

接口获取openId => 用户微信信息入库 => 手机号授权入库

逻辑详解:

我们知道小程序都是需要openId的,那我们可以通过前端获取,也可以通过后端接口获取,

前端就是这个地址,appid和secret 在你微信公众平台下都可以找到, code,在你调用uni.login就可以获取,但是切记,code码只能使用一次,你在开发环境时可以使用下面链接来前端获取openId,但是在线上生产环境,就要切换成后端接口获取了,因为会被小程序服务器域名所限制。

https://api.weixin.qq.com/sns/jscode2session?appid=' +
						appid + '&secret=' + secret + '&js_code=' + code +
						'&grant_type=authorization_code

获取到openId的目的,就是判断你数据库里是否有该用户,在小程序里,openId就是唯一主键的意思,然后下一步就是获取你的微信昵称和头像,那么这个要调用

uni.getUserProfile()

大家一定要用这个api来获取微信信息,否则其他获取的是假的用户信息 !

获取手机号授权,这个必须要求你在微信公众平台申请哦,否则是没有这个权限的,另外大家可能有疑问,微信信息授权和手机号授权为啥不写在一起? 因为手机号授权只能通过button按钮,并且使用open-type来获取,这一点,uniapp和微信原生是一致的,而且这个获取手机号的按钮,必须用户主动去点击喔,所以这也是我为啥将他写在遮盖层上了。

 <button  type="primary"  open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">绑定手机号</button>

手机号和微信用户信息这样都拿到了,那你就可以完成自己想要的操作了,那么又有同学想问,那我想获取身份证信息咋办? 那我明确告诉你,取不到!那有没有类似的呢,可以通过百度ocr识别来将前端传上去的身份证照片进行验证识别,这一点,我下一篇博客将会写上去 。

部分截图:

点击授权登录,将会弹出微信用户信息授权,然后会出现获取手机号按钮的遮盖层,点击获取手机号授权

所有代码:

这里简单说一下, proxy.$api.user.xxx, 这是我调用接口的方式,大家可以根据自己想要方式来实现uni.request,这一点没有啥强制性要求

<template>
	<view>
		<view>
			<view>
				<view class="header">
					<image src="/static/img/login-wx.png"></image>
				</view>
				<view class="content">
					<view>申请获取以下权限</view>
					<text>获得你的公开信息(昵称,头像、地区等)</text>
				</view>
				<button class="bottom" type="primary" :disabled="userInfoDisabled" @click="wxGetUserInfo">授权登录</button>
			</view>
		</view>
		<van-overlay :show="overlayShow">
		  <view class="login-wrapper">
			  <view class="login-bottom">
					 <button  type="primary"  open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">绑定手机号</button>
			  </view>
		  </view>
		</van-overlay>
	</view>
</template>

<script setup>
	import {
		ref,
		reactive,
		getCurrentInstance
	} from 'vue'
	import {
		onLoad
	} from '@dcloudio/uni-app'

	const {
		proxy
	} = getCurrentInstance()
	const appid = "xxx"
	const secret = "xxx"
	const userInfoDisabled = ref(false)
	const userInfo = reactive({
		thirdAppType: 1,
		thirdUserId: "",
		nickName: '',
		wechatPicture: ''
	})
	const sessionKey = ref('') // session码
	const pageOption = ref()
	const overlayShow = ref(false)
	const wxGetUserInfo = () => {
		if (uni.getUserProfile) {
			uni.getUserProfile({
				desc: 'Wexin', // 这个参数是必须的
				success: result => {
					uni.showLoading({
						title: '授权中...'
					});
					userInfoDisabled.value = true
					userInfo.nickName = result.userInfo.nickName
					userInfo.wechatPicture = result.userInfo.avatarUrl
					proxy.$api.user.login({
						thirdAppType: userInfo.thirdAppType,
						thirdUserId: userInfo.thirdUserId,
						nickName: userInfo.nickName,
						wechatPicture: userInfo.wechatPicture
					}).then(res => {
						userInfoDisabled.value = false
						uni.hideLoading();
						if (res.data.bindSpecialCode == 203) {
							uni.setStorageSync('id', res.data.id);
							uni.setStorageSync('nickName', res.data.nickName);
							uni.setStorageSync('wechatPicture', res.data.wechatPicture);
							overlayShow.value = true
							return
						} else {
							uni.showToast({
								title: '登录成功'
							})
							uni.setStorageSync('id', res.data.id);
							uni.setStorageSync('nickName', res.data.nickName);
							uni.setStorageSync('wechatPicture', res.data.wechatPicture);
							uni.setStorageSync('tel', res.data.tel.data);
							// 然后跳回原页面
							if (pageOption.value.backtype == 1) {
								uni.redirectTo({
									url: '/pages/home/index'
								})
							} else {
								uni.switchTab({
									url: '/pages/home/index'
								})
							}
						}
					}).catch(e => {
						userInfoDisabled.value = false
						uni.hideLoading();
						uni.showToast({
							title: '用户信息操作失败',
							icon: 'none'
						});
					})
				},
				fail: res => {
					console.log('用户拒绝授权信息');
				}
			})
		} else {
			uni.showToast({
				title: '获取用户信息失败',
				icon: 'none'
			});
		}
	}

	const login = () => {
		uni.showLoading({
			title: '登录中...'
		});
		uni.login({
			provider: 'weixin',
			success: loginRes => {
				let code = loginRes.code;
				proxy.$api.user.getOpenId({
					appid,
					secret,
					code
				}).then(res => {
					if (res.code == 200) {
						getOpenId(res.data)
					}
				}).catch(e => {
					uni.hideLoading();
					uni.showToast({
						title: '获取 OpenId 失败',
						icon: 'none'
					});
					userInfoDisabled.value = false
				})
			},
			fail: () => {
				uni.hideLoading();
				uni.showToast({
					title: '获取 code 失败',
					icon: 'none'
				});
				userInfoDisabled.value = false
				return false;
			}
		});
		return false;
	}
	const getOpenId = (codeRes) => {
		let openId = codeRes.openid;
		sessionKey.value = codeRes.sessionKey;
		userInfo.thirdUserId = openId	
		proxy.$api.user.openIdParse({
			thirdAppType: userInfo.thirdAppType,
			thirdUserId: openId
		}).then(res => {
			uni.hideLoading();
			uni.setStorageSync('openId', openId);
			userInfoDisabled.value = false
			// 用户信息未授权入库
			if (res.data.bindSpecialCode == 202) {
				uni.showToast({
					title: '请点击授权登录',
					icon: 'none'
				});
			// 用户手机号未授权入库
			} else if (res.data.bindSpecialCode == 203) {
				overlayShow.value = true
				uni.setStorageSync('id', res.data.id);
				uni.setStorageSync('nickName', res.data.nickName);
				uni.setStorageSync('wechatPicture', res.data.wechatPicture);
			} else {
				uni.showToast({
					title: '登录成功'
				})
				uni.setStorageSync('id', res.data.id);
				uni.setStorageSync('nickName', res.data.nickName);
				uni.setStorageSync('wechatPicture', res.data.wechatPicture);
				uni.setStorageSync('tel', res.data.tel.data);
				if (pageOption.value.backtype == 1) {
					uni.redirectTo({
						url: '/pages/home/index'
					})
				} else {
					uni.switchTab({
						url: '/pages/home/index'
					})
				}
			}
		}).catch(e => {
			uni.hideLoading();
			uni.showToast({
				title: '获取授权信息失败',
				icon: 'none'
			});
			userInfoDisabled.value = false
		})
	}
	/**
	 * 手机号授权
	 */
	const getPhoneNumber = (e) => {
	    if (e.detail.errMsg == 'getPhoneNumber:fail user deny') {
	        console.log('用户拒绝提供手机号');
	    } else {
	        let encryptedData = e.detail.encryptedData
	        let iv = e.detail.iv
			overlayShow.value = false
			if (encryptedData && iv) {
				bindTelApi(encryptedData, iv)
			}
	    }
	}
	const bindTelApi = (encryptedData, iv) => {
		uni.showLoading({
			title: '绑定手机号中...'
		});
		proxy.$api.user.bindTel({
			 encryptedData: encryptedData,
			 iv: iv,
			 sessionKey: sessionKey.value,
			 uid: uni.getStorageSync('id')
		}).then(res => {
			uni.hideLoading()
			if (res.code == 200) {
				uni.setStorageSync('tel', res.data.tel.data);
				uni.switchTab({
					url: '/pages/home/index'
				})
			}
		}).catch(e => {
			uni.hideLoading()
		})
	}
	onLoad((options) => {
		pageOption.value = options
		const {
			proxy
		} = getCurrentInstance()
		const loginStatus = proxy.checkLogin('/pages/home/index', 2)
		if (!loginStatus) {
			userInfoDisabled.value = true
			login();
		} else {
			uni.switchTab({
				url: '/pages/home/index'
			})
		}
	})
</script>
<style lang="scss" scoped>
	.header {
		margin: 160rpx 0 60rpx 50rpx;
		text-align: center;
		width: 650rpx;

		image {
			width: 180rpx;
			height: 180rpx;
		}
	}

	.content {
		margin-bottom: 68rpx;
		text-align: center;

		text {
			display: block;
			color: #9d9d9d;
			margin-top: 20rpx;
		}
	}

	.bottom {
		border-radius: 80rpx;
		margin: 70rpx 50rpx;
		font-size: 35rpx;
	}
	.login-wrapper{
		height: 100%;
		position: relative;
		.login-bottom{
			position: absolute;
			bottom: 0;
			left: 0;
			width: 100%;
			height: 133rpx;
			background-color: #fff;
			button{
				position: absolute;
				top: 50%;
				left: 50%;
				background-color: #CA2915;
				transform: translate(-50%, -50%);
				border-radius: 30px;
				width: 435rpx;
				height: 68rpx;
				line-height: 68rpx;
			}
		}
	}
</style>

  • 4
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值