From 2a7c6a8c3a719522f846faa04eee11afc0dae465 Mon Sep 17 00:00:00 2001 From: hrithikeshvm Date: Tue, 12 Dec 2023 00:09:50 +0530 Subject: [PATCH 1/6] feat(core): enable surcharge support for all connectors --- crates/api_models/src/payments.rs | 4 +--- .../src/payments/payment_attempt.rs | 10 +++++++++ crates/router/src/connector/paypal.rs | 9 +------- crates/router/src/connector/trustpay.rs | 20 +++-------------- crates/router/src/connector/utils.rs | 4 ++-- .../src/core/payments/flows/authorize_flow.rs | 6 ----- .../payments/operations/payment_approve.rs | 2 +- .../payments/operations/payment_cancel.rs | 2 +- .../payments/operations/payment_capture.rs | 2 +- .../operations/payment_complete_authorize.rs | 2 +- .../payments/operations/payment_confirm.rs | 6 ++--- .../payments/operations/payment_create.rs | 10 ++++++++- .../payments/operations/payment_reject.rs | 2 +- .../payments/operations/payment_response.rs | 5 +---- .../payments/operations/payment_session.rs | 2 +- .../core/payments/operations/payment_start.rs | 2 +- .../payments/operations/payment_status.rs | 2 +- .../payments/operations/payment_update.rs | 22 +++++++++++++++---- .../payments_incremental_authorization.rs | 2 +- crates/router/src/services/api.rs | 4 ---- crates/router/src/types.rs | 2 +- 21 files changed, 58 insertions(+), 62 deletions(-) diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs index b19f4d7b7db1..7c5f45856563 100644 --- a/crates/api_models/src/payments.rs +++ b/crates/api_models/src/payments.rs @@ -319,9 +319,7 @@ impl PaymentsRequest { pub fn get_total_capturable_amount(&self) -> Option { let surcharge_amount = self .surcharge_details - .map(|surcharge_details| { - surcharge_details.surcharge_amount + surcharge_details.tax_amount.unwrap_or(0) - }) + .map(|surcharge_details| surcharge_details.get_total_surcharge_amount()) .unwrap_or(0); self.amount .map(|amount| i64::from(amount) + surcharge_amount) diff --git a/crates/data_models/src/payments/payment_attempt.rs b/crates/data_models/src/payments/payment_attempt.rs index f7b849f1d4e1..61e48cb64e9a 100644 --- a/crates/data_models/src/payments/payment_attempt.rs +++ b/crates/data_models/src/payments/payment_attempt.rs @@ -156,6 +156,16 @@ pub struct PaymentAttempt { pub unified_message: Option, } +impl PaymentAttempt { + pub fn get_total_amount(&self) -> i64 { + self.amount + self.surcharge_amount.unwrap_or(0) + self.tax_amount.unwrap_or(0) + } + pub fn get_total_surcharge_amount(&self) -> Option { + self.surcharge_amount + .map(|surcharge_amount| surcharge_amount + self.tax_amount.unwrap_or(0)) + } +} + #[derive(Clone, Debug, Eq, PartialEq)] pub struct PaymentListFilters { pub connector: Vec, diff --git a/crates/router/src/connector/paypal.rs b/crates/router/src/connector/paypal.rs index a0d391789020..f449255a5f6e 100644 --- a/crates/router/src/connector/paypal.rs +++ b/crates/router/src/connector/paypal.rs @@ -265,10 +265,6 @@ impl ConnectorValidation for Paypal { ), } } - - fn validate_if_surcharge_implemented(&self) -> CustomResult<(), errors::ConnectorError> { - Ok(()) - } } impl @@ -428,10 +424,7 @@ impl ConnectorIntegration CustomResult<(), errors::ConnectorError> { - Ok(()) - } -} +impl ConnectorValidation for Trustpay {} impl api::Payment for Trustpay {} @@ -435,12 +431,7 @@ impl _connectors: &settings::Connectors, ) -> CustomResult, errors::ConnectorError> { let currency = req.request.get_currency()?; - let amount = req - .request - .surcharge_details - .as_ref() - .map(|surcharge_details| surcharge_details.final_amount) - .unwrap_or(req.request.get_amount()?); + let amount = req.request.get_amount()?; let connector_router_data = trustpay::TrustpayRouterData::try_from(( &self.get_currency_unit(), currency, @@ -552,12 +543,7 @@ impl ConnectorIntegration CustomResult, errors::ConnectorError> { - let amount = req - .request - .surcharge_details - .as_ref() - .map(|surcharge_details| surcharge_details.final_amount) - .unwrap_or(req.request.amount); + let amount = req.request.amount; let connector_router_data = trustpay::TrustpayRouterData::try_from(( &self.get_currency_unit(), req.request.currency, diff --git a/crates/router/src/connector/utils.rs b/crates/router/src/connector/utils.rs index 3990fc9c7e47..1133dc297390 100644 --- a/crates/router/src/connector/utils.rs +++ b/crates/router/src/connector/utils.rs @@ -27,8 +27,8 @@ use crate::{ }, pii::PeekInterface, types::{ - self, api, storage::payment_attempt::PaymentAttemptExt, transformers::ForeignTryFrom, - ApplePayPredecryptData, PaymentsCancelData, ResponseId, + self, api, transformers::ForeignTryFrom, ApplePayPredecryptData, PaymentsCancelData, + ResponseId, }, utils::{OptionExt, ValueExt}, }; diff --git a/crates/router/src/core/payments/flows/authorize_flow.rs b/crates/router/src/core/payments/flows/authorize_flow.rs index 4ef23f481a2c..c934c7c2cd67 100644 --- a/crates/router/src/core/payments/flows/authorize_flow.rs +++ b/crates/router/src/core/payments/flows/authorize_flow.rs @@ -76,12 +76,6 @@ impl Feature for types::PaymentsAu .connector .validate_capture_method(self.request.capture_method) .to_payment_failed_response()?; - if self.request.surcharge_details.is_some() { - connector - .connector - .validate_if_surcharge_implemented() - .to_payment_failed_response()?; - } if self.should_proceed_with_authorize() { self.decide_authentication_type(); diff --git a/crates/router/src/core/payments/operations/payment_approve.rs b/crates/router/src/core/payments/operations/payment_approve.rs index 37a3e1a14123..31b06e8cb2fa 100644 --- a/crates/router/src/core/payments/operations/payment_approve.rs +++ b/crates/router/src/core/payments/operations/payment_approve.rs @@ -139,7 +139,7 @@ impl payment_method_type.or(payment_attempt.payment_method_type); payment_attempt.payment_experience = request.payment_experience; currency = payment_attempt.currency.get_required_value("currency")?; - amount = payment_attempt.amount.into(); + amount = payment_attempt.get_total_amount().into(); helpers::validate_customer_id_mandatory_cases( request.setup_future_usage.is_some(), diff --git a/crates/router/src/core/payments/operations/payment_cancel.rs b/crates/router/src/core/payments/operations/payment_cancel.rs index 7c8fbcc34979..5e6a35f3300a 100644 --- a/crates/router/src/core/payments/operations/payment_cancel.rs +++ b/crates/router/src/core/payments/operations/payment_cancel.rs @@ -102,7 +102,7 @@ impl .await?; let currency = payment_attempt.currency.get_required_value("currency")?; - let amount = payment_attempt.amount.into(); + let amount = payment_attempt.get_total_amount().into(); payment_attempt.cancellation_reason = request.cancellation_reason.clone(); diff --git a/crates/router/src/core/payments/operations/payment_capture.rs b/crates/router/src/core/payments/operations/payment_capture.rs index 65b91f0401cf..f0d517d28912 100644 --- a/crates/router/src/core/payments/operations/payment_capture.rs +++ b/crates/router/src/core/payments/operations/payment_capture.rs @@ -124,7 +124,7 @@ impl currency = payment_attempt.currency.get_required_value("currency")?; - amount = payment_attempt.amount.into(); + amount = payment_attempt.get_total_amount().into(); let shipping_address = helpers::create_or_find_address_for_payment_by_request( db, diff --git a/crates/router/src/core/payments/operations/payment_complete_authorize.rs b/crates/router/src/core/payments/operations/payment_complete_authorize.rs index 48b503b96b0d..fd758e7a9655 100644 --- a/crates/router/src/core/payments/operations/payment_complete_authorize.rs +++ b/crates/router/src/core/payments/operations/payment_complete_authorize.rs @@ -135,7 +135,7 @@ impl .payment_experience .or(payment_attempt.payment_experience); currency = payment_attempt.currency.get_required_value("currency")?; - amount = payment_attempt.amount.into(); + amount = payment_attempt.get_total_amount().into(); helpers::validate_customer_id_mandatory_cases( request.setup_future_usage.is_some(), diff --git a/crates/router/src/core/payments/operations/payment_confirm.rs b/crates/router/src/core/payments/operations/payment_confirm.rs index 612ddadc1c59..b62ae5f89b59 100644 --- a/crates/router/src/core/payments/operations/payment_confirm.rs +++ b/crates/router/src/core/payments/operations/payment_confirm.rs @@ -377,7 +377,7 @@ impl payment_attempt.capture_method = request.capture_method.or(payment_attempt.capture_method); currency = payment_attempt.currency.get_required_value("currency")?; - amount = payment_attempt.amount.into(); + amount = payment_attempt.get_total_amount().into(); helpers::validate_customer_id_mandatory_cases( request.setup_future_usage.is_some(), @@ -731,7 +731,7 @@ impl m_db.update_payment_attempt_with_attempt_id( m_payment_data_payment_attempt, storage::PaymentAttemptUpdate::ConfirmUpdate { - amount: payment_data.amount.into(), + amount: payment_data.payment_attempt.amount, currency: payment_data.currency, status: attempt_status, payment_method, @@ -779,7 +779,7 @@ impl m_db.update_payment_intent( m_payment_data_payment_intent, storage::PaymentIntentUpdate::Update { - amount: payment_data.amount.into(), + amount: payment_data.payment_intent.amount, currency: payment_data.currency, setup_future_usage, status: intent_status, diff --git a/crates/router/src/core/payments/operations/payment_create.rs b/crates/router/src/core/payments/operations/payment_create.rs index cbce6ba9e970..667edf578a1a 100644 --- a/crates/router/src/core/payments/operations/payment_create.rs +++ b/crates/router/src/core/payments/operations/payment_create.rs @@ -297,7 +297,7 @@ impl .map(|(payment_method_data, additional_payment_data)| { payment_method_data.apply_additional_payment_data(additional_payment_data) }); - + let amount = payment_attempt.get_total_amount().into(); let payment_data = PaymentData { flow: PhantomData, payment_intent, @@ -644,6 +644,12 @@ impl PaymentCreate { } else { utils::get_payment_attempt_id(payment_id, 1) }; + let surcharge_amount = request + .surcharge_details + .map(|surcharge_details| surcharge_details.surcharge_amount); + let tax_amount = request + .surcharge_details + .and_then(|surcharge_details| surcharge_details.tax_amount); Ok(( storage::PaymentAttemptNew { @@ -669,6 +675,8 @@ impl PaymentCreate { payment_token: request.payment_token.clone(), mandate_id: request.mandate_id.clone(), business_sub_label: request.business_sub_label.clone(), + surcharge_amount, + tax_amount, mandate_details: request .mandate_data .as_ref() diff --git a/crates/router/src/core/payments/operations/payment_reject.rs b/crates/router/src/core/payments/operations/payment_reject.rs index 03bf6dd46b60..cd9fa926d19f 100644 --- a/crates/router/src/core/payments/operations/payment_reject.rs +++ b/crates/router/src/core/payments/operations/payment_reject.rs @@ -100,7 +100,7 @@ impl .await?; let currency = payment_attempt.currency.get_required_value("currency")?; - let amount = payment_attempt.amount.into(); + let amount = payment_attempt.get_total_amount().into(); let frm_response = db .find_fraud_check_by_payment_id(payment_intent.payment_id.clone(), merchant_account.merchant_id.clone()) diff --git a/crates/router/src/core/payments/operations/payment_response.rs b/crates/router/src/core/payments/operations/payment_response.rs index f92487d74a7b..8b301c525fd7 100644 --- a/crates/router/src/core/payments/operations/payment_response.rs +++ b/crates/router/src/core/payments/operations/payment_response.rs @@ -24,10 +24,7 @@ use crate::{ services::RedirectForm, types::{ self, api, - storage::{ - self, enums, - payment_attempt::{AttemptStatusExt, PaymentAttemptExt}, - }, + storage::{self, enums, payment_attempt::AttemptStatusExt}, transformers::{ForeignFrom, ForeignTryFrom}, CaptureSyncResponse, }, diff --git a/crates/router/src/core/payments/operations/payment_session.rs b/crates/router/src/core/payments/operations/payment_session.rs index 572bc710b963..d0c96dfa58f3 100644 --- a/crates/router/src/core/payments/operations/payment_session.rs +++ b/crates/router/src/core/payments/operations/payment_session.rs @@ -93,7 +93,7 @@ impl payment_attempt.payment_method = Some(storage_enums::PaymentMethod::Wallet); - let amount = payment_intent.amount.into(); + let amount = payment_attempt.get_total_amount().into(); let shipping_address = helpers::create_or_find_address_for_payment_by_request( db, diff --git a/crates/router/src/core/payments/operations/payment_start.rs b/crates/router/src/core/payments/operations/payment_start.rs index 887edd030d13..a471f92eee38 100644 --- a/crates/router/src/core/payments/operations/payment_start.rs +++ b/crates/router/src/core/payments/operations/payment_start.rs @@ -89,7 +89,7 @@ impl .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?; currency = payment_attempt.currency.get_required_value("currency")?; - amount = payment_attempt.amount.into(); + amount = payment_attempt.get_total_amount().into(); let shipping_address = helpers::create_or_find_address_for_payment_by_request( db, diff --git a/crates/router/src/core/payments/operations/payment_status.rs b/crates/router/src/core/payments/operations/payment_status.rs index 0320cf50663e..cfdf37abef98 100644 --- a/crates/router/src/core/payments/operations/payment_status.rs +++ b/crates/router/src/core/payments/operations/payment_status.rs @@ -244,7 +244,7 @@ async fn get_tracker_for_sync< let payment_id_str = payment_attempt.payment_id.clone(); currency = payment_attempt.currency.get_required_value("currency")?; - amount = payment_attempt.amount.into(); + amount = payment_attempt.get_total_amount().into(); let shipping_address = helpers::get_address_by_id( db, diff --git a/crates/router/src/core/payments/operations/payment_update.rs b/crates/router/src/core/payments/operations/payment_update.rs index 84f11124c730..5ca27de98895 100644 --- a/crates/router/src/core/payments/operations/payment_update.rs +++ b/crates/router/src/core/payments/operations/payment_update.rs @@ -1,6 +1,6 @@ use std::marker::PhantomData; -use api_models::enums::FrmSuggestion; +use api_models::{enums::FrmSuggestion, payments::RequestSurchargeDetails}; use async_trait::async_trait; use common_utils::ext_traits::{AsyncExt, Encode, ValueExt}; use error_stack::{report, IntoReport, ResultExt}; @@ -281,11 +281,25 @@ impl }) .await .transpose()?; - let next_operation: BoxedOperation<'a, F, api::PaymentsRequest, Ctx> = + let (next_operation, amount): (BoxedOperation<'a, F, api::PaymentsRequest, Ctx>, _) = if request.confirm.unwrap_or(false) { - Box::new(operations::PaymentConfirm) + let amount = { + let amount = request + .amount + .map(Into::into) + .unwrap_or(payment_attempt.amount); + payment_attempt.amount = amount; + payment_intent.amount = amount; + let surcharge_amount = request + .surcharge_details + .as_ref() + .map(RequestSurchargeDetails::get_total_surcharge_amount) + .or(payment_attempt.get_total_surcharge_amount()); + (amount + surcharge_amount.unwrap_or(0)).into() + }; + (Box::new(operations::PaymentConfirm), amount) } else { - Box::new(self) + (Box::new(self), amount) }; payment_intent.status = match request.payment_method_data.as_ref() { diff --git a/crates/router/src/core/payments/operations/payments_incremental_authorization.rs b/crates/router/src/core/payments/operations/payments_incremental_authorization.rs index 7346c46df120..025143380e44 100644 --- a/crates/router/src/core/payments/operations/payments_incremental_authorization.rs +++ b/crates/router/src/core/payments/operations/payments_incremental_authorization.rs @@ -92,7 +92,7 @@ impl .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?; let currency = payment_attempt.currency.get_required_value("currency")?; - let amount = payment_attempt.amount; + let amount = payment_attempt.get_total_amount(); let profile_id = payment_intent .profile_id diff --git a/crates/router/src/services/api.rs b/crates/router/src/services/api.rs index 918aab929ac9..83f532fceb17 100644 --- a/crates/router/src/services/api.rs +++ b/crates/router/src/services/api.rs @@ -96,10 +96,6 @@ pub trait ConnectorValidation: ConnectorCommon { fn is_webhook_source_verification_mandatory(&self) -> bool { false } - - fn validate_if_surcharge_implemented(&self) -> CustomResult<(), errors::ConnectorError> { - Err(errors::ConnectorError::NotImplemented(format!("Surcharge for {}", self.id())).into()) - } } #[async_trait::async_trait] diff --git a/crates/router/src/types.rs b/crates/router/src/types.rs index aa563c647eaa..6f50bf9852a1 100644 --- a/crates/router/src/types.rs +++ b/crates/router/src/types.rs @@ -38,7 +38,7 @@ use crate::{ payments::{types, PaymentData, RecurringMandatePaymentData}, }, services, - types::{storage::payment_attempt::PaymentAttemptExt, transformers::ForeignFrom}, + types::transformers::ForeignFrom, utils::OptionExt, }; From 22ca09d9a838cf44a45f573a2507d4407fb616bc Mon Sep 17 00:00:00 2001 From: hrithikeshvm Date: Tue, 12 Dec 2023 09:42:30 +0530 Subject: [PATCH 2/6] fix: calculate display_total_surcharge_amount from int --- crates/router/src/core/payments/types.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/router/src/core/payments/types.rs b/crates/router/src/core/payments/types.rs index 001082d2c92e..84f85b8b7d4f 100644 --- a/crates/router/src/core/payments/types.rs +++ b/crates/router/src/core/payments/types.rs @@ -219,13 +219,15 @@ impl ForeignTryFrom<(&SurchargeDetails, &PaymentAttempt)> for SurchargeDetailsRe currency.to_currency_base_unit_asf64(surcharge_details.tax_on_surcharge_amount)?; let display_final_amount = currency.to_currency_base_unit_asf64(surcharge_details.final_amount)?; + let display_total_surcharge_amount = currency.to_currency_base_unit_asf64( + surcharge_details.surcharge_amount + surcharge_details.tax_on_surcharge_amount, + )?; Ok(Self { surcharge: surcharge_details.surcharge.clone().into(), tax_on_surcharge: surcharge_details.tax_on_surcharge.clone().map(Into::into), display_surcharge_amount, display_tax_on_surcharge_amount, - display_total_surcharge_amount: display_surcharge_amount - + display_tax_on_surcharge_amount, + display_total_surcharge_amount, display_final_amount, }) } From e4f0c429be9b837342729d910b1bc54cc982ea98 Mon Sep 17 00:00:00 2001 From: hrithikeshvm Date: Tue, 12 Dec 2023 12:27:23 +0530 Subject: [PATCH 3/6] address comments --- crates/router/src/connector/utils.rs | 25 +++++++++++++++++++ .../surcharge_decision_configs.rs | 1 + crates/router/src/core/payments.rs | 1 + .../router/src/core/payments/transformers.rs | 21 +++++++++++++--- crates/router/src/core/payments/types.rs | 3 +++ crates/router/src/types.rs | 8 ++++++ 6 files changed, 56 insertions(+), 3 deletions(-) diff --git a/crates/router/src/connector/utils.rs b/crates/router/src/connector/utils.rs index 1133dc297390..25c51c5425e0 100644 --- a/crates/router/src/connector/utils.rs +++ b/crates/router/src/connector/utils.rs @@ -349,6 +349,10 @@ pub trait PaymentsAuthorizeRequestData { fn get_connector_mandate_id(&self) -> Result; fn get_complete_authorize_url(&self) -> Result; fn get_ip_address_as_optional(&self) -> Option>; + fn get_original_amount(&self) -> i64; + fn get_surcharge_amount(&self) -> Option; + fn get_tax_on_surcharge_amount(&self) -> Option; + fn get_total_surcharge_amount(&self) -> Option; } pub trait PaymentMethodTokenizationRequestData { @@ -455,6 +459,27 @@ impl PaymentsAuthorizeRequestData for types::PaymentsAuthorizeData { .map(|ip| Secret::new(ip.to_string())) }) } + fn get_original_amount(&self) -> i64 { + self.surcharge_details + .as_ref() + .map(|surcharge_details| surcharge_details.original_amount) + .unwrap_or(self.amount) + } + fn get_surcharge_amount(&self) -> Option { + self.surcharge_details + .as_ref() + .map(|surcharge_details| surcharge_details.surcharge_amount) + } + fn get_tax_on_surcharge_amount(&self) -> Option { + self.surcharge_details + .as_ref() + .map(|surcharge_details| surcharge_details.tax_on_surcharge_amount) + } + fn get_total_surcharge_amount(&self) -> Option { + self.surcharge_details + .as_ref() + .map(|surcharge_details| surcharge_details.get_total_surcharge_amount()) + } } pub trait ConnectorCustomerData { diff --git a/crates/router/src/core/payment_methods/surcharge_decision_configs.rs b/crates/router/src/core/payment_methods/surcharge_decision_configs.rs index e130795e945a..db1064b36a7a 100644 --- a/crates/router/src/core/payment_methods/surcharge_decision_configs.rs +++ b/crates/router/src/core/payment_methods/surcharge_decision_configs.rs @@ -310,6 +310,7 @@ fn get_surcharge_details_from_surcharge_output( .transpose()? .unwrap_or(0); Ok(types::SurchargeDetails { + original_amount: payment_attempt.amount, surcharge: match surcharge_details.surcharge { surcharge_decision_configs::SurchargeOutput::Fixed { amount } => { common_utils_types::Surcharge::Fixed(amount) diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs index 73af17f9d66b..ab7f8a81f962 100644 --- a/crates/router/src/core/payments.rs +++ b/crates/router/src/core/payments.rs @@ -562,6 +562,7 @@ where payment_data.payment_attempt.amount + surcharge_amount + tax_on_surcharge_amount; Ok(Some(api::SessionSurchargeDetails::PreDetermined( types::SurchargeDetails { + original_amount: payment_data.payment_attempt.amount, surcharge: Surcharge::Fixed(surcharge_amount), tax_on_surcharge: None, surcharge_amount, diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs index bd6d03e5625a..bac59465b450 100644 --- a/crates/router/src/core/payments/transformers.rs +++ b/crates/router/src/core/payments/transformers.rs @@ -1032,6 +1032,11 @@ impl TryFrom> for types::PaymentsAuthoriz None } }); + let amount = payment_data + .surcharge_details + .as_ref() + .map(|surcharge_details| surcharge_details.final_amount) + .unwrap_or(payment_data.amount.into()); Ok(Self { payment_method_data: payment_method_data.get_required_value("payment_method_data")?, setup_future_usage: payment_data.payment_intent.setup_future_usage, @@ -1042,7 +1047,7 @@ impl TryFrom> for types::PaymentsAuthoriz statement_descriptor_suffix: payment_data.payment_intent.statement_descriptor_suffix, statement_descriptor: payment_data.payment_intent.statement_descriptor_name, capture_method: payment_data.payment_attempt.capture_method, - amount: payment_data.amount.into(), + amount, currency: payment_data.currency, browser_info, email: payment_data.email, @@ -1417,6 +1422,11 @@ impl TryFrom> for types::CompleteAuthoriz payload: redirect.json_payload, } }); + let amount = payment_data + .surcharge_details + .as_ref() + .map(|surcharge_details| surcharge_details.final_amount) + .unwrap_or(payment_data.amount.into()); Ok(Self { setup_future_usage: payment_data.payment_intent.setup_future_usage, @@ -1426,7 +1436,7 @@ impl TryFrom> for types::CompleteAuthoriz confirm: payment_data.payment_attempt.confirm, statement_descriptor_suffix: payment_data.payment_intent.statement_descriptor_suffix, capture_method: payment_data.payment_attempt.capture_method, - amount: payment_data.amount.into(), + amount, currency: payment_data.currency, browser_info, email: payment_data.email, @@ -1491,12 +1501,17 @@ impl TryFrom> for types::PaymentsPreProce .change_context(errors::ApiErrorResponse::InvalidDataValue { field_name: "browser_info", })?; + let amount = payment_data + .surcharge_details + .as_ref() + .map(|surcharge_details| surcharge_details.final_amount) + .unwrap_or(payment_data.amount.into()); Ok(Self { payment_method_data, email: payment_data.email, currency: Some(payment_data.currency), - amount: Some(payment_data.amount.into()), + amount: Some(amount), payment_method_type: payment_data.payment_attempt.payment_method_type, setup_mandate_details: payment_data.setup_mandate, capture_method: payment_data.payment_attempt.capture_method, diff --git a/crates/router/src/core/payments/types.rs b/crates/router/src/core/payments/types.rs index 84f85b8b7d4f..00160db9855f 100644 --- a/crates/router/src/core/payments/types.rs +++ b/crates/router/src/core/payments/types.rs @@ -178,6 +178,8 @@ impl MultipleCaptureData { #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] pub struct SurchargeDetails { + /// original_amount + pub original_amount: i64, /// surcharge value pub surcharge: common_types::Surcharge, /// tax on surcharge value @@ -198,6 +200,7 @@ impl From<(&RequestSurchargeDetails, &PaymentAttempt)> for SurchargeDetails { let surcharge_amount = request_surcharge_details.surcharge_amount; let tax_on_surcharge_amount = request_surcharge_details.tax_amount.unwrap_or(0); Self { + original_amount: payment_attempt.amount, surcharge: common_types::Surcharge::Fixed(request_surcharge_details.surcharge_amount), tax_on_surcharge: None, surcharge_amount, diff --git a/crates/router/src/types.rs b/crates/router/src/types.rs index 6f50bf9852a1..e61232352096 100644 --- a/crates/router/src/types.rs +++ b/crates/router/src/types.rs @@ -371,6 +371,14 @@ pub struct PayoutsFulfillResponseData { #[derive(Debug, Clone)] pub struct PaymentsAuthorizeData { pub payment_method_data: payments::PaymentMethodData, + /// total amount (original_amount + surcharge_amount + tax_on_surcharge_amount) + /// If connector supports separate field for surcharge amount, consider using below functions defined on `PaymentsAuthorizeData` to fetch original amount and surcharge amount separately + /// ``` + /// get_original_amount() + /// get_surcharge_amount() + /// get_tax_on_surcharge_amount() + /// get_total_surcharge_amount() // returns surcharge_amount + tax_on_surcharge_amount + /// ``` pub amount: i64, pub email: Option, pub currency: storage_enums::Currency, From 54d42875a1df3c7271e84189c4166077fc469beb Mon Sep 17 00:00:00 2001 From: hrithikeshvm Date: Tue, 12 Dec 2023 14:05:20 +0530 Subject: [PATCH 4/6] remove redundant call to populate_payment_data() and handle surcharge for payment retry --- crates/router/src/core/payments.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs index ab7f8a81f962..777ba9882c20 100644 --- a/crates/router/src/core/payments.rs +++ b/crates/router/src/core/payments.rs @@ -204,10 +204,6 @@ where ); if should_continue_transaction { - operation - .to_domain()? - .populate_payment_data(state, &mut payment_data, &merchant_account) - .await?; payment_data = match connector_details { api::ConnectorCallType::PreDetermined(connector) => { let schedule_time = if should_add_task_to_process_tracker { @@ -484,6 +480,13 @@ where .surcharge_applicable .unwrap_or(false) { + if let Some(surcharge_details) = payment_data.payment_attempt.get_surcharge_details() { + // if retry payment, surcharge would have been populated from the previous attempt. Use the same surcharge + let surcharge_details = + types::SurchargeDetails::from((&surcharge_details, &payment_data.payment_attempt)); + payment_data.surcharge_details = Some(surcharge_details); + return Ok(()); + } let raw_card_key = payment_data .payment_method_data .as_ref() From 82cc4389b0e523e1a693745a7b7c6d346a22ec2c Mon Sep 17 00:00:00 2001 From: hrithikeshvm Date: Tue, 12 Dec 2023 19:23:51 +0530 Subject: [PATCH 5/6] do amount operation for PaymentsSessionData --- crates/router/src/core/payments/transformers.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs index 872d22baa685..4dbd714b83da 100644 --- a/crates/router/src/core/payments/transformers.rs +++ b/crates/router/src/core/payments/transformers.rs @@ -1300,9 +1300,14 @@ impl TryFrom> for types::PaymentsSessionD .collect::, _>>() }) .transpose()?; + let amount = payment_data + .surcharge_details + .as_ref() + .map(|surcharge_details| surcharge_details.final_amount) + .unwrap_or(payment_data.amount.into()); Ok(Self { - amount: payment_data.amount.into(), + amount, currency: payment_data.currency, country: payment_data.address.billing.and_then(|billing_address| { billing_address.address.and_then(|address| address.country) From a907bb54ce0fb9c3acb0d1facbb793ac7cc39978 Mon Sep 17 00:00:00 2001 From: "hyperswitch-bot[bot]" <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Date: Wed, 13 Dec 2023 07:04:51 +0000 Subject: [PATCH 6/6] chore: update Cargo.lock --- Cargo.lock | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5f1ab2cd3423..b58631632e4d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1668,7 +1668,7 @@ dependencies = [ "once_cell", "phonenumber", "proptest", - "quick-xml", + "quick-xml 0.28.2", "rand 0.8.5", "regex", "reqwest", @@ -3539,6 +3539,7 @@ version = "0.1.0" dependencies = [ "bytes 1.5.0", "diesel", + "erased-serde", "serde", "serde_json", "subtle", @@ -4330,7 +4331,7 @@ dependencies = [ "itertools 0.11.0", "lazy_static", "nom", - "quick-xml", + "quick-xml 0.28.2", "regex", "regex-cache", "serde", @@ -4621,6 +4622,16 @@ dependencies = [ "serde", ] +[[package]] +name = "quick-xml" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1004a344b30a54e2ee58d66a71b32d2db2feb0a31f9a2d302bf0536f15de2a33" +dependencies = [ + "memchr", + "serde", +] + [[package]] name = "quote" version = "1.0.33" @@ -5087,6 +5098,7 @@ dependencies = [ "openssl", "pm_auth", "qrcode", + "quick-xml 0.31.0", "rand 0.8.5", "rand_chacha 0.3.1", "rdkafka",