107 lines
3.6 KiB
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.');
|
|
}
|
|
}
|