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.
Before you start configuring your checkout, make sure you follow our Getting Started guide
<!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>
import WhenThenSdkLoader from '@whenthen/sdk-loader';
const options = {
apiKey: 'CLIENT_TOKEN_XXX',
};
window.addEventListener('load', async () => {
const checkoutSdk = await WhenThenSdkLoader.loadCheckoutSdkElement('#container', options);
});
elementOrSelector
HTMLElement | String ﹡ The container element or the selector of the container element.
options
Object ﹡ Checkout SDK configuration options. See available options below
apiKey
String ﹡ WhenThen API Client Token.
customerId
String WhenThen Customer ID.
isSavedCardCvcRequired
Boolean / falseAsk the user to provide a CVC code for previously saved cards.
language
String | Object / enCheckout SDK messages language. Specify one of the built-in languages ( 'en’
, 'fr’
) or provide an object with custom messages.
theme
Object Custom Checkout SDK theme object. See available options below.
countries
Array<{name: string;code: string;}> / All countriesThe list of allowed billing address countries. Requires hideBillingAddress
to be false
.
hideBillingAddress
Boolean / falseHide billing address section from the user.
allowSaveCard
Boolean / trueAllow the user to store the card in WhenThen Vault for future payments.
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.alternativePaymentMethods
AlternativePaymentMethod[] / [ ]Allow the user to checkout with an alternative payment method.
See alternative payment methods for more detailssupportedCardBrands
CardBrand[] / [ ]List of card brand icons to display on the checkout form
See Card Brands for more detailsDefault value:
supportedCardBrands : [
"VISA"
"MASTERCARD"
"AMERICAN_EXPRESS"
"DISCOVER"
"DINERS"
"JCB"
]
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');
}
});
});
on
(eventType: string, callback: (event: CustomEvent) => void) => voidSubscribe to the Checkout Element event.
Returns an unsubscribe function.
mount
(elementOrSelector: HTMLElement | string) => voidMounts the Checkout to the container element or the selector of the container element.
unmount
() => voidUnmounts the Checkout and resets all events subscriptions.
disable
() => voidApplies a disabled state to the Checkout such that user input is not accepted.
enable
() => voidApplies an enable state to the Checkout.
createCustomer
(customerInput: CustomerInput) => Promise<CreateCustomerCheckoutResult>Create a customer.
CreateCustomerCheckoutResult : {
customerId: string;
errors: Array<{
type: string;
message: string;
}>;}
tokenisePaymentMethod
() => PromiseTokenise payment method.
setErrorMessage
(message: string | declineCode: string) => voidSet 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.
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;
}>;
}
token
String Card token.
cardNumber
String Card number.
billingName
String Billing name.
cardExpiry
String Card expiry in MM/YY
format.
cardCvc
String Card CVC code.
isSavedCardCvcRequired
option is set to false
(default).isSameBillingAddress
Boolean The billing address is the same as the shipping address.
country
String Country ISO 3166-1 alpha-3 code.
Requires isSameBillingAddress
to be false
.
zip
String Zip/Postal code.
Requires isSameBillingAddress
to be false
.
klarna
object {
type: "klarna"
}
paypal
object {
type: "paypal"
}
applepay
object googlepay
object [
"VISA",
"MASTERCARD",
"AMERICAN_EXPRESS",
"DISCOVER",
"DINERS",
"MAESTRO",
"UNIONPAY",
"JCB",
"CARTE_BANCAIRE",
"DANKORT"
];
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);
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;
const options = {
apiKey: 'CLIENT_TOKEN_XXX',
language: 'en', // 'en' | 'fr' | Object
};
const checkoutSdk = WhenThenCheckoutSdk.loadCheckoutSdkElement('#container', options);
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);
const options = {
apiKey: 'CLIENT_TOKEN_XXX',
customerId: 'CUSTOMER_ID_XXX',
isSavedCardCvcRequired: true,
};
const checkoutSdk = WhenThenCheckoutSdk.loadCheckoutSdkElement('#container', options);
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);
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 = {};
options
Object Checkout SDK configuration options. See available options.
disabled
Boolean 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;
}
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.