В настоящее время я работаю над веб-сайтом для компании, которая хочет показать свои (компании) обновления LinkedIn на веб-странице. На мой взгляд, это должно быть возможно обойтись без необходимости входа для зрителя (oAuth), однако я не могу найти работающее решение.
Я много гуглил и довольно тщательно прочитал документацию, но не смог найти удовлетворительного ответа. Поэтому я прихожу к вам.
Текущий случай
Без oAuth-авторизации появляется ошибка 504 Gateway, в противном случае зритель должен войти в LinkedIn для просмотра обновлений компании. Еще одна странность в том, что несколько недель назад API работал нормально: обновления компании показывались без необходимости входа для зрителя, кто-нибудь еще испытывал это?
Вопросы
Если да, не могли бы вы показать мне пример с собственными обновлениями LinkedIn? Потому что документация не имеет большого смысла в этом вопросе.
Небольшая оболочка API первой версии, которую я создал для этой цели:
<?php
class Linkedin{
const API_LINK = 'https://api.linkedin.com/v1/'; // Link to API
const AUTH_LINK = 'https://www.linkedin.com/uas/oauth2/authorization?'; // Authorisation link
const ACC_LINK = 'https://www.linkedin.com/uas/oauth2/accessToken?'; // Access token link
private $sApikey;
private $sApisecret;
private $sState;
private $sScope;
private $sRedirectUri;
private $aErrors = array();
public function __construct($aParams = array()){
/* Check input */
if(count($aParams)<1){
logmsg('There where no parameters given to the linkedin api.');
return false;
}
/* Basic settings */
$aSettings = array(
'api_key' => null,
'api_secret' => null,
'scope' => 'r_basicprofile',
'redirect_uri' => 'http://' . $_SERVER['SERVER_NAME']
);
$aSettings = array_merge($aSettings,$aParams);
/* Set variables */
$this->sApikey = $aSettings['api_key'];
$this->sApisecret = $aSettings['api_secret'];
$this->sScope = $aSettings['scope'];
$this->sRedirectUri = $aSettings['redirect_uri'];
}public function company($iCompanyID, $aSettings = array()){
$aOutput = $this->fetch('GET', 'companies/'.$iCompanyID.'/updates', $aSettings);
logmsg($aOutput);
return $aOutput;
}public function getErrors($sType = 'array'){
switch($sType){
case 'html':
$sOutput = '<div class="error">';
$sOutput.= '<p>The LinkedIn API failed to connect due to the following error(s):</p>';
$sOutput.= '<ul>';
foreach($this->aErrors as $i => $sError){
$sOutput.= '<li>'.$sError.'</li>';
}
$sOutput.= '</ul></div>';
return $sOutput;
case 'array':
default:
return $this->aErrors;
}
}
private function setError($sString){
$this->aErrors[] = $sString;
}/* The actual fetch */
private function fetch($sMethod, $sLink, $aParams = array()) {
if($_SESSION['access_code']){
$aHeaders = array(
'Authorization' => 'Bearer ' . $_SESSION['access_token'],
'x-li-format' => 'json', // Comment out to use XML
);
}
// Need to use HTTPS
$sUrl = trim(self::API_LINK,'/').'/' . trim($sLink,'/');
// Append query parameters (if there are any)
if (count($aParams)) {
$sUrl .= '?' . http_build_query($aParams);
}
// Tell streams to make a (GET, POST, PUT, or DELETE) request
// And use OAuth 2 access token as Authorization
$context = stream_context_create(
array('http' =>
array('method' => $sMethod,
'header' => (isset($aHeaders)) ? $aHeaders : null
)
)
);
// Hocus Pocus
$sResponse = file_get_contents($sUrl, false, $context);
// Native PHP object, please
return json_decode($sResponse);
}
/* Authorisation handler */
public function oAuth(){
// OAuth 2 Control Flow
if (isset($_GET['error'])) {
$this->setError(trim(htmlentities($_GET['error'].': '.$_GET['error_description'])));
return false;
} elseif (isset($_GET['code'])) {
// User authorized your application
if ($this->getState() == $_GET['state']) {
// Get token so you can make API calls
if($this-getAccessToken()){
return true;
}
} else {
logmsg('Possible CRFS attack. Wrong state code: "'.$this->getState() .'" != "'.$_GET['state'].'"',2);
$this->setError('Login to Linkedin failed because an attack was detected.');
return false;
}
} else {
if ((empty($_SESSION['expires_at'])) || (time() > $_SESSION['expires_at'])) {
// Token has expired, clear the state
$_SESSION = array();
}
if (!isset($_SESSION['access_token']) || empty($_SESSION['access_token'])) {
// Start authorization process
$this->getAuthorisation();
}
}
}
/* Get Authorisation code */
private function getAuthorisation(){
$aParams = array(
'response_type' => 'code',
'client_id' => $this->sApikey,
'scope' => $this->sScope,
'state' => $this->getState(),
'redirect_uri' => $this->sRedirectUri,
);
// Authentication request
$sUrl = self::AUTH_LINK . http_build_query($aParams);
// Redirect user to authenticate
header("Location: $sUrl");
exit();
}
/* Get access token */
private function getAccessToken(){
$aParams = array(
'grant_type' => 'authorization_code',
'client_id' => $this->sApikey,
'client_secret' => $this->sApisecret,
'code' => $_GET['code'],
'redirect_uri' => $this->sRedirectUri,
);
// Access Token request
$sUrl = self::ACC_LINK . http_build_query($aParams);
// Tell streams to make a POST request
$sContext = stream_context_create(
array('http' => array('method' => 'POST') )
);
// Retrieve access token information
$sResponse = file_get_contents($sUrl, false, $sContext);
// Native PHP object, please
$oToken = json_decode($sResponse);
// Store access token and expiration time
$_SESSION['access_token'] = $oToken->access_token; // guard this!
$_SESSION['expires_in'] = $oToken->expires_in; // relative time (in seconds)
$_SESSION['expires_at'] = time() + $_SESSION['expires_in']; // absolute time
return true;
}private function getState(){
if(is_null($this->sScope)){
if(!isset($_SESSION['ln-api-scope'])){
$_SESSION['ln-api-scope'] = md5(uniqid(rand(), true));
}
$this->sScope = $_SESSION['ln-api-scope'];
}
return $this->sScope;
}
}
С областью действия, установленной на rw_nus
и ключ API и секрет поставляются.
Спасибо за любую помощь заранее.
С наилучшими пожеланиями,
кадров в секунду
Задача ещё не решена.
Других решений пока нет …