Skip to content

feat(payments): orchestrate screening and bank submission - #225

Merged
tiana-code merged 1 commit into
mainfrom
feat/E-02-payments-orchestration
Jun 18, 2026
Merged

feat(payments): orchestrate screening and bank submission#225
tiana-code merged 1 commit into
mainfrom
feat/E-02-payments-orchestration

Conversation

@tiana-code

Copy link
Copy Markdown
Owner

What

Sixth slice of E-02. PaymentOrchestrator drives an initiated payment through in-process Decision-Engine screening and then BankProvider submission, wiring #211 (service) + #212 (bank port) + the embedded #175 decision-engine library.

  • Orchestration (PaymentOrchestrator, NOT @Transactional): screen (INITIATED -> SCREENING, one short tx) -> evaluate the configured rule in-process -> on Approve call BankProvider.submit outside any transaction -> Accepted -> SUBMITTED (markSubmitted, emits PaymentScreened, stores provider_reference), Rejected -> FAILED (PaymentFailed); Decline -> FAILED without calling the bank.
  • No external call in a transaction (§8.10): the orchestrator is non-transactional; submit runs between two separate-bean @Transactional PaymentService transitions. A BankProviderException (transient) propagates and leaves the payment in SCREENING for the retry job (F-02.8 Scheduled payment retry job #215), never a wrong terminal outcome.
  • Screening (ScreeningEvaluator): embeds com.fincore:decision-engine (RuleParser + RuleEvaluator); the rule is @ConfigurationProperties parsed fail-closed at startup (default approve-all, generic, no business threshold); EvaluationInput from amount/currency/reference.
  • New @Transactional screen/markSubmitted/markFailed on PaymentService (domain transitionTo + persist + outbox emit). New nullable payments.provider_reference column (producer for F-02.7 Inbound webhook handler (HMAC verify + dedup) #214 webhook correlation). @EnableConfigurationProperties on a PaymentsConfig.

Event placement follows the 5-event taxonomy (no PaymentSubmitted exists): PaymentScreened on the approved+submitted path, PaymentFailed on failure, nothing on the bare SCREENING transition.

Gates

Local (-x integrationTest): :services:payments:{test,detekt,detektTest,spotlessCheck,assemble,compileIntegrationTestKotlin} green. critic GO (C-1 bank-exception-stays-SCREENING + H-1 reentrancy applied), security-auditor PASS (§8.10 + §5.3 verified), evaluator 0.875 (independently confirmed the event placement is correct for the taxonomy). Full INITIATED->SUBMITTED lifecycle IT is #217.

Closes #213

Add PaymentOrchestrator that drives an initiated payment through in-process
decision-engine screening and then bank submission. The orchestrator is not
transactional: it screens the payment to SCREENING in one short transaction,
evaluates the configured rule with the embedded engine, and on approval calls
the bank provider outside any transaction, then settles the result (SUBMITTED
on accept, FAILED on reject) in another short transaction; a declined screening
fails the payment without calling the bank. A technical bank failure propagates
and leaves the payment in SCREENING for the retry job to re-attempt.

The screening rule is generic configuration parsed fail-closed at startup
(default approve-all), so an invalid rule fails startup rather than silently
approving. The bank's provider reference is persisted for later webhook
correlation.

Closes #213
@tiana-code tiana-code added this to the v0.2.0 milestone Jun 18, 2026
@tiana-code
tiana-code merged commit 1d77c89 into main Jun 18, 2026
8 checks passed
@tiana-code
tiana-code deleted the feat/E-02-payments-orchestration branch June 18, 2026 14:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

F-02.6 Payment orchestration + Decision Engine screening

1 participant