How to define a SoapVar namespace? - php

I need to have this node in my SOAP Request (using 1.1):
<CredentialsHeader xmlns="http://www.url.com/Services/P24ListingService11"
<EMail>ricky#email.net</EMail>
<Password>password</Password>
</CredentialsHeader>
So I have the following PHP:
$client = new SoapClient("https://exdev.www.example.com/Services/example.asmx?WSDL",
array(
"trace" => 1,
"exceptions" => 0,
"cache_wsdl" => 0,
'soap_version' => SOAP_1_1
)
);
$CredentialObject = new SoapVar(array('EMail' => 'ricky#email.net', 'Password' => 'password'), SOAP_ENC_OBJECT);
Which generates:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www.example.com/Services/Example">
<SOAP-ENV:Header>
<ns1:CredentialsHeader>
<EMail>ricky#email.net</EMail>
<Password>password</Password>
</ns1:CredentialsHeader>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<ns1:EchoAuthenticated/>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
All I need to do is prevent it using ns1 and actually define the xmlns in the node like so:
<CredentialsHeader xmlns="http://www.example.com/Services/Example">
<EMail>ricky#email.net</EMail>
<Password>password</Password>
</CredentialsHeader>
I have tested that in Firefox Poster and know for a fact that change fixes the problem.

$CredentialObjectXML = '<CredentialsHeader xmlns="http://www.example.com/Services/Example">
<EMail>'.$UserName.'</EMail>
<Password>'.$Password.'</Password>
</CredentialsHeader>';
$CredentialObject = new SoapVar($CredentialObjectXML,XSD_ANYXML);
This way you can directly use the XML with Type XSD_ANYXML.
Hope this will resolve your problem.

http://www.php.net/manual/tr/soapvar.soapvar.php
Parameter "node_namespace" is what you've been looking for i guess.

I had the same problem and found out that if you map a dummy class to the credential complex type from your WSDL, PHP will output something like:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www.example.com/Services/Example">
<SOAP-ENV:Header>
<ns1:CredentialsHeader>
<ns1:EMail>ricky#email.net</ns1:EMail>
<ns1:Password>password</ns1:Password>
</ns1:CredentialsHeader>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<ns1:EchoAuthenticated/>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
This is not exactly what was requested but although more verbose, it is equivalent.
The code goes like this:
$client = new SoapClient("https://exdev.www.example.com/Services/example.asmx?WSDL",
array(
"trace" => 1,
"exceptions" => 0,
"cache_wsdl" => 0,
"soap_version" => SOAP_1_1,
"classmap" => array(
'credential_complex_type' => 'CredentialObject',
),
)
);
class CredentialObject {}
$credentialObject = new CredentialObject();
$credentialObject->Email = 'ricky#email.net';
$credentialObject->Password = 'password';

Related

PHP not modifying header info

I am logging into a server with soap and retreiving a token, no problem....
I then add the token to the soap:header.
This is what I am trying create.
<?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:Header>
<WSAuthorization xmlns="http://url.com/testing/">
<Token>string</Token>
</WSAuthorization>
</soap12:Header>
<soap12:Body>
<ImportDrugTest xmlns="http://url.com/testing/">
<specimenID>int</specimenID>
<midasNumber>string</midasNumber>
<specimenComments>string</specimenComments>
<nonRXDrugsUsed>string</nonRXDrugsUsed>
<testCode>string</testCode>
<testDate>dateTime</testDate>
<testResult>string</testResult>
<collectionDate>dateTime</collectionDate>
<lastName>string</lastName>
<firstName>string</firstName>
<middleName>string</middleName>
<CRUDFlag>string</CRUDFlag>
</ImportDrugTest>
</soap12:Body>
</soap12:Envelope>
This is what I am getting
<?xml version="1.0" encoding="UTF-8"?>
<soap-env:envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://url.com/testing/">
<soap-env:header>
<ns1:wsauthorization />
</soap-env:header>
<soap-env:body>
<ns1:importdrugtest>
<ns1:specimenid>605431024</ns1:specimenid>
<ns1:midasnumber>7700MD2005000001.00</ns1:midasnumber>
<ns1:specimencomments>Miscellaneous</ns1:specimencomments>
<ns1:nonrxdrugsused>N/A</ns1:nonrxdrugsused>
<ns1:testcode>025000</ns1:testcode>
<ns1:testdate>2012-09-24</ns1:testdate>
<ns1:testresult>Negative</ns1:testresult>
<ns1:collectiondate>2012-09-25</ns1:collectiondate>
<ns1:lastname>Last</ns1:lastname>
<ns1:firstname>First</ns1:firstname>
<ns1:middlename>Middle</ns1:middlename>
<ns1:crudflag>C</ns1:crudflag>
</ns1:importdrugtest>
</soap-env:body>
</soap-env:envelope>
Here is my code. Note: I have already stared a new SoapClient() and regeived the token.
$ns = 'http://url.com/testing/';
// $headerParams = array('WSAuthorization'=>array('token'=>$token)); tried this also
$headerParams = array('token'=>$token);
$header = new SoapHeader($ns, 'WSAuthorization', $headerParams);
$client->__setSoapHeaders($header);
$param = array('ImportTest' => array(
'specimenID' => '0605431024',
'midasNumber' => '7700MD2005000001.00',
'county' => '03',
'site' => '00',
'specimenComments' => 'Miscellaneous',
'nonRXDrugsUsed' => 'N/A',
'testCode' => '025000',
'testDate' => '2012-09-24',
'testResult' => 'Negative',
'collectionDate' => '2012-09-25',
'lastName' => 'Last',
'firstName' => 'First',
'middleName' => 'Middle',
'CRUDFlag' => 'C'
));
$result = $client->__soapCall('ImportDrugTest', $param);
Update 12/31/14:
I modified the code and added print_r($header):
$ns = "http://url.com/testing/";
$headerParams = array('token'=>$token);
$header = new SoapHeader($ns, 'WSAuthorization', $headerParams);
print_r($header);
$client->__setSoapHeaders(array($header)); // even tried $client->__setSoapHeaders($header);
I get this:
SoapHeader Object
(
[namespace] => http://url.com/testing/
[name] => WSAuthorization
[data] => Array
(
[token] => UDjVSzGt9J4fKuRuoFHau3gy4CoLo//VlnuZv5oy5tjKPffIeSc+dx7EEDIfosVkVHDD0G/ZBANnCzPmRBo6CIusRL5rak5QdYI9jD7209c=
)
[mustUnderstand] =>
)
But __getLastRequest() gives me this:
<soap-env:header>
<ns1:wsauthorization />
</soap-env:header>
What am I missing?
This works:
$headerParams = array('Token' => $token);
$header = new SoapHeader($NameSpace, 'WSAuthorization', $headerParams, false);
The problem I was having was caused by the token not being parsed from the response.

Unwanted <param0> node from PHP SoapClient non-wsdl mode

I'm trying to make a request with the PHP SoapClient in non-WSDL mode. I'm passing parameters as a multi-dimensional object as shown in the below code snippet:
$params = new stdClass;
$params->Characteristic = new stdClass;
$params->Characteristic->Name = 'PRODUCT_TYPE';
$params->Characteristic->CharacteristicValue = new stdClass;
$params->Characteristic->CharacteristicValue->Value = $type;
$params->Characteristic->CharacteristicValue->Type = 'STRING';
$client = new SoapClient(NULL, array( 'trace' => true, 'exceptions' => true, 'uri' => $uri, 'location' => $location,
'connection_timeout'=>9999,
'features' => SOAP_SINGLE_ELEMENT_ARRAYS,
'soap_version' => SOAP_1_1, 'encoding' => 'ISO-8859-1',
'use' => SOAP_LITERAL
));
$response = $client->thisIsTheFunction($params);
The generated XML is almost right apart from being wrapped in a tag:
<soap-env:envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://[removed]">
<soap-env:body>
<ns1:thisisthefunction>
<param0>
<characteristic>
<name>PRODUCT_TYPE</name>
<characteristicvalue>
<value>Adhoc</value>
<type>STRING</type>
</characteristicvalue>
</characteristic>
</param0>
</ns1:thisisthefunction>
</soap-env:body>
</soap-env:envelope>
The problem is this is being detected as malformed by the service. Is there any way we can remove this extra tag?
I think if you want remove param0 and put characteristicValue in this place, you need to use a SoapParam (http://www.php.net/manual/en/class.soapparam.php).
In fact, your call must proceed like that :
$response = $client->thisIsTheFunction(new SoapParam($params->Characteristic, 'ns1:Characteristic'));
Now, your generated XML looks like that :
<soap-env:envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://[removed]">
<soap-env:body>
<ns1:thisisthefunction>
<ns1:characteristic>
<name>PRODUCT_TYPE</name>
<characteristicvalue>
<value>Adhoc</value>
<type>STRING</type>
</characteristicvalue>
</ns1:characteristic>
</ns1:thisisthefunction>
</soap-env:body>
Good luck !

How do I create this xml with PHP's SoapClient?

From debugging another application, I found that it sends the following xml to a soap server (code parts in this example are minimized, the xml is about 200 lines long:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:m0="http://schemas.ccs.nl/datacatalogus/modellen/modelrelatie">
<SOAP-ENV:Header>
<m:header xmlns:m="http://schemas.ccs.nl/soap">
<m:account>account</m:account>
<m:naam>naam_header</m:naam>
<m:wachtwoord>wachtwoord</m:wachtwoord>
<m:bedrijfsnummer>bedrijfsnummer</m:bedrijfsnummer>
<m:tussenpersoonnummer>tussenpersoonnummer</m:tussenpersoonnummer>
</m:header>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<m:RelatieMuteren xmlns:m="http://schemas.ccs.nl/services/relatieservice">
<m:relatie pc="W">
<m0:adres>adres</m0:adres>
</m:relatie>
</m:RelatieMuteren>
</SOAP-ENV:Body>
Obviously, the part between <m0:adres></m0:adres> is a lot larger and corresponds to my data that is stored in an array. However, if I try to send the request using __soapCall, PHP builds the following request:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns1="http://schemas.ccs.nl/datacatalogus/modellen/modelrelatie"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ns2="http://schemas.ccs.nl/services/relatieservice" xmlns:ns3="http://schemas.ccs.nl/soap">
<SOAP-ENV:Header>
<ns3:header>
<ns3:account>account</ns3:account>
<ns3:naam>naam</ns3:naam>
<ns3:wachtwoord>wachtwoord</ns3:wachtwoord>
<ns3:bedrijfsnummer>bedrijfsnummer</ns3:bedrijfsnummer>
<ns3:tussenpersoonnummer>tussenpersoonnummer</ns3:tussenpersoonnummer>
</ns3:header>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<ns2:RelatieMuteren>
<ns2:relatie pc="I">
<ns1:adres>Postbus 53</ns1:adres>
</ns2:relatie>
</ns2:RelatieMuteren>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
As you can see, the second xml is quite different from the first. Can anyone explain me why it is different and how I can create the first type of xml?
I use the following code to do the request:
$client = new SoapClient( "http://www.cdsverzekeringen.nl/ws_prod/services/RelatieService.asmx?WSDL", array( 'trace' => 1 ) );
$aHeader = array(
'account' => "PRIVATE",
'naam' => "PRIVATE",
'wachtwoord' => "PRIVATE",
'bedrijfsnummer' => "PRIVATE",
'tussenpersoonnummer' => "PRIVATE",
);
$client->__setSoapHeaders( new SoapHeader( "http://schemas.ccs.nl/soap", 'header', $aHeader ) );
$vtResult = $client->__soapCall( "RelatieMuteren", array( $aRelatieInfo ) );
The $aRelatieInfo array is formatted like this:
array
'relatie' =>
array
'adres' => string 'Postbus 53' (length=10)
I hope someone can help me out. Thanks in advance!
How about using SoabVar API like this,
$aHeader = '
<m:header xmlns:m="http://schemas.ccs.nl/soap">
<m:account>account</m:account>
<m:naam>naam_header</m:naam>
<m:wachtwoord>wachtwoord</m:wachtwoord>
<m:bedrijfsnummer>bedrijfsnummer</m:bedrijfsnummer>
<m:tussenpersoonnummer>tussenpersoonnummer</m:tussenpersoonnummer>
</m:header>';
$soap_var_header = new SoapVar( $aHeader , XSD_ANYXML, null, null, null);
$client->__setSoapHeaders( new SoapHeader( "http://schemas.ccs.nl/soap", 'm', $soap_var_header ) );

Creating a SOAP call using PHP with an XML body

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'));

Can't figure out how to create an XML SOAP Post in PHP

I searched for examples and more, but it won't work. I don't know how i can create the piece of "POST code" for my xml message. I think i need a soapclient but i dont exactly know how i use one.
The WSDL file address: https://secure.intelly.nl/webservices/intellymodule001.asmx?WSDL
This is the xml message i created:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
xmlns:tns="http://extranet.intelly.nl/module001/"
xmlns:s="http://www.w3.org/2001/XMLSchema"
xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" >
<SOAP-ENV:Body>
<tns:GetDomains xmlns:tns="http://extranet.intelly.nl/module001/">
<tns:credentials>
<ExternalProgramFunction>***</ExternalProgramFunction>
<ExternalProgramID>***</ExternalProgramID>
<Domain>***</Domain>
<Username>***</Username>
<Password>***</Password>
</tns:credentials>
<tns:message>
</tns:message>
<tns:message>
</tns:message>
<tns:searchParameters>
<OnlyActive>True</OnlyActive>
</tns:searchParameters>
</tns:GetDomains>
</SOAP-ENV:Body>
PHP has a native SoapClient, below is an example using your input structure:
$client = new SoapClient('https://secure.intelly.nl/webservices/intellymodule001.asmx?WSDL');
$params = array(
'credentials' => array(
'ExternalProgramFunction' => 'xxx',
'ExternalProgramID' => 'xxx',
'Domain' => 'xxx',
'UserName' => 'xxx',
'Password' => 'xxx'
),
'message' => array(),
'searchParameters' => array(
'OnlyActive' => true
)
);
$response = $client->GetDomains($params);
print_r($response);

Categories