Scan QR code login method is increasingly used by current applications. Because there is no need to remember the password, as long as you have a WeChat ID, you can log in quickly and easily. This is based on the temporary QR code with parameters on the WeChat public platform, and is combined with Swoole's WebSocket service to achieve scan-code login. This article mainly shares with you Swoole to implement the WeChat code scanning login function, hoping to help everyone.
With the popularity of WeChat, the scanning code login method is increasingly used by current applications. Because you don’t have to remember the password, you can log in quickly and easily as long as you have a WeChat ID. WeChat’s open platform natively supports the function of scanning QR code to log in, but most people still use the public platform, so scanning QR code to log in can only be implemented by themselves. This is based on the WeChat public platform's temporary QR code with parameters, and combines it with Swoole's WebSocket service to implement scan-code login. The general process is as follows:
The client opens the login interface and connects to the WebSocket service
The WebScoket service generates a QR code with parameters and returns it to the customer End
The user scans the displayed QR code with parameters
The WeChat server calls back the scan event and notifies the developer server
The developer server notifies the WebSocket service
The WebSocket service notifies the client of successful login
Connects to the WebSocket service
After installing Swoole, we need to use the WebSocket service. Creating a new WebSocket service is very simple:
$server = new swoole_websocket_server("0.0.0.0", 1099); $server->on('open', function (swoole_websocket_server $server, $request) use ($config){ echo "server: handshake success with fd{$request->fd}\n"; }); $server->on('message', function (swoole_websocket_server $server, $frame) { });
The message callback here is actually not useful, because the server sends messages, but one must be set. If the set port number is lower than 1024, you must have root permissions. Remember to open the port in the firewall on the server.
Generate QR code with parameters
After the WebSocket service successfully connects to the client, it needs to generate a WeChat QR code with parameters and return it to the client for display:
$server->on('open', function (swoole_websocket_server $server, $request) use ($config){ $app = Factory::officialAccount($config['wechat']); $result = $app->qrcode->temporary($request->fd, 120); $url = $app->qrcode->url($result['ticket']); $server->push($request->fd, json_encode([ 'message_type' => 'qrcode_url', 'url' => $url ])); });
In the open callback, we generate a temporary QR code. The scene value of the QR code is the file descriptor of the client connection, so as to ensure the uniqueness of each client. The validity time is set to 120 seconds. , to prevent one QR code from being scanned and used multiple times. When the message is pushed to the client, json is required to facilitate client processing. The client code is also very simple:
const socket = new WebSocket('ws://127.0.0.1:1099'); socket.addEventListener('message', function (event) { var data = JSON.parse(event.data); if (data.message_type == 'qrcode_url'){ $('#qrcode').attr('src', data.url); } });
Callback scan code event
After the QR code is displayed on the client, the user needs to be prompted to scan the code. When a user scans a temporary QR code, WeChat will trigger a corresponding callback event, and we need to handle the user's code scanning behavior in the callback event. Among them, we need to use some parameters passed by WeChat:
FromUserName 发送方帐号(一个OpenID) MsgType 消息类型,event Event 事件类型,subscribe EventKey 事件 KEY 值,qrscene_为前缀,后面为二维码的参数值
One thing to note here: the EventKey pushed by scanning the QR code that has been followed by WeChat does not have the qrscene_ prefix. It can only be found by scanning the QR code and then following it.
After receiving the WeChat callback, we first need to do different processing according to different event types:
if ($message['MsgType'] == 'event'){ if ($message['Event'] == 'subscribe'){ //关注 return $this->subscribe($message); } if ($message['Event'] == 'unsubscribe') { //取消关注 return $this->unsubscribe($message); } if ($message['Event'] == 'SCAN'){ //已关注扫码 return $this->scan($message); } }else{ return "您好!欢迎使用 SwooleWechat 扫描登录"; }
Here we only explain the business logic of one event of concern, and the others are coded by ourselves as needed:
public function subscribe($message){ $eventKey = intval(str_replace('qrscene_', '', $message['EventKey'])); $openId = $message['FromUserName']; $user = $this->app->user->get($openId); $this->notify(json_encode([ 'type' => 'scan', 'fd' => $eventKey, 'nickname' => $user['nickname'] ])); $count = $this->count($openId); $msgTemp = "%s,登录成功!\n这是你第%s次登录,玩的开心!"; return sprintf($msgTemp, $user['nickname'], $count); }
The EventKey here is actually the client file descriptor that connects to WebSocket, obtains the OPEN_ID of the user who scans the QR code, obtains user information based on the user's OPEN_ID, notifies the WebSocket service, and responds to WeChat with a text message.
One of the more troublesome points here is how to notify the WebSocket service. We know that the code for processing WeChat callbacks is not on the WebSocket service. So how do different servers communicate? There are two official solutions given by Swoole:
Listen to an additional UDP port
Use swoole_client as a client to access the Server
Here we choose the second option. Swoole 1.8 version supports one Server to listen to multiple ports. We add a new TCP port to the WebSocket service:
$tcp_server = $server->addListener('0.0.0.0', 9999, SWOOLE_SOCK_TCP); $tcp_server->set([]); $tcp_server->on('receive', function ($serv, $fd, $threadId, $data) { });
The main server is WebSocket or Http protocol. The newly monitored TCP port will inherit the protocol settings of the main Server by default. The set method must be called separately to set the new protocol to enable the new protocol.
Then we can scan the QR code to call back Notify the WebSocket service in the process:
public function notify($message){ $client = new swoole_client(SWOOLE_SOCK_TCP); if (!$client->connect('127.0.0.1', $this->config['notify_port'], -1)) { return "connect failed. Error: {$client->errCode}\n"; } $ret = $client->send($message); }
Notify of successful login
After the WebSocket service receives the notification of successful login, it can process the user information as needed, and then pass the user information to The client's browser displays the results. Do you remember the TCP port we just listened to? It can be processed in the receive event:
$tcp_server->on('receive', function ($serv, $fd, $threadId, $data) { $data = json_decode($data, true); if ($data['type'] == 'scan'){ $serv->push($data['fd'], json_encode([ 'message_type' => 'scan_success', 'user' => $data['nickname'] ])); } $serv->close($fd); });
Last login interface:
Summary
The whole process is not difficult , the two main difficulties are the communication between QR code scanning users and different servers corresponding to connected users. Our solution is to use the connected file descriptor as a temporary QR code scene value (Redis can also be used to store the mapping relationship here) ), listen on the new TCP port to receive notification messages. You can visit http://wechat.sunnyshift.com/index.php to try it out, remember to open it on your computer.
Related recommendations:
How to implement custom WeChat code scanning login style
The idea and code of php to implement WeChat code scanning login
Detailed explanation of PC-side WeChat scan code registration and login example code
The above is the detailed content of Swoole implements WeChat code scanning login function. For more information, please follow other related articles on the PHP Chinese website!