Skip to content

RPP / Failures / Refactor the catch block #7424

Open
@RadoslavGeorgiev

Description

@RadoslavGeorgiev

Description

This issue is regarding the existing catch block of WC_Payment_Gateway_WCPay::process_payment():

} catch ( Exception $e ) {
// We set this variable to be used in following checks.
$blocked_due_to_fraud_rules = $e instanceof API_Exception && 'wcpay_blocked_by_fraud_rule' === $e->get_error_code();
do_action( 'woocommerce_payments_order_failed', $order, $e );
/**
* TODO: Determine how to do this update with Order_Service.
* It seems that the status only needs to change in certain instances, and within those instances the intent
* information is not added to the order, as shown by tests.
*/
if ( ! $blocked_due_to_fraud_rules && ( empty( $payment_information ) || ! $payment_information->is_changing_payment_method_for_subscription() ) ) {
$order->update_status( Order_Status::FAILED );
}
if ( $e instanceof API_Exception && $this->should_bump_rate_limiter( $e->get_error_code() ) ) {
$this->failed_transaction_rate_limiter->bump();
}
if ( $blocked_due_to_fraud_rules ) {
$this->order_service->mark_order_blocked_for_fraud( $order, '', Intent_Status::CANCELED );
} elseif ( ! empty( $payment_information ) ) {
/**
* TODO: Move the contents of this else into the Order_Service.
*/
/* translators: %1: the failed payment amount, %2: error message */
$error_message = __(
'A payment of %1$s <strong>failed</strong> to complete with the following message: <code>%2$s</code>.',
'woocommerce-payments'
);
$error_details = esc_html( rtrim( $e->getMessage(), '.' ) );
if ( $e instanceof API_Exception && 'card_error' === $e->get_error_type() ) {
// If the payment failed with a 'card_error' API exception, initialize the fraud meta box
// type with ALLOW, because fraud checks are passed, and the payment returned a "card error".
$this->order_service->set_fraud_meta_box_type_for_order( $order, Fraud_Meta_Box_Type::ALLOW );
if ( 'incorrect_zip' === $e->get_error_code() ) {
/* translators: %1: the failed payment amount, %2: error message */
$error_message = __(
'A payment of %1$s <strong>failed</strong>. %2$s',
'woocommerce-payments'
);
$error_details = __(
'We couldn’t verify the postal code in the billing address. If the issue persists, suggest the customer to reach out to the card issuing bank.',
'woocommerce-payments'
);
}
}
$note = sprintf(
WC_Payments_Utils::esc_interpolated_html(
$error_message,
[
'strong' => '<strong>',
'code' => '<code>',
]
),
WC_Payments_Explicit_Price_Formatter::get_explicit_price( wc_price( $order->get_total(), [ 'currency' => $order->get_currency() ] ), $order ),
$error_details
);
$order->add_order_note( $note );
}
if ( $e instanceof Process_Payment_Exception && 'rate_limiter_enabled' === $e->get_error_code() ) {
/**
* TODO: Move the contents of this into the Order_Service.
*/
$note = sprintf(
WC_Payments_Utils::esc_interpolated_html(
/* translators: %1: the failed payment amount */
__(
'A payment of %1$s <strong>failed</strong> to complete because of too many failed transactions. A rate limiter was enabled for the user to prevent more attempts temporarily.',
'woocommerce-payments'
),
[
'strong' => '<strong>',
]
),
WC_Payments_Explicit_Price_Formatter::get_explicit_price( wc_price( $order->get_total(), [ 'currency' => $order->get_currency() ] ), $order )
);
$order->add_order_note( $note );
}
if ( WC_Payments_Features::is_upe_legacy_enabled() ) {
UPE_Payment_Gateway::remove_upe_payment_intent_from_session();
}
// Re-throw the exception after setting everything up.
// This makes the error notice show up both in the regular and block checkout.
throw new Exception( WC_Payments_Utils::get_filtered_error_message( $e ) );
}

Presently, there are various checks like ! empty( $payment_information ), which can never be empty, and they force multiple nested IFs. In addition, early returns (or re-throws in this case) with WC_Payments_Utils::get_filtered_error_message() could flatten the code further.

Acceptance criteria

Testing instructions

There should be testing instructions to cover every exception.

Additional context

Epic: #6673
Project: paJDYF-9hL-p2

Metadata

Metadata

Assignees

Labels

category: coreWC Payments core related issues, where it’s obvious.category: engineeringFor product engineering, architecture work, tech debt and so on.category: projectsFor any issues which are part of any project, including bugs, enhancements, etc.component: checkoutIssues related to Checkoutfocus: checkout paymentsstatus: blockedThe issue is blocked from progressing, waiting for another piece of work to be done.status: has prThe issue has a PR.status: on holdThe issue is currently not prioritized.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions