เนื้อหานี้ จะเป็นตอนต่อเนื่องจากตอนที่แล้ว เกี่ยวกับ การใช้งานการล็อกอิน
เว็บไซต์หรือเว็บแอพลิเคชั่นด้วย PHP ผ่าน Line Facebook Google และ Twitter
จะเป็นการแนะนำแนวทางการใช้งาน PHP Library สำหรับแต่ละ Social Platform
ในการเรียกใช้ เพื่อดึงข้อมูลของผู้ใช้งาน platform นั้นๆ
ทบทวนเนื้อหาตอนที่แล้วได้ที่
ล็อกอินด้วย Line Facebook Google Twitter อัพเดทปี 2020 ตอนที่ 1 http://niik.in/986
https://www.ninenik.com/content.php?arti_id=986 via @ninenik
การติดตั้ง PHP Library
เราจะทำการติดตั้ง Library ต่างๆ ผ่าน composer เพื่อใช้งานโฟลเดอร์ vendor หรือหากใคร
ต้องการโฟลเดอร์ vendor ไปใช้งานโดยไม่ต้องติดตั้งเอง สามารถดาวน์โหลดที่ลิ้งค์ด้านล่าง
ดาวน์โหลด Social Library คลิก
กรณีติดตั้งเอง สามารถทำตามขั้นตอนต่างๆ ดังนี้
ติตดั้ง Library สำหรับ Line
composer require ninenik/lineoauth
ตัวนี้ผู้เขียนลองดัดแปลงจาก class ที่เคยเขียนไว้ ทำเป็น package ให้สามารถติดตั้งได้ง่ายขึ้น http://niik.in/831
ติตดั้ง Library สำหรับ Google
composer require google/apiclient:2.5
ติตดั้ง Library สำหรับ Facebook
composer require facebook/graph-sdk:5.7
ติตดั้ง Library สำหรับ Twitter
composer require abraham/twitteroauth:1.1
หลักจากติดตั้งครบทั้ง 4 รายการแล้ว เราจะได้โฟลเดอร์ vendor ในโฟลเดอร์โปรเจ็คเราประมาณนี้
ข้อมูลผู้ใช้จากการใช้งาน Social Api
ก่อนไปสู่รายละเอียดการใช้งานโค้ด ขอพูดถึงเกี่ยวกับข้อมูลจากการเรียกใช้งาน PHP Library ต่างๆ ว่า
ส่วนใหญ่ข้อมูลหลักที่เราจะได้แน่นอน ก็คือ ID และ Name ของผู้ใช้ในแต่ละ Platform นั้นๆ ซึ่งค่า ID จะมี
รูปแบบแตกต่างกันไป ส่วนรูปภาพ Picture โพรไฟล์ของผู้ใช้ ทั้ง 4 Platform ณ ปัจจุบันก็ยังสามารถเรียกข้อมูล
รูปภาพได้ แต่ใน facebook เริ่มมีการกำหนดค่าความเป็นส่วนตัวของรูปภาพ อาจจะเป็นไปได้ว่าต้องมีการขอสิทธิ์
เพิ่มเติมหรือไม่ในอนาคต (ตอนนี้ยังสามารถเรียกข้อมูลรูปได้)
รูปโพรไฟล์ของ facebook จากการใช้งาน API จะมีขนาดที่เล็กคือ 50x50 แต่ในที่นี้เราทำการปรับโค้ดให้ไปดึง
ขนาดรูปที่ 200x200 เพื่อเวลานำไปสร้างเป็นภาพใหม่ตอนบันทึกหรือจัดเก็บไว้ใช้งาน จะได้ภาพที่คมชัดในระดับหนึ่ง
อีกส่วนที่สำคัญสุดท้ายก็คือ Email ข้อมูลส่วนนี้ ส่วนใหญ่แล้วจะไม่ได้มาโดยง่ายนัก หรือบาง Platform ก็จำเป็น
ต้องมีการเปิดการร้องขอพิเศษ หรือการกำหนดการตั้งค่าเพิ่มเติมตอนสร้าง App เช่น ใน Line เราจะต้องสมัครหรือ
ขอรับสิทธิ์การใช้งานหรือเข้าถึงอีเมล ซึ่งมีอยู่ในขั้นตอนการสร้าง App ซึ่งไม่ยุ่งยากนัก เพียงสมัครใช้งานและ อัพโหลด
screenshot หน้า privacy เกี่ยวกับนโยบายความเป็นส่วนการใช้งานข้อมูลของเรา เท่านั้น
เช่นกันในกรณีของ Twiiter เราก็สามารถเพิ่มสิทธิ์การร้องขอข้อมูลอีเมล ในส่วนของการกำหนด permission
ในหน้าจัดการ App ได้ สองส่วนทั้ง Line และ Twitter เกี่ยวกับการใช้งานอีเมล จะไปอัพเดทเพิ่มเติมไว้ในตอนท้าย
ของบทความตอนที่ 1 สำหรับใน Facebook ข้อมูลอีเมลถึงแม้ว่าเราจะสามารถกำหนดฟิลด์เพื่อร้องขอได้ แต่ใช่ว่า
เราจะได้ข้อมูลอีเมลนั้นเสมอ เช่น ผู้ใช้ไม่ได้สมัครหรือกำหนดการใช้งานอีเมล หรือผู้ใช้ไม่ต้องการแสดงอีเมล กรณี
เหล่านี้เราก็จะไม่ได้ข้อมูลอีเมลของผู้ใช้ ทำนองเดียวกันกับอีเมลของ Line และ Twitter หากผู้ใช้ไม่อนุญาตให้เข้า
ถึงข้อมูลอีเมล หรือข้อมูลอีเมลยังไม่ได้ยันยัน ก็จะไม่สามารถดึงข้อมูลได้
ในส่วนของ Google จะไม่มีปัญหาเกี่่ยวกับอีเมล เพราะอีเมลเป็นเสมือน username ของผู้ใช้ของบริการ Google
ที่อธิบายมาข้างต้น ก็เพื่อเป็นแนวทางให้ทำความเข้าใจเกี่ยวกับการนำข้อมูลไปใช้งาน ว่าเราควรยึดโยงความ
สัมพันธ์ของข้อมูลใดในระบบ จึงจะเหมาะสมที่สุด และแน่นอน ในที่นี้เราจะใช้ข้อมูล ID เป็นตัวเชื่อมหรืออ้างอิง
ผู้ใช้งาน เพราะเป็นข้อมูลที่แน่นอนที่สุด
ลำดับการทำงานของระบบ Social Login
เนื้อหาที่จะนำเสนอในตอนนี้ จะไม่ใช่การใช้งานระบบแบบเต็ม ยังไม่นำเอาส่วนของ Database มาประกอบ
แต่จะเป็นรูปแบบที่จะสามารถไปปรับใช้เพิ่มเติม หากต้องการใช้งานเฉพาะ Platform โดยจะสร้างโฟลเดอร์ชื่อ
socialconnect และมีไฟล์ สำหรับการทำงานของแต่ละ platform ให้แยกศึกษา โดยจะจำลองโค้ดการทำงาน
และไฟล์ที่เกี่ยวข้องดังนี้
+ index.php + login.php + member.php + logout.php + /socialconnect/ + line.php + google.php + facebook.php + twitter.php
หน้า index เป็นหน้าหลักมีเมนูไปยังหน้าต่างๆ หน้า login มีปุ่มสำหรับลิ้งค์ไปยังการทำงานการล็อกอินของ
แต่ละ platform เป็นแค่ลิ้งค์ธรรมดา โดยมีการใช้งาน session หากมีการล็อกอินเข้าใช้งานแล้ว จะให้ไปหน้า
member อัตโนมัติ ต่อด้วยหน้า member จะเป็นหน้าจำลองหน้าสมาชิก หน้านี้ เราจะให้ทำการแสดงข้อมูล
session ของผู้ใช้ ที่เราได้จาก การล็อกอินของ platform ที่เรียกใช้ โดยจะมีด้วยกัน 4 ค่าคือ id name email
และ picture ซึ่งข้อมูลจะมีครบหรือไม่ขึ้นกับเงื่อนไขที่อธิบายไปด้านบน หน้า member จะมีการใส่เงื่อนไขว่า
หากยังไม่มีการล็อกอิน โดยเช็คค่า session ถ้ายังไม่มีหรือเป็นค่าว่าง ให้ไปที่หน้า login ก่อน และสุดท้ายหน้า
logout เป็นหน้าที่ใช้สำหรับล้างค่า session ของผู้ใช้ เพื่อออกจากระบบ แล้วไปที่หน้า login หลังจากล้างค่า
ข้อมูล session เรียบร้อยแล้ว
ข้างต้น เป็นหลักการทำงานทั่วไปของระบบสมาชิก
ต่อไปในส่วนของไฟล์ในโฟลเดอร์ socialconnect เราทำการแยกไฟล์สำหรับทำงานแต่ละ platform อย่างที่
ได้อธิบายไป เพื่อให้สามารถเลือกหยิบจับไปประยุกต์ใช้งานตามต้องการ ขั้นตอนการทำงานของระบบล็อกอิน
ด้วย social login จะมีสองขั้นตอน เหมือนกันทั้ง 4 platform คือ เริ่มต้นด้วยการ connerct ไปยัง platform นั้นๆ
แต่ละ platform จะสร้าง url สำหรับลิ้งค์ไปหน้าล็อกอินของ platform นั้น โดยมีค่า callback url ที่จะลิ้งค์กลับมา
พร้อมค่าสำหรับกำหนดสิทธิ์การเข้าถึงข้อมูล ดูรูปแบบจำลองคร่าวๆ ตามนี้
เมื่อเราทำการ connect ไปยัง line และเรากำหนด callback url เป็น a.php
- ลิ้งค์ไป -> lineserver/authorized.php?scope=xx&callback=yourwebsite/a.php
- ขึ้นหน้าล็อกอินผ่าน line หากยืนยันข้อมูลการใช้งานถูกต้อง ก็จะได้ค่า token หรือกุญแจข้อมูลส่งกลับ
- ลิ้งค์กลับมายัง yourwebsite/a.php พร้อมข้อมูลสำหรับใช้ในการเรียกดู รายละเอียดผู้ใช้งาน เช่น
- yourwebsite/a.php?code=ค่า token หรือ yourwebsite/a.php?error กรณีไม่สามารถเข้าใช้งานหรือล็อกอินได้
- ในกรณีล็อกอินสำเร็จ ค่า token หรือ accessToken ที่ได้จะถูกนำมาใช้กับคำสั่ง เรียกดูข้อมูลผู้ใช้ในลำดับต่อไป
ดังนั้นสองขั้นตอนที่กล่าวถึงก็คือ connect เพื่อไปยังหน้าล็อกอินของ platform นั้นๆ และ authorized เพื่อใช้
สิทธื์หรืออำนาจที่ได้รับตอบกลับมา ไปดึงข้อมูลผู้ใช้
รูปแบบคร่าวๆ จะประมาณโค้ดด้านล่างนี้
<?php $social = new Socialconnect(); // ลิ้งค์มาไฟล์ line.php โดยส่ง $_GET['action'] เท่ากับ connect เพื่อให้เรียกใช้งาน คำสั่งการเชื่อม // ต่อกับ platfom นั้น if(isset($_GET['action']) && $_GET['action']=="connect"){ // ล้ิงค์มาจากการที่เรากดปุ่มหนัา login.php $social->connectline(); // ล้ิงค์ไปหน้าล็อกอินของไลน์ เพื่อทำการเชื่อมต่อ }else{ // ลิ้งค์หลังจากล็อกอินด้วยไลน์ มีส่งค่า $_GET['code'] หรือ $_GET['error'] กลับมา // เรียกใช้งานคำสั่งการดึงข้อมูลจากบัญชีไลน์ โดยมีการกำหนด หน้าที่ต้องการล็้งค์ไปถ้าดึงข้อมูลสำเร็จ // กับหน้าที่ไม่สามารถดึงข้อมูลได้ หรือเกิด error $social->authorizedline("../member.php","../login.php"); } ?>
จะเห็นว่าในขั้นตอนการเรียกดูข้อมูลผู้ใช้ด้วยคำสั่ง authorized() เรากำหนดหน้าที่ต้องการลิ้งค์ไปหากทำการล็อกอิน
สำเร็จ หรือลิ้งค์ไปหากไม่สามารถล็อกอินเข้าใช้งานได้ นั่นก็คือหน้า member กับ login ตามลำดับ
ในขั้นตอนการทำงานคำสั่ง authorizedline() หากมีการล็อกอินสำเร็จ เราทำงานสร้าง session ของผู้ใช้ ด้วยค่าประมาณนี้
// โค้ดบางส่วนของการใช้งาน Line // เก็บค่าใน seesion ไว้ไปแสดง $_SESSION['ses_user']['id'] = (isset($line_userID))?$line_userID:null; $_SESSION['ses_user']['name'] = (isset($line_userName))?$line_userName:null; $_SESSION['ses_user']['email'] = (isset($line_email))?$line_email:null; $_SESSION['ses_user']['picture'] = (isset($line_userPicture))?$line_userPicture:null;
ค่า session นี้จะกำหนด้วยชื่อเดียวกันทั้ง 4 platform แต่ค่าจะมีหรือไม่ หรือเป็น null ก็ขึ้นกับสิทธิ์การเข้าถึงข้อมูลนั้น
ในการประยุกต์ใช้งานกับ Database เราสามารถจัดเก็บหรือบันทึกลงฐานข้อมูล ก่อนที่จะลิ้งค์ไปหน้า member ได้
รายละเอียดเกี่ยวกับการประยุกต์กับฐานข้อมูล จะมีในตอนหน้า ในลำดับต่อไป
สิ่งที่ผู้เขียนใช้ และกำหนดสำหรับทดสอบในครั้งนี้คือ ใช้ domain สมมติ
กำหนด callback url แต่ละ platform เป็นดังนี้
https://www.mysslweb.com/socialconnect/line https://www.mysslweb.com/socialconnect/goggle https://www.mysslweb.com/socialconnect/facebook https://www.mysslweb.com/socialconnect/twitter
ซึ่งก่อนหน้า จากการทดลองใช้ url แบบ มี query string ไม่สามารถใช้ได้ เช่น
https://www.mysslweb.com/socialconnect/?type=line https://www.mysslweb.com/socialconnect/?type=google
ดังนั้นจึงจำเป็นต้องกำหนด url แบบไม่ใช้งาน query string แต่ประยุกต์เล็กน้อย
โดยตัดนามสกุลไฟล์ php ออก โดยใช้ mode_rewrite เป็น ไฟล์ .htaccess ไว้ในโฟเลดอร์ socialconnect ดังนี้
ไฟล์ .htaccess ในโฟลเดอร์ socialconnect
RewriteEngine On RewriteRule line line.php [L] RewriteRule google google.php [L] RewriteRule facebook facebook.php [L] RewriteRule twitter twitter.php [L] Options -Indexes
นั่นคือ https://www.mysslweb.com/socialconnect/line ก็คือ https://www.mysslweb.com/socialconnect/line.php
ทั้งนี้เพื่อความสวยงามเท่านั้น หากใครจะไม่ใช้ mode_rewrite ก็ได้ และกำหนด callback url เป็น
https://www.mysslweb.com/socialconnect/line.php ก็สามารถใช้งานได้เหมือนกัน
โค้ดไฟล์ในโปรเจ็คตัวอย่างทั้งหมด
มาดูส่วนของโค้ดไฟล์โปรเจ็คตัวอย่างทั้งหมด จะขอแบ่งเป็นสองส่วน ส่วนแรกเป็นโค้ดสำหรับระบบสมาชิกของเว็บไซต์
ส่วนที่สองเป้นส่วนของ class และไฟล์สำหรับการล็อกอินเข้าใช้งานของแต่ละ platform ที่อยู่ในโฟลเดอร์ socialconnect
ไฟล์ index.php
<?php session_start(); require_once('./vendor/autoload.php') ?> <!DOCTYPE html> <html lang='en'> <head> <meta charset='utf-8' /> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta http-equiv="Content-Security-Policy" content="block-all-mixed-content"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.min.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.12.0-2/css/all.min.css"> <title>Document</title> </head> <body> <div class="mx-auto mt-5" style="width: 500px;"> <h1>HOME</h1> <ul class="nav justify-content-center"> <li class="nav-item"> <a class="nav-link active" href="index.php">Home</a> </li> <li class="nav-item"> <a class="nav-link" href="login.php">Login</a> </li> <li class="nav-item"> <a class="nav-link" href="member.php">Member</a> </li> <li class="nav-item"> <a class="nav-link" href="logout.php">Logout</a> </li> </ul> </div> </body> </html>
ไฟล์ login.php
<?php session_start(); require_once('./vendor/autoload.php'); if(isset($_SESSION['ses_user']) && !empty($_SESSION['ses_user'])){ header("Location:member.php"); exit; } ?> <!DOCTYPE html> <html lang='en'> <head> <meta charset='utf-8' /> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta http-equiv="Content-Security-Policy" content="block-all-mixed-content"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.min.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.12.0-2/css/all.min.css"> <title>Document</title> </head> <body> <div class="mx-auto mt-5" style="width: 500px;"> <h1>LOGIN</h1> <ul class="nav justify-content-center"> <li class="nav-item"> <a class="nav-link active" href="index.php">Home</a> </li> <li class="nav-item"> <a class="nav-link" href="login.php">Login</a> </li> <li class="nav-item"> <a class="nav-link" href="member.php">Member</a> </li> <li class="nav-item"> <a class="nav-link" href="logout.php">Logout</a> </li> </ul> <div class="row"> <div class="col-12 py-1"> <a href="socialconnect/line?action=connect" class="btn btn-outline-success btn-block"> <i class="fab fa-line fa-fw mr-2"></i>ล็อกอินด้วย Line </a> </div> <div class="col-12 py-1"> <a href="socialconnect/google?action=connect" class="btn btn-outline-danger btn-block"> <i class="fab fa-google fa-fw mr-2"></i>ล็อกอินด้วย Google </a> </div> <div class="col-12 py-1"> <a href="socialconnect/facebook?action=connect" class="btn btn-outline-primary btn-block"> <i class="fab fa-facebook fa-fw mr-2"></i>ล็อกอินด้วย Facebook </a> </div> <div class="col-12 py-1"> <a href="socialconnect/twitter?action=connect" class="btn btn-outline-info btn-block"> <i class="fab fa-twitter fa-fw mr-2"></i>ล็อกอินด้วย Twitter </a> </div> </div> </div> </body> </html>
ไฟล์ member.php
<?php session_start(); if(!isset($_SESSION['ses_user']) || empty($_SESSION['ses_user'])){ header("Location:login.php"); exit; } ?> <!DOCTYPE html> <html lang='en'> <head> <meta charset='utf-8' /> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta http-equiv="Content-Security-Policy" content="block-all-mixed-content"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.min.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.12.0-2/css/all.min.css"> <title>Document</title> </head> <body> <div class="mx-auto mt-5" style="width: 500px;"> <h1>MEMBER</h1> <ul class="nav justify-content-center"> <li class="nav-item"> <a class="nav-link active" href="index.php">Home</a> </li> <li class="nav-item"> <a class="nav-link" href="login.php">Login</a> </li> <li class="nav-item"> <a class="nav-link" href="member.php">Member</a> </li> <li class="nav-item"> <a class="nav-link" href="logout.php">Logout</a> </li> </ul> <pre> <?php print_r($_SESSION['ses_user']); ?> </pre> </div> </body> </html>
ไฟล์ logout.php
<?php session_start(); session_destroy(); header("Location:login.php"); exit; ?>
เป็นรูปแบบโค้ดง่ายๆ ไม่มีอะไรซับซ้อน
ต่อไปเป็นส่วนของไฟล์ในโฟลเดอร์ socialconnect
บรรทัดที่ hilight เป็นส่วนของข้อมูลที่สามารถปรับค่า หรือประยุกต์ หรือถ้าสามารถเข้าใจการทำงานทั้งหมด ก็สามารถ
นำไปปรับแต่งได้ตามต้องการ
ไฟล์ line.php
<?php session_start(); require_once('../vendor/autoload.php'); use Ninenik\LineOAuth\LineOAuth; class Socialconnect{ private $_LINE_CLIENT; // $salt สามารถใช้คำสั่ง password_hash("mysslweb",PASSWORD_BCRYPT); สร้างได้ private $_SALT = '$2y$10$cDKiRAzt3zWwiyAu/Nz40Om6yKe1mQZMM4T6yxAlTTI25oIUq9EVm'; // กำหนดค่าที่จะใช้งานในส่วนนี้ private $_CHANNEL_ID = "165xxxxx182"; private $_CHANNEL_SECRET = "46xxxxb273cxxxxxxxx9ee47d"; private $_CHANNEL_CALLBACK = "https://www.mysslweb.com/socialconnect/line"; public function __construct(){ $this->_LINE_CLIENT = new LineOAuth(); } public function redirect($url){ header("Location:{$url}"); exit; } public function line(){ $this->_LINE_CLIENT->setapp( $this->_CHANNEL_ID, $this->_CHANNEL_SECRET, $this->_CHANNEL_CALLBACK ); } public function connectline(){ $this->line(); $this->_LINE_CLIENT->authorize(); } public function authorizedline($success_url,$error_url){ if(isset($_GET['error'])){ $this->redirect($error_url); }else{ if(isset($_GET['code'])){ $this->line(); $dataToken = $this->_LINE_CLIENT->requestAccessToken($_GET, true); print_r($dataToken); if(array_key_exists('access_token',$dataToken)){ $accessToken = $dataToken['access_token']; } if(array_key_exists('id_token',$dataToken)){ $line_userdata = json_decode($dataToken['user'],true); // ค่า ID , name , picture ที่เราสามารถนำไปใช้ได้ $line_userID = $line_userdata['sub']; $line_userName = $line_userdata['name']; $line_email = $line_userdata['email']; $line_userPicture = $line_userdata['picture']; $hashed_token = crypt($line_userID,$this->_SALT); // เก็บค่าใน seesion ไว้ไปแสดง $_SESSION['ses_user']['id'] = (isset($line_userID))?$line_userID:null; $_SESSION['ses_user']['name'] = (isset($line_userName))?$line_userName:null; $_SESSION['ses_user']['email'] = (isset($line_email))?$line_email:null; $_SESSION['ses_user']['picture'] = (isset($line_userPicture))?$line_userPicture:null; } if(isset($line_userID) && isset($hashed_token) && isset($accessToken)){ $this->redirect($success_url); }else{ $this->redirect($error_url); } }else{ $this->redirect($error_url); } } } } ?> <?php $social = new Socialconnect(); if(isset($_GET['action']) && $_GET['action']=="connect"){ $social->connectline(); }else{ $social->authorizedline("../member.php","../login.php"); } ?>
ไฟล์ google.php
<?php session_start(); require_once('../vendor/autoload.php'); class Socialconnect{ private $_GOOGLE_CLIENT; // $salt สามารถใช้คำสั่ง password_hash("mysslweb",PASSWORD_BCRYPT); สร้างได้ private $_SALT = '$2y$10$cDKiRAzt3zWwiyAu/Nz40Om6yKe1mQZMM4T6yxAlTTI25oIUq9EVm'; // กำหนดค่าที่จะใช้งานในส่วนนี้ private $_CLIENT_ID = "108xxxxx47653-0t8ixxxxxxxx55hg45i.apps.googleusercontent.com"; private $_CLIENT_SECRET = "ddBKZxxxxxxxxxxnfhfk"; private $_CLIENT_CALLBACK = "https://www.mysslweb.com/socialconnect/google"; public function __construct(){ $this->_GOOGLE_CLIENT = new Google_Client(); } public function redirect($url){ header("Location:{$url}"); exit; } public function google(){ //Set the OAuth 2.0 Client ID $this->_GOOGLE_CLIENT->setClientId($this->_CLIENT_ID); //Set the OAuth 2.0 Client Secret key $this->_GOOGLE_CLIENT->setClientSecret($this->_CLIENT_SECRET); $this->_GOOGLE_CLIENT->setRedirectUri($this->_CLIENT_CALLBACK); $this->_GOOGLE_CLIENT->addScope('email'); $this->_GOOGLE_CLIENT->addScope('profile'); } public function connectgoogle(){ $this->google(); $this->redirect($this->_GOOGLE_CLIENT->createAuthUrl()); } public function authorizedgoogle($success_url,$error_url){ if(isset($_GET['error'])){ $this->redirect($error_url); }else{ if(isset($_GET['code'])){ $this->google(); $dataToken = $this->_GOOGLE_CLIENT->fetchAccessTokenWithAuthCode($_GET['code']); print_r($dataToken); if(!isset($dataToken['error'])){ $this->_GOOGLE_CLIENT->setAccessToken($dataToken['access_token']); $accessToken = $dataToken['access_token']; //Create Object of Google Service OAuth 2 class $google_service = new Google_Service_Oauth2($this->_GOOGLE_CLIENT); //Get user profile data from google $me = $google_service->userinfo->get(); $google_userdata = array(); $google_userID = $me->getId(); $google_email = $me->getEmail(); $google_name = $me->getName(); $google_picture = $me->getPicture(); $hashed_token = crypt($google_userID,$this->_SALT); // เก็บค่าใน seesion ไว้ไปแสดง $_SESSION['ses_user']['id'] = (isset($google_userID))?$google_userID:null; $_SESSION['ses_user']['name'] = (isset($google_name))?$google_name:null; $_SESSION['ses_user']['email'] = (isset($google_email))?$google_email:null; $_SESSION['ses_user']['picture'] = (isset($google_picture))?$google_picture:null; } if(isset($google_userID) && isset($hashed_token) && isset($accessToken)){ $this->redirect($success_url); }else{ $this->redirect($error_url); } }else{ $this->redirect($error_url); } } } } ?> <?php $social = new Socialconnect(); if(isset($_GET['action']) && $_GET['action']=="connect"){ $social->connectgoogle(); }else{ $social->authorizedgoogle("../member.php","../login.php"); } ?>
ไฟล์ facebook.php
<?php session_start(); require_once('../vendor/autoload.php'); class Socialconnect{ private $_FACEBOOK_CLIENT; // $salt สามารถใช้คำสั่ง password_hash("mysslweb",PASSWORD_BCRYPT); สร้างได้ private $_SALT = '$2y$10$cDKiRAzt3zWwiyAu/Nz40Om6yKe1mQZMM4T6yxAlTTI25oIUq9EVm'; // กำหนดค่าที่จะใช้งานในส่วนนี้ private $_APP_ID = "9xxxxxxxx0469"; private $_APP_SECRET = "15e347xxxxxxxxxxfa9e73"; private $_APP_CALLBACK = "https://www.mysslweb.com/socialconnect/facebook"; public function __construct(){ $this->_FACEBOOK_CLIENT = $this->facebook(); } public function redirect($url){ header("Location:{$url}"); exit; } public function facebook(){ return new \Facebook\Facebook([ 'app_id' => $this->_APP_ID, 'app_secret' => $this->_APP_SECRET, 'default_graph_version' => 'v7.0', //'default_access_token' => '{access-token}', // optional ]); } public function connectfacebook(){ $helper = $this->_FACEBOOK_CLIENT->getRedirectLoginHelper(); $permissions = ['email,public_profile']; // Optional permissions $loginUrl = $helper->getLoginUrl($this->_APP_CALLBACK, $permissions); $this->redirect($loginUrl); } public function authorizedfacebook($success_url,$error_url){ if(isset($_GET['error'])){ $this->redirect($error_url); }else{ if(isset($_GET['code'])){ $helper = $helper = $this->_FACEBOOK_CLIENT->getRedirectLoginHelper(); try { $accessToken = $helper->getAccessToken(); } catch(\Facebook\Exceptions\FacebookResponseException $e) { // When Graph returns an error $this->redirect($error_url); } catch(\Facebook\Exceptions\FacebookSDKException $e) { // When validation fails or other local issues $this->redirect($error_url); } if (isset($accessToken)) { $response = $this->_FACEBOOK_CLIENT->get('/me?fields=id,name,email,picture', $accessToken); $profile_picture = $this->_FACEBOOK_CLIENT->get('/me/picture?type=large', $accessToken); $me = $response->getGraphUser(); $picture = $profile_picture->getHeaders(); $fb_userID = $me->getId(); $fb_name = $me->getName(); $fb_email = $me->getEmail(); $fb_picture = $me->getPicture(); $hashed_token = crypt($fb_userID, $this->_SALT); // เก็บค่าใน seesion ไว้ไปแสดง $_SESSION['ses_user']['id'] = (isset($fb_userID))?$fb_userID:null; $_SESSION['ses_user']['name'] = (isset($fb_name))?$fb_name:null; $_SESSION['ses_user']['email'] = (isset($fb_email))?$fb_email:null; $_SESSION['ses_user']['picture'] = (isset($picture['location']))?$picture['location']:null; } if(isset($fb_userID) && isset($hashed_token) && isset($accessToken)){ $this->redirect($success_url); }else{ $this->redirect($error_url); } }else{ $this->redirect($error_url); } } } } ?> <?php $social = new Socialconnect(); if(isset($_GET['action']) && $_GET['action']=="connect"){ $social->connectfacebook(); }else{ $social->authorizedfacebook("../member.php","../login.php"); } ?>
ไฟล์ twitter.php
<?php session_start(); require_once('../vendor/autoload.php'); use Abraham\TwitterOAuth\TwitterOAuth; class Socialconnect{ private $_TWITTER_CLIENT; // $salt สามารถใช้คำสั่ง password_hash("mysslweb",PASSWORD_BCRYPT); สร้างได้ private $_SALT = '$2y$10$cDKiRAzt3zWwiyAu/Nz40Om6yKe1mQZMM4T6yxAlTTI25oIUq9EVm'; // กำหนดค่าที่จะใช้งานในส่วนนี้ private $_API_KEY = "nMSxxxxxxafvLob"; private $_API_SECRET = "UUB3OxxxxxxxGicKKptayYikz"; private $_API_CALLBACK = "https://www.mysslweb.com/socialconnect/twitter"; public function __construct(){ $this->_TWITTER_CLIENT = $this->twitter(); } public function redirect($url){ header("Location:{$url}"); exit; } public function twitter($token=null,$token_secret=null){ return new TwitterOAuth( $this->_API_KEY, $this->_API_SECRET, $token, $token_secret); } public function connecttwitter(){ $callback_url = $this->_API_CALLBACK; $request_token = $this->_TWITTER_CLIENT->oauth('oauth/request_token', array('oauth_callback' => $callback_url)); $_SESSION['oauth_token'] = $request_token['oauth_token']; $_SESSION['oauth_token_secret'] = $request_token['oauth_token_secret']; $authUrl = $this->_TWITTER_CLIENT->url('oauth/authorize', array('oauth_token' => $request_token['oauth_token'])); $this->redirect($authUrl); } public function authorizedtwitter($success_url,$error_url){ if(isset($_GET['denied'])){ $this->redirect($error_url); }else{ if(isset($_GET['oauth_verifier'])){ try{ $this->_TWITTER_CLIENT = $this->twitter($_SESSION['oauth_token'],$_SESSION['oauth_token_secret']); $access_token = $this->_TWITTER_CLIENT->oauth("oauth/access_token", ["oauth_verifier" => $_GET['oauth_verifier']]); }catch(\Abraham\TwitterOAuth\TwitterOAuthException $e){ $this->redirect($error_url); } if(isset($access_token['oauth_token']) && isset($access_token['oauth_token_secret']) ){ $this->_TWITTER_CLIENT = $this->twitter($access_token['oauth_token'], $access_token['oauth_token_secret']); $me = $this->_TWITTER_CLIENT->get('account/verify_credentials',['include_email' => true]); $accessToken = $access_token['oauth_token']; $twitter_userdata = array(); $twitter_userdata['picture'] = str_replace("normal","400x400",$me->profile_image_url_https); $twitter_userID = $me->id; $twitter_name = $me->name; $twitter_email = (isset($me->email))?$me->email:null; $twitter_picture =$twitter_userdata['picture']; $hashed_token = crypt($twitter_userID, $this->_SALT); // เก็บค่าใน seesion ไว้ไปแสดง $_SESSION['ses_user']['id'] = (isset($twitter_userID))?$twitter_userID:null; $_SESSION['ses_user']['name'] = (isset($twitter_name))?$twitter_name:null; $_SESSION['ses_user']['email'] = (isset($twitter_email))?$twitter_email:null; $_SESSION['ses_user']['picture'] = (isset($twitter_picture))?$twitter_picture:null; }else{ $this->redirect($error_url); } if(isset($twitter_userID) && isset($hashed_token) && isset($accessToken)){ $this->redirect($success_url); }else{ $this->redirect($error_url); } }else{ $this->redirect($error_url); } } } } ?> <?php $social = new Socialconnect(); if(isset($_GET['action']) && $_GET['action']=="connect"){ $social->connecttwitter(); }else{ $social->authorizedtwitter("../member.php","../login.php"); } ?>
ในการทำงานการเข้าถึงข้อมูลผู้ใช้ หากเกิดข้อผิดพลาดใดๆ เราจะทำการลิ้งค์ไปยังหน้า error_url ที่กำหนด ในที่นี้
คือหน้า login หากเราต้องการตรวจสอบโค้ด หรือ dubug สามารถแทรกคำสั่ง ที่ต้องการเข้าไป เพื่อแสดงค่าข้อมูล
ดูลำดับการทำงานได้ เช่น
if(array_key_exists('id_token',$dataToken)){ $line_userdata = json_decode($dataToken['user'],true); // ค่า ID , name , picture ที่เราสามารถนำไปใช้ได้ $line_userID = $line_userdata['sub']; $line_userName = $line_userdata['name']; $line_email = $line_userdata['email']; $line_userPicture = $line_userdata['picture']; $hashed_token = crypt($line_userID,$this->_SALT); // dubug var_dump($line_userdata); exit; // เก็บค่าใน seesion ไว้ไปแสดง $_SESSION['ses_user']['id'] = (isset($line_userID))?$line_userID:null; $_SESSION['ses_user']['name'] = (isset($line_userName))?$line_userName:null; $_SESSION['ses_user']['email'] = (isset($line_email))?$line_email:null; $_SESSION['ses_user']['picture'] = (isset($line_userPicture))?$line_userPicture:null; }
ในขั้นตอนก่อนจะลิ้งค์ไปยังหน้า member หลังจากสร้าง session เรียบร้อยแล้ว เราสามารถประยุกต์จัดการกำหนดฐาน
ข้อมูล โดยแทรกการทำงานเข้าไปในส่วนนี้ได้ เช่น
if(isset($line_userID) && isset($hashed_token) && isset($accessToken)){ // แทรกการทำงานที่ต้องการ เช่น การบันทึกลงฐานข้อมูล หรืออื่นๆ $this->redirect($success_url); }else{ $this->redirect($error_url); }
ใน DEMO ด้านล่าง จะแสดงสาธิตการทำงานในระบบทดสอบให้ดู
เนื้อหาตอนนี้ ผู้เขียนต้องการให้ เห็นภาพการทำงานโดยรวม ของแต่ละ platform และทำความเข้าใจเบื้องต้น โดยไม่ต้องการ
นำเอาในส่วนของการใช้งานร่วมกับฐานข้อมูลมารวมในเนื้อหานี้ แต่เนื้อหาการใช้งานกับฐานข้อมูล เราจะมีแน่นอนในตอนต่อๆ ไป
การใช้งานร่วมกับฐานข้อมูล ยังสามารถใช้งานแยกย่อยไปได้หลายแบบ เช่น
- ระบบที่สมัครสมาชิกโดยใช้ social login เท่านั้น หรือก็คือ ใช้ข้อมูลจากการล็อกอิน สร้างบัญชีผู้ใช้งานใหม่ พร้อมสร้าง
ระบบสมาชิกเพิ่มเติม
- ระบบที่มีการสมัครสมาชิกแบบปกติ มีฟอร์มสำหรับสมัครชิก และรองรับการสมัครชิกด้วยการล็อกอินผ่านระบบ socail login
แล้วทำการเชื่อมโยงข้อมูลกัน
- ระบบที่มีการสมัครสมาชิกโดยใช้รุปแบบที่กำหนด และต้องการเชื่อมการล็อกอินด้วย social กับบัญชีสมาชิกที่มีในระบบแล้ว
เหมือนเป็นการลิ้งค์บัญชี
เหล่านี้เป็นแนวทางการประยุกต์ที่เป็นไปตาม ยังไงรอติดตาม เนื้อหาในตอนต่อไป