API pentru integratori

Consultă rutele API pentru încasări cu cardul, parametrii requesturilor și formatul răspunsurilor. Ghidul explică și stările tranzacțiilor, erorile și diferențele dintre terminale.

Urmează să apară

Plata cu cardul pe terminalele bancare vine într-o versiune viitoare a aplicației FiscalLink. Nu e încă disponibilă: pagina descrie cum va funcționa.

Adresă și acces

Rutele terminalelor fac parte din API-ul local, versiunea 2, la aceeași adresă: https://localhost.fiscallink.ro:65401/api/v2 sau http://{ip-local}:65400/api/v2.

  • Doar pe v2. Rutele sunt sub /api/v2/payment-terminals. Versiunea 1 (/api) nu le are: /api/payment-terminals răspunde 404.
  • Fără cheie. Nu trimiți nicio credențială. Fără licență pe casa conectată, orice rută răspunde 401.
  • Casa de marcat conectată. Plata, anularea, închiderea de zi și testul cer o casă conectată și licențiată; altfel răspund 424 cash_register_required. Citirile (lista, detaliile, o tranzacție) merg și fără casă. Când casa se deconectează, terminalele se deconectează după operațiunea în curs, niciodată în mijlocul unei plăți.
  • Formatul. La succes: { "statusCode": 200, "data": … }, câmpuri camelCase. La eroare: statusCode, message (în limba aplicației) și code, un identificator stabil; unele erori au și câmpuri în plus. Ramifică după code, nu după text.
  • Doar lei. Sumele sunt în RON, cu cel mult două zecimale.
  • Configurarea e în aplicație. Terminalele se adaugă, se modifică și se șterg doar din aplicație; API-ul le folosește.

Ce poate fiecare terminal

Rutele sunt comune tuturor terminalelor, dar operațiunile disponibile depind de protocol. Pentru operațiunile marcate „Nu”, API-ul returnează codul indicat în tabel.

Protocol (protocol)TestPlatăAnulareÎnchidere de ziVerificare automată
SmartPay (SmartPay)Întreabă terminalulDaDaDa: număr, total, lotDa
GPE (Gpe)Întreabă terminalulDaDa (reversare)Da: număr, totalDa
Ingenio (Ingenio)Întreabă terminalulDaDaDa: lotNu
Mellon (Mellon)Doar configurațiaDaNu (409 transaction_not_voidable)Nu (500 internal_error)Nu
Payten (Payten, PaytenBrd)Doar configurațiaDaDaDa: număr, total, lotNu
ePay (Epay)Întreabă terminalulDaNu (409 transaction_not_voidable)Da, fără totaluriNu
Printec (Printec, PrintecDll)Doar configurațiaDaDaNu (500 internal_error)Nu
FIP11 (Fip11)Doar configurațiaDaDaO pornește; nu primești totaluriNu
  • Test. „Întreabă terminalul”: aplicația îi cere terminalului seria și, unde o dă, versiunea software. „Doar configurația”: protocolul nu are o întrebare de identificare, așa că testul răspunde cu portul terminalului, fără să-l contacteze.
  • Anulare. Anulează o plată aprobată, cu toată suma ei. Terminalul găsește plata după identificatorul primit la plată (STAN, RRN, codul de autorizare sau numărul bonului terminalului); o plată fără el nu se poate anula prin API.
  • Verificare automată. Ce face aplicația cu o plată al cărei rezultat nu l-a primit: vezi Rezultat incert.
  • Doar aceste operațiuni. API-ul nu are restituiri, pre-autorizări, cashback sau bacșiș.

Seria terminalului

Fiecare rută a unui terminal are seria lui: /payment-terminals/{serial}/…. Iei seria din GET /payment-terminals; un terminal apare în listă abia după ce aplicația l-a identificat. Seria nu ține cont de litere mari sau mici; spațiile de la capete se taie, iar orice caracter în afară de litere, cifre, ., _ și - devine -. Valoarea raportată de terminal e în rawSerial.

ProtocolCe e serial
SmartPay, ePaySeria terminalului.
GPETerminal ID-ul (TID).
IngenioSeria terminalului; dacă nu o dă, TID-ul; altfel portul.
Mellon, Payten, Printec, FIP11Portul la care e conectat: portul serial (de exemplu COM4) sau, prin rețea, ip:port, cu : scris -.

Fluxul unei plăți

  1. Citești terminalele: GET /payment-terminals. Alegi serial-ul; isDefault arată terminalul ales implicit în aplicație, isConnected dacă e conectat acum.
  2. Ceri plata: POST /payment-terminals/{serial}/sale cu amount și, dacă vrei, reference, referința ta.
  3. Ții cererea deschisă până vine răspunsul. Clientul plătește pe terminal, iar răspunsul vine abia la final, poate după câteva minute. transactionId vine doar în răspuns. Dacă închizi cererea, plata nu se oprește.
  4. Citești răspunsul. 200: plata e aprobată. 402: refuzată, suma nu a fost încasată. 409 terminal_uncertain: rezultatul nu se știe, nu încasa din nou. 409 terminal_busy: terminalul e ocupat. 424 terminal_not_connected: cererea n-a ajuns la terminal, suma nu a fost încasată.
  5. Tipărești bonul fiscal cu plata cu cardul: POST /print-fiscal-receipt. Ruta de plată nu tipărește nimic pe casa de marcat.
  6. Dacă vânzarea se anulează: POST /payment-terminals/{serial}/void cu transactionId-ul plății.
  7. La sfârșitul zilei, unde protocolul o are: POST /payment-terminals/{serial}/settlement.

Cererea de plată

json
{
  "amount": 12.50,
  "reference": "POS-0001"
}

Răspunsul

json
{
  "statusCode": 200,
  "data": {
    "transactionId": "FL261109101500A1B2C3",
    "serial": "PT000001",
    "approved": true,
    "amount": 12.50,
    "currency": "RON",
    "responseCode": "00",
    "responseText": "APPROVED",
    "authCode": "A1B2C3",
    "rrn": "000000000001",
    "stan": "000001",
    "maskedPan": "************0000",
    "cardLabel": "VISA",
    "aid": "A0000000000000",
    "entryMode": "contactless",
    "pinEntered": false,
    "signatureRequired": false,
    "terminalId": "TID00001",
    "merchantId": "MID000000001",
    "timestamp": "2026-11-09T08:15:04Z",
    "receiptText": null
  }
}

Rutele

Exemplele folosesc seria PT000001 și valori inventate.

GET /payment-terminals

Listează terminalele

Terminalele configurate în aplicație care s-au identificat, cu starea lor. Nu ocupă niciun terminal și merge și fără casă de marcat.

CâmpTipDescriere
serialstringSeria terminalului, folosită în rute.
protocolstringSmartPay, Gpe, Ingenio, Mellon, Payten, PaytenBrd, Epay, Printec, PrintecDll sau Fip11.
connectivitystringSerial sau Tcp.
labelstring | nullNumele dat terminalului în aplicație.
isConnectedboolTerminalul e conectat acum.
isBusyboolTerminalul rulează acum o operațiune.
isDefaultboolTerminalul ales implicit în aplicație.

Coduri de răspuns

StatuscodeCând
200—Lista, goală dacă nu e niciun terminal.
401—Casa conectată nu are licență.
GETCerere
curl -X GET 'https://localhost.fiscallink.ro:65401/api/v2/payment-terminals'
200Răspuns
{
  "statusCode": 200,
  "data": [
    {
      "serial": "PT000001",
      "protocol": "SmartPay",
      "connectivity": "Serial",
      "label": "Casa 1",
      "isConnected": true,
      "isBusy": false,
      "isDefault": true
    },
    {
      "serial": "COM4",
      "protocol": "Payten",
      "connectivity": "Serial",
      "label": null,
      "isConnected": false,
      "isBusy": false,
      "isDefault": false
    }
  ]
}

GET /payment-terminals/{serial}

Detaliile unui terminal

Un terminal, cu adresa lui și tranzacțiile încă nerezolvate. Nu ocupă terminalul și merge și fără casă de marcat.

Are câmpurile din listă și, în plus:

CâmpTipDescriere
rawSerialstring | nullSeria cum a raportat-o terminalul, înainte de normalizare.
addressstringPortul serial sau ip:port.
softwareVersionstring | nullVersiunea software a terminalului, când o dă.
terminalIdstring | nullTID-ul, când terminalul l-a dat la identificare sau la ultima tranzacție.
merchantIdstring | nullMID-ul, la fel.
unresolvedTransactionsstring[]transactionId-urile încă în verificare. Cât lista nu e goală, plățile noi și închiderea de zi sunt refuzate.

Coduri de răspuns

StatuscodeCând
200—Terminalul.
401—Casa conectată nu are licență.
404terminal_not_foundNicio serie configurată nu se potrivește.
GETCerere
curl -X GET 'https://localhost.fiscallink.ro:65401/api/v2/payment-terminals/PT000001'
200Răspuns
{
  "statusCode": 200,
  "data": {
    "serial": "PT000001",
    "rawSerial": "PT000001",
    "protocol": "SmartPay",
    "connectivity": "Serial",
    "address": "COM3",
    "label": "Casa 1",
    "isConnected": true,
    "isBusy": false,
    "isDefault": true,
    "softwareVersion": "1.0.0",
    "terminalId": "TID00001",
    "merchantId": "MID000000001",
    "unresolvedTransactions": []
  }
}

POST /payment-terminals/{serial}/sale

Plată cu cardul

Cere terminalului să încaseze amount lei. Răspunde după ce clientul a plătit sau plata s-a încheiat altfel. Ține cererea deschisă: transactionId vine doar în răspuns.

Cerere

CâmpTipObligatoriuDescriere
amountdecimalDaSuma în lei: mai mare decât 0, cel mult două zecimale, cel mult 9.999.999.999,99.
referencestringNuReferința ta, salvată cu tranzacția și întoarsă când o citești.

Răspuns (data)

CâmpTipDescriere
transactionIdstringIdentificatorul tranzacției, dat de aplicație: FL, data și ora (12 cifre) și 6 litere sau cifre.
serialstringSeria terminalului.
approvedbooltrue la o plată aprobată.
amountdecimalSuma aprobată de terminal.
currencystringMereu RON.
responseCodestring | nullCodul de răspuns al terminalului sau al băncii.
responseTextstring | nullTextul răspunsului, când există.
authCodestring | nullCodul de autorizare.
rrnstring | nullNumărul de referință al tranzacției (RRN).
stanstring | nullNumărul tranzacției pe terminal (STAN, numărul bonului sau al facturii terminalului).
maskedPanstring | nullNumărul cardului, mascat de terminal.
cardLabelstring | nullTipul cardului.
aidstring | nullIdentificatorul aplicației de pe cip (AID).
entryModestring | nullchip, contactless sau magstripe, când terminalul o spune.
pinEnteredboolClientul a introdus PIN-ul.
signatureRequiredboolBonul cardului trebuie semnat. Doar te anunță.
terminalIdstring | nullTID-ul.
merchantIdstring | nullMID-ul.
timestampdatetimeMomentul tranzacției.
receiptTextstring | nullDoar GPE, când terminalul e setat să tipărească prin casă: bonul cardului formatat de terminal. Aplicația nu îl tipărește.

Coduri de răspuns

StatuscodeCând
200—Plata e aprobată.
400invalid_requestamount lipsă sau greșit, ori corpul nu e JSON. Nu s-a scris nicio tranzacție.
401—Casa conectată nu are licență.
402terminal_declinedPlata e refuzată; corpul are responseCode și transaction. Suma nu a fost încasată.
404terminal_not_foundSeria nu e a niciunui terminal.
409terminal_busyTerminalul e ocupat cu altă operațiune. Suma nu a fost încasată.
409terminal_uncertainRezultatul nu se știe; corpul are transactionId. Nu încasa din nou.
409terminal_recovery_pendingO tranzacție anterioară e nerezolvată; corpul are transactionIds.
424terminal_not_connectedTerminalul nu e conectat, sau cererea n-a ajuns la el. Suma nu a fost încasată.
424cash_register_requiredNicio casă de marcat conectată și licențiată.
500internal_errorEroare neașteptată înainte ca plata să pornească. Suma nu a fost încasată.
POSTCerere
curl -X POST 'https://localhost.fiscallink.ro:65401/api/v2/payment-terminals/PT000001/sale' \
  -H 'Content-Type: application/json' \
  -d '{
  "amount": 12.5,
  "reference": "POS-0001"
}'
200Răspuns
{
  "statusCode": 200,
  "data": {
    "transactionId": "FL261109101500A1B2C3",
    "serial": "PT000001",
    "approved": true,
    "amount": 12.50,
    "currency": "RON",
    "responseCode": "00",
    "responseText": "APPROVED",
    "authCode": "A1B2C3",
    "rrn": "000000000001",
    "stan": "000001",
    "maskedPan": "************0000",
    "cardLabel": "VISA",
    "aid": "A0000000000000",
    "entryMode": "contactless",
    "pinEntered": false,
    "signatureRequired": false,
    "terminalId": "TID00001",
    "merchantId": "MID000000001",
    "timestamp": "2026-11-09T08:15:04Z",
    "receiptText": null
  }
}
402Răspuns
{
  "statusCode": 402,
  "message": "The card payment was declined: DECLINED",
  "code": "terminal_declined",
  "responseCode": "05",
  "transaction": {
    "transactionId": "FL261109101500A1B2C3",
    "serial": "PT000001",
    "approved": false,
    "amount": 12.50,
    "currency": "RON",
    "responseCode": "05",
    "responseText": "DECLINED",
    "authCode": null,
    "rrn": "000000000001",
    "stan": "000001",
    "maskedPan": "************0000",
    "cardLabel": "VISA",
    "aid": null,
    "entryMode": "chip",
    "pinEntered": true,
    "signatureRequired": false,
    "terminalId": "TID00001",
    "merchantId": "MID000000001",
    "timestamp": "2026-11-09T08:15:04Z",
    "receiptText": null
  }
}
409Răspuns
{
  "statusCode": 409,
  "message": "Payment terminal PT000001 did not confirm the outcome of transaction FL261109101500A1B2C3. It is being checked; do not charge the card again.",
  "code": "terminal_uncertain",
  "transactionId": "FL261109101500A1B2C3"
}

POST /payment-terminals/{serial}/void

Anulează o plată

Anulează pe terminal o plată aprobată, cu toată suma ei. Nu merge pe Mellon și ePay.

CâmpTipObligatoriuDescriere
transactionIdstringDatransactionId-ul din răspunsul plății.

Răspunsul are forma răspunsului de plată, cu același transactionId; stan, rrn și authCode sunt ale anulării. După 200, tranzacția are state Voided.

Coduri de răspuns

StatuscodeCând
200—Plata e anulată.
400invalid_requesttransactionId lipsă, ori corpul nu e JSON.
401—Casa conectată nu are licență.
402terminal_declinedTerminalul a refuzat anularea; plata rămâne încasată.
404terminal_not_foundSeria nu e a niciunui terminal.
404transaction_not_foundTerminalul nu are tranzacția.
409terminal_busyTerminalul e ocupat. Plata rămâne încasată.
409terminal_uncertainRezultatul anulării nu se știe; tranzacția rămâne VoidPending până se verifică.
409transaction_not_voidableTranzacția nu e aprobată sau a fost deja anulată, protocolul nu anulează din program, ori plata nu are identificatorul după care se anulează.
424terminal_not_connectedTerminalul nu e conectat, sau cererea n-a ajuns la el. Plata rămâne încasată.
424cash_register_requiredNicio casă de marcat conectată și licențiată.
500internal_errorEroare neașteptată înainte ca anularea să pornească.
POSTCerere
curl -X POST 'https://localhost.fiscallink.ro:65401/api/v2/payment-terminals/PT000001/void' \
  -H 'Content-Type: application/json' \
  -d '{
  "transactionId": "FL261109101500A1B2C3"
}'
200Răspuns
{
  "statusCode": 200,
  "data": {
    "transactionId": "FL261109101500A1B2C3",
    "serial": "PT000001",
    "approved": true,
    "amount": 12.50,
    "currency": "RON",
    "responseCode": "00",
    "responseText": "APPROVED",
    "authCode": "A1B2C4",
    "rrn": "000000000002",
    "stan": "000002",
    "maskedPan": "************0000",
    "cardLabel": "VISA",
    "aid": null,
    "entryMode": null,
    "pinEntered": false,
    "signatureRequired": false,
    "terminalId": "TID00001",
    "merchantId": "MID000000001",
    "timestamp": "2026-11-09T08:20:11Z",
    "receiptText": null
  }
}
409Răspuns
{
  "statusCode": 409,
  "message": "Transaction FL261109101500A1B2C3 cannot be voided: it is Voided.",
  "code": "transaction_not_voidable",
  "transactionId": "FL261109101500A1B2C3"
}

POST /payment-terminals/{serial}/settlement

Închiderea de zi

Închide lotul zilei pe terminal. E refuzată cât terminalul are o tranzacție nerezolvată, pentru că șterge jurnalul de care depinde verificarea. Fără corp.

CâmpTipDescriere
serialstringSeria terminalului.
approvedboolMereu true la 200; un refuz răspunde 402.
responseCodestring | nullCodul de răspuns al terminalului.
responseTextstring | nullTextul răspunsului, când există.
transactionCountint | nullNumărul de tranzacții din lot, când protocolul îl dă.
totalAmountdecimal | nullTotalul lotului, când protocolul îl dă.
batchNumberstring | nullNumărul lotului, când protocolul îl dă.
terminalIdstring | nullTID-ul, când protocolul îl dă.
merchantIdstring | nullMID-ul, când protocolul îl dă.
timestampdatetimeMomentul închiderii.

Coduri de răspuns

StatuscodeCând
200—Închiderea e făcută (pe FIP11: pornită).
401—Casa conectată nu are licență.
402terminal_declinedTerminalul a refuzat închiderea; corpul are responseCode.
404terminal_not_foundSeria nu e a niciunui terminal.
409terminal_busyTerminalul e ocupat.
409terminal_recovery_pendingO tranzacție e încă nerezolvată; corpul are transactionIds.
424terminal_not_connectedTerminalul nu e conectat, sau cererea n-a ajuns la el.
424cash_register_requiredNicio casă de marcat conectată și licențiată.
500internal_errorEroare neașteptată, sau protocolul nu are închidere de zi din program (Mellon, Printec).
POSTCerere
curl -X POST 'https://localhost.fiscallink.ro:65401/api/v2/payment-terminals/PT000001/settlement'
200Răspuns
{
  "statusCode": 200,
  "data": {
    "serial": "PT000001",
    "approved": true,
    "responseCode": "00",
    "responseText": "OK",
    "transactionCount": 3,
    "totalAmount": 37.50,
    "batchNumber": "000001",
    "terminalId": "TID00001",
    "merchantId": "MID000000001",
    "timestamp": "2026-11-09T20:00:12Z"
  }
}

POST /payment-terminals/{serial}/test

Testează un terminal

Verifică legătura și returnează informațiile de identificare ale terminalului. Pentru Mellon, Payten, Printec și FIP11, răspunsul conține doar portul configurat, fără comunicare cu terminalul. Fără corp.

CâmpTipDescriere
rawSerialstringSeria raportată de terminal, sau portul.
serialstringSeria, normalizată.
softwareVersionstring | nullVersiunea software, când o dă.
terminalIdstring | nullTID-ul, când protocolul îl are la identificare.
merchantIdstring | nullNiciun protocol nu îl dă la test.

Coduri de răspuns

StatuscodeCând
200—Terminalul a răspuns.
401—Casa conectată nu are licență.
404terminal_not_foundSeria nu e a niciunui terminal.
409terminal_busyTerminalul e ocupat.
424terminal_not_connectedTerminalul nu e conectat sau nu răspunde.
424cash_register_requiredNicio casă de marcat conectată și licențiată.
500internal_errorEroare neașteptată.
POSTCerere
curl -X POST 'https://localhost.fiscallink.ro:65401/api/v2/payment-terminals/PT000001/test'
200Răspuns
{
  "statusCode": 200,
  "data": {
    "rawSerial": "PT000001",
    "serial": "PT000001",
    "softwareVersion": "1.0.0",
    "terminalId": null,
    "merchantId": null
  }
}

GET /payment-terminals/{serial}/transactions/{transactionId}

Citește o tranzacție

O tranzacție a terminalului, cu starea ei. Merge oricând, și în timpul unei plăți, și fără casă de marcat.

Are câmpurile răspunsului de plată, fără approved, aid, pinEntered, timestamp și receiptText, plus:

CâmpTipDescriere
statestringPending, Approved, Declined, Uncertain, NotPerformed, VoidPending sau Voided; vezi Stările tranzacției.
amountdecimalSuma cerută.
approvedAmountdecimal | nullSuma aprobată, după aprobare.
referencestring | nullReferința trimisă la plată.
createdAtdatetimeCând a fost scrisă tranzacția (UTC).
updatedAtdatetimeUltima schimbare (UTC).

Coduri de răspuns

StatuscodeCând
200—Tranzacția.
401—Casa conectată nu are licență.
404terminal_not_foundSeria nu e a niciunui terminal.
404transaction_not_foundTerminalul nu are tranzacția (cele încheiate se șterg după 180 de zile).
GETCerere
curl -X GET 'https://localhost.fiscallink.ro:65401/api/v2/payment-terminals/PT000001/transactions/FL261109101500A1B2C3'
200Răspuns
{
  "statusCode": 200,
  "data": {
    "transactionId": "FL261109101500A1B2C3",
    "serial": "PT000001",
    "state": "Approved",
    "amount": 12.50,
    "approvedAmount": 12.50,
    "currency": "RON",
    "reference": "POS-0001",
    "responseCode": "00",
    "responseText": "APPROVED",
    "authCode": "A1B2C3",
    "rrn": "000000000001",
    "stan": "000001",
    "maskedPan": "************0000",
    "cardLabel": "VISA",
    "entryMode": "contactless",
    "signatureRequired": false,
    "terminalId": "TID00001",
    "merchantId": "MID000000001",
    "createdAt": "2026-11-09T08:15:00Z",
    "updatedAt": "2026-11-09T08:15:04Z"
  }
}
404Răspuns
{
  "statusCode": 404,
  "message": "Payment terminal PT000001 has no transaction FL000000000000XXXXXX.",
  "code": "transaction_not_found",
  "transactionId": "FL000000000000XXXXXX"
}

Stările tranzacției

Aplicația salvează tranzacția înainte de a trimite cererea la terminal, apoi actualizează rezultatul. Astfel, poți verifica o plată și după repornire sau după pierderea răspunsului. Citește câmpul state din GET /payment-terminals/{serial}/transactions/{transactionId}.

stateCe înseamnăNerezolvată
PendingPlata a început și aplicația nu a terminat-o (de exemplu, s-a oprit în timpul plății).Da
ApprovedAprobată: banii s-au luat de pe card.Nu
DeclinedRefuzată de bancă, de card sau de client. Suma nu a fost încasată.Nu
UncertainTerminalul a primit cererea, dar nu a venit un răspuns valid: suma poate fi deja încasată.Da
NotPerformedCererea n-a ajuns la terminal, terminalul a refuzat-o fiindcă era ocupat, sau verificarea a aflat că plata nu s-a făcut. Suma nu a fost încasată.Nu
VoidPendingAnularea a pornit și rezultatul ei nu se știe.Da
VoidedAnulată: suma a fost restituită pe card. Și o plată incertă pe care verificarea a găsit-o aprobată și a anulat-o.Nu

Tranzacțiile încheiate se păstrează 180 de zile; cele nerezolvate nu se șterg.

Rezultat incert

Dacă se întrerupe conexiunea sau terminalul nu confirmă rezultatul, aplicația marchează plata ca incertă. Cererea poate fi ajuns la terminal și suma poate fi deja încasată.

  • Plata (sau anularea) răspunde 409 terminal_uncertain, cu transactionId. Nu încasa din nou aceeași vânzare.
  • Cât terminalul are o tranzacție nerezolvată (Pending, Uncertain sau VoidPending), o plată nouă și închiderea de zi pe acel terminal răspund 409 terminal_recovery_pending, cu lista transactionIds. Închiderea de zi e refuzată fiindcă șterge jurnalul terminalului, singura dovadă a ce s-a întâmplat.
  • SmartPay și GPE: aplicația întreabă singură terminalul, când acesta se conectează și apoi periodic, tot mai rar, până la o dată la 10 minute, fără să renunțe. O plată găsită aprobată e anulată, cum cer protocoalele; una care nu s-a făcut devine NotPerformed. O anulare cu rezultat necunoscut se verifică la fel.
  • Ingenio, Mellon, Payten, ePay, Printec și FIP11: aplicația nu poate citi jurnalul acestor terminale, deci nu poate rezolva singură tranzacția. Ea rămâne nerezolvată, iar terminalul refuză plăți noi și închiderea de zi.
  • Verificarea rulează doar cât terminalul e conectat, deci cât e conectată și casa de marcat.
  • Urmărești rezultatul cu GET /payment-terminals/{serial}/transactions/{transactionId}; unresolvedTransactions din GET /payment-terminals/{serial} arată ce se verifică încă.
json
{
  "statusCode": 409,
  "message": "Payment terminal PT000001 did not confirm the outcome of transaction FL261109101500A1B2C3. It is being checked; do not charge the card again.",
  "code": "terminal_uncertain",
  "transactionId": "FL261109101500A1B2C3"
}
json
{
  "statusCode": 409,
  "message": "Payment terminal PT000001 is still checking an earlier transaction (FL261109101500A1B2C3). Try again once it is resolved.",
  "code": "terminal_recovery_pending",
  "transactionIds": ["FL261109101500A1B2C3"]
}

O operațiune pe terminal

  • Fără coadă. Dacă terminalul este ocupat, o cerere nouă primește imediat 409 cu terminal_busy. Așteaptă rezultatul primei operațiuni înainte de a trimite alta. Terminalul este eliberat înainte de transmiterea răspunsului.
  • Terminalele nu se așteaptă între ele. Două terminale încasează în același timp, iar casa de marcat tipărește în timp ce un terminal încasează.
  • Citirile nu ocupă terminalul. Lista, detaliile și o tranzacție răspund oricând, și în timpul unei plăți. isBusy arată dacă terminalul rulează acum o operațiune.
  • Fără `Idempotency-Key`. Rutele terminalelor nu citesc antetul: fiecare POST …/sale e o plată nouă, cu alt transactionId. Nu retrimite o plată al cărei răspuns nu l-ai primit: suma poate fi deja încasată.
json
{
  "statusCode": 409,
  "message": "Payment terminal PT000001 is busy with another operation. Wait for it to finish, then try again.",
  "code": "terminal_busy"
}

Erori și coduri

Verifică întotdeauna câmpul code, nu doar statusul HTTP. De exemplu, 409 cu terminal_busy permite o încercare ulterioară, în timp ce terminal_uncertain cere verificarea plății înainte de o nouă încasare.

StatuscodeCâmpuri în plusCândCe faci
400invalid_request—Corp lipsă sau JSON greșit; amount lipsă, zero, negativ, cu mai mult de două zecimale sau peste 9.999.999.999,99; transactionId lipsă la anulare.Corectezi cererea. Nu s-a scris nicio tranzacție.
401——Casa conectată nu are licență.Activezi licența casei.
402terminal_declinedresponseCode, transactionBanca, cardul sau clientul a refuzat plata; sau terminalul a refuzat anularea ori închiderea de zi.La plată suma nu a fost încasată. La anulare plata rămâne încasată.
404terminal_not_found—Nicio serie configurată nu se potrivește.Citești din nou lista.
404transaction_not_foundtransactionIdTerminalul nu are tranzacția.Verifici transactionId-ul și seria.
409terminal_busy—Terminalul rulează altă operațiune.Încerci după ce se termină. Suma nu a fost încasată.
409terminal_uncertaintransactionIdRezultatul plății sau al anulării nu se știe.Nu încasezi din nou. Urmărești tranzacția.
409terminal_recovery_pendingtransactionIdsO tranzacție anterioară e încă nerezolvată.Aștepți să se rezolve.
409transaction_not_voidabletransactionIdTranzacția nu e aprobată (refuzată, deja anulată, nerezolvată), protocolul nu anulează din program, sau plata nu are identificatorul după care se anulează.Nu se poate anula prin API.
424terminal_not_connected—Terminalul nu e conectat, sau cererea nu a ajuns la el.Suma nu a fost încasată. Verifici cablul sau rețeaua.
424cash_register_required—Nicio casă de marcat conectată și licențiată.Conectezi casa de marcat.
500internal_error—O eroare neașteptată în aplicație, înainte ca plata sau anularea să pornească; sau închiderea de zi pe Mellon și Printec.Suma nu a fost încasată.

Codurile serial_in_use, port_in_use, identity_changed, unresolved_transactions, invalid_configuration și protocol_not_available țin de adăugarea unui terminal în aplicație; rutele de aici nu le întorc.

json
{
  "statusCode": 424,
  "message": "Payment terminals work only while a cash register is connected.",
  "code": "cash_register_required"
}

Diferențe între terminale

Toate terminalele răspund cu aceleași câmpuri. Ce completează fiecare depinde de protocol; un câmp pe care protocolul nu îl dă e null (sau false), iar un terminal anume poate lăsa goale și câmpuri din listă.

ProtocolCâmpuri completate la plată
SmartPayresponseCode, responseText, authCode, rrn, stan, maskedPan, cardLabel, aid, entryMode, pinEntered, signatureRequired, terminalId, merchantId
GPEresponseCode, responseText, authCode, stan, maskedPan, cardLabel, aid, signatureRequired, terminalId, receiptText
IngenioresponseCode, responseText, authCode, rrn, stan, maskedPan, cardLabel, terminalId, merchantId
MellonresponseCode, responseText, authCode, stan, terminalId
PaytenresponseCode, responseText, authCode, rrn, stan, maskedPan, cardLabel, entryMode, pinEntered, terminalId, merchantId
ePayresponseCode, responseText, authCode, rrn, stan, maskedPan, cardLabel, aid, entryMode, terminalId, merchantId
PrintecresponseCode, responseText, authCode, rrn, stan, maskedPan, pinEntered, terminalId
FIP11responseCode, responseText, authCode, stan, maskedPan, cardLabel
ProtocolAnularea se face dupăÎnchiderea de zi întoarce
SmartPaySTANtransactionCount, totalAmount, batchNumber
GPEcodul de autorizare (reversare)transactionCount, totalAmount
IngenioRRNbatchNumber
Mellonnu anulează din programnu are
Paytennumărul tranzacției pe terminaltransactionCount, totalAmount, batchNumber
ePaynu anulează din programdoar confirmarea
Printecnumărul bonului terminaluluinu are
FIP11numărul facturii terminaluluidoar că a pornit
  • `entryMode` e chip, contactless sau magstripe, când terminalul o spune.
  • `signatureRequired` (SmartPay, GPE) te anunță doar că bonul cardului trebuie semnat; verificarea semnăturii revine casierului.
  • `receiptText` (doar GPE, când terminalul e setat să tipărească prin casă): bonul cardului, formatat de terminal pe linii de 24 de caractere, cu marcajele lui de formatare. Aplicația nu îl tipărește.
  • Suma aprobată. amount din răspunsul plății e suma aprobată de terminal; în tranzacție e approvedAmount. Pe SmartPay, o aprobare pe altă sumă decât cea cerută e tratată ca rezultat incert.