MERSEL.Services.DssVerifier.Client
1.0.4
dotnet add package MERSEL.Services.DssVerifier.Client --version 1.0.4
NuGet\Install-Package MERSEL.Services.DssVerifier.Client -Version 1.0.4
<PackageReference Include="MERSEL.Services.DssVerifier.Client" Version="1.0.4" />
<PackageVersion Include="MERSEL.Services.DssVerifier.Client" Version="1.0.4" />
<PackageReference Include="MERSEL.Services.DssVerifier.Client" />
paket add MERSEL.Services.DssVerifier.Client --version 1.0.4
#r "nuget: MERSEL.Services.DssVerifier.Client, 1.0.4"
#:package MERSEL.Services.DssVerifier.Client@1.0.4
#addin nuget:?package=MERSEL.Services.DssVerifier.Client&version=1.0.4
#tool nuget:?package=MERSEL.Services.DssVerifier.Client&version=1.0.4
MERSEL.Services.DssVerifier.Client
mersel-dss-verifier-api-java mikroservisini HTTP üzerinden çağıran istemci SDK'sı.
netstandard2.0 ve net8.0 hedeflerini destekler — yani .NET Framework 4.6.1+, .NET Core 2.x+, .NET 5 / 6 / 7 / 8 / 9, Mono, Xamarin ve Unity 2018.1+ akışlarında çalışır. Sahadaki on-prem Windows servisleri (klasik .NET Framework) ile modern bulut backend'leri (net8.0 LTS) tek paketten beslenir. Tek satır DI kaydıyla XAdES (BES, EPES, T, C, X, XL, A), PAdES (B-B, B-T, B-LT, B-LTA), CAdES (BES → A) imza doğrulama; RFC 3161 zaman damgası doğrulama; sertifika zinciri ve OCSP/CRL revocation kontrollerini uygulamanıza entegre edin. Servis stateless'tir; istemcide herhangi bir özel state tutulmaz, paket güvenle çoklu instance ile kullanılabilir.
Kurulum
dotnet add package MERSEL.Services.DssVerifier.Client
DI Kaydı
// Seçenek 1: appsettings.json'dan oku (varsayılan section: "Services:DssVerifier")
builder.Services.AddDssVerifierClient(builder.Configuration);
// Seçenek 2: Kod ile yapılandır
builder.Services.AddDssVerifierClient(o =>
{
o.BaseUrl = "http://dss-verifier:8086";
o.Timeout = TimeSpan.FromMinutes(5);
});
// Seçenek 3: Sadece URL belirt
builder.Services.AddDssVerifierClient("http://dss-verifier:8086");
appsettings.json:
{
"Services": {
"DssVerifier": {
"BaseUrl": "http://dss-verifier:8086",
"Timeout": "00:02:00"
}
}
}
Not — Authentication: Sunucu kendisi authentication uygulamaz (internal kullanım / API Gateway arkasında çalıştırın). API Gateway, reverse proxy veya başka bir auth katmanı arkasında çalıştırıyorsanız ekstra header'ları (örn.
X-API-Key,Authorization) standartIHttpClientFactoryzincirinden ekleyin:builder.Services.AddHttpClient(DssVerifierClientOptions.HttpClientName) .ConfigureHttpClient(http => { http.DefaultRequestHeaders.Add("X-API-Key", "gateway-secret"); }); // veya: .AddHttpMessageHandler<MyAuthDelegatingHandler>();
DI kaydı sonrası tüketicide:
IDssVerifierClient— tüm domain'lere erişen birleşik cepheISignatureVerifier— XAdES / PAdES / CAdES imza doğrulamaITimestampVerifier— standalone RFC 3161 zaman damgası doğrulamaIHealthClient— sağlık kontrolü ve servis meta-bilgisi
inject edilebilir.
Kullanım
İmza Doğrulama (XAdES / PAdES / CAdES — tek API)
Sunucu içeriği inceleyerek format kararını kendisi verir; istemcinin XML / PDF / CMS ayrımı yapmasına gerek yoktur.
public class EFaturaDogrulama(IDssVerifierClient verifier)
{
public async Task<bool> EFaturaImzasiGecerliMi(byte[] imzaliUblXml, CancellationToken ct = default)
{
var sonuc = await verifier.Signatures.VerifyAsync(imzaliUblXml, ct: ct);
// sonuc.Valid → bütünsel verdict (tüm imzaların AND'i)
// sonuc.Signatures → her bir imza için detay
// sonuc.Status → "VALID" / "INVALID" / "INDETERMINATE"
return sonuc.Valid;
}
}
COMPREHENSIVE Mod — Tam Sertifika Zinciri + Per-CA OCSP/CRL
Audit / compliance akışları için tam detayı çekin:
var sonuc = await verifier.Signatures.VerifyAsync(new VerifySignatureRequest
{
SignedDocument = imzaliPdf,
Level = VerificationLevel.COMPREHENSIVE
});
foreach (var imza in sonuc.Signatures)
{
Console.WriteLine($"Imzacı: {imza.SignerCertificate?.CommonName}");
Console.WriteLine($"Seviye: {imza.SignatureLevel}");
Console.WriteLine($"Qualification: {imza.QualificationDetails?.QualificationLevel}");
Console.WriteLine($"Zincir revocation: {imza.ChainRevocationStatus}");
foreach (var cert in imza.CertificateChain ?? new())
{
Console.WriteLine($" CN={cert.CommonName} revocation={cert.Revocation?.Status}");
}
}
Detached İmza (CAdES detached / external XAdES)
var sonuc = await verifier.Signatures.VerifyDetachedAsync(
signedDocument: detachedP7s, // sadece imza
originalDocument: orijinalDosya // hash karşılaştırması için
);
Per-Request Custom Header'lar (Korelasyon / x-log-*)
Upstream akıştan gelen korelasyon kimliklerini (request ID, tenant, kullanıcı, trace ID) DSS Verifier servisinin log/alarm akışına da geçirmek için VerifySignatureRequest.Headers ve VerifyTimestampRequest.Headers üzerinden custom HTTP header eklenir. Sunucu x-log-* prefix'li header'ları otomatik olarak MDC'ye taşır; bu header'lar:
- Doğrulama log satırlarına JSON olarak iliştirilir (
xlog={"x-log-id":"…","x-log-tenant":"…"}), - INVALID imza tespit edildiğinde webhook payload'una (
logHeadersalanı) düşer, - Webhook isteğine pass-through HTTP header olarak iletilir (receiver kendi log'larını eşleyebilsin),
- Slack alarm mesajına ayrı bir "Korelasyon (x-log-*)" bloğunda gösterilir.
Böylece kullanıcının başlattığı akış (örn. e-fatura kabul / red kararı), DSS Verifier loglarından geri izlenebilir.
public class EFaturaDogrulamaServisi(IDssVerifierClient verifier)
{
public async Task<VerificationResult> DogrulaAsync(
byte[] imzaliUblXml,
string istekId,
string tenantId,
string kullaniciId,
CancellationToken ct = default)
{
return await verifier.Signatures.VerifyAsync(new VerifySignatureRequest
{
SignedDocument = imzaliUblXml,
Level = VerificationLevel.COMPREHENSIVE,
Headers = new Dictionary<string, string>
{
["x-log-id"] = istekId,
["x-log-tenant"] = tenantId,
["x-log-user"] = kullaniciId,
["x-log-trace"] = System.Diagnostics.Activity.Current?.Id
?? Guid.NewGuid().ToString("N")
}
}, ct);
}
}
Header kuralları: İsimler küçük harfle eşlenir; değerler sunucuda max 512 char'a kırpılır ve CR/LF gibi kontrol karakterleri boşlukla değiştirilir (log injection koruması). Request başına en fazla 20
x-log-*header işlenir.Tüm tüketici isteklerinde sabit bir header iletmek istiyorsanız (örn.
X-Service-Name)Headersper-request yerineIHttpClientBuilder.ConfigureHttpClient(http => http.DefaultRequestHeaders.Add(...))zincirini kullanın — paket boyu sözleşmenizi tek noktada tutar.
Türkiye'ye Özgü Tanı Kodları (Suppression / Rejection)
Sunucu, DSS upstream'ın jenerik kararlarını Türkiye e-imza ekosistemine özgü kataloglu kodlarla zenginleştirir. Bu kodlar API kontratı olarak kararlıdır:
var sonuc = await verifier.Signatures.VerifyAsync(imzaliUblXml);
foreach (var imza in sonuc.Signatures)
{
// 1) Suppression — DSS INVALID dedi, biz VALID elevate ettik (override).
// İmza geçerli sayıldı, ama hangi tolerans uygulandı audit edilebilir.
foreach (var s in imza.AppliedSuppressions ?? new())
{
Console.WriteLine($"[SUPPRESSION] {s.Code} — {s.Title}");
Console.WriteLine($" Sebep: {s.Reason}");
Console.WriteLine($" Docs : {s.DocsUrl}");
}
// 2) Rejection — DSS INVALID dedi, biz de INVALID diyoruz, AMA neden
// invalid olduğunu Türkiye-spesifik bir tanı koduyla açıklıyoruz.
foreach (var r in imza.AppliedRejections ?? new())
{
Console.WriteLine($"[REJECTION] {r.Code} — {r.Title}");
Console.WriteLine($" Sebep: {r.Reason}");
Console.WriteLine($" Docs : {r.DocsUrl}");
}
}
Kararlı kod listesi:
MERSEL.Services.DssVerifier.Client.Models.Enums.SuppressionCodeveRejectionCodeenum'ları tüm yayınlanmış kodları içerir; yeni sürümlerde değer eklenir, mevcut kod renaming yapılmaz. Wire format kanonik kod stringiMDSS-…formatındadır (örn.MDSS-XADES-LEGACY-TR-TYPE-URI); enum ile dönüşüm içinSuppressionCodeExtensions.GetCode()/TryParse()yardımcılarını kullanın.
RFC 3161 Zaman Damgası Doğrulama (Standalone)
İmzanın içine gömülü zaman damgaları otomatik olarak VerifyAsync akışında doğrulanır ve SignatureInfo.TimestampInfo alanında raporlanır. Tek başına gelen .tsr dosyaları için:
// 1) Yalnız token doğrula (TSA sertifika zinciri kontrol edilir).
var ts = await verifier.Timestamps.VerifyAsync(tsrBytes);
// 2) Orijinal veri ile message imprint karşılaştırması da yap.
var tsWithData = await verifier.Timestamps.VerifyAsync(
timestampToken: tsrBytes,
originalData: orijinalBelge);
Console.WriteLine($"Geçerli mi: {tsWithData.Valid}");
Console.WriteLine($"TSA : {tsWithData.TsaName}");
Console.WriteLine($"Zaman : {tsWithData.TimestampTime:O}");
Console.WriteLine($"Algoritma : {tsWithData.DigestAlgorithm}");
Sağlık Kontrolü
var health = await verifier.Health.GetHealthAsync();
// health.Status → "UP" / "DOWN"
// health.Application → "mersel-dss-verify-api"
// health.Version → "0.5.1"
var info = await verifier.Health.GetInfoAsync();
// info.Features → ["XAdES Verification", "OCSP/CRL Revocation Check", ...]
Hata Yönetimi
Önemli ayrım: İmzanın geçersiz çıkması bir HTTP hatası değildir. Sunucu doğrulamayı başarıyla icra ettiği sürece HTTP 200 ile
VerificationResult.Valid = falsedöner; karar için bu alanı inceleyin.
Yalnız taşıma katmanı / sunucu hataları (4xx/5xx) için DssVerifierApiException fırlatılır. Sunucunun yapılandırılmış hata gövdesi (error + message) varsa ApiError üzerinden erişilir:
try
{
var sonuc = await verifier.Signatures.VerifyAsync(imzaliBelge);
if (!sonuc.Valid)
{
// İmza fiilen geçersiz — exception değil.
foreach (var hata in sonuc.Errors) Console.Error.WriteLine($" - {hata}");
foreach (var s in sonuc.Signatures)
foreach (var r in s.AppliedRejections ?? new())
Console.Error.WriteLine($" - [{r.Code}] {r.Reason}");
}
}
catch (DssVerifierApiException ex)
{
// Sunucu hatası (örn. parse failure, 500).
Console.Error.WriteLine($"[{(int)ex.StatusCode}] {ex.ApiError?.Error}: {ex.ApiError?.Message}");
}
Polly / Retry / Logging
Paket altta Microsoft.Extensions.Http ve IHttpClientFactory üzerinde çalışır; standart retry/policy/logging genişletmeleri için kayıt sonrası IHttpClientBuilder'a kolayca eklenir:
builder.Services.AddDssVerifierClient(builder.Configuration);
builder.Services.AddHttpClient(DssVerifierClientOptions.HttpClientName)
.AddPolicyHandler(Policy<HttpResponseMessage>
.Handle<HttpRequestException>()
.OrResult(r => (int)r.StatusCode >= 500)
.WaitAndRetryAsync(3, attempt => TimeSpan.FromSeconds(Math.Pow(2, attempt))));
SIMPLE vs COMPREHENSIVE — Hangisini Kullanmalıyım?
| Senaryo | Önerilen Mod | Neden? |
|---|---|---|
| ApplicationResponse / yüksek hacimli akış | SIMPLE |
Tek istek başına milisaniyeleri kurtarır; verdict + zincir özet sinyali yeterli. |
| Mali müşavir / denetim arayüzü | COMPREHENSIVE |
Her CA için OCSP/CRL detayı + qualification (QES/AdES/QC) gösterimi gerek. |
| Otomatik karar (kabul/red) sistemleri | SIMPLE |
Valid + ChainRevocationStatus + AppliedRejections karar için yeterli payload. |
| Adli inceleme / chain-of-custody raporu | COMPREHENSIVE |
ValidationDetails, AppliedSuppressions.Evidence ve tam zincir audit için gerek. |
Gereksinimler
| Çalışma Ortamı | Desteklenen Sürüm |
|---|---|
| .NET (modern) | net8.0 (LTS) — özel optimize asset |
| .NET 5 / 6 / 7 / 9 | netstandard2.0 üzerinden |
| .NET Core | 2.0, 2.1, 2.2, 3.0, 3.1 |
| .NET Framework (Windows) | 4.6.1, 4.6.2, 4.7.x, 4.8, 4.8.1 |
| Mono | 5.4+ |
| Xamarin (iOS / Android / Mac) | tüm güncel SDK'lar |
| Unity (IL2CPP / Mono backend) | 2018.1+ |
- Çalışan bir mersel-dss-verifier-api-java mikroservisi (varsayılan port:
8086)
Eski .NET Framework için not:
System.Net.Http.HttpClient4.5.2+ ile gelir; ekstra paket gerekmez.appsettings.json+ DI senaryosu için klasik .NET Framework projelerindeMicrosoft.Extensions.HostingveyaMicrosoft.Extensions.DependencyInjection+Microsoft.Extensions.Configuration.Jsonpaketlerini eklemeniz yeterli — istemci SDK'sı kendi bağımlılıklarını (Microsoft.Extensions.Http8.0.x) zaten getirir.
Bağlantılar
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. 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 was computed. 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 was computed. 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. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- Microsoft.Extensions.Configuration.Abstractions (>= 8.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.2)
- Microsoft.Extensions.Http (>= 8.0.1)
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.2)
- Microsoft.Extensions.Options (>= 8.0.2)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 8.0.0)
- System.Text.Json (>= 8.0.5)
-
net8.0
- Microsoft.Extensions.Configuration.Abstractions (>= 8.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.2)
- Microsoft.Extensions.Http (>= 8.0.1)
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.2)
- Microsoft.Extensions.Options (>= 8.0.2)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 8.0.0)
- System.Text.Json (>= 8.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.