DEV Community

Cover image for How to make payment gateway plugin for Woo Commerce in WordPress
Husnain Mustafa
Husnain Mustafa

Posted on

How to make payment gateway plugin for Woo Commerce in WordPress

Today, we are going to make a payment gateway plugin for WooCommerce in WordPress.

For the sake of simplicity, we will redirect user to another page, which is provided by payment gateway for transactions to be completed.

For this example, we are going to use Raast payment gateway. Raast payment gateway provides an api to, first initiate a payment and then redirect user to Raast payment page.

Making Plugin File

First of all, we need to make our plugin file. WordPress provides a really simple method to make a plugin file.

  1. Make a file with any name, with php extention. For example, in this case, raast.php
  2. Copy the code below


<?php
/*
 * Plugin Name: Raast Payment Gateway for Woocommerce
 * Plugin URI: https://husnaincodes.com/wp-plugins/raast-payment-gateway-for-woocommerce/
 * Description: This plugin helps you integrate Raast Payment Gateway for Woocommerce.
 * Author: Husnain Mustafa
 * Author URI: https://husnaincodes.com
 * Version: 1.0.3
 */



Enter fullscreen mode Exit fullscreen mode

By adding only the above content, wordpress recognizes our plugin and shows it in plugins section of wordpress admin panel. Below is the pictures that describes above written code.

Image description

So now, our plugin file is ready.


Integrating our plugin with WooCommerce

WooCommerce provides a very easy way to integrate plugins with it. As our goal is to make payment gateway plugin, we need to make a class which extends WC_Payment_Gateway class that woocommerce provides.

class Raast_Payment_Gateway extends WC_Payment_Gateway

WC_Payment_Gateway provides different methods which we can override and make use of those.

Below is the structure that we are going to use in our plugin:



function initiate_raast_class() {
class Raast_Payment_Gateway extends WC_Payment_Gateway {


        public function __construct() {

        }

        public function init_form_fields() {

        }

        public function payment_fields() {

        }

        public function validate_fields() {

        }

        public function process_payment( $order_id ) {

        }
    }
}
}

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


add_action( 'plugins_loaded', 'initiate_raast_class' );


Enter fullscreen mode Exit fullscreen mode

Description of above code

  • __construct is basically our class constructor which is executed at the time when object of class is made. Here, we will define multiple fields which are associated with our plugin. I will explain those later.

  • init_form_fields is where we define fields, so that we can get different variable from the woocommerce -> settings -> payments -> -> manage.

Plugin Fields

  • payment_fields is where we define fields which are visible to the customer at the checkout page. This is used if we do not want to redirect our customer to our payment gateway transaction page, rather we want to ask details right on checkout page. Mostly used in the case of payments cards.
    As we are redirecting customer to our payment gateway transaction page, we do not need this method.

  • validate_fields is used to validate the input fields by the customer. Again we are not going to use this in our example.

  • process_payment is the most important method. Because, this method is called when customer clicks on place order. This method is where we define what and how payment happens. In our case, we are going to post a request to Raast. Raast will return us a redirect url, then we are going to redirect our customer to that url so that Raast can handle transaction by itself on its transaction page.


Raast Transaction flow

  1. So Raast provide us the api where we can post request with required parameters
  2. If request is successful, Raast respond with redirect url.
  3. We will redirect our customer to that url.
  4. Our customer fulfills the transaction on Raast transaction page.
  5. If transaction is successful, Raast will post a request on given IPN url which we provide to Raast in first request that we made.
  6. We can further handle the request by Raast by however we want. Usually, we just complete the order by either: $order->update_status( 'processing' ); OR $order->$order->payment_complete();

Inside of the above methods



public function __construct() {

            $this->id = 'raast'; 
            $this->icon = 'https://www.raastid.com/assets/images/logoIcon/light_logo.png'; 
            $this->has_fields = false; 
            $this->method_title = 'Raast Payment Gateway';
            $this->method_description = 'Let Your Customers Pay with Raast ID'; 



            $this->supports = array(
                'products'
            );


            $this->init_form_fields();


            $this->init_settings();
            $this->title = $this->get_option( 'title' );
            $this->description = $this->get_option( 'description' );
            $this->success_url = $this->get_option( 'success_url' );
            $this->cancel_url = $this->get_option( 'cancel_url' );
            $this->logo_url = $this->get_option( 'logo_url' );
            $this->ipn_url = plugin_dir_url( __FILE__ ) . 'ipn.php';
            $this->testmode = 'yes' === $this->get_option( 'testmode' );
            $this->private_key = $this->get_option( 'private_key' );
            $this->publishable_key = $this->get_option( 'publishable_key' );

            if( empty($this->success_url) || $this->success_url == null ){
                $this->success_url = get_site_url();
            }

            if( empty($this->cancel_url) || $this->cancel_url == null ){
                $this->cancel_url = get_site_url();
            }

            if( empty($this->logo_url) || $this->logo_url == null ){
                $this->logo_url = 'https://www.raastid.com/assets/images/logoIcon/light_logo.png';
            }


            add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );

            add_action( 'wp_enqueue_scripts', array( $this, 'payment_scripts' ) );




        }


        public function init_form_fields(){

            $this->form_fields = array(
                'title' => array(
                    'title'       => 'Title',
                    'type'        => 'text',
                    'description' => 'This controls the title which the user sees during checkout.',
                    'default'     => 'Raast',
                    'desc_tip'    => true,
                ),
                'description' => array(
                    'title'       => 'Description',
                    'type'        => 'textarea',
                    'description' => 'This controls the description which the user sees during checkout.',
                    'default'     => 'Pay with your Raast ID',
                ),
                'testmode' => array(
                    'title'       => 'Test mode',
                    'label'       => 'Enable Test Mode',
                    'type'        => 'checkbox',
                    'description' => 'Tick this to enable sandbox/test mode. According to RAAST documentaion, test mail is: test_mode@mail.com and test verification code is: 222666',
                    'default'     => 'yes',
                ),
                'success_url' => array(
                    'title'       => 'Success URL',
                    'description' => 'This is the URL where Raast will redirect after payment was SUCCESSFUL. If you leave this field empty, it will be redirected to your site. Example: https://www.example.com/',
                    'type'        => 'text',
                    'default'     => ''
                ),
                'cancel_url' => array(
                    'title'       => 'Cancel URL',
                    'description' => 'This is the URL where Raast will redirect if payment was CANCELLED. If you leave this field empty, it will be redirected to your site. Example: https://www.example.com/',
                    'type'        => 'text',
                    'default'     => ''
                ),
                'logo_url' => array(
                    'title'       => 'Logo Url',
                    'description' => 'Your Site Logo URL. If you leave this field empty, it will use RAAST icon.  Example: https://www.example.com/image.png',
                    'type'        => 'text',
                    'default'     => ''
                ),
                'publishable_key' => array(
                    'title'       => 'Your Raast Public Key',
                    'type'        => 'text',
                    'default'     => ''
                ),
                'private_key' => array(
                    'title'       => 'Your Raast Private Key',
                    'type'        => 'password',
                    'default'     => ''
                )
            );

        }

        public function process_payment( $order_id ) {
            global $woocommerce;


            $order = wc_get_order( $order_id );
            $amount = $order->get_total();
            $name = $order->get_billing_first_name() . $order->get_billing_first_name();
            $email = $order->get_billing_email();


            ///live end point
            $url = 'https://www.raastid.com/payment/initiate';

            if($this->testmode){
                //test end point
                $url = 'https://www.raastid.com/sandbox/payment/initiate';
            }


            // Paramenters to API Call
            $parameters = [
                'identifier' => $order_id,
                'currency' => 'USD',
                'amount' => $amount,
                'details' => 'Order Placed',
                'ipn_url' => $this->ipn_url,
                'cancel_url' => $this->cancel_url,
                'success_url' => $this->success_url,
                'public_key' => $this->publishable_key,
                'site_logo' => $this->logo_url,
                'checkout_theme' => 'dark',
                'customer_name' => $name,
                'customer_email' => $email,

            ];


            //live end point
            $url = 'https://www.raastid.com/payment/initiate';

            if($this->testmode){
                //test end point
                $url = 'https://www.raastid.com/sandbox/payment/initiate';
            }



            // API Call
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_POSTFIELDS,  $parameters);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            $result = curl_exec($ch);
            curl_close($ch);

            $result = json_decode($result, true);



            if($result['success'] == 'ok'){

                $woocommerce->cart->empty_cart();
                wc_add_notice('Order is Placed Successfully!');

                return array(
                    'result' => 'success',
                    'redirect' => $result['url']
                );


            }
            else{


                // To debug result

                /* 
                if (is_array($result) || is_object($result)) {
                    error_log(print_r($result, true));
                } 
                else {
                    error_log($result);
                }
                */
            }

        }


Enter fullscreen mode Exit fullscreen mode

Understanding the above code

__construct()

  • $this->id is used to define id, we can use this to get reference of our class anywhere outside the file. Like in IPN, I used $raast = WC()->payment_gateways->payment_gateways()['raast']; and further used $raast to get private key in IPN file.

  • $this->icon is used to set url of icon which will be used at checkout page.

Icon at Checkout Page

  • $this->has_fields is a boolean. Used if we want to use fields at checkout page, mostly used for custom credit card form. In our case, it is going to be false.

  • $this->method_title used to define name of our plugin at WooCommerce -> Settings -> Payments

  • $this->method_description used to define description of our plugin at WooCommerce -> Settings -> Payments.

Woocommerce Payments Title and Description

  • $this->init_settings(); to load previous settings

  • $this->title Title at checkout page

  • $this->description Description at checkout page

Other variables are custom variable used in api call.

To get value of any field, at plugin's settings in WooCommerce, we can use $this->get_option( <name of field> )

init_form_fields()

Here, we define the fields that we require from the admin, like title, description and other fields that could be used to integrate payment gateway.

In this method, we defined $this->form_fields which is an array.

We can also assign $this->form_fields in constructor rather than having separate method and then calling it from constructor. But for cleaner code, a separate method is better.

To get values from these fields we can use $this->get_option( <name of field> ).

process_payment( $order_id )

It is used to process the payments. This is called after customer places order. This method is customized according to the need of payment gateway that we are integrating.


Our plugin is good to go now.


Hope this article was helpful. If you have any queries, ask in comments. You can get full code at Github for reference.


Follow me on Twitter.
You can also visit my portfolio

Top comments (0)