Swish SDK for .NET
Comprehensive implementation guide for NordAPI.Swish v1.1.6 on .NET 8, covering mTLS 1.2+ transport, deterministic HMAC-SHA256 webhook verification, and distributed replay protection.
Comprehensive implementation guide for NordAPI.Swish v1.1.6 on .NET 8, covering mTLS 1.2+ transport, deterministic HMAC-SHA256 webhook verification, and distributed replay protection.
Production transport
No silent downgrade
HMAC + nonce checks
Idempotency reuse
Ready to implement? Full technical documentation is available in the GitHub Docs Portal.
Install NordAPI.Swish from NuGet. The package targets .NET 8+ and includes all required dependencies for mTLS transport and webhook verification.
dotnet add package NordAPI.Swish
Or add via PackageReference in your .csproj. Pin a concrete version for
production
deployments.
Register the Swish client in your dependency injection container using AddSwishClient.
Configuration is driven by environment variables. For local development, fallback values are acceptable;
in
production, use secrets management and remove all fallbacks.
using NordAPI.Swish;
using NordAPI.Swish.DependencyInjection;
var builder = WebApplication.CreateBuilder(args);
// Register the Swish client using environment variables
builder.Services.AddSwishClient(opts =>
{
opts.BaseAddress = new Uri(Environment.GetEnvironmentVariable("SWISH_BASE_URL")
?? "https://example.invalid");
opts.ApiKey = Environment.GetEnvironmentVariable("SWISH_API_KEY")
?? "dev-key";
opts.Secret = Environment.GetEnvironmentVariable("SWISH_SECRET")
?? "dev-secret";
});
The client is injected via ISwishClient and provides methods for payments, refunds, and
status
polling.
The SDK enforces mTLS by default. Client certificates are configured via environment variables. If
RequireMtls = true (default) and no certificate is found, the SDK throws
SwishConfigurationException during handler creation.
SWISH_PFX_PATH — Path to the client certificate (.pfx)SWISH_PFX_PASSWORD — Certificate password
In Debug builds, server certificate validation is relaxed for local testing. In Release builds, strict
certificate chain validation is enforced. Set RequireMtls = false only for controlled mock
environments.
NordAPI provides an optional webhook hardening pattern using HMAC-SHA256 signatures. Your webhook endpoint must verify the signature before processing any callback.
X-Swish-Signature, X-Swish-Timestamp, and X-Swish-Nonce are
NordAPI hardening headers, not official Swish callback baseline. You add these at your
edge
layer.
The signature is computed as Base64-encoded HMAC-SHA256 over a canonical string. The canonical string is constructed as:
<timestamp>\n<nonce>\n<body>
Where \n is a literal newline character (0x0A). The body must be the exact raw UTF-8
bytes of the request body with no modification.
Default verification limits are 5 minutes for allowed clock skew and 10 minutes for maximum message age.
# Generate signature for testing
ts="$(date +%s)"
nonce="$(uuidgen)"
body='{"event":"payment_received","paymentId":"pay_123456"}'
canonical="$(printf "%s\n%s\n%s" "$ts" "$nonce" "$body")"
sig="$(printf "%s" "$canonical" | openssl dgst -sha256 -hmac "$SWISH_WEBHOOK_SECRET" -binary | openssl base64)"
Replay protection prevents attackers from re-submitting captured webhook requests. The SDK tracks seen nonces and rejects duplicates with HTTP 409.
SWISH_REDIS,
REDIS_URL, or SWISH_REDIS_CONN
The sample application fails fast in Production environment if no persistent nonce store is
configured.
The SDK is designed to fail closed on security-sensitive operations. Invalid or missing configuration does not result in degraded operation — it results in explicit failure.
RequireMtls = true throws
SwishConfigurationException
This is intentional engineering discipline. Unsafe states are never silently accepted.