Skip to main content
When you call createCheckout(), the SDK renders a complete payment UI inside your container. Learn what the default checkout includes and how to customize it.

Default styles

Out of the box, createCheckout() applies the default CSS styles and renders:
  • An accordion with radio-button selection between available payment methods.
  • A card form with number, expiry, and CVV fields.
  • PayPal, Google Pay, and Apple Pay buttons in their own accordion sections.
  • Loading spinners, error containers, and a success screen.
  • A responsive layout with a mobile breakpoint at 768 px.
The accordion auto-selects the first available payment method and expands it. To customize the default UI, follow the sections below.

Override CSS

The default checkout renders elements with .ff-* CSS classes you can target for visual overrides:
ClassPurpose
.ff-skin-defaultTop-level container (max-width: 400px, centered)
.ff-payment-method-cardPayment method card (hidden until .visible)
.ff-payment-method-card.expandedAccordion expanded state
.ff-payment-method-radioCustom radio button
.ff-payment-method-labelRow with radio button and header
.ff-payment-method-contentAnimated accordion panel
.ff-card-form-containerCard form wrapper
.ff-card-form-submit-buttonSubmit button
.ff-card-form-labelInput labels
.ff-card-form-text-inputNative inputs (cardholder, email)
.ff-card-form-text-input.errorError state for native inputs
.ff-security-messageSecurity message below forms
.ff-payment-featuresCheckmark list per payment method
.payment-errors-containerError message area
.loader-containerFull overlay with loading spinner
For example, to change the submit button border radius:
.ff-card-form-submit-button {
  border-radius: 8px;
}

Customize checkout

For full control over the checkout UI, provide both cardSelectors and paymentButtonSelectors to createCheckout(). The SDK skips the default UI entirely and injects payment inputs into your own HTML elements.
The paymentMethodOrder option is ignored when using a custom layout.

Card selectors

Card selectors are resolved relative to the container element.
cardNumber
string
required
An empty div where the hosted card number input is injected.
expiryDate
string
required
An empty div for the hosted expiry input.
cvv
string
required
An empty div for the hosted CVV input.
button
string
required
A button element. The SDK hooks its click event for form submission.
cardholderName
string
An input element. The SDK reads its value directly.
emailAddress
string
An input element. The SDK reads its value directly.
<!-- Card form inside the container -->
<div id="checkout-container" style="position: relative;
  min-height: 200px;">
  <div id="my-card-number"></div>
  <div id="my-expiry"></div>
  <div id="my-cvv"></div>
  <input id="my-cardholder" placeholder="Cardholder name" />
  <input id="my-email" placeholder="Email" />
  <button id="my-submit-button">Pay</button>
</div>
cardSelectors: {
  cardNumber: '#my-card-number',
  expiryDate: '#my-expiry',
  cvv: '#my-cvv',
  cardholderName: '#my-cardholder',
  emailAddress: '#my-email',
  button: '#my-submit-button',
},

Payment button selectors

Payment button selectors are resolved relative to document, not the container.
paypal
string
required
A div for the PayPal button.
googlePay
string
required
A div for the Google Pay button.
applePay
string
required
A div for the Apple Pay button.
All three payment button selectors are required. Omitting any of them throws a CheckoutError.
<!-- Payment buttons outside the container -->
<div id="my-paypal-container"></div>
<div id="my-gpay-container"></div>
<div id="my-applepay-container"></div>
paymentButtonSelectors: {
  paypal: '#my-paypal-container',
  googlePay: '#my-gpay-container',
  applePay: '#my-applepay-container',
},

Payment method order

The paymentMethodOrder array controls the display order of payment methods in the checkout accordion. By default, it shows: APPLE_PAY > GOOGLE_PAY > PAYPAL > PAYMENT_CARD.
await Billing.createCheckout({
  // ...required options
  paymentMethodOrder: [
    'APPLE_PAY',
    'GOOGLE_PAY',
    'PAYPAL',
    'PAYMENT_CARD',
  ],
});
Omit a method from the array to exclude it from the checkout. For example, to show only card and PayPal:
paymentMethodOrder: ['PAYMENT_CARD', 'PAYPAL'],

Card form

Customize card form fields visibility.

Cardholder name field

The cardholder name field visibility is controlled by the server response by default. Override it using the required parameter:
  • true: Show and require the field.
  • false or unset: Hide the field.
Your explicit configuration takes precedence over the server default.
await Billing.createCheckout({
  // ...required options
  card: {
    cardholderName: {
      required: true,
    },
  },
});

Email address field

The email field is also server-controlled by default. Override it to show an email input in the card form: Set visible: true to render an email input pre-populated with the customer.email value. Use template to optionally format the email before sending it as the payment email address. Any occurrence of {{email}} is replaced with the actual email.
await Billing.createCheckout({
  // ...required options
  card: {
    emailAddress: {
      visible: true,
      template: '{{email}}',
    },
  },
});

Payment button

Each payment method button accepts styling options that are passed to the underlying payment provider SDK.

Apple Pay

By default, buttonStyle is set to black, but you can optionally use white or white-outline.
await Billing.createCheckout({
  // ...required options
  applePay: {
    buttonStyle: 'black', // 'black' | 'white' | 'white-outline'
  },
});

PayPal

Customize the PayPal button appearance and payment flow.
OptionValuesDefault
buttonColor'gold', 'blue', 'silver', 'black', 'white''gold'
buttonShape'pill', 'rect''pill'
buttonLabel'pay', 'checkout', 'buynow', 'paypal''pay'
buttonSize'small', 'medium', 'large''large'
buttonHeightPixel value54
paymentFlow'PREFER_VAULT', 'DEFAULT''PREFER_VAULT'
await Billing.createCheckout({
  // ...required options
  paypal: {
    buttonColor: 'gold',
    buttonShape: 'pill',
    buttonLabel: 'pay',
    buttonSize: 'large',
    buttonHeight: 54,
    paymentFlow: 'PREFER_VAULT',
  },
});

Google Pay

Customize the Google Pay button appearance and sizing.
OptionValuesDefault
buttonColor'black', 'white''black'
buttonSizeMode'fill', 'static''fill'
buttonType'pay', 'book', 'buy', 'checkout', 'donate', 'order', 'plain', 'subscribe''pay'
await Billing.createCheckout({
  // ...required options
  googlePay: {
    buttonColor: 'black',
    buttonSizeMode: 'fill',
    buttonType: 'pay',
  },
});

Card input

Card number, expiry, and CVV fields are rendered inside iframes by the payment provider, so regular CSS cannot reach them. Use the style option to control their appearance:
await Billing.createCheckout({
  // ...required options
  style: {
    input: {
      base: {
        borderWidth: '1px',
        borderStyle: 'solid',
        borderColor: 'rgb(0 0 0 / 10%)',
        height: '36px',
        paddingHorizontal: 10,
        borderRadius: '6px',
      },
      error: {
        borderColor: 'rgb(227, 47, 65)',
      },
    },
  },
});
The base object also supports fontSize, color, fontFamily, and fontWeight. By default, SDK applies the following styles:
PropertyBase stateError state
borderWidth'1px'
borderStyle'solid'
borderColor'rgb(0 0 0 / 10%)''rgb(227, 47, 65)'
height'36px'
paddingHorizontal10
borderRadius'6px'
The cardholder name and email inputs are native HTML input elements. Style them with CSS using the .ff-card-form-text-input class, not through the style option.

Single payment method

Use Billing.initMethod() to render a single payment method into your own container:
import { Billing, PaymentMethod } from '@funnelfox/billing';

const container = document.getElementById('payment-container');

const method = await Billing.initMethod(
  PaymentMethod.PAYMENT_CARD,
  container,
  {
    orgId: 'your-org-id',
    priceId: 'price_123',
    externalId: 'user_456',
    email: 'user@example.com',

    // Optional styling
    style: { /* CheckoutStyle */ },
    card: { /* BillingCardOptions */ },

    // Callbacks
    onRenderSuccess: () => {
      console.log('Payment method rendered');
    },
    onPaymentSuccess: () => {
      console.log('Payment completed');
    },
    onPaymentFail: (error) => {
      console.error('Payment failed:', error.message);
    },
  }
);
Available payment methods: PAYMENT_CARD, PAYPAL, GOOGLE_PAY, APPLE_PAY. For PAYMENT_CARD, the SDK renders a card form (number, expiry, CVV, optional cardholder name, optional email) inside the container. For PAYPAL, GOOGLE_PAY, and APPLE_PAY, the payment button is rendered directly. The returned interface provides:
  • setDisabled(disabled): Enable or disable the payment method.
  • submit(): Programmatically trigger form submission (card payments only).
  • destroy(): Clean up and remove the payment method.