Product Decisions This Supports
- Invoice "scan-to-pay" experiences. This package generates the EPC (European Payments Council) QR payload — the "BCD" string a banking app scans to prefill a SEPA credit transfer (IBAN, BIC, amount, remittance reference). The highest-leverage PM use case is putting that QR on PDF invoices, statements, dunning notices, and payment-reminder emails so an EU customer can pay from their bank app in three taps instead of retyping an IBAN.
- A zero-fee payment rail in checkout. For EU markets, offering "pay by bank transfer via QR" alongside cards gives you a payment path with no interchange, no PSP percentage, and no chargeback exposure. That is a direct COGS lever on every transaction and a conversion lever for cost-sensitive or card-averse segments.
- Geographic expansion sequencing. EPC QR is native to the DACH, Benelux, and Nordic banking habits. If your roadmap has an "EU launch" line item, this is the cheapest credible payment affordance you can ship for those markets — it's a string builder, not a merchant onboarding project.
- Build vs. buy. This is the classic "build" quadrant: the EPC v2 spec is a short, well-documented, deterministic payload format. The package is a thin encoder (18 stars, 0 dependents, last release Sept 2021). The real decision isn't "adopt vs. buy a vendor" — it's "reuse this encoder as a spec reference or port ~200 lines into our own codebase." Either way the decision cost is days, not sprints.
- B2B / high-ticket flows. Where card fees and limits bite (invoices above a few thousand euros, SEPA-only counterparties), QR-initiated credit transfer is often the expected mechanism rather than a fallback.
- Explicitly out of scope: recurring billing, card acquiring, PSD2/Open Banking account information, and payment confirmation. EPC QR is initiation-only — there is no callback, no webhook, no settlement signal. Any roadmap item that assumes "customer scanned → we know they paid" is architecturally wrong.
When to Consider This Package
Adopt (or port) when:
- Your payers hold accounts at EPC QR-supporting banks and you already collect
IBAN, BIC, beneficiary name, and a remittance reference — the package turns that into a scannable payload with correct field ordering, charset, and length validation.
- You need the format right rather than approximate: version, character set ID, identification code, purpose code, structured vs. unstructured reference, and optional fields are easy to get subtly wrong, and a malformed payload fails silently in a banking app.
- You want a dependency-free, MIT-licensed encoder you can vendor into your own namespace and own outright.
- You're shipping a document-generation or billing feature where a printed QR is a supporting affordance, not a revenue-critical integration.
Look elsewhere when:
- You need a maintained dependency. Last release 2021-09-27, 18 stars, 0 dependents. No security-response posture, no Laravel-version support matrix, no active issue triage. Treat it as code to read, not a library to trust with a supply chain. Fork it into your repo, add tests, and take ownership — the surface area is small enough that this is cheap.
- You need payment confirmation or reconciliation. EPC QR gives you nothing back. If your product requires "did they pay?", you need a PSP, a bank statement ingestion pipeline, or PSD2 account access — a separate and much larger build.
- You need card, wallet, or non-SEPA rails. Different problem, different vendor.
- Your users are outside the SEPA/EPC QR footprint, or their banks don't surface a scanner in their app. Validate this with five real customers before committing roadmap.
- You need SEPA Instant semantics (near-real-time settlement, instant confirmation). Some banks infer speed from the scheme, but this package only encodes the transfer; instant settlement is a bank-side property you can't control from a QR string.
Validation gate before committing: take three generated payloads to three different EU banking apps and confirm they prefill correctly, including the amount and the reference. That single test de-risks the entire feature.
How to Pitch It (Stakeholders)
To executives: We can add a "scan the QR to pay" option on EU invoices and checkout for roughly a day of engineering, using an MIT-licensed open-source encoder. It routes payment as a standard SEPA bank transfer, which means no card interchange, no PSP percentage, and no chargebacks on those transactions — a direct margin improvement that compounds with volume. It also removes real friction for customers in Germany, Austria, the Netherlands, Belgium, and the Nordics, where scanning a QR from a banking app is routine. The trade-off to be explicit about: this is a payment initiation tool, not a payment processor — it does not tell us when the money arrives, so reconciliation stays with finance or a future bank-feed project. Risk is low and contained: the library is a small pure-PHP string builder, we will fork it into our own codebase and add our own tests, so we are not taking on an unmaintained third-party dependency.
To engineering: Small, pure-PHP, no runtime dependencies, single responsibility — it encodes EPC v2 payloads. Last release 2021 with 18 stars and no dependents, so we treat it as reference implementation, not a dependency: vendor or reimplement, own the tests, and pin the spec version in a comment. Two things to be careful about: silent failure modes (a malformed payload simply doesn't prefill in a banking app — no error surfaces to us), and field-length/charset handling that the library may not enforce. Add golden-file tests against real bank-app behavior. Keep the encoder behind our own interface so the payment-rail choice stays swappable.
To the product owner: Ship it as a complement, never as the only way to pay. Instrument the funnel — render rate, scan rate inferred from a "did you pay by QR?" prompt or a short-link redirect — so we can measure whether payers actually use it before we invest in reconciliation infrastructure.