Embed the Checkout

Load the checkout in an iframe on your page and follow the payment with postMessage events.

Every session has a checkout url. You can redirect the customer to it, or embed it in an iframe on your own page and receive events as the customer moves through the payment.

Hosted (redirect)Embedded (iframe)
checkout_typehosted (default)embedded
Where the customer paysOn Tonder's pageInside your page
How you follow itRedirect URLs + webhookspostMessage events + webhooks

Your site's domain must be enabled for embedding in each environment. Ask Tonder support to add it before you test.

Step by step

Create the session with checkout_type: "embedded" and post_message_enabled: true. Add redirect_on_completion: "never" if you want your page, not the checkout, to decide where the customer goes at the end.

{
  "customer": { "first_name": "Ana", "last_name": "Garcia", "email": "ana@example.com" },
  "amount_total": 100.00,
  "currency": "MXN",
  "line_items": [{ "name": "Deposit", "quantity": 1, "unit_price": 100.00 }],
  "payment_method_types": ["card", "spei"],
  "external_id": "ORD-001",
  "return_url": "https://your-store.com/checkout/complete",
  "checkout_type": "embedded",
  "post_message_enabled": true,
  "redirect_on_completion": "never"
}

Accept messages only from the checkout origin of your environment: https://stage-payflow.tonder.io (Sandbox) or https://payflow.tonder.io (Production).

Use the url from the session response as the iframe src.

Events tell your page what to show. Confirm the payment itself from your backend, with webhooks or Get a session.

Events

EventWhentransaction_statussession_status
checkout.initiatedThe checkout has loaded—pending
checkout.redirectedThe customer goes to a voucher or external payment pagePendingpending
checkout.returnedThe customer comes back from that pagevariesvaries
checkout.failedAn attempt failed; the customer can retry (may repeat)Failed, Declinedpending
checkout.completedPayment or card saving succeeded (sent once)Successcompleted

Event fields

FieldDescription
eventEvent name.
session_typepayment or enrollment.
payment_idThe payment (not present on enrollment).
direct_transaction_idDirect API accounts only: the latest attempt (not present before the first attempt).
external_idYour order reference.
transaction_status, session_statusCurrent statuses.
payment_methodMethod used, e.g. card, oxxopay.
{
  "event": "checkout.completed",
  "session_type": "payment",
  "payment_id": 41528,
  "external_id": "ORD-001",
  "transaction_status": "Success",
  "session_status": "completed",
  "payment_method": "card"
}

Example page

<!DOCTYPE html>
<html>
<body>
  <div id="status"></div>
  <script>
    window.addEventListener('message', function (event) {
      const allowedOrigins = ['https://payflow.tonder.io', 'https://stage-payflow.tonder.io'];
      if (!allowedOrigins.includes(event.origin)) return;
      const data = event.data;
      switch (data.event) {
        case 'checkout.initiated':
          document.getElementById('status').textContent = 'Ready to pay';
          break;
        case 'checkout.completed':
          window.location.href = data.session_type === 'enrollment'
            ? '/card-saved'
            : '/success?payment=' + data.payment_id;
          break;
        case 'checkout.failed':
          document.getElementById('status').textContent =
            'Payment failed: ' + data.transaction_status + '. Please try again.';
          break;
        case 'checkout.redirected':
          document.getElementById('status').textContent =
            'Redirecting to ' + data.payment_method + '...';
          break;
        case 'checkout.returned':
          if (data.transaction_status === 'Success') {
            window.location.href = '/success?payment=' + data.payment_id;
          }
          break;
      }
    });
  </script>
  <iframe id="checkout-iframe" src="SESSION_URL" style="width: 100%; height: 600px; border: none;"></iframe>
</body>
</html>

Never fulfill an order from a browser event alone. A message in the page can be forged; the webhook or a server-side read of the session is the source of truth.

Next steps

Was this page helpful?

On this page