amjadiqbal/filament-billing-console
A Filament billing console for Laravel that adds an admin interface for managing plans, subscriptions, invoices, and payments. It integrates billing dashboards and actions directly into Filament panels, making it easier to oversee customer billing from one place.
Billing Console is a read-only Filament plugin that surfaces Laravel Cashier (Stripe) customers, subscriptions, invoices, payments, MRR, and churn inside an internal Filament panel. It is aimed at support, ops, and developers who need to answer billing questions without opening the Stripe dashboard.
Minimum setup:
Confirm your app meets the supported matrix: PHP 8.2–8.5, Laravel 12/13, Filament 4/5, and Cashier Stripe with its migrations and Stripe keys configured.
Install the package:
composer require amjadiqbal/filament-billing-console
Register the plugin on an internal/admin panel, not a customer-facing panel:
use AmjadIqbal\FilamentBillingConsole\BillingConsolePlugin;
public function panel(Panel $panel): Panel
{
return $panel
// ...
->plugin(BillingConsolePlugin::make());
}
Configure authorization before exposing the panel. The package supports authorizeUsing(), a viewBillingConsole gate, and model policies. A simple gate-based setup:
// AuthServiceProvider
Gate::define('viewBillingConsole', fn (User $user) => $user->hasRole('billing-admin'));
BillingConsolePlugin::make()
->authorizeUsing(fn (User $user) => $user->can('viewBillingConsole'));
Verify the default behaviour in your panel: do not assume the console is locked down until you have tested it with a non-admin user.
Where to look first: the Billing Console menu item in your panel. The customer list is the main entry point; the subscriptions page and dashboard widgets surface MRR, churn, and past-due/unpaid counts.
First practical use case: support triage. Search for a customer by email, open their customer page, confirm their active subscription and latest invoice/payment, and send a receipt or invoice PDF link. If the customer needs an actual change—refund, cancellation, plan swap—use the “Open in Stripe” link, because the console never writes to Stripe.
Keep it on an internal panel. Register the plugin on your admin/staff panel only. Do not enable it on a customer or tenant-facing panel unless you have verified tenancy scoping and authorization thoroughly.
Use gates for broad access, policies for narrower rules. The viewBillingConsole gate is a good fit for “billing staff can see the console.” Use authorizeUsing() when access depends on panel context or custom business rules. If you expose customer records to tenant admins, verify whether model policies are applied to the customer/user model and to Cashier subscriptions; test cross-tenant access explicitly.
Support workflow: search → customer → subscription → invoice. The common day-to-day path is:
Use the filters for retention and dunning work. The subscriptions table filters by status and by “cancelled, still in grace period.” Pair that with the past-due/unpaid counters to prioritise outreach. The dashboard MRR and 30-day churn widgets are useful for a quick operational read, not for finance-grade reporting.
Use “Sync from Stripe” as a recovery tool, not the primary webhook path. If a webhook was missed or a local Cashier record drifted, the sync action stores Stripe’s copy in your Cashier tables using Cashier’s own webhook code. A sensible pattern is:
Treat invoice/payment data as cached API data. Invoices and payments come from the Stripe API and are cached. For support workflows this is usually fine; for “did this charge just succeed?” checks, use “Open in Stripe” or refresh/sync rather than trusting a stale cached list.
Match the Stripe mode to the environment. “Open in Stripe” links use test or live mode based on your configured Stripe key. Ensure staging uses test keys and production uses live keys; otherwise support staff will open the wrong dashboard.
Extend through Filament and the documented authorization hooks. The package is a Filament plugin, so navigation labels, panel placement, and widget/resource customisation should follow Filament plugin/resource conventions. The stable extension points called out in the release are authorizeUsing(), the viewBillingConsole gate, and model policies. Avoid relying on undocumented internals without pinning the package version.
authorizeUsing() callback, or policy is configured.stripe_id, stripe_status, and relevant date columns in your Cashier migrations if you have high volume.ends_at semantics. If your app uses custom cancellation or pause logic, verify that “cancelled, still in grace period” matches your actual entitlement rules.How can I help you explore Laravel packages today?