uniapp登录授权获取微信手机号组件封装

最近在公司写项目,刚好有需求要写小程序登录和授权手机号,封装成了一个组件,这里给大家总结一下,话不多说,上代码

1、样式基本结构,你们可以自己写需要的样式,我这个仅供参考,这里因为授权头像昵称等信息和手机号是两个弹出框,所以我这边也是写了两个,css代码我就不上了,先弹授权头像框,授权完成登录后才会弹授权手机号框

<view>
		<view class='Popup' v-if='isShowAuth'>
			<view class="logo-auth">
				 <image :src='logoUrl' mode="aspectFit"></image>
			</view>
		   <view class='title'>授权提醒</view>
		   <view class='tip'>请授权头像等信息,以便为您提供更好的服务</view>
		   <view class='bottom flex'>
		      <view class='item' @click='close'>随便逛逛</view>
			  <!-- #ifdef APP-PLUS -->
			  <button class='item grant' @click="setUserInfo">去授权</button>
			  <!-- #endif -->
			  <!-- #ifdef MP -->
			  <button class='item grant'  type="primary" open-type="getUserInfo" lang="zh_CN" @getuserinfo="setUserInfo">去授权</button>
			  <!-- #endif -->
		   </view>
		</view>
		<view class='mask' v-if='isShowAuth' @click='close'></view>

		<view class='Popup' v-if='loginShow'>
			<view class="logo-auth">
				 <image :src='logoUrl' mode="aspectFit"></image>
			</view>
		   <view class='title'>授权提醒</view>
		   <view class='tip'>请授权您的手机号码,以便为您提供更好的服务</view>
		   <view class='bottom flex'>
			  <view class='item' @click='closePhone'>暂不授权</view>
			  <!-- #ifdef MP -->
			  <button class='item grant' type='primary' open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">授权手机号</button>
			  <!-- #endif -->
		   </view>
		</view>
		<view class='mask' v-if='loginShow' @click='closePhone'></view>
	</view>

效果是下面这样的,隐私地方我就打码了
uniapp登录授权获取微信手机号组件封装_第1张图片
uniapp登录授权获取微信手机号组件封装_第2张图片
uniapp登录授权获取微信手机号组件封装_第3张图片
uniapp登录授权获取微信手机号组件封装_第4张图片

下面来看怎么实现的

首先是要先授权页面登录,才能获取手机号,我这边是封装成了一个组件,因为好几个页面都要用到授权,获取手机号的时候,需要传给后端三个值,code encryptedData iv code是uni.login时获取到的,后面两个值是在用户点击授权手机号时点击了允许授权才能获取到的,前端可以用这个code去获取seeion和openId,但是不安全,在控制台就能看到,所以一般都是后端去解密,我这边是后端去解密手机号的,后端有接口,后端一般都有接口,把code传给后端就行了

<script>
	const app = getApp();
	import Cache from '../utils/cache';
	import { getLogo } from '../api/public';
	import { LOGO_URL } from '../config/cache';
  import {
    mapGetters
  } from "vuex";
	import Routine from '../libs/routine';  // 这是我用面向对象封装的一个获取登录等信息的js文件,代码附在下面了
	import { weCatBinding } from '../api/api.js';
	import { getUserAccount } from '../api/user.js';
	export default {
		name:'Authorize',
		props:{
			isAuto:{
				type:Boolean,
				default:true
			},
			isGoIndex:{
				type:Boolean,
				default:true
			},
			isShowAuth:{
				type:Boolean,
				default:false
			},
			LoginShow:{
				type:Boolean,
				default:false
			},
		},
		data(){
			return {
				logoUrl: app.globalData.routine_logo,
				phoneEncryptedData:'', // 必传
				phoneIv:'', // 必传
				code:'',  // 必传
				openid:'',
				session_key:'',
				unionid:'',
				loginShow:false
			}
		},
		computed:mapGetters(['isLogin','userInfo']),
		watch:{
			isLogin(n){
				n === true && this.$emit('onLoadFun',this.userInfo);
			}
		},
		created() {
			this.getLogoUrl();
			this.setAuthStatus();
			uni.$on('update', (data) => {
				this.logoUrl = data.login_logo
			})
		},
		mounted: function() {
			this.$nextTick(() => {
				this.logoUrl = app.globalData.login_logo
			});
		},
		methods: {
			setAuthStatus() {
				Routine.authorize().then(res => {
					if (res.islogin === false)
						this.setUserInfo();
					else
						this.$emit('onLoadFun', this.userInfo);
				}).catch(res => {
					if (this.isAuto)
						this.$emit('authColse', true);
				})
			},
			// 获取用户信息
			getUserInfo(code) {
				Routine.getUserInfo().then(res => {
					let userInfo = res.userInfo
					userInfo.code = code;
					console.log(this.$Cache.get("spread"))
					Routine.authUserInfo(userInfo).then(res => {
						uni.hideLoading();
						this.$emit('authColse',false);
						this.$emit('onLoadFun',this.userInfo);
						this.getUserPhone() // 判断是否已经绑定手机号
					}).catch(res=>{
						uni.hideLoading();
						uni.showToast({
							title:res.msg,
							icon:'none',
							duration:2000
						});
					})
				}).catch(res =>{
					uni.hideLoading();
				})
			},
			setUserInfo(){
				uni.showLoading({title:'正在登录中'});
				Routine.getCode().then(code=>{
					this.getUserInfo(code);
					this.$emit('authColse',false);
					this.code = code   // 这个code至关重要,是需要传给后端的,所以这里我们把他附上值,绑定手机号的时候后端一共接收三个值 code encryptedData iv
				}).catch(res=>{
					uni.hideLoading();
				})
			},
			setUserPhone() {
				this.loginShow = true // 判断是否授权登录标识  默认为false
			},
			// 获取用户是否绑定手机号
			getUserPhone(){
				getUserAccount().then(res => {
				  if (res.status == 200 && null == res.data.phone) {
					  this.loginShow = true; // 判断是否授权登录标识  默认为false
				  }
				}).catch(err => {
					console.log("获取用户是否绑定手机号---", err)
				})
			},
			// 绑定手机号,调用后端给的接口
			getPhoneNumber(e) {
				if(e.detail.errMsg=="getPhoneNumber:fail user deny"){       //用户拒绝授权
				  this.loginShow = false
				} else {      //允许授权
				  this.phoneEncryptedData = e.detail.encryptedData
				  this.phoneIv = e.detail.iv  // 这两个是传给后端的  用于解析手机号用的
				  let that = this
				  let data = {
					code:that.code,
					encryptedData:this.phoneEncryptedData,
					iv:this.phoneIv
				  }
				  weCatBinding(data).then((res) => {
					if (res.status == 200) {
					  this.loginShow = false
					}
					console.log('绑定手机号成功',res)
				  }).catch(err => {
					this.loginShow = false
					console.log('绑定手机号失败',err)
				  })
				}
			},
			// 这个是获取我的小程序的logo(这个你们自己写自己公司的)
			getLogoUrl(){
				this.logoUrl = app.globalData.routine_logo
			},
			// 授权手机号点击关闭按钮,弹框隐藏
			closePhone(){
				this.loginShow = false
			},
			// 授权信息点击关闭按钮,跳转到首页
			close(){
				let pages = getCurrentPages(), currPage  = pages[pages.length - 1];
				if(this.isGoIndex){
					uni.switchTab({url:'/pages/index/index'});
				} else {
					this.$emit('authColse',false);
				}
			},
		}
	}
</script>

封装的Routine 文件,routine.js

class Routine
{

	constructor()
	{
	    this.scopeUserInfo = 'scope.userInfo';
	}

	async getUserCode(){
		let isAuth = await this.isAuth(), code = '' ;
		if(isAuth)
			code = await this.getCode();
		return code;
	}

	/**
	 * 获取用户信息
	 */
	getUserInfo(){
		let  that = this , code = this.getUserCode();
		return new Promise( (resolve,reject) => {
			uni.getUserInfo({
				lang: 'zh_CN',
				success(user) {
					if(code) user.code = code;
					resolve({userInfo:user,islogin:false});
				},
				fail(res){
					reject(res);
				}
			})
		})
	}

	/**
	 * 获取用户信息
	 */
	authorize()
	{
		let that = this;
		return new Promise((resolve,reject)=>{
			if(checkLogin())
				return resolve({
					userInfo:Cache.get(USER_INFO,true),
					islogin:true,
				});
			uni.authorize({
			    scope: that.scopeUserInfo,
			    success() {
					resolve({islogin:false});
			    },
				fail(res){
					reject(res);
				}
			})
		})
	}
	/**
	 * uni.login 获取登录code
	 */
	async getCode(){
		let provider = await this.getProvider();
		return new Promise((resolve,reject)=>{
			if(Cache.has(STATE_R_KEY)){
				return resolve(Cache.get(STATE_R_KEY));
			}
			uni.login({
				provider:provider,
				success(res) {
					if (res.code) Cache.set(STATE_R_KEY, res.code ,10800);
					return resolve(res.code);
				},
				fail(){
					return reject(null);
				}
			})
		})
	}

	/**
	 * 是否授权
	 */
	isAuth(){
		let that = this;
		return new Promise((resolve,reject)=>{
			uni.getSetting({
				success(res) {
					if (!res.authSetting[that.scopeUserInfo]) {
						resolve(true)
					} else {
						resolve(true);
					}
				},
				fail(){
					 resolve(false);
				}
			});
		});
	}
}

export default new Routine();

你可能感兴趣的:(token验证,uni-app,vue.js,前端)