PHP Pure XML in SOAP - php

I am trying to call an API using SOAPclient but the authentification fail because namespace missing in the xml
Excepted XML
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://tourico.com/webservices/" xmlns:trav="http://tourico.com/travelservices/">
<soapenv:Header>
<web:LoginHeader>
<trav:username>*****</trav:username>
<trav:password>*******</trav:password>
<trav:culture>en_US</trav:culture>
<trav:version>7.123</trav:version>
</web:LoginHeader>
</soapenv:Header>
<soapenv:Body>
<web:CancelReservation>
<web:nResID>1235456</web:nResID>
</web:CancelReservation>
</soapenv:Body>
</soapenv:Envelope>
What I am actualy sending (No namespace in the LoginHeader)
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://tourico.com/webservices/" xmlns:ns2="http://tourico.com/travelservices/">
<SOAP-ENV:Header>
<ns2:LoginHeader>
<username>******</username>
<password>*******</password>
<culture>en_US</culture>
<version>8.0</version>
</ns2:LoginHeader>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<ns1:CancelReservation>
<ns1:nResID>95665639</ns1:nResID>
</ns1:CancelReservation>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
My PHP code
$url = "http://demo-wsnew.touricoholidays.com/ReservationsService.asmx?wsdl";
$user = "*****";
$pwd = "********";
$culture = "en_US";
$version = "8.0";
$wsdl = $url;
$client = new SOAPClient($wsdl,array("trace" => true, "exceptions" => true, 'soap_version' => SOAP_1_1));
$login = new stdClass();
$login->usernam= $user;
$login->password = $pwd;
$login->culture = $culture;
$login->version = $version;
// Turn auth header into a SOAP Header
$header = new SoapHeader('http://tourico.com/travelservices', 'LoginHeader', $login, false);
// set the header
$client->__setSoapHeaders($header);
$r = new stdClass();
$r->nResID = 123456;
try
{
$res = $client->CancelReservation($r);
$results = json_decode(json_encode($res), true);
Log::error($client->__getLastRequest());
Log::error(print_r($results , true));
}
catch(Exception $e)
{
Log::error($client->__getLastRequest());
Log::error($e->getMessage());
}
Is there a way I could just send a XML string to the SOAPclient ?

You were missing a trailing slash on the namespace, so that was likely part of the problem.
This is a case where the classmap feature might help. Try this code:
$url = "http://demo-wsnew.touricoholidays.com/ReservationsService.asmx?wsdl";
$user = "*****";
$pwd = "********";
$culture = "en_US";
$version = "8.0";
$wsdl = $url;
class MyLoginHeader
{
public $username;
public $password;
public $culture;
public $version;
}
$classmap = array('LoginHeader' => 'MyLoginHeader');
$client = new SOAPClient($wsdl,array("classmap" => $classmap,"trace" => true, "exceptions" => true, 'soap_version' => SOAP_1_1));
$login = new MyLoginHeader();
$login->username = $user;
$login->password = $pwd;
$login->culture = $culture;
$login->version = $version;
// Turn auth header into a SOAP Header
$header = new SoapHeader('http://tourico.com/travelservices/', 'LoginHeader', $login, false);
// set the header
$client->__setSoapHeaders($header);
$r = new stdClass();
$r->nResID = 123456;
try
{
$res = $client->CancelReservation($r);
$results = json_decode(json_encode($res), true);
}
catch(Exception $e)
{
var_dump($client->__getLastRequest());
var_dump($e->getMessage());
}
The code produces an XML request that looks like:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns1="http://tourico.com/webservices/" xmlns:ns2="http://tourico.com/travelservices/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Header>
<ns2:LoginHeader xsi:type="ns2:LoginHeader">
<ns2:username>*****</ns2:username>
<ns2:password>********</ns2:password>
<ns2:culture>en_US</ns2:culture>
<ns2:version>8.0</ns2:version>
</ns2:LoginHeader>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<ns1:CancelReservation>
<ns1:nResID>123456</ns1:nResID>
</ns1:CancelReservation>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Related

How to receive Soap response in php

However, what I want is to be able to get response request and populate PHP
I already did that using soapUI and got the response in xml format like
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
<s:Header>
<a:Action s:mustUnderstand="1">http://bsestarmfdemo.bseindia.com/2016/01/IMFUploadService/MFAPIResponse</a:Action>
<a:RelatesTo>uuid:804ed18e-630f-4b16-86ee-6f97ee71743e</a:RelatesTo>
</s:Header>
<s:Body>
<MFAPIResponse xmlns="http://bsestarmfdemo.bseindia.com/2016/01/">
<MFAPIResult>100|PAYMENT NOT INITIATED FOR GIVEN ORDER</MFAPIResult>
</MFAPIResponse>
</s:Body>
</s:Envelope>
MY PHP Code
I don’t have much experience with SOAP but am required to build a validator for my work and using a specific SOAP wsdl.
I’ve set up the connect
<?php
$url= "http://bsestarmfdemo.bseindia.com/StarMFFileUploadService/StarMFFileUploadService.svc?wsdl";
$method = "MFAPI";
$error=0;
$fault=0;
$client = new SoapClient($url, array('soap_version' => SOAP_1_2 , 'SoapAction'=>'http://tempuri.org/IStarMFFileUploadService/MFAPI'));
$actionHeader= array();
$actionHeader[] = new SoapHeader('http://www.w3.org/2005/08/addressing',
'Action',
'http://tempuri.org/IStarMFFileUploadService/MFAPI');
$actionHeader[] = new SoapHeader('http://www.w3.org/2005/08/addressing',
'To',
'http://bsestarmfdemo.bseindia.com/MFUploadService/MFUploadService.svc/Basic');
$client->__setSoapHeaders($actionHeader);
$featchData = array('Param' => array('UserId' => 'xxxxx', 'Flag' => 'xxxx', 'EncryptedPassword' => 'xxxx', 'param' => 'xxxx') );
try{
$resultData = $client->__call($method, array($featchData));
}
catch (SoapFault $resultData) {
$error = 1;
}
if($error==1) {
$result=$fault;
}else{
$result = $resultData;
var_dump($result);
}
// echo $result;
?>

soap client error bad request

I need to use a webservice with php and I got the bad request error,
this is my code:
try{
$client = new \SoapClient("http://54.88.59.192/Cashier/SwCashier.asmx?wsdl");
$params = new \SoapVar('<?xml version="1.0" encoding="UTF-8"?><XMLTransaccion><DatosTransaccion><idTransaccion>06b09c6b-f9e3-4371-a3ef-4af947d2e488</idTransaccion><idServicio>0001</idServicio><tipoTransaccion>00</tipoTransaccion><fechaTransaccion>20160527015625</fechaTransaccion><usuarioRed>pagofacil</usuarioRed><passwordRed>123456PF</passwordRed><usuarioCaja>jperez</usuarioCaja><idCaja>0016</idCaja><idRed>6548</idRed></DatosTransaccion><DatosServicio><idCliente>pepe#gmail.com</idCliente><username>pepe</username><name>pepen</name><lastname>pepe#gmail.com</lastname></DatosServicio></XMLTransaccion>', XSD_ANYXML);
$res = $client->GetServiceTransaction($params);
$res->GetServiceTransactionResponse();
var_dump($res);
}catch(\soapFault $e){
var_dump($e);
}
And the Data should be sent by xml this is the request:
<?xml version="1.0" encoding="UTF-8"?>
<XMLTransaccion>
<DatosTransaccion>
<idTransaccion>06b09c6b-f9e3-4371-a3ef-4af947d2e488</idTransaccion>
<idServicio>0001</idServicio>
<tipoTransaccion>00</tipoTransaccion>
<fechaTransaccion>20160527015625</fechaTransaccion>
<usuarioRed>pagofacil</usuarioRed>
<passwordRed>123456PF</passwordRed>
<usuarioCaja>jperez</usuarioCaja>
<idCaja>0016</idCaja>
<idRed>6548</idRed>
</DatosTransaccion>
<DatosServicio>
<idCliente>pepe#gmail.com</idCliente>
<username>pepe</username>
<name>pepen</name>
<lastname>pepe#gmail.com</lastname>
</DatosServicio>
</XMLTransaccion>
Try to check validity of your request:
$client = new \SoapClient("http://54.88.59.192/Cashier/SwCashier.asmx?wsdl", array('trace' => 1));
$params = new \SoapVar('GetServiceTransaction($params);
echo "REQUEST:\n" . $client->__getLastRequest() . "\n";

Creating a SOAP header with PHP using SoapClient with security mode "TransportWithMessageCredential“

How can I construct a SOAP header using the "TransportWithMessageCredential" mode in PHP using the SoapClient. I'm using the SoapClient as this seems to be the best solution. The following is from the given documentation:
The Webservice uses the security mode "TransportWithMessageCredential“.
For secure transmission an SSL certificate is being used. Furthermore, for the security of the message exchange, a combination of username and password is required. The username and password are transmitted in the SOAP-Header.
Example:
<soapenv:Header>
<wsse:Security soapenv:mustUnderstand="1" xmlns:wsse="http://docs.oasisopen.
org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss wssecurityutility-1.0.xsd">
<wsse:UsernameToken wsu:Id="UsernameToken-37">
<wsse:Username>MyUsername</wsse:Username>
<wsse:Password Type="http://docs.oasisopen.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">MyPassword!</wsse:Password>
<wsse:Nonce EncodingType="http://docs.oasisopen.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">vAvnhyzl+yP8Yb8ZVdKnMw==</wsse:Nonce>
<wsu:Created>2014-03-17T13:08:02.795Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
Where "MyUserName" and "MyPassword!" ofc. is interchanged with the actual login information.
wsdl's are available for every functionality offered.
This class returns a header with the above defined format:)
class WsseAuthHeader extends SoapHeader
{
private $wssNs = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd';
private $wsuNs = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd';
private $passType = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText';
private $nonceType = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary';
private $username = 'Username';
private $password = 'Password';
function __construct()
{
$created = gmdate('Y-m-d\TH:i:s\Z');
$nonce = mt_rand();
$encodedNonce = base64_encode(pack('H*', sha1(pack('H*', $nonce) . pack('a*', $created) . pack('a*', $this->password))));
// Creating WSS identification header using SimpleXML
$root = new SimpleXMLElement('<root/>');
$security = $root->addChild('wsse:Security', null, $this->wssNs);
$usernameToken = $security->addChild('wsse:UsernameToken', null, $this->wssNs);
$usernameToken->addChild('wsse:Username', $this->username, $this->wssNs);
$passNode = $usernameToken->addChild('wsse:Password', htmlspecialchars($this->password, ENT_XML1, 'UTF-8'), $this->wssNs);
$passNode->addAttribute('Type', $this->passType);
$nonceNode = $usernameToken->addChild('wsse:Nonce', $encodedNonce, $this->wssNs);
$nonceNode->addAttribute('EncodingType', $this->nonceType);
$usernameToken->addChild('wsu:Created', $created, $this->wsuNs);
// Recovering XML value from that object
$root->registerXPathNamespace('wsse', $this->wssNs);
$full = $root->xpath('/root/wsse:Security');
$auth = $full[0]->asXML();
parent::SoapHeader($this->wssNs, 'Security', new SoapVar($auth, XSD_ANYXML), true);
}
};

SOAP function giving me a 500 error

I'm trying to connect to a soap api, but every time i try and call a function i get a 500 internal error.
I able able to call $client->__getFunctions() with out any issue, so i'm guessing that the code was able to connect to the soap server ok? I can see the function that i'm trying to call in the array:
GetCatalogFullResponse GetCatalogFull(GetCatalogFull $parameters)
heres my code:
$GUID = '000-000-000-000';
$user = 'user';
$pass = 'pass';
$url = 'https://example.net/webservices.asmx?WSDL';
$localCert = "cert.pem";
$options = array(
'local_cert' => $localCert,
'user' => $user,
'passphrase' =>$pass,
'soap_version' => SOAP_1_2,
);
try {
$client = new SoapClient($url, $options);
$result = $client->GetCatalogFull(['AccountGUID'=>$GUID,'UserLogin'=>$user]);
echo '<pre>';
print_r($client->__getFunctions());
} catch (SoapFault $fault) {
trigger_error("SOAP Fault: (faultcode: {$fault->faultcode}, faultstring: {$fault->faultstring})", E_USER_ERROR);
}
this is the request i am trying to make with the soap client class:
<?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:Body>
<GetCatalogFull xmlns="http://www.example.com">
<AccountGUID>string</AccountGUID>
<UserLogin>string</UserLogin>
</GetCatalogFull>
</soap12:Body>
</soap12:Envelope>

How to call web service with auth using php

I need to make a call to the webservice bellow, but so far failed to create the code for it.
https://www.nightline-delivers.com/ParcelMotel_UAT/RetailService.svc?wsdl
The request needs to look like the following:
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ret="Retail">
<soapenv:Header>
<UserName>WebServiceSample</UserName>
<Password>password</Password>
</soapenv:Header>
<soapenv:Body>
<ret:ValidateCredentials>
<ret:motelId>BAC032</ret:motelId>
<ret:mobileNumber>0865596800</ret:mobileNumber>
</ret:ValidateCredentials>
</soapenv:Body>
</soapenv:Envelope>
My code so far looks like this:
$client = new SoapClient("https://www.nightline-delivers.com/ParcelMotel_UAT/RetailService.svc?wsdl");
$location = new StdClass();
$location->motelId = 'BAC032';
$location->mobileNumber = '0866696800';
$auth = array(
'UserName'=>'WebServiceSample',
'Password'=>'password',
);
$header = new SoapHeader('NAMESPACE','Auth',$auth,false);
$client->__setSoapHeaders( $header );
try {
$response = $client->ValidateLocation( $location );
var_dump($response);
} catch( Exception $e ) {
echo $e->getMessage();
}
According to this it is impossible in PHP to get a header element without namespace (which is the case in your example) so that is not possible with SoapClient. However you may try to send request where both UserName and Password fields are in the Retail namespace, maybe server will accept this:
<?php
$client = new SoapClient("https://www.nightline-delivers.com/ParcelMotel_UAT/RetailService.svc?wsdl", array('trace' => TRUE));
$location = new StdClass();
$location->motelId = 'BAC032';
$location->mobileNumber = '0866696800';
$auth = array(
'UserName'=>'WebServiceSample',
'Password'=>'password',
);
$headers = array();
foreach($auth as $k=>$v) {
$headers[] = new SoapHeader('Retail', $k, $v);
}
$client->__setSoapHeaders( $headers );
try {
$response = $client->ValidateCredentials( $location );
var_dump($response);
} catch( Exception $e ) {
echo "REQUEST: ".$client->__getLastRequest();
echo $e->getMessage();
}
This code also will show you request if an exception occurs, and I have changed ValidateLocation to ValidateCredentials as in your example message. It produces following message:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="Retail">
<SOAP-ENV:Header>
<ns1:UserName>WebServiceSample</ns1:UserName>
<ns1:Password>password</ns1:Password>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<ns1:ValidateLocation>
<ns1:motelId>BAC032</ns1:motelId>
<ns1:mobileNumber>0866696800</ns1:mobileNumber>
</ns1:ValidateLocation>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
I got it working. Here is the code:
<?php
$username = 'WebServiceSample';
$password = 'password';
function formatXML($xml)
{
libxml_use_internal_errors(true);
$doc = new DOMDocument();
$doc->preserveWhiteSpace = false;
$doc->formatOutput = true;
$doc->loadXML($xml);
return $doc->saveXML();
}
try {
$client = new SoapClient("https://www.nightline-delivers.com/ParcelMotel_UAT/RetailService.svc?wsdl", array(
'trace' => true,
));
$headers = array();
$headers[] = new SoapHeader('Retail', 'UserName', 'WebServiceSample');
$headers[] = new SoapHeader('Retail', 'Password', 'password');
$client->__setSoapHeaders($headers);
$params = array(
'motelId' => 'BAz031',
'mobileNumber' => '0866696800'
);
$result = $client->__soapCall('ValidateLocation', array('ValidateLocation' => $params), array(
'location' => 'https://www.nightline-delivers.com/ParcelMotel_UAT/RetailService.svc/basic?APIKey=7C3A0EA9-C8D6-4DB0-ADF0-615BFD29DC1D'
));
} catch (SoapFault $e) {
exit($e->getMessage());
}
$request = $client->__getLastRequest();
$response = $client->__getLastResponse();
echo '<pre>';
echo htmlspecialchars( formatXML($request) );
echo "\n";
echo htmlspecialchars( formatXML($response) );

Categories