Posting xml via http using php and curl - php

I have been following some other examples I found on here including this one: Send an XML post request to a web server with CURL and also some external examples such as http://www.phpmind.com/blog/2009/08/how-to-post-xml-using-curl/
For some reason my code is not working. I am repeatedly getting a response of 0 after a lengthy period of time when I try visiting the php file on the actual server.
The exact same XML returns a response of 200 OK when I test posting it to the same request URL in the Chrome Advance REST Client, so clearly the URL is working.
Can anyone please tell me what is wrong with my PHP code?
<?php
$xml_data ='<cXML version="1.2.005" xml:lang="en-US" payloadID="removedforprivacy" timestamp="2017-05-15T13:00:00.000">'
.'<Header>'
.'<From>'
.'<Credential domain="DUNS">'
.'<Identity>removedforprivacy</Identity>'
.'</Credential>'
.'<Credential domain="CompanyName">'
.'<Identity>removedforprivacy</Identity>'
.'</Credential>'
.'</From>'
.'<To>'
.'<Credential domain="CompanyName">'
.'<Identity>removedforprivacy</Identity>'
.'</Credential>'
.'</To>'
.'<Sender>'
.'<Credential domain="DUNS">'
.'<Identity>removedforprivacy</Identity>'
.'<SharedSecret>removedforprivacy</SharedSecret>'
.'</Credential>'
.'</Sender>'
.'</Header>'
.'<Request deploymentMode="production">'
.'<OrderRequest>'
.'<OrderRequestHeader orderID="999" orderDate="2017-05-08 02:41:17" type="new">'
.'<BillTo>'
.'<Address>'
.'<Name xml:lang="en-US">Nicole Testing</Name>'
.'<PostalAddress name="Nicole Testing">'
.'<DeliverTo>Nicole Testing</DeliverTo>'
.'<Street>1 Test St.</Street>'
.'<Street></Street>'
.'<City>Melbourne</City>'
.'<State>VIC</State>'
.'<PostalCode>3000</PostalCode>'
.'<Country isoCountryCode="AU">AU</Country>'
.'</PostalAddress>'
.'</Address>'
.'</BillTo>'
.'<Comments xml:lang="en-US"></Comments>'
.'</OrderRequestHeader>'
.'<ItemOut lineNumber="1" quantity="1" requestedDeliveryDate="2017-05-20T13:49:32">'
.'<ItemID>'
.'<SupplierPartID>51239929_GC</SupplierPartID>'
.'<SupplierPartAuxiliaryID>Joe Simth</SupplierPartAuxiliaryID>'
.'</ItemID>'
.'<ItemDetail>'
.'<UnitPrice>'
.'<Money currency="AUD">1.32</Money>'
.'</UnitPrice>'
.'<Description xml:lang="en-US">Relaxed Tiger</Description>'
.'<UnitOfMeasure>Landscape Size: 24” x 16”</UnitOfMeasure>'
.'<URL>http://image.url.removed.for.privacy</URL>'
.'<Extrinsic name="quantityMultiplier">1</Extrinsic>'
.'</ItemDetail>'
.'<ShipTo>'
.'<Address addressID="0001">'
.'<Name xml:lang="en-US">Your Name</Name>'
.'<PostalAddress name="">'
.'<DeliverTo>Nicole Testing</DeliverTo>'
.'<Street>1 Test St.</Street>'
.'<Street></Street>'
.'<City>Melbourne</City>'
.'<State>VIC</State>'
.'<PostalCode>3000</PostalCode>'
.'<Country isoCountryCode="AU">AU</Country>'
.'</PostalAddress>'
.'</Address>'
.'</ShipTo>'
.'</ItemOut>'
.'</OrderRequest>'
.'</Request>'
.'</cXML>';
$url = 'http://removed.for.privacy';
$ch = curl_init();
curl_setopt( $ch, CURLOPT_URL, $url );
curl_setopt( $ch, CURLOPT_POST, true );
curl_setopt( $ch, CURLOPT_HTTPHEADER, array('Content-Type: text/xml')); // also tried this with application/xml and same response.
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch, CURLOPT_POSTFIELDS, $xml_data );
$response = curl_exec($ch);
print_r($response);
echo "HTTP response code: ".(int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
?>

It would appear that there is nothing wrong with my code and rather port :8080 was blocked by a firewall. The request URL was using port :8080 so it was returning a status of 0.

I'm not familiar with transferring XML, but it's desirable to use heredocs, in your case it will be:
$xml_data = <<<EOD
<cXML version="1.2.005" xml:lang="en-US" payloadID....
//xml body here
</cXML>
EOD;

Related

CURL not posting data to URL

I have a simple form which i want to convert into a PHP backend system.
Now this form has an action to submit to a URL - the URL only accepts an invite only when a data with the name postdata and correct information is submitted (xml which has been encoded).
Works: - Note that the input name is called postdata and the value contains the xml which has been urlencoded and it works perfectly.
<form name="nonjava" method="post" action="https://url.com">
<input name="postdata" id="nonjavapostdata" type="hidden" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;" />
<button type="submit" name="submit">Button</button>
</form>
However, i want to achieve the following by moving the postdata element within PHP as a lot of information is passed through that way.
Please note: the link is https but it wasnt working on local so i had to disable it within the CURL.
<?php
$url = 'https://super.com';
$xmlData = '<?xml version="1.0" encoding="utf-8"?>
<postdata
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<api>2</api>
</postdata>';
$testing = urlencode($xmlData);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "postdata=" . $testing);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($ch, CURLOPT_VERBOSE, true);
$response = curl_exec($ch);
// Then, after your curl_exec call:
$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$header = substr($response, 0, $header_size);
$body = substr($response, $header_size);
echo $header_size . '<br>';
echo htmlspecialchars($header) . '<br>';
echo htmlspecialchars($body) . '<br><br>';
$http_status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
echo "$http_status for $url <br>";
?>
I keep getting a 302 error (which is the url content is not finding the data so its redirecting to a not found page.)
302 is NOT error; it just means you need to go to the redirected URL. A browser does that automatically for you. In PHP code, you would have to do it yourself. Look at the Location header on 302.
I tried to look if there is a way that Curl could be told to follow through redirects; many language HTTP libraries support that. This thread seems to suggest that CuRL also supports it - Is there a way to follow redirects with command line cURL
Your code works as it is supposed to, I am getting POST data:
Array ( [postdata] => <?xml version="1.0" encoding="utf-8"?> <postdata xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/20
01/XMLSchema"> <api>2</api> </postdata> )
as a result. The problem is on the receiving side, it isnt handling it correctly.
You need to follow the 302 redirect in curl. This is relatively easy to do by adding the location flag. curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
This is the equivalent of doing curl -L at the CLI. You can see an example here in the php documentation.

Convert URL encoded to JSON object

I've never worked with JSON objects before but I think this is probably the best route for what I'm trying to achieve (if you think there is a better option please let me know, though I cannot use SOAP)
I am trying to submit some data via POST to an API in order to add some data to a newsletter list which is stored as XML. Here is the documentation for the request I am trying to complete: https://api.dotmailer.com/v2/help/wadl#PostAddressBookContacts
When visiting the API url and authenticating I see data laid out in the following:
<ArrayOfApiContact xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://apiconnector.com">
<ApiContact>
<Id>1058905201</Id>
<Email>email#email.co.uk</Email>
<OptInType>Unknown</OptInType>
<EmailType>Html</EmailType>
<DataFields i:nil="true"/>
<Status>Subscribed</Status>
</ApiContact>
</ArrayOfApiContact>
So I have attempted to replicate as such, using a variable instead of a hardcoded email:
$xml = array(
'id' => urlencode('123456789'),
'email' => urlencode($useremail),
'optInType' => urlencode('Unknown'),
'emailType' => urlencode('Html'),
'dataFields' => urlencode(':null'),
'status' => urlencode('Subscribed')
);
I am combining the array here:
foreach($xml as $key=>$value) { $xml_string .= $key.'='.$value.'&'; }
And then using cURL to POST the request to the API, with my authentication (apipassword and apiemail which the username)
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$auth_url);
curl_setopt($ch,CURLOPT_POST, count($xml));
curl_setopt($ch,CURLOPT_POSTFIELDS, $xml_string);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_setopt($ch, CURLOPT_USERPWD, "$apiemail:$apipassword");
$status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); //get status code
$result = curl_exec ($ch);
curl_close ($ch);
I have already tested this without the POST and I do indeed get the data back in this form:
[{"id":1058905201,"email":"email#email.co.uk","optInType":"Unknown","emailType":"Html","dataFields":null,"status":"Subscribed"}]
So I know the auth is working and the data is coming back correctly, but now when I try to POST my data I get:
{"message":"Content type \"application/x-www-form-urlencoded\" is not supported. Please use one of: application/json,application/xml ERROR_CONTENT_TYPE_IS_NOT_SUPPORTED"}
So how do I convert my array which is URL encoded into something readable by the API?
Try a content type of application/json like so:
curl_setopt($ch, CURLOPT_HTTPHEADER, array('content-type: application/json'));
Two things here (a) content-type header JSON missing and (b) payload not JSON.
// setup request to send json via POST.
$payload = json_encode(array("json"=> $data)); // or json_encode(array($data));
curl_setopt( $ch, CURLOPT_POSTFIELDS, $payload );
// set proper content-type for sending JSON
curl_setopt( $ch, CURLOPT_HTTPHEADER, array('Content-Type:application/json'));

Getting content body from http post using php CURL

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";

how to send HTTP request by GET method in PHP to another website

I'm developing a web application for sending SMS to mobile from website like 160by2.
I can prepare the URL required for the HTTP GET request as mentioned in the API provided by the SMS Gateway provider smslane.com, here is the link for the API.
how to send the HTTP request from PHP?
I used cURL for that purpose but the response is not displayed. here is the code i used,
<?php
$url="http://smslane.com/vendorsms/pushsms.aspx?user=abc&password=xyz&msisdn=919898123456&sid=WebSMS&msg=Test message from SMSLane&fl=0";
$ch = curl_init();
curl_setopt( $ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.1; rv:1.7.3) Gecko/20041001 Firefox/0.10.1" );
curl_setopt( $ch, CURLOPT_URL, $url );
$content = curl_exec( $ch );
$response = curl_getinfo( $ch );
curl_close ( $ch );
echo $content;
?>
fsockopen() was not used because port number unknown, mailed the support team for port number. (if any code for fsockopen through GET method is invited :). )
are there any other methods for doing this?
any help is welcome.
Thanks in advance.
EDIT
Could any one tell me is there any other way to send this HTTP Request except cURL and if possible give code for that.
I'm asking this because the current cURL code taking too much time for execution and fails after 60 seconds, i increased max_execution_time to 120 in php.ini on my local system even though it is not doing good for me :( .
Your problem is the way you are constructing the URL. The spaces you are including in the query string will result in a malformed request URL being sent.
Here is an example that replicates your circumstances:
request.php:
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_URL,
'http://your_server/response.php?foo=yes we can&baz=foo bar'
);
$content = curl_exec($ch);
echo $content;
response.php:
<?php
print_r($_GET);
The output of request.php is:
Array
(
[foo] => yes
)
The reason for this is the query string is not properly encoded and the server interpreting the request assumes the URL ends at the first space, which in this case is in the middle of the query: foo=yes we can&baz=foo bar.
You need to build your URL using http_build_query, which will take care of urlencoding your query string properly and generally makes the code look a lot more readable:
echo http_build_query(array(
'user'=>'abc',
'password'=>'xyz',
'msisdn'=>'1234',
'sid'=>'WebSMS',
'msg'=>'Test message from SMSLane',
'fl'=>0
));
You also need to set CURLOPT_RETURNTRANSFER:
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
<?php
print file_get_contents("http://some_server/some_file.php?some_args=true");
?>
The below code will make a HTTP request with curl and return the response in $content.
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_URL,'http://www.anydomain.com/anyapi.php?a=parameters');
$content = curl_exec($ch);
echo $content;
?>
nothing wrong with your code that I can see right off. have you tried pasting the url into a browser so you can see the response? you could even use wget to download the response to a file. I suppose if you want to try fsocket that you would use port 80 as that's the default http port.
Try using following code.
$r = new HttpRequest('http://www.xencomsoftware.net/configurator/tracker/ip.php', HttpRequest::METH_GET);
try {
$r->send();
echo $r->getResponseCode();
if ($r->getResponseCode() == 200)
{
}
}
make sure that you have loaded HttpRequest extension (share object0 in your server.

Passing a parameter in the header (XML RPC)

I'm trying to set up a server status for the MMORPG Champions Online. I got some basic information from the web master and this is all he told me:
XML-RPC call to server: http://www.champions-online.com/xmlrpc.php
function name: wgsLauncher.getServerStatus
Parameter (language): en-US
Now, I found a nice example to start with here, and I ended up with this code:
<?php
ini_set('display_errors', 1);
error_reporting(E_ALL);
# Using the XML-RPC extension to format the XML package
$request = xmlrpc_encode_request("wgsLauncher.getServerStatus", "<param><value><string>en-US</string></value></param>", null );
# Using the cURL extension to send it off,
# first creating a custom header block
$header[] = "Host: http://www.champions-online.com:80/";
$header[] = "Content-type: text/xml";
$header[] = "Content-length: ".strlen($request) . "\r\n";
$header[] = $request;
$ch = curl_init();
curl_setopt( $ch, CURLOPT_URL, "http://www.champions-online.com/xmlrpc.php"); # URL to post to
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 ); # return into a variable
curl_setopt( $ch, CURLOPT_HTTPHEADER, $header ); # custom headers, see above
curl_setopt( $ch, CURLOPT_CUSTOMREQUEST, 'POST' ); # This POST is special, and uses its specified Content-type
$result = curl_exec( $ch ); # run!
curl_close($ch);
echo $result;
?>
But I'm getting a "400 Bad Request" error. I'm new to XML RPC and I barely know php, so I'm at a loss. The examples from the php site show how to use an array as a parameter, but nothing else.
I obtained the parameter string <param><value><string>en-US</string></value></param> from this XMLRPC Debugger (very nice btw). I entered the parameter I needed in the "payload" box and this was the output.
So, I would appreciate any help on how to pass this parameter to the header.
Note: My host supports xmlrpc but it seems the function "xmlrpc_client" doesn't exist.
Update: The web master replied with this information, but it's still not working... it's getting to the point I may just scrape the status off the page.
$request = xmlrpc_encode_request("wgsLauncher.getServerStatus", "en-US" );
Ok, I finally figured out my answer... It seemed to be a problem in the header, because it worked when I changed the cURL code to match the code I found it on this site. The post is about how to remotely post to wordpress using XMLRPC in php.
This is the code I ended up with:
<?php
// ini_set('display_errors', 1);
// error_reporting(E_ALL);
# Using the XML-RPC extension to format the XML package
$request = xmlrpc_encode_request( "wgsLauncher.getServerStatus", "en-US" );
$ch = curl_init();
curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
curl_setopt($ch, CURLOPT_URL, "http://www.champions-online.com/xmlrpc.php");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 1);
$result = curl_exec($ch);
curl_close($ch);
$method = null;
$params = xmlrpc_decode_request($result, &$method);
# server status result = true (up) or false (down)
$status = ($params['status']) ? 'up' : 'down';
$notice = ($params['notice'] == "") ? "" : "Notice: " + $params['notice'];
echo "Server Status: " . $status . "<br>";
echo $notice;
?>

Categories