PhoenixKitBilling.Notifications (PhoenixKitBilling v0.5.2)

Copy Markdown View Source

Billing notifications: who hears about an invoice or a payment, and when.

Sends go through core's notification layer, so each recipient's own per-type preferences and delivery channels (in-app inbox, email, Telegram, digest cadence) apply. This module only decides the audience and the copy.

Recipients

admin_recipients/1 unions three sources, because no single one is complete:

  • holders of the relevant permission key (users_with_permission/1)
  • Owner-role holders, whose access is implicit and who therefore have no permission rows at all
  • holders of the "*" superadmin key, likewise absent from a key-specific query

A resolver that queried only the first would miss the primary operator of a default install — the person most likely to want the notification.

Money copy carries no PII

Notification text names an invoice or order NUMBER and an amount, never a customer name, address or email: a notification lands in someone's inbox and can be routed onward to email or Telegram.

Failure is never fatal

Every send is wrapped. A notification reports a committed fact — a payment that has been recorded, an invoice that has been issued — and must never be able to undo it.

Summary

Functions

Everyone who should hear about billing operations: holders of key, unioned with Owner-role holders and "*" superadmins.

An invoice was issued: tells billing operators, and the customer.

A payment attempt failed.

A payment was recorded against an invoice.

Functions

admin_recipients(key)

Everyone who should hear about billing operations: holders of key, unioned with Owner-role holders and "*" superadmins.

invoice_issued(invoice)

An invoice was issued: tells billing operators, and the customer.

Separate sub-types, so an operator muting the invoice firehose does not also silence their own receipts.

payment_failed(invoice, reason)

A payment attempt failed.

Admin-only: the customer already saw the failure in the checkout flow, and a second channel telling them their card was declined is noise at best. Operators need it, because a failed payment is work.

payment_received(invoice, paid \\ nil)

A payment was recorded against an invoice.

paid is the amount actually recorded. It matters: quoting the invoice total on a PARTIAL payment tells an operator 500 arrived when 50 did. Falls back to the invoice total when a caller has no amount to hand.