diff --git a/README.md b/README.md
index e5869eb20..eb0251f35 100644
--- a/README.md
+++ b/README.md
@@ -14,7 +14,7 @@ The Amadeus documentation portal can be found at https://webservices.amadeus.com
* PHP 5.4+
* SOAP and XSL extensions activated
-* A WSDL & authentication details from Amadeus
+* A WSDL & authentication details from Amadeus _(SoapHeader 4 or SoapHeader 2)_
# Installation
diff --git a/docs/about-get-started.rst b/docs/about-get-started.rst
index 411b8998a..5717d6771 100644
--- a/docs/about-get-started.rst
+++ b/docs/about-get-started.rst
@@ -11,7 +11,7 @@ See `the Amadeus Web Services website `_ for m
The basic pieces of information you will need to use this library are:
- **The WSDL file with all its includes**: You can just extract the ZIP file you received from Amadeus to a location on your filesystem where the client can access it.
-- **The authentication information required to start a session**: Office ID's, User Id (=Originator), Password, Duty Code. *For legacy WSAP's using Soap Header 1 or 2, you'll need: Office ID, Originator, Organization ID, Password Length, Password Data. Soap Header 1 & 2 is not yet implemented in this library*
+- **The authentication information required to start a session**: Office ID's, User Id (=Originator), Password, Duty Code. *For legacy WSAP's using Soap Header 1 or 2, you'll need: Office ID, Originator, Organization ID, Password Length, Password Data. Soap Header 1 is not yet implemented in this library*
You usually receive this information after the project kick-off has been done and a support person has been assigned to your project.
@@ -20,9 +20,12 @@ Support for Amadeus Soap Header versions
****************************************
Upon receiving access, Amadeus will give you a Web Service Access Point with a specific Soap Header version to use. This will define how you can handle session management *(e.g. support for stateless calls, requiring session pooling or not)*.
-This library is initially built to support the current Soap Header v4, which is the Soap Header Version you would get for a new WSAP requested today (2016).
+This library is built to support the current **Soap Header 4** and the legacy **Soap Header 2**.
-Legacy applications using already certified WSAP's can still be running on legacy Soap Header versions - most notably Soap Header 1 & 2. This library currently doesn't support those yet, but we plan to add that in the future.
+- Soap Header 4 is the Soap Header Version you would get for a new WSAP requested today (2016).
+- Soap Header 2 is still in use in legacy applications.
+
+Legacy applications using already certified WSAP's can still be running on legacy Soap Header versions (Soap Header 1 & 2). This library doesn't support Soap Header 1 at the moment.
******************************************
Support for different versions of messages
@@ -52,6 +55,8 @@ Install the client library in your PHP project by requiring the package with Com
Set up a test client
********************
+Soap Header 4 example:
+
.. code-block:: php
'ABC123'])
);
+Soap Header 2 example:
+
+.. code-block:: php
+
+ [
+ 'soapHeaderVersion' => Client::HEADER_V2,
+ 'wsdl' => '/home/user/mytestproject/data/amadeuswsdl/1ASIWXXXXXX_PDT_20110101_080000.wsdl', //Points to the location of the WSDL file for your WSAP. Make sure the associated XSD's are also available.
+ 'logger' => new Psr\Log\NullLogger(),
+ 'authParams' => [
+ 'officeId' => 'BRUXX1111', //The Amadeus Office Id you want to sign in to - must be open on your WSAP.
+ 'userId' => 'WSBENXXX', //Also known as 'Originator' for Soap Header 1 & 2 WSDL's
+ 'passwordData' => 'dGhlIHBhc3N3b3Jk' // **base 64 encoded** password
+ 'passwordLength' => 12,
+ 'dutyCode' => 'SU',
+ 'organizationId' => 'DUMMY-ORG',
+ ]
+ ],
+ 'requestCreatorParams' => [
+ 'receivedFrom' => 'my test project' // The "Received From" string that will be visible in PNR History
+ ]
+ ]);
+
+ $client = new Client($params);
+
+ $authResult = $client->securityAuthenticate();
+
+ if (isset($authResult->processStatus->statusCode) && $authResult->processStatus->statusCode === 'P') {
+ //We are authenticated!
+ $pnrContent = $client->pnrRetrieve(
+ new PnrRetrieveOptions(['recordLocator' => 'ABC123'])
+ );
+ }
+
******************
Messages supported
@@ -92,6 +139,7 @@ Messages supported
This is the list of messages that are at least partially supported at this time:
+- Security_Authenticate
- Security_SignOut
- PNR_Retrieve
- PNR_RetrieveAndDisplay
@@ -135,5 +183,3 @@ On the to-do list / work in progress:
- Ticket_DisplayTST
- Ticket_DeleteTST
- SalesReports_DisplayQueryReport
-
-- Support for SoapHeader V2
diff --git a/docs/samples.rst b/docs/samples.rst
index 57f6ebeb6..cac15d1fc 100644
--- a/docs/samples.rst
+++ b/docs/samples.rst
@@ -4,9 +4,9 @@ EXAMPLES
Here are some examples of how you can handle some problems you might encounter and how to send specific messages.
-***********************************************
-Switching between stateful & stateless messages
-***********************************************
+***************************************************************
+Switching between stateful & stateless messages (Soap Header 4)
+***************************************************************
If you do not require an active context in your session, you're better off using stateless messages.
@@ -38,9 +38,9 @@ It's also possible to specify the default stateful setting at construction time
$client = new Client($params);
-*************************
-Ending a stateful session
-*************************
+*****************************************
+Ending a stateful session (Soap Header 4)
+*****************************************
After doing multiple calls with a stateful session, there are two ways to end the session:
@@ -59,6 +59,30 @@ After doing multiple calls with a stateful session, there are two ways to end th
['endSession' => true]
);
+************************************
+Handling sessions with Soap Header 2
+************************************
+
+Soap Header 2 based applications are a bit more cumbersome to handle in order to get a successful certification:
+
+- you need to implement session pooling in order to limit the number of session creation/destruction events
+- you need to enforce your maximum number of concurrent sessions
+- you need to send a separate authentication message before you can do anything
+
+This library does not provide any session pooling mechanism, you'll have to implement this yourself.
+
+You can get a current session's info (for later re-use) by calling
+
+.. code-block:: php
+
+ $client->getSessionData();
+
+You can restore a previous current session after you retrieved it from your session pool for later re-use:
+
+.. code-block:: php
+
+ $client->setSessionData($previousSessionData);
+
*********************
Handling the response
diff --git a/src/Amadeus/Client.php b/src/Amadeus/Client.php
index 000f1cd00..2aab39114 100644
--- a/src/Amadeus/Client.php
+++ b/src/Amadeus/Client.php
@@ -36,8 +36,7 @@
* Amadeus Web Service Client.
*
* TODO:
- * - have a solution for session pooling for stateful sessions (soapheader 1 & 2)
- * - support older versions of SoapHeader (1, 2)
+ * - support older versions of SoapHeader (1)
* - implement calls for full online booking flow:
* SalesReports_DisplayQueryReport
* Air_MultiAvailability
@@ -97,6 +96,13 @@ class Client
*/
protected $responseHandler;
+ /**
+ * Authentication parameters
+ *
+ * @var Params\AuthParams
+ */
+ protected $authParams;
+
/**
* Set the session as stateful (true) or stateless (false)
*
@@ -149,6 +155,19 @@ public function getLastResponse()
return $this->sessionHandler->getLastResponse();
}
+ /**
+ * Restore a previously used session
+ *
+ * To be used when implementing your own session pooling system on legacy Soap Header 2 applications.
+ *
+ * @param array $sessionData
+ * @return bool
+ */
+ public function setSessionData(array $sessionData)
+ {
+ return $this->sessionHandler->setSessionData($sessionData);
+ }
+
/**
* Construct Amadeus Web Services client
*
@@ -156,6 +175,13 @@ public function getLastResponse()
*/
public function __construct($params)
{
+ if ($params->authParams instanceof Params\AuthParams) {
+ $this->authParams = $params->authParams;
+ if (isset($params->sessionHandlerParams) && $params->sessionHandlerParams instanceof Params\SessionHandlerParams) {
+ $params->sessionHandlerParams->authParams = $this->authParams;
+ }
+ }
+
$this->sessionHandler = $this->loadSessionHandler(
$params->sessionHandler,
$params->sessionHandlerParams
@@ -174,6 +200,31 @@ public function __construct($params)
);
}
+ /**
+ * Authenticate.
+ *
+ * Parameters were provided at construction time (sessionhandlerparams)
+ *
+ * @return \stdClass
+ * @throws Exception
+ */
+ public function securityAuthenticate()
+ {
+ $msgName = 'Security_Authenticate';
+ $messageOptions = $this->makeMessageOptions([], false, false);
+
+ return $this->sessionHandler->sendMessage(
+ $msgName,
+ $this->requestCreator->createRequest(
+ $msgName,
+ new RequestOptions\SecurityAuthenticateOptions(
+ $this->authParams
+ )
+ ),
+ $messageOptions
+ );
+ }
+
/**
* Terminate a session - only applicable to non-stateless mode.
*
diff --git a/src/Amadeus/Client/Params.php b/src/Amadeus/Client/Params.php
index 55a045fb8..0a5da35a6 100644
--- a/src/Amadeus/Client/Params.php
+++ b/src/Amadeus/Client/Params.php
@@ -22,6 +22,7 @@
namespace Amadeus\Client;
+use Amadeus\Client\Params\AuthParams;
use Amadeus\Client\Params\RequestCreatorParams;
use Amadeus\Client\Params\SessionHandlerParams;
use Amadeus\Client\RequestCreator\RequestCreatorInterface;
@@ -57,6 +58,13 @@ class Params
*/
public $responseHandler;
+ /**
+ * Parameters for authenticating to the Amadeus Web Services
+ *
+ * @var Params\AuthParams
+ */
+ public $authParams;
+
/**
* Parameters required to create the Session Handler
*
@@ -72,7 +80,6 @@ class Params
public $requestCreatorParams;
-
/**
* @param array $params
*/
@@ -98,6 +105,14 @@ protected function loadFromArray(array $params) {
$this->responseHandler = $params['responseHandler'];
}
+ if (isset($params['authParams'])) {
+ if ($params['authParams'] instanceof AuthParams) {
+ $this->authParams = $params['authParams'];
+ } elseif (is_array($params['authParams'])) {
+ $this->authParams = new AuthParams($params['authParams']);
+ }
+ }
+
if (isset($params['sessionHandlerParams'])) {
if ($params['sessionHandlerParams'] instanceof SessionHandlerParams) {
$this->sessionHandlerParams = $params['sessionHandlerParams'];
diff --git a/src/Amadeus/Client/RequestCreator/Base.php b/src/Amadeus/Client/RequestCreator/Base.php
index a042a560a..f7a8cb714 100644
--- a/src/Amadeus/Client/RequestCreator/Base.php
+++ b/src/Amadeus/Client/RequestCreator/Base.php
@@ -50,6 +50,7 @@
use Amadeus\Client\RequestOptions\QueuePlacePnrOptions;
use Amadeus\Client\RequestOptions\QueueRemoveItemOptions;
use Amadeus\Client\RequestOptions\RequestOptionsInterface;
+use Amadeus\Client\RequestOptions\SecurityAuthenticateOptions;
use Amadeus\Client\RequestOptions\TicketCreateTstFromPricingOptions;
use Amadeus\Client\Struct;
@@ -110,6 +111,17 @@ protected function createSecuritySignOut()
return new Struct\Security\SignOut();
}
+ /**
+ * Create request object for Security_Authenticate message
+ *
+ * @param SecurityAuthenticateOptions $params
+ * @return Struct\Security\Authenticate
+ */
+ protected function createSecurityAuthenticate(SecurityAuthenticateOptions $params)
+ {
+ return new Struct\Security\Authenticate($params);
+ }
+
/**
* Create request object for PNR_Retrieve message
*
diff --git a/src/Amadeus/Client/RequestOptions/SecurityAuthenticateOptions.php b/src/Amadeus/Client/RequestOptions/SecurityAuthenticateOptions.php
new file mode 100644
index 000000000..17269a262
--- /dev/null
+++ b/src/Amadeus/Client/RequestOptions/SecurityAuthenticateOptions.php
@@ -0,0 +1,114 @@
+
+ */
+class SecurityAuthenticateOptions extends Base
+{
+ /**
+ * The Amadeus Office ID to sign in to
+ *
+ * @var string
+ */
+ public $officeId;
+
+ /**
+ * User ID / Originator
+ *
+ * @var string
+ */
+ public $userId;
+
+ /**
+ * Originator Typecode
+ *
+ * @var string
+ */
+ public $originatorTypeCode;
+
+ /**
+ * Duty code
+ *
+ * @var string
+ */
+ public $dutyCode;
+
+ /**
+ * Organization ID
+ *
+ * @var string
+ */
+ public $organizationId;
+
+ /**
+ * Password Length of plain password.
+ *
+ * Only for SoapHeader < 4.
+ *
+ * @var int
+ */
+ public $passwordLength;
+
+ /**
+ * Password Data (base-64 encoded password)
+ *
+ * @var string
+ */
+ public $passwordData;
+
+ /**
+ * SecurityAuthenticateOptions constructor.
+ *
+ * @param AuthParams|null $authParams
+ */
+ public function __construct(AuthParams $authParams = null)
+ {
+ if ($authParams instanceof AuthParams) {
+ $this->loadFromAuthParams($authParams);
+ }
+
+ parent::__construct([]);
+ }
+
+ /**
+ * Load security authenticate options from auth params
+ *
+ * @param AuthParams $authParams
+ */
+ protected function loadFromAuthParams(AuthParams $authParams)
+ {
+ $this->officeId = $authParams->officeId;
+ $this->dutyCode = $authParams->dutyCode;
+ $this->organizationId = $authParams->organizationId;
+ $this->originatorTypeCode = $authParams->originatorTypeCode;
+ $this->userId = $authParams->userId;
+ $this->passwordLength = $authParams->passwordLength;
+ $this->passwordData = $authParams->passwordData;
+ }
+}
diff --git a/src/Amadeus/Client/Session/Handler/Base.php b/src/Amadeus/Client/Session/Handler/Base.php
index f05a6f628..cb9ce165e 100644
--- a/src/Amadeus/Client/Session/Handler/Base.php
+++ b/src/Amadeus/Client/Session/Handler/Base.php
@@ -22,8 +22,13 @@
namespace Amadeus\Client\Session\Handler;
+use Amadeus\Client;
+use Amadeus\Client\Struct\BaseWsMessage;
+use Amadeus\Client\Params\SessionHandlerParams;
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerAwareTrait;
+use Psr\Log\LoggerInterface;
+use Psr\Log\LogLevel;
use Psr\Log\NullLogger;
/**
@@ -41,12 +46,350 @@ abstract class Base implements HandlerInterface, LoggerAwareInterface
use LoggerAwareTrait;
+ /**
+ * XPATH query to retrieve all operations from the WSDL
+ *
+ * @var string
+ */
+ const XPATH_ALL_OPERATIONS = '/wsdl:definitions/wsdl:portType/wsdl:operation/@name';
+ /**
+ * XPATH query to retrieve the full operation name + version from the WSDL for a given operation.
+ *
+ * @var string
+ */
+ const XPATH_VERSION_FOR_OPERATION = "string(/wsdl:definitions/wsdl:message[contains(./@name, '%s_')]/@name)";
+
+
+ /**
+ * Status variable to know wether the given session is in a certain context.
+ *
+ * @todo implement this feature - currently the application using the client must know the context itself.
+ * @var bool
+ */
+ protected $hasContext = false;
+
+ /**
+ * The context of the currently active session
+ *
+ * @todo implement this feature - currently the application using the client must know the context itself.
+ * @var mixed
+ */
+ protected $context;
+
+
+ /**
+ * Session information:
+ * - session ID
+ * - sequence number
+ * - security Token
+ *
+ * @var array
+ */
+ protected $sessionData = [
+ 'sessionId' => null,
+ 'sequenceNumber' => null,
+ 'securityToken' => null
+ ];
+
+ /**
+ * Status variable to know if the session is currently logged in
+ *
+ * @var bool
+ */
+ protected $isAuthenticated = false;
+
/**
* @var \SoapClient
*/
protected $soapClient;
+ /**
+ * SoapClient options used during initialisation
+ *
+ * @var array
+ */
+ protected $soapClientOptions = [
+ 'trace' => 1,
+ 'exceptions' => 1,
+ 'soap_version' => SOAP_1_1
+ ];
+
+
+ /**
+ * @var SessionHandlerParams
+ */
+ protected $params;
+
+
+ /**
+ * Dom Document where the WSDL's contents will be loaded
+ *
+ * @var \DOMDocument
+ */
+ protected $wsdlDomDoc;
+ /**
+ * To query the WSDL contents
+ *
+ * @var \DOMXpath
+ */
+ protected $wsdlDomXpath;
+
+ /**
+ * Get the session parameters of the active session
+ *
+ * @return array|null
+ */
+ public function getSessionData()
+ {
+ return $this->sessionData;
+ }
+
+ /**
+ * Set the session data to continue a previously started session.
+ *
+ * @param array $sessionData
+ * @return bool
+ */
+ public function setSessionData(array $sessionData)
+ {
+ if (isset($sessionData['sessionId'], $sessionData['sequenceNumber'], $sessionData['securityToken'])) {
+ $this->sessionData['sessionId'] = $sessionData['sessionId'];
+ $this->sessionData['sequenceNumber'] = $sessionData['sequenceNumber'];
+ $this->sessionData['securityToken'] = $sessionData['securityToken'];
+ $this->isAuthenticated = true;
+ } else {
+ $this->isAuthenticated = false;
+ }
+
+ return $this->isAuthenticated;
+ }
+
+
+ /**
+ * @param SessionHandlerParams $params
+ */
+ public function __construct(SessionHandlerParams $params)
+ {
+ $this->params = $params;
+ if($params->logger instanceof LoggerInterface) {
+ $this->setLogger($params->logger);
+ $this->log(LogLevel::INFO, __METHOD__. "(): Logger started.");
+ }
+ if ($params->overrideSoapClient instanceof \SoapClient) {
+ $this->soapClient = $params->overrideSoapClient;
+ }
+ $this->setStateful($params->stateful);
+ }
+
+
+ /**
+ * @param string $messageName Method Operation name as defined in the WSDL.
+ * @param BaseWsMessage $messageBody
+ * @param array $messageOptions options: bool 'asString', bool 'endSession'
+ * @return mixed
+ * @throws \InvalidArgumentException
+ * @throws Client\Exception
+ * @throws \SoapFault
+ */
+ public function sendMessage($messageName, Client\Struct\BaseWsMessage $messageBody, $messageOptions = [])
+ {
+ $result = null;
+
+ $this->prepareForNextMessage($messageName, $messageOptions);
+
+ try {
+ $result = $this->getSoapClient()->$messageName($messageBody);
+
+ $this->logRequestAndResponse($messageName);
+
+ $this->handlePostMessage($messageName, $this->getLastResponse(), $messageOptions, $result);
+
+ } catch(\SoapFault $ex) {
+ $this->log(
+ LogLevel::ERROR,
+ "SOAPFAULT while sending message " . $messageName . ": " .
+ $ex->getMessage() . " code: " .$ex->getCode() . " at " . $ex->getFile() .
+ " line " . $ex->getLine() . ": \n" . $ex->getTraceAsString()
+ );
+ $this->logRequestAndResponse($messageName);
+ //TODO We must be able to handle certain soapfaults inside the client, so maybe pass through after logging?
+ throw $ex;
+ } catch (\Exception $ex) {
+ $this->log(
+ LogLevel::ERROR,
+ "EXCEPTION while sending message " . $messageName . ": " .
+ $ex->getMessage() . " at " . $ex->getFile() . " line " . $ex->getLine() . ": \n" .
+ $ex->getTraceAsString()
+ );
+ $this->logRequestAndResponse($messageName);
+ //TODO We must be able to handle certain exceptions inside the client, so maybe pass through after logging?
+ throw new Client\Exception($ex->getMessage(), $ex->getCode(), $ex);
+ }
+
+ if ($messageOptions['asString'] === true) {
+ $result = Client\Util\MsgBodyExtractor::extract($this->getLastResponse());
+ }
+
+ return $result;
+ }
+
+ /**
+ * Prepare to send a next message and checks if authenticated
+ *
+ * @param string $messageName
+ * @param array $messageOptions
+ */
+ protected abstract function prepareForNextMessage($messageName, $messageOptions);
+
+ /**
+ * Handles post message actions
+ *
+ * Handles session state based on received response
+ *
+ * @param string $messageName
+ * @param string $lastResponse
+ * @param array $messageOptions
+ * @param mixed $result
+ */
+ protected abstract function handlePostMessage($messageName, $lastResponse, $messageOptions, $result);
+
+ /**
+ * Get the last raw XML message that was sent out
+ *
+ * @return string|null
+ */
+ public function getLastRequest()
+ {
+ return $this->getSoapClient()->__getLastRequest();
+ }
+
+ /**
+ * Get the last raw XML message that was received
+ *
+ * @return string|null
+ */
+ public function getLastResponse()
+ {
+ return $this->getSoapClient()->__getLastResponse();
+ }
+
+ /**
+ * Get the office that we are using to sign in to.
+ *
+ * @return string
+ */
+ public function getOriginatorOffice()
+ {
+ return $this->params->authParams->officeId;
+ }
+
+
+ /**
+ * Extract the Messages and versions from the loaded WSDL file.
+ *
+ * Result is an associative array: keys are message names, values are versions.
+ *
+ * @return array
+ */
+ public function getMessagesAndVersions()
+ {
+ $this->loadWsdlXpath($this->params->wsdl);
+
+ $msgAndVer = [];
+ $operations = $this->wsdlDomXpath->query(self::XPATH_ALL_OPERATIONS);
+
+ foreach ($operations as $operation) {
+ if (!empty($operation->value)) {
+ $fullVersion = $this->wsdlDomXpath->evaluate(sprintf(self::XPATH_VERSION_FOR_OPERATION, $operation->value));
+ if (!empty($fullVersion)) {
+ $extractedVersion = $this->extractMessageVersion($fullVersion);
+ $msgAndVer[$operation->value] = $extractedVersion;
+ }
+ }
+ }
+
+ return $msgAndVer;
+ }
+
+ /**
+ * extractMessageVersion
+ *
+ * extracts "4.1" from a string like "Security_SignOut_4_1"
+ *
+ * @param string $fullVersionString
+ * @return string
+ */
+ protected function extractMessageVersion($fullVersionString)
+ {
+ $secondUnderscore = strpos($fullVersionString, '_', strpos($fullVersionString, '_')+1);
+ $num = substr($fullVersionString, $secondUnderscore+1);
+
+ return str_replace('_', '.', $num);
+ }
+
+ /**
+ * Load the WSDL contents to a queryable DOMXpath.
+ *
+ * @param string $wsdlFilePath
+ * @uses $this->wsdlDomDoc
+ * @uses $this->wsdlDomXpath
+ */
+ protected function loadWsdlXpath($wsdlFilePath)
+ {
+ if (is_null($this->wsdlDomXpath)) {
+ $wsdlContent = file_get_contents($wsdlFilePath);
+
+ $this->wsdlDomDoc = new \DOMDocument('1.0', 'UTF-8');
+ $this->wsdlDomDoc->loadXML($wsdlContent);
+ $this->wsdlDomXpath = new \DOMXPath($this->wsdlDomDoc);
+ $this->wsdlDomXpath->registerNamespace(
+ 'wsdl',
+ 'http://schemas.xmlsoap.org/wsdl/'
+ );
+ $this->wsdlDomXpath->registerNamespace(
+ 'soap',
+ 'http://schemas.xmlsoap.org/wsdl/soap/'
+ );
+ }
+ }
+
+
+ /**
+ * @return \SoapClient
+ */
+ protected function getSoapClient()
+ {
+ if (!$this->soapClient instanceof \SoapClient) {
+ $this->soapClient = $this->initSoapClient();
+ }
+
+ return $this->soapClient;
+ }
+
+ /**
+ * @return \SoapClient
+ */
+ protected abstract function initSoapClient();
+
+
+ /**
+ * @param string $messageName
+ * @uses $this->log
+ */
+ protected function logRequestAndResponse($messageName)
+ {
+ $this->log(
+ LogLevel::INFO,
+ 'Called ' . $messageName . ' with request: ' . $this->getSoapClient()->__getLastRequest()
+ );
+ $this->log(
+ LogLevel::INFO,
+ 'Response: ' . $this->getSoapClient()->__getLastResponse()
+ );
+ }
+
+
/**
* @param mixed $level
* @param string $message
@@ -61,5 +404,4 @@ protected function log($level, $message, $context = [])
return $this->logger->log($level, $message, $context);
}
-
-}
\ No newline at end of file
+}
diff --git a/src/Amadeus/Client/Session/Handler/Classmap.php b/src/Amadeus/Client/Session/Handler/Classmap.php
index fcd0a37cf..32bc32ce0 100644
--- a/src/Amadeus/Client/Session/Handler/Classmap.php
+++ b/src/Amadeus/Client/Session/Handler/Classmap.php
@@ -43,6 +43,15 @@ class Classmap
'Session' => 'Amadeus\Client\Struct\HeaderV4\Session',
];
+ /**
+ * The PHP -> WSDL translation classmap for Soap Header 2 specific message parts
+ *
+ * @var array
+ */
+ public static $soapheader2map = [
+ 'Session' => 'Amadeus\Client\Struct\HeaderV2\Session',
+ ];
+
/**
* The PHP -> WSDL translation classmap for the Amadeus WS Client
*
diff --git a/src/Amadeus/Client/Session/Handler/HandlerFactory.php b/src/Amadeus/Client/Session/Handler/HandlerFactory.php
index 8c4cf29de..91954ddfd 100644
--- a/src/Amadeus/Client/Session/Handler/HandlerFactory.php
+++ b/src/Amadeus/Client/Session/Handler/HandlerFactory.php
@@ -55,9 +55,11 @@ public static function createHandler($handlerParams)
$theHandler = new SoapHeader4($handlerParams);
break;
case Client::HEADER_V2:
+ $theHandler = new SoapHeader2($handlerParams);
+ break;
case Client::HEADER_V1:
default:
- //TODO implement Client::HEADER_V2 & Client::HEADER_V1
+ //TODO implement Client::HEADER_V1
throw new \InvalidArgumentException(
'No Session Handler found for soapHeaderVersion ' . $handlerParams->soapHeaderVersion
);
diff --git a/src/Amadeus/Client/Session/Handler/HandlerInterface.php b/src/Amadeus/Client/Session/Handler/HandlerInterface.php
index 1104c3115..113aecfde 100644
--- a/src/Amadeus/Client/Session/Handler/HandlerInterface.php
+++ b/src/Amadeus/Client/Session/Handler/HandlerInterface.php
@@ -80,6 +80,14 @@ public function setStateful($stateful);
*/
public function getSessionData();
+ /**
+ * Set the session data to continue a previously started session.
+ *
+ * @param array $sessionData
+ * @return bool success or failure
+ */
+ public function setSessionData(array $sessionData);
+
/**
* Get the current stateful mode (true is stateful, false is stateless)
*
diff --git a/src/Amadeus/Client/Session/Handler/InvalidSessionException.php b/src/Amadeus/Client/Session/Handler/InvalidSessionException.php
new file mode 100644
index 000000000..5e73ebb3b
--- /dev/null
+++ b/src/Amadeus/Client/Session/Handler/InvalidSessionException.php
@@ -0,0 +1,38 @@
+
+ */
+class InvalidSessionException extends Exception
+{
+
+}
diff --git a/src/Amadeus/Client/Session/Handler/SoapHeader2.php b/src/Amadeus/Client/Session/Handler/SoapHeader2.php
new file mode 100644
index 000000000..b4b273f61
--- /dev/null
+++ b/src/Amadeus/Client/Session/Handler/SoapHeader2.php
@@ -0,0 +1,187 @@
+
+ */
+class SoapHeader2 extends Base
+{
+ /**
+ * Namespace of SoapHeader V2
+ */
+ const CORE_WS_V2_SESSION_NS = 'http://xml.amadeus.com/ws/2009/01/WBS_Session-2.0.xsd';
+
+ /**
+ * Node for Session ID
+ */
+ const NODENAME_SESSIONID = "SessionId";
+ /**
+ * Node for Session Sequence Number
+ */
+ const NODENAME_SEQENCENR = "SequenceNumber";
+ /**
+ * Node for Session Security Token
+ */
+ const NODENAME_SECURITYTOKEN = "SecurityToken";
+
+ /**
+ * Prepare to send a next message and checks if authenticated
+ *
+ * @param string $messageName
+ * @param array $messageOptions
+ * @throws InvalidSessionException When trying to send a message without session.
+ */
+ protected function prepareForNextMessage($messageName, $messageOptions)
+ {
+ if (!$this->isAuthenticated && $messageName !== 'Security_Authenticate') {
+ throw new InvalidSessionException('No active session');
+ }
+
+ $this->getSoapClient()->__setSoapHeaders(null);
+
+ if ($this->isAuthenticated === true && is_int($this->sessionData['sequenceNumber'])) {
+ $this->sessionData['sequenceNumber']++;
+
+ $session = new Client\Struct\HeaderV2\Session(
+ $this->sessionData['sessionId'],
+ $this->sessionData['sequenceNumber'],
+ $this->sessionData['securityToken']
+ );
+
+ $this->getSoapClient()->__setSoapHeaders(
+ new \SoapHeader(self::CORE_WS_V2_SESSION_NS, self::NODENAME_SESSIONID, $session)
+ );
+ }
+ }
+
+ /**
+ * Handles post message actions
+ *
+ * Handles session state based on received response
+ *
+ * @param string $messageName
+ * @param string $lastResponse
+ * @param array $messageOptions
+ * @param mixed $result
+ */
+ protected function handlePostMessage($messageName, $lastResponse, $messageOptions, $result)
+ {
+ if ($messageName === "Security_Authenticate") {
+ $this->sessionData = $this->getSessionDataFromHeader($lastResponse);
+ $this->isAuthenticated = (!empty($this->sessionData['sessionId']) &&
+ !empty($this->sessionData['sequenceNumber']) &&
+ !empty($this->sessionData['securityToken']));
+ }
+ }
+
+ /**
+ * @param string $responseMsg the full response XML received.
+ * @return array
+ */
+ protected function getSessionDataFromHeader($responseMsg)
+ {
+ $newSessionData = [
+ 'sessionId' => null,
+ 'sequenceNumber' => null,
+ 'securityToken' => null
+ ];
+
+ $responseDomDoc = new \DOMDocument('1.0', 'UTF-8');
+ $ok = $responseDomDoc->loadXML($responseMsg);
+
+ if ($ok) {
+ $sessionId = $responseDomDoc->getElementsByTagName(self::NODENAME_SESSIONID)->item(0)->nodeValue;
+ if ($sessionId) {
+ $newSessionData['sessionId'] = $sessionId;
+ }
+ $sequence = (int)$responseDomDoc->getElementsByTagName(self::NODENAME_SEQENCENR)->item(0)->nodeValue;
+ if ($sequence) {
+ $newSessionData['sequenceNumber'] = $sequence;
+ }
+ $securityToken = $responseDomDoc->getElementsByTagName(self::NODENAME_SECURITYTOKEN)->item(0)->nodeValue;
+ if ($securityToken) {
+ $newSessionData['securityToken'] = $securityToken;
+ }
+ }
+
+ unset($responseDomDoc);
+
+ return $newSessionData;
+ }
+
+ /**
+ * Cannot set stateless on Soap Header v2
+ *
+ * @param bool $stateful
+ * @throws UnsupportedOperationException
+ */
+ public function setStateful($stateful)
+ {
+ if ($stateful === false) {
+ throw new UnsupportedOperationException('Stateful messages are mandatory on SoapHeader 2');
+ }
+ }
+
+ /**
+ * Soap Header 2 sessions are always stateful
+ *
+ * @return bool
+ */
+ public function isStateful()
+ {
+ return true;
+ }
+
+ /**
+ * @return \SoapClient
+ */
+ protected function initSoapClient()
+ {
+ $client = new Client\SoapClient(
+ $this->params->wsdl,
+ $this->makeSoapClientOptions(),
+ $this->params->logger
+ );
+
+ return $client;
+ }
+
+ /**
+ * @return array
+ */
+ protected function makeSoapClientOptions()
+ {
+ $options = $this->soapClientOptions;
+ $options['classmap'] = array_merge(Classmap::$soapheader2map, Classmap::$map);
+
+ return $options;
+ }
+}
diff --git a/src/Amadeus/Client/Session/Handler/SoapHeader4.php b/src/Amadeus/Client/Session/Handler/SoapHeader4.php
index 020cc99c9..212391682 100644
--- a/src/Amadeus/Client/Session/Handler/SoapHeader4.php
+++ b/src/Amadeus/Client/Session/Handler/SoapHeader4.php
@@ -22,12 +22,9 @@
namespace Amadeus\Client\Session\Handler;
-use Amadeus\Client\Struct\BaseWsMessage;
use Amadeus\Client;
-use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;
-
/**
* SoapHeader4: Session Handler for web service applications using Amadeus WS Soap Header v4.
*
@@ -48,138 +45,14 @@ class SoapHeader4 extends Base
* @var string
*/
const XPATH_ENDPOINT = 'string(/wsdl:definitions/wsdl:service/wsdl:port/soap:address/@location)';
- /**
- * XPATH query to retrieve all operations from the WSDL
- *
- * @var string
- */
- const XPATH_ALL_OPERATIONS = '/wsdl:definitions/wsdl:portType/wsdl:operation/@name';
- /**
- * XPATH query to retrieve the full operation name + version from the WSDL for a given operation.
- *
- * @var string
- */
- const XPATH_VERSION_FOR_OPERATION = "string(/wsdl:definitions/wsdl:message[contains(./@name, '%s_')]/@name)";
- /**
- * Status variable to know if the session is currently logged in
- *
- * @var bool
- */
- protected $isAuthenticated = false;
- /**
- * Status variable to know wether the given session is in a certain context.
- *
- * @var bool
- */
- protected $hasContext = false;
+
/**
* Switch between stateful & stateless sessions. Default: stateful
*
* @var bool
*/
protected $isStateful = true;
- /**
- * The context of the currently active session
- *
- * @todo implement this feature - currently the application using the client must know the context itself.
- * @var mixed
- */
- protected $context;
- /**
- * Session information:
- * - session ID
- * - sequence number
- * - security Token
- *
- * @var array
- */
- protected $sessionData = [
- 'sessionId' => null,
- 'sequenceNumber' => null,
- 'securityToken' => null
- ];
- /**
- * SoapClient options used during initialisation
- *
- * @var array
- */
- protected $soapClientOptions = [
- 'trace' => 1,
- 'exceptions' => 1,
- 'soap_version' => SOAP_1_1
- ];
-
- /**
- * Dom Document where the WSDL's contents will be loaded
- *
- * @var \DOMDocument
- */
- protected $wsdlDomDoc;
- /**
- * To query the WSDL contents
- *
- * @var \DOMXpath
- */
- protected $wsdlDomXpath;
-
- /**
- * @var Client\Params\SessionHandlerParams
- */
- protected $params;
-
- /**
- * @param Client\Params\SessionHandlerParams $params
- */
- public function __construct(Client\Params\SessionHandlerParams $params)
- {
- $this->params = $params;
- if($params->logger instanceof LoggerInterface) {
- $this->setLogger($params->logger);
- //$this->log(LogLevel::INFO, __METHOD__. "(): Logger started.");
- }
- if ($params->overrideSoapClient instanceof \SoapClient) {
- $this->soapClient = $params->overrideSoapClient;
- }
- $this->setStateful($params->stateful);
- }
-
- /**
- * Get the office that we are using to sign in to.
- *
- * @return string
- */
- public function getOriginatorOffice()
- {
- return $this->params->authParams->officeId;
- }
-
- /**
- * Extract the Messages and versions from the loaded WSDL file.
- *
- * Result is an associative array: keys are message names, values are versions.
- *
- * @return array
- */
- public function getMessagesAndVersions()
- {
- $this->loadWsdlXpath($this->params->wsdl);
-
- $msgAndVer = [];
- $operations = $this->wsdlDomXpath->query(self::XPATH_ALL_OPERATIONS);
-
- foreach ($operations as $operation) {
- if (!empty($operation->value)) {
- $fullVersion = $this->wsdlDomXpath->evaluate(sprintf(self::XPATH_VERSION_FOR_OPERATION, $operation->value));
- if (!empty($fullVersion)) {
- $extractedVersion = $this->extractMessageVersion($fullVersion);
- $msgAndVer[$operation->value] = $extractedVersion;
- }
- }
- }
-
- return $msgAndVer;
- }
/**
* @param bool $stateful
@@ -199,88 +72,6 @@ public function isStateful()
return $this->isStateful;
}
- /**
- * Get the session parameters of the active session
- *
- * @return array|null
- */
- public function getSessionData()
- {
- return $this->sessionData;
- }
-
- /**
- * Get the last raw XML message that was sent out
- *
- * @return string|null
- */
- public function getLastRequest()
- {
- return $this->getSoapClient()->__getLastRequest();
- }
-
- /**
- * Get the last raw XML message that was received
- *
- * @return string|null
- */
- public function getLastResponse()
- {
- return $this->getSoapClient()->__getLastResponse();
- }
-
-
- /**
- * @param string $messageName Method Operation name as defined in the WSDL.
- * @param BaseWsMessage $messageBody
- * @param array $messageOptions options: bool 'asString', bool 'endSession'
- * @return mixed
- * @throws \InvalidArgumentException
- * @throws Client\Exception
- * @throws \SoapFault
- */
- public function sendMessage($messageName, BaseWsMessage $messageBody, $messageOptions = [])
- {
- $result = null;
-
- $this->prepareForNextMessage($messageName, $messageOptions);
-
- try {
- $result = $this->getSoapClient()->$messageName($messageBody);
-
- $this->logRequestAndResponse($messageName);
-
- $this->handlePostMessage($messageName, $this->getLastResponse(), $messageOptions, $result);
-
- } catch(\SoapFault $ex) {
- $this->log(
- LogLevel::ERROR,
- "SOAPFAULT while sending message " . $messageName . ": " .
- $ex->getMessage() . " code: " .$ex->getCode() . " at " . $ex->getFile() .
- " line " . $ex->getLine() . ": \n" . $ex->getTraceAsString()
- );
- $this->logRequestAndResponse($messageName);
- //TODO We must be able to handle certain soapfaults inside the client, so maybe pass through after logging?
- throw $ex;
- } catch (\Exception $ex) {
- $this->log(
- LogLevel::ERROR,
- "EXCEPTION while sending message " . $messageName . ": " .
- $ex->getMessage() . " at " . $ex->getFile() . " line " . $ex->getLine() . ": \n" .
- $ex->getTraceAsString()
- );
- $this->logRequestAndResponse($messageName);
- //TODO We must be able to handle certain exceptions inside the client, so maybe pass through after logging?
- throw new Client\Exception($ex->getMessage(), $ex->getCode(), $ex);
- }
-
- if ($messageOptions['asString'] === true) {
- $result = Client\Util\MsgBodyExtractor::extract($this->getLastResponse());
- }
-
- return $result;
- }
-
/**
* Handles authentication & sessions
*
@@ -336,8 +127,6 @@ protected function handlePostMessage($messageName, $lastResponse, $messageOption
} else {
$this->isAuthenticated = false;
}
-
- //TODO: check for errors in response?
}
/**
@@ -374,6 +163,8 @@ protected function getSessionDataFromHeader($responseMsg)
$newSessionData['securityToken'] = $responseDomXpath->evaluate($querySecurityToken);
}
+ unset($responseDomDoc, $responseDomXpath);
+
return $newSessionData;
}
@@ -511,58 +302,32 @@ protected function createSoapHeaders($sessionData, $params, $messageName, $messa
}
/**
- * Get the SOAPAction for a given message from the WSDL contents.
+ * Get the Web Services server Endpoint from the WSDL.
*
* @param string $wsdlFilePath
- * @param string $messageName
* @return string
*/
- protected function getActionFromWsdl($wsdlFilePath, $messageName)
+ protected function getEndpointFromWsdl($wsdlFilePath)
{
$this->loadWsdlXpath($wsdlFilePath);
- $action = $this->wsdlDomXpath->evaluate(sprintf(self::XPATH_OPERATION_ACTION, $messageName));
-
- return $action;
+ return $this->wsdlDomXpath->evaluate(self::XPATH_ENDPOINT);
}
/**
- * Get the Web Services server Endpoint from the WSDL.
+ * Get the SOAPAction for a given message from the WSDL contents.
*
* @param string $wsdlFilePath
+ * @param string $messageName
* @return string
*/
- protected function getEndpointFromWsdl($wsdlFilePath)
+ protected function getActionFromWsdl($wsdlFilePath, $messageName)
{
$this->loadWsdlXpath($wsdlFilePath);
- return $this->wsdlDomXpath->evaluate(self::XPATH_ENDPOINT);
- }
+ $action = $this->wsdlDomXpath->evaluate(sprintf(self::XPATH_OPERATION_ACTION, $messageName));
- /**
- * Load the WSDL contents to a queryable DOMXpath.
- *
- * @param string $wsdlFilePath
- * @uses $this->wsdlDomDoc
- * @uses $this->wsdlDomXpath
- */
- protected function loadWsdlXpath($wsdlFilePath)
- {
- if (is_null($this->wsdlDomXpath)) {
- $wsdlContent = file_get_contents($wsdlFilePath);
-
- $this->wsdlDomDoc = new \DOMDocument('1.0', 'UTF-8');
- $this->wsdlDomDoc->loadXML($wsdlContent);
- $this->wsdlDomXpath = new \DOMXPath($this->wsdlDomDoc);
- $this->wsdlDomXpath->registerNamespace(
- 'wsdl',
- 'http://schemas.xmlsoap.org/wsdl/'
- );
- $this->wsdlDomXpath->registerNamespace(
- 'soap',
- 'http://schemas.xmlsoap.org/wsdl/soap/'
- );
- }
+ return $action;
}
/**
@@ -660,35 +425,6 @@ protected function createDateTimeStringForAuth($creationDateTime, $micro)
return $creationDateTime->format("Y-m-d\TH:i:s:") . $micro . 'Z';
}
- /**
- * extractMessageVersion
- *
- * extracts "4.1" from a string like "Security_SignOut_4_1"
- *
- * @param string $fullVersionString
- * @return string
- */
- protected function extractMessageVersion($fullVersionString)
- {
- $secondUnderscore = strpos($fullVersionString, '_', strpos($fullVersionString, '_')+1);
- $num = substr($fullVersionString, $secondUnderscore+1);
-
- return str_replace('_', '.', $num);
- }
-
- /**
- * @return \SoapClient
- */
- protected function getSoapClient()
- {
- if (!$this->soapClient instanceof \SoapClient) {
- $this->soapClient = $this->initSoapClient();
- }
-
- return $this->soapClient;
- }
-
-
/**
* @return \SoapClient
*/
@@ -713,21 +449,4 @@ protected function makeSoapClientOptions()
return $options;
}
-
-
- /**
- * @param string $messageName
- * @uses $this->log
- */
- protected function logRequestAndResponse($messageName)
- {
- $this->log(
- LogLevel::INFO,
- 'Called ' . $messageName . ' with request: ' . $this->getSoapClient()->__getLastRequest()
- );
- $this->log(
- LogLevel::INFO,
- 'Response: ' . $this->getSoapClient()->__getLastResponse()
- );
- }
}
diff --git a/src/Amadeus/Client/Struct/SessionHeaderV2.php b/src/Amadeus/Client/Session/Handler/UnsupportedOperationException.php
similarity index 80%
rename from src/Amadeus/Client/Struct/SessionHeaderV2.php
rename to src/Amadeus/Client/Session/Handler/UnsupportedOperationException.php
index 15e2f28ec..d5b18e552 100644
--- a/src/Amadeus/Client/Struct/SessionHeaderV2.php
+++ b/src/Amadeus/Client/Session/Handler/UnsupportedOperationException.php
@@ -20,16 +20,17 @@
* @license https://opensource.org/licenses/Apache-2.0 Apache 2.0
*/
-namespace Amadeus\Client\Struct;
+namespace Amadeus\Client\Session\Handler;
+
+use Amadeus\Client\Exception;
/**
- * Class SessionHeaderV2
+ * UnsupportedOperation
*
- * @todo NOT YET IMPLEMENTED
- * @package Amadeus\Client\Struct
+ * @package Amadeus\Client\Session\Handler
* @author Dieter Devlieghere
*/
-class SessionHeaderV2
+class UnsupportedOperationException extends Exception
{
- //TODO
+
}
diff --git a/src/Amadeus/Client/Struct/HeaderV2/Session.php b/src/Amadeus/Client/Struct/HeaderV2/Session.php
new file mode 100644
index 000000000..29f9b6a80
--- /dev/null
+++ b/src/Amadeus/Client/Struct/HeaderV2/Session.php
@@ -0,0 +1,57 @@
+
+ */
+class Session
+{
+ /**
+ * @var string
+ */
+ public $sessionId;
+ /**
+ * @var int
+ */
+ public $sequenceNumber;
+ /**
+ * @var string
+ */
+ public $securityToken;
+
+ /**
+ * @param string $sessId
+ * @param int $seqNr
+ * @param string $secTok
+ */
+ public function __construct($sessId, $seqNr, $secTok)
+ {
+ $this->sessionId = $sessId;
+ $this->sequenceNumber = $seqNr;
+ $this->securityToken = $secTok;
+ }
+}
diff --git a/src/Amadeus/Client/Struct/Security/ApplicationDetails.php b/src/Amadeus/Client/Struct/Security/ApplicationDetails.php
new file mode 100644
index 000000000..5ba6d7677
--- /dev/null
+++ b/src/Amadeus/Client/Struct/Security/ApplicationDetails.php
@@ -0,0 +1,41 @@
+
+ */
+class ApplicationDetails
+{
+ /**
+ * @var string
+ */
+ public $internalId;
+ /**
+ * @var string
+ */
+ public $seqNumber;
+}
diff --git a/src/Amadeus/Client/Struct/Security/ApplicationId.php b/src/Amadeus/Client/Struct/Security/ApplicationId.php
new file mode 100644
index 000000000..7551b65f1
--- /dev/null
+++ b/src/Amadeus/Client/Struct/Security/ApplicationId.php
@@ -0,0 +1,37 @@
+
+ */
+class ApplicationId
+{
+ /**
+ * @var ApplicationDetails
+ */
+ public $applicationDetails;
+}
diff --git a/src/Amadeus/Client/Struct/Security/Authenticate.php b/src/Amadeus/Client/Struct/Security/Authenticate.php
index fb47964e1..cfaa638f1 100644
--- a/src/Amadeus/Client/Struct/Security/Authenticate.php
+++ b/src/Amadeus/Client/Struct/Security/Authenticate.php
@@ -22,12 +22,12 @@
namespace Amadeus\Client\Struct\Security;
+use Amadeus\Client\RequestOptions\SecurityAuthenticateOptions;
use Amadeus\Client\Struct\BaseWsMessage;
/**
* Authenticate
*
- * @todo Implement this message when we support SoapHeader v. 1 or 2
* @package Amadeus\Client\Struct\Security
* @author Dieter Devlieghere
*/
@@ -61,4 +61,27 @@ class Authenticate extends BaseWsMessage
* @var ApplicationId
*/
public $applicationId;
+
+ /**
+ * Authenticate constructor.
+ *
+ * @param SecurityAuthenticateOptions $params
+ */
+ public function __construct(SecurityAuthenticateOptions $params)
+ {
+ $this->userIdentifier = new UserIdentifier(
+ $params->officeId,
+ $params->originatorTypeCode,
+ $params->userId
+ );
+
+ $this->dutyCode = new DutyCode($params->dutyCode);
+
+ $this->systemDetails = new SystemDetails($params->organizationId);
+
+ $this->passwordInfo = new PasswordInfo(
+ $params->passwordData,
+ $params->passwordLength
+ );
+ }
}
diff --git a/src/Amadeus/Client/Struct/Security/ConversationClt.php b/src/Amadeus/Client/Struct/Security/ConversationClt.php
new file mode 100644
index 000000000..962c1c18b
--- /dev/null
+++ b/src/Amadeus/Client/Struct/Security/ConversationClt.php
@@ -0,0 +1,49 @@
+
+ */
+class ConversationClt
+{
+ /**
+ * @var string
+ */
+ public $senderIdentification = 0;
+ /**
+ * @var string
+ */
+ public $recipientIdentification = 0;
+ /**
+ * @var string
+ */
+ public $senderInterchangeControlReference = 0;
+ /**
+ * @var string
+ */
+ public $recipientInterchangeControlReference = 0;
+}
diff --git a/src/Amadeus/Client/Struct/Security/DutyCode.php b/src/Amadeus/Client/Struct/Security/DutyCode.php
new file mode 100644
index 000000000..8fb873f3a
--- /dev/null
+++ b/src/Amadeus/Client/Struct/Security/DutyCode.php
@@ -0,0 +1,47 @@
+
+ */
+class DutyCode
+{
+ /**
+ * @var DutyCodeDetails
+ */
+ public $dutyCodeDetails;
+
+ /**
+ * DutyCode constructor.
+ *
+ * @param string $dutyCode
+ */
+ public function __construct($dutyCode)
+ {
+ $this->dutyCodeDetails = new DutyCodeDetails($dutyCode);
+ }
+}
diff --git a/src/Amadeus/Client/Struct/Security/DutyCodeDetails.php b/src/Amadeus/Client/Struct/Security/DutyCodeDetails.php
new file mode 100644
index 000000000..d85d458b3
--- /dev/null
+++ b/src/Amadeus/Client/Struct/Security/DutyCodeDetails.php
@@ -0,0 +1,62 @@
+
+ */
+class DutyCodeDetails
+{
+ /**
+ * Definition of Dutycode Reference qualifier "Duty Code"
+ *
+ * See Amadeus Core Webservices documentation
+ * [Reference qualifier codesets (Ref: 1153 IA 01.2.57)]
+ * @var string
+ */
+ const RQ_DUTYCODE = "DUT";
+
+ /**
+ * @var string
+ */
+ public $referenceQualifier;
+ /**
+ * @var string
+ */
+ public $referenceIdentifier;
+
+ /**
+ * DutyCodeDetails constructor.
+ *
+ * @param string $dutyCode
+ * @param string $qual
+ */
+ public function __construct($dutyCode, $qual = self::RQ_DUTYCODE)
+ {
+ $this->referenceIdentifier = $dutyCode;
+ $this->referenceQualifier = $qual;
+ }
+}
diff --git a/src/Amadeus/Client/Struct/Security/OrganizationDetails.php b/src/Amadeus/Client/Struct/Security/OrganizationDetails.php
new file mode 100644
index 000000000..2db829c3a
--- /dev/null
+++ b/src/Amadeus/Client/Struct/Security/OrganizationDetails.php
@@ -0,0 +1,47 @@
+
+ */
+class OrganizationDetails
+{
+ /**
+ * @var string
+ */
+ public $organizationId;
+
+ /**
+ * OrganizationDetails constructor.
+ *
+ * @param string $organizationId
+ */
+ public function __construct($organizationId)
+ {
+ $this->organizationId = $organizationId;
+ }
+}
diff --git a/src/Amadeus/Client/Struct/Security/OriginIdentification.php b/src/Amadeus/Client/Struct/Security/OriginIdentification.php
new file mode 100644
index 000000000..64a4f5cb1
--- /dev/null
+++ b/src/Amadeus/Client/Struct/Security/OriginIdentification.php
@@ -0,0 +1,47 @@
+
+ */
+class OriginIdentification
+{
+ /**
+ * @var string
+ */
+ public $sourceOffice;
+
+ /**
+ * OriginIdentification constructor.
+ *
+ * @param string $officeId
+ */
+ public function __construct($officeId)
+ {
+ $this->sourceOffice = $officeId;
+ }
+}
diff --git a/src/Amadeus/Client/Struct/Security/PasswordInfo.php b/src/Amadeus/Client/Struct/Security/PasswordInfo.php
new file mode 100644
index 000000000..06af03392
--- /dev/null
+++ b/src/Amadeus/Client/Struct/Security/PasswordInfo.php
@@ -0,0 +1,76 @@
+
+ */
+class PasswordInfo
+{
+ /**
+ * Definition of Password Data type "EDIFACT DATA"
+ *
+ * See Amadeus Core Webservices documentation
+ * [DATA TYPE codesets (Ref: 116Z 1A 02.1.8)]
+ * @var string
+ */
+ const DATA_TYPE_EDIFACT = 'E';
+ /**
+ * Definition of Password Data type "BINARY DATA"
+ *
+ * See Amadeus Core Webservices documentation
+ * [DATA TYPE codesets (Ref: 116Z 1A 02.1.8)]
+ * @var string
+ */
+ const DATA_TYPE_BINARY = 'B';
+
+ /**
+ * @var int
+ */
+ public $dataLength;
+ /**
+ * @var string
+ */
+ public $dataType;
+ /**
+ * @var string
+ */
+ public $binaryData;
+
+ /**
+ * PasswordInfo constructor.
+ *
+ * @param string $passwordData
+ * @param int $passwordLength
+ * @param string $type
+ */
+ public function __construct($passwordData, $passwordLength, $type = self::DATA_TYPE_EDIFACT)
+ {
+ $this->binaryData = $passwordData;
+ $this->dataLength = $passwordLength;
+ $this->dataType = $type;
+ }
+}
diff --git a/src/Amadeus/Client/Struct/Security/SystemDetails.php b/src/Amadeus/Client/Struct/Security/SystemDetails.php
new file mode 100644
index 000000000..71294f69b
--- /dev/null
+++ b/src/Amadeus/Client/Struct/Security/SystemDetails.php
@@ -0,0 +1,55 @@
+
+ */
+class SystemDetails
+{
+ /**
+ * @var string
+ */
+ public $workstationId;
+ /**
+ * @var OrganizationDetails
+ */
+ public $organizationDetails;
+ /**
+ * @var string
+ */
+ public $idQualifier;
+
+ /**
+ * SystemDetails constructor.
+ *
+ * @param string $organizationId
+ */
+ public function __construct($organizationId)
+ {
+ $this->organizationDetails = new OrganizationDetails($organizationId);
+ }
+}
diff --git a/src/Amadeus/Client/Struct/Security/UserIdentifier.php b/src/Amadeus/Client/Struct/Security/UserIdentifier.php
new file mode 100644
index 000000000..c63cf9aa9
--- /dev/null
+++ b/src/Amadeus/Client/Struct/Security/UserIdentifier.php
@@ -0,0 +1,59 @@
+
+ */
+class UserIdentifier
+{
+ /**
+ * @var OriginIdentification
+ */
+ public $originIdentification;
+ /**
+ * @var string
+ */
+ public $originatorTypeCode;
+ /**
+ * @var string
+ */
+ public $originator;
+
+ /**
+ * UserIdentifier constructor.
+ *
+ * @param string $officeId
+ * @param string $originatorTypeCode
+ * @param string $originator
+ */
+ public function __construct($officeId, $originatorTypeCode, $originator)
+ {
+ $this->originIdentification = new OriginIdentification($officeId);
+ $this->originatorTypeCode = $originatorTypeCode;
+ $this->originator = $originator;
+ }
+}
diff --git a/src/Amadeus/Client/Util/MsgBodyExtractor.php b/src/Amadeus/Client/Util/MsgBodyExtractor.php
index c28602cf1..572ccfef0 100644
--- a/src/Amadeus/Client/Util/MsgBodyExtractor.php
+++ b/src/Amadeus/Client/Util/MsgBodyExtractor.php
@@ -37,6 +37,13 @@ class MsgBodyExtractor
*/
const REGEXP_SOAP_ENVELOPE_CONTENTS = "|\\(.*?)\\<\\/SOAP-ENV:Body\\>|";
+ /**
+ * Regular expression for extracting the Soap Envelope Body's content - legacy format for Soap Header v2 and older
+ *
+ * @var string
+ */
+ const REGEXP_SOAP_ENVELOPE_CONTENTS_LEGACY = "|\\(.*?)\\<\\/soap:Body\\>|";
+
/**
* Extracts the message content from the soap envelope (i.e. everything under the soap body)
*
@@ -52,6 +59,12 @@ public static function extract($soapResponse)
$messageBody = $matches[1];
}
+ if (empty($messageBody)) {
+ if (preg_match(self::REGEXP_SOAP_ENVELOPE_CONTENTS_LEGACY, $soapResponse, $matches) === 1) {
+ $messageBody = $matches[1];
+ }
+ }
+
return $messageBody;
}
}
diff --git a/tests/Amadeus/Client/Session/Handler/HandlerFactoryTest.php b/tests/Amadeus/Client/Session/Handler/HandlerFactoryTest.php
index cb05526eb..2c4797410 100644
--- a/tests/Amadeus/Client/Session/Handler/HandlerFactoryTest.php
+++ b/tests/Amadeus/Client/Session/Handler/HandlerFactoryTest.php
@@ -49,13 +49,33 @@ public function testCreateWithoutAuthWillThrowException()
HandlerFactory::createHandler($params);
}
- public function testCreateSoapHeader2WillThrowException()
+
+ public function testCreateSoapHeader4WillCreateSoapHeader4Handler()
{
- $this->setExpectedException('\InvalidArgumentException');
+ $params = $par = new SessionHandlerParams([
+ 'wsdl' => '/dummy/path',
+ 'soapHeaderVersion' => Client::HEADER_V4,
+ 'receivedFrom' => 'unittests',
+ 'logger' => new NullLogger(),
+ 'authParams' => [
+ 'officeId' => 'BRUXX0000',
+ 'originatorTypeCode' => 'U',
+ 'userId' => 'DUMMYORIG',
+ 'organizationId' => 'DUMMYORG',
+ 'passwordLength' => 12,
+ 'passwordData' => 'dGhlIHBhc3N3b3Jk'
+ ]
+ ]);
+ $createdHandler = HandlerFactory::createHandler($params);
+
+ $this->assertInstanceOf('Amadeus\Client\Session\Handler\SoapHeader4', $createdHandler);
+ }
+
+ public function testCreateSoapHeader2WillCreateSoapHeader2Handler()
+ {
$params = $par = new SessionHandlerParams([
'wsdl' => '/dummy/path',
- 'stateful' => false,
'soapHeaderVersion' => Client::HEADER_V2,
'receivedFrom' => 'unittests',
'logger' => new NullLogger(),
@@ -69,6 +89,30 @@ public function testCreateSoapHeader2WillThrowException()
]
]);
+ $createdHandler = HandlerFactory::createHandler($params);
+
+ $this->assertInstanceOf('Amadeus\Client\Session\Handler\SoapHeader2', $createdHandler);
+ }
+
+ public function testCreateSoapHeader1WillThrowException()
+ {
+ $this->setExpectedException('\InvalidArgumentException');
+
+ $params = $par = new SessionHandlerParams([
+ 'wsdl' => '/dummy/path',
+ 'soapHeaderVersion' => Client::HEADER_V1,
+ 'receivedFrom' => 'unittests',
+ 'logger' => new NullLogger(),
+ 'authParams' => [
+ 'officeId' => 'BRUXX0000',
+ 'originatorTypeCode' => 'U',
+ 'userId' => 'DUMMYORIG',
+ 'organizationId' => 'DUMMYORG',
+ 'passwordLength' => 12,
+ 'passwordData' => 'dGhlIHBhc3N3b3Jk'
+ ]
+ ]);
+
HandlerFactory::createHandler($params);
}
}
diff --git a/tests/Amadeus/Client/Session/Handler/SoapHeader2Test.php b/tests/Amadeus/Client/Session/Handler/SoapHeader2Test.php
new file mode 100644
index 000000000..dbc8ae998
--- /dev/null
+++ b/tests/Amadeus/Client/Session/Handler/SoapHeader2Test.php
@@ -0,0 +1,211 @@
+
+ */
+class SoapHeader2Test extends BaseTestCase
+{
+
+ public function testCanTrySendMessageWhenNotAuthenticated()
+ {
+ $this->setExpectedException('Amadeus\Client\Session\Handler\InvalidSessionException');
+
+ $handler = new SoapHeader2($this->makeSessionHandlerParams());
+
+ $handler->sendMessage(
+ 'PNR_Retrieve',
+ new Client\Struct\Pnr\Retrieve(Client\Struct\Pnr\Retrieve::RETR_TYPE_BY_RECLOC, 'ABC123'),
+ [
+ 'asString' => false,
+ 'endSession' => false
+ ]
+ );
+ }
+
+ public function testCanTryPrepareNextMessageWhenAuthenticated()
+ {
+ $overrideSoapClient = $this->getMock(
+ 'Amadeus\Client\SoapClient',
+ ['__getLastRequest', '__getLastResponse', 'PNR_Retrieve'],
+ [],
+ '',
+ false
+ );
+
+ $dummyPnrRequest = $this->getTestFile('dummyPnrRequestsoapheader2.txt');
+ $dummyPnrReply = $this->getTestFile('dummyPnrReplysoapheader2.txt');
+ $dummyPnrReplyExtractedMessage = $this->getTestFile('dummyPnrReplyExtractedMessageSoapHeader2.txt');
+
+ $overrideSoapClient
+ ->expects($this->atLeastOnce())
+ ->method('__getLastRequest')
+ ->will($this->returnValue($dummyPnrRequest));
+
+ $overrideSoapClient
+ ->expects($this->atLeastOnce())
+ ->method('__getLastResponse')
+ ->will($this->returnValue($dummyPnrReply));
+
+ $overrideSoapClient
+ ->expects($this->any())
+ ->method('PNR_Retrieve')
+ ->will($this->returnValue(''));
+
+ $handler = new SoapHeader2($this->makeSessionHandlerParams(
+ $overrideSoapClient
+ ));
+ $handler->setSessionData([
+ 'sessionId' => 'XFHZEKLRZHREJ',
+ 'sequenceNumber' => 12,
+ 'securityToken' => 'RKLERJEZLKRHZEJKLRHEZJKLREZRHEZK'
+ ]);
+
+ $messageResponse = $handler->sendMessage(
+ 'PNR_Retrieve',
+ new Client\Struct\Pnr\Retrieve(Client\Struct\Pnr\Retrieve::RETR_TYPE_BY_RECLOC, 'ABC123'),
+ [
+ 'asString' => true,
+ 'endSession' => false
+ ]
+ );
+
+ $this->assertInternalType('string', $messageResponse);
+ $this->assertEquals($dummyPnrReplyExtractedMessage, $messageResponse);
+ }
+
+ public function testCanSendAuthCallAndStartSession()
+ {
+ $overrideSoapClient = $this->getMock(
+ 'Amadeus\Client\SoapClient',
+ ['__getLastRequest', '__getLastResponse', 'Security_Authenticate'],
+ [],
+ '',
+ false
+ );
+
+ $dummyRequest = $this->getTestFile('soapheader2' . DIRECTORY_SEPARATOR . 'dummySecurityAuth.txt');
+ $dummyReply = $this->getTestFile('soapheader2' . DIRECTORY_SEPARATOR . 'dummySecurityAuthReply.txt');
+
+ $messageResult = new \stdClass();
+ $messageResult->processStatus = new \stdClass();
+ $messageResult->processStatus->statusCode = 'P';
+
+ $overrideSoapClient
+ ->expects($this->atLeastOnce())
+ ->method('__getLastRequest')
+ ->will($this->returnValue($dummyRequest));
+
+ $overrideSoapClient
+ ->expects($this->atLeastOnce())
+ ->method('__getLastResponse')
+ ->will($this->returnValue($dummyReply));
+
+ $overrideSoapClient
+ ->expects($this->any())
+ ->method('Security_Authenticate')
+ ->will($this->returnValue($messageResult));
+
+ $handlerParams = $this->makeSessionHandlerParams(
+ $overrideSoapClient
+ );
+
+ $handler = new SoapHeader2($handlerParams);
+
+ //SEND MESSAGE AND CHECK RESULT
+ $actualSendResult = $handler->sendMessage(
+ 'Security_Authenticate',
+ new Client\Struct\Security\Authenticate(
+ new Client\RequestOptions\SecurityAuthenticateOptions(
+ $handlerParams->authParams
+ )
+ ),
+ [
+ 'asString' => false,
+ 'endSession' => false
+ ]
+ );
+
+ $this->assertEquals($messageResult, $actualSendResult);
+
+ //ASSERT THAT THE SESSION HAS BEEN STARTED CORRECTLY
+ $expectedSessionData = [
+ 'sessionId' => 'IROZERIIOP',
+ 'sequenceNumber' => 1,
+ 'securityToken' => 'FDKLSDMJFSMLRJEZRHZJ'
+ ];
+
+ $this->assertEquals(
+ $expectedSessionData,
+ $handler->getSessionData()
+ );
+ }
+
+ public function testGetLastRequestEmptyWithNoMessages()
+ {
+
+ $handlerParams = $this->makeSessionHandlerParams();
+
+ $handler = new SoapHeader2($handlerParams);
+
+ $result = $handler->getLastRequest();
+
+ $this->assertNull($result);
+ }
+
+ /**
+ * @param \SoapClient|null $overrideSoapClient
+ * @return SessionHandlerParams
+ */
+ protected function makeSessionHandlerParams($overrideSoapClient = null)
+ {
+ $wsdlpath = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'testfiles' . DIRECTORY_SEPARATOR . 'soapheader2' . DIRECTORY_SEPARATOR . 'testwsdlsoapheader2.wsdl';
+
+ $par = new SessionHandlerParams([
+ 'wsdl' => realpath($wsdlpath),
+ 'soapHeaderVersion' => Client::HEADER_V2,
+ 'receivedFrom' => 'unittests',
+ 'logger' => new NullLogger(),
+ 'overrideSoapClient' => $overrideSoapClient,
+ 'authParams' => [
+ 'officeId' => 'BRUXX0000',
+ 'originatorTypeCode' => 'U',
+ 'userId' => 'DUMMYORIG',
+ 'organizationId' => 'DUMMYORG',
+ 'passwordLength' => 12,
+ 'passwordData' => 'dGhlIHBhc3N3b3Jk'
+ ]
+ ]);
+
+ return $par;
+ }
+}
diff --git a/tests/Amadeus/Client/Session/Handler/testfiles/dummyPnrReplyExtractedMessageSoapHeader2.txt b/tests/Amadeus/Client/Session/Handler/testfiles/dummyPnrReplyExtractedMessageSoapHeader2.txt
new file mode 100644
index 000000000..45bdfda32
--- /dev/null
+++ b/tests/Amadeus/Client/Session/Handler/testfiles/dummyPnrReplyExtractedMessageSoapHeader2.txt
@@ -0,0 +1 @@
+1AABC123090914RPXXXXBRUBGXXXXxxxBRUBGXXXXBRUBRUBGXXXY0001AA090914000000007173P12--- TST RLR ---000000BRUBGXXXXT1ABRUBE0000000BRUBGXXXYE1ABRUBE000000000BRUBGXXXYE1ABRUBE302015311PT2NM1BOWIE1DAVID MRST1AIR210031507551003151020BRUMADIB3207NET1IBABC1231HK321024ST2AIR311031519351103152155MADBRUIB3208NET1IBABC1231HK321034OT7AP4350322112121212-BOT22TK5TL100914BRUBGXXXXOT8OS6328YYDAVIDBOWIE//AMADEUS.COMOT6RM7RMPRICING ENTRY FXP/R,UP,BRU.BRUST1ST2PT2OT9RM8RMMODETICKETOT11RM9RMTIDBOWIEXDAVOT12RM10RMTSA INFORMATION OMITTED ON PURPOSEPT2OT13RM11RMAGENT FEE OF 10.00 EUR VISIBLE IN FEEOT14RM12RMFARE197.52 EURPT2OT15RM13RMFARE :197.52 EURST1ST2OT19RM14RMCOSECONOMY RESTRICTEDST1ST2OT20RM15RMMOPINVOICING TO CORPORATIONOT21RM16RMFTYPRIVATEST1ST2PT2OT16RM17RM*BOOKED BY AMADEUS E-TRAVEL MANAGEMENTOT17RM18RM*TRP/RECBUSOT18RM19RM*TRP/RETBUSINESSOT26RM20RM*ACERMK-FEE-ETMOT4FE21310PAX 22 NOREF-NON END/NO CHGSST1ST2PT2OT23FP22316CASHOT5FV233P18PAX IBST1ST2PT2OT10AB2432A DUMMY ADDRESS
\ No newline at end of file
diff --git a/tests/Amadeus/Client/Session/Handler/testfiles/dummyPnrReplysoapheader2.txt b/tests/Amadeus/Client/Session/Handler/testfiles/dummyPnrReplysoapheader2.txt
new file mode 100644
index 000000000..33a9f4476
--- /dev/null
+++ b/tests/Amadeus/Client/Session/Handler/testfiles/dummyPnrReplysoapheader2.txt
@@ -0,0 +1 @@
+XFHZEKLRZHREJ13RKLERJEZLKRHZEJKLRHEZJKLREZRHEZK1AABC123090914RPXXXXBRUBGXXXXxxxBRUBGXXXXBRUBRUBGXXXY0001AA090914000000007173P12--- TST RLR ---000000BRUBGXXXXT1ABRUBE0000000BRUBGXXXYE1ABRUBE000000000BRUBGXXXYE1ABRUBE302015311PT2NM1BOWIE1DAVID MRST1AIR210031507551003151020BRUMADIB3207NET1IBABC1231HK321024ST2AIR311031519351103152155MADBRUIB3208NET1IBABC1231HK321034OT7AP4350322112121212-BOT22TK5TL100914BRUBGXXXXOT8OS6328YYDAVIDBOWIE//AMADEUS.COMOT6RM7RMPRICING ENTRY FXP/R,UP,BRU.BRUST1ST2PT2OT9RM8RMMODETICKETOT11RM9RMTIDBOWIEXDAVOT12RM10RMTSA INFORMATION OMITTED ON PURPOSEPT2OT13RM11RMAGENT FEE OF 10.00 EUR VISIBLE IN FEEOT14RM12RMFARE197.52 EURPT2OT15RM13RMFARE :197.52 EURST1ST2OT19RM14RMCOSECONOMY RESTRICTEDST1ST2OT20RM15RMMOPINVOICING TO CORPORATIONOT21RM16RMFTYPRIVATEST1ST2PT2OT16RM17RM*BOOKED BY AMADEUS E-TRAVEL MANAGEMENTOT17RM18RM*TRP/RECBUSOT18RM19RM*TRP/RETBUSINESSOT26RM20RM*ACERMK-FEE-ETMOT4FE21310PAX 22 NOREF-NON END/NO CHGSST1ST2PT2OT23FP22316CASHOT5FV233P18PAX IBST1ST2PT2OT10AB2432A DUMMY ADDRESS
\ No newline at end of file
diff --git a/tests/Amadeus/Client/Session/Handler/testfiles/dummyPnrRequestsoapheader2.txt b/tests/Amadeus/Client/Session/Handler/testfiles/dummyPnrRequestsoapheader2.txt
new file mode 100644
index 000000000..8f5767b6a
--- /dev/null
+++ b/tests/Amadeus/Client/Session/Handler/testfiles/dummyPnrRequestsoapheader2.txt
@@ -0,0 +1,2 @@
+
+XFHZEKLRZHREJ13RKLERJEZLKRHZEJKLRHEZJKLREZRHEZK2ABC123
\ No newline at end of file
diff --git a/tests/Amadeus/Client/Session/Handler/testfiles/soapheader2/PriceXplorer_ExtremeSearchReply_10_3_1A.xsd b/tests/Amadeus/Client/Session/Handler/testfiles/soapheader2/PriceXplorer_ExtremeSearchReply_10_3_1A.xsd
new file mode 100644
index 000000000..7db1e9361
--- /dev/null
+++ b/tests/Amadeus/Client/Session/Handler/testfiles/soapheader2/PriceXplorer_ExtremeSearchReply_10_3_1A.xsd
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/Amadeus/Client/Session/Handler/testfiles/soapheader2/PriceXplorer_ExtremeSearch_10_3_1A.xsd b/tests/Amadeus/Client/Session/Handler/testfiles/soapheader2/PriceXplorer_ExtremeSearch_10_3_1A.xsd
new file mode 100644
index 000000000..fe8fdc736
--- /dev/null
+++ b/tests/Amadeus/Client/Session/Handler/testfiles/soapheader2/PriceXplorer_ExtremeSearch_10_3_1A.xsd
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/Amadeus/Client/Session/Handler/testfiles/soapheader2/Security_AuthenticateReply_06_1_1A.xsd b/tests/Amadeus/Client/Session/Handler/testfiles/soapheader2/Security_AuthenticateReply_06_1_1A.xsd
new file mode 100644
index 000000000..3d478f50b
--- /dev/null
+++ b/tests/Amadeus/Client/Session/Handler/testfiles/soapheader2/Security_AuthenticateReply_06_1_1A.xsd
@@ -0,0 +1,173 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Format limitations: an..5
+
+
+
+
+
+
+
+
+
+
+ Format limitations: an..3
+
+
+
+
+
+
+
+
+
+
+ Format limitations: an..3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Format limitations: an..3
+
+
+
+
+
+
+
+
+
+
+ Format limitations: an..4
+
+
+
+
+
+
+
+
+
+
+ Format limitations: an..3
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Format limitations: an..70
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Format limitations: a..6
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Format limitations: an..10
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Format limitations: an..10
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/Amadeus/Client/Session/Handler/testfiles/soapheader2/Security_Authenticate_06_1_1A.xsd b/tests/Amadeus/Client/Session/Handler/testfiles/soapheader2/Security_Authenticate_06_1_1A.xsd
new file mode 100644
index 000000000..31b9c6201
--- /dev/null
+++ b/tests/Amadeus/Client/Session/Handler/testfiles/soapheader2/Security_Authenticate_06_1_1A.xsd
@@ -0,0 +1,367 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ Format limitations: an..35
+
+
+
+
+
+
+
+
+
+
+ Format limitations: an..35
+
+
+
+
+
+
+
+
+
+
+ Format limitations: an..14
+
+
+
+
+
+
+
+
+
+
+ Format limitations: an..14
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Format limitations: an..9
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Format limitations: an1
+
+
+
+
+
+
+
+
+
+
+ Format limitations: an..30
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Format limitations: an..3
+
+
+
+
+
+
+
+
+
+
+ Format limitations: an..35
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Format limitations: an..35
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Format limitations: an..35
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Format limitations: an1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Format limitations: n..15
+
+
+
+
+
+
+
+
+ Format limitations: an1
+
+
+
+
+
+
+
+
+
+
+ Format limitations: an..99999
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Format limitations: an..3
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Format limitations: an..35
+
+
+
+
+
+
+
+
+
+
+ Format limitations: an..17
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Format limitations: an..25
+
+
+
+
+
+
+
+
+
+
+ Format limitations: an..17
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Format limitations: an..3
+
+
+
+
+
+
+
+
+
+
+ Format limitations: an..5
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Format limitations: an..35
+
+
+
+
+
+
+
+
+
+
+ Format limitations: an..6
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/Amadeus/Client/Session/Handler/testfiles/soapheader2/Security_SignOutReply_04_1_1A.xsd b/tests/Amadeus/Client/Session/Handler/testfiles/soapheader2/Security_SignOutReply_04_1_1A.xsd
new file mode 100644
index 000000000..74c9cb884
--- /dev/null
+++ b/tests/Amadeus/Client/Session/Handler/testfiles/soapheader2/Security_SignOutReply_04_1_1A.xsd
@@ -0,0 +1,133 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Format limitations: an..5
+
+
+
+
+
+
+
+
+
+
+ Format limitations: an..3
+
+
+
+
+
+
+
+
+
+
+ Format limitations: an..3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Format limitations: an..3
+
+
+
+
+
+
+
+
+
+
+ Format limitations: an..4
+
+
+
+
+
+
+
+
+
+
+ Format limitations: an..3
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Format limitations: an..70
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Format limitations: a..6
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/Amadeus/Client/Session/Handler/testfiles/soapheader2/Security_SignOut_04_1_1A.xsd b/tests/Amadeus/Client/Session/Handler/testfiles/soapheader2/Security_SignOut_04_1_1A.xsd
new file mode 100644
index 000000000..b6239ab6d
--- /dev/null
+++ b/tests/Amadeus/Client/Session/Handler/testfiles/soapheader2/Security_SignOut_04_1_1A.xsd
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ Format limitations: an..35
+
+
+
+
+
+
+
+
+
+
+ Format limitations: an..35
+
+
+
+
+
+
+
+
+
+
+ Format limitations: an..14
+
+
+
+
+
+
+
+
+
+
+ Format limitations: an..14
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/Amadeus/Client/Session/Handler/testfiles/soapheader2/WBS_Session-2.0.xsd b/tests/Amadeus/Client/Session/Handler/testfiles/soapheader2/WBS_Session-2.0.xsd
new file mode 100644
index 000000000..fcf3ad6ab
--- /dev/null
+++ b/tests/Amadeus/Client/Session/Handler/testfiles/soapheader2/WBS_Session-2.0.xsd
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+ This element defines the identifier part of the SessionId.
+
+
+
+
+ This element defines the sequence number of the SessionId.
+
+
+
+
+ This element defines the SecurityToken of the SessionId.
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/Amadeus/Client/Session/Handler/testfiles/soapheader2/dummySecurityAuth.txt b/tests/Amadeus/Client/Session/Handler/testfiles/soapheader2/dummySecurityAuth.txt
new file mode 100644
index 000000000..18cac6001
--- /dev/null
+++ b/tests/Amadeus/Client/Session/Handler/testfiles/soapheader2/dummySecurityAuth.txt
@@ -0,0 +1,2 @@
+
+BRUXX0000UDUMMYORIGDUTSUDUMMYORG12EdGhlIHBhc3N3b3Jk
\ No newline at end of file
diff --git a/tests/Amadeus/Client/Session/Handler/testfiles/soapheader2/dummySecurityAuthReply.txt b/tests/Amadeus/Client/Session/Handler/testfiles/soapheader2/dummySecurityAuthReply.txt
new file mode 100644
index 000000000..efd636d83
--- /dev/null
+++ b/tests/Amadeus/Client/Session/Handler/testfiles/soapheader2/dummySecurityAuthReply.txt
@@ -0,0 +1 @@
+IROZERIIOP1FDKLSDMJFSMLRJEZRHZJP
\ No newline at end of file
diff --git a/tests/Amadeus/Client/Session/Handler/testfiles/soapheader2/testwsdlsoapheader2.wsdl b/tests/Amadeus/Client/Session/Handler/testfiles/soapheader2/testwsdlsoapheader2.wsdl
new file mode 100644
index 000000000..70c6a5bca
--- /dev/null
+++ b/tests/Amadeus/Client/Session/Handler/testfiles/soapheader2/testwsdlsoapheader2.wsdl
@@ -0,0 +1,91 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/Amadeus/Client/Struct/Security/AuthenticateTest.php b/tests/Amadeus/Client/Struct/Security/AuthenticateTest.php
new file mode 100644
index 000000000..2d4946308
--- /dev/null
+++ b/tests/Amadeus/Client/Struct/Security/AuthenticateTest.php
@@ -0,0 +1,70 @@
+
+ */
+class AuthenticateTest extends BaseTestCase
+{
+
+ public function testCanConstructAuthMessage()
+ {
+ $authParams = new AuthParams([
+ 'officeId' => 'BRUXXXXXX',
+ 'originatorTypeCode' => 'U',
+ 'userId' => 'WSXXXXXX',
+ 'passwordData' => base64_encode('TEST'),
+ 'passwordLength' => 4,
+ 'dutyCode' => 'SU',
+ 'organizationId' => 'DUMMY-ORG',
+ ]);
+
+ $reqOpt = new SecurityAuthenticateOptions($authParams);
+
+ $message = new Authenticate($reqOpt);
+
+ $this->assertEquals('BRUXXXXXX' , $message->userIdentifier->originIdentification->sourceOffice);
+ $this->assertEquals('U' , $message->userIdentifier->originatorTypeCode);
+ $this->assertEquals('WSXXXXXX' , $message->userIdentifier->originator);
+
+ $this->assertEquals('DUT' , $message->dutyCode->dutyCodeDetails->referenceQualifier);
+ $this->assertEquals('SU' , $message->dutyCode->dutyCodeDetails->referenceIdentifier);
+
+ $this->assertEquals('DUMMY-ORG' , $message->systemDetails->organizationDetails->organizationId);
+
+ $this->assertEquals(PasswordInfo::DATA_TYPE_EDIFACT , $message->passwordInfo->dataType);
+ $this->assertEquals(4 , $message->passwordInfo->dataLength);
+ $this->assertEquals(base64_encode('TEST') , $message->passwordInfo->binaryData);
+
+ }
+}
diff --git a/tests/Amadeus/ClientTest.php b/tests/Amadeus/ClientTest.php
index dcd526a30..3ab45ba67 100644
--- a/tests/Amadeus/ClientTest.php
+++ b/tests/Amadeus/ClientTest.php
@@ -74,6 +74,29 @@ public function testCanCreateClientWithOverriddenSessionHandlerRequestCreatorAnd
$this->assertInstanceOf('Amadeus\Client', $client);
}
+ public function testCanCreateClientWithAuthOptionsAndSessionParams()
+ {
+ $par = new Params([
+ 'authParams' => [
+ 'officeId' => 'BRUXXXXXX',
+ 'originatorTypeCode' => 'U',
+ 'userId' => 'WSXXXXXX',
+ 'passwordData' => base64_encode('TEST')
+ ],
+ 'sessionHandlerParams' => [
+ 'wsdl' => $this->makePathToDummyWSDL(),
+ 'stateful' => true,
+ 'logger' => new NullLogger()
+ ],
+ 'requestCreatorParams' => [
+ 'receivedFrom' => 'some RF string'
+ ]
+ ]);
+
+ $client = new Client($par);
+
+ $this->assertTrue($client->isStateful());
+ }
/**
* @dataProvider dataProviderMakeMessageOptions
@@ -1354,6 +1377,88 @@ public function testCanDoSignOutCall()
$this->assertEquals($messageResult, $response);
}
+ public function testCanDoAuthenticateCall()
+ {
+ $mockSessionHandler = $this->getMockBuilder('Amadeus\Client\Session\Handler\HandlerInterface')->getMock();
+
+ $authParams = new Params\AuthParams([
+ 'officeId' => 'BRUXXXXXX',
+ 'originatorTypeCode' => 'U',
+ 'userId' => 'WSXXXXXX',
+ 'passwordData' => base64_encode('TEST'),
+ 'passwordLength' => 4,
+ 'dutyCode' => 'SU',
+ 'organizationId' => 'DUMMY-ORG',
+ ]);
+
+ $messageResult = new \stdClass();
+ $messageResult->processStatus = new \stdClass();
+ $messageResult->processStatus->statusCode = 'P';
+
+ $expectedMessageResult = new Client\Struct\Security\Authenticate(
+ new Client\RequestOptions\SecurityAuthenticateOptions(
+ $authParams
+ )
+ );
+
+ $mockSessionHandler
+ ->expects($this->once())
+ ->method('sendMessage')
+ ->with('Security_Authenticate', $expectedMessageResult, ['asString' => false, 'endSession' => false])
+ ->will($this->returnValue($messageResult));
+ $mockSessionHandler
+ ->expects($this->never())
+ ->method('getLastResponse');
+ $mockSessionHandler
+ ->expects($this->once())
+ ->method('getMessagesAndVersions')
+ ->will($this->returnValue(['Security_Authenticate' => "6.1"]));
+
+ $par = new Params();
+ $par->authParams = $authParams;
+ $par->sessionHandler = $mockSessionHandler;
+ $par->requestCreatorParams = new Params\RequestCreatorParams([
+ 'receivedFrom' => 'some RF string',
+ 'originatorOfficeId' => 'BRUXXXXXX'
+ ]);
+
+ $client = new Client($par);
+
+ $response = $client->securityAuthenticate();
+
+ $this->assertEquals($messageResult, $response);
+ }
+
+ public function testCanSetSessionData()
+ {
+ $mockSessionHandler = $this->getMockBuilder('Amadeus\Client\Session\Handler\HandlerInterface')->getMock();
+
+ $dummySessionData = [
+ 'sessionId' => 'XFHZEKLRZHREJ',
+ 'sequenceNumber' => 12,
+ 'securityToken' => 'RKLERJEZLKRHZEJKLRHEZJKLREZRHEZK'
+ ];
+
+ $mockSessionHandler
+ ->expects($this->once())
+ ->method('setSessionData')
+ ->with($dummySessionData)
+ ->will($this->returnValue(true));
+
+ $par = new Params();
+ $par->sessionHandler = $mockSessionHandler;
+ $par->requestCreatorParams = new Params\RequestCreatorParams([
+ 'receivedFrom' => 'some RF string',
+ 'originatorOfficeId' => 'BRUXXXXXX'
+ ]);
+
+ $client = new Client($par);
+
+ $result = $client->setSessionData($dummySessionData);
+
+ $this->assertTrue($result);
+ }
+
public function testCanGetSessionInfo()
{
$mockSessionHandler = $this->getMockBuilder('Amadeus\Client\Session\Handler\HandlerInterface')->getMock();
@@ -1385,6 +1490,7 @@ public function testCanGetSessionInfo()
+
public function dataProviderMakeMessageOptions()
{
return [