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. 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-terminalsrăspunde404. - 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
424cash_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) șicode, 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) | Test | Plată | Anulare | Închidere de zi | Verificare automată |
|---|---|---|---|---|---|
SmartPay (SmartPay) | Întreabă terminalul | Da | Da | Da: număr, total, lot | Da |
GPE (Gpe) | Întreabă terminalul | Da | Da (reversare) | Da: număr, total | Da |
Ingenio (Ingenio) | Întreabă terminalul | Da | Da | Da: lot | Nu |
Mellon (Mellon) | Doar configurația | Da | Nu (409 transaction_not_voidable) | Nu (500 internal_error) | Nu |
Payten (Payten, PaytenBrd) | Doar configurația | Da | Da | Da: număr, total, lot | Nu |
ePay (Epay) | Întreabă terminalul | Da | Nu (409 transaction_not_voidable) | Da, fără totaluri | Nu |
Printec (Printec, PrintecDll) | Doar configurația | Da | Da | Nu (500 internal_error) | Nu |
FIP11 (Fip11) | Doar configurația | Da | Da | O pornește; nu primești totaluri | Nu |
- 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.
| Protocol | Ce e serial |
|---|---|
| SmartPay, ePay | Seria terminalului. |
| GPE | Terminal ID-ul (TID). |
| Ingenio | Seria terminalului; dacă nu o dă, TID-ul; altfel portul. |
| Mellon, Payten, Printec, FIP11 | Portul la care e conectat: portul serial (de exemplu COM4) sau, prin rețea, ip:port, cu : scris -. |
Fluxul unei plăți
- Citești terminalele:
GET /payment-terminals. Alegiserial-ul;isDefaultarată terminalul ales implicit în aplicație,isConnecteddacă e conectat acum. - Ceri plata:
POST /payment-terminals/{serial}/salecuamountși, dacă vrei,reference, referința ta. - Ț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.
transactionIdvine doar în răspuns. Dacă închizi cererea, plata nu se oprește. - Citești răspunsul.
200: plata e aprobată.402: refuzată, suma nu a fost încasată.409terminal_uncertain: rezultatul nu se știe, nu încasa din nou.409terminal_busy: terminalul e ocupat.424terminal_not_connected: cererea n-a ajuns la terminal, suma nu a fost încasată. - 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. - Dacă vânzarea se anulează:
POST /payment-terminals/{serial}/voidcutransactionId-ul plății. - La sfârșitul zilei, unde protocolul o are:
POST /payment-terminals/{serial}/settlement.
Cererea de plată
{
"amount": 12.50,
"reference": "POS-0001"
}Răspunsul
{
"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âmp | Tip | Descriere |
|---|---|---|
serial | string | Seria terminalului, folosită în rute. |
protocol | string | SmartPay, Gpe, Ingenio, Mellon, Payten, PaytenBrd, Epay, Printec, PrintecDll sau Fip11. |
connectivity | string | Serial sau Tcp. |
label | string | null | Numele dat terminalului în aplicație. |
isConnected | bool | Terminalul e conectat acum. |
isBusy | bool | Terminalul rulează acum o operațiune. |
isDefault | bool | Terminalul ales implicit în aplicație. |
Coduri de răspuns
| Status | code | Când |
|---|---|---|
| 200 | — | Lista, goală dacă nu e niciun terminal. |
| 401 | — | Casa conectată nu are licență. |
curl -X GET 'https://localhost.fiscallink.ro:65401/api/v2/payment-terminals'{
"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âmp | Tip | Descriere |
|---|---|---|
rawSerial | string | null | Seria cum a raportat-o terminalul, înainte de normalizare. |
address | string | Portul serial sau ip:port. |
softwareVersion | string | null | Versiunea software a terminalului, când o dă. |
terminalId | string | null | TID-ul, când terminalul l-a dat la identificare sau la ultima tranzacție. |
merchantId | string | null | MID-ul, la fel. |
unresolvedTransactions | string[] | transactionId-urile încă în verificare. Cât lista nu e goală, plățile noi și închiderea de zi sunt refuzate. |
Coduri de răspuns
| Status | code | Când |
|---|---|---|
| 200 | — | Terminalul. |
| 401 | — | Casa conectată nu are licență. |
| 404 | terminal_not_found | Nicio serie configurată nu se potrivește. |
curl -X GET 'https://localhost.fiscallink.ro:65401/api/v2/payment-terminals/PT000001'{
"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âmp | Tip | Obligatoriu | Descriere |
|---|---|---|---|
amount | decimal | Da | Suma în lei: mai mare decât 0, cel mult două zecimale, cel mult 9.999.999.999,99. |
reference | string | Nu | Referința ta, salvată cu tranzacția și întoarsă când o citești. |
Răspuns (data)
| Câmp | Tip | Descriere |
|---|---|---|
transactionId | string | Identificatorul tranzacției, dat de aplicație: FL, data și ora (12 cifre) și 6 litere sau cifre. |
serial | string | Seria terminalului. |
approved | bool | true la o plată aprobată. |
amount | decimal | Suma aprobată de terminal. |
currency | string | Mereu RON. |
responseCode | string | null | Codul de răspuns al terminalului sau al băncii. |
responseText | string | null | Textul răspunsului, când există. |
authCode | string | null | Codul de autorizare. |
rrn | string | null | Numărul de referință al tranzacției (RRN). |
stan | string | null | Numărul tranzacției pe terminal (STAN, numărul bonului sau al facturii terminalului). |
maskedPan | string | null | Numărul cardului, mascat de terminal. |
cardLabel | string | null | Tipul cardului. |
aid | string | null | Identificatorul aplicației de pe cip (AID). |
entryMode | string | null | chip, contactless sau magstripe, când terminalul o spune. |
pinEntered | bool | Clientul a introdus PIN-ul. |
signatureRequired | bool | Bonul cardului trebuie semnat. Doar te anunță. |
terminalId | string | null | TID-ul. |
merchantId | string | null | MID-ul. |
timestamp | datetime | Momentul tranzacției. |
receiptText | string | null | Doar 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
| Status | code | Când |
|---|---|---|
| 200 | — | Plata e aprobată. |
| 400 | invalid_request | amount lipsă sau greșit, ori corpul nu e JSON. Nu s-a scris nicio tranzacție. |
| 401 | — | Casa conectată nu are licență. |
| 402 | terminal_declined | Plata e refuzată; corpul are responseCode și transaction. Suma nu a fost încasată. |
| 404 | terminal_not_found | Seria nu e a niciunui terminal. |
| 409 | terminal_busy | Terminalul e ocupat cu altă operațiune. Suma nu a fost încasată. |
| 409 | terminal_uncertain | Rezultatul nu se știe; corpul are transactionId. Nu încasa din nou. |
| 409 | terminal_recovery_pending | O tranzacție anterioară e nerezolvată; corpul are transactionIds. |
| 424 | terminal_not_connected | Terminalul nu e conectat, sau cererea n-a ajuns la el. Suma nu a fost încasată. |
| 424 | cash_register_required | Nicio casă de marcat conectată și licențiată. |
| 500 | internal_error | Eroare neașteptată înainte ca plata să pornească. Suma nu a fost încasată. |
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"
}'{
"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
}
}{
"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
}
}{
"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âmp | Tip | Obligatoriu | Descriere |
|---|---|---|---|
transactionId | string | Da | transactionId-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
| Status | code | Când |
|---|---|---|
| 200 | — | Plata e anulată. |
| 400 | invalid_request | transactionId lipsă, ori corpul nu e JSON. |
| 401 | — | Casa conectată nu are licență. |
| 402 | terminal_declined | Terminalul a refuzat anularea; plata rămâne încasată. |
| 404 | terminal_not_found | Seria nu e a niciunui terminal. |
| 404 | transaction_not_found | Terminalul nu are tranzacția. |
| 409 | terminal_busy | Terminalul e ocupat. Plata rămâne încasată. |
| 409 | terminal_uncertain | Rezultatul anulării nu se știe; tranzacția rămâne VoidPending până se verifică. |
| 409 | transaction_not_voidable | Tranzacția nu e aprobată sau a fost deja anulată, protocolul nu anulează din program, ori plata nu are identificatorul după care se anulează. |
| 424 | terminal_not_connected | Terminalul nu e conectat, sau cererea n-a ajuns la el. Plata rămâne încasată. |
| 424 | cash_register_required | Nicio casă de marcat conectată și licențiată. |
| 500 | internal_error | Eroare neașteptată înainte ca anularea să pornească. |
curl -X POST 'https://localhost.fiscallink.ro:65401/api/v2/payment-terminals/PT000001/void' \
-H 'Content-Type: application/json' \
-d '{
"transactionId": "FL261109101500A1B2C3"
}'{
"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
}
}{
"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âmp | Tip | Descriere |
|---|---|---|
serial | string | Seria terminalului. |
approved | bool | Mereu true la 200; un refuz răspunde 402. |
responseCode | string | null | Codul de răspuns al terminalului. |
responseText | string | null | Textul răspunsului, când există. |
transactionCount | int | null | Numărul de tranzacții din lot, când protocolul îl dă. |
totalAmount | decimal | null | Totalul lotului, când protocolul îl dă. |
batchNumber | string | null | Numărul lotului, când protocolul îl dă. |
terminalId | string | null | TID-ul, când protocolul îl dă. |
merchantId | string | null | MID-ul, când protocolul îl dă. |
timestamp | datetime | Momentul închiderii. |
Coduri de răspuns
| Status | code | Când |
|---|---|---|
| 200 | — | Închiderea e făcută (pe FIP11: pornită). |
| 401 | — | Casa conectată nu are licență. |
| 402 | terminal_declined | Terminalul a refuzat închiderea; corpul are responseCode. |
| 404 | terminal_not_found | Seria nu e a niciunui terminal. |
| 409 | terminal_busy | Terminalul e ocupat. |
| 409 | terminal_recovery_pending | O tranzacție e încă nerezolvată; corpul are transactionIds. |
| 424 | terminal_not_connected | Terminalul nu e conectat, sau cererea n-a ajuns la el. |
| 424 | cash_register_required | Nicio casă de marcat conectată și licențiată. |
| 500 | internal_error | Eroare neașteptată, sau protocolul nu are închidere de zi din program (Mellon, Printec). |
curl -X POST 'https://localhost.fiscallink.ro:65401/api/v2/payment-terminals/PT000001/settlement'{
"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âmp | Tip | Descriere |
|---|---|---|
rawSerial | string | Seria raportată de terminal, sau portul. |
serial | string | Seria, normalizată. |
softwareVersion | string | null | Versiunea software, când o dă. |
terminalId | string | null | TID-ul, când protocolul îl are la identificare. |
merchantId | string | null | Niciun protocol nu îl dă la test. |
Coduri de răspuns
| Status | code | Când |
|---|---|---|
| 200 | — | Terminalul a răspuns. |
| 401 | — | Casa conectată nu are licență. |
| 404 | terminal_not_found | Seria nu e a niciunui terminal. |
| 409 | terminal_busy | Terminalul e ocupat. |
| 424 | terminal_not_connected | Terminalul nu e conectat sau nu răspunde. |
| 424 | cash_register_required | Nicio casă de marcat conectată și licențiată. |
| 500 | internal_error | Eroare neașteptată. |
curl -X POST 'https://localhost.fiscallink.ro:65401/api/v2/payment-terminals/PT000001/test'{
"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âmp | Tip | Descriere |
|---|---|---|
state | string | Pending, Approved, Declined, Uncertain, NotPerformed, VoidPending sau Voided; vezi Stările tranzacției. |
amount | decimal | Suma cerută. |
approvedAmount | decimal | null | Suma aprobată, după aprobare. |
reference | string | null | Referința trimisă la plată. |
createdAt | datetime | Când a fost scrisă tranzacția (UTC). |
updatedAt | datetime | Ultima schimbare (UTC). |
Coduri de răspuns
| Status | code | Când |
|---|---|---|
| 200 | — | Tranzacția. |
| 401 | — | Casa conectată nu are licență. |
| 404 | terminal_not_found | Seria nu e a niciunui terminal. |
| 404 | transaction_not_found | Terminalul nu are tranzacția (cele încheiate se șterg după 180 de zile). |
curl -X GET 'https://localhost.fiscallink.ro:65401/api/v2/payment-terminals/PT000001/transactions/FL261109101500A1B2C3'{
"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"
}
}{
"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}.
state | Ce înseamnă | Nerezolvată |
|---|---|---|
Pending | Plata a început și aplicația nu a terminat-o (de exemplu, s-a oprit în timpul plății). | Da |
Approved | Aprobată: banii s-au luat de pe card. | Nu |
Declined | Refuzată de bancă, de card sau de client. Suma nu a fost încasată. | Nu |
Uncertain | Terminalul a primit cererea, dar nu a venit un răspuns valid: suma poate fi deja încasată. | Da |
NotPerformed | Cererea 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 |
VoidPending | Anularea a pornit și rezultatul ei nu se știe. | Da |
Voided | Anulată: 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
409terminal_uncertain, cutransactionId. Nu încasa din nou aceeași vânzare. - Cât terminalul are o tranzacție nerezolvată (
Pending,UncertainsauVoidPending), o plată nouă și închiderea de zi pe acel terminal răspund409terminal_recovery_pending, cu listatransactionIds. Î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};unresolvedTransactionsdinGET /payment-terminals/{serial}arată ce se verifică încă.
{
"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"
}{
"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
409cuterminal_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.
isBusyarată dacă terminalul rulează acum o operațiune. - Fără `Idempotency-Key`. Rutele terminalelor nu citesc antetul: fiecare
POST …/salee o plată nouă, cu alttransactionId. Nu retrimite o plată al cărei răspuns nu l-ai primit: suma poate fi deja încasată.
{
"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.
| Status | code | Câmpuri în plus | Când | Ce faci |
|---|---|---|---|---|
| 400 | invalid_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. |
| 402 | terminal_declined | responseCode, transaction | Banca, 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ă. |
| 404 | terminal_not_found | — | Nicio serie configurată nu se potrivește. | Citești din nou lista. |
| 404 | transaction_not_found | transactionId | Terminalul nu are tranzacția. | Verifici transactionId-ul și seria. |
| 409 | terminal_busy | — | Terminalul rulează altă operațiune. | Încerci după ce se termină. Suma nu a fost încasată. |
| 409 | terminal_uncertain | transactionId | Rezultatul plății sau al anulării nu se știe. | Nu încasezi din nou. Urmărești tranzacția. |
| 409 | terminal_recovery_pending | transactionIds | O tranzacție anterioară e încă nerezolvată. | Aștepți să se rezolve. |
| 409 | transaction_not_voidable | transactionId | Tranzacț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. |
| 424 | terminal_not_connected | — | Terminalul nu e conectat, sau cererea nu a ajuns la el. | Suma nu a fost încasată. Verifici cablul sau rețeaua. |
| 424 | cash_register_required | — | Nicio casă de marcat conectată și licențiată. | Conectezi casa de marcat. |
| 500 | internal_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.
{
"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ă.
| Protocol | Câmpuri completate la plată |
|---|---|
| SmartPay | responseCode, responseText, authCode, rrn, stan, maskedPan, cardLabel, aid, entryMode, pinEntered, signatureRequired, terminalId, merchantId |
| GPE | responseCode, responseText, authCode, stan, maskedPan, cardLabel, aid, signatureRequired, terminalId, receiptText |
| Ingenio | responseCode, responseText, authCode, rrn, stan, maskedPan, cardLabel, terminalId, merchantId |
| Mellon | responseCode, responseText, authCode, stan, terminalId |
| Payten | responseCode, responseText, authCode, rrn, stan, maskedPan, cardLabel, entryMode, pinEntered, terminalId, merchantId |
| ePay | responseCode, responseText, authCode, rrn, stan, maskedPan, cardLabel, aid, entryMode, terminalId, merchantId |
| Printec | responseCode, responseText, authCode, rrn, stan, maskedPan, pinEntered, terminalId |
| FIP11 | responseCode, responseText, authCode, stan, maskedPan, cardLabel |
| Protocol | Anularea se face după | Închiderea de zi întoarce |
|---|---|---|
| SmartPay | STAN | transactionCount, totalAmount, batchNumber |
| GPE | codul de autorizare (reversare) | transactionCount, totalAmount |
| Ingenio | RRN | batchNumber |
| Mellon | nu anulează din program | nu are |
| Payten | numărul tranzacției pe terminal | transactionCount, totalAmount, batchNumber |
| ePay | nu anulează din program | doar confirmarea |
| Printec | numărul bonului terminalului | nu are |
| FIP11 | numărul facturii terminalului | doar că a pornit |
- `entryMode` e
chip,contactlesssaumagstripe, 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ă.
amountdin răspunsul plății e suma aprobată de terminal; în tranzacție eapprovedAmount. Pe SmartPay, o aprobare pe altă sumă decât cea cerută e tratată ca rezultat incert.