Server de test care emulează API-ul Cargus UrgentOnlineAPI (V3) (https://urgentcargus.azure-api.net/api/), cu un panou de control pentru valorile care în platforma reală sunt administrate de Cargus.
- Fără dependențe: doar Node.js ≥ 22.13 (
node:http,node:sqlite,node:crypto). - Persistent: toate datele sunt într-un singur fișier SQLite,
data/cargus.sqlite. - Integrare: în aplicația ta schimbi doar URL-ul de bază, de exemplu
https://cargus-test.exemplu.ro/api/.
npm startLa prima pornire, consola afișează un cod de configurare. Deschide http://<host>:3060/admin/ și creează contul de administrator cu acest cod. După primul cont, înregistrarea se dezactivează definitiv, iar endpoint-ul de setup răspunde 404.
Apoi, în panou:
- Chei abonament: adaugă o cheie. Este valoarea pentru
Ocp-Apim-Subscription-Key. - Utilizatori API: creează un user și o parolă. Sunt datele pentru
LoginUser. - Clientul implicit („Client Test SRL”) există deja, cu tariful
23049și punctul de ridicare201000001(sediu,LocationId = 0).
| Variabilă | Implicit | Rol |
|---|---|---|
PORT |
3060 |
Portul de ascultare. |
HOST |
0.0.0.0 |
Interfața. Pune 127.0.0.1 când rulezi în spatele unui reverse proxy. |
DATA_DIR |
./data |
Directorul bazei de date. |
ADMIN_PATH |
/admin |
Calea panoului. Poți folosi o cale mai greu de ghicit. |
TRUST_PROXY |
0 |
1 în spatele unui proxy. Se folosesc X-Forwarded-For și X-Forwarded-Proto. |
COOKIE_SECURE |
auto | Cookie Secure + prefix __Host-. Se activează automat cu TLS sau TRUST_PROXY=1. |
TLS_CERT, TLS_KEY |
– | HTTPS direct din Node, fără proxy. |
SETUP_TOKEN |
aleator | Codul de configurare inițială (minim 12 caractere). |
Rulează serverul pe 127.0.0.1 în spatele unui reverse proxy cu HTTPS. Exemplu cu Caddy:
cargus-test.exemplu.ro {
reverse_proxy 127.0.0.1:3060
}
HOST=127.0.0.1 TRUST_PROXY=1 ADMIN_PATH=/panou-x7k2 npm startExemplu de unit systemd:
[Service]
User=cargusmock
WorkingDirectory=/opt/cargus-mock
Environment=HOST=127.0.0.1 TRUST_PROXY=1 PORT=3060
ExecStart=/usr/bin/node --disable-warning=ExperimentalWarning src/server.js
Restart=always
NoNewPrivileges=true
ProtectSystem=strict
ReadWritePaths=/opt/cargus-mock/dataDacă ai pierdut parola de administrator, rulează pe server npm run reset-admin și repornește serverul. Va afișa un cod de configurare nou.
- Înregistrare unică:
- Înregistrarea cere codul din consolă.
- Inserarea e atomică (
INSERT … WHERE NOT EXISTS), deci doar primul cont poate fi creat. - După aceea, ruta de setup răspunde 404.
- Parole:
- Hash scrypt cu sare, comparate în timp constant.
- Tokenurile API și sesiunile sunt stocate doar ca hash SHA-256.
- Sesiuni:
- Cookie
HttpOnly,SameSite=Strict,Secure/__Host-cu HTTPS, expiră în 12 ore. - La schimbarea parolei, celelalte sesiuni sunt invalidate.
- Cookie
- CSRF: header
X-CSRF-Tokenobligatoriu, verificareaOriginșiContent-Type: application/jsonobligatoriu. - Limitare de rată:
- Login admin: 10 încercări / user / 15 min și 20 / IP.
LoginUser: 30 / min / IP.- Cereri anonime sau cu cheie greșită: 60 / min / IP; peste limită nu se mai jurnalizează.
- Cereri pe cheie de abonament: configurabil.
- Protecții HTTP:
- CSP strict, fără scripturi inline, și
X-Frame-Options: DENY. - HSTS sub HTTPS.
- Limite de mărime pentru body și timeouts pentru request și headere.
- CSP strict, fără scripturi inline, și
- Date:
- SQL exclusiv cu parametri; numele de coloane vin doar din definițiile din cod.
- UI-ul nu folosește
innerHTML.
- Jurnal: parolele, tokenurile și cheile sunt mascate.
Este confirmat prin probe pe API-ul real:
- Rutare case-insensitive pentru căi și pentru parametrii de query.
- Ruta, metoda HTTP și parametrii obligatorii se verifică înaintea cheii. Dacă lipsesc, răspunsul e 404
{ "statusCode": 404, "message": "Resource not found" }, cu spațierea exactă. - Cheie lipsă sau invalidă: 401 cu mesajele exacte APIM și headerul
WWW-Authenticate. - Token invalid sau expirat: 401
"Failed to authenticate!". - POST/PUT fără
Content-Length: 411.
| Metodă | Cale |
|---|---|
| POST | LoginUser |
| GET | TokenVerification |
| GET | Countries, Counties, Localities, Localities/DetailsLocality, Streets |
| GET, POST, PUT | PickupLocations |
| GET | PickupLocations/GetForClient |
| POST | PickupLocations/AssignToUser |
| GET | Recipients, PudoPoints, PriceTables |
| POST | ShippingCalculation |
| POST | Awbs, Awbs/WithGetAwb, AwbPickup, AwbPickup/WithGetAwb |
| GET, DELETE | Awbs |
| GET | Awbs/GetByDate |
| POST | GetRoutingAddress, Awbs/GetRoutingAddress |
| GET | AwbDocuments (PDF/HTML, A4/etichetă, printMainOnce) |
| GET | AwbTrace, AwbTrace/WithRedirect, AwbTrace/GetDeltaEvents |
| GET | AwbStatus/GetAwbSyncStatusByBarCode |
| GET | AwbRetur, AwbScan |
| PUT | Orders, Orders/PutAll |
| GET | Orders, Orders/GetByDate, Orders/GetByOrderId |
| GET | CashAccount, CashAccount/GetByDate, CashAccount/GetByDeductionDate |
| GET | Invoices, InvoiceDocuments |
Datele provin din fișierele livrate cu plugin-ul oficial Cargus pentru WooCommerce, deci id-urile sunt cele reale:
- 44 de județe;
- 13.643 de localități (de exemplu București = 150, Pitești = 157, Iași = 163, Cluj-Napoca = 164);
- 1.966 de puncte Ship & Go.
Străzile sunt doar câteva exemple; le poți adăuga din panou.
- AWB-uri:
- Localitatea se rezolvă după id sau după nume (fără diacritice).
- Validări pentru plicuri, greutate, ServiceId, Multipiece (≤15 colete, ≤31 kg/colet, ≤465 kg), PUDO (ServiceId 38), plaja de AWB-uri a clientului și livrarea sâmbăta.
- Codurile de colet se generează automat.
- Comenzi:
- AWB-urile intră în comanda deschisă a punctului de ridicare.
PUT Ordersvalidează (action=1) sau anulează (action=0) comanda.- Comenzile se închid automat la
AutomaticEOD.
- Ștergere AWB: reușește doar fără evenimente de tracking. AWB-urile șterse apar în continuare cu
Status: "Deleted". - Tarife: costurile se calculează după tabelele de tarif editabile (bază, kg suplimentare, km suplimentari, asigurare, ramburs, taxe speciale, discount, TVA).
- Setări administrative:
- Formatul erorilor:
["mesaj"],"mesaj"sau{"Error":"mesaj"}. - Statusul HTTP pentru erori.
- Barcode returnat ca număr sau ca string.
- Valabilitatea tokenului, următorul număr de AWB sau comandă, plaja de AWB-uri.
- TVA, validări stricte, latență simulată, liste goale cu 204.
- Formatul erorilor:
- Scenarii: forțează un răspuns (status + body exact), o întârziere sau un număr limitat de eșecuri pe un endpoint. Exemple: un 500 la primul
POST Awbs, un timeout laAwbTrace. - AWB-uri:
- Evenimente de tracking (cu presetări), status, confirmare de livrare.
- Greutate măsurată, retur sau redirecționare (
AwbRetur,ResponseCode). - Ramburs în cont colector (
CashAccount), poză de confirmare (AwbScan). - Editarea JSON-ului brut returnat de API.
- Comenzi, facturi, clienți, utilizatori, puncte de ridicare, tarife, agendă, nomenclator, PUDO.
- Jurnal API: fiecare cerere, cu headere, body și răspuns.
- Tokenuri: poți revoca toate tokenurile ca să simulezi expirarea.
- Backup: descarcă baza de date SQLite.
Unele detalii nu apar în documentație sau în codul plugin-urilor. Sunt configurabile, ca să le poți potrivi cu ce vezi în producție:
- Statusul HTTP exact la
LoginUsercu parolă greșită (implicit 400, body{"Error": "..."}). - Formatul și statusul erorilor de validare la
Awbs(implicit 400["mesaj"]). - Dacă
POST Awbsîntoarce barcode-ul ca număr sau ca string (implicit număr). - EventId-urile și textele reale ale evenimentelor de tracking; presetările din panou sunt doar sugestii.
- Formatul răspunsurilor pentru
Recipients,CashAccount,Invoices,AwbReturșiGetDeltaEvents, construit după documentația PDF.
npm testTestul end-to-end pornește serverul pe o bază de date temporară și parcurge:
- configurarea inițială;
- comportamentul APIM;
- login și nomenclator;
- tarife, AWB, comenzi, tracking, retur și ramburs;
- scenariile și setările.