mollie/mollie-api-php
Mollie API client for PHP: accept iDEAL, Apple Pay, credit card, SEPA, PayPal, Klarna and more with a clean, well-tested library. Create payments, handle refunds, subscriptions, customers, and webhooks through a simple, intuitive API.
Architecture fit. mollie/mollie-api-php is a framework-agnostic Composer SDK, not a Laravel package — it provides transport, request objects, typed value objects (Money), endpoint collections, and resource hydration, and nothing else. That is actually a good fit: it gives us a stable seam (MollieApiClient::send(Request)) to wrap behind a PaymentGateway contract, keeping SDK types out of domain models and Eloquent entities. The v3 request-object API (CreatePaymentRequest, Money) plus pluggable HTTP adapters means we can swap the transport (e.g., a Laravel-HTTP or Guzzle-backed adapter) and inject a mock adapter in tests without touching business logic.
The important architectural caveat for a TPM: this package owns zero business logic. No state machine, no retry policy, no webhook queue, no reconciliation, no idempotency store. Every one of those is ours to build. Budget accordingly — the SDK is perhaps 10% of the production effort.
Integration feasibility. High. composer require mollie/mollie-api-php, one API key (test_/live_ auto-detected via setToken(), or explicit setApiKey() / setAccessToken()), and roughly 20 lines of service-provider/config wiring. Requirements (PHP ≥ 7.4, cURL ≥ 7.19.4, current OpenSSL) are satisfied by any modern Laravel runtime; we should target PHP 8.2+ regardless of the package floor.
Technical risk. Moderate, concentrated in three areas:
| Risk | Evidence | TPM read |
|---|---|---|
| 3.x API churn / BC-implied breaks | v3.11.0 narrows getResponse() to ?Response and getPendingRequest() to ?PendingRequest; user code chaining ->getResponse()->successful() on webhook-origin resources will NPE |
Real upgrade hazard for webhook handlers. Pin tightly, read changelogs before every minor bump |
| Release hygiene | Changelogs show 3.0.2→3.1.4 in rapid succession plus a stray v1.0.0-test tag in the notes |
Active maintenance, but cadence implies we need an upgrade DRI, not "set and forget" |
| Popularity signal is misleading | 606 stars and "dependents: 0" | Official vendor SDKs are consumed via Composer, not GitHub forks. Validate adoption via Packagist download counts and Laravel ecosystem usage — do not treat these metrics as a maturity verdict |
Secondary risks: it is a client, so API-version drift is Mollie's to manage but ours to absorb; and mollie/laravel-mollie (the Laravel wrapper) must be version-pinned against this package's 3.x line — if the wrapper lags, we hand-roll the provider.
Key questions.
mollie/laravel-mollie wrapper, and which tracks 3.x more reliably?access_ tokens, oauth2-mollie-php) for a marketplace model — a materially larger scope?Stack fit. Laravel 10–12, PHP 8.2+. Bind MollieApiClient as a container singleton configured from config/services.php → env vars; expose a PaymentGateway interface (createPayment, refund, capture, handleWebhook) with a Mollie adapter implementing it. Persist our own payments / refunds / webhook_events tables; treat Mollie resources as DTOs, not models. Keep the API key in a secret manager, never in .env files committed to disk, and never log request bodies (the debugging guide exists precisely because this is easy to get wrong).
Migration path. Strangler pattern behind the gateway contract. If replacing an existing PSP or a legacy Mollie v1 integration: stand up the new adapter in parallel, route by feature flag at the payment-method level, run test mode end-to-end (create → redirect → webhook → refund → reconciliation) before touching live traffic, then migrate one method/country at a time and decommission the old path only after a full settlement cycle has reconciled cleanly.
Compatibility. Pin mollie/mollie-api-php with a caret constraint and a committed lockfile; verify the Laravel wrapper's constraint against it. Audit any existing getResponse() / getPendingRequest() chaining for null-safety before accepting 3.11+. Confirm cURL and a complete CA bundle in every container image (a classic silent failure in slim base images). If using OAuth/Connect, add mollie/oauth2-mollie-php and a token-refresh flow — treat as a separate workstream.
Sequencing.
MockResponse is serializable, so fixtures are cheap).Maintenance. Vendor-maintained and actively released (multiple patches per quarter), BSD-2-Clause — no legal friction, no copyleft review, no commercial license cost. The cost is the upgrade treadmill: because 3.x has shipped BC-implied changes, each minor bump needs a changelog read and a regression pass on webhook handling. Assign a named DRI and a monthly upgrade cadence rather than reacting to advisories.
Support. Two distinct channels and it matters for escalation: Mollie merchant support covers account, onboarding, settlements, and API behavior (with a contractual relationship behind it); the GitHub repo covers SDK bugs only, on a best-effort, no-SLA basis. Do not let anyone believe the OSS repo carries a support commitment. Documentation quality is genuinely above average — dedicated guides for idempotency, webhooks, testing, debugging, HTTP adapters, plus a recipes directory — which materially reduces ramp-up and support load.
Scaling. The client is stateless HTTP, so scale is an application concern: horizontal workers, connection reuse, sane timeouts, and a circuit breaker around PSP calls so a Mollie degradation doesn't exhaust PHP-FPM. Real scaling risks are (a) API rate limits under batch refunds or backfills, (b) webhook bursts arriving faster than synchronous handlers can process, and (c) unbounded retries without idempotency keys creating duplicate charges. Queue all webhooks; always send idempotency keys on create/refund.
Failure modes to design for.
Response — the 3.11+ NPE trap; enforce null-safe access and a lint rule or static analysis gate.setToken() auto-detection is convenient but silent; assert key prefix against APP_ENV at boot and fail fast.Money is minor-unit based; a rounding or locale bug here is a financial incident, not a display bug.Ramp-up. Developer ramp to a working test-mode payment is roughly 1–2 days given the recipes. Production-grade — webhooks, idempotency, reconciliation, observability, runbook — is 1–2 sprints of real work. Before go-live, require: a payment-state dashboard, alerting on webhook failure rate and reconciliation mismatches, an on-call runbook covering "Mollie is down" and "webhooks stopped," and finance sign-off on the ledger mapping. Treat the SDK as a well-supported dependency and the payment flow as a first-class product surface.
How can I help you explore Laravel packages today?