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.
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
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
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
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);
}
}
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());
}
}
}
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']);
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:
Send Mail with Payment Link
Stripe Payment
You might also like:
For finding the right web hosting provider, you need to do a lot of research. There are hundreds of web hosting provider...
Nov-12-2021
Hello Devs, In this tutorial we will learn how to use SEOTools in laravel 8. we will give you example of se...
Jun-07-2021
In this article, we will see how to install Vue JS 3 in laravel 9. Laravel is a web application framework with...
Oct-07-2022
In this example, I will show you how to make simple laravel CRUD(insert, update, delete, or list) operations with e...
May-08-2020