關於接入微博登入的程式碼實現

surest發表於2019-02-16

關於接入微博登入的程式碼實現

今天嘗試使用了微博登入的介面,也是即將使用接入微信登入,QQ登入,手機號登入、使用者名稱登入等支援多種操作的問題

微博的介面特別簡單明瞭,文件也挺清晰的。

採用了OAuth2.0 的方式

請求授權 – 獲取code – 使用token獲取access_token+uid – 使用access_token+uid 獲取使用者的資訊

操作流程如下:

1) 申請網站接入

http://open.weibo.com/connect – 立即建立 – 應用地址填寫你的本地測試的地址即可,其他都是正常操作

2) 使用文件操作

http://open.weibo.com/wiki/%E… – 文件中心

http://open.weibo.com/wiki/Co… – 微博登入詳情

http://open.weibo.com/wiki/2/… – 獲取使用者資訊介面

3) 程式碼實現

我這裡沒有使用自帶的微博 phpsdk

使用了https://github.com/guzzle/guzzle 來模擬請求

為了可擴充套件性接入其他支付,我公用了一個配置檔案


    return [
        `log` => [
            `file` =>storage_path(`logs/login/`.date(`Y-m-d`) . `.php`)
        ],
       `weibo` => [
           // 微博登入相關key
           `w_key` => ENV(`W_KEY`,``),
           `w_secret` => ENV(`W_SECRET`,``),
           `w_get_code_url` => `https://api.weibo.com/oauth2/authorize?client_id=%d&response_type=code&redirect_uri=%s`,
           `w_get_access_token_url` => `https://api.weibo.com/oauth2/access_token?client_id=%d&client_secret=%s&grant_type=authorization_code&redirect_uri=%s&code=%s`,
           `w_user_url` => `https://api.weibo.com/2/users/show.json`
       ]
    ];
    

相關配置url 採用sprintf的方式進行拼接


核心程式碼如下:

控制器程式碼 –


    namespace AppHttpControllersAuth;
   
    use AppHttpTraitsLoginWeiboHandler;
    use IlluminateHttpRequest;
    
    class LoginWeiboController extends BaseController
    {
        use LoginWeiboHandler;
    
        /**
         * 微博登入
         * 調起微博登入 - 獲取code - 攜帶code請求accessToken - 攜帶token獲取使用者資訊
         */
        public function login(Request $request)
        {
            $code = $request->code;
            if (!$code) {
                return $this->getCode();
            }
            $result = $this->setGetWbAccessToken($code);
            $access_token = $result[`access_token`];
            $uid = $result[`uid`];
            return $this->user($access_token,$uid);
            // 獲取使用者資訊
    
        }
    
        public function user($access_token,$uid)
        {
            $userInfo = $this->getUserInfo($access_token,$uid);
            // 執行登入操作
            $this->store($uid,`weibo`,$userInfo);
        }
    
    }
    

實現類程式碼 –


    namespace AppHttpTraits;
    use GuzzleHttpClient;
    use GuzzleHttpExceptionClientException;
    use AppExceptionsLoginException;
    
    /**
     * 處理微博登入邏輯
     * Class LoginWeiboHandler
     * @package AppHttpTraits
     */
    trait LoginWeiboHandler
    {
        private $key;
        private $secret;
        private $getCodeUrl;
        private $getAccessTokenUrl;
        private $host;
        private $client;
    
        public function __construct()
        {
            $this->client = new Client();
            $this->key = config(`login.weibo.w_key`);
            $this->secret = config(`login.weibo.w_secret`);
            $this->getCodeUrl = config(`login.weibo.w_get_code_url`);
            $this->getAccessTokenUrl = config(`login.weibo.w_get_access_token_url`);
            $this->host = route(`login.weibo`);
        }
    
        /**
         * 設定 獲取 code的url
         * @return string
         */
        public function setWbCodeUrl()
        {
            $url = sprintf($this->getCodeUrl,$this->key,$this->host);
            return $url;
        }
    
        /**
         * @param $code string 授權後取得的code值
         */
        public function setGetWbAccessToken($code)
        {
            if( !$code ) {
                throw new LoginException([
                    `message` => `CODE不存在`
                ]);
            }
            $url = sprintf($this->getAccessTokenUrl,$this->key,$this->secret,$this->host,$code);
            try{
                $res = $this->client->request(`POST`,$url)->getBody();
            }catch (ClientException $e){
                // 處理錯誤
                throw new LoginException([
                    `message` => `CODE已經失效`
                ]);
            }
            return json_decode($res,true);
        }
    
        /**
         * 獲取code
         * @return IlluminateHttpRedirectResponse
         */
        public function getCode()
        {
            $getCodeUrl = $this->setWbCodeUrl();
            return redirect()->away($getCodeUrl);
        }
    
        /**
         * 獲取使用者資訊介面
         * @param $access_token
         * @param $uid
         * @return mixed
         * @throws LoginException
         * @throws GuzzleHttpExceptionGuzzleException
         */
        public function getUserInfo($access_token,$uid)
        {
            $arr = [
                `access_token` => $access_token,
                `uid` => $uid
            ];
    
            $url = config(`login.weibo.w_user_url`) . `?` .http_build_query($arr);
            $res = $this->client->request(`GET`,$url);
            try{
                $res = $this->client->request(`GET`,$url)->getBody();
            }catch (ClientException $e){
                // 處理錯誤
                throw new LoginException([
                    `message` => `請求微部落格戶端出現問題,請選擇更換登入方式`
                ]);
            }
            return json_decode($res,true);
    
        }
    }

4) 程式碼分析

控制器程式碼中,方法 getCode 用來調去微博登入,他會進入到請求授權的介面,當你授權第一次後或者保持登入後,會直接忽略授權頁面,直接返回code。

程式碼中有個邏輯,一個是喚起登入;一個是處理code,再次呼叫獲取access_token + uid

當code不存在時,表明當前需要請求授權,使用getCode方法,這個方法採用的是GET請求,會自動返回一個string資訊,通過你傳遞的 redirect_uri 來決定返回到哪個頁面(redirect_uri再我的應用-應用資訊-高階資訊中可以看到) ,
所以需要使用重定向的方式來獲取資料

code存在時,使用 setGetWbAccessToken 方法獲取 access_token + uid的值,setGetWbAccessToken 方法採用post請求,返回的是一個json引數,需要自己轉義,不會自動重定向,直接返回資料

access_token 、code 是動態的 uid是唯一的

獲取 access_token 請求使用者資訊介面,getUserInfo,使用GET方法傳遞兩個值即可,如果請求報錯,容易出現錯誤,期待使用錯誤捕獲


關於使用者表的設計,以及多欄位登入的方式和方法我會再明天發出來

轉載請聯絡本人,唯一原創

來自於: http://surest.cn/article/46

相關文章