Table des matières :
- Admin API PrestaShop : périmètre réel, dépendances Symfony et pièges de doc
- Prérequis de dev (PrestaShop 9.x, PHP 8.2/8.3, Node) et règles de sécurité
- Docker Compose : stack de développement reproductible (Nginx + PHP-FPM + DB) + options
- Swagger/OpenAPI avec API Platform : activer, exposer, corriger les URL derrière proxy
- Auth, droits et tests automatisés : valider l’Admin API sans bricoler le BO
- Génération de client et intégration module : OpenAPI Generator, compat et CI
Admin API PrestaShop : périmètre réel, dépendances Symfony et pièges de doc
Quand on parle de PrestaShop Admin API, on parle du socle API exposé côté back-office (gestion catalogue, commandes, etc.) et construit autour de la stack Symfony moderne. Sur PrestaShop 9.x (au moment d’écrire ces lignes, la branche 9.1/9.2 est celle qu’on retrouve le plus en dev), cette API s’appuie généralement sur les composants Symfony 6.4 et un générateur de schéma OpenAPI via API Platform (cf. l’article interne : PrestaShop 9 : nouveautés Symfony 6.4, Hummingbird et API Platform). Le point important : ce n’est pas le Webservice historique (clé API + endpoints XML/JSON) ; les conventions, la sécurité et l’outillage ne sont pas les mêmes.
Ce qui piège le plus souvent en mission, c’est le périmètre réel : “Admin API” ne veut pas dire “100% du back-office en REST”. On a plutôt un socle qui évolue, et des zones qui restent pilotées par des contrôleurs BO “classiques” (ou des endpoints internes non documentés). Deux réflexes utiles avant de promettre une intégration :
- Cartographier les ressources réellement exposées : produits, déclinaisons, catégories, clients, commandes… mais aussi ce qui manque (ou n’est pas stable) selon la version et les modules installés.
- Identifier la part “API Platform” vs “legacy” : certaines routes sont propres à API Platform (docs, openapi, endpoints JSON-LD/JSON), d’autres restent du Symfony/legacy sans schéma OpenAPI fiable.
Si vous avez accès au code, un “audit express” de l’existant vous fait gagner du temps :
- dans
composer.json: repérer la présence/versions d’API Platform et bundles de sécurité (JWT/OAuth2, etc.) ; - dans
config/routes*: chercher les préfixes (/api,/admin-api, etc.) et les imports API Platform ; - dans le code : repérer les
ApiResource/ metadata (attributs PHP) et les serialization groups (c’est souvent la source de champs “manquants” côté Swagger).
Le cœur PrestaShop reste inégal sur deux sujets qui piquent dès qu’on veut faire du dev sérieux : (1) la parité dev/staging/prod est rarement fournie “prête à l’emploi” (les équipes bricolent des VM, puis découvrent les divergences PHP/extensions/FS), et (2) la documentation d’API change plus vite que les projets clients. C’est exactement le type de cas où Docker vaut son poids : pas pour “faire joli”, mais pour figer les versions et rendre reproductibles les bugs (et donc les fixes).
Une définition qui met les choses au clair côté contrat : l’OpenAPI n’est pas “de la doc”, c’est une spécification machine-readable. Le texte de référence de l’OpenAPI Initiative est explicite : « The OpenAPI Specification (OAS) defines a standard, programming language-agnostic interface description for HTTP APIs… » (OpenAPI Initiative, spécification officielle : OpenAPI Specification (GitHub)). À partir de là, Swagger UI n’est qu’un viewer ; votre vérité, c’est le JSON/YAML OpenAPI.
Deux conséquences concrètes en contexte PrestaShop :
- si la spec OpenAPI est incomplète (schémas incomplets, endpoints manquants, auth mal déclarée), Swagger UI sera trompeur ;
- si la spec est bonne mais votre reverse proxy est mal configuré (base URL, headers, HTTPS), Swagger UI affichera des URLs erronées (et on perd du temps à incriminer “l’API”).
Prérequis de dev (PrestaShop 9.x, PHP 8.2/8.3, Node) et règles de sécurité
Contexte versions (recommandation réaliste en 2026) : partez sur PrestaShop 9.x avec PHP 8.2 ou 8.3, MySQL 8 ou MariaDB récent, et une toolchain front (Node) si vous reconstruisez des assets BO/Theme. Sur la question PHP, gardez un œil critique sur les écarts entre “support théorique” et “support testé en conditions” (voir : PrestaShop 9 : versions PHP recommandées et incohérences de documentation). L’objectif ici n’est pas de coller au plus neuf, mais au plus reproductible.
En pratique, si votre objectif est “Admin API + Swagger + tests”, ajoutez à la checklist technique :
- extensions PHP fréquentes côté core + API :
intl,zip,gd,pdo_mysql,opcache,curl,mbstring,xml(les manquantes se traduisent vite en erreurs “à l’installation” ou en 500 sur des endpoints) ; - configuration
php.inicohérente : timezone, memory_limit (en dev, trop bas = erreurs “aléatoires” sur génération d’assets, export, etc.) ; - Node uniquement si vous reconstruisez des assets (selon votre workflow, vous pouvez aussi consommer des assets pré-build).
Côté hygiène, isolez clairement votre environnement : base de données dédiée, volumes Docker nommés (ou bind mounts maîtrisés), et aucune réutilisation d’identifiants réels. En France/UE, c’est aussi une précaution simple vis-à-vis du RGPD : on évite d’embarquer des données clients réelles dans des laptops, des dumps non chiffrés ou des conteneurs “jetables”.
Un Admin API est, par nature, une surface d’attaque plus large qu’un front. Si vous exposez un Swagger UI sur un réseau non maîtrisé, vous facilitez la reconnaissance (endpoints, schémas, paramètres). Vous devriez traiter ce service comme n’importe quelle API interne : auth stricte, firewall, pas de ports “ouverts pour voir”. Pour la stratégie globale, vous pouvez recouper avec : PrestaShop : sécuriser APIs et modules avec SBOM, WAF et CI/CD.
Un minimum de garde-fous “dev” (souvent oubliés) :
- ne publiez pas votre Swagger sur
0.0.0.0sans contrôle d’accès (au pire, limitez au réseau local, ou mettez un basic auth côté proxy) ; - ne logguez pas des tokens (JWT, bearer) en clair dans vos traces applicatives ;
- évitez d’utiliser des emails/numéros réels dans les fixtures (les workflows BO peuvent déclencher des envois si SMTP est branché).
Enfin, l’argument “Docker = simple” est faux si vous ne figez pas vos paramètres. La règle des 12-factor apps sur la parité est encore la meilleure boussole : « Keep development, staging, and production as similar as possible » (12factor, Dev/prod parity : 12factor – Dev/prod parity). En clair : même version PHP, mêmes extensions, même serveur web (ou au moins mêmes headers/proxy), et mêmes contraintes de réseau.
Pour une Admin API, deux écarts dev/prod reviennent en boucle :
- HTTPS (cookies Secure, redirections, génération d’URL dans Swagger/OpenAPI) ;
- reverse proxy (Host, X-Forwarded-*, trusted proxies Symfony).
Docker Compose : stack de développement reproductible (Nginx + PHP-FPM + DB) + options
Une stack de dev orientée Admin API doit prioriser : (1) un PHP-FPM avec extensions compatibles (intl, gd, zip, pdo_mysql…), (2) un reverse proxy (Nginx) qui respecte les headers (X-Forwarded-* si vous êtes derrière Traefik/Caddy), et (3) une base MySQL/MariaDB avec collation/charset cohérents.
Exemple minimal (à adapter à votre repo PrestaShop 9.x). Remarque : ce fichier suppose que vous avez un Dockerfile PHP dans docker/php/ (avec composer) et une conf Nginx dans docker/nginx/default.conf.
services:
nginx:
image: nginx:1.27-alpine
ports:
- "8080:80"
volumes:
- ./:/var/www/html:delegated
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
- php
php:
build:
context: ./docker/php
environment:
APP_ENV: dev
# XDEBUG_MODE: debug,develop
# XDEBUG_CONFIG: client_host=host.docker.internal client_port=9003
volumes:
- ./:/var/www/html:delegated
db:
image: mariadb:11.4
environment:
MARIADB_DATABASE: prestashop
MARIADB_USER: prestashop
MARIADB_PASSWORD: prestashop
MARIADB_ROOT_PASSWORD: root
command: ["--character-set-server=utf8mb4", "--collation-server=utf8mb4_unicode_ci"]
ports:
- "3307:3306"
volumes:
- db-data:/var/lib/mysql
volumes:
db-data:
Trois points qui évitent 80% des tickets “ça marche pas” : (1) UID/GID : si vous êtes sous Linux, alignez l’utilisateur du conteneur PHP avec votre utilisateur hôte, sinon vous allez vous battre avec les permissions sur var/ et cache/. (2) DNS interne Compose : utilisez db comme host (pas 127.0.0.1). (3) extensions PHP : ne “devinez” pas, listez les prérequis du cœur et des modules (intl est souvent oublié, idem pour exif/opcache selon cas).
Deux compléments très concrets, surtout si vous travaillez en équipe (Linux/macOS/Windows) :
depends_onne garantit pas que MariaDB est “prête” : pour éviter les erreurs au premierinstall/bin/console, vous pouvez ajouter unhealthchecksurdbet, côté PHP, attendre la DB (ou relancer l’étape d’installation).- Les bind mounts peuvent être lents sur macOS/Windows : le
:delegatedaide parfois, mais sur un gros PrestaShop, prévoyez du temps pour les caches Symfony et la génération d’assets.
Pour cadrer les variables critiques (et éviter les .env divergents), mettez noir sur blanc ce qui doit être identique dans tous les environnements Docker :
| Élément | Recommandation | Pourquoi (Admin API/Swagger) |
|---|---|---|
| Version PHP | figée (8.2.x ou 8.3.x) | compat extensions + comportements runtime |
| Base URL | stable (http://localhost:8080) | génération des URLs dans Swagger/OpenAPI |
| Charset/Collation DB | utf8mb4 + collation cohérente |
évite bugs sur tri/recherche et migrations |
| Proxy headers | Host + X-Forwarded-* |
URLs et schémas corrects derrière proxy |
| Mode debug | activé en dev uniquement | erreurs API plus lisibles, profiling possible |
Pour aller plus loin (sans surcomplexifier), ajoutez Redis (sessions/cache) et MailHog/Mailpit si vous testez des workflows de back-office. Si vous voulez un Compose plus proche de la prod (TLS, reverse proxy, multi-services), recoupez avec : Docker Compose : orchestrer des services multi-conteneurs en production. Le but n’est pas de “copier une infra prod” sur un laptop, mais d’éviter les écarts qui cassent l’Admin API (URLs générées, cookies sécurisés, CORS).
Swagger/OpenAPI avec API Platform : activer, exposer, corriger les URL derrière proxy
Avec API Platform, l’UI Swagger et la spec OpenAPI sont en général exposées via des routes dédiées (souvent /api/docs pour Swagger UI et un endpoint JSON pour la spec). Ne partez pas du principe que c’est identique sur tous les projets PrestaShop : vérifiez dans votre instance. Le réflexe : lister les routes et filtrer.
docker compose exec php php bin/console debug:router | grep -E "api|docs|openapi|swagger" -i
Astuce utile : une fois la route repérée, validez aussi les URLs réellement générées (notamment si vous êtes derrière un proxy) :
curl -I http://localhost:8080/api/docs || true
Si les routes existent mais que Swagger UI renvoie des 404 sur les assets ou des URLs d’API erronées, vous avez presque toujours un problème de base URL ou de proxy headers. Sous Nginx, assurez-vous d’envoyer X-Forwarded-Proto, Host et X-Forwarded-For, et côté Symfony, configurez trusted_proxies/trusted_headers (sinon Symfony considère que tout est en HTTP et génère des URLs fausses). En dev local, ce symptôme se voit quand Swagger appelle http:// au lieu de https:// (même sans TLS, certains navigateurs bloquent des appels mixtes, et les cookies Secure sont ignorés).
Exemple minimal côté Nginx (idée : ne pas perdre les infos de schéma/host, surtout si vous mettez Traefik/Caddy devant Nginx plus tard) :
location / {
try_files $uri /index.php$is_args$args;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param HTTP_HOST $host;
# Forwarded headers (si vous terminez TLS ailleurs)
fastcgi_param HTTPS $https if_not_empty;
fastcgi_param HTTP_X_FORWARDED_PROTO $scheme;
fastcgi_param HTTP_X_FORWARDED_FOR $proxy_add_x_forwarded_for;
fastcgi_param HTTP_X_FORWARDED_HOST $host;
fastcgi_pass php:9000;
}
Et côté Symfony (principe : déclarer les proxies de confiance, sinon Symfony ignore X-Forwarded-*) :
# config/packages/framework.yaml
framework:
trusted_proxies: '%env(TRUSTED_PROXIES)%'
trusted_headers: ['x-forwarded-for', 'x-forwarded-host', 'x-forwarded-proto', 'x-forwarded-port']
En local, vous pouvez démarrer simplement avec une variable d’environnement large (à restreindre ensuite) :
TRUSTED_PROXIES=127.0.0.1,REMOTE_ADDR
Pour stabiliser le contrat, exportez la spec OpenAPI et versionnez-la (au minimum dans vos artefacts CI). C’est utile pour détecter un breaking change non prévu. Dans API Platform, on peut généralement récupérer le JSON OpenAPI via une route dédiée (varie selon configuration), ou au minimum via un dump depuis Symfony si vous avez le service. À défaut, vous pouvez automatiser un “snapshot” en CI en appelant l’URL de spec et en la comparant (diff). Cette approche est cohérente avec une stratégie de performance/observabilité API (voir : Performance API : index, pagination et pool de connexions).
Dernier point (souvent négligé) : Swagger UI en prod. Même si c’est “pratique”, c’est aussi un inventaire d’API prêt à l’emploi. Sur une boutique exposée, pensez au minimum à :
- désactiver l’UI en production (ou la mettre derrière authentification),
- limiter l’accès réseau (IP allowlist, VPN),
- éviter que la spec expose des exemples réalistes (tokens, IDs significatifs, etc.).
Pour cadrer les risques API (authZ, exposition d’objets, mauvaises configs), une lecture utile est l’OWASP API Security Top 10 (2023) : OWASP API Security
Auth, droits et tests automatisés : valider l’Admin API sans bricoler le BO
Le vrai sujet sur une Admin API PrestaShop n’est pas “comment appeler un endpoint”, c’est comment prouver qu’on est autorisé (authN) et qu’on a les droits (authZ). Ne partez pas du principe que “Swagger = utilisable” : Swagger UI affiche, mais ne garantit pas votre configuration de sécurité. Inspectez la config Symfony :
docker compose exec php php bin/console debug:config security
Cherchez les firewalls liés à l’API (api, admin_api, etc.), les authenticators (JWT, session, OAuth2, token custom), et les règles d’accès. PrestaShop peut mixer des mécanismes (session BO + endpoints API internes). En pratique, si votre firewall API repose sur la session back-office, vous allez devoir gérer cookie + CSRF, ce qui est pénible en tests automatisés. À l’inverse, si vous avez un bearer token (JWT/OAuth2), les tests deviennent beaucoup plus propres (Postman, curl, k6).
Pour éviter de “tester à l’aveugle”, posez une matrice de tests très simple par endpoint critique (catalogue, commandes, stocks). Exemple de grille minimale :
| Cas | Attendu | Ce que ça valide |
|---|---|---|
| sans auth | 401 |
l’endpoint est protégé (authN) |
| auth mais mauvais rôle | 403 |
contrôle de droits (authZ) |
| payload invalide | 400 / 422 |
validation serveur + messages d’erreur |
| succès | 200/201 |
logique métier + sérialisation |
| ressource inexistante | 404 |
gestion des IDs et des erreurs |
Mini-scénario typique côté agence (très fréquent en France sur des stacks e-commerce multi-intervenants) : un développeur branche Swagger, teste “Create product”, obtient 403, conclut “API cassée”. En réalité, dans 80% des cas le problème est ailleurs : rôle Symfony absent, firewall qui matche une route inattendue, cookie SameSite qui ne passe pas à cause d’un changement de domaine, ou un proxy/WAF qui bloque une méthode/charge utile.
Pour tester correctement, traitez vos endpoints comme des contrats : (1) test d’auth (401), (2) test de droits insuffisants (403), (3) test fonctionnel (200/201), (4) test de validation (400/422). C’est exactement l’endroit où les erreurs “403 Forbidden” doivent être diagnostiquées méthodiquement (voir : Erreur 403 Forbidden : causes et dépannage étape par étape). Et oui : un 403 peut venir d’un WAF, d’un reverse proxy, d’un CORS mal configuré, ou juste d’un rôle Symfony.
Un exemple de commande “sans magie” (utile pour isoler Swagger UI vs API réelle) :
curl -i \
-H "Accept: application/json" \
-H "Authorization: Bearer <TOKEN>" \
"http://localhost:8080/api/..."
Si curl fonctionne mais pas Swagger :
- soit Swagger n’envoie pas le bon header (définition de
securitySchemesincorrecte dans la spec), - soit un problème de CORS / cookies / mixed content (cas fréquent si vous forcez HTTPS d’un côté et pas de l’autre),
- soit une base URL mal calculée (proxy headers).
Côté outillage, privilégiez des tests qui tournent dans Docker (mêmes libs, même php.ini), et versionnez un jeu de données minimal (fixtures) au lieu de cliquer dans le BO. Ça rejoint une approche CI/CD propre : SBOM, secrets, tests, etc. (cf. PrestaShop : sécuriser APIs et modules avec SBOM, WAF et CI/CD). Et pour les définitions REST (méthodes HTTP, idempotence, codes), vous pouvez pointer vos juniors vers : Endpoint API : définition, méthodes HTTP et bonnes pratiques REST.
Génération de client et intégration module : OpenAPI Generator, compat et CI
Une fois Swagger/OpenAPI exposé proprement, le gain immédiat c’est la génération de client. L’OpenAPI vous permet de générer du TypeScript (front BO), du PHP (SDK interne), ou même des clients Java/Kotlin si vous avez un SI hétérogène. L’outil le plus courant reste OpenAPI Generator (OpenAPI Generator) ; en CI, vous récupérez la spec depuis votre environnement Docker, vous générez, et vous comparez le diff. Si le diff est “bruyant”, c’est souvent un problème d’ordre des champs ou de descriptions non stables : à corriger côté spec, pas à ignorer.
Pour rendre ça industrialisable (et éviter les “clients générés différents selon la machine”), deux règles simples :
- pinner la version d’OpenAPI Generator (ou du conteneur utilisé en CI) ;
- versionner un fichier de configuration de génération (naming, namespaces/packages, options de sérialisation).
Un workflow CI très pragmatique, même sur un projet PrestaShop “classique” :
- démarrer la stack Docker (ou une instance éphémère en CI),
- récupérer la spec OpenAPI (URL stable),
- générer le client,
- échouer le pipeline si le diff n’est pas attendu (ou exiger une validation explicite via PR).
Dans PrestaShop, l’intégration “propre” se fait souvent via un module qui consomme l’Admin API (ou expose des endpoints complémentaires). Attention au piège classique : générer un client “trop intelligent” qui encode des hypothèses du core (noms de routes, formats de dates, pagination) et qui casse à la mise à jour 9.x.y. Mettez en place un versioning : taggez la spec (ou au minimum hash/artefact), et imposez une compat ascendante dans vos pipelines. Si votre projet implique des flux avec un ERP/PIM, ça se raccorde directement à vos choix d’API-first (voir : PrestaShop intégration ERP PIM : définir la source de vérité et les flux).
Enfin, ne sous-estimez pas le debug : un client généré ne “résout” pas les problèmes d’API, il les rend juste plus visibles. Activez Xdebug en dev quand vous travaillez sur les contrôleurs/DTO/normalizers, et profilez vos endpoints sur un dataset réaliste (pagination, index DB, n+1). Pour la mise en place Xdebug côté conteneurs et IDE, vous avez deux références internes utiles : Xdebug : installer et activer Xdebug 3 pour PHP CLI et web et Xdebug : configurer le débogage PHP dans Visual Studio Code. C’est le combo qui évite de “debugger” une API au var_dump dans des réponses JSON.




