Worked Example

This example shows a complete operator checkout flow.

Scenario

  • Terminal IP: 192.168.1.50.
  • ECR port: 10000.
  • Sale amount: EUR 6.50.
  • Application must avoid double charges if the LAN socket drops.
  1. Configure the client.

    const client = createEcr17Client({
      host: "192.168.1.50",
      port: 10000,
      terminalId: "12345678",
      cashRegisterId: "00000001",
      lrcMode: "std",
      autoReconnect: true,
      responseTimeoutMs: 60000,
      ackTimeoutMs: 5000
    });
    
  2. Register events.

    client.setOnConnectionStateChange(setConnectionState);
    client.setOnProgress((event) => setPaymentMessage(event.message));
    client.setOnReceiptLine((line) => receiptBuffer.push(line.text));
    
  3. Confirm the terminal is reachable.

    await client.connect();
    const status = await client.status();
    
  4. Collect payment.

    const result = await collectWithRecovery(650);
    
  5. Persist the structured result.

    savePaymentAttempt({
      amountCents: 650,
      outcome: result.outcome,
      resultCode: result.resultCode,
      stan: result.stan,
      authCode: result.authCode,
      onlineId: result.onlineId
    });
    

Recovery helper

async function collectWithRecovery(amountCents: number) {
  try {
    return await client.pay({ amountCents });
  } catch (error) {
    await client.connect();
    return client.sendLastResult();
  }
}
The helper does not retry pay

It recovers the latest terminal outcome with command G. That is the safety boundary that prevents a duplicate payment command.