Charge / payment intent / setup intent write surface.
Ships three public entry points, all exposed on Accrue.Billing via
defdelegate:
charge/3— atomic charge creation with SCA-safe tagged returns. Resolves payment method fromopts[:payment_method]or the customer'sdefault_payment_methodassociation. Returns a typed{:error, %Accrue.Error.NoDefaultPaymentMethod{}}when neither is set — Accrue never silently falls back to the first attached payment method, because doing so can charge the wrong card when a customer has multiple payment methods on file.create_payment_intent/2— thin wrapper withIntentResult.wrap/1on the result.create_setup_intent/2— off-session card-on-file setup.
Every mutation runs inside Accrue.Repo.transact/2 with an
accrue_events row written in the same transaction.
Summary
Functions
Charges a customer a fixed amount of %Accrue.Money{}. Returns
intent_result(Charge.t())
Raising variant of charge/3. Raises Accrue.ActionRequiredError on
{:ok, :requires_action, pi}, re-raises typed errors otherwise.
Thin wrapper over Processor.create_payment_intent/2. Returns
intent_result(map()) so SCA paths surface via
{:ok, :requires_action, pi}.
Raising variant of create_payment_intent/2.
Off-session card-on-file parallel. Creates a SetupIntent with
usage: "off_session" so the resulting PaymentMethod can be charged
off-session later (e.g. subscription renewals with SCA pre-authorized).
Returns intent_result(map()).
Raising variant of create_setup_intent/2.
Functions
@spec charge(Accrue.Billing.Customer.t() | struct(), Accrue.Money.t(), keyword()) :: {:ok, Accrue.Billing.Charge.t()} | {:ok, :requires_action, map()} | {:error, term()}
Charges a customer a fixed amount of %Accrue.Money{}. Returns
intent_result(Charge.t()):
{:ok, %Charge{}}— happy path{:ok, :requires_action, pi}— SCA / 3DS required{:error, %Accrue.Error.NoDefaultPaymentMethod{}}— no PM resolved (typed, loud, pattern-matchable; never silently falls back to "first attached PM"){:error, other}— anything else
Options
:payment_method— processor-side payment method id (e.g."pm_..."). If absent, resolves to the customer'sdefault_payment_methodvia the schema association.:description— charge description (string).:operation_id— deterministic idempotency seed. Defaults toAccrue.Actor.current_operation_id!/0.
@spec charge!(Accrue.Billing.Customer.t() | struct(), Accrue.Money.t(), keyword()) :: Accrue.Billing.Charge.t()
Raising variant of charge/3. Raises Accrue.ActionRequiredError on
{:ok, :requires_action, pi}, re-raises typed errors otherwise.
@spec create_payment_intent( map(), keyword() ) :: {:ok, map()} | {:ok, :requires_action, map()} | {:error, term()}
Thin wrapper over Processor.create_payment_intent/2. Returns
intent_result(map()) so SCA paths surface via
{:ok, :requires_action, pi}.
Raising variant of create_payment_intent/2.
@spec create_setup_intent( Accrue.Billing.Customer.t() | struct(), keyword() ) :: {:ok, map()} | {:ok, :requires_action, map()} | {:error, term()}
Off-session card-on-file parallel. Creates a SetupIntent with
usage: "off_session" so the resulting PaymentMethod can be charged
off-session later (e.g. subscription renewals with SCA pre-authorized).
Returns intent_result(map()).
@spec create_setup_intent!( Accrue.Billing.Customer.t() | struct(), keyword() ) :: map()
Raising variant of create_setup_intent/2.