loadConfigurations(); $this->registerDefaultProviders(); } /** * Register a payment provider */ public function register(string $name, PaymentProviderContract $provider): void { $this->providers[$name] = $provider; Log::info('Payment provider registered', [ 'provider' => $name, 'class' => get_class($provider), ]); } /** * Get a specific provider */ public function get(string $name): ?PaymentProviderContract { return $this->providers[$name] ?? null; } /** * Get all registered providers */ public function getAllProviders(): Collection { return collect($this->providers); } /** * Get only active providers */ public function getActiveProviders(): Collection { return collect($this->providers) ->filter(fn ($provider) => $provider->isActive()); } /** * Check if provider exists */ public function has(string $name): bool { return isset($this->providers[$name]); } /** * Unregister a provider */ public function unregister(string $name): bool { if (isset($this->providers[$name])) { unset($this->providers[$name]); Log::info('Payment provider unregistered', ['provider' => $name]); return true; } return false; } /** * Get provider configuration */ public function getConfiguration(string $providerName): array { return $this->configurations[$providerName] ?? []; } /** * Update provider configuration */ public function updateConfiguration(string $providerName, array $config): void { $this->configurations[$providerName] = $config; Cache::put("payment_config_{$providerName}", $config); Log::info('Payment provider configuration updated', [ 'provider' => $providerName, 'config_keys' => array_keys($config), ]); } /** * Get providers that support recurring payments */ public function getRecurringProviders(): Collection { return $this->getActiveProviders() ->filter(fn ($provider) => $provider->supportsRecurring()); } /** * Get providers that support one-time payments */ public function getOneTimeProviders(): Collection { return $this->getActiveProviders() ->filter(fn ($provider) => $provider->supportsOneTime()); } /** * Get providers that support a specific currency */ public function getProvidersForCurrency(string $currency): Collection { return $this->getActiveProviders() ->filter(function ($provider) use ($currency) { return in_array($currency, $provider->getSupportedCurrencies()); }); } /** * Get provider by webhook URL pattern */ public function getProviderByWebhookUrl(string $url): ?PaymentProviderContract { return $this->getActiveProviders() ->first(function ($provider) use ($url) { $config = $provider->getConfiguration(); $webhookUrl = $config['webhook_url'] ?? null; return $webhookUrl && str_contains($url, parse_url($webhookUrl, PHP_URL_PATH)); }); } /** * Validate provider health status */ public function validateProviders(): array { $results = []; foreach ($this->providers as $name => $provider) { try { $isActive = $provider->isActive(); $config = $provider->getConfiguration(); $results[$name] = [ 'active' => $isActive, 'configured' => ! empty($config), 'supports_recurring' => $provider->supportsRecurring(), 'supports_one_time' => $provider->supportsOneTime(), 'supported_currencies' => $provider->getSupportedCurrencies(), 'last_checked' => now()->toISOString(), ]; if (! $isActive) { Log::warning('Payment provider is inactive', ['provider' => $name]); } } catch (\Exception $e) { $results[$name] = [ 'active' => false, 'error' => $e->getMessage(), 'last_checked' => now()->toISOString(), ]; Log::error('Payment provider health check failed', [ 'provider' => $name, 'error' => $e->getMessage(), ]); } } return $results; } /** * Get provider statistics */ public function getProviderStats(): array { $stats = [ 'total_providers' => count($this->providers), 'active_providers' => 0, 'recurring_providers' => 0, 'one_time_providers' => 0, 'supported_currencies' => [], 'providers' => [], ]; foreach ($this->providers as $name => $provider) { $isActive = $provider->isActive(); if ($isActive) { $stats['active_providers']++; } if ($provider->supportsRecurring()) { $stats['recurring_providers']++; } if ($provider->supportsOneTime()) { $stats['one_time_providers']++; } $stats['supported_currencies'] = array_merge( $stats['supported_currencies'], $provider->getSupportedCurrencies() ); $stats['providers'][$name] = [ 'active' => $isActive, 'class' => get_class($provider), 'supports_recurring' => $provider->supportsRecurring(), 'supports_one_time' => $provider->supportsOneTime(), 'currencies' => $provider->getSupportedCurrencies(), ]; } $stats['supported_currencies'] = array_unique($stats['supported_currencies']); return $stats; } /** * Load provider configurations from cache/database */ protected function loadConfigurations(): void { // Load from cache first $cachedConfigs = Cache::get('payment_providers_config', []); if (empty($cachedConfigs)) { // Load from database or config files $this->configurations = config('payment.providers', []); // Cache for 1 hour Cache::put('payment_providers_config', $this->configurations, 3600); } else { $this->configurations = $cachedConfigs; } } /** * Register default providers */ protected function registerDefaultProviders(): void { // Auto-register providers based on configuration $enabledProviders = config('payment.enabled_providers', []); foreach ($enabledProviders as $providerName) { $this->registerProviderByName($providerName); } } /** * Register provider by name using configuration */ protected function registerProviderByName(string $providerName): void { $providerClass = config("payment.providers.{$providerName}.class"); if (! $providerClass || ! class_exists($providerClass)) { Log::error('Payment provider class not found', [ 'provider' => $providerName, 'class' => $providerClass, ]); return; } try { $config = $this->getConfiguration($providerName); $provider = new $providerClass($config); if ($provider instanceof PaymentProviderContract) { $this->register($providerName, $provider); } else { Log::error('Payment provider does not implement contract', [ 'provider' => $providerName, 'class' => $providerClass, ]); } } catch (\Exception $e) { Log::error('Failed to register payment provider', [ 'provider' => $providerName, 'error' => $e->getMessage(), ]); } } /** * Refresh provider (useful for configuration changes) */ public function refreshProvider(string $name): bool { if (! isset($this->providers[$name])) { return false; } // Unregister current instance unset($this->providers[$name]); // Re-register with fresh configuration $this->registerProviderByName($name); return isset($this->providers[$name]); } /** * Enable/disable a provider */ public function toggleProvider(string $name, bool $enabled): bool { $config = $this->getConfiguration($name); if (empty($config)) { return false; } $config['enabled'] = $enabled; $this->updateConfiguration($name, $config); // Refresh the provider to apply changes return $this->refreshProvider($name); } /** * Get provider for fallback */ public function getFallbackProvider(): ?PaymentProviderContract { $fallbackProvider = config('payment.fallback_provider'); if ($fallbackProvider && $this->has($fallbackProvider)) { $provider = $this->get($fallbackProvider); if ($provider && $provider->isActive()) { return $provider; } } // Return first active provider as fallback return $this->getActiveProviders()->first(); } }