Přeskočit obsah

Obchod (Store) — prodej a pronájem aplikací

Stav: P3 SHIPPED 2026-06-12 (BFF 1c8837e + launcher 0.6.61 de6bf57). Navazuje na handoff app-payments (avax-apps/app-payments-app docs/HANDOFF-JC.md §4) — P1 apps-catalog + P2 entitlements viz 677f0da.

1. Architektura — core-api jako BFF

Ceník, objednávky, platby a fulfillment vlastní app-payments (source of truth pro ceny vč. individuálních slev, schvalování produktů, VS/QR/Comgate, dunning). Její store endpointy jsou M2M-only (scopes payments:store, payments:checkout) — desktop launcher drží jen user JWT a M2M secret mít nesmí. Core-api proto překládá:

launcher / web portál (user JWT)
core-api /store/*  ←─ BFF (routers/store.py + services/store.py)
        │   interní M2M token (create_access_token, client_id
        │   core-api-internal, company_id AVAXIS) — vzor
        │   billable_services forwardu v routers/connectors.py
app-payments kontejner (container_host:container_port z apps registry)
  GET  /v1/store/catalog      POST /v1/orders      GET /v1/orders/{vs}/status

Obě plochy (launcher Obchod teď, web portál F6 později) jsou tencí klienti nad /store/* — portál se přidá bez změny payments kontraktů.

2. Endpointy core-api

Endpoint Auth Popis
GET /store/catalog user JWT (kdokoliv) Schválené produkty (store_visible + approved) s katalogovými cenami. Cache 60 s (in-process).
POST /store/orders company_admin / super_admin Checkout: {items:[{sku,qty,billing_period?}], payment_method_hint?, note?}. company_id/company_name/customer_email doplní server z JWT usera. Vrací {order_id, vs, total, currency, due_date, qr_spd, qr_png_base64, account, card_redirect, instructions_text}.
GET /store/orders/{vs}/status company_admin / super_admin Poll: {status, amount_due, paid_at}.

Error mapping: 4xx od payments propadá s detailem (402 insufficient_credit, 404 neznámé SKU, 422 chybí cena), 5xx → 502, síť/timeout → 503.

3. Flow nákupu (launcher 0.6.61)

  1. AppStoreScreen čte /catalog/public-apps + /store/catalog; produkty se párují na app karty přes app_slug. App s placeným produktem má „💳 Koupit" (+ cenovka) místo free „Přidat do Knihovny". Produkty bez app_slug (credit_topup) → sekce „💰 Kredity a služby".
  2. _PurchaseDialog: varianta (monthly/yearly/one_time dle prices), způsob platby (převod QR / karta) → POST /store/orders.
  3. Platební krok: QR PNG (base64), částka + VS + účet + splatnost, instructions_text, příp. tlačítko card_redirect (otevře prohlížeč).
  4. Poll /store/orders/{vs}/status à 5 s. Po paid → reload obrazovky; entitlement zapisuje payments fulfillment přes M2M (POST /v1/entitlements/grant, P2) → app naskočí jako „✓ V Knihovně". Zavření dialogu nákup neruší (objednávka platí, fulfillment je async).
  5. Store nedostupný → katalog se degraduje na free flow (žádný crash).

E2E ověřeno na avaxdev: order VS 2600000001 (app-vzor.licence monthly, 240.79 CZK s DPH) → manual-payment → paidapp-vzor subscribed: true.

4. Provoz / správa produktů

  • Produkt vznikne v app-payments (POST /products + /prices) nebo automaticky z billable_services v connector.json (draft). Do obchodu se dostane po approve + store-visibility (super_admin, payments UI/API: POST /products/{id}/approve, POST /products/{id}/store-visibility?visible=true).
  • Schvalování cen zůstává v payments (audit + price_trace pohromadě, H4).
  • Dev testovací produkty (avaxdev): app-vzor.licence (id 2), credit.topup-500 (id 3).

5. Známé limity / follow-upy

  • Ownership check status pollu: payments /orders/{vs}/status nevrací company_id → nelze ověřit, že VS patří firmě volajícího. Admin gate pro MVP stačí; doplnit až payments přidá company filtr.
  • QR/účet v dev: payments na avaxdev nemá nakonfigurovaný bankovní účet → qr_png_base64/account jsou prázdné (UI je skrývá). Prod vyžaduje Fio/účet config v payments.
  • Free self-service POST /catalog/{slug}/subscribe zatím není gated proti placeným produktům (UI Koupit ho nenabízí, ale API ano) — zvážit server-side gate „app má placený produkt → subscribe jen přes store".
  • Množství (qty) je v UI fixně 1; payments podporuje libovolné.
  • Web portál (F6): až vznikne, použije stejné /store/* endpointy.

6. Související

  • docs/spec/connector.md — registry, billable_services deklarace
  • backend/app/routers/m2m_platform.py — P1 /v1/apps + P2 entitlements
  • handoff: avax-apps/app-payments-app repo, docs/HANDOFF-JC.md
  • user-guide: docs/user-guide/launcher/nakup-aplikaci.md