Welcome, Laravel enthusiasts! In this guide, we're going to talk about integrating one of the most powerful and popular online payment gateways - Stripe, into your Laravel application.

Stripe is a fantastic payment platform with excellent API documentation and robust functionality, making it a favourite among many developers. Laravel, on the other hand, is a comprehensive PHP framework that takes much of the pain out of web development. So why would you want to use Stripe with Laravel? Well, simply put, by combining these two, you can build powerful applications that handle payments with ease, thereby allowing you to monetize your product or service.

By the end of this article, you will have a complete understanding of how to integrate Stripe into a Laravel application, complete with user payments and subscriptions. Specifically, we'll cover how to set up your Stripe account, configure Laravel Cashier, build a payment model and checkout process, handle subscriptions, and even test payments.

Whether you're planning to launch a full-fledged e-commerce website, a Software-as-a-Service (SaaS) application, or simply wish to incorporate a paywall into your site, this guide will give you the know-how to do so. So, grab a cup of your favourite beverage and let's dive into the world of Laravel and Stripe integration!

Stay with us and by the end of this journey, you'll be well-equipped to monetize your Laravel applications. Let's get started!

Prerequisites

Before we embark on this exciting journey of integrating Stripe with Laravel, there are a few prerequisites that you need to have in place.

Knowledge Requirements

You should have a basic understanding of the following:

  1. PHP: Laravel is a PHP framework, so a basic understanding of PHP is necessary.
  2. Laravel: Some familiarity with Laravel, its structure, and its concepts, like routing, controllers, and views, will be beneficial.
  3. Basic HTML and CSS: You'll need to create a basic front-end interface for the payment process.

Resource Requirements

You'll also need:

  1. Laravel Environment: You should have a Laravel development environment set up on your computer. This includes having Composer installed, as Laravel uses it for package management. If you haven't set up Laravel yet, you can check out Laravel's official installation guide.
  2. Stripe Account: You'll need a Stripe account. Don't worry if you don't have one yet. We'll walk through the process of creating one in the next section.

Please note, this tutorial is based on Laravel 10.x and Stripe's latest API version available as of June 2023.

Now that we've covered the prerequisites, it's time to dive into the meat of this guide. In the next section, we'll start setting up our Stripe account and configuring our Laravel environment to integrate with Stripe.

Setting up Stripe

The first step in integrating Stripe with Laravel is to set up your Stripe account. If you don't already have a Stripe account, head over to Stripe's website to create one.

Creating a Stripe Account

  1. Visit the Stripe website and click on 'Start Now' to create a new account.
  2. Fill in your business details, including the business type, industry, phone number, and email address.
  3. After registration, verify your email address and set up two-factor authentication for added security.
  4. Finally, navigate to the dashboard and complete the account activation process by providing the necessary business and bank details. Stripe requires these to remit payments to your bank account.

Getting API Keys from Stripe

For Laravel to interact with Stripe, we need Stripe's API keys. Here's how to get them:

  1. From your Stripe Dashboard, navigate to the 'Developers' menu and then click on 'API keys'.
  2. Here, you'll see two types of keys: Publishable key and Secret key. Both keys are unique to your account and allow your Laravel application to interact with the Stripe API.
  3. Keep this page open or copy these keys somewhere secure, as we'll need them when configuring Laravel Cashier.

Great job on setting up Stripe! Now that we have our Stripe account ready and our API keys at hand, let's move on to installing and configuring Laravel Cashier in the next section.

Installing and Configuring Laravel Cashier

Laravel Cashier provides an expressive, fluent interface to Stripe's subscription billing services. It handles almost all of the boilerplate subscription billing code you are dreading to write. In this section, we'll install and configure Laravel Cashier.

Installation

First, let's install the Laravel Cashier via the Composer package manager:

composer require laravel/cashier

Database Migrations

Next, you need to migrate the Cashier's table. This table will keep track of all your customer's subscriptions. Run the following artisan command to migrate the tables:

php artisan migrate

Model Setup

The next step is to add the Billable trait to your billable model (this is typically the 'User' model):

<?php

namespace App\Models;

use Laravel\Cashier\Billable;
use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    use Billable;
}
app/Models/User.php

Configuring .env Variables

Finally, we have to set up the Stripe API keys in our Laravel application. Open your .env file and add the following lines:

STRIPE_KEY=your_stripe_publishable_key
STRIPE_SECRET=your_stripe_secret_key
.env

Remember to replace your_stripe_publishable_key and your_stripe_secret_key with the actual keys you got from your Stripe account.

This concludes the Cashier setup process. With this in place, we have the fundamentals ready to start accepting payments with Stripe in our Laravel application. Let's move to creating a payment model in the next section.

Creating a Payment Model

Now that we've configured Laravel Cashier, let's create a model to manage our Stripe payment data. We'll call this model 'Payment'. It's also crucial to set up migrations and the database for this model.

Creating the Payment Model and Migration

Let's start by creating the model and migration using Laravel's artisan command:

php artisan make:model Payment -m

The -m option creates a migration file for the Payment model.

Setting up the Payments Table

Open the newly created migration file located in database/migrations. We need to define the structure of our payments table here. Update the up() method in the migration to look like this:

public function up()
{
    Schema::create('payments', function (Blueprint $table) {
        $table->id();
        $table->foreignId('user_id')->constrained();
        $table->string('stripe_id');
        $table->string('amount');
        $table->timestamps();
    });
}

In this schema, user_id is a foreign key referencing the user who made the payment, stripe_id stores the Stripe payment ID, and amount is the amount of the payment.

Running the Migration

After setting up the migration, we need to run it to create the payments table in our database. You can do so by running the following command:

php artisan migrate

Great! Now that we've created our Payment model and set up its corresponding table in the database, we're ready to start building our checkout process, which we'll cover in the next section.

Building a Checkout Process

A crucial part of accepting payments is the checkout process. This is where users will enter their payment details and complete their purchase. Let's create the routes, controllers, and views for a simple checkout page.

Creating the Controller

First, let's create a controller named CheckoutController:

php artisan make:controller CheckoutController

Now, open the CheckoutController.php file that's been created in the app/Http/Controllers directory and add a checkout method:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\User;

class CheckoutController extends Controller
{
    public function checkout(User $user)
    {
        // Generate a new Stripe Checkout Session for the user's order
        $checkout = $user->checkout([
            'line_items' => [[
                'price_data' => [
                    'currency' => 'eur',
                    'product_data' => [
                        'name' => 'Your Product',
                    ],
                    'unit_amount' => 2000,
                ],
                'quantity' => 1,
            ]],
            'mode' => 'payment',
            'success_url' => route('success'),
            'cancel_url' => route('cancel'),
        ]);

        return view('checkout', ['checkout' => $checkout]);
    }
}
app/Http/Controllers/CheckoutController.php

This method generates a new Stripe Checkout session and passes it to our checkout view. The product name and unit amount are hardcoded for the purpose of this tutorial, but you'd typically retrieve these from your database.

Creating the Routes

Next, we need to define the routes for our checkout process. Open the routes/web.php file and add the following lines:

use App\Http\Controllers\CheckoutController;

Route::get('/checkout/{user}', [CheckoutController::class, 'checkout'])->name('checkout');

Route::get('/success', function () {
    return 'Payment successful!';
})->name('success');

Route::get('/cancel', function () {
    return 'Payment canceled!';
})->name('cancel');
routes/web.php

These routes define the checkout page for a given user and the success and cancellation pages.

Creating the View

Finally, let's create the checkout view. In the resources/views directory, create a new file called checkout.blade.php and add the following code:

<!DOCTYPE html>
<html>
<head>
    <title>Stripe Checkout</title>
    <script src="<https://js.stripe.com/v3/>"></script>
</head>
<body>
    <button id="checkout-button">Pay</button>

    <script>
        var stripe = Stripe('{{ env("STRIPE_KEY") }}');

        document.getElementById('checkout-button').addEventListener('click', function () {
            stripe.redirectToCheckout({ sessionId: '{{ $checkout->id }}' })
                .then(function (result) {
                    if (result.error) {
                        alert(result.error.message);
                    }
                });
        });
    </script>
</body>
</html>
resources/views/checkout.blade.php

This simple view displays a "Pay" button that, when clicked, redirects the user to Stripe's checkout page. If there's an error, it's displayed to the user.

That's it! We've built a simple checkout process for our Laravel application. In the next section, we'll implement the logic for handling payments and subscriptions.

Handling Payments and Subscriptions

Now that we've built our checkout process, let's implement the logic for handling payments and subscriptions.

Implementing Single Charges

Single charges or one-time payments are a common operation in many e-commerce applications. When a user completes a payment on the Stripe checkout page, Stripe creates a PaymentIntent object that represents the payment.

In your CheckoutController, add a method to handle the payment:

public function handlePayment(Request $request, User $user)
{
    $paymentIntent = $request->input('payment_intent');
    $paymentStatus = $request->input('payment_status');

    if ($paymentStatus === 'succeeded') {
        $user->payments()->create([
            'stripe_id' => $paymentIntent,
            'amount' => $request->input('amount'),
        ]);

        return redirect()->route('success');
    } else {
        return redirect()->route('cancel');
    }
}
app/Http/Controllers/CheckoutController.php

Don't forget to add a route for this method in your routes/web.php file:

Route::post('/handle-payment/{user}', [CheckoutController::class, 'handlePayment'])->name('handle-payment');
routes/web.php

Implementing Subscriptions

Subscriptions are another common use case for online payments. With Laravel Cashier, managing subscriptions is straightforward.

The User model now exposes a newSubscription method to create a new subscription:

$user->newSubscription('default', 'price_EUR')->create($paymentMethod);

In this line of code, 'default' is the name of the subscription, 'price_EUR' is the ID of the pricing plan in Stripe, and $paymentMethod is the payment method ID returned from Stripe.

You can also check the subscription status with methods like $user->subscribed('default'), $user->subscription('default')->renewing(), and $user->subscription('default')->onGracePeriod().

These examples only cover the basics of handling payments and subscriptions. Depending on your application, you might need to handle more complex scenarios, like updating or cancelling subscriptions, applying coupons, and handling invoices. Fortunately, Laravel Cashier makes these tasks relatively easy.

Next, we'll look at how to test our setup to ensure everything is working as expected.

Testing the Payment Flow

Testing is a vital part of the development process, and this holds for your payment flow as well. Stripe provides a suite of test cards for you to test different scenarios.

Stripe Testing

You can access Stripe's testing suite through the Stripe Dashboard:

  1. In your Stripe Dashboard, navigate to "Developers" -> "API keys".
  2. You'll see a toggle at the top to switch between viewing test data and live data. Make sure "View test data" is turned on.
  3. Copy the Test Publishable Key and Test Secret Key and use them in your .env file instead of the live keys.

Stripe provides a list of card numbers that you can use for testing. You can find these in their testing guide in the Stripe Docs. For example, you can use 4242 4242 4242 4242 for a card that will always approve payments.

Testing in Laravel

Now you're ready to test your Laravel application:

  1. Make sure your application is running (you can use php artisan serve if you're testing locally).
  2. Navigate to the checkout page for a user (for example, http://localhost:8000/checkout/1).
  3. Click the "Pay" button. You should be redirected to Stripe's checkout page.
  4. Enter a test card number, a future expiration date, any three digits for the CVC, and any valid postal code.
  5. Complete the payment.

If everything is set up correctly, you should be redirected to your Payment successful! page. You should also see the payment in your Stripe Dashboard under "Payments", and in your database under the 'payments' table.

Remember to switch back to live mode and replace the test keys with live keys in your .env file before deploying your application.

In the final section of our guide, we'll summarize the steps we've taken and discuss where to go next.

Wrapping Up and Next Steps

Congratulations! You've successfully set up a Stripe payment gateway in your Laravel application. We've covered a lot of ground:

  1. We introduced Laravel and Stripe, explaining why they're a powerful combination for handling online payments.
  2. We discussed how to create and configure a Stripe account, ensuring it accepts European currencies and complies with European payment regulations.
  3. We walked through installing and configuring Laravel Cashier, an interface that simplifies the interaction between Laravel and Stripe.
  4. We created a Payment model to manage our payment data.
  5. We built a simple checkout process, including routes, controllers, and views.
  6. We demonstrated how to handle payments and subscriptions.
  7. Finally, we tested the payment flow using Stripe's test mode and cards.

Now that you have a working payment system, you might want to enhance it further:

  • Customize the checkout page: Tailor the Stripe checkout page to match your brand. You can add your logo, choose your brand's colors, and even localize the page to the user's language.
  • Refine your subscriptions: You might want to offer different subscription plans, trial periods, or discounts. You could also allow users to upgrade, downgrade or cancel their subscriptions.
  • Handle more complex scenarios: We've covered the basics, but there's much more you can do with Stripe and Laravel Cashier. You can handle refunds, webhooks, one-time fees, and more.

That's it for our guide on setting up a Stripe payment gateway in Laravel. I hope you found it useful. Happy coding!

Conclusion

Setting up a payment gateway can seem daunting at first, but with Laravel and Stripe, it becomes a manageable task. In this guide, we have taken you step-by-step through the process of integrating Stripe into your Laravel application using Laravel Cashier.

By using Stripe, you're leveraging one of the most powerful, flexible, and secure payment platforms available. Combined with Laravel's expressive syntax and the utility of Laravel Cashier, it becomes an effective solution for handling payments and subscriptions in your application.

By following these steps, you have laid the foundation for a robust payment system. This is just the beginning. As your application grows, Stripe and Laravel offer many more features to further customize and optimize your payment processing.

Remember to always keep testing and refining your payment process. A smooth and secure checkout experience is key to maintaining the trust and satisfaction of your users.

Now that you've mastered the basics, you're well-prepared to explore the more advanced features of Laravel and Stripe. Keep experimenting, keep learning, and, above all, keep coding!