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

Payment Mollie Bundle Laravel Package

ruudk/payment-mollie-bundle

A Symfony bundle that adds a Mollie payment gateway to the ruudk/payment component, letting you create and handle Mollie payments and webhooks through a clean service-based API with minimal configuration.

View on GitHub
Deep Wiki
Context7

Getting Started

What you're actually installing. This bundle is a thin adapter between JMSPaymentCoreBundle and the Mollie API. It ships a JMS payment plugin (tagged payment.plugin), a small return/notify controller, and DI config. You will spend most of your day in JMSPaymentCore's PaymentInstruction lifecycle, not in this bundle.

Minimal setup

  1. Require it alongside JMS Payment Core (the bundle does not install it for you):
    composer require ruudk/payment-mollie-bundle
    
    Be aware: the package is archived (last tag 2019), so Composer will pull old Symfony/Doctrine/Mollie-client constraints. Pin versions and expect conflicts on modern stacks.
  2. Enable both bundles in AppKernel:
    new JMS\Payment\CoreBundle\JMSPaymentCoreBundle(),
    new Ruudk\Payment\MollieBundle\RuudkPaymentMollieBundle(),
    
  3. Configure a Mollie API key (test_... for dev, live_... for prod) under ruudk_payment_mollie.api_key. Confirm the exact key name in DependencyInjection/Configuration.php — this is the first file to read.
  4. Import JMSPaymentCore's routing plus this bundle's routing so the return/notify endpoints exist.
  5. Configure JMSPaymentCore itself (entity classes, Doctrine mapping, any payment.plugin_controller options) — see its docs; this bundle assumes it's already working.

Where to look first

  • DependencyInjection/Configuration.php — the only real config surface.
  • Plugin/*Plugin.php — read getName() to get the exact payment-system string your PaymentInstruction must use (likely mollie_ideal; verify, don't guess), and see exactly which Mollie API calls are made.
  • Resources/config/services.xml / routing.yml — service IDs, tags, route names.
  • JMSPaymentCore's PaymentPluginController and OffsitePluginInterface — the contract this bundle implements.

First use case: a one-off iDEAL payment. Create a PaymentInstruction (amount, EUR, the plugin's payment-system name), persist/flush it, then call payment.plugin_controller->approve($instruction, $amount). If $result->getResult() === Result::STATUS_SUCCESS, return the redirect from $result->getResponse() to send the user to Mollie. When Mollie redirects back, the bundle's controller calls complete() on the plugin controller; from there you inspect the instruction/payment state and fulfil the order. That start → approve → redirect → return → complete loop is the entire happy path.

Implementation Patterns

Keep order state separate from payment state. Your Order entity should have its own status (pending, paid, failed, refunded). JMSPaymentCore tracks ApprovedAmount, DepositedAmount, and ReversingAmount on the instruction — use those for reconciliation, but never derive "the customer has paid" from ApprovedAmount alone. Only flip the order to paid after complete() plus a server-side status check against Mollie.

Two controllers, one flow. A start action (creates instruction, calls approve, redirects) and a return action (looks up the instruction by ID from session or a signed query param, calls complete(), verifies amount+currency match the order, then fulfils). Put the return URL behind your own route so you control error handling; the bundle's own controller is a convenience, not a policy.

Guard the return. Treat the browser redirect as a hint, not proof. In return, re-fetch the payment from Mollie (or rely on complete() doing so) and compare amount, currency, and the Mollie payment ID you stored at approve() time. If it doesn't match, mark the instruction failed and log.

Use the Result object properly. approve()/complete() return a Result; check getResult() against the STATUS_* constants and branch on getResponse() (offsite redirect) vs getPayment(). Don't assume STATUS_SUCCESS means "done" — for offsite plugins it often means "redirect the user".

Testing strategy. Because the plugin is small, stub the Mollie client or replace the plugin service (keep the payment.plugin tag) with a fake. Assert transitions: instruction created → approved → completed → deposited, and the failure path when Mollie returns failed/canceled/expired. Most of your test budget belongs to the order state machine, not to Mollie.

Refunds and reconciliation. If the plugin supports reverseDeposit, wire an admin action that calls it and records the reversing amount. Otherwise treat refunds as manual and log the Mollie payment ID so ops can act in the Mollie dashboard. A nightly job that reconciles pending instructions older than N minutes against Mollie is cheap insurance.

Modernizing path. If you inherit this, put your own PaymentGateway interface in front of it. Then you can replace the internals with mollie/mollie-api-php v2 + a hand-written JMS plugin (or drop JMS entirely for new code) without touching controllers.

Gotchas and Tips

  • Archived and abandoned. Last release 2019, 0 dependents, and JMSPaymentCoreBundle itself is unmaintained. No security patches, no PHP 8.x/Symfony 5+ support without forking. Fine as a historical reference or for maintaining a legacy app; wrong choice for anything new.
  • Old Mollie API. The bundle pins the API-key-era Mollie PHP client (v1). Mollie's v1 API and that client are retired; Orders, Customers, Subscriptions, Payment Links, and universal webhooks are unavailable. Budget for either a fork of the plugin or a full replacement.
  • Return-based completion is fragile. Users close tabs, redirects get lost, and 3DS/bank-transfer flows don't complete synchronously. iDEAL is the least-bad case. For anything else you need webhooks — which this bundle's flow doesn't really model — so add a reconciliation cron that calls complete()/re-checks pending instructions.
  • Payment-system name must match exactly. new PaymentInstruction($amount, 'EUR', $name) with a typo or the wrong plugin name produces a "no plugin found" error far from the cause. Copy the string from the plugin's getName().
  • Currency and precision. iDEAL is EUR-only, and JMS expects decimal strings. Don't pass floats or rely on implicit casting; use bcmath or a money library and assert currency at both ends of the flow.
  • URL generation behind proxies. Return URLs are built from the router request context. Behind a load balancer or in CLI-triggered flows you'll get http:// or the wrong host — set router.request_context parameters or configure trusted proxies, or Mollie will redirect users to the wrong place.
  • Service IDs are internal. If you decorate the plugin, keep the payment.plugin tag; read services.xml before overriding anything. The bundle logs almost nothing useful, so log the instruction ID, Mollie payment ID, and Result status yourself — the Mollie dashboard is your other debugging surface.
  • Extension point is the plugin, not the bundle. The cleanest move for API v2 or a new Mollie method is to copy Plugin/*Plugin.php into your app, adapt the API calls, and register it as your own payment.plugin service. Don't monkey-patch the vendor code.
  • Doctrine mapping lives in JMS Payment Core. If you extend PaymentInstruction or Payment, check JMSPaymentCore's entity configuration; this bundle won't tell you.
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.
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect
youbar/easy-crud
c-point-labs/laravel-hostyourai
dbravoan/dbcms-admin-theme-dbcms
dbravoan/dbcms-theme-db-cyber
dbravoan/dbcms-blocks-basic
dbravoan/dbcms-module-content-audit
dbravoan/dbcms-module-ai-assistant
paygate-to/paygate-php
padosoft/askmydocs-connector-base
defstudio/supercharged-carbon
bernskioldmedia/laravel-matomo