From: Raphael Michel Date: Thu, 26 Jul 2018 20:25:50 +0000 (+0200) Subject: Add docs X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fheads%2Fsepa-transfers;p=thirdparty%2Fpython-fints.git Add docs --- diff --git a/README.md b/README.md index 9b565f3..0b2acdd 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,9 @@ PyFinTS This is a pure-python implementation of FinTS (formerly known as HBCI), a online-banking protocol commonly supported by German banks. + +[Read our documentation for more info](https://python-fints.readthedocs.io) + Limitations ----------- @@ -13,72 +16,14 @@ Limitations * Fetching bank statements * Fetching balances * Fetching holdings - * SEPA transfers (only with required TAN and with specific TAN methods) + * SEPA transfers and debits (only with required TAN and with specific TAN methods) * Supports Python 3.4+ -Banks tested: - -* GLS Bank eG (statements, transfers) -* Triodos Bank (statements) -* BBBank eG (statements) -* Postbank (statements) -* [1822direkt](https://www.1822direkt.de/service/zugang-zum-konto/softwarebanking-mit-hbci/) (statements, holdings) -* Sparkasse (statements) -* Ing-Diba (statements) -* CortalConsors (statements, holdings) -* DKB (statements) -* NIBC Direct (statements) -* Wüstenrot (statements) -* comdirect (holdings) -* Volksbank using Fiducia IT (statements) -* netbank (statements) - -Usage ------ - -```python -import logging -from datetime import date -import getpass -from fints.client import FinTS3PinTanClient - -logging.basicConfig(level=logging.DEBUG) -f = FinTS3PinTanClient( - '123456789', # Your bank's BLZ - 'myusername', - getpass.getpass('PIN:'), - 'https://mybank.com/…' # endpoint, e.g.: https://hbci-pintan.gad.de/cgi-bin/hbciservlet - # for German banks, see http://www.hbci-zka.de/institute/institut_auswahl.htm -) - -accounts = f.get_sepa_accounts() -print(accounts) -# [SEPAAccount(iban='DE12345678901234567890', bic='ABCDEFGH1DEF', accountnumber='123456790', subaccount='', -# blz='123456789')] - -statement = f.get_statement(accounts[0], date(2016, 12, 1), date.today()) -print([t.data for t in statement]) -# The statement is a list of transaction objects as parsed by the mt940 parser, see -# https://mt940.readthedocs.io/en/latest/mt940.html#mt940.models.Transaction -# for documentation. Most information is contained in a dict accessible via their -# ``data`` property - -# for retrieving the holdings of an account: -holdings = f.get_holdings(accounts[0]) -# holdings contains a list of namedtuple values containing ISIN, name, -# market_value, pieces, total_value and valuation_date as parsed from -# the MT535 message. -``` - Credits and License ------------------- Maintainer: Raphael Michel -Big thanks to Daniel Nowak for implementing outgoing transfers. +Big thanks to: Daniel Nowak, Patrick Braune, Mathias Dalheimer, Christopher Grebs, Markus Schindler License: LGPL - -This is a quite close port of the [fints-hbci-php](https://github.com/mschindler83/fints-hbci-php) -implementation that was released by Markus Schindler under the MIT license. -Thanks for your work! diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 0000000..69fa449 --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1 @@ +_build/ diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..905f376 --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,223 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = _build + +# User-friendly check for sphinx-build +ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) + $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don\'t have Sphinx installed, grab it from http://sphinx-doc.org/) +endif + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " applehelp to make an Apple Help Book" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " epub3 to make an epub3" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " xml to make Docutils-native XML files" + @echo " pseudoxml to make pseudoxml-XML files for display purposes" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + @echo " coverage to run coverage check of the documentation (if enabled)" + +.PHONY: clean +clean: + rm -rf $(BUILDDIR)/* + +.PHONY: html +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +.PHONY: dirhtml +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +.PHONY: singlehtml +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +.PHONY: pickle +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +.PHONY: json +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +.PHONY: htmlhelp +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +.PHONY: qthelp +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/django-i18nfield.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/django-i18nfield.qhc" + +.PHONY: applehelp +applehelp: + $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp + @echo + @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." + @echo "N.B. You won't be able to view it unless you put it in" \ + "~/Library/Documentation/Help or install it in your application" \ + "bundle." + +.PHONY: devhelp +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/django-i18nfield" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/django-i18nfield" + @echo "# devhelp" + +.PHONY: epub +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +.PHONY: epub3 +epub3: + $(SPHINXBUILD) -b epub3 $(ALLSPHINXOPTS) $(BUILDDIR)/epub3 + @echo + @echo "Build finished. The epub3 file is in $(BUILDDIR)/epub3." + +.PHONY: latex +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +.PHONY: latexpdf +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +.PHONY: latexpdfja +latexpdfja: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through platex and dvipdfmx..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +.PHONY: text +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +.PHONY: man +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +.PHONY: texinfo +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +.PHONY: info +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +.PHONY: gettext +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +.PHONY: changes +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +.PHONY: linkcheck +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +.PHONY: doctest +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." + +.PHONY: coverage +coverage: + $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage + @echo "Testing of coverage in the sources finished, look at the " \ + "results in $(BUILDDIR)/coverage/python.txt." + +.PHONY: xml +xml: + $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml + @echo + @echo "Build finished. The XML files are in $(BUILDDIR)/xml." + +.PHONY: pseudoxml +pseudoxml: + $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml + @echo + @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 0000000..316782f --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,387 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# python-fints documentation build configuration file, created by +# sphinx-quickstart on Sun Apr 3 00:09:59 2016. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import os +import sys + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +sys.path.insert(0, os.path.abspath('..')) + +try: + from fints import version +except ImportError: + version = '?' + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +# needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.intersphinx', + 'sphinx.ext.todo', + 'sphinx.ext.doctest', +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The encoding of source files. +# source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = 'python-fints' +copyright = '2018, Raphael Michel' +author = 'Raphael Michel' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '.'.join(version.split('.')[:2]) +# The full version, including alpha/beta/rc tags. +release = version + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +# today = '' +# Else, today_fmt is used as the format for a strftime call. +# today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This patterns also effect to html_static_path and html_extra_path +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] + +# The reST default role (used for this markup: `text`) to use for all +# documents. +# default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +# add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +# add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +# show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +# modindex_common_prefix = [] + +# If true, keep warnings as "system message" paragraphs in the built documents. +# keep_warnings = False + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = True + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'alabaster' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +html_theme_options = { + 'description': 'FinTS client library for Python', + 'github_user': 'raphaelm', + 'github_repo': 'python-fints', + 'github_button': True, + 'github_banner': False, + 'travis_button': True, + 'pre_bg': '#FFF6E5', + 'note_bg': '#E5ECD1', + 'note_border': '#BFCF8C', + 'body_text': '#482C0A', + 'sidebar_text': '#49443E', + 'sidebar_header': '#4B4032', +} + +# Add any paths that contain custom themes here, relative to this directory. +# html_theme_path = [] + +# The name for this set of Sphinx documents. +# " v documentation" by default. +# html_title = 'python-fints v0.0.1' + +# A shorter title for the navigation bar. Default is the same as html_title. +# html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +# html_logo = None + +# The name of an image file (relative to this directory) to use as a favicon of +# the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +# html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +# html_extra_path = [] + +# If not None, a 'Last updated on:' timestamp is inserted at every page +# bottom, using the given strftime format. +# The empty string is equivalent to '%b %d, %Y'. +# html_last_updated_fmt = None + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +# html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +html_sidebars = { + '**': [ + 'about.html', 'navigation.html', 'searchbox.html', + ] +} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +# html_additional_pages = {} + +# If false, no module index is generated. +# html_domain_indices = True + +# If false, no index is generated. +# html_use_index = True + +# If true, the index is split into individual pages for each letter. +# html_split_index = False + +# If true, links to the reST sources are added to the pages. +# html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +# html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +# html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +# html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +# html_file_suffix = None + +# Language to be used for generating the HTML full-text search index. +# Sphinx supports the following languages: +# 'da', 'de', 'en', 'es', 'fi', 'fr', 'h', 'it', 'ja' +# 'nl', 'no', 'pt', 'ro', 'r', 'sv', 'tr', 'zh' +# html_search_language = 'en' + +# A dictionary with options for the search language support, empty by default. +# 'ja' uses this config value. +# 'zh' user can custom change `jieba` dictionary path. +# html_search_options = {'type': 'default'} + +# The name of a javascript file (relative to the configuration directory) that +# implements a search results scorer. If empty, the default will be used. +# html_search_scorer = 'scorer.js' + +# Output file base name for HTML help builder. +htmlhelp_basename = 'python-fintsdoc' + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + # 'papersize': 'letterpaper', + + # The font size ('10pt', '11pt' or '12pt'). + # 'pointsize': '10pt', + + # Additional stuff for the LaTeX preamble. + # 'preamble': '', + + # Latex figure (float) alignment + # 'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'pythonfints.tex', 'python-fints Documentation', + 'Raphael Michel', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +# latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +# latex_use_parts = False + +# If true, show page references after internal links. +# latex_show_pagerefs = False + +# If true, show URL addresses after external links. +# latex_show_urls = False + +# Documents to append as an appendix to all manuals. +# latex_appendices = [] + +# If false, no module index is generated. +# latex_domain_indices = True + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'python-fints', 'python-fints Documentation', + [author], 1) +] + +# If true, show URL addresses after external links. +# man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'python-fints', 'python-fonts Documentation', + author, 'python-fints', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +# texinfo_appendices = [] + +# If false, no module index is generated. +# texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +# texinfo_show_urls = 'footnote' + +# If true, do not generate a @detailmenu in the "Top" node's menu. +# texinfo_no_detailmenu = False + + +# -- Options for Epub output ---------------------------------------------- + +# Bibliographic Dublin Core info. +epub_title = project +epub_author = author +epub_publisher = author +epub_copyright = copyright + +# The basename for the epub file. It defaults to the project name. +# epub_basename = project + +# The HTML theme for the epub output. Since the default themes are not +# optimized for small screen space, using the same theme for HTML and epub +# output is usually not wise. This defaults to 'epub', a theme designed to save +# visual space. +# epub_theme = 'epub' + +# The language of the text. It defaults to the language option +# or 'en' if the language is not set. +# epub_language = '' + +# The scheme of the identifier. Typical schemes are ISBN or URL. +# epub_scheme = '' + +# The unique identifier of the text. This can be a ISBN number +# or the project homepage. +# epub_identifier = '' + +# A unique identification for the text. +# epub_uid = '' + +# A tuple containing the cover image and cover page html template filenames. +# epub_cover = () + +# A sequence of (type, uri, title) tuples for the guide element of content.opf. +# epub_guide = () + +# HTML files that should be inserted before the pages created by sphinx. +# The format is a list of tuples containing the path and title. +# epub_pre_files = [] + +# HTML files that should be inserted after the pages created by sphinx. +# The format is a list of tuples containing the path and title. +# epub_post_files = [] + +# A list of files that should not be packed into the epub file. +epub_exclude_files = ['search.html'] + +# The depth of the table of contents in toc.ncx. +# epub_tocdepth = 3 + +# Allow duplicate toc entries. +# epub_tocdup = True + +# Choose between 'default' and 'includehidden'. +# epub_tocscope = 'default' + +# Fix unsupported image types using the Pillow. +# epub_fix_images = False + +# Scale large images. +# epub_max_image_width = 0 + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +# epub_show_urls = 'inline' + +# If false, no index is generated. +# epub_use_index = True + + +# Example configuration for intersphinx: refer to the Python standard library. +intersphinx_mapping = {'https://docs.python.org/': None} diff --git a/docs/debits.rst b/docs/debits.rst new file mode 100644 index 0000000..acf2dbc --- /dev/null +++ b/docs/debits.rst @@ -0,0 +1,41 @@ +Creating SEPA debits +==================== + +You can submit a SEPA debit XML file to the bank with the ``start_sepa_debit`` method: + +.. autoclass:: fints.client.FinTS3Client + :members: start_sepa_debit + +You should then enter a TAN, read our chapter :ref:`tans` to find out more. + +Example +------- + +You can easily generate XML using the ``sepaxml`` python library: + +.. code-block:: python + + 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() diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 0000000..6fc5234 --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,21 @@ +FinTS client library +==================== + +.. image:: https://img.shields.io/pypi/v/python-fints.svg + :target: https://pypi.python.org/pypi/python-fints + +This is a pure-python implementation of FinTS (formerly known as HBCI), a +online-banking protocol commonly supported by German banks. + +Documentation content +--------------------- + +.. toctree:: + :maxdepth: 2 + + quickstart + reading + tans + transfers + debits + tested diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 0000000..3cabb4e --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,272 @@ +@ECHO OFF + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set BUILDDIR=_build +set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . +set I18NSPHINXOPTS=%SPHINXOPTS% . +if NOT "%PAPER%" == "" ( + set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% + set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% +) + +if "%1" == "" goto help + +if "%1" == "help" ( + :help + echo.Please use `make ^` where ^ is one of + echo. html to make standalone HTML files + echo. dirhtml to make HTML files named index.html in directories + echo. singlehtml to make a single large HTML file + echo. pickle to make pickle files + echo. json to make JSON files + echo. htmlhelp to make HTML files and a HTML help project + echo. qthelp to make HTML files and a qthelp project + echo. devhelp to make HTML files and a Devhelp project + echo. epub to make an epub + echo. epub3 to make an epub3 + echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter + echo. text to make text files + echo. man to make manual pages + echo. texinfo to make Texinfo files + echo. gettext to make PO message catalogs + echo. changes to make an overview over all changed/added/deprecated items + echo. xml to make Docutils-native XML files + echo. pseudoxml to make pseudoxml-XML files for display purposes + echo. linkcheck to check all external links for integrity + echo. doctest to run all doctests embedded in the documentation if enabled + echo. coverage to run coverage check of the documentation if enabled + goto end +) + +if "%1" == "clean" ( + for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i + del /q /s %BUILDDIR%\* + goto end +) + + +REM Check if sphinx-build is available and fallback to Python version if any +%SPHINXBUILD% 1>NUL 2>NUL +if errorlevel 9009 goto sphinx_python +goto sphinx_ok + +:sphinx_python + +set SPHINXBUILD=python -m sphinx.__init__ +%SPHINXBUILD% 2> nul +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +:sphinx_ok + + +if "%1" == "html" ( + %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/html. + goto end +) + +if "%1" == "dirhtml" ( + %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. + goto end +) + +if "%1" == "singlehtml" ( + %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. + goto end +) + +if "%1" == "pickle" ( + %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the pickle files. + goto end +) + +if "%1" == "json" ( + %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the JSON files. + goto end +) + +if "%1" == "htmlhelp" ( + %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run HTML Help Workshop with the ^ +.hhp project file in %BUILDDIR%/htmlhelp. + goto end +) + +if "%1" == "qthelp" ( + %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run "qcollectiongenerator" with the ^ +.qhcp project file in %BUILDDIR%/qthelp, like this: + echo.^> qcollectiongenerator %BUILDDIR%\qthelp\django-i18nfield.qhcp + echo.To view the help file: + echo.^> assistant -collectionFile %BUILDDIR%\qthelp\django-i18nfield.ghc + goto end +) + +if "%1" == "devhelp" ( + %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. + goto end +) + +if "%1" == "epub" ( + %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The epub file is in %BUILDDIR%/epub. + goto end +) + +if "%1" == "epub3" ( + %SPHINXBUILD% -b epub3 %ALLSPHINXOPTS% %BUILDDIR%/epub3 + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The epub3 file is in %BUILDDIR%/epub3. + goto end +) + +if "%1" == "latex" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "latexpdf" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + cd %BUILDDIR%/latex + make all-pdf + cd %~dp0 + echo. + echo.Build finished; the PDF files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "latexpdfja" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + cd %BUILDDIR%/latex + make all-pdf-ja + cd %~dp0 + echo. + echo.Build finished; the PDF files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "text" ( + %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The text files are in %BUILDDIR%/text. + goto end +) + +if "%1" == "man" ( + %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The manual pages are in %BUILDDIR%/man. + goto end +) + +if "%1" == "texinfo" ( + %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. + goto end +) + +if "%1" == "gettext" ( + %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The message catalogs are in %BUILDDIR%/locale. + goto end +) + +if "%1" == "changes" ( + %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes + if errorlevel 1 exit /b 1 + echo. + echo.The overview file is in %BUILDDIR%/changes. + goto end +) + +if "%1" == "linkcheck" ( + %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck + if errorlevel 1 exit /b 1 + echo. + echo.Link check complete; look for any errors in the above output ^ +or in %BUILDDIR%/linkcheck/output.txt. + goto end +) + +if "%1" == "doctest" ( + %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest + if errorlevel 1 exit /b 1 + echo. + echo.Testing of doctests in the sources finished, look at the ^ +results in %BUILDDIR%/doctest/output.txt. + goto end +) + +if "%1" == "coverage" ( + %SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage + if errorlevel 1 exit /b 1 + echo. + echo.Testing of coverage in the sources finished, look at the ^ +results in %BUILDDIR%/coverage/python.txt. + goto end +) + +if "%1" == "xml" ( + %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The XML files are in %BUILDDIR%/xml. + goto end +) + +if "%1" == "pseudoxml" ( + %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. + goto end +) + +:end diff --git a/docs/quickstart.rst b/docs/quickstart.rst new file mode 100644 index 0000000..513c56e --- /dev/null +++ b/docs/quickstart.rst @@ -0,0 +1,33 @@ +Getting started +=============== + +First of all, you need to install the library:: + + $ pip3 install fints + +Then, you can initialize a FinTS client by providing your bank's BLZ, your username and PIN as well as the HBCI endpoint +of your bank. Logging in with a signature file or chip card is currently not supported. For example: + +.. code-block:: python + + import logging + from datetime import date + import getpass + from fints.client import FinTS3PinTanClient + + logging.basicConfig(level=logging.DEBUG) + f = FinTS3PinTanClient( + '123456789', # Your bank's BLZ + 'myusername', # Your login name + getpass.getpass('PIN:'), # Your banking PIN + 'https://hbci-pintan.gad.de/cgi-bin/hbciservlet' + ) + + +You can then execute commands using the client instance: + +.. code-block:: python + + accounts = f.get_sepa_accounts() + +Go on to the next pages to find out what commands are supported! \ No newline at end of file diff --git a/docs/reading.rst b/docs/reading.rst new file mode 100644 index 0000000..3355c5b --- /dev/null +++ b/docs/reading.rst @@ -0,0 +1,58 @@ +Reading operations +================== + +Fetching your bank accounts +--------------------------- + +The most simple method allows you to get all bank accounts that your user has access to: + +.. autoclass:: fints.client.FinTS3Client + :members: get_sepa_accounts + +This method will return a list of named tuples of the following type: + +.. autoclass:: fints.models.SEPAAccount + +You will need this account object for many further operations to show which account you want to operate on. + + +Fetching account balances +------------------------- + +You can fetch the current balance of an account with the ``get_balance`` operation. + +.. autoclass:: fints.client.FinTS3Client + :members: get_balance + +This method will return a list of ``Balance`` objects from the ``mt-940`` library. You can find more information +in `balance `_. + + +Reading account statements +-------------------------- + +You can fetch the banking statement of an account within a certain timeframe with the ``get_statement`` +operation. + +.. autoclass:: fints.client.FinTS3Client + :members: get_statement + +This method will return a list of ``Transaction`` objects from the ``mt-940`` library. You can find more information +in `their documentation`_. + + +Fetching holdings +----------------- + +You can fetch the holdings of an account with the ``get_holdings`` method: + +.. autoclass:: fints.client.FinTS3Client + :members: get_holdings + +This method will return a list of ``Holding`` objects: + +.. autoclass:: fints.models.Holding + + +.. _their documentation: https://mt940.readthedocs.io/en/latest/mt940.html#mt940.models.Transaction +.. _balance: https://mt940.readthedocs.io/en/latest/mt940.html#mt940.models.Balance diff --git a/docs/tans.rst b/docs/tans.rst new file mode 100644 index 0000000..729d794 --- /dev/null +++ b/docs/tans.rst @@ -0,0 +1,79 @@ +.. _tans: + +Working with TANs +================= + +TAN methods +----------- + +Before doing any operations involving TANs, you should get a list of supported TAN methods and select the TAN method +you want to use: + +.. code-block:: python + + methods = client.get_tan_methods() + method = methods[0] + +The returned values have a subtype ``fints.models.TANMethod``, with varying parameters depending on the version +used by the bank: + +.. autoclass:: fints.client.FinTS3Client + :members: get_tan_methods + +.. autoclass:: fints.models.TANMethod5 + +.. autoclass:: fints.models.TANMethod6 + +.. warning:: If the ``description_required`` attribute is ``2``, you will need to get the description of the TAN medium + you want to use and pass it as ``tan_description`` to some operations. You can send a request for this + information with the ``client.get_tan_description()`` method call. Currently, this returns an unparsed + response from the bank. In the future, we will probably return a structured result here. + +TAN challenges +-------------- + +You should then pass the chosen ``TANMethod`` object to your operation, e.g. ``start_simple_sepa_transfer``. +If a TAN is required, this operation will return a ``TANChallenge``, again depending on the version used by the bank. + +.. autoclass:: fints.models.TANChallenge3 + +.. autoclass:: fints.models.TANChallenge4 + +.. autoclass:: fints.models.TANChallenge5 + +.. autoclass:: fints.models.TANChallenge6 + +The ``challenge`` attribute will contain human-readable instructions on how to proceed. + +Flicker-Code / optiTAN +---------------------- + +If you want to use chipTAN with an optical TAN device, we provide utilities to print the flicker code on +a unix terminal. Just pass the ``result.challenge_hhd_uc`` value to this method: + +.. autofunction:: fints.hhd.flicker.terminal_flicker_unix + +You should probably catch for ``KeyboardInterrupts`` to allow the user to abort the displaying and to continue +with the TAN: + +.. code-block:: python + + try: + terminal_flicker_unix(result.challenge_hhd_uc) + except KeyboardInterrupt: + pass + +Sending the TAN +--------------- + +Once obtained the TAN, you can send it with the ``send_tan`` client method: + +.. autoclass:: fints.client.FinTS3Client + :members: send_tan + +For example: + +.. code-block:: python + + tan = input('Bitte die TAN eingeben.') + result = client.send_tan(result, tan) diff --git a/docs/tested.rst b/docs/tested.rst new file mode 100644 index 0000000..1b10370 --- /dev/null +++ b/docs/tested.rst @@ -0,0 +1,23 @@ +Tested banks +============ + +The following libraries have been tested with this library: + +======================================== ============ ======== ======== ====== +Bank Statements Holdings Transfer Debits +======================================== ============ ======== ======== ====== +BBBank eG Yes Yes +CortalConsors Yes Yes +comdirect Yes +GLS Bank eG Yes Yes Yes +DKB Yes +ING DiBa Yes +netbank Xes +NIBC Direct Yes +Postbank Yes +Sparkasse Yes +Triodos Bank Yes +Volksbank (Fiducia) Yes +Wüstenrot Yes +1822direkt Yes Yes +======================================== ============ ======== ======== ====== diff --git a/docs/transfers.rst b/docs/transfers.rst new file mode 100644 index 0000000..da28c5c --- /dev/null +++ b/docs/transfers.rst @@ -0,0 +1,57 @@ +Sending SEPA transfers +====================== + +Simple mode +----------- + +You can create a simple SEPA transfer using this convenient client method: + +.. autoclass:: fints.client.FinTS3Client + :members: start_simple_sepa_transfer + +You should then enter a TAN, read our chapter :ref:`tans` to find out more. + +Advanced mode +------------- + +If you want to use advanced methods, you can supply your own SEPA XML: + +.. autoclass:: fints.client.FinTS3Client + :members: start_sepa_transfer + +Example +------- + +.. code-block:: python + + client = FinTS3PinTanClient(…) + + accounts = f.get_sepa_accounts() + account = accounts[0] + + methods = f.get_tan_methods() + method = methods[0] + assert method.description_required != '2' + + tan_desc = '' + res = f.start_simple_sepa_transfer( + account=accounts[0], + iban='DE12345', + bic='BIC12345', + amount=Decimal('7.00'), + recipient_name='Foo', + account_name='Test', + reason='Birthday gift', + endtoend_id='NOTPROVIDED', + tan_method=method + ) + print(res.challenge) + + if getattr(res, challenge_hhd_uc, None): + try: + terminal_flicker_unix(res.challenge_hhd_uc) + except KeyboardInterrupt: + pass + + tan = input('Please enter TAN:') + res = f.send_tan(res, tan) diff --git a/fints/client.py b/fints/client.py index 0fbad86..2f4fdcd 100644 --- a/fints/client.py +++ b/fints/client.py @@ -10,7 +10,6 @@ from fints.segments.debit import HKDSE, HKDME from .connection import FinTSHTTPSConnection from .dialog import FinTSDialog from .message import FinTSMessage -from .message import FinTSResponse from .models import SEPAAccount, TANMethod, TANChallenge6, TANChallenge5, TANChallenge3, TANChallenge4, TANChallenge from .segments.accounts import HKSPA from .segments.auth import HKTAN, HKTAB @@ -36,6 +35,11 @@ class FinTS3Client: raise NotImplemented() def get_sepa_accounts(self): + """ + Returns a list of SEPA accounts + + :return: List of SEPAAccount objects. + """ dialog = self._new_dialog() dialog.sync() dialog.init() @@ -63,7 +67,15 @@ class FinTS3Client: return self.accounts - def get_statement(self, account, start_date, end_date): + def get_statement(self, account: SEPAAccount, start_date: datetime.datetime, end_date: datetime.date): + """ + Fetches the statement of a bank account in a certain timeframe. + + :param account: SEPA + :param start_date: First day to fetch + :param end_date: Last day to fetch + :return: A list of mt940.models.Transaction objects + """ logger.info('Start fetching from {} to {}'.format(start_date, end_date)) dialog = self._new_dialog() @@ -138,7 +150,13 @@ class FinTS3Client: ) ]) - def get_balance(self, account): + def get_balance(self, account: SEPAAccount): + """ + Fetches an accounts current balance. + + :param account: SEPA account to fetch the balance + :return: A mt940.models.Balance object + """ # init dialog dialog = self._new_dialog() dialog.sync() @@ -189,7 +207,13 @@ class FinTS3Client: ) ]) - def get_holdings(self, account): + def get_holdings(self, account: SEPAAccount): + """ + Retrieve holdings of an account. + + :param account: SEPAAccount to retrieve holdings for. + :return: List of Holding objects + """ # init dialog dialog = self._new_dialog() dialog.sync() @@ -248,6 +272,13 @@ class FinTS3Client: ], tan) def send_tan(self, challenge: TANChallenge, tan: str): + """ + Sends a TAN to confirm a pending operation. + + :param challenge: TANChallenge to respond to + :param tan: TAN value + :return: Currently no response + """ if challenge.tan_process != '4': raise NotImplementedError("TAN process {} currently not implemented".format(challenge.tan_process)) with self.pin.protect(): @@ -265,6 +296,21 @@ class FinTS3Client: def start_simple_sepa_transfer(self, account: SEPAAccount, tan_method: TANMethod, iban: str, bic: str, recipient_name: str, amount: Decimal, account_name: str, reason: str, endtoend_id='NOTPROVIDED', tan_description=''): + """ + Start a simple SEPA transfer. + + :param account: SEPAAccount to start the transfer from. + :param tan_method: TANMethod object to use. + :param iban: Recipient's IBAN + :param bic: Recipient's BIC + :param recipient_name: Recipient name + :param amount: Amount as a ``Decimal`` + :param account_name: Sender account name + :param reason: Transfer reason + :param endtoend_id: End-to-end-Id (defaults to ``NOTPROVIDED``) + :param tan_description: TAN medium description (if required) + :return: Returns a TANChallenge object + """ config = { "name": account_name, "IBAN": account.iban, @@ -302,6 +348,19 @@ class FinTS3Client: def start_sepa_transfer(self, account: SEPAAccount, pain_message: str, tan_method, tan_description='', multiple=False, control_sum=None, currency='EUR', book_as_single=False): + """ + Start a custom SEPA transfer. + + :param account: SEPAAccount to send the transfer from. + :param pain_message: SEPA PAIN message containing the transfer details. + :param tan_method: TANMethod object to use. + :param tan_description: TAN medium description (if required) + :param multiple: Whether this message contains multiple transfers. + :param control_sum: Sum of all transfers (required if there are multiple) + :param currency: Transfer currency + :param book_as_single: Kindly ask the bank to put multiple transactions as separate lines on the bank statement (defaults to ``False``) + :return: Returns a TANChallenge object + """ dialog = self._new_dialog() dialog.sync() dialog.tan_mechs = [tan_method] @@ -336,6 +395,19 @@ class FinTS3Client: def start_sepa_debit(self, account: SEPAAccount, pain_message: str, tan_method, tan_description='', multiple=False, control_sum=None, currency='EUR', book_as_single=False): + """ + Start a custom SEPA debit. + + :param account: SEPAAccount to send the debit from. + :param pain_message: SEPA PAIN message containing the debit details. + :param tan_method: TANMethod object to use. + :param tan_description: TAN medium description (if required) + :param multiple: Whether this message contains multiple debits. + :param control_sum: Sum of all debits (required if there are multiple) + :param currency: Debit currency + :param book_as_single: Kindly ask the bank to put multiple transactions as separate lines on the bank statement (defaults to ``False``) + :return: Returns a TANChallenge object + """ dialog = self._new_dialog() dialog.sync() dialog.tan_mechs = [tan_method] @@ -375,6 +447,11 @@ class FinTS3Client: return model(dialog, *s[1:1 + len(model.args)]) def get_tan_methods(self): + """ + Returns a list of TAN methods. + + :return: List of TANMethod objects + """ dialog = self._new_dialog() dialog.sync() dialog.init() @@ -387,6 +464,11 @@ class FinTS3Client: ]) def get_tan_description(self): + """ + TAN method meta data, currently unparsed + + :return: str + """ dialog = self._new_dialog() dialog.sync() dialog.init() diff --git a/fints/hhd/flicker.py b/fints/hhd/flicker.py index a72f176..30ab5d2 100644 --- a/fints/hhd/flicker.py +++ b/fints/hhd/flicker.py @@ -31,6 +31,8 @@ def parse(code): def clean(code): + if code.startswith('@'): + code = code[res.challenge_hhd_uc.index('@', 2) + 1:] code = code.replace(" ", "").strip() if "CHLGUC" in code and "CHLGTEXT" in code: # Sometimes, HHD 1.3 codes are not transfered in the challenge field but in the free text, @@ -233,9 +235,20 @@ class Startcode(DE): def terminal_flicker_unix(code, field_width=3, space_width=3, height=1, clear=False, wait=0.05): + """ + Re-encodes a flicker code and prints it on a unix terminal. + + :param code: Challenge value + :param field_width: Width of fields in characters (default: 3). + :param space_width: Width of spaces in characters (default: 3). + :param height: Height of fields in characters (default: 1). + :param clear: Clear terminal after every line (default: ``False``). + :param wait: Waiting interval between lines (default: 0.05). + """ # Inspired by Andreas Schiermeier # https://git.ccc-ffm.de/?p=smartkram.git;a=blob_plain;f=chiptan/flicker/flicker.sh;h # =7066293b4e790c2c4c1f6cbdab703ed9976ffe1f;hb=refs/heads/master + code = parse(code).render() data = swap_bytes(code) high = '\033[48;05;15m' low = '\033[48;05;0m' diff --git a/fints/models.py b/fints/models.py index 9131725..b53422e 100644 --- a/fints/models.py +++ b/fints/models.py @@ -28,6 +28,30 @@ class TANMethod(DataClass): class TANMethod5(TANMethod): + """ + :param security_feature: + :param tan_process: + :param tech_id: + :param zka_id: + :param zka_version: + :param name: + :param max_length_input: + :param allowed_format: + :param text_returnvalue: + :param max_length_returnvalue: + :param number_of_supported_lists: + :param multiple_tans_allowed: + :param tan_time_dialog_association: + :param tan_list_number_required: + :param cancel_allowed: + :param sms_charge_account_required: + :param principal_account_required: + :param challenge_class_required: + :param challenge_value_required: + :param initialization_mode: + :param description_required: + :param supported_media_number: + """ # Source: PIN/TAN docs – Verfahrensparameter Zwei-Schritt-Verfahren, Elementversion #5 version = 5 args = ['security_feature', 'tan_process', 'tech_id', 'zka_id', 'zka_version', 'name', 'max_length_input', @@ -39,6 +63,30 @@ class TANMethod5(TANMethod): class TANMethod6(TANMethod): # Source: PIN/TAN docs – Verfahrensparameter Zwei-Schritt-Verfahren, Elementversion #6 + """ + :param security_feature: + :param tan_process: + :param tech_id: + :param zka_id: + :param zka_version: + :param name: + :param max_length_input: + :param allowed_format: + :param text_returnvalue: + :param max_length_returnvalue: + :param number_of_supported_lists: + :param multiple_tans_allowed: + :param tan_time_dialog_association: + :param cancel_allowed: + :param sms_charge_account_required: + :param principal_account_required: + :param challenge_class_required: + :param challenge_value_required: + :param initialization_mode: + :param description_required: + :param hhd_uc_required: + :param supported_media_number: + """ version = 6 args = ['security_feature', 'tan_process', 'tech_id', 'zka_id', 'zka_version', 'name', 'max_length_input', 'allowed_format', 'text_returnvalue', 'max_length_returnvalue', 'multiple_tans_allowed', @@ -55,24 +103,65 @@ class TANChallenge(DataClass): class TANChallenge3(TANChallenge): + """ + :param tan_process: + :param request_hash: + :param reference: + :param challenge: + :param challenge_datetime: + :param tan_list_number: + :param ben: + :param medium_description: + """ version = 3 args = ['tan_process', 'request_hash', 'reference', 'challenge', 'challenge_datetime', 'tan_list_number', 'ben', 'medium_description'] class TANChallenge4(TANChallenge): + """ + :param tan_process: + :param request_hash: + :param reference: + :param challenge: + :param challenge_hhd_uc: + :param challenge_datetime: + :param tan_list_number: + :param ben: + :param medium_description: + """ version = 4 args = ['tan_process', 'request_hash', 'reference', 'challenge', 'challenge_hhd_uc', 'challenge_datetime', 'tan_list_number', 'ben', 'medium_description'] class TANChallenge5(TANChallenge): + """ + :param tan_process: + :param request_hash: + :param reference: + :param challenge: + :param challenge_hhd_uc: + :param challenge_datetime: + :param tan_list_number: + :param ben: + :param medium_description: + """ version = 5 args = ['tan_process', 'request_hash', 'reference', 'challenge', 'challenge_hhd_uc', 'challenge_datetime', 'tan_list_number', 'ben', 'medium_description'] class TANChallenge6(TANChallenge): + """ + :param tan_process: + :param request_hash: + :param reference: + :param challenge: + :param challenge_hhd_uc: + :param challenge_datetime: + :param medium_description: + """ version = 6 args = ['tan_process', 'request_hash', 'reference', 'challenge', 'challenge_hhd_uc', 'challenge_datetime', 'medium_description'] \ No newline at end of file