The method of scanning code login is more and more used by current application. Because it does not have to remember the password, as long as the number can be easily and quickly login. This is based on a public platform with the temporary QR Code, and combined with the Swoole WebSocket service to implement the scan code login. This article is mainly to share with you swoole implementation Scan Code login function, hope to help everyone.
With the popularity of the code, the method of login is more and more used in the present application. Because it does not have to remember the password, as long as the number can be easily and quickly login. The open platform natively has the ability to support the scan code login, but most people still use the public platform, so the scan login can only be implemented by itself. Here based on the public platform with the temporary QR Code, and combined with the Swoole WebSocket service to implement the scan code login. The general flow is as follows:
The client opens the login interface and connects to the WebSocket service
Webscoket waiter return to client with parameter QR code
User scan display with parameter QR code
Server callback scan code event and notify developer server
Developer Server notifies WebSocket service
WEBSOCKET Service Notification Client login succeeded
Connecting WebSocket Services
After installing Swoole, we need to use the WebSocket service. Creating a new WebSocket service is 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 is not actually used here, because it is sent by the server, but it must be set to one. If the port number is set below 1024, you must have root privileges, and the server will remember to go to the firewall to open the port.
Generate two-dimensional code with parameters
WebSocket Service After the client connection is successful, you need to generate a QR code with parameters to return to the client display:
$server->on (' Open ', function (Swoole_websocket_server $server, $request) use ($config) { $app = Factory::o Fficialaccount ($config [' WeChat ']); $result = $app->qrcode->temporary ($request->fd); $url = $app->qrcode->url ($result [' ticket ']); $server->push ($request->fd, Json_encode ([ ' message_type ' = ' qrcode_url ', ' url ' + = $ (URL])); });
We generate a temporary QR code in the open callback, and the scene value of the QR code is the file descriptor of the client connection, which guarantees the uniqueness of each client. The effective time is set to 120 seconds to prevent a QR code from being used multiple times. The message push to the client must be JSON to facilitate client processing. The client code is also 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 Sweep Code Event
After the client displays the QR code, the user needs to be prompted to scan the code. For the user to sweep the temporary QR code, will trigger the corresponding callback event, we need to handle the user's sweep code behavior in this callback event. Where we need to use some of the parameters passed over:
Fromusername Sender account (one OpenID) msgtype message type, eventevent event type, Subscribeeventkey event KEY value, qrscene_ as prefix, The parameter values for the two-dimensional code are followed
Note here: has been concerned about the scan code push Eventkey is not qrscene_ prefix, only not focus on scan code and then pay attention to.
After receiving the callback, we first have to do different processing according to different event types:
if ($message [' msgtype '] = = ' event ') { if ($message [' event '] = = ' Subscribe ') {//Follow return $this->subscribe ($ message); } if ($message [' Event '] = = ' unsubscribe ') {//Cancel attention to return $this->unsubscribe ($message); } if ($message [' Event '] = = ' Scan ') { //has been concerned about the code return $this->scan ($message); }} else{ return "Hello!" Welcome to login with Swoolewechat scan;
This is just a matter of business logic that focuses on events, and other codes are self-coding 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, login successful! \ n This is your first%s login, have fun! "; Return sprintf ($msgTemp, $user [' nickname '], $count);}
Here the Eventkey is actually the connection WebSocket client file descriptor, obtains to sweep the code user's open_id, obtains the user information according to the user's open_id, notifies the WebSocket service, responds the text message to.
One of the more troublesome points here is how to notify the WebSocket service, we know that the code to handle the callback is not on the WebSocket service, then how to communicate between different servers? The Swoole official solution has two:
Additional listening for a UDP port
Using Swoole_client as a client access Server
Here we choose the second scenario, Swoole 1.8 supports one Server listening on multiple ports, and we are adding a port to listen on a TCP in 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 primary server is the WebSocket or Http protocol, the newly listening TCP port inherits the protocol settings of the primary server by default, and the new protocol must be set by calling the Set method alone to enable the new protocol
Then we can notify the WebSocket service in the process of the sweep code callback:
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 Login Success
After the WebSocket service receives the login success notification, it can process the user information as needed, then pass the user information to the client's browser to show the results, remember the TCP port we just newly monitored? You can handle it 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 logged-on interface:
Summarize
The whole process is not difficult, the main two difficulties is the corresponding users of the scan code users, the communication between different servers, our solution is to connect the file descriptor as a temporary QR code scene values (here can also use Redis to store mappings), listening to new TCP Port to accept the notification message. Can visit http://wechat.sunnyshift.com/index.php try, remember to use the computer to open.