Skip to content

Commit

Permalink
Improving the redirect URL definition code readability (#3448)
Browse files Browse the repository at this point in the history
* Improve redirect URL logic

* Fix additional metas for orders that requires action

* Changelog and readme entries
  • Loading branch information
wjrosa authored Sep 23, 2024
1 parent 1b5df81 commit 0225c98
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 40 deletions.
1 change: 1 addition & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
*** Changelog ***

= 8.8.0 - xxxx-xx-xx =
* Dev - Improves the readability of the redirect URL generation code (UPE).
* Add - Introduce a new meta data that persists the status of a dispute.
* Fix - Fix mandate creation for subscriptions and saved payment methods.
* Fix - Fix Google Pay address fields mapping for UAE addresses.
Expand Down
97 changes: 57 additions & 40 deletions includes/payment-methods/class-wc-stripe-upe-payment-gateway.php
Original file line number Diff line number Diff line change
Expand Up @@ -859,47 +859,14 @@ private function process_payment_with_deferred_intent( int $order_id ) {
// Save the preferred card brand on the order.
$this->maybe_set_preferred_card_brand_for_order( $order, $payment_method );

$redirect = $this->get_return_url( $order );

/**
* Depending on the payment method used to process the payment, we may need to redirect the user to a URL for further processing.
*
* - Voucher payments (Boleto or Oxxo or Multibanco) respond with a hash URL so the client JS code can recognize the response, pull out the necessary args and handle the displaying of the voucher.
* - Wallet payments (CashApp or WeChat) respond with a hash URL so the client JS code can recognize the response, pull out the necessary args and handle the displaying of the modal.
* - Other payment methods like Giropay, iDEAL, Alipay etc require a redirect to a URL provided by Stripe.
* - 3DS Card payments return a hash URL so the client JS code can recognize the response, pull out the necessary PI args and display the 3DS confirmation modal.
*/
if ( in_array( $payment_intent->status, [ 'requires_confirmation', 'requires_action' ], true ) ) {
if ( isset( $payment_intent->payment_method_types ) && count( array_intersect( [ 'boleto', 'oxxo', 'multibanco' ], $payment_intent->payment_method_types ) ) !== 0 ) {
// For Voucher payment method types (Boleto/Oxxo/Multibanco), redirect the customer to a URL hash formatted #wc-stripe-voucher-{order_id}:{payment_method_type}:{client_secret}:{redirect_url} to confirm the intent which also displays the voucher.
$redirect = sprintf(
'#wc-stripe-voucher-%s:%s:%s:%s',
$order_id,
$payment_information['selected_payment_type'],
$payment_intent->client_secret,
rawurlencode( $redirect )
);
} elseif ( isset( $payment_intent->payment_method_types ) && count( array_intersect( [ 'wechat_pay', 'cashapp' ], $payment_intent->payment_method_types ) ) !== 0 ) {
// For Wallet payment method types (CashApp/WeChat Pay), redirect the customer to a URL hash formatted #wc-stripe-wallet-{order_id}:{payment_method_type}:{payment_intent_type}:{client_secret}:{redirect_url} to confirm the intent which also displays the modal.
$redirect = sprintf(
'#wc-stripe-wallet-%s:%s:%s:%s:%s',
$order_id,
$payment_information['selected_payment_type'],
$payment_intent->object,
$payment_intent->client_secret,
rawurlencode( $redirect )
);
} elseif ( isset( $payment_intent->next_action->type ) && in_array( $payment_intent->next_action->type, [ 'redirect_to_url', 'alipay_handle_redirect' ], true ) && ! empty( $payment_intent->next_action->{$payment_intent->next_action->type}->url ) ) {
$redirect = $payment_intent->next_action->{$payment_intent->next_action->type}->url;
} else {
$redirect = sprintf(
'#wc-stripe-confirm-%s:%s:%s:%s',
$payment_needed ? 'pi' : 'si',
$order_id,
$payment_intent->client_secret,
wp_create_nonce( 'wc_stripe_update_order_status_nonce' )
);
$return_url = $this->get_return_url( $order );

// Updates the redirect URL and add extra meta data to the order if the payment intent requires confirmation or action.
if ( in_array( $payment_intent->status, [ 'requires_confirmation', 'requires_action' ], true ) ) {
$redirect = $this->get_redirect_url( $return_url, $payment_intent, $payment_information, $order, $payment_needed );
$is_wallet_or_voucher_method = isset( $payment_intent->payment_method_types ) && count( array_intersect( [ 'boleto', 'oxxo', 'multibanco', 'wechat_pay', 'cashapp' ], $payment_intent->payment_method_types ) ) !== 0;
$contains_redirect_next_action = isset( $payment_intent->next_action->type ) && in_array( $payment_intent->next_action->type, [ 'redirect_to_url', 'alipay_handle_redirect' ], true ) && ! empty( $payment_intent->next_action->{$payment_intent->next_action->type}->url );
if ( ! $is_wallet_or_voucher_method && ! $contains_redirect_next_action ) {
// Return the payment method used to process the payment so the block checkout can save the payment method.
$response_args['payment_method'] = $payment_information['payment_method'];
}
Expand All @@ -910,6 +877,8 @@ private function process_payment_with_deferred_intent( int $order_id ) {
// Prevent processing the payment intent webhooks while also processing the redirect payment (also prevents duplicate Stripe meta stored on the order).
$order->update_meta_data( '_stripe_upe_waiting_for_redirect', true );
$order->save();
} else {
$redirect = $return_url;
}

if ( $payment_needed ) {
Expand Down Expand Up @@ -2540,6 +2509,54 @@ private function is_refund_request() {
return isset( $_POST['action'] ) && 'woocommerce_refund_line_items' === $_POST['action']; // phpcs:ignore WordPress.Security.NonceVerification.Missing
}

/**
* Depending on the payment method used to process the payment, we may need to redirect the user to a URL for further processing.
*
* - Voucher payments (Boleto or Oxxo or Multibanco) respond with a hash URL so the client JS code can recognize the response, pull out the necessary args and handle the displaying of the voucher.
* - Wallet payments (CashApp or WeChat) respond with a hash URL so the client JS code can recognize the response, pull out the necessary args and handle the displaying of the modal.
* - Other payment methods like Giropay, iDEAL, Alipay etc require a redirect to a URL provided by Stripe.
* - 3DS Card payments return a hash URL so the client JS code can recognize the response, pull out the necessary PI args and display the 3DS confirmation modal.
*
* @param $return_url string The return URL.
* @param $payment_intent object The payment intent object.
* @param $payment_information array The payment information.
* @param $order WC_Order The order.
* @param $payment_needed bool Whether payment is needed.
* @return string The redirect URL.
*/
private function get_redirect_url( $return_url, $payment_intent, $payment_information, $order, $payment_needed ) {
if ( isset( $payment_intent->payment_method_types ) && count( array_intersect( [ 'boleto', 'oxxo', 'multibanco' ], $payment_intent->payment_method_types ) ) !== 0 ) {
// For Voucher payment method types (Boleto/Oxxo/Multibanco), redirect the customer to a URL hash formatted #wc-stripe-voucher-{order_id}:{payment_method_type}:{client_secret}:{redirect_url} to confirm the intent which also displays the voucher.
return sprintf(
'#wc-stripe-voucher-%s:%s:%s:%s',
$order->get_id(),
$payment_information['selected_payment_type'],
$payment_intent->client_secret,
rawurlencode( $return_url )
);
} elseif ( isset( $payment_intent->payment_method_types ) && count( array_intersect( [ 'wechat_pay', 'cashapp' ], $payment_intent->payment_method_types ) ) !== 0 ) {
// For Wallet payment method types (CashApp/WeChat Pay), redirect the customer to a URL hash formatted #wc-stripe-wallet-{order_id}:{payment_method_type}:{payment_intent_type}:{client_secret}:{redirect_url} to confirm the intent which also displays the modal.
return sprintf(
'#wc-stripe-wallet-%s:%s:%s:%s:%s',
$order->get_id(),
$payment_information['selected_payment_type'],
$payment_intent->object,
$payment_intent->client_secret,
rawurlencode( $return_url )
);
} elseif ( isset( $payment_intent->next_action->type ) && in_array( $payment_intent->next_action->type, [ 'redirect_to_url', 'alipay_handle_redirect' ], true ) && ! empty( $payment_intent->next_action->{$payment_intent->next_action->type}->url ) ) {
return $payment_intent->next_action->{$payment_intent->next_action->type}->url;
}

return sprintf(
'#wc-stripe-confirm-%s:%s:%s:%s',
$payment_needed ? 'pi' : 'si',
$order->get_id(),
$payment_intent->client_secret,
wp_create_nonce( 'wc_stripe_update_order_status_nonce' )
);
}

/**
* Saves the default appearance settings to a transient cache.
*
Expand Down
1 change: 1 addition & 0 deletions readme.txt
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ If you get stuck, you can ask for help in the Plugin Forum.
== Changelog ==

= 8.8.0 - xxxx-xx-xx =
* Dev - Improves the readability of the redirect URL generation code (UPE).
* Add - Introduce a new meta data that persists the status of a dispute.
* Fix - Fix mandate creation for subscriptions and saved payment methods.
* Fix - Fix Google Pay address fields mapping for UAE addresses.
Expand Down

0 comments on commit 0225c98

Please sign in to comment.