Skip to content

Validator

The ISO8583Validator class validates ISO 8583 messages for structure and content correctness.

Quick Start

from iso8583sim.core.validator import ISO8583Validator
from iso8583sim.core.types import ISO8583Message

validator = ISO8583Validator()

message = ISO8583Message(
    mti="0100",
    fields={
        0: "0100",
        2: "4111111111111111",
        3: "000000",
        4: "000000001000",
    }
)

errors = validator.validate_message(message)

if errors:
    for error in errors:
        print(f"Error: {error}")
else:
    print("Message is valid!")

Validation Rules

MTI Validation

  • Must be exactly 4 digits
  • First digit: ISO version (0, 1, 2)
  • Second digit: Message class (1-8)
  • Third digit: Message function (0-4, 8, 9)
  • Fourth digit: Message origin (0-5)
# Valid MTIs
"0100"  # Authorization request (1987)
"0110"  # Authorization response
"0200"  # Financial request
"0400"  # Reversal request

# Invalid MTIs
"100"   # Too short
"01A0"  # Non-numeric
"0190"  # Invalid function digit

Field Type Validation

Type Rule Example
Numeric (n) Only digits 0-9 "123456"
Alpha (a) Only letters A-Z, a-z "APPROVED"
Alphanumeric (an) Letters and digits "ABC123"
Binary (b) Hex characters "9F2608"
LLVAR Max 99 chars PAN field
LLLVAR Max 999 chars EMV data

Field Length Validation

# Fixed-length fields must match exactly
# Field 3 (Processing Code): 6 digits
"000000"   # Valid
"00000"    # Invalid (too short)
"0000000"  # Invalid (too long)

# Variable-length fields checked against max
# Field 2 (PAN): LLVAR, max 19
"4111111111111111"     # Valid (16 chars)
"41111111111111111111" # Invalid (20 chars)

Network-Specific Validation

When network is specified, validates required fields:

from iso8583sim.core.types import CardNetwork

message.network = CardNetwork.VISA

# VISA requires: 2, 3, 4, 11, 14, 22, 24, 25
errors = validator.validate_message(message)

Network Required Fields:

Network Required Fields
VISA 2, 3, 4, 11, 14, 22, 24, 25
Mastercard 2, 3, 4, 11, 22, 24, 25
AMEX 2, 3, 4, 11, 22, 25
Discover 2, 3, 4, 11, 22
JCB 2, 3, 4, 11, 22, 25
UnionPay 2, 3, 4, 11, 22, 25, 49

PAN Validation

Luhn checksum validation for Field 2:

"4111111111111111"  # Valid (passes Luhn)
"4111111111111112"  # Invalid (fails Luhn)

Single Field Validation

from iso8583sim.core.types import get_field_definition

field_def = get_field_definition(2)  # PAN field

is_valid, error = validator.validate_field(
    field_number=2,
    value="4111111111111111",
    field_def=field_def
)

if not is_valid:
    print(f"Field 2 error: {error}")

Validation Examples

Valid Authorization Request

message = ISO8583Message(
    mti="0100",
    network=CardNetwork.VISA,
    fields={
        0: "0100",
        2: "4111111111111111",  # PAN
        3: "000000",            # Processing Code
        4: "000000001000",      # Amount
        11: "123456",           # STAN
        14: "2512",             # Expiry
        22: "051",              # POS Entry Mode
        24: "100",              # NII
        25: "00",               # POS Condition Code
    }
)

errors = validator.validate_message(message)
# errors = []  (valid)

Invalid Message Examples

# Missing required field
message.fields.pop(4)  # Remove amount
errors = validator.validate_message(message)
# ["Missing required field: 4"]

# Invalid field type
message.fields[4] = "ABCDEF"  # Amount should be numeric
errors = validator.validate_message(message)
# ["Field 4 must contain only digits"]

# Invalid PAN (Luhn)
message.fields[2] = "4111111111111112"
errors = validator.validate_message(message)
# ["Field 2 (PAN) failed Luhn check"]

Cython Acceleration

Validation functions have Cython optimizations:

Function Speedup
is_numeric() ~2x
is_alphanumeric() ~2x
is_valid_hex() ~2x
validate_pan_luhn() ~3x

Detection is automatic when Cython extensions are compiled.

API Reference

See Core API Reference for complete API documentation.