Skip to content

feat(payments): add bank provider port and sandbox adapter - #224

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

feat(payments): add bank provider port and sandbox adapter#224
tiana-code merged 1 commit into
mainfrom
feat/E-02-payments-bank-provider

Conversation

@tiana-code

Copy link
Copy Markdown
Owner

What

Fifth slice of E-02. A clean-room BankProvider plug-in port (mirrors the #174 RuleSynthesizer pattern) plus a deterministic in-tree sandbox, so payment orchestration (#213) can route to a bank seam with no real provider.

  • Port (com.fincore.payments.application.bank, pure Kotlin, no Spring): BankProvider.submit(BankPaymentRequest): BankSubmissionResult. BankPaymentRequest(paymentId, amount: Money, reference) validates non-blank; BankSubmissionResult is a sealed Accepted(providerReference) / Rejected(reason); BankProviderException carries technical/transient failure. A bank decision is a result, a transport failure is an exception (never conflated). Accepted = accepted-for-processing, not settled (settlement is async, F-02.7 Inbound webhook handler (HMAC verify + dedup) #214).
  • Sandbox (infrastructure.bank): SandboxBankProvider, @ConditionalOnProperty(...sandbox.enabled, matchIfMissing=false) so it is off by default and cannot auto-activate. Deterministic: a reference carrying the reject marker yields Rejected, otherwise Accepted("sbx-<paymentId>"). No randomness, no clock, no business threshold.
  • Unit tests: port contract (interface-only reflection + a fake impl, bridge/synthetic-filtered) and sandbox accept/reject/determinism.

OSS boundary (§5.3): generic seam + fake only. No real bank/provider/partner name, no maritime, no business value. Real adapters are private.

Gates

Local (-x integrationTest): :services:payments:{test,detekt,detektTest,spotlessCheck,assemble,compileIntegrationTestKotlin} green. critic GO, security-auditor PASS (§5.3 clean-room verified), evaluator 0.93.

Closes #212

Add a generic, interface-only BankProvider plug-in port: submit takes a bank
payment request and returns a sealed accept/reject result, with technical
failures surfaced as an exception so a bank decision is never confused with a
transport error. Add a deterministic sandbox adapter, off by default, that
accepts or rejects based on a reference marker so the lifecycle can be driven
end to end without any real bank. Real adapters live out of tree.

Closes #212
@tiana-code tiana-code added this to the v0.2.0 milestone Jun 18, 2026
@tiana-code
tiana-code merged commit 8eb5d58 into main Jun 18, 2026
8 checks passed
@tiana-code
tiana-code deleted the feat/E-02-payments-bank-provider branch June 18, 2026 13:29
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.5 BankProvider port + sandbox adapter

1 participant