🎧 Listening to Checkout Page Events
After the checkout page is generated and initialized, Deets will return tokenization events. These events contain a securely generated payment token, which is required to process a payment.
By listening to these checkout events, you can:
- ✅ Capture the payment token in real-time for seamless processing.
- ✅ Enhance security by validating transaction responses before processing.
- ✅ Improve customer experience by handling checkout success or failure efficiently.
Why Listen to Checkout Page Events? When a customer submits their payment details via Deets iFrame, sensitive card data is never exposed to your system. Instead, Deets tokenizes the payment information and returns a secure token that represents the transaction.
You must listen to these checkout events because:
- 1️⃣ The payment token is sent via the event message. Without listening to the event, you won't receive the token.
- 2️⃣ The token is required to complete a payment. You'll use it in an API request to finalize the transaction.
- 3️⃣ Security and Compliance. Deets ensures PCI compliance by sending only non-sensitive tokenized data through the event listener.
By integrating the event listener correctly, your platform remains secure, PCI-compliant, and capable of handling real-time transactions smoothly.
To capture the tokenization event, add this line of code where the checkout form is embedded inside an iFrame:
window.addEventListener("message", handleTokenizationEvent);
This event listener will detect messages from Deets iFrame, allowing your system to extract the secure payment token.
When a transaction is completed, the event contains the tokenized payment details. The event data follows these structures:
Credit Card Payments
interface TokenizationResponse {
type: "paymentCompleted";
data: {
message: "OK";
data: {
type: "tokenv3";
id: string; // Example: "474747aOlplH4747-1734960710"
attributes: {
label: "tokenv3";
customerId: string;
};
customerId: string; // Same as attributes.customerId
};
};
}
ACH Payments
interface ACHPaymentResponse {
type: "achPaymentInitiated";
data: {
merchantId: string;
miscData: string; // JSON string with additional data
bank: {
accountName: string;
accountType: string; // "checking" or "savings"
accountNumber: string; // This is the tokenized account number
routingNumber: string;
};
StandardEntryClassCode: string; // "WEB"
customer: {
firstname: string;
lastname: string;
email: string;
};
transaction: {
amount: string;
currency: string;
invoice: string;
};
encrypted_id: string;
};
}
Here's how to listen for the event, extract the token, and process it:
const handleTokenizationEvent = (event) => {
// Validate the event origin to ensure it's from Deets
// IMPORTANT: Even though you embed this on YOUR website, the origin to validate
// is the Deets checkout domain (where the iframe content comes from)
const allowedOrigins = [
'https://checkout.staging.digitzs.com',
'https://digitz-iq-ui-iframe-content.s3.us-west-2.amazonaws.com',
'https://checkout.prod.digitzs.com'
];
if (!allowedOrigins.some(origin => event.origin.includes(origin))) return;
// Handle credit card payment event
if (event.data?.type === "paymentCompleted") {
const response = event.data;
const tokenId = response.data.data.id; // Extract the token ID
const customerId = response.data.data.customerId; // Extract customer ID
console.log("Received credit card token:", tokenId);
console.log("Customer ID:", customerId);
// Send this token to your backend for payment processing
}
// Handle ACH payment event
if (event.data?.type === "achPaymentInitiated") {
const response = event.data;
// Extract relevant data for processing
const tokenizedAccountNumber = response.data.bank.accountNumber;
const merchantId = response.data.merchantId;
const routingNumber = response.data.bank.routingNumber;
console.log("Received ACH payment data:");
console.log("- Merchant ID:", merchantId);
console.log("- Tokenized Account Number:", tokenizedAccountNumber);
// Process the ACH payment with your backend
}
};
// Attach event listener
window.addEventListener("message", handleTokenizationEvent);
⚠ Important Security Considerations
When handling payment tokens, always follow best security practices:
Validate the Event Origin
Ensure the message originates from Deets' secure checkout domains:
const allowedOrigins = [
'https://checkout.staging.digitzs.com',
'https://digitz-iq-ui-iframe-content.s3.us-west-2.amazonaws.com',
'https://checkout.prod.digitzs.com'
];
if (!allowedOrigins.some(origin => event.origin.includes(origin))) return;
This prevents malicious actors from injecting fake messages.
Validate the Event Data
- Ensure the response matches the expected schema.
- Use a schema validation library (like
zodorJoi) to validate response integrity.
Handle Tokens Securely
- Never expose the payment token on the frontend. Always send it securely to your backend for further processing.
- Use HTTPS connections when sending the token to your server.
📋 TypeScript Types for Event Handling
For comprehensive type-checking in TypeScript applications, you can use this combined interface:
// Combined type for all possible checkout events
type CheckoutEventResponse = TokenizationResponse | ACHPaymentResponse;
// Parser function with type safety
function parseCheckoutEvent(event: MessageEvent): CheckoutEventResponse | null {
if (!event.data?.type) return null;
switch (event.data.type) {
case "paymentCompleted":
return event.data as TokenizationResponse;
case "achPaymentInitiated":
return event.data as ACHPaymentResponse;
default:
return null;
}
}
// Usage example
window.addEventListener("message", (event) => {
// Validate the event origin to ensure it's from Deets
const allowedOrigins = [
'https://checkout.staging.digitzs.com',
'https://digitz-iq-ui-iframe-content.s3.us-west-2.amazonaws.com',
'https://checkout.prod.digitzs.com'
];
if (!allowedOrigins.some(origin => event.origin.includes(origin))) return;
const response = parseCheckoutEvent(event);
if (!response) return;
switch (response.type) {
case "paymentCompleted":
// Handle credit card payment
const cardToken = response.data.data.id;
processCardPayment(cardToken);
break;
case "achPaymentInitiated":
// Handle ACH payment
const achToken = response.data.bank.accountNumber;
processACHPayment(achToken, response.data);
break;
}
});
🚫 Payment Error Handling Guide
🔍 Overview
This section outlines how to properly handle error events from the Deets checkout UI iframe. When payment errors occur, the checkout UI sends a standardized error message to the parent window through the postMessage API.
Add an event listener in your parent application to capture payment errors:
window.addEventListener("message", function(event) {
// Validate event origin for security
const allowedOrigins = [
'https://checkout.staging.digitzs.com',
'https://digitz-iq-ui-iframe-content.s3.us-west-2.amazonaws.com',
'https://checkout.prod.digitzs.com'
];
if (!allowedOrigins.some(origin => event.origin.includes(origin))) return;
// Handle payment errors
if (event.data && event.data.type === "paymentError") {
handlePaymentError(event.data);
}
});
function handlePaymentError(errorData) {
// Your error handling logic here
console.error("Payment error:", errorData.error);
// Show user-friendly message
showErrorToUser(errorData.error.title, errorData.error.message);
}
All payment errors follow a consistent structure:
interface PaymentErrorEvent {
type: "paymentError";
error: {
title: string; // Error category (e.g., "Payment Failed", "Risk Check Failed")
message: string; // User-friendly error message
details: string; // Technical details (JSON string or error text)
originalError?: any; // Original error object (when available)
};
}
}
Errors are categorized by their source and type:
| Error Title | Source | Description |
|---|---|---|
| "Payment Failed" | card-payment | General card payment processing error |
| "ACH Payment Failed" | ach-payment | ACH payment processing error |
| "Risk Check Failed" | kount-risk-check | Failed risk assessment check |
| "Payment Declined" | kount-declined | Payment declined by risk assessment system |
| "Card Validation Failed" | card-validation | Error validating card details |
| "ACH Validation Failed" | ach-validation | Error validating ACH account details |
| "Payment Processing Error" | tokenex | Error from the TokenEx payment tokenization service |
🛡️ Error Handling Best Practices
-
User-Friendly Messaging: Display the
error.messageto users - it's already formatted for end-users -
Logging: Log the full error details (especially
error.details) for debugging purposes -
Error Recovery Options:
- For validation errors: Highlight form fields and guide users to fix inputs
- For declined payments: Suggest using a different payment method
- For system errors: Provide a way to retry or contact support
-
Specific Error Types:
- TokenEx errors: Check for
dataV3.tokenexErrorproperties for detailed information - Validation errors: Show field-specific guidance
- Network errors: Provide retry options
- Session expired: Prompt user to refresh
- TokenEx errors: Check for
💻 Implementation Example
function handlePaymentError(errorData) {
const error = errorData.error;
const contextData = errorData.dataV3;
// Log full error for debugging
console.error(`Payment error (${contextData.input.paymentMethod}):`, error);
// Check for specific error categories
switch(true) {
case error.title.includes("Validation"):
// Handle validation errors
showValidationError(error.message);
break;
case error.title === "Payment Declined":
// Handle declined payments
showDeclinedMessage(error.message);
break;
case error.title.includes("Session"):
// Handle session expiration
showSessionExpiredMessage();
offerPageRefresh();
break;
default:
// Generic error handling
showErrorMessage(error.title, error.message);
offerSupportContact();
}
// Optional: Send error to your analytics/monitoring service
trackPaymentError({
category: error.title,
message: error.message,
paymentMethod: contextData.input.paymentMethod,
invoiceId: contextData.input.invoice
});
}
🚀 Final Thoughts
By integrating Deets' event listener, you ensure a secure, fast, and seamless payment experience while maintaining full PCI compliance.
🔹 Without this event listener, you won't receive the payment token. This token is essential to process transactions securely.
🔹 Ensure proper validation and security checks before processing any payments.
🔹 Keep your checkout experience smooth by handling payment success or failure events efficiently.
Ready to go live? Start integrating Deets today and enable real-time, secure, and PCI-compliant payments for your business! 🚀