How to Write a Custom Payment Plugin for WooCommerce: A Comprehensive Guide
Introduction
WooCommerce, the leading e-commerce platform built on WordPress, offers unparalleled flexibility. One of its greatest strengths lies in its extensibility through plugins. While WooCommerce offers numerous built-in payment gateways and integrates with countless third-party solutions, sometimes you need something unique. This is where creating a custom payment plugin becomes essential. Whether you need to connect to a specialized local payment processor, handle unusual transaction flows, or simply want to streamline your Explore this article on How To Test Woocommerce Webhook checkout process, this guide will provide you with a step-by-step walkthrough of creating your own WooCommerce payment gateway plugin. This guide will equip you with the knowledge to create a secure and functional solution that perfectly fits your business needs.
Building Your Custom WooCommerce Payment Gateway
This section details the crucial steps involved in developing your custom payment gateway. We’ll cover plugin setup, defining the gateway class, handling payment forms, and processing transactions.
#### 1. Setting Up Your Plugin
First, create a new directory for your plugin within the `wp-content/plugins/` directory. Let’s name it `woocommerce-custom-payment-gateway`. Inside this directory, create your main plugin file, named something like `woocommerce-custom-payment-gateway.php`. This file contains the plugin header and the necessary hooks to initialize your payment gateway.
<?php /**
- Plugin Name: WooCommerce Custom Payment Gateway
- Plugin URI: https://example.com/
- Description: A custom payment gateway for WooCommerce.
- Version: 1.0.0
- Author: Your Name
- Author URI: https://example.com/ */
- Plugin Header: This provides essential Learn more about How To Grant Access To Woocommerce information about your plugin.
- `ABSPATH` Check: Prevents direct access to the file for security.
- `custom_payment_gateway_load()`: This function is hooked into the `plugins_loaded` action, ensuring it runs after WooCommerce is loaded. It includes the main gateway class file and adds your gateway to the list of available gateways.
- `custom_plugin_action_links()`: This function adds a “Settings” link directly on the plugin page, linking to the WooCommerce checkout settings. This makes it easier for users to configure your gateway.
// Exit if accessed directly.
if ( ! defined( ‘ABSPATH’ ) ) {
exit;
}
/
* Include the payment gateway class.
*/
function custom_payment_gateway_load() {
if ( ! class_exists( ‘WC_Payment_Gateway’ ) ) {
return;
}
include_once( ‘includes/class-wc-gateway-custom.php’ );
add_filter( ‘woocommerce_payment_gateways’, ‘custom_add_gateway_class’ );
function custom_add_gateway_class( $gateways ) {
$gateways[] = ‘WC_Gateway_Custom’;
return $gateways;
}
}
add_action( ‘plugins_loaded’, ‘custom_payment_gateway_load’, 0 );
/
* Add custom links to the plugins page
*/
add_filter( ‘plugin_action_links_’ . plugin_basename( __FILE__ ), ‘custom_plugin_action_links’ );
function custom_plugin_action_links( $links ) {
$plugin_links = array(
‘‘ . __( ‘Settings’, ‘woocommerce’ ) . ‘‘,
);
return array_merge( $plugin_links, $links );
}
Explanation:
#### 2. Defining the Gateway Class (includes/class-wc-gateway-custom.php)
Now, create a file named `class-wc-gateway-custom.php` inside the `includes/` directory within your plugin folder. This file will contain the core logic for your payment gateway. This class extends the `WC_Payment_Gateway` class and defines how your gateway interacts with WooCommerce.
<?php if ( ! defined( 'ABSPATH' ) ) { exit; }
/
* Custom Payment Gateway Class
*/
class WC_Gateway_Custom extends WC_Payment_Gateway {
/
* Constructor for the gateway.
*/
public function __construct() {
$this->id = ‘custom_payment’;
$this->icon = apply_filters(‘woocommerce_custom_payment_icon’, ”);
$this->has_fields = true; // If you need custom fields on the checkout page
$this->method_title = ‘Custom Payment Gateway’;
$this->method_description = ‘A custom payment gateway for demonstration purposes.’;
// Load the settings.
$this->init_form_fields();
$this->init_settings();
// Define user set variables
$this->title = $this->get_option( ‘title’ );
$this->description = $this->get_option( ‘description’ );
$this->enabled = $this->get_option( ‘enabled’ );
$this->instructions = $this->get_option( ‘instructions’, $this->description );
// Actions
add_action( ‘woocommerce_update_options_payment_gateways_’ . $this->id, array( $this, ‘process_admin_options’ ) );
add_action( ‘woocommerce_thankyou_’ . $this->id, array( $this, ‘thankyou_page’ ) );
// Customer Emails
add_action( ‘woocommerce_email_before_order_table’, array( $this, ’email_instructions’ ), 10, 3 );
}
/
* Initialise Gateway Settings Form Fields.
*/
public function init_form_fields() {
$this->form_fields = array(
‘enabled’ => array(
‘title’ => ‘Enable/Disable’,
‘type’ => ‘checkbox’,
‘label’ => ‘Enable Custom Payment Gateway’,
‘default’ => ‘yes’
),
‘title’ => array(
‘title’ => ‘Title’,
‘type’ => ‘text’,
‘description’ => ‘This controls the title which the user sees during checkout.’,
‘default’ => ‘Custom Payment’,
‘desc_tip’ => true,
),
‘description’ => array(
‘title’ => ‘Description’,
‘type’ => ‘textarea’,
‘description’ => ‘Payment method description that the customer will see on your checkout.’,
‘default’ => ‘Pay with your custom payment method.’,
‘desc_tip’ => true,
),
‘instructions’ => array(
‘title’ => ‘Instructions’,
‘type’ => ‘textarea’,
‘description’ => ‘Instructions that will be added to the thank you page and emails.’,
‘default’ => ”,
‘desc_tip’ => true,
),
);
}
/
* Output the payment fields for adding credit card number and expiration date.
*/
public function payment_fields() {
if ( $this->description ) {
echo wp_kses_post( wpautop( wptexturize( $this->description ) ) );
}
// Add custom fields here. Example:
echo ‘
‘;
}
/
* Process the payment and return the result.
*
* @param int $order_id
* @return array
*/
public function process_payment( $order_id ) {
$order = wc_get_order( $order_id );
// Mark as processing (payment won’t be taken until delivery).
$order->update_status( ‘processing’, __( ‘Processing payment via custom Explore this article on How To Display The Product Category Description In Woocommerce Shortcode gateway.’, ‘woocommerce’ ) );
// Reduce stock levels
wc_reduce_stock_levels( $order_id );
// Remove cart
WC()->cart->empty_cart();
// Return thankyou redirect
return array(
‘result’ => ‘success’,
‘redirect’ => $this->get_return_url( $order )
);
}
/
* Output for the order received page.
*
* @param int $order_id
*/
public function thankyou_page( $order_id ) {
if ( $this->instructions ) {
echo wp_kses_post( wpautop( wptexturize( $this->instructions ) ) );
}
}
/
* Add content to the WC emails.
*
* @access public
* @param WC_Order $order
* @param bool $sent_to_admin
* @param bool $plain_text
*/
public function email_instructions( $order, $sent_to_admin, $plain_text = false ) {
if ( $this->instructions && ! $sent_to_admin && $this->id === $order->get_payment_method() ) {
echo wp_kses_post( wpautop( wptexturize( $this->instructions ) ) . PHP_EOL );
}
}
}
Explanation:
- Class Definition: `class WC_Gateway_Custom extends WC_Payment_Gateway { … }` Extends the core WooCommerce payment gateway class.
- `__construct()`: The constructor sets up the gateway’s ID, title, description, and settings. Crucially, it loads the settings form fields and hooks actions for updating settings, displaying the thank you page, and adding instructions to emails.
- `init_form_fields()`: Defines the settings that will appear in the WooCommerce admin panel for this gateway (enabled/disabled, title, description, instructions). This allows administrators to configure the gateway.
- `payment_fields()`: This function is responsible for displaying the payment form on the checkout page. The example shows how to add a custom text field. You’ll need to customize this to capture any required payment information from the user.
- `process_payment()`: This is the most important function. It’s called when the order is placed. In this example, it simply marks the order as processing, reduces stock levels, and empties the cart. You’ll need to replace this with the code that actually communicates with your payment processor. This involves:
- Collecting the payment data submitted in `payment_fields()`.
- Authenticating with your payment gateway.
- Sending the payment request.
- Receiving and interpreting the response.
- Updating the order status based on the response (e.g., `completed`, `failed`).
- `thankyou_page()`: Displays custom instructions on the order confirmation (“Thank You”) page.
- `email_instructions()`: Adds instructions to the order confirmation email.
#### 3. Processing Payments (The Core Logic)
The `process_payment()` function is where your payment processing magic happens. This is where you’ll interact with your chosen payment gateway’s API. Here’s a simplified example of what that might look like (assuming a hypothetical API):
/**
$order = wc_get_order( $order_id );
// Get submitted payment data from payment_fields()
$custom_field_value = $_POST[‘custom_field’]; //Example retrieval, sanitize before use!
// Replace with your actual API credentials
$api_key = $this->get_option( ‘api_key’ ); // Assuming you added an API key field in init_form_fields()
// Prepare the payment request
$payment_data = array(
‘api_key’ => Explore this article on How To Create A Cart Page In Woocommerce $api_key,
‘amount’ => $order->get_total(),
‘currency’ => get_woocommerce_currency(),
‘description’ => ‘Payment for order #’ . $order_id,
‘custom_field’ => sanitize_text_field( $custom_field_value ), //Sanitize input!
);
// SEND PAYMENT REQUEST TO YOUR PAYMENT GATEWAY HERE
$response = $this->send_payment_request( $payment_data ); // Assuming you have a method to send the request
if ( $response[‘success’] ) {
// Payment was successful
// Mark order as completed
$order->payment_complete();
$order->add_order_note( __( ‘Payment successful via Custom Payment Gateway.’, ‘woocommerce’ ) );
// Reduce stock levels
wc_reduce_stock_levels( $order_id );
// Remove cart
WC()->cart->empty_cart();
// Return thankyou redirect
return array(
‘result’ => ‘success’,
‘redirect’ => $this->get_return_url( $order )
);
} else {
// Payment failed
wc_add_notice( $response[‘error_message’], ‘error’ );
$order->add_order_note( __( ‘Payment failed via Custom Payment Gateway: ‘ . $response[‘error_message’], ‘woocommerce’ ) );
return array(
‘result’ => ‘failure’,
);
}
}
/
* Example function to send a payment request (replace with your actual API call)
*
* @param array $data
* @return array
*/
private function send_payment_request( $data ) {
// REPLACE WITH YOUR ACTUAL API CALL USING wp_remote_post or similar.
// This is just a placeholder for demonstration.
if ($data[‘amount’] > 0) {
return array(‘success’ => true);
}
else {
return array(‘success’ => false, ‘error_message’ => ‘Payment failed: Amount must be greater than 0.’);
}
}
Important Considerations for `process_payment()`:
- Security: Never store sensitive payment information directly in your database. Use your payment gateway’s provided methods for securely handling payment data (e.g., tokenization).
- Error Handling: Implement robust error handling to catch API errors, network issues, and other potential problems. Display informative error messages to the customer.
- Sanitization: Thoroughly sanitize all user input (e.g., from `$_POST`) to prevent security vulnerabilities. Use functions like `sanitize_text_field()` and `wc_clean()`.
- API Integration: Use `wp_remote_post()` or similar WordPress functions to make API requests to your payment gateway.
- Order Status Updates: Update the order status accurately based on the payment result (e.g., `processing`, `completed`, `failed`, `on-hold`).
- Logging: Implement logging to track transactions and debug issues. Use WooCommerce’s logging functions.
- Testing: Thoroughly test your gateway in a sandbox or testing environment before deploying it to a live site.
- Compliance: Ensure your gateway complies with all relevant payment industry standards (e.g., PCI DSS).
#### 4. Handling Custom Fields and Validation
If your payment gateway requires custom fields (like credit card details, account numbers, etc.), you need to handle these securely and validate them.
- `payment_fields()`: Add the necessary HTML input fields in the `payment_fields()` function. Use appropriate labels and placeholders. Mark required fields clearly.
public function payment_fields() {
if ( $this->description ) {
echo wp_kses_post( wpautop( wptexturize( $this->description ) ) );
}
echo ‘
‘;
}
- Validation: Inside `process_payment()`, retrieve the values submitted in `payment_fields()` using `$_POST`. Crucially, sanitize and validate these values before sending them to your payment gateway.
public function process_payment( $order_id ) {
// …
$account_number = isset( $_POST[‘account_number’] ) ? sanitize_text_field( $_POST[‘account_number’] ) : ”;
if ( empty( $account_number ) ) {
wc_add_notice( __( ‘Please enter your account number.’, ‘woocommerce’ ), ‘error’ );
return array(
‘result’ => ‘failure’,
);
}
// …
}
Conclusion
Developing a custom payment gateway for WooCommerce requires careful planning, secure coding practices, and thorough testing. Security is paramount. Ensure that you handle sensitive payment data responsibly and comply with all relevant industry standards. By following the steps outlined in this guide and paying close attention to security, you can create a powerful and customized payment solution for your WooCommerce store.