Hosted Payments Page

Secure Payment Processing Integration Guide

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:

  1. User enters payment information in the form
  2. On form submission, public keys are fetched from the server (if not already cached)
  3. Sensitive data is encrypted using the Web Crypto API with RSA-OAEP encryption
  4. Encrypted data is base64-encoded for transmission
  5. Original plain text is cleared from the form fields
  6. Encrypted values are submitted to the server
  7. 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 ApplicationId authorization policy requires a numeric appid claim 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(/)<[^<]*)*<\/script>/gi, '');

    return sanitized;
}

paymentWidget.SetFormValues({
    "Request_Name": sanitizeInput(userName),
    "Request_Email": sanitizeInput(userEmail)
});

8. Correlation ID Management

// Generate unique correlation IDs for tracking
function generateCorrelationId() {
    return 'ORDER-' + Date.now() + '-' + Math.random().toString(36).substr(2, 9);
}

var correlationId = generateCorrelationId();

var paymentWidget = new hpp({
    // ... other config ...
    CorrelationID: correlationId,

    OnSuccess: function(response) {
        // Store correlation ID with order for audit trail
        saveOrderRecord({
            orderId: orderId,
            correlationId: correlationId,
            transactionId: response.TransactionId,
            amount: response.AuthAmount,
            timestamp: new Date().toISOString()
        });
    }
});

Security Checklist

Before Going Live:
  • ✓ All pages use HTTPS
  • ✓ Authentication tokens generated server-side
  • ✓ Token expiration times are appropriate (15-30 minutes)
  • ✓ No sensitive data logged or stored
  • ✓ Server-side transaction validation implemented
  • ✓ Rate limiting enabled
  • ✓ Content Security Policy configured
  • ✓ Input sanitization in place
  • ✓ Error handling doesn't expose sensitive information
  • ✓ Correlation IDs tracked for audit trail
  • ✓ PCI compliance validation enabled
  • ✓ Duplicate transaction prevention configured
  • ✓ Monitoring and alerting configured

Incident Response

In case of a security incident:

  1. Immediate Actions:
    • Disable affected merchant accounts
    • Revoke compromised authentication tokens
    • Review transaction logs for unauthorized activity
  2. Investigation:
    • Use correlation IDs to trace affected transactions
    • Review New Relic logs for suspicious patterns
    • Check for unauthorized access attempts
  3. Reporting:
    • Contact your Procare representative immediately
    • Provide correlation IDs and timestamps
    • Document all findings
  4. Recovery:
    • Generate new authentication tokens
    • Re-enable accounts after security review
    • Implement additional security measures as needed