利用 Laravel 實作 Line 登入,並取得使用者的 ID 及 資料

利用 Laravel 實作 Line login 取得使用者資料

教學開始,為何要寫這篇?因為剛好專案需要,需要取得使用者在某個 provider 之下的 ID,就順便寫這篇了,如果是剛好要實作 Line Login 的朋友可以直接參考。

首先,先到

註冊一個 Line Login 的 Service,如果連這個都要教學,那我也沒辦法了。(其實只是懶得截圖?),註冊完成後可以在 Channel Setting 內取得

  1. Channel ID
  2. Channel Secret

這兩個需要記下來~

另外在 App Setting 中有個 Callback Url,之後也要填寫,下方會教你該填寫什麼,這個欄位是 Line 拿來驗證與最後回呼你的網址。

以下準備好之後,首先把我們的 Laravel 專案建立起來

基本上我都是使用 Laravel 5.5 的 LTS 版本。

composer create-project --prefer-dist laravel/laravel login-demo "5.5.*"

不知道 composer 是什麼的可以去官網下載安裝

專案建立起來之後就可以按照步驟來:

第一步:編輯我們的 .env 檔案

  1. APP_URL改成你的網址
  2. 新增兩個欄位
LINE_CHANNEL_ID=這邊填寫你的 Channel ID
LINE_SECRET=這邊填寫你的 Channel Secret

第二步:來在 config 資料夾底下新增一個 line.php,內容如下

<?php

return
[
'channel_id' => env('LINE_CHANNEL_ID'),
'secret' => env('LINE_SECRET'),
'authorize_base_url' => 'https://access.line.me/oauth2/v2.1/authorize',
'get_token_url' => 'https://api.line.me/oauth2/v2.1/token',
'get_user_profile_url' => 'https://api.line.me/v2/profile',
];

主要是記錄一些 Line API 的位址,跟把 env 資料讀進來。

第三步:安裝 Guzzle 套件

主要是拿來取代 Curl 用的。

composer require guzzlehttp/guzzle:~6.0

第四步:建立程式碼

  1. 建立路由

打開我們的 routes/web.php

貼上以下路由程式碼

Route::get('/line', 'LoginController@pageLine');
Route::get('/callback/login', 'LoginController@lineLoginCallBack');

2. 建立 View

resources/views 底下建立一個 line.blade.php

貼上以下 blade 程式碼

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Line Login Demo</title>

<!-- Bootstrap core CSS -->
<link href="https://bootstrap.hexschool.com/docs/4.2/dist/css/bootstrap.css" rel="stylesheet">

<!-- Custom styles for this template -->
<link href="https://bootstrap.hexschool.com/docs/4.2/examples/floating-labels/floating-labels.css" rel="stylesheet">
</head>
<body>
<form class="form-signin">
<div class="text-center mb-4">
<a href="{{ $url }}"><img class="mb-4" src="/images/line/2x/32dp/btn_login_base.png"></a>
</div>
<p class="mt-5 mb-3 text-muted text-center">Yulin &copy; 2019</p>
</form>
</body>
</html>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.6/umd/popper.min.js" integrity="sha384-wHAiFfRlMFy6i5SRaxvfOCifBUQy1xHdJ/yoi7FRNXMRBu5WHdZYu1hA6ZOblgut" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js" integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k" crossorigin="anonymous"></script>

注意其中的

/images/line/2x/32dp/btn_login_base.png

這邊需要改成你自己的圖片網址,需要登入圖片的可以到 Line 官方下載

3. 創建一個 Controller ,可依照下面指令

php artisan make:controller LoginController

並貼上以下程式碼

<?php

namespace
App\Http\Controllers;

use Exception;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use App\Services\LineService;

class LoginController extends Controller
{
protected $lineService;

public function __construct(LineService $lineService)
{
$this->lineService = $lineService;
}

public function pageLine()
{
$url = $this->lineService->getLoginBaseUrl();
return view('line')->with('url', $url);
}

public function lineLoginCallBack(Request $request)
{
try {
$error = $request->input('error', false);
if ($error) {
throw new Exception($request->all());
}
$code = $request->input('code', '');
$response = $this->lineService->getLineToken($code);
$user_profile = $this->lineService->getUserProfile($response['access_token']);
echo "<pre>"; print_r($user_profile); echo "</pre>";
} catch (Exception $ex) {
Log::error($ex);
}
}
}

pageline 只是取得 Line 要求的參數組成網址,並且傳到 view

lineLoginCallBack 則是登入成功後 Line 會呼叫這隻,所以必須把這支網址寫入 App Setting 裡面的 Callback url,上方有提到,內容主要是先跟 Line 取得權杖,隨後 Call Line 取得使用者的 API (透過權杖),實作部分寫在 LineService 裡面

4. 在 app 資料夾底下建立一個 Services 資料夾

5. 在 Services 資料夾底下建立一個 LineService.php,並貼上下方程式碼

<?php

namespace
App\Services;

use GuzzleHttp\Client;

class LineService
{
public function getLoginBaseUrl()
{
// 組成 Line Login Url
$url = config('line.authorize_base_url') . '?';
$url .= 'response_type=code';
$url .= '&client_id=' . config('line.channel_id');
$url .= '&redirect_uri=' . config('app.url') . '/callback/login';
$url .= '&state=test'; // 暫時固定方便測試
$url .= '&scope=openid%20profile';

return $url;
}

public function getLineToken($code)
{
$client = new Client();
$response = $client->request('POST', config('line.get_token_url'), [
'form_params' => [
'grant_type' => 'authorization_code',
'code' => $code,
'redirect_uri' => config('app.url') . '/callback/login',
'client_id' => config('line.channel_id'),
'client_secret' => config('line.secret')
]
]);
return json_decode($response->getBody()->getContents(), true);
}

public function getUserProfile($token)
{
$client = new Client();
$headers = [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
];
$response = $client->request('GET', config('line.get_user_profile_url'), [
'headers' => $headers
]);
return json_decode($response->getBody()->getContents(), true);
}
}

這邊三隻 function 一一解釋:

getLoginBaseUrl 只是取得 Line 要求的固定網址及參數

getLineToken 則是像 Line 取得我們的權杖 (透過 Channel ID, Channel Secret),這邊也會一併驗證你的 Callback Url 是否相同。

getUserProfile 則是透過 getLineToken 獲得的權杖,去要求存取使用者的資料。

完成後把你的 callback url 也就是 http://yourdomain.xxx/callback/login

貼到上述所說的 callback url 部分。讓 Line 可以驗證並回呼

最後,來到 http://yourdomain.xxx/line

點下圖示最後登入成功後就會出現 Line 回傳給你的使用者資料!

長得會如下方

Array
(
[userId] => 使用者的 ID
[displayName] => 使用者的暱稱
[pictureUrl] => 使用者的大頭貼照網址
)

完整的範例程式碼在 Github 上可以找到

以上如果有問題歡迎提問。