This secure payment API solves the critical problem of payment fingerprint harvesting while maintaining the business requirement of publicly shareable booking links. The system implements a multi-layered security architecture with token-based booking access and nonce-based payment protection.
- Fingerprints burn on ANY attempt - not just successful payments
- No feedback mechanism when fingerprints are consumed
- Shareable booking links required - no user authentication possible
Without proper protection, attackers could:
- Mass harvest payment fingerprints by automated requests
- Enumerate booking IDs to access payment pages
- Burn legitimate payment attempts through abuse
- Cause payment failures with no recovery mechanism
graph TB A[Public Booking Link] --> B[256-bit Secure Token] B --> C[Token Validation] C --> D[Booking Data Access] D --> E[Payment Button Click] E --> F[Nonce Generation] F --> G[API Key + Nonce Validation] G --> H[Payment Fingerprint Creation] H --> I[Single-Use Protection]
- Token-Based Booking Access - 256-bit cryptographically secure tokens replace direct booking ID access
- Dual Authentication for Payments - API key + nonce requirement for payment fingerprint creation
- Single-Use Nonces - IP-bound, 15-minute expiry, marked as used immediately
- Environment Protection - Server fails to start without required credentials
- Rate Limiting - Per-endpoint throttling prevents abuse
- Input Validation - Dynamic schema validation against OpenAPI specifications
src/
├── config/
│ └── environment.ts # Environment validation & required secrets enforcement
├── database/
│ ├── database.ts # SQLite database wrapper with connection management
│ └── schema.ts # Database schema with booking tokens & security tables
├── gateway/
│ └── apiGateway.ts # Centralized entry point - all routing & security control
├── handlers/
│ ├── bookingHandler.ts # Token-based booking access & token generation
│ ├── paymentHandler.ts # Nonce generation & dual-auth payment fingerprints
│ ├── turnstileHandler.ts # Cloudflare Turnstile CAPTCHA verification
│ └── webhookHandler.ts # Generic webhook processing (separate concern)
├── middleware/
│ ├── cors.ts # Multi-origin CORS validation & security headers
│ ├── rateLimit.ts # Per-endpoint rate limiting with memory cache
│ └── security.ts # Pattern detection & suspicious activity monitoring
├── services/
│ ├── authService.ts # Token generation & API key validation
│ ├── nonceService.ts # Cryptographically secure nonce management
│ ├── paymentService.ts # SHA3-512 fingerprint generation with server credentials
│ ├── schemaValidationService.ts # Dynamic OpenAPI schema validation
│ └── validationService.ts # Input sanitization & format validation
├── types/
│ └── types.ts # TypeScript interfaces for type safety
└── utils/
├── logger.ts # Structured security event logging
├── openApiLoader.ts # Dynamic OpenAPI specification loading
└── sanitizer.ts # SQL injection prevention utilities
sequenceDiagram participant S as Server Start participant E as Environment participant G as API Gateway participant D as Database participant O as OpenAPI Loader participant L as Logger S->>E: Validate Required Secrets Note over E: PAYMENT_USERNAME, PAYMENT_PASSWORD,<br/>MERCHANT_CODE, API_KEY E-->>S: ✅ Secrets Valid or ❌ Exit(1) S->>G: Initialize API Gateway G->>D: Initialize Database D->>D: Create Tables & Indexes D->>D: Insert Sample Data D-->>G: ✅ Database Ready G->>O: Load OpenAPI Spec O->>O: Parse YAML & Validate O->>O: Extract Endpoints & Security O-->>G: ✅ Specification Loaded G->>L: Display Startup Info L->>L: Log 12 Endpoints Found L->>L: Log Security Features L-->>G: ✅ Startup Complete G-->>S: 🚀 Server Ready on Port 5000
sequenceDiagram participant C as Client participant G as Gateway participant CM as CORS Middleware participant RM as Rate Limit participant SM as Security Middleware participant H as Handler participant DB as Database C->>G: HTTP Request Note over G: Extract method, path, headers G->>CM: CORS Validation CM->>CM: Check Origin Header CM->>CM: Validate Against Allowed Origins CM-->>G: ✅ Pass or ❌ 403 Forbidden G->>RM: Rate Limiting Check RM->>RM: Check IP + Endpoint Limits RM->>RM: Update Request Counter RM-->>G: ✅ Pass or ❌ 429 Too Many Requests G->>SM: Security Validation SM->>SM: Pattern Detection SM->>SM: Header Validation SM->>SM: Input Sanitization SM-->>G: ✅ Pass or ❌ Security Block G->>H: Route to Handler H->>H: Authentication Check Note over H: API Key / Token / Nonce H->>DB: Database Operations DB-->>H: Query Results H->>H: Response Preparation H-->>G: Response Object G->>G: Add Security Headers G-->>C: HTTP Response
sequenceDiagram participant A as Admin participant S as Server participant U as User participant DB as Database Note over A,DB: Token Generation (Admin) A->>S: POST /api/generate-booking-token Note over S: API Key Required S->>S: Validate API Key S->>S: Generate 256-bit Token S->>DB: Store Token + Booking ID + Expiry S-->>A: Return Token & Shareable URL Note over U,DB: Booking Access (Public) U->>S: GET /booking/{token} S->>DB: Validate Token (exists, not expired) S->>DB: Get Booking ID from Token S->>DB: Fetch Booking Details S-->>U: Return Booking Information
Client Requirements:
- Admin: Must provide API key in
Authorization: Bearer {key}header - Public Users: No authentication required - just use the token URL
sequenceDiagram participant C as Client participant S as Server participant DB as Database participant PG as Payment Gateway Note over C,PG: Phase 1: Nonce Generation C->>S: POST /api/create-payment-nonce Note over S: Rate Limited: 5 req/min S->>S: Validate Booking ID S->>S: Generate 64-char Hex Nonce S->>DB: Store Nonce + IP + 15min Expiry S-->>C: Return Nonce + Expiry Note over C,PG: Phase 2: Payment Fingerprint Creation C->>S: POST /api/create-payment-hash Note over S: Dual Auth: API Key + Nonce S->>S: Validate API Key S->>S: Validate Nonce (exists, unused, not expired, IP match) S->>DB: Mark Nonce as USED S->>S: Inject Server Credentials S->>S: Generate SHA3-512 Fingerprint S-->>C: Return Payment Fingerprint Note over C,PG: Phase 3: Payment Gateway C->>PG: Submit Payment with Fingerprint PG-->>C: Payment Result
Client Requirements:
- Nonce Request: Provide valid
bookingIdin request body - Payment Hash: Must include both:
Authorization: Bearer {api_key}headerX-Payment-Nonce: {nonce}header- Valid payment data (amount, merchantUniquePaymentId, timestamp)
sequenceDiagram participant C as Client participant S as Server participant DB as Database Note over C,DB: Payment Failed - Need Fresh Session C->>S: POST /api/v1/payment/refresh S->>S: Validate Booking ID S->>DB: Invalidate Existing Nonces for Booking S->>DB: Generate Fresh Payment Data S-->>C: Return Fresh Session Data Note over C: User can now request new nonce
Purpose: Access booking information using secure token Authentication: None (public endpoint) Security: Token-based access prevents booking ID enumeration
// Frontend Usage
const response = await fetch(`/booking/${token}`);
const { booking } = await response.json();
Purpose: Generate secure shareable booking links (Admin only) Authentication: API Key required Security: Prevents unauthorized token generation
// Admin Usage
const response = await fetch('/api/generate-booking-token', {
method: 'POST',
headers: {
'Authorization': 'Bearer your_api_key',
'Content-Type': 'application/json'
},
body: JSON.stringify({ bookingId: 'booking_123' })
});
const { token, shareableUrl } = await response.json();
Purpose: Generate single-use nonce for payment attempts Authentication: None (rate limited) Security: 5 requests/minute, IP-bound nonces
// Frontend Usage
const response = await fetch('/api/create-payment-nonce', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ bookingId: 'booking_123' })
});
const { nonce, expiresIn } = await response.json();
Purpose: Exchange nonce for payment fingerprint Authentication: API Key + Nonce required Security: Dual authentication prevents unauthorized access
// Frontend Usage - CRITICAL SECURITY
const response = await fetch('/api/create-payment-hash', {
method: 'POST',
headers: {
'Authorization': 'Bearer your_api_key',
'X-Payment-Nonce': nonce,
'Content-Type': 'application/json'
},
body: JSON.stringify({
apikey: 'payment_gateway_key',
mode: '0',
paymentAmount: '1200.00',
merchantUniquePaymentId: generateUUID(),
timestamp: getCurrentTimestamp()
})
});
const { fingerprint, merchantCode, redirectUrl } = await response.json();
Purpose: Refresh payment session after failures Authentication: None (rate limited) Security: Invalidates existing nonces, provides fresh session
// Frontend Usage - After Payment Failure
const response = await fetch('/api/v1/payment/refresh', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ bookingId: 'booking_123' })
});
const { booking, paymentData } = await response.json();
Purpose: Verify Cloudflare Turnstile CAPTCHA token Authentication: None (rate limited) Security: Additional CAPTCHA protection layer
// Frontend Usage
const response = await fetch('/api/v1/turnstile/verify', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ token: turnstileToken })
});
const { success } = await response.json();
// 1. UUID Generation for Payment IDs
function generateUUID() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
// 2. Timestamp Generation (ISO format without timezone)
function getCurrentTimestamp() {
return new Date().toISOString().slice(0, 19); // "2025-07-04T05:15:00"
}
// 3. Error Handling for Payment Failures
function handlePaymentError() {
// Must refresh page or call refresh endpoint
// Cannot reuse burned nonces
alert('Payment failed. Please refresh the page to try again.');
window.location.reload();
}
class SecurePaymentFlow {
constructor(apiKey) {
this.apiKey = apiKey;
}
async initiatePayment(bookingId, amount) {
try {
// Step 1: Generate nonce
const nonceResponse = await fetch('/api/create-payment-nonce', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ bookingId })
});
const { nonce } = await nonceResponse.json();
// Step 2: Create payment hash with dual authentication
const hashResponse = await fetch('/api/create-payment-hash', {
method: 'POST',
headers: {
'Authorization': `Bearer ${this.apiKey}`,
'X-Payment-Nonce': nonce,
'Content-Type': 'application/json'
},
body: JSON.stringify({
apikey: 'payment_gateway_key',
mode: '0',
paymentAmount: amount,
merchantUniquePaymentId: this.generateUUID(),
timestamp: this.getCurrentTimestamp()
})
});
const paymentData = await hashResponse.json();
// Step 3: Initialize payment gateway
return this.initializePaymentGateway(paymentData);
} catch (error) {
console.error('Payment initialization failed:', error);
this.handlePaymentError();
}
}
generateUUID() { /* implementation above */ }
getCurrentTimestamp() { /* implementation above */ }
handlePaymentError() { /* implementation above */ }
}
- Booking ID Enumeration: Tokens prevent direct access to booking IDs
- Mass Fingerprint Harvesting: Dual authentication blocks unauthorized requests
- Replay Attacks: Single-use nonces with IP binding prevent reuse
- Rate Limiting: Prevents automated abuse attempts
- Environment Security: Required secrets prevent unauthorized deployment
- PCI DSS Alignment: No sensitive payment data stored or logged
- GDPR Compliance: Minimal data collection with automatic cleanup
- Industry Standards: 256-bit tokens, SHA3-512 hashing, structured logging
- Audit Trail: Comprehensive security event logging for compliance
The system also includes generic webhook processing capabilities for external integrations:
Purpose: Process any JSON payload from external systems Authentication: API Key required Usage: Third-party system notifications
Purpose: Identical to webhook for maximum flexibility
Authentication: API Key required
Usage: Payment gateway callbacks, external service notifications
These endpoints are separate from the core payment security system and handle generic webhook processing with proper authentication and audit logging.
PAYMENT_USERNAME=your_payment_gateway_username PAYMENT_PASSWORD=your_payment_gateway_password MERCHANT_CODE=your_merchant_code API_KEY=your_secure_api_key_256_bit
- All environment variables configured
- CORS origins set to production domains
- Rate limiting thresholds reviewed
- SSL/TLS certificates installed
- Monitoring and alerting configured
- Database backups scheduled
- Security event logging enabled
The system is designed for production deployment with enterprise-grade security controls and comprehensive audit capabilities.