Documentation for larsasub v0.12.0.
On an older version? Your release notes ship with the package (CHANGELOG.md).
LarsaSub - Quick Start Guide
A Laravel package for managing SaaS subscriptions with Mollie payment integration and multi-tenant support.
Introduction
LarsaSub provides a complete subscription management system for Laravel applications:
- Subscription plans with flexible durations (monthly, yearly, continuous)
- Introduction pricing periods
- Recurring payments via Mollie
- Multi-tenant support with Mollie Connect (per-tenant payment accounts)
- Dual billing: platform charges tenants AND tenants charge their users
- Application fees on tenant payments
- User and company notifications
- Laravel Nova admin interface (separate
larsasub-novapackage) - Standalone dashboard for users and tenant admins
Requirements
- PHP ^8.3
- Laravel ^12.0 | ^13.0
- Mollie API credentials
Quick Install
1. Install Package
LarsaSub is not on Packagist. Point composer at our repository and authenticate with your license token first — see Installation for the three commands and for CI setup. Without that step this fails with "package not found".
composer require peters-development/larsasub
2. Run Installation
php artisan larsasub:install
This publishes config, runs migrations, and seeds payment methods.
3. Configure User Model
Add the BillableModel interface and IsBillableModel trait to your User model:
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use PetersDevelopment\LarsaSub\Contracts\BillableModel;
use PetersDevelopment\LarsaSub\Traits\IsBillableModel;
class User extends Authenticatable implements BillableModel
{
use IsBillableModel;
public function getBillableNameAttribute(): string
{
return $this->name;
}
public function getBillableEmailAttribute(): string
{
return $this->email;
}
public function getBillableIdentifierAttribute(): string
{
return (string) $this->id;
}
}
Billable intermediary: LarsaSub automatically creates a
Billablerecord (inlarsasub_billables) that links your User/Team model to all billing entities. This happens lazily on first use — no manual setup required.
Subscription convenience methods: To use
$user->activeSubscription(),$user->hasFeature(), etc., also add theHasSubscriptionstrait. The matchingContracts\HasSubscriptionsinterface is optional — nothing in the package type-hints on it — but the trait satisfies it in full, so declare it if your own code wants to accept "anything with subscriptions":use PetersDevelopment\LarsaSub\Contracts\HasSubscriptions as HasSubscriptionsContract; use PetersDevelopment\LarsaSub\Traits\HasSubscriptions; class User extends Authenticatable implements BillableModel, HasSubscriptionsContract { use IsBillableModel, HasSubscriptions; }
4. Configure Environment
Add to your .env file:
# Payment Provider
LARSASUB_PROVIDER=mollie
# Currency
LARSASUB_CURRENCY_DEFAULT=EUR
# Mollie API key
MOLLIE_KEY=test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# Notifications (optional)
LARSASUB_NOTIFICATIONS_SALES=sales@yourcompany.com
LARSASUB_NOTIFICATION_CHANNELS=mail
# Company Notification Toggles (optional)
LARSASUB_NOTIFY_COMPANY_SUBSCRIPTION_ACTIVATED=true
5. Add Mollie Trait (Optional)
For Mollie-specific features (customer management, mandates), add the IsMollieBillableModel trait to your User model:
use PetersDevelopment\LarsaSub\PaymentProviders\Mollie\Traits\IsMollieBillableModel;
class User extends Authenticatable implements BillableModel
{
use IsBillableModel, IsMollieBillableModel;
}
This provides $user->mollieCustomers(), $user->mollieMandates(), and $user->getMollieCustomer().
Billing Modes
Direct Billing (Default)
The User model itself holds subscriptions and is charged directly.
// config/larsasub.php
'billable' => [
'model' => \App\Models\User::class,
'relation' => null, // User IS the billable
],
Indirect Billing (Team/Company)
A related model (Team, Company) holds the subscription. Multiple users can share one subscription.
// config/larsasub.php
'billable' => [
'model' => \App\Models\Team::class,
'relation' => 'team', // $user->team() returns the billable
],
The Team model must implement BillableModel and use IsBillableModel:
class Team extends Model implements BillableModel
{
use IsBillableModel;
public function getBillableNameAttribute(): string
{
return $this->name;
}
public function getBillableEmailAttribute(): string
{
return $this->contact_email;
}
public function getBillableIdentifierAttribute(): string
{
return (string) $this->id;
}
// Optional: define who receives notifications
public function getNotifiableUsers(): Collection
{
return $this->users;
}
}
How Billing Works Internally
LarsaSub uses a Billable intermediary model between your application model and all billing entities:
Your Model (User, Team, Company)
│
└── Billable (larsasub_billables) ← created automatically on first billing operation
├── BillableSubscription ← references billable_id
├── RecurringCharge ← references billable_id
├── SinglePayment ← references billable_id
├── BillableCredit ← references billable_id
└── MollieCustomer ← references billable_id
The IsBillableModel trait provides relation helpers that route through the Billable transparently. The HasSubscriptions trait adds subscription and feature convenience methods on top.
Mollie Connect (Multi-Tenant)
Mollie Connect enables multi-tenant platforms where each tenant has their own Mollie account. Payments go directly to the tenant's account, with optional platform application fees.
Enable Connect Mode
Connect collects payments on behalf of others, which requires a Platform license. Declare it alongside the switch — without the declaration the package refuses to boot. Nothing is verified over the network and nothing is sent anywhere; see larsasub.eu/pricing.
# .env
LARSASUB_LICENSE_TIER=platform
LARSASUB_CONNECT_ENABLED=true
LARSASUB_CONNECT_TENANT_RELATION=danceSchool
LARSASUB_CONNECT_TENANT_LABEL="dance school"
LARSASUB_CONNECT_TENANT_NAME_ATTRIBUTE=name
LARSASUB_CONNECT_TENANT_OWNER_ATTRIBUTE=owner_id
# Mollie OAuth credentials (from Mollie Dashboard → Developers → OAuth apps)
MOLLIE_CONNECT_CLIENT_ID=app_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
MOLLIE_CONNECT_CLIENT_SECRET=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
MOLLIE_ORGANIZATION_ID=org_xxxxxxxx
// config/larsasub.php
'license' => [
'tier' => 'platform', // required for Connect
],
'billable' => [
'model' => \App\Models\User::class,
'relation' => 'danceSchool', // $user->danceSchool() returns the billable tenant
],
'connect' => [
'enabled' => true,
'tenant_relation' => 'danceSchool',
'tenant_label' => 'dance school', // Used in UI labels and translations
'tenant_name_attribute' => 'name', // $tenant->name shown in emails
'tenant_owner_attribute' => 'owner_id', // Determines who can manage Mollie connection
],
Application Fees
Charge a platform fee on every tenant payment:
# .env
LARSASUB_CONNECT_FEE_ENABLED=true
LARSASUB_CONNECT_FEE_TYPE=percentage # 'percentage' or 'fixed'
LARSASUB_CONNECT_FEE_VALUE=10 # 10% or €10.00
LARSASUB_CONNECT_FEE_DESCRIPTION="Platform fee"
Fees can also be overridden per subscription plan via the fee_type and fee_value fields on the Subscription model.
Fees are automatically skipped when the platform itself is the billable (self-transactions).
Tenant OAuth Flow
Tenants connect their Mollie account via OAuth:
- Tenant owner clicks "Connect Mollie" in the tenant admin dashboard
- LarsaSub redirects to Mollie OAuth authorization page
- Tenant authorizes the platform to access their Mollie account
- Mollie redirects back with an authorization code
- LarsaSub exchanges the code for access/refresh tokens
- Tokens are stored encrypted in
larsasub_mollie_connected_accounts - Tenant is now ready to receive payments
The tenant admin dashboard is available at the URL configured in standalone.url.tenant-connect-dashboard (default: billing/admin/connect).
Tenant-Aware Models
In Connect mode, Mollie customers and mandates are scoped per tenant:
// Customers and mandates are automatically created under the tenant's Mollie account
$user->getMollieCustomer(); // Creates customer via tenant's access token
// Subscription plans can be global or tenant-specific
$plans = Subscription::forTenant($tenant, includeGlobal: true)->isEnabled()->get(); // Tenant plans + global plans
Dual Billing
For platforms that charge tenants directly AND where tenants charge their own users:
// config/larsasub.php
'billable' => [
'model' => \App\Models\User::class, // Tenant's users (uses Connect account)
'platform_model' => \App\Models\DanceSchool::class, // Platform bills this model (uses global Mollie key)
],
Both models must implement BillableModel. The MollieClientResolver automatically routes:
- Platform model payments → global Mollie API key
- User model payments → tenant's Connect access token
Basic Usage
Check User Subscription
// Get active subscription
$subscription = $user->activeSubscription();
// Check if has active subscription
if ($subscription && $subscription->isActive()) {
// User has active subscription
}
Feature Access
// Check feature access
if ($user->hasFeature('premium_support')) {
// Allow premium support
}
// Get feature value
$limit = $user->featureValue('api_calls', 100);
Query Subscriptions
use PetersDevelopment\LarsaSub\Models\BillableSubscription;
// Get all active subscriptions
$active = BillableSubscription::isActive()->get();
// Get chargeable subscriptions
$chargeable = BillableSubscription::isChargeable()->get();
Resolve Billable
use PetersDevelopment\LarsaSub\Helpers\BillableResolver;
// Resolve the billable from an authenticated user
$billable = BillableResolver::resolve($user);
// Resolve from the current request
$billable = BillableResolver::fromRequest($request);
// Check if using direct mode (User IS billable)
$isDirect = BillableResolver::isDirect();
Standalone Dashboard URLs
Default URLs for user subscription management (configurable via standalone.url config):
| URL | Description |
|---|---|
/billing/dashboard |
View/manage subscription |
/billing/payments |
Payment history |
/billing/payment-methods |
Payment methods |
/billing/admin/... |
Management dashboards: plans, subscribers, charges, invoices. Connect mode: for the tenant owner, scoped to the tenant. Simple mode: operator management on the global plans — set larsasub.policies.admin_role to grant access. |
Key Commands
# Test installation with sample data (fresh install only — skipped on an
# existing installation, so it cannot duplicate a live catalogue)
php artisan larsasub:install --seed
# Plan charges for subscriptions
php artisan larsasub:plan-charges
# Execute pending charges
php artisan larsasub:execute-charges
# Notify upcoming charges
php artisan larsasub:notify-charges
# Renewal management
php artisan larsasub:renew-billable-subscriptions
php artisan larsasub:announce-renewal-billable-subscriptions
# Credit management
php artisan larsasub:process-expired-credits
php artisan larsasub:notify-expiring-credits
# Test notifications
php artisan larsasub:test-notifications --list
Credit System
LarsaSub includes a credit system for managing customer balances. Credits can be:
- Added manually by admins
- Applied automatically to charges
- Set to expire after a specified date
See Full Documentation for detailed credit system documentation.
What's Next?
For complete documentation including:
- Full model reference
- Multi-tenant architecture details
- Mollie Connect OAuth flow
- Dual billing setup
- Credit system details
- Event system
- Notification customization
- Nova integration (separate
larsasub-novapackage) - Webhook setup