From 3f90ff4036bdd43fc936465a861f096ad245e6ce Mon Sep 17 00:00:00 2001 From: mehmet-yoti <111424390+mehmet-yoti@users.noreply.github.com> Date: Tue, 30 Jul 2024 15:01:46 +0300 Subject: [PATCH] Added example for dbs and updated failure details (#362) * Updated Release Version to 4.3.0 * updated receipt advanced identity show profile * Added-example-for-DBS-and-updated-failure-details * updated failure details error handling * updated changes for failure details * Updated IDV Example Defaults * Removed unneccessary used libraries --- composer.json | 4 +- .../app/Http/Controllers/DbsController.php | 53 +++++++++++ .../Http/Controllers/ReceiptController.php | 28 ++++-- .../resources/views/dbs.blade.php | 89 +++++++++++++++++++ .../resources/views/partial/report.blade.php | 87 ++++++++++-------- .../resources/views/receipt.blade.php | 29 ++++++ examples/digitalidentity/routes/web.php | 2 + .../app/Http/Controllers/HomeController.php | 24 +++-- .../resources/views/success.blade.php | 56 +++++++++++- .../resources/views/partial/report.blade.php | 88 ++++++++++-------- src/Constants.php | 2 +- .../Session/Retrieve/GetSessionResult.php | 6 +- .../Retrieve/IdentityProfileResponse.php | 4 +- src/Identity/Policy/Policy.php | 2 +- src/Identity/Receipt.php | 24 +++-- src/Identity/ReceiptBuilder.php | 4 +- src/Identity/ReceiptParser.php | 5 +- src/Identity/WrappedReceipt.php | 18 ++-- src/Profile/UserProfile.php | 1 - tests/Identity/Policy/PolicyBuilderTest.php | 2 +- 20 files changed, 411 insertions(+), 117 deletions(-) create mode 100644 examples/digitalidentity/app/Http/Controllers/DbsController.php create mode 100644 examples/digitalidentity/resources/views/dbs.blade.php diff --git a/composer.json b/composer.json index 46af649a..420fe8e3 100755 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "yoti/yoti-php-sdk", "description": "Yoti SDK for quickly integrating your PHP backend with Yoti", - "version": "4.2.2", + "version": "4.3.0", "keywords": [ "yoti", "sdk" @@ -66,4 +66,4 @@ "phpstan/extension-installer": true } } -} \ No newline at end of file +} diff --git a/examples/digitalidentity/app/Http/Controllers/DbsController.php b/examples/digitalidentity/app/Http/Controllers/DbsController.php new file mode 100644 index 00000000..e8e47e74 --- /dev/null +++ b/examples/digitalidentity/app/Http/Controllers/DbsController.php @@ -0,0 +1,53 @@ +withIdentityProfileRequirements((object)[ + 'trust_framework' => 'UK_TFIDA', + 'scheme' => [ + 'type' => 'DBS', + 'objective' => 'BASIC' + ] + ]) + ->build(); + + $redirectUri = 'https://host/redirect/'; + + $shareSessionRequest = (new ShareSessionRequestBuilder()) + ->withPolicy($policy) + ->withRedirectUri($redirectUri) + ->build(); + $session = $client->createShareSession($shareSessionRequest); + return $session->getId(); + } + catch (\Throwable $e) { + Log::error($e->getTraceAsString()); + throw new BadRequestHttpException($e->getMessage()); + } + } + public function show(DigitalIdentityClient $client) + { + try { + return view('dbs', [ + 'title' => 'Digital Identity DBS Check Example', + 'sdkId' => $client->id + ]); + } catch (\Throwable $e) { + Log::error($e->getTraceAsString()); + throw new BadRequestHttpException($e->getMessage()); + } + } +} diff --git a/examples/digitalidentity/app/Http/Controllers/ReceiptController.php b/examples/digitalidentity/app/Http/Controllers/ReceiptController.php index 39fe75a6..cc529386 100644 --- a/examples/digitalidentity/app/Http/Controllers/ReceiptController.php +++ b/examples/digitalidentity/app/Http/Controllers/ReceiptController.php @@ -9,6 +9,7 @@ use Yoti\Profile\Attribute; use Yoti\Profile\UserProfile; use Yoti\Util\Logger; +use Yoti\Exception\ActivityDetailsException; class ReceiptController extends BaseController { public function show(Request $request, DigitalIdentityClient $client, ?LoggerInterface $logger = null) @@ -17,14 +18,25 @@ public function show(Request $request, DigitalIdentityClient $client, ?LoggerInt $logger->warning("Unknown Content Type parsing as a String"); $shareReceipt = $client->fetchShareReceipt($request->query('ReceiptID')); - - $profile = $shareReceipt->getProfile(); - - return view('receipt', [ - 'fullName' => $profile->getFullName(), - 'selfie' => $profile->getSelfie(), - 'profileAttributes' => $this->createAttributesDisplayList($profile), - ]); + if ($shareReceipt->getError() != null) + { + error_log($shareReceipt->getErrorReason()->getRequirementNotMetDetails()->getDocumentCountryIsoCode()); + return view('receipt', [ + 'fullName' => null, + 'selfie' => null, + 'profileAttributes' => null, + 'error' => $shareReceipt->getErrorReason() + ]); + } + else { + $profile = $shareReceipt->getProfile(); + return view('receipt', [ + 'fullName' => $profile->getFullName(), + 'selfie' => $profile->getSelfie(), + 'profileAttributes' => $this->createAttributesDisplayList($profile), + 'error' => null + ]); + } } /** diff --git a/examples/digitalidentity/resources/views/dbs.blade.php b/examples/digitalidentity/resources/views/dbs.blade.php new file mode 100644 index 00000000..1359cc7c --- /dev/null +++ b/examples/digitalidentity/resources/views/dbs.blade.php @@ -0,0 +1,89 @@ + + + + + + + {{ $title }} + + + + + +
+
+
+ + Yoti + +
+

Digital Identity DBS Ckeck Example

+ +
+
+
+ +
+ +
+

The Yoti app is free to download and use:

+ +
+ + Download on the App Store + + + + get it on Google Play + +
+
+
+ + + + diff --git a/examples/digitalidentity/resources/views/partial/report.blade.php b/examples/digitalidentity/resources/views/partial/report.blade.php index 28bdd3f0..ec1dc60d 100644 --- a/examples/digitalidentity/resources/views/partial/report.blade.php +++ b/examples/digitalidentity/resources/views/partial/report.blade.php @@ -1,39 +1,54 @@ -@foreach ($report as $key => $value) - - - - - - - - @foreach ($value as $name => $result) - @if (is_array($result)) - @foreach ($result as $data => $view) - @if (is_array($view)) - @foreach ($view as $key2 => $value2) - @if (is_array($value2)) - {{json_encode($value2)}} - @else - - - - @endif - @endforeach - @else - - - - @endif - @endforeach - @else - +@if (isset($key) && is_array($key)) + @foreach ($report as $key => $value) +
-

{{ $key }}

-
{{ $key2 }}
{{ $value2 }}
{{ $data }}
{{ $view }}
+ + + + + + + @foreach ($value as $name => $result) + @if (isset($result) && is_array($result)) + @foreach ($result as $data => $view) + @if (is_array($view)) + @foreach ($view as $key2 => $value2) + @if (is_array($value2)) + {{json_encode($value2)}} + @else + + + + @endif + @endforeach + @else + + + + @endif + @endforeach + @else + - - @endif - @endforeach + + @endif + @endforeach - -
+

{{ $key }}

+
{{ $key2 }}
{{ $value2 }}
{{ $data }}
{{ $view }}
{{ $name }}
{{ $result }}
+ + @endforeach +@else + + @foreach ($report as $key => $value) + + + + @endforeach +
+ {{ $key }}
+
+                        {!! json_encode($value, JSON_PRETTY_PRINT) !!}
+                    
+
+@endif diff --git a/examples/digitalidentity/resources/views/receipt.blade.php b/examples/digitalidentity/resources/views/receipt.blade.php index 1fef5463..b166dbdd 100644 --- a/examples/digitalidentity/resources/views/receipt.blade.php +++ b/examples/digitalidentity/resources/views/receipt.blade.php @@ -36,10 +36,37 @@
+ + @if ($error) +
+
Errors
+
+
+
+
Audit Id
+
{{ $error->getRequirementNotMetDetails()->getAuditId() }}
+
+
+
Details
+
{{ $error->getRequirementNotMetDetails()->getDetails() }}
+
+
+
Failure Type
+
{{ $error->getRequirementNotMetDetails()->getFailureType() }}
+
+
+
Document Type
+
{{ $error->getRequirementNotMetDetails()->getDocumentType() }}
+
+
+
Country
+
{{ $error->getRequirementNotMetDetails()->getDocumentCountryIsoCode() }}
+
+ @endif
Attribute
Value
@@ -55,6 +82,7 @@
+ @if(@$profileAttributes) @foreach($profileAttributes as $item) @if ($item['obj'])
@@ -96,6 +124,7 @@
@endif @endforeach + @endif
diff --git a/examples/digitalidentity/routes/web.php b/examples/digitalidentity/routes/web.php index 44933279..3fb377e7 100644 --- a/examples/digitalidentity/routes/web.php +++ b/examples/digitalidentity/routes/web.php @@ -18,3 +18,5 @@ Route::get('/generate-session', 'IdentityController@generateSession'); Route::get('/generate-advanced-identity-share', 'AdvancedIdentityController@show'); Route::get('/generate-advanced-identity-session', 'AdvancedIdentityController@generateSession'); +Route::get('/generate-dbs-share', 'DbsController@show'); +Route::get('/generate-dbs-session', 'DbsController@generateSession'); \ No newline at end of file diff --git a/examples/doc-scan/app/Http/Controllers/HomeController.php b/examples/doc-scan/app/Http/Controllers/HomeController.php index 9bd67d01..299fa6b1 100644 --- a/examples/doc-scan/app/Http/Controllers/HomeController.php +++ b/examples/doc-scan/app/Http/Controllers/HomeController.php @@ -77,18 +77,30 @@ public function show(Request $request, DocScanClient $client) ->withRemoveDeceased(true) ->build(); + //Identity Profile Requeirements Object + /*$identityProfileRequirements = (object)[ + 'trust_framework' => 'UK_TFIDA', + 'scheme' => [ + 'type' => 'DBS', + 'objective' => 'BASIC' + ] + ];*/ $sessionSpec = (new SessionSpecificationBuilder()) ->withClientSessionTokenTtl(600) - ->withResourcesTtl(90000) + ->withResourcesTtl(604800) ->withUserTrackingId('some-user-tracking-id') + //For Identity Profile Requirements Object + //->withBlockBiometricConsent(false) //User needs to provide consent for the liveness detection + //->withIdentityProfileRequirements($identityProfileRequirements) ->withRequestedCheck( (new RequestedDocumentAuthenticityCheckBuilder()) ->build() ) ->withRequestedCheck( (new RequestedLivenessCheckBuilder()) - ->forZoomLiveness() + ->forStaticLiveness() + ->withMaxRetries(3) ->build() ) ->withRequestedCheck( @@ -98,7 +110,7 @@ public function show(Request $request, DocScanClient $client) ) ->withRequestedCheck( (new RequestedFaceMatchCheckBuilder()) - ->withManualCheckAlways() + ->withManualCheckFallback() ->build() ) ->withRequestedCheck( @@ -116,20 +128,20 @@ public function show(Request $request, DocScanClient $client) ) ->withRequestedTask( (new RequestedTextExtractionTaskBuilder()) - ->withManualCheckAlways() + ->withManualCheckFallback() ->withChipDataDesired() ->withCreateExpandedDocumentFields(true) ->build() ) ->withRequestedTask( (new RequestedSupplementaryDocTextExtractionTaskBuilder()) - ->withManualCheckAlways() + ->withManualCheckFallback() ->build() ) ->withSdkConfig( (new SdkConfigBuilder()) ->withAllowsCameraAndUpload() - ->withPrimaryColour('#2d9fff') + ->withPrimaryColour('#2875BC') ->withSecondaryColour('#FFFFFF') ->withFontColour('#FFFFFF') ->withLocale('en-GB') diff --git a/examples/doc-scan/resources/views/success.blade.php b/examples/doc-scan/resources/views/success.blade.php index 0e49c218..63b0b486 100644 --- a/examples/doc-scan/resources/views/success.blade.php +++ b/examples/doc-scan/resources/views/success.blade.php @@ -293,7 +293,61 @@ @endif - + @if (isset($sessionResult)) + @if ($sessionResult->getIdentityProfile() != null) + @if ($sessionResult->getIdentityProfile()->getFailureReason() != null) + @if ($sessionResult->getIdentityProfile()->getFailureReason()->getReasonCode()) +
+
+

Identity Result Error

+
+
+ @if ($sessionResult->getIdentityProfile()->getFailureReason()->getReasonCode()) + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Reason Code + {{$sessionResult->getIdentityProfile()->getFailureReason()->getReasonCode()}} +
Failure Type + {{$sessionResult->getIdentityProfile()->getFailureReason()->getRequirementNotMetDetails()->getFailureType()}} +
Details + {{$sessionResult->getIdentityProfile()->getFailureReason()->getRequirementNotMetDetails()->getDetails()}} +
Audit Id + {{$sessionResult->getIdentityProfile()->getFailureReason()->getRequirementNotMetDetails()->getAuditId()}} +
Country ISO Code + {{$sessionResult->getIdentityProfile()->getFailureReason()->getRequirementNotMetDetails()->getDocumentCountryIsoCode()}} +
Document Type + {{$sessionResult->getIdentityProfile()->getFailureReason()->getRequirementNotMetDetails()->getDocumentType()}} +
+ @endif + @endif + @endif + @endif + @endif @if (count($sessionResult->getResources()->getIdDocuments()) > 0)
diff --git a/examples/profile/resources/views/partial/report.blade.php b/examples/profile/resources/views/partial/report.blade.php index 707abe99..d3466436 100644 --- a/examples/profile/resources/views/partial/report.blade.php +++ b/examples/profile/resources/views/partial/report.blade.php @@ -1,40 +1,54 @@ -@foreach ($report as $key => $value) - - - - - - - - @if (isset($value) && is_array($value)) - @foreach ($value as $name => $result) - @if (is_array($result)) - @foreach ($result as $data => $view) - @if (is_array($view)) - @foreach ($view as $key2 => $value2) - @if (is_array($value2)) - {{json_encode($value2)}} - @else - - - - @endif - @endforeach - @else - - - - @endif - @endforeach - @else - +@if (isset($key) && is_array($key)) + @foreach ($report as $key => $value) +
-

{{ $key }}

-
{{ $key2 }}
{{ $value2 }}
{{ $data }}
{{ $view }}
+ + + + + + + @foreach ($value as $name => $result) + @if (isset($result) && is_array($result)) + @foreach ($result as $data => $view) + @if (is_array($view)) + @foreach ($view as $key2 => $value2) + @if (is_array($value2)) + {{json_encode($value2)}} + @else + + + + @endif + @endforeach + @else + + + + @endif + @endforeach + @else + - - @endif + + @endif + @endforeach + + +
+

{{ $key }}

+
{{ $key2 }}
{{ $value2 }}
{{ $data }}
{{ $view }}
{{ $name }}
{{ $result }}
+ @endforeach +@else + + @foreach ($report as $key => $value) + + + @endforeach - @endif -
+ {{ $key }}
+
+                        {!! json_encode($value, JSON_PRETTY_PRINT) !!}
+                    
+
- @endforeach +@endif \ No newline at end of file diff --git a/src/Constants.php b/src/Constants.php index e6dd08d8..b1cb4499 100644 --- a/src/Constants.php +++ b/src/Constants.php @@ -31,7 +31,7 @@ class Constants public const SDK_IDENTIFIER = 'PHP'; /** Default SDK version */ - public const SDK_VERSION = '4.2.2'; + public const SDK_VERSION = '4.3.0'; /** Base url for connect page (user will be redirected to this page eg. baseurl/app-id) */ public const CONNECT_BASE_URL = 'https://www.yoti.com/connect'; diff --git a/src/DocScan/Session/Retrieve/GetSessionResult.php b/src/DocScan/Session/Retrieve/GetSessionResult.php index 919053c3..857e3263 100644 --- a/src/DocScan/Session/Retrieve/GetSessionResult.php +++ b/src/DocScan/Session/Retrieve/GetSessionResult.php @@ -313,7 +313,11 @@ function ($checkResponse) use ($class): bool { public function getIdentityProfile(): ?IdentityProfileResponse { - return $this->identityProfile; + if (isset($this->identityProfile)) { + return $this->identityProfile; + } else { + return null; + } } public function getIdentityProfilePreview(): ?IdentityProfilePreviewResponse diff --git a/src/DocScan/Session/Retrieve/IdentityProfileResponse.php b/src/DocScan/Session/Retrieve/IdentityProfileResponse.php index 17643e89..06bea9c2 100644 --- a/src/DocScan/Session/Retrieve/IdentityProfileResponse.php +++ b/src/DocScan/Session/Retrieve/IdentityProfileResponse.php @@ -31,7 +31,7 @@ class IdentityProfileResponse */ public function __construct(array $sessionData) { - $this->subjectId = $sessionData['subject_id']; + $this->subjectId = $sessionData['subject_id'] ?? ''; $this->result = $sessionData['result']; if (isset($sessionData['failure_reason'])) { @@ -62,7 +62,7 @@ public function getResult(): string /** * @return FailureReasonResponse */ - public function getFailureReason(): FailureReasonResponse + public function getFailureReason(): ?FailureReasonResponse { return $this->failureReason; } diff --git a/src/Identity/Policy/Policy.php b/src/Identity/Policy/Policy.php index a71e1fdc..5c54f2fa 100644 --- a/src/Identity/Policy/Policy.php +++ b/src/Identity/Policy/Policy.php @@ -37,7 +37,7 @@ class Policy implements \JsonSerializable * @param int[] $wantedAuthTypes * Auth types represents the authentication type to be used. * @param object $identityProfileRequirements - * @param object $advancedidentityProfileRequirements + * @param object $advancedIdentityProfileRequirements */ public function __construct( array $wantedAttributes, diff --git a/src/Identity/Receipt.php b/src/Identity/Receipt.php index 162761f2..893c5459 100644 --- a/src/Identity/Receipt.php +++ b/src/Identity/Receipt.php @@ -12,8 +12,8 @@ class Receipt private string $id; private string $sessionId; private \DateTime $timestamp; - private ApplicationContent $applicationContent; - private UserContent $userContent; + private ?ApplicationContent $applicationContent; + private ?UserContent $userContent; private ?string $rememberMeId; private ?string $parentRememberMeId; private ?string $error; @@ -23,8 +23,8 @@ public function __construct( string $id, string $sessionId, \DateTime $timestamp, - ApplicationContent $applicationContent, - UserContent $userContent, + ?ApplicationContent $applicationContent, + ?UserContent $userContent, ?string $rememberMeId, ?string $parentRememberMeId, ?string $error, @@ -58,20 +58,28 @@ public function getTimestamp(): \DateTime public function getProfile(): ?UserProfile { - return $this->userContent->getProfile(); + if ($this->userContent !== null) { + return $this->userContent->getProfile(); + } else { + return null; + } } public function getExtraData(): ?ExtraData { - return $this->userContent->getExtraData(); + if ($this->userContent !== null) { + return $this->userContent->getExtraData(); + } else { + return null; + } } - public function getApplicationContent(): ApplicationContent + public function getApplicationContent(): ?ApplicationContent { return $this->applicationContent; } - public function getUserContent(): UserContent + public function getUserContent(): ?UserContent { return $this->userContent; } diff --git a/src/Identity/ReceiptBuilder.php b/src/Identity/ReceiptBuilder.php index 7a091388..0851a088 100644 --- a/src/Identity/ReceiptBuilder.php +++ b/src/Identity/ReceiptBuilder.php @@ -16,9 +16,9 @@ class ReceiptBuilder private \DateTime $timestamp; - private ApplicationContent $applicationContent; + private ?ApplicationContent $applicationContent = null; - private UserContent $userContent; + private ?UserContent $userContent = null; private ?string $rememberMeId = null; diff --git a/src/Identity/ReceiptParser.php b/src/Identity/ReceiptParser.php index 375249da..904ef7b7 100644 --- a/src/Identity/ReceiptParser.php +++ b/src/Identity/ReceiptParser.php @@ -93,8 +93,11 @@ public function createFailure(WrappedReceipt $wrappedReceipt): Receipt ->build(); } - private function decryptReceiptKey(string $wrappedKey, ReceiptItemKey $wrappedItemKey, PemFile $pemFile): string + private function decryptReceiptKey(?string $wrappedKey, ReceiptItemKey $wrappedItemKey, PemFile $pemFile): string { + if ($wrappedKey == null) { + throw new EncryptedDataException('Wrapped is null'); + } // Convert 'iv' and 'value' from base64 to binary $iv = (string)base64_decode($wrappedItemKey->getIv(), true); $encryptedItemKey = (string)base64_decode($wrappedItemKey->getValue(), true); diff --git a/src/Identity/WrappedReceipt.php b/src/Identity/WrappedReceipt.php index 7d1f4b74..28e93f60 100644 --- a/src/Identity/WrappedReceipt.php +++ b/src/Identity/WrappedReceipt.php @@ -19,9 +19,9 @@ class WrappedReceipt private Content $otherPartyContent; - private string $wrappedItemKeyId; + private ?string $wrappedItemKeyId = null; - private string $wrappedKey; + private ?string $wrappedKey; private ?string $rememberMeId = null; @@ -38,8 +38,8 @@ public function __construct(array $sessionData) $this->id = $sessionData['id']; $this->sessionId = $sessionData['sessionId']; $this->timestamp = DateTime::stringToDateTime($sessionData['timestamp']); - $this->wrappedItemKeyId = $sessionData['wrappedItemKeyId']; - $this->wrappedKey = $sessionData['wrappedKey']; + $this->wrappedItemKeyId = $sessionData['wrappedItemKeyId'] ?? null; + $this->wrappedKey = $sessionData['wrappedKey'] ?? null; if (isset($sessionData['content'])) { $this->content = new Content( @@ -63,10 +63,10 @@ public function __construct(array $sessionData) if (isset($sessionData['error'])) { $this->error = $sessionData['error']; } - if (isset($sessionData['errorDetails'])) { - if (isset($sessionData["error_details"]["error_reason"]["requirements_not_met_details"])) { + if (isset($sessionData['errorReason'])) { + if (isset($sessionData["errorReason"]["requirements_not_met_details"])) { $this->errorReason = new ErrorReason( - $sessionData['errorDetails']['error_reason']['requirements_not_met_details'] + $sessionData["errorReason"]["requirements_not_met_details"] ); } } @@ -115,12 +115,12 @@ public function getOtherPartyExtraData(): ?string return $this->otherPartyContent->getExtraData(); } - public function getWrappedItemKeyId(): string + public function getWrappedItemKeyId(): ?string { return $this->wrappedItemKeyId; } - public function getWrappedKey(): string + public function getWrappedKey(): ?string { return $this->wrappedKey; } diff --git a/src/Profile/UserProfile.php b/src/Profile/UserProfile.php index d9ac0210..e4189a56 100644 --- a/src/Profile/UserProfile.php +++ b/src/Profile/UserProfile.php @@ -28,7 +28,6 @@ class UserProfile extends BaseProfile public const ATTR_DOCUMENT_IMAGES = 'document_images'; public const ATTR_STRUCTURED_POSTAL_ADDRESS = 'structured_postal_address'; public const ATTR_IDENTITY_PROFILE_REPORT = 'identity_profile_report'; - /** @var \Yoti\Profile\Attribute\AgeVerification[] */ private $ageVerifications; diff --git a/tests/Identity/Policy/PolicyBuilderTest.php b/tests/Identity/Policy/PolicyBuilderTest.php index 58b7968e..4865504b 100644 --- a/tests/Identity/Policy/PolicyBuilderTest.php +++ b/tests/Identity/Policy/PolicyBuilderTest.php @@ -680,7 +680,7 @@ public function testWithAdvancedIdentityProfileRequirements() "label" => "identity-AL-L1", "type" => "IDENTITY", - "objective"=> "AL_L1" + "objective" => "AL_L1" ], [ "label" => "identity-AL-M1",