В предыдущих частях этой серии мы создавали наши начальные интерфейсы, настраивали нашу функцию входа в Google+ и говорили о том, как мы можем объединить наши учетные записи. В этой статье мы интегрируем Twitter и Facebook в наше приложение. Вы увидите много сходства со статьей Google+ , поэтому, если вы сможете легко следовать этой статье , у вас не будет особых проблем с этой статьей . Если вы еще не читали эту статью, я предлагаю вам сначала прочитать ее, прежде чем продолжить эту статью.
Вы можете просмотреть код для всех статей на этой странице Github .
Аутентификация в твиттере
Еще раз, мы начнем с создания следующего каталога: src/SitePoint/SocialLogin/Twitter
В этом каталоге мы создаем класс TwitterLogin
Этот класс реализует интерфейс SocialLoginInterface
Убедитесь, что свойство, называемое service
Как и в Google+, у Twitter есть некоторые особые потребности, чтобы мы могли войти в систему. Поэтому убедитесь, что в классе присутствуют следующие 3 свойства:
- ID клиента
- ключ
- URL обратного вызова
Поскольку все 3 свойства необходимы для работы нашего приложения, наш конструктор получит эти 3 переменные в качестве параметров и установит свойства.
До сих пор ваш код должен выглядеть так же, как первый пример в статье Google+ .
Наш следующий шаг — создать наш сервис Twitter. Мы будем использовать ту же библиотеку OAuth и установим соединение в методе init.
Прежде чем мы сможем начать, мы должны добавить некоторые операторы использования в начало нашего класса.
use OAuth\ServiceFactory;
use OAuth\OAuth1\Service\Twitter;
use OAuth\Common\Storage\Session;
use OAuth\Common\Consumer\Credentials;
Все для нашего метода init теперь присутствует. Время установить нашу связь с Twitter. Мы делаем это с помощью основных примеров библиотеки OAuth, которую мы используем.
/**
* Initializes our service
*/
public function init()
{
$storage = new Session();
$serviceFactory = new ServiceFactory();
$credentials = new Credentials($this->clientId, $this->key, $this->callbackUrl);
$this->service = $serviceFactory->createService('twitter', $credentials, $storage);
return $this;
}
Наш сервис настроен, поэтому мы можем продолжить, заполнив другие методы интерфейса. Мы начнем с метода getLoginUrl
Этот метод возвращает URL-адрес, на который вы будете перенаправлять пользователя.
/**
* Returns the login url for the social network
*
* @return string
*/
public function getLoginUrl()
{
$token = $this->service->requestRequestToken();
return $this->service->getAuthorizationUri(array('oauth_token' => $token->getRequestToken()));
}
Вы можете заметить, что этот метод (и следующий, который мы обсудим) немного отличается от статьи в Google+. Это связано с тем, что Google+ использует OAuth 2, а Twitter использует OAuth 1. Twitter был одной из первых компаний, использовавших OAuth, поскольку в то время первоначальный создатель OAuth работал в Twitter. Твиттер все еще использует OAuth 1, хотя они продвигаются к переходу на OAuth 2.
Следующий метод для определения — метод loginCallback
Когда пользователь принимает данные Twitter для обмена с вашим приложением, он будет перенаправлен обратно на URL-адрес, который вы определили как callbackUrl
Когда пользователь запрашивает этот URL, вы должны вызвать метод loginCallback
Если все прошло хорошо, теперь мы можем получить данные из Twitter.
/**
* Handles the login callback from the social network
*
* @return SocialUserInterface
*/
public function loginCallback()
{
$storage = new Session();
$token = $storage->retrieveAccessToken('Twitter');
$this->service->requestAccessToken(
$_GET['oauth_token'],
$_GET['oauth_verifier'],
$token->getRequestTokenSecret()
);
$userData = json_decode($this->service->request('account/verify_credentials.json'), true);
$twitterUser = new TwitterUser($userData);
return $twitterUser;
}
На этот раз мы используем класс с именем TwitterUser
SocialUserInterface
Однако этого класса еще нет. Время создать это!
Пользователь Twitter
Twitter возвращает данные другим способом, нежели Google+, поэтому нам нужно снова нормализоваться. Нам нужно создать класс с именем TwitterUser
SocialUserInterface
В этом случае конструктор этого класса ожидает необработанные данные Twitter. В каждом получателе мы будем извлекать нужные данные из необработанных данных. В конце ваш класс TwitterUser
<?php
namespace SitePoint\SocialLogin\Twitter;
use SitePoint\SocialLogin\Interfaces\SocialUserInterface;
class TwitterUser implements SocialUserInterface {
/**
* @var mixed user data
*/
private $userData;
/**
* Constructor.
*
* @param $userData mixed Raw social network data for this particular user
*/
public function __construct($userData)
{
$this->userData = $userData;
}
/**
* Get the provider name
*
* @return string
*/
public function getProvider()
{
return "twitter";
}
/**
* Get the UID of the user
*
* @return string
*/
public function getUid()
{
if(array_key_exists('id', $this->userData)) {
return $this->userData['id'];
}
return null;
}
/**
* Get the first name of the user
*
* @return string
*/
public function getFirstname()
{
if(array_key_exists('name', $this->userData)) {
list($firstname, $lastname) = explode(" ", $this->userData['name']); // TODO: Of course you have to make this smarter
return $firstname;
}
return null;
}
/**
* Get the last name of the user
*
* @return string
*/
public function getLastname()
{
if(array_key_exists('name', $this->userData)) {
list($firstname, $lastname) = explode(" ", $this->userData['name']); // TODO: Of course you have to make this smarter
return $lastname;
}
return null;
}
/**
* Get the username
*
* @return string
*/
public function getUsername()
{
if(array_key_exists('screen_name', $this->userData)) {
return $this->userData['screen_name'];
}
return null;
}
/**
* Get the emailaddress
*
* @return string
*/
public function getEmailAddress()
{
return null;
}
/**
* Get the city
*
* @return string
*/
public function getCity()
{
if(array_key_exists('location', $this->userData)) {
return $this->userData['location'];
}
return null;
}
/**
* Get the birthdate
*
* @return string
*/
public function getBirthDate()
{
return null;
}
/**
* Get the gender
*
* @return string
*/
public function getGender()
{
return null;
}
}
Вы можете заметить, что у нас намного меньше информации, чем с Google+. Твиттер просто не делится такой большой информацией. Например, нам не хватает адреса электронной почты, хотя это одно из самых распространенных полей, которые вы хотели бы иметь в своем приложении.
Единственное, что вы можете сделать, это, после входа в Twitter, попросить пользователя ввести свой адрес электронной почты и сохранить его в своей базе данных. Кроме этого, вы можете попытаться объединить учетную запись Twitter с уже заданной учетной записью, как в предыдущей части этой серии.
Логин в фейсбук
Обладая знаниями, которые вы получили из объяснений в Google+ и Twitter, вам будет легко настроить версию Facebook. Здесь у вас есть полная реализация для класса входа в систему.
<?php
namespace SitePoint\SocialLogin\Facebook;
use SitePoint\SocialLogin\Interfaces\SocialLoginInterface;
use OAuth\ServiceFactory;
use OAuth\OAuth2\Service\Facebook;
use OAuth\Common\Storage\Session;
use OAuth\Common\Consumer\Credentials;
class FacebookLogin implements SocialLoginInterface {
/**
* Facebook service
*
* @var string
*/
protected $service;
/**
* OAuth client ID
*
* @var string
*/
protected $clientId;
/**
* OAuth key
*
* @var string
*/
protected $key;
/**
* Callback url
*
* @var string
*/
protected $callbackUrl;
/**
* Constructor.
*
* @param $clientId string
* @param $key string
* @param $callbackUrl string
*/
public function __construct($clientId, $key, $callbackUrl)
{
$this->clientId = $clientId;
$this->key = $key;
$this->callbackUrl = $callbackUrl;
}
/**
* Initializes our service
*/
public function init()
{
$storage = new Session();
$serviceFactory = new ServiceFactory();
$credentials = new Credentials($this->clientId, $this->key, $this->callbackUrl);
$this->service = $serviceFactory->createService(
'facebook',
$credentials,
$storage,
array(
Facebook::SCOPE_EMAIL,
Facebook::SCOPE_USER_BIRTHDAY,
Facebook::SCOPE_USER_LOCATION
)
);
return $this;
}
/**
* Returns the login url for the social network
*
* @return string
*/
public function getLoginUrl()
{
return $this->service->getAuthorizationUri();
}
/**
* Handles the login callback from the social network
*
* @param string $accessCode
*
* @return SocialUserInterface
*/
public function loginCallback($accessCode)
{
$token = $this->service->requestAccessToken($accessCode);
// Send a request with it
$userData = json_decode($this->service->request('/me'), true);
$facebookUser = new FacebookUser($userData);
return $facebookUser;
}
}
Вы можете заметить, что я определил некоторые области при создании сервиса Facebook. Определив эти области, я могу получить некоторые дополнительные детали от пользователя. В этом случае я также собираю адрес электронной почты, день рождения и местоположение. Учтите, что чем больше данных вы соберете, тем больше у вас шансов, что пользователь откажется войти в приложение.
Пользователь facebook
Пользовательский класс еще проще и не содержит никаких сюрпризов. Когда закончите, это должно выглядеть так.
<?php
namespace SitePoint\SocialLogin\Facebook;
use SitePoint\SocialLogin\Interfaces\SocialUserInterface;
class FacebookUser implements SocialUserInterface {
/**
* @var mixed user data
*/
private $userData;
/**
* Constructor.
*
* @param $userData mixed Raw social network data for this particular user
*/
public function __construct($userData)
{
$this->userData = $userData;
}
/**
* Get the provider name
*
* @return string
*/
public function getProvider()
{
return "facebook";
}
/**
* Get the UID of the user
*
* @return string
*/
public function getUid()
{
if(array_key_exists('id', $this->userData)) {
return $this->userData['id'];
}
return null;
}
/**
* Get the first name of the user
*
* @return string
*/
public function getFirstname()
{
if(array_key_exists('first_name', $this->userData)) {
return $this->userData['first_name'];
}
return null;
}
/**
* Get the last name of the user
*
* @return string
*/
public function getLastname()
{
if(array_key_exists('last_name', $this->userData)) {
return $this->userData['last_name'];
}
return null;
}
/**
* Get the username
*
* @return string
*/
public function getUsername()
{
if(array_key_exists('name', $this->userData)) {
return str_replace(" ", "_", $this->userData['name']);
}
return null;
}
/**
* Get the emailaddress
*
* @return string
*/
public function getEmailAddress()
{
if(array_key_exists('email', $this->userData)) {
return $this->userData['email'];
}
return null;
}
/**
* Get the city
*
* @return string
*/
public function getCity()
{
if(array_key_exists('location', $this->userData)) {
return $this->userData['location'];
}
return null;
}
/**
* Get the birthdate
*
* @return string
*/
public function getBirthDate()
{
if(array_key_exists('birthday', $this->userData)) {
return $this->userData['birthday'];
}
return null;
}
/**
* Get the gender
*
* @return string
*/
public function getGender()
{
if(array_key_exists('location', $this->userData)) {
return $this->userData['location']['name'];
}
return null;
}
}
Быстрый тест
Если вы хотите выполнить быстрый тест для проверки кода, клонируйте репозиторий Github на локальный компьютер и переключитесь на ветку с именем part4
В этой ветке вы увидите testTwitter.php
testFacebook.php
Вы можете заполнить сведения об API обеих служб и запустить файл в своем браузере. При запросе страницы вы будете перенаправлены на страницу социальной сети с просьбой поделиться информацией.
Когда вы нажмете «Принять», вы будете перенаправлены обратно на страницу, которую вы настроили в качестве URL обратного вызова, с указанием вашего имени и фамилии.
Вывод
В этой статье мы взяли основу, которую мы заложили в предыдущих статьях, и продолжили работу над этим. Рядом с Google+ теперь мы можем войти через Twitter и Facebook. Во всех случаях мы возвращаем нормализованный пользовательский объект, который мы можем добавить в нашу собственную пользовательскую систему. С этой статьей мы подошли к концу этой серии. Это дало вам некоторое представление о том, как обращаться с пакетами, не связанными с социальными сетями или инфраструктурой? Не стесняйтесь задавать любые вопросы в комментариях ниже!