Cart and Checkout – Filtering payment methods in the Checkout block
The problem
You’re an extension developer, and your extension is conditionally hiding payment gateways on the checkout step. You need to be able to hide payment gateways on the Checkout block using a front-end extensibility point.
The solution
WooCommerce Blocks provides a function called registerPaymentMethodExtensionCallbacks
which allows extensions to register callbacks for specific payment methods to determine if they can make payments.
Importing
Aliased import
import { registerPaymentMethodExtensionCallbacks } from '@woocommerce/blocks-registry';
wc global
const { registerPaymentMethodExtensionCallbacks } = window.wc.wcBlocksRegistry;
Signature
Parameter | Description | Type |
---|---|---|
namespace |
Unique string to identify your extension. Choose something that eliminates a name collision with another extension. | string |
callbacks |
An object containing callbacks registered for different payment methods | Record< string, CanMakePaymentExtensionCallback > |
Read more below about callbacks.
Extension namespace collision
When trying to register callbacks under an extension namespace already used with registerPaymentMethodExtensionCallbacks
, the registration will be aborted and you will be notified that you are not using a unique namespace. This will be shown in the JavaScript console.
Usage example
registerPaymentMethodExtensionCallbacks( 'my-hypothetical-extension', {
cod: ( arg ) => {
return arg.shippingAddress.city === 'Berlin';
},
cheque: ( arg ) => {
return false;
},
} );
Callbacks registered for payment methods
Extensions can register only one callback per payment method:
payment_method_name: ( arg ) => {...}
payment_method_name
is the value of the name property used when the payment method was registered with WooCommerce Blocks.
The registered callbacks are used to determine whether the corresponding payment method should be available as an option for the shopper. The function will be passed an object containing data about the current order.
type CanMakePaymentExtensionCallback = (
cartData: CanMakePaymentArgument
) => boolean;
Each callback will have access to the information bellow
interface CanMakePaymentArgument {
cart: Cart;
cartTotals: CartTotals;
cartNeedsShipping: boolean;
billingAddress: CartResponseBillingAddress;
shippingAddress: CartResponseShippingAddress;
selectedShippingMethods: Record< string, unknown >;
paymentRequirements: Array< string >;
}
If you need data that is not available in the parameter received by the callback you can consider exposing your data in the Store API.
Filtering payment methods using requirements
The problem
Your extension has added functionality to your store in such a way that only specific payment gateways can process orders that contain certain products.
Using the example of Bookings
if the shopper adds a Bookable
product to their cart, for example a stay in a hotel, and you, the merchant, want to confirm all bookings before taking payment. You would still need to capture the customer’s checkout details but not their payment method at that point.
The solution
To allow the shopper to check out without entering payment details, but still require them to fill in the other checkout details it is possible to create a new payment method which will handle carts containing a Bookable
item.
Using the supports
configuration of payment methods it is possible to prevent other payment methods (such as credit card, PayPal etc.) from being used to check out, and only allow the one your extension has added to appear in the Checkout block.
For more information on how to register a payment method with WooCommerce Blocks, please refer to the Payment method integration documentation.
Basic usage
Following the documentation for registering payment methods linked above, you should register your payment method with a unique supports
feature, for example booking_availability
. This will be used to isolate it and prevent other methods from displaying.
First you will need to create a function that will perform the checks on the cart to determine what the specific payment requirements of the cart are. Below is an example of doing this for our Bookable
products.
Then you will need to use the register_payment_requirements
on the ExtendSchema
class to tell the Checkout block to execute a callback to check for requirements.
Putting it all together
This code example assumes there is some class called Pseudo_Booking_Class
that has the cart_contains_bookable_product
method available. The implementation of this method is not relevant here.
/**
* Check the content of the cart and add required payment methods.
*
*
* @return array list of features required by cart items.
*/
function inject_payment_feature_requirements_for_cart_api() {
// Cart contains a bookable product, so return an array containing our requirement of booking_availability.
if ( Pseudo_Booking_Class::cart_contains_bookable_product() ) {
return array( 'booking_availability' );
}
// No bookable products in the cart, no need to add anything.
return array();
}
To summarise the above: if there’s a bookable product in the cart then this function will return an array containing booking_availability
, otherwise it will return an empty array.
The next step will tell the ExtendSchema
class to execute this callback when checking which payment methods to display.
To do this you could use the following code:
add_action('woocommerce_blocks_loaded', function() {
woocommerce_store_api_register_payment_requirements(
array(
'data_callback' => 'inject_payment_feature_requirements_for_cart_api',
)
);
});
It is important to note the comment in this code block, you must not instantiate your own version of ExtendSchema
.
If you’ve added your payment method correctly with the correct supports
values then when you reach the checkout page with a Bookable
item in your cart, any method that does not supports
the booking_availability
requirement should not display, while yours, the one that does support this requirement will display.
Last updated: July 10, 2024