← All articles

Adding a Crypto Payment Method to the WooCommerce Checkout Block

October 10, 2026 · 5 min read

To show a payment method in the WooCommerce Checkout block, a classic WC_Payment_Gateway is not enough. You also need a small PHP class that extends AbstractPaymentMethodType, and a JavaScript file that calls registerPaymentMethod(). If the gateway redirects to a hosted payment page, which is common for crypto, your existing process_payment() keeps working unchanged. This guide shows the complete integration as we built it for the Clearqo USDT gateway, plus the pitfalls we hit along the way.

Why doesn’t my gateway appear in the Checkout block?

New WooCommerce stores use the block-based Cart and Checkout by default. The block checkout is a React app that talks to the Store API, so it only lists payment methods that register themselves on the JavaScript side. A gateway that only extends WC_Payment_Gateway still works on the classic shortcode checkout, but in the block checkout it is simply missing. Store owners usually report this as “no payment methods available”.

The three parts of a block integration

  1. Declare compatibility, so WooCommerce doesn’t flag your plugin as incompatible.
  2. A PHP integration class that tells the block which script to load and which settings to pass to it.
  3. A JavaScript file that registers the method with the block’s payment registry.

1. Declare compatibility

add_action( 'before_woocommerce_init', function () {
	if ( class_exists( '\Automattic\WooCommerce\Utilities\FeaturesUtil' ) ) {
		\Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'cart_checkout_blocks', __FILE__, true );
		\Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'custom_order_tables', __FILE__, true ); // HPOS
	}
} );

Only declare HPOS (custom_order_tables) compatibility if you read and write order data through the WC_Order API (get_meta(), update_meta_data()) and never through get_post_meta() on orders.

2. The PHP integration class

add_action( 'woocommerce_blocks_loaded', function () {
	if ( ! class_exists( '\Automattic\WooCommerce\Blocks\Payments\Integrations\AbstractPaymentMethodType' ) ) {
		return;
	}

	final class My_Crypto_Blocks extends \Automattic\WooCommerce\Blocks\Payments\Integrations\AbstractPaymentMethodType {
		protected $name = 'my_crypto'; // must equal your gateway ID

		public function initialize() {
			$this->settings = get_option( 'woocommerce_my_crypto_settings', array() );
		}

		public function is_active() {
			return 'yes' === $this->get_setting( 'enabled' );
		}

		public function get_payment_method_script_handles() {
			wp_register_script(
				'my-crypto-blocks',
				plugins_url( 'assets/blocks.js', __FILE__ ),
				array( 'wc-blocks-registry', 'wc-settings', 'wp-element', 'wp-html-entities' ),
				'1.0.0',
				true
			);
			return array( 'my-crypto-blocks' );
		}

		public function get_payment_method_data() {
			return array(
				'title'       => $this->get_setting( 'title' ),
				'description' => $this->get_setting( 'description' ),
				'supports'    => array( 'products' ),
			);
		}
	}

	add_action( 'woocommerce_blocks_payment_method_type_registration', function ( $registry ) {
		$registry->register( new My_Crypto_Blocks() );
	} );
} );

Whatever get_payment_method_data() returns is passed to your script. Only include what the browser may see: never API keys or secrets.

3. The JavaScript file

No build step is needed. Plain ES5 with wp.element.createElement works and keeps the plugin simple:

( function () {
	'use strict';
	var registry = window.wc && window.wc.wcBlocksRegistry;
	var wcSettings = window.wc && window.wc.wcSettings;
	// Newer WooCommerce: getPaymentMethodData(); older versions: the my_crypto_data setting.
	var settings = ! wcSettings ? {} : ( wcSettings.getPaymentMethodData
		? wcSettings.getPaymentMethodData( 'my_crypto', {} )
		: wcSettings.getSetting( 'my_crypto_data', {} ) ) || {};
	if ( ! registry || ! window.wp || ! window.wp.element ) {
		return;
	}
	var el = window.wp.element.createElement;
	var decode = window.wp.htmlEntities ? window.wp.htmlEntities.decodeEntities : function ( s ) { return s; };
	var title = decode( settings.title || 'Pay with USDT' );
	var Content = function () {
		return el( 'div', null, decode( settings.description || '' ) );
	};

	registry.registerPaymentMethod( {
		name: 'my_crypto',
		label: el( 'span', null, title ),
		ariaLabel: title,
		content: el( Content, null ),
		edit: el( Content, null ),
		canMakePayment: function () { return true; },
		supports: { features: settings.supports || [ 'products' ] }
	} );
} )();

What about process_payment()?

For redirect-style gateways, nothing changes. When the customer clicks Place Order, the Store API creates the order and calls your gateway’s process_payment(). Return the usual array and the block redirects the browser:

return array( 'result' => 'success', 'redirect' => $payment_page_url );

Errors work too. Call wc_add_notice( $message, 'error' ) and return array( 'result' => 'failure' ), and the block shows the notice above the form. Keep customer-facing messages neutral (“temporarily unavailable”) and write the technical reason to an order note for the store owner.

Pitfalls we hit

Testing checklist

Just want USDT in your checkout block?

If you’d rather not build this yourself, the free Clearqo for WooCommerce plugin already supports the Checkout block, the classic checkout and HPOS. Its source code, including the files above, is on GitHub. Setup guide: How to Accept USDT Payments on WooCommerce.

FAQ

Do I need React or a build tool?

No. wp.element.createElement is React’s createElement, and WordPress already loads it. A plain script file is enough for a simple method.

Can a payment method show its own fields in the block?

Yes. Render inputs in your content component and pass their values on through the checkout’s payment-processing events. Redirect gateways usually need no fields at all.

Will the classic checkout keep working?

Yes. The block integration is added alongside your existing gateway class, so the classic checkout is unchanged.

Accept USDT on your website

Paid straight to your own Binance, verified automatically.

Create free account