Below is a differential between the unpatched vulnerable code and the patched update, for reference.
--- a/wordpress-simple-paypal-shopping-cart/includes/admin/wp_shopping_cart_menu_stripe_settings.php
+++ b/wordpress-simple-paypal-shopping-cart/includes/admin/wp_shopping_cart_menu_stripe_settings.php
@@ -153,9 +153,7 @@
<td>
<input type="checkbox" name="wpsc_auto_send_receipt_and_invoices" value="1" <?php esc_attr_e($wpsc_auto_send_receipt_and_invoices);?> />
<p class="description">
- <?php _e("When enabled the receipt or invoice generated by stripe will automatically be sent to the customer.", "wordpress-simple-paypal-shopping-cart")?>
- <br>
- <?php echo sprintf(__("First you will need to select %s in stripe dashboard %s.", "wordpress-simple-paypal-shopping-cart"), '<strong>Successful payments</strong>', '<a href="https://dashboard.stripe.com/settings/emails">Customer emails settings</a>') ?>
+ <?php echo sprintf(__("Complete the steps detailed in %s to activate the automated receipt feature.", "wordpress-simple-paypal-shopping-cart"), '<a href="https://www.tipsandtricks-hq.com/ecommerce/simple-cart-enabling-automated-stripe-receipts-and-invoices" target="_blank">this guide</a>') ?>
</p>
</td>
</tr>
--- a/wordpress-simple-paypal-shopping-cart/includes/wpsc-misc-checkout-ajax-handler.php
+++ b/wordpress-simple-paypal-shopping-cart/includes/wpsc-misc-checkout-ajax-handler.php
@@ -70,7 +70,10 @@
$symbol = __( '$', 'wordpress-simple-paypal-shopping-cart' );
}
- $query_args = array( 'simple_cart_stripe_ipn' => '1', 'ref_id' => $wspsc_cart->get_cart_id() );
+ $client_reference_id = $cart_id; // TODO: old code. need to remove
+ $csid = "{CHECKOUT_SESSION_ID}"; // NOTE: Stripe replaces the {CHECKOUT_SESSION_ID} with actual session id before redirecting to this url.
+
+ $query_args = array( 'simple_cart_stripe_ipn' => '1', 'ref_id' => $client_reference_id, 'csid' => $csid );
$stripe_ipn_url = add_query_arg( $query_args, WP_CART_SITE_URL );
wpsc_load_stripe_lib();
@@ -81,10 +84,11 @@
StripeStripe::setApiVersion( "2024-06-20" );
$opts = array(
- 'client_reference_id' => $cart_id,
+ 'client_reference_id' => $client_reference_id,
'billing_address_collection' => $force_collect_address ? 'required' : 'auto',
'mode' => 'payment',
- 'success_url' => $stripe_ipn_url
+ 'success_url' => $stripe_ipn_url,
+ 'metadata' => array(),
);
/*
--- a/wordpress-simple-paypal-shopping-cart/includes/wpsc-misc-functions.php
+++ b/wordpress-simple-paypal-shopping-cart/includes/wpsc-misc-functions.php
@@ -21,12 +21,6 @@
wpc_handle_paypal_ipn();
exit;
}
- else if(isset($_REQUEST["simple_cart_stripe_ipn"]))
- {
- include_once( WP_CART_PATH . 'stripe.php');
- wpc_handle_stripe_ipn();
- exit;
- }
}
if (is_admin()) {
add_action('admin_init', 'wp_cart_add_tinymce_button');
@@ -43,6 +37,15 @@
}
}
+function wpsc_handle_wp_tasks() {
+ if(isset($_REQUEST["simple_cart_stripe_ipn"]))
+ {
+ include_once( WP_CART_PATH . 'stripe.php');
+ wpc_handle_stripe_ipn();
+ exit;
+ }
+}
+
/*
* This function gets called when admin_init hook is executed
*/
--- a/wordpress-simple-paypal-shopping-cart/stripe.php
+++ b/wordpress-simple-paypal-shopping-cart/stripe.php
@@ -16,6 +16,8 @@
private $cart_id = 0;
+ private $csid = '';
+
function __construct() {
$this->secret_key = get_option("wpspc_stripe_live_secret_key");
$this->last_error = '';
@@ -303,11 +305,11 @@
return true;
}
-
function validate_ipn() {
// $this->order_id = isset($_GET["ref_id"])?$_GET["ref_id"]:0; // TODO: old code. need to remove
- $this->cart_id = isset($_GET["ref_id"])?$_GET["ref_id"]:0;
+ $this->cart_id = isset($_GET["ref_id"]) ? sanitize_text_field($_GET["ref_id"]): 0;
+ $this->csid = isset($_GET["csid"]) ? sanitize_text_field($_GET["csid"]): 0;
//IPN validation check
if ($this->validate_ipn_using_client_reference_id()) {
@@ -324,24 +326,7 @@
try {
StripeStripe::setApiKey( $this->secret_key );
- $events = StripeEvent::all(
- array(
- 'type' => 'checkout.session.completed',
- 'created' => array(
- 'gte' => time() - 60 * 60,
- ),
- )
- );
-
- $sess = false;
-
- foreach ( $events->autoPagingIterator() as $event ) {
- $session = $event->data->object;
- if ( isset( $session->client_reference_id ) && $session->client_reference_id === $this->cart_id ) {
- $sess = $session;
- break;
- }
- }
+ $sess = $this->retrieve_checkout_session_object();
if ( false === $sess ) {
// Can't find session.
@@ -380,6 +365,46 @@
return true;
}
+ /**
+ * Retrieves the stripe checkout session.
+ *
+ * It might fail in the first attempt if there is any race condition.
+ * So to prevent that, this method contains a recursion mechanism with max_attempt count.
+ */
+ private function retrieve_checkout_session_object() {
+ // TODO: old code. need to remove
+ //$events = StripeEvent::all(
+ // array(
+ // 'type' => 'checkout.session.completed',
+ // 'created' => array(
+ // 'gte' => time() - 60 * 60,
+ // ),
+ // )
+ //);
+ //
+ //foreach ( $events->autoPagingIterator() as $event ) {
+ // $session = $event->data->object;
+ // if ( isset( $session->client_reference_id ) && $session->client_reference_id === $this->cart_id ) {
+ // $sess = $session;
+ // break;
+ // }
+ //}
+
+ $checkout_session_id = $this->csid;
+ $sess = StripeCheckoutSession::retrieve($checkout_session_id);
+
+ if (!empty($sess)){
+ return $sess;
+ }
+
+ wpsc_log_payment_debug('The checkout session could not be retrieved. Retrying to retrieve checkout session...', false);
+ sleep(2);
+
+ $sess = StripeCheckoutSession::retrieve($checkout_session_id);
+
+ return $sess;
+ }
+
function create_ipn_from_stripe( $pi_object, $additional_data = array() ) {
//converting the payment intent object to array
@@ -603,6 +628,9 @@
wpsc_log_debug_array($array_to_write, $success, $end);
}
+ public function get_cart_id() {
+ return $this->cart_id;
+ }
}
// Start of Stripe IPN handling (script execution)
@@ -642,7 +670,7 @@
$return_url = WP_CART_SITE_URL . '/';
}
- $cart_id = isset($_GET["ref_id"])?$_GET["ref_id"]:'';
+ $cart_id = $ipn_handler_instance->get_cart_id();
$redirect_url = add_query_arg( 'cart_id', $cart_id, $return_url );
$redirect_url = add_query_arg('_wpnonce', wp_create_nonce('wpsc_thank_you_nonce_action'), $redirect_url);
if ( ! headers_sent() ) {
--- a/wordpress-simple-paypal-shopping-cart/wp_shopping_cart.php
+++ b/wordpress-simple-paypal-shopping-cart/wp_shopping_cart.php
@@ -2,7 +2,7 @@
/*
Plugin Name: Simple Shopping Cart
-Version: 5.2.4
+Version: 5.2.5
Plugin URI: https://www.tipsandtricks-hq.com/wordpress-simple-paypal-shopping-cart-plugin-768
Author: Tips and Tricks HQ, Ruhul Amin, mra13
Author URI: https://www.tipsandtricks-hq.com/
@@ -17,7 +17,7 @@
exit;
}
-define( 'WP_CART_VERSION', '5.2.4' );
+define( 'WP_CART_VERSION', '5.2.5' );
define( 'WP_CART_FOLDER', dirname( plugin_basename( __FILE__ ) ) );
define( 'WP_CART_PATH', plugin_dir_path( __FILE__ ) );
define( 'WP_CART_URL', plugins_url( '', __FILE__ ) );
@@ -850,3 +850,5 @@
add_action( 'wp_enqueue_scripts', 'wpsc_front_side_enqueue_scripts' );
add_action( 'admin_enqueue_scripts', 'wpsc_admin_side_enqueue_scripts' );
add_action( 'admin_print_styles', 'wpsc_admin_side_styles' );
+
+add_action( 'wp', 'wpsc_handle_wp_tasks' );
No newline at end of file
--- a/wordpress-simple-paypal-shopping-cart/wp_shopping_cart_shortcodes.php
+++ b/wordpress-simple-paypal-shopping-cart/wp_shopping_cart_shortcodes.php
@@ -114,6 +114,8 @@
$thumb_alt = $name;
}
+ $description = sanitize_text_field($description);
+
$price = wpsc_strip_char_from_price_amount($price);
$shipping = wpsc_strip_char_from_price_amount($shipping);
@@ -137,17 +139,17 @@
<div class="wp_cart_product_display_box_wrapper">
<div class="wp_cart_product_display_box">
<div class="wp_cart_product_thumbnail">
- <?php echo $thumbnail_code; ?>
+ <?php echo wp_kses_post($thumbnail_code); ?>
</div>
<div class="wp_cart_product_display_bottom">
<div class="wp_cart_product_name">
- <?php echo $name ?>
+ <?php echo esc_attr($name) ?>
</div>
<div class="wp_cart_product_description">
- <?php echo $description ?>
+ <?php echo wp_kses_post($description) ?>
</div>
<div class="wp_cart_product_price">
- <?php echo $formatted_price ?>
+ <?php echo wp_kses_post($formatted_price) ?>
</div>
<div class="wp_cart_product_button">
<?php echo $button_code ?>