Convert Rest API call from PHP to RUBY - php

Im trying to convert a post connection to the walmart api, from php to ruby, this is the php version
$client_id = $data['client_id'];
$client_secret = $data['client_secret'];
$url = "https://marketplace.walmartapis.com/v3/token";
$uniqid = uniqid();
$authorization_key = base64_encode($client_id.":".$client_secret);
$code = "";
$ch = curl_init();
$options = array(
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 60,
CURLOPT_HEADER => false,
CURLOPT_POST =>1,
CURLOPT_POSTFIELDS => "grant_type=client_credentials",
CURLOPT_HTTPHEADER => array(
"WM_SVC.NAME: Walmart Marketplace",
"WM_QOS.CORRELATION_ID: $uniqid",
"Authorization: Basic $authorization_key",
"Accept: application/json",
"Content-Type: application/x-www-form-urlencoded",
),
);
curl_setopt_array($ch,$options);
$response = curl_exec($ch);
$code = curl_getinfo($ch,CURLINFO_HTTP_CODE);
curl_close($ch);
and this is what i have so far:
url = "https://marketplace.walmartapis.com/v3/token/"
uniqid = "1234567890a1b"
uri = URI.parse(url)
request = Net::HTTP::Post.new(uri)
request["WM_SVC.NAME"] = "Walmart Marketplace"
request["WM_QOS.CORRELATION_ID"] = uniqid
request.basic_auth(client_id, client_secret)
request["Accept"] = "application/json"
request.content_type = "application/x-www-form-urlencoded"
request["WM_SVC.VERSION"] = "1.0.0"
req_options = {
use_ssl: uri.scheme == "https",
}
response = Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') do |http|
http.request(request)
end
puts "error " + response.code
puts response.body
Now, im getting a 400 error, so something of the data im sending is incorrect or missing... comparing both, i dont have set the postfields option on ruby, for the POST request, not sure if the rest is required as well... any ideas?

Try adding this line:
request.body = 'grant_type=client_credentials'

Related

PHP - Getting bearer token from HERE REST API throws a signature mismatch error

before posting this question I have searched a solution for a long but all the snippets of code I tried always failed. It sounds really weird that there aren't working examples available in PHP!
I want to use HERE Maps REST API to geocode mail addresses. I have created my account and got the credentials as prerequisite.
Reference articles I followed are:
https://developer.here.com/blog/requesting-here-oauth-bearer-token-using-python
Cannot generate token via Here Map API in php
HERE Maps: Invalid Client Authorization header, expecting signed request format
https://developer.here.com/documentation/identity-access-management/dev_guide/topics/postman.html
The code I have developed is a combination/adaption of these referenced articles:
//This snippet is for signature
$timer = time();
$grant_type = 'client_credentials';
$oauth_consumer_key = 'here.access.key.id';
$oauth_nonce = (string)((int) ($timer * 1000));
$oauth_signature_method = 'HMAC-SHA256';
$oauth_timestamp = (string) ((int) ($timer));
$oauth_version = '1.0';
$url = 'https://account.api.here.com/oauth2/token';
$access_key_secret = "here.access.key.secret";
$parameter_string = 'grant_type='.$grant_type;
$parameter_string .= '&oauth_consumer_key='.$oauth_consumer_key;
$parameter_string .= '&oauth_nonce='.$oauth_nonce;
$parameter_string .= '&oauth_signature_method='.$oauth_signature_method;
$parameter_string .= '&oauth_version='.$oauth_version;
$encode_parameter_string = urlencode($parameter_string);
$encoded_base_string = 'POST'.'&'.urlencode($url).'&'.$encode_parameter_string;
$signing_key = $access_key_secret.'&';
$signature = hash_hmac('sha256', $encoded_base_string, $signing_key, true);
$encodedSignature = base64_encode($signature);
//This snippet is for getting the bearer token
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => 'grant_type=client_credentials',
CURLOPT_HTTPHEADER => array(
'oauth_consumer_key: '.urlencode($oauth_consumer_key),
'oauth_nonce: '.urlencode($oauth_nonce),
'oauth_signature: '.urlencode($encodedSignature),
'oauth_signature_method: '.urlencode($oauth_signature_method),
'oauth_timestamp: '.urlencode($oauth_timestamp),
'oauth_version: '.urlencode($oauth_version),
'Content-Type: application/x-www-form-urlencoded',
'Authorization: OAuth oauth_consumer_key="'.urlencode($oauth_consumer_key).'",oauth_signature_method="'.urlencode($oauth_signature_method).'",oauth_timestamp="'.urlencode($oauth_timestamp).'",oauth_nonce="'.urlencode($oauth_nonce).'",oauth_version="'.urlencode($oauth_version).'",oauth_signature="'.urlencode($encodedSignature).'"'
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
This seems to avoid the wrong formatting of the request, the main error message I used to get as response. Unfortunately, the new error thrown with this snippet is "errorCode":401300,"message":"Signature mismatch. Authorization signature or client credential is wrong." but I am sure that the credentials I am passing are correct.
I suspect there is something wrong in the signature snippet. Any clue? Can you help me to provide a reference for HERE Oauth signature in PHP?
Thanks for sharing your comments!
I made it!
I missed a parameter in the signature and the $encodedSignature must be further url-encoded. Then I was able to get my access token.
I am embedding the full working code, hoping that this may help the community:
<?php
$timer = (string) time();
$grant_type = 'client_credentials';
$oauth_consumer_key = 'my_consumer_key';
$oauth_nonce = uniqid(mt_rand(1, 1000));
$oauth_signature_method = 'HMAC-SHA256';
$oauth_timestamp = $timer;
$oauth_version = '1.0';
$url = 'https://account.api.here.com/oauth2/token';
$access_key_secret = "my_access_key_secret";
$parameter_string = 'grant_type='.$grant_type;
$parameter_string .= '&oauth_consumer_key='.$oauth_consumer_key;
$parameter_string .= '&oauth_nonce='.$oauth_nonce;
$parameter_string .= '&oauth_signature_method='.$oauth_signature_method;
$parameter_string .= '&oauth_timestamp='.$oauth_timestamp;
$parameter_string .= '&oauth_version='.$oauth_version;
$encoded_parameter_string = urlencode($parameter_string);
$encoded_base_string = 'POST'.'&'.urlencode($url).'&'.$encoded_parameter_string;
$signing_key = $access_key_secret.'&';
$signature = hash_hmac('SHA256', $encoded_base_string, $signing_key, true);
$encodedSignature = urlencode(base64_encode($signature));
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://account.api.here.com/oauth2/token',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => 'grant_type=client_credentials',
CURLOPT_HTTPHEADER => array(
'Authorization: OAuth oauth_consumer_key="'.$oauth_consumer_key.'",oauth_signature_method="HMAC-SHA256",oauth_timestamp="'.$oauth_timestamp.'",oauth_nonce="'.$oauth_nonce.'",oauth_version="1.0",oauth_signature="'.$encodedSignature.'"',
'Content-Type: application/x-www-form-urlencoded'
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;

Converting wp_remote_post() to cURL

I have this WordPress code using wp_remote_post() to make an API call to LinkedIn.
$args = array(
'headers' => array('Content-Type' => 'text/xml'),
'body' => "<?xml version='1.0' encoding='UTF-8' standalone='yes'?><company><id>{$nCompanyID}</id></company>"
);
$access_token = $datapass->access_token_get();
$params = array('oauth2_access_token' => $access_token);
$resource = "https://api.linkedin.com/v1/people/~/following/companies?" . http_build_query($params);
$response = wp_remote_post( $resource, $args);
$code = $response['response']['code'];
$body = wp_remote_retrieve_body($response);
$RV = ($code == '201');
return $RV;
It works. Now, I need to convert it to php cURL.
I have tried various examples of php cURL posting XML that I found online, but no luck.
Here's the latest attempt.
$access_token = "long_string_of_characters";
$nCompanyID = 2495437;
$xml = "<?xml version='1.0' encoding='UTF-8' standalone='yes'?><company><id>{$nCompanyID}</id></company>";
$url = 'https://api.linkedin.com/v1/people/~/following/companies?oauth2_access_token='.$access_token;
$headers = array(
"Content-type: text/xml",
"Content-length: " . strlen($xml)
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, array('body' => $xml));
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$data = curl_exec($ch);
$data comes back with a 400 error and message saying 'Unexpected element: CDATA'. If I remove the array from CURLOPT_POSTFIELDS and use just $xml, $data comes back as an empty string.
Any help will be appreciated.
If the server is expecting an XML POST, then passing an array to CURLOPT_POSTFIELDS is not going to make it happy.
Note in your original code the method of building the URL:
$params = array('oauth2_access_token' => $access_token);
$resource = "https://api.linkedin.com/v1/people/~/following/companies?" . http_build_query($params);
You'll want to keep that. http_build_query() performs the escaping needed if your access token contains special characters.
I'd have questions whether or not your access token is valid, given the original code seems to dynamically generate it with $datapass->access_token_get();
Otherwise it looks like you have everything set the same.
<?php
$access_token = "long_string_of_characters";
$nCompanyID = 2495437;
$xml = "<?xml version='1.0' encoding='UTF-8' standalone='yes'?><company><id>$nCompanyID</id></company>";
$params = ["oauth2_access_token" => $access_token];
$url = "https://api.linkedin.com/v1/people/~/following/companies?";
$url .= http_build_query($params);
$headers = [
"Content-type: text/xml",
"Content-length: " . strlen($xml)
];
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $xml,
CURLOPT_HTTPHEADER => $headers,
]);
$data = curl_exec($ch);

Missing parameters when requesting OAUTH token survey monkey v3

I'm trying to obtain my "long lived access token" using CURL/PHP but I'm receiving the error "Missing parameters for client_id, client_secret, code, grant_type, redirect_uri".
The URL I'm calling is where you can clearly see the parameters I'm trying to pass in!
https://api.surveymonkey.net/oauth/token?client_secret='.urlencode($client_secret).'&code='.urlencode($short_token).'&redirect_uri='.urlencode($redirect_url).'&client_id='.urlencode($client_id).'&grant_type=authorization_code
I'm also using the content-type of "application/x-www-form-urlencoded" as per the docs (see below).
My CURL request:
function survey_monkey_curl_request($url, $params=[], $request_type = 'get', $access_token) {
print_r($url);
$ch = curl_init();
$headers = [
"Content-Type: application/x-www-form-urlencoded",
"Authorization: bearer " .$access_token
];
$opts = [
CURLOPT_URL => $url,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_0,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_SSL_VERIFYPEER => 0,
];
if ($request_type == 'post') {
$opts[CURLOPT_POST] = 1;
//$opts[CURLOPT_POSTFIELDS] = json_encode($params);
}
if ($request_type == 'patch') {
$opts[CURLOPT_CUSTOMREQUEST] = "PATCH";
$opts[CURLOPT_POSTFIELDS] = json_encode($params);
}
curl_setopt_array($ch, $opts);
$result = curl_exec($ch);
if ($result === false) {
curl_close($ch);
throw new Exception(curl_error($ch));
}
curl_close($ch);
return $result;
}
Where am I going wrong?
Straight from the documentation it looks like to get the long-lived token you need to post your fields:
//Exchange for long-lived token
curl -i -X POST https://api.surveymonkey.net/oauth/token -d \
"client_secret=YOUR_CLIENT_SECRET \
&code=AUTH_CODE \
&redirect_uri=YOUR_REDIRECT_URI \
&client_id=YOUR_CLIENT_ID \
&grant_type=authorization_code"
https://developer.surveymonkey.com/api/v3/?shell#new-authentication
When you append your parameters onto your url you are sending then as GET request paramters
You need to put your data string into CURL POSTFIELDS and do not json encode
The PHP Answer
<?php
$ch = curl_init();
$data = [
'client_secret' => $YOUR_CLIENT_SECRET,
'code' => $AUTH_CODE,
'redirect_url' => $YOUR_REDIRECT_URI,
'client_id' => $YOUR_CLIENT_ID,
'grant_type' => 'authorization_code'
];//set your data as an array
$headers = [
"Content-Type: application/x-www-form-urlencoded",
"Authorization: bearer " . $access_token
];
$opts = [
CURLOPT_URL => $url,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_0,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_SSL_VERIFYPEER => 0,
];
if ($request_type == 'post') {
$opts[CURLOPT_POST] = 1;
$opts[CURLOPT_POSTFIELDS] = http_build_query($data);// this will build your data string from the array
}
curl_setopt_array($ch, $opts);
$result = curl_exec($ch);
curl_close($ch);
return $result;

Dropbox HTTP API - PHP cURL added header item boundary automatically

I'm new with the Dropbox API integrations, and I'm using the PHP cURL extension to make calls to the HTTP REST API, and when I try to make a request I receive the following string:
Error in call to API function "files/list_folder":
Bad HTTP "Content-Type" header:
"text/plain; boundary=----------------------------645eb1c4046b".
Expecting one of "application/json", "application/json; charset=utf-8",
"text/plain; charset=dropbox-cors-hack".
I'm sending this with code very similar to this:
$sUrl = "https://api.dropboxapi.com/2/files/list_folder";
$oCurl = curl_init($sUrl);
$aPostData = array('path' => '', 'recursive' => true, 'show_hidden' => true);
$sBearer = "MY_TOKEN";
$aRequestOptions = array(
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => array('Content-Type: text/plain',
'Authorization: Bearer ' . $sBearer),
CURLOPT_POSTFIELDS => $aPostData,
CURLOPT_RETURNTRANSFER => true);
curl_setopt_array($aRequestOptions);
$hExec = curl_exec($oCurl);
if ($hExec === false){
// Some error info in JSON format
} else {
var_dump($hExec);
}
As you have it, you're doing a multipart form upload, which isn't what the API expects.
There are a few things you need to do differently:
You should be sending up the parameters as JSON in the body.
You should set the Content-Type to application/json, accordingly.
There isn't a show_hidden parameter on /files/list_folder, but perhaps you meant to send include_deleted.
The curl_setopt_array method takes two parameters, the first of which should be the curl handle.
Here's an updated version of your code that works for me:
<?php
$sUrl = "https://api.dropboxapi.com/2/files/list_folder";
$oCurl = curl_init($sUrl);
$aPostData = array('path' => '', 'recursive' => true, 'include_deleted' => true);
$sBearer = "MY_TOKEN";
$aRequestOptions = array(
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => array('Content-Type: application/json',
'Authorization: Bearer ' . $sBearer),
CURLOPT_POSTFIELDS => json_encode($aPostData),
CURLOPT_RETURNTRANSFER => true);
curl_setopt_array($oCurl, $aRequestOptions);
$hExec = curl_exec($oCurl);
if ($hExec === false){
// Some error info in JSON format
} else {
var_dump($hExec);
}
?>

Send a data request with headers

I'm using Twitter API v1.1. I've created a valid authorization header (using 0auth).
Now I want to actually send a request to Twitter for the data I want but I'm fairly new to PHP and certainly haven't got a damn clue about cURL.
So far I've got:
$authHeader = 'Authorization: 0Auth ....... Expect:'
$baseURL = 'https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name='.$screenName.'&count='.$tweetCount;
Then I found the following code in twitterAPIexchange which I can't get working for me:
$options = array(
CURLOPT_HTTPHEADER => $authHeader,
CURLOPT_HEADER => false,
CURLOPT_URL => $baseURL,
CURLOPT_RETURNTRANSFER => true
);
$feed = curl_init();
curl_setopt_array($feed, $options);
$json = curl_exec($feed);
curl_close($feed);
Can anyone help me with the header formation to make this request?
You must pass the headers as an array, e.g.
curl_setopt($feed, CURLOPT_HTTPHEADER, array('HeaderName1: HeaderValue1', 'HeaderName2: HeaderValue2'));
Or, in your case,
$authHeader = array('Authorization: OAuth oauth_consumer_key...');
$baseURL = 'https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name='.$screenName.'&count='.$tweetCount;
$options = array(
CURLOPT_HTTPHEADER => $authHeader,
CURLOPT_HEADER => false,
CURLOPT_URL => $baseURL,
CURLOPT_RETURNTRANSFER => true
);
$feed = curl_init();
curl_setopt_array($feed, $options);
$json = curl_exec($feed);
curl_close($feed);

Categories