Skip to content

SDK-SPEC-CSHARP — C# SDK Specification

Status: Draft Owner: Platform Engineering Package: Simpaisa.SDK Runtime: .NET 6+ Last Updated: 2026-04-03


1. Overview

Official C# SDK for the Simpaisa Payment Gateway. Provides async-first typed access to Pay-Ins, Pay-Outs, Remittances, and Cards across PK, BD, NP, and IQ corridors. Handles 270M+ annual transactions at $1B+ volume. Published to NuGet as Simpaisa.SDK.

2. NuGet Package

<PackageReference Include="Simpaisa.SDK" Version="1.*" />

CLI: dotnet add package Simpaisa.SDK

3. Namespace Structure

Simpaisa.SDK/
├── src/
│   ├── Simpaisa.SDK/
│   │   ├── SimPaisaClient.cs           # Main client entry point
│   │   ├── SimPaisaOptions.cs          # Configuration options
│   │   ├── PayIn/
│   │   │   ├── IPayInClient.cs         # Interface
│   │   │   ├── PayInClient.cs          # initiate, verify, status, list
│   │   │   ├── PayInRequest.cs
│   │   │   └── PayInResponse.cs
│   │   ├── PayOut/
│   │   │   ├── IPayOutClient.cs
│   │   │   ├── PayOutClient.cs         # initiate, status, batch, cancel
│   │   │   ├── PayOutRequest.cs
│   │   │   └── PayOutResponse.cs
│   │   ├── Remittance/
│   │   │   ├── IRemittanceClient.cs
│   │   │   ├── RemittanceClient.cs     # quote, initiate, status, beneficiaries
│   │   │   ├── RemittanceRequest.cs
│   │   │   └── RemittanceResponse.cs
│   │   ├── Cards/
│   │   │   ├── ICardsClient.cs
│   │   │   ├── CardsClient.cs          # pay, capture, void, refund, tokenise
│   │   │   ├── CardPaymentRequest.cs
│   │   │   └── CardPaymentResponse.cs
│   │   ├── Webhook/
│   │   │   ├── WebhookVerifier.cs      # HMAC-SHA256 verification
│   │   │   └── WebhookEvent.cs
│   │   ├── Auth/
│   │   │   ├── RSAAuthProvider.cs      # RSA-SHA256 request signing
│   │   │   └── IAuthProvider.cs        # Interface for custom auth
│   │   ├── Exceptions/
│   │   │   ├── SimPaisaException.cs    # Base exception
│   │   │   ├── AuthenticationException.cs
│   │   │   ├── ValidationException.cs
│   │   │   ├── RateLimitException.cs
│   │   │   └── WebhookVerificationException.cs
│   │   ├── Retry/
│   │   │   └── RetryPolicyOptions.cs   # Polly-based retry configuration
│   │   ├── Idempotency/
│   │   │   └── IdempotencyKeyGenerator.cs
│   │   └── Generated/
│   │       └── Models/                 # OpenAPI-generated models
│   └── Simpaisa.SDK.csproj
├── tests/
│   └── Simpaisa.SDK.Tests/
├── Simpaisa.SDK.sln
└── Directory.Build.props

4. Authentication — RSAAuthProvider

  • Load merchant private key from PEM file via RSA.Create() + ImportFromPem()
  • Sign request body with RSA-SHA256 using System.Security.Cryptography
  • Attach X-Simpaisa-Signature and X-Simpaisa-Merchant-Id headers
  • No third-party crypto dependency required (.NET 6+ has native PEM support)
  • Support key rotation via collection of key paths
var auth = new RSAAuthProvider(
    merchantId: "MCH-001",
    privateKeyPath: "./keys/merchant.pem"
);

5. Async/Await Throughout

  • ALL public methods SHALL be async, returning Task<T>
  • Follow TAP (Task-based Asynchronous Pattern)
  • Accept CancellationToken on all async methods
  • No .Result or .Wait() calls internally
  • Synchronous wrappers NOT provided (async-only by design)
var result = await client.PayIn.InitiateAsync(request, cancellationToken);

6. WebhookVerifier

  • Verify X-Simpaisa-Webhook-Signature using HMACSHA256 class
  • bool Verify(ReadOnlySpan<byte> payload, string signature)
  • Constant-time comparison via CryptographicOperations.FixedTimeEquals()
  • Replay protection: validate timestamp header within tolerance (default 300s)
  • Throw WebhookVerificationException on failure

7. Retry (Polly)

  • Exponential backoff with jitter via Microsoft.Extensions.Http.Polly
  • Configurable max retries (default 3)
  • Retry on: 429, 502, 503, 504, HttpRequestException
  • Never retry: 400, 401, 403, 404, 409, 422
  • Respect Retry-After header
  • Circuit breaker policy optional
  • OnRetryAsync delegate for observability

8. HttpClientFactory Integration

  • Register via dependency injection:
services.AddSimpaisa(options =>
{
    options.Environment = SimPaisaEnvironment.Sandbox;
    options.MerchantId = "MCH-001";
    options.PrivateKeyPath = "./keys/merchant.pem";
    options.Timeout = TimeSpan.FromSeconds(30);
    options.MaxRetries = 3;
});
  • Uses IHttpClientFactory for connection pooling and lifetime management
  • Named HttpClient: "SimPaisaClient"
  • Polly policies attached via AddPolicyHandler()
  • Supports IOptions<SimPaisaOptions> pattern for configuration binding

9. Error Handling

SimPaisaException (base)
├── AuthenticationException     — 401/403 responses
├── ValidationException         — 400/422 with field-level details
├── RateLimitException          — 429 with RetryAfter
├── TimeoutException            — request/connection timeout
├── IdempotencyException        — conflicting idempotency key
├── NetworkException            — connection/DNS failures
└── WebhookVerificationException — signature mismatch

All exceptions include: ErrorCode, StatusCode, RequestId, IsRetryable.

10. Model Generation

  • Models auto-generated from canonical OpenAPI 3.1 spec via NSwag or Kiota
  • Generated into Simpaisa.SDK.Generated.Models namespace
  • System.Text.Json serialisation (not Newtonsoft)
  • Immutable record types where appropriate
  • Regenerated in CI on OpenAPI spec changes

11. Example Usage

using Simpaisa.SDK;

var client = new SimPaisaClient(new SimPaisaOptions
{
    Environment = SimPaisaEnvironment.Sandbox,
    MerchantId = "MCH-001",
    PrivateKeyPath = "./keys/merchant.pem",
});

// Pay-In
var payIn = await client.PayIn.InitiateAsync(new PayInRequest
{
    Amount = 5000m,
    Currency = "PKR",
    Channel = "EASYPAISA",
    CustomerMsisdn = "03001234567",
    CallbackUrl = "https://merchant.com/webhook",
});

// Webhook
var verifier = new WebhookVerifier(secret: "whsec_...");
bool valid = verifier.Verify(rawBody, signatureHeader);

12. Build and Publish

  • Build: dotnet build / MSBuild
  • Test runner: xUnit + FluentAssertions + Moq
  • Linting: .editorconfig + Roslyn analysers
  • CI: Bitbucket Pipelines — lint → test → build → pack → push
  • Publish: NuGet.org with API key
  • Versioning: Semantic versioning via Directory.Build.props
  • Target frameworks: net6.0;net8.0;net9.0

13. Testing Requirements

  • Unit tests for every public method (>90% coverage via Coverlet)
  • Integration tests against sandbox environment
  • Contract tests validating against OpenAPI spec
  • Webhook verification round-trip tests
  • Retry/circuit breaker tests with simulated failures
  • DI registration tests

14. Documentation

  • XML documentation comments on all public types and members
  • README with quickstart, DI setup, and corridor-specific examples
  • CHANGELOG following Keep a Changelog format
  • IntelliSense-compatible (XML docs included in NuGet package)