Plugin Directory

Changeset 3732472


Ignore:
Timestamp:
10/07/2026 11:37:59 AM (3 weeks ago)
Author:
eupagoip
Message:

v 4.7.5

Location:
eupago-gateway-for-woocommerce
Files:
148 added
2 deleted
38 edited

Legend:

Unmodified
Added
Removed
  • eupago-gateway-for-woocommerce/trunk/README.md

    r3611346 r3732472  
    11=== Eupago Gateway For Woocommerce ===
    22Contributors: eupagoip
    3 Tags: woocommerce, payment, gateway, multibanco, atm, debit card, credit card, bank, ecommerce, e-commerce, eupago, mb way, payshop, cofidispay, bizum, europix, pagamento, refund, reembolso
     3Tags: woocommerce, payment, gateway, multibanco, atm, debit card, credit card, bank, ecommerce, e-commerce, eupago, mb way, payshop, bizum, europix, pagamento, refund, reembolso
    44Author URI: https://www.eupago.pt/
    55Plugin URI:
    6 Requires at least: 4.4
    7 Tested up to: 6.8.3
    8 Requires PHP: 7.0
    9 Stable tag: 4.7.4
     6Requires at least: 6.0
     7Tested up to: 7.1
     8Requires PHP: 7.4
     9WC requires at least: 7.1
     10WC tested up to: 11.1.0
     11Stable tag: 4.7.5
    1012License: GPLv2 or later
    1113License URI: http://www.gnu.org/licenses/gpl-2.0.html
    1214
    1315
    14 Plugin para recebimento de pagamentos via Multibanco, PayShop, MB WAY, Cartão de Crédito, Paysafecard, CofidisPay, Bizum e EuroPix. O plugin permite ainda fazer reembolsos directamente pela plataforma do WooCommerce.
     16Plugin para recebimento de pagamentos via Multibanco, PayShop, MB WAY, Cartão de Crédito, Paysafecard, Bizum e EuroPix. O plugin permite ainda fazer reembolsos directamente pela plataforma do WooCommerce.
    1517
    1618== Description ==
    1719
    18 Testado até à versão 8.2.11 de PHP
     20Testado até à versão 8.3 de PHP
    1921
    2022= Features: =
    … …  
    2729* geração de um pedido de pagamento MB WAY. O pagamento é realizado na aplicação da MB WAY;
    2830* geração de pedido de pagamentos via Cartão de Crédito;
    29 * geração de pedido de pagamentos via CofidisPay (para valores estipulados pela Cofidis);
    3031* geração de pedido de pagamentos via Bizum;
    3132* geração de pedido de pagamentos via EuroPix;
    … …  
    4546
    4647== Changelog ==
     48= 4.7.5(17/09/2026) =
     49* Removed: CofidisPay payment method, discontinued by the provider. It is no longer offered on the checkout nor configurable; existing CofidisPay orders keep their payment details and callbacks
     50* Feature: WordPress 7.0 and 7.1 compatibility (tested up to WordPress 7.1 and WooCommerce 11.1)
     51* Fix: "Back" button and failed payments on Credit Card, Google Pay and Apple Pay return the customer to the checkout with the cart restored (order stays on-hold)
     52* Fix: Payment details block in the on-hold email now works for every payment method
     53* Fix: Google Pay and Apple Pay description was shown twice on the block checkout
     54* Fix: Remove third-party CDN jQuery from the settings page, use the one bundled with WordPress
     55* Fix: Callback no longer returns HTTP 500 when the Eupago settings page was never saved
     56* Fix: Refund request no longer fails with a fatal error on PHP 8 when the amount is empty or the order is invalid
     57* Fix: Saving the settings no longer performs a dead HTTP request and prints an error on screen
     58* Fix: Remove the unused Refund user and password fields.
     59* Fix: Remove PHP warnings on the order screen
     60* Fix: Telemetry headers (X-App-Source, X-App-Version, X-Runtime-Info) were never sent because they were built as associative array entries; API requests now carry them
     61* Fix: EuroPix SMS no longer falls through to the Google Pay case and sends the wrong payment details
     62* Security: webhook 2.0 callbacks are now signature-checked with the channel key whether or not the body is encrypted; callbacks are ignored for orders not paid through Eupago
     63* Fix: Apple Pay and Google Pay no longer crash at checkout when stock is reduced at order time
     64* Fix: Order screen (HPOS) no longer crashes when opening a Credit Card or Bizum order without a stored reference
     65* Fix: Block checkout no longer breaks with a server error when Multibanco, Payshop, Paysafecard or Pagaqui reject a payment; the error message is shown instead
     66* Fix: Block cart and checkout no longer crash when Floa is enabled but the terms have not been accepted yet
     67* Change: Credit Card requests now use the REST API v1.02
     68* Change: Multibanco, Payshop and Paysafecard now use the REST API first and only fall back to SOAP when the REST request cannot be completed; the SOAP extension is no longer required for Credit Card
     69* Change: Eupago no longer emails the customer directly (customer.notify = false), the shop's WooCommerce emails are used
     70* Improvement: New design for the payment details block in emails
     71* Improvement: Uniform payment method icons on both checkouts, new Pagaqui logo
     72
    4773= 4.7.4(17/07/2026) =
    4874* Fix: Remove invalid use statements that caused PHP warnings visible on client websites
  • eupago-gateway-for-woocommerce/trunk/eupago-gateway-for-woocommerce.php

    r3611346 r3732472  
    33* Plugin Name: Eupago Gateway For Woocommerce
    44* Plugin URI:
    5 * Description: This plugin allows customers to pay their orders with Multibanco, MB WAY, Payshop, Credit Card, CofidisPay, Bizum and EuroPix with Eupago’s gateway.
    6 * Version: 4.7.4
     5* Description: This plugin allows customers to pay their orders with Multibanco, MB WAY, Payshop, Credit Card, Bizum and EuroPix with Eupago’s gateway.
     6* Version: 4.7.5
    77* Author: Eupago
    88* Author URI: https://www.eupago.pt/
    99* Text Domain: eupago-gateway-for-woocommerce
    10 * WC tested up to: 10.2.2
    11 * Tested up to: 6.8.3
     10* Requires at least: 6.0
     11* Tested up to: 7.1
     12* Requires PHP: 7.4
     13* WC requires at least: 7.1
     14* WC tested up to: 11.1.0
    1215**/
    1316
    … …  
    2730         * @var string
    2831         */
    29         public const VERSION = '4.7.4';
     32        public const VERSION = '4.7.5';
    3033
    3134        /**
    … …  
    3538         */
    3639        public const SOURCE = 'woocommerce';
     40
    3741
    3842        /**
    … …  
    123127                // Set Callback.
    124128                new WC_Eupago_Callback();
     129
     130                // Landing endpoint for the "back" button and the failure return of the Eupago payment page.
     131                new WC_Eupago_Payment_Return();
     132
     133                // Payment-method icon sizes on the checkout (classic and blocks).
     134                add_action('wp_enqueue_scripts', [ $this, 'enqueue_checkout_styles' ]);
    125135            } else {
    126136                add_action('admin_notices', [ $this, 'woocommerce_missing_notice' ]);
    … …  
    349359                return;
    350360            }
    351             wp_enqueue_script('eupago-redirect', plugin_dir_url(__FILE__) . 'assets/js/redirect.js', [], false, true);
     361            wp_enqueue_script('eupago-redirect', plugin_dir_url(__FILE__) . 'assets/js/redirect.js', [ 'jquery' ], self::VERSION, true);
    352362        }
    353363   
    … …  
    388398         * Load css.
    389399         */
     400        /**
     401         * Icon sizes for the Eupago payment methods on the checkout page, classic
     402         * and blocks alike (assets/css/checkout.css). One place to adjust them.
     403         */
     404        public function enqueue_checkout_styles()
     405        {
     406            if (!function_exists('is_checkout') || !is_checkout()) {
     407                return;
     408            }
     409
     410            wp_enqueue_style('eupago-checkout', plugin_dir_url(__FILE__) . 'assets/css/checkout.css', [], self::VERSION);
     411        }
     412
    390413        public function load_scripts()
    391414        {
    392             wp_enqueue_style('admin_style', plugin_dir_url(__FILE__) . 'assets/css/admin_style.css');
     415            wp_enqueue_style('admin_style', plugin_dir_url(__FILE__) . 'assets/css/admin_style.css', [], self::VERSION);
    393416            $hpos_enabled = $this->is_hpos_compliant();
    394417
    … …  
    419442            $cc_text_en = __('Credit Card', 'eupago-gateway-for-woocommerce');
    420443            $payshop_text_en = __('Payshop', 'eupago-gateway-for-woocommerce');
    421             $cofidispay_text_en = __('CofidisPay', 'eupago-gateway-for-woocommerce');
    422444            $bizum_text_en = __('Bizum', 'eupago-gateway-for-woocommerce');
    423445            $pix_text_en = __('EuroPix', 'eupago-gateway-for-woocommerce');
    … …  
    433455            $cc_text_pt = __('Cartão de Crédito', 'eupago-gateway-for-woocommerce-pt');
    434456            $payshop_text_pt = __('Payshop', 'eupago-gateway-for-woocommerce-pt');
    435             $cofidispay_text_pt = __('CofidisPay', 'eupago-gateway-for-woocommerce-pt');
    436457            $bizum_text_pt = __('Bizum', 'eupago-gateway-for-woocommerce-pt');
    437458            $pix_text_pt = __('EuroPix', 'eupago-gateway-for-woocommerce-pt');
    … …  
    447468            $cc_text_es = __('Tarjeta de Crédito', 'eupago-gateway-for-woocommerce-es');
    448469            $payshop_text_es = __('Payshop', 'eupago-gateway-for-woocommerce-es');
    449             $cofidispay_text_es = __('CofidisPay', 'eupago-gateway-for-woocommerce-es');
    450470            $bizum_text_es = __('Bizum', 'eupago-gateway-for-woocommerce-es');
    451471            $pix_text_es = __('EuroPix', 'eupago-gateway-for-woocommerce-es');
    … …  
    461481                    $cc_text = $cc_text_es;
    462482                    $payshop_text = $payshop_text_es;
    463                     $cofidispay_text = $cofidispay_text_es;
    464483                    $bizum_text = $bizum_text_es;
    465484                    $pix_text = $pix_text_es;
    … …  
    475494                    $cc_text = $cc_text_pt;
    476495                    $payshop_text = $payshop_text_pt;
    477                     $cofidispay_text = $cofidispay_text_pt;
    478496                    $bizum_text = $bizum_text_pt;
    479497                    $pix_text = $pix_text_pt;
    … …  
    489507                    $cc_text = $cc_text_en;
    490508                    $payshop_text = $payshop_text_en;
    491                     $cofidispay_text = $cofidispay_text_en;
    492509                    $bizum_text = $bizum_text_en;
    493510                    $pix_text = $pix_text_en;
    … …  
    504521            $cc_url = esc_url(admin_url('admin.php?page=wc-settings&tab=checkout&section=eupago_cc'));
    505522            $payshop_url = esc_url(admin_url('admin.php?page=wc-settings&tab=checkout&section=eupago_payshop'));
    506             $cofidispay_url = esc_url(admin_url('admin.php?page=wc-settings&tab=checkout&section=eupago_cofidispay'));
    507523            $bizum_url = esc_url(admin_url('admin.php?page=wc-settings&tab=checkout&section=eupago_bizum'));
    508524            $pix_url = esc_url(admin_url('admin.php?page=wc-settings&tab=checkout&section=eupago_pix'));
    … …  
    522538            $plugin_links[] = '<a href="' . $cc_url . '">' . $cc_text . '</a>';
    523539            $plugin_links[] = '<a href="' . $payshop_url . '">' . $payshop_text . '</a>';
    524             $plugin_links[] = '<a href="' . $cofidispay_url . '">' . $cofidispay_text . '</a>';
    525540            $plugin_links[] = '<a href="' . $bizum_url . '">' . $bizum_text . '</a>';
    526541            $plugin_links[] = '<a href="' . $pix_url . '">' . $pix_text . '</a>';
    … …  
    557572            include_once 'includes/class-wc-eupago-pix.php';
    558573
    559             include_once 'includes/class-wc-eupago-cofidispay.php';
    560 
    561574            include_once 'includes/class-wc-eupago-cc.php';
    562575
    … …  
    564577
    565578            include_once 'includes/class-wc-eupago-callback.php';
     579
     580            include_once 'includes/class-wc-eupago-payment-return.php';
     581
     582            include_once 'includes/class-wc-eupago-email-instructions.php';
    566583
    567584            include_once 'includes/hooks/hooks-refund.php';
    … …  
    595612                $methods[] = 'WC_Eupago_PayShop';
    596613                $methods[] = 'WC_Eupago_MBWAY';
    597                 $methods[] = 'WC_Eupago_CofidisPay';
    598614                $methods[] = 'WC_Eupago_CC';
    599615                $methods[] = 'WC_Eupago_PF';
    … …  
    821837            $file_path_cc = __DIR__ . '/includes/woocommerce-blocks/cc/CcBlock.php';
    822838            $file_path_payshop = __DIR__ . '/includes/woocommerce-blocks/payshop/PayshopBlock.php';
    823             $file_path_cofidispay = __DIR__ . '/includes/woocommerce-blocks/cofidispay/CofidisPayBlock.php';
    824839            $file_path_bizum = __DIR__ . '/includes/woocommerce-blocks/bizum/BizumBlock.php';
    825840            $file_path_pix = __DIR__ . '/includes/woocommerce-blocks/pix/PixBlock.php';
    … …  
    924939                    function (Automattic\WooCommerce\Blocks\Payments\PaymentMethodRegistry $payment_method_registry) {
    925940                        $payment_method_registry->register(new \Automattic\WooCommerce\Blocks\Payments\Integrations\PayshopBlock());
    926                     }
    927                 );
    928             }
    929 
    930             if (file_exists($file_path_cofidispay)) {
    931                 require_once $file_path_cofidispay;
    932 
    933                 add_action(
    934                     'woocommerce_blocks_payment_method_type_registration',
    935                     function (Automattic\WooCommerce\Blocks\Payments\PaymentMethodRegistry $payment_method_registry) {
    936                         $payment_method_registry->register(new \Automattic\WooCommerce\Blocks\Payments\Integrations\CofidisPayBlock());
    937941                    }
    938942                );
    … …  
    987991                'headers' => [
    988992                    'Content-Type' => 'application/json',
    989                     'X-App-Source'   => WC_Eupago::SOURCE,
    990                     'X-App-Version'  => WC_Eupago::VERSION,
    991                     'X-Runtime-Info' => 'PHP ' . PHP_VERSION
     993                    'X-App-Source: ' . WC_Eupago::SOURCE,
     994                    'X-App-Version: ' . WC_Eupago::VERSION,
     995                    'X-Runtime-Info: PHP ' . PHP_VERSION
    992996                ],
    993997                'timeout' => 15,
    … …  
    10181022                        'Content-Type'  => 'application/json',
    10191023                        'Authorization' => 'Bearer ' . $accessToken,
    1020                         'X-App-Source'   => WC_Eupago::SOURCE,
    1021                         'X-App-Version'  => WC_Eupago::VERSION,
    1022                         'X-Runtime-Info' => 'PHP ' . PHP_VERSION
     1024                        'X-App-Source: ' . WC_Eupago::SOURCE,
     1025                        'X-App-Version: ' . WC_Eupago::VERSION,
     1026                        'X-Runtime-Info: PHP ' . PHP_VERSION
    10231027                    ],
    10241028                    'timeout' => 15,
    … …  
    10731077                'headers' => [
    10741078                    'Content-Type' => 'application/json',
    1075                     'X-App-Source'   => WC_Eupago::SOURCE,
    1076                     'X-App-Version'  => WC_Eupago::VERSION,
    1077                     'X-Runtime-Info' => 'PHP ' . PHP_VERSION
     1079                    'X-App-Source: ' . WC_Eupago::SOURCE,
     1080                    'X-App-Version: ' . WC_Eupago::VERSION,
     1081                    'X-Runtime-Info: PHP ' . PHP_VERSION
    10781082                ],
    10791083                'timeout' => 15,
    … …  
    10991103                        'Content-Type'  => 'application/json',
    11001104                        'Authorization' => 'Bearer ' . $accessToken,
    1101                         'X-App-Source'   => WC_Eupago::SOURCE,
    1102                         'X-App-Version'  => WC_Eupago::VERSION,
    1103                         'X-Runtime-Info' => 'PHP ' . PHP_VERSION
     1105                        'X-App-Source: ' . WC_Eupago::SOURCE,
     1106                        'X-App-Version: ' . WC_Eupago::VERSION,
     1107                        'X-Runtime-Info: PHP ' . PHP_VERSION
    11041108                    ],
    11051109                    'timeout' => 15,
  • eupago-gateway-for-woocommerce/trunk/includes/class-wc-eupago-api.php

    r3611346 r3732472  
    2828  }
    2929
    30   public function get_cofidis_url()
    31   {
    32     if (get_option('eupago_endpoint') == 'sandbox') {
    33       return 'https://sandbox.eupago.pt/api/v1.02/cofidis/create';
    34     } else {
    35       return 'https://clientes.eupago.pt/api/v1.02/cofidis/create';
    36     }
    37   }
    38 
    3930  public function get_api_key()
    4031  {
    … …  
    5950  }
    6051
     52  /**
     53   * Error object in the shape the legacy API returns, so callers can treat a
     54   * transport failure like any other rejected request.
     55   */
     56  protected function legacy_error($message)
     57  {
     58    return (object) array(
     59      'sucesso'  => false,
     60      'estado'   => -1,
     61      'resposta' => $message,
     62    );
     63  }
     64
     65  /**
     66   * Legacy REST API call (clientes/rest_api/<path>).
     67   *
     68   * @return object|null Decoded response, or null when the request itself could
     69   *                     not be completed (network error, non-2xx status, body
     70   *                     that is not a JSON object).
     71   */
     72  protected function legacy_rest_post($path, array $body)
     73  {
     74    $url = 'https://' . get_option('eupago_endpoint') . '.eupago.pt/clientes/rest_api/' . ltrim($path, '/');
     75
     76    $response = wp_remote_post($url, array(
     77      'body'    => $body,
     78      'timeout' => 60,
     79      'headers' => array(
     80        'X-App-Source'   => WC_Eupago::SOURCE,
     81        'X-App-Version'  => WC_Eupago::VERSION,
     82        'X-Runtime-Info' => 'PHP ' . PHP_VERSION,
     83      ),
     84    ));
     85
     86    if (is_wp_error($response)) {
     87      $this->log_error("REST {$path}: " . $response->get_error_message());
     88      return null;
     89    }
     90
     91    $code = (int) wp_remote_retrieve_response_code($response);
     92    $raw  = wp_remote_retrieve_body($response);
     93    $data = json_decode($raw);
     94
     95    if ($code < 200 || $code >= 300 || !is_object($data)) {
     96      $this->log_error("REST {$path}: HTTP {$code}, body: " . substr((string) $raw, 0, 500));
     97      return null;
     98    }
     99
     100    return $data;
     101  }
     102
     103  /**
     104   * Legacy SOAP API call. Only used when the REST request could not be completed.
     105   *
     106   * @return object|null Response object, or null when SOAP is unavailable or the call failed.
     107   */
     108  protected function legacy_soap_call($method, array $args)
     109  {
     110    if (!extension_loaded('soap')) {
     111      $this->log_error("SOAP {$method}: soap extension not loaded, no fallback available");
     112      return null;
     113    }
     114
     115    try {
     116      $client = new SoapClient($this->get_url(), array('cache_wsdl' => WSDL_CACHE_NONE, 'exceptions' => true));
     117      $result = $client->{$method}($args);
     118    } catch (Throwable $e) {
     119      $this->log_error("SOAP {$method}: " . $e->getMessage());
     120      return null;
     121    }
     122
     123    return is_object($result) ? $result : null;
     124  }
     125
     126  /**
     127   * Legacy request: REST first, SOAP as fallback when REST could not be completed.
     128   * A response the API rejected (estado != 0) is returned as is, it is not retried.
     129   */
     130  protected function legacy_request($rest_path, $soap_method, array $args)
     131  {
     132    $response = $this->legacy_rest_post($rest_path, $args);
     133
     134    if ($response === null) {
     135      $response = $this->legacy_soap_call($soap_method, $args);
     136    }
     137
     138    if ($response === null) {
     139      return $this->legacy_error(__('Could not reach the Eupago service. Please try again.', 'eupago-gateway-for-woocommerce'));
     140    }
     141
     142    return $response;
     143  }
     144
     145  protected function log_error($message)
     146  {
     147    if (function_exists('wc_get_logger')) {
     148      wc_get_logger()->error($message, array('source' => 'eupago-api'));
     149    }
     150  }
     151
    61152  public function getReferenciaMB($order_id, $valor, $per_dup = 0, $deadline = null)
    62153  {
    63 
    64     if (extension_loaded('soap')) {
    65 
    66       $get_order = wc_get_order($order_id);
    67       $email = $get_order->get_billing_email();
    68       $phone = $get_order->get_billing_phone();
    69 
    70       $client = @new SoapClient($this->get_url(), array('cache_wsdl' => WSDL_CACHE_NONE));
    71 
    72       $args = array(
    73         'chave' => $this->get_api_key(),
    74         'valor' => $this->money_format($valor),
    75         'id' => $order_id,
    76         'per_dup' => $per_dup,
    77         "failOver" => (int)$this->get_failover(),
    78         'email'   => $email,
    79         'contacto' => (int)$phone
    80       );
    81 
    82       if (isset($deadline) && !empty($deadline)) {
    83 
    84         $args['data_inicio'] = date('Y-m-d');
    85         $args['data_fim'] = date('Y-m-d', strtotime('+' . $deadline . ' day', strtotime($args['data_inicio'])));
    86 
    87         return $client->gerarReferenciaMBDL($args);
    88       }
    89 
    90       return $client->gerarReferenciaMB($args);
    91     } else {
    92 
    93       //$curl = curl_init();
    94 
    95       if (isset($deadline) && !empty($deadline)) {
    96         $body = array(
    97           'chave'         => $this->get_api_key(),
    98           'valor'         => $this->money_format($valor),
    99           'id'            => $order_id,
    100           'per_dup'       => $per_dup,
    101           'data_inicio'   => date('Y-m-d'),
    102           'data_fim'      => date('Y-m-d', strtotime('+' . $deadline . ' day', strtotime(date('Y-m-d'))))
    103         );
    104       } else {
    105         $body = array(
    106           'chave'         => $this->get_api_key(),
    107           'valor'         => $this->money_format($valor),
    108           'id'            => $order_id,
    109           'per_dup'       => $per_dup
    110         );
    111       }
    112 
    113       $url = 'https://' . get_option('eupago_endpoint') . '.eupago.pt/clientes/rest_api/multibanco/create';
    114       $args = array(
    115         'body' => $body,
    116         'timeout'     => '60',
    117       );
    118 
    119       $response = wp_remote_post($url, $args);
    120       $client     = wp_remote_retrieve_body($response);
    121 
    122       return $client;
    123     }
    124   }
    125 
    126   public function getReferenciaApplePay($order, $valor, $lang, $return_url)
     154    $order = wc_get_order($order_id);
     155
     156    $args = array(
     157      'chave'    => $this->get_api_key(),
     158      'valor'    => $this->money_format($valor),
     159      'id'       => $order_id,
     160      'per_dup'  => $per_dup,
     161      'failOver' => (int) $this->get_failover(),
     162      'email'    => $order ? $order->get_billing_email() : '',
     163      'contacto' => $order ? (int) $order->get_billing_phone() : 0,
     164    );
     165
     166    $soap_method = 'gerarReferenciaMB';
     167
     168    if (isset($deadline) && !empty($deadline)) {
     169      $args['data_inicio'] = date('Y-m-d');
     170      $args['data_fim']    = date('Y-m-d', strtotime('+' . $deadline . ' day', strtotime($args['data_inicio'])));
     171      $soap_method = 'gerarReferenciaMBDL';
     172    }
     173
     174    return $this->legacy_request('multibanco/create', $soap_method, $args);
     175  }
     176
     177  public function getReferenciaApplePay($order, $valor, $lang, $return_url, $cancel_url)
    127178  {
    128179    $url = 'https://' . get_option('eupago_endpoint') . '.eupago.pt/api/v1.02/euapplepay/create';
    … …  
    137188        'lang'        => $lang,
    138189        'successUrl'  => $return_url,
    139         'failUrl'     => $return_url,
    140         'backUrl'     => $return_url,
     190        'failUrl'     => $cancel_url,
     191        'backUrl'     => $cancel_url,
    141192      ),
    142193      'customer' => array(
    … …  
    153204      'Accept: application/json',
    154205      'Authorization: ApiKey ' . $this->get_api_key(),
    155       'X-App-Source'   => WC_Eupago::SOURCE,
    156       'X-App-Version'  => WC_Eupago::VERSION,
    157       'X-Runtime-Info' => 'PHP ' . PHP_VERSION
     206      'X-App-Source: ' . WC_Eupago::SOURCE,
     207      'X-App-Version: ' . WC_Eupago::VERSION,
     208      'X-Runtime-Info: PHP ' . PHP_VERSION
    158209    );
    159210
    … …  
    179230  }
    180231
    181 
    182   public function getReferenciaGooglePay($order, $valor, $lang, $return_url)
     232  public function getReferenciaGooglePay($order, $valor, $lang, $return_url, $cancel_url)
    183233  {
    184234    $url = 'https://' . get_option('eupago_endpoint') . '.eupago.pt/api/v1.02/googlepay/create';
    … …  
    193243        'lang' => 'PT',
    194244        'successUrl' => $return_url,
    195         'failUrl' => $return_url,
    196         'backUrl' => $return_url
     245        'failUrl'    => $cancel_url,
     246        'backUrl'    => $cancel_url,
    197247      ),
    198248      'customer' => array(
    … …  
    209259      'Accept: application/json',
    210260      'Authorization: ApiKey ' . $this->get_api_key(),
    211       'X-App-Source'   => WC_Eupago::SOURCE,
    212       'X-App-Version'  => WC_Eupago::VERSION,
    213       'X-Runtime-Info' => 'PHP ' . PHP_VERSION
     261      'X-App-Source: ' . WC_Eupago::SOURCE,
     262      'X-App-Version: ' . WC_Eupago::VERSION,
     263      'X-Runtime-Info: PHP ' . PHP_VERSION
    214264    );
    215265
    … …  
    237287  public function getReferenciaPS($order_id, $valor)
    238288  {
    239     if (extension_loaded('soap')) {
    240       $client = @new SoapClient($this->get_url(), array('cache_wsdl' => WSDL_CACHE_NONE));
    241       return $client->gerarReferenciaPS(array(
    242         "chave" => $this->get_api_key(),
    243         "valor" => $this->money_format($valor),
    244         "id" => $order_id
    245       ));
    246     } else {
    247       $url = 'https://' . get_option('eupago_endpoint') . '.eupago.pt/clientes/rest_api/payshop/create';
    248       $args = array(
    249         'body' => array(
    250           "chave" => $this->get_api_key(),
    251           "valor" => $this->money_format($valor),
    252           "id" => $order_id
    253         ),
    254         'timeout'     => '60',
    255       );
    256 
    257       $response = wp_remote_post($url, $args);
    258       $client     = wp_remote_retrieve_body($response);
    259 
    260       return $client;
    261     }
     289    return $this->legacy_request('payshop/create', 'gerarReferenciaPS', array(
     290      'chave' => $this->get_api_key(),
     291      'valor' => $this->money_format($valor),
     292      'id'    => $order_id,
     293    ));
    262294  }
    263295
    … …  
    287319      ),
    288320      'customer' => array(
    289         'notify' => true
     321        'notify' => false
    290322      )
    291323    );
    … …  
    295327      'Accept: application/json',
    296328      'Content-Type: application/json',
    297       'X-App-Source'   => WC_Eupago::SOURCE,
    298       'X-App-Version'  => WC_Eupago::VERSION,
    299       'X-Runtime-Info' => 'PHP ' . PHP_VERSION
     329      'X-App-Source: ' . WC_Eupago::SOURCE,
     330      'X-App-Version: ' . WC_Eupago::VERSION,
     331      'X-Runtime-Info: PHP ' . PHP_VERSION
    300332    );
    301333
    … …  
    334366      ),
    335367      'customer' => array(
    336         'notify' => true,
     368        'notify' => false,
    337369        'name' => $order->get_formatted_billing_full_name(),
    338370        'email' => $order->get_billing_email()
    … …  
    344376      'Accept: application/json',
    345377      'Content-Type: application/json',
    346       'X-App-Source'   => WC_Eupago::SOURCE,
    347       'X-App-Version'  => WC_Eupago::VERSION,
    348       'X-Runtime-Info' => 'PHP ' . PHP_VERSION
     378      'X-App-Source: ' . WC_Eupago::SOURCE,
     379      'X-App-Version: ' . WC_Eupago::VERSION,
     380      'X-Runtime-Info: PHP ' . PHP_VERSION
    349381    );
    350382
    … …  
    382414      ),
    383415      'customer' => array(
    384         'notify' => true,
     416        'notify' => false,
    385417        //'countryCode' => '+351',
    386418        'phoneNumber' => $order->get_billing_phone(),
    … …  
    400432      'Authorization: ApiKey ' . $this->get_api_key(),
    401433      'Content-Type: application/json',
    402       'X-App-Source'   => WC_Eupago::SOURCE,
    403       'X-App-Version'  => WC_Eupago::VERSION,
    404       'X-Runtime-Info' => 'PHP ' . PHP_VERSION
     434      'X-App-Source: ' . WC_Eupago::SOURCE,
     435      'X-App-Version: ' . WC_Eupago::VERSION,
     436      'X-Runtime-Info: PHP ' . PHP_VERSION
    405437    );
    406438
    … …  
    424456  }
    425457
    426   public function pedidoCC($order, $amount, $logo_url, $return_url, $lang, $comment)
     458  /**
     459   * Creates a Credit Card payment through the REST API (v1.02).
     460   *
     461   * @param WC_Order $order
     462   * @param float    $amount
     463   * @param string   $return_url Thank-you page: only a successful payment lands here.
     464   * @param string   $lang       PT, EN or ES.
     465   * @param string   $cancel_url Where the payment page sends the buyer when the payment fails
     466   *                             or they press "back" (WC_Eupago_Payment_Return endpoint).
     467   * @return array Decoded API response, or ['error' => message] when the call itself failed.
     468   */
     469  public function pedidoCC($order, $amount, $return_url, $lang, $cancel_url)
    427470  {
    428471    $url = 'https://' . get_option('eupago_endpoint') . '.eupago.pt/api/v1.02/creditcard/create';
    429     $api_key = $this->get_api_key();
    430     // --- Try SOAP first ---
    431     if (extension_loaded('soap')) {
    432       try {
    433         $client = new \SoapClient($this->get_url(), ['cache_wsdl' => WSDL_CACHE_NONE]);
    434         $response = $client->pedidoCC([
    435           'chave'        => $api_key,
    436           'valor'        => $this->money_format($amount),
    437           'id'           => $order->get_id(),
    438           'url_logotipo' => $logo_url,
    439           'url_retorno'  => $return_url,
    440           'nome'         => $order->get_billing_first_name() . ' ' . $order->get_billing_last_name(),
    441           'email'        => $order->get_billing_email(),
    442           'lang'         => strtolower($lang),
    443           'comentario'   => $comment,
    444           'tds'          => 1,
    445         ]);
    446 
    447         $decoded = json_decode(json_encode($response), true);
    448 
    449         $response = [
    450           'success'   => isset($decoded['sucesso']) ? (bool)$decoded['sucesso'] : null,
    451           'redirectUrl'       => $decoded['url'] ?? null,
    452           'transactionID'     => $decoded['token'] ?? null,
    453           'reference' => $decoded['referencia'] ?? null,
    454           'amount'    => $decoded['valor'] ?? null,
    455           'transactionStatus'    => $decoded['estado'] ?? null,
    456           'message'   => $dadecodedta['resposta'] ?? null,
    457         ];
    458 
    459         // Convert SOAP object to array
    460         return $response;
    461       } catch (\Exception $e) {
    462         wc_get_logger()->error("CC SOAP error: " . $e->getMessage(), ['source' => 'eupago-cc']);
    463         // fallback to cURL
    464       }
    465     }
    466 
    467     // --- cURL fallback ---
     472
    468473    $data = [
    469474      'payment' => [
    470475        'amount' => [
    471           'value' => $amount,
     476          'value' => $this->money_format($amount),
    472477          'currency' => 'EUR',
    473478        ],
    474479        'identifier' => (string) $order->get_id(),
    475         'lang' => $lang,
     480        'lang' => strtoupper($lang),
    476481        'successUrl' => $return_url,
    477         'failUrl'    => $return_url,
    478         'backUrl'    => $return_url,
     482        'failUrl'    => $cancel_url,
     483        'backUrl'    => $cancel_url,
    479484      ],
    480485      'customer' => [
    481         'notify' => true,
     486        'notify' => false,
    482487        'email'  => $order->get_billing_email(),
    483488      ],
    … …  
    487492      'Content-Type: application/json',
    488493      'Accept: application/json',
    489       'Authorization: ApiKey ' . $api_key,
    490       'X-App-Source'   => WC_Eupago::SOURCE,
    491       'X-App-Version'  => WC_Eupago::VERSION,
    492       'X-Runtime-Info' => 'PHP ' . PHP_VERSION
     494      'Authorization: ApiKey ' . $this->get_api_key(),
     495      'X-App-Source: ' . WC_Eupago::SOURCE,
     496      'X-App-Version: ' . WC_Eupago::VERSION,
     497      'X-Runtime-Info: PHP ' . PHP_VERSION
    493498    ];
    494499
    … …  
    524529  public function pedidoPF($order, $valor, $return_url, $comment)
    525530  {
    526     if (extension_loaded('soap')) {
    527       $client = @new SoapClient($this->get_url(), array('cache_wsdl' => WSDL_CACHE_NONE));
    528       return $client->pedidoPF(array(
    529         'chave' => $this->get_api_key(),
    530         'valor' => $this->money_format($valor),
    531         'id' => $order->get_id(),
    532         'admin_callback' => '',
    533         'url_retorno' => $return_url,
    534         'comentario' => $comment,
    535       ));
    536     } else {
    537 
    538       $url = 'https://' . get_option('eupago_endpoint') . '.eupago.pt/clientes/rest_api/paysafecard/create';
    539       $args = array(
    540         'body' => array(
    541           'chave' => $this->get_api_key(),
    542           'valor' => $this->money_format($valor),
    543           'id' => $order->get_id(),
    544           'admin_callback' => '',
    545           'url_retorno' => $return_url,
    546           'comentario' => $comment,
    547         ),
    548         'timeout'     => '60',
    549       );
    550 
    551       $response = wp_remote_post($url, $args);
    552       $client     = wp_remote_retrieve_body($response);
    553 
    554       return $client;
    555     }
     531    return $this->legacy_request('paysafecard/create', 'pedidoPF', array(
     532      'chave'          => $this->get_api_key(),
     533      'valor'          => $this->money_format($valor),
     534      'id'             => $order->get_id(),
     535      'admin_callback' => '',
     536      'url_retorno'    => $return_url,
     537      'comentario'     => $comment,
     538    ));
    556539  }
    557540
    … …  
    570553      'lang' => $lang,
    571554    ));
    572   }
    573 
    574   public function cofidispay_create($order_id, $return_url = null)
    575   {
    576 
    577     $nonce = wp_create_nonce('wp_rest');
    578 
    579     $order = wc_get_order($order_id);
    580 
    581     $tax_code_string = get_option('woocommerce_eupago_cofidispay_settings');
    582     $code = $tax_code_string['zero_tax_code'];
    583 
    584     $data = [
    585       'payment' => [
    586         'identifier' => $order->get_order_number(),
    587         'amount' => [
    588           'value' => $order->get_total(),
    589           'currency' => 'EUR'
    590         ],
    591         'successUrl' => $return_url,
    592         'failUrl' => $return_url,
    593       ],
    594       'customer' => [
    595         'notify' => false,
    596         'email' => $order->get_billing_email(),
    597         'name' => $order->get_formatted_billing_full_name(),
    598         'vatNumber' => $order->get_meta('_eupago_cofidis_vat_number', true),
    599         'phoneNumber' => $order->get_billing_phone(),
    600         'billingAddress' => [
    601           'address' => $order->get_billing_address_1() . ' ' . $order->get_billing_address_2(),
    602           'zipCode' => $order->get_billing_postcode(),
    603           'city' => $order->get_billing_city(),
    604         ],
    605       ],
    606       'items' => [],
    607       'taxCode' => $code,
    608     ];
    609 
    610     $tax = new WC_Tax();
    611     foreach ($order->get_items() as $item) {
    612       $product_variation_id = $item['variation_id'];
    613 
    614       // Check if product has variation.
    615       if ($product_variation_id) {
    616         $_product = wc_get_product($item['variation_id']);
    617       } else {
    618         $_product = wc_get_product($item['product_id']);
    619       }
    620 
    621       // Get SKU
    622       $item_sku = $_product->get_sku();
    623 
    624       //For taxes
    625       $taxes = $tax->get_rates($item->get_tax_class());
    626       $rates = array_shift($taxes);
    627 
    628       //Take only the item rate and round it.  NULL is for default tax
    629       ($rates == NULL ? $item_rate = 23 : $item_rate = round(array_shift($rates)));
    630 
    631       $data['items'][] = [
    632         'reference' => $item_sku,
    633         'price' => (float) $item->get_total() / $item->get_quantity(),
    634         'quantity' => $item->get_quantity(),
    635         'tax' => $item_rate,
    636         'discount' => 0,
    637         'description' => $item->get_name(),
    638       ];
    639     }
    640 
    641 
    642     $portes = 0;
    643 
    644     $portes = $order->get_shipping_total() + $order->get_shipping_tax();
    645 
    646     foreach ($order->fee_lines as $fee_item) {
    647       $portes += $fee_item->total;
    648     }
    649 
    650     if ($portes > 0) {
    651       $data['items'][] = [
    652         'reference' => 'PORTES',
    653         'price' => $portes,
    654         'quantity' => 1,
    655         'tax' => 23,
    656         'discount' => 0,
    657         'description' => 'Custos de expedição',
    658       ];
    659     }
    660 
    661 
    662     $response = wp_remote_request(
    663       $this->get_cofidis_url(),
    664       [
    665         'method' => 'POST',
    666         'user-agent' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:20.0) Gecko/20100101 Firefox/20.0',
    667         'headers' => [
    668           'Content-Type' => 'application/json',
    669           'Cache-Control' => 'no-cache',
    670           'X-WP-Nonce' => $nonce,
    671           'Authorization' => 'ApiKey ' . $this->get_api_key(),
    672           'X-App-Source'   => WC_Eupago::SOURCE,
    673           'X-App-Version'  => WC_Eupago::VERSION,
    674           'X-Runtime-Info' => 'PHP ' . PHP_VERSION
    675         ],
    676         'body' => json_encode($data),
    677       ]
    678     );
    679 
    680     $response_body = wp_remote_retrieve_body($response);
    681 
    682     return json_decode($response_body);
    683555  }
    684556
    … …  
    759631          'Accept: application/json',
    760632          'Authorization: ApiKey ' . $this->get_api_key(),
    761           'X-App-Source'   => WC_Eupago::SOURCE,
    762           'X-App-Version'  => WC_Eupago::VERSION,
    763           'X-Runtime-Info' => 'PHP ' . PHP_VERSION
     633          'X-App-Source: ' . WC_Eupago::SOURCE,
     634          'X-App-Version: ' . WC_Eupago::VERSION,
     635          'X-Runtime-Info: PHP ' . PHP_VERSION
    764636      );
    765637     
    … …  
    798670      ),
    799671      'customer' => array(
    800         'notify'      => true,
     672        'notify' => false,
    801673        'email'       => $order->get_billing_email(),
    802674        'nome'   => $order->get_billing_first_name() . ' ' . $order->get_billing_last_name(),
    … …  
    808680      'Accept: application/json',
    809681      'Authorization: ApiKey ' . $this->get_api_key(),
    810       'X-App-Source'   => WC_Eupago::SOURCE,
    811       'X-App-Version'  => WC_Eupago::VERSION,
    812       'X-Runtime-Info' => 'PHP ' . PHP_VERSION
     682      'X-App-Source: ' . WC_Eupago::SOURCE,
     683      'X-App-Version: ' . WC_Eupago::VERSION,
     684      'X-Runtime-Info: PHP ' . PHP_VERSION
    813685    );
    814686
  • eupago-gateway-for-woocommerce/trunk/includes/class-wc-eupago-applepay.php

    r3375615 r3732472  
    3737            add_action('woocommerce_thankyou_' . $this->id, [ $this, 'thankyou_page' ]);
    3838            add_action('woocommerce_order_details_after_order_table', [ $this, 'order_details_after_order_table' ], 20);
     39            add_action('woocommerce_email_before_order_table', [ $this, 'email_instructions' ], 10, 3);
    3940            add_filter('woocommerce_available_payment_gateways', [ $this, 'disable_unless_portugal' ]);
    4041            add_filter('woocommerce_available_payment_gateways', [ $this, 'disable_only_above_or_below' ]);
    … …  
    240241            $lang       = $this->determine_language();
    241242            $return_url = $this->get_return_url($order);
    242            
    243             $response = $this->client->getReferenciaApplePay($order, $order_total, $lang, $return_url);
     243
     244            // Failed payment or "back" button: back to the checkout with the cart restored (order stays on-hold)
     245            $cancel_url = WC_Eupago_Payment_Return::get_url($order);
     246
     247            $response = $this->client->getReferenciaApplePay($order, $order_total, $lang, $return_url, $cancel_url);
    244248           
    245249            $logger->info('Raw API response: ' . print_r($response, true), $context);
    … …  
    251255            }
    252256           
     257            if (isset($response['transactionStatus']) && strtolower($response['transactionStatus']) !== 'success') {
     258                $error_message = $response['text'] ?? __('Unknown error.', 'eupago-gateway-for-woocommerce');
     259                $logger->error("Transaction rejected: {$error_message}. Full response: " . print_r($response, true), $context);
     260                wc_add_notice(__('Payment error:', 'eupago-gateway-for-woocommerce') . ' ' . $error_message, 'error');
     261                return [ 'result' => 'fail' ];
     262            }
     263
    253264            $redirect_url = $response['redirectUrl'] ?? '';
    254265            if (empty($redirect_url)) {
    … …  
    258269            }
    259270           
    260             if (isset($response['transactionStatus']) && strtolower($response['transactionStatus']) !== 'success') {
    261                 $error_message = $response['text'] ?? __('Unknown error.', 'eupago-gateway-for-woocommerce');
    262                 $logger->error("Transaction rejected: {$error_message}. Full response: " . print_r($response, true), $context);
    263                 wc_add_notice(__('Payment error:', 'eupago-gateway-for-woocommerce') . ' ' . $error_message, 'error');
    264                 return [ 'result' => 'fail' ];
    265             }
    266            
    267271            $order->update_meta_data('_eupago_applepay_tid', $response['transactionID'] ?? '');
    268272            $order->update_meta_data('_eupago_applepay_reference', $response['reference'] ?? '');
    … …  
    271275            $order->update_status('on-hold', __('Awaiting Apple Pay payment.', 'eupago-gateway-for-woocommerce'));
    272276           
    273             $this->reduce_stock_levels($order_id);
     277            $this->reduce_stock_levels($order);
    274278            WC()->cart->empty_cart();
    275279            WC()->session->__unset('order_awaiting_payment');
    … …  
    281285        }
    282286       
     287        /**
     288         * Payment block in the customer's on-hold email, same templates as the
     289         * other gateways.
     290         */
     291        public function email_instructions($order, $sent_to_admin, $plain_text = false) {
     292            if ($sent_to_admin || !$order->has_status('on-hold') || $order->get_payment_method() !== $this->id) {
     293                return;
     294            }
     295
     296            wc_get_template(
     297                $plain_text ? 'emails/plain-instructions.php' : 'emails/html-instructions.php',
     298                [
     299                    'method'       => $this->id,
     300                    'payment_name' => $this->title,
     301                    'instructions' => isset($this->instructions) && !empty($this->instructions) ? $this->instructions : '',
     302                    'referencia'   => $order->get_meta('_eupago_applepay_reference', true),
     303                    'order_total'  => $order->get_total(),
     304                ],
     305                'woocommerce/eupago/',
     306                (new WC_Eupago())->get_templates_path()
     307            );
     308        }
     309
    283310        private function reduce_stock_levels($order) {
    284311            if ($this->stock_when == 'order') {
  • eupago-gateway-for-woocommerce/trunk/includes/class-wc-eupago-callback.php

    r3432579 r3732472  
    2222    }
    2323
     24    protected function debug_log($message)
     25    {
     26        if ($this->log instanceof WC_Logger) {
     27            $this->log->add($this->id, $message);
     28        }
     29    }
     30
    2431    function callback_log($message, $error = false)
    2532    {
    … …  
    2734        $response = $error ? 500 : 200;
    2835
    29         if ($this->integration->debug) {
    30             $this->log->add($this->id, '- Callback (' . $_SERVER['REQUEST_URI'] . ') ' . $_SERVER['REMOTE_ADDR'] . ' - ' . $message);
    31         }
     36        $request_uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
     37        $remote_addr = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '';
     38
     39        $this->debug_log('- Callback (' . $request_uri . ') ' . $remote_addr . ' - ' . $message);
    3240        if ($this->integration->debug_email != '') {
    33             wp_mail($this->integration->debug_email, $this->id . ' - Error: Callback with missing arguments', 'Callback ( ' . $_SERVER['HTTP_HOST'] . ' ' . $_SERVER['REQUEST_URI'] . ' ) with missing arguments from ' . $_SERVER['REMOTE_ADDR'] . $message);
     41            $http_host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '';
     42            wp_mail($this->integration->debug_email, $this->id . ' - Error: Callback with missing arguments', 'Callback ( ' . $http_host . ' ' . $request_uri . ' ) with missing arguments from ' . $remote_addr . $message);
    3443        }
    3544
    … …  
    3948    public function callback_handler()
    4049    {
    41         $this->log->add($this->id, 'Callback handler triggered.');
    42 
    43         $request_method = $_SERVER['REQUEST_METHOD'];
     50        $this->debug_log('Callback handler triggered.');
     51
     52        $request_method = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : '';
    4453        $order = null;
    4554        $transacao = null;
    … …  
    5160
    5261        if ($request_method === 'POST') {
    53             $this->log->add($this->id, 'Processing POST request...');
     62            $this->debug_log('Processing POST request...');
    5463
    5564            if (function_exists('getallheaders')) {
    … …  
    7988                $this->callback_log('Chave criptográfica não configurada.', true);
    8089                return;
     90            }
     91
     92            $raw_body  = file_get_contents('php://input');
     93            $post_body = json_decode($raw_body, true);
     94
     95            // Encrypted deliveries carry the ciphertext in "data" plus an IV header;
     96            // unencrypted ones carry the transaction JSON directly in the body.
     97            $is_encrypted = is_array($post_body) && isset($post_body['data']) && is_string($post_body['data']) && $iv !== '';
     98
     99            if ($key == 'NA') {
     100                // Channel without a key (older channels). There is nothing to verify
     101                // the signature against, so only unencrypted payloads can be processed.
     102                if ($is_encrypted) {
     103                    $this->callback_log('Webhook encriptado mas o canal não tem chave configurada. Sincronize o canal nas definições do plugin.', true);
     104                    return;
     105                }
     106                $this->debug_log('Channel key is NA: processing unsigned webhook.');
     107                $response_data = $post_body;
    81108            } else {
    82                 $post_body = json_decode(file_get_contents('php://input'), true);
    83                 if ($key == 'NA') {
    84                     $response_data = $post_body;
    85                 } else {
    86                     $encrypted_data = $post_body['data'] ?? '';
    87                     $response_data = json_decode($this->decryptData($encrypted_data, $iv, $key), true);
    88                     $isSignatureVerified = $this->verifySignature($encrypted_data, $signature, $key);
    89 
    90                     if (!$isSignatureVerified || empty($response_data)) {
    91                         $this->callback_log('Assinatura inválida ou dados desencriptados inválidos', true);
    92                         return;
    93                     }
     109                // Every webhook is signed with the channel key, encrypted or not:
     110                // HMAC over the ciphertext when encrypted, over the raw body otherwise.
     111                $signed_payload = $is_encrypted ? $post_body['data'] : $raw_body;
     112
     113                if ($signature === '' || !$this->verifySignature($signed_payload, $signature, $key)) {
     114                    $this->callback_log('Assinatura inválida', true);
     115                    return;
     116                }
     117
     118                $response_data = $is_encrypted
     119                    ? json_decode($this->decryptData($post_body['data'], $iv, $key), true)
     120                    : $post_body;
     121
     122                if (empty($response_data) || !is_array($response_data)) {
     123                    $this->callback_log('Dados do webhook inválidos', true);
     124                    return;
    94125                }
    95126            }
    … …  
    103134
    104135        } elseif ($request_method === 'GET') {
    105             $this->log->add($this->id, 'Processing GET request...');
     136            $this->debug_log('Processing GET request...');
    106137
    107138            $api_key = isset($_GET['chave_api']) ? sanitize_text_field($_GET['chave_api']) : '';
    … …  
    136167        if (!$order->has_status(['on-hold', 'pending'])) {
    137168            $this->callback_log('Pedido já não se encontra pendente.', true);
     169            return;
     170        }
     171
     172        if (strpos((string) $order->get_payment_method(), 'eupago_') !== 0) {
     173            $this->callback_log('Pedido não foi pago através da Eupago.', true);
    138174            return;
    139175        }
    … …  
    204240    public function decryptData($encrypted_data, $iv, $key)
    205241    {
    206         $this->log->add($this->id, 'Decrypting data...');
     242        $this->debug_log('Decrypting data...');
    207243        $cipher = 'aes-256-cbc';
    208244        $options = OPENSSL_RAW_DATA;
    … …  
    210246
    211247        if ($response_data) {
    212             $this->log->add($this->id, 'Data decrypted successfully.');
    213         } else {
    214             $this->log->add($this->id, 'Failed to decrypt data.', true);
     248            $this->debug_log('Data decrypted successfully.');
     249        } else {
     250            $this->debug_log('Failed to decrypt data.');
    215251        }
    216252
    … …  
    220256    public function verifySignature($encrypted_data, $signature, $key)
    221257    {
    222         $this->log->add($this->id, 'Verifying signature...');
     258        $this->debug_log('Verifying signature...');
    223259        $generated_signature = hash_hmac('sha256', $encrypted_data, $key, true);
    224260
    225261        if ($generated_signature) {
    226             $this->log->add($this->id, 'Signature verified successfully.');
    227         } else {
    228             $this->log->add($this->id, 'Failed to verify signature.', true);
     262            $this->debug_log('Signature verified successfully.');
     263        } else {
     264            $this->debug_log('Failed to verify signature.');
    229265        }
    230266
    … …  
    242278                'PSC:PT' => ['eupago_psc'],
    243279                'PF:PT' => ['eupago_pf'],
    244                 'CP:PT' => ['eupago_cofidispay'],
    245280                'BZ:PT' => ['eupago_bizum'],
    246281                'PX:PT' => ['eupago_pix'],
    … …  
    266301                'eupago_psc' => 'WC_Eupago_PSC',
    267302                'eupago_pf' => 'WC_Eupago_PF',
    268                 'eupago_codifispay' => 'WC_Eupago_CofidisPay',
    269303                'eupago_bizum' => 'WC_Eupago_Bizum',
    270304                'eupago_pix' => 'WC_Eupago_Pix',
  • eupago-gateway-for-woocommerce/trunk/includes/class-wc-eupago-cc.php

    r3382429 r3732472  
    7474
    7575            // Customer Emails
    76             add_action('woocommerce_email_before_order_table', [$this, 'email_instructions'], 10, 2);
     76            add_action('woocommerce_email_before_order_table', [$this, 'email_instructions'], 10, 3);
    7777
    7878            // Filter to decide if payment_complete reduces stock, or not
    … …  
    464464            $lang = $this->determine_language();
    465465
    466             // Call API
    467466            $eupagoCC = $this->client->pedidoCC(
    468467                $order,
    469468                $order_total,
    470                 $this->get_option('logo_url'),
    471469                $this->get_return_url($order),
    472470                $lang,
    473                 $this->get_comment_table($order, $order_total)
     471                WC_Eupago_Payment_Return::get_url($order)
    474472            );
    475473
    476474            $logger->debug("CC: Raw response -> " . print_r($eupagoCC, true), $context);
    477475
     476            if (!is_array($eupagoCC) || isset($eupagoCC['error'])) {
     477                $error_message = is_array($eupagoCC) && !empty($eupagoCC['error']) ? $eupagoCC['error'] : __('Unknown error', 'eupago-gateway-for-woocommerce');
     478                $logger->error("CC: API call failed -> {$error_message}", $context);
     479                wc_add_notice(__('Payment error:', 'eupago-gateway-for-woocommerce') . ' ' . $error_message, 'error');
     480                return ['result' => 'fail', 'redirect' => ''];
     481            }
     482
     483            // Handle errors
     484            if (!isset($eupagoCC['transactionStatus']) || strtolower($eupagoCC['transactionStatus']) !== 'success') {
     485                $error_message = $eupagoCC['text'] ?? $eupagoCC['message'] ?? __('Unknown error', 'eupago-gateway-for-woocommerce');
     486                $logger->error("CC: Eupago returned transactionStatus=" . ($eupagoCC['transactionStatus'] ?? 'n/a') . " -> {$error_message}", $context);
     487                wc_add_notice(__('Payment error:', 'eupago-gateway-for-woocommerce') . ' ' . $error_message, 'error');
     488                return ['result' => 'fail', 'redirect' => ''];
     489            }
     490
    478491            // Extract redirect URL
    479             if (isset($eupagoCC['redirectUrl'])) {
    480                 $redirect_url = $eupagoCC['redirectUrl'];
    481             } else {
     492            $redirect_url = $eupagoCC['redirectUrl'] ?? '';
     493            if (empty($redirect_url)) {
    482494                $logger->error("CC: No redirectUrl found in response", $context);
    483495                wc_add_notice(__('No redirect URL received from Eupago.', 'eupago-gateway-for-woocommerce'), 'error');
    484                 return ['result' => 'fail', 'redirect' => ''];
    485             }
    486 
    487             // Handle errors
    488             if (!empty($eupagoCC['transactionStatus']) && $eupagoCC['transactionStatus'] != 0 && $eupagoCC['estado'] != 'Success') {
    489                 $error_message = $eupagoCC['message'] ?? __('Unknown error', 'eupago-gateway-for-woocommerce');
    490                 $logger->error("CC: Eupago returned estado={$eupagoCC['transactionStatus']} -> {$error_message}", $context);
    491                 wc_add_notice(__('Payment error:', 'eupago-gateway-for-woocommerce') . ' ' . $error_message, 'error');
    492496                return ['result' => 'fail', 'redirect' => ''];
    493497            }
    … …  
    498502            $order->save();
    499503
    500             $logger->debug("CC: Saved TID={$eupagoCC['transactionID']} reference={$eupagoCC['reference']}", $context);
     504            $logger->debug("CC: Saved TID=" . ($eupagoCC['transactionID'] ?? '') . " reference=" . ($eupagoCC['reference'] ?? ''), $context);
    501505
    502506            // Mark order on-hold
  • eupago-gateway-for-woocommerce/trunk/includes/class-wc-eupago-googlepay.php

    r3383861 r3732472  
    6060           
    6161            // Emails
    62             add_action('woocommerce_email_before_order_table', [ $this, 'email_instructions' ], 10, 2);
     62            add_action('woocommerce_email_before_order_table', [ $this, 'email_instructions' ], 10, 3);
    6363        }
    6464       
    … …  
    282282       
    283283        public function email_instructions($order, $sent_to_admin, $plain_text = false) {
    284             if ($sent_to_admin || $order->get_payment_method() !== $this->id) {
     284            if ($sent_to_admin || !$order->has_status('on-hold') || $order->get_payment_method() !== $this->id) {
    285285                return;
    286286            }
    287            
     287
    288288            wc_get_template(
    289                 'emails/email-instructions.php',
     289                $plain_text ? 'emails/plain-instructions.php' : 'emails/html-instructions.php',
    290290                [
    291                     'order'         => $order,
    292                     'email_heading' => $this->title,
    293                     'payment_method'=> $this->id,
    294                     'instructions'  => $this->instructions,
    295                     'transaction_id'=> $order->get_meta('_eupago_googlepay_tid'),
    296                     'reference'     => $order->get_meta('_eupago_googlepay_reference'),
    297                     'order_total'   => $order->get_total(),
     291                    'method'       => $this->id,
     292                    'payment_name' => $this->title,
     293                    'instructions' => isset($this->instructions) && !empty($this->instructions) ? $this->instructions : '',
     294                    'referencia'   => $order->get_meta('_eupago_googlepay_reference', true),
     295                    'order_total'  => $order->get_total(),
    298296                ],
    299297                'woocommerce/eupago/',
    … …  
    353351            $lang       = $this->determine_language();
    354352            $return_url = $this->get_return_url($order);
    355            
    356             $gpayResponse = $this->client->getReferenciaGooglePay($order, $order_total, $lang, $return_url);
     353            // Only a successful payment may land on the thank-you page. A failed
     354            // payment or the "back" button go through the payment-return endpoint,
     355            // which leaves the order on-hold and restores the cart.
     356            $cancel_url = WC_Eupago_Payment_Return::get_url($order);
     357
     358            $gpayResponse = $this->client->getReferenciaGooglePay($order, $order_total, $lang, $return_url, $cancel_url);
    357359           
    358360            if (!is_array($gpayResponse)) {
    … …  
    362364            }
    363365           
     366            // Check the status before the redirect URL: a rejected request has no
     367            // redirectUrl, and the rejection reason (e.g. URL_INVALID) is what
     368            // has to reach the log and the customer.
     369            if (isset($gpayResponse['transactionStatus']) && strtolower($gpayResponse['transactionStatus']) !== 'success') {
     370                $error_message = $gpayResponse['text'] ?? __('Erro desconhecido.', 'eupago-gateway-for-woocommerce');
     371                $logger->error("Transaction rejected: {$error_message} (code=" . ($gpayResponse['code'] ?? 'n/a') . ")", $context);
     372                wc_add_notice(__('Payment error:', 'eupago-gateway-for-woocommerce') . ' ' . $error_message, 'error');
     373                return [ 'result' => 'fail' ];
     374            }
     375
    364376            $redirect_url = $gpayResponse['redirectUrl'] ?? '';
    365377            if (empty($redirect_url)) {
    366                 $logger->error("No redirectUrl in response", $context);
     378                $logger->error("No redirectUrl in response: " . print_r($gpayResponse, true), $context);
    367379                wc_add_notice(__('Erro ao obter URL de redirecionamento do gateway.', 'eupago-gateway-for-woocommerce'), 'error');
    368                 return [ 'result' => 'fail' ];
    369             }
    370            
    371             if (isset($gpayResponse['transactionStatus']) && strtolower($gpayResponse['transactionStatus']) !== 'success') {
    372                 $error_message = $gpayResponse['text'] ?? __('Erro desconhecido.', 'eupago-gateway-for-woocommerce');
    373                 $logger->error("Transaction rejected: {$error_message}", $context);
    374                 wc_add_notice(__('Payment error:', 'eupago-gateway-for-woocommerce') . ' ' . $error_message, 'error');
    375380                return [ 'result' => 'fail' ];
    376381            }
    … …  
    382387            $order->update_status('on-hold', __('Aguardando pagamento via Google Pay.', 'eupago-gateway-for-woocommerce'));
    383388           
    384             $this->reduce_stock_levels($order->get_id());
     389            $this->reduce_stock_levels($order);
    385390           
    386391            WC()->cart->empty_cart();
  • eupago-gateway-for-woocommerce/trunk/includes/class-wc-eupago-multibanco.php

    r3375615 r3732472  
    458458                wc_add_notice(__('Payment error:', 'eupago-gateway-for-woocommerce') . $error_message, 'error');
    459459
    460                 return;
     460                return ['result' => 'failure', 'redirect' => ''];
    461461            }
    462462
    … …  
    472472            }
    473473
    474             if (extension_loaded('soap')) {
    475                 if ($eupagoMultibanco->estado != 0) {
    476                     $error_message = $eupagoMultibanco->resposta;
    477                     wc_add_notice(__('Payment error:', 'eupago-gateway-for-woocommerce') . $error_message, 'error');
    478 
    479                     return;
    480                 }
    481             } else {
    482                 $eupagoMultibanco_decode = json_decode($eupagoMultibanco, true);
    483 
    484                 if ($eupagoMultibanco_decode['estado'] != 0) {
    485                     $error_message = $eupagoMultibanco_decode['resposta'];
    486                     wc_add_notice(__('Payment error:', 'eupago-gateway-for-woocommerce') . $error_message, 'error');
    487 
    488                     return;
    489                 }
    490             }
    491 
    492             if (extension_loaded('soap')) {
    493                 // update_post_meta ($order_id, '_eupago_multibanco_entidade', $eupagoMultibanco->entidade);
    494                 // update_post_meta ($order_id, '_eupago_multibanco_referencia', $eupagoMultibanco->referencia);
    495                 $order->update_meta_data('_eupago_multibanco_entidade', $eupagoMultibanco->entidade);
    496                 $order->update_meta_data('_eupago_multibanco_referencia', $eupagoMultibanco->referencia);
    497                 $order->save();
    498             } else {
    499                 $eupagoMultibanco_decode = json_decode($eupagoMultibanco, true);
    500                 // update_post_meta ($order_id, '_eupago_multibanco_entidade', $eupagoMultibanco_decode['entidade']);
    501                 // update_post_meta ($order_id, '_eupago_multibanco_referencia', $eupagoMultibanco_decode['referencia']);
    502                 $order->update_meta_data('_eupago_multibanco_entidade', $eupagoMultibanco_decode['entidade']);
    503                 $order->update_meta_data('_eupago_multibanco_referencia', $eupagoMultibanco_decode['referencia']);
    504                 $order->save();
    505             }
     474            if (!is_object($eupagoMultibanco) || !isset($eupagoMultibanco->estado) || $eupagoMultibanco->estado != 0) {
     475                $error_message = is_object($eupagoMultibanco) && isset($eupagoMultibanco->resposta) ? $eupagoMultibanco->resposta : '';
     476                wc_add_notice(__('Payment error:', 'eupago-gateway-for-woocommerce') . $error_message, 'error');
     477
     478                return ['result' => 'failure', 'redirect' => ''];
     479            }
     480
     481            $order->update_meta_data('_eupago_multibanco_entidade', $eupagoMultibanco->entidade ?? '');
     482            $order->update_meta_data('_eupago_multibanco_referencia', $eupagoMultibanco->referencia ?? '');
     483            $order->save();
    506484
    507485            // Mark as on-hold
  • eupago-gateway-for-woocommerce/trunk/includes/class-wc-eupago-pagaqui.php

    r3432579 r3732472  
    3232      $this->id = 'eupago_pagaqui';
    3333
    34       $this->icon = plugins_url('assets/images/pagaqui_icon.png', dirname(__FILE__));
     34      $this->icon = plugins_url('assets/images/pagaqui_logo.png', dirname(__FILE__));
    3535      $this->has_fields = false;
    3636      $this->method_title = __('Pagaqui (Eupago)', 'eupago-gateway-for-woocommerce');
    … …  
    343343      if ($error_message = $this->check_order_errors($order_id)) {
    344344        wc_add_notice(__('Payment error:', 'eupago-gateway-for-woocommerce') . $error_message, 'error');
    345         return;
     345        return ['result' => 'failure', 'redirect' => ''];
    346346      }
    347347
  • eupago-gateway-for-woocommerce/trunk/includes/class-wc-eupago-paysafecard.php

    r3332324 r3732472  
    254254      if ($error_message = $this->check_order_errors($order_id)) {
    255255        wc_add_notice( __('Payment error:', 'eupago-gateway-for-woocommerce') . ' ' . $error_message, 'error' );
    256         return;
     256        return ['result' => 'failure', 'redirect' => ''];
    257257      }
    258258
    … …  
    265265
    266266
    267       if (extension_loaded('soap')) {
    268         if ( $eupagoPF->estado != 0 ) {
    269           $error_message = $eupagoPF->resposta;
    270           wc_add_notice( __('Payment error:', 'eupago-gateway-for-woocommerce') . ' ' . $error_message, 'error' );
    271           return;
    272         }
    273       } else {
    274         $eupagoPF_decode = json_decode($eupagoPF, true);
    275         if ( $eupagoPF_decode['estado'] != 0 ) {
    276           $error_message = $eupagoPF_decode['resposta'];
    277           wc_add_notice( __('Payment error:', 'eupago-gateway-for-woocommerce') . ' ' . $error_message, 'error' );
    278           return;
    279         }
    280       }
    281 
    282       if (extension_loaded('soap')) {
    283         // update_post_meta ($order_id, '_eupago_pf_referencia', $eupagoPF->referencia);
    284         $order->update_meta_data( '_eupago_pf_referencia', $eupagoPF->referencia);
    285         $order->save();
    286       } else {
    287         $eupagoPF_decode = json_decode($eupagoPF, true);
    288         // update_post_meta ($order_id, '_eupago_pf_referencia', $eupagoPF_decode['referencia']);
    289         $order->update_meta_data( '_eupago_pf_referencia', $eupagoPF_decode['referencia']);
    290         $order->save();
    291       }
     267      if ( ! is_object( $eupagoPF ) || ! isset( $eupagoPF->estado ) || $eupagoPF->estado != 0 ) {
     268        $error_message = is_object( $eupagoPF ) && isset( $eupagoPF->resposta ) ? $eupagoPF->resposta : '';
     269        wc_add_notice( __('Payment error:', 'eupago-gateway-for-woocommerce') . ' ' . $error_message, 'error' );
     270        return ['result' => 'failure', 'redirect' => ''];
     271      }
     272
     273      $order->update_meta_data( '_eupago_pf_referencia', $eupagoPF->referencia ?? '' );
     274      $order->save();
    292275
    293276      // Mark as on-hold
  • eupago-gateway-for-woocommerce/trunk/includes/class-wc-eupago-payshop.php

    r3375615 r3732472  
    401401      if ($error_message = $this->check_order_errors($order_id)) {
    402402        wc_add_notice( __('Payment error:', 'eupago-gateway-for-woocommerce') . $error_message, 'error' );
    403         return;
     403        return ['result' => 'failure', 'redirect' => ''];
    404404      }
    405405     
    406406      $eupagoPayShop = $this->client->getReferenciaPS( $order_id, $order_total );
    407407     
    408       if (extension_loaded('soap')) {
    409         if ( $eupagoPayShop->estado != 0 ) {
    410           $error_message = $eupagoPayShop->resposta;
    411           wc_add_notice( __('Payment error:', 'eupago-gateway-for-woocommerce') . $error_message, 'error' );
    412           return;
    413         }
    414       } else {
    415         $eupagoPayShop_decode = json_decode($eupagoPayShop, true);
    416         if ( $eupagoPayShop_decode['estado'] != 0 ) {
    417           $error_message = $eupagoPayShop_decode['resposta'];
    418           wc_add_notice( __('Payment error:', 'eupago-gateway-for-woocommerce') . $error_message, 'error' );
    419           return;
    420         }
    421       }
    422      
    423       if (extension_loaded('soap')) {
    424         // update_post_meta ($order_id, '_eupago_payshop_referencia', $eupagoPayShop->referencia);
    425         $order->update_meta_data( '_eupago_payshop_referencia', $eupagoPayShop->referencia);
    426         $order->save();
    427       } else {
    428         $eupagoPayShop_decode = json_decode($eupagoPayShop, true);
    429         // update_post_meta ($order_id, '_eupago_payshop_referencia', $eupagoPayShop_decode['referencia']);
    430         $order->update_meta_data( '_eupago_payshop_referencia', $eupagoPayShop_decode['referencia']);
    431         $order->save();
    432       }
     408      if ( ! is_object( $eupagoPayShop ) || ! isset( $eupagoPayShop->estado ) || $eupagoPayShop->estado != 0 ) {
     409        $error_message = is_object( $eupagoPayShop ) && isset( $eupagoPayShop->resposta ) ? $eupagoPayShop->resposta : '';
     410        wc_add_notice( __('Payment error:', 'eupago-gateway-for-woocommerce') . $error_message, 'error' );
     411        return ['result' => 'failure', 'redirect' => ''];
     412      }
     413
     414      $order->update_meta_data( '_eupago_payshop_referencia', $eupagoPayShop->referencia ?? '' );
     415      $order->save();
    433416     
    434417      // Mark as on-hold
  • eupago-gateway-for-woocommerce/trunk/includes/hooks/hooks-refund.php

    r3522116 r3732472  
    3232    $order = wc_get_order($refund_order);
    3333
    34     $trid = $order->get_meta('_transaction_id', true);
     34    // wc_get_order() returns false for an invalid id, so bail before using $order.
     35    if (!$order) {
     36        echo '<p class="eupago-output-error">' . esc_html__('Order not found', 'eupago-gateway-for-woocommerce') . '</p>';
     37        wp_die();
     38    }
     39
     40    $trid = $order->get_transaction_id();
    3541
    3642    $payment_method = $order->get_payment_method();
     43
     44    $output_class   = 'eupago-output-error';
     45    $output_request = __('Request error', 'eupago-gateway-for-woocommerce');
    3746
    3847    if (!empty($refund_amount)) {
    … …  
    5766        // Check if the request was successful
    5867
    59         if ($responseData['transactionStatus'] === 'Rejected') {
     68        $transaction_status = isset($responseData['transactionStatus']) ? $responseData['transactionStatus'] : '';
     69
     70        if ($transaction_status === 'Rejected') {
    6071            // Handle the error
    6172            $output_class = 'eupago-output-error';
    6273            $output_request = __('Invalid Credentials: Check your client id and client secret', 'eupago-gateway-for-woocommerce');
     74        } elseif ($transaction_status !== 'Success') {
     75            // Unexpected response: without this branch both $output_* stay undefined.
     76            $output_class = 'eupago-output-error';
     77            $output_request = __('Request error', 'eupago-gateway-for-woocommerce');
    6378        } else {
    6479            curl_close($ch);
    65             if ($responseData['transactionStatus'] === 'Success') {
    66                 $accessToken = $responseData['access_token'];
     80                $accessToken = isset($responseData['access_token']) ? $responseData['access_token'] : '';
    6781                $headerRefund = [
    6882                    'Content-Type: application/json',
    … …  
    108122                $newResponse = curl_exec($newCh);
    109123                $jsonResponseRefund = json_decode($newResponse, true);
    110                 if ($jsonResponseRefund['transactionStatus'] === 'Success') {
     124                $refund_status      = isset($jsonResponseRefund['transactionStatus']) ? $jsonResponseRefund['transactionStatus'] : '';
     125                $refund_code        = isset($jsonResponseRefund['code']) ? $jsonResponseRefund['code'] : '';
     126                if ($refund_status === 'Success') {
    111127                    // Add a note to the order with the refunded amount
    112                     $order = wc_get_order(sanitize_text_field($_POST['refund_order']));
    113128                    $refunded_amount = floatval($refund_amount);
    114129                    $current_time = current_time('Y-m-d H:i:s'); // Get the current timestamp
    … …  
    119134                } else {
    120135                    $output_class = 'eupago-output-error';
    121                     if ($jsonResponseRefund['code'] == 'IBAN_INVALID') {
     136                    if ($refund_code == 'IBAN_INVALID') {
    122137                        $output_request = __('IBAN Invalid', 'eupago-gateway-for-woocommerce');
    123                     } elseif ($jsonResponseRefund['code'] == 'BIC_INVALID') {
     138                    } elseif ($refund_code == 'BIC_INVALID') {
    124139                        $output_request = __('BIC Invalid', 'eupago-gateway-for-woocommerce');
    125                     } elseif ($jsonResponseRefund['code'] == 'AMOUNT_INVALID') {
     140                    } elseif ($refund_code == 'AMOUNT_INVALID') {
    126141                        $output_request = __('Amount Invalid', 'eupago-gateway-for-woocommerce');
    127142                    } else {
    … …  
    129144                    }
    130145                }
    131             }
    132146        }
    133147    } else {
    134         // Close the cURL session
    135         curl_close($ch);
    136148        $output_class = 'eupago-output-error';
    137149        $output_request = __('Fill all fields', 'eupago-gateway-for-woocommerce');
  • eupago-gateway-for-woocommerce/trunk/includes/hooks/hooks-sms.php

    r3611346 r3732472  
    6363               $pixCode       = $order->get_meta('_eupago_pix_pixCode', true);
    6464               $payment_data  =  __( 'Reference:', 'eupago-gateway-for-woocommerce' ) . ' ' . $reference . ' ' . __( 'Value:', 'eupago-gateway-for-woocommerce' ) . ' ' . $amount . ' ' . __( 'QR Code:', 'eupago-gateway-for-woocommerce' ) . ' ' . $pixImage . ' ' . __( 'EuroPix Code:', 'eupago-gateway-for-woocommerce' ) . ' ' . $pixCode;
     65                break;
    6566          case 'eupago_googlepay': // google pay
    6667            $reference     = $order->get_meta( '_eupago_googlepay_reference', true );
    … …  
    104105            'Accept: application/json',
    105106            'Content-Type: application/x-www-form-urlencoded',
    106             'X-App-Source'   => WC_Eupago::SOURCE,
    107             'X-App-Version'  => WC_Eupago::VERSION,
    108             'X-Runtime-Info' => 'PHP ' . PHP_VERSION
     107            'X-App-Source: ' . WC_Eupago::SOURCE,
     108            'X-App-Version: ' . WC_Eupago::VERSION,
     109            'X-Runtime-Info: PHP ' . PHP_VERSION
    109110         ),
    110111         'body' => array(
    … …  
    140141            'Accept: application/json',
    141142            'Content-Type: application/x-www-form-urlencoded',
    142             'X-App-Source'   => WC_Eupago::SOURCE,
    143             'X-App-Version'  => WC_Eupago::VERSION,
    144             'X-Runtime-Info' => 'PHP ' . PHP_VERSION
     143            'X-App-Source: ' . WC_Eupago::SOURCE,
     144            'X-App-Version: ' . WC_Eupago::VERSION,
     145            'X-Runtime-Info: PHP ' . PHP_VERSION
    145146         ),
    146147         'body' => array(
  • eupago-gateway-for-woocommerce/trunk/includes/views/eupago-admin-page.php

    r3522116 r3732472  
    77    // Check if WooCommerce is active
    88    if (class_exists('WooCommerce')) {
    9         // Get the URL components
    10         $protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https://' : 'http://';
    11         $domain = $_SERVER['HTTP_HOST'];
    12 
    13         // Get the shop base slug
    14         $shop_base_slug = get_option('woocommerce_shop_page_id');
    15         // $base_uri = ($shop_base_slug) ? '/' . get_page_uri($shop_base_slug) . '/' : '/';
    16 
    17         // Add the custom part to the store URL
    18         $custom_part = '/?wc-api=WC_euPago';
    19 
    20         // Combine the components to form the store URL
    21         $store_url = $protocol . $domain . $custom_part;
    22 
    23         return $store_url;
     9        // home_url() instead of $_SERVER['HTTPS'] and $_SERVER['HTTP_HOST']: those are
     10        // not always set, and they ignore the site URL configured in WordPress.
     11        return home_url('/?wc-api=WC_euPago');
    2412    } else {
    2513        // WooCommerce is not active, handle the error or return a default URL
    … …  
    4735    $callback_url = getStoreUrl(); // Set the callback URL to the value returned by getStoreUrl()
    4836
    49     if (isset($_POST['eupago_save']) && wp_verify_nonce($_POST['_wpnonce'], 'eupago_settings_nonce')) {
     37    if (isset($_POST['eupago_save'], $_POST['_wpnonce']) && wp_verify_nonce($_POST['_wpnonce'], 'eupago_settings_nonce')) {
    5038        if (sanitize_text_field(isset($_POST['eupago_save']))) {
    5139            $channel   = isset($_POST['channel'])
    … …  
    7765                : '';
    7866
    79             $user_eupago = isset($_POST['user_eupago'])
    80                 ? sanitize_text_field(wp_unslash($_POST['user_eupago']))
    81                 : '';
    82 
    83             $password_eupago = isset($_POST['password_eupago'])
    84                 ? sanitize_text_field(wp_unslash($_POST['password_eupago']))
    85                 : '';
    86 
    8767            $sms_enable = isset($_POST['sms_enable'])
    8868                ? sanitize_text_field(wp_unslash($_POST['sms_enable']))
    … …  
    167147            }
    168148
    169             if (empty(get_option('eupago_user'))) {
    170                 delete_option('eupago_user');
    171                 add_option('eupago_user', $user_eupago, '', 'yes');
    172             } else {
    173                 update_option('eupago_user', $user_eupago);
    174             }
    175 
    176             if (empty(get_option('eupago_password'))) {
    177                 delete_option('eupago_password');
    178                 add_option('eupago_password', $password_eupago, '', 'yes');
    179             } else {
    180                 update_option('eupago_password', $password_eupago);
    181             }
    182 
    183149            if (empty(get_option('eupago_sms_enable'))) {
    184150                delete_option('eupago_sms_enable');
    … …  
    235201                update_option('biziq_environment', $biziq_environment);
    236202            }
    237 
    238             // Prepare POST data
    239             $request_body = [
    240                 'grant_type'       => 'client_credentials',
    241                 'client_id'        => $client_id,
    242                 'client_secret'    => $client_secret,
    243                 'callback_api_key' => $api_key,
    244             ];
    245 
    246             // Make the request to info-script.php
    247             $response = wp_remote_post(site_url('/wp-content/plugins/eupago-gateway-for-woocommerce/includes/views/info-script.php'), [
    248                 'body'    => $request_body,
    249                 'timeout' => 15,
    250             ]);
    251 
    252             // Handle errors
    253             if (is_wp_error($response)) {
    254                 $error_message = $response->get_error_message();
    255                 echo "Something went wrong: $error_message";
    256             } else {
    257                 // Retrieve and decode JSON body
    258                 $body = wp_remote_retrieve_body($response);
    259                 $data = json_decode($body, true);
    260 
    261                 if (!empty($data['channelInfo'])) {
    262                     $channel_data['eupago_webhook_version'] = $data['channelInfo']['webhookVersion'];
    263                     $channel_data['eupago_webhook_encrypt_key'] = $data['channelInfo']['webhookEncryptKey'];
    264                     $channel_data['eupago_webhook_url'] = $data['channelInfo']['webhookUrl'];
    265                     saveWebhookInfo($channel_data);
    266                 } else {
    267                     echo "Unexpected response format or missing channelInfo.";
    268                 }
    269             }
    270203        }
    271204    }
    272205
    273206    if (
    274         $_SERVER['REQUEST_METHOD'] === 'POST' &&
     207        isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'POST' &&
    275208        isset($_POST['eupago_webhook_nonce']) &&
    276209        wp_verify_nonce($_POST['eupago_webhook_nonce'], 'eupago_save_webhook')
    … …  
    313246    $eupago_settings_nonce = wp_create_nonce('eupago_settings_nonce');
    314247?>
    315     <!-- Include jQuery library -->
    316     <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    317 
    318248    <div class="eupago_header">
    319249        <div>
    … …  
    383313                    $debug_log = esc_html__('Debug Log: ', 'eupago-gateway-for-woocommerce');
    384314                    $log_plugins = esc_html__('Log plugin events and request responses inside', 'eupago-gateway-for-woocommerce');
    385                     $refund_text = esc_html('Refund:', 'eupago-gateway-for-woocommerce');
    386                     $user_text = esc_html__('User: ', 'eupago-gateway-for-woocommerce');
    387                     $password_text = esc_html__('Password', 'eupagp-gateway-for-woocommerce');
     315                    $refund_text = esc_html('Refund', 'eupago-gateway-for-woocommerce');
    388316                    $notificacoes_sms = esc_html__('Nofitications Biziq: ', 'eupago-gateway-for-woocommerce');
    389317                    $payment_on_hold = esc_html__('Send SMS with payment details:', 'eupago-gateway-for-woocommerce');
    … …  
    399327                    $environment = esc_html__('Environment', 'eupago-gateway-for-woocommerce');
    400328                    $sync_channel = esc_html__('Synchronize Channel Info', 'eupago-gateway-for-woocommerce');
    401                     $refund_note = esc_html__('Please make sure that the fields Client ID and Client Secret are properly filled to configure the refund functionality', 'eupago-gateway-for-woocommerce');
     329                    $refund_note = esc_html__('To use the refund functionality, the Client ID and Client Secret fields must be properly filled in.', 'eupago-gateway-for-woocommerce');
    402330                    if (get_locale() == 'pt_BR' || get_locale() == 'pt_PT') {
    403331                        $texto_traduzido = 'Cada conta tem pelo menos um canal. Cada canal possui uma chave API que identifica a sua conta da Eupago.';
    … …  
    423351                        $debug_log = esc_html__('Log de Depuração: ', 'eupago-gateway-for-woocommerce');
    424352                        $log_plugins = esc_html__('Registe eventos do plugin e as respostas a pedidos, dentro do diretório', 'eupago-gateway-for-woocommerce');
    425                         $refund_text = esc_html__('Reembolso:', 'eupago-gateway-for-woocommerce');
    426                         $user_text = esc_html__('Utilizador: ', 'eupago-gateway-for-woocommerce');
    427                         $password_text = esc_html__('Palavra-Passe', 'eupagp-gateway-for-woocommerce');
     353                        $refund_text = esc_html__('Reembolso', 'eupago-gateway-for-woocommerce');
    428354                        $notificacoes_sms = esc_html__('Notificações Biziq: ', 'eupago-gateway-for-woocommerce');
    429355                        $payment_on_hold = esc_html__('Envio de SMS dos detalhes de pagamento:', 'eupago-gateway-for-woocommerce');
    … …  
    439365                        $environment = esc_html__('Ambiente', 'eupago-gateway-for-woocommerce');
    440366                        $sync_channel = esc_html__('Sincronizar Informações do Canal', 'eupago-gateway-for-woocommerce');
    441                         $refund_note = esc_html__('Certifique-se de que os campos Client ID e Client Secret estão devidamente preenchidos para configurar a funcionalidade de reembolso.', 'eupago-gateway-for-woocommerce');
     367                        $refund_note = esc_html__('Para utilizar a funcionalidade de reembolso, os campos Client ID e Client Secret devem estar corretamente preenchidos.', 'eupago-gateway-for-woocommerce');
    442368                    } else if (get_locale() == 'es_ES') {
    443369                        $texto_traduzido = 'Cada cuenta tiene al menos un canal. Cada canal tiene una Clave API que identifica su cuenta de Eupago.';
    … …  
    463389                        $debug_log = esc_html__('Registro de depuración: ', 'eupago-gateway-for-woocommerce');
    464390                        $log_plugins = esc_html__('Registrar eventos del plugin y las respuestas a solicitudes dentro', 'eupago-gateway-for-woocommerce');
    465                         $refund_text = esc_html__('Reembolso:', 'eupago-gateway-for-woocommerce');
    466                         $user_text = esc_html__('Usuario: ', 'eupago-gateway-for-woocommerce');
    467                         $password_text = esc_html__('Contraseña', 'eupagp-gateway-for-woocommerce');
     391                        $refund_text = esc_html__('Reembolso', 'eupago-gateway-for-woocommerce');
    468392                        $notificacoes_sms = esc_html__('Notificaciones Biziq: ', 'eupago-gateway-for-woocommerce');
    469393                        $payment_on_hold = esc_html__('Envío de SMS con los detalles de pago:', 'eupago-gateway-for-woocommerce');
    … …  
    479403                        $environment = esc_html__('Entorno', 'eupago-gateway-for-woocommerce');
    480404                        $sync_channel = esc_html__('Sincronizar Información del Canal', 'eupago-gateway-for-woocommerce');
    481                         $refund_note = esc_html__('Asegúrese de que los campos Client ID y Client Secret estén correctamente completados para configurar la funcionalidad de reembolso.', 'eupago-gateway-for-woocommerce');
     405                        $refund_note = esc_html__('Para utilizar la funcionalidad de reembolso, los campos Client ID y Client Secret deben estar correctamente rellenados.', 'eupago-gateway-for-woocommerce');
    482406                    }
    483407                    ?><tbody>
    … …  
    575499
    576500                <h3><?php esc_html_e($refund_text); ?></h3>
    577                 <table class="form-table" role="presentation">
    578                     <tbody>
    579                         <tr>
    580                             <th scope="row"><label for="user_eupago"><?php esc_html_e($user_text); ?></label></th>
    581                             <td><input class="regular-text" type="text" name="user_eupago" value="<?php echo esc_attr(get_option('eupago_user')); ?>"></td>
    582                         </tr>
    583                         <tr>
    584                             <th scope="row"><label for="password_eupago"><?php esc_html_e($password_text); ?></label></th>
    585                             <td><input class="regular-text" type="password" name="password_eupago" value="<?php echo esc_attr(get_option('eupago_password')); ?>"></td>
    586                         </tr>
    587 
    588 
    589                     </tbody>
    590                 </table>
    591501                <p><?php esc_html_e($refund_note); ?></p>
    592502
    … …  
    697607
    698608    <script>
     609    // WordPress loads jQuery in noConflict mode, so $ is not global here.
     610    (function ($) {
    699611        // Função genérica para os pedidos da Eupago
    700612        function eupago_admin_ajax(action, data, successCallback) {
    … …  
    756668            });
    757669        });
     670    })(jQuery);
    758671    </script>
    759672
  • eupago-gateway-for-woocommerce/trunk/includes/views/html-admin-page.php

    r3267908 r3732472  
    1919   
    2020    <?php if ($this->id == 'eupago_cc') { ?>
    21       <?php if (!extension_loaded('soap')) { ?>
    22         <div class="eupago-soap-error">
    23           <p><?php esc_html_e('Requires SOAP protocol active on your server.', 'eupago-gateway-for-woocommerce'); ?></p>
    24         </div>
    25       <?php } ?>
    26 
    2721      <h4><?php echo esc_html($payment_method_text); ?></h4>
    2822      <p>
  • eupago-gateway-for-woocommerce/trunk/includes/views/order-meta-box-hpos.php

    r3605677 r3732472  
    11<?php
    2 $order = wc_get_order($post->ID);
    32$order_id = 0;
    43
    5 // 1. From query var (thank-you page)
    6 if ( isset( $_GET['order-received'] ) ) {
    7     $order_id = absint( $_GET['order-received'] );
     4// 1. From the object WooCommerce passes to the metabox: a WC_Order with HPOS,
     5//    a WP_Post without it. Reading $post->ID on a WC_Order triggers an
     6//    "Order properties should not be accessed directly" notice.
     7if (isset($post) && $post instanceof WC_Order) {
     8  $order_id = $post->get_id();
     9} elseif (isset($post->ID)) {
     10  $order_id = absint($post->ID);
     11// 2. From admin edit URL like ?id=1332
     12} elseif (isset($_GET['id'])) {
     13    $order_id = absint($_GET['id']);
     14// 3. From query var (thank-you page)
     15} elseif (isset($_GET['order-received'])) {
     16    $order_id = absint($_GET['order-received']);
     17}
    818
    9 // 2. From admin edit URL like ?id=1332
    10 } elseif ( isset( $_GET['id'] ) ) {
    11     $order_id = absint( $_GET['id'] );
     19$order = wc_get_order($order_id);
     20if (!$order) {
     21    return;
     22}
    1223
    13 // 3. If you already have a WC_Order object
    14 } elseif ( isset( $order ) && $order instanceof WC_Order ) {
    15     $order_id = $order->get_id();
    16 }
    17 $order = wc_get_order($order_id);
    1824$client = new WC_Eupago_API();
    1925$payment_method = version_compare(WC_VERSION, '3.0', '>=') ? $order->get_payment_method() : $order->payment_method;
    … …  
    2733    if (trim($order->get_meta('_eupago_multibanco_referencia')) == '') {
    2834      $pedido = $client->getReferenciaMB($order->get_id(), $order_total);
    29       if ($pedido->estado == 0) {
     35      if (is_object($pedido) && isset($pedido->estado) && $pedido->estado == 0) {
    3036        $order->update_meta_data('_eupago_multibanco_entidade', $pedido->entidade ?? '');
    3137        $order->update_meta_data('_eupago_multibanco_referencia', $pedido->referencia ?? '');
    … …  
    6167
    6268  case 'eupago_cc':
    63     if (trim($order->get_meta('_eupago_cc_referencia')) == '') {
    64       $lang = get_post_meta( $post->ID, 'wpml_language', true );
    65       if ( empty( $lang ) ) {
    66         $lang = 'pt-pt';
    67       }
    68       $logo='https://woo.eupago.pt/wp-content/plugins/eupago-gateway-for-woocommerce/includes/views/images/avatar.png';
    69       $return_url='https://eupago.pt';
    70       $comment='';
     69    if (trim($order->get_meta('_eupago_cc_referencia')) == '' && class_exists('WC_Eupago_Payment_Return')) {
     70      $lang = $order->get_meta('wpml_language');
     71      $lang = $lang ? strtoupper(substr($lang, 0, 2)) : 'PT';
    7172
    72       $pedido = $client->pedidoCC($order->get_id(), $order_total, $logo, $return_url, $lang, $comment);
    73       if ($pedido['status'] == 0) {
     73      // Same call shape as WC_Eupago_CC::process_payment() (REST v1.02, returns an array).
     74      $pedido = $client->pedidoCC(
     75        $order,
     76        $order_total,
     77        $order->get_checkout_order_received_url(),
     78        $lang,
     79        WC_Eupago_Payment_Return::get_url($order)
     80      );
     81      if (is_array($pedido) && isset($pedido['transactionStatus']) && strtolower($pedido['transactionStatus']) === 'success') {
     82        $order->update_meta_data('_eupago_cc_tid', $pedido['transactionID'] ?? '');
    7483        $order->update_meta_data('_eupago_cc_referencia', $pedido['reference'] ?? '');
    7584        $order->update_meta_data('_eupago_cc_link', $pedido['redirectUrl'] ?? '');
    … …  
    8493
    8594  case 'eupago_cofidispay':
    86     if (trim($order->get_meta('_eupago_cofidispay_referencia')) == '') {
    87       $cofidispay_vat_number = get_post_meta($post->ID, 'nif', true);
    88       update_post_meta($post->ID, '_eupago_cofidis_vat_number', $cofidispay_vat_number);
    89 
    90       $pedido = $client->cofidispay_create($post->ID);
    91       $pedido = json_decode($pedido);
    92       if ($pedido->transactionStatus == 'Success') {
    93         $order->update_meta_data('_eupago_cofidispay_referencia', $pedido->referencia ?? '');
    94         $order->update_meta_data('_eupago_cofidispay_redirectUrl', $pedido->redirectUrl ?? '');
    95         $order->save();
    96       }
    97     }
     95    // CofidisPay was discontinued: existing orders keep showing their payment
     96    // details, but no new payment request is ever created here.
    9897    echo '<img src="' . plugins_url('assets/images/cofidispay.png', dirname(dirname(__FILE__))) . '" /><br />';
    9998    echo '<b>' . esc_html(__('Reference', 'eupago-gateway-for-woocommerce')) . '</b>: ' . esc_html($order->get_meta('_eupago_cofidispay_referencia')) . '<br/>';
    … …  
    105104    if (trim($order->get_meta('_eupago_payshop_referencia')) == '') {
    106105      $pedido = $client->getReferenciaPS($order->get_id(), $order_total);
    107       if ($pedido->estado == 0) {
     106      if (is_object($pedido) && isset($pedido->estado) && $pedido->estado == 0) {
    108107        $order->update_meta_data('_eupago_payshop_referencia', $pedido->referencia ?? '');
    109108        $order->save();
    … …  
    117116  case 'eupago_bizum':
    118117    if (trim($order->get_meta('_eupago_bizum_referencia')) == '') {
    119       $pedido = $client->getReferenciaBizum($order->get_id(), $order_total);
    120       if ($pedido->estado == 0) {
    121         $order->update_meta_data('_eupago_bizum_referencia', $pedido->referencia ?? '');
    122         $order->update_meta_data('_eupago_bizum_redirect_url', $pedido->redirect_url ?? '');
     118      // Same call shape as WC_Eupago_Bizum::process_payment() (returns a JSON string).
     119      $pedido = json_decode($client->getReferenciaBizum(
     120        $order->get_id(),
     121        $order_total,
     122        $order->get_checkout_order_received_url(),
     123        $order->get_checkout_payment_url()
     124      ), true);
     125      if (is_array($pedido) && isset($pedido['transactionStatus']) && $pedido['transactionStatus'] === 'Success') {
     126        $order->update_meta_data('_eupago_bizum_referencia', $pedido['reference'] ?? '');
     127        $order->update_meta_data('_eupago_bizum_transactionID', $pedido['transactionID'] ?? '');
     128        $order->update_meta_data('_eupago_bizum_redirect_url', $pedido['redirectUrl'] ?? '');
    123129        $order->save();
    124130      }
    … …  
    168174    if (trim($order->get_meta('_eupago_pagaqui_reference')) == '') {
    169175      $pedido = $client->getReferenciaPagaqui($order, $order_total);
    170       if ($pedido->estado == 0) {
     176      if (is_object($pedido) && isset($pedido->estado) && $pedido->estado == 0) {
    171177        $order->update_meta_data('_eupago_pagaqui_reference', $pedido->referencia ?? '');
    172178        $order->save();
  • eupago-gateway-for-woocommerce/trunk/includes/views/order-meta-box.php

    r3605677 r3732472  
    2525        $eupagoMultibanco = $pedido = $client->getReferenciaMB($post->ID, $order_total, $duplicate_payments);
    2626      }
    27       if (extension_loaded('soap')) {
    28         if ( $eupagoMultibanco->estado != 0 ) {
    29           $error_message = $eupagoMultibanco->resposta;
    30           wc_add_notice( __('Payment error:', 'eupago-gateway-for-woocommerce') . $error_message, 'error' );
    31           return;
    32         }
    33       } else {
    34         $eupagoMultibanco_decode = json_decode($eupagoMultibanco, true);
    35         if ( $eupagoMultibanco_decode['estado'] != 0 ) {
    36           $error_message = $eupagoMultibanco_decode['resposta'];
    37           wc_add_notice( __('Payment error:', 'eupago-gateway-for-woocommerce') . $error_message, 'error' );
    38           return;
    39         }
     27      if ( ! is_object( $eupagoMultibanco ) || ! isset( $eupagoMultibanco->estado ) || $eupagoMultibanco->estado != 0 ) {
     28        $error_message = is_object( $eupagoMultibanco ) && isset( $eupagoMultibanco->resposta ) ? $eupagoMultibanco->resposta : '';
     29        wc_add_notice( __('Payment error:', 'eupago-gateway-for-woocommerce') . $error_message, 'error' );
     30        return;
    4031      }
    41       if (extension_loaded('soap')) {
    42         update_post_meta ($post->ID, '_eupago_multibanco_entidade', $eupagoMultibanco->entidade);
    43         update_post_meta ($post->ID, '_eupago_multibanco_referencia', $eupagoMultibanco->referencia);
    44       } else {
    45         $eupagoMultibanco_decode = json_decode($eupagoMultibanco, true);
    46         update_post_meta ($post->ID, '_eupago_multibanco_entidade', $eupagoMultibanco_decode['entidade']);
    47         update_post_meta ($post->ID, '_eupago_multibanco_referencia', $eupagoMultibanco_decode['referencia']);
    48       }
     32      update_post_meta ($post->ID, '_eupago_multibanco_entidade', $eupagoMultibanco->entidade ?? '');
     33      update_post_meta ($post->ID, '_eupago_multibanco_referencia', $eupagoMultibanco->referencia ?? '');
    4934    }
    5035  echo '<img src="' . plugins_url('assets/images/multibanco_banner.png', dirname(dirname(__FILE__))) . '" alt="' . esc_attr($payment_method_title) . '" title="' . esc_attr($payment_method_title) . '" /><br />';
    … …  
    9580
    9681  case 'eupago_cofidispay':
    97     if (trim(get_post_meta($post->ID, $payment_method_ref, true)) == 0) {
    98      
    99       $cofidispay_vat_number = get_post_meta($post->ID, 'nif', true);
    100       update_post_meta($post->ID, '_eupago_cofidis_vat_number', $cofidispay_vat_number);
    101       $pedido = $client->cofidispay_create($post->ID, $this->get_return_url($order));
    102       if ( $pedido->transactionStatus != 'Success' ) {
    103         wc_add_notice(__('Payment error:', 'eupago-for-woocommerce') . ' Ocorreu um erro com o pedido de pagamento', 'error');
    104         return;
    105       } else {
    106         update_post_meta($post->ID, '_eupago_cofidispay_transactionID', $pedido->transactionID);
    107         update_post_meta($post->ID, '_eupago_cofidispay_referencia', $pedido->reference);
    108         update_post_meta($post->ID, '_eupago_cofidispay_redirectUrl', $pedido->redirectUrl);
    109       }
    110     }
     82    // CofidisPay was discontinued: existing orders keep showing their payment
     83    // details, but no new payment request is ever created here.
    11184  echo '<img src="' . plugins_url('assets/images/cofidispay.png', dirname(dirname(__FILE__))) . '" alt="' . esc_attr($payment_method_title) . '" title="' . esc_attr($payment_method_title) . '" /><br />';
    11285  echo '<b>'.__('Reference', 'eupago-gateway-for-woocommerce').'</b>: '.chunk_split(trim(get_post_meta($post->ID, '_eupago_cofidispay_referencia', true)), 3, ' ').'<br/>';
    … …  
    11891    if (trim(get_post_meta($post->ID, $payment_method_ref, true)) == 0) {
    11992      $pedido = $client->getReferenciaPS($post->ID, $order_total);
    120       if ($pedido->estado == 0) {
     93      if (is_object($pedido) && isset($pedido->estado) && $pedido->estado == 0) {
    12194        update_post_meta($post->ID, '_eupago_payshop_referencia', $pedido->referencia);
    12295      }
    … …  
    194167    if (trim(get_post_meta($post->ID, $payment_method_ref, true)) == 0) {
    195168      $pedido = $client->getReferenciaPagaqui($order, $order_total);
    196       if ($pedido->estado == 0) {
     169      if (is_object($pedido) && isset($pedido->estado) && $pedido->estado == 0) {
    197170        update_post_meta($post->ID, '_eupago_pagaqui_reference', $pedido->referencia);
    198171      }
  • eupago-gateway-for-woocommerce/trunk/includes/woocommerce-blocks/applepay/ApplePayBlock.php

    r3338852 r3732472  
    5252        return [
    5353            'title'       => $this->settings['title'] ?? 'Apple Pay',
    54             'description' => $this->settings['description'] ?? 'Pague com Apple Pay via eupago',
    55             'instructions' => $this->settings['instructions'] ?? 'Pague com Apple Pay via eupago',
     54            'description' => $this->settings['description'] ?? '',
    5655            'supports'    => [ 'products' ],
    5756        ];
  • eupago-gateway-for-woocommerce/trunk/includes/woocommerce-blocks/applepay/src/index.js

    r3338852 r3732472  
    33const applePayLabel = window.wp.htmlEntities.decodeEntities(settings_applepay.title) || defaultLabel;
    44
    5 const applePayDescription = React.createElement(
    6   'p',
    7   null,
    8   window.wp.htmlEntities.decodeEntities(settings_applepay.description || 'Use Apple Pay')
    9 );
    10 
    115const ContentApplePay = (props) => {
    12   const decodedDescription = window.wp.htmlEntities.decodeEntities(
    13     settings_applepay.description || 'Use Apple Pay'
    14   );
    15 
    16   const decodedInstructions = window.wp.htmlEntities.decodeEntities(
    17     settings_applepay.instructions || ''
    18   );
    19 
    20   return React.createElement(
    21     'div',
    22     null,
    23     React.createElement('p', null, decodedDescription),
    24     decodedInstructions
    25       ? React.createElement('p', { style: { fontSize: '0.85em', color: '#555' } }, decodedInstructions)
    26       : null
    27   );
     6  const description = window.wp.htmlEntities.decodeEntities(settings_applepay.description || '');
     7  return description ? React.createElement('p', null, description) : null;
    288};
    299
    … …  
    3212  const icon = React.createElement('img', {
    3313    src: '/wp-content/plugins/eupago-gateway-for-woocommerce/includes/woocommerce-blocks/applepay/applepay_icon.png',
     14    // Size comes from assets/css/checkout.css (one rule for both checkouts).
    3415    style: {
    3516      display: 'inline',
    36       marginLeft: '5px',
     17      marginLeft: '6px',
    3718    },
    3819  });
  • eupago-gateway-for-woocommerce/trunk/includes/woocommerce-blocks/bizum/src/index.js

    r3249626 r3732472  
    2424    var icon = React.createElement('img', {
    2525        src: '/wp-content/plugins/eupago-gateway-for-woocommerce/includes/woocommerce-blocks/bizum/bizum_banner.png',
     26        // Size comes from assets/css/checkout.css (one rule for both checkouts).
    2627        style: {
    27             display: 'inline',
    28             marginLeft: '8px', // Adjust the value as needed
     28          display: 'inline',
     29          marginLeft: '6px',
    2930        },
    3031    });
  • eupago-gateway-for-woocommerce/trunk/includes/woocommerce-blocks/cc/src/index.js

    r3123345 r3732472  
    2525        var icon = React.createElement('img', {
    2626          src: '/wp-content/plugins/eupago-gateway-for-woocommerce/includes/woocommerce-blocks/cc/cc_icon.jpg',
     27          // Size comes from assets/css/checkout.css (one rule for both checkouts).
    2728          style: {
    28                 display: 'inline',
    29                 marginLeft: '5px', // Adjust the value as needed
     29            display: 'inline',
     30            marginLeft: '6px',
    3031          },
    3132        });
  • eupago-gateway-for-woocommerce/trunk/includes/woocommerce-blocks/floa/FloaBlock.php

    r3383861 r3732472  
    4949    public function is_active()
    5050    {
    51         return ! empty($this->settings['enabled']) && 'yes' === $this->settings['enabled'];
     51        // Without a registered gateway (e.g. terms not accepted yet after an
     52        // activation) there is nothing to pay with, so do not load the block.
     53        return $this->gateway !== null
     54            && ! empty($this->settings['enabled'])
     55            && 'yes' === $this->settings['enabled'];
    5256    }
    5357
    … …  
    129133            'installmentsText'  => $installmentsText,
    130134            'bannerUrl'         => esc_url( $banner_url ),
    131             'supports'          => array_filter( $this->gateway->supports, [ $this->gateway, 'supports' ] )
     135            'supports'          => $this->gateway ? array_filter( $this->gateway->supports, [ $this->gateway, 'supports' ] ) : []
    132136        ];
    133137    }
  • eupago-gateway-for-woocommerce/trunk/includes/woocommerce-blocks/floa/src/index.js

    r3383861 r3732472  
    6464    src: iconUrl,
    6565    alt: 'Floa',
     66    // Size comes from assets/css/checkout.css (one rule for both checkouts).
    6667    style: {
    67       display: 'inline-block',
    68       marginLeft: '5px',
    69       verticalAlign: 'middle',
    70       width: '40px', // Example width, adjust as needed
     68      display: 'inline',
     69      marginLeft: '6px',
    7170    },
    7271  });
  • eupago-gateway-for-woocommerce/trunk/includes/woocommerce-blocks/googlepay/GooglePayBlock.php

    r3338852 r3732472  
    5252        return [
    5353            'title'       => $this->settings['title'] ?? 'Google Pay',
    54             'description' => $this->settings['description'] ?? 'Pague com Google Pay via Eupago.',
    55             'instructions' => $this->settings['instructions'] ?? 'Pague com Google Pay via Eupago.',
     54            'description' => $this->settings['description'] ?? '',
    5655            'supports'    => [ 'products' ],
    5756        ];
  • eupago-gateway-for-woocommerce/trunk/includes/woocommerce-blocks/googlepay/src/index.js

    r3338852 r3732472  
    22const defaultLabel_googlepay = window.wp.i18n.__('Eupago Google Pay', 'eupago_googlepay');
    33const label_googlepay = window.wp.htmlEntities.decodeEntities(settings_googlepay.title) || defaultLabel_googlepay;
    4 var description = React.createElement('p', null, window.wp.htmlEntities.decodeEntities(settings_googlepay.description || 'Use Google Pay'));
    54
    65const ContentGooglePay = (props) => {
    7   const decodedDescription = window.wp.htmlEntities.decodeEntities(
    8     settings_googlepay.description || 'Use Google Pay'
    9   );
    10 
    11   const decodedInstructions = window.wp.htmlEntities.decodeEntities(
    12     settings_googlepay.instructions || ''
    13   );
    14 
    15   return React.createElement(
    16     'div',
    17     null,
    18     React.createElement('p', null, decodedDescription),
    19     decodedInstructions
    20       ? React.createElement('p', { style: { fontSize: '0.85em', color: '#555' } }, decodedInstructions)
    21       : null
    22   );
     6  const description = window.wp.htmlEntities.decodeEntities(settings_googlepay.description || '');
     7  return description ? React.createElement('p', null, description) : null;
    238};
    249
    2510const LabelGooglePay = (props) => {
    26   var icon = React.createElement('img', { 
     11  var icon = React.createElement('img', {
    2712    src: '/wp-content/plugins/eupago-gateway-for-woocommerce/includes/woocommerce-blocks/googlepay/googlepay_icon.png',
     13    // Size comes from assets/css/checkout.css (one rule for both checkouts).
    2814    style: {
    2915      display: 'inline',
    30       marginLeft: '5px',
     16      marginLeft: '6px',
    3117    },
    3218  });
  • eupago-gateway-for-woocommerce/trunk/includes/woocommerce-blocks/mbway/src/index.js

    r3464434 r3732472  
    146146        var icon = React.createElement('img', {
    147147                src: '/wp-content/plugins/eupago-gateway-for-woocommerce/includes/woocommerce-blocks/mbway/mbway_banner.png',
     148                // Size comes from assets/css/checkout.css (one rule for both checkouts).
    148149                style: {
    149                         display: 'inline',
    150                         marginLeft: '5px', // Adjust the value as needed
     150                  display: 'inline',
     151                  marginLeft: '6px',
    151152                },
    152153        });
  • eupago-gateway-for-woocommerce/trunk/includes/woocommerce-blocks/multibanco/src/index.js

    r3123345 r3732472  
    2929        var icon = React.createElement('img', {
    3030          src: '/wp-content/plugins/eupago-gateway-for-woocommerce/includes/woocommerce-blocks/multibanco/multibanco_banner.png',
     31          // Size comes from assets/css/checkout.css (one rule for both checkouts).
    3132          style: {
    32                 display: 'inline',
    33                 marginLeft: '5px', // Adjust the value as needed
     33            display: 'inline',
     34            marginLeft: '6px',
    3435          },
    3536        });
  • eupago-gateway-for-woocommerce/trunk/includes/woocommerce-blocks/pagaqui/src/index.js

    r3432579 r3732472  
    2828const LabelPagaqui = (props) => {
    2929        var icon = React.createElement('img', {
    30           src: '/wp-content/plugins/eupago-gateway-for-woocommerce/assets/images/pagaqui_banner.png',
     30          src: '/wp-content/plugins/eupago-gateway-for-woocommerce/assets/images/pagaqui_logo.png',
     31          alt: 'Pagaqui',
     32          // Size comes from assets/css/checkout.css (one rule for both checkouts).
    3133          style: {
    32                 display: 'inline',
    33                 marginLeft: '5px', // Adjust the value as needed
     34            display: 'inline',
     35            marginLeft: '6px',
    3436          },
    3537        });
  • eupago-gateway-for-woocommerce/trunk/includes/woocommerce-blocks/payshop/src/index.js

    r3123345 r3732472  
    2222    var icon = React.createElement('img', {
    2323        src: '/wp-content/plugins/eupago-gateway-for-woocommerce/includes/woocommerce-blocks/payshop/payshop_banner.png',
     24        // Size comes from assets/css/checkout.css (one rule for both checkouts).
    2425        style: {
    25             display: 'inline',
    26             marginLeft: '5px', // Adjust the value as needed
     26          display: 'inline',
     27          marginLeft: '6px',
    2728        },
    2829    });
  • eupago-gateway-for-woocommerce/trunk/includes/woocommerce-blocks/pix/src/index.js

    r3249626 r3732472  
    2424    var icon = React.createElement('img', {
    2525        src: '/wp-content/plugins/eupago-gateway-for-woocommerce/includes/woocommerce-blocks/pix/pix_banner.png',
     26        // Size comes from assets/css/checkout.css (one rule for both checkouts).
    2627        style: {
    27             display: 'inline',
    28             marginLeft: '8px', // Adjust the value as needed
     28          display: 'inline',
     29          marginLeft: '6px',
    2930        },
    3031    });
  • eupago-gateway-for-woocommerce/trunk/languages/eupago-gateway-for-woocommerce-es_ES.po

    r3605677 r3732472  
    8787msgid "Value:"
    8888msgstr "Importe:"
     89
     90
     91
     92#: includes/class-wc-eupago-payment-return.php
     93msgid "The customer left the Eupago payment page without paying. The cart was restored so they can try again."
     94msgstr "El cliente salió de la página de pago de Eupago sin pagar. El carrito se ha restaurado para que pueda intentarlo de nuevo."
     95
     96#: includes/class-wc-eupago-payment-return.php
     97msgid "The payment was not completed. Your cart has been restored so you can try again."
     98msgstr "El pago no se completó. El carrito se ha restaurado para que pueda intentarlo de nuevo."
     99
     100#: includes/class-wc-eupago-email-instructions.php
     101msgid "Payment method"
     102msgstr "Método de pago"
  • eupago-gateway-for-woocommerce/trunk/languages/eupago-gateway-for-woocommerce-pt_PT.po

    r3605677 r3732472  
    874874msgid "QR Code"
    875875msgstr "Código QR"
     876
     877
     878
     879#: includes/class-wc-eupago-payment-return.php
     880msgid "The customer left the Eupago payment page without paying. The cart was restored so they can try again."
     881msgstr "O cliente saiu da página de pagamento Eupago sem pagar. O carrinho foi reposto para poder tentar de novo."
     882
     883#: includes/class-wc-eupago-payment-return.php
     884msgid "The payment was not completed. Your cart has been restored so you can try again."
     885msgstr "O pagamento não foi concluído. O carrinho foi reposto para poder tentar de novo."
     886
     887#: includes/class-wc-eupago-email-instructions.php
     888msgid "Payment method"
     889msgstr "Método de pagamento"
  • eupago-gateway-for-woocommerce/trunk/languages/eupago-gateway-for-woocommerce.pot

    r3605677 r3732472  
    827827msgid "QR Code"
    828828msgstr ""
     829
     830
     831
     832#: includes/class-wc-eupago-payment-return.php
     833msgid "The customer left the Eupago payment page without paying. The cart was restored so they can try again."
     834msgstr ""
     835
     836#: includes/class-wc-eupago-payment-return.php
     837msgid "The payment was not completed. Your cart has been restored so you can try again."
     838msgstr ""
     839
     840#: includes/class-wc-eupago-email-instructions.php
     841msgid "Payment method"
     842msgstr ""
  • eupago-gateway-for-woocommerce/trunk/readme.txt

    r3611346 r3732472  
    11=== Eupago Gateway For Woocommerce ===
    22Contributors: eupagoip
    3 Tags: woocommerce, payment, gateway, multibanco, atm, debit card, credit card, bank, ecommerce, e-commerce, eupago, mb way, payshop, cofidispay, bizum, europix, pagamento, refund, reembolso
     3Tags: woocommerce, payment, gateway, multibanco, atm, debit card, credit card, bank, ecommerce, e-commerce, eupago, mb way, payshop, bizum, europix, pagamento, refund, reembolso
    44Author URI: https://www.eupago.pt/
    55Plugin URI:
    6 Requires at least: 4.4
    7 Tested up to: 6.8.3
    8 Requires PHP: 7.0
    9 Stable tag: 4.7.4
     6Requires at least: 6.0
     7Tested up to: 7.1
     8Requires PHP: 7.4
     9WC requires at least: 7.1
     10WC tested up to: 11.1.0
     11Stable tag: 4.7.5
    1012License: GPLv2 or later
    1113License URI: http://www.gnu.org/licenses/gpl-2.0.html
    1214
    1315
    14 Plugin para recebimento de pagamentos via Multibanco, PayShop, MB WAY, Cartão de Crédito, Paysafecard, CofidisPay, Bizum e EuroPix. O plugin permite ainda fazer reembolsos directamente pela plataforma do WooCommerce.
     16Plugin para recebimento de pagamentos via Multibanco, PayShop, MB WAY, Cartão de Crédito, Paysafecard, Bizum e EuroPix. O plugin permite ainda fazer reembolsos directamente pela plataforma do WooCommerce.
    1517
    1618== Description ==
    1719
    18 Testado até à versão 8.2.11 de PHP
     20Testado até à versão 8.3 de PHP
    1921
    2022= Features: =
    … …  
    2729* geração de um pedido de pagamento MB WAY. O pagamento é realizado na aplicação da MB WAY;
    2830* geração de pedido de pagamentos via Cartão de Crédito;
    29 * geração de pedido de pagamentos via CofidisPay (para valores estipulados pela Cofidis);
    3031* geração de pedido de pagamentos via Bizum;
    3132* geração de pedido de pagamentos via EuroPix;
    … …  
    4546
    4647== Changelog ==
     48= 4.7.5(17/09/2026) =
     49* Removed: CofidisPay payment method, discontinued by the provider. It is no longer offered on the checkout nor configurable; existing CofidisPay orders keep their payment details and callbacks
     50* Feature: WordPress 7.0 and 7.1 compatibility (tested up to WordPress 7.1 and WooCommerce 11.1)
     51* Fix: "Back" button and failed payments on Credit Card, Google Pay and Apple Pay return the customer to the checkout with the cart restored (order stays on-hold)
     52* Fix: Payment details block in the on-hold email now works for every payment method
     53* Fix: Google Pay and Apple Pay description was shown twice on the block checkout
     54* Fix: Remove third-party CDN jQuery from the settings page, use the one bundled with WordPress
     55* Fix: Callback no longer returns HTTP 500 when the Eupago settings page was never saved
     56* Fix: Refund request no longer fails with a fatal error on PHP 8 when the amount is empty or the order is invalid
     57* Fix: Saving the settings no longer performs a dead HTTP request and prints an error on screen
     58* Fix: Remove the unused Refund user and password fields.
     59* Fix: Remove PHP warnings on the order screen
     60* Fix: Telemetry headers (X-App-Source, X-App-Version, X-Runtime-Info) were never sent because they were built as associative array entries; API requests now carry them
     61* Fix: EuroPix SMS no longer falls through to the Google Pay case and sends the wrong payment details
     62* Security: webhook 2.0 callbacks are now signature-checked with the channel key whether or not the body is encrypted; callbacks are ignored for orders not paid through Eupago
     63* Fix: Apple Pay and Google Pay no longer crash at checkout when stock is reduced at order time
     64* Fix: Order screen (HPOS) no longer crashes when opening a Credit Card or Bizum order without a stored reference
     65* Fix: Block checkout no longer breaks with a server error when Multibanco, Payshop, Paysafecard or Pagaqui reject a payment; the error message is shown instead
     66* Fix: Block cart and checkout no longer crash when Floa is enabled but the terms have not been accepted yet
     67* Change: Credit Card requests now use the REST API v1.02
     68* Change: Multibanco, Payshop and Paysafecard now use the REST API first and only fall back to SOAP when the REST request cannot be completed; the SOAP extension is no longer required for Credit Card
     69* Change: Eupago no longer emails the customer directly (customer.notify = false), the shop's WooCommerce emails are used
     70* Improvement: New design for the payment details block in emails
     71* Improvement: Uniform payment method icons on both checkouts, new Pagaqui logo
     72
    4773= 4.7.4(17/07/2026) =
    4874* Fix: Remove invalid use statements that caused PHP warnings visible on client websites
  • eupago-gateway-for-woocommerce/trunk/templates/emails/html-instructions.php

    r3432579 r3732472  
    11<?php
    22/**
    3 * HTML email instructions.
    4 *
    5 * @author  WebAtual
    6 * @package eupago-gateway-for-woocommerce/Templates
    7 * @version 0.1
    8 */
     3 * HTML email instructions.
     4 *
     5 * Renders the "payment instructions" card inside WooCommerce's order emails.
     6 * The data (logo, rows, note) comes from WC_Eupago_Email_Instructions so every
     7 * payment method gets a block and the plain-text template shows the same thing.
     8 *
     9 * @package eupago-gateway-for-woocommerce/Templates
     10 * @version 0.2
     11 */
    912
    10 if ( ! defined( 'ABSPATH' ) ) {
    11   exit; // Exit if accessed directly.
     13if (!defined('ABSPATH')) {
     14    exit; // Exit if accessed directly.
    1215}
     16
     17$block = WC_Eupago_Email_Instructions::build($method, get_defined_vars());
     18
     19if (empty($block['rows'])) {
     20    return;
     21}
     22
     23if (!empty($instructions)) {
     24    echo wp_kses_post(wpautop(wptexturize($instructions)));
     25}
     26
     27$row_count = count($block['rows']);
     28$label_css = 'padding: 11px 0; font-size: 13px; line-height: 1.4; color: #6b7785; vertical-align: top;';
     29$value_css = 'padding: 11px 0 11px 16px; font-size: 15px; line-height: 1.4; color: #1f2933; font-weight: 600; text-align: right; vertical-align: top;';
     30$divider   = ' border-bottom: 1px solid #edf0f3;';
    1331?>
    14 
    15 <?php if ($method == 'eupago_multibanco') : ?>
    16   <?php echo wpautop( wptexturize( $instructions ) ) . PHP_EOL; ?>
    17   <table cellpadding="10" cellspacing="0" align="center" border="0" style="margin: auto; margin-top: 10px; margin-bottom: 10px; border-collapse: collapse; border: 1px solid #1465AA; border-radius: 4px !important; background-color: #FFFFFF;">
     32<table role="presentation" cellpadding="0" cellspacing="0" border="0" align="center" width="100%" style="max-width: 420px; margin: 18px auto; border-collapse: separate; border-spacing: 0; border: 1px solid #dfe3e8; border-radius: 10px; background-color: #ffffff; font-family: Helvetica, Arial, sans-serif; color: #1f2933;">
    1833    <tr>
    19       <td style="border: 1px solid #1465AA; border-top-right-radius: 4px !important; border-top-left-radius: 4px !important; text-align: center; color: #000000; font-weight: bold;" colspan="2">
    20         <?php _e('Payment instructions', 'eupago-gateway-for-woocommerce'); ?>
    21         <br/>
    22         <img src="<?php echo plugins_url('assets/images/multibanco_banner.png', dirname(dirname(__FILE__))); ?>" alt="<?php echo esc_attr($payment_name); ?>" title="<?php echo esc_attr($payment_name); ?>" style="margin-top: 10px;"/>
    23       </td>
     34        <td style="padding: 18px 20px 14px; text-align: center; background-color: #f7f9fb; border-bottom: 1px solid #e6eaef; border-radius: 10px 10px 0 0;">
     35            <div style="font-size: 11px; line-height: 1.4; font-weight: 700; letter-spacing: 1.5px; text-transform: uppercase; color: #6b7785;"><?php echo esc_html($block['title']); ?></div>
     36            <?php if ($block['logo'] !== '') : ?>
     37                <?php $logo_height = !empty($block['logo_height']) ? (int) $block['logo_height'] : 36; ?>
     38                <img src="<?php echo esc_url($block['logo']); ?>" alt="<?php echo esc_attr($payment_name); ?>" title="<?php echo esc_attr($payment_name); ?>" height="<?php echo $logo_height; ?>" style="height: <?php echo $logo_height; ?>px; width: auto; max-width: 180px; margin: 10px 0 0; display: inline-block; border: 0;" />
     39            <?php endif; ?>
     40        </td>
    2441    </tr>
    2542    <tr>
    26       <td style="border: 1px solid #1465AA; color: #000000;"><?php _e('Entity', 'eupago-gateway-for-woocommerce'); ?>:</td>
    27       <td style="border: 1px solid #1465AA; color: #000000; white-space: nowrap;"><?php echo esc_html($entidade); ?></td>
     43        <td style="padding: 4px 20px 6px;">
     44            <table role="presentation" cellpadding="0" cellspacing="0" border="0" width="100%" style="border-collapse: collapse;">
     45                <?php foreach ($block['rows'] as $index => $row) :
     46                    $last = ($index === $row_count - 1);
     47                    $tdl  = $label_css . ($last ? '' : $divider);
     48                    $tdv  = $value_css . ($last ? '' : $divider);
     49                ?>
     50                    <?php if ($row['type'] === 'image') : ?>
     51                        <tr>
     52                            <td colspan="2" style="padding: 14px 0; text-align: center;<?php echo $last ? '' : $divider; ?>">
     53                                <div style="font-size: 13px; color: #6b7785; margin-bottom: 8px;"><?php echo esc_html($row['label']); ?></div>
     54                                <img src="<?php echo esc_url($row['value']); ?>" alt="<?php echo esc_attr($row['label']); ?>" width="160" style="width: 160px; height: auto; margin: 0; display: inline-block; border: 0;" />
     55                            </td>
     56                        </tr>
     57                    <?php elseif ($row['type'] === 'code') : ?>
     58                        <tr>
     59                            <td colspan="2" style="padding: 11px 0;<?php echo $last ? '' : $divider; ?>">
     60                                <div style="font-size: 13px; color: #6b7785; margin-bottom: 6px;"><?php echo esc_html($row['label']); ?></div>
     61                                <div style="font-family: Menlo, Consolas, 'Courier New', monospace; font-size: 12px; line-height: 1.5; color: #1f2933; word-break: break-all; background-color: #f7f9fb; border: 1px solid #e6eaef; border-radius: 6px; padding: 8px 10px;"><?php echo esc_html($row['value']); ?></div>
     62                            </td>
     63                        </tr>
     64                    <?php elseif ($row['type'] === 'link') : ?>
     65                        <tr>
     66                            <td colspan="2" style="padding: 11px 0;<?php echo $last ? '' : $divider; ?>">
     67                                <div style="font-size: 13px; color: #6b7785; margin-bottom: 6px;"><?php echo esc_html($row['label']); ?></div>
     68                                <a href="<?php echo esc_url($row['value']); ?>" style="font-size: 13px; line-height: 1.5; color: #1465aa; word-break: break-all; text-decoration: underline;"><?php echo esc_html($row['value']); ?></a>
     69                            </td>
     70                        </tr>
     71                    <?php elseif ($row['type'] === 'html') : ?>
     72                        <tr>
     73                            <td style="<?php echo $tdl; ?>"><?php echo esc_html($row['label']); ?></td>
     74                            <td style="<?php echo $tdv; ?> white-space: nowrap;"><?php echo wp_kses_post($row['value']); ?></td>
     75                        </tr>
     76                    <?php else : ?>
     77                        <tr>
     78                            <td style="<?php echo $tdl; ?>"><?php echo esc_html($row['label']); ?></td>
     79                            <td style="<?php echo $tdv; ?> white-space: nowrap; letter-spacing: 0.3px;"><?php echo esc_html($row['value']); ?></td>
     80                        </tr>
     81                    <?php endif; ?>
     82                <?php endforeach; ?>
     83            </table>
     84        </td>
    2885    </tr>
    29     <tr>
    30       <td style="border: 1px solid #1465AA; color: #000000;"><?php _e('Reference', 'eupago-gateway-for-woocommerce'); ?>:</td>
    31       <td style="border: 1px solid #1465AA; color: #000000; white-space: nowrap;"><?php echo esc_html(chunk_split($referencia, 3, ' ')); ?></td>
    32     </tr>
    33     <tr>
    34       <td style="border: 1px solid #1465AA; color: #000000;"><?php _e('Value', 'eupago-gateway-for-woocommerce'); ?>:</td>
    35       <td style="border: 1px solid #1465AA; color: #000000; white-space: nowrap;"><?php echo esc_html($order_total); ?>€</td>
    36     </tr>
    37     <?php if ( isset( $data_fim ) && !empty( $data_fim ) ) : ?>
    38 <tr>
    39       <td style="border: 1px solid #1465AA; color: #000000;"><?php _e('Limit Date', 'eupago-gateway-for-woocommerce'); ?>:</td>
    40       <td style="border: 1px solid #1465AA; color: #000000; white-space: nowrap;"><?php echo esc_html($data_fim); ?></td>
    41     <tr>
     86    <?php if ($block['note'] !== '' || !empty($block['footer_logo'])) : ?>
     87        <tr>
     88            <td style="padding: 15px 5px 15px; text-align: center; background-color: #1f2933; border-radius: 0 0 10px 10px;">
     89                <?php if ($block['note'] !== '') : ?>
     90                    <div style="font-size: 12px; line-height: 1.5; color: #cbd2d9;<?php echo !empty($block['footer_logo']) ? ' margin-bottom: 8px;' : ''; ?>"><?php echo esc_html($block['note']); ?></div>
     91                <?php endif; ?>
     92                <?php if (!empty($block['footer_logo'])) : ?>
     93                    <a href="https://www.eupago.pt/"><img src="<?php echo esc_url($block['footer_logo']); ?>" alt="Eupago" title="Eupago" height="16" style="height: 16px; width: auto; margin: 0; display: inline-block; border: 0; vertical-align: middle;" /></a>
     94                <?php endif; ?>
     95            </td>
     96        </tr>
    4297    <?php endif; ?>
    43 
    44       <td style="font-size: x-small; border: 1px solid #1465AA; border-bottom-right-radius: 4px !important; border-bottom-left-radius: 4px !important; color: #000000; text-align: center;" colspan="2"><?php _e('The receipt issued by the ATM machine is a proof of payment. Keep it.', 'eupago-gateway-for-woocommerce'); ?></td>
    45     </tr>
    46   </table>
    47 <?php elseif ($method == 'eupago_payshop') : ?>
    48   <?php echo wp_kses_post(wpautop(wptexturize($instructions)) . PHP_EOL); ?>
    49   <table cellpadding="10" cellspacing="0" align="center" border="0" style="margin: auto; margin-top: 10px; margin-bottom: 10px; border-collapse: collapse; border: 1px solid #1465AA; border-radius: 4px !important; background-color: #FFFFFF;">
    50     <tr>
    51       <td style="border: 1px solid #1465AA; border-top-right-radius: 4px !important; border-top-left-radius: 4px !important; text-align: center; color: #000000; font-weight: bold;" colspan="2">
    52         <?php _e('Payment instructions', 'eupago-gateway-for-woocommerce'); ?>
    53         <br/>
    54         <img src="<?php echo plugins_url('assets/images/payshop_banner.png', dirname(dirname(__FILE__))); ?>" alt="<?php echo esc_attr($payment_name); ?>" title="<?php echo esc_attr($payment_name); ?>" style="margin-top: 10px;"/>
    55       </td>
    56     </tr>
    57     <tr>
    58       <td style="border: 1px solid #1465AA; color: #000000;"><?php _e('Reference', 'eupago-gateway-for-woocommerce'); ?>:</td>
    59       <td style="border: 1px solid #1465AA; color: #000000; white-space: nowrap;"><?php echo esc_html(chunk_split($referencia, 3, ' ')); ?></td>
    60     </tr>
    61     <tr>
    62       <td style="border: 1px solid #1465AA; color: #000000;"><?php _e('Value', 'eupago-gateway-for-woocommerce'); ?>:</td>
    63       <td style="border: 1px solid #1465AA; color: #000000; white-space: nowrap;"><?php echo esc_html($order_total); ?>€</td>
    64     </tr>
    65     <tr>
    66       <td style="font-size: x-small; border: 1px solid #1465AA; border-bottom-right-radius: 4px !important; border-bottom-left-radius: 4px !important; color: #000000; text-align: center;" colspan="2"><?php _e('The receipt issued by the ATM machine is a proof of payment. Keep it.', 'eupago-gateway-for-woocommerce'); ?></td>
    67     </tr>
    68   </table>
    69   <?php elseif ($method == 'eupago_pagaqui') : ?>
    70   <table cellpadding="10" cellspacing="0" align="center" border="0" style="margin: auto; margin-top: 10px; margin-bottom: 10px; border-collapse: collapse; border: 1px solid #1465AA; border-radius: 4px !important; background-color: #FFFFFF;">
    71     <tr>
    72       <td style="border: 1px solid #1465AA; border-top-right-radius: 4px !important; border-top-left-radius: 4px !important; text-align: center; color: #000000; font-weight: bold;" colspan="2">
    73         <?php _e('Payment instructions', 'eupago-gateway-for-woocommerce'); ?>
    74         <br/>
    75         <img src="<?php echo plugins_url('assets/images/pagaqui_banner.png', dirname(dirname(__FILE__))); ?>" alt="<?php echo esc_attr($payment_name); ?>" title="<?php echo esc_attr($payment_name); ?>" style="margin-top: 10px;"/>
    76       </td>
    77     </tr>
    78     <tr>
    79       <td style="border: 1px solid #1465AA; color: #000000;"><?php _e('Reference', 'eupago-gateway-for-woocommerce'); ?>:</td>
    80       <td style="border: 1px solid #1465AA; color: #000000; white-space: nowrap;"><?php echo esc_html(chunk_split($referencia, 3, ' ')); ?></td>
    81     </tr>
    82     <tr>
    83       <td style="border: 1px solid #1465AA; color: #000000;"><?php _e('Value', 'eupago-gateway-for-woocommerce'); ?>:</td>
    84       <td style="border: 1px solid #1465AA; color: #000000; white-space: nowrap;"><?php echo esc_html($order_total); ?>€</td>
    85     </tr>
    86     <tr>
    87       <td style="font-size: x-small; border: 1px solid #1465AA; border-bottom-right-radius: 4px !important; border-bottom-left-radius: 4px !important; color: #000000; text-align: center;" colspan="2"><?php _e('The receipt issued by Pagaqui serves as proof of payment. Please keep it.', 'eupago-gateway-for-woocommerce'); ?></td>
    88     </tr>
    89   </table>
    90 <?php elseif ($method == 'eupago_mbway') : ?>
    91   <table cellpadding="10" cellspacing="0" align="center" border="0" style="margin: auto; margin-top: 10px; margin-bottom: 10px; border-collapse: collapse; border: 1px solid #1465AA; border-radius: 4px !important; background-color: #FFFFFF;">
    92     <tr>
    93       <td style="border: 1px solid #1465AA; border-top-right-radius: 4px !important; border-top-left-radius: 4px !important; text-align: center; color: #000000; font-weight: bold;" colspan="2">
    94         <?php _e('Payment instructions', 'eupago-gateway-for-woocommerce'); ?>
    95         <br/>
    96         <img src="<?php echo plugins_url('assets/images/mbway_banner.png', dirname(dirname(__FILE__))); ?>" alt="<?php echo esc_attr($payment_name); ?>" title="<?php echo esc_attr($payment_name); ?>" style="margin-top: 10px;"/>
    97       </td>
    98     </tr>
    99     <tr>
    100       <td style="border: 1px solid #1465AA; color: #000000;"><?php _e('Entity', 'eupago-gateway-for-woocommerce'); ?>:</td>
    101       <td style="border: 1px solid #1465AA; color: #000000; white-space: nowrap;">EUPAGO.PT</td>
    102     </tr>
    103     <tr>
    104       <td style="border: 1px solid #1465AA; color: #000000;"><?php _e('Reference', 'eupago-gateway-for-woocommerce'); ?>:</td>
    105       <td style="border: 1px solid #1465AA; color: #000000; white-space: nowrap;"><?php echo esc_html(chunk_split($referencia, 3, ' ')); ?></td>
    106     </tr>
    107     <tr>
    108       <td style="border: 1px solid #1465AA; color: #000000;"><?php _e('Value', 'eupago-gateway-for-woocommerce'); ?>:</td>
    109       <td style="border: 1px solid #1465AA; color: #000000; white-space: nowrap;"><?php echo esc_html($order_total); ?>€</td>
    110     </tr>
    111     <tr>
    112       <td style="font-size: x-small; border: 1px solid #1465AA; border-bottom-right-radius: 4px !important; border-bottom-left-radius: 4px !important; color: #000000; text-align: center;" colspan="2"><?php _e('Accept this payment at your MBWAY mobile app.', 'eupago-gateway-for-woocommerce'); ?></td>
    113     </tr>
    114   </table>
    115   <?php elseif ($method == 'eupago_pix') : ?>
    116   <table cellpadding="10" cellspacing="0" align="center" border="0" style="margin: auto; margin-top: 10px; margin-bottom: 10px; border-collapse: collapse; border: 2px solid #e5e5e5; border-radius: 4px !important;">
    117     <tr>
    118       <td style="border: 2px solid #e5e5e5; border-top-right-radius: 4px !important; border-top-left-radius: 4px !important; text-align: center; font-weight: bold;" colspan="2">
    119         <?php _e('Payment instructions', 'eupago-gateway-for-woocommerce'); ?>
    120         <br/>
    121         <img src="<?php echo plugins_url('assets/images/pix_icon.png', dirname(dirname(__FILE__))); ?>" alt="<?php echo esc_attr($payment_name); ?>" title="<?php echo esc_attr($payment_name); ?>" style="margin-top: 10px;"/>
    122       </td>
    123     </tr>
    124     <tr>
    125       <td style="border: 2px solid #e5e5e5;"><?php _e('Reference', 'eupago-gateway-for-woocommerce'); ?>:</td>
    126       <td style="border: 2px solid #e5e5e5;"><?php echo esc_html($referencia); ?></td>
    127     </tr>
    128     <tr>
    129       <td style="border: 2px solid #e5e5e5;"><?php _e('Value', 'eupago-gateway-for-woocommerce'); ?>:</td>
    130       <td style="border: 2px solid #e5e5e5;"><?php echo esc_html($order_total); ?>€</td>
    131     </tr>
    132     <tr>
    133       <td style="border: 2px solid #e5e5e5;"><?php _e('QR Code', 'eupago-gateway-for-woocommerce'); ?>:</td>
    134       <td style="border: 2px solid #e5e5e5;"><img src="<?php echo esc_url($pixImage); ?>" alt="<?php echo esc_attr($payment_name); ?>" title="<?php echo esc_attr($payment_name); ?>"/></td>
    135     </tr>
    136     <tr>
    137       <td style="border: 2px solid #e5e5e5;"><?php _e('EuroPix Code', 'eupago-gateway-for-woocommerce'); ?>:</td>
    138       <td style="border: 2px solid #e5e5e5;"><?php echo esc_html($pixCode); ?></td>
    139     </tr>
    140   </table>
    141 <?php elseif ($method == 'eupago_bizum') : ?>
    142   <table cellpadding="10" cellspacing="0" align="center" border="0" style="margin: auto; margin-top: 10px; margin-bottom: 10px; border-collapse: collapse; border: 2px solid #e5e5e5; border-radius: 4px !important;">
    143     <tr>
    144       <td style="border: 2px solid #e5e5e5; border-top-right-radius: 4px !important; border-top-left-radius: 4px !important; text-align: center; font-weight: bold;" colspan="2">
    145         <?php _e('Payment instructions', 'eupago-gateway-for-woocommerce'); ?>
    146         <br/>
    147         <img src="<?php echo plugins_url('assets/images/bizum_icon.png', dirname(dirname(__FILE__))); ?>" alt="<?php echo esc_attr($payment_name); ?>" title="<?php echo esc_attr($payment_name); ?>" style="margin-top: 10px;"/>
    148       </td>
    149     </tr>
    150     <tr>
    151       <td style="border: 2px solid #e5e5e5;"><?php _e('Reference', 'eupago-gateway-for-woocommerce'); ?>:</td>
    152       <td style="border: 2px solid #e5e5e5;"><?php echo esc_html($referencia); ?></td>
    153     </tr>
    154     <tr>
    155       <td style="border: 2px solid #e5e5e5;"><?php _e('Value', 'eupago-gateway-for-woocommerce'); ?>:</td>
    156       <td style="border: 2px solid #e5e5e5;"><?php echo esc_html($order_total); ?>€</td>
    157     </tr>
    158     <tr>
    159       <td style="border: 2px solid #e5e5e5;"><?php _e('URL', 'eupago-gateway-for-woocommerce'); ?>:</td>
    160       <td style="border: 2px solid #e5e5e5;"><?php echo esc_url($redirect_url); ?></td>
    161     </tr>
    162   </table>
    163 <?php else :
    164   echo '<p><strong>' . __('Error getting payment details', 'eupago-gateway-for-woocommerce') . '</strong>';
    165 endif; ?>
     98</table>
  • eupago-gateway-for-woocommerce/trunk/templates/emails/plain-instructions.php

    r3432579 r3732472  
    1 html-<?php
     1<?php
    22/**
    3 * Plain email instructions.
    4 *
    5 * @author  WebAtual
    6 * @package eupago-gateway-for-woocommerce/Templates
    7 * @version 0.1
    8 */
     3 * Plain-text email instructions.
     4 *
     5 * Same data as the HTML card (WC_Eupago_Email_Instructions), one "label: value"
     6 * line per row.
     7 *
     8 * @package eupago-gateway-for-woocommerce/Templates
     9 * @version 0.2
     10 */
    911
    10 if ( ! defined( 'ABSPATH' ) ) {
    11   exit; // Exit if accessed directly.
     12if (!defined('ABSPATH')) {
     13    exit; // Exit if accessed directly.
    1214}
    13 ?>
    1415
    15 <?php
    16 if ($method == 'eupago_multibanco') :
    17   _e('Payment instructions', 'eupago-gateway-for-woocommerce');
    18   echo "\n";
    19   _e('Entity', 'eupago-gateway-for-woocommerce'); echo esc_html(': '); echo esc_html($entidade);
    20   echo "\n";
    21   _e('Reference', 'eupago-gateway-for-woocommerce'); echo esc_html(': '); echo esc_html(chunk_split($referencia, 3, ' '));
    22   echo "\n";
    23   _e('Value', 'eupago-gateway-for-woocommerce'); echo esc_html(': '); echo esc_html($order_total); echo esc_html('€');
    24   echo "\n";
    25   _e('The receipt issued by the ATM machine is a proof of payment. Keep it.', 'eupago-gateway-for-woocommerce');
    26 elseif ($method == 'eupago_payshop') :
    27   _e('Payment instructions', 'eupago-gateway-for-woocommerce');
    28   echo "\n";
    29   _e('Reference', 'eupago-gateway-for-woocommerce'); echo esc_html(': '); echo esc_html(chunk_split($referencia, 3, ' '));
    30   echo "\n";
    31   _e('Value', 'eupago-gateway-for-woocommerce'); echo esc_html(': '); echo esc_html($order_total); echo esc_html('€');
    32   echo "\n";
    33   _e('The receipt issued by the ATM machine is a proof of payment. Keep it.', 'eupago-gateway-for-woocommerce');
    34 elseif ($method == 'eupago_pagaqui') :
    35   _e('Payment instructions', 'eupago-gateway-for-woocommerce');
    36   echo "\n";
    37   _e('Reference', 'eupago-gateway-for-woocommerce'); echo esc_html(': '); echo esc_html(chunk_split($referencia, 3, ' '));
    38   echo "\n";
    39   _e('Value', 'eupago-gateway-for-woocommerce'); echo esc_html(': '); echo esc_html($order_total); echo esc_html('€');
    40   echo "\n";
    41   _e('The receipt issued by Pagaqui serves as proof of payment. Please keep it.', 'eupago-gateway-for-woocommerce');
    42 elseif ($method == 'eupago_mbway') :
    43   _e('Payment instructions', 'eupago-gateway-for-woocommerce');
    44   echo "\n";
    45   _e('Entity', 'eupago-gateway-for-woocommerce'); echo esc_html(': '); echo esc_html($entidade);
    46   echo "\n";
    47   _e('Reference', 'eupago-gateway-for-woocommerce'); echo esc_html(': '); echo esc_html(chunk_split($referencia, 3, ' '));
    48   echo "\n";
    49   _e('Value', 'eupago-gateway-for-woocommerce'); echo esc_html(': '); echo esc_html($order_total); echo esc_html('€');
    50   echo "\n";
    51   _e('Accept this payment at your MBWAY mobile app', 'eupago-gateway-for-woocommerce');
    52 elseif ($method == 'eupago_pix') :
    53   _e('Payment instructions', 'eupago-gateway-for-woocommerce');
    54   echo "\n";
    55   _e('Reference', 'eupago-gateway-for-woocommerce'); echo esc_html(': '); echo esc_html($referencia);
    56   echo "\n";
    57   _e('Value', 'eupago-gateway-for-woocommerce'); echo esc_html(': '); echo esc_html($order_total); echo esc_html('€');
    58   echo "\n";
    59   _e('QR Code', 'eupago-gateway-for-woocommerce'); echo esc_html(': '); echo esc_url($pixImage);
    60   echo "\n";
    61   _e('EuroPix Code', 'eupago-gateway-for-woocommerce'); echo esc_html(': '); echo esc_html($pixCode);
    62 elseif ($method == 'eupago_bizum') :
    63   _e('Payment instructions', 'eupago-gateway-for-woocommerce');
    64   echo "\n";
    65   _e('Reference', 'eupago-gateway-for-woocommerce'); echo esc_html(': '); echo esc_html($referencia);
    66   echo "\n";
    67   _e('Value', 'eupago-gateway-for-woocommerce'); echo esc_html(': '); echo esc_html($order_total); echo esc_html('€');
    68   echo "\n";
    69   _e('URL', 'eupago-gateway-for-woocommerce'); echo esc_html(': '); echo esc_html($redirect_url);
    70 else :
    71   _e('Error getting payment details', 'eupago-gateway-for-woocommerce');
    72 endif;
    73 ?>
     16$block = WC_Eupago_Email_Instructions::build($method, get_defined_vars());
     17
     18if (empty($block['rows'])) {
     19    return;
     20}
     21
     22if (!empty($instructions)) {
     23    echo esc_html(wp_strip_all_tags(wptexturize($instructions))) . "\n\n";
     24}
     25
     26echo esc_html(strtoupper($block['title'])) . "\n";
     27echo str_repeat('-', 40) . "\n";
     28
     29foreach ($block['rows'] as $row) {
     30    $value = $row['type'] === 'html' ? wp_strip_all_tags($row['value']) : $row['value'];
     31    echo esc_html($row['label']) . ': ' . esc_html(html_entity_decode($value, ENT_QUOTES, get_bloginfo('charset'))) . "\n";
     32}
     33
     34if ($block['note'] !== '') {
     35    echo "\n" . esc_html($block['note']) . "\n";
     36}
     37
     38echo "\n";
Note: See TracChangeset for help on using the changeset viewer.