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

Symfony Ideal Laravel Package

lensmedia/symfony-ideal

Symfony bundle from Lensmedia for integrating iDEAL payments into your application, with configurable payment flows, simple service setup, and a developer-friendly API for initiating and handling transactions securely. It helps add online payment support to Symfony projects with minimal configuratio...

View on GitHub
Deep Wiki
Context7

Getting Started

  • Start by reading the source, not by installing. This is a Symfony bundle (symfony/framework-bundle, DI container, config tree, bundle autoregistration). Laravel does not ship framework-bundle, and its pinned Symfony components (http-foundation, console, process, routing) will typically conflict with the bundle's transitive requirements. Run composer why-not lensmedia/symfony-ideal in a throwaway branch before you commit to any integration design — expect a hard conflict.
  • What to look at first, in order:
    1. The payment service/client class in src/ — is the iDEAL logic separable from the container glue, or is it entangled with AbstractController / container-aware services?
    2. Resources/config/services.* — the real service IDs and dependencies.
    3. Any routing file / return controller — this is the part you must audit before trusting it.
    4. The extension/Configuration class — the actual config keys (acquirer URL, merchant ID, sub-ID, certificate paths, test mode, return URL). README/config docs are secondary; for a package with 0 stars and one release, src/ is authoritative.
  • If you are on Symfony: composer require lensmedia/symfony-ideal, register the bundle if Flex doesn't, create config/packages/<alias>.yaml with credentials from .env/secrets (never committed), then verify wiring with debug:container | grep -i ideal, debug:router | grep -i ideal, and config:dump-reference <alias>.
  • If you are on Laravel (the realistic case): do not composer require. Vendor the underlying payment client into app/Domain/Payments/Providers/Ideal, strip DI/controller coupling, and replace the Symfony HTTP client with Laravel's Http facade or Guzzle. Wrap it behind a first-party PaymentGateway interface (createPayment / getStatus / refund / handleCallback).
  • First use case (the one thing to prove end-to-end in sandbox): a checkout action that creates a transaction for an order, persists a local record, and redirects the customer to the issuer — followed by a return/callback action that re-queries status server-side and marks the order paid. Get that loop green in sandbox before touching production credentials.

Implementation Patterns

  • Local record first, always. Create your own payments row (order id, amount in cents, currency, description, status, provider transaction id, created/updated timestamps) before calling the provider. You need it for reconciliation and for the case where a callback arrives before your redirect response has rendered.
  • Redirect flow:
    $payment = Payment::create([...]);           // local record, status=pending
    $txn = $gateway->createPayment($payment);    // returns issuer redirect URL + txn id
    $payment->update(['provider_txn_id' => $txn->id]);
    return redirect()->away($txn->redirectUrl);
    
  • Return/callback flow — never trust the redirect. The customer returning to your return URL is not proof of payment. Take the transaction id from your own DB (or the signed query param), call getStatus() server-side, and only then transition pending → paid. Verify any signature/checksum the provider sends; treat the browser redirect as a trigger to check, not as authority.
  • Wrap it behind a domain interface. Define PaymentGateway with DTOs at the boundary; nothing from this package should leak into controllers or models. This is what makes the inevitable swap to Mollie/Stripe/Adyen a config change rather than a rewrite, and it's the only sane way to adopt a zero-signal package.
  • Idempotency on create. Put a unique constraint on your local transaction reference and generate an idempotency key per checkout attempt. Client retries or double form-submits must not produce two transactions.
  • Status reconciliation job. A scheduled command that sweeps pending payments older than N minutes and re-queries status handles the "user paid but callback never arrived" case. Never rely on the return redirect alone.
  • Events → queues. The bundle dispatches events on status changes in Symfony; in the extracted Laravel version, dispatch your own PaymentPaid/PaymentFailed events and handle order fulfilment in queued listeners, not in the callback controller.
  • Test with a fake provider. Implement the same PaymentGateway interface with a fake/fixture provider for feature tests, so the redirect/return/status loop is covered without hitting sandbox.
  • Config-driven provider selector. Read the provider from config so sandbox/production and future PSP swaps are config changes.
  • Amounts in integer cents, EUR only. iDEAL is EUR-only; don't build multi-currency assumptions into the DTO.

Gotchas and Tips

  • The 2.0.5 fix is a warning sign. The only listed release note is "Error in old/new status conversion tables." Status mapping bugs are exactly the kind that silently mark paid orders as failed (or vice versa). Re-derive the status state machine yourself (open/pending/paid/expired/cancelled) from the provider docs and assert it in tests — don't trust the bundled table.
  • framework-bundle is unbootable in Laravel. No amount of version alignment fixes a missing bundle. Extraction, not installation, is the only path on Laravel.
  • Zero stars / zero dependents means assume it is unaudited. Read (and ideally rewrite) the signature/callback-verification code. Payments code handles request signing, certificate storage, amount tampering, and replay — none of which you should trust to a single-release package.
  • iDEAL is mid-migration (EPI/Worldline, "iDEAL 2.0"). A package last released January 2024 may wrap exactly the classic Acquirer/Hub interfaces being retired. Confirm which API it actually talks to before building anything. Scheme retirement will break your integration with no code change on your side — subscribe to PSP/scheme bulletins, not the library's changelog.
  • Certificate rotation is an outage waiting to happen. Merchant certs expire. Add a monitoring check for cert expiry and clock skew; a silent 500 on every payment is the failure mode.
  • Do not poll synchronously in the web request. Callback handling should be quick (persist intent, queue the work). Status polling belongs in a queued job or scheduled sweeper.
  • Amount/currency tampering: always trust the PSP status response, not the form POST. Re-read the amount from your own DB when verifying.
  • Abandonment risk is real. Budget a named owner, a private fork in your registry, and a quarterly review. If upstream disappears, that's an ops event — plan so it isn't an incident.
  • Debugging checklist when the flow stalls: check debug:router/route registration (Symfony) or your own route (Laravel); dump the provider request/response at the HTTP client boundary; verify return URL is fully qualified and matches what's registered; confirm the sandbox/test toggle is actually being read from config; check the status conversion table if a status looks wrong.
  • Extension points to lean on: the status-change events (hook fulfilment, notifications, audit log), the config tree (feature flag / provider selector / test mode), and the return controller (replace it entirely with your own so verification logic is yours).
  • License: confirm it before vendoring/extracting. With no README license section visible, check the repo's LICENSE file — a private-sounding "private bundle" description may mean it was never intended for external use.
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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource