I have recently upgraded from PHP5.4 to PHP7. Boy was that a change, but that is beside the point.
I'm having issues with a SoapService since the upgrade.
Here is what my SoapRequest looked like on PHP5.4:
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:ns1="urn:usaepay" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:enc="http://www.w3.org/2003/05/soap-encoding">
<env:Body>
<ns1:searchTransactions env:encodingStyle="http://www.w3.org/2003/05/soap-encoding">
<Token xsi:type="ns1:ueSecurityToken">
<ClientIP xsi:type="xsd:string">*redacted*</ClientIP>
<PinHash xsi:type="ns1:ueHash">
<HashValue xsi:type="xsd:string">*redacted*</HashValue>
<Seed xsi:type="xsd:string">*redacted*</Seed>
<Type xsi:type="xsd:string">sha1</Type>
</PinHash>
<SourceKey xsi:type="xsd:string">*redacted*</SourceKey>
</Token>
<Search enc:itemType="ns1:SearchParam" enc:arraySize="3" xsi:type="ns1:SearchParamArray">
<item xsi:type="ns1:SearchParam">
<Field xsi:type="xsd:string">created</Field>
<Type xsi:type="xsd:string">gt</Type>
<Value xsi:type="xsd:string">2016-07-26</Value>
</item>
<item xsi:type="ns1:SearchParam">
<Field xsi:type="xsd:string">created</Field>
<Type xsi:type="xsd:string">lt</Type>
<Value xsi:type="xsd:string">2016-07-27</Value>
</item>
<item xsi:type="ns1:SearchParam">
<Field xsi:type="xsd:string">response</Field>
<Type xsi:type="xsd:string">eq</Type>
<Value xsi:type="xsd:string">A</Value>
</item>
</Search>
<MatchAll xsi:type="xsd:boolean">true</MatchAll>
<Start xsi:type="xsd:integer">0</Start>
<Limit xsi:type="xsd:integer">9999</Limit>
<Sort xsi:type="xsd:string">TransID</Sort>
</ns1:searchTransactions>
</env:Body>
</env:Envelope>
Here is what the request looks like running the exact same piece of code on PHP7:
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:ns1="urn:usaepay" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns2="http://xml.apache.org/xml-soap" xmlns:enc="http://www.w3.org/2003/05/soap-encoding">
<env:Body>
<ns1:searchTransactions env:encodingStyle="http://www.w3.org/2003/05/soap-encoding">
<Token xsi:type="ns1:ueSecurityToken">
<ClientIP xsi:type="xsd:string">*redacted*</ClientIP>
<PinHash xsi:type="ns1:ueHash">
<HashValue xsi:type="xsd:string">*redacted*</HashValue>
<Seed xsi:type="xsd:string">*redacted*</Seed>
<Type xsi:type="xsd:string">sha1</Type>
</PinHash>
<SourceKey xsi:type="xsd:string">*redacted*</SourceKey>
</Token>
<Search enc:itemType="ns2:Map" enc:arraySize="3" xsi:type="ns1:SearchParamArray">
<item xsi:type="ns2:Map">
<item>
<key xsi:type="xsd:string">Field</key>
<value xsi:type="xsd:string">created</value>
</item>
<item>
<key xsi:type="xsd:string">Type</key>
<value xsi:type="xsd:string">gt</value>
</item>
<item>
<key xsi:type="xsd:string">Value</key>
<value xsi:type="xsd:string">2016-07-26</value>
</item>
</item>
<item xsi:type="ns2:Map">
<item>
<key xsi:type="xsd:string">Field</key>
<value xsi:type="xsd:string">created</value>
</item>
<item>
<key xsi:type="xsd:string">Type</key>
<value xsi:type="xsd:string">lt</value>
</item>
<item>
<key xsi:type="xsd:string">Value</key>
<value xsi:type="xsd:string">2016-07-26</value>
</item>
</item>
<item xsi:type="ns2:Map">
<item>
<key xsi:type="xsd:string">Field</key>
<value xsi:type="xsd:string">response</value>
</item>
<item>
<key xsi:type="xsd:string">Type</key>
<value xsi:type="xsd:string">eq</value>
</item>
<item>
<key xsi:type="xsd:string">Value</key>
<value xsi:type="xsd:string">A</value>
</item>
</item>
</Search>
<MatchAll xsi:type="xsd:boolean">true</MatchAll>
<Start xsi:type="xsd:integer">0</Start>
<Limit xsi:type="xsd:integer">9999</Limit>
<Sort xsi:type="xsd:string">created</Sort>
</ns1:searchTransactions>
</env:Body>
</env:Envelope>
Here is the relevant PHP code: (Note $sec) is the security information that has been redacted.
$param = array(
array('Field' => 'created', 'Type' => 'gt', 'Value' => date('Y-m-d', strtotime('2016-07-26'))),
array('Field' => 'created', 'Type' => 'lt', 'Value' => date('Y-m-d', strtotime('2016-07-26'))),
array('Field' => 'response', 'Type' => 'eq', 'Value' => 'A')
);
$matchAll = true;
$start = 0;
$limit = 9999;
$sort = 'TransID';
$this->advClient = new SoapClient($this->adv_wsdl, array('trace' => 1, 'exceptions' => 1, 'cache_wsdl' => WSDL_CACHE_BOTH, 'soap_version' => SOAP_1_2));
$result = $this->advClient->searchTransactions($sec, $searchParam, $matchAll, $start, $limit, $sort);
What I end up with is an error. I think the issue is that in PHP7 it is wrapping and adding extra "item" tags. However some of the functions still work no problem. Has anyone else ran into this?
Interestingly enough, I used wsdltophp.com and created a class for the WSDL and everything worked fine.
Related
this is how my request needs to look in XML format:
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:ns="http://www.juniper.es/webservice/2007/">
<soap:Header/>
<soap:Body>
<ns:HotelList>
<ns:HotelListRQ Version="1.1" Language="en">
<Login Password="pass" Email="me#mydomain"/>
<ns:HotelListRequest ZoneCode="12345">
</ns:HotelListRQ>
</ns:HotelList>
</soap:Body>
</soap:Envelope>
Here is my attempt to pass the following array as the 2nd param in __soapCall(). Docs here: https://www.php.net/manual/en/soapclient.soapcall.php
$argument = ["body" =>
["HotelList" =>
["HotelListRQ" =>
["Login" => ["password" => "pass", "email" => "me#mydomain"],
["HotelListRequest" => ["ZoneCode" => $zoneCode]],
],
],
];
But the resulting request is a mess, see here:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://xml-uat.bookingengine.es/webservice/JP/WebServiceJP.asmx?WSDL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns2="http://xml.apache.org/xml-soap" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<ns1:HotelList>
<param0 xsi:type="ns2:Map">
<item>
<key xsi:type="xsd:string">HotelList</key>
<value xsi:type="ns2:Map">
<item>
<key xsi:type="xsd:string">HotelListRQ</key>
<value xsi:type="ns2:Map">
<item>
<key xsi:type="xsd:string">Login</key>
<value xsi:type="ns2:Map">
<item>
<key xsi:type="xsd:string">email</key>
<value xsi:type="xsd:string">me#mydomain</value>
</item>
<item>
<key xsi:type="xsd:string">password</key>
<value xsi:type="xsd:string">pass</value>
</item>
</value>
</item>
</value>
</item>
<item>
<key xsi:type="xsd:int">0</key>
<value xsi:type="ns2:Map">
<item>
<key xsi:type="xsd:string">HotelListRequest</key>
<value xsi:type="ns2:Map">
<item>
<key xsi:type="xsd:string">ZoneCode</key>
<value xsi:type="xsd:int">12345</value>
</item>
</value>
</item>
</value>
</item>
</value>
</item>
</param0>
</ns1:HotelList>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
what's the correct way to construct this request as an array?
I need to create an xml to send via soap, but I can not. I need an xml with a CDATA tag and I can not do it.
The xml must be in this format:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="url-here">
<soapenv:Header/>
<soapenv:Body>
<ser:callServiceMethod>
<!--Optional:-->
<xml>
<![CDATA[<fruits>
<type>G</type>
<flav>grape</flav>
<orders>
<order>
<client>12345</client>
<itens>
<item>
<cod>1</cod>
<name>Grape</name>
</item>
<item>
<cod>2</cod>
<name>Apple</name>
</item>
</itens>
</order>
</orders>
</fruits>]]>
</xml>
</ser:callServiceMethod>
</soapenv:Body>
</soapenv:Envelope>
I tried to create an array to generate the xml, this works, but without the CDATA, like this:
$soapArgs = array(
'xml' => array(
//need CDATA here
'fruits' => array(
'type' => 'G',
'flav' => 'grape',
'orders' => array(
'order' => array(
'client' => 12345,
'itens' => array(
'item' => array(
'cod' => 1,
'name' => 'Grape',
),
'item' => array(
'cod' => 2,
'name' => 'Apple',
),
)
)
)
)
)
);
$soapClient = new SoapClient($params);
$serviceResponse = $soapClient->callServiceMethod($soapArgs);
How do I generate this xml with CDATA to be able to send via SOAP?
Thank you guys!
As discussed under What does <![CDATA[]]> in XML mean? a CDATA section is a way of including a string in an XML document without it being parsed. Everything from <fruits> to </fruits> is therefore not part of the actual XML document; as far as the SOAP request is concerned, it's just a string.
(This kind of thing is quite common in SOAP services, because people find it easier to parse the payload outside of their SOAP code, so they use SOAP as a large wrapper around arbitrary content. It could just as well be <json><![CDATA[{"foo": "bar"}]]></json> or some other format of payload.)
Assuming the owner of the SOAP service hasn't done something really weird, this:
<xml>
<![CDATA[<fruits>
<type>G</type>
<flav>grape</flav>
<orders>
<order>
<client>12345</client>
<itens>
<item>
<cod>1</cod>
<name>Grape</name>
</item>
<item>
<cod>2</cod>
<name>Apple</name>
</item>
</itens>
</order>
</orders>
</fruits>]]>
</xml>
should be completely equivalent to this:
<xml>
<fruits>
<type>G</type>
<flav>grape</flav>
<orders>
<order>
<client>12345</client>
<itens>
<item>
<cod>1</cod>
<name>Grape</name>
</item>
<item>
<cod>2</cod>
<name>Apple</name>
</item>
</itens>
</order>
</orders>
</fruits>
</xml>
The function creating the XML will handle escaping the string, or wrapping it in CDATA, so all you should need is:
$xml = '<fruits>
<type>G</type>
<flav>grape</flav>
<orders>
<order>
<client>12345</client>
<itens>
<item>
<cod>1</cod>
<name>Grape</name>
</item>
<item>
<cod>2</cod>
<name>Apple</name>
</item>
</itens>
</order>
</orders>
</fruits>';
$soapArgs = array('xml' => $xml);
How you create the string $xml is, obviously, up to you.
I'm new to using SOAP and PHP, and I need to create a request exactly like this using PHP SoapClient class:
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
xmlns:ent="http://enterprise.000.000.com/Infrastructure/EnterpriseContext"
xmlns:ns="http://000.000.com/000/service/000/intf/1">
<soap:Header>
<ent:enterpriseContext>
<ent:contextInfo>
<ent:ProcessContextId>000K121300223393915419638486638404</ent:ProcessContextId>
<ent:businessContextId>CO</ent:businessContextId>
<ent:applicationContextId>3</ent:applicationContextId>
</ent:contextInfo>
<ent:requestOriginator>
<ent:requesterCode>000</ent:requesterCode>
<ent:machineIPAddress>0.0.0.0</ent:machineIPAddress>
<ent:userPrincipleName>000</ent:userPrincipleName>
<ent:requestedTimestamp>2015-10-01T05:53:04</ent:requestedTimestamp>
<ent:channelId>1</ent:channelId>
</ent:requestOriginator>
</ent:enterpriseContext>
</soap:Header>
<soap:Body>
<ns:InitiatePaymentDetails>
<InitiatePaymentDetailsRequest>
<transactionAmount>35</transactionAmount>
<olpIdAlias>000_uat_uat1</olpIdAlias>
<merchantRefNum>7999</merchantRefNum>
<!--1 or more repetitions:-->
<merchants>
<merchantId>1003</merchantId>
<merchantRefNum>7999</merchantRefNum>
<paymentAmount>35</paymentAmount>
<paymentCurrency>SAR</paymentCurrency>
<merchantType>1</merchantType>
</merchants>
<merchantId>1003</merchantId>
</InitiatePaymentDetailsRequest>
</ns:InitiatePaymentDetails>
</soap:Body>
</soap:Envelope>
How can I achieve that?
I just managed to solve the problem
Although the code I used didn't produce an identical XML request, but It fulfills the web service requirements. I put the answer here for any one with a similar problem.
$wsdl = 'https://000.000.com/000abpayproc-ws/000PaymentManager.wsdl';
$client = new SoapClient($wsdl, array('trace' => 1));
$unique_id = mt_rand(100000, 999999);
$timestamp = time();
$ref_number = mt_rand(10000000, 99999999);
$headerbody = array(
'contextInfo' => array(
'ProcessContextId' => '000'.$unique_id.$timestamp,
'businessContextId' => 'CO',
'applicationContextId' => 3
),
'requestOriginator' => array(
'requesterCode' => '000',
'machineIPAddress' => '00.00.00.00',
'userPrincipleName' => '000',
'requestedTimestamp' => '2015-10-01T05:53:04',
'channelId' => 1
),
);
$ns = 'http://000.000.com/000/service/000/intf/1';
$header = new SOAPHeader($ns, 'enterpriseContext', $headerbody);
$ent = 'http://000.000.000.com/Infrastructure/EnterpriseContext';
$header2 = new SOAPHeader($ent, 'enterpriseContext', $headerbody);
$parm = array(
'InitiatePaymentDetailsRequest' =>
array(
'transactionAmount' => 35,
'olpIdAlias' => '000',
'merchantRefNum' => $ref_number,
'merchants' => array(
'merchantId' => 1003,
'merchantRefNum' => 7999,
'paymentAmount' => 35,
'paymentCurrency' => 'SAR',
'merchantType' => 1,
),
'merchantId' => 1003
)
);
try {
$resp = $client->__soapCall('InitiatePaymentDetails', array($parm), array(), array($header, $header2));
echo 'REQUEST:<br />';
var_dump($client->__getLastRequest());
echo '<br />';
echo 'RESPONSE:<br />';
dd($resp);
} catch (SoapFault $ex) {
echo 'REQUEST:<br />';
$client->__getLastRequest();
echo '<br />';
echo 'RESPONSE:<br />';
echo $ex->getMessage();
}
The resulting request was as follows:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://000.000.com/000/service/000/intf/1" xmlns:ns2="http://enterprise.000.000.com/Infrastructure/EnterpriseContext">
<SOAP-ENV:Header>
<ns1:enterpriseContext>
<item>
<key>contextInfo</key>
<value>
<item>
<key>ProcessContextId</key>
<value>0004331921464611756</value>
</item>
<item>
<key>businessContextId</key>
<value>CO</value>
</item>
<item>
<key>applicationContextId</key>
<value>3</value>
</item>
</value>
</item>
<item>
<key>requestOriginator</key>
<value>
<item>
<key>requesterCode</key>
<value>000</value>
</item>
<item>
<key>machineIPAddress</key>
<value>00.00.00.00</value>
</item>
<item>
<key>userPrincipleName</key>
<value>000</value>
</item>
<item>
<key>requestedTimestamp</key>
<value>2015-10-01T05:53:04</value>
</item>
<item>
<key>channelId</key>
<value>1</value>
</item>
</value>
</item>
</ns1:enterpriseContext>
<ns2:enterpriseContext>
<ns2:contextInfo>
<ns2:ProcessContextId>004331921464611756</ns2:ProcessContextId>
<ns2:businessContextId>CO</ns2:businessContextId>
<ns2:applicationContextId>3</ns2:applicationContextId>
</ns2:contextInfo>
<ns2:requestOriginator>
<ns2:requesterCode>000</ns2:requesterCode>
<ns2:machineIPAddress>00.00.00.00</ns2:machineIPAddress>
<ns2:userPrincipleName>000</ns2:userPrincipleName>
<ns2:requestedTimestamp>2015-10-01T05:53:04</ns2:requestedTimestamp>
<ns2:channelId>1</ns2:channelId>
</ns2:requestOriginator>
</ns2:enterpriseContext>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<ns1:InitiatePaymentDetails>
<InitiatePaymentDetailsRequest>
<transactionAmount>35</transactionAmount>
<olpIdAlias>000</olpIdAlias>
<merchantRefNum>51777161</merchantRefNum>
<merchants>
<merchantId>1003</merchantId>
<merchantRefNum>7999</merchantRefNum>
<paymentAmount>35</paymentAmount>
<paymentCurrency>SAR</paymentCurrency>
<merchantType>1</merchantType>
</merchants>
<merchantId>1003</merchantId>
</InitiatePaymentDetailsRequest>
</ns1:InitiatePaymentDetails>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
I'm having some problems by making my SOAP headers:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="elementos" xmlns:ns2="elementoscomunes">
<SOAP-ENV:Header>
<ns2:CABECERA>
<item>
<key>Element</key>
<value>
<item>
<key>Key</key>
<value/>
</item>
<item>
<key>Values</key>
<value>
<item>
<key>Value</key>
<value/>
</item>
</value>
</item>
</value>
</item>
</ns2:CABECERA>
So, ITEM tags are added because the namespace must not be found, i've tried to change the namespace root, but i think this is not the solution..
My service is under ssl, does all namespaces must be under ssl?
Can the tag be the error code explanation?
A PHP Error was encountered
Severity: Warning
Message: SoapClient::__doRequest(): SSL: Connection reset by peer
AND
THE SOAP FAULT:
SoapFault Object
(
[message:protected] => Error Fetching http headers
My original .wdsl has the next header definition:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:elem="elementoscomunes" xmlns:elem1="elementos">
<soapenv:Header>
<elem:CABECERA>
<!--Zero or more repetitions:-->
<Element>
<Key>?</Key>
<Values>
<!--Zero or more repetitions:-->
<Value>?</Value>
</Values>
</Element>
</elem:CABECERA>
</soapenv:Header>
</elem:CABECERA>
</soapenv:Header>
Does i have to add a new namespace?
I'm on an Apache Server so key tag must be "Key" i generate the code as shown below:
$headerbody = array('Element' => array('Key' => '', 'Values' => array('Value' => '')));
$header = new SOAPHeader('namespace', 'CABECERA', $headerbody );
$sClient->__setSoapHeaders($header);
Any Suggestions?
Thanks you!
I think it's too old, but my solution to do this was:
just replace this:
$headerbody = array('Element' => array('Key' => '', 'Values' => array('Value' => '')));
with this:
$headerbody = (object) array('Element' => array('Key' => '', 'Values' => array('Value' => '')));
Hope this help.!
When using php soap client sending data to the header or the body will result in the addition of item tags if the data is an array.
i.e.
$this->header(NAMESPACE, 'abc', [
'animal' => 'dog,
]);
becomes
<SOAP-ENV:Header>
<ns1:abc>
<item>
<key>animal</key>
<value>dog</value>
</item>
</ns1:abc>
</SOAP-ENV:Header>
Sending an object
$this->header(NAMESPACE, 'abc', (object)[
'animal' => 'dog,
]);
becomes
<SOAP-ENV:Header>
<ns1:abc>
<animal>dog</animal>
</ns1:abc>
</SOAP-ENV:Header>
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>
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.
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'));