From 0540df3b3086b04058b898b12e6b832d6aeaf432 Mon Sep 17 00:00:00 2001 From: Matt Peel Date: Wed, 8 Sep 2021 01:20:19 +1200 Subject: [PATCH 1/3] Add phpcs linting and code coverage via codecov.io. Linting supports both PHP 7.4 and 8.0. **Changes:** - No longer catch exceptions in GlobalAuthenticationService->verifyIdentity() - we just immediately re-threw it anyway - Allow both $gateway and $soapOptions arguments to GlobalAuthenticationService constructor to be optional (backwards compatibility with 0.2, and make ->setApiUsername() etc actually useful) - Add return type hints where-ever they were missing - Add phpdocs where-ever they were missing - Don't pass `null` into SoapVar object creation as it should be a string - Lots of other changes to comply with linting rules (no significant code changes) - Ensure all files are using strict_types=1 **Tests & linting:** - Include strict slevomat/coding-standard module for additional phpcs checks - Configure phpcs.xml.dist with specific linting rules (based on PSR-12 and slevomat/coding-standard defaults, with minor tweaks) - Run full linting pass - Approx ~150 changes to comply with linting rules - Add code coverage to phpunit run - Via GitHub Actions, upload code coverage information to codecov.io - Include php-parallel-lint and phpcs to GitHub Actions workflow, rename from phpunit.yml to run-tests.yml - Allow BandText to be changed during test runs and add a new test for it **Documentation:** - Move the full PHP code example from README.md into new docs/full-code-example.md and link through - Add new documentation covering various module settings to README.md - Update full code example with descriptions for key classes, and remove outdated info **Minor:** - Update .gitignore to ignore new .artifacts directory and re-order alphabetically --- .../workflows/{phpunit.yml => run-tests.yml} | 21 ++- .gitignore | 5 +- README.md | 162 +++++------------- composer.json | 5 +- docs/full-code-example.md | 102 +++++++++++ phpcs.xml.dist | 102 +++++++++++ phpunit.xml.dist | 9 +- .../IdentityVerificationFailureException.php | 29 +++- src/Gateway/GlobalAuthenticationGateway.php | 8 +- src/Gateway/ID3GlobalBaseGateway.php | 21 ++- src/Gateway/Request/AuthenticateSPRequest.php | 115 +++++++------ .../SoapClient/ID3GlobalSoapClient.php | 19 +- src/Gateway/SoapClient/ID3WsseAuthHeader.php | 44 +++-- src/Identity/Address/Address.php | 2 + src/Identity/Address/AddressContainer.php | 2 + src/Identity/Address/FixedFormatAddress.php | 134 +-------------- src/Identity/Address/FreeFormatAddress.php | 109 +----------- src/Identity/ContactDetails.php | 43 +---- src/Identity/ContactDetails/PhoneNumber.php | 13 +- src/Identity/Documents/DocumentContainer.php | 38 ++-- .../Documents/InternationalPassport.php | 114 ++---------- src/Identity/Documents/NZ/DrivingLicence.php | 30 +--- src/Identity/ID3IdentityObject.php | 13 +- src/Identity/Identity.php | 40 +---- src/Identity/PersonalDetails.php | 102 +++-------- src/Service/GlobalAuthenticationService.php | 136 +++++++++------ src/Service/ID3BaseService.php | 18 +- .../GlobalAuthenticationGatewayFake.php | 62 ++++--- .../Request/AuthenticateSPRequestTest.php | 32 ++-- .../GlobalAuthenticationServiceTest.php | 60 ++++--- 30 files changed, 699 insertions(+), 891 deletions(-) rename .github/workflows/{phpunit.yml => run-tests.yml} (53%) create mode 100644 docs/full-code-example.md create mode 100644 phpcs.xml.dist diff --git a/.github/workflows/phpunit.yml b/.github/workflows/run-tests.yml similarity index 53% rename from .github/workflows/phpunit.yml rename to .github/workflows/run-tests.yml index 8462206..df0dc8b 100644 --- a/.github/workflows/phpunit.yml +++ b/.github/workflows/run-tests.yml @@ -1,10 +1,9 @@ -name: PHP Composer +name: Run PHP Parallel Lint, PHP CodeSniffer, and PHPUnit tests on: [ push, pull_request ] jobs: build: - runs-on: ubuntu-latest steps: @@ -25,8 +24,20 @@ jobs: - name: Install dependencies run: composer install --prefer-dist --no-progress - # Add a test script to composer.json, for instance: "test": "vendor/bin/phpunit" - # Docs: https://getcomposer.org/doc/articles/scripts.md + - name: Run PHP Parallel Lint + run: vendor/bin/parallel-lint . --exclude vendor + + - name: Run phpcs + run: vendor/bin/phpcs -s - name: Run test suite - run: vendor/bin/phpunit + run: XDEBUG_MODE=coverage vendor/bin/phpunit + + - name: Upload code coverage to Codecov + uses: codecov/codecov-action@v2 + with: + token: ${{ secrets.CODECOV_TOKEN }} + directory: ./.artifacts + fail_ci_if_error: true + flags: phpunit + verbose: true diff --git a/.gitignore b/.gitignore index b1521b6..cc041d3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ +/.artifacts /.idea +/.phpunit.result.cache +/composer.lock /vendor -.phpunit.result.cache -*.lock diff --git a/README.md b/README.md index 3341b3f..1a13e28 100644 --- a/README.md +++ b/README.md @@ -14,124 +14,52 @@ The WSDL file gives an overview of the values that can be provided, these will v * [Online WSDL viewer](http://www.id3globalsupport.com/Website/content/Web-Service/WSDL%20Page/WSDL%20HTML/ID3%20Global%20WSDL-%20Live.xhtml) * [Sample code per country](http://www.id3globalsupport.com/Website/Sample-Code.html) -*Note:* The code below is entirely subject to change. It is primarily focused at the moment around the `AuthenticateSP` method of the ID3global API, and specifically on New Zealand (Aotearoa), however it should be generic enough to easily support other countries. +Please see the [Full Code Example](docs/full-code-example.md) that provides a complete overview of usage of this module. + +### Accessing the underlying ID3global request and response +Depending on your use case, you may need to access the underlying request sent to ID3global, or the response returned by the ID3global API. Typical use cases of this are for auditing purposes - to confirm that identity information hasn't changed since the last time an identity verification was performed for example. + +In order to facilitate this, the `GlobalAuthenticationService` class has a number of helper methods to give you access to the underlying data. All of the below code assumes that you have already called the `->verifyIdentity()` method and that either you have a valid BandText, or you have caught the `IdentityVerificationFailureException` that may be thrown. ```php -/** - * Namespaces: - * - * \ID3Global\Constants\Identity - * \ID3Global\Gateways\GlobalAuthenticationGateway - * \ID3Global\Services\GlobalAuthenticationService - * \ID3Global\Identity\Address\FreeFormatAddress - * \ID3Global\Identity\Address\FixedFormatAddress - * \ID3Global\Identity\ContactDetails - * \ID3Global\Identity\ContactDetails\LandTelephone - * \ID3Global\Identity\ContactDetails\MobileTelephone - * \ID3Global\Identity\ContactDetails\WorkTelephone - * \ID3Global\Identity\Documents\NZ\DrivingLicence - * \ID3Global\Identity\PersonalDetails - * - * \ID3Global\Identity\Addresses<\ID3Global\Identity\Address\FreeFormatAddress, \ID3Global\Identity\Address\FixedFormatAddress> - * - CurrentAddress - * - PreviousAddress[1-3] - * - HistoricAddresses<\ID3Global\Identity\Address\FreeFormatAddress, \ID3Global\Identity\Address\FixedFormatAddress> - * - * \ID3Global\Identity\Documents - * - * Not core for implementation - * \ID3Global\Identity\Aliases - * \ID3Global\Identity\AlternateName - * \ID3Global\Identity\BankingDetails\BankAccount - * \ID3Global\Identity\BankingDetails\CreditDebitCard - * \ID3Global\Identity\Documents\Address\UK\ElectricitySupplier - * \ID3Global\Identity\Documents\Identity\Global\InternationalPassport - * \ID3Global\Identity\Documents\Identity\Europe\EuropeanIdentityCard - * \ID3Global\Identity\Documents\Identity\AU\ShortPassport - * \ID3Global\Identity\Documents\Identity\AU\Medicare - * \ID3Global\Identity\Documents\Identity\BR\CPFNumber - * \ID3Global\Identity\Documents\Identity\CA\SocialInsuranceNumber - * \ID3Global\Identity\Documents\Identity\CN\ResidentIdentityCard - * \ID3Global\Identity\Documents\Identity\ES\TaxIDNumber - * \ID3Global\Identity\Documents\Identity\MX\TaxIdentificationNumber - * \ID3Global\Identity\Documents\Identity\UK\Passport - * \ID3Global\Identity\Documents\Identity\UK\DrivingLicence - * \ID3Global\Identity\Documents\Identity\UK\NationalInsuranceNumber - * \ID3Global\Identity\Documents\Identity\UK\DrivingLicence - * \ID3Global\Identity\Documents\Identity\US\DrivingLicence - * \ID3Global\Identity\Documents\Identity\US\SocialSecurity - * \ID3Global\Identity\Documents\Identity\US\IdentityCard - * \ID3Global\Identity\Employment - * \ID3Global\Identity\GlobalGeneric - * \ID3Global\Identity\Images - * \ID3Global\Identity\Location - * \ID3Global\Identity\PersonalDetails\BirthInfo - */ - -$birthday = DateTime::createFromFormat('Y-m-d', '1922-08-20'); -$personalDetails = new \ID3Global\Identity\PersonalDetails(); -$personalDetails - ->setTitle('Mr') - ->setForeName('Dworkin') - ->setMiddleName('John') - ->setSurname('Barimen') - ->setGender('male') - ->setDateOfBirth($birthday); - -$currentAddress = new \ID3Global\Identity\Address\FreeFormatAddress(); -$currentAddress - ->setCountry('New Zealand') - ->setPostCode('90210') - // You can set up to 8 address lines if required using ->setAddressLine3(), ->setAddressLine8() etc. - ->setAddressLine1('Dungeon 1') - ->setAddressLine2('Courts of Amber'); - -$addressContainer = new \ID3Global\Identity\Address\AddressContainer(); -$addressContainer->setCurrentAddress($currentAddress); - -$phone = new \ID3Global\Identity\ContactDetails\PhoneNumber(); -$phone->setNumber(1234567890); - -$contactDetails = new \ID3Global\Identity\ContactDetails(); -$contactDetails - ->setLandTelephone($phone) - ->setMobileTelephone($phone) - ->setWorkTelephone($phone) - ->setEmail('dworkin@thepattern.net'); - -$internationalPassport = new \ID3Global\Identity\Documents\InternationalPassport(); -$documentContainer = new \ID3Global\Identity\Documents\DocumentContainer(); -$documentContainer->addIdentityDocument(new \ID3Global\Identity\Documents\NZ\DrivingLicence(), 'New Zealand'); - -/** - * $result will be a string representing the 'BandText' as returned by the ID3global API. By default, this may be a word - * like 'PASS', 'REFER' or 'ALERT' but could also be any string value e.g. 'Name, Address and DOB Match'. The exact - * string returned is entirely dependent on how the profile is configured within ID3global, and can vary if you adjust - * the profile id and profile version. - * - * It is up to your implementation how these are handled. Note that generally there is only a single value that - * represents an identity that has passed the necessary verification, and multiple BandTexts that represent a failing - * identity. You **must** handle this in your own code, as the ID3Global API does not provide any kind of boolean value - * for whether a given identity passed identity verification or not. - * - * An exception is thrown if the web service fails or cannot be contacted. - */ -$validIdentityBandText = 'PASS'; // See note above about how this may differ for you - -$identity = new \ID3Global\Identity\Identity(); -$identity - ->setPersonalDetails($personalDetails) - ->setAddresses($addressContainer) - ->setContactDetails($contactDetails) - ->setIdentityDocuments($documentContainer); - -$gateway = new \ID3Global\Gateway\GlobalAuthenticationGateway('username', 'password'); -$id3Service = new \ID3Global\Service\GlobalAuthenticationService($gateway); -$result = $id3Service - ->setProfileId('Profile ID as provided by ID3global interface') - ->verifyIdentity($identity, 'Unique customer reference'); - -if($result === $validIdentityBandText) { - // Identity is verified, continue processing +// Assumes $service is an instance of ID3Global\Service\GlobalAuthenticationService + +// Return the last SOAP request made to the ID3global API as a string +$lastRawRequest = $service->getLastRawRequest(); + +// Returns the SoapClient interpreted response from the API (this will be an object of type \stdClass, or null if the SOAP request failed entirely +// For example you can access the BandText of a valid response with $lastResponse->AuthenticateSPResult->BandText +$lastResponse = $service->getLastVerifyIdentityResponse(); + +// Access the underlying SoapClient object to perform more detailed debugging +$gateway = $service->getGateway(); // Returns a ID3Global\Gateway\GlobalAuthenticationGateway object +$soapClient = $gateway->getSoapClient(); // Returns a ID3Global\Gateway\SoapClient\ID3GlobalSoapClient object + +// You can then do anything you'd normally do on SoapClient, such as: +$lastRawRequestHeaders = $soapClient->__getLastRequestHeaders(); // Returns an array of the headers sent to the API +$lastRawResponse = $soapClient->__getLastResponse(); // Returns the last response returned by the API +``` + +### Debugging identity verification failures +In certain circumstances, generally when the ID3Global API produces unexpected results, you may get an `IdentityVerificationFailureException` returned to you. This can happen in a number of scenarios, such as required fields being missing from the request, or data being in an invalid format. + +You should also wrap your `->verifyIdentity()` calls within a try/catch to prevent users from seeing these exceptions. + +By default, this library does not expose information in the exception message that would leak personally identifiable information, however this can be enabled if you are confident that the exception is properly handled (e.g. is being forwarded to a GDPR-compliant logging service). Sometimes this level of detail is necessary to determine why the API request failed. + +You can enable logging of this information via the exception message with the following configuration: + +```php +$service = new ID3Global\Service\GlobalAuthenticationService; + +// Must be set before calling ->verifyIdentity() +$service->setVerboseExceptionHandling(true); + +// Either way, regardless of whether or not you enable verbose exception handling, IdentityVerificationFailureException will still contain the response +try { + $service->verifyIdentity($identity, 'customer reference'); +} catch (IdentityVerificationFailureException $e) { + /** @var stdClass $response */ + $response = $e->getResponse(); } ``` diff --git a/composer.json b/composer.json index c84ea36..339c937 100644 --- a/composer.json +++ b/composer.json @@ -12,7 +12,10 @@ }, "require-dev": { - "phpunit/phpunit": "^9.5.8" + "phpunit/phpunit": "^9.5.8", + "slevomat/coding-standard": "^7.0", + "php-parallel-lint/php-parallel-lint": "^1.3", + "php-parallel-lint/php-console-highlighter": "^0.5.0" }, "authors": [ diff --git a/docs/full-code-example.md b/docs/full-code-example.md new file mode 100644 index 0000000..9574b80 --- /dev/null +++ b/docs/full-code-example.md @@ -0,0 +1,102 @@ +# id3global-service + +## Key classes + +**Core services:** +* `ID3Global\Service\GlobalAuthenticationService`: The core service class used to request identity verification +* `ID3Global\Gateway\GlobalAuthenticationGateway`: The internal gateway class that communicates (via SOAP) with ID3global + +**Identity information:** +* `ID3Global\Identity\Identity`: The base class for a single person's identity +* `ID3Global\Identity\PersonalDetails`: A class to capture core identity information (name, date of birth etc) +* `ID3Global\Identity\ContactDetails\PhoneNumber`: Include a single phone number (can be used for landline, mobile etc) + +**Address specification:** +* `ID3Global\Identity\Address\FreeFormatAddress`: A 'free-form' address where individual address fields aren't specified +* `ID3Global\Identity\Address\FixedFormatAddress`: A fixed address format (e.g. fields for street, city, subcity etc) + +**Additional identity documents:** +* `ID3Global\Identity\Documents\DocumentContainer`: Class that contains all below documents +* `ID3Global\Identity\Documents\InternationalPassport`: Contains details about a passport +* `ID3Global\Identity\Documents\NZ\DrivingLicence`: Contains details about a New Zealand drivers licence + +## Full code example + +Below is a complete example of how to utilise this module, configuring personal details, a single address, multiple phone numbers and a passport. + +Once the identity is created, we create and submit it to the `GlobalAuthenticationService`. + +In the below example, we enable the 'pilot' site, which is the ID3global test environment. Leave this line out to query production (this will incur costs). + +Finally, please review the comment below regarding the value of `$validIdentityBandText` - it's critically important that this is correct. + +```php +$birthday = DateTime::createFromFormat('Y-m-d', '1922-08-20'); +$personalDetails = new \ID3Global\Identity\PersonalDetails(); +$personalDetails + ->setTitle('Mr') + ->setForeName('Dworkin') + ->setMiddleName('John') + ->setSurname('Barimen') + ->setGender('male') + ->setDateOfBirth($birthday); + +$currentAddress = new \ID3Global\Identity\Address\FreeFormatAddress(); +$currentAddress + ->setCountry('New Zealand') + ->setPostCode('90210') + // You can set up to 8 address lines if required using ->setAddressLine3(), ->setAddressLine8() etc. + ->setAddressLine1('Dungeon 1') + ->setAddressLine2('Courts of Amber'); + +$addressContainer = new \ID3Global\Identity\Address\AddressContainer(); +$addressContainer->setCurrentAddress($currentAddress); + +$phone = new \ID3Global\Identity\ContactDetails\PhoneNumber(); +$phone->setNumber(1234567890); + +$contactDetails = new \ID3Global\Identity\ContactDetails(); +$contactDetails + ->setLandTelephone($phone) + ->setMobileTelephone($phone) + ->setWorkTelephone($phone) + ->setEmail('dworkin@thepattern.net'); + +$internationalPassport = new \ID3Global\Identity\Documents\InternationalPassport(); +$documentContainer = new \ID3Global\Identity\Documents\DocumentContainer(); +$documentContainer->addIdentityDocument(new \ID3Global\Identity\Documents\NZ\DrivingLicence(), 'New Zealand'); + +/** + * $result will be a string representing the 'BandText' as returned by the ID3global API. By default, this may be a word + * like 'PASS', 'REFER' or 'ALERT' but could also be any string value e.g. 'Name, Address and DOB Match'. The exact + * string returned is entirely dependent on how the profile is configured within ID3global, and can vary if you adjust + * the profile id and profile version. + * + * It is up to your implementation how these are handled. Note that generally there is only a single value that + * represents an identity that has passed the necessary verification, and multiple BandTexts that represent a failing + * identity. You **must** handle this in your own code, as the ID3Global API does not provide any kind of boolean value + * for whether a given identity passed identity verification or not. + * + * An exception is thrown if the web service fails or cannot be contacted. + */ +$validIdentityBandText = 'PASS'; // See note above about how this may differ for you + +$identity = new \ID3Global\Identity\Identity(); +$identity + ->setPersonalDetails($personalDetails) + ->setAddresses($addressContainer) + ->setContactDetails($contactDetails) + ->setIdentityDocuments($documentContainer); + +$gateway = new \ID3Global\Gateway\GlobalAuthenticationGateway('username', 'password'); +$id3Service = new \ID3Global\Service\GlobalAuthenticationService($gateway); +$result = $id3Service + ->setProfileId('Profile ID as provided by ID3global interface') + ->setProfileVersion(0) + ->setPilotSiteEnabled(true) + ->verifyIdentity($identity, 'Unique customer reference'); + +if($result === $validIdentityBandText) { + // Identity is verified, continue processing +} +``` diff --git a/phpcs.xml.dist b/phpcs.xml.dist new file mode 100644 index 0000000..0eec660 --- /dev/null +++ b/phpcs.xml.dist @@ -0,0 +1,102 @@ + + + PHP Code Sniffer ruleset for id3global-service module. + + src/ + tests/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/phpunit.xml.dist b/phpunit.xml.dist index fa73348..edf052b 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,10 +1,15 @@ - + - ./src + src + + + + + ./tests/ diff --git a/src/Exceptions/IdentityVerificationFailureException.php b/src/Exceptions/IdentityVerificationFailureException.php index 1aa877c..7768fcb 100644 --- a/src/Exceptions/IdentityVerificationFailureException.php +++ b/src/Exceptions/IdentityVerificationFailureException.php @@ -1,18 +1,43 @@ response = $response; - $message = sprintf('Invalid Response returned by ID3global API. Serialized response: %s', serialize($response)); + parent::__construct($message); } diff --git a/src/Gateway/GlobalAuthenticationGateway.php b/src/Gateway/GlobalAuthenticationGateway.php index 00e6a1a..7392215 100644 --- a/src/Gateway/GlobalAuthenticationGateway.php +++ b/src/Gateway/GlobalAuthenticationGateway.php @@ -1,5 +1,7 @@ setCustomerReference($customerReference); $profile = new stdClass(); - $profile->Version = $profileVersion; - $profile->ID = $profileID; + $profile->Version = $pVer; + $profile->ID = $pId; $request->setProfileIDVersion($profile); $request->addFieldsFromIdentity($identity); diff --git a/src/Gateway/ID3GlobalBaseGateway.php b/src/Gateway/ID3GlobalBaseGateway.php index 6731eee..30e8c52 100644 --- a/src/Gateway/ID3GlobalBaseGateway.php +++ b/src/Gateway/ID3GlobalBaseGateway.php @@ -1,5 +1,7 @@ pilotSiteWsdl; } else { $wsdl = $this->liveSiteWsdl; @@ -25,12 +35,13 @@ public function __construct($username, $password, $soapClientOptions = [], $useP $defaultOptions = [ 'soap_version' => SOAP_1_1, - 'exceptions' => true, + 'exceptions' => true, + // We always enable trace so that requests and responses can be logged if required by calling applications 'trace' => true, ]; - $soapClientOptions = array_merge($defaultOptions, $soapClientOptions); + $soapClientOptions = array_merge($defaultOptions, $options); $this->setClient(new ID3GlobalSoapClient($wsdl, $username, $password, $soapClientOptions)); } diff --git a/src/Gateway/Request/AuthenticateSPRequest.php b/src/Gateway/Request/AuthenticateSPRequest.php index be66ff3..e253047 100644 --- a/src/Gateway/Request/AuthenticateSPRequest.php +++ b/src/Gateway/Request/AuthenticateSPRequest.php @@ -1,5 +1,7 @@ verifyIdentity(). */ private ?string $CustomerReference; /** - * @var stdClass + * @var stdClass The Profile ID and Version in a single stdClass object as required by the ID3global API. */ private stdClass $ProfileIDVersion; /** - * @var stdClass + * @var stdClass All other input data for an Identity to be provided to the ID3global API. */ private stdClass $InputData; - public function addFieldsFromIdentity(Identity $identity) + public function addFieldsFromIdentity(Identity $identity): void { $this->InputData = new stdClass(); @@ -38,7 +40,50 @@ public function addFieldsFromIdentity(Identity $identity) $this->addContactDetails($identity); } - private function addPersonalDetails(Identity $identity) + /** + * @return string The customer reference as provided to GlobalAuthenticationService->verifyIdentity(). + */ + public function getCustomerReference(): string + { + return $this->CustomerReference; + } + + /** + * @param ?string $CustomerReference Customer reference as provided to GlobalAuthenticationService->verifyIdentity() + * @return AuthenticateSPRequest + */ + public function setCustomerReference(?string $CustomerReference): self + { + $this->CustomerReference = $CustomerReference; + + return $this; + } + + /** + * @return stdClass A stdClass that includes ->Version and ->ID values, correlating to Profile Version and ID. + */ + public function getProfileIDVersion(): stdClass + { + return $this->ProfileIDVersion; + } + + /** + * @param stdClass $ProfileIDVersion A complete stdClass including both ->Version and ->ID values. + * @return AuthenticateSPRequest + */ + public function setProfileIDVersion(stdClass $ProfileIDVersion): self + { + $this->ProfileIDVersion = $ProfileIDVersion; + + return $this; + } + + public function getInputData(): stdClass + { + return $this->InputData; + } + + private function addPersonalDetails(Identity $identity): void { $this->InputData->Personal = new stdClass(); $personalDetails = $identity->getPersonalDetails(); @@ -48,7 +93,7 @@ private function addPersonalDetails(Identity $identity) } } - private function addAddresses(Identity $identity) + private function addAddresses(Identity $identity): void { $this->InputData->Addresses = new stdClass(); $addresses = $identity->getAddresses(); @@ -62,7 +107,7 @@ private function addAddresses(Identity $identity) } } - private function addIdentityDocuments(Identity $identity) + private function addIdentityDocuments(Identity $identity): void { $this->InputData->IdentityDocuments = new stdClass(); $documents = $identity->getIdentityDocuments(); @@ -85,7 +130,7 @@ private function addIdentityDocuments(Identity $identity) } } - private function addContactDetails(Identity $identity) + private function addContactDetails(Identity $identity): void { $this->InputData->ContactDetails = new stdClass(); $contactDetails = $identity->getContactDetails(); @@ -94,64 +139,22 @@ private function addContactDetails(Identity $identity) $this->InputData->ContactDetails->Email = $contactDetails->getEmail(); if ($contactDetails->getLandTelephone() instanceof ContactDetails\PhoneNumber) { + $number = $contactDetails->getLandTelephone()->getNumber(); $this->InputData->ContactDetails->LandTelephone = new stdClass(); - $this->InputData->ContactDetails->LandTelephone->Number = $contactDetails->getLandTelephone()->getNumber(); + $this->InputData->ContactDetails->LandTelephone->Number = $number; } if ($contactDetails->getMobileTelephone() instanceof ContactDetails\PhoneNumber) { + $number = $contactDetails->getMobileTelephone()->getNumber(); $this->InputData->ContactDetails->MobileTelephone = new stdClass(); - $this->InputData->ContactDetails->MobileTelephone->Number = $contactDetails->getMobileTelephone()->getNumber(); + $this->InputData->ContactDetails->MobileTelephone->Number = $number; } if ($contactDetails->getWorkTelephone() instanceof ContactDetails\PhoneNumber) { + $number = $contactDetails->getWorkTelephone()->getNumber(); $this->InputData->ContactDetails->WorkTelephone = new stdClass(); - $this->InputData->ContactDetails->WorkTelephone->Number = $contactDetails->getWorkTelephone()->getNumber(); + $this->InputData->ContactDetails->WorkTelephone->Number = $number; } } } - - /** - * @return ?string - */ - public function getCustomerReference(): ?string - { - return $this->CustomerReference; - } - - /** - * @param ?string $CustomerReference - * - * @return AuthenticateSPRequest - */ - public function setCustomerReference(?string $CustomerReference): AuthenticateSPRequest - { - $this->CustomerReference = $CustomerReference; - - return $this; - } - - /** - * @return stdClass - */ - public function getProfileIDVersion(): stdClass - { - return $this->ProfileIDVersion; - } - - /** - * @param stdClass $ProfileIDVersion - * - * @return AuthenticateSPRequest - */ - public function setProfileIDVersion(stdClass $ProfileIDVersion): AuthenticateSPRequest - { - $this->ProfileIDVersion = $ProfileIDVersion; - - return $this; - } - - public function getInputData(): stdClass - { - return $this->InputData; - } } diff --git a/src/Gateway/SoapClient/ID3GlobalSoapClient.php b/src/Gateway/SoapClient/ID3GlobalSoapClient.php index 4cbb0e0..8517151 100644 --- a/src/Gateway/SoapClient/ID3GlobalSoapClient.php +++ b/src/Gateway/SoapClient/ID3GlobalSoapClient.php @@ -1,16 +1,29 @@ wsseNamespace = $ns; } $auth = new stdClass(); - $auth->Username = new SoapVar($username, XSD_STRING, null, $this->wsseNamespace, null, $this->wsseNamespace); - $auth->Password = new SoapVar($password, XSD_STRING, null, $this->wsseNamespace, null, $this->wsseNamespace); + $auth->Username = new SoapVar($username, XSD_STRING, '', $this->wsseNamespace, '', $this->wsseNamespace); + $auth->Password = new SoapVar($password, XSD_STRING, '', $this->wsseNamespace, '', $this->wsseNamespace); $usernameToken = new stdClass(); - $usernameToken->UsernameToken = new SoapVar($auth, SOAP_ENC_OBJECT, null, $this->wsseNamespace, 'UsernameToken', $this->wsseNamespace); - - $token = new SoapVar($usernameToken, SOAP_ENC_OBJECT, null, $this->wsseNamespace, 'UsernameToken', $this->wsseNamespace); - - $security = new SoapVar($token, SOAP_ENC_OBJECT, null, $this->wsseNamespace, 'Security', $this->wsseNamespace); + $usernameToken->UsernameToken = new SoapVar( + $auth, + SOAP_ENC_OBJECT, + '', + $this->wsseNamespace, + 'UsernameToken', + $this->wsseNamespace + ); + + $token = new SoapVar( + $usernameToken, + SOAP_ENC_OBJECT, + '', + $this->wsseNamespace, + 'UsernameToken', + $this->wsseNamespace + ); + + $security = new SoapVar($token, SOAP_ENC_OBJECT, '', $this->wsseNamespace, 'Security', $this->wsseNamespace); parent::__construct($this->wsseNamespace, 'Security', $security, true); } diff --git a/src/Identity/Address/Address.php b/src/Identity/Address/Address.php index 8a704b2..873f19f 100644 --- a/src/Identity/Address/Address.php +++ b/src/Identity/Address/Address.php @@ -1,5 +1,7 @@ Country; } - /** - * @param string|null $country - * - * @return FixedFormatAddress - */ public function setCountry(?string $country): FixedFormatAddress { $this->Country = $country; @@ -86,19 +44,11 @@ public function setCountry(?string $country): FixedFormatAddress return $this; } - /** - * @return string|null - */ public function getStreet(): ?string { return $this->Street; } - /** - * @param string|null $street - * - * @return FixedFormatAddress - */ public function setStreet(?string $street): FixedFormatAddress { $this->Street = $street; @@ -106,19 +56,11 @@ public function setStreet(?string $street): FixedFormatAddress return $this; } - /** - * @return string|null - */ public function getSubStreet(): ?string { return $this->SubStreet; } - /** - * @param string|null $subStreet - * - * @return FixedFormatAddress - */ public function setSubStreet(?string $subStreet): FixedFormatAddress { $this->SubStreet = $subStreet; @@ -126,19 +68,11 @@ public function setSubStreet(?string $subStreet): FixedFormatAddress return $this; } - /** - * @return string|null - */ public function getCity(): ?string { return $this->City; } - /** - * @param string|null $city - * - * @return FixedFormatAddress - */ public function setCity(?string $city): FixedFormatAddress { $this->City = $city; @@ -146,19 +80,11 @@ public function setCity(?string $city): FixedFormatAddress return $this; } - /** - * @return string|null - */ public function getSubCity(): ?string { return $this->SubCity; } - /** - * @param string|null $subCity - * - * @return FixedFormatAddress - */ public function setSubCity(?string $subCity): FixedFormatAddress { $this->SubCity = $subCity; @@ -166,19 +92,11 @@ public function setSubCity(?string $subCity): FixedFormatAddress return $this; } - /** - * @return string|null - */ public function getStateDistrict(): ?string { return $this->StateDistrict; } - /** - * @param string|null $stateDistrict - * - * @return FixedFormatAddress - */ public function setStateDistrict(?string $stateDistrict): FixedFormatAddress { $this->StateDistrict = $stateDistrict; @@ -186,19 +104,11 @@ public function setStateDistrict(?string $stateDistrict): FixedFormatAddress return $this; } - /** - * @return string|null - */ public function getRegion(): ?string { return $this->Region; } - /** - * @param string|null $region - * - * @return FixedFormatAddress - */ public function setRegion(?string $region): FixedFormatAddress { $this->Region = $region; @@ -206,19 +116,11 @@ public function setRegion(?string $region): FixedFormatAddress return $this; } - /** - * @return string|null - */ public function getPrincipality(): ?string { return $this->Principality; } - /** - * @param string|null $principality - * - * @return FixedFormatAddress - */ public function setPrincipality(?string $principality): FixedFormatAddress { $this->Principality = $principality; @@ -226,19 +128,11 @@ public function setPrincipality(?string $principality): FixedFormatAddress return $this; } - /** - * @return string|null - */ public function getZipPostcode(): ?string { return $this->ZipPostcode; } - /** - * @param string|null $zipPostcode - * - * @return FixedFormatAddress - */ public function setZipPostcode(?string $zipPostcode): FixedFormatAddress { $this->ZipPostcode = $zipPostcode; @@ -246,19 +140,11 @@ public function setZipPostcode(?string $zipPostcode): FixedFormatAddress return $this; } - /** - * @return string|null - */ public function getBuilding(): ?string { return $this->Building; } - /** - * @param string|null $building - * - * @return FixedFormatAddress - */ public function setBuilding(?string $building): FixedFormatAddress { $this->Building = $building; @@ -266,19 +152,11 @@ public function setBuilding(?string $building): FixedFormatAddress return $this; } - /** - * @return string|null - */ public function getSubBuilding(): ?string { return $this->SubBuilding; } - /** - * @param string|null $subBuilding - * - * @return FixedFormatAddress - */ public function setSubBuilding(?string $subBuilding): FixedFormatAddress { $this->SubBuilding = $subBuilding; @@ -286,19 +164,11 @@ public function setSubBuilding(?string $subBuilding): FixedFormatAddress return $this; } - /** - * @return string|null - */ public function getPremise(): ?string { return $this->Premise; } - /** - * @param string|null $premise - * - * @return FixedFormatAddress - */ public function setPremise(?string $premise): FixedFormatAddress { $this->Premise = $premise; diff --git a/src/Identity/Address/FreeFormatAddress.php b/src/Identity/Address/FreeFormatAddress.php index 4b919d4..c48450c 100644 --- a/src/Identity/Address/FreeFormatAddress.php +++ b/src/Identity/Address/FreeFormatAddress.php @@ -1,74 +1,38 @@ Country; } - /** - * @param string|null $Country - * - * @return FreeFormatAddress - */ public function setCountry(?string $Country): FreeFormatAddress { $this->Country = $Country; @@ -76,19 +40,11 @@ public function setCountry(?string $Country): FreeFormatAddress return $this; } - /** - * @return string|null - */ public function getPostCode(): ?string { return $this->ZipPostcode; } - /** - * @param string|null $PostCode - * - * @return FreeFormatAddress - */ public function setPostCode(?string $PostCode): FreeFormatAddress { $this->ZipPostcode = $PostCode; @@ -96,9 +52,6 @@ public function setPostCode(?string $PostCode): FreeFormatAddress return $this; } - /** - * @return string|null - */ public function getAddressLine1(): ?string { return $this->AddressLine1; @@ -107,8 +60,6 @@ public function getAddressLine1(): ?string /** * @param string|null $AddressLine1 *? - * - * @return FreeFormatAddress */ public function setAddressLine1(?string $AddressLine1): FreeFormatAddress { @@ -117,19 +68,11 @@ public function setAddressLine1(?string $AddressLine1): FreeFormatAddress return $this; } - /** - * @return string|null - */ public function getAddressLine2(): ?string { return $this->AddressLine2; } - /** - * @param string|null $AddressLine2 - * - * @return FreeFormatAddress - */ public function setAddressLine2(?string $AddressLine2): FreeFormatAddress { $this->AddressLine2 = $AddressLine2; @@ -137,19 +80,11 @@ public function setAddressLine2(?string $AddressLine2): FreeFormatAddress return $this; } - /** - * @return string|null - */ public function getAddressLine3(): ?string { return $this->AddressLine3; } - /** - * @param string|null $AddressLine3 - * - * @return FreeFormatAddress - */ public function setAddressLine3(?string $AddressLine3): FreeFormatAddress { $this->AddressLine3 = $AddressLine3; @@ -157,19 +92,11 @@ public function setAddressLine3(?string $AddressLine3): FreeFormatAddress return $this; } - /** - * @return string|null - */ public function getAddressLine4(): ?string { return $this->AddressLine4; } - /** - * @param string|null $AddressLine4 - * - * @return FreeFormatAddress - */ public function setAddressLine4(?string $AddressLine4): FreeFormatAddress { $this->AddressLine4 = $AddressLine4; @@ -177,19 +104,11 @@ public function setAddressLine4(?string $AddressLine4): FreeFormatAddress return $this; } - /** - * @return string|null - */ public function getAddressLine5(): ?string { return $this->AddressLine5; } - /** - * @param string|null $AddressLine5 - * - * @return FreeFormatAddress - */ public function setAddressLine5(?string $AddressLine5): FreeFormatAddress { $this->AddressLine5 = $AddressLine5; @@ -197,19 +116,11 @@ public function setAddressLine5(?string $AddressLine5): FreeFormatAddress return $this; } - /** - * @return string|null - */ public function getAddressLine6(): ?string { return $this->AddressLine6; } - /** - * @param string|null $AddressLine6 - * - * @return FreeFormatAddress - */ public function setAddressLine6(?string $AddressLine6): FreeFormatAddress { $this->AddressLine6 = $AddressLine6; @@ -217,19 +128,11 @@ public function setAddressLine6(?string $AddressLine6): FreeFormatAddress return $this; } - /** - * @return string|null - */ public function getAddressLine7(): ?string { return $this->AddressLine7; } - /** - * @param string|null $AddressLine7 - * - * @return FreeFormatAddress - */ public function setAddressLine7(?string $AddressLine7): FreeFormatAddress { $this->AddressLine7 = $AddressLine7; @@ -237,19 +140,11 @@ public function setAddressLine7(?string $AddressLine7): FreeFormatAddress return $this; } - /** - * @return string|null - */ public function getAddressLine8(): ?string { return $this->AddressLine8; } - /** - * @param string|null $AddressLine8 - * - * @return FreeFormatAddress - */ public function setAddressLine8(?string $AddressLine8): FreeFormatAddress { $this->AddressLine8 = $AddressLine8; diff --git a/src/Identity/ContactDetails.php b/src/Identity/ContactDetails.php index e9cbede..7b7eb6a 100644 --- a/src/Identity/ContactDetails.php +++ b/src/Identity/ContactDetails.php @@ -1,44 +1,26 @@ LandTelephone; } - /** - * @param PhoneNumber|null $LandTelephone - * - * @return ContactDetails - */ public function setLandTelephone(?PhoneNumber $LandTelephone): ContactDetails { $this->LandTelephone = $LandTelephone; @@ -46,19 +28,11 @@ public function setLandTelephone(?PhoneNumber $LandTelephone): ContactDetails return $this; } - /** - * @return PhoneNumber|null - */ public function getMobileTelephone(): ?PhoneNumber { return $this->MobileTelephone; } - /** - * @param PhoneNumber|null $MobileTelephone - * - * @return ContactDetails - */ public function setMobileTelephone(?PhoneNumber $MobileTelephone): ContactDetails { $this->MobileTelephone = $MobileTelephone; @@ -66,19 +40,11 @@ public function setMobileTelephone(?PhoneNumber $MobileTelephone): ContactDetail return $this; } - /** - * @return PhoneNumber|null - */ public function getWorkTelephone(): ?PhoneNumber { return $this->WorkTelephone; } - /** - * @param PhoneNumber|null $WorkTelephone - * - * @return ContactDetails - */ public function setWorkTelephone(?PhoneNumber $WorkTelephone): ContactDetails { $this->WorkTelephone = $WorkTelephone; @@ -91,11 +57,6 @@ public function getEmail(): ?string return $this->Email; } - /** - * @param string|null $Email - * - * @return ContactDetails - */ public function setEmail(?string $Email): ContactDetails { $this->Email = $Email; diff --git a/src/Identity/ContactDetails/PhoneNumber.php b/src/Identity/ContactDetails/PhoneNumber.php index 17497c2..c3539cb 100644 --- a/src/Identity/ContactDetails/PhoneNumber.php +++ b/src/Identity/ContactDetails/PhoneNumber.php @@ -1,19 +1,13 @@ Number = $Number; @@ -21,9 +15,6 @@ public function setNumber(?string $Number): PhoneNumber return $this; } - /** - * @return string|null - */ public function getNumber(): ?string { return $this->Number; diff --git a/src/Identity/Documents/DocumentContainer.php b/src/Identity/Documents/DocumentContainer.php index 20b2de5..d631542 100644 --- a/src/Identity/Documents/DocumentContainer.php +++ b/src/Identity/Documents/DocumentContainer.php @@ -1,5 +1,7 @@ Used by self::addIdentityDocument() to ensure the country name is valid. Each array item is + * the country name, per ID3global documentation for the `GlobalIdentityDocuments` type, which can be viewed in + * their documentation here: https://bit.ly/2WWVHfW+ */ private array $validCountries = [ 'NewZealand', ]; - /** - * @return InternationalPassport|null - */ public function getInternationalPassport(): ?InternationalPassport { return $this->InternationalPassport; } - /** - * @param InternationalPassport $InternationalPassport - * - * @return DocumentContainer - */ - public function setInternationalPassport(InternationalPassport $InternationalPassport): DocumentContainer + public function setInternationalPassport(InternationalPassport $InternationalPassport): self { $this->InternationalPassport = $InternationalPassport; return $this; } - /** - * @return stdClass|null - */ public function getNewZealandDocuments(): ?stdClass { return $this->NewZealand; } /** - * @param ID3IdentityObject $document - * @param string $country The country to assign this document to (e.g. 'New Zealand') - * + * @param ID3IdentityObject $document An identity document to be assigned to a country-specific container + * @param string $country The country to assign this document to (e.g. 'New Zealand') * @return DocumentContainer */ - public function addIdentityDocument(ID3IdentityObject $document, string $country): DocumentContainer + public function addIdentityDocument(ID3IdentityObject $document, string $country): self { - // + // Remove any characters that aren't A-Z or a-z (e.g. "New Zealand" -> "NewZealand") $varName = preg_replace('/[^A-Za-z]*/', '', $country); $r = new ReflectionClass($document); $docType = $r->getShortName(); - if (in_array($varName, $this->validCountries)) { + if (in_array($varName, $this->validCountries, true)) { if (is_null($this->$varName)) { $this->$varName = new stdClass(); } @@ -80,6 +73,9 @@ public function addIdentityDocument(ID3IdentityObject $document, string $country return $this; } + /** + * @return array The list of all valid countries + */ public function getValidCountries(): array { return $this->validCountries; diff --git a/src/Identity/Documents/InternationalPassport.php b/src/Identity/Documents/InternationalPassport.php index 42e1ead..55d5a82 100644 --- a/src/Identity/Documents/InternationalPassport.php +++ b/src/Identity/Documents/InternationalPassport.php @@ -1,5 +1,7 @@ Number; } - /** - * @param string|null $Number - * - * @return InternationalPassport - */ public function setNumber(?string $Number): InternationalPassport { $this->Number = $Number; @@ -72,19 +66,11 @@ public function setNumber(?string $Number): InternationalPassport return $this; } - /** - * @return string|null - */ public function getShortPassportNumber(): ?string { return $this->ShortPassportNumber; } - /** - * @param string|null $ShortPassportNumber - * - * @return InternationalPassport - */ public function setShortPassportNumber(?string $ShortPassportNumber): InternationalPassport { $this->ShortPassportNumber = $ShortPassportNumber; @@ -92,19 +78,11 @@ public function setShortPassportNumber(?string $ShortPassportNumber): Internatio return $this; } - /** - * @return int|null - */ public function getExpiryDay(): ?int { return $this->ExpiryDay; } - /** - * @param int|null $ExpiryDay - * - * @return InternationalPassport - */ public function setExpiryDay(?int $ExpiryDay): InternationalPassport { $this->ExpiryDay = $ExpiryDay; @@ -112,19 +90,11 @@ public function setExpiryDay(?int $ExpiryDay): InternationalPassport return $this; } - /** - * @return int|null - */ public function getExpiryMonth(): ?int { return $this->ExpiryMonth; } - /** - * @param int|null $ExpiryMonth - * - * @return InternationalPassport - */ public function setExpiryMonth(?int $ExpiryMonth): InternationalPassport { $this->ExpiryMonth = $ExpiryMonth; @@ -132,19 +102,11 @@ public function setExpiryMonth(?int $ExpiryMonth): InternationalPassport return $this; } - /** - * @return int|null - */ public function getExpiryYear(): ?int { return $this->ExpiryYear; } - /** - * @param int|null $ExpiryYear - * - * @return InternationalPassport - */ public function setExpiryYear(?int $ExpiryYear): InternationalPassport { $this->ExpiryYear = $ExpiryYear; @@ -152,33 +114,20 @@ public function setExpiryYear(?int $ExpiryYear): InternationalPassport return $this; } - /** - * @param DateTime|null $expiryDate - * - * @return InternationalPassport - */ public function setExpiryDate(?DateTime $expiryDate): InternationalPassport { - $this->setExpiryDay($expiryDate->format('d')); - $this->setExpiryMonth($expiryDate->format('m')); - $this->setExpiryYear($expiryDate->format('Y')); + $this->setExpiryDay((int)$expiryDate->format('d')); + $this->setExpiryMonth((int)$expiryDate->format('m')); + $this->setExpiryYear((int)$expiryDate->format('Y')); return $this; } - /** - * @return int|null - */ public function getIssueDay(): ?int { return $this->IssueDay; } - /** - * @param int|null $IssueDay - * - * @return InternationalPassport - */ public function setIssueDay(?int $IssueDay): InternationalPassport { $this->IssueDay = $IssueDay; @@ -186,19 +135,11 @@ public function setIssueDay(?int $IssueDay): InternationalPassport return $this; } - /** - * @return int|null - */ public function getIssueMonth(): ?int { return $this->IssueMonth; } - /** - * @param int|null $IssueMonth - * - * @return InternationalPassport - */ public function setIssueMonth(?int $IssueMonth): InternationalPassport { $this->IssueMonth = $IssueMonth; @@ -206,19 +147,11 @@ public function setIssueMonth(?int $IssueMonth): InternationalPassport return $this; } - /** - * @return int|null - */ public function getIssueYear(): ?int { return $this->IssueYear; } - /** - * @param int|null $IssueYear - * - * @return InternationalPassport - */ public function setIssueYear(?int $IssueYear): InternationalPassport { $this->IssueYear = $IssueYear; @@ -226,33 +159,20 @@ public function setIssueYear(?int $IssueYear): InternationalPassport return $this; } - /** - * @param DateTime|null $issueDate - * - * @return InternationalPassport - */ public function setIssueDate(?DateTime $issueDate): InternationalPassport { - $this->setIssueDay($issueDate->format('d')); - $this->setIssueMonth($issueDate->format('m')); - $this->setIssueYear($issueDate->format('Y')); + $this->setIssueDay((int)$issueDate->format('d')); + $this->setIssueMonth((int)$issueDate->format('m')); + $this->setIssueYear((int)$issueDate->format('Y')); return $this; } - /** - * @return string|null - */ public function getCountryOfOrigin(): ?string { return $this->CountryOfOrigin; } - /** - * @param string $CountryOfOrigin - * - * @return InternationalPassport - */ public function setCountryOfOrigin(string $CountryOfOrigin): InternationalPassport { $this->CountryOfOrigin = $CountryOfOrigin; diff --git a/src/Identity/Documents/NZ/DrivingLicence.php b/src/Identity/Documents/NZ/DrivingLicence.php index ede0f27..efc3709 100644 --- a/src/Identity/Documents/NZ/DrivingLicence.php +++ b/src/Identity/Documents/NZ/DrivingLicence.php @@ -1,5 +1,7 @@ Number; } - /** - * @param string|null $Number - * - * @return DrivingLicence - */ public function setNumber(?string $Number): DrivingLicence { $this->Number = $Number; @@ -41,19 +35,11 @@ public function setNumber(?string $Number): DrivingLicence return $this; } - /** - * @return int|null - */ public function getVersion(): ?int { return $this->Version; } - /** - * @param int|null $Version - * - * @return DrivingLicence - */ public function setVersion(?int $Version): DrivingLicence { $this->Version = $Version; @@ -61,19 +47,11 @@ public function setVersion(?int $Version): DrivingLicence return $this; } - /** - * @return string|null - */ public function getVehicleRegistration(): ?string { return $this->VehicleRegistration; } - /** - * @param string|null $VehicleRegistration - * - * @return DrivingLicence - */ public function setVehicleRegistration(?string $VehicleRegistration): DrivingLicence { $this->VehicleRegistration = $VehicleRegistration; diff --git a/src/Identity/ID3IdentityObject.php b/src/Identity/ID3IdentityObject.php index decbb81..9eb21d6 100644 --- a/src/Identity/ID3IdentityObject.php +++ b/src/Identity/ID3IdentityObject.php @@ -1,10 +1,21 @@ personalDetails = $personalDetails; @@ -44,11 +29,6 @@ public function getPersonalDetails(): ?PersonalDetails return $this->personalDetails; } - /** - * @param ContactDetails $contactDetails - * - * @return Identity - */ public function setContactDetails(ContactDetails $contactDetails): Identity { $this->contactDetails = $contactDetails; @@ -56,19 +36,11 @@ public function setContactDetails(ContactDetails $contactDetails): Identity return $this; } - /** - * @return ContactDetails|null - */ public function getContactDetails(): ?ContactDetails { return $this->contactDetails; } - /** - * @param Address\AddressContainer $addresses - * - * @return Identity - */ public function setAddresses(AddressContainer $addresses): Identity { $this->addresses = $addresses; @@ -81,19 +53,11 @@ public function getAddresses(): ?AddressContainer return $this->addresses; } - /** - * @return DocumentContainer|null - */ public function getIdentityDocuments(): ?DocumentContainer { return $this->identityDocuments; } - /** - * @param Documents\DocumentContainer $identityDocuments - * - * @return Identity - */ public function setIdentityDocuments(DocumentContainer $identityDocuments): Identity { $this->identityDocuments = $identityDocuments; diff --git a/src/Identity/PersonalDetails.php b/src/Identity/PersonalDetails.php index 55001d4..e6dad50 100644 --- a/src/Identity/PersonalDetails.php +++ b/src/Identity/PersonalDetails.php @@ -1,5 +1,7 @@ dateOfBirth, but just the value + * as the ID3global API expects it in a singluar field). */ private ?int $DOBDay = null; /** - * @var int|null + * @var int|null The month (e.g. 1, 5, 12) the person was born in (similar to $this->dateOfBirth, but just the value + * as the ID3global API expects it in a singluar field). */ private ?int $DOBMonth = null; /** - * @var int|null + * @var int|null The year (e.g. 1995) the person was born in (similar to $this->dateOfBirth, but just the value as + * the ID3global API expects it in a singluar field). */ private ?int $DOBYear = null; /** - * @var string|null + * @var string|null The country of birth for the specified identity (e.g. 'New Zealand', 'Austria' etc) */ private ?string $CountryOfBirth = null; - /** - * @param string|null $title - * - * @return PersonalDetails - */ public function setTitle(?string $title): PersonalDetails { $this->Title = $title; @@ -68,11 +71,6 @@ public function setTitle(?string $title): PersonalDetails return $this; } - /** - * @param string|null $forename - * - * @return PersonalDetails - */ public function setForename(?string $forename): PersonalDetails { $this->Forename = $forename; @@ -80,11 +78,6 @@ public function setForename(?string $forename): PersonalDetails return $this; } - /** - * @param string|null $middleName - * - * @return PersonalDetails - */ public function setMiddleName(?string $middleName): PersonalDetails { $this->MiddleName = $middleName; @@ -92,11 +85,6 @@ public function setMiddleName(?string $middleName): PersonalDetails return $this; } - /** - * @param string|null $surname - * - * @return PersonalDetails - */ public function setSurname(?string $surname): PersonalDetails { $this->Surname = $surname; @@ -104,11 +92,6 @@ public function setSurname(?string $surname): PersonalDetails return $this; } - /** - * @param string|null $gender - * - * @return PersonalDetails - */ public function setGender(?string $gender): PersonalDetails { $this->Gender = $gender; @@ -117,30 +100,27 @@ public function setGender(?string $gender): PersonalDetails } /** - * @param DateTime|null $birthday + * Sets the date of birth for the specified identity. Populates both the 'dateOfBirth' (DateTime) field, as well as + * the individual DOBDay, DOBMonth and DOBYear fields that are actually submitted to the ID3global API. * - * @return PersonalDetails + * @param DateTime|null $birthday The date of birth for the specified identity. + * @return self */ public function setDateOfBirth(?DateTime $birthday): PersonalDetails { - if ($birthday == null) { + if ($birthday === null) { return $this; } $this->dateOfBirth = $birthday; - $this->DOBDay = $birthday->format('d') ?? null; - $this->DOBMonth = $birthday->format('m') ?? null; - $this->DOBYear = $birthday->format('Y') ?? null; + $this->DOBDay = (int)$birthday->format('d') ?? null; + $this->DOBMonth = (int)$birthday->format('m') ?? null; + $this->DOBYear = (int)$birthday->format('Y') ?? null; return $this; } - /** - * @param string|null $CountryOfBirth - * - * @return PersonalDetails - */ public function setCountryOfBirth(?string $CountryOfBirth): PersonalDetails { $this->CountryOfBirth = $CountryOfBirth; @@ -148,81 +128,51 @@ public function setCountryOfBirth(?string $CountryOfBirth): PersonalDetails return $this; } - /** - * @return string|null - */ public function getTitle(): ?string { return $this->Title; } - /** - * @return string|null - */ public function getForename(): ?string { return $this->Forename; } - /** - * @return string|null - */ public function getMiddleName(): ?string { return $this->MiddleName; } - /** - * @return string|null - */ public function getSurname(): ?string { return $this->Surname; } - /** - * @return string|null - */ public function getGender(): ?string { return $this->Gender; } - /** - * @return DateTime|null - */ public function getDateOfBirth(): ?DateTime { return $this->dateOfBirth; } - /** - * @return int|null - */ public function getDOBDay(): ?int { return $this->DOBDay; } - /** - * @return int|null - */ public function getDOBMonth(): ?int { return $this->DOBMonth; } - /** - * @return int|null - */ public function getDOBYear(): ?int { return $this->DOBYear; } - /** - * @return string|null - */ public function getCountryOfBirth(): ?string { return $this->CountryOfBirth; diff --git a/src/Service/GlobalAuthenticationService.php b/src/Service/GlobalAuthenticationService.php index 83e26a7..d77a2f1 100644 --- a/src/Service/GlobalAuthenticationService.php +++ b/src/Service/GlobalAuthenticationService.php @@ -1,5 +1,7 @@ verifyIdentity(). - * * @see self::setProfileId() */ private ?string $profileId = null; /** - * @var int The version of the Profile ID to be used when verifying identities via->verifyIdentity(). - * The special value of 0 is treated specially by ID3global and represents the 'most recent version of the profile'. - * + * @var int The version of the Profile ID to be used when verifying identities via->verifyIdentity(). The special + * value of 0 is special for ID3global and represents the 'most recent version of the profile'. * @see self::setProfileVersion() */ private int $profileVersion = 0; + /** + * @var bool Whether or not to include the full ID3global API response in exception messages. Enable only if you're + * logging exception messages to a GDPR-compliant store as this may include PII. + * @see self::setVerboseExceptionHandling() + */ + private bool $verboseExceptionHandling = false; + /** * @var Identity The most recent Identity object to be verified by the ID3global API (regardless of the outcome of - * the API request). + * the API request). + * @see self::getLastVerifiedIdentity() */ private Identity $lastIdentity; /** * @var string|null The most recent customer reference to be verified by the ID3global API (regardless of the - * outcome of the API request). + * outcome of the API request). */ private ?string $lastCustomerReference; /** - * @var stdClass|null The last response, directly from the API gateway. Can be retrieved using - * {@link getLastVerifyIdentityResponse()}. + * @var \stdClass|null The last response, directly from the API gateway. Can be retrieved using + * {@link getLastVerifyIdentityResponse()}. */ private ?stdClass $lastVerifyIdentityResponse = null; @@ -57,10 +65,23 @@ class GlobalAuthenticationService extends ID3BaseService /** * @var array Optional extras for the SOAP client + * @phpcsSuppress SlevomatCodingStandard.TypeHints.PropertyTypeHint.MissingTraversableTypeHintSpecification */ private array $soapOptions = []; - public function __construct(GlobalAuthenticationGateway $gateway, array $soapOptions = []) + /** + * When constructing this class, you can either first construct a GlobalAuthenticationGateway and pass it in, or you + * can leave this blank to use the default GlobalAuthenticationGateway. In the former case, you should set the API + * username/password and SOAP options directly on the gateway when you create it. Otherwise, you should set that on + * this service class before calling ->verifyIdentity(). + * + * @param GlobalAuthenticationGateway|null $gateway Either the gateway class to use, or null to have the service + * instantiate this gateway for you. + * @param array $soapOptions If you don't pass in a gateway and you want to configure options for the SoapClient, + * you can pass these in here, or call ->setSoapOptions() after constructing the object. + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingTraversableTypeHintSpecification + */ + public function __construct(?GlobalAuthenticationGateway $gateway, array $soapOptions = []) { $this->gateway = $gateway; $this->soapOptions = $soapOptions; @@ -80,16 +101,14 @@ public function __construct(GlobalAuthenticationGateway $gateway, array $soapOpt * Ensure you call at least ->setProfileId() prior to calling this method. * Optionally call ->setProfileVersion() if you wish to set a specific profile version to query against. * - * @param Identity $identity The full Identity object that should be verified with the ID3global API + * @param Identity $identity The full Identity object that should be verified with the ID3global API * @param string|null $customerReference A reference stored against this identity request within the ID3global - * interface. This is optional, but is highly recommended to set a reference - * and store it against the identity so that it can be later tracked if - * necessary for compliance purposes. - * + * interface. This is optional, but it's highly recommended that you set a customer reference and store it against + * the identity long-term in your own data store so that it can be later tracked if necessary for compliance + * purposes. + * @throws Exception May throw a generic Exception or SoapFault if any part of the SOAP callstack fails. * @throws IdentityVerificationFailureException Thrown specifically if the SOAP response was 'valid' according to - * SOAP but does not conform to the expected response (missing BandText or Score elements of the response). - * @throws Exception May throw a generic Exception or SoapFault if any part of the SOAP callstack fails. - * + * SOAP but does not conform to the expected response (missing BandText or Score elements of the response). * @return string The raw BandText as provided by the API. */ public function verifyIdentity(Identity $identity, ?string $customerReference = null): string @@ -108,32 +127,28 @@ public function verifyIdentity(Identity $identity, ?string $customerReference = $profileId = $this->profileId; $profileVersion = $this->profileVersion; - try { - $response = $gateway->AuthenticateSP($profileId, $profileVersion, $customerReference, $identity); - - if ($gateway->getClient() instanceof SoapClient) { - $this->lastRawRequest = $gateway->getClient()->__getLastRequest(); - } - - $validResult = false; - $this->lastVerifyIdentityResponse = $response; - - if ( - isset($response) && - isset($response->AuthenticateSPResult) && - isset($response->AuthenticateSPResult->BandText) && isset($response->AuthenticateSPResult->Score) - ) { - $validResult = true; - } - - if ($validResult) { - return $response->AuthenticateSPResult->BandText; - } else { - throw new IdentityVerificationFailureException($response); - } - } catch (Exception $e) { - throw $e; + $response = $gateway->AuthenticateSP($profileId, $profileVersion, $customerReference, $identity); + + if ($gateway->getClient() instanceof SoapClient) { + $this->lastRawRequest = $gateway->getClient()->__getLastRequest(); } + + $validResult = false; + $this->lastVerifyIdentityResponse = $response; + + if ( + isset($response) && + isset($response->AuthenticateSPResult) && + isset($response->AuthenticateSPResult->BandText) && isset($response->AuthenticateSPResult->Score) + ) { + $validResult = true; + } + + if (!$validResult) { + throw new IdentityVerificationFailureException($response, $this->getVerboseExceptionHandling()); + } + + return $response->AuthenticateSPResult->BandText; } public function setProfileId(string $profileId): self @@ -162,7 +177,7 @@ public function getProfileVersion(): int /** * @return Identity|null The last Identity object to be verified by the API (regardless of whether it was - * successfully accepted by the ID3global API or not). Returns null if ->verifyIdentity() has not yet been called. + * successfully accepted by the ID3global API or not). Returns null if ->verifyIdentity() has not yet been called. */ public function getLastVerifiedIdentity(): ?Identity { @@ -171,7 +186,7 @@ public function getLastVerifiedIdentity(): ?Identity /** * @return string|null The last customer reference value to be verified by the API (regardless of whether it was - * successfully accepted by the ID3global API or not). Returns null if ->verifyIdentity() has not yet been called. + * successfully accepted by the ID3global API or not). Returns null if ->verifyIdentity() has not yet been called. */ public function getLastCustomerReference(): ?string { @@ -180,8 +195,8 @@ public function getLastCustomerReference(): ?string /** * @return stdClass|null Either the full response as returned by ID3global, or null if no call has been made yet. If - * the request was made but failed to validate (e.g. the ID3global API returned an invalid SOAP object, this will - * still be populated. + * the request was made but failed to validate (e.g. the ID3global API returned an invalid SOAP object, this will + * still be populated. */ public function getLastVerifyIdentityResponse(): ?stdClass { @@ -196,9 +211,6 @@ public function getLastRawRequest(): ?string return $this->lastRawRequest; } - /** - * @return GlobalAuthenticationGateway - */ public function getGateway(): GlobalAuthenticationGateway { if (!$this->gateway) { @@ -213,16 +225,16 @@ public function getGateway(): GlobalAuthenticationGateway return $this->gateway; } - /** - * @param GlobalAuthenticationGateway $gateway - */ public function setGateway(GlobalAuthenticationGateway $gateway): void { $this->gateway = $gateway; } /** - * @return array + * @return array The currently configured SoapClient options. After ->getGateway() is called above, or if you + * define your own gateway when constructing this class, these may not be the actual SoapClient options specified + * (as you can access the underlying SoapClient and configure options directly on it). + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingTraversableTypeHintSpecification */ public function getSoapOptions(): array { @@ -231,8 +243,8 @@ public function getSoapOptions(): array /** * @param array $soapOptions - * * @return $this + * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingTraversableTypeHintSpecification */ public function setSoapOptions(array $soapOptions): GlobalAuthenticationService { @@ -240,4 +252,16 @@ public function setSoapOptions(array $soapOptions): GlobalAuthenticationService return $this; } + + public function getVerboseExceptionHandling(): bool + { + return $this->verboseExceptionHandling; + } + + public function setVerboseExceptionHandling(bool $val): self + { + $this->verboseExceptionHandling = $val; + + return $this; + } } diff --git a/src/Service/ID3BaseService.php b/src/Service/ID3BaseService.php index d823fdf..fff6267 100644 --- a/src/Service/ID3BaseService.php +++ b/src/Service/ID3BaseService.php @@ -1,22 +1,24 @@ pilotSiteEnabled; } - public function setPilotSiteEnabled($bool = true): ID3BaseService + public function setPilotSiteEnabled(bool $bool = true): ID3BaseService { - if (!is_bool($bool)) { - $bool = false; - } - $this->pilotSiteEnabled = $bool; return $this; @@ -41,7 +39,7 @@ public function getApiUsername(): string return $this->apiUsername; } - public function setApiUsername($username): ID3BaseService + public function setApiUsername(string $username): ID3BaseService { $this->apiUsername = $username; @@ -53,7 +51,7 @@ public function getApiPassword(): string return $this->apiPassword; } - public function setApiPassword($password): ID3BaseService + public function setApiPassword(string $password): ID3BaseService { $this->apiPassword = $password; diff --git a/src/Stubs/Gateway/GlobalAuthenticationGatewayFake.php b/src/Stubs/Gateway/GlobalAuthenticationGatewayFake.php index c707932..00da8f1 100644 --- a/src/Stubs/Gateway/GlobalAuthenticationGatewayFake.php +++ b/src/Stubs/Gateway/GlobalAuthenticationGatewayFake.php @@ -1,45 +1,42 @@ bandText = $bandText; @@ -47,26 +44,35 @@ public function setBandText(string $bandText): GlobalAuthenticationGatewayFake } /** - * @param int $score - * - * @return GlobalAuthenticationGatewayFake + * Sets a custom Score to be returned whenever AuthenticateSP is called. */ - public function setScore(int $score): GlobalAuthenticationGatewayFake + public function setScore(int $score): self { $this->score = $score; return $this; } - public function AuthenticateSP(string $profileID, int $profileVersion, ?string $customerReference, Identity $identity) + /** + * @inheritDoc + * @phpcsSuppress SlevomatCodingStandard.Functions.UnusedParameter.UnusedParameter + */ + public function AuthenticateSP(string $pId, int $pVer, ?string $customerReference, Identity $identity): stdClass { + $result = 'O:8:"stdClass":1:{s:20:"AuthenticateSPResult";O:8:"stdClass":12:{s:16:"AuthenticationID";s:36:"' + . 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";s:9:"Timestamp";s:33:"2016-01-01T00:00:00.0000000+01:00";s:11:"' + . 'CustomerRef";s:%d:"%s";s:9:"ProfileID";s:%d:"%s";s:11:"ProfileName";s:15:"Default Profile";s:14:"' + . 'ProfileVersion";i:%d;s:15:"ProfileRevision";i:1;s:12:"ProfileState";s:9:"Effective";s:11:"ResultCodes";' + . 'O:8:"stdClass":1:{s:26:"GlobalItemCheckResultCodes";a:0:{}}s:5:"Score";i:%d;s:8:"BandText";s:%d:"%s";s:7' + . ':"Country";s:11:"New Zealand";}}'; + return unserialize(sprintf( - 'O:8:"stdClass":1:{s:20:"AuthenticateSPResult";O:8:"stdClass":12:{s:16:"AuthenticationID";s:36:"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";s:9:"Timestamp";s:33:"2016-01-01T00:00:00.0000000+01:00";s:11:"CustomerRef";s:%d:"%s";s:9:"ProfileID";s:%d:"%s";s:11:"ProfileName";s:15:"Default Profile";s:14:"ProfileVersion";i:%d;s:15:"ProfileRevision";i:1;s:12:"ProfileState";s:9:"Effective";s:11:"ResultCodes";O:8:"stdClass":1:{s:26:"GlobalItemCheckResultCodes";a:0:{}}s:5:"Score";i:%d;s:8:"BandText";s:%d:"%s";s:7:"Country";s:11:"New Zealand";}}', - strlen($customerReference), + $result, + $customerReference ? strlen($customerReference) : 0, $customerReference, - strlen($profileID), - $profileID, - $profileVersion, + strlen($pId), + $pId, + $pVer, $this->score, strlen($this->bandText), $this->bandText diff --git a/tests/Gateway/Request/AuthenticateSPRequestTest.php b/tests/Gateway/Request/AuthenticateSPRequestTest.php index b69c0d4..669a6ce 100644 --- a/tests/Gateway/Request/AuthenticateSPRequestTest.php +++ b/tests/Gateway/Request/AuthenticateSPRequestTest.php @@ -1,5 +1,7 @@ identity = new Identity(); - } - - public function testStandardParams() + public function testStandardParams(): void { $version = new stdClass(); $version->Version = 1; @@ -44,7 +39,7 @@ public function testStandardParams() $this->assertEquals('X', $r->getCustomerReference()); } - public function testPersonalDetails() + public function testPersonalDetails(): void { $birthday = DateTime::createFromFormat('Y-m-d', '1973-04-05'); @@ -72,7 +67,7 @@ public function testPersonalDetails() $this->assertSame('US', $test->CountryOfBirth); } - public function testContactDetails() + public function testContactDetails(): void { $landTelephone = new ContactDetails\PhoneNumber(); $landTelephone->setNumber('1(800) 786-1410'); @@ -91,7 +86,7 @@ public function testContactDetails() $this->assertSame('1(800) 786-1410', $test->LandTelephone->Number); } - public function testInternationalPassport() + public function testInternationalPassport(): void { $issueDate = DateTime::createFromFormat('Y-m-d', '2020-01-02'); $expiryDate = DateTime::createFromFormat('Y-m-d', '2030-01-02'); @@ -122,7 +117,7 @@ public function testInternationalPassport() $this->assertSame('Azerbaijan', $test->CountryOfOrigin); } - public function testFixedLengthAddress() + public function testFixedLengthAddress(): void { $address = new FixedFormatAddress(); $address @@ -161,7 +156,7 @@ public function testFixedLengthAddress() $this->assertSame('10118', $test->ZipPostcode); } - public function testFreeFormatAddress() + public function testFreeFormatAddress(): void { $address = new FreeFormatAddress(); @@ -197,7 +192,7 @@ public function testFreeFormatAddress() $this->assertSame('NZ', $test->AddressLine8); } - public function testNZDrivingLicence() + public function testNZDrivingLicence(): void { $licence = new DrivingLicence(); @@ -218,4 +213,11 @@ public function testNZDrivingLicence() $this->assertSame(123, $test->NewZealand->DrivingLicence->Version); $this->assertSame('ABC123', $test->NewZealand->DrivingLicence->VehicleRegistration); } + + protected function setUp(): void + { + parent::setUp(); + + $this->identity = new Identity(); + } } diff --git a/tests/Service/GlobalAuthenticationServiceTest.php b/tests/Service/GlobalAuthenticationServiceTest.php index ef1b5ee..d088fd1 100644 --- a/tests/Service/GlobalAuthenticationServiceTest.php +++ b/tests/Service/GlobalAuthenticationServiceTest.php @@ -1,5 +1,7 @@ service->getLastVerifyIdentityResponse(); $this->assertSame('stdClass', get_class($response)); - $this->assertSame(GlobalAuthenticationGatewayFake::IDENTITY_BAND_PASS, $response->AuthenticateSPResult->BandText); + $this->assertSame( + GlobalAuthenticationGatewayFake::IDENTITY_BAND_PASS, + $response->AuthenticateSPResult->BandText + ); $this->assertSame('Default Profile', $response->AuthenticateSPResult->ProfileName); } /** * @dataProvider fakeResponses - * - * @param string $profileId - * @param int $profileVersion - * @param string $customerReference - * @param string $bandText - * @param int $score - * + * @param string $pId Profile ID value + * @param int $pVer Profile Version value + * @param string $custRef Customer reference submitted + * @param string $bandText The BandText to return from the fake gateway + * @param int $score The score to return from the fake gateway * @throws IdentityVerificationFailureException */ - public function testFakeResponses(string $profileId, int $profileVersion, string $customerReference, string $bandText, int $score) + public function testFakeResponses(string $pId, int $pVer, string $custRef, string $bandText, int $score): void { // Arrange $this->fakeGateway->setBandText($bandText)->setScore($score); @@ -87,19 +86,21 @@ public function testFakeResponses(string $profileId, int $profileVersion, string // Act $result = $this->service - ->setProfileId($profileId) - ->setProfileVersion($profileVersion) - ->verifyIdentity($identity, $customerReference); + ->setProfileId($pId) + ->setProfileVersion($pVer) + ->verifyIdentity($identity, $custRef); + + $response = $this->service->getLastVerifyIdentityResponse(); // Assert $this->assertSame($bandText, $result); - $this->assertSame($score, $this->service->getLastVerifyIdentityResponse()->AuthenticateSPResult->Score); - $this->assertSame($profileId, $this->service->getLastVerifyIdentityResponse()->AuthenticateSPResult->ProfileID); - $this->assertSame($profileVersion, $this->service->getLastVerifyIdentityResponse()->AuthenticateSPResult->ProfileVersion); - $this->assertSame($customerReference, $this->service->getLastVerifyIdentityResponse()->AuthenticateSPResult->CustomerRef); + $this->assertSame($score, $response->AuthenticateSPResult->Score); + $this->assertSame($pId, $response->AuthenticateSPResult->ProfileID); + $this->assertSame($pVer, $response->AuthenticateSPResult->ProfileVersion); + $this->assertSame($custRef, $response->AuthenticateSPResult->CustomerRef); } - public function testNotSettingProfileIdThrows() + public function testNotSettingProfileIdThrows(): void { $identity = new Identity(); @@ -107,7 +108,10 @@ public function testNotSettingProfileIdThrows() $this->service->verifyIdentity($identity); } - public function authenticateSp(): array + /** + * @return array> Various options of customer reference and birthdays for testing purposes + */ + public function authenticateSpDataProvider(): array { return [ ['customer-reference', DateTime::createFromFormat('Y-m-d', '1976-03-06')], @@ -116,6 +120,10 @@ public function authenticateSp(): array ]; } + /** + * @return array> Options for profile id, profile version, customer + * reference, BandText to return and score to return from the fake gateway + */ public function fakeResponses(): array { return [ From 0242945f414bfdebd1676d699c44d9827988f9af Mon Sep 17 00:00:00 2001 From: Matt Peel Date: Wed, 8 Sep 2021 16:16:28 +1200 Subject: [PATCH 2/3] Resolve peer review feedback from @elnurvl (thanks!) - Fix method signatures longer than 120 chars by making them multi-line - Don't allow nullable DateTime arguments on InternationalPassport - Fix GlobalAuthenticationService constructor to allow nullable $gateway - Remove additional coding standard that only works with PHP8 --- phpcs.xml.dist | 3 ++- src/Gateway/GlobalAuthenticationGateway.php | 12 ++++++--- .../Documents/InternationalPassport.php | 4 +-- src/Service/GlobalAuthenticationService.php | 2 +- .../GlobalAuthenticationGatewayFake.php | 14 ++++++---- .../GlobalAuthenticationServiceTest.php | 27 +++++++++++-------- 6 files changed, 38 insertions(+), 24 deletions(-) diff --git a/phpcs.xml.dist b/phpcs.xml.dist index 0eec660..441aca2 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -36,7 +36,8 @@ - + + diff --git a/src/Gateway/GlobalAuthenticationGateway.php b/src/Gateway/GlobalAuthenticationGateway.php index 7392215..0cfe23b 100644 --- a/src/Gateway/GlobalAuthenticationGateway.php +++ b/src/Gateway/GlobalAuthenticationGateway.php @@ -10,14 +10,18 @@ class GlobalAuthenticationGateway extends ID3GlobalBaseGateway { - public function AuthenticateSP(string $pId, int $pVer, ?string $customerReference, Identity $identity): stdClass - { + public function AuthenticateSP( + string $profileId, + int $profileVersion, + ?string $customerReference, + Identity $identity + ): stdClass { $request = new AuthenticateSPRequest(); $request->setCustomerReference($customerReference); $profile = new stdClass(); - $profile->Version = $pVer; - $profile->ID = $pId; + $profile->ID = $profileId; + $profile->Version = $profileVersion; $request->setProfileIDVersion($profile); $request->addFieldsFromIdentity($identity); diff --git a/src/Identity/Documents/InternationalPassport.php b/src/Identity/Documents/InternationalPassport.php index 55d5a82..b0a9dc2 100644 --- a/src/Identity/Documents/InternationalPassport.php +++ b/src/Identity/Documents/InternationalPassport.php @@ -114,7 +114,7 @@ public function setExpiryYear(?int $ExpiryYear): InternationalPassport return $this; } - public function setExpiryDate(?DateTime $expiryDate): InternationalPassport + public function setExpiryDate(DateTime $expiryDate): InternationalPassport { $this->setExpiryDay((int)$expiryDate->format('d')); $this->setExpiryMonth((int)$expiryDate->format('m')); @@ -159,7 +159,7 @@ public function setIssueYear(?int $IssueYear): InternationalPassport return $this; } - public function setIssueDate(?DateTime $issueDate): InternationalPassport + public function setIssueDate(DateTime $issueDate): InternationalPassport { $this->setIssueDay((int)$issueDate->format('d')); $this->setIssueMonth((int)$issueDate->format('m')); diff --git a/src/Service/GlobalAuthenticationService.php b/src/Service/GlobalAuthenticationService.php index d77a2f1..37760b0 100644 --- a/src/Service/GlobalAuthenticationService.php +++ b/src/Service/GlobalAuthenticationService.php @@ -81,7 +81,7 @@ class GlobalAuthenticationService extends ID3BaseService * you can pass these in here, or call ->setSoapOptions() after constructing the object. * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingTraversableTypeHintSpecification */ - public function __construct(?GlobalAuthenticationGateway $gateway, array $soapOptions = []) + public function __construct(?GlobalAuthenticationGateway $gateway = null, array $soapOptions = []) { $this->gateway = $gateway; $this->soapOptions = $soapOptions; diff --git a/src/Stubs/Gateway/GlobalAuthenticationGatewayFake.php b/src/Stubs/Gateway/GlobalAuthenticationGatewayFake.php index 00da8f1..70a24ef 100644 --- a/src/Stubs/Gateway/GlobalAuthenticationGatewayFake.php +++ b/src/Stubs/Gateway/GlobalAuthenticationGatewayFake.php @@ -57,8 +57,12 @@ public function setScore(int $score): self * @inheritDoc * @phpcsSuppress SlevomatCodingStandard.Functions.UnusedParameter.UnusedParameter */ - public function AuthenticateSP(string $pId, int $pVer, ?string $customerReference, Identity $identity): stdClass - { + public function AuthenticateSP( + string $profileId, + int $profileVersion, + ?string $customerReference, + Identity $identity + ): stdClass { $result = 'O:8:"stdClass":1:{s:20:"AuthenticateSPResult";O:8:"stdClass":12:{s:16:"AuthenticationID";s:36:"' . 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";s:9:"Timestamp";s:33:"2016-01-01T00:00:00.0000000+01:00";s:11:"' . 'CustomerRef";s:%d:"%s";s:9:"ProfileID";s:%d:"%s";s:11:"ProfileName";s:15:"Default Profile";s:14:"' @@ -70,9 +74,9 @@ public function AuthenticateSP(string $pId, int $pVer, ?string $customerReferenc $result, $customerReference ? strlen($customerReference) : 0, $customerReference, - strlen($pId), - $pId, - $pVer, + strlen($profileId), + $profileId, + $profileVersion, $this->score, strlen($this->bandText), $this->bandText diff --git a/tests/Service/GlobalAuthenticationServiceTest.php b/tests/Service/GlobalAuthenticationServiceTest.php index d088fd1..7ed1766 100644 --- a/tests/Service/GlobalAuthenticationServiceTest.php +++ b/tests/Service/GlobalAuthenticationServiceTest.php @@ -70,15 +70,20 @@ public function testSuccessfulResponse(?string $customerReference, ?DateTime $bi /** * @dataProvider fakeResponses - * @param string $pId Profile ID value - * @param int $pVer Profile Version value - * @param string $custRef Customer reference submitted + * @param string $profileId Profile ID value + * @param int $profileVersion Profile Version value + * @param string $customerReference Customer reference submitted * @param string $bandText The BandText to return from the fake gateway * @param int $score The score to return from the fake gateway * @throws IdentityVerificationFailureException */ - public function testFakeResponses(string $pId, int $pVer, string $custRef, string $bandText, int $score): void - { + public function testFakeResponses( + string $profileId, + int $profileVersion, + string $customerReference, + string $bandText, + int $score + ): void { // Arrange $this->fakeGateway->setBandText($bandText)->setScore($score); @@ -86,18 +91,18 @@ public function testFakeResponses(string $pId, int $pVer, string $custRef, strin // Act $result = $this->service - ->setProfileId($pId) - ->setProfileVersion($pVer) - ->verifyIdentity($identity, $custRef); + ->setProfileId($profileId) + ->setProfileVersion($profileVersion) + ->verifyIdentity($identity, $customerReference); $response = $this->service->getLastVerifyIdentityResponse(); // Assert $this->assertSame($bandText, $result); $this->assertSame($score, $response->AuthenticateSPResult->Score); - $this->assertSame($pId, $response->AuthenticateSPResult->ProfileID); - $this->assertSame($pVer, $response->AuthenticateSPResult->ProfileVersion); - $this->assertSame($custRef, $response->AuthenticateSPResult->CustomerRef); + $this->assertSame($profileId, $response->AuthenticateSPResult->ProfileID); + $this->assertSame($profileVersion, $response->AuthenticateSPResult->ProfileVersion); + $this->assertSame($customerReference, $response->AuthenticateSPResult->CustomerRef); } public function testNotSettingProfileIdThrows(): void From 21cd220938b62c6e351f60272a62ab9675fd7c30 Mon Sep 17 00:00:00 2001 From: Matt Peel Date: Thu, 9 Sep 2021 00:41:49 +1200 Subject: [PATCH 3/3] - Allow expiry and issue date for InternationalPassport to be null --- .../Documents/InternationalPassport.php | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/Identity/Documents/InternationalPassport.php b/src/Identity/Documents/InternationalPassport.php index b0a9dc2..216a932 100644 --- a/src/Identity/Documents/InternationalPassport.php +++ b/src/Identity/Documents/InternationalPassport.php @@ -114,8 +114,15 @@ public function setExpiryYear(?int $ExpiryYear): InternationalPassport return $this; } - public function setExpiryDate(DateTime $expiryDate): InternationalPassport + public function setExpiryDate(?DateTime $expiryDate): InternationalPassport { + // Set all expiry date fields to null if we're not given a valid date + if (!$expiryDate) { + $this->setExpiryDay(null)->setExpiryMonth(null)->setExpiryYear(null); + + return $this; + } + $this->setExpiryDay((int)$expiryDate->format('d')); $this->setExpiryMonth((int)$expiryDate->format('m')); $this->setExpiryYear((int)$expiryDate->format('Y')); @@ -159,8 +166,15 @@ public function setIssueYear(?int $IssueYear): InternationalPassport return $this; } - public function setIssueDate(DateTime $issueDate): InternationalPassport + public function setIssueDate(?DateTime $issueDate): InternationalPassport { + // Set all issue date fields to null if we're not given a valid date + if (!$issueDate) { + $this->setIssueDay(null)->setIssueMonth(null)->setIssueYear(null); + + return $this; + } + $this->setIssueDay((int)$issueDate->format('d')); $this->setIssueMonth((int)$issueDate->format('m')); $this->setIssueYear((int)$issueDate->format('Y'));