axelvnk/sylius-mollie-payum-bundle
Install the Bundle Add the package via Composer:
composer require axelvnk/sylius-mollie-payum-bundle
Register the bundle in AppKernel.php:
new Axelvnk\SyliusMolliePayumBundle\SyliusMolliePayumBundle(),
Configure Mollie API Key
Add your Mollie API key to config/parameters.yml:
parameters:
axelvnk.payum.mollie_api_key: "test_xxxxxxxxxxxxxxxxxxxxxxxxx"
Import the bundle's config:
imports:
- { resource: "@SyliusMolliePayumBundle/Resources/config/config.yml" }
Set Up Database Entry
Insert a gateway config into sylius_gateway_config:
INSERT INTO `sylius_gateway_config` (`config`, `gateway_name`, `factory_name`)
VALUES ('a:1:{s:6:"apiKey";s:35:"test_xxxxxxxxxxxxxxxxxxxxxxxxx";}', 'mollie', 'axelvnk_mollie');
Test in Sylius Admin
Checkout Flow
notificationUrl callback.Webhook Handling (Critical) Mollie sends asynchronous notifications for payment status changes. Configure a route to handle these:
# app/config/routing.yml
sylius_mollie_payum_notification:
path: /mollie-notification
defaults: { _controller: axelvnk_sylius_mollie_payum.controller.notification:handle }
Ensure your NotifyAction (customizable via parameters.yml) processes these updates.
Customizing Payment States
Override default actions (e.g., CaptureAction, ResolveNextRouteAction) to handle edge cases:
parameters:
axelvnk.payum.action.capture.class: App\Action\CustomCaptureAction
Example: Prevent cart deletion on failed payments by setting STATE_PAYMENT_SELECTED instead of STATE_COMPLETED.
Testing Use Mollie’s test API keys and simulate:
// In NotifyAction
$this->logger->debug('Mollie notification', ['payload' => $payload]);
idempotencyKey in your CaptureAction to avoid duplicate processing.NotifyAction to handle subscription events.Cart State on Failed Payments
new. Override ResolveNextRouteAction to set STATE_CART and STATE_PAYMENT_SELECTED to retain the cart:
$order->setState(OrderInterface::STATE_CART);
$order->setCheckoutState(OrderCheckoutStates::STATE_PAYMENT_SELECTED);
Webhook Verification
NotifyAction validates the signature:
if (!$this->mollieClient->verifyWebhook($payload, $signature)) {
throw new \RuntimeException('Invalid Mollie webhook signature');
}
Database Config Quirk
factory_name in sylius_gateway_config is unused but required. Use 'axelvnk_mollie' as shown in the README.Payum Token Expiry
notificationUrl is reachable within this window.Mollie API Rate Limits
Mollie\Api\Client to bypass rate limits:
$client = $this->createMock(Mollie\Api\Client::class);
$client->method('request')->willReturn($mockResponse);
Enable Payum Debugging
Add to config/packages/payum.yaml:
payum:
storage:
payum:
class: Payum\Core\Storage\FilesystemStorage
options:
directory: "%kernel.project_dir%/var/payum"
Check var/payum for stored tokens and payment details.
Log Mollie API Calls Use a Mollie API client wrapper with logging:
$client = new Mollie\Api\Client();
$client->setLogger(new Monolog\Logger('mollie'));
Test Webhooks Locally
Use ngrok to expose your local notificationUrl to Mollie’s test environment:
ngrok http 8000 # Forward to your Symfony dev server
Configure Mollie’s test notificationUrl to point to https://<your-ngrok-subdomain>.ngrok.io/mollie-notification.
Custom Actions
Override Payum actions (e.g., CaptureAction, NotifyAction) to:
Mollie Features
sepadirectdebit payment methods.CaptureAction to handle 3D Secure flows.NotifyAction.Sylius Events Listen to Sylius events to sync Mollie data:
// src/EventListener/MollieSyncListener.php
class MollieSyncListener
{
public function onOrderPaymentCompleted(OrderPaymentCompletedEvent $event)
{
$payment = $event->getPayment();
if ($payment->getGatewayName() === 'mollie') {
// Sync Mollie data (e.g., update order with Mollie ID)
}
}
}
Register the listener in services.yaml:
services:
App\EventListener\MollieSyncListener:
tags:
- { name: kernel.event_listener, event: sylius.order.payment.completed }
Testing with PHPUnit Mock the Mollie client in tests:
$client = $this->createMock(Mollie\Api\Client::class);
$payment = new Payment();
$payment->setGatewayName('mollie');
$this->payum->getTokenFactory()->createCaptureToken(
'mollie',
$payment,
$client
);
How can I help you explore Laravel packages today?