Dev.to Security 🔐 Cybersecurity 👁 0 📖 3 min read

Defeating Friendly Fraud with Visa Compelling Evidence 3.0: The Exact Data Schema

When a cardholder files a dispute under Visa Reason Code 10.4 ("Fraud - Card-Absent Environment"), merchants historically faced low win rates. The merchant bore the burden of proving that the legitimate cardholder actual

When a cardholder files a dispute under Visa Reason Code 10.4 ("Fraud - Card-Absent Environment"), merchants historically faced low win rates. The merchant bore the burden of proving that the legitimate cardholder actually authorized and received the digital goods or service.

Under Visa Compelling Evidence 3.0 (CE 3.0), if a merchant can provide deterministic proof of qualifying historical transactions between the customer and their platform, liability shifts back to the issuing bank before a formal chargeback is finalized.

However, the evidentiary requirements are rigid. If your telemetry fails to match the required schema, the rebuttal is rejected.

Here is the exact data structure your payment logging pipeline must capture to satisfy Visa CE 3.0 rules.

The Rule of Historical Qualification

To invoke CE 3.0 on a disputed transaction, you must present evidence of at least two prior non-disputed transactions that satisfy three conditions:

  1. Age: The transactions must have settled between 120 and 365 calendar days prior to the disputed transaction date.
  2. Payment Credential: The transactions must have used the identical core account number (PAN) or network payment token.
  3. Core Identifiers: At least two core data elements must match identically across both historical transactions AND the disputed transaction.

The 4 Recognized Core Data Elements

Visa recognizes four specific data elements for establishing identity in digital environments:

  1. IP Address: The public client IP captured at checkout.
  2. Device Fingerprint / Device ID: A persistent cryptographic hash generated from device attributes.
  3. User Account ID / Login Credential: The unique merchant-assigned identifier (e.g., user UUID or validated customer profile ID).
  4. Delivery Address: Physical shipping address or validated endpoint destination.

Of these four, one of the matching elements MUST be either the IP Address or the Device ID. A match on User Account ID and Shipping Address alone is insufficient without network-level identity.

Transaction Schema Definition

To automate this defense, your backend checkout service should persist a normalized transaction fingerprint record upon every authorization:

interface CE30TransactionRecord {
  transactionId: string;
  panFingerprint: string; // SHA-256 hash of PAN or network token
  settlementDate: string;  // ISO-8601 UTC
  disputed: boolean;

  // Visa CE 3.0 Matching Elements
  clientIp: string;
  deviceId: string;
  accountUserId: string;
  shippingAddressHash?: string;

  // Qualifying Signals
  cvvMatch: boolean;
  avsResultCode: string;
}

Automating the Historical Match Algorithm

When a pre-dispute alert (via Verifi CDRN or Order Insight) arrives via webhook, your system must scan previous settled transactions to compile the historical pair:

from datetime import datetime, timedelta

def find_ce30_qualifiers(disputed_tx, historical_txs):
    """
    Evaluates historical transactions to identify qualifying Visa CE 3.0 pairs.
    """
    dispute_date = datetime.fromisoformat(disputed_tx["settlement_date"])
    window_start = dispute_date - timedelta(days=365)
    window_end = dispute_date - timedelta(days=120)

    candidates = []
    for tx in historical_txs:
        if tx.get("disputed", False):
            continue

        tx_date = datetime.fromisoformat(tx["settlement_date"])
        if not (window_start <= tx_date <= window_end):
            continue

        # Verify PAN fingerprint match
        if tx["pan_fingerprint"] != disputed_tx["pan_fingerprint"]:
            continue

        # Score matching core elements
        matches = {
            "ip": tx["client_ip"] == disputed_tx["client_ip"],
            "device": tx["device_id"] == disputed_tx["device_id"],
            "user_id": tx["account_user_id"] == disputed_tx["account_user_id"]
        }

        # Check rule: At least 2 matches, where one is IP or Device
        has_network_match = matches["ip"] or matches["device"]
        match_count = sum(matches.values())

        if match_count >= 2 and has_network_match:
            candidates.append(tx)

    # Visa requires at least TWO distinct qualifying historical transactions
    if len(candidates) >= 2:
        return True, candidates[:2]

    return False, []

Common Traps in Implementation

  1. IPv6 vs IPv4 Mismatches: Mobile users frequently transition between IPv6 cellular connections and residential Wi-Fi (IPv4). Relying strictly on exact IP equality without robust device fingerprinting causes many legitimate qualifying transactions to miss the match criteria.
  2. Ephemeral Guest Checkouts: Allowing unauthenticated checkouts without generating a stable device fingerprint leaves you with zero core identifiers to link historical purchases.
  3. Overly Aggressive Data Pruning: Many engineering teams purge raw connection logs after 90 days. If your transaction database does not retain the required hashed core elements for at least 365 days, you cannot produce the necessary historical evidence.

Building compliance into your payment pipeline before chargebacks occur transforms friendly fraud disputes from an expensive manual chore into an automated, programmatic win.

Audit your chargeback evidence against Visa CE 3.0 rules free: https://rebuttaldesk.pages.dev/?src=devto

📰 Read the original article on Dev.to Security

Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.