Bug: [FEATURE] [BOA/Cybersource] Pass commerce indicator using card network for apple pay



### Feature Description

Apple pay transactions via BOA and Cybersource require a specific field `commerce_indicator` which is based on the card network type used during apple pay transactions.
https://docs.cybersource.com/content/dam/documentation/en/apple-pay/fdiglobal/so/applepay-so-fdiglobal.pdf

### Possible Implementation

`commerce_indicator` should be passed using the card network data being shared from SDK during apple pay payments for BOA and Cybersource

### 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/transformers.rs b/crates/router/src/connector/bankofamerica/transformers.rs
index 235321f1ac6..0be25b078bc 100644
--- a/crates/router/src/connector/bankofamerica/transformers.rs
+++ b/crates/router/src/connector/bankofamerica/transformers.rs
@@ -330,21 +330,34 @@ impl
     From<(
         &BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>,
         Option<PaymentSolution>,
+        Option<String>,
     )> for ProcessingInformation
 {
     fn from(
-        (item, solution): (
+        (item, solution, network): (
             &BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>,
             Option<PaymentSolution>,
+            Option<String>,
         ),
     ) -> Self {
+        let commerce_indicator = match network {
+            Some(card_network) => match card_network.to_lowercase().as_str() {
+                "amex" => "aesk",
+                "discover" => "dipb",
+                "mastercard" => "spa",
+                "visa" => "internet",
+                _ => "internet",
+            },
+            None => "internet",
+        }
+        .to_string();
         Self {
             capture: Some(matches!(
                 item.router_data.request.capture_method,
                 Some(enums::CaptureMethod::Automatic) | None
             )),
             payment_solution: solution.map(String::from),
-            commerce_indicator: String::from("internet"),
+            commerce_indicator,
         }
     }
 }
@@ -552,7 +565,7 @@ impl
                 card_type,
             },
         });
-        let processing_information = ProcessingInformation::from((item, None));
+        let processing_information = ProcessingInformation::from((item, None, None));
         let client_reference_information = ClientReferenceInformation::from(item);
         let merchant_defined_information =
             item.router_data.request.metadata.clone().map(|metadata| {
@@ -574,20 +587,25 @@ impl
     TryFrom<(
         &BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>,
         Box<ApplePayPredecryptData>,
+        payments::ApplePayWalletData,
     )> for BankOfAmericaPaymentsRequest
 {
     type Error = error_stack::Report<errors::ConnectorError>;
     fn try_from(
-        (item, apple_pay_data): (
+        (item, apple_pay_data, apple_pay_wallet_data): (
             &BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>,
             Box<ApplePayPredecryptData>,
+            payments::ApplePayWalletData,
         ),
     ) -> Result<Self, Self::Error> {
         let email = item.router_data.request.get_email()?;
         let bill_to = build_bill_to(item.router_data.get_billing()?, email)?;
         let order_information = OrderInformationWithBill::from((item, bill_to));
-        let processing_information =
-            ProcessingInformation::from((item, Some(PaymentSolution::ApplePay)));
+        let processing_information = ProcessingInformation::from((
+            item,
+            Some(PaymentSolution::ApplePay),
+            Some(apple_pay_wallet_data.payment_method.network),
+        ));
         let client_reference_information = ClientReferenceInformation::from(item);
         let expiration_month = apple_pay_data.get_expiry_month()?;
         let expiration_year = apple_pay_data.get_four_digit_expiry_year()?;
@@ -640,7 +658,7 @@ impl
             },
         });
         let processing_information =
-            ProcessingInformation::from((item, Some(PaymentSolution::GooglePay)));
+            ProcessingInformation::from((item, Some(PaymentSolution::GooglePay), None));
         let client_reference_information = ClientReferenceInformation::from(item);
         let merchant_defined_information =
             item.router_data.request.metadata.clone().map(|metadata| {
@@ -672,7 +690,7 @@ impl TryFrom<&BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>>
                     match item.router_data.payment_method_token.clone() {
                         Some(payment_method_token) => match payment_method_token {
                             types::PaymentMethodToken::ApplePayDecrypt(decrypt_data) => {
-                                Self::try_from((item, decrypt_data))
+                                Self::try_from((item, decrypt_data, apple_pay_data))
                             }
                             types::PaymentMethodToken::Token(_) => {
                                 Err(errors::ConnectorError::InvalidWalletToken)?
@@ -685,6 +703,7 @@ impl TryFrom<&BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>>
                             let processing_information = ProcessingInformation::from((
                                 item,
                                 Some(PaymentSolution::ApplePay),
+                                Some(apple_pay_data.payment_method.network),
                             ));
                             let client_reference_information =
                                 ClientReferenceInformation::from(item);
diff --git a/crates/router/src/connector/checkout/transformers.rs b/crates/router/src/connector/checkout/transformers.rs
index f96bd50ffc8..2a20999085d 100644
--- a/crates/router/src/connector/checkout/transformers.rs
+++ b/crates/router/src/connector/checkout/transformers.rs
@@ -207,7 +207,7 @@ pub struct ApplePayPredecrypt {
     token_type: String,
     expiry_month: Secret<String>,
     expiry_year: Secret<String>,
-    eci: Option<Secret<String>>,
+    eci: Option<String>,
     cryptogram: Secret<String>,
 }
 
diff --git a/crates/router/src/connector/cybersource/transformers.rs b/crates/router/src/connector/cybersource/transformers.rs
index 646fe179da6..4bb28439b7f 100644
--- a/crates/router/src/connector/cybersource/transformers.rs
+++ b/crates/router/src/connector/cybersource/transformers.rs
@@ -489,13 +489,15 @@ impl
     TryFrom<(
         &CybersourceRouterData<&types::PaymentsAuthorizeRouterData>,
         Option<PaymentSolution>,
+        Option<String>,
     )> for ProcessingInformation
 {
     type Error = error_stack::Report<errors::ConnectorError>;
     fn try_from(
-        (item, solution): (
+        (item, solution, network): (
             &CybersourceRouterData<&types::PaymentsAuthorizeRouterData>,
             Option<PaymentSolution>,
+            Option<String>,
         ),
     ) -> Result<Self, Self::Error> {
         let (action_list, action_token_types, authorization_options) =
@@ -539,6 +541,17 @@ impl
             } else {
                 (None, None, None)
             };
+        let commerce_indicator = match network {
+            Some(card_network) => match card_network.to_lowercase().as_str() {
+                "amex" => "aesk",
+                "discover" => "dipb",
+                "mastercard" => "spa",
+                "visa" => "internet",
+                _ => "internet",
+            },
+            None => "internet",
+        }
+        .to_string();
         Ok(Self {
             capture: Some(matches!(
                 item.router_data.request.capture_method,
@@ -549,7 +562,7 @@ impl
             action_token_types,
             authorization_options,
             capture_options: None,
-            commerce_indicator: String::from("internet"),
+            commerce_indicator,
         })
     }
 }
@@ -721,7 +734,7 @@ impl
             },
         });
 
-        let processing_information = ProcessingInformation::try_from((item, None))?;
+        let processing_information = ProcessingInformation::try_from((item, None, None))?;
         let client_reference_information = ClientReferenceInformation::from(item);
         let merchant_defined_information =
             item.router_data.request.metadata.clone().map(|metadata| {
@@ -820,20 +833,25 @@ impl
     TryFrom<(
         &CybersourceRouterData<&types::PaymentsAuthorizeRouterData>,
         Box<ApplePayPredecryptData>,
+        payments::ApplePayWalletData,
     )> for CybersourcePaymentsRequest
 {
     type Error = error_stack::Report<errors::ConnectorError>;
     fn try_from(
-        (item, apple_pay_data): (
+        (item, apple_pay_data, apple_pay_wallet_data): (
             &CybersourceRouterData<&types::PaymentsAuthorizeRouterData>,
             Box<ApplePayPredecryptData>,
+            payments::ApplePayWalletData,
         ),
     ) -> Result<Self, Self::Error> {
         let email = item.router_data.request.get_email()?;
         let bill_to = build_bill_to(item.router_data.get_billing()?, email)?;
         let order_information = OrderInformationWithBill::from((item, bill_to));
-        let processing_information =
-            ProcessingInformation::try_from((item, Some(PaymentSolution::ApplePay)))?;
+        let processing_information = ProcessingInformation::try_from((
+            item,
+            Some(PaymentSolution::ApplePay),
+            Some(apple_pay_wallet_data.payment_method.network),
+        ))?;
         let client_reference_information = ClientReferenceInformation::from(item);
         let expiration_month = apple_pay_data.get_expiry_month()?;
         let expiration_year = apple_pay_data.get_four_digit_expiry_year()?;
@@ -887,7 +905,7 @@ impl
             },
         });
         let processing_information =
-            ProcessingInformation::try_from((item, Some(PaymentSolution::GooglePay)))?;
+            ProcessingInformation::try_from((item, Some(PaymentSolution::GooglePay), None))?;
         let client_reference_information = ClientReferenceInformation::from(item);
         let merchant_defined_information =
             item.router_data.request.metadata.clone().map(|metadata| {
@@ -922,7 +940,7 @@ impl TryFrom<&CybersourceRouterData<&types::PaymentsAuthorizeRouterData>>
                             match item.router_data.payment_method_token.clone() {
                                 Some(payment_method_token) => match payment_method_token {
                                     types::PaymentMethodToken::ApplePayDecrypt(decrypt_data) => {
-                                        Self::try_from((item, decrypt_data))
+                                        Self::try_from((item, decrypt_data, apple_pay_data))
                                     }
                                     types::PaymentMethodToken::Token(_) => {
                                         Err(errors::ConnectorError::InvalidWalletToken)?
@@ -934,9 +952,12 @@ impl TryFrom<&CybersourceRouterData<&types::PaymentsAuthorizeRouterData>>
                                         build_bill_to(item.router_data.get_billing()?, email)?;
                                     let order_information =
                                         OrderInformationWithBill::from((item, bill_to));
-                                    let processing_information = ProcessingInformation::try_from(
-                                        (item, Some(PaymentSolution::ApplePay)),
-                                    )?;
+                                    let processing_information =
+                                        ProcessingInformation::try_from((
+                                            item,
+                                            Some(PaymentSolution::ApplePay),
+                                            Some(apple_pay_data.payment_method.network),
+                                        ))?;
                                     let client_reference_information =
                                         ClientReferenceInformation::from(item);
                                     let payment_information = PaymentInformation::ApplePayToken(
@@ -1048,7 +1069,7 @@ impl
             String,
         ),
     ) -> Result<Self, Self::Error> {
-        let processing_information = ProcessingInformation::try_from((item, None))?;
+        let processing_information = ProcessingInformation::try_from((item, None, None))?;
         let payment_instrument = CybersoucrePaymentInstrument {
             id: connector_mandate_id,
         };
diff --git a/crates/router/src/connector/stripe/transformers.rs b/crates/router/src/connector/stripe/transformers.rs
index 8c370317c62..7c7a534f1c0 100644
--- a/crates/router/src/connector/stripe/transformers.rs
+++ b/crates/router/src/connector/stripe/transformers.rs
@@ -489,7 +489,7 @@ pub struct StripeApplePayPredecrypt {
     #[serde(rename = "card[cryptogram]")]
     cryptogram: Secret<String>,
     #[serde(rename = "card[eci]")]
-    eci: Option<Secret<String>>,
+    eci: Option<String>,
     #[serde(rename = "card[tokenization_method]")]
     tokenization_method: String,
 }
diff --git a/crates/router/src/connector/utils.rs b/crates/router/src/connector/utils.rs
index 7951246790f..fde9195143e 100644
--- a/crates/router/src/connector/utils.rs
+++ b/crates/router/src/connector/utils.rs
@@ -949,7 +949,6 @@ impl ApplePayDecrypt for Box<ApplePayPredecryptData> {
         Ok(Secret::new(format!(
             "20{}",
             self.application_expiration_date
-                .peek()
                 .get(0..2)
                 .ok_or(errors::ConnectorError::RequestEncodingFailed)?
         )))
@@ -958,7 +957,6 @@ impl ApplePayDecrypt for Box<ApplePayPredecryptData> {
     fn get_expiry_month(&self) -> Result<Secret<String>, Error> {
         Ok(Secret::new(
             self.application_expiration_date
-                .peek()
                 .get(2..4)
                 .ok_or(errors::ConnectorError::RequestEncodingFailed)?
                 .to_owned(),
diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs
index 050b0dd4b7b..e13d54f80d1 100644
--- a/crates/router/src/core/payments.rs
+++ b/crates/router/src/core/payments.rs
@@ -1129,6 +1129,8 @@ where
             .parse_value::<router_types::ApplePayPredecryptData>("ApplePayPredecryptData")
             .change_context(errors::ApiErrorResponse::InternalServerError)?;
 
+        logger::debug!(?apple_pay_predecrypt);
+
         router_data.payment_method_token = Some(router_types::PaymentMethodToken::ApplePayDecrypt(
             Box::new(apple_pay_predecrypt),
         ));
diff --git a/crates/router/src/types.rs b/crates/router/src/types.rs
index e163de9a5da..07691879d4a 100644
--- a/crates/router/src/types.rs
+++ b/crates/router/src/types.rs
@@ -334,9 +334,9 @@ pub enum PaymentMethodToken {
 #[serde(rename_all = "camelCase")]
 pub struct ApplePayPredecryptData {
     pub application_primary_account_number: Secret<String>,
-    pub application_expiration_date: Secret<String>,
-    pub currency_code: Secret<String>,
-    pub transaction_amount: Secret<i64>,
+    pub application_expiration_date: String,
+    pub currency_code: String,
+    pub transaction_amount: i64,
     pub device_manufacturer_identifier: Secret<String>,
     pub payment_data_type: Secret<String>,
     pub payment_data: ApplePayCryptogramData,
@@ -346,7 +346,7 @@ pub struct ApplePayPredecryptData {
 #[serde(rename_all = "camelCase")]
 pub struct ApplePayCryptogramData {
     pub online_payment_cryptogram: Secret<String>,
-    pub eci_indicator: Option<Secret<String>>,
+    pub eci_indicator: Option<String>,
 }
 
 #[derive(Debug, Clone)]

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

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

## Description
<!-- Describe your changes in detail -->
Apple pay transactions via BOA and Cybersource require a specific field `commerce_indicator` which is based on the card network type used during apple pay transactions.
https://docs.cybersource.com/content/dam/documentation/en/apple-pay/fdiglobal/so/applepay-so-fdiglobal.pdf

This data is now being passed using the card network data being shared from SDK during apple pay payments.

### 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).
-->
https://github.com/juspay/hyperswitch/issues/3783

## 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)?
-->
Apple pay payments need to be tested using simplified and manual flow for connectors BOA and Cybersource.
![image](https://github.com/juspay/hyperswitch/assets/41580413/40e4b1af-87d2-4ab2-a9c1-8a5e3f2d355f)


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