目前,我正在为一家希望在网页上展示其(公司)LinkedIn更新的公司开发网站。在我看来,这应该可以在不需要登录查看器(oAuth)的情况下完成,但是,我无法找到可行的解决方案。
我已经搜索了很多内容,并且非常彻底地阅读了文档,但找不到令人满意的答案。因此,我来找你。
当前案例
如果没有oAuth授权,则会出现504 Gateway错误,否则观看者需要登录LinkedIn才能查看公司更新。另一个奇怪的事情是,几个星期前,API运行良好:公司更新显示无需登录查看器,是否有其他人体验过这个?
问题
如果是这样,你能告诉我一个关于LinkedIn自己更新的例子吗?因为文档在这一点上没有多大意义。
[只是为了确认]是否有其他人对LinkedIn API的授权需求有所改变?
我为此目的创建的小型第一版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密钥和密码。
感谢您提前提供任何帮助。
亲切的问候,
FPS