maartenpaauw/filament-cashier-billing-provider
Installation
Run composer require maartenpaauw/filament-cashier-billing-provider:^3.1.0 and publish the config:
php artisan vendor:publish --provider="MaartenPaauw\FilamentCashierBillingProvider\FilamentCashierBillingProviderServiceProvider"
Register the Provider
Add the provider to your PanelServiceProvider (or AppServiceProvider):
public function panel(Panel $panel): Panel
{
return $panel
->providers([
\MaartenPaauw\FilamentCashierBillingProvider\FilamentCashierBillingProvider::make(),
]);
}
First Use Case: Display Subscription Status
Ensure your User model (or Billable model) uses HasApiTokens and HasBilling traits. Then, add a widget to your Filament dashboard:
use MaartenPaauw\FilamentCashierBillingProvider\Widgets\SubscriptionStatusWidget;
public function widgets(Panel $panel): array
{
return [
SubscriptionStatusWidget::class,
];
}
Subscription Management Use the built-in Resources to manage subscriptions directly in Filament:
use MaartenPaauw\FilamentCashierBillingProvider\Resources\SubscriptionResource;
public function resources(Panel $panel): array
{
return [
SubscriptionResource::class,
];
}
Customizing Subscription Fields
Extend the SubscriptionResource or override fields in your panel:
public function form(Form $form): Form
{
return $form
->schema([
// Custom fields or overrides
TextInput::make('custom_field')->rules(['required']),
// ... other fields
]);
}
Multi-Tenant Billing Leverage Filament’s tenant system to scope billing data:
public function getRelations(): array
{
return [
RelationManager::make('subscriptions')
->for(\MaartenPaauw\FilamentCashierBillingProvider\Models\Subscription::class)
->title('Subscriptions')
->canView(function (User $user) {
return $user->can('viewSubscriptions');
}),
];
}
Webhook Handling Use Filament’s Notifications to display Stripe webhook events:
use MaartenPaauw\FilamentCashierBillingProvider\Notifications\SubscriptionWebhookNotification;
// Trigger in your Stripe webhook controller:
SubscriptionWebhookNotification::dispatch($event);
Sync with Existing Models
If your Billable model isn’t User, configure the provider in config/filament-cashier-billing-provider.php:
'model' => \App\Models\Customer::class,
Localization
Override translations in resources/lang/vendor/filament-cashier-billing-provider:
'subscription_status' => [
'active' => 'Active Subscription',
'canceled' => 'Canceled',
// ...
],
Permissions Use Filament’s Policies to restrict access:
public static function getPages(): array
{
return [
'subscriptions' => [
'view' => 'viewSubscriptions',
'create' => 'createSubscription',
],
];
}
Model Mismatch
Billable model isn’t properly configured with HasApiTokens and HasBilling, the provider will throw errors.use Laravel\Cashier\Billable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class Customer extends Authenticatable implements Billable
{
use HasApiTokens, HasBilling;
}
Stripe Key Configuration
STRIPE_KEY and STRIPE_SECRET in .env will cause silent failures.config/filament-cashier-billing-provider.php:
'stripe' => [
'key' => env('STRIPE_KEY'),
'secret' => env('STRIPE_SECRET'),
],
Webhook Verification
STRIPE_WEBHOOK_SECRET in your webhook endpoint:
$payload = request()->getContent();
$sigHeader = request()->header('Stripe-Signature');
$event = \Stripe\Webhook::constructEvent($payload, $sigHeader, env('STRIPE_WEBHOOK_SECRET'));
Laravel 11 Deprecation
composer require laravel/framework:^13.0
Caching Subscriptions
Billable model:
public function getSubscriptionAttribute()
{
return cache()->remember("subscription-{$this->id}", now()->addHours(1), function () {
return $this->stripe_subscription;
});
}
Log Webhook Events
Enable logging in config/filament-cashier-billing-provider.php:
'logging' => [
'enabled' => true,
'channel' => 'single',
],
Check logs in storage/logs/filament-cashier-billing-provider.log.
Test Mode Use Stripe’s test mode for development:
config(['services.stripe.test_mode' => true]);
Widget Visibility
If the SubscriptionStatusWidget doesn’t appear, ensure:
widgets().viewSubscriptions permission.Custom Widgets Extend the base widget to add functionality:
class CustomSubscriptionWidget extends SubscriptionStatusWidget
{
protected function getHeaderActions(): array
{
return [
Action::make('cancelSubscription')
->action(fn () => $this->cancelSubscription())
->requiresConfirmation(),
];
}
protected function cancelSubscription()
{
$this->user->cancelSubscription();
$this->dispatchBrowserEvent('alert', ['type' => 'success', 'message' => 'Subscription canceled.']);
}
}
Override Resource Classes
Replace the default SubscriptionResource with a custom class:
'resources' => [
'subscription' => \App\Filament\Resources\CustomSubscriptionResource::class,
],
Add Custom Actions Attach actions to subscription records:
public static function getTableActions(): array
{
return [
Action::make('resendInvoice')
->action(function (Subscription $record) {
$record->invoice()->resend();
}),
];
}
Hook into Events Listen for Cashier events to trigger Filament notifications:
use MaartenPaauw\FilamentCashierBillingProvider\Notifications\SubscriptionFailedNotification;
event(new \Laravel\Cashier\Events\SubscriptionFailed($user, $exception));
// Automatically triggers the notification if configured.
How can I help you explore Laravel packages today?