raphaelm / python-fints

Pure-python FinTS (formerly known as HBCI) implementation
https://pypi.python.org/pypi/fints
GNU Lesser General Public License v3.0
328 stars 81 forks source link

Error after entering the TAN number when sending multiple sepa direct debit transaction. #157

Closed Estartu closed 10 months ago

Estartu commented 10 months ago

Describe the bug Error after entering the TAN number when sending multiple sepa direct debit transaction.

In September the same script worked perfectly.

The Bank app reported the amount, the correct number of transactions and produced a tan.

Today it reported an error after I entered the generated TAN.

*Bank I tested this with Name of the bank: VR Bank Augsburg-Ostallgäu eG FinTS URL: https://fints2.atruvia.de/cgi-bin/hbciservlet

Expected behavior Confirmation of the successful operation.

Code required to reproduce

class FinTSConnection:

    def __init__(self):
        self.__client = None
        self.__account = None

    def setup_client(self):
        f = FinTS3PinTanClient(
                '72090000',  # Your bank's BLZ
                input("Bank NetKey:"),  # Your login name
                getpass.getpass('PIN:'),  # Your banking PIN
                'https://fints2.atruvia.de/cgi-bin/hbciservlet',
                mode=FinTSClientMode.INTERACTIVE,
                product_id='<vaild product id>'
        )
        minimal_interactive_cli_bootstrap(f)
        self.__client = f
        return f

   def change_account(self):
        accounts = self.client.get_sepa_accounts()
        if isinstance(accounts, NeedTANResponse):
            accounts = self.tan_challenge(accounts)

        print('Konto auswählen:')
        print('   IBAN                   Konto')
        number = 0
        for account in accounts:
            print('{1}: {0.iban} {0.accountnumber:12s}'.format(account, number + 1))
            number += 1

        selection = int(input('Welches Konto [1]:') or '1')

        self.__account = accounts[selection - 1]
        return self.__account

    def list_account_balances(self):
        accounts = self.client.get_sepa_accounts()
        if isinstance(accounts, NeedTANResponse):
            accounts = self.tan_challenge(accounts)

        print('Kontoliste:')
        print('IBAN                   Konto               Saldo')
        for account in accounts:
            balance = self.client.get_balance(account)
            print('{0.iban} {0.accountnumber:12s} {1.amount.amount:10.2f} € ({1.date})'.format(account, balance, ))

    def get_account_transactions(self, start: datetime.date = None, end: datetime.date = None):
        transactions = self.client.get_transactions(self.account, start_date=start, end_date=end)
        if isinstance(transactions, NeedTANResponse):
            transactions = self.tan_challenge(transactions)
        for transaction in transactions:
            yield transaction.data

    @property
    def client(self):
        if self.__client is None:
            self.setup_client()
        return self.__client

    @property
    def account(self):
        if self.__account is None:
            self.change_account()
        return self.__account

    @property
    def account_selected(self):
        return self.__account is not None

    def execute_direct_debit(self, pain_message, transactions, amount):
        with self.client:
            if self.client.init_tan_response:
                self.tan_challenge(self.client.init_tan_response.challenge)

            res = self.client.sepa_debit(
                    account=self.account,
                    pain_message=pain_message,
                    multiple=transactions > 1,
                    control_sum=Decimal(amount),
                    pain_descriptor='urn:iso:std:iso:20022:tech:xsd:pain.008.001.02'
            )

            if isinstance(res, NeedTANResponse):
                res = self.tan_challenge(res)

            return res.status

    def tan_challenge(self, res):
        print("Eine TAN wird benötigt!")
        print(res.challenge)

        tan = input('TAN:')
        return self.client.send_tan(res, tan)

Log output / error message

Traceback (most recent call last):
  File "/usr/local/bin/banking", line 8, in <module>
    sys.exit(main())
             ^^^^^^
  File "/usr/local/lib/python3.11/site-packages/acf_banking/banking.py", line 84, in main
    debit_member_fees(api_client=api_client, args=args)
  File "/usr/local/lib/python3.11/site-packages/acf_banking/member_fees.py", line 187, in debit_member_fees
    fints_connection.execute_direct_debit(pain_message, buchungen, gesamtbetrag)
  File "/usr/local/lib/python3.11/site-packages/acf_banking/fints.py", line 109, in execute_direct_debit
    res = self.tan_challenge(res)
          ^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/acf_banking/fints.py", line 118, in tan_challenge
    return self.client.send_tan(res, tan)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/fints/client.py", line 1266, in send_tan
    response = dialog.send(tan_seg)
               ^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/fints/dialog.py", line 156, in send
    self.client.process_response_message(self, response, internal_send=internal_send)
  File "/usr/local/lib/python3.11/site-packages/fints/client.py", line 241, in process_response_message
    self._process_response(dialog, segment, response)
  File "/usr/local/lib/python3.11/site-packages/fints/client.py", line 1293, in _process_response
    raise FinTSClientError("Error during dialog initialization, could not fetch BPD. Please check that you "
fints.exceptions.FinTSClientError: Error during dialog initialization, could not fetch BPD. Please check that you passed the correct bank identifier to the HBCI URL of the correct bank.

Additional context I can get the accounts and account balances. I can fetch the accounts transactions.

I tried your test script and made a simple test transaction. It worked but didn't required a tan.

Estartu commented 10 months ago

Was a Bank error.