关于接入微博登录的代码实现

今天尝试使用了微博登录的接口,也是即将使用接入微信登录,QQ登录,手机号登录、用户名登录等支持多种操作的问题

微博的接口特别简单明了,文档也挺清晰的。

采用了OAuth2.0 的方式

请求授权 - 获取code - 使用token获取access_token+uid - 使用access_token+uid 获取用户的信息

操作流程如下:

  1. 申请网站接入

    http://open.weibo.com/connect - 立即创建 - 应用地址填写你的本地测试的地址即可,其他都是正常操作

  2. 使用文档操作

    http://open.weibo.com/wiki/%E9%A6%96%E9%A1%B5 - 文档中心

    http://open.weibo.com/wiki/Connect/login - 微博登录详情

    http://open.weibo.com/wiki/2/users/show - 获取用户信息接口

  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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,837评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,551评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,417评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,448评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,524评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,554评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,569评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,316评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,766评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,077评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,240评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,912评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,560评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,176评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,425评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,114评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,114评论 2 352

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,647评论 18 139
  • "use strict";function _classCallCheck(e,t){if(!(e instanc...
    久些阅读 2,028评论 0 2
  • 在分布式环境中,如何支持PC、APP(ios、android)等多端的会话共享,这也是所有公司都需要的解决方案,用...
    安琪拉_4b7e阅读 1,724评论 2 7
  • 人之所以活得累,是因为想得太多。身体累不可怕,可怕的是心累。每个人都有被他人牵累,为自己负累的时候,只不过有些人会...
    哈哈楼哈哈阅读 136评论 0 0
  • 咖啡之于我主要就是功能型饮料。一开始是为了提神,口味上喜欢喝牛奶和咖啡的交融口感,比如拿铁和卡布奇诺,不希望放糖。...
    William孙筱奇阅读 925评论 1 4