- A+
所属分类:Web前端
授权页面
因为微信小程序提供的 权限弹窗 只能通用户确认授权 所以可以 写一个授权页面,让用户点击 来获取用户相关信息 然后再配合后台就可以完成登录
<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; 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) },
这个需要 真机测试 或 预览
<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