Skip to content

Counter Card

One code, printed once, left on the counter all day. No amount — the customer types the figure themselves.

Printed counter card with a static Raast QR

Generating It

bash
php artisan raast-qr:generate PK33ABCD0000000000000000 \
    --output=storage/app/counter-card.svg \
    --size=1200 \
    --margin=4 \
    --color='#01411C'

Or in code:

php
RaastQr::iban(config('raast-qr.iban'))
    ->format('svg')
    ->size(1200)
    ->margin(4)
    ->color('#01411C')
    ->save(storage_path('app/print/counter-card.svg'));

Why SVG

A counter card gets printed, and print wants vectors. An SVG scales to A5, A4 or a shop window poster with a perfectly crisp edge. A 1200px PNG blown up to A3 will not.

A Print-Ready Page

blade
{{-- resources/views/print/counter-card.blade.php --}}
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Scan to pay</title>
    <style>
        @page { size: A5; margin: 12mm; }
        body {
            font-family: system-ui, sans-serif;
            text-align: center;
            color: #01411C;
        }
        .qr { width: 90mm; margin: 8mm auto; }
        .qr svg { width: 100%; height: auto; }
        h1 { font-size: 28pt; margin: 0; }
        .title { font-size: 16pt; margin-top: 6mm; }
        .iban { font-family: ui-monospace, monospace; font-size: 12pt; }
        .note { font-size: 10pt; color: #4b5563; margin-top: 8mm; }
    </style>
</head>
<body>
    <h1>Scan to Pay</h1>

    <div class="qr">
        {!! RaastQr::iban(config('raast-qr.iban'))->size(600)->color('#01411C')->toSvg() !!}
    </div>

    <p class="title">{{ config('raast-qr.account_title') }}</p>
    <p class="iban">{{ RaastQr::formatIban(config('raast-qr.iban')) }}</p>

    <p class="note">
        Open your banking app, choose Raast or Scan to Pay, then enter the amount.
        Please check the account title before you confirm.
    </p>
</body>
</html>
php
RaastQr::iban(config('raast-qr.iban'))
    ->format('svg')
    ->size(1200)
    ->color('#01411C')
    ->errorCorrection('H')
    ->logo(public_path('brand/mark.png'), size: 200)
    ->save(storage_path('app/print/counter-card.svg'));

Test the printed card, not the screen

A logo that scans perfectly on your monitor can fail on a card printed at 300dpi under fluorescent light. Print one, scan it with three different phones, then print the rest.

Practical Notes

  • Print at least A5. A code smaller than about 5cm is a struggle for older phone cameras across a counter.
  • Laminate it. A code with a coffee ring through it is why you set errorCorrection('H'), but don't push your luck.
  • Keep contrast high. Dark green on white. Not grey on cream.
  • Put the account title on the card. People compare it against what their app shows. That comparison is the whole security model.

Reconciliation Reality

Every payment through one static code lands in the same account with the amount the customer typed and no reference at all.

That's fine for a small stall. For anything with volume, you'll want either a screenshot-on-payment habit at the counter, or Raast P2M through an acquirer that gives you real settlement reporting.


Made with ❤️ from Pakistan