rikudou/qr-payment-interface
A PHP interface package defining a common contract for generating QR payment codes. Implement it in your library to support standardized QR payments such as Czech QR Platba, letting applications swap implementations without changing their code.
Architecture fit. rikudou/qr-payment-interface is a contract package, not a Laravel package. It ships a QrPaymentInterface plus a QrPaymentOptions value object and nothing else — no service provider, facade, config file, or migrations. That makes it a natural fit as a port in a hexagonal/layered design: our domain code depends on the interface, and a thin adapter binds it to a concrete implementation (rikudou/qr-payment-cz for Czech QR Platba / SPAYD, rikudou/qr-payment-sk for Slovak Pay by Square). It also means the package does not generate QR images — it produces the payment string only — so any image rendering (endroid/qr-code, bacon/bacon-qr-code, or a JS library) remains our responsibility.
Integration feasibility. High. Composer install is trivial, there is no framework coupling, and therefore no Laravel version ceiling and no conflict surface. The work is entirely in the wiring we author: a service provider binding the interface to a concrete class, a config file for default IBAN/BIC/currency/country, a validation layer, and a renderer. Expect a few hours for the spike and one to two days for a production-grade adapter with tests.
Technical risk. Low code risk, high lifecycle risk. The surface area is a handful of classes (easy to audit, easy to fork, MIT-licensed), but the maturity signals are poor: 3 stars, 0 dependents, last release April 2021, single maintainer. The real exposure is not a security bug — it's specification drift. Payment QR standards (SPAYD, Pay by Square, EPC) get revised, and an unmaintained formatter will silently emit codes that banking apps reject at the point of payment, which is a user-facing failure we cannot observe from our side. The "opportunity" signal here is real: nobody has published the Laravel-native glue, so the value we add is the provider/config/validation/rendering layer, not the interface itself.
Key questions. Which standards must we support at launch (CZ, SK, EPC, all three)? Do we need only generation, or also parsing/validation of inbound codes? Where does the QR image get rendered — server-side PNG/SVG, or client-side? Who owns the fork if upstream goes dark? What is the tolerance for a payment code being rejected by a banking app, and can we canary against real apps before rollout?
Stack fit. Clean. The interface has no Laravel dependency, so it installs alongside any Laravel 9–11 application on PHP 8.x without touching the framework's version matrix. The idiomatic integration is a dedicated QrPaymentServiceProvider that binds QrPaymentInterface to the concrete country implementation and publishes a config/qr-payment.php holding defaults (IBAN, BIC, currency, country code, message length limits). Wrap the interface in an application-level QrPaymentGenerator service so controllers and jobs never reference vendor namespaces directly — that is what makes the eventual fork or swap a one-line change.
Migration path. If we are currently hand-concatenating SPAYD strings (common in Czech/Slovak e-shops), capture the existing output as golden-file fixtures first, then introduce the interface behind the adapter and assert byte-for-byte parity against those fixtures. If we are adopting fresh, start with the interface as the seam from day one and add implementations per market rather than per feature.
Compatibility. Verify the composer constraint against our PHP floor — a 2021 package may declare ^7.x || ^8.0 and predate PHP 8.2's dynamic-property deprecation. Run a static analysis pass (PHPStan at our level) over the concrete implementation before committing, and pin the exact version in composer.lock. There is no extra.laravel auto-discovery, which is a feature here: nothing loads unless we explicitly register it.
Sequencing. (1) Spike: generate a code, scan it with two or three real banking apps. (2) Decide build-vs-fork and pin or vendor. (3) Author the service provider, config, and adapter with golden-file tests. (4) Add domain validation: IBAN mod-97, BIC format, amount in minor units, currency/country compatibility, message charset and length truncation. (5) Add the QR rendering layer as a separate, swappable concern. (6) Add observability before enabling for all users.
Maintenance. Treat this as an owned fork from day one. The surface is small enough that a mid-level engineer can re-implement it in a day, so the abandonment risk is containable — but it must be planned, not discovered. Options: pin the version and accept drift, vendor the source into app/, or maintain a private fork under the org with a replace entry. Budget a recurring review cadence against the underlying standards, not against upstream commits.
Support. Effectively none. No dependents means no downstream bug reports to learn from, no community forum, and a single maintainer whose responsiveness is unknown. Internal ramp-up is the real cost: an engineer can read the interface in twenty minutes, but understanding why a code is rejected requires reading the SPAYD / Pay by Square specifications directly, since the package documents neither.
Scaling. A non-issue. Generation is pure string formatting with no I/O, no database, and no external calls. Value objects are stateless and safe under Octane and under queue workers. The only scaling question is image rendering, which is CPU-bound and should be cached by a hash of the payment parameters rather than regenerated per request.
Failure modes. The dangerous ones are silent. Malformed or unsupported IBAN/BIC combinations can throw at runtime and surface as a 500 at checkout. Float rounding of amounts produces codes that scan but pay the wrong value. Over-length message fields get truncated in ways that break the standard or mangle diacritics. Most importantly, a spec-invalid code is valid-looking to us and rejected only by the payer's banking app — a failure our monitoring cannot see. Mitigate with strict domain validation on input, a rendering fallback that shows the human-readable payment details alongside the QR, and a canary rollout measured on "scan success" rather than "code generated."
Ramp-up. Low for the interface, moderate for the domain. Expect half a day to be productive in the code and two to three days to be genuinely confident about the payment standards and their edge cases. Pair the integration with a short internal write-up of the standard we implement; that document, not the package, will be what the next engineer actually relies on.
How can I help you explore Laravel packages today?