Streamlining Subscriptions: Integrating Paddle into Laravel with Filament

The devlog-ist/landing project, a foundational platform, recently underwent a significant upgrade to its billing infrastructure. Our goal was to introduce a robust and flexible subscription management system, moving beyond basic one-time payments to support recurring plans. This involved integrating Paddle as our primary payment gateway, alongside building a comprehensive administration interface using Filament.

The Challenge

Before this integration, managing subscription plans and user billing cycles was a manual, often cumbersome process. We needed a system that could handle various subscription types (free, monthly, annual, lifetime), automate billing, and provide a clear administrative overview. The solution had to be scalable, secure, and developer-friendly, leveraging existing Laravel ecosystem strengths.

Implementing Paddle Cashier

Our journey began with integrating Paddle's billing capabilities through Laravel Cashier. This involved configuring cashier.php to use Paddle as the default driver and extending our database schema with several new tables: customers, subscriptions, subscription_items, and transactions. These migrations provided the necessary structure to store detailed billing information, tying user accounts directly to their Paddle subscriptions.

// config/cashier.php
'driver' => env('CASHIER_DRIVER', 'paddle'),
'paddle' => [
    'vendor_id' => env('PADDLE_VENDOR_ID'),
    'vendor_auth_code' => env('PADDLE_VENDOR_AUTH_CODE'),
    'public_key' => env('PADDLE_PUBLIC_KEY'),
    'sandbox' => env('PADDLE_SANDBOX', true),
    'connect_timeout' => 30,
    'timeout' => 60,
],

This configuration snippet ensures Laravel Cashier communicates correctly with the Paddle API, using environment variables for sensitive credentials and allowing easy toggling between sandbox and live modes.

Admin UI with Filament

To empower administrators, we leveraged Filament to build a dedicated UI for managing subscription plans. This involved creating a PlanResource with associated pages for CreatePlan, ListPlans, and EditPlan. Factories and seeders were developed to populate the database with initial plan data, including free, monthly, annual, and lifetime options, each with specific features and pricing. This centralized management ensures that plan details can be updated dynamically without code changes.

// app/Filament/Resources/PlanResource.php
use Filament\Resources\Resource;
use Filament\Forms;
use Filament\Tables;

class PlanResource extends Resource
{
    protected static ?string $model = App\Models\Plan::class;

    protected static ?string $navigationIcon = 'heroicon-o-currency-dollar';

    public static function form(Forms\Form $form): Forms\Form
    {
        return $form
            ->schema([
                Forms\Components\TextInput::make('name')->required()->maxLength(255),
                Forms\Components\TextInput::make('paddle_product_id')->required()->numeric(),
                // ... other fields like price, features
            ]);
    }

    public static function table(Tables\Table $table): Tables\Table
    {
        return $table
            ->columns([
                Tables\Columns\TextColumn::make('name')->searchable(),
                Tables\Columns\TextColumn::make('price')->money('USD'),
                // ...
            ]);
    }
}

This simplified PlanResource example demonstrates how Filament resources allow for rapid development of administrative interfaces, linking directly to the underlying Plan model.

Testing the Integration

Robust testing was crucial. We developed PlanResourceTest cases to cover the full lifecycle of plan management: creation, editing, deletion, and listing, including checks for tenant access controls. Additionally, UserBillingTest was updated to verify the correct population of Paddle-related columns and the overall functionality of the Cashier integration for users. This rigorous testing ensured both the admin interface and the core billing logic were sound.

The Outcome

By integrating Paddle with Laravel Cashier and providing an intuitive Filament administration panel, the devlog-ist/landing project now boasts a fully functional, flexible, and easily manageable subscription system. Users can select from various plans, and administrators can effortlessly manage these plans, ensuring a seamless experience for both.

Actionable Takeaway

When implementing complex billing systems, combine a powerful billing gateway like Paddle with a robust administration framework like Filament. This approach not only streamlines development but also provides a superior management experience, making your application's monetization strategy both scalable and maintainable. Remember to leverage Laravel Cashier for abstraction and prioritize comprehensive testing for all billing-related workflows to ensure reliability and accuracy.

Streamlining Subscriptions: Integrating Paddle into Laravel with Filament
GERARDO RUIZ

GERARDO RUIZ

Author

Share: