Elements

Elements provides a set of pre-built components to build your own checkout experience and tokenises sensitive payment details. Using Elements you can control when the payment logic on your backend. It also allows you to customise 3DS and APM logic on your frontend.

example of checkout
info icon

Before you start configuring your checkout, make sure you follow our Getting Started guide

Initialisation

<!DOCTYPE html>
<html>
  <body>
    <form novalidate id="checkoutForm">
      <div id="container"></div>
      <button type="submit" id="submitButton">Submit</button>
    </form>

    <script src="dist/index.js"></script>
  </body>
</html>

WhenThen Checkout Element will be attached to #container element inside #checkoutForm form.

import WhenThenSdkLoader from '@whenthen/sdk-loader';

const options = {
   apiKey: 'CLIENT_TOKEN_XXX',
};    

window.addEventListener('load', async () => {
   const checkoutSdk = await WhenThenSdkLoader.loadCheckoutSdkElement('#container', options);
});

loadCheckoutSdkElement

PropType
  • elementOrSelectorHTMLElement | String

    The container element or the selector of the container element.

  • optionsObject

    Checkout SDK configuration options. See available options below

Element Options

PropType / Default
  • apiKeyString

    WhenThen API Client Token.

  • customerIdString

    WhenThen Customer ID.

  • isSavedCardCvcRequiredBoolean / false

    Ask the user to provide a CVC code for previously saved cards.

  • languageString | Object / en

    Checkout SDK messages language. Specify one of the built-in languages ( 'en’ , 'fr’) or provide an object with custom messages.

  • themeObject

    Custom Checkout SDK theme object. See available options below.

  • countriesArray<{name: string;code: string;}> / All countries

    The list of allowed billing address countries. Requires hideBillingAddress to be false.

    info icon
    Country code must be an ISO 3166-1 alpha-3 code.
  • hideBillingAddressBoolean / false

    Hide billing address section from the user.

  • allowSaveCardBoolean / true

    Allow the user to store the card in WhenThen Vault for future payments.

    info icon
    allowSaveCard option displays the Save card checkbox on the UI. If the user unchecks this option, the customerId will not be attached with the card token. Set to false to hide the checkbox from the UI and explicitly attach card tokens to the customer id passed on in the checkout option.
  • alternativePaymentMethodsAlternativePaymentMethod[] / [ ]

    Allow the user to checkout with an alternative payment method.

    See alternative payment methods for more details
  • supportedCardBrandsCardBrand[] / [ ]

    List of card brand icons to display on the checkout form

    See Card Brands for more details

    Default value:

    supportedCardBrands : [
      "VISA"
      "MASTERCARD" 
      "AMERICAN_EXPRESS"
      "DISCOVER"
      "DINERS"
      "JCB"
    ]
    

Integration

import WhenThenSdkLoader from '@whenthen/sdk-loader';

const options = {
  apiKey: 'CLIENT_TOKEN_XXX',
};

window.addEventListener('load', async () => {
  const checkoutSdk = await WhenThenSdkLoader.loadCheckoutSdkElement('#container', options);


  // Checkout form submit button
  const submitButtonElement = document.querySelector('#submitButton');

  checkoutSdk.on('change', (event) => {
    if (event.detail.isComplete) {
      submitButtonElement.removeAttribute('disabled');
    } else {
      submitButtonElement.setAttribute('disabled', 'disabled');
    }
  });

  checkoutSdk.on('error', (event) => console.error(event.detail.errors));

  submitButtonElement.addEventListener('click', async (event) => {
    event.preventDefault();

    checkoutSdk.disable();
    submitButtonElement.setAttribute('disabled', 'disabled');
    try {
      const { token, errors } = await checkoutSdk.tokenisePaymentMethod();
      if (!errors?.length) {
        // Complete payment using payment method token
      }
    } finally {
      checkoutSdk.enable();
      submitButtonElement.removeAttribute('disabled');
    }
  });
});

Once WhenThen Checkout SDK element is initialised - you can subscribe to the Checkout Element events. When checkout form is submitted - call tokenisePaymentMethod() SDK method to generate token which could be used to create a payment.

Element instance methods

PropArgument
  • on(eventType: string, callback: (event: CustomEvent) => void) => void

    Subscribe to the Checkout Element event.

    Returns an unsubscribe function.

  • mount(elementOrSelector: HTMLElement | string) => void

    Mounts the Checkout to the container element or the selector of the container element.

  • unmount() => void

    Unmounts the Checkout and resets all events subscriptions.

  • disable() => void

    Applies a disabled state to the Checkout such that user input is not accepted.

  • enable() => void

    Applies an enable state to the Checkout.

  • createCustomer(customerInput: CustomerInput) => Promise<CreateCustomerCheckoutResult>

    Create a customer.

    CreateCustomerCheckoutResult : {
      customerId: string;
      errors: Array<{ 
        type: string;
        message: string;
      }>;}
    
  • tokenisePaymentMethod() => Promise

    Tokenise payment method.

  • setErrorMessage(message: string | declineCode: string) => void

    Set error message to display on the UI. You can either pass DECLINE code or custom error message. if DECLINE code is passed, it's mapped against the Localisation options.

  • authorizePayment(authorizeRequestInput: AuthorizePaymentInput) => Promise<AuthorizePaymentResult>

    Create a payment.

Element SDK Events

Prop
  • change

    Triggered when data exposed by WhenThen Checkout SDK is changed. isComplete is true when all required fields are complete and there are no validation errors. value reflects the data entered into the Checkout form by the user. errors reflect the validation errors displayed inside the Checkout form.

    {
      isComplete: boolean;
      value: {
        card: CheckoutCard;
        billingAddress: BillingAddress;
      };
      errors: Array<{
        type: string;
        field: string;
        message: string;
      }>;
    }
  • error

    Triggered when an internal SDK error occurs.

    {
      errors: Array<{
        type: string;
        message: string;
      }>;
    }
  • paymentRequest

    Triggered when user clicks on an alternative payment method button. Returns payment method selected and payment data when available.

    {
      errors: Array<{
        paymentMethod: string;
        paymentData: GooglePayPaymentRequestPayload | undefined;
      }>;
    }

CheckoutCard

PropType
  • tokenString

    Card token.

  • cardNumberString

    Card number.

    info icon
    Previously saved card number is masked for security reasons.
  • billingNameString

    Billing name.

  • cardExpiryString

    Card expiry in MM/YY format.

  • cardCvcString

    Card CVC code.

    info icon
    CVC code is not required for previously saved cards if isSavedCardCvcRequired option is set to false (default).

BillingAddress

PropType
  • isSameBillingAddressBoolean

    The billing address is the same as the shipping address.

  • countryString

    Country ISO 3166-1 alpha-3 code.

    Requires isSameBillingAddress to be false.

  • zipString

    Zip/Postal code.

    Requires isSameBillingAddress to be false.

Alternative Payment Methods

PropType
  • klarnaobject
    {
       type: "klarna"
    }
  • paypalobject
    {
       type: "paypal"
    }
  • applepayobject

    See Apple Pay for apple pay options

     

    {
       type: "applepay"
       options: {...}
    }
  • googlepayobject

    See Google Pay for google pay options

     

    {
       type: "googlepay"
       options: {...}
    }

Card Brands

[
  "VISA",
  "MASTERCARD",
  "AMERICAN_EXPRESS",
  "DISCOVER",
  "DINERS",
  "MAESTRO",
  "UNIONPAY",
  "JCB",
  "CARTE_BANCAIRE",
  "DANKORT"
];

List of card brand icons to display on the checkout form. supportedCardBrands

Branding

const options = {
  apiKey: 'CLIENT_TOKEN_XXX',
  theme: {
    fontFamily: 'Helvetica Neue',
      fontSize: {
        primary: '14px',
        secondary: '12px',
      },
      borderType: 'square', // 'square' | 'round' | 'bottom'
      colors: {
        primary: '#000000',
        secondary: '#545A61',
        accent: '#4E40EF',
        accentContrast: '#FFFFFF',
        border: '#E6E9EC',
        borderFocused: '#000000',
        error: '#EC0B43',
      },
      borderRadius: '0', 
		  backgroundColor: '#ffffff', 
		  textColor: '#000000', 
		  lineHeight: '48px'
      variables: undefined,
      rules: undefined,
    },
  },
};

const checkoutSdk = WhenThenCheckoutSdk.loadCheckoutSdkElement('#container', options);

You can customise Checkout Form appearance using theme object.

Theme Rules and Variables

Use rules and variables to further customize the checkout form.

Variables

Variables are CSS variables that you can declare and use in your theme rules.

{
  theme: {
    ...,
    variables: {
        primaryColor: "#1D3557"
        secondaryColor: "#457B9D"
    }

    rules : {
        PayButton: `
            backgroundColor: var(--primaryColor);
            `
    }
  }
}

Rules

Rules allows you to apply CSS styles to checkout components. Target components by class names, with OR without the CSS class selector prefix - FieldContainer or .FieldContainer and specify the styles to apply. Supports all native CSS properties and nesting.

{
    theme: {
      ...,
      variables: {
          primaryColor: "#1D3557"
          secondaryColor: "#457B9D"
      }
  
      rules : {
        '.FieldContainer': `
              height: 40px;
              border-radius: 8px;
              backgroundColor: var(--primaryColor);
              
              &:hover {
                backgroundColor: var(--secondaryColor);
              }
          `
      }
    }
  }

Available Rules Classnames

PayButton: string | undefined;
PayButton__LoadingState: string | undefined;

PaymentErrorContainer: string | undefined;
PaymentErrorContainer__Label: string | undefined;
ErrorMessage: string | undefined;

SuccessStateContainer: string | undefined;
SuccessStateContainer__Content: string | undefined;
SuccessStateContainer__Content__Icon: string | undefined;
SuccessStateContainer__Content__Label: string | undefined;

GridColumn: string | undefined;
GridRow: string | undefined;

FieldContainer: string | undefined;
FieldContainer__CardNumber: string | undefined;
FieldContainer__BillingName: string | undefined;
FieldContainer__CardExpiry: string | undefined;
FieldContainer__CardCvc: string | undefined;
FieldContainer__BillingAddressCountry: string | undefined;
FieldContainer__BillingAddressPostalCode: string | undefined;

TextField: string | undefined;
TextField__CardNumber: string | undefined;
TextField__BillingName: string | undefined;
TextField__CardExpiry: string | undefined;
TextField__CardCvc: string | undefined;
TextField__BillingAddressPostalCode: string | undefined;

SelectField: string | undefined;
SelectField__Option: string | undefined;

SelectField__BillingAddressCountry: string | undefined;
SelectField__Option__BillingAddressCountry: string | undefined;

CheckboxFieldContainer: string | undefined;
CheckboxFieldContainer__InputContainer: string | undefined;
CheckboxFieldContainer__InputContainer__Icon: string | undefined;

IconContainer: string | undefined;
IconContainer__Front: string | undefined;
IconContainer__Front__Flipped: string | undefined;
IconContainer__Back: string | undefined;
IconContainer__Back__Flipped: string | undefined;

CardNumberContainer: string | undefined;
CardNumberIconContainer: string | undefined;

SavedCardsContainer: string | undefined;
SavedCardsContainer__ClearButton: string | undefined;

SavedCardsDropdown: string | undefined;
SavedCardsDropdown__Button: string | undefined;
SavedCardsDropdown__List: string | undefined;
SavedCardsDropdown__ListItem: string | undefined;

SavedCardsDropdown__ListItem__Divider: string | undefined;
SavedCardsDropdown__ListItem__CardBrandIcon: string | undefined;
SavedCardsDropdown__ListItem__CardNumber: string | undefined;
SavedCardsDropdown__ListItem__CardExpiry: string | undefined;

CheckoutContainer: string | undefined;

AlternativePaymentMethodsContainer: string | undefined;
DividerContainer: string | undefined;
DividerContainer__Divider: string | undefined;
DividerContainer__Label: string | undefined;

AlternativePaymentMethodButton: string | undefined;

AlternativePaymentMethodButton__Klarna: string | undefined;
AlternativePaymentMethodButton__Paypal: string | undefined;
AlternativePaymentMethodButton__ApplePay: string | undefined;
AlternativePaymentMethodButton__GooglePay: string | undefined;

AlternativePaymentMethodButton__IconContainer: string | undefined;
AlternativePaymentMethodButton__IconContainer__Klarna: string | undefined;
AlternativePaymentMethodButton__IconContainer__Paypal: string | undefined;
AlternativePaymentMethodButton__IconContainer__ApplePay: string | undefined;

AlternativePaymentMethodButton__Label: string | undefined;
AlternativePaymentMethodButton__Label__Klarna: string | undefined;
AlternativePaymentMethodButton__Label__Paypal: string | undefined;
AlternativePaymentMethodButton__Label__ApplePay: string | undefined;

SupportedCardBrandContainer: string | undefined;
SupportedCardBrandContainer__Icon: string | undefined;

Localisation

const options = {
  apiKey: 'CLIENT_TOKEN_XXX',
  language: 'en', // 'en' | 'fr' | Object
};

const checkoutSdk = WhenThenCheckoutSdk.loadCheckoutSdkElement('#container', options);

WhenThen Checkout SDK has built-in support for English and French.

const customLanguage = {
  'card.number.placeholder': '1234 1234 1234 1234',
  'card.number.aria-label': 'Card number',
  'card.number.errors.required': 'Card number is required',
  'card.number.errors.min-length': 'Minimum number of digits is 13',
  'card.number.errors.invalid-number': 'Invalid card number',

  'card.save.label': 'Save card',
  'card.saved-cards.choose-card.label': 'Choose card',
  'card.saved-cards.clear-card.label': 'Clear',
  'card.saved-cards.saved-card.aria-label': 'The card ending in',

  'card.billing-name.placeholder': 'Name on card',
  'card.billing-name.aria-label': 'Name on card',
  'card.billing-name.errors.required': 'Full name is required',
  'card.billing-name.errors.min-length': 'Full name is too short',

  'card.expiry.placeholder': 'MM / YY',
  'card.expiry.aria-label': 'Card expiration',
  'card.expiry.errors.required': 'Expiration date is required',
  'card.expiry.errors.pattern': 'Expiration date format is not valid (MM/YY)',
  'card.expiry.errors.expired': 'Your card is expired',

  'card.cvc.placeholder': 'CVC',
  'card.cvc.aria-label': 'Card CVC',
  'card.cvc.errors.required': 'Security code is required',
  'card.cvc.errors.min-length': 'Security code is too short',
  'card.cvc.errors.max-length': 'Security code is too long',

  'billing-address.same-as-shipping.label': 'Billing address is the same as shipping',

  'billing-address.country.placeholder': 'Country',
  'billing-address.country.aria-label': 'Country',
  'billing-address.country.errors.required': 'Country is required',

  'billing-address.zip.placeholder': 'Zip/Postal code',
  'billing-address.zip.aria-label': 'Zip/Postal code',
  'billing-address.zip.errors.required': 'Zip/Postal code is required',
  'billing-address.zip.errors.min-length': 'Zip/Postal code is too short',

  'pay-button.label': 'Pay',
  'pay-button.aria-label': 'Pay with card',

  'alternative-payment-methods.divider.label': 'OR',
  'alternative-payment-methods.paypal.label': 'PayPal',
  'alternative-payment-methods.paypal.aria-label': 'Pay with PayPal',
  'alternative-payment-methods.klarna.label': 'Klarna',
  'alternative-payment-methods.klarna.aria-label': 'Pay with Klarna',
  'alternative-payment-methods.applepay.label': 'Apple Pay',
  'alternative-payment-methods.applepay.aria-label': 'Pay with Apple Pay',

  'payment-success-state.label': 'Payment Succeeded',

  'error.invalid_cvc': 'Invalid CVC',
  'error.authorization_required': 'Authorization Required',
  'error.contact_card_issuer': 'Contact Card Issuer',
  'error.unsupported_card': 'Unsupported Card',
  'error.insufficient_funds': 'Insufficient Funds',
  'error.unsupported_currency': 'Unsupported Currency',
  'error.card_rejected': 'Card Rejected',
  'error.expired_card': 'Expired Card',
  'error.suspected_fraud': 'Suspected Fraud',
  'error.general_decline': 'General Decline',
  'error.incorrect_number': 'Incorrect Number',
  'error.incorrect_pin': 'Incorrect Pin',
  'error.invalid_address': 'Invalid Address',
  'error.invalid_card_or_account': 'Invalid Card or Account',
  'error.invalid_amount': 'Invalid Amount',
  'error.invalid_date': 'Invalid Date',
  'error.lost_restricted_or_stolen_card': 'Lost, Restricted or Stolen Card',
  'error.blocked_list': 'Blocked List',
  'error.not_permitted': 'Not Permitted',
  'error.offline_or_online_pin_required': 'Offline or Online Pin Required',
  'error.pin_retry_exceeded': 'Pin Retry Exceeded',
  'error.processing_error': 'Processing Error',
  'error.withdrawal_count_limit_exceeded': 'Withdrawal Count Limit Exceeded',
  'error.unknown': 'Unknown error',
  'error.fraud': 'Fraud',
  'error.three_d_secure': '3DS Failed',
  'error.custom_rule': 'Custom Rule',
};

const options = {
  apiKey: 'CLIENT_TOKEN_XXX',
  language: customLanguage
};

const checkoutSdk = WhenThenCheckoutSdk.loadCheckoutSdkElement('#container', options);

You can customize messages by providing a custom language object.

Saved Cards

const options = {
  apiKey: 'CLIENT_TOKEN_XXX',
  customerId: 'CUSTOMER_ID_XXX',
  isSavedCardCvcRequired: true,
};

const checkoutSdk = WhenThenCheckoutSdk.loadCheckoutSdkElement('#container', options);

To enabled saved cards experience - specify customerId configuration option. The user would have an option to use previously saved card securely stored inside WhenThen Vault or enter a new one.

Billing Address

const options = {
  apiKey: 'CLIENT_TOKEN_XXX',
  hideBillingAddress: false,
  // The list of allowed billing address countries
  countries: [
    { name: 'United States', code: 'USA' },
    { name: 'United Kingdom', code: 'GBR' },
    { name: 'Ireland', code: 'IRL' },
  ],
};

const checkoutSdk = WhenThenCheckoutSdk.loadCheckoutSdkElement('#container', options);

Hide billing address section or specify the list of allowed countries.

React Integration

import React, { FunctionComponent, useCallback, useRef, useState } from 'react';
  import {
    WhenThenCheckoutElement,
    WhenThenCheckoutElementForwardedRef,
    CheckoutChangeEventDetails,
    ErrorEventDetails,
    CheckoutSdkElementOptions,
    CheckoutPaymentRequestEventDetails
  } from '@whenthen/checkout-sdk-react';
  
  const options: CheckoutSdkElementOptions = {
    apiKey: 'CLIENT_TOKEN_XXX',
    customerId: 'CUSTOMER_ID_XXX',
    isSavedCardCvcRequired: true,
  };
  
  export interface CheckoutFormProps {}
  
  export const CheckoutForm: FunctionComponent<CheckoutFormProps> =
    () => {
      const sdkRef = useRef<WhenThenCheckoutElementForwardedRef>(null);
      const [isFormComplete, setIsFormComplete] = useState<boolean>(false);
      const [isLoaded, setIsLoaded] = useState<boolean>(false);
      const [isDisabled, setIsDisabled] = useState<boolean>(false);
  
      const handleChange = useCallback((details: CheckoutChangeEventDetails) => {
        setIsFormComplete(details.isComplete);
      }, []);
  
      const handleError = useCallback((details: ErrorEventDetails) => {
        console.error(details.errors);
      }, []);
  
      const handleLoaded = useCallback(() => {
        setIsLoaded(true);
      }, []);
  
      const handleSubmit = useCallback(
        async (event: React.MouseEvent<HTMLElement>) => {
          event.preventDefault();
  
          if (!sdkRef.current) {
            return;
          }
  
          setIsDisabled(true);
          try {
            const { token, errors } = await sdkRef.current.tokeniseCard();
            if (!errors?.length) {
              // Complete payment using card token
            }       
          } finally {
            setIsDisabled(false);
          }
        },
        []
      );
  
      const handlePaymentRequest = ({paymentMethod, paymentData}: CheckoutPaymentRequestEventDetails) => {
        switch(paymentMethod) {
          case "klarna":
            // handle klarna
          case "googlepay":
            // handle googlepay
        }
      }
  
      return (
        <form noValidate>
          <WhenThenCheckoutElement
            ref={sdkRef}
            disabled={isDisabled}
            options={options}
            onChange={handleChange}
            onError={handleError}
            onLoaded={handleLoaded}
            onPaymentRequest={handlePaymentRequest}
          />
  
          <button
            type="submit"
            onClick={handleSubmit}
            disabled={!isLoaded || isDisabled || !isFormComplete}
          >
            Submit
          </button>
        </form>
      );
    };
  
  CheckoutForm.displayName = 'CheckoutForm';
  CheckoutForm.propTypes = {};

WhenThenCheckout Element Props

PropType
  • optionsObject

    Checkout SDK configuration options. See available options.

    info icon
    Any change to options property resets the form.
  • disabledBoolean

    Applies a disabled state to the Checkout Component such that user input is not accepted.

  • onLoaded() => void

    Triggered when WhenThen Checkout SDK is loaded.

  • onChange(details: CheckoutChangeEventDetails) => void

    Triggered when data exposed by WhenThen Checkout SDK is changed.

    CheckoutChangeEventDetails : {
      isComplete: boolean;
      value: {
        card: CheckoutCard;  
        billingAddress: BillingAddress; 
      };
      errors: Array<{ 
        type: string;
        field: string;
        message: string;
      }>;}
    
  • onError(details: ErrorEventDetails) => void

    Triggered when an internal SDK error occurs.

            ErrorEventDetails {
      errors: Array<{ 
        type: string;
        message: string;
      }>;
    }
  • onPaymentRequest(details: CheckoutPaymentRequestEventDetails) => void

    Triggered when user clicks on an alternative payment method button. Returns payment method selected and payment data when available.

            CheckoutPaymentRequestEventDetails {
       paymentMethod: string;
       paymentData: GooglePayPaymentRequestPayload | undefined;
    }

WhenThenCheckout Element forwarded ref

PropType
  • tokenisePaymentMethod() => Promise

    Tokenise payment method.

  • createCustomer(customerInput: CustomerInput) => Promise<CreateCustomerCheckoutResult>

    Create a customer.

    CreateCustomerCheckoutResult : {
      customerId: string;
      errors: Array<{ 
        type: string;
        message: string;
      }>;}
    
  • authorizePayment(authorizeRequestInput: AuthorizePaymentInput) => Promise<AuthorizePaymentResult>

    Create a payment

  • setErrorMessage(errorMessage: string | declineCode: string) => void

    Set error message to display on the UI. You can either pass DECLINE code or custom error message. if DECLINE code is passed, it's mapped against the Localisation options.