Lue dans les fichiers PHP du paquet au commit c096d4c3559b : ses espaces de noms, classes, interfaces et énumérations, leurs constantes, propriétés et méthodes publiques avec leur PHPDoc, et les options que prennent ses fabriques. Rien n’en est exécuté.
ApiclassThe statement files a connection carries, read and put together, and the transfer files written. The files travel in the connection's state:
3 methods
FilesGatewayFactoryclassStatement files: what the bank exports (CAMT.053, OFX, CSV) read from the connection's state, and transfers written as the pain.001 file the bank takes. No network, no consent: connect() has nothing to do.
12 options
FingerprintsclassIds for the lines a file gives no reference to: a hash of the date, the amount, the label and the counterparty, so the same line read from two files (two exports that overlap) is one transaction. Two identical lines in one file - two coffees the same day - are told apart by their rank: the second is "<hash>#2", and it is #2 in the next export too.
1 method
Pain001WriterclassSEPA credit transfers as the pain.001.001.03 file a bank takes (the EPC implementation: SEPA service level, SLEV charges, euros): one payment block per debtor account and execution date, one transaction each.
2 methods · 1 constant
StatementclassOne account's statement as a file tells it: the account, its balances, its lines.
1 method · 3 properties
TextclassWhat the readers and the writer share: amounts, dates, encodings, IBANs, the SEPA character set.
8 methods
AccountsActionclassThe accounts the statement files are about.
3 methods
BalancesActionclassThe latest balance of each type the account's statements give (closing booked, available...).
3 methods
ConnectActionclassNothing to open: the files are the access. The connection comes back as it is, its consent active.
2 methods
TransactionsActionclassThe account's lines from every statement, each once, oldest first, between the dates asked.
3 methods
TransferActionclassThe transfer as a pain.001.001.03 file: the result is "generated", the file and its name in it, to upload to the bank's website. Its id is the file's message id, and the end-to-end id when none was given - the one the bank's statement will carry back.
3 methods
Camt053ReaderclassISO 20022 bank-to-customer statements: camt.053 (BkToCstmrStmt/Stmt), and the same entries in camt.052 reports and camt.054 notifications, whatever the version (001.02 to 001.08 and on). One Statement per Stmt.
3 methods
CsvReaderclassA bank's CSV export, read through a column map. The "csv" option (the gateway's, a statement's own over it):
3 methods · 2 constants
OfxReaderclassOFX statements: 1.x (SGML, leaf tags left open, the CHARSET:1252 of French banks) and 2.x (XML), bank accounts (STMTRS) and cards (CCSTMTRS). One Statement per account statement.
3 methods
ReaderInterfaceinterfaceReads one kind of statement file.
3 methods
Omnibank\Files
Api class
final class Api Api.php:28
The statement files a connection carries, read and put together, and the transfer files written. The files travel in the connection's state:
['statements' => [ ['name' => 'releve-2026-09.xml', 'content' => '<?xml ...'], ['name' => 'export.csv', 'content' => '...', 'account' => ['iban' => 'FR76...', 'name' => 'Compte courant'], 'csv' => ['date_format' => 'd/m/Y']], ]]
A statement's "format" (camt053, ofx, csv) is found from its content when not given. Statements of one account are one account: their lines put together, each line once (by its id - files that overlap are fine), oldest first; their balances, the latest of each type.
Api::__construct()
public function __construct(readonly array $readers, readonly array $options = [])$readersin the order they are tried, the catch-all (CSV) last
$optionsthe gateway's
Api::statements()
public function statements(Connection $connection): array- Returns
by account id
Api::transfer()
public function transfer(Transfer $transfer, ?\DateTimeImmutable $now = null): TransferResultThe transfer as a pain.001 file to hand the bank.
FilesGatewayFactory class
final class FilesGatewayFactory extends GatewayFactory FilesGatewayFactory.php:29
Statement files: what the bank exports (CAMT.053, OFX, CSV) read from the connection's state, and transfers written as the pain.001 file the bank takes. No network, no consent: connect() has nothing to do.
options: currency: EUR # a CSV's, when it does not say csv: { delimiter: ';', date_format: 'd/m/Y', columns: { ... } } # see Reader\CsvReader debtor_name: 'Nakaya SAS' # for transfer(): the account holder, as the bank knows it debtor_bic: null # the debtor's bank's BIC; "NOTPROVIDED" goes without initiating_party: null # who sends the file, when not the debtor batch_booking: false
Options
| Option | Default | |
|---|---|---|
currency | 'EUR' | |
csv | [] | |
debtor_name | null | |
debtor_bic | null | |
initiating_party | null | |
batch_booking | false | |
omnibank.api | static fn(Config $c) => new Api([new Camt053Reader(), new OfxReader(), new CsvReader()], ['currency' => $c['currency'], 'csv' => (array) $c['csv'], 'debtor_n… | |
omnibank.action.connect | new ConnectAction() | |
omnibank.action.accounts | new AccountsAction() | |
omnibank.action.balances | new BalancesAction() | |
omnibank.action.transactions | new TransactionsAction() | |
omnibank.action.transfer | new TransferAction() |
Fingerprints class
final class Fingerprints Fingerprints.php:14
Ids for the lines a file gives no reference to: a hash of the date, the amount, the label and the counterparty, so the same line read from two files (two exports that overlap) is one transaction. Two identical lines in one file - two coffees the same day - are told apart by their rank: the second is "<hash>#2", and it is #2 in the next export too.
Fingerprints::id()
public function id(\DateTimeInterface $bookedOn, Money $amount, string $label, ?string $counterparty = null): stringPain001Writer class
final class Pain001Writer Pain001Writer.php:18
SEPA credit transfers as the pain.001.001.03 file a bank takes (the EPC implementation: SEPA service level, SLEV charges, euros): one payment block per debtor account and execution date, one transaction each.
Names and texts are put in the SEPA character set and cut to their lengths (70 for a name, 140 for the remittance information); IBANs are checked. With no BIC for the debtor's bank, "NOTPROVIDED" goes, as the EPC allows; the creditor's agent is left out when its BIC is unknown.
const NAMESPACE = 'urn:iso:std:iso:20022:tech:xsd:pain.001.001.03'
Pain001Writer::__construct()
public function __construct(readonly string $debtorName, readonly ?string $debtorBic = null, readonly ?string $initiatingParty = null, readonly bool $batchBooking = false)Pain001Writer::write()
public function write(array $transfers, string $messageId, ?\DateTimeImmutable $now = null): string- Returns
the pain.001 XML
Statement class
final readonly class Statement Statement.php:10
One account's statement as a file tells it: the account, its balances, its lines.
public Account $accountpublic array $balancespublic array $transactions
Statement::__construct()
public function __construct(public Account $account, public array $balances = [], public array $transactions = [])Text class
final class Text Text.php:6
What the readers and the writer share: amounts, dates, encodings, IBANs, the SEPA character set.
Text::utf8()
public static function utf8(string $content, ?string $encoding = null): stringThe content as UTF-8: as it is when it is UTF-8 already (its BOM dropped), from Windows-1252 otherwise.
Text::decimal()
public static function decimal(string $amount, ?string $decimal = null): ?stringA bank's amount as a plain decimal ("-1234.56"): spaces, non-breaking spaces and apostrophes between thousands dropped, the decimal mark found - the last of "," and "." when both are there, "," alone when it is followed by one or two digits, or as $decimal says. A trailing or parenthesized minus counts.
Text::date()
public static function date(string $value, array $formats): ?\DateTimeImmutableA date in the first of $formats it matches, at midnight.
Text::isoDate()
public static function isoDate(?string $value): ?\DateTimeImmutableAn ISO date ("2026-09-03") or date-time ("2026-09-03T10:15:00+02:00") from an XML file.
Text::iban()
public static function iban(?string $iban): ?stringAn IBAN as it is written in files: upper case, no spaces.
Text::isIban()
public static function isIban(?string $iban): boolWhether an IBAN holds: its shape and its check digits (ISO 13616, modulo 97).
Text::sepa()
public static function sepa(string $text, int $length): stringText in the character set every SEPA bank takes (EPC: a-z A-Z 0-9 / - ? : ( ) . , ' + and space), accents transliterated, the rest made spaces, cut at $length.
Text::key()
public static function key(string $text): stringLower case, accents and punctuation gone: how a CSV header is compared.
Omnibank\Files\Action
AccountsAction class
final class AccountsAction implements ActionInterface, ApiAwareInterface AccountsAction.php:14
The accounts the statement files are about.
AccountsAction::__construct()
public function __construct()AccountsAction::supports()
public function supports(Request $request): boolAccountsAction::execute()
public function execute(Request $request): voidBalancesAction class
final class BalancesAction implements ActionInterface, ApiAwareInterface BalancesAction.php:14
The latest balance of each type the account's statements give (closing booked, available...).
BalancesAction::__construct()
public function __construct()BalancesAction::supports()
public function supports(Request $request): boolBalancesAction::execute()
public function execute(Request $request): voidConnectAction class
final class ConnectAction implements ActionInterface ConnectAction.php:12
Nothing to open: the files are the access. The connection comes back as it is, its consent active.
ConnectAction::supports()
public function supports(Request $request): boolConnectAction::execute()
public function execute(Request $request): voidTransactionsAction class
final class TransactionsAction implements ActionInterface, ApiAwareInterface TransactionsAction.php:15
The account's lines from every statement, each once, oldest first, between the dates asked.
TransactionsAction::__construct()
public function __construct()TransactionsAction::supports()
public function supports(Request $request): boolTransactionsAction::execute()
public function execute(Request $request): voidTransferAction class
final class TransferAction implements ActionInterface, ApiAwareInterface TransferAction.php:18
The transfer as a pain.001.001.03 file: the result is "generated", the file and its name in it, to upload to the bank's website. Its id is the file's message id, and the end-to-end id when none was given - the one the bank's statement will carry back.
TransferAction::__construct()
public function __construct()TransferAction::supports()
public function supports(Request $request): boolTransferAction::execute()
public function execute(Request $request): voidOmnibank\Files\Reader
Camt053Reader class
final class Camt053Reader implements ReaderInterface Camt053Reader.php:29
ISO 20022 bank-to-customer statements: camt.053 (BkToCstmrStmt/Stmt), and the same entries in camt.052 reports and camt.054 notifications, whatever the version (001.02 to 001.08 and on). One Statement per Stmt.
Each booked entry (Ntry) is a transaction - pending and information-only ones are left out - signed by CdtDbtInd (DBIT is money gone out, a reversal's included: RvslInd only says the parties are the original operation's). A batch entry whose details (TxDtls) carry their own amounts is one transaction per detail. The counterparty is the debtor of a credit and the creditor of a debit; the reference is the remittance information (RmtInf/Ustrd), else the end-to-end id. The id is the bank's (AcctSvcrRef, else NtryRef), else a fingerprint of the line.
Camt053Reader::format()
public function format(): stringCamt053Reader::accepts()
public function accepts(string $content, string $name): boolCamt053Reader::read()
public function read(string $content, string $name, array $options = []): arrayCsvReader class
final class CsvReader implements ReaderInterface CsvReader.php:48
A bank's CSV export, read through a column map. The "csv" option (the gateway's, a statement's own over it):
delimiter: null # ";", ",", "\t"...; found from the header line when null enclosure: '"' encoding: null # UTF-8 when the file is, Windows-1252 otherwise (French exports) decimal: null # "," or "."; found per amount when null ("1 234,56", "1,234.56") date_format: [d/m/Y, Y-m-d, d/m/y, d.m.Y, d-m-Y, Y/m/d] # tried in order header: true # false: no header line, the columns are 0-based indexes columns: # a header's name (accents and case aside), a list of names, or an index date: ... # the booking date (required) value_date: ... label: ... # required amount: ... # signed; or debit and credit, two columns debit: ... # gone out: made negative, whatever its sign in the file credit: ... counterparty: ... counterparty_iban: ... reference: ... currency: ... balance: ... # the balance after the line: the latest one is the account's id: ... # the bank's id for the line, when the export has one
Each column has defaults that read the usual French and English exports (Crédit Mutuel, CIC, BNP, Société Générale, LCL, La Banque Postale, Boursorama...). The lines above the header (an export's title, the account number) are skipped; so are lines with no amount. A line with an amount and a date that reads in none of the formats is an error, never skipped.
The account is the statement's "account" option (id, iban, bic, name, currency, type), else the file's name.
const COLUMNS = ['date' => ['date', 'date operation', 'date d operation', 'date de l operation', 'date comptable', 'date de comptabilisation', 'booking date', 'transaction d…The header names each column is looked for under, by default.
const DATE_FORMATS = ['d/m/Y', 'Y-m-d', 'd/m/y', 'd.m.Y', 'd-m-Y', 'Y/m/d', 'Y-m-d H:i:s', 'd/m/Y H:i:s', 'd/m/Y H:i']
CsvReader::format()
public function format(): stringCsvReader::accepts()
public function accepts(string $content, string $name): boolCsvReader::read()
public function read(string $content, string $name, array $options = []): arrayOfxReader class
final class OfxReader implements ReaderInterface OfxReader.php:24
OFX statements: 1.x (SGML, leaf tags left open, the CHARSET:1252 of French banks) and 2.x (XML), bank accounts (STMTRS) and cards (CCSTMTRS). One Statement per account statement.
A line (STMTTRN) is signed by TRNAMT (a decimal comma is read too), booked on DTPOSTED, its value date DTAVAIL; its label is NAME, MEMO after it when it says more; its id the bank's FITID, else a fingerprint of the line. OFX carries no IBAN: a statement's "account" option gives one.
OfxReader::format()
public function format(): stringOfxReader::accepts()
public function accepts(string $content, string $name): boolOfxReader::read()
public function read(string $content, string $name, array $options = []): arrayReaderInterface interface
interface ReaderInterface ReaderInterface.php:9
Reads one kind of statement file.
ReaderInterface::format()
public function format(): stringThe format's name, as a statement's "format" key gives it: "camt053", "ofx", "csv".
ReaderInterface::accepts()
public function accepts(string $content, string $name): boolWhether the file looks like this format: its content first, its name second.
ReaderInterface::read()
public function read(string $content, string $name, array $options = []): array$optionsthe gateway's options, the statement's own over them
- Throws
ProviderException when the file cannot be read