File "ResponseController.php"
Full path: /home/dora/public_html/wp-content/plugins/transbank-webpay-plus-rest/src/Controllers/ResponseController.php
File size: 15.57 KB
MIME-type: --
Charset: utf-8
<?php
namespace Transbank\WooCommerce\WebpayRest\Controllers;
use DateTime;
use DateTimeZone;
use Transbank\Webpay\WebpayPlus\Responses\TransactionCommitResponse;
use Transbank\WooCommerce\WebpayRest\Helpers\SessionMessageHelper;
use Transbank\WooCommerce\WebpayRest\Models\Transaction;
use Transbank\WooCommerce\WebpayRest\TransbankSdkWebpayRest;
use WC_Order;
class ResponseController
{
/**
* @var array
*/
protected $pluginConfig;
/**
* ResponseController constructor.
*
* @param array $pluginConfig
*/
public function __construct(array $pluginConfig)
{
$this->pluginConfig = $pluginConfig;
}
/**
* @param $paymentTypeCode
*
* @return string
*/
public static function getHumanReadableInstallemntsType($paymentTypeCode): string
{
$installmentTypes = [
'VD' => 'Venta Débito',
'VN' => 'Venta Normal',
'VC' => 'Venta en cuotas',
'SI' => '3 cuotas sin interés',
'S2' => '2 cuotas sin interés',
'NC' => 'N cuotas sin interés',
];
$paymentCodeResult = isset($installmentTypes[$paymentTypeCode]) ? $installmentTypes[$paymentTypeCode] : 'Sin cuotas';
return $paymentCodeResult;
}
/**
* @throws \GuzzleHttp\Exception\GuzzleException
* @throws \Transbank\WooCommerce\WebpayRest\Exceptions\TokenNotFoundOnDatabaseException
*/
public function response($postData)
{
if ($this->transactionWasTimeout()) {
$this->throwError('La transacción fue cancelada automáticamente por estar inactivo mucho tiempo en el formulario de pago de Webpay. Puede reintentar el pago');
do_action('transbank_webpay_plus_timeout_on_form');
wp_redirect(wc_get_checkout_url());
exit;
}
$token_ws = $this->getTokenWs($postData);
$webpayTransaction = Transaction::getByToken($token_ws);
$wooCommerceOrder = $this->getWooCommerceOrderById($webpayTransaction->order_id);
if ($this->transactionWasCanceledByUser()) {
$params = ['transbank_webpayplus_cancelled_order' => 1];
$redirectUrl = add_query_arg($params, wc_get_checkout_url());
if ($webpayTransaction->status !== Transaction::STATUS_INITIALIZED || $wooCommerceOrder->is_paid()) {
$wooCommerceOrder->add_order_note('El usuario canceló la transacción en el formulario de pago, pero esta orden ya estaba pagada o en un estado diferente a INICIALIZADO');
wp_safe_redirect($redirectUrl);
return;
}
$this->setOrderAsCancelledByUser($wooCommerceOrder, $webpayTransaction);
do_action('transbank_webpay_plus_transaction_cancelled_by_user', $wooCommerceOrder, $webpayTransaction);
wp_safe_redirect($redirectUrl);
return;
}
if ($wooCommerceOrder->is_paid()) {
// TODO: Revisar porqué no se muestra el mensaje de abajo. H4x
//SessionMessageHelper::set('Orden <strong>ya ha sido pagada</strong>.', 'notice');
$wooCommerceOrder->add_order_note('El usuario intentó pagar esta orden nuevamente, cuando esta ya '.
'estaba pagada.');
do_action('transbank_webpay_plus_already_paid_transaction', $wooCommerceOrder);
return wp_safe_redirect($wooCommerceOrder->get_checkout_order_received_url());
}
if (!$wooCommerceOrder->needs_payment()) {
// TODO: Revisar porqué no se muestra el mensaje de abajo.
//SessionMessageHelper::set('El estado de la orden no permite que sea pagada. Comuníquese con la tienda.', 'error');
$wooCommerceOrder->add_order_note(
'El usuario intentó pagar la orden cuando estaba en estado: '.
$wooCommerceOrder->get_status().".\n".
'No se ejecutó captura del pago de esta solicitud.'
);
do_action('transbank_webpay_plus_paying_transaction_that_does_not_needs_payment', $wooCommerceOrder);
return wp_safe_redirect($wooCommerceOrder->get_checkout_order_received_url());
}
$transbankSdkWebpay = new TransbankSdkWebpayRest($this->pluginConfig);
$result = $transbankSdkWebpay->commitTransaction($token_ws);
if ($this->transactionIsApproved($result) && $this->validateTransactionDetails($result, $webpayTransaction)) {
$this->completeWooCommerceOrder($wooCommerceOrder, $result, $webpayTransaction);
do_action('transbank_webpay_plus_transaction_approved', $wooCommerceOrder, $webpayTransaction);
return wp_redirect($wooCommerceOrder->get_checkout_order_received_url());
}
$this->setWooCommerceOrderAsFailed($wooCommerceOrder, $webpayTransaction, $result);
do_action('transbank_webpay_plus_transaction_failed', $wooCommerceOrder, $webpayTransaction, $result);
return wp_redirect($wooCommerceOrder->get_checkout_order_received_url());
}
/**
* @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());
exit;
}
return $token_ws;
}
/**
* @param $orderId
*
* @return WC_Order
*/
protected function getWooCommerceOrderById($orderId)
{
$wooCommerceOrder = new WC_Order($orderId);
return $wooCommerceOrder;
}
/**
* @param WC_Order $wooCommerceOrder
* @param array $result
* @param $webpayTransaction
*/
protected function completeWooCommerceOrder(WC_Order $wooCommerceOrder, TransactionCommitResponse $result, $webpayTransaction)
{
list($authorizationCode, $amount, $sharesNumber, $transactionResponse, $paymentCodeResult, $date_accepted, $sharesAmount, $paymentType) = $this->getTransactionDetails($result);
$cardNumber = $result->cardDetail['card_number'];
$date = $date_accepted->format('d-m-Y / H:i:s');
update_post_meta($wooCommerceOrder->get_id(), 'transactionResponse', $transactionResponse);
update_post_meta($wooCommerceOrder->get_id(), 'buyOrder', $result->buyOrder);
update_post_meta($wooCommerceOrder->get_id(), 'authorizationCode', $authorizationCode);
update_post_meta($wooCommerceOrder->get_id(), 'cardNumber', $cardNumber);
update_post_meta($wooCommerceOrder->get_id(), 'paymentCodeResult', $paymentCodeResult);
update_post_meta($wooCommerceOrder->get_id(), 'amount', $amount);
update_post_meta($wooCommerceOrder->get_id(), 'installmentsNumber', $sharesNumber ? $sharesNumber : '0');
update_post_meta($wooCommerceOrder->get_id(), 'installmentsAmount', $sharesAmount ? $sharesAmount : '0');
update_post_meta($wooCommerceOrder->get_id(), 'transactionDate', $date);
update_post_meta($wooCommerceOrder->get_id(), 'webpay_transaction_id', $webpayTransaction->id);
update_post_meta($wooCommerceOrder->get_id(), 'webpay_rest_response', json_encode($result));
$message = 'Pago exitoso con Webpay Plus';
$this->addOrderDetailsOnNotes(
$amount,
$result,
$sharesAmount,
$message,
$transactionResponse,
$authorizationCode,
$cardNumber,
$sharesNumber,
$paymentType,
$paymentCodeResult,
$webpayTransaction,
$date,
$wooCommerceOrder
);
Transaction::update(
$webpayTransaction->id,
[
'status' => Transaction::STATUS_APPROVED,
'transbank_status' => $result->getStatus(),
'transbank_response' => json_encode($result), ]
);
$wooCommerceOrder->payment_complete();
$final_status = $this->pluginConfig['STATUS_AFTER_PAYMENT'];
if ($final_status) {
$wooCommerceOrder->update_status($final_status);
}
}
/**
* @param WC_Order $wooCommerceOrder
* @param array $result
* @param $webpayTransaction
*/
protected function setWooCommerceOrderAsFailed(WC_Order $wooCommerceOrder, $webpayTransaction, $result = null)
{
$_SESSION['woocommerce_order_failed'] = true;
$wooCommerceOrder->update_status('failed');
if ($result !== null) {
$message = 'Pago rechazado';
list($authorizationCode, $amount, $sharesNumber, $transactionResponse, $paymentCodeResult, $date_accepted, $sharesAmount, $paymentType) = $this->getTransactionDetails($result);
$cardNumber = isset($result->cardDetail['card_number']) ? $result->cardDetail['card_number'] : '-';
$date = $date_accepted->format('d-m-Y / H:i:s');
$this->addOrderDetailsOnNotes(
$amount,
$result,
$sharesAmount,
$message,
$transactionResponse,
$authorizationCode,
$cardNumber,
$sharesNumber,
$paymentType,
$paymentCodeResult,
$webpayTransaction,
$date,
$wooCommerceOrder
);
}
Transaction::update(
$webpayTransaction->id,
[
'status' => Transaction::STATUS_FAILED,
'transbank_response' => json_encode($result),
]
);
}
/**
* @param array $result
*
* @return bool
*/
protected function transactionIsApproved($result)
{
if (!isset($result->responseCode)) {
return false;
}
return (int) $result->responseCode === 0;
}
/**
* @param array $result
* @param $webpayTransaction
*
* @return bool
*/
protected function validateTransactionDetails($result, $webpayTransaction)
{
if (!isset($result->responseCode)) {
return false;
}
return $result->buyOrder == $webpayTransaction->buy_order && $result->sessionId == $webpayTransaction->session_id && $result->amount == $webpayTransaction->amount;
}
/**
* @param array $result
*
* @throws \Exception
*
* @return array
*/
public function getTransactionDetails($result)
{
$paymentTypeCode = isset($result->paymentTypeCode) ? $result->paymentTypeCode : null;
$authorizationCode = isset($result->authorizationCode) ? $result->authorizationCode : null;
$amount = isset($result->amount) ? $result->amount : null;
$sharesNumber = isset($result->installmentsNumber) ? $result->installmentsNumber : null;
$sharesAmount = isset($result->installmentsAmount) ? $result->installmentsAmount : null;
$responseCode = isset($result->responseCode) ? $result->responseCode : null;
if ($responseCode == 0) {
$transactionResponse = 'Transacción Aprobada';
} else {
$transactionResponse = 'Transacción Rechazada';
}
$paymentCodeResult = self::getHumanReadableInstallemntsType($paymentTypeCode);
$paymentType = $this->getHumanReadablePaymentType($paymentTypeCode);
$transactionDate = isset($result->transactionDate) ? $result->transactionDate : null;
$date_accepted = new DateTime($transactionDate, new DateTimeZone('UTC'));
$date_accepted->setTimeZone(new DateTimeZone(wc_timezone_string()));
return [$authorizationCode, $amount, $sharesNumber, $transactionResponse, $paymentCodeResult, $date_accepted, $sharesAmount, $paymentType];
}
protected function setOrderAsCancelledByUser(WC_Order $order_info, $webpayTransaction)
{
// Transaction aborted by user
$order_info->add_order_note(__('Webpay Plus: Pago abortado por el usuario en el formulario de pago', 'transbank_wc_plugin'));
$order_info->update_status('cancelled');
Transaction::update(
$webpayTransaction->id,
['status' => Transaction::STATUS_ABORTED_BY_USER]
);
}
/**
* @return bool
*/
private function transactionWasCanceledByUser()
{
$buyOrder = $_POST['TBK_ORDEN_COMPRA'] ?? $_GET['TBK_ORDEN_COMPRA'] ?? null;
$sessionId = $_POST['TBK_ID_SESION'] ?? $_GET['TBK_ID_SESION'] ?? null;
$token = $_POST['TBK_TOKEN'] ?? $_GET['TBK_TOKEN'] ?? null;
return $buyOrder && $sessionId && $token;
}
/**
* @return bool
*/
private function transactionWasTimeout()
{
$buyOrder = $_POST['TBK_ORDEN_COMPRA'] ?? $_GET['TBK_ORDEN_COMPRA'] ?? null;
$sessionId = $_POST['TBK_ID_SESION'] ?? $_GET['TBK_ID_SESION'] ?? null;
$token = $_POST['TBK_TOKEN'] ?? $_GET['TBK_TOKEN'] ?? null;
return $buyOrder && $sessionId && !$token;
}
/**
* @param $amount
* @param array $result
* @param $sharesAmount
* @param string $message
* @param $transactionResponse
* @param $authorizationCode
* @param $cardNumber
* @param $sharesNumber
* @param $paymentType
* @param $paymentCodeResult
* @param $webpayTransaction
* @param $date
* @param WC_Order $wooCommerceOrder
*/
protected function addOrderDetailsOnNotes(
$amount,
$result,
$sharesAmount,
string $message,
$transactionResponse,
$authorizationCode,
$cardNumber,
$sharesNumber,
$paymentType,
$paymentCodeResult,
$webpayTransaction,
$date,
WC_Order $wooCommerceOrder
) {
$amountFormatted = number_format($amount, 0, ',', '.');
$responseCode = isset($result->responseCode) ? $result->responseCode : '-';
$sharesAmount = $sharesAmount ? $sharesAmount : '-';
$transactionDetails = "
<div class='transbank_response_note'>
<p><h3>{$message}</h3></p>
<strong>Estado: </strong>{$transactionResponse} <br />
<strong>Orden de compra: </strong>{$result->buyOrder} <br />
<strong>Código de autorización: </strong>{$authorizationCode} <br />
<strong>Últimos dígitos tarjeta: </strong>{$cardNumber} <br />
<strong>Monto: </strong>$ {$amountFormatted} <br />
<strong>Código de respuesta: </strong>{$responseCode} <br />
<strong>Tipo de pago: </strong>{$paymentType} <br />
<strong>Tipo de cuota: </strong>{$paymentCodeResult} <br />
<strong>Número de cuotas: </strong>{$sharesNumber} <br />
<strong>Monto de cada cuota: </strong>{$sharesAmount} <br />
<strong>Token:</strong> {$webpayTransaction->token} <br />
<strong>Fecha:</strong> {$date} <br />
<strong>ID interno: </strong>{$webpayTransaction->id} <br />
</div>
";
$wooCommerceOrder->add_order_note($transactionDetails);
}
/**
* @param $paymentTypeCode
*
* @return string|void
*/
public static function getHumanReadablePaymentType($paymentTypeCode)
{
$paymentType = __('Crédito', 'transbank_wc_plugin');
if ($paymentTypeCode == 'VD') {
$paymentType = __('Débito', 'transbank_wc_plugin');
}
return $paymentType;
}
/**
* @param string $msg
*/
protected function throwError(string $msg)
{
$error_message = __($msg);
wc_add_notice($error_message, 'error');
}
}