silarhi / cfonb-parser
A PHP Parser for CFONB transactions with zero dependencies
Installs: 41 459
Dependents: 0
Suggesters: 1
Security: 0
Stars: 11
Watchers: 3
Forks: 7
Open Issues: 0
Requires
- php: >=8.2
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.72
- phpstan/phpstan: ^2
- phpunit/phpunit: ^10.5.26
- rector/rector: ^2
- vimeo/psalm: ^5.26
This package is auto-updated.
Last update: 2025-09-29 07:49:37 UTC
README
A zero dependencies PHP Parser for CFONB statements
Supports CFONB 120/240 format
Installation
The preferred method of installation is via Composer. Run the following
command to install the package and add it as a requirement to your project's
composer.json
:
composer require silarhi/cfonb-parser
How to use
Parse CFONB 120
<?php use Silarhi\Cfonb\Cfonb120Reader; $reader = new Cfonb120Reader(); //Gets all statements day by day foreach($reader->parse('My Content') as $statement) { if ($statement->hasOldBalance()) { echo sprintf("Old balance : %f\n", $statement->getOldBalance()->getAmount()); } foreach($statement->getOperations() as $operation) { //Gets all statement operations } if ($statement->hasNewBalance()) { echo sprintf("New balance : %f\n", $statement->getNewBalance()->getAmount()); } }
Reading CFONB 120 from file
<?php use Silarhi\Cfonb\Cfonb120Reader; $reader = new Cfonb120Reader(); $content = file_get_contents('/path/to/cfonb120-file.txt'); foreach($reader->parse($content) as $statement) { // Process each daily statement echo "Statement date: " . $statement->getOldBalance()->getDate()->format('Y-m-d') . "\n"; }
Detailed operation processing
<?php use Silarhi\Cfonb\Cfonb120Reader; $reader = new Cfonb120Reader(); foreach($reader->parse($content) as $statement) { foreach($statement->getOperations() as $operation) { echo "Date: " . $operation->getDate()->format('Y-m-d') . "\n"; echo "Value Date: " . $operation->getValueDate()->format('Y-m-d') . "\n"; echo "Amount: " . $operation->getAmount() . "\n"; echo "Label: " . $operation->getLabel() . "\n"; echo "Reference: " . $operation->getReference() . "\n"; echo "Bank Code: " . $operation->getBankCode() . "\n"; echo "Account: " . $operation->getAccountNumber() . "\n"; // Access optional fields if ($operation->getInternalCode()) { echo "Internal Code: " . $operation->getInternalCode() . "\n"; } // Process operation details (additional information) foreach($operation->getDetails() as $detail) { echo "Additional Info: " . $detail->getAdditionalInformations() . "\n"; } echo "---\n"; } }
Using strict mode (default) vs non-strict mode
<?php use Silarhi\Cfonb\Cfonb120Reader; use Silarhi\Cfonb\Exceptions\ParseException; $reader = new Cfonb120Reader(); // Strict mode (default) - throws exception on parsing errors try { $statements = $reader->parse($content); // strict=true by default } catch (ParseException $e) { echo "Parsing error: " . $e->getMessage() . "\n"; } // Non-strict mode - continues parsing despite errors $statements = $reader->parse($content, false); // strict=false
Parse CFONB 240
<?php use Silarhi\Cfonb\Cfonb240Reader; use Silarhi\Cfonb\Banking\Transfer; $reader = new Cfonb240Reader(); foreach($reader->parse('My Content') as $transfer) { assert($transfer instanceof Transfer); }
Detailed CFONB 240 transfer processing
<?php use Silarhi\Cfonb\Cfonb240Reader; $reader = new Cfonb240Reader(); foreach($reader->parse($content) as $transfer) { // Access transfer header information $header = $transfer->getHeader(); echo "Transfer Date: " . $header->getPrevTransactionFileDate()->format('Y-m-d') . "\n"; echo "Bank Code: " . $header->getRecipientBankCode1() . "\n"; echo "Account: " . $header->getRecipientAccountNumber1() . "\n"; // Process all transactions in the transfer foreach($transfer->getTransactions() as $transaction) { echo "Transaction Date: " . $transaction->getSettlementDate()->format('Y-m-d') . "\n"; echo "Amount: " . $transaction->getTransactionAmount() . "\n"; echo "Recipient: " . $transaction->getRecipientName1() . "\n"; echo "Reference: " . $transaction->getPresenterReference() . "\n"; } // Access transfer total $total = $transfer->getTotal(); echo "Total Amount: " . $total->getTotalAmount() . "\n"; echo "Sequence Number: " . $total->getSequenceNumber() . "\n"; }
Reading CFONB 240 from file with error handling
<?php use Silarhi\Cfonb\Cfonb240Reader; use Silarhi\Cfonb\Exceptions\ParseException; use Silarhi\Cfonb\Exceptions\HeaderUnavailableException; $reader = new Cfonb240Reader(); try { $content = file_get_contents('/path/to/cfonb240-file.txt'); foreach($reader->parse($content) as $transfer) { // Safely access optional header try { $header = $transfer->getHeader(); echo "Processing transfer from: " . $header->getRecipientBankCode1() . "\n"; } catch (HeaderUnavailableException $e) { echo "Transfer header not available\n"; } // Process transactions... } } catch (ParseException $e) { echo "Failed to parse CFONB file: " . $e->getMessage() . "\n"; }
Parse both CFONB 120 and CFONB 240
<?php use Silarhi\Cfonb\CfonbReader; use Silarhi\Cfonb\Banking\Statement; use Silarhi\Cfonb\Banking\Transfer; $reader = new CfonbReader(); foreach($reader->parseCfonb120('My Content') as $statement) { assert($statement instanceof Statement); } foreach($reader->parseCfonb240('My Content') as $transfer) { assert($transfer instanceof Transfer); }
Advanced Usage Examples
Processing bank statements with filtering
<?php use Silarhi\Cfonb\Cfonb120Reader; use Silarhi\Cfonb\Banking\Operation; $reader = new Cfonb120Reader(); $statements = $reader->parse($content); // Filter operations by amount foreach ($statements as $statement) { $largeOperations = array_filter( $statement->getOperations(), fn(Operation $op) => abs($op->getAmount()) > 1000 ); foreach ($largeOperations as $operation) { echo "Large operation: {$operation->getAmount()} - {$operation->getLabel()}\n"; } }
Building a transaction summary
<?php use Silarhi\Cfonb\Cfonb120Reader; $reader = new Cfonb120Reader(); $statements = $reader->parse($content); $summary = [ 'total_debit' => 0, 'total_credit' => 0, 'operation_count' => 0 ]; foreach ($statements as $statement) { foreach ($statement->getOperations() as $operation) { $amount = $operation->getAmount(); if ($amount > 0) { $summary['total_credit'] += $amount; } else { $summary['total_debit'] += abs($amount); } $summary['operation_count']++; } } echo "Summary:\n"; echo "Total Credits: {$summary['total_credit']}\n"; echo "Total Debits: {$summary['total_debit']}\n"; echo "Operation Count: {$summary['operation_count']}\n";
Converting to array for API usage
<?php use Silarhi\Cfonb\Cfonb120Reader; $reader = new Cfonb120Reader(); $statements = $reader->parse($content); $data = []; foreach ($statements as $statement) { $statementData = [ 'date' => $statement->getOldBalance()->getDate()->format('Y-m-d'), 'opening_balance' => $statement->hasOldBalance() ? $statement->getOldBalance()->getAmount() : null, 'closing_balance' => $statement->hasNewBalance() ? $statement->getNewBalance()->getAmount() : null, 'operations' => [] ]; foreach ($statement->getOperations() as $operation) { $statementData['operations'][] = [ 'date' => $operation->getDate()->format('Y-m-d'), 'value_date' => $operation->getValueDate()->format('Y-m-d'), 'amount' => $operation->getAmount(), 'label' => $operation->getLabel(), 'reference' => $operation->getReference(), 'bank_code' => $operation->getBankCode(), 'account_number' => $operation->getAccountNumber() ]; } $data[] = $statementData; } // Convert to JSON for API response echo json_encode($data, JSON_PRETTY_PRINT);
Handling multiple account statements
<?php use Silarhi\Cfonb\Cfonb120Reader; $reader = new Cfonb120Reader(); $statements = $reader->parse($content); // Group statements by account $accountStatements = []; foreach ($statements as $statement) { if ($statement->hasOldBalance()) { $accountNumber = $statement->getOldBalance()->getAccountNumber(); $accountStatements[$accountNumber][] = $statement; } } // Process each account separately foreach ($accountStatements as $accountNumber => $statements) { echo "Account: $accountNumber\n"; echo "Number of statements: " . count($statements) . "\n"; $totalBalance = 0; foreach ($statements as $statement) { if ($statement->hasNewBalance()) { $totalBalance = $statement->getNewBalance()->getAmount(); } } echo "Final balance: $totalBalance\n\n"; }
Troubleshooting
Common parsing errors
<?php use Silarhi\Cfonb\Cfonb120Reader; use Silarhi\Cfonb\Exceptions\ParseException; $reader = new Cfonb120Reader(); try { $statements = $reader->parse($content); } catch (ParseException $e) { // Common issues: // - Invalid line length (should be 120 characters) // - Malformed line format // - Invalid date format // - Invalid amount format echo "Parse error on line: " . $e->getMessage() . "\n"; // Try non-strict mode to continue parsing $statements = $reader->parse($content, false); }
Validating file format before parsing
<?php use Silarhi\Cfonb\Cfonb120Reader; function validateCfonbFormat(string $content): bool { $lines = explode("\n", trim($content)); foreach ($lines as $line) { // Skip empty lines if (empty(trim($line))) continue; // Check line length for CFONB 120 if (strlen($line) !== 120) { return false; } // Check if line starts with valid CFONB code $lineCode = substr($line, 0, 2); if (!in_array($lineCode, ['01', '04', '05', '07'])) { return false; } } return true; } // Usage if (validateCfonbFormat($content)) { $reader = new Cfonb120Reader(); $statements = $reader->parse($content); } else { echo "Invalid CFONB format\n"; }