Mokėjimų branduolys
Nuo framework nepriklausantis TS mokėjimų branduolys LT bankams — su apsaugotais webhook ir sumų srautais.
Mokėjimų branduolys
Iššūkis
Mokėjimų logika vis būdavo perrašoma kiekvienam produktui ir susipindavo su to produkto karkasu bei duomenų baze — kaip tik ten ir slepiasi mokėjimų klaidos.
Ką darėme
Grynas TypeScript branduolys su mokėjimų srities taisyklėmis be jokių framework ar DB importų; kiekvienas Lietuvos bankas ar PSP yra plonas provaiderio adapteris, o branduolys sustiprintas ten, kur pinigai realiai lūžta: webhook parašo ir šviežumo tikrinimai, apsaugos nuo sumos perpildymo ir per daug skaitmenų, patikrinti nukreipimo taikiniai ir rankinės peržiūros srautai, kai callback nuoroda ar suma nesutampa.
Rezultatas
Naujas produktas prijungia mokėjimus rašydamas adapterius aplink vieną ištestuotą, saugumo patikromis apsaugotą branduolį, o ne iš naujo įgyvendindamas bankų srautus ir klaidų būsenas.
Dev-story straipsnis
Kaip buvo kuriamas projektas: Mokėjimų branduolys
Naršyklės peradresavimas iš banko reiškia tik tai, kad vartotojas grįžo į svetainę — jis nereiškia, kad pinigai pajudėjo, tačiau daugybė integracijų pažymi užsakymą apmokėtu būtent pagal šį signalą. Šis branduolys sukurtas remiantis priešinga prielaida: peradresavimas nieko neįrodo, o vienintelė patikima būsena ateina iš pasirašyto atgalinio iškvietimo arba serverinio būsenos patikrinimo. Visą laiką įtampą kėlė tai, kad kiekvienas bankų nuorodų protokolas, kortelių agregatorius ir piniginės API pasirašo, koduoja ir praneša sumas skirtingai, todėl sutvirtinimas turėjo būti bendra logika, o ne kopijavimas kiekvienam teikėjui atskirai.
Skyriai
05
Moduliai
05
Stackas
TypeScript + Bank integrations
Kodėl projektas atsirado
Mokėjimų logika vis būdavo perrašoma kiekvienam produktui ir susipindavo su to produkto karkasu bei duomenų baze — kaip tik ten ir slepiasi mokėjimų klaidos.
Naršyklės peradresavimas iš banko reiškia tik tai, kad vartotojas grįžo į svetainę — jis nereiškia, kad pinigai pajudėjo, tačiau daugybė integracijų pažymi užsakymą apmokėtu būtent pagal šį signalą. Šis branduolys sukurtas remiantis priešinga prielaida: peradresavimas nieko neįrodo, o vienintelė patikima būsena ateina iš pasirašyto atgalinio iškvietimo arba serverinio būsenos patikrinimo. Visą laiką įtampą kėlė tai, kad kiekvienas bankų nuorodų protokolas, kortelių agregatorius ir piniginės API pasirašo, koduoja ir praneša sumas skirtingai, todėl sutvirtinimas turėjo būti bendra logika, o ne kopijavimas kiekvienam teikėjui atskirai.
Ką sukūrėme
Grynas TypeScript branduolys su mokėjimų srities taisyklėmis be jokių framework ar DB importų; kiekvienas Lietuvos bankas ar PSP yra plonas provaiderio adapteris, o branduolys sustiprintas ten, kur pinigai realiai lūžta: webhook parašo ir šviežumo tikrinimai, apsaugos nuo sumos perpildymo ir per daug skaitmenų, patikrinti nukreipimo taikiniai ir rankinės peržiūros srautai, kai callback nuoroda ar suma nesutampa.
Tai TypeScript paketas, apimantis tik mokėjimų srities taisykles — užklausų pasirašymą, atgalinių iškvietimų validavimą, būsenų normalizavimą, sumos ir valiutos patikras, pasikartojančių iškvietimų tvarkymą ir audito požiūriu saugius normalizuotus įvykius. Branduolys neimportuoja jokio karkaso, HTTP vykdymo aplinkos ar duomenų bazės kliento: jis priima paprastą PaymentHttpRequest struktūrą, todėl tas pats teikėjų kodas veikia iš mūsų reaktyvaus serverio, Node darbininkų ar testų. Įgyvendinti keli realūs Lietuvos bankų ir PSP teikėjai; bankai be oficialios komercinės medžiagos tiekiami kaip griežti karkasai, kurie meta klaidą, o ne spėja.
Pagrindiniai moduliai ir vartotojo kelias
Pasirašytų atgalinių iškvietimų ir webhook'ų patikra pagal kiekvieną protokolą (RSA-SHA512/SHA1/SHA256, atskirtas JWS, hex HMAC-SHA256) naudojant tikslius neapdorotus užklausos baitus, o grįžimo peradresavimai modeliuojami kaip provesPayment:false, kad suklastotas sėkmės URL niekada negalėtų užbaigti užsakymo
Apsauga nuo pakartojimo per pasirenkamus šviežumo langus: nedatuoti iškvietimai arba tie, kurių laiko žyma ar JWS iat peržengia toleranciją, atmetami kaip nepatikimi; pagal nutylėjimą išjungta, kad teisėtai vėluojantys iškvietimai vis tiek pasiektų
Pinigų apsaugos kaip bendri pagalbininkai: decimalAmountToCents, grąžinantis undefined virš Number.MAX_SAFE_INTEGER, ir sumų su daugiau nei dviem dešimtainėmis atmetimas, o ne tylus 12.999 apvalinimas iki 1300 centų
Nukreipimas į rankinį peržiūrą esant neatitikimui: kai webhook'o nuoroda, suma ar valiuta nesutampa su serverio gauto autoritetingo užsakymo duomenimis, įvykis siunčiamas į requires_manual_review kaip klastojimo signalas, o ne aklai pasitikima kuria nors puse
Nuo karkaso nepriklausantis branduolys plius ploni adapteriai, su griežtais teikėjų karkasais, kurie meta aiškias „reikia įgyvendinimo“ klaidas, kol neatsiranda tikri endpoint'ai, laukai, parašai ir sertifikatai
Architektūra ir technologiniai sprendimai
Sukurta su TypeScript, Bank integrations, Crypto.
Grynas TypeScript su prijungiamais Web Crypto ir Node crypto adapteriais, jokio karkaso importų branduolio įėjimo taške ir CI vartai, laikantys 100% sakinių, šakų, funkcijų ir eilučių padengimą vykdymo kode.
Rezultatas ir pamokos
Naujas produktas prijungia mokėjimus rašydamas adapterius aplink vieną ištestuotą, saugumo patikromis apsaugotą branduolį, o ne iš naujo įgyvendindamas bankų srautus ir klaidų būsenas.
Tas pats teikėjų kodas veikia nepakeistas skirtinguose serveriuose ir testuose, o kiekvienas pinigus užbaigiantis kelias lūžta saugiai — perpildyta suma, pakartotas iškvietimas ar nesutampanti nuoroda parodo jokio mokėjimo arba peržiūros žymą, o ne neteisingą.
Susiję straipsniai
Toliau skaityti
Susijusios projektų istorijos
Šie projektai turi artimų technologinių arba produkto sprendimų, todėl padeda matyti, kaip tas pats principas veikia kitame kontekste.
Dev-storyCMS
Dinaminis CMS ant webedge-db — turinio tipai, medija, rolės ir vieša skaitymo API, maitinanti mūsų svetaines ir straipsnius.
Dev-storyWebEdge viešoji svetainė
Mūsų lt/en/ru svetainė su Astro, turinys iš WebEdge CMS.
Dev-storyPi vietinio modelio darbo eiga
Pi plėtinys: vietinis modelis dirba, GPT-5.6 tik tikrina planą ir peržiūrą.
Turite panašią idėją?
Aptarti projektą