Skip to main content

Error Handling

This guide explains how to handle errors returned by the Drop-in Checkout.

Error Sources

Errors can originate from two sources:

SourceDeliveryWhen
Event listenerevent.code === "error"Initialization failures, internal errors
Method returnresult instanceof ErrorsubmitPayment(), mount(), setSession(), setWalletSession()

Handling Event Errors

Listen for errors through the eventListener callback:

const dropin = await Purse.createDropinCheckout({
session: clientSession.widget.data,
eventListener: (event) => {
if (event.code === "error") {
console.error("Error:", event.payload.message);
showErrorToUser(event.payload.message);
}
}
});

Error Event Structure

{
code: "error";
payload: {
message: string; // Human-readable description
code?: string; // Error code (when available)
};
}

Handling Method Errors

Wrap async method calls in try/catch:

submitPayment()

try {
await dropin.submitPayment();
// Success - SDK handles redirection
} catch (error) {
console.error("Payment failed:", error.message);
payButton.disabled = false;
payButton.textContent = "Pay";
showErrorToUser(error.message);
}

mount()

try {
await dropin.mount(container);
} catch (error) {
console.error("Mount failed:", error.message);
// Show fallback or error state
}

setWalletSession()

try {
await dropin.setWalletSession(walletSession);
} catch (error) {
console.error("Wallet session failed:", error.message);
}

setSession()

setSession() handles errors internally. Errors are reported through the eventListener callback:

await dropin.setSession(newSessionData);
// Errors are emitted via the eventListener, not thrown

Common Error Scenarios

ScenarioSuggested Action
Network errorDisplay retry option
Session expiredFetch new session and call setSession()
Payment declinedShow decline message, allow retry
Validation errorPrompt user to correct input

Session Expiration

If a session expires, obtain a new session from your backend and update the Drop-in:

async function refreshSession() {
const newSession = await fetchClientSessionFromBackend();
await dropin.setSession(newSession.widget.data);
}

Example: Comprehensive Error Handling

const payButton = document.getElementById("pay-button");

try {
const dropin = await Purse.createDropinCheckout({
session: clientSession.widget.data,
eventListener: (event) => {
if (event.code === "ready") {
document.getElementById("loading-spinner").style.display = "none";
}
if (event.code === "error") {
showError(event.payload.message);
}
}
});

await dropin.mount(container);

// Enable pay button when payment method is selected
dropin.isPaymentFulfilled.subscribe((isFulfilled) => {
payButton.disabled = !isFulfilled;
});

payButton.addEventListener("click", async () => {
payButton.disabled = true;
payButton.textContent = "Processing...";
hideError();

try {
await dropin.submitPayment();
} catch (error) {
showError(error.message || "Payment failed. Please try again.");
payButton.disabled = false;
payButton.textContent = "Pay";
}
});
} catch (error) {
showError("Failed to load payment form. Please refresh.");
}

Next Steps