# Receipt Generator

**Source:** `jpos/src/main/java/org/jpos/tcpay/service/ReceiptGenerator.java`

## Overview

`ReceiptGenerator` is a static utility service that produces JSON receipt payloads for financial transactions. It is called after a transaction completes (approved or declined) and serializes receipt data into `DE-63` via the returned JSON string.

Receipts are generated for all transaction types **except** reversal (`0400`) and key exchange (`0800`).

## Entry Point

```java
String json = ReceiptGenerator.generateReceipt(ISOMsg request, ISOMsg response, Map<String, Object> metadata);
```

Returns `null` if no receipt should be generated (reversal / key exchange / unhandled exception).

## Receipt JSON Structure

```json
{
  "r": {
    "type": "<transaction type>",
    "e": [ /* ordered list of receipt elements */ ]
  }
}
```

### Element Types

| Key        | Description |
|------------|-------------|
| `txt`      | Text line — has `va` (value), `al` (alignment: LEFT/CENTER/RIGHT), `fs` (font size), `b` (bold: 1), `lf` (line feed) |
| `field`    | Label-value pair — app renders label left-aligned, value right-aligned. Has `label`, `value`, `lineFeed`, `fs` |
| `dualField`| Two label-value pairs on one line. Has `leftLabel`, `leftValue`, `rightLabel`, `rightValue`, `leftChars`, `rightChars`, `fs`, `rightAlign`, `lineFeed` |
| `ls`       | Line separator (blank line) |
| `lg`       | Logo image — has `url` |
| `emv`      | EMV marker — `{"emv": "local"}` when field 55 is present and parseable |
| `pc`       | Paper cut (currently commented out) |

## Receipt Blocks (in order)

### Block 1 — Header
- Logo (`lg`) — URL from `EvaluateRules.RULES_HEADER_LOGO` in metadata, with base URL from `cfg/application.properties` key `receipt.logo.baseurl`. Falls back to a hardcoded default.
- Merchant name and address from `EvaluateRules.RULES_HEADER_MERCHANT_NAME` / `RULES_HEADER_MERCHANT_ADDRESS` (word-wrapped to 38 chars).
- **TID / MID** (dual field): sourced from metadata keys `BankTerminalId` / `BankMerchantId`; falls back to `RouterConstants.SHUKRIA_TERMINAL_ID` / `SHUKRIA_MERCHANT_ID` (device-provided values used for declined transactions where no bank response exists).
- **DATE / TIME** (dual field): parsed from response field 13 (MMDD) and field 12 (HHMMSS).

### Block 2 — Transaction Details
- Scheme + entry mode label: e.g. `VISA (CHIP)`
- Transaction type (bold)
- Masked PAN (last 4 digits visible)
- **BATCH NO / RECEIPT NO** (dual field): from metadata `BankBatchNumber` / `BankStan` (falls back to field 11).
- RRN from response field 37.

### Block 3 — Amount
- `AED<amount>` centered, large (`fs: "3:3"`), bold. Amount from field 4, divided by 100.

### Block 4 — Status
- Approval code (`APPROVAL CODE: <field 38>`) — approved only.
- Account message (see table below).
- CVM result (approved only): PIN Verified (field 52 present), or parsed from EMV tag `9F34` (CVM Results) or `9F6C` (CTQ), with optional signature line.

### Block 6 — EMV Details
- Only for approved transactions with field 55 present.
- Parses TLV tags: `84` AID, `95` TVR, `9B` TSI, `9F27` CID, `9F26` AC.
- Emits `{"emv": "local"}` marker (not individual tag values).

### Block 7 — Footer
- App version from field 56 JSON (`Version` key).
- Footer message and description from `EvaluateRules.RULES_FOOTER_MESSAGE` / `RULES_FOOTER_DESCRIPTION` (word-wrapped to 38 chars).

## Transaction Types

Derived from MTI + processing code (field 3):

| Condition | Type |
|-----------|------|
| MTI `0100` | Pre-Auth |
| MTI `0200`, proc `00xx` | Sale (or Sale-Tip if field 54 present) |
| MTI `0200`, proc `20xx` | Refund |
| MTI `0200`, proc `02xx` | Void-Sale / Void-Preauth / Void-Completion |
| MTI `0220`, proc `20xx` | Refund |
| MTI `0220` | Auth-Compl |
| MTI `0400`/`0420` | Void-Sale / Void-Preauth / Void-Completion |

## Account Messages

| Scenario | Message |
|----------|---------|
| Declined (any RC ≠ `00`/`10`/`11`) | `MW - DECLINED- Tran not Permitted` |
| Sale, Pre-Auth, Auth-Compl, Payment | `PLEASE DEBIT MY ACCOUNT` |
| Void, Refund | `PLEASE CREDIT MY ACCOUNT` |

## Card Scheme Detection (priority order)

1. Field 55 (EMV) — Tag `84` (AID), matched against a prefix map (first 10 hex chars):
   - `A000000003` → VISA, `A000000004` → MASTERCARD, `A000000025` → AMEX, `A000000524` → RUPAY, `A000000152` → DISCOVER, `A000000065` → JCB, `A000000333` → CUP, `A000000912` → Jaywan
2. Field 2 (PAN) — BIN/IIN range detection.
3. Field 35 (Track 2) — PAN extracted before `=`, same BIN logic.
4. Default: `UNKNOWN`

## Entry Mode (Field 22, first 2 digits)

| Code | Label |
|------|-------|
| `05` | CHIP |
| `07` | CONTACTLESS |
| `90` | MAGNETIC STRIPE |
| `01` | MANUAL |
| `02` | MAGNETIC STRIPE |
| `80` | FALLBACK |
| default | CONTACT ENTRY |

## CVM Interpretation

**Tag 9F34 (CVM Results)** — byte 0 low 6 bits = method, byte 2 = result (0x00 or 0x02 = success):

| Method | Result |
|--------|--------|
| `0x01` | OFFLINE PLAIN PIN VERIFIED (no sign) |
| `0x02` | PIN VERIFIED (no sign) |
| `0x04` | OFFLINE ENC PIN VERIFIED (no sign) |
| `0x03`/`0x05` | PIN AND SIGN VERIFIED (sign required) |
| `0x1E` | SIGNATURE REQUIRED (sign required) |
| `0x1F` | NO CVM REQUIRED (no sign) |
| `0x3F` | NO CVM VERIFIED (no sign) |

**Tag 9F6C (CTQ)** — bit flags on bytes 0 and 1:

| Bit | Result |
|-----|--------|
| byte 0 bit 7 | PIN VERIFIED (no sign) |
| byte 0 bit 6 | SIGNATURE REQUIRED (sign required) |
| byte 1 bit 7 | AUTHENTICATED BY DEVICE / CDCVM VERIFIED (no sign) |

## Configuration

| Key (`cfg/application.properties`) | Purpose |
|------------------------------------|---------|
| `receipt.logo.baseurl` | Base URL prepended to the logo path from rules metadata |

## Metadata Keys Used

| Key | Source | Usage |
|-----|--------|-------|
| `BankTerminalId` | Translator (bank response) | TID on receipt |
| `BankMerchantId` | Translator (bank response) | MID on receipt |
| `RouterConstants.SHUKRIA_TERMINAL_ID` | Validation phase (device request) | TID fallback for declined txns |
| `RouterConstants.SHUKRIA_MERCHANT_ID` | Validation phase (device request) | MID fallback for declined txns |
| `BankBatchNumber` | Translator | Batch number |
| `BankStan` | Translator | Receipt / STAN number |
| `EvaluateRules.RULES_HEADER_LOGO` | Rules engine | Logo path |
| `EvaluateRules.RULES_HEADER_MERCHANT_NAME` | Rules engine | Merchant name |
| `EvaluateRules.RULES_HEADER_MERCHANT_ADDRESS` | Rules engine | Merchant address |
| `EvaluateRules.RULES_FOOTER_MESSAGE` | Rules engine | Footer message |
| `EvaluateRules.RULES_FOOTER_DESCRIPTION` | Rules engine | Footer description |
