利用臨時二維碼實如今電腦瀏覽器上的微信掃碼登錄功能 - EasyWeChat版

這個方法最開始用在尚未「微信開放平臺」的時候,如今也有很多網站在用,簡單說就是生成一個臨時二維碼放到服務器,而後微信掃描二維碼後將該值傳遞給服務器進行比對,實現登錄,和手機動態碼登錄思路相似。php

流程說明

先把咱們要實現的步驟說下:html

  • 用戶訪問微信登錄頁面,程序生成一個臨時二維碼。web

  • 用戶使用微信掃描剛生成的二維碼。瀏覽器

  • 掃碼後微信發送二維碼所含內容給網站程序。服務器

  • 客戶端每隔N秒(或填寫)將第一步的二維碼內容和網站從微信接收的二維碼內容比對,若是找到則登錄成功。微信

準備工做

因臨時二維碼生成和掃碼操做須要用到公衆帳號通信接口,所以咱們先配置它(微信相關頁面)。首先在@app/controllers/下新建一個名爲WxController.php的控制器文件而且定義一個actionIndex來處理和微信之間的交互,以下面代碼:yii2

namespace app\controllers;

use Yii;
use yii\web\Controller;
use EasyWeChat\Foundation\Application;// 引入EasyWeChat

class WxController extends Controller {

    /**
     * 服務器與微信通信處理接口
     * @author abei<abei@nai8.me>
     */
    public function actionIndex(){
        /*
         * 'WECHAT'=>[
         *      'appId'=>'xxx',
         *      'appSecret'=>'xxxxx',
         *      'token'=>'nai8_me'
         * ]
         */
        $options = Yii::$app->params['WECHAT'];
        $app = new Application($options);

        $response = $app->server->serve();
        $response->send();
    }
}

根據微信文檔,首先咱們須要經過服務器驗證。app

$response = $app->server->serve();
$response->send();

這段代碼就是處理和微信響應的,咱們在測試平臺填寫action的url和tokenyii

alt

當配置驗證經過後,咱們再對微信服務器發過來的各類請求作相應處理,好比傳過來一個文本,好比一次二維碼掃描,好比一個地理位置,好比等等。關於EasyWechat對於和微信服務器交互的文檔能夠查看以下地址。函數

https://easywechat.org/zh-cn/...

https://easywechat.org/zh-cn/...

接下來咱們來處理微信發過來的請求,在本文檔裏咱們要處理的是掃描二維碼後的接收事件,固然掃描二維碼根據當前微信是否關注公衆號返回的是不一樣的,因篇幅問題,咱們只說關注後的狀況。

增長功能後的代碼以下

namespace app\controllers;

use Yii;
use yii\web\Controller;
use EasyWeChat\Foundation\Application;// 引入EasyWeChat

class WxController extends Controller {

    public $wxApp;

    /**
     * 服務器與微信通信處理接口
     * @author abei<abei@nai8.me>
     */
    public function actionIndex(){
        $options = Yii::$app->params['WECHAT'];
        $app = new Application($options);

        $server = $app->server;
        $this->wxApp = $app;

        $server->setMessageHandler(function ($message) {
            switch ($message->MsgType) {
                case 'event':// SCAN & subscribe
                    return $this->doEvent($message);
                    break;
            }
        });

        $response = $server->serve();
        $response->send();
    }

    /**
     * 處理事件
     * @param $message
     * @author abei<abei@nai8.me>
     */
    protected function doEvent($message){
        switch ($message->Event) {
            case 'SCAN':
                return $this->doScan($message);
                break;
        }
    }

    /**
     * 處理具體掃描事件
     * @param $message
     * @author abei<abei@nai8.me>
     */
    protected function doScan($message){
        $key = $message->EventKey;
        $openId = $message->FromUserName;
        return $openId;
    }
}

爲防止函數過長,咱們拆分爲幾個小方法處理,同時增長一個叫作$wxApp的變量表明本次交互,串聯每一個函數。

咱們準備工做暫時到這裏,下面用到的時候再說。

生成臨時二維碼

如今咱們經過 EasyWeChat 來生成一個臨時二維碼,那就定義一個叫作 actionQrcode 的函數吧。

namespace app\controllers;

use Yii;
use yii\web\Controller;
use EasyWeChat\Foundation\Application;// 引入EasyWeChat

class WxController extends Controller {
    public $wxApp;

    ...

    public $enableCsrfValidation = false;

    /**
     * 生成一個臨時二維碼
     * @author abei<abei@nai8.me>
     */
    public function actionQrcode(){
        $options = Yii::$app->params['WECHAT'];
        $app = new Application($options);
        $qrcode = $app->qrcode;

        $rand = mt_rand(100000,999999);
        $result = $qrcode->temporary($rand, 6 * 24 * 3600);
        $ticket = $result->ticket;// 或者 $result['ticket']
        $url = $qrcode->url($ticket);
    
        return $this->render('qrcode',[
            'url'=>$url,
            'rand'=>$rand
        ]);
    }
}

actionQrcode 方法將一個隨機的6位數字放到了臨時二維碼中,這裏要說明有兩點

  • $url 即爲二維碼圖片地址,在視圖裏直接用img 標籤接收便可。

  • 除了微信服務器驗證爲GET請求,其餘的事件均爲POST請求,可是yii2默認對於POST提交是進行crsf驗證的,所以爲了有效的接收微信服務器給咱們的推送信息,咱們須要關閉crsf驗證。

public $enableCsrfValidation = false; // 我就是用來關閉crsf驗證滴

這樣咱們就生成了一個含有$rand值的二維碼,對於如何使用完成登錄方法不少,我這裏使用瀏覽器請求方式,在actionQrcode的視圖內,我填寫以下代碼

<img src="<?= $url;?>" alt="">
<script>
    //todo 每隔N秒鐘向程序發起一次請求,詢問一個叫作wx_qrcode的數據表是否有含有$rand的記錄,若是有則php完成登錄,瀏覽器跳轉到好比我的中心等頁面
</script>

那麼接下來就是這個叫作wx_qrcode的表如何設計以及記錄如何產生的問題了。

重要的wx_qrcode表

若是你看了微信文檔必定知道,當咱們使用微信掃描臨時二維碼的時候,微信除了告訴咱們服務器二維碼所表明的$rand隨機數字外,還有一個叫作$openId的標識,它表明掃碼微信的惟一身份,所以咱們設計了wx_qrcode表,裏面含有open_id和rand。

思路是這樣的

  • 掃碼後程序接到微信傳遞過來的open_id和rand隨機碼,進行會員初始化工做,同時往wx_qrcode表內存此記錄。

  • 程序接到瀏覽器請求,根據請求中的rand隨機碼來查詢wx_qrcode,若是找到記錄,則找到了open_id,也就找到了此會員,而後使用Yii::$app->user->login()方法進行登陸受權,而後刪除該記錄後返給瀏覽器登陸成功,不然返回失敗,繼續讓瀏覽器N秒後詢問。

也就是說咱們須要修改第一步裏的微信掃碼處理程序,作簡單處理。

namespace app\controllers;

use Yii;
use yii\web\Controller;
use EasyWeChat\Foundation\Application;// 引入EasyWeChat

class WxController extends Controller {

    public $wxApp;

    public $enableCsrfValidation = false;

    ...

    /**
     * 處理具體掃描事件
     * @param $message
     * @author abei<abei@nai8.me>
     */
    protected function doScan($message){
        $key = $message->EventKey;
        $openId = $message->FromUserName;
        
        $user = User::find()->where(['open_id'=>$openId])->one();
        if($user == false){
            //todo 新建會員
        }
        
        $wxQrcode = new WxQrcode();
        $wxQrcode->open_id = $openId;
        $wxQrcode->rand = $key;
        $wxQrcode->save();
    }
}

這只是一個思路,各位兄弟根據本身系統的狀況須要更加完善這塊的邏輯,反正這個掃描的接收,咱們須要填充wx_qrcode記錄,讓瀏覽器來詢問。

ok,接下來我再說下PHP如何處理瀏覽器諮詢的邏輯

public function actionAsk(){
        $rand = Yii::$app->request->get('key');
        $check = WxQrcode::find()->where(['rand'=>$rand])->one();
        if($check){
            $user = User::find()->where(['open_id'=>$check->open_id)->one();
            Yii::$app->user->login($user);
            
            $check->delete();
            
            return Json::encode(['done'=>true]);
        }else{
            //todo 不作什麼,讓瀏覽器繼續問。
        }
    }

總結一下

掃碼登錄有不少,好比生成二維碼後不進行視圖的循環,而是掃碼後以動態碼形式用模板消息等發給微信,微信在頁面添加動態碼實現驗證登錄,就像兄弟連的微信登錄同樣。

方法不少,核心就一條,就是利用二維碼的內容進行PC和微信之間的傳遞。

更多yii文章歡迎來個人博客 http://nai8.me

相關文章
相關標籤/搜索