uni-app開發經驗分享二十: 微信小程序 受權登陸 獲取詳細信息 獲取手機號

受權頁面

由於微信小程序提供的 權限彈窗 只能通用戶確認受權 因此能夠 寫一個受權頁面,讓用戶點擊 來獲取用戶相關信息 而後再配合後臺就能夠完成登陸html

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

 素材vue

 頁面代碼示例
這個接口要在後端調用(https://api.weixin.qq.com沒法加入白名單)java

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
前提條件 先要登陸sql

onLoad() {
	this.login()
},

仍是用上面的受權頁面vuex

<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)
},

這個須要 真機測試 或 預覽數據庫

<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>

至於後臺解密

個人項目後臺解密apache

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;
	}

}

可參考 http://www.javashuo.com/article/p-bybbuadw-nn.htmljson

獲取詳細信息 獲取手機號 優化封裝

頁面

<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小程序

相關文章
相關標籤/搜索