扫码登陆成为一种日趋流行的登陆方式,它具备较高的安全性,同时又使咱们从记忆大量的帐号密码并手动输入的繁琐流程中解脱出来,有些平台甚至无帐号也能扫码登陆,连注册的麻烦都省了。php
对于接入微信开放平台的公众号应用来讲,实现扫码登陆是至关容易的,有 EasyWeChat SDK 加持,再按着官方的文档一把梭,很快就能完成。 然而本文所要讨论的是另外一种状况,有时候出于某些缘由,本身的公众号不能接入开放平台,但又想进行微信扫码登陆,这种状况下显示就不能再换官方的套路来了。但只要咱们稍做变通,就能实现这一需求。html
如下就来介绍一下具体实现,先放效果图。前端
配合本文,我建立了一个简单的示例项目,有兴趣的能够克隆下来,配合源码一块儿服用,效果更佳。项目地址:github.com/tianyong90/…mysql
laravel-echo
和 socket.io-client
前端监听事件广播是关键,咱们须要一个 websocket 服务端,Laravel 官方文档在介绍消息广播时提到了 Pusher 和 laravel-echo-server。由于我使用 laradock 做为开发环境,其中内置了 laravel-echo-server 容器,十分方便,因此决定直接用它。实际上也可使用 Pusher 服务,那么则须要安装 pusher.js 替代 socket.io-client,同时在 .env 中修改相关配置nginx
主要是配置数据库和 redis 链接,而后把 BROADCAST_DRIVER 设置为 redis(这一点很重要,若是使用 pusher 则须要修改成 pusher)laravel
若是 QUEUE_CONNECTION 设置为 redis 了,则须要记得启动队列 worker.git
由于使用 laradock,因此只须要启动时带上 laravel-echo-server 参数就能够了,进入 laradock 目录github
docker-compose up -d nginx php-worker nginx mysql redis laravel-echo-server
复制代码
php artisan make:event WechatScanLogin
复制代码
class WechatScanLogin implements ShouldBroadcast {
use Dispatchable, InteractsWithSockets, SerializesModels;
public $token;
/** * Create a new event instance. * * @param $token */
public function __construct($token) {
$this->token = $token;
}
/** * Get the channels the event should broadcast on. * * @return \Illuminate\Broadcasting\Channel|array */
public function broadcastOn() {
return new Channel(‘scan-login’);
}
}
复制代码
上面最关键的就是事件要实现 ShouldBroadcast 接口并在 broadcastOn 方法中指定要广播的频道。WechatScanLogin 的公开属性 token 会自动包含在广播数据中。web
laravel-wechat 的相关配置和对接,请阅读 EasyWeChat SDK 官方文档。redis
接收扫码的消息并进行相关处理。
public function serve() {
$app = app('wechat.official_account');
$app->server->push(function ($message) {
if ($message['Event'] === 'SCAN') {
$openid = $message['FromUserName'];
$user = User::where('openid', $openid)->first();
if ($user) {
// TODO: 这里根据状况加入其它鉴权逻辑
// 使用 laravel-passport 的我的访问令牌
$token = $user->createToken($user->name)->accessToken;
// 广播扫码登陆的消息,以便前端处理
event(new WechatScanLogin($token));
\Log::info('haha login');
return '登陆成功!';
}
return '失败鸟';
} else {
// TODO: 用户不存在时,能够直接回返登陆失败,也能够建立新的用户并登陆该用户再返回
return '登陆失败';
}
}, \EasyWeChat\Kernel\Messages\Message::EVENT);
return $app->server->serve();
}
复制代码
public function index() {
$wechat = app('wechat.official_account');
$result = $wechat->qrcode->temporary('foo', 600);
$qrcodeUrl = $wechat->qrcode->url($result['ticket']);
return view('index', compact('qrcodeUrl'));
}
复制代码
<img src={{ qrcodeUrl }} />>
复制代码
import Echo from 'laravel-echo'
import io from 'socket.io-client'
window.io = io
let EchoInstance = new Echo({
broadcaster: 'socket.io',
host: window.location.hostname + ':6001',
})
EchoInstance.channel('scan-login').listen('WechatScanLogin', e => {
localStorage.setItem('my_token', this.token)
// 其它处理
})
复制代码
至此,简单的扫码登陆就完成了。固然,本文示例代码不怎么优雅、流程可能也有不完善的地方,主要是为了提供一个大体思路。有了这个思路,咱们能够实现其它诸如扫码签到、扫码投票等各类功能,具体如何就看你们的创意了。
最后放上我的博客地址:tianyong90.com/, 欢迎各位大佬批评指正。