Skip to content

Instantly share code, notes, and snippets.

@owenconti
Last active August 20, 2023 18:14
Show Gist options
  • Save owenconti/cb6a11cf8cb4272733843657cd7ce385 to your computer and use it in GitHub Desktop.
Save owenconti/cb6a11cf8cb4272733843657cd7ce385 to your computer and use it in GitHub Desktop.
Adding Stripe Checkout and Customer Portal to your Laravel application
<?php
Route::get('/subscription', ManageSubscriptionController::class)->name('subscription');
<?php
namespace App\Http\Controllers\Teams;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class BillingPortalController extends Controller
{
public function __invoke(Request $request)
{
return $request->user()->currentTeam->redirectToBillingPortal();
}
}
<?php
namespace App\Http\Middleware;
use Closure;
class BillingMiddleware
{
public function handle($request, Closure $next)
{
$user = $request->user();
if ($user && !$user->currentTeam->subscribed('default')) {
return redirect('subscription');
}
return $next($request);
}
}
<script src="https://js.stripe.com/v3/" defer></script>
<?php
protected $routeMiddleware = [
// ...
'billing' => BillingMiddleware::class
];
<?php
namespace App\Models;
use Laravel\Cashier\Billable;
class Team extends Model
{
use Billable;
}
composer require laravel/cashier
<?php
use Laravel\Cashier\Cashier;
/**
* Register any application services.
*
* @return void
*/
public function register()
{
Cashier::ignoreMigrations();
}
<?php
// I changed 'users' to 'teams'
Schema::table('teams', function (Blueprint $table) {
$table->string('stripe_id')->nullable()->index();
$table->string('card_brand')->nullable();
$table->string('card_last_four', 4)->nullable();
$table->timestamp('trial_ends_at')->nullable();
});
<template>
<page :title="title">
<div class="max-w-7xl mx-auto py-10 sm:px-6 lg:px-8">
<div class="text-center">
<h2 class="font-bold text-2xl">
Hold up! You need an active subscription first.
</h2>
<jet-button class="mt-4" @click.native="checkout">
Head to the checkout page
</jet-button>
</div>
</div>
</page>
</template>
<script>
import Page from '../../Layouts/Page';
import AppLayout from '../../Layouts/AppLayout';
import JetButton from '../../Jetstream/Button';
export default {
layout: AppLayout,
components: {
Page,
JetButton,
},
props: {
stripeKey: {
type: String,
required: true,
},
sessionId: {
type: String,
required: true,
},
},
computed: {
title() {
return 'Manage Subscription';
},
},
methods: {
checkout() {
window
.Stripe(this.stripeKey)
.redirectToCheckout({
sessionId: this.sessionId,
})
.then(function (result) {
console.error('result', result);
});
},
},
};
</script>
<?php
namespace App\Http\Controllers\Teams;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Inertia\Inertia;
class ManageSubscriptionController extends Controller
{
public function __invoke(Request $request)
{
$checkout = $request->user()->currentTeam->newSubscription('default', config('stripe.price_id'))->checkout();
return Inertia::render('Teams/ManageSubscription', [
'stripeKey' => config('cashier.key'),
'sessionId' => $checkout->id
]);
}
}
<jet-dropdown-link href="/billing-portal" :external="true">
Billing Portal
</jet-dropdown-link>
<?php
Route::get('/billing-portal', BillingPortalController::class);
<?php
class CreateSubscriptionsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('subscriptions', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('team_id'); // I changed this from `user_id`
$table->string('name');
$table->string('stripe_id');
$table->string('stripe_status');
$table->string('stripe_plan')->nullable();
$table->integer('quantity')->nullable();
$table->timestamp('trial_ends_at')->nullable();
$table->timestamp('ends_at')->nullable();
$table->timestamps();
$table->index(['team_id', 'stripe_status']); // I changed this from `user_id`
});
}
CASHIER_MODEL=App\Models\Team
STRIPE_KEY=XXXXXXX
STRIPE_SECRET=XXXXXXX
php artisan vendor:publish --tag="cashier-migrations"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment