Skip to content

Commit 78689c4

Browse files
authored
Merge pull request #12 from madmatt/pulls/api-adjustments
2 parents 3705011 + b9f2386 commit 78689c4

File tree

6 files changed

+151
-43
lines changed

6 files changed

+151
-43
lines changed

README.md

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ The WSDL file gives an overview of the values that can be provided, these will v
88
* [Online WSDL viewer](http://www.id3globalsupport.com/Website/content/Web-Service/WSDL%20Page/WSDL%20HTML/ID3%20Global%20WSDL-%20Live.xhtml)
99
* [Sample code per country](http://www.id3globalsupport.com/Website/Sample-Code.html)
1010

11-
*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 NZ, however it should be generic enough to easily support non-NZ systems easily.
11+
*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 non-NZ systems easily.
1212

1313
```php
1414
/**
@@ -98,14 +98,20 @@ $documentContainer = new \ID3Global\Identity\Documents\DocumentContainer();
9898
$documentContainer->addIdentityDocument(new \ID3Global\Identity\Documents\NZ\DrivingLicence(), 'New Zealand');
9999

100100
/**
101-
* $result will be one of the following:
102-
* - \ID3Global\Constants\Identity::IDENTITY_BAND_PASS
103-
* - \ID3Global\Constants\Identity::IDENTITY_BAND_REFER
104-
* - \ID3Global\Constants\Identity::IDENTITY_BAND_ALERT
101+
* $result will be a string representing the 'BandText' as returned by the ID3global API. By default, this may be a word
102+
* like 'PASS', 'REFER' or 'ALERT' but could also be any string value e.g. 'Name, Address and DOB Match'. The exact
103+
* string returned is entirely dependent on how the profile is configured within ID3global, and can vary if you adjust
104+
* the profile id and profile version.
105+
*
106+
* It is up to your implementation how these are handled. Note that generally there is only a single value that
107+
* represents an identity that has passed the necessary verification, and multiple BandTexts that represent a failing
108+
* identity. You **must** handle this in your own code, as the ID3Global API does not provide any kind of boolean value
109+
* for whether a given identity passed identity verification or not.
105110
*
106-
* It is up to the implementation how these are handled.
107111
* An exception is thrown if the web service fails or cannot be contacted.
108112
*/
113+
$validIdentityBandText = 'PASS'; // See note above about how this may differ for you
114+
109115
$identity = new \ID3Global\Identity\Identity();
110116
$identity
111117
->setPersonalDetails($personalDetails)
@@ -116,9 +122,10 @@ $identity
116122
$gateway = new \ID3Global\Gateway\GlobalAuthenticationGateway('username', 'password');
117123
$id3Service = new \ID3Global\Service\GlobalAuthenticationService($gateway);
118124
$result = $id3Service
119-
->verifyIdentity($identity, 'profile-id');
125+
->setProfileId('Profile ID as provided by ID3global interface')
126+
->verifyIdentity($identity, 'Unique customer reference');
120127

121-
if($result === 'PASS') {
128+
if($result === $validIdentityBandText) {
122129
// Identity is verified, continue processing
123130
}
124131
```

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "madmatt/id3global-service",
33
"description": "Allows a PHP-powered website to communicate with the GBG ID3global API to verify identities. This library is not affiliated with GBG PLC in any way.",
44
"type": "library",
5-
"keywords": [ "id3global", "GBG", "GBG PLC", "ID3Global", "identity verification", "identity" ],
5+
"keywords": [ "id3global", "GBG", "GBG PLC", "ID3Global", "ID3global", "identity verification", "identity" ],
66
"homepage": "https://github.com/madmatt/id3global-service/",
77
"license": "BSD-3-Clause",
88

src/Exceptions/IdentityVerificationFailureException.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ class IdentityVerificationFailureException extends Exception
1212
public function __construct($response)
1313
{
1414
$this->response = $response;
15-
$message = sprintf('Invalid Response returned by ID3Global API. Serialized response: %s', serialize($response));
15+
$message = sprintf('Invalid Response returned by ID3global API. Serialized response: %s', serialize($response));
1616
parent::__construct($message);
1717
}
1818

src/Service/GlobalAuthenticationService.php

Lines changed: 107 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace ID3Global\Service;
44

55
use Exception;
6+
use LogicException;
67
use ID3Global\Exceptions\IdentityVerificationFailureException;
78
use ID3Global\Gateway\GlobalAuthenticationGateway;
89
use ID3Global\Identity\Identity;
@@ -16,6 +17,31 @@ class GlobalAuthenticationService extends ID3BaseService
1617
*/
1718
private GlobalAuthenticationGateway $gateway;
1819

20+
/**
21+
* @var string The Profile ID to be used when verifying identities via $this->verifyIdentity().
22+
* @see self::setProfileId()
23+
*/
24+
private string $profileId = '';
25+
26+
/**
27+
* @var int The version of the Profile ID to be used when verifying identities via $this->verifyIdentity().
28+
* The special value of 0 is treated specially by ID3global and represents the 'most recent version of the profile'.
29+
* @see self::setProfileVersion()
30+
*/
31+
private int $profileVersion = 0;
32+
33+
/**
34+
* @var Identity The most recent Identity object to be verified by the ID3global API (regardless of the outcome of
35+
* the API request).
36+
*/
37+
private Identity $lastIdentity;
38+
39+
/**
40+
* @var string|null The most recent customer reference to be verified by the ID3global API (regardless of the
41+
* outcome of the API request).
42+
*/
43+
private ?string $lastCustomerReference;
44+
1945
/**
2046
* @var stdClass|null The last response, directly from the API gateway. Can be retrieved using
2147
* {@link getLastVerifyIdentityResponse()}.
@@ -39,39 +65,54 @@ public function __construct(GlobalAuthenticationGateway $gateway, array $soapOpt
3965
}
4066

4167
/**
42-
* @param Identity $identity
43-
* @param string $profileId The Profile ID to be used when verifying a @link \ID3Global\Identity\Identity object
44-
* @param int $profileVersion The Profile Version to be used when verifying a @link \ID3Global\Identity\Identity object. The version
45-
* 0 represents the 'most recent version of the profile', which is generally what is required.
46-
* @param string|null $customerReference A reference stored against this identity request. This is optional, but is recommended to set a
47-
* customer reference and store it against the returned identity verification so it can be later tracked if
68+
* Given an Identity and a profile of checks to perform, query ID3Global and verify the given $identity object. The
69+
* raw response is the output of the 'BandText' as returned directly by the ID3Global API. Per the
70+
* [ID3Global 'Integrate now' documentation](https://www.id3globalsupport.com/integrate-now/), you should use this
71+
* value to determine whether or not to consider the identity to be sufficiently verified for your needs.
72+
*
73+
* If you want to dive deeper (e.g. to look at individual checks that were performed such as whether the identity
74+
* matched on a driver's license or passport record), you can do this by calling
75+
* $service->getLastVerifyIdentityResponse() after calling this method - this will return the full response from the
76+
* API.
77+
*
78+
* Ensure you call at least ->setProfileId() prior to calling this method.
79+
* Optionally call ->setProfileVersion() if you wish to set a specific profile version to query against.
80+
*
81+
* @param Identity $identity The full Identity object that should be verified with the ID3global API
82+
* @param string|null $customerReference A reference stored against this identity request within the ID3global
83+
* interface. This is optional, but is highly recommended to set a reference
84+
* and store it against the identity so that it can be later tracked if
4885
* necessary for compliance purposes.
4986
*
50-
* @throws IdentityVerificationFailureException
87+
* @throws IdentityVerificationFailureException Thrown specifically if the SOAP response was 'valid' according to
88+
* SOAP but does not conform to the expected response (missing BandText or Score elements of the response).
89+
* @throws Exception May throw a generic Exception or SoapFault if any part of the SOAP callstack fails.
5190
*
52-
* @return string One of Identity::IDENTITY_BAND_PASS, Identity::IDENTITY_BAND_REFER, or Identity::IDENTITY_BAND_ALERT
53-
*/
54-
public function verifyIdentity(
55-
Identity $identity,
56-
string $profileId,
57-
int $profileVersion = 0,
58-
?string $customerReference = null
59-
): string {
91+
* @return string The raw BandText as provided by the API.
92+
*/
93+
public function verifyIdentity(Identity $identity, ?string $customerReference = null): string {
94+
$this->lastIdentity = $identity;
95+
$this->lastCustomerReference = $customerReference;
96+
6097
$gateway = $this->getGateway();
6198

99+
if (!$this->profileId) {
100+
$error = 'An ID3global Profile ID must be set by calling setProfileId() before calling verifyIdentity().';
101+
throw new LogicException($error);
102+
}
103+
104+
$profileId = $this->profileId;
105+
$profileVersion = $this->profileVersion;
106+
62107
try {
63-
$response = $gateway->AuthenticateSP(
64-
$profileId,
65-
$profileVersion,
66-
$customerReference,
67-
$identity
68-
);
108+
$response = $gateway->AuthenticateSP($profileId, $profileVersion, $customerReference, $identity);
69109

70110
if ($gateway->getClient() instanceof SoapClient) {
71111
$this->lastRawRequest = $gateway->getClient()->__getLastRequest();
72112
}
73113

74114
$validResult = false;
115+
$this->lastVerifyIdentityResponse = $response;
75116

76117
if (
77118
isset($response) &&
@@ -82,8 +123,6 @@ public function verifyIdentity(
82123
}
83124

84125
if ($validResult) {
85-
$this->lastVerifyIdentityResponse = $response;
86-
87126
return $response->AuthenticateSPResult->BandText;
88127
} else {
89128
throw new IdentityVerificationFailureException($response);
@@ -93,9 +132,52 @@ public function verifyIdentity(
93132
}
94133
}
95134

135+
public function setProfileId(string $profileId): self
136+
{
137+
$this->profileId = $profileId;
138+
139+
return $this;
140+
}
141+
142+
public function getProfileId(): string
143+
{
144+
return $this->profileId;
145+
}
146+
147+
public function setProfileVersion(int $profileVersion): self
148+
{
149+
$this->profileVersion = $profileVersion;
150+
151+
return $this;
152+
}
153+
154+
public function getProfileVersion(): int
155+
{
156+
return $this->profileVersion;
157+
}
158+
159+
/**
160+
* @return Identity|null The last Identity object to be verified by the API (regardless of whether it was
161+
* successfully accepted by the ID3global API or not). Returns null if ->verifyIdentity() has not yet been called.
162+
*/
163+
public function getLastVerifiedIdentity(): ?Identity
164+
{
165+
return $this->lastIdentity;
166+
}
167+
168+
/**
169+
* @return string|null The last customer reference value to be verified by the API (regardless of whether it was
170+
* successfully accepted by the ID3global API or not). Returns null if ->verifyIdentity() has not yet been called.
171+
*/
172+
public function getLastCustomerReference(): ?string
173+
{
174+
return $this->lastCustomerReference;
175+
}
176+
96177
/**
97-
* @return stdClass|null Either the full response as returned by ID3Global, or null if no call has been made (or
98-
* if the previous call failed for any reason)
178+
* @return stdClass|null Either the full response as returned by ID3global, or null if no call has been made yet. If
179+
* the request was made but failed to validate (e.g. the ID3global API returned an invalid SOAP object, this will
180+
* still be populated.
99181
*/
100182
public function getLastVerifyIdentityResponse(): ?stdClass
101183
{

src/Stubs/Gateway/GlobalAuthenticationGatewayFake.php

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,20 @@
88
class GlobalAuthenticationGatewayFake extends GlobalAuthenticationGateway
99
{
1010
/**
11-
* @var string The const returned by the ID3Global API when this identity passed verification, according to the
12-
* ruleset used.
11+
* @var string A BandText value returned by the ID3global API when this identity passed verification, according to
12+
* the selected profile.
1313
*/
1414
const IDENTITY_BAND_PASS = 'PASS';
1515

1616
/**
17-
* @var string The const returned by the ID3Global API when this identity needs additional referral, according to
18-
* the ruleset used.
17+
* @var string A BandText value returned by the ID3global API when this identity needs additional referral,
18+
* according to the selected profile.
1919
*/
2020
const IDENTITY_BAND_REFER = 'REFER';
2121

2222
/**
23-
* The const returned by the ID3Global API when this identity needs additional referral, according to
24-
* the ruleset used.
23+
* @var string A BandText value returned by the ID3global API when this identity has a significant issue, according
24+
* to the selected profile.
2525
*/
2626
const IDENTITY_BAND_ALERT = 'ALERT';
2727

@@ -32,6 +32,11 @@ public function __construct($username, $password, $soapClientOptions = [], $useP
3232

3333
public function AuthenticateSP($profileID, $profileVersion, $customerReference, Identity $identity)
3434
{
35-
return unserialize('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:1:"x";s:9:"ProfileID";s:36:"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";s:11:"ProfileName";s:15:"Default Profile";s:14:"ProfileVersion";i:1;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:3000;s:8:"BandText";s:4:"PASS";s:7:"Country";s:11:"New Zealand";}}');
35+
$bandText = self::IDENTITY_BAND_PASS;
36+
37+
return unserialize(sprintf(
38+
'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:1:"x";s:9:"ProfileID";s:36:"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";s:11:"ProfileName";s:15:"Default Profile";s:14:"ProfileVersion";i:1;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:3000;s:8:"BandText";s:4:"%s";s:7:"Country";s:11:"New Zealand";}}',
39+
$bandText
40+
));
3641
}
3742
}

tests/Service/GlobalAuthenticationServiceTest.php

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use DateTime;
66
use Exception;
7+
use LogicException;
78
use ID3Global\Identity\Identity;
89
use ID3Global\Identity\PersonalDetails;
910
use ID3Global\Service\GlobalAuthenticationService;
@@ -36,18 +37,31 @@ public function testSuccessfulResponse()
3637
->setSurname('Huntsman')
3738
->setGender('Female')
3839
->setDateOfBirth(DateTime::createFromFormat('Y-m-d', '1976-03-06'));
40+
3941
$identity = new Identity();
4042
$identity->setPersonalDetails($personalDetails);
4143

4244
$profileId = 'profile-id';
4345

4446
// Act
45-
$bandText = $this->service->verifyIdentity($identity, $profileId, 0, 'x');
47+
$bandText = $this->service
48+
->setProfileId($profileId)
49+
->verifyIdentity($identity, 'customer reference');
4650

4751
// Assert
4852
$this->assertSame(GlobalAuthenticationGatewayFake::IDENTITY_BAND_PASS, $bandText);
53+
4954
$response = $this->service->getLastVerifyIdentityResponse();
55+
$this->assertSame('stdClass', get_class($response));
5056
$this->assertSame(GlobalAuthenticationGatewayFake::IDENTITY_BAND_PASS, $response->AuthenticateSPResult->BandText);
5157
$this->assertSame('Default Profile', $response->AuthenticateSPResult->ProfileName);
5258
}
59+
60+
public function testNotSettingProfileIdThrows()
61+
{
62+
$identity = new Identity();
63+
64+
$this->expectException(LogicException::class);
65+
$this->service->verifyIdentity($identity);
66+
}
5367
}

0 commit comments

Comments
 (0)