uni-app开发经验分享二十: 微信小程序 授权登录 获取详细信息 获取手机号

  • A+
所属分类:Web前端
摘要

因为微信小程序提供的 权限弹窗 只能通用户确认授权 所以可以 写一个授权页面,让用户点击 来获取用户相关信息 然后再配合后台就可以完成登录


授权页面

因为微信小程序提供的 权限弹窗 只能通用户确认授权 所以可以 写一个授权页面,让用户点击 来获取用户相关信息 然后再配合后台就可以完成登录

<button class="btnInfo" open-type="getUserInfo"/>

uni-app开发经验分享二十: 微信小程序 授权登录 获取详细信息 获取手机号

 素材

uni-app开发经验分享二十: 微信小程序 授权登录 获取详细信息 获取手机号

 页面代码示例
这个接口要在后端调用(https://api.weixin.qq.com无法加入白名单)

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

 

<template> 	<view> 		<view> 		  <view> 			<view class='header'> 			  <image src='../../static/wx_login.png'></image> 			</view> 			<view class='content'> 			  <view>申请获取以下权限</view> 			  <text>获得你的公开信息(昵称,头像、地区等)</text> 			</view> 			<!-- withCredentials=true  获取到除用户基本信息之外的encryptedData以及iv等数据 --> 			<button class='bottom' type='primary' open-type="getUserInfo" withCredentials="true" lang="zh_CN" @getuserinfo="wxGetUserInfo"> 			  授权登录 			</button> 			 			<!-- <button class='bottom' type='primary' open-type="getPhoneNumber"  @getphonenumber="getPhoneNumber"> 			  授权登录 			</button> --> 		  </view> 		</view> 	</view> </template>  <script> 	import { htxcx } from "@/store/api.js" 	import { mapMutations } from 'vuex' 	export default { 		data() { 			return { 				code:"", 				SessionKey: '', 				encryptedData:"", 				iv:"", 				OpenId: '', 				nickName: null, 				avatarUrl: null, 				isCanUse: uni.getStorageSync('isCanUse')//默认为true  记录当前用户是否是第一次授权使用的 			} 		},  		onLoad() { 			this.login() 		}, 		methods: { 			...mapMutations(["setName"]), 			wxGetUserInfo(){ //第一授权获取用户信息===》按钮触发 				let _this = this; 				// 获取用户信息 				uni.getUserInfo({ 					provider: 'weixin', 					success: function (infoRes) { 						_this.encryptedData = infoRes.encryptedData 						_this.iv = infoRes.iv 						_this.nickName = infoRes.userInfo.nickName; //昵称 						_this.avatarUrl = infoRes.userInfo.avatarUrl; //头像 						uni.setStorageSync('isCanUse', false);//记录是否第一次授权 false:表示不是第一次授权 						_this.updateUserInfo(); 					},fail:function (fail){console.log("fail:",fail)} 				}); 			}, 			login(){ 				let _this = this; 				uni.showLoading({ 				  title: '登录中...' 				}); 				 				// 1.wx获取登录用户code 				uni.login({ 					provider: 'weixin', 					success: function(loginRes) { 						_this.code = loginRes.code; 						if (!_this.isCanUse) { 							//非第一次授权获取用户信息 							uni.getUserInfo({ 								provider: 'weixin', 								success: function(infoRes) { 									console.log('login用户信息:',infoRes); 				            //获取用户信息后向调用信息更新方法 									_this.nickName = infoRes.userInfo.nickName; //昵称 									_this.avatarUrl = infoRes.userInfo.avatarUrl; //头像 									_this.updateUserInfo();//调用更新信息方法 								} 							}); 						} 						// 将用户登录code传递到后台置换用户SessionKey、OpenId等信息 						 						uni.hideLoading(); 					}, 				}) 					 			}, 			updateUserInfo(){ //向后台更新信息 				this.setName(this.nickName,this.avatarUrl) 				let _this = this; 				var obj ={ 					appid:"wx1*********0f06", 					secret:"07bd3*************096", 					code:this.code 				} 				// 这个接口要在后端调用(https://api.weixin.qq.com无法加入白名单) 				// https://api.weixin.qq.com/sns/jscode2session?appid="+appid+"&secret="+secret+"&js_code="+code+"&grant_type=authorization_code 				// 请求微信端地址获取用户唯一标识的 				htxcx(obj.appid,obj.secret,obj.code).then(res=>{ 					console.log("res:",res) 									 					res.data.openid // 唯一 					res.data.session_key  					this.encryptedData 					this.iv 					 					 					 					 					uni.reLaunch({//信息更新成功后跳转到小程序首页 						url: '/pages/index/index' 					}); 				},err=>{ 					console.log("err:",err) 				}) 				 				 				 				 			} 		} 	} </script>  <style scoped> 	.header { 	    margin: 90rpx 0 90rpx 50rpx; 	    border-bottom: 1px solid #ccc; 	    text-align: center; 	    width: 650rpx; 	    height: 300rpx; 	    line-height: 450rpx; 	  } 	  	  .header image { 	    width: 200rpx; 	    height: 200rpx; 	  } 	  	  .content { 	    margin-left: 50rpx; 	    margin-bottom: 90rpx; 	  } 	  	  .content text { 	    display: block; 	    color: #9d9d9d; 	    margin-top: 40rpx; 	  } 	  	  .bottom { 	    border-radius: 80rpx; 	    margin: 70rpx 50rpx; 	    font-size: 35rpx; 	  } </style> 

获取手机号

微信文档:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/getPhoneNumber.html
前提条件 先要登录

onLoad() { 	this.login() }, 

还是用上面的授权页面

<button class='bottom' type='primary' open-type="getUserInfo" withCredentials="true" lang="zh_CN" @getuserinfo="wxGetUserInfo">授权登录</button> 			 <button class='bottom' type='primary' open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">获取手机号</button>  事件 getPhoneNumber(val){ 	console.log(val) },

这个需要 真机测试 或 预览

uni-app开发经验分享二十: 微信小程序 授权登录 获取详细信息 获取手机号

<template> 	<view> 		<view> 		  <view> 			<view class='header'> 			  <image src='../../static/wx_login.png'></image> 			</view> 			<view class='content'> 			  <view>申请获取以下权限</view> 			  <text>获得你的公开信息(昵称,头像、地区等)</text> 			</view> 			<!-- withCredentials=true  获取到除用户基本信息之外的encryptedData以及iv等数据 --> 			<!-- <button class='bottom' type='primary' open-type="getUserInfo" withCredentials="true" lang="zh_CN" @getuserinfo="wxGetUserInfo"> 			  授权登录 			</button> --> 			 			<button class='bottom' type='primary' open-type="getPhoneNumber"  @getphonenumber="getPhoneNumber"> 			  授权登录 			</button> 		  </view> 		</view> 	</view> </template>  <script> 	 	import { htxcx } from "@/store/api.js" 	import { mapMutations } from 'vuex' 	export default { 		data() { 			return { 				code:"", 				SessionKey: '', 				encryptedData:"", 				iv:"", 				OpenId: '', 				nickName: null, 				avatarUrl: null, 				isCanUse: uni.getStorageSync('isCanUse')//默认为true  记录当前用户是否是第一次授权使用的 			} 		},  		onLoad() { 			this.login() 		}, 		methods: { 		 			...mapMutations(["setName"]), 			wxGetUserInfo(){ //第一授权获取用户信息===》按钮触发 				let _this = this; 				// 获取用户信息 				uni.getUserInfo({ 					provider: 'weixin', 					success: function (infoRes) { 						_this.encryptedData = infoRes.encryptedData 						_this.iv = infoRes.iv 						_this.nickName = infoRes.userInfo.nickName; //昵称 						_this.avatarUrl = infoRes.userInfo.avatarUrl; //头像 						uni.setStorageSync('isCanUse', false);//记录是否第一次授权 false:表示不是第一次授权 						_this.updateUserInfo(); 					},fail:function (fail){console.log("fail:",fail)} 				}); 			}, 			getPhoneNumber:function(e){ 				this.encryptedData = e.detail.encryptedData 				this.iv = e.detail.iv 				uni.setStorageSync('isCanUse', false); 				this.updateUserInfo() 			}, 			login(){ 				let _this = this; 				uni.showLoading({ 				  title: '登录中...' 				}); 				 				// 1.wx获取登录用户code 				uni.login({ 					provider: 'weixin', 					success: function(loginRes) { 						console.log("登录",loginRes.code) 						_this.code = loginRes.code; 						if (!_this.isCanUse) { 							//非第一次授权获取用户信息 							uni.getUserInfo({ 								provider: 'weixin', 								success: function(infoRes) { 									console.log('login用户信息:',infoRes); 				            //获取用户信息后向调用信息更新方法 									_this.nickName = infoRes.userInfo.nickName; //昵称 									_this.avatarUrl = infoRes.userInfo.avatarUrl; //头像 									_this.updateUserInfo();//调用更新信息方法 								}, 								fail(err) { 									console.log(err) 								} 							}); 						} 						// 将用户登录code传递到后台置换用户SessionKey、OpenId等信息 						 						uni.hideLoading(); 					}, 				}) 					 			}, 			updateUserInfo(){ //向后台更新信息 				this.setName(this.nickName,this.avatarUrl) 				let _this = this; 				var obj ={ 					appid:"wx1b02a26b03110f06", 					secret:"07bd35d41e7fb6a9bff173c728d6a096", 					code:this.code 				} 				 				// 这一步一般是在后台  这里是为了测试 				// 正常给 后台 5个测试 appId appsecret code(登录接口获取) encryptedData iv 				 				htxcx(obj.appid,obj.secret,obj.code).then(res=>{ 					console.log("res:",res) 									 					res.data.openid // 唯一 					res.data.session_key  					this.encryptedData 					this.iv 					 					// 把这些参数通过接口传给后台 解密 获取手机号 					 					 					return 					uni.reLaunch({//信息更新成功后跳转到小程序首页 						url: '/pages/index/index' 					}); 				},err=>{ 					console.log("err:",err) 				}) 			} 		} 	} </script> 

至于后台解密

我的项目后台解密

package jstfsn;  import java.io.UnsupportedEncodingException; import java.security.Security; import java.security.spec.AlgorithmParameterSpec; import java.sql.Connection; import java.text.ParseException;  import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.KeyGenerator; import javax.crypto.NoSuchPaddingException; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import javax.naming.NamingException;  import org.apache.commons.codec.binary.Base64; import org.apache.log4j.Logger;  import GCcom.CommonValue; import GCcom.DBOperation; import StxsysBass.StxsysAdmin.CheckingLineService; import com.alibaba.fastjson.JSONObject; import com.justep.baas.action.ActionContext;   public class Login { 	 	 	/** 	 * 查询历史线路未巡检的巡检点 	 *  	 * @param params 	 * @param context 	 * @return 	 * @throws NamingException 	 */ 	 	/** 	 * 日志 	 */ 	public static Logger logger = Logger.getLogger(CheckingLineService.class); 	/** 	 * 数据库名 	 */ //	public static String DATASOURCE = CommonValue.MYSQL_DATA_BASE_JSTFSN; 	 	/************************************************************************************ 	 * 函数名:	getWxUserInfo  	 * 参数名:	JSONObject params: 参数集 	 * 			ActionContext context : 上下文 	 *  	 * 功能:	通过用户授权加密信息解密获取用户信息 	 *  	 * 开发者:	Leechen8@gmail.com 20200317 	 *  	 * 修改者: 	 *  	 * @return 	 * @throws ParseException 	 *  	 *  	 ************************************************************************************/ 	public static JSONObject getWxUserInfo(JSONObject params, ActionContext context) throws NamingException { 		// 获取参数 		String strCipher = ""; 		String strEncrypdata = params.getString("encrypdata"); 		String strIvdata = params.getString("ivdata"); 		String strSessionkey= params.getString("sessionkey"); 		 		byte[] byEncrypdata = Base64.decodeBase64(strEncrypdata); 		byte[] byIvdata = Base64.decodeBase64(strIvdata); 		byte[] bySessionkey = Base64.decodeBase64(strSessionkey);   		JSONObject jsData = new JSONObject(); 	 		AlgorithmParameterSpec ivSpec = new IvParameterSpec(byIvdata); 		Cipher cipher; 		try {	         			SecretKeySpec keySpec = new SecretKeySpec(bySessionkey, "AES"); 			cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 			cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec); 			strCipher = new String(cipher.doFinal(byEncrypdata),"UTF-8"); 			jsData.put("phone", strCipher); 			 		} catch (Exception e) { 			// TODO Auto-generated catch block 			e.printStackTrace(); 			jsData.put("error", e.getMessage()); 		} 			          		return jsData; 	}  } 

可参考 https://blog.csdn.net/qq_38194393/article/details/81382108

获取详细信息 获取手机号 优化封装

页面

<template> 	<view> 		<view> 			 <view> 				<view class='header'> 					<image src='../../static/wx_login.png'></image> 				</view> 				<view class='content'> 					<view>申请获取以下权限</view> 					<text>获得你的公开信息(昵称,头像、地区等)</text> 					<text>获得你微信绑定的手机号</text> 				</view> 	 				<!-- <picker class="view_input" @change="bindPickerMPChange" :value="type" :range="typeArr"> 					<view :class="typeArr[type]?'uni-input':'uni-input options'">{{typeArr[type]? typeArr[type]:"请选择用户身份"}}</view> 				</picker> --> 				 				<button class='bottom' type='primary' open-type="getUserInfo" withCredentials="true" lang="zh_CN" @getuserinfo="wxGetUserInfo"> 					授权登录 				</button> 				 				<button class='bottom' type='primary' open-type="getPhoneNumber"  @getphonenumber="getPhoneNumber"> 					手机号授权 				</button> 			</view> 		</view> 	</view> </template>  <script> 	import {wxlogin, getPhone, wxUserInfo} from "@/store/wxlogin.js" 	import {htxcx} from "@/store/api.js" 	export default { 		data() { 			return { 				appid:"wx1b02a26b03110f06", 				secret:"07bd35d41e7fb6a9bff173c728d6a096", 				type:0, 				phone:"", 				typeArr:["承运人","管理员"], 				phoneParams:{  					sessionkey:"", 					ivdata:"", 					encrypdata:"" 				}, 				loginStatus:false, 				phoneStatus:false 			} 		}, 		onLoad() { 			try{ 				this.init() 			}catch(e){ 				console.log("init错误信息:",e) 			} 		}, 		methods: { 			async init(){ 				var code = await wxlogin() 				// 获取sessionkey 				var key = await htxcx(this.appid,this.secret,code) 				this.phoneParams.sessionkey = key.data.session_key; 			}, 			async getPhoneNumber(e){ 				this.phoneParams.encrypdata = e.detail.encryptedData 				this.phoneParams.ivdata = e.detail.iv 				 				var phone = await getPhone(this.phoneParams) 				this.phone = phone.purePhoneNumber 				console.log("phone:",this.phone) 				 				if(this.phone){ 					this.phoneStatus = true 					this.reLaunch() 				} 			}, 			async wxGetUserInfo(){ 				var info = await wxUserInfo() 				this.loginStatus = true 				this.reLaunch() 			}, 			reLaunch(){ 				if(this.loginStatus && this.phoneStatus){ 					uni.setStorageSync("tongfang-phone",this.phone) 					 					// 后续业务代码 					 					// uni.reLaunch({//信息更新成功后跳转到小程序首页 					// 	url: '/pages/index/index' 					// }); 				} 			}, 			 			bindPickerMPChange(e){ 				this.type =  e.target.value 			}	 		} 	} </script>  <style> 	.header { 	    margin: 90rpx 0 50rpx 50rpx; 	    border-bottom: 1px solid #ccc; 	    text-align: center; 	    width: 650rpx; 	    height: 300rpx; 	    line-height: 450rpx; 	} 	.header image { 	    width: 200rpx; 	    height: 200rpx; 	} 	.content { 	    margin-left: 50rpx; 	    margin-bottom: 50rpx; 	} 	.content text { 	    display: block; 	    color: #9d9d9d; 	    margin-top: 40rpx; 	} 	.bottom { 	    border-radius: 80rpx; 	    margin: 35rpx 50rpx; 	    font-size: 35rpx; 	} 	.bottom:first-child{ 		margin-top: 50rpx; 	} 	 	.view_input{ 		margin: 0 50rpx; 		background-color: white; 		padding: 10px; 		height: 1rem; 		line-height: 1rem; 	} </style> 

wxlogin.js

import {getPhone as getphone} from '@/store/api.js' /* 微信登录 	返回 code */ export const wxlogin = ()=> { 	return new Promise((resolve, reject)=>{ 		uni.showLoading({ 		  title: '登录中...' 		}); 		 		uni.login({ 			provider: 'weixin', 			success: function(loginRes) { 				resolve(loginRes.code); 				uni.hideLoading(); 			}, 			fail(err) { 				reject(err) 				uni.hideLoading(); 			} 		}) 		 	}) }  /* 获取微信用户信息 要先调用登录接口 	返回用户信息 */ export const wxUserInfo = ()=>{ 	return new Promise((resolve, reject)=>{ 		uni.getUserInfo({ 			provider: 'weixin', 			success: function(res) { 				resolve(res); 			}, 			fail(err) { 				reject(err) 			} 		}); 	}) }  /* 获取微信用户手机号 要先调用登录接口 	参数:obj{ 		sessionkey, 		ivdata, 		encrypdata 	} 	返回手机号相关信息 	 */ export const getPhone = (obj)=>{ 	return new Promise((resolve, reject)=>{ 		getphone(obj).then(res=>{ 			resolve(JSON.parse(res.data.data.phone)) 		},err=>{ 			reject(err) 		}) 	}) } 

api.js

// 接口获取 sessionkey export const htxcx = (appid,secret,code)=>uniAjax("https://api.weixin.qq.com/sns/jscode2session?appid="+appid+"&secret="+secret+"&js_code="+code+"&grant_type=authorization_code")  // 解密手机号 export const getPhone = (obj)=>uniAjax(BASE_URL_dev+"/getWxUserInfo",obj,"POST") 

转载于:https://blog.csdn.net/weixin_42448623/article/details/104928750