Sending SEPA transfers¶
Simple mode¶
You can create a simple SEPA transfer using this convenient client method:
- class fints.client.FinTS3Client(bank_identifier, user_id, customer_id=None, from_data: bytes = None, system_id=None, product_id=None, product_version='5.0.0', mode=FinTSClientMode.INTERACTIVE)[source]
- simple_sepa_transfer(account: SEPAAccount, iban: str, bic: str, recipient_name: str, amount: Decimal, account_name: str, reason: str, instant_payment=False, endtoend_id='NOTPROVIDED')[source]
Simple SEPA transfer.
- Parameters:
account – SEPAAccount to start the transfer from.
iban – Recipient’s IBAN
bic – Recipient’s BIC (Can be None if domestic)
recipient_name – Recipient name
amount – Amount as a
Decimalaccount_name – Sender account name
reason – Transfer reason
instant_payment – Whether to use instant payment (defaults to
False)endtoend_id – End-to-end-Id (defaults to
NOTPROVIDED)
- Returns:
Returns either a NeedRetryResponse or NeedVOPResponse or TransactionResponse
The return value may be a NeedVOPResponse in which case you need to call approve_vop_response to proceed.
At any point, you might receive a NeedTANResponse. You should then enter a TAN, read our chapter Working with TANs to find out more.
- class fints.client.FinTS3PinTanClient(bank_identifier, user_id, pin, server, customer_id=None, tan_medium=None, *args, **kwargs)[source]
- approve_vop_response(challenge: NeedVOPResponse)[source]
Approves an operation that had a non-match VoP (verification of payee) response.
- Parameters:
challenge – NeedVOPResponse to respond to
- Returns:
New response after sending VOP response
Advanced mode¶
If you want to use advanced methods, you can supply your own SEPA XML:
- class fints.client.FinTS3Client(bank_identifier, user_id, customer_id=None, from_data: bytes = None, system_id=None, product_id=None, product_version='5.0.0', mode=FinTSClientMode.INTERACTIVE)[source]
- sepa_transfer(account: SEPAAccount, pain_message: str, multiple=False, control_sum=None, currency='EUR', book_as_single=False, pain_descriptor='urn:iso:std:iso:20022:tech:xsd:pain.001.001.03', instant_payment=False)[source]
Custom SEPA transfer.
- Parameters:
account – SEPAAccount to send the transfer from.
pain_message – SEPA PAIN message containing the transfer details.
multiple – Whether this message contains multiple transfers.
control_sum – Sum of all transfers (required if there are multiple)
currency – Transfer currency
book_as_single – Kindly ask the bank to put multiple transactions as separate lines on the bank statement (defaults to
False)pain_descriptor – URN of the PAIN message schema used.
instant_payment – Whether this is an instant transfer (defaults to
False)
- Returns:
Returns either a NeedRetryResponse or TransactionResponse
Full example¶
client = FinTS3PinTanClient(...)
minimal_interactive_cli_bootstrap(client)
with client:
if client.init_tan_response:
print("A TAN is required", client.init_tan_response.challenge)
if getattr(client.init_tan_response, 'challenge_hhduc', None):
try:
terminal_flicker_unix(client.init_tan_response.challenge_hhduc)
except KeyboardInterrupt:
pass
tan = input('Please enter TAN:')
client.send_tan(client.init_tan_response, tan)
res = client.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',
)
while isinstance(res, NeedTANResponse | NeedVOPResponse):
if isinstance(res, NeedTANResponse):
print("A TAN is required", res.challenge)
if getattr(res, 'challenge_hhduc', None):
try:
terminal_flicker_unix(res.challenge_hhduc)
except KeyboardInterrupt:
pass
if result.decoupled:
tan = input('Please press enter after confirming the transaction in your app:')
else:
tan = input('Please enter TAN:')
res = client.send_tan(res, tan)
elif isinstance(res, NeedVOPResponse):
if res.vop_result.vop_single_result.result == "RCVC":
print("Payee name is an exact match")
if res.vop_result.vop_single_result.other_identification:
print("Other info retrieved by bank:", res.vop_result.vop_single_result.other_identification)
elif res.vop_result.vop_single_result.result == "RVMC":
print("Payee name is a close match")
print("Name retrieved by bank:", res.vop_result.vop_single_result.close_match_name)
if res.vop_result.vop_single_result.other_identification:
print("Other info retrieved by bank:", res.vop_result.vop_single_result.other_identification)
elif res.vop_result.vop_single_result.result == "RVNM":
print("Payee name does not match match")
elif res.vop_result.vop_single_result.result == "RVNA":
print("Payee name could not be verified")
print("Reason:", res.vop_result.vop_single_result.na_reason)
elif res.vop_result.vop_single_result.result == "PDNG":
print("Payee name could not be verified (pending state, can't be handled by this library)")
print("Do you want to continue? Your bank will not be liable if the money ends up in the wrong place.")
input('Please press enter to confirm or Ctrl+C to cancel')
res = client.approve_vop_response(res)
print(res.status)
print(res.responses)