Handling Errors
Everything in the package throws a single exception type, RaastQrException, carrying a machine-readable code.
use RealRashid\RaastQr\Exceptions\RaastQrException;
use RealRashid\RaastQr\Facades\RaastQr;
try {
$qr = RaastQr::iban($request->iban)->amount($request->amount)->toSvg();
} catch (RaastQrException $e) {
return response()->json([
'code' => $e->reason(), // 'INVALID_AMOUNT'
'message' => $e->getMessage(),
], 422);
}The Codes
| Code | Cause |
|---|---|
INVALID_OPTIONS | No IBAN was supplied and none is configured |
INVALID_IBAN | Wrong shape, wrong country, or failed checksum |
INVALID_AMOUNT | Not positive, too many decimals, or too long |
INVALID_EXPIRY | Not a real calendar date, or the wrong format |
INVALID_CRC_INPUT | Internal — the checksum received a non-string |
INVALID_QR_OPTIONS | Bad colour, bad format, bad error correction, missing logo |
RENDERER_FAILURE | The image layer could not draw the code |
Branching on the Enum
$e->reason() gives you the string. $e->errorCode gives you the enum, which is what you want in a match:
use RealRashid\RaastQr\Enums\ErrorCode;
try {
return RaastQr::iban($vendor->iban)->amount($order->total)->format('svg');
} catch (RaastQrException $e) {
return match ($e->errorCode) {
ErrorCode::InvalidIban => back()->withErrors([
'iban' => 'This vendor\'s account number needs updating.',
]),
ErrorCode::InvalidAmount => back()->withErrors([
'amount' => 'This total cannot be encoded in a QR code.',
]),
default => throw $e,
};
}Note the default => throw $e
Rethrowing anything you didn't plan for keeps genuine bugs visible instead of swallowing them into a generic 422.
$code vs $errorCode
RaastQrException extends InvalidArgumentException, so it inherits $code from PHP's Exception — an integer, always 0 here. The enum lives on its own property:
$e->code; // 0, inherited from \Exception — ignore it
$e->errorCode; // ErrorCode::InvalidAmount
$e->reason(); // 'INVALID_AMOUNT'Catch Early, Not Late
The exception is thrown when you ask for output, not when you set a value:
$qr = RaastQr::iban('nonsense')->amount('also nonsense'); // fine, nothing computed
$qr->toPng(); // throws hereThat means a builder returned from a controller throws during response rendering, which is a worse place to handle it. If the input came from a user, validate first:
$request->validate([
'iban' => ['required', new PakistaniIban],
'amount' => ['required', 'numeric', 'min:0.01', 'max:9999999.99', 'decimal:0,2'],
]);See Validating IBANs.
Reporting
RaastQrException extends InvalidArgumentException, so Laravel reports it like any other exception. If bad IBANs are routine user input rather than bugs, tell the handler not to bother:
// bootstrap/app.php
->withExceptions(function (Exceptions $exceptions) {
$exceptions->dontReport(RaastQrException::class);
})Only do this once you're validating input properly, or you'll lose sight of real failures.
Made with ❤️ from Pakistan