A modern React + TypeScript implementation of CardCom's Open Fields feature, providing a PCI-compliant payment gateway that integrates seamlessly into existing forms with customizable styling.
- Intro
- Basic Workflow
- Project Structure
- Setup & Installation
- Environment Configuration
- List of Actions
- Backend Requirements
- Security Features
- Additional Features
- Customization
- Development
This feature allows developers to integrate secure payment fields into existing forms while maintaining complete control over styling and user experience. By utilizing iframes and the postMessage API, you get a PCI-approved payment method that looks and feels exactly how you want.
Key Benefits:
- 🔒 PCI Compliance - Secure iframe-based payment processing
- 🎨 Full Customization - Style payment fields to match your brand
- ⚡ Modern React/TypeScript - Built with latest React 19 and TypeScript
- 🌐 3DS Support - Built-in 3D Secure authentication
- 💳 Google Pay Integration - Alternative payment method included
- 📱 Responsive Design - Mobile-friendly implementation
You are required to add a postMessage event listener and 4 specific iframes to your form:
- Master Iframe (
CardComMasterFrame) - Manages all operations - Credit Card Input (
CardComCardNumber) - Secure card number input - CVV Input (
CardComCvv) - Secure CVV input - Google Pay (
CardComGooglePay) - Alternative payment method - Credits Footer (
CardcomCredits) - CardCom branding
-
Create LowProfile Deal: Use CardCom's LowProfile API to create a payment session (handled by backend to protect API credentials)
-
Initialize Iframes: Send configuration message to master iframe with styling and LowProfile code using the
initmessage -
Handle User Input: Collect additional form data (expiration dates, customer info)
-
Submit Transaction: Send
doTransactionmessage with all payment data -
Handle Response: Process success/error responses from CardCom
src/
├── components/
│ ├── CheckoutForm.tsx # Main payment form with iframes
│ └── Summary.tsx # Order summary component
├── css/
│ └── cardNumber.css # Styling for card number field
├── types.ts # TypeScript type definitions
├── App.tsx # Main application component
├── index.css # Global styles
└── main.tsx # Application entry point
- Node.js 18+
- npm or yarn
- Backend server for LowProfile deal creation
- Clone and Install Dependencies
npm install- Configure Environment Variables
cp .env.example .env
# Edit .env with your configuration- Start Development Server
npm run dev- Start Backend Server (separate repository/implementation required)
# Your backend should handle /init endpoint
# Example: http://127.0.0.1:8000/initCreate a .env file with the following variables:
# Backend Configuration - Your server handling LowProfile creation
VITE_BACKEND_URL=http://127.0.0.1:8000
# CardCom Configuration
VITE_CARDCOM_URL=https://secure.cardcom.solutions
VITE_CARDCOM_TERMINAL_NUMBER=1000
# Development Settings
VITE_DEV_MODE=true
VITE_ENABLE_DEBUG=true
# Test Configuration
VITE_TEST_CARD_NUMBER=4580000000000000
# Application Info
VITE_APP_NAME=Cardcom Open Fields
VITE_APP_VERSION=1.0.0Initializes the iframes with styling and configuration:
{
action: 'init',
cardFieldCSS: string, // CSS for card number field
cvvFieldCSS: string, // CSS for CVV field
reCaptchaFieldCSS: string, // CSS for reCaptcha
placeholder: '1111-2222-3333-4444',
cvvPlaceholder: '123',
lowProfileCode: string // From backend LowProfile creation
}Submits the payment with all required data:
{
action: 'doTransaction',
cardOwnerId: string,
cardOwnerName: string,
cardOwnerEmail: string,
expirationMonth: string, // MM format
expirationYear: string, // YY format
cardOwnerPhone: string,
numberOfPayments: string,
document?: DocumentData // Optional invoice/receipt data
}addCvvFieldClass/removeCvvFieldClassaddCardNumberFieldClass/removeCardNumberFieldClass
Updates card owner information for prefill and validation. This step is required for Google Pay payments:
{
action: 'setCardOwnerDetails',
data: {
cardOwnerName: string,
cardOwnerEmail: string,
cardOwnerPhone: string
}
}Contains payment processing results:
{
action: 'HandleSubmit',
data: {
IsSuccess: boolean,
Description: string,
ResponseCode: number,
InternalDealNumber: number,
// ... additional response fields
}
}Reports payment processing errors:
{
action: 'HandleEror',
message: string,
isError: boolean,
IsDeveloperError?: boolean,
IsInputError?: boolean
}Real-time field validation feedback:
{
action: 'handleValidations',
field: 'cardNumber' | 'cvv' | 'reCaptcha',
isValid: boolean
}Triggered when Google Pay payment begins processing. Used for triggering loading gifs
Those methods allow to validate the fields in the iframes, you can invoke them from your form validation logic. Meant to allow you to enable / disable the "pay" button in your form according to the fields validations. The result will return under "handleValidations" message with the field name and the result. Same behavior occurs on focus out event of those the fields.
{
masterRef.current?.contentWindow?.postMessage({ action: "validateCvv" }, '*');
masterRef.current?.contentWindow?.postMessage({ action: "validateCardNumber" }, '*');
}Your backend must implement an /init endpoint that:
- Creates LowProfile Deal using CardCom API
- Returns LowProfile Code to frontend
- Handles API Credentials securely
Example backend response:
{
"LowProfileId": "63fca7b4-85a8-4698-9f17-a1739920d958"
}Security Note: Never expose CardCom API credentials in frontend code.
- Payment data never touches your servers
- Secure iframe isolation prevents data access
- Industry-standard encryption
- Automatic 3DS challenge handling
- Seamless authentication flow
- Enhanced fraud protection
- postMessage API for secure communication
- No payment data stored locally
- Tokenization support
- One-click payment option
- Automatic customer data prefill
- Mobile-optimized experience
Create invoices or receipts automatically:
document: {
DocumentTypeToCreate: "Receipt" | "Invoice" | "Other",
Products: [{
ProductID: "ui-321",
Description: "Product Description",
Quantity: 1,
UnitCost: 9.99,
TotalLineCost: 9.99
}]
}- Mobile-first approach
- Flexible layout system
- Cross-browser compatibility
- Instant field validation feedback
- Custom error styling
- Accessibility support
Modify CSS in iframe initialization:
const cardFieldCSS = `
.cardNumber {
border: 2px solid #your-color;
border-radius: 8px;
padding: 12px;
font-size: 16px;
background: #your-background;
}
.cardNumber.invalid {
border-color: #error-color;
}
`;Extend the onValidation function:
const onValidation = (field: string, isValid: boolean) => {
// Custom validation logic
if (!isValid) {
showCustomErrorMessage(field);
}
};Update global CSS variables in src/index.css:
:root {
--primary-color: #your-brand-color;
--error-color: #your-error-color;
--border-radius: 8px;
}npm run dev # Start development server
npm run build # Build for production
npm run lint # Run ESLint
npm run preview # Preview production build- Start Server - Launch PHP development server
- Run In Browser - Open application in browser
- Run In Terminal - Execute PHP scripts
- React 19 - Latest React with concurrent features
- TypeScript 5.8 - Type safety and developer experience
- Vite 7 - Fast build tool and dev server
- ESLint - Code quality and consistency
Test with CardCom's sandbox environment:
- Test terminal number:
1000(No deposits, you can't be charged) - Test terminal username:
test2025(this is frequentrly changed so contact support to get the latest) - Test Card:
4580000000000000 - Any future expiration date
- Any 3-digit CVV
Need Help? Contact CardCom support at support@cardcom.solutions.co.il or +972-03-