This guide will show you how to integrate the Stripe Payment API with your existing CodeIgniter website. CodeIgniter’s Model-View-Controller structure and Query Builder Class make this integration pretty straightforward. If you’re used to working with API’s then this integration should be pretty simple for you.
I would highly recommend you use either Stripe Checkout or Elements JavaScript library to accept customer payment details. If you don’t, you won’t be able to make use of the client-side tokenization they offer. In this guide, I will cover an implementation of Elements as it is much more involved.
Overview
The beauty of Stripe is how it takes the customer’s payment details without them ever touching your site’s server. This means no PCI compliance and fewer headaches for you. Here’s an overview of the process we’ll be setting up:
- The user enters their credit card information into the payment form and clicks Submit. Stripe.js takes the credit card details and sends them to Stripe.
- Stripe stores the details in their database and sends you back an associated token.
- You can use this token to interact with Stripe’s API on behalf of this customer for one use.
- The form action that you specify in the form that the user fills out is where this token is Posted to. The form action is your handle payment method.
- In your handle payment method, you will create a Customer object with the token. This customer object will be sent to Stripe and you will store the ID of the customer in your database.
- From here, you can create a Charge object using the customer ID and that will charge the customer.
Front End Work
Add Checkout.js or Elements to the Front End
Since implementing checkout is very simple, I’ll show you how to create a custom payment form with Elements. Elements is included in Stripe.js. First, add Stripe.js to your page and create a form. You can add fields and CSS styles but, here is some basic HTML code for a payment form:
<form action="<?php echo base_url() ?>/payment/charge" method="post" id="payment-form">
<div class="form-row">
<label for="card-element">
Credit or debit card
</label>
<div id="card-element">;
<!-- A Stripe Element will be inserted here. -->
</div>
<div id="card-expiry-element" class="field">
<!-- A Stripe Element will be inserted here. -->
</div>
<div id="card-cvc-element" class="field">
<!-- A Stripe Element will be inserted here. -->
</div>
<!-- Used to display Element errors. -->
<div id="card-errors" role="alert"></div>
</div>
<button>Submit Payment</button>
</form>
<script src="https://js.stripe.com/v3/"></script>
It’s important to note that Stripe recommends developers put Stripe.js on every page in the site and not just the page containing the payment form. This is one way Stripe works to reduce fraud. Also, make sure you always load Stripe.js from Stripe’s server and not your own. You always want to have the most up-to-date version.
Collect the Card Information
Now we’re ready to collect the payment information the user entered and use Stripe.js to send it off to Stripe. Create a file called payment.js and add it to your page. Now create an instance of Stripe with your publishable key. Make sure to start with your test publishable key. Then call elements() on that instance to get started.
var stripe = Stripe('publishable_key');
var elements = stripe.elements();
It’s time to set up the input fields in our form. Note how the styles and placeholder are added below. You have to add these things using Stripe.js functions. The pattern is to create the element and then mount it to the existing form element by id. Below that, we’ll add an event listener to the card number input element. This will display any errors Stripe.js finds in the card number while the user is typing. The errors will show in the id=”card-errors” element.
// style elements
var style = {
base: {
iconColor: '#666EE8',
color: '#31325F',
fontSize: '16px',
'::placeholder': {
color: '#CFD7E0',
},
},
};
// Create an instance of the Card Element
var cardNumberElement = elements.create('cardNumber', {
style: style
});
cardNumberElement.mount('#card-number-element');
// Create an instance of the Card Expiry Element
var cardExpiryElement = elements.create('cardExpiry', {
style: style
});
cardExpiryElement.mount('#card-expiry-element');
// Create an instance of the Card CVC Element
var cardCvcElement = elements.create('cardCvc', {
style: style
});
cardCvcElement.mount('#card-cvc-element');
// check for card errors
cardNumberElement.addEventListener('change', function(event) {
var displayError = document.getElementById('card-errors');
if (event.error) {
displayError.textContent = event.error.message;
} else {
displayError.textContent = '';
}
});
Create Token and Submit
We need to convert the payment details into a token. This is 100% copied from the documentation. You probably won’t need to change it even for a custom payment form. It tokenizes the payment details, sends the details to Stripe, and sends the token to your back-end by submitting the form.
// Create a token or display an error when the form is submitted.
var form = document.getElementById('payment-form');
form.addEventListener('submit', function(event) {
event.preventDefault();
stripe.createToken(cardNumberElement).then(function(result) {
if (result.error) {
// Inform the user if there was an error
var errorElement = document.getElementById('card-errors');
errorElement.textContent = result.error.message;
} else {
// Send the token to your server
stripeTokenHandler(result.token);
}
});
});
function stripeTokenHandler(token) {
// Insert the token ID into the form so it gets submitted to the server
var form = document.getElementById('payment-form');
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();
}
In the form action attribute, we put “/payment/charge”. This is calling the Charge method of the Payment controller. We will create that after taking care of our back-end dependencies and API keys.
Back End Work
Add Stripe PHP Library
Before we can start the backend work, we’ll need a library to create customer objects, charge objects, etc. I recommend using Stripe’s PHP library and handling the dependency with Composer.
Make Publishable and Secret Keys Available
First, you’ll need to go over to your Stripe account. Select the API menu item on the left and copy the secret and publishable keys. Make sure you’ve select “Test Data” at the bottom of the left menu.
There are several ways to make these available. One way is to add them to your controller or a class your controller inherits and access them statically. Just make sure that they are available to any controller that needs them. To do this, add your secret and publishable keys in a public static array.
// Stripe TEST keys
public static $stripe = array(
"secret_key" => "sk_test_xxxxxxxxxxxxxxxxxxxxxxxx",
"publishable_key" => "pk_test_xxxxxxxxxxxxxxxxxxxxxxxx"
);
Access them statically:
MY_Controller::$stripe['secret_key'];
MY_Controller::$stripe['publishable_key'];
Create a Payment Controller and a Handle Payment Method
Create a controller called Payment.php. First, you’ll need to define the charge() method. This function will receive the one-time use token that Stripe creates for this payment. Don’t forget to set up your plans and prices in your Stripe Dashboard. You will need those details to process the payment.
I would recommend requiring users to sign up for an account on your site if you’re not doing this already. This will allow you to associate one simple user id from your site to one Stripe customer id.
/* Handle payment. This receives a token, 'stripeToken',
* to work with the customer's info.
*/
public function charge() {
$this->load->model('Model_payment');
$user_email = get_user_email();
get_user_id() = get_user_id();
$customer_id;
$trial_used = false;
// Check if they're already a customer. If not, create a new customer.
if($this->Model_payment->get_subscriber_by_id(get_user_id()) == false) {
\Stripe\Stripe::setApiKey(MY_Controller::$stripe['secret_key']);
// Create customer with payment source
$customer = \Stripe\Customer::create(array(
'email' => $user_email,
// Get the payment token ID submitted by the form:
'source' => $_POST['stripeToken']
));
$customer_id =$customer['id'];
// Save the Stripe customer ID to our database
$this->Model_payment->create_stripe_customer($customer['id'], get_user_id());
}
// Add logic to choose your plan and the amount to charge for it.
$plan = 'starter';
$amount = 10000;
// Add the plan to the customer (subscribe the customer)
\Stripe\Subscription::create(array(
"customer" => $customer_id,
"items" => array(
array(
"plan" => $plan,
),
),
));
// Charge the customer's card
$charge = \Stripe\Charge::create(array(
"amount" => $amount,
"currency" => "usd",
"description" => "Monthly Subscription",
"receipt_email" => $user_email,
"customer" => $customer_id,
));
// Check if the charge succeeded or failed
if ($charge['status'] == 'succeeded') {
$this->Model_payment->update_subscriber(get_user_id(), 'active');
// Show success message
} else {
// Tell the user that you're a failure and
// they should shop on someone else's site.
}
}
Create a Payment Model to Interact With the Database
This is a pretty simple model. It will need to create and update Stripe customers, check subscription status, and get Stripe customer id by your site’s user id. I won’t go into these because the data access techniques used are not unique to Stripe Payment processing.
Create a Database Table to Store Subscriptions
At the very least, you will need to store the Stripe Customer ID in a table with the user ID that your application gave the user when they created an account.
If you’re signing customers up for recurring payments via Stripe Subscriptions, I would recommend also adding a subscription status column. API calls are slower and less reliable. Anything from Stripe that your application checks a lot should be stored in this table. Here a simple example of a Stripe customers table:

Now your users should be able to enter their billing information and sign up for a subscription using your payment form. If you’re having trouble, don’t hesitate to consult Stripe’s amazing documentation. You can also leave a comment below. Once everything is working, just swap out your references to the test keys, and add your plans and pricing to your Stripe Dashboard.
Great article! Thank you for all the details and sample code!