# ----------------------------------------------------------------------------- # Fabri-Ka — Agrégateur de produits québécois # Auteur : Simon-Pierre Boucher — contact@spboucher.ai # connectors/wix.py : connecteur générique Wix Stores. # 1) GET /_api/v1/access-tokens -> jeton d'instance public de l'app Wix Stores # 2) GraphQL storefront getFilteredProducts (catalogue complet, paginé) # ----------------------------------------------------------------------------- from __future__ import annotations from ..schema import Product, parse_price from .base import BaseConnector WIX_STORES_APP = "1380b703-ce81-ff05-f115-39571d94dfcd" ALL_PRODUCTS_CATEGORY = "00000000-000000-000000-000000000001" GQL = """query getFilteredProducts($limit:Int!,$offset:Int!){ catalog{category(categoryId:"%s"){numOfProducts productsWithMetaData(limit:$limit,offset:$offset,onlyVisible:true){ list{id name urlPart price comparePrice formattedPrice description media{url} isInStock productType ribbon options{title selections{description}}}}}}}""" % ALL_PRODUCTS_CATEGORY class WixConnector(BaseConnector): platform = "wix" def fetch(self) -> list[Product]: r = self.get(f"{self.base}/_api/v1/access-tokens") apps = r.json().get("apps", {}) inst = (apps.get(WIX_STORES_APP) or {}).get("instance") if not inst: return [] # site Wix sans app Boutique — rien à agréger out: list[Product] = [] offset, total = 0, None while offset < (total if total is not None else 1) and offset < 20000: resp = self.session.post( f"{self.base}/_api/wix-ecommerce-storefront-web/api", headers={"Authorization": inst, "Content-Type": "application/json"}, json={"query": GQL, "variables": {"limit": 100, "offset": offset}}, timeout=self.timeout) resp.raise_for_status() cat = (((resp.json().get("data") or {}).get("catalog") or {}) .get("category") or {}) if total is None: total = int(cat.get("numOfProducts") or 0) if total == 0: break items = ((cat.get("productsWithMetaData") or {}).get("list")) or [] if not items: break for it in items: imgs = [] for m in (it.get("media") or []): u = m.get("url") or "" if u and not u.startswith("http"): u = "https://static.wixstatic.com/media/" + u.lstrip("/") if u: imgs.append(u) price = parse_price(it.get("price")) compare = parse_price(it.get("comparePrice")) out.append(Product( store_id=self.store_id, external_id=str(it.get("id", "")), url=f"{self.base}/product-page/{it.get('urlPart', '')}", title=it.get("name", ""), description=it.get("description", "") or "", price=price, price_max=price, compare_at_price=compare if compare and price and compare > price else None, images=imgs, product_type=it.get("productType", "") or "", tags=[it["ribbon"]] if it.get("ribbon") else [], available=bool(it.get("isInStock", True)), )) offset += 100 return out