API WebSocket
Această pagină descrie protocolul WebSocket utilizat de driverul FisCool pentru integrarea în timp real, precum și maparea acestuia pe API-ul HTTP standard.
1. Conexiunea WebSocket
Acesta este un model „invers" (inițiat de client). Dvs., integratorul, găzduiți serverul WebSocket; driverul FisCool funcționează ca Client WebSocket și se conectează în afară, către serverul dvs., deschizând o conexiune persistentă. Serverul dvs. controlează apoi dispozitivele locale prin acea conexiune.
Deoarece driverul se conectează spre exterior, acest lucru funcționează fără port forwarding, IP static sau reguli de firewall de intrare pe mașina pe care rulează driverul - chiar și în spatele NAT. Este metoda ideală pentru a controla o flotă de drivere din propriul dvs. backend central.
| Rol | Cine | Responsabilitate |
|---|---|---|
| Server WebSocket | Dvs. (integratorul) | Îl găzduiți, autentificați conexiunile, trimiteți cereri, citiți răspunsuri. |
| Client WebSocket | Driverul FisCool | Se conectează către serverul dvs., execută cererile pe dispozitivele locale, răspunde. |
Cerințe de Configurare
Pentru a îndrepta un driver către serverul dvs., îi furnizați un certificat de configurare - un mic obiect JSON care conține URL-ul serverului dvs. și un token de autentificare la alegerea dvs. Nu aveți nimic de solicitat de la noi: URL-ul și token-ul vă aparțin, fiind definite de propriul dvs. server.
Instrucțiuni: certificatul se încarcă în driver din meniul Setări → Certificat sistem vânzare.
Format Certificat (JSON)
Fișierul JSON trebuie să conțină url și token, ambele indicând către infrastructura dvs. token-ul este un secret partajat opac pe care serverul dvs. îl validează când driverul se conectează (alegeți orice valoare doriți). Câmpul driver_id este configurat separat în interfața aplicației (câmpul „ID Driver"), ca să vă puteți distinge driverele; valoarea din fișier (dacă există) este ignorată la import.
{
"url": "wss://api.domeniultau.ro/ws", // URL-ul serverului WebSocket
"token": "abc-123-xyz" // token de autentificare
}
Driverul construiește URL-ul de conexiune astfel:
{url}?token={token}&driver_id={driver_id_din_interfata}
Notă: driverul se reconectează automat în cazul pierderii conexiunii (reîncercare la fiecare 5 secunde) și monitorizează pachetele de ping primite de la server pentru a verifica starea tunelului.
2. Protocolul de Comunicare
Toate mesajele sunt cadre text JSON încapsulate într-un plic standardizat.
Cerere (Server → Driver)
{
"id": 101, // ID unic al cererii (pentru corelare cu răspunsul)
"type": 0, // 0 = cerere
"content": {
"action": 203, // codul acțiunii (vezi mai jos)
"idempotency_id": "uuid-optional", // OPȚIONAL, respectat doar de acțiunea 203
"parameters": { // payload-ul specific acțiunii
...
}
}
}
Driverul reacționează doar la mesajele cu type = 0; orice altceva este ignorat.
Răspuns (Driver → Server)
{
"id": 101, // același ID ca în cerere
"type": 1, // 1 = răspuns
"status": 0, // 0 = succes, 1 = eroare de execuție, 2 = acțiune necunoscută
"content": { // rezultatul operațiunii (sau detaliile erorii)
...
}
}
Răspunsuri Fragmentate (Chunked)
Răspunsurile mari (în prezent doar rezultatele căutării de imagini, acțiunea 205) sunt transmise în fragmente de ~5 KB cu type = 3:
{
"type": 3, // cadru de răspuns fragmentat
"id": 101,
"status": 0,
"content": {
"d": "…fragment de șir JSON…", // fragmentul de date
"f": false // true la fragmentul final
}
}
Concatenați toate fragmentele d în ordinea sosirii până când f = true, apoi parsați șirul rezultat ca JSON.
3. Acțiuni Disponibile
| Cod Acțiune | Nume | Descriere |
|---|---|---|
999 | PING | Keep-alive. Driverul răspunde cu un pong (vezi mai jos). |
201 | GET_CASE | Returnează dispozitivele fiscale configurate. |
204 | GET_POS | Returnează doar terminalele POS configurate. |
203 | DEVICE_OPERATION | Execută o operațiune fiscală sau POS (bon, raport Z, vânzare, …). Este acțiunea principală - vezi Operațiuni Dispozitive pentru toate payload-urile. |
200 | GET_SYSTEM_PRINTERS | Returnează imprimantele de sistem activate în FisCool. |
202 | PRINT_HTML | Randează HTML și îl tipărește ca bitmap pe o imprimantă de sistem. Parametri: {"html": "...", "printer_name": "..."}. |
205 | SEARCH_IMAGES | Caută imagini de produse. Parametri: {"query": "...", "limit": 5}. Răspunsul (data-URI-uri base64) este livrat ca răspuns fragmentat. |
Acțiunea 201 - răspuns GET_CASE
{
"id": 42, "type": 1, "status": 0,
"content": {
"status": 0,
"msg": "Device list retrieved",
"case": [ ... ] // array de dispozitive fiscale (aceleași obiecte ca GET /devices/fiscal)
}
}
Acțiunea 204 - răspuns GET_POS
{
"id": 43, "type": 1, "status": 0,
"content": {
"status": 0,
"msg": "POS terminals retrieved",
"terminals": [ ... ]
}
}
Acțiunea 200 - răspuns GET_SYSTEM_PRINTERS
{
"id": 44, "type": 1, "status": 0,
"content": {
"status": 0,
"msg": "System printers retrieved",
"printers": ["POS-80", "Microsoft Print to PDF"] // numele imprimantelor, doar cele activate în FisCool
}
}
Acțiunea 202 - răspuns PRINT_HTML
{
"id": 45, "type": 1, "status": 0,
"content": {
"status": 0,
"msg": "Bitmap print job completed successfully"
}
}
La eșec, status-ul exterior este 1, iar content conține un cod de eroare de imprimantă (2001–2005, vezi Coduri de Eroare).
Acțiunea 205 - răspuns SEARCH_IMAGES
Livrat ca răspuns segmentat (type = 3, vezi mai sus). După reasamblarea fragmentelor, conținutul este:
{
"status": 0,
"msg": "Images retrieved",
"images": ["data:image/jpeg;base64,...", ...] // cel mult "limit" imagini
}
4. Mecanismul Keep-Alive (Ping/Pong)
Pentru a menține conexiunea activă și a detecta întreruperile, driverul implementează un watchdog:
- Timeout: driverul așteaptă cel puțin un cadru de intrare (de regulă un PING) la fiecare 20 de secunde.
- Comportament: dacă nu se recepționează nimic în acest interval, driverul consideră conexiunea moartă, o închide și se reconectează.
- Cadrele Ping de la nivelul protocolului WebSocket primesc automat răspuns cu cadre Pong.
Format Ping (Server → Driver)
{
"id": 9999,
"type": 0,
"content": {
"action": 999,
"parameters": {}
}
}
Format Pong (Driver → Server)
{
"id": 9999,
"type": 1,
"status": 0,
"content": {
"pong": "pong"
}
}
5. Operațiuni Dispozitiv (Acțiunea 203) vs API-ul HTTP
Acțiunea WebSocket 203 este echivalentul direct al endpoint-ului HTTP POST /devices/operation. Ambele execută aceeași logică internă; diferă doar transportul.
Structura Cererii
WebSocket (acțiunea 203): payload-ul se pune în câmpul parameters al plicului.
{
"id": 500,
"type": 0,
"content": {
"action": 203,
"parameters": {
"device_id": "uuid-dispozitiv",
"operation": {
"type": "print_receipt",
"lines": [ ... ]
}
}
}
}
HTTP (POST /devices/operation): același payload este corpul (body) cererii JSON.
Structura Răspunsului și Dublul Status
Există două câmpuri de status într-un răspuns WebSocket. Este important să înțelegeți diferența dintre ele:
| Nivel | Câmp | Valori Posibile | Semnificație |
|---|---|---|---|
| 1. Plic (outer) | status |
0 = succes execuție 1 = eroare execuție 2 = acțiune necunoscută |
Indică dacă driverul a reușit să proceseze cererea. 1 înseamnă că a apărut o excepție (eroare de comunicare, validare, eroare de dispozitiv, …). |
| 2. Conținut (inner) | content.status |
0 = succes logic > 0 = cod de eroare specific |
Rezultatul de business al operațiunii - identic cu corpul răspunsului din API-ul HTTP. Vezi Coduri Eroare. |
Regula de aur:
- Dacă
status-ul exterior este0, operațiunea a reușit complet (iar statusul interior este tot0). - Dacă
status-ul exterior este1, citițicontent.statusșicontent.errorpentru a afla de ce (eroare hardware, parametri greșiți, …).
Exemplu de Succes (outer 0, inner 0)
{
"id": 500,
"type": 1,
"status": 0, // ← OK
"content": {
"status": 0, // ← bonul a ieșit OK
"msg": "Receipt printed",
"slip_number": 123,
"z_report_number": 45,
"fiscal_receipt_count": 1050
}
}
Exemplu de Eroare (outer 1, inner 500)
{
"id": 500,
"type": 1,
"status": 1, // ← a apărut o eroare
"content": {
"status": 500, // ← cod specific
"error": "Lipsă hârtie în imprimantă."
}
}
Cum Începeți
Pentru a integra prin WebSocket:
- Rulați un server WebSocket pe propria infrastructură, care implementează protocolul descris mai sus.
- Alegeți un token de autentificare și faceți ca serverul dvs. să accepte conexiunile care îl prezintă (prin parametrul de interogare
token). Folosițidriver_idpentru a identifica ce driver s-a conectat. - Creați un certificat JSON cu
url-ul șitoken-ul serverului dvs. și încărcați-l în fiecare driver din Setări → Certificat sistem vânzare. - Când un driver se conectează, trimiteți-i cereri (acțiunea
203pentru operațiuni de dispozitiv,201/204pentru a lista dispozitivele) și citiți răspunsurile.
Pentru întrebări tehnice, contactați office@ceapa.cool.