From: Raphael Michel Date: Sun, 22 Dec 2019 17:59:55 +0000 (+0100) Subject: Update docs X-Git-Tag: v3.0.0~2^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F95%2Fhead;p=thirdparty%2Fpython-fints.git Update docs --- diff --git a/docs/debits.rst b/docs/debits.rst index 2038338..7829cea 100644 --- a/docs/debits.rst +++ b/docs/debits.rst @@ -44,18 +44,21 @@ You can easily generate XML using the ``sepaxml`` python library: pain_message = sepa.export().decode() client = FinTS3PinTanClient(...) + minimal_interactive_cli_bootstrap(client) - accounts = client.get_sepa_accounts() - account = accounts[0] + with client: + if client.init_tan_response: + print("A TAN is required", client.init_tan_response.challenge) - mechanisms = client.get_tan_mechanisms() - mechanism = mechanisms[client.get_current_tan_mechanism()] - if mechanism.description_required == fints.formals.DescriptionRequired.MUST: - usage_option, media = client.get_tan_media() + if getattr(client.init_tan_response, 'challenge_hhduc', None): + try: + terminal_flicker_unix(client.init_tan_response.challenge_hhduc) + except KeyboardInterrupt: + pass - client.set_tan_medium(media[0]) + tan = input('Please enter TAN:') + client.send_tan(client.init_tan_response, tan) - with client: res = client.sepa_debit( account=accounts[0], data=pain_message, @@ -65,7 +68,7 @@ You can easily generate XML using the ``sepaxml`` python library: ) if isinstance(res, NeedTANResponse): - print(res.challenge) + print("A TAN is required", res.challenge) if getattr(res, 'challenge_hhduc', None): try: diff --git a/docs/index.rst b/docs/index.rst index 1ace6bd..8746371 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -20,7 +20,9 @@ Library user documentation content transfers debits tested + upgrading_2_3 upgrading_1_2 + trouble Library developer documentation content diff --git a/docs/quickstart.rst b/docs/quickstart.rst index 966971c..cfd4912 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -24,12 +24,28 @@ of your bank. Logging in with a signature file or chip card is currently not sup product_id='Your product ID' ) +Since the implementation of PSD2, you will in almost all cases need to be ready to deal with TANs. For a quick start, +we included a minimal command-line utility to help choose a TAN method: -You can then execute commands using the client instance: +.. code-block:: python + + from fints.utils import minimal_interactive_cli_bootstrap + minimal_interactive_cli_bootstrap(f) + +You can then open up a real communication dialog to the bank with a ``with`` statement and issue commands: +commands using the client instance: .. code-block:: python - accounts = f.get_sepa_accounts() + with f: + # Since PSD2, a TAN might be needed for dialog initialization. Let's check if there is one required + if f.init_tan_response: + print("A TAN is required", f.init_tan_response.challenge) + tan = input('Please enter TAN:') + f.send_tan(f.init_tan_response, tan) + + # Fetch accounts + accounts = f.get_sepa_accounts() Go on to the next pages to find out what commands are supported! diff --git a/docs/reading.rst b/docs/reading.rst index e9b889e..e34b91d 100644 --- a/docs/reading.rst +++ b/docs/reading.rst @@ -1,6 +1,11 @@ Reading operations ================== +.. note:: + + Starting from version 3, **all of the methods on this page** can return a ``NeedTANResponse`` instead of actual + data if your bank requires a TAN. You should then enter a TAN, read our chapter :ref:`tans` to find out more. + Fetching your bank accounts --------------------------- diff --git a/docs/tans.rst b/docs/tans.rst index c45ef2f..d3fe836 100644 --- a/docs/tans.rst +++ b/docs/tans.rst @@ -30,6 +30,9 @@ If the ``description_required`` attribute for the TAN mechanism is :attr:`~fints you will need to get a list of TAN media with :func:`~fints.client.FinTS3PinTanClient.get_tan_media` and select the appropriate one with :func:`~fints.client.FinTS3PinTanClient.set_tan_medium`. +Have a look at the source code of :func:`~fints.utils.minimal_interactive_cli_bootstrap` for an example on how to +ask the user for these properties. + You may not change the active TAN mechanism or TAN medium within a standing dialog (see :ref:`client-dialog-state`). The selection of the active TAN mechanism/medium is stored with the persistent client data (see :ref:`client-state`). diff --git a/docs/tested.rst b/docs/tested.rst index 215ff9f..3a53e78 100644 --- a/docs/tested.rst +++ b/docs/tested.rst @@ -1,30 +1,27 @@ Tested banks ============ -The following banks have been tested with version 2.x of this library: +The following banks have been tested with version 3.x of this library: ======================================== ============ ======== ======== ====== Bank Transactions Holdings Transfer Debits and Balance ======================================== ============ ======== ======== ====== -GLS Bank eG Yes Yes Yes Postbank Yes -Triodos Bank Yes Yes -Volksbank Darmstadt-Südhessen Yes Yes -Deutsche Skatbank Yes Yes BBBank eG Yes Yes -MLP Banking AG Yes +Sparkasse Heidelberg Yes ======================================== ============ ======== ======== ====== Tested security functions ------------------------- +* ``921`` "pushTAN" +* ``930`` "mobile TAN" * ``942`` "mobile TAN" * ``962`` "Smart-TAN plus manuell" * ``972`` "Smart-TAN plus optisch" - Legacy results --------------- @@ -48,3 +45,18 @@ Volksbank (Fiducia) Yes Wüstenrot Yes 1822direkt Yes Yes ======================================== ============ ======== ======== ====== + +The following banks have been tested with the old version 2.x of this library: + +======================================== ============ ======== ======== ====== +Bank Transactions Holdings Transfer Debits + and Balance +======================================== ============ ======== ======== ====== +GLS Bank eG Yes Yes Yes +Postbank Yes +Triodos Bank Yes Yes +Volksbank Darmstadt-Südhessen Yes Yes +Deutsche Skatbank Yes Yes +BBBank eG Yes Yes +MLP Banking AG Yes +======================================== ============ ======== ======== ====== diff --git a/docs/transfers.rst b/docs/transfers.rst index 9e0447b..28d6a0a 100644 --- a/docs/transfers.rst +++ b/docs/transfers.rst @@ -29,18 +29,21 @@ Full example .. code-block:: python client = FinTS3PinTanClient(...) + minimal_interactive_cli_bootstrap(client) - accounts = client.get_sepa_accounts() - account = accounts[0] + with client: + if client.init_tan_response: + print("A TAN is required", client.init_tan_response.challenge) - mechanisms = client.get_tan_mechanisms() - mechanism = mechanisms[client.get_current_tan_mechanism()] - if mechanism.description_required == fints.formals.DescriptionRequired.MUST: - usage_option, media = client.get_tan_media() + if getattr(client.init_tan_response, 'challenge_hhduc', None): + try: + terminal_flicker_unix(client.init_tan_response.challenge_hhduc) + except KeyboardInterrupt: + pass - client.set_tan_medium(media[0]) + tan = input('Please enter TAN:') + client.send_tan(client.init_tan_response, tan) - with client: res = client.simple_sepa_transfer( account=accounts[0], iban='DE12345', @@ -53,7 +56,7 @@ Full example ) if isinstance(res, NeedTANResponse): - print(res.challenge) + print("A TAN is required", res.challenge) if getattr(res, 'challenge_hhduc', None): try: diff --git a/docs/trouble.rst b/docs/trouble.rst new file mode 100644 index 0000000..264123b --- /dev/null +++ b/docs/trouble.rst @@ -0,0 +1,173 @@ +Troubleshooting and bug reporting +================================= + +The FinTS specification is long and complicated and in many parts leaves things open to interpretation -- or sometimes +implementors interpret things differently even though they're not really open to interpretation. This is valid for us, +but also for the banks. Making the library work with many diffrent banks is hard, and often impossible without access +to a test account. Therefore, we ask you for patience when reporting issues with different banks -- and you need to be +ready that we might not be able to help you because we do not have the time or bank account required to dig deeper. + +Therefore, if you run into trouble with this library, you first need to ask yourself a very important question: **Is it +me or the library?** To answer this question for most cases, we have attached a script below, that we ask you to use +to try the affected feature of the library in a well-documented way. Apart from changing the arguments (i.e. your bank's +parameters and your credentials) at the top, we ask you **not to make any modifications**. Pasting this bit by bit into +a Jupyter notebook **is a modification**. If your issue does not include information as to whether the script below works +or does not work for your bank, **we will close your issue without further comment.** + +**If the script below does not work for you**, there is probably a compatibility issue between this library and your +bank. Feel free to open an issue, but make sure the issue title includes the name of the bank and the text includes +what operations specifically fail. + +**If the script below does work for you**, there is probably something wrong with your usage of the library or our +documentation. Feel free to open an issue, but **include full working example code** that is necessary to reproduce +the problem. + +.. note:: Before posting anything on GitHub, make sure it does not contain your username, PIN, IBAN, or similarly sensitive data. + +.. code-block:: python + + import datetime + import getpass + import logging + import sys + from decimal import Decimal + + from fints.client import FinTS3PinTanClient, NeedTANResponse, FinTSUnsupportedOperation + from fints.hhd.flicker import terminal_flicker_unix + from fints.utils import minimal_interactive_cli_bootstrap + + logging.basicConfig(level=logging.DEBUG) + + client_args = ( + 'REPLACEME', # BLZ + 'REPLACEME', # USER + getpass.getpass('PIN: '), + 'REPLACEME' # ENDPOINT + ) + + f = FinTS3PinTanClient(*client_args) + minimal_interactive_cli_bootstrap(f) + + + def ask_for_tan(response): + print("A TAN is required") + print(response.challenge) + if getattr(response, 'challenge_hhduc', None): + try: + terminal_flicker_unix(response.challenge_hhduc) + except KeyboardInterrupt: + pass + tan = input('Please enter TAN:') + return f.send_tan(response, tan) + + + # Open the actual dialog + with f: + # Since PSD2, a TAN might be needed for dialog initialization. Let's check if there is one required + if f.init_tan_response: + ask_for_tan(f.init_tan_response) + + # Fetch accounts + accounts = f.get_sepa_accounts() + if isinstance(accounts, NeedTANResponse): + accounts = ask_for_tan(accounts) + if len(accounts) == 1: + account = accounts[0] + else: + print("Multiple accounts available, choose one") + for i, mm in enumerate(accounts): + print(i, mm.iban) + choice = input("Choice: ").strip() + account = accounts[int(choice)] + + # Test pausing and resuming the dialog + dialog_data = f.pause_dialog() + + client_data = f.deconstruct(including_private=True) + + f = FinTS3PinTanClient(*client_args, from_data=client_data) + with f.resume_dialog(dialog_data): + while True: + operations = [ + "End dialog", + "Fetch transactions of the last 30 days", + "Fetch transactions of the last 120 days", + "Fetch transactions XML of the last 30 days", + "Fetch transactions XML of the last 120 days", + "Fetch information", + "Fetch balance", + "Fetch holdings", + "Fetch scheduled debits", + "Fetch status protocol", + "Make a simple transfer" + ] + + print("Choose an operation") + for i, o in enumerate(operations): + print(i, o) + choice = int(input("Choice: ").strip()) + try: + if choice == 0: + break + elif choice == 1: + res = f.get_transactions(account, datetime.date.today() - datetime.timedelta(days=30), + datetime.date.today()) + while isinstance(res, NeedTANResponse): + res = ask_for_tan(res) + print("Found", len(res), "transactions") + elif choice == 2: + res = f.get_transactions(account, datetime.date.today() - datetime.timedelta(days=120), + datetime.date.today()) + while isinstance(res, NeedTANResponse): + res = ask_for_tan(res) + print("Found", len(res), "transactions") + elif choice == 3: + res = f.get_transactions_xml(account, datetime.date.today() - datetime.timedelta(days=30), + datetime.date.today()) + while isinstance(res, NeedTANResponse): + res = ask_for_tan(res) + print("Found", len(res[0]) + len(res[1]), "XML documents") + elif choice == 4: + res = f.get_transactions_xml(account, datetime.date.today() - datetime.timedelta(days=120), + datetime.date.today()) + while isinstance(res, NeedTANResponse): + res = ask_for_tan(res) + print("Found", len(res[0]) + len(res[1]), "XML documents") + elif choice == 5: + print(f.get_information()) + elif choice == 6: + res = f.get_balance(account) + while isinstance(res, NeedTANResponse): + res = ask_for_tan(res) + print(res) + elif choice == 7: + res = f.get_holdings(account) + while isinstance(res, NeedTANResponse): + res = ask_for_tan(res) + print(res) + elif choice == 8: + res = f.get_scheduled_debits(account) + while isinstance(res, NeedTANResponse): + res = ask_for_tan(res) + print(res) + elif choice == 9: + res = f.get_status_protocol() + while isinstance(res, NeedTANResponse): + res = ask_for_tan(res) + print(res) + elif choice == 10: + res = f.simple_sepa_transfer( + account=accounts[0], + iban=input('Target IBAN:'), + bic=input('Target BIC:'), + amount=Decimal(input('Amount:')), + recipient_name=input('Recipient name:'), + account_name=input('Your name:'), + reason=input('Reason:'), + endtoend_id='NOTPROVIDED', + ) + + if isinstance(res, NeedTANResponse): + ask_for_tan(res) + except FinTSUnsupportedOperation as e: + print("This operation is not supported by this bank:", e) \ No newline at end of file diff --git a/docs/upgrading_1_2.rst b/docs/upgrading_1_2.rst index d4f51b6..6342a73 100644 --- a/docs/upgrading_1_2.rst +++ b/docs/upgrading_1_2.rst @@ -1,5 +1,5 @@ -Upgrading from python-fints 1.x -=============================== +Upgrading from python-fints 1.x to 2.x +====================================== This library has seen a major rewrite in version 2.0 and the API has changed in a lot of places. These are the most important changes to know: diff --git a/docs/upgrading_2_3.rst b/docs/upgrading_2_3.rst new file mode 100644 index 0000000..10d308a --- /dev/null +++ b/docs/upgrading_2_3.rst @@ -0,0 +1,15 @@ +Upgrading from python-fints 2.x to 3.x +====================================== + +Release 3.0 of this library was made to adjust to changes made by the banks as part of their PSD2 implementation +in 2019. Here's what you should know when porting your code: + +* A TAN can now be required for dialog initialization. In this case, ``client.init_tan_response`` will contain a + ``NeedTANResponse``. + +* Basically every method of the client class can now return a ``NeedTANResponse``, so you should always expect this + case and handle it gracefully. + +* Since everything can require a TAN, everything requires a standing dialog. Issuing interactive commands outside of a + ``with client:`` statement is now deprecated. It still might work in very few cases, so we didn't disable it, but we + do not support it any longer. This affects you mostly when you work with this on a Python REPL or e.g. in a Notebook.