Implement callbacks to customise your card payment flow for web.
Components emit events based on user interaction or validation. You can use these to implement callback functions, which allow you to inject your own business logic and user experience customisations into the payment flow at critical moments. They ensure that while the SDK handles the complex technical aspects of payment processing, you retain full control over the customer experience and can seamlessly integrate payments into your broader business workflows and systems.
Callbacks enable you to:
- Validate business rules before payments proceed.
- Display custom error, failure, or success messages.
- Tailor user interfaces to match your brand's look and feel.
- Integrate with your own systems for fraud detection or customer management.
- Control exactly how your customers experience both successful and failed transactions.
- Handle card-specific requirements like 3DS authentication and tokenisation.
- Manage saved payment methods and customer billing information.
All events are optional and can be mixed and matched based on your business needs.
The following tables lists all events supported by the different pre-built components.
Event | Billing address | Card-on-file | Click-once | New card |
---|---|---|---|---|
onBlur | ||||
onCardBrandCannotRecognised | ||||
onCardBrandDetected | ||||
onChange | ||||
onClick | ||||
onCollectEnd | ||||
onCollectStart | ||||
onCvcEntered | ||||
onDeleteTokenFailed | ||||
onDeleteTokenSuccess | ||||
onFocus | ||||
onGetFingerprintResult | ||||
onOnceCardClick | ||||
onPostAuthentication | ||||
onPostAuthorisation | ||||
onPostInitiateAuthentication | ||||
onPostTokenisation | ||||
onPreAuthentication | ||||
onPreAuthorisation | ||||
onPreDeleteToken | ||||
onPreInitiateAuthentication | ||||
onPreRenderTokens | ||||
onPreTokenisation | ||||
onRetrieveTokensFailed | ||||
onSubmitError | ||||
onUpdateTokenFailed | ||||
onUpdateTokenSuccess | ||||
onValidation | ||||
onValidationPassed | ||||
onValidationFailed | ||||
tokenItemBuilder | ||||
tokenLabelBuilder |
This callback is triggered after the payment transaction has been processed and authorisation has been completed (successfully or unsuccessfully).
You can use it to:
- Redirect customers to a success page with order confirmation.
- Update stock levels for purchased items.
- Send order confirmation emails to customers.
- Record successful transactions for business intelligence.
Event data | Description |
---|---|
submitResult BaseSubmitResult | The payment processing result from PXP's backend. |
submitResult.transactionId string | The unique identifier for the transaction. |
submitResult.state string | The transaction state: Authorised , Declined , Failed , or Pending . |
submitResult.timestamp string | The date and time of the transaction, in ISO 8601 format. |
submitResult.correlationId string | The correlation ID for tracking the transaction across systems. |
submitResult.cardVerificationCodeResult string | The result of the CVC verification (if applicable). |
submitResult.addressVerificationServiceResult string | The result of the address verification (if applicable). |
const cardSubmit = sdk.create('card-submit', {
onPostAuthorisation: (submitResult) => {
if (submitResult.state === 'Authorised') {
// Payment successful
console.log('Payment authorised successfully');
console.log('Transaction ID:', submitResult.transactionId);
// Update inventory
updateInventory(submitResult.transactionId);
// Send confirmation email
sendConfirmationEmail(customerEmail, submitResult.transactionId);
// Track analytics
trackPurchase(submitResult.transactionId, submitResult.correlationId);
// Redirect to success page
window.location.href = `/payment-success?txn=${submitResult.transactionId}`;
} else if (submitResult.state === 'Declined') {
console.error('Payment declined:', submitResult);
handleDeclinedPayment(submitResult);
} else if (submitResult.state === 'Failed') {
console.error('Payment failed:', submitResult);
showErrorMessage('Payment failed. Please try again or use a different payment method.');
} else if (submitResult.state === 'Pending') {
console.log('Payment pending further processing');
showMessage('Payment is being processed. You will receive confirmation shortly.', 'info');
}
}
});
This callback is triggered before the transaction authorisation, allowing you to provide additional transaction data or perform validation.
You can use it to:
- Integrate with Kount or other fraud detection services.
- Perform AVS (Address Verification System) checks.
- Enable 3DS authentication for specific transactions.
- Apply business rules based on transaction amount or customer history.
- Check product availability before processing payment.
Parameter | Description |
---|---|
data PreAuthorizationData | Contains the tokenisation result and authentication data (if applicable). |
data.initiateIntegratedSuccessAuthenticationResult InitiateIntegratedSuccessAuthenticationResult | The 3DS authentication result (null for payouts or when 3DS isn't performed). |
data.initiateIntegratedSuccessAuthenticationResult.authenticationId string | The unique identifier for the authentication session. |
data.initiateIntegratedSuccessAuthenticationResult.transactionId string | The transaction ID associated with authentication. |
data.initiateIntegratedSuccessAuthenticationResult.cavv string | The Cardholder Authentication Verification Value. |
data.initiateIntegratedSuccessAuthenticationResult.eci string | The Electronic Commerce Indicator. |
data.initiateIntegratedSuccessAuthenticationResult.version string | The 3DS protocol version used. |
data.cardTokenData CardTokenData | Token data for payout transactions or card-on-file usage (null for new card payments). |
data.cardTokenData.gatewayTokenId string | The token ID from the payment gateway. |
data.cardTokenData.schemeTokenId string | The token ID from the card scheme. |
data.cardTokenData.maskedPrimaryAccountNumber string | The masked card number for display. |
data.cardTokenData.expiryDate string | The ard expiry date in MM/YY format. |
data.cardTokenData.cardScheme string | The card scheme (Visa, MasterCard, etc.). |
data.cardTokenData.cvc string | The CVC value (if provided for token usage). |
threeDSAuthenticationData ThreeDSAuthenticationData | 3DS authentication data from the previous authentication step (optional). |
threeDSAuthenticationData.authenticationId string | The authentication session identifier. |
threeDSAuthenticationData.cavv string | The Cardholder Authentication Verification Value. |
threeDSAuthenticationData.eci string | The Electronic Commerce Indicator value. |
threeDSAuthenticationData.xid string | The transaction identifier for 3DS 1.0. |
threeDSAuthenticationData.version string | The 3DS protocol version (1.0, 2.1, 2.2). |
threeDSAuthenticationData.dsTransId string | The Directory Server Transaction ID for 3DS 2.0+. |
threeDSAuthenticationData.acsTransId string | The ACS Transaction ID for 3DS 2.0+. |
const cardSubmit = sdk.create('card-submit', {
onPreAuthorisation: async (data, threeDSAuthenticationData) => {
console.log('Pre-authorisation data:', data);
// Perform pre-payment validation
const deviceSessionId = await getKountSessionId();
const isHighRisk = await checkCustomerRiskProfile();
const customerTier = await getCustomerTier();
// Get billing address if AVS is enabled
const billingAddress = await getBillingAddress();
return {
addressVerification: billingAddress ? {
countryCode: billingAddress.countryCode,
houseNumberOrName: billingAddress.address,
postalCode: billingAddress.postalCode,
city: billingAddress.city,
state: billingAddress.state
} : undefined,
riskScreeningData: {
deviceSessionId: deviceSessionId,
performRiskScreening: true,
customData: {
customerTier: customerTier,
orderType: 'ecommerce',
previousTransactionCount: await getPreviousTransactionCount(),
riskScore: isHighRisk ? 'high' : 'low'
}
},
threeDSecureData: threeDSAuthenticationData ? {
authenticationId: threeDSAuthenticationData.authenticationId,
cavv: threeDSAuthenticationData.cavv,
eci: threeDSAuthenticationData.eci,
xid: threeDSAuthenticationData.xid,
version: threeDSAuthenticationData.version
} : undefined
};
}
});
This callback is triggered before card tokenisation begins, allowing you to control whether tokenisation should proceed.
You can use it to:
- Validate card information before tokenisation.
- Check if the customer wants to save their payment method.
- Apply business rules for token storage.
- Implement custom security checks.
This callback receives no parameters.
const cardSubmit = sdk.create('card-submit', {
onPreTokenisation: () => {
// Check if customer consented to save card
const saveCardConsent = document.getElementById('save-card-checkbox')?.checked;
if (!saveCardConsent) {
console.log('Customer declined to save card - skipping tokenisation');
return false;
}
// Additional validation
const isValidForStorage = validateCardForStorage();
if (!isValidForStorage) {
console.log('Card not suitable for storage - skipping tokenisation');
return false;
}
console.log('Proceeding with card tokenisation');
return true;
}
});
This callback is triggered after card tokenisation completes with the tokenisation result.
You can use it to:
- Store the token ID for future use.
- Update the user interface to show saved payment methods.
- Link the token to the customer's account.
- Log tokenisation events for analytics.
Parameter | Description |
---|---|
tokenData CardTokenizationResult | The tokenisation result containing token information. |
tokenData.gatewayTokenId string | The unique identifier for the tokenised card. |
tokenData.maskedPrimaryAccountNumber string | The masked card number for display purposes. |
tokenData.scheme string | The card scheme (Visa, MasterCard, etc.). |
tokenData.expiryDate string | The card expiry date. |
const cardSubmit = sdk.create('card-submit', {
onPostTokenisation: (tokenData) => {
console.log('Card tokenised successfully:', tokenData);
// Store token for future use
saveTokenToCustomerAccount({
tokenId: tokenData.gatewayTokenId,
maskedNumber: tokenData.maskedPrimaryAccountNumber,
scheme: tokenData.scheme,
expiryDate: tokenData.expiryDate,
customerId: getCurrentCustomerId()
});
// Update UI to show saved card
updateSavedPaymentMethodsUI(tokenData);
// Track tokenisation event
trackEvent('card-tokenized', {
scheme: tokenData.scheme,
timestamp: new Date().toISOString()
});
// Show success message
showMessage('Payment method saved successfully', 'success');
}
});
This callback is triggered when the input loses focus.
You can use it to:
- Validate field data when user moves to next field.
- Show field-specific help or validation messages.
- Track user interaction patterns for UX analytics.
- Auto-format field values on blur.
Parameter | Description |
---|---|
event Event | The blur event object containing target and field information. |
event.type string | The event type (always blur ). |
event.target HTMLInputElement | The input element that lost focus. |
event.target.value string | The current value of the field. |
event.target.id string | The field identifier (e.g., card-number , card-expiry-date ). |
event.target.name string | The field name attribute. |
event.target.validity ValidityState | The HTML5 validation state of the field. |
event.target.validity.valid boolean | Whether the field passes HTML5 validation. |
event.target.validity.valueMissing boolean | Whether a required field is empty. |
event.currentTarget HTMLInputElement | The element that the event listener is attached to. |
event.timestamp number | The date and time when the event occurred. |
const cardNumberComponent = sdk.create('card-number', {
onBlur: (event) => {
console.log('Card number field blurred:', event.target.value);
// Validate card number on blur
if (event.target.value) {
const isValid = validateCardNumber(event.target.value);
if (!isValid) {
showFieldError('card-number', 'Please enter a valid card number');
} else {
clearFieldError('card-number');
}
}
// Track field interaction
trackFieldInteraction('card-number', 'blur', {
hasValue: !!event.target.value,
timestamp: new Date().toISOString()
});
}
});
This callback is triggered when the card number input changes, but the entered digits don't match any known card brand patterns.
You can use it to:
- Display appropriate error messages for unsupported card types.
- Guide users to use supported payment methods.
- Log attempts to use unsupported card brands for analytics.
- Redirect users to alternative payment options.
Parameter | Description |
---|---|
event CustomEvent | The card brand recognition failure event object. |
event.type string | The event type (always cardbrandcannotrecognised ). |
event.target HTMLInputElement | The card number input field. |
event.target.value string | The current card number value that couldn't be recognised. |
event.target.selectionStart number | The current cursor/selection start position. |
event.target.selectionEnd number | The current cursor/selection end position. |
event.detail object | Additional details about the recognition failure. |
event.detail.inputLength number | The length of the current input value. |
event.detail.attempts number | The number of recognition attempts made. |
event.detail.lastKnownBrand string | The last successfully detected brand (if any). |
event.detail.supportedBrands array | Array of the card brands you support. |
event.detail.inputPattern string | The current input pattern (first 6 digits or BIN). |
const cardNumberComponent = sdk.create('card-number', {
onCardBrandCannotRecognised: (event) => {
console.log('Card brand could not be recognised for:', event.target.value);
// Show error message for unsupported card
showFieldError('card-number', 'This card type is not supported. Please use Visa, MasterCard, or American Express.');
// Log unsupported card attempt
trackEvent('unsupported-card-attempted', {
cardNumberPrefix: event.target.value.substring(0, 6),
timestamp: new Date().toISOString()
});
// Show alternative payment methods
showAlternativePaymentMethods();
// Disable submit button until valid card is entered
disableSubmitButton();
}
});
This callback is triggered when the card number input changes and a recognised card brand (e.g., Visa, MasterCard) is detected from the input value.
You can use it to:
- Update the card brand logo display in real-time.
- Apply brand-specific validation rules or formatting.
- Show relevant rewards or benefits for the detected card.
- Enable or disable certain features based on the card brand.
Parameter | Description |
---|---|
event CustomEvent | The card brand detection event object. |
event.type string | The event type (always cardbranddetected ). |
event.target HTMLInputElement | The card number input field. |
event.target.value string | The current card number value. |
event.detail object | Enhanced card brand detection details. |
event.detail.cardBrand object | The detected card brand information. |
event.detail.cardBrand.brand string | The card brand identifier (e.g., visa , mastercard ). |
event.detail.cardBrand.displayName string | The user-friendly brand name (e.g., Visa , MasterCard ). |
event.detail.cardBrand.type string | The card type (e.g., credit , debit , prepaid ). |
event.detail.cardBrand.category string | The card category (e.g., consumer , business , corporate ). |
event.detail.cardBrand.logo string | The URL to the card brand logo image. |
event.detail.cardBrand.colors object | The brand colour scheme for UI theming. |
event.detail.cardBrand.colors.primary string | The primary brand colour (hex code). |
event.detail.cardBrand.colors.secondary string | The secondary brand colour (hex code). |
event.detail.cardBrand.cardNumberLength number | The expected card number length for this brand. |
event.detail.cardBrand.cvcLength number | The expected CVC length for this brand (3 or 4). |
event.detail.cardBrand.supportedCountries array | Array of country codes where this brand is supported. |
event.detail.isCardBrandAccept boolean | Whether this card brand is accepted by you. |
event.detail.confidence number | The confidence level of the brand detection (0 -1 ). |
event.detail.alternativeBrands array | Array of possible alternative brand matches. |
const cardNumberComponent = sdk.create('card-number', {
onCardBrandDetected: (event) => {
const cardBrand = event.detail.cardBrand;
const isAccepted = event.detail.isCardBrandAccept;
console.log(`Card brand detected: ${cardBrand.brand}`, isAccepted);
// Update card brand logo
updateCardBrandLogo(cardBrand.brand);
// Check if card brand is accepted
if (!isAccepted) {
showFieldError('card-number', `${cardBrand.displayName} cards are not accepted. Please use a different card.`);
disableSubmitButton();
} else {
clearFieldError('card-number');
enableSubmitButton();
// Show brand-specific benefits
showCardBrandBenefits(cardBrand.brand);
}
// Apply brand-specific validation
applyBrandSpecificValidation(cardBrand.brand);
// Track card brand usage
trackEvent('card-brand-detected', {
brand: cardBrand.brand,
accepted: isAccepted,
timestamp: new Date().toISOString()
});
}
});
This callback is triggered when the input value changes in one or more fields.
You can use it to:
- Update UI elements based on field values in real-time.
- Perform progressive validation as users type.
- Calculate and display dynamic totals or fees.
- Enable or disable form elements based on input values.
Parameter | Description |
---|---|
event CustomEvent | The input change event object with enhanced properties. |
event.type string | The event type (always change ). |
event.target HTMLInputElement | The input element that changed. |
event.target.value string | The current value of the field. |
event.target.name string | The field name identifier (e.g., cardNumber , expiryDate ). |
event.target.id string | The field ID attribute. |
event.detail object | Enhanced event details provided by the SDK. |
event.detail.isValid boolean | Whether the current field value is valid (if validation is enabled). |
event.detail.isEmpty boolean | Whether the field is empty. |
event.detail.isComplete boolean | Whether the field is completely filled (i.e., meets the expected length). |
event.detail.cardBrand object | Card brand information (for card number fields only). |
event.detail.cardBrand.brand string | The detected card brand (e.g., visa , mastercard ). |
event.detail.cardBrand.displayName string | The user-friendly brand name (e.g., Visa , MasterCard ). |
event.detail.cardBrand.logo string | The URL to the card brand logo image. |
event.detail.cardBrand.cvcLength number | The expected CVC length for this card brand (3 or 4). |
event.detail.formattedValue string | The formatted display value (with spaces, dashes, etc.). |
event.detail.errors array | Array of validation error objects (if validation failed). |
event.detail.errors[].code string | The error code for programmatic handling. |
event.detail.errors[].message string | A human-readable error message. |
const cardNumberComponent = sdk.create('card-number', {
onChange: (event) => {
console.log('Card number changed:', event.target.value);
// Update card brand display
if (event.detail.cardBrand) {
updateCardBrandDisplay(event.detail.cardBrand);
}
// Progressive validation
if (event.target.value.length >= 4) {
const isValid = event.detail.isValid;
if (isValid) {
clearFieldError('card-number');
showFieldSuccess('card-number');
} else {
showFieldError('card-number', 'Please enter a valid card number');
}
}
// Enable submit button when all fields are filled
checkFormCompletion();
// Track input progress
trackFieldProgress('card-number', {
length: event.target.value.length,
isValid: event.detail.isValid,
timestamp: new Date().toISOString()
});
}
});
const cardExpiryComponent = sdk.create('card-expiry-date', {
onChange: (event) => {
console.log('Expiry date changed:', event.target.value);
// Check for near-expiry warnings
if (event.detail.isValid) {
const expiryDate = new Date(event.target.value);
const now = new Date();
const monthsUntilExpiry = (expiryDate.getFullYear() - now.getFullYear()) * 12 +
(expiryDate.getMonth() - now.getMonth());
if (monthsUntilExpiry <= 1) {
showWarning('Your card expires soon. Please ensure it will be valid when your payment is processed.');
}
}
}
});
This callback is triggered when the submit button is clicked, before any payment processing begins.
You can use it to:
- Perform final form validation before payment processing.
- Show loading states or disable the button to prevent double-clicks.
- Track conversion funnel progression for analytics.
- Execute pre-payment business logic or confirmations.
Parameter | Description |
---|---|
event MouseEvent | The click event object from the submit button. |
event.type string | The event type (always click ). |
event.target HTMLButtonElement | The submit button element that was clicked. |
event.target.disabled boolean | Whether the button is currently disabled. |
event.target.textContent string | The button's text content. |
event.target.form HTMLFormElement | The form element containing the button (if any). |
event.currentTarget HTMLButtonElement | The element the event listener is attached to. |
event.clientX number | The X coordinate of the mouse pointer relative to the viewport. |
event.clientY number | The Y coordinate of the mouse pointer relative to the viewport. |
event.button number | Which mouse button was pressed (0 = left, 1 = wheel, 2 = right). |
event.ctrlKey boolean | Whether the Ctrl key was held during the click. |
event.shiftKey boolean | Whether the Shift key was held during the click. |
event.altKey boolean | Whether the Alt key was held during the click. |
event.metaKey boolean | Whether the Meta key (Cmd on Mac) was held during the click. |
event.timeStamp number | The time when the event occurred. |
event.preventDefault function | Method to prevent the default submission behaviour. |
event.stopPropagation function | Method to stop the event from bubbling up. |
const cardSubmit = sdk.create('card-submit', {
onClick: (event) => {
console.log('Submit button clicked');
// Track the payment attempt
trackEvent('payment-attempt-started', {
paymentMethod: 'card',
timestamp: new Date().toISOString(),
amount: getCurrentAmount(),
currency: getCurrentCurrency()
});
// Perform final validation
const validationErrors = performFinalValidation();
if (validationErrors.length > 0) {
event.preventDefault();
showValidationErrors(validationErrors);
return;
}
// Check inventory one final time
const inventoryCheck = checkInventoryAvailability();
if (!inventoryCheck.available) {
event.preventDefault();
showError('Some items in your cart are no longer available. Please review your order.');
return;
}
// Show loading state
showSubmitLoading(true);
event.target.disabled = true;
// Optional: Show confirmation dialog for high-value transactions
const amount = getCurrentAmount();
if (amount > 1000) {
const confirmed = confirm(`Please confirm your payment of ${formatCurrency(amount)}`);
if (!confirmed) {
event.preventDefault();
showSubmitLoading(false);
event.target.disabled = false;
return;
}
}
// Log that payment is proceeding
console.log('Payment processing initiated');
}
});
This callback is triggered when device fingerprinting and data collection ends.
You can use it to:
- Hide loading indicators shown during data collection.
- Log data collection completion for debugging.
- Proceed to the next step in the payment flow.
- Track data collection performance metrics.
Parameter | Description |
---|---|
data object | The data collection result object. |
data.success boolean | Whether data collection completed successfully. |
data.sessionId string | The session ID used for data collection. |
data.fingerprintData string | The collected device fingerprint data (if successful). |
data.provider string | The fraud detection provider used (e.g., kount ). |
data.duration number | The time taken for data collection in milliseconds. |
data.startTime number | The date and time when collection started. |
data.endTime number | The date and time when collection completed. |
data.dataPoints object | The summary of collected data points. |
data.dataPoints.deviceInfo boolean | Whether device information was collected. |
data.dataPoints.browserInfo boolean | Whether browser information was collected. |
data.dataPoints.networkInfo boolean | Whether network information was collected. |
data.dataPoints.behavioralInfo boolean | Whether behavioural patterns were collected. |
data.error Error | The error object if data collection failed (optional). |
data.error.code string | The error code for programmatic handling. |
data.error.message string | A human-readable error description. |
data.error.provider string | The provider that generated the error. |
data.retryAttempts number | The number of retry attempts made during collection. |
data.fallbackUsed boolean | Whether fallback collection methods were used. |
const cardSubmit = sdk.create('card-submit', {
onCollectEnd: (data) => {
console.log('Data collection completed:', data);
// Hide loading indicator
hideMessage();
hideDataCollectionSpinner();
// Track collection metrics
trackEvent('device-data-collection-completed', {
success: data.success,
duration: data.duration,
timestamp: new Date().toISOString()
});
if (data.success) {
console.log('Device fingerprinting successful');
// Store fingerprint data for fraud detection
storeFingerprintData(data.fingerprintData);
// Enable submit button now that data collection is complete
enableSubmitButton();
// Show completion indicator
showSuccessMessage('Security check completed', 2000);
} else {
console.warn('Data collection failed:', data.error);
// Handle collection failure - continue without fingerprinting
logError('fingerprint-collection-failed', {
error: data.error?.message,
duration: data.duration
});
// Still allow payment to proceed (fingerprinting is optional)
enableSubmitButton();
showWarningMessage('Security check unavailable - payment will proceed normally');
}
}
});
This callback is triggered when device fingerprinting and data collection begins.
You can use it to:
- Show loading indicators to inform users about the security process.
- Track the start of data collection for performance monitoring.
- Display educational messages about fraud prevention.
- Initialise any UI elements related to the collection process.
Parameter | Description |
---|---|
data object | The data collection initialisation object. |
data.provider string | The fraud detection provider (e.g., kount ). |
data.sessionId string | The session ID for the data collection process. |
data.timeout number | The maximum time allowed for data collection, in milliseconds. |
data.startTime number | The date and time when collection is starting. |
data.config object | Provider-specific configuration settings. |
data.config.merchantId string | The merchant identifier for the fraud detection service. |
data.config.environment string | The environment setting. |
data.config.version string | The provider SDK version being used. |
data.dataTypes array | The types of data to be collected (e.g., ['device', 'browser', 'network'] ). |
data.retryConfig object | The retry configuration for failed collection attempts. |
data.retryConfig.maxAttempts number | The maximum number of retry attempts. |
data.retryConfig.backoffMs number | The backoff time between retries in milliseconds. |
data.fallbackEnabled boolean | Whether fallback collection methods are enabled. |
const cardSubmit = sdk.create('card-submit', {
onCollectStart: (data) => {
console.log('Data collection started:', data);
// Show informative loading message
showMessage('Performing security check...', 'info');
showDataCollectionSpinner();
// Track collection start
trackEvent('device-data-collection-started', {
provider: data.provider,
sessionId: data.sessionId,
timeout: data.timeout,
timestamp: new Date().toISOString()
});
// Disable submit button during collection
disableSubmitButton();
// Show educational tooltip about fraud prevention
showTooltip('security-info',
'We\'re performing a quick security check to protect against fraud. This helps keep your payment safe.');
// Set up timeout warning
const warningTime = data.timeout * 0.8; // Warn at 80% of timeout
setTimeout(() => {
if (!isDataCollectionComplete()) {
showWarningMessage('Security check taking longer than expected...');
}
}, warningTime);
// Log provider-specific information
if (data.provider === 'kount') {
console.log('Kount fraud detection initiated with session:', data.sessionId);
} else if (data.provider === 'threatmetrix') {
console.log('ThreatMetrix profiling started with session:', data.sessionId);
}
}
});
This callback is triggered when a customer enters a CVC value in the click-once component's CVC field.
You can use it to:
- Enable the submit button when CVC is provided for saved cards.
- Perform real-time CVC validation.
- Track security code entry for analytics.
- Show completion indicators for the payment form.
Parameter | Description |
---|---|
data object | The CVC entry event data. |
data.isValid boolean | Whether the entered CVC is valid for the card type. |
data.cvcValue string | The masked CVC value (e.g., '' or '*'). |
data.cvcLength number | The length of the entered CVC. |
data.expectedLength number | The expected CVC length for this card brand. |
data.cardType string | The type of card the CVC was entered for (e.g., visa , amex ). |
data.cardBrand object | Detailed card brand information. |
data.cardBrand.displayName string | The user-friendly brand name (e.g., Visa , American Express ). |
data.cardBrand.requiresCvc boolean | Whether this card brand typically requires CVC. |
data.maskedCardNumber string | The masked card number associated with the CVC. |
data.tokenId string | The token ID of the saved card (for click-once components). |
data.validationErrors array | Array of validation error objects (if validation failed). |
data.validationErrors[].code string | The error code for programmatic handling. |
data.validationErrors[].message string | A human-readable error message. |
data.inputSource string | How the CVC was entered (e.g., keyboard ). |
data.timeTaken number | The time taken to enter the CVC, in milliseconds. |
const clickOnceComponent = sdk.create('click-once', {
onCvcEntered: (data) => {
console.log('CVC has been entered for card:', data.maskedCardNumber);
// Validate CVC format
if (data.isValid) {
console.log('Valid CVC entered');
// Clear any previous errors
clearFieldError('cvc');
// Show success indicator
showFieldSuccess('cvc');
// Enable submit button
enableSubmitButton();
// Track successful CVC entry
trackEvent('cvc-entered-valid', {
cardType: data.cardType,
maskedCardNumber: data.maskedCardNumber,
timestamp: new Date().toISOString()
});
// Show payment ready indicator
showPaymentReadyMessage();
} else {
console.log('Invalid CVC entered');
// Show validation error
showFieldError('cvc', 'Please enter a valid security code');
// Keep submit button disabled
disableSubmitButton();
// Track invalid CVC attempts
trackEvent('cvc-entered-invalid', {
cardType: data.cardType,
timestamp: new Date().toISOString()
});
}
// Update UI to reflect CVC completion
updateFormCompletionStatus();
}
});
This callback is triggered when a card token deletion request fails, for example due to a network error or authorisation issues.
You can use it to:
- Display user-friendly error messages for deletion failures.
- Log deletion errors for debugging and monitoring.
- Offer retry options for failed deletions.
- Track failure rates for saved payment method management.
Parameter | Description |
---|---|
data DeleteCardTokenResponseFailed | The failed deletion response object. |
data.error object | The error details for the failed deletion. |
data.error.message string | A human-readable error message. |
data.error.code string | The specific error code for programmatic handling. |
data.tokenId string | The ID of the token that failed to be deleted. |
data.correlationId string | The correlation ID for tracking the request. |
const cardOnFileComponent = sdk.create('card-on-file', {
onDeleteTokenFailed: (data) => {
console.log('Token deletion failed:', data.error);
// Log the error for debugging
logError('token-deletion-failed', {
tokenId: data.tokenId,
errorCode: data.error.code,
errorMessage: data.error.message,
correlationId: data.correlationId,
timestamp: new Date().toISOString()
});
// Handle different error types
let userMessage = 'Failed to delete payment method. Please try again.';
if (data.error.code === 'UNAUTHORIZED') {
userMessage = 'You are not authorised to delete this payment method.';
} else if (data.error.code === 'TOKEN_NOT_FOUND') {
userMessage = 'This payment method no longer exists.';
// Remove from UI since it doesn't exist
removeTokenFromUI(data.tokenId);
} else if (data.error.code === 'NETWORK_ERROR') {
userMessage = 'Network error. Please check your connection and try again.';
// Offer retry option
showRetryButton(() => retryDeleteToken(data.tokenId));
} else if (data.error.code === 'TOKEN_IN_USE') {
userMessage = 'This payment method cannot be deleted as it is currently being used.';
}
// Show error message to user
showErrorMessage(userMessage);
// Track deletion failure analytics
trackEvent('token-deletion-failed', {
tokenId: data.tokenId,
errorCode: data.error.code,
errorType: data.error.message,
timestamp: new Date().toISOString()
});
// Re-enable delete button if it was disabled
enableDeleteButton(data.tokenId);
}
});
This callback is triggered when a card token is successfully deleted from the vault.
You can use it to:
- Update the UI to remove the deleted payment method.
- Show success confirmation messages to users.
- Track successful payment method deletions for analytics.
- Update local storage or state management.
Parameter | Description |
---|---|
data DeleteCardTokenResponseSuccess | The successful deletion response object. |
data.tokenId string | The ID of the successfully deleted token. |
data.maskedCardNumber string | The masked card number of the deleted token. |
data.cardScheme string | The card scheme of the deleted token. |
data.correlationId string | The correlation ID for tracking the request. |
data.timestamp string | When the deletion was completed, in ISO 8601 format. |
const cardOnFileComponent = sdk.create('card-on-file', {
onDeleteTokenSuccess: (data) => {
console.log('Token deleted successfully:', data.tokenId);
// Remove the token from the UI
removeTokenFromUI(data.tokenId);
// Show success message
showSuccessMessage(`${data.cardScheme} ending in ${data.maskedCardNumber.slice(-4)} has been removed successfully.`);
// Update local data
removeTokenFromLocalStorage(data.tokenId);
// Track successful deletion
trackEvent('token-deletion-success', {
tokenId: data.tokenId,
cardScheme: data.cardScheme,
maskedCardNumber: data.maskedCardNumber,
correlationId: data.correlationId,
timestamp: new Date().toISOString()
});
// Check if this was the last saved card
const remainingTokens = getRemainingTokenCount();
if (remainingTokens === 0) {
showEmptyStateMessage('No saved payment methods. Add a new card to save time on future purchases.');
hideCardOnFileSection();
}
// If this was the default card, update default selection
if (isDefaultCard(data.tokenId)) {
updateDefaultCard();
}
// Log successful deletion
console.log(`Payment method deleted: ${data.cardScheme} ${data.maskedCardNumber} at ${data.timestamp}`);
// Optional: Trigger email notification about deleted payment method
if (shouldNotifyOfDeletion()) {
sendPaymentMethodDeletedNotification(data);
}
}
});
This callback is triggered when an input field receives focus.
You can use it to:
- Show helpful tooltips or instructions when users focus on fields.
- Highlight field requirements or formatting examples.
- Track user interaction patterns and form navigation.
- Update UI elements to show the active field state.
Parameter | Description |
---|---|
event FocusEvent | The focus event object. |
event.type string | The event type (always focus ). |
event.target HTMLInputElement | The input field that received focus. |
event.target.name string | The field name identifier. |
event.target.value string | The current value of the field. |
event.target.id string | The field ID attribute. |
event.target.placeholder string | The field's placeholder text. |
event.target.selectionStart number | The starting position of text selection. |
event.target.selectionEnd number | The ending position of text selection. |
event.target.validity ValidityState | The HTML5 validation state of the field. |
event.currentTarget HTMLInputElement | The element the event listener is attached to. |
event.relatedTarget HTMLElement | The element that previously had focus (if any). |
event.timeStamp number | The date and time when the event occurred. |
const cardNumberComponent = sdk.create('card-number', {
onFocus: (event) => {
console.log('Card number field focused');
// Clear any previous errors
clearFieldError('card-number');
// Show helpful formatting tooltip
showTooltip('card-number-help', 'Enter your 16-digit card number without spaces or dashes');
// Highlight the field container
highlightField('card-number');
// Track field interaction
trackEvent('field-focused', {
fieldName: 'card-number',
hasExistingValue: !!event.target.value,
timestamp: new Date().toISOString()
});
// Show accepted card brands
showAcceptedCardBrands();
}
});
const cardExpiryComponent = sdk.create('card-expiry-date', {
onFocus: (event) => {
console.log('Expiry date field focused');
// Show format example
showTooltip('expiry-help', 'MM/YY format (e.g., 12/25)');
// Clear errors
clearFieldError('card-expiry-date');
// Highlight field
highlightField('card-expiry-date');
// Track focus
trackEvent('field-focused', {
fieldName: 'card-expiry-date',
timestamp: new Date().toISOString()
});
}
});
const cardCvcComponent = sdk.create('card-cvc', {
onFocus: (event) => {
console.log('CVC field focused');
// Show security code help
showTooltip('cvc-help', 'Enter the 3-digit security code from the back of your card (4 digits for Amex)');
// Show CVC location diagram
showCvcLocationDiagram();
// Clear errors
clearFieldError('card-cvc');
// Track focus
trackEvent('field-focused', {
fieldName: 'card-cvc',
timestamp: new Date().toISOString()
});
}
});
This callback is used to retrieve device fingerprint data for fraud detection and authentication purposes.
You can use it to:
- Integrate with third-party fraud detection services (Kount, ThreatMetrix, etc.).
- Provide device fingerprint data for enhanced security.
- Implement custom device identification logic.
- Return cached fingerprint data if available.
This callback receives no parameters but should return fingerprint data.
const cardSubmit = sdk.create('card-submit', {
onGetFingerprintResult: async () => {
console.log('Fingerprint data requested');
try {
// Check if we have cached fingerprint data
let fingerprintData = getCachedFingerprintData();
if (!fingerprintData) {
console.log('Generating new fingerprint data');
// Generate new fingerprint using Kount
if (window.ka && window.ka.collect) {
fingerprintData = await new Promise((resolve, reject) => {
window.ka.collect({
sessionId: getKountSessionId(),
onSuccess: (sessionId) => resolve(sessionId),
onFailure: (error) => reject(error)
});
});
}
// Generate fingerprint using ThreatMetrix
else if (window.tmx && window.tmx.profiling) {
fingerprintData = await window.tmx.profiling.generateSessionId();
}
// Fallback: Generate basic browser fingerprint
else {
fingerprintData = generateBasicFingerprint();
}
// Cache the fingerprint data for future use
cacheFingerprintData(fingerprintData);
}
// Track successful fingerprint generation
trackEvent('fingerprint-generated', {
method: getFingerprintMethod(),
sessionId: fingerprintData,
cached: !!getCachedFingerprintData(),
timestamp: new Date().toISOString()
});
console.log('Returning fingerprint data:', fingerprintData);
return fingerprintData;
} catch (error) {
console.error('Fingerprint generation failed:', error);
// Log the error
logError('fingerprint-generation-failed', {
error: error.message,
stack: error.stack,
timestamp: new Date().toISOString()
});
// Return a fallback fingerprint or empty string
const fallbackFingerprint = generateFallbackFingerprint();
trackEvent('fingerprint-fallback-used', {
error: error.message,
fallbackData: fallbackFingerprint,
timestamp: new Date().toISOString()
});
return fallbackFingerprint;
}
}
});
// Helper functions for fingerprint generation
function generateBasicFingerprint() {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
ctx.textBaseline = 'top';
ctx.font = '14px Arial';
ctx.fillText('Basic fingerprint', 2, 2);
const fingerprint = btoa(JSON.stringify({
userAgent: navigator.userAgent,
language: navigator.language,
platform: navigator.platform,
screenResolution: `${screen.width}x${screen.height}`,
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
canvas: canvas.toDataURL(),
timestamp: Date.now()
}));
return fingerprint.substring(0, 32); // Truncate for consistency
}
function generateFallbackFingerprint() {
return btoa(`fallback_${Date.now()}_${Math.random()}`).substring(0, 32);
}
This callback is triggered when a customer selects a saved card in the click-once component.
You can use it to:
- Update the UI to show the selected card.
- Enable or disable the CVC field based on card requirements.
- Track card selection patterns for analytics.
- Load card-specific settings or preferences.
Parameter | Description |
---|---|
data object | The card selection event data. |
data.tokenId string | The ID of the selected card token. |
data.maskedCardNumber string | The masked card number of the selected card. |
data.cardScheme string | The card scheme identifier (e.g., visa , mastercard ). |
data.cardSchemeName string | User-friendly card scheme name (e.g., Visa , MasterCard ). |
data.expiryDate string | The card expiry date in MM/YY format. |
data.expiryMonth string | The expiry month (MM). |
data.expiryYear string | The expiry year (YY). |
data.isExpired boolean | Whether the card is currently expired. |
data.expiresWithinMonths number | The number of months until expiry (negative if expired). |
data.cardType string | The card type (e.g., credit , debit , prepaid ). |
data.fundingSource string | The funding source type. |
data.issuerName string | The name of the card issuing bank. |
data.issuerCountry string | The country code of the card issuer. |
data.isCvcRequired boolean | Whether CVC is required for this card. |
data.isDefault boolean | Whether this is the customer's default payment method. |
data.lastUsedDate string | The ISO date when this card was last used for payment. |
data.addedDate string | The ISO date when this card was added to the vault. |
data.usageCount number | The number of times this card has been used. |
data.metadata object | Additional metadata associated with the token. |
data.metadata.customerNickname string | The customer-provided nickname for the card (optional). |
data.metadata.verificationStatus string | The verification status of the card. |
const clickOnceComponent = sdk.create('click-once', {
onOnceCardClick: (data) => {
console.log('User clicked on saved card:', data.maskedCardNumber);
// Update UI to show selected card
updateSelectedCardDisplay(data);
// Track card selection
trackEvent('saved-card-selected', {
tokenId: data.tokenId,
cardScheme: data.cardScheme,
maskedCardNumber: data.maskedCardNumber,
timestamp: new Date().toISOString()
});
// Show/hide CVC field based on requirements
if (data.isCvcRequired) {
showCvcField();
showMessage('Please enter your security code to continue');
disableSubmitButton(); // Keep disabled until CVC is entered
} else {
hideCvcField();
enableSubmitButton();
}
// Check if card is expired
const now = new Date();
const [month, year] = data.expiryDate.split('/');
const expiryDate = new Date(2000 + parseInt(year), parseInt(month) - 1);
if (expiryDate < now) {
showWarning('This card has expired. Please update your payment method or select a different card.');
disableSubmitButton();
showUpdateCardOption(data.tokenId);
}
// Show card-specific benefits
showCardBenefits(data.cardScheme);
// Update payment summary
updatePaymentSummary({
paymentMethod: `${data.cardScheme} ending in ${data.maskedCardNumber.slice(-4)}`,
requiresCvc: data.isCvcRequired
});
}
});
This callback is triggered after 3DS authentication is completed, providing the authentication result and any associated 3DS data.
You can use it to:
- Handle successful authentication and proceed with payment.
- Manage authentication failures with appropriate user messaging.
- Log authentication results for fraud monitoring.
- Update UI based on authentication status.
Parameter | Description |
---|---|
authResult AuthenticationResult | The authentication result object. |
authResult.status string | The authentication status: AUTHENTICATED , FAILED , CANCELLED , or ERROR . |
authResult.authenticationId string | The unique identifier for the authentication attempt. |
authResult.transactionId string | The transaction ID associated with the authentication. |
threeDSAuthenticationData ThreeDSAuthenticationData | 3DS authentication data (optional). |
threeDSAuthenticationData.cavv string | The Cardholder Authentication Verification Value. |
threeDSAuthenticationData.eci string | The Electronic Commerce Indicator. |
threeDSAuthenticationData.version string | The 3DS protocol version used. |
const cardSubmit = sdk.create('card-submit', {
onPostAuthentication: (authResult, threeDSAuthenticationData) => {
console.log('3DS authentication completed:', authResult);
// Track authentication completion
trackEvent('3ds-authentication-completed', {
status: authResult.status,
authenticationId: authResult.authenticationId,
transactionId: authResult.transactionId,
threeDSVersion: threeDSAuthenticationData?.version,
timestamp: new Date().toISOString()
});
// Handle different authentication outcomes
switch (authResult.status) {
case 'AUTHENTICATED':
console.log('3DS authentication successful');
// Show success message
showMessage('Authentication successful. Processing payment...', 'success');
// Store authentication data for transaction
storeAuthenticationData({
authenticationId: authResult.authenticationId,
cavv: threeDSAuthenticationData?.cavv,
eci: threeDSAuthenticationData?.eci,
version: threeDSAuthenticationData?.version
});
// Continue with payment processing
enablePaymentProcessing();
// Log successful authentication
console.log(`3DS ${threeDSAuthenticationData?.version} authentication successful`);
break;
case 'FAILED':
console.error('3DS authentication failed');
// Show failure message
showErrorMessage('Authentication failed. Please try again or use a different payment method.');
// Offer alternative payment methods
showAlternativePaymentMethods();
// Track authentication failure
trackEvent('3ds-authentication-failed', {
authenticationId: authResult.authenticationId,
reason: 'authentication_failed',
timestamp: new Date().toISOString()
});
// Reset payment form
resetPaymentForm();
break;
case 'CANCELLED':
console.log('3DS authentication cancelled by user');
// Show cancellation message
showMessage('Authentication was cancelled. You can try again or use a different payment method.', 'info');
// Track cancellation
trackEvent('3ds-authentication-cancelled', {
authenticationId: authResult.authenticationId,
timestamp: new Date().toISOString()
});
// Re-enable payment form
enablePaymentForm();
break;
case 'ERROR':
console.error('3DS authentication error');
// Show error message
showErrorMessage('Authentication error occurred. Please try again.');
// Log the error
logError('3ds-authentication-error', {
authenticationId: authResult.authenticationId,
transactionId: authResult.transactionId,
timestamp: new Date().toISOString()
});
// Fallback to non-3DS payment if allowed
if (isNon3DSFallbackAllowed()) {
showMessage('Continuing without additional authentication...', 'info');
enablePaymentProcessing();
} else {
showAlternativePaymentMethods();
}
break;
default:
console.warn('Unknown authentication status:', authResult.status);
showErrorMessage('Authentication status unknown. Please try again.');
}
// Hide authentication loading indicators
hideAuthenticationLoader();
}
});
This callback is triggered after 3DS authentication is initiated, providing details about the authentication setup.
You can use it to:
- Handle different initiation results (challenge required, frictionless, failed).
- Show appropriate UI based on authentication requirements.
- Track 3DS initiation success rates and performance.
- Prepare the user for challenge flows or frictionless authentication.
Parameter | Description |
---|---|
authResult AuthenticationResult | The authentication initiation result. |
authResult.status string | The initiation status: CHALLENGE_REQUIRED , FRICTIONLESS , FAILED , or ERROR . |
authResult.authenticationId string | The unique identifier for the authentication session. |
authResult.challengeUrl string | The URL for 3DS challenge (if challenge is required). |
authResult.acsTransId string | The ACS Transaction ID for 3DS 2.0. |
const cardSubmit = sdk.create('card-submit', {
onPostInitiateAuthentication: (authResult) => {
console.log('3DS authentication initiated:', authResult);
// Track initiation result
trackEvent('3ds-authentication-initiated', {
status: authResult.status,
authenticationId: authResult.authenticationId,
challengeRequired: authResult.status === 'CHALLENGE_REQUIRED',
timestamp: new Date().toISOString()
});
// Handle different initiation outcomes
switch (authResult.status) {
case 'CHALLENGE_REQUIRED':
console.log('3DS challenge required');
// Show challenge preparation message
showMessage('Additional authentication required. Please complete the verification process.', 'info');
// Prepare challenge UI
prepareChallengeUI();
// Track challenge initiation
trackEvent('3ds-challenge-required', {
authenticationId: authResult.authenticationId,
challengeUrl: authResult.challengeUrl,
timestamp: new Date().toISOString()
});
break;
case 'FRICTIONLESS':
console.log('3DS frictionless authentication');
// Show frictionless message
showMessage('Authentication in progress...', 'info');
// Track frictionless flow
trackEvent('3ds-frictionless-flow', {
authenticationId: authResult.authenticationId,
timestamp: new Date().toISOString()
});
break;
case 'FAILED':
console.error('3DS initiation failed');
// Show failure message
showErrorMessage('Authentication setup failed. Proceeding without additional verification.');
// Track initiation failure
trackEvent('3ds-initiation-failed', {
authenticationId: authResult.authenticationId,
timestamp: new Date().toISOString()
});
// Continue with non-3DS flow
continueWithoutAuthentication();
break;
case 'ERROR':
console.error('3DS initiation error');
// Show error message
showErrorMessage('Authentication error. Please try again.');
// Log the error
logError('3ds-initiation-error', {
authenticationId: authResult.authenticationId,
timestamp: new Date().toISOString()
});
break;
}
}
});
This callback is triggered before 3DS authentication starts, allowing you to provide authentication configuration.
You can use it to:
- Configure 3DS authentication parameters.
- Set up merchant-specific authentication data.
- Customise the authentication flow based on business rules.
- Provide acquirer and merchant information for 3DS.
Parameter | Description |
---|---|
preInitData PreInitiateSuccessAuthenticationResult | The pre-initiation authentication data. |
preInitData.authenticationId string | The authentication ID from pre-initiation. |
preInitData.transactionId string | The transaction ID associated with authentication. |
const cardSubmit = sdk.create('card-submit', {
onPreAuthentication: async (preInitData) => {
console.log('Starting 3DS authentication setup:', preInitData);
// Track authentication start
trackEvent('3ds-authentication-starting', {
authenticationId: preInitData.authenticationId,
transactionId: preInitData.transactionId,
timestamp: new Date().toISOString()
});
try {
// Get merchant configuration
const merchantConfig = await getMerchantAuthenticationConfig();
// Get customer information for authentication
const customerInfo = await getCustomerAuthenticationInfo();
// Determine authentication settings based on transaction risk
const riskLevel = await assessTransactionRisk(preInitData.transactionId);
const authenticationData = {
acquirerProfileId: merchantConfig.acquirerProfileId,
providerId: merchantConfig.providerId,
timeout: riskLevel === 'high' ? 600 : 300, // Longer timeout for high-risk
merchantName: merchantConfig.merchantName,
merchantCategoryCode: merchantConfig.mcc,
// Customer information
threeDSRequestorAuthenticationInfo: {
threeDSReqAuthMethod: customerInfo.authMethod,
threeDSReqAuthTimestamp: customerInfo.lastAuthTime
},
// Purchase information
purchaseAmount: getCurrentTransactionAmount(),
purchaseCurrency: getCurrentTransactionCurrency(),
purchaseExponent: 2,
// Browser information (auto-collected by SDK)
browserInfo: {
acceptHeaders: navigator.userAgent,
userAgent: navigator.userAgent,
javaEnabled: navigator.javaEnabled(),
language: navigator.language,
colorDepth: screen.colorDepth,
screenHeight: screen.height,
screenWidth: screen.width,
timeZoneOffset: new Date().getTimezoneOffset()
}
};
console.log('Authentication configuration prepared');
return authenticationData;
} catch (error) {
console.error('Failed to prepare authentication:', error);
// Log configuration error
logError('3ds-config-failed', {
authenticationId: preInitData.authenticationId,
error: error.message,
timestamp: new Date().toISOString()
});
// Return null to skip authentication
return null;
}
}
});
This callback is triggered before a token deletion attempt, allowing you to show custom confirmation dialogs or perform validation.
You can use it to:
- Show custom confirmation dialogs for token deletion.
- Validate whether the user has permission to delete the token.
- Check if the token is currently being used in active subscriptions.
- Log token deletion attempts for security auditing.
Parameter | Description |
---|---|
token BaseCardToken | The card token that will be deleted. |
token.gatewayTokenId string | The unique identifier of the token. |
token.maskedPrimaryAccountNumber string | The masked card number. |
token.scheme string | The card scheme. |
token.expiryDate string | The card expiry date. |
const cardOnFileComponent = sdk.create('card-on-file', {
onPreDeleteToken: async (token) => {
console.log('Token deletion requested:', token.maskedPrimaryAccountNumber);
// Track deletion attempt
trackEvent('token-deletion-requested', {
tokenId: token.gatewayTokenId,
cardScheme: token.scheme,
maskedCardNumber: token.maskedPrimaryAccountNumber,
timestamp: new Date().toISOString()
});
try {
// Check if token is used in active subscriptions
const activeSubscriptions = await checkActiveSubscriptions(token.gatewayTokenId);
if (activeSubscriptions.length > 0) {
const subscriptionList = activeSubscriptions.map(sub => sub.name).join(', ');
const confirmed = confirm(
`This payment method is used for active subscriptions: ${subscriptionList}. ` +
`Deleting it may affect these subscriptions. Are you sure you want to continue?`
);
if (!confirmed) {
trackEvent('token-deletion-cancelled-subscriptions', {
tokenId: token.gatewayTokenId,
subscriptionCount: activeSubscriptions.length,
timestamp: new Date().toISOString()
});
return false;
}
}
// Show confirmation dialog
const cardDescription = `${token.scheme} ending in ${token.maskedPrimaryAccountNumber.slice(-4)}`;
const confirmed = confirm(`Are you sure you want to delete ${cardDescription}?`);
if (confirmed) {
// Log confirmation
trackEvent('token-deletion-confirmed', {
tokenId: token.gatewayTokenId,
cardScheme: token.scheme,
timestamp: new Date().toISOString()
});
// Show deletion in progress
showMessage('Deleting payment method...', 'info');
return true;
} else {
// Log cancellation
trackEvent('token-deletion-cancelled', {
tokenId: token.gatewayTokenId,
timestamp: new Date().toISOString()
});
return false;
}
} catch (error) {
console.error('Error during token deletion validation:', error);
// Log validation error
logError('token-deletion-validation-failed', {
tokenId: token.gatewayTokenId,
error: error.message,
timestamp: new Date().toISOString()
});
// Show error and allow user to decide
const confirmed = confirm(
'Unable to check payment method usage. Do you still want to delete it?'
);
return confirmed;
}
}
});
This callback is triggered after 3DS authentication is initiated.
You can use it to:
- Handle different initiation results (challenge required, frictionless, failed).
- Show appropriate UI based on authentication requirements.
- Track 3DS initiation success rates and performance.
- Prepare the user for challenge flows or frictionless authentication.
Parameter | Description |
---|---|
authResult AuthenticationResult | The authentication initiation result. |
authResult.status string | The initiation status: CHALLENGE_REQUIRED , FRICTIONLESS , FAILED , or ERROR . |
authResult.authenticationId string | The unique identifier for the authentication session. |
authResult.challengeUrl string | The URL for 3DS challenge (if challenge is required). |
authResult.acsTransId string | The ACS Transaction ID for 3DS 2.0. |
const cardSubmit = sdk.create('card-submit', {
onPostInitiateAuthentication: (authResult) => {
console.log('3DS authentication initiated:', authResult);
if (authResult.status === 'CHALLENGE_REQUIRED') {
showMessage('Please complete 3DS verification', 'info');
}
}
});
This callback is triggered after tokenisation completes with the tokenisation result.
You can use it to:
- Store the token ID for future use.
- Update the user interface to show saved payment methods.
- Link the token to the customer's account.
- Log tokenisation events for analytics.
Parameter | Description |
---|---|
tokenData CardTokenizationResult | The tokenisation result containing token information. |
tokenData.gatewayTokenId string | The unique identifier for the tokenized card. |
tokenData.maskedPrimaryAccountNumber string | The masked card number for display purposes. |
tokenData.scheme string | The card scheme. |
tokenData.expiryDate string | The card expiry date in MM/YY format. |
tokenData.issuerName string | The name of the card issuing bank. |
tokenData.issuerCountryCode string | The country code of the card issuer. |
tokenData.fundingSource string | The funding source type. |
tokenData.correlationId string | The correlation ID for tracking the request. |
const cardSubmit = sdk.create('card-submit', {
onPostTokenisation: (tokenData) => {
console.log('Card tokenised:', tokenData);
// Store token information for future use
const savedCard = {
tokenId: tokenData.gatewayTokenId,
maskedNumber: tokenData.maskedPrimaryAccountNumber,
scheme: tokenData.scheme,
expiryDate: tokenData.expiryDate,
issuer: tokenData.issuerName,
savedAt: new Date().toISOString()
};
// Save to local storage or send to your backend
localStorage.setItem(`card_token_${tokenData.gatewayTokenId}`, JSON.stringify(savedCard));
// Track tokenisation success for analytics
trackEvent('card-tokenisation-success', {
tokenId: tokenData.gatewayTokenId,
scheme: tokenData.scheme,
issuer: tokenData.issuerName,
correlationId: tokenData.correlationId
});
// Update UI to show the card was saved
showSuccessMessage('Your payment method has been saved securely!');
// Add to saved cards list in UI
addToSavedCardsList(savedCard);
}
});
This callback is triggered before 3DS authentication starts, allowing you to provide authentication configuration.
You can use it to:
- Configure 3DS authentication parameters.
- Set up merchant-specific authentication data.
- Customise the authentication flow based on business rules.
- Provide acquirer and merchant information for 3DS.
Parameter | Description |
---|---|
preInitData PreInitiateSuccessAuthenticationResult | The pre-initiation authentication data. |
preInitData.authenticationId string | The authentication ID from pre-initiation. |
preInitData.transactionId string | The transaction ID associated with authentication. |
preInitData.scaMandated boolean | Whether Strong Customer Authentication is mandated. |
preInitData.applicableExemptions array | Array of applicable SCA exemptions for this transaction. |
const cardSubmit = sdk.create('card-submit', {
onPreAuthentication: async (preInitData) => {
console.log('Starting 3DS authentication:', preInitData);
// Analyze pre-initiation data to determine strategy
const authConfig = {
challengeWindowSize: '02', // 390x400px window
timeout: 30, // 30 seconds timeout
};
// Check if SCA is mandated
if (preInitData.scaMandated) {
console.log('SCA is mandated for this transaction');
authConfig.timeout = 60; // Give more time for mandated SCA
}
// Check for applicable exemptions
if (preInitData.applicableExemptions?.includes('LowValue')) {
console.log('Low value exemption available');
// You might choose to apply exemption here
}
// Track authentication initiation
trackEvent('3ds-authentication-starting', {
authenticationId: preInitData.authenticationId,
scaMandated: preInitData.scaMandated,
exemptions: preInitData.applicableExemptions
});
return authConfig;
}
});
This callback is triggered before the transaction authorisation, allowing you to provide additional transaction data or perform validation.
You can use it to:
- Integrate with Kount or other fraud detection services.
- Perform AVS (Address Verification System) checks.
- Enable 3DS authentication for specific transactions.
- Apply business rules based on transaction amount or customer history.
Parameter | Description |
---|---|
data PreAuthorizationData | Contains the tokenisation result and authentication data (if applicable). |
data.initiateIntegratedSuccessAuthenticationResult InitiateIntegratedSuccessAuthenticationResult | The 3DS authentication result (null for payouts or when 3DS isn't performed). |
data.initiateIntegratedSuccessAuthenticationResult.authenticationId string | The unique identifier for the authentication session. |
data.initiateIntegratedSuccessAuthenticationResult.transactionId string | The transaction ID associated with authentication. |
data.initiateIntegratedSuccessAuthenticationResult.cavv string | The Cardholder Authentication Verification Value. |
data.initiateIntegratedSuccessAuthenticationResult.eci string | The Electronic Commerce Indicator. |
data.initiateIntegratedSuccessAuthenticationResult.version string | The 3DS protocol version used. |
data.cardTokenData CardTokenData | Token data for payout transactions or card-on-file usage (null for new card payments). |
data.cardTokenData.gatewayTokenId string | The token ID from the payment gateway. |
data.cardTokenData.schemeTokenId string | The token ID from the card scheme. |
data.cardTokenData.maskedPrimaryAccountNumber string | The masked card number for display. |
data.cardTokenData.expiryDate string | The card expiry date in MM/YY format. |
data.cardTokenData.cardScheme string | The card scheme. |
data.cardTokenData.cvc string | The CVC value (if provided for token usage). |
threeDSAuthenticationData ThreeDSAuthenticationData | 3DS authentication data from the previous authentication step (optional). |
threeDSAuthenticationData.authenticationId string | The authentication session identifier. |
threeDSAuthenticationData.cavv string | The Cardholder Authentication Verification Value. |
threeDSAuthenticationData.eci string | The Electronic Commerce Indicator value. |
threeDSAuthenticationData.xid string | The transaction identifier for 3DS 1.0. |
threeDSAuthenticationData.version string | The 3DS protocol version (1.0, 2.1, 2.2). |
threeDSAuthenticationData.dsTransId string | The Directory Server Transaction ID for 3DS 2.0+. |
threeDSAuthenticationData.acsTransId string | The ACS Transaction ID for 3DS 2.0+. |
const cardSubmit = sdk.create('card-submit', {
onPreAuthorisation: async (data, threeDSAuthenticationData) => {
console.log('Pre-authorisation data:', data);
console.log('3DS authentication data:', threeDSAuthenticationData);
// Example: Integrate with fraud detection service
const fraudScore = await checkFraudScore({
tokenId: data.cardTokenData?.gatewayTokenId,
authenticationId: data.initiateIntegratedSuccessAuthenticationResult?.authenticationId
});
// Configure transaction based on business rules
const transactionConfig = {
addressVerification: {
countryCode: "US",
houseNumberOrName: "123 Main St",
postalCode: "12345"
},
identityVerification: {
nameVerification: true
},
psd2Data: {
scaExemption: fraudScore < 0.3 ? 'LowRisk' : null
}
};
// Add 3DS data if authentication was performed
if (threeDSAuthenticationData) {
transactionConfig.threeDSecureData = {
authenticationId: threeDSAuthenticationData.authenticationId
};
}
return transactionConfig;
});
This callback is triggered before a token deletion attempt, allowing you to show custom confirmation dialogs or perform validation.
You can use it to:
- Show custom confirmation dialogs for token deletion.
- Validate whether the user has permission to delete the token.
- Check if the token is currently being used in active subscriptions.
- Log token deletion attempts for security auditing.
Parameter | Description |
---|---|
token BaseCardToken | The card token that will be deleted. |
token.gatewayTokenId string | The unique identifier of the token. |
token.maskedPrimaryAccountNumber string | The masked card number. |
token.scheme string | The card scheme. |
token.expiryDate string | The card expiry date. |
const cardOnFileComponent = sdk.create('card-on-file', {
onPreDeleteToken: async (token) => {
// Check if token is used in active subscriptions
const hasActiveSubscriptions = await checkActiveSubscriptions(token.gatewayTokenId);
if (hasActiveSubscriptions) {
const confirmed = confirm(
`This card is used for active subscriptions. Deleting it will cancel those subscriptions. Continue?`
);
if (!confirmed) return false;
}
// Show custom confirmation dialog
const confirmed = confirm(
`Delete ${token.scheme} card ending in ${token.maskedPrimaryAccountNumber.slice(-4)}?`
);
// Log deletion attempt for security auditing
if (confirmed) {
trackEvent('token-deletion-confirmed', {
tokenId: token.gatewayTokenId,
scheme: token.scheme,
lastFour: token.maskedPrimaryAccountNumber.slice(-4)
});
}
return confirmed;
}
});
This callback is triggered before 3DS authentication initiation, allowing you to configure authentication parameters.
You can use it to:
- Configure 3DS authentication parameters and merchant data.
- Set up acquirer and provider information for 3DS.
- Customise authentication timeout and retry behaviour.
- Control whether to proceed with 3DS authentication.
This callback receives no parameters.
const cardSubmit = sdk.create('card-submit', {
onPreInitiateAuthentication: () => {
// Configure 3DS authentication parameters
return {
acquirerProfileId: 'your-acquirer-profile-id',
providerId: 'your-3ds-provider-id',
requestorAuthenticationIndicator: '01', // Payment transaction
timeout: 30 // 30 seconds timeout for fingerprinting
};
}
});
This callback is triggered before card tokenisation begins, allowing you to control whether tokenisation should proceed.
You can use it to:
- Validate card information before tokenization.
- Check if the customer wants to save their payment method.
- Apply business rules for token storage.
- Implement custom security checks.
This callback receives no parameters.
const cardSubmit = sdk.create('card-submit', {
onPreTokenisation: () => {
console.log('About to tokenise card');
// Check if user has opted in to save payment method
const savePaymentMethod = document.getElementById('save-card-checkbox')?.checked;
if (!savePaymentMethod) {
console.log('User opted out of saving payment method');
return false;
}
// Apply business rules
const isValidForStorage = validateCardForStorage();
if (!isValidForStorage) {
console.log('Card not suitable for storage - skipping tokenisation');
return false;
}
console.log('Proceeding with card tokenisation');
return true;
}
});
This callback is triggered after tokens are retrieved but before they're rendered, allowing filtering and transformation.
You can use it to:
- Filter tokens based on business rules or user preferences.
- Transform token display order and configuration.
- Set custom CVC requirements for specific tokens.
- Apply merchant-specific token visibility rules.
Parameter | Description |
---|---|
data RetrieveCardTokensReponseSuccess | The successful response from the token retrieval API. |
data.gatewayTokens array | Array of gateway tokens retrieved from the vault. |
data.gatewayTokens[].gatewayTokenId string | The unique identifier for the gateway token. |
data.gatewayTokens[].maskedPrimaryAccountNumber string | The masked card number for display. |
data.gatewayTokens[].scheme string | The card scheme. |
data.gatewayTokens[].expiryDate string | The card expiry date. |
data.gatewayTokens[].issuerName string | The name of the card issuing bank. |
data.gatewayTokens[].issuerCountryCode string | The country code of the card issuer. |
data.schemeTokens array | Array of scheme tokens retrieved from the vault (if applicable). |
data.correlationId string | The correlation ID for tracking the request. |
const cardOnFileComponent = sdk.create('card-on-file', {
onPreRenderTokens: (data) => {
// Filter and transform tokens based on business rules
const filteredTokens = data.gatewayTokens
.filter(token => {
// Only show non-expired cards
const currentDate = new Date();
const expiryParts = token.expiryDate.split('/');
const expiryDate = new Date(2000 + parseInt(expiryParts[1]), parseInt(expiryParts[0]) - 1);
return expiryDate > currentDate;
})
.filter(token => {
// Only show cards from supported countries
const supportedCountries = ['US', 'GB', 'CA', 'AU'];
return supportedCountries.includes(token.issuerCountryCode);
})
.sort((a, b) => {
// Sort by scheme preference
const schemeOrder = { 'Visa': 1, 'MasterCard': 2, 'Amex': 3 };
return (schemeOrder[a.scheme] || 999) - (schemeOrder[b.scheme] || 999);
});
// Transform to required format with custom CVC requirements
return filteredTokens.map(token => ({
id: token.gatewayTokenId,
isCvcRequired: token.scheme === 'Amex' ? false : true // Amex doesn't require CVC
}));
}
});
This callback is triggered when the initial request to fetch saved card tokens fails.
You can use it to:
- Display error messages to users about token retrieval failures.
- Implement fallback UI when saved cards cannot be loaded.
- Track token retrieval failure rates for monitoring.
- Offer alternative payment methods when tokens are unavailable.
Parameter | Description |
---|---|
data RetrieveCardTokensReponseFailed | The failed response from the token retrieval API. |
data.error object | The error details for the failed retrieval. |
data.error.message string | A human-readable error message. |
data.error.code string | The specific error code for programmatic handling. |
data.correlationId string | The correlation ID for tracking the request. |
data.statusCode number | The HTTP status code of the failed request. |
data.timestamp string | When the error occurred, in ISO 8601 format. |
const cardOnFileComponent = sdk.create('card-on-file', {
onRetrieveTokensFailed: (data) => {
console.error('Failed to retrieve saved cards:', data.error);
// Track the error for analytics
trackError('token-retrieval-failed', {
errorCode: data.error.code,
correlationId: data.correlationId,
statusCode: data.statusCode
});
// Show user-friendly error message
let errorMessage = 'Unable to load your saved payment methods.';
if (data.error.code === 'NETWORK_ERROR') {
errorMessage = 'Network connection issue. Please check your internet connection.';
} else if (data.error.code === 'UNAUTHORIZED') {
errorMessage = 'Please log in again to access your saved payment methods.';
}
showNotification(errorMessage, 'error');
// Hide the saved cards section and show alternative options
document.getElementById('saved-cards-section').style.display = 'none';
document.getElementById('add-new-card-section').style.display = 'block';
}
});
This callback is triggered when submission fails due to PXP-specific errors or validation issues.
You can use it to:
- Display user-friendly error messages for submission failures.
- Implement retry logic for transient errors.
- Track submission error rates and patterns.
- Handle different types of submission errors appropriately.
Parameter | Description |
---|---|
error object | The error object containing submission failure details. |
error.message string | A human-readable error message. |
error.errorCode string | The specific error code for programmatic handling. |
error.correlationId string | The correlation ID for tracking the request (if available). |
error.validationErrors array | Array of field-specific validation errors (if applicable). |
error.timestamp string | When the error occurred, in ISO 8601 format. |
const cardSubmit = sdk.create('card-submit', {
onSubmitError: (error) => {
console.error('Card submission failed:', error);
// Track the error for analytics
trackError('card-submit-error', {
errorCode: error.errorCode,
correlationId: error.correlationId,
timestamp: error.timestamp
});
// Handle different types of errors
let userMessage = 'Payment submission failed. Please try again.';
switch (error.errorCode) {
case 'VALIDATION_FAILED':
userMessage = 'Please check your card details and try again.';
// Handle specific field validation errors
if (error.validationErrors) {
error.validationErrors.forEach(validationError => {
highlightFieldError(validationError.field, validationError.message);
});
}
break;
case 'NETWORK_ERROR':
userMessage = 'Network connection issue. Please check your internet connection and try again.';
break;
case 'CARD_DECLINED':
userMessage = 'Your card was declined. Please try a different payment method.';
break;
case 'INSUFFICIENT_FUNDS':
userMessage = 'Insufficient funds. Please try a different card or payment method.';
break;
case 'EXPIRED_CARD':
userMessage = 'Your card has expired. Please update your card details.';
break;
default:
userMessage = `Payment failed: ${error.message}`;
}
// Show error to user
showErrorNotification(userMessage);
// Re-enable submit button for retry
document.getElementById('submit-button').disabled = false;
}
});
This callback is triggered when updating card token information (e.g., expiry date) fails.
You can use it to:
- Display error messages for failed token updates.
- Implement retry logic for token update failures.
- Track token update failure rates for monitoring.
- Handle different types of update errors appropriately.
Parameter | Description |
---|---|
data UpdateCardTokenResponseFailed | The failed response from the token update API. |
data.error object | The error details for the failed update. |
data.error.message string | A human-readable error message. |
data.error.code string | The specific error code for programmatic handling. |
data.tokenId string | The ID of the token that failed to be updated. |
data.correlationId string | The correlation ID for tracking the request. |
data.statusCode number | The HTTP status code of the failed request. |
data.timestamp string | When the error occurred, in ISO 8601 format. |
const cardOnFileComponent = sdk.create('card-on-file', {
onUpdateTokenFailed: (data) => {
console.error('Token update failed:', data.error);
// Track the error for analytics
trackError('token-update-failed', {
errorCode: data.error.code,
tokenId: data.tokenId,
correlationId: data.correlationId
});
// Handle different types of errors
let errorMessage = 'Failed to update card details. Please try again.';
switch (data.error.code) {
case 'INVALID_EXPIRY_DATE':
errorMessage = 'Please enter a valid expiry date.';
break;
case 'TOKEN_NOT_FOUND':
errorMessage = 'This payment method no longer exists.';
break;
case 'UNAUTHORIZED':
errorMessage = 'You are not authorised to update this payment method.';
break;
case 'NETWORK_ERROR':
errorMessage = 'Network connection issue. Please try again.';
break;
}
// Show error notification
showErrorNotification(errorMessage);
// Revert UI changes if update failed
document.getElementById(`token-${data.tokenId}`).classList.remove('updating');
// Show retry button
const retryButton = document.getElementById(`retry-update-${data.tokenId}`);
if (retryButton) {
retryButton.style.display = 'block';
}
}
});
This callback is triggered when card token information is successfully updated.
You can use it to:
- Display success messages for token updates.
- Update the UI to reflect the changes.
- Track successful token updates for analytics.
- Sync updated token information with local storage.
Parameter | Description |
---|---|
data UpdateCardTokenResponseSuccess | The successful response from the token update API. |
data.tokenId string | The ID of the successfully updated token. |
data.maskedCardNumber string | The masked card number of the updated token. |
data.cardScheme string | The card scheme of the updated token. |
data.updatedFields object | The fields that were updated. |
data.updatedFields.expiryMonth string | The new expiry month (if updated). |
data.updatedFields.expiryYear string | The new expiry year (if updated). |
data.correlationId string | The correlation ID for tracking the request. |
data.timestamp string | When the update was completed, in ISO 8601 format. |
const cardOnFileComponent = sdk.create('card-on-file', {
onUpdateTokenSuccess: (data) => {
console.log('Token updated successfully:', data);
// Track the success for analytics
trackEvent('token-update-success', {
tokenId: data.tokenId,
correlationId: data.correlationId,
updatedFields: Object.keys(data.updatedFields)
});
// Show success message
showSuccessNotification('Payment method updated successfully!');
// Update the UI to reflect changes
const tokenElement = document.getElementById(`token-${data.tokenId}`);
if (tokenElement) {
tokenElement.classList.add('updated');
// Update expiry display if it was changed
if (data.updatedFields.expiryMonth && data.updatedFields.expiryYear) {
const expiryElement = tokenElement.querySelector('.expiry-date');
if (expiryElement) {
expiryElement.textContent = `${data.updatedFields.expiryMonth}/${data.updatedFields.expiryYear}`;
}
}
}
// Update local storage with new token data
updateLocalTokenData(data.tokenId, data.updatedFields);
// Remove any error states
document.getElementById(`token-${data.tokenId}`).classList.remove('error', 'updating');
}
});
This callback is triggered when form validation occurs.
You can use it to:
- Handle validation results for all form fields.
- Display custom error messages based on validation results.
- Track validation patterns and field-specific error rates.
- Implement custom validation logic or additional checks.
Parameter | Description |
---|---|
validationResults ValidationResult[] | Array of validation results for all validated fields. |
validationResults[].valid boolean | Whether the field passed validation. |
validationResults[].isNotValidated boolean | Whether the field was not validated (optional field that's empty). |
validationResults[].errors object | Object containing field-specific errors (if validation failed). |
validationResults[].errors[fieldName] object | Error details for a specific field. |
validationResults[].errors[fieldName].code string | The error code for programmatic handling. |
validationResults[].errors[fieldName].message string | A human-readable error message. |
const newCard = sdk.create('new-card', {
onValidation: (validationResults) => {
console.log('Card form validation:', validationResults);
let allValid = true;
let errorCount = 0;
validationResults.forEach(result => {
if (!result.valid && !result.isNotValidated) {
allValid = false;
errorCount++;
// Handle field-specific errors
if (result.errors) {
Object.keys(result.errors).forEach(fieldName => {
const error = result.errors[fieldName];
// Track validation errors for analytics
trackEvent('validation-error', {
field: fieldName,
errorCode: error.code,
errorMessage: error.message
});
// Show custom error message
showFieldError(fieldName, error.message);
console.log(`${fieldName}: ${error.message} (${error.code})`);
});
}
}
});
// Update form validity state
const submitButton = document.getElementById('submit-button');
if (submitButton) {
submitButton.disabled = !allValid;
submitButton.classList.toggle('valid', allValid);
}
// Update overall form status
const formStatus = document.getElementById('form-status');
if (formStatus) {
if (allValid) {
formStatus.textContent = 'All fields are valid';
formStatus.className = 'status-valid';
} else {
formStatus.textContent = `${errorCount} field(s) need attention`;
formStatus.className = 'status-invalid';
}
}
}
});
This callback is triggered when validation fails for a single field.
You can use it to:
- Display field-specific error messages when validation fails.
- Track validation failure patterns for analytics.
- Implement custom error handling for specific field types.
- Update UI to highlight invalid fields.
Parameter | Description |
---|---|
validationResults ValidationResult[] | Array of validation results for the failed field. |
validationResults[].valid boolean | Always false for this event. |
validationResults[].errors object | Object containing field-specific errors. |
validationResults[].errors[fieldName] object | Error details for the specific field that failed. |
validationResults[].errors[fieldName].code string | The error code for programmatic handling. |
validationResults[].errors[fieldName].message string | A human-readable error message. |
const component = sdk.create('card-number', {
onValidationFailed: (validationResults) => {
console.log('Validation failed:', validationResults);
validationResults.forEach(result => {
if (result.errors) {
Object.keys(result.errors).forEach(fieldName => {
const error = result.errors[fieldName];
// Track validation failure for analytics
trackEvent('field-validation-failed', {
field: fieldName,
errorCode: error.code,
errorMessage: error.message
});
// Show field-specific error styling
const fieldElement = document.getElementById(fieldName);
if (fieldElement) {
fieldElement.classList.add('error');
fieldElement.setAttribute('aria-invalid', 'true');
}
// Display error message near the field
showFieldErrorMessage(fieldName, error.message);
});
}
});
}
});
This callback is triggered when validation is successful for a single field.
You can use it to:
- Display success indicators when field validation passes.
- Track validation success patterns for analytics.
- Clear previous error states and messages.
- Update UI to show valid field status.
Parameter | Description |
---|---|
validationResults ValidationResult[] | Array of validation results for the successful field. |
validationResults[].valid boolean | Always true for this event. |
validationResults[].isNotValidated boolean | Whether the field was actually validated or just not required. |
validationResults[].errors object | The error object. Empty object since validation passed. |
const component = sdk.create('card-number', {
onValidationPassed: (validationResults) => {
console.log('Validation passed:', validationResults);
validationResults.forEach(result => {
if (result.valid) {
const fieldElement = document.querySelector('[data-field-type="card-number"]');
if (fieldElement) {
// Remove error states
fieldElement.classList.remove('error');
fieldElement.classList.add('valid');
fieldElement.setAttribute('aria-invalid', 'false');
// Clear any error messages
const errorElement = fieldElement.parentElement?.querySelector('.error-message');
if (errorElement) {
errorElement.remove();
}
// Show success indicator
const successIcon = fieldElement.parentElement?.querySelector('.success-icon');
if (successIcon) {
successIcon.style.display = 'block';
}
}
// Track successful validation for analytics
trackEvent('field-validation-passed', {
field: 'card-number',
wasNotValidated: result.isNotValidated || false
});
}
});
}
});
This callback is called when each token item's user interface is being constructed, allowing you to customise the HTML layout.
You can use it to:
- Create custom layouts for saved card tokens.
- Implement responsive designs for different screen sizes.
- Add custom branding and styling to token displays.
- Include additional elements like badges or status indicators.
Parameter | Description |
---|---|
elementIds TokenBuilderElementIds | Object containing all the element IDs that need to be included in the HTML. |
elementIds.tokenImageId string | The ID for the card brand image element. |
elementIds.tokenLabelId string | The ID for the token label text element. |
elementIds.expiryDateId string | The ID for the expiry date display element. |
elementIds.editButtonId string | The ID for the edit button element. |
elementIds.deleteButtonId string | The ID for the delete button element. |
const cardOnFileComponent = sdk.create('card-on-file', {
tokenItemBuilder: (elementIds) => {
return `
<div class="custom-token-card" style="
border: 1px solid #e1e5e9;
border-radius: 8px;
padding: 16px;
margin-bottom: 12px;
background: white;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
transition: all 0.2s ease;
" onmouseover="this.style.boxShadow='0 4px 8px rgba(0,0,0,0.15)'"
onmouseout="this.style.boxShadow='0 2px 4px rgba(0,0,0,0.1)'">
<div style="display: flex; align-items: center; justify-content: space-between;">
<!-- Left side: Card info -->
<div style="display: flex; align-items: center; flex: 1;">
<div id="${elementIds.tokenImageId}" style="
width: 48px;
height: 32px;
margin-right: 12px;
display: flex;
align-items: center;
justify-content: center;
"></div>
<div style="flex: 1;">
<div id="${elementIds.tokenLabelId}" style="
font-weight: 600;
font-size: 14px;
color: #2c3e50;
margin-bottom: 4px;
"></div>
<div id="${elementIds.expiryDateId}" style="
font-size: 12px;
color: #7f8c8d;
"></div>
</div>
</div>
<!-- Right side: Actions -->
<div style="display: flex; gap: 8px;">
<div id="${elementIds.editButtonId}" style="
cursor: pointer;
padding: 6px;
border-radius: 4px;
transition: background-color 0.2s;
" onmouseover="this.style.backgroundColor='#f8f9fa'"
onmouseout="this.style.backgroundColor='transparent'"></div>
<div id="${elementIds.deleteButtonId}" style="
cursor: pointer;
padding: 6px;
border-radius: 4px;
transition: background-color 0.2s;
" onmouseover="this.style.backgroundColor='#fee'"
onmouseout="this.style.backgroundColor='transparent'"></div>
</div>
</div>
</div>
`;
}
});
This callback is called to generate the display text for each card token. It replaces the default masked card number.
You can use it to:
- Customise how card information is displayed to users.
- Include additional card details like issuer name or card type.
- Implement localized or branded token labels.
- Add custom formatting or styling to card displays.
Parameter | Description |
---|---|
token BaseCardToken | The card token object containing all available card information. |
token.gatewayTokenId string | The unique identifier for the gateway token (if gateway token). |
token.schemeTokenId string | The unique identifier for the scheme token (if scheme token). |
token.maskedPrimaryAccountNumber string | The masked card number for display. |
token.scheme string | The card scheme. |
token.expiryDate string | The card expiry date in MM/YY format. |
token.issuerName string | The name of the card issuing bank. |
token.issuerCountryCode string | The country code of the card issuer. |
token.fundingSource string | The funding source type. |
const cardOnFileComponent = sdk.create('card-on-file', {
tokenLabelBuilder: (token) => {
// Create a comprehensive, user-friendly label
const cardEnding = token.maskedPrimaryAccountNumber.slice(-4);
const brandName = token.scheme || 'Card';
const issuer = token.issuerName ? ` - ${token.issuerName}` : '';
const fundingType = token.fundingSource ? ` (${token.fundingSource})` : '';
// Check if card is expiring soon
const currentDate = new Date();
const [month, year] = token.expiryDate.split('/');
const expiryDate = new Date(2000 + parseInt(year), parseInt(month) - 1);
const monthsUntilExpiry = (expiryDate.getFullYear() - currentDate.getFullYear()) * 12 +
(expiryDate.getMonth() - currentDate.getMonth());
let expiryWarning = '';
if (monthsUntilExpiry <= 2 && monthsUntilExpiry > 0) {
expiryWarning = ' ⚠️ Expires Soon';
} else if (monthsUntilExpiry <= 0) {
expiryWarning = ' ❌ Expired';
}
return `${brandName} •••• ${cardEnding}${issuer}${fundingType}${expiryWarning}`;
}
});
The following snippet is an example of how you might handle a declined transaction when using the card submit component.
const cardSubmitComponent = sdk.create('card-submit', {
onPostAuthorisation: (submitResult) => {
console.log('Transaction result:', submitResult);
if (submitResult.status === 'Refused') {
// Transaction was declined by the issuer or payment provider
const refusedResult = submitResult as RefusedSubmitResult;
// Handle the declined transaction
handleDeclinedTransaction(refusedResult);
} else if (submitResult.status === 'Authorised') {
// Transaction was successful
handleSuccessfulTransaction(submitResult);
} else if (submitResult.status === 'Error') {
// System error occurred
handleSystemError(submitResult);
} else if (submitResult.status === 'Pending') {
// Transaction is pending further processing
handlePendingTransaction(submitResult);
}
}
});
function handleDeclinedTransaction(refusedResult) {
// Extract decline information
const stateData = refusedResult.stateData;
const providerResponse = refusedResult.providerResponse;
const fundingData = refusedResult.fundingData;
// Log decline details
console.log('Transaction declined:', {
stateCode: stateData?.code,
stateMessage: stateData?.message,
providerCode: providerResponse?.code,
providerMessage: providerResponse?.message,
merchantAdvice: providerResponse?.merchantAdvice
});
// Show user-friendly error message based on decline reason
const declineCode = providerResponse?.code;
let userMessage = 'Your payment was declined. Please try again or use a different payment method.';
switch (declineCode) {
case 'INSUFFICIENT_FUNDS':
userMessage = 'Your card has insufficient funds. Please try a different payment method.';
break;
case 'EXPIRED_CARD':
userMessage = 'Your card has expired. Please check your card details or use a different card.';
break;
case 'INVALID_CVV':
userMessage = 'The security code (CVV) is incorrect. Please check and try again.';
break;
case 'CARD_BLOCKED':
userMessage = 'Your card is blocked. Please contact your bank or use a different payment method.';
break;
case 'LIMIT_EXCEEDED':
userMessage = 'Transaction exceeds your card limit. Please try a smaller amount or different card.';
break;
default:
// Use merchant advice if available
if (providerResponse?.merchantAdvice?.message) {
userMessage = providerResponse.merchantAdvice.message;
}
}
// Display error to user
showErrorMessage(userMessage);
// Check if retry is recommended
if (providerResponse?.merchantAdvice?.code === 'RETRY') {
enableRetryOption();
} else if (providerResponse?.merchantAdvice?.code === 'DO_NOT_RETRY') {
disableRetryOption();
suggestAlternativePayment();
}
// Log analytics event for declined transaction
logDeclineAnalytics(declineCode, stateData?.code);
}
The following snippet is an example of how you might handle authentication problems when using the card submit component.
const cardSubmitComponent = sdk.create('card-submit', {
onSubmitError: (error) => {
console.log('Submit error occurred:', error);
// Handle different types of authentication and processing errors
switch (error.ErrorCode) {
case 'SDK0503': // Transaction authentication rejected
showErrorMessage('Authentication was rejected by your bank. Please try again or contact your bank.');
enableRetryOption();
break;
case 'SDK0505': // Transaction authentication failed
showErrorMessage('Authentication failed. Please try again or contact your bank for assistance.');
enableRetryOption();
break;
case 'SDK0504': // SCA exemption required
showErrorMessage('Additional authentication is required. Please complete the verification process.');
// Handle SCA exemption flow
break;
default:
// Generic error handling
showErrorMessage('Payment processing failed. Please try again.');
logError(error);
}
}
});