One Time Payment with Laravel Cashier-Stripe

UI-Lib
7 min readMay 31, 2022

Introduction

Implementing a payment gateway is necessary when developing an e-commerce or business website. However, the process of payment gateway implementation might be confusing sometimes. But, with Laravel Cashier one can easily create “One Time Payment” or “Subscription Plans” and start to charge users very easily.

Laravel Cashier is an in-built Laravel Package that helps achieve payment gateway function with related subscriptions and transaction history in a jiffy. Developers just need to install the Laravel Cashier package for Stripe, set the required API keys, code the frontend views, and voila! your payment gateway integration is a success.

Previously we have shown how to implement Paddle Payment Gateway with Laravel Cashier-Paddle.

Now, Let us create a “One Time Payment” option in our Laravel Project and start charging users with Laravel Cashier-Stripe.

Getting Started on One Time Payment with Laravel Cashier-Stripe

We will start by creating a new laravel project. For this let us run the following command,

composer create-project laravel/laravel paymentGateway

If you see any errors such as, “ ‘composer’ is not recognized as an internal or external command in windows server”, this is because you have not downloaded and installed composer yet! Please do so by visiting this link.

Now, if everything goes well, the command above will create a laravel project folder titled “paymentGateway”. We will now navigate to that folder and start coding.

cd paymentGateway

I am using Visual Studio Code for implementing One Time Payment with Laravel Cashier-Stripe. You could just start VS Code and open the project folder manually. Also, you could locate the folder, open command prompt from that folder, and run the following command if you have VS Code in your environment path variable.

code .

Now we create our database and add the database name to our project .env file.

DB_CONNECTION=mysqlDB_HOST=127.0.0.1DB_PORT=3306DB_DATABASE=stripeDB_USERNAME=rootDB_PASSWORD=

Integrating Authentication

For authentication, we can use Laravels in-built package Laravel UI. Entering the following command will install Laravel UI in our project.

composer require laravel/ui

Laravel UI offers authentication scaffolding with bootstrap, vue, and with react.

php artisan ui bootstrap --auth
php artisan ui vue --auth //I am using vue in my case
php artisan ui react --auth

Now for successfully finishing the authentication scaffolding run,

npm install && npm run dev

Integrating One Time Payment With Laravel Cashier-Stripe

We are finally at the stage where we will start building the“ One Time Payment” option with Laravel Cashier-Stripe. First, we need to install the Laravel Cashier-Stripe package.

composer require laravel/cashier

Laravel Cashier package comes with its own database migration directory so it is necessary to migrate our database after installing the Laravel Cashier-Stripe package.

php artisan migrate

This will add several columns to our existing user table and also publish a subscription table that will hold all types of customer subscriptions.

Now we need to add the “Billable” trait to the User Model. Basically, this trait provides us with various methods to allow performing common billing tasks, such as creating subscriptions, charging for products, etc.

use Laravel\Cashier\Billable;class User extends Authenticatable{use Billable;}

We now have to set our Stripe API keys in the .env file. To get the Stripe Key and Stripe Secret we need to sign up on Stripe.

STRIPE_KEY=your-stripe-keySTRIPE_SECRET=your-stripe-secret

Let us register a user and redirect to the homepage. The homepage will basically look like this,

In our home.blade.php file let us write the following code,

@extends('layouts.app')@section('content')<div class="container"><div class="row justify-content-center"><div class="col-md-8"><div class="card"><div class="card-header">{{ __('Dashboard') }}</div><div class="card-body">@if (session('status'))<div class="alert alert-success" role="alert">{{ session('status') }}</div>@endif{{ __('You are logged in!') }} <br><br><h3>Products</h3><a href="{{route('goToPayment', ['search list', 25])}}"><button>In Recommended Search List for $25</button></a> &nbsp;<a href="{{route('goToPayment', ['update information', 10])}}"><button>Update Information for $10</button></a></div></div></div></div></div>@endsection

Now our homepage will look like the following where we are allowing users to a “One Time Payment” of $25 for getting in the recommended search list or $10 for updating information.

Let’s create a controller file called “PaymentController” and when any user clicks any one of the products from the homepage he or she will be redirected to a checkout page.

php artisan make:controller PaymentController

For this, the web.php file let us add the following route,

Route::get('/payment/{string}/{price}', [PaymentController::class, 'charge'])->name('goToPayment');

In our PaymentController.php file let us write the following charge() function that will redirect us to the checkout page,

<?phpnamespace App\Http\Controllers;use Illuminate\Http\Request;use Auth;class PaymentController extends Controller{public function charge(String $product, $price){$user = Auth::user();return view('payment',['user'=>$user,'intent' => $user->createSetupIntent(),'product' => $product,'price' => $price]);}}

Now we should create a view file in the resources folder titled payment.blade.php and write the following code,

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"></head><body><form action="{{route('processPayment', [$product, $price])}}" method="POST" id="subscribe-form"><div class="form-group"><div class="row"><div class="col-md-4"><div class="subscription-option"><label for="plan-silver"><span class="plan-price">${{$price}}</span></label></div></div></div></div><label for="card-holder-name">Card Holder Name</label><input id="card-holder-name" type="text" value="{{$user->name}}" disabled>@csrf<div class="form-row"><label for="card-element">Credit or debit card</label><div id="card-element" class="form-control">   </div><!-- Used to display form errors. --><div id="card-errors" role="alert"></div></div><div class="stripe-errors"></div>@if (count($errors) > 0)<div class="alert alert-danger">@foreach ($errors->all() as $error){{ $error }}<br>@endforeach</div>@endif<div class="form-group text-center"><button type="button"  id="card-button" data-secret="{{ $intent->client_secret }}" class="btn btn-lg btn-success btn-block">SUBMIT</button></div></form><script src="https://js.stripe.com/v3/"></script><script>var stripe = Stripe('{{ env('STRIPE_KEY') }}');var elements = stripe.elements();var style = {base: {color: '#32325d',fontFamily: '"Helvetica Neue", Helvetica, sans-serif',fontSmoothing: 'antialiased',fontSize: '16px','::placeholder': {color: '#aab7c4'}},invalid: {color: '#fa755a',iconColor: '#fa755a'}};var card = elements.create('card', {hidePostalCode: true, style: style});card.mount('#card-element');console.log(document.getElementById('card-element'));card.addEventListener('change', function(event) {var displayError = document.getElementById('card-errors');if (event.error) {displayError.textContent = event.error.message;} else {displayError.textContent = '';}});const cardHolderName = document.getElementById('card-holder-name');const cardButton = document.getElementById('card-button');const clientSecret = cardButton.dataset.secret;    cardButton.addEventListener('click', async (e) => {console.log("attempting");const { setupIntent, error } = await stripe.confirmCardSetup(clientSecret, {payment_method: {card: card,billing_details: { name: cardHolderName.value }}});        if (error) {var errorElement = document.getElementById('card-errors');errorElement.textContent = error.message;}else {paymentMethodHandler(setupIntent.payment_method);}});function paymentMethodHandler(payment_method) {var form = document.getElementById('subscribe-form');var hiddenInput = document.createElement('input');hiddenInput.setAttribute('type', 'hidden');hiddenInput.setAttribute('name', 'payment_method');hiddenInput.setAttribute('value', payment_method);form.appendChild(hiddenInput);form.submit();}</script></body></html>

For the payment.blade.php file the user interface will look like the following,

We see that the checkout page requires a card number. As we are testing out if our payment gateway works or not we do not need a valid card number rather we can use test card numbers.

We can use the following test card number,

Now after we enter the card details we need to process payment for this add the following route,

Route::post('payment/process-payment/{string}/{price}', [PaymentController::class, 'processPayment'])->name('processPayment');

In the PaymentController.php file add the following peocessPayment() function,

public function processPayment(Request $request, String $product, $price){$user = Auth::user();$paymentMethod = $request->input('payment_method');$user->createOrGetStripeCustomer();$user->addPaymentMethod($paymentMethod);try{$user->charge($price*100, $paymentMethod);}catch (\Exception $e){return back()->withErrors(['message' => 'Error creating subscription. ' . $e->getMessage()]);}return redirect('home');}

Now if we enter card details and click the submit button we will charge the user for the product he or she wants to purchase.

Finally, our “One Time Payment” with Laravel Cashier-Stripe is implemented.

Successful One Time Payment with Laravel Cashier-Stripe

Conclusion

Laravel is a PHP-based open source web framework that is highly appreciated amongst web developers because of its robust amount of built-in packages. These packages make a developer's coding journey more soothing and easy.

Laravel Cashier is one of the many packages that help us implement payment gateways such as Stripe and Paddle with ease. We saw how effortlessly we can integrate a “One Time Payment” option with Laravel Cashier-Stripe.

Our Products Implemented With Laravel

Gull — Bootstrap & Laravel Admin Dashboard Template

Aatrox — TailwindCSS Admin Dashboard Template

Stocky — Ultimate Inventory Management System with Pos & HRM

WorkTick — Ultimate HRM & Project Management

Similar Articles

--

--

UI-Lib

At UI-Lib you can download hand coded free and premium Admin Dashboards, Landing pages, UI Kits & Design Systems built with Angular, React & Bootstrap, etc.