diff --git a/docs/FRONTEND_REFACTORING_PLAN.md b/docs/FRONTEND_REFACTORING_PLAN.md new file mode 100644 index 0000000..6e2cf90 --- /dev/null +++ b/docs/FRONTEND_REFACTORING_PLAN.md @@ -0,0 +1,476 @@ +# Plan refaktoryzacji frontendu shopPRO + +## Kontekst + +Panel administratora (33 moduły) został w pełni zmigrowany na architekturę Domain + DI + Controllers (ver. 0.237–0.277). Teraz kolej na frontend: klasy `front/`, `shop/`, `cms/`, klasy utility z `autoload/` oraz szablony `templates/`. + +**Cel:** przenieść logikę biznesową z warstwy frontendowej do warstwy domenowej (`Domain/`), zachowując kompatybilność wsteczną przez fasady. Zastosować te same wzorce co w adminie (DI, repozytoria/serwisy, testy PHPUnit). + +--- + +## Inwentaryzacja — co istnieje + +### front/controls/ (8 klas — handlery requestów) +| Klasa | Status | Logika biznesowa | +|-------|--------|-----------------| +| Site | Router główny | route(), check_url_params(), title() | +| ShopBasket | MIXED | Operacje koszyka, add/remove/quantity, checkout | +| ShopClient | Fasada | Deleguje do factory | +| ShopOrder | KRYTYCZNY | Webhooki płatności (tPay, Przelewy24, Hotpay) — bezpośrednie operacje DB | +| ShopProduct | Fasada | lazy_loading, warehouse_message, draw_product_attributes | +| ShopProducer | Fasada | list(), products() | +| ShopCoupon | Fasada | use_coupon(), delete_coupon() | +| Newsletter | Fasada | signin(), confirm(), unsubscribe() | + +### front/factory/ (20 klas — pobieranie danych + logika) +| Klasa | Status | Priorytet migracji | +|-------|--------|--------------------| +| ShopProduct | ORYGINALNA LOGIKA (~370 linii) | KRYTYCZNY — product_details(), promoted/top/new products | +| ShopOrder | ORYGINALNA LOGIKA (~180 linii) | KRYTYCZNY — basket_save() tworzy zamówienie | +| ShopClient | ORYGINALNA LOGIKA | KRYTYCZNY — login (BUG: hardcoded bypass 'Legia1916'), signup, recover | +| ShopCategory | ORYGINALNA LOGIKA | WYSOKI — złożone SQL z language fallback | +| Articles | ORYGINALNA LOGIKA | WYSOKI — złożone SQL z language fallback | +| ShopPromotion | ORYGINALNA LOGIKA | WYSOKI — silnik promocji (5 typów) | +| ShopBasket | Fasada | ŚREDNI — summary_price, count | +| ShopTransport | CZĘŚCIOWO zmigrowana | ŚREDNI — transport_methods z filtrowaniem | +| ShopPaymentMethod | ZMIGROWANA (Domain) | — | +| ShopStatuses | ZMIGROWANA (Domain) | — | +| Scontainers | ZMIGROWANA (Domain) | — | +| Newsletter | CZĘŚCIOWO zmigrowana | ŚREDNI | +| Settings | Fasada (BUG: get_single_settings_value ignoruje $param) | NISKI | +| Languages | Fasada | NISKI | +| Layouts | Fasada | NISKI | +| Banners | Fasada | NISKI | +| Menu | Fasada | NISKI | +| Pages | Fasada | NISKI | +| ShopAttribute | Fasada | NISKI | +| ShopCoupon | Model danych | NISKI | + +### front/view/ (12 klas — renderowanie) +| Klasa | Status | +|-------|--------| +| Site | KRYTYCZNY — show() ~600 linii, pattern substitution engine | +| ShopCategory | VIEW z logiką routingu (infinite scroll vs pagination) | +| Articles, Banners, Languages, Menu, Newsletter, Scontainers | Czyste VIEW | +| ShopClient, ShopOrder, ShopPaymentMethod | Czyste VIEW | +| ShopTransport | PUSTA klasa (placeholder) | + +### shop/ (14 klas — encje biznesowe) +| Klasa | Linii | Status | Priorytet | +|-------|-------|--------|-----------| +| Product | ~950 | KRYTYCZNY — pricing, atrybuty, search, cache, permutacje | KRYTYCZNY | +| Order | ~500+ | KRYTYCZNY — statusy, Apilo sync, emaile, webhooki | KRYTYCZNY | +| Promotion | ~200 | WYSOKI — matching aktywnych promocji + delegacja do factory | WYSOKI | +| Basket | ~80 | ŚREDNI — walidacja stanów magazynowych | ŚREDNI | +| Category | ~60 | NISKI — proste zapytania, pusty konstruktor | NISKI | +| Search | ~80 | NISKI — wrapper na szablony | NISKI | +| Coupon | ~60 | NISKI — niekompletne metody | NISKI | +| Transport | ~30 | NISKI — transport_list() | NISKI | +| PaymentMethod | — | ZMIGROWANA (fasada do Domain) | — | +| Producer | — | ZMIGROWANA (fasada do Domain) | — | +| ProductSet | — | ZMIGROWANA (fasada do Domain) | — | +| ProductAttribute | ~100 | OK — dobry caching | — | +| ProductCustomField | ~50 | OK — Redis caching | — | +| Shop | ~30 | OK — utility do cen | — | + +### autoload/ root (klasy utility) +| Klasa | Linii | Status | +|-------|-------|--------| +| S | ~1130 | htacces() ~500 linii — generowanie .htaccess; reszta to utility | +| Tpl | ~90 | OK — silnik szablonów, bez zmian | +| CacheHandler | ~50 | OK — Redis wrapper | +| RedisConnection | ~40 | OK — singleton | +| Email | ~100 | OK — PHPMailer wrapper (drobne poprawki) | +| Log | ~20 | OK — audit logging | +| DbModel | ~60 | OK — base ORM | +| Cache | ~50 | LEGACY — file-based cache, rozważyć usunięcie | +| Html | ~80 | OK — form helpers | +| Image | ~100 | OK — GD wrapper | +| Mobile_Detect | — | Third-party, bez zmian | + +### cms/ (1 klasa) +| Klasa | Status | +|-------|--------| +| Layout | BUG w __get() — referuje $this->data które nie istnieje | + +### templates/ (75 plików w 15 modułach) +articles(8), banner(2), controls(1), menu(4), newsletter(2), scontainers(1), shop-basket(9), shop-category(6), shop-client(8), shop-coupon(1), shop-order(3), shop-producer(3), shop-product(12), shop-search(3), site(11) + +### Entry points +- `index.php` — główny frontend (autoload, sesja, DB, routing, DOM post-processing) +- `ajax.php` — AJAX handler (koszyk, transport, kontakt) +- `api.php` — REST API (Ekomi CSV export) +- `download.php` — pobieranie plików +- `cron-turstmate.php` — TrustMate integracja + +--- + +## Znane bugi do naprawy podczas refaktoringu + +1. **KRYTYCZNY** `front\factory\ShopClient::login()` — hardcoded password bypass `'Legia1916'` +2. `front\factory\Settings::get_single_settings_value()` — ignoruje `$param`, zawsze zwraca `firm_name` +3. `front\factory\Newsletter::newsletter_unsubscribe()` — błędna składnia SQL w delete +4. `cms\Layout::__get()` — referuje nieistniejące `$this->data` +5. `shop\Search` — typo w use: `shop\Produt` (brak 'c') + +--- + +## Kolejność migracji (graf zależności) + +``` +Settings, Languages (liście — brak zależności) + ↓ +Banners, Menu, Pages, Articles, Layouts (zależą od Languages) + ↓ +Category (zależy od Languages) + ↓ +Promotion (zależy od Category — rozbicie circular dep) + ↓ +Product Frontend (zależy od Category, Promotion, Languages) + ↓ +Client/Auth (standalone + security fix) + ↓ +Transport, Payment, Coupon (frontend serwisy) + ↓ +Basket (zależy od Product, Promotion, Transport, Coupon) + ↓ +Order Creation (zależy od Basket, Product, Transport, Payment) + ↓ +Payment Webhooks (zależy od Order) + ↓ +shop\Order instance + Apilo (zależy od Order Operations) + ↓ +shop\Product instance + cache (zależy od ProductFrontendService) + ↓ +Frontend App + Controllers (nowa warstwa DI) + ↓ +Site Layout Engine (zależy od wszystkiego) + ↓ +Entry Point Unification (index.php, ajax.php) + ↓ +Legacy Cleanup +``` + +--- + +## Plan wersjonowany + +### ver. 0.278 — Settings + Languages Frontend Services + +**Cel:** Stworzyć serwisy domenowe dla Settings i Languages, naprawić buga Settings. + +**NOWE:** +- `Domain/Settings/SettingsFrontendService.php` — `allSettings()`, `getSingleValue($param)` (FIX: używa poprawnie $param) +- `Domain/Languages/LanguagesFrontendService.php` — `defaultLanguage()`, `activeLanguages()`, `translations($lang)` +- Testy: `SettingsFrontendServiceTest`, `LanguagesFrontendServiceTest` + +**ZMIANA:** +- `front/factory/Settings` → fasada delegująca do `SettingsFrontendService` +- `front/factory/Languages` → fasada delegująca do `LanguagesFrontendService` + +**BUG FIX:** `get_single_settings_value()` — zmiana `['param' => 'firm_name']` na `['param' => $param]` + +--- + +### ver. 0.279 — Category Frontend Service + +**Cel:** Migracja `front\factory\ShopCategory` do Domain. + +**NOWE:** +- `Domain/Category/CategoryFrontendService.php` — `getCategorySort()`, `categoryName()`, `categoryUrl()`, `blogCategoryProducts()`, `categoryProducts()`, `productsId()` (złożone SQL z sortowaniem/language fallback/paginacją), `categoryDetails()`, `categoriesDetails()` (rekurencyjne), `categoryProductsCount()` +- Testy: `CategoryFrontendServiceTest` + +**ZMIANA:** +- `front/factory/ShopCategory` → fasada +- `front/factory/ShopProduct::product_categories()` → deleguje do `CategoryFrontendService` + +--- + +### ver. 0.280 — Banners, Menu, Pages, Articles, Layouts Frontend Services + +**Cel:** Migracja pozostałych fabryk "liściowych". + +**NOWE:** +- `Domain/Banner/BannerFrontendService.php` — `mainBanner()`, `banners()` (filtrowanie po datach) +- `Domain/Menu/MenuFrontendService.php` — `menuDetails()`, `menuPages()` (rekurencja) +- `Domain/Pages/PagesFrontendService.php` — `pageDetails()`, `mainPageId()`, `langUrl()`, `pageSort()` +- `Domain/Article/ArticleFrontendService.php` — `articleDetails()`, `news()`, `pageArticles()`, `pageArticlesCount()`, `generateTableOfContents()`, `generateHeadersIds()` +- `Domain/Layouts/LayoutsFrontendService.php` — `activeLayout()`, `articleLayout()`, `productLayout()`, `categoryLayout()`, `defaultLayout()`, `categoryDefaultLayout()` +- Testy: 5 plików testowych + +**ZMIANA:** +- `front/factory/Banners`, `Menu`, `Pages`, `Articles`, `Layouts` → fasady + +**BUG FIX:** `cms\Layout::__get()` — poprawka referencji do `$this->data` + +--- + +### ver. 0.281 — Promotion Engine (rozbicie circular dependency) + +**Cel:** Przeniesienie silnika promocji do Domain. Rozbicie cyklicznej zależności `shop\Promotion ↔ front\factory\ShopPromotion`. + +**Obecna zależność cykliczna:** +``` +shop\Promotion::find_promotion() → front\factory\ShopPromotion::promotion_type_XX() +front\factory\ShopPromotion::promotion_type_XX() → shop\Product::is_product_on_promotion() +``` + +**Rozwiązanie:** Wszystko w jednym serwisie `PromotionFrontendService`. + +**NOWE:** +- `Domain/Promotion/PromotionFrontendService.php`: + - `getActivePromotions()` (z `shop\Promotion`) + - `applyPromotions(array $basket)` (z `shop\Promotion::find_promotion()`) + - `private applyType01..05()` (z `front\factory\ShopPromotion`) + - `private isProductOnPromotion()` (z `shop\Product` — proste zapytanie) +- Testy: `PromotionFrontendServiceTest` (7 typów promocji + brak aktywnych) + +**ZMIANA:** +- `shop/Promotion` → fasada do `PromotionFrontendService::applyPromotions()` +- `front/factory/ShopPromotion` → fasada + +--- + +### ver. 0.282 — Product Frontend Service + +**Cel:** Migracja `front\factory\ShopProduct` i statycznych metod `shop\Product` do Domain. + +**NOWE:** +- `Domain/Product/ProductFrontendService.php`: + - Z `front\factory\ShopProduct`: `productDetails()` (~330 linii z Redis), `promotedProducts()`, `topProducts()`, `newProducts()`, `productUrl()`, `getMinimalPrice()`, `isProductActive()`, `getProductSku()`, `getProductEan()`, `productImage()`, `productWp()`, `randomProducts()`, `warehouseMessageZero()`, `warehouseMessageNonzero()` + - Z `shop\Product` (statyczne): `isProductOnPromotion()`, `getProductImg()`, `getProductUrl()`, `addVisit()`, `productSetsForBasket()`, `searchProductsByName()`, `searchProductByNameAjax()` +- Testy: `ProductFrontendServiceTest` + +**ZMIANA:** +- `front/factory/ShopProduct` → fasada +- `shop/Product` statyczne metody → fasady do `ProductFrontendService` + +**UWAGA:** Konstruktor `shop\Product`, `getFromCache()`, `calculate_basket_product_price()` — zostają na razie (instancyjne, używane w szablonach). Migracja w ver. 0.286. + +--- + +### ver. 0.283 — Client Authentication (Security Fix) + +**Cel:** Migracja `front\factory\ShopClient` + NAPRAWIENIE hardcoded password bypass. + +**NOWE:** +- `Domain/Client/ClientFrontendService.php`: + - `login()` — **BEZ** bypassa 'Legia1916', z opcjonalną migracją md5 → password_hash + - `signup()`, `registerConfirm()`, `sendPasswordRecovery()`, `resetPassword()` + - `clientDetails()`, `clientOrders()` + - CRUD adresów: `saveAddress()`, `deleteAddress()`, `getAddresses()`, `markAddressAsCurrent()` +- Testy: `ClientFrontendServiceTest` — **KRYTYCZNY test: login z 'Legia1916' NIE przechodzi** + +**ZMIANA:** +- `front/factory/ShopClient` → fasada +- `front/controls/ShopClient` → deleguje do serwisu + +--- + +### ver. 0.284 — Transport, Payment, Coupon Frontend Services + +**Cel:** Frontend serwisy dla transportu, płatności i kuponów. + +**NOWE:** +- `Domain/Transport/TransportFrontendService.php` — `transportMethods()` (filtrowanie WP, free delivery), `transportCost()`, `transportDetails()` +- `Domain/PaymentMethod/PaymentMethodFrontendService.php` — `activePaymentMethods()`, `paymentMethodsByTransport()`, `paymentMethodDetails()` +- `Domain/Coupon/CouponFrontendService.php` — `validateCoupon()`, `applyCoupon()`, `markCouponUsed()` +- Testy: 3 pliki testowe + +**ZMIANA:** +- `front/factory/ShopTransport` → fasada +- `front/factory/ShopCoupon` → fasada +- `shop/Coupon` → fasada +- `shop/Transport` → fasada + +--- + +### ver. 0.285 — Basket Service + +**Cel:** Migracja logiki koszyka do `Domain\Basket\BasketService`. + +**NOWE:** +- `Domain/Basket/BasketService.php`: + - `addProduct()`, `removeProduct()`, `changeQuantity()`, `increaseQuantity()`, `decreaseQuantity()` + - `summaryPrice()`, `countProducts()`, `countProductsText()` + - `validateStock()` (z `shop\Basket::check_product_quantity_in_stock()`) + - `calculateProductPrice()` (z `shop\Product::calculate_basket_product_price()` ~112 linii) +- Testy: `BasketServiceTest` (pricing z promocjami/kuponami, walidacja stanów) + +**ZMIANA:** +- `front/factory/ShopBasket` → fasada +- `front/controls/ShopBasket` — wewnętrznie używa `BasketService` +- `shop/Basket` → fasada +- `shop/Product::calculate_basket_product_price()` → fasada + +--- + +### ver. 0.286 — shop\Product Instance + Cache + +**Cel:** Refaktoring konstruktora `shop\Product` i `getFromCache()`. + +**NOWE:** +- `Domain/Product/ProductDataLoader.php`: + - `loadFull(int $productId, ?string $langId, ?string $permutationHash)` — ładowanie pełnych danych produktu + - `loadCached()` — Redis cache wrapper +- Testy: `ProductDataLoaderTest` + +**ZMIANA:** +- `shop/Product` — konstruktor i `getFromCache()` delegują do `ProductDataLoader` +- ArrayAccess interface zachowany (szablony dalej używają `$product->property`) + +--- + +### ver. 0.287 — Order Creation Frontend Service + +**Cel:** Migracja `front\factory\ShopOrder::basket_save()` (~180 linii). + +**NOWE:** +- `Domain/Order/OrderFrontendService.php`: + - `createOrder()` — tworzenie zamówienia z koszyka (walidacja, kalkulacja cen, insert, redukcja stanów, obsługa kuponu, wysyłka emaili, auto-status dla pobrania) + - `generateOrderNumber()` — format YYYY/MM/NNN + - `orderDetails()`, `orderIdByHash()`, `orderHashById()` +- Testy: `OrderFrontendServiceTest` + +**ZMIANA:** +- `front/factory/ShopOrder` → fasada + +--- + +### ver. 0.288 — Payment Webhook Service + +**Cel:** Wyodrębnienie webhooków płatności z `front\controls\ShopOrder`. + +**NOWE:** +- `Domain/Payment/PaymentWebhookService.php`: + - `processTpay(array $params)` — weryfikacja tPay + - `processPrzelewy24(array $params)` — weryfikacja przez API + walidacja kwoty + - `processHotpay(array $params)` — walidacja SHA256 hash + - `private markOrderPaid()` — wspólna logika (update status + email + Apilo sync) +- Testy: `PaymentWebhookServiceTest` + +**ZMIANA:** +- `front/controls/ShopOrder` — webhooki stają się thin wrappers + +**POPRAWA:** Zamiana `file_put_contents('tpay.txt')` na `\Log::save_log()` + +--- + +### ver. 0.289 — shop\Order Instance + Apilo Service + +**Cel:** Refaktoring `shop\Order` instancyjnych metod + wyodrębnienie integracji Apilo. + +**NOWE:** +- `Domain/Integrations/ApiloService.php`: + - `syncPayment()`, `syncStatus()`, `processQueue()` + - `private queueSync()`, `private loadQueue()`, `private saveQueue()` +- `Domain/Order/OrderOperationsService.php`: + - `setAsPaid()`, `setAsUnpaid()`, `updateStatus()`, `sendStatusChangeEmail()`, `resendConfirmationEmail()` +- Testy: `ApiloServiceTest`, `OrderOperationsServiceTest` + +**ZMIANA:** +- `shop/Order` instancyjne metody → fasady do `OrderOperationsService` +- Konstruktor i ArrayAccess bez zmian + +--- + +### ver. 0.290 — Frontend App + Controllers (DI layer) + +**Cel:** Stworzenie `front\App` (wzorowanego na `admin\App`) z mapą kontrolerów i DI. + +**NOWE:** +- `autoload/front/App.php` — `render()`, `handleAjax()`, `getControllerFactories()` (DI wiring) +- `autoload/front/Controllers/ShopBasketController.php` — DI z `BasketService`, `ProductFrontendService` +- `autoload/front/Controllers/ShopOrderController.php` — DI z `OrderFrontendService`, `PaymentWebhookService` +- `autoload/front/Controllers/ShopClientController.php` — DI z `ClientFrontendService` +- Testy: 3 pliki testowe kontrolerów + +**ZMIANA:** +- `front/controls/ShopBasket`, `ShopOrder`, `ShopClient` → delegują do nowych kontrolerów + +--- + +### ver. 0.291 — Site Layout Engine + +**Cel:** Refaktoring `front\view\Site::show()` (~600 linii) na testowalny `LayoutEngine`. + +**NOWE:** +- `autoload/front/View/LayoutEngine.php`: + - `resolveLayout(array $page, array $params)` — wybór layoutu (product > category > article > page > default) + - `processPatterns(string $html, array $context)` — zamiana tagów szablonowych + - Osobne prywatne metody: `replaceCategories()`, `replaceProducts()`, `replaceMenus()`, `replaceLanguageTags()`, `replaceBanners()`, `replaceArticles()`, `replaceContainers()`, `replaceMetaTags()`, etc. +- Testy: `LayoutEngineTest` + +**ZMIANA:** +- `front/view/Site::show()` → thin wrapper na `LayoutEngine` + +--- + +### ver. 0.292 — Entry Point Unification + +**Cel:** Ujednolicenie bootstrapu `index.php` i `ajax.php`. + +**NOWE:** +- `autoload/front/Bootstrap.php` — `init()` (autoloader, config, sesja, DB, lang/settings) +- `autoload/front/PostProcessor.php` — ekstrakcja DOM manipulacji z `index.php` (GTM, Facebook Pixel, WebP, lazy loading) + +**ZMIANA:** +- `index.php` → uproszczony: `Bootstrap::init()` → `App::render()` → `PostProcessor::process()` +- `ajax.php` → uproszczony: `Bootstrap::init()` → `App::handleAjax()` + +--- + +### ver. 0.293 — Legacy Cleanup + +**Cel:** Finalne porządki. + +**USUNIĘCIE:** +- Martwy kod `eval()` dla `[PHP]` bloków (jeśli nieużywany) +- `class.Cache.php` (legacy file-based) jeśli wszystkie użycia przeniesione na `CacheHandler` +- Pusta klasa `front\view\ShopTransport` + +**ZMIANA:** +- Dodanie `@deprecated` do wszystkich metod-fasad w `front/factory/`, `front/controls/`, `shop/` +- PHPDoc do wszystkich nowych klas Domain z `@since` +- Aktualizacja `tests/bootstrap.php` +- BUG FIX: `shop\Search` — typo `shop\Produt` → `shop\Product` +- BUG FIX: `front\factory\Newsletter::newsletter_unsubscribe()` — poprawka SQL + +--- + +## Podsumowanie + +| Wersja | Zakres | Priorytet | Nowe klasy Domain | Testy | +|--------|--------|-----------|-------------------|-------| +| 0.278 | Settings + Languages | FUNDAMENT | 2 serwisy | 2 | +| 0.279 | Category Frontend | WYSOKI | 1 serwis | 1 | +| 0.280 | Banners/Menu/Pages/Articles/Layouts | ŚREDNI | 5 serwisów | 5 | +| 0.281 | Promotion Engine | KRYTYCZNY | 1 serwis | 1 | +| 0.282 | Product Frontend | KRYTYCZNY | 1 serwis | 1 | +| 0.283 | Client/Auth (security fix) | KRYTYCZNY | 1 serwis | 1 | +| 0.284 | Transport/Payment/Coupon | WYSOKI | 3 serwisy | 3 | +| 0.285 | Basket Service | WYSOKI | 1 serwis | 1 | +| 0.286 | Product Instance + Cache | ŚREDNI | 1 loader | 1 | +| 0.287 | Order Creation | WYSOKI | 1 serwis | 1 | +| 0.288 | Payment Webhooks | WYSOKI | 1 serwis | 1 | +| 0.289 | Order Instance + Apilo | ŚREDNI | 2 serwisy | 2 | +| 0.290 | Frontend App + Controllers | WYSOKI | App + 3 kontrolery | 3 | +| 0.291 | Layout Engine | ŚREDNI | 1 engine | 1 | +| 0.292 | Entry Point Unification | ŚREDNI | Bootstrap + PostProcessor | 1 | +| 0.293 | Legacy Cleanup | NISKI | — | — | + +**Łącznie:** 16 wersji, ~24 nowe klasy Domain, ~25 plików testowych + +### Wzorce do przestrzegania (z migracji admin) +- Konstruktor DI z `$db` (medoo) +- CacheHandler (Redis) dla cachingu — unifikacja (usunięcie starego `Cache`) +- Fasady w `shop\*` i `front\factory\*` dla kompatybilności wstecznej +- Testy PHPUnit z mockami medoo +- Namespace `\Domain\*` → `autoload/Domain/*/` +- Namespace `\front\Controllers\` → `autoload/front/Controllers/` + +### Weryfikacja po każdej wersji +1. `composer test` (pełny suite PHPUnit) +2. Manualne sprawdzenie frontendu: strona główna, kategoria, produkt, koszyk, zamówienie +3. Sprawdzenie AJAX: dodawanie do koszyka, zmiana transportu, kupon +4. Sprawdzenie webhooków płatności (tPay, Przelewy24, Hotpay)