V rokoch 2017 – 2022 sme cez partnerskú spoločnosť pracovali vo vývojovom tíme win2day, online kasína a lotérií Rakúskej lotérie, a jednou z našich úloh bola implementácia hier tretích strán cez webové služby. Každý výrobca hry mal iné rozhranie, iný spôsob autentifikácie a inú predstavu o tom, kto nesie zodpovednosť za výsledok hry a pohyb na účte hráča. Prvé integrácie trvali mesiace, posledné už len týždne. Rozdiel urobil jeden interný kontrakt. Článok je pre architektov a vedúcich vývoja, ktorí napájajú externú službu na systém, kde sa hýbu peniaze.
Najprv model peňaženky: kto drží zostatok
V modeli spoločnej peňaženky (seamless alebo single wallet) zostatok hráča ostáva v systéme prevádzkovateľa a server hry pri každej stávke a výhre volá jeho rozhranie: odpíš stávku, pripíš výhru, stornuj. V modeli prevodu (transfer wallet) sa pred hrou presunie časť prostriedkov na účet u dodávateľa hry a po skončení späť. Jednotlivé stávky sa systému prevádzkovateľa nedotýkajú.
Pri spoločnej peňaženke sa rozhranie prevádzkovateľa volá v každom kole. Od jeho dostupnosti a odozvy závisí, či hra beží, a počet volaní rastie s počtom stávok, nie relácií. Výhodou je jeden zostatok, každá stávka je hneď viditeľná a dajú sa na ňu uplatniť limity. Pri prevode je volaní málo, ale časť peňazí hráča leží mimo vlastnej účtovnej evidencie, pri výpadku dodávateľa môže ostať zablokovaná a o jednotlivých stávkach sa prevádzkovateľ dozvie až z jeho hlásení. Hráč má účet u prevádzkovateľa, takže za správnosť zostatku a výplatu sa mu zodpovedá prevádzkovateľ. Kontrakt preto musí jednoznačne povedať, ktorý model sa použije a čo sa stane s prostriedkami pri výpadku každej zo strán.
Jedno interné rozhranie, adaptér pre každého dodávateľa
Platforma pozná jedno vlastné rozhranie pre hru: spustiť, vsadiť, vyplatiť, zrušiť, zistiť stav. Každý výrobca má adaptér, ktorý jeho rozhranie prekladá do nášho. V terminológii doménovo riadeného návrhu (Eric Evans) ide o protikorupčnú vrstvu (anti-corruption layer). Cudzí model, názvy a chybové kódy ostanú za hranicou adaptéra a jadro platformy sa pri novom výrobcovi nemení.
Do adaptéra patrí preklad formátov, mapovanie chybových kódov a overenie volaní. Pravidlá zaúčtovania, limity a stavový automat transakcie doň nepatria, tie sú v jadre raz pre všetkých. Ak sa biznis logika dostane do adaptérov, po niekoľkých dodávateľoch máte niekoľko mierne odlišných účtovných pravidiel. Vrstva má aj cenu, ktorú pri tomto vzore uvádza katalóg Azure Architecture Center: ďalší komponent na prevádzku a ďalší krok, ktorý predĺži odozvu.
Overenie volaní: podpis, relácia hry, opakovanie
Autentifikácia sa medzi dodávateľmi líši viac než čokoľvek iné: od HTTP Basic cez TLS so zoznamom povolených adries až po podpis tela správy. U nás bolo každé volanie podpísané na oboch stranách. Pri zdieľanom tajomstve je štandardom HMAC podľa RFC 2104. Vlastné konštrukcie typu hash(tajomstvo + správa) sú pri hashoch ako SHA-1 či SHA-256 náchylné na útok predĺžením správy. Podpis sa porovnáva funkciou s konštantným časom a pokrýva celé telo vrátane časovej známky alebo jednorazovej hodnoty, inak sa zachytená správa dá poslať znova. HMAC však dokazuje len to, že správu vytvoril držiteľ zdieľaného kľúča, teda ktorákoľvek z dvoch strán. Ak treba preukázať, ktorá strana ju odoslala, potrebujete asymetrický podpis. Asymetrickému podpisu platobných požiadaviek sa venujeme v článku o bezpečnosti online platieb.
Druhou vrstvou je token relácie hry. Vydá ho platforma pri spustení hry, viaže sa na hráča, hru a menu a má obmedzenú platnosť. Hráča platforma určuje podľa tokenu, nie podľa identifikátora v tele správy. Výhra alebo storno k už prijatej stávke však môže prísť aj po vypršaní relácie, preto je pravidlo „neplatný token, odmietni“ rozumné pre nové stávky, nie automaticky pre všetky volania.
Idempotencia, timeouty a storno
Samotné HTTP idempotenciu peňažných volaní nerieši. Podľa RFC 9110 sú idempotentné metódy PUT, DELETE a bezpečné metódy, POST medzi ne nepatrí. Dodávatelia hier pritom pri timeoute alebo nečitateľnej odpovedi bežne opakujú, často viackrát s narastajúcim odstupom. Každé peňažné volanie preto nesie jedinečný identifikátor transakcie, ktorý platforma eviduje s obmedzením jedinečnosti priamo v databáze. Opakované doručenie s rovnakým identifikátorom a obsahom vráti pôvodnú odpoveď bez nového zaúčtovania. Rovnaký identifikátor s iným obsahom je chyba, nie opakovanie.
Najzradnejší je timeout. Server hry nevie, či platforma stávku zaúčtovala, a pošle storno, ktoré môže doraziť skôr než samotná stávka alebo k transakcii, ktorú platforma nikdy nevidela. Osvedčilo sa evidovať aj storno neznámej transakcie, aby neskôr doručená stávka s tým istým identifikátorom už neprešla. Kontrakt adaptéra musí pokryť, v čom sa dodávatelia líšia: odpoveď na storno neznámej transakcie, či storno vracia sumu pôvodnej transakcie alebo sumu z požiadavky, či je storno uzavretej transakcie povolené a čo nastane po vyčerpaní opakovaní.
- Každá transakcia má stav: prijatá, overená, zaúčtovaná, zrušená. Prechody sú definované a iné neexistujú. Neplatný prechod sa odmietne a zaznamená, potichu sa „neopravuje“.
- Zaúčtovaná transakcia sa nemaže ani neprepisuje. Storno po zaúčtovaní je nový protismerný zápis s odkazom na pôvodnú transakciu.
- S výpadkom spojenia uprostred hry treba počítať ako s bežným stavom. Platforma vie dohrať alebo vrátiť každú rozohranú transakciu a pravidelne hľadá tie, ktoré ostali v prechodnom stave neobvykle dlho.
- Každý prechod nesie čas, pôvodcu (hráč, server hry, operátor, zladenie) a identifikátor požiadavky, aby sa priebeh kola dal zrekonštruovať aj po rokoch.
Výsledok hry, sumy a meny
Výsledok hry vzniká na serveri dodávateľa a platforma ho neprepočíta, generátor náhodných čísel a matematika hry sú jeho. Bez kontroly ho však nepreberá. Pred zaúčtovaním overí, čo overiť vie: že výhra patrí k existujúcej a nestornovanej stávke toho istého hráča a kola, že mena sedí s reláciou, že suma neprekračuje maximálnu výhru, ktorú pre danú hru a stávku pripúšťajú jej pravidlá, a že kolo ešte nebolo uzavreté. Výsledok mimo týchto hraníc sa automaticky nezaúčtuje a zastaví sa na posúdenie.
Sumy sa neprenášajú ako čísla s pohyblivou desatinnou čiarkou, pretože hodnotu 0,1 nemožno v dvojkovej sústave vyjadriť presne. Bezpečné sú celé čísla v najmenšej jednotke meny alebo desatinný typ s pevnou presnosťou a v každom volaní výslovne uvedená mena podľa ISO 4217. Desatinné miesta nie sú pri všetkých menách dve: japonský jen ich má podľa ISO 4217 nula, kuvajtský či bahrajnský dinár tri. Ak dodávateľ počíta výhru ako násobok stávky, zaokrúhľovanie (kto, ktorým smerom, na koľko miest) musí byť dohodnuté a pokryté testom, inak sa ukáže pri zladení ako séria drobných nezrovnalostí.
Denné zladenie a postup pri nezrovnalosti
Zladenie (reconciliation) s dodávateľom beží denne nad uzavretým obdobím a porovnáva jednotlivé transakcie, nielen súčty, pretože súčet môže sedieť aj vtedy, keď sa dve chyby navzájom vyrušia. Nezrovnalosti sú štyroch typov: transakcia chýba u nás, chýba u dodávateľa, líši sa suma, líši sa stav. Dohodnúť treba aj formát výpisu, časové pásmo uzávierky a to, do ktorého dňa patrí kolo, ktoré prešlo cez polnoc.
Postup pri nezrovnalosti je dôležitejší než samotné porovnanie. Nezrovnalosť zastaví dotknuté výplaty, kým sa nevysvetlí. Nerieši sa úpravou zostatku v databáze. Príčina sa hľadá v stope transakcie na oboch stranách a oprava ide ako nový auditovaný zápis, ideálne so schválením druhou osobou. Opakujúci sa typ nezrovnalosti je chyba v kontrakte alebo adaptéri a patrí do testovacích vektorov.
Testovacie vektory a certifikácia
Bez testov je kontrakt len dokument, preto k nemu patria testovacie vektory: pre podpis známe vstupy a očakávané výsledky bajt po bajte, pre peňažné toky scenáre ako opakovaná stávka, timeout a storno, storno pred stávkou, výhra bez stávky, výhra po storne či mena s iným počtom desatinných miest. Vďaka kontraktu, testovacím vektorom a referenčnej implementácii adaptéra bolo nasadenie novej hry opakovateľným postupom s kontrolným zoznamom, a nie samostatným projektom.
Certifikácia je samostatná vrstva. V regulovaných trhoch je bežné, že hry a generátory náhodných čísel pred uvedením otestuje nezávislá skúšobňa podľa technických štandardov regulátora alebo rozšírených štandardov, napríklad GLI-19 pre interaktívne herné systémy. Britská Gambling Commission vo svojej testovacej stratégii vyžaduje test schválenou skúšobňou pred uvedením novej hry, opätovný test pri zmenách ovplyvňujúcich férovosť a otestovanie aj pri sprístupnení existujúcej hry cez nový kanál. Pre integráciu z toho plynie, že platforma má evidovať, ktorú verziu hry hráč hral, a zmena na našej strane, ktorá mení to, čo hráč vidí, nemusí byť „len technická“. Čo konkrétne platí, určuje regulátor daného trhu.
Kontrolný zoznam pre nového dodávateľa hry
- Model peňaženky: spoločná peňaženka alebo prevod a čo sa stane s prostriedkami pri výpadku každej strany.
- Podpis a relácia: algoritmus, čo presne sa podpisuje a v akom kódovaní, ochrana proti opakovaniu, výmena kľúčov bez výpadku, platnosť tokenu relácie a správanie výplat po jeho vypršaní.
- Identifikátory: jedinečný identifikátor transakcie a kola, rozsah ich jedinečnosti a odpoveď na duplicitu.
- Timeouty a opakovania: ako dlho dodávateľ čaká, koľkokrát a s akým odstupom opakuje, kedy pošle storno a čo nasleduje po vyčerpaní opakovaní.
- Storno: správanie pri neznámej, už stornovanej a už uzavretej transakcii a ktorá suma platí.
- Sumy a meny: formát súm, podporované meny, presnosť a pravidlá zaokrúhľovania.
- Chybové kódy: úplný zoznam, rozlíšenie dočasných a trvalých chýb a mapovanie na interné stavy.
- Zladenie: formát a frekvencia výpisu, časové pásmo uzávierky, kontakt a lehoty pri nezrovnalosti.
- Certifikácia: certifikáty hier a ich verzií pre cieľový trh a spôsob oznamovania zmien, ktoré vyžadujú nové testovanie.
- Testovanie a prevádzka: testovacie prostredie s možnosťou vyvolať chybové scenáre, kontakty pre incidenty, plánované odstávky a možnosť vypnúť jednu hru bez vplyvu na ostatné.
Kedy sa to oplatí a čo odporúčame
Vlastná vrstva adaptérov s kontraktom sa oplatí, keď dodávateľov pribúda a integrácie sa opakujú. Pri jednom či dvoch dodávateľoch, alebo ak sa platforma pripája cez agregátor, ktorý rozhrania zjednocuje sám, môže byť zbytočná. Kontraktom je potom rozhranie agregátora a tie isté otázky o peňaženke, storne a zladení treba položiť jemu. Odporúčame najprv kontrakt a testovacie vektory, až potom adaptér. V regulovanom prostredí, kde chyba v pohybe peňazí môže znamenať reklamácie, audit a vysvetľovanie regulátorovi, je rutina to najcennejšie, čo sa dá vybudovať.