Security Features
Encryption
The HPP implements multiple layers of encryption to protect sensitive payment data:
Client-Side RSA Encryption
All sensitive payment data is encrypted in the browser before transmission:
- PAN (Primary Account Number): Credit card numbers and bank account numbers are encrypted using RSA-OAEP with SHA-256
- SAD (Sensitive Authentication Data): CVV codes and card track data are encrypted using a separate RSA key
- Key Management: Public keys are fetched securely from the server and cached for the session
- Clear After Encrypt: Plain text values are immediately cleared from form fields after encryption
Encryption Implementation
The encryption process follows these steps:
- User enters payment information in the form
- On form submission, public keys are fetched from the server (if not already cached)
- Sensitive data is encrypted using the Web Crypto API with RSA-OAEP encryption
- Encrypted data is base64-encoded for transmission
- Original plain text is cleared from the form fields
- Encrypted values are submitted to the server
- Server decrypts using corresponding private keys
Supported Encryption
- Algorithm: RSA-OAEP (Optimal Asymmetric Encryption Padding)
- Hash Function: SHA-256
- Key Length: Configurable (typically 2048-bit or 4096-bit)
- Encoding: Base64 for transmission
PCI Compliance
The HPP includes built-in PCI compliance features to prevent accidental exposure of sensitive data:
Sensitive Data Protection
- Field Validation: Prevents users from entering credit card or bank account numbers in non-secure fields (name, address, email, city)
- Pattern Detection: Identifies suspicious sequences of 13+ digits that may indicate card numbers
- Substring Matching: Detects if non-secure fields contain sequences of 6+ digits from the actual payment account
- Real-time Feedback: Displays validation errors immediately when PCI violations are detected
PCI Validation Rules
// Fields checked for PCI compliance violations:
- Request_Name (cardholder name)
- Request_Address (street address)
- Request_City (city)
- Request_Email (email address)
// Validation logic:
1. Check for 13+ consecutive digits (suspicious pattern)
2. For credit cards: Check if middle digits (excluding first 2 and last 4) appear in field
3. For bank accounts: Check if any 6+ digit sequence from account appears in field
// If violation detected:
- Form submission is blocked
- Validation error is displayed
- OnValidation event is fired with error details
PCI Compliance Warning: The HPP will block form submission if sensitive payment data is detected in non-secure fields. This protects both you and your customers from accidental PCI violations.
Authentication
- Bearer Token Authentication: All API requests require a valid JWT bearer token
- Token Claim: The server's
ApplicationIdauthorization policy requires a numericappidclaim in the token; other claims (merchant ID, expiration, etc.) are validated by the JWT middleware per the configured authority - CORS Protection: Cross-origin requests are controlled via CORS policies
- Content Security Policy: CSP headers prevent XSS attacks and unauthorized script execution
Token Requirements
// JWT Token Structure
{
"header": {
"alg": "RS256",
"typ": "JWT"
},
"payload": {
"appid": "12", // Application ID (required, numeric string)
"exp": 1234567890, // Expiration timestamp
"iat": 1234567800 // Issued at timestamp
// Additional claims (iss, aud, etc.) are validated by the
// JWT bearer middleware per the configured authority.
}
}
Data Isolation
- Iframe Sandbox: Payment form runs in an isolated iframe context
- Post Message Communication: Parent and iframe communicate only via secure postMessage API
- No Direct DOM Access: Parent page cannot access payment form DOM or read sensitive fields
- Encrypted Transmission: All data is encrypted before leaving the iframe
- Same-Origin Policy: Browser enforces separation between parent and iframe
Communication Security
// Secure postMessage communication
// From parent to iframe:
window.postMessage({
type: "set_amount",
detail: { amount: 100.00, surcharge: 2.50 }
}, "*");
// From iframe to parent:
window.parent.postMessage({
type: "payment_successful",
detail: { TransactionId: "abc123", AuthAmount: 100.00 }
}, "*");
// Security notes:
// - Sensitive payment data is never sent via postMessage
// - Only encrypted values and transaction results are transmitted
// - Message types are validated before processing
Transaction Security
- Duplicate Detection: Optional duplicate transaction prevention based on amount, card, and time window
- Correlation Tracking: Each transaction includes a correlation ID for audit trails
- Expiration Validation: Credit card expiration dates are validated against current date
- Bank Account Verification: ACH transactions require double-entry verification of account numbers
- CVV Validation: Card security codes are required and validated for credit card transactions
Duplicate Transaction Prevention
// Enable duplicate detection
var paymentWidget = new hpp({
// ... other config ...
AllowDuplicateTransaction: false, // Prevent duplicates (default)
OnError: function(error) {
// Handle duplicate transaction error
if (error.includes("duplicate")) {
alert("This transaction was already processed. " +
"If you want to process it again, please wait a few minutes.");
}
}
});
// Duplicate detection checks:
// - Same card number
// - Same amount
// - Within time window (typically 5-10 minutes)
// To allow duplicate transactions (not recommended):
AllowDuplicateTransaction: true
Logging and Monitoring
- New Relic Integration: All events, errors, and transactions are logged to New Relic
- Correlation IDs: Every request includes a correlation ID for distributed tracing
- Error Tracking: Exceptions are logged with full context for debugging
- PCI-Compliant Logging: Logs never contain unencrypted payment data
- Event Logging: All user interactions and system events are logged
What Gets Logged
| Event Type | Information Logged | Contains PCI Data |
|---|---|---|
| Form Load | Correlation ID, merchant ID, payment types | No |
| Payment Type Change | New payment type selected | No |
| BIN Lookup | BIN (first 6-8 digits), card type, issuer | No (only BIN) |
| Validation Error | Field ID, error message | No |
| Form Submission | Amount, merchant ID, correlation ID | No |
| Transaction Success | Transaction ID, amount, response status | No |
| Transaction Decline | Response message, reason | No |
| Error | Error type, message, stack trace | No |
Best Security Practices
1. Always Use HTTPS
Critical Requirement: Always serve your pages over HTTPS. Modern browsers will block mixed content, preventing the HPP from loading properly if your page uses HTTP.
2. Token Management
- Generate tokens server-side with appropriate expiration times
- Never expose token generation secrets in client-side code
- Include only necessary claims in the token (merchant ID, application ID, permissions)
- Implement token refresh logic for long-lived sessions
- Use short expiration times (15-30 minutes recommended)
3. Never Store Sensitive Data
Critical: Never log, store, or transmit unencrypted payment card numbers, CVV codes, or bank account numbers. The HPP handles all encryption automatically.
// BAD - Never do this:
console.log("Card number:", cardNumber);
localStorage.setItem('cardNumber', cardNumber);
sendToAnalytics({cardNumber: cardNumber});
// GOOD - Let HPP handle sensitive data:
// HPP encrypts automatically, only transaction IDs are returned
OnSuccess: function(response) {
console.log("Transaction ID:", response.TransactionId);
localStorage.setItem('lastTransactionId', response.TransactionId);
sendToAnalytics({transactionId: response.TransactionId});
}
4. Validate Server-Side
- Always validate transaction responses on your server before fulfilling orders
- Don't rely solely on the client-side OnSuccess callback
- Verify transaction status via the backend API before considering payment complete
- Check transaction amount matches expected amount
- Verify merchant ID and correlation ID
5. Implement Rate Limiting
- Limit the number of payment attempts per session/user (e.g., 3-5 attempts)
- Monitor for suspicious patterns (many failures, repeated attempts)
- Implement CAPTCHA or other bot detection for public-facing forms
- Lock accounts after excessive failed attempts
- Alert on unusual activity patterns
6. Content Security Policy
// Recommended CSP headers for pages embedding HPP:
Content-Security-Policy:
default-src 'self';
script-src 'self' https://your-payment-domain.com;
frame-src https://your-payment-domain.com;
connect-src 'self' https://your-payment-domain.com;
style-src 'self' 'unsafe-inline';
img-src 'self' data: https:;
// This policy:
// - Allows scripts only from your domain and the HPP domain
// - Allows iframes only from the HPP domain
// - Allows connections only to your domain and HPP domain
// - Prevents inline scripts (except for inline styles)
// - Prevents loading resources from untrusted domains
7. Input Sanitization
// Sanitize any data you send to HPP via SetFormValues
function sanitizeInput(input) {
// Remove HTML tags
var div = document.createElement('div');
div.textContent = input;
var sanitized = div.innerHTML;
// Remove script-like patterns
sanitized = sanitized.replace(/