0Bit Documentation

Handle widget callbacks

Wire 0Gate browser callbacks for UX while keeping fulfillment, ledger updates, and support state on verified backend events.

Widget callbacks are browser events from the hosted 0Gate iframe to your page. Use them to update the screen, measure availability, and route the user. Do not use them to fulfill value.

Callbacks are UX hints

Browser callbacks can be missed, replayed, blocked, or seen before webhook delivery. Your backend should close attempts from signed events or trusted reconciliation reads.

Callback sequence

Callback matrix

CallbackMeaningPage actionBackend action
onReadyIframe mounted and can receive config.Stop loading state.Optional health/analytics event only.
onSuccessHosted flow reached a success UX state.Show processing and refresh your status endpoint.Wait for signed event before fulfillment.
onErrorHosted flow reported a recoverable or terminal error.Show generic failure or retry UI.Wait for event/reconciliation before closing final state.
onCloseUser dismissed or session closed in browser.Offer retry, resume, or support.Do not mark failed without trusted state.
onUnavailableEmbed bootstrap says the partner/session is unavailable.Show neutral unavailable UI.Do not create uncontrolled retry loops.
onMountErrorReact wrapper caught mount/bootstrap failure.Fall back to redirect or show support.Keep the existing attempt open unless trusted state says otherwise.

Browser implementation

import { GateRamp } from '@0bit/gate/browser';

const ramp = new GateRamp({
  publishableKey,
  clientSecret,
  environment: 'sandbox',
});

await ramp.mount('#gate-checkout', {
  onReady: () => setView('ready'),
  onSuccess: ({ sessionId }) => {
    setView('processing');
    refreshStatus({ gateSessionId: sessionId });
  },
  onError: ({ code }) => {
    setLastSafeCode(code);
    setView('recoverable_error');
  },
  onClose: ({ reason }) => {
    setCloseReason(reason);
    setView('retry_or_support');
  },
  onUnavailable: () => setView('unavailable'),
});

React implementation

import { RampCheckout } from '@0bit/gate/react';

<RampCheckout
  publishableKey={publishableKey}
  clientSecret={clientSecret}
  environment="sandbox"
  onReady={() => setView('ready')}
  onSuccess={() => setView('processing')}
  onError={({ code }) => setSafeErrorCode(code)}
  onClose={() => setView('retry')}
  onUnavailable={() => setView('unavailable')}
  onMountError={() => setView('redirect_fallback')}
/>;

Status refresh pattern

After any terminal-looking browser callback, fetch your own status endpoint.

async function refreshStatus(attemptId: string) {
  const status = await fetch(`/api/checkouts/${attemptId}/status`).then((res) => res.json());

  if (status.view === 'success') showSuccess();
  else if (status.view === 'failed') showFailure();
  else if (status.view === 'expired') showExpired();
  else if (status.view === 'cancelled') showCancelled();
  else showProcessing();
}

Safe event handling

RuleReason
Let the SDK own postMessage filtering.The SDK checks iframe origin and message shape before firing callbacks.
Do not attach broad payment listeners globally.Multiple widgets, browser extensions, or unrelated frames can emit messages.
Store only safe callback fields.Codes and reasons are useful; raw payloads and secrets are not.
Keep fulfillment in backend workers.Webhooks are retryable, signed, and dedupable.
Unmount on route or modal close.Prevent stale listeners and duplicate browser states.

On this page