diff --git a/app/Console/Commands/Payment/SyncNonRecurringSubscriptions.php b/app/Console/Commands/Payment/SyncNonRecurringSubscriptions.php new file mode 100644 index 0000000..519ffb1 --- /dev/null +++ b/app/Console/Commands/Payment/SyncNonRecurringSubscriptions.php @@ -0,0 +1,142 @@ +option('dry-run'); + + $this->info('๐Ÿ”„ Syncing non-recurring payment provider subscriptions...'); + + if ($dryRun) { + $this->warn('๐Ÿ“‹ DRY RUN MODE - No actual updates will be made'); + } + + // Get all active non-recurring payment providers + $nonRecurringProviders = PaymentProvider::where('is_active', true) + ->where('supports_recurring', false) + ->where('supports_one_time', true) + ->pluck('name') + ->toArray(); + + $this->info('๐Ÿ“‹ Non-recurring providers found: '.implode(', ', $nonRecurringProviders)); + + $totalProcessed = 0; + $totalExpired = 0; + + foreach ($nonRecurringProviders as $providerName) { + $this->info("๐Ÿ” Processing provider: {$providerName}"); + + $result = $this->syncProviderSubscriptions($providerName, $dryRun); + $totalProcessed += $result['processed']; + $totalExpired += $result['expired']; + } + + $this->info('โœ… Sync completed!'); + $this->info("๐Ÿ“Š Total subscriptions processed: {$totalProcessed}"); + $this->info("โฐ Total subscriptions expired: {$totalExpired}"); + + if (! $dryRun && $totalExpired > 0) { + $this->info('๐Ÿ’ก Tip: Set up a cron job to run this command every few hours:'); + $this->info(' */4 * * * * php artisan app:sync-non-recurring-subscriptions'); + } + } + + /** + * Sync subscriptions for a specific provider + */ + protected function syncProviderSubscriptions(string $providerName, bool $dryRun): array + { + $query = Subscription::where('provider', $providerName) + ->where('status', '!=', 'expired') + ->where('status', '!=', 'cancelled') + ->whereNotNull('ends_at'); + + if ($dryRun) { + $subscriptions = $query->get(); + $expiredCount = $subscriptions->filter(function ($sub) { + return $sub->ends_at->isPast(); + })->count(); + + $this->line(" ๐Ÿ“Š Found {$subscriptions->count()} subscriptions"); + $this->line(" โฐ Would expire {$expiredCount} subscriptions"); + + return [ + 'processed' => $subscriptions->count(), + 'expired' => $expiredCount, + ]; + } + + // Get subscriptions that should be expired + $expiredSubscriptions = $query->where('ends_at', '<', now())->get(); + + $expiredCount = 0; + foreach ($expiredSubscriptions as $subscription) { + try { + $subscription->update([ + 'status' => 'expired', + 'unified_status' => 'expired', + 'updated_at' => now(), + ]); + + $expiredCount++; + + $this->line(" โœ… Expired subscription #{$subscription->id} (User: {$subscription->user_id})"); + + Log::info('Non-recurring subscription expired via sync command', [ + 'subscription_id' => $subscription->id, + 'provider' => $providerName, + 'user_id' => $subscription->user_id, + 'ends_at' => $subscription->ends_at, + 'command' => 'app:sync-non-recurring-subscriptions', + ]); + + } catch (\Exception $e) { + $this->error(" โŒ Failed to expire subscription #{$subscription->id}: {$e->getMessage()}"); + + Log::error('Failed to expire non-recurring subscription', [ + 'subscription_id' => $subscription->id, + 'provider' => $providerName, + 'error' => $e->getMessage(), + ]); + } + } + + $totalProcessed = $query->count(); + + if ($expiredCount > 0) { + $this->info(" โœ… Expired {$expiredCount} subscriptions for {$providerName}"); + } else { + $this->info(" โ„น๏ธ No expired subscriptions found for {$providerName}"); + } + + return [ + 'processed' => $totalProcessed, + 'expired' => $expiredCount, + ]; + } +} diff --git a/app/Models/Subscription.php b/app/Models/Subscription.php index b6af72e..f638335 100644 --- a/app/Models/Subscription.php +++ b/app/Models/Subscription.php @@ -62,6 +62,9 @@ class Subscription extends Model 'customer_metadata', 'trial_will_end_sent_at', 'pause_reason', + 'amount', + 'currency', + 'expires_at', ]; protected $casts = [ diff --git a/app/Services/Payments/Providers/OxapayProvider.php b/app/Services/Payments/Providers/OxapayProvider.php index 252a84b..ba622cd 100644 --- a/app/Services/Payments/Providers/OxapayProvider.php +++ b/app/Services/Payments/Providers/OxapayProvider.php @@ -3,9 +3,11 @@ namespace App\Services\Payments\Providers; use App\Contracts\Payments\PaymentProviderContract; +use App\Models\PaymentProvider as PaymentProviderModel; use App\Models\Plan; use App\Models\Subscription; use App\Models\User; +use Carbon\Carbon; use Illuminate\Http\Request; use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Http; @@ -15,14 +17,75 @@ class OxapayProvider implements PaymentProviderContract { protected array $config; + protected bool $sandbox; + protected string $baseUrl; + protected string $merchantApiKey; + public function __construct(array $config = []) { + // Load configuration from PaymentProvider model to get the latest data + $dbConfig = $this->loadConfigurationFromModel(); + + // Merge with any passed config (passed config takes precedence) + $config = array_merge($dbConfig, $config); + $this->config = $config; - $this->baseUrl = $config['sandbox'] ?? false - ? 'https://api-sandbox.oxapay.com/v1' - : 'https://api.oxapay.com/v1'; + $this->sandbox = (bool) ($config['sandbox'] ?? false); + $this->merchantApiKey = $this->sandbox ? ($config['sandbox_merchant_api_key'] ?? '') : ($config['merchant_api_key'] ?? ''); + + $this->baseUrl = 'https://api.oxapay.com/v1'; + + Log::info('OxaPayProvider configuration loaded', [ + 'sandbox' => $this->sandbox, + 'has_merchant_api_key' => ! empty($this->merchantApiKey), + 'base_url' => $this->baseUrl, + ]); + } + + /** + * Load configuration from PaymentProvider model + */ + protected function loadConfigurationFromModel(): array + { + try { + $providerModel = PaymentProviderModel::where('name', 'oxapay')->first(); + + + if ($providerModel && $providerModel->configuration) { + return $providerModel->configuration; + } + + Log::warning('OxaPayProvider configuration not found in database, using defaults'); + + return $this->getDefaultConfiguration(); + + } catch (\Exception $e) { + Log::error('OxaPayProvider failed to load configuration from database', [ + 'error' => $e->getMessage(), + ]); + + return $this->getDefaultConfiguration(); + } + } + + /** + * Get default configuration + */ + protected function getDefaultConfiguration(): array + { + return [ + 'merchant_api_key' => '', + 'sandbox_merchant_api_key' => '', + 'sandbox' => false, + 'webhook_url' => route('webhook.payment', 'oxapay'), + 'success_url' => route('payment.success'), + 'cancel_url' => route('payment.cancel'), + 'default_lifetime' => 60, // minutes + 'default_under_paid_coverage' => 5, // percentage + 'fee_paid_by_payer' => 0, // merchant pays by default + ]; } public function getName(): string @@ -32,7 +95,7 @@ class OxapayProvider implements PaymentProviderContract public function isActive(): bool { - return ! empty($this->config['merchant_api_key']); + return ! empty($this->merchantApiKey); } public function supportsRecurring(): bool @@ -50,7 +113,7 @@ class OxapayProvider implements PaymentProviderContract return Cache::remember('oxapay_currencies', now()->addHour(), function () { try { $response = Http::withHeaders([ - 'merchant_api_key' => $this->config['merchant_api_key'], + 'merchant_api_key' => $this->merchantApiKey, ])->get("{$this->baseUrl}/info/currencies"); if ($response->successful()) { @@ -91,7 +154,24 @@ class OxapayProvider implements PaymentProviderContract public function cancelSubscription(Subscription $subscription, string $reason = ''): bool { - throw new \Exception('OxaPay does not support recurring subscriptions'); + try { + // For oxapay, we don't actually cancel since it's a one-time activation + // We can deactivate the subscription if needed + $subscription->update([ + 'status' => 'cancelled', + 'cancelled_at' => now(), + 'cancellation_reason' => $reason, + ]); + + return true; + + } catch (\Exception $e) { + Log::error('Oxapay subscription cancellation failed', [ + 'subscription_id' => $subscription->id, + 'error' => $e->getMessage(), + ]); + throw $e; + } } public function updateSubscription(Subscription $subscription, Plan $newPlan): array @@ -117,43 +197,105 @@ class OxapayProvider implements PaymentProviderContract public function createCheckoutSession(User $user, Plan $plan, array $options = []): array { try { - $amount = $options['amount'] ?? $plan->price; - $currency = $options['currency'] ?? 'USD'; - $toCurrency = $options['to_currency'] ?? 'USDT'; + $amount = (float) $plan->price; + $currency = (string) ($this->config['currency'] ?? 'USD'); + // Build simple invoice request payload $payload = [ - 'amount' => $amount, - 'currency' => $currency, - 'to_currency' => $toCurrency, - 'lifetime' => $options['lifetime'] ?? 60, // 60 minutes default - 'fee_paid_by_payer' => $options['fee_paid_by_payer'] ?? 0, - 'callback_url' => $this->config['webhook_url'] ?? route('webhooks.oxapay'), - 'return_url' => $this->config['success_url'] ?? route('payment.success'), - 'email' => $user->email, - 'order_id' => $options['order_id'] ?? null, - 'description' => $options['description'] ?? "Payment for {$plan->name}", - 'sandbox' => $this->config['sandbox'] ?? false, + 'amount' => $amount, // number ยท decimal + 'currency' => $currency, // string + 'lifetime' => (int) ($this->config['lifetime'] ?? 30), // integer ยท min: 15 ยท max: 2880 + 'fee_paid_by_payer' => (int) ($this->config['fee_paid_by_payer'] ?? 1), // number ยท decimal ยท max: 1 + 'under_paid_coverage' => (float) ($this->config['under_paid_coverage'] ?? 2.5), // number ยท decimal ยท max: 60 + 'auto_withdrawal' => (bool) ($this->config['auto_withdrawal'] ?? false), // boolean + 'mixed_payment' => (bool) ($this->config['mixed_payment'] ?? false), // boolean + 'return_url' => (string) ($this->config['success_url'] ?? route('payment.success')), // string + 'callback_url' => (string) ($this->config['callback_url'] ?? route('webhook.oxapay')), // string + 'order_id' => (string) ($this->config['order_id'] ?? 'order_'.$user->id.'_'.time()), // string + 'thanks_message' => (string) ($this->config['thanks_message'] ?? 'Thank you for your payment!'), // string + 'description' => (string) ($this->config['description'] ?? "Payment for plan: {$plan->name}"), // string + 'sandbox' => $this->sandbox, // boolean ]; + // Add to_currency only if it's properly configured + $configuredToCurrency = $this->config['to_currency'] ?? null; + if (! empty($configuredToCurrency)) { + $toCurrency = (string) $configuredToCurrency; + $payload['to_currency'] = $toCurrency; + } + + Log::info('Creating OxaPay invoice', [ + 'user_id' => $user->id, + 'plan_id' => $plan->id, + 'payload_keys' => array_keys($payload), + ]); + $response = Http::withHeaders([ - 'merchant_api_key' => $this->config['merchant_api_key'], + 'merchant_api_key' => $this->merchantApiKey, 'Content-Type' => 'application/json', ])->post("{$this->baseUrl}/payment/invoice", $payload); if (! $response->successful()) { - throw new \Exception('Failed to create OxaPay invoice: '.$response->body()); + $errorData = $response->json(); + $errorMessage = $errorData['message'] ?? 'Unknown error'; + + Log::error('OxaPay invoice creation failed', [ + 'status' => $response->status(), + 'response' => $errorData, + 'payload' => $payload, + ]); + + throw new \Exception("Failed to create OxaPay invoice: {$errorMessage}"); } $data = $response->json(); + if (! isset($data['data']) || $data['status'] !== 200) { + throw new \Exception('Invalid response from OxaPay API'); + } + + $paymentData = $data['data']; + + // Create local subscription record + $subscription = Subscription::create([ + 'user_id' => $user->id, + 'plan_id' => $plan->id, + 'provider' => 'oxapay', + 'type' => 'one_time', // OxaPay doesn't support recurring + 'provider_subscription_id' => $paymentData['track_id'], + 'provider_checkout_id' => $paymentData['track_id'], + 'status' => 'pending_payment', + 'unified_status' => 'pending_payment', + 'quantity' => 1, + 'provider_data' => $paymentData, + 'starts_at' => now(), + 'ends_at' => $this->calculateSubscriptionEndDate($plan), + 'last_provider_sync' => now(), + ]); + + Log::info('OxaPay subscription created', [ + 'subscription_id' => $subscription->id, + 'track_id' => $paymentData['track_id'], + 'user_id' => $user->id, + 'plan_id' => $plan->id, + ]); + return [ 'success' => true, - 'checkout_url' => $data['data']['payment_url'] ?? null, - 'payment_id' => $data['data']['track_id'] ?? null, - 'expires_at' => $data['data']['expired_at'] ?? null, - 'amount' => $amount, - 'currency' => $currency, + 'checkout_url' => $paymentData['payment_url'] ?? null, + 'payment_id' => $paymentData['track_id'] ?? null, + 'track_id' => $paymentData['track_id'] ?? null, + 'subscription_id' => $subscription->id, + 'amount' => $paymentData['amount'] ?? $amount, + 'currency' => $paymentData['currency'] ?? $currency, + 'pay_amount' => $paymentData['pay_amount'] ?? null, + 'pay_currency' => $paymentData['pay_currency'] ?? null, + 'expires_at' => isset($paymentData['expired_at']) ? Carbon::createFromTimestamp($paymentData['expired_at']) : null, + 'lifetime' => $paymentData['lifetime'] ?? $payload['lifetime'], + 'under_paid_coverage' => $paymentData['under_paid_coverage'] ?? $payload['under_paid_coverage'], + 'fee_paid_by_payer' => $paymentData['fee_paid_by_payer'] ?? $payload['fee_paid_by_payer'], 'provider' => 'oxapay', + 'provider_data' => $paymentData, ]; } catch (\Exception $e) { @@ -186,10 +328,23 @@ class OxapayProvider implements PaymentProviderContract } $data = $request->json()->all(); - $status = $data['status'] ?? 'unknown'; + $status = strtolower($data['status'] ?? 'unknown'); $trackId = $data['track_id'] ?? null; $type = $data['type'] ?? 'payment'; + if (! $trackId) { + throw new \Exception('Missing track_id in webhook payload'); + } + + Log::info('OxaPay webhook received', [ + 'track_id' => $trackId, + 'status' => $status, + 'type' => $type, + ]); + + // Process the webhook based on status + $result = $this->handleWebhookStatus($status, $data); + return [ 'success' => true, 'event_type' => $status, @@ -197,6 +352,7 @@ class OxapayProvider implements PaymentProviderContract 'processed' => true, 'data' => $data, 'type' => $type, + 'result' => $result, ]; } catch (\Exception $e) { @@ -219,16 +375,41 @@ class OxapayProvider implements PaymentProviderContract { try { $payload = $request->getContent(); - $signature = $request->header('HMAC'); - $apiSecret = $this->config['merchant_api_key']; + $signature = $request->header('hmac'); // Use lowercase 'hmac' as per official implementation + + if (empty($signature)) { + Log::warning('OxaPay webhook validation failed: missing HMAC header'); - if (empty($signature) || empty($apiSecret)) { return false; } - $expectedSignature = hash_hmac('sha512', $payload, $apiSecret); + // Get webhook data to determine type + $data = $request->json()->all(); + $type = $data['type'] ?? ''; - return hash_equals($expectedSignature, $signature); + // Resolve API key based on webhook type (following official implementation) + $apiKey = $this->resolveApiKeyByType($type); + + if (empty($apiKey)) { + Log::warning('OxaPay webhook validation failed: no API key available for type', [ + 'type' => $type, + ]); + + return false; + } + + $expectedSignature = hash_hmac('sha512', $payload, $apiKey); + + $isValid = hash_equals($expectedSignature, $signature); + + Log::info('OxaPay webhook validation', [ + 'type' => $type, + 'signature_provided' => ! empty($signature), + 'api_key_available' => ! empty($apiKey), + 'valid' => $isValid, + ]); + + return $isValid; } catch (\Exception $e) { Log::error('OxaPay webhook validation failed', [ @@ -239,6 +420,156 @@ class OxapayProvider implements PaymentProviderContract } } + /** + * Resolve API key based on webhook type (following official OxaPay implementation) + */ + private function resolveApiKeyByType(string $type): string + { + // Map webhook types to API key groups per official implementation + $merchantTypes = ['invoice', 'white_label', 'static_address', 'payment_link', 'donation']; + $payoutTypes = ['payout']; + + if (in_array($type, $merchantTypes, true)) { + return $this->config['merchant_api_key'] ?? ''; + } + + if (in_array($type, $payoutTypes, true)) { + return $this->config['payout_api_key'] ?? ''; + } + + // Default to merchant API key for unknown types + return $this->config['merchant_api_key'] ?? ''; + } + + /** + * Handle different webhook statuses + */ + protected function handleWebhookStatus(string $status, array $data): array + { + $trackId = $data['track_id']; + $orderId = $data['order_id'] ?? null; + + switch ($status) { + case 'paying': + // Payment is being processed, show as pending + return $this->updatePaymentStatus($trackId, 'paying', $data); + + case 'paid': + // Payment completed successfully + return $this->updatePaymentStatus($trackId, 'paid', $data); + + case 'underpaid': + // Partial payment received + return $this->updatePaymentStatus($trackId, 'underpaid', $data); + + case 'expired': + // Payment expired + return $this->updatePaymentStatus($trackId, 'expired', $data); + + case 'refunded': + // Payment was refunded + return $this->updatePaymentStatus($trackId, 'refunded', $data); + + case 'manual_accept': + // Manually accepted + return $this->updatePaymentStatus($trackId, 'manual_accept', $data); + + default: + Log::warning('Unknown OxaPay webhook status', [ + 'status' => $status, + 'track_id' => $trackId, + ]); + + return ['status' => 'unknown', 'message' => "Unknown status: {$status}"]; + } + } + + /** + * Update payment status in local system + */ + protected function updatePaymentStatus(string $trackId, string $status, array $data): array + { + try { + // Find subscription by provider subscription ID (track_id) + $subscription = Subscription::where('provider', 'oxapay') + ->where('provider_subscription_id', $trackId) + ->first(); + + if (! $subscription) { + Log::warning('OxaPay webhook: Subscription not found', [ + 'track_id' => $trackId, + 'status' => $status, + ]); + + return [ + 'status' => 'not_found', + 'message' => 'Subscription not found for track_id: '.$trackId, + ]; + } + + // Update subscription based on payment status + $updateData = [ + 'provider_data' => array_merge($subscription->provider_data ?? [], $data), + 'last_provider_sync' => now(), + ]; + + // Map OxaPay statuses to Laravel subscription statuses + switch ($status) { + case 'paying': + case 'underpaid': + $updateData['status'] = 'pending_payment'; + $updateData['unified_status'] = 'pending_payment'; + break; + + case 'paid': + case 'manual_accept': + $updateData['status'] = 'active'; + $updateData['unified_status'] = 'active'; + $updateData['starts_at'] = now(); + break; + + case 'refunded': + $updateData['status'] = 'cancelled'; + $updateData['unified_status'] = 'cancelled'; + $updateData['cancelled_at'] = now(); + break; + + case 'expired': + $updateData['status'] = 'expired'; + $updateData['unified_status'] = 'expired'; + $updateData['ends_at'] = now(); + break; + } + + $subscription->update($updateData); + + Log::info('OxaPay subscription updated', [ + 'subscription_id' => $subscription->id, + 'track_id' => $trackId, + 'status' => $status, + 'new_status' => $updateData['status'], + ]); + + return [ + 'status' => 'updated', + 'subscription_id' => $subscription->id, + 'new_status' => $updateData['status'], + ]; + + } catch (\Exception $e) { + Log::error('OxaPay payment status update failed', [ + 'track_id' => $trackId, + 'status' => $status, + 'error' => $e->getMessage(), + ]); + + return [ + 'status' => 'error', + 'message' => $e->getMessage(), + ]; + } + } + public function getConfiguration(): array { return $this->config; @@ -246,14 +577,127 @@ class OxapayProvider implements PaymentProviderContract public function syncSubscriptionStatus(Subscription $subscription): array { - throw new \Exception('OxaPay does not support recurring subscriptions'); + try { + $trackId = $subscription->provider_subscription_id; + + if (empty($trackId)) { + throw new \Exception('No track_id found for subscription'); + } + + Log::info('Syncing OxaPay subscription status', [ + 'subscription_id' => $subscription->id, + 'track_id' => $trackId, + ]); + + $response = Http::withHeaders([ + 'merchant_api_key' => $this->merchantApiKey, + 'Content-Type' => 'application/json', + ])->get("{$this->baseUrl}/payment/{$trackId}"); + + if (! $response->successful()) { + throw new \Exception('Failed to fetch payment status from OxaPay'); + } + + $data = $response->json(); + + if (! isset($data['data'])) { + throw new \Exception('Invalid response from OxaPay API'); + } + + $paymentData = $data['data']; + $oxapayStatus = $paymentData['status'] ?? 'unknown'; + + // Map OxaPay status to Laravel subscription status + $statusMapping = [ + 'paying' => 'pending_payment', + 'underpaid' => 'pending_payment', + 'paid' => 'active', + 'manual_accept' => 'active', + 'expired' => 'expired', + 'refunded' => 'cancelled', + ]; + + $newStatus = $statusMapping[$oxapayStatus] ?? 'pending_payment'; + + // Update subscription with latest data + $updateData = [ + 'status' => $newStatus, + 'unified_status' => $newStatus, + 'provider_data' => array_merge($subscription->provider_data ?? [], $paymentData), + 'last_provider_sync' => now(), + ]; + + // Add timestamps based on status + switch ($newStatus) { + case 'active': + if (! $subscription->starts_at) { + $updateData['starts_at'] = now(); + } + break; + case 'expired': + $updateData['ends_at'] = now(); + break; + case 'cancelled': + $updateData['cancelled_at'] = now(); + break; + } + + $subscription->update($updateData); + + Log::info('OxaPay subscription synced successfully', [ + 'subscription_id' => $subscription->id, + 'track_id' => $trackId, + 'oxapay_status' => $oxapayStatus, + 'new_status' => $newStatus, + ]); + + return [ + 'success' => true, + 'status' => $newStatus, + 'oxapay_status' => $oxapayStatus, + 'provider_data' => $paymentData, + ]; + + } catch (\Exception $e) { + Log::error('OxaPay subscription sync failed', [ + 'subscription_id' => $subscription->id, + 'error' => $e->getMessage(), + ]); + + return [ + 'success' => false, + 'error' => $e->getMessage(), + ]; + } + } + + /** + * Calculate subscription end date based on plan billing cycle days + */ + protected function calculateSubscriptionEndDate(Plan $plan): ?Carbon + { + try { + // Use billing_cycle_days from plans table + $billingCycleDays = $plan->billing_cycle_days ?? 30; + + return now()->addDays($billingCycleDays); + + } catch (\Exception $e) { + Log::error('Failed to calculate subscription end date', [ + 'plan_id' => $plan->id, + 'error' => $e->getMessage(), + ]); + + // Safe fallback: 30 days + return now()->addDays(30); + } } public function getPaymentMethodDetails(string $paymentId): array { try { $response = Http::withHeaders([ - 'merchant_api_key' => $this->config['merchant_api_key'], + 'merchant_api_key' => $this->merchantApiKey, ])->get("{$this->baseUrl}/payment/info", [ 'track_id' => $paymentId, ]); @@ -294,7 +738,7 @@ class OxapayProvider implements PaymentProviderContract { try { $response = Http::withHeaders([ - 'merchant_api_key' => $this->config['merchant_api_key'], + 'merchant_api_key' => $this->merchantApiKey, ])->get("{$this->baseUrl}/payment/history", array_merge([ 'email' => $user->email, ], $filters)); diff --git a/resources/views/livewire/settings/billing.blade.php b/resources/views/livewire/settings/billing.blade.php index 33ab377..970218b 100644 --- a/resources/views/livewire/settings/billing.blade.php +++ b/resources/views/livewire/settings/billing.blade.php @@ -116,7 +116,7 @@ @endif - @if($latestActiveSubscription->isActive() && in_array($latestActiveSubscription->provider, ['activation_key'])) + @if($latestActiveSubscription->isActive() && in_array($latestActiveSubscription->provider, ['activation_key', 'oxapay'])) - \ No newline at end of file + diff --git a/routes/web.php b/routes/web.php index 9752c92..6f575ea 100644 --- a/routes/web.php +++ b/routes/web.php @@ -2,27 +2,6 @@ use App\Http\Controllers\AppController; -// DEBUG: Test route to check PolarProvider -Route::get('/debug-polar', function () { - try { - $provider = new \App\Services\Payments\Providers\PolarProvider; - - return response()->json([ - 'status' => 'success', - 'provider_class' => get_class($provider), - 'is_active' => $provider->isActive(), - 'config' => $provider->getConfiguration(), - 'sandbox' => $provider->config['sandbox'] ?? 'unknown', - 'timestamp' => '2025-12-04-17-15-00', - ]); - } catch (\Exception $e) { - return response()->json([ - 'status' => 'error', - 'message' => $e->getMessage(), - 'trace' => $e->getTraceAsString(), - ]); - } -}); use App\Http\Controllers\ImpersonationController; use App\Http\Controllers\WebhookController; use App\Http\Middleware\CheckPageSlug; @@ -180,7 +159,7 @@ Route::middleware(['auth'])->group(function (): void { Route::get('settings/appearance', Appearance::class)->name('settings.appearance'); }); -Route::post('/webhook/oxapay', [WebhookController::class, 'oxapay'])->name('webhook.oxapay'); +Route::post('/webhook/oxapayLegacy', [WebhookController::class, 'oxapay'])->name('webhook.oxapayLegacy'); // Unified Payment System Routes require __DIR__.'/payment.php';