How to Integrate Stripe in PHP Applications?

Today, We want to share with you stripe payment gateway integration in php.In this post we will show you stripe custom checkout example php, hear for Payment gateway integration in PHP With Database Connection we will give you demo and example for implement.In this post, we will learn about CodeIgniter Stripe Payment Gateway Api Integration with an example.

Payment gateway integration tutorial for developers

So let’s start coding. As we will cover this tutorial with live demo to to integrate Stripe payment gateway in PHP, so the file structure for this example is following.

File structure for stripe payment gateway integration in PHP

 stripe
 -|ajax-endpoint
  |-create-checkout-session.php
 -|lib
 -|Service
 -|vendor
 -|webhook-ep
 -|cancel.php
 -|index.php
 -|init.php
 -|succes.php

index.php

<?php

use Pakainfo\stripeClient;

require_once __DIR__ . "/lib/stripeClient.php";
?>
<html>
<head>
<title>Checkout</title>
<link href="./assets/css/style.css" type="text/css" rel="stylesheet" />
<script src="https://js.stripe.com/v3/"></script>
<script src="./assets/js/stripe.js"></script>
</head>
<body>
    <div class="product-plan-tile">
    <h2><?php echo stripeClient::PRODUCT_NAME; ?></h2>
    <p>Best reference suitable for beginners to experts.</p>
    <div class="plan-pricing">$20 / month</div>
    <input type="button" id="subscribe" value="Subscribe Now" />
    </div>
    <div id="error-message"></div>
<script>
var stripe = Stripe('<?php echo stripeClient::STRIPE_PUBLISHIABLE_KEY; ?>');
//Setup event handler to create a Checkout Session when button is clicked
document.getElementById("subscribe").addEventListener("click", function(evt) {
    createCheckoutSession('<?php echo stripeClient::SUBSCRIPTION_PLAN_ID; ?>').then(function(data) {
      // Call Stripe.js method to redirect to the new Checkout page
      stripe.redirectToCheckout({
          sessionId: data.id
      }).then(handleResult);
    });
  });
</script>
</body>
</html>

cancel.php

<?php
use Pakainfo\stripeClient;

require_once __DIR__ . "/lib/stripeClient.php";
?>
<html>
<head>
<title>Payment Response - www.pakainfo.com</title>
<link href="./assets/css/style.css" type="text/css" rel="stylesheet" />
</head>
<body>
    <div class="subscription-response">
    <h2>Sorry. Your subscription request is not completed.</h2>
    <p>If you want to subscribe with us please try again.</p>
    <p>If you finding any difficulty in  completing the subscription flow, contact the support.</p>
    </div>
</body>
</html>

init.php

<?php
namespace Pakainfo;

use Pakainfo\Service;

require_once __DIR__ . '/Service/StripeService.php';
$stripeService = new StripeService();

$product = $stripeService->createProduct();
$planId = $stripeService->createPlan($product->id);

if(!empty($planId))
{
    echo "Product pricing plan is created and the plan id id is: ";
    print_r($planId);
}
?>

success.php

<?php
use Pakainfo\stripeClient;

require_once __DIR__ . "/lib/stripeClient.php";
?>
<html>
<head>
<title>Payment Response</title>
<link href="./assets/css/style.css" type="text/css" rel="stylesheet" />
</head>
<body>
    <div class="subscription-response">
    <h1>Thank you for subscribing with us.</h1>
    <p>You have subscribed for our "<?php echo stripeClient::PRODUCT_NAME; ?>" service's monthly plan.</p>
    <p>You have been notified about the status of your subscription shortly.</p>
    </div>
</body>
</html>

ajax-endpoint/create-checkout-session.php

<?php
namespace Pakainfo;

use Pakainfo\StripeService;

require_once __DIR__ . '/../Service/StripeService.php';
$stripeService = new StripeService();

$plan = json_decode($_POST["plan"]);
$planId = $plan->plan_id;

$session  = $stripeService->createCheckoutSession($planId);

echo json_encode($session);
?>

lib/stripeClient.php

<?php
namespace Pakainfo;
class stripeClient
{
    const STRIPE_PUBLISHIABLE_KEY = "pk_test_dfhdsfds4f5dsfdsFDSFDSFdf45d4f5d4sfdsfjFDGDFGfd655556fdgfdf5878dfgf";
    const STRIPE_SECRET_KEY = "sk_test_98fdgkfjdgljdfkjgkfdjgkjfdgjfdkjgkfdjgkjfdkjgkfjdgjfkjgkfjgkfjg9889998ggggjkfkgjfgkgkg5555fgf";

    //const SUBSCRIPTION_PLAN_ID = "prod_IL9ujdIA8gj5JW";
    const SUBSCRIPTION_PLAN_ID = "price_1HlSBQAREDQbc791fdlqHdQB";

    const PRODUCT_NAME = 'T-shirt test';

    const PRODUCT_TYPE = 'service';
}
?>

lib/MainController.php

<?php
/**
 * Copyright (C) 2019 Pakainfo
 *
 * Distributed under MIT license with an exception that,
 * you don’t have to include the full MIT License in your code.
 * In essense, you can use it on commercial software, modify and distribute free.
 * Though not mandatory, you are requested to attribute this URL in your code or website.
 */
namespace Pakainfo;

/**
 * Generic datasource class for handling DB operations.
 * Uses MySqli and PreparedStatements.
 *
 * @version 2.5 - recordCount function added
 */
class MainController
{
    const HOST = 'localhost';

    const USERNAME = 'root';

    const PASSWORD = '';

    const DATABASENAME = 'stripe_payment';

    private $link;

    function __construct()
    {
        $this->link = $this->getConnection();
    }

    public function getConnection()
    {
        $link = new \mysqli(self::HOST, self::USERNAME, self::PASSWORD, self::DATABASENAME);

        if (mysqli_connect_errno()) {
            trigger_error("Problem with connecting to database.");
        }

        $link->set_charset("utf8");
        return $link;
    }

    public function select($query, $argumentType = "", $argumentArray = array())
    {
        $sqlQQ = $this->link->prepare($query);

        if (! empty($argumentType) && ! empty($argumentArray)) {

            $this->bindQueryParams($sqlQQ, $argumentType, $argumentArray);
        }
        $sqlQQ->execute();
        $result = $sqlQQ->get_result();

        if ($result->num_rows > 0) {
            while ($row = $result->fetch_assoc()) {
                $resultset[] = $row;
            }
        }

        if (! empty($resultset)) {
            return $resultset;
        }
    }

    public function insert($query, $argumentType, $argumentArray)
    {
        $sqlQQ = $this->link->prepare($query);
        $this->bindQueryParams($sqlQQ, $argumentType, $argumentArray);

        $sqlQQ->execute();
        $insertId = $sqlQQ->insert_id;
        return $insertId;
    }

    public function execute($query, $argumentType = "", $argumentArray = array())
    {
        $sqlQQ = $this->link->prepare($query);

        if (! empty($argumentType) && ! empty($argumentArray)) {
            $this->bindQueryParams($sqlQQ, $argumentType, $argumentArray);
        }
        $sqlQQ->execute();
    }

    public function bindQueryParams($sqlQQ, $argumentType, $argumentArray = array())
    {
        $argumentValueReference[] = & $argumentType;
        for ($i = 0; $i < count($argumentArray); $i ++) {
            $argumentValueReference[] = & $argumentArray[$i];
        }
        call_user_func_array(array(
            $sqlQQ,
            'bind_argument'
        ), $argumentValueReference);
    }


    public function getRecordCount($query, $argumentType = "", $argumentArray = array())
    {
        $sqlQQ = $this->link->prepare($query);
        if (! empty($argumentType) && ! empty($argumentArray)) {

            $this->bindQueryParams($sqlQQ, $argumentType, $argumentArray);
        }
        $sqlQQ->execute();
        $sqlQQ->store_result();
        $recordCount = $sqlQQ->num_rows;

        return $recordCount;
    }
}

lib/StripePayment.php

<?php
namespace Pakainfo;

use Pakainfo\MainController;

class StripePayment
{
    private $ds;

    function __construct()
    {
        require_once __DIR__ . "/../lib/MainController.php";
        $this->ds = new MainController();
    }
    public function insertCustomer($customer)
    {
        $insertQuery = "INSERT INTO tbl_customer(customer_id, email) VALUES (?, ?) ";

        $argumentValue = array(
            $customer["customer_id"],
            $customer["customer_email"],
        );

        $argumentType = "ss";
        $this->ds->insert($insertQuery, $argumentType, $argumentValue);
    }

    public function insertSubscription($subscription)
    {
        $insertQuery = "INSERT INTO tbl_subscription(subscription_id, customer_id, subscription_plan, subscription_interval, current_period_start, current_period_end, subscription_status, subscription_created_date) VALUES (?, ?, ?, ?, ?, ?, ?, ?) ";

        $argumentValue = array(
            $subscription["id"],
            $subscription["customer_id"],
            $subscription["subscription_plan"],
            $subscription["subscription_interval"],
            $subscription["current_period_start"],
            $subscription["current_period_end"],
            $subscription["subscription_status"],
            $subscription["subscription_created_date"],
        );

        $argumentType = "ssssssss";
        $this->ds->insert($insertQuery, $argumentType, $argumentValue);
    }

    public function insertInvoice($invoice)
    {
        $insertQuery = "INSERT INTO tbl_invoice(invoice_number, subscription_id, invoice_id, customer_id, billing_email, currency, invoice_status, invoice_created_date) VALUES (?, ?, ?, ?, ?, ?, ?, ?) ";

        $argumentValue = array(
            $invoice["invoice_number"],
            $invoice["subscription"],
            $invoice["id"],
            $invoice["customer_id"],
            $invoice["billing_email"],
            $invoice["currency"],
            $invoice["invoice_status"],
            $invoice["invoice_created_date"],
        );

        $argumentType = "ssssssss";
        $inserId = $this->ds->insert($insertQuery, $argumentType, $argumentValue);
        if(!empty($inserId))
        {
            $this->insertInvoiceItem($invoice["invoice_items"], $inserId);
        }
    }

    public function insertInvoiceItem($invoiceItem, $invoiceMasterId)
    {
        $insertQuery = "INSERT INTO tbl_invoice_items(invoice_master_id, description, quantity, amount, currency) VALUES (?, ?, ?, ?, ?) ";

        $argumentValue = array(
            $invoiceMasterId,
            $invoiceItem[0]["description"],
            $invoiceItem[0]["quantity"],
            $invoiceItem[0]["amount"],
            $invoiceItem[0]["currency"]
        );

        $argumentType = "issss";
        $this->ds->insert($insertQuery, $argumentType, $argumentValue);
    }

    public function updateInvoice($invoice)
    {
        $query = "UPDATE tbl_invoice SET invoice_finalized_date = ?, invoice_status = ? WHERE invoice_id = ?";

        $argumentValue = array(
            $invoice["invoice_finalized_date"],
            $invoice["invoice_status"],
            $invoice["id"]
        );

        $argumentType = "sss";
        $this->ds->execute($query, $argumentType, $argumentValue);
    }

    public function updateInvoiceStatus($invoice)
    {
        $query = "UPDATE tbl_invoice SET invoice_status = ? WHERE invoice_id = ?";

        $argumentValue = array(
            $invoice["invoice_status"],
            $invoice["id"]
        );

        $argumentType = "ss";
        $this->ds->execute($query, $argumentType, $argumentValue);
    }

    public function updateSubscription($subscription)
    {
        $query = "UPDATE tbl_subscription SET subscription_status = ? WHERE subscription_id = ?";

        $argumentValue = array(
            $subscription["subscription_status"],
            $subscription["id"]
        );

        $argumentType = "ss";
        $this->ds->execute($query, $argumentType, $argumentValue);
    }
}
?>

Service/StripeService.php

<?php
namespace Pakainfo;

use Pakainfo\stripeClient;
require_once __DIR__ . '/../lib/stripeClient.php';

class StripeService
{
    function __construct()
    {
        require_once __DIR__ . "/../vendor/autoload.php";
        // Set your secret key. Remember to switch to your live secret key in production!
        // See your keys here: https://dashboard.stripe.com/account/apikeys
        \Stripe\Stripe::setApiKey(stripeClient::STRIPE_SECRET_KEY);
    }

    public function createProduct()
    {
        $product = \Stripe\Product::create([
            'name' => stripeClient::PRODUCT_NAME,
            'type' => stripeClient::PRODUCT_TYPE,
        ]);
        return $product;
    }

    public function createPlan()
    {
        $plan = \Stripe\Plan::create([
            'amount' => 1500,
            'currency' => 'usd',
            'interval' => 'month',
            'product' => ['name' => stripeClient::PRODUCT_NAME],
        ]);
        return $plan;
    }

    public function createCheckoutSession($planId)
    {
        $session = \Stripe\Checkout\Session::create([
            'payment_method_types' => ['card'],
            'subscription_data' => [
                'items' => [[
                    'plan' => $planId,
                ]],
            ],
            //'success_url' => 'http://localhost/stripe/ https://www.yourdomain.com/stripe-checkout/success.php?session_id={CHECKOUT_SESSION_ID}',
            'success_url' => 'http://localhost/stripe/success.php?session_id={CHECKOUT_SESSION_ID}',
            'cancel_url' => 'http://localhost/stripe/cancel.php',
            //'cancel_url' => 'https://www.yourdomain.com/stripe-checkout/cancel.php',
        ]);        
        return $session;
    }

    public function getStripeResponse()
    {
        $body = @file_get_contents('php://input');
        $event_json = json_decode($body);
        return $event_json;
    }
}
?>

webhook-ep/capture-response.php

<?php
namespace Pakainfo;

use Pakainfo\StripePayment;
use Pakainfo\StriService;

require_once __DIR__ . "/../lib/StripePayment.php";
require_once __DIR__ . "/../Service/StripeService.php";

$stripeService = new StripeService();

$response = $stripeService->getStripeResponse();

$stripePayment = new StripePayment();

if(!empty($response))
{
    switch($response->type) {
        case "invoice.payment_succeeded":
            $argument["id"] = $response->data->object->id;
            $argument["invoice_status"] = $response->data->object->status;
            $stripePayment->updateInvoiceStatus($argument);
            break;

        case "invoice.payment_failed":
            $argument["id"] = $response->data->object->id;
            $argument["invoice_status"] = $response->data->object->status;
            $stripePayment->updateInvoiceStatus($argument);
            break;

        case "customer.created":
            $argument = array();
            $argument["customer_id"] = $response->data->object->id;
            $argument["customer_email"] = $response->data->object->email;
            $stripePayment->insertCustomer($argument);
            break;

        case "customer.subscription.created":
            $argument = array();
            $argument["id"] = $response->data->object->id;
            $argument["customer_id"] = $response->data->object->customer;
            $argument["subscription_plan"] = $response->data->object->plan->id;
            $argument["subscription_interval"] = $response->data->object->plan->interval_count . " " .$response->data->object->plan->interval;
            $argument["subscription_status"] = $response->data->object->status;
            $argument["current_period_start"] = date("Y-m-d H:i:s", $response->data->object->current_period_start);
            $argument["current_period_end"] = date("Y-m-d H:i:s", $response->data->object->current_period_end);
            $argument["subscription_created_date"] = date("Y-m-d H:i:s", $response->data->object->created);
            $stripePayment->insertSubscription($argument);
            break;

        case "customer.subscription.updated":
            $argument = array();
            $argument["id"] = $response->data->object->id;
            $argument["subscription_status"] = $response->data->object->status;
            $stripePayment->updateSubscription($argument);
            break;

        case "invoice.created":
            $argument = array();
            $argument["id"] = $response->data->object->id;
            $argument["subscription_id"] = $response->data->object->subscription;
            $argument["invoice_number"] = $response->data->object->number;
            $argument["customer_id"] = $response->data->object->customer;
            $argument["billing_email"] = $response->data->object->customer_email;
            $argument["currency"] = $response->data->object->currency;
            $argument["invoice_status"] = $response->data->object->status;
            $argument["invoice_created_date"] = date("Y-m-d H:i:s", $response->data->object->created);

            $i = 0;
            foreach($response->data->object->lines->data as $data)
            {
                $argument["invoice_items"][$i]["amount"] = $data->amount;
                $argument["invoice_items"][$i]["currency"] = $data->currency;
                $argument["invoice_items"][$i]["quantity"] = $data->quantity;
                $argument["invoice_items"][$i]["description"] = $data->description;
                $i++;
            }

            $stripePayment->insertInvoice($argument);
            break;

        case "invoice.finalized":
            $argument["id"] = $response->data->object->id;
            $argument["invoice_finalized_date"] = date("Y-m-d H:i:s", $response->data->object->finalized_at);
            $argument["invoice_status"] = $response->data->object->status;
            $stripePayment->updateInvoice($argument);
            break;
    }
}
?>

assets/css/style.css

body {
    font-family: Arial;
    font-size: 0.9em;
    color: #232323;
}

#subscribe {
    background: #80c26c;
    border: #529b3c 1px solid;
    padding: 8px 30px;
    border-radius: 2px;
    font-size: 1em;
    width: 100%;
}

.product-plan-tile {
    width: 330px;
    border: #d0d0d0 1px solid;
    padding: 40px;
    text-align: center;
    border-radius: 2px;
    margin: 40px auto;
}

.product-plan-tile h2 {
    padding: 0px;
    margin: 0px 0px 10px 0px;
}

.plan-pricing {
    padding: 15px 0px 28px;
    font-size: 1.2em;
}

.subscription-response {
    max-width: 700px;
    margin: 100px auto;
    text-align: center;
}

assets/js/stripe.js

var createCheckoutSession = function(planId) {
  var plan = {
		    plan_id: planId
		};

		var data = new FormData();
		data.append( "plan", JSON.stringify( plan ) );
  return fetch("ajax-endpoint/create-checkout-session.php", {
    method: "POST",
    body: data
  }).then(function(result) {
	  console.log(result);
    return result.json();
  });
};

// Handle any errors returned from Checkout
var handleResult = function(result) {
  if (result.error) {
    var displayError = document.getElementById("error-message");
    displayError.textContent = result.error.message;
  }
};

I hope you get an idea about stripe v3 php example.
I would like to have feedback on my infinityknow.com blog.
Your valuable feedback, question, or comments about this article are always welcome.
If you enjoyed and liked this post, don’t forget to share.