'boolean', 'configuration' => 'encrypted:array', 'supports_recurring' => 'boolean', 'supports_one_time' => 'boolean', 'supported_currencies' => 'array', 'fee_structure' => 'array', 'is_fallback' => 'boolean', ]; /** * Scope to get only active providers */ public function scopeActive($query) { return $query->where('is_active', true); } /** * Scope to get providers that support recurring payments */ public function scopeRecurring($query) { return $query->where('supports_recurring', true); } /** * Scope to get providers that support one-time payments */ public function scopeOneTime($query) { return $query->where('supports_one_time', true); } /** * Scope to get providers ordered by priority */ public function scopeByPriority($query) { return $query->orderBy('priority', 'desc'); } /** * Get the fallback provider */ public static function getFallback() { return static::where('is_fallback', true)->active()->first(); } /** * Check if provider supports a specific currency */ public function supportsCurrency(string $currency): bool { return in_array(strtoupper($currency), $this->supported_currencies); } /** * Get fee for a specific amount */ public function calculateFee(float $amount): array { if (! $this->fee_structure) { return [ 'fixed_fee' => 0, 'percentage_fee' => 0, 'total_fee' => 0, 'net_amount' => $amount, ]; } $fixedFee = $this->fee_structure['fixed_fee'] ?? 0; $percentageFee = $this->fee_structure['percentage_fee'] ?? 0; $percentageAmount = ($amount * $percentageFee) / 100; $totalFee = $fixedFee + $percentageAmount; return [ 'fixed_fee' => $fixedFee, 'percentage_fee' => $percentageAmount, 'total_fee' => $totalFee, 'net_amount' => $amount - $totalFee, ]; } /** * Get webhook endpoint URL */ public function getWebhookUrl(): string { return $this->webhook_url ?? route('webhook.payment', $this->name); } /** * Update configuration */ public function updateConfiguration(array $config): void { $this->configuration = array_merge($this->configuration ?? [], $config); $this->save(); } /** * Get specific configuration value */ public function getConfigValue(string $key, $default = null) { return data_get($this->configuration, $key, $default); } /** * Set specific configuration value */ public function setConfigValue(string $key, $value): void { $config = $this->configuration ?? []; data_set($config, $key, $value); $this->configuration = $config; $this->save(); } /** * Check if provider is properly configured */ public function isConfigured(): bool { $requiredFields = $this->getConfigValue('required_fields', []); foreach ($requiredFields as $field) { if (empty($this->getConfigValue($field))) { return false; } } return true; } /** * Get provider statistics */ public function getStats(): array { $subscriptionCount = Subscription::where('provider', $this->name)->count(); $activeSubscriptionCount = Subscription::where('provider', $this->name) ->where('unified_status', 'active') ->count(); return [ 'name' => $this->name, 'display_name' => $this->display_name, 'is_active' => $this->is_active, 'is_configured' => $this->isConfigured(), 'total_subscriptions' => $subscriptionCount, 'active_subscriptions' => $activeSubscriptionCount, 'supports_recurring' => $this->supports_recurring, 'supports_one_time' => $this->supports_one_time, 'supported_currencies' => $this->supported_currencies, 'is_fallback' => $this->is_fallback, 'priority' => $this->priority, ]; } /** * Activate provider */ public function activate(): void { $this->is_active = true; $this->save(); } /** * Deactivate provider */ public function deactivate(): void { if ($this->is_fallback) { throw new \Exception('Cannot deactivate fallback provider'); } $this->is_active = false; $this->save(); } /** * Set as fallback provider */ public function setAsFallback(): void { // Remove fallback status from other providers static::where('is_fallback', true)->update(['is_fallback' => false]); $this->is_fallback = true; $this->save(); } /** * Remove fallback status */ public function removeFallback(): void { $this->is_fallback = false; $this->save(); } /** * Get provider class name */ public function getProviderClass(): string { return $this->getConfigValue('class', ''); } /** * Test provider connection */ public function testConnection(): array { try { $class = $this->getProviderClass(); if (! class_exists($class)) { return [ 'success' => false, 'error' => "Provider class {$class} not found", ]; } $provider = new $class($this->configuration); if (! $provider instanceof \App\Contracts\Payments\PaymentProviderContract) { return [ 'success' => false, 'error' => 'Provider class does not implement PaymentProviderContract', ]; } $isActive = $provider->isActive(); return [ 'success' => true, 'is_active' => $isActive, 'configuration_valid' => $this->isConfigured(), ]; } catch (\Exception $e) { return [ 'success' => false, 'error' => $e->getMessage(), ]; } } /** * Get all active providers ordered by priority */ public static function getActiveOrdered() { return static::active()->byPriority()->get(); } /** * Get providers that support a specific plan type */ public static function getForPlanType(bool $recurring = false) { $query = static::active(); if ($recurring) { $query->recurring(); } else { $query->oneTime(); } return $query->byPriority()->get(); } }