--- a/bluesnap-payment-gateway-for-woocommerce/assets/js/payment-methods/bluesnap-ach/index.asset.php
+++ b/bluesnap-payment-gateway-for-woocommerce/assets/js/payment-methods/bluesnap-ach/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'wp-components', 'wp-data', 'wp-element', 'wp-html-entities', 'wp-i18n'), 'version' => '6b1ea1df02f1f985a388');
+<?php return array('dependencies' => array('react', 'wp-components', 'wp-data', 'wp-element', 'wp-html-entities', 'wp-i18n'), 'version' => 'bbafe4cbd313f00e98bd');
--- a/bluesnap-payment-gateway-for-woocommerce/bluesnap-for-woocommerce.php
+++ b/bluesnap-payment-gateway-for-woocommerce/bluesnap-for-woocommerce.php
@@ -16,15 +16,15 @@
* Plugin Name: BlueSnap Payment Gateway for WooCommerce
* Plugin URI: https://bluesnap.com/
* Description: WooCommerce gateway module to accept credit/debit card payments worldwide
- * Version: 3.4.0
+ * Version: 3.4.1
* Author: SAU/CAL
* Author URI: https://saucal.com
* License: GPL-2.0+
* License URI: http://www.gnu.org/licenses/gpl-2.0.txt
* Text Domain: woocommerce-bluesnap-gateway
* Domain Path: /i18n/languages
- * Tested up to: 6.8.3
- * WC tested up to: 9.4
+ * Tested up to: 6.9.1
+ * WC tested up to: 10.5
* WC requires at least: 8.5.0
* Requires Plugins: woocommerce
*/
--- a/bluesnap-payment-gateway-for-woocommerce/class-woocommerce-bluesnap-gateway.php
+++ b/bluesnap-payment-gateway-for-woocommerce/class-woocommerce-bluesnap-gateway.php
@@ -8,6 +8,10 @@
* @version 1.3.5
*/
+if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+}
+
if ( ! class_exists( 'Woocommerce_Bluesnap_Gateway' ) ) :
final class Woocommerce_Bluesnap_Gateway {
@@ -18,7 +22,7 @@
* @var string
*/
- public $version = '3.4.0';
+ public $version = '3.4.1';
public $db_version = '2.5.0';
--- a/bluesnap-payment-gateway-for-woocommerce/includes/admin/bluesnap-settings.php
+++ b/bluesnap-payment-gateway-for-woocommerce/includes/admin/bluesnap-settings.php
@@ -25,11 +25,6 @@
'default' => 'yes',
'desc_tip' => true,
),
- 'ipn' => array(
- 'title' => __( 'Webhook (IPN) configuration', 'woocommerce-bluesnap-gateway' ),
- 'type' => 'title',
- 'description' => __( 'You must add the following webhook endpoint to your Bluesnap account <a href="https://support.bluesnap.com/docs/ipn-setup" target="_blank">here</a>: ', 'woocommerce-bluesnap-gateway' ) . add_query_arg( 'wc-api', 'bluesnap', trailingslashit( get_home_url() ) ),
- ),
'title' => array(
'title' => __( 'Title', 'woocommerce-bluesnap-gateway' ),
'type' => 'text',
@@ -69,6 +64,17 @@
'default' => '',
'desc_tip' => true,
),
+ 'ipn' => array(
+ 'title' => __( 'Webhook (IPN) configuration', 'woocommerce-bluesnap-gateway' ),
+ 'type' => 'title',
+ 'description' => __( 'You must add the following Webhook Endpoint to your BlueSnap account <a href="https://support.bluesnap.com/docs/ipn-setup#step-2-enabling-webhooks-in-bluesnap" target="_blank">here</a>: <strong>', 'woocommerce-bluesnap-gateway' ) . add_query_arg( 'wc-api', 'bluesnap', trailingslashit( get_home_url() ) ) . '</strong><br/>' . __( 'In <strong>Security Header</strong>, toggle <strong>Add Security Header</strong> to the right to generate a unique encryption key that you can use to validate your webhook.', 'woocommerce-bluesnap-gateway' ),
+ ),
+ 'webhook_secret' => array(
+ 'title' => __( 'Security Header', 'woocommerce-bluesnap-gateway' ),
+ 'type' => 'password',
+ 'description' => __( 'Enter the security header secret generated for the Endpoint. Webhook notifications will be rejected until this is configured.', 'woocommerce-bluesnap-gateway' ),
+ 'default' => '',
+ ),
'capture_charge' => array(
'title' => __( 'Capture', 'woocommerce-bluesnap-gateway' ),
'type' => 'checkbox',
--- a/bluesnap-payment-gateway-for-woocommerce/includes/admin/class-wc-bluesnap-admin.php
+++ b/bluesnap-payment-gateway-for-woocommerce/includes/admin/class-wc-bluesnap-admin.php
@@ -119,6 +119,26 @@
</div>
<?php
}
+
+ $webhook_secret = WC_Bluesnap()->get_option( 'webhook_secret' );
+ if ( empty( $webhook_secret ) ) {
+ $settings_url = admin_url( 'admin.php?page=wc-settings&tab=checkout§ion=bluesnap#woocommerce_bluesnap_ipn' );
+ ?>
+ <div class="notice notice-warning">
+ <p>
+ <?php
+ echo wp_kses_post(
+ sprintf(
+ /* translators: %s: URL to plugin settings page */
+ __( '<strong>BlueSnap Payment Gateway:</strong> Webhook notifications will be rejected until the Security Header is configured. Go to the <strong>Merchant Portal > Settings > Webhook Settings</strong>, enable the Security Header for the Endpoint and paste the generated secret in the <a href="%s">Security Header setting</a>.', 'woocommerce-bluesnap-gateway' ),
+ esc_url( $settings_url )
+ )
+ );
+ ?>
+ </p>
+ </div>
+ <?php
+ }
}
--- a/bluesnap-payment-gateway-for-woocommerce/includes/admin/views/admin-display.php
+++ b/bluesnap-payment-gateway-for-woocommerce/includes/admin/views/admin-display.php
@@ -11,6 +11,9 @@
* @package Woocommerce_Bluesnap_Gateway
* @subpackage Woocommerce_Bluesnap_Gateway/Admin/views
*/
+if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+}
?>
<!-- This file should primarily consist of HTML with a little bit of PHP. -->
--- a/bluesnap-payment-gateway-for-woocommerce/includes/class-wc-bluesnap-api.php
+++ b/bluesnap-payment-gateway-for-woocommerce/includes/class-wc-bluesnap-api.php
@@ -528,7 +528,7 @@
protected static function handle_error_response( $error ) {
$error_message = ( is_wp_error( $error ) ) ? $error->get_error_message() : $error['body'];
WC_Bluesnap_Logger::log( $error_message, 'error' );
- throw new WC_Bluesnap_API_Exception( $error );
+ throw new WC_Bluesnap_API_Exception( $error ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
}
/**
--- a/bluesnap-payment-gateway-for-woocommerce/includes/class-wc-bluesnap-ipn-webhooks.php
+++ b/bluesnap-payment-gateway-for-woocommerce/includes/class-wc-bluesnap-ipn-webhooks.php
@@ -18,31 +18,6 @@
*/
class WC_Bluesnap_IPN_Webhooks {
- /**
- * https://support.bluesnap.com/docs/ipn-setup#section-1-setting-up-your-server-to-receive-ipns
- * Prod IP whitelist.
- */
- const BLUESNAP_PROD_IPS = array(
- '38.99.111.60',
- '38.99.111.160',
- '141.226.140.100',
- '141.226.141.100',
- '141.226.142.100',
- '141.226.143.100',
- );
-
- /**
- * Sandbox IP Whitelist.
- */
- const BLUESNAP_SANDBOX_IPS = array(
- '38.99.111.50',
- '38.99.111.150',
- '141.226.140.200',
- '141.226.141.200',
- '141.226.142.200',
- '141.226.143.200',
- );
-
private $debounce_key;
/**
@@ -90,7 +65,7 @@
WC_Bluesnap_Logger::log( $message, 'error', 'ipn' );
$this->ipn_cleanup();
status_header( $status_code );
- die( $response ); // WPCS: XSS ok
+ die( $response ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
exit;
}
@@ -243,7 +218,7 @@
if ( is_wp_error( $refund ) ) {
/* translators: %1$s reason */
- throw new Exception( sprintf( __( 'wc_create_refund failed: %1$s.', 'woocommerce-bluesnap-gateway' ), $refund->get_error_message() ) );
+ throw new Exception( sprintf( __( 'wc_create_refund failed: %1$s.', 'woocommerce-bluesnap-gateway' ), $refund->get_error_message() ) ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
}
}
@@ -317,7 +292,6 @@
} else {
throw new Exception( esc_html__( 'No Payment ID detected in Charge Failure Webhook.', 'woocommerce-bluesnap-gateway' ), 400 );
}
-
}
@@ -354,13 +328,14 @@
'Order with ID #%1$s found, but the expected transaction ID is missing.',
'woocommerce-bluesnap-gateway'
),
- $order->get_id(),
+ $order->get_id(), // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
),
400
);
}
if ( $body['referenceNumber'] !== $order->get_transaction_id() ) {
+ // phpcs:disable WordPress.Security.EscapeOutput.ExceptionNotEscaped
throw new Exception(
sprintf(
esc_html__(
@@ -373,6 +348,7 @@
),
400
);
+ // phpcs:enable WordPress.Security.EscapeOutput.ExceptionNotEscaped
}
return $order;
@@ -404,48 +380,52 @@
}
/**
- * Validate incoming request against IP and User-Agent.
+ * Validate incoming webhook request using HMAC-SHA256 signature verification.
*
- * @return bool
+ * @param array $headers Request headers.
+ * @param string $raw_body Raw request body.
+ *
+ * @return array Parsed body.
+ * @throws Exception When validation fails.
*/
private function validate_source( $headers, $raw_body ) {
- if ( empty( $headers ) || empty( $raw_body ) ) {
+ if ( empty( $headers ) || ! is_array( $headers ) || empty( $raw_body ) ) {
throw new Exception( esc_html__( 'Empty request', 'woocommerce-bluesnap-gateway' ), 400 );
- return false;
}
- $remote_ip = WC_Geolocation::get_ip_address();
+ if ( isset( $headers['User-Agent'] ) && 'BlueSnap' !== $headers['User-Agent'] ) {
+ throw new Exception( esc_html__( 'Invalid User-Agent', 'woocommerce-bluesnap-gateway' ), 400 );
+ }
- if ( ! in_array( $remote_ip, $this->get_ip_whitelist() ) ) {
- throw new Exception( esc_html__( 'Invalid Webhook source', 'woocommerce-bluesnap-gateway' ), 401 );
- return false;
+ $secret = WC_Bluesnap()->get_option( 'webhook_secret' );
+ if ( empty( $secret ) ) {
+ throw new Exception( esc_html__( 'Webhook secret is not configured. Please add your BlueSnap Security Header secret in the plugin settings.', 'woocommerce-bluesnap-gateway' ), 403 );
}
- if ( isset( $headers['User-Agent'] ) && 'BlueSnap' !== $headers['User-Agent'] ) {
- throw new Exception( esc_html__( 'Invalid User-Agent', 'woocommerce-bluesnap-gateway' ), 400 );
- return false;
+ $headers = array_change_key_case( $headers, CASE_LOWER );
+ $signature = isset( $headers['bls-signature'] ) ? $headers['bls-signature'] : '';
+ $timestamp = isset( $headers['bls-ipn-timestamp'] ) ? $headers['bls-ipn-timestamp'] : '';
+
+ if ( empty( $signature ) || empty( $timestamp ) ) {
+ throw new Exception( esc_html__( 'Missing security headers. Ensure the Security Header is enabled in your BlueSnap dashboard.', 'woocommerce-bluesnap-gateway' ), 401 );
+ }
+
+ $expected_signature = hash_hmac( 'sha256', $timestamp . $raw_body, $secret );
+ if ( ! hash_equals( $expected_signature, $signature ) ) {
+ throw new Exception( esc_html__( 'Invalid webhook signature', 'woocommerce-bluesnap-gateway' ), 401 );
}
$body = array();
parse_str( $raw_body, $body );
if ( empty( $body['transactionType'] ) ) {
- throw new Exception( esc_html__( 'transactionType not set', 'woocommerce-bluesnap-gateway' ), 401 );
- return false;
+ throw new Exception( esc_html__( 'transactionType not set', 'woocommerce-bluesnap-gateway' ), 400 );
}
return $body;
}
/**
- * @return array
- */
- private function get_ip_whitelist() {
- $is_sandbox = ( 'yes' === WC_Bluesnap()->get_option( 'testmode' ) ) ? true : false;
- return ( $is_sandbox ) ? self::BLUESNAP_SANDBOX_IPS : self::BLUESNAP_PROD_IPS;
- }
-
- /**
* getallheaders is only available for apache, we need a fallback in case of nginx or others,
* http://php.net/manual/es/function.getallheaders.php
* @return array|false
@@ -468,7 +448,7 @@
/**
* Do not allow the same IPN request to be processed concurrently.
*
- * @param array $raw_body
+ * @param string $raw_body
* @return void
*
* @throws Exception
@@ -478,7 +458,7 @@
$this->debounce_key = 'bluesnap_ipn_debounce_' . md5( $raw_body );
if ( false !== get_transient( $this->debounce_key ) ) {
- throw new Exception( __( 'Webhook request repeated too soon or previous request exited abnormally.', 'woocommerce-bluesnap-gateway' ) );
+ throw new Exception( __( 'Webhook request repeated too soon or previous request exited abnormally.', 'woocommerce-bluesnap-gateway' ) ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
}
set_transient( $this->debounce_key, time(), 10 * MINUTE_IN_SECONDS );
@@ -494,7 +474,6 @@
delete_transient( $this->debounce_key );
}
}
-
}
new WC_Bluesnap_IPN_Webhooks();
--- a/bluesnap-payment-gateway-for-woocommerce/includes/payment-methods/class-wc-bluesnap-gateway.php
+++ b/bluesnap-payment-gateway-for-woocommerce/includes/payment-methods/class-wc-bluesnap-gateway.php
@@ -470,7 +470,7 @@
$this->render_fraud_kount_iframe();
if ( ! empty( $this->description ) ) {
- echo apply_filters( 'wc_bluesnap_description', wpautop( wp_kses_post( $this->description ) ), $this->id ); // WPCS: XSS ok, sanitization ok.
+ echo apply_filters( 'wc_bluesnap_description', wpautop( wp_kses_post( $this->description ) ), $this->id ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
$this->maybe_load_tokenization_scripts();
--- a/bluesnap-payment-gateway-for-woocommerce/includes/trait-wc-bluesnap-addons.php
+++ b/bluesnap-payment-gateway-for-woocommerce/includes/trait-wc-bluesnap-addons.php
@@ -1,5 +1,7 @@
<?php
-
+if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+}
trait WC_Bluesnap_Gateway_Addons_Trait {
/**
@@ -919,7 +921,7 @@
$error_msg = __( 'This Subscription is pending. Please try again after the initial payment has been processed.', 'woocommerce-bluesnap-gateway' );
}
- throw new Exception( $error_msg );
+ throw new Exception( $error_msg ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
} else {
return $ret;
}
--- a/bluesnap-payment-gateway-for-woocommerce/includes/woo-blocks/abstract-wc-bluesnap-block-compat.php
+++ b/bluesnap-payment-gateway-for-woocommerce/includes/woo-blocks/abstract-wc-bluesnap-block-compat.php
@@ -7,6 +7,10 @@
* @since 3.3.0
*/
+if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+}
+
use AutomatticWooCommerceBlocksPaymentsIntegrationsAbstractPaymentMethodType;
/**
--- a/bluesnap-payment-gateway-for-woocommerce/includes/woocommerce-bluesnap-gateway-template-functions.php
+++ b/bluesnap-payment-gateway-for-woocommerce/includes/woocommerce-bluesnap-gateway-template-functions.php
@@ -65,7 +65,7 @@
$located = woocommerce_bluesnap_gateway_locate_template( $template_name, $template_path, $default_path );
if ( ! file_exists( $located ) ) {
- _doing_it_wrong( __FUNCTION__, sprintf( '<code>%s</code> does not exist.', $located ), '1.0.0' ); // WPCS: XSS ok.
+ _doing_it_wrong( __FUNCTION__, sprintf( '<code>%s</code> does not exist.', $located ), '1.0.0' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
return;
}
--- a/bluesnap-payment-gateway-for-woocommerce/templates/emails/plain/admin-chargeback-order.php
+++ b/bluesnap-payment-gateway-for-woocommerce/templates/emails/plain/admin-chargeback-order.php
@@ -15,7 +15,7 @@
exit;
}
-echo '= ' . $email_heading . " =nn"; // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped
+echo '= ' . $email_heading . " =nn"; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
/* translators: %1$s: Order number. %2$s: Customer full name. */
echo sprintf( esc_html__( 'Payment for order #%1$s from %2$s has received a chargeback.', 'woocommerce-bluesnap-gateway' ), esc_html( $order->get_order_number() ), esc_html( $order->get_formatted_billing_full_name() ) ) . "nn";
--- a/bluesnap-payment-gateway-for-woocommerce/templates/fraud-kount-iframe.php
+++ b/bluesnap-payment-gateway-for-woocommerce/templates/fraud-kount-iframe.php
@@ -11,6 +11,11 @@
* @package Woocommerce_Bluesnap_Gateway
* @subpackage Woocommerce_Bluesnap_Gateway/public/partials
*/
+
+if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+}
+
?>
<div style='position: relative;'>
<iframe width='1' height='1' frameborder='0' scrolling='no' src='<?php echo esc_attr( $domain ); ?>/servlet/logo.htm?s=<?php echo esc_attr( $fraud_id ); ?>&d=<?php echo esc_attr( $developer_id ); ?>' style='position: absolute;'>
--- a/bluesnap-payment-gateway-for-woocommerce/templates/multicurrency-selector.php
+++ b/bluesnap-payment-gateway-for-woocommerce/templates/multicurrency-selector.php
@@ -11,6 +11,11 @@
* @package Woocommerce_Bluesnap_Gateway
* @subpackage Woocommerce_Bluesnap_Gateway/public/partials
*/
+
+if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+}
+
?>
--- a/bluesnap-payment-gateway-for-woocommerce/templates/multicurrency-wrapper.php
+++ b/bluesnap-payment-gateway-for-woocommerce/templates/multicurrency-wrapper.php
@@ -11,8 +11,13 @@
* @package Woocommerce_Bluesnap_Gateway
* @subpackage Woocommerce_Bluesnap_Gateway/public/partials
*/
+
+if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+}
+
?>
<span class="bluesnap-multicurrency-html <?php echo ( $hide ) ? 'currency-hide' : 'currency-show'; ?>" currency="<?php echo esc_attr( $currency ); ?>">
- <?php echo $html; // WPCS: XSS ok, sanitization ok. ?>
+ <?php echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
</span>
--- a/bluesnap-payment-gateway-for-woocommerce/templates/payment-fields-bluesnap-ach.php
+++ b/bluesnap-payment-gateway-for-woocommerce/templates/payment-fields-bluesnap-ach.php
@@ -1,5 +1,4 @@
<?php
-
/**
* Provide a public-facing view for bluesnap checkout.
*
@@ -9,6 +8,11 @@
* @package Woocommerce_Bluesnap_Gateway
* @subpackage Woocommerce_Bluesnap_Gateway/public/partials
*/
+
+if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+}
+
?>
<fieldset id="wc-<?php echo esc_attr( $gateway->id ); ?>-ach-form" class="wc-ach-payment-form wc-payment-form">
--- a/bluesnap-payment-gateway-for-woocommerce/templates/payment-fields-bluesnap.php
+++ b/bluesnap-payment-gateway-for-woocommerce/templates/payment-fields-bluesnap.php
@@ -9,6 +9,11 @@
* @package Woocommerce_Bluesnap_Gateway
* @subpackage Woocommerce_Bluesnap_Gateway/public/partials
*/
+
+if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+}
+
?>
<script type="text/javascript">
--- a/bluesnap-payment-gateway-for-woocommerce/templates/public-display.php
+++ b/bluesnap-payment-gateway-for-woocommerce/templates/public-display.php
@@ -11,6 +11,11 @@
* @package Woocommerce_Bluesnap_Gateway
* @subpackage Woocommerce_Bluesnap_Gateway/public/partials
*/
+
+if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+}
+
?>
<!-- This file should primarily consist of HTML with a little bit of PHP. -->
--- a/bluesnap-payment-gateway-for-woocommerce/vendor/composer/installed.php
+++ b/bluesnap-payment-gateway-for-woocommerce/vendor/composer/installed.php
@@ -3,7 +3,7 @@
'name' => 'bluesnap/bluesnap-payment-gateway-for-woocommerce',
'pretty_version' => 'dev-master',
'version' => 'dev-master',
- 'reference' => 'c9dd653059d89c33f056a43f22b7bb561b881b87',
+ 'reference' => '43d9788c7889e071b447d5332e17c152c35cad11',
'type' => 'wordpress-plugin',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
@@ -13,7 +13,7 @@
'bluesnap/bluesnap-payment-gateway-for-woocommerce' => array(
'pretty_version' => 'dev-master',
'version' => 'dev-master',
- 'reference' => 'c9dd653059d89c33f056a43f22b7bb561b881b87',
+ 'reference' => '43d9788c7889e071b447d5332e17c152c35cad11',
'type' => 'wordpress-plugin',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),