This guide explains how to integrate Mollie payment gateway with the Laravel Payments package.
Mollie is a leading European payment gateway supporting multiple payment methods across 35+ countries. It offers:
composer require mollie/laravel-mollie
php artisan vendor:publish --tag=mollie-config
php artisan vendor:publish --tag=mollie-migrations
Add your Mollie credentials to your .env file:
MOLLIE_KEY=your_mollie_api_key_here
MOLLIE_REDIRECT_URL=https://yoursite.com/payment/success
MOLLIE_WEBHOOK_URL=https://yoursite.com/mollie/webhook
You can obtain these credentials from your Mollie dashboard.
Mollie provides different types of API keys:
Add the appropriate key to your .env:
# For test mode
MOLLIE_KEY=test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# For production
MOLLIE_KEY=live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
use Mdiqbal\LaravelPayments\Facades\Payment;
$paymentRequest = [
'amount' => 100.00,
'currency' => 'EUR',
'email' => 'customer@example.com',
'transaction_id' => 'TXN' . time(),
'redirect_url' => 'https://yoursite.com/payment/callback',
'payment_options' => ['ideal', 'creditcard', 'paypal'],
'customer' => [
'name' => 'John Doe',
'email' => 'customer@example.com',
'phone' => '+31201234567',
'address' => '123 Main St',
'city' => 'Amsterdam',
'country' => 'NL',
'postal_code' => '1012JS'
],
'metadata' => [
'order_id' => 'ORD123456',
'user_id' => 789
]
];
$payment = Payment::gateway('mollie')->pay($paymentRequest);
$verification = Payment::gateway('mollie')->verify($transactionId);
if ($verification['success']) {
$status = $verification['status'];
$amount = $verification['amount'];
if ($status === 'paid') {
// Payment was successful
}
}
$refundData = [
'payment_id' => 'tr_xxxxxxxxxxxxxxxx',
'amount' => 50.00,
'currency' => 'EUR',
'reason' => 'Customer requested refund'
];
$refund = Payment::gateway('mollie')->refund($refundData);
$customerData = [
'name' => 'John Doe',
'email' => 'customer@example.com',
'locale' => 'nl_NL',
'metadata' => [
'user_id' => 789,
'source' => 'website'
]
];
$customer = Payment::gateway('mollie')->createCustomer($customerData);
$subscriptionData = [
'customer_id' => 'cst_xxxxxxxxxxxxxxxx',
'amount' => 25.00,
'currency' => 'EUR',
'interval' => '1 month',
'description' => 'Monthly subscription',
'start_date' => '2024-02-01',
'times' => 12,
'mandate_id' => 'mdt_xxxxxxxxxxxxxxxx',
'metadata' => [
'plan_id' => 'basic'
]
];
$subscription = Payment::gateway('mollie')->createSubscription($subscriptionData);
$linkData = [
'amount' => 100.00,
'currency' => 'EUR',
'description' => 'Payment for invoice #123',
'redirect_url' => 'https://yoursite.com/success',
'payment_options' => ['ideal', 'bancontact', 'creditcard'],
'metadata' => [
'invoice_id' => 'INV123456'
]
];
$paymentLink = Payment::gateway('mollie')->createPaymentLink($linkData);
$methodsParams = [
'amount' => 100.00,
'currency' => 'EUR',
'locale' => 'nl_NL',
'billing_country' => 'NL'
];
$availableMethods = Payment::gateway('mollie')->getAvailablePaymentMethods($methodsParams);
$mandateData = [
'method' => 'directdebit',
'consumer_account' => 'NL91ABNA0417164300',
'consumer_name' => 'John Doe',
'mandate_reference' => 'MANDATE_' . time(),
'signature_date' => '2024-01-01'
];
$mandate = Payment::gateway('mollie')->createMandate($customerId, $mandateData);
$mandates = Payment::gateway('mollie')->getCustomerMandates($customerId);
Set up your webhook endpoint in the Mollie dashboard
Create a route to handle webhooks:
// routes/web.php
Route::post('/mollie/webhook', [MollieWebhookController::class, 'handleWebhook']);
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Mdiqbal\LaravelPayments\Facades\Payment;
class MollieWebhookController extends Controller
{
public function handleWebhook(Request $request)
{
// Mollie webhooks don't contain the full payload, only the payment ID
$paymentId = $request->input('id');
if (!$paymentId) {
return response()->json(['error' => 'Missing payment ID'], 400);
}
// Get full payment details
$molliePayment = Mollie::api()->payments->get($paymentId, [
'embed' => ['refunds', 'chargebacks']
]);
// Process using our gateway
$result = Payment::gateway('mollie')->processWebhook(['id' => $paymentId]);
if ($result['success']) {
$eventType = $result['event_type'];
$transactionId = $result['transaction_id'];
switch ($eventType) {
case 'payment.paid':
$this->handlePaidPayment($result);
break;
case 'payment.authorized':
$this->handleAuthorizedPayment($result);
break;
case 'payment.failed':
$this->handleFailedPayment($result);
break;
case 'payment.expired':
$this->handleExpiredPayment($result);
break;
case 'payment.canceled':
$this->handleCanceledPayment($result);
break;
}
}
return response()->json(['status' => 'ok']);
}
protected function handlePaidPayment($data)
{
// Update order status, send confirmation email, etc.
$transactionId = $data['transaction_id'];
$amount = $data['amount'];
$currency = $data['currency'];
$paymentMethod = $data['payment_method'];
$refunds = $data['refunds'];
}
protected function handleFailedPayment($data)
{
// Log failed payment, notify user, etc.
}
protected function handleExpiredPayment($data)
{
// Handle expired payment
}
protected function handleCanceledPayment($data)
{
// Handle canceled payment
}
protected function handleAuthorizedPayment($data)
{
// Handle authorized payment (first charge)
}
}
Mollie supports a wide range of payment methods:
You can specify which payment methods to display:
$paymentRequest = [
'amount' => 100.00,
'currency' => 'EUR',
'email' => 'customer@example.com',
'transaction_id' => 'TXN' . time(),
'payment_options' => [
'ideal',
'creditcard',
'bancontact'
],
// ... other parameters
];
$country = request()->input('country', 'NL');
$amount = 100.00;
// Get available methods for specific country and amount
$methods = Payment::gateway('mollie')->getAvailablePaymentMethods([
'amount' => $amount,
'currency' => 'EUR',
'billing_country' => $country,
'locale' => 'en_US'
]);
// Use the first 3 available methods
$paymentMethods = array_slice(array_column($methods['methods'], 'id'), 0, 3);
// Monthly
'interval' => '1 month'
// Every 3 months
'interval' => '3 months'
// Yearly
'interval' => '12 months'
// Weekly
'interval' => '1 week'
// Daily
'interval' => '1 day'
// Create a mandate for SEPA Direct Debit
$mandateData = [
'method' => 'directdebit',
'consumer_account' => 'NL91ABNA0417164300',
'consumer_name' => 'John Doe',
'signatureDate' => '2024-01-15'
];
$mandate = Payment::gateway('mollie')->createMandate($customerId, $mandateData);
// Use the mandate for subscription
$subscriptionData = [
'customer_id' => $customerId,
'amount' => 25.00,
'currency' => 'EUR',
'interval' => '1 month',
'mandate_id' => $mandate['mandate_id'],
// ... other parameters
];
The Mollie gateway provides detailed error messages:
$payment = Payment::gateway('mollie')->pay($paymentRequest);
if (!$payment['success']) {
$error = $payment['error'];
$message = $error['message'];
$code = $error['code'];
// Handle error based on type
if ($code === 'PAYMENT_FAILED') {
// Payment initialization failed
}
}
PAYMENT_FAILED - Payment initialization failedVERIFICATION_FAILED - Transaction verification failedREFUND_FAILED - Refund processing failedSUBSCRIPTION_FAILED - Subscription creation failedCUSTOMER_FAILED - Customer creation failedMANDATE_FAILED - Mandate creation failedWEBHOOK_FAILED - Webhook processing failedMollie provides a comprehensive test environment. Use test API keys:
MOLLIE_KEY=test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Use these test payment methods in test mode:
Test Cards:
Test Bank Accounts for SEPA:
Test iDEAL Banks:
Mollie supports the following currencies:
Mollie supports payments in the following countries:
Mollie implements rate limits:
Implement proper rate limiting in your application to avoid being blocked.
pay() - Initialize a paymentverify() - Verify a transactionrefund() - Process a refundgetTransactionStatus() - Get transaction statuscreateCustomer() - Create a customercreateSubscription() - Create a subscriptioncancelSubscription() - Cancel a subscriptioncreateMandate() - Create a mandate for recurring paymentsgetCustomerMandates() - Get customer mandatescreatePaymentLink() - Create a payment linkgetAvailablePaymentMethods() - Get available payment methodsgetSupportedCurrencies() - Get supported currenciesgetGatewayConfig() - Get gateway configurationIf you have multiple profiles in Mollie:
// In config/services.php
'mollie' => [
'key' => env('MOLLIE_KEY'),
'profile_id' => env('MOLLIE_PROFILE_ID'), // Optional
],
// Create custom webhook model
class MollieWebhook extends \Mollie\Laravel\Models\WebhookCall
{
// Add custom methods or relationships
}
// In config/mollie.php
'models' => [
'webhook_call' => \App\Models\MollieWebhook::class,
],
// In your payment success controller
public function paymentSuccess(Request $request)
{
$molliePaymentId = request()->get('id');
if (!$molliePaymentId) {
return redirect('/payment/failed');
}
$verification = Payment::gateway('mollie')->verify($molliePaymentId);
if ($verification['success'] && $verification['status'] === 'paid') {
// Update order
$order = Order::where('transaction_id', $verification['transaction_id'])->first();
$order->status = 'paid';
$order->payment_method = $verification['payment_method'];
$order->paid_at = now();
$order->save();
return redirect('/payment/success')->with('order', $order);
}
return redirect('/payment/failed');
}
// Set locale based on user preference
$paymentRequest = [
'amount' => 100.00,
'currency' => 'EUR',
'email' => $customer->email,
'locale' => app()->getLocale(), // e.g., 'nl_NL', 'de_DE', 'fr_FR'
// ... other parameters
];
For Mollie-specific support:
For Laravel Payments package support:
How can I help you explore Laravel packages today?