Visi projektai

Mokėjimų branduolys

Nuo framework nepriklausantis TS mokėjimų branduolys LT bankams — su apsaugotais webhook ir sumų srautais.

TypeScriptBank integrationsCrypto
01

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.

02

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.

03

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

01

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.

02

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.

03

Pagrindiniai moduliai ir vartotojo kelias

M01

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

M02

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ų

M03

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ų

M04

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

M05

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

04

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.

05

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ą.

Toliau skaityti

Šie projektai turi artimų technologinių arba produkto sprendimų, todėl padeda matyti, kaip tas pats principas veikia kitame kontekste.

Turite panašią idėją?

Aptarti projektą