I created a new application in Linkedin with r_basicprofile and r_emailaddress flags set to active.
I'm using the following PHP library (with CodeIgniter framework) to get user profile data. As you can see on the results, for some reason I can't get the e-mail address of user.
Someone know how to get the e-mail address ?
Thank you.
class linkedin
{
private $client_id = "123456789";
private $client_secret = "123456789012356";
public function in_redirect_url($redirect_url){
$state = $this->in_genState();
return "https://www.linkedin.com/oauth/v2/authorization?response_type=code&client_id=$this->client_id&state=$state&scope=r_basicprofile&redirect_uri=$redirect_url";
}
public function in_genState()
{
return "123456789";
}
public function in_exchange_code_token($code)
{
// replace code with auth token
$url = 'https://www.linkedin.com/oauth/v2/accessToken';
$headers = [
'Content-type: application/x-www-form-urlencoded',
'Host: www.linkedin.com',
];
$fields = [
'grant_type' => 'authorization_code',
'code' => $code,
'redirect_uri' => base_url('login/linkedin'),
'client_id' => $this->client_id,
'client_secret' => $this->client_secret,
];
//url-ify the data for the POST
$fields_string = '';
foreach ($fields as $key => $value) {
$fields_string .= $key.'='.$value.'&';
}
rtrim($fields_string, '&');
// init curl handle
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// execute!
$response = curl_exec($ch);
// close the connection, release resources used
curl_close($ch);
// do anything you want with your response
$response = json_decode($response);
return $response;
}
public function in_get_user_data($auth_token)
{
// replace code with auth token
$url = 'https://api.linkedin.com/v1/people/~:(email-address,id,first-name,last-name,location)';
$headers = [
'Host: api.linkedin.com',
'Connection: Keep-Alive',
];
$fields = [
'oauth2_access_token' => $auth_token,
'format' => 'json',
];
//url-ify the data
$fields_string = '';
foreach ($fields as $key => $value) {
$fields_string .= $key.'='.$value.'&';
}
rtrim($fields_string, '&');
// init curl handle
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url.'?'.$fields_string);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// execute!
$response = curl_exec($ch);
// close the connection, release resources used
curl_close($ch);
// do anything you want with your response
$response = json_decode($response);
return $response;
}
}
And the following login code:
public function linkedin()
{
$code = $this->input->get('code');
$state = $this->input->get('state');
if (!$code) {
// redirect to linkedin login
$local_url = base_url('/login/linkedin');
header("Location: " . $this->linkedin->in_redirect_url($local_url));
die();
return;
}
// verify state
if ($state != $this->linkedin->in_genState()) {
echo 'Invalid request';
die(400);
}
$response = $this->linkedin->in_exchange_code_token($code);
if (property_exists($response, 'access_token')) {
echo 'Success !<br/>';
var_dump($response);
$access_token = $response->access_token;
var_dump($this->linkedin->in_get_user_data($access_token));
} else {
echo 'Error !<br/>';
var_dump($response);
}
}
This is an example result:
Success !
object(stdClass)[74]
public 'access_token' => string '*****' (length=179)
public 'expires_in' => string '5184000000' (length=10)
object(stdClass)[75]
public 'firstName' => string '***' (length=6)
public 'id' => string '***' (length=10)
public 'lastName' => string '***' (length=8)
public 'location' =>
object(stdClass)[76]
public 'country' =>
object(stdClass)[77]
public 'code' => string 'us' (length=2)
public 'name' => string 'United States' (length=6)
If you look in this section of your code:
public function in_redirect_url($redirect_url){
$state = $this->in_genState();
return "https://www.linkedin.com/oauth/v2/authorization?response_type=code&client_id=$this->client_id&state=$state&scope=r_basicprofile&redirect_uri=$redirect_url";
}
Note that your &scope= parameter only requests r_basicprofile, and not r_emailaddress. If you want to rely on your LinkedIn application's default permissions to control what permission your app requests, you cannot specify a scope in your auth flow. If you do, it will override it - which is what's happening here, and you're overriding your scope to a value that does not include all of the member permissions that you think.
Related
I've this mutation that allows me to insert a client inside a collection in MongoDB.
when i create the function the php trows a error 500.
it's strange for me because it happens when i write the function, and not when i call it
the function is:
function graphQLPost(string $endpoint, string $query, array $variables = [], ?string $token = null)
{
$payload = json_encode(['query' => $query, 'variables' => $variables]);
$headers = array();
if ($token != null) {
$headers[] = "Content-Type: application/json\r\n" .
'Authorization: Bearer ' . $token;
} else
$headers[] = 'Content-Type: application/json';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $endpoint);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 0);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
// Submit the POST request
$resultJson = curl_exec($ch);
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
// Close cURL session handle
curl_close($ch);
return array($resultJson, $httpcode);
}
// definiamo la mutation
$mutation = '
mutation createClients($project_id: ID!, $input: ClientInput!) {
createClients(project_id: $project_id, input: $input) {
id
firstName
lastName
tel
email
trattamento
profilazione
marketing
}
} ';
// parametri da passare come argomenti
$param = [
'project_id' => $PROJECT_ID,
'input' => array(
'firstName' => $nome,
'lastName' => $cognome,
'email' => $email,
'tel' => $telefono,
'trattamento' => $trattamento_DB,
'profilazione' => $profilazione_DB,
'marketing' => $marketing_DB,
'status' => 'lead',
)
];
// esecuzione del comando
$response = graphQLPost($API_URI, $mutation, $param, $TOKEN);
just find out why. i made a stupid syntax error here ?string $token = null
the question mark isn't necessary.
I got method in getting the access token and here it is
public $token; //I declare global var to read in every func
public function getToken(){
$key = 'xxxxxxxxxxxxxx';
$secret = 'xxxxxxxxxxxxxxxxxx';
$data = array(
'key' => 'xxxxxxxxxxxxxxxxxx',
'secret' => 'xxxxxxxxxxxxxxx'
);
$payload = json_encode($data);
$ch = curl_init('https://cgi.singmap.com/token?key='.$key.'&secret='.$secret.'');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/x-www-form-urlencoded',
'Accept: application/json',
'Content-Length: ' . strlen($payload))
);
// Submit the POST request
$response = json_decode(curl_exec($ch), true);
$trimmed = $response['datas'];
$token = $trimmed['access_token'];
curl_close($ch);
$this->token = $token;
}
The token only lasts for 5 minutes to use. But in my other method like this which uses token
public function propertyUnitDetails(){
$unitId = \DB::table('property_unit_list')
->select('projectId','unitId')
->get();
foreach($unitId as $res){
$this->getToken();
$final_token = $this->token;
// dd($final_token);
$request_time = Carbon::now()->format('YmdHis');
$sign = md5($final_token.$request_time);
$pageNo = 1;
$pageSize = 200;
$url = 'https://cgi.singmap.com/unit/queryUnitDetail?request_time='.$request_time.
'&token='.$final_token.'&sign='.$sign.'&projectId='.$res->projectId.'&unitId='.$res->unitId.'';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$response = json_decode(curl_exec($ch), true);
$trimmed = $response['datas'];
if(empty($trimmed)){
$this->getToken();
$final_token = $this->token;
}
foreach ($trimmed as $data){
$inserts[] = [
'projectId' => $res->projectId,
'stack' => $data['stack'],
'floorPlanId' => $data['floorPlanId'],
'soldBy' => $data['soldBy'],
'transactionPrice' => $data['transactionPrice'],
'type' => $data['type'],
'unitId' => $data['unitId'],
'floorPlanName' => $data['floorPlanName'],
'price1' => $data['price1'],
'price2' => $data['price2'],
'price3' => $data['price3'],
'price4' => $data['price4'],
'custom1' => $data['custom1'],
'custom2' => $data['custom2'],
'custom3' => $data['custom3'],
'custom4' => $data['custom4'],
'direction' => $data['direction'],
'area' => $data['area'],
'buildName' => $data['buildName'],
'unitName' => $data['unitName'],
'buildId' => $data['buildId'],
'bathrooms' => $data['bathrooms'],
'transactionDate' => $data['transactionDate'],
'bedrooms' => $data['bedrooms'],
'purchaseStatus' => $data['purchaseStatus'],
];
}
}
$chuncked = array_chunk($inserts, 10);
foreach($chuncked as $inserts){
\DB::table('property_project_details')->insert($inserts);
}
dd('record inserted');
}
When the function is not completely excecuted or the data is not fully inserted, maybe because it has a large amount of data. It throws an error of datas index is not found or something from the curl response. It is because I can only get the datas based on the token i get manually or declared manually. What I want is that if the token expires, it will run the function getToken() and pass the token to the running function in order to avoid interrupting it.
EDIT:
I added
$this->getToken();
$final_token = $this->token;
in my foreach statement because #user001232 said that in every unitId result query I got, a new token would be generated. But I still got an error every 5 mins that is because i cant get a new token even if i add that function in there.
Here you go, this will work:
<?php
class NameOfYourClass {
public $token;
public function refreshToken()
{
$key = 'xxxxxxxxxxxxxx';
$secret = 'xxxxxxxxxxxxxxxxxx';
$data = array(
'key' => 'xxxxxxxxxxxxxxxxxx',
'secret' => 'xxxxxxxxxxxxxxx'
);
$payload = json_encode($data);
$ch = curl_init('https://cgi.singmap.com/token?key='.$key.'&secret='.$secret.'');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/x-www-form-urlencoded',
'Accept: application/json',
'Content-Length: ' . strlen($payload))
);
$response = json_decode(curl_exec($ch), true);
$trimmed = $response['datas'];
$this->token = $trimmed['access_token'];
curl_close($ch);
}
private function getUnitDetails($res, $attempts = 1)
{
// We only allow 5 attempts to avoid getting into infinite loops
if ($attempts > 5) {
throw new \Exception('Signmap API Issue');
}
$request_time = Carbon::now()->format('YmdHis');
$sign = md5($this->token.$request_time);
$pageNo = 1;
$pageSize = 200;
$url = 'https://cgi.singmap.com/unit/queryUnitDetail?request_time='.$request_time.
'&token='.$this->token.'&sign='.$sign.'&projectId='.$res->projectId.'&unitId='.$res->unitId.'';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$response = json_decode(curl_exec($ch), true);
$trimmed = $response['datas'] ?? null;
// If the response datas is empty, we're assuming it's because of a token error, so we retry
if(empty($trimmed)){
$attempts++;
$this->refreshToken();
return $this->getUnitDetails($res, $attempts);
}
return $trimmed;
}
public function propertyUnitDetails()
{
// Grab all of the units
$unitItds = \DB::table('property_unit_list')->select('projectId','unitId')->get();
foreach($unitId as $res) {
$trimmed = $this->getUnitDetails($res);
foreach ($trimmed as $data){
$inserts[] = [
'projectId' => $res->projectId,
'stack' => $data['stack'],
'floorPlanId' => $data['floorPlanId'],
'soldBy' => $data['soldBy'],
'transactionPrice' => $data['transactionPrice'],
'type' => $data['type'],
'unitId' => $data['unitId'],
'floorPlanName' => $data['floorPlanName'],
'price1' => $data['price1'],
'price2' => $data['price2'],
'price3' => $data['price3'],
'price4' => $data['price4'],
'custom1' => $data['custom1'],
'custom2' => $data['custom2'],
'custom3' => $data['custom3'],
'custom4' => $data['custom4'],
'direction' => $data['direction'],
'area' => $data['area'],
'buildName' => $data['buildName'],
'unitName' => $data['unitName'],
'buildId' => $data['buildId'],
'bathrooms' => $data['bathrooms'],
'transactionDate' => $data['transactionDate'],
'bedrooms' => $data['bedrooms'],
'purchaseStatus' => $data['purchaseStatus'],
];
}
}
$chuncked = array_chunk($inserts, 10);
foreach($chuncked as $inserts){
\DB::table('property_project_details')->insert($inserts);
}
dd('record inserted');
}
}
What if you call the method getToken() everytime you got a projectId in your loop. Its like this
foreach($project_id as $res){
$this->getToken();
$final_token = $this->token;
$request_time = Carbon::now()->format('YmdHis');
$sign = md5($final_token.$request_time);
//and so on ....
In that way. it will get a new token in every projectId. the only drawbacks is it will execute very slowly.
And if it is still got the error replace your code like this. Add a condition if empty
public function propertyBuildings(){
$project_id = \DB::table('project_list')
->select('projectId')
->get();
foreach($project_id as $res){
$this->getToken();
$final_token = $this->token;
$request_time = Carbon::now()->format('YmdHis');
$sign = md5($final_token.$request_time);
$url = 'https://cgi.singmap.com/project/queryBuilding?request_time='.$request_time.
'&token='.$token.'&sign='.$sign.'&projectId='.$res->projectId.'';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$response = json_decode(curl_exec($ch), true);
$trimmed = $response['datas'];
if(empty($trimmed)){
$this->getToken();
$final_token = $this->token;
}
// return $trimmed;
foreach($trimmed as $data){
$inserts[] = [
'projectId' => $res->projectId,
'buildId' => $data['buildId'],
'buildName' => $data['buildName'],
];
}
}
\DB::table('property_building')->insert($inserts);
dd('Data Inserted');
}
my php POST request script always returns error,and i have no idea why.
i tried different approaches and still no luck.
when i try this, it returns
'Not Found
Sorry, we could not find a page at that URL.'
why?there is a page at that URL 100%
here is the code
$params = array(
'apiKey' =>'*********',
'titleID' => $title,
'forename' => $yname,
'surname' => $surname,
'dayPhone' => $phone,
'eveningPhone' => $phone_evening,
'mobilePhone' => $phone_mobile,
'email' => $email,
'buyingBedrooms' => $bedroom_num,
'buyingMinPrice' => $min_budget,
'buyingMaxPrice' => $max_budget,
'buyingNotes' => $message,
'buyingActive' => true
);
function httpPost($url,$params)
{
$postData = '';
foreach($params as $k => $v)
{
$postData .= $k . '='.$v.'&';
}
$postData = rtrim($postData, '&');
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch,CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_POST, count($postData));
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
$output=curl_exec($ch);
if($output === false)
{
echo "Error Number:".curl_errno($ch)."<br>";
echo "Error String:".curl_error($ch);
}
curl_close($ch);
return $output;
}
echo httpPost("http://daisylets.domus.net/site/go/api/saveRegistration",$params);
Any help appreciated.
Without seeing the data, it is impossible to tell, but a potential problem is that you could be breaking your own query string:
$postData = '';
foreach($params as $k => $v)
{
$postData .= $k . '='.$v.'&';
}
$postData = rtrim($postData, '&');
You are not encoding your values so any character that has a special meaning in a url / has to be encoded in a url, will break your cURL request.
You should replace that whole section with just:
$postData = http_build_query($params);
Try encoding the URL
$postUrl = urlencode("http://daisylets.domus.net/site/go/api/saveRegistration");
echo httpPost($postUrl,$params);
After many tests, I cannot retrieve the access token. It gives me every time this error:
"error_description":"missing required parameters, includes an invalid parameter value, parameter more than once. : Unable to retrieve access token : authorization code not found","error":"invalid_request"
I totally distraught. For a few days I cannot solve my problem.
Here is the code of my application :
Route::get('login/linkedin', function()
{
$lk_credentials = Config::get('linkedin.public0');
$provider = new LinkedIn($lk_credentials);
if(!Input::has('code')){
$provider->authorize();
}else{
$code = Input::get('code');
if(strlen($code) == 0) return Redirect::to('/')->with('message', 'There was an error communicating with LinkedIn');
try{
$params = array(
'response_type' => 'code',
'client_id' => '*************',
'redirect_uri' => urlencode(url('login/linkedin')),
'state' => $_GET['state'],
);
$postdata = http_build_query($params);
$url = '/uas/oauth2/authorization?'.$postdata;
$context = stream_context_create(array('https' => array('method' => 'GET')));
$t = $provider->getAccessToken('authorization_code', array('code' => $_GET['code']));
Session::put('oauth2_access_token', $t->accessToken);session(['oauth2_access_token' => $t->accessToken]);
try{
if(count($_POST) > 0){
print_r($_POST);
exit('post');
}
$params = array(
'grant_type' => 'authorization_code',
'code' => Session::get('oauth2_access_token'), //$_GET['code'],
'redirect_uri' => urlencode(url('login/linkedin')),
'client_id' => '123456789',
'client_secret' => '123456789',
);
$postdata = http_build_query($params);
$c = curl_init();
curl_setopt($c, CURLOPT_URL, 'https://www.linkedin.com/uas/oauth2/accessToken');
curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
curl_setopt($c, CURLOPT_POST,true);
curl_setopt($c, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($c, CURLOPT_POSTFIELDS,$postdata);
curl_setopt($c, CURLOPT_HEADER, false);
curl_setopt($c, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded',));
$output = curl_exec($c);
if($output === false){
trigger_error('Erreur curl : '.curl_error($c),E_USER_WARNING);
exit('Erreur');
}else{
var_dump($output);
//exit('Affiche');
}
curl_close($c);
}catch(Exception $e){
return 'Unable to get Request Token';
}
}catch(Exception $e){
return 'Unable to get user authorization_code';
}
try{
$resource = '/v1/people/~:(id,emailAddress,firstName,lastName,pictureUrl,dateOfBirth,location)';
$params = array(
'oauth2_access_token' => Session::get('oauth2_access_token'),
'format' => 'json',
);
$url = 'https://api.linkedin.com' . $resource . '?' . http_build_query($params);
$context = stream_context_create(array('http' => array('method' => 'GET')));
$response = file_get_contents($url, false, $context);
$data = json_decode($response);
Session::put('data', $data);session(['data' => $data]);
return redirect('/')->with('data',$data);
}catch(Exception $e){
return 'Unable to get user details';
}
}
});
Does anyone could help me?
For information; I use Laravel5 and for the authentication is OAuth2.
Thank you in advance, David.
I have a problem with a request post http. The params are correct but I have an error.
This is my code
Route::get('login/linkedin', function()
{
$lk_credentials = Config::get('linkedin.public0');
$provider = new LinkedIn($lk_credentials);
if(!Input::has('code')){
//exit('debug');
$provider->authorize();
}else{
try{
$code = Input::get('code');
if(strlen($code) == 0) return Redirect::to('/')->with('message', 'There was an error communicating with LinkedIn');
$t = $provider->getAccessToken('authorization_code', array('code' => $code));
}catch(Exception $e){
return 'Unable to get access token';
}
try{
$userDetails = $provider->getUserDetails($t);
$resource = '/v1/people/~:(id,emailAddress,firstName,lastName,pictureUrl,dateOfBirth,location)';
$params = array(
'oauth2_access_token' => $t->accessToken,
'format' => 'json',
);
Session::put('oauth2_access_token', $t->accessToken);session(['oauth2_access_token' => $t->accessToken]);
$url = 'https://api.linkedin.com' . $resource . '?' . http_build_query($params);
$context = stream_context_create(array('http' => array('method' => 'GET')));
$response = file_get_contents($url, false, $context);
$data = json_decode($response);
Session::put('data', $data);session(['data' => $data]);
}catch(Exception $e){
return 'Unable to get user details';
}
try{
if(count($_POST) > 0){
print_r($_POST);
exit();
}
$params = array(
'grant_type' => 'authorization_code',
'code' => Session::get('oauth2_access_token'),
'redirect_uri' => url('login/linkedin'),
'client_id' => '************',
'client_secret' => '***************',
);
$c = curl_init();
curl_setopt($c, CURLOPT_URL, 'http://www.linkedin.com/uas/oauth2/accessToken?');
curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
curl_setopt($c, CURLOPT_POST,true);
curl_setopt($c, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($c, CURLOPT_POSTFIELDS,$params);
curl_setopt($c, CURLOPT_HEADER, false);
curl_setopt($c, CURLOPT_HTTPHEADER, array(
'Content-Type: application/x-www-form-urlencoded',
)
);
$output = curl_exec($c);
if($output === false){
trigger_error('Erreur curl : '.curl_error($c),E_USER_WARNING);
exit('Erreur');
}
else{
var_dump($output);
exit('Affiche');
}
curl_close($c);
return redirect('/')->with('data',$data);
}catch(Exception $e){
return 'Unable to get Request Token';
}
}
});
And this is my error :
{"error_description":"missing required parameters,
includes an invalid parameter value, parameter more than once.
: Unable to retrieve access token : authorization code not found",
"error":"invalid_request"}
While building $params array remember that url must be urlencoded, so if your url function doesn't do that, change this line to:
'redirect_uri' => urlencode(url('login/linkedin'))
Then make post string like this:
$params = http_build_query($params);
And remove ? at the end of CURLOPT_URL.
Also you should include CURLOPT_USERAGENT.