Skip to content

Paywall

Most SaaS products are freemium: everybody gets in, and a plan buys more. Some are not. One config key decides which yours is:

php
// config/laraspring-billing.php
'require_subscription' => (bool) env('LARASPRING_BILLING_REQUIRE_SUBSCRIPTION', false),

Freemium, the default

Leave it false and nothing is gated wholesale. Gate individual features where they live:

php
if (! Billing::subscribed(null, 'pro')) {
    abort(403);
}
tsx
{plan.id === 'pro' && <AuditLog />}

Pay to enter

Turn it on and a billable without an active subscription cannot reach the application at all: every page load lands on the plan picker until they have one. A trial counts as active, so this is not "pay before you look" unless your plans have no trial.

The gate is middleware, registered by the package on the whole web group rather than on a handful of routes. A gate an edition has to remember to add is a gate missing from the route added next month. Redirecting after sign-in would not be enough either, because a bookmark or a typed URL skips it.

Three restraints, and why each one matters

Page loads only. A form post is never redirected out from under somebody, so a subscription that lapses mid-session does not throw away what they were typing. They are redirected on their next page load.

A bypass list. Without it the paywall is a trap: somebody who cannot pay could not sign out, could not verify their address, and could not reach the checkout that would have let them in.

php
'require_subscription_bypass' => [
    'billing.*',
    'organizations.*',
    'logout',
    'verification.*',
    'password.confirm',
    'two-factor.*',
    'profile.*',
],

Route names, matched as patterns. Add your own marketing or support routes here.

No billable, no gate. A user with no active organization has nothing that could hold a subscription, so they pass through; laraspring/organizations' own onboarding gate is what handles them, and it runs first. Sending them to a pricing page they cannot buy from would strand them between two gates.

Guests pass through too. Whatever gates authentication should answer for them, and a paywall that redirected a signed-out visitor would replace "please sign in" with "please pay".

On one route rather than all of them

If you would rather gate a section than the application, turn require_subscription on and add every other route to the bypass list, or use the alias directly:

php
Route::middleware(['auth', 'subscription.required'])->group(function () {
    // …
});

The screen they land on

The redirect goes to billing.plans, which is the same pricing screen reachable from settings. It is handed required, so your edition can draw it standalone rather than inside the application shell, and change the heading from "Plans" to "Choose a plan to continue". resources/js/pages/billing/plans.tsx (.vue) does both.

Laraspring is a commercial starter kit. Buying it gets you the source.