# Fogyasztó Barát Shopify App - Fejlesztői dokumentáció

Ez a dokumentáció a Fogyasztó Barát Shopify app technikai működését írja le fejlesztői nézőpontból. A célja nem csak az, hogy felsorolja az egyes modulokat, hanem hogy érthetően végigvezesse, hogyan áll össze a rendszer, milyen adatfolyamok futnak benne, milyen külső függőségei vannak, és mely pontokon kell óvatosan hozzányúlni.

## Tartalomjegyzék
1. [Áttekintés](#1-attekintes)
2. [A rendszer fő részei](#2-a-rendszer-fo-reszei)
3. [Projektstruktúra](#3-projektstruktura)
4. [Adatmodell és tartós állapot](#4-adatmodell-es-tartos-allapot)
5. [Admin felület működése](#5-admin-felulet-mukodese)
6. [Theme extension és Fogyasztó Barát widget](#6-theme-extension-es-fogyaszto-barat-widget)
7. [Checkout és köszönő oldali értékelés](#7-checkout-es-koszono-oldali-ertekeles)
8. [ÁSZF és adatkezelési oldalak kezelése](#8-aszf-es-adatkezelesi-oldalak-kezelese)
9. [Szabályzat (policy) frissítés](#9-szabalyzat-policy-frissites)
10. [Távoli refresh endpoint](#10-tavoli-refresh-endpoint)
11. [Adatfolyamok](#11-adatfolyamok)
12. [Fogyasztó Barát integráció](#12-fogyaszto-barat-integracio)
13. [Környezeti változók és jogosultságok](#13-kornyezeti-valtozok-es-jogosultsagok)
14. [Migrációk és szinkronok](#14-migraciok-es-szinkronok)
15. [Hibakeresés](#15-hibakereses)
16. [Amit az app nem automatizál](#16-amit-az-app-nem-automatizal)
17. [Ismert korlátok és kockázatok](#17-ismert-korlatok-es-kockazatok)

## 1. Áttekintés

Az app három, egymással összefüggő területet kezel. Az első a Fogyasztó Barát widget megjelenítése a storefronton. A második a köszönő oldali értékelési blokk, amely Shopify checkout extensionként működik. A harmadik a jogi tartalmak kezelése, ideértve a normál Shopify oldalakba beszúrt Multifunkciós kódot, valamint a Shopify checkout alján linkelt szabályzat (policy) felugró ablakok tartalmának frissítését.

Technikai szempontból az app egy React Router alapú embedded Shopify admin app, Prisma alapú adattárolással. A Shopify felé Admin GraphQL hívásokat használ, a Fogyasztó Barát rendszer felé pedig saját hitelesített HTTP integrációt.

## 2. A rendszer fő részei

### 2.1. Admin alkalmazás

Az admin felület a merchant számára biztosítja a teljes beállítási felületet. Itt történik a Widget ID megadása, az előfizetés ellenőrzése, a Fogyasztó Barát widget és az értékelés engedélyezése, valamint az ÁSZF és adatkezelési oldalak kiválasztása. Ugyaninnen érhetők el a manuális szabályzat (policy) frissítő gombok is.

### 2.2. Theme extension

A storefronton megjelenő Fogyasztó Barát widget theme extensionként működik. Az admin oldali kapcsoló csak az app oldali állapotot kezeli; a tényleges megjelenéshez a merchantnak a Theme Editorban is engedélyeznie kell az app embedet.

### 2.3. Checkout extension

A köszönő oldali értékelés Shopify checkout UI extensionként jelenik meg. Ez nem a klasszikus Fogyasztó Barát widget, hanem egy Shopify-kompatibilis blokk, amely a vásárlót egy külön értékelő oldalra irányítja.

### 2.4. Szabályzat (policy) frissítő réteg

Az app képes a Shopify `TERMS_OF_SERVICE`, `PRIVACY_POLICY` és `REFUND_POLICY` tartalmát a Fogyasztó Barátból származó HTML alapján frissíteni. Ez elérhető manuálisan az adminból és szerver-szerver módon egy külön refresh endpointon keresztül is.

## 3. Projektstruktúra

Az app fő működése néhány központi fájl köré szerveződik.

- [app/routes/app._index.jsx](/c:/Users/csord/Documents/Codex%20projects/fbarat-app/app/routes/app._index.jsx)
  A fő admin route. Itt van a loader, az action és a teljes admin UI.
- [app/routes/api.policies.refresh.jsx](/c:/Users/csord/Documents/Codex%20projects/fbarat-app/app/routes/api.policies.refresh.jsx)
  A külső, hitelesített szabályzat (policy) refresh endpoint.
- [app/services/policies.server.js](/c:/Users/csord/Documents/Codex%20projects/fbarat-app/app/services/policies.server.js)
  A távoli HTML lekérését és a Shopify szabályzat (policy) frissítést végző szerver oldali helper réteg.
- [app/shopify.server.js](/c:/Users/csord/Documents/Codex%20projects/fbarat-app/app/shopify.server.js)
  A Shopify app konfiguráció, autentikáció és admin context kezelés központi pontja.
- [app/db.server.js](/c:/Users/csord/Documents/Codex%20projects/fbarat-app/app/db.server.js)
  Prisma kliens.
- [prisma/schema.prisma](/c:/Users/csord/Documents/Codex%20projects/fbarat-app/prisma/schema.prisma)
  Az adatmodell, különösen a `Session` és `AppSettings` táblák leírása.

Az extensionök külön könyvtárban élnek:

- [extensions/fbarat-widget](/c:/Users/csord/Documents/Codex%20projects/fbarat-app/extensions/fbarat-widget)
- [extensions/fbarat-rating](/c:/Users/csord/Documents/Codex%20projects/fbarat-app/extensions/fbarat-rating)

## 4. Adatmodell és tartós állapot

### 4.1. `Session`

A `Session` tábla a Shopify OAuth sessionöket és különösen az offline access tokent tárolja. A távoli refresh endpoint működése ettől függ, mert a Shopify Admin API hívásokat a megfelelő shophoz tartozó session alapján tudjuk végrehajtani.

A legfontosabb mezők a `shop`, az `accessToken` és az `isOnline`. Távoli, user nélküli háttérműveletekhez az offline session a lényeges.

### 4.2. `AppSettings`

Az `AppSettings` tábla tartalmazza a shophoz kapcsolódó Fogyasztó Barát beállításokat. Ide kerül a `widgetId`, a widget és rating kapcsolók állapota, az ÁSZF és adatkezelési oldalak azonosítója, valamint a storefronttal kapcsolatos segédmezők.

A jelenlegi logika szempontjából fontos mezők:

- `shopDomain`
- `storefrontUrl`
- `normalizedStorefrontHost`
- `widgetId`
- `widgetEnabled`
- `ratingEnabled`
- `termsPageEnabled`
- `privacyPageEnabled`
- `termsPageId`
- `privacyPageId`

A `storefrontUrl` és a `normalizedStorefrontHost` nem ugyanarra a célra szolgálnak. A `normalizedStorefrontHost` a távoli refresh lookuphoz kell, míg a `storefrontUrl` elsődlegesen a Fogyasztó Barát HTML végpont felé küldött `Origin` és `Referer` headerhez használatos.

## 5. Admin felület működése

Az admin route két nagy részre osztható: loader és action.

### 5.1. Loader

A loader autentikálja a Shopify admin requestet, lekéri a shop aktuális storefront URL-jét, betölti a mentett app settingset, lekéri az oldalválasztókhoz szükséges Shopify oldalakat, lefuttatja az előfizetés-ellenőrzést, és előkészíti a UI-hoz szükséges linkeket és állapotokat.

Itt történik a storefront adatok részleges szinkronja is. Ha az élő Shopify primary domain eltér a mentett storefront adattól, a loader frissíti a kapcsolódó mezőket.

### 5.2. Action

Az action több külön feladatot kezel egy helyen. Ide tartozik a beállítások mentése, a page embed szinkron, a metafield frissítés, valamint a szabályzat (policy) frissítő gombok kezelése is. Emiatt ez a route ma a rendszer egyik központi koordinációs pontja.

### 5.3. UI felosztása

Az admin felület tudatosan külön blokkokra van bontva. A storefronthoz tartozó normál oldalak és a checkout popup szabályzatok külön kezelést kapnak, mert más a céljuk, más a technikai működésük és más hibák érinthetik őket.

## 6. Theme extension és Fogyasztó Barát widget

A Fogyasztó Barát widget storefront oldali megjelenítése theme extensionön keresztül történik. Az admin felületen bekapcsolt widget állapot önmagában nem elég. A merchantnak a Theme Editorban is aktívvá kell tennie az app embedet, különben a widget nem jelenik meg.

A rendszer több ponton is támaszkodik a mentett `widgetId`-re. Ez az azonosító megy a Fogyasztó Barát irányába az előfizetés-ellenőrzéshez, és ez kell a Multifunkciós kódhoz, valamint a szabályzat (policy) HTML lekéréséhez is.

## 7. Checkout és köszönő oldali értékelés

A Shopify checkout és köszönő oldal korlátozott környezet, ezért itt nem ugyanaz a megjelenítési modell használható, mint a storefronton. A klasszikus Fogyasztó Barát widget helyett egy Shopify-kompatibilis extension blokk jelenik meg, amely CTA gombbal vezeti át a felhasználót az értékelő oldalra.

Ez fontos termékoldali korlát, nem implementációs hiányosság. Ha valaki a köszönő oldalon hagyományos widget-viselkedést vár, azt dokumentációban és támogatásban is külön kezelni kell.

## 8. ÁSZF és adatkezelési oldalak kezelése

A normál Shopify oldalakba történő beszúrás marker alapú. Az app nem vakon írja felül az oldal teljes tartalmát, hanem saját markerpárokat használ, és csak a saját blokkját kezeli.

A két markerpár:

- `FBARAT_TERMS_START` és `FBARAT_TERMS_END`
- `FBARAT_PRIVACY_START` és `FBARAT_PRIVACY_END`

Ez a megoldás azért fontos, mert így a merchant egyéb oldal tartalma megmarad, és a script kikapcsolása esetén is csak az app által kezelt rész törlődik. A ténylegesen beszúrt rész a Fogyasztó Barát Multifunkciós kódja, megfelelő `data-id` és `data-type` attribútumokkal.

## 9. Szabályzat (policy) frissítés

Az admin felületen külön blokk kezeli az ÁSZF popupot és külön blokk az adatkezelési popupot. Ez nem csak UX döntés, hanem technikailag is indokolt, mert más Shopify szabályzatokat érintenek.

Az ÁSZF frissítő gomb két célmezőt érint:

- `TERMS_OF_SERVICE`, amely a `?aszf=` végpontról frissül
- `REFUND_POLICY`, amely a `?em=` végpontról frissül

Az adatkezelési gomb a `PRIVACY_POLICY` szabályzatot frissíti a `?at=` végpont alapján.

Privacy esetén van egy fontos Shopify korlát. Ha az adatvédelmi szabályzat automatizált kezelés alatt áll, az app nem tudja felülírni. Ezt a felületen külön hibaüzenettel jelezzük, és a merchantnak a Shopify adminban kell kikapcsolnia az automatizálást.

## 10. Távoli refresh endpoint

Az app külső szerver-szerver refresh útvonala:

- `POST /api/policies/refresh`

Ez az endpoint arra szolgál, hogy a Fogyasztó Barát backend közvetlen merchant beavatkozás nélkül szabályzat (policy) frissítést indíthasson.

### 10.1. Elvárt request

A request kötelező mezői:

- `shop_url`
- `widget_id`
- `action`
- `timestamp`

Kötelező header:

- `X-FB-Signature`

Az engedélyezett actionök:

- `aszf`
- `at`
- `em`
- `aszf_and_em`

### 10.2. Hitelesítés

Az endpoint HMAC SHA-256 aláírást ellenőriz. A signature payload formátuma:

`shop_url|widget_id|action|timestamp`

Az endpoint emellett ellenőrzi a timestamp frissességét, az action típusát, a request metódust és a JSON body jelenlétét is.

### 10.3. Lookup és végrehajtás

Az endpoint csak akkor enged tovább, ha a `widget_id` és a normalizált shop host együtt ugyanarra az `AppSettings` rekordra mutat. Ezután a shophoz tartozó Shopify session alapján Admin API hívásokat tud indítani.

### 10.4. Debug válaszmezők

A response nem csak a frissítés eredményét adja vissza, hanem diagnosztikai mezőket is:

- `stored_storefront_url`
- `live_storefront_url`
- `widget_id`
- `normalized_shop_host`

Ezek célja, hogy domainváltás vagy lookup-probléma esetén a logokból gyorsan látszódjon az eltérés.

### 10.5. Fogyasztó Barát oldali automatikus meghívások

A távoli refresh endpointot nem csak manuális tesztekhez használjuk. A Fogyasztó Barát backend két fontos folyamatból is automatikusan hívja:

- `ajax/public.php`
- `pages/generate-all-docs-ajax.php`

Az `ajax/public.php` közzétételkor fut bele ebbe a folyamatba. A `pages/generate-all-docs-ajax.php` a tömeges dokumentumgenerálásnál érintett. Mindkét esetben az a cél, hogy amikor a Fogyasztó Barát oldalon elkészül vagy frissül egy dokumentum, akkor a Shopify app is megkapja az érintett shopot, widget ID-t és dokumentumtípust, majd a megfelelő Shopify szabályzat (policy) tartalmat frissítse.

Fejlesztői szempontból ez azt jelenti, hogy a `/api/policies/refresh` endpoint szerződését óvatosan kell módosítani. Ha változik a request formátuma, az action / dokumentumtípus kezelése, a HMAC payload vagy a válaszstruktúra, akkor a Fogyasztó Barát oldali PHP hívó kódokat is ellenőrizni kell.

Az automatikus hívások a Fogyasztó Barát oldali adatbázisban az `agrgen_shopify_policy_refresh_logs` táblába is naplózódnak. Ez azért fontos, hogy utólag visszakereshető legyen, mikor melyik shopnál, melyik widget ID-val, milyen dokumentumtípusra indult refresh, milyen HTTP státusszal és milyen válasszal tért vissza a Shopify app.

## 11. Adatfolyamok

### 11.1. Widget ID mentés

A merchant megadja a `Widget ID`-t az admin felületen. Az action elmenti ezt az `AppSettings` rekordba, a loader pedig később ebből dolgozik. Az előfizetés-ellenőrzés és több külső Fogyasztó Barát integráció is erre az értékre épül.

### 11.2. Fogyasztó Barát widget bekapcsolása

Amikor a merchant bekapcsolja a Fogyasztó Barát widgetet, az app elmenti az állapotot és frissíti a kapcsolódó metafield adatokat. Ettől azonban a storefront megjelenés még nem garantált, mert a Theme Editorban külön engedélyezés szükséges.

### 11.3. Köszönő oldali értékelés bekapcsolása

Az értékelés kapcsoló mentése az app oldali állapotot frissíti. A tényleges működéshez a checkout extension blokkot a merchantnak külön hozzá kell adnia a checkout editorban.

### 11.4. ÁSZF vagy adatkezelési oldal mentése

Az action elmenti a kiválasztott oldalak azonosítóját, majd a page body szinkron réteg marker alapú módon frissíti az érintett oldal tartalmát. Bekapcsoláskor beszúr, kikapcsoláskor eltávolít.

### 11.5. Admin gombos szabályzat (policy) frissítés

Az admin gomb megnyomása után az action a `refreshShopPolicies` helperre delegál. A helper lekéri a megfelelő HTML-t a Fogyasztó Barát végpontról, majd Shopify Admin API hívással frissíti a szabályzatot vagy szabályzatokat.

### 11.6. Távoli, szerver-szerver refresh

A Fogyasztó Barát backend hitelesített requestet küld az app endpointjára. Az endpoint ellenőrzi a requestet, lookupolja a shopot, majd ugyanazt a helper logikát hívja, amit az admin gombok is használnak.

## 12. Fogyasztó Barát integráció

Az app több irányból kapcsolódik a Fogyasztó Baráthoz.

Az előfizetés ellenőrzése külön endpointon történik aláírt requesttel. A szabályzat (policy) HTML forrásai a `?aszf=`, `?at=` és `?em=` végpontokról érkeznek. Ezek a hívások a shophoz tartozó storefront URL alapján küldött `Origin` és `Referer` headerre is támaszkodhatnak, ezért a `storefrontUrl` mező szerepe nem csak kényelmi, hanem működési.

## 13. Környezeti változók és jogosultságok

### 13.1. Fontos környezeti változók

Shopify oldal:

- `SHOPIFY_API_KEY`
- `SHOPIFY_API_SECRET`
- `SHOPIFY_APP_URL`
- `SCOPES`

Fogyasztó Barát integráció:

- `FB_SHOPIFY_ELIGIBILITY_SECRET`
- `FB_SHOPIFY_POLICY_REFRESH_SECRET`

### 13.2. Fontos Shopify scope-ok

- `read_content`
- `write_content`
- `write_legal_policies`
- `write_metaobject_definitions`
- `write_metaobjects`
- `write_products`

## 14. Migrációk és szinkronok

Az app működése nem csak adatbázis migrációktól, hanem runtime szinkronoktól is függ. A főbb migrációk között szerepelnek az app settings, page id, policy flag és storefront mezőket bevezető módosítások.

Runtime oldalon fontos, hogy a loader frissíti a storefront adatokat, a mentés upserteli az `AppSettings` rekordot, a page body kezelő réteg pedig marker alapú tartalomfrissítést végez.

## 15. Hibakeresés

### 15.1. A Fogyasztó Barát widget nem jelenik meg

Ilyenkor először nem a theme extension kódot érdemes hibáztatni. Ellenőrizni kell, hogy van-e `Widget ID`, aktív-e az előfizetés, be van-e kapcsolva a Fogyasztó Barát widget az appban, és a Theme Editorban aktív-e az app embed.

### 15.2. A köszönő oldali értékelés nem jelenik meg

Ellenőrizni kell, hogy az értékelés engedélyezett-e, illetve a Shopify checkout editorban ténylegesen felkerült-e a blokk. Ha ez rendben van, utána érdemes extension build vagy deploy irányba vizsgálódni.

### 15.3. Az oldalba beszúrt Multifunkciós kód nem működik

Meg kell nézni, hogy a megfelelő Shopify oldal van-e kiválasztva, a script checkbox aktív-e, a `body` mezőben valóban megjelent-e a markerelt blokk, és a storefronton tényleg ugyanaz az oldal nyílik-e meg.

### 15.4. A szabályzat (policy) frissítés hibázik

Ilyenkor külön kell választani a lookup hibát, a távoli HTML lekérési hibát és a Shopify policy update hibát. Privacy esetén mindig érdemes első körben ellenőrizni, hogy nincs-e automatizált Shopify adatvédelmi kezelés.

### 15.5. A távoli refresh endpoint hibázik

Első körben a route URL-jét, a HMAC payloadot, a secret egyezőségét, a timestampet és a `widget_id + shop_url` párost kell ellenőrizni. Ha a responseban eltér a `stored_storefront_url` és a `live_storefront_url`, akkor domainváltás vagy szinkroncsúszás is szóba kerülhet.

## 16. Amit az app nem automatizál

Az app több dolgot tud, de néhány fontos lépést tudatosan nem automatizál.

Nem kapcsolja be helyetted a Theme Editorban az app embedet. Nem rakja fel helyetted a checkout editorban az értékelési blokkot. Nem hoz létre helyetted Shopify oldalakat az ÁSZF vagy adatkezelés számára. Nem szerkeszti automatikusan a rendelés-visszaigazoló email sablont. Nem tudja automatikusan kikapcsolni a Shopify privacy automatizálást sem.

## 17. Ismert korlátok és kockázatok

Domainváltás esetén átmeneti lookup-probléma előfordulhat, ha a mentett storefront adatok és az élő Shopify adatok között eltérés van. A Shopify privacy automatizálás felülírhatatlansága szintén külső korlát. A köszönő oldalon pedig a Shopify technikai korlátai miatt nem használható a klasszikus Fogyasztó Barát widget.

Az email csatolmány logika is részben külső korlátra épül: az app csak útmutatást ad a `attach_as_pdf` snippethez, de magát az order confirmation sablont nem módosítja automatikusan.
