Payment Gateway Module¶
The Payment Gateway module provides the infrastructure for building WooCommerce payment gateway plugins. It includes base classes for payment plugins, gateways, and transaction handling.
Overview¶
The Payment Gateway module handles:
- Payment gateway plugin base class
- Gateway registration and management
- Transaction processing
- Tokenization support
- Admin order and user handlers
- My Payment Methods integration
Key Classes¶
| Class | File | Purpose |
|---|---|---|
Woodev_Payment_Gateway_Plugin |
payment-gateway/class-payment-gateway-plugin.php |
Base payment plugin class |
Woodev_Payment_Gateway |
payment-gateway/class-payment-gateway.php |
Abstract base gateway class |
Woodev_Payment_Gateway_Direct |
payment-gateway/class-payment-gateway-direct.php |
Direct (onsite) gateway class |
Woodev_Payment_Gateway_Hosted |
payment-gateway/class-payment-gateway-hosted.php |
Hosted (offsite) gateway class |
Woodev_Payment_Gateway_Admin_Order |
payment-gateway/admin/class-payment-gateway-admin-order.php |
Admin order handler |
Woodev_Payment_Gateway_Admin_User_Handler |
payment-gateway/admin/class-payment-gateway-admin-user-handler.php |
Admin user handler |
Woodev_Payment_Gateway_My_Payment_Methods |
payment-gateway/class-payment-gateway-my-payment-methods.php |
Customer payment methods |
Woodev_Payment_Gateway_Payment_Form |
payment-gateway/class-payment-gateway-payment-form.php |
Checkout payment form |
Woodev_Payment_Gateway_Payment_Token |
payment-gateway/payment-tokens/class-payment-gateway-payment-token.php |
Payment token representation |
Woodev_Payment_Gateway_Payment_Tokens_Handler |
payment-gateway/payment-tokens/class-payment-gateway-payment-tokens-handler.php |
Token storage and retrieval |
Creating a Payment Plugin¶
Basic Plugin Structure¶
<?php
/**
* Plugin Name: My Payment Gateway
* Plugin URI: https://example.com/my-payment
* Description: WooCommerce payment gateway
* Version: 1.0.0
* Author: Your Name
* Text Domain: my-payment
* Requires at least: 5.9
* Requires PHP: 7.4
* WC requires at least: 5.6
*/
defined( 'ABSPATH' ) || exit;
// Include bootstrap
if ( ! class_exists( 'Woodev_Plugin_Bootstrap' ) ) {
require_once plugin_dir_path( __FILE__ ) . 'woodev/bootstrap.php';
}
// Register plugin
add_action( 'plugins_loaded', 'init_my_payment', 0 );
function init_my_payment() {
Woodev_Plugin_Bootstrap::instance()->register_plugin(
'1.4.0',
'My Payment Gateway',
__FILE__,
'my_payment_init',
[
'minimum_wc_version' => '8.0',
'minimum_wp_version' => '5.9',
'is_payment_gateway' => true, // Important!
]
);
}
function my_payment_init() {
require_once plugin_dir_path( __FILE__ ) . 'includes/class-my-payment-plugin.php';
return My_Payment_Plugin::instance();
}
Plugin Class¶
<?php
defined( 'ABSPATH' ) || exit;
final class My_Payment_Plugin extends Woodev_Payment_Gateway_Plugin {
private static $instance;
public static function instance(): self {
if ( null === self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
public function __construct() {
parent::__construct(
'my-payment',
'1.0.0',
[
'text_domain' => 'my-payment',
'gateways' => [
'my_credit_card' => 'My_Credit_Card_Gateway',
],
'currencies' => [ 'USD', 'EUR', 'GBP' ],
'supports' => [
Woodev_Payment_Gateway_Plugin::FEATURE_CAPTURE_CHARGE,
Woodev_Payment_Gateway_Plugin::FEATURE_CUSTOMER_ID,
Woodev_Payment_Gateway_Plugin::FEATURE_MY_PAYMENT_METHODS,
],
'require_ssl' => true,
]
);
}
protected function get_file(): string {
return __FILE__;
}
public function get_plugin_name(): string {
return __( 'My Payment Gateway', 'my-payment' );
}
public function get_download_id(): int {
return 0;
}
}
Creating Payment Gateways¶
Gateways extend Woodev_Payment_Gateway_Direct (for onsite payment processing) or Woodev_Payment_Gateway_Hosted (for offsite/redirect payment processing). Both inherit from Woodev_Payment_Gateway, which extends WC_Payment_Gateway.
The gateway constructor signature is __construct( $id, $plugin, $args ). The framework handles form fields, settings, and payment form rendering automatically. You provide gateway-specific settings by overriding get_method_form_fields().
Credit Card Gateway¶
<?php
class My_Credit_Card_Gateway extends Woodev_Payment_Gateway_Direct {
/**
* Returns gateway-specific form fields.
*
* These are merged with common fields (enabled, title, description,
* environment, debug mode) that the framework provides automatically.
*
* @since 1.0.0
*
* @return array
*/
protected function get_method_form_fields() {
return [
'api_key' => [
'title' => __( 'API Key', 'my-payment' ),
'type' => 'text',
'description' => __( 'Your API key', 'my-payment' ),
'default' => '',
],
'api_secret' => [
'title' => __( 'API Secret', 'my-payment' ),
'type' => 'password',
'description' => __( 'Your API secret', 'my-payment' ),
'default' => '',
],
];
}
/**
* Returns the API instance for this gateway.
*
* @since 1.0.0
*
* @return My_Payment_API
*/
public function get_api() {
if ( ! isset( $this->api ) ) {
$this->api = new My_Payment_API( $this );
}
return $this->api;
}
}
Note: The framework's
Woodev_Payment_Gatewaybase class already providespayment_fields()rendering viaWoodev_Payment_Gateway_Payment_Form, andWoodev_Payment_Gateway_Directalready implementsprocess_payment()with full transaction handling, token management, and error handling. You do not need to override these unless you require custom behavior.
Transaction Handling¶
Capture Charge¶
To enable capture charge support, include Woodev_Payment_Gateway_Plugin::FEATURE_CAPTURE_CHARGE in the plugin's supports array. The framework's Woodev_Payment_Gateway_Admin_Order class automatically adds a capture button to the admin order screen when this feature is enabled.
<?php
parent::__construct(
'my-payment',
'1.0.0',
[
'gateways' => [
'my_credit_card' => 'My_Credit_Card_Gateway',
],
'supports' => [
Woodev_Payment_Gateway_Plugin::FEATURE_CAPTURE_CHARGE,
],
]
);
Manual Capture¶
The Woodev_Payment_Gateway_Admin_Order handles capture via AJAX automatically. To capture programmatically, use the gateway's API instance:
<?php
$gateway = My_Payment_Plugin::instance()->get_gateway( 'my_credit_card' );
$api = $gateway->get_api();
try {
$response = $api->capture( $transaction_id, $order->get_total() );
$order->add_order_note( __( 'Charge captured', 'my-payment' ) );
} catch ( Woodev_API_Exception $e ) {
$order->add_order_note(
sprintf( __( 'Capture failed: %s', 'my-payment' ), $e->getMessage() )
);
}
Tokenization¶
The framework uses its own tokenization system through Woodev_Payment_Gateway_Payment_Token and Woodev_Payment_Gateway_Payment_Tokens_Handler (not WooCommerce's WC_Payment_Token classes). Tokens are stored in user meta, keyed by environment.
Enable tokenization by adding Woodev_Payment_Gateway::FEATURE_TOKENIZATION to your gateway's supported features.
Working with Tokens¶
<?php
// Get the token handler from the gateway.
$gateway = My_Payment_Plugin::instance()->get_gateway( 'my_credit_card' );
$token_handler = $gateway->get_payment_tokens_handler();
// Retrieve all tokens for a user in the current environment.
$tokens = $token_handler->get_tokens( $user_id );
// Add a new token.
$token = new Woodev_Payment_Gateway_Payment_Token( $remote_token_id, [
'type' => 'credit_card',
'last_four' => '4242',
'card_type' => 'visa',
'exp_month' => '12',
'exp_year' => '2028',
] );
$token_handler->add_token( $user_id, $token );
// Update an existing token.
$token_handler->update_token( $user_id, $token );
// Delete a token.
$token_handler->delete_token( $user_id, $token );
Admin Handlers¶
Order Handler¶
Woodev_Payment_Gateway_Admin_Order is instantiated internally by Woodev_Payment_Gateway_Plugin and is not meant to be extended. It automatically provides:
- Capture charge button (when
FEATURE_CAPTURE_CHARGEis supported) - Bulk capture order action
- AJAX capture processing
The handler receives the plugin instance via its constructor:
<?php
// The framework instantiates this automatically in Woodev_Payment_Gateway_Plugin::init_admin().
// Access it via the plugin:
$admin_order_handler = My_Payment_Plugin::instance()->get_admin_order_handler();
User Handler¶
Woodev_Payment_Gateway_Admin_User_Handler is also instantiated internally. It automatically provides:
- Customer ID fields on the admin user profile page (when
FEATURE_CUSTOMER_IDis supported) - Token editor for each tokenized gateway
- Save/update hooks for profile fields
<?php
// The framework instantiates this automatically in Woodev_Payment_Gateway_Plugin::init_admin().
// Access it via the plugin:
$admin_user_handler = My_Payment_Plugin::instance()->get_admin_user_handler();
My Payment Methods¶
Woodev_Payment_Gateway_My_Payment_Methods extends Woodev_Script_Handler and renders the My Payment Methods table on the My Account page. It is initialized automatically when FEATURE_MY_PAYMENT_METHODS is included in the plugin's supports array.
The class receives the plugin instance via its constructor and handles:
- Loading and displaying saved tokens for all tokenized gateways
- Token editing (nickname) via AJAX
- Token deletion
- Setting a default payment method
- Enqueuing required scripts and styles
Customizing My Payment Methods¶
To customize, override get_my_payment_methods_instance() in your plugin class:
<?php
class My_Payment_Plugin extends Woodev_Payment_Gateway_Plugin {
/**
* Returns the My Payment Methods instance.
*
* @since 1.0.0
*
* @return My_Payment_Methods
*/
protected function get_my_payment_methods_instance() {
return new My_Payment_Methods( $this );
}
}
<?php
class My_Payment_Methods extends Woodev_Payment_Gateway_My_Payment_Methods {
/**
* Customizes the table headers.
*
* @since 1.0.0
*
* @return array
*/
protected function get_table_headers() {
$headers = parent::get_table_headers();
// Add a custom column.
$headers['custom'] = __( 'Status', 'my-payment' );
return $headers;
}
}
API Client¶
The framework provides Woodev_API_Base as the abstract base for all API communication. Key points:
get_plugin()is abstract and must return the plugin instanceget_new_request( $args )is abstract and must return aWoodev_API_Requestinstanceperform_request( $request )is protected and returns aWoodev_API_Responseobject (not raw data)get_api_id()is not abstract; by default it returns the plugin ID- Request/response logging is handled automatically via the
woodev_{plugin_id}_api_request_performedaction
Payment API¶
<?php
class My_Payment_API extends Woodev_API_Base {
const API_URL = 'https://api.mypayment.com';
/** @var Woodev_Payment_Gateway gateway instance */
private $gateway;
/**
* Constructor.
*
* @since 1.0.0
*
* @param My_Credit_Card_Gateway $gateway the gateway instance
*/
public function __construct( $gateway ) {
$this->gateway = $gateway;
$this->set_request_content_type_header( 'application/json' );
$this->set_request_accept_header( 'application/json' );
}
/**
* Returns the plugin instance.
*
* @since 1.0.0
*
* @return Woodev_Payment_Gateway_Plugin
*/
protected function get_plugin() {
return $this->gateway->get_plugin();
}
/**
* Returns a new request object.
*
* @since 1.0.0
*
* @param array $args request arguments
* @return My_Payment_API_Request
*/
protected function get_new_request( $args = [] ) {
return new My_Payment_API_Request( self::API_URL, $args );
}
/**
* Charge payment.
*
* @since 1.0.0
*
* @param array $data payment data
* @return Woodev_API_Response
* @throws Woodev_API_Exception on API error
*/
public function charge( array $data ) {
$request = $this->get_new_request( [
'method' => 'POST',
'path' => '/v1/charges',
] );
$request->set_data( $data );
return $this->perform_request( $request );
}
/**
* Capture a previously authorized charge.
*
* @since 1.0.0
*
* @param string $transaction_id transaction identifier
* @param float $amount amount to capture
* @return Woodev_API_Response
* @throws Woodev_API_Exception on API error
*/
public function capture( string $transaction_id, float $amount ) {
$request = $this->get_new_request( [
'method' => 'POST',
'path' => '/v1/charges/' . $transaction_id . '/capture',
] );
$request->set_data( [ 'amount' => $amount ] );
return $this->perform_request( $request );
}
}
Complete Example¶
<?php
/**
* Plugin Name: My Payment Gateway
* Version: 1.0.0
* Requires PHP: 7.4
*/
defined( 'ABSPATH' ) || exit;
// Include the framework bootstrap.
if ( ! class_exists( 'Woodev_Plugin_Bootstrap' ) ) {
require_once plugin_dir_path( __FILE__ ) . 'woodev/bootstrap.php';
}
// Register plugin with the framework bootstrap.
Woodev_Plugin_Bootstrap::instance()->register_plugin(
'1.4.0',
'My Payment Gateway',
__FILE__,
'my_payment_init',
[
'minimum_wc_version' => '8.0',
'minimum_wp_version' => '5.9',
'is_payment_gateway' => true,
]
);
/**
* Initializes the plugin.
*
* @return My_Payment_Plugin
*/
function my_payment_init() {
require_once __DIR__ . '/includes/class-my-payment-plugin.php';
require_once __DIR__ . '/includes/class-my-credit-card-gateway.php';
require_once __DIR__ . '/includes/class-my-payment-api.php';
return My_Payment_Plugin::instance();
}
Best Practices¶
1. Use SSL for Production¶
2. Log All Transactions¶
<?php
// Use the plugin's log() method. It writes to WooCommerce logs.
$this->get_plugin()->log( 'Processing payment for order #' . $order_id );
try {
$response = $this->get_api()->charge( $data );
$this->get_plugin()->log( 'Payment successful' );
} catch ( Woodev_API_Exception $e ) {
$this->get_plugin()->log( 'Payment failed: ' . $e->getMessage() );
throw $e;
}
3. Handle Errors Gracefully¶
<?php
try {
$response = $api->charge( $data );
} catch ( Woodev_API_Exception $e ) {
wc_add_notice( __( 'Payment failed. Please try again.', 'my-payment' ), 'error' );
return [ 'result' => 'failure' ];
}
4. Support Tokenization¶
Tokenization is enabled via the gateway constructor args, not the WC $supports array:
<?php
// In your gateway constructor args, or by calling add_support():
$this->add_support( Woodev_Payment_Gateway::FEATURE_TOKENIZATION );
5. Add Transaction Links¶
Override get_transaction_url() (from WC_Payment_Gateway) in your gateway class, and include 'transaction_link' in your plugin's supports array:
<?php
// In your gateway class:
public function get_transaction_url( $order ) {
$this->view_transaction_url = 'https://dashboard.mypayment.com/tx/%s';
return parent::get_transaction_url( $order );
}
Related Documentation¶
- Core Framework — Plugin base class
- REST API — REST endpoints
- Admin Module — Admin pages
For more information, see README.md.