validationFailureLogMessage() was an abstract hook whose only job was to return a
cosmetically different warning string per provider ("Binance credential validation
failed", "Indexa Capital token validation failed", ...). It carried no functional
value and forced five one-line overrides.
Log a single structured message in the base with the provider enum value as
context, which is more useful for filtering than the free-text variants, and
remove the hook and its five overrides. Also restore the array-shape PHPDoc on
IndexaCapital's buildPendingAccounts() that the shared mixed signature dropped.
Only the warning-log text changes (now includes a "provider" key); the HTTP
responses are untouched. OpenBanking feature tests pass (304/304).
The Binance, Bitpanda, Coinbase, Indexa Capital, and Interactive Brokers connect
controllers each carried a ~60-line store() that was near-identical: subscription
gate, credential validation, Bank + BankingConnection creation, pending-account
mapping, and the onboarding/redirect branch. Any behavior change or bug fix had
to be repeated five times.
Introduce an abstract OpenBankingConnectController that owns the shared flow via a
template method (connect()), with per-provider extension points: provider(),
providerName(), bankLogo(), aspspCountry(), fetchProviderData(),
validationFailureLogMessage(), credentialErrorMessage(), buildPendingAccounts(),
and an optional emptyProviderDataMessage() guard (used by Interactive Brokers).
Each controller now declares only what varies.
Behavior is unchanged; the existing OpenBanking feature tests pass (304/304).
Wise is intentionally left as-is: it builds pending accounts before creating the
connection and has its own empty-result guard, so it does not fit this flow.