A Guide to Enable Stripe Subscription Payment Integration in CodeIgniter

The Stripe payment gateway brings ease in recurring bill payments. It is ideal for websites that offer a subscription based monthly or weekly payment. So, you can integrate the stripe subscription API to enable recurring payment features on your website. In this tutorial, we will learn about the Stripe Subscription Payment Integration in CodeIgniter.

This is how your users can make recurring bill payment to continue with your subscription plans. Moreover, it will allow your website users to pay recurring membership fees online using credit cards. 

Further, you can integrate the Stripe PHP library and API into your CodeIgniter framework. And, this PHP library is beneficial to integrate subscription API into PHP. 

In the below example script, you will learn to create a CodeIgniter Subscription application with Stripe API. So, one can implement the following points to enable the functionality. 

  • Get the database subscription forms & arrange them under a dropdown.
  • Generate a HTML form to fill in credit card information after selecting relevant plans.
  • After that, generate Stripe token to secure the credit card information while making payment.
  • Also, re-check the credit card details & generate a Stripe API subscription plan. 
  • Lastly, save transaction information & relevant subscription plan data in the database.

Test Stripe API keys to validate payment procedure

You must verify the checkout process before making it live on your webpage. So, make sure that you test check API keys data before making the Stripe payment gateway live. In the end, it will ensure smooth credit card payment procedures. 

To begin with,

  • Login your Stripe account & go to Developers » API Keys page. 
  • After that, you will find API keys namely Publishable key and Secret key. So, these are available under the Standard keys section in the test data. You might need to click on the Reveal test key token button to see the Secret key. 

Image showing API keys to enable Stripe Subscription Payment Integration in CodeIgniter

Also, save the Publishable key and Secret key data to use it later. 

Further, we will begin Stripe Subscription Payment Integration in CodeIgniter. However, before that, take a glimpse over our file structures.

codeigniter_stripe_subscription_payment_integration/
├── application/
│   ├── config/
│   │   └── stripe.php
│   ├── controllers/
│   │   └── Subscription.php
│   ├── libraries/
│   │   └── Stripe_lib.php
│   ├── models/
│   │   └── User.php
│   ├── third_party/
│   │   └── stripe-php/
│   ├── views/
│   │   └── subscription/
│   │       ├── index.php
│   │       └── payment-status.php
└── assets/
    └── css/
        └── style.css

Creating Database Tables

You are required to generate 3 tables to store the relevant information. Further, you need to save the plan, subscription, & member data in the database. 

  1. Create a plans table to store subscription plan data in the MySQL database 
CREATE TABLE `plans` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
 `price` float(10,2) NOT NULL,
 `currency` varchar(10) COLLATE utf8_unicode_ci NOT NULL DEFAULT 'USD',
 `interval` enum('week','month','year') COLLATE utf8_unicode_ci NOT NULL,
 PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

2. Create a users table to store member data in the MySQL database

CREATE TABLE `users` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `subscription_id` int(11) NOT NULL DEFAULT 0,
 `first_name` varchar(25) COLLATE utf8_unicode_ci NOT NULL,
 `last_name` varchar(25) COLLATE utf8_unicode_ci NOT NULL,
 `email` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
 `password` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
 `gender` enum('Male','Female') COLLATE utf8_unicode_ci NOT NULL,
 `phone` varchar(15) COLLATE utf8_unicode_ci NOT NULL,
 `created` datetime NOT NULL,
 `modified` datetime NOT NULL,
 `status` enum('1','0') COLLATE utf8_unicode_ci NOT NULL DEFAULT '1',
 PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

3. Create user_subscriptions table to store payment & subscription information in the MySQL database

CREATE TABLE `user_subscriptions` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `user_id` int(11) NOT NULL DEFAULT 0,
 `plan_id` int(11) NOT NULL,
 `payment_method` enum('stripe') COLLATE utf8_unicode_ci NOT NULL DEFAULT 'stripe',
 `stripe_subscription_id` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
 `stripe_customer_id` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
 `stripe_plan_id` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
 `plan_amount` float(10,2) NOT NULL,
 `plan_amount_currency` varchar(10) COLLATE utf8_unicode_ci NOT NULL,
 `plan_interval` varchar(10) COLLATE utf8_unicode_ci NOT NULL,
 `plan_interval_count` tinyint(2) NOT NULL,
 `plan_period_start` datetime NOT NULL,
 `plan_period_end` datetime NOT NULL,
 `payer_email` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
 `created` datetime NOT NULL,
 `status` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
 PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

Configurate

The Stripe library config variables are stored under stripe.php file. 

  • Firstly, define the Stripe API Secret key (stripe_api_key), API Publishable key (stripe_publishable_key). Also, do not forget to specify the currency code (stripe_currency). 
<?php 
defined('BASEPATH') OR exit('No direct script access allowed'); 
/* 
| ------------------------------------------------------------------- 
|  Stripe API Configuration 
| ------------------------------------------------------------------- 
| 
| You will get the API keys from Developers panel of the Stripe account 
| Login to Stripe account (https://dashboard.stripe.com/) 
| and navigate to the Developers » API keys page 
| Remember to switch to your live publishable and secret key in production! 
| 
|  stripe_api_key            string   Your Stripe API Secret key. 
|  stripe_publishable_key    string   Your Stripe API Publishable key. 
|  stripe_currency           string   Currency code. 
*/ 
$config['stripe_api_key']         = 'Your_API_Secret_key'; 
$config['stripe_publishable_key'] = 'Your_API_Publishable_key'; 
$config['stripe_currency']        = 'usd';

Third party

Further, you can use Stripe PHP bindings library to generate member, plan, & subscription data. In the CodeIgniter application, one can place the Stripe PHP library in the third_party/ directory. Also, it is one of the important steps to enable Stripe Subscription Payment Integration in CodeIgniter.

Further, note that you do need to separately download the Stripe PHP library. It is already saved in the source code. 

Library

The Stripe_lib.php is useful to integrate Stripe subscription payment. So, this file is dependent upon the configuration file (application/config/stripe.php). Also, it is dependable upon bindings library (application/third_party/stripe-php). 

  • _construct() – Define an API key & proceed with the Stripe class. 
  • addCustomer() – Use Stripe Customer API to add customers to Stripe account.
  • createPlan() – Specify a plan with Stripe Plan API
  • createSubscription() – Specify a subscription payment with Stripe subscription API
<?php 
defined('BASEPATH') OR exit('No direct script access allowed'); 
 
/** 
 * Stripe Library for CodeIgniter 3.x 
 * 
 * Library for Stripe payment gateway. It helps to integrate Stripe payment gateway 
 * in CodeIgniter application. 
 * 
 * This library requires the Stripe PHP bindings and it should be placed in the third_party folder. 
 * It also requires Stripe API configuration file and it should be placed in the config directory. 
 * 
 * @package     CodeIgniter 
 * @category    Libraries 
 * @author      PHPStackoverflow
 * @version     3.0 
 */ 
 
class Stripe_lib{ 
    var $CI; 
    var $api_error; 
     
    function __construct(){ 
        $this->api_error = ''; 
        $this->CI =& get_instance(); 
        $this->CI->load->config('stripe'); 
         
        // Include the Stripe PHP bindings library 
        require APPPATH .'third_party/stripe-php/init.php'; 
         
        // Set API key 
        \Stripe\Stripe::setApiKey($this->CI->config->item('stripe_api_key')); 
    } 
 
    function addCustomer($name, $email, $token){ 
        try { 
            // Add customer to stripe 
            $customer = \Stripe\Customer::create(array( 
                'name' => $name, 
                'email' => $email, 
                'source'  => $token 
            )); 
            return $customer; 
        }catch(Exception $e) { 
            $this->api_error = $e->getMessage(); 
            return false; 
        } 
    } 
     
    function createPlan($planName, $planPrice, $planInterval){ 
        // Convert price to cents 
        $priceCents = ($planPrice*100); 
        $currency = $this->CI->config->item('stripe_currency'); 
         
        try { 
            // Create a plan 
            $plan = \Stripe\Plan::create(array( 
                "product" => [ 
                    "name" => $planName 
                ], 
                "amount" => $priceCents, 
                "currency" => $currency, 
                "interval" => $planInterval, 
                "interval_count" => 1 
            )); 
            return $plan; 
        }catch(Exception $e) { 
            $this->api_error = $e->getMessage(); 
            return false; 
        } 
    } 
     
    function createSubscription($customerID, $planID){ 
        try { 
            // Creates a new subscription 
            $subscription = \Stripe\Subscription::create(array( 
                "customer" => $customerID, 
                "items" => array( 
                    array( 
                        "plan" => $planID 
                    ), 
                ), 
            )); 
             
            // Retrieve charge details 
            $subsData = $subscription->jsonSerialize(); 
            return $subsData; 
        }catch(Exception $e) { 
            $this->api_error = $e->getMessage(); 
            return false; 
        } 
    } 
}

Controller (Subscription.php)

So, this controller manages the plans & subscription payment procedure using Stripe library. 

__construct() –

  • You have to load the user model & Stripe library. 
  • Generate the logged-in user ID

index() –

  • Get the plans data from the database and view it for plan listing.
  • So, when payment form is submitted, 
  • Verify the stripe token validity
  • Extract stripe token, member, and plan information from the submitted data
  • Also, enable payment() function & pass posted data to initiate payment.
  • So, when payment gets successful, you have to redirect it to the subscription page. It is also an important step while enabling Stripe Subscription Payment Integration in CodeIgniter.

payment()

  • Fetch the user info and stripe token.
  • Get plan data from the database with getPlans() method of User model.
  • Add customer data including name, email, & stripe token using addCustomer() method of Stripe library. 
  • After that, create a plan with the createPlan() method of Stripe library.
  • Generate a subscription data by customer ID and plan ID with createSubscription() method of Stripe library.
  • So, when subscription gets successful, 
  • Enter transaction & subscription credentials into the database with insertSubscription() method of user model. 
  • Return subscription ID.

payment_status() –

  • Get the subscription credentials from the database with getSubscription() method of the user model. 
  • Also, view subscription status using subscription data. 
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); 
 
class Subscription extends CI_Controller { 
     
    function __construct() { 
        parent::__construct(); 
         
        // Load Stripe library 
        $this->load->library('stripe_lib'); 
         
        // Load product model 
        $this->load->model('user'); 
         
        // Get user ID from current SESSION 
        $this->userID = isset($_SESSION['loggedInUserID'])?$_SESSION['loggedInUserID']:1; 
    } 
     
    public function index(){ 
        $data = array(); 
         
        // If payment form is submitted with token 
        if($this->input->post('stripeToken')){ 
            // Retrieve stripe token and user info from the posted form data 
            $postData = $this->input->post(); 
             
            // Make payment 
            $paymentID = $this->payment($postData); 
             
            // If payment successful 
            if($paymentID){ 
                redirect('subscription/payment_status/'.$paymentID); 
            }else{ 
                $apiError = !empty($this->stripe_lib->api_error)?' ('.$this->stripe_lib->api_error.')':''; 
                $data['error_msg'] = 'Transaction has been failed!'.$apiError; 
            } 
        } 
         
        // Get plans from the database 
        $data['plans'] = $this->user->getPlans(); 
         
        // Pass plans data to the list view 
        $this->load->view('subscription/index', $data); 
    } 
     
    function payment($postData){ 
         
        // If post data is not empty 
        if(!empty($postData)){ 
            // Retrieve stripe token and user info from the submitted form data 
            $token  = $postData['stripeToken']; 
            $name = $postData['name']; 
            $email = $postData['email']; 
             
            // Plan info 
            $planID = $_POST['subscr_plan']; 
            $planInfo = $this->user->getPlans($planID); 
            $planName = $planInfo['name']; 
            $planPrice = $planInfo['price']; 
            $planInterval = $planInfo['interval']; 
             
            // Add customer to stripe 
            $customer = $this->stripe_lib->addCustomer($name, $email, $token); 
             
            if($customer){ 
                // Create a plan 
                $plan = $this->stripe_lib->createPlan($planName, $planPrice, $planInterval); 
                 
                if($plan){ 
                    // Creates a new subscription 
                    $subscription = $this->stripe_lib->createSubscription($customer->id, $plan->id); 
                     
                    if($subscription){ 
                        // Check whether the subscription activation is successful 
                        if($subscription['status'] == 'active'){ 
                            // Subscription info 
                            $subscrID = $subscription['id']; 
                            $custID = $subscription['customer']; 
                            $planID = $subscription['plan']['id']; 
                            $planAmount = ($subscription['plan']['amount']/100); 
                            $planCurrency = $subscription['plan']['currency']; 
                            $planInterval = $subscription['plan']['interval']; 
                            $planIntervalCount = $subscription['plan']['interval_count']; 
                            $created = date("Y-m-d H:i:s", $subscription['created']); 
                            $current_period_start = date("Y-m-d H:i:s", $subscription['current_period_start']); 
                            $current_period_end = date("Y-m-d H:i:s", $subscription['current_period_end']); 
                            $status = $subscription['status']; 
                             
                            // Insert tansaction data into the database 
                            $subscripData = array( 
                                'user_id' => $this->userID, 
                                'plan_id' => $planInfo['id'], 
                                'stripe_subscription_id' => $subscrID, 
                                'stripe_customer_id' => $custID, 
                                'stripe_plan_id' => $planID, 
                                'plan_amount' => $planAmount, 
                                'plan_amount_currency' => $planCurrency, 
                                'plan_interval' => $planInterval, 
                                'plan_interval_count' => $planIntervalCount, 
                                'plan_period_start' => $current_period_start, 
                                'plan_period_end' => $current_period_end, 
                                'payer_email' => $email, 
                                'created' => $created, 
                                'status' => $status 
                            ); 
                            $subscription_id = $this->user->insertSubscription($subscripData); 
                             
                            // Update subscription id in the users table  
                            if($subscription_id && !empty($this->userID)){ 
                                $data = array('subscription_id' => $subscription_id); 
                                $update = $this->user->updateUser($data, $this->userID); 
                            } 
                             
                            return $subscription_id; 
                        } 
                    } 
                } 
            } 
        } 
        return false; 
    } 
     
    function payment_status($id){ 
        $data = array(); 
         
        // Get subscription data from the database 
        $subscription = $this->user->getSubscription($id); 
         
        // Pass subscription data to the view 
        $data['subscription'] = $subscription; 
        $this->load->view('subscription/payment-status', $data); 
    } 
}

Model (User.php)

It manages fetch, insert, & update operations in the database. 

  • ___construct() – Specify database table names
  • updateUser() – Upgrade user data in the users table
  • getSubscription() – Get the subscription data from the users_subscriptions and plans table. 
  • insertSubscription() – Fill in the subscription data in the users_subscription table. 
  • getPlans() – Get the records from the plans table & return as an array. 

So, follow this step to enable Stripe Subscription Payment Integration in CodeIgniter.

<?php 
if ( ! defined('BASEPATH')) exit('No direct script access allowed'); 
 
class User extends CI_Model { 
    function __construct(){ 
        $this->userTbl        = 'users'; 
        $this->planTbl    = 'plans'; 
        $this->subscripTbl    = 'user_subscriptions'; 
    } 
     
    /* 
     * Update user data to the database 
     * @param data array 
     * @param id specific user 
     */ 
    public function updateUser($data, $id){ 
        $update = $this->db->update($this->userTbl, $data, array('id' => $id)); 
        return $update?true:false; 
    } 
     
    /* 
     * Fetch order data from the database 
     * @param id returns a single record 
     */ 
    public function getSubscription($id){ 
        $this->db->select('s.*, p.name as plan_name, p.price as plan_price, p.currency as plan_price_currency, p.interval'); 
        $this->db->from($this->subscripTbl.' as s'); 
        $this->db->join($this->planTbl.' as p', 'p.id = s.plan_id', 'left'); 
        $this->db->where('s.id', $id); 
        $query  = $this->db->get(); 
        return ($query->num_rows() > 0)?$query->row_array():false; 
    } 
     
    /* 
     * Insert subscription data in the database 
     * @param data array 
     */ 
    public function insertSubscription($data){ 
        $insert = $this->db->insert($this->subscripTbl,$data); 
        return $insert?$this->db->insert_id():false; 
    } 
     
    /* 
     * Fetch plans data from the database 
     * @param id returns a single record if specified, otherwise all records 
     */ 
    public function getPlans($id = ''){ 
        $this->db->select('*'); 
        $this->db->from($this->planTbl); 
        if($id){ 
            $this->db->where('id', $id); 
            $query  = $this->db->get(); 
            $result = ($query->num_rows() > 0)?$query->row_array():array(); 
        }else{ 
            $this->db->order_by('id', 'asc'); 
            $query  = $this->db->get(); 
            $result = ($query->num_rows() > 0)?$query->result_array():array(); 
        } 
         
        // return fetched data 
        return !empty($result)?$result:false; 
    } 
}

View

  1. subscription/index.php

Firstly, you need to select the layout of the dropdown with payment data form on the display page. 

Plan & payment form

You will collect user credentials under an HTML form. So, these details include name, email, card number. Also, it includes expiration date & CVC number.

  • The available plans are to be listed under a dropdown as shown below.
<div class="panel">
    <form action="" method="POST" id="paymentFrm">
        <div class="panel-heading">
            <h3 class="panel-title">Plan Subscription with Stripe</h3>
            <!-- Plan Info -->
            <p>
                <b>Select Plan:</b>
                <select name="subscr_plan" id="subscr_plan">
                    <?php foreach($plans as $plan){ ?>
                    <option value="<?php echo $plan['id']; ?>"><?php echo $plan['name'].' [$'.$plan['price'].'/'.$plan['interval'].']'; ?></option>
                    <?php } ?>
                </select>
            </p>
        </div>
        <div class="panel-body">
            <!-- Display errors returned by createToken -->
            <div id="paymentResponse"></div>
			
            <!-- Payment form -->
            <div class="form-group">
                <label>NAME</label>
                <input type="text" name="name" id="name" class="field" placeholder="Enter name" required="" autofocus="">
            </div>
            <div class="form-group">
                <label>EMAIL</label>
                <input type="email" name="email" id="email" class="field" placeholder="Enter email" required="">
            </div>
            <div class="form-group">
                <label>CARD NUMBER</label>
                <div id="card_number" class="field"></div>
            </div>
            <div class="row">
                <div class="left">
                    <div class="form-group">
                        <label>EXPIRY DATE</label>
                        <div id="card_expiry" class="field"></div>
                    </div>
                </div>
                <div class="right">
                    <div class="form-group">
                        <label>CVC CODE</label>
                        <div id="card_cvc" class="field"></div>
                    </div>
                </div>
            </div>
            <button type="submit" class="btn btn-success" id="payBtn">Submit Payment</button>
        </div>
    </form>
</div>

Validate Card with Stripe JS Library

Firstly, you need to integrate Stripe.js v3 library in the example script. So, it assures secure data transmission from browser to Stripe.

<script src="https://js.stripe.com/v3/"></script>

Secondly, you need below JavaScript code to generate a token using Stripe JS v3 library. So, it is an important step while enabling Stripe Subscription Payment Integration in CodeIgniter.

  • Define a publishable API key to determine your website with Stripe. 
  • Utilize Stripe components to enable payment form UI customizations.
  • Generate element instances with stripe.elements method.
  • Further, generate specific element instances with elements.create() method. 
  • Connect elements to the DOM with element.mount() method. 
  • Further, you have to generate a single-use token through stripe.createToken() method. Also, you need to create card elements through createToken() function. 
  • Moreover, you need to create a hidden input with the Stripe token. It will be created using stripeTokenHandler() function. You can append it to the payment data form.
  • In the end, you will see payment card details submitted on the server. If not, an error will display on your screen. 
<script>
// Create an instance of the Stripe object
// Set your publishable API key
var stripe = Stripe('<?php echo $this->config->item('stripe_publishable_key'); ?>');

// Create an instance of elements
var elements = stripe.elements();

var style = {
    base: {
        fontWeight: 400,
        fontFamily: 'Roboto, Open Sans, Segoe UI, sans-serif',
        fontSize: '16px',
        lineHeight: '1.4',
        color: '#555',
        backgroundColor: '#fff',
        '::placeholder': {
            color: '#888',
        },
    },
    invalid: {
        color: '#eb1c26',
    }
};

var cardElement = elements.create('cardNumber', {
    style: style
});
cardElement.mount('#card_number');

var exp = elements.create('cardExpiry', {
    'style': style
});
exp.mount('#card_expiry');

var cvc = elements.create('cardCvc', {
    'style': style
});
cvc.mount('#card_cvc');

// Validate input of the card elements
var resultContainer = document.getElementById('paymentResponse');
cardElement.addEventListener('change', function(event) {
    if (event.error) {
        resultContainer.innerHTML = '<p>'+event.error.message+'</p>';
    } else {
        resultContainer.innerHTML = '';
    }
});

// Get payment form element
var form = document.getElementById('paymentFrm');

// Create a token when the form is submitted.
form.addEventListener('submit', function(e) {
    e.preventDefault();
    createToken();
});

// Create single-use token to charge the user
function createToken() {
    stripe.createToken(cardElement).then(function(result) {
        if (result.error) {
            // Inform the user if there was an error
            resultContainer.innerHTML = '<p>'+result.error.message+'</p>';
        } else {
            // Send the token to your server
            stripeTokenHandler(result.token);
        }
    });
}

// Callback to handle the response from stripe
function stripeTokenHandler(token) {
    // Insert the token ID into the form so it gets submitted to the server
    var hiddenInput = document.createElement('input');
    hiddenInput.setAttribute('type', 'hidden');
    hiddenInput.setAttribute('name', 'stripeToken');
    hiddenInput.setAttribute('value', token.id);
    form.appendChild(hiddenInput);
	
    // Submit the form
    form.submit();
}
</script>

2. subscription/payment-status.php

On this page, you will see the subscription data & payment status.

<?php if(!empty($subscription)){ ?>
    <?php if($subscription['status'] == 'active'){ ?>
    <h1 class="success">Your Subscription Payment has been Successful!</h1>
    <?php }else{ ?>
    <h1 class="error">Subscription activation failed!</h1>
    <?php } ?>

    <h4>Payment Information</h4>
    <p><b>Reference Number:</b> <?php echo $subscription['id']; ?></p>
    <p><b>Transaction ID:</b> <?php echo $subscription['stripe_subscription_id']; ?></p>
    <p><b>Amount:</b> <?php echo $subscription['plan_amount'].' '.$subscription['plan_amount_currency']; ?></p>
    
    <h4>Subscription Information</h4>
    <p><b>Plan Name:</b> <?php echo $subscription['plan_name']; ?></p>
    <p><b>Amount:</b> <?php echo $subscription['plan_price'].' '.$subscription['plan_price_currency']; ?></p>
    <p><b>Plan Interval:</b> <?php echo $subscription['plan_interval']; ?></p>
    <p><b>Period Start:</b> <?php echo $subscription['plan_period_start']; ?></p>
    <p><b>Period End:</b> <?php echo $subscription['plan_period_end']; ?></p>
    <p><b>Status:</b> <?php echo $subscription['status']; ?></p>
<?php }else{ ?>
    <h1 class="error">The transaction has been failed!</h1>
<?php } ?>

It’s time to live Stripe Payment Gateway

So, you have ensured the Stripe checkout process by now. All these were necessary steps to enable Stripe Subscription Payment Integration in CodeIgniter. After this, it’s time to follow the below steps to make Stripe payment gateway live. 

  1. Firstly, open your Stripe account & go to the Developers » API keys page. 
  2. Secondly, get the API keys from live data status. 
  3. Lastly, set live API keys in place of Test API keys.

Conclusion

So, this is how you integrate the subscription payment system on your site. You can receive the monthly/weekly/yearly recurring bill payments with it. Moreover, your customers can easily make payment through debit/credit cards. Nevertheless, the recurring bill payment procedure using Stripe is user-friendly. Also, you can enable single page checkout for your customers. 

Also Read, A Complete Tutorial to install WordPress with Apache on Ubuntu 18.04

Step by step Magento 2 Tutorial for Beginners Level

Important links : 
CodeIgniter – https://www.codeigniter.com/

Stripe – https://stripe.com/en-in