Skip to content

Events

Implement callbacks to customise your card payment flow for web.

Overview

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.

Supported events

The following tables lists all events supported by the different pre-built components.

EventBilling addressCard-on-fileClick-onceNew 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

Callbacks

onPostAuthorisation

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

Event dataDescription
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).

Example implementation

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');
    }
  }
});

onPreAuthorisation

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.

Event data

ParameterDescription
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+.

Example implementation

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
    };
  }
});

onPreTokenisation

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.

Event data

This callback receives no parameters.

Example implementation

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;
  }
});

onPostTokenisation

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.

Event data

ParameterDescription
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.

Example implementation

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');
  }
});

onBlur

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.

Event data

ParameterDescription
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.

Example implementation

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()
    });
  }
});

onCardBrandCannotRecognised

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.

Event data

ParameterDescription
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).

Example implementation

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();
  }
});

onCardBrandDetected

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.

Event data

ParameterDescription
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.

Example implementation

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()
    });
  }
});

onChange

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.

Event data

ParameterDescription
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.

Example implementation

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.');
      }
    }
  }
});

onClick

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.

Event data

ParameterDescription
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.

Example implementation

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');
    }
});

onCollectEnd

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.

Event data

ParameterDescription
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.

Example implementation

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');
    }
  }
});

onCollectStart

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.

Event data

ParameterDescription
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.

Example implementation

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);
    }
  }
});

onCvcEntered

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.

Event data

ParameterDescription
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.

Example implementation

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();
  }
});

onDeleteTokenFailed

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.

Event data

ParameterDescription
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.

Example implementation

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);
  }
});

onDeleteTokenSuccess

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.

Event data

ParameterDescription
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.

Example implementation

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);
    }
  }
});

onFocus

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.

Event data

ParameterDescription
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.

Example implementation

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()
    });
  }
});

onGetFingerprintResult

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.

Event data

This callback receives no parameters but should return fingerprint data.

Example implementation

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);
}

onOnceCardClick

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.

Event data

ParameterDescription
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.

Example implementation

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
    });
  }
});

onPostAuthentication

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.

Event data

ParameterDescription
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.

Example implementation

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();
  }
});

onPostInitiateAuthentication

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.

Event data

ParameterDescription
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.

Example implementation

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;
    }
  }
});

onPreAuthentication

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.

Event data

ParameterDescription
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.

Example implementation

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;
    }
  }
});

onPreDeleteToken

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.

Event data

ParameterDescription
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.

Example implementation

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;
    }
  }
});

onPostInitiateAuthentication

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.

Event data

ParameterDescription
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');
    }
  }
});

onPostTokenisation

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.

Event data

ParameterDescription
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.

Example implementation

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);
  }
});

onPreAuthentication

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.

Event data

ParameterDescription
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.

Example implementation

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;
  }
});

onPreAuthorisation

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.

Event data

ParameterDescription
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+.

Example implementation

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;
});

onPreDeleteToken

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.

Event data

ParameterDescription
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.

Example implementation

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;
  }
});

onPreInitiateAuthentication

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.

Event data

This callback receives no parameters.

Example implementation

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
    };
  }
});

onPreTokenisation

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.

Event data

This callback receives no parameters.

Example implementation

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;
  }
});

onPreRenderTokens

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.

Event data

ParameterDescription
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.

Example implementation

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
      }));
  }
});

onRetrieveTokensFailed

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.

Event data

ParameterDescription
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.

Example implementation

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';
  }
});

onSubmitError

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.

Event data

ParameterDescription
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.

Example implementation

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;
  }
});

onUpdateTokenFailed

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.

Event data

ParameterDescription
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.

Example implementation

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';
    }
  }
});

onUpdateTokenSuccess

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.

Event data

ParameterDescription
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.

Example implementation

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');
  }
});

onValidation

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.

Event data

ParameterDescription
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.

Example implementation

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';
      }
    }
  }
});

onValidationFailed

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.

Event data

ParameterDescription
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.

Example implementation

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);
        });
      }
    });
  }
});

onValidationPassed

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.

Event data

ParameterDescription
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.

Example implementation

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
        });
      }
    });
  }
});

tokenItemBuilder

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.

Event data

ParameterDescription
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.

Example implementation

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>
    `;
  }
});

tokenLabelBuilder

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.

Event data

ParameterDescription
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.

Example implementation

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}`;
  }
});

Common scenarios

Handle a declined transaction

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);
}

Handle an authentication failure

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);
    }
  }
});