omnipay/sagepay
Sage Pay (Opayo) driver for Omnipay, the framework-agnostic PHP payment library. Integrates Form, Server, Direct and XML gateways behind a consistent API, covering purchases, refunds, voids, recurring payments and 3D Secure in Laravel or any PHP application.
Architecture fit. omnipay/sagepay is a driver plugin for the framework-agnostic Omnipay payment abstraction layer, not a Laravel package. It slots in cleanly at the service layer: a Laravel service provider binds an Omnipay gateway instance, controllers wrap purchase()/authorize()/capture()/refund()/void() calls, and the app owns all UI, persistence, and business logic. This is the correct shape for a payment integration — it keeps the vendor SDK at arm's length and gives us a swappable seam if the gateway changes. The package exposes multiple gateway classes (Form, Server, Direct, and REST/PI-style variants depending on release), which map to materially different integration patterns: Form is a redirect + signed callback, Server is a server-to-server notification flow, Direct is a direct API card capture (heaviest PCI burden). The choice of gateway class is effectively an architecture decision, not a config flag.
Integration feasibility. Composer-installable, MIT-licensed, PSR-4, depends on omnipay/common. A senior Laravel developer can stand up a sandbox purchase in hours and a production-grade flow in two to four weeks, with most of that time in 3-D Secure handling, webhook idempotency, and token/repeat billing rather than the driver itself. The driver is a thin request/response mapper, so the integration work is overwhelmingly in our code. Feasibility is high; effort is dominated by edge cases and compliance, not by the library.
Technical risk.
Key questions.
Stack fit. Target Laravel 9–11 on PHP 8.1+, Omnipay 3.x, and the driver pinned to a minor version. Bind the gateway through a dedicated SagePayServiceProvider, surface it behind our own PaymentGateway interface, and keep Omnipay request/response objects out of controllers and models. Queue notification handling; never process a webhook inside the request cycle.
Migration path. Two scenarios. Greenfield: build the interface first, implement a sandbox adapter, then harden. Replacement (legacy Sage Pay integration or another PSP): do not do a lift-and-shift. Introduce the interface, run the new driver in parallel behind a feature flag, and dual-write transaction records. Stored tokens are not portable across providers — plan for either a merchant-led account migration or a customer re-tokenization campaign with a defined grace window.
Compatibility. Verify the PHP/Laravel support matrix, Guzzle/PSR-18 version constraints against the rest of the dependency graph, and the driver's major-version alignment with omnipay/common. Add a CI job that runs the full checkout suite against the lowest and highest supported Laravel versions. Confirm currency, locale, and AVS/CV2 rules with the acquiring bank before writing validation logic.
Sequencing.
PaymentGateway interface and domain events; implement the adapter.Maintenance. Low release cadence (last release March 2024) is a double-edged signal: stable, but not actively evolving. Budget roughly 1–2 engineer-days per quarter for dependency bumps and regression testing, plus a standing contingency to fork and vendor the driver. Given the Opayo/Elavon transition, maintain a written exit plan — an alternate PSP adapter behind the same interface — before this becomes urgent rather than after.
Support. Community GitHub issues only; no SLA, no vendor escalation through the package maintainer. Elavon/Opayo merchant support covers the gateway, not the PHP driver, so integration defects are ours to diagnose. Standing capability required: one engineer who can read Omnipay internals and raw gateway XML/HTTP traces.
Scaling. The driver is stateless and horizontally scalable — throughput is bounded by the gateway's rate limits, not by PHP. The real scaling concerns are the token store (needs durable, encrypted persistence with key rotation) and the reconciliation pipeline (must handle settlement lag and late-arriving notifications). Queue webhooks with retry and dead-letter handling; cap concurrency per merchant account.
Failure modes. Duplicate charges from client retries or webhook replays; lost notifications leaving orders in a pending state; 3DS redirect abandonment; signature/encryption-key mismatch after rotation; partial refunds recorded inconsistently; currency or AVS misconfiguration surfacing only at settlement; silent driver breakage after an unpinned dependency update. Mitigations: idempotency keys on every outbound request, a reconciliation job comparing our ledger to settlement reports daily, alerting on unmatched transactions older than one settlement cycle, automated key-rotation tests, and synthetic sandbox transactions in CI.
Ramp-up. A mid-level Laravel developer needs about a week to become productive with Omnipay's request/response model and roughly two to three more weeks to be trustworthy on Sage Pay specifics — 3DS, token semantics, notification ordering, and refund rules. QA needs a curated sandbox card matrix and a documented expected-result table. Total time-to-confidence for a single engineer: four to six weeks, assuming a merchant account and sandbox credentials are available on day one, which is frequently the actual bottleneck.
How can I help you explore Laravel packages today?