apps/batch — Hangfire İşçi
Bankayla konuşan tek uygulama. Her tip → görev + metot metot ne yaptığı + bağlantılar. Türkçe wire DTO'ları yalnız Integration/Ohvps altında (anti-corruption).
Worker (host + iç uçlar)
Program.csFinevoConnect.Yos.Batch.WorkerWorker host; Serilog+Hangfire+DI; 10 recurring job kaydı (8 job sınıfı; PeriodicResourceRefreshJob balance/transaction/card için 3×); JWS/mTLS bayrak boot-gate (fail-closed).
RecurringJob.AddOrUpdate ×10 | sync-intent-consumer, periodic-{balance,transaction,card}-refresh, decoupled-gkd-poll, recurring-payment-execution, forward-dated-status-sync, consent-timeout-sweep, event-subscription-ensure, undelivered-events-poll — cron config sabitlerinden. |
OhvpsEventsControllerFinevoConnect.Yos.Batch.Worker/ControllersÖHVPS olay webhook'u (POST /api/v1/ohvps/events).
Receive() | JWS imza filtresinden geçer → IOhvpsEventParser.Parse → IOhvpsEventService.HandleEventAsync → 202. Gövde tampon + idempotency olay servisinde. |
LiveQueryControllerFinevoConnect.Yos.Batch.Worker/Controllersİç senkron canlı-sorgu ucu (POST /internal/live-query).
Execute(req) | X-Internal-Secret'i config secret ile FixedTimeEquals doğrular (yoksa/uymazsa 401); SetFromIntent(PsuInitiator.UserPresent) ile PSU=E bağlamı; ILiveQueryService.ExecuteAsync → LiveQueryResponse. |
Uygulama servisleri
ConnectionSyncServiceFinevoConnect.Yos.Batch.Application/SyncBir bağlantı için hesap/işlem/kart senkronu + kota + token yenileme.
RunInitialFetchAsync(id, reason) | Bağlantıyı çözer (token süresi dolduysa RefreshAsync); kota rezerve (AccountList/Balance); GetAccountsAsync → UpsertAccounts; SyncTransactions + SyncCards. |
RefreshBalanceAsync(id, reason) | TryReserveAsync(Balance); GetAccountsAsync (bakiye içerir) → UpsertAccounts; kota dolduysa QuotaExhausted döner. |
RefreshTransactionsAsync(id, reason, accountRef?) | TryReserveAsync(Transaction); hesap(lar) için işlem çeker (sayfalı) → upsert. |
RefreshCardsAsync(id, reason) | Kart izni kontrolü; kota; kart başlık + ekstre-tipi + detay + işlem tek geçişte upsert. |
TryReserveAsync(conn, kind, reason) | reason UserRequested VEYA EventTriggered ise (E/O) → (true,null) KOTASIZ. Autonomous(H) ise pencere bul/oluştur + TryConsumeSlot (atomik ExecuteUpdate); dolu ise (false,null). |
LiveQueryServiceFinevoConnect.Yos.Batch.Application/LiveQuerySenkron canlı-sorgu; kind → ConnectionSyncService (RefreshReason.UserRequested → E, kotasız).
ExecuteAsync(req) | Bağlantı yoksa/Connected değilse not_connected. SetGroupId(connection.GroupId). Kind eşleme: Accounts→RefreshBalance, AccountTransactions→RefreshTransactions(accountRef), Cards/CardDetail/CardTransactions→RefreshCards, ConnectionStatus→ConsentStatus handler'ı inline çalıştır. OhvpsIntegrationException→hhs_error. Outcome+AsOf döner. |
ConsentActivationServiceFinevoConnect.Yos.Batch.Application/ConsentRıza aktivasyonu (yetKod→token→Connected).
CompleteAuthorizationAsync(id, authCode?) | Connected/Pending değilse no-op. SetGroupId. authCode verildiyse (redirect) → MarkAuthorized + doğrudan ExchangeAuthorizationCode; yoksa (decoupled) → GetAuthorizationCode poll. Token'ı şifreleyip MarkConnected; TrySaveChanges (dup-key sessiz). |
OhvpsEventServiceFinevoConnect.Yos.Batch.Application/EventsGelen ÖHVPS olayı; YÖS-kod + idempotency + dispatch.
HandleEventAsync / HandleUndeliveredEventsAsync | YÖS kod eşleşmezse düşer; her olay için yaş penceresi + BuildEventId idempotency (InboundEventStore). |
dispatch (HandleOneAsync) | AyrikGkdBasarili→ActivateAsync, AyrikGkdBasarisiz→MarkFailedAsync, KaynakGuncellendi→HandleResourceUpdatedAsync, diğer→no-op. |
HandleResourceUpdatedAsync | kaynakTip: HesapBilgisiRizasi→ConsentStatusSync niyeti, Bakiye→BalanceRefresh(EventTriggered), KartBilgileri→CardRefresh(EventTriggered), diğer→no-op. |
⚠ ActivateAsync | ConsentType'a BAKMAZ — CompleteAuthorization + InitialFetch (hesap) yapar. Ödeme rızası ayrık-GKD olayında yanlış (bilinen açık). |
Niyet işleyicileri
SyncIntentConsumerJob, niyet Kind'ine göre bunlardan birine dispatch eder.
ConsentCreateHandlerSync/HandlersYeni hesap-bilgisi rızası.
HandleAsync(intent) | Payload çöz; idempotency (zaten oluşturulduysa çık); kimliği çöz; CreateAccountConsentAsync → MarkConsentCreated. Kalıcı red (4xx)→MarkFailed; geçici (5xx)→fırlat (retry). |
AuthorizationCompleteHandler / InitialFetchHandlerSync/HandlersAktivasyon + ilk veri zinciri.
AuthorizationComplete.HandleAsync | payload.AuthorizationCode ile ConsentActivationService.CompleteAuthorizationAsync; bağlanınca InitialFetch niyeti zincirler. |
InitialFetch.HandleAsync | ConnectionSyncService.RunInitialFetchAsync (hesap+işlem+kart). |
BalanceRefresh / TransactionRefresh / CardRefreshHandlerSync/HandlersKaynak yenileme.
HandleAsync | İlgili Refresh*Async'i payload.Reason ile çağırır; QuotaExhausted dönerse SyncIntentRescheduleSignal fırlatır (kota penceresi sonuna ertelenir). |
ConsentStatusSyncHandlerSync/HandlersRıza durum senkronu.
HandleAsync | GetConsentStatusAsync → duruma göre MarkCancelled/MarkExpired/MarkFailed + izin reconcile; yetki-zaman-aşımı kontrolü. |
PaymentOrderSubmit / *AuthorizationCompleteHandler + PaymentInstructionCompletionFlowSync/HandlersÖdeme aileleri.
Submit.HandleAsync | CreatePaymentConsentAsync → order+connection MarkConsentCreated. |
AuthorizationComplete.HandleAsync | PaymentInstructionCompletionFlow.RunAsync. |
CompletionFlow.RunAsync | redirect'te callback-yetKod / decoupled'da GetAuthorizationCode poll → ExchangeAuthorizationCode → placeInstruction (odeme-emri) → attachInstruction(ref+token) → TrySaveChanges → commit'te triggerAsync. |
Hangfire job'ları
SyncIntentConsumerJobInfrastructure/JobsNiyet kuyruğunun kalbi.
DrainDueAsync | ListDueAsync(now) → her niyet için ProcessOneCoreAsync. |
ProcessOneCoreAsync | MarkDispatched; InboundEventStore.TryMarkConsumed (at-least-once guard); SetFromIntent(GroupId, ResolvePsuInitiator, requestId=intent.Id); handlersByKind[Kind].HandleAsync; MarkConsumed + FireChainedTriggers. |
ResolvePsuInitiator / MapReason | Refresh niyetlerinde payload.Reason → PSU: UserRequested→UserPresent(E), EventTriggered→HhsInitiated(O), Autonomous→Autonomous(H). |
hata yolları | SyncIntentRescheduleSignal→MarkRetryScheduled; dup-key→consumed; diğer→exponential backoff, max deneme→MarkDead. |
PeriodicResourceRefreshJobInfrastructure/JobsOtonom (H) periyodik yenileme.
RefreshBalances/Transactions/Cards → RunCoreAsync | SetFromIntent(Autonomous); ListConnectedPageAsync (keyset); süresi geçmemiş bağlı bağlantılara ConnectionSyncService.Refresh* (kota sayılır). |
ConsentTimeoutSweepJob / DecoupledGkdPollJobInfrastructure/JobsSüpürme + ayrık yoklama.
SweepAsync | Takılı onay pencerelerine ConsentStatusSync niyeti; süresi geçmiş rızalara MarkExpired. |
PollDueAsync | Bekleyen ayrık bağlantılara DecoupledGkdPoller.TryAdvanceAsync (⚠ ConsentType ayırmaz — ödeme için de InitialFetch). |
EventSubscriptionEnsureJob / UndeliveredEventsPollJobInfrastructure/JobsOlay aboneliği + yedek çekme.
EnsureAsync | Her etkin banka için abonelik yoksa Create, varsa Get/Update (auto-subscribe). |
PollAsync | Abone bankalardan ulaşamamış olayları çeker → HandleUndeliveredEventsAsync (anlık kanal koparsa kurtarır). |
RecurringPaymentExecutionJob / ForwardDatedPaymentStatusSyncJobInfrastructure/JobsÖdeme yürütme/durum.
ExecuteDueAsync (recurring) | Vadesi gelen düzenli ödemeleri yürütür (SyncInstructionAsync). |
ExecuteDueAsync (forward-dated) | Planlı ileri tarihli ödemelerin durumunu senkronlar. |
ÖHVPS entegrasyonu (DelegatingHandler zinciri: Auth→JWS→Log)
OhvpsAuthHandlerIntegration/Ohvps/PlumbingGiden başlık üretimi (DelegatingHandler).
SendAsync | X-ASPSP/X-TPP-Code; X-Request-ID (pinned ise ScopeToOperation=MD5(flowId|method|path) → retry-stabil + operasyon-tekil, yoksa yeni GUID); X-Group-ID (explicit||pinned); PSU-Initiated (E/H/O) + E'de PSU-Fraud-Check; Authorization Bearer + X-Access-Token. |
JwsSigningHandlerIntegration/Ohvps/Plumbingİmza (DelegatingHandler).
SendAsync | EnableJws ise POST/PUT/PATCH/DELETE gövdesini PS256 detached JWS imzalar (X-JWS-Signature); yanıtta imza yoksa/geçersizse HttpRequestException (downgrade reddi). |
OhvpsConsentClient / PaymentClient / TokenClient / EventClient (+Factory)Integration/Ohvps/*Slice client'lar; Türkçe wire DTO → domain (AutoMapper).
Consent: CreateAccountConsent / Cancel / GetConsentStatus | hesap-bilgisi-rizasi CRUD. |
Payment: CreatePaymentConsent / CreatePaymentOrder / Recurring / ForwardDated | ödeme aileleri rıza+emir. |
Token: GetAuthorizationCode / ExchangeAuthorizationCode / Refresh | yetKod poll + token değişim/yenileme. |
Event: Create/Get/Update Subscription / GetUndeliveredEvents | olay-abonelik + olay-dinleme (çekme). |