สร้าง Line Login ให้กับเว็บไซต์ ด้วยภาษา PHP

วันที่: 22 เม.ย. 2565 22:55 น.

สร้าง Line Login ให้กับเว็บไซต์ ด้วยภาษา PHP

ในปัจจุบันเราจะเห็นเว็บไซต์หลายแห่งมีระบบ login ผ่าน social media ไม่ว่าจะ login หรือ register โดยใช้ facebook twitter หรือแม้แต่ google หรือ apple id และที่ขาดไม่ได้นั้น ก็คือ Line นั่นเอง ซึ่งในบทความนี้จะพาสร้างระบบ login ด้วย line ในภาษา PHP กันครับ

ต้องบอกก่อนว่า จะขอข้ามขั้นตอนที่คิดว่าทุกคนทำไว้แล้ว เช่น การสร้าง channel ใน https://developers.line.biz/console/ ใครที่ยังไม่ได้สร้างไว้ ก็ไปสร้างให้เรียบร้อยนะครับ โดยต้องสร้างเป็น Type Line Login นะครับ

เอาล่ะ ในเมื่อสร้าง channel เรียบร้อยแล้ว สิ่งที่เราต้องตั้งค่าในการสร้างระบบ login จะมี 3 ส่วน ดังนี้

  • Channel ID
  • Channel secret
  • Callback URL

ข้อมูล Callback URL นั้นจะเป็น url ที่เอาไว้รับค่าหลังจากที่ login มาแล้ว เช่น หากอยากเก็บข้อมูลผู้ใช้ลงในฐานข้อมูล ก็จะเขียนไว้ที่นี่ ซึ่งจะมีหน้าตาของ url แบบนี้ครับ https://myweb.com/callback.php ซึ่งเดี๋ยวจะพาเขียนต่อไปนี้แหละครับ

สร้างไฟล์ชื่อ LineLogin.php มีโค้ดดังนี้

<?php
class LineLogin
{
    #### change your id
    private const CLIENT_ID = 'ใส่ไอดีของคุณ';
    private const CLIENT_SECRET = 'ใส่ไอดีของคุณ';
    private const REDIRECT_URL = 'https://เว็บของคุณ.com/callback.php';

    private const AUTH_URL = 'https://access.line.me/oauth2/v2.1/authorize';
    private const PROFILE_URL = 'https://api.line.me/v2/profile';
    private const TOKEN_URL = 'https://api.line.me/oauth2/v2.1/token';
    private const REVOKE_URL = 'https://api.line.me/oauth2/v2.1/revoke';
    private const VERIFYTOKEN_URL = 'https://api.line.me/oauth2/v2.1/verify';


    function getLink()
    {
        if (session_status() == PHP_SESSION_NONE) {
            session_start();
        }

        $_SESSION['state'] = hash('sha256', microtime(TRUE) . rand() . $_SERVER['REMOTE_ADDR']);

        $link = self::AUTH_URL . '?response_type=code&client_id=' . self::CLIENT_ID . '&redirect_uri=' . self::REDIRECT_URL . '&scope=profile%20openid%20email&state=' . $_SESSION['state'];
        return $link;
    }

    function refresh($token)
    {
        $header = ['Content-Type: application/x-www-form-urlencoded'];
        $data = [
            "grant_type" => "refresh_token",
            "refresh_token" => $token,
            "client_id" => self::CLIENT_ID,
            "client_secret" => self::CLIENT_SECRET
        ];

        $response = $this->sendCURL(self::TOKEN_URL, $header, 'POST', $data);
        return json_decode($response);
    }

    function token($code, $state)
    {
        if (session_status() == PHP_SESSION_NONE) {
            session_start();
        }

        if ($_SESSION['state'] != $state) {
            return false;
        }

        $header = ['Content-Type: application/x-www-form-urlencoded'];
        $data = [
            "grant_type" => "authorization_code",
            "code" => $code,
            "redirect_uri" => self::REDIRECT_URL,
            "client_id" => self::CLIENT_ID,
            "client_secret" => self::CLIENT_SECRET
        ];

        $response = $this->sendCURL(self::TOKEN_URL, $header, 'POST', $data);
        return json_decode($response);
    }

    function profileFormIdToken($token = null)
    {
        $payload = explode('.', $token->id_token);
        $ret = array(
            'access_token' => $token->access_token,
            'refresh_token' => $token->refresh_token,
            'name' => '',
            'picture' => '',
            'email' => ''
        );

        if (count($payload) == 3) {
            $data = json_decode(base64_decode($payload[1]));
            if (isset($data->name))
                $ret['name'] = $data->name;

            if (isset($data->picture))
                $ret['picture'] = $data->picture;

            if (isset($data->email))
                $ret['email'] = $data->email;
        }
        return (object) $ret;
    }

    function profile($token)
    {
        $header = ['Authorization: Bearer ' . $token];
        $response = $this->sendCURL(self::PROFILE_URL, $header, 'GET');
        return json_decode($response);
    }

    function verify($token)
    {
        $url = self::VERIFYTOKEN_URL . '?access_token=' . $token;
        $response = $this->sendCURL($url, NULL, 'GET');
        return $response;
    }

    function revoke($token)
    {
        $header = ['Content-Type: application/x-www-form-urlencoded'];
        $data = [
            "access_token" => $token,
            "client_id" => self::CLIENT_ID,
            "client_secret" => self::CLIENT_SECRET
        ];
        $response = $this->sendCURL(self::REVOKE_URL, $header, 'POST', $data);
        return $response;
    }

    private function sendCURL($url, $header, $type, $data = NULL)
    {
        $request = curl_init();

        if ($header != NULL) {
            curl_setopt($request, CURLOPT_HTTPHEADER, $header);
        }

        curl_setopt($request, CURLOPT_URL, $url);
        curl_setopt($request, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($request, CURLOPT_SSL_VERIFYPEER, false);

        if (strtoupper($type) === 'POST') {
            curl_setopt($request, CURLOPT_POST, TRUE);
            curl_setopt($request, CURLOPT_POSTFIELDS, http_build_query($data));
        }

        curl_setopt($request, CURLOPT_FOLLOWLOCATION, 1);
        curl_setopt($request, CURLOPT_RETURNTRANSFER, 1);

        $response = curl_exec($request);
        return $response;
    }
}

 

สร้างไฟล์ callback.php โดยมีโค้ดดังนี้

<?php
session_start();
require_once('LineLogin.php');

$line = new LineLogin();
$get = $_GET;

$code = $get['code'];
$state = $get['state'];
$token = $line->token($code, $state);

if (property_exists($token, 'error'))
    header('location: index.php');

if ($token->id_token) {
    $profile = $line->profileFormIdToken($token);
    $_SESSION['profile'] = $profile;
    header('location: index.php');
}

## get profile by token
// $profile = $line->profile($token->access_token);
// print_r($profile);

 

สร้างไฟล์ชื่อ index.php โดยมีโค้ดดังนี้

<?php
session_start();
require_once('LineLogin.php');

if (isset($_SESSION['profile'])) {
    $profile = $_SESSION['profile'];
    echo '<img src="', $profile->picture, '/large">';
    echo '<p>Name: ', $profile->name, '</p>';
    echo '<p>Email: ', $profile->email, '</p>';
    echo '<a href="logout.php">Logout</a>';
} else {
    $line = new LineLogin();
    $link = $line->getLink();
    echo '<a href="', $link, '">Login</a>';
}

 

และสุดท้ายไฟล์ logout.php

<?php
session_start();
require_once('LineLogin.php');

if (isset($_SESSION['profile'])) {
    $profile = $_SESSION['profile'];
    $line = new LineLogin();
    $line->revoke($profile->access_token);
    session_destroy();
}

header('location: index.php');

 

ในโค้ดตัวอย่างจะยังไม่มีการบันทึกลงฐานข้อมูลนะครับ เพียงแสดงให้เห็นว่า Line ส่งอะไรกลับมาให้เราเรียกใช้งานได้บ้าง ซึ่งก็ครอบคลุม เพียงพอต่อการนำไปใช้สำหรับสมาชิกของเว็บไซต์ได้เลยแหละ ไม่ว่าจะเป็น รหัส ชื่อ อีเมล์ กรณีที่ผู้ใช้ลงทะเบียนและอนุญาตให้เข้าถึง และรูปภาพโปรไฟล์ หน้าตาจะออกมาแบบนี้ครับ

 

สิ่งสำคัญที่ไม่ควรมองข้าม

ปุ่ม login ของ line นั้น ต้องกำหนดรูปแบบให้เป็นไปตามข้อกำหนดของ line ด้วย โดยสามารถดูรายละเอียดได้ที่นี่ https://developers.line.biz/en/docs/line-login/login-button/

 

ศึกษาเพิ่มเติม

 

เรื่องอื่น ๆ ที่เกี่ยวข้อง