Before deploying CityPay Elements to production, ensure the following security controls are in place.

These controls are designed to:

  • maintain a reduced PCI DSS scope
  • protect cardholder data and authentication flows
  • support PCI DSS v4 expectations and common security reviews

They apply whether you are using Direct or Proxy (middleware) integration modes.


Credential handling

API Keys

  • API Keys must be stored and used on the backend only.
  • API Keys must never be exposed in client-side code, build artefacts, or logs.
  • Keys should be rotated periodically and revoked when no longer required.
  • Test and production API Keys must be strictly separated.

Public Keys

  • Public Keys are safe to embed in browser applications.
  • Public Keys are used only to initialise the Elements SDK.
  • Public Keys do not grant access to merchant APIs or sensitive operations.
  • Separate Public Keys should be used for test and production environments.

Session Tokens

  • Session Tokens are short-lived, intent-scoped credentials generated by your backend.
  • A Session Token is always associated with a specific Payment Intent.
  • Session Tokens authorise the browser to perform limited client-side actions for that intent.
  • Session Tokens must be generated server-side and delivered to the browser securely.
  • Session Tokens must not be reused across intents or sessions.

Opaque Intent Keys

  • Payment Intents expose an opaque key used internally to bind browser and backend operations.
  • Opaque keys must be treated as confidential operational identifiers.
  • Opaque keys must not be logged or exposed beyond their intended scope.

Transport security

  • All payment-related traffic must use HTTPS.
  • HTTP Strict Transport Security (HSTS) should be enabled on production domains.
  • Mixed-content requests must not be permitted.

Content Security Policy (CSP)

A restrictive Content Security Policy must be configured to explicitly allow CityPay resources while denying all others by default.

At a minimum:

  • CityPay domains must be allow-listed for:
    • script-src
    • frame-src
    • connect-src
  • All other sources should be denied unless explicitly required.

Illustrative example (adjust to your environment):

Content-Security-Policy:
  default-src 'none';
  script-src 'self' https://*.citypay.com;
  frame-src https://*.citypay.com;
  connect-src 'self' https://*.citypay.com;

Additionally:

  • Configure frame-ancestors to prevent unauthorised embedding.
  • Avoid wildcarding unrelated third-party domains.

Iframe and embedding controls

  • CityPay-hosted iframes must be allowed to render without sandbox restrictions that interfere with payment flows.
  • Merchant pages should be protected from hostile embedding using frame-ancestors or equivalent controls.
  • Applications must not attempt to inspect iframe contents or intercept postMessage traffic.

Backend endpoint hardening

For any middleware or proxy endpoints:

  • API Keys must never be exposed to the browser.
  • Endpoints should accept path-only URLs by default.
  • Absolute URLs should be explicitly whitelisted if external forwarding is required.
  • Input payloads must be validated strictly.
  • Authentication and authorisation must be enforced.
  • Rate limiting should be applied to payment-related routes.

Session binding and intent isolation

  • Every browser session must be bound to a single Payment Intent via a Session Token.
  • Client-side operations must be rejected if the Session Token does not match the intended Payment Intent.
  • Expired or invalid Session Tokens must fail safely and require re-issuance from the backend.
  • Do not allow browser-driven operations without a valid Session Token.

Idempotency and retries

  • Always propagate the SDK-generated idempotencyKey to backend → CityPay API calls.
  • The same idempotency key must be reused for retries of the same logical attempt.
  • Idempotency keys should be stored or cached for the duration of the payment flow.
  • New idempotency keys should be generated only when starting a new attempt.

Logging and data handling

  • Card numbers (PAN), CVV/CVC values, and magnetic-stripe data must never be logged.
  • 3DS challenge payloads and authentication artefacts must never be logged.
  • Session Tokens and opaque intent keys must not be logged.
  • Tokens and intent identifiers should be treated as sensitive operational data.
  • Logs should be correlated using:
  • intentId
  • idempotencyKey
  • Elements event names (cpe:*)
  • Access to logs must be restricted and retention policies defined.

Frontend integration hygiene

  • Elements must be initialised client-side only and never during server-side rendering.
  • Mount containers must exist and be visible before initialisation.
  • Payment submission controls should be disabled during cpe:processing:start.
  • Errors emitted via cpe:error should be handled gracefully with user-safe messaging.
  • No custom handling of raw card data should exist outside Elements components.

Environment separation

  • Test and production environments must be fully isolated.
  • Separate API Keys, Public Keys, and endpoints must be used for each environment.
  • Production frontends must never reference test credentials or services.

Apple Pay Production Readiness

If you are using Apple Pay:

  • Ensure your production domain is registered and whitelisted with CityPay.
  • Verify that your domain association file is hosted correctly at /.well-known/apple-developer-merchantid-domain-association.
  • Test the flow in an Apple-supported browser (Safari) on a compatible device.

Final validation before launch

Before enabling production traffic:

  • Complete an end-to-end payment using a real 3DS challenge.
  • Verify frictionless and challenge authentication flows.
  • Confirm correct behaviour for declines and retries.
  • Ensure refunds and captures are correctly linked to the originating Payment Intent.
  • Review CSP reports and browser console output for warnings or violations.

Shared responsibility model

CityPay is responsible for:

  • hosted payment components
  • tokenisation
  • authentication orchestration (3DS)
  • Payment Intent state management
  • payment processing infrastructure

You remain responsible for:

  • securing your application and backend systems
  • protecting credentials and Session Tokens
  • enforcing transport and browser security controls
  • implementing Elements in accordance with this documentation