Skip to content

Configuration

Configure Checkout Drop-in once with unified settings for all payment methods, callbacks, and transaction data.

Overview

Checkout Drop-in uses a single, unified configuration at initialisation. Instead of configuring individual payment components, you configure Drop-in once and it automatically handles all payment methods.

Configuration structure

All configuration happens at initialisation via CheckoutDropIn.initialize():

import CheckoutDropIn from '@pxpio/web-components-sdk/src/checkoutDropIn/CheckoutDropIn';
import IntentType from '@pxpio/web-components-sdk/src/basePxpCheckout/types/IntentType';

const checkoutDropIn = CheckoutDropIn.initialize({
  // REQUIRED
  environment: 'test',
  session: sessionData,
  ownerId: 'YourMerchantId',
  // ownerType is set to 'MerchantGroup' automatically by Checkout Drop-in
  transactionData: {
    currency: 'USD',
    amount: 99.99,
    entryType: 'Ecom',
    intent: {
      card: IntentType.Authorisation,
      paypal: IntentType.Authorisation
    },
    merchantTransactionId: crypto.randomUUID(),
    merchantTransactionDate: () => new Date().toISOString()
  },
  
  // REQUIRED: Callbacks
  onSuccess: (result) => { /* ... */ },
  onError: (error) => { /* ... */ },
  
  // OPTIONAL: Callbacks
  onGetShopper: () => Promise.resolve({ id: 'shopper-123' }),
  onBeforeSubmit: async (before) => { /* return true to proceed */ },
  onSubmit: (submit) => { /* ... */ },
  analyticsEvent: (event) => { /* ... */ }
});

// Mount to page
checkoutDropIn.create('checkout-drop-in-container');

Required configuration

Environment

Specifies which Unity environment to connect to:

{
  environment: 'test' // or 'live'
}
ValueDescription
'test'Sandbox environment. Use this for development, testing, and staging.
'live'Live environment. Use this for production deployments.

Session data

Session data is retrieved from your backend and contains payment configuration:

// Backend endpoint
const sessionData = await fetch('/api/create-session')
  .then(response => response.json());

// Pass to Drop-in
{
  session: sessionData
}

Session data includes:

  • sessionId: The unique session identifier
  • hmacKey: HMAC authentication key
  • encryptionKey: Encryption key
  • allowedFundingTypes: Which payment methods are enabled
  • Session timeout and merchant identification

For session creation details, see our implementation guide.

Owner identification

Identifies who owns this transaction:

{
  ownerId: 'YourMerchantId',
  // ownerType is optional; Checkout Drop-in sets it to 'MerchantGroup'
}

Transaction data

Defines the payment amount, currency, and intent:

import IntentType from '@pxpio/web-components-sdk/src/basePxpCheckout/types/IntentType';

{
  transactionData: {
    currency: 'USD',                      // ISO 4217 currency code
    amount: 99.99,                        // Transaction amount
    entryType: 'Ecom',                    // Entry type (usually 'Ecom' for web)
    intent: {
      card: IntentType.Authorisation,     // Card payment intent
      paypal: IntentType.Authorisation    // PayPal payment intent
    },
    merchantTransactionId: crypto.randomUUID(),              // Unique per transaction
    merchantTransactionDate: () => new Date().toISOString()  // Current timestamp
  }
}

Merchant transaction ID

Your unique identifier for the transaction:

merchantTransactionId: crypto.randomUUID()

// Or use your own format
merchantTransactionId: `order-${orderId}`

Optional configuration

Unified callbacks

Drop-in provides unified callbacks that work for all payment methods:

import { BaseSubmitResult } from '@pxpio/web-components-sdk/src/checkoutDropIn/types/BaseSubmitResult';
import BaseSdkException from '@pxpio/web-components-sdk/src/types/sdkExceptions/BaseSdkException';
import PaymentMethod from '@pxpio/web-components-sdk/src/components/checkoutDropInComponents/types/PaymentMethod';

{
  // REQUIRED: Get shopper information
  onGetShopper: () => {
    return Promise.resolve({ id: 'shopper-123' });
  },
  
  // REQUIRED: Called when payment succeeds
  onSuccess: async (result: BaseSubmitResult) => {
    console.log('Payment successful:', result.systemTransactionId);
    // CRITICAL: Always verify on backend before fulfilling order
    await verifyPaymentOnBackend(result);
  },
  
  // REQUIRED: Called when payment fails
  onError: (error: BaseSdkException) => {
    console.error('Payment failed:', error.code, error.message);
  },
  
  // OPTIONAL: Called before payment submission (can cancel)
  onBeforeSubmit: async (paymentMethod: PaymentMethod) => {
    console.log('Payment method:', paymentMethod);
    // Return false to cancel payment
    return true;
  },
  
  // OPTIONAL: Called when payment starts processing
  onSubmit: (paymentMethod: PaymentMethod) => {
    console.log('Processing payment...');
  }
}

For detailed callback documentation, see Implementation.

Analytics

Track payment flow events:

{
  analyticsEvent: (event) => {
    console.log('Analytics:', event.eventName, event);
    // Send to your analytics platform
    sendToGA4(event);
  }
}

For detailed analytics documentation, see Analytics.

Backend-driven configuration

Many behaviours are configured on the backend (in the Unity Portal), rather than in frontend code:

Payment method availability

Controlled via session data:

// Backend session creation
{
  "allowedFundingTypes": {
    "cards": ["visa", "mastercard"],
    "cardSchemes": ["Visa", "Mastercard"],
    "wallets": {
      "paypal": {
        "allowedFundingOptions": ["PAYPAL"],
        "merchantId": "paypal-merchant-123"
      },
      "googlePay": {
        "merchantId": "your-googlepay-merchant-id",
        "gatewayMerchantId": "gateway-merchant-id",
        "merchantName": "Your merchant name"
      },
      "applePay": {
        "merchantId": "your-applepay-merchant-id"
      }
    }
  }
}

Drop-in automatically shows only enabled payment methods.

Branding

Drop-in fetches and applies your branding configuration from the Unity Portal.

3DS requirements

Drop-in respects the amount thresholds, risk assessment rules, and exemptions configured in the Unity Portal. For more information, see the 3DS section.

Recurring payments

Configured in transactionData:

{
  transactionData: {
    // ... other transaction fields
    recurring: {
      frequencyInDays: 30,
      frequencyExpiration: '2025-12-31'
    }
  }
}

Complete configuration examples

Minimal configuration (most common)

import CheckoutDropIn from '@pxpio/web-components-sdk/src/checkoutDropIn/CheckoutDropIn';
import IntentType from '@pxpio/web-components-sdk/src/basePxpCheckout/types/IntentType';

// Get session from backend
const sessionData = await fetch('/api/create-session', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' }
}).then(response => response.json());

// Initialise with minimal config
const checkoutDropIn = CheckoutDropIn.initialize({
  environment: 'test',
  session: sessionData,
  ownerId: 'YourMerchantId',
  ownerType: 'MerchantGroup',
  transactionData: {
    currency: 'USD',
    amount: 99.99,
    entryType: 'Ecom',
    intent: {
      card: IntentType.Authorisation,
      paypal: IntentType.Authorisation
    },
    merchantTransactionId: crypto.randomUUID(),
    merchantTransactionDate: () => new Date().toISOString()
  },
  onGetShopper: () => Promise.resolve({ id: 'shopper-123' }),
  onSuccess: async (result) => {
    await verifyPaymentOnBackend(result);
  },
  onError: (error) => {
    alert(`Payment failed: ${error.message}`);
  }
});

// Mount
checkoutDropIn.create('checkout-drop-in-container');

Full configuration (with all callbacks)

import CheckoutDropIn from '@pxpio/web-components-sdk/src/checkoutDropIn/CheckoutDropIn';
import IntentType from '@pxpio/web-components-sdk/src/basePxpCheckout/types/IntentType';
import PaymentMethod from '@pxpio/web-components-sdk/src/components/checkoutDropInComponents/types/PaymentMethod';
import { BaseSubmitResult } from '@pxpio/web-components-sdk/src/checkoutDropIn/types/BaseSubmitResult';
import BaseSdkException from '@pxpio/web-components-sdk/src/types/sdkExceptions/BaseSdkException';

// Get session from backend
const sessionData = await fetch('/api/create-session', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' }
}).then(response => response.json());

// Initialise with all callbacks
const checkoutDropIn = CheckoutDropIn.initialize({
  // REQUIRED
  environment: 'live',
  session: sessionData,
  ownerId: 'YourMerchantId',
  ownerType: 'MerchantGroup',
  transactionData: {
    currency: 'USD',
    amount: 149.99,
    entryType: 'Ecom',
    intent: {
      card: IntentType.Authorisation,
      paypal: IntentType.Purchase
    },
    merchantTransactionId: `order-${orderId}`,
    merchantTransactionDate: () => new Date().toISOString()
  },
  
  // CALLBACKS
  onGetShopper: () => Promise.resolve({ id: 'shopper-123' }),
  
  onBeforeSubmit: async (paymentMethod: PaymentMethod) => {
    console.log('Payment method selected:', paymentMethod);
    
    // Custom validation
    const isValid = await validateOrder(orderId);
    if (!isValid) {
      alert('Order validation failed. Please review your order.');
      return false; // Cancel payment
    }
    
    // Check inventory
    const inStock = await checkInventory(orderId);
    if (!inStock) {
      alert('Item is out of stock. Please update your cart.');
      return false; // Cancel payment
    }
    
    return true; // Proceed with payment
  },
  
  onSubmit: (paymentMethod: PaymentMethod) => {
    console.log('Payment processing started for:', paymentMethod);
    // Show loading spinner
    document.getElementById('loading-spinner').style.display = 'block';
  },
  
  onSuccess: async (result: BaseSubmitResult) => {
    console.log('Payment successful:', result.systemTransactionId);
    
    document.getElementById('loading-spinner').style.display = 'none';
    
    // CRITICAL: Verify on backend before fulfilling
    try {
      const verified = await fetch('/api/verify-payment', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          systemTransactionId: result.systemTransactionId,
          merchantTransactionId: result.merchantTransactionId,
          orderId: orderId
        })
      }).then(r => r.json());
      
      if (verified.success) {
        window.location.href = `/order-confirmation?orderId=${verified.orderId}`;
      } else {
        alert('Payment verification failed. Please contact support.');
      }
    } catch (error) {
      console.error('Verification failed:', error);
      alert('Unable to verify payment. Please contact support.');
    }
  },
  
  onError: (error: BaseSdkException) => {
    console.error('Payment error:', error);
    document.getElementById('loading-spinner').style.display = 'none';
    
    // Show user-friendly error message based on error code and message
    let userMessage = `Payment failed: ${error.message}`;
    
    if (error.code === 'SDK1116' && error.message.toLowerCase().includes('declined')) {
      userMessage = 'Card declined. Please try a different card.';
    } else if (error.code === 'SDK1116' && error.message.toLowerCase().includes('insufficient funds')) {
      userMessage = 'Insufficient funds.';
    } else if (error.code === 'SDK1114') {
      userMessage = 'Card verification failed.';
    } else if (error.code === 'SDK0500') {
      userMessage = 'Connection error. Check your internet.';
    } else if (error.message.toLowerCase().includes('session') || 
               error.message.toLowerCase().includes('expired')) {
      userMessage = 'Session expired. Please refresh.';
    }
    
    document.getElementById('error-message').textContent = userMessage;
    document.getElementById('error-message').style.display = 'block';
  },
  
  analyticsEvent: (event) => {
    // Send to Google Analytics
    if (typeof gtag !== 'undefined') {
      gtag('event', event.eventName, {
        event_category: 'checkout',
        ...event
      });
    }
    
    // Send to backend
    fetch('/api/analytics', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(event)
    }).catch(console.error);
  }
});

// Mount
checkoutDropIn.create('checkout-drop-in-container');