woocommerce-payments
WooCommerce Payment Gateway Development
Reference for building payment gateways with classic and block checkout support.
1. Gateway Registration
add_filter( 'woocommerce_payment_gateways', function ( array $gateways ): array {
$gateways[] = 'MCE_Gateway';
return $gateways;
} );
Extend WC_Payment_Gateway and implement process_payment() and optionally
process_refund().
2. Supported Features
| Feature | Description |
|---|---|
products |
Standard product payments |
refunds |
Admin refund processing |
subscriptions |
WooCommerce Subscriptions support |
tokenization |
Saved payment methods |
pre-orders |
Pre-order charge scheduling |
3. Gateway Class Structure
Key methods to implement:
| Method | Purpose |
|---|---|
__construct() |
Set $this->id, $this->supports, call init_form_fields() and init_settings() |
init_form_fields() |
Define admin settings (enabled, title, description, API keys) |
process_payment( $order_id ) |
Process payment — return ['result' => 'success', 'redirect' => $url] or ['result' => 'failure'] |
process_refund( $order_id, $amount, $reason ) |
Process refund — return true or WP_Error |
validate_fields() |
Validate checkout fields — call wc_add_notice() on errors, return bool |
Payment Flow
Customer clicks "Place Order"
→ validate_fields()
→ process_payment( $order_id )
→ Call external API
→ $order->payment_complete()
→ WC()->cart->empty_cart()
→ Return redirect to thank-you page
Tokenization (Saved Cards)
Extend WC_Payment_Gateway_CC (credit cards) or WC_Payment_Gateway_eCheck for
built-in tokenization UI. Add 'tokenization' to $this->supports and implement
add_payment_method().
4. Block Checkout Integration
The Block Checkout (default since WooCommerce 8.3) requires separate registration
from the classic WC_Payment_Gateway.
Architecture
Classic Checkout Block Checkout
───────────────── ─────────────────
WC_Payment_Gateway + AbstractPaymentMethodType (server)
registerPaymentMethod() (client JS)
Server-Side: AbstractPaymentMethodType
| Method | Purpose |
|---|---|
initialize() |
Load settings from get_option() |
is_active() |
Return whether gateway is enabled |
get_payment_method_script_handles() |
Register and return JS handles |
get_payment_method_data() |
Return title, description, supports array for JS |
Register with:
add_action( 'woocommerce_blocks_payment_method_type_registration', function ( $registry ): void {
$registry->register( new MCE_Block_Gateway() );
} );
Client-Side: registerPaymentMethod
const { registerPaymentMethod } = wc.wcBlocksRegistry;
registerPaymentMethod( {
name: 'mce_gateway',
label: 'My Gateway',
content: React.createElement( 'div', null, 'Pay with My Gateway.' ),
edit: React.createElement( 'div', null, '[My Gateway]' ),
canMakePayment: () => true,
ariaLabel: 'My Gateway',
supports: { features: [ 'products' ] },
} );
Declare Compatibility
add_action( 'before_woocommerce_init', function (): void {
if ( class_exists( '\Automattic\WooCommerce\Utilities\FeaturesUtil' ) ) {
\Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility(
'cart_checkout_blocks', __FILE__, true
);
}
} );
5. Common Mistakes
| Mistake | Fix |
|---|---|
| Only implementing classic checkout | Register AbstractPaymentMethodType for block checkout too |
| Not declaring block checkout compatibility | Add FeaturesUtil::declare_compatibility('cart_checkout_blocks', ...) |
Missing validate_fields() |
Always validate before process_payment() |
Not calling $order->payment_complete() |
Required to trigger order status change and emails |
Forgetting WC()->cart->empty_cart() |
Cart persists after payment without this |
| Hard-coding currency/amount format | Use $order->get_total() and WC formatting functions |
Related Skills
- woocommerce-setup — Extension architecture, plugin headers, FeaturesUtil
- woocommerce-data — Order/product CRUD, HPOS, Store API, REST API
- woocommerce-hooks — Order lifecycle hooks, checkout hooks, email hooks
More from peixotorms/odinlayer-skills
elementor-development
Use when building Elementor addons, creating custom widgets, or managing Elementor components. Covers Widget_Base class (get_name, get_title, get_icon, register_controls, render, content_template), widget registration via elementor/widgets/register hook, addon structure and plugin header, wp_enqueue_script for widget assets, get_script_depends, get_style_depends, inline editing toolbars, custom widget categories, manager registration (register/unregister), selector tokens ({{WRAPPER}}), deprecation handling, and Elementor CLI commands.
65elementor-hooks
Use when hooking into Elementor lifecycle events, injecting controls, filtering widget output, or using the JS APIs. Covers elementor/init, elementor/element/before_section_end, elementor/element/after_section_end, elementor/widget/render_content filter, elementor/frontend/after_enqueue_styles, frontend JS hooks (elementorFrontend.hooks, frontend/element_ready), editor JS hooks (elementor.hooks), $e.commands API ($e.run, $e.commands.register), $e.routes, $e.hooks (registerUIBefore, registerUIAfter), control injection patterns, CSS file hooks, forms hooks (Pro), and query filters.
26elementor-themes
Use when building Elementor-compatible themes, registering theme locations, creating dynamic tags, or extending the Finder. Covers register_location, theme_builder locations, elementor_theme_do_location, Theme_Document and theme conditions, Tag_Base for dynamic tags (register_tag, get_value, render), Finder extension (Category_Base, register via elementor/finder/register), Context_Menu customization (elements/context-menu/groups filter), Hello Elementor theme (elementor-hello-theme, hello_elementor_* filters), and hosting page cache integration hooks.
25elementor-controls
Use when adding controls to Elementor widgets, creating custom controls, or referencing control type parameters. Covers add_control with types (TEXT, SELECT, SLIDER, COLOR, MEDIA, REPEATER, CHOOSE, NUMBER, SWITCHER, URL, ICONS), TYPOGRAPHY and BACKGROUND group controls, BORDER, BOX_SHADOW group controls, add_responsive_control, add_group_control, CSS selectors ({{WRAPPER}}, {{VALUE}}), condition and conditions for conditional display, dynamic content tags, POPOVER_TOGGLE, and global styles integration.
16elementor-forms
Use when creating custom Elementor form actions, custom form field types, form validation, or processing form submissions. Covers Elementor Pro forms (ElementorPro\Modules\Forms), Action_Base (get_name, get_label, run, register_settings_section, on_export), after_submit processing, Field_Base (field_type, render field HTML, validation callback, update_controls), content_template for editor preview, form action registration, export_type handling, update_record patterns, elementor_pro/forms/validation hook, email filters, and webhook response handling.
12flyonui
Use when building with FlyonUI — Tailwind CSS component library with CSS classes and optional JS plugins. Covers CSS component classes, JS plugin system (accordion, carousel, collapse, combobox, datatable, dropdown, select, tabs, tooltip, etc.), theming, installation, class reference, and plugin initialization via MCP tools.
9