Bug: [BUG] Add changes for field CybersourceConsumerAuthInformation



### Bug Description

Cybersource payments via Netcetera are failing for a France based acquirer in prod, the PR provides fix for the same by introducing field effective_authentication_type, and making sure semantic_version is sent.



### Expected Behavior

Payments should pass

### Actual Behavior

Payments are currently failing in prod a france based acquirer

### Steps To Reproduce

Provide an unambiguous set of steps to reproduce this bug. Include code or configuration to reproduce, if relevant.
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'


### Context For The Bug

_No response_

### Environment

Are you using hyperswitch hosted version? Yes/No
If yes, please provide the value of the `x-request-id` response header to help us debug your issue.

If not (or if building/running locally), please provide the following details:
1. Operating System or Linux distribution:
2. Rust version (output of `rustc --version`): ``
3. App version (output of `cargo r --features vergen -- --version`): ``


### Have you spent some time checking if this bug has been raised before?

- [x] I checked and didn't find a similar issue

### Have you read the Contributing Guidelines?

- [x] I have read the [Contributing Guidelines](https://github.com/juspay/hyperswitch/blob/main/docs/CONTRIBUTING.md)

### Are you willing to submit a PR?

Yes, I am willing to submit a PR!
diff --git a/crates/hyperswitch_connectors/src/connectors/cybersource/transformers.rs b/crates/hyperswitch_connectors/src/connectors/cybersource/transformers.rs
index da1237f3f4f..2112989969e 100644
--- a/crates/hyperswitch_connectors/src/connectors/cybersource/transformers.rs
+++ b/crates/hyperswitch_connectors/src/connectors/cybersource/transformers.rs
@@ -377,7 +377,7 @@ pub struct CybersourceConsumerAuthInformation {
     ucaf_authentication_data: Option<Secret<String>>,
     xid: Option<String>,
     directory_server_transaction_id: Option<Secret<String>>,
-    specification_version: Option<String>,
+    specification_version: Option<SemanticVersion>,
     /// This field specifies the 3ds version
     pa_specification_version: Option<SemanticVersion>,
     /// Verification response enrollment status.
@@ -393,6 +393,15 @@ pub struct CybersourceConsumerAuthInformation {
     pares_status: Option<CybersourceParesStatus>,
     //This field is used to send the authentication date in yyyyMMDDHHMMSS format
     authentication_date: Option<String>,
+    /// This field indicates the 3D Secure transaction flow. It is only supported for secure transactions in France.
+    /// The possible values are - CH (Challenge), FD (Frictionless with delegation), FR (Frictionless)
+    effective_authentication_type: Option<EffectiveAuthenticationType>,
+}
+
+#[derive(Debug, Serialize)]
+pub enum EffectiveAuthenticationType {
+    CH,
+    FR,
 }
 
 #[derive(Debug, Serialize)]
@@ -1232,6 +1241,15 @@ fn convert_metadata_to_merchant_defined_info(metadata: Value) -> Vec<MerchantDef
     vector
 }
 
+impl From<common_enums::DecoupledAuthenticationType> for EffectiveAuthenticationType {
+    fn from(auth_type: common_enums::DecoupledAuthenticationType) -> Self {
+        match auth_type {
+            common_enums::DecoupledAuthenticationType::Challenge => Self::CH,
+            common_enums::DecoupledAuthenticationType::Frictionless => Self::FR,
+        }
+    }
+}
+
 impl
     TryFrom<(
         &CybersourceRouterData<&PaymentsAuthorizeRouterData>,
@@ -1330,6 +1348,8 @@ impl
                     date_time::DateFormat::YYYYMMDDHHmmss,
                 )
                 .ok();
+                let effective_authentication_type = authn_data.authentication_type.map(Into::into);
+
                 CybersourceConsumerAuthInformation {
                     pares_status,
                     ucaf_collection_indicator,
@@ -1340,11 +1360,12 @@ impl
                         .ds_trans_id
                         .clone()
                         .map(Secret::new),
-                    specification_version: None,
+                    specification_version: authn_data.message_version.clone(),
                     pa_specification_version: authn_data.message_version.clone(),
                     veres_enrolled: Some("Y".to_string()),
                     eci_raw: authn_data.eci.clone(),
                     authentication_date,
+                    effective_authentication_type,
                 }
             });
 
@@ -1418,6 +1439,7 @@ impl
             .authentication_data
             .as_ref()
             .map(|authn_data| {
+                let effective_authentication_type = authn_data.authentication_type.map(Into::into);
                 let (ucaf_authentication_data, cavv, ucaf_collection_indicator) =
                     if ccard.card_network == Some(common_enums::CardNetwork::Mastercard) {
                         (Some(authn_data.cavv.clone()), None, Some("2".to_string()))
@@ -1439,11 +1461,12 @@ impl
                         .ds_trans_id
                         .clone()
                         .map(Secret::new),
-                    specification_version: None,
+                    specification_version: authn_data.message_version.clone(),
                     pa_specification_version: authn_data.message_version.clone(),
                     veres_enrolled: Some("Y".to_string()),
                     eci_raw: authn_data.eci.clone(),
                     authentication_date,
+                    effective_authentication_type,
                 }
             });
 
@@ -1520,6 +1543,8 @@ impl
             .authentication_data
             .as_ref()
             .map(|authn_data| {
+                let effective_authentication_type = authn_data.authentication_type.map(Into::into);
+
                 let (ucaf_authentication_data, cavv, ucaf_collection_indicator) =
                     if token_data.card_network == Some(common_enums::CardNetwork::Mastercard) {
                         (Some(authn_data.cavv.clone()), None, Some("2".to_string()))
@@ -1541,11 +1566,12 @@ impl
                         .ds_trans_id
                         .clone()
                         .map(Secret::new),
-                    specification_version: None,
+                    specification_version: authn_data.message_version.clone(),
                     pa_specification_version: authn_data.message_version.clone(),
                     veres_enrolled: Some("Y".to_string()),
                     eci_raw: authn_data.eci.clone(),
                     authentication_date,
+                    effective_authentication_type,
                 }
             });
 
@@ -1725,11 +1751,12 @@ impl
             directory_server_transaction_id: three_ds_info
                 .three_ds_data
                 .directory_server_transaction_id,
-            specification_version: three_ds_info.three_ds_data.specification_version,
-            pa_specification_version: None,
+            specification_version: three_ds_info.three_ds_data.specification_version.clone(),
+            pa_specification_version: three_ds_info.three_ds_data.specification_version.clone(),
             veres_enrolled: None,
             eci_raw: None,
             authentication_date: None,
+            effective_authentication_type: None,
         });
 
         let merchant_defined_information = item
@@ -1827,6 +1854,7 @@ impl
                 veres_enrolled: None,
                 eci_raw: None,
                 authentication_date: None,
+                effective_authentication_type: None,
             }),
             merchant_defined_information,
         })
@@ -1971,6 +1999,7 @@ impl
                 veres_enrolled: None,
                 eci_raw: None,
                 authentication_date: None,
+                effective_authentication_type: None,
             }),
             merchant_defined_information,
         })
@@ -2172,6 +2201,7 @@ impl TryFrom<&CybersourceRouterData<&PaymentsAuthorizeRouterData>> for Cybersour
                                                 veres_enrolled: None,
                                                 eci_raw: None,
                                                 authentication_date: None,
+                                                effective_authentication_type: None,
                                             },
                                         ),
                                     })
@@ -3221,7 +3251,7 @@ pub struct CybersourceConsumerAuthValidateResponse {
     cavv: Option<Secret<String>>,
     ucaf_authentication_data: Option<Secret<String>>,
     xid: Option<String>,
-    specification_version: Option<String>,
+    specification_version: Option<SemanticVersion>,
     directory_server_transaction_id: Option<Secret<String>>,
     indicator: Option<String>,
 }
diff --git a/crates/hyperswitch_domain_models/src/router_request_types.rs b/crates/hyperswitch_domain_models/src/router_request_types.rs
index c7ac3664835..9e6dd7ea3c7 100644
--- a/crates/hyperswitch_domain_models/src/router_request_types.rs
+++ b/crates/hyperswitch_domain_models/src/router_request_types.rs
@@ -683,6 +683,7 @@ pub struct AuthenticationData {
     pub message_version: Option<common_utils::types::SemanticVersion>,
     pub ds_trans_id: Option<String>,
     pub created_at: time::PrimitiveDateTime,
+    pub authentication_type: Option<common_enums::DecoupledAuthenticationType>,
 }
 
 #[derive(Debug, Clone)]
diff --git a/crates/router/src/core/payments/types.rs b/crates/router/src/core/payments/types.rs
index acba2c35edc..10df4034c92 100644
--- a/crates/router/src/core/payments/types.rs
+++ b/crates/router/src/core/payments/types.rs
@@ -390,6 +390,7 @@ impl
                 threeds_server_transaction_id,
                 message_version,
                 ds_trans_id: authentication.ds_trans_id.clone(),
+                authentication_type: authentication.authentication_type,
             })
         } else {
             Err(errors::ApiErrorResponse::PaymentAuthenticationFailed { data: None }.into())

## Type of Change
<!-- Put an `x` in the boxes that apply -->

- [ ] Bugfix
- [ ] New feature
- [X] Enhancement
- [ ] Refactoring
- [ ] Dependency updates
- [ ] Documentation
- [ ] CI/CD

## Description
Context - Cybersource payments via Netcetera are failing for a France based acquirer in prod, the PR provides fix for the same by introducing field **_consumerAuthenticationInformation. effectiveAuthenticationType_** and making sure **_consumerAuthenticationInformation.specificationVersion** is sent.


### Additional Changes

- [ ] This PR modifies the API contract
- [ ] This PR modifies the database schema
- [ ] This PR modifies application configuration/environment variables

<!--
Provide links to the files with corresponding changes.

Following are the paths where you can find config files:
1. `config`
3. `crates/router/src/configs`
4. `loadtest/config`
-->


## Motivation and Context
<!--
Why is this change required? What problem does it solve?
If it fixes an open issue, please link to the issue here.

If you don't have an issue, we'd recommend starting with one first so the PR
can focus on the implementation (unless it is an obvious bug or documentation fix
that will have little conversation).
-->


## How did you test it?
<!--
Did you write an integration/unit/API test to verify the code changes?
Or did you test this change manually (provide relevant screenshots)?
-->
**Testing for field effective_authentication_type and specification_version** 

### Step 1 - Call /payments

**Curl**

`curl --location 'http://localhost:8080/payments' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'x-feature: integ-custom' \
--header 'api-key: dev_TSUxfiSwiAelCPTr9xN2ValUdd1fvmeYg0AtMUwdJukRkTlCpHL9p2IWxn6fouYl' \
--data-raw '{
    "amount": 2540,
    "currency": "USD",
    "profile_id": "pro_aKVBsBqyTIq2T1UIaapY",
    "confirm": true,
    "amount_to_capture": 2540,
    "capture_method": "automatic",
    "capture_on": "2022-09-10T10:11:12Z",
    "customer_id": "StripeCustomer",
    "email": "abcdef123@gmail.com",
    "name": "John Doe",
    "phone": "999999999",
    "request_external_three_ds_authentication": true,
    "phone_country_code": "+65",
    "description": "Its my first payment request",
    "authentication_type": "three_ds",
    "return_url": "https://google.com",
    "setup_future_usage": "on_session",
    "browser_info": {
        "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36",
        "accept_header": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
        "language": "nl-NL",
        "color_depth": 24,
        "screen_height": 723,
        "screen_width": 1536,
        "time_zone": 0,
        "java_enabled": true,
        "java_script_enabled": true,
        "ip_address": "127.0.0.1"
    },
    "shipping": {
        "address": {
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "city": "San Fransico",
            "state": "California",
            "zip": "94122",
            "country": "US",
            "first_name": "John",
            "last_name": "Doe"
        }
    },
    "routing": {
        "type": "single",
        "data": "nmi"
    },
    "statement_descriptor_name": "joseph",
    "statement_descriptor_suffix": "JS",
    "metadata": {
        "udf1": "value1",
        "new_customer": "true",
        "login_date": "2019-09-10T10:11:12Z"
    },
    "payment_method": "card",
    "payment_method_type": "credit",
    "payment_method_data": {
        "card": {
            "card_number": "4000000000002370",
            "card_exp_month": "08",
            "card_exp_year": "25",
            "card_holder_name": "joseph Doe",
            "card_cvc": "999"
        }
    },
    "billing": {
        "address": {
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "city": "San Fransico",
            "state": "California",
            "zip": "94122",
            "country": "US",
            "first_name": "John",
            "last_name": "Doe"
        }
    }
}'`

<img width="837" height="743" alt="Screenshot 2025-07-29 at 6 40 54 PM" src="https://github.com/user-attachments/assets/5810eda7-6dcf-474a-813b-eab7f2fb3e28" />


###  Step 2- Call /3ds/authentication via Netcetera 

**Curl**

`curl --location 'http://localhost:8080/payments/pay_1tQlG51BwoiUpLE3YKBV/3ds/authentication' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: pk_dev_8891a001315d40d0a26d1028ad51fe0b' \
--data '{
    "client_secret": "pay_1tQlG51BwoiUpLE3YKBV_secret_EqDy0WeEHEfkkOjUd9R0",
    "device_channel": "BRW",
    "threeds_method_comp_ind": "Y"
}'`
<img width="1035" height="782" alt="Screenshot 2025-07-29 at 6 41 14 PM" src="https://github.com/user-attachments/assets/0b683f45-472f-47fe-9ef8-84a8db019c3b" />

### Step 3- Call /authorize via Cybersource

`curl --location --request POST 'http://localhost:8080/payments/pay_1tQlG51BwoiUpLE3YKBV/merchant_1753777600/authorize/cybersource' \
--header 'api-key: dev_TSUxfiSwiAelCPTr9xN2ValUdd1fvmeYg0AtMUwdJukRkTlCpHL9p2IWxn6fouYl'`

<img width="1035" height="750" alt="Screenshot 2025-07-29 at 6 44 11 PM" src="https://github.com/user-attachments/assets/6ae685e7-0816-4164-9fae-840cd5f2266e" />

 
**specificationVersion and effectiveAuthenticationType are getting populated, and are sent to Cybersource_**
<img width="1488" height="343" alt="Screenshot 2025-07-29 at 3 25 00 PM" src="https://github.com/user-attachments/assets/a62d4e3d-a168-48a2-bd02-67c279b087ad" />

Please note - Effective authentication type is FR, since the test flow is Frictionless

## Checklist
<!-- Put an `x` in the boxes that apply -->

- [x] I formatted the code `cargo +nightly fmt --all`
- [x] I addressed lints thrown by `cargo clippy`
- [x] I reviewed the submitted code
- [ ] I added unit tests for my changes where possible
