授權頁面
因為微信小程序提供的 權限彈窗 只能通用戶確認授權 所以可以 寫一個授權頁面,讓用戶點擊 來獲取用戶相關信息 然后再配合后台就可以完成登錄
<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
