DevSkill.SSLCommerz
4.0.0
See the version list below for details.
dotnet add package DevSkill.SSLCommerz --version 4.0.0
NuGet\Install-Package DevSkill.SSLCommerz -Version 4.0.0
<PackageReference Include="DevSkill.SSLCommerz" Version="4.0.0" />
<PackageVersion Include="DevSkill.SSLCommerz" Version="4.0.0" />
<PackageReference Include="DevSkill.SSLCommerz" />
paket add DevSkill.SSLCommerz --version 4.0.0
#r "nuget: DevSkill.SSLCommerz, 4.0.0"
#:package DevSkill.SSLCommerz@4.0.0
#addin nuget:?package=DevSkill.SSLCommerz&version=4.0.0
#tool nuget:?package=DevSkill.SSLCommerz&version=4.0.0
DevSkill.SSLCommerz
A .NET library for integrating with the SSLCommerz payment gateway: payment session requests, order validation, IPN verify_sign verification, and transaction search — fully async, typed, and testable.
| Branch | Status |
|---|---|
| main | |
| develop |
Requirements
- .NET 10 SDK or later (the package targets
net10.0)
Installation
dotnet add package DevSkill.SSLCommerz
Configuration
Bind SslCommerzSettings from configuration — this is the single credential source; the client stamps store_id/store_passwd onto every call at send time (credentials never appear on request models).
{
"SSLCommerz": {
"StoreId": "your_store_id",
"StorePassword": "your_store_password",
"Environment": "Sandbox",
"SandboxBaseUrl": null,
"LiveBaseUrl": null
}
}
| Setting | Required | Default | Notes |
|---|---|---|---|
StoreId |
yes | — | Store identifier from the SSLCommerz dashboard |
StorePassword |
yes | — | Stamped at send time, never logged |
Environment |
yes | — | Sandbox or Live |
SandboxBaseUrl |
no | https://sandbox.sslcommerz.com |
Override for proxies/test fakes. Must be absolute HTTPS without a query string |
LiveBaseUrl |
no | https://securepay.sslcommerz.com |
Override, same rules |
Registration
using DevSkill.SSLCommerz;
using DevSkill.SSLCommerz.Models;
builder.Services.Configure<SslCommerzSettings>(
builder.Configuration.GetSection("SSLCommerz"));
builder.Services.AddSingleton<IGatewayClient, GatewayClient>();
To configure the underlying HttpClient (timeouts, proxies, resilience), register via the factory instead — the client accepts an injected HttpClient:
builder.Services.AddHttpClient<IGatewayClient, GatewayClient>();
Results and error handling
API calls never throw for transport, HTTP, or provider failures — they return SslCommerzResult<T>:
| Member | Meaning |
|---|---|
Success |
true when the call succeeded and the payload deserialized |
Value |
The parsed response. Also populated for ProviderFailed results, so the provider's failure payload (e.g. failedreason) stays reachable |
RawJson |
The raw response body, whenever one arrived |
Error |
Category + Message, plus HTTP StatusCode when applicable |
SslCommerzErrorCategory |
Meaning |
|---|---|
Transport |
Timeout or connection failure |
HttpError |
Non-2xx HTTP status (e.g. a 500 HTML error page) |
ProviderFailed |
HTTP 200 but provider status is FAILED — Value still populated |
InvalidResponse |
HTTP 200 body failed to deserialize |
Caller errors (null requests, models failing data-annotation validation) throw synchronously before any I/O.
Request a payment session
using DevSkill.SSLCommerz;
using DevSkill.SSLCommerz.Models;
public sealed class CheckoutService(IGatewayClient gateway)
{
public async Task<string?> StartPaymentAsync(string transactionId, CancellationToken ct = default)
{
var request = new TransactionSessionRequestBuilder()
.AddIntegrationRequiredParameter(new IntegrationRequiredParameter(
totalAmount: 1750.50m,
currency: "BDT",
transactionId: transactionId,
successUrl: "https://yourapp.com/payment/success",
failUrl: "https://yourapp.com/payment/fail",
cancelUrl: "https://yourapp.com/payment/cancel"))
.AddCustomerInformation(new CustomerInformation(
customerName: "Rahim Uddin",
customerEmail: "rahim@example.com",
customerAddress1: "12 Uttara Sector 4",
customerCity: "Dhaka",
customerPostcode: "1230",
customerCountry: "Bangladesh",
customerPhone: "+8801700000000"))
.AddShipmentInformation(new ShipmentInformation(shippingMethod: "NO"))
.AddProductInformation(new ProductInformation(
productName: "Dev Skill Course",
productCategory: "Education",
productProfile: "general"))
.Build();
var result = await gateway.RequestSessionAsync(request, ct);
return result.Success ? result.Value!.GatewayPageUrl : null;
}
}
On success, redirect the customer to result.Value.GatewayPageUrl. Money fields serialize with invariant culture (1750.50), and optional numeric fields left unset (Vat, DiscountAmount, NumberOfItem, …) are simply not sent.
Validate a transaction (Order Validation)
The authoritative money-state check — run it on your success/cancel/IPN callbacks before fulfilling anything:
var result = await gateway.ValidateTransactionAsync(
new ValidationRequest { ValidationId = valId }, ct);
if (result.Success
&& result.Value!.Status == "VALID"
&& result.Value.TransactionId == expectedTransactionId
&& result.Value.CurrencyType == "BDT"
&& result.Value.Amount == expectedAmount)
{
// The payment is real and belongs to this order — fulfil it
}
Handle an IPN
Verify the verify_sign checksum over the raw posted fields (never over a re-serialized model), then parse:
using DevSkill.SSLCommerz;
using DevSkill.SSLCommerz.Models;
using Microsoft.Extensions.Options;
[ApiController]
public sealed class IpnController(
IOptions<SslCommerzSettings> settings,
IGatewayClient gateway) : ControllerBase
{
[HttpPost("/ipn")]
public async Task<IActionResult> Receive(CancellationToken ct)
{
var form = await Request.ReadFormAsync(ct);
var fields = form.ToDictionary(kv => kv.Key, kv => kv.Value.ToString());
// 1. Verify the checksum over the raw field dictionary (fail-closed)
var verifier = new VerifySignVerifier(settings.Value);
if (!verifier.Verify(fields))
{
return Unauthorized();
}
// 2. Parse the notification into a typed model
var notification = PaymentNotificationParser.Parse(fields);
// 3. A valid signature is necessary, NOT sufficient — re-check money
// state via Order Validation before acting on it
var validation = await gateway.ValidateTransactionAsync(
new ValidationRequest { ValidationId = notification.ValidationId! }, ct);
return Ok();
}
}
JSON-body notifications are also supported: PaymentNotificationParser.ParseJson(body).
Query transactions
Search by session key or transaction id — for pending-payment sweeps and late-completion hunts:
var result = await gateway.QueryTransactionAsync(
new TransactionQuery { TransactionId = "DSAB12CD" }, ct);
if (result.Success)
{
foreach (var element in result.Value!)
{
// element.Status (VALID / PENDING / CANCELLED / FAILED, ...) is
// transaction data for your reconciliation logic to decide on
}
}
Upgrading from 3.x
v4 is a breaking overhaul:
GatewayClientis now async behindIGatewayClient(RequestSessionAsync/ValidateTransactionAsync/QueryTransactionAsync) and returnsSslCommerzResult<T>instead of tuples.- Credentials come from
SslCommerzSettingsonly — theCredentialtype and the builder's credential argument are gone. Environments.Development→SslCommerzEnvironment.Sandbox.- Optional numeric request fields are nullable; unset fields are no longer sent as
0. - Transport/HTTP/provider failures return error results instead of throwing during deserialization.
License
See License.txt.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Microsoft.Extensions.Options (>= 10.0.0)
- Newtonsoft.Json (>= 13.0.3)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 4.0.1 | 222 | 8/19/2026 |
| 4.0.0 | 101 | 8/19/2026 |
| 2.0.105 | 556 | 1/11/2024 |
| 2.0.104 | 657 | 9/21/2023 |
| 2.0.103 | 260 | 9/21/2023 |
| 2.0.33 | 587 | 6/22/2023 |
| 2.0.31 | 2,131 | 3/2/2022 |
| 2.0.30 | 675 | 3/1/2022 |
| 2.0.29 | 1,120 | 1/17/2022 |
| 2.0.3 | 476 | 12/5/2022 |
| 1.0.39 | 571 | 11/18/2021 |
| 1.0.38 | 500 | 11/18/2021 |
| 1.0.37 | 502 | 11/18/2021 |
| 1.0.36 | 476 | 11/18/2021 |
| 1.0.26 | 543 | 12/12/2021 |
| 1.0.25 | 498 | 12/5/2021 |
| 1.0.23 | 498 | 12/5/2021 |
| 1.0.22 | 484 | 12/5/2021 |
| 1.0.21 | 506 | 12/5/2021 |
| 1.0.20 | 496 | 12/5/2021 |
v4.0.0 — breaking overhaul: async IGatewayClient with a typed SslCommerzResult result type (transport/HTTP/provider errors never throw); credentials stamped from SslCommerzSettings (single source); configurable sandbox/live base URLs; IPN verify_sign verifier and payment-notification parser; transaction query API; optional numeric request fields are nullable and unset fields are no longer sent; invariant-culture money formatting; SslCommerzEnvironment { Sandbox, Live } replaces Environments { Development, Live }.