HEX
Server: Apache/2.4.58 (Ubuntu)
System: Linux ip-172-26-0-120 6.17.0-1009-aws #9~24.04.2-Ubuntu SMP Fri Mar 6 23:50:29 UTC 2026 x86_64
User: ubuntu (1000)
PHP: 8.3.6
Disabled: NONE
Upload Files
File: /var/www/html/spion/app/Http/Controllers/PaymentsController.php
<?php

namespace App\Http\Controllers;

use App\Models\Plan;
use App\Models\UserSubscription;
use App\Models\UserTransaction;
use App\Models\UserWebsite;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Razorpay\Api\Api;
use Razorpay\Api\Errors\BadRequestError;
use Razorpay\Api\Errors\UnauthorizedError;
use Razorpay\Api\Errors\MethodNotAllowedError;

class PaymentsController extends Controller
{
    public function buy_subscription_plan(Request $request)
    {
        $request->validate([
            'plan_id' => 'required|string|exists:plans,key',
            'website_id' => 'nullable|string',
        ]);
    
        try {
            // Fetch the plan details
            $plan = Plan::where('key', $request->plan_id)->first();
            if (!$plan) {
                return response()->json(['error' => 'Invalid plan selected.'], 400);
            }
    
            // Razorpay credentials
            $razorpayKeyId = env('RAZORPAY_KEY_ID');
            $razorpayKeySecret = env('RAZORPAY_KEY_SECRET');
            $api = new Api($razorpayKeyId, $razorpayKeySecret);
    
            // Create a Razorpay subscription
            try {
                $subscription = $api->subscription->create([
                    'plan_id' => $request->plan_id,
                    'total_count' => 12,  // You can adjust this value based on your requirements
                    'customer_notify' => 1,
                    'notes' => [
                        'plan_name' => $plan->name,
                        'website_id' => $request->website_id,
                        'user_id' => auth()->user()->id ?? null,
                    ],
                ]);
    
                if ($subscription) {
                    // Return the subscription URL as response
                    return response()->json(['subscription_url' => $subscription->short_url]);
                }
    
            } catch (BadRequestError $e) {
                Log::error('Razorpay Subscription Error', ['message' => $e->getMessage()]);
            } catch (\Exception $e) {
                Log::error('General Razorpay Error', ['message' => $e->getMessage()]);
            }
            return response()->json(['error' => 'Unable to create subscription.'], 500);
        } catch (\Exception $e) {
            Log::error('Subscription Plan Error', ['message' => $e->getMessage()]);
            return response()->json(['error' => 'Unable to process subscription. Please try again later.'], 500);
        }
    }
    
    public function handleWebhook(Request $request)
    {

        $input = $request->all();
        Log::info('Webhook Payload:--------' .json_encode($input)); 
        // dd($input);
        // return true;
        if (!isset($input['event'])) {
            Log::error('Event type not found in the payload');
            return response()->json(['status' => 'error', 'message' => 'Event type missing'], 400);
        } 

        $event = $input['event'];

        // Handle events based on their type
        switch ($event) {
            case 'payment.authorized':
                $this->handlePaymentAuthorized($input);
                break;
            case 'payment.failed':
                $this->handlePaymentFailed($input);
                break;
            case 'payment.captured':
                $this->handlePaymentCaptured($input);
                break;
            case 'payment.dispute.created':
                $this->handlePaymentDisputeCreated($input);
                break;
            // case 'order.paid':
            //     $this->handleOrderPaid($input);
            //     break;
            // case 'order.notification.delivered':
            //     $this->handleOrderNotificationDelivered($input);
            //     break;
            // case 'order.notification.failed':
            //     $this->handleOrderNotificationFailed($input);
            //     break;
            // case 'invoice.paid':
            //     $this->handleInvoicePaid($input);
            //     break;
            // case 'invoice.partially_paid':
            //     $this->handleInvoicePartiallyPaid($input);
            //     break;
            // case 'invoice.expired':
            //     $this->handleInvoiceExpired($input);
            //     break;
            case 'subscription.authenticated':
                $this->handleSubscriptionAuthenticated($input);
                break;
            case 'subscription.paused':
                $this->handleSubscriptionPaused($input);
                break;
            case 'subscription.resumed':
                $this->handleSubscriptionResumed($input);
                break;
            case 'subscription.activated':
                $this->handleSubscriptionActivated($input);
                break;
            case 'subscription.pending':
                $this->handleSubscriptionPending($input);
                break;
            case 'subscription.halted':
                $this->handleSubscriptionHalted($input);
                break;
            case 'subscription.charged':
                $this->handleSubscriptionCharged($input);
                break;
            case 'subscription.cancelled':
                $this->handleSubscriptionCancelled($input);
                break;
            case 'subscription.completed':
                $this->handleSubscriptionCompleted($input);
                break;
            case 'subscription.updated':
                $this->handleSubscriptionUpdated($input);
                break;
            // case 'payment.dispute.won':
            //     $this->handlePaymentDisputeWon($input);
            //     break;
            // case 'payment.dispute.lost':
            //     $this->handlePaymentDisputeLost($input);
            //     break;
            // case 'payment.dispute.closed':
            //     $this->handlePaymentDisputeClosed($input);
            //     break;
            // case 'payment.dispute.under_review':
            //     $this->handlePaymentDisputeUnderReview($input);
            //     break;
            // case 'payment.dispute.action_required':
            //     $this->handlePaymentDisputeActionRequired($input);
            //     break;
            // case 'payment.downtime.started':
            //     $this->handlePaymentDowntimeStarted($input);
            //     break;
            // case 'payment.downtime.updated':
            //     $this->handlePaymentDowntimeUpdated($input);
            //     break;
            // case 'payment.downtime.resolved':
            //     $this->handlePaymentDowntimeResolved($input);
            //     break;
            default:
                Log::warning("Unhandled event type: $event");
                break;
        }
        // $statusMap = [
        //     'created' => 1,
        //     'authenticated' => 2,
        //     'active' => 3,
        //     'halted' => 4,
        //     'cancelled' => 5,
        // ];
        // if (isset($input['payload']['subscription']['entity'])) {
        //     $subscription = $input['payload']['subscription']['entity'];
        //     // dd(Carbon::createFromTimestamp($subscription['charge_at'])->format('d-m-Y H:i:s'));
        //     $data = [
        //         'user_id' => $subscription['notes']['user_id'] ?? null,
        //         'website_id' => $subscription['notes']['website_id'] ?? null, 
        //         'plan_name' => $subscription['notes']['plan_name'] ?? null, 
        //         'rz_subscription_id' => $subscription['id'],
        //         'rz_plan_id' => $subscription['plan_id'], 
        //         'customer_id' => $subscription['customer_id'], 
        //         'start_at' => $subscription['start_at'],
        //         'end_at' => $subscription['end_at'],
        //         'rz_quantity' => $subscription['quantity'], 
        //         'rz_status' => $statusMap[$subscription['status']] ?? null,
        //         'charge_at' => $subscription['charge_at'],

        //     ];
        //     // dd($data);
        //     UserSubscription::updateOrCreate(
        //         ['rz_subscription_id' => $subscription['id']], 
        //         $data
        //     );

        //     // Log success
        //     Log::info('Subscription data stored successfully', $data);
        // } else {
        //     // Log error if subscription data is missing
        //     Log::error('Subscription entity not found in the payload');
        // }

        // Return a success response for the webhook
        return response()->json(['status' => 'success']);
    }
    // Function to handle subscription update and save
    protected function handleSubscriptionEvent($input, $status) {
        if (isset($input['payload']['subscription']['entity'])) {
            $subscription = $input['payload']['subscription']['entity'];

            $statusMap = [
                'created' => 1,           // Pending
                'authenticated' => 2,     // Authenticated
                'active' => 3,            // Active
                'halted' => 4,            // Halted
                'cancelled' => 5,         // Cancelled
                'paused' => 6,            // Paused
                'resumed' => 7,           // Resumed
                'charged' => 8,           // Charged
                'completed' => 9,         // Completed
                'updated' => 10,          // Updated
                // 'expired' => 11,          // Expired
                // 'failed' => 12,  
            ];

            // Mapping status using the provided $status
            $statusValue = $statusMap[$status] ?? null;
            $data = [
                'user_id' => $subscription['notes']['user_id'] ?? null,
                'website_id' => $subscription['notes']['website_id'] ?? null, 
                'plan_name' => $subscription['notes']['plan_name'] ?? null, 
                'rz_subscription_id' => $subscription['id'],
                'rz_plan_id' => $subscription['plan_id'], 
                'customer_id' => $subscription['customer_id'], 
                'start_at' => $subscription['start_at'],
                'end_at' => $subscription['end_at'],
                'rz_quantity' => $subscription['quantity'], 
                'rz_status' => $statusValue,
                'charge_at' => $subscription['charge_at'],
            ];

            // Save the subscription data to the database
            UserSubscription::updateOrCreate(
                ['rz_subscription_id' => $subscription['id']], 
                $data
            );
            
            // Add specific logic for payment details
            $payment = $input['payload']['payment']['entity'] ?? null;
            // dd($payment);
            if ($payment) {
                Log::info('Payment details received', $payment);
                // Update the subscription record in the payment transaction
                $transaction = UserTransaction::where('transaction_id', $payment['id'])->first();
                if ($transaction) {
                    $transaction->update(['rz_subscription_id' => $input['payload']['subscription']['entity']['id']]);
                    Log::info('Transaction updated with subscription ID');
                }
            }
            $websiteId = $subscription['notes']['website_id'] ?? null;

            if ($websiteId) {
                Log::info('website ID details received', ['id' => $websiteId]);
            
                // Find the UserWebsite record associated with the website_id
                $userWebsite = UserWebsite::where('id', $websiteId)->first();
            
                if ($userWebsite) {
                    // Update the status to 2
                    $userWebsite->update(['status' => 2]);
                    Log::info('UserWebsite status updated to 2', ['id' => $websiteId]);
                } else {
                    Log::warning('No UserWebsite found for the given website ID', ['id' => $websiteId]);
                }
            }
            // Log success
            Log::info('Subscription data stored successfully', $data);
        } else {
            // Log error if subscription data is missing
            Log::error('Subscription entity not found in the payload');
        }
    }
    protected function handlePaymentAuthorized($input)
    {
        $payment = $input['payload']['payment']['entity'] ?? null;
        if ($payment) {
            $paymentId = $payment['id'];
            $customerId = $payment['customer_id'] ?? null; // Safely retrieve `customer_id` or set to null
            
            // Set the numeric status for 'payment.authorized' event
            $paymentStatus = 1;  // Assuming 'authorized' means pending
            
            Log::info('Payment Authorized', $payment);
    
            // Update or create the transaction record with the 'pending' status (1)
            UserTransaction::updateOrCreate(
                ['transaction_id' => $paymentId], // Check if the transaction already exists
                [
                    'transaction_id' => $paymentId,
                    'customer_id' => $customerId,
                    'pay_status' => $paymentStatus,
                ]
            );
        }
    }
    
    protected function handlePaymentFailed($input)
    {
        $payment = $input['payload']['payment']['entity'] ?? null;
        if ($payment) {
            $paymentId = $payment['id'];
            $customerId = $payment['customer_id'] ?? null; // Safely retrieve `customer_id` or set to null
            
            // Set the numeric status for 'payment.failed' event
            $paymentStatus = 4;  // 'failed' corresponds to status 4
            
            Log::info('Payment Failed', $payment);
    
            // Update or create the transaction record with the 'failed' status (4)
            UserTransaction::updateOrCreate(
                ['transaction_id' => $paymentId], // Check if the transaction already exists
                [
                    'transaction_id' => $paymentId,
                    'customer_id' => $customerId,
                    'pay_status' => $paymentStatus,
                ]
            );
        }
    }
    
    protected function handlePaymentCaptured($input)
    {
        $payment = $input['payload']['payment']['entity'] ?? null;
        if ($payment) {
            $paymentId = $payment['id'];
            $customerId = $payment['customer_id'] ?? null; // Safely retrieve `customer_id` or set to null
            
            // Set the numeric status for 'payment.captured' event
            $paymentStatus = 3;  // 'captured' corresponds to status 3
            
            Log::info('Payment Captured', $payment);
    
            // Update or create the transaction record with the 'paid' status (3)
            UserTransaction::updateOrCreate(
                ['transaction_id' => $paymentId], // Check if the transaction already exists
                [
                    'transaction_id' => $paymentId,
                    'customer_id' => $customerId,
                    'pay_status' => $paymentStatus,
                ]
            );
        }
    }
    
    protected function handlePaymentDisputeCreated($input)
    {
        $dispute = $input['payload']['dispute']['entity'] ?? null;
        if ($dispute) {
            $disputeId = $dispute['id'];
            $paymentId = $dispute['payment_id'];
            
            // Set the numeric status for 'payment.dispute.created' event
            $paymentStatus = 4;  // Dispute status might map to halted (4)
            
            Log::info('Payment Dispute Created', $dispute);
    
            // Update or create the transaction record with the 'halted' status (4)
            UserTransaction::updateOrCreate(
                ['transaction_id' => $paymentId], // Check if the transaction already exists
                [
                    'transaction_id' => $paymentId,
                    'pay_status' => $paymentStatus,
                ]
            );
        }
    }
    
    // protected function handleOrderPaid($input)
    // {
    //     $order = $input['payload']['order']['entity'] ?? null;
    //     if ($order) {
    //         Log::info('Order Paid', $order);
    //         // Add your logic here
    //     }
    // }

    // protected function handleOrderNotificationDelivered($input)
    // {
    //     $notification = $input['payload']['order']['entity'] ?? null;
    //     if ($notification) {
    //         Log::info('Order Notification Delivered', $notification);
    //         // Add your logic here
    //     }
    // }

    // protected function handleOrderNotificationFailed($input)
    // {
    //     $notification = $input['payload']['order']['entity'] ?? null;
    //     if ($notification) {
    //         Log::info('Order Notification Failed', $notification);
    //         // Add your logic here
    //     }
    // }

    // protected function handleInvoicePaid($input)
    // {
    //     $invoice = $input['payload']['invoice']['entity'] ?? null;
    //     if ($invoice) {
    //         Log::info('Invoice Paid', $invoice);
    //         // Add your logic here
    //     }
    // }

    // protected function handleInvoicePartiallyPaid($input)
    // {
    //     $invoice = $input['payload']['invoice']['entity'] ?? null;
    //     if ($invoice) {
    //         Log::info('Invoice Partially Paid', $invoice);
    //         // Add your logic here
    //     }
    // }

    // protected function handleInvoiceExpired($input)
    // {
    //     $invoice = $input['payload']['invoice']['entity'] ?? null;
    //     if ($invoice) {
    //         Log::info('Invoice Expired', $invoice);
    //         // Add your logic here
    //     }
    // }

    // Handle subscription events
    protected function handleSubscriptionAuthenticated($input)
    {
        Log::info('Subscription Authenticated');
        $this->handleSubscriptionEvent($input, 'authenticated');
    }

    protected function handleSubscriptionPaused($input)
    {
        Log::info('Subscription Paused');
        $this->handleSubscriptionEvent($input, 'paused');
    }

    protected function handleSubscriptionResumed($input)
    {
        Log::info('Subscription Resumed');
        $this->handleSubscriptionEvent($input, 'resumed');
    }

    protected function handleSubscriptionActivated($input)
    {
        Log::info('Subscription Activated');
        $this->handleSubscriptionEvent($input, 'active');
    }

    protected function handleSubscriptionPending($input)
    {
        Log::info('Subscription Pending');
        $this->handleSubscriptionEvent($input, 'created');
    }

    protected function handleSubscriptionHalted($input)
    {
        Log::info('Subscription Halted');
        $this->handleSubscriptionEvent($input, 'halted');
    }

    protected function handleSubscriptionCharged($input)
    {
        Log::info('Subscription Charged');
        $this->handleSubscriptionEvent($input, 'charged');
    }

    protected function handleSubscriptionCancelled($input)
    {
        $subscription = $input['payload']['subscription']['entity'] ?? null;
        if ($subscription) {
            Log::info('Subscription Cancelled', $subscription);
            $this->handleSubscriptionEvent($input, 'cancelled');

            // Add your logic here
        }
    }

    protected function handleSubscriptionCompleted($input)
    {
        $subscription = $input['payload']['subscription']['entity'] ?? null;
        if ($subscription) {
            Log::info('Subscription Completed', $subscription);
            $this->handleSubscriptionEvent($input, 'completed');

            // Add your logic here
        }
    }

    protected function handleSubscriptionUpdated($input)
    {
        $subscription = $input['payload']['subscription']['entity'] ?? null;
        if ($subscription) {
            Log::info('Subscription Updated', $subscription);
            $this->handleSubscriptionEvent($input, 'updated');

            // Add your logic here
        }
    }

    // protected function handlePaymentDisputeWon($input)
    // {
    //     $dispute = $input['payload']['dispute']['entity'] ?? null;
    //     if ($dispute) {
    //         Log::info('Payment Dispute Won', $dispute);
    //         // Add your logic here
    //     }
    // }

    // protected function handlePaymentDisputeLost($input)
    // {
    //     $dispute = $input['payload']['dispute']['entity'] ?? null;
    //     if ($dispute) {
    //         Log::info('Payment Dispute Lost', $dispute);
    //         // Add your logic here
    //     }
    // }

    // protected function handlePaymentDisputeClosed($input)
    // {
    //     $dispute = $input['payload']['dispute']['entity'] ?? null;
    //     if ($dispute) {
    //         Log::info('Payment Dispute Closed', $dispute);
    //         // Add your logic here
    //     }
    // }

    // protected function handlePaymentDisputeUnderReview($input)
    // {
    //     $dispute = $input['payload']['dispute']['entity'] ?? null;
    //     if ($dispute) {
    //         Log::info('Payment Dispute Under Review', $dispute);
    //         // Add your logic here
    //     }
    // }

    // protected function handlePaymentDisputeActionRequired($input)
    // {
    //     $dispute = $input['payload']['dispute']['entity'] ?? null;
    //     if ($dispute) {
    //         Log::info('Payment Dispute Action Required', $dispute);
    //         // Add your logic here
    //     }
    // }

    // protected function handlePaymentDowntimeStarted($input)
    // {
    //     $downtime = $input['payload']['downtime']['entity'] ?? null;
    //     if ($downtime) {
    //         Log::info('Payment Downtime Started', $downtime);
    //         // Add your logic here
    //     }
    // }

    // protected function handlePaymentDowntimeUpdated($input)
    // {
    //     $downtime = $input['payload']['downtime']['entity'] ?? null;
    //     if ($downtime) {
    //         Log::info('Payment Downtime Updated', $downtime);
    //         // Add your logic here
    //     }
    // }

    // protected function handlePaymentDowntimeResolved($input)
    // {
    //     $downtime = $input['payload']['downtime']['entity'] ?? null;
    //     if ($downtime) {
    //         Log::info('Payment Downtime Resolved', $downtime);
    //         // Add your logic here
    //     }
    // }

    public function checkSubscriptionStatus(Request $request)
    {

        $websiteId = $request->website_id;

        $planId = $request->plan_id;

        $subscription = UserSubscription::where('website_id', $websiteId)->where('rz_plan_id', $planId)->latest()->first();

        if ($subscription) {
            if (in_array($subscription->rz_status, [2, 3, 8])) {
                return response()->json(['status' => 'success']);
            }
        }

        return response()->json(['status' => 'failed']);
    }
   
    public function subscription_transactions(Request $request)
    {
        $limit = 10; // Items per page
        $currentPage = $request->page ?: 1; // Current page
        $searchTerm = $request->search; // Get the search term from the request

        $query = UserSubscription::with(['website', 'plan', 'transactions'])
            ->where('user_id', auth()->id());

        // Apply search filter
        if ($searchTerm) {
            $query->whereHas('website', function ($query) use ($searchTerm) {
                $query->where('first_name', 'like', '%' . $searchTerm . '%')
                    ->orWhere('last_name', 'like', '%' . $searchTerm . '%')
                    ->orWhere(DB::raw("CONCAT(first_name, ' ', last_name)"), 'like', '%' . $searchTerm . '%');

                })->orWhereHas('plan', function ($query) use ($searchTerm) {
                    $query->where('name', 'like', '%' . $searchTerm . '%')
                    ->orWhere('price', 'like', '%' . $searchTerm . '%');
                })
               ->orWhereHas('transactions', function ($query) use ($searchTerm) {
                    $query->where('transaction_id', 'like', '%' . $searchTerm . '%');
                });
        }

        // Paginate results
        $totalSubscriptions = $query->count();
        $subscriptions = $query
            ->skip(($currentPage - 1) * $limit)
            ->take($limit)
            ->get();

        foreach ($subscriptions as $subscription) {
            $subscription->formatted_start_at = Carbon::parse($subscription->start_at)->format('d-m-Y H:i:s');
        }

        $lastPage = ceil($totalSubscriptions / $limit); // Total pages

        if ($request->ajax()) {
            return response()->json([
                'subscriptions' => $subscriptions,
                'current_page' => $currentPage,
                'last_page' => $lastPage,
            ]);
        }

        return view('user.transactions', compact('subscriptions'));
    }

    public function unsubscribe(Request $request)
    {
        $user = auth()->user();
        
        // Find the subscription to be unsubscribed
        $subscription = UserSubscription::where('user_id', $user->id)
                                         ->where('website_id', $request->website_id)
                                         ->first();
        //  dd($request->website_id);
        if ($subscription) {
            // Update the status to 'inactive' or delete the subscription
            // $subscription->update(['rz_status' => '6']);
            $subscription->delete();

            $websiteId = $request->website_id;

            if ($websiteId) {
                $userWebsite = UserWebsite::where('id', $websiteId)->first();
            
                if ($userWebsite) {
                    // Update the status to 1
                    $userWebsite->update(['status' => 1]);
                    Log::info('UserWebsite status updated to 1', ['id' => $websiteId]);
                } else {
                    Log::warning('No UserWebsite found for the given website ID', ['id' => $websiteId]);
                }
            }
            return response()->json(['status' => 'success', 'message' => 'Subscription successfully removed']);
        }
       
        return response()->json(['status' => 'failure', 'message' => 'Subscription not found']);
    }
    
}