Download the PHP package graystackit/laravel-mollie-billing without Composer

On this page you can find all versions of the php package graystackit/laravel-mollie-billing. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package laravel-mollie-billing

graystackit/laravel-mollie-billing

Batteries-included Mollie billing for Laravel: VAT/OSS compliance, wallet-based metered billing, coupons, scheduled plan changes, trial flow, admin panel and a Livewire 4 customer portal.

Latest Version on Packagist PHP Version Laravel Version Tests Total Downloads

A batteries-included Mollie billing layer for Laravel that wraps mollie/laravel-mollie ^4 and adds VAT/OSS compliance, wallet-based metered billing, a coupon engine, scheduled plan changes, an admin panel, and a Livewire 4 customer portal — all keyed off a Billable contract that lives on whichever model owns the subscription (typically your Organization, not your User).

Highlights

Requirements

Installation

Publish the config and migrations:

Edit config/mollie-billing.php and set the billable model:

Important: billable_key_type and user_key_type must be set before running migrations for the first time. billable_key_type controls the column type of every polymorphic foreign key that references your billable — including bavix/laravel-wallet's wallets.holder_id, transactions.payable_id, and transfers.{from,to}_id, which we rewrite from the default bigint to uuid/ulid. user_key_type controls columns that reference the auth user (e.g. billing_country_mismatches.resolved_by_user_id). Changing them later requires manually altering those columns.

Then run migrations:

Frontend assets

The package ships server-rendered Blade/Livewire views but no compiled CSS or JS — it relies on your host app's Vite pipeline. The shipped layouts (portal, checkout, admin) call @vite(['resources/css/app.css', 'resources/js/app.js']), so your app must:

  1. Expose those two entry points in vite.config.js (the Laravel default).
  2. Scan the package's Blade views in your Tailwind build, otherwise utility classes used inside the package will be purged and the portal/checkout will render unstyled. See Tailwind CSS content source below for the one-line @source (Tailwind v4) or content (v3) entry to add.

If you publish the views (--tag=mollie-billing-views) and Tailwind already scans resources/views/**, the published copies are picked up automatically — but the @source line for the vendor path is still needed for any unpublished views.

Verify your configuration before deploying — the package ships a validator that checks both mollie-billing.php and mollie-billing-plans.php for syntax errors, broken references (unknown feature_keys, allowed_addons, product group, …) and likely misconfigurations:

See the Commands section below for the full list of issues it detects.

Quick start

Add the HasBilling trait and implement the Billable contract on your billable model — typically a tenant or organization, not the User:

Configure your environment:

BILLING_MOLLIE_KEY is an alias for MOLLIE_KEY from mollie/laravel-mollie — either works. The package propagates BILLING_MOLLIE_KEY into mollie.key so your .env stays on the BILLING_* prefix.

Mount the package routes in routes/web.php. The three route groups serve different scopes and need different middleware:

The admin routes are auto-loaded by the service provider as well, so you only need to call adminRoutes() if you want them under a custom middleware stack.

Multi-tenant URL prefixes

If your app nests the portal behind a tenant parameter (e.g. prefix('{organization:slug}')), mount MollieBilling::routes() inside that group — do not apply your own ->name('tenant.') prefix around it, because the package's views call route('billing.*') by those exact names. Keep checkoutRoutes() outside the tenant group since no tenant exists yet at checkout time:

The package ships a PropagateRouteDefaults middleware that copies the active route's parameters into URL::defaults, so generated links inside the portal (e.g. route('billing.plan')) automatically carry the tenant slug — no app-side URL::defaults wiring required.

For contexts without an active HTTP request — queued notifications, background jobs, or services that run before tenant resolution — PropagateRouteDefaults cannot help. Register a global URL parameter resolver so the package can build correct URLs from any context:

The $billable parameter is null in rare cases where no billable is available yet (e.g. some middleware checks). In those cases the closure should return [] or derive a fallback from auth()->user() or session state.

How the two mechanisms interact: PropagateRouteDefaults covers the request context (portal views, form submissions). urlParametersUsing covers everything else (Mollie webhook URLs, redirect URLs sent to Mollie, queued mail, background jobs). They complement each other — both can be active simultaneously without conflict.

If your billable model needs custom logic beyond the global resolver, you can still override urlRouteParameters() on the model directly — the override takes precedence.

Tell the facade how to resolve the current billable for the authenticated user — usually in AppServiceProvider::boot():

Checkout-route fallback: the checkout route is mounted outside any tenant prefix, so a typical resolveBillableUsing closure that reads from a tenant context returns null there. When that happens the package falls back to looking up the billable from the request's query parameters, matching against the billable model's getRouteKeyName(). A returning customer hitting /billing/checkout?organization=acme-corp therefore re-uses the existing billable instead of being asked for the company details again. Reserved query keys (back, plan, interval, redirect, token) are skipped.

Customize config/mollie-billing-plans.php to define your plans, addons and feature keys.

First checkout

The package ships a complete first-checkout flow — a multi-step Livewire wizard that collects billing details, lets the customer choose a plan, optional addons/seats, apply a coupon, and redirects to Mollie for payment.

Setup

Register three callbacks in your AppServiceProvider::boot():

Link to checkout

The optional $backUrl parameter controls where the "Back" link in the checkout header leads. When omitted, the package falls back to config('mollie-billing.checkout_back_url') (default /).

To pre-select a plan and/or billing interval, pass them as additional parameters:

The plan step will still be shown so the customer can change their mind, but the given plan will be pre-selected. Invalid plan codes or intervals are silently ignored.

Checkout countries

By default the checkout shows all 27 EU member states. Customize via config:

Country names are translated via the package's billing::countries lang files (English and German included). Publish and extend them for additional locales:

Custom checkout steps

If your app needs additional steps before the billing-address form (e.g. "Create your account"), register them via the facade. Custom steps are inserted before the package's built-in steps; numbering, timeline and navigation adjust automatically.

Each step definition requires:

Key Type Description
key string Unique identifier for the step.
label string Short label shown in the timeline.
headline string Heading displayed above the step content.
description string Subheading text below the headline.
view string Blade view name to @include for this step's form fields.
validate Closure (optional) Receives the Livewire Component instance. Throw a ValidationException (or call $component->validate(...)) to block navigation.

Binding form data — The checkout component exposes a public array $customData = [] property. Use wire:model with dot notation in your step view:

The customData array is passed to your createBillableUsing callback as $data['custom'], so you can access it when creating the billable:

You can register multiple custom steps — they appear in the order returned by the callback.

Customizing views

All Livewire views (checkout, portal, admin) can be published and customized:

Views are published to resources/views/vendor/mollie-billing/. SFC files use the ⚡ prefix convention (e.g. ⚡checkout.blade.php).

Tailwind CSS content source

The package's Blade views use Tailwind utility classes (including responsive breakpoints like sm:, lg:). Your host app's Tailwind build must scan the package views, otherwise these classes will be purged.

Tailwind v4 — add a @source directive in your resources/css/app.css:

Tailwind v3 — add the path to the content array in tailwind.config.js:

Without this, responsive grid layouts and other utility classes in the portal, checkout and admin panel may not render correctly.

Configuration

Highlights of config/mollie-billing.php:

Key Purpose
currency Default currency for prices and invoices (e.g. EUR).
logo_url Logo displayed in checkout and portal headers.
primary_color Accent color for checkout UI (hex, e.g. #6366f1).
dashboard_url URL the portal logo links to (e.g. your app's main dashboard). Supports route: prefix.
checkout_back_url Where the checkout "Back" link leads (default /).
checkout_countries Countries shown in checkout (regions, include, exclude).
allow_overage_default Default policy when a plan does not declare its own overage rule.
additional_countries ISO-3166 codes + VAT rates for non-EU jurisdictions.
vat_rate_overrides Map of country code to override VAT percentage.
company_name Display name used in headers, notifications and signatures.
billable_model Fully-qualified class name of your billable model.
billable_key_type uuid, ulid, or int — determines morph column shape.
user_key_type uuid, ulid, or int — primary key type of your auth user model (used e.g. for billing_country_mismatches.resolved_by_user_id).
billing_timezone IANA timezone for the customer portal display (BILLING_TIMEZONE, default UTC). Persistence and computation always remain UTC; the admin panel renders UTC. See Timezones.

Portal "back to dashboard" link

By default the portal logo links to the billing dashboard itself. Set dashboard_url to link it to your app's main dashboard instead — a "Back to dashboard" link will also appear at the bottom of the sidebar:

Plans and addons

Define your catalog in config/mollie-billing-plans.php. Free plans run as SubscriptionSource::Local (no Mollie subscription), paid plans are SubscriptionSource::Mollie.

The Billable contract

A minimal billable model needs the trait plus one required method — getUsedBillingSeats(). This method is intentionally not provided by the trait because only your app knows how to count active seats (team members, users, etc.):

The seat count is used during plan-change previews to calculate whether extra seats need to be purchased on the new plan.

Building on getUsedBillingSeats(), the trait derives seat availability for you:

HasBilling provides among others:

Billing name vs. personal name

The checkout collects a company name and writes it through the getBillingName() / setBillingName() pair on the billable. By default both methods read and write the model's name column, which is fine when the billable is a dedicated Organization / Tenant model.

When your billable is the User model, however, name typically already stores the user's personal name. To keep the personal name intact while still letting the customer enter a company name for invoices, override the two methods (or billingNameAttribute()) on the billable model:

The name key passed to your createBillableUsing callback always carries the company name from the checkout form — your callback decides which attribute to persist it into.

The admin panel never reads the name / email columns directly — every billable label is rendered through getBillingName() / getBillingEmail(), so overriding the accessors above is enough to make the admin listings, the billable detail header, scheduled-changes, past-due, refunds and grant views all show the right value.

Admin search & sort on custom columns

Display goes through getBillingName() / getBillingEmail(), but the admin listings also search and sort by name and email — and a query can't call a PHP accessor. When your display name or contact email lives on a different column (or behind a relation), point the three search/sort scopes at the right place. They default to the name and email columns, so a User-as-billable setup needs no override:

All three are part of the Billable contract, so your IDE/static analysis will flag them if you implement the interface manually instead of using the HasBilling trait.

Restricting which rows are treated as billable

When the billable table also stores rows that are not customers — typically a single users table that mixes admins/staff with paying users — override applyBillingScope() on the model. The HasBilling trait registers BillingScope as a global scope and delegates to this method, so the same filter applies to admin listings, KPI queries, and every lifecycle job that iterates billables.

Bypass the scope on the rare lookups that must reach every row regardless of the app-defined restriction (Mollie webhook resolution, retry jobs, admin impersonation):

The default implementation is a no-op, so models where the table only contains billables need not override it.

Coupon types

Type Behavior Quick example
SinglePayment Discounts only a single invoice (Subscription Checkout or One-Time-Order). 100 % is supported — Subscription Checkout uses a Mandate-Only flow so Mollie keeps a mandate for period 2; One-Time-Order skips Mollie entirely and writes a local 0-EUR audit invoice. MollieBilling::coupons()->singlePaymentCoupon('LAUNCH', 50, 'percent');
Recurring Discounts each invoice for N periods (Subscription Checkout or any plan-change-style flow). 100 % is supported via a deferred Mollie startDate. Not accepted on One-Time-Orders (no follow-up charges to attach to). MollieBilling::coupons()->recurringCoupon('LOYAL', 10, 'percent', periods: 6);
Credits Adds wallet credit balance. MollieBilling::coupons()->creditsCoupon('PROMO5', cents: 500);
TrialExtension Extends the active trial. MollieBilling::coupons()->trialExtensionCoupon('EXTEND14', days: 14);
AccessGrant Grants free access without payment. See below.

Access Grants

Access Grants come in two flavors — full-plan grants and addon-only grants:

Updating subscriptions

The update orchestrator handles plan changes, addon toggles and seat sync atomically:

Local subscriptions

The package distinguishes two subscription sources via the subscription_source column:

When does a Local subscription arise?

Trigger Service Notes
Free plan checkout StartSubscriptionCheckoutActivateLocalSubscription Mollie returns no checkout_url for a 0 € first payment; the app activates the plan locally.
AccessGrant coupon CouponService::applyAccessGrantActivateLocalSubscription Coupon-granted plans (timed or unlimited) live as Local.
Mollie → Free downgrade UpdateSubscription Cancels the Mollie subscription, sets subscription_source = local, status remains active, wallets are rebalanced (purchased credits preserved).

What is allowed on a Local subscription?

A Local subscription has no Mollie mandate, so no money can flow from the customer. Anything that would result in a charge is blocked.

Operation Allowed?
Free addons (price 0) yes
Paid addons noLocalSubscriptionDoesNotSupportPaidExtrasException
Extra seats on a plan with seat_price_net > 0 no — same exception
Switch to another free plan yes
Switch directly to a paid plan via UpdateSubscription noLocalSubscriptionUpgradeRequiresMolliePathException. Use UpgradeLocalToMollie instead (the bundled plan-change UI does this automatically).
Track metered usage (recordBillingUsage) yes — included quota is credited and reset at period boundaries
Charge the customer for usage overages noPrepareUsageOverageJob only charges Mollie + mandate billables. Negative balances on Local subs are silently reset at the next period. See docs/usage-billing.md.
Purchase one-time products opt-in via config('mollie-billing.local_subscription.allow_one_time_orders'). Default is false — purchase attempts throw LocalSubscriptionCannotPurchaseProductsException and the products page hides the buy buttons. Set to true if your business model treats the free plan as a default tier monetised through token packs etc.
Cancel yes — status switches to cancelled, wallets are kept until subscription_ends_at.

If you need to bill free-tier users for usage overages or sell them seat upgrades, do not ship the plan at price 0. Set the lowest non-zero amount that still makes commercial sense — that triggers the regular Mollie checkout, captures a mandate, and makes the user a paid (Mollie-source) subscriber.

Local → Mollie upgrade

The webhook on the resulting first payment carries metadata.upgrade_from_local = true and routes through MollieWebhookController::handleLocalToMollieUpgrade(), which reuses the existing wallet (purchased balance preserved) instead of seeding a fresh one.

The bundled plan-change UI (resources/views/livewire/billing/⚡plan-change.blade.php) detects Local → paid plan automatically and shows a confirmation step before the Mollie redirect — no second checkout wizard.

Mollie → Free behaviour

A user-initiated downgrade follows whatever config('mollie-billing.plan_change_mode') is set to (Immediate, EndOfPeriod, UserChoice). For EndOfPeriod, ScheduleSubscriptionChange queues the change and PrepareUsageOverageJob applies it at the period boundary — the same Mollie cancel + Source=Local flip happens then.

purchased_balance (one-time orders, coupon credits) is preserved across every plan change, including downgrades to free.

Preview

Preview the financial impact of an update before applying it:

Refunds

Three convenience methods cover the common cases:

Admin panel

The admin panel lives at /billing/admin. Authorize access by implementing AuthorizesBillingAdmin directly on your user model. The billing.admin middleware checks auth()->user() instanceof AuthorizesBillingAdmin && canAccessBillingAdmin(); users without the interface receive a 403.

Promotion links

Generate signed promotion URLs that auto-apply a coupon when the customer follows them:

Tokens are generated via MollieBilling::coupons()->promotionToken($coupon).

Events

Every state change dispatches a Laravel event so apps can react via listeners. Notable events include:

Subscribe in your EventServiceProvider exactly like any other Laravel event.

Testing

The package ships with helpers for both unit and feature tests:

Commands

See docs/testing-flows.md for the full list of simulated flows, options, and what is/isn't covered.

billing:check-config reports two classes of issues:

Run it after editing either config file or as part of CI to catch typos before deployment.

Documentation

Detailed technical documentation is available in the docs/ directory:

Architecture

This package wraps mollie/laravel-mollie ^4 and adds a VAT/OSS layer (mpociot/vat-calculator plus VIES), a wallet layer for metered billing (bavix/laravel-wallet), a coupon engine, a built-in first-checkout wizard, an admin panel and a Livewire 4 customer portal. Subscription lifecycle is split into single-purpose service classes per action (Start, Create, Activate, Change, Cancel, Resubscribe, EnableAddon, DisableAddon, SyncSeats) — the HasBilling trait delegates to them via the container, so apps customize behavior by rebinding services rather than subclassing models. Extension points are provided via facade callbacks (createBillableUsing, beforeCheckoutUsing, afterCheckoutUsing, resolveBillableUsing, etc.) and events.

Webhook handling is similarly split: MollieWebhookController is a thin façade that reserves the payment, fetches it from Mollie, and routes by payment type to a dedicated handler in src/Services/Webhook/ (FirstPaymentHandler, MandateOnlyPaymentHandler, SubscriptionPaymentHandler, ProrataChargeHandler, SingleChargeHandler, CountryCorrectionHandler, LocalToMollieUpgradeHandler, OneTimeOrderHandler, RefundHandler). Each handler is auto-resolved from the container — apps can rebind any of them to customize per-payment-type behavior without touching the controller.

Free or zero-price plans run as SubscriptionSource::Local without a Mollie subscription; paid plans are SubscriptionSource::Mollie. Paid plans with a configured trial_days go through a Mandate-Only checkout (0 EUR, captures the payment method) and create the Mollie subscription with startDate = now + trial_days — no charge during the trial, status = trial, wallet hydrated aliquot to the trial length. See Subscription Lifecycle.

License

The MIT License (MIT). See LICENSE for details.

Credits


All versions of laravel-mollie-billing with dependencies

PHP Build Version
Package Version
Requires php Version ^8.3
brick/money Version ^0.11
bavix/laravel-wallet Version ^11.5|^12.0
elegantly/laravel-invoices Version ^4.8
dragonmantank/cron-expression Version ^3.4
laravel/framework Version ^12.0|^13.0
laravel/prompts Version ^0.3|^1.0
livewire/flux Version ^2.0
livewire/livewire Version ^4.0
mollie/laravel-mollie Version ^4.1
mpociot/vat-calculator Version ^3.26
spatie/laravel-activitylog Version ^4.12|^5.0
symfony/http-foundation Version ^7.0|^8.0
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package graystackit/laravel-mollie-billing contains the following files

Loading the files please wait ...