目录
01: 前言
02: 第三方平台登录解决方案流程大解析
03: QQ 开放平台流程大解析
04: QQ 登录对接流程:获取 QQ 用户信息
05: QQ 登录对接流程:跨页面信息传输
06: QQ 登录对接流程:认证是否已注册,完成 QQ 登录流程
07: 移动端 QQ 登录对接:触发吊起操作,完成移动端 QQ 登录
08: 微信开放平台大解析
微信公众平台和微信开放平台的区别
微信开放平台账户注册
个人主体注册
企业主体注册
微信开放平台应用注册
开发者资质认证
09: 对接微信扫码登录
10: 总结
01: 前言
从本文章开始我们将要去完成各种第三方的功能。
首先我们要去处理的就是 第三方登录。
1. QQ 登录
2. 微信登录
第三方登录是平时开发中一个非常常见的功能。针对这种功能,我们需要进行哪些准备,对接时又有哪些坑在等着我们呢? 让我们拭目以待吧。
02: 第三方平台登录解决方案流程大解析
通常情况下,我们所说的第三方登录指的是:通过第三方 APP 进行登录。
这个第三方 APP 是如何与我们自己的应用进行关联的呢?如果大家不是很清楚,本小节将为你解答。
想要搞明白这个问题,首先需要清楚整个第三方登录的流程是如何进行的。
我们以**网第三方登录为例:
1. 点击第三方登录按钮。
2. 弹出一个小窗口,展示对应的二维码。
3. 手机打开对应的 APP 进行扫码之后,会跳转到 同意页面,同时浏览器端也会显示扫码成功。
4. 手机端操作同意登录之后,会出现两种情况:
1. 当前用户已注册:
1. 直接登录。
2. 当前用户未注册:
1. 执行注册功能。
2. 注册成功即可登录。
在这样的一个流程之中,第三方 APP 和我们自己的应用,分别都做了什么事情呢?
同样,我们对照流程进行说明:
1. 点击第三方登录按钮:执行 window.open 方法,打开一个第三方指定的 URL 窗口,该地址会指向第三方登录的 URL,并且由第三方提供一个对应的 二维码。
2. 弹出一个小窗口,展示对应二维码:此处展示的二维码,为上一步中第三方提供的二维码。
3. 手机打开对应的 APP 进行扫码之后,会跳转到 同意页面。同时浏览器端也会显示扫码成功。在第三方中会一直对该页面进行 轮询,配合第三方 APP 来判断是否扫码成功。
4. 手机端操作同意登录之后,会出现两种情况:在 APP 中同意之后,第三方会进行对应的跳转,跳转地址为你指定的地址。在该地址中可以获取到 第三方的用户信息,该信息即为第三方登录时要获取到的关键数据。
5. 至此,第三方操作完成。接下来需要进行本平台的登录判定。
1. 该注册指的是 第三方用户 是否在本平台中进行了注册。
2. 因为之前的所有操作中,我们拿到的是 第三方用户信息。
3. 该信息可以帮助我们直接显示用户的用户名(nickname)和头像。但是因为不包含关键信息(手机号、用户名 username、密码),所以我们无法使用该信息帮助用户直接登录。
4. 所以我们需要判断当前用户是否在咱们自己的平台中完成了注册。
1. 当前用户已注册:
1. 直接登录。
2. 当前用户未注册:
1. 执行注册功能。
综上所述,我们想要完成第三方登录功能,共分为两个大的步骤:
1. 对接第三方平台,获取第三方平台的用户信息。
2. 使用该用户信息,完成本应用的注册。
03: QQ 开放平台流程大解析
想要对接 QQ 登录,需要使用到 QQ 互联 平台。在该平台中:
1. 注册账户。
2. 认证开发者。
3. 注册应用。
整体流程如下:
1. 注册账户
1. 点击登录按钮,进行扫码登录。
2. 进行扫码登录。
2. 进行开发者审核
1. 点击顶部头像,进入开发者审核阶段。
2. 开发者审核分为:公司接入(需要上传营业执照信息)和 个人接入(需要上传身份证信息)两种。
3. 信息输入完成之后,点击下一步进行 邮箱验证。
4. 进入邮箱,访问链接。
5. 信息注册成功。
6. 点击 管理中心,此时账户应处于 个人开发者 审核中 状态。
7. 等待审核信息通过。
3. 创建网站应用(需要等待审核通过之后)
1. 选择 网站应用,点击 创建应用。
2. 选择 创建网站应用。
3. 填写网站资料。填写完成后,点击 创建应用。
4. 应用创建成功。
5. 完善资料,填写网站信息。
1. 回调地址常见问题及修改方法。
6. 应用创建成功。点击 应用管理 可进入应用管理后台。
7. 此时应用状态应该为 审核中。
8. 点击 查看 按钮,选择 应用接口。
9. 此时 登录 功能应该为 已获取 状态。
10. 点击 get_user_info 即可进入 API 文档。
此时,应用创建成功之后,即可进行 QQ 登录对接。
04: QQ 登录对接流程:获取 QQ 用户信息
对接 QQ 登录分为以下几步:
1. 展示 QQ 登录二维码
2. 获取用户信息
3. 完成跨页面数据传输
4. 认证是否已注册
5. 完成 QQ 对接
1. 在 index.html 中,导入 QQ SDK。
<!-- QQ 登录 -->
<script type="text/javascript" charset="utf-8"src="http://connect.qq.com/qc_jssdk.js"data-appid="APPID"data-redirecturi="REDIRECTURI"
></script>
2. 创建 src/views/login-register/login/qq-login.vue 组件,作为 QQ 登录处理组件,并初始化对应样式和基础功能:
- src/views/login-register/login
- - qq-login.vue
// src/views/login-register/login/qq-login.vue<template><div><span id="qqLoginBtn" v-show="false"></span><m-svg-iconclass="w-4 cursor-pointer"name="qq"@click="onQQLogin"></m-svg-icon></div>
</template><script>
// QQ 登录的 URL
const QQ_LOGIN_URL ='https://graph.qq.com/oauth2.0/authorize?client_id=101998494&response_type=token&scope=all&redirect_uri=https%3A%2F%2Fimooc-front.lgdsunday.club%2Flogin'
</script><script setup>
import { onMounted } from 'vue'
import brodacast from './brodacast'
import { oauthLogin } from './oauth'
import { LOGIN_TYPE_QQ } from '@/constants'// QQ 登录挂起
onMounted(() => {QC.Login({btnId: 'qqLoginBtn' //插入按钮的节点id},// 登录成功之后的回调,但是需要注意,这个回调只会在《登录回调页面中被执行》// 登录存在缓存,登录成功一次之后,下次进入会自动重新登录// (即:触发该方法,所以我们应该在离开登录页面时,注销登录)(data, opts) => {console.log('QQ登录成功')// 1. 注销登录,否则在后续登录中会直接触发该回调QC.Login.signOut()// 2. 获取当前用户唯一标识,作为判断用户是否已注册的依据const accessToken = /access_token=((.*))&expires_in/.exec(window.location.hash)[1]// 3. 拼接请求对象const oauthObj = {nickname: data.nickname,figureurl_qq_2: data.figureurl_qq_2,accessToken}// 4. 完成跨页面传输brodacast.send(oauthObj)// 针对于 移动端而言:通过移动端触发 QQ 登录会展示三个页面,// 原页面、QQ 吊起页面、回调页面。// 并且移动端一个页面展示整屏内容,且无法直接通过 window.close() 关闭,// 所以在移动端中,我们需要在当前页面继续进行后续操作。oauthLogin(LOGIN_TYPE_QQ, oauthObj)// 5. 在 PC 端下,关闭第三方窗口window.close()})
})/*** 登录按钮事件*/
const onQQLogin = () => {openQQWindow()
}/*** 处理 QQ 登录视窗*/
const openQQWindow = async () => {window.open(QQ_LOGIN_URL,'oauth2Login_10609','height=525,width=585, toolbar=no, menubar=no, scrollbars=no, status=no, location=yes, resizable=yes')// 打开视窗之后开始等待brodacast.wait().then(async (oauthObj) => {// 登录成功,关闭通知brodacast.clear()// 执行登录操作oauthLogin(LOGIN_TYPE_QQ, oauthObj)})
}
</script>
05: QQ 登录对接流程:跨页面信息传输
想要实现跨页面信息传输,通常有两种方式:
1. BroadcastChannel:允许 同源 的不同浏览器窗口、Tab 页、Frame 或者 Frame 下的不同文档之间相互通信。但是会有兼容性问题,实测 Safari@15.3 无法使用。
2. localstorage + window.onstorage:通过 localStorage 进行 同源 的数据传输。用来处理 BroadcastChannel 不兼容的浏览器。
依据以上两个 API,我们实现对应的通讯模块:
1. 创建 src/views/login-register/login/broadcast.js 模块:
// 频道名
const LOGIN_SUCCESS_CHANNEL = 'LOGIN_SUCCESS_CHANNEL'// 官方声明 safari 支持 BroadcastChannel ,但是实测 15.3 的版本并不支持 😠,所以我们需要对其进行判定使用,在不支持 BroadcastChannel 的浏览器中,使用 localstorage
let broadcastChannel = null
if (window.BroadcastChannel) {broadcastChannel = new BroadcastChannel(LOGIN_SUCCESS_CHANNEL)
}/*** 等待 QQ 登录成功* 因为 QQ 登录会在一个新的窗口中进行,用户扫码登录成功之后会回调《新窗口的 QC.Login 第二参数 cb》,而不会回调到原页面。* 所以我们需要在《新窗口中通知到原页面》,所以就需要涉及到 JS 的跨页面通讯,而跨页面通讯指的主要就是《同源页面的通讯》* 同源页面的通讯方式有很多,我们这里主要介绍:* 1. BroadcastChannel -> https://developer.mozilla.org/zh-CN/docs/Web/API/BroadcastChannel* 2. window.onstorage:注意:该事件不在导致数据变化的当前页面触发*/
/*** 等待回调,它将返回一个 promise,并携带对应的数据*/
const wait = () => {return new Promise((resolve, reject) => {if (broadcastChannel) {// 触发 message 事件时的回调函数broadcastChannel.onmessage = async (event) => {// 改变 promise 状态resolve(event.data)}} else {// 触发 localStorage 的 setItem 事件时回调函数window.onstorage = (e) => {// 判断当前的事件名if (e.key === LOGIN_SUCCESS_CHANNEL) {// 改变 promise 状态resolve(JSON.parse(e.newValue))}}}})
}/*** 发送消息。* broadcastChannel:触发 message* localStorage:触发 setItem*/
const send = (data) => {if (broadcastChannel) {broadcastChannel.postMessage(data)} else {localStorage.setItem(LOGIN_SUCCESS_CHANNEL, JSON.stringify(data))}
}/*** 清除*/
const clear = () => {if (broadcastChannel) {broadcastChannel.close()broadcastChannel = null}localStorage.removeItem(LOGIN_SUCCESS_CHANNEL)
}export default {wait,send,clear
}
2. 在 src/views/login-register/login/qq-login.vue 中使用:
<script setup>
import brodacast from './brodacast'// QQ 登录挂起
onMounted(() => {QC.Login({btnId: 'qqLoginBtn' //插入按钮的节点id},// 登录成功之后的回调,但是需要注意,这个回调只会在《登录回调页面中被执行》(data, opts) => {// 1. 注销登录,否则在后续登录中会直接触发该回调// 2. 获取当前用户唯一标识,作为判断用户是否已注册的依据// 3. 拼接请求对象const oauthObj = {nickname: data.nickname,figureurl_qq_2: data.figureurl_qq_2,accessToken}// 4. 完成跨页面传输brodacast.send(oauthObj)// 针对于 移动端而言:通过移动端触发 QQ 登录会展示三个页面,// 原页面、QQ 吊起页面、回调页面。并且移动端一个页面展示整屏内容,// 且无法直接通过 window.close() 关闭,// 所以在移动端中,我们需要在当前页面继续进行后续操作。oauthLogin(LOGIN_TYPE_QQ, oauthObj)// 5. 在 PC 端下,关闭第三方窗口window.close()})
})/*** 处理 QQ 登录视窗*/
const openQQWindow = async () => {……// 打开视窗之后开始等待brodacast.wait().then(async (oauthObj) => {// 登录成功,关闭通知brodacast.clear()// 执行登录操作oauthLogin(LOGIN_TYPE_QQ, oauthObj)})
}
</script>
06: QQ 登录对接流程:认证是否已注册,完成 QQ 登录流程
有了数据之后,接下来就可以认证当前用户是否已注册,从而判断是否需要进入注册页面。
1. 创建 src/views/login-register/login/oauth.js 模块:
import store from '@/store'
import router from '@/router'
import { message } from '@/libs'
import { LOGIN_TYPE_OAUTH_NO_REGISTER_CODE } from '@/constants'/*** 第三方登录统一处理方法* @param {*} oauthType 登录方式* @param {*} oauthData 第三方数据*/
export const oauthLogin = async (oauthType, oauthData) => {// 触发登录操作。根据登录操作的返回 判断 当前用户是否已经注册。const code = await store.dispatch('user/login', {loginType: oauthType,...oauthData})// 返回 204 表示当前用户未注册,此时给用户一个提示,走注册页面if (code === LOGIN_TYPE_OAUTH_NO_REGISTER_CODE) {message('success', `欢迎您 ${oauthData.nickname},请创建您的账号`, 6000)// 进入注册页面,同时携带当前的第三方数据和注册标记router.push({path: '/register',query: {reqType: oauthType,...oauthData}})return}// 否则表示用户已注册,直接进入首页router.push('/')
}
2. src/store/modules/user.js 中:
/*** 登录*/async login(context, payload) {const { password } = payloadconst data = await loginUser({...payload,password: password ? md5(password) : ''})// QQ 扫码登录,用户未注册if (data.code === LOGIN_TYPE_OAUTH_NO_REGISTER_CODE) {return data.code}context.commit('setToken', data.token)context.dispatch('profile')}
登录接口信息:
登录时也需要头像信息 figureurl_qq_2,这里没展示出来。
3. src/views/login-register/register/index.vue 中:
/*** 触发注册*/
const route = useRoute()const onRegister = async () => {loading.value = truetry {const payload = {username: regForm.value.username,password: regForm.value.password}// 触发注册,携带第三方数据await store.dispatch('user/register', {...payload,...route.query})// 注册成功,触发登录await store.dispatch('user/login', {...payload,loginType: LOGIN_TYPE_USERNAME})} finally {loading.value = false}router.push('/')
}
注册接口信息:
4. src/views/login-register/login/qq-login.vue 中:
……
// 执行登录操作
oauthLogin(LOGIN_TYPE_QQ, oauthObj)
……// 详细上下文代码 在上一小节中。
07: 移动端 QQ 登录对接:触发吊起操作,完成移动端 QQ 登录
目前我们的 QQ 登录功能已经可以在 PC 端中正常使用了。
但是在移动端中进行访问,大家会发现,有一些问题。
出现这个问题的原因是因为:
对于 移动端 而言,通过移动端触发 QQ 登录,会展示三个页面,原页面、QQ 吊起页面、回调页面。
并且移动端一个页面占据整屏,无法直接通过 window.close() 关闭。
因此,在移动端 我们需要在当前页面中,继续进行后续操作。
据此,我们可以在 src/views/login-register/login/qq-login.vue 中执行以下代码:
// QQ 登录挂起
onMounted(() => {QC.Login({btnId: 'qqLoginBtn' //插入按钮的节点id},// 登录成功之后的回调,但是需要注意,这个回调只会在《登录回调页面中被执行》(data, opts) => {// 1. 注销登录,否则在后续登录中会直接触发该回调// 2. 获取当前用户唯一标识,作为判断用户是否已注册的依据// 3. 拼接请求对象// 4. 完成跨页面传输// 针对于 移动端而言:通过移动端触发 QQ 登录会展示三个页面,// 原页面、QQ 吊起页面、回调页面。// 并且移动端一个页面展示整屏内容,且无法直接通过 window.close() 关闭,// 所以在移动端中,我们需要在当前页面继续进行后续操作。oauthLogin(LOGIN_TYPE_QQ, oauthObj)// 5. 在 PC 端下,关闭第三方窗口})
})
window.open() 打开的视窗,在移动端下会以满屏的形式展示。因此,在移动端下,没必要执着于回到原页面。可以在新打开的页面中触发“后续的登录操作”。
08: 微信开放平台大解析
搞定了 QQ 扫码登录之后,接下来我们来处理 微信扫码 登录。
对于微信扫码登录而言,同样需要进行开放平台的注册。本小节将为大家讲解微信开发平台的注册流程。
整个讲解将会分为:
1. 微信公众平台与微信开放平台的区别。
2. 微信开放平台账户注册。
3. 微信开放平台应用注册。
4. 开发者资质认证。
微信公众平台和微信开放平台的区别
微信公众平台
地址:https://mp.weixin.qq.com
作用:用于管理、开发 微信公众号(包括订阅号、服务号、企业号),相当于微信公众号的后台运营、管理系统。
微信开放平台
地址:https://open.weixin.qq.com/
作用:主要面对移动应用、网站应用 开发者,为其提供微信登录、分享、支付等相关权限和服务。
微信开放平台账户注册
1. 进入 微信开放平台,点击账号注册(注意:此账号将同时应用到登录、分享、支付等微信第三方模块)。
2. 填写基本信息。
3. 登记主体信息 - 主体类型说明:
1. 主体信息常用的分为:企业 和 个人。
2. 其中企业又分为:企业 和 个体工商户。
3. 三者之间的区别如下图所示:
个人主体注册
1. 登记主体信息
2. 扫码进行身份验证
3. 点击下一步、确认主体信息
企业主体注册
1. 企业主体注册需要具备 企业营业执照信息。
2. 填写信息,选择 验证方式。
3. 验证方式分为两种:
1. 支付验证:免费,对公转账验证。
2. 微信认证:300元审核费用。
4. 支付验证方式:填写对公账户信息。
5. 扫码确认管理员信息。
6. 最后确认主体信息即可。
7. 企业用户最终还需要进行支付验证,每个注册账号对应的25位收款账号不同。
微信开放平台应用注册
1. 账户注册通过之后,可进入 管理中心,选择 网站应用,点击 创建网站应用。
2. 创建网站应用共分为三步:
1. 填写基本信息。
2. 填写网站信息。
3. 提交成功。
3. 第一步:填写基本信息。
4. 填写基本信息时,需要下载并填写《网站信息登记表扫描件》。
5. 填写完成。
6. 点击下一步,进入 授权回调域 输入。(请填写开发需要的合法域名,用户使用微信账号登录后,只能回调至该域名下的页面)
7. 点击 提交审核。审核通过后,你才可以获得 AppID 和 AppSecret,来进行开发。
8. 审核通过(可能会需要进行多次修改)。
1. 微信登录接口:可用。
2. 微信支付接口:不可用,有坑。
开发者资质认证
应用审核通过之后,大家可以发现应用的 微信登录 与 微信支付 功能处于 未获得 状态。如果想要获得,需要 申请开通。(需要交钱)
1. 点击 申请开通。
2. 此时需要先进行开发者认证。
3. 点击 去认证。
4. 此时会进入到 开发者资质认证页面,在此页面中大家可以看到,想要申请开发者认证,则需要交付 300元 认证费用。
5. 如果你当前需要支付此费用,则点击 现在申请。
6. 之后会进入 协议声明 页面,点击 下一步。
7. 填写企业信息。
1. 填写企业资质信息。
2. 填写对公账户信息。
3. 认证联系人。
4. 联系人验证。
5. 点击下一步
8. 填写发票信息,点击下一步。
9. 确认发票信息无误,点击继续。
10. 支付审核费用。300元。
11. 支付成功之后,会得到对应的订单详情数据。
12. 同时会有对应的邮件通知。
13. 等待审核通过即可。
14. 等待审核的过程中,会有 微信客服 与你电话联系,请注意接听(通常会在当天)
15. 审核通过之后,状态会变为 已验证。
16. 此时,返回应用详情,微信登录 为 已获得 状态,微信支付 为 未获得状态。
到这里,整体的微信开放平台注册流程就已经全部讲解完。
09: 对接微信扫码登录
进入 微信登录对接官方文档
整个微信登录流程与 QQ 登录流程略有不同,分为以下几步:
1. 通过 微信登录前置数据获取 接口,获取登录数据(比如 appId)。
2. 根据获取到的数据,拼接得到 open url 地址。
3. 打开该地址,展示微信登录二维码。
4. 移动端微信扫码确定登录。
5. 从当前窗口中解析 window.location.search 得到用户的 code 数据。
6. 根据 appId、appSecret、code,通过接口获取用户的 access_token。
7. 根据 access_token 获取用户信息。
8. 通过用户信息触发 oauthLogin 方法。
接下来,我们根据以上分析,开发对应代码逻辑:
1. 创建 src/views/login-register/login/weixin-login.vue 组件。
<template><div @click="onWeiXinLogin"><m-svg-icon class="w-4 cursor-pointer" name="wexin"></m-svg-icon><div id="login_container"></div></div>
</template><script setup>
import { getWXLoginData, getWXLoginToken, getWXLoginUserInfo } from '@/api/sys'
import brodacast from './brodacast'
import { oauthLogin } from './oauth'
import { LOGIN_TYPE_WX } from '@/constants'/*** 微信登录成功之后的窗口数据解析*/
if (window.location.search) {const code = /code=((.*))&state/.exec(window.location.search)[1]if (code) {brodacast.send({code})// 关闭回调网页window.close()}
}/*** 触发微信登录*/
const onWeiXinLogin = async () => {// 1. 通过微信登录前置数据获取接口,获取登录数据const { appId, appSecret, redirectUri, scope, state } = await getWXLoginData()// 2. 根据获取到的数据,拼接得到 `open url` 地址window.open(`https://open.weixin.qq.com/connect/qrconnect?appid=${appId}&redirect_uri=${redirectUri}&response_type=code&scope=${scope}&state=${state}#wechat_redirect`,'','height=525,width=585, toolbar=no, menubar=no, scrollbars=no, status=no, location=yes, resizable=yes')// 等待扫码登录成功通知brodacast.wait().then(async ({ code }) => {console.log('微信扫码登录成功')console.log(code)// 微信登录成功,关闭通知brodacast.clear()// 获取 AccessToken 和 openidconst { access_token, openid } = await getWXLoginToken(appId,appSecret,code)console.log('access_token, openid')console.log(access_token, openid)// 获取登录用户信息const { nickname, headimgurl } = await getWXLoginUserInfo(access_token,openid)console.log(nickname, headimgurl)// 执行登录操作oauthLogin(LOGIN_TYPE_WX, {openid,nickname,headimgurl})})
}
</script><style lang="scss" scoped></style>
10: 总结
至此,我们完成了 QQ 扫码登录、微信扫码登录、移动端下的 QQ 主动吊起登录。但是对于 移动端网页 微信APP 而言,我们不能在普通的 H5 下吊起微信 APP 触发登录。
根据本文章的内容可以发现,整个第三方登录逻辑还是比较复杂的。特别是微信的第三方登录步骤更加繁琐。并且我们在调试的时候必须要在线上进行调试(测试环境),所以大家在企业开发时,需要有更大的耐心才可以。