Communication via postMessage and Error Handling
The communication between the store page and the iframe occurs through postMessage events sent by the checkout and the front-end's own states. These mechanisms allow adjusting the display, reacting to successes, capturing failures, and keeping the payment flow functional even when errors occur.
Front-end Errors
Failure to create the payment page
The most critical error occurs when the checkoutUrl is not present in the back-end response. The front-end stops loading and displays a friendly message.
try {
const data = await CheckoutFetcher.callCreateCheckout(apiUrl, payload);
// Extrai a checkoutUrl da resposta
// A URL pode estar em diferentes lugares dependendo da versão da API
let checkoutUrl = '';
if (data?.data?.settings?.checkoutUrl) {
checkoutUrl = data.data.settings.checkoutUrl;
} else if (data?.data?.checkoutUrl) {
checkoutUrl = data.data.checkoutUrl;
} else if (data?.data?.url) {
checkoutUrl = data.data.url;
}
this.checkoutUrl = checkoutUrl;
if (!this.checkoutUrl) {
this.error = 'URL de checkout não encontrada na resposta.';
}
} catch (e) {
this.error = 'Erro ao criar checkout.';
console.error(e);
} finally {
this.loading = false;
}
}
}
};Iframe does not appear
The iframe does not load when the checkoutUrl is empty or invalid. Validating the URL helps identify the issue:
console.log('checkoutUrl recebida:', checkoutUrl);CORS Error
Occurs when the Checkout API is called directly from the front-end. The call must always occur through the back-end.
Null or non-standard URL
Changes in the API structure can cause the URL to appear in different fields:
const checkoutUrl =
data?.data?.settings?.checkoutUrl ||
data?.data?.checkoutUrl ||
data?.data?.url;Back-end Errors
Error 401 (Unauthorized)
Indicates a problem with the MerchantId or authentication configuration. It is necessary to review the header sent to the API.
Failure to create checkout in the API
The back-end must handle API exceptions and return a consistent response to the front-end.
try {
const { data } = await axios.post(
'https://cieloecommerce.cielo.com.br/api/public/v1/orders/',
payload,
{
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
MerchantId: CIELO_MERCHANT_ID
},
timeout: 10000
}
);
const checkoutUrl = data?.CheckoutUrl || data?.checkoutUrl || data?.url;
return res.json({ checkoutUrl });
} catch (err) {
return res.status(err.response?.status || 500).json({
message: 'Falha ao criar checkout',
detail: err.response?.data || err.message
});
}
This handling allows:
- Differentiating API errors from internal failures;
- Returning an appropriate HTTP status code;
- Exposing a controlled error message to the front-end.
Best Practices for Error Handling
Some practices help make the checkout flow more resilient:
- Implement
timeoutsin API calls; - Consider
retrieswith exponential backoff in instability scenarios; - Apply idempotency in order or checkout creation;
- Validate input data before sending to the back-end;
- Monitor errors and API responses to detect failure patterns;
- Use TLS and Content Security Policies (CSP) on the store's domain.
Timeout and iframe fallback
Loading the iframe uses a maximum time to detect when the checkout has not responded in time. When this limit is reached, the flow triggers the fallback, preventing the shopper from staying indefinitely on the loading screen and providing a safe alternative to continue the payment.
Timeout
const FAIL_TIMEOUT_MS = 7000; // ajuste conforme sua UXMarkup Structure
<div id="checkout-loading" role="status">
Carregando o checkout…
</div>
<div id="checkout-fallback" hidden>
Não foi possível carregar o checkout embutido.
<a id="checkout-direct-link" rel="noopener">Abrir pagamento</a>.
</div>How It Works
function loadCheckout(url) {
directLink.href = url;
iframe.src = url;
let finished = false;
const FAIL_TIMEOUT_MS = 7000;
iframe.addEventListener(
'load',
() => {
finished = true;
loadingEl.hidden = true;
},
{ once: true }
);
setTimeout(() => {
if (!finished) {
loadingEl.hidden = true;
fallbackEl.hidden = false;
}
}, FAIL_TIMEOUT_MS);
}This flow keeps the loading process under control and provides an alternative when the iframe does not respond in time.