關於接入微博登陸的代碼實現

關於接入微博登陸的代碼實現

今天嘗試使用了微博登陸的接口,也是即將使用接入微信登陸,QQ登陸,手機號登陸、用戶名登陸等支持多種操做的問題php

微博的接口特別簡單明瞭,文檔也挺清晰的。git

採用了OAuth2.0 的方式github

請求受權 - 獲取code - 使用token獲取access_token+uid - 使用access_token+uid 獲取用戶的信息json

操做流程以下:api

1) 申請網站接入微信

http://open.weibo.com/connect - 當即建立 - 應用地址填寫你的本地測試的地址便可,其餘都是正常操做post

2) 使用文檔操做測試

http://open.weibo.com/wiki/%E... - 文檔中心網站

http://open.weibo.com/wiki/Co... - 微博登陸詳情ui

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 App\Http\Controllers\Auth;
   
    use App\Http\Traits\LoginWeiboHandler;
    use Illuminate\Http\Request;
    
    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 App\Http\Traits;
    use GuzzleHttp\Client;
    use GuzzleHttp\Exception\ClientException;
    use App\Exceptions\LoginException;
    
    /**
     * 處理微博登陸邏輯
     * Class LoginWeiboHandler
     * @package App\Http\Traits
     */
    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 \Illuminate\Http\RedirectResponse
         */
        public function getCode()
        {
            $getCodeUrl = $this->setWbCodeUrl();
            return redirect()->away($getCodeUrl);
        }
    
        /**
         * 獲取用戶信息接口
         * @param $access_token
         * @param $uid
         * @return mixed
         * @throws LoginException
         * @throws \GuzzleHttp\Exception\GuzzleException
         */
        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

相關文章
相關標籤/搜索