JavaScript SDK (FastStar.js)
FastStar.js is a zero-dependency, single-file browser SDK (UMD). It opens the hosted checkout in a centered overlay so buyers never leave your site, and provides a secure popup flow for saving cards to the vault.
Including the SDK
Add the script at the bottom of your page, or in <head> with defer:
<script src="https://cashier.faststarpay.com/sdk/v1/faststar.min.js" defer></script>
The SDK also works in CommonJS/AMD environments via its UMD wrapper
(require('./faststar.js')). FastStar.init() is optional — calling
FastStar.checkout.open() directly initializes the SDK with defaults.
Subresource Integrity (SRI)
The SDK is served from a versioned path (/sdk/v1/). If your security policy
requires it, you can pin the exact file with Subresource Integrity: compute the hash of the
file you verified (for example openssl dgst -sha384 -binary faststar.min.js | openssl base64 -A)
and add integrity="sha384-..." together with crossorigin="anonymous"
to the script tag. Re-generate the hash whenever you adopt a new SDK build.
Fixed cashier domain & origin whitelist
Since v1.1.0 the cashier domain is pinned to https://cashier.faststarpay.com and
cannot be configured. A configurable base URL would be a phishing and
overlay-hijacking surface: any page could point a FastStar-looking overlay at an arbitrary
domain.
For the same reason, FastStar.checkout.open({ url }) only opens URLs on
the platform's whitelisted origins — https://cashier.faststarpay.com and
https://merchant.faststarpay.com. Any other URL is rejected. Only
http(s) URLs are accepted, so pseudo-protocols such as javascript:
cannot be injected.
Opening the checkout
The recommended flow is a Checkout Session: your
server creates the session with your API key and returns its url to the
browser:
// presentation: 'iframe' — SDK overlay (buyer stays on your site)
FastStar.checkout.open({ url: data.url });
// presentation: 'link' — full-page redirect
window.location.href = data.url; Payment links are also supported, by full URL or by id:
// full payment link URL
FastStar.checkout.open({ url: 'https://cashier.faststarpay.com/pay/plink_abc123' });
// linkId only — the SDK builds {cashier}/pay/{linkId}
FastStar.checkout.open({ linkId: 'plink_abc123' });
The SDK renders a full-screen translucent backdrop with a centered iframe (the checkout URL
automatically gets an embedded=1 query parameter). The overlay has a close
button, closes on backdrop click or ESC, shows a CSS-only loading spinner, and
goes full-screen on mobile (width ≤ 640px). Close it programmatically with
FastStar.checkout.close().
Events
The checkout page reports results back to your page via postMessage; the SDK
wraps them as events:
| Event | When | Example data |
|---|---|---|
checkout.success | Payment succeeded (the overlay closes automatically) | { payment_intent_id: 'pi_xxx' } |
checkout.cancel | Buyer closed the overlay or canceled on the checkout page | { reason: 'user_closed' } |
checkout.error | Payment failed (overlay stays open so the buyer can retry) | { message: '...' } |
checkout.open / checkout.loaded / checkout.close | Overlay lifecycle | — |
function onSuccess(data) {
console.log('Paid, payment_intent_id =', data.payment_intent_id);
// Note: always fulfill based on the server-side webhook, not this event
}
FastStar.on('checkout.success', onSuccess);
FastStar.on('checkout.cancel', function (data) { console.log('Canceled', data); });
FastStar.on('checkout.error', function (data) { console.warn('Failed', data); });
// Unbind: pass the callback to remove one listener,
// or omit it to remove all listeners for that event
FastStar.off('checkout.success', onSuccess);
For Checkout Sessions the event data also carries the
checkout_session_id.
Auto-binding with data-faststar-checkout
Add the data-faststar-checkout attribute to any element and a click opens the
overlay. The value can be a full URL or a linkId:
<!-- full URL -->
<a href="#" data-faststar-checkout="https://cashier.faststarpay.com/pay/plink_abc123">Buy now</a>
<!-- linkId only -->
<button data-faststar-checkout="plink_abc123">Buy now</button>
<!-- empty value: falls back to the <a> tag's href -->
<a href="https://cashier.faststarpay.com/pay/plink_abc123" data-faststar-checkout>Buy now</a> Binding is implemented with event delegation, so dynamically inserted elements work without re-initialization.
Saving cards: FastStar.cards.add
FastStar.cards.add(session, callbacks) opens a secure popup that saves a
buyer's card to the FastStar vault for later
off-session charges. The flow is an iframe inside an iframe:
your site → (SDK overlay iframe) → FastStar card page (our domain) → processor's secure iframe
The card number only ever enters the payment processor's secure iframe — it never touches
your servers or FastStar's. You receive only a FastStar token (pm_xxx)
plus masked card details.
Sequence (follow exactly)
- Your server creates a SetupIntent with your API key (never expose the key in the
browser):
POST /api/v1/public/customers/:id/setup-intent → data: { client_secret, publishable_key, setup_intent_id, provider } -
Your server sends that result — together with the attach endpoint URL and a short-lived
auth token it issues — to the browser, which calls:
FastStar.cards.add( { customerId: 'cus_xxx', clientSecret: 'seti_xxx_secret_xxx', // from setup-intent publishableKey: 'pk_live_xxx', // from setup-intent attachUrl: 'https://api.faststarpay.com/api/v1/public/customers/cus_xxx/payment-methods', authToken: 'SHORT_LIVED_TOKEN' // issued by your server, used to call attachUrl }, { onSuccess: function (card) { // card = { payment_method_id: 'pm_xxx', brand, last4, exp_month, exp_year, is_default } console.log('Card saved', card.payment_method_id); }, onError: function (err) { console.warn('Card save failed', err.message); }, // popup stays open for retry onCancel: function () { console.log('Buyer canceled'); } } ); -
The SDK opens a centered popup iframe at
cards/add?embedded=1on the cashier domain. When the card page signals it is ready, the SDK passes thesessionin viapostMessage— credentials never appear in the URL, so theauthTokenis not exposed. -
The buyer enters the card in the processor's secure inputs and saves. The card page
completes tokenization, then calls
attachUrlwith{ setup_intent_id }to attach the payment method. -
The card page posts the masked card back to the SDK, which fires
onSuccess(card)and closes the popup automatically.
Card events
The same results are also emitted as events you can observe with FastStar.on:
| Event | Meaning | data |
|---|---|---|
card.added | Card saved (popup closes automatically) | { payment_method_id, brand, last4, exp_month, exp_year, is_default } |
card.error | Tokenization or attach failed (popup stays open for retry) | { message } |
card.cancel | Buyer closed the popup or canceled | — |
card.ready | Card page ready (the SDK uses this internally to inject the session) | — |
FastStar.cards.close() closes the popup without firing callbacks — useful for
cleanup inside your own handlers.
Security notes
-
The overlay iframe runs with
sandbox(allow-scripts allow-forms allow-same-origin allow-popups allow-popups-to-escape-sandbox allow-top-navigation-by-user-activation);allow-top-navigation-by-user-activationandallow-popupsexist to support 3-D Secure bank redirects. -
The SDK only accepts
postMessagepayloads whose body is{ source: 'faststar', ... }and whoseoriginmatches the current checkout/card page. Everything else is ignored. -
checkout.successis for front-end interaction only (closing the overlay, showing a thank-you page). Fulfillment must rely on server-side webhooks. -
During card saving, the card number never passes through your servers or FastStar's; the
authTokentravels viapostMessage, never in a URL.