Skip to content
Santosh Gautam - Full Stack Developer Gurugram India
SANTOSH GAUTAM Full Stack Developer
WooCommerce Dev 10 min read · Updated March 2026 Technical Guide
WooCommerce Payment Gateway Development Guide 2026 — WC_Payment_Gateway, Webhooks, Blocks by Santosh Gautam

WooCommerce Payment Gateway Development — Complete 2026 Technical Guide

Deep technical guide to building a production-ready WooCommerce custom payment gateway using WC_Payment_Gateway, REST APIs, Blocks compatibility, secure SHA-512 hashing and webhook validation — covering PayU, Razorpay & UPI integrations.

Santosh Gautam - Full Stack Developer India

Full Stack Developer · India

WooCommercePHPWordPressPayment APIWebhooks

1. Understanding WooCommerce Payment Gateway Architecture

Before building, understand how WooCommerce handles payment flow. Every custom gateway must integrate with the WC_Payment_Gateway base class and follow this lifecycle:

Customer → Checkout
    ↓
WC_Payment_Gateway::process_payment()
    ↓
Redirect / API Request to Payment Provider
    ↓
Payment Provider Processes Transaction
    ↓
Webhook Callback → Your REST Endpoint
    ↓
Order Status Update (Pending → Processing → Completed)
  • WooCommerce expects a structured response from process_payment().
  • Order state management is critical — Pending → Processing → Completed.
  • Session integrity must be maintained during redirection.
  • Webhooks guarantee asynchronous confirmation — critical for reliability.
  • Security hash validation must occur before order completion.

Always handle the case where a user closes their browser after payment — webhooks ensure order completion even without a browser callback.

2. Extending WC_Payment_Gateway Class

The foundation of any WooCommerce payment gateway is extending the WC_Payment_Gateway abstract class and implementing the required methods.

class WC_Custom_Gateway extends WC_Payment_Gateway {

  public function __construct() {
    $this->id                 = 'custom_gateway';
    $this->method_title       = 'Custom Gateway';
    $this->method_description = 'Pay securely via Custom Gateway';
    $this->has_fields         = true;
    $this->supports           = ['products', 'refunds'];

    // Load settings
    $this->init_form_fields();
    $this->init_settings();

    $this->title       = $this->get_option('title');
    $this->description = $this->get_option('description');

    // Save settings hook
    add_action(
      'woocommerce_update_options_payment_gateways_' . $this->id,
      [$this, 'process_admin_options']
    );
  }

  public function process_payment( $order_id ) {
    $order = wc_get_order( $order_id );

    // Reduce stock, mark pending
    wc_reduce_stock_levels( $order_id );
    $order->update_status( 'pending', 'Awaiting payment confirmation.' );

    return [
      'result'   => 'success',
      'redirect' => $this->get_return_url( $order ),
    ];
  }
}
  • Extend WC_Payment_Gateway base class.
  • Define unique $this->id — used for settings and hooks.
  • Register admin settings with init_form_fields().
  • Implement process_payment() with correct return array.
  • Declare supports array for refunds and product types.

3. Secure Hashing & Checksum Validation (SHA-512)

Payment providers like PayU, Razorpay and Cashfree require a secure hash for request integrity — preventing tampering between your server and the payment gateway.

// Generate hash for payment request
function generate_payment_hash( $merchant_key, $txn_id, $amount, $email, $secret ) {
  $hash_string = implode('|', [
    $merchant_key,
    $txn_id,
    $amount,
    'Product Name',
    $email,
    $secret
  ]);
  return strtolower( hash( 'sha512', $hash_string ) );
}

// Validate webhook hash from payment provider
function validate_webhook_hash( $response, $secret ) {
  $received_hash = $response['hash'];
  $computed_hash = generate_payment_hash(
    $response['key'], $response['txnid'],
    $response['amount'], $response['email'], $secret
  );
  return hash_equals( $computed_hash, $received_hash );
}
  • SHA-512 — prevents request tampering in transit.
  • Validates integrity between your server and payment gateway.
  • Mandatory for PayU India, Razorpay and UPI integrations.
  • Use hash_equals() for timing-safe comparison — prevents timing attacks.
  • Secret key must never be exposed in frontend or logs.

Never use == for hash comparison — always use hash_equals() which is timing-safe and prevents timing-based attacks.

4. Handling Webhooks (IPN — Instant Payment Notification)

Webhooks are the backbone of reliable payment processing. Register a REST API endpoint to receive asynchronous payment confirmations from the gateway.

// Register REST endpoint for webhook
add_action('rest_api_init', function () {
  register_rest_route('custom-gateway/v1', '/webhook', [
    'methods'             => 'POST',
    'callback'            => 'handle_payment_webhook',
    'permission_callback' => '__return_true',
  ]);
});

function handle_payment_webhook( WP_REST_Request $request ) {
  $data = $request->get_json_params() ?: $request->get_body_params();

  // 1. Validate hash
  if ( ! validate_webhook_hash( $data, get_option('wc_custom_secret') ) ) {
    return new WP_REST_Response(['status' => 'invalid_hash'], 400);
  }

  // 2. Get WooCommerce order
  $order = wc_get_order( sanitize_text_field( $data['order_id'] ) );
  if ( ! $order ) {
    return new WP_REST_Response(['status' => 'order_not_found'], 404);
  }

  // 3. Update order status
  if ( $data['status'] === 'success' ) {
    $order->payment_complete( $data['txn_id'] );
    $order->add_order_note('Payment confirmed via webhook. TXN: ' . $data['txn_id']);
  } else {
    $order->update_status('failed', 'Payment failed via webhook.');
  }

  return new WP_REST_Response(['status' => 'ok'], 200);
}
  • Registers a custom REST endpoint at /wp-json/custom-gateway/v1/webhook.
  • Always validate hash before processing — reject invalid requests.
  • Use payment_complete() to properly finalize WooCommerce order.
  • Add order notes for transaction ID tracking and debugging.
  • Ensures payment success even if user closes browser after payment.

5. WooCommerce Blocks Compatibility

WooCommerce is migrating to a React-based Checkout Block. Legacy PHP templates won't render in the new checkout. You must register a JavaScript payment method.

// register-payment-method.js
import { registerPaymentMethod } from '@woocommerce/blocks-registry';
import { decodeEntities } from '@wordpress/html-entities';

const settings = window.wcSettings['custom_gateway_data'] ?? {};

registerPaymentMethod({
  name: 'custom_gateway',
  label: decodeEntities( settings.title ) || 'Custom Gateway',
  content: 
{ decodeEntities( settings.description ) }
, edit:
Custom Gateway payment method
, canMakePayment: () => true, ariaLabel: 'Custom Gateway payment method', supports: { features: settings.supports ?? [], }, });
// PHP — Declare Blocks compatibility
class WC_Custom_Gateway_Blocks extends AbstractPaymentMethodType {
  protected $name = 'custom_gateway';

  public function initialize() {
    $this->settings = get_option('woocommerce_custom_gateway_settings', []);
  }

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

  public function get_payment_method_script_handles() {
    wp_register_script(
      'custom-gateway-blocks',
      plugin_dir_url(__FILE__) . 'build/index.js',
      ['wc-blocks-registry', 'wc-settings'],
      null, true
    );
    return ['custom-gateway-blocks'];
  }
}
  • Required for new React-based WooCommerce Checkout Block.
  • Legacy PHP checkout templates won't render in Blocks checkout.
  • Ensures future WooCommerce compatibility as classic checkout is deprecated.
  • Declare support using AbstractPaymentMethodType.

6. Deployment & Production Checklist

Test in Sandbox Mode

Full payment flow test before going live.

Validate Checksum Logic

SHA-512 hash verified on all requests.

Whitelist Webhook IPs

Only accept from payment provider IPs.

Enable Logging in Testing

WooCommerce logs help debug webhook issues.

Disable Debug Logs in Prod

Logs expose sensitive data in production.

Confirm Refund Callback

Test partial & full refund flow.

Blocks Checkout Tested

Verify payment renders in React Checkout Block.

HTTPS Enforced

Never use HTTP for payment endpoints.

7. Frequently Asked Questions

Yes. Modern WooCommerce gateways must follow strict typing and PHP 8+ compatibility. Use typed properties, return types and avoid deprecated functions.