So, I had issue because I don't have OAuth 1, so to access to ETSY API I had to struggle.
finally I have this :
My function __construct() :
parent::__construct();
$this->allowForUser();
$this->etsyDb = new EtsyordersModel;
$this->client = new Etsy([
'identifier' => getApp()->getConfig('identifier'),
'secret' => getApp()->getConfig('secret'),
'scope' => 'listings_r transactions_r',
'callback_uri' => 'http://*****-*****.loc/etsyapp/next',
'access_token' => getApp()->getConfig('access_token'),
'access_token_secret' => getApp()->getConfig('access_token_secret'),
]);
And here is how I get the url to access my JSON with the result :
$key = rawurlencode($oauthtoken) . "&" . rawurlencode($tokensecret);
$method = "GET";
$baseurl = "https://openapi.etsy.com/v2/shops/24749672/receipts/";
$nonce = "1234";
$timenow = time();
$oauthversion = '1.0';
$paramstring = "oauth_consumer_key=" . $oauthconsumerkey . "&oauth_nonce=" . $nonce . "&oauth_signature_method=HMAC-SHA1" . "&oauth_timestamp=" . $timenow . "&oauth_token=" . $clientsecret . "&oauth_version=" . $oauthversion;
//
// Signature GET to retrieve signature OAuth
$encodeurl = $method . "&" . rawurlencode($baseurl) . "&" . rawurlencode($paramstring);
$signature = hash_hmac( 'sha1', $encodeurl, $key, TRUE );
$signature = base64_encode( $signature );
// url JSON shop ETSY
$curlurl = $baseurl . "?" . $paramstring . "&oauth_signature=" . $signature;
// get JSON content in $orders
$orders = file_get_contents($curlurl);
And so I get my JSON :
I got 90++ items, but because of the pagination, it show me only 25 items.
I tried to add active?limit=100&offset=0 to my $baseurl (at the end of it, as parameter for signature calculation) but it say oauth_problem=signature_invalid&. I tried to put it on the $paramstring
instead, but same result.
How can I have all my result shown, or how can I access to page 2, 3, etc... of the pagination?
I am on PHP 7.4, XAMPP (one of the last version), I don't have OAuth 1 so I used a combination of package Y0lk\OAuth1 and thephpleague\oauth1-client.
Thank you for your time.
I'm trying to connect to the LivePerson Engagement History API and I'm running into an issue that I believe is related to the signature being generated.
First off, the API already provides the necessary consumer key, consumer secret, access token, and token secret. So I don't have to go through the process of retrieving those. In order to access their API I just have to provide the auth header. I've mocked everything up using Postman and it all works correctly. The issue is when I try to generate my own timestamp/nonce/signature in my class.
Here's the method from my class that sends the cURL request:
private function execute($options = array())
{
if (!isset($options['url'])) {
return;
}
$ch = curl_init($options['url']);
$method = (isset($options['method'])) ? $options['method'] : 'GET';
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
if (isset($options['auth']) && $options['auth']) {
$timestamp = round(microtime(true) * 1000);
$nonce = $this->getNonce(11);
$version = "1.0";
$signatureMethod = "HMAC-SHA1";
$signature = $this->generateSignature($options, $timestamp, $nonce, $signatureMethod, $version);
$authHeader = "Authorization: OAuth oauth_consumer_key=\"{$this->consumerKey}\",oauth_token=\"{$this->accessToken}\",oauth_signature_method=\"{$signatureMethod}\",oauth_timestamp=\"{$timestamp}\",oauth_nonce=\"{$nonce}\",oauth_version=\"{$version}\",oauth_signature=\"{$signature}\"";
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
$authHeader,
"Content-Type: application/json"
));
}
if (isset($options['body']) && !empty($options['body'])) {
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($options['body']));
}
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
The getNonce method I copied pretty much directly from https://github.com/BaglerIT/OAuthSimple/blob/master/src/OAuthSimple.php.
Here's the method I've written to generate the signature (which has been cobbled together from various SO posts and other sources):
protected function generateSignature($request, $timestamp, $nonce, $signatureMethod, $version)
{
$base = $request['method'] . "&" . rawurlencode($request['url']) . "&"
. rawurlencode("oauth_consumer_key=" . rawurlencode($this->consumerKey)
. "&oauth_nonce=" . rawurlencode($nonce)
. "&oauth_signature_method=" . rawurlencode($signatureMethod)
. "&oauth_timestamp=" . $timestamp
. "&oauth_version=" . $version);
$key = rawurlencode($this->consumerSecret) . '&' . rawurlencode($this->tokenSecret);
$signature = base64_encode(hash_hmac('sha1', $base, $key, true));
return $signature;
}
I can actually copy and paste the authorization header from Postman into my $authHeader variable, and replace everything except the timestamp/nonce/signature, and it works.
The response I'm getting from their server right now is [code] => 0005 but I can't find anything in their docs about response codes.
Edit: I had missed looking at the response header - the exact error is invalid signature.
There are 2 things I changed to get this to work.
I was missing the oauth_token when creating the base string for the signature
According to the OAuth Core 1.0 documentation, "Parameters are sorted by name, using lexicographical byte value ordering."
So I ended up re-ordering the parameters to be alphabetical. Here's what the code for generating the base string ended up looking like:
$base = $request['method'] . "&" . rawurlencode($request['url']) . "&"
. rawurlencode("oauth_consumer_key=" . rawurlencode($this->consumerKey)
. "&oauth_nonce=" . rawurlencode($nonce)
. "&oauth_signature_method=" . rawurlencode($signatureMethod)
. "&oauth_timestamp=" . rawurlencode($timestamp)
. "&oauth_token=" . rawurlencode($this->accessToken)
. "&oauth_version=" . rawurlencode($version));
I also re-ordered the params in the auth header to match the order of the base string:
$authHeader = "Authorization: OAuth oauth_consumer_key=\"{$this->consumerKey}\",oauth_nonce=\"{$nonce}\",oauth_signature_method=\"{$signatureMethod}\",oauth_timestamp=\"{$timestamp}\",oauth_token=\"{$this->accessToken}\",oauth_version=\"{$version}\",oauth_signature=\"{$signature}\"";
$base = $request['method']
. '&' . rawurlencode($request['url'])
. '&' . rawurlencode('oauth_consumer_key=' . $this->consumerKey)
. rawurlencode('&oauth_nonce=' . $nonce)
. rawurlencode('&oauth_signature_method=' . $signatureMethod)
. rawurlencode('&oauth_timestamp=' . $timestamp)
. rawurlencode('&oauth_version=' . $version)
. rawurlencode('&' . http_build_query($data));
$key = rawurlencode($this->consumerSecret) . '&';
$signature = rawurlencode(base64_encode(hash_hmac('SHA1', $base, $key, true)));
If you do a POST, make sure to include your posted data, otherwise the signature will not validate.
CURLOPT_HTTPHEADER => array(
"authorization: OAuth oauth_consumer_key=\"{$consumerKey}\",oauth_signature_method=\"{$signatureMethod}\",oauth_timestamp=\"{$timestamp}\",oauth_nonce=\"{$nonce}\",oauth_version=\"{$version}\",oauth_signature=\"{$oauthSignature}\"",
"content-type: application/x-www-form-urlencoded",
),
And the header should be as above
This fixed version worked for me :
function generateOauthSignature($method, $url, $consumerKey, $nonce, $signatureMethod, $timestamp, $version, $consumerSecret, $tokenSecret, $tokenValue, $extraParams = array())
{
$base = strtoupper($method) . "&" . rawurlencode($url) . "&"
. rawurlencode("oauth_consumer_key=" . $consumerKey
. "&oauth_nonce=" . $nonce
. "&oauth_signature_method=" . $signatureMethod
. "&oauth_timestamp=" . $timestamp
. "&oauth_token=" . $tokenValue
. "&oauth_version=" . $version);
if (!empty($extraParams)) {
$base .= rawurlencode("&" . http_build_query($extraParams));
}
$key = rawurlencode($consumerSecret) . '&' . rawurlencode($tokenSecret);
$signature = base64_encode(hash_hmac('sha1', $base, $key, true));
return rawurlencode($signature);
}
The following twitter thread helped me : https://twittercommunity.com/t/how-to-generate-oauth-signature-when-post-json-body-in-php/87581
I was also struggling with the proper setup of the OAuth 1 signature and had a lot of failed attempts. After TGA's hint to have a look how it's done with Twitter, I found out that there is an existing class which may be used out-of-the-box:
TwitterAPIExchange.php from the repository https://github.com/J7mbo/twitter-api-php.
Even if is called "Twitter...", it may also be used for other OAuth1 APIs. Calls will look like this:
$settings = array(
'oauth_access_token' => TOKEN,
'oauth_access_token_secret' => TOKEN_SECRET,
'consumer_key' => CONSUMER_KEY,
'consumer_secret' => CONSUMER_SECRET
);
$url = "https://api-url.com/api/v4/users/0451432/";
$requestMethod = 'POST';
$postfields = array(
'groupIds' => '23,24,25',
);
$twitter = new TwitterAPIExchange($settings);
return $twitter->buildOauth($url, $requestMethod)
->setPostfields($postfields)
->performRequest();
It works perfect for me.
This version matches the OAuth PECL library's function so you no longer need it.
public static function oauth_get_sbs(
$requestMethod,
$requestURL,
$request_parameters
): string
{
return $requestMethod . "&" . rawurlencode($requestURL) . "&"
. rawurlencode("oauth_consumer_key=" . rawurlencode($request_parameters['oauth_consumer_key'])
. "&oauth_nonce=" . rawurlencode($request_parameters['oauth_nonce'])
. "&oauth_signature_method=" . rawurlencode($request_parameters['oauth_signature_method'])
. "&oauth_timestamp=" . $request_parameters['oauth_timestamp']
. "&oauth_token=" . $request_parameters['oauth_token']
. "&oauth_version=" . $request_parameters['oauth_version']);
}
I'm trying to create a script that uses the twitter streaming api to keep a tab on tweets with a certain hash-tag.
Whenever I try creating a request though, I always get a 401 Unauthorized return. Can anyone help me figure out what I'm doing incorrectly?
I tried to follow twitter's api to the dot, but apparently I'm doing something wrong. The code I have is below.
$base_url_string = urlencode($base_url);
$parameter_string = urlencode('oauth_consumer_key') . '=' . urlencode($consumer_key) . '&'
. urlencode('oauth_nonce') . '=' . urlencode($nonce) . '&'
. urlencode('oauth_signature_method') . '=' . urlencode($signature_method) . '&'
. urlencode('oauth_timestamp') . '=' . urlencode($timestamp) . '&'
. urlencode('oauth_token') . '=' . urlencode($token) . '&'
. urlencode('oauth_version') . '=' . urlencode($version) . '&'
. urlencode('track') . '=' . urlencode('#kitten');
$signature_base_string = $method . "&" . $base_url_string . "&" . urlencode($parameter_string);
$signature = base64_encode(hash_hmac('sha1', $signature_base_string, $secret, true));
$fp = fsockopen("ssl://stream.twitter.com", 443, $errno, $errstr, 30);
if (!$fp) {
print "$errstr ($errno)\n";
} else {
$request = $method . " /1.1/statuses/filter.json?" . urlencode("track") . "=" . urlencode("#kitten") . " HTTP/1.1\r\n";
$request .= "Host: stream.twitter.com\r\n";
$request .= 'Authorization: OAuth'
. ' oauth_consumer_key="' . $consumer_key . '",'
. ' oauth_nonce="' . $nonce . '",'
. ' oauth_signature="' . $signature . '",'
. ' oauth_signature_method="' . $signature_method . '",'
. ' oauth_timestamp="' . $timestamp . '",'
. ' oauth_token="' . $token . '",'
. ' oauth_version="' . $version . '"'
. "\r\n\r\n";
print $request . "</br>";
fwrite($fp, $request);
while (!feof($fp)) {
$json = fgets($fp);
echo $json;
$data = json_decode($json, true);
if ($data) {
print $data;
}
}
print 'exiting...';
fclose($fp);
}
Ok so I figured this all out. It was a combination of poor string manipulation and not Percent Encoding everything. Both the keys and values of the OAuth string must be Percent encoded. I had done that in the signature, but not in the actual request. Once I fixed that, the request got through and I was connected to the Twitter Streaming API.
I am trying to construct a custom upload script that uploads to a defined flickr account, I'm looking for something other than phpflickr (which uses the deprecated version of the flickr api). I know how to authorize flickr calls in the new method and have successfully used at least half-a-dozen of their methods but I'm failing to understand how to upload (mainly due to the fact of very limited documentation).
Here is my authorization call that I'm using:
<?php
$url = "format=" . $this->format;
$url .= "&method=" . $method;
$url .= "&nojsoncallback=1";
$url .= "&oauth_consumer_key=" . $this->flickr_key;
$url .= "&oauth_nonce=" . $this->nonce;
$url .= "&oauth_signature_method=" . $this->sig_method;
$url .= "&oauth_timestamp=" . $this->timestamp;
$url .= "&oauth_token=" . $access_token;
$url .= "&oauth_version=1.0";
$url .= "&photoset_id=" . $photoset_id;
$baseurl = "GET&" . urlencode( $flickr_upload_call ) . "&" . urlencode( $url );
$hashkey = $this->flickr_secret . "&" . $access_token_secret;
$oauth_signature = base64_encode( hash_hmac( 'sha1', $baseurl, $hashkey, true ));
$url_parameters = array(
'method' =>$method,
'oauth_consumer_key' =>$this->flickr_key,
'photoset_id' =>$photoset_id,
'format' =>$this->format,
'nojsoncallback' =>'1',
'oauth_nonce' =>$this->nonce,
'oauth_timestamp' =>$this->timestamp,
'oauth_signature_method'=>$this->sig_method,
'oauth_version' =>'1.0',
'oauth_token' =>$access_token,
'oauth_signature' =>$oauth_signature
);
/* Now that we have encoded the parameters for our ouath_signature
* and have reformated them for the url we need to send... we must
* re-urlencode them too. */
$parameters_string = "";
foreach ( $url_parameters as $key=>$value )
$parameters_string .= "$key=" . urlencode( $value ) . "&";
$url = $flickr_api_call . "?" . $parameters_string;
So, what I need to know is how to change this to allow for the flickr upload api to accept it; any ways I can do this better, or how can I use what is in phpflickr and convert it to the new method to suit my needs?
I am trying to create a PHP page that will create a photo album and upload a photo. So far, it authenticates and creates a photo album without any problem but I cant seem to get it to upload the photo. I keep getting the following error:
Warning: fopen(https://graph.facebook.com/yyyyyyyyyyyyyyyyy/photos?access_token=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx) [function.fopen]: failed to open stream: HTTP request failed! HTTP/1.0 400 Bad Request in /home/content/30/8734730/html/uploadPhoto.php on line 96
<html>
<head>
<title>Photo Upload</title>
</head>
<body>
<?php
$app_id = "xxxxxxxxxxxxxxxx";
$app_secret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
$post_login_url = "http://xyz.com/uploadPhoto.php";
$album_name = "Brand Image Productions";
$album_description = "Blah Blah event Photos";
$photo_source = 'C:\Users\Public\Pictures\Sample Pictures\Lighthouse.jpg';
$photo_message = 'Here is the lighthouse';
$code = $_REQUEST["code"];
echo "code ==>" . $code . '<br/><br/>';
//Obtain the access_token with publish_stream permission
if(empty($code)){
$dialog_url= "http://www.facebook.com/dialog/oauth?"
. "client_id=" . $app_id
. "&redirect_uri=" . urlencode($post_login_url)
. "&scope=publish_stream,user_photos";
echo("<script>top.location.href='" . $dialog_url .
"'</script>");
}
else {
$token_url= "https://graph.facebook.com/oauth/"
. "access_token?"
. "client_id=" . $app_id
. "&redirect_uri=" . urlencode( $post_login_url)
. "&client_secret=" . $app_secret
. "&code=" . $code;
$response = file_get_contents($token_url);
$params = null;
parse_str($response, $params);
$access_token = $params['access_token'];
echo "access_token ==>" . $access_token . '<br/><br/>';
// Create a new album
$graph_url = "https://graph.facebook.com/me/albums?"
. "access_token=". $access_token;
$postdata = http_build_query(
array(
'name' => $album_name,
'message' => $album_description
)
);
$opts = array('http' =>
array(
'method'=> 'POST',
'header'=> 'Content-type: application/x-www-form-urlencoded',
'content' => $postdata
)
);
$context = stream_context_create($opts);
$result = json_decode(file_get_contents($graph_url, false, $context));
// Get the new album ID
$album_id = $result->id; //upload photo
echo "album_id ==>" . $album_id . '<br/><br/>';
// Upload the photo
$graph_url = "https://graph.facebook.com/" . $album_id . "/photos?access_token=" . $access_token;
echo "graph_url ==>" . $graph_url . '<br/><br/>';
echo "photo_message ==>" . $photo_message . '<br/>';
echo "photo_source ==>" . $photo_source . '<br/><br/>';
$postdata = http_build_query(
array(
'message' => $photo_message,
'source' => $photo_source
)
);
$opts = array('http' =>
array(
'method'=> 'POST',
'header'=> 'Content-type: application/x-www-form-urlencoded',
'enctype' => 'multipart/form-data',
'content' => $postdata
)
);
$context = stream_context_create($opts);
$fp = fopen($graph_url, 'r', false, $context);
fpassthru($fp);
fclose($fp);
}
?>
</body>
</html>