Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ACSS: Handle errors and edge cases #3870

Open
wants to merge 49 commits into
base: develop
Choose a base branch
from

Conversation

ricardo
Copy link
Member

@ricardo ricardo commented Feb 11, 2025

Fixes #3830

Changes proposed in this Pull Request:

  • Display payment method inline notice to blocks and classic checkout (showErrorPaymentMethod) when the create intent request fails, or when there's a loaderror in the payment element.
  • Similar to WooPayments, add flag hasLoadError to classic and blocks to prevent form submissions if the payment method fails to load.
  • Fix console errors triggered from showErrorCheckout.
  • Ignore ACSS-specific charge_exceeds_transaction_limit error from retrials.
  • Fixed: Display load error if the order amount is too small.

Setup

  1. Enable the ACSS feature flag:
    • Use the Stripe Dev Tools plugin to enable the ACSS feature flag.
  2. Enable ACSS in Stripe:
    • Navigate to the Stripe Dashboard.
    • Enable "Canadian Pre-Authorized Debits" in the payment methods settings.
  3. Enable ACSS in WC Stripe:
    • Go to WooCommerce > Settings > Payments > Stripe.
    • Enable "Pre-Authorized Debit (ACSS)".
  4. Listen to webhooks:
npm run listen
  1. Change the store currency to CAD.

Testing Instructions

👉 Please test on both classic checkout and shortcode checkout.

Test 1: Failing to load the Payment Element

  1. Change this line to WC_Stripe_API::request( $request, 'test' ); or some corrupt request endpoint to test an error.
  2. As a shopper, add a simple product to your cart and proceed to checkout.
  3. Select Canada, and enter a valid address (e.g., Vancouver, British Columbia, K1A 0B1).
  4. Select Pre-Authorized Debit (ACSS) as the payment method.
  5. Notice there's an error in loading the payment method. The message in this case is not very helpful for the user, but since the error is created artificially, we shouldn't account for this specific error message.
  6. Revert the change from line 1 before proceeding to the next tests.

Test 2: Minimum order amount error

  1. As a merchant, create a simple product priced at $0.20 USD.
  2. As a shopper, add this product to your cart and proceed to checkout.
  3. Select ACSS as the payment method, then select credit card.
  4. Notice that for both payment methods, the element fails to load due to the small order amount.
  5. Attempt to click the Place Order button.
  6. Observe that an error notice is displayed, preventing the form from being submitted.

Test 3: Failing account numbers

Institution Number Transit Number Account Number Failure Scenario
000 11000 000222222227 Fails immediately after micro-deposit verification.
000 11000 900222222227 Fails with a three-minute delay after verification.
000 11000 000666666661 Fails to send verification micro-deposits.
000 11000 000777777771 Fails due to exceeding the weekly payment volume limit.
000 11000 000888888881 Fails due to exceeding the transaction limit.

Test Steps:

  1. As a shopper, add a simple product to your cart and proceed to checkout.
  2. Enter a valid email in the format {any_prefix}+test_email@{any_domain} to receive the micro-deposit verification email.
  3. Select Canada, and enter a valid address (e.g., Vancouver, British Columbia, K1A 0B1).
  4. Select Pre-Authorized Debit (ACSS) as the payment method.
  5. Click Place Order, then select Manually Verify.
  6. At checkout, select ACSS and click Place Order.
  7. Click Manually Verify and enter one of the failing account numbers above.
  8. Click Submit, Confirm, and then Agree.
  9. Depending on the account number you should receive a micro-deposit email.
  10. Verify the deposits with 32 and 45.
  11. Expected failure behavior:
  • If the payment fails immediately, an error should be displayed on the checkout page.
  • If the payment fails after a delay, there is no error on the checkout page, but order notes are added.
  1. Verify that appropriate error messages are displayed.
  2. As the merchant, check WooCommerce > Orders for order notes and failure reasons.

  • Covered with tests (or have a good reason not to test in description ☝️)
  • Added changelog entry in both changelog.txt and readme.txt (or does not apply)
  • Tested on mobile (or does not apply)

Post merge

ricardo and others added 30 commits January 22, 2025 15:40
…merce/woocommerce-gateway-stripe into fix/3804-refactor-deferred-intent
@ricardo ricardo changed the base branch from develop to fix/3851-non-di-blocks-pm February 11, 2025 16:56
Base automatically changed from fix/3851-non-di-blocks-pm to develop February 26, 2025 16:07
@ricardo ricardo marked this pull request as ready for review February 27, 2025 18:22
@ricardo ricardo requested review from a team and cesarcosta99 and removed request for a team February 27, 2025 18:22
Comment on lines +63 to +77
const paymentMethodTitle =
getBlocksConfiguration()?.paymentMethodsConfig?.[
paymentMethodId
]?.title ?? '';
setErrorMessage(
error?.message ??
sprintf(
// translators: %s is the payment method title.
__(
'Failed to load %s payment method. Please refresh the page and try again.',
'woocommerce-gateway-stripe'
),
paymentMethodTitle
)
);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is specific to non-deferred intent payment methods (ACSS and BLIK).

Comment on lines +145 to +151
{ paymentProcessorLoadErrorMessage?.error?.message && (
<div className="wc-block-components-notices">
<StoreNotice status="error" isDismissible={ false }>
{ paymentProcessorLoadErrorMessage.error.message }
</StoreNotice>
</div>
) }
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This approach is sourced from WooPayments (src).

This fixes any rendering issues due to minimum order amount or any other possible load error.

Comment on lines +168 to +176
if ( hasLoadErrorRef.current ) {
return {
type: 'error',
message: __(
'Invalid or missing payment details. Please ensure the provided payment method is correctly entered.',
'woocommerce-gateway-stripe'
),
};
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is also sourced from WooPayments (Automattic/woocommerce-payments#8908), and it fixes any potential form submissions in case the PE has failed to load.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this related? #3991

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't try to reproduce in this PR, but at first glance it doesn't seem related. This would only get triggered for Payment Element load errors, but the error from the issue seems like it's generated from the backend.

Comment on lines +150 to +157
if (
isset( $error->code ) &&
(
'payment_intent_mandate_invalid' === $error->code || // Don't retry payments when a 3DS mandate is invalid.
'charge_exceeds_transaction_limit' === $error->code || // Don't retry payments when the charge exceeds the transaction limit.
'amount_too_small' === $error->code
)
) {
Copy link
Member Author

@ricardo ricardo Feb 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI @asumaran @rafaelzaleski – In case you find any issues with retrials due to ACH/BACS specific errors, you can check and ignore the error in is_retryable_error.

Copy link
Contributor

@cesarcosta99 cesarcosta99 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM and tests well! I went through all tests against shortcode and Block-based checkout and everything worked as expected!

  • Test 1: Failing to load the Payment Element ✅
  • Test 2: Minimum order amount error ✅
  • Test 3: Failing account numbers ✅

Comment on lines +558 to +563
const $container = jQuery( containerSelector ).first();

if ( ! $container.length ) {
// If the container doesn't exist, do nothing.
return;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest moving this check to the beginning of the function as the entire logic depend on this container existing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

ACSS: Handle Errors and Edge Cases
4 participants