Hosted Checkout
Finomesh hosts the payment page for you — the default, lowest-code way to accept a payment. After creating a payment, redirect your customer to:
https://checkout.finomesh.com/p/{paymentId}
(staging: https://checkout-staging.finomesh.com/p/{paymentId})
Deciding between this and building your own UI? See Checkout Modes.
The checkout:
- shows one offer per crypto asset your gateway accepts — the crypto amount, network fee, commission, and total;
- displays the deposit address and QR code for the asset the customer selects;
- runs the payment countdown (
timeoutSeconds, default 1 hour) and live-updates over a WebSocket when the on-chain deposit is detected and confirmed; - shows the terminal result screen — including the transaction hash linked to the chain explorer — and then redirects the customer back to you.
The page is branded with your gateway's theme (colors, logo, display name) configured in the dashboard.
The callback redirect
When a payment is determined as SUCCESS, ACCEPTABLE, or MISMATCH while the customer is on the checkout, a 10-second countdown runs and the browser is redirected to your callbackUrl with three kinds of query parameters merged in:
| Parameter | Source |
|---|---|
| your own params | The callbackParams object you sent at creation, flattened into the query string |
paymentId | Added by Finomesh — your correlation key and the key for verify |
status | Added by Finomesh — SUCCESS | ACCEPTABLE | MISMATCH — a display hint only |
Example, for callbackParams: { "orderId": "ORD-1042" }:
https://shop.example.com/payment/result?orderId=ORD-1042&paymentId=0d9f3a64-…&status=SUCCESS
Notes:
callbackUrlis required on every payment. It may be any absolute URL —localhostis allowed in every environment, which is convenient during development.- An
EXPIREDpayment never redirects — the customer sees the expired screen with a support prompt. Your server still learns about the expiry via the webhook. - The redirect only auto-fires on a live determination (the customer was on the page when the payment resolved). If they refresh into an already-final payment they see the result without the redirect — another reason the webhook is the reliable server-side channel.
The redirect happens in the customer's browser, so every parameter on it can be forged (?status=SUCCESS is one address-bar edit away). It is deliberately not signed so the rule stays unambiguous: treat the callback as a UX hint that tells you which payment to look at, then confirm the outcome with verify before fulfilling.
A typical callback handler
GET /payment/result?orderId=…&paymentId=…&status=…
1. Look up the order by orderId (or by the stored paymentId).
2. Call POST /api/v1/payments/{paymentId}/verify from your server.
3. Render the result page from the VERIFIED status — not the query param.
Payment expiry
Every payment has a deadline (createdAt + timeoutSeconds). When the checkout countdown reaches zero the page notifies the API, and a server-side sweep also expires overdue payments on its own — you do not need to do anything. Expiry is safe-by-construction: a payment can only transition to EXPIRED when it is genuinely past its deadline and still unpaid.
Related
- Callback vs Webhook — which channel to trust for what.
- Verify Payments — the authoritative outcome check.
- Create payment reference — every field and default.