Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Cashfree Laravel Package

loveycom/cashfree

Laravel package for CashFree (India) integrating Marketplace Settlement and Payment Gateway APIs. Includes config publishing, environment switching (test/prod), and helper classes like Marketplace (e.g., checkBalance) to simplify CashFree API calls in Laravel.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps to First Use

  1. Installation:

    composer require loveycom/cashfree
    php artisan vendor:publish --provider="LoveyCom\CashFree\CashFreeServiceProvider"
    

    Configure config/cashfree.php with your appID, secretKey, and environment (testURL/prodURL).

  2. First Payment Flow:

    use LoveyCom\CashFree\PaymentGateway\Order;
    
    $order = new Order();
    $orderData = [
        'orderId' => 'UNIQUE-ORDER-ID-' . time(),
        'orderAmount' => 10000, // INR (use integers)
        'customerName' => 'John Doe',
        'customerEmail' => 'john@example.com',
        'customerPhone' => '919999999999',
        'returnUrl' => route('payment.success'),
        'notifyUrl' => route('payment.webhook'),
    ];
    $response = $order->create($orderData);
    $paymentLink = $order->getLink($orderData['orderId']);
    

    Redirect users to $paymentLink for payment.

  3. First Marketplace Action:

    use LoveyCom\CashFree\Marketplace\Vendor;
    
    $vendor = new Vendor();
    $vendorData = [
        'vendorName' => 'Vendor ABC',
        'vendorEmail' => 'vendor@example.com',
        'vendorPhone' => '919876543210',
        'bankDetails' => [
            'accountNumber' => '1234567890',
            'ifscCode' => 'HDFC0001234',
        ],
    ];
    $createdVendor = $vendor->create($vendorData);
    

Where to Look First


Implementation Patterns

Core Workflows

1. Payment Processing

  • Create Order → Redirect → Verify:
    // Create order (returns orderId)
    $orderId = $order->create($orderData)->orderId;
    
    // Redirect user to payment link
    return redirect($order->getLink($orderId));
    
    // Verify after redirect (e.g., in success controller)
    $status = $order->getStatus($orderId);
    if ($status->paymentStatus === 'PAID') {
        // Fulfill order
    }
    
  • Refunds:
    $refund = $refundService->create(
        $orderId,
        'REF-' . time(),
        5000, // Amount to refund
        'Customer requested refund'
    );
    

2. Marketplace Settlements

  • Vendor Payouts:
    $vendorId = 'VENDOR-123';
    $payout = $vendor->requestVendorPayout($vendorId, 50000);
    
  • Commission Splits:
    $transaction->attachVendorToTransaction(
        $orderId,
        $vendorId,
        10, // 10% commission
        500  // Fixed amount (optional)
    );
    

3. Webhook Handling

  • Notify URL Endpoint:
    Route::post('/payment/webhook', function (Request $request) {
        $payload = $request->all();
        // Validate signature (CashFree provides `x-cashfree-signature` header)
        if (validatesCashFreeSignature($payload, $request->header('x-cashfree-signature'))) {
            switch ($payload['event']) {
                case 'ORDER.PAID':
                    // Update order status
                    break;
                case 'REFUND.COMPLETED':
                    // Update refund status
                    break;
            }
        }
    });
    

Integration Tips

  • Error Handling: Wrap API calls in try-catch blocks. CashFree returns HTTP errors (e.g., 400 for invalid orderId):

    try {
        $status = $order->getStatus($orderId);
    } catch (\LoveyCom\CashFree\Exceptions\CashFreeException $e) {
        Log::error('CashFree API Error: ' . $e->getMessage());
        // Retry or notify user
    }
    
  • Idempotency: Use unique orderId/referenceId values to avoid duplicate transactions. CashFree’s API supports idempotency keys for refunds (pass via merchantRefundId).

  • Testing: Use CashFree’s sandbox (isLive: false) for development. Mock the notifyUrl endpoint to test webhooks:

    Route::post('/payment/webhook', function () {
        // Log payload for testing
        file_put_contents(storage_path('logs/cashfree_webhook.log'), print_r(request()->all(), true));
    });
    
  • Batch Operations: For ledgers/transactions, paginate results using maxReturn and lastReturnId:

    $ledger = $vendor->getLedger($vendorId, 50, $lastReturnId);
    
  • Laravel Service Container: Bind the package to the container for dependency injection:

    $this->app->bind('cashfree.order', function ($app) {
        return new \LoveyCom\CashFree\PaymentGateway\Order();
    });
    

    Then inject via constructor:

    public function __construct(private Order $order) {}
    

Gotchas and Tips

Pitfalls

  1. API Key Exposure:

    • Risk: Hardcoding appID/secretKey in config/cashfree.php may expose credentials in version control.
    • Fix: Use Laravel’s .env:
      CASHFREE_APP_ID=your_app_id
      CASHFREE_SECRET_KEY=your_secret_key
      
      Update the config file to read from .env:
      'appID' => env('CASHFREE_APP_ID'),
      'secretKey' => env('CASHFREE_SECRET_KEY'),
      
  2. Webhook Signature Validation:

    • Gotcha: CashFree sends a signature header (x-cashfree-signature) to verify webhook authenticity. The package does not include validation logic.
    • Fix: Implement HMAC-SHA256 validation:
      use Illuminate\Support\Facades\Http;
      
      function validatesCashFreeSignature(array $payload, string $signature): bool {
          $secretKey = config('cashfree.secretKey');
          $stringToSign = http_build_query($payload);
          $expectedSignature = hash_hmac('sha256', $stringToSign, $secretKey);
          return hash_equals($expectedSignature, $signature);
      }
      
  3. Amount Precision:

    • Gotcha: CashFree expects amounts in paise (INR) as integers (e.g., 10000 for ₹100). Floating-point values (e.g., 100.00) will fail.
    • Fix: Convert amounts explicitly:
      $amountInPaise = (int) ($amount * 100);
      
  4. Order ID Uniqueness:

    • Gotcha: Duplicate orderId values may cause conflicts. CashFree’s API does not enforce uniqueness globally.
    • Fix: Use UUIDs or timestamp-based IDs:
      $orderId = 'ORD-' . Str::uuid()->toString();
      
  5. Rate Limits:

    • Gotcha: CashFree enforces rate limits (e.g., 100 requests/minute). Batch operations may hit limits.
    • Fix: Implement exponential backoff or queue delayed requests:
      use Illuminate\Support\Facades\Queue;
      
      Queue::later(now()->addSeconds(5), function () use ($orderId) {
          $order->getStatus($orderId);
      });
      
  6. Webhook Retries:

    • Gotcha: CashFree retries failed webhook deliveries (up to 3 times). Your notifyUrl must be idempotent.
    • Fix: Design your endpoint to handle duplicate payloads:
      if (Order::where('cashfree_order_id', $payload['orderId'])->exists()) {
          return response()->json(['status' => 'OK']);
      }
      

Debugging Tips

  1. Enable API Logging: Add a middleware to log all CashFree API requests/responses:
    namespace App\Http\Middleware;
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
croct/coding-standard
croct/plug-php
nqxcode/phpmorphy
boundwize/pyrameter
testo/facade
headercat/phpstan-extension-ide-helper
yosymfony/parser-utils
innmind/black-box
babenkoivan/elastic-migrations
babenkoivan/elastic-adapter
develia/commons
dmstr/symfony-system-resources-bundle
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
renatomarinho/laravel-page-speed
develia/geo-bundle
austinheap/laravel-database-encryption
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle