Bug: [Nexixpay]: handle error_code and error_message in failure responses of nexixpay



Nexixpay does not send error_code and error_message in case of failure responses. We will send NO_ERROR_CODE and nexixpay operation result as error_message in this case.
diff --git a/crates/hyperswitch_connectors/src/connectors/nexixpay/transformers.rs b/crates/hyperswitch_connectors/src/connectors/nexixpay/transformers.rs
index 68f3b4bb695..32e630a2be7 100644
--- a/crates/hyperswitch_connectors/src/connectors/nexixpay/transformers.rs
+++ b/crates/hyperswitch_connectors/src/connectors/nexixpay/transformers.rs
@@ -8,7 +8,7 @@ use common_utils::{
 use error_stack::ResultExt;
 use hyperswitch_domain_models::{
     payment_method_data::PaymentMethodData,
-    router_data::{ConnectorAuthType, RouterData},
+    router_data::{ConnectorAuthType, ErrorResponse, RouterData},
     router_flow_types::{
         refunds::{Execute, RSync},
         SetupMandate,
@@ -25,9 +25,10 @@ use hyperswitch_domain_models::{
         PaymentsCompleteAuthorizeRouterData, PaymentsPreProcessingRouterData, RefundsRouterData,
     },
 };
-use hyperswitch_interfaces::errors;
+use hyperswitch_interfaces::{consts::NO_ERROR_CODE, errors};
 use masking::{ExposeInterface, Secret};
 use serde::{Deserialize, Serialize};
+use strum::Display;
 
 use crate::{
     types::{RefundsResponseRouterData, ResponseRouterData},
@@ -305,6 +306,23 @@ fn update_nexi_meta_data(
     }))
 }
 
+pub fn get_error_response(
+    operation_result: NexixpayPaymentStatus,
+    status_code: u16,
+) -> ErrorResponse {
+    ErrorResponse {
+        status_code,
+        code: NO_ERROR_CODE.to_string(),
+        message: operation_result.to_string(),
+        reason: Some(operation_result.to_string()),
+        attempt_status: None,
+        connector_transaction_id: None,
+        network_advice_code: None,
+        network_decline_code: None,
+        network_error_message: None,
+    }
+}
+
 #[derive(Debug, Clone, Serialize, Deserialize)]
 #[serde(rename_all = "camelCase")]
 pub struct ThreeDSAuthData {
@@ -425,22 +443,35 @@ impl<F>
             is_auto_capture,
         })?);
 
-        Ok(Self {
-            status: AttemptStatus::from(item.response.operation.operation_result),
-            response: Ok(PaymentsResponseData::TransactionResponse {
-                resource_id: ResponseId::ConnectorTransactionId(
-                    item.response.operation.order_id.clone(),
-                ),
-                redirection_data: Box::new(None),
-                mandate_reference: Box::new(None),
-                connector_metadata,
-                network_txn_id: None,
-                connector_response_reference_id: Some(item.response.operation.order_id),
-                incremental_authorization_allowed: None,
-                charges: None,
+        let status = AttemptStatus::from(item.response.operation.operation_result.clone());
+        match status {
+            AttemptStatus::Failure => {
+                let response = Err(get_error_response(
+                    item.response.operation.operation_result.clone(),
+                    item.http_code,
+                ));
+                Ok(Self {
+                    response,
+                    ..item.data
+                })
+            }
+            _ => Ok(Self {
+                status,
+                response: Ok(PaymentsResponseData::TransactionResponse {
+                    resource_id: ResponseId::ConnectorTransactionId(
+                        item.response.operation.order_id.clone(),
+                    ),
+                    redirection_data: Box::new(None),
+                    mandate_reference: Box::new(None),
+                    connector_metadata,
+                    network_txn_id: None,
+                    connector_response_reference_id: Some(item.response.operation.order_id),
+                    incremental_authorization_allowed: None,
+                    charges: None,
+                }),
+                ..item.data
             }),
-            ..item.data
-        })
+        }
     }
 }
 
@@ -632,7 +663,7 @@ impl TryFrom<&ConnectorAuthType> for NexixpayAuthType {
     }
 }
 
-#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
+#[derive(Display, Debug, Clone, Serialize, Deserialize, PartialEq)]
 #[serde(rename_all = "SCREAMING_SNAKE_CASE")]
 pub enum NexixpayPaymentStatus {
     Authorized,
@@ -821,51 +852,80 @@ impl<F>
                     },
                     psync_flow: NexixpayPaymentIntent::Authorize
                 }));
-                Ok(Self {
-                    status: AttemptStatus::from(response_body.operation.operation_result.clone()),
-                    response: Ok(PaymentsResponseData::TransactionResponse {
-                        resource_id: ResponseId::ConnectorTransactionId(
-                            response_body.operation.order_id.clone(),
-                        ),
-                        redirection_data: Box::new(Some(redirection_form.clone())),
-                        mandate_reference: Box::new(Some(MandateReference {
-                            connector_mandate_id: item
-                                .data
-                                .connector_mandate_request_reference_id
-                                .clone(),
-                            payment_method_id: None,
-                            mandate_metadata: None,
-                            connector_mandate_request_reference_id: None,
-                        })),
-                        connector_metadata,
-                        network_txn_id: None,
-                        connector_response_reference_id: Some(
-                            response_body.operation.order_id.clone(),
-                        ),
-                        incremental_authorization_allowed: None,
-                        charges: None,
+                let status = AttemptStatus::from(response_body.operation.operation_result.clone());
+                match status {
+                    AttemptStatus::Failure => {
+                        let response = Err(get_error_response(
+                            response_body.operation.operation_result.clone(),
+                            item.http_code,
+                        ));
+                        Ok(Self {
+                            response,
+                            ..item.data
+                        })
+                    }
+                    _ => Ok(Self {
+                        status,
+                        response: Ok(PaymentsResponseData::TransactionResponse {
+                            resource_id: ResponseId::ConnectorTransactionId(
+                                response_body.operation.order_id.clone(),
+                            ),
+                            redirection_data: Box::new(Some(redirection_form.clone())),
+                            mandate_reference: Box::new(Some(MandateReference {
+                                connector_mandate_id: item
+                                    .data
+                                    .connector_mandate_request_reference_id
+                                    .clone(),
+                                payment_method_id: None,
+                                mandate_metadata: None,
+                                connector_mandate_request_reference_id: None,
+                            })),
+                            connector_metadata,
+                            network_txn_id: None,
+                            connector_response_reference_id: Some(
+                                response_body.operation.order_id.clone(),
+                            ),
+                            incremental_authorization_allowed: None,
+                            charges: None,
+                        }),
+                        ..item.data
                     }),
-                    ..item.data
-                })
+                }
+            }
+            NexixpayPaymentsResponse::MandateResponse(ref mandate_response) => {
+                let status =
+                    AttemptStatus::from(mandate_response.operation.operation_result.clone());
+                match status {
+                    AttemptStatus::Failure => {
+                        let response = Err(get_error_response(
+                            mandate_response.operation.operation_result.clone(),
+                            item.http_code,
+                        ));
+                        Ok(Self {
+                            response,
+                            ..item.data
+                        })
+                    }
+                    _ => Ok(Self {
+                        status,
+                        response: Ok(PaymentsResponseData::TransactionResponse {
+                            resource_id: ResponseId::ConnectorTransactionId(
+                                mandate_response.operation.order_id.clone(),
+                            ),
+                            redirection_data: Box::new(None),
+                            mandate_reference: Box::new(None),
+                            connector_metadata: None,
+                            network_txn_id: None,
+                            connector_response_reference_id: Some(
+                                mandate_response.operation.order_id.clone(),
+                            ),
+                            incremental_authorization_allowed: None,
+                            charges: None,
+                        }),
+                        ..item.data
+                    }),
+                }
             }
-            NexixpayPaymentsResponse::MandateResponse(ref mandate_response) => Ok(Self {
-                status: AttemptStatus::from(mandate_response.operation.operation_result.clone()),
-                response: Ok(PaymentsResponseData::TransactionResponse {
-                    resource_id: ResponseId::ConnectorTransactionId(
-                        mandate_response.operation.order_id.clone(),
-                    ),
-                    redirection_data: Box::new(None),
-                    mandate_reference: Box::new(None),
-                    connector_metadata: None,
-                    network_txn_id: None,
-                    connector_response_reference_id: Some(
-                        mandate_response.operation.order_id.clone(),
-                    ),
-                    incremental_authorization_allowed: None,
-                    charges: None,
-                }),
-                ..item.data
-            }),
         }
     }
 }
@@ -975,27 +1035,42 @@ impl<F>
         } else {
             AttemptStatus::from(item.response.operation.operation_result.clone())
         };
-        Ok(Self {
-            status,
-            response: Ok(PaymentsResponseData::TransactionResponse {
-                resource_id: ResponseId::ConnectorTransactionId(
-                    item.response.operation.order_id.clone(),
-                ),
-                redirection_data: Box::new(None),
-                mandate_reference: Box::new(Some(MandateReference {
-                    connector_mandate_id: item.data.connector_mandate_request_reference_id.clone(),
-                    payment_method_id: None,
-                    mandate_metadata: None,
-                    connector_mandate_request_reference_id: None,
-                })),
-                connector_metadata,
-                network_txn_id: None,
-                connector_response_reference_id: Some(item.response.operation.order_id),
-                incremental_authorization_allowed: None,
-                charges: None,
+        match status {
+            AttemptStatus::Failure => {
+                let response = Err(get_error_response(
+                    item.response.operation.operation_result.clone(),
+                    item.http_code,
+                ));
+                Ok(Self {
+                    response,
+                    ..item.data
+                })
+            }
+            _ => Ok(Self {
+                status,
+                response: Ok(PaymentsResponseData::TransactionResponse {
+                    resource_id: ResponseId::ConnectorTransactionId(
+                        item.response.operation.order_id.clone(),
+                    ),
+                    redirection_data: Box::new(None),
+                    mandate_reference: Box::new(Some(MandateReference {
+                        connector_mandate_id: item
+                            .data
+                            .connector_mandate_request_reference_id
+                            .clone(),
+                        payment_method_id: None,
+                        mandate_metadata: None,
+                        connector_mandate_request_reference_id: None,
+                    })),
+                    connector_metadata,
+                    network_txn_id: None,
+                    connector_response_reference_id: Some(item.response.operation.order_id),
+                    incremental_authorization_allowed: None,
+                    charges: None,
+                }),
+                ..item.data
             }),
-            ..item.data
-        })
+        }
     }
 }
 
@@ -1122,25 +1197,32 @@ impl TryFrom<&NexixpayRouterData<&PaymentsCompleteAuthorizeRouterData>>
                     .into())
                 }
             };
-        let contract_id = Secret::new(
-            item.router_data
-                .connector_mandate_request_reference_id
-                .clone()
-                .ok_or_else(|| errors::ConnectorError::MissingRequiredField {
-                    field_name: "connector_mandate_request_reference_id",
-                })?,
-        );
+
+        let recurrence_request_obj = if item.router_data.request.is_mandate_payment() {
+            let contract_id = Secret::new(
+                item.router_data
+                    .connector_mandate_request_reference_id
+                    .clone()
+                    .ok_or_else(|| errors::ConnectorError::MissingRequiredField {
+                        field_name: "connector_mandate_request_reference_id",
+                    })?,
+            );
+            Some(RecurrenceRequest {
+                action: NexixpayRecurringAction::ContractCreation,
+                contract_id,
+                contract_type: ContractType::MitUnscheduled,
+            })
+        } else {
+            None
+        };
+
         Ok(Self {
             order: order_data,
             card: card?,
             operation_id,
             capture_type,
             three_d_s_auth_data,
-            recurrence: Some(RecurrenceRequest {
-                action: NexixpayRecurringAction::ContractCreation,
-                contract_id,
-                contract_type: ContractType::MitUnscheduled,
-            }),
+            recurrence: recurrence_request_obj,
         })
     }
 }
@@ -1159,25 +1241,41 @@ impl<F>
             PaymentsResponseData,
         >,
     ) -> Result<Self, Self::Error> {
-        Ok(Self {
-            status: AttemptStatus::from(item.response.operation_result),
-            response: Ok(PaymentsResponseData::TransactionResponse {
-                resource_id: ResponseId::ConnectorTransactionId(item.response.order_id.clone()),
-                redirection_data: Box::new(None),
-                mandate_reference: Box::new(Some(MandateReference {
-                    connector_mandate_id: item.data.connector_mandate_request_reference_id.clone(),
-                    payment_method_id: None,
-                    mandate_metadata: None,
-                    connector_mandate_request_reference_id: None,
-                })),
-                connector_metadata: item.data.request.connector_meta.clone(),
-                network_txn_id: None,
-                connector_response_reference_id: Some(item.response.order_id.clone()),
-                incremental_authorization_allowed: None,
-                charges: None,
+        let status = AttemptStatus::from(item.response.operation_result.clone());
+        match status {
+            AttemptStatus::Failure => {
+                let response = Err(get_error_response(
+                    item.response.operation_result.clone(),
+                    item.http_code,
+                ));
+                Ok(Self {
+                    response,
+                    ..item.data
+                })
+            }
+            _ => Ok(Self {
+                status,
+                response: Ok(PaymentsResponseData::TransactionResponse {
+                    resource_id: ResponseId::ConnectorTransactionId(item.response.order_id.clone()),
+                    redirection_data: Box::new(None),
+                    mandate_reference: Box::new(Some(MandateReference {
+                        connector_mandate_id: item
+                            .data
+                            .connector_mandate_request_reference_id
+                            .clone(),
+                        payment_method_id: None,
+                        mandate_metadata: None,
+                        connector_mandate_request_reference_id: None,
+                    })),
+                    connector_metadata: item.data.request.connector_meta.clone(),
+                    network_txn_id: None,
+                    connector_response_reference_id: Some(item.response.order_id.clone()),
+                    incremental_authorization_allowed: None,
+                    charges: None,
+                }),
+                ..item.data
             }),
-            ..item.data
-        })
+        }
     }
 }
 
@@ -1349,26 +1447,43 @@ impl
             },
             psync_flow: NexixpayPaymentIntent::Authorize
         }));
-        Ok(Self {
-            status: AttemptStatus::from(item.response.operation.operation_result.clone()),
-            response: Ok(PaymentsResponseData::TransactionResponse {
-                resource_id: ResponseId::ConnectorTransactionId(
-                    item.response.operation.order_id.clone(),
-                ),
-                redirection_data: Box::new(Some(redirection_form.clone())),
-                mandate_reference: Box::new(Some(MandateReference {
-                    connector_mandate_id: item.data.connector_mandate_request_reference_id.clone(),
-                    payment_method_id: None,
-                    mandate_metadata: None,
-                    connector_mandate_request_reference_id: None,
-                })),
-                connector_metadata,
-                network_txn_id: None,
-                connector_response_reference_id: Some(item.response.operation.order_id.clone()),
-                incremental_authorization_allowed: None,
-                charges: None,
+
+        let status = AttemptStatus::from(item.response.operation.operation_result.clone());
+        match status {
+            AttemptStatus::Failure => {
+                let response = Err(get_error_response(
+                    item.response.operation.operation_result.clone(),
+                    item.http_code,
+                ));
+                Ok(Self {
+                    response,
+                    ..item.data
+                })
+            }
+            _ => Ok(Self {
+                status,
+                response: Ok(PaymentsResponseData::TransactionResponse {
+                    resource_id: ResponseId::ConnectorTransactionId(
+                        item.response.operation.order_id.clone(),
+                    ),
+                    redirection_data: Box::new(Some(redirection_form.clone())),
+                    mandate_reference: Box::new(Some(MandateReference {
+                        connector_mandate_id: item
+                            .data
+                            .connector_mandate_request_reference_id
+                            .clone(),
+                        payment_method_id: None,
+                        mandate_metadata: None,
+                        connector_mandate_request_reference_id: None,
+                    })),
+                    connector_metadata,
+                    network_txn_id: None,
+                    connector_response_reference_id: Some(item.response.operation.order_id.clone()),
+                    incremental_authorization_allowed: None,
+                    charges: None,
+                }),
+                ..item.data
             }),
-            ..item.data
-        })
+        }
     }
 }

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

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

## Description
<!-- Describe your changes in detail -->
Nexixpay does not send error_code and error_message in case of failure responses. We will store NO_ERROR_CODE and nexixpay operation result as error_message in this case in our DB. This is sent in outgoing webhooks to the merchants.
Possible values of error messages:
1. Declined
2. DeniedByRisk
3. ThreedsFailed
4. Failed

### 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).
-->
Currently error_code and error_message goes null in case of webhooks to merchants for nexixpay. We need to pass NO_ERROR_CODE and nexixpay operation result as error_message as connector doesn't sends us any message or code.

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

Curls to test:
```
curl --location 'http://localhost:8080/payments' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: dev_nRAnqXGtbt60CdOO7rfovzh4MdEAIiaqnWc78AdQIx4yWnDXIKetpkjGFOvwFPcb' \
--data-raw '{
    "amount": 3596,
    "currency": "EUR",
    "amount_to_capture": 3596,
    "return_url": "https://google.com",
    "payment_method": "card",
    "payment_method_type": "credit",
    "payment_method_data": { 
        "card": {
            "card_number": "4742158750987704",
            "card_exp_month": "12",
            "card_exp_year": "30",
            "card_holder_name": "joseph Doe",
            "card_cvc": "861"
        }
    },

    "confirm": true,
    "profile_id": "pro_PBNVTjuDfM7y2MyljTkG",
    "capture_method": "manual",
    "capture_on": "2022-09-10T10:11:12Z",
    "authentication_type": "three_ds",
    "setup_future_usage": "off_session", 
    "customer": {
        "id": "customer123",
        "name": "John Doe",
        "email": "customer@gmail.com",
        "phone": "9999999999",
        "phone_country_code": "+1"
    },
    "customer_id": "customer123",
    "phone_country_code": "+1",
    "description": "Its my first payment request",
    
    "billing": {
        "address": {
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "city": "San Fransico",
            "state": "California",
            "zip": "94122",
            "country": "IT",
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": {
            "number": "8056594427",
            "country_code": "+91"
        },
        "email": "guest@example.com"
    },
    "shipping": {
        "address": {
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "city": "San Fransico",
            "state": "California",
            "zip": "94122",
            "country": "IT",
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": {
            "number": "8056594427",
            "country_code": "+91"
        },
        "email": "guest@example.com"
    },
    "statement_descriptor_name": "joseph",
    "statement_descriptor_suffix": "JS",
    "order_details": [
        {
            "product_name": "Apple iphone 15",
            "quantity": 1,
            "amount": 3545,
            "account_name": "transaction_processing"
        }
    ],
    "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": "128.0.0.1"
    },
    "customer_acceptance": {
          "acceptance_type": "online",
          "accepted_at":"1963-05-03T04:07:52.723Z",
          "online": {
            "ip_address":"127.0.0.1",
            "user_agent": "amet irure esse"
          }
    },
    
    "connector_metadata": {
        "noon": {
            "order_category": "pay"
        }
    },
    "payment_link": false,
    "payment_link_config": {
        "theme": "",
        "logo": "",
        "seller_name": "",
        "sdk_layout": "",
        "display_sdk_only": false,
        "enabled_saved_payment_method": false
    },
    "payment_type": "normal", 
    "request_incremental_authorization": false,
    "merchant_order_reference_id": "test_ord",
    "session_expiry": 900   
}'
```

Webhook for failed payment via nexixpay:
```
{
    "merchant_id": "merchant_1743678217",
    "event_id": "evt_0195fbf468957b539666947e6762e0af",
    "event_type": "payment_failed",
    "content": {
        "type": "payment_details",
        "object": {
            "payment_id": "pay_LOrSTDvs2fs1rntR8Bv7",
            "merchant_id": "merchant_1743678217",
            "status": "failed",
            "amount": 3596,
            "net_amount": 3596,
            "shipping_cost": null,
            "amount_capturable": 3596,
            "amount_received": null,
            "connector": "nexixpay",
            "client_secret": "pay_LOrSTDvs2fs1rntR8Bv7_secret_ZAC52wYDhKokuUvZjKws",
            "created": "2025-04-03T14:00:35.887Z",
            "currency": "EUR",
            "customer_id": "customer123",
            "customer": {
                "id": "customer123",
                "name": "John Doe",
                "email": "customer@gmail.com",
                "phone": "9999999999",
                "phone_country_code": "+1"
            },
            "description": "Its my first payment request",
            "refunds": null,
            "disputes": null,
            "mandate_id": null,
            "mandate_data": null,
            "setup_future_usage": "off_session",
            "off_session": null,
            "capture_on": null,
            "capture_method": "manual",
            "payment_method": "card",
            "payment_method_data": {
                "card": {
                    "last4": "7704",
                    "card_type": null,
                    "card_network": null,
                    "card_issuer": null,
                    "card_issuing_country": null,
                    "card_isin": "474215",
                    "card_extended_bin": null,
                    "card_exp_month": "12",
                    "card_exp_year": "30",
                    "card_holder_name": "joseph Doe",
                    "payment_checks": null,
                    "authentication_data": null
                },
                "billing": null
            },
            "payment_token": "token_r5dkurdxxncdiAxecZp2",
            "shipping": {
                "address": {
                    "city": "San Fransico",
                    "country": "IT",
                    "line1": "1467",
                    "line2": "Harrison Street",
                    "line3": "Harrison Street",
                    "zip": "94122",
                    "state": "California",
                    "first_name": "joseph",
                    "last_name": "Doe"
                },
                "phone": {
                    "number": "8056594427",
                    "country_code": "+91"
                },
                "email": "guest@example.com"
            },
            "billing": {
                "address": {
                    "city": "San Fransico",
                    "country": "IT",
                    "line1": "1467",
                    "line2": "Harrison Street",
                    "line3": "Harrison Street",
                    "zip": "94122",
                    "state": "California",
                    "first_name": "joseph",
                    "last_name": "Doe"
                },
                "phone": {
                    "number": "8056594427",
                    "country_code": "+91"
                },
                "email": "guest@example.com"
            },
            "order_details": [
                {
                    "brand": null,
                    "amount": 3545,
                    "category": null,
                    "quantity": 1,
                    "tax_rate": null,
                    "product_id": null,
                    "product_name": "Apple iphone 15",
                    "product_type": null,
                    "sub_category": null,
                    "product_img_link": null,
                    "product_tax_code": null,
                    "total_tax_amount": null,
                    "requires_shipping": null
                }
            ],
            "email": "customer@gmail.com",
            "name": "John Doe",
            "phone": "9999999999",
            "return_url": "https://google.com/",
            "authentication_type": "three_ds",
            "statement_descriptor_name": "joseph",
            "statement_descriptor_suffix": "JS",
            "next_action": null,
            "cancellation_reason": null,
            "error_code": "No error code",
            "error_message": "ThreedsFailed",
            "unified_code": "UE_9000",
            "unified_message": "Something went wrong",
            "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": true,
            "connector_transaction_id": "pay_LOrSTDvs2fs1rntR8Bv7_1",
            "frm_message": null,
            "metadata": null,
            "connector_metadata": {
                "apple_pay": null,
                "airwallex": null,
                "noon": {
                    "order_category": "pay"
                },
                "braintree": null
            },
            "feature_metadata": null,
            "reference_id": "pay_LOrSTDvs2fs1rntR8Bv7_1",
            "payment_link": null,
            "profile_id": "pro_9rN5ntPWxQFSDMxRHEZ5",
            "surcharge_details": null,
            "attempt_count": 1,
            "merchant_decision": null,
            "merchant_connector_id": "mca_bB3eKYzBDOgKte0bcmKl",
            "incremental_authorization_allowed": false,
            "authorization_count": null,
            "incremental_authorizations": null,
            "external_authentication_details": null,
            "external_3ds_authentication_attempted": false,
            "expires_on": "2025-04-03T14:15:35.887Z",
            "fingerprint": null,
            "browser_info": {
                "language": "nl-NL",
                "time_zone": 0,
                "ip_address": "128.0.0.1",
                "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",
                "color_depth": 24,
                "java_enabled": true,
                "screen_width": 1536,
                "accept_header": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
                "screen_height": 723,
                "java_script_enabled": true
            },
            "payment_method_id": "pm_stzSPzwuoRaFMpPpYb9r",
            "payment_method_status": "inactive",
            "updated": "2025-04-03T14:00:53.638Z",
            "split_payments": null,
            "frm_metadata": null,
            "extended_authorization_applied": null,
            "capture_before": null,
            "merchant_order_reference_id": "test_ord",
            "order_tax_amount": null,
            "connector_mandate_id": "6Hj8lx8blnGI3EMXRX",
            "card_discovery": "manual",
            "issuer_error_code": null,
            "issuer_error_message": null
        }
    },
    "timestamp": "2025-04-03T14:00:53.654Z"
}
```


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