app->singleton(PaymentDriver::class, function ($app) { $driver = config('services.payments.driver', 'manual'); $key = (string) config('services.paymongo.secret_key'); if ($driver === 'paymongo' && $key !== '') { return new PayMongoDriver( secretKey: $key, webhookSecret: (string) config('services.paymongo.webhook_secret'), successUrl: (string) config('services.paymongo.success_url'), cancelUrl: (string) config('services.paymongo.cancel_url'), ); } return new ManualPaymentDriver; }); $this->app->singleton(PushDriver::class, function ($app) { $driver = config('services.push.driver', 'log'); $key = (string) config('services.fcm.server_key'); if ($driver === 'fcm' && $key !== '') { return new FcmPushDriver($key); } return new LogPushDriver; }); $this->app->singleton(SmsService::class, function ($app) { $driver = config('services.sms.driver', 'log'); return match ($driver) { 'semaphore' => new SemaphoreSmsService( apiKey: (string) config('services.semaphore.api_key'), senderName: (string) config('services.semaphore.sender_name', 'VERDE'), ), 'fake' => new FakeSmsService, default => new LogSmsService, }; }); } public function boot(): void { // Listeners under App\Listeners are auto-discovered by Laravel 11 // based on their handle() method's type-hint. Don't register them // explicitly here — that causes double-dispatch. // Broadcasting auth needs to accept Sanctum bearer tokens (admin web // posts them via Echo's authorizer callback). Without this override // it would only accept session cookies via the default `web` guard. Broadcast::routes(['middleware' => ['auth:sanctum']]); } }