From Postman to PHP: Can't Properly Generate an Oauth 1 Signature - php

I’m having a rough time getting a simple Oauth 1 api call to work. I’ve figured out how to access the data I want via Postman and have made successful calls for lists, starred items, etc. If I copy an already-run call from postman and rerun it locally, as long as the timestamp is the timeout time (3 minutes) the api will accept it and I’ll be able to receive and parse the json data.
I've tested and run all of the elements of the code in isolation and everything seems to work fine... What seems to not work is generating a proper signature.
Full code is below... Any help is appreciated!
<?php
// Include Manually Entered Credentials
include 'credentials.php';
####################################
// GENERATE TIMESTAMP:
$oathtimestamp = time();
// GENERATE NONCE:
function generateNonce() {
$length = 15;
$chars='1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM';
$ll = strlen($chars)-1;
$o = '';
while (strlen($o) < $length) {
$o .= $chars[ rand(0, $ll) ];
}
return $o;
}
$oathnonce = generateNonce();
####################################
// API Determinants
$APIurl = "https://www.example.com/api/";
####################################
// GENERATE Oath1 Signature:
$signatureMethod = "HMAC-SHA1";
$oathVersion = "1.0";
$base = "POST&".$APIurl."&"."folder_id=starred"."&limit=25"."&oauth_consumer_key=".$oauth_consumer_key."&oauth_nonce=".$oathnonce."&oauth_signature_method=".$signatureMethod."&oauth_timestamp=".$oathtimestamp."&oauth_token=".$oauth_token."&oauth_version=".$oathVersion."&x_auth_mode=client_auth"."&x_auth_password=".$x_auth_password."&x_auth_username=".$x_auth_username;
//echo $base;
$key = $oauth_consumer_key."&".$oath_tokenSecret;
//echo $key;
$signature = base64_encode(hash_hmac('sha1', $oauth_consumer_key, $key));
//echo $signature;
$oath_getstringlength =
"folder_id=starred".
"&limit=25".
"&oauth_consumer_key=".$oauth_consumer_key.
"&oauth_nonce=".$oathnonce.
"&oauth_signature=".$signature.
"&oauth_signature_method=".$signatureMethod.
"&oauth_timestamp=".$oathtimestamp.
"&oauth_token=".$oauth_token.
"&oauth_version=".$oathVersion.
"&x_auth_mode=client_auth".
"&x_auth_password=".$x_auth_password.
"&x_auth_username=".$x_auth_username;
$oath_stringlength = strlen($oath_getstringlength);
//echo $oath_stringlength;
####################################
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => "https://www.example.com/api/",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS =>
"folder_id=starred".
"&limit=25".
"&oauth_consumer_key=".$oauth_consumer_key.
"&oauth_nonce=".$oathnonce.
"&oauth_signature=".$signature.
"&oauth_signature_method=".$signatureMethod.
"&oauth_timestamp=".$oathtimestamp.
"&oauth_token=".$oauth_token.
"&oauth_version=".$oathVersion.
"&x_auth_mode=client_auth".
"&x_auth_password=".$x_auth_password.
"&x_auth_username=".$x_auth_username,
CURLOPT_HTTPHEADER => array(
"Accept: */*",
"Accept-Encoding: gzip, deflate",
"Cache-Control: no-cache",
"Connection: keep-alive",
"Content-Length: $oath_stringlength",
"Content-Type: application/x-www-form-urlencoded",
"Host: www.example.com",
"User-Agent: curlAPICall",
"cache-control: no-cache"
),
));
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "... cURL Error #:" . $err;
} else {
echo $response;
$jsonresponse = json_decode($response, true);
print_r($jsonresponse);
}
?>

Related

Authenticating to Google Auth with PHP cURL causes continuously forwarding

I want to retrieve the Auth token from Google OAuth 2.0 ( i used this tutorial)
However, when I want to Authenticate, it results in an infinite loop of redirecting to nothing, thus kind of refreshing the page. Without any error messages. I cannot find out whats going wrong.
This is my PHP code:
<?php
// Admin Google API settings
// Portal url:
require_once('./curl.php');
define("CALLBACK_URL", "http://localhost/losapi/index2.php"); //Callback URL
define("AUTH_URL", "https://accounts.google.com/o/oauth2/v2/auth"); //Used to get CODE (not Token!)
define("CLIENT_ID", "***"); // Personal
define("CLIENT_SECRET", "***"); // Personal
define("SCOPE", "https://www.googleapis.com/auth/admin.directory.device.chromeos https://www.googleapis.com/auth/admin.directory.user https://www.googleapis.com/auth/admin.directory.orgunit"); // Depends on what you want to do.
define("APIURL_DIRECTORY","https://www.googleapis.com/admin/directory/v1/customer/"); // For Google Directory actions
define("CUSTOMER_ID","***"); // Personal
define("TOKEN_URL","https://oauth2.googleapis.com/token"); // URL to get Token (not code).
$curl = new \CURL\cURL();
// Initiate code for access token
if(isset($_GET["code"])){
//DEBUG: echo "Code: ".$_GET["code"];
$url = TOKEN_URL."?";
$url .= "code=".$_GET["code"];
$url .= "&grant_type=authorization_code";
$url .= "&client_id=". urlencode(CLIENT_ID);
$url .= "&client_secret=". urlencode(CLIENT_SECRET);
$url .= "&redirect_uri=". urlencode(CALLBACK_URL);
$response = json_decode($curl->exeCurl($url,"POST"), true);
if(isset($response)){
if(array_key_exists("access_token", $response)) {
$access_token = $response;
setcookie("LOStoken", $response['access_token'], time() + (86400 * 30), "/"); // 86400 = 1 day
}
}
} else {
if(isset($_POST['gettoken'])){
$url = AUTH_URL."?";
$url .= "response_type=code";
$url .= "&client_id=". urlencode(CLIENT_ID);
$url .= "&scope=". urlencode(SCOPE);
$url .= "&redirect_uri=". urlencode(CALLBACK_URL);
echo $curl->exeCurl($url,"GET");
}
}
?>
curl.php
namespace CURL;
class cURL
{
// Algeneme cURL functie om web call te doen.
function exeCurl($url,$method,$body="") {
$curl = curl_init(); // initiate curl
// Afhankelijk van TOKEN worden er andere headers gegeven.
if(isset($_COOKIE["LOStoken"])){
$headers = array(
"Accept: */*",
"Accept-Encoding: gzip, deflate",
"Authorization: Bearer ". $_COOKIE["LOStoken"],
"Connection: keep-alive",
"Content-Length: ". strlen($body),
"Content-Type: application/json",
"cache-control: no-cache"
);
} else {
$headers = array(
"Accept: */*",
"Cache-Control: no-cache",
"Content-Length: ". strlen($body),
"Connection: keep-alive",
"cache-control: no-cache"
);
}
// Set parameters for curl
$params = array(
CURLOPT_URL => $url, // API URL
CURLOPT_RETURNTRANSFER => true, // Return answer
CURLOPT_SSL_VERIFYPEER => false, // SSL, enable in production
//CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10, // Max redirect
CURLOPT_FOLLOWLOCATION => true, // If 301, follow redirect
CURLOPT_TIMEOUT => 30, // Max timeout
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, // HTTP version used
CURLOPT_CUSTOMREQUEST => $method, // HTTP method used
CURLOPT_HTTPHEADER => $headers); // HTTP headers
// Combineer curl + parameters
curl_setopt_array($curl, $params);
// Curl antwoorden
$response = curl_exec($curl);
$err = curl_error($curl); // vul met errors
curl_close($curl); // Sluit verbinding
if ($err) {
echo "cURL Error #:" . $err; // Als er errors zijn
}
if(array_key_exists("error", $response)) echo $response["error_description"];
return $response; // Geef volledige antwoord terug
}
}
You are trying to fetch the auth URL via cURL - that can not work, this authorization flow requires user interaction. You need to redirect the user to this URL in their browser.
You can either redirect the user to that URL automatically; or you just put it into the href attribute of a link, so that the user can click on that then, to start the whole process. (I would recommend the second option in general, but at least during development. With an automatic redirect, there’s a good chance you’ll create a circular redirect again, if anything goes wrong.)

Interrogate API until no results left

I am working with an API at the moment that will only return 200 results at a time, so I am trying to run some code that works out if there is more data to fetch based on whether or not the results have a offsetCursor param in them as this tells me that that there are more results to get, this offsetCursor is then sent a param in the next request, the next set of results come back and if there is an offsetCursor param then we make another request.
What I am wanting to do is push the results of each request into a an array, here is my attempt,
function get_cars($url, $token)
{
$cars = [];
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => array(
"Content-Type: application/x-www-form-urlencoded",
"Authorization: Bearer " . $token
)
));
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if($err) {
return false;
} else {
$results = json_decode($response, TRUE);
//die(print_r($results));
$cars[] = $results['_embedded']['results'];
if(isset($results['cursorOffset']))
{
//die($url.'&cursor_offset='.$results['cursorOffset']);
get_cars('https://abcdefg.co.uk/service/search1/advert?size=5&cursor_offset='.$results['cursorOffset'], $token);
//array_push($cars, $results['_embedded']['results']);
}
}
die(print_r($cars));
}
I assume I am doing the polling of the api correct in so mush as that if there is a cursor offet then I just call the function from within itself? But I am struggling to create an array from the results that isnt just an array within and array like this,
[
[result from call],
[resul from call 2]
]
what I really want is result from call1 right through to call n be all within the same sequential array.
using a do+while loop, you'll have only 1 instance of cars variable, that would work.
Since you're using recursion, when you call get_cars inside get_cars, you have 2 instances of cars variable, one per get_cars call.
IMHO, using a loop is better in your case.
But if you still want to use recursion, you should use the result of get_cars call, something like this:
if(isset($results['cursorOffset']))
{
//die($url.'&cursor_offset='.$results['cursorOffset']);
$newcars = get_cars('https://abcdefg.co.uk/service/search1/advert?size=5&cursor_offset='.$results['cursorOffset'], $token);
$cars = array_merge($cars, $newcars);
//array_push($cars, $results['_embedded']['results']);
}
(and get_cars should return $cars, instead of printing it with print_r)
Edit: here is an example of, untested, code with a while loop (no need for do+while here)
<?php
function get_cars($baseUrl, $token)
{
$cars = [];
// set default url to call (1st call)
$url = $baseUrl;
while (!empty($url))
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => array(
"Content-Type: application/x-www-form-urlencoded",
"Authorization: Bearer " . $token
)
));
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if($err)
{
// it was "return false" in your code
// what if it's the 3rd call that fails ?
// - "return $cars" will return cars from call 1 and 2 (which are OK)
// - "return false" will return no car (but call 1 and 2 were OK !!)
return $cars;
}
$results = json_decode($response, TRUE);
$cars[] = $results['_embedded']['results'];
if(isset($results['cursorOffset']))
{
// next call will be using this url
$url = $baseUrl . '&cursor_offset='.$results['cursorOffset'];
// DONT DO THE FOLLOWING (concatenating with $url, $url = $url . 'xxx')
// you will end up with url like 'http://example.com/path/to/service?cursor_offset=xxx&cursor_offset==yyy&cursor_offset==zzz'
// $url = $url . '&cursor_offset='.$results['cursorOffset'];
}
else
{
$url = null;
}
}
return $cars;
}

How to import php file to your controller and gather data

My Controller.
public function showMonthlyReport($site_id, $report_id){
$reports = Report::where('report_id', $report_id)->firstOrFail();
$uptime = ???
return view('records', compact('site_id', 'report_id', 'reports', 'uptime'));
}
And my UptimeRobot.php reference https://uptimerobot.com/api getMonitors()method
<?php
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => "https://api.uptimerobot.com/v2/getMonitors",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "Your Api Key",
CURLOPT_HTTPHEADER => array(
"cache-control: no-cache",
"content-type: application/x-www-form-urlencoded"
),
));
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
$data = json_decode($response);
$custom_uptime = ($data->monitors[0]->custom_uptime_ratio);
$uptime = explode("-",$custom_uptime);
}
?>
ApiCommand.php
public function handle()
{
include(app_path() . '/Includes/DeepCrawl.php');
include(app_path() . '/Includes/Uptime.php');
include(app_path() . '/Includes/HelloAnalytics.php');
$stringData = ApiCommand::drawGraph($uptime, $dates, $users, $otherResultsRows, $array_issues, $array_pages_breakdown, $array_uncrawled_url, $array_non_200_pages, $array_orphaned_pages, $array_non_indexable_pages, $array_crawl_source_gap, $array_https_http);
Storage::disk('local')->put('hello.txt', $stringData);
}
Currently building a laravel web application.
I am just wondering how can i able to gather data from uptimerobot. I'm going to use my controller so I can pass it to my view but I don't know how. I have code below with the curl php type above. Really confused what am I doing new programmer here. Can someone explain if I'm at the right path or is it possible to do in controller. Thanks in advance.
I can suggest slightly different solution:
Extract your curl code in a separate console command and run this command each minute (for example, as a cron job).
The result of the command save to database/file/memory.
In your showMonthlyReport() refer to existing result.
Benefits:
In this way you would not have to wait for your curl result on each showMonthlyReport(). All code will run asynchronously
All errors processing will be in one place
Command is testable

How to use CURL to send data for Wordpress

I would like to send data from one WP site to an other.
I have two plugins the sender ad the reciver.
In the sender side I used the init hook
add_action('init', array($this, 'say_hello') );
....
public function say_hello() {
$data = get_plugin_data( $this->pDIR.'/plugin.php', $markup = false, $translate = false );
$url = $_SERVER['HTTP_HOST'].'/wp-admin/admin-ajax.php';
$fields = array(
'action' => 'Hello_ajax',
'zpm_hello' => '1',
'zpm_plugin_version' => $data['Version'],
'zpm_host' => $_SERVER['HTTP_HOST']
);
foreach($fields as $key=>$value) {
$fields_string .= $key.'='.$value.'&';
}
rtrim($fields_string, '&');
//open connection
$ch = curl_init();
//set the url, number of POST vars, POST data
curl_setopt($ch,CURLOPT_URL, $url);
curl_setopt($ch,CURLOPT_POST, count($fields));
curl_setopt($ch,CURLOPT_POSTFIELDS, $fields_string);
//execute post
$result = curl_exec($ch);
var_dump($result);
//close connection
curl_close($ch);
}
The variables are fine the url is correct I printed out.
On the reciver side I registered the admin ajax
add_action('wp_ajax_Hello_ajax', array($this, 'zpm_api_hello'));
add_action('wp_ajax_nopriv_Hello_ajax', array($this, 'zpm_api_hello'));
public function zpm_api_hello() {
$response['success'] = false;
$response['response'] = "";
$error = false;
$hello = $_POST['zpm_hello'];
$plugin_version = $_POST['zpm_plugin_version'];
$plugin_host = $_POST['zpm_host'];
if(!isset($hello)) {
$error = true;
$response['response'] .= "Ello >> Auth ERROR - CODE - 01 ";
}
if(!isset($plugin_version)) {
$error = true;
$response['response'] .= "Ello >> Plugin Version error - CODE - 02 ";
}
if(!isset($plugin_host)) {
$error = true;
$response['response'] .= "Ello >> Plugin host error - CODE - 03 ";
}
if(!$error) {
$response['success'] = true;
$response['response'] .= "Ello >> Auth OK ";
}
echo json_encode($response);
die();
}
So the code is here.
My problem is when I try to load the sender site it is just loading and loading for ever and I doesn't get back the result. Could you tell me what could be the problem with this method? Thanks all of your answers!
you might want to use this example to build your PHP request, if you send me the POST body, headers and url parameters I will even build it for you:
<?php
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => "http://example.com//wp-admin/admin-ajax.php",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "blakey=blaval",
CURLOPT_HTTPHEADER => array(
"action: Hello_ajax",
"cache-control: no-cache",
"content-type: application/x-www-form-urlencoded",
"postman-token: fd5bcc0b-f46d-0cf8-a5cf-dc83bfe7dbec",
"zpm_hello: 1"
),
));
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}

Mention API - Mark a mention as READ

Using the API here: https://dev.mention.com/resources/alert_mentions/#put-accounts-id-alerts-alert-id-mentions-mention-id
From what I understand, if I want to mark a specific "mention" as read, I do something like this:
$browser = new \Buzz\Browser(new \Buzz\Client\Curl);
$params = ['read' => true]; //tried this
$url = "https://api.mention.net/api/accounts/" . $this->getAccountId() . "/alerts/{$alert_id}/mentions/{$mention_id}";
if(!empty($params))
{
$url .= '?' . http_build_query($params); //i think this isnt needed because i pass $params below to the $browser->put but it was worth a try.
}
$response = $browser->put($url, array(
"Authorization: Bearer {$this->getAccessToken()}",
"Accept: application/json",
), $params);
if (200 != $response->getStatusCode()) {
return false;
}
However, when I run the code, it doesn't produce any errors and infact returns a valid response, but the "read" flag is still set to false.
Also tried:
$params = ['read' => 'true']; //tried this
$params = ['read' => 1]; //tried this
The Mention API accepts JSON in request bodies: https://dev.mention.com/#request-format
You can mark a mention as read like this:
$params = ['read' => true];
// params are json encoded
$params = json_encode($params);
$response = $browser->put($url, array(
"Authorization: Bearer $token",
"Accept: application/json",
// the Content-Type header is set to application/json
"Content-Type: application/json",
), $params);

Categories