HEX
Server: Apache/2.4.41 (Ubuntu)
System: Linux ip-172-31-42-149 5.15.0-1084-aws #91~20.04.1-Ubuntu SMP Fri May 2 07:00:04 UTC 2025 aarch64
User: ubuntu (1000)
PHP: 7.4.33
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
File: /var/www/vhost/disk-apps/teamdemo.sports-crowd.com/app/Http/Controllers/PaymentController.php
<?php

namespace App\Http\Controllers;

use App\Core\Academy\Application\AcademyPurchaseService;
use App\Core\Academy\Application\AcademyTournamentPaymentService;
use App\Core\Academy\Application\ExperiencePaymentService;
use App\Core\Academy\Application\MembershipOrderService;
use App\Core\CorporateIdentity\Application\CorporateIdentityService;
use App\Core\Order\Application\OrderService;
use App\Core\Order\OrderStatusEnum;
use App\Core\Payment\Application\PaymentGatewayService;
use App\Core\Payment\Application\PaymentTransactionService;
use App\Core\Payment\Entities\PaymentIntentResponse;
use App\Core\Payment\PaymentMethodContext;
use App\Core\Payment\PaymentStatusEnum;
use App\Core\Ticket\Application\TicketService;
use App\Parameter;
use Illuminate\Http\Request;

class PaymentController extends Controller
{
    private $paymentGateway;
    private $paymentGatewayData;
    private $paymentContext;
    private $paymentGatewayService;
    private $orderService;
    private $ticketService;
    private $paymentTransactionService;
    private $academyPurchaseService;
    private $academyTournamentPaymentService;
    private $membershipOrderService;
    private $experiencePaymentService;

    private $postPurchaseTeamImage;
    private $appOrigin;

    public function __construct(Request $request)
    {
        $this->paymentGatewayService = new PaymentGatewayService();
        $this->orderService = new OrderService();
        $this->ticketService = new TicketService();
        $this->paymentTransactionService = new PaymentTransactionService();
        $this->academyPurchaseService = new AcademyPurchaseService();
        $this->academyTournamentPaymentService = new AcademyTournamentPaymentService();
        $this->membershipOrderService = new MembershipOrderService();
        $this->experiencePaymentService = new ExperiencePaymentService();

        if ($request->paymentGatewayId || $request->paymentgatewayid) {
            $this->initGateway($request);

            // TODO: move to a service, check if we can use a singleton pattern here
            $parameters = Parameter::first();
            $this->postPurchaseTeamImage = $parameters->image_url_finish_payment ? $parameters->image_url_finish_payment . ('?dc=' . \Carbon\Carbon::now()->getTimestamp()) : '';
        }
    }

    public function webcheckout(Request $request)
    {
        $this->appOrigin = $request->appOrigin;
        if ($request->has("uid")) {
            $this->payOrder($request->uid);
        }

        if ($request->has("ticketId")) {
            $this->payTicket($request->ticketId);
        }

        if ($request->has("academyPurchaseId")) {
            $this->payAcademyPurchase($request->academyPurchaseId);
        }

        if ($request->has("academyTournamentPaymentId")) {
            $this->payAcademyTournament($request->academyTournamentPaymentId);
        }

        if ($request->has("membershipId")) {
            $this->payMembership($request->membershipId);
        }

        if ($request->has("experiencePaymentId")) {
            $this->payExperience($request->experiencePaymentId);
        }
    }

    public function payment(Request $request)
    {
        $origin = null;
        $orderPaymentTransaction = $this->orderService->getByReference($request->reference);
        $ticketPaymentTransaction = $this->ticketService->getByReference($request->reference);
        $genericPaymentTransaction = $this->paymentTransactionService->getByReference($request->reference);

        $paymentTransaction = $orderPaymentTransaction ?? $ticketPaymentTransaction ?? $genericPaymentTransaction;
        $paymentData = null;
        if (!is_null($paymentTransaction)) {
            if ($paymentTransaction === $orderPaymentTransaction) {
                $paymentData = $this->orderService->validatePayment($paymentTransaction);
                $origin = "order";
            }

            if ($paymentTransaction === $ticketPaymentTransaction) {
                $paymentData = $this->ticketService->validatePayment($paymentTransaction);
                $origin = "ticket";
            }

            if ($paymentTransaction === $genericPaymentTransaction) {
                $paymentData = $this->paymentTransactionService->validatePayment($paymentTransaction);
                $origin = "generic";
            }
        }

        if (!$paymentData) {
            return response()->json([
                'r' => false,
                'm' => 'Payment not found'
            ]);
        }

        if ($paymentData->status() == PaymentStatusEnum::CONFIRMED) {
            $webcheckoutConfirmData = [
                'state' => $paymentData->status(),
                'comment' => 'Venta exitosa',
                'origin' => $origin,
                'appOrigin' => $request->appOrigin
            ];
        } else {
            $webcheckoutConfirmData = [
                'state' => $paymentData->status(),
                'comment' => $paymentData->status(),
                'origin' => $origin,
                'appOrigin' => $request->appOrigin
            ];
        }

        return $this->webcheckoutConfirm($webcheckoutConfirmData, $paymentTransaction, $paymentData);
    }

    public function webcheckoutConfirm($data, $paymentTransaction, $paymentData)
    {
        $is_url_image = $this->postPurchaseTeamImage;
        switch ($data['origin']) {
            case 'ticket':
                $data['message'] = 'messages.paymentResponse.webcheckout_confirm_2';
                break;

            case 'order':
                $data['message'] = 'messages.paymentResponse.webcheckout_confirm_3';
                break;

            default:
                $data['message'] = 'messages.paymentResponse.webcheckout_confirm_7';
                sleep(2); // To wait for finishPayment
                $paymentTransaction = $this->paymentTransactionService->getById($paymentTransaction->id);
                break;
        }

        $corporateIdentity = CorporateIdentityService::get();
        return view('paymentResponse.webcheckout-confirm', compact('is_url_image', 'data', 'corporateIdentity'))
            ->with("paymentTransaction", $paymentTransaction)
            ->with("paymentData", $paymentData);
    }

    public function webhooksListener(Request $request)
    {
        return $this->paymentGateway->webhooksListener($request);
    }

    public function getTransactionByReference(Request $request)
    {
        $origin = null;
        $orderPaymentTransaction = $this->orderService->getByReference($request->reference);
        $ticketPaymentTransaction = $this->ticketService->getByReference($request->reference);
        $genericPaymentTransaction = $this->paymentTransactionService->getByReference($request->reference);

        $paymentTransaction = $orderPaymentTransaction ?? $ticketPaymentTransaction ?? $genericPaymentTransaction;
        if (!is_null($paymentTransaction)) {
            try {
                if ($paymentTransaction === $orderPaymentTransaction) {
                    $paymentData = $this->orderService->validatePayment($paymentTransaction);
                    $origin = "order";
                }

                if ($paymentTransaction === $ticketPaymentTransaction) {
                    $paymentData = $this->ticketService->validatePayment($paymentTransaction);
                    $origin = "ticket";
                }

                if ($paymentTransaction === $genericPaymentTransaction) {
                    $paymentData = $this->paymentTransactionService->validatePayment($paymentTransaction);
                    $origin = "generic";
                }

                return response()->json([
                    'r' => true,
                    'd' => [
                        'data' => array_merge(['origin' => $origin], $paymentData->toArray())
                    ]
                ]);
            } catch (\Throwable $th) {
                return response()->json([
                    'r' => false,
                    'm' => $th->getMessage()
                ]);
            }
        } else {
            return response()->json([
                'r' => false,
                'm' => 'Payment not found'
            ]);
        }
    }

    public function confirmTransaction(Request $request)
    {
        return $this->paymentGateway->confirmTransaction($request);
    }

    public function validatePayment($paymentGatewayId, $transactionId, $reference)
    {
        $this->paymentGateway->validatePayment($transactionId, $reference);
    }

    public function responseTransaction(Request $request)
    {
        return $this->paymentGateway->responseTransaction($request);
    }

    private function initGateway($request): void
    {
        $this->paymentGatewayData = $this->paymentGatewayService->find(
            (int) ($request->paymentGatewayId ?? $request->paymentgatewayid)
        );

        $this->paymentGatewayData->appOrigin = $request->appOrigin;
        $this->paymentContext = PaymentMethodContext::init($this->paymentGatewayData->id);
        $this->paymentContext->setExtraConfirmUrlData(['appOrigin' => $request->appOrigin]);
        $this->paymentGateway = new $this->paymentGatewayData->class;
    }

    private function payOrder($orderId)
    {
        $order = $this->orderService->find((int) $orderId);

        $isPending = $this->orderService->isProcessingPayment($order);
        if ($isPending) {
            return $this->paymentAlreadyDone(__('messages.paymentResponse.payment_pending'));
        }

        // check confirmed order before go to processor
        if ($this->orderService->isPaymentConfirmed($order)) {
            return $this->paymentAlreadyDone("La orden ya registra un pago.");
        }

        $currentPaymentStatus = $this->paymentContext->retrieveOrderPayment($order);

        if ($currentPaymentStatus->status() && $currentPaymentStatus->status() == OrderStatusEnum::CONFIRMED) {
            $this->orderService->setOrderAsConfirmed($order);
            return $this->paymentAlreadyDone("La orden ya registra un pago.");
        }

        $this->orderService->setPaymentGatewayId($order, $this->paymentGatewayData->id);
        $this->orderService->setOrderAsPending($order);

        $paymentProcessorResponse = $this->paymentContext->payOrder($order);
        $this->orderService->setPaymentGatewayTxId($order, $paymentProcessorResponse->paymentGatewayTxId());

        return $this->processResponse($paymentProcessorResponse);
    }

    private function payTicket($ticketId)
    {
        $ticket = $this->ticketService->find((int) $ticketId);

        $isPending = $this->ticketService->isProcessingPayment($ticket);
        if ($isPending) {
            return $this->paymentAlreadyDone(__('messages.paymentResponse.payment_pending'));
        }

        if ($ticket->payment_state == PaymentStatusEnum::CONFIRMED) {
            return $this->paymentAlreadyDone("El ticket ya registra un pago.");
        }

        $this->ticketService->setTicketAsPending($ticket);
        $this->ticketService->setPaymentGatewayId($ticket, $this->paymentGatewayData->id);

        $currentPaymentStatus = $this->paymentContext->retrieveTicketPayment($ticket);

        if ($currentPaymentStatus->status() == PaymentStatusEnum::CONFIRMED) {
            $this->setTicketAsConfirmed($ticket);
            return $this->paymentAlreadyDone("El ticket ya registra un pago.");
        }

        $paymentProcessorResponse = $this->paymentContext->payTicket($ticket);
        $this->ticketService->setPaymentGatewayTxId($ticket, $paymentProcessorResponse->paymentGatewayTxId());

        return $this->processResponse($paymentProcessorResponse);
    }

    private function payAcademyPurchase($academyPurchasePaymentId)
    {
        $academyPurchase = $this->academyPurchaseService->find($academyPurchasePaymentId);

        $isPending = $this->academyPurchaseService->isProcessingPayment($academyPurchase);
        if ($isPending) {
            return $this->paymentAlreadyDone(__('messages.paymentResponse.payment_pending'));
        }

        $paymentTransaction = $this->academyPurchaseService->getPaymentTransaction(
            $academyPurchase,
            $this->paymentGatewayData->id
        );

        if ($paymentTransaction->state == PaymentStatusEnum::CONFIRMED) {
            return $this->paymentAlreadyDone("Ya existe un pago registrado para este concepto.");
        }

        $this->paymentContext->setMarketplaceId(
            $academyPurchase->academy_user->academy_category->academy_location->marketplace_id ?? null
        );

        $this->paymentTransactionService->setPaymentGatewayId(
            $academyPurchase->payment_transaction,
            $this->paymentGatewayData->id
        );

        $paymentProcessorResponse = $this->paymentContext->payAcademyPurchase($academyPurchase);

        $this->paymentTransactionService->setPaymentGatewayTxId(
            $academyPurchase->payment_transaction,
            $paymentProcessorResponse->paymentGatewayTxId()
        );

        return $this->processResponse($paymentProcessorResponse);
    }

    private function payAcademyTournament($academyTournamentPaymentId)
    {
        $academyTournamentPayment = $this->academyTournamentPaymentService->find($academyTournamentPaymentId);

        $isPending = $this->academyTournamentPaymentService->isProcessingPayment($academyTournamentPayment);
        if ($isPending) {
            return $this->paymentAlreadyDone(__('messages.paymentResponse.payment_pending'));
        }

        $paymentTransaction = $this->academyTournamentPaymentService->getPaymentTransaction(
            $academyTournamentPayment,
            $this->paymentGatewayData->id
        );

        if ($paymentTransaction->state == PaymentStatusEnum::CONFIRMED) {
            return $this->paymentAlreadyDone("Ya existe un pago registrado para este concepto.");
        }

        $this->paymentContext->setMarketplaceId(
            $academyTournamentPayment->academy_user->academy_category->academy_location->marketplace_id ?? null
        );

        $this->paymentTransactionService->setPaymentGatewayId(
            $academyTournamentPayment->payment_transaction,
            $this->paymentGatewayData->id
        );

        $paymentProcessorResponse = $this->paymentContext->payAcademyTournament($academyTournamentPayment);

        $this->paymentTransactionService->setPaymentGatewayTxId(
            $academyTournamentPayment->payment_transaction,
            $paymentProcessorResponse->paymentGatewayTxId()
        );

        return $this->processResponse($paymentProcessorResponse);
    }

    private function payMembership($membershipId)
    {
        try {
            $membershipPayment = $this->membershipOrderService->find($membershipId);
        } catch (\Throwable $th) {
            return $this->paymentAlreadyDone($th->getMessage());
        }

        $isPending = $this->membershipOrderService->isProcessingPayment($membershipPayment);
        if ($isPending) {
            return $this->paymentAlreadyDone(__('messages.paymentResponse.payment_pending'));
        }

        $paymentTransaction = $this->membershipOrderService->getPaymentTransaction($membershipPayment);
        if ($paymentTransaction->state == PaymentStatusEnum::CONFIRMED) {
            return $this->paymentAlreadyDone("Ya existe un pago registrado para este concepto.");
        }

        $this->paymentTransactionService->setPaymentGatewayId(
            $membershipPayment->paymentTransaction,
            $this->paymentGatewayData->id
        );

        $paymentProcessorResponse = $this->paymentContext->payMembership($membershipPayment);

        $this->paymentTransactionService->setPaymentGatewayTxId(
            $membershipPayment->paymentTransaction,
            $paymentProcessorResponse->paymentGatewayTxId()
        );

        return $this->processResponse($paymentProcessorResponse);
    }

    private function payExperience($experiencePaymentId)
    {
        $experiencePayment = $this->experiencePaymentService->find($experiencePaymentId);

        $isPending = $this->experiencePaymentService->isProcessingPayment($experiencePayment);
        if ($isPending) {
            return $this->paymentAlreadyDone(__('messages.paymentResponse.payment_pending'));
        }

        $paymentTransaction = $this->experiencePaymentService->getPaymentTransaction($experiencePayment);
        if ($paymentTransaction->state == PaymentStatusEnum::CONFIRMED) {
            return $this->paymentAlreadyDone("Ya existe un pago registrado para este concepto.");
        }

        $this->paymentTransactionService->setPaymentGatewayId(
            $experiencePayment->payment_transaction,
            $this->paymentGatewayData->id
        );

        $paymentProcessorResponse = $this->paymentContext->payExperience($experiencePayment);

        $this->paymentTransactionService->setPaymentGatewayTxId(
            $experiencePayment->payment_transaction,
            $paymentProcessorResponse->paymentGatewayTxId()
        );

        return $this->processResponse($paymentProcessorResponse);
    }

    private function processResponse(PaymentIntentResponse $response)
    {
        if ($response->action() == PaymentIntentResponse::ACTION_SHOW) {
            return response()->view($response->view(), $response->data())->send();
        }

        if ($response->action() == PaymentIntentResponse::ACTION_REDIRECT) {
            return redirect()->to($response->redirectUrl(), 302)->send();
        }

        if ($response->action() == PaymentIntentResponse::ACTION_FAILED) {
            $message = $response->message();
            $is_url_image = $this->postPurchaseTeamImage;
            return response()->view($response->redirectUrl(), compact('message', 'is_url_image'))->send();
        }
    }

    private function paymentAlreadyDone($message)
    {
        $is_url_image = $this->postPurchaseTeamImage;
        $appOrigin = $this->appOrigin;
        return response()->view("paymentResponse.webcheckout-done", compact('message', 'is_url_image', 'appOrigin'))->send();
    }

    public function getAuthorizationCode($paymentTransaction)
    {
        return $this->paymentGateway->getAuthorizationCode($paymentTransaction->gateway_response);
    }

    public function validatePaymentAvailability(Request $request)
    {
        if ($request->has("academyPurchaseId")) {
            return $this->validatePayAcademyPurchase($request->academyPurchaseId);
        }

        if ($request->has("academyTournamentPaymentId")) {
            return $this->validatePayAcademyTournament($request->academyTournamentPaymentId);
        }

        return $this->responseSuccess(__('messages.paymentResponse.payment_available'));
    }

    public function validatePayAcademyPurchase($academyPurchaseId)
    {
        $academyPurchase = $this->academyPurchaseService->find($academyPurchaseId);

        if ($this->academyPurchaseService->isPaymentConfirmed($academyPurchase)) {
            return $this->reponseWarning(__('messages.paymentResponse.payment_confirmed'));
        } else if ($this->academyPurchaseService->isProcessingPayment($academyPurchase)) {
            return $this->reponseWarning(__('messages.paymentResponse.payment_pending'));
        }

        return $this->responseSuccess(__('messages.paymentResponse.payment_available'));
    }

    private function validatePayAcademyTournament($academyTournamentPaymentId)
    {
        $academyTournamentPayment = $this->academyTournamentPaymentService->find($academyTournamentPaymentId);

        if ($this->academyTournamentPaymentService->isPaymentConfirmed($academyTournamentPayment)) {
            return $this->reponseWarning(__('messages.paymentResponse.payment_confirmed'));
        } else if ($this->academyTournamentPaymentService->isProcessingPayment($academyTournamentPayment)) {
            return $this->reponseWarning(__('messages.paymentResponse.payment_pending'));
        }

        return $this->responseSuccess(__('messages.paymentResponse.payment_available'));
    }

    private function reponseWarning($message)
    {
        return array('r' => false, 'm' => $message);
    }

    private function responseSuccess($message)
    {
        return array('r' => true, 'm' => $message);
    }

    public function getPaymentMethod($paymentTransaction)
    {
        return $this->paymentGateway->getPaymentMethod($paymentTransaction->gateway_response);
    }
}