Repository navigation
Improve VoP polling flow and TAN response detection - #211
ArlindNocaj wants to merge 3 commits into
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>
…sponse 1. Implement VoP polling (FinTS spec E.8.3.1): when the bank returns HIVPP with a polling_id but no vop_id, re-send HKVPP with polling_id + aufsetzpunkt (from HIRMS 3040) until the VoP check resolves and a vop_id is returned. 2. Broaden 3945 response code detection in VoP flow: check all HIRMG/HIRMS segments, not just tan_seg responses, since some banks attach it to different segments. 3. Add TAN fallback in approve_vop_response: after VoP approval, check command_seg and global HIRMG/HIRMS segments for 0030/3955 TAN-required codes (mirrors Fix 4 from PR raphaelm#210 but in the VoP approval path). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Commerzbank rejects every transfer to a third-party payee with
"3945 Freigabe ohne VOP-Bestaetigung nicht moeglich", even though HIVPPS is
present, HKVPP is sent and HIVPP comes back with a vop_id.
The reason is where the bank attaches 3945. The existing condition only looked at
responses tied to the TAN segment:
'3945' in [res.code for res in response.responses(tan_seg)]
Commerzbank attaches it elsewhere, so the condition never matched, no
NeedVOPResponse was produced, the flow fell through to TAN handling, and HKVPA was
never sent -- leaving the order permanently rejected.
Observed order on that bank: order submitted -> TAN requested -> TAN submitted ->
3945. The VoP branch is skipped entirely; no polling occurs (vop_id is inline).
Now scanned across all HIRMG/HIRMS segments. Same idea as in raphaelm#211, which describes
this as "some banks attach it to different segments".
Verified against Commerzbank (BLZ 10080000). Atruvia and Sparkasse paths are
unaffected: for them the code was already found at the TAN segment, so the wider
search returns the same result.
|
This PR (and #210, #223) handles Cause
Impact
Affected versions5.0.1 (tag ReproductionSynthetic, no bank: the library's own parser output fed into Not checked
SolutionOne helper that looks for AI disclosure: an AI assistant (Claude, Anthropic) helped find and write this; the line references were checked against the source at |
Builds on top of #210. Three improvements to the Verification of Payee (VoP) flow:
VoP polling (FinTS spec E.8.3.1): When the bank returns HIVPP with a
polling_idbut novop_id, re-send HKVPP withpolling_id+aufsetzpunkt(extracted from HIRMS 3040) until the VoP check resolves and avop_idis returned. This is required by banks like Consorsbank that perform asynchronous VoP verification.Broader
3945response code detection: Check all HIRMG/HIRMS segments for the3945code, not justtan_segresponses, since some banks attach it to different segments.TAN fallback in
approve_vop_response: After VoP approval, checkcommand_segand global HIRMG/HIRMS segments for0030/3955TAN-required codes. This mirrors the Fix 4 pattern from Fix Consorsbank compatibility (3 issues found via hbci4j comparison) #210 but in the VoP approval path, handling banks that attach the TAN challenge to the command segment rather than HKTAN.All changes are backwards-compatible.
Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com