mollie/mollie-api-php
Official Mollie API client for PHP. Create and manage payments, orders, customers, subscriptions, refunds, and settlements. Supports iDEAL, card, PayPal, Apple Pay, Google Pay, Bancontact, SEPA and more. Includes webhooks and OAuth support.
## Getting Started
### Minimal Setup
1. **Installation**:
```bash
composer require mollie/mollie-api-php
config/services.php or directly in code):
$mollie = new \Mollie\Api\MollieApiClient();
$mollie->setApiKey(env('MOLLIE_API_KEY')); // Use `test_` or `live_` prefix
use Mollie\Api\Http\Data\Money;
use Mollie\Api\Http\Requests\CreatePaymentRequest;
$payment = $mollie->send(new CreatePaymentRequest(
description: 'Order #123',
amount: new Money('EUR', '29.99'),
redirectUrl: route('mollie.redirect'),
webhookUrl: route('mollie.webhook')
));
docs/recipes/ (pre-built workflows for payments, subscriptions, etc.)docs/webhooks.md (critical for async operations)// Create a payment (sync)
$payment = $mollie->payments->create([
'amount' => ['currency' => 'EUR', 'value' => '10.00'],
'description' => 'Premium Subscription',
'metadata' => ['user_id' => auth()->id()],
'redirectUrl' => route('checkout.success'),
]);
// Capture a deferred payment (e.g., for credit cards)
$payment->capture();
// Refund a payment
$refund = $payment->refund(['amount' => ['currency' => 'EUR', 'value' => '5.00']]);
// Laravel Route (webhook endpoint)
Route::post('/mollie/webhook', function (Request $request) {
$event = $request->json()->all();
$mollie->webhooks->handle($event); // Auto-verifies signature
// Handle specific events (e.g., payment.completed)
if ($event['type'] === 'payment.completed') {
orderConfirmed($event['data']['id']);
}
});
// Create a subscription
$subscription = $mollie->subscriptions->create([
'amount' => ['currency' => 'EUR', 'value' => '9.99'],
'interval' => 'month',
'metadata' => ['customer_email' => 'user@example.com'],
]);
// Cancel a subscription
$subscription->cancel();
// Create/update a customer
$customer = $mollie->customers->create([
'email' => 'user@example.com',
'name' => 'John Doe',
]);
// Attach a payment to a customer
$payment->setCustomerId($customer->id);
// app/Providers/MollieServiceProvider.php
public function register()
{
$this->app->singleton(\Mollie\Api\MollieApiClient::class, function ($app) {
$mollie = new \Mollie\Api\MollieApiClient();
$mollie->setApiKey(config('services.mollie.key'));
return $mollie;
});
}
// app/Http/Controllers/MollieController.php
use Mollie\Api\Http\Requests\CreatePaymentRequest;
public function createPayment()
{
$request = new CreatePaymentRequest(
description: 'Order #' . $order->id,
amount: new Money('EUR', $order->total),
metadata: ['order_id' => $order->id],
// ... other params
);
return $mollie->payments->create($request);
}
// app/Listeners/HandleMollieWebhook.php
public function handle($event)
{
$data = $event['data'];
switch ($event['type']) {
case 'payment.completed':
Order::find($data['metadata']['order_id'])->markAsPaid();
break;
case 'subscription.cancelled':
User::find($data['metadata']['user_id'])->cancelSubscription();
break;
}
}
// tests/Feature/MolliePaymentTest.php
public function test_payment_creation()
{
$mollie = Mockery::mock(\Mollie\Api\MollieApiClient::class);
$mollie->shouldReceive('payments->create')
->once()
->andReturn(new Payment(['id' => 'tr_abc123']));
$response = $this->post('/checkout', ['amount' => '10.00']);
$response->assertRedirect('/order/confirmed');
}
// Ensure retries don’t duplicate payments
$payment = $mollie->payments->create([
'amount' => ['currency' => 'EUR', 'value' => '10.00'],
'idempotencyKey' => 'unique_order_123', // Must be unique per order
]);
// For custom logging/retries
$mollie->setHttpAdapter(new \Mollie\Api\Http\Adapters\GuzzleAdapter([
'handler' => HandlerStack::create([
new RetryMiddleware(),
new LoggingMiddleware(),
]),
]));
// Refund multiple payments
$refunds = $mollie->payments->refund([
'payments' => ['tr_123', 'tr_456'],
'amount' => ['currency' => 'EUR', 'value' => '5.00'],
]);
Webhook Signature Verification
X-Mollie-Signature header is missing or malformed.$mollie->webhooks->validate($request->header('X-Mollie-Signature'), $request->getContent());
Currency/Amount Formatting
"10,00" (comma) instead of "10.00" (dot) for decimal amounts.new Money('EUR', '10.00')).Redirect URLs
redirectUrl in payment requests causes Mollie to redirect to a default page.redirectUrl and webhookUrl:
'redirectUrl' => route('mollie.redirect', ['payment_id' => $payment->id]),
'webhookUrl' => route('mollie.webhook'),
Idempotency Key Conflicts
idempotencyKey for different payments may silently fail.order_id + timestamp).Payment Method Restrictions
ideal) require additional configuration in the Mollie dashboard.Webhook Retries
if (Webhook::where('event_id', $event['id'])->exists()) {
return response()->json(['status' => 'ok']);
}
Enable Debug Logging
$mollie->setDebugMode(true); // Logs requests/responses to storage/logs/mollie.log
Inspect Raw Responses
$response = $mollie->send($request);
\Log::debug('Mollie Response:', $response->getData());
Test Mode Quirks
test_123 cards for immediate success).Common HTTP Errors
amount, description).How can I help you explore Laravel packages today?