Skip to content

Commit

Permalink
Merge branch 'develop' into fix/duplicate-emails
Browse files Browse the repository at this point in the history
  • Loading branch information
Mayisha authored Jan 9, 2025
2 parents 4fd608b + 7bd8824 commit d2e7ca1
Show file tree
Hide file tree
Showing 15 changed files with 259 additions and 121 deletions.
2 changes: 2 additions & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* Fix - Return to the correct page when redirect-based payment method fails.
* Fix - Show default recipient for Payment Authentication Requested email.
* Fix - Correctly handles IPP failed payments webhook calls by extracting the order ID from the payment intent metadata.
* Dev - Fix lint issues raised by WordPress code standards.
* Fix - Fix ECE crash in classic cart and checkout pages for non-English language sites.
* Fix - Correctly handles UK postcodes redacted by Apple Pay.
* Tweak - Avoid re-sending Processing Order customer email when merchant wins dispute.
Expand Down Expand Up @@ -32,6 +33,7 @@
* Dev - Add a GitHub Action workflow to run QIT E2E Integrations tests.
* Fix - Check billing interval and period to set in mandate options.
* Fix - Check order currency on pay for order page to display supported payment methods.
* Update - Migrate payment request settings data to express checkout settings data.
* Update - Make the new Stripe Express Checkout Element enabled by default in all accounts.
* Fix - Duplicate emails when enabling the gateway.

Expand Down
2 changes: 1 addition & 1 deletion includes/abstracts/abstract-wc-stripe-payment-gateway.php
Original file line number Diff line number Diff line change
Expand Up @@ -1408,7 +1408,7 @@ public function get_level3_data_from_order( $order ) {
$currency = $order->get_currency();

$stripe_line_items = array_map(
function( $item ) use ( $currency ) {
function ( $item ) use ( $currency ) {
if ( is_a( $item, 'WC_Order_Item_Product' ) ) {
$product_id = $item->get_variation_id()
? $item->get_variation_id()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,6 @@ private function update_is_debug_log_enabled( WP_REST_Request $request ) {
}

$this->gateway->update_option( 'logging', $is_debug_log_enabled ? 'yes' : 'no' );

}

/**
Expand Down
4 changes: 3 additions & 1 deletion includes/admin/stripe-eps-settings.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<?php
// This file is the body of WC_Gateway_Stripe_Eps::init_form_fields().

if ( ! defined( 'ABSPATH' ) ) {
exit;
}
Expand Down Expand Up @@ -39,7 +41,7 @@
'title' => __( 'Webhook Endpoints', 'woocommerce-gateway-stripe' ),
'type' => 'title',
/* translators: webhook URL */
'description' => $this->display_admin_settings_webhook_description(),
'description' => $this->display_admin_settings_webhook_description(), // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable
],
]
);
4 changes: 3 additions & 1 deletion includes/admin/stripe-p24-settings.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<?php
// This file is the body of WC_Gateway_Stripe_P24::init_form_fields().

if ( ! defined( 'ABSPATH' ) ) {
exit;
}
Expand Down Expand Up @@ -39,7 +41,7 @@
'title' => __( 'Webhook Endpoints', 'woocommerce-gateway-stripe' ),
'type' => 'title',
/* translators: webhook URL */
'description' => $this->display_admin_settings_webhook_description(),
'description' => $this->display_admin_settings_webhook_description(), // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable
],
]
);
4 changes: 3 additions & 1 deletion includes/admin/stripe-sepa-settings.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<?php
// This file is the body of WC_Gateway_Stripe_Sepa::init_form_fields().

if ( ! defined( 'ABSPATH' ) ) {
exit;
}
Expand Down Expand Up @@ -43,7 +45,7 @@
'title' => __( 'Webhook Endpoints', 'woocommerce-gateway-stripe' ),
'type' => 'title',
/* translators: webhook URL */
'description' => $this->display_admin_settings_webhook_description(),
'description' => $this->display_admin_settings_webhook_description(), // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable
],
]
);
2 changes: 1 addition & 1 deletion includes/class-wc-stripe-intent-controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -1101,7 +1101,7 @@ public function confirm_change_payment_from_setup_intent_ajax() {
throw new WC_Stripe_Exception( 'subscription_not_found', __( "We're not able to process this subscription change payment request payment. Please try again later.", 'woocommerce-gateway-stripe' ) );
}

$setup_intent_id = isset( $_POST['intent_id'] ) ? wc_clean( wp_unslash( $_POST['intent_id'] ) ) : null;
$setup_intent_id = ( isset( $_POST['intent_id'] ) && is_string( $_POST['intent_id'] ) ) ? sanitize_text_field( wp_unslash( $_POST['intent_id'] ) ) : null;

if ( empty( $setup_intent_id ) ) {
throw new WC_Stripe_Exception( 'intent_not_found', __( "We're not able to process this subscription change payment request payment. Please try again later.", 'woocommerce-gateway-stripe' ) );
Expand Down
1 change: 0 additions & 1 deletion includes/class-wc-stripe-webhook-handler.php
Original file line number Diff line number Diff line change
Expand Up @@ -1200,7 +1200,6 @@ protected function handle_deferred_payment_intent_succeeded( $order, $intent_id

do_action( 'wc_gateway_stripe_process_payment', $charge, $order );
$this->process_response( $charge, $order );

}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,16 +90,19 @@ public function maybe_update_subscription_source( WC_Subscription $subscription
*/
private function get_subscription_to_migrate( $subscription_id ) {
if ( ! WC_Stripe_Feature_Flags::is_upe_checkout_enabled() ) {
// phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
throw new \Exception( sprintf( '---- Skipping migration of subscription #%d. The Legacy experience is enabled.', $subscription_id ) );
}

if ( ! class_exists( 'WC_Subscriptions' ) ) {
// phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
throw new \Exception( sprintf( '---- Skipping migration of subscription #%d. The WooCommerce Subscriptions extension is not active.', $subscription_id ) );
}

$subscription = wcs_get_subscription( $subscription_id );

if ( ! $subscription ) {
// phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
throw new \Exception( sprintf( '---- Skipping migration of subscription #%d. Subscription not found.', $subscription_id ) );
}

Expand All @@ -121,6 +124,7 @@ private function set_subscription_updated_payment_method( WC_Subscription $subsc

// Bail out if the subscription is already using a pm_.
if ( 0 !== strpos( $source_id, 'src_' ) ) {
// phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
throw new \Exception( sprintf( 'The subscription is not using a Stripe Source for renewals.', $subscription->get_id() ) );
}

Expand All @@ -129,11 +133,13 @@ private function set_subscription_updated_payment_method( WC_Subscription $subsc

// Bail out, if the source object isn't expected to be migrated. eg Card sources are not migrated.
if ( isset( $source_object->type ) && 'card' === $source_object->type ) {
// phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
throw new \Exception( sprintf( 'Skipping migration of Source for subscription #%d. Source is a card.', $subscription->get_id() ) );
}

// Bail out if the src_ hasn't been migrated to pm_ yet.
if ( ! isset( $source_object->metadata->migrated_payment_method ) ) {
// phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
throw new \Exception( sprintf( 'The Source has not been migrated to PaymentMethods on the Stripe account.', $subscription->get_id() ) );
}

Expand All @@ -153,6 +159,7 @@ private function set_subscription_updated_payment_method( WC_Subscription $subsc
private function set_subscription_updated_payment_gateway_id( WC_Subscription $subscription ) {
// The subscription is not using the legacy SEPA gateway ID.
if ( WC_Gateway_Stripe_Sepa::ID !== $subscription->get_payment_method() ) {
// phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
throw new \Exception( sprintf( '---- Skipping migration of subscription #%d. Subscription is not using the legacy SEPA payment method.', $subscription->get_id() ) );
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php
/**
* Class Migrate_Payment_Request_Data_To_Express_Checkout_Data
*/

defined( 'ABSPATH' ) || exit;

/**
* Class Migrate_Payment_Request_Data_To_Express_Checkout_Data
*
* Migrates Payment Request settings data to Express Checkout settings data.
*
* @since 9.1.0
*/
class Migrate_Payment_Request_Data_To_Express_Checkout_Data {
/**
* Migrate_Payment_Request_Data_To_Express_Checkout_Data constructor.
*/
public function __construct() {
add_action( 'woocommerce_stripe_updated', [ $this, 'maybe_migrate' ] );
}

/**
* Only execute the migration if not applied yet.
*/
public function maybe_migrate() {
$stripe_gateway = $this->get_gateway();

$express_checkout_enabled = $stripe_gateway->get_option( 'express_checkout' );

if ( empty( $express_checkout_enabled ) ) {
$this->migrate();
}
}

/**
* Copies over Payment Request settings data to Express Checkout settings data.
*/
private function migrate() {
$stripe_gateway = $this->get_gateway();

$payment_request_enabled = $stripe_gateway->get_option( 'payment_request', 'no' );
$payment_request_button_type = $stripe_gateway->get_option( 'payment_request_button_type', 'default' );
$payment_request_button_theme = $stripe_gateway->get_option( 'payment_request_button_theme', 'dark' );
$payment_request_button_size = $stripe_gateway->get_option( 'payment_request_button_size', 'default' );
$payment_request_button_locations = $stripe_gateway->get_option( 'payment_request_button_locations', [ 'checkout' ] );

$stripe_gateway->update_option( 'express_checkout', $payment_request_enabled );
$stripe_gateway->update_option( 'express_checkout_button_type', $payment_request_button_type );
$stripe_gateway->update_option( 'express_checkout_button_theme', $payment_request_button_theme );
$stripe_gateway->update_option( 'express_checkout_button_size', $payment_request_button_size );
$stripe_gateway->update_option( 'express_checkout_button_locations', $payment_request_button_locations );
}

/**
* Returns the main Stripe payment gateways.
*
* @return WC_Stripe_Payment_Gateway
*/
public function get_gateway() {
return woocommerce_gateway_stripe()->get_main_stripe_gateway();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public function is_account_creation_possible() {
* @return string
*/
public function get_button_type() {
return isset( $this->stripe_settings['payment_request_button_type'] ) ? $this->stripe_settings['payment_request_button_type'] : 'default';
return isset( $this->stripe_settings['express_checkout_button_type'] ) ? $this->stripe_settings['express_checkout_button_type'] : 'default';
}

/**
Expand All @@ -94,7 +94,7 @@ public function get_button_type() {
* @return string
*/
public function get_button_theme() {
return isset( $this->stripe_settings['payment_request_button_theme'] ) ? $this->stripe_settings['payment_request_button_theme'] : 'dark';
return isset( $this->stripe_settings['express_checkout_button_theme'] ) ? $this->stripe_settings['express_checkout_button_theme'] : 'dark';
}

/**
Expand All @@ -103,7 +103,7 @@ public function get_button_theme() {
* @return string
*/
public function get_button_height() {
$height = isset( $this->stripe_settings['payment_request_button_size'] ) ? $this->stripe_settings['payment_request_button_size'] : 'default';
$height = isset( $this->stripe_settings['express_checkout_button_size'] ) ? $this->stripe_settings['express_checkout_button_size'] : 'default';
if ( 'small' === $height ) {
return '40';
}
Expand All @@ -121,7 +121,7 @@ public function get_button_height() {
* @return string
*/
public function get_button_radius() {
$height = isset( $this->stripe_settings['payment_request_button_size'] ) ? $this->stripe_settings['payment_request_button_size'] : 'default';
$height = isset( $this->stripe_settings['express_checkout_button_size'] ) ? $this->stripe_settings['express_checkout_button_size'] : 'default';
if ( 'small' === $height ) {
return '2';
}
Expand Down Expand Up @@ -1329,18 +1329,18 @@ public function get_login_confirmation_settings() {
*/
public function get_button_locations() {
// If the locations have not been set return the default setting.
if ( ! isset( $this->stripe_settings['payment_request_button_locations'] ) ) {
if ( ! isset( $this->stripe_settings['express_checkout_button_locations'] ) ) {
return [ 'product', 'cart' ];
}

// If all locations are removed through the settings UI the location config will be set to
// an empty string "". If that's the case (and if the settings are not an array for any
// other reason) we should return an empty array.
if ( ! is_array( $this->stripe_settings['payment_request_button_locations'] ) ) {
if ( ! is_array( $this->stripe_settings['express_checkout_button_locations'] ) ) {
return [];
}

return $this->stripe_settings['payment_request_button_locations'];
return $this->stripe_settings['express_checkout_button_locations'];
}

/**
Expand All @@ -1351,7 +1351,7 @@ public function get_button_locations() {
* @return boolean
*/
public function is_express_checkout_enabled() {
return isset( $this->stripe_settings['payment_request'] ) && 'yes' === $this->stripe_settings['payment_request'];
return isset( $this->stripe_settings['express_checkout'] ) && 'yes' === $this->stripe_settings['express_checkout'];
}

/**
Expand Down
39 changes: 16 additions & 23 deletions includes/payment-tokens/class-wc-stripe-payment-tokens.php
Original file line number Diff line number Diff line change
Expand Up @@ -192,22 +192,19 @@ public function woocommerce_get_customer_payment_tokens_legacy( $tokens, $custom
} else {
unset( $stored_tokens[ $source->id ] );
}
} elseif ( ! isset( $stored_tokens[ $source->id ] ) && WC_Stripe_Payment_Methods::CARD === $source->object ) {
$token = new WC_Payment_Token_CC();
$token->set_token( $source->id );
$token->set_gateway_id( WC_Gateway_Stripe::ID );
$token->set_card_type( strtolower( $source->brand ) );
$token->set_last4( $source->last4 );
$token->set_expiry_month( $source->exp_month );
$token->set_expiry_year( $source->exp_year );
$token->set_user_id( $customer_id );
$token->save();
$tokens[ $token->get_id() ] = $token;
} else {
if ( ! isset( $stored_tokens[ $source->id ] ) && WC_Stripe_Payment_Methods::CARD === $source->object ) {
$token = new WC_Stripe_Payment_Token_CC();
$token->set_token( $source->id );
$token->set_gateway_id( WC_Gateway_Stripe::ID );
$token->set_card_type( strtolower( $source->brand ) );
$token->set_last4( $source->last4 );
$token->set_expiry_month( $source->exp_month );
$token->set_expiry_year( $source->exp_year );
$token->set_user_id( $customer_id );
$token->set_fingerprint( $source->fingerprint );
$token->save();
$tokens[ $token->get_id() ] = $token;
} else {
unset( $stored_tokens[ $source->id ] );
}
unset( $stored_tokens[ $source->id ] );
}
}
}
Expand Down Expand Up @@ -446,10 +443,8 @@ public function woocommerce_payment_token_deleted( $token_id, $token ) {
}

$stripe_customer->detach_payment_method( $token->get_token() );
} else {
if ( WC_Gateway_Stripe::ID === $token->get_gateway_id() || WC_Gateway_Stripe_Sepa::ID === $token->get_gateway_id() ) {
$stripe_customer->delete_source( $token->get_token() );
}
} elseif ( WC_Gateway_Stripe::ID === $token->get_gateway_id() || WC_Gateway_Stripe_Sepa::ID === $token->get_gateway_id() ) {
$stripe_customer->delete_source( $token->get_token() );
}
} catch ( WC_Stripe_Exception $e ) {
WC_Stripe_Logger::log( 'Error: ' . $e->getMessage() );
Expand All @@ -471,10 +466,8 @@ public function woocommerce_payment_token_set_default( $token_id ) {
if ( WC_Stripe_UPE_Payment_Gateway::ID === $token->get_gateway_id() ) {
$stripe_customer->set_default_payment_method( $token->get_token() );
}
} else {
if ( WC_Gateway_Stripe::ID === $token->get_gateway_id() || WC_Gateway_Stripe_Sepa::ID === $token->get_gateway_id() ) {
$stripe_customer->set_default_source( $token->get_token() );
}
} elseif ( WC_Gateway_Stripe::ID === $token->get_gateway_id() || WC_Gateway_Stripe_Sepa::ID === $token->get_gateway_id() ) {
$stripe_customer->set_default_source( $token->get_token() );
}
} catch ( WC_Stripe_Exception $e ) {
WC_Stripe_Logger::log( 'Error: ' . $e->getMessage() );
Expand Down
2 changes: 2 additions & 0 deletions readme.txt
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ If you get stuck, you can ask for help in the [Plugin Forum](https://wordpress.o
* Fix - Return to the correct page when redirect-based payment method fails.
* Fix - Show default recipient for Payment Authentication Requested email.
* Fix - Correctly handles IPP failed payments webhook calls by extracting the order ID from the payment intent metadata.
* Dev - Fix lint issues raised by WordPress code standards.
* Fix - Fix ECE crash in classic cart and checkout pages for non-English language sites.
* Fix - Correctly handles UK postcodes redacted by Apple Pay.
* Tweak - Avoid re-sending Processing Order customer email when merchant wins dispute.
Expand Down Expand Up @@ -142,6 +143,7 @@ If you get stuck, you can ask for help in the [Plugin Forum](https://wordpress.o
* Dev - Add a GitHub Action workflow to run QIT E2E Integrations tests.
* Fix - Check billing interval and period to set in mandate options.
* Fix - Check order currency on pay for order page to display supported payment methods.
* Update - Migrate payment request settings data to express checkout settings data.
* Update - Make the new Stripe Express Checkout Element enabled by default in all accounts.
* Fix - Duplicate emails when enabling the gateway.

Expand Down
Loading

0 comments on commit d2e7ca1

Please sign in to comment.