zoukankan      html  css  js  c++  java
  • uni-app开发经验分享二十: 微信小程序 授权登录 获取详细信息 获取手机号

    授权页面

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

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

     素材

     页面代码示例
    这个接口要在后端调用(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;
    	     650rpx;
    	    height: 300rpx;
    	    line-height: 450rpx;
    	  }
    	 
    	  .header image {
    	     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)
    },

    这个需要 真机测试 或 预览

    <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;
    	     650rpx;
    	    height: 300rpx;
    	    line-height: 450rpx;
    	}
    	.header image {
    	     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

  • 相关阅读:
    SQL语句执行效率及分析(note)
    双重检查锁定及单例模式
    可定制生命周期的缓存
    php CI框架高级视图功能,视图继承,多重继承,视图片段
    php 使用pdo连接postgresql
    python 学习整理
    phpmailer 发送邮件
    php syslog记录系统日志
    php 学习整理
    php 生成唯一id方法
  • 原文地址:https://www.cnblogs.com/smileZAZ/p/14298426.html
Copyright © 2011-2022 走看看