Aller au contenu

Confirmation de collecte — contrat réel de Paiement 2.x

Erratum du 5 novembre 2026

Le guide consommateur présent dans le tag immuable v2.0.0 indique à tort paiement.intent.completed.v1. Le producteur de confirmation et les transports SLY/Events émettent paiement.payment.completed, avec schemaVersion: 1. Aucun alias ou renommage vers paiement.intent.completed.v1 n'existe. Ce constat ne correspond pas à un contrat externe distinct pour la collecte générique.

L'image 2.0.0 et le tag restent inchangés. Cet erratum corrige la documentation ; il n'introduit ni nouvel événement ni nouvelle release runtime. Toute future évolution du nom/schéma requerra son propre contrat de migration. Un consommateur préparé sur le nom erroné doit corriger son filtre avant activation ; aucun fallback acceptant indistinctement plusieurs noms n'est ajouté.

Enveloppe SLY et Events

Le corps SLY de collecte et l'enveloppe IntegrationEventEnvelope du bus portent le même type et le même payload métier. Exemple synthétique, sans identité ni autorité réellement provisionnée :

{
  "eventId": "58e06cb5-2f96-4bfc-af04-4ad91e95566b",
  "eventType": "paiement.payment.completed",
  "schemaVersion": 1,
  "tenantCode": "tenant-exemple",
  "sourceApp": "paiement",
  "occurredAt": "2026-11-05T12:00:00Z",
  "payload": {
    "paymentIntentId": "intention-exemple",
    "paymentAttemptId": "essai-exemple",
    "businessReference": "commande-opaque-exemple",
    "legalEntityId": "beneficiaire-exemple",
    "status": "COMPLETED",
    "amount": 1000,
    "currency": "XOF",
    "paymentMethod": "WAVE",
    "selectedProvider": "PAYTECH",
    "metadata": {}
  },
  "metadata": {"deliveryId": "b19bbec4-e832-4c99-b7a8-a8e0c18c33cb"}
}

Les noms exacts sont paymentIntentId et paymentAttemptId, pas intentId/attemptId. amount est un entier en unités mineures de la devise, pas un prix décimal. metadata à l'intérieur du payload appartient au métier et reste borné/minimisé ; metadata de l'enveloppe appartient au transport. Sur Events, la metadata comporte aussi un requestId et éventuellement la corrélation disponible. Sur SLY, le requestId de tentative est transmis par header ; il change lors d'une nouvelle émission, alors que l'eventId et le deliveryId restent stables.

Le JSON ne prouve pas l'identité : vérifier Auth/SLY ou le contrat de confiance du bus, puis la cohérence source/tenant/bénéficiaire et la commande locale. Refuser les événements non autorisés et les montants/devises/références contradictoires. Dédupliquer l'eventId et enregistrer l'effet métier dans la transaction locale. Le seul retour navigateur n'est jamais une confirmation de collecte.

Destination et route

Aucune route ELISA n'est fournie ou déclarée disponible par Paiement. Pour SLY, le consommateur implémente et sécurise son ingress, puis Ops provisionne sa destination logique dans le scope exact sourceApp|tenantCode|legalEntityId de dynors.paiement.delivery.targets, ou, à partir de 2.0.1, de la collection native DYNORS_PAIEMENT_DELIVERY_COLLECTION_JSON (sources exclusives).

elisa:/api/v1/internal/payment-facts serait une destination explicite possible si ELISA implémente et qualifie cette route. Elle n'est ni une valeur par défaut, ni une route Paiement, ni la preuve d'un raccordement déjà existant. Le processeur envoie un POST via InterAppCallService à l'application logique et au chemin configurés ; il ne découvre/crée pas l'endpoint. Absence de destination configurée = aucun outbox vers cette application, même si le fait financier est persisté.

Pour Events, le topic vaut le type du fait lorsque la destination est dynors-events. Une destination dynors-events:<topic> configure explicitement un autre topic ; elle ne change pas l'eventType de l'enveloppe. Un abonnement au bus et une route SLY sont deux raccordements distincts à qualifier.

Exception explicite Books : books:<chemin> déclenche la projection B02 PAYMENT_SETTLED. Ce contrat comptable distinct ne constitue pas un alias de collecte ELISA. Les sorties HTTPS utilisent l'emballage Webhooks 2 et leur propre contrat de signature : ne pas les confondre avec le corps SLY brut.

État des preuves et adoption ELISA

Sources du tag : PaymentConfirmationEventService.enqueue → PaymentFactStore.emit → PaymentOutboxProcessor.dispatch. Le producteur conserve paiement.payment.completed jusqu'aux transports génériques. Les callbacks provider et leurs contrôles précèdent ce producteur.

Les essais locaux emploient callbacks authentifiés synthétiques, stockage H2, transports simulés et enveloppe Events. Ils démontrent la persistance du nom/payload et la construction de la requête SLY au chemin configuré. Ils ne qualifient ni le vrai SLY, ni le broker partagé, ni un endpoint ELISA, ni un PSP réel. Les preuves PostgreSQL et broker de la release conservent leurs périmètres propres.

La clarification du nom est levée. L'activation ELISA attend toujours son ingress, ses contrôles, la destination provisionnée et la recette réelle de bout en bout, ainsi que les réserves Vault/Auth/PDP/TLS/PSP de la release. Ne pas transformer cet erratum en GO financier.