All packages
QR for Laravel
SEPA credit transfer (EPC)
EpcPayment implements EPC069-12 v3.1, the SEPA credit-transfer QR code (often called GiroCode). Amounts are money-for-laravel Money values — exact minor units, no floating-point rounding:
use RoundlyConsulting\Money\Money;
use RoundlyConsulting\Qr\Enums\{EpcCharset, EpcVersion};
use RoundlyConsulting\Qr\Payloads\Payments\Epc\EpcPayment;
$svg = Qr::epc(new EpcPayment(
name: 'Roundly Consulting s.r.o.',
iban: 'SK46 1100 0000 0029 4714 7960',
bic: 'TATRSKBX', // optional for EEA IBANs in version 002
amount: Money::ofMinor(12550, 'EUR'), // EUR only, 0.01 – 999 999 999.99
purpose: 'GDDS',
reference: 'RF18539007547034', // ISO 11649 structured reference …
// text: 'Invoice 2026-0042', // … or free text (not both)
information: 'Thank you',
version: EpcVersion::V002,
charset: EpcCharset::Utf8,
strictCharset: false,
))->svg();Arguments
| Argument | Rule |
|---|---|
name | Beneficiary name, 1–70 characters. |
iban | String or Iban; must be a valid IBAN. |
bic | Optional. Required in version 001, and in 002 for IBANs outside the EEA. |
amount | Optional Money, EUR only, 0.01 – 999 999 999.99. |
purpose | Optional purpose code, 1–4 uppercase letters or digits (e.g. GDDS). |
reference | Structured reference, 1–35 characters; an RF… value must pass ISO 11649. |
text | Unstructured remittance text, 1–140 characters — not together with reference. |
information | Beneficiary-to-originator information, 1–70 characters. |
version / charset / strictCharset | null takes the payments.epc.* config values through Qr::…; a direct toQrString() uses the standard’s defaults (002, UTF-8, not strict). |
What the standard fixes
- LF-separated elements without a trailing separator, at most 331 bytes in the declared character set — longer payloads throw PaymentPayloadTooLongException.
- Error correction M, at most version 13, byte segmentation, no ECI and no boost — these options are locked.
- Version 001 requires a BIC; version 002 without a BIC requires an EEA IBAN (EU 27 + IS, LI, NO).
- Eight character sets (UTF-8 and ISO-8859-1, -2, -4, -5, -7, -10, -15); a character the charset can’t represent throws an unrepresentable error naming the field.
- strictCharset restricts name, text, information and reference to the SEPA Latin subset.
- Text is NFC-normalised before length checks when ext-intl is available.
Parsing a scanned code
$payment = EpcPayment::fromString($scannedPayload); // parse (LF or CRLF)
$carried = Qr::epc($payment)->payload()->toQrString(); // the exact string the code carries (config applied)
$standard = $payment->toQrString(); // standard defaults for null fields — ignores configThe serialised form follows the standard — this is the example from EPC069-12 §2.3, reproduced byte for byte in the package’s tests:
BCD
001
1
SCT
BHBLDEHHXXX
Franz Mustermänn
DE71110220330123456789
EUR12.3
GDDS
RF18539007547034EPC codes default to Personal sensitivity; lower it to Public for a code printed on a public invoice page.
Show your open-source love
This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.
More ways to support, including cryptoBy donating, you agree to our donation terms.
Want this built into your product?
We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.