I want to send a request to a web service via an API as shown below, i have to pass
a custom http header(Hash), i'm using CURL, my code seems to work but I'm not getting
the rigth response, I'm told it has to do with the hash value, though the value has
been seen to be correct, is there anything wrong with the way I'm passing it or with
the code itself.
<?php
$ttime=time();
$hash="123"."$ttime"."dfryhmn";
$hash=hash("sha512","$hash");
$curl = curl_init();
curl_setopt($curl,CURLOPT_HTTPHEADER,array('Hash:$hash'));
curl_setopt ($curl, CURLOPT_URL, 'http://web-service-api.com/getresult.xml?clientid=456&time=$ttime');
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$xml = curl_exec ($curl);
if ($xml === false) {
die('Error fetching data: ' . curl_error($curl));
}
curl_close ($xml);
echo htmlspecialchars("$xml", ENT_QUOTES);
?>
If you need to get and set custom http headers in php, the following short tutorial is really useful:
Sending The Request Header
$uri = 'http://localhost/http.php';
$ch = curl_init($uri);
curl_setopt_array($ch, array(
CURLOPT_HTTPHEADER => array('X-User: admin', 'X-Authorization: 123456'),
CURLOPT_RETURNTRANSFER =>true,
CURLOPT_VERBOSE => 1
));
$out = curl_exec($ch);
curl_close($ch);
// echo response output
echo $out;
Reading the custom header
print_r(apache_request_headers());
you should see
Array
(
[Host] => localhost
[Accept] => */*
[X-User] => admin
[X-Authorization] => 123456
[Content-Length] => 9
[Content-Type] => application/x-www-form-urlencoded
)
Custom Headers with PHP CGI
in .htaccess
RewriteEngine On
RewriteRule .? - [E=User:%{HTTP:X-User}, E=Authorization:%{HTTP:X-Authorization}]
Reading the custom headers from $_SERVER
echo $_SERVER['User'];
echo $_SERVER['Authorization'];
Resources
http://www.omaroid.com/php-get-and-set-custom-http-headers/
How can I get PHP to display the headers it received from a browser?
'Hash:$hash' should be either "Hash: $hash" (double quotes) or 'Hash: '.$hash
The same goes for your URL passed in CURLOPT_URL
Related
I am trying to make a simple GET request to the yesmail api, i have the url which i can paste directly in the browser and it displays the correct information, and also if i add the following code as shown in the brief documentation in the Firefox RESTClient i get the correct response:
GET https://services.yesmail.com/enterprise/subscribers?email=karina#email.co.uk HTTP/1.1
Accept-Encoding: gzip,deflate
User-Agent: Jakarta Commons-HttpClient/3.1
Authorization: Basic xxxxxxxxxxxxx
Host: services.yesmail.com
However, when trying to connect using CURL, i am getting nothing, no HTTP response at all and just a blank page. I am not sure what i am doing wrong? This is what i have:
$url = "https://services.yesmail.com/enterprise/subscribers?email=karina#email.co.uk";
$header[] = "Accept-Encoding: gzip, deflate";
$header[] = "User Agent: Jakarta Commons-HttpClient/3.1";
$header[] = "Authorization: Basic xxxxxxxxxxxxx";
$header[] = "Host: services.yesmail.com";
$ch = curl_init();
curl_setopt($ch, CURLOPT_HTTPHEADER, $header );
curl_setopt($ch, CURLOPT_USERPWD, 'xxxxx:xxxxxxxxxx');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_URL, $url );
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true );
$response = (curl_exec($ch));
print_r($response);
curl_close($ch);
Am i wrong in thinking that the information i put in to the RESTClient goes into the headers in CURL? This is the first time i have been working with API's so any help appreciated.
update
When using the function file_get_contents i get the correct response(which for the GET method is just a URL with my unique subscriber number):
$context = stream_context_create(array(
'http' => array(
'header' => "Authorization: Basic " . base64_encode("*******:********")
)
));
$data = file_get_contents('https://services.yesmail.com/enterprise/subscribers?email=karina#email.co.uk', false, $context);
echo $data;
However i really want to get the CURL method working as i will want to be able to add a subscriber.
I actually work at Yesmail so I may be able to help you out here.
Give the following code a try (be sure to replace the your-auth-here text with your base64 encoded authentication info and to set the appropriate URL in $ym_api_url)
<?php
// Set the HTTP headers needed for this API call.
$http_headers = array(
"Authorization: Basic your-auth-here",
"Accept: application/json",
"Connection: close", // Disable Keep-Alive
"Expect:" // Disable "100 Continue" server response
);
// URL Endpoint of the API to be called.
$ym_api_url = 'https://services.yesmail.com/enterprise/subscribers?email=karina#email.co.uk';
$curl_hdl = curl_init();
$curl_options = array(
CURLOPT_VERBOSE => 1, // Verbose mode for diagnostics
CURLOPT_HEADER => TRUE, // Include the header in the output.
CURLOPT_HTTPHEADER => $http_headers, // HTTP headers to set
CURLOPT_HTTPAUTH => CURLAUTH_BASIC, // Use basic authentication.
CURLOPT_PROTOCOLS => CURLPROTO_HTTPS, // Bitmask of protocols libcurl may use in this transfer
CURLOPT_RETURNTRANSFER => TRUE, // Return result as return value of curl_exec()
CURLOPT_URL => $ym_api_url, // URL to POST data to
);
curl_setopt_array($curl_hdl, $curl_options);
// Make the API call
$response = curl_exec($curl_hdl);
// Get the http response code
$http_response_code = curl_getinfo($curl_hdl, CURLINFO_HTTP_CODE);
curl_close($curl_hdl);
echo PHP_EOL . "INFO: HTTP Response Code was: " . $http_response_code . PHP_EOL;
if ( $response === false )
{
echo PHP_EOL . "ERROR: curl_exec() has failed." . PHP_EOL;
}
else
{
echo PHP_EOL . "INFO: Response Follows..." . PHP_EOL;
echo PHP_EOL . $response;
}
?>
The CURLOPT_VERBOSE => 1 option will output additional diagnostic info. Note any issues there to see if that points to a specific problem. Once you have the issue(s) worked out you can remove or disable those options.
Also, remember you can always contact your Yesmail Account Manager and request assistance.
So you get the $response, but don't do anything with it.
There is no line in your code which is expected to display anything.
Update: I see you updated your question.
A very important rule: always check the return value of API calls.
curl_exec() signals an error by returning FALSE, if that's the case, check it with curl_error($ch).
Im making this API adapter to POST data our OMS (Order Management System). And I keep getting this error. I dunno if it's really an error because the adapter is connected. the POSTing is the problem. I'm using JSON and cURL to pass data to be updated. So here's my code:
$data = array(
'package' => array(
'tracking_number' => '735897086',
'package_status' => 'failed',
'failed_reason' => 'other1',
'update_at' => '2013-11-22 09:58:39'
)
);
and this is how I POST it.
$postdata = "apikey=$apikey&method=$method&data=$check";
$ch = curl_init();
//SSL verification fixed with this two codes
curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt_array(
$ch,
array(
CURLOPT_URL => $url.'/webservice/',
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_VERBOSE => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => $postdata,
CURLOPT_HTTPHEADER => array('Content-type: application/x-www-form-urlencoded')
)
);
$result = curl_exec($ch);
and this is my code to test the connection and check if the POSTing is success.
if(curl_exec($ch) === false) { echo 'Curl error: ' . curl_error($ch); } else { echo 'Operation completed without any errors'; }
$result = curl_exec($ch);
echo $result;
curl_close($ch);
I don't really know why I keep getting the "INCORRECT PARAMETERS SENT TO SERVICE". I already reviewed the documentation, the parameters are right. :(
I do believe it is because your POST variables are an array within an array so, what you end up trying to do with your current approach is invalid as stated.
Prior to setting $data in CURL try running the following:
$data = http_build_query($data);
See the PHP definition of http_build_query for more details
I forgot to add this. I encode it to JSON that's why I use arrays.
$check=json_encode($data);
echo $check;
$postdata = "method=$method&data=$check&apikey=$apikey";
$ch = curl_init();
I echo it first before getting the response to check if it's encoded in JSON. then I got this error:
{"package":{"order_number":"200118788","package_number":"200118788-4274","tracking_number":"735897086","package_status":"failed","failed_reason":"other1","update_at":"2013-08-06 17:02:14"}}Operation completed without any errors{"OmsSuccessResponse":false,"message":"Incorrect parameters sent to service","package_status":null}
A http connection requires a HTTP POST request with a custom header object Authentication-API-Key
With CURL it's automatically converted to [HTTP_AUTHENTICATION_API_KEY] => 12345
Cannot figure out why
A simplle extract from a php class for testing is
Please help me out, how to get a $_SERVER result with [Authentication-API-Key] => 123456
<?php
$contentType = 'text/xml';
$method = 'POST';
$auth = '';
$header1 = 'Authentication-API-Key: 12345';
$charset= 'ISO-8859-1';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://localhost/test/returnurl.php");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, Array('Content-type: ' .
$contentType . '; charset=' . $charset,
$header1));
curl_exec($ch);
?>
<?php
//http://localhost/test/returnurl.php
Print_r($_SERVER,true)
?>
output:
Array
(
[HTTP_HOST] => localhost
[HTTP_ACCEPT] => */*
[CONTENT_TYPE] => text/xml; charset=ISO-8859-1
[HTTP_AUTHENTICATION_API_KEY] => 12345
...
)
If I run your code, I get the message that $header2 is undefined, so I think you need to fix that.
If I remove $header2, this is the output:
GET /test/returnurl.php HTTP/1.1
Host: localhost
Accept: */*
Content-type: text/xml; charset=ISO-8859-1
Authentication-API-Key: 12345
So that seems to be okay. What is your output? Note that currently the request is send using GET, not POST.
EDIT: I created the script /test/returnurl.php that simply dumps the $_SERVER array, now I see what you mean. The fact that it ends up like that on the receiving end does not mean that you haven't set the header correctly, so the service that you're using should be receiving it as intended.
That's how _SERVER works; it does not give you the HTTP header keys verbatim.
It is not CURL doing this. Examine the actual HTTP request and you'll see that your header is fine.
Another example is $_SERVER['CONTENT_TYPE'], which gives you the value of the Content-Type HTTP header.
There is no problem here.
A script I am using passes an array like array("Content-type: image/png").
Perhaps by putting it in an array you prevent it from breaking into an array at the :
I am new to cURL so I haven't even been able to test this theory yet..
I am trying to debug an http post the I am trying to send from list application. I have been able to send the correct post from php CURL which corectly interfaces with my drupal 7 website and uploads an image.
In order to get this to work in my lisp application I really need to see the content body of my http post I have been able to see the headers using a call like this:
curl_setopt($curl, CURLOPT_STDERR, $fp);
curl_setopt($curl, CURLOPT_VERBOSE, 1);
and the headers look the same in my lisp application but I have been unable to examine the body of the post. I have searched online and other people have asked this question but no one posted a response.
The content type of my http post is:
application/x-www-form-urlencoded
I have also tried many http proxy debuging tools but they only ever the http GET to get my php page but never capture the get sent from server once the php code is executed.
EDIT: I have added a code snipet showing where I actually upload the image file.
// file
$file = array(
'filesize' => filesize($filename),
'filename' => basename($filename),
'file' => base64_encode(file_get_contents($filename)),
'uid' => $logged_user->user->uid,
);
$file = http_build_query($file);
// REST Server URL for file upload
$request_url = $services_url . '/file';
// cURL
$curl = curl_init($request_url);
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-type: application/x-www-form-urlencoded'));
curl_setopt($curl, CURLOPT_STDERR, $fp);
curl_setopt($curl, CURLOPT_VERBOSE, 1);
curl_setopt($curl, CURLOPT_POST, 1); // Do a regular HTTP POST
curl_setopt($curl, CURLOPT_POSTFIELDS, $file); // Set POST data
curl_setopt($curl, CURLOPT_HEADER, FALSE); // Ask to not return Header
curl_setopt($curl, CURLOPT_COOKIE, "$cookie_session"); // use the previously saved session
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($curl, CURLOPT_FAILONERROR, TRUE);
curl_setopt_array($curl, array(CURLINFO_HEADER_OUT => true) );
$response = curl_exec($curl);
CURLOPT_VERBOSE should actually show the details. If you're looking for the response body content, you can also use CURLOPT_RETURNTRANSFER, curl_exec() will then return the response body.
If you need to inspect the request body, CURLOPT_VERBOSE should give that to you but I'm not totally sure.
In any case, a good network sniffer should give you all the details transparently.
Example:
$curlOptions = array(
CURLOPT_RETURNTRANSFER => TRUE,
CURLOPT_FOLLOWLOCATION => TRUE,
CURLOPT_VERBOSE => TRUE,
CURLOPT_STDERR => $verbose = fopen('php://temp', 'rw+'),
CURLOPT_FILETIME => TRUE,
);
$url = "http://stackoverflow.com/questions/tagged/java";
$handle = curl_init($url);
curl_setopt_array($handle, $curlOptions);
$content = curl_exec($handle);
echo "Verbose information:\n", !rewind($verbose), stream_get_contents($verbose), "\n";
curl_close($handle);
echo $content;
Output:
Verbose information:
* About to connect() to stackoverflow.com port 80 (#0)
* Trying 64.34.119.12...
* connected
* Connected to stackoverflow.com (64.34.119.12) port 80 (#0)
> GET /questions/tagged/java HTTP/1.1
Host: stackoverflow.com
Accept: */*
< HTTP/1.1 200 OK
< Cache-Control: private
< Content-Type: text/html; charset=utf-8
< Date: Wed, 14 Mar 2012 19:27:53 GMT
< Content-Length: 59110
<
* Connection #0 to host stackoverflow.com left intact
<!DOCTYPE html>
<html>
<head>
<title>Newest 'java' Questions - Stack Overflow</title>
<link rel="shortcut icon" href="http://cdn.sstatic.net/stackoverflow/img/favicon.ico">
<link rel="apple-touch-icon" href="http://cdn.sstatic.net/stackoverflow/img/apple-touch-icon.png">
<link rel="search" type="application/opensearchdescription+xml" title="Stack Overflow" href="/opensearch.xml">
...
Just send it to a random local port and listen on it.
# terminal 1
nc -l localhost 12345
# terminal 2
php -e
<?php
$curl = curl_init('http://localhost:12345');
// etc
If you're talking about viewing the response, if you add curl_setopt( $curl, CURLOPT_RETURNTRANSFER, true );, then the document returned by the request should be returned from your call to curl_exec.
If you're talking about viewing the postdata you are sending, well, you should be able to view that anyway since you're setting that in your PHP.
EDIT: Posting a file, eh? What is the content of $file? I'm guessing probably a call to file_get_contents()?
Try something like this:
$postdata = array( 'upload' => '#/path/to/upload/file.ext' );
curl_setopt( $curl, CURLOPT_POSTFIELDS, $postdata );
You can't just send the file, you still need a postdata array that assigns a key to that file (so you can access in PHP as $_FILES['upload']). Also, the # tells cURL to load the contents of the specified file and send that instead of the string.
You were close:
The PHP manual instructs that you must call the constant CURLINFO_HEADER_OUT in both curl_setopt and curl_getinfo.
$ch = curl_init($url);
... other curl options ...
curl_setopt($ch,CURLINFO_HEADER_OUT,true);
curl_exec(ch);
//Call curl_getinfo(*args) after curl_exec(*args) otherwise the output will be NULL.
$header_info = curl_getinfo($ch,CURLINFO_HEADER_OUT); //Where $header_info contains the HTTP Request information
Synopsis
Set curl_setopt
Set curl_getinfo
Call curl_getinfo after curl_exec
I think you're better off doing this with a proxy than in the PHP. I don't think it's possible to pull the raw POST data from the PHP CURL library.
A proxy should show you the request and response contents
To get the header the CURLINFO_HEADER_OUT flag needs to be set before curl_exec is called.
Then use curl_getinfo with the same flag to get the header after curl_exec.
If you want to see the post data, grab the value you set at CURLOPT_POSTFIELDS
For example:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://example.com/webservice");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($payload));
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
curl_exec($ch);
$header = curl_getinfo($ch, CURLINFO_HEADER_OUT);
curl_close($ch);
echo "Request-Header:\r\n" . $header . "\r\n";
echo "Request-Body(URL Encoded):\r\n" . http_build_query($payload) . "\r\n";
echo "Request-Body(Json Encoded):\r\n" . json_encode($payload) . "\r\n";
I have done some research regarding on how to use file_get_content with post. And I have also read this one which is I honestly don't understand since I am not that familiar with PHP. Below is my php code in getting my json and used it for my ajax request, using methog GET.:
<?php
echo(file_get_contents("http://localhost:8001/" . $_GET["path"] . "?json=" . urlencode($_GET["json"])));
?>
Now, I am using method POST and I dont know how to modify my php code to post my data from my javascript. Below is my data which I wanted to post in my url request (that is also what I used as json in method GET):
{"SessionID":"9SQLF17XcFu0MTdj5n",
"operation":"add",
"transaction_date":"2011-7-28T00:00:00",
"supplier_id":"10000000108",
"wood_specie_id":"1",
"lines": [{"...":"...","..":"..."},{"...":"...","..":"..."}],
"scaled_by":"SCALED BY",
"tallied_by":"TALLIED BY",
"checked_by":"CHECKED BY",
"total_bdft":"23.33",
"final":"N"}
I just need to change this code
echo(file_get_contents("http://localhost:8001/" . $_GET["path"] . "?json=" . urlencode($_GET["json"])));
with POST to send my post my data.
EDIT:
I need to produce a request like this:
http://localhost/jQueryStudy/RamagalHTML/processjson.php?path=getData/supplier?json={"SessionID":"KozebJ4SFqdqsJtRpG6t1o3uQxgoeLjT"%2C"dataType":"data"}
You can pass a Stream Context as the third argument to file_get_contents. With the Stream Context, you can influence how the HTTP request will be made, e.g. you can change the Method, add Content or arbirtrary headers.
file_get_contents($url, false, stream_context_create(
array (
'http' => array(
'method'=>'POST',
'header' => "Connection: close\r\nContent-Length: $data_len\r\n",
'content'=>$data_url
)
)
));
After each request, PHP will automatically populate the $http_response_header which will contain all the information about the request, e.g. Status Code and stuff.
$data_url = http_build_query (array('json' => $_GET["json"]));
$data_len = strlen ($data_url);
echo file_get_contents("http://localhost:8001/" . $_GET["path"], false, stream_context_create(
array (
'http' => array(
'method'=>'POST',
'header' => "Connection: close\r\nContent-Length: $data_len\r\n",
'content'=>$data_url
)
)
));
What you need is cURL.
Example:
$dataString = "firstName=John&lastname=Smith";
$ch = curl_init();
//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,2); // number of variables
curl_setopt($ch,CURLOPT_POSTFIELDS,$dataString);
//execute post
$result = curl_exec($ch);
//close connection
curl_close($ch);
If i understand you correctly(I might not) you should use CURL.
CURL is the way to submit POST requests within PHP. (but it is not the only way)
What you are doing is sending the data by the GET method
some think like this, please read about it, this one will not work out of the box
<?php
$ch = curl_init("http://localhost:8001/" . $_GET["path"] );
curl_setopt ($ch, CURLOPT_POST, 1);
curl_setopt ($ch, CURLOPT_POSTFIELDS, "json=".urlencode($_GET["json"]));
curl_exec ($ch);
curl_close ($ch);
?>