- Replace Laravel Cashier methods with new subscription system - Remove session-based subscription checking in bulk components - Update Dashboard.php to use PaymentOrchestrator for provider-agnostic sync - Maintain backward compatibility with existing Stripe subscriptions - Improve performance by eliminating session overhead - Add automatic migration of legacy subscriptions to new system BREAKING CHANGE: Subscription checking now uses unified payment system instead of Laravel Cashier methods
221 lines
9.0 KiB
PHP
221 lines
9.0 KiB
PHP
<?php
|
|
|
|
namespace App\Livewire\Dashboard;
|
|
|
|
use App\Models\UsageLog;
|
|
use Exception;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Cache;
|
|
use Illuminate\Support\Facades\Date;
|
|
use Illuminate\Support\Facades\Log;
|
|
use Livewire\Component;
|
|
use Stripe\StripeClient;
|
|
use App\Models\Subscription;
|
|
|
|
class Dashboard extends Component
|
|
{
|
|
public $message;
|
|
|
|
public $usageLog;
|
|
|
|
public $subscription;
|
|
|
|
public $plans;
|
|
|
|
public $showStripeBilling = false;
|
|
|
|
public function paymentStatus(Request $request)
|
|
{
|
|
$status = $request->route('status');
|
|
$request->fullUrl();
|
|
if ($status === 'success') {
|
|
$this->syncSubscription();
|
|
|
|
return to_route('dashboard')->with('status', 'success');
|
|
}
|
|
if ($status === 'cancel') {
|
|
return to_route('dashboard')->with('status', 'cancel');
|
|
}
|
|
}
|
|
|
|
private function checkForSubscriptionStatus(): bool
|
|
{
|
|
$redirect = false;
|
|
$user = auth()->user();
|
|
|
|
// Use the new subscription system
|
|
if ($user->hasActiveSubscription()) {
|
|
$currentSubscription = $user->currentSubscription;
|
|
|
|
if ($currentSubscription && $currentSubscription->provider === 'stripe') {
|
|
$subscriptionId = $currentSubscription->provider_subscription_id;
|
|
$cacheKey = "stripe_check_executed_user_{$user->id}_{$subscriptionId}";
|
|
|
|
if (! Cache::has($cacheKey)) {
|
|
try {
|
|
$stripe = new StripeClient(config('cashier.secret'));
|
|
$subscriptionData = $stripe->subscriptions->retrieve($subscriptionId, []);
|
|
|
|
if ($subscriptionData !== null) {
|
|
$items = $subscriptionData->items->data[0];
|
|
if ($items !== null) {
|
|
$cancel_at_period_end = $subscriptionData->cancel_at_period_end;
|
|
$ends_at = $items->current_period_end;
|
|
$cancel_at = $subscriptionData->cancel_at;
|
|
$canceled_at = $subscriptionData->canceled_at;
|
|
$status = $subscriptionData->status;
|
|
|
|
if ($cancel_at_period_end) {
|
|
$final_ends_at = Date::createFromTimestamp($cancel_at)->toDateTimeString();
|
|
} elseif ($cancel_at === null && $canceled_at !== null && $status === 'canceled' && $cancel_at_period_end === false) {
|
|
$final_ends_at = Date::now()->subDays(2)->toDateTimeString();
|
|
$redirect = true;
|
|
} elseif ($status === 'active' && $cancel_at !== null) {
|
|
$final_ends_at = Date::createFromTimestamp($cancel_at)->toDateTimeString();
|
|
} else {
|
|
$final_ends_at = null;
|
|
}
|
|
|
|
// Update using the new subscription model
|
|
$currentSubscription->update([
|
|
'status' => $status,
|
|
'ends_at' => $final_ends_at ? Date::createFromTimeString($final_ends_at) : null,
|
|
'updated_at' => now(),
|
|
]);
|
|
}
|
|
}
|
|
Cache::put($cacheKey, true, now()->addMinute());
|
|
} catch (Exception $exception) {
|
|
Log::error($exception->getMessage());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return $redirect;
|
|
}
|
|
|
|
private function syncSubscription(): void
|
|
{
|
|
$user = auth()->user();
|
|
|
|
// Use the new payment orchestrator to sync subscription
|
|
try {
|
|
$currentSubscription = $user->currentSubscription;
|
|
|
|
if ($currentSubscription && $currentSubscription->provider === 'stripe') {
|
|
// Sync with the new payment system
|
|
$currentSubscription->syncWithProvider();
|
|
}
|
|
|
|
// For backward compatibility, also check legacy Stripe data
|
|
if ($user->hasStripeId()) {
|
|
$stripe = new StripeClient(config('cashier.secret'));
|
|
$subscriptions = $stripe->subscriptions->all(['limit' => 1]);
|
|
|
|
if (! $subscriptions->isEmpty()) {
|
|
$data = $subscriptions->data[0];
|
|
$items = $subscriptions->data[0]->items->data[0];
|
|
|
|
$type = 'default';
|
|
$subscriptionId = $items->subscription;
|
|
$status = $data->status;
|
|
$cancel_at_period_end = $data->cancel_at_period_end;
|
|
$quantity = $items->quantity;
|
|
$stripe_price = $items->price->id;
|
|
$stripe_product = $items->price->product;
|
|
$ends_at = $items->current_period_end;
|
|
$subscriptionItemId = $items->id;
|
|
$final_ends_at = $cancel_at_period_end ? Date::createFromTimestamp($ends_at)->toDateTimeString() : null;
|
|
|
|
if ($status === 'active') {
|
|
// Check if subscription exists in new system
|
|
$existingSubscription = Subscription::where('provider', 'stripe')
|
|
->where('provider_subscription_id', $subscriptionId)
|
|
->where('user_id', $user->id)
|
|
->first();
|
|
|
|
if (! $existingSubscription) {
|
|
// Create subscription in new system
|
|
$newSubscription = Subscription::create([
|
|
'user_id' => $user->id,
|
|
'type' => $type,
|
|
'provider' => 'stripe',
|
|
'provider_subscription_id' => $subscriptionId,
|
|
'status' => $status,
|
|
'stripe_price' => $stripe_price,
|
|
'quantity' => $quantity,
|
|
'ends_at' => $final_ends_at ? Date::createFromTimeString($final_ends_at) : null,
|
|
'stripe_id' => $subscriptionId, // Keep for backward compatibility
|
|
'stripe_status' => $status, // Keep for backward compatibility
|
|
'created_at' => now(),
|
|
'updated_at' => now(),
|
|
]);
|
|
|
|
// Try to find the associated plan
|
|
$plan = \App\Models\Plan::where('stripe_price_id', $stripe_price)->first();
|
|
if ($plan) {
|
|
$newSubscription->update(['plan_id' => $plan->id]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} catch (Exception $exception) {
|
|
Log::error($exception->getMessage());
|
|
}
|
|
}
|
|
|
|
public function mount(Request $request)
|
|
{
|
|
if ($this->checkForSubscriptionStatus()) {
|
|
return to_route('dashboard');
|
|
}
|
|
try {
|
|
$status = $request->session()->get('status');
|
|
if (isset($status)) {
|
|
if ($status === 'success') {
|
|
$this->message = ['type' => 'success', 'message' => 'Order completed successfully.'];
|
|
} else {
|
|
$this->message = ['type' => 'error', 'message' => 'Order cancelled.'];
|
|
}
|
|
$request->session()->forget('status');
|
|
}
|
|
} catch (Exception) {
|
|
|
|
}
|
|
|
|
// Use the new subscription system
|
|
if (auth()->user()->hasActiveSubscription()) {
|
|
try {
|
|
$currentSubscription = auth()->user()->currentSubscription;
|
|
|
|
if ($currentSubscription && $currentSubscription->plan) {
|
|
$planName = $currentSubscription->plan->name;
|
|
$subscriptionEnd = $currentSubscription->ends_at;
|
|
|
|
// Check if plan accepts Stripe (for backward compatibility)
|
|
$this->showStripeBilling = $currentSubscription->provider === 'stripe';
|
|
|
|
$this->subscription['name'] = $planName;
|
|
$this->subscription['ends_at'] = $subscriptionEnd;
|
|
}
|
|
|
|
} catch (Exception $e) {
|
|
Log::error($e->getMessage());
|
|
}
|
|
}
|
|
|
|
$usageLog = UsageLog::query()->where('user_id', auth()->user()->id)->first();
|
|
$this->usageLog = [
|
|
'emails_created_count' => $usageLog->emails_created_count ?? 0,
|
|
'emails_received_count' => $usageLog->emails_received_count ?? 0,
|
|
];
|
|
}
|
|
|
|
public function render()
|
|
{
|
|
return view('livewire.dashboard.dashboard')->layout('components.layouts.dashboard')->with('message', $this->message);
|
|
}
|
|
}
|