Kamu Kurumlarıyla Entegrasyon Projesi Nasıl Planlanır? KPS, e-Devlet, Sanal POS ve Dış Servisler
Mehmet Fatih İçin · · 10 dk okuma
Kurumsal bir yazılımda en çok sürprizi kendi kodunuz değil, kontrolünüzde olmayan sistemler çıkarır. Kimlik doğrulama için KPS, vatandaş girişi için e-Devlet, ödeme için banka sanal POS'u, meslek kuruluşu doğrulaması için TÜRSAB gibi servisler; her birinin kendi başvuru süreci, kendi test ortamı, kendi hata dili ve kendi bakım takvimi vardır. Bu yazıda, kamu tarafında yıllardır yürüttüğüm entegrasyonlardan çıkardığım planlama yaklaşımını süreç düzeyinde anlatıyorum. Amaç, kod yazmaya başlamadan önce sorulması gereken soruları netleştirmek. Güvenlik mimarisinin ve anahtar yönetiminin ayrıntılarına bilerek girmiyorum; onlar her kurumun kendi politikasına göre şekillenir.
1. Entegrasyon bir yazılım işi değil, önce bir yazışma işidir
Kamu servislerine bağlanmanın ilk adımı neredeyse hiçbir zaman teknik değildir. Çoğu serviste kurumunuzun resmi bir başvuru yapması, kullanım amacını gerekçelendirmesi ve bir protokol ya da taahhütname imzalaması gerekir. Bankalarda sanal POS için üye işyeri sözleşmesi, güvenlik değerlendirmesi ve bazen ödeme kuruluşu tarafında bir test onayı istenir. Bu süreçler haftalar, bazen aylar sürebilir.
Planlamada yaptığım ilk şey, takvimi bu yazışmaların etrafına kurmaktır. Geliştirme ekibi hazır olsa bile, test ortamı erişimi gelmeden yapılabilecek iş sınırlıdır. Bu yüzden proje planında en baştan şunları ayrı satırlar olarak tutarım:
- Başvuru ve izin: Hangi birim başvuracak, hangi belgeler gerekiyor, imza yetkisi kimde?
- Teknik doküman: Servis sağlayıcının güncel teknik dokümanı ve örnek mesajları elimizde mi? Eski bir sürümle mi çalışıyoruz?
- Test erişimi: Test ortamı var mı, yoksa doğrudan canlıda mı sınırlı deneme yapılıyor?
- Ağ erişimi: Servis belirli IP adreslerinden erişime mi izin veriyor, kurum içi ağdan dışarı çıkış için güvenlik duvarı talebi gerekiyor mu?
- Muhatap: Sorun çıktığında kime yazılacak, destek hangi kanaldan veriliyor?
Bu listenin her satırı ayrı bir gecikme kaynağıdır. Paralel yürütülmezse, kod bitmiş halde aylarca erişim beklemek çok olağan bir durumdur.
2. Kapsamı “kullanım senaryosu” üzerinden yazın
“KPS entegrasyonu yapılacak” cümlesi bir gereksinim değildir. Doğru soru şudur: Sistemin hangi anında, hangi kullanıcı için, hangi bilgiyi neden doğrulamamız gerekiyor? Örneğin bir biletleme sisteminde kimlik doğrulaması indirimli bilet hakkı için mi gerekiyor, yoksa kayıt sırasında kişinin gerçek olduğunu teyit etmek için mi? Bu ayrım; çağrının ne zaman yapılacağını, sonucun ne kadar süre geçerli sayılacağını ve hangi verinin saklanıp hangisinin saklanmayacağını belirler.
KVKK açısından da kapsam belirleyicidir. Veri minimizasyonu ilkesi gereği yalnızca amaca yetecek kadar veri istenmeli ve saklanmalıdır. Bir doğrulama servisinden dönen bilginin tamamını veritabanına yazmak yerine, çoğu zaman “doğrulandı / doğrulanmadı” sonucunu, zamanını ve hangi işlem için yapıldığını tutmak yeterlidir.
3. Dış servisi kendi sisteminizden yalıtın
Dış servis çağrılarını uygulamanın içine dağıtmak, ilk değişiklikte büyük bir bakım yükü doğurur. Her dış servis için tek bir istemci katmanı, yani bir “adaptör” yazarım. Uygulamanın geri kalanı servis sağlayıcının mesaj biçimini bilmez; yalnızca kendi tanımladığımız sade bir arayüzü görür.
public interface IKimlikDogrulama
{
Task<DogrulamaSonucu> DogrulaAsync(KimlikSorgusu sorgu, CancellationToken ct);
}
public record DogrulamaSonucu(bool Gecerli, string? HataKodu, bool TekrarDenenebilir);
Bu ayrımın üç faydası olur. Servis sağlayıcı mesaj biçimini değiştirdiğinde yalnızca adaptör değişir. Test ortamında gerçek servis yerine sahte (mock) bir uygulama kullanılabilir. Hata kodları da tek yerde sizin iş dilinize çevrilir; ekranda kullanıcıya gösterilecek mesaj, servisin teknik hata metni olmaktan çıkar.
4. Zaman aşımı ve hata senaryolarını baştan tasarlayın
Dış servislerin en sinsi davranışı yanıt vermemek değil, geç yanıt vermektir. Varsayılan zaman aşımı değerleri çoğu HTTP istemcisinde gereğinden uzundur ve bir servisin yavaşlaması, sizin uygulamanızdaki iş parçacıklarını ve bağlantıları tüketerek tüm sistemi yavaşlatabilir. Her dış çağrı için bilinçli bir zaman aşımı belirlerim ve bu değeri kullanıcının o ekranda ne kadar bekleyebileceğine göre seçerim.
.NET tarafında Microsoft.Extensions.Http.Resilience paketi bu işi standart hale getirir:
builder.Services.AddHttpClient<IKimlikDogrulama, KpsAdaptoru>()
.AddResilienceHandler("kps", b =>
{
b.AddTimeout(TimeSpan.FromSeconds(5));
b.AddRetry(new HttpRetryStrategyOptions
{
MaxRetryAttempts = 2,
BackoffType = DelayBackoffType.Exponential,
UseJitter = true
});
b.AddCircuitBreaker(new HttpCircuitBreakerStrategyOptions());
});
Burada önemli olan değerlerin kendisi değil, her birinin bir karar olmasıdır. Kaç kez tekrar denenecek? Tekrar denemek güvenli mi? Servis uzun süre yanıt vermezse “devre kesici” devreye girip kullanıcıya hızlıca anlamlı bir mesaj mı gösterilecek, yoksa işlem kuyruğa alınıp sonra mı tamamlanacak? Bu soruların cevabı her servis ve her senaryo için farklıdır ve iş birimiyle birlikte verilmelidir.
Hataları da sınıflandırmak gerekir. “Kimlik bilgisi uyuşmuyor” bir iş hatasıdır, tekrar denemek anlamsızdır. “Servis geçici olarak kullanılamıyor” teknik bir hatadır, makul aralıklarla tekrar denenebilir. Bu iki türü aynı şekilde ele almak ya gereksiz yükleme ya da yanlış ret sonucunu doğurur.
5. Ödeme ve durum değiştiren çağrılarda idempotency şart
Bir doğrulama sorgusunu iki kez çalıştırmak çoğu zaman zararsızdır. Ama ödeme almak, iade yapmak ya da dış sistemde kayıt oluşturmak gibi durum değiştiren işlemlerde aynı isteğin iki kez işlenmesi ciddi sorun yaratır. Ağ kesildiğinde istemci “istek gitti mi, gitmedi mi?” bilemez ve tekrar dener. Sunucu iki isteği ayrı işlem sayarsa müşteri iki kez ödeme yapmış olur.
Çözüm, her işleme sizin tarafınızda benzersiz bir işlem kimliği vermek ve bu kimliği hem dış servise iletmek hem de kendi veritabanınızda benzersiz indeksle korumaktır. Sanal POS entegrasyonlarında sipariş numarası bu rolü görür; aynı sipariş numarasıyla ikinci bir provizyon isteği banka tarafında da reddedilir. Kendi tarafınızda ise işlemi önce “başlatıldı” durumunda kaydedip, yanıt geldikten sonra “tamamlandı” ya da “başarısız” olarak güncellemek, yarım kalan işlemleri sonradan bulup mutabakat yapmayı mümkün kılar.
CREATE TABLE OdemeIslem (
IslemId UNIQUEIDENTIFIER NOT NULL PRIMARY KEY,
SiparisNo VARCHAR(40) NOT NULL UNIQUE,
Durum TINYINT NOT NULL, -- 0 başlatıldı, 1 tamamlandı, 2 başarısız
OlusturmaZ DATETIME2 NOT NULL DEFAULT SYSUTCDATETIME(),
GuncellemeZ DATETIME2 NULL
);
Gün sonunda bankanın işlem listesiyle kendi tablonuzu karşılaştıran bir mutabakat işi, “başlatıldı” durumunda kalmış kayıtları yakalar. Bu iş, entegrasyonun kendisi kadar önemlidir ve çoğu projede son ana bırakılır.
6. Loglama: her şeyi kaydedin, kişisel veriyi asla açık kaydetmeyin
Dış servislerle yaşanan sorunların çözümü neredeyse her zaman loglardan çıkar: hangi istek, ne zaman, hangi yanıtı aldı, ne kadar sürdü? Bu yüzden her dış çağrının isteğini, yanıtını, süresini ve korelasyon kimliğini kayıt altına almak gerekir. Ancak bu mesajların içinde T.C. kimlik numarası, ad-soyad, doğum tarihi, telefon ya da kart bilgisi gibi kişisel veriler bulunur.
KVKK açısından güvenli yaklaşım, loglama katmanında maskelemeyi otomatik yapmaktır. Geliştiricinin her log satırında maskelemeyi hatırlamasına güvenmek yerine, belirli alan adlarını yakalayıp maskeleyen merkezi bir filtre kullanırım:
static string Maskele(string deger) =>
deger.Length <= 4 ? "****" : new string('*', deger.Length - 4) + deger[^4..];
// "TCKimlikNo": "12345678901" -> "TCKimlikNo": "*******8901"
Kart numaraları için kural daha katıdır: kart verisi hiçbir koşulda log'a ya da veritabanına yazılmamalıdır. Sanal POS entegrasyonlarında 3D Secure ve bankanın ödeme sayfası kullanmak, kart verisinin sizin sistemlerinizden hiç geçmemesini sağlar ve ödeme güvenliği standartlarına uyum yükünü ciddi ölçüde azaltır.
Logların saklama süresi ve erişim yetkisi de bir karardır. Hata ayıklama için gereken süre ile KVKK'nın “gerektiği kadar saklama” ilkesi arasında makul bir denge kurulmalı, bu süre yazılı hale getirilmelidir.
7. Test ortamı yoksa kendi test ortamınızı kurun
Her servis sağlayıcı gerçekçi bir test ortamı sunmaz. Bazılarında test ortamı sürekli kapalıdır, bazılarında yalnızca birkaç sabit test verisi çalışır. Bu durumda adaptör katmanının faydası tekrar ortaya çıkar: servisin davranışını taklit eden bir sahte sunucu yazmak, hem otomatik testleri hem de arayüz geliştirmesini dış servisten bağımsız hale getirir.
Sahte sunucuda yalnızca başarılı senaryoyu değil, en az şunları da canlandırırım: geçersiz veri yanıtı, zaman aşımı, bozuk ya da eksik yanıt, servisin geçici olarak kapalı olması ve beklenmeyen bir hata kodu. Canlıda karşılaşılacak sorunların çoğu bu beş senaryodan biridir.
8. Sözleşme ve SLA: neyi garanti edebilirsiniz?
Kamu servislerinin çoğu bir hizmet seviyesi taahhüdü vermez; bakım çalışmaları önceden duyurulmayabilir. Bu durum, sizin kendi kullanıcılarınıza verdiğiniz sözü doğrudan etkiler. Sisteminizin bir dış servise bağımlı olan her işlevi için şu soruyu yanıtlamak gerekir: Bu servis bir saat erişilemezse ne olacak?
Bazı işlevler bekleyebilir; işlem kuyruğa alınır ve servis geri geldiğinde tamamlanır. Bazıları alternatif bir yolla sürdürülebilir. Bazılarında ise kullanıcıya dürüst bir mesaj göstermekten başka seçenek yoktur. Bu kararları önceden vermek, kriz anında doğaçlama yapmaktan çok daha iyidir. Bir yüklenici olarak çalışıyorsanız, kendi sözleşmenizde dış servislerin erişilebilirliğinin sizin taahhüdünüzün dışında olduğunu açıkça yazmak da önemlidir.
9. İzleme: sorunu kullanıcıdan önce görün
Canlıya geçtikten sonra dış servislerin sağlığını izlemek gerekir. Her servis için başarı oranı, ortalama yanıt süresi ve hata türlerinin dağılımı izlenmeli; olağan dışı bir değişiklikte ilgili kişiye haber verilmelidir. Sessizce bozulan bir entegrasyonu ilk fark edenin şikâyet eden kullanıcı olması, en kötü senaryodur.
10. Canlıya geçiş kontrol listesi
- Canlı ortam erişimi, IP izinleri ve güvenlik duvarı kuralları test edildi mi?
- Canlı ortamın uç noktaları ve kimlik bilgileri yapılandırmada mı, kodun içinde değil mi?
- Zaman aşımı, tekrar deneme ve devre kesici değerleri her servis için belirlendi mi?
- Durum değiştiren her çağrıda benzersiz işlem kimliği ve idempotency var mı?
- Loglarda kişisel veri maskeleniyor mu, kart verisi hiçbir yere yazılmıyor mu?
- Mutabakat işi çalışıyor ve yarım kalan işlemleri raporluyor mu?
- Servis erişilemezse kullanıcının göreceği mesajlar hazır mı?
- İzleme ve uyarılar devrede mi, uyarı kime gidiyor?
- Servis sağlayıcının destek iletişim bilgileri ekipte biliniyor mu?
- Geri dönüş planı var mı: entegrasyon sorun çıkarırsa eski akışa nasıl dönülür?
Kısaca
Kamu entegrasyonlarında başarı, kodun zarafetinden çok hazırlığın kalitesinden gelir. İzin sürecini erkenden başlatın, dış servisi kendi sisteminizden yalıtın, hata ve zaman aşımı senaryolarını önceden tasarlayın, durum değiştiren her çağrıyı idempotent yapın ve kişisel veriyi loglama katmanında otomatik maskeleyin. Bu ilkelerin gerçek sistemlerde nasıl uygulandığını merkezi e-bilet ve gişe ile acente portalı vaka çalışmalarında görebilirsin.
Entegrasyon sırasında işine yarayabilecek araçlar: dönen yanıtları okumak için JSON biçimlendirici, token içeriğine bakmak için JWT çözücü, işlem kimliği üretmek için UUID oluşturucu ve zaman damgalarını okumak için Unix zaman damgası çevirici. Daha önce yazdığım .NET ile güvenli REST API tasarımı yazısı da bu konunun devamı niteliğinde. Bir entegrasyon projesi planlıyorsan teklif formundan yazabilirsin.