From: Raphael Michel Date: Wed, 25 Jul 2018 16:49:13 +0000 (+0200) Subject: Implement direct debit X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9fb9b07418387139f6cd7a7ce2390d975569bc4c;p=thirdparty%2Fpython-fints.git Implement direct debit --- diff --git a/fints/client.py b/fints/client.py index 03e189f..0fbad86 100644 --- a/fints/client.py +++ b/fints/client.py @@ -6,6 +6,7 @@ from decimal import Decimal from mt940.models import Balance from sepaxml import SepaTransfer +from fints.segments.debit import HKDSE, HKDME from .connection import FinTSHTTPSConnection from .dialog import FinTSDialog from .message import FinTSMessage @@ -319,6 +320,40 @@ class FinTS3Client: logger.debug('Got response: {}'.format(resp)) return self._tan_requiring_response(dialog, resp) + def _get_start_sepa_debit_message(self, dialog, account: SEPAAccount, pain_message: str, tan_method, + tan_description, multiple, control_sum, currency, book_as_single): + if multiple: + if not control_sum: + raise ValueError("Control sum required.") + segreq = HKDME(3, account, pain_message, control_sum, currency, book_as_single) + else: + segreq = HKDSE(3, account, pain_message) + segtan = HKTAN(4, '4', '', tan_description, tan_method.version) + return self._new_message(dialog, [ + segreq, + segtan + ]) + + 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): + dialog = self._new_dialog() + dialog.sync() + dialog.tan_mechs = [tan_method] + dialog.init() + + with self.pin.protect(): + logger.debug('Sending: {}'.format(self._get_start_sepa_debit_message( + dialog, account, pain_message, tan_method, tan_description, multiple, control_sum, currency, + book_as_single + ))) + + resp = dialog.send(self._get_start_sepa_debit_message( + dialog, account, pain_message, tan_method, tan_description, multiple, control_sum, currency, + book_as_single + )) + logger.debug('Got response: {}'.format(resp)) + return self._tan_requiring_response(dialog, resp) + def _tan_requiring_response(self, dialog, resp): seg = resp._find_segment('HITAN') s = split_for_data_groups(seg) diff --git a/fints/segments/debit.py b/fints/segments/debit.py new file mode 100644 index 0000000..0c349ca --- /dev/null +++ b/fints/segments/debit.py @@ -0,0 +1,48 @@ +from . import FinTS3Segment +from ..models import SEPAAccount + + +class HKDSE(FinTS3Segment): + """ + HKDSE (Einreichung terminierter SEPA-Einzellastschrift) + Section C.10.2.5.4.1 + """ + type = 'HKDSE' + + def __init__(self, segno, account: SEPAAccount, pain_msg): + self.version = 1 + sepa_descriptor = 'urn?:iso?:std?:iso?:20022?:tech?:xsd?:pain.008.003.02' + msg = ':'.join([ + account.iban, + account.bic + ]) + data = [ + msg, + sepa_descriptor, + '@{}@{}'.format(len(pain_msg), pain_msg) + ] + super().__init__(segno, data) + + +class HKDME(FinTS3Segment): + """ + HKDME (Einreichung terminierter SEPA-Sammellastschrift) + Section C.10.3.2.2.1 + """ + type = 'HKDME' + + def __init__(self, segno, account: SEPAAccount, pain_msg, control_sum, currency, book_as_single): + self.version = 1 + sepa_descriptor = 'urn?:iso?:std?:iso?:20022?:tech?:xsd?:pain.008.003.02' + msg = ':'.join([ + account.iban, + account.bic + ]) + data = [ + msg, + str(control_sum).replace('.', ',') + ':' + currency, + 'J' if book_as_single else '', + sepa_descriptor, + '@{}@{}'.format(len(pain_msg), pain_msg) + ] + super().__init__(segno, data)