1. 程式人生 > >PHP微信掃描登陸(模擬微信企業號平臺登陸)

PHP微信掃描登陸(模擬微信企業號平臺登陸)

最近在做一款基於微信公眾號的管理系統,我們為公司的微信公眾號提供後臺管理功能,此係統能夠實現關注人資訊的上傳和下載,能實現資訊的推送,以及實現一些公司業務相關的功能。鑑於此係統緊密的微信公眾號結合,而且能夠給關注公眾號的人推送資訊,於是在系統的安全上就有別於其他的系統,同時系統也需要使用者的微信資訊,於是我們決定使用類似於微信企業號的登陸機制(微信企業號)。

準備工作:在決定使用這套登陸機制以後,我們開始根據微信公眾號提供的文件進行開發,微信掃描二維碼登陸的業務邏輯可簡單歸結如下:使用者掃描二維碼——後臺驗證此微信使用者是否存在——跳轉輸入密碼——驗證密碼進行登陸。看似簡單的幾個業務邏輯,實則在開發中遇到不少問題。在進行正式的開發前,我們需要確定以下幾個必要的工作:

1. 我們的微信公眾號是否獲得高階許可權,微信掃描登陸需要(OAuth2.0網頁授權許可權)。高階許可權的獲得,需要進行微信認證,提供公司相關資料,繳納一定費用。

設定—微信認證


2.在獲得OAuth2.0網頁授權許可權以後我們查閱微信公眾號提供的文件(OAuth2.0網頁授權)我們需要對此許可權進行相關配置,首先我們需要配置授權回撥域名

開發者中心——介面許可權表(網頁服務)


3.配置好OAuth2.0網頁授權許可權,我們需要了解一個微信公眾號的第三方平臺——微信開放平臺,在我們的業務中,我們需要使用微訊號作為我們網站登陸、移動端登陸的賬號,因此我們選擇了微信開放平臺,來進行我們賬號的統一,此處我們需要介紹一下微信開放平臺:

微信開發平臺主要用於將微信服務號、網站應用、移動應用統一起來,在微信開放平臺進行註冊繫結相關應用稽核以後我們可以獲得一個UnionID,我們可以通過這個id在不同應用中唯一標識我們的使用者。同時我們的微信登陸的功能還需要使用微信開放平臺提供的介面:


同時微信開放平臺下提供了更多的高階介面,需要在第三方平臺處申請。

在這個地方筆者出現了幾個問題並再多次閱讀文件後得到解決:

(1)通過開放平臺下的文件,配置wxLogin的時候,對於scope引數,只能填寫snsapi_login,填寫其他的比如(微信公眾平臺文件中的snsapi_base、snsapi_userinfo)會出現報錯。解決方案:在開放平臺中,擁有另外一種機制來獲取高階許可權的access_token,換句話說此處填寫

snsapi_login即可,而反覆測試下,通過此二維碼跳轉的code換取的access_token無法請求高階介面,我們應該在管理中心——公眾號第三方平臺配置申請許可權,則可以使用access_token去請求高階介面。

(2)在配置wxLogin的時候,根據文件我們配置的appid、secret均為微信開放平臺下申請網站應用的appid,而此appid在微信公眾號下也是可用的,所以我們可以通過此appid和擁有許可權的access_token去請求高階介面,獲得使用者資訊。

注意:微信開放平臺需要繳納相關費用進行材料稽核,如果有需求完成微信掃描登陸、不同應用間的賬號統一,那麼這個費用是必須的。

在完成好以上三個步驟以後我們就可以正式進行微信掃描登陸的業務開發了。

頁面開發:可以根據微信開放平臺提供的js,就可以獲得登陸時掃描的二維碼。程式碼示例:

<script src="<?=site_url()?>source/jquery/jquery-1.7.2.min.js"></script> 
 <script src="http://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js"></script>
<script>
var obj = new WxLogin({
        id:"login_container",
        appid: "APPID",
        scope: "snsapi_login",
        redirect_uri: "URL",
        state: state,
        style: "balck"
    });
</script>
這裡的id即為你需要放置二維碼的div的id,state引數則是配合你自己網站的安全機制,還有一個href引數,來調整二維碼的樣式。

使用者掃描二維碼,同意授權登陸以後,網站會自動跳轉至你填寫的回撥URL,此URL可以是你後臺的控制器當中,根據接收的code引數,後臺模擬https請求,獲得使用者的union_id,進行使用者驗證,如果使用者存在,則跳轉至密碼輸入頁面,如果不存在,則跳轉至失敗頁面。程式碼示例:

    public function admin_login() {
        //如果存在session直接訪問登陸介面
        if(!empty($this->session->userdata('weixin_name'))){
            if($this->session->userdata('weixin_name') != "not_exist"){
                $weixin_name = $this->session->userdata('weixin_name');
                $time = substr($weixin_name,strlen($weixin_name)-strlen(date("Y-m-d H:i:s")),strlen(date("Y-m-d H:i:s")));
                if(time()-strtotime($time)<5*60){
                    $data['login_frame'] = "login_first_suc";
                    $this->load->view("login",$data);
                }else{
                    $this->session->unset_userdata('weixin_name');
                    $login_url = URL;
                    header("Location:".$login_url);
                }
            }else{
                $data['login_frame'] = "login_error";
                $this->load->view("login",$data);
            }
        }else{
            $state_str = $this->input->get("state");
            if($state_str){
                if($state_str == md5($this->config->item('kaifang')['state'])){
                    $code = $this->input->get("code");
                    $user_access = $this->wei_model->get_access_token_from_web($code);
                    if($user_access){
                        if($username = $this->login_model->check_weixin_user($user_access)){
                            $this -> session -> set_userdata("weixin_name",$user_access->unionid.date("Y-m-d H:i:s"));
                        }else{
                            $this -> session -> set_userdata("weixin_name","not_exist");
                        }
                    }else{
                        $this -> session -> set_userdata("weixin_name","not_exist");
                    }
                }else{
                    //非法登陸
                    $this -> session -> set_userdata("weixin_name","not_exist");
                }
                $login_url = URL;
                header("Location:".$login_url);
            }else{
                $data['login_frame'] = "login_weixin";
                $this->load->view("login",$data);
            }
        }
    }
其中,我將weixin_name進行了session處理,同時對state引數進行了簡單的md5加密驗證。

到此為止,微信掃描二維碼登陸的業務邏輯就算完成了,博主用了幾天的時間才把文件讀透,實現了相關的業務邏輯和許可權控制。如果大家還有什麼不明白的地方,可以留言交流。