DocHub
Full 3D Secure payment flow with setup, device fingerprinting, challenge/frictionless handling, and capture

CyberSource 3DS Integration

Overview

Full rework of the CyberSource 3D Secure payment flow for BAC (Banco Atlantida) approval. Previous implementation had multiple issues flagged by Gerson (BAC reviewer): non-secure ECI indicators, auth-only (no capture), and missing brand coverage.

Payment Flow

  1. SetupPOST /api/payments/setup calls CyberSource /risk/v1/authentication-setups to get a referenceId and device data collection URL
  2. Device Fingerprint — Hidden iframe loads CyberSource device data collection page (captures browser fingerprint)
  3. PaymentPOST /api/payments sends card details + referenceId + deviceInformation (browser data)
  4. 3DS Challenge — If PENDING_AUTHENTICATION, user redirected to bank’s stepUpUrl for challenge
  5. 3DS Frictionless — If no stepUpUrl, verify inline (low-risk transaction approved without user interaction)
  6. VerifyPOST /api/payments/verify validates 3DS result and captures payment
  7. Capturecapture: true enabled (was previously auth-only)

Issues Fixed (11 total)

# Issue Fix
1 Missing CyberSource credentials on server Added from migration-data/credentials.txt to OVH3 .env.local
2 null.from() crash ordersRepo.ts imported browser-only supabase. Replaced with supabaseAdmin
3 Payment amount mismatch Aligned fee calculation base (server vs client). Increased tolerance to 50 cents
4 Exp year validation Accepted 2-digit years, auto-expand to 4-digit
5 PENDING status not handled Combined actionList returns PENDING not PENDING_AUTHENTICATION
6 Frictionless 3DS AMEX frictionless had no stepUpUrl. Added inline verify for frictionless flow
7 AMEX INVALID_ACCOUNT BAC sandbox doesn’t support AMEX. Added error handling for 2xx with errorInformation
8 3DS indicators missing Added deviceInformation (browser fingerprint) to payment request
9 httpAcceptBrowserValue field name Was using wrong field name across all files
10 Full 3DS setup flow Implemented setup → device data collection → payment with referenceId
11 Capture not enabled Changed capture: false to capture: true

Test Results

Brand veresEnrolled paresStatus ECI CAVV Indicator Status
Visa Y Y 05 Present vbv Captured
Mastercard Y Y ucafCollectionIndicator: 2 spa Captured
AMEX INVALID_ACCOUNT (sandbox limitation)

AMEX Status

BAC requires all three brands (Visa, MC, AMEX). AMEX test cards return INVALID_ACCOUNT on the CyberSource sandbox — appears to be a sandbox/merchant config issue. The code handles AMEX correctly (detects card type 003, sends proper 3DS setup). Pending confirmation from Gerson/BAC whether AMEX needs to be enabled on the sandbox merchant account.

Files

File Purpose
src/app/api/payments/setup/route.ts New — CyberSource authentication setup endpoint
src/app/api/payments/route.ts supabaseAdmin, deviceInformation, capture, error handling
src/app/api/payments/verify/route.ts supabaseAdmin fix
src/app/cart/page.tsx 3DS setup flow, device data collection, frictionless handling
src/lib/orderTotalCalculator.ts supabaseAdmin, fee base alignment
src/services/paymentApi.ts deviceInformation and referenceId types