diff options
Diffstat (limited to 'libeufin')
-rw-r--r-- | libeufin/api-nexus.rst | 567 | ||||
-rw-r--r-- | libeufin/api-sandbox.rst | 261 | ||||
-rw-r--r-- | libeufin/architecture.rst | 58 | ||||
-rw-r--r-- | libeufin/bank-transport-ebics.rst | 55 | ||||
-rw-r--r-- | libeufin/banking-protocols.rst | 125 | ||||
-rw-r--r-- | libeufin/concepts.rst | 160 | ||||
-rw-r--r-- | libeufin/index.rst | 10 | ||||
-rw-r--r-- | libeufin/iso20022.rst | 215 | ||||
-rw-r--r-- | libeufin/sepa.rst | 24 | ||||
-rw-r--r-- | libeufin/transaction-identification.rst | 85 |
10 files changed, 1226 insertions, 334 deletions
diff --git a/libeufin/api-nexus.rst b/libeufin/api-nexus.rst index 745182cf..d58b43bd 100644 --- a/libeufin/api-nexus.rst +++ b/libeufin/api-nexus.rst @@ -1,187 +1,536 @@ Nexus API ########### +.. contents:: Table of Contents HTTP API ======== -Users Management ----------------- +Authentication +-------------- -Users are the entity that access accounts. They do not necessarily correspond -to the actual legal owner of an account. Their main purpose in the nexus is -access management. +Currently every request made to nexus must be authenticated using the *HTTP +basic auth* mechanism. -.. http:get:: <nexus>/users +Other authentication mechanisms (e.g. OpenID Connect) might +be supported in the future. - List users. +User Management +--------------- - **Required permission:** Administrator. +.. http:get:: {nexusBase}/user -.. http:post:: <nexus>/users + Get information about the current user (based on the authentication information + in this request). - Create a new user. + **Response:** - **Required permission:** Administrators. + .. ts:def:: GetUserResponse + interface UserResponse { -Bank Account Management ------------------------ + // User name + username: string; -.. http:get:: <nexus>/bank-accounts + // Is it a superuser? + superuser: boolean; + } - List bank accouts managed by nexus. +.. http:post:: {nexusBase}/users + Create a new user. Only a superuser can call this API. -.. http:post:: <nexus>/bank-accounts + **Request:** - List bank accouts managed by nexus. + The body is a `User` object. + **Response:** -.. http:get:: <nexus>/bank-accounts/{acctid}/history + :status 409 Conflict: Username is not available. - :query method: Method to query the bank transaction (cached, ebics, fints, ...) + **Details:** - Query the transaction history of an account via the specified method. + .. ts:def:: User + interface User { -.. http:get:: <nexus>/bank-accounts/{acctid}/payments + // User name + username: string; - List payments made with this bank account via nexus. + // Initial password + password: string; + } -.. http:post:: <nexus>/bank-accounts/{acctid}/payments - Initiate a payment. +.. http:get:: {nexusBase}/users + Return list of users. -Low-level EBICS API -------------------- +Bank Accounts +------------- -.. http:post:: <nexus>/ebics/subscribers/{id}/backup +The LibEuFin maintains a copy of the bank account transaction history and balance information, +manages payment initiations of the account and tracks the of payment initiations. + +.. http:get:: {nexusBase}/bank-accounts - Ask the server to export the three keys, protected with passphrase. + **Response:** - .. ts:def:: NexusEbicsBackupRequest - - interface NexusEbicsBackupRequest { - passphrase: string; - } + A list of `BankAccount` objects + that belong to the requester. + .. ts:def:: BankAccount + + interface BankAccount { + // mnemonic name identifying this bank account. + nexusBankAccountId: string; + // IBAN + iban: string; + // BIC + bic: string; + // Legal subject owning the account. + ownerName: string; + } - .. ts:def:: NexusEbicsBackupResponse +.. http:post:: {nexusBase}/bank-accounts/{acctid}/payment-initiations/{pmtid}/submit - interface NexusEbicsBackupResponse { - - // The three passphrase-protected private keys in the PKCS#8 format + Ask nexus to submit one prepare payment at the bank. + + :status 404 Not Found: the unique identifier **or** + the bank connection could not be found in the system + + +.. http:get:: {nexus}/bank-accounts/{my-acct}/payment-initiations/{uuid} + + Ask the status of payment ``$uuid``. + + **Response:** + + .. ts:def:: PaymentStatus + + interface PaymentStatus { + + // Payment unique identifier + uuid: string; + + // True for submitted payments + submitted: boolean; + + // Creditor IBAN + creditorIban: string; + + // Creditor BIC + creditorBic: string; + + // Creditor legal name + creditorName: string; + + // Amount + amount: string; + + // Subject + subject: string; + + // Date of submission (in dashed form YYYY-MM-DD) + submissionDate: string; + + // Date of preparation (in dashed form YYYY-MM-DD) + preparationDate: string; + } + +.. http:get:: {nexusBase}/bank-accounts/{my-acct}/payment-initiations + + Ask nexus the list of initiated payments. At this stage of the API, + **all** is returned: submitted and non submitted payments. + + **Response** + + .. ts:def:: InitiatedPayments + + interface InitiatedPayments { + + // list of all the initiated payments' UID. + initiatedPayments: PaymentStatus[]; + } + + +.. http:post:: {nexusBase}/bank-accounts/{my-acct}/payment-initiations + + Ask nexus to prepare instructions for a new payment. + Note that ``my-acct`` is the bank account that will be + **debited** after this operation. + + **Request:** + + .. ts:def:: PreparedPaymentRequest + + interface PreparedPaymentRequest { + // IBAN that will receive the payment. + iban: string; + // BIC hosting the IBAN. + bic: string; + // Legal subject that will receive the payment. + name: string; + // payment subject. + subject: string; + // amount, in the format CURRENCY:XX.YY + amount: string + } + + **Response:** + + .. ts:def:: PreparedPaymentResponse + + interface PreparedPaymentResponse { + + // Opaque identifier to be communicated when + // the user wants to submit the payment to the + // bank. + uuid: string; + } + +.. http:post:: {nexusBase}/bank-accounts/{acctid}/fetch-transactions + + Nexus will download bank transactions using the given connection. + + **Request:** + + .. ts:def:: CollectedTransaction + + interface CollectedTransaction { + // Optional field to specify the bank connection to + // use for such operation. + bankConnection?: string; + // dashed date (YYYY-MM-DD) of the earliest payment + // in the result. Optional, defaults to "earliest + // possible" date. + start: string; + // dashed date (YYYY-MM-DD) of the earliest payment + // in the result. Optional, defaults to "latest + // possible" date. + end: string; + } + +.. http:get:: {nexusBase}/bank-accounts/{acctid}/transactions + + Shows which transactions are stored locally at nexus. + + **Query parameters:** + + * **start** start (dashed YYYY-MM-DD) date of desired payments. + Optional, defaults to "earliest possible" date + * **end** end (dashed YYYY-MM-DD) date of desired payments. + Optional, defaults to "earliest possible" date + + + **Response:** A list of `Transaction` objects. + + .. ts:def:: Transaction + + interface Transaction { + // local bank account involved in the transaction. + account: string; + + // counterpart IBAN + counterpartIban: string; + + // counterpart BIC + counterpartBic: string; + + // counterpart holder name + counterpartName: string; + + // amount, in the format [-]CURRENCY:XX.YY, + // where the minus sign as prefix indicates + // a debit for the user's bank account. + amount: string; + + // Dashed date YYYY-MM(01-12)-DD(01-31) of the transaction. + date: string; + + // Payment subject. + subject: string; + } + + +Bank Connections +---------------- + +Bank connections connect the local LibEuFin bank account +to the real bank. + +.. http:post:: <nexus>/bank-connections + + Activate a new bank connection for the requesting user. - authBlob: string; // base64 - encBlob: string; // base64 - sigBlob: string; // base64 - hostID: string; - userID: string; - partnerID: string; - ebicsURL: string; - } + **Request:** + .. ts:def:: BankConnectionRestoreRequest -.. http:post:: <nexus>/ebics/subscribers/{id}/restoreBackup + interface BankConnectionRestoreRequest { + + source: "new" | "backup"; + + name: string; + + // Restore a previous connection. Take precedence + // over the 'new' field. + backup?: BankConnectionBackup; + + passphrase?: string; + + // Data to create a fresh bank connection without + // restoring any backup. + data?: BankConnectionNew; + } + + + .. ts:def:: BankConnectionNew + + interface BankConnectionNew { + + // This type is strictly dependent on + // the connection being created. For Ebics, + // it will contain the required fields (as strings): + // 'ebicsURL', 'userID', 'partnerID', 'hostID', and + // the optional 'systemID'. - Ask the server to restore the keys. Always creates a NEW - "{id}" account, and fails if it exists already. + // Other connection types, like 'local' (used for testing + // purposes skipping any interaction with the bank service) + // and 'fints' are all work in progress! + + } + + + .. ts:def:: BankConnectionBackup + + interface BankConnectionBackup { + + // The information needed in this type depend entirely + // on which connectionis being restored. + + } + + **Response:** + + :status 409 Conflict: The ``name`` field exists already for + the requesting user. - .. ts:def:: NexusEbicsRestoreBackupRequest +.. http:post:: {nexusBase}/bank-connections/delete-connection - interface NexusEbicsRestoreBackupRequest { + **Request:** + + .. ts:def:: BankConnectionDeletion + + interface BankConnectionDeletion { + // label of the bank connection to delete + bankConnectionId: string; + } + +.. http:get:: {nexusBase}/bank-connections + + List available bank connections. + + +.. http:get:: {nexusBase}/bank-connections/{connId} + + Get information about one bank connection. + + .. ts:def:: BankConnectionInfo - // passphrase to decrypt the keys - passphrase: string; + interface BankConnectionInfo { + bankConnectionId: string; + + bankConnectionType: string; + + // Is this bank connection ready, or + // are we waiting for the bank to activate + // the connection? + ready: boolean; + + // Did the user review the bank's keys? + bankKeysReviewed: boolean; + } + + +.. http:post:: {nexusBase}/bank-connections/{connId}/connect + + Initialize the connection by talking to the bank. - // The three passphrase-protected private keys in the PKCS#8 format - authBlob: string; // base64 - encBlob: string; // base64 - sigBlob: string; // base64 - hostID: string; - userID: string; - partnerID: string; - ebicsURL: string; - } +.. http:post:: {nexusBase}/bank-connections/{connId}/export-backup - .. ts:def:: NexusEbicsCreateSubscriber + Make a passphrase-encrypted backup of this connection. -.. http:post:: <nexus>/ebics/subscribers +.. http:post:: {nexusBase}/bank-connections/{connId}/fetch-accounts - Create a new subscriber. Create keys for the subscriber that - will be used in later operations. + Update accounts that are accessible via this bank connection. - .. ts:def:: NexusEbicsCreateSubscriber +.. http:get:: {nexusBase}/bank-connections/{connId}/accounts - interface NexusEbicsCreateSubscriber { - ebicsUrl: string; - hostID: string; - partnerID: string; - userID: string; - systemID: string? - } + List the bank accounts that this bank connection provides access to. + .. ts:def:: OfferedBankAccount -.. http:get:: <nexus>/ebics/subscribers + interface OfferedBankAccount { - List EBICS subscribers managed by nexus. + // Unique identifier for the offered account + offeredAccountId: string; + // IBAN of the offered account + iban: string; -.. http:get:: <nexus>/ebics/subscribers/{id} + // BIC of the account's financial institution + bic: string; - Get details about an EBICS subscriber. + // Account owner name + ownerName: string; -.. http:get:: <nexus>/ebics/subscriber/{id}/keyletter + // If the account has been imported, + // this field contains the ID of the + // Nexus bank account associated with it. + nexusBankAccountId: string | null; + } - Get a formatted letter (mark-down) to confirm keys via ordinary mail. +.. http:post:: {nexusBase}/bank-connections/{connId}/import-account -.. http:post:: <nexus>/ebics/subscriber/{id}/sendIni + Import a bank account provided by the connection into the Nexus. - Send INI message to the EBICS host. + If no Nexus bank account with the ID ``nexusBankAccountId`` exists, + a new one will be created, and it will have ``connId`` as the + default bank connection. -.. http:post:: <nexus>/ebics/subscriber/{id}/sendHia + If an existing Nexus bank account with the same ID already exists, + this connection will be added as an available connection for it. + This only succeeds if the bank account has the same IBAN. - Send HIA message to the EBICS host. + .. ts:def:: ImportBankAccount -.. http:get:: <nexus>/ebics/subscriber/{id}/sendHtd + interface ImportBankAccount { - Send HTD message to the EBICS host. + // Identifier for the bank account, as returned by /accounts + // of the bank connection. + offeredAccountId: string; -.. http:post:: <nexus>/ebics/subscriber/{id}/sync + // Nexus-local identifier for the bank account. + nexusBankAccountId: string; + } - Synchronize with the EBICS server. Sends the HPB message - and updates the bank's keys. +Facades +------- -.. http:post:: <nexus>/ebics/subscriber/{id}/sendEbicsOrder +.. http:get:: <nexus>/facades - Sends an arbitrary bank-technical EBICS order. Can be an upload - order or a download order. + List available facades. - .. ts:def:: NexusEbicsSendOrderRequest:: +.. http:post:: {nexus}/facades + + Create a new facade; it requires a `FacadeInfo` as the request's body. + +.. http:get:: {nexus}/facades/${fcid} + + Get details about a facade. + + .. ts:def:: FacadeInfo + + interface FacadeInfo { + // Name of the facade, same as the "fcid" parameter. + name: string; + + // Type of the facade. + // For example, "taler-wire-gateway". + type: string; + + // Name of the user that created the facade. + // Whenever the facade accesses a resource it is allowed to + // access, the creator must *also* have access to that resource. + creator: string; + + // Bank accounts that the facade has read/write + // access to. + bankAccountsRead: string[]; + bankAccountsWrite: string[]; + + // Bank connections that the facade has read/write + // access to. + bankConnectionsRead: string[]; + bankConnectionsWrite: string[]; + + // Facade-specific configuration details. + config: any; + } + + +Bank Connection Protocols +------------------------- + +.. http:get:: {nexus}/bank-connection-protocols + + List supported bank connection protocols. + +.. http:post:: {nexus}/bank-connection-protocols/ebics/test-host + + Check if the nexus can talk to an EBICS host. + This doesn't create a new connection in the database, + and is useful during setup when the user hasn't entered + the full details for the connection yet. + + .. ts:def:: EbicsHostTestRequest + + interface EbicsHostTestRequest { + ebicsBaseUrl: string; + ebicsHostId: string; + } + + +EBICS-specific APIs +------------------- + +The following endpoints are only available for EBICS bank connections. +They are namespaced under the ``/ebics/`` sub-resource. + +.. http:post:: {nexusBase}/bank-connections/{connection-name}/ebics/download/{msg} + + .. warning:: + + Use with care. Typically only necessary for testing and debugging. + + Perform an EBICS download transaction of type ``msg``. + This request will not affect any bank account or other state + in the nexus database. It will just make a request to the bank + and return the answer. + +.. http:post:: {nexusBase}/bank-connections/{connection-name}/ebics/upload/{msg} + + .. warning:: + + Use with care. Typically only necessary for testing and debugging. + + Perform an EBICS upload transaction of type ``msg``. + This request will not affect any bank account or other state + in the nexus database. It will just make a request to the bank + and return the answer. - interface NexusEbicsSendOrderRequest { - // Bank-technical order type, such as C54 (query transactions) - // or CCC (initiate payment) - orderType: string; - // Generic order parameters, such as a date range for querying - // an account's transaction history. - orderParams: OrderParams +The taler-wire-gateway facade +----------------------------- - // Body (XML, MT940 or whatever the bank server wants) - // of the order type, if it is an upload order - orderMessage: string; - } +The ``taler-wire-gateway`` facade has the following configuration: -.. http:post:: <nexus>/ebics/subscriber/{id}/ebicsOrders +.. ts:def:: TalerWireGatewayFacadeConfig + + interface TalerWireGatewayFacadeConfig { + // Bank account and connection that is + // abstracted over. + bankAccount: string; + bankConnection: string; - .. note:: + // Corresponds to whether we trust C52, C53 or C54 (SEPA ICT) + // for incoming transfers. + reserveTransferLevel: "statement" | "report" | "notification"; - This one should be implemented last and specified better! + // Time between incremental requests + intervalIncremental: string; - Return a list of previously sent ebics messages together with their status. - This allows retrying sending a message, if there was a crash during sending - the message. + // FIXME: maybe more scheduling parameters? + } diff --git a/libeufin/api-sandbox.rst b/libeufin/api-sandbox.rst index ee298d85..f75c76e0 100644 --- a/libeufin/api-sandbox.rst +++ b/libeufin/api-sandbox.rst @@ -1,189 +1,164 @@ + Sandbox API ########### -Entities +HTTP API ======== -Bank Account - ... +.. + Payments. -EBICS Host +.. http:post:: /admin/payments -EBICS Subscriber - ... + Adds a new payment to the book. Mainly used for testing + purposes. -EBICS Partner - ... + **Request:** + .. ts:def:: PaymentRequest + interface PaymentRequest { + + // IBAN that will receive the payment. + creditorIban: string; -HTTP API -======== + // IBAN that will send the payment. + debitorIban: string; + amount: string; + currency: string; -.. http:post:: /ebicsweb + // subject of the payment. + subject: string; + } - Submit an EBICS request to the sandbox. +.. + Host management. +.. http:post:: /admin/ebics/hosts + + Creates a new Ebics host. -.. http:post:: /admin/customers + **Request:** - Create a new customer. A customer identifies a human that - may own multiple bank accounts. + .. ts:def:: EbicsHostRequest - When creating a customer, one EBICS subscriber is automatically - created for the customer. + interface EbicsHostRequest { + + // Ebics version. + hostID: string; - In the future, we might add an API to create multiple additional subscribers for - a customer. + // Name of the host. + ebicsVersion: string; + } + - When creating a new customer, an ID will be assigned automatically. +.. http:get:: /admin/ebics/hosts + + Shows the list of all the hosts existing + in the system. - .. code-block:: tsref + **Response:** - interface CustomerCreationRequest { - // human-readable name for the customer - name: string; - } + .. ts:def:: EbicsHostResponse -.. http:get:: /admin/customers/:id + interface EbicsHostResponse { + + // shows the host IDs that are active in the system. + // The Ebics version *is* missing, but it's still available + // via the HEV message. + ebicsHosts: string[]; + } + - Get information about a customer. +.. + Subscriber management. - .. ts:def:: CustomerInfo +.. http:post:: /admin/ebics/subscribers - interface CustomerInfo { - ebicsInfo?: CustomerEbicsInfo; - finTsInfo?: CustomerFinTsInfo; - } + Creates a new Ebics subscriber. - .. ts:def:: CustomerEbicsInfo + **Request:** - interface CustomerEbicsInfo { - ebicsHostId: string; - ebicsParterId: string; - ebicsUserId: string; + .. ts:def:: SubscriberRequest - // Info for the customer's "main subscriber" - subscriberInitializationState: "NEW" | "PARTIALLY_INITIALIZED_INI" | "PARTIALLY_INITIALIZED_HIA" | "READY" | "INITIALIZED"; - } + interface SubscriberRequest { + + // hostID + hostID: string; - .. ts:def:: CustomerFinTsInfo - - // TODO + // userID + userID: string; -.. http:post:: /admin/customers/:id/ebics/keyletter + // partnerID + partnerID: string; - Accept the information from the customer's ("virtual") INI-Letter and HIA-Letter - and change the key's state as required. + // systemID + systemID: string; - .. code-block:: tsref + } + - interface KeyLetterRequest { +.. http:get:: /admin/ebics/subscribers - ini: { - // The user ID that participates in a EBICS subscriber. - userId: string; + Shows the list of all the subscribers existing + in the system. - // The customer ID specific to the bank (therefore not - // participating in a EBICS subscriber). - customerId: string; + **Response:** - // Human name of the user - name: string; + .. ts:def:: SubscribersResponse - // As per specification, this value is: - // "Date of processing of the corresponding EBICS order". DD.MM.YYYY format. - date: string; + interface SubscribersResponse { + + subscribers: Subscriber[] + } + + .. ts:def:: Subscriber - // As per specification, this value is: - // "Time of processing of the corresponding EBICS order". HH:MM:SS format. - time: string; + interface Subscriber { + + // userID + userID: string; - // Identification token of the bank. Not required to obey to any particular standard. - recipient: string; + // partnerID + partnerID: string; - // Electronic signature version. Admitted values: A005, A006. - version: string; + // hostID + hostID: string; - // Length in bits of the key exponent. - public_exponent_length: number; - // RSA key exponent in hexadecimaml notation. - public_exponent: string; + } - // Length in bits of the key modulus. - public_modulus_length: number; - // RSA key modulus in hexadecimaml notation. - public_modulus: string; +.. http:post:: /admin/ebics/bank-accounts - // RSA key hash. - // - // A005, A005 versions require hash type SHA-256. - hash: string; - } + Associates a new bank account to an existing subscriber. - hia: { - // The user ID that participates in a EBICS subscriber. - userId: string; - - // The customer ID specific to the bank (therefore not - // participating in a EBICS subscriber). - customerId: string; - - // Human name of the user - name: string; - - // As per specification, this value is: - // "Date of processing of the corresponding EBICS order". DD.MM.YYYY format. - date: string; - - // As per specification, this value is: - // "Time of processing of the corresponding EBICS order". HH:MM:SS format. - time: string; - - // Identification token of the bank. Not required to obey to any particular standard. - recipient: string; - - //////////////////////////////////////////////////// - // Identification and Authentication key details. // - //////////////////////////////////////////////////// - - // Identification and authentication signature version. - // Admitted value: X002. - ia_version: string; - - // length of the exponent, in bits. - ia_public_exponent_length: number; - // RSA key exponent in hexadecimaml notation. - ia_public_exponent: string; - - // length of the modulus, in bits. - ia_public_modulus_length: number; - // RSA key modulus in hexadecimaml notation. - ia_public_modulus: string; - - // SHA-256 hash of the identification and authentication key. - ia_hash: string; - - ///////////////////////////// - // Encryption key details. // - ///////////////////////////// - - // Encryption version. Admitted value: E002. - enc_version: string; - - // length of the exponent, in bits. - enc_public_exponent_length: number; - // RSA key exponent in hexadecimaml notation. - enc_public_exponent: string; - - // length of the modulus, in bits. - enc_public_modulus_length: number; - // RSA key modulus in hexadecimaml notation. - enc_public_modulus: string; - - // SHA-256 hash of the encryption key. - enc_hash: string; - } - } + **Request:** + + .. ts:def:: BankAccountRequest + + interface BankAccountRequest { + + // Ebics subscriber + subscriber: string; + + // IBAN + iban: string; + + // BIC + bic: string; + + // human name + name: string; + + // bank account label + label: string; + + } + +.. + Main EBICS service. + +.. http:post:: /ebicsweb + + Serves all the Ebics requests. diff --git a/libeufin/architecture.rst b/libeufin/architecture.rst deleted file mode 100644 index e5cad890..00000000 --- a/libeufin/architecture.rst +++ /dev/null @@ -1,58 +0,0 @@ -LibEuFin Architecture -##################### - -Sandbox -======= - -* the sandbox's EBICS API emulates the behavior of a real bank's EBICS - interface - -* *(Only in the future)*: FinTS API and other FinTech APIs - -* the sandbox's management API allows an administrator to: - - * create new **bank** accounts - * create new **EBICS subscriber** accounts - - * a subscriber has (optionally?) a SystemID (for technical subscribers), - a UserID and a PartnerID - * each bank account has a list of subscribers than can access it - - * delete accounts - * ... - -* the sandbox's "miscellaneous" API provides public functionality that is not covered - directly by EBICS, such as: - - * a way to get the transactions in form of a JSON message, to check if it matches the EBICS response - - * you could call it a "reference history" - - * publicly accessible key management functionality, for example for the EBICS INI process - - * this is the "electronic version" of sending an HIA/INI letter - -* things that we do **not** want to implement right now: - - * Distributed electronic signatures. For now, it is enough for every order - to be signed just by one authorized subscriber. - -Nexus -===== - -The Nexus takes JSON requests and translates them into API calls for the -respective real bank accounts (EBICS, FinTS, ...). It also stores the bank -transaction history to enable a linearlized view on the transaction history -with unique transaction identifier, which some of the underlying banking APIs -don't provide directly. - -``libeufin-nexus-httpd`` is the binary (or wrapper around the Java invocation) -that runs the HTTP service. - - -CLI Tools -========= - -The Sandbox and Nexus are only HTTP services. The CLI tools are used to -actually access them. - diff --git a/libeufin/bank-transport-ebics.rst b/libeufin/bank-transport-ebics.rst new file mode 100644 index 00000000..0d06f83b --- /dev/null +++ b/libeufin/bank-transport-ebics.rst @@ -0,0 +1,55 @@ +The EBICS Bank Transport +======================== + +An EBICS bank transport in LibEuFin conceptually corresponds +to the "EBICS Subscriber" in EBICS terminology. + + +Bank Transport Setup +-------------------- + +The following steps are required to set up an EBICS bank transport: + +1. The bank must set up the EBICS access for the user. + The bank will notify the user of the following parameters: + + * the URL of the EBICS server used by the bank + * the HostID of the bank within the EBICS server (sometimes one EBICS server hosts multiple banks) + * the PartnerID (typically identifies the owner of the bank account within the banking system) + * the UserID (typically identifies the person that accesses the bank account, can be different from the owner) + * the SystemID (optional and rarely used, basically a "sub-identity" of a subscriber when multiple technical + systems have access to the account via EBICS) + +2. The user enters the information from the list above in the setup dialog in the LibEuFin nexus (UI/CLI). + +3. The LibEuFin nexus generates cryptographic key material (3 RSA key pairs) + +5. The nexus sends the public keys electronically to the bank's EBICS server, together with the information + identifying the subscriber (PartnerID, UserID, SystemID). + +6. The user print a document that contains the public key and hashes for all three key pairs. + The user then signs this document sends it to the bank (physically/scanned). + +7. The bank receives the letter and verifies that the keys from the letter correspond + to the electronically sent keys. If they match, the bank sets the state of the + subscriber to "ready". + +8. The user now has to wait until the bank has set the EBICS subscriber state to "ready". + There is no in-band notification for this, but the Nexus can try downloading the bank's + cryptographic parameters. This will only succeed once the EBICS subscriber is set to "ready" + by the bank. + +9. The user should confirm the public keys of the bank received in the previous step. + Typically the bank gives the value of these public keys in an out-of-band channel. + +10. Now the user can finally use the EBICS bank transport. The first step after finishing + the setup should be to import the bank accounts accessible for this EBICS subscriber. + + +Alternative ways of setting up the EBICS bank transport are: + +* Importing from a backup. The backup contains metadata (EBICS URL, HostID, + UserId, ...) and the three passphrase-protected subscriber keys. +* Certificate-based setup (currently not supported by LibEuFin, only used in France) + + diff --git a/libeufin/banking-protocols.rst b/libeufin/banking-protocols.rst new file mode 100644 index 00000000..17dda0b9 --- /dev/null +++ b/libeufin/banking-protocols.rst @@ -0,0 +1,125 @@ +Banking Protocols +################# + +This page collects information we have about banking protocols available around +the world. + + +Open Financial Exchange (OFX) Direct Connect +============================================ + +`OFX <https://www.ofx.net/>`__ is widely used in the US. It defines a completely +custom protocol (based on HTTP) and data formats (**not** based on ISO20022) for banking. + + +Electronic Banking Internet Communication Standard (EBICS) +========================================================== + +EBICS is used primarily in Germany, France and Switzerland. Some banks (such as BNPParibas +with their `Global Ebics <https://cashmanagement.bnpparibas.com/our-solutions/solution/global-ebics>`__) +also allow EBICS access to accounts in other countries. + +EBICS is just a transfer layer for communicating with banks. Banks define what +messages they support. In practice, EBICS is very often used to transfer +ISO20022 messages. + +German banks that are part of the German Banking Industry Committee all must offer EBICS access. +Thus this protocol is a good choice for the German market. + + +FinTS / HBCI +============ + +German home-banking standard. FinTS is the successor of the Home Banking +Computer Interface (HBCI), but older versions of FinTS are often still called +HBCI. + +The current version, FinTS 4.0, is not widely supported by banks yet. Starting with FinTS, +XML is used as a data format. Previous versions used a custom text/binary format. + +Only some banks allow authentication based on key pairs. +Due to different interpretation of PSD2, other banks now only allow authentication +methods that require interaction from the customer (SCA / Strong Customer Authentication). + +Payloads these days can be ISO20022 messages. + +Examples: + * `GLS <https://www.gls.de/geschaefts-firmenkunden/zahlungsverkehr/onlinebankingverfahren-und-programme/daten-zum-onlinebanking/>`__ + + +PSD2 +==== + +PSD2 is not a technical standard, but high-level legal requirements on (amongst other things) APIs +that banks have to offer. + +There are many implementations of PSD2 APIs. The `Berlin Group <https://www.berlin-group.org/>`__ +provides a framework that somewhat standardizes technical details, but the use of this standard +is by no means necessary. + +Unfortunately, it focuses on *other* parties accessing *your* bank account. It +does not give customers access to their own bank account. Customers can manage +third party access they give to their bank account in their online banking +system. That mechanism is conceptually similar to OAuth2. In fact, some +implementations of PSD2 even use OAuth2 directly. + +PSD2 APIs usually use JSON as a data format. Often the schema and terminology is "inspired" by ISO20022 +messages, but no actual ISO20022 XML message formats are used. + +PSD2 requires two main services to be available via an API: + +* AIS (Account Information Service). +* PIS (Payment Initiation Service). + +Together, they're often called XS2A ("access to account"). + +An entity that wants to use AIS has to be registered with the financial +oversight authority in its country (BAFIN in Germany). PIS has even stronger +legal prerequisites. + +On a technical level, using PSD2 APIs usually requires having an `EIDAS <https://en.wikipedia.org/wiki/EIDAS>`__ certificate. + +Examples (bank offerings): + * `Sparkasse <https://xs2a.sparkassen-hub.com/home>`__ (Berlin Group based) + * `Deutsche Bank <https://developer.db.com/products/psd2>`__ + +Examples (standards): + * `STET PSD2 API <https://www.stet.eu/en/psd2/>`__ + * `Berlin Group NextGenPSD2 <https://www.berlin-group.org/nextgenpsd2-downloads>`__ + + + +Bank-Proprietary APIs +===================== + +Some banks offer completely custom APIs to access services of the bank. These often include services +not available via more standardized APIs, such as account creation. + +Often banks frame PSD2 as just another API available in their portfolio of API offerings. + +Examples: + +* `Deutsche Bank <https://developer.db.com/products>`__ +* `ING Group <https://developer.ing.com/api-marketplace/marketplace>`__ +* `Revolut <https://revolut-engineering.github.io/api-docs/business-api/>`__ +* `PayPal <https://developer.paypal.com/classic-home/>`__ + + +Open Bank Project +================= + +The `Open Bank Project <https://www.openbankproject.com/>`__ provides a free software implementation of +banking middleware that supports various APIs, including PSD2-compatible APIs (based on Berlin Group). + +API Docs: https://github.com/OpenBankProject/OBP-API/wiki/Open-Bank-Project-Architecture + + +UK Open Banking +=============== + +Open Banking is the (quite confusing!) name of a UK-based open banking initiative. + +What's nice about Open Banking is that their APIs are really close to ISO 20022, unlike many +similar HTTP+JSON APIs. + +https://openbanking.atlassian.net/wiki/spaces/DZ/pages/16385802/Specifications diff --git a/libeufin/concepts.rst b/libeufin/concepts.rst new file mode 100644 index 00000000..da48d7f8 --- /dev/null +++ b/libeufin/concepts.rst @@ -0,0 +1,160 @@ +################### +Conceptual Overview +################### + + +What is LibEuFin +================ + +The goal of LibEuFin is to make the development and testing of +FinTech applications easier. It hides implementation details +of complex legacy banking APIs behind a simple interface. + +LibEuFin Nexus and Sandbox +-------------------------- + +LibEuFin has two main components: + +1. The LibEuFin nexus receives banking-related requests in a LibEuFin-specific + format via an HTTP API. It then translates those requests into interactions + with other banking APIs, abstracting away different underlying protocols and + hiding the complexity of the legacy protocols used by some banks. + +2. The LibEuFin sandbox implements the server side of protocols + that banks speak. It also emulates a *very*, *very* simple + core banking system to manage accounts and their balance. + The main use case for the sandbox is testing LibEuFin itself, + as well as applications developed with LibEuFin. + The sandbox has a JSON API to set it up for tests (creating bank + hosts, bank accounts, fake transactions). + + +High-Level Concepts +=================== + +Nexus Users +----------- + +The concept of a *nexus user* is used to implement access control to the +operations that the nexus provides. + +A user has a login name and a (salted, hashed) password. (Other authentication +methods could be added in the future.) + +A nexus user can be marked as *superuser*. All permission checks are skipped +for superusers. Only superusers are allowed to create/modify other users. + +Bank Accounts +------------- + +A bank account is the local representation of some bank account. +The information stored about it includes: + +* Local alias ("nickname") of the bank account +* Account identification (IBAN / BIC / account holder) +* A local mirror of the bank transaction history +* Payment requests, i.e. payments that have been locally requested, together + with their state (sent or not sent, acknowledged in bank statement or not). +* Error reports (e.g. failed payment requests, bank statement items that were not understood + by LibEuFin) +* A default bank connection (if configured) that is used by default + for operations on the account +* Other enabled bank connections + +Examples: + +.. code:: none + + # Download latest transactions via the default bank connection and store them locally + curl -XPOST $AUTHEADER https://example1.libeufin.tech/bank-accounts/my-acct/collect-transactions + +Bank Connections +---------------- + +Bank connections connect the local LibEuFin bank account to the real bank. +The bank connection includes the following data: + +* Local alias ("nickname") of the bank connection +* the type of connection, i.e. the protocol used (EBICS, FinTS, loopback, sandbox) +* protocol configuration (hostname, port, protocol sub-version/flags) +* credentials to use the connection (e.g. password, EBICS subscriber keys) + +Bank connections provide the following actions: + +* Initial setup of the connection + +* Execute protocol-specific actions (e.g. EBICS: C53, C52, CCT, CRZ) + + * These actions do not have any effect on the LibEuFin local bank account. + To persist changes to the local bank account (transaction history, payment request status), + the bank connection must be invoked via the bank account. + +* Import bank accounts + + * Some bank connection protocols allow LibEuFin to query a list of bank + accounts that the connection has access to. This makes setup easier, + as the user doesn't have to create the local bank account manually. + +Examples: + +.. code:: none + + # Manually request the inter-day account report via the EBICS C52 order + curl -XPOST $AUTHEADER https://example1.libeufin.tech/bank-connections/my-ebics-testacct/send-c52 + + # Download available bank accounts that can be accessed through this connection, + # according to the bank server (with EBICS, does a HTD request). + # For each of them, create a bank account resource in LibEuFin. + curl -XPOST $AUTHEADER https://example1.libeufin.tech/bank-connection/my-ebics-testacct/import-accounts + +Facades +------- + +Facades allow extra domain-specific functionality to be implemented on top of users, bank accounts +and bank connections. Facades store the following information: + +* Local name of the facade +* Facade type and options specific to the type +* Associated bank accounts and bank connections that can be accessed by the layer +* Internal tables used by the facade (i.e. facades are stateful) + +The only facade currently supported by LibEuFin is the "Taler Wire Gateway API" layer. +It provides a filtered view on the transaction history, a more restricted API to create payment +requests, and a mechanism to create a counter-transaction for incoming transaction that do +not conform to a certain format. + +Examples: + +.. code:: none + + # Request the Taler-specific history through the facade + curl $AUTHEADER https://example1.libeufin.tech/facades/my-taler-wire-gw/api/history/incoming + +Access Control +============== + +The goal of access control in LibEuFin is to allow the following scenarios: + +* The Nexus can be used by multiple clients for different bank accounts/connections + and these users can't access each other's bank accounts +* For monitoring / dashboard (e.g. Taler rejected transactions, blacklists), + some users should only be able to have read-only access. + +It is currently not planned to have more fine-grained permissions, such as +spending limits or more fine-grained read/write permissions. + +Users can be normal users or superusers. Permission checks do not apply to superusers, +and only superusers can create other users. + +Each top-level object (bank account, bank connection, facade) has a list of +nexus users with write access, and a list of users with read access. + +When using a bank connection through a bank account, permission checks must +succeed for both the bank account and the bank connection + +This works differently for facades: A facade has a set of associated bank connections +and bank accounts it can access. Permissions on these associated objects +are checked when the facade is *created*. When invoking operations on the facade, +the nexus only checks if the current nexus user can access the facade and *not* the +underlying objects abstracted by the facade. + diff --git a/libeufin/index.rst b/libeufin/index.rst index 62af14b4..766410e2 100644 --- a/libeufin/index.rst +++ b/libeufin/index.rst @@ -6,8 +6,12 @@ LibEuFin is a project providing free software tooling for European FinTech. .. toctree:: :glob: - ebics - architecture - api-sandbox + concepts + bank-transport-ebics api-nexus + api-sandbox + ebics + sepa iso20022 + banking-protocols + transaction-identification diff --git a/libeufin/iso20022.rst b/libeufin/iso20022.rst index a7d90586..06d929c2 100644 --- a/libeufin/iso20022.rst +++ b/libeufin/iso20022.rst @@ -5,35 +5,208 @@ ISO 20022 is the standard that defines many XML messages for FinTech. It is very general, and often countries/orgs define subsets (TVS, technical validation subset) of the schema. +Documentation for message fields can be viewed at https://www.iso20022.org/standardsrepository -Cash Management (camt) -====================== +The primary syntax for ISO 20022 messages is XML. To avoid LibEuFin clients +having to deal with XML, we define a mapping from ISO 20022 messages into JSON. -camt.052: Bank to Customer Account Report ------------------------------------------ +The specifics of this mapping are: -* pending and booked transaction + * The JSON should be "idiomatic" and easy to process + * When possible, the highly nested structures of ISO 20022 should be flattened + * It must be possible round-trip between the LibEuFin JSON and ISO 20022 + XML messages. The mapping of message types is not 1-to-1, as some ISO 20022 messages are + very similar and can be mapped to the same JSON structure. + * JSON-mapped messages are not explicitly versioned. Instead, changes + are made in a backwards-compatible way, possibly preserving old versions + of message elements in the same schema. -Schema versions: -* GLS uses camt.052.001.02 +Why does LibEuFin not use ISO 20022? +==================================== -.. code-block:: none +While LibEuFin can ingest ISO 20022 messages (camt.05x, pain.002) and generate +them (pain.001), it does not use ISO 20022 in its API and internal data model. - + Document/BkToCstmrAcctRpt - ++ GroupHeader [1..1] - ++ Report [1..*] - +++ Account [1..1] - +++ Balance [1..*] - +++ Entry [1..*] - ++++ Amount [1..1] - ++++ Status [1..1] - ++++ EntryDetails [1..1] +Reasons for not using ISO 20022 directly are: +1. Impedence mismatch. ISO 20022 messages do not map well to query/response + APIs. +2. Cumbersome to use. Even when ISO 20022 messages are directly mapped + to JSON, they are difficult to use due to their verbosity. +3. Underspecification. Messages like camt.05x leave many "degrees of freedom" + when translating the underlying data into a message. +4. No interoperability. As a result of underspecification, different countries/organisations + define their own subset and interpretation rules for ISO 20022 messages. This can + lead to even contradictory usage rules. An example for this is how the Swiss and EPC + interpretations handle transaction amounts in the presence of multiple currencies. +5. Redundancy. ISO 20022 are redundant, and often mix aspects of the "presentation logic" + with the underlying data model. An example of this is the optional "summary" information + in camt.05x messages. -camt.053: Bank to Customer Statement ------------------------------------- +Instead of using ISO 20022 messages directly, LibEuFin leverages the standard in other ways: -* only booked transactions -* only for the last day (?) +* As the data exchange format with banks +* As a guideline for naming in data formats +* As a guideline for which concepts need to be understood by LibEuFin + + +Implementation notes for camt.05x +================================= + +Types of amounts in camt messages +--------------------------------- + +* Entry amount + + * ISO 20022: Mandatory, with debit/credit indicator. Indicates money + moving in/out of the account in the account's currency. + * LibEuFin: Same. + +* Entry transaction amount + + * ISO 20022: Optional, direction-less. Amount of money + moving between the debtor and creditor bank, may not be + in the account's currency (but the "native" currency between + the two banks). + * LibEuFin: Same. + +* Entry instructed amount + + * ISO 20022: Optional, direction-less. Amount of money specified in the + payment initiation message. Usually only specified when the amount is in a + different currency than the account currency. + * LibEuFin: Same. + +* Entry counter value amount + + * ISO 20022: Optional, direction-less. Amount in the account's + currency before charges. + * LibEuFin: Same. + +* Entry announced posting amount + + * (not used by LibEuFin) + +* EntryDetails amount + + * ISO 20022: Optional, with debit-credit indicator. Same as "Entry amount" + but for EntryDetails (= logical transactions). + * LibEuFin: Always present. In Swiss camt messages, the element is always + present. In German/Swedish/... camt, we take the "Entry amount" for + non-batch entries, whereas in batch entries we use the "EntryDetails + transaction amount" with the same debit credit indicator as the whole + entry, which by local rules is always in the bank account currency. + +* EntryDetails (transaction / instructed / counter value) amount + + * ISO 20022: Optional, direction-less. Same as "Entry ... amount" + but for EntryDetails (= logical transactions). + * Same. + +* EntryDetails announced posting amount + + * (not used by LibEuFin) + + +LibEuFin schema for account history +----------------------------------- + +FIXME: This is not complete yet. + +.. code-block:: typescript + + interface NexusTransactionsReponse { + entries: NexusAccountEntryItem[]; + } + + interface NexusAccountEntryItem { + nexusEntryId: string; + + // Serial number that will increase with each update + // to the entry. + nexusStatusSequenceId: number; + + entry: AccountEntryItem; + } + + interface AccountEntryItem { + + // At least one of entryId or accountServicerRef + // must be non-null + entryId?: string; + accountServicerRef?: string; + + creditDebitIndicator: "credit" | "debit"; + amount: string; + currency: string; + instructedAmountDetails?: { + amount: string; + currency: string; + currencyExchange?: { + sourceCurrency: string; + targetCurrency: string; + unitCurrency: string; + exchangeRate: string; + contractId: string; + quotationDate: string; + }; + }; + status: "booked" | "pending" | "info"; + valueDate?: string; + bookingDate?: string; + mandateId?: string; + endToEndId?: string; + messageId?: string; + + creditor?: Party + creditorAgent?: FinancialInstitution; + creditorAccount?: FinancialInstitution; + + debtor?: Party + debtorAgent?: FinancialInstitution; + debtorAccount?: FinancialInstitution; + + unstructuredRemittanceInformation?: string; + bankTransactionCode: BankTransactionCode; + } + + interface Party { + name?: string; + partyType: "private" | "organization"; + otherId?: { + id: string; + schemeName?: string; + issuer?: string; + }; + } + + interface Account { + name?: string; + currency?: string; + otherId?: { + id: string; + schemeName?: string; + issuer?: string; + }; + } + + interface FinancialInstitution { + type: "financial-institution"; + name?: string; + bic?: string; + otherId?: { + id: string; + schemeName?: string; + issuer?: string; + }; + } + + interface BankTransactionCode { + domain?: string; + family?: string; + subfamily?: string; + proprietaryIssuer?: string; + proprietaryCode?: string; + } diff --git a/libeufin/sepa.rst b/libeufin/sepa.rst new file mode 100644 index 00000000..9555256a --- /dev/null +++ b/libeufin/sepa.rst @@ -0,0 +1,24 @@ +SEPA Payments +############# + +This page collects reference materials and details for specifics of SEPA payments. + +SEPA Credit Transfer (SCT) +========================== + +SCT is a "normal" bank transfer. Details (terminology, data definitions, flow diagrams) can be found in the EPC's +`SCT rulebook <https://www.europeanpaymentscouncil.eu/document-library/rulebooks/sepa-credit-transfer-rulebook>`__. + + +Reject vs Return vs Recall +-------------------------- + +* A **rejected** payment is refused by the originator bank or the + clearing and settlement layer. +* A **returned** payment is refused by the beneficiary's bank via a + counter-transaction over the settlement layer. +* A payment is **recalled** when the originator's bank (potentially + requested by the originator) wants to "undo" a SCT. + +SEPA currently does **not** directly support a mechanism for the **beneficiary** to return +a payment. diff --git a/libeufin/transaction-identification.rst b/libeufin/transaction-identification.rst new file mode 100644 index 00000000..7c737fc2 --- /dev/null +++ b/libeufin/transaction-identification.rst @@ -0,0 +1,85 @@ +Transaction Identification +########################## + +This page describes how bank transactions are **identified** in various banking protocols and +data formats. + +**Why is transaction identification necessary?** +When a client downloads the transaction history from some data source, it has to know +whether a transaction is new, or whether the transaction is already part of the +client's local records. + +Protocol-specific Details +========================= + +ISO 20022 camt.05X +------------------ + +The camt52/53/54 messages defined by ISO 20022 do not have a mandatory transaction +identifier. Instead if defines a handful of optional references. + +Two identifiers seem to be used in practice: The *Account Servicer Reference* and the +*Entry Reference*. Of these, only the *Account Servicer Reference* seems to be useful +for transaction identification. + +The Account Servicer Reference is assigned by the bank to a transaction. In +practice, all banks assign the **same** Account Servicer Reference to the same +transaction showing up in camt52 (the account report), camt53 (the account +statement) and camt53 (credit notifications). + +The Account Servicer Reference is assigned by the bank that reports the transaction, +and does **not** serve as a globally unique identifier for the transaction. + +However, in rare cases, a transaction can be reported that does not yet have an +Account Servicer Reference assigned to it by the bank yet. This can happen +when the bank only received a (SWIFT) pre-notification for the transaction, but decides +to already pass on this information to the customer. In this case, banks seem to +assign an *Entry Reference* to the corresponding entry. + +Most other transactions, however, do **not** have an *Entry Reference* assigned to it. +Some banks document that the *Entry Reference* is only unique within one report for one account. + +OFX +--- + +OFX assigns a transaction identifier to each reported transactions, allowing the client +to know which transactions it has already seen. + +Problems and Possible Solutions +=============================== + +Sometimes the same bank can offer **multiple** ways to download transactions. +In Germany, most banks offer EBICS and FinTS access, which delivers transactions +in the camt.52/53 format. However, some also offer access via PSD2 APIs and completely custom APIs. + +Two APIs from the same bank do not necessarily need to support the same transaction identification scheme. +This could lead to the same transaction showing up multiple times in the account transaction history, which +is clearly bad! + +LibEuFin intends to solve this problem in the following ways: + +1. Each local account has a single "transaction identification scheme". + Importing transactions via a bank connection that has a different transaction + identifier scheme will fail. +2. When a bank connection reports a transaction that is missing the expected transaction identifier, + the status (booked, pending, info) is examined: + + 1. When the status is booked, an error is reported, and corresponding bank message + will be made available for review + 2. When the status is "pending" or "info", the entry will simply be ignored. + +In the future, this might be extended to be less restrictive: + +* An account could be configured to do transaction identification based on a "core attributes hash", + i.e. a cryptographic hash of core attributes of the transactions that are expected to not change. + This should only apply to booked transactions. +* Un-identifiable pending/info transactions could be managed in a separate + "informational" transactions table that is purged as soon as a *booked statement closing transaction* + is reported with a higher booking date. + +Others +====== + +* `UETR <https://www.swift.com/your-needs/industry-themes/unique-end-to-end-transaction-reference-uetr>`__ is + a unique identifier used on the SWIFT level. It doesn't help for transaction identification + as not every transaction goes over SWIFT, even for SEPA accounts. |