Module 5: Transaction Flows & Message Matching - Slides
1 / 25
┌────────────────────────────────────────────────────────────────┐
│ THE FUNDAMENTAL PATTERN │
├────────────────────────────────────────────────────────────────┤
│ │
│ Every request expects a response. │
│ Every request gets a response... or a timeout. │
│ │
│ ┌──────────┐ ┌──────────┐ │
│ │ Terminal │───── 0100 ────────────►│ Network │ │
│ │ │ │ │ │
│ │ │◄───── 0110 ────────────│ │ │
│ └──────────┘ └──────────┘ │
│ │
│ MTI Pattern: │
│ ┌─────────────┬─────────────┐ │
│ │ Request │ Response │ │
│ ├─────────────┼─────────────┤ │
│ │ 0100 │ 0110 │ Authorization │
│ │ 0120 │ 0130 │ Financial Advice │
│ │ 0200 │ 0210 │ Financial │
│ │ 0400 │ 0410 │ Reversal │
│ │ 0800 │ 0810 │ Network Management │
│ └─────────────┴─────────────┘ │
│ │
│ Rule: Response MTI = Request MTI + 10 │
│ │
└────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────┐
│ AUTHORIZATION FLOW │
├────────────────────────────────────────────────────────────────┤
│ │
│ Terminal Acquirer Network Issuer │
│ │ │ │ │ │
│ │─── 0100 ─────►│ │ │ │
│ │ │─── 0100 ─────►│ │ │
│ │ │ │─── 0100 ─────►│ │
│ │ │ │ │ │
│ │ │ │ │ Auth? │
│ │ │ │ │ │
│ │ │ │◄─── 0110 ─────│ │
│ │ │◄─── 0110 ─────│ │ │
│ │◄─── 0110 ─────│ │ │ │
│ │ │ │ │ │
│ │
│ Typical timing: 1-3 seconds end-to-end │
│ Timeout threshold: 30-60 seconds │
│ │
│ 0100 Fields: 0110 Fields: │
│ ├─ DE2 (PAN) ├─ DE2-4 (echoed) │
│ ├─ DE3 (Processing Code) ├─ DE11 (echoed) │
│ ├─ DE4 (Amount) ├─ DE37 (RRN - new) │
│ ├─ DE11 (STAN) ├─ DE38 (Auth Code - new) │
│ └─ DE41 (Terminal ID) └─ DE39 (Response Code) │
│ │
└────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────┐
│ HOW RESPONSES FIND REQUESTS │
├────────────────────────────────────────────────────────────────┤
│ │
│ Problem: Terminal sends multiple requests. Response arrives. │
│ Which request does it belong to? │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ MATCHING KEY │ │
│ │ │ │
│ │ DE11 (STAN) + DE12 (Local Time) + DE32 (Acquirer ID) │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ Example: │
│ ┌─────────────────────────────────────────┐ │
│ │ Request: │ │
│ │ DE11 = "123456" │ │
│ │ DE12 = "143045" │──┐ │
│ │ DE32 = "999888" │ │ │
│ └─────────────────────────────────────────┘ │ │
│ │ MATCH │
│ ┌─────────────────────────────────────────┐ │ │
│ │ Response: │ │ │
│ │ DE11 = "123456" │ │ │
│ │ DE12 = "143045" │◄─┘ │
│ │ DE32 = "999888" │ │
│ │ DE39 = "00" (approved!) │ │
│ └─────────────────────────────────────────┘ │
│ │
└────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────┐
│ SYSTEMS TRACE AUDIT NUMBER (DE11) │
├────────────────────────────────────────────────────────────────┤
│ │
│ STAN = 6-digit number, unique per terminal per day │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ 000001 → 000002 → ... → 999999 → 000001 (wrap) │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ CRITICAL REQUIREMENTS: │
│ ┌──────────────────────────────────────────────┐ │
│ │ 1. Thread-safe generation (no race conditions)│ │
│ │ 2. Monotonically increasing within settlement │ │
│ │ 3. Unique per terminal, not globally │ │
│ │ 4. Persisted across restarts │ │
│ └──────────────────────────────────────────────┘ │
│ │
│ What happens with duplicate STANs: │
│ │
│ 14:30:45 ─── 0100 (STAN=123456) ───► │
│ 14:30:46 ─── 0100 (STAN=123456) ───► BUG! │
│ 14:30:47 ◄─── 0110 (STAN=123456) ─── Which one? │
│ │
│ Result: Chaos. Double charges or lost responses. │
│ │
└────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────┐
│ STORE-AND-FORWARD (SAF) │
├────────────────────────────────────────────────────────────────┤
│ │
│ When the network is down, transactions don't stop. │
│ Terminals approve offline and send later. │
│ │
│ NORMAL FLOW: │
│ Terminal ─── 0100 ───► Network ─── 0110 ───► Terminal │
│ (real-time) │
│ │
│ SAF FLOW: │
│ Terminal ─── [offline approval] ───► Local Storage │
│ │
│ ... network comes back ... │
│ │
│ Terminal ─── 0120 (advice) ───► Network │
│ Terminal ◄─── 0130 ───────────── Network │
│ │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ KEY DIFFERENCE │ │
│ │ │ │
│ │ 0100 = "Can this happen?" (request) │ │
│ │ 0120 = "This happened." (advice/notification) │ │
│ │ │ │
│ │ Issuer MUST accept 0120 (within floor limits) │ │
│ └───────────────────────────────────────────────────────┘ │
│ │
│ DE25 = 06 indicates offline transaction │
│ │
└────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────┐
│ WHY REVERSALS EXIST │
├────────────────────────────────────────────────────────────────┤
│ │
│ SCENARIO 1: TIMEOUT │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Terminal ─── 0100 ───► Network │ │
│ │ ... 30 seconds, no response ... │ │
│ │ Terminal ─── 0400 ───► Network "Cancel it" │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ SCENARIO 2: CUSTOMER CANCELLATION │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Terminal ─── 0100 ───► Network ─── 0110 ───► Terminal │ │
│ │ Customer: "Actually, I don't want this." │ │
│ │ Terminal ─── 0400 ───► Network "Cancel it" │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ SCENARIO 3: SYSTEM ERROR │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Terminal ─── 0100 ───► Network ─── 0110 ───► Terminal │ │
│ │ ... terminal crashes before receipt ... │ │
│ │ Terminal ─── 0400 ───► Network "Unsure, reverse it" │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ The rule: When in doubt, REVERSE. │
│ │
└────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────┐
│ REVERSAL REQUEST (0400) │
├────────────────────────────────────────────────────────────────┤
│ │
│ The reversal must reference the original transaction. │
│ │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ FROM ORIGINAL: │ │
│ │ DE2 = PAN (same) │ │
│ │ DE3 = Processing Code (same) │ │
│ │ DE4 = Amount (same, or partial) │ │
│ │ DE32 = Acquirer ID (same) │ │
│ │ DE37 = RRN from 0110 response │ │
│ │ DE38 = Auth Code from 0110 response │ │
│ │ DE41 = Terminal ID (same) │ │
│ │ │ │
│ │ NEW FOR REVERSAL: │ │
│ │ DE7 = Current transmission time │ │
│ │ DE11 = NEW STAN (not original) │ │
│ │ DE12 = Current local time │ │
│ │ DE90 = Original Data Elements ← THE KEY FIELD │ │
│ └────────────────────────────────────────────────────────┘ │
│ │
│ DE90 Structure (42 characters): │
│ ┌────┬──────┬──────────┬───────────┬───────────┐ │
│ │MTI │ STAN │ DateTime │ Acquirer │ Forwarder │ │
│ │ 4 │ 6 │ 10 │ 11 │ 11 │ │
│ └────┴──────┴──────────┴───────────┴───────────┘ │
│ Example: "0100123456122914304599988800000099988800000" │
│ │
└────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────┐
│ REVERSAL RESPONSE (0410) CODES │
├────────────────────────────────────────────────────────────────┤
│ │
│ DE39 in 0410 response: │
│ │
│ ┌──────┬────────────────────────────────────────────────┐ │
│ │ Code │ Meaning │ │
│ ├──────┼────────────────────────────────────────────────┤ │
│ │ 00 │ Reversal successful - original reversed │ │
│ │ 12 │ Invalid transaction - nothing to reverse │ │
│ │ 25 │ Unable to locate record - original not found │ │
│ │ 21 │ No action taken - already reversed │ │
│ │ 96 │ System malfunction - try again │ │
│ └──────┴────────────────────────────────────────────────┘ │
│ │
│ IMPORTANT: Response code != success guarantee │
│ │
│ What to do on failure: │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Code 12/14: Original already posted → Queue for refund │ │
│ │ Code 25: Original not found → Verify with issuer │ │
│ │ Code 96: System error → Retry with 0421 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ If 0400 fails repeatedly, send 0420 (Reversal Advice) │
│ │
└────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────┐
│ REVERSAL ADVICE (0420) │
├────────────────────────────────────────────────────────────────┤
│ │
│ When reversal requests fail, send a reversal ADVICE. │
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Terminal ─── 0400 ───► Network (no response) │ │
│ │ Terminal ─── 0400 ───► Network (no response) │ │
│ │ Terminal ─── 0400 ───► Network (no response) │ │
│ │ │ │
│ │ Terminal: "I've tried 3 times. I'm reversing anyway." │ │
│ │ │ │
│ │ Terminal ─── 0420 ───► Network (advice) │ │
│ │ Network ─── 0430 ───► Terminal (acknowledged) │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ KEY DIFFERENCE │ │
│ │ │ │
│ │ 0400 = "Please reverse this" (request, can fail) │ │
│ │ 0420 = "I'm reversing this" (advice, declaration) │ │
│ │ │ │
│ │ The terminal has already voided the transaction. │ │
│ │ The 0420 is just a notification. │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────┐
│ REVERSAL DECISION TREE │
├────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────┐ │
│ │ Send 0100 │ │
│ └────────┬────────┘ │
│ │ │
│ ┌────────▼────────┐ │
│ │ Got response? │ │
│ └────────┬────────┘ │
│ YES │ NO │
│ ┌──────────┴──────────┐ │
│ │ │ │
│ ┌────────▼────────┐ ┌────────▼────────┐ │
│ │ DE39 = 00? │ │ TIMEOUT │ │
│ └────────┬────────┘ │ Send 0400 │ │
│ YES │ NO └────────┬────────┘ │
│ ┌──────────┴─────┐ │ │
│ │ │ ┌────────▼────────┐ │
│ ┌─────▼─────┐ ┌──────▼────┐ │ Got 0410? │ │
│ │ Approved │ │ Declined │ └────────┬────────┘ │
│ │ Complete │ │ Log it │ YES │ NO │
│ └─────┬─────┘ └───────────┘ ┌─────┴─────┐ │
│ │ │ │ │
│ ┌─────▼─────┐ ┌──────▼────┐ ┌────▼────┐ │
│ │ Local OK? │ │ Reversed │ │ Retry │ │
│ └─────┬─────┘ │ Done │ │ 0400 │ │
│ YES │ NO └───────────┘ └────┬────┘ │
│ ┌───┴───┐ │ │
│ ┌─▼─┐ ┌───▼───┐ ┌──────▼──────┐ │
│ │OK │ │ 0400 │ │ Still fails?│ │
│ └───┘ └───────┘ └──────┬──────┘ │
│ │ │
│ ┌──────▼──────┐ │
│ │ Send 0420 │ │
│ │ (Advice) │ │
│ └─────────────┘ │
│ │
└────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────┐
│ NETWORK MANAGEMENT MESSAGES │
├────────────────────────────────────────────────────────────────┤
│ │
│ Before financial messages flow, the session must be set up. │
│ │
│ SIGN-ON (DE70 = 001): │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Terminal ─── 0800 (Sign-On) ───► Network │ │
│ │ Network ─── 0810 (DE39=00) ───► Terminal │ │
│ │ │ │
│ │ "Hello, I'm Terminal TERM0001. Let me in." │ │
│ │ "Welcome. You're authenticated." │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ECHO TEST (DE70 = 301): │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Terminal ─── 0800 (Echo) ───► Network │ │
│ │ Network ─── 0810 ───► Terminal │ │
│ │ │ │
│ │ Purpose: Keep-alive, network health check │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ KEY EXCHANGE (DE70 = 101/102): │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Terminal ─── 0800 (Key Req) ───► Network │ │
│ │ Network ─── 0810 (New Keys) ───► Terminal │ │
│ │ │ │
│ │ Purpose: Exchange encryption keys for PIN/MAC │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────┐
│ NETWORK MANAGEMENT INFORMATION CODE (DE70) │
├────────────────────────────────────────────────────────────────┤
│ │
│ ┌───────┬─────────────────────────────────────────────────┐ │
│ │ Code │ Function │ │
│ ├───────┼─────────────────────────────────────────────────┤ │
│ │ 001 │ Sign-On │ │
│ │ 002 │ Sign-Off │ │
│ │ 101 │ Key Exchange Request │ │
│ │ 102 │ Key Exchange Response (Acknowledgment) │ │
│ │ 161 │ New Key (Push from Network) │ │
│ │ 162 │ New Key Acknowledgment │ │
│ │ 201 │ Cutover (Switch to new processing date) │ │
│ │ 202 │ Cutover Complete │ │
│ │ 301 │ Echo Test │ │
│ │ 302 │ Echo Test Response │ │
│ └───────┴─────────────────────────────────────────────────┘ │
│ │
│ TYPICAL DAILY SEQUENCE: │
│ │
│ 06:00 ─── 0800 (Sign-On) ───► │
│ 06:00 ─── 0800 (Key Exchange) ───► │
│ 06:00 ─── 0800 (Echo) ───► (periodic throughout day) │
│ ... financial transactions ... │
│ 23:00 ─── 0800 (Cutover) ───► │
│ 23:00 ─── 0800 (Sign-Off) ───► │
│ │
└────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────┐
│ THE TIMEOUT PROBLEM │
├────────────────────────────────────────────────────────────────┤
│ │
│ A timeout doesn't mean failure. It means UNCERTAINTY. │
│ │
│ SCENARIO A: Request never arrived │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Terminal ─── 0100 ──X (packet lost) │ │
│ │ │ │
│ │ Outcome: Network never saw it. Safe to retry/reverse. │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ SCENARIO B: Response was lost │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Terminal ─── 0100 ───► Network ───► Issuer (APPROVED) │ │
│ │ Terminal ◄─── 0110 ──X (packet lost) │ │
│ │ │ │
│ │ Outcome: Charge went through! MUST REVERSE. │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ SCENARIO C: Still processing │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Terminal ─── 0100 ───► Network ───► Issuer (thinking...)│ │
│ │ Terminal gives up after 30s │ │
│ │ │ │
│ │ Outcome: Approval might come later! MUST REVERSE. │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ THE TERMINAL CANNOT DISTINGUISH THESE CASES. │
│ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ │
│ Rule: On timeout, ALWAYS send reversal. │
│ │
└────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────┐
│ TIMEOUT CONFIGURATION │
├────────────────────────────────────────────────────────────────┤
│ │
│ type TimeoutConfig struct { │
│ AuthorizationTimeout time.Duration // 30-60s │
│ ReversalTimeout time.Duration // 30s │
│ ReversalRetries int // 3 │
│ ReversalRetryDelay time.Duration // 30s │
│ ReversalAdviceThreshold int // 2-3 │
│ } │
│ │
│ TIMELINE: │
│ │
│ 0s Send 0100 │
│ │ │
│ 30s Timeout! Send 0400 (reversal #1) │
│ │ │
│ 60s Timeout! Send 0400 (reversal #2) │
│ │ │
│ 90s Timeout! Send 0420 (reversal advice) │
│ │ │
│ ? Receive 0430 → Done │
│ │
│ KEY INSIGHT: │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ After ReversalAdviceThreshold failed 0400s, │ │
│ │ switch from REQUEST (0400) to ADVICE (0420). │ │
│ │ │ │
│ │ 0400 = "Please reverse" (might be denied) │ │
│ │ 0420 = "I reversed it" (just notifying) │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────┐
│ HANDLING LATE RESPONSES │
├────────────────────────────────────────────────────────────────┤
│ │
│ What if a response arrives AFTER the timeout? │
│ │
│ TIMELINE: │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ 0s ─── 0100 ───► (sent) │ │
│ │ 30s TIMEOUT! Start reversal │ │
│ │ 31s ─── 0400 ───► (reversal sent) │ │
│ │ 32s ◄─── 0110 ─── (LATE! Original response) │ │
│ │ 35s ◄─── 0410 ─── (Reversal response) │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
│ func HandleLateResponse(resp *Message, tx *Transaction) { │
│ switch tx.State { │
│ case StateTimedOut: │
│ // Already reversing - ignore but log │
│ log.Printf("Late 0110 for STAN %s", resp.DE11) │
│ return │
│ │
│ case StateReversalSent: │
│ if resp.MTI == "0410" { │
│ // Reversal response - process normally │
│ tx.State = StateReversed │
│ } │
│ // Late 0110 - ignore, reversal in progress │
│ return │
│ │
│ case StateReversed: │
│ // Already done - ignore everything │
│ return │
│ } │
│ } │
│ │
└────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────┐
│ TRANSACTION STATE MACHINE │
├────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────┐ │
│ │ INITIAL │ │
│ └────┬────┘ │
│ │ send 0100 │
│ ┌────▼────┐ │
│ │ SENT │ │
│ └────┬────┘ │
│ ┌──────────────┼──────────────┐ │
│ │ │ │ │
│ 0110 (00) 0110 (other) timeout │
│ │ │ │ │
│ ┌────▼────┐ ┌────▼────┐ ┌────▼────┐ │
│ │APPROVED │ │DECLINED │ │TIMEDOUT │ │
│ └────┬────┘ └─────────┘ └────┬────┘ │
│ │ │ │
│ complete? send 0400 │
│ ┌────┴────┐ │ │
│ YES NO ┌────────▼────────┐ │
│ │ │ │ REVERSAL_SENT │ │
│ ┌────▼────┐ │ └────────┬────────┘ │
│ │COMPLETE │ │ ┌────────────┼────────────┐ │
│ └─────────┘ │ │ │ │ │
│ │ 0410 (00) 0410 (other) timeout │
│ send 0400 │ │ │ │
│ │ ┌────▼────┐ ┌────▼────┐ │ │
│ │ │REVERSED │ │ RETRY │◄──────┘ │
│ │ └─────────┘ └────┬────┘ │
│ │ │ │
│ ▼ too many? │
│ (merge) │ │
│ ┌────▼────┐ │
│ │ ADVICE │ │
│ │ SENT │ │
│ └─────────┘ │
│ │
└────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────┐
│ PARTIAL REVERSALS │
├────────────────────────────────────────────────────────────────┤
│ │
│ Not all reversals are full cancellations. │
│ │
│ SCENARIO: Pre-auth for $100, actual charge $80 │
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Original: │ │
│ │ 0100, DE4 = 000000010000 ($100.00) │ │
│ │ 0110, DE39 = 00 (approved for $100) │ │
│ │ │ │
│ │ Customer only buys $80 worth: │ │
│ │ 0400, DE4 = 000000002000 ($20.00 partial reversal) │ │
│ │ DE90 contains original reference │ │
│ │ │ │
│ │ Result: $20 released back to cardholder │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
│ COMMON IN: │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ • Hotels (pre-auth vs final bill) │ │
│ │ • Car rentals (estimated vs actual) │ │
│ │ • Gas stations (pre-auth $100, pump $47) │ │
│ │ • Restaurants (add tip to original) │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ DE30 (Original Amount) contains the original DE4 value │
│ DE4 contains the REVERSAL amount (not final amount) │
│ │
└────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────┐
│ NETWORK-SPECIFIC MATCHING RULES │
├────────────────────────────────────────────────────────────────┤
│ │
│ Different networks use different matching keys. │
│ │
│ VISA: │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Primary: DE11 (STAN) + DE7 (TransmissionDateTime) │ │
│ │ Alternate: DE37 (RRN) alone │ │
│ │ Extra: DE63 contains Visa Trace ID │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ MASTERCARD: │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Primary: DE11 + DE12 + DE32 │ │
│ │ Cross-border: DE63 contains Trace ID │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ LOCAL/REGIONAL: │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Often: DE11 + DE41 (STAN + TerminalID) │ │
│ │ Sometimes: DE37 (RRN) alone │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ IMPLEMENTATION: │
│ type MatchingStrategy interface { │
│ BuildKey(msg *Message) string │
│ ValidateResponse(req, resp *Message) error │
│ } │
│ │
│ Use configurable strategy based on network routing. │
│ │
└────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────┐
│ COMMON PITFALLS │
├────────────────────────────────────────────────────────────────┤
│ │
│ 1. REUSING STANs TOO QUICKLY │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ WRONG: STAN resets on process restart │ │
│ │ RIGHT: Persist STAN counter to disk │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 2. NOT HANDLING LATE RESPONSES │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ WRONG: Assume responses always come before timeout │ │
│ │ RIGHT: Log and ignore late responses gracefully │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 3. MATCHING ON INSUFFICIENT FIELDS │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ WRONG: if DE11 matches, it's the response │ │
│ │ RIGHT: Match DE11 + DE12 + DE32 (composite key) │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 4. INCORRECT DE90 CONSTRUCTION │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ WRONG: Build DE90 from response │ │
│ │ RIGHT: Build DE90 from original REQUEST │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 5. IGNORING REVERSAL RESPONSE CODES │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ WRONG: sendReversal(); state = Reversed │ │
│ │ RIGHT: Check DE39, handle 12/25/96 differently │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────┐
│ TRANSACTION FLOWS QUICK REFERENCE │
├────────────────────────────────────────────────────────────────┤
│ │
│ MESSAGE TYPES: │
│ ┌──────┬──────────────────────────────────────────────────┐ │
│ │ MTI │ Purpose │ │
│ ├──────┼──────────────────────────────────────────────────┤ │
│ │ 0100 │ Authorization Request │ │
│ │ 0110 │ Authorization Response │ │
│ │ 0120 │ Financial Advice (SAF) │ │
│ │ 0130 │ Financial Advice Response │ │
│ │ 0400 │ Reversal Request │ │
│ │ 0410 │ Reversal Response │ │
│ │ 0420 │ Reversal Advice │ │
│ │ 0430 │ Reversal Advice Response │ │
│ │ 0800 │ Network Management Request │ │
│ │ 0810 │ Network Management Response │ │
│ └──────┴──────────────────────────────────────────────────┘ │
│ │
│ MATCHING KEY: DE11 + DE12 + DE32 │
│ REVERSAL LINK: DE90 (Original Data Elements) │
│ AUTH TIMEOUT: 30-60 seconds │
│ REVERSAL RETRIES: 3 attempts, then send 0420 │
│ │
│ ON TIMEOUT: Always send reversal (0400) │
│ ON REVERSAL FAIL: Retry, then send advice (0420) │
│ ON LATE RESPONSE: Log and ignore │
│ │
│ KEY FIELDS IN REVERSAL: │
│ • DE11 = NEW STAN (not original) │
│ • DE37/38 = FROM original 0110 response │
│ • DE90 = Built from original 0100 request │
│ │
└────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────┐
│ KEY TAKEAWAYS │
├────────────────────────────────────────────────────────────────┤
│ │
│ 1. EVERY REQUEST EXPECTS A RESPONSE │
│ Response MTI = Request MTI + 10 │
│ │
│ 2. TIMEOUT ≠ FAILURE. TIMEOUT = UNCERTAINTY. │
│ When in doubt, REVERSE. │
│ │
│ 3. THE MATCHING KEY IS CRITICAL │
│ DE11 + DE12 + DE32 links responses to requests │
│ STAN must be unique per terminal per day │
│ │
│ 4. REVERSALS HAVE TWO FORMS │
│ 0400 = Request ("please reverse") │
│ 0420 = Advice ("I reversed") │
│ │
│ 5. DE90 LINKS REVERSAL TO ORIGINAL │
│ Contains original MTI, STAN, DateTime, Acquirer │
│ Built from REQUEST, not response │
│ │
│ 6. LATE RESPONSES HAPPEN │
│ Don't assume responses arrive before timeout │
│ Log them, but don't process them │
│ │
│ 7. NETWORK MANAGEMENT COMES FIRST │
│ Sign-on, key exchange, echo before financial messages │
│ │
│ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ │
│ The system that handles timeouts correctly is the one │
│ that doesn't lose money. │
│ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ │
│ │
└────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────┐
│ IDEMPOTENCY IN RETRIES │
├────────────────────────────────────────────────────────────────┤
│ │
│ Retries are normal. Side effects are not. │
│ │
│ 1) 0100 sent, response lost │
│ 2) terminal retries (0200/0400/0121/0420) │
│ 3) same logical action can be sent multiple times │
│ │
│ SAFE PATTERN: │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ • Build deterministic keys │ │
│ │ • Check key before applying state change │ │
│ │ • Return success ACK for duplicates │ │
│ │ • Never apply effects twice │ │
│ └───────────────────────────────────────────────────────────┘ │
│ │
│ 0130, 0410, 0430 duplicates: │
│ Should ACK, but do not re-apply posting or rollback. │
│ │
└────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────┐
│ PROGRESSIVE TEST LADDER │
├────────────────────────────────────────────────────────────────┤
│ │
│ LEVEL 1: HAPPY PATH │
│ • Match 0100/0110 MTI and composite key │
│ │
│ LEVEL 2: TIMEOUT UNCERTAINTY │
│ • Trigger 0400 on timeout │
│ • Send 0420 after N failed 0400s │
│ │
│ LEVEL 3: OUT-OF-ORDER & LATE │
│ • Accept late 0110 as non-fatal once reversal in progress │
│ │
│ LEVEL 4: NETWORK VARIANTS │
│ • Visa strategy DE11+DE7 │
│ • Mastercard strategy DE11+DE12+DE32 │
│ • Local strategy DE11+DE41 │
│ │
│ LEVEL 5: RECOVERY PATH │
│ • Route DE39=12/25 to review queue │
│ • Ensure unresolved cases have reconciliation hooks │
└────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────┐
│ REAL-PRODUCTION HARD PROBLEMS │
├────────────────────────────────────────────────────────────────┤
│ │
│ 1. What if terminal crashes before clearing local state? │
│ 2. What if SAF queue grows past limit during outage? │
│ 3. What if reversal succeeds, but advice fails repeatedly? │
│ 4. How do you avoid duplicate reversal against posted tx? │
│ 5. How long do you keep unknown/ambiguous transactions? │
│ │
│ Design checklist: │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ • Durable state before network send │ │
│ │ • Correlation IDs across retries │ │
│ │ • SLA-based retention for pending/uncertain states │ │
│ │ • Escalation path to refunds/manual intervention │ │
│ └──────────────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────────────┘