app/app/Http/Controllers/SubscriptionController.php

107 lines
3.6 KiB
PHP

<?php
namespace App\Http\Controllers;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Laravel\Cashier\Cashier;
use Symfony\Component\HttpFoundation\Response;
class SubscriptionController extends Controller
{
public function checkout(Request $request)
{
$planner = $request->user();
if ($planner->subscribed()) {
return redirect()->route('dashboard');
}
$plan = $request->input('plan', 'monthly');
$priceId = $plan === 'yearly'
? config('services.stripe.price_yearly')
: config('services.stripe.price_monthly');
return $planner->newSubscription('default', $priceId)
->checkout([
'success_url' => route('subscription.success') . '?session_id={CHECKOUT_SESSION_ID}',
'cancel_url' => route('subscription.index'),
]);
}
public function success(Request $request): RedirectResponse
{
$sessionId = $request->query('session_id');
if ($sessionId) {
$planner = $request->user();
$session = Cashier::stripe()->checkout->sessions->retrieve($sessionId, [
'expand' => ['subscription'],
]);
if ($session->subscription && ! $planner->subscribed()) {
$subscription = $session->subscription;
$planner->subscriptions()->create([
'type' => 'default',
'stripe_id' => $subscription->id,
'stripe_status' => $subscription->status,
'stripe_price' => $subscription->items->data[0]->price->id ?? null,
'quantity' => $subscription->items->data[0]->quantity ?? 1,
'trial_ends_at' => $subscription->trial_end ? now()->setTimestamp($subscription->trial_end) : null,
'ends_at' => null,
]);
}
}
return redirect()->route('dashboard')->with('success', 'Subscription activated!');
}
public function billing(Request $request)
{
$planner = $request->user();
$subscription = $planner->subscription();
if (! $subscription) {
return redirect()->route('subscription.index');
}
$planType = match ($subscription->stripe_price) {
config('services.stripe.price_yearly') => 'Yearly',
config('services.stripe.price_monthly') => 'Monthly',
default => 'Unknown',
};
$nextBillingDate = null;
if ($subscription->stripe_status === 'active') {
try {
$stripeSubscription = Cashier::stripe()->subscriptions->retrieve($subscription->stripe_id);
$nextBillingDate = $stripeSubscription->current_period_end
? now()->setTimestamp($stripeSubscription->current_period_end)
: null;
} catch (\Exception $e) {
// Stripe API error - continue without next billing date
}
}
return view('billing.index', [
'subscription' => $subscription,
'planner' => $planner,
'planType' => $planType,
'nextBillingDate' => $nextBillingDate,
]);
}
public function cancel(Request $request): RedirectResponse
{
$planner = $request->user();
if (! $planner->subscribed()) {
return back()->with('error', 'No active subscription found.');
}
$planner->subscription()->cancel();
return back()->with('success', 'Subscription canceled. Access will continue until the end of your billing period.');
}
}