Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Skqrpayment Laravel Package

rikudou/skqrpayment

Laravel package for generating Slovak QR payment codes. Build payment strings with IBAN, amount, variable symbol, and recipient details, then render scannable QR codes for mobile banking apps. Simple, configurable, and easy to integrate.

View on GitHub
Deep Wiki
Context7

Getting Started

1. Install

composer require rikudou/skqrpayment:^4.2.3

Pin to ^4.2.3 (or at minimum >=4.2.3) if you run PHP 8.4 — see the PHP version note in Gotchas.

2. Look here first

  • README.md — the only usage doc; confirm the exact class name/namespace before writing code (it is a single-class-style library, so the README is the whole API surface).
  • src/QrPayment.php — the entire public API: setters for IBAN, amount, currency, variable/specific/constant symbol, due date, note, and a method that returns the QR payload string.
  • composer.json — check the PHP version constraint and whether ext-* (e.g. mbstring, compression) is required.

There is no service provider, no facade, no config file, no migrations. It is a framework-agnostic leaf dependency. In Laravel you simply new it (or resolve it from the container).

3. First use case — invoice → scannable Pay by Square QR

use Rikudou\QrPaymentSK\QrPayment; // verify FQCN against the README

$payment = new QrPayment();
$payment->setIban('SK3112000000198742637541');     // no spaces
$payment->setAmount(49.99);                         // check float vs string in README
$payment->setCurrency('EUR');
$payment->setVariableSymbol('2025001');
$payment->setDueDate(new \DateTimeImmutable('2025-06-30'));
$payment->setNote('Faktura 2025-001');

$payload = $payment->getQrString();   // Pay by Square string, or (string) $payment

The package does not render images — it only produces the payload. Pair it with any QR renderer:

composer require endroid/qr-code
use Endroid\QrCode\QrCode;
use Endroid\QrCode\Writer\PngWriter;

$qr = new QrCode($payload);
$qr->setSize(320);
$qr->setMargin(8); // quiet zone matters for scanners
$png = (new PngWriter())->write($qr)->getString();

That is the whole first milestone: a scannable QR that a Slovak banking app will accept.

Implementation Patterns

Wrap it in a domain action. Don't sprinkle new QrPayment() across controllers. Build one class that maps your Invoice model to a payment and returns the payload:

final class BuildInvoiceQrPayload
{
    public function __invoke(Invoice $invoice): string
    {
        $payment = new QrPayment();
        $payment->setIban($invoice->bankAccount->iban);
        $payment->setAmount(number_format($invoice->total, 2, '.', ''));
        $payment->setCurrency('EUR');
        $payment->setVariableSymbol((string) $invoice->number);
        $payment->setDueDate($invoice->due_at);
        $payment->setNote(mb_substr($invoice->label, 0, 60));

        return $payment->getQrString();
    }
}

Return a data URI from a Blade component so the same QR works in web views, PDFs, and emails:

public function render(): string
{
    $png = (new PngWriter())->write(new QrCode($this->payload))->getString();

    return 'data:image/png;base64,' . base64_encode($png);
}

Embed in mailables with $message->embedData($png, 'qr.png', 'image/png') — do not attach as a file, scanners expect a rendered image.

Cache the payload, not the image. Key on the invoice's stable identifier plus updated_at; the payload only changes when bank details or amount change. Images are cheap to regenerate and expensive to invalidate.

Bulk/queued generation. For month-end PDF runs, generate payloads in a queued job and write the PNG to storage; the library itself is pure CPU and safe under concurrency (stateless, no I/O).

Integration with existing PDF tooling. Pass the PNG bytes into dompdf/snappy via the data URI above. Keep the QR at ≥ 256 px in the rendered document.

Testing pattern. Golden-file your payloads:

$payload = (new BuildInvoiceQrPayload())(Invoice::factory()->make([...]));

$this->assertSame(file_get_contents(base_path('tests/fixtures/qr.txt')), $payload);

Better: decode with a reference implementation in a separate test and assert the decoded fields, so a library re-release that changes compression doesn't break CI.

Pin and upgrade deliberately. These are patch-only releases with no changelog surface beyond PR titles; bump the constraint in a dedicated dependency PR with your payload tests green, not as a side-effect of composer update.

Isolate the dependency. Because the package is a single leaf class, a one-file adapter (QrPayloadFactory) means swapping it out later is a day's work, not a refactor.

No config needed. If you want the library injectable for mocking, bind it in a service provider as a closure factory rather than a singleton — it carries mutable state across setters, so a singleton is a footgun.

Gotchas and Tips

  • Don't expect a facade or config/skqrpayment.php. If your codebase assumes Laravel-style packages, this one will surprise you — resolve it manually or behind your own adapter.
  • PHP 8.4: use v4.2.3 or later. v4.2.3 is a single fix for a PHP 8.4 deprecation notice (implicit-nullable/related deprecations in the encoder path). Behaviour is unchanged — the payload bytes are identical — but on 8.4 older versions emit deprecations that will pollute storage/logs/laravel.log and can fail suites that convert deprecations to exceptions (PHPUnit convertDeprecationsToExceptions, failOnDeprecation under Pest). This is a drop-in patch; no API change, no re-testing of payload fixtures required beyond your normal suite.
  • IBAN format is strict. Strip spaces before setting; ideally validate with IsoCodes\Iban or a regex, because a wrong IBAN produces a valid-looking QR that fails in the banking app, not at generation time.
  • Amount precision is the classic bug. Decide once whether setAmount() wants 49.99 (float/string) or 4999 (cents) — the README is authoritative. Prefer passing number_format($x, 2, '.', '') and never a raw float, to dodge 49.989999 serialization in the payload.
  • Due dates take a DateTimeInterface and are serialized as Ymd — timezone irrelevant, but passing a string will throw. Format at the boundary.
  • Optional fields must be omitted, not set to '' or null. An empty note or specific symbol can change the payload or trigger a validation exception. Guard every optional setter with if (!empty(...)).
  • Notes and symbols have character limits (the spec caps the note around 60 chars and disallows some characters). Strip diacritics or restrict to [A-Za-z0-9 .,-/] before setting; don't let user-entered Slovak text flow straight through.
  • Never mutate the payload string. It contains a compressed, base32-encoded body. trim(), lowercase/uppercase conversion, URL-encoding, or newline normalization will corrupt it. Store and transmit it byte-for-byte.
  • Error correction and size. Banking apps are fussy; use a quiet zone (margin ≥ 4 modules), a rendered size of at least 256×256 px, and let your QR library pick the EC level rather than forcing one — the Pay by Square spec constrains this.
  • Library updates can change the payload without changing the data (compression settings, field ordering). Never assert exact bytes against user-visible behavior; assert decoded semantics or pin the version in composer.json with a ~ constraint given 37 stars and zero dependents — you are the QA team. v4.2.3 is purely a deprecation fix, so it is one of the safest bumps you'll get; use it to stay current on PHP 8.4 without payload risk.
  • Debugging failures: if a scanner rejects the code, first decode the payload with a reference bysquare decoder to confirm the library's output, then check rendering (size/margin) — the two failure modes look identical to users.
  • Exceptions are InvalidArgumentException-flavored. Catch at the boundary (e.g. a form request or job) and surface a validation error, rather than letting a bad IBAN produce a 500 halfway through PDF generation.
  • Currency: in practice only EUR is accepted by Slovak banking apps — don't expose a currency selector in your UI.
  • Extension points are minimal by design. There is no plugin hook; extend by composing (subclass QrPayment only if you need to intercept payload generation, which is rarely wise for a spec-bound format).
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core