From d3a332d7cfc49a0b83aa4659cc711e3085529841 Mon Sep 17 00:00:00 2001 From: DEEPANSHU BANSAL Date: Fri, 23 Feb 2024 13:32:28 +0530 Subject: [PATCH 1/2] feat(connector): [BOA/Cybersource] Pass commerce indicator using card network for apple pay --- .../connector/bankofamerica/transformers.rs | 33 ++++++++++---- .../src/connector/checkout/transformers.rs | 2 +- .../src/connector/cybersource/transformers.rs | 43 +++++++++++++------ .../src/connector/stripe/transformers.rs | 2 +- crates/router/src/connector/utils.rs | 2 - crates/router/src/core/payments.rs | 2 + crates/router/src/types.rs | 8 ++-- 7 files changed, 64 insertions(+), 28 deletions(-) diff --git a/crates/router/src/connector/bankofamerica/transformers.rs b/crates/router/src/connector/bankofamerica/transformers.rs index 235321f1ac6..9ea7bc756ae 100644 --- a/crates/router/src/connector/bankofamerica/transformers.rs +++ b/crates/router/src/connector/bankofamerica/transformers.rs @@ -330,21 +330,32 @@ impl From<( &BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>, Option, + Option, )> for ProcessingInformation { fn from( - (item, solution): ( + (item, solution, network): ( &BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>, Option, + Option, ), ) -> Self { + let commerce_indicator = match network { + Some(card_network) => match card_network.as_str() { + "AmEx" => String::from("aesk"), + "Discover" => String::from("dipb"), + "MasterCard" => String::from("spa"), + _ => String::from("internet"), + }, + None => String::from("internet"), + }; 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 +563,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 +585,25 @@ impl TryFrom<( &BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>, Box, + payments::ApplePayWalletData, )> for BankOfAmericaPaymentsRequest { type Error = error_stack::Report; fn try_from( - (item, apple_pay_data): ( + (item, apple_pay_data, apple_pay_wallet_data): ( &BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>, Box, + payments::ApplePayWalletData, ), ) -> Result { 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 +656,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 +688,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 +701,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, expiry_year: Secret, - eci: Option>, + eci: Option, cryptogram: Secret, } diff --git a/crates/router/src/connector/cybersource/transformers.rs b/crates/router/src/connector/cybersource/transformers.rs index 646fe179da6..b53d639be81 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, + Option, )> for ProcessingInformation { type Error = error_stack::Report; fn try_from( - (item, solution): ( + (item, solution, network): ( &CybersourceRouterData<&types::PaymentsAuthorizeRouterData>, Option, + Option, ), ) -> Result { let (action_list, action_token_types, authorization_options) = @@ -539,6 +541,15 @@ impl } else { (None, None, None) }; + let commerce_indicator = match network { + Some(card_network) => match card_network.as_str() { + "AmEx" => String::from("aesk"), + "Discover" => String::from("dipb"), + "MasterCard" => String::from("spa"), + _ => String::from("internet"), + }, + None => String::from("internet"), + }; Ok(Self { capture: Some(matches!( item.router_data.request.capture_method, @@ -549,7 +560,7 @@ impl action_token_types, authorization_options, capture_options: None, - commerce_indicator: String::from("internet"), + commerce_indicator, }) } } @@ -721,7 +732,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 +831,25 @@ impl TryFrom<( &CybersourceRouterData<&types::PaymentsAuthorizeRouterData>, Box, + payments::ApplePayWalletData, )> for CybersourcePaymentsRequest { type Error = error_stack::Report; fn try_from( - (item, apple_pay_data): ( + (item, apple_pay_data, apple_pay_wallet_data): ( &CybersourceRouterData<&types::PaymentsAuthorizeRouterData>, Box, + payments::ApplePayWalletData, ), ) -> Result { 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 +903,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 +938,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 +950,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 +1067,7 @@ impl String, ), ) -> Result { - 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, #[serde(rename = "card[eci]")] - eci: Option>, + eci: Option, #[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 { 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 { fn get_expiry_month(&self) -> Result, 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::("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, - pub application_expiration_date: Secret, - pub currency_code: Secret, - pub transaction_amount: Secret, + pub application_expiration_date: String, + pub currency_code: String, + pub transaction_amount: i64, pub device_manufacturer_identifier: Secret, pub payment_data_type: Secret, pub payment_data: ApplePayCryptogramData, @@ -346,7 +346,7 @@ pub struct ApplePayPredecryptData { #[serde(rename_all = "camelCase")] pub struct ApplePayCryptogramData { pub online_payment_cryptogram: Secret, - pub eci_indicator: Option>, + pub eci_indicator: Option, } #[derive(Debug, Clone)] From 0db0543bc4432c34b1993142bbe797da34aa5373 Mon Sep 17 00:00:00 2001 From: DEEPANSHU BANSAL Date: Fri, 23 Feb 2024 13:45:40 +0530 Subject: [PATCH 2/2] feat(connector): [BOA/Cybersource] Resoolve PR Comments --- .../src/connector/bankofamerica/transformers.rs | 16 +++++++++------- .../src/connector/cybersource/transformers.rs | 16 +++++++++------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/crates/router/src/connector/bankofamerica/transformers.rs b/crates/router/src/connector/bankofamerica/transformers.rs index 9ea7bc756ae..0be25b078bc 100644 --- a/crates/router/src/connector/bankofamerica/transformers.rs +++ b/crates/router/src/connector/bankofamerica/transformers.rs @@ -341,14 +341,16 @@ impl ), ) -> Self { let commerce_indicator = match network { - Some(card_network) => match card_network.as_str() { - "AmEx" => String::from("aesk"), - "Discover" => String::from("dipb"), - "MasterCard" => String::from("spa"), - _ => String::from("internet"), + Some(card_network) => match card_network.to_lowercase().as_str() { + "amex" => "aesk", + "discover" => "dipb", + "mastercard" => "spa", + "visa" => "internet", + _ => "internet", }, - None => String::from("internet"), - }; + None => "internet", + } + .to_string(); Self { capture: Some(matches!( item.router_data.request.capture_method, diff --git a/crates/router/src/connector/cybersource/transformers.rs b/crates/router/src/connector/cybersource/transformers.rs index b53d639be81..4bb28439b7f 100644 --- a/crates/router/src/connector/cybersource/transformers.rs +++ b/crates/router/src/connector/cybersource/transformers.rs @@ -542,14 +542,16 @@ impl (None, None, None) }; let commerce_indicator = match network { - Some(card_network) => match card_network.as_str() { - "AmEx" => String::from("aesk"), - "Discover" => String::from("dipb"), - "MasterCard" => String::from("spa"), - _ => String::from("internet"), + Some(card_network) => match card_network.to_lowercase().as_str() { + "amex" => "aesk", + "discover" => "dipb", + "mastercard" => "spa", + "visa" => "internet", + _ => "internet", }, - None => String::from("internet"), - }; + None => "internet", + } + .to_string(); Ok(Self { capture: Some(matches!( item.router_data.request.capture_method,