SEPA direct debit with Stripe

Collect a buyer's SEPA authorization once, reuse that mandate for later debits, then synchronize every Stripe execution into the canonical Ormuz PSP payment before reconciliation.

Business objective

A recurring debit combines two distinct responsibilities: obtain a reusable mandate and execute a payment. The mandate belongs to the Stripe Customer context; each debit is materialized in Ormuz by a psp_payment distinct object carrying amount, currency, and business attachments.

Mandate ≠ payment

A SEPA mandate authorizes a debit rail; it proves neither that a debit was initiated nor that it was collected. Create a new psp_payment for each debit intent.

Mental model

Customer Stripe + mandat actif
psp_payment draft or pending
Trigger SEPA Debit
PaymentIntent Stripe
Synchronisation psp_payment

The Customer and mandate are reusable; the `psp_payment` represents one precise payment intent and remains the Ormuz anchor for its Stripe execution.

The mapping between Ormuz and Stripe objects is durable. The process therefore does not need to carry raw Stripe IDs between steps: Stripe nodes accept typed objects and reuse existing mappings.

Prerequisites

  • A Stripe configuration active and consistent with the Ormuz environment.
  • A buyer company and, for interactive collection, a contact with the required information.
  • A process able to present a User Journey when mandate signature is required.
  • A clear rule for creating the psp_payment : invoice, order, checkout session, or another explicit business basis.

1. Collect or reuse the mandate

Start with stripe.ensure_customer. The node creates the Stripe Customer only when no reusable mapping exists for the company or contact.

Then use stripe.ensure_sepa_debit_mandate for the standard path. It first looks for active mandates: if none exists, it opens a Stripe Elements user action; if exactly one exists, it reuses it without interaction; if several exist, it stops on ambiguity rather than choosing arbitrarily.

NeedNodeBehavior
Reuse when possible, collect when no mandate existsstripe.ensure_sepa_debit_mandateReuses the unique active mandate, collects when none exists, and fails on ambiguity.
Resolve without interactionstripe.resolve_sepa_debit_mandateExplicitly routes zero, one, or several mandate candidates.
Force a new collectionstripe.collect_sepa_debit_mandateCreates a new SetupIntent and suspends the process during signature.
Never silently choose among several mandates

When resolution returns several active mandates, handle the ambiguity in the process. Choosing a mandate is a business decision and must not depend on provider list ordering.

2. Create and then trigger the debit

First create the Ormuz intent with create_psp_payment. Amount, currency, and business basis of the debit are then frozen in a platform.psp_payment in draft status.

Pass this payment, the Customer, and mandate to stripe.trigger_sepa_debit. The node validates mandate consistency, creates or reuses the Stripe PaymentIntent idempotently, and preserves its mapping to the same psp_payment.

The amount comes from Ormuz

The Stripe node does not freely redefine the debit amount: the supplied psp_payment remains the source of truth for the payment intent.

3. Track the result and reconcile

A SEPA direct debit may evolve after creation. Use Stripe events and stripe.sync_psp_payment to reread the PaymentIntent and report authoritative status and amounts back to the psp_payment Ormuz.

When the payment genuinely represents a receipt to apply to an invoice or receivable, then use reconcile_payment or the payment reconciliationjourney. Invoice settlement must not be inferred from provider status alone without creating the corresponding business allocation.

Resume, idempotency, and security

  • Customer : reused through the company's or contact's Stripe mapping.
  • Mandat : reusable while it remains active and compatible with the Customer.
  • PaymentIntent : correlated to the psp_payment to avoid a second debit on resume.
  • Secrets Stripe : values required by the browser must be exposed only during the interaction that consumes them.
  • Replay : place a resume boundary before any interaction that would be dangerous to repeat automatically.

Checklist

  • Resolve the Stripe Customer from an Ormuz object, never from a hard-coded Stripe ID.
  • Reuse an active mandate when one exists and explicitly handle ambiguities.
  • Create a distinct psp_payment for every debit.
  • Trigger the debit from the amount and currency of the Ormuz payment.
  • Synchronize the Stripe result before any business decision depending on final status.
  • Create a payment_allocation when cash must settle an invoice or reduce a receivable.