Fix Consorsbank compatibility (4 issues: TAN version, account details, forced TAN, QR-TAN routing)#209
Open
ArlindNocaj wants to merge 2 commits intoraphaelm:masterfrom
Open
Conversation
These three issues were discovered by comparing mitmdump traces of the working hbci4j Java library against python-fints when connecting to Consorsbank (BLZ 76030080). After applying all three fixes, transactions are fetched successfully, matching the Java output exactly. 1. security.py: Use security_method_version=2 for two-step TAN auth Per the ZKA FinTS spec (page 58), two-step TAN methods (security_function != '999') require version 2 in the SecurityProfile of the HNSHK signature header. The previous hardcoded value of 1 caused Consorsbank to reject the request. Ref: raphaelm#99 2. formals.py: Include full account details in KTI1.from_sepa_account KTI1.from_sepa_account only populated iban and bic, but Consorsbank requires the full account details (account_number, subaccount_number, bank_identifier). Other classes like KTZ1 already include these fields — KTI1 was the only one missing them. 3. client.py: Add force_twostep_tan parameter for banks that require HKTAN despite HIPINS saying otherwise Some banks (Consorsbank) report HKKAZ:N in HIPINS yet reject requests without HKTAN (error 9075). The new opt-in force_twostep_tan parameter (set of segment types) allows users to override HIPINS for specific segments. Defaults to empty set, so existing behavior is unchanged. All three fixes are backwards-compatible and all existing tests pass. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Some banks (e.g. Consorsbank) attach the 0030/3955 response code to the original command segment (HKCCS) rather than to the HKTAN segment. This caused _send_pay_with_possible_retry() to miss the TAN challenge and return a plain TransactionResponse instead of NeedTANResponse. Added fallback: after checking tan_seg responses, also check command_seg responses for 0030/3955 codes. Also: - Add photoTAN QR code handling to transfers.rst full example - Fix typo (result.decoupled → res.decoupled) in transfers.rst - Add Consorsbank to tested.rst (Transactions + Transfer) - Add security function 900 (photoTAN / SecurePlus) - Add sample_consorsbank.py showing photoTAN transfer flow Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes four protocol-level issues preventing Consorsbank (BLZ 76030080) from working with python-fints. Discovered by comparing mitmdump traces of the working hbci4j Java library against python-fints.
After all four fixes, transactions and SEPA transfers with photoTAN (QR code) work correctly.
Fix 1:
security_method_version=2for two-step TAN auth (fints/security.py)Per the ZKA FinTS spec (page 58), two-step TAN methods (
security_function != '999') requiresecurity_method_version=2in theSecurityProfileof the HNSHK signature header. The previous hardcoded value of1caused Consorsbank to reject the request.Before (wire):
HNSHK:...:PIN:1→ bank rejectsAfter (wire):
HNSHK:...:PIN:2→ bank acceptsCloses #99
Fix 2: Full account details in
KTI1.from_sepa_account(fints/formals.py)KTI1.from_sepa_accountonly populatedibanandbic. Consorsbank requires the full account details (account_number,subaccount_number,bank_identifier). Other classes (KTZ1,Account2,Account3) already include these fields —KTI1was the only inconsistent one.Before (wire):
HKKAZ:...:DE12345:CSDBDE71→ error 9010 (missing required fields)After (wire):
HKKAZ:...:DE12345:CSDBDE71:1234567890::280:76030080→ acceptedFix 3:
force_twostep_tanparameter (fints/client.py)Some banks (Consorsbank) report
HKKAZ:Nin HIPINS (TAN not required) yet reject requests without HKTAN (error 9075). Added an opt-inforce_twostep_tanparameter toFinTS3PinTanClient.__init__— a set of segment types that should always include HKTAN regardless of HIPINS.Usage:
Defaults to empty set, so existing behavior is completely unchanged.
Fix 4: Handle TAN response attached to command segment (
fints/client.py)Some banks (Consorsbank) attach the
0030(TAN required) response code to the original command segment (e.g. HKCCS for transfers) rather than to the HKTAN segment. This caused_send_pay_with_possible_retry()to miss the TAN challenge entirely and return a plainTransactionResponse(SUCCESS)instead ofNeedTANResponse— the transfer appeared to succeed but was never authorized.Root cause: The code only checked
response.responses(tan_seg)which filters by the HKTAN segment reference number. When the bank attaches0030to the HKCCS segment reference instead, the loop finds no matching responses.Fix: Added a fallback that also checks
response.responses(command_seg)for0030/3955codes. This correctly surfaces theNeedTANResponsewith the photoTAN QR code image.Verified with a real SEPA transfer using photoTAN (security function 900).
Additional changes
docs/transfers.rst: Added photoTAN/QR code handling to the full example; fixed typo (result.decoupled→res.decoupled)docs/tested.rst: Added Consorsbank (Transactions + Transfer) and security function 900sample_consorsbank.py: Complete example showing Consorsbank setup with photoTAN transfersMethodology
mitmdump -s dump.py)Backwards compatibility
security_function != '999'). One-step mode still uses version 1.KTI1DEG. Banks that don't need them will ignore them per the FinTS spec.