How to Create Payment Link in Stripe using API in Laravel 10

Websolutionstuff | Oct-09-2023 | Categories : Laravel PHP

In today's digital age, the ability to facilitate online payments efficiently is crucial for businesses and developers alike. I'm a Laravel developer, and if you're like me, you might be excited about integrating Stripe's payment solutions into your web applications.

Stripe provides a powerful API that makes this integration seamless, and in this tutorial, I'm here to guide you through the process.

In this tutorial, we'll explore how to create payment links in Stripe using the Laravel framework and its robust API. Payment links offer a flexible way to request payments from customers, making it ideal for various use cases, including e-commerce, subscriptions, and one-time payments.

Throughout this journey, I'll walk you through essential steps such as setting up your Laravel project, configuring Stripe API keys, creating a dedicated controller, defining the logic for generating payment links, and handling success and cancellation scenarios.

By the end of this tutorial, you'll have a clear understanding of how to seamlessly integrate Stripe's payment link functionality into your Laravel application, allowing you to streamline payment processes and enhance the user experience.

So, let's see how to create a payment link in Stripe using API in laravel 10, how to create a payment link in Stripe API, laravel creating stripe payment link API, and stripe payment link example.

Step 1: Set Up Laravel Project

Ensure you have a Laravel project set up and configured properly. If you haven't already, you can create a new Laravel project using Composer

composer create-project laravel/laravel your-project-name

 

Step 2: Install Stripe PHP Library

Install the Stripe PHP library using Composer. The Stripe PHP library provides convenient access to the Stripe API from applications written in the PHP language.

composer require stripe/stripe-php

 

Step 3: Configure Stripe API Keys

In your Laravel project, you should configure your Stripe API keys. Add your Stripe API keys to your .env file.

STRIPE_KEY=your_stripe_public_key
STRIPE_SECRET=your_stripe_secret_key

 

Step 4: Create Migration and Model

Create a migration and model using the following command.

php artisan make:model PaymentDetail -m

Migration:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreatePaymentDetailsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('payment_details', function (Blueprint $table) {
            $table->id();
            $table->integer('user_id');
            $table->string('email');
            $table->double('amount')->default(0);
            $table->text('description');
            $table->date("due_date")->default(null);
            $table->string('invoice_number')->unique();
            $table->boolean('paid')->default(false);   
            $table->string('link'); 
            $table->text('stripe_payment_id')->nullable();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('payment_details');
    }
}

App\Models\PaymentDetail

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class PaymentDetail extends Model
{
    use HasFactory;
    // protected $guarded = [];
    protected $fillable = ['user_id', 'email','amount','description','due_date','invoice_number','paid','link','stripe_payment_id'];


    public function user() {
        return $this->belongsTo('App\Model\User', 'user_id', 'id');
    }

    public function storeData($data) {
        return static::create($data);
    }

    public function updateData($input, $slug) {
        return static::where('link', $slug)->update($input);
    }
}

 

Step 5: Create a Controller

Create a controller where you will define the logic to create the payment link. You can use the following command to create a controller.

php artisan make:controller StripeWebhookController

In your StripeWebhookController, you can define the logic to create a payment link. Here's an example of how to create a payment link and return it as a JSON response

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Event;
use Stripe;
use Illuminate\Support\Facades\Mail;
use App\Models\PaymentDetail;

class StripeWebhookController extends Controller
{
    public function handleWebhook(Request $request)
    {        
        
        $stripe = new \Stripe\StripeClient(env('STRIPE_SECRET'));        

        // Replace this endpoint secret with your endpoint's unique secret
        // If you are testing with the CLI, find the secret by running 'stripe listen'
        // If you are using an endpoint defined with the API or dashboard, look in your webhook settings
        // at https://dashboard.stripe.com/webhooks

        $endpoint_secret = 'whsec_....';

        $payload = @file_get_contents('php://input');
        $sig_header = $_SERVER['HTTP_STRIPE_SIGNATURE'];
        $event = null;

        try {
            $event = \Stripe\Webhook::constructEvent(
                $payload, $sig_header, $endpoint_secret
            );
        } catch(\UnexpectedValueException $e) {
            // Invalid payload
            http_response_code(400);
            exit();
        } catch(\Stripe\Exception\SignatureVerificationException $e) {
            // Invalid signature
            http_response_code(400);
            exit();
        }        


        // Handle the "checkout.session.completed" event.
        if ($event->type === 'checkout.session.completed') {
            if($event->data->object['payment_status'] == "paid"){
                $data = $event->data->object['customer_details']['email'];                
                PaymentDetail::where('stripe_payment_id', $event->data->object['payment_link'])->update(['paid' => 1]);
                $payment_data = PaymentDetail::where('stripe_payment_id', $event->data->object['payment_link'])->first();
                Mail::send('mail', ["data"=>$data], function ($message) use ($data, $payment_data) {
                    $message->to($data)
                    ->cc($payment_data->email)
                    ->subject("Payment Successfull");
                });
            }
        }
        http_response_code(200);
    }
}

Now, we will change in HomeController as per the below code. Also, we will send the invoice with the payment link to email.

App\Http\Controllers\HomeController

Set up your webhook endpoint to receive live events from Stripe or learn more about Webhooks.

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Stripe;
use App\Models\PaymentDetail;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Mail;
use PDF;
use Session;

class HomeController extends Controller
{
    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('auth');
        $this->payment_detail = new PaymentDetail;
    }

    /**
     * Show the application dashboard.
     *
     * @return \Illuminate\Contracts\Support\Renderable
     */
    public function index()
    {
        return view('home');
    }

    public function storePaymentRequest(Request $request)
    {                
        $input = $request->all();
        $validatedData = $request->validate([
            'email' => 'required|email',
            'amount' => 'required|numeric|min:0',
            'description' => 'required|string',
            'due_date' => 'required|date',
        ]);
        
        $input['user_id'] = auth()->user()->id;        
        $input['invoice_number'] = uniqid();
        $input['link'] = Str::random(15);
                
        $this->payment_detail->storeData($input);    
        
        $pdf = PDF::loadView('invoice', [
            'email' => $validatedData['email'],
            'amount' => $validatedData['amount'],
            'description' => $validatedData['description'],
            'due_date' => $validatedData['due_date'],
        ]);

        $data = [            
            'email' => $validatedData['email'],
            'payment_link' => $input['link']
        ]; 

        Mail::send('send_mail_with_pdf', ["data"=>$data], function ($message) use ($data, $pdf) {
            $message->to($data['email'])
                ->cc(auth()->user()->email)
                ->subject("Payment Link with Invoice")
                ->attachData($pdf->output(), "invoice.pdf");
        });

        Session::flash('success', 'Payment Details Created Successfully');

        return redirect()->route('home');
    }

    public function paymentCheckout(Request $request){
        $slug = $request->route('slug');
        $payment_details = PaymentDetail::select('amount','due_date','stripe_payment_id')->where('link',$slug)->first();
        
        DB::beginTransaction();
        try {
            if (!empty($payment_details->due_date) && strtotime($payment_details->due_date) <  strtotime(date('Y-m-d'))) {
                
                PaymentDetail::where('link', $slug)->update(['paid' => 0]);
                
                return view('error.abort')->with([
                    'heading' => 'Expired',
                    'message' => 'Payment link is expired'
                ]);
            }

            $stripe = new \Stripe\StripeClient(env('STRIPE_SECRET'));
            
            $product_response = $stripe->products->create([
                'name' => 'Gold Special 1',
            ]);        

            $amount = $payment_details->amount * 100;

            if(isset($product_response) && $product_response != ''){
                $price_response = $stripe->prices->create([
                    'unit_amount' => $amount,
                    'currency' => 'inr',        
                    'product' => $product_response['id'],
                ]);
            }

            if(isset($price_response) && $price_response != ''){                    
                                
                $webhookEndpoints_response = $stripe->webhookEndpoints->create([
                    'url' => 'your_webhook_endpoints_url/stripe/webhook',
                    'enabled_events' => [
                        'checkout.session.completed',                    
                    ],
                ]);
                                

                $payment_link_response = $stripe->paymentLinks->create([
                    'line_items' => [
                        [
                        'price' => $price_response['id'],
                        'quantity' => 1,
                        ],
                    ],
                    'after_completion' => [
                        'redirect' => [
                            'url' => 'http://localhost:8000/home',
                        ],
                        'type' => 'redirect'
                    ]
                ]);

                if(isset($payment_link_response) && $payment_link_response != ''){                    
                    $payment_link_id = $payment_link_response['id'];                     
                    PaymentDetail::where('link', $slug)->update(['stripe_payment_id' => $payment_link_id]);
                    DB::commit();
                }
            }                

            return redirect()->away($payment_link_response['url']);
            
        }catch (\Exception $e) {
            DB::rollback();
            info($e->getMessage());
        }
    }    
}

 

Step 6: Define Routes

Define the routes for your payment-related actions in the routes/web.php file.

<?php

use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/', function () {
    return view('welcome');
});

Auth::routes();

Route::get('/home', [App\Http\Controllers\HomeController::class, 'index'])->name('home');
Route::post('/payment-request', [App\Http\Controllers\HomeController::class, 'storePaymentRequest'])->name('payment-request');
Route::get('/payment/{slug}', [App\Http\Controllers\HomeController::class, 'paymentCheckout'])->name('payment-checkout');
Route::get('/payment/success/{session_id}', [App\Http\Controllers\HomeController::class, 'paymentSuccess'])->name('payment-success');
Route::post('stripe/webhook', [App\Http\Controllers\StripeWebhookController::class, 'handleWebhook']);

 

Step 7: Create Views

You may want to create views for the success and cancel pages. You can customize these views as per your requirements.

resources\views\home.blade.php

@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">Payment Request</div>
                <div class="card-body">
                    @if (Session::has('success'))
                        <div class="alert alert-success text-center">                            
                            <span>{{ Session::get('success') }}</span>
                        </div>
                    @endif


                    <form method="POST" action="{{ route('payment-request') }}">
                        @csrf

                        <div class="form-group">
                            <label for="email">Email:</label>
                            <input type="email" name="email" id="email" class="form-control" required>
                        </div>

                        <div class="form-group">
                            <label for="amount">Amount:</label>
                            <input type="number" name="amount" id="amount" min="1" class="form-control" required>
                        </div>

                        <div class="form-group">
                            <label for="description">Description:</label>
                            <textarea name="description" id="description" class="form-control" required></textarea>
                        </div>

                        <div class="form-group">
                            <label for="due_date">Due Date:</label>
                            <input type="date" name="due_date" id="due_date" class="form-control" required>
                        </div>

                        <button type="submit" class="btn btn-primary mt-2">Submit</button>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
<script type="text/javascript">
$(function(){
    var dtToday = new Date();

    var month = dtToday.getMonth() + 1;
    var day = dtToday.getDate();
    var year = dtToday.getFullYear();
    if(month < 10)
        month = '0' + month.toString();
    if(day < 10)
     day = '0' + day.toString();
    var maxDate = year + '-' + month + '-' + day;
    $('#due_date').attr('min', maxDate);
});
</script>
@endsection

resources\views\invoice.blade.php

<!DOCTYPE html>
<html>
<head>
    <title>Invoice</title>
</head>
<body>
    <h1>Invoice</h1>
    <p><strong>Email:</strong> {{ $email }}</p>
    <p><strong>Amount:</strong> ${{ $amount }}</p>
    <p><strong>Description:</strong> {{ $description }}</p>
    <p><strong>Due Date:</strong> {{ $due_date }}</p>
</body>
</html>

resources\views\mail.blade.php

<!DOCTYPE html>
<html>
<body>    
    <h3>Payment is done</h3>   
    <p>Thanks & Regards</p>
</body>
</html>

resources\views\send_mail_with_pdf.blade.php

<!DOCTYPE html>
<html>
<body>    
    <h3>Pay payment using <a href="{{ route('payment-checkout',$data['payment_link'])}}" target="_blank">Payment Link</a></h3>
    <p>Please find invoice attachment</p>
    <p>Thanks & Regards</p>
</body>
</html>

Output:

how-to-create-payment-link-in-stripe-api

Send Mail with Payment Link

stripr-payment-link-with-invoice-mail-laravel

Stripe Payment

stripr-payment-link-payment-laravel

 


You might also like:

Recommended Post
Featured Post
Laravel 9 React JS CRUD Operation Example
Laravel 9 React JS CRUD Operat...

This article will show the laravel 9 react js crud operation example. Here, we will learn how to create crud operation i...

Read More

Dec-08-2022

How To Add Default Value Of Column In Laravel Migration
How To Add Default Value Of Co...

In this article, we will explore how to add default values to columns in Laravel 10 migrations, although the information...

Read More

May-01-2023

Laravel 11 Install Yajra Datatable Example
Laravel 11 Install Yajra Datat...

In this tutorial, we'll explore an example of installing Yajra Datatable in Laravel 11. In every project, it's e...

Read More

Apr-10-2024

Mastering Reactive Forms Validation in Angular 15
Mastering Reactive Forms Valid...

Welcome to "Mastering Reactive Forms Validation in Angular 15: A Comprehensive Guide." In this guide, we will...

Read More

Jun-14-2023