I am trying to connect API after jwt token. But this my first time experience with API. So Company give me to codes On is "Generate JWT token" other is httpRequest with php. Company give me Object of class "$request = new HttpRequest();". But i don't know to work this object.
Create a jwt at your end to request a token (PHP).
Replace {CLIENT_ID}, {CLIENT_SECRET} in php code.
This code works fine.
function base64url_encode($str) {
return rtrim(strtr(base64_encode($str), '+/', '-_'), '=');
}
function generate_jwt($headers, $payload, $secret = 'CLIENT_SECRET') {
$headers_encoded = base64url_encode(json_encode($headers));
$payload_encoded = base64url_encode(json_encode($payload));
$signature = hash_hmac('SHA256', "$headers_encoded.$payload_encoded", $secret, true);
$signature_encoded = base64url_encode($signature);
$jwt = "$headers_encoded.$payload_encoded.$signature_encoded";
return $jwt;
}
$headers = array('alg'=>'HS256','typ'=>'JWT');
$payload = array('aud'=>'https://s1.serviceaccountsapi.example.net/v1/{client_id}/api/token', 'iss'=>'CLIENT_ID', 'expiry'=> 3600);
$jwt = generate_jwt($headers, $payload);
echo $jwt;
To request in PHP:
This is not working. Because this object don't have class . So i don't know what i write in this class.
$request = new HttpRequest();
$request->setUrl('https://s2.serviceaccounts.example.net/v1/{CLIENT_ID}/api/token');
$request->setMethod(HTTP_METH_POST);
$request->setHeaders(array(
'content-type' => 'application/x-www-form-urlencoded'
));
$request->setContentType('application/x-www-form-urlencoded');
$request->setPostFields(array(
'assertion' => 'Bearer {PUT YOUR TOKEN HERE WITHOUT BRACES}',
'grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer'
));
try {
$response = $request->send();
echo $response->getBody();
} catch (HttpException $ex) {
echo $ex;
}
Seems like it's proposing you to implement an HttpRequest class following the suggested interface.
Related
I'm trying to communicate to an API with laravel using guzzleHttp but I can't receive nothing.
If I test in postman returns me information.
In postman I set the configuration as you see in image:
In code I'm trying to do that:
$token = env('API_TOKEN');
$company = env('API_COMPANY_ID');
$link = 'https://xpto.pt/APIs.aspx/Con';
$data = array('token' => $token, 'empresa' => $company);
$data = json_encode($data);
echo $data;
$client = new Client();
$request = $client->post($link, ['raw'=>$data]);
$response = $request->send();
dd($response);
Thank you
I have an API that I am trying to create a function for to send requests, the docs are here: http://simportal-api.azurewebsites.net/Help
I thought about creating this function in PHP:
function jola_api_request($url, $vars = array(), $type = 'POST') {
$username = '***';
$password = '***';
$url = 'https://simportal-api.azurewebsites.net/api/v1/'.$url;
if($type == 'GET') {
$call_vars = '';
if(!empty($vars)) {
foreach($vars as $name => $val) {
$call_vars.= $name.'='.urlencode($val).'&';
}
$url.= '?'.$call_vars;
}
}
$ch = curl_init($url);
// Specify the username and password using the CURLOPT_USERPWD option.
curl_setopt($ch, CURLOPT_USERPWD, $username . ":" . $password);
if($type == 'POST') {
curl_setopt($ch, CURLOPT_POSTFIELDS, $vars);
}
// Tell cURL to return the output as a string instead
// of dumping it to the browser.
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
//Execute the cURL request.
$response = curl_exec($ch);
// Check for errors.
if(curl_errno($ch)){
// If an error occured, throw an Exception.
//throw new Exception(curl_error($ch));
$obj = array('success' => false, 'errors' => curl_error($ch));
} else {
$response = json_decode($response);
$obj = array('success' => true, 'response' => $response);
}
return $obj;
}
So this determintes whether its a GET or POST request, but the response being returned on some calls is that GET is not supported or POST is not supported, although I am specifying the correct one for each call.
I think I have the function wrong somehow though and wondered if someone could assist me in the right direction? As I've also noticed, I need to allow for DELETE requests too.
for the easier life, try guzzle.
http://docs.guzzlephp.org/en/stable/
you can make a request like this :
use GuzzleHttp\Client;
$client = new Client();
$myAPI = $client->request('GET', 'Your URL goes here');
$myData = json_decode($myAPI->getBody(), true);
then you can access the data like an array
$myData["Head"][0]
The problem is in $url you try to create for GET request.
Your $url for GET request looks like:
GET https://simportal-api.azurewebsites.net/api/v1/?param1=val1¶m2=val2
but from documentation you can clearly see that you $url should be:
GET https://simportal-api.azurewebsites.net/api/v1/param1/val1/param2
for ex.:
GET https://simportal-api.azurewebsites.net/api/v1/customers/{id}
GuzzleHttp is the standard way to work with web service.
You can use auth parameter to send your authentication detail. Also, you can use Oath or Beer token whatever your convenient method is. If you try to call service via a token method, keep in mind you will need to pass authorization by header instead of auth.
See this GuzzleHttp authentication via token. Also, you can catch exception very quickly. See Handle Guzzle exception and get HTTP body
Try below code got from official site ;)
$client = new GuzzleHttp\Client();
$res = $client->request('GET', 'https://api.github.com/user', [
'auth' => ['user', 'pass']
]);
echo $res->getStatusCode();
// "200"
echo $res->getHeader('content-type')[0];
// 'application/json; charset=utf8'
echo $res->getBody();
// {"type":"User"...'
// Send an asynchronous request.
$request = new \GuzzleHttp\Psr7\Request('GET', 'http://httpbin.org');
$promise = $client->sendAsync($request)->then(function ($response) {
echo 'I completed! ' . $response->getBody();
});
$promise->wait();
You can find more about GuzzleHttp request here: http://docs.guzzlephp.org/en/stable/quickstart.html#making-a-request
Hope this what you want!
I think you should try to use Postman Tool to request to that API first. If postman does the job it means problem in your PHP code. But if you already used postman and still can't fetch response, so it may be problem with that API. Like URL block.
I am using "google api client php" to get access token using service account json base key file. But i am getting access token null. My sample code is
$client = new \Google_Client();
$client->setApplicationName('My App');
putenv('GOOGLE_APPLICATION_CREDENTIALS=path-to-the-key.json');
$client->useApplicationDefaultCredentials();
$client->setScopes(['https://www.googleapis.com/auth/analytics.readonly']);
$client->authorize();
$token = $client->getAccessToken();
echo $token; // null
I was solved my problem by developing own php code from google documentation. I use sign JWT payload using Guzzle HTTP Client to get access token. Here is the doc
My implementation:
public static function base64url_encode($data) {
return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
}
public static function getJwtAssertion($private_key_file)
{
$json_file = file_get_contents($private_key_file);
$info = json_decode($json_file);
$private_key = $info->{'private_key'};
//{Base64url encoded JSON header}
$jwtHeader = self::base64url_encode(json_encode(array(
"alg" => "RS256",
"typ" => "JWT"
)));
//{Base64url encoded JSON claim set}
$now = time();
$jwtClaim = self::base64url_encode(json_encode(array(
"iss" => $info->{'client_email'},
"scope" => "https://www.googleapis.com/auth/analytics.readonly",
"aud" => "https://www.googleapis.com/oauth2/v4/token",
"exp" => $now + 3600,
"iat" => $now
)));
$data = $jwtHeader.".".$jwtClaim;
// Signature
$Sig = '';
openssl_sign($data,$Sig,$private_key,'SHA256');
$jwtSign = self::base64url_encode($Sig);
//{Base64url encoded JSON header}.{Base64url encoded JSON claim set}.{Base64url encoded signature}
$jwtAssertion = $data.".".$jwtSign;
return $jwtAssertion;
}
public static function getGoogleAccessToken($private_key_file)
{
$result = [
'success' => false,
'message' => '',
'token' => null
];
if (Cache::has('google_token')) {
$result['token'] = Cache::get('google_token');
$result['success'] = true;
return $result;
}
if(!file_exists($private_key_file)){
$result['message'] = 'Google json key file missing!';
return $result;
}
$jwtAssertion = self::getJwtAssertion($private_key_file);
try {
$client = new Client([
'base_uri' => 'https://www.googleapis.com',
]);
$payload = [
'grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer',
'assertion' => $jwtAssertion
];
$response = $client->request('POST', 'oauth2/v4/token', [
'form_params' => $payload
]);
$data = json_decode($response->getBody());
$result['token'] = $data->access_token;
$result['success'] = true;
$expiresAt = now()->addMinutes(58);
Cache::put('google_token', $result['token'], $expiresAt);
} catch (RequestException $e) {
$result['message'] = $e->getMessage();
}
return $result;
}
Now call it:
$googleToken = getGoogleAccessToken($KEY_FILE_LOCATION);
I used similar type of client to get access token but that was for google sheets.
This would be same like that. So I'm sharing my google sheets code snippet here.
<?php
if (!function_exists('curl_reset'))
{
function curl_reset(&$ch)
{
$ch = curl_init();
}
}
require_once __DIR__ . '/goog/vendor/autoload.php';
define('APPLICATION_NAME', 'Google Sheets API PHP Quickstart');
define('CREDENTIALS_PATH', __DIR__ . '/sheets.googleapis.com-php-quickstart.json');
define('CLIENT_SECRET_PATH', __DIR__ . '/client_secret.json');
// If modifying these scopes, delete your previously saved credentials
// at ~/.credentials/sheets.googleapis.com-php-quickstart.json
define('SCOPES', implode(' ', array(
Google_Service_Sheets::SPREADSHEETS)
));
if (php_sapi_name() != 'cli') {
throw new Exception('This application must be run on the command line.');
}
/**
* Returns an authorized API client.
* #return Google_Client the authorized client object
*/
function getClient() {
$client = new Google_Client();
$client->setApplicationName(APPLICATION_NAME);
$client->setScopes(SCOPES);
$client->setAuthConfig(CLIENT_SECRET_PATH);
$client->setAccessType('offline');
// Load previously authorized credentials from a file.
$credentialsPath = CREDENTIALS_PATH;
if (file_exists($credentialsPath)) {
$accessToken = json_decode(file_get_contents($credentialsPath), true);
} else {
// Request authorization from the user.
$authUrl = $client->createAuthUrl();
printf("Open the following link in your browser:\n%s\n", $authUrl);
print 'Enter verification code: ';
$authCode = trim(fgets(STDIN));
// Exchange authorization code for an access token.
$accessToken = $client->fetchAccessTokenWithAuthCode($authCode);
// Store the credentials to disk.
if(!file_exists(dirname($credentialsPath))) {
mkdir(dirname($credentialsPath), 0700, true);
}
file_put_contents($credentialsPath, json_encode($accessToken));
printf("Credentials saved to %s\n", $credentialsPath);
}
$client->setAccessToken($accessToken);
// Refresh the token if it's expired.
if ($client->isAccessTokenExpired()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
file_put_contents($credentialsPath, json_encode($client->getAccessToken()));
}
return $client;
}
So when you call getClient function in a php script in command line it will generate a link to verify the user in browser after that it will provide an code which you have to place in the command line. Then it will generate the access token which can be reused later.
Here below i have attached my api request
$apiKey = "XXXX";
$Secret = "XXX";
$endpoint = "https://api.test.hotelbeds.com/hotel-api/1.0/hotels";
$request = new http\Client\Request("POST",
$endpoint,
[ "Api-Key" => $apiKey,
"X-Signature" => $signature,
"Accept" => "application/xml" ]);
try
{ $client = new http\Client;
$client->enqueue($request)->send();
$response = $client->getResponse();
if ($response->getResponseCode() != 200) {
printf("%s returned '%s' (%d)\n",
$response->getTransferInfo("effective_url"),
$response->getInfo(),
$response->getResponseCode()
);
} else {
printf($response->getBody());
}
} catch (Exception $ex) {
printf("Error while sending request, reason: %s\n",$ex->getMessage());
}'
getting following error
Uncaught Error: Class 'http\Client\Request' not found in
You need to add a use statement.
use http\Client\Request;
$request = new Request(blah blah);
Of course I assume you are using Composer autoloader. If not, you will also need to require_once() the file.
You can try using cURL instead of pecl_http. Here is an example:
<?php
// Your API Key and secret
$apiKey = "yourApiKey";
$Secret = "yourSecret";
// Signature is generated by SHA256 (Api-Key + Secret + Timestamp (in seconds))
$signature = hash("sha256", $apiKey.$Secret.time());
$endpoint = "https://api.test.hotelbeds.com/hotel-api/1.0/status";
echo "Your API Key is: " . $apiKey . "<br>";
echo "Your X-Signature is: " . $signature . "<br><br>";
// Example of call to the API
try
{
// Get cURL resource
$curl = curl_init();
// Set some options - we are passing in a useragent too here
curl_setopt_array($curl, array(
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_URL => $endpoint,
CURLOPT_HTTPHEADER => ['Accept:application/json' , 'Api-key:'.$apiKey.'', 'X-Signature:'.$signature.'']
));
// Send the request & save response to $resp
$resp = curl_exec($curl);
// Check HTTP status code
if (!curl_errno($curl)) {
switch ($http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE)) {
case 200: # OK
echo "Server JSON Response:<br>" . $resp;
break;
default:
echo 'Unexpected HTTP code: ', $http_code, "\n";
echo $resp;
}
}
// Close request to clear up some resources
curl_close($curl);
} catch (Exception $ex) {
printf("Error while sending request, reason: %s\n",$ex->getMessage());
}
?>
Just make sure that first you uncomment ;extension=php_curl.dll in your php.ini file and restart your server.
We are planning to update our examples in the developer portal because some are outdated or not well documented.
I'm currently trying to develop a connection to the Reddit api through Oauth using Guzzle. I get to the point where I authenticate in Reddit, then I get to the authorization token, but I can't take the access token from the Guzzle response so I can set it as a cookie and using on subsequent requests. My current code looks like this:
public function __construct(){
if(isset($_COOKIE['reddit_token'])){
$token_info = explode(":", $_COOKIE['reddit_token']);
$this->token_type = $token_info[0];
$this->access_token = $token_info[1];
} else {
if (isset($_GET['code'])){
//capture code from auth
$code = $_GET["code"];
//construct POST object for access token fetch request
$postvals = sprintf("code=%s&redirect_uri=%s&grant_type=authorization_code",
$code,
redditConfig::$ENDPOINT_OAUTH_REDIRECT);
//get JSON access token object (with refresh_token parameter)
$token = self::runCurl(redditConfig::$ENDPOINT_OAUTH_TOKEN, $postvals, null, true);
//store token and type
if (isset($token->access_token)){
$this->access_token = $token->access_token;
$this->token_type = $token->token_type;
//set token cookie for later use
$cookie_time = 60 * 59 + time(); //seconds * minutes = 59 minutes (token expires in 1hr)
setcookie('reddit_token', "{$this->token_type}:{$this->access_token}", $cookie_time);
}
} else {
$state = rand();
$urlAuth = sprintf("%s?response_type=code&client_id=%s&redirect_uri=%s&scope=%s&state=%s",
redditConfig::$ENDPOINT_OAUTH_AUTHORIZE,
redditConfig::$CLIENT_ID,
redditConfig::$ENDPOINT_OAUTH_REDIRECT,
redditConfig::$SCOPES,
$state);
//forward user to PayPal auth page
header("Location: $urlAuth");
}
}
This is my authentication flow. The I have the runCurl method that is going to make the guzzle requests:
private function runCurl($url, $postVals = null, $headers = null, $auth = false){
$options = array(
'timeout' => 10,
'verify' => false,
'headers' => ['User-Agent' => 'testing/1.0']
);
$requestType = 'GET';
if ($postVals != null){
$options['body'] = $postVals;
$requestType = "POST";
}
if ($this->auth_mode == 'oauth'){
$options['headers'] = [
'User-Agent' => 'testing/1.0',
'Authorization' => "{$this->token_type} {$this->access_token}"];
}
if ($auth){
$options['auth'] = [redditConfig::$CLIENT_ID, redditConfig::$CLIENT_SECRET];
}
$client = new \GuzzleHttp\Client();
$response = $client->request($requestType, $url, $options);
$body = $response->getBody();
return $body;
}
The problem resides here, the getBody() method returns a stream, and if I use getBody()->getContents() I get a string, none of which can help me.
Any idea on how can I get the access token so I can finish the authentication process?
To answer the question itself - you just need to cast $body to string. It should be a json, so you will also need to json_decode it to use it as an object in the code above. So instead of return $body; in your runCurl, you need to do:
return json_decode((string)$body);
I would recommend to use the official client tho. The code in the question has some unrelated issues, which will make it costy to maintain.