Please review my cURL test code and let me know if you see any reason why executing it does not update the inventory of my product Variant. There is only one Product that has it's Variant data, there are not separate Variants of the Product. So it should be pretty straight-forward, right?
cURL is installed and is working fine on my box, and the API key / token are also verified.
Here is my code
//Set up access
$apiKey = "[my api key]";
$pwd = "[my pwd]";
$baseUrl = $apiKey . $pwd ."#sensible-herbs.myshopify.com/admin/";
//Set up test data
$variantId = '3744859331';
$inventoryQty = '50';
//Set up JSON payload
$payload = array (
"variant" => array("id" => $variantId,
" nventory_quantity" => $inventoryQty
)
);
$payload = json_encode($payload, JSON_NUMERIC_CHECK);
echo 'JSON payload: ' .$payload ."<p>";
$putUrl = $baseUrl ."variants/" ."$variantId".".json";
echo 'url: ' .$putUrl ."<hr>";
$session = curl_init();
curl_setopt($session, CURLOPT_URL, $putUrl);
curl_setopt($session, CURLOPT_CONNECTTIMEOUT, 30); //seconds to allow for connection
curl_setopt($session, CURLOPT_TIMEOUT, 30); //seconds to allow for cURL commands
curl_setopt($session, CURLOPT_HEADER, true); //include header info in return value ?
curl_setopt($session, CURLOPT_RETURNTRANSFER, true); //return response as a string
curl_setopt($session, CURLOPT_PUT, 1);
curl_setopt($session, CURLOPT_POSTFIELDS, $payload);
curl_setopt($session, CURLOPT_HTTPHEADER, array('Accept: application/json', 'Content-Type: application/json'));
$data = curl_exec($session);
print_r(curl_getinfo($session));
curl_close($session);
echo $data; // session data
The response I am getting is:
Array ( [url] => https://[apikey+password]#sensible-herbs.myshopify.com/admin/variants/3744859331.json [content_type] => [http_code] => 0 [header_size] => 0 [request_size] => 0 [filetime] => -1 [ssl_verify_result] => 0 [redirect_count] => 0 [total_time] => 0.156 [namelookup_time] => 0.078 [connect_time] => 0.156 [pretransfer_time] => 0 [size_upload] => 0 [size_download] => 0 [speed_download] => 0 [speed_upload] => 0 [download_content_length] => -1 [upload_content_length] => -1 [starttransfer_time] => 0 [redirect_time] => 0 [certinfo] => Array ( ) [primary_ip] => 23.227.38.71 [primary_port] => 443 [local_ip] => 192.168.0.10 [local_port] => 50573 [redirect_url] => )
So it looks like it's connecting but either the payload is not getting PUT...or I just don't understand what the API / URL requirements are for this... or maybe there is some hidden or missing switch or permission I need to set up other than the APIKey generation... I wish I knew!
Thanks in advance and namaste!
Kailas
It looks like you have a spell mistake in your payload array, inventory_quantity not nventory_quantity
$payload = array (
"variant" => array(
"id" => $variantId,
"inventory_quantity" => $inventoryQty
)
);
Related
I am trying to set 2 variables to the curl headers and can't seem to see what's wrong. I am not receiving any errors in the php logs, but when I print out the curl info I can see that the headers are not being set. Any point in the right direction would be helpful. Thanks
The Example I'm using
PHP cURL custom headers
class GetAuctions
{
private $APIKeyID = "theIDhere";
private $APIKeyPass = "thePasswordHere";
private $BaseURL = "https://someurlHere";
public function __construct()
{
//get list of upcoming auctions
$get_data = $this->callAPI('GET', $this->BaseURL, false);
//turn the response into a json
$response = json_decode($get_data, true);
//display the response for testing
echo print_r($response);
$errors = $response['response']['errors'];
$data = $response['response']['data'][0];
echo print_r($data);
}
function callAPI($method, $url, $data){
$curl = curl_init();
switch ($method){
case "POST":
curl_setopt($curl, CURLOPT_POST, 1);
if ($data)
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
break;
case "PUT":
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PUT");
if ($data)
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
break;
default:
if ($data)
$url = sprintf("%s?%s", $url, http_build_query($data));
}
// OPTIONS:
curl_setopt($curl, CURLOPT_URL, $url);
$headers =array();
$headers['apiKeyID'] = $this->APIKeyID;
$headers['apiKeyPass'] = $this->APIKeyPass;
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
echo "<br/>";
echo print_r(curl_getinfo($curl));
echo "<br/>";
// EXECUTE:
$result = curl_exec($curl);
if(!$result){die("Connection Failure");}
curl_close($curl);
return $result;
}
}
I've also tried this:
curl_setopt($curl, CURLOPT_HTTPHEADER, array(
"apiKeyID: $this->APIKeyID",
"apiKeyPass: $this->APIKeyPass"
));
My response looks like this:
Array ( [url] => https://MyURLHere [content_type] => [http_code] => 0 [header_size] => 0 [request_size] => 0 [filetime] => -1 [ssl_verify_result] => 0 [redirect_count] => 0 [total_time] => 0 [namelookup_time] => 0 [connect_time] => 0 [pretransfer_time] => 0 [size_upload] => 0 [size_download] => 0 [speed_download] => 0 [speed_upload] => 0 [download_content_length] => -1 [upload_content_length] => -1 [starttransfer_time] => 0 [redirect_time] => 0 [redirect_url] => [primary_ip] => [certinfo] => Array ( ) [primary_port] => 0 [local_ip] => [local_port] => 0 ) 1
Connection Failure
It looks like your headers are incorrectly formatted:
"apiKeyID : $this->APIKeyID",
You should remove space before your colon:
"apiKeyID: ${this->APIKeyID}",
BTW: for debugging purpose you may also use CURLOPT_VERBOSE to see what's is being send by cURL. If you cannot peek stderr at runtime, redirect it to the file:
curl_setopt($c, CURLOPT_STDERR, fopen('curl-log.txt', 'w+'));
I have a cURL command using which I get authenticated to a website and it gives a cookie in response, then subsequently using this cookie I can make REST API calls to this service
Here is the working cURL command:
curl -v -l -H "Content-Type: application/x-www-form-urlencoded" -H "Referrer:https://mywebsiteurl.com?ticket=unique_ticket_id" -d "_charset_=UTF-8&errorMessage=User+name+and+password+do+not+match&resource=%2F&username=username%40domain.com&password=XXXXXX&nextpage=welcomeCM.jsp&viewInfo=&ticket=unique_ticket_id" -X POST https://mywebsiteurl.com/index.jsp
In the above command ticket parameter contains a unique ticket id that is passed along with the website url
Now, I'm trying to accomplish the same using cURL PHP, here is the PHP code:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://mywebsiteurl.com/index.jsp");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "_charset_=UTF-8&errorMessage=User+name+and+password+do+not+match&resource=%2F&username=username%40domain.com&password=XXXXXX&nextpage=welcomeCM.jsp&viewInfo=&ticket=unique_ticket_id");
curl_setopt($ch, CURLOPT_POST, 1);
$headers = array(
'Content-Type: application/x-www-form-urlencoded',
'Referrer: https://mywebsiteurl.com?ticket=unique_ticket_id'
);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$result = curl_exec($ch);
if (curl_errno($ch)) {
echo 'Error:' . curl_error($ch);
}
echo $result;
curl_close ($ch);
Here echo $result shows nothing
I then tried var_dump($result); and it gives this output: string(0) "" which means nothing is getting returned in $response
After this I tried curl_getinfo and added the following code:
echo "<pre>";
$info = curl_getinfo($ch);
print_r($info);
echo "</pre>";
And this gave me the following array:
Array
(
[url] => https://mywebsiteurl.com/index.jsp
[content_type] => text/html;charset=UTF-8
[http_code] => 302
[header_size] => 1306
[request_size] => 619
[filetime] => -1
[ssl_verify_result] => 0
[redirect_count] => 0
[total_time] => 1.540687
[namelookup_time] => 0.028262
[connect_time] => 0.171774
[pretransfer_time] => 0.462507
[size_upload] => 280
[size_download] => 0
[speed_download] => 0
[speed_upload] => 181
[download_content_length] => 0
[upload_content_length] => 280
[starttransfer_time] => 1.54066
[redirect_time] => 0
[redirect_url] => https://mywebsiteurl.com/welcomeCM.jsp?username=username#domain.com&locale=en_US
[primary_ip] => YY.YYY.YYY.YY
[certinfo] => Array
(
)
[primary_port] => 443
[local_ip] => XX.XX.XXX.XX
[local_port] => 47692
)
Now my goal is to get the cookie in $result, but it is empty & nothing is getting returned into it
Is it that something is missing in the cURL command equivalent PHP code?
Can someone please help me out & point me in the direction to retrieve the cookie
Thanks a lot!
UPDATE
I added curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); to the request to have it follow the 302 redirect after successful login
But this time after the execution of cURL, echo $result is redirecting my current local webpage to /Dashboard?viewInfo= which obviously does not exist
Also this time var_dump($result); is resulting in: string(1462) " "
And curl_getinfo($ch) this time is giving the following array:
Array
(
[url] => https://mywebsiteurl.com/welcomeCM.jsp?username=username#domain.com&locale=en_US
[content_type] => text/html;charset=UTF-8
[http_code] => 200
[header_size] => 1821
[request_size] => 956
[filetime] => -1
[ssl_verify_result] => 0
[redirect_count] => 1
[total_time] => 1.746911
[namelookup_time] => 1.5E-5
[connect_time] => 1.5E-5
[pretransfer_time] => 6.2E-5
[size_upload] => 0
[size_download] => 1462
[speed_download] => 836
[speed_upload] => 0
[download_content_length] => 1462
[upload_content_length] => 0
[starttransfer_time] => 0.146587
[redirect_time] => 1.6003
[redirect_url] =>
[primary_ip] => YY.YYY.YYY.YY
[certinfo] => Array
(
)
[primary_port] => 443
[local_ip] => YY.YY.YYY.YY
[local_port] => 47705
)
Still can't get the required cookie here,
Please help!
If you want to use curls given functionality you can try using CURLOPT_COOKIEJAR / CURLOPT_COOKIEFILE, to store and get your cookie. This if file based.
In this case, curl will then write any Cookie related Information in a file.
You can define where this file will be located.
By using CURLOPT_COOKIEJAR , you will tell curl that it shall capture the cookie data.
// create cookie file
$cookie = __DIR__ . "/where/you/want/to/store/your/cookie/mycookie.txt";
fopen($cookie, "w");
// you may want to use some random identicator in your cookie file
// to make sure it does not get overwritten by some action
// prepare login
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://mywebsiteurl.com/index.jsp");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// tell curl to follow redirects
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURlOPT_POSTFIELDS, "username=usernam&password=XXXXXX");
curl_setopt($ch, CURLOPT_POST, 1);
// set a jar, to store your cookie
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie);
$headers = array(
'Content-Type: application/x-www-form-urlencoded',
'Referrer: https://mywebsiteurl.com?ticket=unique_ticket_id'
);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
// do login
$loginResult = curl_exec($ch);
// check if your login has worked according to the given result by any method you want
if (preg_match("/Welcome/", $loginResult)) {
// simple regex for demonstration purpose
}
// now you could load your cookie out of the file, or just use the file for future requests
If your login has worked, you will have all information stored in your cookie file.
Now you can use that cookie again with the curlopt CURLOPT_COOKIEFILE for future requests.
// do other request, with your cookie
curl_setopt($ch, CURLOPT_URL, "https://mywebsiteurl.com/api/rest.php");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "your new post data");
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
// set a jar to update your cookie if needed
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie);
// give curl the location of your cookie file, so it can send it
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie);
I'm trying to setup the following code to accept curl requests from php with nodejs via https protocol. I know the code works with http in nodejs side but as soon as I switch the protocol to https, "RECEIVED" is not logged in nodejs. This is:
app.post('/posts', function(req, res){
console.log("RECEIVED");
});
Suming up:
"received" is logged with nodejs in http mode
"received" is NOT logged with nodejs in https mode
$curl_url (in HTTP) 'http://127.0.0.1:'.$socket_port.'/posts';
$curl_url (in HTTPS) 'https://127.0.0.1:'.$socket_port.'/posts';
Does anybody have any idea on this? Here is my curl function:
$ch = curl_init();
$ch_options = array("Expect:");
if($encode_json){
array_push($ch_options,"Content-type: application/json");
$data = json_encode($data);
}else{
$data = http_build_query($data);
}
//$data isn't received in either format mode
curl_setopt($ch, CURLOPT_HTTPHEADER, $ch_options);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 2);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_exec($ch);
$feedback = curl_getinfo($ch);
curl_close($ch);
EDIT: the code that decides it all (called after app.post, which works with http. With https only this functionality [app.post('/post'...] fails AFAIK)
if(protocol == "https"){
preparedApp = require(protocol).createServer(sslOptions,app);
}else if(protocol == "http")
preparedApp = require(protocol).Server(app);
preparedApp.listen(socket_port, function(){
//literally nothing here
});
$feedbackdump:
print_r:
Array
(
[url] => https://127.0.0.1:socket_port/posts
[content_type] =>
[http_code] => 0
[header_size] => 0
[request_size] => 0
[filetime] => -1
[ssl_verify_result] => 1
[redirect_count] => 0
[total_time] => 0.005724
[namelookup_time] => 1.1E-5
[connect_time] => 5.5E-5 //IT IS connecting / knows presence, but doens't route /posts...
[pretransfer_time] => 0
[size_upload] => 0
[size_download] => 0
[speed_download] => 0
[speed_upload] => 0
[download_content_length] => -1
[upload_content_length] => -1
[starttransfer_time] => 0
[redirect_time] => 0
[redirect_url] =>
[primary_ip] => 127.0.0.1
[certinfo] => Array
(
)
[primary_port] => socket_port
[local_ip] => 127.0.0.1
[local_port] => 54576
)
After doing some research I noticed curl_exec($ch) was returning false. After programming a throw such as
try{ $test = curl_exec($ch)
if ($test)
throw new Exception(curl_error($ch), curl_errno($ch));
} catch(Exception $e) {
trigger_error(sprintf(
'Curl failed with error #%d: %s',
$e->getCode(), $e->getMessage()),
E_USER_ERROR);
}
I got the error Curl failed with error #51: SSL: certificate subject name 'mydomain.com' does not match target host name '127.0.0.1'
TL;DR: So I just added
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
to the ch options and it is now working
I am using Curl in PHP to call an API.
According to their documentation, they are returning "Authentication-Callback" within the returned page's header.
It works perfectly when I paste the URL into the browser, but Curl seems to leave it out.
Here is my code
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://api.themoviedb.org/3/authentication/token/new?api_key=[MY_API_KEY]&language=en');
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FAILONERROR, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$results = curl_exec($ch);
$headers = curl_getinfo($ch);
Here is the returned header
Array
(
[url] => http://api.themoviedb.org/3/authentication/token/new?api_key=[MY_API_KEY]&language=en&
[content_type] => application/json;charset=utf-8
[http_code] => 200
[header_size] => 470
[request_size] => 137
[filetime] => -1
[ssl_verify_result] => 0
[redirect_count] => 0
[total_time] => 0.109
[namelookup_time] => 0
[connect_time] => 0.047
[pretransfer_time] => 0.047
[size_upload] => 0
[size_download] => 116
[speed_download] => 1064
[speed_upload] => 0
[download_content_length] => 116
[upload_content_length] => 0
[starttransfer_time] => 0.109
[redirect_time] => 0
[certinfo] => Array
(
)
)
As far as I can tell, everything is right. Curl returns the data that I need perfectly, just not the correct headers.
Any help is appreciated!
What you're doing right now is getting stored information about the header via curl_getinfo() which only gets the information in the OPT list on that page.
What you should do instead is to return the header and then manually separate it:
curl_setopt($ch, CURLOPT_HEADER, 1);
// The rest of your options
$output = curl_exec($ch);
// Since the end of the header is always delimited by two newlines
$output = explode("\n\n", $output, 2);
$header = $output[0];
$content = $output[1];
This is more work but will get you the real headers.
This is my code to do what phsource has suggested the headers are put into the $headers array
# Extract headers from response
preg_match_all('%HTTP/\\d\\.\\d.*?(\\r\\n|\\n){2,}%si', $curl_result, $header_matches);
$headers = preg_split('/\\r\\n/', str_replace("\r\n\r\n",'',array_pop($header_matches[0])));
# Convert headers into an associative array
if(is_array($headers))
{
foreach ($headers as $header)
{
preg_match('#(.*?)\:\s(.*)#', $header, $header_matches);
if(isset($header_matches[1]))
{
$headers[$header_matches[1]] = $header_matches[2];
$headers['lowercase'][strtolower($header_matches[1])] = $header_matches[2];
}
}
}
# Remove the headers from the response body
$curl_result = preg_replace('%HTTP/\\d\\.\\d.*?(\\r\\n|\\n){2,}%si','',$curl_result);
you may want to replace \r\n with PHP_EOL as you see fit
With every Twitter request I make, the returned HTTP headers should include X-RateLimit-Limit.
However, I seem unable to retrieve these using PHP. Can someone tell me what bone-headed mistake I've made?
I've set my curl up in the normal way and am able to successfully GET and POST requests.
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:'));
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_HEADER, FALSE);
curl_setopt($ch, CURLINFO_HEADER_OUT, TRUE);
curl_setopt($ch, CURLOPT_VERBOSE, TRUE);
$response = curl_exec($ch);
$response_info=curl_getinfo($ch);
$erno = curl_errno($ch);
$er = curl_error($ch);
curl_close($ch);
I'm able to get some response information, like http_code
$response_info['http_code']
But this line just returns null
//Doesn't bloody work. No idea why!
$rate_limit = $response_info['X-RateLimit-Limit'];
I'm running PHP Version 5.3.10.
EDIT
This is the result of print_r($response_info);
Array
(
[url] => https://api.twitter.com/1/statuses/home_timeline.json...
[content_type] => application/json;charset=utf-8
[http_code] => 200
[header_size] => 695
[request_size] => 410
[filetime] => -1
[ssl_verify_result] => 0
[redirect_count] => 0
[total_time] => 1.239977
[namelookup_time] => 0.007361
[connect_time] => 0.155783
[pretransfer_time] => 0.465397
[size_upload] => 0
[size_download] => 99425
[speed_download] => 80182
[speed_upload] => 0
[download_content_length] => 99425
[upload_content_length] => 0
[starttransfer_time] => 0.794829
[redirect_time] => 0
[certinfo] => Array()
[redirect_url] =>
[request_header] => GET /1/statuses/home_timeline.json... HTTP/1.1
Host: api.twitter.com
Accept: */*
)
curl_getinfo does not return the response headers, only other meta info about the request. To retrieve headers, set CURLOPT_HEADER to true. That will include the headers in the output. To separate them from the response body do:
list($headers, $body) = explode("\n\n", $response, 2);
To parse the headers, explode again:
$headers = explode("\n", $headers);
foreach ($headers as $header) {
list($key, $value) = explode(':', $header, 2);
$headers[trim($key)] = trim($value);
}
echo $headers['X-RateLimit-Limit'];