Simple Payments with Stripe and Laravel

In this article you will learn:

  • How to configure Stripe with Laravel

  • How to make single charges through Stripe

The example project is a website where you can sell digital products, like ebooks or audiobooks. The user can sign in and pay through Stripe. An administrative area will show the order information.

The full code is hosted on Github.

Project Configuration

Create a new project with:

Or:

In composer.json install Cashier:

In the terminal:

Go to config/app.php and add the Cashier Provider to the providers and alias sections.

Despite using Cashier, there is no need to setup subscriptions right now. We only need a simple payment, so let’s use the default SDK instructions on the Stripe site.

We will be using SQLite for storing data. Create the database file in database/database.sqlite (assuming you are in the root of the project):

Set the environmental variables in the .env file, located in the root of the project:

You can delete the DB_DATABASE, DB_USERNAME, DB_PASSWORD, DB_HOST and DB_PORT variables.

Finally, change the line in config/database.php :

To:

Launch your server and you should be able to see the project running in http://localhost:8000

Stripe Configuration

Secret Key

First, create a Stripe account in https://dashboard.stripe.com/register or login https://dashboard.stripe.com/login.

In your dashboard, click in Your Account → API Keys. You will find a set of test keys and live keys. Don’t bother with the live ones – you will only use them when you application is ready to charge users. For now, copy the Test Secret Key and the Test Publishable Key and paste in your .env file:

We need to put the secret key in a secure place. The .env file is exactly what we need. This file, by default, are ignored by version control, so you can push in to the server without worrying.

IMPORTANT: If you are developing this in a production server you need to manually create an .env file. Generally, you want to copy the local/development one and just adapt to your server configuration.

After that, go to app/services.php and add the following:

The env function allow us to get the values defined in the .env file. If you follow this instruction Laravel probably have already taken care of it.

Cashier Tables

Cashier needs a user and a subscription table. We’re only going to use the subscription table in later tutorials, but is good to have everything ready when the time comes.

For the users table, let’s use the default that comes with Laravel. Since we need an administrative area to see the orders, add the admin column in the up() function. It should be in app/database/migrations:

Create the following migration:

Your migration should look like app/database/migrations/2016_08_24_202103_add_cashier_tables.php

Here we are adding some fields to the users table and creating the subscription table. We are only going to use the subscription in the next tutorial, so don’ worry about. Don’t forget to drop the subscriptions table in the down() function!

Execute the migration:

Configuring the User

Laravel also comes with a User model out of the box. In app/User.php add the Billable trait:

This is another very important aspect of Cashier. The Billable trait is responsible to add some methods to the user model. Through then we can subscribe the user etc. Again, we’re not going to use it now, so don’t worry about.

Creating the Models and Migrations

In addition to the user model, we also need the product and order models. You can create both the models and migrations with the following commands:

Product Migration

In app/database/migration/2016_08_25_001434_create_products_table.php:

Stripe calculate the price in cents. For example, if you need to charge $19.90, pass 1990 to the checkout form. The price must be in integer, not in decimal.

Order Migration

In app/database/migration/2016_08_25_001822_create_orders_table.php:

Defing Relationships

We need to show the orders in the administrative area. The easiest way is to define the relationships in the Order model.

In app/Order.php:

Populating the Database

Let’s use Tinker to populate the database:

Sometimes you wouldn’t be able to use some keys in Tinker, for example, the up key to return to a previously command. You can use rlwrap to solve this issue:

In tinker, enter the following:

Creating the Controller

With the auth command Laravel handles all the authentication and registration for us:

The product controller is responsible for showing all the products for the user:

In app/Http/Controllers/ProductController.php:

This controller simply loads all our products from the database in to the template.

To handle our payments we need one more controller:

In app/Http/Controllers/OrderController.php:

This controller holds the core of our application:

  • getAllOrders() – simply return all orders and show in the admin area.

  • postPayWithStripe() – responsible for getting the parameters. We pass a product object and the stripeToken, which comes from the request. This token holds the credit information from the client.

  • chargeCustomer() – we need to make sure that the user is in the Stripe system. Thus, we check if the user is already a Stripe customer. If positive, we retrieve it. Otherwise, a function create a new customer. In the end, we will have created or retrieved a customer.

  • createStripeCharge() – we can pass values to create a charge using the Charge::create. An important detail is that the “customer” attribute is equal to the customer ID. This is not the user ID on our application, but the Stripe ID. Remember, when dealing the customers we are talking about Stripe.

  • createStripeCustomer() – creates a new Stripe Customer. We also set the stripe_id in our database as the customer ID. Note that we’re always referring to the user Auth::user().

  • isStripeCustomer() – to check if a user is a Stripe customer we only need to see if the stripe_id is not null. Remember that in the createStripeCustomer we set the stripe_id to the customer ID.

  • postStoreOrder() – finally, we create a new Order redirect the user to the index page.

At last, create a new middleware to only limit access to the administrative area:

In app/Http/Middleare/AdminMiddleware.php

This is a very simply middleware. The handle function checks if the user is authenticate and if he is the administrator. If positive the request continues, otherwise we redirect the user to the index.

Register the admin middleware in app/Http/Kernel.php:

Defining the Routes

In app/Http/Route.php:

Creating the Views

In resources/views/index.blade.php:

If you are familiar with Blade the only thing different here is the Stripe button. There is no need to set up a form since we’re using the checkout.js solution. When the user clicks on Pay With Stripe, our application sends a request to validate the credit card information and returns the request.

An important aspect of checkout.js is that we can pass various parameters. For example, here the amount is equal to the product price, as well as the data-description is the ebook name. Besides, we’re also passing the currency, which in this case is USD. It’s very important that you put the currency that your account supports. Otherwise, Stripe will throw an error.

A “stripeToken” is returned if everything is correct. We used this token to charge the user. Visit https://stripe.com/docs/checkout/tutorial for more information.

In resources/views/admin.blade.php:

The administrative area only shows the user e-mail and product for each placed order. From here you can send your digital product, for example. We’re nothing going to add more functionality than this since this tutorial is about showing the Stripe payment process. This page is accessible through localhost:8000/admin only for the admin user.

Testing

For testing we can use some dummy credit card. Click on Pay With Stripe and put 4242 4242 4242 4242 as a credit card number as well any email. The expiration date can be any future date and the CVC any three or four digits. Click in Pay and you should be seeing a thanks message. Login as the administrator and head to localhost:8000/admin. Your order should be in place.

Conclusion

Stripe makes single payments very easy to handle. Remember that you also need to create a Stripe Customer for every user in your application. Without this, you probably are going to find errors with the token.

After creating or retrieving a customer, the Stripe::charge method takes care of charging the given credit card. Our application only starts to handle the payment after the confirmation. From here you could save the data in Orders table or send an email to the user. For more information visit https://stripe.com/docs.

Share you thoughts in the comment section below.

Share on FacebookShare on Google+Tweet about this on TwitterShare on LinkedInShare on Reddit

Published by

Feliciano

Developer with experience in PHP, Laravel, Ruby on Rails, and Android. B.S. in Information Technology.

6 thoughts on “Simple Payments with Stripe and Laravel”

  1. Thank you for this clean explanation of stripe integration in laravel.
    I just have not seen how to handle subscription , something like $user->newSubscription ….

  2. hi!

    i have some problem with the display 🙁
    this is an example of my admin.blade.php and i have the same issue in index.blade.php… (php:5.6.25,laravel 5.2,i just change sqlite for mysql)

    @extends(‘layouts.app’) @section(‘content’)
    Orders

    @foreach ($orders as $order)
    {{ $order->email}} – {{ $order->product }}
    @endforeach
    @endsection

    sorry for my english i’ m from france ,how can help me please !

  3. Hi
    I’m trying to integrate this code into my project but it’s not working, then I debug it and found stripeToken “$request->input(‘stripeToken’)” always empty on OrderController postPayWithStripe method, can you please tell me is this problem or any other problems?

    Thanks

  4. Hi,
    @Sam, @Sandy,
    There is a few things to change to make this example working. Orders migration is out of date in this example. Orders table contain product_id and user_id keys but the OrderController try to save email and product name in the method postStoreOrder. The admin.blade view and Order model needs to be changed accordingly.

    1) In Order model change hasOne to belongsTo relations for both products() and user() methods:
    //in App\Order.php
    class Order extends Model
    {
    protected $fillable = [‘user_id’, ‘product_id’];
    public function user()
    {
    return $this->belongsTo(‘App\User’);
    }
    public function product()
    {
    return $this->belongsTo(‘App\Product’);
    }
    }

    2) In orders view:
    //in admin.blade.php
    @foreach ($orders as $order)

    {{ $order->user()->first()->email}} – {{ $order->product()->first()->name }}

    @endforeach
    3) in OrderController.php

    public function createStripeCharge($product_id, $product_price, $product_name, $customer)
    {
    //…all good until last line
    return $this->postStoreOrder($product_id);
    }

    //Change last method call to save product_id and user_id
    public function postStoreOrder($product_id)
    {
    Order::create([
    ‘user_id’ => Auth::user()->id,
    ‘product_id’ => $product_id
    ]);
    //…all good after this
    }
    Working example here : https://github.com/remichautemps/laravel-stripe-bitcoin

Leave a Reply to Kenneth Brøgger-Luplau Cancel reply

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