An open-source, multi-language Pay By Square suite by usmansher: generate the payload behind Slovak banking payment QR codes in TypeScript, PHP, Laravel, or over HTTP — with the same contract everywhere. Every implementation is verified in CI against the same shared test vectors and the same normative reference verifier, so identical input produces an identically-decodable payload in every language.
▶ Try the live demo — the
in-browser Storybook runs the real @paybysquare/core encoder and renders
the QR as you edit the payment.
Beyond the cross-language conformance suite, the generated codes are scan-tested with real Slovak banking apps: payment details pre-fill as expected, including UTF-8 diacritics in names and notes.
| Path | What it is | Distribution |
|---|---|---|
spec/ |
Normative encoding spec, shared test vectors, reference verifier, OpenAPI contract | — |
packages/core |
TypeScript payload generator, zero runtime dependencies (Node, browsers, edge) | npm @paybysquare/core |
packages/php |
Pure PHP (>= 8.2) payload generator, no extensions, no shell-outs | Packagist paybysquare/php |
packages/laravel |
Laravel integration: config defaults, facade, Blade QR component | Packagist paybysquare/laravel |
service/ |
Node/Fastify HTTP microservice with Docker image (private package) | Docker / self-hosted |
npm install @paybysquare/core qrcodeimport { generatePayload } from '@paybysquare/core';
import QRCode from 'qrcode';
const payload = generatePayload({
amount: 25.5,
iban: 'SK7283300000009111111118',
beneficiaryName: 'John Doe',
swift: 'FIOZSKBAXXX',
variableSymbol: '12345',
});
// Pair with any QR library, e.g. `qrcode`:
const dataUrl = await QRCode.toDataURL(payload);generatePayload returns the text to put into the QR code; the library
deliberately has zero runtime dependencies and leaves QR rendering to you.
Invalid input throws a ValidationError with a field property.
composer require paybysquare/phpuse PayBySquare\PayBySquare;
$payload = PayBySquare::generatePayload([
'amount' => 25.50,
'iban' => 'SK7283300000009111111118',
'beneficiaryName' => 'John Doe',
'swift' => 'FIOZSKBAXXX',
'variableSymbol' => '12345',
]);
// Render $payload with any QR library, e.g. bacon/bacon-qr-code.Accepts a PayBySquare\Payment object or an array of the canonical
field names from spec/SPEC.md.
composer require paybysquare/laravel bacon/bacon-qr-code
php artisan vendor:publish --tag=paybysquare-configSet defaults (IBAN, SWIFT, currency, beneficiary name) in
config/paybysquare.php or via PAYBYSQUARE_* env vars, then:
use PayBySquare\Laravel\Facades\PayBySquare;
$payload = PayBySquare::payload(['amount' => 25.50, 'variableSymbol' => '12345']);
$svg = PayBySquare::qrSvg(['amount' => 25.50], size: 256);Or drop the Blade component straight into a view:
<x-paybysquare-qr :payment="['amount' => 25.50, 'variableSymbol' => '12345']" :size="256" />The Fastify service in service/ exposes the generator over HTTP
(OpenAPI contract in spec/openapi.yaml, served at
GET /v1/openapi.json):
# Build from the repository root (the image needs packages/core and spec/openapi.yaml)
docker build -f service/Dockerfile -t paybysquare-service .
docker run --rm -p 8080:8080 -e AUTH_TOKEN=your-token paybysquare-servicecurl -X POST "http://localhost:8080/v1/qr?format=png" \
-H "Authorization: Bearer your-token" \
-H "Content-Type: application/json" \
-d '{"amount": 25.50, "iban": "SK7283300000009111111118", "beneficiaryName": "John Doe"}' \
--output qr.pngPOST /v1/payload returns the raw payload as JSON; POST /v1/qr renders PNG
or SVG (?format=svg, ?size=...). Auth is optional (the API is open when
AUTH_TOKEN is unset) and rate limiting defaults to 60 requests/minute.
The byte-for-byte encoding contract lives in spec/SPEC.md.
All implementations share spec/test-vectors.json
and a large differential
spec/conformance-corpus.json: the TypeScript
core is the golden encoder, and every other implementation must reproduce each
payload byte-for-byte, so cross-language parity is enforced across the whole
input space in CI. Each package's test suite decodes its own output with an
in-language decoder (no runtime dependency), while
spec/tools/verify.py (python3, stdlib only) is the
general liblzma decoder for verifying any payload, including scanned ones.
"PAY by square" is a payment standard of the Slovak Banking Association. This project is an independent open-source implementation and is not affiliated with, endorsed by, or sponsored by the Slovak Banking Association.
See CONTRIBUTING.md for dev setup, the test-vector contract, and PR conventions. For copy-paste recipes to generate payloads and QR codes during development (every stack, shared dev parameters), see the development playbook.
MIT © 2026 usmansher