SEPA XML Generator
This is a python implementation to generate SEPA XML files.
Limitations
Supported standards:
- SEPA PAIN.001.001.03
- SEPA PAIN.001.001.09
- SEPA PAIN.001.001.10
- SEPA PAIN.001.001.11
- SEPA PAIN.008.001.02
- SEPA PAIN.008.001.08
- SEPA PAIN.008.001.09
- SEPA PAIN.008.001.10
Usage
Direct debit
Example:
from sepaxml import SepaDD import datetime, uuid config = { # "msg_id": "", # If your bank require a specific format for MsgId, you can optionnaly set it up here. Default will be randomly generated with timestamp followed by a random value. "name": "Test von Testenstein", "IBAN": "NL50BANK1234567890", "BIC": "BANKNL2A", "batch": True, "creditor_id": "DE26ZZZ00000000000", # supplied by your bank or financial authority "currency": "EUR", # ISO 4217 # "instrument": "B2B", # - default is CORE (B2C) "address": { # The address and all of its fields are optional but in some countries they are required "address_type": "ADDR", # valid: ADDR, PBOX, HOME, BIZZ, MLTO, DLVY "department": "Head Office", "subdepartment": None, "street_name": "Musterstr.", "building_number": "1", "postcode": "12345", "town": "Berlin", "country": "DE", "country_subdivision": None, "lines": ["Line 1", "Line 2"], }, # "initiating_party": "John Doe", # optional name of the initiator of the payment, required by some banks. default to ''name' # "initiating_party_id": "DE26ZZZ00000000002", # optional, supplied by your bank or financial authority. default to 'creditor_id' "ultimate_creditor": { # The ultimate_creditor and all of its fields are optional but in some financial institution they are required "name": "Real Creditor", "BIC_or_BEI": "REALNL2A", "id": "12345678900001", # can be a local official id or the creditor_id "id_scheme_name": "SIRET", # proprietary scheme of the id provided (i.e. SEPA, SIRET...) }, } sepa = SepaDD(config, schema="pain.008.001.02", clean=True) payment = { "name": "Test von Testenstein", "IBAN": "NL50BANK1234567890", "BIC": "BANKNL2A", "amount": 5000, # in cents "type": "RCUR", # FRST,RCUR,OOFF,FNAL "collection_date": datetime.date.today(), "mandate_id": "1234", "mandate_date": datetime.date.today(), "description": "Test transaction", # "endtoend_id": str(uuid.uuid1()).replace("-", ""), # autogenerated if obmitted "address": { # The address and all of its fields are optional but in some countries they are required "address_type": "ADDR", # valid: ADDR, PBOX, HOME, BIZZ, MLTO, DLVY "department": "Head Office", "subdepartment": None, "street_name": "Musterstr.", "building_number": "1", "postcode": "12345", "town": "Berlin", "country": "DE", "country_subdivision": None, "lines": ["Line 1", "Line 2"], }, # "initiating_party": "John Doe", # optional name of the initiator of the payment, required by some banks. default to ''name' # "initiating_party_id": "DE26ZZZ00000000002", # optional, supplied by your bank or financial authority. default to 'creditor_id' } sepa.add_payment(payment) print(sepa.export(validate=True))
Credit transfer
Example:
from sepaxml import SepaTransfer import datetime, uuid config = { # "msg_id": "", # If your bank require a specific message_id format, you can set it up here. Default will be randomly generated with timestamp followed by a random value. "name": "Test von Testenstein", "IBAN": "NL50BANK1234567890", "BIC": "BANKNL2A", "batch": True, # For non-SEPA transfers, set "domestic" to True, necessary e.g. for CH/LI "currency": "EUR", # ISO 4217 "address": { # The address and all of its fields are optional but in some countries they are required "address_type": "ADDR", # valid: ADDR, PBOX, HOME, BIZZ, MLTO, DLVY "department": "Head Office", "subdepartment": None, "street_name": "Musterstr.", "building_number": "1", "postcode": "12345", "town": "Berlin", "country": "DE", "country_subdivision": None, "lines": ["Line 1", "Line 2"], }, } sepa = SepaTransfer(config, clean=True) payment = { "name": "Test von Testenstein", "IBAN": "NL50BANK1234567890", "BIC": "BANKNL2A", "amount": 5000, # in cents "execution_date": datetime.date.today() + datetime.timedelta(days=2), "description": "Test transaction", # "endtoend_id": str(uuid.uuid1()).replace("-", ""), # optional "address": { # The address and all of its fields are optional but in some countries they are required "address_type": "ADDR", # valid: ADDR, PBOX, HOME, BIZZ, MLTO, DLVY "department": "Head Office", "subdepartment": None, "street_name": "Musterstr.", "building_number": "1", "postcode": "12345", "town": "Berlin", "country": "DE", "country_subdivision": None, "lines": ["Line 1", "Line 2"], }, } sepa.add_payment(payment) print(sepa.export(validate=True))
Development
To run the included tests:
pip install -r requirements_dev.txt py.test tests
To automatically sort your Imports as required by CI:
pip install isort isort -rc .
Security
If you discover a security issue, please contact us at security@pretix.eu and see our Responsible Disclosure Policy further information.
Credits and License
Maintainer: Raphael Michel <mail@raphaelmichel.de>
This basically started as a properly packaged, python 3 tested version of the PySepaDD implementation that was released by The Congressus under the MIT license. Thanks for your work!
The source code is released under MIT license.
Not part of the MIT-licensed project are the XML schemas in the sepaxml/schemas/
folder which are copyrighted by the ISO 20022 organization but allowed to be reproduced
freely.