# Weryfikacja wieku w PrestaShop: blokujące okno dla CBD, alkoholu, e-papierosów i branży medycznej

> Moduł dfagegate dodaje blokujące okno weryfikacji wieku do Twojego sklepu PrestaShop 8 lub 9. Pokrywa dwa odrębne rynki: tryb standardowy dla produktów regulowanych progiem wieku (CBD, alkohol, e-papierosy, broń, zapalniczki,…

- Strona: <https://www.datafirefly.com/pl/documentation/verification-age-prestashop-modal-cbd-alcool-vape-medical/>
- Język: pl
- Zaktualizowano: 2026-09-28
- Inne języki: [fr](https://www.datafirefly.com/documentation/verification-age-prestashop-modal-cbd-alcool-vape-medical/index.md), [en](https://www.datafirefly.com/en/documentation/verification-age-prestashop-modal-cbd-alcool-vape-medical/index.md), [es](https://www.datafirefly.com/es/documentation/verification-age-prestashop-modal-cbd-alcool-vape-medical/index.md), [de](https://www.datafirefly.com/de/documentation/verification-age-prestashop-modal-cbd-alcool-vape-medical/index.md), [it](https://www.datafirefly.com/it/documentation/verification-age-prestashop-modal-cbd-alcool-vape-medical/index.md), [pt](https://www.datafirefly.com/pt/documentation/verification-age-prestashop-modal-cbd-alcool-vape-medical/index.md), [nl](https://www.datafirefly.com/nl/documentation/verification-age-prestashop-modal-cbd-alcool-vape-medical/index.md)
- Indeks: <https://www.datafirefly.com/pl/documentation/llms.txt>

Moduł **dfagegate** dodaje **blokujące** okno weryfikacji wieku do Twojego sklepu PrestaShop 8 lub 9. Pokrywa dwa odrębne rynki: **tryb standardowy** dla produktów regulowanych progiem wieku (CBD, alkohol, e-papierosy, broń, zapalniczki, produkty od 18 lat) oraz **tryb medyczny** dla wyrobów medycznych zastrzeżonych dla profesjonalistów ochrony zdrowia.

**Zgodność**: PrestaShop 1.7.7+, 8.x i 9.0. PHP 7.4 minimum, zalecane 8.1+. Multistore i wielojęzyczność (FR/EN/ES/DE uzupełnione przy instalacji).

## Instalacja

Instalacja przebiega standardowym trybem PrestaShop. Po zakupie w DataFirefly otrzymujesz plik ZIP `dfagegate-X.Y.Z.zip`.

### Przez panel administracyjny (zalecane)

1. Zaloguj się do panelu administracyjnego PrestaShop
2. Przejdź do **Moduły → Katalog modułów**
3. Kliknij **Wgraj moduł** w prawym górnym rogu
4. Wybierz plik ZIP `dfagegate-X.Y.Z.zip`
5. Po zakończeniu przesyłania kliknij **Zainstaluj**

### Przez FTP

1. Rozpakuj plik ZIP lokalnie
2. Wgraj katalog `dfagegate/` do katalogu `modules/` Twojego PrestaShop
3. Przejdź do **Moduły → Katalog modułów**
4. Wyszukaj „DataFirefly Age Gate" i kliknij **Zainstaluj**

**Ważne**: po instalacji **moduł jest domyślnie wyłączony**. To celowe: pozwala skonfigurować teksty i tryb, zanim zablokujesz sklep. Przejdź do konfiguracji modułu i włącz przełącznik w zakładce _Ogólne_, gdy wszystko będzie gotowe.

## Pierwsza konfiguracja

Wejdź w konfigurację: **Moduły → Zainstalowane moduły → DataFirefly Age Gate → Konfiguruj**.

Konfiguracja jest podzielona na 6 zakładek:

- **Ogólne**: aktywacja, tryb, typ weryfikacji, minimalny wiek, zakres wyświetlania
- **Treść**: teksty wielojęzyczne (tytuł, komunikat, przyciski, informacje prawne)
- **Wygląd**: logo, kolory, rozmycie tła
- **Zachowanie**: ciasteczko, przekierowanie, wykluczenia
- **Tryb medyczny**: zawody i numer uprawnień (pojawia się wyłącznie w trybie medycznym)
- **Logi i RODO**: dziennik zdarzeń, statystyki i diagnostyka

### Zakładka Ogólne

Tutaj konfigurujesz główne zachowanie modułu.

- **Włącz moduł**: przełącznik tak/nie, steruje globalnym wyświetlaniem okna
- **Tryb**: _standardowy_ (CBD, alkohol, e-papierosy, broń) albo _medyczny_ (profesjonaliści ochrony zdrowia)
- **Typ weryfikacji**: _przycisk tak/nie_, _data urodzenia_ albo _deklaracja zawodu_
- **Minimalny wiek**: domyślnie 18, wartość 21 dla wybranych rynków (na przykład część stanów USA przy alkoholu)
- **Zakres wyświetlania**: cały sklep, wybrane kategorie albo wybrane produkty (opis poniżej)
- **Przetestuj okno**: przycisk otwierający sklep w trybie podglądu (opis w sekcji Diagnostyka)

**Który typ weryfikacji wybrać?** _Przycisk tak/nie_ sprawdza się w większości przypadków (CBD, alkohol dla szerokiego odbiorcy, e-papierosy): jest szybki, ma niskie tarcie i wystarczający efekt odstraszający przy kontroli Inspekcji Handlowej lub sanepidu. _Data urodzenia_ jest bardziej rygorystyczna i zalecana przy broni oraz płynach z nikotyną. _Deklaracja zawodu_ jest zarezerwowana dla trybu medycznego.

### Zakres wyświetlania: wybrane kategorie albo produkty

Od wersji 1.1.0 ustawienie **Zakres wyświetlania** w zakładce Ogólne oferuje trzy tryby:

- **Cały sklep**: okno pojawia się na wszystkich stronach. To dotychczasowe zachowanie i wartość domyślna
- **Tylko wybrane kategorie**: okno pojawia się na stronach zaznaczonych kategorii oraz na kartach produktów, które do nich należą. Wyboru dokonujesz w drzewie kategorii z polami wyboru, natychmiastowym filtrem wyszukiwania i licznikiem zaznaczeń
- **Tylko wybrane produkty**: okno pojawia się wyłącznie na kartach wybranych produktów. Szukasz po nazwie albo referencji, podpowiedzi pojawiają się w trakcie pisania, a każdy wybrany produkt staje się usuwalną etykietą

W trybie kategorii opcja **Uwzględnij podkategorie** (domyślnie włączona) automatycznie obejmuje całe potomstwo zaznaczonych kategorii: zaznacz „CBD", a jej podkategorie „Oleje", „Susz" czy „Żywice" zostaną objęte bez zaznaczania ich pojedynczo. Rozwinięcie opiera się na strukturze nested sets PrestaShop, w jednym zapytaniu.

**Sklep mieszany?** To typowy przypadek użycia zakresu: delikatesy sprzedające także mocne alkohole, drogeria z działem sprzętu profesjonalnego. Obejmij dział regulowany zakresem po kategoriach: jest chroniony, a reszta sklepu pozostaje bez okna.

**Tryb produktów a strony listingów**: w trybie wybranych produktów strony listingów (kategoria, wyszukiwanie, nowości) nie uruchamiają okna, robią to wyłącznie karty wybranych produktów. Aby objąć cały dział razem z listingami, wybierz zakres po kategoriach.

Decyzja o wyświetleniu zapada **po stronie serwera**, nie w JavaScripcie. Komentarz diagnostyczny w sekcji head wskazuje aktywny zakres: `scope=all`, `scope=categories` albo `scope=products`. Przy zapisie zakres z wyborem i pustą selekcją zostaje odrzucony z komunikatem błędu, aby nie zostawić konfiguracji w niespójnym stanie.

### Zakładka Treść

Każdy język włączony w Twoim PrestaShop ma własny blok tekstów. Wartości domyślne są uzupełnione w **FR, EN, ES i DE**. Dla każdego języka możesz skonfigurować:

- **Tytuł**: wyświetlany dużą czcionką na górze okna (domyślnie: „Weryfikacja wieku")
- **Komunikat**: główny tekst wyjaśniający, znaki końca linii są zachowywane
- **Przycisk potwierdzenia**: etykieta przycisku pozytywnego (domyślnie: „Mam 18 lat lub więcej")
- **Przycisk odmowy**: etykieta przycisku negatywnego
- **Informacja prawna**: tekst na dole okna (domyślnie ostrzeżenie o szkodliwości nadużywania alkoholu)
- **Komunikat przy odmowie**: ekran wyświetlany, gdy użytkownik odmówi, przed przekierowaniem

**HTML**: treść jest sanityzowana przy zapisie (wyłącznie czysty tekst). Znaki końca linii są zamieniane na znaczniki łamania wiersza podczas renderowania, przez automatyczny filtr `nl2br`.

**Polska wersja językowa**: teksty domyślne nie są uzupełnione po polsku. Po instalacji wejdź w zakładkę Treść i wpisz sześć pól dla języka polskiego. Sugerowana informacja prawna dla sklepu z alkoholem to standardowa formuła o szkodliwości spożywania alkoholu, dla sklepu z e-papierosami komunikat o zakazie sprzedaży osobom poniżej 18 lat.

### Zakładka Wygląd

Dostosuj wygląd okna do swojej identyfikacji wizualnej:

- **Logo**: PNG, JPG, SVG albo WEBP, maksymalnie 2 MB, wyświetlane na górze okna
- **Kolor tła**: kolor głównej karty (domyślnie biały)
- **Kolor podstawowy**: tytuł i przycisk główny (domyślnie czarny #111111)
- **Kolor tekstu**: treść komunikatu
- **Kolor przesłony**: warstwa za oknem, przyjmuje formaty CSS `rgba()` i hex (domyślnie: `rgba(15,15,20,0.85)`)
- **Rozmycie tła**: efekt rozmycia w tle, działa we wszystkich aktualnych przeglądarkach

### Zakładka Zachowanie

Steruje trwałością wyboru i przypadkami wykluczeń.

- **Czas życia ciasteczka**: w dniach (domyślnie 90). Wartość `0` daje ciasteczko sesyjne (usuwane po zamknięciu przeglądarki)
- **Adres przekierowania przy odmowie**: zostaw pusty, aby wyświetlić wyłącznie komunikat odmowy, albo wpisz adres zewnętrzny (wyszukiwarka, strona informacyjna, strona dostawcy)
- **Wykluczenie po IP**: lista adresów IP (po jednym w wierszu), dla których okno się nie wyświetla. Idealne dla Ciebie i zespołu podczas testów
- **Wykluczenie adresów URL**: częściowe ścieżki wyłączone z blokady. Domyślnie uzupełnione francuskimi ścieżkami: `/legal`, `/contact`, `/cgv`, `/mentions-legales`, `/politique-confidentialite`
- **Wykluczenie zalogowanych klientów**: gdy włączone, klienci już zalogowani nie widzą okna (przydatne, jeśli Twój sklep jest zastrzeżony dla zweryfikowanych kont)

**Dla polskiego sklepu** zastąp domyślne ścieżki francuskie odpowiednikami z Twojego adresowania: `/regulamin`, `/kontakt`, `/polityka-prywatnosci`, `/informacje-prawne`. Wykluczenie działa na fragmentach adresu, więc wpisanie samego `/regulamin` pokryje wszystkie warianty tej ścieżki.

### Zakładka Tryb medyczny

Ta zakładka ma zastosowanie wyłącznie wtedy, gdy **tryb** jest ustawiony na _medyczny_, a **typ weryfikacji** na _deklarację zawodu_.

- **Lista zawodów**: po jednym w wierszu. Domyślnie: lekarz, farmaceuta, pielęgniarka lub pielęgniarz, fizjoterapeuta, dentysta, lekarz weterynarii, inny profesjonalista ochrony zdrowia. W pełni konfigurowalna pod Twoją grupę docelową
- **Numer uprawnień obowiązkowy**: gdy włączone, w oknie pojawia się dodatkowe pole. Walidacja przez wyrażenie regularne akceptujące od 9 do 11 cyfr. **Numer nie jest przechowywany**, służy wyłącznie walidacji po stronie serwera

**Zgodność prawna**: tryb medyczny materializuje oświadczenie w rozumieniu francuskiego artykułu L5122-9 Kodeksu zdrowia publicznego, który zastrzega reklamę wybranych wyrobów medycznych dla uprawnionych profesjonalistów ochrony zdrowia. Polskim odpowiednikiem jest ustawa o wyrobach medycznych, która także ogranicza reklamę części wyrobów do profesjonalistów. **Moduł nie zastępuje przeglądu prawnego Twojego katalogu przez wyspecjalizowanego prawnika**. Skonsultuj konfigurację ze swoim doradcą.

**Numer PWZ**: walidacja regex została zaprojektowana pod francuskie rejestry RPPS i ADELI (od 9 do 11 cyfr). Polski numer prawa wykonywania zawodu lekarza ma 7 cyfr, więc domyślny wzorzec go odrzuci. Masz dwie ścieżki: wyłącz obowiązkowość numeru i pozostaw samą deklarację zawodu z polem oświadczenia (to wystarcza do materializacji deklaracji), albo dostosuj wzorzec w kodzie kontrolera AJAX do formatu polskiego.

### Zakładka Logi i RODO

Opcjonalny dziennik zdarzeń, statystyki i informacje o zgodności.

- **Loguj odmowy**: zapisuje każdą odmowę w tabeli `ps_dfagegate_log` z adresem IP zahashowanym w SHA-256 (nigdy jawnym), datą i powodem
- **Okres przechowywania logów**: czas przechowywania w dniach (domyślnie 365, wartość `0` oznacza bezterminowo). Odmowy starsze niż ten okres są usuwane automatycznie przy każdym otwarciu strony konfiguracji

Od wersji 1.1.0 zakładka wyświetla także **statystyki odmów**: sumę z ostatnich 30 dni, podział według powodu oraz 15 ostatnich odmów z datą, powodem, zadeklarowanym wiekiem i zawodem, jeśli dotyczy. Przycisk **Wyczyść wszystkie logi odmów** (z potwierdzeniem) opróżnia tabelę dla bieżącego sklepu.

Zakładka wyświetla również ściągawkę RODO:

- **Zakładane ciasteczko**: `dfagegate_ok`
- **Kategoria**: ściśle niezbędne (spełnienie obowiązku prawnego dotyczącego dostępu)
- **Dane**: wartość „1", konfigurowalny czas życia, SameSite=Lax, Secure przy HTTPS

## Konfiguracja pod Twój rynek

Kilka gotowych konfiguracji dla inspiracji.

### Sklep CBD dla szerokiego odbiorcy

- Tryb: **standardowy**
- Typ weryfikacji: **przycisk tak/nie**
- Minimalny wiek: **18**
- Czas życia ciasteczka: **90 dni** (dobry kompromis między zgodnością a wygodą)
- Adres przekierowania: _pusty_ (sam komunikat odmowy)
- Informacja prawna: „Kannabidiol może wchodzić w interakcje z niektórymi lekami. Skonsultuj się z lekarzem."

### Sklep z alkoholami premium

- Tryb: **standardowy**
- Typ weryfikacji: **data urodzenia** (ściślejsza kontrola dla rynków premium)
- Minimalny wiek: **18** (lub 21 dla części rynków zagranicznych)
- Adres przekierowania: dowolna oficjalna strona informacyjna o profilaktyce uzależnień
- Informacja prawna: standardowa formuła o szkodliwości nadużywania alkoholu

### Sklep z e-papierosami i płynami z nikotyną

- Tryb: **standardowy**
- Typ weryfikacji: **data urodzenia** (zdecydowanie zalecane przy nikotynie)
- Minimalny wiek: **18**
- Loguj odmowy: **tak** (przydatne przy kontroli sanepidu)

### Sklep z bronią

- Tryb: **standardowy**
- Typ weryfikacji: **data urodzenia** (obowiązkowo)
- Minimalny wiek: **18**
- Wykluczenie adresów URL: dodaj `/przepisy`, `/pozwolenie-na-bron`
- Loguj odmowy: **tak**

### Delikatesy z działem alkoholi mocnych (sklep mieszany)

- Tryb: **standardowy**
- Typ weryfikacji: **przycisk tak/nie**
- Zakres wyświetlania: **wybrane kategorie**, z zaznaczoną kategorią Alkohole mocne i uwzględnionymi podkategoriami
- Efekt: okno pojawia się tylko w dziale alkoholi i na jego kartach produktów, reszta delikatesów pozostaje bez tarcia

### Sklep ze sprzętem medycznym (wyroby dla profesjonalistów)

- Tryb: **medyczny**
- Typ weryfikacji: **deklaracja zawodu**
- Lista zawodów: lekarz, farmaceuta, fizjoterapeuta, osteopata (dostosuj do swojego katalogu)
- Numer uprawnień obowiązkowy: **tak** po dostosowaniu wzorca, w przeciwnym razie **nie**
- Wykluczenie zalogowanych klientów: **tak** (jeśli weryfikujesz zawód już przy rejestracji)

## Jak działa weryfikacja przez datę urodzenia

W odróżnieniu od zwykłego przycisku weryfikacja przez datę urodzenia wykonuje obliczenie **po stronie serwera**, a nie w przeglądarce. Pełny przebieg:

1. Odwiedzający wpisuje dzień, miesiąc i rok w oknie
2. JavaScript wysyła te wartości do kontrolera AJAX `DfagegateAjaxModuleFrontController`
3. PHP waliduje datę przez `checkdate()`, a następnie wylicza wiek przez `DateTimeImmutable::diff()`
4. Jeśli wiek jest niższy od skonfigurowanego progu, serwer zwraca odpowiedź JSON `success=false, denied=true` wraz z komunikatem błędu
5. Okno wyświetla komunikat odmowy i przekierowuje po 2 sekundach
6. Jeśli wiek jest równy progowi albo wyższy, zakładane jest ciasteczko `dfagegate_ok`, a okno się zamyka

**Dlaczego po stronie serwera?** Kontrolę wyłącznie w JavaScripcie da się obejść przez narzędzia deweloperskie w mniej niż 10 sekund. Obliczenie serwerowe gwarantuje, że użytkownik poniżej progu wieku nie uzyska dostępu do strony, nawet mając wiedzę techniczną. To kluczowe, aby obronić się przy kontroli.

Zwróć uwagę, że **data urodzenia nigdy nie jest przechowywana**: służy przez czas obliczenia, po czym zostaje zapomniana. Zachowywana jest wyłącznie binarna walidacja (zaakceptowano lub odrzucono) w postaci ciasteczka.

## Jak działa tryb medyczny

Tryb medyczny działa podobnie, ale na innych polach:

1. Okno wyświetla listę rozwijaną zawodów (konfigurowalną) i ewentualnie pole numeru uprawnień
2. Obecne jest obowiązkowe pole wyboru z **oświadczeniem**
3. Kontroler AJAX sprawdza, czy zawód został wybrany
4. Jeśli numer uprawnień jest obowiązkowy, serwer waliduje format wyrażeniem regularnym akceptującym od 9 do 11 kolejnych cyfr
5. Brak przechowywania: ani zawód, ani numer nie trafiają do bazy, a ciasteczko `dfagegate_ok` materializuje wyłącznie fakt pomyślnego przejścia

**Decyzja projektowa**: przepisy o reklamie wyrobów medycznych wymagają materializacji deklaracji, niekoniecznie weryfikacji w czasie rzeczywistym wobec rejestru centralnego. Nasze podejście to _minimalna wykonalna zgodność_: prosimy o deklarację, walidujemy ją formalnie, zapisujemy odmowę, jeśli logi są włączone, ale nie zbieramy zbędnych danych osobowych. Jeśli potrzebujesz weryfikacji w czasie rzeczywistym wobec Centralnego Rejestru Lekarzy albo francuskiego rejestru ANS, to osobne wdrożenie na zamówienie.

## Multistore

Moduł jest **w pełni zgodny z multistore**. Wszystkie konfiguracje (tryb, typ weryfikacji, teksty wielojęzyczne, kolory, wykluczenia, zakres wyświetlania) są przechowywane per kontekst sklepu przez `id_shop_group` i `id_shop`. Oznacza to, że w jednym PrestaShop możesz mieć:

- Sklep **CBD PL** w trybie standardowym z progiem 18 lat i tekstami po polsku
- Sklep **e-papierosy UK** w trybie standardowym z progiem 18 lat i tekstami po angielsku
- Sklep **sprzęt medyczny DE** w trybie medycznym z obowiązkowym numerem uprawnień i tekstami po niemiecku

Aby skonfigurować konkretny podsklep:

1. W selektorze kontekstu na górze panelu administracyjnego wybierz docelowy podsklep
2. Otwórz konfigurację modułu
3. Zmień wartości: zostaną zapisane wyłącznie dla tego sklepu

**Hooki są rejestrowane we wszystkich sklepach** w momencie instalacji przez `Shop::getCompleteListOfShopsID()`, co pozwala uniknąć klasycznej pułapki modułu działającego wyłącznie na bieżącym sklepie.

## Zgodność z motywami własnymi

Moduł korzysta ze standardowego hooka `displayBeforeBodyClosingTag`, aby wstrzyknąć okno tuż przed zamknięciem znacznika body. Ten hook powinien być uniwersalny od PrestaShop 1.7.5+.

Niestety **część motywów własnych nie wywołuje tego hooka** w swoim layoucie. Na ten przypadek dfagegate zawiera **mechanizm awaryjny w JavaScripcie**:

1. PHP prerenderuje pełny kod HTML okna i przekazuje go do JS przez `Media::addJsDef`
2. Przy zdarzeniu `DOMContentLoaded` skrypt sprawdza, czy element o identyfikatorze `dfagegate-modal` istnieje w DOM
3. Jeśli tak, wszystko jest w porządku: hook zadziałał
4. Jeśli nie, skrypt sam wstrzykuje okno przez `insertAdjacentHTML('beforeend', ...)`
5. Komunikat `console.info` potwierdza uruchomienie mechanizmu awaryjnego, informując, że okno zostało wstrzyknięte przez JS, ponieważ motyw nie wyzwala hooka

**Praktyczny efekt**: moduł działa na dowolnym motywie PrestaShop 1.7.5+, także na niekompletnych motywach własnych, **bez konieczności modyfikowania layoutu**. Możesz go wdrożyć bez koordynacji z agencją odpowiadającą za motyw.

## Diagnostyka i debugowanie

Po aktywacji dfagegate dodaje **komentarz HTML w sekcji head** każdej strony frontu, w postaci informacji o wersji modułu (1.1.0), stanie włączenia, aktywnym zakresie wyświetlania i tym, czy okno powinno się wyświetlić.

Ten komentarz to Twój pierwszy punkt diagnostyczny. Otwórz kod źródłowy dowolnej strony frontu (Ctrl+U albo Cmd+U) i wyszukaj „dfagegate".

| Komentarz | Interpretacja |
| --- | --- |
| Brak komentarza | Hook `displayHeader` nie jest zarejestrowany: sprawdź, czy moduł jest zainstalowany i aktywny |
| `enabled=0` | Przełącznik „Włącz moduł" jest ustawiony na nie w zakładce Ogólne |
| `enabled=1 should_display=0` | Aktywne jest wykluczenie (Twój adres IP jest na białej liście, bieżący adres URL pasuje do wykluczonej ścieżki albo jesteś zalogowanym klientem przy włączonym wykluczeniu) albo bieżąca strona jest poza wybranym zakresem: sprawdź wartość `scope=` |
| `enabled=1 should_display=1` | Po stronie serwera wszystko jest w porządku. Jeśli okno się nie pojawia, sprawdź konsolę przeglądarki pod kątem komunikatu mechanizmu awaryjnego albo błędu |

### Okno nadal się nie pojawia?

Szybka lista kontrolna:

1. Czy komentarz diagnostyczny jest obecny z wartością `should_display=1`? Jeśli nie, popraw konfigurację
2. Otwórz sklep w **trybie prywatnym**. Ciasteczko `dfagegate_ok` mogło zostać założone w poprzedniej sesji
3. Sprawdź swój adres IP w wykluczeniach w zakładce _Zachowanie_
4. Przy wybranym zakresie sprawdź, czy testowana strona należy do zaznaczonych kategorii albo produktów
5. Otwórz konsolę przeglądarki (F12). Wyszukaj `[dfagegate]` pod kątem komunikatów wstrzykiwania awaryjnego albo błędów
6. Sprawdź logi PrestaShop w **Ustawienia zaawansowane → Logi**, filtrując po „dfagegate"
7. **Wyczyść cache PrestaShop** po każdej zmianie konfiguracji: _Ustawienia zaawansowane → Wydajność → Wyczyść pamięć podręczną_

### Testowanie w trybie podglądu

Od wersji 1.1.0 przycisk **Przetestuj okno** w zakładce Ogólne otwiera sklep w nowej karcie z parametrem `?dfagegate_preview=1`. W tym trybie:

- Okno pojawia się **nawet wtedy, gdy ciasteczko dfagegate_ok jest już założone**
- Potwierdzenie **nie zakłada żadnego ciasteczka**: test można powtarzać dowolną liczbę razy, bez trybu prywatnego i bez ręcznego usuwania

Przy wybranym zakresie przejdź na objętą nim stronę, zachowując parametr w adresie, aby zobaczyć okno.

### Zresetowanie ciasteczka po stronie przeglądarki

Aby przetestować okno bez zmiany adresu IP:

1. Otwórz narzędzia deweloperskie (F12)
2. Zakładka **Application** (Chrome) albo **Storage** (Firefox)
3. Sekcja **Cookies** → Twoja domena
4. Usuń wiersz `dfagegate_ok`
5. Przeładuj stronę

## Zgodność z RODO

Moduł został zaprojektowany tak, aby był zgodny z RODO domyślnie.

### Ciasteczko `dfagegate_ok`

- **Typ**: ściśle niezbędne do spełnienia obowiązku prawnego dotyczącego dostępu
- **Podstawa prawna**: zwolnione z obowiązku uprzedniej zgody na podstawie przepisów wdrażających dyrektywę ePrivacy, które wyłączają z tego obowiązku ciasteczka niezbędne do świadczenia usługi żądanej przez użytkownika
- **Wartość**: binarna (`1` = potwierdzone)
- **Czas życia**: konfigurowalny (domyślnie 90 dni) albo sesyjny przy wartości 0
- **Atrybuty**: `SameSite=Lax`, automatyczny `Secure` przy HTTPS, `Path=/`

**W praktyce**: **nie musisz** dodawać tego ciasteczka do swojego banera zgód. Mieści się w tej samej kategorii co ciasteczko sesji PrestaShop albo ciasteczko CSRF: niezbędne do zgodnego z prawem działania strony, a więc zwolnione.

### Logi odmów

Jeśli włączysz opcję _Loguj odmowy_, każda odmowa jest zapisywana w tabeli `ps_dfagegate_log` wraz z:

- `id_shop`: którego podsklepu dotyczy
- `reason`: powód odmowy (`user_refused` albo `dob_under_age`)
- `age`: zadeklarowany wiek, jeśli dotyczy
- `profession`: zadeklarowany zawód, jeśli dotyczy
- `ip_hash`: **SHA-256 adresu IP**, nigdy adres jawny
- `date_add`: znacznik czasu

Haszowanie SHA-256 sprawia, że adres IP jest **nieodwracalny**, a jednocześnie pozwala deduplikować próby (ten sam adres IP zawsze da ten sam skrót). To kompromis zalecany przy statystyce dostępu, akceptowany przez organy ochrony danych.

**Przechowywanie jest automatyczne** od wersji 1.1.0: wpisy starsze niż skonfigurowany okres (domyślnie 365 dni) są usuwane przy każdym otwarciu strony konfiguracji. Ograniczony w czasie okres przechowywania to dokładnie to, czego zasada minimalizacji z RODO oczekuje od takiego dziennika. Statystyki z zakładki Logi (suma z 30 dni, podział według powodu, ostatnie odmowy) opierają się na tych samych danych zahashowanych.

### Dane weryfikacyjne

- **Data urodzenia** przechodzi przez AJAX na potrzeby obliczenia, ale **nigdy nie jest przechowywana**
- **Numer uprawnień** jest walidowany po stronie serwera, a następnie **zapominany**, nigdy nie trafia do bazy
- Zachowywana jest wyłącznie **binarna walidacja**, w postaci ciasteczka

## Struktura techniczna i integracja

Dla deweloperów, którzy chcą pójść dalej albo wpiąć moduł we własny proces.

### Wykorzystywane hooki

- `displayHeader`: wstrzykuje komentarz diagnostyczny
- `actionFrontControllerSetMedia`: rejestruje CSS i JS, przekazuje konfigurację oraz prerenderowany kod HTML okna do JS
- `displayBeforeBodyClosingTag`: renderuje okno po stronie serwera (mechanizm awaryjny w JS, jeśli hooka brakuje w motywie)

### Punkty wejścia AJAX

Kontroler AJAX odpowiada pod adresem `/module/dfagegate/ajax` i przyjmuje dwie akcje:

- `action=confirm`: z parametrami zależnymi od typu weryfikacji (żadnych przy tak/nie, day/month/year przy dacie urodzenia, profession/rpps w trybie medycznym)
- `action=refuse`: zapisuje odmowę i zwraca adres przekierowania

Odpowiedzi są w formacie JSON. Potwierdzenie zwraca `success=true`. Odmowa z powodu niewystarczającego wieku zwraca `success=false`, `denied=true` oraz odpowiedni komunikat błędu. Błąd walidacji zwraca `success=false` z komunikatem. Odmowa użytkownika zwraca `success=true` oraz `redirect_url` ze skonfigurowanym adresem przekierowania.

### Schemat bazy danych

Tworzona jest jedna tabela: `ps_dfagegate_log`. Zawiera kolumny `id_log` (klucz główny z autoinkrementacją), `id_shop`, `reason` (varchar 64), `age` (dopuszcza null), `profession` (varchar 128, dopuszcza null), `ip_hash` (char 64 na skrót SHA-256) oraz `date_add` (datetime). Dwa indeksy wtórne optymalizują zapytania raportowe: `idx_shop_date` na (id_shop, date_add) i `idx_reason` na reason.

## Odinstalowanie

Dwa poziomy odinstalowania:

### Wyłączenie bez usuwania

**Moduły → Zainstalowane moduły → DataFirefly Age Gate → Wyłącz**. Konfiguracja zostaje zachowana, tabela logów również. Możesz w każdej chwili włączyć moduł ponownie bez ponownej konfiguracji.

### Pełne odinstalowanie

**Moduły → Zainstalowane moduły → DataFirefly Age Gate → Odinstaluj**. Ta operacja:

- Usuwa tabelę `ps_dfagegate_log`
- Usuwa wszystkie wpisy konfiguracji (23 klucze skalarne i 6 kluczy wielojęzycznych)
- Wyrejestrowuje hooki
- Usuwa moduł z systemu

**Uwaga**: odinstalowanie jest **nieodwracalne**. Jeśli chcesz zachować historię logów odmów (na przykład na potrzeby audytu ochrony danych), wyeksportuj tabelę wcześniej.

## Wsparcie i aktualizacje

Każda licencja obejmuje:

- **12 miesięcy aktualizacji**: zgodność z PrestaShop, poprawki, usprawnienia
- **Wsparcie techniczne przez e-mail**: odpowiedź w ciągu 24 godzin roboczych, FR i EN
- **Zwrot w 30 dni** bez pytań
- **Niezaszyfrowany kod źródłowy**: możesz swobodnie dostosować moduł do swoich potrzeb

W razie pytań technicznych albo zgłoszenia błędu skontaktuj się z nami z poziomu swojego konta DataFirefly. Podaj wersję PrestaShop, wersję PHP, wersję modułu (widoczną na górze ekranu konfiguracji) i w miarę możliwości komentarz diagnostyczny obecny w sekcji head Twojego sklepu.
