Bug: [FEATURE] [BOA/Cybersource] Store AVS Response in connector metadata



### Feature Description

The AVS fields in payments response for authorize flow should be stored in connector metadata.

### Possible Implementation

The AVS fields in payments response for authorize flow should be stored in connector metadata.

### Have you spent some time checking if this feature request 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/router/src/connector/bankofamerica.rs b/crates/router/src/connector/bankofamerica.rs
index 1e0856a9ccc..aeb3dafcfa2 100644
--- a/crates/router/src/connector/bankofamerica.rs
+++ b/crates/router/src/connector/bankofamerica.rs
@@ -205,7 +205,7 @@ impl ConnectorCommon for Bankofamerica {
         };
         match response {
             transformers::BankOfAmericaErrorResponse::StandardError(response) => {
-                let (code, message) = match response.error_information {
+                let (code, connector_reason) = match response.error_information {
                     Some(ref error_info) => (error_info.reason.clone(), error_info.message.clone()),
                     None => (
                         response
@@ -218,13 +218,13 @@ impl ConnectorCommon for Bankofamerica {
                             .map_or(error_message.to_string(), |message| message),
                     ),
                 };
-                let connector_reason = match response.details {
+                let message = match response.details {
                     Some(details) => details
                         .iter()
                         .map(|det| format!("{} : {}", det.field, det.reason))
                         .collect::<Vec<_>>()
                         .join(", "),
-                    None => message.clone(),
+                    None => connector_reason.clone(),
                 };
 
                 Ok(ErrorResponse {
diff --git a/crates/router/src/connector/bankofamerica/transformers.rs b/crates/router/src/connector/bankofamerica/transformers.rs
index e024eb7a501..6abe1b634df 100644
--- a/crates/router/src/connector/bankofamerica/transformers.rs
+++ b/crates/router/src/connector/bankofamerica/transformers.rs
@@ -343,6 +343,30 @@ pub struct ClientReferenceInformation {
     code: Option<String>,
 }
 
+#[derive(Debug, Clone, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct ClientProcessorInformation {
+    avs: Option<Avs>,
+}
+
+#[derive(Debug, Clone, Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct ClientRiskInformation {
+    rules: Option<Vec<ClientRiskInformationRules>>,
+}
+
+#[derive(Debug, Clone, Deserialize)]
+pub struct ClientRiskInformationRules {
+    name: String,
+}
+
+#[derive(Debug, Clone, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Avs {
+    code: String,
+    code_raw: String,
+}
+
 impl
     TryFrom<(
         &BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>,
@@ -658,10 +682,12 @@ pub struct BankOfAmericaClientReferenceResponse {
     id: String,
     status: BankofamericaPaymentStatus,
     client_reference_information: ClientReferenceInformation,
+    processor_information: Option<ClientProcessorInformation>,
+    risk_information: Option<ClientRiskInformation>,
     error_information: Option<BankOfAmericaErrorInformation>,
 }
 
-#[derive(Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize)]
 #[serde(rename_all = "camelCase")]
 pub struct BankOfAmericaErrorInformationResponse {
     id: String,
@@ -674,6 +700,55 @@ pub struct BankOfAmericaErrorInformation {
     message: Option<String>,
 }
 
+impl<F, T>
+    From<(
+        &BankOfAmericaErrorInformationResponse,
+        types::ResponseRouterData<F, BankOfAmericaPaymentsResponse, T, types::PaymentsResponseData>,
+        Option<enums::AttemptStatus>,
+    )> for types::RouterData<F, T, types::PaymentsResponseData>
+{
+    fn from(
+        (error_response, item, transaction_status): (
+            &BankOfAmericaErrorInformationResponse,
+            types::ResponseRouterData<
+                F,
+                BankOfAmericaPaymentsResponse,
+                T,
+                types::PaymentsResponseData,
+            >,
+            Option<enums::AttemptStatus>,
+        ),
+    ) -> Self {
+        let error_reason = error_response
+            .error_information
+            .message
+            .to_owned()
+            .unwrap_or(consts::NO_ERROR_MESSAGE.to_string());
+        let error_message = error_response.error_information.reason.to_owned();
+        let response = Err(types::ErrorResponse {
+            code: error_message
+                .clone()
+                .unwrap_or(consts::NO_ERROR_CODE.to_string()),
+            message: error_message.unwrap_or(consts::NO_ERROR_MESSAGE.to_string()),
+            reason: Some(error_reason),
+            status_code: item.http_code,
+            attempt_status: None,
+            connector_transaction_id: Some(error_response.id.clone()),
+        });
+        match transaction_status {
+            Some(status) => Self {
+                response,
+                status,
+                ..item.data
+            },
+            None => Self {
+                response,
+                ..item.data
+            },
+        }
+    }
+}
+
 fn get_error_response_if_failure(
     (info_response, status, http_code): (
         &BankOfAmericaClientReferenceResponse,
@@ -684,6 +759,7 @@ fn get_error_response_if_failure(
     if utils::is_payment_failure(status) {
         Some(types::ErrorResponse::from((
             &info_response.error_information,
+            &info_response.risk_information,
             http_code,
             info_response.id.clone(),
         )))
@@ -706,7 +782,10 @@ fn get_payment_response(
             resource_id: types::ResponseId::ConnectorTransactionId(info_response.id.clone()),
             redirection_data: None,
             mandate_reference: None,
-            connector_metadata: None,
+            connector_metadata: info_response
+                .processor_information
+                .as_ref()
+                .map(|processor_information| serde_json::json!({"avs_response": processor_information.avs})),
             network_txn_id: None,
             connector_response_reference_id: Some(
                 info_response
@@ -752,26 +831,13 @@ impl<F>
                     ..item.data
                 })
             }
-            BankOfAmericaPaymentsResponse::ErrorInformation(error_response) => Ok(Self {
-                response: {
-                    let error_reason = &error_response.error_information.reason;
-
-                    Err(types::ErrorResponse {
-                        code: error_reason
-                            .clone()
-                            .unwrap_or(consts::NO_ERROR_CODE.to_string()),
-                        message: error_reason
-                            .clone()
-                            .unwrap_or(consts::NO_ERROR_MESSAGE.to_string()),
-                        reason: error_response.error_information.message,
-                        status_code: item.http_code,
-                        attempt_status: None,
-                        connector_transaction_id: Some(error_response.id),
-                    })
-                },
-                status: enums::AttemptStatus::Failure,
-                ..item.data
-            }),
+            BankOfAmericaPaymentsResponse::ErrorInformation(ref error_response) => {
+                Ok(Self::from((
+                    &error_response.clone(),
+                    item,
+                    Some(enums::AttemptStatus::Failure),
+                )))
+            }
         }
     }
 }
@@ -806,24 +872,9 @@ impl<F>
                     ..item.data
                 })
             }
-            BankOfAmericaPaymentsResponse::ErrorInformation(error_response) => Ok(Self {
-                response: {
-                    let error_reason = &error_response.error_information.reason;
-                    Err(types::ErrorResponse {
-                        code: error_reason
-                            .clone()
-                            .unwrap_or(consts::NO_ERROR_CODE.to_string()),
-                        message: error_reason
-                            .clone()
-                            .unwrap_or(consts::NO_ERROR_MESSAGE.to_string()),
-                        reason: error_response.error_information.message,
-                        status_code: item.http_code,
-                        attempt_status: None,
-                        connector_transaction_id: Some(error_response.id),
-                    })
-                },
-                ..item.data
-            }),
+            BankOfAmericaPaymentsResponse::ErrorInformation(ref error_response) => {
+                Ok(Self::from((&error_response.clone(), item, None)))
+            }
         }
     }
 }
@@ -858,24 +909,9 @@ impl<F>
                     ..item.data
                 })
             }
-            BankOfAmericaPaymentsResponse::ErrorInformation(error_response) => Ok(Self {
-                response: {
-                    let error_reason = &error_response.error_information.reason;
-                    Err(types::ErrorResponse {
-                        code: error_reason
-                            .clone()
-                            .unwrap_or(consts::NO_ERROR_CODE.to_string()),
-                        message: error_reason
-                            .clone()
-                            .unwrap_or(consts::NO_ERROR_MESSAGE.to_string()),
-                        reason: error_response.error_information.message,
-                        status_code: item.http_code,
-                        attempt_status: None,
-                        connector_transaction_id: Some(error_response.id),
-                    })
-                },
-                ..item.data
-            }),
+            BankOfAmericaPaymentsResponse::ErrorInformation(ref error_response) => {
+                Ok(Self::from((&error_response.clone(), item, None)))
+            }
         }
     }
 }
@@ -927,10 +963,12 @@ impl<F>
                     app_response.application_information.status,
                     item.data.request.is_auto_capture()?,
                 ));
+                let risk_info: Option<ClientRiskInformation> = None;
                 if utils::is_payment_failure(status) {
                     Ok(Self {
                         response: Err(types::ErrorResponse::from((
                             &app_response.error_information,
+                            &risk_info,
                             item.http_code,
                             app_response.id.clone(),
                         ))),
@@ -1213,8 +1251,8 @@ pub struct BankOfAmericaAuthenticationErrorResponse {
 #[derive(Debug, Deserialize)]
 #[serde(untagged)]
 pub enum BankOfAmericaErrorResponse {
-    StandardError(BankOfAmericaStandardErrorResponse),
     AuthenticationError(BankOfAmericaAuthenticationErrorResponse),
+    StandardError(BankOfAmericaStandardErrorResponse),
 }
 
 #[derive(Debug, Deserialize, Clone)]
@@ -1235,29 +1273,53 @@ pub struct AuthenticationErrorInformation {
     pub rmsg: String,
 }
 
-impl From<(&Option<BankOfAmericaErrorInformation>, u16, String)> for types::ErrorResponse {
+impl
+    From<(
+        &Option<BankOfAmericaErrorInformation>,
+        &Option<ClientRiskInformation>,
+        u16,
+        String,
+    )> for types::ErrorResponse
+{
     fn from(
-        (error_data, status_code, transaction_id): (
+        (error_data, risk_information, status_code, transaction_id): (
             &Option<BankOfAmericaErrorInformation>,
+            &Option<ClientRiskInformation>,
             u16,
             String,
         ),
     ) -> Self {
-        let error_message = error_data
+        let avs_message = risk_information
             .clone()
-            .and_then(|error_details| error_details.message);
+            .map(|client_risk_information| {
+                client_risk_information.rules.map(|rules| {
+                    rules
+                        .iter()
+                        .map(|risk_info| format!(" , {}", risk_info.name))
+                        .collect::<Vec<String>>()
+                        .join("")
+                })
+            })
+            .unwrap_or(Some("".to_string()));
         let error_reason = error_data
+            .clone()
+            .map(|error_details| {
+                error_details.message.unwrap_or("".to_string())
+                    + &avs_message.unwrap_or("".to_string())
+            })
+            .unwrap_or(consts::NO_ERROR_MESSAGE.to_string());
+        let error_message = error_data
             .clone()
             .and_then(|error_details| error_details.reason);
 
         Self {
-            code: error_reason
+            code: error_message
                 .clone()
                 .unwrap_or(consts::NO_ERROR_CODE.to_string()),
-            message: error_reason
+            message: error_message
                 .clone()
                 .unwrap_or(consts::NO_ERROR_MESSAGE.to_string()),
-            reason: error_message.clone(),
+            reason: Some(error_reason.clone()),
             status_code,
             attempt_status: Some(enums::AttemptStatus::Failure),
             connector_transaction_id: Some(transaction_id.clone()),
diff --git a/crates/router/src/connector/cybersource.rs b/crates/router/src/connector/cybersource.rs
index 33503102e4b..6c4ea4c61fe 100644
--- a/crates/router/src/connector/cybersource.rs
+++ b/crates/router/src/connector/cybersource.rs
@@ -124,7 +124,7 @@ impl ConnectorCommon for Cybersource {
         };
         match response {
             transformers::CybersourceErrorResponse::StandardError(response) => {
-                let (code, message) = match response.error_information {
+                let (code, connector_reason) = match response.error_information {
                     Some(ref error_info) => (error_info.reason.clone(), error_info.message.clone()),
                     None => (
                         response
@@ -137,13 +137,13 @@ impl ConnectorCommon for Cybersource {
                             .map_or(error_message.to_string(), |message| message),
                     ),
                 };
-                let connector_reason = match response.details {
+                let message = match response.details {
                     Some(details) => details
                         .iter()
                         .map(|det| format!("{} : {}", det.field, det.reason))
                         .collect::<Vec<_>>()
                         .join(", "),
-                    None => message.clone(),
+                    None => connector_reason.clone(),
                 };
 
                 Ok(types::ErrorResponse {
diff --git a/crates/router/src/connector/cybersource/transformers.rs b/crates/router/src/connector/cybersource/transformers.rs
index bc69fb78129..8ae2ce29e5b 100644
--- a/crates/router/src/connector/cybersource/transformers.rs
+++ b/crates/router/src/connector/cybersource/transformers.rs
@@ -1105,6 +1105,8 @@ pub struct CybersourceClientReferenceResponse {
     id: String,
     status: CybersourcePaymentStatus,
     client_reference_information: ClientReferenceInformation,
+    processor_information: Option<ClientProcessorInformation>,
+    risk_information: Option<ClientRiskInformation>,
     token_information: Option<CybersourceTokenInformation>,
     error_information: Option<CybersourceErrorInformation>,
 }
@@ -1136,6 +1138,30 @@ pub struct ClientReferenceInformation {
     code: Option<String>,
 }
 
+#[derive(Debug, Clone, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct ClientProcessorInformation {
+    avs: Option<Avs>,
+}
+
+#[derive(Debug, Clone, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Avs {
+    code: String,
+    code_raw: String,
+}
+
+#[derive(Debug, Clone, Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct ClientRiskInformation {
+    rules: Option<Vec<ClientRiskInformationRules>>,
+}
+
+#[derive(Debug, Clone, Deserialize)]
+pub struct ClientRiskInformationRules {
+    name: String,
+}
+
 #[derive(Debug, Clone, Deserialize)]
 #[serde(rename_all = "camelCase")]
 pub struct CybersourceTokenInformation {
@@ -1152,10 +1178,11 @@ impl<F, T>
     From<(
         &CybersourceErrorInformationResponse,
         types::ResponseRouterData<F, CybersourcePaymentsResponse, T, types::PaymentsResponseData>,
+        Option<enums::AttemptStatus>,
     )> for types::RouterData<F, T, types::PaymentsResponseData>
 {
     fn from(
-        (error_response, item): (
+        (error_response, item, transaction_status): (
             &CybersourceErrorInformationResponse,
             types::ResponseRouterData<
                 F,
@@ -1163,25 +1190,35 @@ impl<F, T>
                 T,
                 types::PaymentsResponseData,
             >,
+            Option<enums::AttemptStatus>,
         ),
     ) -> Self {
-        Self {
-            response: {
-                let error_reason = &error_response.error_information.reason;
-                Err(types::ErrorResponse {
-                    code: error_reason
-                        .clone()
-                        .unwrap_or(consts::NO_ERROR_CODE.to_string()),
-                    message: error_reason
-                        .clone()
-                        .unwrap_or(consts::NO_ERROR_MESSAGE.to_string()),
-                    reason: error_response.error_information.message.clone(),
-                    status_code: item.http_code,
-                    attempt_status: None,
-                    connector_transaction_id: Some(error_response.id.clone()),
-                })
+        let error_reason = error_response
+            .error_information
+            .message
+            .to_owned()
+            .unwrap_or(consts::NO_ERROR_MESSAGE.to_string());
+        let error_message = error_response.error_information.reason.to_owned();
+        let response = Err(types::ErrorResponse {
+            code: error_message
+                .clone()
+                .unwrap_or(consts::NO_ERROR_CODE.to_string()),
+            message: error_message.unwrap_or(consts::NO_ERROR_MESSAGE.to_string()),
+            reason: Some(error_reason),
+            status_code: item.http_code,
+            attempt_status: None,
+            connector_transaction_id: Some(error_response.id.clone()),
+        });
+        match transaction_status {
+            Some(status) => Self {
+                response,
+                status,
+                ..item.data
+            },
+            None => Self {
+                response,
+                ..item.data
             },
-            ..item.data
         }
     }
 }
@@ -1196,6 +1233,7 @@ fn get_error_response_if_failure(
     if utils::is_payment_failure(status) {
         Some(types::ErrorResponse::from((
             &info_response.error_information,
+            &info_response.risk_information,
             http_code,
             info_response.id.clone(),
         )))
@@ -1229,7 +1267,10 @@ fn get_payment_response(
                 resource_id: types::ResponseId::ConnectorTransactionId(info_response.id.clone()),
                 redirection_data: None,
                 mandate_reference,
-                connector_metadata: None,
+                connector_metadata: info_response
+                    .processor_information
+                    .as_ref()
+                    .map(|processor_information| serde_json::json!({"avs_response": processor_information.avs})),
                 network_txn_id: None,
                 connector_response_reference_id: Some(
                     info_response
@@ -1276,25 +1317,11 @@ impl<F>
                     ..item.data
                 })
             }
-            CybersourcePaymentsResponse::ErrorInformation(error_response) => {
-                let error_reason = &error_response.error_information.reason;
-                Ok(Self {
-                    response: Err(types::ErrorResponse {
-                        code: error_reason
-                            .clone()
-                            .unwrap_or(consts::NO_ERROR_CODE.to_string()),
-                        message: error_reason
-                            .clone()
-                            .unwrap_or(consts::NO_ERROR_MESSAGE.to_string()),
-                        reason: error_response.error_information.message,
-                        status_code: item.http_code,
-                        attempt_status: None,
-                        connector_transaction_id: Some(error_response.id.clone()),
-                    }),
-                    status: enums::AttemptStatus::Failure,
-                    ..item.data
-                })
-            }
+            CybersourcePaymentsResponse::ErrorInformation(ref error_response) => Ok(Self::from((
+                &error_response.clone(),
+                item,
+                Some(enums::AttemptStatus::Failure),
+            ))),
         }
     }
 }
@@ -1330,7 +1357,7 @@ impl<F>
                 })
             }
             CybersourcePaymentsResponse::ErrorInformation(ref error_response) => {
-                Ok(Self::from((&error_response.clone(), item)))
+                Ok(Self::from((&error_response.clone(), item, None)))
             }
         }
     }
@@ -1367,7 +1394,7 @@ impl<F>
                 })
             }
             CybersourcePaymentsResponse::ErrorInformation(ref error_response) => {
-                Ok(Self::from((&error_response.clone(), item)))
+                Ok(Self::from((&error_response.clone(), item, None)))
             }
         }
     }
@@ -1556,10 +1583,12 @@ impl<F>
                 ));
                 let incremental_authorization_allowed =
                     Some(status == enums::AttemptStatus::Authorized);
+                let risk_info: Option<ClientRiskInformation> = None;
                 if utils::is_payment_failure(status) {
                     Ok(Self {
                         response: Err(types::ErrorResponse::from((
                             &app_response.error_information,
+                            &risk_info,
                             item.http_code,
                             app_response.id.clone(),
                         ))),
@@ -1782,30 +1811,53 @@ pub struct AuthenticationErrorInformation {
     pub rmsg: String,
 }
 
-impl From<(&Option<CybersourceErrorInformation>, u16, String)> for types::ErrorResponse {
+impl
+    From<(
+        &Option<CybersourceErrorInformation>,
+        &Option<ClientRiskInformation>,
+        u16,
+        String,
+    )> for types::ErrorResponse
+{
     fn from(
-        (error_data, status_code, transaction_id): (
+        (error_data, risk_information, status_code, transaction_id): (
             &Option<CybersourceErrorInformation>,
+            &Option<ClientRiskInformation>,
             u16,
             String,
         ),
     ) -> Self {
-        let error_message = error_data
+        let avs_message = risk_information
             .clone()
-            .and_then(|error_details| error_details.message);
-
+            .map(|client_risk_information| {
+                client_risk_information.rules.map(|rules| {
+                    rules
+                        .iter()
+                        .map(|risk_info| format!(" , {}", risk_info.name))
+                        .collect::<Vec<String>>()
+                        .join("")
+                })
+            })
+            .unwrap_or(Some("".to_string()));
         let error_reason = error_data
+            .clone()
+            .map(|error_details| {
+                error_details.message.unwrap_or("".to_string())
+                    + &avs_message.unwrap_or("".to_string())
+            })
+            .unwrap_or(consts::NO_ERROR_MESSAGE.to_string());
+        let error_message = error_data
             .clone()
             .and_then(|error_details| error_details.reason);
 
         Self {
-            code: error_reason
+            code: error_message
                 .clone()
                 .unwrap_or(consts::NO_ERROR_CODE.to_string()),
-            message: error_reason
+            message: error_message
                 .clone()
                 .unwrap_or(consts::NO_ERROR_MESSAGE.to_string()),
-            reason: error_message.clone(),
+            reason: Some(error_reason.clone()),
             status_code,
             attempt_status: Some(enums::AttemptStatus::Failure),
             connector_transaction_id: Some(transaction_id.clone()),

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

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

## Description
<!-- Describe your changes in detail -->
This PR contains the following changes for BOA/Cybersource:
1.  The AVS response being sent by BOA/Cybersource for authorize flow is being stored in `connector_metadata`
2. In case of payments failing due to AVS check the failure reason will also contain the details of the AVS Check
3. In case of general failures the response message is used to populate our error reason and response details is used to populate our error message.

### 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`
4. `crates/router/src/configs`
5. `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).
-->
https://github.com/juspay/hyperswitch/issues/3272

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

1. Create a successful payment and verify that avs_response is stored in connector_metadata in db for the payment
<img width="1073" alt="image" src="https://github.com/juspay/hyperswitch/assets/41580413/ceed3f94-523c-424a-be4d-32657b193416">

Curl for creating payment:
```curl
curl --location 'http://localhost:8080/payments' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: API_KEY_HERE' \
--data-raw '{
  "amount": 1404,
  "currency": "USD",
  "confirm": true,
  "capture_method": "automatic",
  "capture_on": "2022-09-10T10:11:12Z",
  "customer_id": "CustomerX",
  "email": "guest@example.com",
  "authentication_type": "no_three_ds",
  "return_url": "https://google.com",
  "payment_method": "card",
  "payment_method_type": "credit",
  "payment_method_data": {
    "card": {
      "card_number": "4111111111111111",
      "card_exp_month": "12",
      "card_exp_year": "30",
      "card_holder_name": "joseph Doe",
      "card_cvc": "029"
    }
  },
  "billing": {
    "address": {
      "line1": "cq",
      "city": "dshcvjhdw",
      "state": "whecvjkcdv",
      "zip": "46205",
      "country": "MW",
      "first_name": "joseph",
      "last_name": "doe"
    },
    "phone": {
      "number": "12345",
      "country_code": "+93"
    }
  },
  "metadata": {
    "count_tickets": 1,
    "transaction_number": "12321"
  },
  "business_label": "food",
  "business_country": "US"
}'
```

connector_response: 
```json
Ok(Ok(Response { headers: Some({"cache-control": "no-cache, no-store, must-revalidate", "pragma": "no-cache", "expires": "-1", "strict-transport-security": "max-age=31536000", "content-type": "application/hal+json", "content-length": "1621", "x-response-time": "1481ms", "x-opnet-transaction-trace": "HIDDEN", "connection": "keep-alive", "v-c-correlation-id": "HIDDEN"}), response: b"{\"_links\":{\"void\":{\"method\":\"POST\",\"href\":\"/pts/v2/payments/7049799548496957104951/voids\"},\"self\":{\"method\":\"GET\",\"href\":\"/pts/v2/payments/7049799548496957104951\"}},\"clientReferenceInformation\":{\"code\":\"pay_D0hUwTOaupjcu8P2qqcH_1\"},\"consumerAuthenticationInformation\":{\"token\":\"HIDDEN"},\"id\":\"7049799548496957104951\",\"orderInformation\":{\"amountDetails\":{\"totalAmount\":\"14.04\",\"authorizedAmount\":\"14.04\",\"currency\":\"USD\"}},\"paymentAccountInformation\":{\"card\":{\"type\":\"001\"}},\"paymentInformation\":{\"tokenizedCard\":{\"type\":\"001\"},\"scheme\":\"VISA DEBIT\",\"bin\":\"411111\",\"accountType\":\"Visa Classic\",\"issuer\":\"HIDDEN SP. Z O.O\",\"card\":{\"type\":\"001\"},\"binCountry\":\"PL\"},\"processorInformation\":{\"systemTraceAuditNumber\":\"HIDDEN\",\"approvalCode\":\"HIDDEN\",\"cardVerification\":{\"resultCodeRaw\":\"M\",\"resultCode\":\"M\"},\"merchantAdvice\":{\"code\":\"01\",\"codeRaw\":\"M001\"},\"responseDetails\":\"ABC\",\"networkTransactionId\":\"HIDDEN\",\"retrievalReferenceNumber\":\"HIDDEN\",\"consumerAuthenticationResponse\":{\"code\":\"2\",\"codeRaw\":\"2\"},\"transactionId\":\"HIDDEN\",\"responseCode\":\"00\",**\"avs\":{\"code\":\"Y\",\"codeRaw\":\"Y\"}},**\"reconciliationId\":\"HIDDEN\",\"riskInformation\":{\"localTime\":\"15:32:34\",\"score\":{\"result\":\"68\",\"factorCodes\":[\"B\"],\"modelUsed\":\"default_cemea\"},\"infoCodes\":{\"address\":[\"MM-BIN\",\"UNV-ADDR\"],\"identityChange\":[\"ID-X-HPOS\"]},\"profile\":{\"earlyDecision\":\"ACCEPT\",\"name\":\"Standard mid-market profile\",\"selectorRule\":\"Default Active Profile\"}},\"status\":\"AUTHORIZED\",\"submitTimeUtc\":\"2024-01-11T13:32:35Z\"}", status_code: 201 }))
```


2. Testing can be done by creating a AVS mismatch error for a payment. You should see the following details in the error_message.
(AVS Mismatch can be triggered by enabling Fraud Rules on BOA/Cybersource Dashboard)
```json
{
    "payment_id": "pay_p6jsWMZ0Rdi2eZTasuTm",
    "merchant_id": "merchant_1704716850",
    "status": "failed",
    "amount": 1404,
    "net_amount": 1404,
    "amount_capturable": 0,
    "amount_received": null,
    "connector": "cybersource",
    "client_secret": "pay_p6jsWMZ0Rdi2eZTasuTm_secret_7P0lx3N6COfGLvS4yBRl",
    "created": "2024-01-11T13:37:01.254Z",
    "currency": "USD",
    "customer_id": "CustomerX",
    "description": null,
    "refunds": null,
    "disputes": null,
    "mandate_id": null,
    "mandate_data": null,
    "setup_future_usage": null,
    "off_session": null,
    "capture_on": null,
    "capture_method": "automatic",
    "payment_method": "card",
    "payment_method_data": {
        "card": {
            "last4": "1111",
            "card_type": null,
            "card_network": null,
            "card_issuer": null,
            "card_issuing_country": null,
            "card_isin": "411111",
            "card_exp_month": "12",
            "card_exp_year": "30",
            "card_holder_name": "joseph Doe"
        }
    },
    "payment_token": null,
    "shipping": null,
    "billing": {
        "address": {
            "city": "dshcvjhdw",
            "country": "MW",
            "line1": "cq",
            "line2": null,
            "line3": null,
            "zip": "46205",
            "state": "whecvjkcdv",
            "first_name": "joseph",
            "last_name": "doe"
        },
        "phone": {
            "number": "12345",
            "country_code": "+93"
        }
    },
    "order_details": null,
    "email": "guest@example.com",
    "name": "John Doe",
    "phone": "999999999",
    "return_url": "https://google.com/",
    "authentication_type": "no_three_ds",
    "statement_descriptor_name": null,
    "statement_descriptor_suffix": null,
    "next_action": null,
    "cancellation_reason": null,
    "error_code": "DECISION_PROFILE_REJECT",
    "error_message": "The order has been rejected by Decision Manager , Fraud Score - Reject",
    "unified_code": null,
    "unified_message": null,
    "payment_experience": null,
    "payment_method_type": "credit",
    "connector_label": "cybersource_US_food_default",
    "business_country": "US",
    "business_label": "food",
    "business_sub_label": null,
    "allowed_payment_method_types": null,
    "ephemeral_key": {
        "customer_id": "CustomerX",
        "created_at": 1704980221,
        "expires": 1704983821,
        "secret": "epk_83a362750bd34f1f85c1a3303905bf4b"
    },
    "manual_retry_allowed": true,
    "connector_transaction_id": "7049802214936686604953",
    "frm_message": null,
    "metadata": {
        "count_tickets": 1,
        "transaction_number": "5590043"
    },
    "connector_metadata": null,
    "feature_metadata": null,
    "reference_id": null,
    "payment_link": null,
    "profile_id": "pro_aLMwDWebJFLj05EIBPCm",
    "surcharge_details": null,
    "attempt_count": 1,
    "merchant_decision": null,
    "merchant_connector_id": "mca_x7psrN0rGR7OOaljMXC3",
    "incremental_authorization_allowed": false,
    "authorization_count": null,
    "incremental_authorizations": null
}
```

![Screenshot 2024-01-11 at 7 07 40 PM](https://github.com/juspay/hyperswitch/assets/41580413/f43168ea-21db-4032-abb4-968884b20447)



3. To create a general failure pass line1 as empty string. You should see the following error_message.
![Screenshot 2024-01-08 at 7 55 02 PM](https://github.com/juspay/hyperswitch/assets/41580413/71342cc7-3d55-4b1c-9ce1-b23dd3765f89)


## 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
- [ ] I added a [CHANGELOG](/CHANGELOG.md) entry if applicable
