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/qas.sports-crowd.com/app/Http/Controllers/WompiController.php
<?php

namespace App\Http\Controllers;

use App\Core\Order\Application\OrderService;
use App\Core\Payment\Application\PaymentTransactionService;
use App\Core\Ticket\Application\TicketService;
use App\Order;
use App\TicketMain;
use App\GatewayPayment;
use Illuminate\Http\Request;
use App\Http\Controllers\Api\LealPayController;
use App\Http\Controllers\Interfaces\PaymentGatewayControllerInterface;
use Illuminate\Http\Response;

class WompiController extends PaymentGatewayBridgeController implements PaymentGatewayControllerInterface
{

    private $util;
    private $expirationTimeDefault = 30;   // Tiempo dado en minutos
    private $orderService;
    private $ticketService;
    private $paymentTransactionService;

    public function __construct()
    {
        $this->determinateWebService('wompi', 'wompi');
        $this->util = new UtilController();
        $this->orderService = new OrderService();
        $this->ticketService = new TicketService();
        $this->paymentTransactionService = new PaymentTransactionService();
    }

    public function index($order)
    {
        // Verifico sin consultar a Wompi.
        if ($order->gw_state == 'CONFIRMED') {
            $this->validateUserPointsAccumulation($order);
            return view("wompi.webcheckout-done");
        }

        // Consulto a Wompi el estado
        $this->updateStatusOrderFromReference($order->id);
        $order = Order::where('id', $order->id)->first();
        if ($order->gw_state == 'CONFIRMED') {
            $this->validateUserPointsAccumulation($order);
            return view("wompi.webcheckout-done");
        }

        $order->gw_code_transaction = strtoupper(hash("md5", $order->id)) . '_' . $order->code;
        $order->gw_state = "PENDING";
        $order->update();

        $amountInCents = $order->total_price * 100;
        $expirationTime = $this->expirationTime();
        $signature = $this->generateSignature($order->gw_code_transaction, $amountInCents, $this->gatewayData->currency, $this->gatewayData->client_signature, $expirationTime);

        return view("wompi.webcheckout")
            ->with('gateway_data', $this->gatewayData)
            ->with('amountInCents', $amountInCents)
            ->with('reference', $order->gw_code_transaction)
            ->with('confirm_url', config('app.url') .  '/store/payment?paymentGatewayId=' . $order->gateway_payments_id . '&origin=order')
            ->with('signature', $signature)
            ->with('expirationTime', $expirationTime);
    }

    public function ticketIndex($ticket)
    {
        // Verifico sin consultar a Wompi.
        if ($ticket->payment_state == 'CONFIRMED') {
            return view("wompi.webcheckout-done");
        }

        // Consulto a Wompi el estado
        $this->updateStatusTicketFromReference($ticket->id);
        $ticket = TicketMain::where('id', $ticket->id)->first();
        if ($ticket->payment_state == 'CONFIRMED') {
            return view("wompi.webcheckout-done");
        }

        // actualizamos ticket con la referencia de pago
        $ticket->payment_reference = strtoupper(hash("md5", $ticket->id)) . '_' . $ticket->pin;
        $ticket->payment_state = "PENDING";
        $ticket->update();

        $amountInCents = $ticket->total * 100;
        $expirationTime = $this->expirationTime(25);
        $signature = $this->generateSignature($ticket->payment_reference, $amountInCents, $this->gatewayData->currency, $this->gatewayData->client_signature, $expirationTime);

        return view("wompi.webcheckout")
            ->with('gateway_data', $this->gatewayData)
            ->with('amountInCents', $amountInCents)
            ->with('reference', $ticket->payment_reference)
            ->with('confirm_url', config('app.url') .  '/store/payment?paymentGatewayId=' . $ticket->gateway_payments_id . '&origin=ticket')
            ->with('signature', $signature)
            ->with('expirationTime', $expirationTime);
    }

    public function genericIndex($paymentTransaction, $price, $origin, $clientId, $description)
    {
        if ($paymentTransaction->state == 'CONFIRMED') {
            return view("wompi.webcheckout-done");
        }

        $amountInCents = $price * 100;
        $expirationTime = $this->expirationTime(20);
        $signature = $this->generateSignature($paymentTransaction->reference, $amountInCents, $this->gatewayData->currency, $this->gatewayData->client_signature, $expirationTime);

        return view("wompi.webcheckout")
            ->with('gateway_data', $this->gatewayData)
            ->with('amountInCents', $amountInCents)
            ->with('reference', $paymentTransaction->reference)
            ->with('confirm_url', config('app.url') . '/store/payment?paymentGatewayId=' . $paymentTransaction->gateway_payments_id . '&origin=' . $origin)
            ->with('signature', $signature)
            ->with('expirationTime', $expirationTime);
    }

    public function payment(Request $request)
    {
        // no implemented
    }

    public function webcheckout(Request $request)
    {
        $id = $request->input("uid");

        // Verifico sin consultar a Wompi.
        $o = Order::where('id', $id)->first();
        if ($o->gw_state == 'CONFIRMED') {
            $this->validateUserPointsAccumulation($o);
            return view("wompi.webcheckout-done");
        }

        // Consulto a Wompi el estado
        $this->updateStatusOrderFromReference($id);

        $o = Order::where('id', $id)->first();
        if ($o->gw_state == 'CONFIRMED') {
            $this->validateUserPointsAccumulation($o);
            return view("wompi.webcheckout-done");
        }

        $o->gw_code_transaction = strtoupper(hash("md5", $o->id)) . '_' . $o->code;
        $o->gw_state = "PENDING";
        $o->update();

        $amountInCents = $o->total_price * 100;
        $expirationTime = $this->expirationTime();
        $signature = $this->generateSignature($o->gw_code_transaction, $amountInCents, $this->gatewayData->currency, $this->gatewayData->client_signature, $expirationTime);

        return view("wompi.webcheckout")
            ->with('gateway_data', $this->gatewayData)
            ->with('amountInCents', $amountInCents)
            ->with('reference', $o->gw_code_transaction)
            ->with('confirm_url', config('app.url') . '/store/wompi/confirm')
            ->with('order_id', $id)
            ->with('signature', $signature)
            ->with('expirationTime', $expirationTime);
    }

    public function confirmFromWompi(Request $request)
    {
        $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)) {
            if ($paymentTransaction === $orderPaymentTransaction) {
                $this->orderService->setPaymentGatewayTxId($paymentTransaction, $request->id);
            }

            if ($paymentTransaction === $ticketPaymentTransaction) {
                $this->ticketService->setPaymentGatewayTxId($paymentTransaction, $request->id);
            }

            if ($paymentTransaction === $genericPaymentTransaction) {
                $this->paymentTransactionService->setPaymentGatewayTxId($paymentTransaction, $request->id);
            }
        }

        $processPayment = new PaymentController($request);
        return $processPayment->payment($request);
    }

    public function updateStatusOrderFromID($wompi_id)
    {
        $client = new \GuzzleHttp\Client();
        $response = $client->get($this->urlApi . "/transactions/" . $wompi_id);

        $body = $response->getBody()->getContents();
        $body = json_decode($body);

        $o = Order::where('gw_code_transaction', $body->data->reference)->first();
        $o->gw_state = $body->data->status == "APPROVED" ? "CONFIRMED" : "PENDING";
        $o->update();
        if ($o->gw_state == 'CONFIRMED') {
            $this->validateUserPointsAccumulation($o);
        }
        return $this->webcheckoutConfirm($o, null);
    }

    public function updateStatusOrderFromReference($order_id)
    {
        $o = Order::where('id', $order_id)->first();

        $client = new \GuzzleHttp\Client();
        $response = $client->get($this->urlApi . "/transactions?reference=" . $o->gw_code_transaction, [
            'headers' => ['Authorization' => 'Bearer ' . $this->privateKey]
        ]);

        $body = $response->getBody()->getContents();
        $body = json_decode($body);

        if ($body->data && count($body->data)) {
            $order = end($body->data);
            $isApproved = collect($body->data)->where('status', "APPROVED")->first();
            if ($isApproved) {
                $order = $isApproved;
            }
            if ($order->status == "APPROVED") {
                $o->gw_state = "CONFIRMED";
                $o->update();
            }
        }
    }

    public function updateStatusTicketFromReference($ticketId)
    {
        $o = TicketMain::where('id', $ticketId)
            ->with(['ticket_user_blocks' => function ($q) {
                $q->where('ticket_user_blocks.is_social_distancing', false);
            }])
            ->first();

        $client = new \GuzzleHttp\Client();
        $response = $client->get($this->urlApi . "/transactions?reference=" . $o->payment_reference, [
            'headers' => ['Authorization' => 'Bearer ' . $this->privateKey]
        ]);

        $body = $response->getBody()->getContents();
        $body = json_decode($body);

        if ($body->data && count($body->data)) {
            $ticket = end($body->data);
            $isApproved = collect($body->data)->where('status', "APPROVED")->first();
            if ($isApproved) {
                $ticket = $isApproved;
            }
            if ($ticket->status == "APPROVED") {
                $paymentState = true;
                if (!$o->ticket_user_blocks->isEmpty()) {
                    $tickets = new TicketsController();
                    $paymentState = $tickets->generateTickets($o->ticket_user_blocks, $o->id);
                }
                if ($paymentState) {
                    $o->payment_state = "CONFIRMED";
                    $o->payment_comment = $ticket->status;
                    $o->update();
                }
            }
        }
    }

    public function getStatusTransaction($order_id)
    {
        $o = Order::where('id', $order_id)->first();
        $client = new \GuzzleHttp\Client();

        $response = $client->post($this->urlApi . "/transactions?reference=" . $o->gw_code_transaction, [
            'headers' => ['Authorization' => $this->privateKey]
        ]);

        $body = $response->getBody()->getContents();
        return json_decode($body);
    }

    public function validateUserPointsAccumulation($order)
    {
        $pay = new LealPayController();
        $pay->validateUserPointsAccumulation($order);
    }

    public function webhooksListener(Request $request)
    {
        $this->util->logFile($request);
        $requestContent = json_decode($request->getContent());
        $gatewayTxId = $requestContent->data->transaction->id;
        $reference = $requestContent->data->transaction->reference;

        $orderPaymentTransaction = $this->orderService->getByReference($reference);
        $ticketPaymentTransaction = $this->ticketService->getByReference($reference);
        $genericPaymentTransaction = $this->paymentTransactionService->getByReference($reference);

        $paymentTransaction = $orderPaymentTransaction ?? $ticketPaymentTransaction ?? $genericPaymentTransaction;

        if (!is_null($paymentTransaction)) {
            if ($paymentTransaction === $orderPaymentTransaction) {
                $this->orderService->setPaymentGatewayTxId($paymentTransaction, $gatewayTxId);
                $this->orderService->validatePayment($paymentTransaction);
            }

            if ($paymentTransaction === $ticketPaymentTransaction) {
                $this->ticketService->setPaymentGatewayTxId($paymentTransaction, $gatewayTxId);
                $this->ticketService->validatePayment($paymentTransaction);
            }

            if ($paymentTransaction === $genericPaymentTransaction) {
                $this->paymentTransactionService->setPaymentGatewayTxId($paymentTransaction, $gatewayTxId);
                $this->paymentTransactionService->validatePayment($paymentTransaction);
            }
        }

        return response('OK', Response::HTTP_OK);
    }

    // TODO: old function, this can be removed in further commits
    public function webhooksListenerOld(Request $request)
    {
        $this->util->logFile($request);
        $requestContent = json_decode($request->getContent(), true);

        if ($requestContent['event'] != "transaction.updated") {
            return response(array('r' => false, 'm' => "Recibido", 'd' => 'El evento es de nequi'));
        }

        $paymentReference = $requestContent['data']['transaction']['reference'];
        $paymentTransactionId = $requestContent['data']['transaction']['id'];

        switch ($requestContent['data']['transaction']['status']) {
            case 'APPROVED':
                $this->updatePayment(
                    $paymentReference,
                    'CONFIRMED',
                    2,
                    'Transacción confirmada por webhook',
                    $paymentTransactionId
                );
                break;

            case 'VOIDED':
                $this->updatePayment($paymentReference, 'VOIDED', 7, 'Transacción anulada', $paymentTransactionId);
                break;

            case 'DECLINED':
                $this->updatePayment($paymentReference, 'DECLINED', 7, 'Transacción declinada', $paymentTransactionId);
                break;

            case 'ERROR':
                $this->updatePayment($paymentReference, 'ERROR', 7, 'Error en la trasacción', $paymentTransactionId);
                break;
        }

        return response(array('r' => true, 'm' => "Recibido", 'd' => null));
    }

    public function getTransactionByReference(Request $request)
    {
        $idTransaction = $request["idTransaction_value"];
        $refTransaction = $request["refTransaction_value"];
        $payment = GatewayPayment::where("id", $request["account_value"])->first();
        $private_key = $payment->client_secret;
        $_gw_url = $payment->gw_url_prd;

        try {
            if ($payment) {
                if ($refTransaction) {
                    $d = $this->getStatusTransactionByReference($refTransaction, $_gw_url, $private_key);
                    $response = array('r' => true, 'd' => $d);
                }

                if ($idTransaction) {
                    $d = [$this->getStatusTransactionId($idTransaction, $_gw_url, $private_key)];
                    $response = array('r' => true, 'd' => array('data' => $d));
                }
            } else {
                $response = array('r' => false, 'm' => trans('mal'));
            }
        } catch (\Throwable $th) {
            $response = array("r" => false, "type" => "error", "title" => "Oops...", "m" => $th->getMessage());
        }

        return response()->json($response);
    }

    public function getStatusTransactionByReference($code_transaction, $gw_url, $private_key)
    {
        $client = new \GuzzleHttp\Client();

        $response = $client->get($gw_url . "/transactions?reference=" . $code_transaction, [
            'headers' => ['Authorization' => 'Bearer ' . $private_key]
        ]);

        $body = $response->getBody()->getContents();
        return json_decode($body);
    }

    public function getStatusTransactionId($id_transaction, $gw_url, $private_key)
    {
        $client = new \GuzzleHttp\Client();

        $response = $client->get($gw_url . "/transactions/" . $id_transaction, [
            'headers' => ['Authorization' => 'Bearer ' . $private_key]
        ]);

        $body = $response->getBody()->getContents();
        return json_decode($body);
    }

    private function getTransactionByRerefenceFromPaymentGateway($paymentReference)
    {
        $httpClient = new \GuzzleHttp\Client();
        $response = $httpClient->get($this->urlApi . "/transactions?reference=" . $paymentReference, [
            'headers' => ['Authorization' => 'Bearer ' . $this->privateKey]
        ]);

        $body = $response->getBody()->getContents();
        return json_decode($body);
    }

    public function validatePayment($transactionId, $reference)
    {
        $apiResponse = $this->getTransactionByRerefenceFromPaymentGateway($reference);
        $apiResponse = end($apiResponse->data);

        if (isset($apiResponse->status)) {
            switch ($apiResponse->status) {
                case 'APPROVED':
                    $this->updatePayment(
                        $reference,
                        'CONFIRMED',
                        2,
                        'Transacción confirmada por validación',
                        $apiResponse->id
                    );
                    break;

                case 'VOIDED':
                    $this->updatePayment($reference, 'VOIDED', 7, 'Transacción anulada', $apiResponse->id);
                    break;

                case 'DECLINED':
                    $this->updatePayment($reference, 'DECLINED', 7, 'Transacción declinada',  $apiResponse->id);
                    break;

                case 'ERROR':
                    $this->updatePayment($reference, 'ERROR', 7, 'Error en la transacción',  $apiResponse->id);
                    break;
            }
        }
    }
    /**
     * @param Request $request
     * @return mixed
     */
    public function responseTransaction(Request $request) {}

    public function referenceValidator()
    {
        $gateways = GatewayPayment::where('active', true)->get();
        return view('wompi_reference.wompi_reference', compact('gateways'));
    }

    public function expirationTime($time = null)
    {
        return \Carbon\Carbon::now()->addMinutes($time ?? $this->expirationTimeDefault)->toISOString();
    }

    public function generateSignature($reference, $price, $currency, $clientSignature, $expirationTime = null)
    {
        if (!$expirationTime) {
            $expirationTime = $this->expirationTime();
        }
        $signatureData = ($reference . '' . $price . '' . $currency . '' . $expirationTime . '' . $clientSignature);
        $signature = hash("sha256", $signatureData);
        return $signature;
    }

    public function getAuthorizationCode($gatewayResponse)
    {
        return null;
    }

    public function getPaymentMethod($gatewayResponse)
    {
        return null;
    }
}