All notable changes to this project will be documented in this file.
- [Unreleased]
- [1.2.18] - 2026-04-14
- [1.2.17] - 2026-03-30
- [1.2.16] - 2026-03-19
- [1.2.15] - 2026-03-04
- [1.2.12] - 2026-03-04
- [1.2.11] - 2026-02-11
- [1.2.10] - 2026-01-13
- [1.2.9] - 2026-01-13
- [1.2.8] - 2026-01-13
- [1.2.7] - 2026-01-13
- [1.2.6] - 2026-01-13
- [1.2.5] - 2026-01-12
- [1.2.4] - 2026-01-12
- [1.2.3] - 2026-01-09
- [1.2.2] - 2026-01-09
- [1.2.1] - 2026-01-09
- [1.2.0] - 2026-01-09
- [1.1.0] - 2026-01-09
- [1.0.0] - 2026-01-09
- [0.0.12] - 2026-01-09
- [0.0.11] - 2025-12-19
- [0.0.10] - 2025-12-17
- [0.0.9] - 2025-12-16
- [0.0.8] - 2025-12-17
- [0.0.7] - 2025-12-17
- [0.0.6] - 2025-12-16
- [0.0.5] - 2025-12-16
- [0.0.4] - 2025-12-16
- [0.0.3] - 2025-01-23
- [0.0.2] - 2025-01-23
- [0.0.1] - 2025-01-23
- Added The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Repository tooling (maintainers):
.cursor/rules/(PHP/Symfony bundle, Twig/assets, frontend TS/Vite, tests/quality, docs/release, global),.cursorignore, and.github/copilot-instructions.md. - GitHub: Workflows
pr-lint.yml(YAML/markdown checks on pull requests) andstale.yml(stale issues/PRs). Dependabot: grouped updates forsymfony/*andphpstan/*on the root Composer ecosystem entry.
- Scrutinizer (
.scrutinizer.yml): PHP code rating and duplication checks; path filters excludingdemo/,tests/,vendor/,node_modules/; test run usescomposer test-coveragewith Clovercoverage.xmland Xdebug/coverage ini (see file for full layout). - Demos:
docker-compose.ymlfor symfony6, symfony7, and symfony8 sets explicitdns(8.8.8.8,8.8.4.4) to reduce Docker/WSL failures resolvingrepo.packagist.org. - Composer locks: Root
composer.lockand demo locks (symfony7, symfony8) refreshed (Symfony 8.0.x and related polyfills in resolved trees where applicable). - Rector: Removed a dead
withSkip()entry forCommandHelpToAttributeRector(not registered in the current Rector set; no change to console commands, which still usesetHelp()for Symfony 6.0 / 6.1 compatibility).
- RELEASE.md: Maintainer release checklist lives only in
RELEASE.mdunder Current release (vX.Y.Z);RELEASE_CHECKLIST.mdremoved. README links todocs/RELEASE.mdonly for the release process.
- No breaking API changes to the bundle’s public PHP API. Cursor/GitHub workflow and Scrutinizer changes affect repository maintenance only. Demo DNS and lock updates apply when you run demos from this repo; applications consuming
nowo-tech/sepa-payment-bundlevia Composer are unchanged unless you pin transitive versions yourself.
- Scrutinizer CI: Added
.scrutinizer.yml— build imagedefault-bionic, PHP 8.2, environment variableXDEBUG_MODE=coverage,composer install --no-interaction --prefer-dist, and PHPUnit using the rootphpunit.xml.distonly. This avoids the PHP build failure when OpenSSL on the default image is too old for PHP 8.2+, and avoids running PHPUnit against demo apps without a committedvendor/tree.
- Demos: Distinct default
PORTandDEFAULT_URIper demo (symfony6: 8001,symfony7: 8002,symfony8: 8003). Demo.gitignorefiles align with local env files and common archive patterns. - demo/Makefile: Fixed shell syntax in
test-coverage-all(if/then/fi) somake -C demo release-checkruns correctly. - Development: Root
docker-composeuses a singlephpservice with acoverage-datavolume mounted at/app/coverage. Root Makefile includes avalidate-translationstarget for bundle YAML undersrc/Resources/translations/. - Makefile:
composer-syncrunscomposer install --dry-runinstead ofcomposer update --no-install, socomposer.lockis not rewritten duringmake release-check(usemake updatewhen you intentionally refresh the lock). - Rector:
CommandHelpToAttributeRectoris skipped so console commands keep help inconfigure()/setHelp()and remain compatible with Symfony Console 6.0 and 6.1 (thehelpparameter on#[AsCommand]exists only from 6.2+).
- README / USAGE / UPGRADING: Standalone examples for
CreditTransferGeneratorandXsdValidatorinclude the requiredTranslatorInterface(usingIdentityTranslatorwhere appropriate). Constructor argument order for BIC lookup, XSD validation, events, and logging matches the currentCreditTransferGeneratorsignature. - USAGE.md: Removed stray text before the XSD section;
XsdValidatorsnippets pass a translator. - DEMO-FRANKENPHP.md: Caddyfile path corrected to
docker/frankenphp/Caddyfile.dev;bundles.phpexample updated with Twig Inspector (as in demos); clarified production bundle loading; table of contents lists###subsections under Development configuration. - INSTALLATION.md: Table of contents for the main sections.
- README: Demo section clarifies FrankenPHP development (no worker) vs production-style (worker); highlighted line uses Found this useful? for consistency with project documentation standards.
- No breaking API changes: Patch release. Applications using the bundle as a dependency do not need code changes. Scrutinizer and Makefile targets affect maintainers and CI only.
- Console commands (Symfony 6.0 / 6.1): Removed the
helpparameter from the#[AsCommand]attribute inValidateIbanCommand,ValidateCreditCardCommand,ParseDirectDebitCommand, andConvertCccCommand. Thehelpparameter is only available from Symfony Console 6.2+. Help text is now set viasetHelp()inconfigure(), socache:clearand the commands work correctly on Symfony 6.0 and 6.1 without "Unknown named parameter $help".
- Translation file names: Bundle translation files have been renamed from
nowo_sepa_payment.*.yamlandvalidators.*.yamltoNowoSepaPaymentBundle.*.yaml(one domain per locale). The translation domain used in code remainsNowoSepaPaymentBundle. If you override bundle messages in your application, rename your override files to use the new domain, e.g.translations/NowoSepaPaymentBundle.es.yaml.
- CONFIGURATION.md: Added sections explaining that bundle translations are overridable, the translation load order (project
translations/first, then app bundle overrides, then bundleResources/translations/), and how to override messages in the application.
- No breaking API changes: Commands and validation behaviour are unchanged. If you do not override bundle translations in your project, no migration is required. If you have custom translation files for the old domains (
nowo_sepa_paymentorvalidators), rename them to theNowoSepaPaymentBundledomain and the same keys.
- MandateStatusTest: Unit tests for
MandateStatus::getValues()andMandateStatus::isValid() - BicLookupService: Tests for country not in switch (default branch), addMapping then lookup for existing country
- CreditCardValidator: Tests for getCardType (Diners Club, JCB), mask with short number, getCardType with zero
- CreditTransferGenerator: Test for BIC lookup filling transaction creditor BIC when IBAN is Spanish
- Bundle / CI: Added
brick/mathconstraint^0.11 || ^0.12 || ^0.13in rootcomposer.jsonso installs on PHP 8.1 (including GitHub CI) resolve to a PHP 8.1‑compatible version (avoidsbrick/math0.14.x which requires PHP 8.2+) - Demo Symfony 6.4: Constrained
brick/mathto^0.11 || ^0.12 || ^0.13in democomposer.jsonfor PHP 8.1 compatibility (same reason as above) - Test coverage: Line coverage improved;
@codeCoverageIgnoreadded for library-compatibility branches and defensive paths in CreditTransferGenerator and DirectDebitGenerator (alternative Digitick\Sepa API and DOM fallbacks that are not exercised with current library version)
- No breaking changes: Patch release; no migration required.
- Rector: PHP refactoring tool integrated for code quality
rector.phpconfig (PHP 8.1, dead code, code quality, type declarations); excludesdemo/- Composer scripts:
rector,rector-dry - Makefile targets:
rector,rector-dry
- PHPStan: Static analysis at level 8
phpstan.neon.distandphpstan-baseline.neon(extensions: phpstan-symfony, phpstan-phpunit)- Composer script:
phpstan - Makefile target:
phpstan
- Release check:
release-checknow runs cs-check, rector-dry, phpstan, and test (composer script and Makefile)
- Static analysis: Codebase passes PHPStan level 8; type safety improvements in parsers, generators, validators, and models
- CreditTransferParser / DirectDebitParser:
getFirstNode()helper for XPath results; safe handling ofDOMNodeList|falseandDOMNode/DOMElement - CreditTransferGenerator / DirectDebitGenerator: DOM and
saveXML()/getAttribute()type guards; direct use of library methods wheremethod_existswas redundant - BicLookupService: BIC database initialized via
getDefaultBicDatabase()for correct typing - Mandate:
getExpirationDate()usesDateTime::createFromInterface()andmodify()with correct typing - Validators: PHPDoc for
$optionsand$value(mixed) where required by PHPStan - SepaPaymentLogger: constructor normalizes
nulltoNullLoggerso the logger property is alwaysLoggerInterface - NowoSepaPaymentBundle:
getContainerExtension()return type aligned with parent
- CreditTransferParser / DirectDebitParser:
- Documentation: All inline code comments (including PHPStan/Rector notes) are in English
- PHPStan baseline: Removed obsolete baseline entries; analysis runs with no ignored patterns (all previous issues resolved in code)
- ParseDirectDebitCommand: Validate path is a readable file before reading
- Added
is_file()andis_readable()checks beforefile_get_contents()to avoid PHP Notice when the path is a directory (e.g. errno 21 "Is a directory") - Users now get a clear "Could not read file" error instead of a Notice followed by "Invalid SEPA Direct Debit XML format"
- Compatible with all PHP versions in CI (8.1–8.5)
- Added
- SepaBusinessRulesValidator: PHP 8.4+ compatibility for sequence type transitions
- Replaced
nullas array key with empty string''inisValidSequenceTypeTransition()to avoid "Using null as array offset" deprecation in PHP 8.4+ - Lookup uses
$previousSequenceType ?? ''so behaviour is unchanged on all supported PHP versions
- Replaced
- ValidateCreditCardCommandTest: Relaxed assertion for invalid card message so it accepts the actual multi-line output ("valid according to the Luhn algorithm")
- ParseDirectDebitCommandTest: Relaxed assertion for unreadable file so it accepts "Invalid SEPA Direct Debit XML" when the message is wrapped across lines
- CI / test suite: Tests now pass with exit code 0 on all CI matrix combinations (PHP 8.1–8.5, Symfony 6.4 / 7.0 / 8.0)
- RemesaGeneratorTest: Added
#[IgnoreDeprecations]on tests that exercise the deprecated RemesaGenerator API - RemesaParserTest: Added
#[IgnoreDeprecations]and temporary suppression ofE_DEPRECATED/E_USER_DEPRECATEDin tests that call deprecated RemesaParser methods, so deprecation output does not mark tests as risky - No behaviour change for application code; only test and CI behaviour
- RemesaGeneratorTest: Added
- CI / coverage: Minimum code coverage requirement lowered from 85% to 80% (enforced in the
testandcoveragejobs in.github/workflows/ci.yml). See DEVELOPMENT.md for current requirements. - Release workflow: GitHub API now expects
make_latestas a string ('true'|'false'|'legacy'). Updated.github/workflows/release.ymlandsync-releases.ymlso release creation/update no longer returns 422.
- Improved Packagist search visibility: Enhanced package metadata for better discoverability
- Updated
composer.jsondescription to include key terms:pain.001,pain.008,ISO 20022,IBAN/BIC validation - Expanded keywords from 9 to 30 terms, including:
- SEPA formats:
pain.001,pain.008,iso20022,iso-20022 - Functionality:
sepa-payment,sepa-credit-transfer,sepa-direct-debit - Validations:
iban-validation,bic-validation,xsd-validation - Utilities:
xml-generator,ccc-to-iban,credit-card-validation - Spanish terms:
remesa-pago,remesa-cobro - Other:
european-payments,bank-transfer,symfony-bundle
- SEPA formats:
- Enhanced README.md initial description with SEPA standards and ISO 20022 compliance mentions
- This improvement makes the package easier to find when searching for SEPA, ISO 20022, pain.001, pain.008, IBAN validation, and related terms
- Updated
- French and Italian translations: Removed translation files with YAML syntax errors
- Removed
nowo_sepa_payment.fr.yaml- had YAML syntax errors with incorrectly escaped apostrophes - Removed
nowo_sepa_payment.it.yaml- had YAML syntax errors with incorrectly escaped apostrophes - Removed
validators.fr.yaml- had YAML syntax errors with incorrectly escaped apostrophes - These translation files had YAML syntax errors and are no longer maintained
- This cleanup helps streamline the translation resources in the project
- French and Italian language support can be added back in the future if needed
- If you were using these translations, they will fall back to the default language (usually English)
- Removed
- Catalan translations: Removed Catalan translation files (
nowo_sepa_payment.ca.yamlandvalidators.ca.yaml)- These translation files had YAML syntax errors and are no longer maintained
- This cleanup helps streamline the translation resources in the project
- Catalan language support can be added back in the future if needed
- CreditTransferGenerator: Fixed incorrect usage of deprecated
debtor*methods inTransactionobjects- Changed
getDebtorAddress()togetCreditorAddress()in transaction address handling - Changed
setDebtorBic()tosetCreditorBic()when setting transaction BIC - Changed
setDebtorAddressFromArray()tosetCreditorAddressFromArray()when setting transaction address from array - Changed
setDebtorAddress()tosetCreditorAddress()when setting transaction address - Updated comments and variable names for consistency
- This fix ensures compatibility with the refactored
Transactionclass that now usescreditor*field names (changed in 1.2.4)
- Changed
- Catalan translations: Removed Catalan translation files (
nowo_sepa_payment.ca.yamlandvalidators.ca.yaml)- These translation files had YAML syntax errors and are no longer maintained
- This cleanup helps streamline the translation resources in the project
- Catalan language support can be added back in the future if needed
- CreditTransferGenerator: Fixed incorrect usage of deprecated
debtor*methods inTransactionobjects- Changed
getDebtorAddress()togetCreditorAddress()in transaction address handling - Changed
setDebtorBic()tosetCreditorBic()when setting transaction BIC - Changed
setDebtorAddressFromArray()tosetCreditorAddressFromArray()when setting transaction address from array - Changed
setDebtorAddress()tosetCreditorAddress()when setting transaction address - Updated comments and variable names for consistency
- This fix ensures compatibility with the refactored
Transactionclass that now usescreditor*field names (changed in 1.2.4)
- Changed
- TranslatorInterface is now required:
TranslatorInterfaceis now a mandatory dependency for error message translationCreditTransferGenerator: Constructor now requiresTranslatorInterfaceas the second parameter (previously optional)XsdValidator: Constructor now requiresTranslatorInterfaceas the first parameter (previously optional)- Null-safe operators (
?->) and English fallback messages have been removed - All error messages now use translations from the
nowo_sepa_paymentdomain - Breaking Change: Code that instantiates these classes directly must now provide a
TranslatorInterfaceinstance - Migration: Use Symfony's dependency injection to automatically inject the translator, or provide a translator instance when creating these classes manually
- Dependencies moved to require: Moved Symfony dependencies from
require-devtorequire(production dependencies)symfony/translation: Now required in production (previously inrequire-dev)symfony/validator: Now required in production (previously inrequire-dev)symfony/yaml: Now required in production (previously inrequire-dev)- These dependencies are needed at runtime, not just for development
- Internationalized error messages: Error messages in
CreditTransferGeneratornow use Symfony's translation system- All validation error messages are translatable
- Supports 11 languages:
en_GB,en_US,es,pt,ca,de,fr,it,nb,pt_PT,ru - Translation domain:
nowo_sepa_payment - Error messages include proper parameter substitution (e.g.,
%field%,%iban%,%error%)
- CreditTransferGenerator: Fixed incorrect usage of deprecated
debtor*methods inTransactionobjects- Changed
getDebtorAddress()togetCreditorAddress()in transaction address handling - Changed
setDebtorBic()tosetCreditorBic()when setting transaction BIC - Changed
setDebtorAddressFromArray()tosetCreditorAddressFromArray()when setting transaction address from array - Changed
setDebtorAddress()tosetCreditorAddress()when setting transaction address - Updated comments and variable names for consistency
- This fix ensures compatibility with the refactored
Transactionclass that now usescreditor*field names (changed in 1.2.4)
- Changed
- Credit Transfer Generator Validation: Added validation to detect incorrect key usage in
generateFromArray()method- Detects when
creditor*keys are used at the top level (should bedebtor*keys) - Detects when
debtor*keys are used in transactions (should becreditor*keys) - Provides clear error messages with suggestions for correct key names
- Helps prevent confusion between debtor and creditor roles in SEPA Credit Transfers
- Errors are thrown early during array normalization, before XML generation
- Detects when
- Demo Applications: Refactored demo controllers for better code organization
- Separated large
DemoController(1558 lines) into multiple focused controllers by functionality - Created
ValidationController,CreditTransferController,DirectDebitController,MandateController,ExportImportController,DeprecatedController, andValidationAdvancedController - Applied to all demo applications (Symfony 6, 7, and 8)
- Makes demo code more maintainable and easier to understand
- Separated large
- Credit Transfer Transaction Model: Refactored
CreditTransfer\Transactionto usecreditor*field names instead ofdebtor*- Changed field names:
debtorIban→creditorIban,debtorName→creditorName,debtorBic→creditorBic,debtorAddress→creditorAddress - Updated all methods:
getDebtorIban()→getCreditorIban(),setDebtorBic()→setCreditorBic(), etc. - This change makes the code self-documenting: Transaction fields now correctly reflect that they represent creditors (suppliers/beneficiaries that receive money)
- Breaking Change: Code using
CreditTransfer\Transactiondirectly must be updated to use the newcreditor*method names - Breaking Change: The
generateFromArray()method now acceptsdebtor*field names at the top level of the array (representing the company that pays) andcreditor*field names in transactions (representing who receives payment). The deprecateddebtor*field names in transactions are no longer supported
- Changed field names:
- Credit Transfer Generator: Fixed incorrect mapping of creditor/debtor roles in SEPA Credit Transfer generation
- Corrected
PaymentInformationto use debtor data (company that pays) instead of creditor data - Corrected
CustomerCreditTransferInformationto use creditor data (supplier/beneficiary that receives) instead of debtor data - Updated address handling methods (
setDebtorPostalAddressandsetPostalAddress) to correctly map addresses - Updated DOM manipulation methods (
addDebtorAddressToDomandaddCreditorAddressToDom) to correctly add addresses to XML - This fix ensures compliance with SEPA pain.001 standard where one debtor (company) pays multiple creditors (suppliers)
- Corrected
- Deprecated Attribute Parameter: Fixed incorrect parameter name in
#[Deprecated]attribute- Changed
reasonparameter tomessagein#[Deprecated]attribute (correct PHP 8.1+ syntax) - Updated
RemesaGeneratormethods:generateFromArray(),generate(),createResponse() - Updated
RemesaParsermethods:parseCreditTransfer(),isValidCreditTransfer() - The
#[Deprecated]attribute usesmessageparameter, notreason
- Changed
- ValidationCache Tests: Fixed cache implementation for tests
- Created
ArrayCacheclass for testing that properly implements PSR-16 SimpleCache interface methods - Fixed
ValidationCache::get()logic to checkhas()before callingget()for better compatibility - All ValidationCache tests now pass correctly
- Created
- ParseDirectDebitCommand Tests: Fixed Symfony 6+ compatibility
- Removed deprecated
Application::add()calls from tests (not needed in Symfony 6+) - Commands with
#[AsCommand]attribute are automatically registered - All ParseDirectDebitCommand tests now pass correctly
- Removed deprecated
- ParseDirectDebitCommand Output: Fixed amount formatting
- Amount values are now formatted with 2 decimal places using
number_format() - Ensures consistent display format (e.g., "100.50" instead of "100.5")
- Amount values are now formatted with 2 decimal places using
- Deprecated Attribute: Fixed incorrect usage of
#[Deprecated]attribute with invalidreplacementparameter- Removed invalid
replacementparameter from#[Deprecated]attribute inRemesaGeneratormethods - Removed invalid
replacementparameter from#[Deprecated]attribute inRemesaParsermethods - Corrected attribute syntax to use only valid parameters:
reasonandsince - The
replacementparameter only exists in PHPDoc@deprecatedannotations, not in PHP#[Deprecated]attribute
- Removed invalid
- Mandate Management: Complete mandate lifecycle management system for SEPA Direct Debit
MandateService- Service for managing mandate lifecycle (create, suspend, reactivate, revoke)MandateRepositoryInterfaceandMandateRepository- Repository pattern for mandate storageMandateStatusenum - Status enumeration (ACTIVE, EXPIRED, REVOKED, SUSPENDED)MandateHistory- History tracking for mandate changes- Enhanced
Mandatemodel with status, expiration date, and revocation support - Mandate expiration date validation (defaults to 36 months after signature date)
- Mandate sequence type transition validation (FRST → RCUR/FNAL, RCUR → RCUR/FNAL, etc.)
- Mandate history tracking for all status and sequence type changes
createMandate()- Create new mandatesupdateSequenceType()- Update mandate sequence type with validationrevokeMandate()- Revoke mandates with optional reasonsuspendMandate()- Suspend mandates temporarilyreactivateMandate()- Reactivate suspended mandatesvalidateMandateForTransaction()- Validate mandates before use in transactionsisValidSequenceTransition()- Check if sequence type transitions are validfindMandatesByDebtorIban()- Find all mandates for a debtorfindActiveMandates()- Find all active mandatesfindExpiredMandates()- Find expired mandatesgetMandateHistory()- Get complete history for a mandate- In-memory repository implementation (can be extended with database-backed implementation)
- Comprehensive test coverage with 12 test cases
- Demo endpoints:
/demo-mandate-management,/demo-mandate-lifecycle,/demo-mandate-sequence-transitions
- Validation Caching: New caching system for validation results to improve performance
ValidationCacheInterfaceandValidationCache- Service for caching validation results (PSR-16 SimpleCache compatible)CachedIbanValidator- Cached wrapper for IBAN validationCachedBicValidator- Cached wrapper for BIC validation- Optional cache adapter support (works without cache, backward compatible)
- Configurable TTL for cached results
- Cache key normalization and management
- Console Command for Direct Debit Parsing: New command to parse SEPA Direct Debit XML files
nowo:sepa:parse-direct-debit- Parse and display Direct Debit XML information- JSON output option (
--json) - Displays group header, payment information, and transaction details
- Validates XML structure before parsing
- Validation Events: Event system for validation operations
BeforeValidationEvent- Dispatched before validation (allows custom validation logic)AfterValidationEvent- Dispatched after validation (for logging and monitoring)- Full integration with Symfony EventDispatcher
- Automatic BIC Lookup by IBAN: New
BicLookupServicefor automatically looking up BIC codes from IBANsBicLookupServiceInterface- Interface for BIC lookup servicesBicLookupService- Implementation with local database of IBAN to BIC mappings- Support for 8 countries: ES (Spain), DE (Germany), FR (France), IT (Italy), GB (UK), NL (Netherlands), BE (Belgium), PT (Portugal)
- Automatic BIC lookup in
CreditTransferGeneratorandDirectDebitGeneratorwhen BIC is missing - Optional cache support (PSR-16 SimpleCache compatible)
lookupBic()- Look up BIC code for a given IBANisAvailable()- Check if BIC lookup is available for a given IBANaddMapping()- Add custom IBAN to BIC mappings for bank-specific codes- Country-specific bank code extraction patterns for accurate BIC lookup
- Comprehensive local database with common bank mappings
- Export to Other Formats: New
ExportServicefor exporting SEPA payment data to various formatsexportCreditTransferToJson()- Export Credit Transfer data to JSON format (with pretty print option)exportDirectDebitToJson()- Export Direct Debit data to JSON format (with pretty print option)exportCreditTransferToCsv()- Export Credit Transfer data to CSV format (customizable delimiter and enclosure)exportDirectDebitToCsv()- Export Direct Debit data to CSV format (customizable delimiter and enclosure)importCreditTransferFromJson()- Import Credit Transfer data from JSON formatimportDirectDebitFromJson()- Import Direct Debit data from JSON format- Full support for multiple transactions in CSV exports
- Comprehensive CSV headers for both Credit Transfer and Direct Debit formats
- Symfony Events: Event system for extensibility without modifying bundle code
BeforeCreditTransferGenerationEvent- Dispatched before Credit Transfer XML generation (allows data modification)AfterCreditTransferGenerationEvent- Dispatched after Credit Transfer XML generation (allows XML modification)BeforeDirectDebitGenerationEvent- Dispatched before Direct Debit XML generation (allows data modification)AfterDirectDebitGenerationEvent- Dispatched after Direct Debit XML generation (allows XML modification)- Event dispatcher integration in
CreditTransferGeneratorandDirectDebitGenerator(optional dependency injection) - Full support for event listeners and subscribers to modify data and XML
- Structured Logging: New
SepaPaymentLoggerservice for structured logging of SEPA operations- Integration with
Psr\Log\LoggerInterfacefor flexible logging backends - Structured logging methods for Credit Transfer and Direct Debit generation (start, success, failure)
- Structured logging methods for validation events (IBAN, BIC, XSD validation)
- Structured logging methods for parsing events (Credit Transfer and Direct Debit parsing)
- Context data included in all log entries (messageId, transactionCount, etc.)
- Optional logger injection in generators (backward compatible)
- Automatic logging of generation lifecycle events
- Integration with
- SEPA String Sanitization: New
SepaStringSanitizerservice for validating and sanitizing strings according to SEPA character rules- Validates allowed characters in SEPA names and addresses
- Sanitizes invalid characters and replaces accented characters with ASCII equivalents
- Validates and truncates field lengths (names, addresses, remittance information)
- Supports maximum length validation for all SEPA fields
- SEPA Country Validation: New
SepaCountryValidatorservice for validating SEPA member countries- Validates if a country code is a SEPA member (34 countries supported)
- Validates country from IBAN
- Provides country names for all SEPA member countries
- Includes all current SEPA members (EU, EEA, Switzerland, UK, Monaco, San Marino)
- SEPA Business Rules Validation: New
SepaBusinessRulesValidatorservice for validating SEPA business rules and limits- Validates transaction amount limits (max: 999,999,999.99 EUR)
- Validates transaction count limits (max: 99,999 per file)
- Validates execution date rules (must be today or future)
- Validates business day rules (Monday to Friday)
- Validates currency restrictions (EUR only for SEPA)
- Validates mandate expiration dates
- Validates sequence type transitions for Direct Debit (FRST → RCUR, etc.)
- Comprehensive validation methods for Credit Transfer and Direct Debit
- Generators:
CreditTransferGeneratornow auto-fills creditor and debtor BIC when missing (ifBicLookupServiceis injected)DirectDebitGeneratornow auto-fills creditor and debtor BIC when missing (ifBicLookupServiceis injected)- BIC lookup is optional and backward compatible (only works if service is injected)
- Demo Applications:
- Added new demo endpoints for export/import functionality, BIC lookup, string sanitization, country validation, business rules validation, validation caching, and mandate management
- Added
/demo-validation-cache-iban- Demonstrates IBAN validation caching with performance comparison - Added
/demo-validation-cache-bic- Demonstrates BIC validation caching with performance comparison - Added
/demo-sepa-string-sanitizer- Demonstrates SEPA string sanitization - Added
/demo-sepa-country-validator- Demonstrates SEPA country validation - Added
/demo-sepa-business-rules- Demonstrates SEPA business rules validation - Added
/demo-mandate-management- Demonstrates mandate creation and management - Added
/demo-mandate-lifecycle- Demonstrates mandate lifecycle (create, suspend, reactivate, revoke) - Added
/demo-mandate-sequence-transitions- Demonstrates sequence type transition validation - Fixed JsonResponse usage in all demo endpoints (proper encoding options with
setEncodingOptions()) - All demo endpoints now properly format JSON output with pretty print and unicode support
- Documentation:
- Updated
USAGE.mdwith comprehensive examples for all new services - Updated
FUTURE.mdto mark Validation Caching and Mandate Management as completed - Updated
UPGRADE.mdwith Mandate Management documentation
- Updated
- Test Coverage:
- Added 5 new tests for
ValidationCache(ValidationCacheTest.php) - Added 4 new tests for
CachedIbanValidator(CachedIbanValidatorTest.php) - Added 4 new tests for
CachedBicValidator(CachedBicValidatorTest.php) - Added 4 new tests for
ParseDirectDebitCommand(ParseDirectDebitCommandTest.php) - Added 2 new tests for validation events (
ValidationEventTest.php) - Added 12 new tests for
MandateService(MandateServiceTest.php) - Total: 335+ tests, 1042+ assertions
- Added 5 new tests for
- DirectDebitParser: Complete SEPA Direct Debit XML parser for feature parity with Credit Transfer parser
parseDirectDebit()method to extract all information from SEPA Direct Debit XML filesisValidDirectDebit()method to validate XML structure- Full support for parsing:
- Group header (message ID, creation date, initiating party)
- Payment information (payment info ID, sequence type, due date, local instrument code)
- Creditor information (name, IBAN, BIC, creditor ID)
- Transaction details (end-to-end ID, amount, currency, debtor information, mandate details)
- Creditor and debtor postal addresses (full and partial)
- Supports pain.008.001.02 format
- Comprehensive test coverage with 7 test cases
- Test Coverage: Added comprehensive test cases for both parsers:
- RemesaParser: Added 4 new test cases (multiple transactions, addresses, optional fields, different currencies)
- DirectDebitParser: Added 5 new test cases (sequence types, missing BIC, missing remittance info, B2B instrument, optional fields)
- Total test suite: 182+ tests with comprehensive coverage
- Documentation: Enhanced documentation with parser examples in all demo applications
- Badge Fix: Replaced PUGX PHP version badge with shields.io for better reliability
- Fixed PHP version badge not displaying correctly by switching from PUGX to shields.io
- RemesaGenerator: Complete Feature Parity with DirectDebitGenerator:
- Added
generateFromArray()method toRemesaGeneratorfor generating SEPA Credit Transfer XML from array data - Supports both camelCase and snake_case field names (same as DirectDebitGenerator)
- Added postal address support for creditor in
RemesaData:setCreditorAddress()- Set creditor address (array or individual fields)setCreditorAddressFromArray()- Set creditor address from arraygetCreditorAddress()- Get creditor address
- Added postal address support for debtor in
Transaction:setDebtorAddress()- Set debtor address (array or individual fields)setDebtorAddressFromArray()- Set debtor address from arraygetDebtorAddress()- Get debtor address
- Addresses are automatically included in the generated XML (pain.001.001.03 format)
- Addresses are added using DOM manipulation to ensure compatibility with SEPA standards
- Support for address fields in
generateFromArray()method:creditorAddressor individual fields:creditorStreet,creditorCity,creditorPostalCode,creditorCountrydebtorAddressor individual fields:debtorStreet,debtorCity,debtorPostalCode,debtorCountry- Both camelCase and snake_case formats supported
- Added
- Feature Parity:
RemesaGeneratornow has the same functionality asDirectDebitGenerator:- Array-based generation with
generateFromArray() - Postal address support (creditor and debtor)
- Snake_case and camelCase field name support
- Automatic address inclusion in XML
- Array-based generation with
- Demo Applications: Updated all demo applications (Symfony 6, 7, 8) with new endpoints:
/demo-credit-transfer-array- Generate from array (camelCase)/demo-credit-transfer-with-addresses- Generate from array with addresses/demo-credit-transfer-snake-case- Generate from array (snake_case)- Updated existing
/demo-credit-transferto include address examples
- Test Coverage: Added comprehensive test coverage for new
RemesaGeneratorfeatures:- Tests for
generateFromArray()method with camelCase and snake_case formats - Tests for address handling (creditor and debtor) in both array and object formats
- Tests for
RemesaDataandTransactionaddress methods - Edge case tests (empty arrays, missing fields, validation)
- Additional tests for DateTimeInterface support (requestedExecutionDate, creationDate)
- Tests for amount conversion from cents (> 10000)
- Tests for optional fields (creditorBic, debtorBic, remittanceInformation, currency, batchBooking)
- Tests for date type validation (invalid types)
- Tests for multiple transactions with addresses
- Total of 30 tests for
RemesaGenerator(12 new tests added) - Test coverage improved to 83.08% lines for
RemesaGenerator - Overall test suite: 173 tests, 608 assertions
- Tests for
- Documentation: Improved documentation structure:
- Moved detailed usage examples to
docs/USAGE.md - Moved console commands documentation to
docs/COMMANDS.md - Moved demo information to
docs/DEMOS.md - Moved development guidelines to
docs/DEVELOPMENT.md - Main
README.mdnow provides concise overview with references
- Moved detailed usage examples to
- Internationalization: All demo routes and templates now use English:
- Routes translated to English:
/demo-remesa-pago→/demo-credit-transfer/demo-remesa-pago-array→/demo-credit-transfer-array/demo-remesa-pago-with-addresses→/demo-credit-transfer-with-addresses/demo-remesa-pago-snake-case→/demo-credit-transfer-snake-case/demo-remesa-cobro→/demo-direct-debit/demo-remesa-cobro-snake-case→/demo-direct-debit-snake-case/demo-remesa-cobro-with-addresses→/demo-direct-debit-with-addresses
- Route names translated: All route names now use English (e.g.,
demo_credit_transferinstead ofdemo_remesa_pago) - File names translated: Generated XML files now use English names (e.g.,
credit-transfer.xmlinstead ofremesa-pago.xml) - Templates translated: All demo templates now use English text:
- Replaced "Remesa de Pago" with "Credit Transfer"
- Replaced "Remesa de Cobro" with "Direct Debit"
- All user-facing text in demo applications is now in English
- Routes translated to English:
- Code Documentation: All PHPDoc comments translated to English:
- Replaced "remesa data" with "credit transfer data" in all PHPDoc comments
- Updated example filenames in PHPDoc:
remesa-pago.xml→credit-transfer.xml - Updated example filenames in PHPDoc:
remesa-cobro.xml→direct-debit.xml - Updated class descriptions to use English terminology
- All PHPDoc comments now consistently use English
- Improved PHPDoc comments for address handling methods to clarify DOM manipulation fallback mechanism
- Added PHPStan ignore annotations for dynamic method calls verified with
method_exists()
- Complete Service Auto-Registration with
#[AsAlias]Attributes: All services now use Symfony's#[AsAlias]attribute for automatic service registration- Added
#[AsAlias]attribute to all service classes:IbanValidator-nowo_sepa_payment.validator.iban_validatorBicValidator-nowo_sepa_payment.validator.bic_validatorCreditCardValidator-nowo_sepa_payment.validator.credit_card_validatorCccConverter-nowo_sepa_payment.converter.ccc_converterRemesaParser-nowo_sepa_payment.parser.remesa_parserRemesaGenerator-nowo_sepa_payment.generator.remesa_generator(already had it)DirectDebitGenerator-nowo_sepa_payment.generator.direct_debit_generator(already had it)IdentifierGenerator-nowo_sepa_payment.generator.identifier_generator(already had it)
- Each service class now includes a
SERVICE_NAMEconstant for consistent alias naming - Services are automatically registered as public services via the
#[AsAlias]attribute
- Added
- Simplified Service Configuration: Updated
services.yamlto use resource-based service discovery- Services are now automatically discovered via
resourcedirectives for each namespace - Removed manual service definitions (now handled by
#[AsAlias]attributes) - All services are configured as public by default
- Only console commands require explicit configuration (for tags and arguments)
- This follows Symfony best practices for modern service registration
- Services are now automatically discovered via
- Code Organization: All services follow a consistent pattern with
#[AsAlias]attributes - Maintainability: Service registration is now declarative in the classes themselves rather than in configuration files
- Symfony Best Practices: Aligns with Symfony's recommended approach for service registration using attributes
- Service Configuration: Updated service definitions in
services.yamlto use service aliases directly instead of fully qualified class names- All services now use consistent alias naming:
nowo_sepa_payment.{category}.{service_name} - Service IDs changed from class names to aliases:
Nowo\SepaPaymentBundle\Validator\IbanValidator→nowo_sepa_payment.validator.iban_validatorNowo\SepaPaymentBundle\Validator\BicValidator→nowo_sepa_payment.validator.bic_validatorNowo\SepaPaymentBundle\Validator\CreditCardValidator→nowo_sepa_payment.validator.credit_card_validatorNowo\SepaPaymentBundle\Converter\CccConverter→nowo_sepa_payment.converter.ccc_converterNowo\SepaPaymentBundle\Generator\RemesaGenerator→nowo_sepa_payment.generator.remesa_generatorNowo\SepaPaymentBundle\Generator\DirectDebitGenerator→nowo_sepa_payment.generator.direct_debit_generatorNowo\SepaPaymentBundle\Generator\IdentifierGenerator→nowo_sepa_payment.generator.identifier_generatorNowo\SepaPaymentBundle\Parser\RemesaParser→nowo_sepa_payment.parser.remesa_parser
- All service arguments now reference services by their aliases instead of class names
- This change improves consistency with Symfony best practices and aligns with the
#[AsAlias]attributes used in generator classes - Services can still be injected by type-hinting (autowiring) or by their aliases using
#[Autowire]attribute
- All services now use consistent alias naming:
- Service Dependency Resolution: Service dependencies now use alias references, making the service container configuration more maintainable and consistent
- HTTP Response Helper Method: Added
createResponse()method to bothDirectDebitGeneratorandRemesaGenerator- Method accepts XML content (string) and filename (string) as parameters
- Returns a Symfony
Responseobject with proper headers for XML file download - Automatically sets
Content-Type: application/xmlandContent-Disposition: attachment; filename="..." - Simplifies controller code by eliminating manual Response creation
- Example usage:
$generator->createResponse($xml, 'direct-debit.xml')
-
Additional Fields Support for DirectDebit Transactions:
- Added
debtorBicfield support inDirectDebitTransaction(optional BIC for debtor) - Added
additionalDataarray for storing custom fields internally - Added methods:
setDebtorBic(),getDebtorBic(),setAdditionalData(),getAdditionalData(),setAdditionalField(),getAdditionalField() debtorBicis included in generated XML when providedadditionalDatais stored internally but not included in XML (for internal use only)- Support for
debtorBicand additional fields ingenerateFromArray()method
- Added
-
Documentation:
- Added
DEPRECATED_FIELDS.mddocumenting fields that are no longer allowed in SEPA Direct Debit transactions - Documented that postal addresses and contact information cannot be included in transactions (only in mandates)
- Added examples of correct and incorrect usage
- Added
-
Test Coverage:
- Added 5 new tests for
DirectDebitTransactioncoveringdebtorBicandadditionalDatafunctionality - Added 5 new tests for
DirectDebitGeneratorverifying BIC inclusion in XML and additional data handling - Tests verify that additional data is stored but not included in generated XML
- Added 5 new tests for
- Fixed constant type declarations for PHP 8.2 compatibility
- Removed
const stringtype declarations that caused syntax errors in PHP 8.2 - Changed to untyped constants with literal string values
- Fixed in
Configuration::ALIAS,DirectDebitGenerator::SERVICE_NAME,RemesaGenerator::SERVICE_NAME,IdentifierGenerator::SERVICE_NAME
- Removed
- Postal Address Support (Optional): Added support for exporting creditor and debtor postal addresses in the generated XML
- Addresses are completely optional - only included if provided in the array
- Addresses are included using structured format (PstlAdr) with elements: StrtNm, TwnNm, PstCd, and Ctry
- Addresses are automatically added to XML using DOM manipulation after generation
- Both
DirectDebitDataandDirectDebitTransactionsupport address fields - Addresses can be set via object methods (
setCreditorAddress(),setDebtorAddress()) or array input (both camelCase and snake_case) - Support for
creditorAddressanddebtorAddressingenerateFromArray()method - Support for
creditor_addressanddebtor_addressin snake_case format - Support for individual address fields:
creditor_street,creditor_city,creditor_postal_code,creditor_country,debtor_street,debtor_city,debtor_postal_code,debtor_country - Updated
setCreditorAddress()andsetDebtorAddress()methods to accept arrays directly - Empty address arrays are ignored and will not create address elements
- At least one address field must be provided for the address to be included in XML
- Updated documentation to reflect address support and optional nature
- Updated
DEPRECATED_FIELDS.mdto clarify that addresses are now supported (as of v0.0.8) - Updated README examples to show address usage and clarify that addresses are optional
- Address methods now accept arrays directly as first parameter for better usability
- Added 8 new tests for address functionality:
testGenerateXmlWithCreditorAddress()- Tests creditor address with object methodstestGenerateXmlWithDebtorAddress()- Tests debtor address with object methodstestGenerateXmlWithBothAddresses()- Tests both addresses togethertestGenerateFromArrayWithCreditorAddressSnakeCase()- Tests creditor address in snake_casetestGenerateXmlWithoutAddresses()- Tests that addresses are not included when not providedtestGenerateXmlWithEmptyAddressArray()- Tests that empty address arrays are ignored- Updated
testGenerateXml()- Verifies no address elements when addresses are not provided - Updated
testGenerateFromArrayWithAddresses()- Enhanced assertions for address elements - Updated
testGenerateFromArrayWithAddressesSnakeCase()- Enhanced assertions for address elements
-
Additional Fields Support for DirectDebit Transactions:
- Added
debtorBicfield support inDirectDebitTransaction(optional BIC for debtor) - Added
additionalDataarray for storing custom fields internally - Added methods:
setDebtorBic(),getDebtorBic(),setAdditionalData(),getAdditionalData(),setAdditionalField(),getAdditionalField() debtorBicis included in generated XML when providedadditionalDatais stored internally but not included in XML (for internal use only)- Support for
debtorBicand additional fields ingenerateFromArray()method
- Added
-
Snake_case Field Name Support:
DirectDebitGenerator::generateFromArray()now supports both camelCase and snake_case field names- Automatic field name normalization for maximum flexibility
- Supports common snake_case formats:
message_id,initiating_party_name,payment_name,due_date,creditor_name,creditor_iban,creditor_bic,sequence_type,creditor_id,instrument_code,items,instruction_id,debtor_iban,debtor_name,debtor_mandate,debtor_mandate_signature_date,information - Backward compatible: existing camelCase code continues to work
-
Documentation:
- Added
DEPRECATED_FIELDS.mddocumenting fields that are no longer allowed in SEPA Direct Debit transactions - Documented that postal addresses and contact information cannot be included in transactions (only in mandates)
- Added examples of correct and incorrect usage
- Updated README with snake_case examples
- Added
-
Test Coverage:
- Added 5 new tests for
DirectDebitTransactioncoveringdebtorBicandadditionalDatafunctionality - Added 5 new tests for
DirectDebitGeneratorverifying BIC inclusion in XML and additional data handling - Added 2 new tests for snake_case format support
- Tests verify that additional data is stored but not included in generated XML
- Added 5 new tests for
-
Demo Applications:
- Added
/demo-direct-debit-snake-caseendpoint to all demo applications (Symfony 6, 7, 8) - Demonstrates usage of snake_case format with real-world example
- Added
- Fixed constant type declarations for PHP 8.2 compatibility
- Removed
const stringtype declarations that caused syntax errors in PHP 8.2 - Changed to untyped constants with literal string values
- Fixed in
Configuration::ALIAS,DirectDebitGenerator::SERVICE_NAME,RemesaGenerator::SERVICE_NAME,IdentifierGenerator::SERVICE_NAME
- Removed
-
Service Registration with Attributes:
DirectDebitGeneratornow uses Symfony#[AsAlias]attribute for automatic service registration- Service is registered with alias
nowo_sepa_payment.generator.direct_debit_generator - Service is marked as public for explicit service retrieval
- Added
SERVICE_NAMEconstant usingConfiguration::ALIASfor consistent naming
- Service is registered with alias
-
Enhanced Test Coverage for DirectDebitGenerator: Added comprehensive test cases to improve code coverage
- Tests for
generateFromArray()withDateTimeInterfaceobjects - Tests for amount conversion from cents (> 10000)
- Tests for optional fields (
creditorBic,remittanceInformation,debtorMandateSignDate) - Tests for missing required fields validation
- Tests for invalid data types validation
- Tests for edge cases (empty transactions, missing transactions)
- Total of 14 new test methods covering all code paths
- Tests for
- Removed
setPaymentMethod()calls fromRemesaGeneratorandDirectDebitGenerator- Payment method is now automatically set by Digitick\Sepa v3.0 based on transfer file type
- Fixed
testGenerateFromArraytest to use correct field names (reference,bankAccountOwner,seqType) - Updated CHANGELOG documentation
- Complete Digitick\Sepa v3.0 API compatibility:
- Updated
PaymentInformationconstructor usage - Updated transaction creation with
CustomerCreditTransferInformationandCustomerDirectDebitTransferInformation - Fixed transaction amounts to use integers (cents)
- Updated method names to match v3.0 API
- Removed deprecated methods (
setCreationDateTime,setNumberOfTransactions,setControlSum) - Updated documentation and CHANGELOG
- Updated README with dependency information
- Updated
- Full compatibility with Digitick\Sepa v3.0 API changes:
- Fixed
GroupHeaderconstructor to pass required parameters (messageIdandinitiatingPartyName) - Removed
setCreationDateTime()calls (creation date is now set automatically by GroupHeader) - Updated
PaymentInformationconstructor to use required parameters (id,originAccountIBAN,originAgentBIC,originName,originAccountCurrency) - Updated transaction creation to use
CustomerCreditTransferInformationandCustomerDirectDebitTransferInformationconstructors - Changed transaction amounts to be passed as integers (cents) instead of floats
- Updated method names to match v3.0 API:
setRequestedExecutionDate()→setDueDate()setRequestedCollectionDate()→setDueDate()setCreditorSchemeIdentification()→setCreditorId()setMandateIdentification()→setMandateId()setDateOfSignature()→setMandateSignDate()addCreditTransferTransaction()→addTransfer()withCustomerCreditTransferInformationaddTransferInformation()→addTransfer()withCustomerDirectDebitTransferInformation
- Removed automatic calculation methods (
setNumberOfTransactions,setControlSum) as they are now calculated automatically
- Fixed
- Updated
RemesaGeneratorandDirectDebitGeneratorto useGroupHeaderin constructor instead of format string - Fixed footer display in demo templates using flexbox layout for proper positioning
- Updated demo
composer.jsonfiles to use@devversion for local development with path repositories
- Initial release of SEPA Payment Bundle
- Full SEPA payment management functionality
- IBAN validation and utilities
- CCC to IBAN conversion
- BIC validation
- Credit Card validation
- Identifier generation
- SEPA Credit Transfer XML generation (pain.001.001.03)
- SEPA Direct Debit XML generation (pain.008.001.02)
- SEPA XML parsing (Credit Transfer)
- Basic demo applications
- IBAN validation and utilities
- CCC to IBAN conversion
- BIC validation
- Credit Card validation
- Identifier generation
- SEPA Credit Transfer XML generation (pain.001.001.03)
- SEPA Direct Debit XML generation (pain.008.001.02)
- SEPA XML parsing (Credit Transfer)
- Basic demo applications