Sklep, w którym katalog jest czytany w czasie rzeczywistym, nie skopiowany raz i zapomniany.
Budujemy sklepy, a nad nimi warstwę, której zwykle brakuje: agent odpowiadający klientowi czyta cenę i stan magazynowy bezpośrednio ze sklepu, w chwili pytania, i odmawia wymyślenia nieopublikowanej ceny.
Construit dejaSe poate verifica din exterior chiar acum, fără să ne întrebi pe noi. Punctul nostru de catalog livrat unui distribuitor răspunde 200 și spune „154 rezultate”; interfața publică a magazinului lui, interogată direct, întoarce antetul `x-wp-total: 154`. Aceeași cifră, două surse independente, verificat pe 06.09.2026. A doua implementare e integrată în platforma de asistenți: serviciul `storeCatalog.service.js` plus trei unelte pe care agentul le poate chema. Rezerva care trebuie spusă: acest al doilea traseu stă pe o ramură de dezvoltare (`feat/store-catalog-global`, `481cfa0`) și nu e încă unificat în trunchi — deci e livrat pentru clienții pe care i-am conectat, nu pornit implicit pentru toți.
Cele mai multe „integrări de catalog” sunt de fapt un export. Cineva descarcă produsele o dată, le lipește într-un fișier, iar de atunci înainte agentul care vorbește cu clientul citește o fotografie veche a magazinului. Funcționează impecabil până la prima schimbare de preț sau primul produs epuizat — și atunci greșește cu convingere, ceea ce e mai rău decât să tacă.
Noi citim magazinul în momentul întrebării. Pentru magazinele pe WooCommerce există o interfață publică — Store API — care întoarce produse, prețuri și disponibilitate fără chei, fără cont, fără plugin instalat. Adresa e `/wp-json/wc/store/v1/products`, o cerem cu 100 de produse pe pagină, cu timp maxim de așteptare 20 de secunde, și aflăm din antetul răspunsului câte pagini sunt, în loc să ghicim. Prima pagină o luăm singură, restul în paralel.
Partea care separă o integrare corectă de una care pare corectă e traducerea prețului. Store API nu întoarce „129,90”; întoarce un șir de cifre în unități minore și, separat, câte zecimale are moneda. Cine împarte la 100 din obișnuință greșește tăcut pe orice monedă care nu are două zecimale. Și mai important: un preț zero nu înseamnă gratis, înseamnă nepublicat. La noi zero devine „preț la cerere — se confirmă de colegi”, iar agentul primește instrucțiunea explicită să nu inventeze. Se vede în răspunsul public al punctului de catalog, chiar acum.
Peste catalog vin celelalte piese, fiecare cu starea ei reală: coș și trimitere de comandă către sistemul de gestiune al restaurantului sau magazinului, plată prin interfața MAIB pentru comercianți sau prin Stripe, recuperarea coșurilor abandonate, urmărirea stării comenzii cu sincronizare la fiecare 15 minute. Unde nu avem o integrare funcțională — și sunt astfel de cazuri — scrie mai jos exact care.
Co obejmuje
Praca, po kolei
Catalog citit în timp real, fără chei și fără plugin
Pentru WooCommerce folosim Store API, interfața publică a magazinului: `/wp-json/wc/store/v1/products`, 100 de produse pe pagină, timp maxim de așteptare 20 de secunde, un identificator de client propriu în antet și acceptarea exclusivă a codului 200. Numărul de pagini îl citim din antetul `x-wp-totalpages`, iar totalul de produse din `x-wp-total` — nu paginăm până dăm de gol. Prima pagină se ia singură, restul în paralel, cu plafon de 30 de pagini. Nu se instalează nimic în magazin și nu ni se dau chei de comerciant.
Prețul tradus corect, iar zero tratat ca nepublicat
Store API întoarce prețul ca șir în unități minore, plus numărul de zecimale al monedei. Împărțim la zece la puterea acelui număr, nu la 100 fix — altfel orice monedă cu alt număr de zecimale iese greșită și nimeni nu observă. Zero devine `null`, iar în răspuns apare „preț la cerere — se confirmă de colegi”, împreună cu instrucțiunea explicită dată agentului să nu inventeze și să ceară confirmarea unui coleg. Prețul pleacă în două forme deodată: text gata de afișat pentru interfață și număr pentru logica din spate.
Trei unelte pe care agentul le poate chema
În platforma de asistenți catalogul e expus ca trei unelte încorporate — căutare după cuvinte, potrivire pe un aparat sau un caz de folosință, și aducerea unui produs după identificator. Agentul le vede sub numele `catalog_cauta`, `catalog_potrivire` și `catalog_produs`, fiecare cu parametrii lui declarați. Când platforma magazinului nu e cea așteptată sau lipsește adresa, unealta refuză explicit în loc să întoarcă o listă goală care ar fi interpretată drept „nu avem produsul”.
Cuvintele de legătură nu strică rezultatul
„Filtru de apă” căutat literal potrivește tot ce conține „de”. În punctul de catalog livrat și în căutarea din widgetul vocal tăiem lista de cuvinte goale — `si`, `sau`, `de`, `din`, `la`, `cu`, `pe`, `in`, `pentru` — și, dacă după tăiere nu mai rămâne nimic util, revenim la cuvintele mai lungi de două litere. Potrivirea parțială are prag: un produs intră în rezultate doar dacă atinge cel puțin jumătate din cuvintele rămase.
Când magazinul nu are interfață, citim pagina
Nu orice magazin are Store API. Pentru restul avem un extractor care deschide paginile de listare și le citește cardurile de produs, cu buget scris în cod: maximum 20 de pagini de listare, 200 de produse, 24 de pagini de detaliu, 50.000 de caractere de HTML pe pagină, 5 secunde pe cerere și un termen limită de 45 de secunde pentru toată operațiunea. Citește întâi datele structurate de tip produs din pagină, apoi cardurile, apoi metadatele de partajare — în ordinea asta, pentru că prima sursă e cea pe care magazinul a scris-o intenționat.
Prospețime cu limite scrise, nu cu speranță
Catalogul se ține în memorie 10 minute per magazin, iar cererile simultane pentru același magazin se contopesc într-una singură, ca zece clienți care întreabă în același moment să nu producă zece descărcări. Pe punctul public de catalog, răspunsul poartă și instrucțiune de cache pentru rețeaua de distribuție: 5 minute proaspăt, încă 10 minute servit vechi în timp ce se reîmprospătează în fundal. Numărul de rezultate întoarse e plafonat la 20, cu valoare implicită 6.
Comandă, coș și legătura cu sistemul de gestiune
Coșul, trimiterea comenzii și predarea ei către sistemul de gestiune al clientului sunt funcții separate, nu un formular. Există și recuperarea coșurilor abandonate, comanda prin conversație și urmărirea stării comenzii, cu două sarcini programate care rulează la fiecare 15 minute — una sincronizează rezultatul comenzilor, cealaltă completează stările din sistemul de gestiune pe o fereastră de două zile în urmă și o zi înainte.
Plăți: ce e funcțional și ce nu
Funcțional și în cod: interfața MAIB pentru comercianți — jeton, apoi cerere de plată, cu credențialele fiecărui magazin citite din baza de date și funcția activată explicit — și Stripe, cu sumă convertită în unități minore și încasarea salvată în evidență. Ce NU e funcțional, ca să nu existe surprize: Paynet, Netopia și mobilPay nu au implementare, iar codul refuză explicit când sunt cerute. Traseul Moldindconbank e un schelet care întoarce eroare fără credențiale. Le luăm în proiect ca lucrare, nu ca integrare existentă.
Agentul nu inventează când rețeaua cade
Dacă interogarea magazinului eșuează, unealta nu întoarce o listă goală — întoarce un mesaj care îi spune agentului să nu formuleze un răspuns despre catalog. Diferența e importantă: o listă goală se traduce în „nu avem”, iar „nu avem” spus greșit pierde o comandă la fel de sigur ca un preț greșit.
Jak to wygląda
Przebieg, krok po kroku.
01
Verificarea magazinului, înainte de orice promisiune
Interogăm interfața publică cu o singură cerere, cu timp maxim de așteptare 15 secunde, și citim câte produse are din antet. Din răspunsul ăsta știm dacă traseul viu e posibil, câte produse sunt și cât de completă e informația de preț. Dacă magazinul nu răspunde, o spunem înainte de ofertă, nu în timpul implementării.
02
Conectarea catalogului și prima trecere prin prețuri
Livrăm conexiunea, plus o trecere prin produsele cu preț zero sau lipsă — sunt aproape întotdeauna produse reale, nu erori, iar felul în care le tratează agentul e o decizie a magazinului, nu a noastră. Livrăm și textul exact cu care agentul refuză să dea un preț nepublicat.
03
Uneltele agentului și limitele lor
Montăm căutarea, potrivirea și aducerea unui produs, fiecare cu numărul maxim de rezultate stabilit împreună. Aici se scriu și sinonimele proprii magazinului — cum îi spune clientul unui produs față de cum îl numește catalogul. Fără pasul ăsta, căutarea e corectă tehnic și inutilă practic.
04
Comanda, plata și legătura cu gestiunea
Se construiesc în ordinea asta, iar fiecare piesă intră numai după ce se verifică accesul real la sistemul celuilalt capăt. Pentru plăți se pornește doar de la un furnizor pentru care avem implementare funcțională; restul se tratează ca lucrare nouă, cu riscul spus înainte, nu ca o bifă în ofertă.
05
Predarea, cu lista de lipsuri
Predăm adresele, configurările, limitele scrise în cod și lista a ce nu e acoperit. De exemplu: punctul public de catalog livrat nu are timp maxim de așteptare pe cererea către magazin — dacă magazinul răspunde foarte încet, cererea se prelungește. E o lipsă reală, o trecem în lista de predare și în planul de reparații, nu într-o notă internă.
Magazinul, agentul care răspunde, sistemul de gestiune și furnizorul de plată — patru sisteme separate, cu o singură sursă de adevăr pentru preț: magazinul, citit în momentul întrebării.
Datele
Czego dotykamy, gdzie to leży i jak długo zostaje
Pytania, które zadaje każdy, kto ma inspektora ochrony danych — postawione tutaj, zanim on je zada.
Datele de catalog
Denumire, descriere scurtă, preț curent și preț de listă, disponibilitate, imagine, categorie și adresa produsului — toate citite din interfața publică a magazinului, care le publică oricum către orice vizitator. Nu copiem baza de date a magazinului și nu cerem chei de comerciant. Rămân la client; noi le citim la cerere.
Unde se păstrează și cât
Catalogul se ține în memoria procesului 10 minute per magazin și dispare la repornire — nu există o copie persistentă a lui la noi. Pe punctul public de catalog, rețeaua de distribuție îl mai ține 5 minute proaspăt și 10 minute ca variantă veche în timp ce se reîmprospătează. Un export înghețat, atunci când e singura variantă tehnică, se marchează explicit ca instantaneu cu dată, nu ca sursă vie.
Datele conversației și ale comenzii
Ce întreabă clientul și ce comandă trec prin platforma de conversație și, unde e cazul, către sistemul de gestiune al magazinului. Cine are acces, cât se păstrează și ce se șterge se stabilesc pe proiect, cu registrul de prelucrări scris înainte de pornire, nu după primul incident.
Credențialele de plată
Credențialele de comerciant stau în baza de date a platformei, per magazin, și se citesc doar când funcția de plată e activată explicit pentru acel magazin. Nu ajung în pagina publică și nu trec prin conversație. Configurarea contului de comerciant se face de titularul contului, nu de noi.
Ce nu atingem
Nu preluăm date de card. Nu cerem acces de administrator la magazin pentru citirea catalogului — interfața folosită e publică. Când un proiect chiar cere acces privilegiat, se cere separat, cu scop scris, și nu se ține „pentru orice eventualitate”.
Przykład
Katalog 154 produktów, czytany w chwili pytania
Situația
Un distribuitor de cafea și apă din Chișinău, cu magazin pe WooCommerce și agenți care răspund clienților în text și la telefon. Catalogul se schimbă des; o listă copiată o dată devine greșită în câteva zile, iar un preț greșit spus la telefon nu se retrage.
Ce am construit
Am montat un punct de catalog separat, care interoghează interfața publică a magazinului: 100 de produse pe pagină, numărul de pagini citit din antet, prima pagină luată singură și restul în paralel, plafon 30 de pagini. Prețul se traduce din unități minore după numărul de zecimale declarat de magazin; zero devine „preț la cerere — se confirmă de colegi”, cu instrucțiune scrisă pentru agent să nu inventeze. Căutarea taie cuvintele de legătură și cere ca un produs să atingă cel puțin jumătate din cuvintele rămase înainte să apară în rezultate. Răspunsul se ține 10 minute în memorie și 5 minute în rețeaua de distribuție, cu încă 10 minute servite vechi în timp ce se reîmprospătează. Agenții vocali îl cheamă ca simplu punct web, nu ca integrare specială.
Ce a ieșit
Verificat pe 06.09.2026, în două cereri independente: punctul de catalog răspunde „154 rezultate” și listează primul produs cu preț și disponibilitate, iar al doilea cu „preț la cerere — se confirmă de colegi”; interogată direct, interfața magazinului întoarce `x-wp-total: 154`. Aceeași cifră din două surse care nu se cunosc între ele — asta e verificarea, nu declarația noastră.
Ce nu spune cazul
Punctul de catalog livrat nu are timp maxim de așteptare pe cererea către magazin: dacă magazinul răspunde foarte încet, cererea se prelungește în loc să cadă curat. E o lipsă reală, aflată la recitirea codului, și e în lista de reparații — nu în lista de funcții. Separat: filtrul de cuvinte goale descris mai sus e activ în punctul livrat și în căutarea din widgetul vocal; în varianta încorporată în platformă nu e încă portat, deci acolo o căutare cu multe cuvinte de legătură dă rezultate mai largi.
Întrebări
O co pytają nas ludzie, zanim zadzwonią
Ce înseamnă „catalog viu” și cum verific că nu e o vorbă?
Înseamnă că agentul citește magazinul în momentul întrebării. Se verifică în două cereri, fără noi: punctul nostru de catalog pentru un distribuitor răspunde „154 rezultate”, iar interfața publică a magazinului lui, interogată direct, întoarce în antet `x-wp-total: 154`. Aceeași cifră, două surse independente, la aceeași dată. Un catalog copiat o dată nu poate face asta — se desincronizează la prima schimbare.
Trebuie să vă dau chei sau acces la magazin?
Pentru citirea catalogului pe WooCommerce, nu. Store API este interfața publică a magazinului: aceleași date pe care le vede orice vizitator, servite în format citibil de program, fără cheie de comerciant și fără plugin instalat. Comentariul e scris chiar în codul nostru, ca să nu se piardă. Acces privilegiat cerem doar acolo unde funcția chiar îl cere — de exemplu la trimiterea comenzilor în sistemul de gestiune — și atunci cu scop scris.
Ce se întâmplă cu produsele fără preț?
Sunt tratate ca nepublicate, nu ca gratuite. În interfața magazinului un preț absent vine ca zero, iar o integrare naivă îl afișează „0 MDL”. La noi zero devine „preț la cerere — se confirmă de colegi”, iar agentul primește instrucțiunea explicită să nu inventeze o cifră și să ceară confirmarea unui om. Se vede în răspunsul public: al doilea produs din listă exact așa apare.
Cât de proaspăt e prețul, concret?
Cel mult 10 minute vechime la nivelul platformei, per magazin, iar cererile simultane pentru același magazin se contopesc într-o singură descărcare. Pe punctul public de catalog, rețeaua de distribuție servește 5 minute varianta proaspătă și încă 10 minute varianta veche, în timp ce o reîmprospătează în fundal. Valorile sunt configurabile pe proiect; sunt scrise ca variabile, nu ascunse.
Magazinul meu nu e pe WooCommerce. Ce faceți?
Depinde de ce expune. Dacă are o interfață proprie, o citim ca pe oricare alta. Dacă nu are nimic, avem un extractor care deschide paginile de listare și citește cardurile de produs, cu buget scris în cod: 20 de pagini, 200 de produse, 5 secunde pe cerere, 45 de secunde termen limită. Citește întâi datele structurate din pagină, apoi cardurile, apoi metadatele de partajare. E o soluție de rezervă onestă, nu una echivalentă: un magazin care își schimbă tema poate rupe extractorul, iar o interfață nu.
Ce plăți puteți integra chiar acum?
Funcțional și în cod: interfața MAIB pentru comercianți — obținere de jeton, apoi cerere de plată, cu credențialele fiecărui magazin citite din baza de date și funcția activată explicit — și Stripe, cu suma convertită în unități minore și încasarea salvată în evidență. Ce nu e funcțional, spus înainte de contract: Paynet, Netopia și mobilPay nu au implementare, iar codul refuză explicit când sunt cerute; traseul Moldindconbank e un schelet care întoarce eroare fără credențiale. Oricare dintre ele se poate construi, dar intră ca lucrare nouă, cu riscul ei.
Agentul poate să inventeze un produs pe care nu îl aveți?
Poate, dacă nu îl împiedici — și de asta ne ocupăm noi. Trei bariere: prețul nepublicat vine cu instrucțiune scrisă de a nu inventa; platforma nepotrivită sau adresa lipsă fac unealta să refuze explicit, nu să întoarcă o listă goală; iar căderea de rețea întoarce un mesaj care îi spune agentului să nu formuleze un răspuns despre catalog. Diferența dintre „listă goală” și „nu am putut citi” e diferența dintre o comandă pierdută și una amânată cu o frază.
De ce contează cine împarte la 100?
Pentru că interfața nu trimite „129,90”. Trimite un șir de cifre în unități minore și, separat, câte zecimale are moneda. Împărțirea la 100 e corectă pentru monedele cu două zecimale și tăcut greșită pentru celelalte — nimeni nu primește eroare, doar cifre proaste. Noi împărțim la zece la puterea numărului declarat de magazin. E o linie de cod, și e exact genul de linie pe care se vede dacă cineva a citit documentația sau a ghicit.
Ce nu vă asumați?
Nu preluăm date de card și nu configurăm contul de comerciant în locul titularului. Nu garantăm că un extractor de pagini rezistă la o schimbare de temă a magazinului — de asta preferăm interfața când există. Nu promitem creșteri de vânzări; ce putem arăta e că cifra spusă de agent coincide cu cifra din magazin, la aceeași dată. Și nu prezentăm ca integrare ceva ce în cod e un schelet: lista de mai sus spune care sunt.
Pe ce se sprijină afirmațiile de mai sus (18 surse)
16 dintre ele sunt cod și fișiere din depozitele noastre. Nu le publicăm numele și nici linia: împreună, pe o singură pagină, ar descrie prea exact cum sunt construite sisteme care nu sunt doar ale noastre. Le parcurgem cu tine, în depozit, la cerere — verificarea rămâne posibilă, doar că se face într-o discuție.