npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@flopay/js

v1.2.8

Published

Browser-side FloPay SDK. Provides `loadFloPay()` to initialize the SDK, a `FloPay` class for managing payment elements and confirmations, `PaymentAPI` for billing API calls, and `createCheckoutSession` for server-initiated checkout flows.

Readme

@flopay/js

Browser-side FloPay SDK. Provides loadFloPay() to initialize the SDK, a FloPay class for managing payment elements and confirmations, PaymentAPI for billing API calls, and createCheckoutSession for server-initiated checkout flows.

Currently backed by Stripe via the StripeAdapter. The adapter pattern (PaymentProviderAdapter interface) allows swapping providers without changing consumer code.

Installation

pnpm add @flopay/js

@stripe/stripe-js ships as a direct dependency of @flopay/js — consumers do not need to install it separately.

Quick Start

Initialize the SDK

import { loadFloPay } from '@flopay/js';

const flopay = await loadFloPay('pk_test_...', {
  billingApiUrl: 'https://billing.example.com', // optional, enables retrieveSession/retrieveUnifiedSession
});

loadFloPay caches the instance -- calling it again with the same key returns the cached FloPay instance. The optional second argument accepts a FloPayConfig with billingApiUrl, locale, and appearance.

Create and Mount Elements

const elements = flopay.elements({
  amount: 2999,       // in cents
  currency: 'usd',
});

const cardElement = await elements.create('card');
cardElement.mount(document.getElementById('card-container')!);

Tokenize and Confirm Payment

// 1. Validate elements
const { error: submitError } = await flopay.submitElements();
if (submitError) throw submitError;

// 2. Tokenize card into a PaymentMethod
const { paymentMethodId, error } = await flopay.createPaymentMethod();
if (error || !paymentMethodId) throw error;

// 3. Confirm card payment with a client secret from your server
const result = await flopay.confirmCardPayment({
  clientSecret: 'pi_xxx_secret_yyy',
  paymentMethodId,
});

if (result.error) {
  console.error(result.error.message);
} else {
  console.log('Payment status:', result.status);
}

PayPal Payment

const result = await flopay.confirmPayPalPayment({
  billingApiUrl: 'https://billing.example.com',
  sessionId: 'session_uuid',
  email: '[email protected]',
  returnUrl: window.location.href,
});

// After redirect return, resume the payment:
const resumed = await flopay.resumePayPalPayment();
if (resumed) {
  console.log('PayPal payment status:', resumed.status);
}

Retrieve a Session

// Using billingApiUrl from config (set at init time):
const session = await flopay.retrieveSession('session_uuid');
console.log(session.amount, session.currency, session.status);

// Or pass billingApiUrl explicitly:
const session2 = await flopay.retrieveSession('session_uuid', 'https://billing.example.com');

// For provider-specific data (Stripe clientSecret, publishableKey, etc.):
const unified = await flopay.retrieveUnifiedSession('session_uuid');
console.log(unified.data.stripe?.clientSecret);

Failed session loads reject with FloPayError. When the billing API returns a structured error body, the SDK preserves the safe message, backend code, and HTTP statusCode; body-less responses fall back to code: "http_<status>".

PaymentAPI (Billing API Client)

import { PaymentAPI } from '@flopay/js';

const api = new PaymentAPI('https://billing.example.com');

// Fetch and normalize a checkout session. `nonce` is the session-bound
// checkout token returned from session creation — required by post-#640
// backends, which match it against `checkout_session.nonce` before returning
// the row.
const session = await api.getUnifiedCheckoutSession('session_uuid', sessionNonce);
// session.provider === 'stripe' | 'chargebee' | 'recurly'
// session.data.session contains the normalized CheckoutSession
// session.data.session.clientSecret carries the same nonce so downstream
// code can re-use it.

// Create a PaymentIntent — nonce becomes the `x-checkout-session-token`
// header automatically.
const intentResponse = await api.createPaymentIntent(
  'session_uuid',
  '[email protected]',
  'pm_xxx',
  { nonce: sessionNonce },
);

// Process a tokenized payment. `nonce` is required: the SDK throws a
// `FloPayError` with code `MissingCheckoutSessionToken` when it is missing,
// and otherwise POSTs to `/v1/checkouts/sessions/<id>/process` with the
// header set.
const processResponse = await api.processPayment('user_id', {
  sessionId: 'session_uuid',
  nonce: sessionNonce,
  tokenizedData: { id: 'pm_xxx', type: 'card' },
  accountData: { userId: 'user_id', email: '[email protected]', firstName: 'John', lastName: 'Doe' },
});
// If the backend returns `202 checkout_processing`, the SDK keeps polling the
// checkout session until it completes or times out, then resolves/rejects.

// Check for prior payments (saved card UX)
const payments = await api.getPaymentsByEmail('[email protected]');

createCheckoutSession

import { createCheckoutSession } from '@flopay/js';

const result = await createCheckoutSession({
  billingApiUrl: 'https://billing.example.com',
  checkoutBaseUrl: 'https://checkout.example.com',
  clientId: 'client_123',
  items: [{
    providerItemId: 'prod_abc',
    providerItemName: 'Pro Plan',
    totalAmount: 49.99,
    overrideAmount: 24.99,
  }],
  account: { userId: 'user_1', email: '[email protected]' },
  successUrl: '/success',
  cancelUrl: '/cancel',
  redirectParams: { email: '[email protected]', bg: 'courses', mode: 'confirm' },
});
// On 201: browser redirects to checkout page. The resolved
// `CheckoutSessionResult` is `{ status: 201, redirectUrl, nonce }` — `nonce` is
// the session-bound checkout token returned by the billing API. A matching
// `flopay_checkout_token` cookie is written to the same parent domain as
// `checkout_data`, so a hosted-checkout page can read the token from
// `document.cookie` and forward it on continuation calls without having to
// pull it from the URL (kept out of history/Referer).
// On 204: browser redirects to successUrl (payment method on file)

Use createCheckoutSessionWithRetries for automatic retry with exponential backoff on timeout errors.

Coupon validation errors are surfaced as FloPayError with structured code:

  • CouponLimitExceeded — more than 5 coupon codes supplied (also enforced client-side before the request leaves the browser).
  • CouponCurrencyUnsupported — an amount-based coupon has no price for the cart currency.
import { FloPayError } from '@flopay/shared';

try {
  await createCheckoutSession({ /* … */ couponCodes });
} catch (err) {
  if (err instanceof FloPayError) {
    if (err.code === 'CouponLimitExceeded') {
      // show "Too many coupons" toast
    } else if (err.code === 'CouponCurrencyUnsupported') {
      // show "Coupon is not valid for this currency" toast
    }
  }
}

API Reference

Exports

| Export | Description | |--------|-------------| | loadFloPay(publishableKey, options?) | Initializes the SDK. Returns a Promise<FloPay>. Caches by key. | | FloPay | Main SDK class. Methods: elements(), submitElements(), createPaymentMethod(), confirmCardPayment(), confirmPayment(), confirmPayPalPayment(), resumePayPalPayment(), retrieveSession(), retrieveUnifiedSession(), getRawProvider(), destroy() | | FloPayElements | Element group manager. Methods: create(type, options?), getElement(type), submit(), destroy() | | StripeAdapter | PaymentProviderAdapter implementation for Stripe | | PaymentAPI | Billing API client. Methods: getCheckoutSession(), getUnifiedCheckoutSession(), processPayment(), waitForCheckoutSessionCompletion(), createPaymentIntent(), createSetupIntent(), getPaymentsByEmail() | | createCheckoutSession(options) | Creates a checkout session and redirects. Returns CheckoutSessionResult. | | createCheckoutSessionWithRetries(options) | Same as above with automatic retries (default 3, exponential backoff). |

FloPay Class Methods

| Method | Returns | Description | |--------|---------|-------------| | elements(options?) | FloPayElements | Creates a new elements group. Destroys previous group. | | submitElements() | Promise<{ error? }> | Validates all mounted elements | | createPaymentMethod() | Promise<CreatePaymentMethodResult> | Tokenizes card fields into a pm_xxx ID. Auto-detects split fields vs unified PaymentElement. | | confirmCardPayment(params) | Promise<ConfirmCardPaymentResult> | Confirms with clientSecret + paymentMethodId. Handles 3DS. | | confirmPayment(params) | Promise<PaymentResult> | Confirms using mounted elements + clientSecret | | confirmPayPalPayment(params) | Promise<ConfirmCardPaymentResult> | Full PayPal flow: create PM -> create intent -> confirm/redirect | | resumePayPalPayment() | Promise<ConfirmCardPaymentResult \| null> | Resumes after PayPal redirect. Returns null if no PayPal params in URL. | | retrieveSession(sessionId, billingApiUrl?) | Promise<CheckoutSession> | Retrieves a checkout session by ID via GET /v1/checkouts/sessions/{id}. Uses billingApiUrl from config or the optional second argument. | | retrieveUnifiedSession(sessionId, billingApiUrl?) | Promise<NormalizedCheckoutSession> | Retrieves and normalizes a checkout session, including provider-specific data (Stripe clientSecret/publishableKey, etc.). | | getRawProvider() | unknown | Returns the raw underlying provider instance (e.g. Stripe object) | | destroy() | void | Tears down elements and provider |

Supported Element Types

  • payment -- Unified PaymentElement (cards, wallets, etc.)
  • card -- Combined card input (number + expiry + CVC)
  • cardNumber -- Card number field (for split card forms)
  • cardExpiry -- Card expiry field
  • cardCvc -- Card CVC field
  • address -- Address input element