Integration guides
Handle payment results
A payment result arrives after the API call that starts it. Use webhook events to act on results, and use the API to confirm the current state.
On this page
Why results arrive later#
A successful API response means that Merxian accepted the request. It does not mean that money moved. The buyer, the payment method, and the bank decide the result, and that takes time. Merxian sends the result to your webhook endpoint as an event. See Asynchronous results.
Map events to actions#
| Event | What happened | What you should do |
|---|---|---|
payment.processing |
The payment is in progress. | Show the purchase as pending. Do not fulfil. |
payment.succeeded |
The payment was authorized and captured. Capture is automatic. | Fulfil, or wait for transaction.completed if a transaction can have more than one payment. |
transaction.completed |
Payments collected the full amount of the transaction. | Fulfil, if you did not fulfil on payment.succeeded. |
payment.failed |
The payment was refused or could not complete. | Let the buyer try again. |
payment.canceled |
You or an ended session canceled the payment. | Stop waiting for this payment. |
payment.expired |
The payer did not complete the payment in time. | Stop waiting. Offer a new checkout session. |
checkout.expired |
The checkout session ended without a payment. | Release reservations. |
Which success event to use#
Three events report success at different levels:
checkout.completedreports that the buyer finished the hosted page. Use it for the buyer interface.payment.succeededreports that one payment collected its amount.transaction.completedreports that the transaction is fully paid.
On hosted checkout, one payment pays the whole transaction, so payment.succeeded and transaction.completed mean the same money. Choose one of them as your fulfilment signal, and use it everywhere. Do not fulfil on checkout.completed alone.
Failed payments#
On hosted checkout, a failed payment returns the session to open. The buyer stays on the page and can try again until the session expires. You do not need to call the API.
For a payment that you created with POST/v1/payments, you can call POST/v1/payments/{paymentId}/retry. It works on a failed payment when the failure allows a retry. The payment keeps its ID and gets a new paymentAttemptId. A payment has at most five attempts.
failure.code in the event is always payment_failed in this version. Do not branch on failure.message. You can show the message to the buyer.
What to show the buyer#
| State that your server knows | Show the buyer |
|---|---|
No event yet after the return to successUrl |
“Your payment is being processed.” Check again after a short wait. |
payment.succeeded or transaction.completed received |
A confirmation. |
payment.failed received and the session is still open |
A link back to the hosted page. |
checkout.expired received |
A way to start a new checkout. |
Confirm the state with the API#
Read the current state when an event is late, or before an action that you cannot undo:
- GET
/v1/transactions/{transactionId}:statusiscompletedwhen the transaction is paid.paymentStatusshows the progress, for examplepaidorpartially_refunded. - GET
/v1/transactions/{transactionId}/payments: every payment of the transaction, with itsstatus. - GET
/v1/checkout-sessions/{sessionId}:statusandpaymentStatusof the session.
The payment states are in Payments.