pratiksahu2003/cashfree-sdk

A lightweight PHP SDK and Laravel package for the Cashfree Payment Gateway (PG v3 API).

Maintainers

Package info

github.com/Pratiksahu2003/cashfree-sdk

pkg:composer/pratiksahu2003/cashfree-sdk

Statistics

Installs: 1

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.0.1 2026-06-24 07:40 UTC

This package is auto-updated.

Last update: 2026-06-24 07:46:58 UTC


README

Tests License: MIT PHP Version

Repository: github.com/Pratiksahu2003/cashfree-sdk

A production-ready PHP SDK and Laravel package for the Cashfree Payment Gateway (PG v3 API).

Create orders, fetch payment status, process refunds, verify webhooks with HMAC-SHA256 signatures, and optionally persist transactions in Laravel using the included Eloquent model and migration.

Table of Contents

Features

Feature Description
PG v3 API Orders, order status, refunds
Webhook security HMAC-SHA256 signature verification
Laravel integration Auto-discovered service provider, facade, config, migrations
Plain PHP support Use CashfreeClient directly without Laravel
Safe logging Request/response logging with secret key redaction
Automatic retries Configurable retries for network and transient API errors
Eloquent model Optional cashfree_payments table for transaction records

Requirements

  • PHP 8.0+
  • Composer
  • Cashfree merchant account (Sign up)
  • Laravel 10, 11, or 12 (only if using the Laravel integration)

Installation

Install in your Laravel project with one command:

composer require pratiksahu2003/cashfree-sdk

When Composer asks to trust the plugin, choose yes (or add this once to your Laravel composer.json):

"config": {
    "allow-plugins": {
        "pratiksahu2003/cashfree-sdk": true
    }
}

What happens automatically

After composer require, the package runs setup for you — no manual steps:

Step Automatic action
Service provider & facade Laravel auto-discovery
Config Published to config/cashfree.php
Environment variables Appended to .env and .env.example
Migrations Loaded from the package (run php artisan migrate when ready)
Cache package:discover and config:clear run for you

You only need to fill in your Cashfree credentials in .env:

CASHFREE_APP_ID=your_app_id
CASHFREE_SECRET_KEY=your_secret_key

Configuration

Config and .env keys are created automatically when you install the package. Customize config/cashfree.php if needed.

Environment Variables

# Required — get from Cashfree Merchant Dashboard
CASHFREE_APP_ID=your_app_id
CASHFREE_SECRET_KEY=your_secret_key

# sandbox (testing) or production (live payments)
CASHFREE_ENV=sandbox

# Optional
CASHFREE_API_VERSION=2023-08-01
CASHFREE_LOGGING_ENABLED=true
CASHFREE_LOG_CHANNEL=cashfree
CASHFREE_RETRY_ATTEMPTS=3
CASHFREE_RETRY_BACKOFF_MS=500
Variable Required Default Description
CASHFREE_APP_ID Yes Cashfree Client ID
CASHFREE_SECRET_KEY Yes Cashfree Client Secret
CASHFREE_ENV No sandbox sandbox or production
CASHFREE_API_VERSION No 2023-08-01 Cashfree API version header
CASHFREE_LOGGING_ENABLED No true Enable API and webhook logs
CASHFREE_LOG_CHANNEL No Laravel default Dedicated log channel name
CASHFREE_RETRY_ATTEMPTS No 3 Retry count for transient failures
CASHFREE_RETRY_BACKOFF_MS No 500 Backoff delay in milliseconds

Custom Log Channel (Optional)

Add to config/logging.php:

'channels' => [
    'cashfree' => [
        'driver' => 'single',
        'path' => storage_path('logs/cashfree.log'),
        'level' => 'debug',
    ],
],

Database Migration (Optional)

Run the included migration to create the cashfree_payments table:

php artisan migrate

To customize the schema, publish migrations first:

php artisan vendor:publish --tag=cashfree-migrations
php artisan migrate

Usage

Laravel (Facade)

Create an Order

use CashfreePayment\Facades\Cashfree;

$response = Cashfree::createOrder([
    'order_id' => 'order_' . uniqid(),
    'order_amount' => 150.00,
    'order_currency' => 'INR',
    'customer_details' => [
        'customer_id' => 'user_992',
        'customer_phone' => '9999999999',
        'customer_email' => 'customer@example.com',
    ],
    'order_meta' => [
        'return_url' => 'https://yoursite.com/payment/callback?order_id={order_id}',
        'notify_url' => 'https://yoursite.com/payment/webhook',
    ],
]);

$paymentSessionId = $response['payment_session_id'];
$paymentLink = $response['payment_link'];

Get Order Status

$order = Cashfree::getOrder('order_abc123');
$status = $order['order_status']; // PAID, ACTIVE, EXPIRED, etc.

Create a Refund

$refund = Cashfree::createRefund('order_abc123', [
    'refund_amount' => 150.00,
    'refund_id' => 'refund_' . uniqid(),
    'refund_note' => 'Customer requested refund',
]);

List Refunds for an Order

$refunds = Cashfree::getRefunds('order_abc123');

Dependency Injection

use CashfreePayment\CashfreeClient;

public function __construct(protected CashfreeClient $cashfree) {}

public function pay()
{
    return $this->cashfree->createOrder([/* ... */]);
}

Plain PHP (No Framework)

Use CashfreeClient directly in any PHP project:

<?php

require __DIR__ . '/vendor/autoload.php';

use CashfreePayment\CashfreeClient;
use CashfreePayment\Exceptions\CashfreeException;

$client = new CashfreeClient(
    appId: getenv('CASHFREE_APP_ID'),
    secretKey: getenv('CASHFREE_SECRET_KEY'),
    environment: 'sandbox',
    apiVersion: '2023-08-01',
    logger: null,
    loggingEnabled: false
);

try {
    $order = $client->createOrder([
        'order_id' => 'order_' . uniqid(),
        'order_amount' => 99.00,
        'order_currency' => 'INR',
        'customer_details' => [
            'customer_id' => 'cust_1',
            'customer_phone' => '9999999999',
            'customer_email' => 'user@example.com',
        ],
    ]);

    echo $order['payment_link'];
} catch (CashfreeException $e) {
    echo 'Payment error: ' . $e->getMessage();
}

Webhook Verification

Cashfree sends webhooks with x-webhook-signature and x-webhook-timestamp headers. Always verify before processing.

Laravel Controller

use CashfreePayment\Facades\Cashfree;
use Illuminate\Http\Request;

public function webhook(Request $request)
{
    $signature = $request->header('x-webhook-signature');
    $timestamp = $request->header('x-webhook-timestamp');
    $rawPayload = $request->getContent();

    if (!Cashfree::verifyWebhook($timestamp, $rawPayload, $signature)) {
        return response()->json(['message' => 'Invalid signature'], 400);
    }

    $payload = json_decode($rawPayload, true);
    // Process payment event safely...

    return response()->json(['status' => 'OK']);
}

Exclude Webhook from CSRF (Laravel)

Laravel 11+ — in bootstrap/app.php:

->withMiddleware(function (Middleware $middleware) {
    $middleware->validateCsrfTokens(except: [
        'payment/webhook',
    ]);
})

Laravel 10 and below — in app/Http/Middleware/VerifyCsrfToken.php:

protected $except = [
    'payment/webhook',
];

Configure the webhook URL in your Cashfree Dashboard to match your route (e.g. https://yoursite.com/payment/webhook).

Database Model (Laravel)

use CashfreePayment\Models\CashfreePayment;

$payment = CashfreePayment::where('order_id', 'order_abc123')->first();

if ($payment) {
    echo $payment->status;           // PAID, ACTIVE, FAILED, etc.
    echo $payment->transaction_id;
    echo $payment->amount;
    $rawData = $payment->raw_response; // auto-cast to array
}

Save a record after creating an order:

CashfreePayment::create([
    'order_id' => $orderId,
    'amount' => 150.00,
    'currency' => 'INR',
    'customer_id' => 'user_992',
    'customer_phone' => '9999999999',
    'customer_email' => 'customer@example.com',
    'status' => $response['order_status'] ?? 'ACTIVE',
    'payment_session_id' => $response['payment_session_id'] ?? null,
    'raw_response' => $response,
]);

Complete Laravel Example

The examples/ directory contains ready-to-use reference code:

File Description
examples/PaymentController.php Full controller: create order, callback, webhook, refund
examples/routes.php Route definitions and CSRF exclusion notes

Copy these into your Laravel app and adjust route names/URLs as needed.

Error Handling

All API methods throw CashfreePayment\Exceptions\CashfreeException on failure.

use CashfreePayment\Exceptions\CashfreeException;

try {
    $order = Cashfree::createOrder($params);
} catch (CashfreeException $e) {
    $message = $e->getMessage();           // Human-readable error
    $httpCode = $e->getCode();             // HTTP status code
    $apiError = $e->getErrorResponse();    // Raw Cashfree error payload (array|null)
}

Common causes:

Error Fix
Cashfree credentials are not configured Set CASHFREE_APP_ID and CASHFREE_SECRET_KEY in .env
401 Unauthorized Wrong App ID or Secret Key
Signature verification failed Wrong secret key or modified webhook body
Connection errors Check server outbound HTTPS; retries run automatically

Logging

When CASHFREE_LOGGING_ENABLED=true, the SDK logs:

  • API requests — method, URL, payload, redacted headers
  • API responses — status code and JSON body
  • API errors — error payloads and system messages
  • Webhook events — verification success/failure with payload

The x-client-secret header is always logged as REDACTED.

API Reference

CashfreeClient / Cashfree Facade

Method Description
createOrder(array $params): array Create a new payment order
getOrder(string $orderId): array Fetch order details
createRefund(string $orderId, array $params): array Initiate a refund
getRefunds(string $orderId): array List refunds for an order
verifyWebhook(string $timestamp, string $rawBody, string $signature): bool Validate webhook signature

Order Payload (Minimum)

[
    'order_id' => 'unique_order_id',      // Required — your reference
    'order_amount' => 100.00,             // Required
    'order_currency' => 'INR',            // Required
    'customer_details' => [              // Required
        'customer_id' => 'cust_1',
        'customer_phone' => '9999999999',
        'customer_email' => 'user@example.com',
    ],
    'order_meta' => [                    // Recommended
        'return_url' => 'https://yoursite.com/callback?order_id={order_id}',
        'notify_url' => 'https://yoursite.com/webhook',
    ],
]

Refer to the Cashfree PG API documentation for full parameter details.

Testing

Run the package test suite:

composer install
composer test

Or directly:

./vendor/bin/phpunit

Tests cover webhook verification, credential validation, and environment configuration.

Troubleshooting

Package not auto-discovered

php artisan package:discover
php artisan config:clear

Webhook returns 419 (CSRF token mismatch)

Add your webhook route to CSRF exceptions (see Webhook Verification).

Webhook signature always fails

  • Use $request->getContent() for the raw body — do not use $request->all() or $request->json()
  • Ensure CASHFREE_SECRET_KEY matches the environment (sandbox vs production)
  • Confirm x-webhook-timestamp and x-webhook-signature headers are present

Payments work in sandbox but not production

  • Set CASHFREE_ENV=production
  • Use production App ID and Secret Key from the Cashfree dashboard
  • Update webhook URL to your live domain

Class "CashfreePayment\Facades\Cashfree" not found

Run composer dump-autoload and ensure the package is installed correctly.

License

This project is open-sourced software licensed under the MIT License.

Support