Module 7: Visa BASE I/II - Slides

Slide 1: Visa's Scale

                    VISA BY THE NUMBERS (2023)

   ┌────────────────────────────────────────────────────────────┐
   │                                                            │
   │         212 BILLION TRANSACTIONS                           │
   │                                                            │
   │               $14.8 TRILLION VALUE                         │
   │                                                            │
   │              ~6,700 TRANSACTIONS / SECOND                  │
   │                                                            │
   │              ~65% OF GLOBAL CARD VOLUME                    │
   │                                                            │
   └────────────────────────────────────────────────────────────┘

   Every single transaction is an ISO8583 message.
   But it's VISA's ISO8583—not vanilla.

   If you work in payments, you WILL work with VisaNet.
1 / 25

Slide 2: The Dual Message Architecture

                 BASE I vs BASE II

  ┌─────────────────────────────┐  ┌─────────────────────────────┐
  │         BASE I              │  │         BASE II             │
  │    Authorization System     │  │   Clearing & Settlement     │
  ├─────────────────────────────┤  ├─────────────────────────────┤
  │                             │  │                             │
  │  • Real-time processing     │  │  • Batch processing         │
  │  • 0100/0110, 0400/0410     │  │  • TC05/TC07 files          │
  │  • < 2 second response      │  │  • Overnight runs           │
  │  • TCP/IP over dedicated    │  │  • File transfers           │
  │  • "Can this card pay?"     │  │  • "Here's what happened"   │
  │                             │  │                             │
  └─────────────────────────────┘  └─────────────────────────────┘

  WHY TWO SYSTEMS?
  In 1973, real-time data was expensive.
  Split the problem: fast approval, detailed settlement later.

  This module focuses on BASE I (real-time authorization).
2 / 25

Slide 3: Visa Transaction Flow

  Terminal        Acquirer         VisaNet           Issuer
     │               │                │                │
     │               │    BASE I (Real-Time)          │
     │               │                │                │
     ├──── 0100 ────►├──── 0100 ─────►├──── 0100 ────►│
     │   Auth Req    │                │                │ Approve?
     │               │                │                │
     │◄─── 0110 ────┤◄─── 0110 ─────┤◄─── 0110 ─────┤
     │   Auth Resp   │                │ Assigns       │
     │               │                │ Transaction   │
     │               │                │ ID            │
     │               │                │                │
     ·               ·    BASE II (Batch)             ·
     ·               ·                ·                ·
     │               ├──── TC05 ─────►├──── TC05 ────►│
     │               │   Clearing     │   Settlement  │
     │               │   (overnight)  │   (overnight) │
     │               │                │                │

  BASE I: "Can I charge $50?"
  BASE II: "Here's the detail for that $50 charge"
3 / 25

Slide 4: Visa MTI Usage

                   VISA MESSAGE TYPE INDICATORS

  Authorization:
  ┌────────────────────────────────────────────────────────────┐
  │  0100  Authorization Request                               │
  │  0110  Authorization Response                              │
  │  0120  Authorization Advice (store-and-forward)           │
  │  0130  Authorization Advice Response                       │
  └────────────────────────────────────────────────────────────┘

  Reversals:
  ┌────────────────────────────────────────────────────────────┐
  │  0400  Reversal Request                                    │
  │  0410  Reversal Response                                   │
  │  0420  Reversal Advice                                     │
  │  0430  Reversal Advice Response                            │
  └────────────────────────────────────────────────────────────┘

  Network Management:
  ┌────────────────────────────────────────────────────────────┐
  │  0800  Network Management Request (sign-on, echo)          │
  │  0810  Network Management Response                         │
  └────────────────────────────────────────────────────────────┘

  NOTE: Visa uses 0100/0110 primarily (auth only).
        0200/0210 (financial) used in some single-message regions.
4 / 25

Slide 5: The Private Data Elements

                    VISA'S PRIVATE FIELDS

  ISO8583 reserves DE48-63 and DE>120 as "private use".
  Visa uses three heavily:

  ┌────────────────────────────────────────────────────────────┐
  │  DE48: Additional Data - Private Use                       │
  │        └─ Supplementary transaction data                   │
  │        └─ Merchant advice codes                            │
  │        └─ TLV subelements                                  │
  └────────────────────────────────────────────────────────────┘

  ┌────────────────────────────────────────────────────────────┐
  │  DE62: Custom Payment Service Data                         │
  │        └─ Authorization Characteristics Indicator          │
  │        └─ Transaction qualifiers                           │
  └────────────────────────────────────────────────────────────┘

  ┌────────────────────────────────────────────────────────────┐
  │  DE63: THE BIG ONE                                         │
  │        └─ Transaction ID (from VisaNet)                    │
  │        └─ CVV2 results                                     │
  │        └─ Multiple TLV subelements                         │
  │        └─ Most integration failures happen here            │
  └────────────────────────────────────────────────────────────┘
5 / 25

Slide 6: DE63 Structure

                      DE63 ANATOMY

  ┌───────────────────────────────────────────────────────────┐
  │ Bytes 1-3:  Total length ("035" = 35 bytes follow)        │
  │ Bytes 4-5:  Network ID ("VS" for Visa)                    │
  │ Bytes 6+:   Subelements                                   │
  └───────────────────────────────────────────────────────────┘

  Subelement Format:
  ┌─────┬──────────┬────────────────────────────────────────┐
  │ ID  │  Length  │              Value                     │
  │ (1) │   (2)    │           (variable)                   │
  └─────┴──────────┴────────────────────────────────────────┘

  Example:
  "035VS115412345678901232I24020M"
   │  │ │ │               │ │ │ │
   │  │ │ │               │ │ │ └─ Value: "M" (CVV2 Match)
   │  │ │ │               │ │ └─ Length: 02
   │  │ │ │               │ └─ Subelement 4
   │  │ │ │               └─ Value: "I2"
   │  │ │ └─ Value: "541234567890123" (15-char TxnID)
   │  │ └─ Subelement 1, Length 15
   │  └─ Network ID "VS"
   └─ Total length 35
6 / 25

Slide 7: Critical DE63 Subelements

                  MOST IMPORTANT SUBELEMENTS

  Subelement 1: Transaction ID (15 bytes)
  ────────────────────────────────────────
  • Assigned by VisaNet
  • Links auth → clearing → disputes
  • MUST store this for reconciliation

  Subelement 2: Auth Characteristics Indicator (2 bytes)
  ─────────────────────────────────────────────────────
  Position 1:  Card Presence
    I = Chip present    M = Magnetic stripe
    N = Card not present

  Position 2:  Verification Method
    1 = Signature    2 = PIN    3 = No CVM

  Subelement 3: Validation Code (4 bytes)
  ───────────────────────────────────────
  CVV2/CVC2 result:
    M = Match         N = No Match
    P = Not Processed S = Should be present
    U = Issuer not certified

  WARNING: "N" doesn't mean decline!
  Issuer may approve despite CVV2 mismatch.
7 / 25

Slide 8: DE63 Parsing in Go

type VisaDE63 struct {
    NetworkID          string            // "VS"
    TransactionID      string            // Subelement 1
    AuthCharIndicator  string            // Subelement 2
    ValidationCode     string            // Subelement 3
    RawSubelements     map[int][]byte
}

func ParseDE63(data []byte) (*VisaDE63, error) {
    if len(data) < 2 {
        return nil, errors.New("DE63 too short")
    }

    result := &VisaDE63{
        NetworkID:      string(data[0:2]),
        RawSubelements: make(map[int][]byte),
    }

    pos := 2
    for pos+3 <= len(data) {
        subID := int(data[pos] - '0')
        length, _ := strconv.Atoi(string(data[pos+1:pos+3]))
        pos += 3

        if pos+length > len(data) {
            break
        }
        result.RawSubelements[subID] = data[pos:pos+length]
        pos += length
    }

    return result, nil
}
8 / 25

Slide 9: Transaction Identifiers

               VISA TRANSACTION ID HIERARCHY

  ┌─────────────────────────────────────────────────────────────┐
  │                                                             │
  │  ACQUIRER ASSIGNS:                VISANET ASSIGNS:          │
  │                                                             │
  │  ┌───────────────────┐           ┌───────────────────┐      │
  │  │ STAN (DE11)       │           │ Transaction ID    │      │
  │  │ "123456"          │           │ (DE63 SE1)        │      │
  │  │ 6 digits          │           │ "543210987654321" │      │
  │  │ Unique per day    │           │ 15 characters     │      │
  │  └───────────────────┘           │ Globally unique   │      │
  │                                  └───────────────────┘      │
  │  ┌───────────────────┐                                      │
  │  │ RRN (DE37)        │                                      │
  │  │ "432512345678"    │                                      │
  │  │ 12 characters     │                                      │
  │  │ Acquirer reference│                                      │
  │  └───────────────────┘                                      │
  │                                                             │
  │  MATCHING KEY = STAN + Date + Acquirer ID + Transaction ID  │
  │                                                             │
  │  For disputes: Transaction ID is the master key             │
  │                                                             │
  └─────────────────────────────────────────────────────────────┘
9 / 25

Slide 10: Visa Response Codes

                   VISA RESPONSE CODE CATEGORIES

  APPROVED (00-10):
  ┌──────────────────────────────────────────────────────────┐
  │  00 = Approved                                           │
  │  01 = Refer to issuer (call)                            │
  │  05 = Do not honor (generic decline)                     │
  │  10 = Partial approval                                   │
  └──────────────────────────────────────────────────────────┘

  CARD ISSUES (41-65):
  ┌──────────────────────────────────────────────────────────┐
  │  41 = Lost card - pickup                                 │
  │  43 = Stolen card - pickup                               │
  │  51 = Insufficient funds                                 │
  │  54 = Expired card                                       │
  │  55 = Incorrect PIN                                      │
  │  61 = Exceeds withdrawal limit                           │
  │  65 = Soft decline (frequency exceeded)                  │
  └──────────────────────────────────────────────────────────┘

  SYSTEM ISSUES (91-96):
  ┌──────────────────────────────────────────────────────────┐
  │  91 = Issuer unavailable (retry)                         │
  │  94 = Duplicate transmission                             │
  │  96 = System malfunction (retry)                         │
  └──────────────────────────────────────────────────────────┘
10 / 25

Slide 11: Merchant Advice Codes

             DE48 TAG 26: MERCHANT ADVICE CODE

  ┌────────────────────────────────────────────────────────────┐
  │                                                            │
  │  Code  Meaning                         Action              │
  │  ────  ───────────────────────────────  ─────────────────  │
  │                                                            │
  │   01   New account info available      Update card data    │
  │                                                            │
  │   02   Cannot approve now, try again   Retry later         │
  │                                                            │
  │   03   Do not try again                Stop recurring      │
  │                                                            │
  │   04   Token requirements not met      Check tokenization  │
  │                                                            │
  │   21   Payment cancellation request    Cancel subscription │
  │                                                            │
  │   24   Retry after 24 hours            Wait then retry     │
  │                                                            │
  └────────────────────────────────────────────────────────────┘

  CRITICAL for recurring payments:
  Code 03 = Cardholder asked issuer to stop this merchant!
11 / 25

Slide 12: Visa Quirk #1 - Bitmap Format

              VISA ALWAYS USES HEX-ASCII BITMAPS

  Pure ISO8583 allows:
  ┌────────────────────────────────────────────────────────────┐
  │  Binary:    72 3A 44 81 08 E1 80 00     (8 bytes)          │
  │  Hex-ASCII: "723A448108E18000"          (16 characters)    │
  └────────────────────────────────────────────────────────────┘

  Visa BASE I requires:
  ┌────────────────────────────────────────────────────────────┐
  │  ALWAYS Hex-ASCII: "723A448108E18000"   (16 characters)    │
  └────────────────────────────────────────────────────────────┘

  Why? Human-readable in logs, easier debugging.

  TRAP: If you send binary bitmap, Visa will reject:
  ┌────────────────────────────────────────────────────────────┐
  │  Sent:     72 3A 44 81 08 E1 80 00   (8 binary bytes)      │
  │  Visa saw: Some garbage starting with "r:" (ASCII)          │
  │  Result:   Format error, DE39 = 30                         │
  └────────────────────────────────────────────────────────────┘
12 / 25

Slide 13: Visa Quirk #2 - Time Zones

                VISA REQUIRES GMT/UTC

  All timestamp fields must be in GMT:

  ┌────────────────────────────────────────────────────────────┐
  │  DE7:   Transmission Date/Time   → GMT                     │
  │  DE12:  Local Time               → Convert to GMT          │
  │  DE13:  Local Date               → Convert to GMT          │
  └────────────────────────────────────────────────────────────┘

  COMMON BUG:
  ┌─────────────────────────────────────────────────────────────┐
  │  // WRONG - Uses local timezone                            │
  │  de7 := time.Now().Format("0102150405")                    │
  │                                                             │
  │  // RIGHT - Explicit UTC                                    │
  │  de7 := time.Now().UTC().Format("0102150405")              │
  └─────────────────────────────────────────────────────────────┘

  Symptom: Transactions dated on wrong day
  Cause:   Server in UTC+8, using local time
           9:00 AM local = 1:00 AM UTC (yesterday!)
13 / 25

Slide 14: Visa Quirk #3 - Track 2 Sentinels

             STRIP START/END SENTINELS

  Track 2 on magnetic stripe:
  ┌────────────────────────────────────────────────────────────┐
  │  ;4532015112830366=25121011234?                            │
  │  ↑                             ↑                           │
  │  Start sentinel               End sentinel                 │
  └────────────────────────────────────────────────────────────┘

  Pure ISO8583: May include sentinels
  Visa:         Strip them!

  DE35 for Visa:
  ┌────────────────────────────────────────────────────────────┐
  │  4532015112830366=25121011234                              │
  │  (No ; at start, no ? at end)                              │
  └────────────────────────────────────────────────────────────┘

  Why? Visa's parser doesn't expect them.
  Including sentinels = format error.
14 / 25

Slide 15: DE62 Authorization Characteristics

              DE62 POSITION 1-2 FORMAT

  Position 1: Transaction Type
  ┌────────────────────────────────────────────────────────────┐
  │  A = Auto fuel dispenser                                   │
  │  C = Card present, not read                               │
  │  E = E-commerce                                            │
  │  F = Fallback to magnetic stripe                           │
  │  M = MOTO (mail/telephone order)                           │
  │  P = Card present, read successfully                       │
  │  R = Recurring payment                                     │
  └────────────────────────────────────────────────────────────┘

  Position 2: Authentication Method
  ┌────────────────────────────────────────────────────────────┐
  │  0 = No authentication                                     │
  │  1 = Signature                                             │
  │  2 = PIN                                                   │
  │  5 = No CVM performed                                      │
  └────────────────────────────────────────────────────────────┘

  Examples:
    "P2" = Card present with PIN
    "E0" = E-commerce, no auth
    "R0" = Recurring, no CVM
15 / 25

Slide 16: TLV Parsing - Simple Format

            VISA'S SIMPLE TLV (DE48, DE63)

  Format:
  ┌─────────────────────────────────────────────────────────────┐
  │  Tag    : 1 byte (ASCII digit or letter)                    │
  │  Length : 2 bytes (ASCII digits "00"-"99")                  │
  │  Value  : Variable (per length)                             │
  └─────────────────────────────────────────────────────────────┘

  Example: "115Hello World!"
           │││└───────────┘
           │││    Value (11 bytes)
           ││└── Length: "15" ... wait, that's wrong

  Let me show correctly:
  "111Hello World"
   │ │└──────────┘
   │ │   Value (11 bytes)
   │ └── Length: "11"
   └── Tag: "1"


  Parsing loop:
  pos = 0
  while pos < len(data):
      tag = data[pos]           # 1 byte
      len = atoi(data[pos+1:3]) # 2 bytes as decimal
      val = data[pos+3:pos+3+len]
      pos += 3 + len
16 / 25

Slide 17: TLV Parsing - EMV Format (DE55)

              EMV BER-TLV (DE55 - Chip Data)

  More complex than simple TLV:

  Tag (1-3 bytes):
  ┌────────────────────────────────────────────────────────────┐
  │  If first byte ends in 1F: multi-byte tag                  │
  │  Example: 9F26 (2-byte tag)                                │
  └────────────────────────────────────────────────────────────┘

  Length (1-3 bytes):
  ┌────────────────────────────────────────────────────────────┐
  │  ≤ 127: Single byte is length                              │
  │  > 127: First byte = 0x81/0x82, next byte(s) = length      │
  └────────────────────────────────────────────────────────────┘

  Example (hex):
    9F 26 08 A1B2C3D4E5F6A7B8
    └───┘ └┘ └──────────────┘
     Tag  Len    Value (8 bytes)

  Common EMV Tags:
    9F26 = Application Cryptogram (ARQC/TC/AAC)
    9F27 = Cryptogram Information Data
    9F10 = Issuer Application Data
    9F37 = Unpredictable Number
17 / 25

Slide 18: Building a Visa Auth Request

func BuildVisaAuthRequest(card, merchant) *Message {
    msg := NewMessage()

    // Standard ISO8583
    msg.SetMTI("0100")
    msg.SetField(2, card.PAN)
    msg.SetField(3, "000000")           // Purchase
    msg.SetField(4, "000000010000")     // $100.00
    msg.SetField(7, utcNow("0102150405"))
    msg.SetField(11, generateSTAN())
    msg.SetField(14, card.Expiry)
    msg.SetField(22, "051")             // Chip read
    msg.SetField(32, merchant.AcqID)
    msg.SetField(35, stripSentinels(card.Track2))
    msg.SetField(37, generateRRN())
    msg.SetField(41, merchant.TerminalID)
    msg.SetField(42, merchant.MerchantID)
    msg.SetField(49, "840")             // USD

    // VISA-SPECIFIC
    msg.SetField(62, "P2")  // Card present, PIN

    // DE63 populated by VisaNet in response

    return msg
}
18 / 25

Slide 19: Parsing Visa Response

func ParseVisaResponse(data []byte) (*AuthResponse, error) {
    msg, err := ParseMessage(data)
    if err != nil {
        return nil, err
    }

    resp := &AuthResponse{
        ResponseCode: msg.GetField(39),
        AuthCode:     msg.GetField(38),
        RRN:          msg.GetField(37),
    }

    // CRITICAL: Parse DE63 for Visa data
    if de63 := msg.GetField(63); de63 != "" {
        visa, err := ParseDE63([]byte(de63))
        if err != nil {
            log.Warn("DE63 parse failed:", err)
            // Don't fail entirely - DE39 is still valid
        } else {
            resp.TransactionID = visa.TransactionID
            resp.CVVResult = visa.ValidationCode
        }
    }

    // Store TransactionID for disputes!
    if resp.TransactionID != "" {
        storeForReconciliation(resp.TransactionID, resp)
    }

    return resp, nil
}
19 / 25

Slide 20: Common Production Issues

           TOP 5 VISA INTEGRATION FAILURES

  1. DE63 LENGTH MISMATCH
     ─────────────────────
     Symptom: Parser crash
     Cause:   LLLVAR length doesn't match content
     Fix:     Verify len(content) == declared_length

  2. TRANSACTION ID MISSING
     ───────────────────────
     Symptom: Empty DE63
     Cause:   VisaNet rejected early (DE39 != 00)
     Fix:     Check response code first

  3. TIMEZONE DRIFT
     ───────────────
     Symptom: Wrong date on transactions
     Cause:   Using local time instead of UTC
     Fix:     time.Now().UTC() everywhere

  4. CVV2 CONFUSION
     ───────────────
     Symptom: "CVV mismatch but approved"
     Cause:   CVV result (N) != auth result (00)
     Fix:     Check DE39 for approval, DE63 SE3 for CVV

  5. CHARACTER ENCODING
     ──────────────────
     Symptom: DE43 rejected
     Cause:   Non-ASCII characters
     Fix:     Sanitize to ASCII only
20 / 25

Slide 21: Debugging Checklist

           VISA DEBUGGING CHECKLIST

  □ BITMAP FORMAT
    Is it hex-ASCII (16 chars), not binary (8 bytes)?

  □ TIMESTAMP TIMEZONE
    Are DE7, DE12, DE13 all in UTC/GMT?

  □ TRACK 2 SENTINELS
    Are ; and ? stripped from DE35?

  □ DE63 PARSING
    1. Check network ID = "VS"
    2. Verify length prefix matches content
    3. Parse subelements in order

  □ TRANSACTION ID STORAGE
    Are you saving DE63 SE1 for every authorization?

  □ RESPONSE CODE HANDLING
    Are you checking DE39 before assuming DE63 is complete?

  □ CHARACTER SET
    Is DE43 ASCII-only (no accents, no CJK)?

  □ AMOUNTS
    Integer format? Minor units? No decimal points?
21 / 25

Slide 22: Case Study - The Phantom Approval

           THE PHANTOM APPROVAL MYSTERY

  SYMPTOMS:
  ┌────────────────────────────────────────────────────────────┐
  │  Processor log: DE39=00, AuthCode=123456                   │
  │  Issuer log:    No matching transaction                    │
  │  Customer:      "Charged but didn't get product"           │
  └────────────────────────────────────────────────────────────┘

  INVESTIGATION:
  ┌────────────────────────────────────────────────────────────┐
  │  Transaction IDs didn't match any issuer records.          │
  │  Where did the processor get this response?                │
  │                                                            │
  │  Discovery: Load balancer had response cache               │
  │  Cache key: STAN only (6 digits)                           │
  │  STAN resets daily - can repeat!                           │
  │  Old response matched to new request!                      │
  └────────────────────────────────────────────────────────────┘

  ROOT CAUSE:
  ┌────────────────────────────────────────────────────────────┐
  │  WRONG: cacheKey = stan                                    │
  │  RIGHT: cacheKey = stan + date + acquirerId                │
  └────────────────────────────────────────────────────────────┘

  LESSON: STAN alone is NEVER sufficient for matching.
22 / 25

Slide 23: Quick Reference Card

┌──────────────────────────────────────────────────────────────┐
│              VISA BASE I QUICK REFERENCE                     │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│ MESSAGE TYPES:                                               │
│   0100/0110: Authorization request/response                  │
│   0400/0410: Reversal request/response                       │
│   0800/0810: Network management                              │
│                                                              │
│ KEY VISA FIELDS:                                             │
│   DE62: Auth characteristics (Position 1-2)                  │
│   DE63: Transaction ID + subelements (TLV)                   │
│                                                              │
│ DE63 CRITICAL SUBELEMENTS:                                   │
│   SE1: Transaction ID (15 bytes) - MUST STORE                │
│   SE2: Auth Char Indicator (2 bytes)                         │
│   SE3: CVV2 Result (M/N/P/S/U)                               │
│                                                              │
│ VISA QUIRKS:                                                 │
│   • Hex-ASCII bitmaps only                                   │
│   • GMT/UTC for all timestamps                               │
│   • Strip Track 2 sentinels                                  │
│   • ASCII only in DE43                                       │
│                                                              │
│ MATCHING KEY:                                                │
│   STAN + Date + Acquirer ID + Transaction ID                 │
│                                                              │
└──────────────────────────────────────────────────────────────┘
23 / 25

Slide 24: Key Takeaways

              WHAT YOU MUST REMEMBER

  1. DUAL MESSAGE SYSTEM
     BASE I = real-time auth (ISO8583)
     BASE II = batch clearing (file-based)

  2. DE63 IS CRITICAL
     Contains Transaction ID, CVV result, auth indicators
     Parse it on every response
     Store Transaction ID for disputes

  3. VISA-SPECIFIC REQUIREMENTS
     • Hex-ASCII bitmaps
     • UTC timestamps
     • No Track 2 sentinels
     • ASCII-only merchant name

  4. TRANSACTION MATCHING
     STAN alone is insufficient
     Use STAN + date + acquirer + Transaction ID

  5. RESPONSE CODES
     Check DE39 before parsing DE63
     Decline codes may have minimal DE63
     Merchant Advice Code (DE48) tells what to do next

  REMEMBER: ~65% of global card transactions flow through
  VisaNet. Mastering Visa's ISO8583 variant is essential.
24 / 25

Slide 25: Next Steps

               APPLY YOUR KNOWLEDGE

  Problem 1: visa-de63-parser
  ────────────────────────────
  Parse Visa's Field 63 TLV structure
  • Extract Transaction ID (SE1)
  • Parse Auth Characteristics (SE2)
  • Handle variable subelements
  • Robust error handling


  Problem 2: visa-message-adapter
  ────────────────────────────────
  Convert generic ISO8583 to Visa format
  • Add Visa-specific DE62, DE63
  • Convert bitmaps to hex-ASCII
  • Handle timezone conversion
  • Strip Track 2 sentinels


  These problems simulate real Visa integration work.
  The skills transfer directly to production systems.
25 / 25
Use arrow keys or click edges to navigate. Press H to toggle help, F for fullscreen.