# ISO 8583 Operations

This document covers two related pipeline operations used for ISO8583 processing:

* `HexMessageRouterOperation`
* `ReplaceISOOperation`

Together, they are commonly used to:

1. identify the kind of incoming ISO message
2. choose the correct sub-pipeline for that message
3. parse the ISO payload
4. redact or reveal selected ISO fields

### Flow Diagram

````mermaid
flowchart TD
    A[Incoming payload bytes] --> B[Optional header handling]
    B --> C[HexMessageRouterOperation]
    C -->|Route matches hex signature| D[Route-specific nested pipeline]
    C -->|No route match| E[Default pipeline if configured]

    D --> F[ReplaceISOOperation]
    F --> G[Unpack ISO message with originalPackager]
    G --> H[Extract configured fields]
    H --> I{Downstream operation}
    I -->|RedactOperation| J[Tokenize field value]
    I -->|RevealOperation| K[Reveal token value]
    J --> L[Write returned value back into ISO field]
    K --> L
    L --> M[Pack ISO message with processedPackager]
    M --> N[Final payload]

    E --> N
```
````

### HexMessageRouterOperation

`HexMessageRouterOperation` is a conditional dispatcher.

It:

1. converts the incoming payload bytes into a hex string
2. compares that hex string against configured route keys
3. runs the matching nested pipeline for any matching route
4. optionally runs a `defaultPipeline`

It does not parse ISO fields directly. It routes based on raw payload hex.

#### How Routing Works

Each route key represents the MTI. A route matches if either:

* the payload hex starts with the route key
* the payload hex contains the route key and `checkContains` is enabled

Conceptual example:

```
{
  "@type": "type.googleapis.com/HexMessageRouterOperationConfig",
  "router": {
    "0200": {
      "operations": [
        {
          "@type": "type.googleapis.com/ReplaceISOOperationConfig",
          "fields": [2],
          "charset": "ISO-8859-1",
          "originalPackager": "<base64-encoded-jpos-packager-xml>",
          "processedPackager": "<base64-encoded-jpos-packager-xml>"
        },
        {
          "@type": "type.googleapis.com/RedactOperationConfig"
        }
      ]
    }
  }
}
```

In this example:

* &#x20;`0200` is ASCII for `30323030`&#x20;
* if the payload starts with `0200`, the router runs the nested ISO pipeline and processes the payload based on the JPOS packager config.

#### Does It Route On MTI?

Not inherently.

`HexMessageRouterOperation` operates on the entire payload as raw bytes converted to hex. It only becomes "MTI routing" if the configured route key corresponds to the MTI bytes at the start of the payload.

For ISO8583, that is a common setup:

* `0200` -> hex `30323030`
* `0800` -> hex `30383030`

If the MTI is not at byte 0 because the payload has a transport header, another operation usually runs first to remove or skip that header. For example, a `SkipBytesOperation` may be used so the MTI becomes the first visible bytes before routing.

#### Common Pattern

A common ISO flow is:

1. skip transport/header bytes if needed
2. route by MTI using `HexMessageRouterOperation`
3. parse the ISO payload with `ReplaceISOOperation`
4. redact or reveal selected fields

### ReplaceISOOperation

`ReplaceISOOperation` is a reversible pipeline step that:

1. Unpacks an ISO8583 message using a configured jPOS packager.
2. Extracts one or more configured ISO fields.
3. Sends each extracted field value through the rest of the pipeline.
4. Writes the downstream result back into the same ISO field.
5. Re-packs the ISO message and returns it.

This means `ReplaceISOOperation` does not tokenize or reveal values by itself. It only isolates ISO fields and hands them to later operations such as `RedactOperation` or `RevealOperation`.

### How It Works

For each field listed in `fields`:

* `ReplaceISOOperation` reads the field value from the unpacked `ISOMsg`.
* It calls `next(fieldValue)`, which passes that value to downstream operations.
* When the downstream operations return, `inverse()` writes the returned bytes back into the current field.

As a result:

* If the downstream pipeline returns a token, the ISO field becomes a token.
* If the downstream pipeline returns cleartext, the ISO field becomes cleartext.

### Configuration

The operation is configured with `ReplaceISOOperationConfig`.

```
{
  "@type": "type.googleapis.com/ReplaceISOOperationConfig",
  "fields": [2],
  "charset": "ISO-8859-1",
  "originalPackager": "<base64-encoded-jpos-packager-xml>",
  "processedPackager": "<base64-encoded-jpos-packager-xml>",
  "skipIfFieldNotFound": false
}
```

#### Fields

* `fields`: ISO field numbers to extract and process.
* `charset`: used when converting values to and from bytes. If blank, the code defaults to `ISO-8859-1`.
* `originalPackager`: base64-encoded jPOS `GenericPackager` XML used to unpack the incoming ISO message.
* `processedPackager`: base64-encoded jPOS `GenericPackager` XML used to pack the outgoing ISO message.
* `skipIfFieldNotFound`: if `false`, a missing field causes an error. If `true`, the field is skipped.

### What The Packager Does

The packager is the schema for the ISO message. It tells jPOS how to interpret raw bytes:

* which fields exist
* whether a field is fixed-length or variable-length
* whether a field is numeric, character, or binary
* how long the field is
* how nested components should be parsed

A simple decoded packager XML looks like this:

```
<isopackager>
  <isofield id="0" length="4" class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield id="1" length="16" class="org.jpos.iso.IFB_BITMAP"/>
  <isofield id="2" length="19" class="org.jpos.iso.IFA_LLNUM"/>
  <isofield id="3" length="6" class="org.jpos.iso.IFA_NUMERIC"/>
</isopackager>
```

In that example:

* field `0` is a 4-digit numeric MTI
* field `1` is the bitmap
* field `2` is an LLVAR numeric field up to 19 digits
* field `3` is a fixed 6-digit numeric field

For field `2`, a wire value like:

```
16 4111111111111111
```

means:

* `16`: the field length prefix
* `4111111111111111`: the actual PAN

Without the packager, the system would not know how to split those bytes correctly.

### Redaction Flow

When used with `RedactOperation`, the field value is tokenized.

#### Example Pipeline

```
{
  "operations": [
    {
      "@type": "type.googleapis.com/ReplaceISOOperationConfig",
      "fields": [2],
      "charset": "ISO-8859-1",
      "originalPackager": "<base64-encoded-jpos-packager-xml>",
      "processedPackager": "<base64-encoded-jpos-packager-xml>",
      "skipIfFieldNotFound": false
    },
    {
      "@type": "type.googleapis.com/RedactOperationConfig"
    }
  ]
}
```

#### Example Input / Output

Input ISO field:

```
field 2 = 4111111111111111
```

Downstream redactor result:

```
tok_sandbox_abc123
```

Output ISO field after re-pack:

```
field 2 = tok_sandbox_abc123
```

#### Conceptual Processing Steps

1. Unpack the ISO message with `originalPackager`.
2. Extract field `2`.
3. Pass `4111111111111111` to `RedactOperation`.
4. Receive `tok_sandbox_abc123`.
5. Write `tok_sandbox_abc123` back into field `2`.
6. Re-pack the ISO message with `processedPackager`.

### Reveal Flow

When used with `RevealOperation`, the token is de-tokenized.

#### Example Pipeline

```
{
  "operations": [
    {
      "@type": "type.googleapis.com/ReplaceISOOperationConfig",
      "fields": [2],
      "charset": "ISO-8859-1",
      "originalPackager": "<base64-encoded-jpos-packager-xml>",
      "processedPackager": "<base64-encoded-jpos-packager-xml>",
      "skipIfFieldNotFound": false
    },
    {
      "@type": "type.googleapis.com/RevealOperationConfig"
    }
  ]
}
```

#### Example Input / Output

Input ISO field:

```
field 2 = tok_sandbox_abc123
```

Downstream reveal result:

```
4111111111111111
```

Output ISO field after re-pack:

```
field 2 = 4111111111111111
```

#### Conceptual Processing Steps

1. Unpack the ISO message with `originalPackager`.
2. Extract field `2`.
3. Pass `tok_sandbox_abc123` to `RevealOperation`.
4. Receive `4111111111111111`.
5. Write `4111111111111111` back into field `2`.
6. Re-pack the ISO message with `processedPackager`.

### Important Clarification

`ReplaceISOOperation` is not the tokenization engine.

It only:

* parses the ISO message
* extracts the configured fields
* routes those field values through downstream operations
* writes the returned value back into the message

The actual tokenization or reveal logic is performed by the configured redactor behind `RedactOperation` or `RevealOperation`.
