@@ -260,31 +260,46 @@ export class Dialog extends DialogConfig {
260260 if ( ! response . success ) {
261261 throw new ResponseError ( response ) ;
262262 }
263- if ( response . returnValues ( ) . has ( "0030" ) ) {
264- const hitan = response . findSegment ( HITAN ) ;
265- const returnValue = response . returnValues ( ) . get ( "0030" ) ;
263+ const returnValues = response . returnValues ( ) ;
264+ const hasTanRequiredCode = returnValues . has ( "0030" ) ;
265+ let hitan : HITAN | undefined ;
266+ let tanRequiredCode : "0030" | "3955" | undefined ;
267+ if ( hasTanRequiredCode ) {
268+ tanRequiredCode = "0030" ;
269+ } else if ( returnValues . has ( "3955" ) ) {
270+ hitan = response . findSegment ( HITAN ) ;
271+ tanRequiredCode = hitan ? "3955" : undefined ;
272+ }
273+ if ( tanRequiredCode ) {
274+ hitan = hitan ?? response . findSegment ( HITAN ) ;
275+ const returnValue = returnValues . get ( tanRequiredCode ) ;
266276
267277 // Determine which segment triggered the TAN requirement
268278 const triggeringSegment = request . segments . length > 0 ? request . segments [ 0 ] . type : undefined ;
269279
270280 // Check for decoupled TAN indicators per FinTS 3.0 PINTAN specification:
271281 // - "3956": Indicates strong customer authentication (SCA) is pending on trusted device
272282 // - "3076": PSD2-mandated strong customer authentication required
273- // When either code is present alongside "0030", it signals decoupled TAN flow
274- // where the user must approve the transaction in a separate app (e.g., mobile banking)
275- const returnValues = response . returnValues ( ) ;
276- const isDecoupled = returnValues . has ( "3956" ) || returnValues . has ( "3076" ) ;
283+ // - "3955": Security approval takes place in another channel
284+ // These codes indicate a decoupled TAN flow where the user must approve the
285+ // transaction in a separate app or device. "3955" can either accompany "0030"
286+ // or be the primary TAN-required return code itself when returned with HITAN.
287+ const isDecoupled = returnValues . has ( "3956" ) || returnValues . has ( "3076" ) || returnValues . has ( "3955" ) ;
288+ const fallbackMessage =
289+ tanRequiredCode === "3955"
290+ ? "TAN required: Security approval via alternate channel (3955)"
291+ : "TAN required" ;
277292
278293 const error = new TanRequiredError (
279- returnValue . message ,
294+ returnValue ? .message ?? fallbackMessage ,
280295 hitan . transactionReference ,
281296 hitan . challengeText ,
282297 hitan . challengeMedia ,
283298 this ,
284299 TanProcessStep . CHALLENGE_RESPONSE_NEEDED ,
285300 triggeringSegment ,
286301 {
287- returnCode : "0030" ,
302+ returnCode : tanRequiredCode ,
288303 requestSegments : request . segments . map ( ( s ) => s . type ) ,
289304 } ,
290305 ) ;
0 commit comments