diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index 0207dcb4..58822967 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -45,7 +45,8 @@ public function register() $this->renderable(function (InvalidQrCodeException $exception, $request) { return response()->json([ - 'message' => 'not a valid QR code', ], 400); + 'message' => $exception->getMessage(), + ], 400); }); $this->renderable(function (InvalidSecretException $exception, $request) { diff --git a/app/Services/QrCodeService.php b/app/Services/QrCodeService.php index 3379da92..db9b69c5 100644 --- a/app/Services/QrCodeService.php +++ b/app/Services/QrCodeService.php @@ -5,6 +5,9 @@ use chillerlan\QRCode\QRCode; use chillerlan\QRCode\QROptions; use Illuminate\Support\Facades\Log; +use Zxing\ChecksumException; +use Zxing\FormatException; +use Zxing\NotFoundException; use Zxing\QrReader; class QrCodeService @@ -37,12 +40,39 @@ public static function encode(string $data) public static function decode(\Illuminate\Http\UploadedFile $file) { $qrcode = new QrReader($file->get(), QrReader::SOURCE_TYPE_BLOB); - $data = urldecode($qrcode->text()); + $text = $qrcode->text(); - if (! $data) { - throw new \App\Exceptions\InvalidQrCodeException; + if (! $text) { + $text = $qrcode->text([ + 'TRY_HARDER' => true, + 'NR_ALLOW_SKIP_ROWS' => 0, + ]); } + // At this point, if we do not have a text, QR code cannot be detected or decoded + // so we check the error to provide the user a relevant error message + if (! $text) { + switch (get_class($qrcode->getError())) { + case NotFoundException::class: + throw new \App\Exceptions\InvalidQrCodeException(__('errors.cannot_detect_qrcode_in_image')); + break; + + case FormatException::class: + throw new \App\Exceptions\InvalidQrCodeException(__('errors.cannot_decode_detected_qrcode')); + break; + + case ChecksumException::class: + throw new \App\Exceptions\InvalidQrCodeException(__('errors.qrcode_has_invalid_checksum')); + break; + + default: + throw new \App\Exceptions\InvalidQrCodeException(__('errors.no_readable_qrcode')); + break; + } + } + + $data = urldecode($qrcode->text()); + Log::info('QR code decoded'); return $data; diff --git a/resources/lang/en/errors.php b/resources/lang/en/errors.php index fff97798..817b355e 100644 --- a/resources/lang/en/errors.php +++ b/resources/lang/en/errors.php @@ -67,5 +67,8 @@ 'account_managed_by_external_provider' => 'Account managed by an external provider', 'data_cannot_be_refreshed_from_server' => 'Data cannot be refreshed from server', 'no_pwd_reset_for_this_user_type' => 'Password reset unavailable for this user', - 'app_key_is_not_set' => 'The APP_KEY environment variable is not set', + 'cannot_detect_qrcode_in_image' => 'Cannot detect a QR code in the image, try to crop the image', + 'cannot_decode_detected_qrcode' => 'Cannot decode detected QR code, try to crop or sharpen the image', + 'qrcode_has_invalid_checksum' => 'QR code has invalid checksum', + 'no_readable_qrcode' => 'No readable QR code', ]; \ No newline at end of file