Ashik Basheer
Ashik Basheer

Reputation: 1601

PHP: Write SOAP request containing XML data and SOAPHeader

Hi I've got an issue with PHP SOAP request and I'm exhausted of the samples found on the web. Following is the request XML which i need to send.

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://schemas.navitaire.com/WebServices/ISessionManager/Logon</Action>
<h:ContractVersion xmlns:h="http://schemas.navitaire.com/WebServices">330</h:ContractVersion>
</s:Header>
<s:Body>
<LogonRequest xmlns="http://schemas.navitaire.com/WebServices/ServiceContracts/SessionService">
  <logonRequestData xmlns:d4p1="http://schemas.navitaire.com/WebServices/DataContracts/Session" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <d4p1:DomainCode>WWW</d4p1:DomainCode>
    <d4p1:AgentName>API****</d4p1:AgentName>
    <d4p1:Password>********</d4p1:Password>
    <d4p1:LocationCode i:nil="true" />
    <d4p1:RoleCode>APIB</d4p1:RoleCode>
    <d4p1:TerminalInfo i:nil="true" />
  </logonRequestData>
</LogonRequest>
</s:Body>
</s:Envelope>

The WSDL contains http://pastie.org/9263788

I have tried the following code

$test = array("DomainCode"=>"WWW","AgentName"=>"API****",
              "Password"=>"******","RoleCode"=>"APIB",
              "LocationCode"=>"","TerminalInfo"=>"");

$wsdl = "https://trtestr3xapi.navitaire.com/sessionmanager.svc?wsdl";

$client = new SoapClient($wsdl, array('trace' => 1,'exceptions' => true));

$header = new SoapHeader('http://schemas.navitaire.com/WebServices/ISessionManager/Logon','ContractVersion','330', '1');
$client->__setSoapHeaders($header);

try {    
$logon_request = $client->Logon($test);
print_r($logon_request);
echo "success!";
} catch (SoapFault $soap_error) {
echo $soap_error;
echo "error!";
}

I have generated the functions using $client->__getFunctions()

 array(4) {
 [0]=>
 string(54) "void ChangePassword(ChangePasswordRequest $parameters)"
 [1]=>
 string(45) "LogonResponse Logon(LogonRequest $parameters)"
 [2]=>
 string(38) "void Logout(LogoutRequest $parameters)"
 [3]=>
 string(75) "TransferSessionResponse TransferSession(TransferSessionRequest $parameters)"
 }

And the types are in this link http://pastie.org/9289906

The link https://trtestr3xapi.navitaire.com/SessionManager.svc?xsd=xsd3 contained in the WSDL has ContractVersion information

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://schemas.navitaire.com/WebServices" elementFormDefault="qualified" targetNamespace="http://schemas.navitaire.com/WebServices">
<xs:element name="ContractVersion" type="xs:int"/>
<xs:element name="LogonResponse">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="Signature" nillable="true" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Signature" nillable="true" type="xs:string"/>
</xs:schema>

CODE UPDATE

$wsdl = 'https://trtestr3xapi.navitaire.com/sessionmanager.svc?wsdl';
$header = new SoapHeader('http://schemas.navitaire.com/WebServices','ContractVersion','330', '1');

$ns_d4p1 = 'http://schemas.navitaire.com/WebServices/DataContracts/Session';
$ns_i = 'http://www.w3.org/2001/XMLSchema-instance';

$client = new SoapClient($wsdl, array('trace' => 1));
$client->__setSoapHeaders($header);

$logonResquestData = new SimpleXMLElement("<logonRequestData xmlns:i='$ns_i' xmlns:d4p1='$ns_d4p1' />");

$logonResquestData->addChild('d4p1:DomainCode', 'WWW', $ns_d4p1);
$logonResquestData->addChild('d4p1:AgentName', 'APISERANGOONAT', $ns_d4p1);
$logonResquestData->addChild('d4p1:Password', 'Newskies-1', $ns_d4p1);
$logonResquestData->addChild('d4p1:LocationCode', null, $ns_d4p1)->addAttribute('i:nil', 'true', $ns_i);
$logonResquestData->addChild('d4p1:RoleCode', 'APIB', $ns_d4p1);
$logonResquestData->addChild('d4p1:TerminalInfo', null, $ns_d4p1)->addAttribute('i:nil', 'true', $ns_i);

//var_dump($logonResquestData->asXML());

$logon_request = $client->Logon($logonResquestData);

return $logon_request;

The above code throws the following error

Fatal error: Uncaught SoapFault exception: [a:InternalServiceFault] LogonRequest.AgentName:LengthStringAttribute: The value of LogonRequest.AgentName:LengthStringAttribute is empty, but is not optional. in C:\Inetpub\vhosts\ezyflying.com\tiger\x.php:22 Stack trace: #0 C:\Inetpub\vhosts\ezyflying.com\tiger\x.php(22): SoapClient->__call('Logon', Array) #1 C:\Inetpub\vhosts\ezyflying.com\tiger\x.php(22): SoapClient->Logon(Object(SimpleXMLElement)) #2 {main} thrown in C:\Inetpub\vhosts\ezyflying.com\tiger\x.php on line 22

Upvotes: 2

Views: 2040

Answers (1)

helderdarocha
helderdarocha

Reputation: 23637

The error says that the header ContractVersion from the namespace you used when declaring the header "was not understood". That's because there is probably no ContractVersion element declared in the schema for this target namespace.

According to your SOAP request ContractVersion belongs to another namespace:

<h:ContractVersion xmlns:h="http://schemas.navitaire.com/WebServices">

You should use that namespace when adding the header:

$header = new SoapHeader('http://schemas.navitaire.com/WebServices','ContractVersion','330', '1');

As for your LogonRequest data, according to the result you expect to generate you will need to add a LogonRequestData object to it. Your schema is not available and I don't know the exact syntax using the PHP API. One way would be to add the payload as literal XML. You might have to set some configuration in your SOAP client for this and I'm not sure if this is the standard recommended procedure for PHP. If you can send literal XML, then you can build a <logonRequestData> object like the one you posted using the code below:

$ns_d4p1 = 'http://schemas.navitaire.com/WebServices/DataContracts/Session';
$ns_i = 'http://www.w3.org/2001/XMLSchema-instance';

$logonResquestData = new SimpleXMLElement("<logonRequestData xmlns:i='$ns_i' xmlns:d4p1='$ns_d4p1' />");

$logonResquestData->addChild('d4p1:DomainCode', 'WWW', $ns_d4p1);
$logonResquestData->addChild('d4p1:AgentName', 'API****', $ns_d4p1);
$logonResquestData->addChild('d4p1:Password', '****', $ns_d4p1);
$logonResquestData->addChild('d4p1:LocationCode', null, $ns_d4p1)->addAttribute('i:nil', 'true', $ns_i);
$logonResquestData->addChild('d4p1:RoleCode', 'APIB', $ns_d4p1);
$logonResquestData->addChild('d4p1:TerminalInfo', null, $ns_d4p1)->addAttribute('i:nil', 'true', $ns_i);

You can check if the code above generates the correct XML by printing:

print_r($logonResquestData->asXML());

Now you have to add that object to your LogonRequest object by passing it as a parameter to your Logon operation somehow. I'm not sure about the exact syntax. You might need to add a SoapParam or a SoapVar. You suggested using an array. Whatever the method, you have to test it and see if it generates the correct XML before attempting to send it. It will be easier to debug that way.

Upvotes: 1

Related Questions