How to Integrate Custom Payment Gateways with WooCommerce Checkout Block

On my blog you can find a complete tutorial about creating a WooCommerce payment gateway but in the latest versions of WooCommerce (since 8.3 I guess) you may notice that your custom payment method isn’t available in the Checkout block.

For example if you try to deactivate all the payment methods except your custom one on your store, you’ll probably get an error message like this:

Custom payment method is not displaying in the checkout block
Here I am using Storefront theme as an example, but the same error message will appear for any WordPress theme anyway.

But for sure everything is working great when you’re using a legacy [woocommerce_checkout] shortcode.

Yes, it seems like my complete payment gateway tutorial isn’t that complete anymore, but we’re about to change it today by this extra tutorial where I guide you step by step what you should do in order to add the compatibility of your custom WooCommerce payment method for the WooCommerce Cart and Checkout blocks.

That’s what we’re going to achieve by end of this tutorial:

Custom payment gateway integration with WooCommerce checkout blocks

Sure thing, I will also show you some neat extra stuff like adding a custom icon for your payment method.

Server-Side Integration

First things first, let’s begin with the server-side integration, I am pretty sure that many of you guys feel more comfortable developing with PHP than JavaScript + React, so let’s start with simple things.

Registering a block support PHP class

“Block support PHP class” is the PHP class in addition to the main payment gateway class. We are about to register it with the simple code snippet below, kind of similar to what we did when registered our main gateway class in woocommerce_payment_gateways hook.

add_action( 'woocommerce_blocks_loaded', 'rudr_gateway_block_support' );
function rudr_gateway_block_support() {

	// if( ! class_exists( 'Automattic\WooCommerce\Blocks\Payments\Integrations\AbstractPaymentMethodType' ) ) {
	// 	return;
	// }

	// here we're including our "gateway block support class"
	require_once __DIR__ . '/includes/class-wc-misha-gateway-blocks-support.php';

	// registering the PHP class we have just included
	add_action(
		'woocommerce_blocks_payment_method_type_registration',
		function( Automattic\WooCommerce\Blocks\Payments\PaymentMethodRegistry $payment_method_registry ) {
			$payment_method_registry->register( new WC_Misha_Gateway_Blocks_Support );
		}
	);

}

Keep in mind the following:

  • I commented class_exists() condition because we don’t need it anymore since the checkout block is a part of WooCommerce now and not a standalone plugin.
  • Our block support PHP class itself is going to be in a separate file which is class-wc-misha-gateway-blocks-support.php and we’ll take a look at it in the next step.

Block support PHP class

In this part I am creating a WC_Misha_Gateway_Blocks_Support PHP class which extends the the WooCommerce class AbstractPaymentMethodType. At the same time don’t forget that we already have WC_Misha_Gateway which extends WC_Payment_Gateway.

In my case I put it into includes/class-wc-misha-gateway-blocks-support.php.

<?php
use Automattic\WooCommerce\Blocks\Payments\Integrations\AbstractPaymentMethodType;

final class WC_Misha_Gateway_Blocks_Support extends AbstractPaymentMethodType {
	
	private $gateway;
	
	protected $name = 'misha'; // payment gateway id

	public function initialize() {
		// get payment gateway settings
		$this->settings = get_option( "woocommerce_{$this->name}_settings", array() );
		
		// you can also initialize your payment gateway here
		// $gateways = WC()->payment_gateways->payment_gateways();
		// $this->gateway  = $gateways[ $this->name ];
	}

	public function is_active() {
		return ! empty( $this->settings[ 'enabled' ] ) && 'yes' === $this->settings[ 'enabled' ];
	}

	public function get_payment_method_script_handles() {

		wp_register_script(
			'wc-misha-blocks-integration',
			plugin_dir_url( __DIR__ ) . 'build/index.js',
			array(
				'wc-blocks-registry',
				'wc-settings',
				'wp-element',
				'wp-html-entities',
			),
			null, // or time() or filemtime( ... ) to skip caching
			true
		);

		return array( 'wc-misha-blocks-integration' );

	}

	public function get_payment_method_data() {
		return array(
			'title'        => $this->get_setting( 'title' ),
			// almost the same way:
			// 'title'     => isset( $this->settings[ 'title' ] ) ? $this->settings[ 'title' ] : 'Default value';
			'description'  => $this->get_setting( 'description' ),
			// if $this->gateway was initialized on line 15
			// 'supports'  => array_filter( $this->gateway->supports, [ $this->gateway, 'supports' ] ),

			// example of getting a public key
			// 'publicKey' => $this->get_publishable_key(),
		);
	}

	//private function get_publishable_key() {
	//	$test_mode   = ( ! empty( $this->settings[ 'testmode' ] ) && 'yes' === $this->settings[ 'testmode' ] );
	//	$setting_key = $test_mode ? 'test_publishable_key' : 'publishable_key';
	//	return ! empty( $this->settings[ $setting_key ] ) ? $this->settings[ $setting_key ] : '';
	//}

}

First of all let’s take a look at class properties and methods.

Properties:

  • $name – this is a payment gateway ID from this step.
  • $gateway – we can store an instance of the payment gateway object here, but it is not like a required thing, so I commented this part in my code.

Methods:

  • is_active(),
  • get_payment_method_script_handles() – that’s where we include a JavaScript file which contains the client-side part of the integration.
  • get_payment_method_data() – provide all the necessary data you’re going to use on the front-end as an associative array.

You can also use index.asset.php to get a script version and dependencies from.

public function get_payment_method_script_handles() {

	$asset_path   = plugin_dir_path( __DIR__ ) . 'build/index.asset.php';
	$version      = null;
	$dependencies = array();
	if( file_exists( $asset_path ) ) {
		$asset        = require $asset_path;
		$version      = isset( $asset[ 'version' ] ) ? $asset[ 'version' ] : $version;
		$dependencies = isset( $asset[ 'dependencies' ] ) ? $asset[ 'dependencies' ] : $dependencies;
	}
	
	wp_register_script( 
		'wc-misha-blocks-integration', 
		plugin_dir_url( __DIR__ ) . 'build/index.js', 
		$dependencies, 
		$version, 
		true 
	);

	return array( 'wc-misha-blocks-integration' );

}

Declare compatibility

This part is usually useful when you would like to let your users know that your payment method is not compatible with the WooCommerce Checkout block.

Users will be notified about it when they try to edit the Checkout page in Gutenberg:

Notification that a custom payment method does not support the WooCommerce checkout block.

And here is how to do that:

add_action( 'before_woocommerce_init', 'rudr_cart_checkout_blocks_compatibility' );

function rudr_cart_checkout_blocks_compatibility() {

    if( class_exists( '\Automattic\WooCommerce\Utilities\FeaturesUtil' ) ) {
        \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility(
				'cart_checkout_blocks',
				__FILE__,
				false // true (compatible, default) or false (not compatible)
			);
    }
		
}

Client-Side Integration

Setting up a project

Once again, I would like to keep the things super-simple in this tutorial, so I am just going to use @wordpress/scripts and that’s all.

In our build for sure you can go further and configure WooCommerce hybrid build, so you can use import { registerPaymentMethod } from ....

That’s how my folder structure looks like:

Folder structure of a custom payment gateway with WooCommerce checkout block support.

Register a custom payment method for WooCommerce Checkout Block

Below is the /src/index.js file in case you have doubts.

import { decodeEntities } from '@wordpress/html-entities';

const { registerPaymentMethod } = window.wc.wcBlocksRegistry
const { getSetting } = window.wc.wcSettings

const settings = getSetting( 'misha_data', {} )

const label = decodeEntities( settings.title )

const Content = () => {
	return decodeEntities( settings.description || '' )
}

const Label = ( props ) => {
	const { PaymentMethodLabel } = props.components
	return <PaymentMethodLabel text={ label } />
}

registerPaymentMethod( {
	name: "misha",
	label: <Label />,
	content: <Content />,
	edit: <Content />,
	canMakePayment: () => true,
	ariaLabel: label,
	supports: {
		features: settings.supports,
	}
} )

Probably it’d be a great idea to talk about registerPaymentMethod() in details and also about registerExpressPaymentMethod(), but I think we’re going to take a deeper look on a specific examples in the next tutorials on my blog.

Finally! 🎉

Custom payment gateway integration with WooCommerce checkout blocks

In case you’re wondering where the payment method title and description come from:

Add a payment method icon

Since I promised you more examples and probably you don’t want to wait till the next tutorials, so let’s start with this one.

My goal right now is to display an icon near my custom payment gateway title in the WooCommerce Checkout block:

Add a logo to the custom payment gateway in the WooCommerce checkout block.

First of all let’s modify our block support PHP class, specifically its get_payment_method_data(), we’re just about to provide one more parameter there:

public function get_payment_method_data() {
	return array(
		'title'        => $this->get_setting( 'title' ),
		'description'  => $this->get_setting( 'description' ),
		'icon'         => plugin_dir_url( __DIR__ ) . 'assets/icon.png',
		
		...

Then I recommend to create another React component for it:

const Icon = () => {
	return settings.icon 
		? <img src={settings.icon} style={{ float: 'right', marginRight: '20px' }} /> 
		: ''
}

const Label = () => {
	return (
        <span style={{ width: '100%' }}>
            {label}
            <Icon />
        </span>
    )
}

If the icon image URL isn’t provided, <img> tag won’t be displayed, great!

Misha Rudrastyh

Misha Rudrastyh

Hey guys and welcome to my website. For more than 10 years I've been doing my best to share with you some superb WordPress guides and tips for free.

Need some developer help? Contact me

Follow me on X