e-bon
e-bon.ro
SDK TypeScript

Evenimente

Clasa EventSubscriber — conectare, ascultare cu payload-uri tipate, reconectare automată cu backoff exponențial și catalogul complet de evenimente din EventMap.

Evenimente

EventSubscriber înfășoară WebSocket-ul de evenimente e-bon (wss://api.e-bon.ro/ws) cu listeneri tipați și reconectare automată. Este înlocuitorul recomandat al pollingului pe client.commands.get(id) îndată ce integrarea ta are mai mult de o mână de dispozitive.

Pornire rapidă

Cea mai simplă cale este să lași EBonClient să-ți construiască subscriber-ul, reutilizând aceleași credențiale:

import { EBonClient } from '@e-bon/sdk';

const client = new EBonClient({
  baseUrl: 'https://api.e-bon.ro',
  apiKey: process.env.EBON_API_KEY!,
});

const events = client.events.subscribe();

events.on('receipt.created', (data) => {
  console.log(`bon fiscal ${data.receiptId} pe dispozitivul ${data.deviceId} = ${data.total}`);
});

events.on('command.failed', (data) => {
  // data.fiscalError este o instanță reală FiscalError — o poți arunca direct.
  console.error(data.fiscalError);
});

// Mai târziu, la oprire:
events.close();

Construiește direct un EventSubscriber

EventSubscriber este de asemenea exportat separat și poate fi construit direct atunci când nu ai un EBonClient la îndemână (de exemplu într-un worker care doar ascultă):

import { EventSubscriber } from '@e-bon/sdk';

const events = new EventSubscriber('https://api.e-bon.ro', {
  apiKey: 'ebon_live_...',
});

Semnătura:

new EventSubscriber(baseUrl: string, auth: { apiKey?: string; token?: string })
  • baseUrl — același URL de bază pe care îl dai lui EBonClient. Subscriber-ul rescrie protocolul în ws / wss și adaugă /ws.
  • auth.token — token de acces JWT. Trimis ca ?token=... în URL-ul WebSocket. Are prioritate față de auth.apiKey când sunt setate amândouă.
  • auth.apiKey — cheie API. Trimisă ca ?apiKey=... când nu este oferit niciun token.

Subscriber-ul se conectează imediat la construcție; nu trebuie să apelezi tu o metodă connect().

Ascultă cu on, off, once

Toate cele trei metode sunt tipate prin uniunea EventName derivată din EventMap, deci payload-ul listener-ului este inferat pentru tine:

events.on('device.status', (data) => {
  // data este DeviceStatusEvent { deviceId, status, timestamp }
});

const handler = (data: ReceiptCreatedEvent) => { /* … */ };
events.on('receipt.created', handler);
events.off('receipt.created', handler); // elimină un listener anume

events.once('command.completed', (data) => {
  // se declanșează exact o dată și se dezînregistrează singur
});

Erorile aruncate dintr-un listener sunt înghițite — un throw într-un listener nu va opri ceilalți listeneri să ruleze și nu va distruge bucla WebSocket.

Închide subscriber-ul

Apelează events.close() când ai terminat. Marchează subscriber-ul ca închis, anulează orice timer de reconectare în așteptare și închide socket-ul subiacent. După close(), subscriber-ul este permanent închis — construiește unul nou dacă vrei să o iei de la capăt.

Reconectează automat cu backoff exponențial

Când socket-ul cade, subscriber-ul se reconectează automat. Programul este fix:

ConstantăValoareÎnțeles
DEFAULT_RECONNECT_DELAY1000 msPrima reîncercare are loc la 1 secundă după deconectare.
RECONNECT_BACKOFF_FACTOR2Fiecare reîncercare următoare dublează întârzierea.
MAX_RECONNECT_DELAY30000 msPlafon — întârzierea nu trece niciodată de 30 de secunde.

Așadar, intervalele dintre încercările de reconectare merg 1s → 2s → 4s → 8s → 16s → 30s → 30s → … până când socket-ul revine, moment în care întârzierea se resetează la 1 secundă pentru următoarea deconectare. Evenimentul connected se declanșează de fiecare dată când socket-ul se redeschide; disconnected se declanșează de fiecare dată când cade.

events.on('connected', () => console.log('evenimente: live'));
events.on('disconnected', () => console.warn('evenimente: căzut — se reconectează'));
events.on('error', (err) => console.error('evenimente: eroare socket', err));
Subscriber-ul se bazează pe WebSocket-ul nativ al runtime-ului. Mesajele incorecte primite de la server sunt ignorate în tăcere (socket-ul rămâne deschis). Dacă runtime-ul tău nu pune la dispoziție WebSocket global, instalează un polyfill înainte de a importa @e-bon/sdk.

Răsfoiește catalogul de evenimente

Mulțimea completă a evenimentelor pe care te poți abona este interfața EventMap re-exportată din @e-bon/sdk. Cheile de mai jos sunt exact șirurile pe care le pasezi lui on / off / once; coloana de payload este forma tipată a celui de-al doilea argument.

Șir evenimentTip payloadSe declanșează când
device.statusDeviceStatusEventStatusul de conexiune al unui dispozitiv se schimbă (online / offline / busy).
device.claimedDeviceClaimedEventUn controler (instanță a aplicației mobile E-BON) revendică un dispozitiv.
receipt.createdReceiptCreatedEventUn bon fiscal este stocat pe platformă.
command.completedCommandCompletedEventO comandă fiscală se termină cu succes la imprimantă.
command.failedCommandFailedEventO comandă fiscală eșuează. Payload-ul include un fiscalError precalculat.
app.connectedAppConnectedEventO instanță a aplicației mobile E-BON își deschide WebSocket-ul către server.
app.disconnectedAppDisconnectedEventO instanță a aplicației mobile E-BON se deconectează.
connectedundefinedSocket-ul de evenimente tocmai s-a (re)deschis — doar ciclu de viață local.
disconnectedundefinedSocket-ul de evenimente tocmai a căzut — doar ciclu de viață local.
errorErrorSocket-ul de evenimente a emis o eroare — doar ciclu de viață local.

Tipurile de payload exportate sunt: DeviceStatusEvent, DeviceClaimedEvent, ReceiptCreatedEvent, CommandCompletedEvent, CommandFailedEvent, CommandTimeoutEvent, AppConnectedEvent și AppDisconnectedEvent. Toate pot fi importate ca tipuri din @e-bon/sdk. CommandTimeoutEvent este forma folosită de pipeline-ul de timeout din server; pe fir, evenimentul este livrat ca command.failed cu errorCode: ErrorCode.TimeoutCommand, deci îl tratezi prin același listener.

Exemplu — reacționează la receipt.created

Un worker minim care oglindește fiecare bon fiscal într-un jurnal de audit local:

import { EBonClient, type ReceiptCreatedEvent } from '@e-bon/sdk';

const client = new EBonClient({
  baseUrl: 'https://api.e-bon.ro',
  apiKey: process.env.EBON_API_KEY!,
});

const events = client.events.subscribe();

events.on('connected', () => console.log('evenimente: live'));
events.on('disconnected', () => console.warn('evenimente: se reconectează…'));

events.on('receipt.created', async (event: ReceiptCreatedEvent) => {
  // Aducem bonul fiscal complet acum că îi știm id-ul.
  const receipt = await client.receipts.get(event.receiptId);
  await auditLog.append({
    receiptId: receipt.id,
    deviceId: event.deviceId,
    total: event.total,
    timestamp: event.timestamp,
  });
});

process.on('SIGTERM', () => events.close());

Unde mergi mai departe

  • Erori — forma FiscalError atașată payload-urilor command.failed.
  • API › Webhook-uri — apeluri HTTP de ieșire dacă nu poți menține un WebSocket cu durată lungă de viață.
  • Prezentare generală SDK — înapoi la suprafața clientului.