3DIS PAYMENT — Configuration et vérification des webhooks Stripe
Documentation de développement — 30 septembre 2026

1. Choisir le compte et l'environnement

Le webhook doit appartenir au compte Stripe dont les clés API sont enregistrées
dans 3DIS PAYMENT. Le nom commercial affiché par Stripe peut différer du domaine
WordPress : comparer le compte utilisé pour les clés, pas seulement son nom.
Pour la recette, activer Mode test dans Stripe. Ne pas modifier les clés LIVE.
Une destination TEST et une destination LIVE possèdent des secrets distincts.

2. Créer la destination

Stripe > Développeurs > Workbench > Webhooks / Destinations d'événements.
Créer une destination, choisir Votre compte, puis Endpoint webhook.
URL générique : https://VOTRE-SITE/wp-json/3dis-payment/v1/webhooks/stripe
Exemple du site de recette :
https://www.3dis-development.com/wp-json/3dis-payment/v1/webhooks/stripe
Utiliser l'adresse HTTPS canonique du site, avec son éventuel sous-répertoire.
Ne pas utiliser une URL d'administration WordPress ou une page de remerciement.

3. Sélectionner les événements de cette recette

Sélectionner tous les événements des catégories Payment Intent et Subscription
Schedule, et pas seulement created. Ne pas sélectionner tous les événements du
compte. Liste observée dans Stripe lors de cette recette :

payment_intent.amount_capturable_updated
payment_intent.canceled
payment_intent.created
payment_intent.partially_funded
payment_intent.payment_failed
payment_intent.processing
payment_intent.requires_action
payment_intent.succeeded
subscription_schedule.aborted
subscription_schedule.canceled
subscription_schedule.completed
subscription_schedule.created
subscription_schedule.expiring
subscription_schedule.released
subscription_schedule.updated

Depuis dev.3, compléter cette liste avec :
refund.created, refund.updated, refund.failed, charge.refund.updated,
invoice.finalized, invoice.paid, invoice.payment_failed,
invoice.payment_action_required, invoice.voided, invoice.marked_uncollectible,
customer.subscription.created, customer.subscription.updated,
customer.subscription.deleted, customer.subscription.paused,
customer.subscription.resumed.
Ces 30 événements sont enregistrés sur la destination TEST le 30 septembre 2026.
Cette configuration ne vaut pas validation de tous les scénarios de facturation.
Le format attendu contient data.object (événement snapshot), pas uniquement une
notification thin. Noter la version d'API de la destination et la valider pendant
la recette ; elle est distincte de la version des requêtes API sortantes.

4. Raccorder le secret dans WordPress

Dans le détail de la destination Stripe, afficher la clé secrète de signature.
Elle commence par whsec_. Copier cette valeur directement dans :
WordPress > 3DIS PAYMENT > Stripe > Stripe TEST > Webhook Signing Secret.
Enregistrer les modifications. Recharger la page : le champ doit indiquer
Configuré — laisser vide pour conserver. Le champ vide après sauvegarde ne
signifie donc pas que le secret a été effacé ; vérifier son indicateur.
Ne pas confondre whsec_ avec la clé API secrète sk_ ou la clé publique pk_.
Ne pas placer ces secrets dans les URL, captures publiques, journaux ou messages.

5. Vérifier la réception

Créer un paiement de test identifiable une fois le parcours prêt, puis consulter
Stripe > destination > Événements envoyés. Vérifier la réponse HTTP et retrouver
le paiement dans WordPress avec le même montant, la même devise et le même état.
Un code 2xx seul ne prouve pas l'association : un événement sans transaction
locale peut être reçu mais non rattaché (202). Aucun événement envoyé ne constitue
pas une preuve de fonctionnement. Ne pas effectuer de débit réel pour cette recette.

En cas de signature refusée : vérifier compte, TEST/LIVE, secret de cette
destination, horloge serveur et absence de modification du corps HTTP.
En cas de 404 : vérifier activation du plugin, URL REST et permaliens.
En cas de 403 : vérifier protections serveur/pare-feu sans désactiver globalement
la sécurité ; la signature Stripe doit toujours être vérifiée.
En cas de délai/5xx : examiner les journaux et le rapprochement avant toute
nouvelle opération financière. Rejouer un événement n'est pas recréer un paiement.

6. Fonctionnement et limites

Le contrôleur vérifie la signature et l'horodatage avant le traitement Billing.
Le traitement relit l'objet auprès de Stripe et contrôle son association au
contrat. Un webhook ne doit pas créer un nouveau débit. Les rejouements ne doivent
pas dupliquer un paiement. La réception HTTP ne dépend pas d'une visite du client
ni de WP-Cron, mais nécessite que le site soit joignable. Les échéances variables
locales utilisent un déclenchement distinct : ne pas confondre ces mécanismes.

Constat de recette du 30/09/2026 (non généralisable aux installations clientes) :
destination TEST active, URL et 30 événements vérifiés ; version webhook
2020-08-27 ; secret TEST enregistré, indicateur Configuré vérifié après rechargement.
Un déclenchement Stripe TEST « stripe trigger payment_intent.succeeded » a créé
un paiement synthétique de 20 USD, sans mouvement réel. Les événements created et
succeeded ont été livrés le 30/09 à 13:40 CEST avec réponse HTTP 202 OK.
Réponse observée : received=true, matched=false. Signature et réception validées ;
absence de rattachement normale pour une donnée créée par la CLI hors WordPress.
Ce contrôle ne valide ni les clés API sortantes ni un parcours marchand complet.
Ce premier contrôle a été effectué avec la version 1.0.1. La recette ultérieure
du 30/09 a installé 1.1.0-dev.4 sur le site pour les profils TEST isolés et validé
un paiement initial, un refus suivi de régularisation et une facture native
d'abonnement. Ces essais ne constituent pas une validation commerciale complète.

Ajout local du 01/10/2026, non encore installé : rapprochement des remboursements
des factures natives via refund.created, refund.updated, refund.failed et
charge.refund.updated. Ces événements sont déjà dans la sélection de recette.
Après vérification de signature, le plugin relit le remboursement, le paiement,
la facture, l'abonnement et l'échéancier auprès de Stripe. Les associations,
le client, la devise et l'environnement doivent correspondre. Seul un
remboursement confirmé succeeded permet d'afficher Partiellement remboursée ou
Remboursée. Un remboursement pending, requires_action, failed ou canceled n'est
pas déclaré réussi. Le montant payé affiché reste le montant brut encaissé.
Une notification rejouée ne crée ni nouvelle facture ni nouvel encaissement.
Les tests SQLite avec transport simulé couvrent cette modification ; la recette
Stripe TEST et MariaDB de cette modification reste à effectuer avant diffusion.

Limites à lever avant commercialisation : les dates natives Stripe doivent
encore être vérifiées pour les souscriptions en fin de mois et les changements
d'heure. Le calcul local depuis l'ancre originale ne prouve pas que l'échéancier
natif, démarré à la date suivante, retrouve le jour 31 après février.

Référence officielle : https://docs.stripe.com/webhooks
