釘釘掃碼登錄-PHP版本

  • 2020 年 4 月 10 日
  • 筆記

今天寫了一個第三方登錄的功能,使用的是釘釘,實現的功能就是打開網頁,使用的釘釘APP掃描二維碼,快捷登錄網站,下面一起來看一下!

釘釘開放平台

首先,登錄管理後台,點擊右上角進行登錄,這裡的登錄需要是管理員身份或者授權許可權的子管理員身份,其他的身份不好使,如果沒有管理員身份或子管理員身份(如我一樣),那麼就只能自己創建一個團隊了,裡面邀請了好友就可以了。這樣你就是擁有管理員身份了。繼而可以登錄這個管理後台了(第一次登錄需要設置個密碼,後續登錄時需要輸入的)。

創建應用

進入管理頁面後,我們進入應用開發菜單,找到最下方的「移動接入應用」,進入子級菜單中的「登錄」,在裡面創建一個應用。如下圖:

創建應用後,回到頁面中,我們可以看到 appid 和 appSecret 這兩項參數,後續我們會用到。

授權流程

第三方發起釘釘授權登錄請求,釘釘用戶允許授權第三方應用後,釘釘會拉起應用或重定向到第三方網站,並且帶上授權臨時票據code參數。

通過code調用介面getuserinfo_bycode獲取授權登錄用戶資訊。

構造掃碼登錄頁面

構建登錄頁面有兩種方式,我們以跳轉方式為例,這種方式使用得較多,也非常方便。在企業Web系統里,用戶點擊使用釘釘掃描登錄,第三方Web系統跳轉到如下地址:地址就不做展示了,說一下地址的參數:

獲取用戶資訊

首先說一下,我們獲取到的用戶資訊只有三項,如下表:

但是在下午的實際測試中發現,介面返回的值還多了兩項,文檔中沒有做出說明,猜測是許可權欄位和許可權標識欄位。

在獲取用戶資訊時我們要使用到的參數有如下:

在請求的時候需要使用POST方式並傳遞數據,數據如下:

{"tmp_auth_code": "23152698ea18304da4d0ce1xxxxx"}

這裡需要注意一點,傳遞數據為json格式,如果使用CURL進行請求時會出現post請求數據格式錯誤的提示,我們需要在curl請求頭上面做出說明,程式碼如下:

$header = [ "Content-Type: application/json; charset=utf-8", "Content-Length:" . strlen(json_encode($postFields)) ];  curl_setopt($ch, CURLOPT_HTTPHEADER, $header);

程式碼

<?php  /**   * Created by PhpStorm.   * User: Administrator   * Date: 2020/4/3 0003   * Time: 11:27   */    namespace appcontroller;    use thinkController;    class Login extends Controller  {      /**       * 登錄       * @return thinkresponseView       */      public function index()      {          // 臨時關閉模板布局          $this->view->engine->layout(false);          return view("login/index");      }        public function out()      {      }          public function back()      {          $code  = input('get.code');          $state = input('get.state');          if(!$code or !$state) {              $this->error('參數缺失');          }          if($state > time()) {              $this->error('參數異常');          }            $accessKey = 'dingoa9f8qj1**********';          $timestamp = $this->mTime();          $signature = $this->signature($timestamp);          $url       = 'https://oapi.dingtalk.com/sns/getuserinfo_bycode?accessKey=' . $accessKey . '&timestamp=' . $timestamp . '&signature=' . $signature;          $data      = [ 'tmp_auth_code' => $code ];          $userInfo  = $this->curl_json($url, $data);          $res       = json_decode($userInfo, true);            if(isset($res['errcode']) and $res['errcode'] == 0) {              //登錄成功              echo 1;          }      }          /**       * 計算簽名       * @param $timestamp       * @return string       */      public function signature($timestamp)      {          // 根據timestamp, appSecret計算簽名值          $s                   = hash_hmac('sha256', $timestamp, '**********G6KaiRey7NFJxXHyBthsPL5Q4rBSvlJhQvREadhO__uHhDs', true);          $signature           = base64_encode($s);          $urlEncode_signature = urlencode($signature);          return $urlEncode_signature;      }        /**       * 毫秒級時間戳       * @return float       */      public function mTime()      {          list($s1, $s2) = explode(' ', microtime());          $mTime = (float)sprintf('%.0f', (floatval($s1) + floatval($s2)) * 1000);          return $mTime;      }        public function curl_json($url, $postFields = null)      {          $ch = curl_init();          curl_setopt($ch, CURLOPT_URL, $url);          curl_setopt($ch, CURLOPT_FAILONERROR, false);          curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);          curl_setopt($ch, CURLOPT_USERAGENT, "dingtalk-sdk-php");          //https 請求          if(strlen($url) > 5 && strtolower(substr($url, 0, 5)) == "https") {              curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);              curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);          }          curl_setopt($ch, CURLOPT_POST, true);          $header = [ "Content-Type: application/json; charset=utf-8", "Content-Length:" . strlen(json_encode($postFields)) ];          curl_setopt($ch, CURLOPT_HTTPHEADER, $header);          curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($postFields));          $reponse = curl_exec($ch);          if(curl_errno($ch)) {              throw new Exception(curl_error($ch), 0);          } else {              $httpStatusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);              if(200 !== $httpStatusCode) {                  throw new Exception($reponse, $httpStatusCode);              }          }          curl_close($ch);          return $reponse;      }  }