PHP SOAP complex types - php

I have a working XML request body, which I'm trying to send via PHP to a SOAP server:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="urn:servicewsdl" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<mns:getQuote xmlns:mns="urn:getquoteswsdl" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<authorisation xsi:type="tns:Authorisation">
<username xsi:type="xsd:string">****</username>
<password xsi:type="xsd:string">****</password>
</authorisation>
<symbol xsi:type="xsd:string">****</symbol>
</mns:getQuote>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
I tried passing the params in an array like so:
$result = $client->getQuote(array('username' => '****', 'password' => '****'), array('symbol' => '****'));
but it returns me an error:
SOAP-ERROR: Encoding: object has no 'username' property

you probably need to put the username/password array inside authorisation like:
$result = $client->getQuote(array('authorisation'=>array('username' => '****', 'password' => '****')), array('symbol' => '****'));
or, maybe you should send it an object instead:
$params = new stdClass();
$params->authorisation = new stdClass();
$params->authorisation->username = '****';
$params->authorisation->password = '****';
$params->symbol = '****';
$result = $client->getQuote($params);
EDIT: From the comments, in the end, getQuote was accessed via PHP in this method:
$auth = new stdClass();
$auth->username = '****';
$auth->password = '****';
$symbol = '****';
$result = $client->getQuote($auth, $symbol);

I had a heck of a time working with PHP and SOAP as well. I seem to recall a similar situation where I used the standard PHP class (new stdClass()) to help build the object with params. Here's the questions/answer page.
How can I add Attributes to a PHP SoapVar Object?
I hope it helps.

Related

SOAP-ERROR: Encoding: object has no 'ACCION' property

I have a PHP script which calls a web service created in SAP, I already validated it with soapui5 and it works fine, but PHP throws the following message:
SOAP-ERROR: Encoding: object has no 'ACCION' property
PHP code :
$url = 'https://www.ceramicaitalia.com/wssap/zwebservice1.wsdl';
$client = new SoapClient($url);
echo PHP_EOL;
$xmlr = new SimpleXMLElement("<ZWS_WEBSERVICE1></ZWS_WEBSERVICE1>");
$xmlr->addChild('login', '***');
$xmlr->addChild('password', '******');
$xmlr->addChild('ACCION', '/');
$params = new stdClass();
$params->xml = $xmlr->asXML();
$client->ZWS_WEBSERVICE1($params);
$result = $client->ZWS_WEBSERVICE1('RTA');
print_r($result);
Test in soapui5 :
Request :
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
xmlns:urn="urn:sap-com:document:sap:rfc:functions">
<soap:Header/>
<soap:Body>
<urn:ZWS_WEBSERVICE1>
<ACCION>/</ACCION>
</urn:ZWS_WEBSERVICE1>
</soap:Body>
</soap:Envelope>
Response :
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
<env:Header/>
<env:Body>
<n0:ZWS_WEBSERVICE1Response xmlns:n0="urn:sap-com:document:sap:rfc:functions">
<RTA>1.5</RTA>
</n0:ZWS_WEBSERVICE1Response>
</env:Body>
</env:Envelope>
You don't need to set root element. You can to xml as array param. Library will auto set matched elements. If you have multiple element with same name but different namespace you can check SoapVar. Working sample is below.
<?php
$url = 'https://www.ceramicaitalia.com/wssap/zwebservice1.wsdl';
$client = new SoapClient($url, ['trace' => true]);
$params = ['ACCION' => '/'];
$client->ZWS_WEBSERVICE1($params);
$result = $client->ZWS_WEBSERVICE1('RTA');
print_r($result);
?>

Change format of the output XML , generated from PHP SoapClient?

I am trying to create this :
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<AccessKey xmlns="http://eatright/membership" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Value>67a4ef47-9ddf-471f-b6d0-0000c28d57d1</Value>
</AccessKey>
</s:Header>
<s:Body>
<WebUserLogin xmlns="http://eatright/membership">
<loginOrEmail>1083790</loginOrEmail>
<password>thomas</password>
</WebUserLogin>
</s:Body>
</s:Envelope>
I created this PHP code
class ChannelAdvisorAuth
{
public $AccessKey ;
public function __construct($key)
{
$this->AccessKey = $key;
}
}
$AccessKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
$url = "http://ws.eatright.org/service/service.svc?wsdl";
$client = new SoapClient($url, array("trace" => 1, "exception" => 0));
$auth = new ChannelAdvisorAuth($AccessKey);
$header = new SoapHeader("AccessKey", "Value", $AccessKey, false);
$client->__setSoapHeaders($header);
$result = $client->ValidateAccessKey();
echo "REQUEST:\n" . $client->__getLastRequest() . "\n";
The output of the above PHP code is :
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://eatright/membership" xmlns:ns2="AccessKey">
<SOAP-ENV:Header>
<ns2:Value>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</ns2:Value>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<ns1:ValidateAccessKey/>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
How to change the PHP code to output the XML as requested by web service provider?
How to replace the "SOAP-ENV" to "S"?
Is there is a way to remove the NS1 and NS2? and also adjust the whole format of the XML to meet the requirements? thanks
You don't need to worry about SOAP-ENV, ns1 or ns2 - they are just prefixes referring to the namespaces. As long as the full namespaces are correct, it's going to be alright.
I think the SOAP header should be made like this:
$access_key = new stdClass();
$access_key->Value = 'XXX';
$hdr = new SoapHeader('http://eatright/membership', 'AccessKey', $access_key);
$client->__setSoapHeaders($hdr);
I don't see a purpose of xmlns:i in the first example - there are no elements having XSI attributes.
I'm not sure what to do with the body. In your first example, there is a call to the WebUserLogin operation, while in your PHP code you are trying to call ValidateAccessKey.
Have you tried reading the WSDL file which is pointed by $url
Ok I found the problem and I will add it here in case someone looking for same issue.
$access_key = new stdClass();
$access_key->Value = 'xxxxxxxxxxxxxxxxxxx';
// Create the SoapClient instance
$url = "http://ws.eatright.org/service/service.svc?wsdl";
$client = new SoapClient($url, array("trace" => 1, "exception" => 0));
$hdr = new SoapHeader('http://eatright/membership', 'AccessKey', $access_key);
$client->__setSoapHeaders($hdr);
$soapParameters = array('loginOrEmail ' => $username, 'password' => $password);
$login = new stdClass();
$login->loginOrEmail='LoginID';
$login->password='Password';
$result = $client->WebUserLogin($login);

PHP and a soap call with a complex parameter

I'm trying to pass a fairly complex parameter string which I have an XML example of and I'm trying to encode it properly using PHP. The example request I was given is this:
<?xml version="1.0" standalone="no"?>
<SOAP-ENV:Envelope xmlns:SOAPSDK1="http://www.w3.org/2001/XMLSchema" xmlns:SOAPSDK2="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAPSDK3="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body xmlns:tns="http://172.16.53.121/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:ns="http://www.amtrak.com/TrainStatus/2006/01/01" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:wsdns1="http://www.amtrak.com/schema/2006/01/01" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<TrainStatusRQ xmlns="http://www.amtrak.com/schema/2006/01/01" xmlns:ota="http://www.opentravel.org/OTA/2003/05" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Version="1.0" EchoToken="TestToken">
<POS>
<ota:Source>
<ota:RequestorID Type="WAS" ID="ToBeProvidedByAmtrak">
<ota:CompanyName CompanyShortName="ToBeProvidedByAmtrak"/>
</ota:RequestorID>
</ota:Source>
</POS>
<TrainStatusInfo TrainNumber="3">
<TravelDate>
<ota:DepartureDateTime>2006-01-07</ota:DepartureDateTime>
</TravelDate>
<Location LocationCode="KNG"/>
</TrainStatusInfo>
</TrainStatusRQ>
</SOAP-ENV:Body>
And I'm going to call it use it like this
try
{
$client = new SoapClient($soapURL, $soapOptions);
$trainStatus = $client->processTrainStatus($TrainStatusRQ);
var_dump($trainStatus);
//var_dump($client->__getTypes());
}
catch(SoapFault $e)
{
echo "<h2>Exception Error!</h2></b>";
echo $e->faultstring;
}
Its the encoding of $TrainStatusRQ that I cant seem to figure out since there are attributes and multilevel parameters. This is as close as I have gotten.
$RQStruc = array(
"POS" => array(
"Source"=> array(
"RequestorID" => array(
'type'=>'WAS',
'ID'=>'0',
'CompanyName'=>array(
'CompanyShortName'=>"0"
)
)
)
),
"TrainStatusInfo" => array(
'TrainNumber'=>$TrainNumber,
'TravelDate' => array(
'DepartureDateTime' => array(
'_' => $today
)
),
"Location" => array(
'LocationCode'=>$LocationCode
)
)
);
$TrainStatusRQ = new SoapVar($RQStruc, XSD_ANYTYPE, "TrainStatusRQ","http://www.amtrak.com/schema/2006/01/01" );
I had similar problems when dealing with a .NET service.
What I ended up with was assembling the structure as plain string.
$p = array();
foreach ($items as $item) {
$p[] = "
<MyEntity class='entity'> // the attribute was required by .NET
<MyId>{$item->SomeID}</MyId>
<ItemId>{$item->ItemId}</ItemId>
<Qty>{$item->Qty}</Qty>
</MyEntity>";
}
$exp = implode("\n", $p);
$params['MyEntity'] = new \SoapVar("<MyEntity xmlns='http://schemas.microsoft.com/dynamics/2008/01/documents/MyEntity'>$exp</MyEntity>", XSD_ANYXML);
Worked without problems.
Passing in the XML as a string with XSD_ANYXML as the type was the answer. I also needed to leave out the third and fourth parameters in the SoapVar() function call.
$XML = '<TrainStatusRQ xmlns="http://www.amtrak.com/schema/2006/01/01" xmlns:ota="http://www.opentravel.org/OTA/2003/05" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Version="1.0" EchoToken="TestToken">
<POS>
<ota:Source>
<ota:RequestorID Type="WAS" ID="foo">
<ota:CompanyName CompanyShortName="bat"/>
</ota:RequestorID>
</ota:Source>
</POS>
<TrainStatusInfo TrainNumber="'.$TrainNumber.'">
<TravelDate>
<ota:DepartureDateTime>'.$Today.'</ota:DepartureDateTime>
</TravelDate>
</TrainStatusInfo>
</TrainStatusRQ>';
$TrainStatusRQ = new SoapVar($XML,XSD_ANYXML);

Create this SOAP XML request with PHP's SOAP extension

I'm trying to recreate this XML request using PHP's SOAP extension and having trouble doing it:
<?xml version="1.0"?>
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://services.web.stormpost.skylist.com">
<soapenv:Header>
<authInfo xmlns:soap="http://skylist.com/services/SoapRequestProcessor" xsi:type="soap:authentication">
<!--You may enter the following 2 items in any order-->
<username xsi:type="xsd:string">****#example.com</username>
<password xsi:type="xsd:string">*******</password>
</authInfo>
</soapenv:Header>
<soapenv:Body>
<ser:doImportFromTemplate soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<impTempId xsi:type="xsd:int">7</impTempId>
<data xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="soapenc:string">
Joe|Doe|joe#example.com John|Doe|john#example.com </data>
</ser:doImportFromTemplate>
</soapenv:Body>
</soapenv:Envelope>
Here is my testing code so far:
// set connection params
$wsdl = 'http://api.stormpost.datranmedia.com/services/SoapRequestProcessor?wsdl';
$namespace = 'https://api.stormpost.datranmedia.com/services/SoapRequestProcessor';
$credentials = (object)array(
'username' => '****#example.com',
'password' => '*******'
);
$auth_values = new SoapVar($credentials, SOAP_ENC_OBJECT);
$header = new SoapHeader($namespace, "authInfo", $auth_values);
// set client, headers, and call function
$client = new SoapClient($wsdl, array('trace' => true));
$client->__setSoapHeaders(array($header));
$client->__soapCall("doImportFromTemplate", array(7, 'Joe|Doe|joe#example.com John|Doe|john#example.com'));
It doesn't seem to be implementing the authInfo node correctly with the xsi:type="soap:authentication" among other things. How should I change my code to output this XML? I'm having trouble finding good implementation examples.
I struggled with the php SOAP client myself a while ago, i didn't really got a full understanding but this worked for me:
$auth_values = array('username' => '****#example.com', 'password' => '*******');
$header = new SoapHeader($namespace, "authInfo", $auth_values, false);
// set client, headers, and call function
$client = new SoapClient($wsdl, array('trace' => true));
$client->__setSoapHeaders(array($header));

PHP SOAP Header construction

So basically I want the SOAP header to be like this:
<soapenv:Header>
<v1:loginDetails>
<v11:Id>0</v11:Id>
<v11:username>MEMBERS</v11:username>
$ <v11:password>0x909711E5,0xE301F82A,0x0E2783CC,0xAF6BC3DB,0x57727CFB</v11:password>
</v1:loginDetails>
</soapenv:Header>
<soapenv:Body>
<v11:GetNextAvailableMemberNumberRequest>
<v11:Id>1</v11:Id>
<v11:memberId>1</v11:memberId>
</v11:GetNextAvailableNumberRequest>
</soapenv:Body>
</soapenv:Envelope>
But instead, now I have this:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www..com/membership/types/v1_0">
<SOAP-ENV:Header>
<ns1:loginDetails>
<item><key>siteId</key><value>0</value></item>
<item><key>Username</key><value>MEMBERSHIP</value></item>
<item><key>Password</key><value>P#ssw0rd</value></item>
</ns1:loginDetails>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<ns1:GetNextAvailableMemberNumberRequest/>
<param1>1</param1>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
And this is the php code that I'm currently using:
$client = new SOAPClient('http://192.168.180.128:8010//membershipService?wsdl',array('trace' => true));
$client->__setSoapHeaders(null);
$headerbody = array ('siteId' => '0','Username' => 'MEMBERSHIP',
'Password' => 'P#ssw0rd');
$header = new SOAPHeader('http://www.com/club/services/membership/types/v1_0','loginDetails',$headerbody);
$client->__setSoapHeaders($header);
Where have I gone wrong? I seems unable to construct the header properly.
Just try to use an anonymous class instead of an array :
// Use standard class and set magic properties.
$header = new stdClass();
$header->siteId = '0';
$header->Username = 'MEMBERSHIP';
$header->Password = 'P#ssw0rd';
Casting the array of parameters to an object works pretty well
$auth = (object)array(
'Username' => 'AzureDiamond',
'Password' => 'hunter2',
);
$header = new SOAPHeader('http://my.ns/','loginDetails',$auth);
However, I find that it still doesn't get namespaces quite right. The above produces
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns2="http://my.ns/">
<SOAP-ENV:Header>
<ns2:loginDetails>
<Username>AzureDiamond</Username>
<Password>hunter2</Password>
</ns2:loginDetails>
</SOAP-ENV:Header>
....
And you'll see that although the 'loginDetails' tag is in the requested namespace, it's child elements are not.
I just encountered a very similar problem.
To fix it, you need to use the SoapVar class. This allows you to control what namespace to use for each tag.
$client = new SOAPClient('http://192.168.180.128:8010//membershipService?wsdl',array('trace' => true));
$ns = 'http://www.com/club/services/membership/types/v1_0';
$headerbody = new SoapVar([
new SoapVar('0', XSD_STRING, null, null, 'siteId', $ns),
new SoapVar('MEMBERSHIP', XSD_STRING, null, null, 'Username', $ns),
new SoapVar('P#ssw0rd', XSD_STRING, null, null, 'Password', $ns),
], SOAP_ENC_OBJECT);
$header = new SOAPHeader($ns,'loginDetails',$headerbody);
$client->__setSoapHeaders($header);
Your request's soap header should look something like this with this:
<SOAP-ENV:Header>
<ns1:loginDetails>
<ns1:siteId>0</ns2:siteId>
<ns1:Username>MEMBERSHIP</ns2:Username>
<ns1:Password>P#ssw0rd</ns2:Password>
</ns1:loginDetails>
</SOAP-ENV:Header>
There was typo:
$header = NEW stdClass() ;
$headerbody = array ('Id' => '0','username' => 'MEMBERSHIP',
'password' => 'P#ssw0rd');
Please refer the link
http://php.net/manual/en/class.soapheader.php
Also make sure that you are passing correct namespace (first parameter) in SOAPHeader constructor

Categories