Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a SOAP call using PHP with an XML body

Tags:

I'm trying to call a SOAP method using PHP.

Here's the code I've got:

$data = array('Acquirer' =>   array(     'Id' => 'MyId',     'UserId' => 'MyUserId',     'Password' => 'MyPassword'   )); $method = 'Echo'; $client = new SoapClient(NULL,            array('location' => 'https://example.com/ExampleWebServiceDL/services/ExampleHandler',             'uri' => 'http://example.com/wsdl', 'trace' => 1)); $result = $client->$method($data); 

Here's the request it creates:

  <?xml version="1.0" encoding="UTF-8"?>   <SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://example.com/wsdl" xmlns:ns2="http://xml.apache.org/xml-soap" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">     <SOAP-ENV:Body>       <ns1:Echo>         <param0 xsi:type="ns2:Map">           <item>             <key xsi:type="xsd:string">Acquirer</key>             <value xsi:type="ns2:Map">               <item>                 <key xsi:type="xsd:string">Id</key>                 <value xsi:type="xsd:string">mcp</value>               </item>               <item>                 <key xsi:type="xsd:string">UserId</key>                 <value xsi:type="xsd:string">tst001</value>               </item>               <item>                 <key xsi:type="xsd:string">Password</key>                 <value xsi:type="xsd:string">test</value>               </item>             </value>           </item>         </param0>       </ns1:Echo>     </SOAP-ENV:Body>   </SOAP-ENV:Envelope> 

And here's what I want the request to look like:

  <?xml version="1.0" encoding="UTF-8"?>   <SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://example.com/wsdl" xmlns:ns2="http://xml.apache.org/xml-soap" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">     <SOAP-ENV:Body>       <Echo>         <Acquirer>           <Id>MyId</Id>           <UserId>MyUserId</UserId>           <Password>MyPassword</Password>         </Acquirer>       </Echo>     </SOAP-ENV:Body>   </SOAP-ENV:Envelope> 
like image 742
greggles Avatar asked Mar 08 '13 18:03

greggles


People also ask

How do I create a SOAP request in XML?

To make SOAP requests to the SOAP API endpoint, use the "Content-Type: application/soap+xml" request header, which tells the server that the request body contains a SOAP envelope. The server informs the client that it has returned a SOAP envelope with a "Content-Type: application/soap+xml" response header.

Does SOAP allow XML?

A Quick Overview of SOAPSOAP relies exclusively on XML to provide messaging services. Microsoft originally developed SOAP to take the place of older technologies that don't work well on the internet such as the Distributed Component Object Model (DCOM) and Common Object Request Broker Architecture (CORBA).

Why XML is used in SOAP?

SOAP uses XML to package the data passed to a method, or received as a response. SOAP itself is nothing more than a set of rules that define how to describe method calls and return values using XML syntax. XML merely describes data, without consideration for the way that the data is processed or presented.


2 Answers

There are a couple of ways to solve this. The least hackiest and almost what you want:

$client = new SoapClient(     null,     array(         'location' => 'https://example.com/ExampleWebServiceDL/services/ExampleHandler',         'uri' => 'http://example.com/wsdl',         'trace' => 1,         'use' => SOAP_LITERAL,     ) ); $params = new \SoapVar("<Acquirer><Id>MyId</Id><UserId>MyUserId</UserId><Password>MyPassword</Password></Acquirer>", XSD_ANYXML); $result = $client->Echo($params); 

This gets you the following XML:

<?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://example.com/wsdl">     <SOAP-ENV:Body>         <ns1:Echo>             <Acquirer>                 <Id>MyId</Id>                 <UserId>MyUserId</UserId>                 <Password>MyPassword</Password>             </Acquirer>         </ns1:Echo>     </SOAP-ENV:Body> </SOAP-ENV:Envelope> 

That is almost exactly what you want, except for the namespace on the method name. I don't know if this is a problem. If so, you can hack it even further. You could put the <Echo> tag in the XML string by hand and have the SoapClient not set the method by adding 'style' => SOAP_DOCUMENT, to the options array like this:

$client = new SoapClient(     null,     array(         'location' => 'https://example.com/ExampleWebServiceDL/services/ExampleHandler',         'uri' => 'http://example.com/wsdl',         'trace' => 1,         'use' => SOAP_LITERAL,         'style' => SOAP_DOCUMENT,     ) ); $params = new \SoapVar("<Echo><Acquirer><Id>MyId</Id><UserId>MyUserId</UserId><Password>MyPassword</Password></Acquirer></Echo>", XSD_ANYXML); $result = $client->MethodNameIsIgnored($params); 

This results in the following request XML:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">     <SOAP-ENV:Body>         <Echo>             <Acquirer>                 <Id>MyId</Id>                 <UserId>MyUserId</UserId>                 <Password>MyPassword</Password>             </Acquirer>         </Echo>     </SOAP-ENV:Body> </SOAP-ENV:Envelope> 

Finally, if you want to play around with SoapVar and SoapParam objects, you can find a good reference in this comment in the PHP manual: http://www.php.net/manual/en/soapvar.soapvar.php#104065. If you get that to work, please let me know, I failed miserably.

like image 68
Matthijs van den Bos Avatar answered Oct 17 '22 01:10

Matthijs van den Bos


First off, you have to specify you wish to use Document Literal style:

$client = new SoapClient(NULL, array(     'location' => 'https://example.com/path/to/service',     'uri' => 'http://example.com/wsdl',     'trace' => 1,     'use' => SOAP_LITERAL) ); 

Then, you need to transform your data into a SoapVar; I've written a simple transform function:

function soapify(array $data) {         foreach ($data as &$value) {                 if (is_array($value)) {                         $value = soapify($value);                 }         }          return new SoapVar($data, SOAP_ENC_OBJECT); } 

Then, you apply this transform function onto your data:

$data = soapify(array(     'Acquirer' => array(         'Id' => 'MyId',         'UserId' => 'MyUserId',         'Password' => 'MyPassword',     ), )); 

Finally, you call the service passing the Data parameter:

$method = 'Echo';  $result = $client->$method(new SoapParam($data, 'Data')); 
like image 27
Ja͢ck Avatar answered Oct 17 '22 03:10

Ja͢ck