current(); if (! $tenant) abort(404); $user = $request->user(); if (! $user) { return redirect('/app/login'); } $invoices = Subscription::where('company_id', $tenant->id) ->latest('period_end') ->limit(20) ->get(); $methods = $this->availableMethods(); $bank = PlatformSetting::get('payments.bank', []); $legal = PlatformSetting::get('payments.company_legal', []); return view('site.billing', [ 'tenant' => $tenant, 'invoices' => $invoices, 'methods' => $methods, 'bank' => $bank, 'legal' => $legal, 'themeColor' => $tenant->settings['theme_color'] ?? '#3B82F6', ]); } public function startCheckout(Request $request, int $subscription) { $tenant = app(TenantManager::class)->current(); $sub = Subscription::where('company_id', $tenant?->id)->findOrFail($subscription); $method = $request->input('method'); if (! in_array($method, ['stripe', 'paypal', 'bank'], true)) { abort(422, 'Method invalid'); } if ($sub->status === 'paid') { return back()->with('error', 'Factura este deja plătită'); } if ($method === 'bank') { // Show bank instructions page; payment is manual. return view('site.bank-instructions', [ 'tenant' => $tenant, 'sub' => $sub, 'bank' => PlatformSetting::get('payments.bank', []), 'themeColor' => $tenant->settings['theme_color'] ?? '#3B82F6', ]); } if ($method === 'stripe') { return $this->startStripe($sub); } if ($method === 'paypal') { return $this->startPaypal($sub); } } private function startStripe(Subscription $sub) { $stripe = PlatformSetting::get('payments.stripe', []); if (empty($stripe['enabled']) || empty($stripe['secret_key'])) { return back()->with('error', 'Stripe nu este configurat. Contactează operatorul.'); } // Real implementation requires `stripe/stripe-php` package. Here we // produce a stub that explains the flow; in prod, replace with: // $session = \Stripe\Checkout\Session::create([...]); // return redirect($session->url); return view('site.checkout-stub', [ 'gateway' => 'Stripe', 'sub' => $sub, 'note' => 'Pentru a activa Stripe Checkout, instalează `composer require stripe/stripe-php` și activează în /admin/payment-settings.', ]); } private function startPaypal(Subscription $sub) { $paypal = PlatformSetting::get('payments.paypal', []); if (empty($paypal['enabled']) || empty($paypal['client_id'])) { return back()->with('error', 'PayPal nu este configurat.'); } return view('site.checkout-stub', [ 'gateway' => 'PayPal', 'sub' => $sub, 'note' => 'Pentru a activa PayPal, instalează `composer require srmklive/paypal` și activează în /admin/payment-settings.', ]); } public function success(int $subscription) { $sub = Subscription::findOrFail($subscription); return view('site.payment-success', ['sub' => $sub]); } public function cancel(int $subscription) { return view('site.payment-cancel'); } public function stripeWebhook(Request $request) { $stripe = PlatformSetting::get('payments.stripe', []); $secret = $stripe['webhook_secret'] ?? null; if (! $secret) { Log::warning('Stripe webhook hit but no secret configured'); return response()->json(['ok' => false], 400); } // Real impl: \Stripe\Webhook::constructEvent($payload, $sig, $secret) // Mock: trust the body shape for stub mode. $payload = $request->json()->all(); $event = $payload['type'] ?? null; if ($event === 'checkout.session.completed') { $subId = $payload['data']['object']['metadata']['subscription_id'] ?? null; if ($subId && $sub = Subscription::find($subId)) { $this->markPaid($sub, 'stripe_card', $payload['data']['object']['id'] ?? null); } } return response()->json(['ok' => true]); } public function paypalWebhook(Request $request) { // Real impl: verify signature with PayPal $payload = $request->json()->all(); $event = $payload['event_type'] ?? null; if ($event === 'CHECKOUT.ORDER.APPROVED' || $event === 'PAYMENT.CAPTURE.COMPLETED') { $subId = $payload['resource']['custom_id'] ?? null; if ($subId && $sub = Subscription::find($subId)) { $this->markPaid($sub, 'paypal', $payload['resource']['id'] ?? null); } } return response()->json(['ok' => true]); } private function markPaid(Subscription $sub, string $method, ?string $reference): void { if ($sub->status === 'paid') return; $sub->update([ 'status' => 'paid', 'paid_at' => now(), 'payment_method' => $method, 'reference' => $reference, ]); // Extend company subscription $sub->company?->update([ 'status' => 'active', 'active_until' => $sub->period_end, ]); } private function availableMethods(): array { $stripe = PlatformSetting::get('payments.stripe', []); $paypal = PlatformSetting::get('payments.paypal', []); $bank = PlatformSetting::get('payments.bank', []); return [ 'stripe' => ! empty($stripe['enabled']) && ! empty($stripe['publishable_key']), 'paypal' => ! empty($paypal['enabled']) && ! empty($paypal['client_id']), 'bank' => ! empty($bank['enabled']) && ! empty($bank['iban']), ]; } }