# LAN-based integration

LAN-based Pay@Table integration is the Pay@Table pathway that gives a simpler, easier-to-implement
and more localised setup. It uses a locally-hosted POS Pay@Table server that communicates with both
the Tyro terminals and the POS system — the terminals talk directly to the local POS Pay@Table
server, and that server manages communication between the POS system and the Tyro terminals.

The communication pathways and information exchanged between the POS Pay@Table server and the Tyro
terminal for LAN-based Pay@Table integrations are shown below:

![LAN-based Pay@Table integration](/assets/paytable-lan-based.956c00f8f74a11d926368adff4c74622e22a4d6518c18b0ed344e2f3e2ddeac6.68286485.jpg)

## Requirements for LAN-based Pay@Table integration

1. Three URLs (open sales, transaction result, diagnostics) for the local POS Pay@Table server —
with the `http` prefix — along with a passphrase meeting the criteria defined in the
certification criteria, must be specified for each merchant location.
2. The Tyro terminals and the POS Pay@Table server must be on the same Wi-Fi network or IP address
subnet.
3. LAN-based Pay@Table integrations can't operate over the terminal's 3G connectivity mode, due to
the limitation described above.


## Requesting open sales

**Sample URL schematics:**

* LAN-based Pay@Table: `http://[pos server IP address][:port]/open-sales`
* Cloud-based Pay@Table: `https://my.pos.server/open-sales`


The terminal makes an HTTP GET request to this URL, appending a numeric `operatorId` parameter, an
optional numeric `table` parameter, an alphanumeric Merchant ID (`mid`) and an alphanumeric
Terminal ID (`tid`) — for example:

* LAN-based Pay@Table: `http://[pos server IP address][:port]/open-sales?operatorId=2175&mid=1234&tid=5[&table=37]`
* Cloud-based Pay@Table: `https://my.pos.server/open-sales?operatorId=2175&mid=1234&tid=5[&table=37]`


The `table` parameter is only provided when the terminal is in one of the two Restaurant modes, and
gives the POS an additional data element to help narrow down the list of open sales to return to
the terminal.

The response from the POS server is a list of open sales in JSON format, where an open sale has the
following attributes:

| Parameter | Description | Mandatory |
|  --- | --- | --- |
| `amount` | Amount in cents, between 1 and 9999999. | Yes |
| `pos-reference` | POS-generated reference (must be unique for new sales, but must be the same for subsequent requests in a split-bill scenario). | Yes |
| `display-text` | Text displayed next to the amount on the select-open-sale screen when there's more than one open sale in the response. Due to screen size limitations, only 6 characters can be displayed. | No |
| `table` | The table number associated with this open sale. Used only to indicate to the terminal that it should use the restaurant workflow (i.e. offer split billing) if retrieved using the **BAR** button. | No |
| `always-return-outcome` | Whether all transaction outcomes should be reported back to the POS. Lets POS systems with table-locking workflows know they'll always receive a response from the terminal, so the terminal can also participate in the table-locking workflow. | No (default is `false`) |


### Examples

* Single open sale:

```json
{"open-sales":[{"amount":"4595","pos-reference":"abc123"}]}
```
* Multiple open sales:

```json
{
  "open-sales": [
    { "amount": "5000", "pos-reference": "abc123", "display-text": "group1" },
    { "amount": "2000", "pos-reference": "abc124", "display-text": "group2" },
    { "amount": "2000", "pos-reference": "abc125", "display-text": "group3" },
    { "amount": "10000", "pos-reference": "abc126", "display-text": "group4" }
  ]
}
```
* No open sales:

```json
{"open-sales":[]}
```
* Single open sale with `always-return-outcome`:

```json
{"open-sales":[{"amount":"4595","pos-reference":"abc123"}], "always-return-outcome":"true"}
```
* Multiple open sales with `always-return-outcome`:

```json
{
  "open-sales": [
    { "amount": "5000", "pos-reference": "abc123", "display-text": "group1" },
    { "amount": "2000", "pos-reference": "abc124", "display-text": "group2" },
    { "amount": "2000", "pos-reference": "abc125", "display-text": "group3" },
    { "amount": "10000", "pos-reference": "abc126", "display-text": "group4" }
  ],
  "always-return-outcome": "true"
}
```


The response must have the content type set to `text/plain` (all other content types are
rejected) and a character encoding of ISO-8859-1 (LATIN1).

### Error codes

* If the requested table doesn't exist, the POS server must return an HTTP status code of 400.
* If the `operatorId` is invalid, the POS server must return an HTTP status code of 401.
* If the table is unavailable (due to locking, etc.), the POS server must return an HTTP status
code of 412. An optional status message can be included in the response content, to be displayed
on the terminal — up to ninety characters; longer messages are truncated to the first ninety. If
no message is provided, the terminal displays a default message: "Table is unavailable at this
time."


HTTP URL redirects aren't followed by the terminal.

## Posting approved transaction result for a table

**Sample URL schematics:**

* LAN-based Pay@Table: `http://[pos server IP address][:port]/transaction-result`
* Cloud-based Pay@Table: `https://my.pos.server/transaction-result`


The terminal sends an HTTP POST request to this URL, where the message body contains the approved
transaction result in JSON format (content type `text/plain`), with the following data:

| Parameter | Description | Mandatory |
|  --- | --- | --- |
| `result` | Always `APPROVED`. | Yes |
| `table` | The table number. | No |
| `approval-code` | The issuer approval code. | No |
| `mid` | The Tyro Merchant ID. | Yes |
| `tid` | The Tyro Terminal ID. | Yes |
| `pos-reference` | POS-generated reference. | Yes |
| `response-message` | The transaction response message. Always `APPROVED` or `APPROVED W/ SIGNATURE`. | Yes |
| `tip-amount` | The tip amount, to two decimal places, in AUD. | Yes |
| `base-amount` | The transaction request amount, to two decimal places, in AUD. | Yes |
| `base-currency` | The transaction request currency code. Always `AUD`. | Yes |
| `card-currency` | The currency code the transaction was processed in. | Yes |
| `card-type` | The card type used in the transaction — may be `EFTPOS`, `Visa`, `MasterCard`, `American Express`, `Diners Club`, `JCB`, `PayPal` or `UnionPay`. Tyro adds new card types as new payment types are accepted, so this list expands over time. | Yes |
| `elided-pan` | The card PAN with all digits shown as `x` except the last four. | Yes |
| `gst-percentage` | The percentage of the sale that attracts GST. | No |
| `operator-id` | The operator ID used to process the transaction. | Yes |
| `pan-length` | The length of the PAN. | Yes |
| `rrn` | The Retrieval Reference Number for the transaction (safe to treat as unique for a merchant within a 7-day period). | Yes |
| `surcharge-amount` | The surcharge amount added, to two decimal places, in AUD (incl. GST). | No |
| `terminal-transaction-local-date-time` | The local date/time of the transaction. Format: `YYYYMMDDHHMMSSZZZZZ`. | Yes |
| `transaction-reference` | The non-unique transaction reference. | Yes |
| `transaction-type` | The transaction type. Always `purchase`. | Yes |
| `transmission-date-time` | The date/time the transaction was transmitted to the issuer, in UTC. Format: `YYYYMMDDHHMMSSZZZZZ`. | Yes |
| `transaction-amount` | The total transaction amount (base amount plus tip amount plus surcharge amount) in the selected currency, expressed with the currency's appropriate number of decimal places. | Yes |
| `transaction-currency` | The currency code the transaction was processed in. | Yes |
| `exchange-rate` | The exchange rate the customer agreed to, expressed as a divisor. | No |
| `receipt-block` | A plain-text, pre-formatted receipt block suitable for printing or storing. | Yes |


### Examples

**Example 1:** Transaction processed in AUD with surcharging


```json
{
  "approval-code": "027573",
  "base-amount": "100.00",
  "base-currency": "AUD",
  "card-currency": "AUD",
  "card-type": "American Express",
  "elided-pan": "xxxxxxxxxxx8431",
  "issuer-action-code": "00",
  "mid": "25",
  "operator-id": "10",
  "pan-length": "15",
  "pos-reference": "VE39LVUXNY",
  "receipt-block": "removed for brevity",
  "response-message": "APPROVED",
  "result": "APPROVED",
  "rrn": "565351134949",
  "surcharge-amount": "3.00",
  "table": "0",
  "terminal-transaction-local-date-time": "20160923134949+1000",
  "tid": "488",
  "tip-amount": "0.00",
  "transaction-amount": "103.00",
  "transaction-currency": "AUD",
  "transaction-reference": "565351",
  "transaction-type": "purchase",
  "transmission-date-time": "20160923034949+0000"
}
```

**Example 2:** Transaction in AUD with surcharging and tip


```json
{
  "approval-code": "027576",
  "base-amount": "100.00",
  "base-currency": "AUD",
  "card-currency": "AUD",
  "card-type": "American Express",
  "elided-pan": "xxxxxxxxxxx8431",
  "issuer-action-code": "00",
  "mid": "25",
  "operator-id": "10",
  "pan-length": "15",
  "pos-reference": "LQZRW1EUX4",
  "receipt-block": "removed for brevity",
  "response-message": "APPROVED",
  "result": "APPROVED",
  "rrn": "565358143510",
  "surcharge-amount": "3.00",
  "table": "0",
  "terminal-transaction-local-date-time": "20160923143510+1000",
  "tid": "488",
  "tip-amount": "10.00",
  "transaction-amount": "113.00",
  "transaction-currency": "AUD",
  "transaction-reference": "565358",
  "transaction-type": "purchase",
  "transmission-date-time": "20160923043511+0000"
}
```

**Example 3:** Transaction in USD with tip


```json
{
  "approval-code": "037492",
  "base-amount": "100.00",
  "base-currency": "AUD",
  "card-currency": "USD",
  "card-type": "Visa",
  "elided-pan": "xxxxxxxxxxxx0010",
  "exchange-rate": "1.390000000",
  "issuer-action-code": "00",
  "mid": "25",
  "operator-id": "10",
  "pan-length": "16",
  "pos-reference": "JS44PCP5P1",
  "receipt-block": "removed for brevity",
  "response-message": "APPROVED",
  "result": "APPROVED",
  "rrn": "626716706773",
  "surcharge-amount": "0.00",
  "table": "0",
  "terminal-transaction-local-date-time": "20160923160940+1000",
  "tid": "488",
  "tip-amount": "10.00",
  "transaction-amount": "79.14",
  "transaction-currency": "USD",
  "transaction-reference": "706773",
  "transaction-type": "purchase",
  "transmission-date-time": "20160923060940+0000"
}
```

**Example 4:** Transaction in AUD with receipt block


```json
{
 "approval-code": "000003",
 "base-amount": "100.00",
 "base-currency": "AUD",
 "card-currency": "AUD",
 "card-type": "Visa",
 "elided-pan": "xxxxxxxxxxxx9521",
 "issuer-action-code": "00",
 "mid": "850",
 "operator-id": "6",
 "pan-length": "16",
 "pos-reference": "6UDMSOZA9O",
 "receipt-block": "
       Pay@table test      
      123 test street      
      Sydney NSW 2000      
 
       MERCHANT COPY       
 
    Tyro Payments EFTPOS   
 
NAB Visa Credit
AID: A0000000031010
Card: xxxxxxxxxxxx9521 (t)
 
Purchase    AUD     $100.00
Surcharge   AUD       $0.50
                 ----------
Total       AUD     $100.50
 
APPROVED              00
 
Table number: 2
Terminal ID: 437
Transaction Ref: 460030
Authorisation No: 000003
25 Jan 2021 at 02:19 PM
 
Retain copy for your records
 
Response time: 1.12 sec
 
",
 "response-message": "APPROVED",
 "result": "APPROVED",
 "rrn": "102514460030",
 "surcharge-amount": "0.50",
 "table": "2",
 "terminal-transaction-local-date-time": "20210125141924+1100",
 "tid": "437",
 "tip-amount": "0.00",
 "transaction-amount": "100.50",
 "transaction-currency": "AUD",
 "transaction-reference": "460030",
 "transaction-type": "purchase",
 "transmission-date-time": "20210125031925+0000"
}
```

**Error codes:**

* To acknowledge the request from the terminal, the POS server returns an HTTP status code of
200 (OK).
* Any other HTTP status code from the POS server is interpreted as a permanent error condition, and
the terminal resets ready for the next transaction. If the terminal receives no response from the
POS server, it continues to send the transaction result until a response is received.


Because the terminal resends transaction results until a response is received, POS servers should
handle duplicate receipt of transaction results. To let the POS server determine the authenticity
of the message, the terminal includes a Message Authentication Code (MAC) as an HTTP header named
`x-tyro-mac`. See
[Generating and verifying Message Authentication Codes](/docs/in-person-payments/pay-in-person/features/pay-at-table/testing#generating-and-verifying-message-authentication-codes)
for how to generate and verify the MAC for the message.

Continue to [Posting cancelled transactions](/docs/in-person-payments/pay-in-person/features/pay-at-table/posting-cancelled).