Creating SEPA debits

You can submit a SEPA debit XML file to the bank with the sepa_debit method:

class fints.client.FinTS3Client(bank_identifier, user_id, customer_id=None, from_data: bytes = None, product_id=None, product_version='4.0.0', mode=<FinTSClientMode.INTERACTIVE: 'interactive'>)[source]
sepa_debit(account: fints.models.SEPAAccount, pain_message: str, multiple=False, cor1=False, control_sum=None, currency='EUR', book_as_single=False, pain_descriptor='urn:iso:std:iso:20022:tech:xsd:pain.008.003.01')[source]

Custom SEPA debit.

Parameters:
  • account – SEPAAccount to send the debit from.
  • pain_message – SEPA PAIN message containing the debit details.
  • multiple – Whether this message contains multiple debits.
  • cor1 – Whether to use COR1 debit (lead time reduced to 1 day)
  • control_sum – Sum of all debits (required if there are multiple)
  • currency – Debit currency
  • book_as_single – Kindly ask the bank to put multiple transactions as separate lines on the bank statement (defaults to False)
  • pain_descriptor – URN of the PAIN message schema used. Defaults to urn:iso:std:iso:20022:tech:xsd:pain.008.003.01.
Returns:

Returns either a NeedRetryResponse or TransactionResponse (with data[‘task_id’] set, if available)

You should then enter a TAN, read our chapter Working with TANs to find out more.

Full example

You can easily generate XML using the sepaxml python library:

from sepaxml import SepaDD

config = {
    "name": "Test Company",
    "IBAN": "DE12345",
    "BIC": "BIC12345",
    "batch": False,
    "creditor_id": "TESTCORPID",
    "currency": "EUR",
}

sepa = SepaDD(config, schema="pain.008.002.02")
sepa.add_payment({
    "name": "Customer",
    "IBAN": "DE12345",
    "BIC": "BIC12345",
    "amount": 100,
    "type": "OOFF",  # FRST, RCUR, OOFF, FNAL
    "collection_date": datetime.date.today() + datetime.timedelta(days=3),
    "mandate_id": "FINTSTEST1",
    "mandate_date": datetime.date(2018, 7, 26),
    "description": "FinTS Test transaction",
})
pain_message = sepa.export().decode()

client = FinTS3PinTanClient(...)
minimal_interactive_cli_bootstrap(client)

with client:
    if client.init_tan_response:
        print("A TAN is required", client.init_tan_response.challenge)

        if getattr(client.init_tan_response, 'challenge_hhduc', None):
            try:
                terminal_flicker_unix(client.init_tan_response.challenge_hhduc)
            except KeyboardInterrupt:
                pass

        tan = input('Please enter TAN:')
        client.send_tan(client.init_tan_response, tan)

    res = client.sepa_debit(
        account=accounts[0],
        data=pain_message,
        multiple=False,
        control_sum=Decimal('1.00'),
        pain_descriptor='urn:iso:std:iso:20022:tech:xsd:pain.008.002.02'
    )

    if isinstance(res, NeedTANResponse):
        print("A TAN is required", res.challenge)

        if getattr(res, 'challenge_hhduc', None):
            try:
                terminal_flicker_unix(res.challenge_hhduc)
            except KeyboardInterrupt:
                pass

        tan = input('Please enter TAN:')
        res = client.send_tan(res, tan)

    print(res.status)
    print(res.responses)