3.5 KiB
3.5 KiB
Handle Payment Webhooks
How to handle payment status updates via webhooks from the Mollie API.
The Code
use Mollie\Api\Http\Requests\GetPaymentRequest;
try {
// Retrieve the payment's current state
$payment = $mollie->send(
new GetPaymentRequest(
id: $_POST['id']
)
);
$orderId = $payment->metadata->order_id;
// First handle status changes
if ($payment->status !== $previousPaymentStatus) {
// Update your order administration with the new status
updateOrder($orderId, $payment->status);
// Handle the status change
if ($payment->isPaid()) {
// The payment is paid
// Start the process of delivering the product to the customer
startDeliveryProcess($orderId);
} elseif ($payment->isFailed()) {
// The payment has failed
// Notify the customer
notifyCustomerOfFailure($orderId);
} elseif ($payment->isExpired()) {
// The payment is expired
// Notify the customer
notifyCustomerOfExpiration($orderId);
} elseif ($payment->isCanceled()) {
// The payment is canceled
// Notify the customer
notifyCustomerOfCancellation($orderId);
}
}
// Then handle refunds and chargebacks (these don't change the payment status)
if ($payment->hasRefunds()) {
// The payment has possibly been (partially) refunded
// Note: the payment status remains "paid"
processPotentialRefund($orderId);
}
if ($payment->hasChargebacks()) {
// The payment has possibly been (partially) charged back
// Note: the payment status remains "paid"
processPotentialChargeback($orderId);
}
// Always return 200 OK to Mollie
http_response_code(200);
} catch (\Mollie\Api\Exceptions\ApiException $e) {
// Handle the error
logError($e->getMessage());
http_response_code(500);
}
The Response
$payment->id; // "tr_7UhSN1zuXS"
$payment->status; // "paid"
$payment->amount->currency; // "EUR"
$payment->amount->value; // "10.00"
$payment->description; // "Order #1234"
$payment->metadata; // Object containing order_id
$payment->createdAt; // "2024-02-24T12:13:14+00:00"
$payment->paidAt; // "2024-02-24T12:15:00+00:00"
Additional Notes
- Handle webhooks in the correct order:
- First check for payment status changes
- Then handle refunds and chargebacks (these don't change the payment status).
- When completing a payment, the webhook may be called after the customer has already been redirected to the payment's
redirectUrl. - A payment can have multiple partial refunds and multiple partial chargebacks.
- Always respond with a 200 OK status code, even when the payment status is not successful
- Process the webhook quickly (within 2 seconds) to avoid timeouts
- Use the payment status helper methods (
$payment->isPaid(),$payment->isFailed(), etc.) for reliable status checks - Store the payment status in your database to track the order status
- The webhook may be called multiple times for the same payment as Mollie will retry the webhook call.
- Webhooks are sent asynchronously, so there might be a delay
- Test your webhook implementation thoroughly with different payment scenarios, including:
- Status changes (paid, failed, expired, etc.)
- Refunds (full and partial)
- Chargebacks