Aller au contenu

Intégration Zapier

Extension payante. Un déclencheur Nouvelle soumission sur la place de marché Zapier : on choisit un formulaire dans un menu, et chaque réponse part vers le Zap. Six mille services s’y branchent sans écrire une ligne.

Ce document décrit ce que le module garantit et ce qu’il refuse. Le guide utilisateur en donne la version courte, dans la section « Brancher un formulaire sur Zapier ».

Ce que Zapier ajoute au webhook

Rien, techniquement : les deux envoient un JSON signé à une adresse. Le webhook générique reste le repli, et il reste le bon outil pour un service maison.

Ce que Zapier apporte tient à qui s’en sert. On choisit un formulaire dans un menu plutôt que de coller une adresse, on voit les champs disponibles avant d’avoir reçu quoi que ce soit, et l’on branche Google Sheets, Notion, Slack ou un CRM sans rien configurer d’autre. Le webhook demande de savoir ce qu’est un crochet HTTP ; celui-ci non.

L’abonnement vient de Zapier, le reste vient du site

C’est le partage qui commande tout le module.

Zapier décide où livrer. Il crée un abonnement quand on allume un Zap, le supprime quand on l’éteint. Ces lignes ne sont donc jamais écrites par un administrateur, et c’est pourquoi elles vivent dans une table plutôt que dans les réglages JSON du formulaire : ce document aurait été écrit à deux mains — l’écran du constructeur et une requête HTTP — avec la perte de l’une des deux au premier croisement.

Le site décide si et quoi. L’interrupteur du formulaire, la condition d’envoi et la liste des champs vivent dans le constructeur.

Le partage n’est pas arbitraire. Un réglage qui vit dans Zapier est modifiable par qui a accès au compte Zapier ; la donnée, elle, est au site. Ce qui la restreint doit y être aussi.

Souscrire deux fois n’abonne qu’une fois

Zapier réémet une souscription dès qu’il n’est pas certain que la première a abouti — une coupure réseau au mauvais moment suffit. La clé unique (form_id, empreinte de l'adresse) rend le doublon impossible, et la route rend l’abonnement déjà en place plutôt qu’une erreur : du point de vue de Zapier la demande est satisfaite, et elle l’est.

Sans cela, un même Zap aurait reçu deux fois chaque soumission.

L’exemple est fabriqué, jamais prélevé

C’est la décision centrale de ce module.

Quand on construit un Zap, Zapier affiche un élément d’exemple pour qu’on associe les colonnes. La façon évidente de le fournir est de rendre la dernière soumission reçue. Elle est aussi la pire : cet exemple est conservé dans la configuration du Zap, visible par tous ceux qui y ont accès, exporté avec lui, et il y reste quand la soumission est effacée du site.

Une demande de devis contenant un nom, un téléphone et un message se retrouverait ainsi recopiée dans un service tiers, hors de toute purge RGPD, parce que quelqu’un a cliqué sur « Tester le déclencheur ».

L’exemple est donc bâti depuis la définition des champs : leur identifiant, leur libellé, et une valeur de démonstration choisie d’après leur type. Il a exactement la forme d’une vraie livraison — ce qui suffit à associer des colonnes — et il ne contient la donnée de personne.

Il suit la liste blanche : un champ qui ne sortira pas n’apparaît pas dans l’exemple. Sans quoi on associerait une colonne qui resterait éternellement vide, et l’on chercherait l’erreur du mauvais côté.

La liste blanche

Vide, elle laisse sortir tous les champs non sensibles — exactement ce que fait le webhook générique, vers une adresse elle aussi choisie par le site. Imposer une liste ferait d’un Zapier fraîchement activé une intégration qui n’envoie rien, et qu’on croirait cassée.

Elle existe pour le cas où le Zap mène ailleurs que chez soi : un tableur partagé, un prestataire. Cocher trois champs est alors un geste, et c’est le bon moment pour le faire.

Quatre types ne sortent jamais, quoi qu’on coche : mot de passe, paiement, fichier et signature. Les deux premiers parce qu’ils sont écartés en amont par la mise en forme des valeurs, comme pour les courriels et les exports. Les deux autres parce qu’une adresse de téléversement est un accès permanent : la coller dans un Zap la recopierait dans un service tiers, hors de toute expiration.

Un champ retiré du formulaire quitte la liste de lui-même. Sans ce filtrage, une liste devenue entièrement obsolète se comporterait comme une liste non vide, et le Zap cesserait de recevoir quoi que ce soit sans que rien ne l’explique.

La condition d’envoi

La même structure que la logique d’affichage d’un champ et que l’envoi conditionnel d’une notification, évaluée par le même code. Trois mécanismes de condition pour trois usages auraient donné trois comportements à expliquer, et deux à corriger le jour où le premier se révèle fautif.

Une condition absente laisse passer : c’est le cas courant, et exiger une règle pour livrer ferait d’un Zapier fraîchement allumé une intégration muette.

La livraison

Asynchrone. Appeler Zapier pendant la soumission ferait patienter le visiteur le temps d’un aller-retour réseau qu’il n’a pas demandé. La soumission est déjà enregistrée à ce stade : rien ne justifie de lui adosser le sort d’un tiers.

Une tâche par abonnement. Un formulaire peut alimenter trois Zaps. Les livrer ensemble ferait dépendre les deux derniers du sort du premier : un Zap en panne retarderait les autres de son délai d’expiration, et une reprise les rejouerait tous les trois — dont deux qui avaient abouti.

La tâche ne porte que des rangs. La charge utile est recomposée au moment de l’envoi. Recopier des valeurs de soumission dans la table des tâches planifiées en ferait une seconde copie des données personnelles, qui survivrait à l’effacement de la première.

Tout est revérifié à l’envoi. Le réglage a pu être éteint, le champ retiré de la liste, la soumission mise à la corbeille entre la planification et le passage du planificateur — quelques minutes, parfois une demi-heure sur une troisième tentative. Ce qui était vrai à la soumission ne l’est plus nécessairement, et une livraison part vers un tiers : on relit.

La déduplication

Chaque livraison porte un identifiant slf-<abonnement>-<soumission>. Zapier dédoublonne sur cette clé : deux livraisons portant le même identifiant ne déclenchent qu’un Zap.

Il ne dépend ni de l’heure ni du rang de la tentative. Une troisième tentative porte donc le même identifiant que la première, ce qui est tout l’intérêt : une reprise après panne réseau ne crée pas de seconde facture, de second courriel ni de seconde ligne de tableur.

La reprise

La même règle que le webhook : trois tentatives, espacées d’une minute, cinq puis trente. Une panne réseau, une indisponibilité ou une limitation de débit sont rejouées ; une requête refusée pour son contenu ne l’est pas — elle ne le serait pas davantage à la troisième tentative.

Un Zap éteint se désabonne lui-même

Zapier répond 410 Gone sur l’adresse d’un Zap arrêté. C’est la convention de son protocole de crochets, et elle est utile : sans elle, un Zap éteint le premier jour continuerait de recevoir des livraisons jusqu’à ce que quelqu’un pense à nettoyer la table. L’abonnement est donc supprimé, et la reprise annulée.

La signature

Horodatage et HMAC-SHA256 de « horodatage.corps », dans un en-tête X-SolisForms-Signature de la forme t=…,v1=…. C’est le schéma du webhook de ce plugin et celui de Stripe : un destinataire déjà outillé pour l’un n’a rien de nouveau à écrire pour l’autre. L’horodatage borne la fenêtre de rejeu.

Le secret n’est pas stocké. Il est dérivé du sel du site et du rang de l’abonnement, et recalculé à chaque envoi. Qui lit la table ne peut donc pas forger de livraison signée, et une rotation du sel invalide d’un coup toutes les signatures en circulation.

C’est une différence avec les autres secrets du projet. Un lien de reprise ou un lien privé de portail sont vérifiés : on compare ce qu’on reçoit à une empreinte, et la base n’a jamais besoin du secret. Celui-ci est produit : il faut la clé pour signer. Le stocker en clair aurait été la solution évidente, et une base lue aurait donné le moyen de forger des livraisons vers tous les Zaps du site.

Nous ne vérifions rien de notre côté : la signature est émise, et c’est Zapier qui la vérifie s’il le souhaite. Aucune comparaison en temps constant n’a donc lieu ici, et en annoncer une décrirait un contrôle qui n’existe pas.

Les droits

L’authentification est celle de WordPress, par mot de passe d’application — dans le cœur depuis la 5.6, propre à une application, révocable depuis la fiche de l’utilisateur sans toucher au mot de passe du compte.

Le plan recommandait OAuth. WordPress n’embarque pas de serveur d’autorisation : l’offrir supposerait d’en écrire un, c’est-à-dire une surface d’authentification de plus à tenir, sur un plugin qui en a déjà assez. Ce qu’OAuth aurait apporté est un consentement par portée — « ce Zap peut lire ce formulaire, et lui seul ». Ici la portée est celle du compte : c’est écrit plutôt que tu, et c’est la raison pour laquelle on recommande un compte dédié à l’automatisation.

Chaque route exige deux contrôles : la capacité de consultation des soumissions, et l’accès au formulaire visé. La première seule laisserait un gestionnaire de ses propres formulaires abonner un Zap au formulaire d’autrui, en changeant un chiffre dans la requête.

Le désabonnement exige en plus d’être le propriétaire de l’abonnement. Sans ce contrôle, un rang deviné éteindrait le Zap de quelqu’un d’autre — et rien ne le signalerait, puisqu’un Zap éteint se tait.

Un abonnement vaut par le droit de celui qui l’a créé : le compte supprimé, la ligne part avec lui. WordPress réattribue les identifiants, et un abonnement orphelin livrerait au nom du prochain inscrit.

La limite de débit

Trente abonnements par heure et par compte. Elle porte sur la souscription, qui s’appelle depuis l’extérieur et écrit une ligne — pas sur la livraison, qui part de chez nous. Sans borne, une boucle mal réglée chez un tiers remplirait la table.

Le journal

Chaque livraison est consignée dans le journal des envois de la soumission, au même titre qu’un courriel ou un webhook, avec son code HTTP, le rang de la tentative et la réponse reçue. Il se lit sur l’écran de détail de la soumission.

Le client Zapier

Il vit dans zapier-app/ et n’est pas livré avec le plugin : Zapier héberge les clients de sa place de marché. Trois fichiers — l’authentification, le déclencheur, le menu des formulaires — et aucune logique métier, qui est côté WordPress, où vit la donnée.

Les routes

GET    /wp-json/solis-forms/v1/zapier/forms
POST   /wp-json/solis-forms/v1/zapier/subscriptions      { form_id, target_url }
DELETE /wp-json/solis-forms/v1/zapier/subscriptions/<id>
GET    /wp-json/solis-forms/v1/zapier/sample?form_id=<id>

Ce que la V1 ne fait pas

  • Pas d’action Zapier : rien ne vient modifier une entrée ni en créer une depuis Zapier. Le déclencheur va dans un sens.
  • Pas de recherche d’entrée, pas de transfert de fichiers.
  • Pas d’événement autre que la création : le paiement et la modération viendront comme déclencheurs distincts, non comme variantes de celui-ci.
  • Pas de route de simple réception d’URL : le webhook générique la couvre déjà.