Phase 3 Plan 06 payment method write surface (BILL-23, BILL-25).
Ships three public entry points, all exposed via defdelegate on
Accrue.Billing:
attach_payment_method/3— attaches a processor-side payment method to a customer, with fingerprint dedup (BILL-23). If an existing PaymentMethod row for the same(customer_id, fingerprint)exists, the processor-side duplicate is detached and the existing row is returned withexisting?: true. A concurrent race that slips past the application-level check hits theaccrue_payment_methods_customer_fingerprint_idxpartial unique index and is rescued viaEcto.ConstraintError.detach_payment_method/2— detaches on the processor and deletes the local row.set_default_payment_method/3— assertspm.customer_id == customer.id(BILL-25, strict attachment check) and raisesAccrue.Error.NotAttachedotherwise. Never silently wires a foreign PM as a customer default.
Summary
Functions
Attaches a processor-side payment method to a customer with fingerprint
dedup (BILL-23). Returns {:ok, %PaymentMethod{}}; the
existing?: true virtual flag is set when dedup hit an existing row.
Raising variant of attach_payment_method/3.
Detaches a payment method from its customer on the processor and deletes the local row in the same transaction.
Raising variant of detach_payment_method/2.
Sets a payment method as the customer's default. Raises
Accrue.Error.NotAttached if pm.customer_id != customer.id (BILL-25
strict attachment check — never silently wires a foreign PM as
default).
Raising variant of set_default_payment_method/3.
Functions
@spec attach_payment_method(Accrue.Billing.Customer.t(), String.t(), keyword()) :: {:ok, Accrue.Billing.PaymentMethod.t()} | {:error, term()}
Attaches a processor-side payment method to a customer with fingerprint
dedup (BILL-23). Returns {:ok, %PaymentMethod{}}; the
existing?: true virtual flag is set when dedup hit an existing row.
@spec attach_payment_method!(Accrue.Billing.Customer.t(), String.t(), keyword()) :: Accrue.Billing.PaymentMethod.t()
Raising variant of attach_payment_method/3.
@spec detach_payment_method( Accrue.Billing.PaymentMethod.t(), keyword() ) :: {:ok, Accrue.Billing.PaymentMethod.t()} | {:error, term()}
Detaches a payment method from its customer on the processor and deletes the local row in the same transaction.
@spec detach_payment_method!( Accrue.Billing.PaymentMethod.t(), keyword() ) :: Accrue.Billing.PaymentMethod.t()
Raising variant of detach_payment_method/2.
@spec set_default_payment_method( Accrue.Billing.Customer.t(), Accrue.Billing.PaymentMethod.t(), keyword() ) :: {:ok, Accrue.Billing.Customer.t()} | {:error, term()}
Sets a payment method as the customer's default. Raises
Accrue.Error.NotAttached if pm.customer_id != customer.id (BILL-25
strict attachment check — never silently wires a foreign PM as
default).
@spec set_default_payment_method!( Accrue.Billing.Customer.t(), Accrue.Billing.PaymentMethod.t(), keyword() ) :: Accrue.Billing.Customer.t()
Raising variant of set_default_payment_method/3.