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

Conversation

@opr
Copy link
Contributor

@opr opr commented Jan 14, 2021

Saved payment methods are now correctly displayed - previously they were hidden based on whether or not the 'Save payment method' checkbox was visible, by running the wc_stripe_display_save_payment_method_checkbox filter.

The checkbox display was ultimately decided by the Stripe extension, which set the checkbox to not display if a subscription product was in the cart. The logic was because the payment method should always be saved when buying a subscription, so displaying the checkbox was unnecessary.

To fix this I have changed the naming of some props used when registering payment methods:

  • Previously, we used savePaymentInfo to inform the UI whether we should show saved cards and the checkbox.
  • I have now changed this to showSavedCards and showSaveOption to give more granular control over the UI to the payment methods. In our Stripe integration, we set showSavedCards based on the value of the saved_cards option in the Stripe extension, and we set showSaveOption based on the result of the wc_stripe_display_save_payment_method_checkbox filter.
  • Change get_allow_saved_cards method in the Stripe class to be named get_show_saved_cards and return whether the saved_cards option is enabled, without running the checkbox filter mentioned above.
  • Add a method to the Stripe class get_show_save_option which will return the result of get_show_saved_cards filtered through wc_stripe_display_save_payment_method_checkbox
  • Change the PaymentMethodTab component to accept a boolean showSaveOption prop. It is this prop that determines if the checkbox should be displayed or not.
  • Update the payment method registration code to reflect the new names of these props.
  • Update the payment method config and validation to reflect the new names of these props. I also included a shim to set supports.showSavedCards to the same value as supports.savePaymentInfo for backward compatibility. If any payment methods are registering and still using savePaymentInfo then a deprecation notice will be emitted using @wordpress/deprecated.
  • Updated test files to reflect the new names of these props.

I have also modified the Checkout API so that it will fire a new action __experimental_woocommerce_blocks_checkout_update_order_meta which is handled in Subscriptions - this is required as extensions should be given the chance to update the metadata for the orders.

Fixes #3616
Fixes #3620
Fixes #3271
Related PR in subs: 3963-gh-woocommerce/woocommerce-subscriptions

How to test the changes in this Pull Request

  1. Check out this branch and add/actions-hooks-for-update-meta-from-blocks on woocommerce-subscriptions
  2. Enable a payment gateway that supports subs and blocks, for example Stripe 💳
  3. Add a non-subscription product to your cart.
  4. Go to the checkout block and when using the Stripe payment method verify that the Save payment method checkbox shows.
  5. Empty your cart.
  6. Create a subscription product that has multiple variations so that you may up/down/crossgrade between them.
  7. Add a subscription for this product to your cart and check out using the checkout block, and ensure any saved cards show as options.
  8. Ensure the checkout block asks you for payment, or allows you to use an existing method if you have one saved.
  9. Ensure the subscription is created correctly with the correct variation, renewal dates, and price. Also ensure the payment method used to create the subscription was recorded.
  10. Go to My account -> Subscription -> and begin the process to up/down/crossgrade the subscription.
  11. Go to the checkout block and ensure you are not asked for payment. The payment method should already be saved on the subscription. (If you have prorate upgrades and downgrades turned on you may actually be asked for payment here)
  12. Check out, and ensure the checkout completes and you can see the order summary showing your subscription on the client.
  13. Visit the subscription in the admin dashboard and ensure it has the correct details for the order you just created.
  14. Ensure there is a singular additional order in the Orders list for the *grade we just performed.

@opr opr added category: extensibility Work involving adding or updating extensibility. Useful to combine with other scopes impacted. focus: rest api Work impacting REST api routes. block: checkout Issues related to the checkout block. labels Jan 14, 2021
@github-actions
Copy link
Contributor

github-actions bot commented Jan 14, 2021

Size Change: +137 B (0%)

Total Size: 1.19 MB

Filename Size Change
build/cart.js 34.2 kB +2 B (0%)
build/checkout-frontend.js 89.3 kB -9 B (0%)
build/checkout.js 39.8 kB -4 B (0%)
build/wc-blocks-registry.js 2.54 kB +143 B (+6%) 🔍
build/wc-payment-method-stripe.js 12.1 kB +5 B (0%)
ℹ️ View Unchanged
Filename Size Change
build/active-filters-frontend.js 8.32 kB 0 B
build/active-filters.js 8.49 kB 0 B
build/all-products-frontend.js 34.7 kB 0 B
build/all-products.js 36.1 kB 0 B
build/all-reviews.js 9.88 kB 0 B
build/atomic-block-components/add-to-cart--atomic-block-components/button.js 3.34 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 9.2 kB 0 B
build/atomic-block-components/add-to-cart.js 7.7 kB 0 B
build/atomic-block-components/button-frontend.js 2.35 kB 0 B
build/atomic-block-components/button.js 837 B 0 B
build/atomic-block-components/category-list-frontend.js 469 B 0 B
build/atomic-block-components/category-list.js 476 B 0 B
build/atomic-block-components/image-frontend.js 1.68 kB 0 B
build/atomic-block-components/image.js 1.13 kB 0 B
build/atomic-block-components/price-frontend.js 1.83 kB 0 B
build/atomic-block-components/price.js 1.85 kB 0 B
build/atomic-block-components/rating-frontend.js 525 B 0 B
build/atomic-block-components/rating.js 528 B 0 B
build/atomic-block-components/sale-badge-frontend.js 859 B 0 B
build/atomic-block-components/sale-badge.js 862 B 0 B
build/atomic-block-components/sku-frontend.js 389 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 918 B 0 B
build/atomic-block-components/summary.js 926 B 0 B
build/atomic-block-components/tag-list-frontend.js 467 B 0 B
build/atomic-block-components/tag-list.js 471 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.2 kB 0 B
build/attribute-filter.js 12.5 kB 0 B
build/blocks-checkout.js 50.1 kB 0 B
build/blocks.js 3.49 kB 0 B
build/cart-frontend.js 63.6 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.81 kB 0 B
build/featured-product.js 10.1 kB 0 B
build/handpicked-products.js 7.49 kB 0 B
build/price-filter-frontend.js 14.5 kB 0 B
build/price-filter.js 9.92 kB 0 B
build/product-best-sellers.js 7.56 kB 0 B
build/product-categories.js 3.23 kB 0 B
build/product-category.js 8.51 kB 0 B
build/product-new.js 7.74 kB 0 B
build/product-on-sale.js 8.12 kB 0 B
build/product-search.js 3.56 kB 0 B
build/product-tag.js 6.56 kB 0 B
build/product-top-rated.js 7.71 kB 0 B
build/products-by-attribute.js 8.49 kB 0 B
build/reviews-by-category.js 11.9 kB 0 B
build/reviews-by-product.js 13.5 kB 0 B
build/reviews-frontend.js 9.51 kB 0 B
build/single-product-frontend.js 37.9 kB 0 B
build/single-product.js 10.3 kB 0 B
build/style-rtl.css 18.7 kB 0 B
build/style.css 18.7 kB 0 B
build/vendors--atomic-block-components/price-frontend.js 5.73 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 435 kB 0 B
build/wc-blocks-data.js 6.97 kB 0 B
build/wc-blocks-middleware.js 935 B 0 B
build/wc-payment-method-bacs.js 775 B 0 B
build/wc-payment-method-cheque.js 771 B 0 B
build/wc-payment-method-cod.js 866 B 0 B
build/wc-payment-method-paypal.js 813 B 0 B
build/wc-settings.js 2.4 kB 0 B
build/wc-shared-context.js 1.53 kB 0 B
build/wc-shared-hocs.js 1.68 kB 0 B

compressed-size-action

@opr opr force-pushed the fix/allow-0-payment-on-crossgrade branch 2 times, most recently from fd6e4a1 to e08c56a Compare January 19, 2021 15:32
@opr opr marked this pull request as ready for review January 19, 2021 18:30
@opr opr requested a review from a team as a code owner January 19, 2021 18:30
@opr opr requested review from budzanowski and senadir and removed request for a team January 19, 2021 18:30
@opr opr changed the title WIP Change payment processing for subscriptions hange payment processing for subscriptions Jan 19, 2021
@opr opr changed the title hange payment processing for subscriptions Change payment processing for subscriptions Jan 19, 2021
@budzanowski
Copy link
Contributor

This is not a reliable check, and I don't think it should be the job of the client to decide which payment methods to display. We should rely on the server-side to send back only valid payment methods. This may need testing to ensure only valid payment methods for subscriptions can be selected.

With the check removed, we will surface the saved payment methods even if they are not allowed. If we would want to remove the check here we should ensure that the payment methods are not sending the saved options otherwise we are exposing them to the user even if they are not working. This is how I understand the problem.

@nerrad
Copy link
Contributor

nerrad commented Jan 20, 2021

If we would want to remove the check here we should ensure that the payment methods are not sending the saved options otherwise we are exposing them to the user even if they are not working.

I agree with Bartek here. Thomas did you confirm that the server is only surfacing saved payment methods for payment methods that are active? If not, we will need to make sure this is fixed on the server side.

Comment on lines 94 to 100
( { method: { gateway } } ) => {
const isAvailable = gateway in availablePaymentMethods;
return (
isAvailable &&
availablePaymentMethods[ gateway ].supports?.savePaymentInfo
);
}
Copy link
Member

Choose a reason for hiding this comment

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

It's still fuzzy to me what this check does exactly? and why did it had supports?.savePaymentInfo?

Comment on lines +377 to +374
/**
* WooCommerce Blocks Checkout Update Order Meta (experimental).
*
* This hook gives extensions the chance to add or update meta data on the $order.
*
* This is similar to existing core hook woocommerce_checkout_update_order_meta.
* We're using a new action:
* - To keep the interface focused (only pass $order, not passing request data).
* - This also explicitly indicates these orders are from checkout block/StoreAPI.
*
* @see https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/3686
* @internal This Hook is experimental and may change or be removed.
*
* @param WC_Order $order Order object.
*/
do_action( '__experimental_woocommerce_blocks_checkout_update_order_meta', $this->order );

Copy link
Member

Choose a reason for hiding this comment

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

We did a lot of testing yesterday in our call so I'm confident that this works, I can't comment yet on the payment change until I understand it a bit better but approving this part.

}
if (
config.supports &&
typeof config.supports.requiresSaving !== 'undefined' &&
Copy link
Contributor

Choose a reason for hiding this comment

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

If you use optional chaining here you can get rid of the previous line.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Great idea, let's add this as a cooldown task to tidy this up so we don't pollute the PR. Thanks for the tip!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Never mind, I see how small this change is, I thought it was going to be much larger. I've added it to the PR!

Copy link
Contributor

@nerrad nerrad left a comment

Choose a reason for hiding this comment

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

Thanks for tackling this Thomas! I have some feedback that might be due to a lack of fully understanding on my part. As noted in one of the inline comments, I have some concern about the implicit assumptions being made by the usage of the filter.

* @param {boolean} props.allowsSaving Whether that payment method allows saving
* the data for future purchases.
* @param {boolean} props.requiresSaving Whether the payment method should display the option to save
* the details entered by the customer.
Copy link
Contributor

Choose a reason for hiding this comment

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

nit, comment block spacing here seems off.

<PaymentMethodErrorBoundary isEditor={ isEditor }>
{ children }
{ customerId > 0 && allowsSaving && (
{ customerId > 0 && allowsSaving && ! requiresSaving && (
Copy link
Contributor

Choose a reason for hiding this comment

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

hmm this conditional seems a bit wonky to me. Don't we want something like:

Suggested change
{ customerId > 0 && allowsSaving && ! requiresSaving && (
{ customerId > 0 && ( allowsSaving || requiresSaving ) && (

In other words, "If a customer is logged in, and the payment method allows saving or requires saving, then show the checkbox".

Comment on lines 107 to 108
$saved_cards = isset( $this->settings['saved_cards'] ) ? $this->settings['saved_cards'] : false;
return isset( $this->settings['saved_cards'] ) ? 'yes' === $this->settings['saved_cards'] : false;
Copy link
Contributor

Choose a reason for hiding this comment

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

nice little improvement here :)

// See https://github.com/woocommerce/woocommerce-gateway-stripe/blob/ad19168b63df86176cbe35c3e95203a245687640/includes/class-wc-gateway-stripe.php#L271 and
// https://github.com/woocommerce/woocommerce/wiki/Payment-Token-API .
return apply_filters( 'wc_stripe_display_save_payment_method_checkbox', filter_var( $saved_cards, FILTER_VALIDATE_BOOLEAN ) );
return ! apply_filters( 'wc_stripe_display_save_payment_method_checkbox', filter_var( $saved_cards, FILTER_VALIDATE_BOOLEAN ) );
Copy link
Contributor

Choose a reason for hiding this comment

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

hmm this seems to indicate to me that I might be confused about what requiresSaving means. I'm a bit wary of the implicit connection between requiresSaving and allowsSavedCards. So essentially what we're saying here is that if anything filters this option so it returns false, that means the the saved payment methods ARE required (double negative resulting in that). I wonder if we should introduce a new filter that allows for explicitly setting this rather than implicitly?

Copy link
Member

Choose a reason for hiding this comment

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

I wonder if we should introduce a new filter that allows for explicitly setting this rather than implicitly?

double down on this.

Copy link
Contributor

@nerrad nerrad Jan 21, 2021

Choose a reason for hiding this comment

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

Thomas and I chatted about this in our call and reviewed existing behaviour in the shortcode flow. It turns out we think we can improve this by retaining the explicit use of the filtered value and non filtered value and update the name of the properties to make it more clear how things are used. He's in the process of doing that now. My concerns and wariness with the current approach ended up being more an artifact of how the filtered value was returned (switching boolean) and the naming of the properties/values involved.

@opr
Copy link
Contributor Author

opr commented Jan 21, 2021

Thanks for the feedback everyone, I have updated the testing instructions and PR body to include more information about what changes I have made. Would you mind taking another look and giving it a quick spin?

@opr opr requested review from budzanowski, nerrad and senadir January 21, 2021 19:03
opr and others added 25 commits January 24, 2021 14:45
This is needed because some extensions rely on this action to add their information to the metadata of order items.
This adds displaySavePaymentMethodCheckbox which will be used to determine if the checkbox to save payment methods should display.
This will determine whether the "Save payment information" checkbox will be displayed.
This is informed by the saved_cards option and the result of the wc_stripe_display_save_payment_method_checkbox filter.
We are going to rename the properties we use to determine whether saved cards are shown, or whether the save payment method checkbox is shown, so that their names are more descriptive of what they are for.
This is so we can hide the checkbox independently of hiding the saved payment methods.
This is because we are leaving it in to enable backward compatibility but payment methods registering using this should be informed of the change in case it gets removed.
This will allow us to show the save checkbox only if the payment method says it should be shown.
…g.js

Co-authored-by: Seghir Nadir <nadir.seghir@gmail.com>
@senadir senadir force-pushed the fix/allow-0-payment-on-crossgrade branch from 99de9e5 to e8ac0ee Compare January 24, 2021 13:46
@senadir senadir merged commit bf4fabe into trunk Jan 24, 2021
@senadir senadir deleted the fix/allow-0-payment-on-crossgrade branch January 24, 2021 13:59
@mikejolley mikejolley added the skip-changelog PRs that you don't want to appear in the changelog. label Feb 1, 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. focus: rest api Work impacting REST api routes. skip-changelog PRs that you don't want to appear in the changelog.

Projects

None yet

6 participants