3DIS PAYMENT — raccordement générique, version 1.1.0
Guide vérifié contre le code au 1er octobre 2026.
Les limites de validation figurent dans le readme et les notes de version.

1. RESPONSABILITÉS
Le marchand définit son formulaire, son contrat commercial, ses tarifs et sa
politique de garantie. PAYMENT conserve un dossier financier et l'autorisation
de paiement ; il ne rédige ni ne signe un contrat juridique.
La source métier fournit le montant de consommation déjà calculé. PAYMENT
contrôle la correspondance client/contrat/période/devise et exécute le paiement.
Une garantie encaissée est un paiement, pas une préautorisation bancaire bloquée.

2. CAPACITÉS DE CETTE INTÉGRATION
Stripe : abonnement fixe, fractionnement avec dernier versement ajusté,
consommation seule ou abonnement plus consommation ; jusqu'à deux paiements
initiaux séparés provenant de sources configurées.
PayPal : abonnement fixe et fractionnement en versements égaux. Les consommations
variables et les paiements initiaux séparés sont refusés par cette intégration.
Cette restriction ne décrit pas toutes les possibilités commerciales de PayPal.
Les intervalles actuellement exposés sont mensuel et annuel.

3. CONFIGURATION UNIQUE PAR SITE ET ENVIRONNEMENT
Configurer le prestataire, ses identifiants et son webhook. TEST/Sandbox et LIVE
sont distincts. Consulter docs/stripe-webhooks.txt et docs/paypal-webhooks.txt.
Ne pas recréer le webhook pour chaque client. Conserver les secrets côté serveur.
Créer et publier un profil récurrent : mode, devise, montant ou source, fréquence,
conditions financières, sources initiales et nombre d'échéances si nécessaire.
La permission manage_3dis_payment est requise pour créer les dossiers.
La permission financière ne remplace pas le contrôle métier du client concerné.

4. CRÉATION D'UN DOSSIER FINANCIER
L'administration propose la création d'un lien de souscription. Un logiciel
marchand peut aussi appeler, en HTTPS avec authentification WordPress autorisée :
POST /wp-json/3dis-payment/v1/billing/contracts
Content-Type: application/json

Exemple fictif (remplacer l'ID de profil par un profil récurrent publié) :
{
  "profile_id": 123,
  "customer_id": "client-001",
  "contract_id": "dossier-001",
  "provider": "stripe",
  "environment": "test",
  "start_at": "2026-10-15 10:00:00",
  "timezone": "Europe/Paris"
}

Le montant ne vient pas du navigateur. Il est relu dans le profil et ses sources
serveur, puis figé dans l'instantané avant acceptation. start_at est une date
locale dans timezone. Les conditions financières proviennent également du profil.
Le corps est limité à 8192 octets. Les références doivent rester stables et uniques.
Ne jamais appeler cet endpoint avec des identifiants marchands depuis le JavaScript
public. Vérifier côté serveur que l'utilisateur peut souscrire le dossier indiqué.

Réponse : contract_uuid, checkout_token, expires_in (86400 secondes), status.
La page contient [3dis_billing_checkout]. Construire son lien personnel :
https://VOTRE-SITE/page/#contract=UUID&access=JETON
Transmettre ce lien uniquement au client concerné, sans le journaliser.
Une page privée exige aussi une connexion WordPress autorisée.
Un nouvel accès généré pour le même dossier invalide l'ancien accès ; il ne doit
pas servir de prétexte à recréer aveuglément une souscription distante incertaine.

5. SOURCE HTTP DES MONTANTS
Configurer une URL HTTPS fixe sans query string, fragment ni identifiants dans
l'URL, et un jeton Bearer. PAYMENT ajoute à sa requête GET les paramètres :
customer_id, contract_id, period, currency.
Il envoie Authorization: Bearer JETON et demande du JSON.
Les redirections sont refusées ; délai 15 secondes, réponse limitée à 65536 octets.
La validation réseau de WordPress reste appliquée. L'URL n'est jamais fournie
par un visiteur. Le service métier doit authentifier et autoriser la demande.

Réponse canonique fictive, après correspondance des noms de champs :
{
  "reference": "consommation-001-2026-10",
  "customer_id": "client-001",
  "contract_id": "dossier-001",
  "period": "2026-10",
  "currency": "EUR",
  "amount_minor": 1750
}

La période doit reprendre EXACTEMENT celle reçue dans la requête ; l'exemple
ne définit pas à lui seul le format de toutes les périodes produites par le moteur.
amount_minor est un entier : 1750 signifie 17,50 EUR, mais 1750 JPY signifie
1750 yens. Zéro est une consommation valide. Si le mode décimal est configuré,
fournir une chaîne exacte telle que "17.50", jamais un nombre flottant ambigu.
Une réponse absente, ambiguë ou étrangère au dossier bloque le prélèvement.
Une indisponibilité de source ne doit jamais être remplacée par un montant zéro.

6. TABLE SQL SUR LE MÊME WORDPRESS
Configurer une source SQL autorisée et la correspondance des colonnes dans le
plugin. Une datatable n'a pas besoin d'un logiciel intermédiaire : ce sont ses
données serveur qui sont lues, pas son HTML ni le contenu fourni par le navigateur.
Si nécessaire, le plugin expose la source SQL configurée par :
GET /wp-json/3dis-payment/v1/billing/sources/IDENTIFIANT/amount
avec les quatre paramètres précédents et une clé Bearer propre à cette source,
ou un utilisateur WordPress disposant de manage_3dis_payment.
Cet endpoint expose un montant, il ne déclenche pas un paiement.
Ne pas exposer une requête SQL libre ou des credentials de base au navigateur.
Une modification de configuration de source après souscription demande un
contrôle administratif : le moteur compare sa révision à celle du dossier.

7. FORMULAIRE CF7 ET ÉCHÉANCES
Voir docs/cf7-recurring.txt pour la balise, l'association au profil et la preuve
limitée au formulaire. Le traitement juridique du formulaire reste au marchand.
Une autorisation ACTIVE n'est pas une preuve d'encaissement. Si une première
échéance est due, sa confirmation financière est nécessaire au parcours CF7.
Les abonnements fixes natifs s'exécutent chez Stripe/PayPal. La collecte variable
Stripe dépend des exécutions WordPress : cron ou rattrapage limité par visite PHP.
Une page entièrement servie depuis un cache ne déclenche pas ce rattrapage.
Voir docs/billing-runtime.txt et docs/billing-recovery.txt pour incidents et reprise.

8. RECETTE ET PUBLICATION
Conserver distincts : approbation, encaissement, webhook livré, rapprochement,
soumission CF7, envoi SMTP et réception du courriel. Aucune de ces preuves ne
remplace les autres. Tester remboursements, rejouements et états terminaux.
Le cycle PayPal mensuel suivant et la fin naturelle n'ont PAS été exécutés dans
la recette actuelle ; leur simulation locale ne constitue pas une preuve distante.
Les rapports RECETTE-DEV9-20261001.md et RECETTE-DEV10-20261001.md donnent les
preuves et limites. Le passage LIVE et sa recette ne sont pas réalisés.
