PHPackages                             raiyansarker/sslcommerz-sdk - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Payment Processing](/categories/payments)
4. /
5. raiyansarker/sslcommerz-sdk

ActiveLibrary[Payment Processing](/categories/payments)

raiyansarker/sslcommerz-sdk
===========================

A modern, typesafe PHP SDK for SSLCommerz Payment Gateway using Saloon PHP.

00PHPCI passing

Since Apr 14Pushed 2mo agoCompare

[ Source](https://github.com/raiyansarker/sslcommerz-sdk)[ Packagist](https://packagist.org/packages/raiyansarker/sslcommerz-sdk)[ RSS](/packages/raiyansarker-sslcommerz-sdk/feed)WikiDiscussions main Synced 2w ago

READMEChangelogDependenciesVersions (1)Used By (0)

SSLCommerz PHP SDK
==================

[](#sslcommerz-php-sdk)

> **⚠️ Experimental**This package is under active development. The implementation is based on the [official v4 documentation](https://developer.sslcommerz.com/doc/v4) but has not been exhaustively tested against the live API. Breaking changes may occur between releases. **Test thoroughly in sandbox mode before deploying to production.**

A modern, typesafe PHP SDK for [SSLCommerz](https://www.sslcommerz.com/) Payment Gateway, built on top of [Saloon PHP](https://docs.saloon.dev/).

Features
--------

[](#features)

- **Modern PHP**: Requires PHP 8.3 or higher.
- **Typesafe**: Uses DTOs and custom response classes.
- **Saloon PHP**: Leverages the power of [Saloon v4](https://docs.saloon.dev/) for API requests.
- **Testing**: Built-in support for mocking and testing with [Pest v4](https://pestphp.com/).
- **PHPStan**: Analyzed at `max` level for maximum reliability.

Installation
------------

[](#installation)

```
composer require raiyansarker/sslcommerz-sdk
```

Usage
-----

[](#usage)

### Initialize Connector

[](#initialize-connector)

```
use RaiyanSarker\SSLCommerz\SSLCommerzConnector;

$connector = new SSLCommerzConnector(
    storeId: 'your_store_id',
    storePassword: 'your_store_password',
    isSandbox: true // Set to false for live
);
```

### Initialize Payment

[](#initialize-payment)

```
use RaiyanSarker\SSLCommerz\Data\PaymentData;

$paymentData = new PaymentData(
    totalAmount: 100.00,
    currency: 'BDT',
    transactionId: 'TRANS_123456',
    successUrl: 'https://your-domain.com/success',
    failUrl: 'https://your-domain.com/fail',
    cancelUrl: 'https://your-domain.com/cancel',
    customerName: 'John Doe',
    customerEmail: 'john@example.com',
    customerAddress1: 'Dhaka',
    customerCity: 'Dhaka',
    customerCountry: 'Bangladesh',
    customerPhone: '01700000000',
    customerPostcode: '1234',
    productName: 'Test Product',
    productCategory: 'Electronics'
);

$response = $connector->initializePayment($paymentData);

if ($response->isSuccess()) {
    $gatewayUrl = $response->getGatewayPageURL();
    // Redirect user to $gatewayUrl
} else {
    echo "Error: " . $response->getFailedReason();
}
```

### Validate Payment

[](#validate-payment)

```
$valId = $_POST['val_id']; // From SSLCommerz callback

// ⚠️ Never trust the raw POST data from SSLCommerz callbacks directly.
// Always validate the val_id against the SSLCommerz Validation API.
$response = $connector->validatePayment($valId);

if ($response->isValid()) {
    // ⚠️ Always verify the amount and currency match your order records.
    $transactionId = $response->getTransactionId();
    $amount = $response->getAmount();
    $currency = $response->getCurrency();

    // ⚠️ Check risk level before fulfilling. 0 = safe, 1 = risky.
    if ($response->getRiskLevel() === 1) {
        // Hold the order and review manually
    }

    // Update your database
}
```

### Query Transaction

[](#query-transaction)

```
$response = $connector->queryTransaction('TRANS_123456');

if ($response->isSuccess()) {
    $transaction = $response->getFirstTransaction();
    // Handle transaction details
}
```

### Refund Transaction

[](#refund-transaction)

```
$response = $connector->refundTransaction(
    refundAmount: 50.00,
    bankTransactionId: 'BANK_TRAN_ID',
    refundTransactionId: 'REFUND_TRAN_' . uniqid(),
    referenceTransactionId: 'TRANS_123456',
    refundRemarks: 'Customer requested refund'
);

if ($response->isSuccess()) {
    echo "Refund initiated: " . $response->getRefundReferenceId();
}
```

Laravel Integration
-------------------

[](#laravel-integration)

The SSLCommerz PHP SDK provides seamless integration with Laravel through a built-in Service Provider and Facade.

### 1. Installation &amp; Auto-Discovery

[](#1-installation--auto-discovery)

The SDK uses Laravel's package auto-discovery. Once you install the package via Composer, the Service Provider and `SSLCommerz` Facade will be registered automatically.

### 2. Configuration

[](#2-configuration)

Publish the default configuration file to `config/sslcommerz.php`:

```
php artisan vendor:publish --tag="sslcommerz-config"
```

#### Environment Variables

[](#environment-variables)

Configure your SSLCommerz credentials in your `.env` file:

```
SSLCOMMERZ_STORE_ID=your_store_id
SSLCOMMERZ_STORE_PASSWORD=your_store_password
SSLCOMMERZ_SANDBOX=true
```

#### Configuration Options

[](#configuration-options)

The published `config/sslcommerz.php` file allows you to manage:

OptionEnvironment VariableDefaultDescription`store_id``SSLCOMMERZ_STORE_ID``null`Your SSLCommerz Store ID.`store_password``SSLCOMMERZ_STORE_PASSWORD``null`Your SSLCommerz Store Password.`sandbox``SSLCOMMERZ_SANDBOX``true`Set to `false` for production (live) mode.### 3. Usage

[](#3-usage)

You can interact with the SDK using either the `SSLCommerz` Facade or by injecting the `SSLCommerzConnector`.

#### Using the Facade

[](#using-the-facade)

The Facade provides a static interface to all connector methods:

```
use RaiyanSarker\SSLCommerz\Laravel\Facades\SSLCommerz;
use RaiyanSarker\SSLCommerz\Data\PaymentData;

public function initiatePayment()
{
    $paymentData = new PaymentData(
        totalAmount: 100.00,
        currency: 'BDT',
        transactionId: 'TXN_' . uniqid(),
        successUrl: route('payment.success'),
        failUrl: route('payment.fail'),
        cancelUrl: route('payment.cancel'),
        customerName: 'John Doe',
        customerEmail: 'john@example.com',
        customerAddress1: 'Dhaka',
        customerCity: 'Dhaka',
        customerCountry: 'Bangladesh',
        customerPhone: '01700000000',
        customerPostcode: '1207',
        productName: 'Test Product',
        productCategory: 'General',
    );

    $response = SSLCommerz::initializePayment($paymentData);

    if ($response->isSuccess()) {
        return redirect()->away($response->getGatewayPageURL());
    }

    return back()->with('error', $response->getFailedReason());
}
```

#### Dependency Injection

[](#dependency-injection)

The `SSLCommerzConnector` is bound as a singleton in the Laravel service container:

```
use RaiyanSarker\SSLCommerz\SSLCommerzConnector;
use RaiyanSarker\SSLCommerz\Data\PaymentData;

public function handleCallback(Request $request, SSLCommerzConnector $connector)
{
    $response = $connector->validatePayment($request->input('val_id'));

    if ($response->isValid()) {
        // Handle successful payment
    }
}
```

### 4. Handling Callbacks &amp; CSRF

[](#4-handling-callbacks--csrf)

SSLCommerz requires three mandatory callback URLs (Success, Fail, and Cancel) and an optional IPN (Instant Payment Notification) URL.

#### Define Routes

[](#define-routes)

SSLCommerz sends a **POST** request to these URLs. Define them in your `routes/web.php`:

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

Route::post('/payment/success', [PaymentController::class, 'success']);
Route::post('/payment/fail', [PaymentController::class, 'fail']);
Route::post('/payment/cancel', [PaymentController::class, 'cancel']);
Route::post('/payment/ipn', [PaymentController::class, 'ipn']);
```

#### Exclude from CSRF Protection

[](#exclude-from-csrf-protection)

Since SSLCommerz sends external POST requests, you must exclude these routes from Laravel's CSRF protection.

**For Laravel 11+ (in `bootstrap/app.php`):**

```
->withMiddleware(function (Middleware $middleware) {
    $middleware->validateCsrfTokens(except: [
        '/payment/success',
        '/payment/fail',
        '/payment/cancel',
        '/payment/ipn',
    ]);
})
```

**For older Laravel versions (in `app/Http/Middleware/VerifyCsrfToken.php`):**

```
protected $except = [
    '/payment/success',
    '/payment/fail',
    '/payment/cancel',
    '/payment/ipn',
];
```

#### Handling the Callback in a Controller

[](#handling-the-callback-in-a-controller)

```
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use RaiyanSarker\SSLCommerz\Laravel\Facades\SSLCommerz;

class PaymentController extends Controller
{
    public function success(Request $request)
    {
        $validationId = $request->input('val_id');
        $response = SSLCommerz::validatePayment($validationId);

        if ($response->isValid()) {
            // ⚠️ Always verify amount and currency match your order records.
            // ⚠️ Check risk level before fulfilling. 0 = safe, 1 = risky.
            if ($response->getRiskLevel() === 1) {
                // Hold the order and review manually
                return redirect()->route('checkout')->with('error', 'Payment is under review.');
            }

            $transactionId = $response->getTransactionId();
            // Update your database, mark order as paid
            return redirect()->route('order.complete', ['id' => $transactionId]);
        }

        return redirect()->route('checkout')->with('error', 'Payment validation failed.');
    }

    public function fail(Request $request)
    {
        return redirect()->route('checkout')->with('error', 'Payment failed.');
    }

    public function cancel(Request $request)
    {
        return redirect()->route('checkout')->with('info', 'Payment cancelled.');
    }

    public function ipn(Request $request)
    {
        // IPN is sent in the background by SSLCommerz
        $validationId = $request->input('val_id');
        $status = $request->input('status');

        if ($status === 'VALID' || $status === 'VALIDATED') {
            $response = SSLCommerz::validatePayment($validationId);

            if ($response->isValid()) {
                // Update your database using $response->getTransactionId()
                // It is recommended to check if the order is already marked as paid
            }
        }

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

### 5. Testing &amp; Mocking in Laravel

[](#5-testing--mocking-in-laravel)

When writing tests for your Laravel application, you can use the `SSLCommerz` Facade's built-in mocking capabilities or Saloon's mocking features.

#### Mocking with Facade

[](#mocking-with-facade)

```
use RaiyanSarker\SSLCommerz\Laravel\Facades\SSLCommerz;
use RaiyanSarker\SSLCommerz\Responses\PaymentInitializationResponse;

test('it redirects to gateway on successful initialization', function () {
    SSLCommerz::shouldReceive('initializePayment')
        ->once()
        ->andReturn(/* mock response object */);

    $response = $this->post('/checkout');

    $response->assertRedirect();
});
```

#### Mocking with Saloon

[](#mocking-with-saloon)

Since the SDK is built on Saloon, you can use `Saloon::fake()` for more granular control:

```
use Saloon\Http\Faking\MockResponse;
use Saloon\Laravel\Facades\Saloon;
use RaiyanSarker\SSLCommerz\Requests\InitializePaymentRequest;

Saloon::fake([
    InitializePaymentRequest::class => MockResponse::make(['status' => 'SUCCESS', 'GatewayPageURL' => 'https://sandbox.sslcommerz.com/gw'], 200),
]);
```

Testing
-------

[](#testing)

The project uses [Pest](https://pestphp.com/) for testing. Tests are divided into:

- `tests/Unit`: For isolated logic (e.g., DTO transformations).
- `tests/Feature`: For integration tests and API request/response validation.

Run tests with Pest:

```
composer test
```

Run static analysis with PHPStan:

```
composer stan
```

Run both:

```
composer all
```

Resources
---------

[](#resources)

- **Postman Collection**: A comprehensive Postman collection is available in `resources/postman/SSLCommerz.postman_collection.json` to help you explore and test the API endpoints.

Credits
-------

[](#credits)

- Special thanks to [sumoncse19](https://www.postman.com/sumoncse19) for providing the original Postman collection for the SSLCommerz API.

License
-------

[](#license)

MIT

###  Health Score

19

—

LowBetter than 9% of packages

Maintenance57

Moderate activity, may be stable

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity12

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/479370?v=4)[Raiyan Kabir](/maintainers/raiyan)[@raiyan](https://github.com/raiyan)

---

Top Contributors

[![raiyansarker](https://avatars.githubusercontent.com/u/38852396?v=4)](https://github.com/raiyansarker "raiyansarker (34 commits)")

### Embed Badge

![Health badge](/badges/raiyansarker-sslcommerz-sdk/health.svg)

```
[![Health](https://phpackages.com/badges/raiyansarker-sslcommerz-sdk/health.svg)](https://phpackages.com/packages/raiyansarker-sslcommerz-sdk)
```

###  Alternatives

[omnipay/coinbase

Coinbase driver for the Omnipay payment processing library

18570.2k1](/packages/omnipay-coinbase)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
