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

POC - Centralized payment method definitions #10217

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

Conversation

brettshumaker
Copy link
Contributor

@brettshumaker brettshumaker commented Jan 22, 2025

Fixes #10400

Changes proposed in this Pull Request

This PR introduces a centralized system for defining payment methods in WooCommerce Payments, significantly reducing the complexity and maintenance burden of implementing new payment methods. Previously, adding or modifying payment methods required changes across multiple files with duplicated logic. This new architecture provides a single source of truth for payment method definitions.

This PR was born out of a POC for centralizing payment method definitions to reduce the amount of changes that need to be made while implementing (or removing support for) a new payment method. It's resulting from #10098

Once I've added the appropriate unit tests, I'll mark the PR as ready but, given it's size I thought it'd be good to get an initial review.

Initially, I had converted Affirm, Afterpay/Clearpay, and Klarna to use the new definition system, but @FangedParakeet suggested I remove those changes so we're only reviewing the base functionality in this PR. All payment methods will be converted to use the new definition and registration system in separate issues (to be created). So this PR doesn't technically introduce any change in functionality for any payment method.

Testing instructions

  • Nothing should break.
  • All payment methods still show up in all expected places.
  • All payment methods should still be able to be used to checkout.

  • Run npm run changelog to add a changelog file, choose patch to leave it empty if the change is not significant. You can add multiple changelog files in one PR by running this command a few times.
  • Covered with tests (or have a good reason not to test in description ☝️)
  • Tested on mobile (or does not apply)

Post merge

@botwoo
Copy link
Collaborator

botwoo commented Jan 22, 2025

Test the build

Option 1. Jetpack Beta

  • Install and activate Jetpack Beta.
  • Use this build by searching for PR number 10217 or branch name poc/centralized-payment-method-definitions in your-test.site/wp-admin/admin.php?page=jetpack-beta&plugin=woocommerce-payments

Option 2. Jurassic Ninja - available for logged-in A12s

🚀 Launch a JN site with this branch 🚀

ℹ️ Install this Tampermonkey script to get more options.


Build info:

  • Latest commit: 13fec88
  • Build time: 2025-02-27 21:16:57 UTC

Note: the build is updated when a new commit is pushed to this PR.

Copy link
Contributor

github-actions bot commented Jan 22, 2025

Size Change: +834 B (0%)

Total Size: 1.29 MB

Filename Size Change
release/woocommerce-payments/dist/blocks-checkout.js 55.5 kB +137 B (0%)
release/woocommerce-payments/dist/cart-block.js 17.3 kB -24 B (0%)
release/woocommerce-payments/dist/checkout.js 34.6 kB +70 B (0%)
release/woocommerce-payments/dist/express-checkout.js 15.8 kB +83 B (+1%)
release/woocommerce-payments/dist/index.js 234 kB +80 B (0%)
release/woocommerce-payments/dist/multi-currency-switcher-block.js 61.1 kB -54 B (0%)
release/woocommerce-payments/dist/multi-currency.js 59.2 kB +72 B (0%)
release/woocommerce-payments/dist/order.js 42.5 kB -62 B (0%)
release/woocommerce-payments/dist/payment-gateways.js 40.3 kB +83 B (0%)
release/woocommerce-payments/dist/product-details.js 12.6 kB +66 B (+1%)
release/woocommerce-payments/dist/settings.js 224 kB +254 B (0%)
release/woocommerce-payments/dist/tokenized-express-checkout.js 16.8 kB +71 B (0%)
release/woocommerce-payments/dist/woopay-express-button.js 23.4 kB +58 B (0%)
ℹ️ View Unchanged
Filename Size
release/woocommerce-payments/assets/css/admin.css 1.4 kB
release/woocommerce-payments/assets/css/admin.rtl.css 1.4 kB
release/woocommerce-payments/assets/css/success.css 189 B
release/woocommerce-payments/assets/css/success.rtl.css 190 B
release/woocommerce-payments/dist/blocks-checkout-rtl.css 2.67 kB
release/woocommerce-payments/dist/blocks-checkout.css 2.67 kB
release/woocommerce-payments/dist/cart.js 5.73 kB
release/woocommerce-payments/dist/checkout-rtl.css 1.28 kB
release/woocommerce-payments/dist/checkout.css 1.28 kB
release/woocommerce-payments/dist/express-checkout-rtl.css 236 B
release/woocommerce-payments/dist/express-checkout.css 236 B
release/woocommerce-payments/dist/frontend-tracks.js 854 B
release/woocommerce-payments/dist/index-rtl.css 35.5 kB
release/woocommerce-payments/dist/index.css 35.6 kB
release/woocommerce-payments/dist/multi-currency-analytics.js 1.08 kB
release/woocommerce-payments/dist/multi-currency-rtl.css 4.29 kB
release/woocommerce-payments/dist/multi-currency.css 4.29 kB
release/woocommerce-payments/dist/order-rtl.css 740 B
release/woocommerce-payments/dist/order.css 740 B
release/woocommerce-payments/dist/payment-gateways-rtl.css 1.34 kB
release/woocommerce-payments/dist/payment-gateways.css 1.34 kB
release/woocommerce-payments/dist/plugins-page-rtl.css 386 B
release/woocommerce-payments/dist/plugins-page.css 386 B
release/woocommerce-payments/dist/plugins-page.js 20.1 kB
release/woocommerce-payments/dist/product-details-rtl.css 433 B
release/woocommerce-payments/dist/product-details.css 436 B
release/woocommerce-payments/dist/settings-rtl.css 11.4 kB
release/woocommerce-payments/dist/settings.css 11.4 kB
release/woocommerce-payments/dist/subscription-edit-page.js 703 B
release/woocommerce-payments/dist/subscription-product-onboarding-modal-rtl.css 524 B
release/woocommerce-payments/dist/subscription-product-onboarding-modal.css 524 B
release/woocommerce-payments/dist/subscription-product-onboarding-modal.js 20.2 kB
release/woocommerce-payments/dist/subscription-product-onboarding-toast.js 730 B
release/woocommerce-payments/dist/subscriptions-empty-state-rtl.css 120 B
release/woocommerce-payments/dist/subscriptions-empty-state.css 120 B
release/woocommerce-payments/dist/subscriptions-empty-state.js 19.3 kB
release/woocommerce-payments/dist/tokenized-express-checkout-rtl.css 236 B
release/woocommerce-payments/dist/tokenized-express-checkout.css 236 B
release/woocommerce-payments/dist/tos-rtl.css 235 B
release/woocommerce-payments/dist/tos.css 235 B
release/woocommerce-payments/dist/tos.js 21.8 kB
release/woocommerce-payments/dist/woopay-direct-checkout.js 6.13 kB
release/woocommerce-payments/dist/woopay-rtl.css 4.31 kB
release/woocommerce-payments/dist/woopay.css 4.28 kB
release/woocommerce-payments/dist/woopay.js 71 kB
release/woocommerce-payments/includes/subscriptions/assets/css/plugin-page.css 625 B
release/woocommerce-payments/includes/subscriptions/assets/js/plugin-page.js 814 B
release/woocommerce-payments/vendor/automattic/jetpack-assets/build/i18n-loader.js 2.46 kB
release/woocommerce-payments/vendor/automattic/jetpack-assets/build/jetpack-script-data.js 772 B
release/woocommerce-payments/vendor/automattic/jetpack-assets/src/js/i18n-loader.js 1.02 kB
release/woocommerce-payments/vendor/automattic/jetpack-assets/src/js/script-data.js 69 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/babel.config.js 163 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/identity-crisis.css 2.47 kB
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/identity-crisis.js 14.2 kB
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/identity-crisis.rtl.css 2.47 kB
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/jetpack-connection.css 10 kB
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/jetpack-connection.js 28.4 kB
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/jetpack-connection.rtl.css 10 kB
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/jetpack-sso-admin-create-user.css 198 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/jetpack-sso-admin-create-user.js 280 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/jetpack-sso-admin-create-user.rtl.css 198 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/jetpack-sso-login.css 625 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/jetpack-sso-login.js 333 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/jetpack-sso-login.rtl.css 626 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/jetpack-sso-users.js 424 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/tracks-ajax.js 521 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/dist/tracks-callables.js 585 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/src/sso/jetpack-sso-admin-create-user.css 215 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/src/sso/jetpack-sso-admin-create-user.js 521 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/src/sso/jetpack-sso-login.css 721 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/src/sso/jetpack-sso-login.js 412 B
release/woocommerce-payments/vendor/automattic/jetpack-connection/src/sso/jetpack-sso-users.js 632 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/about.css 1.04 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/admin-empty-state.css 294 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/admin-order-statuses.css 408 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/admin.css 3.59 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/checkout.css 301 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/modal.css 746 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/view-subscription.css 574 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/css/wcs-upgrade.css 414 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/admin-pointers.js 543 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/admin.js 9.4 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/jstz.js 6.78 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/jstz.min.js 3.84 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/meta-boxes-coupon.js 545 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/meta-boxes-subscription.js 2.52 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/moment.js 22.2 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/moment.min.js 11.7 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/payment-method-restrictions.js 1.29 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/admin/wcs-meta-boxes-order.js 507 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/frontend/payment-methods.js 358 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/frontend/single-product.js 428 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/frontend/view-subscription.js 1.38 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/frontend/wcs-cart.js 782 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/modal.js 1.09 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/assets/js/wcs-upgrade.js 1.26 kB
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/build/index.css 391 B
release/woocommerce-payments/vendor/woocommerce/subscriptions-core/build/index.js 3.04 kB

compressed-size-action

I also got rid of the payment method class constants that were referring to another constant to get the ID. That required changes in a few other places to address errors. I added a new get_keywords() method to be able to implement these into the duplicate detection service.
…tion and move that functionality to a util class since it should largely be the same for all payment method definitions
Copy link
Contributor

@frosso frosso left a comment

Choose a reason for hiding this comment

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

The approach you have here is really good and smart - I bet it wasn't easy to create the abstraction to support the use cases we have now.

I think you proved the viability pretty well by having Affirm/Afterpay/Klarna.

Tomorrow I'll take a closer look at better understanding the build steps and the complexity/extendability needs in case we need more use cases for the other "special" payment methods (like Alipay and the different supported currencies at checkout, which are based on the account's country).

Great job so far!

This reverts commit dccdc2d.
There was an issue with `require.context` not being available in Jest since it's a webpack thing. We're now mocking the CreatePaymentMethodIconComponent instead.
@brettshumaker brettshumaker marked this pull request as ready for review February 26, 2025 16:23
@brettshumaker brettshumaker requested a review from frosso February 26, 2025 16:38
@brettshumaker
Copy link
Contributor Author

@frosso this is ready for another review. There have been some significant changes since you last reviewed it.

  1. We're no longer generating the JS types for payment methods. Instead, we're attaching them to the global scope via wp_add_inline_script().
  2. I've removed the payment methods I had already converted (Affirm, Afterpay/Clearpay, and Klarna) to reduce the size of this PR and I will create issues for all payment methods separately. This will also help me to give a "blueprint" PR for converting an existing payment method.

Copy link
Contributor

@frosso frosso left a comment

Choose a reason for hiding this comment

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

Thank you for the additional ping! I also appreciate the smaller PR approach 👍
I think building the definitions from the server-side and dynamically injecting them into the front-end via a JS variable sounds like a good approach 👍

So good that I think aligns pretty well with what I was attempting in my PR before I noticed your refactor here 🤣 #10376

One question: is there some flexibility in this approach to build the supported currencies or supported countries dynamically based on the account's country (for example)? I am asking because I see that the PaymentMethodDefinitionInterface::get_currencies() is a static method.

In your mind, would the payment method need to call \WC_Payments::get_account_service()->get_cached_account_data() statically to get the account data and the account's base country?

Asking because we're using this requirement in Klarna_Payment_Method and Alipay_Payment_Method, for example.

@brettshumaker
Copy link
Contributor Author

is there some flexibility in this approach to build the supported currencies or supported countries dynamically based on the account's country (for example)? I am asking because I see that the PaymentMethodDefinitionInterface::get_currencies() is a static method.

Possibly, though I think there's value in having get_supported_countries/currencies() return the true list and not be based on context. Maybe those methods could accept an $account_country param and, if null, just return the full list and not filter it. Or, to keep the output of those methods consistent, we could make new methods in the interface for something like get_supported_countries/currencies_for_account_country().

In your mind, would the payment method need to call \WC_Payments::get_account_service()->get_cached_account_data() statically to get the account data and the account's base country?

I guess it depends on the answer above. I'm ok with it doing that or accepting an $account_country param.

@brettshumaker
Copy link
Contributor Author

brettshumaker commented Feb 27, 2025

So good that I think aligns pretty well with what I was attempting in my PR before I noticed your refactor here 🤣 10376

@frosso One thing I noticed about this while looking into actual implementation of a new payment method is that this line is getting payment method data from a hard-coded list. Was it going to be part of your (in progress) PR to make that dynamic? Just thinking about how we can get rid of these lists that exist throughout the code base. I think it makes sense for upeCapabilityStatuses to be constant but it would be nice to make upeMethods dynamic.

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.

Implement a centralized payment method definition system
4 participants