From 5c718fc9aaeaa78b1029e0993fcbf3583cb53d00 Mon Sep 17 00:00:00 2001 From: Peter Wilson Date: Wed, 13 Aug 2025 15:24:40 +1000 Subject: [PATCH] Prevent cancelling tokens on ITN replays. --- includes/class-wc-gateway-payfast.php | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/includes/class-wc-gateway-payfast.php b/includes/class-wc-gateway-payfast.php index a3bce9f..f7b6591 100644 --- a/includes/class-wc-gateway-payfast.php +++ b/includes/class-wc-gateway-payfast.php @@ -707,14 +707,29 @@ public function handle_itn_request( $data ) { $subscription = wcs_get_subscription( $order_id ); if ( ! empty( $subscription ) && ! empty( $token ) ) { $old_token = $this->_get_subscription_token( $subscription ); - // Cancel old subscription token of subscription if we have it. - if ( ! empty( $old_token ) ) { + + /* + * Cancel old subscription token. + * + * Cancels an old subscription token if it is defined and differs from + * the new token. The check for the same token is to account for replayed + * ITN requests as a result of an HTTP timeout or network issues returning + * the success response to the Payfast gateway. + */ + if ( + ! empty( $old_token ) + && $old_token !== $token + ) { $this->cancel_subscription_listener( $subscription ); } - // Set new subscription token on subscription. - $this->_set_subscription_token( $token, $subscription ); - $this->log( 'Payfast token updated on Subcription: ' . $order_id ); + // Set new subscription token on subscription if not an ITN replay. + if ( $old_token !== $token ) { + $this->_set_subscription_token( $token, $subscription ); + $this->log( 'Payfast token updated on Subscription: ' . $order_id ); + } else { + $this->log( 'Possible ITN replay detected for Payfast token update on Subscription: ' . $order_id ); + } } } return;