Providers
Building a provider
Connect a bank by implementing the provider contract
Adding a bank to Yapilayer means adding a module — never touching the core. The worked example throughout is providers/mock-bank/, the reference connector.
The contract
Three interfaces in providers/provider-sdk (ADR 0004):
public interface BankConnector {
ProviderDescriptor descriptor(); // id, name, country, capabilities
default Optional<AisProviderPort> aisPort() { … } // present iff AIS declared
default Optional<PisProviderPort> pisPort() { … } // present iff PIS declared
}AisProviderPort covers the consent → authorise → exchange → accounts/balances/transactions flow; PisProviderPort covers payment consent → authorise → submit → status. Two rules make connectors composable:
- Stateless — all consent/session state arrives through method parameters (
ProviderSession); never cache tokens in the connector. - Errors stay wrapped — throw
ProviderException; bank-specific error details must not leak upward.
Steps
- Create the module —
providers/your-bank/, add one line tosettings.gradle.kts, depend onprovider-sdk. Connectors need no Spring: the mock connector is plain Java + Jackson over the JDK HTTP client. - Implement the descriptor — declare only the capabilities the bank actually supports.
- Implement the ports — map the bank's API to the domain types (
Account,Balance,Transaction,PaymentStatus). If the bank distinguishes API host from customer-facing authorisation host, take both URLs (the mock connector'sapiBaseUrl/publicBaseUrlsplit). - Register it — add the connector to
ProvidersConfigurationinplatform-bootstrapwith its configuration properties. - Test it — the pattern in
ConnectorEndToEndTest: drive the real connector through complete AIS and PIS journeys against the bank's sandbox (or your own simulator).
Documentation expectations
Per PRODUCT_REQUIREMENTS.md §10, each real-bank connector ships with: the developer-portal URL and sandbox registration steps, certificate requirements, OAuth configuration, and known limitations. Put this in the module's README.