Paiement PSP (psp_payment)

Un psp_payment est l'enregistrement côté Ormuz d'un paiement ayant transité par un prestataire de services de paiement (PSP). Il porte le montant attendu, le montant effectivement encaissé, la méthode de paiement et le statut d'encaissement — et sert de pont entre l'événement provider et les objets financiers de la plateforme.

Rôle

Chaque paiement entrant traité via un PSP — qu'il provienne d'un webhook Stripe, d'un virement bancaire détecté par open banking ou d'un enregistrement manuel — est représenté sous la forme d'un psp_payment. Il documente l'encaissement brut : combien a été reçu, via quelle méthode, et à quelle commande ou créance il se rapporte.

Le psp_payment alimente ensuite le rapprochement : une fois appliqué via reconcile_payment, il met à jour le settlement_status des factures concernées et déclenche le recalcul du receivable de l'acheteur.

Identifiant et structure

Chaque PSP payment porte un identifiant stable préfixé par psp_.

JSON
"psp_payment":{20 items
"object":"psp_payment"
"id":"psp_7e3b9f2a1c4d8e5f"
"merchant_id":"mer_1a2b3c4d5e6f7a8b"
"buyer_id":"cmp_3a8f1d9c2b4e7f6a"
"checkout_session_id":null
"order_id":null
"invoice_id":"inv_4a7b2e9f1c3d8a5e"
"payment_id":null
"basis":"invoice"
"basis_snapshot_at":null
"basis_snapshot_amount":null
"source_reference":"pi_3Nx8kLInvalidExample"
"metadata":{}0 items
"amount":120000
"amount_received":120000
"currency":"eur"
"payment_method":"sepa_debit"
"status":"succeeded"
"created_at":"2026-06-17T12:00:00.000Z"
"updated_at":"2026-06-17T12:05:00.000Z"
}
{
  "object": "psp_payment",
  "id": "psp_7e3b9f2a1c4d8e5f",
  "merchant_id": "mer_1a2b3c4d5e6f7a8b",
  "buyer_id": "cmp_3a8f1d9c2b4e7f6a",
  "checkout_session_id": null,
  "order_id": null,
  "invoice_id": "inv_4a7b2e9f1c3d8a5e",
  "payment_id": null,
  "basis": "invoice",
  "basis_snapshot_at": null,
  "basis_snapshot_amount": null,
  "source_reference": "pi_3Nx8kLInvalidExample",
  "metadata": {},
  "amount": 120000,
  "amount_received": 120000,
  "currency": "eur",
  "payment_method": "sepa_debit",
  "status": "succeeded",
  "created_at": "2026-06-17T12:00:00.000Z",
  "updated_at": "2026-06-17T12:05:00.000Z"
}

Champs

ChampTypeDescription
idstringIdentifiant du PSP payment (préfixe psp_).
objectstringToujours "psp_payment".
merchant_idstringMarchand propriétaire.
buyer_idstring | nullEntreprise acheteuse (cmp_…). Peut être déduit de l'order ou de l'invoice si non fourni explicitement.
checkout_session_idstring | nullSession de paiement associée (cs_…). Optionnel.
typeenumNature de l’intention : payment ou refund.
source_psp_payment_idstring | nullPaiement PSP parent lorsqu’il s’agit d’un remboursement.
amount_refundedintegerMontant des remboursements PSP enfants réussis sur un paiement.
amount_refundableintegerCapacité encore remboursable après remboursements réussis et intentions actives.
reasonstring | nullMotif métier d’une intention de remboursement.
order_idstring | nullCommande associée (ord_…). Requis si basis = "order".
invoice_idstring | nullFacture associée (inv_…). Requis si basis = "invoice".
payment_idstring | nullPaiement plateforme lié (pay_…). Optionnel — établit le pont vers le paiement rapproché.
basisenum | nullBase de rattachement : order, invoice, receivable, ou null.
basis_snapshot_atdatetime | nullHorodatage du snapshot de receivable (requis si basis = "receivable").
basis_snapshot_amountinteger | nullMontant du receivable au moment du snapshot (requis si basis = "receivable").
source_referencestring | nullRéférence provider écrite après création de l’intention, par exemple un PaymentIntent Stripe. Elle est unique par marchand et ne sert plus de clé à la création du draft.
metadataobjectMap plate de scalaires `string | number | boolean`, selon la convention metadata de l’API.
amountintegerMontant total attendu en centimes (> 0).
amount_receivedintegerMontant effectivement encaissé en centimes (≥ 0). Ne peut pas dépasser amount.
currencystringCode devise ISO 4217 en minuscules (ex. eur).
payment_methodstringMéthode de paiement utilisée (ex. manual, sepa_debit, bank_transfer, card).
statusenumStatut : draft, pending, partially_funded, succeeded, failed, cancelled ou disputed.
created_atdatetimeDate de création.
updated_atdatetimeDate de dernière mise à jour.

Statut

Le status décrit le cycle de vie de l'intention de paiement puis son état d'encaissement. Un PSP payment commence normalement en draft : Ormuz a défini l'intention, mais aucun paiement provider n'est encore établi.pending signifie au contraire que le provider a créé ou accepté cette intention et que l'encaissement reste attendu.

StatutContrainte sur amount_receivedDescription
draftamount_received = 0Intention Ormuz créée avant que le provider ait établi le paiement.
pendingamount_received < amountLe provider a établi le paiement ; l’encaissement reste attendu.
partially_funded0 < amount_received < amountMontant partiellement encaissé. Fréquent pour les virements bancaires.
succeededamount_received > 0Paiement entièrement encaissé.
failed—Tentative de paiement échouée.
cancelled—Paiement annulé avant encaissement.
disputed—Litige ouvert (chargeback ou contestation).

Le statut peut être fixé à la création (utile quand le signal PSP est déjà traité) ou mis à jour via POST /v1/psp-payments/:id. Une transition vers un statut différent de pending émet l'événement correspondant.

Base de rattachement

Le champ basis qualifie l'intention commerciale du paiement. Il détermine quels champs de liaison sont requis ou interdits, et fournit du contexte pour le rapprochement.

basisRequisExcluDescription
orderorder_idinvoice_idLe paiement est rattaché à une commande spécifique.
invoiceinvoice_idorder_idLe paiement est rattaché à une facture spécifique.
receivablebasis_snapshot_at, basis_snapshot_amountorder_id, invoice_idLe paiement couvre tout ou partie de la créance ouverte de l'acheteur. Le snapshot capture le receivable au moment de l'initiation.
null——Aucune base déclarée — usage libre.
Cohérence buyer_id et currency Si buyer_id est fourni en même temps qu'un order_id ou invoice_id, il doit correspondre au buyer_id de l'order ou de la facture. La devise doit également correspondre. Si buyer_id est absent, il est déduit automatiquement de l'order ou de la facture.

Idempotence de l’intention et référence provider

Un nouveau psp_payment est d’abord créé comme intention Ormuz au statut draft, sans référence provider. Si une reprise tente de recréer le même draft avant toute exécution externe, Ormuz réutilise l’intention existante lorsque son type, son montant, sa devise et sa clé métier de rattachement sont identiques.

source_reference est renseigné ensuite, lorsque le provider a réellement créé ou identifié son objet. Cette référence est unique par marchand et écrite une seule fois ; elle permet ensuite de corréler les mises à jour et événements provider au même PSP payment. Elle ne remplace pas la déduplication du draft avant l’appel externe.

Remboursements PSP

Un remboursement PSP est lui aussi une intention persistée avant l’appel provider. Le noderefund_psp_payment crée un psp_payment de type refund au statutdraft, lié par source_psp_payment_id à un paiement PSP source déjà réussi. L’extension PSP matérialise ensuite ce remboursement et fait converger son statut avec le provider. Le paiement parent reste succeeded : son champ amount_refunded agrège les remboursements enfants réussis, il n’existe pas de statut parent refunded.

Pour des avoirs, create_credit_note_psp_refunds résout les paiements PSP qui ont réellement financé les factures concernées, réserve la capacité encore remboursable et crée les intentions correspondantes. La création peut rester séparée par avoir ou être agrégée par paiement PSP source selon le besoin du processus.

Une intention active réserve sa part du montant remboursable : deux processus concurrents ne peuvent donc pas engager silencieusement le même montant. L’exécution provider reste une étape explicite, distincte de la création de l’intention Ormuz.

Dans les processus

create_psp_payment

Ce helper crée ou réutilise une intention psp_payment draft à partir de la base métier fournie. Il ne demande pas de source_reference provider à la création : cette référence est attachée plus tard par la capacité qui exécute ou synchronise réellement le paiement.

Paramètres principaux

JSON
{11 items
"company":"platform.company"
"order":"platform.order"
"invoice":"platform.invoice"
"receivable":"platform.receivable"
"checkout_session":"platform.checkout_session"
"amount":120000
"amount_received":120000
"currency":"eur"
"payment_method":"sepa_debit"
"status":"succeeded"
"source_reference":"pi_3Nx8kL"
}
{
  "company": "platform.company",
  "order": "platform.order",
  "invoice": "platform.invoice",
  "receivable": "platform.receivable",
  "checkout_session": "platform.checkout_session",
  "amount": 120000,
  "amount_received": 120000,
  "currency": "eur",
  "payment_method": "sepa_debit",
  "status": "succeeded",
  "source_reference": "pi_3Nx8kL"
}

Sortie

JSON
{1 item
"psp_payment":"platform.psp_payment"
}
{
  "psp_payment": "platform.psp_payment"
}

reconcile_payment

Impute un PSP payment ou un payment bancaire sur une ou plusieurs créances Ormuz selon une proposition d'allocation. Met à jour les statuts des documents et le receivable selon la source reçue.

Paramètres

JSON
{2 items
"payment":"platform.payment | platform.psp_payment"
"receivable_allocation":"common.receivable_allocation"
}
{
  "payment": "platform.payment | platform.psp_payment",
  "receivable_allocation": "common.receivable_allocation"
}

Sortie

JSON
{1 item
"payment_allocation":"platform.payment_allocation"
}
{
  "payment_allocation": "platform.payment_allocation"
}

La receivable_allocation est typiquement produite par le node propose_payment_allocation qui identifie les factures candidates pour un montant et une company donnés.

Nodes Stripe

Plusieurs nodes d'intégration Stripe produisent ou consomment un psp_payment :

NodeRôle
stripe.sync_psp_paymentSynchronise explicitement un PaymentIntent Stripe vers son PSP payment Ormuz. Utile pour forcer un refresh d'état sans attendre le webhook.
stripe.create_bank_transfer_payment_intentCrée ou réutilise un PaymentIntent de virement bancaire à partir d’un PSP payment Ormuz draft, puis fait converger son état avec le provider.
stripe.trigger_sepa_debitDéclenche un prélèvement SEPA à partir d’un PSP payment Ormuz draft et associe durablement le PaymentIntent Stripe à ce paiement.

Événements

ÉvénementDéclencheur
psp_payment.createdLe PSP payment vient d'être créé.
psp_payment.partially_fundedLe statut est passé à partially_funded.
psp_payment.succeededLe statut est passé à succeeded.
psp_payment.failedLe statut est passé à failed.
psp_payment.cancelledLe statut est passé à cancelled.
psp_payment.disputedLe statut est passé à disputed.

Si le PSP payment est créé directement avec un statut autre que pending (ex. succeeded), les deux événements psp_payment.created et psp_payment.succeeded sont émis à la création. Les transitions de statut ultérieures n'émettent que l'événement du nouveau statut.