Stripe Subscription Payment Integration in PHP

The Stripe Subscription API provides an easy way to integrate recurring payments on the website. If you want to implement the membership subscription system on the web application, subscription payment is required for recurring billing. The Stripe payment gateway helps to integrate recurring payment with Plans and Subscription API. Stripe subscription is a quick and effective way to allow your website members to purchase a membership online using their credit cards.

In Stripe subscription payment, the buyer is charged recurringly based on the specific interval. The member of your website can subscribe to a plan and make payments with their credit/debit card without leaving the website. In this tutorial, we will show you how to integrate Stripe subscription payment using PHP.

In the example script, we will implement the following functionality to accept payment for a subscription via Stripe Payment Gateway in PHP.

  • Create an HTML form to select a subscription plan and provide credit card information.
  • Attach Stripe card element to HTML form using Stripe JS library.
  • Securely transmit card details, validate, and create subscription with Stripe API.
  • Retrieve PaymentIntent and subscription info using Stripe API.
  • Confirm card payment with 3D Secure authentication that supports the Strong Customer Authentication (SCA) process.
  • Verify the card and create a subscription plan with Stripe API.
  • Store transaction data with subscription details in the database and display the payment status.

Before getting started to integrate Stripe Subscription payment API in PHP, take a look at the file structure.

stripe_subscription_payment_with_php/
├── config.php
├── dbConnect.php
├── index.php
├── payment_init.php
├── payment-status.php
├── stripe-php/
├── js/
|    └── checkout.js
└── css/
    └── style.css

Stripe Test API Keys

Before making the Stripe subscription payment gateway live, it needs to be checked whether the subscription process is working properly. You need the test API key data to check the subscription payment process.

  • Login to your Stripe account and navigate to the Developers » API keys page.
  • In the TEST DATA block, you’ll see the API keys (Publishable key and Secret key) are listed under the Standard keys section. To show the Secret key, click on the Reveal test key token button.
    stripe-developer-test-data-publishable-secret-api-keys-codexworld

Collect the Publishable key and Secret key to use later in the script.

Create Database Tables

To store the plans, members, and subscriptions information 3 tables are required in the database.

1. The following SQL creates a plans table to hold the subscription plans info in the MySQL database.

CREATE TABLE `plans` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  `price` float(10,2) NOT NULL DEFAULT 0.00 COMMENT 'Minimum amount is $0.50 US',
  `interval` enum('day','week','month','year') NOT NULL DEFAULT 'month',
  `interval_count` tinyint(2) NOT NULL DEFAULT 1,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

2. The following SQL creates a users table to hold the member’s info in the MySQL database.

CREATE TABLE `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `subscription_id` int(11) NOT NULL DEFAULT 0 COMMENT 'foreign key of "user_subscriptions" table',
  `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 DEFAULT NULL,
  `phone` varchar(15) COLLATE utf8_unicode_ci DEFAULT NULL,
  `created` datetime NOT NULL DEFAULT current_timestamp(),
  `modified` datetime NOT NULL DEFAULT current_timestamp(),
  `status` tinyint(1) NOT NULL DEFAULT 1 COMMENT '1=Active | 0=Inactive',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

3. The following SQL creates a user_subscriptions table to hold the subscription info in the MySQL database.

CREATE TABLE `user_subscriptions` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) NOT NULL DEFAULT 0 COMMENT 'foreign key of "users" table',
  `plan_id` int(5) DEFAULT NULL COMMENT 'foreign key of "plans" table',
  `stripe_customer_id` varchar(50) NOT NULL,
  `stripe_plan_price_id` varchar(255) DEFAULT NULL,
  `stripe_payment_intent_id` varchar(50) NOT NULL,
  `stripe_subscription_id` varchar(50) NOT NULL,
  `default_payment_method` varchar(255) DEFAULT NULL,
  `default_source` varchar(255) DEFAULT NULL,
  `paid_amount` float(10,2) NOT NULL,
  `paid_amount_currency` varchar(10) NOT NULL,
  `plan_interval` varchar(10) NOT NULL,
  `plan_interval_count` tinyint(2) NOT NULL DEFAULT 1,
  `customer_name` varchar(50) DEFAULT NULL,
  `customer_email` varchar(50) DEFAULT NULL,
  `plan_period_start` datetime DEFAULT NULL,
  `plan_period_end` datetime DEFAULT NULL,
  `created` datetime NOT NULL,
  `status` varchar(50) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

Before proceeding further, add some data to the plans table of the database, so that the user can select a plan for their subscription.

INSERT INTO `plans` (`id`, `name`, `price`, `interval`, `interval_count`) VALUES
(1, 'Daily Subscription', 15.00, 'day', 1),
(2, 'Weekly Subscription', 25.00, 'week', 1),
(3, 'Monthly Subscription', 75.00, 'month', 1),
(4, 'Quarterly Subscription', 199.00, 'month', 3),
(5, 'Half-yearly Subscription', 255.00, 'month', 6),
(6, 'Yearly Subscription', 349.00, 'year', 1);

Stripe API and Database Configuration (config.php)

In the config.php file, constant variables are defined for the Stripe API and database settings.

Stripe API Constants:

  • STRIPE_API_KEY – Specify the API Secret key.
  • STRIPE_PUBLISHABLE_KEY – Specify the API Publishable key.
  • STRIPE_CURRENCY – Currency code.

Database Constants:

  • DB_HOST – Specify the database host.
  • DB_USERNAME – Specify the database username.
  • DB_PASSWORD – Specify the database password.
  • DB_NAME – Specify the database name.
<?php 
/* Stripe API configuration
 * Remember to switch to your live publishable and secret key in production!
 * See your keys here: https://dashboard.stripe.com/account/apikeys
 */
define('STRIPE_API_KEY''Your_API_Secret_key');
define('STRIPE_PUBLISHABLE_KEY''Your_API_Publishable_key');
define('STRIPE_CURRENCY''USD');
 
// Database configuration 
define('DB_HOST''MySQL_Database_Host');
define('DB_USERNAME''MySQL_Database_Username');
define('DB_PASSWORD''MySQL_Database_Password');
define('DB_NAME''MySQL_Database_Name');

Note that: Stripe API Secret key and Publishable key will be found in the API Keys Data section of your Stripe account.

Database Connection (dbConnect.php)

The dbConnect.php file is used to connect the database using PHP and MySQL.

<?php  
// Connect with the database 
$db = new mysqli(DB_HOSTDB_USERNAMEDB_PASSWORDDB_NAME); 
 
// Display error if failed to connect 
if ($db->connect_errno) { 
    
printf("Connect failed: %s\n"$db->connect_error); 
    exit(); 
}

Stripe Subscription Form (index.php)

Include the configuration files and fetch the subscription plans from the database.

<?php 
// Include configuration file 
require_once 'config.php';

// Include the database connection file
include_once 'dbConnect.php';

// Fetch plans from the database
$sqlQ "SELECT * FROM plans";
$stmt $db->prepare($sqlQ);
$stmt->execute();
$stmt->store_result();
?>

Stripe JS Library:
Include the Stripe.js v3 library that helps securely send sensitive information to Stripe directly from the browser.

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

Checkout JS Script:
Include the custom script (checkout.js) to process subscription with Stripe API using JavaScript.

  • The STRIPE_PUBLISHABLE_KEY attribute is used to pass the Stripe API Key to the JS script.
<script src="js/checkout.js" STRIPE_PUBLISHABLE_KEY="<?php echo STRIPE_PUBLISHABLE_KEY?>" defer></script>

HTML Subscription Form:
Initially, all the plans are listed under a dropdown select box and an HTML form is defined to collect the user information (name and email) and card details (Card Number, Expiration Date, and CVC No.).

  • Define an HTML element (#card-element) to attach Card Elements by Stripe.js library.
  • Define element to display payment processing notification.
<div class="panel">
    <div class="panel-heading">
        <h3 class="panel-title">Subscription with Stripe</h3>
        
        <!-- Subscription Plan Info -->
        <div>
            <b>Select Plan:</b>
            <select id="subscr_plan" class="form-control">
                <?php 
                
if($stmt->num_rows 0){
                    
$stmt->bind_result($id$name$price$interval$interval_count);
                    while(
$stmt->fetch()){
                        
$interval_str = ($interval_count 1)?$interval_count.' '.$interval.'s':$interval;
                
?> <option value="<?php echo $id?>"><?php echo $name.' [$'.$price.'/'.$interval_str.']'?></option>                 <?php
                    
}
                }
                
?> </select> </div> </div> <div class="panel-body"> <!-- Display status message --> <div id="paymentResponse" class="hidden"></div> <!-- Display a subscription form --> <form id="subscrFrm"> <div class="form-group"> <label>NAME</label> <input type="text" id="name" class="form-control" placeholder="Enter name" required="" autofocus=""> </div> <div class="form-group"> <label>EMAIL</label> <input type="email" id="email" class="form-control" placeholder="Enter email" required=""> </div> <div class="form-group"> <label>CARD INFO</label> <div id="card-element"> <!-- Stripe.js will create card input elements here --> </div> </div> <!-- Form submit button --> <button id="submitBtn" class="btn btn-success"> <div class="spinner hidden" id="spinner"></div> <span id="buttonText">Proceed</span> </button> </form> </div> </div>

Subscription Checkout Handler Script (checkout.js)

The following JavaScript code is used to handle the subscription process with the Stripe JS v3 library.

  • Create an instance of the Stripe object and set the publishable API key.
  • Create card element and mount cardElement to HTML element (#card-element).
  • Attach an event handler (handleSubscrSubmit) to the subscription form.
  • handleSubscrSubmit() function is used to,
    • Post selected plan ID and customer details to the server-side script (payment_init.php).
    • Load paymentProcess() method and pass subscriptionId & Payment Intent clientSecret in it.
  • paymentProcess() function is used to,
    • Confirm PaymentIntent using stripe.confirmPayment of Stripe Payment Intents JS API.
    • Post the subscription and transaction info to the server-side script (payment_init.php) and redirect to the payment status page (payment-status.php).
  • showMessage() function helps to display status messages.
  • setLoading() function disable submit button and show a spinner on payment submission.
  • setProcessing() function disable the payment form and show the notification about payment processing.
// Get API Key
let STRIPE_PUBLISHABLE_KEY = document.currentScript.getAttribute('STRIPE_PUBLISHABLE_KEY');

// Create an instance of the Stripe object and set your publishable API key
const stripe = Stripe(STRIPE_PUBLISHABLE_KEY);

// Select subscription form element
const subscrFrm = document.querySelector("#subscrFrm");

// Attach an event handler to subscription form
subscrFrm.addEventListener("submit", handleSubscrSubmit);

let elements = stripe.elements();
var style = {
    base: {
        lineHeight: "30px",
        fontSize: "16px",
        border: "1px solid #ced4da",
    }
};
let cardElement = elements.create('card', { style: style });
cardElement.mount('#card-element');

cardElement.on('change', function (event) {
    displayError(event);
});

function displayError(event) {
    if (event.error) {
        showMessage(event.error.message);
    }
}

async function handleSubscrSubmit(e) {
    e.preventDefault();
    setLoading(true);
    
    let subscr_plan_id = document.getElementById("subscr_plan").value;
    let customer_name = document.getElementById("name").value;
    let customer_email = document.getElementById("email").value;
    
    // Post the subscription info to the server-side script
    fetch("payment_init.php", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ request_type:'create_customer_subscription', subscr_plan_id: subscr_plan_id, name: customer_name, email: customer_email }),
    })
    .then(response => response.json())
    .then(data => {
        if (data.subscriptionId && data.clientSecret) {
            paymentProcess(data.subscriptionId, data.clientSecret, data.customerId);
        } else {
            showMessage(data.error);
        }
        
        setLoading(false);
    })
    .catch(console.error);
}

function paymentProcess(subscriptionId, clientSecret, customerId){
    let subscr_plan_id = document.getElementById("subscr_plan").value;
    let customer_name = document.getElementById("name").value;
    
    // Create payment method and confirm payment intent.
    stripe.confirmCardPayment(clientSecret, {
        payment_method: {
            card: cardElement,
            billing_details: {
                name: customer_name,
            },
        }
    }).then((result) => {
        if(result.error) {
            showMessage(result.error.message);
            setLoading(false);
        } else {
            // Successful subscription payment
            // Post the transaction info to the server-side script and redirect to the payment status page
            fetch("payment_init.php", {
                method: "POST",
                headers: { "Content-Type": "application/json" },
                body: JSON.stringify({ request_type:'payment_insert', subscription_id: subscriptionId, customer_id: customerId, subscr_plan_id: subscr_plan_id,payment_intent: result.paymentIntent }),
            })
            .then(response => response.json())
            .then(data => {
                if (data.payment_id) {
                    window.location.href = 'payment-status.php?sid='+data.payment_id;
                } else {
                    showMessage(data.error);
                    setLoading(false);
                }
            })
            .catch(console.error);
        }
    });
}

// Display message
function showMessage(messageText) {
    const messageContainer = document.querySelector("#paymentResponse");
    
    messageContainer.classList.remove("hidden");
    messageContainer.textContent = messageText;
    
    setTimeout(function () {
        messageContainer.classList.add("hidden");
        messageText.textContent = "";
    }, 5000);
}

// Show a spinner on payment submission
function setLoading(isLoading) {
    if (isLoading) {
        // Disable the button and show a spinner
        document.querySelector("#submitBtn").disabled = true;
        document.querySelector("#spinner").classList.remove("hidden");
        document.querySelector("#buttonText").classList.add("hidden");
    } else {
        // Enable the button and hide spinner
        document.querySelector("#submitBtn").disabled = false;
        document.querySelector("#spinner").classList.add("hidden");
        document.querySelector("#buttonText").classList.remove("hidden");
    }
}

Stripe PHP Library

The Stripe PHP library is used to access the Stripe API in PHP. It helps to create customer, plan, and subscription with Stipre API. All the required library files are included in our source code, you don’t need to download it separately.

Process Subscription Payment (payment_init.php)

This server-side script is accessed by the client-side Fetch API in the JavaScript code (js/checkout.js) to create PaymentIntent, subscription, and process credit card payment using the Stripe API PHP library.

  • Include the Stripe PHP library.
  • Set API Secret key using setApiKey() method of Stripe class.
  • Retrieve JSON from the POST body using file_get_contents() and json_decode() in PHP.
  • Get the logged-in user ID from the SESSION.

If create_customer_subscription request is submitted:

  • Get the selected plan ID and buyer info from the form fields using the PHP $_POST method.
  • Fetch plan details from the database based on the selected plan ID.
  • Create customer using create() method of Stripe Customer API.
    • name – Customer name.
    • email – Customer email.
  • Create price using create() method of Stripe Price API.
    • unit_amount – A positive integer in cents (or 0 for a free plan) that will charge on a recurring basis.
    • currency – Three-letter ISO currency code in lowercase.
    • recurring.interval – Specify billing frequency (day, week, month, or year).
    • recurring.interval_count – The number of intervals between subscription billings. For example, interval=month and interval_count=2 bills every 2 months. Maximum of one year (1 year, 12 months, or 52 weeks) interval allowed.
    • product_data.name – Name of the subscription plan.
  • Create subscription using create() method of Stripe Subscription API.
    • customer – The identifier of the customer to subscribe.
    • items.price – The ID of the price object.
    • payment_behavior – Create Subscriptions with status=incomplete to make the 3DS authentication require to complete payment.
    • expand – Use latest_invoice.payment_intent
  • Return subscriptionId, clientSecret, and customerId to the client-side.

If payment_insert request is submitted:

  • Get the payment_intent, subscription_id, and customer_id from the form fields using the PHP $_POST method.
  • Create customer using create() method of Stripe Customer API.
  • Update PaymentIntent with the customer ID using update() method of Payment Intents API.
  • Retrieve customer details using the retrieve() method of Stripe Customer API.
  • Check whether the charge was successful and validate subscription status.
  • Retrieve customer details using the retrieve() method of Stripe Customer API.
  • If the user ID is not available in the SESSION, insert the customer details in the DB users table and get the user ID which will be associated with the subscription data.
  • Retrieve subscription details using the retrieve() method of Stripe Subscription API.
  • Insert transaction data into the database using MySQL Prepared Statements with PHP.
  • Return the DB insert ID as payment ID to the client-side.
<?php 
// Include the configuration file
require_once 'config.php';

// Include the database connection file
include_once 'dbConnect.php';

// Include the Stripe PHP library
require_once 'stripe-php/init.php';

// Set API key
\Stripe\Stripe::setApiKey(STRIPE_API_KEY);

// Retrieve JSON from POST body
$jsonStr file_get_contents('php://input');
$jsonObj json_decode($jsonStr);

// Get user ID from current SESSION
$userID = isset($_SESSION['loggedInUserID'])?$_SESSION['loggedInUserID']:0;

if(
$jsonObj->request_type == 'create_customer_subscription'){
    
$subscr_plan_id = !empty($jsonObj->subscr_plan_id)?$jsonObj->subscr_plan_id:'';
    
$name = !empty($jsonObj->name)?$jsonObj->name:'';
    
$email = !empty($jsonObj->email)?$jsonObj->email:'';
    
    
// Fetch plan details from the database
    
$sqlQ "SELECT `name`,`price`,`interval`,`interval_count` FROM plans WHERE id=?";
    
$stmt $db->prepare($sqlQ);
    
$stmt->bind_param("i"$subscr_plan_id);
    
$stmt->execute();
    
$stmt->bind_result($planName$planPrice$planInterval$intervalCount);
    
$stmt->fetch();

    
// Convert price to cents
    
$planPriceCents round($planPrice*100);
    
    
// Add customer to stripe
    
try {  
        
$customer \Stripe\Customer::create([
            
'name' => $name
            
'email' => $email
        
]); 
    }catch(
Exception $e) {  
        
$api_error $e->getMessage();  
    }
    
    if(empty(
$api_error) && $customer){
        try {
            
// Create price with subscription info and interval
            
$price \Stripe\Price::create([
                
'unit_amount' => $planPriceCents,
                
'currency' => STRIPE_CURRENCY,
                
'recurring' => ['interval' => $planInterval'interval_count' => $intervalCount],
                
'product_data' => ['name' => $planName],
            ]);
        } catch (
Exception $e) { 
            
$api_error $e->getMessage();
        }
        
        if(empty(
$api_error) && $price){
            
// Create a new subscription
            
try {
                
$subscription \Stripe\Subscription::create([
                    
'customer' => $customer->id,
                    
'items' => [[
                        
'price' => $price->id,
                    ]],
                    
'payment_behavior' => 'default_incomplete',
                    
'payment_settings' => ['save_default_payment_method' => 'on_subscription'],
                    
'expand' => ['latest_invoice.payment_intent'],
                ]);
            }catch(
Exception $e) {
                
$api_error $e->getMessage();
            }
            
            if(empty(
$api_error) && $subscription){
                
$output = [
                    
'subscriptionId' => $subscription->id,
                    
'clientSecret' => $subscription->latest_invoice->payment_intent->client_secret,
                    
'customerId' => $customer->id
                
];
            
                echo 
json_encode($output);
            }else{
                echo 
json_encode(['error' => $api_error]);
            }
        }else{
            echo 
json_encode(['error' => $api_error]);
        }
    }else{
        echo 
json_encode(['error' => $api_error]);
    }
}elseif(
$jsonObj->request_type == 'payment_insert'){
    
$payment_intent = !empty($jsonObj->payment_intent)?$jsonObj->payment_intent:'';
    
$subscription_id = !empty($jsonObj->subscription_id)?$jsonObj->subscription_id:'';
    
$customer_id = !empty($jsonObj->customer_id)?$jsonObj->customer_id:'';
    
$subscr_plan_id = !empty($jsonObj->subscr_plan_id)?$jsonObj->subscr_plan_id:'';

    
// Retrieve customer info
    
try {  
        
$customer \Stripe\Customer::retrieve($customer_id); 
    }catch(
Exception $e) {  
        
$api_error $e->getMessage();  
    }
    
    
// Check whether the charge was successful
    
if(!empty($payment_intent) && $payment_intent->status == 'succeeded'){
        
$payment_intent_id $payment_intent->id;
        
$paidAmount $payment_intent->amount;
        
$paidAmount = ($paidAmount/100);
        
$paidCurrency $payment_intent->currency;
        
$payment_status $payment_intent->status;
        
$created date("Y-m-d H:i:s"$payment_intent->created);

        
// Retrieve subscription info
        
try {  
            
$subscriptionData \Stripe\Subscription::retrieve($subscription_id); 
        }catch(
Exception $e) {  
            
$api_error $e->getMessage();  
        }

        
$default_payment_method $subscriptionData->default_payment_method;
        
$default_source $subscriptionData->default_source;
        
$plan_obj $subscriptionData->plan;
        
$plan_price_id $plan_obj->id;
        
$plan_interval $plan_obj->interval;
        
$plan_interval_count $plan_obj->interval_count;

        
$current_period_start $current_period_end '';
        if(!empty(
$subscriptionData)){
            
$created date("Y-m-d H:i:s"$subscriptionData->created);
            
$current_period_start date("Y-m-d H:i:s"$subscriptionData->current_period_start);
            
$current_period_end date("Y-m-d H:i:s"$subscriptionData->current_period_end);
        }
        
        
$customer_name $customer_email '';
        if(!empty(
$customer)){
            
$customer_name = !empty($customer->name)?$customer->name:'';
            
$customer_email = !empty($customer->email)?$customer->email:'';

            if(!empty(
$customer_name)){
                
$name_arr explode(' '$customer_name);
                
$first_name = !empty($name_arr[0])?$name_arr[0]:'';
                
$last_name = !empty($name_arr[1])?$name_arr[1]:'';
            }
            
            
// Insert user details if not exists in the DB users table
            
if(empty($userID)){
                
$sqlQ "INSERT INTO users (first_name,last_name,email) VALUES (?,?,?)";
                
$stmt $db->prepare($sqlQ);
                
$stmt->bind_param("sss"$first_name$last_name$customer_email);
                
$insertUser $stmt->execute();
                
                if(
$insertUser){
                    
$userID $stmt->insert_id;
                }
            }
        }
        
        
// Check if any transaction data exists already with the same TXN ID
        
$sqlQ "SELECT id FROM user_subscriptions WHERE stripe_payment_intent_id = ?";
        
$stmt $db->prepare($sqlQ); 
        
$stmt->bind_param("s"$payment_intent_id);
        
$stmt->execute();
        
$stmt->bind_result($id);
        
$stmt->fetch();
        
$prevPaymentID $id;
        
$stmt->close();
        
        
$payment_id 0;
        if(!empty(
$prevPaymentID)){
            
$payment_id $prevPaymentID;
        }else{
            
// Insert transaction data into the database
            
$sqlQ "INSERT INTO user_subscriptions (user_id,plan_id,stripe_customer_id,stripe_plan_price_id,stripe_payment_intent_id,stripe_subscription_id,default_payment_method,default_source,paid_amount,paid_amount_currency,plan_interval,plan_interval_count,customer_name,customer_email,plan_period_start,plan_period_end,created,status) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
            
$stmt $db->prepare($sqlQ);
            
$stmt->bind_param("iissssssdssissssss"$userID$subscr_plan_id$customer_id$plan_price_id$payment_intent_id$subscription_id$default_payment_method$default_source$paidAmount$paidCurrency$plan_interval$plan_interval_count$customer_name$customer_email$current_period_start$current_period_end$created$payment_status);
            
$insert $stmt->execute();
            
            if(
$insert){
                
$payment_id $stmt->insert_id;
                
                
// Update subscription ID in users table
                
$sqlQ "UPDATE users SET subscription_id=? WHERE id=?";
                
$stmt $db->prepare($sqlQ);
                
$stmt->bind_param("ii"$payment_id$userID);
                
$update $stmt->execute();
            }
        }
        
        
$output = [
            
'payment_id' => base64_encode($payment_id)
        ];
        echo 
json_encode($output);
    }else{
        echo 
json_encode(['error' => 'Transaction has been failed!']);
    }
}
?>

Payment Status (payment-status.php)

Based on the paymentIntent.status and payment confirmation by 3D Secure authentication, the user is redirected to this page.

  • Fetch transaction data from the database using PHP and MySQL.
  • Display subscription status and transaction info on the web page.
<?php 
// Include the configuration file 
require_once 'config.php';

// Include the database connection file 
require_once 'dbConnect.php';

$payment_id $statusMsg '';
$status 'error';

// Check whether the subscription ID is not empty
if(!empty($_GET['sid'])){
    
$subscr_id  base64_decode($_GET['sid']);
    
    
// Fetch subscription info from the database
    
$sqlQ "SELECT S.id, S.stripe_subscription_id, S.paid_amount, S.paid_amount_currency, S.plan_interval, S.plan_interval_count, S.plan_period_start, S.plan_period_end, S.customer_name, S.customer_email, S.status, P.name as plan_name, P.price as plan_amount FROM user_subscriptions as S LEFT JOIN plans as P On P.id = S.plan_id WHERE S.id = ?";
    
$stmt $db->prepare($sqlQ); 
    
$stmt->bind_param("i"$subscr_id);
    
$stmt->execute();
    
$stmt->store_result();
    
    if(
$stmt->num_rows 0){
        
// Subscription and transaction details
        
$stmt->bind_result($subscription_id$stripe_subscription_id$paid_amount$paid_amount_currency$plan_interval$plan_interval_count$plan_period_start$plan_period_end$customer_name$customer_email$subscr_status$plan_name$plan_amount);
        
$stmt->fetch();
        
        
$status 'success';
        
$statusMsg 'Your Subscription Payment has been Successful!';
    }else{
        
$statusMsg "Transaction has been failed!";
    }
}else{
    
header("Location: index.php");
    exit;
}
?> <?php if(!empty($subscription_id)){ ?> <h1 class="<?php echo $status?>"><?php echo $statusMsg?></h1> <h4>Payment Information</h4> <p><b>Reference Number:</b> <?php echo $subscription_id?></p> <p><b>Subscription ID:</b> <?php echo $stripe_subscription_id?></p> <p><b>Paid Amount:</b> <?php echo $paid_amount.' '.$paid_amount_currency?></p> <p><b>Status:</b> <?php echo $subscr_status?></p> <h4>Subscription Information</h4> <p><b>Plan Name:</b> <?php echo $plan_name?></p> <p><b>Amount:</b> <?php echo $plan_amount.' '.STRIPE_CURRENCY?></p> <p><b>Plan Interval:</b> <?php echo ($plan_interval_count 1)?$plan_interval_count.' '.$plan_interval.'s':$plan_interval?></p> <p><b>Period Start:</b> <?php echo $plan_period_start?></p> <p><b>Period End:</b> <?php echo $plan_period_end?></p> <h4>Customer Information</h4> <p><b>Name:</b> <?php echo $customer_name?></p> <p><b>Email:</b> <?php echo $customer_email?></p> <?php }else{ ?> <h1 class="error">Your Transaction been failed!</h1> <p class="error"><?php echo $statusMsg?></p> <?php ?>

Test Card Details

To test the Stripe subscription payment API integration, use the following test card numbers, a valid future expiration date, and any random CVC number.

  • 4242424242424242 – Visa
  • 4000056655665556 – Visa (debit)
  • 5555555555554444 – Mastercard
  • 5200828282828210 – Mastercard (debit)
  • 378282246310005 – American Express
  • 6011111111111117 – Discover

Test Card Numbers for 3D Secure Authentication:

  • 4000002500003155 – Require 3D Secure authentication (SCA)
  • 4000002760003184 – Require 3D Secure authentication (SCA)

Make Stripe Payment Gateway Live

Once the subscription API integration is completed and the payment process is working properly, follow the below steps to make Stripe payment gateway live.

  • Login to your Stripe account and navigate to the Developers » API keys page.
  • Collect the API keys (Publishable key and Secret key) from the LIVE DATA section.
  • In the config.php file, replace the Test API keys (Publishable key and Secret key) by the Live API keys (Publishable key and Secret key).
    define('STRIPE_API_KEY''Insert_Stripe_Live_API_Secret_Key_HERE');  
    define('STRIPE_PUBLISHABLE_KEY''Insert_Stripe_Live_API_Publishable_Key_HERE');

PayPal Subscriptions Payment Gateway Integration in PHP

Conclusion

Stripe subscription payment API is the easiest option to accept credit payment online for the subscription. You can add the recurring billing featured to the web application using Stripe API and PHP. Our example script helps you to charge the user recurringly in a specific interval via Stripe. Also, the 3D Secure authentication feature is integrated to make this Stripe integration script ready for SCA (Strong Customer Authentication). The functionality of this Stripe subscription payment script can be enhanced as per your needs.

Do you want to get implementation help, or enhance the functionality of this script? Click here to Submit Service Request

15 Comments

  1. Michael Said...
  2. Artem Said...
  3. Artem Said...
  4. Charles Said...
  5. Mukesh Said...
  6. Magnus Said...
  7. Sourav Kar Said...
  8. Keith Said...
  9. Raju Said...
  10. Nicolas Said...
  11. Nicolò Peroni Said...
  12. Pragna Said...
  13. Martin Teefy Said...
    • CodexWorld Said...

Leave a reply

keyboard_double_arrow_up