Skip to content
This repository has been archived by the owner on Feb 23, 2024. It is now read-only.

Refactor Payment Methods Integration API to fire onPaymentProcessing event with saved tokens. #3982

Merged

Conversation

nerrad
Copy link
Contributor

@nerrad nerrad commented Mar 19, 2021

Fixes: #3980

Currently there exists what is arguably a flaw in the checkout event system in that onPaymentProcessing event can be observed by express payment methods and regular payment methods but not by saved payment methods (implementing the savedTokenComponent configuration property). This inconsistency is a flaw in that some payment methods implementing this component will have no way to reliably update the paymentMethodData in the checkout state before it is passed along on the checkout endpoint request for server side processing. You can read more about where this can manifest in #3980.

A significant reason for why this inconsistency existed is because when the system was initially designed, an assumption was made that saved tokens would always be processed server side and payment method logic would never need to interact on the client. This was a faulty assumption which I started rectifying in #3961 and now finished with this PR here.

As a result, this PR implements the following changes to ensure the onPaymentProcessing event is accessible to the savedTokenComponent:

  • Implemented a started action creator that returns an action object that when dispatched will allow for updating the payment method data in the checkout state.
  • The above allows the checkout flow to "initialize" selected saved payment method tokens to a started status for the payment method and store data about the saved token in the checkout state. This replaces the existing logic that was setting the payment method status for saved tokens to "success".
  • Some slight improvements of types (TS) to account for the fact that both started and success payment method status changes allow for retaining existing payment method data in the state if it's not provided by the action. This improves performance because there are many places where just the payment status needs updated by checkout without changing anything else in the state.
  • The above change does however mean that any place we change the status to success or started where the payment method data does need wiped, must be done explicitly (by passing in an empty object to the dispatched action). Thus one change was needed here for express payment methods. Also where express payment methods restored the saved token status (if the modal was closed without completing), the action dispatched was switched from success to started in order to reflect the changes made for saved token handling.

Outside of the necessary TypeScript type changes for existing typescript files, I didn't implement typescript anywhere else mostly because there's some time sensitivity around the need for this API change.

Regarding documentation, I did do a pass through the existing documentation and I don't see anywhere that needs updated. Indeed, the existing documentation already pointed to the onPaymentProcessing event being available for savedTokenComponent so the changes here are actually more in line with what the documentation already indicates!

To Test

The changes here implement any payment method type processing, so it's important to verify there is no impact to existing payment method handling by these changes. This means setting up an environment where you have the core payment methods and Stripe (along with Stripe express payments, either Chrome Pay or Apple Pay) available for testing.

  • Verify that you can pay with a saved token.
  • Verify that you can pay with an express payment method (Apple Pay or Chrome Pay - either working should be sufficient).
  • Verify that you can pay with a Stripe Credit Card
  • Verify that you can pay with any other Woo core payment method.
  • Try all of the above (except saved token) in incognito mode.

Besides the above smoke tests, try intentionally confusing or breaking the system. Some example scenarios:

  • When checkout loads with available multiple saved tokens (which you might have to setup in previous purchases), try switching between saved tokens and different payment methods, and back to a saved token before completing the purchase. Ensure the saved payment method you selected was used for the payment.
  • Try different payment methods and triggering a scenario that fails payment or causes an error. In the case of Stripe CC (or express payment) there are a bunch of test cards you can access for triggering different payment failure conditions. After a payment method failure, ensure you can pay with an alternative method of payment that should succeed without issues.
  • Trigger starting an express payment method, selecting different shipping addresses and different rates and ensure it completes successfully after submitting.
  • Do the above, but instead of completing the payment, just cancel and close the modal. Ensure that you can make a payment with the saved payment method token after doing so without issue.
  • Optional (I tested this fairly throughly): For this test you'll have to use Stripe built with this pr. Verify that if your saved token is using a 3DS card always 3DS auth ( such as 4000002760003184), then the 3DS validation process still works when attempting to make a payment using the token.

The above all validates that the changes in this PR don't break existing behaviour. There's no easy way to test (currently) the actual implementation exposing onPaymentProcessing event for savedTokenComponents without manually implementing a dummy test. I did this to verify it works as expected. However, this PR will also be tested as a part of the work being done for the Square extension.

Changelog

Payment methods implementing the savedTokenComponent configuration property will now have the onPaymentProcessing event available to the registered component.

@github-actions
Copy link
Contributor

github-actions bot commented Mar 19, 2021

Size Change: -9 B (0%)

Total Size: 1.16 MB

Filename Size Change
build/cart-frontend.js 76.4 kB +10 B (0%)
build/cart.js 42.5 kB -5 B (0%)
build/checkout-frontend.js 80.9 kB +1 B (0%)
build/checkout.js 44.9 kB -15 B (0%)
ℹ️ View Unchanged
Filename Size Change
build/active-filters-frontend.js 8.62 kB 0 B
build/active-filters.js 8.71 kB 0 B
build/all-products-frontend.js 35.1 kB 0 B
build/all-products.js 37 kB 0 B
build/all-reviews.js 9.91 kB 0 B
build/atomic-block-components/add-to-cart--atomic-block-components/button-frontend.js 1.97 kB 0 B
build/atomic-block-components/add-to-cart--atomic-block-components/button.js 3.59 kB 0 B
build/atomic-block-components/add-to-cart--atomic-block-components/image--atomic-block-components/title.js 336 B 0 B
build/atomic-block-components/add-to-cart-frontend.js 8.09 kB 0 B
build/atomic-block-components/add-to-cart.js 7.74 kB 0 B
build/atomic-block-components/button-frontend.js 1.04 kB 0 B
build/atomic-block-components/button.js 1.05 kB 0 B
build/atomic-block-components/category-list-frontend.js 470 B 0 B
build/atomic-block-components/category-list.js 476 B 0 B
build/atomic-block-components/image-frontend.js 1.77 kB 0 B
build/atomic-block-components/image.js 1.24 kB 0 B
build/atomic-block-components/price-frontend.js 1.98 kB 0 B
build/atomic-block-components/price.js 2 kB 0 B
build/atomic-block-components/rating-frontend.js 520 B 0 B
build/atomic-block-components/rating.js 525 B 0 B
build/atomic-block-components/sale-badge-frontend.js 861 B 0 B
build/atomic-block-components/sale-badge.js 871 B 0 B
build/atomic-block-components/sku-frontend.js 391 B 0 B
build/atomic-block-components/sku.js 394 B 0 B
build/atomic-block-components/stock-indicator-frontend.js 569 B 0 B
build/atomic-block-components/stock-indicator.js 573 B 0 B
build/atomic-block-components/summary-frontend.js 922 B 0 B
build/atomic-block-components/summary.js 924 B 0 B
build/atomic-block-components/tag-list-frontend.js 467 B 0 B
build/atomic-block-components/tag-list.js 473 B 0 B
build/atomic-block-components/title-frontend.js 1.35 kB 0 B
build/atomic-block-components/title.js 1.21 kB 0 B
build/attribute-filter-frontend.js 18.4 kB 0 B
build/attribute-filter.js 12.5 kB 0 B
build/blocks-checkout.js 17 kB 0 B
build/blocks.js 3.5 kB 0 B
build/editor-rtl.css 14.9 kB 0 B
build/editor.css 14.9 kB 0 B
build/featured-category.js 7.86 kB 0 B
build/featured-product.js 10.1 kB 0 B
build/handpicked-products.js 7.54 kB 0 B
build/price-filter-frontend.js 14.7 kB 0 B
build/price-filter.js 10 kB 0 B
build/price-format.js 1.46 kB 0 B
build/product-best-sellers.js 7.61 kB 0 B
build/product-categories.js 3.23 kB 0 B
build/product-category.js 8.56 kB 0 B
build/product-new.js 7.78 kB 0 B
build/product-on-sale.js 8.18 kB 0 B
build/product-search.js 3.61 kB 0 B
build/product-tag.js 6.61 kB 0 B
build/product-top-rated.js 7.75 kB 0 B
build/products-by-attribute.js 8.54 kB 0 B
build/reviews-by-category.js 12 kB 0 B
build/reviews-by-product.js 13.5 kB 0 B
build/reviews-frontend.js 9.58 kB 0 B
build/single-product-frontend.js 38.1 kB 0 B
build/single-product.js 10.3 kB 0 B
build/style-rtl.css 18.4 kB 0 B
build/style.css 18.4 kB 0 B
build/vendors--atomic-block-components/price-frontend.js 6.54 kB 0 B
build/vendors-style-rtl.css 1.05 kB 0 B
build/vendors-style.css 1.05 kB 0 B
build/vendors.js 419 kB 0 B
build/wc-blocks-data.js 7.2 kB 0 B
build/wc-blocks-google-analytics.js 1.35 kB 0 B
build/wc-blocks-middleware.js 1.11 kB 0 B
build/wc-blocks-registry.js 2.74 kB 0 B
build/wc-payment-method-bacs.js 812 B 0 B
build/wc-payment-method-cheque.js 807 B 0 B
build/wc-payment-method-cod.js 903 B 0 B
build/wc-payment-method-paypal.js 844 B 0 B
build/wc-payment-method-stripe.js 12.3 kB 0 B
build/wc-settings.js 2.43 kB 0 B
build/wc-shared-context.js 1.53 kB 0 B
build/wc-shared-hocs.js 1.72 kB 0 B

compressed-size-action

@nerrad nerrad force-pushed the add/expose-onPaymentProcessing-event-for-saved-payment-methods branch from 083d883 to 9c8875a Compare March 19, 2021 23:00
nerrad added 9 commits March 20, 2021 11:47
Also for TS typing I changed `paymentMethodData` to be optional for both the `success` and `started` action creators.

This is because the behaviour allows for paymentMethodData to be retained in the state if it is not explicitly provided on dispatch.
…cher.

The implementation now allows for receiving payment method data when the `start` status is dispatched.
It is intended that if paymentMethodData is undefined, that is simply passed through to the dispatched action. This signals the reducer to retain the existing paymentMethodData in state (when undefined).

The correct way to clear the paymentMethodData is to either explictly provide an empty object, or set the status to pristine.
This changeset also configures the reducer to retain the existing paymentMethodData in state (and related correlated information0 when the provided paymentMethodData property is undefined.

The only time paymentMethodData should be reset in state is when it is explicitly provided or the status is set to PRISTINE.
Also restores previous paymentMethodData when express payment cancelled.
…atched action instead of success.

This change ensures that savedToken handlers registered by payment methods have access to the `onPaymentProcessing` checkout event.
Really just need to ensure types are used anywhere, this is a temporary change due to the time sensitive needs for this PR.
@nerrad nerrad force-pushed the add/expose-onPaymentProcessing-event-for-saved-payment-methods branch from 9c8875a to c3d5163 Compare March 20, 2021 15:58
@nerrad nerrad marked this pull request as ready for review March 20, 2021 17:33
@nerrad nerrad requested a review from a team as a code owner March 20, 2021 17:33
@nerrad nerrad requested review from Aljullu and removed request for a team March 20, 2021 17:33
@nerrad nerrad self-assigned this Mar 20, 2021
@nerrad nerrad added category: extensibility Work involving adding or updating extensibility. Useful to combine with other scopes impacted. block: cart Issues related to the cart block. block: checkout Issues related to the checkout block. type: refactor The issue/PR is related to refactoring. type: enhancement The issue is a request for an enhancement. and removed block: cart Issues related to the cart block. type: enhancement The issue is a request for an enhancement. labels Mar 20, 2021
@nerrad nerrad added this to the 4.8.0 milestone Mar 20, 2021
Comment on lines -117 to +119
if ( token === '0' ) {
setPaymentStatus().started();
}
setActiveSavedToken( token );
},
[ setActiveSavedToken, setPaymentStatus ]
[ setActiveSavedToken ]
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This logic hasn't been needed ever since we switched away from tabs and radios to only radios for payment method selection. There is no longer a possibility for a token with a value of '0' in the checkout flow.

Copy link
Contributor

@Aljullu Aljullu left a comment

Choose a reason for hiding this comment

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

Code changes look good, and following the testing steps from the PR description worked well. For express payment methods I tested with Chrome Pay. I also did some extra testing trying to break the system without luck, so LGTM.

@nerrad nerrad merged commit 1b636ea into trunk Mar 22, 2021
@nerrad nerrad deleted the add/expose-onPaymentProcessing-event-for-saved-payment-methods branch March 22, 2021 14:02
@nerrad nerrad added the needs: dev note PR that has some text that needs to be included in the release notes. label Mar 22, 2021
@ralucaStan ralucaStan added the type: enhancement The issue is a request for an enhancement. label Mar 31, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
block: checkout Issues related to the checkout block. category: extensibility Work involving adding or updating extensibility. Useful to combine with other scopes impacted. needs: dev note PR that has some text that needs to be included in the release notes. type: enhancement The issue is a request for an enhancement. type: refactor The issue/PR is related to refactoring.
Projects
None yet
3 participants