CoderFunda
  • Home
  • About us
    • Contact Us
    • Disclaimer
    • Privacy Policy
    • About us
  • Home
  • Php
  • HTML
  • CSS
  • JavaScript
    • JavaScript
    • Jquery
    • JqueryUI
    • Stock
  • SQL
  • Vue.Js
  • Python
  • Wordpress
  • C++
    • C++
    • C
  • Laravel
    • Laravel
      • Overview
      • Namespaces
      • Middleware
      • Routing
      • Configuration
      • Application Structure
      • Installation
    • Overview
  • DBMS
    • DBMS
      • PL/SQL
      • SQLite
      • MongoDB
      • Cassandra
      • MySQL
      • Oracle
      • CouchDB
      • Neo4j
      • DB2
      • Quiz
    • Overview
  • Entertainment
    • TV Series Update
    • Movie Review
    • Movie Review
  • More
    • Vue. Js
    • Php Question
    • Php Interview Question
    • Laravel Interview Question
    • SQL Interview Question
    • IAS Interview Question
    • PCS Interview Question
    • Technology
    • Other

20 August, 2026

Laravel Razorpay Payment Gateway with Transaction Tracking, OTP Verification & Custom SMS

 Programing Coderfunda     August 20, 2026     Laravel     No comments   

Build a secure, production-ready Razorpay payment integration in Laravel with complete transaction management, server-side payment verification, OTP authentication, custom SMS notifications, and webhook support.

Description

This implementation provides a complete payment workflow:

  • πŸ’³ Razorpay payment gateway integration
  • πŸ” Secure Razorpay signature verification
  • πŸ†” Unique transaction ID for every payment
  • πŸ“¦ Razorpay Order ID and Payment ID tracking
  • πŸ’° Amount and currency verification
  • πŸ—„️ Complete payment and customer data stored in MySQL
  • πŸ“‹ Transaction event/audit history
  • πŸ“± OTP generation after successful payment
  • πŸ”’ Hashed OTP storage with expiration
  • 🚫 OTP attempt limits and duplicate OTP protection
  • πŸ’¬ Custom SMS message after successful payment
  • ⚡ Queue-based SMS sending
  • πŸ”„ Razorpay webhook integration
  • πŸ›‘️ Idempotent payment processing
  • ❌ Payment failure handling
  • πŸ’Έ Refund/status tracking support
  • πŸ“ Detailed payment response storage
  • πŸ” Transaction reconciliation and debugging support
  • πŸ” Production-focused security practices

Complete Payment Flow

Customer
↓
Create Transaction
↓
Generate Transaction ID
↓
Create Razorpay Order
↓
Razorpay Checkout
↓
Payment Successful
↓
Server-Side Signature Verification
↓
Verify Order + Amount + Currency
↓
Save Payment Details
↓
Mark Transaction as PAID
↓
Generate OTP
↓
Store Hashed OTP
↓
Send Custom SMS
↓
Customer Enters OTP
↓
Verify OTP
↓
Mark Transaction COMPLETED

Goal: Create a reliable Laravel payment system where every payment is securely tracked from transaction creation → Razorpay payment → verification → OTP → final completion, with a complete database audit trail.


I’ll use Laravel 12-style structure, Eloquent, queued SMS, signed Razorpay checkout, server-side verification, webhook handling, idempotency, OTP hashing, expiry, and attempt limits.

Important: Replace the SmsService implementation with your actual SMS provider credentials/API. The payment logic itself does not depend on the SMS provider.


1. Install Razorpay

composer require razorpay/razorpay

.env

APP_NAME="My Laravel App"
APP_ENV=production
APP_DEBUG=false
APP_URL=https://example.com

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=my_database
DB_USERNAME=my_user
DB_PASSWORD=my_password

RAZORPAY_KEY_ID=rzp_live_xxxxxxxxx
RAZORPAY_KEY_SECRET=xxxxxxxxxxxxxxxx
RAZORPAY_WEBHOOK_SECRET=xxxxxxxxxxxxxxxx

QUEUE_CONNECTION=database

OTP_EXPIRY_MINUTES=10
OTP_MAX_ATTEMPTS=5

config/services.php

'razorpay' => [
'key' => env('RAZORPAY_KEY_ID'),
'secret' => env('RAZORPAY_KEY_SECRET'),
'webhook_secret' => env('RAZORPAY_WEBHOOK_SECRET'),
],

'otp' => [
'expiry_minutes' => env('OTP_EXPIRY_MINUTES', 10),
'max_attempts' => env('OTP_MAX_ATTEMPTS', 5),
],

2. Database structure

We'll create:

transactions
transaction_events
otps

The important identifier is our own:

transaction_id

For example:

TXN-20260820-A8F92KLM7P

This is separate from Razorpay's:

razorpay_order_id
razorpay_payment_id

3. Transactions migration

Create:

php artisan make:migration create_transactions_table
<?php

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

return new class extends Migration
{
public function up(): void
{
Schema::create('transactions', function (Blueprint $table) {
$table->id();

$table->uuid('uuid')->unique();

$table->string('transaction_id', 50)->unique();

$table->foreignId('user_id')
->nullable()
->constrained()
->nullOnDelete();

$table->string('customer_name');
$table->string('customer_email');
$table->string('customer_phone', 20);

$table->decimal('amount', 12, 2);
$table->string('currency', 3)->default('INR');

$table->string('status')->default('created');

$table->string('razorpay_order_id')
->nullable()
->unique();

$table->string('razorpay_payment_id')
->nullable()
->unique();

$table->string('razorpay_signature')
->nullable();

$table->string('payment_method')
->nullable();

$table->string('payment_status')
->nullable();

$table->timestamp('paid_at')->nullable();

$table->timestamp('failed_at')->nullable();

$table->text('failure_reason')->nullable();

$table->json('razorpay_order_response')->nullable();

$table->json('razorpay_payment_response')->nullable();

$table->json('metadata')->nullable();

$table->timestamps();

$table->index(['user_id', 'status']);
$table->index(['customer_phone']);
$table->index(['created_at']);
});
}

public function down(): void
{
Schema::dropIfExists('transactions');
}
};

4. Transaction events

This gives you an audit trail.

php artisan make:migration create_transaction_events_table
<?php

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

return new class extends Migration
{
public function up(): void
{
Schema::create('transaction_events', function (Blueprint $table) {
$table->id();

$table->foreignId('transaction_id')
->constrained('transactions')
->cascadeOnDelete();

$table->string('event');

$table->string('source')->nullable();

$table->json('payload')->nullable();

$table->timestamps();

$table->index([
'transaction_id',
'event'
]);
});
}

public function down(): void
{
Schema::dropIfExists('transaction_events');
}
};

5. OTP migration

php artisan make:migration create_otps_table
<?php

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

return new class extends Migration
{
public function up(): void
{
Schema::create('otps', function (Blueprint $table) {
$table->id();

$table->foreignId('transaction_id')
->constrained('transactions')
->cascadeOnDelete();

$table->string('phone', 20);

$table->string('otp_hash');

$table->timestamp('expires_at');

$table->unsignedTinyInteger('attempts')
->default(0);

$table->unsignedTinyInteger('max_attempts')
->default(5);

$table->timestamp('verified_at')
->nullable();

$table->timestamp('last_sent_at')
->nullable();

$table->timestamps();

$table->index([
'transaction_id',
'verified_at'
]);
});
}

public function down(): void
{
Schema::dropIfExists('otps');
}
};

Run:

php artisan migrate

6. Transaction model

app/Models/Transaction.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class Transaction extends Model
{
protected $fillable = [
'uuid',
'transaction_id',
'user_id',
'customer_name',
'customer_email',
'customer_phone',
'amount',
'currency',
'status',
'razorpay_order_id',
'razorpay_payment_id',
'razorpay_signature',
'payment_method',
'payment_status',
'paid_at',
'failed_at',
'failure_reason',
'razorpay_order_response',
'razorpay_payment_response',
'metadata',
];

protected $casts = [
'amount' => 'decimal:2',
'paid_at' => 'datetime',
'failed_at' => 'datetime',
'razorpay_order_response' => 'array',
'razorpay_payment_response' => 'array',
'metadata' => 'array',
];

public function events(): HasMany
{
return $this->hasMany(TransactionEvent::class);
}

public function otps(): HasMany
{
return $this->hasMany(Otp::class);
}

public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
}

7. TransactionEvent model

app/Models/TransactionEvent.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class TransactionEvent extends Model
{
protected $fillable = [
'transaction_id',
'event',
'source',
'payload',
];

protected $casts = [
'payload' => 'array',
];

public function transaction(): BelongsTo
{
return $this->belongsTo(Transaction::class);
}
}

8. OTP model

app/Models/Otp.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class Otp extends Model
{
protected $fillable = [
'transaction_id',
'phone',
'otp_hash',
'expires_at',
'attempts',
'max_attempts',
'verified_at',
'last_sent_at',
];

protected $casts = [
'expires_at' => 'datetime',
'verified_at' => 'datetime',
'last_sent_at' => 'datetime',
];

protected $hidden = [
'otp_hash',
];

public function transaction(): BelongsTo
{
return $this->belongsTo(Transaction::class);
}
}

9. Razorpay service

Create:

app/Services/RazorpayService.php
<?php

namespace App\Services;

use Razorpay\Api\Api;

class RazorpayService
{
protected Api $api;

public function __construct()
{
$this->api = new Api(
config('services.razorpay.key'),
config('services.razorpay.secret')
);
}

public function createOrder(
string $receipt,
int $amountInPaise,
string $currency = 'INR'
): array {
$order = $this->api->order->create([
'receipt' => $receipt,
'amount' => $amountInPaise,
'currency' => $currency,
]);

return $order->toArray();
}

public function verifyPayment(
string $orderId,
string $paymentId,
string $signature
): bool {
$this->api->utility->verifyPaymentSignature([
'razorpay_order_id' => $orderId,
'razorpay_payment_id' => $paymentId,
'razorpay_signature' => $signature,
]);

return true;
}

public function fetchPayment(string $paymentId): array
{
return $this->api
->payment
->fetch($paymentId)
->toArray();
}
}

10. Transaction service

This is where the important business logic lives.

app/Services/PaymentService.php

<?php
'-' .
strtoupper(Str::random(10));

$transaction = Transaction::create([
'uuid' => (string) Str::uuid(),

'transaction_id' => $transactionId,

'user_id' => $data['user_id'] ?? null,

'customer_name' => $data['name'],
'customer_email' => $data['email'],
'customer_phone' => $data['phone'],

'amount' => $data['amount'],

'currency' => 'INR',

'status' => 'creating',

'metadata' => $data['metadata'] ?? null,
]);

$amountPaise = (int) round(
$transaction->amount * 100
);

$order = $this->razorpay->createOrder(
$transaction->transaction_id,
$amountPaise,
$transaction->currency
);

$transaction->update([
'razorpay_order_id' => $order['id'],
'status' => 'created',
'razorpay_order_response' => $order,
]);

$transaction->events()->create([
'event' => 'order_created',
'source' => 'application',
'payload' => $order,
]);

return $transaction->fresh();
});
}

public function verifyAndCapturePayment(
Transaction $transaction,
array $paymentData
): Transaction {

return DB::transaction(function () use (
$transaction,
$paymentData
) {

$transaction = Transaction::query()
->whereKey($transaction->id)
->lockForUpdate()
->firstOrFail();

/*
* Idempotency:
*
* If the payment was already processed,
* don't process it again.
*/
if ($transaction->status === 'paid') {
return $transaction;
}

$this->razorpay->verifyPayment(
$paymentData['razorpay_order_id'],
$paymentData['razorpay_payment_id'],
$paymentData['razorpay_signature']
);

/*
* Make sure the payment belongs to
* our transaction.

11. OTP service

app/Services/OtpService.php

<?php
'expires_at' => now(),
]);

$otp = (string) random_int(100000, 999999);

$record = Otp::create([
'transaction_id' => $transaction->id,

'phone' => $transaction->customer_phone,

'otp_hash' => Hash::make($otp),

'expires_at' => now()->addMinutes(
config('services.otp.expiry_minutes', 10)
),

'attempts' => 0,

'max_attempts' => config(
'services.otp.max_attempts',
5
),

'last_sent_at' => now(),
]);

/*
* Never return/store plaintext OTP in DB.
*
* Return it temporarily so the SMS job can use it.
*/
$record->plain_otp = $otp;

return $record;
});
}

public function verify(
Transaction $transaction,
string $inputOtp
): bool {

return DB::transaction(function () use (
$transaction,
$inputOtp
) {

$otp = Otp::query()
->where('transaction_id', $transaction->id)
->whereNull('verified_at')
->latest()
->lockForUpdate()
->first();

if (!$otp) {
throw new RuntimeException(
'OTP not found.'
);
}

if ($otp->expires_at->isPast()) {
throw new RuntimeException(
'OTP has expired.'
);
}

if ($otp->attempts >= $otp->max_attempts) {
throw new RuntimeException(
'Maximum OTP attempts exceeded.'
);
}

$otp->increment('attempts');

if (!Hash::check($inputOtp, $otp->otp_hash)) {
throw new RuntimeException(
'Invalid OTP.'
);
}

$otp->update([
'verified_at' => now(),
]);

12. SMS service

Create:

app/Services/SmsService.php
<?php

namespace App\Services;

class SmsService
{
public function sendOtp(
string $phone,
string $name,
string $otp
): bool {

$message =
"Hello {$name}, your payment was successful. " .
"Your OTP is {$otp}. " .
"This OTP is valid for 10 minutes. " .
"Do not share this OTP with anyone.";

/*
* Integrate your SMS provider here.
*
* Example:
*
* Http::post(...)
*/

logger()->info('OTP SMS prepared', [
'phone' => $phone,
'message' => $message,
]);

return true;
}
}

Do not log the OTP in production. The logger above is only illustrative; remove the message from production logs.


13. Queue job for SMS

Sending SMS inside the payment request can slow down the payment response.

Create:

php artisan make:job SendOtpSmsJob

app/Jobs/SendOtpSmsJob.php

<?php

namespace App\Jobs;

use App\Models\Transaction;
use App\Services\SmsService;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;

class SendOtpSmsJob implements ShouldQueue
{
use Queueable;

public int $tries = 3;

public function __construct(
public int $transactionId,
public string $otp
) {
}

public function handle(SmsService $sms): void
{
$transaction = Transaction::findOrFail(
$this->transactionId
);

$sms->sendOtp(
$transaction->customer_phone,
$transaction->customer_name,
$this->otp
);
}
}

14. Payment controller

Create:

php artisan make:controller PaymentController

app/Http/Controllers/PaymentController.php

<?php
}

return response()->json([
'success' => true,

'transaction_id' =>
$transaction->transaction_id,

'message' =>
'Payment successful. OTP has been sent.',
]);

} catch (Throwable $e) {

Log::error(
'Payment verification failed',
[
'message' => $e->getMessage(),
'transaction_id' =>
$request->transaction_id,
]
);

return response()->json([
'success' => false,

'message' =>
'Payment verification failed.',
], 400);
}
}

public function otpPage(
string $transactionId
) {

$transaction = Transaction::where(
'transaction_id',
$transactionId
)->firstOrFail();

abort_unless(
$transaction->status === 'paid',
403
);

return view(
'payment.otp',
compact('transaction')
);
}

public function verifyOtp(Request $request)
{
$validated = $request->validate([
'transaction_id' =>
'required|string',

'otp' =>
'required|digits:6',
]);

try {

$transaction = Transaction::where(
'transaction_id',
$validated['transaction_id']
)->firstOrFail();

$this->otpService->verify(
$transaction,
$validated['otp']
);

return response()->json([
'success' => true,

'message' =>
'OTP verified successfully.',
]);

} catch (Throwable $e) {


15. Routes

routes/web.php

<?php

use App\Http\Controllers\PaymentController;
use Illuminate\Support\Facades\Route;

Route::get(
'/payment',
[PaymentController::class, 'checkout']
)->name('payment.checkout');

Route::post(
'/payment/create-order',
[PaymentController::class, 'createOrder']
)->name('payment.create');

Route::post(
'/payment/success',
[PaymentController::class, 'success']
)->name('payment.success');

Route::get(
'/payment/otp/{transactionId}',
[PaymentController::class, 'otpPage']
)->name('payment.otp');

Route::post(
'/payment/verify-otp',
[PaymentController::class, 'verifyOtp']
)->name('payment.verify-otp');

If your payment requires authentication, use:

Route::middleware('auth')->group(function () {

Route::get(
'/payment',
[PaymentController::class, 'checkout']
);

Route::post(
'/payment/create-order',
[PaymentController::class, 'createOrder']
);

// ...
});

16. Checkout Blade

resources/views/payment/checkout.blade.php

<!DOCTYPE html>
<html>
<head>
<title>Payment</title>

<meta name="csrf-token"
content="{{ csrf_token() }}">

<script src="https://checkout.razorpay.com/v1/checkout.js"></script>
</head>

<body>

<h2>Make Payment</h2>

<form id="paymentForm">

<input
type="text"
id="name"
placeholder="Name"
required
>

<br><br>

<input
type="email"
id="email"
placeholder="Email"
required
>

<br><br>

<input
type="text"
id="phone"
placeholder="Phone"
required
>

<br><br>

<input
type="number"
id="amount"
value="499"
min="1"
required
>

<br><br>

<button type="submit">
Pay Now
</button>

</form>

<script>

const form = document.getElementById('paymentForm');

form.addEventListener('submit', async function (e) {

e.preventDefault();

const data = {
name: document.getElementById('name').value,
email: document.getElementById('email').value,
phone: document.getElementById('phone').value,
amount: document.getElementById('amount').value
};

const response = await fetch(

17. OTP page

resources/views/payment/otp.blade.php

<!DOCTYPE html>
<html>
<head>
<title>Verify OTP</title>

<meta name="csrf-token"
content="{{ csrf_token() }}">
</head>

<body>

<h2>Verify OTP</h2>

<p>
Payment successful.
</p>

<p>
OTP has been sent to:
{{ substr($transaction->customer_phone, 0, 3) }}******
</p>

<form id="otpForm">

<input
type="hidden"
id="transaction_id"
value="{{ $transaction->transaction_id }}"
>

<input
type="text"
id="otp"
maxlength="6"
pattern="[0-9]{6}"
placeholder="Enter OTP"
required
>

<br><br>

<button type="submit">
Verify OTP
</button>

</form>

<div id="message"></div>

<script>


18. Razorpay webhook

This is extremely important for production.

The browser can disappear after payment. Your server should also receive Razorpay's webhook.

Create:

app/Http/Controllers/RazorpayWebhookController.php
<?php
$payload,
config('services.razorpay.webhook_secret')
);

if (!hash_equals(
$expectedSignature,
$signature
)) {

Log::warning(
'Invalid Razorpay webhook signature'
);

return response()->json([
'message' => 'Invalid signature'
], 400);
}

$data = $request->json()->all();

$event = $data['event'] ?? null;

$paymentEntity =
$data['payload']['payment']['entity']
?? null;

if (!$paymentEntity) {

return response()->json([
'success' => true
]);
}

$razorpayOrderId =
$paymentEntity['order_id']
?? null;

if (!$razorpayOrderId) {

return response()->json([
'success' => true
]);
}

DB::transaction(function () use (
$razorpayOrderId,
$paymentEntity,
$event
) {

$transaction =
Transaction::where(
'razorpay_order_id',
$razorpayOrderId
)
->lockForUpdate()
->first();

if (!$transaction) {

Log::warning(
'Transaction not found for webhook',
[
'order_id' =>
$razorpayOrderId
]
);

return;
}

/*
* Store webhook event.
*/
$transaction->events()->create([
'event' =>
$event ?? 'unknown',

'source' =>
'razorpay_webhook',

'payload' =>
$paymentEntity,

19. Webhook route

Put this in routes/api.php:

use App\Http\Controllers\RazorpayWebhookController;

Route::post(
'/razorpay/webhook',
[RazorpayWebhookController::class, 'handle']
);

The webhook endpoint should not require CSRF because Razorpay is calling it server-to-server.

Configure the webhook in your Razorpay dashboard to:

https://example.com/api/razorpay/webhook

Subscribe to at least:

payment.captured
payment.failed
order.paid

20. Queue setup

Because SMS is queued, create the jobs table if necessary:

php artisan make:queue-table
php artisan migrate

Then run:

php artisan queue:work --tries=3

For production, use Supervisor rather than manually running queue:work.

Example Supervisor configuration:

[program:laravel-worker]

process_name=%(program_name)s_%(process_num)02d

command=php /var/www/html/artisan queue:work --sleep=3 --tries=3 --timeout=90

autostart=true
autorestart=true

stopasgroup=true
killasgroup=true

numprocs=2

redirect_stderr=true

stdout_logfile=/var/www/html/storage/logs/worker.log

stopwaitsecs=3600

21. Payment statuses

I recommend using:

creating
created
paid
completed
failed
refunded
cancelled

The lifecycle is:

creating
↓
created
↓
paid
↓
completed

If payment fails:

created
↓
failed

If later refunded:

paid/completed
↓
refunded

22. Example database record

After payment, transactions could contain:

id: 25
uuid: 2a9c...uuid
transaction_id: TXN-20260820-A8F92KLM7P
user_id: 15

customer_name: Rahul
customer_email: rahul@example.com
customer_phone: 9876543210

amount: 499.00
currency: INR

status: paid
payment_status: captured

razorpay_order_id: order_Random123
razorpay_payment_id: pay_Random456

payment_method: upi

paid_at: 2026-08-20 15:20:30

And the Razorpay response is preserved in:

razorpay_order_response
razorpay_payment_response

This is useful for reconciliation and debugging.


23. Transaction event history

You can then see:

transaction_events

order_created
payment_verified
payment.captured
otp_verified

For example:

TXN-20260820-A8F92KLM7P

15:20:01 order_created
15:20:29 payment_verified
15:20:31 payment.captured
15:20:35 otp_verified

This is much better than trying to infer the payment history from a single transactions row.


24. Very important: prevent duplicate OTPs

There is one more production concern.

The browser callback and webhook can both arrive.

You must not do this:

generateOtp();
sendSms();

every time a payment callback arrives.

Instead, use a locked transaction and check whether a valid OTP already exists.

For even stronger protection, add an otp_sent_at column to transactions:

$table->timestamp('otp_sent_at')->nullable();

Then inside the locked transaction:

if (!$transaction->otp_sent_at) {

// Generate OTP

$transaction->update([
'otp_sent_at' => now(),
]);

// Dispatch SMS
}

That makes the OTP process explicitly idempotent.


25. Security checklist

For a real production deployment, I recommend all of these:

✓ HTTPS
✓ Razorpay signature verification
✓ Razorpay webhook signature verification
✓ Server-side amount verification
✓ Server-side currency verification
✓ Transaction/order ID matching
✓ DB row locking
✓ Idempotency protection
✓ OTP hashed in database
✓ OTP expiration
✓ OTP attempt limit
✓ SMS queued
✓ Payment audit events
✓ Razorpay response stored
✓ No card information stored
✓ No plaintext OTP stored
✓ No OTP in production logs
✓ Rate limiting on OTP endpoints
✓ Rate limiting on payment creation
✓ Production APP_DEBUG=false
✓ Queue worker with Supervisor
✓ Database backups
✓ Payment reconciliation

One change I strongly recommend

For the most robust version, don't make the frontend callback responsible for generating the OTP. Let the server-side payment confirmation service own the entire process:

Razorpay payment
↓
Signature verification
↓
Amount/order verification
↓
Transaction locked
↓
Transaction = PAID
↓
Create OTP exactly once
↓
Commit DB transaction
↓
Queue SMS

Then the Razorpay webhook can independently reconcile the transaction without accidentally sending another OTP.

If you tell me your Laravel version (10/11/12), whether you're using login/authentication, and which SMS provider (MSG91, Twilio, Fast2SMS, etc.), I can adapt this into the exact production structure for your project, including the SMS API implementation and rate-limited resend-OTP endpoint.

 

Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Google+
  •  Stumble
  •  Digg
Older Posts Home

Meta

Popular Posts

  • Generate Migrations from an Existing Database With the Migration Generator Package
    Laravel Migration Generator Migration Generator for Laravel is a package by Bennett Treptow to generate migrations from existing database ...
  • 'Ramayana' to have 'Baahubali'-style cliffhanger ending
    image/jpeg https://timesofindia.indiatimes.com/entertainment/hindi/bollywood/news/ramayana-to-end-on-baahubali-style-cliffhanger-director-ni...
  • 'Spider-Man: Brand New Day' records Rs 300 crore weekend in India
    image/jpeg https://timesofindia.indiatimes.com/entertainment/english/hollywood/box-office/spider-man-brand-new-day-box-office-collection-day...
  • SRK's King eyes record-breaking Rs 50 crore music rights deal
    image/jpeg https://timesofindia.indiatimes.com/entertainment/hindi/bollywood/news/shah-rukh-khans-king-eyes-record-breaking-rs-50-crore-musi...
  • Vijay talks about being harassed in an uncomfortable encounter with a model coordinator
    image/jpeg https://timesofindia.indiatimes.com/entertainment/hindi/bollywood/news/he-was-getting-touchy-feely-vijay-varma-opens-up-about-bei...

Categories

  • Ajax (26)
  • Bootstrap (30)
  • DBMS (42)
  • HTML (12)
  • HTML5 (45)
  • JavaScript (10)
  • Jquery (34)
  • Jquery UI (2)
  • JqueryUI (32)
  • Laravel (1018)
  • Laravel Tutorials (23)
  • Laravel-Question (6)
  • Magento (9)
  • Magento 2 (95)
  • MariaDB (1)
  • MySql Tutorial (2)
  • PHP-Interview-Questions (3)
  • Php Question (13)
  • Python (36)
  • RDBMS (13)
  • SQL Tutorial (79)
  • Vue.js Tutorial (69)
  • Wordpress (150)
  • Wordpress Theme (3)
  • codeigniter (108)
  • oops (4)
  • php (853)

Social Media Links

  • Follow on Twitter
  • Like on Facebook
  • Subscribe on Youtube
  • Follow on Instagram

Pages

  • Home
  • Contact Us
  • Privacy Policy
  • About us

Blog Archive

  • ▼  2026 (118)
    • ▼  08/16 - 08/23 (1)
      • Laravel Razorpay Payment Gateway with Transaction ...
    • ►  08/02 - 08/09 (8)
    • ►  07/26 - 08/02 (108)
    • ►  06/28 - 07/05 (1)
  • ►  2025 (4)
    • ►  07/06 - 07/13 (2)
    • ►  06/29 - 07/06 (2)
  • ►  2024 (486)
    • ►  09/15 - 09/22 (30)
    • ►  09/08 - 09/15 (35)
    • ►  09/01 - 09/08 (35)
    • ►  08/11 - 08/18 (2)
    • ►  08/04 - 08/11 (33)
    • ►  07/28 - 08/04 (30)
    • ►  07/07 - 07/14 (11)
    • ►  06/30 - 07/07 (35)
    • ►  06/23 - 06/30 (5)
    • ►  06/02 - 06/09 (31)
    • ►  05/26 - 06/02 (20)
    • ►  05/05 - 05/12 (29)
    • ►  04/28 - 05/05 (26)
    • ►  04/07 - 04/14 (10)
    • ►  03/31 - 04/07 (34)
    • ►  03/24 - 03/31 (10)
    • ►  03/03 - 03/10 (35)
    • ►  02/25 - 03/03 (15)
    • ►  02/04 - 02/11 (22)
    • ►  01/28 - 02/04 (30)
    • ►  01/07 - 01/14 (8)
  • ►  2023 (484)
    • ►  12/31 - 01/07 (35)
    • ►  12/24 - 12/31 (10)
    • ►  12/03 - 12/10 (33)
    • ►  11/26 - 12/03 (20)
    • ►  11/05 - 11/12 (35)
    • ►  10/29 - 11/05 (20)
    • ►  10/22 - 10/29 (9)
    • ►  10/15 - 10/22 (7)
    • ►  10/08 - 10/15 (9)
    • ►  10/01 - 10/08 (10)
    • ►  09/24 - 10/01 (9)
    • ►  09/17 - 09/24 (9)
    • ►  09/10 - 09/17 (7)
    • ►  09/03 - 09/10 (9)
    • ►  08/27 - 09/03 (9)
    • ►  08/20 - 08/27 (8)
    • ►  08/13 - 08/20 (8)
    • ►  08/06 - 08/13 (8)
    • ►  07/30 - 08/06 (8)
    • ►  07/23 - 07/30 (7)
    • ►  07/16 - 07/23 (8)
    • ►  07/09 - 07/16 (7)
    • ►  07/02 - 07/09 (8)
    • ►  06/25 - 07/02 (7)
    • ►  06/18 - 06/25 (7)
    • ►  06/11 - 06/18 (7)
    • ►  06/04 - 06/11 (11)
    • ►  05/28 - 06/04 (7)
    • ►  05/21 - 05/28 (8)
    • ►  05/14 - 05/21 (11)
    • ►  05/07 - 05/14 (7)
    • ►  04/30 - 05/07 (7)
    • ►  04/23 - 04/30 (8)
    • ►  04/16 - 04/23 (9)
    • ►  04/09 - 04/16 (7)
    • ►  04/02 - 04/09 (4)
    • ►  03/26 - 04/02 (21)
    • ►  03/19 - 03/26 (2)
    • ►  03/12 - 03/19 (9)
    • ►  03/05 - 03/12 (26)
    • ►  02/26 - 03/05 (25)
    • ►  01/15 - 01/22 (7)
    • ►  01/08 - 01/15 (1)
  • ►  2022 (1037)
    • ►  12/11 - 12/18 (13)
    • ►  12/04 - 12/11 (1)
    • ►  11/27 - 12/04 (40)
    • ►  11/06 - 11/13 (1)
    • ►  10/16 - 10/23 (13)
    • ►  09/04 - 09/11 (5)
    • ►  08/21 - 08/28 (24)
    • ►  08/14 - 08/21 (24)
    • ►  07/03 - 07/10 (9)
    • ►  06/19 - 06/26 (3)
    • ►  05/29 - 06/05 (3)
    • ►  05/22 - 05/29 (3)
    • ►  05/15 - 05/22 (109)
    • ►  05/01 - 05/08 (7)
    • ►  04/24 - 05/01 (7)
    • ►  04/17 - 04/24 (64)
    • ►  04/10 - 04/17 (115)
    • ►  04/03 - 04/10 (73)
    • ►  03/27 - 04/03 (77)
    • ►  03/13 - 03/20 (2)
    • ►  03/06 - 03/13 (25)
    • ►  02/27 - 03/06 (18)
    • ►  02/20 - 02/27 (153)
    • ►  02/13 - 02/20 (187)
    • ►  01/30 - 02/06 (45)
    • ►  01/23 - 01/30 (15)
    • ►  01/16 - 01/23 (1)
  • ►  2021 (412)
    • ►  10/24 - 10/31 (2)
    • ►  07/25 - 08/01 (1)
    • ►  07/11 - 07/18 (10)
    • ►  06/13 - 06/20 (29)
    • ►  05/23 - 05/30 (1)
    • ►  05/02 - 05/09 (24)
    • ►  04/25 - 05/02 (24)
    • ►  04/18 - 04/25 (112)
    • ►  04/11 - 04/18 (1)
    • ►  04/04 - 04/11 (6)
    • ►  03/28 - 04/04 (86)
    • ►  03/21 - 03/28 (19)
    • ►  03/14 - 03/21 (2)
    • ►  03/07 - 03/14 (10)
    • ►  02/28 - 03/07 (1)
    • ►  02/21 - 02/28 (29)
    • ►  02/14 - 02/21 (13)
    • ►  02/07 - 02/14 (12)
    • ►  01/31 - 02/07 (6)
    • ►  01/17 - 01/24 (2)
    • ►  01/10 - 01/17 (8)
    • ►  01/03 - 01/10 (14)
  • ►  2020 (376)
    • ►  12/27 - 01/03 (37)
    • ►  12/20 - 12/27 (92)
    • ►  12/13 - 12/20 (29)
    • ►  12/06 - 12/13 (37)
    • ►  11/29 - 12/06 (4)
    • ►  11/15 - 11/22 (14)
    • ►  11/08 - 11/15 (8)
    • ►  11/01 - 11/08 (2)
    • ►  10/18 - 10/25 (14)
    • ►  10/11 - 10/18 (16)
    • ►  10/04 - 10/11 (10)
    • ►  09/20 - 09/27 (10)
    • ►  09/06 - 09/13 (19)
    • ►  08/30 - 09/06 (26)
    • ►  08/23 - 08/30 (4)
    • ►  08/16 - 08/23 (2)
    • ►  07/12 - 07/19 (48)
    • ►  05/17 - 05/24 (2)
    • ►  01/05 - 01/12 (2)
  • ►  2019 (74)
    • ►  07/07 - 07/14 (6)
    • ►  06/16 - 06/23 (6)
    • ►  02/10 - 02/17 (17)
    • ►  01/13 - 01/20 (37)
    • ►  01/06 - 01/13 (8)
  • ►  2018 (376)
    • ►  12/30 - 01/06 (24)
    • ►  12/16 - 12/23 (8)
    • ►  12/09 - 12/16 (98)
    • ►  12/02 - 12/09 (16)
    • ►  11/18 - 11/25 (36)
    • ►  11/04 - 11/11 (18)
    • ►  10/28 - 11/04 (10)
    • ►  10/21 - 10/28 (26)
    • ►  10/14 - 10/21 (52)
    • ►  10/07 - 10/14 (4)
    • ►  09/30 - 10/07 (2)
    • ►  09/23 - 09/30 (68)
    • ►  09/16 - 09/23 (4)
    • ►  09/09 - 09/16 (4)
    • ►  08/26 - 09/02 (6)

Data Publish News

Loading...

Al Jazeera – Breaking News, World News and Video from Al Jazeera

Loading...

Laravel News

Loading...

Copyright © CoderFunda | Powered by Blogger
Design by Coderfunda | Blogger Theme by Coderfunda | Distributed By Coderfunda