Anyone know how can I post a SOAP Request from PHP?
This is a low level API function that is used to make a SOAP call. Usually, in WSDL mode, SOAP functions can be called as methods of the SoapClient object. This method is useful in non-WSDL mode when soapaction is unknown, uri differs from the default or when sending and/or receiving SOAP Headers.
Yes, Servlet request and Web service request both are normal HTTP request and yes, SOAP web service internally use HTTP POST. SOAP message mostly send data using XML format.
In my experience, it's not quite that simple. The built-in PHP SOAP client didn't work with the .NET-based SOAP server we had to use. It complained about an invalid schema definition. Even though .NET client worked with that server just fine. By the way, let me claim that SOAP interoperability is a myth.
The next step was NuSOAP. This worked for quite a while. By the way, for God's sake, don't forget to cache WSDL! But even with WSDL cached users complained the damn thing is slow.
Then, we decided to go bare HTTP, assembling the requests and reading the responses with SimpleXMLElemnt
, like this:
$request_info = array();
$full_response = @http_post_data(
'http://example.com/OTA_WS.asmx',
$REQUEST_BODY,
array(
'headers' => array(
'Content-Type' => 'text/xml; charset=UTF-8',
'SOAPAction' => 'HotelAvail',
),
'timeout' => 60,
),
$request_info
);
$response_xml = new SimpleXMLElement(strstr($full_response, '<?xml'));
foreach ($response_xml->xpath('//@HotelName') as $HotelName) {
echo strval($HotelName) . "\n";
}
Note that in PHP 5.2 you'll need pecl_http, as far as (surprise-surpise!) there's no HTTP client built in.
Going to bare HTTP gained us over 30% in SOAP request times. And from then on we redirect all the performance complains to the server guys.
In the end, I'd recommend this latter approach, and not because of the performance. I think that, in general, in a dynamic language like PHP there's no benefit from all that WSDL/type-control. You don't need a fancy library to read and write XML, with all that stubs generation and dynamic proxies. Your language is already dynamic, and SimpleXMLElement
works just fine, and is so easy to use. Also, you'll have less code, which is always good.
PHP has SOAP support. Just call
$client = new SoapClient($url);
to connect to the SoapServer and then you can get list of functions and call functions simply by doing...
$client->__getTypes();
$client->__getFunctions();
$result = $client->functionName();
for more http://www.php.net/manual/en/soapclient.soapclient.php
I needed to do many very simple XML requests and after reading @Ivan Krechetov's comment about the speed hit of SOAP, I tried his code and discovered http_post_data() is not built into PHP 5.2. Not really wanting to install it, I tried cURL which is on all my servers. Although I do not know how fast cURL is compared to SOAP, it sure was easy to do what I needed. Below is a sample with cURL for anyone needing it.
$xml_data = '<?xml version="1.0" encoding="UTF-8" ?>
<priceRequest><customerNo>123</customerNo><password>abc</password><skuList><SKU>99999</SKU><lineNumber>1</lineNumber></skuList></priceRequest>';
$URL = "https://test.testserver.com/PriceAvailability";
$ch = curl_init($URL);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: text/xml'));
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "$xml_data");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
curl_close($ch);
print_r($output);
We can use the PHP cURL library to generate simple HTTP POST request. The following example shows you how to create a simple SOAP request using cURL.
Create the soap-server.php which write the SOAP request into soap-request.xml in web folder.
We can use the PHP cURL library to generate simple HTTP POST request. The following example shows you how to create a simple SOAP request using cURL.
Create the soap-server.php which write the SOAP request into soap-request.xml in web folder.
<?php
$HTTP_RAW_POST_DATA = isset($HTTP_RAW_POST_DATA) ? $HTTP_RAW_POST_DATA : '';
$f = fopen("./soap-request.xml", "w");
fwrite($f, $HTTP_RAW_POST_DATA);
fclose($f);
?>
The next step is creating the soap-client.php which generate the SOAP request using the cURL library and send it to the soap-server.php URL.
<?php
$soap_request = "<?xml version=\"1.0\"?>\n";
$soap_request .= "<soap:Envelope xmlns:soap=\"http://www.w3.org/2001/12/soap-envelope\" soap:encodingStyle=\"http://www.w3.org/2001/12/soap-encoding\">\n";
$soap_request .= " <soap:Body xmlns:m=\"http://www.example.org/stock\">\n";
$soap_request .= " <m:GetStockPrice>\n";
$soap_request .= " <m:StockName>IBM</m:StockName>\n";
$soap_request .= " </m:GetStockPrice>\n";
$soap_request .= " </soap:Body>\n";
$soap_request .= "</soap:Envelope>";
$header = array(
"Content-type: text/xml;charset=\"utf-8\"",
"Accept: text/xml",
"Cache-Control: no-cache",
"Pragma: no-cache",
"SOAPAction: \"run\"",
"Content-length: ".strlen($soap_request),
);
$soap_do = curl_init();
curl_setopt($soap_do, CURLOPT_URL, "http://localhost/php-soap-curl/soap-server.php" );
curl_setopt($soap_do, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($soap_do, CURLOPT_TIMEOUT, 10);
curl_setopt($soap_do, CURLOPT_RETURNTRANSFER, true );
curl_setopt($soap_do, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($soap_do, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($soap_do, CURLOPT_POST, true );
curl_setopt($soap_do, CURLOPT_POSTFIELDS, $soap_request);
curl_setopt($soap_do, CURLOPT_HTTPHEADER, $header);
if(curl_exec($soap_do) === false) {
$err = 'Curl error: ' . curl_error($soap_do);
curl_close($soap_do);
print $err;
} else {
curl_close($soap_do);
print 'Operation completed without any errors';
}
?>
Enter the soap-client.php URL in browser to send the SOAP message. If success, Operation completed without any errors will be shown and the soap-request.xml will be created.
<?xml version="1.0"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope" soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
<soap:Body xmlns:m="http://www.example.org/stock">
<m:GetStockPrice>
<m:StockName>IBM</m:StockName>
</m:GetStockPrice>
</soap:Body>
</soap:Envelope>
Original - http://eureka.ykyuen.info/2011/05/05/php-send-a-soap-request-by-curl/
You might want to look here and here.
A Little code example from the first link:
<?php
// include the SOAP classes
require_once('nusoap.php');
// define parameter array (ISBN number)
$param = array('isbn'=>'0385503954');
// define path to server application
$serverpath ='http://services.xmethods.net:80/soap/servlet/rpcrouter';
//define method namespace
$namespace="urn:xmethods-BNPriceCheck";
// create client object
$client = new soapclient($serverpath);
// make the call
$price = $client->call('getPrice',$param,$namespace);
// if a fault occurred, output error info
if (isset($fault)) {
print "Error: ". $fault;
}
else if ($price == -1) {
print "The book is not in the database.";
} else {
// otherwise output the result
print "The price of book number ". $param[isbn] ." is $". $price;
}
// kill object
unset($client);
?>
Below is a quick example of how to do this (which best explained the matter to me) that I essentially found at this website. That website link also explains WSDL, which is important for working with SOAP services.
However, I don't think the API address they were using in the example below still works, so just switch in one of your own choosing.
$wsdl = 'http://terraservice.net/TerraService.asmx?WSDL';
$trace = true;
$exceptions = false;
$xml_array['placeName'] = 'Pomona';
$xml_array['MaxItems'] = 3;
$xml_array['imagePresence'] = true;
$client = new SoapClient($wsdl, array('trace' => $trace, 'exceptions' => $exceptions));
$response = $client->GetPlaceList($xml_array);
var_dump($response);
If the XML have identities with same name in different levels there is a solution. You don´t have to ever submit a raw XML (this PHP SOAP object don´t allows send a RAW XML), so you have to always translate your XML to a array, like the example below:
$originalXML = "
<xml>
<firstClient>
<name>someone</name>
<adress>R. 1001</adress>
</firstClient>
<secondClient>
<name>another one</name>
<adress></adress>
</secondClient>
</xml>"
//Translate the XML above in a array, like PHP SOAP function requires
$myParams = array('firstClient' => array('name' => 'someone',
'adress' => 'R. 1001'),
'secondClient' => array('name' => 'another one',
'adress' => ''));
$webService = new SoapClient($someURL);
$result = $webService->someWebServiceFunction($myParams);
or
$soapUrl = "http://privpakservices.schenker.nu/package/package_1.3/packageservices.asmx?op=SearchCollectionPoint";
$xml_post_string = '<?xml version="1.0" encoding="utf-8"?><soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope"><soap12:Body><SearchCollectionPoint xmlns="http://privpakservices.schenker.nu/"><customerID>XXX</customerID><key>XXXXXX-XXXXXX</key><serviceID></serviceID><paramID>0</paramID><address>RiksvŠgen 5</address><postcode>59018</postcode><city>Mantorp</city><maxhits>10</maxhits></SearchCollectionPoint></soap12:Body></soap12:Envelope>';
$headers = array(
"POST /package/package_1.3/packageservices.asmx HTTP/1.1",
"Host: privpakservices.schenker.nu",
"Content-Type: application/soap+xml; charset=utf-8",
"Content-Length: ".strlen($xml_post_string)
);
$url = $soapUrl;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml_post_string);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($ch);
curl_close($ch);
$response1 = str_replace("<soap:Body>","",$response);
$response2 = str_replace("</soap:Body>","",$response1);
$parser = simplexml_load_string($response2);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With