Loading Symbol

How to Integrate Stripe Payment API with CodeIgniter & PHP

Man With Credit Card Entering Payment Details on Laptop for E-Commerce

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:

  1. 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.
  2. Stripe stores the details in their database and sends you back an associated token.
  3. You can use this token to interact with Stripe’s API on behalf of this customer for one use.
  4. 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.
  5. 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.
  6. 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();

Loading GIF

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.

Loading GIF

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:

Stripe Customer Database Table Example

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.


Loading Symbol


One response to “How to Integrate Stripe Payment API with CodeIgniter & PHP

Leave a Reply

Your email address will not be published. Required fields are marked *