No format is privileged
Nothing in the message builder is hardcoded to a particular scheme. Field numbers, names, lengths, encodings and framing all come from the specification you are running.
Feature reference
FlexSim is a universal ISO 8583 simulator — ISO8583, if you write it without the space — one desktop window covering the message format, the card data, the calculations, the connection, the checking and the record — in either direction.
Scope
Most simulators are written around one network's message format and bend awkwardly to anything else. FlexSim treats the format as data you supply, so the link you have to test is a specification you describe rather than a feature request you file.
Nothing in the message builder is hardcoded to a particular scheme. Field numbers, names, lengths, encodings and framing all come from the specification you are running.
Point it at a switch, an issuer host or an acquirer front end — or let it be the thing being pointed at. The same specification serves both.
Specifications live together in one database with their own suites and cases. Switch the active one from the status bar without restarting the app.
Message format
A specification defines which data elements exist, how long each one is, how it is encoded, and what wraps the message on the wire. FlexSim ships four working profiles to start from, and gives you the editor to change them or build your own from nothing.
| Setting | Options | Notes |
|---|---|---|
| Data elements | Any number, named and numbered | Add, remove and rename fields to match the document you were given. |
| Field encoding | ASCII, EBCDIC, Binary | Set per field, so a mostly-EBCDIC message can still carry binary chip data. |
| Length encoding | ASCII, EBCDIC, Binary | Applies to the length prefix of variable fields, independently of the data. |
| Length type | Fixed, LLVAR, LLLVAR | Two- or three-digit prefixes for variable fields. |
| Bitmap format | Binary, Hex | Hex writes the bitmap as characters rather than raw bytes. |
| MTI encoding | ASCII, EBCDIC, Binary | Chosen separately from the body of the message. |
| Application headers | Any number, per specification | Fixed-length headers written ahead of the MTI. |
| Subfields | Nested, to any depth | A subfield can hold subfields of its own; the parent's value is composed from them. |
| Framing | 2-byte, 4-byte, TPDU | The length header the socket adds around each message. |
Switching does not need a restart. The specification name in the status bar is a button. Changing it reloads the suite tree, because suites and cases belong to a specification — and it is refused while a run is in progress.
Composition is declared, not guessed. How a field turns its subfields into a value — joined, positional, tag-length-value, nested, or a counted buffer — is a setting on the field, so unusual framing is described rather than special-cased.
Renaming a specification breaks nothing. Suites, test cases and log entries are tied to the specification itself rather than to what it is called, so a rename carries all of them with it and leaves no history stranded.
Four profiles are ready to use on the first run. They cover a range of shapes — ASCII and EBCDIC bodies, hex and binary bitmaps, application headers and none, and fields carrying anything from a flat value to a nested tree — so there is something close to the link you are testing before you write a line of it yourself.
They are a starting point, not a black box. Every field, length, encoding and subfield in a shipped profile is editable in the same editor you would use to write one from scratch — because the document you were actually given never quite matches anyone else's.
Modes
Each mode is named for the system you are testing, and FlexSim plays the other side of the link. The same test case definition works in both directions — what decides which way a case runs is whether you have given it a response definition: without one it sends, with one it listens and answers.
Acquirer mode
The app listens on a port and stands in for the issuer host. Use it when the thing you are testing is the terminal or the switch, and the real issuer is not something you can point at.
Issuer mode
The app connects out and drives the exchange as the acquirer. Use it to certify an issuer host, exercise a switch, or reproduce a message someone captured in production.
| Setting | Behaviour |
|---|---|
| Arming | Running a case that has a response definition starts listening instead of sending. Stop disarms it and releases the port. |
| Iterations | Becomes the number of requests to answer before the listener closes. |
| Response MTI | Left blank, the third digit of the request is stepped — 0200 becomes 0210. Set it and that value is used as given. |
| Explicit fields | Written with the value in the response definition. This is where the response code goes, so you can approve, decline or return anything you want handled. |
| Echoed fields | Copied straight from the incoming request. A field absent from the request is left out of the reply rather than sent empty. |
| Comparison | The request definition doubles as the expectation. Every field that differs is logged. |
| Rule sets | Arming loads every responder case in the suite as a rule, in order, so one suite can answer different requests differently. |
Matching is diagnostic, not gating. A mismatch tells you what the system under test actually sent; it does not abort the exchange, and the reply goes out either way. That is deliberate — a failed comparison is usually the thing you were trying to observe.
Composition
The test case editor lists every data element in the active specification. Tick the ones the message carries, set the values, and FlexSim builds the bitmap and the framing for you.
Search by field number or by name. Enabled fields stay distinct from the rest, so a long specification stays workable.
A field with structure is edited part by part and its value composed from them. Change a leaf and every level above it recomposes, right up to the field.
Any field can be typed, generated at send time, or resolved from the selected card — and you choose which card value it takes, so the CVV can go in a private-use element. Generated values can read fields just resolved.
| Kind | Examples |
|---|---|
| From the card | PAN or masked PAN, expiry, service code, sequence number, track 2, PIN and PIN block, CVV, CVV2, iCVV, PVV and PVKI, the card status update, and the keys themselves — any of them in any field you point at it |
| From the message | Amounts and transaction types that must agree with another field |
| From the clock | Transmission date and time, local date and time |
| From a counter | Trace numbers and transaction counters that survive restarts |
| From the keys | Verification values, PIN blocks, authentication codes, chip cryptograms |
| Random | Unpredictable numbers and any field where the value only has to vary |
A captured message is a starting point. Paste a hex dump and FlexSim parses it against the active specification, turning it into a test case with the fields already populated — including any structure inside them. A composed field is taken apart the same way it was put together, so positional halves, counted token buffers and nested tag-length-value trees all land back in their own subfields rather than being dropped for want of a place to go.
Only the subfields carrying something arrive ticked. A specification with twenty-eight chip tags used to open with all twenty-eight switched on, which told you nothing. Now a subfield is on when it has a value, a generation method or a slot the composer fills — and one you switched off by hand stays off.
Reversals
A good deal of what a host has to get right only happens when a transaction is taken back. A test case can carry the reversal for its own request: once the reply lands, FlexSim builds the reversal from the request it actually sent and puts it out on the same connection.
An echoed field the request never carried is left out rather than sent empty, and the log names it. A reversal quietly missing a field is worse than one that says so.
No issuer cryptogram is added. A reversal is a request travelling the other way — an issuer's answer inside one would be the host replying to itself.
Test data
A saved card carries everything a message might need from it. Test cases reference the card rather than copying values out of it, so a card change lands in every case at once.
| Value | Used for |
|---|---|
| PAN | The account number, and the basis of most derived values |
| Expiry date | Its own field, and a component of the track and the verification values |
| Service code | Its own field, and a component of the verification values |
| PIN | PIN block and PIN verification value |
| Card sequence number | Chip key derivation and its own data element |
| CVV | Magnetic stripe card verification value, carried in track 2 |
| CVV2 | The printed value, for card-not-present tests |
| iCVV | The chip variant, substituted automatically on a chip transaction |
| PVV | PIN verification value, carried in track 2 |
| PVKI | PIN verification key index — a second PVV comes from a different index |
| Track 2 layout | The order and presence of each part, saved per card |
| Key references | Which stored key backs each calculation for this card |
Any of them can go in any field. A field set to take card data used to be answered by its own number, which reached the PAN, the expiry, the track and the PIN block and nothing else. Now the field names the value it wants, so a CVV in a private-use element or a key in an element of its own is a dropdown rather than a figure pasted in by hand and left to go stale.
The track is built from the card's own fields and the arrangement is saved with the card, so it reproduces exactly every time.
Calculation
Keys are stored once and referenced by the cards that use them. Anything derived from a key is then worked out on demand, so a test stays correct when the card, the amount or the key changes.
| Value | Needs |
|---|---|
| CVV / CVV2 / iCVV | The card and its card verification key |
| PVV | The PIN, the key index and the PIN verification key |
| PIN block | The PIN, the PAN and the PIN key |
| MAC | The assembled message and the authentication key |
| Request cryptogram | The card, its cryptogram master key and the chip data in the message |
| Response cryptogram | The incoming request and the response code being returned |
| Key check value | Shown per key as you type it, so a mistyped digit surfaces before it is saved |
Keys live in their own store with a type and a description; cards reference them by type-filtered picker. Rotate a key once and every card that uses it follows.
If a calculation needs something you have not supplied — a PIN, a key, a card — FlexSim names it instead of leaving the field blank or filling it with something that looks plausible.
Checking
Each case carries its own expectations of the reply, so a run reports pass or fail rather than handing you a log to read.
| Result | Meaning |
|---|---|
| Pass | A reply came back and every rule on that case was satisfied. |
| Fail | A reply came back and at least one rule was not. The rule that failed is named. |
| Sent | The case ran with checking switched off. Deliberately not counted as a pass — unchecked cases would otherwise inflate the number the run exists to produce. |
| Error | No usable reply: a timeout, a connection failure, or a message that would not parse. The elapsed time is recorded. |
The same message sent in two contexts can be judged by two different standards, because the rules belong to the case and not to the specification.
A case with checking off still runs and still sends; its reply simply is not judged. The rules stay put and come back when you switch it on.
Results stream in as each case finishes and export as a spreadsheet or a self-contained report that survives being emailed. Failures carry their raw bytes.
No rules means a reply that parses is a pass. The alternative — failing every case you have not configured yet — reports nothing useful on the day you start.
Transport
ISO 8583 says nothing about how a message is delimited on a stream, which is why every link does it differently. FlexSim makes framing a setting rather than an assumption, and works from either end of the socket.
Visibility
Everything the app does is written down three ways: parsed on screen as it happens, kept in a searchable history, and mirrored to a plain text file on disk.
Requests and responses broken out into named fields, colour-coded and readable without decoding anything yourself. Nothing is trimmed away mid-run, and a burst of traffic does not slow the window down.
Past exchanges stay in the database, filtered to the specification you are working in, with time, direction, mode, message type and length. Select one and read the hex, the character rendering and the parsed elements together — and renaming the specification does not hide its own history from it.
A plain text mirror of the on-screen log, rolling at a size you set and again at midnight, in a folder you choose. If that folder goes missing the app falls back to the default rather than losing lines quietly.
Appearance
Testing days are long, and the log is what you stare at. FlexSim lets you set how it looks and applies every change as you make it.
Working day
How a single case becomes a run, and the parts that decide whether a testing day goes smoothly.
Cases live in suites per specification. Run one, or run the lot. Cases set up to answer are skipped in a send run, and the count is logged rather than passed over silently.
An iteration count sits beside Send. Set it and the case runs that many times without you clicking that many times — for volume, soak testing, or driving a sequence forward.
Suites round-trip through JSON and XML so a colleague can import yours. Card and key material is deliberately left out of the file.
| Element | Behaviour across passes |
|---|---|
| Generated fields | Recomputed every pass, so a run of 500 is 500 distinct messages rather than the same bytes 500 times. |
| Trace numbers | Advance on each pass, and carry on from where the last session left them — counters survive a restart. |
| Date and time fields | Taken from the clock at the moment each message is built. |
| Random fields | New value per pass, so unpredictable numbers stay unpredictable. |
| Calculated values | Recalculated against whatever the other fields now hold, so a cryptogram still matches its own message. |
| Typed values | Sent unchanged — anything you entered by hand stays exactly as entered. |
| Stop | Halts the run immediately rather than at the end of the count. |
| Reversals | Sent once per pass, after that pass's reply — a run of ten authorisations produces ten reversals. |
| In acquirer mode | The same count means how many incoming requests to answer before the listener closes. |
| Tool | What it answers |
|---|---|
| Card values | Everything the card screen calculates — CVV, CVV2, iCVV, PVV and the PIN block — from a PAN and keys typed straight in, with no card saved. |
| Encoding converter | Moves a value between ASCII, EBCDIC, hex and binary. |
| Key tools | Component combination, key generation, key wrapping and derived unique keys per transaction. |
| TLV decoder | Breaks a tag-length-value blob into its tags. |
Nothing on the tools window touches the database. Keys are typed in rather than picked from the key store, which is what keeps it a scratchpad — check a figure against a card you have not saved, or one you never will.
Storage
One file holds everything: specifications, suites, test cases, cards, keys, counters, settings and the message history.
Sensitive values are encrypted in the database. Nothing is sent anywhere — the app is offline unless you point it at a host yourself.
Set a master password and the stored secrets are re-encrypted under it in one step, with the app locked until it is entered. Switching back is just as reversible.
Move the database to another machine and your specifications, cards and suites come with it. The startup log prints the path in use.
| Platform | Path |
|---|---|
| Windows | %LOCALAPPDATA%\FlexSim\simulator.db |
| Linux | ~/.local/share/FlexSim/simulator.db |
| macOS | ~/Library/Application Support/FlexSim/simulator.db |
The same path in every build. It sits outside the folder you unzipped, so replacing the application with a newer one cannot reach your data.
Pick your platform, unzip, and point it at a test endpoint — or let it answer one.
Windows · macOS · Linux · x64 and ARM64