Slowhand's avatar

Restrict access based on subscriptions Laravel Cashier

Hi all.

I've just installed Cashier and made some tests and it works great.

I created a product on Stripe with 2 prices (montly payments and one time payment)

Both prices should give access to the same content but I don't know how to restrict from viewing certain parts of my website or "block" certain routes (like creating posts).

My app is a simple nwesportal website and I want visitors to pay for reading posts how have "paid" field on DB at true.

Also, they will need to subscribe to any of the plans to write messages on the forum I created.

How can I do that?

Thank you all and happy holidays!

1 like
6 replies
avinash11's avatar

If I understood correctly, when a successful payment goes through for the product (whether it’s a one-time payment or monthly), you set the paid field on the users table to true.

Once this happens, the user should be able to:

  • View posts
  • Create new forum posts

If this is the case, you can leverage Laravel’s Gate system to control access across your application.

You could use policies as well but here’s the Gate approach through the register() in the AppServiceProvider

use Illuminate\Support\Facades\Gate;

Gate::define('view-post', function ($user) {
    return $user->paid;
});

Gate::define('create-post', function ($user) {
    return $user->paid;
});

If you later decide to introduce different rules for viewing vs creating posts, you can easily modify these independently. Otherwise, a single rule works perfectly fine.

For the routes, you can use the can middleware:

Route::get('/posts/{post}', [PostController::class, 'show'])
->middleware(['auth', 'can:view-post']);

Route::post('/forum/posts', [ForumController::class, 'store'])
->middleware(['auth', 'can:create-post']);

Laravel will automatically return a 403 Forbidden response if the user does not pass the gate check.

Laravel also provides Blade directives for authorization checks:

@can('view-post')
{{-- Show paid content --}}
@endcan

@can('create-post')
{{-- Show post creation form --}}
@endcan

This allows you to easily hide UI elements from users who don’t have access.

A great resource for understanding Laravel authorization in depth:

https://laracasts.com/series/mastering-permissions-in-laravel

Slowhand's avatar

Hey thamks @avinash11

English is not my first language... So sorry if my question was unclear.

I write posts and some are free and others are "paid"

Every time I create a new post, I decide if it's free or not (like any newspaper company) and the "paid" field is in my posts table as bool

I created a product on Stripe with 2 different prices that give access to the same content.

Now, I want to restrict access to the non registered an non subscribed users and make sure they can't read the "paid" posts and redirect them to a pricing page I made.

Thank you very much!

martinbean's avatar

@slowhand The docs cover this: https://laravel.com/docs/12.x/billing#quickstart-selling-subscriptions

You can block access either in Blade templates:

@if ($user->subscribed())
    <p>You are subscribed.</p>
@endif
@if ($user->subscribedToProduct('pro_basic'))
    <p>You are subscribed to our Basic product.</p>
@endif
 
@if ($user->subscribedToPrice('price_basic_monthly'))
    <p>You are subscribed to our monthly Basic plan.</p>
@endif

Or via middleware:

class Subscribed
{
    /**
     * Handle an incoming request.
     */
    public function handle(Request $request, Closure $next): Response
    {
        if (! $request->user()?->subscribed()) {
            // Redirect user to billing page and ask them to subscribe...
            return redirect('/billing');
        }
 
        return $next($request);
    }
}
Route::get('/dashboard', function () {
    // ...
})->middleware([Subscribed::class]);
Slowhand's avatar

Hi @martinbean

Thank you! I tried with @if ($user->subscribedToProduct('pro_basic')) You are subscribed to our Basic product. @endif

It works great.

Now, can you tell me how to show all subscribed users on admin dashboard?

Thank you!

martinbean's avatar

can you tell me how to show all subscribed users on admin dashboard?

@slowhand Query your subscriptions for those that are active:

$activeSubscriptions = Subscription::query()->active()->with('user')->latest()->paginate();
<ul>
    @foreach($activeSubscriptions as $subscription)
        <li>{{ $subscription->user->name }}</li>
    @endforeach
</ul>
jlrdw's avatar

If you have a boolean column, just use a where clause. Orderby however you need.

Please or to participate in this conversation.