网站应用接入微信登录可以使用户更加快捷的参与到应用的深层次交互中来,大大降低了用户登陆的繁琐性。网站应用微信登录是基于OAuth2.0协议标准构建的微信OAuth2.0授权登录系统。所谓OAuth2.0模式简单来说就是:授权码模式,即通过授权方的code换token,登录方通过token获取用户信息,来实现登录的方式。

前端微信授权登陆时序图

在前端界面方面,我们需要生成二维码页面,移动端微信跳转确认登陆页;服务端方面,需要添加websocket服务实时响应扫码信息。如上面的时序图,PC页面获取相关信息生成二维码,并连接websocket服务实时响应授权状态,微信扫描二维码跳转至确认登陆页面,微信端页面确认登陆后PC页面监听到websocket服务返回确认登陆的标识,PC页面通过标识调用登陆接口获取token及用户信息,整个流程完成。

本篇案例采用vue emementUi开发,只摘取部分核心代码。

1.PC端页面布局

canvas二维码容器和三种二维码状态遮罩。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
<!--微信扫码登陆部分-->
<div>
<div>
<div class="imgWrap">
<div class="failQr" v-if="isFailQr">
<span>二维码已失效</span>
<el-button size="mini" type="primary" @click="getWxLogin">点击刷新</el-button>
</div>
<div class="failQr qrConfirm" v-if="isConfirm">
<span>扫码成功,等待确认</span>
</div>
<div class="failQr qrConfirm" v-if="onLogin">
<span>登录成功,正在跳转!</span>
</div>
<!--<img id="QrCode" src="http://zhongweipeng.cn/timg.jpg">-->
<canvas id="canvas"></canvas>
</div>
</div>
<p class="scrpText">打开手机微信,扫一扫登陆</p>
</div>

<!--部分样式-->
<style>
.imgWrap{
padding: 15px;
background-color: #fff;
width: 207px;
height: 207px;
margin: 30px auto 0;
position: relative;
}
.imgWrap canvas{
display: block;
width: 207px !important;
height: 207px !important;
margin: 0 auto;
}
.scrpText{
font-size: 12px;
color: #fff;
text-align: center;
}
.failQr{
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(255, 255, 255, 0.7);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.qrConfirm{
background-color: rgba(255, 255, 255, 0.8);
color: #0880fd;
font-weight: bold;
}
.failQr span{
margin-bottom: 6px;
}
</style>

2.PC端JS代码

使用qrcode插件来生成canvas二维码,然后利用二维码code来连接websocket服务,监听授权登录状态。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import QRCode from 'qrcode';

export default {
data() {
return {
isFailQr: false, /*失效二维码*/
isConfirm: false, /*扫码成功等待*/
onLogin: false, /*登陆成功*/
failQr_time: 300, /*失效时间*/
qrCode: '', /*微信二维码返回的code*/
};
},
mounted() {
this.getWxLogin();
this.handleFailQr();
},
methods: {
// 获取后台信息并生成二维码
getWxLogin(){
let that = this;
this.$axios.get(`/api/getQrInfo`)
.then(function (res) {
if (res.code) {
that.qrCode = res.code;
that.$nextTick(() => {
let canvas = document.getElementById('canvas')
QRCode.toCanvas(canvas, res.url, function (error) {
if (error) console.error(error);
that.getQrCode(); // 连接wss
console.log('QRCode success!');
})
})

} else {
this.$message({
message: res.msg,
type: 'error',
});
}
})
.catch(function (error) {
console.log(error);
});

this.isFailQr = false;
this.handleFailQr();
},
getQrCode(){
let that = this;
let wsuri = `wss://api.net/wss/${this.qrCode}`; //带上返回的qrcode连接websocket服务
let websock = new WebSocket(wsuri);
websock.onmessage = function(e){
that.websocketOnMessage(e);
}
// websock.onclose = function(e){
// // websocketclose(e);
// }
// websock.onopen = function () {
// // websocketOpen();
// }
//连接发生错误的回调方法
websock.onerror = function () {
console.log("WebSocket连接发生错误");
}
},
//数据接收
websocketOnMessage(e){
// console.log(JSON.parse(e.data), 'data')
let data = JSON.parse(e.data);
if(data.action === "scan"){ // 扫码成功
clearInterval(this.failQr_timetimer);
this.isFailQr = false;
this.isConfirm = true;
}else if(data.action === "successLogin"){ // 登录成功
this.onLogin = true;
console.log(data, '登陆成功返回的信息');
// ...
// 执行的登陆操作 保存用户信息token等...
// ...
}
},
//二维码失效操作
handleFailQr(){
this.failQr_time = 301;
this.failQr_timetimer = setInterval(()=>{
this.failQr_time--;
if(this.failQr_time <= 0){
this.isFailQr = true;
clearInterval(this.failQr_timetimer);
}
}, 1000);
},
}
};

3.h5移动端处理

扫码后跳转的移动页面比较简单,所以这里简略描述一下,授权登录页按钮触发授权登录操作,通过请求回调成功数据判断状态显示。

4.微信端确认登陆,PC端登陆成功

这个步骤其实在服务端过程比较复杂,但是对于用户来说感觉不到什么。首先,微信服务端判断登录成功重定向到登录成功的页面,后台服务端接收到微信服务端登录成功返回的code,后台服务端使用code向微信服务端获取token,后台服务端在是使用token向微信服务端获取用户信息,返回给客户端操作,至此,整个操作完成。