Widget Integration

Embed hosted checkout with the browser widget runtime.

Use the widget runtime when your frontend needs to launch a Stafiel checkout session. Create the checkout session first on your server, then pass the complete checkoutSessionUrl from the response data to the browser. Do not parse, rebuild, or modify this URL.

Important: Do not put API keys in browser code.

Widget Base URL

https://widget.stafiel.com

Choose a Runtime

Checkout Snippet

Script path:

/widget/v1/checkout.js

This script exposes window.StafielCheckout. Use it for button binding and declarative HTML.

Widget Runtime

Script path:

/widget/v1/widget.js

This script exposes window.StafielWidget. Use it to control widget instances, events, mounting, theme updates, and cleanup.

Your application loads the browser script. Once the checkout frame starts, Stafiel renders and manages the checkout interface.

A merchant-rendered payment page uses a separate integration model. See Custom Payment Page.

Content Security Policy

If the page loading checkout.js or widget.js uses Content Security Policy (CSP), allow these sources in its policy:

  • script-src: https://widget.stafiel.com. Include the same source in script-src-elem if that directive is present.
  • frame-src: https://widget.stafiel.com for modal, inline, lite, and micro.
  • connect-src: https://api.stafiel.com for requests made by the runtime from your page.

Note: Add these sources to your existing directives rather than replacing your site's policy. These are integration requirements, not a complete CSP. The inline scripts in this page's examples must also comply with your script policy; their initialization code can be moved to an allowed external JavaScript file.

Widget Modes

Mode Widget runtime call Fixed scale 1 reference Description
redirect open() — Opens hosted checkout in a new tab by default, or in the current tab when openInNewTab is false.
modal open() 828 x 648 px Opens checkout in the built-in modal.
inline mount() 272 x 384 px Mounts a full checkout frame in your page.
lite mount() 368 x 144 px Mounts a compact checkout frame.
micro mount() 256 x 128 px Mounts the smallest checkout frame.

In redirect mode, an allowed metadata.returnToUrl supplies the hosted checkout Back destination. In modal, inline, lite, and micro modes, the merchant frontend controls surrounding-page navigation.

Sizing

Modal, inline, lite, and micro use the structured sizing option. Modal defaults to sizing: { strategy: 'auto', fit: 'height' }. Inline, lite, and micro default to:

sizing: { strategy: 'auto', fit: 'width' }

Auto sizing supports:

  • width: fit the available width.
  • height: fit the available height.
  • contain: fit within both dimensions.

Fixed sizing uses a numeric multiplier:

sizing: { strategy: 'fixed', scale: 1 }

1 uses the reference dimensions in Widget Modes, 0.8 renders both dimensions at 80%, and 2.5 at 250%. The runtime clamps values to this range. Every sizing strategy preserves the checkout's aspect ratio and internal layout.

Set the width, height, and overflow of containers used by inline, lite, and micro modes. Provide a positive width for width, a positive height for height, and both dimensions for contain.

Auto sizing follows container size changes. During an active checkout, change the sizing strategy with:

widget.setSizing({ strategy: 'auto', fit: 'contain' });

checkoutBinding.update({
  sizing: { strategy: 'fixed', scale: 1.2 }
});

Automatic Fallback

With autoFallback: true, a recoverable error can move checkout to the next mode in this sequence:

micro → lite → inline → modal → redirect

Fallback starts from the selected mode. Non-recoverable errors remain errors. The default is false.

Checkout Snippet

Checkout Snippet Quick Start

<button id="pay-now">Pay now</button>

<script src="https://widget.stafiel.com/widget/v1/checkout.js"></script>
<script>
  window.StafielCheckout.bind('#pay-now', {
    checkoutSessionUrl: 'https://pay.stafiel.com/pay/ps_your_session_token',
    mode: 'modal'
  });
</script>

For inline, lite, and micro, use open() with a container. This example opens an inline checkout immediately:

<div id="stafiel-payment"></div>

<style>
  #stafiel-payment {
    width: 100%;
    max-width: 400px;
  }
</style>

<script src="https://widget.stafiel.com/widget/v1/checkout.js"></script>
<script type="module">
  const checkoutBinding = await window.StafielCheckout.open({
    checkoutSessionUrl: 'https://pay.stafiel.com/pay/ps_your_session_token',
    mode: 'inline',
    container: document.getElementById('stafiel-payment')
  });
</script>

Checkout Snippet API

Method Returns Description
open(options) Promise<CheckoutSnippetBinding> Opens checkout immediately. For inline, lite, and micro, provide container.
bind(target, options) CheckoutSnippetBinding Binds checkout to a CSS selector or HTMLElement.
bindAll(root?, defaults?) CheckoutSnippetBinding[] Binds every [data-stafiel-checkout] node under root.
setTheme(target, theme) void Updates the theme for an existing binding.
setLanguage(target, language) void Updates the language for an existing binding.
unbind(target) void Removes the click trigger listener for one binding.
destroy(target?) void Removes one binding, or all bindings when no target is provided.

Binding Methods

Method Returns Description
open() Promise<void> Opens the bound checkout.
close() void Closes the current checkout surface when supported.
destroy() void Removes the binding and its runtime state.
setTheme(theme) void Switches the binding between light and dark.
setLanguage(language) void Switches the binding language between en, zh-CN, and zh-TW.
update(options) void Updates supported options, including sizing and language, for the current binding.

Checkout Snippet Options

Option Required Default Description
checkoutSessionUrl Yes None Hosted checkout URL returned by Stafiel's Checkout Sessions API.
mode Yes None One of the values listed in Widget Modes.
container For mounted modes Bound target for bind() Container selector or element for inline, lite, and micro.
openInNewTab No true for redirect Controls redirect mode tab behavior.
sizing No Mode-specific auto sizing Auto or fixed sizing for modal and mounted modes. See Sizing.
borderRadius No 24 for modal, 16 otherwise Frame border radius in pixels, clamped between 0 and 24.
backdrop No true Modal only. Set to false to hide the dimming; the page remains non-interactive.
theme No light One of light or dark.
language No en One of en, zh-CN, or zh-TW. en-US is accepted as English.
autoFallback No false Enables mode fallback for recoverable errors. See Automatic Fallback.
onOpen No None Called when the checkout surface opens; payment data may still be loading.
onClose No None Called when checkout closes.
onError No None Called when checkout fails to initialize or open.
onFallback No None Called when the runtime falls back to another mode.

Checkout Snippet modal uses the current document viewport. Custom modal boundaries are available through the Widget runtime.

Declarative Binding

Declare bindings directly in HTML:

<button
  data-stafiel-checkout
  data-checkout-session-url="https://pay.stafiel.com/pay/ps_your_session_token"
  data-mode="modal"
  data-theme="light"
  data-language="en"
  data-sizing-strategy="auto"
  data-sizing-fit="height"
  data-border-radius="24"
  data-backdrop="true"
>
  Pay now
</button>

<script src="https://widget.stafiel.com/widget/v1/checkout.js"></script>
<script>
  window.StafielCheckout.bindAll();
</script>
Attribute Required Description
data-stafiel-checkout Yes Marks the element for bindAll().
data-checkout-session-url Yes, or supply it in bindAll defaults Hosted checkout URL returned by Stafiel's Checkout Sessions API.
data-mode Yes One of the values listed in Widget Modes.
data-container No Selector for a separate mounted container.
data-sizing-strategy No auto or fixed. Required when sizing attributes are used.
data-sizing-fit No width, height, or contain for auto sizing.
data-sizing-scale No Positive decimal required for fixed sizing.
data-border-radius No Frame border radius in pixels.
data-backdrop No Modal only. Set to false to hide the dimming; the page remains non-interactive.
data-theme No light or dark.
data-language No en, zh-CN, or zh-TW. Inherits bindAll defaults when omitted.
data-auto-fallback No Boolean value: true, false, 1, or 0.
data-open-in-new-tab No Boolean value used by redirect mode.

Widget Runtime

Widget Runtime Quick Start

<div id="stafiel-payment"></div>

<script src="https://widget.stafiel.com/widget/v1/widget.js"></script>
<script>
  const widget = window.StafielWidget.create({
    checkoutSessionUrl: 'https://pay.stafiel.com/pay/ps_your_session_token',
    mode: 'inline',
    container: document.getElementById('stafiel-payment')
  });

  widget.mount();
</script>

Widget Options

Option Required Default Description
checkoutSessionUrl Yes None Hosted checkout URL returned by Stafiel's Checkout Sessions API.
mode Yes None One of the values listed in Widget Modes.
container For mounted modes None Connected HTMLElement used by inline, lite, and micro.
openInNewTab No true for redirect Controls whether redirect mode opens a new browser tab.
sizing No Mode-specific auto sizing Auto or fixed sizing for modal and mounted modes. See Sizing.
appearance.borderRadius No 24 for modal, 16 otherwise Frame border radius in pixels, clamped between 0 and 24.
modal.backdrop No true Modal only. Set to false to hide the dimming; the page remains non-interactive.
modal.boundary No Full page Connected, positioned HTMLElement that bounds the complete modal area.
autoFallback No false Enables mode fallback for recoverable errors. See Automatic Fallback.
theme No light One of light or dark.
language No en One of en, zh-CN, or zh-TW. en-US is accepted as English.

Use borderRadius with Checkout Snippet and appearance.borderRadius with the Widget runtime.

Widget Methods

Method Returns Description
StafielWidget.create(options) WidgetInstance Creates a widget instance from a hosted checkout session URL and widget options.
widget.open() Promise<void> Opens redirect or modal mode.
widget.mount(container?) Promise<void> Mounts inline, lite, or micro mode.
widget.close() void Closes the current checkout and built-in modal.
widget.destroy() void Removes listeners, frames, and runtime state for the instance.
widget.setTheme(theme) void Switches the instance between light and dark.
widget.setLanguage(language) void Switches the instance language between en, zh-CN, and zh-TW.
widget.setSizing(sizing) void Changes sizing for the current modal or mounted widget.
widget.on(event, handler) () => void Subscribes to a widget event and returns an unsubscribe function.

Custom Modal Boundary

The default modal uses the full page. Set modal.boundary to a connected, positioned HTMLElement with a visible size to contain the backdrop, payment panel, and close control. Auto sizing follows changes to this boundary.

<div id="stafiel-modal-boundary"></div>

<style>
  #stafiel-modal-boundary {
    position: relative;
    width: 100%;
    height: 720px;
    overflow: hidden;
  }
</style>

<script>
  (async function () {
    const boundary = document.getElementById('stafiel-modal-boundary');
    const widget = window.StafielWidget.create({
      checkoutSessionUrl: 'https://pay.stafiel.com/pay/ps_your_session_token',
      mode: 'modal',
      modal: {
        boundary
      }
    });

    await widget.open();
  })();
</script>

Events

Subscribe to Widget runtime UI and status signals with widget.on(event, handler). Order events are available while an embedded checkout frame is active in modal, inline, lite, or micro mode. Checkout Snippet provides onOpen, onClose, onError, and onFallback callbacks in Checkout Snippet Options. Use webhooks or the order query APIs as the authoritative source for server-side state changes.

Event Description
widget.ready The widget instance is ready. Emitted once per instance.
widget.opened Checkout was opened or mounted; payment data may still be loading.
widget.closed Checkout was closed.
widget.error The widget failed to initialize, mount, open, or load.
widget.fallback The runtime switched to another mode.
order.created The checkout surface observed the order in the awaiting-payment state.
order.payment.detected The checkout surface received a real-time payment-detected signal. This event is not guaranteed for every payment path.
order.payment.received_fullpaid The currently recorded payment amount matched the required amount.
order.payment.received_underpaid The currently recorded payment amount was below the required amount.
order.payment.received_overpaid The currently recorded payment amount exceeded the required amount.

Event payload fields vary by event type.

Field Description
event Event name. Present on every widget event.
version Widget event payload version. Present on every widget event.
timestamp Event timestamp. Present on every widget event.
orderId Order ID when available.
paymentToken Payment token when available.
mode Active widget mode. Present on lifecycle, error, and order events.
reason Error or fallback reason. Present on widget.error and widget.fallback.
recoverable Whether the error can fall back to another mode. Present on widget.error.
fromMode Original widget mode. Present on widget.fallback.
toMode Fallback widget mode. Present on widget.fallback.
status Order status. Present on order events.
payload Event-specific payload. Present on order events and some error events.