由於微信小程序提供的 權限彈窗 只能通用戶確認受權 因此能夠 寫一個受權頁面,讓用戶點擊 來獲取用戶相關信息 而後再配合後臺就能夠完成登陸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>
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) }) }) }
// 接口獲取 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小程序