--- a/woo-rede/Includes/LknIntegrationRedeForWoocommerce.php
+++ b/woo-rede/Includes/LknIntegrationRedeForWoocommerce.php
@@ -2,6 +2,8 @@
namespace LknwooIntegrationRedeForWoocommerceIncludes;
+if ( ! defined( 'ABSPATH' ) ) exit;
+
use LknwooIntegrationRedeForWoocommerceAdminLknIntegrationRedeForWoocommerceAdmin;
use LknwooIntegrationRedeForWoocommerceIncludesLknIntegrationRedeForWoocommerceLoader;
use LknwooIntegrationRedeForWoocommercePublicViewLknIntegrationRedeForWoocommercePublic;
@@ -236,8 +238,8 @@
$extra_fees = 0;
foreach ($fees_objects as $fee) {
if (
- strtolower($fee->name) !== strtolower(__('Interest', 'rede-for-woocommerce-pro')) &&
- strtolower($fee->name) !== strtolower(__('Discount', 'rede-for-woocommerce-pro'))
+ strtolower($fee->name) !== strtolower(__('Interest', 'woo-rede')) &&
+ strtolower($fee->name) !== strtolower(__('Discount', 'woo-rede'))
) {
$extra_fees += floatval($fee->amount);
}
@@ -345,8 +347,8 @@
$extra_fees = 0;
foreach ($fees_objects as $fee) {
if (
- strtolower($fee->name) !== strtolower(__('Interest', 'rede-for-woocommerce-pro')) &&
- strtolower($fee->name) !== strtolower(__('Discount', 'rede-for-woocommerce-pro'))
+ strtolower($fee->name) !== strtolower(__('Interest', 'woo-rede')) &&
+ strtolower($fee->name) !== strtolower(__('Discount', 'woo-rede'))
) {
$extra_fees += floatval($fee->amount);
}
@@ -472,8 +474,8 @@
$extra_fees = 0;
foreach ($fees_objects as $fee) {
if (
- strtolower($fee->name) !== strtolower(__('Interest', 'rede-for-woocommerce-pro')) &&
- strtolower($fee->name) !== strtolower(__('Discount', 'rede-for-woocommerce-pro'))
+ strtolower($fee->name) !== strtolower(__('Interest', 'woo-rede')) &&
+ strtolower($fee->name) !== strtolower(__('Discount', 'woo-rede'))
) {
$extra_fees += floatval($fee->amount);
}
@@ -708,8 +710,8 @@
$extra_fees = 0;
foreach ($fees_objects as $fee) {
if (
- strtolower($fee->name) !== strtolower(__('Interest', 'rede-for-woocommerce-pro')) &&
- strtolower($fee->name) !== strtolower(__('Discount', 'rede-for-woocommerce-pro'))
+ strtolower($fee->name) !== strtolower(__('Interest', 'woo-rede')) &&
+ strtolower($fee->name) !== strtolower(__('Discount', 'woo-rede'))
) {
$extra_fees += floatval($fee->amount);
}
--- a/woo-rede/Includes/LknIntegrationRedeForWoocommerceHelper.php
+++ b/woo-rede/Includes/LknIntegrationRedeForWoocommerceHelper.php
@@ -43,15 +43,19 @@
final public static function getTransactionBrandDetails($tid, $instance)
{
- // Autenticação básica
- $auth = base64_encode($instance->pv . ':' . $instance->token);
+ // Usar OAuth2 para API v2
+ $oauth_token = self::get_rede_oauth_token_for_gateway($instance->id);
+
+ if (!$oauth_token) {
+ return null;
+ }
$apiUrl = ('production' === $instance->environment)
- ? 'https://api.userede.com.br/erede/v1/transactions'
- : 'https://sandbox-erede.useredecloud.com.br/v1/transactions';
+ ? 'https://api.userede.com.br/redelabs/v2/transactions'
+ : 'https://rl7-sandbox-api.useredecloud.com.br/v2/transactions';
$headers = array(
- 'Authorization' => 'Basic ' . $auth,
+ 'Authorization' => 'Bearer ' . $oauth_token,
'Content-Type' => 'application/json',
'Transaction-Response' => 'brand-return-opened',
);
@@ -79,17 +83,22 @@
final public static function getCardBrand($tid, $instance)
{
- $auth = base64_encode($instance->pv . ':' . $instance->token);
+ // Usar OAuth2 para API v2
+ $oauth_token = self::get_rede_oauth_token_for_gateway($instance->id);
+
+ if (!$oauth_token) {
+ return null;
+ }
if ('production' === $instance->environment) {
- $apiUrl = 'https://api.userede.com.br/erede/v1/transactions';
+ $apiUrl = 'https://api.userede.com.br/redelabs/v2/transactions';
} else {
- $apiUrl = 'https://sandbox-erede.useredecloud.com.br/v1/transactions';
+ $apiUrl = 'https://rl7-sandbox-api.useredecloud.com.br/v2/transactions';
}
$response = wp_remote_get($apiUrl . '/' . $tid, array(
'headers' => array(
- 'Authorization' => 'Basic ' . $auth,
+ 'Authorization' => 'Bearer ' . $oauth_token,
'Content-Type' => 'application/json',
'Transaction-Response' => 'brand-return-opened'
),
@@ -340,8 +349,8 @@
$additional_fees = 0;
foreach (WC()->cart->get_fees() as $fee) {
// Ignorar fees criados pelo próprio plugin
- if ($fee->name !== __('Interest', 'rede-for-woocommerce-pro') &&
- $fee->name !== __('Discount', 'rede-for-woocommerce-pro')) {
+ if ($fee->name !== __('Interest', 'woo-rede') &&
+ $fee->name !== __('Discount', 'woo-rede')) {
$additional_fees += $fee->total;
}
}
@@ -365,8 +374,8 @@
$additional_fees = 0;
foreach ($order->get_fees() as $fee) {
// Ignorar fees criados pelo próprio plugin
- if ($fee->get_name() !== __('Interest', 'rede-for-woocommerce-pro') &&
- $fee->get_name() !== __('Discount', 'rede-for-woocommerce-pro')) {
+ if ($fee->get_name() !== __('Interest', 'woo-rede') &&
+ $fee->get_name() !== __('Discount', 'woo-rede')) {
$additional_fees += $fee->get_total();
}
}
@@ -404,7 +413,7 @@
} else {
// Sem juros, mas ainda aplicar outros valores
$final_total = $base_amount + $additional_fees - $discount_amount + $tax_amount;
- return html_entity_decode(sprintf('%dx de %s', $i, wp_strip_all_tags( wc_price( $final_total / $i)))) . ' ' . __("interest-free", 'rede-for-woocommerce-pro');
+ return html_entity_decode(sprintf('%dx de %s', $i, wp_strip_all_tags( wc_price( $final_total / $i)))) . ' ' . __("interest-free", 'woo-rede');
}
} else {
$discount = round((float) $instance->get_option($i . 'x_discount'), 0);
@@ -496,7 +505,7 @@
'body' => 'grant_type=client_credentials',
'timeout' => 30
));
-
+
if (is_wp_error($oauth_response)) {
return false;
}
@@ -685,97 +694,6 @@
}
/**
- * Gera token OAuth2 para API Rede v2 (mantido para compatibilidade)
- * @deprecated Use generate_rede_oauth_token_for_gateway() instead
- */
- final public static function generate_rede_oauth_token($environment = 'test')
- {
- // Tenta usar credenciais do gateway de crédito como padrão
- $credentials = self::get_gateway_credentials('rede_credit');
-
- if ($credentials === false) {
- // Se crédito não está configurado, tenta débito
- $credentials = self::get_gateway_credentials('rede_debit');
- }
-
- if ($credentials === false) {
- return false;
- }
-
- $oauth_url = $environment === 'production'
- ? 'https://api.userede.com.br/redelabs/oauth2/token'
- : 'https://rl7-sandbox-api.useredecloud.com.br/oauth2/token';
-
- $auth = base64_encode($credentials['pv'] . ':' . $credentials['token']);
-
- $oauth_response = wp_remote_post($oauth_url, array(
- 'method' => 'POST',
- 'headers' => array(
- 'Authorization' => 'Basic ' . $auth,
- 'Content-Type' => 'application/x-www-form-urlencoded'
- ),
- 'body' => 'grant_type=client_credentials',
- 'timeout' => 30
- ));
-
- if (is_wp_error($oauth_response)) {
- return false;
- }
-
- $oauth_body = wp_remote_retrieve_body($oauth_response);
- $oauth_data = json_decode($oauth_body, true);
-
- if (!isset($oauth_data['access_token'])) {
- return false;
- }
-
- return $oauth_data;
- }
-
- /**
- * Salva token OAuth2 no cache com timestamp
- */
- final public static function cache_rede_oauth_token($token_data, $environment = 'test')
- {
- $cache_data = array(
- 'token' => $token_data['access_token'],
- 'expires_in' => $token_data['expires_in'],
- 'generated_at' => time(),
- 'environment' => $environment
- );
-
- // Codifica em base64 para segurança
- $encoded_data = base64_encode(json_encode($cache_data));
-
- $option_name = 'lkn_rede_oauth_token_' . $environment;
- update_option($option_name, $encoded_data);
-
- return $cache_data;
- }
-
- /**
- * Recupera token OAuth2 do cache
- */
- final public static function get_cached_rede_oauth_token($environment = 'test')
- {
- $option_name = 'lkn_rede_oauth_token_' . $environment;
- $cached_data = get_option($option_name, '');
-
- if (empty($cached_data)) {
- return null;
- }
-
- // Decodifica do base64
- $decoded_data = json_decode(base64_decode($cached_data), true);
-
- if (!$decoded_data || !isset($decoded_data['token']) || !isset($decoded_data['generated_at'])) {
- return null;
- }
-
- return $decoded_data;
- }
-
- /**
* Verifica se o token está válido (não expirou)
*/
final public static function is_rede_oauth_token_valid($cached_token)
@@ -792,58 +710,6 @@
}
/**
- * Obtém token OAuth2 válido (mantido para compatibilidade)
- * @deprecated Use get_rede_oauth_token_for_gateway() instead
- */
- final public static function get_rede_oauth_token($environment = 'test')
- {
- // Tenta recuperar do cache
- $cached_token = self::get_cached_rede_oauth_token($environment);
-
- // Se token está válido, retorna ele
- if ($cached_token && self::is_rede_oauth_token_valid($cached_token)) {
- return $cached_token['token'];
- }
-
- // Token não existe ou expirou, tenta gerar novo
- $token_data = self::generate_rede_oauth_token($environment);
-
- // Se falhou ao gerar novo token
- if ($token_data === false) {
- // Se há um token em cache (mesmo expirado), usa ele como fallback
- if ($cached_token && isset($cached_token['token'])) {
- return $cached_token['token'];
- }
-
- // Se não há token em cache, retorna null para forçar erro na API
- return null;
- }
-
- // Salva o novo token no cache
- self::cache_rede_oauth_token($token_data, $environment);
-
- return $token_data['access_token'];
- }
-
- /**
- * Força renovação do token OAuth2 (mantido para compatibilidade)
- * @deprecated Use refresh_all_rede_oauth_tokens() instead
- */
- final public static function refresh_rede_oauth_token($environment = 'test')
- {
- $token_data = self::generate_rede_oauth_token($environment);
-
- // Se falhou ao gerar novo token, mantém o cache atual
- if ($token_data === false) {
- return false;
- }
-
- self::cache_rede_oauth_token($token_data, $environment);
-
- return $token_data['access_token'];
- }
-
- /**
* Verifica se a licença PRO está ativa e válida
*
* @return bool
--- a/woo-rede/Includes/LknIntegrationRedeForWoocommerceLoader.php
+++ b/woo-rede/Includes/LknIntegrationRedeForWoocommerceLoader.php
@@ -1,6 +1,8 @@
<?php
namespace LknwooIntegrationRedeForWoocommerceIncludes;
+if ( ! defined( 'ABSPATH' ) ) exit;
+
/**
* Register all actions and filters for the plugin
*
--- a/woo-rede/Includes/LknIntegrationRedeForWoocommerceWcEndpoint.php
+++ b/woo-rede/Includes/LknIntegrationRedeForWoocommerceWcEndpoint.php
@@ -457,6 +457,18 @@
return new WP_REST_Response($response_body['authorization']['status'] ?? 'Accepted', 200);
}
+ /**
+ * Processa callback de sucesso do 3D Secure
+ *
+ * SEGURANÇA: Este endpoint foi protegido contra bypass de pagamento através de:
+ * 1. Validação de TID contra dados armazenados no pedido
+ * 2. Verificação de correspondência entre reference e order_id
+ * 3. Consulta à API da Rede para confirmar autenticidade da transação
+ * 4. Validação de amount para evitar alteração de valores
+ *
+ * @param WP_REST_Request $request Requisição REST
+ * @return WP_REST_Response|WP_Error
+ */
public function handle3dsSuccess($request)
{
$parameters = $request->get_params();
@@ -483,6 +495,12 @@
return new WP_Error('invalid_order', __('Order not found', 'woo-rede'), array('status' => 404));
}
+ // VALIDAÇÃO DE SEGURANÇA: Verifica autenticidade da requisição
+ if (!$this->validate_webhook_security($order, $parameters, 'success')) {
+ $order->add_order_note(__('Security validation failed for 3DS webhook', 'woo-rede'));
+ return new WP_Error('security_validation_failed', __('Security validation failed', 'woo-rede'), array('status' => 403));
+ }
+
try {
// Usa os dados que já vêm no webhook da Rede
$this->update_order_metadata_and_status($order, $parameters);
@@ -496,6 +514,17 @@
}
}
+ /**
+ * Processa callback de falha do 3D Secure
+ *
+ * SEGURANÇA: Este endpoint foi protegido contra bypass de pagamento através de:
+ * 1. Validação de TID contra dados armazenados no pedido
+ * 2. Verificação de correspondência entre reference e order_id
+ * 3. Consulta à API da Rede para confirmar autenticidade da transação
+ *
+ * @param WP_REST_Request $request Requisição REST
+ * @return WP_REST_Response|WP_Error
+ */
public function handle3dsFailure($request)
{
$parameters = $request->get_params();
@@ -521,6 +550,11 @@
return new WP_Error('invalid_order', __('Order not found', 'woo-rede'), array('status' => 404));
}
+ // VALIDAÇÃO DE SEGURANÇA: Verifica autenticidade da requisição
+ if (!$this->validate_webhook_security($order, $parameters, 'failure')) {
+ return new WP_Error('security_validation_failed', __('Security validation failed', 'woo-rede'), array('status' => 403));
+ }
+
// Marca pedido como falhado
$order->add_order_note(__('3D Secure authentication failed', 'woo-rede'));
// $order->update_status('failed');
@@ -532,6 +566,244 @@
exit;
}
+ /**
+ * Processa status do pedido especificamente para retorno 3DS
+ * A resposta 3DS tem estrutura diferente e precisamos do card_type dos metadados
+ */
+ private function process_3ds_order_status($order, $webhook_data, $note = '')
+ {
+ $return_code = $webhook_data['returnCode'] ?? '';
+ $return_message = $webhook_data['returnMessage'] ?? '';
+
+ // Para 3DS, recuperar o card_type dos metadados do pedido
+ $saved_card_type = $order->get_meta('_wc_rede_card_type') ?: 'debit';
+
+ // Obter configuração de auto_capture do gateway debit
+ $debit_settings = get_option('woocommerce_rede_debit_settings');
+ $auto_capture = sanitize_text_field($debit_settings['auto_capture'] ?? 'yes') == 'no' ? false : true;
+
+ // Determinar se foi capturado baseado no tipo de cartão e configuração
+ $capture = ($saved_card_type === 'debit') ? true : $auto_capture;
+
+ // Adiciona informação sobre o tipo de cartão detectado na nota
+ $card_type_note = sprintf(' [Card Type: %s, Capture: %s]', $saved_card_type, $capture ? 'Yes' : 'No');
+ $status_note = sprintf('Rede[%s]', $return_message);
+ $order->add_order_note($status_note . ' ' . $note . $card_type_note);
+
+ // Só altera o status se o pedido estiver pendente
+ if ($order->get_status() === 'pending') {
+ if ($return_code == '00') {
+ if ($capture) {
+ // Status configurável pelo usuário para pagamentos aprovados com captura
+ $payment_complete_status = $debit_settings['payment_complete_status'] ?? 'processing';
+ $order->update_status($payment_complete_status);
+ } else {
+ // Para pagamentos credit sem captura, aguardando captura manual
+ $order->update_status('on-hold', 'Pagamento autorizado, aguardando captura manual.');
+ wc_reduce_stock_levels($order->get_id());
+ }
+ } else {
+ $order->update_status('failed', $status_note);
+ }
+ }
+ }
+
+ public function regOrderLogs($orderId, $order_total, $cardData, $transaction, $order, $brand = null): void
+ {
+ $debit_settings = get_option('woocommerce_rede_debit_settings');
+ if (($debit_settings['debug'] ?? 'no') === 'yes') {
+ $tId = null;
+ $returnCode = null;
+
+ if ($brand === null && $transaction) {
+ $brand = null;
+ if (is_array($transaction)) {
+ $tId = $transaction['tid'] ?? null;
+ $returnCode = $transaction['returnCode'] ?? null;
+ }
+
+ if ($tId) {
+ $gateway = new LknwooIntegrationRedeForWoocommerceIncludesLknIntegrationRedeForWoocommerceWcRedeDebit();
+ $brand = LknIntegrationRedeForWoocommerceHelper::getTransactionBrandDetails($tId, $gateway);
+ }
+ }
+
+ $default_currency = get_option('woocommerce_currency', 'BRL');
+ $order_currency = method_exists($order, 'get_currency') ? $order->get_currency() : $default_currency;
+ $currency_json_path = INTEGRATION_REDE_FOR_WOOCOMMERCE_DIR . 'Includes/files/linkCurrencies.json';
+ $currency_data = LknIntegrationRedeForWoocommerceHelper::lkn_get_currency_rates($currency_json_path);
+ $convert_to_brl_enabled = LknIntegrationRedeForWoocommerceHelper::is_convert_to_brl_enabled('rede_debit');
+
+ $exchange_rate_value = 1;
+ if ($convert_to_brl_enabled && $currency_data !== false && is_array($currency_data) && isset($currency_data['rates']) && isset($currency_data['base'])) {
+ // Exibe a cotação apenas se não for BRL
+ if ($order_currency !== 'BRL' && isset($currency_data['rates'][$order_currency])) {
+ $rate = $currency_data['rates'][$order_currency];
+ // Converte para string, preservando todas as casas decimais
+ $exchange_rate_value = (string)$rate;
+ }
+ }
+
+ // Recupera metadados do pedido se não estiverem em cardData
+ $final_card_type = isset($cardData['card_type']) ? $cardData['card_type'] : ($order->get_meta('_wc_rede_card_type') ?: 'debit');
+ $final_installments = isset($cardData['installments']) ? $cardData['installments'] : ($order->get_meta('_wc_rede_installments') ?: 1);
+
+ $bodyArray = array(
+ 'orderId' => $orderId,
+ 'amount' => $order_total,
+ 'orderCurrency' => $order_currency,
+ 'currencyConverted' => $convert_to_brl_enabled ? 'BRL' : null,
+ 'exchangeRateValue' => $exchange_rate_value,
+ 'cardData' => $cardData,
+ 'cardType' => $final_card_type,
+ 'installments' => ($final_card_type === 'credit' && $final_installments >= 1) ? $final_installments : null,
+ 'brand' => isset($tId) && isset($brand) ? $brand['brand'] : null,
+ 'returnCode' => isset($returnCode) ? $returnCode : null,
+ );
+
+ $bodyArray['cardData']['card_number'] = LknIntegrationRedeForWoocommerceHelper::censorString($bodyArray['cardData']['card_number'], 8);
+
+ // Remove parâmetros desnecessários da resposta
+ $cleanedTransaction = $transaction;
+ if (is_array($cleanedTransaction)) {
+ unset($cleanedTransaction['o'], $cleanedTransaction['k'], $cleanedTransaction['r']);
+ }
+
+ $orderLogsArray = array(
+ 'body' => $bodyArray,
+ 'response' => $cleanedTransaction
+ );
+
+ $orderLogs = json_encode($orderLogsArray);
+ $order->update_meta_data('lknWcRedeOrderLogs', $orderLogs);
+ $order->save();
+ }
+ }
+
+ /**
+ * Valida a segurança do webhook 3DS para evitar bypass de pagamento
+ *
+ * @param WC_Order $order O pedido do WooCommerce
+ * @param array $webhook_data Dados do webhook recebido
+ * @return bool True se válido, false caso contrário
+ */
+ private function validate_webhook_security($order, $webhook_data, $validation_type)
+ {
+ try {
+ $tid = sanitize_text_field($webhook_data['tid'] ?? '');
+ if($tid === '') {
+ return true;
+ }
+
+ return $this->verify_transaction_with_rede_api($order, $tid, $webhook_data, $validation_type);
+
+ } catch (Exception $e) {
+ // Log do erro para debug
+ if (function_exists('wc_get_logger')) {
+ $logger = wc_get_logger();
+ $logger->error('3DS Webhook security validation error: ' . $e->getMessage(), array('source' => 'rede_security'));
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Verifica a transação diretamente na API da Rede para validar autenticidade
+ *
+ * @param WC_Order $order O pedido do WooCommerce
+ * @param string $tid Transaction ID
+ * @param array $webhook_data Dados do webhook
+ * @return bool True se válido, false caso contrário
+ */
+ private function verify_transaction_with_rede_api($order, $tid, $webhook_data, $validation_type)
+ {
+ try {
+ // Determina o gateway usado para buscar configurações corretas
+ $payment_method = $order->get_payment_method();
+ $gateway_id = 'rede_debit'; // default
+ $gateway_settings = get_option('woocommerce_' . $gateway_id . '_settings', array());
+ $environment = isset($gateway_settings['environment']) ? $gateway_settings['environment'] : 'test';
+ // Mapeia método de pagamento para gateway ID
+ if (strpos($payment_method, 'rede_credit') !== false) {
+ $gateway_id = 'rede_credit';
+ } elseif (strpos($payment_method, 'rede_debit') !== false) {
+ $gateway_id = 'rede_debit';
+ }
+
+ // Obtém token OAuth2 válido
+ LknIntegrationRedeForWoocommerceHelper::refresh_expired_rede_oauth_tokens(20);
+ $token_data = LknIntegrationRedeForWoocommerceHelper::get_cached_rede_oauth_token_for_gateway($gateway_id, $environment);
+
+ if (!$token_data || empty($token_data['token'])) {
+ return false;
+ }
+
+ // Determina ambiente (produção/teste) baseado nas configurações do gateway
+ $gateway_settings = get_option('woocommerce_' . $gateway_id . '_settings');
+ $environment = $gateway_settings['environment'] ?? 'test';
+
+ // Define URL da API baseada no ambiente
+ if ($environment === 'production') {
+ $apiUrl = 'https://api.userede.com.br/erede/v2/transactions/' . $tid;
+ } else {
+ $apiUrl = 'https://sandbox-erede.useredecloud.com.br/v2/transactions/' . $tid;
+ }
+
+ // Faz requisição à API da Rede
+ $response = wp_remote_get($apiUrl, array(
+ 'headers' => array(
+ 'Content-Type' => 'application/json',
+ 'Authorization' => 'Bearer ' . $token_data['token']
+ ),
+ 'timeout' => 15
+ ));
+
+ if (is_wp_error($response)) {
+ return false;
+ }
+
+ $response_code = wp_remote_retrieve_response_code($response);
+ $response_body = wp_remote_retrieve_body($response);
+
+ if ($response_code !== 200) {
+ return false;
+ }
+
+ $transaction_data = json_decode($response_body, true);
+ $authorization = $transaction_data['authorization'] ?? array();
+ if (!$transaction_data || empty($authorization)) {
+ return false;
+ }
+ // Valida dados críticos da transação
+ $api_tid = $authorization['tid'] ?? '';
+ $api_reference = $authorization['reference'] ?? '';
+ $api_amount = $authorization['amount'] ?? 0;
+ $api_status = $authorization['status'] ?? '';
+
+ // Verifica se TID, reference e amount correspondem
+ if ($api_tid !== $tid) {
+ return false;
+ }
+
+ if ($api_reference !== $webhook_data['reference']) {
+ return false;
+ }
+
+ if($api_status === 'Declined' && $validation_type === 'success') {
+ return false;
+ }
+
+ if($api_status === 'Approved' && $validation_type === 'failure') {
+ return false;
+ }
+
+ return true;
+
+ } catch (Exception $e) {
+ return false;
+ }
+ }
+
private function query_rede_transaction_by_reference($reference)
{
try {
@@ -703,118 +975,4 @@
$this->process_3ds_order_status($order, $webhook_data, '3D Secure authentication completed');
}
- /**
- * Processa status do pedido especificamente para retorno 3DS
- * A resposta 3DS tem estrutura diferente e precisamos do card_type dos metadados
- */
- private function process_3ds_order_status($order, $webhook_data, $note = '')
- {
- $return_code = $webhook_data['returnCode'] ?? '';
- $return_message = $webhook_data['returnMessage'] ?? '';
-
- // Para 3DS, recuperar o card_type dos metadados do pedido
- $saved_card_type = $order->get_meta('_wc_rede_card_type') ?: 'debit';
-
- // Obter configuração de auto_capture do gateway debit
- $debit_settings = get_option('woocommerce_rede_debit_settings');
- $auto_capture = sanitize_text_field($debit_settings['auto_capture'] ?? 'yes') == 'no' ? false : true;
-
- // Determinar se foi capturado baseado no tipo de cartão e configuração
- $capture = ($saved_card_type === 'debit') ? true : $auto_capture;
-
- // Adiciona informação sobre o tipo de cartão detectado na nota
- $card_type_note = sprintf(' [Card Type: %s, Capture: %s]', $saved_card_type, $capture ? 'Yes' : 'No');
- $status_note = sprintf('Rede[%s]', $return_message);
- $order->add_order_note($status_note . ' ' . $note . $card_type_note);
-
- // Só altera o status se o pedido estiver pendente
- if ($order->get_status() === 'pending') {
- if ($return_code == '00') {
- if ($capture) {
- // Status configurável pelo usuário para pagamentos aprovados com captura
- $payment_complete_status = $debit_settings['payment_complete_status'] ?? 'processing';
- $order->update_status($payment_complete_status);
- } else {
- // Para pagamentos credit sem captura, aguardando captura manual
- $order->update_status('on-hold', 'Pagamento autorizado, aguardando captura manual.');
- wc_reduce_stock_levels($order->get_id());
- }
- } else {
- $order->update_status('failed', $status_note);
- }
- }
- }
-
- public function regOrderLogs($orderId, $order_total, $cardData, $transaction, $order, $brand = null): void
- {
- $debit_settings = get_option('woocommerce_rede_debit_settings');
- if (($debit_settings['debug'] ?? 'no') === 'yes') {
- $tId = null;
- $returnCode = null;
-
- if ($brand === null && $transaction) {
- $brand = null;
- if (is_array($transaction)) {
- $tId = $transaction['tid'] ?? null;
- $returnCode = $transaction['returnCode'] ?? null;
- }
-
- if ($tId) {
- $gateway = new LknwooIntegrationRedeForWoocommerceIncludesLknIntegrationRedeForWoocommerceWcRedeDebit();
- $brand = LknIntegrationRedeForWoocommerceHelper::getTransactionBrandDetails($tId, $gateway);
- }
- }
-
- $default_currency = get_option('woocommerce_currency', 'BRL');
- $order_currency = method_exists($order, 'get_currency') ? $order->get_currency() : $default_currency;
- $currency_json_path = INTEGRATION_REDE_FOR_WOOCOMMERCE_DIR . 'Includes/files/linkCurrencies.json';
- $currency_data = LknIntegrationRedeForWoocommerceHelper::lkn_get_currency_rates($currency_json_path);
- $convert_to_brl_enabled = LknIntegrationRedeForWoocommerceHelper::is_convert_to_brl_enabled('rede_debit');
-
- $exchange_rate_value = 1;
- if ($convert_to_brl_enabled && $currency_data !== false && is_array($currency_data) && isset($currency_data['rates']) && isset($currency_data['base'])) {
- // Exibe a cotação apenas se não for BRL
- if ($order_currency !== 'BRL' && isset($currency_data['rates'][$order_currency])) {
- $rate = $currency_data['rates'][$order_currency];
- // Converte para string, preservando todas as casas decimais
- $exchange_rate_value = (string)$rate;
- }
- }
-
- // Recupera metadados do pedido se não estiverem em cardData
- $final_card_type = isset($cardData['card_type']) ? $cardData['card_type'] : ($order->get_meta('_wc_rede_card_type') ?: 'debit');
- $final_installments = isset($cardData['installments']) ? $cardData['installments'] : ($order->get_meta('_wc_rede_installments') ?: 1);
-
- $bodyArray = array(
- 'orderId' => $orderId,
- 'amount' => $order_total,
- 'orderCurrency' => $order_currency,
- 'currencyConverted' => $convert_to_brl_enabled ? 'BRL' : null,
- 'exchangeRateValue' => $exchange_rate_value,
- 'cardData' => $cardData,
- 'cardType' => $final_card_type,
- 'installments' => ($final_card_type === 'credit' && $final_installments >= 1) ? $final_installments : null,
- 'brand' => isset($tId) && isset($brand) ? $brand['brand'] : null,
- 'returnCode' => isset($returnCode) ? $returnCode : null,
- );
-
- $bodyArray['cardData']['card_number'] = LknIntegrationRedeForWoocommerceHelper::censorString($bodyArray['cardData']['card_number'], 8);
-
- // Remove parâmetros desnecessários da resposta
- $cleanedTransaction = $transaction;
- if (is_array($cleanedTransaction)) {
- unset($cleanedTransaction['o'], $cleanedTransaction['k'], $cleanedTransaction['r']);
- }
-
- $orderLogsArray = array(
- 'body' => $bodyArray,
- 'response' => $cleanedTransaction
- );
-
- $orderLogs = json_encode($orderLogsArray);
- $order->update_meta_data('lknWcRedeOrderLogs', $orderLogs);
- $order->save();
- }
- }
-
}
--- a/woo-rede/Includes/LknIntegrationRedeForWoocommerceWcPixRede.php
+++ b/woo-rede/Includes/LknIntegrationRedeForWoocommerceWcPixRede.php
@@ -380,7 +380,7 @@
// Verificar se a resposta do refund contém o returnCode
if (!is_array($refund) || !isset($refund['returnCode'])) {
- throw new Exception(__('Invalid refund response from Rede API.', 'woo-rede'));
+ throw new Exception(esc_html(__('Invalid refund response from Rede API.', 'woo-rede')));
}
if ('359' == $refund['returnCode']) {
--- a/woo-rede/Includes/LknIntegrationRedeForWoocommerceWcRedeAbstract.php
+++ b/woo-rede/Includes/LknIntegrationRedeForWoocommerceWcRedeAbstract.php
@@ -209,8 +209,8 @@
// Adicionar taxas (fees) do pedido, excluindo fees do próprio plugin
foreach ($order->get_fees() as $fee) {
// Ignorar fees criados pelo próprio plugin
- if ($fee->get_name() !== __('Interest', 'rede-for-woocommerce-pro') &&
- $fee->get_name() !== __('Discount', 'rede-for-woocommerce-pro')) {
+ if ($fee->get_name() !== __('Interest', 'woo-rede') &&
+ $fee->get_name() !== __('Discount', 'woo-rede')) {
$subtotal += (float) $fee->get_amount();
}
}
@@ -225,8 +225,8 @@
// Adicionar taxas (fees) do carrinho, excluindo fees do próprio plugin
foreach ($woocommerce->cart->get_fees() as $fee) {
// Ignorar fees criados pelo próprio plugin
- if ($fee->name !== __('Interest', 'rede-for-woocommerce-pro') &&
- $fee->name !== __('Discount', 'rede-for-woocommerce-pro')) {
+ if ($fee->name !== __('Interest', 'woo-rede') &&
+ $fee->name !== __('Discount', 'woo-rede')) {
$subtotal += (float) $fee->amount;
}
}
--- a/woo-rede/Includes/LknIntegrationRedeForWoocommerceWcRedeDebit.php
+++ b/woo-rede/Includes/LknIntegrationRedeForWoocommerceWcRedeDebit.php
@@ -2,6 +2,8 @@
namespace LknwooIntegrationRedeForWoocommerceIncludes;
+if ( ! defined( 'ABSPATH' ) ) exit;
+
use Exception;
use LknwooIntegrationRedeForWoocommerceIncludesLknIntegrationRedeForWoocommerceWcRedeAbstract;
use WC_Order;
--- a/woo-rede/Includes/views/notices/html-notice-woocommerce-missing.php
+++ b/woo-rede/Includes/views/notices/html-notice-woocommerce-missing.php
@@ -21,7 +21,7 @@
<?php
esc_attr_e(
'Integration Rede Itaú for WooCommerce — Payment PIX, Credit Card and Debit Disabled',
- 'integration-rede-for-woocommerce'
+ 'woo-rede'
);
?>
</strong>:
@@ -30,7 +30,7 @@
// translators: %s is the name of the plugin required for this one to work.
esc_attr__(
'This plugin depends on the last version of %s to work!',
- 'integration-rede-for-woocommerce'
+ 'woo-rede'
),
'<a href="' . esc_url($integration_rede_for_woocommerce_url) . '">' . esc_attr__('WooCommerce', 'woo-rede') . '</a>'
);
--- a/woo-rede/integration-rede-for-woocommerce.php
+++ b/woo-rede/integration-rede-for-woocommerce.php
@@ -15,7 +15,7 @@
* @wordpress-plugin
* Plugin Name: Integration Rede Itaú for WooCommerce — Payment PIX, Credit Card and Debit
* Description: Receba pagamentos por meio de cartões de crédito e débito, de diferentes bandeiras, usando a tecnologia de autenticação 3DS e recursos avançados de proteção contra fraudes.
- * Version: 5.1.2
+ * Version: 5.1.3
* Author: Link Nacional
* Author URI: https://linknacional.com.br/wordpress
* License: GPL-3.0+
--- a/woo-rede/lkn-integration-rede-for-woocommerce-file.php
+++ b/woo-rede/lkn-integration-rede-for-woocommerce-file.php
@@ -17,7 +17,7 @@
* Rename this for your plugin and update it as you release new versions.
*/
if (! defined('INTEGRATION_REDE_FOR_WOOCOMMERCE_VERSION')) {
- define('INTEGRATION_REDE_FOR_WOOCOMMERCE_VERSION', '5.1.2');
+ define('INTEGRATION_REDE_FOR_WOOCOMMERCE_VERSION', '5.1.3');
}
if (! defined('INTEGRATION_REDE_FOR_WOOCOMMERCE_FILE')) {