Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Saferpay Bundle Laravel Package

payment/saferpay-bundle

A Symfony bundle for integrating the Saferpay payment gateway into PHP applications. It streamlines configuration and payment processing, helping you accept secure online card payments with less boilerplate.

View on GitHub
Deep Wiki
Context7

Getting Started

Treat this as a protocol reference, not an installable dependency. The package is a Symfony bundle (payment/saferpay-bundle) with a DI extension, Resources/config/ service definitions, and the older Payment/JMS payment abstractions. There is no Laravel service provider, no facade, no publishable config, and no queue/event hooks — so composer require-ing it into a Laravel app just gets you a dormant bundle plus its transitive baggage.

Minimal first steps:

  1. Clone it, don't install it. git clone https://github.com/payment-legacy/SaferpayBundle into a scratch directory and read it. Confirm a LICENSE exists before copying anything.
  2. Read composer.json first. Note the PHP constraint, Guzzle version, and whether it pulls in payment/… abstractions you do not want. If it targets PHP 5.6/7.x-era deps, expect mcrypt, each(), or create_function style artifacts — a hard stop on PHP 8.2/8.3 without patches.
  3. Where to look, in order:
    • DependencyInjection/ + Resources/config/services.* — reveals the credential keys (account ID, terminal ID, customer/signature ID, environment) and which endpoint URLs are baked in.
    • The gateway/client class that assembles requests — this is the real artifact. It tells you which Saferpay API generation is targeted (legacy Saferpay "Interface"/HTML redirect vs. the modern JSON API).
    • Any response model / status enum classes — cheap, useful DTO material.
    • Tests, if any. Absence of a test suite means the request shapes are undocumented; you are reverse-engineering them.
  4. First real use case: stand up a throwaway script (Symfony skeleton app or even plain PHP calling the client class directly) pointed at the Saferpay sandbox, and exercise Initialize → authorize → capture with a test card. Your output is a written catalogue of request/response JSON — that catalogue, not the code, is what you carry into Laravel.
  5. Decision gate before you write app code: if the sandbox calls fail against current endpoints, or the flow has no 3DS2/SCA challenge path, stop. Go to Saferpay/Worldline's official JSON API docs and write a thin client. Most projects end here, and that is the correct outcome.

Implementation Patterns

Extract, don't bridge. Bootstrapping Symfony's DI container alongside Laravel's to reuse ~a dozen request builders is a bad trade. Lift the payload shapes into app-owned DTOs and reimplement the transport with Illuminate\Support\Facades\Http. Define your own SaferpayGateway implementing an application-owned contract:

interface PaymentGateway {
    public function authorize(AuthorizeRequest $r): PaymentResult;
    public function capture(string $transactionId, int $minorAmount): PaymentResult;
    public function refund(string $transactionId, int $minorAmount): PaymentResult;
    public function status(string $transactionId): PaymentStatus;
    public function tokenize(TokenizeRequest $r): StoredInstrument;
}

Everything downstream depends on the interface, never on Saferpay types — that is what makes the next provider swap bounded.

Config goes in Laravel config, not the bundle's. config/services.php → saferpay.customer_id, terminal_id, username, password, base_url, all from env(). No committed credentials, no parameters.yml-style files.

Strangler migration when replacing an existing integration:

  1. Introduce the PaymentGateway contract and point current call sites at it.
  2. Wrap whatever is live today in an adapter so behavior is frozen and testable.
  3. Implement Saferpay behind the same contract, validated against sandbox.
  4. Cut over per payment method behind a feature flag with per-merchant/per-cohort routing — card first, tokenized/subscription flows last.
  5. Keep the old path warm for one full billing cycle before deleting it.

Never trust the redirect alone. Two paths into the same state machine:

  • Browser returns to /checkout/return → dispatch a queued ConfirmSaferpayPayment job.
  • Provider notification (if supported) → verify, dedupe, dispatch the same job. The job calls Saferpay's transaction/status endpoint out-of-band and only then marks the order paid. Callback-only state machines silently diverge.

Idempotency by construction. Generate your own order_reference per attempt, put a unique index on it, and reuse it on retry. Guard capture/refund with a state-transition check (authorized → captured only) so a double-submitted form or a queue retry cannot double-charge or double-refund.

Amounts are integer minor units, everywhere. Currency + int cents through DTOs, database, and API payload. A float anywhere in the amount path is a defect.

Queue the slow parts. No synchronous Saferpay calls in the request cycle beyond the initial Initialize. Status polling, notification processing, and reconciliation run as jobs with backoff and a circuit breaker around the provider.

Scheduled reconciliation command. Nightly php artisan saferpay:reconcile --since=yesterday comparing your transactions table against Saferpay's transaction API, keyed by transactionId/orderReference, diffed against finance settlement reports. This is the control that catches lost callbacks and rounding mismatches.

Testing from recorded fixtures. Take the sandbox request/response pairs from your spike and commit them as JSON fixtures; drive Http::fake([...]) with them so contract tests cover every lifecycle state (authorized, captured, failed, expired, refunded, partially refunded) without hitting the network.

Gotchas and Tips

  • It is not a Laravel package. No service provider, no facade, no config/ publish. Any guide implying composer require + php artisan is wrong.
  • Archived means zero upstream fixes. No CVE response, no PHP 8.3 patch, no API-version bump. Any defect becomes permanently yours — record that in the ADR so future maintainers see the cost.
  • API generation is the make-or-break question. If it targets the legacy Saferpay Interface/HTML redirect rather than the JSON API, hard-coded endpoint URLs may already be sunset; failures present as 4xx/410 and a sudden total payment outage.
  • 3DS2/SCA is very likely absent. A package of this vintage typically has no Authentication challenge flow. That passes in sandbox and fails on live EU/EEA card traffic — test a challenge-required card, not just a frictionless one.
  • Callbacks are probably unverified. Audit for signature/IP-allowlist checks and constant-time comparisons. Absent that, an attacker POSTs a forged "success": always re-confirm status out-of-band before fulfillment.
  • Credentials in committed config and verbose exception logs are the classic failure mode here. Enforce secret storage, and redact password/customer_id before logging any request or response — you will need those structured logs during disputes.
  • Watch for global state. Static credentials or superglobal reads break under Octane and long-running workers; if you copy code, move state into injected config.
  • Container bridging is a trap. Laravel already ships select Symfony components, so reusing a PSR-18/Guzzle transport or a DTO shape is fine — pulling in the bundle's DI wiring is not.
  • Pin and verify: Guzzle 7, PSR-18 client discovery, no mcrypt/each()/create_function, timezone handling on expiry timestamps.
  • Licensing hygiene: no LICENSE file means no reuse — read it before lifting code, and check transitive deps aren't themselves abandoned.
  • Extension points are effectively nil. There is no maintained plugin surface; the only extensible seam worth designing is your own PaymentGateway contract and a SaferpayClient behind it. Budget ~10–15% of one engineer in steady state for owning that fork, plus a re-review whenever Worldline announces an API deprecation.
  • On-call readiness: an engineer must be able to read a redacted log of every Saferpay request/response, and finance must have a reconciliation report keyed by transactionId/orderReference. Without both, disputes become archaeology.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle