Datatrans.Sdk
2.0.0
dotnet add package Datatrans.Sdk --version 2.0.0
NuGet\Install-Package Datatrans.Sdk -Version 2.0.0
<PackageReference Include="Datatrans.Sdk" Version="2.0.0" />
<PackageVersion Include="Datatrans.Sdk" Version="2.0.0" />
<PackageReference Include="Datatrans.Sdk" />
paket add Datatrans.Sdk --version 2.0.0
#r "nuget: Datatrans.Sdk, 2.0.0"
#:package Datatrans.Sdk@2.0.0
#addin nuget:?package=Datatrans.Sdk&version=2.0.0
#tool nuget:?package=Datatrans.Sdk&version=2.0.0
Datatrans.Sdk — Datatrans .NET SDK
A strongly-typed, production-ready .NET SDK for the Datatrans Payment API, compatible with .NET 8, .NET 9, and .NET 10. It wraps every documented endpoint behind clean async interfaces, handles authentication, idempotency, and webhook signature validation, and uses System.Text.Json source-generation for zero-reflection serialization.
Both the v1 and v2 transactions APIs are supported behind a single version selector: v1 (DatatransClient.Transactions.V1) has full feature and payment-method coverage and is the recommended default; v2 (DatatransClient.Transactions.V2) is the next-generation API required for Mobile SDK 4.
Table of Contents
- Features
- Requirements
- Installation
- Quick Start
- Configuration
- Services
- Webhook Validation
- Error Handling
- Security
- Testing
- Project Structure
- Contributing
- License
Features
- Full API coverage — all Datatrans v1 endpoints: transactions, aliases, reconciliation, multi-currency, and health check
- Transactions API v2 — UUID transaction IDs and attempt-based status, for Mobile SDK 4 scenarios
- Dependency injection — one-line
services.AddDatatrans(...)wiring - Idempotency support — pass an idempotency key to any mutating operation
- Webhook security — HMAC-SHA256 validation with constant-time comparison
- TLS 1.2/1.3 enforced —
SocketsHttpHandleris configured at registration time - Zero reflection — System.Text.Json source generators throughout
- Typed exceptions —
DatatransAuthenticationException,DatatransValidationException,DatatransApiException - Sandbox / Production — switch environments with a single enum value
Requirements
| Item | Minimum |
|---|---|
| .NET SDK | 8.0 |
| Datatrans merchant account | any |
Installation
The SDK is referenced as a project reference in this repository. Once published to NuGet, add it with:
dotnet add package Datatrans.Sdk
Or reference the project directly:
<ProjectReference Include="..\src\DTSdk\DTSdk.csproj" />
Quick Start
1. Register in Program.cs
using Datatrans.DependencyInjection;
var builder = WebApplication.CreateBuilder(args);
// Register from appsettings.json "Datatrans" section
builder.Services.AddDatatrans(builder.Configuration);
// — OR — configure inline
builder.Services.AddDatatrans(options =>
{
options.MerchantId = "<YOUR_MERCHANT_ID>";
options.Password = "<YOUR_API_PASSWORD>";
options.Environment = DatatransEnvironment.Sandbox;
options.WebhookHmacKey = "your-hmac-hex-key";
});
2. Inject and use DatatransClient
public class PaymentService(DatatransClient datatrans)
{
public async Task<string> CreatePaymentAsync(decimal amount, string currency, string refno)
{
var response = await datatrans.Transactions.V1.InitAsync(new InitTransactionRequest
{
Currency = currency,
Refno = refno,
Amount = (long)(amount * 100), // Datatrans uses minor units (CHF → Rappen)
PaymentMethods = ["VIS", "ECA"],
Redirect = new RedirectRequest
{
SuccessUrl = "https://yoursite.com/success",
CancelUrl = "https://yoursite.com/cancel",
ErrorUrl = "https://yoursite.com/error"
}
});
return response.GetRedirectUrl(); // Redirect customer here
}
}
3. Handle the result
After the customer completes payment and is redirected back, authorize the transaction:
var auth = await datatrans.Transactions.V1.AuthorizeSplitAsync(
transactionId: 240110170459754479L,
request: new AuthorizeSplitRequest
{
Refno = refno,
Amount = 2000,
AutoSettle = true
});
Console.WriteLine($"Auth code: {auth.AcquirerAuthorizationCode}");
Configuration
Add a Datatrans section to appsettings.json:
{
"Datatrans": {
"MerchantId": "<YOUR_MERCHANT_ID>",
"Password": "<YOUR_API_PASSWORD>",
"Environment": "Sandbox",
"Timeout": "00:00:30",
"WebhookHmacKey":"your-hmac-key-hex-from-dashboard",
"WebhookAllowedSkew": "00:05:00",
"EnforceWebhookTimestampOnlyInProduction": false
}
}
| Key | Type | Default | Description |
|---|---|---|---|
MerchantId |
string |
required | Your Datatrans merchant ID |
Password |
string |
required | API password from the dashboard |
Environment |
Sandbox | Production |
Sandbox |
Target API environment |
Timeout |
TimeSpan |
00:00:30 |
Per-request HTTP timeout |
WebhookHmacKey |
string |
null |
Hex HMAC key for webhook validation |
WebhookAllowedSkew |
TimeSpan |
00:05:00 |
Allowed clock skew for webhook timestamp validation. Set to 00:00:00 to disable enforcement. |
EnforceWebhookTimestampOnlyInProduction |
bool |
false |
When true, timestamp validation is only enforced when Environment is Production. |
Never commit credentials to source control. Use environment variables, Azure Key Vault, AWS Secrets Manager, or ASP.NET Core user secrets.
# Use environment variables
export Datatrans__MerchantId=<YOUR_MERCHANT_ID>
export Datatrans__Password=<YOUR_API_PASSWORD>
Services
All services are accessible through the DatatransClient facade injected via DI:
DatatransClient.Transactions // ITransactionsApi — version selector (.V1 / .V2)
DatatransClient.Transactions.V1 // ITransactionService — 16 methods (v1, numeric IDs)
DatatransClient.Transactions.V2 // ITransactionService — 9 methods (v2, UUID IDs)
DatatransClient.Aliases // IAliasService — 7 methods
DatatransClient.Reconciliations // IReconciliationService — 2 methods
DatatransClient.MultiCurrency // IMultiCurrencyService — 1 method
DatatransClient.HealthCheck // IHealthCheckService — 1 method
See the docs/ folder for detailed per-service documentation:
| Service | Documentation |
|---|---|
| Transactions (v1) | docs/transactions.md |
| Transactions (v2) | docs/transactions-v2.md |
| Aliases | docs/aliases.md |
| Reconciliation | docs/reconciliation.md |
| Multi-Currency | docs/multi-currency.md |
| Webhooks | docs/webhooks.md |
Webhook Validation
Datatrans sends POST notifications to your webhook endpoint with a Datatrans-Signature header. Validate it using the injected WebhookSignatureValidator:
[HttpPost("/webhook")]
public async Task<IActionResult> Receive(
[FromServices] WebhookSignatureValidator validator,
[FromServices] IOptions<DatatransOptions> options)
{
Request.EnableBuffering();
using var reader = new StreamReader(Request.Body, leaveOpen: true);
var payload = await reader.ReadToEndAsync();
var signature = Request.Headers["Datatrans-Signature"].ToString();
if (!validator.Validate(signature, payload, options.Value.WebhookHmacKey!))
return Unauthorized();
// Process payload ...
return NoContent();
}
See docs/webhooks.md for full details.
Error Handling
All SDK methods throw typed exceptions derived from DatatransException:
DatatransException
└── DatatransApiException (any non-2xx response)
├── DatatransAuthenticationException (401 / 403)
└── DatatransValidationException (INVALID_PROPERTY, INVALID_JSON_PAYLOAD, …)
try
{
var auth = await datatrans.Transactions.V1.AuthorizeAsync(request);
}
catch (DatatransValidationException ex)
{
// 400 Bad Request — invalid field value
Console.WriteLine($"Validation failed: {ex.Code} — {ex.Message}");
}
catch (DatatransAuthenticationException)
{
// 401/403 — wrong credentials
}
catch (DatatransApiException ex)
{
// Any other API error (declined, not found, server error…)
Console.WriteLine($"API error {ex.HttpStatusCode}: {ex.Code}");
}
Every DatatransApiException exposes:
| Property | Type | Description |
|---|---|---|
Code |
string |
Datatrans error code (e.g. DECLINED) |
Message |
string |
Human-readable error message |
HttpStatusCode |
int |
Raw HTTP status code |
Security
- TLS 1.2 / 1.3 only —
SocketsHttpHandlerrefuses older protocol versions - Basic Auth via DelegatingHandler — credentials are never stored in request bodies
- Webhook HMAC-SHA256 with constant-time comparison — prevents timing attacks
- No credential logging —
DatatransOptionsnever serializes itsPasswordfield - Source-generated JSON — no
JsonSerializer.Deserialize<object>anywhere
Testing
# Run all unit tests
dotnet test tests/Datatrans.Sdk.Tests/Datatrans.Sdk.Tests.csproj
# With coverage
dotnet test tests/Datatrans.Sdk.Tests/Datatrans.Sdk.Tests.csproj \
--collect:"XPlat Code Coverage" \
--results-directory ./coverage
# Run a specific test
dotnet test --filter "FullyQualifiedName~TransactionServiceTests"
The test suite contains 64 unit tests covering:
- All 16 transaction operations (v1)
- All 9 transaction operations (v2)
- All 7 alias operations
- Reconciliation (single & bulk)
- Multi-currency rates
- Health check (ok / non-ok / error)
- Webhook signature validation (10 scenarios)
- Full exception hierarchy (401, 403, 400, 422, 404, 500)
Project Structure
DTSdk/
├── src/Datatrans.Sdk/ # SDK library
│ ├── DatatransClient.cs # Facade: entry point for consumers
│ ├── DatatransOptions.cs # Configuration options
│ ├── DatatransEnvironment.cs # Sandbox / Production enum
│ ├── DependencyInjection/
│ │ └── ServiceCollectionExtensions.cs
│ ├── Http/
│ │ ├── DatatransHttpClient.cs # Internal HTTP wrapper
│ │ ├── DatatransAuthHandler.cs # Basic Auth delegating handler
│ │ ├── IdempotencyHandler.cs # Idempotency-Key header injection
│ │ └── DatatransJsonContext.cs # STJ source-generation context
│ ├── Services/
│ │ ├── Transactions/
│ │ │ ├── ITransactionsApi.cs / TransactionsApi.cs # version selector (.V1 / .V2)
│ │ │ ├── V1/ITransactionService.cs / TransactionService.cs
│ │ │ └── V2/ITransactionService.cs / TransactionService.cs
│ │ ├── IAliasService.cs / AliasService.cs
│ │ ├── IReconciliationService.cs / ReconciliationService.cs
│ │ ├── IMultiCurrencyService.cs / MultiCurrencyService.cs
│ │ └── IHealthCheckService.cs / HealthCheckService.cs
│ ├── Models/
│ │ ├── Common/ # Shared types (Card, Address, detail, etc.)
│ │ ├── Transactions/ # Transaction DTOs: shared + V1/ + V2/
│ │ ├── Requests/ # Alias / reconciliation request DTOs
│ │ └── Responses/ # Alias / reconciliation / multi-currency response DTOs
│ ├── Exceptions/
│ │ ├── DatatransException.cs
│ │ ├── DatatransApiException.cs
│ │ ├── DatatransAuthenticationException.cs
│ │ └── DatatransValidationException.cs
│ └── Webhooks/
│ └── WebhookSignatureValidator.cs
├── tests/Datatrans.Sdk.Tests/ # xUnit unit tests (64 tests)
│ ├── Helpers/MockHttpMessageHandler.cs
│ ├── TestBase.cs
│ └── Unit/
│ ├── TransactionServiceTests.cs
│ ├── TransactionV2ServiceTests.cs
│ ├── AliasServiceTests.cs
│ ├── ReconciliationServiceTests.cs
│ ├── MultiCurrencyServiceTests.cs
│ ├── HealthCheckServiceTests.cs
│ ├── WebhookSignatureValidatorTests.cs
│ └── ErrorHandlingTests.cs
├── samples/Datatrans.Sdk.Example/ # ASP.NET Core Web API sample
│ ├── Program.cs
│ ├── appsettings.json
│ └── Controllers/
│ ├── TransactionsController.cs
│ ├── TransactionsV2Controller.cs
│ ├── AliasController.cs
│ ├── ReconciliationController.cs
│ ├── MultiCurrencyController.cs
│ └── WebhookController.cs
└── docs/ # Per-service documentation
├── transactions.md
├── transactions-v2.md
├── aliases.md
├── reconciliation.md
├── multi-currency.md
└── webhooks.md
Releasing
Create a Git tag and push it to trigger the release workflow which builds, tests, packs and (optionally) publishes the NuGet package.
Run locally:
# create annotated tag
git tag -a v1.2.3 -m "Release v1.2.3"
# push the tag
git push origin --tags
From the GitHub UI you can also run the release workflow manually: Actions → Release → Run workflow.
To publish to NuGet.org automatically, add your API key to repository Secrets as NUGET_API_KEY (Settings → Secrets → Actions). The release workflow will fail early with a clear message if this secret is missing for non-manual (tag) runs.
CI fallback package version
When the release workflow runs without a tag-derived version (for example, a manual run or a branch-based run), the workflow will create a semver-compatible fallback package version so dotnet pack succeeds. The fallback version format is:
0.0.0-ci-<short-sha>
This is only used for producing build artifacts in CI; to publish a final NuGet package with a stable version, create and push a tag like v1.2.3.
Contributing
- Fork the repository and create a feature branch:
git checkout -b feat/my-feature - Write tests — all new behaviour must be covered by unit tests
- Build:
dotnet build DTSdk.sln - Test:
dotnet test tests/DTSdk.Tests/ - Open a Pull Request against
main
Coding conventions
- Target
net10.0; no multi-targeting unless strictly needed - Services are
internal sealed classimplementing apublic interface - All public types use
[JsonPropertyName]— no attribute-less serialization - Async methods must end in
Asyncand accept aCancellationToken - No
Console.WriteLineor logging in the SDK library itself
License
MIT © 2026
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. 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.Http (>= 10.0.5)
- Microsoft.Extensions.Options (>= 10.0.5)
-
net8.0
- Microsoft.Extensions.Http (>= 10.0.5)
- Microsoft.Extensions.Options (>= 10.0.5)
-
net9.0
- Microsoft.Extensions.Http (>= 10.0.5)
- Microsoft.Extensions.Options (>= 10.0.5)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.