Bug: [REFACTOR]: [NUVIE] Fix card 3ds



Fix card 3ds for Nuvie connector
diff --git a/crates/hyperswitch_connectors/src/connectors/nuvei/transformers.rs b/crates/hyperswitch_connectors/src/connectors/nuvei/transformers.rs
index 6d4b27f17e6..3e811b7dddf 100644
--- a/crates/hyperswitch_connectors/src/connectors/nuvei/transformers.rs
+++ b/crates/hyperswitch_connectors/src/connectors/nuvei/transformers.rs
@@ -62,6 +62,11 @@ fn to_boolean(string: String) -> bool {
     }
 }
 
+// The dimensions of the challenge window for full screen.
+const CHALLENGE_WINDOW_SIZE: &str = "05";
+// The challenge preference for the challenge flow.
+const CHALLENGE_PREFERNCE: &str = "01";
+
 trait NuveiAuthorizePreprocessingCommon {
     fn get_browser_info(&self) -> Option<BrowserInformation>;
     fn get_related_transaction_id(&self) -> Option<String>;
@@ -527,6 +532,7 @@ pub struct V2AdditionalParams {
     pub rebill_expiry: Option<String>,
     /// Recurring Frequency in days
     pub rebill_frequency: Option<String>,
+    pub challenge_preference: Option<String>,
 }
 
 #[derive(Debug, Clone, Default, Serialize, Deserialize)]
@@ -563,7 +569,7 @@ pub struct NuveiACSResponse {
     pub message_type: String,
     pub message_version: String,
     pub trans_status: Option<LiabilityShift>,
-    pub message_extension: Vec<MessageExtensionAttribute>,
+    pub message_extension: Option<Vec<MessageExtensionAttribute>>,
     pub acs_signed_content: Option<serde_json::Value>,
 }
 
@@ -1197,11 +1203,22 @@ where
                         ),
                         rebill_frequency: Some(mandate_meta.frequency),
                         challenge_window_size: None,
+                        challenge_preference: None,
                     }),
                     item.request.get_customer_id_required(),
                 )
             }
-            _ => (None, None, None),
+            // non mandate transactions
+            _ => (
+                None,
+                Some(V2AdditionalParams {
+                    rebill_expiry: None,
+                    rebill_frequency: None,
+                    challenge_window_size: Some(CHALLENGE_WINDOW_SIZE.to_string()),
+                    challenge_preference: Some(CHALLENGE_PREFERNCE.to_string()),
+                }),
+                None,
+            ),
         };
     let three_d = if item.is_three_ds() {
         let browser_details = match &browser_information {
@@ -1277,14 +1294,18 @@ impl TryFrom<(&types::PaymentsCompleteAuthorizeRouterData, Secret<String>)>
     ) -> Result<Self, Self::Error> {
         let item = data.0;
         let request_data = match item.request.payment_method_data.clone() {
-            Some(PaymentMethodData::Card(card)) => Ok(Self {
-                payment_option: PaymentOption::from(NuveiCardDetails {
-                    card,
-                    three_d: None,
-                    card_holder_name: item.get_optional_billing_full_name(),
-                }),
-                ..Default::default()
-            }),
+            Some(PaymentMethodData::Card(card)) => {
+                let device_details = DeviceDetails::foreign_try_from(&item.request.browser_info)?;
+                Ok(Self {
+                    payment_option: PaymentOption::from(NuveiCardDetails {
+                        card,
+                        three_d: None,
+                        card_holder_name: item.get_optional_billing_full_name(),
+                    }),
+                    device_details,
+                    ..Default::default()
+                })
+            }
             Some(PaymentMethodData::Wallet(..))
             | Some(PaymentMethodData::PayLater(..))
             | Some(PaymentMethodData::BankDebit(..))
@@ -1319,6 +1340,7 @@ impl TryFrom<(&types::PaymentsCompleteAuthorizeRouterData, Secret<String>)>
         Ok(Self {
             related_transaction_id: request_data.related_transaction_id,
             payment_option: request_data.payment_option,
+            device_details: request_data.device_details,
             ..request
         })
     }
diff --git a/crates/hyperswitch_domain_models/src/router_request_types/authentication.rs b/crates/hyperswitch_domain_models/src/router_request_types/authentication.rs
index a26d0c7689f..1c6977ac5c9 100644
--- a/crates/hyperswitch_domain_models/src/router_request_types/authentication.rs
+++ b/crates/hyperswitch_domain_models/src/router_request_types/authentication.rs
@@ -75,7 +75,7 @@ pub struct MessageExtensionAttribute {
     pub id: String,
     pub name: String,
     pub criticality_indicator: bool,
-    pub data: String,
+    pub data: serde_json::Value,
 }
 
 #[derive(Clone, Default, Debug)]

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

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

## Description
Fix deserlization  error for Nuvei card 3ds

### 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`
2. `crates/router/src/configs`
3. `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?
Create nuvie card 3ds
```
curl --location 'http://localhost:8080/payments' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: dev_5iub419oM0WIf9pI6nHrCbopoQ5dSKQEJkyPJZCmYbqECx5KC61S7N1yl7c1IdKD' \
--data-raw '{
    "amount": 15100,
    "currency": "EUR",
    "confirm": true,
    "customer_id":"nithxxinn",
    "return_url": "https://www.google.com",
    "capture_method": "automatic",
    "payment_method": "card",
    "payment_method_type": "credit",
    "authentication_type": "three_ds",
    "description": "hellow world",
    "billing": {
        "address": {
            "zip": "560095",
            "country": "US",
            "first_name": "Sakil",
            "last_name": "Mostak",
            "line1": "Fasdf",
            "line2": "Fasdf",
            "city": "Fasdf"
        }
    },
    "browser_info": {
        "accept_header": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
        "ip_address": "192.168.1.1",
        "java_enabled": false,
        "java_script_enabled": true,
        "language": "en-US",
        "color_depth": 24,
        "screen_height": 1080,
        "screen_width": 1920,
        "time_zone": 330,
        "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
    },
    "email": "hello@gmail.com",
    "payment_method_data": {
        "card": {
            "card_number": "2221008123677736",
            "card_exp_month": "12",
            "card_exp_year": "2030",
            "card_holder_name": "CL-BRW2",
            "card_cvc": "217"
        }
    },
     "setup_future_usage": "on_session"
}'
```
response
```
{
    "payment_id": "pay_SwA17VK0vJc9lZyksSsp",
    "merchant_id": "merchant_1754896786",
    "status": "requires_customer_action",
    "amount": 15100,
    "net_amount": 15100,
    "shipping_cost": null,
    "amount_capturable": 15100,
    "amount_received": null,
    "connector": "nuvei",
    "client_secret": "pay_SwA17VK0vJc9lZyksSsp_secret_1Le4qoHaeDahJN4pDv4N",
    "created": "2025-08-11T12:47:40.099Z",
    "currency": "EUR",
    "customer_id": "nithxxinn",
    "customer": {
        "id": "nithxxinn",
        "name": null,
        "email": "hello@gmail.com",
        "phone": null,
        "phone_country_code": null
    },
    "description": "hellow world",
    "refunds": null,
    "disputes": null,
    "mandate_id": null,
    "mandate_data": null,
    "setup_future_usage": "on_session",
    "off_session": null,
    "capture_on": null,
    "capture_method": "automatic",
    "payment_method": "card",
    "payment_method_data": {
        "card": {
            "last4": "7736",
            "card_type": null,
            "card_network": null,
            "card_issuer": null,
            "card_issuing_country": null,
            "card_isin": "222100",
            "card_extended_bin": null,
            "card_exp_month": "12",
            "card_exp_year": "2030",
            "card_holder_name": "CL-BRW2",
            "payment_checks": {
                "avs_description": null,
                "avs_result_code": "",
                "cvv_2_reply_code": "",
                "cvv_2_description": null,
                "merchant_advice_code": "",
                "merchant_advice_code_description": null
            },
            "authentication_data": {
                "cReq": "eyJ0aHJlZURTU2VydmVyVHJhbnNJRCI6IjZjNzNkZWQ5LTRmMzEtNDNjMS1iYjdmLTEwMDA2YmYyMTBmYiIsImFjc1RyYW5zSUQiOiIzZmRhNGVjYS0xMzI3LTQyZjctOGU2Ny1mYzE4ZDUxNDM0NTIiLCJjaGFsbGVuZ2VXaW5kb3dTaXplIjoiMDUiLCJtZXNzYWdlVHlwZSI6IkNSZXEiLCJtZXNzYWdlVmVyc2lvbiI6IjIuMi4wIn0",
                "flow": "challenge",
                "acsUrl": "https://3dsn.sandbox.safecharge.com/ThreeDSACSEmulatorChallenge/api/ThreeDSACSChallengeController/ChallengePage?eyJub3RpZmljYXRpb25VUkwiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvcGF5bWVudHMvcGF5X1N3QTE3VkswdkpjOWxaeWtzU3NwL21lcmNoYW50XzE3NTQ4OTY3ODYvcmVkaXJlY3QvY29tcGxldGUvbnV2ZWkiLCJ0aHJlZURTU2VydmVyVHJhbnNJRCI6IjZjNzNkZWQ5LTRmMzEtNDNjMS1iYjdmLTEwMDA2YmYyMTBmYiIsImFjc1RyYW5zSUQiOiIzZmRhNGVjYS0xMzI3LTQyZjctOGU2Ny1mYzE4ZDUxNDM0NTIiLCJkc1RyYW5zSUQiOiI3ZGUyY2YxZC00MmYxLTQ1ZWItOGE1Mi02MmQ5Mjk3OWEwOWUiLCJkYXRhIjpudWxsLCJNZXNzYWdlVmVyc2lvbiI6IjIuMi4wIn0=",
                "version": "2.2.0",
                "threeDFlow": "1",
                "decisionReason": "NoPreference",
                "threeDReasonId": "",
                "acquirerDecision": "ExemptionRequest",
                "challengePreferenceReason": "12",
                "isExemptionRequestInAuthentication": "0"
            }
        },
        "billing": null
    },
    "payment_token": "token_jptsctTb26hNYSmaPHom",
    "shipping": null,
    "billing": {
        "address": {
            "city": "Fasdf",
            "country": "US",
            "line1": "Fasdf",
            "line2": "Fasdf",
            "line3": null,
            "zip": "560095",
            "state": null,
            "first_name": "Sakil",
            "last_name": "Mostak",
            "origin_zip": null
        },
        "phone": null,
        "email": null
    },
    "order_details": null,
    "email": "hello@gmail.com",
    "name": null,
    "phone": null,
    "return_url": "https://www.google.com/",
    "authentication_type": "three_ds",
    "statement_descriptor_name": null,
    "statement_descriptor_suffix": null,
    "next_action": {
        "type": "redirect_to_url",
        "redirect_to_url": "http://localhost:8080/payments/redirect/pay_SwA17VK0vJc9lZyksSsp/merchant_1754896786/pay_SwA17VK0vJc9lZyksSsp_1"
    },
    "cancellation_reason": null,
    "error_code": null,
    "error_message": null,
    "unified_code": null,
    "unified_message": null,
    "payment_experience": null,
    "payment_method_type": "credit",
    "connector_label": null,
    "business_country": null,
    "business_label": "default",
    "business_sub_label": null,
    "allowed_payment_method_types": null,
    "ephemeral_key": {
        "customer_id": "nithxxinn",
        "created_at": 1754916460,
        "expires": 1754920060,
        "secret": "epk_00825ca507a647b1a68b6e174af4ad28"
    },
    "manual_retry_allowed": null,
    "connector_transaction_id": "8110000000012074375",
    "frm_message": null,
    "metadata": null,
    "connector_metadata": null,
    "feature_metadata": null,
    "reference_id": "7784849111",
    "payment_link": null,
    "profile_id": "pro_Ff3vG29EedTBVrRtdf20",
    "surcharge_details": null,
    "attempt_count": 1,
    "merchant_decision": null,
    "merchant_connector_id": "mca_vvdYt5E4uXbNvYftGlYf",
    "incremental_authorization_allowed": null,
    "authorization_count": null,
    "incremental_authorizations": null,
    "external_authentication_details": null,
    "external_3ds_authentication_attempted": false,
    "expires_on": "2025-08-11T13:02:40.099Z",
    "fingerprint": null,
    "browser_info": {
        "language": "en-US",
        "time_zone": 330,
        "ip_address": "192.168.1.1",
        "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36",
        "color_depth": 24,
        "java_enabled": false,
        "screen_width": 1920,
        "accept_header": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
        "screen_height": 1080,
        "java_script_enabled": true
    },
    "payment_channel": null,
    "payment_method_id": null,
    "network_transaction_id": null,
    "payment_method_status": null,
    "updated": "2025-08-11T12:47:42.875Z",
    "split_payments": null,
    "frm_metadata": null,
    "extended_authorization_applied": null,
    "capture_before": null,
    "merchant_order_reference_id": null,
    "order_tax_amount": null,
    "connector_mandate_id": null,
    "card_discovery": "manual",
    "force_3ds_challenge": false,
    "force_3ds_challenge_trigger": false,
    "issuer_error_code": null,
    "issuer_error_message": null,
    "is_iframe_redirection_enabled": null,
    "whole_connector_response": null,
    "enable_partial_authorization": null
}
```
Complete payment using redirection

2. Do psync
Response
```
{
    "payment_id": "pay_SwA17VK0vJc9lZyksSsp",
    "merchant_id": "merchant_1754896786",
    "status": "succeeded",
    "amount": 15100,
    "net_amount": 15100,
    "shipping_cost": null,
    "amount_capturable": 0,
    "amount_received": 15100,
    "connector": "nuvei",
    "client_secret": "pay_SwA17VK0vJc9lZyksSsp_secret_1Le4qoHaeDahJN4pDv4N",
    "created": "2025-08-11T12:47:40.099Z",
    "currency": "EUR",
    "customer_id": "nithxxinn",
    "customer": {
        "id": "nithxxinn",
        "name": null,
        "email": "hello@gmail.com",
        "phone": null,
        "phone_country_code": null
    },
    "description": "hellow world",
    "refunds": null,
    "disputes": null,
    "mandate_id": null,
    "mandate_data": null,
    "setup_future_usage": "on_session",
    "off_session": null,
    "capture_on": null,
    "capture_method": "automatic",
    "payment_method": "card",
    "payment_method_data": {
        "card": {
            "last4": "7736",
            "card_type": null,
            "card_network": null,
            "card_issuer": null,
            "card_issuing_country": null,
            "card_isin": "222100",
            "card_extended_bin": null,
            "card_exp_month": "12",
            "card_exp_year": "2030",
            "card_holder_name": "CL-BRW2",
            "payment_checks": {
                "avs_description": null,
                "avs_result_code": "",
                "cvv_2_reply_code": "",
                "cvv_2_description": null,
                "merchant_advice_code": "",
                "merchant_advice_code_description": null
            },
            "authentication_data": {
                "flow": "challenge",
                "decisionReason": "NoPreference",
                "acquirerDecision": "ExemptionRequest",
                "challengePreferenceReason": "12"
            }
        },
        "billing": null
    },
    "payment_token": "token_jptsctTb26hNYSmaPHom",
    "shipping": null,
    "billing": {
        "address": {
            "city": "Fasdf",
            "country": "US",
            "line1": "Fasdf",
            "line2": "Fasdf",
            "line3": null,
            "zip": "560095",
            "state": null,
            "first_name": "Sakil",
            "last_name": "Mostak",
            "origin_zip": null
        },
        "phone": null,
        "email": null
    },
    "order_details": null,
    "email": "hello@gmail.com",
    "name": null,
    "phone": null,
    "return_url": "https://www.google.com/",
    "authentication_type": "three_ds",
    "statement_descriptor_name": null,
    "statement_descriptor_suffix": null,
    "next_action": null,
    "cancellation_reason": null,
    "error_code": null,
    "error_message": null,
    "unified_code": null,
    "unified_message": null,
    "payment_experience": null,
    "payment_method_type": "credit",
    "connector_label": null,
    "business_country": null,
    "business_label": "default",
    "business_sub_label": null,
    "allowed_payment_method_types": null,
    "ephemeral_key": null,
    "manual_retry_allowed": false,
    "connector_transaction_id": "8110000000012074525",
    "frm_message": null,
    "metadata": null,
    "connector_metadata": null,
    "feature_metadata": null,
    "reference_id": "7784849111",
    "payment_link": null,
    "profile_id": "pro_Ff3vG29EedTBVrRtdf20",
    "surcharge_details": null,
    "attempt_count": 1,
    "merchant_decision": null,
    "merchant_connector_id": "mca_vvdYt5E4uXbNvYftGlYf",
    "incremental_authorization_allowed": null,
    "authorization_count": null,
    "incremental_authorizations": null,
    "external_authentication_details": null,
    "external_3ds_authentication_attempted": false,
    "expires_on": "2025-08-11T13:02:40.099Z",
    "fingerprint": null,
    "browser_info": {
        "language": "en-US",
        "time_zone": 330,
        "ip_address": "192.168.1.1",
        "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36",
        "color_depth": 24,
        "java_enabled": false,
        "screen_width": 1920,
        "accept_header": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
        "screen_height": 1080,
        "java_script_enabled": true
    },
    "payment_channel": null,
    "payment_method_id": null,
    "network_transaction_id": null,
    "payment_method_status": null,
    "updated": "2025-08-11T12:49:18.842Z",
    "split_payments": null,
    "frm_metadata": null,
    "extended_authorization_applied": null,
    "capture_before": null,
    "merchant_order_reference_id": null,
    "order_tax_amount": null,
    "connector_mandate_id": null,
    "card_discovery": "manual",
    "force_3ds_challenge": false,
    "force_3ds_challenge_trigger": false,
    "issuer_error_code": null,
    "issuer_error_message": null,
    "is_iframe_redirection_enabled": null,
    "whole_connector_response": null,
    "enable_partial_authorization": null
}
```

cypress test
<img width="1486" height="1756" alt="Screenshot 2025-08-12 at 1 41 17 PM" src="https://github.com/user-attachments/assets/e52ca0ab-1600-48ca-8430-3b3e80ba4545" />

<img width="1824" height="1550" alt="Screenshot 2025-08-12 at 4 44 25 PM" src="https://github.com/user-attachments/assets/42c36473-c99e-489c-b668-07782a3b7a99" />

<img width="855" height="792" alt="Screenshot 2025-08-19 at 3 30 24 PM" src="https://github.com/user-attachments/assets/78d85781-a5e4-4e6c-842a-26736dd57151" />



## 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
