I am using Google Tracks API to build a simple web based program to track a vehicle that has a tracking device sending latitude and longitude coordinates.
I am using PHP and the OAuth2 PHP library to make an authorized connection.
After authorizing and getting an access token I am making a request to create entities. Though I can't seem to get this working and keep getting a "400 Bad Request" response. Following all the steps shown in the documentation.
Here is my code:
$url = 'https://www.googleapis.com/tracks/v1/entities/create/?access_token='.$parsedAuth['access_token'];
$data = array('entities' => array( "name"=> "Chevrolet" ));
$json_data = json_encode($data);
$data_length = http_build_query($data);
$options = array(
'http' => array(
'header' => "Content-type: application/json\r\n". "Content-Length: " . strlen($data_length) . "\r\n",
'method' => 'POST',
'content' => $json_data
),
);
$context = stream_context_create($options);
$response = file_get_contents($url, false, $context);
var_dump($response);
Exact Error is: "failed to open stream: HTTP request failed! HTTP/1.0 400 Bad Request"
Why am I getting a bad request? What would be a good request that will register these entities and return id's?
Thank you
The answer given here is wrong. The documentation states that it must be a POST see here My issue was not with the Auth but with the Tracks API itself. I ended up moving to create the request with CURL and it works just fine.
Please. This is PHP with CURL. It works 100%.
//Google maps tracks connection
//Get Files From PHP Library
require_once 'google-api-php-client/src/Google/autoload.php';
require_once 'google-api-php-client/src/Google/Service/MapsEngine.php';
//Set Client Credentials
$client_id = '*************.apps.googleusercontent.com'; //Client ID
$service_account_name = '************#developer.gserviceaccount.com'; //Email Address
$client_email = '*************#developer.gserviceaccount.com';
$private_key = file_get_contents('************.p12');
$scopes = array('https://www.googleapis.com/auth/tracks');
//Create Client
$client = new Google_Client();
$client->setApplicationName("Client_Library_Examples");
//Send Credentials
$credentials = new Google_Auth_AssertionCredentials(
$client_email,
$scopes,
$private_key
);
$client->setAssertionCredentials($credentials);
if ($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion($credentials);
}
if (isset($_SESSION['service_token'])) {
$client->setAccessToken($_SESSION['service_token']);
}
$client->setAssertionCredentials($credentials);
$_SESSION['service_token'] = $client->getAccessToken();
foreach ($_SESSION as $key=> $value) {
$vars = json_decode($value);
}
$parsedAuth = (array) $vars;
$token = $parsedAuth['access_token'];
//all functions in the program use this auth token- It should be global for easy accesses.
global $token;
function createEntities(){
global $token;
$url = 'https://www.googleapis.com/tracks/v1/entities/create/?access_token='.$token;
//FIX ME: fields is temporarily hard coded- should be brought from DB
$fields = array(
'entities' => array(
'name' => "DemoTruck",
'type' => "AUTOMOBILE"
),
);
//json string the data for the POST
$query_string = '';
foreach($fields as $key => $array) {
$query_string .= '{"' . urlencode($key).'":[{';
foreach($array as $k => $v) {
$query_string .= '"' . urlencode($k) . '":"' . urlencode($v) . '",';
}
}
$str = rtrim($query_string , ',');
$fstr = $str.'}]}';
$length = strlen( $fstr );
//open connection
$ch = curl_init();
//test connection
if (FALSE === $ch)
throw new Exception('failed to initialize');
//set options
$header = array('Content-type: application/json');
curl_setopt($ch,CURLOPT_URL, $url);
curl_setopt($ch,CURLOPT_HTTPHEADER, $header);
curl_setopt($ch,CURLOPT_POSTFIELDS, $fstr);
$result = curl_exec($ch);
//dump in case of error
if (FALSE === $result){
var_dump( curl_error($ch) );
var_dump( curl_getinfo($ch) );
}
//close connection
curl_close($ch);
}
Related
I'm trying to signin the user just with PHP and curl, without any external libraries for Twitter authentication. I follow these Twitter instructions. But I can't figure out how to complete step 3.
1. Obtaining a request token (done)
2. Redirecting the user (done)
3. Converting the request token to an access token. (done * problem)
Here is my code:
// API SETTINGS
$consumerSecret = 'xxx';
$consumerKey = 'xxx';
$oauth_signature_method = 'HMAC-SHA1';
if (!isset($_GET['oauth_verifier'])) {
// STEP 1 - TWITTER OBTAINING A REQUEST TOKEN
$callbackUrl = 'http://localhost/skeletons/webiik/example/login/';
$url = 'https://api.twitter.com/oauth/request_token';
// Data we will send
$data = [
'oauth_callback' => $callbackUrl,
'oauth_consumer_key' => $consumerKey,
'oauth_signature_method' => $oauth_signature_method,
'oauth_timestamp' => time(),
'oauth_nonce' => $token->generate(3),
'oauth_version' => '1.0',
];
// Sort data alphabetically, because Twitter requires that
ksort($data);
// Generate signature and add it to data array
$signData = 'POST&' . urlencode($url) . '&' . urlencode(http_build_query($data));
$secret = '';
$signKey = urlencode($consumerSecret) . '&' . urlencode($secret);
$data['oauth_signature'] = base64_encode(hash_hmac('sha1', $signData, $signKey, true));
// Prepare http headers from data
$httpHeaders = [];
foreach ($data as $key => $value) {
$httpHeaders[] = urlencode($key) . '="' . urlencode($value) . '"';
}
// Add OAuth header with all data
$httpHeaders = 'Authorization: OAuth ' . implode(', ', $httpHeaders);
// Send post request to Twitter API with http headers and data
$res = $http->post($url, ['httpHeaders' => [$httpHeaders]], []);
// If we got some error, show error message and stop
if (count($res['err']) > 0) {
echo $res['err'];
exit;
}
// Prepare data for step 2 and 3 from Twitter's response
parse_str($res['body'], $res);
$oauth_callback_confirmed = $res['oauth_callback_confirmed'];
$oauth_request_token = $res['oauth_token'];
// Store oauth_token_secret into session, we will need it in step 3
$this->sessions->setToSession('oauth_token_secret', $res['oauth_token_secret']);
$this->sessions->setToSession('oauth_token', $oauth_request_token);
// STEP 2 - REDIRECTING THE USER TO TWITTER LOGIN
header('HTTP/1.1 302 Found');
header('Location: https://api.twitter.com/oauth/authenticate?oauth_token=' . urlencode($oauth_request_token));
}
// STEP 3 - CONVERTING THE REQUEST TOKEN TO AN ACCESS TOKEN
$url = 'https://api.twitter.com/oauth/access_token';
$oauth_token = $_GET['oauth_token'];
$oauth_verifier = $_GET['oauth_verifier'];
// Data we will send
$data = [
'oauth_consumer_key' => $consumerKey,
'oauth_nonce' => $token->generate(3),
'oauth_signature_method' => $oauth_signature_method,
'oauth_timestamp' => time(),
'oauth_token' => $oauth_token,
'oauth_version' => '1.0',
];
// Sort data alphabetically, because Twitter requires that
ksort($data);
// Generate signature and add it to data array
$signData = 'POST&' . urlencode($url) . '&' . urlencode(http_build_query($data));
$secret = $this->sessions->getFromSession('oauth_token_secret');
$signKey = urlencode($consumerSecret) . '&' . urlencode($secret);
$data['oauth_signature'] = base64_encode(hash_hmac('sha1', $signData, $signKey, true));
// Sort data also with added oauth_signature, just for sure
ksort($data);
// Prepare http headers from data
$httpHeaders = [];
foreach ($data as $key => $value) {
$httpHeaders[] = urlencode($key) . '="' . urlencode($value) . '"';
}
// Add OAuth header with all data
$httpHeaders = ['Authorization: OAuth ' . implode(', ', $httpHeaders)];
$httpHeaders[] = 'Content-Length: ' . strlen('oauth_verifier=' . urlencode($oauth_verifier));
$httpHeaders[] = 'Content-Type: application/x-www-form-urlencoded';
// Add oauth_verifier to POST data
$postData = ['oauth_verifier' => $oauth_verifier];
// Send post request to Twitter API with http headers and data
$res = $http->post($url, ['httpHeaders' => $httpHeaders], $postData);
// If we got some error, show error message and stop
if (count($res['err']) > 0) {
echo $res['err'];
exit;
}
print_r($res);
Edit 1:
$http is just object that creates standard curl requests. In third step the curl request looks like:
$curl = curl_init($url);
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_FAILONERROR => 1,
CURLOPT_VERBOSE => 1,
CURLOPT_HEADER => 1,
CURLOPT_HTTPHEADER => $arrayOfHttpHeaders,
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => http_build_query($postData),
]);
$response = curl_exec($curl);
// Process response...
Edit 2:
I just updated the code to be more accurate to Twitter's example. Now I really don't know where can be the problem.
Edit 3:
Solution: The code is ok. I had problem with router, which added slash at the end of URL. And I grabbed verifier_token with that slash.
I am really struggling to work with the Instagram API. I currently have this code in a file called data.php which I want to return a JSON response which I can process in a JS file but I am getting this response failed to open stream: HTTP request failed! HTTP/1.1 400 Bad Request
Here is the code:
<?php
$access_token = '********';
$client_id = '********';
$client_secret = "*******";
$user = "*******";
$endpoint = '/media/657988443280050001_25025320';
$params = array(
'access_token' => '********',
'count' => 10,
);
$signature = generate_sig($endpoint, $params, $client_secret);
var_dump("Signature: ". $signature);
$data = file_get_contents("https://api.instagram.com/v1/users/$user/media/recent/?access_token=$signature");
header('Content-Type: application/json; charset=UTF-8');
echo $data;
function generate_sig($endpoint, $params, $secret) {
$sig = $endpoint;
ksort($params);
foreach ($params as $key => $val) {
$sig .= "|$key=$val";
}
return hash_hmac('sha256', $sig, $secret, false);
}
?>
Here are my app settings. It is in Sandbox Mode and hasn't been submitted for review.
I'm trying to get latitude and longitude from Google's Geocode API. The $url I'm using outputs the correct JSON however something in my script isn't working correctly. It's not outputting the $lati & $longi variables. Please check see the script below:
PHP:
<?php
$address = 'Tempe AZ';
$address = urlencode($address);
$url = "https://maps.google.com/maps/api/geocode/json?sensor=false&address={$address}";
$resp_json = file_get_contents($url);
$resp = json_decode($resp_json, true);
if ($resp['status'] == 'OK') {
// get the important data
$lati = $resp['results'][0]['geometry']['location']['lat'];
$longi = $resp['results'][0]['geometry']['location']['lng'];
echo $lati;
echo $longi;
} else {
return false;
}
?>
I brought in the Guzzle http package at the top of my Laravel file/class: use GuzzleHttp\Client;
Then, to take an address and convert it to lat and lng to save with PHP/Laravel and Google Maps API, I added this code in my save() method:
// get latitude and longitude of address with Guzzle http package and Google Maps geocode API
$client = new Client(); // GuzzleHttp\Client
$baseURL = 'https://maps.googleapis.com/maps/api/geocode/json?address=';
$addressURL = urlencode(request('street')) . ',' . urlencode(request('city')) . ',' . urlencode(request('state')) . '&key=' . env('GOOGLE_MAPS_API_KEY');
$url = $baseURL . $addressURL;
$request = $client->request('GET', $url);
$response = $request->getBody()->getContents();
$response = json_decode($response);
$latitude = $response->results[0]->geometry->location->lat;
$longitude = $response->results[0]->geometry->location->lng;
It turned out to be a proxy issue. This thread helped: Using proxy with file_get_contents
Added this:
$opts = array(
'http' => array(
'method' => "GET",
'header' => "Accept-language: en\r\n".
"Cookie: foo=bar\r\n",
'proxy' => 'tcp://proxy.proxy.com:8080',
)
);
$context = stream_context_create($opts);
// open the file using the HTTP headers set above
$file = file_get_contents($url, false, $context);
Your script works for me too. Maybe you will get an error calling:
$resp_json = file_get_contents($url);.
If that happens you should do this:
$resp_json = #file_get_contents($url);
if ($resp_json === FALSE) {
///logic for exception
} else {
///do your logic hear
}
As per the new oauth 2.0 for linkedin.
I am unable to get user profile details.
I have set the attributes in my app but still cant get the details.
Can somebody help me the code snippet to get user details.
public function fetch($method, $resource, $body = '') {
$opts = array(
'http' => array(
'method' => $method,
'header' => "Authorization: Bearer " .
$_SESSION['oauth_access_token'] . "\r\n" .
"x-li-format: json\r\n"
)
);
$url = 'api.linkedin.com' . $resource;
if (count($this->$params)) {
$url .= '?' . http_build_query($this->$params);
}
$context = stream_context_create($opts);
$response = file_get_contents($url, false, $context);
return json_decode($response);
}
$xml_response = $LinkedInn->fetch("GET","/v1/people/~");
Please check your permissions in your code when you are logging in with linked-in.
Look at this link-
https://developer.linkedin.com/support/developer-program-transition
I am trying to get issue a cURL request for "request token" method using Fitbit API. Problem is it does not show anything but a blank screen. However this process is suppose to give me an "access token" which I can use to generate a login URL to authenticate users and give access to my app.
I know there is oAuth php class for this but my server doesn't support oAuth so got to use cURL only. Please help! Many thanks in advance.
<?php
define('FITBIT_KEY', '<consumer key from fitbit website>');
define('FITBIT_SECRET', '<consumer secret from fitbit website>');
function buildBaseString($baseURI, $method, $params)
{
$r = array();
ksort($params);
foreach($params as $key=>$value){
$r[] = "$key=" . rawurlencode($value);
}
return $method."&" . rawurlencode($baseURI) . '&' . rawurlencode(implode('&', $r)); //return complete base string
}
function buildAuthorizationHeader($oauth)
{
$r = 'Authorization: OAuth ';
$values = array();
foreach($oauth as $key=>$value)
$values[] = "$key=\"" . rawurlencode($value) . "\"";
$r .= implode(', ', $values);
return $r;
}
$url = "http://api.fitbit.com/oauth/request_token";
$oauth = array( 'oauth_consumer_key' => FITBIT_KEY,
'oauth_consumer_secret' => FITBIT_SECRET,
'oauth_nonce' => time(),
'oauth_signature_method' => 'HMAC-SHA1',
'oauth_timestamp' => time(),
'oauth_version' => '1.0',
'oauth_callback' => 'http://h1.servy.net/zerocuisine/index.php');
$base_info = buildBaseString($url, 'GET', $oauth);
$composite_key = rawurlencode(FITBIT_SECRET) . '&';
$oauth_signature = base64_encode(hash_hmac('sha1', $base_info, $composite_key, true));
$oauth['oauth_signature'] = $oauth_signature;
$header = array(buildAuthorizationHeader($oauth), 'Expect:');
$options = array( CURLOPT_HTTPHEADER => $header,
CURLOPT_HEADER => false,
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYPEER => false);
$feed = curl_init();
curl_setopt_array($feed, $options);
$json = curl_exec($feed);
curl_close($feed);
$fitbit_data = json_decode($json);
echo '<pre>'.print_r($fitbit_data,true).'</pre>'; ?>
There's two problems here which lead to a blank screen. You used http instead of https in your $url. https is required for fitbit token request. You're also running json_decode on a string that's not a json array. The data inside $json is a string from http body response.
Here's my run down in detail to make it fully working below.
Instead of:
$url = "http://api.fitbit.com/oauth/request_token";
Use:
$url = "https://api.fitbit.com/oauth/request_token";
Also remove:
$fitbit_data = json_decode($json);
Change:
echo '<pre>'.print_r($json,true).'</pre>'; ?>
To:
echo '<pre>'. $json .'</pre>'; ?>
This will leave you with the successful response of:
<pre>oauth_token=93bf6ded129fcfa2b687ce6e625477af&oauth_token_secret=c9cc547ca6dd484f73763e23b0987121&oauth_callback_confirmed=true</pre>
shown into your browser.
P.S. make sure to remake this to Oauth 2.0. OAuth 1.0a support will be removed from the Fitbit Web API on April 12, 2016.