最近刚接触了uni-app,用于开发微信小程序,设计到了微信授权登录。抽个时间整理个笔记,适用于向我一样刚开始上手uni-app的初学者。
首先要明确uni-app框架有自己的开发一套开发流程,和微信开发者工具使用的语法,api是不同的
如果把微信开发者工具比作原生js,那uni-app就好比React,Vue。
1.获取用户名及头像(真的就只获取用户名和头像地址,没有其他用户信息)
主要步骤:
- onLoad中调用 uni.login()获取登录用户code
- 调用后端接口,将code作为参数置换出SessionKey和OpenId进行存储(可以使用uni.setStorageSync)
- 点击“授权登录”,新版微信再确认授权后可以直接调用uni.getUserProfile()
老版微信可以通过给button设置open-type="getUserInfo"和@getuserinfo=“事件”,通过e.detail.userInfo获取 - 调后端自己写的登录接口,参数就是上一步用户信息以及存储的OpenId,获取到cookie等信息完成登录
直接上代码
<template>
<view class="page-login">
<view v-if="canIUse||canIGetUserProfile">
<view class='content'>
<image style="width: 140rpx; height: 140rpx;" mode="aspectFit" src="../../static/wx.jpg"></image>
<view class="name">登录</view>
<view>申请获取以下权限</view>
<text>获得你的公开信息(昵称、头像、地区等)</text>
</view>
<view class="login-box">
<!--新版登录方式-->
<button v-if="canIGetUserProfile" class='login-btn' type='primary' @click="bindGetUserInfo"> 授权登录 </button>
<!--旧版登录方式-->
<button v-else class='login-btn' type='primary' open-type="getUserInfo" withCredentials="true" lang="zh_CN" @getuserinfo="bindGetUserInfo"> 授权登录 </button>
</view>
</view>
<view v-else class="text-center">
请升级微信版本
</view>
</view>
</template>
<script>
export default {
data () {
return {
canIUse: uni.canIUse('button.open-type.getUserInfo'),
canIGetUserProfile: false,//微信登录新旧版本 true是新
}
},
onLoad () {
//必须先调用微信的登录接口 然后再去调用授权拿微信个人信息(否则顺序错乱会导致 小概率授权后拿不到头像和昵称)
this.wxLogin()
var _this = this
if (uni.getUserProfile) {
this.canIGetUserProfile = true
}
},
onShow () {
},
methods: {
//登录授权
bindGetUserInfo (e) {
console.log('e', e)
var _this = this
if (this.canIGetUserProfile) {
//新版登录方式
uni.getUserProfile({
desc: '获取您个人信息用于登录!',
success: (res) => {
console.log('用户信息', res)
// 存入个人信息
uni.setStorageSync('userInfo_winxin', res.userInfo)
_this.updateUserInfo()
},
fail: (res) => {
console.log(res)
}
})
} else {
//旧版登录方式 --自动就拉起授权窗口
if (e.detail.userInfo) {
//用户按了允许授权按钮
//console.log('手动');
console.log('老版用户信息', e.detail.userInfo)
// 存入个人信息
uni.setStorageSync('userInfo_winxin', e.detail.userInfo)
_this.updateUserInfo()
} else {
console.log('用户拒绝了授权')
//用户按了拒绝按钮
}
}
},
//登录---目的拿到code
wxLogin () {
let _this = this
// 获取登录用户code
uni.login({
provider: 'weixin',
success: function (res) {
console.log(res);
if (res.code) {
//将用户登录code传递到后台置换用户SessionKey、OpenId等信息 可参照此篇文章: https://ask.dcloud.net.cn/article/37452
// 1.拿code调后端接口1 也就是getOpenid() 换取到SessionKey、OpenId(这个是唯一且固定不变)
// 2.拿openId 调后端自己写的登录接口2 获取到cookie等信息 (这个cookie后期请求放在请求头上的) 登陆成功进行存储和跳转页面
//这是我们的后端接口1--换取到SessionKey、OpenId
// let params = { code: res.code}
// getOpenid(params, false).then((res) => {
// console.log('拿code调后端接口1 换取到SessionKey、OpenId', res)
// uni.setStorageSync('session_key', res.data.session_key)
// uni.setStorageSync('openid', res.data.openid)
// })
} else {
uni.showToast({ title: '获取logon_code失败', duration: 2000 })
console.log('获取logon_code失败' + res.errMsg)
_this.wxLogin()
}
},
fail: (res) => {
uni.showToast({ title: '获取logon_code失败', duration: 2000 })
console.log('获取logon_code失败' + res.errMsg)
_this.wxLogin()
}
})
},
//向后台更新信息
updateUserInfo () {
let _this = this
//这是我们的后端接口2--登录接口2 获取到cookie等信息(这个cookie后期请求放在请求头上的)
// let params = {
// openid: uni.getStorageSync('openid'),
// nickname: uni.getStorageSync('userInfo_winxin').nickName,
// head_image: uni.getStorageSync('userInfo_winxin').avatarUrl,
// }
// loginByWechat(params).then((res) => {
// })
//下面的这个cookie键值对是暂时写死的,正常应该接口2返回的
let login_cookie_name = 'login_cookie_name'
let login_cookie_value = 'login_cookie_value'
uni.setStorageSync('login_cookie_name', login_cookie_name)
uni.setStorageSync('login_cookie_value', login_cookie_value)
// 注意:以上的存储为了在request请求时候携带和判断用 在退出登录时候需要清除掉
uni.hideLoading()
uni.showToast({
title: '接口登录逻辑自写-登陆成功',
duration: 1500,
icon: 'success',
})
// 跳转到首页
uni.reLaunch({ url: '/pages/index/index' })
}
}
}
</script>
<style lang="less" scoped>
.content {
text-align: center;
}
</style>
2.获取用户手机号(真的就只获取手机号)
主要步骤:
- onLoad中调用 uni.login()获取登录用户code
- 调用后端接口,将code作为参数置换出SessionKey和OpenId进行存储(可以使用uni.setStorageSync)
- 点击“手机号登录”按钮,触发getphonenumber事件,获取如下相关信息,重要是的encryptedData和iv。请求后端接口,将encryptedData,iv,
SessionKey作为参数传递给后端,后端处理后返回正确的电话号码(后端如何解析可参考网上教程) - 直接上代码