Skip to content

Commit

Permalink
Merge pull request #251 from TransbankDevelopers/refactor/restructure…
Browse files Browse the repository at this point in the history
…-code-flow

refactor: restructure code flow
  • Loading branch information
gasspper authored Aug 14, 2024
2 parents acf66c5 + d87157c commit 92868f6
Show file tree
Hide file tree
Showing 3 changed files with 197 additions and 197 deletions.
64 changes: 22 additions & 42 deletions plugin/src/Controllers/ResponseController.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

use DateTime;
use DateTimeZone;
use Transbank\Plugin\Helpers\PluginLogger;
use Transbank\WooCommerce\WebpayRest\WebpayplusTransbankSdk;
use Transbank\WooCommerce\WebpayRest\Helpers\TransactionResponseHandler;
use Transbank\Webpay\WebpayPlus\Responses\TransactionCommitResponse;
use Transbank\WooCommerce\WebpayRest\Models\Transaction;
use Transbank\WooCommerce\WebpayRest\Helpers\HposHelper;
Expand All @@ -24,14 +26,14 @@ class ResponseController
{
/**
* @var array
*/
protected $pluginConfig;
protected $logger;

/**
* @var PluginLogger
* @var WebpayplusTransbankSdk
* @var TransactionResponseHandler
*/
protected $webpayplusTransbankSdk;
protected array $pluginConfig;
protected PluginLogger $logger;
protected WebpayplusTransbankSdk $webpayplusTransbankSdk;
protected TransactionResponseHandler $transactionResponseHandler;

/**
* ResponseController constructor.
Expand All @@ -43,6 +45,7 @@ public function __construct(array $pluginConfig)
$this->logger = TbkFactory::createLogger();
$this->pluginConfig = $pluginConfig;
$this->webpayplusTransbankSdk = TbkFactory::createWebpayplusTransbankSdk();
$this->transactionResponseHandler = new TransactionResponseHandler();
}

/**
Expand All @@ -57,7 +60,7 @@ public function response($requestMethod, $params)
$this->logger->logInfo('Request: payload -> ' . json_encode($params));

try {
$transaction = $this->webpayplusTransbankSdk->handleRequestFromTbkReturn($params);
$transaction = $this->transactionResponseHandler->handleRequestFromTbkReturn($params);
$wooCommerceOrder = $this->getWooCommerceOrderById($transaction->order_id);
$commitResponse = $this->webpayplusTransbankSdk->commitTransaction($transaction->order_id, $transaction->token);
$this->completeWooCommerceOrder($wooCommerceOrder, $commitResponse, $transaction);
Expand All @@ -66,13 +69,12 @@ public function response($requestMethod, $params)
'order' => $wooCommerceOrder->get_data(),
'transbankTransaction' => $transaction
]);
return wp_redirect($wooCommerceOrder->get_checkout_order_received_url());
$redirectUrl = $wooCommerceOrder->get_checkout_order_received_url();
} catch (TimeoutWebpayException $e) {
$this->throwError($e->getMessage());

do_action('transbank_webpay_plus_timeout_on_form');
$urlWithErrorCode = $this->addErrorQueryParams(wc_get_checkout_url(), BlocksHelper::WEBPAY_TIMEOUT);
return wp_redirect($urlWithErrorCode);
$redirectUrl = $this->addErrorQueryParams(wc_get_checkout_url(), BlocksHelper::WEBPAY_TIMEOUT);
} catch (UserCancelWebpayException $e) {
$params = ['transbank_webpayplus_cancelled_order' => 1];
$redirectUrl = add_query_arg($params, wc_get_checkout_url());
Expand All @@ -81,14 +83,12 @@ public function response($requestMethod, $params)
$this->setOrderAsCancelledByUser($wooCommerceOrder, $transaction);

do_action('transbank_webpay_plus_transaction_cancelled_by_user', $wooCommerceOrder, $transaction);
$urlWithErrorCode = $this->addErrorQueryParams($redirectUrl, BlocksHelper::WEBPAY_USER_CANCELED);
return wp_safe_redirect($urlWithErrorCode);
$redirectUrl = $this->addErrorQueryParams($redirectUrl, BlocksHelper::WEBPAY_USER_CANCELED);
} catch (DoubleTokenWebpayException $e) {
$this->throwError($e->getMessage());

do_action('transbank_webpay_plus_unexpected_error');
$urlWithErrorCode = $this->addErrorQueryParams(wc_get_checkout_url(), BlocksHelper::WEBPAY_DOUBLE_TOKEN);
return wp_redirect($urlWithErrorCode);
$redirectUrl = $this->addErrorQueryParams(wc_get_checkout_url(), BlocksHelper::WEBPAY_DOUBLE_TOKEN);
} catch (InvalidStatusWebpayException $e) {
$errorMessage = 'No se puede confirmar la transacción, estado de transacción invalido.';
$wooCommerceOrder = $this->getWooCommerceOrderById($transaction->order_id);
Expand All @@ -98,8 +98,7 @@ public function response($requestMethod, $params)
'order' => $wooCommerceOrder->get_data(),
'transbankTransaction' => $e->getTransaction()
]);
$urlWithErrorCode = $this->addErrorQueryParams(wc_get_checkout_url(), BlocksHelper::WEBPAY_INVALID_STATUS);
return wp_redirect($urlWithErrorCode);
$redirectUrl = $this->addErrorQueryParams(wc_get_checkout_url(), BlocksHelper::WEBPAY_INVALID_STATUS);
} catch (RejectedCommitWebpayException $e) {
$transaction = $e->getTransaction();
$commitResponse = $e->getCommitResponse();
Expand All @@ -111,7 +110,7 @@ public function response($requestMethod, $params)
'transbankTransaction' => $transaction,
'transbankResponse' => $commitResponse
]);
return wp_redirect($wooCommerceOrder->get_checkout_order_received_url());
$redirectUrl = $wooCommerceOrder->get_checkout_order_received_url();
} catch (CommitWebpayException $e) {
$errorMessage = 'Error al confirmar la transacción de Transbank';
$wooCommerceOrder = $this->getWooCommerceOrderById($transaction->order_id);
Expand All @@ -121,43 +120,24 @@ public function response($requestMethod, $params)
'order' => $wooCommerceOrder->get_data(),
'transbankTransaction' => $e->getTransaction()
]);
$urlWithErrorCode = $this->addErrorQueryParams(wc_get_checkout_url(), BlocksHelper::WEBPAY_COMMIT_ERROR);
return wp_redirect($urlWithErrorCode);
$redirectUrl = $this->addErrorQueryParams(wc_get_checkout_url(), BlocksHelper::WEBPAY_COMMIT_ERROR);
} catch (AlreadyProcessedException $e) {
$errorMessage = 'Error al confirmar la transacción, ya fue procesada anteriormente';
$transaction = $e->getTransaction();
$orderId = $transaction['order_id'];
$wooCommerceOrder = $this->getWooCommerceOrderById($orderId);
$wooCommerceOrder->add_order_note($errorMessage);

if ($e->getFlow() == WebpayplusTransbankSdk::WEBPAY_NORMAL_FLOW) {
return wp_redirect($wooCommerceOrder->get_checkout_order_received_url());
}

$urlWithErrorCode = $this->addErrorQueryParams(wc_get_checkout_url(), BlocksHelper::WEBPAY_ALREADY_PROCESSED);
return wp_redirect($urlWithErrorCode);
$e->getFlow() == TransactionResponseHandler::WEBPAY_NORMAL_FLOW
? $redirectUrl = $wooCommerceOrder->get_checkout_order_received_url()
: $redirectUrl = $this->addErrorQueryParams(wc_get_checkout_url(), BlocksHelper::WEBPAY_ALREADY_PROCESSED);
} catch (\Exception $e) {
$this->throwError($e->getMessage());
do_action('transbank_webpay_plus_unexpected_error');
$urlWithErrorCode = $this->addErrorQueryParams(wc_get_checkout_url(), BlocksHelper::WEBPAY_EXCEPTION);
wp_redirect($urlWithErrorCode);
}
}

/**
* @param $data
*
* @return |null
*/
protected function getTokenWs($data)
{
$token_ws = isset($data['token_ws']) ? $data['token_ws'] : (isset($data['TBK_TOKEN']) ? $data['TBK_TOKEN'] : null);
if (!isset($token_ws)) {
$this->throwError('No se encontró el token');
wp_redirect(wc_get_checkout_url());
$redirectUrl = $this->addErrorQueryParams(wc_get_checkout_url(), BlocksHelper::WEBPAY_EXCEPTION);
}

return $token_ws;
return wp_redirect($redirectUrl);
}

/**
Expand Down
174 changes: 174 additions & 0 deletions plugin/src/Helpers/TransactionResponseHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
<?php

namespace Transbank\WooCommerce\WebpayRest\Helpers;

use Transbank\WooCommerce\WebpayRest\Models\Transaction;
use Transbank\WooCommerce\WebpayRest\WebpayplusTransbankSdk;
use Transbank\Plugin\Exceptions\Webpay\AlreadyProcessedException;
use Transbank\Plugin\Exceptions\Webpay\TimeoutWebpayException;
use Transbank\Plugin\Exceptions\Webpay\UserCancelWebpayException;
use Transbank\Plugin\Exceptions\Webpay\DoubleTokenWebpayException;
use Transbank\WooCommerce\WebpayRest\Helpers\TbkFactory;

class TransactionResponseHandler
{
const WEBPAY_NORMAL_FLOW = 'Normal';
const WEBPAY_TIMEOUT_FLOW = 'Timeout';
const WEBPAY_ABORTED_FLOW = 'Aborted';
const WEBPAY_ERROR_FLOW = 'Error';

const WEBPAY_ALREADY_PROCESSED_MESSAGE = 'La transacción fue procesada anteriormente.';
const WEBPAY_FAILED_FLOW_MESSAGE = 'Transacción no autorizada.';
const WEBPAY_TIMEOUT_FLOW_MESSAGE = 'Tiempo excedido en el formulario de Webpay.';
const WEBPAY_ABORTED_FLOW_MESSAGE = 'Orden anulada por el usuario.';
const WEBPAY_ERROR_FLOW_MESSAGE = 'Orden cancelada por un error en el formulario de pago.';

protected WebpayplusTransbankSdk $webpayPlusTransaction;

public function __construct()
{
$this->webpayPlusTransaction = TbkFactory::createWebpayplusTransbankSdk();
}

private function isTransactionProcessed(string $token): bool
{
$transaction = Transaction::getByToken($token);
$status = $transaction->status;

return $status != Transaction::STATUS_INITIALIZED;
}

private function handleProcessedTransaction(string $token)
{
$transaction = get_object_vars(Transaction::getByToken($token)) ?? null;
$buyOrder = $transaction['buy_order'] ?? null;
$status = $transaction['status'] ?? null;
$logMessage = self::WEBPAY_ALREADY_PROCESSED_MESSAGE;

if ($status == Transaction::STATUS_APPROVED) {
$this->webpayPlusTransaction->logInfoData($buyOrder, $logMessage, $transaction);
throw new AlreadyProcessedException($logMessage, $transaction, self::WEBPAY_NORMAL_FLOW);
}

if ($status == Transaction::STATUS_TIMEOUT) {
$logMessage = self::WEBPAY_TIMEOUT_FLOW_MESSAGE;
$this->webpayPlusTransaction->logInfoData($buyOrder, $logMessage, $transaction);
throw new AlreadyProcessedException($logMessage, $transaction, self::WEBPAY_TIMEOUT_FLOW);
}

if ($status == Transaction::STATUS_ABORTED_BY_USER) {
$logMessage = self::WEBPAY_ABORTED_FLOW_MESSAGE;
$this->webpayPlusTransaction->logInfoData($buyOrder, $logMessage, $transaction);
throw new AlreadyProcessedException($logMessage, $transaction, self::WEBPAY_ABORTED_FLOW);
}

if ($status == Transaction::STATUS_FAILED) {
$logMessage = self::WEBPAY_FAILED_FLOW_MESSAGE;
$this->webpayPlusTransaction->logInfoData($buyOrder, $logMessage, $transaction);
throw new AlreadyProcessedException($logMessage, $transaction, self::WEBPAY_ERROR_FLOW);
}
}

private function detectFlow(array $params): string
{
$tokenWs = $params['token_ws'] ?? null;
$tbkToken = $params['TBK_TOKEN'] ?? null;
$tbkSessionId = $params['TBK_ID_SESION'] ?? null;

$flow = self::WEBPAY_ERROR_FLOW;

if ($tokenWs && !$tbkToken && !$tbkSessionId) {
$flow = self::WEBPAY_NORMAL_FLOW;
}
if ($tbkSessionId && !$tbkToken && !$tokenWs) {
$flow = self::WEBPAY_TIMEOUT_FLOW;
}
if ($tbkToken && $tbkSessionId && !$tokenWs) {
$flow = self::WEBPAY_ABORTED_FLOW;
}
return $flow;
}

public function handleRequestFromTbkReturn(array $params)
{
$tokenWs = $params['token_ws'] ?? null;
$tbkToken = $params['TBK_TOKEN'] ?? null;
$sessionId = $params['TBK_ID_SESION'] ?? null;
$buyOrder = $params['TBK_ORDEN_COMPRA'] ?? null;
$flow = $this->detectFlow($params);

switch ($flow) {
case self::WEBPAY_NORMAL_FLOW:
return $this->handleNormalFlow($tokenWs);
case self::WEBPAY_TIMEOUT_FLOW:
$this->handleTimeoutFlow($sessionId, $buyOrder);
break;
case self::WEBPAY_ABORTED_FLOW:
$this->handleAbortedFlow($tbkToken);
break;
default:
$this->handleErrorFlow($tokenWs, $tbkToken);
break;
}
}

private function handleNormalFlow(string $token)
{
$this->webpayPlusTransaction->logInfo("Flujo normal detectado, token: $token");

if ($this->isTransactionProcessed($token)) {
$this->handleProcessedTransaction($token);
}

return Transaction::getByToken($token);
}

private function handleTimeoutFlow(string $sessionId, string $buyOrder)
{
$this->webpayPlusTransaction->logInfo("Flujo de timeout detectado, sessionId: $sessionId, buyOrder: $buyOrder");
$transaction = Transaction::getByBuyOrderAndSessionId($buyOrder, $sessionId) ?? null;
$token = $transaction->token ?? null;

if ($this->isTransactionProcessed($token)) {
$this->handleProcessedTransaction($token);
}

$errorMessage = self::WEBPAY_TIMEOUT_FLOW_MESSAGE;
$orderId = $transaction->order_id ?? 0;
$data = [
'TBK_ID_SESION' => $sessionId,
'TBK_ORDEN_COMPRA' => $buyOrder
];
$this->webpayPlusTransaction->errorExecution($orderId, 'commit', $data, 'TimeoutWebpayException', $errorMessage, $errorMessage);
$this->webpayPlusTransaction->saveTransactionWithErrorByTransaction($transaction, 'TimeoutWebpayException', $errorMessage);
throw new TimeoutWebpayException($errorMessage, $buyOrder, $sessionId, $transaction);
}

private function handleAbortedFlow(string $token)
{
$this->webpayPlusTransaction->logInfo("Flujo de pago abortado detectado, token: $token");

if ($this->isTransactionProcessed($token)) {
$this->handleProcessedTransaction($token);
}

$errorMessage = self::WEBPAY_ABORTED_FLOW_MESSAGE;
$transaction = $this->webpayPlusTransaction->saveTransactionWithErrorByToken($token, 'UserCancelWebpayException', $errorMessage);
$this->webpayPlusTransaction->errorExecution($transaction->order_id, 'commit', $token, 'UserCancelWebpayException', $errorMessage, $errorMessage);
throw new UserCancelWebpayException($errorMessage, $token, $transaction);
}

private function handleErrorFlow(string $token, string $tbkToken)
{
$this->webpayPlusTransaction->logInfo("Flujo con error en el formulario detectado, token: $token");

if ($this->isTransactionProcessed($token)) {
$this->handleProcessedTransaction($token);
}

$errorMessage = self::WEBPAY_ERROR_FLOW_MESSAGE;
$transaction = $this->webpayPlusTransaction->saveTransactionWithErrorByToken($tbkToken, 'DoubleTokenWebpayException', $errorMessage);
$this->webpayPlusTransaction->errorExecution($transaction->order_id, 'commit', $token, 'DoubleTokenWebpayException', $errorMessage, $errorMessage);
throw new DoubleTokenWebpayException($errorMessage, $tbkToken, $token, $transaction);
}
}
Loading

0 comments on commit 92868f6

Please sign in to comment.