profileFor($user); if (! $profile) { throw new RuntimeException(__('identity_verification.profile_missing')); } if ($profile->identity_verification_status === IdentityVerificationStatusEnum::APPROVED) { throw new RuntimeException(__('identity_verification.already_approved')); } $maxAttempts = (int) config('services.didit.max_attempts', 3); if ((int) $profile->identity_verification_attempts >= $maxAttempts) { throw new RuntimeException(__('identity_verification.attempts_exhausted')); } $open = IdentityVerification::query() ->where('user_id', $user->id) ->whereIn('didit_status', ['Not Started', 'In Progress']) ->latest('id') ->first(); if ($open) { return $open; } $response = $this->diditRequest( method: 'POST', path: '/v3/session/', errorMessage: __('identity_verification.session_failed'), payload: $this->buildRequest($user, $profile, $native), ); $session = SessionResponseData::fromResponse($response); return DB::transaction(function () use ($user, $profile, $session) { $attempt = (int) $profile->identity_verification_attempts + 1; $profile->forceFill([ 'identity_verification_status' => IdentityVerificationStatusEnum::PENDING->value, ])->save(); return IdentityVerification::create([ 'user_id' => $user->id, 'session_id' => $session->sessionId, 'session_token' => $session->sessionToken, 'workflow_id' => $session->workflowId, 'didit_status' => $session->status ?? 'Not Started', 'attempt' => $attempt, 'started_at' => now(), ]); }); } public function getDecision(string $sessionId): array { return $this->diditRequest( method: 'GET', path: "/v3/session/{$sessionId}/decision/", errorMessage: __('identity_verification.decision_failed'), ); } public function verificationUrl(IdentityVerification $verification): string { return 'https://verify.didit.me/pt/session/'.$verification->session_token; } // private function buildRequest(User $user, Model $profile, bool $native = false): SessionRequestData { return new SessionRequestData( workflowId: $this->workflowFor($user), vendorData: (string) $user->id, callback: $this->callbackFor($user, $native), language: 'pt', expectedDetails: ExpectedDetailsData::fromName( fullName: $user->name, dateOfBirth: $profile->birth_date?->format('Y-m-d'), document: $profile->document, ), contactDetails: new ContactDetailsData( email: $user->email, phone: $user->phone, ), ); } private const APP_SCHEMES = [ 'provider' => 'br.com.diarista.provider', 'client' => 'br.com.diarista.client', ]; private function callbackFor(User $user, bool $native = false): ?string { $app = $user->type === UserTypeEnum::PROVIDER ? 'provider' : 'client'; if ($native) { return self::APP_SCHEMES[$app].'://verification/done'; } $callback = config('services.didit.callback_url'); if (! is_string($callback) || $callback === '') { return null; } return $callback.(str_contains($callback, '?') ? '&' : '?').'app='.$app; } private function workflowFor(User $user): string { $workflow = $user->type === UserTypeEnum::PROVIDER ? config('services.didit.workflow_provider') : config('services.didit.workflow_client'); if (! is_string($workflow) || $workflow === '') { throw new RuntimeException(__('identity_verification.workflow_missing')); } return $workflow; } private function profileFor(User $user): Provider|Client|null { return $user->type === UserTypeEnum::PROVIDER ? $user->provider : $user->client; } }