Create a Custom WooCommerce payment gateway from Cash on Delivery Gateway

In the previous article, we learned how you can create a custom WooCommerce payment gateway from scratch.

Today, we shall build a custom WooCommerce payment gateway from the WooCommerece Cash on Delivery Gateway.

If you check wp-content/plugins/woocommerce/includes/gateways/ and you will find all the available gateways.

Get a Copy of Cash On Delivery payment gateway

Get a copy of the Cash On Delivery gateway, paste into your plugins folder and rename it. I will call it Payleo Payments Gateway.

wp-content/plugins/woocommerce/includes/gateways/cod/class-wc-gateway-cod.php

Rename the plugin file and drag and drop it inside your editor.

Setup Custom WooCommerece Payment Gateway Plugin

Let’s delete a couple of things. We shall start by editing the plugin setup.

Use the following code for the plugin setup

<?php
/**
 * Plugin Name: Payleo Payments Gateway
 * Plugin URI: https://omukiguy.com
 * Author: Techiepress
 * Author URI: https://omukiguy.com
 * Description: Local Payments Gateway for mobile.
 * Version: 0.1.0
 * License: GPL2
 * License URL: http://www.gnu.org/licenses/gpl-2.0.txt
 * text-domain: payleo-payments-woo
 * 
 * Class WC_Gateway_Payleo file.
 *
 * @package WooCommerce\PayLeo
 */

Editing Cash On Delivery Payment Gateway

Replace everything that has WC_gateway_COD, with WC_Gateway_Payleo. Change the COD to Payleo

After that, remove the constants that are coming from Jetpack.

Note that our class WC_Gateway_Payleo extends WC_Pyment_Gateway

We went through all this during our previous video of How to create a custom WooCommerce Payment Gateway

Reviewing COD Payment Gateway

We can see that we now have a couple of things thrown out into different functions.

setup_properties()

We have the setup properties that has the plugin ID, the filters, the title and a method.

The following code shows our setup properties.

/*
 Setup general properties for the gateway.
 */
	protected function setup_properties() {
		$this->id                 = 'cod';
		$this->icon               = apply_filters( 'woocommerce_cod_icon', '' );
		$this->method_title       = __( 'Cash on delivery', 'woocommerce' );
		$this->method_description = __( 'Have your customers pay with cash (or by other means) upon delivery.', 'woocommerce' );
		$this->has_fields         = false;
	}

These are things we can change in contrast to the plugin we had already done.

init_form _fields()

Then we have the init form fields that show you whether the plugin should be enabled, the title, description, instructions, enable_for_methods(set shipping methods), enable_for_virtual(show whether it is a virtual product or now)

The following code shows the init form fields settings.

* Initialise Gateway Settings Form Fields.*/
public function init_form_fields() {
		$this->form_fields = array(
			'enabled'            => array(
				'title'       => __( 'Enable/Disable', 'woocommerce' ),
				'label'       => __( 'Enable cash on delivery', 'woocommerce' ),
				'type'        => 'checkbox',
				'description' => '',
				'default'     => 'no',
			),
			'title'              => array(
				'title'       => __( 'Title', 'woocommerce' ),
				'type'        => 'text',
				'description' => __( 'Payment method description that the customer will see on your checkout.', 'woocommerce' ),
				'default'     => __( 'Cash on delivery', 'woocommerce' ),
				'desc_tip'    => true,
			),
			'description'        => array(
				'title'       => __( 'Description', 'woocommerce' ),
				'type'        => 'textarea',
				'description' => __( 'Payment method description that the customer will see on your website.', 'woocommerce' ),
				'default'     => __( 'Pay with cash upon delivery.', 'woocommerce' ),
				'desc_tip'    => true,
			),
			'instructions'       => array(
				'title'       => __( 'Instructions', 'woocommerce' ),
				'type'        => 'textarea',
				'description' => __( 'Instructions that will be added to the thank you page.', 'woocommerce' ),
				'default'     => __( 'Pay with cash upon delivery.', 'woocommerce' ),
				'desc_tip'    => true,
			),
			'enable_for_methods' => array(
				'title'             => __( 'Enable for shipping methods', 'woocommerce' ),
				'type'              => 'multiselect',
				'class'             => 'wc-enhanced-select',
				'css'               => 'width: 400px;',
				'default'           => '',
				'description'       => __( 'If COD is only available for certain methods, set it up here. Leave blank to enable for all methods.', 'woocommerce' ),
				'options'           => $this->load_shipping_method_options(),
				'desc_tip'          => true,
				'custom_attributes' => array(
					'data-placeholder' => __( 'Select shipping methods', 'woocommerce' ),
				),
			),
			'enable_for_virtual' => array(
				'title'   => __( 'Accept for virtual orders', 'woocommerce' ),
				'label'   => __( 'Accept COD if the order is virtual', 'woocommerce' ),
				'type'    => 'checkbox',
				'default' => 'yes',
			),
		);
	}

The beauty of using what is already existing is that you don’t have to reinvent the wheel.

init_settings()

Furthermore, we have the init settings which is already part of the extension of the WC_Payment_Gateway class.

We then add the extra settings like title, description, instructions. These are already being got from what we have saved in the init form fields function.

In addition, we have actions like updating the payment gateways, thank you, payment order status and the payment gateway method added into our email instructions.

The following code shows init settings of the payment gateway.

$this->init_settings();
// Get settings.
		$this->title              = $this->get_option( 'title' );
		$this->description        = $this->get_option( 'description' );
		$this->instructions       = $this->get_option( 'instructions' );
		$this->enable_for_methods = $this->get_option( 'enable_for_methods', array() );
		$this->enable_for_virtual = $this->get_option( 'enable_for_virtual', 'yes' ) === 'yes';

		add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
		add_action( 'woocommerce_thankyou_' . $this->id, array( $this, 'thankyou_page' ) );
		add_filter( 'woocommerce_payment_complete_order_status', array( $this, 'change_payment_complete_order_status' ), 10, 3 );

		// Customer Emails.
		add_action( 'woocommerce_email_before_order_table', array( $this, 'email_instructions' ), 10, 3 );
	}

So that’s the beauty of actually starting with this extension.

Replace cod with Payleo for example

	$this->id         = 'cod';

becomes

	$this->id       = 'payleo';

Let’s pick a few things from our first plugin.

Ensure to have it in your workspace.

Get the assets and drop them in there

Also, get the icon link and edit it to look like this

$this->icon         = apply_filters( 'woocommerce_payleo_icon', plugins_url('/assets/icon.png'__FILE__) );

That is all you need to do for now.

Let’s make more edits and then check whether our function is working.

Edit setup properties

Replace “Cash on Delivery” with “Payleo Mobile Payments”. For example, this

$this->method_title       = __( 'Cash on delivery', 'woocommerce' );
$this->method_description = __( 'Have your customers pay with cash (or by other means) upon delivery.', 'woocommerce' );

now becomes

$this->method_title       = __( 'Payment Mobile Payments', 'woocommerce' );
$this->method_description = __( 'Use your mobile payments to clear the bill', 'woocommerce' );

Edit init form fields function

change

'description' => __( 'Payment method description that the customer will see on your checkout.', 'woocommerce' ),
'default'     => __( 'Cash on delivery', 'woocommerce' ),

to

'description' => __( 'Payleo Payment method description that the customer will see on your checkout.', 'woocommerce' ),
'default'     => __( 'Pay with your mobile cash balance', 'woocommerce' ),

Activate Custom WooCommerce Payment Gateway

Now go back to your plugin settings and activate the plugin

Also, activate payleo payment gateway from WooCommerce settings

activate custom woocommerce payment plugin

Use the following code snippet to check if WooCommerce is installed and activated. Then load this payment and if the Gateway class exists, we shall extend it.

if ( ! in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) return;

Add the filter.

Whenever we have the payment gateways, we are going to add to WooCommerce, payleo payment gateway which is actually WC_Gateway_Payleo

Use the following code to add the custom payment gateway to WooCommerce.

add_filter( 'woocommerce_payment_gateways', 'add_to_woo_payleo_payment_gateway');
function add_to_woo_payleo_payment_gateway( $gateways ) {
    $gateways[] = 'WC_Gateway_Payleo';
    return $gateways;
}

Save the code and reload.

Now go to WooCommerce settings and you will notice that we have our Payleo Mobile Payments showing up among the payment gateways. Activate it and save changes.

Go to manage, you will see all the setup that we have and we shall not exclude it from any shipping method. We have also allowed it for virtual products.

If you place an order now, you will get an invalid currency code. This is because we don’t have a currency code. We need to check whether our plugin is using a particular currency.

Add a currency

11:54 Watch this video to learn how to add a particular currency.

Now, let’s add our currency and the currency setup

Go to WooCommerce-General settings- Currency Options

currency options

Let’s add some code to allow us to add a particular currency and a symbol. It also checks if we have this particular currency inside the plugin and if we don’t have it, we add it.

add_filter( 'woocommerce_currencies', 'techiepress_add_ugx_currencies' );
add_filter( 'woocommerce_currency_symbol', 'techiepress_add_ugx_currencies_symbol', 10, 2 );

function techiepress_add_ugx_currencies( $currencies ) {
	$currencies['UGX'] = __( 'Ugandan Shillings', 'payleo-payments-woo' );
	return $currencies;
}

Now go to your shop and place an order. Then go to WooCommerce orders and check out. The order must be in processing status.

As you can see we paid via Payleo Mobile Payments

custom mobile payment gateway

So we have managed to convert our Cash On Delivery Payment Gateway to a Custom Mobile Payment Gateway.

Using the API

The task at hand now is using the API

Let’s break down this piece of code into more reusable pieces. Let’s make it a class system.

Firstly, we shall have a new file called includes and add our class there.

Secondly, we have to require particular files from includes into class-wc-payment-gateway-payleo.php

This is what your file structure should look like.

custom payment file structure

In the class-wc-payment-gateway-payleo.php file, we have our biggest function which is the process_payments(). All it does is get the order, through the order id and we see that if it is greater than zero, we place it on hold and if it is less than zero, we complete the order. This is where we shall add our new function.

let’s add a new function payleo_payment_processing() we make it a private function because we want it inside a particular class.

private function payleo_payment_processing() {
		 pending payment
		 $order->update_status( apply_filters( 'woocommerce_payleo_process_payment_order_status', $order->has_downloadable_item() ? 'wc-invoiced' : 'processing', $order ), __( 'Payments pending.', 'payleo-payments-woo' ) );
		
		 If cleared
		 $order->payment_complete();
	}

Note that in WooCommerce, there are already a number of order statuses available for example, on hold, completed, processing, cancelled, failed and so on. You can also add your own order status.

woocommerce payment status

Learn how to add your own order status from this video.

Add new Order Status

Let’s add a new order status to our plugin.

Add this code to /includes/payleo-order-statuses.php

Then require it inside payleo-payments-woocommerce.php

function payleo_payment_init() {
    if( class_exists( 'WC_Payment_Gateway' ) ) {
		require_once plugin_dir_path( __FILE__ ) . '/includes/class-wc-payment-gateway-payleo.php';
		require_once plugin_dir_path( __FILE__ ) . '/includes/payleo-order-statuses.php';
	}
}

Firstly, we register a new post status using register_my_new_order_statuses() which is a default WordPress function and we add wc-invoiced as its name. It’s public, can be shown in the admin list and so on.

function register_my_new_order_statuses() {
    register_post_status( 'wc-invoiced', array(
        'label'                     => _x( 'Invoiced', 'Order status', 'payleo-payments-woo' ),
        'public'                    => true,
        'exclude_from_search'       => false,
        'show_in_admin_all_list'    => true,
        'show_in_admin_status_list' => true,
        'label_count'               => _n_noop( 'Invoiced <span class="count">(%s)</span>', 'Invoiced<span class="count">(%s)</span>', 'payleo-payments-woo' )
    ) );
}

Then we add that into our available order statuses by using a filter.

add_filter( 'wc_order_statuses', 'my_new_wc_order_statuses' );

Furthermore, we add it to the bulk pieces of information so that we’re able to perform bulk actions on it.

function payleo_add_bulk_invoice_order_status() {
    global $post_type;

    if ( $post_type == 'shop_order' ) {
        ?>
            <script type="text/javascript">
                jQuery(document).ready(function() {
                    jQuery('<option>').val('mark_invoiced').text('<?php _e( 'Change status to invoiced', 'payleo-payments-woo' ); ?>').appendTo("select[name='action']");
                    jQuery('<option>').val('mark_invoiced').text('<?php _e( 'Change status to invoiced', 'payleo-payments-woo' ); ?>').appendTo("select[name='action2']");   
                });
            </script>
        <?php
    }
}

All the code for this file can be found here

In conclusion, we can be able to query our server using this status. Let’s say it failed at some point, we can check if our server applied the status to a particular payment

We shall stop here and in the next tutorial, we shall learn how to add your own API into the system.

All the code for this tutorial can be found on Github

Proceed to Part 3.


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *