diff --git a/app/Http/Controllers/SubscriptionController.php b/app/Http/Controllers/SubscriptionController.php
index 46f4c3d..d84e561 100644
--- a/app/Http/Controllers/SubscriptionController.php
+++ b/app/Http/Controllers/SubscriptionController.php
@@ -19,8 +19,8 @@ public function checkout(Request $request)
$plan = $request->input('plan', 'monthly');
$priceId = $plan === 'yearly'
- ? env('STRIPE_PRICE_YEARLY')
- : env('STRIPE_PRICE_MONTHLY');
+ ? config('services.stripe.price_yearly')
+ : config('services.stripe.price_monthly');
return $planner->newSubscription('default', $priceId)
->checkout([
@@ -57,6 +57,41 @@ public function success(Request $request): RedirectResponse
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();
diff --git a/app/Http/Middleware/RequireSaasMode.php b/app/Http/Middleware/RequireSaasMode.php
new file mode 100644
index 0000000..0950eb6
--- /dev/null
+++ b/app/Http/Middleware/RequireSaasMode.php
@@ -0,0 +1,19 @@
+alias([
'subscription' => RequireSubscription::class,
+ 'saas' => RequireSaasMode::class,
]);
// Exclude Stripe webhook from CSRF verification
diff --git a/config/services.php b/config/services.php
index 66bade1..cf3ce61 100644
--- a/config/services.php
+++ b/config/services.php
@@ -41,6 +41,8 @@
'webhook' => [
'secret' => env('STRIPE_WEBHOOK_SECRET'),
],
+ 'price_monthly' => env('STRIPE_PRICE_MONTHLY'),
+ 'price_yearly' => env('STRIPE_PRICE_YEARLY'),
],
];
diff --git a/resources/views/billing/index.blade.php b/resources/views/billing/index.blade.php
new file mode 100644
index 0000000..c41163f
--- /dev/null
+++ b/resources/views/billing/index.blade.php
@@ -0,0 +1,49 @@
+BILLING
+
+ Subscription Details
+
+