File: /var/www/vhost/disk-apps/demo.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;
}
}