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
-----------
* 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 <mail@raphaelmichel.de>
-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!
--- /dev/null
+# 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 <target>' where <target> 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."
--- /dev/null
+#!/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.
+# "<project> v<release> 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 <link> 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}
--- /dev/null
+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()
--- /dev/null
+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
--- /dev/null
+@ECHO OFF\r
+\r
+REM Command file for Sphinx documentation\r
+\r
+if "%SPHINXBUILD%" == "" (\r
+ set SPHINXBUILD=sphinx-build\r
+)\r
+set BUILDDIR=_build\r
+set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .\r
+set I18NSPHINXOPTS=%SPHINXOPTS% .\r
+if NOT "%PAPER%" == "" (\r
+ set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%\r
+ set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%\r
+)\r
+\r
+if "%1" == "" goto help\r
+\r
+if "%1" == "help" (\r
+ :help\r
+ echo.Please use `make ^<target^>` where ^<target^> is one of\r
+ echo. html to make standalone HTML files\r
+ echo. dirhtml to make HTML files named index.html in directories\r
+ echo. singlehtml to make a single large HTML file\r
+ echo. pickle to make pickle files\r
+ echo. json to make JSON files\r
+ echo. htmlhelp to make HTML files and a HTML help project\r
+ echo. qthelp to make HTML files and a qthelp project\r
+ echo. devhelp to make HTML files and a Devhelp project\r
+ echo. epub to make an epub\r
+ echo. epub3 to make an epub3\r
+ echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter\r
+ echo. text to make text files\r
+ echo. man to make manual pages\r
+ echo. texinfo to make Texinfo files\r
+ echo. gettext to make PO message catalogs\r
+ echo. changes to make an overview over all changed/added/deprecated items\r
+ echo. xml to make Docutils-native XML files\r
+ echo. pseudoxml to make pseudoxml-XML files for display purposes\r
+ echo. linkcheck to check all external links for integrity\r
+ echo. doctest to run all doctests embedded in the documentation if enabled\r
+ echo. coverage to run coverage check of the documentation if enabled\r
+ goto end\r
+)\r
+\r
+if "%1" == "clean" (\r
+ for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i\r
+ del /q /s %BUILDDIR%\*\r
+ goto end\r
+)\r
+\r
+\r
+REM Check if sphinx-build is available and fallback to Python version if any\r
+%SPHINXBUILD% 1>NUL 2>NUL\r
+if errorlevel 9009 goto sphinx_python\r
+goto sphinx_ok\r
+\r
+:sphinx_python\r
+\r
+set SPHINXBUILD=python -m sphinx.__init__\r
+%SPHINXBUILD% 2> nul\r
+if errorlevel 9009 (\r
+ echo.\r
+ echo.The 'sphinx-build' command was not found. Make sure you have Sphinx\r
+ echo.installed, then set the SPHINXBUILD environment variable to point\r
+ echo.to the full path of the 'sphinx-build' executable. Alternatively you\r
+ echo.may add the Sphinx directory to PATH.\r
+ echo.\r
+ echo.If you don't have Sphinx installed, grab it from\r
+ echo.http://sphinx-doc.org/\r
+ exit /b 1\r
+)\r
+\r
+:sphinx_ok\r
+\r
+\r
+if "%1" == "html" (\r
+ %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html\r
+ if errorlevel 1 exit /b 1\r
+ echo.\r
+ echo.Build finished. The HTML pages are in %BUILDDIR%/html.\r
+ goto end\r
+)\r
+\r
+if "%1" == "dirhtml" (\r
+ %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml\r
+ if errorlevel 1 exit /b 1\r
+ echo.\r
+ echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.\r
+ goto end\r
+)\r
+\r
+if "%1" == "singlehtml" (\r
+ %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml\r
+ if errorlevel 1 exit /b 1\r
+ echo.\r
+ echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.\r
+ goto end\r
+)\r
+\r
+if "%1" == "pickle" (\r
+ %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle\r
+ if errorlevel 1 exit /b 1\r
+ echo.\r
+ echo.Build finished; now you can process the pickle files.\r
+ goto end\r
+)\r
+\r
+if "%1" == "json" (\r
+ %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json\r
+ if errorlevel 1 exit /b 1\r
+ echo.\r
+ echo.Build finished; now you can process the JSON files.\r
+ goto end\r
+)\r
+\r
+if "%1" == "htmlhelp" (\r
+ %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp\r
+ if errorlevel 1 exit /b 1\r
+ echo.\r
+ echo.Build finished; now you can run HTML Help Workshop with the ^\r
+.hhp project file in %BUILDDIR%/htmlhelp.\r
+ goto end\r
+)\r
+\r
+if "%1" == "qthelp" (\r
+ %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp\r
+ if errorlevel 1 exit /b 1\r
+ echo.\r
+ echo.Build finished; now you can run "qcollectiongenerator" with the ^\r
+.qhcp project file in %BUILDDIR%/qthelp, like this:\r
+ echo.^> qcollectiongenerator %BUILDDIR%\qthelp\django-i18nfield.qhcp\r
+ echo.To view the help file:\r
+ echo.^> assistant -collectionFile %BUILDDIR%\qthelp\django-i18nfield.ghc\r
+ goto end\r
+)\r
+\r
+if "%1" == "devhelp" (\r
+ %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp\r
+ if errorlevel 1 exit /b 1\r
+ echo.\r
+ echo.Build finished.\r
+ goto end\r
+)\r
+\r
+if "%1" == "epub" (\r
+ %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub\r
+ if errorlevel 1 exit /b 1\r
+ echo.\r
+ echo.Build finished. The epub file is in %BUILDDIR%/epub.\r
+ goto end\r
+)\r
+\r
+if "%1" == "epub3" (\r
+ %SPHINXBUILD% -b epub3 %ALLSPHINXOPTS% %BUILDDIR%/epub3\r
+ if errorlevel 1 exit /b 1\r
+ echo.\r
+ echo.Build finished. The epub3 file is in %BUILDDIR%/epub3.\r
+ goto end\r
+)\r
+\r
+if "%1" == "latex" (\r
+ %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex\r
+ if errorlevel 1 exit /b 1\r
+ echo.\r
+ echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.\r
+ goto end\r
+)\r
+\r
+if "%1" == "latexpdf" (\r
+ %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex\r
+ cd %BUILDDIR%/latex\r
+ make all-pdf\r
+ cd %~dp0\r
+ echo.\r
+ echo.Build finished; the PDF files are in %BUILDDIR%/latex.\r
+ goto end\r
+)\r
+\r
+if "%1" == "latexpdfja" (\r
+ %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex\r
+ cd %BUILDDIR%/latex\r
+ make all-pdf-ja\r
+ cd %~dp0\r
+ echo.\r
+ echo.Build finished; the PDF files are in %BUILDDIR%/latex.\r
+ goto end\r
+)\r
+\r
+if "%1" == "text" (\r
+ %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text\r
+ if errorlevel 1 exit /b 1\r
+ echo.\r
+ echo.Build finished. The text files are in %BUILDDIR%/text.\r
+ goto end\r
+)\r
+\r
+if "%1" == "man" (\r
+ %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man\r
+ if errorlevel 1 exit /b 1\r
+ echo.\r
+ echo.Build finished. The manual pages are in %BUILDDIR%/man.\r
+ goto end\r
+)\r
+\r
+if "%1" == "texinfo" (\r
+ %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo\r
+ if errorlevel 1 exit /b 1\r
+ echo.\r
+ echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.\r
+ goto end\r
+)\r
+\r
+if "%1" == "gettext" (\r
+ %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale\r
+ if errorlevel 1 exit /b 1\r
+ echo.\r
+ echo.Build finished. The message catalogs are in %BUILDDIR%/locale.\r
+ goto end\r
+)\r
+\r
+if "%1" == "changes" (\r
+ %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes\r
+ if errorlevel 1 exit /b 1\r
+ echo.\r
+ echo.The overview file is in %BUILDDIR%/changes.\r
+ goto end\r
+)\r
+\r
+if "%1" == "linkcheck" (\r
+ %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck\r
+ if errorlevel 1 exit /b 1\r
+ echo.\r
+ echo.Link check complete; look for any errors in the above output ^\r
+or in %BUILDDIR%/linkcheck/output.txt.\r
+ goto end\r
+)\r
+\r
+if "%1" == "doctest" (\r
+ %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest\r
+ if errorlevel 1 exit /b 1\r
+ echo.\r
+ echo.Testing of doctests in the sources finished, look at the ^\r
+results in %BUILDDIR%/doctest/output.txt.\r
+ goto end\r
+)\r
+\r
+if "%1" == "coverage" (\r
+ %SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage\r
+ if errorlevel 1 exit /b 1\r
+ echo.\r
+ echo.Testing of coverage in the sources finished, look at the ^\r
+results in %BUILDDIR%/coverage/python.txt.\r
+ goto end\r
+)\r
+\r
+if "%1" == "xml" (\r
+ %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml\r
+ if errorlevel 1 exit /b 1\r
+ echo.\r
+ echo.Build finished. The XML files are in %BUILDDIR%/xml.\r
+ goto end\r
+)\r
+\r
+if "%1" == "pseudoxml" (\r
+ %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml\r
+ if errorlevel 1 exit /b 1\r
+ echo.\r
+ echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.\r
+ goto end\r
+)\r
+\r
+:end\r
--- /dev/null
+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
--- /dev/null
+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 <their documentation>`_.
+
+
+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
--- /dev/null
+.. _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)
--- /dev/null
+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
+======================================== ============ ======== ======== ======
--- /dev/null
+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)
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
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()
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()
)
])
- 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()
)
])
- 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()
], 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():
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,
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]
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]
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()
])
def get_tan_description(self):
+ """
+ TAN method meta data, currently unparsed
+
+ :return: str
+ """
dialog = self._new_dialog()
dialog.sync()
dialog.init()
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,
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'
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',
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',
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