getKey(), 30) ->block(5, fn (): IdentityVerificationRequest => $this->store($user, $document)); } private function store(User $user, UploadedFile $document): IdentityVerificationRequest { $existingRequest = $user->identityVerificationRequest()->first(); if ($existingRequest?->status === IdentityVerificationStatus::PENDING) { throw new ConflictHttpException(__('api.certification.already_pending')); } $disk = (string) config('billing.identity_verification.disk', 'identity_documents'); $path = null; try { $path = Storage::disk($disk)->putFileAs( 'submissions', $document, Str::ulid().'.'.$this->extensionFor($document), ['visibility' => 'private'], ); if (! is_string($path) || $path === '') { throw new \RuntimeException('The identity document could not be stored.'); } $verificationRequest = IdentityVerificationRequest::query()->updateOrCreate( ['user_id' => $user->getKey()], [ 'status' => IdentityVerificationStatus::PENDING, 'document_disk' => $disk, 'document_path' => $path, 'document_mime_type' => $document->getMimeType(), 'document_size' => $document->getSize(), 'submitted_at' => now(), 'reviewed_at' => null, 'reviewed_by' => null, 'rejection_reason' => null, 'document_deleted_at' => null, ], ); } catch (Throwable $exception) { if ($path) { Storage::disk($disk)->delete($path); } throw $exception; } if ($existingRequest?->hasDocument() && $existingRequest->document_path !== $path) { Storage::disk($existingRequest->document_disk)->delete($existingRequest->document_path); } return $verificationRequest; } private function extensionFor(UploadedFile $document): string { return match ($document->getMimeType()) { 'image/jpeg' => 'jpg', 'image/png' => 'png', 'application/pdf' => 'pdf', default => throw new \InvalidArgumentException('Unsupported identity document type.'), }; } }