SOAP libraries for PHP
I know of these:
- Nusoap
- PHP SOAP Extension (based on libxml)
- WSO2 Web Services Framework for PHP
- Zend_Soap
PHP SOAP client Tutorial/Recommendation?
Have you tried SoapClient which is already built into PHP?
There is one tutorial: PHP - Soap Client calling .NET Web service
Here is another one, even though it was created for zend developers it should work fine.
How to build a correct SOAP request with PHP
"Is there a more direct approach where I could write the XML?"
By using a SoapVar and setting the encode parameter of the constructor to XSD_ANYXML
you can write the raw XML.
There should be a way where the WSDL helps build the XML though.
You could try something like this:
$wsdl = "http://api.notificationmessaging.com/NMSOAP/NotificationService?wsdl";
$client = new SoapClient($wsdl, array( 'soap_version' => SOAP_1_1,
'trace' => true,
));
try {
$xml = '<arg0>
<content>
<entry>
<key>1</key>
<value>
<![CDATA[
<table width="600">
<tr>
<td>
<font size="2" face="Arial">Our powerful algorithms already
found a matching profile that matches your criteria:
<br>Celina72 </font>
<img src="http://mypath/to/my/image.gif" width="50"
height="50" border="0" />
</td>]]></value>
</entry>
</content>
<dyn>
<entry>
<key>FIRSTNAME</key>
<value>john</value>
</entry>
</dyn>
<email>johnblum@flowerpower.com</email>
<encrypt>BdX7CqkmjSivyBgIcZoN4sPVLkx7FaXGiwsO</encrypt>
<notificationId>6464</notificationId>
<random>985A8B992601985A</random>
<senddate>2008-12-12T00:00:00</senddate>
<synchrotype>NOTHING</synchrotype>
<uidkey>EMAIL</uidkey>
</arg0>';
$args = array(new SoapVar($xml, XSD_ANYXML));
$res = $client->__soapCall('sendObject', $args);
return $res;
} catch (SoapFault $e) {
echo "Error: {$e}";
}
echo "<hr>Last Request";
echo "<pre>", htmlspecialchars($client->__getLastRequest()), "</pre>";
PHP Soap client with complex types
For those who'll get the same problem.
My solution is to use nusoap (https://github.com/yaim/nusoap-php7). This library allows you to make complicated requests, including SWA (SOAP with Attachments).
Here is working code for my question:
$person = array("personId"=>$id, "consentConfirmed"=>$confirmed);
$data = array(
"reportParams"=>new soapval("reportParams", "personCreditReportParams", $person, false, $namespace)
);
$result = $client->call("getCreditReportTypes", $data, $namespace);
P.S. I've tried some generators and no one could make correct request, although classes were generated correctly.
Soap Client Complex Type PHP Request
I found the solution!. It seems the PHP -> .NET web service comparability issue. So from PHP the complex type SOAP (this kind of format) can't access I found some usefull post here. So I switched SOAP to plain XML request with CURL and it seems working fine!. Also from WSDL link we can extract the request template using this online service .
So my final code look like below.
$xml_data = "<?xml version='1.0' encoding='UTF-8'?>
<s12:Envelope xmlns:s12='http://www.w3.org/2003/05/soap-envelope'>
<s12:Header>
<ns1:SecurityHeaderElement xmlns:ns1='http://www.navicure.com/2009/11/NavicureSubmissionService'>
<ns1:originatingIdentifier>****</ns1:originatingIdentifier>
<ns1:submitterIdentifier>****</ns1:submitterIdentifier>
<ns1:submitterPassword>***</ns1:submitterPassword>
<ns1:submissionId>?999?</ns1:submissionId>
</ns1:SecurityHeaderElement>
</s12:Header>
<s12:Body>
<ns1:SubmitAnsiSingleRequestElement xmlns:ns1='http://www.navicure.com/2009/11/NavicureSubmissionService'>
<ns1:timeout>60</ns1:timeout>
<ns1:transactionType>E</ns1:transactionType>
<ns1:submittedAnsiVersion>5010</ns1:submittedAnsiVersion>
<ns1:resultAnsiVersion>5010</ns1:resultAnsiVersion>
<ns1:submitterSubmissionId></ns1:submitterSubmissionId>
<ns1:processingOption>R</ns1:processingOption>
<ns1:payload>EDI270Payload</ns1:payload>
</ns1:SubmitAnsiSingleRequestElement>
</s12:Body>
</s12:Envelope>";
$URL = "https://ww3.navicure.com:7000/webservices/NavicureSubmissionService";
$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);
Hope this will help someone else in future.
How to make a PHP SOAP client and store the result xml in php variables
PHP has a native SoapClient class that makes it easy to call SOAP services. It provides a simple interface allowing you to use native PHP arrays and objects for the request and response data, and handles the intricacies of the SOAP envelope and WSDL.
// create a new SoapClient and pass it the WSDL
$client = new SoapClient('http://webservices.cibg.nl/Ribiz/OpenbaarV2.asmx?WSDL');
// define the input parameters for the webservice call
$params = array('WebSite' => 'Ribiz', 'RegistrationNumber' => 'xxxxxxxxxx');
// invoke the ListHcpApprox3 method
$response = $client->ListHcpApprox3($params);
// print out the response to see its structure
var_dump($response);
You can pick the variables out of the response like this:
$data = $response->ListHcpApprox->ListHcpApprox3
$HcpNumber = $data->HcpNumber;
$BirthSurname = $data->BirthSurname;
echo $HcpNumber;
Parsing a live SOAP data stream with PHP
Ok, the goal is to "stream a SOAP reponse" with a "timeout" and/or in an "interval"?
I suggest to override the SoapClient __doRequest()
method and implement a custom connection via fsockopen()
and stream the data with stream_get_contents()
.
Now you get a stream of XML data and what you want is in the middle of it.
You would have to extract the XML envelope or parts of it, probably using string functions or by using preg_match
to fetch the inner content.
The following code provides a SoapClientTimeout class, where the timeout is set via stream_set_timeout()
. This is for use-case, when the server has slow responses and you want to make sure, when to end listening.
I suggest to play around with it and tweak the timeout behavior on the socket.
Because, what you want is to stop listening after a while (interval fetch).
So, you cloud try to combine timeout with blocking, to stop reading from the stream after a while:
$timeout = 60; // seconds
stream_set_blocking($socket, true);
stream_set_timeout($socket, $timeout);
When you have a stream, which blocks after 1 minute and closes,
you need a loop (with a solid exit condition) triggering the next request.
class SoapClientTimeout extends SoapClient
{
public function __construct ($wsdl, $options = null)
{
if (!$options) $options = [];
$this->_connectionTimeout = @$options['connection_timeout'] ?: ini_get ('default_socket_timeout');
$this->_socketTimeout = @$options['socket_timeout'] ?: ini_get ('default_socket_timeout');
unset ($options['socket_timeout']);
parent::__construct($wsdl, $options);
}
/**
* Override parent __doRequest and add "timeout" functionality.
*/
public function __doRequest ($request, $location, $action, $version, $one_way = 0)
{
// fetch host, port, and scheme from url.
$url_parts = parse_url($location);
$host = $url_parts['host'];
$port = @$url_parts['port'] ?: ($url_parts['scheme'] == 'https' ? 443 : 80);
$length = strlen ($request);
// create HTTP SOAP request.
$http_req = "POST $location HTTP/1.0\r\n";
$http_req .= "Host: $host\r\n";
$http_req .= "SoapAction: $action\r\n";
$http_req .= "Content-Type: text/xml; charset=utf-8\r\n";
$http_req .= "Content-Length: $length\r\n";
$http_req .= "\r\n";
$http_req .= $request;
// switch to SSL, when requested
if ($url_parts['scheme'] == 'https') $host = 'ssl://'.$host;
// connect
$socket = @fsockopen($host, $port, $errno, $errstr, $this->_connectionTimeout);
if (!$socket) {
throw new SoapFault('Client',"Failed to connect to SOAP server ($location): $errstr");
}
// send request with socket timeout
stream_set_timeout($socket, $this->_socketTimeout);
fwrite ($socket, $http_req);
// start reading the response.
$http_response = stream_get_contents($socket);
// close the socket and throw an exception if we timed out.
$info = stream_get_meta_data($socket);
fclose ($socket);
if ($info['timed_out']) {
throw new SoapFault ('Client', "HTTP timeout contacting $location");
}
// the stream contains XML data
// lets extract the XML from the HTTP response and return it.
$response = preg_replace (
'/
\A # Start of string
.*? # Match any number of characters (as few as possible)
^ # Start of line
\r # Carriage Return
$ # End of line
/smx',
'', $http_response
);
return $response;
}
}
PHP SOAP client over IPv4
A SOAP request is a socket connection, so you can use socket_context options.
Use stream_context_create()
to bind your request to a specified IP.
stream_context_create(['socket' => ['bindto' => '123.123.123.123:0']]);
Set 0
for port number so PHP will set this automatically.
Related Topics
Convert the First Element of an Array to a String in PHP
Creating Variable Name by Concatenating Strings in PHP
Symfony Redirect with 2 Parameters
Natural Sorting Algorithm in PHP with Support for Unicode
Use Curl with Sni (Server Name Indication)
PHP $Stmt->Num_Rows Doesnt Work by Prepared Statements
Get_Instance() in Codeigniter: Why Assign It to a Variable
How to Give Apache Permission to Write to Home Directory
How to Pass Param from Controller to Layout in Yii2
How to Convert Date/Time from 24-Hour Format to 12-Hour Am/Pm
How to Minify Js in PHP Easily...Or Something Else
A Restful Persistence Solution Usable with Backbone.Js... in PHP
Is There a Function to Make a Copy of a PHP Array to Another
How to Trigger Xdebug Profiler for a Command Line PHP Script