WordPress
17 juin 2026

Webhook produit PrestaShop vers ERP : fiabiliser sans casser les MAJ

Laptop on a round table showing a multi-panel software dashboard with a large blue Wi‑Fi icon overlay in a green circle.

Le client met un produit en ligne depuis la liste produits de son back-office PrestaShop, l’ERP devrait se synchroniser dans la foulée… et il ne se passe rien. Le webhook existe pourtant, il a été développé, testé, validé. Il fonctionne même très bien — tant qu’on se contente de créer des produits. Le jour où on veut couvrir la vraie vie d’un catalogue (mises à jour, mise en ligne, mise hors ligne), tout se grippe. Ce n’est pas un bug exotique. C’est un classique des flux de synchronisation, et il se règle proprement à condition de remettre à plat le contrat applicatif autour du hook.

Ce que vous allez apprendre :

  • Pourquoi un webhook produit peut « marcher » à la création et être faux dès la première mise à jour
  • Comment diagnostiquer un flux de synchro ERP sans accuser le mauvais coupable
  • Comment refondre le contrat de webhook pour couvrir création et mise à jour
  • Les garde-fous indispensables : volume, opérations en masse, throttling et boucle de synchro

C’est un cas qu’on rencontre souvent en intégration : un module de synchronisation ERP custom relie un PrestaShop à un ERP de type Odoo, et le besoin métier est simple à énoncer. Quand un gestionnaire de catalogue met un produit en ligne ou hors ligne depuis la liste produits du back-office, l’ERP doit être prévenu pour répercuter le changement.

👉 Sur le papier, c’est trivial.
👉 En pratique, le flux livré ne déclenchait la synchro que sur la création initiale.
👉 Tous les changements d’état ultérieurs partaient dans le vide.

Un flux de synchro peut sembler « marcher » très longtemps, simplement parce qu’on ne l’a testé que sur le cas le plus favorable : la création d’un produit tout neuf.

Chez Mintfull, on a repris ce flux, posé le diagnostic, et reconstruit le contrat de webhook. Voici exactement ce qu’on a trouvé et comment on l’a corrigé.

Le besoin réel : synchroniser un changement d’état, pas seulement une création

Reformulons le besoin métier, parce que c’est là que tout se joue. L’équipe catalogue travaille dans la liste produits du back-office. Elle active ou désactive un produit avec le toggle d’état directement dans la liste — sans ouvrir la fiche produit. À chaque bascule, l’ERP doit recevoir l’information pour que le produit apparaisse ou disparaisse côté gestion commerciale.

Autrement dit, l’événement attendu n’est pas « un produit vient d’être créé ». C’est « l’état d’un produit existant vient de changer ». Ce sont deux choses radicalement différentes, et c’est précisément cette nuance que le flux d’origine n’avait jamais intégrée.

Le hook n’était pas le problème

Premier réflexe quand une synchro ne part pas : soupçonner le hook. On a donc vérifié en priorité. Le toggle d’état depuis la liste produits déclenche bien le hook actionObjectProductUpdateAfter. PrestaShop fait son travail, l’événement est émis, le module de synchronisation est appelé.

👉 Le hook se déclenche. Le code de synchro s’exécute. Et pourtant aucun webhook ne part vers l’ERP.

Conclusion immédiate : le problème n’est pas l’accroche dans PrestaShop. Il est dans le contrat applicatif construit autour du hook — la logique qui décide si, quand et comment un webhook est émis. C’est une distinction importante, parce qu’elle évite de partir refaire l’intégration aux hooks alors que tout va bien de ce côté-là.

Le diagnostic : trois défauts qui se cumulent

En lisant le code du module de synchronisation, on a isolé trois défauts. Pris séparément, chacun semble anodin. Ensemble, ils transforment un flux « qui marche » en flux faux dès qu’on sort du cas de la création.

Défaut 1 : un anti-doublon qui bloque toutes les mises à jour

Le module embarquait un mécanisme anti-doublon : il stockait les identifiants des produits déjà traités et refusait d’émettre un webhook pour un produit déjà connu. L’intention était probablement de protéger l’ERP contre des envois redondants pendant une opération d’import.

Sauf que cette logique part d’un postulat faux : qu’un produit ne se synchronise qu’une seule fois dans sa vie. Or un produit existant qu’on met en ligne, puis hors ligne, puis de nouveau en ligne, doit générer un webhook à chaque fois. L’anti-doublon, en mémorisant le produit dès son premier passage, condamnait silencieusement tous les changements d’état ultérieurs.

👉 C’est le cœur du bug : un garde-fou bien intentionné qui empêche le flux de faire exactement ce qu’on attend de lui.

Défaut 2 : tout est émis en product_created

Deuxième défaut, plus insidieux parce qu’il ne « plante » pas : tous les webhooks partaient avec le même type d’événement, product_created. Que le produit vienne d’être créé ou qu’il s’agisse d’une simple modification, l’ERP recevait toujours le même libellé.

Résultat : impossible côté ERP de distinguer une création initiale d’une mise à jour. Si l’anti-doublon n’avait pas déjà bloqué les envois, l’ERP aurait tenté de recréer un produit qui existait déjà à chaque modification. Un contrat de webhook qui ne sait dire qu’une seule chose ne peut pas piloter un cycle de vie qui en comporte plusieurs.

Défaut 3 : le payload n’embarquait pas le champ active

Le troisième défaut est presque ironique. Le besoin, rappelons-le, c’est de synchroniser un changement d’état — donc la valeur du champ active du produit. Et ce champ active était tout simplement absent du payload envoyé à l’ERP.

Le webhook transportait l’identifiant, le nom, le prix… mais pas l’information précise que le toggle en ligne/hors ligne était censé propager. Même si le webhook était parti, l’ERP n’aurait pas su si le produit devait être activé ou désactivé.

Quand le payload n’embarque pas le champ que l’événement est censé propager, le flux ne synchronise pas une donnée : il en synchronise une autre, par accident.

La refonte : un contrat de webhook qui couvre tout le cycle de vie

Une fois les trois défauts posés, la correction devient logique. Il ne s’agit pas de rustiner, mais de redéfinir le contrat de webhook pour qu’il colle au cycle de vie réel d’un produit.

Distinguer création et mise à jour

On garde, si c’est utile côté ERP, une trace de la toute première création — par exemple pour émettre un product_created une seule fois, à la naissance du produit. Mais surtout, on émet un événement product_updated à chaque mise à jour ultérieure. L’ERP reçoit ainsi un signal sémantiquement juste : il sait s’il doit créer une fiche ou en mettre une à jour.

L’anti-doublon, lui, n’est pas supprimé aveuglément : il est repensé. On ne veut plus « ne traiter un produit qu’une fois », mais éventuellement « ne pas émettre deux webhooks strictement identiques dans une fenêtre très courte ». La nuance change tout.

Un payload complet, avec active

Le payload est enrichi pour transporter l’état du produit, active en tête, ainsi que les champs dont l’ERP a besoin pour traiter l’événement sans aller rechercher l’information ailleurs.

// Avant — création déguisée, état manquant
{
  "event": "product_created",
  "product": {
    "id": 4821,
    "name": "...",
    "price": 49.90
  }
}

// Après — événement explicite, état embarqué
{
  "event": "product_updated",
  "product": {
    "id": 4821,
    "name": "...",
    "price": 49.90,
    "active": false
  }
}

👉 L’ERP n’a plus à deviner. Le type d’événement lui dit quoi faire, le champ active lui dit dans quel sens.

Des logs explicites

Enfin, on instrumente le flux avec des logs explicites à chaque étape : événement détecté, type de webhook choisi, payload émis, réponse de l’ERP. Sur un flux de synchro, l’absence de logs lisibles est ce qui rend un défaut comme l’anti-doublon invisible pendant des mois. Conformément à nos standards, aucune exception n’est avalée silencieusement : un échec d’envoi est loggé en error avec l’identifiant produit en contexte.

Les garde-fous : ce qui change quand on émet vraiment à chaque mise à jour

Corriger le flux, c’est bien. Mais passer de « un webhook par produit, une fois » à « un webhook à chaque mise à jour » a des conséquences qu’il faut anticiper, sous peine de remplacer un bug par un autre.

1. La hausse du volume de webhooks

Mécaniquement, on émet beaucoup plus de webhooks qu’avant. Chaque modification de fiche, chaque toggle, chaque ajustement de prix devient un événement. Sur un catalogue actif, on passe d’un ordre de grandeur de quelques centaines d’envois à plusieurs milliers par jour. L’ERP en face doit être dimensionné pour absorber ce volume.

2. Les opérations en masse

Le piège le plus sournois, ce sont les opérations en masse. Une activation groupée de plusieurs centaines de produits depuis la liste produits, un import, une mise à jour de prix sur toute une catégorie : chacun de ces gestes déclenche le hook autant de fois qu’il y a de produits touchés. Sans précaution, c’est une rafale de webhooks émise en quelques secondes.

👉 La parade : un mécanisme de throttling ou une file d’attente. Plutôt que d’émettre en synchrone dans le hook, on empile les événements et on les traite à un rythme maîtrisé. C’est aussi ce qui évite de ralentir le back-office pendant une opération de masse — un point que tout responsable d’un back-office PrestaShop déjà chargé appréciera.

3. La boucle de synchro

Le garde-fou le plus important, et le plus facile à oublier. Si l’ERP, après avoir reçu un webhook, réécrit le produit côté PrestaShop (pour confirmer un état, pousser un stock, corriger un champ), cette écriture déclenche à son tour actionObjectProductUpdateAfter. Qui émet un nouveau webhook. Que l’ERP traite. Qui réécrit le produit. Et ainsi de suite.

Une boucle de synchro ne casse rien immédiatement. Elle sature lentement, jusqu’au jour où le volume de webhooks explose sans raison apparente.

Deux mécanismes complémentaires neutralisent ce risque. D’abord l’idempotence : un événement qui n’apporte aucun changement réel ne doit pas réémettre de webhook. Ensuite un flag de provenance : quand une écriture provient de l’ERP, on la marque pour que le hook sache ne pas la renvoyer à son émetteur. La synchro reste à sens unique pour un même changement, et la boucle est cassée à la racine.

Le plan de validation

Un flux de synchro ne se valide pas en testant uniquement le cas qui posait problème. On a déroulé un plan qui couvre tout le cycle de vie, parce que c’est exactement l’absence de ce plan qui avait laissé passer le bug initial.

  1. Création initiale : un nouveau produit déclenche bien un product_created côté ERP.
  2. Mises à jour depuis la liste BO : le toggle en ligne/hors ligne émet un product_updated avec le bon active — y compris au deuxième, troisième et quatrième passage.
  3. Édition fiche produit : une modification depuis la fiche produit émet elle aussi un product_updated complet.
  4. Vérification des logs : chaque événement laisse une trace lisible, type de webhook et payload inclus.
  5. Réception côté ERP : on confirme que l’ERP reçoit, distingue création et mise à jour, et applique le bon état.

👉 Le test qui compte le plus : basculer le même produit en ligne, puis hors ligne, puis en ligne. C’est exactement ce que l’anti-doublon empêchait, et c’est la preuve que le flux couvre désormais la vraie vie du catalogue.

Notre avis chez Mintfull

Ce genre de flux illustre une vérité un peu inconfortable : un webhook qui « marche » en démo ne prouve rien. La démo teste le cas idéal — un produit neuf, créé une fois. Le catalogue réel, lui, passe son temps à muter : on active, on désactive, on réédite, on réactive.

Le vrai test d’un flux de synchro, ce n’est pas la création. C’est la dixième mise à jour du même produit, six mois après la mise en production.

Ce qui nous frappe à chaque fois, c’est que le hook PrestaShop faisait parfaitement son travail. Tout le problème vivait dans le contrat applicatif : un anti-doublon mal cadré, un type d’événement unique, un payload incomplet. Trois petits choix, posés au moment où seul le cas de la création était en tête, et qui rendent le flux faux dès qu’on couvre la réalité.

👉 La leçon qu’on applique systématiquement : on conçoit un contrat de webhook pour le cycle de vie complet d’une entité, jamais pour son seul premier instant. Et on l’instrumente assez pour qu’un défaut comme celui-là soit visible en lisant les logs, pas en attendant qu’un client signale un produit qui ne remonte pas. C’est la même rigueur de fond que pour une migration vers PrestaShop 9 : ce qui n’est pas mesuré et journalisé finit toujours par dériver.

FAQ : fiabiliser un webhook produit PrestaShop vers un ERP

Pourquoi un webhook qui marche à la création casse-t-il sur les mises à jour ?

Parce qu’on conçoit souvent le flux pour l’événement le plus simple — la création — et qu’on y ajoute des optimisations, comme un anti-doublon, qui supposent qu’un produit ne se synchronise qu’une fois. Dès qu’un produit existant change d’état, ces optimisations se retournent contre le flux et bloquent l’émission du webhook.

Le hook actionObjectProductUpdateAfter est-il fiable pour le toggle d’état ?

Oui. Le toggle en ligne/hors ligne depuis la liste produits déclenche bien ce hook. Si la synchro ne part pas, le problème est presque toujours dans la logique applicative branchée sur le hook — pas dans le hook lui-même. Vérifier d’abord les logs côté module évite de partir refaire l’intégration pour rien.

Comment éviter une boucle de synchro entre PrestaShop et l’ERP ?

Avec deux garde-fous complémentaires : l’idempotence, pour ne pas émettre de webhook quand rien n’a réellement changé, et un flag de provenance, pour qu’une écriture poussée par l’ERP ne soit pas renvoyée à l’ERP. Sans ces deux mécanismes, chaque écriture croisée relance l’autre et le volume de webhooks finit par exploser.

Faut-il émettre les webhooks en synchrone dans le hook ?

Pas sur un catalogue actif. Émettre en synchrone fonctionne tant que le volume est faible, mais une opération en masse — activation groupée, import, mise à jour de prix par catégorie — déclenche une rafale d’envois qui peut ralentir le back-office. Une file d’attente avec throttling lisse la charge et protège à la fois l’ERP et l’expérience back-office.

Conclusion : un contrat de webhook se conçoit pour le cycle de vie, pas pour la démo

Fiabiliser ce flux n’a pas demandé de toucher au hook PrestaShop ni de réinventer l’intégration. Il a fallu remettre à plat le contrat applicatif : distinguer création et mise à jour, embarquer le champ active dans le payload, repenser l’anti-doublon, instrumenter le tout avec des logs explicites.

👉 Le bon ordre des choses :

  1. Distinguer les événements du cycle de vie (création vs mise à jour)
  2. Embarquer dans le payload exactement la donnée que l’événement propage
  3. Protéger le flux du volume, des opérations en masse et des boucles de synchro
  4. Valider sur toute la vie d’un produit, pas seulement sa création

Un flux de synchro fiable, ce n’est pas un flux qui marche le jour de la livraison. C’est un flux qui dit encore la vérité après la centième modification.


Votre synchro PrestaShop vers ERP fonctionne « la plupart du temps » et vous ne savez jamais vraiment ce qui remonte ?

👉 Notre agence PrestaShop conçoit et fiabilise les flux de synchronisation entre PrestaShop et votre ERP : contrat de webhook robuste, garde-fous contre les boucles, file d’attente pour les opérations en masse, et logs qui vous disent enfin ce qui se passe. Une synchro fiable, c’est un catalogue qui dit la même chose des deux côtés.

Nous vous recommandons aussi