From 6c808db391fc12ef37b252be786a18e1cf6fa022 Mon Sep 17 00:00:00 2001 From: swangi-kumari Date: Sat, 10 Aug 2024 18:19:07 +0530 Subject: [PATCH 01/39] feat: add taxjar api --- crates/api_models/src/enums.rs | 21 + crates/api_models/src/events/payment.rs | 15 + crates/api_models/src/payments.rs | 26 +- crates/diesel_models/src/payment_intent.rs | 2 + crates/diesel_models/src/schema.rs | 1 + .../src/default_implementations.rs | 28 +- .../src/default_implementations_v2.rs | 13 +- .../hyperswitch_domain_models/src/payments.rs | 1 + .../src/payments/payment_attempt.rs | 8 + .../src/router_flow_types/payments.rs | 3 + .../src/router_request_types.rs | 12 +- .../src/router_response_types.rs | 5 + .../src/api/payments.rs | 15 +- .../src/api/payments_v2.rs | 16 +- crates/openapi/src/openapi.rs | 1 + crates/router/src/core/payments.rs | 82 +++- .../connector_integration_v2_impls.rs | 18 + crates/router/src/core/payments/flows.rs | 94 +++++ .../payments/flows/tax_calculation_flow.rs | 131 ++++++ crates/router/src/core/payments/helpers.rs | 3 + crates/router/src/core/payments/operations.rs | 17 + .../payments/operations/payment_create.rs | 1 + .../payments/operations/payment_response.rs | 53 ++- .../payments/operations/tax_calculation.rs | 395 ++++++++++++++++++ .../router/src/core/payments/transformers.rs | 43 ++ crates/router/src/core/utils.rs | 110 +++++ crates/router/src/routes/app.rs | 4 + crates/router/src/routes/lock_utils.rs | 3 +- crates/router/src/routes/payments.rs | 83 ++++ crates/router/src/services/api.rs | 5 + crates/router/src/types.rs | 18 +- crates/router/src/types/api.rs | 31 ++ crates/router/src/types/api/payments.rs | 7 +- crates/router/src/types/api/payments_v2.rs | 2 +- crates/router/src/utils/user/sample_data.rs | 1 + crates/router/tests/connectors/utils.rs | 2 + crates/router_derive/src/macros/operation.rs | 10 +- crates/router_env/src/logger/types.rs | 2 + .../down.sql | 3 + .../up.sql | 2 + 40 files changed, 1260 insertions(+), 27 deletions(-) create mode 100644 crates/router/src/core/payments/flows/tax_calculation_flow.rs create mode 100644 crates/router/src/core/payments/operations/tax_calculation.rs create mode 100644 migrations/2024-08-05-171030_add_shipping_cost_in_payment_intent/down.sql create mode 100644 migrations/2024-08-05-171030_add_shipping_cost_in_payment_intent/up.sql diff --git a/crates/api_models/src/enums.rs b/crates/api_models/src/enums.rs index eed29b1aa0d9..b8e970ff72f7 100644 --- a/crates/api_models/src/enums.rs +++ b/crates/api_models/src/enums.rs @@ -402,6 +402,27 @@ pub enum FrmConnectors { Riskified, } +// #[cfg(feature = "tax_calculate")] +#[derive( + Clone, + Copy, + Debug, + Eq, + Hash, + PartialEq, + serde::Serialize, + serde::Deserialize, + strum::Display, + strum::EnumString, + ToSchema, +)] +#[serde(rename_all = "snake_case")] +#[strum(serialize_all = "snake_case")] + +pub enum TaxCalculatorConnectors { + TaxJar, +} + #[derive( Clone, Debug, serde::Deserialize, serde::Serialize, strum::Display, strum::EnumString, ToSchema, )] diff --git a/crates/api_models/src/events/payment.rs b/crates/api_models/src/events/payment.rs index 589dcd8d10b3..5972e6edf083 100644 --- a/crates/api_models/src/events/payment.rs +++ b/crates/api_models/src/events/payment.rs @@ -20,6 +20,7 @@ use crate::{ PaymentListFilterConstraints, PaymentListFilters, PaymentListFiltersV2, PaymentListResponse, PaymentListResponseV2, PaymentsApproveRequest, PaymentsCancelRequest, PaymentsCaptureRequest, PaymentsCompleteAuthorizeRequest, + PaymentsDynamicTaxCalculationRequest, PaymentsDynamicTaxCalculationResponse, PaymentsExternalAuthenticationRequest, PaymentsExternalAuthenticationResponse, PaymentsIncrementalAuthorizationRequest, PaymentsManualUpdateRequest, PaymentsRejectRequest, PaymentsRequest, PaymentsResponse, PaymentsRetrieveRequest, @@ -61,6 +62,20 @@ impl ApiEventMetric for PaymentsCompleteAuthorizeRequest { } } +impl ApiEventMetric for PaymentsDynamicTaxCalculationRequest { + fn get_api_event_type(&self) -> Option { + Some(ApiEventsType::Payment { + payment_id: self.payment_id.clone(), + }) + } +} + +impl ApiEventMetric for PaymentsDynamicTaxCalculationResponse { + fn get_api_event_type(&self) -> Option { + Some(ApiEventsType::ResourceListAPI) + } +} + impl ApiEventMetric for PaymentsCancelRequest { fn get_api_event_type(&self) -> Option { Some(ApiEventsType::Payment { diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs index 88c915f0e73d..fe66febc7b7f 100644 --- a/crates/api_models/src/payments.rs +++ b/crates/api_models/src/payments.rs @@ -260,6 +260,9 @@ pub struct PaymentsRequest { #[schema(value_type = Option, example = 6540)] pub amount_to_capture: Option, + #[schema(value_type = Option, example = 6540)] + pub shipping_cost: Option, + /// Unique identifier for the payment. This ensures idempotency for multiple payments /// that have been done by a single merchant. The value for this field can be specified in the request, it will be auto generated otherwise and returned in the API response. #[schema( @@ -4430,6 +4433,27 @@ pub struct PaymentsSessionRequest { pub merchant_connector_details: Option, } +/// Request for calling tax jar API +#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, ToSchema)] +pub struct PaymentsDynamicTaxCalculationRequest { + /// The unique identifier for the payment + #[serde(skip_deserializing)] + pub payment_id: String, + /// The shipping address for the payment + pub shipping: Address, + /// Client Secret + #[schema(value_type = String)] + pub client_secret: String, +} +/// Response for calling tax jar API +#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, ToSchema)] +pub struct PaymentsDynamicTaxCalculationResponse { + /// Amount of sales tax to collect. + // pub order_tax_amount: i64, + /// net amount + pub net_amount: MinorUnit, +} + #[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, serde::Deserialize, ToSchema)] pub struct GpayAllowedMethodsParameters { /// The list of allowed auth methods (ex: 3DS, No3DS, PAN_ONLY etc) @@ -4696,7 +4720,7 @@ pub struct SessionTokenForSimplifiedApplePay { #[serde(tag = "wallet_name")] #[serde(rename_all = "snake_case")] pub enum SessionToken { - /// The session response structure for Google Pay + /// The session -structure for Google Pay GooglePay(Box), /// The session response structure for Klarna Klarna(Box), diff --git a/crates/diesel_models/src/payment_intent.rs b/crates/diesel_models/src/payment_intent.rs index bdea1fe52a76..4f7ef8715b40 100644 --- a/crates/diesel_models/src/payment_intent.rs +++ b/crates/diesel_models/src/payment_intent.rs @@ -130,6 +130,7 @@ pub struct PaymentIntent { pub merchant_order_reference_id: Option, pub shipping_details: Option, pub is_payment_processor_token_flow: Option, + pub shipping_cost: Option, } #[derive( @@ -190,6 +191,7 @@ pub struct PaymentIntentNew { pub merchant_order_reference_id: Option, pub shipping_details: Option, pub is_payment_processor_token_flow: Option, + pub shipping_cost: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] diff --git a/crates/diesel_models/src/schema.rs b/crates/diesel_models/src/schema.rs index ebeff9c97f3c..4ecd88975406 100644 --- a/crates/diesel_models/src/schema.rs +++ b/crates/diesel_models/src/schema.rs @@ -899,6 +899,7 @@ diesel::table! { merchant_order_reference_id -> Nullable, shipping_details -> Nullable, is_payment_processor_token_flow -> Nullable, + shipping_cost -> Nullable, } } diff --git a/crates/hyperswitch_connectors/src/default_implementations.rs b/crates/hyperswitch_connectors/src/default_implementations.rs index dd3f2152cd87..c4e625c940b7 100644 --- a/crates/hyperswitch_connectors/src/default_implementations.rs +++ b/crates/hyperswitch_connectors/src/default_implementations.rs @@ -28,13 +28,13 @@ use hyperswitch_domain_models::{ files::{Retrieve, Upload}, mandate_revoke::MandateRevoke, payments::{ - Approve, AuthorizeSessionToken, CompleteAuthorize, CreateConnectorCustomer, + Approve, AuthorizeSessionToken, CalculateTax, CompleteAuthorize, CreateConnectorCustomer, IncrementalAuthorization, PostProcessing, PreProcessing, Reject, }, webhooks::VerifyWebhookSource, }, router_request_types::{ - AcceptDisputeRequestData, AuthorizeSessionTokenData, CompleteAuthorizeData, + AcceptDisputeRequestData, AuthorizeSessionTokenData,PaymentsTaxCalculationData, CompleteAuthorizeData, ConnectorCustomerData, DefendDisputeRequestData, MandateRevokeRequestData, PaymentsApproveData, PaymentsIncrementalAuthorizationData, PaymentsPostProcessingData, PaymentsPreProcessingData, PaymentsRejectData, RetrieveFileRequestData, @@ -62,7 +62,7 @@ use hyperswitch_interfaces::{ disputes::{AcceptDispute, DefendDispute, Dispute, SubmitEvidence}, files::{FileUpload, RetrieveFile, UploadFile}, payments::{ - ConnectorCustomer, PaymentApprove, PaymentAuthorizeSessionToken, + ConnectorCustomer, PaymentApprove, PaymentAuthorizeSessionToken,PaymentTaxCalculation, PaymentIncrementalAuthorization, PaymentReject, PaymentsCompleteAuthorize, PaymentsPostProcessing, PaymentsPreProcessing, }, @@ -93,6 +93,28 @@ default_imp_for_authorize_session_token!( connectors::Stax ); +macro_rules! default_imp_for_calculate_tax { + ($($path:ident::$connector:ident),*) => { + $( impl PaymentTaxCalculation for $path::$connector {} + impl + ConnectorIntegration< + CalculateTax, + PaymentsTaxCalculationData, + PaymentsResponseData + > for $path::$connector + {} + )* + }; +} + +default_imp_for_calculate_tax!( + connectors::Bambora, + connectors::Bitpay, + connectors::Fiserv, + connectors::Helcim, + connectors::Stax +); + use crate::connectors; macro_rules! default_imp_for_complete_authorize { ($($path:ident::$connector:ident),*) => { diff --git a/crates/hyperswitch_connectors/src/default_implementations_v2.rs b/crates/hyperswitch_connectors/src/default_implementations_v2.rs index 050c8687d897..e0282c225c03 100644 --- a/crates/hyperswitch_connectors/src/default_implementations_v2.rs +++ b/crates/hyperswitch_connectors/src/default_implementations_v2.rs @@ -14,14 +14,14 @@ use hyperswitch_domain_models::{ payments::{ Approve, Authorize, AuthorizeSessionToken, Capture, CompleteAuthorize, CreateConnectorCustomer, IncrementalAuthorization, PSync, PaymentMethodToken, - PostProcessing, PreProcessing, Reject, Session, SetupMandate, Void, + PostProcessing, PreProcessing, Reject, Session, SetupMandate, Void,CalculateTax, }, refunds::{Execute, RSync}, webhooks::VerifyWebhookSource, AccessTokenAuth, }, router_request_types::{ - AcceptDisputeRequestData, AccessTokenRequestData, AuthorizeSessionTokenData, + AcceptDisputeRequestData, AccessTokenRequestData, AuthorizeSessionTokenData,PaymentsTaxCalculationData, CompleteAuthorizeData, ConnectorCustomerData, DefendDisputeRequestData, MandateRevokeRequestData, PaymentMethodTokenizationData, PaymentsApproveData, PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, @@ -74,7 +74,7 @@ use hyperswitch_interfaces::{ ConnectorCustomerV2, MandateSetupV2, PaymentApproveV2, PaymentAuthorizeSessionTokenV2, PaymentAuthorizeV2, PaymentCaptureV2, PaymentIncrementalAuthorizationV2, PaymentRejectV2, PaymentSessionV2, PaymentSyncV2, PaymentTokenV2, PaymentV2, - PaymentVoidV2, PaymentsCompleteAuthorizeV2, PaymentsPostProcessingV2, + PaymentVoidV2, PaymentsCompleteAuthorizeV2, PaymentsPostProcessingV2, PaymentTaxCalculationV2, PaymentsPreProcessingV2, }, refunds_v2::{RefundExecuteV2, RefundSyncV2, RefundV2}, @@ -104,6 +104,7 @@ macro_rules! default_imp_for_new_connector_integration_payment { impl ConnectorCustomerV2 for $path::$connector{} impl PaymentsPreProcessingV2 for $path::$connector{} impl PaymentsPostProcessingV2 for $path::$connector{} + impl PaymentTaxCalculationV2 for $path::$connector{} impl ConnectorIntegrationV2 for $path::$connector{} @@ -176,6 +177,12 @@ macro_rules! default_imp_for_new_connector_integration_payment { AuthorizeSessionTokenData, PaymentsResponseData > for $path::$connector{} + impl ConnectorIntegrationV2< + CalculateTax, + PaymentFlowData, + PaymentsTaxCalculationData, + PaymentsResponseData, + > for $path::$connector{} )* }; } diff --git a/crates/hyperswitch_domain_models/src/payments.rs b/crates/hyperswitch_domain_models/src/payments.rs index 3f7cfde2f782..f0dc8b72bdb0 100644 --- a/crates/hyperswitch_domain_models/src/payments.rs +++ b/crates/hyperswitch_domain_models/src/payments.rs @@ -16,6 +16,7 @@ pub struct PaymentIntent { pub merchant_id: id_type::MerchantId, pub status: storage_enums::IntentStatus, pub amount: MinorUnit, + pub shipping_cost: Option, pub currency: Option, pub amount_captured: Option, pub customer_id: Option, diff --git a/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs b/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs index 54c86f3a4e11..5ed3db839018 100644 --- a/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs +++ b/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs @@ -474,6 +474,11 @@ pub enum PaymentAttemptUpdate { unified_code: Option, unified_message: Option, }, + // SessionUpdate { + // amount: MinorUnit, + // order_tax_amount: MinorUnit, + // payment_method_shipping_address_id: Option, + // }, } impl ForeignIDRef for PaymentAttempt { @@ -742,6 +747,7 @@ impl behaviour::Conversion for PaymentIntent { merchant_order_reference_id: self.merchant_order_reference_id, shipping_details: self.shipping_details.map(Encryption::from), is_payment_processor_token_flow: self.is_payment_processor_token_flow, + shipping_cost: self.shipping_cost, }) } @@ -811,6 +817,7 @@ impl behaviour::Conversion for PaymentIntent { .request_external_three_ds_authentication, charges: storage_model.charges, frm_metadata: storage_model.frm_metadata, + shipping_cost: storage_model.shipping_cost, customer_details: storage_model .customer_details .async_lift(inner_decrypt) @@ -883,6 +890,7 @@ impl behaviour::Conversion for PaymentIntent { merchant_order_reference_id: self.merchant_order_reference_id, shipping_details: self.shipping_details.map(Encryption::from), is_payment_processor_token_flow: self.is_payment_processor_token_flow, + shipping_cost: self.shipping_cost, }) } } diff --git a/crates/hyperswitch_domain_models/src/router_flow_types/payments.rs b/crates/hyperswitch_domain_models/src/router_flow_types/payments.rs index 1263f8f975a6..8a6414c2bfd1 100644 --- a/crates/hyperswitch_domain_models/src/router_flow_types/payments.rs +++ b/crates/hyperswitch_domain_models/src/router_flow_types/payments.rs @@ -49,3 +49,6 @@ pub struct IncrementalAuthorization; #[derive(Debug, Clone)] pub struct PostProcessing; + +#[derive(Debug, Clone)] +pub struct CalculateTax; diff --git a/crates/hyperswitch_domain_models/src/router_request_types.rs b/crates/hyperswitch_domain_models/src/router_request_types.rs index 808000e8dc89..bf39587325f0 100644 --- a/crates/hyperswitch_domain_models/src/router_request_types.rs +++ b/crates/hyperswitch_domain_models/src/router_request_types.rs @@ -2,7 +2,7 @@ pub mod authentication; pub mod fraud_check; use api_models::payments::RequestSurchargeDetails; use common_utils::{ - consts, errors, ext_traits::OptionExt, id_type, pii, types as common_types, types::MinorUnit, + consts, crypto::Encryptable, errors, ext_traits::OptionExt, id_type, pii, types::{self as common_types, MinorUnit} }; use diesel_models::enums as storage_enums; use error_stack::ResultExt; @@ -771,6 +771,16 @@ pub struct PaymentsSessionData { pub minor_amount: MinorUnit, } +#[derive(Debug, Clone, Default)] +pub struct PaymentsTaxCalculationData { + pub amount: i64, + // New amount for amount frame work + // pub minor_amount: MinorUnit, + pub shipping_cost: MinorUnit, + pub shipping: Option>>, + pub order_details: Option>>, +} + #[derive(Debug, Clone)] pub struct SetupMandateRequestData { pub currency: storage_enums::Currency, diff --git a/crates/hyperswitch_domain_models/src/router_response_types.rs b/crates/hyperswitch_domain_models/src/router_response_types.rs index e41b0aa78b9d..91345b994379 100644 --- a/crates/hyperswitch_domain_models/src/router_response_types.rs +++ b/crates/hyperswitch_domain_models/src/router_response_types.rs @@ -68,6 +68,11 @@ pub enum PaymentsResponseData { PostProcessingResponse { session_token: Option, }, + TaxCalculationResponse { + order_tax_amount: i64, + net_amount: i64, + shipping_address: Option, + }, } #[derive(serde::Serialize, Debug, Clone)] diff --git a/crates/hyperswitch_interfaces/src/api/payments.rs b/crates/hyperswitch_interfaces/src/api/payments.rs index 8a53f65805e7..9ce106624e86 100644 --- a/crates/hyperswitch_interfaces/src/api/payments.rs +++ b/crates/hyperswitch_interfaces/src/api/payments.rs @@ -2,13 +2,13 @@ use hyperswitch_domain_models::{ router_flow_types::payments::{ - Approve, Authorize, AuthorizeSessionToken, Capture, CompleteAuthorize, + Approve, Authorize, AuthorizeSessionToken, Capture, CalculateTax, CompleteAuthorize, CreateConnectorCustomer, IncrementalAuthorization, PSync, PaymentMethodToken, PostProcessing, PreProcessing, Reject, Session, SetupMandate, Void, }, router_request_types::{ AuthorizeSessionTokenData, CompleteAuthorizeData, ConnectorCustomerData, - PaymentMethodTokenizationData, PaymentsApproveData, PaymentsAuthorizeData, + PaymentMethodTokenizationData, PaymentsApproveData, PaymentsAuthorizeData, PaymentsTaxCalculationData, PaymentsCancelData, PaymentsCaptureData, PaymentsIncrementalAuthorizationData, PaymentsPostProcessingData, PaymentsPreProcessingData, PaymentsRejectData, PaymentsSessionData, PaymentsSyncData, SetupMandateRequestData, @@ -37,6 +37,7 @@ pub trait Payment: + PaymentsPostProcessing + ConnectorCustomer + PaymentIncrementalAuthorization + + PaymentTaxCalculation { } @@ -110,6 +111,16 @@ pub trait PaymentIncrementalAuthorization: { } +/// trait PaymentTaxCalculation +pub trait PaymentTaxCalculation: + api::ConnectorIntegration< + CalculateTax, + PaymentsTaxCalculationData, + PaymentsResponseData, +> +{ +} + /// trait PaymentsCompleteAuthorize pub trait PaymentsCompleteAuthorize: api::ConnectorIntegration diff --git a/crates/hyperswitch_interfaces/src/api/payments_v2.rs b/crates/hyperswitch_interfaces/src/api/payments_v2.rs index 4ebe9e8517f0..7efc3ac6a92e 100644 --- a/crates/hyperswitch_interfaces/src/api/payments_v2.rs +++ b/crates/hyperswitch_interfaces/src/api/payments_v2.rs @@ -5,14 +5,14 @@ use hyperswitch_domain_models::{ router_flow_types::payments::{ Approve, Authorize, AuthorizeSessionToken, Capture, CompleteAuthorize, CreateConnectorCustomer, IncrementalAuthorization, PSync, PaymentMethodToken, - PostProcessing, PreProcessing, Reject, Session, SetupMandate, Void, + PostProcessing, PreProcessing, Reject, Session, SetupMandate, Void,CalculateTax, }, router_request_types::{ AuthorizeSessionTokenData, CompleteAuthorizeData, ConnectorCustomerData, PaymentMethodTokenizationData, PaymentsApproveData, PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, PaymentsIncrementalAuthorizationData, PaymentsPostProcessingData, PaymentsPreProcessingData, PaymentsRejectData, - PaymentsSessionData, PaymentsSyncData, SetupMandateRequestData, + PaymentsSessionData, PaymentsSyncData, SetupMandateRequestData,PaymentsTaxCalculationData, }, router_response_types::PaymentsResponseData, }; @@ -89,6 +89,17 @@ pub trait PaymentIncrementalAuthorizationV2: { } +///trait PaymentTaxCalculationV2 +pub trait PaymentTaxCalculationV2: + ConnectorIntegrationV2< + CalculateTax, + PaymentFlowData, + PaymentsTaxCalculationData, + PaymentsResponseData, +> +{ +} + /// trait PaymentsCompleteAuthorizeV2 pub trait PaymentsCompleteAuthorizeV2: ConnectorIntegrationV2< @@ -163,5 +174,6 @@ pub trait PaymentV2: + PaymentsPostProcessingV2 + ConnectorCustomerV2 + PaymentIncrementalAuthorizationV2 + + PaymentTaxCalculationV2 { } diff --git a/crates/openapi/src/openapi.rs b/crates/openapi/src/openapi.rs index 50bbd7970516..ad74bcde1558 100644 --- a/crates/openapi/src/openapi.rs +++ b/crates/openapi/src/openapi.rs @@ -568,6 +568,7 @@ Never share your secret api keys. Keep them guarded and secure. api_models::payments::CustomerDetailsResponse, api_models::payments::OpenBankingData, api_models::payments::OpenBankingSessionToken, + api_models::payments::PaymentsDynamicTaxCalculationRequest, )), modifiers(&SecurityAddon) )] diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs index b4f369f71b45..a66cd10a5f8b 100644 --- a/crates/router/src/core/payments.rs +++ b/crates/router/src/core/payments.rs @@ -29,7 +29,7 @@ pub use common_enums::enums::CallConnectorAction; use common_utils::{ ext_traits::{AsyncExt, StringExt}, id_type, pii, - types::{MinorUnit, Surcharge}, + types::{ MinorUnit, Surcharge}, }; use diesel_models::{ephemeral_key, fraud_check::FraudCheck}; use error_stack::{report, ResultExt}; @@ -55,7 +55,7 @@ use time; pub use self::operations::{ PaymentApprove, PaymentCancel, PaymentCapture, PaymentConfirm, PaymentCreate, PaymentIncrementalAuthorization, PaymentReject, PaymentResponse, PaymentSession, PaymentStatus, - PaymentUpdate, + PaymentTaxCalculation, PaymentUpdate, }; use self::{ conditional_configs::perform_decision_management, @@ -249,6 +249,19 @@ where &key_store, ) .await?; + + let tax_response = operation + .to_domain()? + .payments_dynamic_tax_calculation( + state, + &mut payment_data, + &mut should_continue_transaction, + &connector_details, + &key_store, + &merchant_account, + ) + .await?; + if should_continue_transaction { #[cfg(feature = "frm")] match ( @@ -783,6 +796,70 @@ where }) } } +// pub async fn payments_dynamic_tax_calculation( +// state: SessionState, +// req_state: ReqState, +// merchant_account: domain::MerchantAccount, +// key_store: domain::MerchantKeyStore, +// operation: Op, +// req: api_models::payments::PaymentsDynamicTaxCalculationRequest, +// auth_flow: services::AuthFlow, +// call_connector_action: CallConnectorAction, +// eligible_connectors: Option>, +// customer: &Option, +// // header_payload: HeaderPayload, +// ) -> RouterResponse { + +// let db = &state.store; +// let payment_intent = db +// .find_payment_intent_by_payment_id_merchant_id( +// &(&state).into(), +// &req.payment_id.clone(), +// &merchant_account.merchant_id, +// &key_store, +// merchant_account.storage_scheme, +// ) +// .await +// .change_context(errors::ApiErrorResponse::PaymentNotFound)?; +// let attempt_id = payment_intent.active_attempt.get_id().clone(); +// let payment_attempt = db +// .find_payment_attempt_by_payment_id_merchant_id_attempt_id( +// &payment_intent.payment_id, +// &merchant_account.merchant_id, +// &attempt_id.clone(), +// merchant_account.storage_scheme, +// ) +// .await +// .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?; +// let connector_data = api::TaxCalculateConnectorData::get_connector_by_name( +// payment_attempt.connector.as_ref().unwrap(), +// )?; +// let router_data = utils::construct_payments_dynamic_tax_calculation_router_data( +// &state, +// &payment_intent, +// &payment_attempt, +// &merchant_account, +// &key_store, +// &customer, +// ) +// .await?; +// let connector_integration: services::BoxedPaymentConnectorIntegrationInterface = connector_data.connector.get_connector_integration(); +// let response = services::execute_connector_processing_step( +// &state, +// connector_integration, +// &router_data, +// CallConnectorAction::Trigger, +// None, +// ) +// .await.change_context(errors::ApiErrorResponse::InternalServerError)?; +// Ok(services::ApplicationResponse::Json( +// api_models::payments::PaymentsDynamicTaxCalculationResponse { +// order_tax_amount: response.amount_captured.unwrap_or_default(), +// net_amount: response.amount_captured.unwrap_or_default(), +// } +// )) +// } + #[allow(clippy::too_many_arguments)] pub async fn payments_core( state: SessionState, @@ -2857,6 +2934,7 @@ pub fn should_call_connector( "PaymentApprove" => true, "PaymentReject" => true, "PaymentSession" => true, + "PaymentTaxCalculation" => true, "PaymentIncrementalAuthorization" => matches!( payment_data.payment_intent.status, storage_enums::IntentStatus::RequiresCapture diff --git a/crates/router/src/core/payments/connector_integration_v2_impls.rs b/crates/router/src/core/payments/connector_integration_v2_impls.rs index 92ec7c0094d4..6a4530b5c578 100644 --- a/crates/router/src/core/payments/connector_integration_v2_impls.rs +++ b/crates/router/src/core/payments/connector_integration_v2_impls.rs @@ -42,6 +42,8 @@ mod dummy_connector_default_impl { impl api::PaymentsPostProcessingV2 for connector::DummyConnector {} + impl api::PaymentTaxCalculationV2 for connector::DummyConnector {} + impl services::ConnectorIntegrationV2< api::Authorize, @@ -181,6 +183,15 @@ mod dummy_connector_default_impl { > for connector::DummyConnector { } + impl + services::ConnectorIntegrationV2< + api::CalculateTax, + types::PaymentFlowData, + types::PaymentsTaxCalculationData, + types::PaymentsResponseData, + > for connector::DummyConnector + { + } impl services::ConnectorIntegrationV2< @@ -557,6 +568,7 @@ macro_rules! default_imp_for_new_connector_integration_payment { impl api::ConnectorCustomerV2 for $path::$connector{} impl api::PaymentsPreProcessingV2 for $path::$connector{} impl api::PaymentsPostProcessingV2 for $path::$connector{} + impl api::PaymentTaxCalculationV2 for $path::$connector{} impl services::ConnectorIntegrationV2 for $path::$connector{} @@ -629,6 +641,12 @@ macro_rules! default_imp_for_new_connector_integration_payment { types::AuthorizeSessionTokenData, types::PaymentsResponseData > for $path::$connector{} + impl services::ConnectorIntegrationV2< + api::CalculateTax, + types::PaymentFlowData, + types::PaymentsTaxCalculationData, + types::PaymentsResponseData, + > for $path::$connector{} )* }; } diff --git a/crates/router/src/core/payments/flows.rs b/crates/router/src/core/payments/flows.rs index 893cc957bb2e..26acdbe4921f 100644 --- a/crates/router/src/core/payments/flows.rs +++ b/crates/router/src/core/payments/flows.rs @@ -8,6 +8,7 @@ pub mod psync_flow; pub mod reject_flow; pub mod session_flow; pub mod setup_mandate_flow; +pub mod tax_calculation_flow; use async_trait::async_trait; @@ -3131,3 +3132,96 @@ default_imp_for_authorize_session_token!( connector::Zen, connector::Zsl ); + + +macro_rules! default_imp_for_calculate_tax { + ($($path:ident::$connector:ident),*) => { + $( impl api::PaymentTaxCalculation for $path::$connector {} + impl + services::ConnectorIntegration< + api::CalculateTax, + types::PaymentsTaxCalculationData, + types::PaymentsResponseData + > for $path::$connector + {} + )* + }; +} +#[cfg(feature = "dummy_connector")] +impl api::PaymentTaxCalculation for connector::DummyConnector {} +#[cfg(feature = "dummy_connector")] +impl + services::ConnectorIntegration< + api::CalculateTax, + types::PaymentsTaxCalculationData, + types::PaymentsResponseData, + > for connector::DummyConnector +{ +} + +default_imp_for_calculate_tax!( + connector::Aci, + connector::Adyen, + connector::Adyenplatform, + connector::Airwallex, + connector::Authorizedotnet, + connector::Bamboraapac, + connector::Bankofamerica, + connector::Billwerk, + connector::Bluesnap, + connector::Boku, + connector::Braintree, + connector::Cashtocode, + connector::Checkout, + connector::Cryptopay, + connector::Coinbase, + connector::Cybersource, + connector::Datatrans, + connector::Dlocal, + connector::Ebanx, + connector::Forte, + connector::Globalpay, + connector::Globepay, + connector::Gocardless, + connector::Gpayments, + connector::Iatapay, + connector::Itaubank, + connector::Klarna, + connector::Mifinity, + connector::Mollie, + connector::Multisafepay, + connector::Netcetera, + connector::Nexinets, + connector::Nuvei, + connector::Nmi, + connector::Noon, + connector::Opayo, + connector::Opennode, + connector::Paybox, + connector::Payeezy, + connector::Payme, + connector::Payone, + connector::Paypal, + connector::Payu, + connector::Placetopay, + connector::Plaid, + connector::Powertranz, + connector::Prophetpay, + connector::Rapyd, + connector::Razorpay, + connector::Riskified, + connector::Square, + connector::Signifyd, + connector::Stripe, + connector::Shift4, + connector::Threedsecureio, + connector::Trustpay, + connector::Tsys, + connector::Volt, + connector::Wellsfargo, + connector::Wise, + connector::Worldline, + connector::Worldpay, + connector::Zen, + connector::Zsl +); diff --git a/crates/router/src/core/payments/flows/tax_calculation_flow.rs b/crates/router/src/core/payments/flows/tax_calculation_flow.rs new file mode 100644 index 000000000000..d8b8e891ae7e --- /dev/null +++ b/crates/router/src/core/payments/flows/tax_calculation_flow.rs @@ -0,0 +1,131 @@ +use async_trait::async_trait; + +use super::ConstructFlowSpecificData; +use crate::{ + core::{ + errors::{ConnectorErrorExt, RouterResult}, + payments::{self, access_token, helpers, transformers, Feature, PaymentData}, + }, + routes::SessionState, + services, + types::{self, api, domain}, +}; + +#[async_trait] +impl + ConstructFlowSpecificData< + api::CalculateTax, + types::PaymentsTaxCalculationData, + types::PaymentsResponseData, + > for PaymentData +{ + async fn construct_router_data<'a>( + &self, + state: &SessionState, + connector_id: &str, + merchant_account: &domain::MerchantAccount, + key_store: &domain::MerchantKeyStore, + customer: &Option, + merchant_connector_account: &helpers::MerchantConnectorAccountType, + merchant_recipient_data: Option, + ) -> RouterResult { + Box::pin(transformers::construct_payment_router_data::< + api::CalculateTax, + types::PaymentsTaxCalculationData, + >( + state, + self.clone(), + connector_id, + merchant_account, + key_store, + customer, + merchant_connector_account, + merchant_recipient_data, + )) + .await + } + + async fn get_merchant_recipient_data<'a>( + &self, + _state: &SessionState, + _merchant_account: &domain::MerchantAccount, + _key_store: &domain::MerchantKeyStore, + _merchant_connector_account: &helpers::MerchantConnectorAccountType, + _connector: &api::ConnectorData, + ) -> RouterResult> { + Ok(None) + } +} + +#[async_trait] +impl Feature + for types::RouterData< + api::CalculateTax, + types::PaymentsTaxCalculationData, + types::PaymentsResponseData, + > +{ + async fn decide_flows<'a>( + self, + state: &SessionState, + connector: &api::ConnectorData, + call_connector_action: payments::CallConnectorAction, + connector_request: Option, + _business_profile: &domain::BusinessProfile, + _header_payload: api_models::payments::HeaderPayload, + ) -> RouterResult { + let connector_integration: services::BoxedPaymentConnectorIntegrationInterface< + api::CalculateTax, + types::PaymentsTaxCalculationData, + types::PaymentsResponseData, + > = connector.connector.get_connector_integration(); + + let resp = services::execute_connector_processing_step( + state, + connector_integration, + &self, + call_connector_action, + connector_request, + ) + .await + .to_payment_failed_response()?; + + Ok(resp) + } + + async fn add_access_token<'a>( + &self, + state: &SessionState, + connector: &api::ConnectorData, + merchant_account: &domain::MerchantAccount, + creds_identifier: Option<&String>, + ) -> RouterResult { + access_token::add_access_token(state, connector, merchant_account, self, creds_identifier) + .await + } + + async fn build_flow_specific_connector_request( + &mut self, + state: &SessionState, + connector: &api::ConnectorData, + call_connector_action: payments::CallConnectorAction, + ) -> RouterResult<(Option, bool)> { + let request = match call_connector_action { + payments::CallConnectorAction::Trigger => { + let connector_integration: services::BoxedPaymentConnectorIntegrationInterface< + api::CalculateTax, + types::PaymentsTaxCalculationData, + types::PaymentsResponseData, + > = connector.connector.get_connector_integration(); + + connector_integration + .build_request(self, &state.conf.connectors) + .to_payment_failed_response()? + } + _ => None, + }; + + Ok((request, true)) + } +} + diff --git a/crates/router/src/core/payments/helpers.rs b/crates/router/src/core/payments/helpers.rs index d3ca7d042864..50fa6840e52c 100644 --- a/crates/router/src/core/payments/helpers.rs +++ b/crates/router/src/core/payments/helpers.rs @@ -3089,6 +3089,7 @@ mod tests { merchant_order_reference_id: None, shipping_details: None, is_payment_processor_token_flow: None, + shipping_cost: None, }; let req_cs = Some("1".to_string()); assert!(authenticate_client_secret(req_cs.as_ref(), &payment_intent).is_ok()); @@ -3154,6 +3155,7 @@ mod tests { merchant_order_reference_id: None, shipping_details: None, is_payment_processor_token_flow: None, + shipping_cost: None, }; let req_cs = Some("1".to_string()); assert!(authenticate_client_secret(req_cs.as_ref(), &payment_intent,).is_err()) @@ -3217,6 +3219,7 @@ mod tests { merchant_order_reference_id: None, shipping_details: None, is_payment_processor_token_flow: None, + shipping_cost: None, }; let req_cs = Some("1".to_string()); assert!(authenticate_client_secret(req_cs.as_ref(), &payment_intent).is_err()) diff --git a/crates/router/src/core/payments/operations.rs b/crates/router/src/core/payments/operations.rs index cd932fd54a8c..f38d9e79e1bd 100644 --- a/crates/router/src/core/payments/operations.rs +++ b/crates/router/src/core/payments/operations.rs @@ -11,6 +11,7 @@ pub mod payment_start; pub mod payment_status; pub mod payment_update; pub mod payments_incremental_authorization; +pub mod tax_calculation; use api_models::enums::FrmSuggestion; use async_trait::async_trait; @@ -24,6 +25,7 @@ pub use self::{ payment_response::PaymentResponse, payment_session::PaymentSession, payment_start::PaymentStart, payment_status::PaymentStatus, payment_update::PaymentUpdate, payments_incremental_authorization::PaymentIncrementalAuthorization, + tax_calculation::PaymentTaxCalculation, }; use super::{helpers, CustomerDetails, PaymentData}; use crate::{ @@ -178,6 +180,21 @@ pub trait Domain: Send + Sync { Ok(()) } + // + async fn payments_dynamic_tax_calculation<'a>( + &'a self, + _state: &SessionState, + _payment_data: &mut PaymentData, + _should_continue_confirm_transaction: &mut bool, + _connector_call_type: &ConnectorCallType, + // _merchant_account: &storage::BusinessProfile, + _key_store: &domain::MerchantKeyStore, + // _storage_scheme: enums::MerchantStorageScheme, + _merchant_account: &domain::MerchantAccount, + ) -> CustomResult<(), errors::ApiErrorResponse> { + Ok(()) + } + #[instrument(skip_all)] async fn guard_payment_against_blocklist<'a>( &'a self, diff --git a/crates/router/src/core/payments/operations/payment_create.rs b/crates/router/src/core/payments/operations/payment_create.rs index 72266e647e91..9839b4032931 100644 --- a/crates/router/src/core/payments/operations/payment_create.rs +++ b/crates/router/src/core/payments/operations/payment_create.rs @@ -1234,6 +1234,7 @@ impl PaymentCreate { merchant_order_reference_id: request.merchant_order_reference_id.clone(), shipping_details, is_payment_processor_token_flow, + shipping_cost: request.shipping_cost, }) } diff --git a/crates/router/src/core/payments/operations/payment_response.rs b/crates/router/src/core/payments/operations/payment_response.rs index fee90d8c42af..d850f29edc68 100644 --- a/crates/router/src/core/payments/operations/payment_response.rs +++ b/crates/router/src/core/payments/operations/payment_response.rs @@ -1,5 +1,6 @@ use std::collections::HashMap; +// use api_models::payments::PaymentsDynamicTaxCalculationRequest; use async_trait::async_trait; use common_enums::AuthorizationStatus; use common_utils::{ @@ -44,7 +45,7 @@ use crate::{ #[derive(Debug, Clone, Copy, router_derive::PaymentOperation)] #[operation( operations = "post_update_tracker", - flow = "sync_data, cancel_data, authorize_data, capture_data, complete_authorize_data, approve_data, reject_data, setup_mandate_data, session_data,incremental_authorization_data" + flow = "sync_data, cancel_data, authorize_data, capture_data, complete_authorize_data, approve_data, reject_data, setup_mandate_data, session_data,incremental_authorization_data, tax_calculation_data" )] pub struct PaymentResponse; @@ -479,6 +480,43 @@ impl PostUpdateTracker, types::PaymentsSessionData> } } +#[async_trait] +impl PostUpdateTracker, types::PaymentsTaxCalculationData> + for PaymentResponse +{ + async fn update_tracker<'b>( + &'b self, + db: &'b SessionState, + payment_id: &api::PaymentIdType, + mut payment_data: PaymentData, + router_data: types::RouterData< + F, + types::PaymentsTaxCalculationData, + types::PaymentsResponseData, + >, + key_store: &domain::MerchantKeyStore, + storage_scheme: enums::MerchantStorageScheme, + ) -> RouterResult> + where + F: 'b + Send, + { + let shipping_address = payment_data.address.get_shipping(); + let amount = payment_data.amount; + + payment_data = Box::pin(payment_response_update_tracker( + db, + payment_id, + payment_data, + router_data, + key_store, + storage_scheme, + )) + .await?; + + Ok(payment_data) + } +} + #[async_trait] impl PostUpdateTracker, types::PaymentsCaptureData> for PaymentResponse @@ -1125,6 +1163,19 @@ async fn payment_response_update_tracker( types::PaymentsResponseData::IncrementalAuthorizationResponse { .. } => (None, None), + types::PaymentsResponseData::TaxCalculationResponse { .. } => (None, None), + // types::PaymentsResponseData::TaxCalculationResponse { + // order_tax_amount, + // net_amount, + // shipping_address, + // } => ( + // None, + // Some(storage::PaymentAttemptUpdate::SessionUpdate { + // amount: net_amount, + // order_tax_amount, + // payment_method_shipping_address_id: shipping_address, + // }), + // ), types::PaymentsResponseData::MultipleCaptureResponse { capture_sync_response_list, } => match payment_data.multiple_capture_data { diff --git a/crates/router/src/core/payments/operations/tax_calculation.rs b/crates/router/src/core/payments/operations/tax_calculation.rs new file mode 100644 index 000000000000..ba95830eeeb3 --- /dev/null +++ b/crates/router/src/core/payments/operations/tax_calculation.rs @@ -0,0 +1,395 @@ +use std::marker::PhantomData; +use api_models::enums::FrmSuggestion; +use async_trait::async_trait; +use common_utils:: + types::keymanager::KeyManagerState +; +use error_stack::ResultExt; +use router_derive::PaymentOperation; +use router_env::{instrument, tracing}; +// use crate::core::payments::Operation; +use super::{BoxedOperation, Domain, GetTracker, Operation, UpdateTracker, ValidateRequest}; +use crate::{ + core::{ + errors::{self, RouterResult, StorageErrorExt}, + payments::{self, helpers, operations, PaymentData}, + utils as core_utils, + }, + routes::{app::ReqState, SessionState}, + services, + types::{ + self, + api::{self, ConnectorCallType, PaymentIdTypeExt}, + domain, + storage::{self, enums as storage_enums}, + }, + utils::OptionExt, +}; +// use api_models::payments::PaymentsDynamicTaxCalculationRequest; +// use crate::types::api::PaymentsDynamicTaxCalculationRequest; + +#[derive(Debug, Clone, Copy, PaymentOperation)] +#[operation(operations = "all", flow = "tax_calculation")] +pub struct PaymentTaxCalculation; + +#[async_trait] +impl GetTracker, api::PaymentsDynamicTaxCalculationRequest> + for PaymentTaxCalculation +{ + #[instrument(skip_all)] + async fn get_trackers<'a>( + &'a self, + state: &'a SessionState, + payment_id: &api::PaymentIdType, + request: &api::PaymentsDynamicTaxCalculationRequest, + merchant_account: &domain::MerchantAccount, + key_store: &domain::MerchantKeyStore, + _auth_flow: services::AuthFlow, + _header_payload: &api::HeaderPayload, + ) -> RouterResult< + operations::GetTrackerResponse<'a, F, api::PaymentsDynamicTaxCalculationRequest>, + > { + let payment_id = payment_id + .get_payment_intent_id() + .change_context(errors::ApiErrorResponse::PaymentNotFound)?; + + let db = &*state.store; + let key_manager_state: &KeyManagerState = &state.into(); + let merchant_id = merchant_account.get_id(); + let storage_scheme = merchant_account.storage_scheme; + + let payment_intent = db + .find_payment_intent_by_payment_id_merchant_id( + &state.into(), + &payment_id, + merchant_id, + key_store, + storage_scheme, + ) + .await + .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?; + + helpers::validate_payment_status_against_not_allowed_statuses( + &payment_intent.status, + &[ + storage_enums::IntentStatus::Failed, + storage_enums::IntentStatus::Succeeded, + ], + "create a session update for", + )?; + + helpers::authenticate_client_secret(Some(&request.client_secret), &payment_intent)?; + + let payment_attempt = db + .find_payment_attempt_by_payment_id_merchant_id_attempt_id( + payment_intent.payment_id.as_str(), + merchant_id, + payment_intent.active_attempt.get_id().as_str(), + storage_scheme, + ) + .await + .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?; + + let currency = payment_intent.currency.get_required_value("currency")?; + + let amount = payment_attempt.get_total_amount().into(); + + let shipping_address = helpers::get_address_by_id( + state, + payment_intent.shipping_address_id.clone(), + key_store, + &payment_intent.payment_id, + merchant_id, + merchant_account.storage_scheme, + ) + .await?; + + let profile_id = payment_intent + .profile_id + .as_ref() + .get_required_value("profile_id") + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("'profile_id' not set in payment intent")?; + + let business_profile = db + .find_business_profile_by_profile_id(key_manager_state, key_store, profile_id) + .await + .to_not_found_response(errors::ApiErrorResponse::BusinessProfileNotFound { + id: profile_id.to_string(), + })?; + + let payment_data = PaymentData { + flow: PhantomData, + payment_intent, + payment_attempt, + currency, + amount, + email: None, + mandate_id: None, + mandate_connector: None, + customer_acceptance: None, + token: None, + token_data: None, + setup_mandate: None, + address: payments::PaymentAddress::new( + shipping_address.as_ref().map(From::from), + None, + None, + business_profile.use_billing_as_payment_method_billing, + ), + confirm: None, + payment_method_data: None, + payment_method_info: None, + force_sync: None, + refunds: vec![], + disputes: vec![], + attempts: None, + sessions_token: vec![], + card_cvc: None, + creds_identifier: None, + pm_token: None, + connector_customer_id: None, + recurring_mandate_payment_data: None, + ephemeral_key: None, + multiple_capture_data: None, + redirect_response: None, + surcharge_details: None, + frm_message: None, + payment_link_data: None, + incremental_authorization_details: None, + authorizations: vec![], + authentication: None, + recurring_details: None, + poll_config: None, + }; + let get_trackers_response = operations::GetTrackerResponse { + operation: Box::new(self), + customer_details: None, + payment_data, + business_profile, + mandate_type: None, + }; + + Ok(get_trackers_response) + } +} + +#[async_trait] +impl Domain + for PaymentTaxCalculation +{ + #[instrument(skip_all)] + async fn get_or_create_customer_details<'a>( + &'a self, + _state: &SessionState, + _payment_data: &mut PaymentData, + _request: Option, + _merchant_key_store: &domain::MerchantKeyStore, + _storage_scheme: storage_enums::MerchantStorageScheme, + ) -> errors::CustomResult< + ( + BoxedOperation<'a, F, api::PaymentsDynamicTaxCalculationRequest>, + Option, + ), + errors::StorageError, + > { + Ok((Box::new(self), None)) + } + + async fn payments_dynamic_tax_calculation<'a>( + &'a self, + state: &SessionState, + // key_manager_state: &common_utils::types::keymanager::KeyManagerState, + payment_data: &mut PaymentData, + _should_continue_confirm_transaction: &mut bool, + _connector_call_type: &ConnectorCallType, + // _merchant_account: &storage::BusinessProfile, + key_store: &domain::MerchantKeyStore, + // storage_scheme: storage_enums::MerchantStorageScheme, + merchant_account: &domain::MerchantAccount, + ) -> errors::CustomResult<(), errors::ApiErrorResponse> { + let db = state.store.as_ref(); + let key_manager_state: KeyManagerState = state.into(); + // Remove these db calls + let mut payment_intent = db + .find_payment_intent_by_payment_id_merchant_id( + &state.into(), + &payment_data.payment_intent.payment_id, + &payment_data.payment_intent.merchant_id, + key_store, + merchant_account.storage_scheme, + ) + .await + .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?; + + let attempt_id = payment_intent.active_attempt.get_id().clone(); + + let mut payment_attempt = db + .find_payment_attempt_by_payment_id_merchant_id_attempt_id( + payment_intent.payment_id.as_str(), + merchant_account.get_id(), + payment_intent.active_attempt.get_id().as_str(), + merchant_account.storage_scheme, + ) + .await + .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?; + + // Derive this connector from business profile + let connector_data = api::TaxCalculateConnectorData::get_connector_by_name( + payment_attempt.connector.as_ref().unwrap(), + )?; + + let router_data = core_utils::construct_payments_dynamic_tax_calculation_router_data( + &state, + &payment_intent, + &payment_attempt, + &merchant_account, + &key_store, + // &customer, + ) + .await?; + let connector_integration: services::BoxedPaymentConnectorIntegrationInterface< + api::CalculateTax, + types::PaymentsTaxCalculationData, + types::PaymentsResponseData, + > = connector_data.connector.get_connector_integration(); + + let response = services::execute_connector_processing_step( + &state, + connector_integration, + &router_data, + payments::CallConnectorAction::Trigger, + None, + ) + .await + .change_context(errors::ApiErrorResponse::InternalServerError)?; + + let tax_response = + response + .response + .map_err(|err| errors::ApiErrorResponse::ExternalConnectorError { + code: err.code, + message: err.message, + connector: connector_data.connector_name.clone().to_string(), + status_code: err.status_code, + reason: err.reason, + })?; + + + // Update payment data.payment_attempt with new amount which was returned by the connector + //payment_data + + Ok(()) + } + + #[instrument(skip_all)] + async fn make_pm_data<'a>( + &'a self, + _state: &'a SessionState, + _payment_data: &mut PaymentData, + _storage_scheme: storage_enums::MerchantStorageScheme, + _merchant_key_store: &domain::MerchantKeyStore, + _customer: &Option, + _business_profile: Option<&domain::BusinessProfile>, + ) -> RouterResult<( + BoxedOperation<'a, F, api::PaymentsDynamicTaxCalculationRequest>, + Option, + Option, + )> { + Ok((Box::new(self), None, None)) + } + + async fn get_connector<'a>( + &'a self, + _merchant_account: &domain::MerchantAccount, + state: &SessionState, + _request: &api::PaymentsDynamicTaxCalculationRequest, + _payment_intent: &storage::PaymentIntent, + _merchant_key_store: &domain::MerchantKeyStore, + ) -> errors::CustomResult { + helpers::get_connector_default(state, None).await + } + + #[instrument(skip_all)] + async fn guard_payment_against_blocklist<'a>( + &'a self, + _state: &SessionState, + _merchant_account: &domain::MerchantAccount, + _key_store: &domain::MerchantKeyStore, + _payment_data: &mut PaymentData, + ) -> errors::CustomResult { + Ok(false) + } +} + +#[async_trait] +impl UpdateTracker, api::PaymentsDynamicTaxCalculationRequest> for PaymentTaxCalculation { + #[instrument(skip_all)] + async fn update_trackers<'b>( + &'b self, + state: &'b SessionState, + _req_state: ReqState, + mut payment_data: PaymentData, + _customer: Option, + storage_scheme: storage_enums::MerchantStorageScheme, + _updated_customer: Option, + key_store: &domain::MerchantKeyStore, + _frm_suggestion: Option, + _header_payload: api::HeaderPayload, + ) -> RouterResult<( + BoxedOperation<'b, F, api::PaymentsDynamicTaxCalculationRequest>, + PaymentData, + )> + where + F: 'b + Send, + { + let payment_intent_update = hyperswitch_domain_models::payments::payment_intent::PaymentIntentUpdate::CompleteAuthorizeUpdate { + shipping_address_id: payment_data.payment_intent.shipping_address_id.clone() + }; + + let db = &*state.store; + let payment_intent = payment_data.payment_intent.clone(); + + let updated_payment_intent = db + .update_payment_intent( + &state.into(), + payment_intent, + payment_intent_update, + key_store, + storage_scheme, + ) + .await + .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?; + + payment_data.payment_intent = updated_payment_intent; + Ok((Box::new(self), payment_data)) + + } +} + +impl ValidateRequest + for PaymentTaxCalculation +{ + #[instrument(skip_all)] + fn validate_request<'a, 'b>( + &'b self, + request: &api::PaymentsDynamicTaxCalculationRequest, + merchant_account: &'a domain::MerchantAccount, + ) -> RouterResult<( + BoxedOperation<'b, F, api::PaymentsDynamicTaxCalculationRequest>, + operations::ValidateResult, + )> { + //paymentid is already generated and should be sent in the request + let given_payment_id = request.payment_id.clone(); + + Ok(( + Box::new(self), + operations::ValidateResult { + merchant_id:merchant_account.get_id().to_owned(), + payment_id: api::PaymentIdType::PaymentIntentId(given_payment_id), + storage_scheme: merchant_account.storage_scheme, + requeue: false, + }, + )) + } +} diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs index 404eb4bae760..4e0ba8dbaab6 100644 --- a/crates/router/src/core/payments/transformers.rs +++ b/crates/router/src/core/payments/transformers.rs @@ -313,6 +313,33 @@ where } } +impl ToResponse, Op> for api::PaymentsDynamicTaxCalculationResponse +where + F: Clone, + Op: Debug, +{ + #[allow(clippy::too_many_arguments)] + fn generate_response( + payment_data: PaymentData, + _customer: Option, + _auth_flow: services::AuthFlow, + _base_url: &str, + _operation: Op, + _connector_request_reference_id_config: &ConnectorRequestReferenceIdConfig, + _connector_http_status_code: Option, + _external_latency: Option, + _is_latency_header_enabled: Option, + ) -> RouterResponse { + Ok(services::ApplicationResponse::JsonWithHeaders(( + Self { + // order_tax_amount: payment_data.amount, + net_amount: MinorUnit::from(payment_data.amount), + }, + vec![], + ))) + } +} + impl ToResponse, Op> for api::VerifyResponse where F: Clone, @@ -1650,6 +1677,22 @@ impl TryFrom> for types::PaymentsApproveD } } + +impl TryFrom> for types::PaymentsTaxCalculationData { + type Error = error_stack::Report; + + fn try_from(additional_data: PaymentAdditionalData<'_, F>) -> Result { + let payment_data = additional_data.payment_data; + let amount = MinorUnit::from(payment_data.amount); + Ok(Self { + amount: amount.get_amount_as_i64(), //need to change after we move to connector module + shipping_cost: payment_data.payment_intent.shipping_cost.ok_or(errors::ApiErrorResponse::InternalServerError).attach_printable("missing shipping_cost in payment_data.payment_intent")?, + shipping: payment_data.payment_intent.shipping_details, + order_details: payment_data.payment_intent.order_details, + }) + } +} + impl TryFrom> for types::PaymentsRejectData { type Error = error_stack::Report; diff --git a/crates/router/src/core/utils.rs b/crates/router/src/core/utils.rs index acedad05b676..fff3da863a8f 100644 --- a/crates/router/src/core/utils.rs +++ b/crates/router/src/core/utils.rs @@ -799,6 +799,116 @@ pub async fn construct_upload_file_router_data<'a>( Ok(router_data) } +pub async fn construct_payments_dynamic_tax_calculation_router_data<'a>( + state: &'a SessionState, + payment_intent: &'a storage::PaymentIntent, + payment_attempt: &storage::PaymentAttempt, + merchant_account: &domain::MerchantAccount, + key_store: &domain::MerchantKeyStore, + // customer: &'a Option, +) -> RouterResult { + let key_manager_state = &state.into(); + let profile_id = get_profile_id_from_business_details( + key_manager_state, + key_store, + payment_intent.business_country, + payment_intent.business_label.as_ref(), + merchant_account, + payment_intent.profile_id.as_ref(), + &*state.store, + false, + ) + .await + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("profile_id is not set in payment_intent")?; + + let merchant_connector_account = helpers::get_merchant_connector_account( + state, + merchant_account.get_id(), + None, + key_store, + &profile_id, + &payment_attempt.connector.as_ref().unwrap(), + payment_attempt.merchant_connector_id.as_ref(), + ) + .await?; + + let test_mode = merchant_connector_account.is_test_mode_on(); + + let connector_auth_type: types::ConnectorAuthType = merchant_connector_account + .get_connector_account_details() + .parse_value("ConnectorAuthType") + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Failed while parsing value for ConnectorAuthType")?; + + let router_data = types::RouterData { + flow: PhantomData, + merchant_id: merchant_account.get_id().to_owned(), + customer_id: payment_intent.customer_id.to_owned(), + connector_customer: None, + connector: payment_attempt + .connector + .clone() + .clone() + .ok_or(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Missing connector")?, + payment_id: payment_attempt.payment_id.clone(), + attempt_id: payment_attempt.attempt_id.clone(), + status: payment_attempt.status, + payment_method: diesel_models::enums::PaymentMethod::default(), + connector_auth_type, + description: payment_intent.description.clone(), + return_url: payment_intent.return_url.clone(), + address: PaymentAddress::default(), + auth_type: payment_attempt.authentication_type.unwrap_or_default(), + connector_meta_data: None, + connector_wallets_details: None, + amount_captured: payment_intent + .amount_captured + .map(|amt| amt.get_amount_as_i64()), + access_token: None, + session_token: None, + reference_id: None, + payment_method_token: None, + recurring_mandate_payment_data: None, + preprocessing_id: None, + payment_method_balance: None, + connector_api_version: None, + request: types::PaymentsTaxCalculationData { + amount: payment_intent.amount.clone().get_amount_as_i64(), + shipping_cost: payment_intent + .shipping_cost + .clone() + .ok_or(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Missing shipping_cost")?, + shipping: payment_intent.shipping_details.clone(), + order_details: payment_intent.order_details.clone(), + }, + response: Err(ErrorResponse::default()), + connector_request_reference_id: get_connector_request_reference_id( + &state.conf, + merchant_account.get_id(), + &payment_attempt, + ), + #[cfg(feature = "payouts")] + payout_method_data: None, + #[cfg(feature = "payouts")] + quote_id: None, + test_mode, + connector_http_status_code: None, + external_latency: None, + apple_pay_flow: None, + frm_metadata: None, + refund_id: None, + dispute_id: None, + connector_response: None, + payment_method_status: None, + minor_amount_captured: payment_intent.amount_captured, + integrity_check: Ok(()), + }; + Ok(router_data) +} + #[instrument(skip_all)] pub async fn construct_defend_dispute_router_data<'a>( state: &'a SessionState, diff --git a/crates/router/src/routes/app.rs b/crates/router/src/routes/app.rs index 3c891d8a537e..3dc701f4f9b7 100644 --- a/crates/router/src/routes/app.rs +++ b/crates/router/src/routes/app.rs @@ -614,6 +614,10 @@ impl Payments { .service( web::resource("/{payment_id}/extended_card_info").route(web::get().to(retrieve_extended_card_info)), ) + .service( + web::resource("{payment_id}/calculate_tax") + .route(web::post().to(payments_dynamic_tax_calculation)), + ); } route } diff --git a/crates/router/src/routes/lock_utils.rs b/crates/router/src/routes/lock_utils.rs index 9f073853d88c..86a9933edd9f 100644 --- a/crates/router/src/routes/lock_utils.rs +++ b/crates/router/src/routes/lock_utils.rs @@ -132,7 +132,8 @@ impl From for ApiIdentifier { | Flow::PaymentsAuthorize | Flow::GetExtendedCardInfo | Flow::PaymentsCompleteAuthorize - | Flow::PaymentsManualUpdate => Self::Payments, + | Flow::PaymentsManualUpdate + | Flow::PaymentsDynamicTaxCalculation => Self::Payments, Flow::PayoutsCreate | Flow::PayoutsRetrieve diff --git a/crates/router/src/routes/payments.rs b/crates/router/src/routes/payments.rs index d2f0cfeb7759..634a56a8e196 100644 --- a/crates/router/src/routes/payments.rs +++ b/crates/router/src/routes/payments.rs @@ -583,6 +583,73 @@ pub async fn payments_capture( )) .await } + +//Dynamic Tax Calculation + +#[utoipa::path( + post, + path = "/payments/{payment_id}/calculate_tax", + request_body=PaymentsDynamicTaxCalculationRequest, + responses( + (status = 200, description = "Tax Calculation is done", body = PaymentsDynamicTaxCalculationResponse), + (status = 400, description = "Missing mandatory fields") + ), + tag = "Payments", + operation_id = "Create Tax Calculation for a Payment", + security(("publishable_key" = [])) +)] +#[instrument(skip_all, fields(flow = ?Flow::PaymentsDynamicTaxCalculation, payment_id))] +pub async fn payments_dynamic_tax_calculation( + state: web::Data, + req: actix_web::HttpRequest, + json_payload: web::Json, +) -> impl Responder { + let flow = Flow::PaymentsDynamicTaxCalculation; + let payload = json_payload.into_inner(); + let header_payload = match HeaderPayload::foreign_try_from(req.headers()) { + Ok(headers) => headers, + Err(error) => { + logger::error!( + ?error, + "Failed to get headers in payments_connector_session" + ); + HeaderPayload::default() + } + }; + tracing::Span::current().record("payment_id", &payload.payment_id); + let locking_action = payload.get_locking_input(flow.clone()); + Box::pin(api::server_wrap( + flow, + state, + &req, + payload, + |state, auth, payload, req_state| { + payments::payments_core::< + api_types::CalculateTax, + payment_types::PaymentsDynamicTaxCalculationResponse, + _, + _, + _, + >( + state, + req_state, + auth.merchant_account, + auth.profile_id, + auth.key_store, + payments::PaymentTaxCalculation, + payload, + api::AuthFlow::Client, + payments::CallConnectorAction::Trigger, + None, + header_payload.clone(), + ) + }, + &auth::PublishableKeyAuth, + locking_action, + )) + .await +} + /// Payments - Session token /// /// To create the session object or to get session token for wallets @@ -1587,6 +1654,22 @@ impl GetLockingInput for payment_types::PaymentsSessionRequest { } } +impl GetLockingInput for payment_types::PaymentsDynamicTaxCalculationRequest { + fn get_locking_input(&self, flow: F) -> api_locking::LockAction + where + F: types::FlowMetric, + lock_utils::ApiIdentifier: From, + { + api_locking::LockAction::Hold { + input: api_locking::LockingInput { + unique_locking_key: self.payment_id.to_owned(), + api_identifier: lock_utils::ApiIdentifier::from(flow), + override_lock_retries: None, + }, + } + } +} + impl GetLockingInput for payments::PaymentsRedirectResponseData { fn get_locking_input(&self, flow: F) -> api_locking::LockAction where diff --git a/crates/router/src/services/api.rs b/crates/router/src/services/api.rs index 3049a49c601d..afba7e1f4b82 100644 --- a/crates/router/src/services/api.rs +++ b/crates/router/src/services/api.rs @@ -1240,6 +1240,11 @@ impl Authenticate for api_models::payments::PaymentsSessionRequest { Some(&self.client_secret) } } +impl Authenticate for api_models::payments::PaymentsDynamicTaxCalculationRequest { + fn get_client_secret(&self) -> Option<&String> { + Some(&self.client_secret) + } +} impl Authenticate for api_models::payments::PaymentsRetrieveRequest {} impl Authenticate for api_models::payments::PaymentsCancelRequest {} diff --git a/crates/router/src/types.rs b/crates/router/src/types.rs index 2bd6e27acab2..ff188cfe03c3 100644 --- a/crates/router/src/types.rs +++ b/crates/router/src/types.rs @@ -58,8 +58,8 @@ pub use hyperswitch_domain_models::{ PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, PaymentsIncrementalAuthorizationData, PaymentsPostProcessingData, PaymentsPreProcessingData, PaymentsRejectData, PaymentsSessionData, PaymentsSyncData, - RefundsData, ResponseId, RetrieveFileRequestData, SetupMandateRequestData, - SubmitEvidenceRequestData, SyncRequestType, UploadFileRequestData, + PaymentsTaxCalculationData, RefundsData, ResponseId, RetrieveFileRequestData, + SetupMandateRequestData, SubmitEvidenceRequestData, SyncRequestType, UploadFileRequestData, VerifyWebhookSourceRequestData, }, router_response_types::{ @@ -126,10 +126,15 @@ pub type PaymentsIncrementalAuthorizationRouterData = RouterData< PaymentsIncrementalAuthorizationData, PaymentsResponseData, >; -pub type PaymentsCancelRouterData = RouterData; -pub type PaymentsRejectRouterData = RouterData; -pub type PaymentsApproveRouterData = RouterData; -pub type PaymentsSessionRouterData = RouterData; +pub type PaymentsTaxCalculationRouterData = + RouterData; +pub type PaymentsCancelRouterData = RouterData; +pub type PaymentsRejectRouterData = + RouterData; +pub type PaymentsApproveRouterData = + RouterData; +pub type PaymentsSessionRouterData = + RouterData; pub type RefundsRouterData = RouterData; pub type RefundExecuteRouterData = RouterData; pub type RefundSyncRouterData = RouterData; @@ -362,6 +367,7 @@ impl Capturable for CompleteAuthorizeData { } } impl Capturable for SetupMandateRequestData {} +impl Capturable for PaymentsTaxCalculationData {} impl Capturable for PaymentsCancelData { fn get_captured_amount(&self, payment_data: &PaymentData) -> Option where diff --git a/crates/router/src/types/api.rs b/crates/router/src/types/api.rs index fa04ae2ec14a..ea84223ccad0 100644 --- a/crates/router/src/types/api.rs +++ b/crates/router/src/types/api.rs @@ -35,6 +35,7 @@ pub mod payments_v2; #[cfg(feature = "payouts")] pub mod payouts_v2; pub mod refunds_v2; +// pub mod calculate_tax; use std::{fmt::Debug, str::FromStr}; @@ -112,6 +113,7 @@ pub trait Connector: + ConnectorMandateRevokeV2 + ExternalAuthentication + ExternalAuthenticationV2 + + PaymentTaxCalculation { } @@ -569,3 +571,32 @@ mod test { assert!(result.is_err()); } } + +#[derive(Clone)] +pub struct TaxCalculateConnectorData { + pub connector: ConnectorEnum, + pub connector_name: enums::TaxCalculatorConnectors, +} + +impl TaxCalculateConnectorData { + pub fn get_connector_by_name(name: &str) -> CustomResult { + let connector_name = enums::TaxCalculatorConnectors::from_str(name) + .change_context(errors::ApiErrorResponse::IncorrectConnectorNameGiven) + .attach_printable_lazy(|| format!("unable to parse connector: {name}"))?; + let connector = Self::convert_connector(connector_name)?; + Ok(Self { + connector, + connector_name, + }) + } + + fn convert_connector( + connector_name: enums::TaxCalculatorConnectors, + ) -> CustomResult { + match connector_name { + enums::TaxCalculatorConnectors::TaxJar => { + Ok(ConnectorEnum::Old(Box::new(&connector::TaxJar))) + } + } + } +} diff --git a/crates/router/src/types/api/payments.rs b/crates/router/src/types/api/payments.rs index 04889e191b19..fa735dc43165 100644 --- a/crates/router/src/types/api/payments.rs +++ b/crates/router/src/types/api/payments.rs @@ -7,6 +7,7 @@ pub use api_models::payments::{ PaymentListResponseV2, PaymentMethodData, PaymentMethodDataRequest, PaymentMethodDataResponse, PaymentOp, PaymentRetrieveBody, PaymentRetrieveBodyWithCredentials, PaymentsApproveRequest, PaymentsCancelRequest, PaymentsCaptureRequest, PaymentsCompleteAuthorizeRequest, + PaymentsDynamicTaxCalculationRequest, PaymentsDynamicTaxCalculationResponse, PaymentsExternalAuthenticationRequest, PaymentsIncrementalAuthorizationRequest, PaymentsManualUpdateRequest, PaymentsRedirectRequest, PaymentsRedirectionResponse, PaymentsRejectRequest, PaymentsRequest, PaymentsResponse, PaymentsResponseForm, @@ -16,7 +17,7 @@ pub use api_models::payments::{ }; use error_stack::ResultExt; pub use hyperswitch_domain_models::router_flow_types::payments::{ - Approve, Authorize, AuthorizeSessionToken, Balance, Capture, CompleteAuthorize, + Approve, Authorize, AuthorizeSessionToken, Balance, CalculateTax, Capture, CompleteAuthorize, CreateConnectorCustomer, IncrementalAuthorization, InitPayment, PSync, PaymentMethodToken, PostProcessing, PreProcessing, Reject, Session, SetupMandate, Void, }; @@ -24,14 +25,14 @@ pub use hyperswitch_interfaces::api::payments::{ ConnectorCustomer, MandateSetup, Payment, PaymentApprove, PaymentAuthorize, PaymentAuthorizeSessionToken, PaymentCapture, PaymentIncrementalAuthorization, PaymentReject, PaymentSession, PaymentSync, PaymentToken, PaymentVoid, PaymentsCompleteAuthorize, - PaymentsPostProcessing, PaymentsPreProcessing, + PaymentsPostProcessing, PaymentsPreProcessing,PaymentTaxCalculation, }; pub use super::payments_v2::{ ConnectorCustomerV2, MandateSetupV2, PaymentApproveV2, PaymentAuthorizeSessionTokenV2, PaymentAuthorizeV2, PaymentCaptureV2, PaymentIncrementalAuthorizationV2, PaymentRejectV2, PaymentSessionV2, PaymentSyncV2, PaymentTokenV2, PaymentV2, PaymentVoidV2, - PaymentsCompleteAuthorizeV2, PaymentsPostProcessingV2, PaymentsPreProcessingV2, + PaymentsCompleteAuthorizeV2, PaymentsPostProcessingV2, PaymentsPreProcessingV2,PaymentTaxCalculationV2, }; use crate::core::errors; diff --git a/crates/router/src/types/api/payments_v2.rs b/crates/router/src/types/api/payments_v2.rs index 8d8e3498eff4..42e4d3b3f933 100644 --- a/crates/router/src/types/api/payments_v2.rs +++ b/crates/router/src/types/api/payments_v2.rs @@ -2,5 +2,5 @@ pub use hyperswitch_interfaces::api::payments_v2::{ ConnectorCustomerV2, MandateSetupV2, PaymentApproveV2, PaymentAuthorizeSessionTokenV2, PaymentAuthorizeV2, PaymentCaptureV2, PaymentIncrementalAuthorizationV2, PaymentRejectV2, PaymentSessionV2, PaymentSyncV2, PaymentTokenV2, PaymentV2, PaymentVoidV2, - PaymentsCompleteAuthorizeV2, PaymentsPostProcessingV2, PaymentsPreProcessingV2, + PaymentsCompleteAuthorizeV2, PaymentsPostProcessingV2, PaymentsPreProcessingV2,PaymentTaxCalculationV2, }; diff --git a/crates/router/src/utils/user/sample_data.rs b/crates/router/src/utils/user/sample_data.rs index ac9272c86d79..d8f2c8fd286b 100644 --- a/crates/router/src/utils/user/sample_data.rs +++ b/crates/router/src/utils/user/sample_data.rs @@ -252,6 +252,7 @@ pub async fn generate_sample_data( merchant_order_reference_id: Default::default(), shipping_details: None, is_payment_processor_token_flow: None, + shipping_cost: None, }; let payment_attempt = PaymentAttemptBatchNew { attempt_id: attempt_id.clone(), diff --git a/crates/router/tests/connectors/utils.rs b/crates/router/tests/connectors/utils.rs index 16e1d6a7c22c..ae3ec3f82719 100644 --- a/crates/router/tests/connectors/utils.rs +++ b/crates/router/tests/connectors/utils.rs @@ -565,6 +565,7 @@ pub trait ConnectorActions: Connector { Ok(types::PaymentsResponseData::MultipleCaptureResponse { .. }) => None, Ok(types::PaymentsResponseData::IncrementalAuthorizationResponse { .. }) => None, Ok(types::PaymentsResponseData::PostProcessingResponse { .. }) => None, + Ok(types::PaymentsResponseData::TaxCalculationResponse { .. }) => None, Err(_) => None, } } @@ -1075,6 +1076,7 @@ pub fn get_connector_transaction_id( Ok(types::PaymentsResponseData::MultipleCaptureResponse { .. }) => None, Ok(types::PaymentsResponseData::IncrementalAuthorizationResponse { .. }) => None, Ok(types::PaymentsResponseData::PostProcessingResponse { .. }) => None, + Ok(types::PaymentsResponseData::TaxCalculationResponse { .. }) => None, Err(_) => None, } } diff --git a/crates/router_derive/src/macros/operation.rs b/crates/router_derive/src/macros/operation.rs index c1e8c4e5bbce..8d05714b5f2f 100644 --- a/crates/router_derive/src/macros/operation.rs +++ b/crates/router_derive/src/macros/operation.rs @@ -29,6 +29,8 @@ pub enum Derives { SessionData, IncrementalAuthorization, IncrementalAuthorizationData, + TaxCalculation, + TaxCalculationData, } impl Derives { @@ -103,6 +105,10 @@ impl Conversion { Derives::IncrementalAuthorizationData => { syn::Ident::new("PaymentsIncrementalAuthorizationData", Span::call_site()) } + Derives::TaxCalculation => { + syn::Ident::new("PaymentsDynamicTaxCalculationRequest", Span::call_site()) + } + Derives::TaxCalculationData => syn::Ident::new("PaymentsTaxCalculationData", Span::call_site()), } } @@ -423,6 +429,7 @@ pub fn operation_derive_inner(input: DeriveInput) -> syn::Result syn::Result Date: Tue, 13 Aug 2024 18:46:26 +0000 Subject: [PATCH 02/39] chore: run formatter --- .../src/default_implementations.rs | 18 +++++++------ .../src/default_implementations_v2.rs | 16 ++++++------ .../src/router_request_types.rs | 7 ++++- .../src/api/payments.rs | 12 +++------ .../src/api/payments_v2.rs | 6 ++--- crates/router/src/core/payments.rs | 4 +-- crates/router/src/core/payments/flows.rs | 1 - .../payments/flows/tax_calculation_flow.rs | 11 ++++---- .../payments/operations/tax_calculation.rs | 26 +++++++++---------- .../router/src/core/payments/transformers.rs | 7 +++-- crates/router/src/core/utils.rs | 2 +- crates/router/src/types/api/payments.rs | 8 +++--- crates/router/src/types/api/payments_v2.rs | 4 +-- crates/router_derive/src/macros/operation.rs | 4 ++- 14 files changed, 66 insertions(+), 60 deletions(-) diff --git a/crates/hyperswitch_connectors/src/default_implementations.rs b/crates/hyperswitch_connectors/src/default_implementations.rs index 00080d34d499..f79c5391cb61 100644 --- a/crates/hyperswitch_connectors/src/default_implementations.rs +++ b/crates/hyperswitch_connectors/src/default_implementations.rs @@ -28,17 +28,19 @@ use hyperswitch_domain_models::{ files::{Retrieve, Upload}, mandate_revoke::MandateRevoke, payments::{ - Approve, AuthorizeSessionToken, CalculateTax, CompleteAuthorize, CreateConnectorCustomer, - IncrementalAuthorization, PostProcessing, PreProcessing, Reject, + Approve, AuthorizeSessionToken, CalculateTax, CompleteAuthorize, + CreateConnectorCustomer, IncrementalAuthorization, PostProcessing, PreProcessing, + Reject, }, webhooks::VerifyWebhookSource, }, router_request_types::{ - AcceptDisputeRequestData, AuthorizeSessionTokenData,PaymentsTaxCalculationData, CompleteAuthorizeData, + AcceptDisputeRequestData, AuthorizeSessionTokenData, CompleteAuthorizeData, ConnectorCustomerData, DefendDisputeRequestData, MandateRevokeRequestData, PaymentsApproveData, PaymentsIncrementalAuthorizationData, PaymentsPostProcessingData, - PaymentsPreProcessingData, PaymentsRejectData, RetrieveFileRequestData, - SubmitEvidenceRequestData, UploadFileRequestData, VerifyWebhookSourceRequestData, + PaymentsPreProcessingData, PaymentsRejectData, PaymentsTaxCalculationData, + RetrieveFileRequestData, SubmitEvidenceRequestData, UploadFileRequestData, + VerifyWebhookSourceRequestData, }, router_response_types::{ AcceptDisputeResponse, DefendDisputeResponse, MandateRevokeResponseData, @@ -62,9 +64,9 @@ use hyperswitch_interfaces::{ disputes::{AcceptDispute, DefendDispute, Dispute, SubmitEvidence}, files::{FileUpload, RetrieveFile, UploadFile}, payments::{ - ConnectorCustomer, PaymentApprove, PaymentAuthorizeSessionToken,PaymentTaxCalculation, - PaymentIncrementalAuthorization, PaymentReject, PaymentsCompleteAuthorize, - PaymentsPostProcessing, PaymentsPreProcessing, + ConnectorCustomer, PaymentApprove, PaymentAuthorizeSessionToken, + PaymentIncrementalAuthorization, PaymentReject, PaymentTaxCalculation, + PaymentsCompleteAuthorize, PaymentsPostProcessing, PaymentsPreProcessing, }, ConnectorIntegration, ConnectorMandateRevoke, ConnectorRedirectResponse, }, diff --git a/crates/hyperswitch_connectors/src/default_implementations_v2.rs b/crates/hyperswitch_connectors/src/default_implementations_v2.rs index c438f050cf7f..9aaf83e71d81 100644 --- a/crates/hyperswitch_connectors/src/default_implementations_v2.rs +++ b/crates/hyperswitch_connectors/src/default_implementations_v2.rs @@ -12,23 +12,23 @@ use hyperswitch_domain_models::{ files::{Retrieve, Upload}, mandate_revoke::MandateRevoke, payments::{ - Approve, Authorize, AuthorizeSessionToken, Capture, CompleteAuthorize, + Approve, Authorize, AuthorizeSessionToken, CalculateTax, Capture, CompleteAuthorize, CreateConnectorCustomer, IncrementalAuthorization, PSync, PaymentMethodToken, - PostProcessing, PreProcessing, Reject, Session, SetupMandate, Void,CalculateTax, + PostProcessing, PreProcessing, Reject, Session, SetupMandate, Void, }, refunds::{Execute, RSync}, webhooks::VerifyWebhookSource, AccessTokenAuth, }, router_request_types::{ - AcceptDisputeRequestData, AccessTokenRequestData, AuthorizeSessionTokenData,PaymentsTaxCalculationData, + AcceptDisputeRequestData, AccessTokenRequestData, AuthorizeSessionTokenData, CompleteAuthorizeData, ConnectorCustomerData, DefendDisputeRequestData, MandateRevokeRequestData, PaymentMethodTokenizationData, PaymentsApproveData, PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, PaymentsIncrementalAuthorizationData, PaymentsPostProcessingData, PaymentsPreProcessingData, PaymentsRejectData, PaymentsSessionData, PaymentsSyncData, - RefundsData, RetrieveFileRequestData, SetupMandateRequestData, SubmitEvidenceRequestData, - UploadFileRequestData, VerifyWebhookSourceRequestData, + PaymentsTaxCalculationData, RefundsData, RetrieveFileRequestData, SetupMandateRequestData, + SubmitEvidenceRequestData, UploadFileRequestData, VerifyWebhookSourceRequestData, }, router_response_types::{ AcceptDisputeResponse, DefendDisputeResponse, MandateRevokeResponseData, @@ -73,9 +73,9 @@ use hyperswitch_interfaces::{ payments_v2::{ ConnectorCustomerV2, MandateSetupV2, PaymentApproveV2, PaymentAuthorizeSessionTokenV2, PaymentAuthorizeV2, PaymentCaptureV2, PaymentIncrementalAuthorizationV2, - PaymentRejectV2, PaymentSessionV2, PaymentSyncV2, PaymentTokenV2, PaymentV2, - PaymentVoidV2, PaymentsCompleteAuthorizeV2, PaymentsPostProcessingV2, PaymentTaxCalculationV2, - PaymentsPreProcessingV2, + PaymentRejectV2, PaymentSessionV2, PaymentSyncV2, PaymentTaxCalculationV2, + PaymentTokenV2, PaymentV2, PaymentVoidV2, PaymentsCompleteAuthorizeV2, + PaymentsPostProcessingV2, PaymentsPreProcessingV2, }, refunds_v2::{RefundExecuteV2, RefundSyncV2, RefundV2}, ConnectorAccessTokenV2, ConnectorMandateRevokeV2, ConnectorVerifyWebhookSourceV2, diff --git a/crates/hyperswitch_domain_models/src/router_request_types.rs b/crates/hyperswitch_domain_models/src/router_request_types.rs index bf39587325f0..945613b4d38a 100644 --- a/crates/hyperswitch_domain_models/src/router_request_types.rs +++ b/crates/hyperswitch_domain_models/src/router_request_types.rs @@ -2,7 +2,12 @@ pub mod authentication; pub mod fraud_check; use api_models::payments::RequestSurchargeDetails; use common_utils::{ - consts, crypto::Encryptable, errors, ext_traits::OptionExt, id_type, pii, types::{self as common_types, MinorUnit} + consts, + crypto::Encryptable, + errors, + ext_traits::OptionExt, + id_type, pii, + types::{self as common_types, MinorUnit}, }; use diesel_models::enums as storage_enums; use error_stack::ResultExt; diff --git a/crates/hyperswitch_interfaces/src/api/payments.rs b/crates/hyperswitch_interfaces/src/api/payments.rs index 9ce106624e86..96a01aace0b7 100644 --- a/crates/hyperswitch_interfaces/src/api/payments.rs +++ b/crates/hyperswitch_interfaces/src/api/payments.rs @@ -2,16 +2,16 @@ use hyperswitch_domain_models::{ router_flow_types::payments::{ - Approve, Authorize, AuthorizeSessionToken, Capture, CalculateTax, CompleteAuthorize, + Approve, Authorize, AuthorizeSessionToken, CalculateTax, Capture, CompleteAuthorize, CreateConnectorCustomer, IncrementalAuthorization, PSync, PaymentMethodToken, PostProcessing, PreProcessing, Reject, Session, SetupMandate, Void, }, router_request_types::{ AuthorizeSessionTokenData, CompleteAuthorizeData, ConnectorCustomerData, - PaymentMethodTokenizationData, PaymentsApproveData, PaymentsAuthorizeData, PaymentsTaxCalculationData, + PaymentMethodTokenizationData, PaymentsApproveData, PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, PaymentsIncrementalAuthorizationData, PaymentsPostProcessingData, PaymentsPreProcessingData, PaymentsRejectData, - PaymentsSessionData, PaymentsSyncData, SetupMandateRequestData, + PaymentsSessionData, PaymentsSyncData, PaymentsTaxCalculationData, SetupMandateRequestData, }, router_response_types::PaymentsResponseData, }; @@ -113,11 +113,7 @@ pub trait PaymentIncrementalAuthorization: /// trait PaymentTaxCalculation pub trait PaymentTaxCalculation: - api::ConnectorIntegration< - CalculateTax, - PaymentsTaxCalculationData, - PaymentsResponseData, -> + api::ConnectorIntegration { } diff --git a/crates/hyperswitch_interfaces/src/api/payments_v2.rs b/crates/hyperswitch_interfaces/src/api/payments_v2.rs index 7efc3ac6a92e..4eefa0c9ae25 100644 --- a/crates/hyperswitch_interfaces/src/api/payments_v2.rs +++ b/crates/hyperswitch_interfaces/src/api/payments_v2.rs @@ -3,16 +3,16 @@ use hyperswitch_domain_models::{ router_data_v2::PaymentFlowData, router_flow_types::payments::{ - Approve, Authorize, AuthorizeSessionToken, Capture, CompleteAuthorize, + Approve, Authorize, AuthorizeSessionToken, CalculateTax, Capture, CompleteAuthorize, CreateConnectorCustomer, IncrementalAuthorization, PSync, PaymentMethodToken, - PostProcessing, PreProcessing, Reject, Session, SetupMandate, Void,CalculateTax, + PostProcessing, PreProcessing, Reject, Session, SetupMandate, Void, }, router_request_types::{ AuthorizeSessionTokenData, CompleteAuthorizeData, ConnectorCustomerData, PaymentMethodTokenizationData, PaymentsApproveData, PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, PaymentsIncrementalAuthorizationData, PaymentsPostProcessingData, PaymentsPreProcessingData, PaymentsRejectData, - PaymentsSessionData, PaymentsSyncData, SetupMandateRequestData,PaymentsTaxCalculationData, + PaymentsSessionData, PaymentsSyncData, PaymentsTaxCalculationData, SetupMandateRequestData, }, router_response_types::PaymentsResponseData, }; diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs index c89bf9b39fba..a8632beb025b 100644 --- a/crates/router/src/core/payments.rs +++ b/crates/router/src/core/payments.rs @@ -29,7 +29,7 @@ pub use common_enums::enums::CallConnectorAction; use common_utils::{ ext_traits::{AsyncExt, StringExt}, id_type, pii, - types::{ MinorUnit, Surcharge}, + types::{MinorUnit, Surcharge}, }; use diesel_models::{ephemeral_key, fraud_check::FraudCheck}; use error_stack::{report, ResultExt}; @@ -261,7 +261,7 @@ where &key_store, ) .await?; - + let tax_response = operation .to_domain()? .payments_dynamic_tax_calculation( diff --git a/crates/router/src/core/payments/flows.rs b/crates/router/src/core/payments/flows.rs index 9eacb96b7dbf..3797ff5c3c66 100644 --- a/crates/router/src/core/payments/flows.rs +++ b/crates/router/src/core/payments/flows.rs @@ -3172,7 +3172,6 @@ default_imp_for_authorize_session_token!( connector::Zsl ); - macro_rules! default_imp_for_calculate_tax { ($($path:ident::$connector:ident),*) => { $( impl api::PaymentTaxCalculation for $path::$connector {} diff --git a/crates/router/src/core/payments/flows/tax_calculation_flow.rs b/crates/router/src/core/payments/flows/tax_calculation_flow.rs index d8b8e891ae7e..1a41fc5f20ab 100644 --- a/crates/router/src/core/payments/flows/tax_calculation_flow.rs +++ b/crates/router/src/core/payments/flows/tax_calculation_flow.rs @@ -71,7 +71,7 @@ impl Feature connector: &api::ConnectorData, call_connector_action: payments::CallConnectorAction, connector_request: Option, - _business_profile: &domain::BusinessProfile, + _business_profile: &domain::BusinessProfile, _header_payload: api_models::payments::HeaderPayload, ) -> RouterResult { let connector_integration: services::BoxedPaymentConnectorIntegrationInterface< @@ -113,10 +113,10 @@ impl Feature let request = match call_connector_action { payments::CallConnectorAction::Trigger => { let connector_integration: services::BoxedPaymentConnectorIntegrationInterface< - api::CalculateTax, - types::PaymentsTaxCalculationData, - types::PaymentsResponseData, - > = connector.connector.get_connector_integration(); + api::CalculateTax, + types::PaymentsTaxCalculationData, + types::PaymentsResponseData, + > = connector.connector.get_connector_integration(); connector_integration .build_request(self, &state.conf.connectors) @@ -128,4 +128,3 @@ impl Feature Ok((request, true)) } } - diff --git a/crates/router/src/core/payments/operations/tax_calculation.rs b/crates/router/src/core/payments/operations/tax_calculation.rs index ba95830eeeb3..9da7b598fd0c 100644 --- a/crates/router/src/core/payments/operations/tax_calculation.rs +++ b/crates/router/src/core/payments/operations/tax_calculation.rs @@ -1,12 +1,12 @@ use std::marker::PhantomData; + use api_models::enums::FrmSuggestion; use async_trait::async_trait; -use common_utils:: - types::keymanager::KeyManagerState -; +use common_utils::types::keymanager::KeyManagerState; use error_stack::ResultExt; use router_derive::PaymentOperation; use router_env::{instrument, tracing}; + // use crate::core::payments::Operation; use super::{BoxedOperation, Domain, GetTracker, Operation, UpdateTracker, ValidateRequest}; use crate::{ @@ -15,7 +15,7 @@ use crate::{ payments::{self, helpers, operations, PaymentData}, utils as core_utils, }, - routes::{app::ReqState, SessionState}, + routes::{app::ReqState, SessionState}, services, types::{ self, @@ -55,7 +55,7 @@ impl GetTracker, api::PaymentsDynamicTaxCalcu let db = &*state.store; let key_manager_state: &KeyManagerState = &state.into(); - let merchant_id = merchant_account.get_id(); + let merchant_id = merchant_account.get_id(); let storage_scheme = merchant_account.storage_scheme; let payment_intent = db @@ -207,7 +207,7 @@ impl Domain key_store: &domain::MerchantKeyStore, // storage_scheme: storage_enums::MerchantStorageScheme, merchant_account: &domain::MerchantAccount, - ) -> errors::CustomResult<(), errors::ApiErrorResponse> { + ) -> errors::CustomResult<(), errors::ApiErrorResponse> { let db = state.store.as_ref(); let key_manager_state: KeyManagerState = state.into(); // Remove these db calls @@ -227,7 +227,7 @@ impl Domain let mut payment_attempt = db .find_payment_attempt_by_payment_id_merchant_id_attempt_id( payment_intent.payment_id.as_str(), - merchant_account.get_id(), + merchant_account.get_id(), payment_intent.active_attempt.get_id().as_str(), merchant_account.storage_scheme, ) @@ -274,12 +274,11 @@ impl Domain status_code: err.status_code, reason: err.reason, })?; - - // Update payment data.payment_attempt with new amount which was returned by the connector + // Update payment data.payment_attempt with new amount which was returned by the connector //payment_data - Ok(()) + Ok(()) } #[instrument(skip_all)] @@ -323,7 +322,9 @@ impl Domain } #[async_trait] -impl UpdateTracker, api::PaymentsDynamicTaxCalculationRequest> for PaymentTaxCalculation { +impl UpdateTracker, api::PaymentsDynamicTaxCalculationRequest> + for PaymentTaxCalculation +{ #[instrument(skip_all)] async fn update_trackers<'b>( &'b self, @@ -363,7 +364,6 @@ impl UpdateTracker, api::PaymentsDynamicTaxCalculati payment_data.payment_intent = updated_payment_intent; Ok((Box::new(self), payment_data)) - } } @@ -385,7 +385,7 @@ impl ValidateRequest TryFrom> for types::PaymentsApproveD } } - impl TryFrom> for types::PaymentsTaxCalculationData { type Error = error_stack::Report; @@ -1619,7 +1618,11 @@ impl TryFrom> for types::PaymentsTaxCalcu let amount = MinorUnit::from(payment_data.amount); Ok(Self { amount: amount.get_amount_as_i64(), //need to change after we move to connector module - shipping_cost: payment_data.payment_intent.shipping_cost.ok_or(errors::ApiErrorResponse::InternalServerError).attach_printable("missing shipping_cost in payment_data.payment_intent")?, + shipping_cost: payment_data + .payment_intent + .shipping_cost + .ok_or(errors::ApiErrorResponse::InternalServerError) + .attach_printable("missing shipping_cost in payment_data.payment_intent")?, shipping: payment_data.payment_intent.shipping_details, order_details: payment_data.payment_intent.order_details, }) diff --git a/crates/router/src/core/utils.rs b/crates/router/src/core/utils.rs index 2d8492c253b9..be46987ba99a 100644 --- a/crates/router/src/core/utils.rs +++ b/crates/router/src/core/utils.rs @@ -868,7 +868,7 @@ pub async fn construct_payments_dynamic_tax_calculation_router_data<'a>( key_store: &domain::MerchantKeyStore, // customer: &'a Option, ) -> RouterResult { - let key_manager_state = &state.into(); + let key_manager_state = &state.into(); let profile_id = get_profile_id_from_business_details( key_manager_state, key_store, diff --git a/crates/router/src/types/api/payments.rs b/crates/router/src/types/api/payments.rs index 0ede1d62640b..0e82e7bb99a0 100644 --- a/crates/router/src/types/api/payments.rs +++ b/crates/router/src/types/api/payments.rs @@ -24,15 +24,15 @@ pub use hyperswitch_domain_models::router_flow_types::payments::{ pub use hyperswitch_interfaces::api::payments::{ ConnectorCustomer, MandateSetup, Payment, PaymentApprove, PaymentAuthorize, PaymentAuthorizeSessionToken, PaymentCapture, PaymentIncrementalAuthorization, PaymentReject, - PaymentSession, PaymentSync, PaymentToken, PaymentVoid, PaymentsCompleteAuthorize, - PaymentsPostProcessing, PaymentsPreProcessing,PaymentTaxCalculation, + PaymentSession, PaymentSync, PaymentTaxCalculation, PaymentToken, PaymentVoid, + PaymentsCompleteAuthorize, PaymentsPostProcessing, PaymentsPreProcessing, }; pub use super::payments_v2::{ ConnectorCustomerV2, MandateSetupV2, PaymentApproveV2, PaymentAuthorizeSessionTokenV2, PaymentAuthorizeV2, PaymentCaptureV2, PaymentIncrementalAuthorizationV2, PaymentRejectV2, - PaymentSessionV2, PaymentSyncV2, PaymentTokenV2, PaymentV2, PaymentVoidV2, - PaymentsCompleteAuthorizeV2, PaymentsPostProcessingV2, PaymentsPreProcessingV2,PaymentTaxCalculationV2, + PaymentSessionV2, PaymentSyncV2, PaymentTaxCalculationV2, PaymentTokenV2, PaymentV2, + PaymentVoidV2, PaymentsCompleteAuthorizeV2, PaymentsPostProcessingV2, PaymentsPreProcessingV2, }; use crate::core::errors; diff --git a/crates/router/src/types/api/payments_v2.rs b/crates/router/src/types/api/payments_v2.rs index 42e4d3b3f933..ec3f599df8a0 100644 --- a/crates/router/src/types/api/payments_v2.rs +++ b/crates/router/src/types/api/payments_v2.rs @@ -1,6 +1,6 @@ pub use hyperswitch_interfaces::api::payments_v2::{ ConnectorCustomerV2, MandateSetupV2, PaymentApproveV2, PaymentAuthorizeSessionTokenV2, PaymentAuthorizeV2, PaymentCaptureV2, PaymentIncrementalAuthorizationV2, PaymentRejectV2, - PaymentSessionV2, PaymentSyncV2, PaymentTokenV2, PaymentV2, PaymentVoidV2, - PaymentsCompleteAuthorizeV2, PaymentsPostProcessingV2, PaymentsPreProcessingV2,PaymentTaxCalculationV2, + PaymentSessionV2, PaymentSyncV2, PaymentTaxCalculationV2, PaymentTokenV2, PaymentV2, + PaymentVoidV2, PaymentsCompleteAuthorizeV2, PaymentsPostProcessingV2, PaymentsPreProcessingV2, }; diff --git a/crates/router_derive/src/macros/operation.rs b/crates/router_derive/src/macros/operation.rs index 8d05714b5f2f..ef8c70cf6af1 100644 --- a/crates/router_derive/src/macros/operation.rs +++ b/crates/router_derive/src/macros/operation.rs @@ -108,7 +108,9 @@ impl Conversion { Derives::TaxCalculation => { syn::Ident::new("PaymentsDynamicTaxCalculationRequest", Span::call_site()) } - Derives::TaxCalculationData => syn::Ident::new("PaymentsTaxCalculationData", Span::call_site()), + Derives::TaxCalculationData => { + syn::Ident::new("PaymentsTaxCalculationData", Span::call_site()) + } } } From 39f8e50beb998a618f9409a003e312ff99e35930 Mon Sep 17 00:00:00 2001 From: "hyperswitch-bot[bot]" <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Date: Tue, 13 Aug 2024 18:49:20 +0000 Subject: [PATCH 03/39] docs(openapi): re-generate OpenAPI specification --- api-reference-v2/openapi_spec.json | 24 +++++++++++++++++ api-reference/openapi_spec.json | 41 ++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/api-reference-v2/openapi_spec.json b/api-reference-v2/openapi_spec.json index 8974f940bac1..3afefa6bb1a6 100644 --- a/api-reference-v2/openapi_spec.json +++ b/api-reference-v2/openapi_spec.json @@ -10718,6 +10718,12 @@ "example": 6540, "nullable": true }, + "shipping_cost": { + "type": "integer", + "format": "int64", + "example": 6540, + "nullable": true + }, "payment_id": { "type": "string", "description": "Unique identifier for the payment. This ensures idempotency for multiple payments\nthat have been done by a single merchant. The value for this field can be specified in the request, it will be auto generated otherwise and returned in the API response.", @@ -11063,6 +11069,12 @@ "example": 6540, "nullable": true }, + "shipping_cost": { + "type": "integer", + "format": "int64", + "example": 6540, + "nullable": true + }, "payment_id": { "type": "string", "description": "Unique identifier for the payment. This ensures idempotency for multiple payments\nthat have been done by a single merchant. The value for this field can be specified in the request, it will be auto generated otherwise and returned in the API response.", @@ -12036,6 +12048,12 @@ "example": 6540, "nullable": true }, + "shipping_cost": { + "type": "integer", + "format": "int64", + "example": 6540, + "nullable": true + }, "payment_id": { "type": "string", "description": "Unique identifier for the payment. This ensures idempotency for multiple payments\nthat have been done by a single merchant. The value for this field can be specified in the request, it will be auto generated otherwise and returned in the API response.", @@ -13155,6 +13173,12 @@ "example": 6540, "nullable": true }, + "shipping_cost": { + "type": "integer", + "format": "int64", + "example": 6540, + "nullable": true + }, "payment_id": { "type": "string", "description": "Unique identifier for the payment. This ensures idempotency for multiple payments\nthat have been done by a single merchant. The value for this field can be specified in the request, it will be auto generated otherwise and returned in the API response.", diff --git a/api-reference/openapi_spec.json b/api-reference/openapi_spec.json index e16343595655..98cf37172e69 100644 --- a/api-reference/openapi_spec.json +++ b/api-reference/openapi_spec.json @@ -15540,6 +15540,12 @@ "example": 6540, "nullable": true }, + "shipping_cost": { + "type": "integer", + "format": "int64", + "example": 6540, + "nullable": true + }, "payment_id": { "type": "string", "description": "Unique identifier for the payment. This ensures idempotency for multiple payments\nthat have been done by a single merchant. The value for this field can be specified in the request, it will be auto generated otherwise and returned in the API response.", @@ -15885,6 +15891,12 @@ "example": 6540, "nullable": true }, + "shipping_cost": { + "type": "integer", + "format": "int64", + "example": 6540, + "nullable": true + }, "payment_id": { "type": "string", "description": "Unique identifier for the payment. This ensures idempotency for multiple payments\nthat have been done by a single merchant. The value for this field can be specified in the request, it will be auto generated otherwise and returned in the API response.", @@ -16739,6 +16751,23 @@ } } }, + "PaymentsDynamicTaxCalculationRequest": { + "type": "object", + "description": "Request for calling tax jar API", + "required": [ + "shipping", + "client_secret" + ], + "properties": { + "shipping": { + "$ref": "#/components/schemas/Address" + }, + "client_secret": { + "type": "string", + "description": "Client Secret" + } + } + }, "PaymentsExternalAuthenticationRequest": { "type": "object", "required": [ @@ -16858,6 +16887,12 @@ "example": 6540, "nullable": true }, + "shipping_cost": { + "type": "integer", + "format": "int64", + "example": 6540, + "nullable": true + }, "payment_id": { "type": "string", "description": "Unique identifier for the payment. This ensures idempotency for multiple payments\nthat have been done by a single merchant. The value for this field can be specified in the request, it will be auto generated otherwise and returned in the API response.", @@ -17977,6 +18012,12 @@ "example": 6540, "nullable": true }, + "shipping_cost": { + "type": "integer", + "format": "int64", + "example": 6540, + "nullable": true + }, "payment_id": { "type": "string", "description": "Unique identifier for the payment. This ensures idempotency for multiple payments\nthat have been done by a single merchant. The value for this field can be specified in the request, it will be auto generated otherwise and returned in the API response.", From 337b7ba01c0ac915216bf015869e02d204ba1268 Mon Sep 17 00:00:00 2001 From: swangi-kumari Date: Wed, 14 Aug 2024 00:50:13 +0530 Subject: [PATCH 04/39] refactor: merege main --- .../src/default_implementations.rs | 22 +++++++++------ .../src/default_implementations_v2.rs | 16 +++++------ .../src/router_request_types.rs | 7 ++++- .../src/api/payments.rs | 12 +++----- .../src/api/payments_v2.rs | 6 ++-- crates/router/src/core/payments.rs | 4 +-- crates/router/src/core/payments/flows.rs | 2 +- .../payments/flows/tax_calculation_flow.rs | 11 ++++---- .../payments/operations/tax_calculation.rs | 28 +++++++++---------- .../router/src/core/payments/transformers.rs | 7 +++-- crates/router/src/core/utils.rs | 2 +- crates/router/src/types.rs | 19 ++++++------- crates/router/src/types/api.rs | 2 +- crates/router/src/types/api/payments.rs | 8 +++--- crates/router/src/types/api/payments_v2.rs | 4 +-- crates/router_derive/src/macros/operation.rs | 4 ++- 16 files changed, 80 insertions(+), 74 deletions(-) diff --git a/crates/hyperswitch_connectors/src/default_implementations.rs b/crates/hyperswitch_connectors/src/default_implementations.rs index 00080d34d499..cf0219d485ff 100644 --- a/crates/hyperswitch_connectors/src/default_implementations.rs +++ b/crates/hyperswitch_connectors/src/default_implementations.rs @@ -28,17 +28,19 @@ use hyperswitch_domain_models::{ files::{Retrieve, Upload}, mandate_revoke::MandateRevoke, payments::{ - Approve, AuthorizeSessionToken, CalculateTax, CompleteAuthorize, CreateConnectorCustomer, - IncrementalAuthorization, PostProcessing, PreProcessing, Reject, + Approve, AuthorizeSessionToken, CalculateTax, CompleteAuthorize, + CreateConnectorCustomer, IncrementalAuthorization, PostProcessing, PreProcessing, + Reject, }, webhooks::VerifyWebhookSource, }, router_request_types::{ - AcceptDisputeRequestData, AuthorizeSessionTokenData,PaymentsTaxCalculationData, CompleteAuthorizeData, + AcceptDisputeRequestData, AuthorizeSessionTokenData, CompleteAuthorizeData, ConnectorCustomerData, DefendDisputeRequestData, MandateRevokeRequestData, PaymentsApproveData, PaymentsIncrementalAuthorizationData, PaymentsPostProcessingData, - PaymentsPreProcessingData, PaymentsRejectData, RetrieveFileRequestData, - SubmitEvidenceRequestData, UploadFileRequestData, VerifyWebhookSourceRequestData, + PaymentsPreProcessingData, PaymentsRejectData, PaymentsTaxCalculationData, + RetrieveFileRequestData, SubmitEvidenceRequestData, UploadFileRequestData, + VerifyWebhookSourceRequestData, }, router_response_types::{ AcceptDisputeResponse, DefendDisputeResponse, MandateRevokeResponseData, @@ -62,9 +64,9 @@ use hyperswitch_interfaces::{ disputes::{AcceptDispute, DefendDispute, Dispute, SubmitEvidence}, files::{FileUpload, RetrieveFile, UploadFile}, payments::{ - ConnectorCustomer, PaymentApprove, PaymentAuthorizeSessionToken,PaymentTaxCalculation, - PaymentIncrementalAuthorization, PaymentReject, PaymentsCompleteAuthorize, - PaymentsPostProcessing, PaymentsPreProcessing, + ConnectorCustomer, PaymentApprove, PaymentAuthorizeSessionToken, + PaymentIncrementalAuthorization, PaymentReject, PaymentTaxCalculation, + PaymentsCompleteAuthorize, PaymentsPostProcessing, PaymentsPreProcessing, }, ConnectorIntegration, ConnectorMandateRevoke, ConnectorRedirectResponse, }, @@ -113,8 +115,10 @@ default_imp_for_calculate_tax!( connectors::Bambora, connectors::Bitpay, connectors::Fiserv, + connectors::Fiservemea, connectors::Helcim, - connectors::Stax + connectors::Stax, + connectors::Taxjar ); use crate::connectors; diff --git a/crates/hyperswitch_connectors/src/default_implementations_v2.rs b/crates/hyperswitch_connectors/src/default_implementations_v2.rs index c438f050cf7f..9aaf83e71d81 100644 --- a/crates/hyperswitch_connectors/src/default_implementations_v2.rs +++ b/crates/hyperswitch_connectors/src/default_implementations_v2.rs @@ -12,23 +12,23 @@ use hyperswitch_domain_models::{ files::{Retrieve, Upload}, mandate_revoke::MandateRevoke, payments::{ - Approve, Authorize, AuthorizeSessionToken, Capture, CompleteAuthorize, + Approve, Authorize, AuthorizeSessionToken, CalculateTax, Capture, CompleteAuthorize, CreateConnectorCustomer, IncrementalAuthorization, PSync, PaymentMethodToken, - PostProcessing, PreProcessing, Reject, Session, SetupMandate, Void,CalculateTax, + PostProcessing, PreProcessing, Reject, Session, SetupMandate, Void, }, refunds::{Execute, RSync}, webhooks::VerifyWebhookSource, AccessTokenAuth, }, router_request_types::{ - AcceptDisputeRequestData, AccessTokenRequestData, AuthorizeSessionTokenData,PaymentsTaxCalculationData, + AcceptDisputeRequestData, AccessTokenRequestData, AuthorizeSessionTokenData, CompleteAuthorizeData, ConnectorCustomerData, DefendDisputeRequestData, MandateRevokeRequestData, PaymentMethodTokenizationData, PaymentsApproveData, PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, PaymentsIncrementalAuthorizationData, PaymentsPostProcessingData, PaymentsPreProcessingData, PaymentsRejectData, PaymentsSessionData, PaymentsSyncData, - RefundsData, RetrieveFileRequestData, SetupMandateRequestData, SubmitEvidenceRequestData, - UploadFileRequestData, VerifyWebhookSourceRequestData, + PaymentsTaxCalculationData, RefundsData, RetrieveFileRequestData, SetupMandateRequestData, + SubmitEvidenceRequestData, UploadFileRequestData, VerifyWebhookSourceRequestData, }, router_response_types::{ AcceptDisputeResponse, DefendDisputeResponse, MandateRevokeResponseData, @@ -73,9 +73,9 @@ use hyperswitch_interfaces::{ payments_v2::{ ConnectorCustomerV2, MandateSetupV2, PaymentApproveV2, PaymentAuthorizeSessionTokenV2, PaymentAuthorizeV2, PaymentCaptureV2, PaymentIncrementalAuthorizationV2, - PaymentRejectV2, PaymentSessionV2, PaymentSyncV2, PaymentTokenV2, PaymentV2, - PaymentVoidV2, PaymentsCompleteAuthorizeV2, PaymentsPostProcessingV2, PaymentTaxCalculationV2, - PaymentsPreProcessingV2, + PaymentRejectV2, PaymentSessionV2, PaymentSyncV2, PaymentTaxCalculationV2, + PaymentTokenV2, PaymentV2, PaymentVoidV2, PaymentsCompleteAuthorizeV2, + PaymentsPostProcessingV2, PaymentsPreProcessingV2, }, refunds_v2::{RefundExecuteV2, RefundSyncV2, RefundV2}, ConnectorAccessTokenV2, ConnectorMandateRevokeV2, ConnectorVerifyWebhookSourceV2, diff --git a/crates/hyperswitch_domain_models/src/router_request_types.rs b/crates/hyperswitch_domain_models/src/router_request_types.rs index bf39587325f0..945613b4d38a 100644 --- a/crates/hyperswitch_domain_models/src/router_request_types.rs +++ b/crates/hyperswitch_domain_models/src/router_request_types.rs @@ -2,7 +2,12 @@ pub mod authentication; pub mod fraud_check; use api_models::payments::RequestSurchargeDetails; use common_utils::{ - consts, crypto::Encryptable, errors, ext_traits::OptionExt, id_type, pii, types::{self as common_types, MinorUnit} + consts, + crypto::Encryptable, + errors, + ext_traits::OptionExt, + id_type, pii, + types::{self as common_types, MinorUnit}, }; use diesel_models::enums as storage_enums; use error_stack::ResultExt; diff --git a/crates/hyperswitch_interfaces/src/api/payments.rs b/crates/hyperswitch_interfaces/src/api/payments.rs index 9ce106624e86..96a01aace0b7 100644 --- a/crates/hyperswitch_interfaces/src/api/payments.rs +++ b/crates/hyperswitch_interfaces/src/api/payments.rs @@ -2,16 +2,16 @@ use hyperswitch_domain_models::{ router_flow_types::payments::{ - Approve, Authorize, AuthorizeSessionToken, Capture, CalculateTax, CompleteAuthorize, + Approve, Authorize, AuthorizeSessionToken, CalculateTax, Capture, CompleteAuthorize, CreateConnectorCustomer, IncrementalAuthorization, PSync, PaymentMethodToken, PostProcessing, PreProcessing, Reject, Session, SetupMandate, Void, }, router_request_types::{ AuthorizeSessionTokenData, CompleteAuthorizeData, ConnectorCustomerData, - PaymentMethodTokenizationData, PaymentsApproveData, PaymentsAuthorizeData, PaymentsTaxCalculationData, + PaymentMethodTokenizationData, PaymentsApproveData, PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, PaymentsIncrementalAuthorizationData, PaymentsPostProcessingData, PaymentsPreProcessingData, PaymentsRejectData, - PaymentsSessionData, PaymentsSyncData, SetupMandateRequestData, + PaymentsSessionData, PaymentsSyncData, PaymentsTaxCalculationData, SetupMandateRequestData, }, router_response_types::PaymentsResponseData, }; @@ -113,11 +113,7 @@ pub trait PaymentIncrementalAuthorization: /// trait PaymentTaxCalculation pub trait PaymentTaxCalculation: - api::ConnectorIntegration< - CalculateTax, - PaymentsTaxCalculationData, - PaymentsResponseData, -> + api::ConnectorIntegration { } diff --git a/crates/hyperswitch_interfaces/src/api/payments_v2.rs b/crates/hyperswitch_interfaces/src/api/payments_v2.rs index 7efc3ac6a92e..4eefa0c9ae25 100644 --- a/crates/hyperswitch_interfaces/src/api/payments_v2.rs +++ b/crates/hyperswitch_interfaces/src/api/payments_v2.rs @@ -3,16 +3,16 @@ use hyperswitch_domain_models::{ router_data_v2::PaymentFlowData, router_flow_types::payments::{ - Approve, Authorize, AuthorizeSessionToken, Capture, CompleteAuthorize, + Approve, Authorize, AuthorizeSessionToken, CalculateTax, Capture, CompleteAuthorize, CreateConnectorCustomer, IncrementalAuthorization, PSync, PaymentMethodToken, - PostProcessing, PreProcessing, Reject, Session, SetupMandate, Void,CalculateTax, + PostProcessing, PreProcessing, Reject, Session, SetupMandate, Void, }, router_request_types::{ AuthorizeSessionTokenData, CompleteAuthorizeData, ConnectorCustomerData, PaymentMethodTokenizationData, PaymentsApproveData, PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, PaymentsIncrementalAuthorizationData, PaymentsPostProcessingData, PaymentsPreProcessingData, PaymentsRejectData, - PaymentsSessionData, PaymentsSyncData, SetupMandateRequestData,PaymentsTaxCalculationData, + PaymentsSessionData, PaymentsSyncData, PaymentsTaxCalculationData, SetupMandateRequestData, }, router_response_types::PaymentsResponseData, }; diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs index c89bf9b39fba..a8632beb025b 100644 --- a/crates/router/src/core/payments.rs +++ b/crates/router/src/core/payments.rs @@ -29,7 +29,7 @@ pub use common_enums::enums::CallConnectorAction; use common_utils::{ ext_traits::{AsyncExt, StringExt}, id_type, pii, - types::{ MinorUnit, Surcharge}, + types::{MinorUnit, Surcharge}, }; use diesel_models::{ephemeral_key, fraud_check::FraudCheck}; use error_stack::{report, ResultExt}; @@ -261,7 +261,7 @@ where &key_store, ) .await?; - + let tax_response = operation .to_domain()? .payments_dynamic_tax_calculation( diff --git a/crates/router/src/core/payments/flows.rs b/crates/router/src/core/payments/flows.rs index 9eacb96b7dbf..7ffb88c39e7d 100644 --- a/crates/router/src/core/payments/flows.rs +++ b/crates/router/src/core/payments/flows.rs @@ -3172,7 +3172,6 @@ default_imp_for_authorize_session_token!( connector::Zsl ); - macro_rules! default_imp_for_calculate_tax { ($($path:ident::$connector:ident),*) => { $( impl api::PaymentTaxCalculation for $path::$connector {} @@ -3258,6 +3257,7 @@ default_imp_for_calculate_tax!( connector::Tsys, connector::Volt, connector::Wellsfargo, + connector::Wellsfargopayout, connector::Wise, connector::Worldline, connector::Worldpay, diff --git a/crates/router/src/core/payments/flows/tax_calculation_flow.rs b/crates/router/src/core/payments/flows/tax_calculation_flow.rs index d8b8e891ae7e..1a41fc5f20ab 100644 --- a/crates/router/src/core/payments/flows/tax_calculation_flow.rs +++ b/crates/router/src/core/payments/flows/tax_calculation_flow.rs @@ -71,7 +71,7 @@ impl Feature connector: &api::ConnectorData, call_connector_action: payments::CallConnectorAction, connector_request: Option, - _business_profile: &domain::BusinessProfile, + _business_profile: &domain::BusinessProfile, _header_payload: api_models::payments::HeaderPayload, ) -> RouterResult { let connector_integration: services::BoxedPaymentConnectorIntegrationInterface< @@ -113,10 +113,10 @@ impl Feature let request = match call_connector_action { payments::CallConnectorAction::Trigger => { let connector_integration: services::BoxedPaymentConnectorIntegrationInterface< - api::CalculateTax, - types::PaymentsTaxCalculationData, - types::PaymentsResponseData, - > = connector.connector.get_connector_integration(); + api::CalculateTax, + types::PaymentsTaxCalculationData, + types::PaymentsResponseData, + > = connector.connector.get_connector_integration(); connector_integration .build_request(self, &state.conf.connectors) @@ -128,4 +128,3 @@ impl Feature Ok((request, true)) } } - diff --git a/crates/router/src/core/payments/operations/tax_calculation.rs b/crates/router/src/core/payments/operations/tax_calculation.rs index ba95830eeeb3..58d141785850 100644 --- a/crates/router/src/core/payments/operations/tax_calculation.rs +++ b/crates/router/src/core/payments/operations/tax_calculation.rs @@ -1,12 +1,12 @@ use std::marker::PhantomData; + use api_models::enums::FrmSuggestion; use async_trait::async_trait; -use common_utils:: - types::keymanager::KeyManagerState -; +use common_utils::types::keymanager::KeyManagerState; use error_stack::ResultExt; use router_derive::PaymentOperation; use router_env::{instrument, tracing}; + // use crate::core::payments::Operation; use super::{BoxedOperation, Domain, GetTracker, Operation, UpdateTracker, ValidateRequest}; use crate::{ @@ -15,7 +15,7 @@ use crate::{ payments::{self, helpers, operations, PaymentData}, utils as core_utils, }, - routes::{app::ReqState, SessionState}, + routes::{app::ReqState, SessionState}, services, types::{ self, @@ -55,7 +55,7 @@ impl GetTracker, api::PaymentsDynamicTaxCalcu let db = &*state.store; let key_manager_state: &KeyManagerState = &state.into(); - let merchant_id = merchant_account.get_id(); + let merchant_id = merchant_account.get_id(); let storage_scheme = merchant_account.storage_scheme; let payment_intent = db @@ -207,7 +207,7 @@ impl Domain key_store: &domain::MerchantKeyStore, // storage_scheme: storage_enums::MerchantStorageScheme, merchant_account: &domain::MerchantAccount, - ) -> errors::CustomResult<(), errors::ApiErrorResponse> { + ) -> errors::CustomResult<(), errors::ApiErrorResponse> { let db = state.store.as_ref(); let key_manager_state: KeyManagerState = state.into(); // Remove these db calls @@ -227,7 +227,7 @@ impl Domain let mut payment_attempt = db .find_payment_attempt_by_payment_id_merchant_id_attempt_id( payment_intent.payment_id.as_str(), - merchant_account.get_id(), + merchant_account.get_id(), payment_intent.active_attempt.get_id().as_str(), merchant_account.storage_scheme, ) @@ -274,12 +274,11 @@ impl Domain status_code: err.status_code, reason: err.reason, })?; - - // Update payment data.payment_attempt with new amount which was returned by the connector + // Update payment data.payment_attempt with new amount which was returned by the connector //payment_data - Ok(()) + Ok(()) } #[instrument(skip_all)] @@ -293,7 +292,7 @@ impl Domain _business_profile: Option<&domain::BusinessProfile>, ) -> RouterResult<( BoxedOperation<'a, F, api::PaymentsDynamicTaxCalculationRequest>, - Option, + Option, Option, )> { Ok((Box::new(self), None, None)) @@ -323,7 +322,9 @@ impl Domain } #[async_trait] -impl UpdateTracker, api::PaymentsDynamicTaxCalculationRequest> for PaymentTaxCalculation { +impl UpdateTracker, api::PaymentsDynamicTaxCalculationRequest> + for PaymentTaxCalculation +{ #[instrument(skip_all)] async fn update_trackers<'b>( &'b self, @@ -363,7 +364,6 @@ impl UpdateTracker, api::PaymentsDynamicTaxCalculati payment_data.payment_intent = updated_payment_intent; Ok((Box::new(self), payment_data)) - } } @@ -385,7 +385,7 @@ impl ValidateRequest TryFrom> for types::PaymentsApproveD } } - impl TryFrom> for types::PaymentsTaxCalculationData { type Error = error_stack::Report; @@ -1619,7 +1618,11 @@ impl TryFrom> for types::PaymentsTaxCalcu let amount = MinorUnit::from(payment_data.amount); Ok(Self { amount: amount.get_amount_as_i64(), //need to change after we move to connector module - shipping_cost: payment_data.payment_intent.shipping_cost.ok_or(errors::ApiErrorResponse::InternalServerError).attach_printable("missing shipping_cost in payment_data.payment_intent")?, + shipping_cost: payment_data + .payment_intent + .shipping_cost + .ok_or(errors::ApiErrorResponse::InternalServerError) + .attach_printable("missing shipping_cost in payment_data.payment_intent")?, shipping: payment_data.payment_intent.shipping_details, order_details: payment_data.payment_intent.order_details, }) diff --git a/crates/router/src/core/utils.rs b/crates/router/src/core/utils.rs index 2d8492c253b9..be46987ba99a 100644 --- a/crates/router/src/core/utils.rs +++ b/crates/router/src/core/utils.rs @@ -868,7 +868,7 @@ pub async fn construct_payments_dynamic_tax_calculation_router_data<'a>( key_store: &domain::MerchantKeyStore, // customer: &'a Option, ) -> RouterResult { - let key_manager_state = &state.into(); + let key_manager_state = &state.into(); let profile_id = get_profile_id_from_business_details( key_manager_state, key_store, diff --git a/crates/router/src/types.rs b/crates/router/src/types.rs index ff188cfe03c3..c1d6a353d7bb 100644 --- a/crates/router/src/types.rs +++ b/crates/router/src/types.rs @@ -30,9 +30,9 @@ use hyperswitch_domain_models::router_flow_types::{ files::{Retrieve, Upload}, mandate_revoke::MandateRevoke, payments::{ - Approve, Authorize, AuthorizeSessionToken, Balance, Capture, CompleteAuthorize, - CreateConnectorCustomer, IncrementalAuthorization, InitPayment, PSync, PostProcessing, - PreProcessing, Reject, Session, SetupMandate, Void, + Approve, Authorize, AuthorizeSessionToken, Balance, CalculateTax, Capture, + CompleteAuthorize, CreateConnectorCustomer, IncrementalAuthorization, InitPayment, PSync, + PostProcessing, PreProcessing, Reject, Session, SetupMandate, Void, }, refunds::{Execute, RSync}, webhooks::VerifyWebhookSource, @@ -127,14 +127,11 @@ pub type PaymentsIncrementalAuthorizationRouterData = RouterData< PaymentsResponseData, >; pub type PaymentsTaxCalculationRouterData = - RouterData; -pub type PaymentsCancelRouterData = RouterData; -pub type PaymentsRejectRouterData = - RouterData; -pub type PaymentsApproveRouterData = - RouterData; -pub type PaymentsSessionRouterData = - RouterData; + RouterData; +pub type PaymentsCancelRouterData = RouterData; +pub type PaymentsRejectRouterData = RouterData; +pub type PaymentsApproveRouterData = RouterData; +pub type PaymentsSessionRouterData = RouterData; pub type RefundsRouterData = RouterData; pub type RefundExecuteRouterData = RouterData; pub type RefundSyncRouterData = RouterData; diff --git a/crates/router/src/types/api.rs b/crates/router/src/types/api.rs index f72a0125d4f7..0b90875f8e6d 100644 --- a/crates/router/src/types/api.rs +++ b/crates/router/src/types/api.rs @@ -602,7 +602,7 @@ impl TaxCalculateConnectorData { ) -> CustomResult { match connector_name { enums::TaxCalculatorConnectors::TaxJar => { - Ok(ConnectorEnum::Old(Box::new(&connector::TaxJar))) + Ok(ConnectorEnum::Old(Box::new(connector::Taxjar::new()))) } } } diff --git a/crates/router/src/types/api/payments.rs b/crates/router/src/types/api/payments.rs index 0ede1d62640b..0e82e7bb99a0 100644 --- a/crates/router/src/types/api/payments.rs +++ b/crates/router/src/types/api/payments.rs @@ -24,15 +24,15 @@ pub use hyperswitch_domain_models::router_flow_types::payments::{ pub use hyperswitch_interfaces::api::payments::{ ConnectorCustomer, MandateSetup, Payment, PaymentApprove, PaymentAuthorize, PaymentAuthorizeSessionToken, PaymentCapture, PaymentIncrementalAuthorization, PaymentReject, - PaymentSession, PaymentSync, PaymentToken, PaymentVoid, PaymentsCompleteAuthorize, - PaymentsPostProcessing, PaymentsPreProcessing,PaymentTaxCalculation, + PaymentSession, PaymentSync, PaymentTaxCalculation, PaymentToken, PaymentVoid, + PaymentsCompleteAuthorize, PaymentsPostProcessing, PaymentsPreProcessing, }; pub use super::payments_v2::{ ConnectorCustomerV2, MandateSetupV2, PaymentApproveV2, PaymentAuthorizeSessionTokenV2, PaymentAuthorizeV2, PaymentCaptureV2, PaymentIncrementalAuthorizationV2, PaymentRejectV2, - PaymentSessionV2, PaymentSyncV2, PaymentTokenV2, PaymentV2, PaymentVoidV2, - PaymentsCompleteAuthorizeV2, PaymentsPostProcessingV2, PaymentsPreProcessingV2,PaymentTaxCalculationV2, + PaymentSessionV2, PaymentSyncV2, PaymentTaxCalculationV2, PaymentTokenV2, PaymentV2, + PaymentVoidV2, PaymentsCompleteAuthorizeV2, PaymentsPostProcessingV2, PaymentsPreProcessingV2, }; use crate::core::errors; diff --git a/crates/router/src/types/api/payments_v2.rs b/crates/router/src/types/api/payments_v2.rs index 42e4d3b3f933..ec3f599df8a0 100644 --- a/crates/router/src/types/api/payments_v2.rs +++ b/crates/router/src/types/api/payments_v2.rs @@ -1,6 +1,6 @@ pub use hyperswitch_interfaces::api::payments_v2::{ ConnectorCustomerV2, MandateSetupV2, PaymentApproveV2, PaymentAuthorizeSessionTokenV2, PaymentAuthorizeV2, PaymentCaptureV2, PaymentIncrementalAuthorizationV2, PaymentRejectV2, - PaymentSessionV2, PaymentSyncV2, PaymentTokenV2, PaymentV2, PaymentVoidV2, - PaymentsCompleteAuthorizeV2, PaymentsPostProcessingV2, PaymentsPreProcessingV2,PaymentTaxCalculationV2, + PaymentSessionV2, PaymentSyncV2, PaymentTaxCalculationV2, PaymentTokenV2, PaymentV2, + PaymentVoidV2, PaymentsCompleteAuthorizeV2, PaymentsPostProcessingV2, PaymentsPreProcessingV2, }; diff --git a/crates/router_derive/src/macros/operation.rs b/crates/router_derive/src/macros/operation.rs index 8d05714b5f2f..ef8c70cf6af1 100644 --- a/crates/router_derive/src/macros/operation.rs +++ b/crates/router_derive/src/macros/operation.rs @@ -108,7 +108,9 @@ impl Conversion { Derives::TaxCalculation => { syn::Ident::new("PaymentsDynamicTaxCalculationRequest", Span::call_site()) } - Derives::TaxCalculationData => syn::Ident::new("PaymentsTaxCalculationData", Span::call_site()), + Derives::TaxCalculationData => { + syn::Ident::new("PaymentsTaxCalculationData", Span::call_site()) + } } } From 461c6aa170560a368436970da60c7333107a3f73 Mon Sep 17 00:00:00 2001 From: swangi-kumari Date: Wed, 14 Aug 2024 01:29:17 +0530 Subject: [PATCH 05/39] refactor: resolve clippy --- .../src/payments/payment_attempt.rs | 4 +- crates/router/src/core/payments.rs | 2 +- .../payments/flows/tax_calculation_flow.rs | 43 ++++++++++++------- .../payments/operations/payment_response.rs | 4 +- .../payments/operations/tax_calculation.rs | 40 +++++------------ crates/router/src/core/utils.rs | 5 +-- 6 files changed, 46 insertions(+), 52 deletions(-) diff --git a/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs b/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs index 5ed3db839018..db940341928c 100644 --- a/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs +++ b/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs @@ -476,8 +476,8 @@ pub enum PaymentAttemptUpdate { }, // SessionUpdate { // amount: MinorUnit, - // order_tax_amount: MinorUnit, - // payment_method_shipping_address_id: Option, + // // order_tax_amount: MinorUnit, + // // payment_method_shipping_address_id: Option, // }, } diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs index a8632beb025b..4e064afe5cd7 100644 --- a/crates/router/src/core/payments.rs +++ b/crates/router/src/core/payments.rs @@ -262,7 +262,7 @@ where ) .await?; - let tax_response = operation + operation .to_domain()? .payments_dynamic_tax_calculation( state, diff --git a/crates/router/src/core/payments/flows/tax_calculation_flow.rs b/crates/router/src/core/payments/flows/tax_calculation_flow.rs index 1a41fc5f20ab..d0b816227f38 100644 --- a/crates/router/src/core/payments/flows/tax_calculation_flow.rs +++ b/crates/router/src/core/payments/flows/tax_calculation_flow.rs @@ -29,6 +29,7 @@ impl merchant_connector_account: &helpers::MerchantConnectorAccountType, merchant_recipient_data: Option, ) -> RouterResult { + // create a new function to construct router data to send the updated amount Box::pin(transformers::construct_payment_router_data::< api::CalculateTax, types::PaymentsTaxCalculationData, @@ -74,23 +75,35 @@ impl Feature _business_profile: &domain::BusinessProfile, _header_payload: api_models::payments::HeaderPayload, ) -> RouterResult { - let connector_integration: services::BoxedPaymentConnectorIntegrationInterface< - api::CalculateTax, - types::PaymentsTaxCalculationData, - types::PaymentsResponseData, - > = connector.connector.get_connector_integration(); + /* Have a check here whether to call the connector or not + If check { + call connector + } else { + Ok(self) + } + */ - let resp = services::execute_connector_processing_step( - state, - connector_integration, - &self, - call_connector_action, - connector_request, - ) - .await - .to_payment_failed_response()?; + if connector.connector_name == types::Connector::Klarna { + let connector_integration: services::BoxedPaymentConnectorIntegrationInterface< + api::CalculateTax, + types::PaymentsTaxCalculationData, + types::PaymentsResponseData, + > = connector.connector.get_connector_integration(); + + let resp = services::execute_connector_processing_step( + state, + connector_integration, + &self, + call_connector_action, + connector_request, + ) + .await + .to_payment_failed_response()?; - Ok(resp) + Ok(resp) + } else { + Ok(self) + } } async fn add_access_token<'a>( diff --git a/crates/router/src/core/payments/operations/payment_response.rs b/crates/router/src/core/payments/operations/payment_response.rs index d850f29edc68..2975ab7fe87a 100644 --- a/crates/router/src/core/payments/operations/payment_response.rs +++ b/crates/router/src/core/payments/operations/payment_response.rs @@ -500,8 +500,8 @@ impl PostUpdateTracker, types::PaymentsTaxCalculatio where F: 'b + Send, { - let shipping_address = payment_data.address.get_shipping(); - let amount = payment_data.amount; + let _shipping_address = payment_data.address.get_shipping(); + let _amount = payment_data.amount; payment_data = Box::pin(payment_response_update_tracker( db, diff --git a/crates/router/src/core/payments/operations/tax_calculation.rs b/crates/router/src/core/payments/operations/tax_calculation.rs index 58d141785850..18d42e9aa23c 100644 --- a/crates/router/src/core/payments/operations/tax_calculation.rs +++ b/crates/router/src/core/payments/operations/tax_calculation.rs @@ -208,31 +208,12 @@ impl Domain // storage_scheme: storage_enums::MerchantStorageScheme, merchant_account: &domain::MerchantAccount, ) -> errors::CustomResult<(), errors::ApiErrorResponse> { - let db = state.store.as_ref(); - let key_manager_state: KeyManagerState = state.into(); - // Remove these db calls - let mut payment_intent = db - .find_payment_intent_by_payment_id_merchant_id( - &state.into(), - &payment_data.payment_intent.payment_id, - &payment_data.payment_intent.merchant_id, - key_store, - merchant_account.storage_scheme, - ) - .await - .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?; + // let db = state.store.as_ref(); + let payment_intent = payment_data.payment_intent.clone(); - let attempt_id = payment_intent.active_attempt.get_id().clone(); + // let attempt_id = payment_intent.active_attempt.get_id().clone(); - let mut payment_attempt = db - .find_payment_attempt_by_payment_id_merchant_id_attempt_id( - payment_intent.payment_id.as_str(), - merchant_account.get_id(), - payment_intent.active_attempt.get_id().as_str(), - merchant_account.storage_scheme, - ) - .await - .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?; + let payment_attempt = payment_data.payment_attempt.clone(); // Derive this connector from business profile let connector_data = api::TaxCalculateConnectorData::get_connector_by_name( @@ -240,11 +221,11 @@ impl Domain )?; let router_data = core_utils::construct_payments_dynamic_tax_calculation_router_data( - &state, + state, &payment_intent, &payment_attempt, - &merchant_account, - &key_store, + merchant_account, + key_store, // &customer, ) .await?; @@ -255,7 +236,7 @@ impl Domain > = connector_data.connector.get_connector_integration(); let response = services::execute_connector_processing_step( - &state, + state, connector_integration, &router_data, payments::CallConnectorAction::Trigger, @@ -264,7 +245,7 @@ impl Domain .await .change_context(errors::ApiErrorResponse::InternalServerError)?; - let tax_response = + let _tax_response = response .response .map_err(|err| errors::ApiErrorResponse::ExternalConnectorError { @@ -275,7 +256,8 @@ impl Domain reason: err.reason, })?; - // Update payment data.payment_attempt with new amount which was returned by the connector + // Update payment_data.tax_details with new amount which was returned by the connector + // When constructing the router data, add this to the net amount //payment_data Ok(()) diff --git a/crates/router/src/core/utils.rs b/crates/router/src/core/utils.rs index be46987ba99a..d6275985d0f0 100644 --- a/crates/router/src/core/utils.rs +++ b/crates/router/src/core/utils.rs @@ -889,7 +889,7 @@ pub async fn construct_payments_dynamic_tax_calculation_router_data<'a>( None, key_store, &profile_id, - &payment_attempt.connector.as_ref().unwrap(), + payment_attempt.connector.as_ref().unwrap(), payment_attempt.merchant_connector_id.as_ref(), ) .await?; @@ -939,7 +939,6 @@ pub async fn construct_payments_dynamic_tax_calculation_router_data<'a>( amount: payment_intent.amount.clone().get_amount_as_i64(), shipping_cost: payment_intent .shipping_cost - .clone() .ok_or(errors::ApiErrorResponse::InternalServerError) .attach_printable("Missing shipping_cost")?, shipping: payment_intent.shipping_details.clone(), @@ -949,7 +948,7 @@ pub async fn construct_payments_dynamic_tax_calculation_router_data<'a>( connector_request_reference_id: get_connector_request_reference_id( &state.conf, merchant_account.get_id(), - &payment_attempt, + payment_attempt, ), #[cfg(feature = "payouts")] payout_method_data: None, From 3cd1f0973d7571c8dc6478808d82e95099c26302 Mon Sep 17 00:00:00 2001 From: swangi-kumari Date: Thu, 22 Aug 2024 14:46:03 +0530 Subject: [PATCH 06/39] feat: update order_tax_amount in payment_data_payment_intent_tax_details --- crates/diesel_models/src/payment_intent.rs | 30 +++- crates/diesel_models/src/schema.rs | 3 +- .../hyperswitch_domain_models/src/payments.rs | 5 +- .../src/payments/payment_attempt.rs | 8 +- .../payments/flows/tax_calculation_flow.rs | 28 ++-- crates/router/src/core/payments/helpers.rs | 3 + .../payments/operations/payment_create.rs | 1 + .../payments/operations/tax_calculation.rs | 18 ++- .../router/src/core/payments/transformers.rs | 153 +++++++++++++++++- crates/router/src/utils/user/sample_data.rs | 1 + .../down.sql | 2 + .../up.sql | 2 + 12 files changed, 234 insertions(+), 20 deletions(-) create mode 100644 migrations/2024-08-21-085916_add_tax_details_in_payment_intent_to_store_tax_amount/down.sql create mode 100644 migrations/2024-08-21-085916_add_tax_details_in_payment_intent_to_store_tax_amount/up.sql diff --git a/crates/diesel_models/src/payment_intent.rs b/crates/diesel_models/src/payment_intent.rs index 4f7ef8715b40..f22a79bb5654 100644 --- a/crates/diesel_models/src/payment_intent.rs +++ b/crates/diesel_models/src/payment_intent.rs @@ -129,10 +129,37 @@ pub struct PaymentIntent { pub billing_details: Option, pub merchant_order_reference_id: Option, pub shipping_details: Option, - pub is_payment_processor_token_flow: Option, pub shipping_cost: Option, + pub is_payment_processor_token_flow: Option, + pub tax_details: Option, +} + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, diesel::AsExpression)] +#[diesel(sql_type = diesel::sql_types::Jsonb)] +pub struct TaxDetails { + pub default: DefaultTax, + pub pmt: Option } +common_utils::impl_to_sql_from_sql_json!(TaxDetails); + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct PmtTax { + pub order_tax_amount: i64, + pub shipping_details: String, +} +// common_utils::impl_to_sql_from_sql_json!(PmtTax); + + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct DefaultTax { + pub order_tax_amount: i64, + pub pmt: Option, + pub shipping_details: String, +} + +// common_utils::impl_to_sql_from_sql_json!(DefaultTax); + #[derive( Clone, Debug, PartialEq, Insertable, router_derive::DebugAsDisplay, Serialize, Deserialize, )] @@ -192,6 +219,7 @@ pub struct PaymentIntentNew { pub shipping_details: Option, pub is_payment_processor_token_flow: Option, pub shipping_cost: Option, + pub tax_details: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] diff --git a/crates/diesel_models/src/schema.rs b/crates/diesel_models/src/schema.rs index 44d3b818041f..8bb23aa07690 100644 --- a/crates/diesel_models/src/schema.rs +++ b/crates/diesel_models/src/schema.rs @@ -900,8 +900,9 @@ diesel::table! { #[max_length = 255] merchant_order_reference_id -> Nullable, shipping_details -> Nullable, - is_payment_processor_token_flow -> Nullable, shipping_cost -> Nullable, + is_payment_processor_token_flow -> Nullable, + tax_details -> Nullable, } } diff --git a/crates/hyperswitch_domain_models/src/payments.rs b/crates/hyperswitch_domain_models/src/payments.rs index f0dc8b72bdb0..746aebdcc5c4 100644 --- a/crates/hyperswitch_domain_models/src/payments.rs +++ b/crates/hyperswitch_domain_models/src/payments.rs @@ -2,6 +2,8 @@ use common_utils::{self, crypto::Encryptable, id_type, pii, types::MinorUnit}; use masking::Secret; use time::PrimitiveDateTime; +use diesel_models::payment_intent::TaxDetails; + pub mod payment_attempt; pub mod payment_intent; @@ -68,4 +70,5 @@ pub struct PaymentIntent { pub merchant_order_reference_id: Option, pub shipping_details: Option>>, pub is_payment_processor_token_flow: Option, -} + pub tax_details: Option, +} \ No newline at end of file diff --git a/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs b/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs index db940341928c..f9e1cb08ff59 100644 --- a/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs +++ b/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs @@ -7,7 +7,7 @@ use common_utils::{ types::{ keymanager::{self, KeyManagerState}, MinorUnit, - }, + } }; use error_stack::ResultExt; use masking::PeekInterface; @@ -748,6 +748,7 @@ impl behaviour::Conversion for PaymentIntent { shipping_details: self.shipping_details.map(Encryption::from), is_payment_processor_token_flow: self.is_payment_processor_token_flow, shipping_cost: self.shipping_cost, + tax_details: self.tax_details, }) } @@ -772,6 +773,7 @@ impl behaviour::Conversion for PaymentIntent { .await .and_then(|val| val.try_into_optionaloperation()) }; + Ok::>(Self { payment_id: storage_model.payment_id, merchant_id: storage_model.merchant_id, @@ -818,6 +820,7 @@ impl behaviour::Conversion for PaymentIntent { charges: storage_model.charges, frm_metadata: storage_model.frm_metadata, shipping_cost: storage_model.shipping_cost, + tax_details: storage_model.tax_details, customer_details: storage_model .customer_details .async_lift(inner_decrypt) @@ -891,6 +894,7 @@ impl behaviour::Conversion for PaymentIntent { shipping_details: self.shipping_details.map(Encryption::from), is_payment_processor_token_flow: self.is_payment_processor_token_flow, shipping_cost: self.shipping_cost, + tax_details: self.tax_details, }) } -} +} \ No newline at end of file diff --git a/crates/router/src/core/payments/flows/tax_calculation_flow.rs b/crates/router/src/core/payments/flows/tax_calculation_flow.rs index d0b816227f38..e17bb960643e 100644 --- a/crates/router/src/core/payments/flows/tax_calculation_flow.rs +++ b/crates/router/src/core/payments/flows/tax_calculation_flow.rs @@ -30,19 +30,21 @@ impl merchant_recipient_data: Option, ) -> RouterResult { // create a new function to construct router data to send the updated amount - Box::pin(transformers::construct_payment_router_data::< - api::CalculateTax, - types::PaymentsTaxCalculationData, - >( - state, - self.clone(), - connector_id, - merchant_account, - key_store, - customer, - merchant_connector_account, - merchant_recipient_data, - )) + Box::pin( + transformers::construct_router_date_to_update_calculated_tax::< + api::CalculateTax, + types::PaymentsTaxCalculationData, + >( + state, + self.clone(), + connector_id, + merchant_account, + key_store, + customer, + merchant_connector_account, + // merchant_recipient_data, + ), + ) .await } diff --git a/crates/router/src/core/payments/helpers.rs b/crates/router/src/core/payments/helpers.rs index c2931968b927..bfbcfca74eb5 100644 --- a/crates/router/src/core/payments/helpers.rs +++ b/crates/router/src/core/payments/helpers.rs @@ -3091,6 +3091,7 @@ mod tests { shipping_details: None, is_payment_processor_token_flow: None, shipping_cost: None, + tax_details: None, }; let req_cs = Some("1".to_string()); assert!(authenticate_client_secret(req_cs.as_ref(), &payment_intent).is_ok()); @@ -3157,6 +3158,7 @@ mod tests { shipping_details: None, is_payment_processor_token_flow: None, shipping_cost: None, + tax_details: None, }; let req_cs = Some("1".to_string()); assert!(authenticate_client_secret(req_cs.as_ref(), &payment_intent,).is_err()) @@ -3221,6 +3223,7 @@ mod tests { shipping_details: None, is_payment_processor_token_flow: None, shipping_cost: None, + tax_details: None, }; let req_cs = Some("1".to_string()); assert!(authenticate_client_secret(req_cs.as_ref(), &payment_intent).is_err()) diff --git a/crates/router/src/core/payments/operations/payment_create.rs b/crates/router/src/core/payments/operations/payment_create.rs index f021bc584d3c..641ac1ab85d8 100644 --- a/crates/router/src/core/payments/operations/payment_create.rs +++ b/crates/router/src/core/payments/operations/payment_create.rs @@ -1247,6 +1247,7 @@ impl PaymentCreate { shipping_details, is_payment_processor_token_flow, shipping_cost: request.shipping_cost, + tax_details: None, }) } diff --git a/crates/router/src/core/payments/operations/tax_calculation.rs b/crates/router/src/core/payments/operations/tax_calculation.rs index 18d42e9aa23c..1e4f330132c6 100644 --- a/crates/router/src/core/payments/operations/tax_calculation.rs +++ b/crates/router/src/core/payments/operations/tax_calculation.rs @@ -245,7 +245,7 @@ impl Domain .await .change_context(errors::ApiErrorResponse::InternalServerError)?; - let _tax_response = + let tax_response = response .response .map_err(|err| errors::ApiErrorResponse::ExternalConnectorError { @@ -260,6 +260,22 @@ impl Domain // When constructing the router data, add this to the net amount //payment_data + + match tax_response { + hyperswitch_domain_models::router_response_types::PaymentsResponseData::TaxCalculationResponse { order_tax_amount, .. } => { + // Update payment_data.payment_intent.tax_details.order_tax_amount with the order_tax_amount from the TaxCalculationResponse + + payment_data.payment_intent.tax_details.clone().map(| tax_details| { + tax_details.pmt.map(| mut pmt| { + pmt.order_tax_amount = order_tax_amount; + }); + }); + } + _ => { + Err(errors::ApiErrorResponse::InternalServerError)? + } + } + Ok(()) } diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs index 67157f64384a..51a797f366a4 100644 --- a/crates/router/src/core/payments/transformers.rs +++ b/crates/router/src/core/payments/transformers.rs @@ -35,6 +35,152 @@ use crate::{ utils::{OptionExt, ValueExt}, }; +pub async fn construct_router_date_to_update_calculated_tax<'a, F, T>( + state: &'a SessionState, + payment_data: PaymentData, + connector_id: &str, + merchant_account: &domain::MerchantAccount, + key_store: &domain::MerchantKeyStore, + customer: &'a Option, + merchant_connector_account: &helpers::MerchantConnectorAccountType, +) -> RouterResult> +where + T: TryFrom>, + types::RouterData: Feature, + F: Clone, + error_stack::Report: + From<>>::Error>, +{ + let (payment_method, router_data); + + fp_utils::when(merchant_connector_account.is_disabled(), || { + Err(errors::ApiErrorResponse::MerchantConnectorAccountDisabled) + })?; + + let test_mode = merchant_connector_account.is_test_mode_on(); + + let auth_type: types::ConnectorAuthType = merchant_connector_account + .get_connector_account_details() + .parse_value("ConnectorAuthType") + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Failed while parsing value for ConnectorAuthType")?; + + payment_method = payment_data + .payment_attempt + .payment_method + .or(payment_data.payment_attempt.payment_method) + .get_required_value("payment_method_type")?; + + let resource_id = match payment_data + .payment_attempt + .connector_transaction_id + .clone() + { + Some(id) => types::ResponseId::ConnectorTransactionId(id), + None => types::ResponseId::NoResponseId, + }; + + // [#44]: why should response be filled during request + let response = Ok(types::PaymentsResponseData::TransactionResponse { + resource_id, + redirection_data: None, + mandate_reference: None, + connector_metadata: None, + network_txn_id: None, + connector_response_reference_id: None, + incremental_authorization_allowed: None, + charge_id: None, + }); + let additional_data = PaymentAdditionalData { + router_base_url: state.base_url.clone(), + connector_name: connector_id.to_string(), + payment_data: payment_data.clone(), + state, + customer_data: customer, + }; + let customer_id = customer + .to_owned() + .map(|customer| customer.get_customer_id()); + + let unified_address = + if let Some(payment_method_info) = payment_data.payment_method_info.clone() { + let payment_method_billing = + crate::core::payment_methods::cards::decrypt_generic_data::
( + state, + payment_method_info.payment_method_billing_address, + key_store, + ) + .await + .attach_printable("unable to decrypt payment method billing address details")?; + payment_data + .address + .clone() + .unify_with_payment_data_billing(payment_method_billing) + } else { + payment_data.address + }; + + router_data = types::RouterData { + flow: PhantomData, + merchant_id: merchant_account.get_id().clone(), + customer_id, + connector: connector_id.to_owned(), + payment_id: payment_data.payment_attempt.payment_id.clone(), + attempt_id: payment_data.payment_attempt.attempt_id.clone(), + status: payment_data.payment_attempt.status, + payment_method, + connector_auth_type: auth_type, + description: payment_data.payment_intent.description.clone(), + return_url: payment_data.payment_intent.return_url.clone(), + address: unified_address, + auth_type: payment_data + .payment_attempt + .authentication_type + .unwrap_or_default(), + connector_meta_data: None, + connector_wallets_details: merchant_connector_account.get_connector_wallets_details(), + request: T::try_from(additional_data)?, + response, + amount_captured: payment_data + .payment_intent + .amount_captured + .map(|amt| amt.get_amount_as_i64()), + minor_amount_captured: payment_data.payment_intent.amount_captured, + access_token: None, + session_token: None, + reference_id: None, + payment_method_status: payment_data.payment_method_info.map(|info| info.status), + payment_method_token: payment_data + .pm_token + .map(|token| types::PaymentMethodToken::Token(Secret::new(token))), + connector_customer: payment_data.connector_customer_id, + recurring_mandate_payment_data: payment_data.recurring_mandate_payment_data, + connector_request_reference_id: core_utils::get_connector_request_reference_id( + &state.conf, + merchant_account.get_id(), + &payment_data.payment_attempt, + ), + preprocessing_id: payment_data.payment_attempt.preprocessing_step_id, + #[cfg(feature = "payouts")] + payout_method_data: None, + #[cfg(feature = "payouts")] + quote_id: None, + test_mode, + payment_method_balance: None, + connector_api_version: None, + connector_http_status_code: None, + external_latency: None, + apple_pay_flow: None, + frm_metadata: None, + refund_id: None, + dispute_id: None, + connector_response: None, + integrity_check: Ok(()), + }; + + Ok(router_data) +} + #[instrument(skip_all)] #[allow(clippy::too_many_arguments)] pub async fn construct_payment_router_data<'a, F, T>( @@ -1635,9 +1781,14 @@ impl TryFrom> for types::PaymentsTaxCalcu fn try_from(additional_data: PaymentAdditionalData<'_, F>) -> Result { let payment_data = additional_data.payment_data; + let order_tax_amount = payment_data.payment_intent.tax_details.clone().and_then(| tax_details| + tax_details.pmt.map(| pmt| + pmt.order_tax_amount + ) + ).unwrap_or(0); let amount = MinorUnit::from(payment_data.amount); Ok(Self { - amount: amount.get_amount_as_i64(), //need to change after we move to connector module + amount: (amount.get_amount_as_i64()) + order_tax_amount, //need to change after we move to connector module shipping_cost: payment_data .payment_intent .shipping_cost diff --git a/crates/router/src/utils/user/sample_data.rs b/crates/router/src/utils/user/sample_data.rs index d8f2c8fd286b..5cb8df96b50d 100644 --- a/crates/router/src/utils/user/sample_data.rs +++ b/crates/router/src/utils/user/sample_data.rs @@ -253,6 +253,7 @@ pub async fn generate_sample_data( shipping_details: None, is_payment_processor_token_flow: None, shipping_cost: None, + tax_details: None, }; let payment_attempt = PaymentAttemptBatchNew { attempt_id: attempt_id.clone(), diff --git a/migrations/2024-08-21-085916_add_tax_details_in_payment_intent_to_store_tax_amount/down.sql b/migrations/2024-08-21-085916_add_tax_details_in_payment_intent_to_store_tax_amount/down.sql new file mode 100644 index 000000000000..235f027efd2f --- /dev/null +++ b/migrations/2024-08-21-085916_add_tax_details_in_payment_intent_to_store_tax_amount/down.sql @@ -0,0 +1,2 @@ +-- This file should undo anything in `up.sql` +ALTER TABLE payment_intent DROP COLUMN IF EXISTS tax_details; diff --git a/migrations/2024-08-21-085916_add_tax_details_in_payment_intent_to_store_tax_amount/up.sql b/migrations/2024-08-21-085916_add_tax_details_in_payment_intent_to_store_tax_amount/up.sql new file mode 100644 index 000000000000..547b6ff28609 --- /dev/null +++ b/migrations/2024-08-21-085916_add_tax_details_in_payment_intent_to_store_tax_amount/up.sql @@ -0,0 +1,2 @@ +-- Your SQL goes here +ALTER TABLE payment_intent ADD COLUMN IF NOT EXISTS tax_details JSONB; From 51f8c1196b7944e6a7a286f5363a3eb9f24f98ed Mon Sep 17 00:00:00 2001 From: swangi-kumari Date: Thu, 22 Aug 2024 14:49:09 +0530 Subject: [PATCH 07/39] refactor: formatting --- crates/api_models/src/events/payment.rs | 3 ++- crates/diesel_models/src/payment_intent.rs | 3 +-- .../hyperswitch_domain_models/src/payments.rs | 5 ++--- .../src/payments/payment_attempt.rs | 4 ++-- .../core/payments/operations/tax_calculation.rs | 1 - crates/router/src/core/payments/transformers.rs | 17 +++++++++-------- crates/router/src/types/api/payments.rs | 3 ++- 7 files changed, 18 insertions(+), 18 deletions(-) diff --git a/crates/api_models/src/events/payment.rs b/crates/api_models/src/events/payment.rs index 02a90d09aba6..59c2fe3047ab 100644 --- a/crates/api_models/src/events/payment.rs +++ b/crates/api_models/src/events/payment.rs @@ -20,7 +20,8 @@ use crate::{ PaymentListFilterConstraints, PaymentListFilters, PaymentListFiltersV2, PaymentListResponse, PaymentListResponseV2, PaymentsAggregateResponse, PaymentsApproveRequest, PaymentsCancelRequest, PaymentsCaptureRequest, - PaymentsCompleteAuthorizeRequest, PaymentsDynamicTaxCalculationRequest, PaymentsDynamicTaxCalculationResponse, PaymentsExternalAuthenticationRequest, + PaymentsCompleteAuthorizeRequest, PaymentsDynamicTaxCalculationRequest, + PaymentsDynamicTaxCalculationResponse, PaymentsExternalAuthenticationRequest, PaymentsExternalAuthenticationResponse, PaymentsIncrementalAuthorizationRequest, PaymentsManualUpdateRequest, PaymentsRejectRequest, PaymentsRequest, PaymentsResponse, PaymentsRetrieveRequest, PaymentsSessionResponse, PaymentsStartRequest, diff --git a/crates/diesel_models/src/payment_intent.rs b/crates/diesel_models/src/payment_intent.rs index f22a79bb5654..875d340b0aed 100644 --- a/crates/diesel_models/src/payment_intent.rs +++ b/crates/diesel_models/src/payment_intent.rs @@ -138,7 +138,7 @@ pub struct PaymentIntent { #[diesel(sql_type = diesel::sql_types::Jsonb)] pub struct TaxDetails { pub default: DefaultTax, - pub pmt: Option + pub pmt: Option, } common_utils::impl_to_sql_from_sql_json!(TaxDetails); @@ -150,7 +150,6 @@ pub struct PmtTax { } // common_utils::impl_to_sql_from_sql_json!(PmtTax); - #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct DefaultTax { pub order_tax_amount: i64, diff --git a/crates/hyperswitch_domain_models/src/payments.rs b/crates/hyperswitch_domain_models/src/payments.rs index 746aebdcc5c4..9ac8101a48c5 100644 --- a/crates/hyperswitch_domain_models/src/payments.rs +++ b/crates/hyperswitch_domain_models/src/payments.rs @@ -1,9 +1,8 @@ use common_utils::{self, crypto::Encryptable, id_type, pii, types::MinorUnit}; +use diesel_models::payment_intent::TaxDetails; use masking::Secret; use time::PrimitiveDateTime; -use diesel_models::payment_intent::TaxDetails; - pub mod payment_attempt; pub mod payment_intent; @@ -71,4 +70,4 @@ pub struct PaymentIntent { pub shipping_details: Option>>, pub is_payment_processor_token_flow: Option, pub tax_details: Option, -} \ No newline at end of file +} diff --git a/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs b/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs index f9e1cb08ff59..0aa23fba41e5 100644 --- a/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs +++ b/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs @@ -7,7 +7,7 @@ use common_utils::{ types::{ keymanager::{self, KeyManagerState}, MinorUnit, - } + }, }; use error_stack::ResultExt; use masking::PeekInterface; @@ -897,4 +897,4 @@ impl behaviour::Conversion for PaymentIntent { tax_details: self.tax_details, }) } -} \ No newline at end of file +} diff --git a/crates/router/src/core/payments/operations/tax_calculation.rs b/crates/router/src/core/payments/operations/tax_calculation.rs index 1e4f330132c6..95655775e782 100644 --- a/crates/router/src/core/payments/operations/tax_calculation.rs +++ b/crates/router/src/core/payments/operations/tax_calculation.rs @@ -260,7 +260,6 @@ impl Domain // When constructing the router data, add this to the net amount //payment_data - match tax_response { hyperswitch_domain_models::router_response_types::PaymentsResponseData::TaxCalculationResponse { order_tax_amount, .. } => { // Update payment_data.payment_intent.tax_details.order_tax_amount with the order_tax_amount from the TaxCalculationResponse diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs index 51a797f366a4..5f1a64fdf296 100644 --- a/crates/router/src/core/payments/transformers.rs +++ b/crates/router/src/core/payments/transformers.rs @@ -142,9 +142,9 @@ where request: T::try_from(additional_data)?, response, amount_captured: payment_data - .payment_intent - .amount_captured - .map(|amt| amt.get_amount_as_i64()), + .payment_intent + .amount_captured + .map(|amt| amt.get_amount_as_i64()), minor_amount_captured: payment_data.payment_intent.amount_captured, access_token: None, session_token: None, @@ -1781,11 +1781,12 @@ impl TryFrom> for types::PaymentsTaxCalcu fn try_from(additional_data: PaymentAdditionalData<'_, F>) -> Result { let payment_data = additional_data.payment_data; - let order_tax_amount = payment_data.payment_intent.tax_details.clone().and_then(| tax_details| - tax_details.pmt.map(| pmt| - pmt.order_tax_amount - ) - ).unwrap_or(0); + let order_tax_amount = payment_data + .payment_intent + .tax_details + .clone() + .and_then(|tax_details| tax_details.pmt.map(|pmt| pmt.order_tax_amount)) + .unwrap_or(0); let amount = MinorUnit::from(payment_data.amount); Ok(Self { amount: (amount.get_amount_as_i64()) + order_tax_amount, //need to change after we move to connector module diff --git a/crates/router/src/types/api/payments.rs b/crates/router/src/types/api/payments.rs index 8c7a0a7788b2..df66f2d5592c 100644 --- a/crates/router/src/types/api/payments.rs +++ b/crates/router/src/types/api/payments.rs @@ -7,7 +7,8 @@ pub use api_models::payments::{ PaymentListResponseV2, PaymentMethodData, PaymentMethodDataRequest, PaymentMethodDataResponse, PaymentOp, PaymentRetrieveBody, PaymentRetrieveBodyWithCredentials, PaymentsAggregateResponse, PaymentsApproveRequest, PaymentsCancelRequest, PaymentsCaptureRequest, - PaymentsCompleteAuthorizeRequest, PaymentsDynamicTaxCalculationRequest, PaymentsDynamicTaxCalculationResponse, PaymentsExternalAuthenticationRequest, + PaymentsCompleteAuthorizeRequest, PaymentsDynamicTaxCalculationRequest, + PaymentsDynamicTaxCalculationResponse, PaymentsExternalAuthenticationRequest, PaymentsIncrementalAuthorizationRequest, PaymentsManualUpdateRequest, PaymentsRedirectRequest, PaymentsRedirectionResponse, PaymentsRejectRequest, PaymentsRequest, PaymentsResponse, PaymentsResponseForm, PaymentsRetrieveRequest, PaymentsSessionRequest, PaymentsSessionResponse, From 72e9e13f633c3ab4dffb20c89d33ff5ad2746c97 Mon Sep 17 00:00:00 2001 From: swangi-kumari Date: Thu, 22 Aug 2024 15:15:13 +0530 Subject: [PATCH 08/39] refactor: resolve clippy errors --- crates/router/src/core/payments/flows/tax_calculation_flow.rs | 2 +- crates/router/src/core/payments/operations/payment_response.rs | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/router/src/core/payments/flows/tax_calculation_flow.rs b/crates/router/src/core/payments/flows/tax_calculation_flow.rs index e17bb960643e..2469f4a16868 100644 --- a/crates/router/src/core/payments/flows/tax_calculation_flow.rs +++ b/crates/router/src/core/payments/flows/tax_calculation_flow.rs @@ -27,7 +27,7 @@ impl key_store: &domain::MerchantKeyStore, customer: &Option, merchant_connector_account: &helpers::MerchantConnectorAccountType, - merchant_recipient_data: Option, + _merchant_recipient_data: Option, ) -> RouterResult { // create a new function to construct router data to send the updated amount Box::pin( diff --git a/crates/router/src/core/payments/operations/payment_response.rs b/crates/router/src/core/payments/operations/payment_response.rs index 490258f10646..6efbd06cf525 100644 --- a/crates/router/src/core/payments/operations/payment_response.rs +++ b/crates/router/src/core/payments/operations/payment_response.rs @@ -504,6 +504,7 @@ impl PostUpdateTracker, types::PaymentsTaxCalculatio >, key_store: &domain::MerchantKeyStore, storage_scheme: enums::MerchantStorageScheme, + locale: &Option, ) -> RouterResult> where F: 'b + Send, @@ -518,6 +519,7 @@ impl PostUpdateTracker, types::PaymentsTaxCalculatio router_data, key_store, storage_scheme, + locale, )) .await?; From 0428e30f4558aaa18b002f7537564d617e357f02 Mon Sep 17 00:00:00 2001 From: swangi-kumari Date: Fri, 23 Aug 2024 00:30:01 +0530 Subject: [PATCH 09/39] refactor: add session update api --- crates/common_enums/src/enums.rs | 20 ++++ .../src/default_implementations.rs | 41 ++++++-- .../src/default_implementations_v2.rs | 22 +++-- .../src/router_flow_types/payments.rs | 3 + .../src/router_request_types.rs | 6 ++ .../src/router_response_types.rs | 10 ++ .../src/api/payments.rs | 16 ++- .../src/api/payments_v2.rs | 16 ++- crates/router/src/core/payments.rs | 4 +- .../connector_integration_v2_impls.rs | 19 ++++ crates/router/src/core/payments/flows.rs | 97 ++++++++++++++++++- .../payments/flows/tax_calculation_flow.rs | 28 +++--- crates/router/src/core/payments/operations.rs | 2 +- .../payments/operations/payment_response.rs | 38 +++++++- .../payments/operations/tax_calculation.rs | 41 ++++---- .../router/src/core/payments/transformers.rs | 12 +-- crates/router/src/routes/payments.rs | 4 +- crates/router/src/types.rs | 18 ++-- crates/router/src/types/api/payments.rs | 11 ++- crates/router/src/types/api/payments_v2.rs | 5 +- crates/router/tests/connectors/utils.rs | 2 + crates/router_derive/src/macros/operation.rs | 7 ++ 22 files changed, 335 insertions(+), 87 deletions(-) diff --git a/crates/common_enums/src/enums.rs b/crates/common_enums/src/enums.rs index 8df5885e7b6b..5ed3c5dc0a79 100644 --- a/crates/common_enums/src/enums.rs +++ b/crates/common_enums/src/enums.rs @@ -398,6 +398,26 @@ pub enum AuthorizationStatus { Unresolved, } +#[derive( + Clone, + Debug, + Eq, + PartialEq, + serde::Deserialize, + serde::Serialize, + strum::Display, + strum::EnumString, + ToSchema, + Hash, +)] +#[router_derive::diesel_enum(storage_type = "text")] +#[serde(rename_all = "snake_case")] +#[strum(serialize_all = "snake_case")] +pub enum SessionUpdateStatus { + Success, + Failure, +} + #[derive( Clone, Debug, diff --git a/crates/hyperswitch_connectors/src/default_implementations.rs b/crates/hyperswitch_connectors/src/default_implementations.rs index cf0219d485ff..b3bd0145a06c 100644 --- a/crates/hyperswitch_connectors/src/default_implementations.rs +++ b/crates/hyperswitch_connectors/src/default_implementations.rs @@ -30,7 +30,7 @@ use hyperswitch_domain_models::{ payments::{ Approve, AuthorizeSessionToken, CalculateTax, CompleteAuthorize, CreateConnectorCustomer, IncrementalAuthorization, PostProcessing, PreProcessing, - Reject, + Reject, SessionUpdate, }, webhooks::VerifyWebhookSource, }, @@ -39,13 +39,13 @@ use hyperswitch_domain_models::{ ConnectorCustomerData, DefendDisputeRequestData, MandateRevokeRequestData, PaymentsApproveData, PaymentsIncrementalAuthorizationData, PaymentsPostProcessingData, PaymentsPreProcessingData, PaymentsRejectData, PaymentsTaxCalculationData, - RetrieveFileRequestData, SubmitEvidenceRequestData, UploadFileRequestData, - VerifyWebhookSourceRequestData, + RetrieveFileRequestData, SessionUpdateData, SubmitEvidenceRequestData, + UploadFileRequestData, VerifyWebhookSourceRequestData, }, router_response_types::{ AcceptDisputeResponse, DefendDisputeResponse, MandateRevokeResponseData, - PaymentsResponseData, RetrieveFileResponse, SubmitEvidenceResponse, UploadFileResponse, - VerifyWebhookSourceResponseData, + PaymentsResponseData, RetrieveFileResponse, SubmitEvidenceResponse, + TaxCalculationResponseData, UploadFileResponse, VerifyWebhookSourceResponseData, }, }; #[cfg(feature = "frm")] @@ -65,8 +65,9 @@ use hyperswitch_interfaces::{ files::{FileUpload, RetrieveFile, UploadFile}, payments::{ ConnectorCustomer, PaymentApprove, PaymentAuthorizeSessionToken, - PaymentIncrementalAuthorization, PaymentReject, PaymentTaxCalculation, - PaymentsCompleteAuthorize, PaymentsPostProcessing, PaymentsPreProcessing, + PaymentIncrementalAuthorization, PaymentReject, PaymentSessionUpdate, + PaymentTaxCalculation, PaymentsCompleteAuthorize, PaymentsPostProcessing, + PaymentsPreProcessing, }, ConnectorIntegration, ConnectorMandateRevoke, ConnectorRedirectResponse, }, @@ -104,7 +105,7 @@ macro_rules! default_imp_for_calculate_tax { ConnectorIntegration< CalculateTax, PaymentsTaxCalculationData, - PaymentsResponseData + TaxCalculationResponseData, > for $path::$connector {} )* @@ -121,6 +122,30 @@ default_imp_for_calculate_tax!( connectors::Taxjar ); +macro_rules! default_imp_for_session_update { + ($($path:ident::$connector:ident),*) => { + $( impl PaymentSessionUpdate for $path::$connector {} + impl + ConnectorIntegration< + SessionUpdate, + SessionUpdateData, + PaymentsResponseData, + > for $path::$connector + {} + )* + }; +} + +default_imp_for_session_update!( + connectors::Bambora, + connectors::Bitpay, + connectors::Fiserv, + connectors::Fiservemea, + connectors::Helcim, + connectors::Stax, + connectors::Taxjar +); + use crate::connectors; macro_rules! default_imp_for_complete_authorize { ($($path:ident::$connector:ident),*) => { diff --git a/crates/hyperswitch_connectors/src/default_implementations_v2.rs b/crates/hyperswitch_connectors/src/default_implementations_v2.rs index 9aaf83e71d81..346cbea275fd 100644 --- a/crates/hyperswitch_connectors/src/default_implementations_v2.rs +++ b/crates/hyperswitch_connectors/src/default_implementations_v2.rs @@ -14,7 +14,7 @@ use hyperswitch_domain_models::{ payments::{ Approve, Authorize, AuthorizeSessionToken, CalculateTax, Capture, CompleteAuthorize, CreateConnectorCustomer, IncrementalAuthorization, PSync, PaymentMethodToken, - PostProcessing, PreProcessing, Reject, Session, SetupMandate, Void, + PostProcessing, PreProcessing, Reject, Session, SessionUpdate, SetupMandate, Void, }, refunds::{Execute, RSync}, webhooks::VerifyWebhookSource, @@ -27,13 +27,14 @@ use hyperswitch_domain_models::{ PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, PaymentsIncrementalAuthorizationData, PaymentsPostProcessingData, PaymentsPreProcessingData, PaymentsRejectData, PaymentsSessionData, PaymentsSyncData, - PaymentsTaxCalculationData, RefundsData, RetrieveFileRequestData, SetupMandateRequestData, - SubmitEvidenceRequestData, UploadFileRequestData, VerifyWebhookSourceRequestData, + PaymentsTaxCalculationData, RefundsData, RetrieveFileRequestData, SessionUpdateData, + SetupMandateRequestData, SubmitEvidenceRequestData, UploadFileRequestData, + VerifyWebhookSourceRequestData, }, router_response_types::{ AcceptDisputeResponse, DefendDisputeResponse, MandateRevokeResponseData, PaymentsResponseData, RefundsResponseData, RetrieveFileResponse, SubmitEvidenceResponse, - UploadFileResponse, VerifyWebhookSourceResponseData, + TaxCalculationResponseData, UploadFileResponse, VerifyWebhookSourceResponseData, }, }; #[cfg(feature = "frm")] @@ -73,9 +74,9 @@ use hyperswitch_interfaces::{ payments_v2::{ ConnectorCustomerV2, MandateSetupV2, PaymentApproveV2, PaymentAuthorizeSessionTokenV2, PaymentAuthorizeV2, PaymentCaptureV2, PaymentIncrementalAuthorizationV2, - PaymentRejectV2, PaymentSessionV2, PaymentSyncV2, PaymentTaxCalculationV2, - PaymentTokenV2, PaymentV2, PaymentVoidV2, PaymentsCompleteAuthorizeV2, - PaymentsPostProcessingV2, PaymentsPreProcessingV2, + PaymentRejectV2, PaymentSessionUpdateV2, PaymentSessionV2, PaymentSyncV2, + PaymentTaxCalculationV2, PaymentTokenV2, PaymentV2, PaymentVoidV2, + PaymentsCompleteAuthorizeV2, PaymentsPostProcessingV2, PaymentsPreProcessingV2, }, refunds_v2::{RefundExecuteV2, RefundSyncV2, RefundV2}, ConnectorAccessTokenV2, ConnectorMandateRevokeV2, ConnectorVerifyWebhookSourceV2, @@ -105,6 +106,7 @@ macro_rules! default_imp_for_new_connector_integration_payment { impl PaymentsPreProcessingV2 for $path::$connector{} impl PaymentsPostProcessingV2 for $path::$connector{} impl PaymentTaxCalculationV2 for $path::$connector{} + impl PaymentSessionUpdateV2 for $path::$connector{} impl ConnectorIntegrationV2 for $path::$connector{} @@ -181,6 +183,12 @@ macro_rules! default_imp_for_new_connector_integration_payment { CalculateTax, PaymentFlowData, PaymentsTaxCalculationData, + TaxCalculationResponseData, + > for $path::$connector{} + impl ConnectorIntegrationV2< + SessionUpdate, + PaymentFlowData, + SessionUpdateData, PaymentsResponseData, > for $path::$connector{} )* diff --git a/crates/hyperswitch_domain_models/src/router_flow_types/payments.rs b/crates/hyperswitch_domain_models/src/router_flow_types/payments.rs index 8a6414c2bfd1..6c895134dd54 100644 --- a/crates/hyperswitch_domain_models/src/router_flow_types/payments.rs +++ b/crates/hyperswitch_domain_models/src/router_flow_types/payments.rs @@ -52,3 +52,6 @@ pub struct PostProcessing; #[derive(Debug, Clone)] pub struct CalculateTax; + +#[derive(Debug, Clone)] +pub struct SessionUpdate; diff --git a/crates/hyperswitch_domain_models/src/router_request_types.rs b/crates/hyperswitch_domain_models/src/router_request_types.rs index 945613b4d38a..01f7476e31d2 100644 --- a/crates/hyperswitch_domain_models/src/router_request_types.rs +++ b/crates/hyperswitch_domain_models/src/router_request_types.rs @@ -786,6 +786,12 @@ pub struct PaymentsTaxCalculationData { pub order_details: Option>>, } +#[derive(Debug, Clone, Default)] +pub struct SessionUpdateData { + pub order_tax_amount: i64, + pub net_amount: i64, +} + #[derive(Debug, Clone)] pub struct SetupMandateRequestData { pub currency: storage_enums::Currency, diff --git a/crates/hyperswitch_domain_models/src/router_response_types.rs b/crates/hyperswitch_domain_models/src/router_response_types.rs index 91345b994379..7a6a9241ccde 100644 --- a/crates/hyperswitch_domain_models/src/router_response_types.rs +++ b/crates/hyperswitch_domain_models/src/router_response_types.rs @@ -73,6 +73,16 @@ pub enum PaymentsResponseData { net_amount: i64, shipping_address: Option, }, + SessionUpdateResponse { + status: common_enums::AuthorizationStatus, + }, +} + +#[derive(Debug, Clone)] +pub struct TaxCalculationResponseData { + pub order_tax_amount: i64, + pub net_amount: i64, + pub shipping_address: Option, } #[derive(serde::Serialize, Debug, Clone)] diff --git a/crates/hyperswitch_interfaces/src/api/payments.rs b/crates/hyperswitch_interfaces/src/api/payments.rs index 96a01aace0b7..cbb329f2ac7b 100644 --- a/crates/hyperswitch_interfaces/src/api/payments.rs +++ b/crates/hyperswitch_interfaces/src/api/payments.rs @@ -4,16 +4,17 @@ use hyperswitch_domain_models::{ router_flow_types::payments::{ Approve, Authorize, AuthorizeSessionToken, CalculateTax, Capture, CompleteAuthorize, CreateConnectorCustomer, IncrementalAuthorization, PSync, PaymentMethodToken, - PostProcessing, PreProcessing, Reject, Session, SetupMandate, Void, + PostProcessing, PreProcessing, Reject, Session, SessionUpdate, SetupMandate, Void, }, router_request_types::{ AuthorizeSessionTokenData, CompleteAuthorizeData, ConnectorCustomerData, PaymentMethodTokenizationData, PaymentsApproveData, PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, PaymentsIncrementalAuthorizationData, PaymentsPostProcessingData, PaymentsPreProcessingData, PaymentsRejectData, - PaymentsSessionData, PaymentsSyncData, PaymentsTaxCalculationData, SetupMandateRequestData, + PaymentsSessionData, PaymentsSyncData, PaymentsTaxCalculationData, SessionUpdateData, + SetupMandateRequestData, }, - router_response_types::PaymentsResponseData, + router_response_types::{PaymentsResponseData, TaxCalculationResponseData}, }; use crate::api; @@ -38,6 +39,7 @@ pub trait Payment: + ConnectorCustomer + PaymentIncrementalAuthorization + PaymentTaxCalculation + + PaymentSessionUpdate { } @@ -113,7 +115,13 @@ pub trait PaymentIncrementalAuthorization: /// trait PaymentTaxCalculation pub trait PaymentTaxCalculation: - api::ConnectorIntegration + api::ConnectorIntegration +{ +} + +/// trait SessionUpdate +pub trait PaymentSessionUpdate: + api::ConnectorIntegration { } diff --git a/crates/hyperswitch_interfaces/src/api/payments_v2.rs b/crates/hyperswitch_interfaces/src/api/payments_v2.rs index 4eefa0c9ae25..dc27b786a28f 100644 --- a/crates/hyperswitch_interfaces/src/api/payments_v2.rs +++ b/crates/hyperswitch_interfaces/src/api/payments_v2.rs @@ -5,16 +5,17 @@ use hyperswitch_domain_models::{ router_flow_types::payments::{ Approve, Authorize, AuthorizeSessionToken, CalculateTax, Capture, CompleteAuthorize, CreateConnectorCustomer, IncrementalAuthorization, PSync, PaymentMethodToken, - PostProcessing, PreProcessing, Reject, Session, SetupMandate, Void, + PostProcessing, PreProcessing, Reject, Session, SessionUpdate, SetupMandate, Void, }, router_request_types::{ AuthorizeSessionTokenData, CompleteAuthorizeData, ConnectorCustomerData, PaymentMethodTokenizationData, PaymentsApproveData, PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, PaymentsIncrementalAuthorizationData, PaymentsPostProcessingData, PaymentsPreProcessingData, PaymentsRejectData, - PaymentsSessionData, PaymentsSyncData, PaymentsTaxCalculationData, SetupMandateRequestData, + PaymentsSessionData, PaymentsSyncData, PaymentsTaxCalculationData, SessionUpdateData, + SetupMandateRequestData, }, - router_response_types::PaymentsResponseData, + router_response_types::{PaymentsResponseData, TaxCalculationResponseData}, }; use crate::api::{ConnectorCommon, ConnectorIntegrationV2, ConnectorValidation}; @@ -95,11 +96,17 @@ pub trait PaymentTaxCalculationV2: CalculateTax, PaymentFlowData, PaymentsTaxCalculationData, - PaymentsResponseData, + TaxCalculationResponseData, > { } +///trait PaymentSessionUpdateV2 +pub trait PaymentSessionUpdateV2: + ConnectorIntegrationV2 +{ +} + /// trait PaymentsCompleteAuthorizeV2 pub trait PaymentsCompleteAuthorizeV2: ConnectorIntegrationV2< @@ -175,5 +182,6 @@ pub trait PaymentV2: + ConnectorCustomerV2 + PaymentIncrementalAuthorizationV2 + PaymentTaxCalculationV2 + + PaymentSessionUpdateV2 { } diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs index b994b583da35..0ce79bdbce52 100644 --- a/crates/router/src/core/payments.rs +++ b/crates/router/src/core/payments.rs @@ -54,8 +54,8 @@ use time; pub use self::operations::{ PaymentApprove, PaymentCancel, PaymentCapture, PaymentConfirm, PaymentCreate, - PaymentIncrementalAuthorization, PaymentReject, PaymentResponse, PaymentSession, PaymentStatus, - PaymentTaxCalculation, PaymentUpdate, + PaymentIncrementalAuthorization, PaymentReject, PaymentResponse, PaymentSession, + PaymentSessionUpdate, PaymentStatus, PaymentUpdate, }; use self::{ conditional_configs::perform_decision_management, diff --git a/crates/router/src/core/payments/connector_integration_v2_impls.rs b/crates/router/src/core/payments/connector_integration_v2_impls.rs index 1de1d91631b9..f34f5c207546 100644 --- a/crates/router/src/core/payments/connector_integration_v2_impls.rs +++ b/crates/router/src/core/payments/connector_integration_v2_impls.rs @@ -44,6 +44,8 @@ mod dummy_connector_default_impl { impl api::PaymentTaxCalculationV2 for connector::DummyConnector {} + impl api::PaymentSessionUpdateV2 for connector::DummyConnector {} + impl services::ConnectorIntegrationV2< api::Authorize, @@ -188,6 +190,15 @@ mod dummy_connector_default_impl { api::CalculateTax, types::PaymentFlowData, types::PaymentsTaxCalculationData, + types::TaxCalculationResponseData, + > for connector::DummyConnector + { + } + impl + services::ConnectorIntegrationV2< + api::SessionUpdate, + types::PaymentFlowData, + types::SessionUpdateData, types::PaymentsResponseData, > for connector::DummyConnector { @@ -569,6 +580,7 @@ macro_rules! default_imp_for_new_connector_integration_payment { impl api::PaymentsPreProcessingV2 for $path::$connector{} impl api::PaymentsPostProcessingV2 for $path::$connector{} impl api::PaymentTaxCalculationV2 for $path::$connector{} + impl api::PaymentSessionUpdateV2 for $path::$connector{} impl services::ConnectorIntegrationV2 for $path::$connector{} @@ -645,6 +657,13 @@ macro_rules! default_imp_for_new_connector_integration_payment { api::CalculateTax, types::PaymentFlowData, types::PaymentsTaxCalculationData, + types::TaxCalculationResponseData, + > for $path::$connector{} + + impl services::ConnectorIntegrationV2< + api::SessionUpdate, + types::PaymentFlowData, + types::SessionUpdateData, types::PaymentsResponseData, > for $path::$connector{} )* diff --git a/crates/router/src/core/payments/flows.rs b/crates/router/src/core/payments/flows.rs index 7ffb88c39e7d..3df1f1d85ab3 100644 --- a/crates/router/src/core/payments/flows.rs +++ b/crates/router/src/core/payments/flows.rs @@ -3179,7 +3179,7 @@ macro_rules! default_imp_for_calculate_tax { services::ConnectorIntegration< api::CalculateTax, types::PaymentsTaxCalculationData, - types::PaymentsResponseData + types::TaxCalculationResponseData > for $path::$connector {} )* @@ -3192,7 +3192,7 @@ impl services::ConnectorIntegration< api::CalculateTax, types::PaymentsTaxCalculationData, - types::PaymentsResponseData, + types::TaxCalculationResponseData, > for connector::DummyConnector { } @@ -3264,3 +3264,96 @@ default_imp_for_calculate_tax!( connector::Zen, connector::Zsl ); + +macro_rules! default_imp_for_session_update { + ($($path:ident::$connector:ident),*) => { + $( impl api::PaymentSessionUpdate for $path::$connector {} + impl + services::ConnectorIntegration< + api::SessionUpdate, + types::SessionUpdateData, + types::PaymentsResponseData + > for $path::$connector + {} + )* + }; +} +#[cfg(feature = "dummy_connector")] +impl api::PaymentSessionUpdate for connector::DummyConnector {} +#[cfg(feature = "dummy_connector")] +impl + services::ConnectorIntegration< + api::SessionUpdate, + types::SessionUpdateData, + types::PaymentsResponseData, + > for connector::DummyConnector +{ +} + +default_imp_for_session_update!( + connector::Aci, + connector::Adyen, + connector::Adyenplatform, + connector::Airwallex, + connector::Authorizedotnet, + connector::Bamboraapac, + connector::Bankofamerica, + connector::Billwerk, + connector::Bluesnap, + connector::Boku, + connector::Braintree, + connector::Cashtocode, + connector::Checkout, + connector::Cryptopay, + connector::Coinbase, + connector::Cybersource, + connector::Datatrans, + connector::Dlocal, + connector::Ebanx, + connector::Forte, + connector::Globalpay, + connector::Globepay, + connector::Gocardless, + connector::Gpayments, + connector::Iatapay, + connector::Itaubank, + connector::Klarna, + connector::Mifinity, + connector::Mollie, + connector::Multisafepay, + connector::Netcetera, + connector::Nexinets, + connector::Nuvei, + connector::Nmi, + connector::Noon, + connector::Opayo, + connector::Opennode, + connector::Paybox, + connector::Payeezy, + connector::Payme, + connector::Payone, + connector::Paypal, + connector::Payu, + connector::Placetopay, + connector::Plaid, + connector::Powertranz, + connector::Prophetpay, + connector::Rapyd, + connector::Razorpay, + connector::Riskified, + connector::Square, + connector::Signifyd, + connector::Stripe, + connector::Shift4, + connector::Threedsecureio, + connector::Trustpay, + connector::Tsys, + connector::Volt, + connector::Wellsfargo, + connector::Wellsfargopayout, + connector::Wise, + connector::Worldline, + connector::Worldpay, + connector::Zen, + connector::Zsl +); diff --git a/crates/router/src/core/payments/flows/tax_calculation_flow.rs b/crates/router/src/core/payments/flows/tax_calculation_flow.rs index 2469f4a16868..289263630525 100644 --- a/crates/router/src/core/payments/flows/tax_calculation_flow.rs +++ b/crates/router/src/core/payments/flows/tax_calculation_flow.rs @@ -14,10 +14,10 @@ use crate::{ #[async_trait] impl ConstructFlowSpecificData< - api::CalculateTax, - types::PaymentsTaxCalculationData, + api::SessionUpdate, + types::SessionUpdateData, types::PaymentsResponseData, - > for PaymentData + > for PaymentData { async fn construct_router_data<'a>( &self, @@ -28,12 +28,12 @@ impl customer: &Option, merchant_connector_account: &helpers::MerchantConnectorAccountType, _merchant_recipient_data: Option, - ) -> RouterResult { + ) -> RouterResult { // create a new function to construct router data to send the updated amount Box::pin( transformers::construct_router_date_to_update_calculated_tax::< - api::CalculateTax, - types::PaymentsTaxCalculationData, + api::SessionUpdate, + types::SessionUpdateData, >( state, self.clone(), @@ -61,12 +61,8 @@ impl } #[async_trait] -impl Feature - for types::RouterData< - api::CalculateTax, - types::PaymentsTaxCalculationData, - types::PaymentsResponseData, - > +impl Feature + for types::RouterData { async fn decide_flows<'a>( self, @@ -87,8 +83,8 @@ impl Feature if connector.connector_name == types::Connector::Klarna { let connector_integration: services::BoxedPaymentConnectorIntegrationInterface< - api::CalculateTax, - types::PaymentsTaxCalculationData, + api::SessionUpdate, + types::SessionUpdateData, types::PaymentsResponseData, > = connector.connector.get_connector_integration(); @@ -128,8 +124,8 @@ impl Feature let request = match call_connector_action { payments::CallConnectorAction::Trigger => { let connector_integration: services::BoxedPaymentConnectorIntegrationInterface< - api::CalculateTax, - types::PaymentsTaxCalculationData, + api::SessionUpdate, + types::SessionUpdateData, types::PaymentsResponseData, > = connector.connector.get_connector_integration(); diff --git a/crates/router/src/core/payments/operations.rs b/crates/router/src/core/payments/operations.rs index 0f87dfdb3654..2c520b839534 100644 --- a/crates/router/src/core/payments/operations.rs +++ b/crates/router/src/core/payments/operations.rs @@ -25,7 +25,7 @@ pub use self::{ payment_response::PaymentResponse, payment_session::PaymentSession, payment_start::PaymentStart, payment_status::PaymentStatus, payment_update::PaymentUpdate, payments_incremental_authorization::PaymentIncrementalAuthorization, - tax_calculation::PaymentTaxCalculation, + tax_calculation::PaymentSessionUpdate, }; use super::{helpers, CustomerDetails, PaymentData}; use crate::{ diff --git a/crates/router/src/core/payments/operations/payment_response.rs b/crates/router/src/core/payments/operations/payment_response.rs index 6efbd06cf525..f2ab80d81d7c 100644 --- a/crates/router/src/core/payments/operations/payment_response.rs +++ b/crates/router/src/core/payments/operations/payment_response.rs @@ -46,7 +46,7 @@ use crate::{ #[derive(Debug, Clone, Copy, router_derive::PaymentOperation)] #[operation( operations = "post_update_tracker", - flow = "sync_data, cancel_data, authorize_data, capture_data, complete_authorize_data, approve_data, reject_data, setup_mandate_data, session_data,incremental_authorization_data, tax_calculation_data" + flow = "sync_data, cancel_data, authorize_data, capture_data, complete_authorize_data, approve_data, reject_data, setup_mandate_data, session_data,incremental_authorization_data, tax_calculation_data, session_update_data" )] pub struct PaymentResponse; @@ -509,6 +509,41 @@ impl PostUpdateTracker, types::PaymentsTaxCalculatio where F: 'b + Send, { + // if connector_ call successfull -> paymnet_intent.amount update + let _shipping_address = payment_data.address.get_shipping(); + let _amount = payment_data.amount; + + payment_data = Box::pin(payment_response_update_tracker( + db, + payment_id, + payment_data, + router_data, + key_store, + storage_scheme, + locale, + )) + .await?; + + Ok(payment_data) + } +} + +#[async_trait] +impl PostUpdateTracker, types::SessionUpdateData> for PaymentResponse { + async fn update_tracker<'b>( + &'b self, + db: &'b SessionState, + payment_id: &api::PaymentIdType, + mut payment_data: PaymentData, + router_data: types::RouterData, + key_store: &domain::MerchantKeyStore, + storage_scheme: enums::MerchantStorageScheme, + locale: &Option, + ) -> RouterResult> + where + F: 'b + Send, + { + // if connector_ call successfull -> paymnet_intent.amount update let _shipping_address = payment_data.address.get_shipping(); let _amount = payment_data.amount; @@ -1215,6 +1250,7 @@ async fn payment_response_update_tracker( .. } => (None, None), types::PaymentsResponseData::TaxCalculationResponse { .. } => (None, None), + types::PaymentsResponseData::SessionUpdateResponse { .. } => (None, None), // types::PaymentsResponseData::TaxCalculationResponse { // order_tax_amount, // net_amount, diff --git a/crates/router/src/core/payments/operations/tax_calculation.rs b/crates/router/src/core/payments/operations/tax_calculation.rs index 95655775e782..7bb71a86a304 100644 --- a/crates/router/src/core/payments/operations/tax_calculation.rs +++ b/crates/router/src/core/payments/operations/tax_calculation.rs @@ -30,11 +30,11 @@ use crate::{ #[derive(Debug, Clone, Copy, PaymentOperation)] #[operation(operations = "all", flow = "tax_calculation")] -pub struct PaymentTaxCalculation; +pub struct PaymentSessionUpdate; #[async_trait] impl GetTracker, api::PaymentsDynamicTaxCalculationRequest> - for PaymentTaxCalculation + for PaymentSessionUpdate { #[instrument(skip_all)] async fn get_trackers<'a>( @@ -176,7 +176,7 @@ impl GetTracker, api::PaymentsDynamicTaxCalcu #[async_trait] impl Domain - for PaymentTaxCalculation + for PaymentSessionUpdate { #[instrument(skip_all)] async fn get_or_create_customer_details<'a>( @@ -232,7 +232,7 @@ impl Domain let connector_integration: services::BoxedPaymentConnectorIntegrationInterface< api::CalculateTax, types::PaymentsTaxCalculationData, - types::PaymentsResponseData, + types::TaxCalculationResponseData, > = connector_data.connector.get_connector_integration(); let response = services::execute_connector_processing_step( @@ -260,20 +260,24 @@ impl Domain // When constructing the router data, add this to the net amount //payment_data - match tax_response { - hyperswitch_domain_models::router_response_types::PaymentsResponseData::TaxCalculationResponse { order_tax_amount, .. } => { - // Update payment_data.payment_intent.tax_details.order_tax_amount with the order_tax_amount from the TaxCalculationResponse - - payment_data.payment_intent.tax_details.clone().map(| tax_details| { - tax_details.pmt.map(| mut pmt| { - pmt.order_tax_amount = order_tax_amount; + // match tax_response { + // hyperswitch_domain_models::router_response_types::PaymentsResponseData::TaxCalculationResponse { order_tax_amount, .. } => { + // // Update payment_data.payment_intent.tax_details.order_tax_amount with the order_tax_amount from the TaxCalculationResponse + + payment_data + .payment_intent + .tax_details + .clone() + .map(|tax_details| { + tax_details.pmt.map(|mut pmt| { + pmt.order_tax_amount = tax_response.order_tax_amount; }); }); - } - _ => { - Err(errors::ApiErrorResponse::InternalServerError)? - } - } + // } + // _ => { + // Err(errors::ApiErrorResponse::InternalServerError)? + // } + // } Ok(()) } @@ -320,7 +324,7 @@ impl Domain #[async_trait] impl UpdateTracker, api::PaymentsDynamicTaxCalculationRequest> - for PaymentTaxCalculation + for PaymentSessionUpdate { #[instrument(skip_all)] async fn update_trackers<'b>( @@ -341,6 +345,7 @@ impl UpdateTracker, api::PaymentsDynamicTaxCalculati where F: 'b + Send, { + //update shipping and tax_details let payment_intent_update = hyperswitch_domain_models::payments::payment_intent::PaymentIntentUpdate::CompleteAuthorizeUpdate { shipping_address_id: payment_data.payment_intent.shipping_address_id.clone() }; @@ -365,7 +370,7 @@ impl UpdateTracker, api::PaymentsDynamicTaxCalculati } impl ValidateRequest - for PaymentTaxCalculation + for PaymentSessionUpdate { #[instrument(skip_all)] fn validate_request<'a, 'b>( diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs index 5f1a64fdf296..e44f15f00b7b 100644 --- a/crates/router/src/core/payments/transformers.rs +++ b/crates/router/src/core/payments/transformers.rs @@ -1776,7 +1776,7 @@ impl TryFrom> for types::PaymentsApproveD } } -impl TryFrom> for types::PaymentsTaxCalculationData { +impl TryFrom> for types::SessionUpdateData { type Error = error_stack::Report; fn try_from(additional_data: PaymentAdditionalData<'_, F>) -> Result { @@ -1789,14 +1789,8 @@ impl TryFrom> for types::PaymentsTaxCalcu .unwrap_or(0); let amount = MinorUnit::from(payment_data.amount); Ok(Self { - amount: (amount.get_amount_as_i64()) + order_tax_amount, //need to change after we move to connector module - shipping_cost: payment_data - .payment_intent - .shipping_cost - .ok_or(errors::ApiErrorResponse::InternalServerError) - .attach_printable("missing shipping_cost in payment_data.payment_intent")?, - shipping: payment_data.payment_intent.shipping_details, - order_details: payment_data.payment_intent.order_details, + net_amount: (amount.get_amount_as_i64()) + order_tax_amount, //need to change after we move to connector module + order_tax_amount, }) } } diff --git a/crates/router/src/routes/payments.rs b/crates/router/src/routes/payments.rs index c07e2bd79cae..2bb76a9fd39d 100644 --- a/crates/router/src/routes/payments.rs +++ b/crates/router/src/routes/payments.rs @@ -631,7 +631,7 @@ pub async fn payments_dynamic_tax_calculation( payload, |state, auth, payload, req_state| { payments::payments_core::< - api_types::CalculateTax, + api_types::SessionUpdate, payment_types::PaymentsDynamicTaxCalculationResponse, _, _, @@ -642,7 +642,7 @@ pub async fn payments_dynamic_tax_calculation( auth.merchant_account, auth.profile_id, auth.key_store, - payments::PaymentTaxCalculation, + payments::PaymentSessionUpdate, payload, api::AuthFlow::Client, payments::CallConnectorAction::Trigger, diff --git a/crates/router/src/types.rs b/crates/router/src/types.rs index c1d6a353d7bb..2dab429b37c1 100644 --- a/crates/router/src/types.rs +++ b/crates/router/src/types.rs @@ -32,7 +32,7 @@ use hyperswitch_domain_models::router_flow_types::{ payments::{ Approve, Authorize, AuthorizeSessionToken, Balance, CalculateTax, Capture, CompleteAuthorize, CreateConnectorCustomer, IncrementalAuthorization, InitPayment, PSync, - PostProcessing, PreProcessing, Reject, Session, SetupMandate, Void, + PostProcessing, PreProcessing, Reject, Session, SessionUpdate, SetupMandate, Void, }, refunds::{Execute, RSync}, webhooks::VerifyWebhookSource, @@ -59,14 +59,15 @@ pub use hyperswitch_domain_models::{ PaymentsIncrementalAuthorizationData, PaymentsPostProcessingData, PaymentsPreProcessingData, PaymentsRejectData, PaymentsSessionData, PaymentsSyncData, PaymentsTaxCalculationData, RefundsData, ResponseId, RetrieveFileRequestData, - SetupMandateRequestData, SubmitEvidenceRequestData, SyncRequestType, UploadFileRequestData, - VerifyWebhookSourceRequestData, + SessionUpdateData, SetupMandateRequestData, SubmitEvidenceRequestData, SyncRequestType, + UploadFileRequestData, VerifyWebhookSourceRequestData, }, router_response_types::{ AcceptDisputeResponse, CaptureSyncResponse, DefendDisputeResponse, MandateReference, MandateRevokeResponseData, PaymentsResponseData, PreprocessingResponseId, - RefundsResponseData, RetrieveFileResponse, SubmitEvidenceResponse, UploadFileResponse, - VerifyWebhookSourceResponseData, VerifyWebhookStatus, + RefundsResponseData, RetrieveFileResponse, SubmitEvidenceResponse, + TaxCalculationResponseData, UploadFileResponse, VerifyWebhookSourceResponseData, + VerifyWebhookStatus, }, }; #[cfg(feature = "payouts")] @@ -127,7 +128,11 @@ pub type PaymentsIncrementalAuthorizationRouterData = RouterData< PaymentsResponseData, >; pub type PaymentsTaxCalculationRouterData = - RouterData; + RouterData; + +pub type SessionUpdateRouterData = + RouterData; + pub type PaymentsCancelRouterData = RouterData; pub type PaymentsRejectRouterData = RouterData; pub type PaymentsApproveRouterData = RouterData; @@ -365,6 +370,7 @@ impl Capturable for CompleteAuthorizeData { } impl Capturable for SetupMandateRequestData {} impl Capturable for PaymentsTaxCalculationData {} +impl Capturable for SessionUpdateData {} impl Capturable for PaymentsCancelData { fn get_captured_amount(&self, payment_data: &PaymentData) -> Option where diff --git a/crates/router/src/types/api/payments.rs b/crates/router/src/types/api/payments.rs index df66f2d5592c..101e09a82a1d 100644 --- a/crates/router/src/types/api/payments.rs +++ b/crates/router/src/types/api/payments.rs @@ -19,20 +19,21 @@ use error_stack::ResultExt; pub use hyperswitch_domain_models::router_flow_types::payments::{ Approve, Authorize, AuthorizeSessionToken, Balance, CalculateTax, Capture, CompleteAuthorize, CreateConnectorCustomer, IncrementalAuthorization, InitPayment, PSync, PaymentMethodToken, - PostProcessing, PreProcessing, Reject, Session, SetupMandate, Void, + PostProcessing, PreProcessing, Reject, Session, SessionUpdate, SetupMandate, Void, }; pub use hyperswitch_interfaces::api::payments::{ ConnectorCustomer, MandateSetup, Payment, PaymentApprove, PaymentAuthorize, PaymentAuthorizeSessionToken, PaymentCapture, PaymentIncrementalAuthorization, PaymentReject, - PaymentSession, PaymentSync, PaymentTaxCalculation, PaymentToken, PaymentVoid, - PaymentsCompleteAuthorize, PaymentsPostProcessing, PaymentsPreProcessing, + PaymentSession, PaymentSessionUpdate, PaymentSync, PaymentTaxCalculation, PaymentToken, + PaymentVoid, PaymentsCompleteAuthorize, PaymentsPostProcessing, PaymentsPreProcessing, }; pub use super::payments_v2::{ ConnectorCustomerV2, MandateSetupV2, PaymentApproveV2, PaymentAuthorizeSessionTokenV2, PaymentAuthorizeV2, PaymentCaptureV2, PaymentIncrementalAuthorizationV2, PaymentRejectV2, - PaymentSessionV2, PaymentSyncV2, PaymentTaxCalculationV2, PaymentTokenV2, PaymentV2, - PaymentVoidV2, PaymentsCompleteAuthorizeV2, PaymentsPostProcessingV2, PaymentsPreProcessingV2, + PaymentSessionUpdateV2, PaymentSessionV2, PaymentSyncV2, PaymentTaxCalculationV2, + PaymentTokenV2, PaymentV2, PaymentVoidV2, PaymentsCompleteAuthorizeV2, + PaymentsPostProcessingV2, PaymentsPreProcessingV2, }; use crate::core::errors; diff --git a/crates/router/src/types/api/payments_v2.rs b/crates/router/src/types/api/payments_v2.rs index ec3f599df8a0..cfcabadee5d8 100644 --- a/crates/router/src/types/api/payments_v2.rs +++ b/crates/router/src/types/api/payments_v2.rs @@ -1,6 +1,7 @@ pub use hyperswitch_interfaces::api::payments_v2::{ ConnectorCustomerV2, MandateSetupV2, PaymentApproveV2, PaymentAuthorizeSessionTokenV2, PaymentAuthorizeV2, PaymentCaptureV2, PaymentIncrementalAuthorizationV2, PaymentRejectV2, - PaymentSessionV2, PaymentSyncV2, PaymentTaxCalculationV2, PaymentTokenV2, PaymentV2, - PaymentVoidV2, PaymentsCompleteAuthorizeV2, PaymentsPostProcessingV2, PaymentsPreProcessingV2, + PaymentSessionUpdateV2, PaymentSessionV2, PaymentSyncV2, PaymentTaxCalculationV2, + PaymentTokenV2, PaymentV2, PaymentVoidV2, PaymentsCompleteAuthorizeV2, + PaymentsPostProcessingV2, PaymentsPreProcessingV2, }; diff --git a/crates/router/tests/connectors/utils.rs b/crates/router/tests/connectors/utils.rs index ae3ec3f82719..60ab44499f7d 100644 --- a/crates/router/tests/connectors/utils.rs +++ b/crates/router/tests/connectors/utils.rs @@ -566,6 +566,7 @@ pub trait ConnectorActions: Connector { Ok(types::PaymentsResponseData::IncrementalAuthorizationResponse { .. }) => None, Ok(types::PaymentsResponseData::PostProcessingResponse { .. }) => None, Ok(types::PaymentsResponseData::TaxCalculationResponse { .. }) => None, + Ok(types::PaymentsResponseData::SessionUpdateResponse { .. }) => None, Err(_) => None, } } @@ -1077,6 +1078,7 @@ pub fn get_connector_transaction_id( Ok(types::PaymentsResponseData::IncrementalAuthorizationResponse { .. }) => None, Ok(types::PaymentsResponseData::PostProcessingResponse { .. }) => None, Ok(types::PaymentsResponseData::TaxCalculationResponse { .. }) => None, + Ok(types::PaymentsResponseData::SessionUpdateResponse { .. }) => None, Err(_) => None, } } diff --git a/crates/router_derive/src/macros/operation.rs b/crates/router_derive/src/macros/operation.rs index ef8c70cf6af1..4177febb5a78 100644 --- a/crates/router_derive/src/macros/operation.rs +++ b/crates/router_derive/src/macros/operation.rs @@ -31,6 +31,8 @@ pub enum Derives { IncrementalAuthorizationData, TaxCalculation, TaxCalculationData, + SessionUpdate, + SessionUpdateData, } impl Derives { @@ -111,6 +113,10 @@ impl Conversion { Derives::TaxCalculationData => { syn::Ident::new("PaymentsTaxCalculationData", Span::call_site()) } + Derives::SessionUpdate => { + syn::Ident::new("PaymentsDynamicTaxCalculationRequest", Span::call_site()) + } + Derives::SessionUpdateData => syn::Ident::new("SessionUpdateData", Span::call_site()), } } @@ -432,6 +438,7 @@ pub fn operation_derive_inner(input: DeriveInput) -> syn::Result Date: Fri, 23 Aug 2024 15:09:31 +0530 Subject: [PATCH 10/39] refactor: change type of shipping and order details --- .../src/router_request_types.rs | 7 ++-- crates/router/src/core/utils.rs | 35 ++++++++++++++++--- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/crates/hyperswitch_domain_models/src/router_request_types.rs b/crates/hyperswitch_domain_models/src/router_request_types.rs index 01f7476e31d2..8565c118e973 100644 --- a/crates/hyperswitch_domain_models/src/router_request_types.rs +++ b/crates/hyperswitch_domain_models/src/router_request_types.rs @@ -1,9 +1,8 @@ pub mod authentication; pub mod fraud_check; -use api_models::payments::RequestSurchargeDetails; +use api_models::payments::{Address, RequestSurchargeDetails}; use common_utils::{ consts, - crypto::Encryptable, errors, ext_traits::OptionExt, id_type, pii, @@ -782,8 +781,8 @@ pub struct PaymentsTaxCalculationData { // New amount for amount frame work // pub minor_amount: MinorUnit, pub shipping_cost: MinorUnit, - pub shipping: Option>>, - pub order_details: Option>>, + pub shipping: Option
, + pub order_details: Option>, } #[derive(Debug, Clone, Default)] diff --git a/crates/router/src/core/utils.rs b/crates/router/src/core/utils.rs index 6a7764a3b492..8e24e0a89cbf 100644 --- a/crates/router/src/core/utils.rs +++ b/crates/router/src/core/utils.rs @@ -1,8 +1,11 @@ use std::{collections::HashSet, marker::PhantomData, str::FromStr}; -use api_models::enums::{DisputeStage, DisputeStatus}; #[cfg(feature = "payouts")] use api_models::payouts::PayoutVendorAccountDetails; +use api_models::{ + enums::{DisputeStage, DisputeStatus}, + payments::{Address, OrderDetailsWithAmount}, +}; use common_enums::{IntentStatus, RequestIncrementalAuthorization}; #[cfg(feature = "payouts")] use common_utils::{crypto::Encryptable, pii::Email}; @@ -81,7 +84,7 @@ pub async fn construct_payout_router_data<'a, F>( state: a.state.map(Encryptable::into_inner), }; - api_models::payments::Address { + Address { phone: Some(phone_details), address: Some(address_details), email: a.email.to_owned().map(Email::from), @@ -869,6 +872,30 @@ pub async fn construct_payments_dynamic_tax_calculation_router_data<'a>( .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Failed while parsing value for ConnectorAuthType")?; + let shipping: Option
= payment_intent + .shipping_details.clone() + .map(|a| { + a.into_inner() + .expose() + .parse_value("Address") + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Failed while parsing value for shipping_details") + }) + .transpose()?; + + let order: Option, _>> = + payment_intent.order_details.clone().map(|o| { + o.into_iter() + .map(|order| { + order + .expose() + .parse_value("OrderDetailsWithAmount") + .change_context(errors::ApiErrorResponse::InternalServerError) + }) + .collect() + }); + let order_details = order.map_or(Ok(None), |r| r.map(Some))?; + let router_data = types::RouterData { flow: PhantomData, merchant_id: merchant_account.get_id().to_owned(), @@ -908,8 +935,8 @@ pub async fn construct_payments_dynamic_tax_calculation_router_data<'a>( .shipping_cost .ok_or(errors::ApiErrorResponse::InternalServerError) .attach_printable("Missing shipping_cost")?, - shipping: payment_intent.shipping_details.clone(), - order_details: payment_intent.order_details.clone(), + shipping, + order_details, }, response: Err(ErrorResponse::default()), connector_request_reference_id: get_connector_request_reference_id( From 73d7923360358ad55952d350bc39aaed3331fda5 Mon Sep 17 00:00:00 2001 From: "hyperswitch-bot[bot]" <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Date: Fri, 23 Aug 2024 09:40:18 +0000 Subject: [PATCH 11/39] chore: run formatter --- .../src/router_request_types.rs | 3 +-- crates/router/src/core/utils.rs | 25 ++++++++++--------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/crates/hyperswitch_domain_models/src/router_request_types.rs b/crates/hyperswitch_domain_models/src/router_request_types.rs index 8565c118e973..985ce10e48fc 100644 --- a/crates/hyperswitch_domain_models/src/router_request_types.rs +++ b/crates/hyperswitch_domain_models/src/router_request_types.rs @@ -2,8 +2,7 @@ pub mod authentication; pub mod fraud_check; use api_models::payments::{Address, RequestSurchargeDetails}; use common_utils::{ - consts, - errors, + consts, errors, ext_traits::OptionExt, id_type, pii, types::{self as common_types, MinorUnit}, diff --git a/crates/router/src/core/utils.rs b/crates/router/src/core/utils.rs index 8e24e0a89cbf..46ec1032d5a9 100644 --- a/crates/router/src/core/utils.rs +++ b/crates/router/src/core/utils.rs @@ -873,7 +873,8 @@ pub async fn construct_payments_dynamic_tax_calculation_router_data<'a>( .attach_printable("Failed while parsing value for ConnectorAuthType")?; let shipping: Option
= payment_intent - .shipping_details.clone() + .shipping_details + .clone() .map(|a| { a.into_inner() .expose() @@ -883,17 +884,17 @@ pub async fn construct_payments_dynamic_tax_calculation_router_data<'a>( }) .transpose()?; - let order: Option, _>> = - payment_intent.order_details.clone().map(|o| { - o.into_iter() - .map(|order| { - order - .expose() - .parse_value("OrderDetailsWithAmount") - .change_context(errors::ApiErrorResponse::InternalServerError) - }) - .collect() - }); + let order: Option, _>> = + payment_intent.order_details.clone().map(|o| { + o.into_iter() + .map(|order| { + order + .expose() + .parse_value("OrderDetailsWithAmount") + .change_context(errors::ApiErrorResponse::InternalServerError) + }) + .collect() + }); let order_details = order.map_or(Ok(None), |r| r.map(Some))?; let router_data = types::RouterData { From a27d6af9cbf67e8661f326eec495a8c816d4e216 Mon Sep 17 00:00:00 2001 From: swangi-kumari Date: Sun, 25 Aug 2024 00:15:42 +0530 Subject: [PATCH 12/39] refactor: tax jar integration --- crates/api_models/src/payments.rs | 4 + .../src/connectors/taxjar.rs | 350 ++---------------- .../src/connectors/taxjar/transformers.rs | 135 +++---- .../src/default_implementations.rs | 3 +- crates/hyperswitch_connectors/src/utils.rs | 206 ++++++++++- .../src/router_request_types.rs | 9 +- crates/hyperswitch_domain_models/src/types.rs | 12 +- crates/hyperswitch_interfaces/src/types.rs | 12 +- .../payments/operations/tax_calculation.rs | 8 +- .../router/src/core/payments/transformers.rs | 1 + crates/router/src/core/utils.rs | 22 +- crates/router/tests/connectors/payme.rs | 4 + crates/router/tests/connectors/zen.rs | 4 + 13 files changed, 361 insertions(+), 409 deletions(-) diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs index 7d7c42616316..976bc53ef8d7 100644 --- a/crates/api_models/src/payments.rs +++ b/crates/api_models/src/payments.rs @@ -4379,6 +4379,8 @@ pub struct OrderDetailsWithAmount { pub brand: Option, /// Type of the product that is being purchased pub product_type: Option, + /// The tax code for the product + pub product_tax_code: Option, } #[derive(Debug, Default, Eq, PartialEq, serde::Deserialize, serde::Serialize, Clone, ToSchema)] @@ -4415,6 +4417,8 @@ pub struct OrderDetails { pub brand: Option, /// Type of the product that is being purchased pub product_type: Option, + /// The tax code for the product + pub product_tax_code: Option, } #[derive(Default, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, Clone, ToSchema)] diff --git a/crates/hyperswitch_connectors/src/connectors/taxjar.rs b/crates/hyperswitch_connectors/src/connectors/taxjar.rs index 3ea453e52859..d1fcb1c71a66 100644 --- a/crates/hyperswitch_connectors/src/connectors/taxjar.rs +++ b/crates/hyperswitch_connectors/src/connectors/taxjar.rs @@ -11,19 +11,21 @@ use hyperswitch_domain_models::{ router_data::{AccessToken, ConnectorAuthType, ErrorResponse, RouterData}, router_flow_types::{ access_token_auth::AccessTokenAuth, - payments::{Authorize, Capture, PSync, PaymentMethodToken, Session, SetupMandate, Void}, + payments::{ + Authorize, CalculateTax, Capture, PSync, PaymentMethodToken, Session, SetupMandate, + Void, + }, refunds::{Execute, RSync}, }, router_request_types::{ AccessTokenRequestData, PaymentMethodTokenizationData, PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, PaymentsSessionData, PaymentsSyncData, - RefundsData, SetupMandateRequestData, + PaymentsTaxCalculationData, RefundsData, SetupMandateRequestData, }, - router_response_types::{PaymentsResponseData, RefundsResponseData}, - types::{ - PaymentsAuthorizeRouterData, PaymentsCaptureRouterData, PaymentsSyncRouterData, - RefundSyncRouterData, RefundsRouterData, + router_response_types::{ + PaymentsResponseData, RefundsResponseData, TaxCalculationResponseData, }, + types::PaymentsTaxCalculationRouterData, }; use hyperswitch_interfaces::{ api::{self, ConnectorCommon, ConnectorCommonExt, ConnectorIntegration, ConnectorValidation}, @@ -33,7 +35,7 @@ use hyperswitch_interfaces::{ types::{self, Response}, webhooks, }; -use masking::{ExposeInterface, Mask}; +use masking::{Mask, PeekInterface}; use transformers as taxjar; use crate::{constants::headers, types::ResponseRouterData, utils}; @@ -63,6 +65,7 @@ impl api::Refund for Taxjar {} impl api::RefundExecute for Taxjar {} impl api::RefundSync for Taxjar {} impl api::PaymentToken for Taxjar {} +impl api::PaymentTaxCalculation for Taxjar {} impl ConnectorIntegration for Taxjar @@ -96,9 +99,6 @@ impl ConnectorCommon for Taxjar { fn get_currency_unit(&self) -> api::CurrencyUnit { api::CurrencyUnit::Base - // TODO! Check connector documentation, on which unit they are processing the currency. - // If the connector accepts amount in lower unit ( i.e cents for USD) then return api::CurrencyUnit::Minor, - // if connector accepts amount in base unit (i.e dollars for USD) then return api::CurrencyUnit::Base } fn common_get_content_type(&self) -> &'static str { @@ -117,7 +117,7 @@ impl ConnectorCommon for Taxjar { .change_context(errors::ConnectorError::FailedToObtainAuthType)?; Ok(vec![( headers::AUTHORIZATION.to_string(), - auth.api_key.expose().into_masked(), + format!("Bearer {}", auth.api_key.peek()).into_masked(), )]) } @@ -145,22 +145,22 @@ impl ConnectorCommon for Taxjar { } } -impl ConnectorValidation for Taxjar { - //TODO: implement functions when support enabled -} +impl ConnectorValidation for Taxjar {} -impl ConnectorIntegration for Taxjar { - //TODO: implement sessions flow -} +impl ConnectorIntegration for Taxjar {} impl ConnectorIntegration for Taxjar {} impl ConnectorIntegration for Taxjar {} -impl ConnectorIntegration for Taxjar { +impl ConnectorIntegration for Taxjar {} + +impl ConnectorIntegration + for Taxjar +{ fn get_headers( &self, - req: &PaymentsAuthorizeRouterData, + req: &PaymentsTaxCalculationRouterData, connectors: &Connectors, ) -> CustomResult)>, errors::ConnectorError> { self.build_headers(req, connectors) @@ -172,20 +172,19 @@ impl ConnectorIntegration CustomResult { Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into()) } - fn get_request_body( &self, - req: &PaymentsAuthorizeRouterData, + req: &PaymentsTaxCalculationRouterData, _connectors: &Connectors, ) -> CustomResult { let amount = utils::convert_amount( self.amount_converter, - req.request.minor_amount, + req.request.amount, req.request.currency, )?; @@ -193,23 +192,22 @@ impl ConnectorIntegration CustomResult, errors::ConnectorError> { Ok(Some( RequestBuilder::new() .method(Method::Post) - .url(&types::PaymentsAuthorizeType::get_url( + .url(&types::PaymentsTaxCalculationType::get_url( self, req, connectors, )?) .attach_default_headers() - .headers(types::PaymentsAuthorizeType::get_headers( + .headers(types::PaymentsTaxCalculationType::get_headers( self, req, connectors, )?) - .set_body(types::PaymentsAuthorizeType::get_request_body( + .set_body(types::PaymentsTaxCalculationType::get_request_body( self, req, connectors, )?) .build(), @@ -218,10 +216,10 @@ impl ConnectorIntegration, res: Response, - ) -> CustomResult { + ) -> CustomResult { let response: taxjar::TaxjarPaymentsResponse = res .response .parse_struct("Taxjar PaymentsAuthorizeResponse") @@ -244,299 +242,15 @@ impl ConnectorIntegration for Taxjar { - fn get_headers( - &self, - req: &PaymentsSyncRouterData, - connectors: &Connectors, - ) -> CustomResult)>, errors::ConnectorError> { - self.build_headers(req, connectors) - } - - fn get_content_type(&self) -> &'static str { - self.common_get_content_type() - } - - fn get_url( - &self, - _req: &PaymentsSyncRouterData, - _connectors: &Connectors, - ) -> CustomResult { - Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into()) - } +impl ConnectorIntegration for Taxjar {} - fn build_request( - &self, - req: &PaymentsSyncRouterData, - connectors: &Connectors, - ) -> CustomResult, errors::ConnectorError> { - Ok(Some( - RequestBuilder::new() - .method(Method::Get) - .url(&types::PaymentsSyncType::get_url(self, req, connectors)?) - .attach_default_headers() - .headers(types::PaymentsSyncType::get_headers(self, req, connectors)?) - .build(), - )) - } - - fn handle_response( - &self, - data: &PaymentsSyncRouterData, - event_builder: Option<&mut ConnectorEvent>, - res: Response, - ) -> CustomResult { - let response: taxjar::TaxjarPaymentsResponse = res - .response - .parse_struct("taxjar PaymentsSyncResponse") - .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; - event_builder.map(|i| i.set_response_body(&response)); - router_env::logger::info!(connector_response=?response); - RouterData::try_from(ResponseRouterData { - response, - data: data.clone(), - http_code: res.status_code, - }) - } - - fn get_error_response( - &self, - res: Response, - event_builder: Option<&mut ConnectorEvent>, - ) -> CustomResult { - self.build_error_response(res, event_builder) - } -} - -impl ConnectorIntegration for Taxjar { - fn get_headers( - &self, - req: &PaymentsCaptureRouterData, - connectors: &Connectors, - ) -> CustomResult)>, errors::ConnectorError> { - self.build_headers(req, connectors) - } - - fn get_content_type(&self) -> &'static str { - self.common_get_content_type() - } - - fn get_url( - &self, - _req: &PaymentsCaptureRouterData, - _connectors: &Connectors, - ) -> CustomResult { - Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into()) - } - - fn get_request_body( - &self, - _req: &PaymentsCaptureRouterData, - _connectors: &Connectors, - ) -> CustomResult { - Err(errors::ConnectorError::NotImplemented("get_request_body method".to_string()).into()) - } - - fn build_request( - &self, - req: &PaymentsCaptureRouterData, - connectors: &Connectors, - ) -> CustomResult, errors::ConnectorError> { - Ok(Some( - RequestBuilder::new() - .method(Method::Post) - .url(&types::PaymentsCaptureType::get_url(self, req, connectors)?) - .attach_default_headers() - .headers(types::PaymentsCaptureType::get_headers( - self, req, connectors, - )?) - .set_body(types::PaymentsCaptureType::get_request_body( - self, req, connectors, - )?) - .build(), - )) - } - - fn handle_response( - &self, - data: &PaymentsCaptureRouterData, - event_builder: Option<&mut ConnectorEvent>, - res: Response, - ) -> CustomResult { - let response: taxjar::TaxjarPaymentsResponse = res - .response - .parse_struct("Taxjar PaymentsCaptureResponse") - .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; - event_builder.map(|i| i.set_response_body(&response)); - router_env::logger::info!(connector_response=?response); - RouterData::try_from(ResponseRouterData { - response, - data: data.clone(), - http_code: res.status_code, - }) - } - - fn get_error_response( - &self, - res: Response, - event_builder: Option<&mut ConnectorEvent>, - ) -> CustomResult { - self.build_error_response(res, event_builder) - } -} +impl ConnectorIntegration for Taxjar {} impl ConnectorIntegration for Taxjar {} -impl ConnectorIntegration for Taxjar { - fn get_headers( - &self, - req: &RefundsRouterData, - connectors: &Connectors, - ) -> CustomResult)>, errors::ConnectorError> { - self.build_headers(req, connectors) - } - - fn get_content_type(&self) -> &'static str { - self.common_get_content_type() - } - - fn get_url( - &self, - _req: &RefundsRouterData, - _connectors: &Connectors, - ) -> CustomResult { - Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into()) - } +impl ConnectorIntegration for Taxjar {} - fn get_request_body( - &self, - req: &RefundsRouterData, - _connectors: &Connectors, - ) -> CustomResult { - let refund_amount = utils::convert_amount( - self.amount_converter, - req.request.minor_refund_amount, - req.request.currency, - )?; - - let connector_router_data = taxjar::TaxjarRouterData::from((refund_amount, req)); - let connector_req = taxjar::TaxjarRefundRequest::try_from(&connector_router_data)?; - Ok(RequestContent::Json(Box::new(connector_req))) - } - - fn build_request( - &self, - req: &RefundsRouterData, - connectors: &Connectors, - ) -> CustomResult, errors::ConnectorError> { - let request = RequestBuilder::new() - .method(Method::Post) - .url(&types::RefundExecuteType::get_url(self, req, connectors)?) - .attach_default_headers() - .headers(types::RefundExecuteType::get_headers( - self, req, connectors, - )?) - .set_body(types::RefundExecuteType::get_request_body( - self, req, connectors, - )?) - .build(); - Ok(Some(request)) - } - - fn handle_response( - &self, - data: &RefundsRouterData, - event_builder: Option<&mut ConnectorEvent>, - res: Response, - ) -> CustomResult, errors::ConnectorError> { - let response: taxjar::RefundResponse = - res.response - .parse_struct("taxjar RefundResponse") - .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; - event_builder.map(|i| i.set_response_body(&response)); - router_env::logger::info!(connector_response=?response); - RouterData::try_from(ResponseRouterData { - response, - data: data.clone(), - http_code: res.status_code, - }) - } - - fn get_error_response( - &self, - res: Response, - event_builder: Option<&mut ConnectorEvent>, - ) -> CustomResult { - self.build_error_response(res, event_builder) - } -} - -impl ConnectorIntegration for Taxjar { - fn get_headers( - &self, - req: &RefundSyncRouterData, - connectors: &Connectors, - ) -> CustomResult)>, errors::ConnectorError> { - self.build_headers(req, connectors) - } - - fn get_content_type(&self) -> &'static str { - self.common_get_content_type() - } - - fn get_url( - &self, - _req: &RefundSyncRouterData, - _connectors: &Connectors, - ) -> CustomResult { - Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into()) - } - - fn build_request( - &self, - req: &RefundSyncRouterData, - connectors: &Connectors, - ) -> CustomResult, errors::ConnectorError> { - Ok(Some( - RequestBuilder::new() - .method(Method::Get) - .url(&types::RefundSyncType::get_url(self, req, connectors)?) - .attach_default_headers() - .headers(types::RefundSyncType::get_headers(self, req, connectors)?) - .set_body(types::RefundSyncType::get_request_body( - self, req, connectors, - )?) - .build(), - )) - } - - fn handle_response( - &self, - data: &RefundSyncRouterData, - event_builder: Option<&mut ConnectorEvent>, - res: Response, - ) -> CustomResult { - let response: taxjar::RefundResponse = res - .response - .parse_struct("taxjar RefundSyncResponse") - .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; - event_builder.map(|i| i.set_response_body(&response)); - router_env::logger::info!(connector_response=?response); - RouterData::try_from(ResponseRouterData { - response, - data: data.clone(), - http_code: res.status_code, - }) - } - - fn get_error_response( - &self, - res: Response, - event_builder: Option<&mut ConnectorEvent>, - ) -> CustomResult { - self.build_error_response(res, event_builder) - } -} +impl ConnectorIntegration for Taxjar {} #[async_trait::async_trait] impl webhooks::IncomingWebhook for Taxjar { diff --git a/crates/hyperswitch_connectors/src/connectors/taxjar/transformers.rs b/crates/hyperswitch_connectors/src/connectors/taxjar/transformers.rs index 81493c8f5d9f..3913cc710803 100644 --- a/crates/hyperswitch_connectors/src/connectors/taxjar/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/taxjar/transformers.rs @@ -1,12 +1,12 @@ use common_enums::enums; -use common_utils::types::StringMinorUnit; +use common_utils::types::{MinorUnit, StringMinorUnit}; +use error_stack::report; use hyperswitch_domain_models::{ - payment_method_data::PaymentMethodData, router_data::{ConnectorAuthType, RouterData}, router_flow_types::refunds::{Execute, RSync}, - router_request_types::ResponseId, - router_response_types::{PaymentsResponseData, RefundsResponseData}, - types::{PaymentsAuthorizeRouterData, RefundsRouterData}, + router_response_types::{RefundsResponseData, TaxCalculationResponseData}, + types, + types::RefundsRouterData, }; use hyperswitch_interfaces::errors; use masking::Secret; @@ -14,7 +14,7 @@ use serde::{Deserialize, Serialize}; use crate::{ types::{RefundsResponseRouterData, ResponseRouterData}, - utils::PaymentsAuthorizeRequestData, + utils::{AddressDetailsData, RouterData as _}, }; //TODO: Fill the struct with respective fields @@ -36,8 +36,27 @@ impl From<(StringMinorUnit, T)> for TaxjarRouterData { //TODO: Fill the struct with respective fields #[derive(Default, Debug, Serialize, PartialEq)] pub struct TaxjarPaymentsRequest { - amount: StringMinorUnit, - card: TaxjarCard, + from_country: enums::CountryAlpha2, + from_zip: Secret, + from_state: Secret, + from_city: Option, + from_street: Option>, + to_country: enums::CountryAlpha2, + to_zip: Secret, + to_state: Secret, + to_city: Option, + to_street: Option>, + amount: MinorUnit, + shipping_cost: MinorUnit, + line_items: Vec, +} + +#[derive(Serialize, Deserialize, Debug, PartialEq)] +pub struct LineItem { + id: Option, + quantity: Option, + product_tax_code: Option, + unit_price: Option, } #[derive(Default, Debug, Serialize, Eq, PartialEq)] @@ -49,32 +68,47 @@ pub struct TaxjarCard { complete: bool, } -impl TryFrom<&TaxjarRouterData<&PaymentsAuthorizeRouterData>> for TaxjarPaymentsRequest { +impl TryFrom<&TaxjarRouterData<&types::PaymentsTaxCalculationRouterData>> + for TaxjarPaymentsRequest +{ type Error = error_stack::Report; fn try_from( - item: &TaxjarRouterData<&PaymentsAuthorizeRouterData>, + item: &TaxjarRouterData<&types::PaymentsTaxCalculationRouterData>, ) -> Result { - match item.router_data.request.payment_method_data.clone() { - PaymentMethodData::Card(req_card) => { - let card = TaxjarCard { - number: req_card.card_number, - expiry_month: req_card.card_exp_month, - expiry_year: req_card.card_exp_year, - cvc: req_card.card_cvc, - complete: item.router_data.request.is_auto_capture()?, - }; - Ok(Self { - amount: item.amount.clone(), - card, - }) - } - _ => Err(errors::ConnectorError::NotImplemented("Payment methods".to_string()).into()), + let request = &item.router_data.request; + let shipping = item.router_data.get_shipping_address()?; + // let shipping = item.router_data.request.shipping + match request.order_details.clone() { + Some(order_details) => Ok(Self { + from_country: item.router_data.get_billing_country()?, + from_zip: item.router_data.get_billing_zip()?, + from_state: item.router_data.get_billing_state_code()?, + from_city: item.router_data.get_optional_billing_city(), + from_street: item.router_data.get_optional_billing_line1(), + to_country: shipping.get_country()?.to_owned(), + to_zip: shipping.get_zip()?.to_owned(), + to_state: shipping.to_state_code()?.to_owned(), + to_city: shipping.get_optional_city(), + to_street: shipping.get_optional_line1(), + amount: request.amount, + shipping_cost: request.shipping_cost, + line_items: order_details + .iter() + .map(|line_item| LineItem { + id: line_item.product_id.clone(), + quantity: Some(line_item.quantity), + product_tax_code: line_item.product_tax_code.clone(), + unit_price: Some(line_item.amount), + }) + .collect(), + }), + None => Err(report!(errors::ConnectorError::MissingRequiredField { + field_name: "order_details" + })), } } } -//TODO: Fill the struct with respective fields -// Auth Struct pub struct TaxjarAuthType { pub(super) api_key: Secret, } @@ -90,52 +124,29 @@ impl TryFrom<&ConnectorAuthType> for TaxjarAuthType { } } } -// PaymentsResponse -//TODO: Append the remaining status flags -#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)] -#[serde(rename_all = "lowercase")] -pub enum TaxjarPaymentStatus { - Succeeded, - Failed, - #[default] - Processing, -} - -impl From for common_enums::AttemptStatus { - fn from(item: TaxjarPaymentStatus) -> Self { - match item { - TaxjarPaymentStatus::Succeeded => Self::Charged, - TaxjarPaymentStatus::Failed => Self::Failure, - TaxjarPaymentStatus::Processing => Self::Authorizing, - } - } -} //TODO: Fill the struct with respective fields #[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)] pub struct TaxjarPaymentsResponse { - status: TaxjarPaymentStatus, - id: String, + order_total_amount: i64, + amount_to_collect: i64, //calculated_tax_amount } -impl TryFrom> - for RouterData +impl TryFrom> + for RouterData { type Error = error_stack::Report; fn try_from( - item: ResponseRouterData, + item: ResponseRouterData, ) -> Result { + let calculated_tax = item.response.amount_to_collect; + let order_total_amount = item.response.order_total_amount; + Ok(Self { - status: common_enums::AttemptStatus::from(item.response.status), - response: Ok(PaymentsResponseData::TransactionResponse { - resource_id: ResponseId::ConnectorTransactionId(item.response.id), - redirection_data: None, - mandate_reference: None, - connector_metadata: None, - network_txn_id: None, - connector_response_reference_id: None, - incremental_authorization_allowed: None, - charge_id: None, + response: Ok(TaxCalculationResponseData { + order_tax_amount: calculated_tax, + net_amount: calculated_tax + order_total_amount, + shipping_address: None, }), ..item.data }) diff --git a/crates/hyperswitch_connectors/src/default_implementations.rs b/crates/hyperswitch_connectors/src/default_implementations.rs index b3bd0145a06c..3c359bc42827 100644 --- a/crates/hyperswitch_connectors/src/default_implementations.rs +++ b/crates/hyperswitch_connectors/src/default_implementations.rs @@ -118,8 +118,7 @@ default_imp_for_calculate_tax!( connectors::Fiserv, connectors::Fiservemea, connectors::Helcim, - connectors::Stax, - connectors::Taxjar + connectors::Stax ); macro_rules! default_imp_for_session_update { diff --git a/crates/hyperswitch_connectors/src/utils.rs b/crates/hyperswitch_connectors/src/utils.rs index ebd3ff347042..cd86af967a84 100644 --- a/crates/hyperswitch_connectors/src/utils.rs +++ b/crates/hyperswitch_connectors/src/utils.rs @@ -1,8 +1,11 @@ use api_models::payments::{self, Address, AddressDetails, OrderDetailsWithAmount, PhoneDetails}; -use common_enums::{enums, enums::FutureUsage}; +use common_enums::{ + enums, + enums::{CanadaStatesAbbreviation, FutureUsage, UsStatesAbbreviation}, +}; use common_utils::{ errors::{CustomResult, ReportSwitchExt}, - ext_traits::{OptionExt, ValueExt}, + ext_traits::{OptionExt, StringExt, ValueExt}, id_type, pii::{self, Email, IpAddress}, types::{AmountConvertor, MinorUnit}, @@ -159,6 +162,9 @@ pub trait RouterData { fn get_billing_full_name(&self) -> Result, Error>; fn get_billing_last_name(&self) -> Result, Error>; fn get_billing_line1(&self) -> Result, Error>; + fn get_billing_zip(&self) -> Result, Error>; + fn get_billing_state(&self) -> Result, Error>; + fn get_billing_state_code(&self) -> Result, Error>; fn get_billing_city(&self) -> Result; fn get_billing_email(&self) -> Result; fn get_billing_phone_number(&self) -> Result, Error>; @@ -401,6 +407,43 @@ impl RouterData "payment_method_data.billing.address.line1", )) } + fn get_billing_zip(&self) -> Result, Error> { + self.address + .get_payment_method_billing() + .and_then(|billing_address| { + billing_address + .clone() + .address + .and_then(|billing_details| billing_details.zip.clone()) + }) + .ok_or_else(missing_field_err("payment_method_data.billing.address.zip")) + } + fn get_billing_state(&self) -> Result, Error> { + self.address + .get_payment_method_billing() + .and_then(|billing_address| { + billing_address + .clone() + .address + .and_then(|billing_details| billing_details.state.clone()) + }) + .ok_or_else(missing_field_err( + "payment_method_data.billing.address.state", + )) + } + fn get_billing_state_code(&self) -> Result, Error> { + let country = self.get_billing_country()?; + let state = self.get_billing_state()?; + match country { + api_models::enums::CountryAlpha2::US => Ok(Secret::new( + UsStatesAbbreviation::foreign_try_from(state.peek().to_string())?.to_string(), + )), + api_models::enums::CountryAlpha2::CA => Ok(Secret::new( + CanadaStatesAbbreviation::foreign_try_from(state.peek().to_string())?.to_string(), + )), + _ => Ok(state.clone()), + } + } fn get_billing_city(&self) -> Result { self.address .get_payment_method_billing() @@ -702,6 +745,10 @@ pub trait AddressDetailsData { fn get_zip(&self) -> Result<&Secret, Error>; fn get_country(&self) -> Result<&api_models::enums::CountryAlpha2, Error>; fn get_combined_address_line(&self) -> Result, Error>; + fn to_state_code(&self) -> Result, Error>; + fn to_state_code_as_optional(&self) -> Result>, Error>; + fn get_optional_city(&self) -> Option; + fn get_optional_line1(&self) -> Option>; fn get_optional_line2(&self) -> Option>; } @@ -774,6 +821,40 @@ impl AddressDetailsData for AddressDetails { ))) } + fn to_state_code(&self) -> Result, Error> { + let country = self.get_country()?; + let state = self.get_state()?; + match country { + api_models::enums::CountryAlpha2::US => Ok(Secret::new( + UsStatesAbbreviation::foreign_try_from(state.peek().to_string())?.to_string(), + )), + api_models::enums::CountryAlpha2::CA => Ok(Secret::new( + CanadaStatesAbbreviation::foreign_try_from(state.peek().to_string())?.to_string(), + )), + _ => Ok(state.clone()), + } + } + fn to_state_code_as_optional(&self) -> Result>, Error> { + self.state + .as_ref() + .map(|state| { + if state.peek().len() == 2 { + Ok(state.to_owned()) + } else { + self.to_state_code() + } + }) + .transpose() + } + + fn get_optional_city(&self) -> Option { + self.city.clone() + } + + fn get_optional_line1(&self) -> Option> { + self.line1.clone() + } + fn get_optional_line2(&self) -> Option> { self.line2.clone() } @@ -1230,3 +1311,124 @@ macro_rules! unimplemented_payment_method { )) }; } + +impl ForeignTryFrom for UsStatesAbbreviation { + type Error = error_stack::Report; + fn foreign_try_from(value: String) -> Result { + let state_abbreviation_check = + StringExt::::parse_enum(value.to_uppercase().clone(), "UsStatesAbbreviation"); + + match state_abbreviation_check { + Ok(state_abbreviation) => Ok(state_abbreviation), + Err(_) => { + let binding = value.as_str().to_lowercase(); + let state = binding.as_str(); + match state { + "alabama" => Ok(Self::AL), + "alaska" => Ok(Self::AK), + "american samoa" => Ok(Self::AS), + "arizona" => Ok(Self::AZ), + "arkansas" => Ok(Self::AR), + "california" => Ok(Self::CA), + "colorado" => Ok(Self::CO), + "connecticut" => Ok(Self::CT), + "delaware" => Ok(Self::DE), + "district of columbia" | "columbia" => Ok(Self::DC), + "federated states of micronesia" | "micronesia" => Ok(Self::FM), + "florida" => Ok(Self::FL), + "georgia" => Ok(Self::GA), + "guam" => Ok(Self::GU), + "hawaii" => Ok(Self::HI), + "idaho" => Ok(Self::ID), + "illinois" => Ok(Self::IL), + "indiana" => Ok(Self::IN), + "iowa" => Ok(Self::IA), + "kansas" => Ok(Self::KS), + "kentucky" => Ok(Self::KY), + "louisiana" => Ok(Self::LA), + "maine" => Ok(Self::ME), + "marshall islands" => Ok(Self::MH), + "maryland" => Ok(Self::MD), + "massachusetts" => Ok(Self::MA), + "michigan" => Ok(Self::MI), + "minnesota" => Ok(Self::MN), + "mississippi" => Ok(Self::MS), + "missouri" => Ok(Self::MO), + "montana" => Ok(Self::MT), + "nebraska" => Ok(Self::NE), + "nevada" => Ok(Self::NV), + "new hampshire" => Ok(Self::NH), + "new jersey" => Ok(Self::NJ), + "new mexico" => Ok(Self::NM), + "new york" => Ok(Self::NY), + "north carolina" => Ok(Self::NC), + "north dakota" => Ok(Self::ND), + "northern mariana islands" => Ok(Self::MP), + "ohio" => Ok(Self::OH), + "oklahoma" => Ok(Self::OK), + "oregon" => Ok(Self::OR), + "palau" => Ok(Self::PW), + "pennsylvania" => Ok(Self::PA), + "puerto rico" => Ok(Self::PR), + "rhode island" => Ok(Self::RI), + "south carolina" => Ok(Self::SC), + "south dakota" => Ok(Self::SD), + "tennessee" => Ok(Self::TN), + "texas" => Ok(Self::TX), + "utah" => Ok(Self::UT), + "vermont" => Ok(Self::VT), + "virgin islands" => Ok(Self::VI), + "virginia" => Ok(Self::VA), + "washington" => Ok(Self::WA), + "west virginia" => Ok(Self::WV), + "wisconsin" => Ok(Self::WI), + "wyoming" => Ok(Self::WY), + _ => Err(errors::ConnectorError::InvalidDataFormat { + field_name: "address.state", + } + .into()), + } + } + } + } +} + +impl ForeignTryFrom for CanadaStatesAbbreviation { + type Error = error_stack::Report; + fn foreign_try_from(value: String) -> Result { + let state_abbreviation_check = + StringExt::::parse_enum(value.to_uppercase().clone(), "CanadaStatesAbbreviation"); + match state_abbreviation_check { + Ok(state_abbreviation) => Ok(state_abbreviation), + Err(_) => { + let binding = value.as_str().to_lowercase(); + let state = binding.as_str(); + match state { + "alberta" => Ok(Self::AB), + "british columbia" => Ok(Self::BC), + "manitoba" => Ok(Self::MB), + "new brunswick" => Ok(Self::NB), + "newfoundland and labrador" | "newfoundland & labrador" => Ok(Self::NL), + "northwest territories" => Ok(Self::NT), + "nova scotia" => Ok(Self::NS), + "nunavut" => Ok(Self::NU), + "ontario" => Ok(Self::ON), + "prince edward island" => Ok(Self::PE), + "quebec" => Ok(Self::QC), + "saskatchewan" => Ok(Self::SK), + "yukon" => Ok(Self::YT), + _ => Err(errors::ConnectorError::InvalidDataFormat { + field_name: "address.state", + } + .into()), + } + } + } + } +} + +pub trait ForeignTryFrom: Sized { + type Error; + + fn foreign_try_from(from: F) -> Result; +} diff --git a/crates/hyperswitch_domain_models/src/router_request_types.rs b/crates/hyperswitch_domain_models/src/router_request_types.rs index 985ce10e48fc..4bb8a2795d32 100644 --- a/crates/hyperswitch_domain_models/src/router_request_types.rs +++ b/crates/hyperswitch_domain_models/src/router_request_types.rs @@ -776,12 +776,13 @@ pub struct PaymentsSessionData { #[derive(Debug, Clone, Default)] pub struct PaymentsTaxCalculationData { - pub amount: i64, - // New amount for amount frame work - // pub minor_amount: MinorUnit, + pub amount: MinorUnit, + pub currency: storage_enums::Currency, pub shipping_cost: MinorUnit, - pub shipping: Option
, + pub shipping: Address, pub order_details: Option>, + // New amount for amount frame work + // pub minor_amount: MinorUnit, } #[derive(Debug, Clone, Default)] diff --git a/crates/hyperswitch_domain_models/src/types.rs b/crates/hyperswitch_domain_models/src/types.rs index e425fc7fcc69..d27c7974092d 100644 --- a/crates/hyperswitch_domain_models/src/types.rs +++ b/crates/hyperswitch_domain_models/src/types.rs @@ -1,15 +1,17 @@ use crate::{ router_data::RouterData, router_flow_types::{ - Authorize, Capture, CompleteAuthorize, CreateConnectorCustomer, PSync, PaymentMethodToken, - RSync, SetupMandate, Void, + Authorize, CalculateTax, Capture, CompleteAuthorize, CreateConnectorCustomer, PSync, + PaymentMethodToken, RSync, SetupMandate, Void, }, router_request_types::{ CompleteAuthorizeData, ConnectorCustomerData, PaymentMethodTokenizationData, PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, PaymentsSyncData, - RefundsData, SetupMandateRequestData, + PaymentsTaxCalculationData, RefundsData, SetupMandateRequestData, + }, + router_response_types::{ + PaymentsResponseData, RefundsResponseData, TaxCalculationResponseData, }, - router_response_types::{PaymentsResponseData, RefundsResponseData}, }; pub type PaymentsAuthorizeRouterData = @@ -27,3 +29,5 @@ pub type ConnectorCustomerRouterData = RouterData; pub type PaymentsCompleteAuthorizeRouterData = RouterData; +pub type PaymentsTaxCalculationRouterData = + RouterData; diff --git a/crates/hyperswitch_interfaces/src/types.rs b/crates/hyperswitch_interfaces/src/types.rs index 06a1d6028e66..e42942a94de9 100644 --- a/crates/hyperswitch_interfaces/src/types.rs +++ b/crates/hyperswitch_interfaces/src/types.rs @@ -7,7 +7,7 @@ use hyperswitch_domain_models::{ files::{Retrieve, Upload}, mandate_revoke::MandateRevoke, payments::{ - Authorize, AuthorizeSessionToken, Balance, Capture, CompleteAuthorize, + Authorize, AuthorizeSessionToken, Balance, CalculateTax, Capture, CompleteAuthorize, CreateConnectorCustomer, IncrementalAuthorization, InitPayment, PSync, PaymentMethodToken, PostProcessing, PreProcessing, Session, SetupMandate, Void, }, @@ -20,13 +20,14 @@ use hyperswitch_domain_models::{ MandateRevokeRequestData, PaymentMethodTokenizationData, PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, PaymentsIncrementalAuthorizationData, PaymentsPostProcessingData, PaymentsPreProcessingData, PaymentsSessionData, - PaymentsSyncData, RefundsData, RetrieveFileRequestData, SetupMandateRequestData, - SubmitEvidenceRequestData, UploadFileRequestData, VerifyWebhookSourceRequestData, + PaymentsSyncData, PaymentsTaxCalculationData, RefundsData, RetrieveFileRequestData, + SetupMandateRequestData, SubmitEvidenceRequestData, UploadFileRequestData, + VerifyWebhookSourceRequestData, }, router_response_types::{ AcceptDisputeResponse, DefendDisputeResponse, MandateRevokeResponseData, PaymentsResponseData, RefundsResponseData, RetrieveFileResponse, SubmitEvidenceResponse, - UploadFileResponse, VerifyWebhookSourceResponseData, + TaxCalculationResponseData, UploadFileResponse, VerifyWebhookSourceResponseData, }, }; #[cfg(feature = "payouts")] @@ -54,6 +55,9 @@ pub struct Response { /// Type alias for `ConnectorIntegration` pub type PaymentsAuthorizeType = dyn ConnectorIntegration; +/// Type alias for `ConnectorIntegration` +pub type PaymentsTaxCalculationType = + dyn ConnectorIntegration; /// Type alias for `ConnectorIntegration` pub type SetupMandateType = dyn ConnectorIntegration; diff --git a/crates/router/src/core/payments/operations/tax_calculation.rs b/crates/router/src/core/payments/operations/tax_calculation.rs index 7bb71a86a304..e1b219bd0ff0 100644 --- a/crates/router/src/core/payments/operations/tax_calculation.rs +++ b/crates/router/src/core/payments/operations/tax_calculation.rs @@ -94,12 +94,14 @@ impl GetTracker, api::PaymentsDynamicTaxCalcu let amount = payment_attempt.get_total_amount().into(); - let shipping_address = helpers::get_address_by_id( + let shipping_address = helpers::create_or_update_address_for_payment_by_request( state, - payment_intent.shipping_address_id.clone(), + Some(&request.shipping), + payment_intent.shipping_address_id.as_deref(), + merchant_id, + payment_intent.customer_id.as_ref(), key_store, &payment_intent.payment_id, - merchant_id, merchant_account.storage_scheme, ) .await?; diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs index e44f15f00b7b..cafe8f07eac1 100644 --- a/crates/router/src/core/payments/transformers.rs +++ b/crates/router/src/core/payments/transformers.rs @@ -1363,6 +1363,7 @@ pub fn change_order_details_to_new_type( sub_category: order_details.sub_category, brand: order_details.brand, product_type: order_details.product_type, + product_tax_code: order_details.product_tax_code, }]) } diff --git a/crates/router/src/core/utils.rs b/crates/router/src/core/utils.rs index 46ec1032d5a9..b829dc494df9 100644 --- a/crates/router/src/core/utils.rs +++ b/crates/router/src/core/utils.rs @@ -872,17 +872,16 @@ pub async fn construct_payments_dynamic_tax_calculation_router_data<'a>( .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Failed while parsing value for ConnectorAuthType")?; - let shipping: Option
= payment_intent + let shipping: Address = payment_intent .shipping_details .clone() - .map(|a| { - a.into_inner() - .expose() - .parse_value("Address") - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Failed while parsing value for shipping_details") - }) - .transpose()?; + .ok_or(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Missing payment_intent.shipping_details")? + .into_inner() + .expose() + .parse_value("Address") + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Failed while parsing value for shipping_details")?; let order: Option, _>> = payment_intent.order_details.clone().map(|o| { @@ -931,13 +930,16 @@ pub async fn construct_payments_dynamic_tax_calculation_router_data<'a>( payment_method_balance: None, connector_api_version: None, request: types::PaymentsTaxCalculationData { - amount: payment_intent.amount.clone().get_amount_as_i64(), + amount: payment_intent.amount, shipping_cost: payment_intent .shipping_cost .ok_or(errors::ApiErrorResponse::InternalServerError) .attach_printable("Missing shipping_cost")?, shipping, order_details, + currency: payment_intent + .currency + .ok_or(errors::ApiErrorResponse::InternalServerError)?, }, response: Err(ErrorResponse::default()), connector_request_reference_id: get_connector_request_reference_id( diff --git a/crates/router/tests/connectors/payme.rs b/crates/router/tests/connectors/payme.rs index 605f63d0f64c..e85c57df622f 100644 --- a/crates/router/tests/connectors/payme.rs +++ b/crates/router/tests/connectors/payme.rs @@ -88,6 +88,7 @@ fn payment_method_details() -> Option { sub_category: None, brand: None, product_type: None, + product_tax_code: None, }]), router_return_url: Some("https://hyperswitch.io".to_string()), webhook_url: Some("https://hyperswitch.io".to_string()), @@ -388,6 +389,7 @@ async fn should_fail_payment_for_incorrect_cvc() { sub_category: None, brand: None, product_type: None, + product_tax_code: None, }]), router_return_url: Some("https://hyperswitch.io".to_string()), webhook_url: Some("https://hyperswitch.io".to_string()), @@ -427,6 +429,7 @@ async fn should_fail_payment_for_invalid_exp_month() { sub_category: None, brand: None, product_type: None, + product_tax_code: None, }]), router_return_url: Some("https://hyperswitch.io".to_string()), webhook_url: Some("https://hyperswitch.io".to_string()), @@ -466,6 +469,7 @@ async fn should_fail_payment_for_incorrect_expiry_year() { sub_category: None, brand: None, product_type: None, + product_tax_code: None, }]), router_return_url: Some("https://hyperswitch.io".to_string()), webhook_url: Some("https://hyperswitch.io".to_string()), diff --git a/crates/router/tests/connectors/zen.rs b/crates/router/tests/connectors/zen.rs index 2b9ea8f8211c..5c9cc2694c4d 100644 --- a/crates/router/tests/connectors/zen.rs +++ b/crates/router/tests/connectors/zen.rs @@ -331,6 +331,7 @@ async fn should_fail_payment_for_incorrect_card_number() { sub_category: None, brand: None, product_type: None, + product_tax_code: None, }]), email: Some(Email::from_str("test@gmail.com").unwrap()), webhook_url: Some("https://1635-116-74-253-164.ngrok-free.app".to_string()), @@ -373,6 +374,7 @@ async fn should_fail_payment_for_incorrect_cvc() { sub_category: None, brand: None, product_type: None, + product_tax_code: None, }]), email: Some(Email::from_str("test@gmail.com").unwrap()), webhook_url: Some("https://1635-116-74-253-164.ngrok-free.app".to_string()), @@ -415,6 +417,7 @@ async fn should_fail_payment_for_invalid_exp_month() { sub_category: None, brand: None, product_type: None, + product_tax_code: None, }]), email: Some(Email::from_str("test@gmail.com").unwrap()), webhook_url: Some("https://1635-116-74-253-164.ngrok-free.app".to_string()), @@ -457,6 +460,7 @@ async fn should_fail_payment_for_incorrect_expiry_year() { sub_category: None, brand: None, product_type: None, + product_tax_code: None, }]), email: Some(Email::from_str("test@gmail.com").unwrap()), webhook_url: Some("https://1635-116-74-253-164.ngrok-free.app".to_string()), From 778a14fe19e78417deabda423a3bc1ecb37e608e Mon Sep 17 00:00:00 2001 From: "hyperswitch-bot[bot]" <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Date: Sat, 24 Aug 2024 18:48:38 +0000 Subject: [PATCH 13/39] docs(openapi): re-generate OpenAPI specification --- api-reference-v2/openapi_spec.json | 10 ++++++++++ api-reference/openapi_spec.json | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/api-reference-v2/openapi_spec.json b/api-reference-v2/openapi_spec.json index e2a8faff04ce..7f7bfe9eafd1 100644 --- a/api-reference-v2/openapi_spec.json +++ b/api-reference-v2/openapi_spec.json @@ -8700,6 +8700,11 @@ } ], "nullable": true + }, + "product_tax_code": { + "type": "string", + "description": "The tax code for the product", + "nullable": true } } }, @@ -8765,6 +8770,11 @@ } ], "nullable": true + }, + "product_tax_code": { + "type": "string", + "description": "The tax code for the product", + "nullable": true } } }, diff --git a/api-reference/openapi_spec.json b/api-reference/openapi_spec.json index 2d1f806db30e..95be1f5f29c9 100644 --- a/api-reference/openapi_spec.json +++ b/api-reference/openapi_spec.json @@ -13292,6 +13292,11 @@ } ], "nullable": true + }, + "product_tax_code": { + "type": "string", + "description": "The tax code for the product", + "nullable": true } } }, @@ -13357,6 +13362,11 @@ } ], "nullable": true + }, + "product_tax_code": { + "type": "string", + "description": "The tax code for the product", + "nullable": true } } }, From a794c410d9081c0aed1cf4e28520f979af0912bb Mon Sep 17 00:00:00 2001 From: swangi-kumari Date: Sun, 25 Aug 2024 01:32:29 +0530 Subject: [PATCH 14/39] feat: update trackers --- crates/diesel_models/src/payment_intent.rs | 67 +++++++++++++++++-- .../src/payments/payment_intent.rs | 15 +++++ .../payments/operations/payment_confirm.rs | 1 + .../payments/operations/payment_update.rs | 1 + .../payments/operations/tax_calculation.rs | 5 +- 5 files changed, 81 insertions(+), 8 deletions(-) diff --git a/crates/diesel_models/src/payment_intent.rs b/crates/diesel_models/src/payment_intent.rs index 875d340b0aed..e7a88178d3d2 100644 --- a/crates/diesel_models/src/payment_intent.rs +++ b/crates/diesel_models/src/payment_intent.rs @@ -134,7 +134,7 @@ pub struct PaymentIntent { pub tax_details: Option, } -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, diesel::AsExpression)] +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize, diesel::AsExpression)] #[diesel(sql_type = diesel::sql_types::Jsonb)] pub struct TaxDetails { pub default: DefaultTax, @@ -148,17 +148,14 @@ pub struct PmtTax { pub order_tax_amount: i64, pub shipping_details: String, } -// common_utils::impl_to_sql_from_sql_json!(PmtTax); -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)] pub struct DefaultTax { pub order_tax_amount: i64, pub pmt: Option, pub shipping_details: String, } -// common_utils::impl_to_sql_from_sql_json!(DefaultTax); - #[derive( Clone, Debug, PartialEq, Insertable, router_derive::DebugAsDisplay, Serialize, Deserialize, )] @@ -294,6 +291,9 @@ pub enum PaymentIntentUpdate { status: Option, updated_by: String, }, + TaxCalculationUpdate { + tax_details: TaxDetails, + }, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -324,6 +324,7 @@ pub struct PaymentIntentUpdateFields { pub merchant_order_reference_id: Option, pub shipping_details: Option, pub is_payment_processor_token_flow: Option, + pub tax_details: Option, } #[derive(Clone, Debug, AsChangeset, router_derive::DebugAsDisplay)] @@ -365,6 +366,7 @@ pub struct PaymentIntentUpdateInternal { pub merchant_order_reference_id: Option, pub shipping_details: Option, pub is_payment_processor_token_flow: Option, + pub tax_details: Option, } impl PaymentIntentUpdate { @@ -405,6 +407,7 @@ impl PaymentIntentUpdate { merchant_order_reference_id, shipping_details, is_payment_processor_token_flow, + tax_details, } = self.into(); PaymentIntent { amount: amount.unwrap_or(source.amount), @@ -449,6 +452,7 @@ impl PaymentIntentUpdate { shipping_details: shipping_details.or(source.shipping_details), is_payment_processor_token_flow: is_payment_processor_token_flow .or(source.is_payment_processor_token_flow), + tax_details: tax_details.or(source.tax_details), ..source } } @@ -496,6 +500,7 @@ impl From for PaymentIntentUpdateInternal { merchant_order_reference_id: None, shipping_details: None, is_payment_processor_token_flow: None, + tax_details: None, }, PaymentIntentUpdate::Update(value) => Self { amount: Some(value.amount), @@ -534,6 +539,7 @@ impl From for PaymentIntentUpdateInternal { incremental_authorization_allowed: None, authorization_count: None, is_payment_processor_token_flow: value.is_payment_processor_token_flow, + tax_details: None, }, PaymentIntentUpdate::PaymentCreateUpdate { return_url, @@ -579,6 +585,7 @@ impl From for PaymentIntentUpdateInternal { merchant_order_reference_id: None, shipping_details: None, is_payment_processor_token_flow: None, + tax_details: None, }, PaymentIntentUpdate::PGStatusUpdate { status, @@ -620,6 +627,7 @@ impl From for PaymentIntentUpdateInternal { merchant_order_reference_id: None, shipping_details: None, is_payment_processor_token_flow: None, + tax_details: None, }, PaymentIntentUpdate::MerchantStatusUpdate { status, @@ -662,6 +670,7 @@ impl From for PaymentIntentUpdateInternal { merchant_order_reference_id: None, shipping_details: None, is_payment_processor_token_flow: None, + tax_details: None, }, PaymentIntentUpdate::ResponseUpdate { // amount, @@ -712,6 +721,7 @@ impl From for PaymentIntentUpdateInternal { merchant_order_reference_id: None, shipping_details: None, is_payment_processor_token_flow: None, + tax_details: None, }, PaymentIntentUpdate::PaymentAttemptAndAttemptCountUpdate { active_attempt_id, @@ -753,6 +763,7 @@ impl From for PaymentIntentUpdateInternal { merchant_order_reference_id: None, shipping_details: None, is_payment_processor_token_flow: None, + tax_details: None, }, PaymentIntentUpdate::StatusAndAttemptUpdate { status, @@ -795,6 +806,7 @@ impl From for PaymentIntentUpdateInternal { merchant_order_reference_id: None, shipping_details: None, is_payment_processor_token_flow: None, + tax_details: None, }, PaymentIntentUpdate::ApproveUpdate { status, @@ -836,6 +848,7 @@ impl From for PaymentIntentUpdateInternal { merchant_order_reference_id: None, shipping_details: None, is_payment_processor_token_flow: None, + tax_details: None, }, PaymentIntentUpdate::RejectUpdate { status, @@ -877,6 +890,7 @@ impl From for PaymentIntentUpdateInternal { merchant_order_reference_id: None, shipping_details: None, is_payment_processor_token_flow: None, + tax_details: None, }, PaymentIntentUpdate::SurchargeApplicableUpdate { surcharge_applicable, @@ -917,6 +931,7 @@ impl From for PaymentIntentUpdateInternal { merchant_order_reference_id: None, shipping_details: None, is_payment_processor_token_flow: None, + tax_details: None, }, PaymentIntentUpdate::IncrementalAuthorizationAmountUpdate { amount } => Self { amount: Some(amount), @@ -954,6 +969,7 @@ impl From for PaymentIntentUpdateInternal { merchant_order_reference_id: None, shipping_details: None, is_payment_processor_token_flow: None, + tax_details: None, }, PaymentIntentUpdate::AuthorizationCountUpdate { authorization_count, @@ -993,6 +1009,7 @@ impl From for PaymentIntentUpdateInternal { merchant_order_reference_id: None, shipping_details: None, is_payment_processor_token_flow: None, + tax_details: None, }, PaymentIntentUpdate::CompleteAuthorizeUpdate { shipping_address_id, @@ -1032,6 +1049,7 @@ impl From for PaymentIntentUpdateInternal { merchant_order_reference_id: None, shipping_details: None, is_payment_processor_token_flow: None, + tax_details: None, }, PaymentIntentUpdate::ManualUpdate { status, updated_by } => Self { status, @@ -1069,6 +1087,45 @@ impl From for PaymentIntentUpdateInternal { merchant_order_reference_id: None, shipping_details: None, is_payment_processor_token_flow: None, + tax_details: None, + }, + PaymentIntentUpdate::TaxCalculationUpdate { tax_details } => Self { + shipping_address_id: None, + amount: None, + currency: None, + status: None, + amount_captured: None, + customer_id: None, + return_url: None, + setup_future_usage: None, + off_session: None, + metadata: None, + billing_address_id: None, + modified_at: common_utils::date_time::now(), + active_attempt_id: None, + business_country: None, + business_label: None, + description: None, + statement_descriptor_name: None, + statement_descriptor_suffix: None, + order_details: None, + attempt_count: None, + merchant_decision: None, + payment_confirm_source: None, + updated_by: String::default(), + surcharge_applicable: None, + incremental_authorization_allowed: None, + authorization_count: None, + session_expiry: None, + fingerprint_id: None, + request_external_three_ds_authentication: None, + frm_metadata: None, + customer_details: None, + billing_details: None, + merchant_order_reference_id: None, + shipping_details: None, + is_payment_processor_token_flow: None, + tax_details: Some(tax_details), }, } } diff --git a/crates/hyperswitch_domain_models/src/payments/payment_intent.rs b/crates/hyperswitch_domain_models/src/payments/payment_intent.rs index c129e83d5563..00bf04d2ea6a 100644 --- a/crates/hyperswitch_domain_models/src/payments/payment_intent.rs +++ b/crates/hyperswitch_domain_models/src/payments/payment_intent.rs @@ -181,6 +181,7 @@ pub struct PaymentIntentUpdateFields { pub merchant_order_reference_id: Option, pub shipping_details: Option>>, pub is_payment_processor_token_flow: Option, + pub tax_details: Option, } #[derive(Debug, Clone, Serialize)] @@ -256,6 +257,9 @@ pub enum PaymentIntentUpdate { status: Option, updated_by: String, }, + TaxCalculationUpdate { + tax_details: diesel_models::TaxDetails, + }, } #[derive(Clone, Debug, Default)] @@ -298,6 +302,7 @@ pub struct PaymentIntentUpdateInternal { pub merchant_order_reference_id: Option, pub shipping_details: Option>>, pub is_payment_processor_token_flow: Option, + pub tax_details: diesel_models::TaxDetails, } impl From for PaymentIntentUpdateInternal { @@ -480,6 +485,10 @@ impl From for PaymentIntentUpdateInternal { updated_by, ..Default::default() }, + PaymentIntentUpdate::TaxCalculationUpdate { tax_details } => Self { + tax_details, + ..Default::default() + }, } } } @@ -543,6 +552,7 @@ impl From for DieselPaymentIntentUpdate { merchant_order_reference_id: value.merchant_order_reference_id, shipping_details: value.shipping_details.map(Encryption::from), is_payment_processor_token_flow: value.is_payment_processor_token_flow, + tax_details: value.tax_details, })) } PaymentIntentUpdate::PaymentCreateUpdate { @@ -643,6 +653,9 @@ impl From for DieselPaymentIntentUpdate { PaymentIntentUpdate::ManualUpdate { status, updated_by } => { Self::ManualUpdate { status, updated_by } } + PaymentIntentUpdate::TaxCalculationUpdate { tax_details } => { + Self::TaxCalculationUpdate { tax_details } + } } } } @@ -687,6 +700,7 @@ impl From for diesel_models::PaymentIntentUpdateInt merchant_order_reference_id, shipping_details, is_payment_processor_token_flow, + tax_details, } = value; Self { @@ -725,6 +739,7 @@ impl From for diesel_models::PaymentIntentUpdateInt merchant_order_reference_id, shipping_details: shipping_details.map(Encryption::from), is_payment_processor_token_flow, + tax_details: Some(tax_details), } } } diff --git a/crates/router/src/core/payments/operations/payment_confirm.rs b/crates/router/src/core/payments/operations/payment_confirm.rs index 2e7131edce23..370e21610b84 100644 --- a/crates/router/src/core/payments/operations/payment_confirm.rs +++ b/crates/router/src/core/payments/operations/payment_confirm.rs @@ -1394,6 +1394,7 @@ impl UpdateTracker, api::PaymentsRequest> for Paymen billing_details, shipping_details, is_payment_processor_token_flow, + tax_details: None, })), &m_key_store, storage_scheme, diff --git a/crates/router/src/core/payments/operations/payment_update.rs b/crates/router/src/core/payments/operations/payment_update.rs index e7045116f23c..a2c2e2568fdb 100644 --- a/crates/router/src/core/payments/operations/payment_update.rs +++ b/crates/router/src/core/payments/operations/payment_update.rs @@ -772,6 +772,7 @@ impl UpdateTracker, api::PaymentsRequest> for Paymen billing_details, shipping_details, is_payment_processor_token_flow: None, + tax_details: None, })), key_store, storage_scheme, diff --git a/crates/router/src/core/payments/operations/tax_calculation.rs b/crates/router/src/core/payments/operations/tax_calculation.rs index e1b219bd0ff0..87c5f9dd62ab 100644 --- a/crates/router/src/core/payments/operations/tax_calculation.rs +++ b/crates/router/src/core/payments/operations/tax_calculation.rs @@ -347,9 +347,8 @@ impl UpdateTracker, api::PaymentsDynamicTaxCalculati where F: 'b + Send, { - //update shipping and tax_details - let payment_intent_update = hyperswitch_domain_models::payments::payment_intent::PaymentIntentUpdate::CompleteAuthorizeUpdate { - shipping_address_id: payment_data.payment_intent.shipping_address_id.clone() + let payment_intent_update = hyperswitch_domain_models::payments::payment_intent::PaymentIntentUpdate::TaxCalculationUpdate { + tax_details: payment_data.payment_intent.tax_details.clone().ok_or(errors::ApiErrorResponse::InternalServerError)? }; let db = &*state.store; From d888f614341e3ab6f3a25007974386240631fa0b Mon Sep 17 00:00:00 2001 From: swangi-kumari Date: Sun, 25 Aug 2024 17:38:23 +0530 Subject: [PATCH 15/39] feat: call tax jar in payment create and update --- .../payments/operations/payment_create.rs | 74 ++++++++++++++++++- .../payments/operations/payment_update.rs | 74 ++++++++++++++++++- .../payments/operations/tax_calculation.rs | 13 ---- 3 files changed, 146 insertions(+), 15 deletions(-) diff --git a/crates/router/src/core/payments/operations/payment_create.rs b/crates/router/src/core/payments/operations/payment_create.rs index 641ac1ab85d8..dea310464e90 100644 --- a/crates/router/src/core/payments/operations/payment_create.rs +++ b/crates/router/src/core/payments/operations/payment_create.rs @@ -40,7 +40,8 @@ use crate::{ }, services, types::{ - api::{self, PaymentIdTypeExt}, + self, + api::{self, ConnectorCallType, PaymentIdTypeExt}, domain, storage::{ self, @@ -582,6 +583,77 @@ impl Domain for PaymentCreate { .await } + async fn payments_dynamic_tax_calculation<'a>( + &'a self, + state: &SessionState, + // key_manager_state: &common_utils::types::keymanager::KeyManagerState, + payment_data: &mut PaymentData, + _should_continue_confirm_transaction: &mut bool, + _connector_call_type: &ConnectorCallType, + // _merchant_account: &storage::BusinessProfile, + key_store: &domain::MerchantKeyStore, + // storage_scheme: storage_enums::MerchantStorageScheme, + merchant_account: &domain::MerchantAccount, + ) -> CustomResult<(), errors::ApiErrorResponse> { + // let db = state.store.as_ref(); + let payment_intent = payment_data.payment_intent.clone(); + + // let attempt_id = payment_intent.active_attempt.get_id().clone(); + + let payment_attempt = payment_data.payment_attempt.clone(); + + // Derive this connector from business profile + let connector_data = api::TaxCalculateConnectorData::get_connector_by_name( + payment_attempt.connector.as_ref().unwrap(), + )?; + + let router_data = core_utils::construct_payments_dynamic_tax_calculation_router_data( + state, + &payment_intent, + &payment_attempt, + merchant_account, + key_store, + // &customer, + ) + .await?; + let connector_integration: services::BoxedPaymentConnectorIntegrationInterface< + api::CalculateTax, + types::PaymentsTaxCalculationData, + types::TaxCalculationResponseData, + > = connector_data.connector.get_connector_integration(); + + let response = services::execute_connector_processing_step( + state, + connector_integration, + &router_data, + payments::CallConnectorAction::Trigger, + None, + ) + .await + .change_context(errors::ApiErrorResponse::InternalServerError)?; + + let tax_response = + response + .response + .map_err(|err| errors::ApiErrorResponse::ExternalConnectorError { + code: err.code, + message: err.message, + connector: connector_data.connector_name.clone().to_string(), + status_code: err.status_code, + reason: err.reason, + })?; + + payment_data + .payment_intent + .tax_details + .clone() + .map(|mut tax_details| { + tax_details.default.order_tax_amount = tax_response.order_tax_amount; + }); + + Ok(()) + } + #[instrument(skip_all)] async fn make_pm_data<'a>( &'a self, diff --git a/crates/router/src/core/payments/operations/payment_update.rs b/crates/router/src/core/payments/operations/payment_update.rs index a2c2e2568fdb..ea0580da5a5a 100644 --- a/crates/router/src/core/payments/operations/payment_update.rs +++ b/crates/router/src/core/payments/operations/payment_update.rs @@ -27,7 +27,8 @@ use crate::{ routes::{app::ReqState, SessionState}, services, types::{ - api::{self, PaymentIdTypeExt}, + self, + api::{self, ConnectorCallType, PaymentIdTypeExt}, domain, storage::{self, enums as storage_enums, payment_attempt::PaymentAttemptExt}, transformers::ForeignTryFrom, @@ -515,6 +516,77 @@ impl Domain for PaymentUpdate { .await } + async fn payments_dynamic_tax_calculation<'a>( + &'a self, + state: &SessionState, + // key_manager_state: &common_utils::types::keymanager::KeyManagerState, + payment_data: &mut PaymentData, + _should_continue_confirm_transaction: &mut bool, + _connector_call_type: &ConnectorCallType, + // _merchant_account: &storage::BusinessProfile, + key_store: &domain::MerchantKeyStore, + // storage_scheme: storage_enums::MerchantStorageScheme, + merchant_account: &domain::MerchantAccount, + ) -> CustomResult<(), errors::ApiErrorResponse> { + // let db = state.store.as_ref(); + let payment_intent = payment_data.payment_intent.clone(); + + // let attempt_id = payment_intent.active_attempt.get_id().clone(); + + let payment_attempt = payment_data.payment_attempt.clone(); + + // Derive this connector from business profile + let connector_data = api::TaxCalculateConnectorData::get_connector_by_name( + payment_attempt.connector.as_ref().unwrap(), + )?; + + let router_data = core_utils::construct_payments_dynamic_tax_calculation_router_data( + state, + &payment_intent, + &payment_attempt, + merchant_account, + key_store, + // &customer, + ) + .await?; + let connector_integration: services::BoxedPaymentConnectorIntegrationInterface< + api::CalculateTax, + types::PaymentsTaxCalculationData, + types::TaxCalculationResponseData, + > = connector_data.connector.get_connector_integration(); + + let response = services::execute_connector_processing_step( + state, + connector_integration, + &router_data, + payments::CallConnectorAction::Trigger, + None, + ) + .await + .change_context(errors::ApiErrorResponse::InternalServerError)?; + + let tax_response = + response + .response + .map_err(|err| errors::ApiErrorResponse::ExternalConnectorError { + code: err.code, + message: err.message, + connector: connector_data.connector_name.clone().to_string(), + status_code: err.status_code, + reason: err.reason, + })?; + + payment_data + .payment_intent + .tax_details + .clone() + .map(|mut tax_details| { + tax_details.default.order_tax_amount = tax_response.order_tax_amount; + }); + + Ok(()) + } + #[instrument(skip_all)] async fn make_pm_data<'a>( &'a self, diff --git a/crates/router/src/core/payments/operations/tax_calculation.rs b/crates/router/src/core/payments/operations/tax_calculation.rs index 87c5f9dd62ab..fae703acb5e2 100644 --- a/crates/router/src/core/payments/operations/tax_calculation.rs +++ b/crates/router/src/core/payments/operations/tax_calculation.rs @@ -258,14 +258,6 @@ impl Domain reason: err.reason, })?; - // Update payment_data.tax_details with new amount which was returned by the connector - // When constructing the router data, add this to the net amount - //payment_data - - // match tax_response { - // hyperswitch_domain_models::router_response_types::PaymentsResponseData::TaxCalculationResponse { order_tax_amount, .. } => { - // // Update payment_data.payment_intent.tax_details.order_tax_amount with the order_tax_amount from the TaxCalculationResponse - payment_data .payment_intent .tax_details @@ -275,11 +267,6 @@ impl Domain pmt.order_tax_amount = tax_response.order_tax_amount; }); }); - // } - // _ => { - // Err(errors::ApiErrorResponse::InternalServerError)? - // } - // } Ok(()) } From 503d79d6d825e7f1f62576da2b3a2297db3c88e5 Mon Sep 17 00:00:00 2001 From: swangi-kumari Date: Tue, 27 Aug 2024 15:02:49 +0530 Subject: [PATCH 16/39] feat: connector call succesfu --- crates/api_models/src/enums.rs | 10 +- crates/api_models/src/payments.rs | 2 + crates/common_utils/src/types.rs | 4 +- crates/connector_configs/src/connector.rs | 2 + crates/diesel_models/src/payment_attempt.rs | 53 +++++ crates/diesel_models/src/payment_intent.rs | 10 +- crates/diesel_models/src/schema.rs | 2 +- .../src/connectors/taxjar.rs | 30 ++- .../src/connectors/taxjar/transformers.rs | 216 ++++++++++-------- crates/hyperswitch_connectors/src/utils.rs | 10 + .../src/payments/payment_attempt.rs | 5 - .../src/router_request_types.rs | 2 +- .../src/router_response_types.rs | 7 +- crates/router/src/core/admin.rs | 10 + crates/router/src/core/payments.rs | 101 ++------ .../payments/flows/tax_calculation_flow.rs | 2 + .../payments/operations/payment_approve.rs | 1 + .../payments/operations/payment_cancel.rs | 1 + .../payments/operations/payment_capture.rs | 1 + .../operations/payment_complete_authorize.rs | 1 + .../payments/operations/payment_confirm.rs | 1 + .../payments/operations/payment_create.rs | 21 +- .../payments/operations/payment_reject.rs | 1 + .../payments/operations/payment_response.rs | 57 ++++- .../payments/operations/payment_session.rs | 1 + .../core/payments/operations/payment_start.rs | 1 + .../payments/operations/payment_status.rs | 1 + .../payments/operations/payment_update.rs | 21 +- .../payments_incremental_authorization.rs | 1 + .../payments/operations/tax_calculation.rs | 108 +++++++-- .../router/src/core/payments/transformers.rs | 23 +- crates/router/src/core/utils.rs | 73 +++--- crates/router/src/routes/payments.rs | 7 +- crates/router/src/types/api.rs | 6 +- crates/router/src/types/transformers.rs | 3 +- .../src/payments/payment_attempt.rs | 4 + 36 files changed, 512 insertions(+), 287 deletions(-) diff --git a/crates/api_models/src/enums.rs b/crates/api_models/src/enums.rs index 543cb5c98656..039be5d3967e 100644 --- a/crates/api_models/src/enums.rs +++ b/crates/api_models/src/enums.rs @@ -131,7 +131,7 @@ pub enum Connector { Square, Stax, Stripe, - // Taxjar, + Taxjar, Threedsecureio, Trustpay, Tsys, @@ -209,7 +209,7 @@ impl Connector { | Self::DummyConnector7 => false, Self::Aci // Add Separate authentication support for connectors - // | Self::Taxjar + | Self::Taxjar // | Self::Fiservemea | Self::Adyen | Self::Adyenplatform @@ -425,7 +425,7 @@ pub enum FrmConnectors { #[strum(serialize_all = "snake_case")] pub enum TaxCalculatorConnectors { - TaxJar, + Taxjar, } #[derive( @@ -669,6 +669,10 @@ pub fn convert_authentication_connector(connector_name: &str) -> Option Option { + TaxCalculatorConnectors::from_str(connector_name).ok() +} + #[derive( Clone, Debug, diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs index 976bc53ef8d7..c286fbd868e3 100644 --- a/crates/api_models/src/payments.rs +++ b/crates/api_models/src/payments.rs @@ -4454,6 +4454,8 @@ pub struct PaymentsDynamicTaxCalculationRequest { /// Client Secret #[schema(value_type = String)] pub client_secret: String, + /// Payment method type + pub payment_method_type: api_enums::PaymentMethodType, } /// Response for calling tax jar API #[derive(Debug, serde::Serialize, serde::Deserialize, Clone, ToSchema)] diff --git a/crates/common_utils/src/types.rs b/crates/common_utils/src/types.rs index f0ecb7085901..5319a4c5f7d6 100644 --- a/crates/common_utils/src/types.rs +++ b/crates/common_utils/src/types.rs @@ -507,7 +507,7 @@ pub struct FloatMajorUnit(f64); impl FloatMajorUnit { /// forms a new major unit from amount - fn new(value: f64) -> Self { + pub fn new(value: f64) -> Self { Self(value) } @@ -517,7 +517,7 @@ impl FloatMajorUnit { } /// converts to minor unit as i64 from FloatMajorUnit - fn to_minor_unit_as_i64( + pub fn to_minor_unit_as_i64( self, currency: enums::Currency, ) -> Result> { diff --git a/crates/connector_configs/src/connector.rs b/crates/connector_configs/src/connector.rs index 51713f6166fb..6819be42911c 100644 --- a/crates/connector_configs/src/connector.rs +++ b/crates/connector_configs/src/connector.rs @@ -212,6 +212,7 @@ pub struct ConnectorConfig { pub paypal_test: Option, pub zen: Option, pub zsl: Option, + pub taxjar: Option, } impl ConnectorConfig { @@ -341,6 +342,7 @@ impl ConnectorConfig { Connector::Stripe => Ok(connector_data.stripe), Connector::Trustpay => Ok(connector_data.trustpay), Connector::Threedsecureio => Ok(connector_data.threedsecureio), + Connector::Taxjar => Ok(connector_data.taxjar), Connector::Tsys => Ok(connector_data.tsys), Connector::Volt => Ok(connector_data.volt), Connector::Wellsfargo => Ok(connector_data.wellsfargo), diff --git a/crates/diesel_models/src/payment_attempt.rs b/crates/diesel_models/src/payment_attempt.rs index 525c681a1e58..4668eb17f9e9 100644 --- a/crates/diesel_models/src/payment_attempt.rs +++ b/crates/diesel_models/src/payment_attempt.rs @@ -437,6 +437,11 @@ pub enum PaymentAttemptUpdate { unified_code: Option, unified_message: Option, }, + // SessionUpdate { + // amount: i64, + // order_tax_amount: i64, + // payment_method_shipping_address_id: Option, + // }, } #[derive(Clone, Debug, AsChangeset, router_derive::DebugAsDisplay)] @@ -1693,6 +1698,54 @@ impl From for PaymentAttemptUpdateInternal { client_version: None, customer_acceptance: None, }, + // PaymentAttemptUpdate::SessionUpdate { amount, order_tax_amount, payment_method_shipping_address_id } => Self { + // amount: Some(amount), + // modified_at: common_utils::date_time::now(), + // amount_capturable: Some(amount + order_tax_amount), + // net_amount: None, + // currency: None, + // status: None, + // connector_transaction_id: None, + // amount_to_capture: None, + // connector: None, + // authentication_type: None, + // payment_method: None, + // error_message: None, + // payment_method_id: None, + // cancellation_reason: None, + // mandate_id: None, + // browser_info: None, + // payment_token: None, + // error_code: None, + // connector_metadata: None, + // payment_method_data: None, + // payment_method_type: None, + // payment_experience: None, + // business_sub_label: None, + // straight_through_algorithm: None, + // preprocessing_step_id: None, + // error_reason: None, + // capture_method: None, + // connector_response_reference_id: None, + // multiple_capture_count: None, + // surcharge_amount: None, + // tax_amount: None, + // updated_by: String::default(), + // merchant_connector_id: None, + // authentication_data: None, + // encoded_data: None, + // unified_code: None, + // unified_message: None, + // external_three_ds_authentication_attempted: None, + // authentication_connector: None, + // authentication_id: None, + // fingerprint_id: None, + // payment_method_billing_address_id: None, + // charge_id: None, + // client_source: None, + // client_version: None, + // customer_acceptance: None, + // }, } } } diff --git a/crates/diesel_models/src/payment_intent.rs b/crates/diesel_models/src/payment_intent.rs index e7a88178d3d2..62a94c6bbbea 100644 --- a/crates/diesel_models/src/payment_intent.rs +++ b/crates/diesel_models/src/payment_intent.rs @@ -129,15 +129,15 @@ pub struct PaymentIntent { pub billing_details: Option, pub merchant_order_reference_id: Option, pub shipping_details: Option, - pub shipping_cost: Option, pub is_payment_processor_token_flow: Option, + pub shipping_cost: Option, pub tax_details: Option, } #[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize, diesel::AsExpression)] #[diesel(sql_type = diesel::sql_types::Jsonb)] pub struct TaxDetails { - pub default: DefaultTax, + pub default: Option, pub pmt: Option, } @@ -146,14 +146,14 @@ common_utils::impl_to_sql_from_sql_json!(TaxDetails); #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct PmtTax { pub order_tax_amount: i64, - pub shipping_details: String, + pub pmt: String, + // pub shipping_details: String, } #[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)] pub struct DefaultTax { pub order_tax_amount: i64, - pub pmt: Option, - pub shipping_details: String, + // pub shipping_details: String, } #[derive( diff --git a/crates/diesel_models/src/schema.rs b/crates/diesel_models/src/schema.rs index 44461b08cead..18f8512a72f3 100644 --- a/crates/diesel_models/src/schema.rs +++ b/crates/diesel_models/src/schema.rs @@ -900,8 +900,8 @@ diesel::table! { #[max_length = 255] merchant_order_reference_id -> Nullable, shipping_details -> Nullable, - shipping_cost -> Nullable, is_payment_processor_token_flow -> Nullable, + shipping_cost -> Nullable, tax_details -> Nullable, } } diff --git a/crates/hyperswitch_connectors/src/connectors/taxjar.rs b/crates/hyperswitch_connectors/src/connectors/taxjar.rs index d1fcb1c71a66..bcb7d62889a1 100644 --- a/crates/hyperswitch_connectors/src/connectors/taxjar.rs +++ b/crates/hyperswitch_connectors/src/connectors/taxjar.rs @@ -4,7 +4,7 @@ use common_utils::{ errors::CustomResult, ext_traits::BytesExt, request::{Method, Request, RequestBuilder, RequestContent}, - types::{AmountConvertor, StringMinorUnit, StringMinorUnitForConnector}, + types::{AmountConvertor, FloatMajorUnit, FloatMajorUnitForConnector}, }; use error_stack::{report, ResultExt}; use hyperswitch_domain_models::{ @@ -39,16 +39,17 @@ use masking::{Mask, PeekInterface}; use transformers as taxjar; use crate::{constants::headers, types::ResponseRouterData, utils}; +// use crate::utils:: #[derive(Clone)] pub struct Taxjar { - amount_converter: &'static (dyn AmountConvertor + Sync), + amount_converter: &'static (dyn AmountConvertor + Sync), } impl Taxjar { pub fn new() -> &'static Self { &Self { - amount_converter: &StringMinorUnitForConnector, + amount_converter: &FloatMajorUnitForConnector, } } } @@ -136,9 +137,9 @@ impl ConnectorCommon for Taxjar { Ok(ErrorResponse { status_code: res.status_code, - code: response.code, - message: response.message, - reason: response.reason, + code: response.status.clone(), + message: response.detail.clone(), + reason: Some(response.detail), attempt_status: None, connector_transaction_id: None, }) @@ -173,9 +174,9 @@ impl ConnectorIntegration CustomResult { - Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into()) + Ok(format!("{}taxes", self.base_url(connectors))) } fn get_request_body( &self, @@ -188,8 +189,18 @@ impl ConnectorIntegration, res: Response, ) -> CustomResult { + print!("response123_connector{:?}", res.response); let response: taxjar::TaxjarPaymentsResponse = res .response .parse_struct("Taxjar PaymentsAuthorizeResponse") diff --git a/crates/hyperswitch_connectors/src/connectors/taxjar/transformers.rs b/crates/hyperswitch_connectors/src/connectors/taxjar/transformers.rs index 3913cc710803..8a25a18c32d9 100644 --- a/crates/hyperswitch_connectors/src/connectors/taxjar/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/taxjar/transformers.rs @@ -1,33 +1,36 @@ use common_enums::enums; -use common_utils::types::{MinorUnit, StringMinorUnit}; +use common_utils::types::{FloatMajorUnit, FloatMajorUnitForConnector, MinorUnit, StringMinorUnit}; use error_stack::report; use hyperswitch_domain_models::{ router_data::{ConnectorAuthType, RouterData}, router_flow_types::refunds::{Execute, RSync}, router_response_types::{RefundsResponseData, TaxCalculationResponseData}, + router_request_types::PaymentsTaxCalculationData, types, types::RefundsRouterData, }; -use hyperswitch_interfaces::errors; +use hyperswitch_interfaces::{api, errors}; use masking::Secret; use serde::{Deserialize, Serialize}; use crate::{ types::{RefundsResponseRouterData, ResponseRouterData}, - utils::{AddressDetailsData, RouterData as _}, + utils::{self, AddressDetailsData, RouterData as _}, }; //TODO: Fill the struct with respective fields pub struct TaxjarRouterData { - pub amount: StringMinorUnit, // The type of amount that a connector accepts, for example, String, i64, f64, etc. + pub amount: FloatMajorUnit, // The type of amount that a connector accepts, for example, String, i64, f64, etc. + pub shipping: FloatMajorUnit, pub router_data: T, } -impl From<(StringMinorUnit, T)> for TaxjarRouterData { - fn from((amount, item): (StringMinorUnit, T)) -> Self { +impl From<(FloatMajorUnit, FloatMajorUnit, T)> for TaxjarRouterData { + fn from((amount, shipping, item): (FloatMajorUnit, FloatMajorUnit, T)) -> Self { //Todo : use utils to convert the amount to the type of amount that a connector accepts Self { amount, + shipping, router_data: item, } } @@ -46,8 +49,8 @@ pub struct TaxjarPaymentsRequest { to_state: Secret, to_city: Option, to_street: Option>, - amount: MinorUnit, - shipping_cost: MinorUnit, + amount: FloatMajorUnit, + shipping: FloatMajorUnit, line_items: Vec, } @@ -56,7 +59,7 @@ pub struct LineItem { id: Option, quantity: Option, product_tax_code: Option, - unit_price: Option, + unit_price: Option, } #[derive(Default, Debug, Serialize, Eq, PartialEq)] @@ -76,8 +79,16 @@ impl TryFrom<&TaxjarRouterData<&types::PaymentsTaxCalculationRouterData>> item: &TaxjarRouterData<&types::PaymentsTaxCalculationRouterData>, ) -> Result { let request = &item.router_data.request; - let shipping = item.router_data.get_shipping_address()?; - // let shipping = item.router_data.request.shipping + // let shipping = item.router_data.get_shipping_address()?; + // println!("$$swangi{:?}", shipping); + let currency = item.router_data.request.currency; + let currency_unit = &api::CurrencyUnit::Base; + let shipping = &item.router_data.request.shipping_address.address.clone().ok_or(errors::ConnectorError::MissingRequiredField { field_name: "address" })?; + + + println!("$$shipping123{:?}", shipping); + + match request.order_details.clone() { Some(order_details) => Ok(Self { from_country: item.router_data.get_billing_country()?, @@ -90,15 +101,15 @@ impl TryFrom<&TaxjarRouterData<&types::PaymentsTaxCalculationRouterData>> to_state: shipping.to_state_code()?.to_owned(), to_city: shipping.get_optional_city(), to_street: shipping.get_optional_line1(), - amount: request.amount, - shipping_cost: request.shipping_cost, + amount: item.amount, + shipping: item.shipping, line_items: order_details .iter() .map(|line_item| LineItem { id: line_item.product_id.clone(), quantity: Some(line_item.quantity), product_tax_code: line_item.product_tax_code.clone(), - unit_price: Some(line_item.amount), + unit_price: Some(FloatMajorUnit::new(utils::get_amount_as_f64(currency_unit, line_item.amount, currency).unwrap())), }) .collect(), }), @@ -128,24 +139,52 @@ impl TryFrom<&ConnectorAuthType> for TaxjarAuthType { //TODO: Fill the struct with respective fields #[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)] pub struct TaxjarPaymentsResponse { - order_total_amount: i64, - amount_to_collect: i64, //calculated_tax_amount + tax: Tax, } -impl TryFrom> - for RouterData +#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)] +pub struct Tax { + order_total_amount: FloatMajorUnit, + amount_to_collect: FloatMajorUnit, //calculated_tax_amount +} + +impl + TryFrom< + ResponseRouterData< + F, + TaxjarPaymentsResponse, + PaymentsTaxCalculationData, + TaxCalculationResponseData, + >, + > for RouterData { type Error = error_stack::Report; fn try_from( - item: ResponseRouterData, + item: ResponseRouterData< + F, + TaxjarPaymentsResponse, + PaymentsTaxCalculationData, + TaxCalculationResponseData, + >, ) -> Result { - let calculated_tax = item.response.amount_to_collect; - let order_total_amount = item.response.order_total_amount; + let currency = item.data.request.currency; + let amount_to_collect = item.response.tax.amount_to_collect; + let order_total_amount = item.response.tax.order_total_amount; + let calculated_tax = utils::convert_back_amount_to_minor_units( + &FloatMajorUnitForConnector, + amount_to_collect, + currency, + )?; + let total_amount = utils::convert_back_amount_to_minor_units( + &FloatMajorUnitForConnector, + order_total_amount, + currency, + )?; Ok(Self { response: Ok(TaxCalculationResponseData { order_tax_amount: calculated_tax, - net_amount: calculated_tax + order_total_amount, + net_amount: (total_amount + calculated_tax), shipping_address: None, }), ..item.data @@ -156,84 +195,83 @@ impl TryFrom TryFrom<&TaxjarRouterData<&RefundsRouterData>> for TaxjarRefundRequest { - type Error = error_stack::Report; - fn try_from(item: &TaxjarRouterData<&RefundsRouterData>) -> Result { - Ok(Self { - amount: item.amount.to_owned(), - }) - } -} +// impl TryFrom<&TaxjarRouterData<&RefundsRouterData>> for TaxjarRefundRequest { +// type Error = error_stack::Report; +// fn try_from(item: &TaxjarRouterData<&RefundsRouterData>) -> Result { +// Ok(Self { +// amount: item.amount.to_owned(), +// }) +// } +// } // Type definition for Refund Response -#[allow(dead_code)] -#[derive(Debug, Serialize, Default, Deserialize, Clone)] -pub enum RefundStatus { - Succeeded, - Failed, - #[default] - Processing, -} +// #[allow(dead_code)] +// #[derive(Debug, Serialize, Default, Deserialize, Clone)] +// pub enum RefundStatus { +// Succeeded, +// Failed, +// #[default] +// Processing, +// } -impl From for enums::RefundStatus { - fn from(item: RefundStatus) -> Self { - match item { - RefundStatus::Succeeded => Self::Success, - RefundStatus::Failed => Self::Failure, - RefundStatus::Processing => Self::Pending, - //TODO: Review mapping - } - } -} +// impl From for enums::RefundStatus { +// fn from(item: RefundStatus) -> Self { +// match item { +// RefundStatus::Succeeded => Self::Success, +// RefundStatus::Failed => Self::Failure, +// RefundStatus::Processing => Self::Pending, +// //TODO: Review mapping +// } +// } +// } //TODO: Fill the struct with respective fields -#[derive(Default, Debug, Clone, Serialize, Deserialize)] -pub struct RefundResponse { - id: String, - status: RefundStatus, -} +// #[derive(Default, Debug, Clone, Serialize, Deserialize)] +// pub struct RefundResponse { +// id: String, +// status: RefundStatus, +// } -impl TryFrom> for RefundsRouterData { - type Error = error_stack::Report; - fn try_from( - item: RefundsResponseRouterData, - ) -> Result { - Ok(Self { - response: Ok(RefundsResponseData { - connector_refund_id: item.response.id.to_string(), - refund_status: enums::RefundStatus::from(item.response.status), - }), - ..item.data - }) - } -} +// impl TryFrom> for RefundsRouterData { +// type Error = error_stack::Report; +// fn try_from( +// item: RefundsResponseRouterData, +// ) -> Result { +// Ok(Self { +// response: Ok(RefundsResponseData { +// connector_refund_id: item.response.id.to_string(), +// refund_status: enums::RefundStatus::from(item.response.status), +// }), +// ..item.data +// }) +// } +// } -impl TryFrom> for RefundsRouterData { - type Error = error_stack::Report; - fn try_from( - item: RefundsResponseRouterData, - ) -> Result { - Ok(Self { - response: Ok(RefundsResponseData { - connector_refund_id: item.response.id.to_string(), - refund_status: enums::RefundStatus::from(item.response.status), - }), - ..item.data - }) - } -} +// impl TryFrom> for RefundsRouterData { +// type Error = error_stack::Report; +// fn try_from( +// item: RefundsResponseRouterData, +// ) -> Result { +// Ok(Self { +// response: Ok(RefundsResponseData { +// connector_refund_id: item.response.id.to_string(), +// refund_status: enums::RefundStatus::from(item.response.status), +// }), +// ..item.data +// }) +// } +// } //TODO: Fill the struct with respective fields #[derive(Default, Debug, Serialize, Deserialize, PartialEq)] pub struct TaxjarErrorResponse { - pub status_code: u16, - pub code: String, - pub message: String, - pub reason: Option, + pub status: String, + pub error: String, + pub detail: String, } diff --git a/crates/hyperswitch_connectors/src/utils.rs b/crates/hyperswitch_connectors/src/utils.rs index cd86af967a84..5306bdb85d9d 100644 --- a/crates/hyperswitch_connectors/src/utils.rs +++ b/crates/hyperswitch_connectors/src/utils.rs @@ -146,6 +146,16 @@ pub(crate) fn convert_amount( .change_context(errors::ConnectorError::AmountConversionFailed) } +pub(crate) fn convert_back_amount_to_minor_units( + amount_convertor: &dyn AmountConvertor, + amount: T, + currency: enums::Currency, +) -> Result> { + amount_convertor + .convert_back(amount, currency) + .change_context(errors::ConnectorError::AmountConversionFailed) +} + // TODO: Make all traits as `pub(crate) trait` once all connectors are moved. pub trait RouterData { fn get_billing(&self) -> Result<&Address, Error>; diff --git a/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs b/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs index 0aa23fba41e5..de832afed91d 100644 --- a/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs +++ b/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs @@ -474,11 +474,6 @@ pub enum PaymentAttemptUpdate { unified_code: Option, unified_message: Option, }, - // SessionUpdate { - // amount: MinorUnit, - // // order_tax_amount: MinorUnit, - // // payment_method_shipping_address_id: Option, - // }, } impl ForeignIDRef for PaymentAttempt { diff --git a/crates/hyperswitch_domain_models/src/router_request_types.rs b/crates/hyperswitch_domain_models/src/router_request_types.rs index 4bb8a2795d32..a2a873e06160 100644 --- a/crates/hyperswitch_domain_models/src/router_request_types.rs +++ b/crates/hyperswitch_domain_models/src/router_request_types.rs @@ -779,8 +779,8 @@ pub struct PaymentsTaxCalculationData { pub amount: MinorUnit, pub currency: storage_enums::Currency, pub shipping_cost: MinorUnit, - pub shipping: Address, pub order_details: Option>, + pub shipping_address: Address, // New amount for amount frame work // pub minor_amount: MinorUnit, } diff --git a/crates/hyperswitch_domain_models/src/router_response_types.rs b/crates/hyperswitch_domain_models/src/router_response_types.rs index 7a6a9241ccde..430fcb7d75c3 100644 --- a/crates/hyperswitch_domain_models/src/router_response_types.rs +++ b/crates/hyperswitch_domain_models/src/router_response_types.rs @@ -74,15 +74,16 @@ pub enum PaymentsResponseData { shipping_address: Option, }, SessionUpdateResponse { - status: common_enums::AuthorizationStatus, + status: common_enums::SessionUpdateStatus, }, } #[derive(Debug, Clone)] pub struct TaxCalculationResponseData { - pub order_tax_amount: i64, - pub net_amount: i64, + pub order_tax_amount: MinorUnit, + pub net_amount: MinorUnit, pub shipping_address: Option, + // pub currency: storage_enums::Currency, } #[derive(serde::Serialize, Debug, Clone)] diff --git a/crates/router/src/core/admin.rs b/crates/router/src/core/admin.rs index ca1b24a06fba..0f2435f6c9b8 100644 --- a/crates/router/src/core/admin.rs +++ b/crates/router/src/core/admin.rs @@ -1486,6 +1486,7 @@ impl<'a> ConnectorAuthTypeAndMetadataValidation<'a> { stax::transformers::StaxAuthType::try_from(self.auth_type)?; Ok(()) } + api_enums::Connector::Taxjar => Ok(()), api_enums::Connector::Stripe => { stripe::transformers::StripeAuthType::try_from(self.auth_type)?; Ok(()) @@ -1841,6 +1842,8 @@ impl<'a> ConnectorTypeAndConnectorName<'a> { api_enums::convert_pm_auth_connector(self.connector_name.to_string().as_str()); let authentication_connector = api_enums::convert_authentication_connector(self.connector_name.to_string().as_str()); + let tax_connector = + api_enums::convert_tax_connector(self.connector_name.to_string().as_str()); if pm_auth_connector.is_some() { if self.connector_type != &api_enums::ConnectorType::PaymentMethodAuth @@ -1858,6 +1861,13 @@ impl<'a> ConnectorTypeAndConnectorName<'a> { } .into()); } + } else if tax_connector.is_some() { + if self.connector_type != &api_enums::ConnectorType::FinOperations { + return Err(errors::ApiErrorResponse::InvalidRequestData { + message: "Invalid connector type given".to_string(), + } + .into()); + } } else { let routable_connector_option = self .connector_name diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs index 0ce79bdbce52..1a87c6bd18ed 100644 --- a/crates/router/src/core/payments.rs +++ b/crates/router/src/core/payments.rs @@ -192,18 +192,29 @@ where ) .await?; - let connector = get_connector_choice( - &operation, - state, - &req, - &merchant_account, - &business_profile, - &key_store, - &mut payment_data, - eligible_connectors, - mandate_type, - ) - .await?; + let connector = if format!("{operation:?}").as_str() == "PaymentSessionUpdate" { + Some(ConnectorCallType::PreDetermined( + api::ConnectorData::get_connector_by_name( + &state.conf.connectors, + "klarna", + api::GetToken::Connector, + None, + )?, + )) + } else { + get_connector_choice( + &operation, + state, + &req, + &merchant_account, + &business_profile, + &key_store, + &mut payment_data, + eligible_connectors, + mandate_type, + ) + .await? + }; let should_add_task_to_process_tracker = should_add_task_to_process_tracker(&payment_data); @@ -836,69 +847,6 @@ where }) } } -// pub async fn payments_dynamic_tax_calculation( -// state: SessionState, -// req_state: ReqState, -// merchant_account: domain::MerchantAccount, -// key_store: domain::MerchantKeyStore, -// operation: Op, -// req: api_models::payments::PaymentsDynamicTaxCalculationRequest, -// auth_flow: services::AuthFlow, -// call_connector_action: CallConnectorAction, -// eligible_connectors: Option>, -// customer: &Option, -// // header_payload: HeaderPayload, -// ) -> RouterResponse { - -// let db = &state.store; -// let payment_intent = db -// .find_payment_intent_by_payment_id_merchant_id( -// &(&state).into(), -// &req.payment_id.clone(), -// &merchant_account.merchant_id, -// &key_store, -// merchant_account.storage_scheme, -// ) -// .await -// .change_context(errors::ApiErrorResponse::PaymentNotFound)?; -// let attempt_id = payment_intent.active_attempt.get_id().clone(); -// let payment_attempt = db -// .find_payment_attempt_by_payment_id_merchant_id_attempt_id( -// &payment_intent.payment_id, -// &merchant_account.merchant_id, -// &attempt_id.clone(), -// merchant_account.storage_scheme, -// ) -// .await -// .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?; -// let connector_data = api::TaxCalculateConnectorData::get_connector_by_name( -// payment_attempt.connector.as_ref().unwrap(), -// )?; -// let router_data = utils::construct_payments_dynamic_tax_calculation_router_data( -// &state, -// &payment_intent, -// &payment_attempt, -// &merchant_account, -// &key_store, -// &customer, -// ) -// .await?; -// let connector_integration: services::BoxedPaymentConnectorIntegrationInterface = connector_data.connector.get_connector_integration(); -// let response = services::execute_connector_processing_step( -// &state, -// connector_integration, -// &router_data, -// CallConnectorAction::Trigger, -// None, -// ) -// .await.change_context(errors::ApiErrorResponse::InternalServerError)?; -// Ok(services::ApplicationResponse::Json( -// api_models::payments::PaymentsDynamicTaxCalculationResponse { -// order_tax_amount: response.amount_captured.unwrap_or_default(), -// net_amount: response.amount_captured.unwrap_or_default(), -// } -// )) -// } #[allow(clippy::too_many_arguments)] pub async fn payments_core( @@ -2834,6 +2782,7 @@ where pub authentication: Option, pub recurring_details: Option, pub poll_config: Option, + pub shipping_details: Option, } #[derive(Clone, serde::Serialize, Debug)] @@ -2969,7 +2918,7 @@ pub fn should_call_connector( "PaymentApprove" => true, "PaymentReject" => true, "PaymentSession" => true, - "PaymentTaxCalculation" => true, + "PaymentSessionUpdate" => true, "PaymentIncrementalAuthorization" => matches!( payment_data.payment_intent.status, storage_enums::IntentStatus::RequiresCapture diff --git a/crates/router/src/core/payments/flows/tax_calculation_flow.rs b/crates/router/src/core/payments/flows/tax_calculation_flow.rs index 289263630525..afd3cf8a16eb 100644 --- a/crates/router/src/core/payments/flows/tax_calculation_flow.rs +++ b/crates/router/src/core/payments/flows/tax_calculation_flow.rs @@ -30,6 +30,8 @@ impl _merchant_recipient_data: Option, ) -> RouterResult { // create a new function to construct router data to send the updated amount + + println!("Constructing router data for session update"); Box::pin( transformers::construct_router_date_to_update_calculated_tax::< api::SessionUpdate, diff --git a/crates/router/src/core/payments/operations/payment_approve.rs b/crates/router/src/core/payments/operations/payment_approve.rs index 401e1c2c7a1c..265b645b3e18 100644 --- a/crates/router/src/core/payments/operations/payment_approve.rs +++ b/crates/router/src/core/payments/operations/payment_approve.rs @@ -182,6 +182,7 @@ impl GetTracker, api::PaymentsCaptureRequest> authentication: None, recurring_details: None, poll_config: None, + shipping_details: None, }; let get_trackers_response = operations::GetTrackerResponse { diff --git a/crates/router/src/core/payments/operations/payment_cancel.rs b/crates/router/src/core/payments/operations/payment_cancel.rs index 84eaf97bfaae..2dcdb2abc634 100644 --- a/crates/router/src/core/payments/operations/payment_cancel.rs +++ b/crates/router/src/core/payments/operations/payment_cancel.rs @@ -196,6 +196,7 @@ impl GetTracker, api::PaymentsCancelRequest> authentication: None, recurring_details: None, poll_config: None, + shipping_details: None, }; let get_trackers_response = operations::GetTrackerResponse { diff --git a/crates/router/src/core/payments/operations/payment_capture.rs b/crates/router/src/core/payments/operations/payment_capture.rs index 0d096e1d3aea..3278af560713 100644 --- a/crates/router/src/core/payments/operations/payment_capture.rs +++ b/crates/router/src/core/payments/operations/payment_capture.rs @@ -242,6 +242,7 @@ impl GetTracker, api::PaymentsCaptu authentication: None, recurring_details: None, poll_config: None, + shipping_details: None, }; let get_trackers_response = operations::GetTrackerResponse { 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 8d4e6f7a5f2e..f8a97d526caa 100644 --- a/crates/router/src/core/payments/operations/payment_complete_authorize.rs +++ b/crates/router/src/core/payments/operations/payment_complete_authorize.rs @@ -339,6 +339,7 @@ impl GetTracker, api::PaymentsRequest> for Co authentication: None, recurring_details, poll_config: None, + shipping_details: None, }; let customer_details = Some(CustomerDetails { diff --git a/crates/router/src/core/payments/operations/payment_confirm.rs b/crates/router/src/core/payments/operations/payment_confirm.rs index 370e21610b84..4e3fef4f502e 100644 --- a/crates/router/src/core/payments/operations/payment_confirm.rs +++ b/crates/router/src/core/payments/operations/payment_confirm.rs @@ -724,6 +724,7 @@ impl GetTracker, api::PaymentsRequest> for Pa authentication: None, recurring_details, poll_config: None, + shipping_details: None, }; let get_trackers_response = operations::GetTrackerResponse { diff --git a/crates/router/src/core/payments/operations/payment_create.rs b/crates/router/src/core/payments/operations/payment_create.rs index dea310464e90..cd52b85a7f7e 100644 --- a/crates/router/src/core/payments/operations/payment_create.rs +++ b/crates/router/src/core/payments/operations/payment_create.rs @@ -540,6 +540,7 @@ impl GetTracker, api::PaymentsRequest> for Pa authentication: None, recurring_details, poll_config: None, + shipping_details: None, }; let get_trackers_response = operations::GetTrackerResponse { @@ -603,16 +604,13 @@ impl Domain for PaymentCreate { let payment_attempt = payment_data.payment_attempt.clone(); // Derive this connector from business profile - let connector_data = api::TaxCalculateConnectorData::get_connector_by_name( - payment_attempt.connector.as_ref().unwrap(), - )?; + let connector_data = api::TaxCalculateConnectorData::get_connector_by_name("taxjar")?; let router_data = core_utils::construct_payments_dynamic_tax_calculation_router_data( state, - &payment_intent, - &payment_attempt, merchant_account, key_store, + payment_data, // &customer, ) .await?; @@ -643,13 +641,12 @@ impl Domain for PaymentCreate { reason: err.reason, })?; - payment_data - .payment_intent - .tax_details - .clone() - .map(|mut tax_details| { - tax_details.default.order_tax_amount = tax_response.order_tax_amount; - }); + payment_data.payment_intent.tax_details = Some(diesel_models::TaxDetails { + default: Some(diesel_models::DefaultTax { + order_tax_amount: tax_response.order_tax_amount.get_amount_as_i64(), + }), + pmt: None, + }); Ok(()) } diff --git a/crates/router/src/core/payments/operations/payment_reject.rs b/crates/router/src/core/payments/operations/payment_reject.rs index a5d0b95a6729..37f784317b29 100644 --- a/crates/router/src/core/payments/operations/payment_reject.rs +++ b/crates/router/src/core/payments/operations/payment_reject.rs @@ -180,6 +180,7 @@ impl GetTracker, PaymentsCancelRequest> for P authentication: None, recurring_details: None, poll_config: None, + shipping_details: None, }; let get_trackers_response = operations::GetTrackerResponse { diff --git a/crates/router/src/core/payments/operations/payment_response.rs b/crates/router/src/core/payments/operations/payment_response.rs index f2ab80d81d7c..595a76033d08 100644 --- a/crates/router/src/core/payments/operations/payment_response.rs +++ b/crates/router/src/core/payments/operations/payment_response.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; // use api_models::payments::PaymentsDynamicTaxCalculationRequest; use async_trait::async_trait; -use common_enums::AuthorizationStatus; +use common_enums::{AuthorizationStatus, SessionUpdateStatus}; use common_utils::{ ext_traits::{AsyncExt, Encode}, types::{keymanager::KeyManagerState, MinorUnit}, @@ -544,6 +544,61 @@ impl PostUpdateTracker, types::SessionUpdateData> fo F: 'b + Send, { // if connector_ call successfull -> paymnet_intent.amount update + + println!("swangi1234"); + + let session_update_details = + payment_data + .payment_intent + .tax_details + .clone() + .ok_or_else(|| { + report!(errors::ApiErrorResponse::InternalServerError) + .attach_printable("missing tax_details in payment_intent") + })?; + + println!("session_update_details: {:?}", session_update_details); + + let pmt_amount = session_update_details + .pmt + .clone() + .map(|pmt| pmt.order_tax_amount) + .ok_or(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Missing tax_details.order_tax_amount")?; + + println!("pmt_amount: {:?}", pmt_amount); + + let total_amount = MinorUnit::from(payment_data.amount) + MinorUnit::new(pmt_amount); + + println!("total_amount: {:?}", total_amount); + + println!("router_data.response: {:?}", router_data.response.clone()); + + match router_data.response.clone() { + Err(_) => (None, None), + Ok(types::PaymentsResponseData::SessionUpdateResponse { status }) => { + if status == SessionUpdateStatus::Success { + ( + Some( + storage::PaymentAttemptUpdate::IncrementalAuthorizationAmountUpdate { + amount: total_amount, + amount_capturable: total_amount, + }, + ), + Some( + storage::PaymentIntentUpdate::IncrementalAuthorizationAmountUpdate { + amount: MinorUnit::new(pmt_amount), + }, + ), + ) + } else { + (None, None) + } + } + _ => Err(errors::ApiErrorResponse::InternalServerError) + .attach_printable("unexpected response in session_update flow")?, + }; + let _shipping_address = payment_data.address.get_shipping(); let _amount = payment_data.amount; diff --git a/crates/router/src/core/payments/operations/payment_session.rs b/crates/router/src/core/payments/operations/payment_session.rs index 371b028154e1..e1bf2ddb185d 100644 --- a/crates/router/src/core/payments/operations/payment_session.rs +++ b/crates/router/src/core/payments/operations/payment_session.rs @@ -205,6 +205,7 @@ impl GetTracker, api::PaymentsSessionRequest> authentication: None, recurring_details: None, poll_config: None, + shipping_details: None, }; let get_trackers_response = operations::GetTrackerResponse { diff --git a/crates/router/src/core/payments/operations/payment_start.rs b/crates/router/src/core/payments/operations/payment_start.rs index ae9397aa8ecf..a0682248d5a2 100644 --- a/crates/router/src/core/payments/operations/payment_start.rs +++ b/crates/router/src/core/payments/operations/payment_start.rs @@ -190,6 +190,7 @@ impl GetTracker, api::PaymentsStartRequest> f authentication: None, recurring_details: None, poll_config: None, + shipping_details: None, }; let get_trackers_response = operations::GetTrackerResponse { diff --git a/crates/router/src/core/payments/operations/payment_status.rs b/crates/router/src/core/payments/operations/payment_status.rs index 587bdc8ef001..e17bbfd61282 100644 --- a/crates/router/src/core/payments/operations/payment_status.rs +++ b/crates/router/src/core/payments/operations/payment_status.rs @@ -466,6 +466,7 @@ async fn get_tracker_for_sync< authentication, recurring_details: None, poll_config: None, + shipping_details: None, }; let get_trackers_response = operations::GetTrackerResponse { diff --git a/crates/router/src/core/payments/operations/payment_update.rs b/crates/router/src/core/payments/operations/payment_update.rs index ea0580da5a5a..e43d4d4a6d03 100644 --- a/crates/router/src/core/payments/operations/payment_update.rs +++ b/crates/router/src/core/payments/operations/payment_update.rs @@ -473,6 +473,7 @@ impl GetTracker, api::PaymentsRequest> for Pa authentication: None, recurring_details, poll_config: None, + shipping_details: None, }; let get_trackers_response = operations::GetTrackerResponse { @@ -536,16 +537,13 @@ impl Domain for PaymentUpdate { let payment_attempt = payment_data.payment_attempt.clone(); // Derive this connector from business profile - let connector_data = api::TaxCalculateConnectorData::get_connector_by_name( - payment_attempt.connector.as_ref().unwrap(), - )?; + let connector_data = api::TaxCalculateConnectorData::get_connector_by_name("klarna")?; let router_data = core_utils::construct_payments_dynamic_tax_calculation_router_data( state, - &payment_intent, - &payment_attempt, merchant_account, key_store, + payment_data, // &customer, ) .await?; @@ -576,13 +574,12 @@ impl Domain for PaymentUpdate { reason: err.reason, })?; - payment_data - .payment_intent - .tax_details - .clone() - .map(|mut tax_details| { - tax_details.default.order_tax_amount = tax_response.order_tax_amount; - }); + payment_data.payment_intent.tax_details = Some(diesel_models::TaxDetails { + default: Some(diesel_models::DefaultTax { + order_tax_amount: tax_response.order_tax_amount.get_amount_as_i64(), + }), + pmt: None, + }); Ok(()) } 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 31883042eca1..7048645e65f4 100644 --- a/crates/router/src/core/payments/operations/payments_incremental_authorization.rs +++ b/crates/router/src/core/payments/operations/payments_incremental_authorization.rs @@ -158,6 +158,7 @@ impl authentication: None, recurring_details: None, poll_config: None, + shipping_details: None, }; let get_trackers_response = operations::GetTrackerResponse { diff --git a/crates/router/src/core/payments/operations/tax_calculation.rs b/crates/router/src/core/payments/operations/tax_calculation.rs index fae703acb5e2..3ba3560c01e9 100644 --- a/crates/router/src/core/payments/operations/tax_calculation.rs +++ b/crates/router/src/core/payments/operations/tax_calculation.rs @@ -58,7 +58,7 @@ impl GetTracker, api::PaymentsDynamicTaxCalcu let merchant_id = merchant_account.get_id(); let storage_scheme = merchant_account.storage_scheme; - let payment_intent = db + let mut payment_intent = db .find_payment_intent_by_payment_id_merchant_id( &state.into(), &payment_id, @@ -94,18 +94,63 @@ impl GetTracker, api::PaymentsDynamicTaxCalcu let amount = payment_attempt.get_total_amount().into(); - let shipping_address = helpers::create_or_update_address_for_payment_by_request( + // payment_intent.order_details = request + // .get_order_details_as_value() + // .change_context(errors::ApiErrorResponse::InternalServerError) + // .attach_printable("Failed to convert order details to value")? + // .or(payment_intent.order_details); + + // let shipping_address = helpers::create_or_update_address_for_payment_by_request( + // state, + // Some(&request.shipping), + // payment_intent.shipping_address_id.as_deref(), + // merchant_id, + // payment_intent.customer_id.as_ref(), + // key_store, + // &payment_intent.payment_id, + // merchant_account.storage_scheme, + // ) + // .await?; + + + + let shipping_address = helpers::get_address_by_id( state, - Some(&request.shipping), - payment_intent.shipping_address_id.as_deref(), + payment_intent.shipping_address_id.clone(), + key_store, + &payment_intent.payment_id, merchant_id, - payment_intent.customer_id.as_ref(), + merchant_account.storage_scheme, + ) + .await?; + println!("shipping_address: {:?}", shipping_address); + + // let billing_address = helpers::create_or_find_address_for_payment_by_request( + // &state, + // None, + // payment_intent.billing_address_id.as_deref(), + // merchant_id, + // payment_intent.customer_id.as_ref(), + // &key_store, + // &payment_intent.payment_id, + // storage_scheme, + // ) + // .await?; + + // println!("billing_address: {:?}", billing_address); + + let billing_address = helpers::get_address_by_id( + state, + payment_intent.billing_address_id.clone(), key_store, &payment_intent.payment_id, + merchant_id, merchant_account.storage_scheme, ) .await?; + // println!("billing: {:?}", billing); + let profile_id = payment_intent .profile_id .as_ref() @@ -135,7 +180,7 @@ impl GetTracker, api::PaymentsDynamicTaxCalcu setup_mandate: None, address: payments::PaymentAddress::new( shipping_address.as_ref().map(From::from), - None, + billing_address.as_ref().map(From::from), None, business_profile.use_billing_as_payment_method_billing, ), @@ -163,6 +208,7 @@ impl GetTracker, api::PaymentsDynamicTaxCalcu authentication: None, recurring_details: None, poll_config: None, + shipping_details: Some(request.shipping.clone()), }; let get_trackers_response = operations::GetTrackerResponse { operation: Box::new(self), @@ -203,13 +249,14 @@ impl Domain state: &SessionState, // key_manager_state: &common_utils::types::keymanager::KeyManagerState, payment_data: &mut PaymentData, - _should_continue_confirm_transaction: &mut bool, + should_continue_confirm_transaction: &mut bool, _connector_call_type: &ConnectorCallType, // _merchant_account: &storage::BusinessProfile, key_store: &domain::MerchantKeyStore, // storage_scheme: storage_enums::MerchantStorageScheme, merchant_account: &domain::MerchantAccount, ) -> errors::CustomResult<(), errors::ApiErrorResponse> { + *should_continue_confirm_transaction = false; // let db = state.store.as_ref(); let payment_intent = payment_data.payment_intent.clone(); @@ -218,16 +265,13 @@ impl Domain let payment_attempt = payment_data.payment_attempt.clone(); // Derive this connector from business profile - let connector_data = api::TaxCalculateConnectorData::get_connector_by_name( - payment_attempt.connector.as_ref().unwrap(), - )?; + let connector_data = api::TaxCalculateConnectorData::get_connector_by_name("taxjar")?; let router_data = core_utils::construct_payments_dynamic_tax_calculation_router_data( state, - &payment_intent, - &payment_attempt, merchant_account, key_store, + payment_data, // &customer, ) .await?; @@ -247,6 +291,8 @@ impl Domain .await .change_context(errors::ApiErrorResponse::InternalServerError)?; + println!("response_core: {:?}", response); + let tax_response = response .response @@ -258,15 +304,31 @@ impl Domain reason: err.reason, })?; - payment_data - .payment_intent - .tax_details - .clone() - .map(|tax_details| { - tax_details.pmt.map(|mut pmt| { - pmt.order_tax_amount = tax_response.order_tax_amount; - }); - }); + println!("tax_response: {:?}", tax_response); + + // payment_data + // .payment_intent + // .tax_details + // .clone() + // .map(|tax_details| { + // tax_details.pmt.map(|mut pmt| { + // pmt.order_tax_amount = tax_response.order_tax_amount; + // }); + // }); + payment_data.payment_intent.tax_details = Some(diesel_models::TaxDetails { + pmt: Some(diesel_models::PmtTax { + order_tax_amount: tax_response.order_tax_amount.get_amount_as_i64(), + pmt: "klarna".to_string(), + }), + default: None, + }); + // .tax_details + // .clone() + // .map(|tax_details| { + // tax_details.pmt.map(|mut pmt| { + // pmt.order_tax_amount = tax_response.order_tax_amount; + // }); + // }); Ok(()) } @@ -338,6 +400,10 @@ impl UpdateTracker, api::PaymentsDynamicTaxCalculati tax_details: payment_data.payment_intent.tax_details.clone().ok_or(errors::ApiErrorResponse::InternalServerError)? }; + let tax_details = payment_data.payment_intent.tax_details.clone().ok_or(errors::ApiErrorResponse::InternalServerError)?; + + println!("update_trackers tax_details : {:?}", tax_details); + let db = &*state.store; let payment_intent = payment_data.payment_intent.clone(); diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs index cafe8f07eac1..e6f8f772d9b0 100644 --- a/crates/router/src/core/payments/transformers.rs +++ b/crates/router/src/core/payments/transformers.rs @@ -51,7 +51,7 @@ where error_stack::Report: From<>>::Error>, { - let (payment_method, router_data); + // let (payment_method, router_data); fp_utils::when(merchant_connector_account.is_disabled(), || { Err(errors::ApiErrorResponse::MerchantConnectorAccountDisabled) @@ -65,11 +65,11 @@ where .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Failed while parsing value for ConnectorAuthType")?; - payment_method = payment_data - .payment_attempt - .payment_method - .or(payment_data.payment_attempt.payment_method) - .get_required_value("payment_method_type")?; + // payment_method = payment_data + // .payment_attempt + // .payment_method + // .or(payment_data.payment_attempt.payment_method) + // .get_required_value("payment_method_type")?; let resource_id = match payment_data .payment_attempt @@ -120,7 +120,9 @@ where payment_data.address }; - router_data = types::RouterData { + println!("unified_address {:?}", unified_address); + + let router_data = types::RouterData { flow: PhantomData, merchant_id: merchant_account.get_id().clone(), customer_id, @@ -128,7 +130,7 @@ where payment_id: payment_data.payment_attempt.payment_id.clone(), attempt_id: payment_data.payment_attempt.attempt_id.clone(), status: payment_data.payment_attempt.status, - payment_method, + payment_method: diesel_models::enums::PaymentMethod::default(), connector_auth_type: auth_type, description: payment_data.payment_intent.description.clone(), return_url: payment_data.payment_intent.return_url.clone(), @@ -1789,6 +1791,11 @@ impl TryFrom> for types::SessionUpdateDat .and_then(|tax_details| tax_details.pmt.map(|pmt| pmt.order_tax_amount)) .unwrap_or(0); let amount = MinorUnit::from(payment_data.amount); + + println!("additional_data_order_tax_amount: {:?}", order_tax_amount); + + println!("additional_data_amount: {:?}", amount.get_amount_as_i64()); + Ok(Self { net_amount: (amount.get_amount_as_i64()) + order_tax_amount, //need to change after we move to connector module order_tax_amount, diff --git a/crates/router/src/core/utils.rs b/crates/router/src/core/utils.rs index b829dc494df9..ece6d09a8c45 100644 --- a/crates/router/src/core/utils.rs +++ b/crates/router/src/core/utils.rs @@ -29,7 +29,10 @@ use crate::core::payments; use crate::{ configs::Settings, consts, - core::errors::{self, RouterResult, StorageErrorExt}, + core::{ + errors::{self, RouterResult, StorageErrorExt}, + payments::PaymentData, + }, db::StorageInterface, routes::SessionState, types::{ @@ -830,14 +833,16 @@ pub async fn construct_upload_file_router_data<'a>( Ok(router_data) } -pub async fn construct_payments_dynamic_tax_calculation_router_data<'a>( +pub async fn construct_payments_dynamic_tax_calculation_router_data<'a, F: Clone>( state: &'a SessionState, - payment_intent: &'a storage::PaymentIntent, - payment_attempt: &storage::PaymentAttempt, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, + payment_data: &mut PaymentData, // customer: &'a Option, ) -> RouterResult { + let payment_intent = &payment_data.payment_intent.clone(); + let payment_attempt = &payment_data.payment_attempt.clone(); + let key_manager_state = &state.into(); let profile_id = get_profile_id_from_business_details( key_manager_state, @@ -859,7 +864,9 @@ pub async fn construct_payments_dynamic_tax_calculation_router_data<'a>( None, key_store, &profile_id, - payment_attempt.connector.as_ref().unwrap(), + // How do we derive the connector name? + "taxjar", + // Take this from business profile payment_attempt.merchant_connector_id.as_ref(), ) .await?; @@ -872,41 +879,40 @@ pub async fn construct_payments_dynamic_tax_calculation_router_data<'a>( .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Failed while parsing value for ConnectorAuthType")?; - let shipping: Address = payment_intent - .shipping_details + + let add = payment_data.address.clone(); + // println!("$$$$$$ {:?}", add); + + let shipping_address = payment_data.shipping_details.clone().ok_or(errors::ApiErrorResponse::InternalServerError).attach_printable("Missing shipping_details")?; + + println!("$$$$$$shipping_address {:?}", shipping_address); + + let order_details: Option> = payment_intent + .order_details .clone() - .ok_or(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Missing payment_intent.shipping_details")? - .into_inner() - .expose() - .parse_value("Address") - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Failed while parsing value for shipping_details")?; - - let order: Option, _>> = - payment_intent.order_details.clone().map(|o| { - o.into_iter() - .map(|order| { - order - .expose() + .map(|order_details| { + order_details + .iter() + .map(|data| { + data.to_owned() .parse_value("OrderDetailsWithAmount") - .change_context(errors::ApiErrorResponse::InternalServerError) + .change_context(errors::ApiErrorResponse::InvalidDataValue { + field_name: "OrderDetailsWithAmount", + }) + .attach_printable("Unable to parse OrderDetailsWithAmount") }) - .collect() - }); - let order_details = order.map_or(Ok(None), |r| r.map(Some))?; + .collect::, _>>() + }) + .transpose()?; + + println!("$$$$$$order2 {:?}", order_details); let router_data = types::RouterData { flow: PhantomData, merchant_id: merchant_account.get_id().to_owned(), customer_id: payment_intent.customer_id.to_owned(), connector_customer: None, - connector: payment_attempt - .connector - .clone() - .clone() - .ok_or(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Missing connector")?, + connector: "taxjar".to_string(), payment_id: payment_attempt.payment_id.clone(), attempt_id: payment_attempt.attempt_id.clone(), status: payment_attempt.status, @@ -914,7 +920,7 @@ pub async fn construct_payments_dynamic_tax_calculation_router_data<'a>( connector_auth_type, description: payment_intent.description.clone(), return_url: payment_intent.return_url.clone(), - address: PaymentAddress::default(), + address: add, auth_type: payment_attempt.authentication_type.unwrap_or_default(), connector_meta_data: None, connector_wallets_details: None, @@ -935,11 +941,11 @@ pub async fn construct_payments_dynamic_tax_calculation_router_data<'a>( .shipping_cost .ok_or(errors::ApiErrorResponse::InternalServerError) .attach_printable("Missing shipping_cost")?, - shipping, order_details, currency: payment_intent .currency .ok_or(errors::ApiErrorResponse::InternalServerError)?, + shipping_address, }, response: Err(ErrorResponse::default()), connector_request_reference_id: get_connector_request_reference_id( @@ -963,6 +969,7 @@ pub async fn construct_payments_dynamic_tax_calculation_router_data<'a>( minor_amount_captured: payment_intent.amount_captured, integrity_check: Ok(()), }; + println!("$$$$$$ {:?}", router_data); Ok(router_data) } diff --git a/crates/router/src/routes/payments.rs b/crates/router/src/routes/payments.rs index 2bb76a9fd39d..6be287676dd0 100644 --- a/crates/router/src/routes/payments.rs +++ b/crates/router/src/routes/payments.rs @@ -609,9 +609,14 @@ pub async fn payments_dynamic_tax_calculation( state: web::Data, req: actix_web::HttpRequest, json_payload: web::Json, + path: web::Path, ) -> impl Responder { let flow = Flow::PaymentsDynamicTaxCalculation; - let payload = json_payload.into_inner(); + let payment_id = path.into_inner(); + let payload = payment_types::PaymentsDynamicTaxCalculationRequest { + payment_id, + ..json_payload.into_inner() + }; let header_payload = match HeaderPayload::foreign_try_from(req.headers()) { Ok(headers) => headers, Err(error) => { diff --git a/crates/router/src/types/api.rs b/crates/router/src/types/api.rs index d1c4c437fd13..383c771099a3 100644 --- a/crates/router/src/types/api.rs +++ b/crates/router/src/types/api.rs @@ -452,7 +452,6 @@ impl ConnectorData { enums::Connector::Stripe => { Ok(ConnectorEnum::Old(Box::new(connector::Stripe::new()))) } - // enums::Connector::Taxjar => Ok(ConnectorEnum::Old(Box::new(connector::Taxjar))), enums::Connector::Wise => Ok(ConnectorEnum::Old(Box::new(&connector::Wise))), enums::Connector::Worldline => { Ok(ConnectorEnum::Old(Box::new(&connector::Worldline))) @@ -494,7 +493,8 @@ impl ConnectorData { enums::Connector::Signifyd | enums::Connector::Riskified | enums::Connector::Gpayments - | enums::Connector::Threedsecureio => { + | enums::Connector::Threedsecureio + | enums::Connector::Taxjar => { Err(report!(errors::ConnectorError::InvalidConnectorName) .attach_printable(format!("invalid connector name: {connector_name}"))) .change_context(errors::ApiErrorResponse::InternalServerError) @@ -607,7 +607,7 @@ impl TaxCalculateConnectorData { connector_name: enums::TaxCalculatorConnectors, ) -> CustomResult { match connector_name { - enums::TaxCalculatorConnectors::TaxJar => { + enums::TaxCalculatorConnectors::Taxjar => { Ok(ConnectorEnum::Old(Box::new(connector::Taxjar::new()))) } } diff --git a/crates/router/src/types/transformers.rs b/crates/router/src/types/transformers.rs index 67af63b154e0..abfae9d6cbd3 100644 --- a/crates/router/src/types/transformers.rs +++ b/crates/router/src/types/transformers.rs @@ -296,7 +296,6 @@ impl ForeignTryFrom for common_enums::RoutableConnectors { api_enums::Connector::Square => Self::Square, api_enums::Connector::Stax => Self::Stax, api_enums::Connector::Stripe => Self::Stripe, - // api_enums::Connector::Taxjar => Self::Taxjar, api_enums::Connector::Trustpay => Self::Trustpay, api_enums::Connector::Tsys => Self::Tsys, api_enums::Connector::Volt => Self::Volt, @@ -321,7 +320,7 @@ impl ForeignTryFrom for common_enums::RoutableConnectors { api_enums::Connector::DummyConnector6 => Self::DummyConnector6, #[cfg(feature = "dummy_connector")] api_enums::Connector::DummyConnector7 => Self::DummyConnector7, - api_enums::Connector::Threedsecureio => { + api_enums::Connector::Threedsecureio | api_enums::Connector::Taxjar => { Err(common_utils::errors::ValidationError::InvalidValue { message: "threedsecureio is not a routable connector".to_string(), })? diff --git a/crates/storage_impl/src/payments/payment_attempt.rs b/crates/storage_impl/src/payments/payment_attempt.rs index 03a9ac6e454c..ebe8039ad514 100644 --- a/crates/storage_impl/src/payments/payment_attempt.rs +++ b/crates/storage_impl/src/payments/payment_attempt.rs @@ -2276,6 +2276,10 @@ impl DataModelExt for PaymentAttemptUpdate { unified_code, unified_message, }, + // DieselPaymentAttemptUpdate::SessionUpdate { amount, order_tax_amount, payment_method_shipping_address_id } => Self::SessionUpdate { + // amount: MinorUnit::new(amount), + // order_tax_amount: MinorUnit::new(order_tax_amount), + // payment_method_shipping_address_id } } } } From 9f8589db25c20757ec332b950809ab588437e10f Mon Sep 17 00:00:00 2001 From: swangi-kumari Date: Tue, 27 Aug 2024 15:05:40 +0530 Subject: [PATCH 17/39] refactor: formatting --- .../src/connectors/taxjar.rs | 2 +- .../src/connectors/taxjar/transformers.rs | 21 +++++--- .../payments/operations/payment_response.rs | 2 +- .../payments/operations/tax_calculation.rs | 50 ++++++++++--------- .../router/src/core/payments/transformers.rs | 4 +- crates/router/src/core/utils.rs | 7 ++- 6 files changed, 50 insertions(+), 36 deletions(-) diff --git a/crates/hyperswitch_connectors/src/connectors/taxjar.rs b/crates/hyperswitch_connectors/src/connectors/taxjar.rs index bcb7d62889a1..ce929bad3ae1 100644 --- a/crates/hyperswitch_connectors/src/connectors/taxjar.rs +++ b/crates/hyperswitch_connectors/src/connectors/taxjar.rs @@ -197,7 +197,7 @@ impl ConnectorIntegration> // println!("$$swangi{:?}", shipping); let currency = item.router_data.request.currency; let currency_unit = &api::CurrencyUnit::Base; - let shipping = &item.router_data.request.shipping_address.address.clone().ok_or(errors::ConnectorError::MissingRequiredField { field_name: "address" })?; - + let shipping = &item + .router_data + .request + .shipping_address + .address + .clone() + .ok_or(errors::ConnectorError::MissingRequiredField { + field_name: "address", + })?; println!("$$shipping123{:?}", shipping); - match request.order_details.clone() { Some(order_details) => Ok(Self { from_country: item.router_data.get_billing_country()?, @@ -109,7 +115,10 @@ impl TryFrom<&TaxjarRouterData<&types::PaymentsTaxCalculationRouterData>> id: line_item.product_id.clone(), quantity: Some(line_item.quantity), product_tax_code: line_item.product_tax_code.clone(), - unit_price: Some(FloatMajorUnit::new(utils::get_amount_as_f64(currency_unit, line_item.amount, currency).unwrap())), + unit_price: Some(FloatMajorUnit::new( + utils::get_amount_as_f64(currency_unit, line_item.amount, currency) + .unwrap(), + )), }) .collect(), }), @@ -184,7 +193,7 @@ impl Ok(Self { response: Ok(TaxCalculationResponseData { order_tax_amount: calculated_tax, - net_amount: (total_amount + calculated_tax), + net_amount: (total_amount + calculated_tax), shipping_address: None, }), ..item.data diff --git a/crates/router/src/core/payments/operations/payment_response.rs b/crates/router/src/core/payments/operations/payment_response.rs index 595a76033d08..7f317e94f95a 100644 --- a/crates/router/src/core/payments/operations/payment_response.rs +++ b/crates/router/src/core/payments/operations/payment_response.rs @@ -557,7 +557,7 @@ impl PostUpdateTracker, types::SessionUpdateData> fo .attach_printable("missing tax_details in payment_intent") })?; - println!("session_update_details: {:?}", session_update_details); + println!("session_update_details: {:?}", session_update_details); let pmt_amount = session_update_details .pmt diff --git a/crates/router/src/core/payments/operations/tax_calculation.rs b/crates/router/src/core/payments/operations/tax_calculation.rs index 3ba3560c01e9..e85327fbf3b9 100644 --- a/crates/router/src/core/payments/operations/tax_calculation.rs +++ b/crates/router/src/core/payments/operations/tax_calculation.rs @@ -112,9 +112,7 @@ impl GetTracker, api::PaymentsDynamicTaxCalcu // ) // .await?; - - - let shipping_address = helpers::get_address_by_id( + let shipping_address = helpers::get_address_by_id( state, payment_intent.shipping_address_id.clone(), key_store, @@ -123,23 +121,23 @@ impl GetTracker, api::PaymentsDynamicTaxCalcu merchant_account.storage_scheme, ) .await?; - println!("shipping_address: {:?}", shipping_address); - - // let billing_address = helpers::create_or_find_address_for_payment_by_request( - // &state, - // None, - // payment_intent.billing_address_id.as_deref(), - // merchant_id, - // payment_intent.customer_id.as_ref(), - // &key_store, - // &payment_intent.payment_id, - // storage_scheme, - // ) - // .await?; - - // println!("billing_address: {:?}", billing_address); - - let billing_address = helpers::get_address_by_id( + println!("shipping_address: {:?}", shipping_address); + + // let billing_address = helpers::create_or_find_address_for_payment_by_request( + // &state, + // None, + // payment_intent.billing_address_id.as_deref(), + // merchant_id, + // payment_intent.customer_id.as_ref(), + // &key_store, + // &payment_intent.payment_id, + // storage_scheme, + // ) + // .await?; + + // println!("billing_address: {:?}", billing_address); + + let billing_address = helpers::get_address_by_id( state, payment_intent.billing_address_id.clone(), key_store, @@ -149,7 +147,7 @@ impl GetTracker, api::PaymentsDynamicTaxCalcu ) .await?; - // println!("billing: {:?}", billing); + // println!("billing: {:?}", billing); let profile_id = payment_intent .profile_id @@ -291,7 +289,7 @@ impl Domain .await .change_context(errors::ApiErrorResponse::InternalServerError)?; - println!("response_core: {:?}", response); + println!("response_core: {:?}", response); let tax_response = response @@ -304,7 +302,7 @@ impl Domain reason: err.reason, })?; - println!("tax_response: {:?}", tax_response); + println!("tax_response: {:?}", tax_response); // payment_data // .payment_intent @@ -400,7 +398,11 @@ impl UpdateTracker, api::PaymentsDynamicTaxCalculati tax_details: payment_data.payment_intent.tax_details.clone().ok_or(errors::ApiErrorResponse::InternalServerError)? }; - let tax_details = payment_data.payment_intent.tax_details.clone().ok_or(errors::ApiErrorResponse::InternalServerError)?; + let tax_details = payment_data + .payment_intent + .tax_details + .clone() + .ok_or(errors::ApiErrorResponse::InternalServerError)?; println!("update_trackers tax_details : {:?}", tax_details); diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs index e6f8f772d9b0..41ff46a3baea 100644 --- a/crates/router/src/core/payments/transformers.rs +++ b/crates/router/src/core/payments/transformers.rs @@ -120,7 +120,7 @@ where payment_data.address }; - println!("unified_address {:?}", unified_address); + println!("unified_address {:?}", unified_address); let router_data = types::RouterData { flow: PhantomData, @@ -1792,7 +1792,7 @@ impl TryFrom> for types::SessionUpdateDat .unwrap_or(0); let amount = MinorUnit::from(payment_data.amount); - println!("additional_data_order_tax_amount: {:?}", order_tax_amount); + println!("additional_data_order_tax_amount: {:?}", order_tax_amount); println!("additional_data_amount: {:?}", amount.get_amount_as_i64()); diff --git a/crates/router/src/core/utils.rs b/crates/router/src/core/utils.rs index ece6d09a8c45..cbc432bf22fb 100644 --- a/crates/router/src/core/utils.rs +++ b/crates/router/src/core/utils.rs @@ -879,11 +879,14 @@ pub async fn construct_payments_dynamic_tax_calculation_router_data<'a, F: Clone .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Failed while parsing value for ConnectorAuthType")?; - let add = payment_data.address.clone(); // println!("$$$$$$ {:?}", add); - let shipping_address = payment_data.shipping_details.clone().ok_or(errors::ApiErrorResponse::InternalServerError).attach_printable("Missing shipping_details")?; + let shipping_address = payment_data + .shipping_details + .clone() + .ok_or(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Missing shipping_details")?; println!("$$$$$$shipping_address {:?}", shipping_address); From 541af039a8e9bf522389c014c64fc48bbfb6386d Mon Sep 17 00:00:00 2001 From: swangi-kumari Date: Tue, 27 Aug 2024 17:15:24 +0530 Subject: [PATCH 18/39] refactor: add shipping_addres_id --- crates/diesel_models/src/payment_intent.rs | 10 ++++-- .../src/payments/payment_intent.rs | 18 +++++++--- .../payments/operations/tax_calculation.rs | 34 +++++++++++++++---- .../router/src/core/payments/transformers.rs | 7 ++-- 4 files changed, 53 insertions(+), 16 deletions(-) diff --git a/crates/diesel_models/src/payment_intent.rs b/crates/diesel_models/src/payment_intent.rs index 62a94c6bbbea..8c6883e9ec20 100644 --- a/crates/diesel_models/src/payment_intent.rs +++ b/crates/diesel_models/src/payment_intent.rs @@ -293,6 +293,7 @@ pub enum PaymentIntentUpdate { }, TaxCalculationUpdate { tax_details: TaxDetails, + shipping_address_id: Option, }, } @@ -1089,9 +1090,13 @@ impl From for PaymentIntentUpdateInternal { is_payment_processor_token_flow: None, tax_details: None, }, - PaymentIntentUpdate::TaxCalculationUpdate { tax_details } => Self { - shipping_address_id: None, + PaymentIntentUpdate::TaxCalculationUpdate { + tax_details, + shipping_address_id, + } => Self { + shipping_address_id, amount: None, + tax_details: Some(tax_details), currency: None, status: None, amount_captured: None, @@ -1125,7 +1130,6 @@ impl From for PaymentIntentUpdateInternal { merchant_order_reference_id: None, shipping_details: None, is_payment_processor_token_flow: None, - tax_details: Some(tax_details), }, } } diff --git a/crates/hyperswitch_domain_models/src/payments/payment_intent.rs b/crates/hyperswitch_domain_models/src/payments/payment_intent.rs index 00bf04d2ea6a..e7d0931d776a 100644 --- a/crates/hyperswitch_domain_models/src/payments/payment_intent.rs +++ b/crates/hyperswitch_domain_models/src/payments/payment_intent.rs @@ -259,6 +259,8 @@ pub enum PaymentIntentUpdate { }, TaxCalculationUpdate { tax_details: diesel_models::TaxDetails, + // amount: MinorUnit, + shipping_address_id: Option, }, } @@ -485,8 +487,12 @@ impl From for PaymentIntentUpdateInternal { updated_by, ..Default::default() }, - PaymentIntentUpdate::TaxCalculationUpdate { tax_details } => Self { + PaymentIntentUpdate::TaxCalculationUpdate { + tax_details, + shipping_address_id, + } => Self { tax_details, + shipping_address_id, ..Default::default() }, } @@ -653,9 +659,13 @@ impl From for DieselPaymentIntentUpdate { PaymentIntentUpdate::ManualUpdate { status, updated_by } => { Self::ManualUpdate { status, updated_by } } - PaymentIntentUpdate::TaxCalculationUpdate { tax_details } => { - Self::TaxCalculationUpdate { tax_details } - } + PaymentIntentUpdate::TaxCalculationUpdate { + tax_details, + shipping_address_id, + } => Self::TaxCalculationUpdate { + tax_details, + shipping_address_id, + }, } } } diff --git a/crates/router/src/core/payments/operations/tax_calculation.rs b/crates/router/src/core/payments/operations/tax_calculation.rs index e85327fbf3b9..71d99678ca89 100644 --- a/crates/router/src/core/payments/operations/tax_calculation.rs +++ b/crates/router/src/core/payments/operations/tax_calculation.rs @@ -2,7 +2,7 @@ use std::marker::PhantomData; use api_models::enums::FrmSuggestion; use async_trait::async_trait; -use common_utils::types::keymanager::KeyManagerState; +use common_utils::types::{keymanager::KeyManagerState, MinorUnit}; use error_stack::ResultExt; use router_derive::PaymentOperation; use router_env::{instrument, tracing}; @@ -394,17 +394,37 @@ impl UpdateTracker, api::PaymentsDynamicTaxCalculati where F: 'b + Send, { - let payment_intent_update = hyperswitch_domain_models::payments::payment_intent::PaymentIntentUpdate::TaxCalculationUpdate { - tax_details: payment_data.payment_intent.tax_details.clone().ok_or(errors::ApiErrorResponse::InternalServerError)? - }; - - let tax_details = payment_data + let session_update_details = payment_data .payment_intent .tax_details .clone() .ok_or(errors::ApiErrorResponse::InternalServerError)?; - println!("update_trackers tax_details : {:?}", tax_details); + println!("update_trackers tax_details : {:?}", session_update_details); + + let calculated_tax_amount = session_update_details + .pmt + .clone() + .map(|pmt| pmt.order_tax_amount) + .ok_or(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Missing tax_details.order_tax_amount")?; + + println!("calculated_tax_amount: {:?}", calculated_tax_amount); + + // let shipping_cost = (payment_data.payment_intent.shipping_cost.clone().ok_or(errors::ApiErrorResponse::InternalServerError).attach_printable("missing"))?; + + // let net_amount = payment_data.amount.into() + MinorUnit::new(calculated_tax_amount) + payment_data.payment_intent.shipping_cost; + // println!("net_amount: {:?}", net_amount); + + let payment_intent_update = hyperswitch_domain_models::payments::payment_intent::PaymentIntentUpdate::TaxCalculationUpdate { + tax_details: payment_data.payment_intent.tax_details.clone().ok_or(errors::ApiErrorResponse::InternalServerError)?, + shipping_address_id: payment_data.payment_intent.shipping_address_id.clone() + }; + + print!( + "update_trackers payment_intent_update : {:?}", + payment_intent_update + ); let db = &*state.store; let payment_intent = payment_data.payment_intent.clone(); diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs index 41ff46a3baea..b2b3b7499d9f 100644 --- a/crates/router/src/core/payments/transformers.rs +++ b/crates/router/src/core/payments/transformers.rs @@ -6,7 +6,7 @@ use api_models::payments::{ }; use common_enums::RequestIncrementalAuthorization; use common_utils::{consts::X_HS_LATENCY, fp_utils, pii::Email, types::MinorUnit}; -use diesel_models::ephemeral_key; +use diesel_models::{ephemeral_key, schema::payment_intent::tax_details}; use error_stack::{report, ResultExt}; use hyperswitch_domain_models::{payments::payment_intent::CustomerData, router_request_types}; use masking::{ExposeInterface, Maskable, PeekInterface, Secret}; @@ -489,6 +489,9 @@ where _external_latency: Option, _is_latency_header_enabled: Option, ) -> RouterResponse { + // let amount = MinorUnit::from(payment_data.amount); + // let shipping_cost = payment_data.payment_intent.shipping_cost; + // let order_tax_amount = MinorUnit::from(payment_data.payment_intent.tax_details.clone().and_then(|tax|tax.pmt.map(|a|a.order_tax_amount))); Ok(services::ApplicationResponse::JsonWithHeaders(( Self { // order_tax_amount: payment_data.amount, @@ -1788,7 +1791,7 @@ impl TryFrom> for types::SessionUpdateDat .payment_intent .tax_details .clone() - .and_then(|tax_details| tax_details.pmt.map(|pmt| pmt.order_tax_amount)) + .and_then(|tax| tax.pmt.map(|pmt| pmt.order_tax_amount)) .unwrap_or(0); let amount = MinorUnit::from(payment_data.amount); From 1533be12eb4f7ee11681ede355bfa0875d9fae4b Mon Sep 17 00:00:00 2001 From: swangi-kumari Date: Wed, 28 Aug 2024 03:07:24 +0530 Subject: [PATCH 19/39] refactor: update shipping add id and populate net amount in response --- Cargo.lock | 1 + crates/common_enums/src/enums.rs | 2 + crates/diesel_models/Cargo.toml | 1 + crates/diesel_models/src/payment_intent.rs | 7 +- .../src/connectors/taxjar/transformers.rs | 8 +- .../src/default_implementations.rs | 6 +- .../src/router_request_types.rs | 4 +- crates/router/src/core/admin.rs | 2 +- crates/router/src/core/payments.rs | 9 +- crates/router/src/core/payments/operations.rs | 3 +- .../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 | 2 +- .../payments/operations/payment_create.rs | 40 ++++-- .../payments/operations/payment_reject.rs | 2 +- .../payments/operations/payment_response.rs | 4 +- .../payments/operations/payment_session.rs | 2 +- .../core/payments/operations/payment_start.rs | 2 +- .../payments/operations/payment_status.rs | 2 +- .../payments/operations/payment_update.rs | 36 ++++- .../payments_incremental_authorization.rs | 2 +- .../payments/operations/tax_calculation.rs | 124 +++++++++--------- .../router/src/core/payments/transformers.rs | 40 +++--- crates/router/src/core/utils.rs | 9 +- .../down.sql | 2 + .../up.sql | 3 + 28 files changed, 198 insertions(+), 123 deletions(-) create mode 100644 migrations/2024-08-27-190822_add_tax_processor_in_connector_type/down.sql create mode 100644 migrations/2024-08-27-190822_add_tax_processor_in_connector_type/up.sql diff --git a/Cargo.lock b/Cargo.lock index 4a37b597d304..94f51b597005 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2711,6 +2711,7 @@ dependencies = [ name = "diesel_models" version = "0.1.0" dependencies = [ + "api_models", "async-bb8-diesel", "common_enums", "common_utils", diff --git a/crates/common_enums/src/enums.rs b/crates/common_enums/src/enums.rs index c332cbf33070..9f8a8e883060 100644 --- a/crates/common_enums/src/enums.rs +++ b/crates/common_enums/src/enums.rs @@ -509,6 +509,8 @@ pub enum ConnectorType { PaymentMethodAuth, /// 3DS Authentication Service Providers AuthenticationProcessor, + /// Tax Calculation Processor + TaxProcessor, } #[derive(Debug, Eq, PartialEq)] diff --git a/crates/diesel_models/Cargo.toml b/crates/diesel_models/Cargo.toml index e95a39e0089d..344fb4b82aac 100644 --- a/crates/diesel_models/Cargo.toml +++ b/crates/diesel_models/Cargo.toml @@ -19,6 +19,7 @@ merchant_connector_account_v2 = [] payment_v2 = [] [dependencies] +api_models = { version = "0.1.0", path = "../api_models", package = "api_models" } async-bb8-diesel = { git = "https://github.com/jarnura/async-bb8-diesel", rev = "53b4ab901aab7635c8215fd1c2d542c8db443094" } diesel = { version = "2.2.3", features = ["postgres", "serde_json", "time", "64-column-tables"] } error-stack = "0.4.1" diff --git a/crates/diesel_models/src/payment_intent.rs b/crates/diesel_models/src/payment_intent.rs index 0971917e96bc..d4e3423a13da 100644 --- a/crates/diesel_models/src/payment_intent.rs +++ b/crates/diesel_models/src/payment_intent.rs @@ -1,3 +1,4 @@ +use api_models::enums; use common_enums::RequestIncrementalAuthorization; use common_utils::{encryption::Encryption, pii, types::MinorUnit}; use diesel::{AsChangeset, Identifiable, Insertable, Queryable, Selectable}; @@ -145,14 +146,14 @@ common_utils::impl_to_sql_from_sql_json!(TaxDetails); #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct PmtTax { - pub order_tax_amount: i64, - pub pmt: String, + pub order_tax_amount: MinorUnit, + pub pmt: enums::PaymentMethodType, // pub shipping_details: String, } #[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)] pub struct DefaultTax { - pub order_tax_amount: i64, + pub order_tax_amount: MinorUnit, // pub shipping_details: String, } diff --git a/crates/hyperswitch_connectors/src/connectors/taxjar/transformers.rs b/crates/hyperswitch_connectors/src/connectors/taxjar/transformers.rs index cff401cbb850..1be9b5747065 100644 --- a/crates/hyperswitch_connectors/src/connectors/taxjar/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/taxjar/transformers.rs @@ -1,20 +1,18 @@ use common_enums::enums; -use common_utils::types::{FloatMajorUnit, FloatMajorUnitForConnector, MinorUnit, StringMinorUnit}; +use common_utils::types::{FloatMajorUnit, FloatMajorUnitForConnector}; use error_stack::report; use hyperswitch_domain_models::{ router_data::{ConnectorAuthType, RouterData}, - router_flow_types::refunds::{Execute, RSync}, router_request_types::PaymentsTaxCalculationData, - router_response_types::{RefundsResponseData, TaxCalculationResponseData}, + router_response_types::TaxCalculationResponseData, types, - types::RefundsRouterData, }; use hyperswitch_interfaces::{api, errors}; use masking::Secret; use serde::{Deserialize, Serialize}; use crate::{ - types::{RefundsResponseRouterData, ResponseRouterData}, + types::ResponseRouterData, utils::{self, AddressDetailsData, RouterData as _}, }; diff --git a/crates/hyperswitch_connectors/src/default_implementations.rs b/crates/hyperswitch_connectors/src/default_implementations.rs index 0ad095c8b65d..b63a04b88458 100644 --- a/crates/hyperswitch_connectors/src/default_implementations.rs +++ b/crates/hyperswitch_connectors/src/default_implementations.rs @@ -119,7 +119,8 @@ default_imp_for_calculate_tax!( connectors::Fiserv, connectors::Fiservemea, connectors::Helcim, - connectors::Stax + connectors::Stax, + connectors::Novalnet ); macro_rules! default_imp_for_session_update { @@ -143,7 +144,8 @@ default_imp_for_session_update!( connectors::Fiservemea, connectors::Helcim, connectors::Stax, - connectors::Taxjar + connectors::Taxjar, + connectors::Novalnet ); use crate::connectors; diff --git a/crates/hyperswitch_domain_models/src/router_request_types.rs b/crates/hyperswitch_domain_models/src/router_request_types.rs index a575fb348ec0..8ec3e8e4ed17 100644 --- a/crates/hyperswitch_domain_models/src/router_request_types.rs +++ b/crates/hyperswitch_domain_models/src/router_request_types.rs @@ -807,8 +807,8 @@ pub struct PaymentsTaxCalculationData { #[derive(Debug, Clone, Default)] pub struct SessionUpdateData { - pub order_tax_amount: i64, - pub net_amount: i64, + pub order_tax_amount: MinorUnit, + pub net_amount: MinorUnit, } #[derive(Debug, Clone)] diff --git a/crates/router/src/core/admin.rs b/crates/router/src/core/admin.rs index 0a370bd17bed..3545b6264640 100644 --- a/crates/router/src/core/admin.rs +++ b/crates/router/src/core/admin.rs @@ -1827,7 +1827,7 @@ impl<'a> ConnectorTypeAndConnectorName<'a> { .into()); } } else if tax_connector.is_some() { - if self.connector_type != &api_enums::ConnectorType::FinOperations { + if self.connector_type != &api_enums::ConnectorType::TaxProcessor { return Err(errors::ApiErrorResponse::InvalidRequestData { message: "Invalid connector type given".to_string(), } diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs index ba70c3d2af08..56c49cc559b9 100644 --- a/crates/router/src/core/payments.rs +++ b/crates/router/src/core/payments.rs @@ -285,6 +285,7 @@ where &mut payment_data, &mut should_continue_transaction, &connector_details, + &business_profile, &key_store, &merchant_account, ) @@ -2781,7 +2782,13 @@ where pub authentication: Option, pub recurring_details: Option, pub poll_config: Option, - pub shipping_details: Option, + pub tax_data: Option, +} + +#[derive(Clone, serde::Serialize, Debug)] +pub struct TaxData { + pub shipping_details: api_models::payments::Address, + pub payment_method_type: enums::PaymentMethodType, } #[derive(Clone, serde::Serialize, Debug)] diff --git a/crates/router/src/core/payments/operations.rs b/crates/router/src/core/payments/operations.rs index 2c520b839534..c24956201670 100644 --- a/crates/router/src/core/payments/operations.rs +++ b/crates/router/src/core/payments/operations.rs @@ -184,10 +184,11 @@ pub trait Domain: Send + Sync { async fn payments_dynamic_tax_calculation<'a>( &'a self, _state: &SessionState, + // _key_manager_state: &common_utils::types::keymanager::KeyManagerState, _payment_data: &mut PaymentData, _should_continue_confirm_transaction: &mut bool, _connector_call_type: &ConnectorCallType, - // _merchant_account: &storage::BusinessProfile, + _business_profile: &domain::BusinessProfile, _key_store: &domain::MerchantKeyStore, // _storage_scheme: enums::MerchantStorageScheme, _merchant_account: &domain::MerchantAccount, diff --git a/crates/router/src/core/payments/operations/payment_approve.rs b/crates/router/src/core/payments/operations/payment_approve.rs index 99434a9d89da..4b0b01717454 100644 --- a/crates/router/src/core/payments/operations/payment_approve.rs +++ b/crates/router/src/core/payments/operations/payment_approve.rs @@ -182,7 +182,7 @@ impl GetTracker, api::PaymentsCaptureRequest> authentication: None, recurring_details: None, poll_config: None, - shipping_details: None, + tax_data: None, }; let get_trackers_response = operations::GetTrackerResponse { diff --git a/crates/router/src/core/payments/operations/payment_cancel.rs b/crates/router/src/core/payments/operations/payment_cancel.rs index 07f75ed7a22d..365548b7c5e7 100644 --- a/crates/router/src/core/payments/operations/payment_cancel.rs +++ b/crates/router/src/core/payments/operations/payment_cancel.rs @@ -196,7 +196,7 @@ impl GetTracker, api::PaymentsCancelRequest> authentication: None, recurring_details: None, poll_config: None, - shipping_details: None, + tax_data: None, }; let get_trackers_response = operations::GetTrackerResponse { diff --git a/crates/router/src/core/payments/operations/payment_capture.rs b/crates/router/src/core/payments/operations/payment_capture.rs index 018b32b98542..ec97c9903ce1 100644 --- a/crates/router/src/core/payments/operations/payment_capture.rs +++ b/crates/router/src/core/payments/operations/payment_capture.rs @@ -242,7 +242,7 @@ impl GetTracker, api::PaymentsCaptu authentication: None, recurring_details: None, poll_config: None, - shipping_details: None, + tax_data: None, }; let get_trackers_response = operations::GetTrackerResponse { 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 dca9c2c13c0d..3ab388de3789 100644 --- a/crates/router/src/core/payments/operations/payment_complete_authorize.rs +++ b/crates/router/src/core/payments/operations/payment_complete_authorize.rs @@ -339,7 +339,7 @@ impl GetTracker, api::PaymentsRequest> for Co authentication: None, recurring_details, poll_config: None, - shipping_details: None, + tax_data: None, }; let customer_details = Some(CustomerDetails { diff --git a/crates/router/src/core/payments/operations/payment_confirm.rs b/crates/router/src/core/payments/operations/payment_confirm.rs index 8b4206f0eabd..92519a0e4976 100644 --- a/crates/router/src/core/payments/operations/payment_confirm.rs +++ b/crates/router/src/core/payments/operations/payment_confirm.rs @@ -724,7 +724,7 @@ impl GetTracker, api::PaymentsRequest> for Pa authentication: None, recurring_details, poll_config: None, - shipping_details: None, + tax_data: None, }; let get_trackers_response = operations::GetTrackerResponse { diff --git a/crates/router/src/core/payments/operations/payment_create.rs b/crates/router/src/core/payments/operations/payment_create.rs index 2d427373f942..cc0ea89bb2b4 100644 --- a/crates/router/src/core/payments/operations/payment_create.rs +++ b/crates/router/src/core/payments/operations/payment_create.rs @@ -8,7 +8,10 @@ use async_trait::async_trait; use common_utils::{ ext_traits::{AsyncExt, Encode, ValueExt}, type_name, - types::{keymanager::Identifier, MinorUnit}, + types::{ + keymanager::{Identifier, KeyManagerState}, + MinorUnit, + }, }; use diesel_models::{ephemeral_key, PaymentMethod}; use error_stack::{self, ResultExt}; @@ -540,7 +543,7 @@ impl GetTracker, api::PaymentsRequest> for Pa authentication: None, recurring_details, poll_config: None, - shipping_details: None, + tax_data: None, }; let get_trackers_response = operations::GetTrackerResponse { @@ -591,26 +594,47 @@ impl Domain for PaymentCreate { payment_data: &mut PaymentData, _should_continue_confirm_transaction: &mut bool, _connector_call_type: &ConnectorCallType, - // _merchant_account: &storage::BusinessProfile, + business_profile: &domain::BusinessProfile, key_store: &domain::MerchantKeyStore, // storage_scheme: storage_enums::MerchantStorageScheme, merchant_account: &domain::MerchantAccount, ) -> CustomResult<(), errors::ApiErrorResponse> { - // let db = state.store.as_ref(); - let payment_intent = payment_data.payment_intent.clone(); + let db = state.store.as_ref(); + // let payment_intent = payment_data.payment_intent.clone(); + let key_manager_state: &KeyManagerState = &state.into(); // let attempt_id = payment_intent.active_attempt.get_id().clone(); - let payment_attempt = payment_data.payment_attempt.clone(); + // let payment_attempt = payment_data.payment_attempt.clone(); + + let merchant_connector_id = business_profile + .tax_connector_id + .as_ref() + .ok_or(errors::ApiErrorResponse::InternalServerError) + .attach_printable("missing business_profile.tax_connector_id")?; + + let mca = db + .find_by_merchant_connector_account_merchant_id_merchant_connector_id( + key_manager_state, + &business_profile.merchant_id, + merchant_connector_id, + key_store, + ) + .await + .to_not_found_response(errors::ApiErrorResponse::MerchantConnectorAccountNotFound { + id: merchant_connector_id.to_string(), + })?; // Derive this connector from business profile - let connector_data = api::TaxCalculateConnectorData::get_connector_by_name("taxjar")?; + let connector_data = + api::TaxCalculateConnectorData::get_connector_by_name(&mca.connector_name)?; let router_data = core_utils::construct_payments_dynamic_tax_calculation_router_data( state, merchant_account, key_store, payment_data, + &mca, // &customer, ) .await?; @@ -643,7 +667,7 @@ impl Domain for PaymentCreate { payment_data.payment_intent.tax_details = Some(diesel_models::TaxDetails { default: Some(diesel_models::DefaultTax { - order_tax_amount: tax_response.order_tax_amount.get_amount_as_i64(), + order_tax_amount: tax_response.order_tax_amount, }), pmt: None, }); diff --git a/crates/router/src/core/payments/operations/payment_reject.rs b/crates/router/src/core/payments/operations/payment_reject.rs index 49210e8623cb..6f67b6a6b22c 100644 --- a/crates/router/src/core/payments/operations/payment_reject.rs +++ b/crates/router/src/core/payments/operations/payment_reject.rs @@ -180,7 +180,7 @@ impl GetTracker, PaymentsCancelRequest> for P authentication: None, recurring_details: None, poll_config: None, - shipping_details: None, + tax_data: None, }; let get_trackers_response = operations::GetTrackerResponse { diff --git a/crates/router/src/core/payments/operations/payment_response.rs b/crates/router/src/core/payments/operations/payment_response.rs index 7f317e94f95a..67d1d37b34e9 100644 --- a/crates/router/src/core/payments/operations/payment_response.rs +++ b/crates/router/src/core/payments/operations/payment_response.rs @@ -568,7 +568,7 @@ impl PostUpdateTracker, types::SessionUpdateData> fo println!("pmt_amount: {:?}", pmt_amount); - let total_amount = MinorUnit::from(payment_data.amount) + MinorUnit::new(pmt_amount); + let total_amount = MinorUnit::from(payment_data.amount) + pmt_amount; println!("total_amount: {:?}", total_amount); @@ -587,7 +587,7 @@ impl PostUpdateTracker, types::SessionUpdateData> fo ), Some( storage::PaymentIntentUpdate::IncrementalAuthorizationAmountUpdate { - amount: MinorUnit::new(pmt_amount), + amount: pmt_amount, }, ), ) diff --git a/crates/router/src/core/payments/operations/payment_session.rs b/crates/router/src/core/payments/operations/payment_session.rs index 8fc8bf0beb74..ab982eeeefce 100644 --- a/crates/router/src/core/payments/operations/payment_session.rs +++ b/crates/router/src/core/payments/operations/payment_session.rs @@ -205,7 +205,7 @@ impl GetTracker, api::PaymentsSessionRequest> authentication: None, recurring_details: None, poll_config: None, - shipping_details: None, + tax_data: None, }; let get_trackers_response = operations::GetTrackerResponse { diff --git a/crates/router/src/core/payments/operations/payment_start.rs b/crates/router/src/core/payments/operations/payment_start.rs index d2c005fe5f5f..ce6c5c2a325b 100644 --- a/crates/router/src/core/payments/operations/payment_start.rs +++ b/crates/router/src/core/payments/operations/payment_start.rs @@ -190,7 +190,7 @@ impl GetTracker, api::PaymentsStartRequest> f authentication: None, recurring_details: None, poll_config: None, - shipping_details: None, + tax_data: None, }; let get_trackers_response = operations::GetTrackerResponse { diff --git a/crates/router/src/core/payments/operations/payment_status.rs b/crates/router/src/core/payments/operations/payment_status.rs index 0891e692f577..5e4550218f49 100644 --- a/crates/router/src/core/payments/operations/payment_status.rs +++ b/crates/router/src/core/payments/operations/payment_status.rs @@ -466,7 +466,7 @@ async fn get_tracker_for_sync< authentication, recurring_details: None, poll_config: None, - shipping_details: None, + tax_data: None, }; let get_trackers_response = operations::GetTrackerResponse { diff --git a/crates/router/src/core/payments/operations/payment_update.rs b/crates/router/src/core/payments/operations/payment_update.rs index 95ecdd2b601b..f8c428c35470 100644 --- a/crates/router/src/core/payments/operations/payment_update.rs +++ b/crates/router/src/core/payments/operations/payment_update.rs @@ -7,6 +7,7 @@ use async_trait::async_trait; use common_utils::{ ext_traits::{AsyncExt, Encode, ValueExt}, pii::Email, + types::keymanager::KeyManagerState, }; use error_stack::{report, ResultExt}; use hyperswitch_domain_models::payments::payment_intent::{ @@ -473,7 +474,7 @@ impl GetTracker, api::PaymentsRequest> for Pa authentication: None, recurring_details, poll_config: None, - shipping_details: None, + tax_data: None, }; let get_trackers_response = operations::GetTrackerResponse { @@ -524,26 +525,47 @@ impl Domain for PaymentUpdate { payment_data: &mut PaymentData, _should_continue_confirm_transaction: &mut bool, _connector_call_type: &ConnectorCallType, - // _merchant_account: &storage::BusinessProfile, + business_profile: &domain::BusinessProfile, key_store: &domain::MerchantKeyStore, // storage_scheme: storage_enums::MerchantStorageScheme, merchant_account: &domain::MerchantAccount, ) -> CustomResult<(), errors::ApiErrorResponse> { - // let db = state.store.as_ref(); - let payment_intent = payment_data.payment_intent.clone(); + let db = state.store.as_ref(); + // let payment_intent = payment_data.payment_intent.clone(); + let key_manager_state: &KeyManagerState = &state.into(); // let attempt_id = payment_intent.active_attempt.get_id().clone(); - let payment_attempt = payment_data.payment_attempt.clone(); + // let payment_attempt = payment_data.payment_attempt.clone(); + + let merchant_connector_id = business_profile + .tax_connector_id + .as_ref() + .ok_or(errors::ApiErrorResponse::InternalServerError) + .attach_printable("missing business_profile.tax_connector_id")?; + + let mca = db + .find_by_merchant_connector_account_merchant_id_merchant_connector_id( + key_manager_state, + &business_profile.merchant_id, + merchant_connector_id, + key_store, + ) + .await + .to_not_found_response(errors::ApiErrorResponse::MerchantConnectorAccountNotFound { + id: merchant_connector_id.to_string(), + })?; // Derive this connector from business profile - let connector_data = api::TaxCalculateConnectorData::get_connector_by_name("klarna")?; + let connector_data = + api::TaxCalculateConnectorData::get_connector_by_name(&mca.connector_name)?; let router_data = core_utils::construct_payments_dynamic_tax_calculation_router_data( state, merchant_account, key_store, payment_data, + &mca, // &customer, ) .await?; @@ -576,7 +598,7 @@ impl Domain for PaymentUpdate { payment_data.payment_intent.tax_details = Some(diesel_models::TaxDetails { default: Some(diesel_models::DefaultTax { - order_tax_amount: tax_response.order_tax_amount.get_amount_as_i64(), + order_tax_amount: tax_response.order_tax_amount, }), pmt: None, }); 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 f41816f50cf5..276ab77fd779 100644 --- a/crates/router/src/core/payments/operations/payments_incremental_authorization.rs +++ b/crates/router/src/core/payments/operations/payments_incremental_authorization.rs @@ -158,7 +158,7 @@ impl authentication: None, recurring_details: None, poll_config: None, - shipping_details: None, + tax_data: None, }; let get_trackers_response = operations::GetTrackerResponse { diff --git a/crates/router/src/core/payments/operations/tax_calculation.rs b/crates/router/src/core/payments/operations/tax_calculation.rs index 71d99678ca89..161d739af9e1 100644 --- a/crates/router/src/core/payments/operations/tax_calculation.rs +++ b/crates/router/src/core/payments/operations/tax_calculation.rs @@ -2,7 +2,7 @@ use std::marker::PhantomData; use api_models::enums::FrmSuggestion; use async_trait::async_trait; -use common_utils::types::{keymanager::KeyManagerState, MinorUnit}; +use common_utils::types::keymanager::KeyManagerState; use error_stack::ResultExt; use router_derive::PaymentOperation; use router_env::{instrument, tracing}; @@ -58,7 +58,7 @@ impl GetTracker, api::PaymentsDynamicTaxCalcu let merchant_id = merchant_account.get_id(); let storage_scheme = merchant_account.storage_scheme; - let mut payment_intent = db + let payment_intent = db .find_payment_intent_by_payment_id_merchant_id( &state.into(), &payment_id, @@ -94,24 +94,6 @@ impl GetTracker, api::PaymentsDynamicTaxCalcu let amount = payment_attempt.get_total_amount().into(); - // payment_intent.order_details = request - // .get_order_details_as_value() - // .change_context(errors::ApiErrorResponse::InternalServerError) - // .attach_printable("Failed to convert order details to value")? - // .or(payment_intent.order_details); - - // let shipping_address = helpers::create_or_update_address_for_payment_by_request( - // state, - // Some(&request.shipping), - // payment_intent.shipping_address_id.as_deref(), - // merchant_id, - // payment_intent.customer_id.as_ref(), - // key_store, - // &payment_intent.payment_id, - // merchant_account.storage_scheme, - // ) - // .await?; - let shipping_address = helpers::get_address_by_id( state, payment_intent.shipping_address_id.clone(), @@ -123,20 +105,6 @@ impl GetTracker, api::PaymentsDynamicTaxCalcu .await?; println!("shipping_address: {:?}", shipping_address); - // let billing_address = helpers::create_or_find_address_for_payment_by_request( - // &state, - // None, - // payment_intent.billing_address_id.as_deref(), - // merchant_id, - // payment_intent.customer_id.as_ref(), - // &key_store, - // &payment_intent.payment_id, - // storage_scheme, - // ) - // .await?; - - // println!("billing_address: {:?}", billing_address); - let billing_address = helpers::get_address_by_id( state, payment_intent.billing_address_id.clone(), @@ -160,9 +128,14 @@ impl GetTracker, api::PaymentsDynamicTaxCalcu .find_business_profile_by_profile_id(key_manager_state, key_store, profile_id) .await .to_not_found_response(errors::ApiErrorResponse::BusinessProfileNotFound { - id: profile_id.to_string(), + id: profile_id.get_string_repr().to_owned(), })?; + let tax_data = payments::TaxData { + shipping_details: request.shipping.clone(), + payment_method_type: request.payment_method_type, + }; + let payment_data = PaymentData { flow: PhantomData, payment_intent, @@ -206,7 +179,7 @@ impl GetTracker, api::PaymentsDynamicTaxCalcu authentication: None, recurring_details: None, poll_config: None, - shipping_details: Some(request.shipping.clone()), + tax_data: Some(tax_data), }; let get_trackers_response = operations::GetTrackerResponse { operation: Box::new(self), @@ -249,27 +222,48 @@ impl Domain payment_data: &mut PaymentData, should_continue_confirm_transaction: &mut bool, _connector_call_type: &ConnectorCallType, - // _merchant_account: &storage::BusinessProfile, + business_profile: &domain::BusinessProfile, key_store: &domain::MerchantKeyStore, // storage_scheme: storage_enums::MerchantStorageScheme, merchant_account: &domain::MerchantAccount, ) -> errors::CustomResult<(), errors::ApiErrorResponse> { *should_continue_confirm_transaction = false; - // let db = state.store.as_ref(); - let payment_intent = payment_data.payment_intent.clone(); + let db = state.store.as_ref(); + // let payment_intent = payment_data.payment_intent.clone(); + let key_manager_state: &KeyManagerState = &state.into(); // let attempt_id = payment_intent.active_attempt.get_id().clone(); - let payment_attempt = payment_data.payment_attempt.clone(); + // let payment_attempt = payment_data.payment_attempt.clone(); + + let merchant_connector_id = business_profile + .tax_connector_id + .as_ref() + .ok_or(errors::ApiErrorResponse::InternalServerError) + .attach_printable("missing business_profile.tax_connector_id")?; + + let mca = db + .find_by_merchant_connector_account_merchant_id_merchant_connector_id( + key_manager_state, + &business_profile.merchant_id, + merchant_connector_id, + key_store, + ) + .await + .to_not_found_response(errors::ApiErrorResponse::MerchantConnectorAccountNotFound { + id: merchant_connector_id.to_string(), + })?; // Derive this connector from business profile - let connector_data = api::TaxCalculateConnectorData::get_connector_by_name("taxjar")?; + let connector_data = + api::TaxCalculateConnectorData::get_connector_by_name(&mca.connector_name)?; let router_data = core_utils::construct_payments_dynamic_tax_calculation_router_data( state, merchant_account, key_store, payment_data, + &mca, // &customer, ) .await?; @@ -313,10 +307,18 @@ impl Domain // pmt.order_tax_amount = tax_response.order_tax_amount; // }); // }); + + let payment_method_type = payment_data + .tax_data + .clone() + .map(|tax_data| tax_data.payment_method_type) + .ok_or(errors::ApiErrorResponse::InternalServerError) + .attach_printable("missing tax_data.payment_method_type")?; + payment_data.payment_intent.tax_details = Some(diesel_models::TaxDetails { pmt: Some(diesel_models::PmtTax { - order_tax_amount: tax_response.order_tax_amount.get_amount_as_i64(), - pmt: "klarna".to_string(), + order_tax_amount: tax_response.order_tax_amount, + pmt: payment_method_type, }), default: None, }); @@ -394,31 +396,27 @@ impl UpdateTracker, api::PaymentsDynamicTaxCalculati where F: 'b + Send, { - let session_update_details = payment_data - .payment_intent - .tax_details - .clone() - .ok_or(errors::ApiErrorResponse::InternalServerError)?; - - println!("update_trackers tax_details : {:?}", session_update_details); - - let calculated_tax_amount = session_update_details - .pmt + //shipping_address_id + let shipping_details = payment_data + .tax_data .clone() - .map(|pmt| pmt.order_tax_amount) - .ok_or(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Missing tax_details.order_tax_amount")?; - - println!("calculated_tax_amount: {:?}", calculated_tax_amount); + .map(|tax_data| tax_data.shipping_details); - // let shipping_cost = (payment_data.payment_intent.shipping_cost.clone().ok_or(errors::ApiErrorResponse::InternalServerError).attach_printable("missing"))?; - - // let net_amount = payment_data.amount.into() + MinorUnit::new(calculated_tax_amount) + payment_data.payment_intent.shipping_cost; - // println!("net_amount: {:?}", net_amount); + let shipping_address = helpers::create_or_update_address_for_payment_by_request( + state, + shipping_details.as_ref(), + payment_data.payment_intent.shipping_address_id.as_deref(), + &payment_data.payment_intent.merchant_id, + payment_data.payment_intent.customer_id.as_ref(), + key_store, + &payment_data.payment_intent.payment_id, + storage_scheme, + ) + .await?; let payment_intent_update = hyperswitch_domain_models::payments::payment_intent::PaymentIntentUpdate::TaxCalculationUpdate { tax_details: payment_data.payment_intent.tax_details.clone().ok_or(errors::ApiErrorResponse::InternalServerError)?, - shipping_address_id: payment_data.payment_intent.shipping_address_id.clone() + shipping_address_id: shipping_address.map(|address| address.address_id), }; print!( diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs index e14056262d2b..d65a0a181007 100644 --- a/crates/router/src/core/payments/transformers.rs +++ b/crates/router/src/core/payments/transformers.rs @@ -6,7 +6,7 @@ use api_models::payments::{ }; use common_enums::RequestIncrementalAuthorization; use common_utils::{consts::X_HS_LATENCY, fp_utils, pii::Email, types::MinorUnit}; -use diesel_models::{ephemeral_key, schema::payment_intent::tax_details}; +use diesel_models::ephemeral_key; use error_stack::{report, ResultExt}; use hyperswitch_domain_models::{payments::payment_intent::CustomerData, router_request_types}; use masking::{ExposeInterface, Maskable, PeekInterface, Secret}; @@ -105,14 +105,13 @@ where let unified_address = if let Some(payment_method_info) = payment_data.payment_method_info.clone() { - let payment_method_billing = - crate::core::payment_methods::cards::decrypt_generic_data::
( - state, - payment_method_info.payment_method_billing_address, - key_store, - ) - .await - .attach_printable("unable to decrypt payment method billing address details")?; + let payment_method_billing = decrypt_generic_data::
( + state, + payment_method_info.payment_method_billing_address, + key_store, + ) + .await + .attach_printable("unable to decrypt payment method billing address details")?; payment_data .address .clone() @@ -489,13 +488,23 @@ where _external_latency: Option, _is_latency_header_enabled: Option, ) -> RouterResponse { - // let amount = MinorUnit::from(payment_data.amount); - // let shipping_cost = payment_data.payment_intent.shipping_cost; - // let order_tax_amount = MinorUnit::from(payment_data.payment_intent.tax_details.clone().and_then(|tax|tax.pmt.map(|a|a.order_tax_amount))); + let mut amount = MinorUnit::from(payment_data.amount); + let shipping_cost = payment_data.payment_intent.shipping_cost; + let order_tax_amount = payment_data + .payment_intent + .tax_details + .clone() + .and_then(|tax| tax.pmt.map(|a| a.order_tax_amount)); + if let Some(shipping_cost) = shipping_cost { + amount = amount + shipping_cost; + } + if let Some(order_tax_amount) = order_tax_amount { + amount = amount + order_tax_amount; + } Ok(services::ApplicationResponse::JsonWithHeaders(( Self { // order_tax_amount: payment_data.amount, - net_amount: MinorUnit::from(payment_data.amount), + net_amount: amount, }, vec![], ))) @@ -1818,7 +1827,8 @@ impl TryFrom> for types::SessionUpdateDat .tax_details .clone() .and_then(|tax| tax.pmt.map(|pmt| pmt.order_tax_amount)) - .unwrap_or(0); + .ok_or(errors::ApiErrorResponse::InternalServerError) + .attach_printable("missing order_tax_amount")?; let amount = MinorUnit::from(payment_data.amount); println!("additional_data_order_tax_amount: {:?}", order_tax_amount); @@ -1826,7 +1836,7 @@ impl TryFrom> for types::SessionUpdateDat println!("additional_data_amount: {:?}", amount.get_amount_as_i64()); Ok(Self { - net_amount: (amount.get_amount_as_i64()) + order_tax_amount, //need to change after we move to connector module + net_amount: amount + order_tax_amount, //need to change after we move to connector module order_tax_amount, }) } diff --git a/crates/router/src/core/utils.rs b/crates/router/src/core/utils.rs index 989e4f75e505..9669b42d1098 100644 --- a/crates/router/src/core/utils.rs +++ b/crates/router/src/core/utils.rs @@ -857,6 +857,7 @@ pub async fn construct_payments_dynamic_tax_calculation_router_data<'a, F: Clone merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, payment_data: &mut PaymentData, + mca: &MerchantConnectorAccount, // customer: &'a Option, ) -> RouterResult { let payment_intent = &payment_data.payment_intent.clone(); @@ -884,7 +885,7 @@ pub async fn construct_payments_dynamic_tax_calculation_router_data<'a, F: Clone key_store, &profile_id, // How do we derive the connector name? - "taxjar", + &mca.connector_name, // Take this from business profile payment_attempt.merchant_connector_id.as_ref(), ) @@ -902,7 +903,9 @@ pub async fn construct_payments_dynamic_tax_calculation_router_data<'a, F: Clone // println!("$$$$$$ {:?}", add); let shipping_address = payment_data - .shipping_details + .tax_data + .clone() + .map(|tax_data| tax_data.shipping_details) .clone() .ok_or(errors::ApiErrorResponse::InternalServerError) .attach_printable("Missing shipping_details")?; @@ -934,7 +937,7 @@ pub async fn construct_payments_dynamic_tax_calculation_router_data<'a, F: Clone merchant_id: merchant_account.get_id().to_owned(), customer_id: payment_intent.customer_id.to_owned(), connector_customer: None, - connector: "taxjar".to_string(), + connector: mca.connector_name.clone(), payment_id: payment_attempt.payment_id.clone(), attempt_id: payment_attempt.attempt_id.clone(), status: payment_attempt.status, diff --git a/migrations/2024-08-27-190822_add_tax_processor_in_connector_type/down.sql b/migrations/2024-08-27-190822_add_tax_processor_in_connector_type/down.sql new file mode 100644 index 000000000000..da13010c0122 --- /dev/null +++ b/migrations/2024-08-27-190822_add_tax_processor_in_connector_type/down.sql @@ -0,0 +1,2 @@ +-- This file should undo anything in `up.sql` +select 1; \ No newline at end of file diff --git a/migrations/2024-08-27-190822_add_tax_processor_in_connector_type/up.sql b/migrations/2024-08-27-190822_add_tax_processor_in_connector_type/up.sql new file mode 100644 index 000000000000..3026bf047825 --- /dev/null +++ b/migrations/2024-08-27-190822_add_tax_processor_in_connector_type/up.sql @@ -0,0 +1,3 @@ +-- Your SQL goes here +ALTER TYPE "ConnectorType" +ADD VALUE IF NOT EXISTS 'tax_processor'; \ No newline at end of file From 5e03bbdf943201300e4f00f68d098712e29a4e99 Mon Sep 17 00:00:00 2001 From: swangi-kumari Date: Wed, 28 Aug 2024 23:54:45 +0530 Subject: [PATCH 20/39] refactor: remove println and some refactoring --- crates/api_models/src/payments.rs | 2 +- crates/common_enums/src/enums.rs | 38 ++--- crates/common_utils/src/types.rs | 2 +- crates/diesel_models/src/payment_attempt.rs | 53 ------- crates/diesel_models/src/payment_intent.rs | 6 +- .../src/connectors/taxjar.rs | 5 - .../src/connectors/taxjar/transformers.rs | 64 ++++---- .../src/default_implementations.rs | 6 +- .../src/default_implementations_v2.rs | 10 +- .../src/payments/payment_attempt.rs | 1 - .../src/payments/payment_intent.rs | 9 +- .../src/router_request_types.rs | 4 +- .../src/router_response_types.rs | 12 +- .../src/api/payments.rs | 6 +- .../src/api/payments_v2.rs | 11 +- crates/router/src/core/payments.rs | 1 - .../connector_integration_v2_impls.rs | 4 +- crates/router/src/core/payments/flows.rs | 4 +- .../payments/flows/tax_calculation_flow.rs | 28 ++-- crates/router/src/core/payments/operations.rs | 4 +- .../payments/operations/payment_create.rs | 10 +- .../payments/operations/payment_response.rs | 137 ++++++++---------- .../payments/operations/payment_update.rs | 9 -- .../payments/operations/tax_calculation.rs | 45 +----- .../router/src/core/payments/transformers.rs | 17 +-- crates/router/src/core/utils.rs | 9 -- crates/router/src/routes/payments.rs | 2 +- crates/router/src/types.rs | 12 +- crates/router/src/types/api.rs | 1 - crates/router/tests/connectors/utils.rs | 6 +- crates/router_derive/src/macros/operation.rs | 6 +- .../src/payments/payment_attempt.rs | 4 - 32 files changed, 172 insertions(+), 356 deletions(-) diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs index bb057508d8a3..86e36677c679 100644 --- a/crates/api_models/src/payments.rs +++ b/crates/api_models/src/payments.rs @@ -4735,7 +4735,7 @@ pub struct SessionTokenForSimplifiedApplePay { #[serde(tag = "wallet_name")] #[serde(rename_all = "snake_case")] pub enum SessionToken { - /// The session -structure for Google Pay + /// The session response structure for Google Pay GooglePay(Box), /// The session response structure for Klarna Klarna(Box), diff --git a/crates/common_enums/src/enums.rs b/crates/common_enums/src/enums.rs index 9f8a8e883060..873a2b2d24f5 100644 --- a/crates/common_enums/src/enums.rs +++ b/crates/common_enums/src/enums.rs @@ -399,25 +399,25 @@ pub enum AuthorizationStatus { Unresolved, } -#[derive( - Clone, - Debug, - Eq, - PartialEq, - serde::Deserialize, - serde::Serialize, - strum::Display, - strum::EnumString, - ToSchema, - Hash, -)] -#[router_derive::diesel_enum(storage_type = "text")] -#[serde(rename_all = "snake_case")] -#[strum(serialize_all = "snake_case")] -pub enum SessionUpdateStatus { - Success, - Failure, -} +// #[derive( +// Clone, +// Debug, +// Eq, +// PartialEq, +// serde::Deserialize, +// serde::Serialize, +// strum::Display, +// strum::EnumString, +// ToSchema, +// Hash, +// )] +// #[router_derive::diesel_enum(storage_type = "text")] +// #[serde(rename_all = "snake_case")] +// #[strum(serialize_all = "snake_case")] +// pub enum SessionUpdateStatus { +// Success, +// Failure, +// } #[derive( Clone, diff --git a/crates/common_utils/src/types.rs b/crates/common_utils/src/types.rs index 5319a4c5f7d6..a7fda21eba56 100644 --- a/crates/common_utils/src/types.rs +++ b/crates/common_utils/src/types.rs @@ -517,7 +517,7 @@ impl FloatMajorUnit { } /// converts to minor unit as i64 from FloatMajorUnit - pub fn to_minor_unit_as_i64( + fn to_minor_unit_as_i64( self, currency: enums::Currency, ) -> Result> { diff --git a/crates/diesel_models/src/payment_attempt.rs b/crates/diesel_models/src/payment_attempt.rs index f32e2882844d..84811f226249 100644 --- a/crates/diesel_models/src/payment_attempt.rs +++ b/crates/diesel_models/src/payment_attempt.rs @@ -438,11 +438,6 @@ pub enum PaymentAttemptUpdate { unified_message: Option, connector_transaction_id: Option, }, - // SessionUpdate { - // amount: i64, - // order_tax_amount: i64, - // payment_method_shipping_address_id: Option, - // }, } #[derive(Clone, Debug, AsChangeset, router_derive::DebugAsDisplay)] @@ -1700,54 +1695,6 @@ impl From for PaymentAttemptUpdateInternal { client_version: None, customer_acceptance: None, }, - // PaymentAttemptUpdate::SessionUpdate { amount, order_tax_amount, payment_method_shipping_address_id } => Self { - // amount: Some(amount), - // modified_at: common_utils::date_time::now(), - // amount_capturable: Some(amount + order_tax_amount), - // net_amount: None, - // currency: None, - // status: None, - // connector_transaction_id: None, - // amount_to_capture: None, - // connector: None, - // authentication_type: None, - // payment_method: None, - // error_message: None, - // payment_method_id: None, - // cancellation_reason: None, - // mandate_id: None, - // browser_info: None, - // payment_token: None, - // error_code: None, - // connector_metadata: None, - // payment_method_data: None, - // payment_method_type: None, - // payment_experience: None, - // business_sub_label: None, - // straight_through_algorithm: None, - // preprocessing_step_id: None, - // error_reason: None, - // capture_method: None, - // connector_response_reference_id: None, - // multiple_capture_count: None, - // surcharge_amount: None, - // tax_amount: None, - // updated_by: String::default(), - // merchant_connector_id: None, - // authentication_data: None, - // encoded_data: None, - // unified_code: None, - // unified_message: None, - // external_three_ds_authentication_attempted: None, - // authentication_connector: None, - // authentication_id: None, - // fingerprint_id: None, - // payment_method_billing_address_id: None, - // charge_id: None, - // client_source: None, - // client_version: None, - // customer_acceptance: None, - // }, } } } diff --git a/crates/diesel_models/src/payment_intent.rs b/crates/diesel_models/src/payment_intent.rs index d4e3423a13da..b4272594faf6 100644 --- a/crates/diesel_models/src/payment_intent.rs +++ b/crates/diesel_models/src/payment_intent.rs @@ -148,13 +148,11 @@ common_utils::impl_to_sql_from_sql_json!(TaxDetails); pub struct PmtTax { pub order_tax_amount: MinorUnit, pub pmt: enums::PaymentMethodType, - // pub shipping_details: String, } #[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)] pub struct DefaultTax { pub order_tax_amount: MinorUnit, - // pub shipping_details: String, } #[derive( @@ -292,7 +290,7 @@ pub enum PaymentIntentUpdate { status: Option, updated_by: String, }, - TaxCalculationUpdate { + SessionResponseUpdate { tax_details: TaxDetails, shipping_address_id: Option, }, @@ -1091,7 +1089,7 @@ impl From for PaymentIntentUpdateInternal { is_payment_processor_token_flow: None, tax_details: None, }, - PaymentIntentUpdate::TaxCalculationUpdate { + PaymentIntentUpdate::SessionResponseUpdate { tax_details, shipping_address_id, } => Self { diff --git a/crates/hyperswitch_connectors/src/connectors/taxjar.rs b/crates/hyperswitch_connectors/src/connectors/taxjar.rs index ce929bad3ae1..94d521e0ce03 100644 --- a/crates/hyperswitch_connectors/src/connectors/taxjar.rs +++ b/crates/hyperswitch_connectors/src/connectors/taxjar.rs @@ -197,10 +197,6 @@ impl ConnectorIntegration, res: Response, ) -> CustomResult { - print!("response123_connector{:?}", res.response); let response: taxjar::TaxjarPaymentsResponse = res .response .parse_struct("Taxjar PaymentsAuthorizeResponse") diff --git a/crates/hyperswitch_connectors/src/connectors/taxjar/transformers.rs b/crates/hyperswitch_connectors/src/connectors/taxjar/transformers.rs index 1be9b5747065..2d36acef84ee 100644 --- a/crates/hyperswitch_connectors/src/connectors/taxjar/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/taxjar/transformers.rs @@ -77,8 +77,6 @@ impl TryFrom<&TaxjarRouterData<&types::PaymentsTaxCalculationRouterData>> item: &TaxjarRouterData<&types::PaymentsTaxCalculationRouterData>, ) -> Result { let request = &item.router_data.request; - // let shipping = item.router_data.get_shipping_address()?; - // println!("$$swangi{:?}", shipping); let currency = item.router_data.request.currency; let currency_unit = &api::CurrencyUnit::Base; let shipping = &item @@ -91,35 +89,41 @@ impl TryFrom<&TaxjarRouterData<&types::PaymentsTaxCalculationRouterData>> field_name: "address", })?; - println!("$$shipping123{:?}", shipping); - match request.order_details.clone() { - Some(order_details) => Ok(Self { - from_country: item.router_data.get_billing_country()?, - from_zip: item.router_data.get_billing_zip()?, - from_state: item.router_data.get_billing_state_code()?, - from_city: item.router_data.get_optional_billing_city(), - from_street: item.router_data.get_optional_billing_line1(), - to_country: shipping.get_country()?.to_owned(), - to_zip: shipping.get_zip()?.to_owned(), - to_state: shipping.to_state_code()?.to_owned(), - to_city: shipping.get_optional_city(), - to_street: shipping.get_optional_line1(), - amount: item.amount, - shipping: item.shipping, - line_items: order_details - .iter() - .map(|line_item| LineItem { - id: line_item.product_id.clone(), - quantity: Some(line_item.quantity), - product_tax_code: line_item.product_tax_code.clone(), - unit_price: Some(FloatMajorUnit::new( - utils::get_amount_as_f64(currency_unit, line_item.amount, currency) - .unwrap(), - )), - }) - .collect(), - }), + Some(order_details) => { + let line_items: Result, error_stack::Report> = + order_details + .iter() + .map(|line_item| { + let unit_price = + utils::get_amount_as_f64(currency_unit, line_item.amount, currency) + .map(FloatMajorUnit::new)?; + + Ok(LineItem { + id: line_item.product_id.clone(), + quantity: Some(line_item.quantity), + product_tax_code: line_item.product_tax_code.clone(), + unit_price: Some(unit_price), + }) + }) + .collect(); + + Ok(Self { + from_country: item.router_data.get_billing_country()?, + from_zip: item.router_data.get_billing_zip()?, + from_state: item.router_data.get_billing_state_code()?, + from_city: item.router_data.get_optional_billing_city(), + from_street: item.router_data.get_optional_billing_line1(), + to_country: shipping.get_country()?.to_owned(), + to_zip: shipping.get_zip()?.to_owned(), + to_state: shipping.to_state_code()?.to_owned(), + to_city: shipping.get_optional_city(), + to_street: shipping.get_optional_line1(), + amount: item.amount, + shipping: item.shipping, + line_items: line_items?, + }) + } None => Err(report!(errors::ConnectorError::MissingRequiredField { field_name: "order_details" })), diff --git a/crates/hyperswitch_connectors/src/default_implementations.rs b/crates/hyperswitch_connectors/src/default_implementations.rs index b63a04b88458..d3fef728919e 100644 --- a/crates/hyperswitch_connectors/src/default_implementations.rs +++ b/crates/hyperswitch_connectors/src/default_implementations.rs @@ -38,8 +38,8 @@ use hyperswitch_domain_models::{ AcceptDisputeRequestData, AuthorizeSessionTokenData, CompleteAuthorizeData, ConnectorCustomerData, DefendDisputeRequestData, MandateRevokeRequestData, PaymentsApproveData, PaymentsIncrementalAuthorizationData, PaymentsPostProcessingData, - PaymentsPreProcessingData, PaymentsRejectData, PaymentsTaxCalculationData, - RetrieveFileRequestData, SessionUpdateData, SubmitEvidenceRequestData, + PaymentsPreProcessingData, PaymentsRejectData, PaymentsSessionUpdateData, + PaymentsTaxCalculationData, RetrieveFileRequestData, SubmitEvidenceRequestData, UploadFileRequestData, VerifyWebhookSourceRequestData, }, router_response_types::{ @@ -129,7 +129,7 @@ macro_rules! default_imp_for_session_update { impl ConnectorIntegration< SessionUpdate, - SessionUpdateData, + PaymentsSessionUpdateData, PaymentsResponseData, > for $path::$connector {} diff --git a/crates/hyperswitch_connectors/src/default_implementations_v2.rs b/crates/hyperswitch_connectors/src/default_implementations_v2.rs index a331cb3ebc7d..365a12fac56a 100644 --- a/crates/hyperswitch_connectors/src/default_implementations_v2.rs +++ b/crates/hyperswitch_connectors/src/default_implementations_v2.rs @@ -26,10 +26,10 @@ use hyperswitch_domain_models::{ MandateRevokeRequestData, PaymentMethodTokenizationData, PaymentsApproveData, PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, PaymentsIncrementalAuthorizationData, PaymentsPostProcessingData, - PaymentsPreProcessingData, PaymentsRejectData, PaymentsSessionData, PaymentsSyncData, - PaymentsTaxCalculationData, RefundsData, RetrieveFileRequestData, SessionUpdateData, - SetupMandateRequestData, SubmitEvidenceRequestData, UploadFileRequestData, - VerifyWebhookSourceRequestData, + PaymentsPreProcessingData, PaymentsRejectData, PaymentsSessionData, + PaymentsSessionUpdateData, PaymentsSyncData, PaymentsTaxCalculationData, RefundsData, + RetrieveFileRequestData, SetupMandateRequestData, SubmitEvidenceRequestData, + UploadFileRequestData, VerifyWebhookSourceRequestData, }, router_response_types::{ AcceptDisputeResponse, DefendDisputeResponse, MandateRevokeResponseData, @@ -188,7 +188,7 @@ macro_rules! default_imp_for_new_connector_integration_payment { impl ConnectorIntegrationV2< SessionUpdate, PaymentFlowData, - SessionUpdateData, + PaymentsSessionUpdateData, PaymentsResponseData, > for $path::$connector{} )* diff --git a/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs b/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs index daef5a0515a7..1565c0d4f125 100644 --- a/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs +++ b/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs @@ -769,7 +769,6 @@ impl behaviour::Conversion for PaymentIntent { .await .and_then(|val| val.try_into_optionaloperation()) }; - Ok::>(Self { payment_id: storage_model.payment_id, merchant_id: storage_model.merchant_id, diff --git a/crates/hyperswitch_domain_models/src/payments/payment_intent.rs b/crates/hyperswitch_domain_models/src/payments/payment_intent.rs index 2a915f10b14b..234aab033456 100644 --- a/crates/hyperswitch_domain_models/src/payments/payment_intent.rs +++ b/crates/hyperswitch_domain_models/src/payments/payment_intent.rs @@ -257,9 +257,8 @@ pub enum PaymentIntentUpdate { status: Option, updated_by: String, }, - TaxCalculationUpdate { + SessionResponseUpdate { tax_details: diesel_models::TaxDetails, - // amount: MinorUnit, shipping_address_id: Option, }, } @@ -487,7 +486,7 @@ impl From for PaymentIntentUpdateInternal { updated_by, ..Default::default() }, - PaymentIntentUpdate::TaxCalculationUpdate { + PaymentIntentUpdate::SessionResponseUpdate { tax_details, shipping_address_id, } => Self { @@ -659,10 +658,10 @@ impl From for DieselPaymentIntentUpdate { PaymentIntentUpdate::ManualUpdate { status, updated_by } => { Self::ManualUpdate { status, updated_by } } - PaymentIntentUpdate::TaxCalculationUpdate { + PaymentIntentUpdate::SessionResponseUpdate { tax_details, shipping_address_id, - } => Self::TaxCalculationUpdate { + } => Self::SessionResponseUpdate { tax_details, shipping_address_id, }, diff --git a/crates/hyperswitch_domain_models/src/router_request_types.rs b/crates/hyperswitch_domain_models/src/router_request_types.rs index 8ec3e8e4ed17..3fd81070495a 100644 --- a/crates/hyperswitch_domain_models/src/router_request_types.rs +++ b/crates/hyperswitch_domain_models/src/router_request_types.rs @@ -801,12 +801,10 @@ pub struct PaymentsTaxCalculationData { pub shipping_cost: MinorUnit, pub order_details: Option>, pub shipping_address: Address, - // New amount for amount frame work - // pub minor_amount: MinorUnit, } #[derive(Debug, Clone, Default)] -pub struct SessionUpdateData { +pub struct PaymentsSessionUpdateData { pub order_tax_amount: MinorUnit, pub net_amount: MinorUnit, } diff --git a/crates/hyperswitch_domain_models/src/router_response_types.rs b/crates/hyperswitch_domain_models/src/router_response_types.rs index 430fcb7d75c3..d81866b1199c 100644 --- a/crates/hyperswitch_domain_models/src/router_response_types.rs +++ b/crates/hyperswitch_domain_models/src/router_response_types.rs @@ -68,14 +68,9 @@ pub enum PaymentsResponseData { PostProcessingResponse { session_token: Option, }, - TaxCalculationResponse { - order_tax_amount: i64, - net_amount: i64, - shipping_address: Option, - }, - SessionUpdateResponse { - status: common_enums::SessionUpdateStatus, - }, + // SessionUpdateResponse { + // status: common_enums::SessionUpdateStatus, + // }, } #[derive(Debug, Clone)] @@ -83,7 +78,6 @@ pub struct TaxCalculationResponseData { pub order_tax_amount: MinorUnit, pub net_amount: MinorUnit, pub shipping_address: Option, - // pub currency: storage_enums::Currency, } #[derive(serde::Serialize, Debug, Clone)] diff --git a/crates/hyperswitch_interfaces/src/api/payments.rs b/crates/hyperswitch_interfaces/src/api/payments.rs index cbb329f2ac7b..1193de2a18c7 100644 --- a/crates/hyperswitch_interfaces/src/api/payments.rs +++ b/crates/hyperswitch_interfaces/src/api/payments.rs @@ -11,8 +11,8 @@ use hyperswitch_domain_models::{ PaymentMethodTokenizationData, PaymentsApproveData, PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, PaymentsIncrementalAuthorizationData, PaymentsPostProcessingData, PaymentsPreProcessingData, PaymentsRejectData, - PaymentsSessionData, PaymentsSyncData, PaymentsTaxCalculationData, SessionUpdateData, - SetupMandateRequestData, + PaymentsSessionData, PaymentsSessionUpdateData, PaymentsSyncData, + PaymentsTaxCalculationData, SetupMandateRequestData, }, router_response_types::{PaymentsResponseData, TaxCalculationResponseData}, }; @@ -121,7 +121,7 @@ pub trait PaymentTaxCalculation: /// trait SessionUpdate pub trait PaymentSessionUpdate: - api::ConnectorIntegration + api::ConnectorIntegration { } diff --git a/crates/hyperswitch_interfaces/src/api/payments_v2.rs b/crates/hyperswitch_interfaces/src/api/payments_v2.rs index dc27b786a28f..dff425ce2bbd 100644 --- a/crates/hyperswitch_interfaces/src/api/payments_v2.rs +++ b/crates/hyperswitch_interfaces/src/api/payments_v2.rs @@ -12,8 +12,8 @@ use hyperswitch_domain_models::{ PaymentMethodTokenizationData, PaymentsApproveData, PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, PaymentsIncrementalAuthorizationData, PaymentsPostProcessingData, PaymentsPreProcessingData, PaymentsRejectData, - PaymentsSessionData, PaymentsSyncData, PaymentsTaxCalculationData, SessionUpdateData, - SetupMandateRequestData, + PaymentsSessionData, PaymentsSessionUpdateData, PaymentsSyncData, + PaymentsTaxCalculationData, SetupMandateRequestData, }, router_response_types::{PaymentsResponseData, TaxCalculationResponseData}, }; @@ -103,7 +103,12 @@ pub trait PaymentTaxCalculationV2: ///trait PaymentSessionUpdateV2 pub trait PaymentSessionUpdateV2: - ConnectorIntegrationV2 + ConnectorIntegrationV2< + SessionUpdate, + PaymentFlowData, + PaymentsSessionUpdateData, + PaymentsResponseData, +> { } diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs index 56c49cc559b9..2ad1cf7d07fa 100644 --- a/crates/router/src/core/payments.rs +++ b/crates/router/src/core/payments.rs @@ -848,7 +848,6 @@ where }) } } - #[allow(clippy::too_many_arguments)] pub async fn payments_core( state: SessionState, diff --git a/crates/router/src/core/payments/connector_integration_v2_impls.rs b/crates/router/src/core/payments/connector_integration_v2_impls.rs index 8ca77c73aa98..a400dc141c8e 100644 --- a/crates/router/src/core/payments/connector_integration_v2_impls.rs +++ b/crates/router/src/core/payments/connector_integration_v2_impls.rs @@ -198,7 +198,7 @@ mod dummy_connector_default_impl { services::ConnectorIntegrationV2< api::SessionUpdate, types::PaymentFlowData, - types::SessionUpdateData, + types::PaymentsSessionUpdateData, types::PaymentsResponseData, > for connector::DummyConnector { @@ -663,7 +663,7 @@ macro_rules! default_imp_for_new_connector_integration_payment { impl services::ConnectorIntegrationV2< api::SessionUpdate, types::PaymentFlowData, - types::SessionUpdateData, + types::PaymentsSessionUpdateData, types::PaymentsResponseData, > for $path::$connector{} )* diff --git a/crates/router/src/core/payments/flows.rs b/crates/router/src/core/payments/flows.rs index 888b2c9dc178..4386f7e8034b 100644 --- a/crates/router/src/core/payments/flows.rs +++ b/crates/router/src/core/payments/flows.rs @@ -3271,7 +3271,7 @@ macro_rules! default_imp_for_session_update { impl services::ConnectorIntegration< api::SessionUpdate, - types::SessionUpdateData, + types::PaymentsSessionUpdateData, types::PaymentsResponseData > for $path::$connector {} @@ -3284,7 +3284,7 @@ impl api::PaymentSessionUpdate for connector::DummyConnector {} impl services::ConnectorIntegration< api::SessionUpdate, - types::SessionUpdateData, + types::PaymentsSessionUpdateData, types::PaymentsResponseData, > for connector::DummyConnector { diff --git a/crates/router/src/core/payments/flows/tax_calculation_flow.rs b/crates/router/src/core/payments/flows/tax_calculation_flow.rs index afd3cf8a16eb..fa32b542bf6d 100644 --- a/crates/router/src/core/payments/flows/tax_calculation_flow.rs +++ b/crates/router/src/core/payments/flows/tax_calculation_flow.rs @@ -15,7 +15,7 @@ use crate::{ impl ConstructFlowSpecificData< api::SessionUpdate, - types::SessionUpdateData, + types::PaymentsSessionUpdateData, types::PaymentsResponseData, > for PaymentData { @@ -29,13 +29,10 @@ impl merchant_connector_account: &helpers::MerchantConnectorAccountType, _merchant_recipient_data: Option, ) -> RouterResult { - // create a new function to construct router data to send the updated amount - - println!("Constructing router data for session update"); Box::pin( transformers::construct_router_date_to_update_calculated_tax::< api::SessionUpdate, - types::SessionUpdateData, + types::PaymentsSessionUpdateData, >( state, self.clone(), @@ -44,7 +41,6 @@ impl key_store, customer, merchant_connector_account, - // merchant_recipient_data, ), ) .await @@ -63,8 +59,12 @@ impl } #[async_trait] -impl Feature - for types::RouterData +impl Feature + for types::RouterData< + api::SessionUpdate, + types::PaymentsSessionUpdateData, + types::PaymentsResponseData, + > { async fn decide_flows<'a>( self, @@ -75,18 +75,10 @@ impl Feature _business_profile: &domain::BusinessProfile, _header_payload: api_models::payments::HeaderPayload, ) -> RouterResult { - /* Have a check here whether to call the connector or not - If check { - call connector - } else { - Ok(self) - } - */ - if connector.connector_name == types::Connector::Klarna { let connector_integration: services::BoxedPaymentConnectorIntegrationInterface< api::SessionUpdate, - types::SessionUpdateData, + types::PaymentsSessionUpdateData, types::PaymentsResponseData, > = connector.connector.get_connector_integration(); @@ -127,7 +119,7 @@ impl Feature payments::CallConnectorAction::Trigger => { let connector_integration: services::BoxedPaymentConnectorIntegrationInterface< api::SessionUpdate, - types::SessionUpdateData, + types::PaymentsSessionUpdateData, types::PaymentsResponseData, > = connector.connector.get_connector_integration(); diff --git a/crates/router/src/core/payments/operations.rs b/crates/router/src/core/payments/operations.rs index c24956201670..b0bf9b3750e8 100644 --- a/crates/router/src/core/payments/operations.rs +++ b/crates/router/src/core/payments/operations.rs @@ -180,17 +180,15 @@ pub trait Domain: Send + Sync { Ok(()) } - // + #[allow(clippy::too_many_arguments)] async fn payments_dynamic_tax_calculation<'a>( &'a self, _state: &SessionState, - // _key_manager_state: &common_utils::types::keymanager::KeyManagerState, _payment_data: &mut PaymentData, _should_continue_confirm_transaction: &mut bool, _connector_call_type: &ConnectorCallType, _business_profile: &domain::BusinessProfile, _key_store: &domain::MerchantKeyStore, - // _storage_scheme: enums::MerchantStorageScheme, _merchant_account: &domain::MerchantAccount, ) -> CustomResult<(), errors::ApiErrorResponse> { Ok(()) diff --git a/crates/router/src/core/payments/operations/payment_create.rs b/crates/router/src/core/payments/operations/payment_create.rs index cc0ea89bb2b4..934002559c16 100644 --- a/crates/router/src/core/payments/operations/payment_create.rs +++ b/crates/router/src/core/payments/operations/payment_create.rs @@ -590,22 +590,16 @@ impl Domain for PaymentCreate { async fn payments_dynamic_tax_calculation<'a>( &'a self, state: &SessionState, - // key_manager_state: &common_utils::types::keymanager::KeyManagerState, payment_data: &mut PaymentData, _should_continue_confirm_transaction: &mut bool, _connector_call_type: &ConnectorCallType, business_profile: &domain::BusinessProfile, key_store: &domain::MerchantKeyStore, - // storage_scheme: storage_enums::MerchantStorageScheme, merchant_account: &domain::MerchantAccount, ) -> CustomResult<(), errors::ApiErrorResponse> { let db = state.store.as_ref(); - // let payment_intent = payment_data.payment_intent.clone(); - let key_manager_state: &KeyManagerState = &state.into(); - - // let attempt_id = payment_intent.active_attempt.get_id().clone(); - // let payment_attempt = payment_data.payment_attempt.clone(); + let key_manager_state: &KeyManagerState = &state.into(); let merchant_connector_id = business_profile .tax_connector_id @@ -625,7 +619,6 @@ impl Domain for PaymentCreate { id: merchant_connector_id.to_string(), })?; - // Derive this connector from business profile let connector_data = api::TaxCalculateConnectorData::get_connector_by_name(&mca.connector_name)?; @@ -635,7 +628,6 @@ impl Domain for PaymentCreate { key_store, payment_data, &mca, - // &customer, ) .await?; let connector_integration: services::BoxedPaymentConnectorIntegrationInterface< diff --git a/crates/router/src/core/payments/operations/payment_response.rs b/crates/router/src/core/payments/operations/payment_response.rs index 67d1d37b34e9..3851841b51db 100644 --- a/crates/router/src/core/payments/operations/payment_response.rs +++ b/crates/router/src/core/payments/operations/payment_response.rs @@ -1,8 +1,7 @@ use std::collections::HashMap; -// use api_models::payments::PaymentsDynamicTaxCalculationRequest; use async_trait::async_trait; -use common_enums::{AuthorizationStatus, SessionUpdateStatus}; +use common_enums::AuthorizationStatus; use common_utils::{ ext_traits::{AsyncExt, Encode}, types::{keymanager::KeyManagerState, MinorUnit}, @@ -509,10 +508,6 @@ impl PostUpdateTracker, types::PaymentsTaxCalculatio where F: 'b + Send, { - // if connector_ call successfull -> paymnet_intent.amount update - let _shipping_address = payment_data.address.get_shipping(); - let _amount = payment_data.amount; - payment_data = Box::pin(payment_response_update_tracker( db, payment_id, @@ -529,13 +524,19 @@ impl PostUpdateTracker, types::PaymentsTaxCalculatio } #[async_trait] -impl PostUpdateTracker, types::SessionUpdateData> for PaymentResponse { +impl PostUpdateTracker, types::PaymentsSessionUpdateData> + for PaymentResponse +{ async fn update_tracker<'b>( &'b self, db: &'b SessionState, payment_id: &api::PaymentIdType, mut payment_data: PaymentData, - router_data: types::RouterData, + router_data: types::RouterData< + F, + types::PaymentsSessionUpdateData, + types::PaymentsResponseData, + >, key_store: &domain::MerchantKeyStore, storage_scheme: enums::MerchantStorageScheme, locale: &Option, @@ -543,64 +544,53 @@ impl PostUpdateTracker, types::SessionUpdateData> fo where F: 'b + Send, { - // if connector_ call successfull -> paymnet_intent.amount update - - println!("swangi1234"); - - let session_update_details = - payment_data - .payment_intent - .tax_details - .clone() - .ok_or_else(|| { - report!(errors::ApiErrorResponse::InternalServerError) - .attach_printable("missing tax_details in payment_intent") - })?; - - println!("session_update_details: {:?}", session_update_details); - - let pmt_amount = session_update_details - .pmt - .clone() - .map(|pmt| pmt.order_tax_amount) - .ok_or(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Missing tax_details.order_tax_amount")?; - - println!("pmt_amount: {:?}", pmt_amount); - - let total_amount = MinorUnit::from(payment_data.amount) + pmt_amount; - - println!("total_amount: {:?}", total_amount); - - println!("router_data.response: {:?}", router_data.response.clone()); - - match router_data.response.clone() { - Err(_) => (None, None), - Ok(types::PaymentsResponseData::SessionUpdateResponse { status }) => { - if status == SessionUpdateStatus::Success { - ( - Some( - storage::PaymentAttemptUpdate::IncrementalAuthorizationAmountUpdate { - amount: total_amount, - amount_capturable: total_amount, - }, - ), - Some( - storage::PaymentIntentUpdate::IncrementalAuthorizationAmountUpdate { - amount: pmt_amount, - }, - ), - ) - } else { - (None, None) - } - } - _ => Err(errors::ApiErrorResponse::InternalServerError) - .attach_printable("unexpected response in session_update flow")?, - }; - - let _shipping_address = payment_data.address.get_shipping(); - let _amount = payment_data.amount; + // let session_update_details = + // payment_data + // .payment_intent + // .tax_details + // .clone() + // .ok_or_else(|| { + // report!(errors::ApiErrorResponse::InternalServerError) + // .attach_printable("missing tax_details in payment_intent") + // })?; + + // let pmt_amount = session_update_details + // .pmt + // .clone() + // .map(|pmt| pmt.order_tax_amount) + // .ok_or(errors::ApiErrorResponse::InternalServerError) + // .attach_printable("Missing tax_details.order_tax_amount")?; + + // let total_amount = MinorUnit::from(payment_data.amount) + pmt_amount; + + // // if connector_ call successfull -> paymnet_intent.amount update + // match router_data.response.clone() { + // Err(_) => (None, None), + // Ok(types::PaymentsResponseData::SessionUpdateResponse { status }) => { + // if status == SessionUpdateStatus::Success { + // ( + // Some( + // storage::PaymentAttemptUpdate::IncrementalAuthorizationAmountUpdate { + // amount: total_amount, + // amount_capturable: total_amount, + // }, + // ), + // Some( + // storage::PaymentIntentUpdate::IncrementalAuthorizationAmountUpdate { + // amount: pmt_amount, + // }, + // ), + // ) + // } else { + // (None, None) + // } + // } + // _ => Err(errors::ApiErrorResponse::InternalServerError) + // .attach_printable("unexpected response in session_update flow")?, + // }; + + // let _shipping_address = payment_data.address.get_shipping(); + // let _amount = payment_data.amount; payment_data = Box::pin(payment_response_update_tracker( db, @@ -1304,20 +1294,7 @@ async fn payment_response_update_tracker( types::PaymentsResponseData::IncrementalAuthorizationResponse { .. } => (None, None), - types::PaymentsResponseData::TaxCalculationResponse { .. } => (None, None), - types::PaymentsResponseData::SessionUpdateResponse { .. } => (None, None), - // types::PaymentsResponseData::TaxCalculationResponse { - // order_tax_amount, - // net_amount, - // shipping_address, - // } => ( - // None, - // Some(storage::PaymentAttemptUpdate::SessionUpdate { - // amount: net_amount, - // order_tax_amount, - // payment_method_shipping_address_id: shipping_address, - // }), - // ), + // types::PaymentsResponseData::SessionUpdateResponse { .. } => (None, None), types::PaymentsResponseData::MultipleCaptureResponse { capture_sync_response_list, } => match payment_data.multiple_capture_data { diff --git a/crates/router/src/core/payments/operations/payment_update.rs b/crates/router/src/core/payments/operations/payment_update.rs index f8c428c35470..5b3da3b447d7 100644 --- a/crates/router/src/core/payments/operations/payment_update.rs +++ b/crates/router/src/core/payments/operations/payment_update.rs @@ -521,23 +521,16 @@ impl Domain for PaymentUpdate { async fn payments_dynamic_tax_calculation<'a>( &'a self, state: &SessionState, - // key_manager_state: &common_utils::types::keymanager::KeyManagerState, payment_data: &mut PaymentData, _should_continue_confirm_transaction: &mut bool, _connector_call_type: &ConnectorCallType, business_profile: &domain::BusinessProfile, key_store: &domain::MerchantKeyStore, - // storage_scheme: storage_enums::MerchantStorageScheme, merchant_account: &domain::MerchantAccount, ) -> CustomResult<(), errors::ApiErrorResponse> { let db = state.store.as_ref(); - // let payment_intent = payment_data.payment_intent.clone(); let key_manager_state: &KeyManagerState = &state.into(); - // let attempt_id = payment_intent.active_attempt.get_id().clone(); - - // let payment_attempt = payment_data.payment_attempt.clone(); - let merchant_connector_id = business_profile .tax_connector_id .as_ref() @@ -556,7 +549,6 @@ impl Domain for PaymentUpdate { id: merchant_connector_id.to_string(), })?; - // Derive this connector from business profile let connector_data = api::TaxCalculateConnectorData::get_connector_by_name(&mca.connector_name)?; @@ -566,7 +558,6 @@ impl Domain for PaymentUpdate { key_store, payment_data, &mca, - // &customer, ) .await?; let connector_integration: services::BoxedPaymentConnectorIntegrationInterface< diff --git a/crates/router/src/core/payments/operations/tax_calculation.rs b/crates/router/src/core/payments/operations/tax_calculation.rs index 161d739af9e1..36a60d575218 100644 --- a/crates/router/src/core/payments/operations/tax_calculation.rs +++ b/crates/router/src/core/payments/operations/tax_calculation.rs @@ -7,7 +7,6 @@ use error_stack::ResultExt; use router_derive::PaymentOperation; use router_env::{instrument, tracing}; -// use crate::core::payments::Operation; use super::{BoxedOperation, Domain, GetTracker, Operation, UpdateTracker, ValidateRequest}; use crate::{ core::{ @@ -25,8 +24,6 @@ use crate::{ }, utils::OptionExt, }; -// use api_models::payments::PaymentsDynamicTaxCalculationRequest; -// use crate::types::api::PaymentsDynamicTaxCalculationRequest; #[derive(Debug, Clone, Copy, PaymentOperation)] #[operation(operations = "all", flow = "tax_calculation")] @@ -103,7 +100,6 @@ impl GetTracker, api::PaymentsDynamicTaxCalcu merchant_account.storage_scheme, ) .await?; - println!("shipping_address: {:?}", shipping_address); let billing_address = helpers::get_address_by_id( state, @@ -115,8 +111,6 @@ impl GetTracker, api::PaymentsDynamicTaxCalcu ) .await?; - // println!("billing: {:?}", billing); - let profile_id = payment_intent .profile_id .as_ref() @@ -218,24 +212,17 @@ impl Domain async fn payments_dynamic_tax_calculation<'a>( &'a self, state: &SessionState, - // key_manager_state: &common_utils::types::keymanager::KeyManagerState, payment_data: &mut PaymentData, should_continue_confirm_transaction: &mut bool, _connector_call_type: &ConnectorCallType, business_profile: &domain::BusinessProfile, key_store: &domain::MerchantKeyStore, - // storage_scheme: storage_enums::MerchantStorageScheme, merchant_account: &domain::MerchantAccount, ) -> errors::CustomResult<(), errors::ApiErrorResponse> { *should_continue_confirm_transaction = false; let db = state.store.as_ref(); - // let payment_intent = payment_data.payment_intent.clone(); let key_manager_state: &KeyManagerState = &state.into(); - // let attempt_id = payment_intent.active_attempt.get_id().clone(); - - // let payment_attempt = payment_data.payment_attempt.clone(); - let merchant_connector_id = business_profile .tax_connector_id .as_ref() @@ -254,7 +241,6 @@ impl Domain id: merchant_connector_id.to_string(), })?; - // Derive this connector from business profile let connector_data = api::TaxCalculateConnectorData::get_connector_by_name(&mca.connector_name)?; @@ -264,7 +250,6 @@ impl Domain key_store, payment_data, &mca, - // &customer, ) .await?; let connector_integration: services::BoxedPaymentConnectorIntegrationInterface< @@ -283,8 +268,6 @@ impl Domain .await .change_context(errors::ApiErrorResponse::InternalServerError)?; - println!("response_core: {:?}", response); - let tax_response = response .response @@ -296,18 +279,6 @@ impl Domain reason: err.reason, })?; - println!("tax_response: {:?}", tax_response); - - // payment_data - // .payment_intent - // .tax_details - // .clone() - // .map(|tax_details| { - // tax_details.pmt.map(|mut pmt| { - // pmt.order_tax_amount = tax_response.order_tax_amount; - // }); - // }); - let payment_method_type = payment_data .tax_data .clone() @@ -322,14 +293,6 @@ impl Domain }), default: None, }); - // .tax_details - // .clone() - // .map(|tax_details| { - // tax_details.pmt.map(|mut pmt| { - // pmt.order_tax_amount = tax_response.order_tax_amount; - // }); - // }); - Ok(()) } @@ -396,7 +359,6 @@ impl UpdateTracker, api::PaymentsDynamicTaxCalculati where F: 'b + Send, { - //shipping_address_id let shipping_details = payment_data .tax_data .clone() @@ -414,16 +376,11 @@ impl UpdateTracker, api::PaymentsDynamicTaxCalculati ) .await?; - let payment_intent_update = hyperswitch_domain_models::payments::payment_intent::PaymentIntentUpdate::TaxCalculationUpdate { + let payment_intent_update = hyperswitch_domain_models::payments::payment_intent::PaymentIntentUpdate::SessionResponseUpdate { tax_details: payment_data.payment_intent.tax_details.clone().ok_or(errors::ApiErrorResponse::InternalServerError)?, shipping_address_id: shipping_address.map(|address| address.address_id), }; - print!( - "update_trackers payment_intent_update : {:?}", - payment_intent_update - ); - let db = &*state.store; let payment_intent = payment_data.payment_intent.clone(); diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs index d65a0a181007..4ed700e016b2 100644 --- a/crates/router/src/core/payments/transformers.rs +++ b/crates/router/src/core/payments/transformers.rs @@ -52,8 +52,6 @@ where error_stack::Report: From<>>::Error>, { - // let (payment_method, router_data); - fp_utils::when(merchant_connector_account.is_disabled(), || { Err(errors::ApiErrorResponse::MerchantConnectorAccountDisabled) })?; @@ -66,12 +64,6 @@ where .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Failed while parsing value for ConnectorAuthType")?; - // payment_method = payment_data - // .payment_attempt - // .payment_method - // .or(payment_data.payment_attempt.payment_method) - // .get_required_value("payment_method_type")?; - let resource_id = match payment_data .payment_attempt .connector_transaction_id @@ -120,8 +112,6 @@ where payment_data.address }; - println!("unified_address {:?}", unified_address); - let router_data = types::RouterData { flow: PhantomData, merchant_id: merchant_account.get_id().clone(), @@ -179,7 +169,6 @@ where connector_response: None, integrity_check: Ok(()), }; - Ok(router_data) } @@ -1817,7 +1806,7 @@ impl TryFrom> for types::PaymentsApproveD } } -impl TryFrom> for types::SessionUpdateData { +impl TryFrom> for types::PaymentsSessionUpdateData { type Error = error_stack::Report; fn try_from(additional_data: PaymentAdditionalData<'_, F>) -> Result { @@ -1831,10 +1820,6 @@ impl TryFrom> for types::SessionUpdateDat .attach_printable("missing order_tax_amount")?; let amount = MinorUnit::from(payment_data.amount); - println!("additional_data_order_tax_amount: {:?}", order_tax_amount); - - println!("additional_data_amount: {:?}", amount.get_amount_as_i64()); - Ok(Self { net_amount: amount + order_tax_amount, //need to change after we move to connector module order_tax_amount, diff --git a/crates/router/src/core/utils.rs b/crates/router/src/core/utils.rs index 9669b42d1098..b088494a9684 100644 --- a/crates/router/src/core/utils.rs +++ b/crates/router/src/core/utils.rs @@ -858,7 +858,6 @@ pub async fn construct_payments_dynamic_tax_calculation_router_data<'a, F: Clone key_store: &domain::MerchantKeyStore, payment_data: &mut PaymentData, mca: &MerchantConnectorAccount, - // customer: &'a Option, ) -> RouterResult { let payment_intent = &payment_data.payment_intent.clone(); let payment_attempt = &payment_data.payment_attempt.clone(); @@ -884,9 +883,7 @@ pub async fn construct_payments_dynamic_tax_calculation_router_data<'a, F: Clone None, key_store, &profile_id, - // How do we derive the connector name? &mca.connector_name, - // Take this from business profile payment_attempt.merchant_connector_id.as_ref(), ) .await?; @@ -900,7 +897,6 @@ pub async fn construct_payments_dynamic_tax_calculation_router_data<'a, F: Clone .attach_printable("Failed while parsing value for ConnectorAuthType")?; let add = payment_data.address.clone(); - // println!("$$$$$$ {:?}", add); let shipping_address = payment_data .tax_data @@ -910,8 +906,6 @@ pub async fn construct_payments_dynamic_tax_calculation_router_data<'a, F: Clone .ok_or(errors::ApiErrorResponse::InternalServerError) .attach_printable("Missing shipping_details")?; - println!("$$$$$$shipping_address {:?}", shipping_address); - let order_details: Option> = payment_intent .order_details .clone() @@ -930,8 +924,6 @@ pub async fn construct_payments_dynamic_tax_calculation_router_data<'a, F: Clone }) .transpose()?; - println!("$$$$$$order2 {:?}", order_details); - let router_data = types::RouterData { flow: PhantomData, merchant_id: merchant_account.get_id().to_owned(), @@ -994,7 +986,6 @@ pub async fn construct_payments_dynamic_tax_calculation_router_data<'a, F: Clone minor_amount_captured: payment_intent.amount_captured, integrity_check: Ok(()), }; - println!("$$$$$$ {:?}", router_data); Ok(router_data) } diff --git a/crates/router/src/routes/payments.rs b/crates/router/src/routes/payments.rs index da0a71cf90af..99d1e63c178c 100644 --- a/crates/router/src/routes/payments.rs +++ b/crates/router/src/routes/payments.rs @@ -590,7 +590,7 @@ pub async fn payments_capture( .await } -//Dynamic Tax Calculation +/// Dynamic Tax Calculation #[utoipa::path( post, diff --git a/crates/router/src/types.rs b/crates/router/src/types.rs index 2dab429b37c1..3a6b736f6eac 100644 --- a/crates/router/src/types.rs +++ b/crates/router/src/types.rs @@ -57,10 +57,10 @@ pub use hyperswitch_domain_models::{ MultipleCaptureRequestData, PaymentMethodTokenizationData, PaymentsApproveData, PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, PaymentsIncrementalAuthorizationData, PaymentsPostProcessingData, - PaymentsPreProcessingData, PaymentsRejectData, PaymentsSessionData, PaymentsSyncData, - PaymentsTaxCalculationData, RefundsData, ResponseId, RetrieveFileRequestData, - SessionUpdateData, SetupMandateRequestData, SubmitEvidenceRequestData, SyncRequestType, - UploadFileRequestData, VerifyWebhookSourceRequestData, + PaymentsPreProcessingData, PaymentsRejectData, PaymentsSessionData, + PaymentsSessionUpdateData, PaymentsSyncData, PaymentsTaxCalculationData, RefundsData, + ResponseId, RetrieveFileRequestData, SetupMandateRequestData, SubmitEvidenceRequestData, + SyncRequestType, UploadFileRequestData, VerifyWebhookSourceRequestData, }, router_response_types::{ AcceptDisputeResponse, CaptureSyncResponse, DefendDisputeResponse, MandateReference, @@ -131,7 +131,7 @@ pub type PaymentsTaxCalculationRouterData = RouterData; pub type SessionUpdateRouterData = - RouterData; + RouterData; pub type PaymentsCancelRouterData = RouterData; pub type PaymentsRejectRouterData = RouterData; @@ -370,7 +370,7 @@ impl Capturable for CompleteAuthorizeData { } impl Capturable for SetupMandateRequestData {} impl Capturable for PaymentsTaxCalculationData {} -impl Capturable for SessionUpdateData {} +impl Capturable for PaymentsSessionUpdateData {} impl Capturable for PaymentsCancelData { fn get_captured_amount(&self, payment_data: &PaymentData) -> Option where diff --git a/crates/router/src/types/api.rs b/crates/router/src/types/api.rs index 4226bf7bddf6..a9c3899ec9ac 100644 --- a/crates/router/src/types/api.rs +++ b/crates/router/src/types/api.rs @@ -35,7 +35,6 @@ pub mod payments_v2; #[cfg(feature = "payouts")] pub mod payouts_v2; pub mod refunds_v2; -// pub mod calculate_tax; use std::{fmt::Debug, str::FromStr}; diff --git a/crates/router/tests/connectors/utils.rs b/crates/router/tests/connectors/utils.rs index 60ab44499f7d..788f913c5c88 100644 --- a/crates/router/tests/connectors/utils.rs +++ b/crates/router/tests/connectors/utils.rs @@ -565,8 +565,7 @@ pub trait ConnectorActions: Connector { Ok(types::PaymentsResponseData::MultipleCaptureResponse { .. }) => None, Ok(types::PaymentsResponseData::IncrementalAuthorizationResponse { .. }) => None, Ok(types::PaymentsResponseData::PostProcessingResponse { .. }) => None, - Ok(types::PaymentsResponseData::TaxCalculationResponse { .. }) => None, - Ok(types::PaymentsResponseData::SessionUpdateResponse { .. }) => None, + // Ok(types::PaymentsResponseData::SessionUpdateResponse { .. }) => None, Err(_) => None, } } @@ -1077,8 +1076,7 @@ pub fn get_connector_transaction_id( Ok(types::PaymentsResponseData::MultipleCaptureResponse { .. }) => None, Ok(types::PaymentsResponseData::IncrementalAuthorizationResponse { .. }) => None, Ok(types::PaymentsResponseData::PostProcessingResponse { .. }) => None, - Ok(types::PaymentsResponseData::TaxCalculationResponse { .. }) => None, - Ok(types::PaymentsResponseData::SessionUpdateResponse { .. }) => None, + // Ok(types::PaymentsResponseData::SessionUpdateResponse { .. }) => None, Err(_) => None, } } diff --git a/crates/router_derive/src/macros/operation.rs b/crates/router_derive/src/macros/operation.rs index 4177febb5a78..821db8659f09 100644 --- a/crates/router_derive/src/macros/operation.rs +++ b/crates/router_derive/src/macros/operation.rs @@ -116,7 +116,9 @@ impl Conversion { Derives::SessionUpdate => { syn::Ident::new("PaymentsDynamicTaxCalculationRequest", Span::call_site()) } - Derives::SessionUpdateData => syn::Ident::new("SessionUpdateData", Span::call_site()), + Derives::SessionUpdateData => { + syn::Ident::new("PaymentsSessionUpdateData", Span::call_site()) + } } } @@ -438,7 +440,7 @@ pub fn operation_derive_inner(input: DeriveInput) -> syn::Result Self::SessionUpdate { - // amount: MinorUnit::new(amount), - // order_tax_amount: MinorUnit::new(order_tax_amount), - // payment_method_shipping_address_id } } } } From 4785eaefd8e3bbedba15122d8cd66c4d52af144f Mon Sep 17 00:00:00 2001 From: swangi-kumari Date: Thu, 29 Aug 2024 15:53:59 +0530 Subject: [PATCH 21/39] refactor: solve clippy and generate schema_v2 --- crates/api_models/src/admin.rs | 6 ++--- crates/diesel_models/src/payment_intent.rs | 2 ++ crates/diesel_models/src/schema_v2.rs | 2 ++ .../src/payments/payment_attempt.rs | 6 +++++ .../payments/operations/payment_create.rs | 16 ++++++++++++ .../payments/operations/payment_update.rs | 16 ++++++++++++ .../payments/operations/tax_calculation.rs | 16 ++++++++++++ .../router/src/core/payments/transformers.rs | 8 ++++++ crates/router/src/core/utils.rs | 25 ++++++++++++++++--- 9 files changed, 90 insertions(+), 7 deletions(-) diff --git a/crates/api_models/src/admin.rs b/crates/api_models/src/admin.rs index fe7f18b97c05..e759516707ff 100644 --- a/crates/api_models/src/admin.rs +++ b/crates/api_models/src/admin.rs @@ -2065,7 +2065,7 @@ pub struct BusinessProfileCreate { pub outgoing_webhook_custom_http_headers: Option>, /// Merchant Connector id to be stored for tax_calculator connector - pub tax_connector_id: Option, + pub tax_connector_id: Option, /// Indicates if tax_calculator connector is enabled or not. /// If set to `true` tax_connector_id will be checked. @@ -2292,7 +2292,7 @@ pub struct BusinessProfileResponse { pub order_fulfillment_time_origin: Option, /// Merchant Connector id to be stored for tax_calculator connector - pub tax_connector_id: Option, + pub tax_connector_id: Option, /// Indicates if tax_calculator connector is enabled or not. /// If set to `true` tax_connector_id will be checked. @@ -2502,7 +2502,7 @@ pub struct BusinessProfileUpdate { pub outgoing_webhook_custom_http_headers: Option>, /// Merchant Connector id to be stored for tax_calculator connector - pub tax_connector_id: Option, + pub tax_connector_id: Option, /// Indicates if tax_calculator connector is enabled or not. /// If set to `true` tax_connector_id will be checked. diff --git a/crates/diesel_models/src/payment_intent.rs b/crates/diesel_models/src/payment_intent.rs index b4272594faf6..f0ff720e96f6 100644 --- a/crates/diesel_models/src/payment_intent.rs +++ b/crates/diesel_models/src/payment_intent.rs @@ -70,6 +70,8 @@ pub struct PaymentIntent { pub merchant_order_reference_id: Option, pub shipping_details: Option, pub is_payment_processor_token_flow: Option, + pub shipping_cost: Option, + pub tax_details: Option, } #[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))] diff --git a/crates/diesel_models/src/schema_v2.rs b/crates/diesel_models/src/schema_v2.rs index 818415a277b0..35bf005667c7 100644 --- a/crates/diesel_models/src/schema_v2.rs +++ b/crates/diesel_models/src/schema_v2.rs @@ -885,6 +885,8 @@ diesel::table! { merchant_order_reference_id -> Nullable, shipping_details -> Nullable, is_payment_processor_token_flow -> Nullable, + shipping_cost -> Nullable, + tax_details -> Nullable, } } diff --git a/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs b/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs index 6b8854bbcb3d..af6ea8803e8b 100644 --- a/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs +++ b/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs @@ -543,6 +543,8 @@ impl behaviour::Conversion for PaymentIntent { merchant_order_reference_id: self.merchant_order_reference_id, shipping_details: self.shipping_details.map(Encryption::from), is_payment_processor_token_flow: self.is_payment_processor_token_flow, + shipping_cost: self.shipping_cost, + tax_details: self.tax_details, }) } async fn convert_back( @@ -625,6 +627,8 @@ impl behaviour::Conversion for PaymentIntent { .async_lift(inner_decrypt) .await?, is_payment_processor_token_flow: storage_model.is_payment_processor_token_flow, + shipping_cost: storage_model.shipping_cost, + tax_details: storage_model.tax_details, }) } .await @@ -683,6 +687,8 @@ impl behaviour::Conversion for PaymentIntent { merchant_order_reference_id: self.merchant_order_reference_id, shipping_details: self.shipping_details.map(Encryption::from), is_payment_processor_token_flow: self.is_payment_processor_token_flow, + shipping_cost: self.shipping_cost, + tax_details: self.tax_details, }) } } diff --git a/crates/router/src/core/payments/operations/payment_create.rs b/crates/router/src/core/payments/operations/payment_create.rs index 74c113052e29..fad70d273833 100644 --- a/crates/router/src/core/payments/operations/payment_create.rs +++ b/crates/router/src/core/payments/operations/payment_create.rs @@ -607,6 +607,10 @@ impl Domain for PaymentCreate { .ok_or(errors::ApiErrorResponse::InternalServerError) .attach_printable("missing business_profile.tax_connector_id")?; + #[cfg(all( + any(feature = "v1", feature = "v2"), + not(feature = "merchant_connector_account_v2") + ))] let mca = db .find_by_merchant_connector_account_merchant_id_merchant_connector_id( key_manager_state, @@ -619,6 +623,18 @@ impl Domain for PaymentCreate { id: merchant_connector_id.get_string_repr().to_string(), })?; + #[cfg(all(feature = "v2", feature = "merchant_connector_account_v2"))] + let mca = db + .find_merchant_connector_account_by_id( + key_manager_state, + merchant_connector_id, + key_store, + ) + .await + .to_not_found_response(errors::ApiErrorResponse::MerchantConnectorAccountNotFound { + id: merchant_connector_id.get_string_repr().to_string(), + })?; + let connector_data = api::TaxCalculateConnectorData::get_connector_by_name(&mca.connector_name)?; diff --git a/crates/router/src/core/payments/operations/payment_update.rs b/crates/router/src/core/payments/operations/payment_update.rs index fe3c34dd230f..be1fad486026 100644 --- a/crates/router/src/core/payments/operations/payment_update.rs +++ b/crates/router/src/core/payments/operations/payment_update.rs @@ -537,6 +537,10 @@ impl Domain for PaymentUpdate { .ok_or(errors::ApiErrorResponse::InternalServerError) .attach_printable("missing business_profile.tax_connector_id")?; + #[cfg(all( + any(feature = "v1", feature = "v2"), + not(feature = "merchant_connector_account_v2") + ))] let mca = db .find_by_merchant_connector_account_merchant_id_merchant_connector_id( key_manager_state, @@ -549,6 +553,18 @@ impl Domain for PaymentUpdate { id: merchant_connector_id.get_string_repr().to_string(), })?; + #[cfg(all(feature = "v2", feature = "merchant_connector_account_v2"))] + let mca = db + .find_merchant_connector_account_by_id( + key_manager_state, + merchant_connector_id, + key_store, + ) + .await + .to_not_found_response(errors::ApiErrorResponse::MerchantConnectorAccountNotFound { + id: merchant_connector_id.get_string_repr().to_string(), + })?; + let connector_data = api::TaxCalculateConnectorData::get_connector_by_name(&mca.connector_name)?; diff --git a/crates/router/src/core/payments/operations/tax_calculation.rs b/crates/router/src/core/payments/operations/tax_calculation.rs index 9313d15b36fb..2546fc7e27a7 100644 --- a/crates/router/src/core/payments/operations/tax_calculation.rs +++ b/crates/router/src/core/payments/operations/tax_calculation.rs @@ -229,6 +229,10 @@ impl Domain .ok_or(errors::ApiErrorResponse::InternalServerError) .attach_printable("missing business_profile.tax_connector_id")?; + #[cfg(all( + any(feature = "v1", feature = "v2"), + not(feature = "merchant_connector_account_v2") + ))] let mca = db .find_by_merchant_connector_account_merchant_id_merchant_connector_id( key_manager_state, @@ -241,6 +245,18 @@ impl Domain id: merchant_connector_id.get_string_repr().to_string(), })?; + #[cfg(all(feature = "v2", feature = "merchant_connector_account_v2"))] + let mca = db + .find_merchant_connector_account_by_id( + key_manager_state, + merchant_connector_id, + key_store, + ) + .await + .to_not_found_response(errors::ApiErrorResponse::MerchantConnectorAccountNotFound { + id: merchant_connector_id.get_string_repr().to_string(), + })?; + let connector_data = api::TaxCalculateConnectorData::get_connector_by_name(&mca.connector_name)?; diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs index 686c39a353ac..2d2521f7c60b 100644 --- a/crates/router/src/core/payments/transformers.rs +++ b/crates/router/src/core/payments/transformers.rs @@ -91,8 +91,16 @@ where state, customer_data: customer, }; + + #[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "customer_v2")))] let customer_id = customer.to_owned().map(|customer| customer.customer_id); + #[cfg(all(feature = "v2", feature = "customer_v2"))] + let customer_id = customer + .to_owned() + .map(|customer| customer.merchant_reference_id) + .ok_or_else(|| errors::ApiErrorResponse::InternalServerError)?; + let unified_address = if let Some(payment_method_info) = payment_data.payment_method_info.clone() { let payment_method_billing = decrypt_generic_data::
( diff --git a/crates/router/src/core/utils.rs b/crates/router/src/core/utils.rs index 43dcfcde4d87..32a70a876813 100644 --- a/crates/router/src/core/utils.rs +++ b/crates/router/src/core/utils.rs @@ -9,7 +9,11 @@ use api_models::{ use common_enums::{IntentStatus, RequestIncrementalAuthorization}; #[cfg(feature = "payouts")] use common_utils::{crypto::Encryptable, pii::Email}; -use common_utils::{errors::CustomResult, ext_traits::AsyncExt, types::MinorUnit}; +use common_utils::{ + errors::CustomResult, + ext_traits::AsyncExt, + types::{keymanager::KeyManagerState, MinorUnit}, +}; use error_stack::{report, ResultExt}; use hyperswitch_domain_models::{ merchant_connector_account::MerchantConnectorAccount, payment_address::PaymentAddress, @@ -876,7 +880,12 @@ pub async fn construct_payments_dynamic_tax_calculation_router_data<'a, F: Clone let payment_intent = &payment_data.payment_intent.clone(); let payment_attempt = &payment_data.payment_attempt.clone(); - let key_manager_state = &state.into(); + let key_manager_state: &KeyManagerState = &state.into(); + // If profile id is not passed, get it from the business_country and business_label + #[cfg(all( + any(feature = "v1", feature = "v2"), + not(feature = "merchant_account_v2") + ))] let profile_id = get_profile_id_from_business_details( key_manager_state, key_store, @@ -891,6 +900,14 @@ pub async fn construct_payments_dynamic_tax_calculation_router_data<'a, F: Clone .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("profile_id is not set in payment_intent")?; + // Profile id will be mandatory in v2 in the request / headers + #[cfg(all(feature = "v2", feature = "merchant_account_v2"))] + let profile_id = payment_intent + .profile_id + .clone() + .get_required_value("profile_id") + .attach_printable("Profile id is a mandatory parameter")?; + let merchant_connector_account = helpers::get_merchant_connector_account( state, merchant_account.get_id(), @@ -1214,7 +1231,7 @@ pub fn get_connector_request_reference_id( /// Validate whether the profile_id exists and is associated with the merchant_id pub async fn validate_and_get_business_profile( db: &dyn StorageInterface, - key_manager_state: &common_utils::types::keymanager::KeyManagerState, + key_manager_state: &KeyManagerState, merchant_key_store: &domain::MerchantKeyStore, profile_id: Option<&common_utils::id_type::ProfileId>, merchant_id: &common_utils::id_type::MerchantId, @@ -1294,7 +1311,7 @@ pub fn get_connector_label( /// or return a `MissingRequiredField` error #[allow(clippy::too_many_arguments)] pub async fn get_profile_id_from_business_details( - key_manager_state: &common_utils::types::keymanager::KeyManagerState, + key_manager_state: &KeyManagerState, merchant_key_store: &domain::MerchantKeyStore, business_country: Option, business_label: Option<&String>, From 52b7dbfc93adf8369a995c3544dd0ef280b944f4 Mon Sep 17 00:00:00 2001 From: swangi-kumari Date: Fri, 30 Aug 2024 13:55:45 +0530 Subject: [PATCH 22/39] refactor: rename trait --- crates/api_models/src/enums.rs | 9 ++- crates/api_models/src/payments.rs | 5 +- .../src/connectors/taxjar.rs | 3 +- .../src/connectors/taxjar/transformers.rs | 8 +-- .../src/default_implementations.rs | 10 ++-- .../src/default_implementations_v2.rs | 12 ++-- .../src/router_flow_types/payments.rs | 2 +- .../src/router_request_types.rs | 2 +- .../src/api/payments.rs | 8 +-- .../src/api/payments_v2.rs | 10 ++-- crates/router/src/core/payments.rs | 59 +++++++++++-------- .../connector_integration_v2_impls.rs | 8 +-- crates/router/src/core/payments/flows.rs | 8 +-- .../payments/flows/tax_calculation_flow.rs | 26 ++++---- .../payments/operations/payment_response.rs | 6 +- .../router/src/core/payments/transformers.rs | 7 +-- crates/router/src/routes/lock_utils.rs | 2 +- crates/router/src/routes/payments.rs | 6 +- crates/router/src/types.rs | 14 ++--- crates/router/src/types/api.rs | 8 +-- crates/router/src/types/api/payments.rs | 2 +- crates/router/src/types/transformers.rs | 7 ++- crates/router_derive/src/macros/operation.rs | 12 ++-- crates/router_env/src/logger/types.rs | 2 +- 24 files changed, 121 insertions(+), 115 deletions(-) diff --git a/crates/api_models/src/enums.rs b/crates/api_models/src/enums.rs index 422072417e61..27a0c13e1ece 100644 --- a/crates/api_models/src/enums.rs +++ b/crates/api_models/src/enums.rs @@ -213,7 +213,6 @@ impl Connector { // Add Separate authentication support for connectors // | Self::Novalnet // | Self::Nexixpay - | Self::Taxjar | Self::Adyen | Self::Adyenplatform | Self::Airwallex @@ -260,6 +259,7 @@ impl Connector { | Self::Shift4 | Self::Square | Self::Stax + | Self::Taxjar | Self::Trustpay | Self::Tsys | Self::Volt @@ -411,7 +411,6 @@ pub enum FrmConnectors { Riskified, } -// #[cfg(feature = "tax_calculate")] #[derive( Clone, Copy, @@ -428,7 +427,7 @@ pub enum FrmConnectors { #[serde(rename_all = "snake_case")] #[strum(serialize_all = "snake_case")] -pub enum TaxCalculatorConnectors { +pub enum TaxConnectors { Taxjar, } @@ -673,8 +672,8 @@ pub fn convert_authentication_connector(connector_name: &str) -> Option Option { - TaxCalculatorConnectors::from_str(connector_name).ok() +pub fn convert_tax_connector(connector_name: &str) -> Option { + TaxConnectors::from_str(connector_name).ok() } #[derive( diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs index 0c248083b0db..794247c15613 100644 --- a/crates/api_models/src/payments.rs +++ b/crates/api_models/src/payments.rs @@ -4447,7 +4447,6 @@ pub struct PaymentsSessionRequest { pub merchant_connector_details: Option, } -/// Request for calling tax jar API #[derive(Debug, serde::Serialize, serde::Deserialize, Clone, ToSchema)] pub struct PaymentsDynamicTaxCalculationRequest { /// The unique identifier for the payment @@ -4461,11 +4460,9 @@ pub struct PaymentsDynamicTaxCalculationRequest { /// Payment method type pub payment_method_type: api_enums::PaymentMethodType, } -/// Response for calling tax jar API + #[derive(Debug, serde::Serialize, serde::Deserialize, Clone, ToSchema)] pub struct PaymentsDynamicTaxCalculationResponse { - /// Amount of sales tax to collect. - // pub order_tax_amount: i64, /// net amount pub net_amount: MinorUnit, } diff --git a/crates/hyperswitch_connectors/src/connectors/taxjar.rs b/crates/hyperswitch_connectors/src/connectors/taxjar.rs index 94d521e0ce03..8e464051ebee 100644 --- a/crates/hyperswitch_connectors/src/connectors/taxjar.rs +++ b/crates/hyperswitch_connectors/src/connectors/taxjar.rs @@ -39,7 +39,6 @@ use masking::{Mask, PeekInterface}; use transformers as taxjar; use crate::{constants::headers, types::ResponseRouterData, utils}; -// use crate::utils:: #[derive(Clone)] pub struct Taxjar { @@ -229,7 +228,7 @@ impl ConnectorIntegration CustomResult { let response: taxjar::TaxjarPaymentsResponse = res .response - .parse_struct("Taxjar PaymentsAuthorizeResponse") + .parse_struct("Taxjar PaymentsResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; event_builder.map(|i| i.set_response_body(&response)); router_env::logger::info!(connector_response=?response); diff --git a/crates/hyperswitch_connectors/src/connectors/taxjar/transformers.rs b/crates/hyperswitch_connectors/src/connectors/taxjar/transformers.rs index 2d36acef84ee..184a56ab053c 100644 --- a/crates/hyperswitch_connectors/src/connectors/taxjar/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/taxjar/transformers.rs @@ -16,7 +16,6 @@ use crate::{ utils::{self, AddressDetailsData, RouterData as _}, }; -//TODO: Fill the struct with respective fields pub struct TaxjarRouterData { pub amount: FloatMajorUnit, // The type of amount that a connector accepts, for example, String, i64, f64, etc. pub shipping: FloatMajorUnit, @@ -25,7 +24,6 @@ pub struct TaxjarRouterData { impl From<(FloatMajorUnit, FloatMajorUnit, T)> for TaxjarRouterData { fn from((amount, shipping, item): (FloatMajorUnit, FloatMajorUnit, T)) -> Self { - //Todo : use utils to convert the amount to the type of amount that a connector accepts Self { amount, shipping, @@ -34,7 +32,6 @@ impl From<(FloatMajorUnit, FloatMajorUnit, T)> for TaxjarRouterData { } } -//TODO: Fill the struct with respective fields #[derive(Default, Debug, Serialize, PartialEq)] pub struct TaxjarPaymentsRequest { from_country: enums::CountryAlpha2, @@ -147,7 +144,6 @@ impl TryFrom<&ConnectorAuthType> for TaxjarAuthType { } } -//TODO: Fill the struct with respective fields #[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)] pub struct TaxjarPaymentsResponse { tax: Tax, @@ -155,8 +151,8 @@ pub struct TaxjarPaymentsResponse { #[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)] pub struct Tax { - order_total_amount: FloatMajorUnit, - amount_to_collect: FloatMajorUnit, //calculated_tax_amount + order_total_amount: FloatMajorUnit, //amount + shipping_cost + amount_to_collect: FloatMajorUnit, //calculated_tax_amount } impl diff --git a/crates/hyperswitch_connectors/src/default_implementations.rs b/crates/hyperswitch_connectors/src/default_implementations.rs index c2773c377202..c28d230272e2 100644 --- a/crates/hyperswitch_connectors/src/default_implementations.rs +++ b/crates/hyperswitch_connectors/src/default_implementations.rs @@ -30,7 +30,7 @@ use hyperswitch_domain_models::{ payments::{ Approve, AuthorizeSessionToken, CalculateTax, CompleteAuthorize, CreateConnectorCustomer, IncrementalAuthorization, PostProcessing, PreProcessing, - Reject, SessionUpdate, + Reject, SdkSessionUpdate, }, webhooks::VerifyWebhookSource, }, @@ -38,8 +38,8 @@ use hyperswitch_domain_models::{ AcceptDisputeRequestData, AuthorizeSessionTokenData, CompleteAuthorizeData, ConnectorCustomerData, DefendDisputeRequestData, MandateRevokeRequestData, PaymentsApproveData, PaymentsIncrementalAuthorizationData, PaymentsPostProcessingData, - PaymentsPreProcessingData, PaymentsRejectData, PaymentsSessionUpdateData, - PaymentsTaxCalculationData, RetrieveFileRequestData, SubmitEvidenceRequestData, + PaymentsPreProcessingData, PaymentsRejectData, PaymentsTaxCalculationData, + RetrieveFileRequestData, SdkPaymentsSessionUpdateData, SubmitEvidenceRequestData, UploadFileRequestData, VerifyWebhookSourceRequestData, }, router_response_types::{ @@ -130,8 +130,8 @@ macro_rules! default_imp_for_session_update { $( impl PaymentSessionUpdate for $path::$connector {} impl ConnectorIntegration< - SessionUpdate, - PaymentsSessionUpdateData, + SdkSessionUpdate, + SdkPaymentsSessionUpdateData, PaymentsResponseData, > for $path::$connector {} diff --git a/crates/hyperswitch_connectors/src/default_implementations_v2.rs b/crates/hyperswitch_connectors/src/default_implementations_v2.rs index dcbc1c65e615..8d64ecb49353 100644 --- a/crates/hyperswitch_connectors/src/default_implementations_v2.rs +++ b/crates/hyperswitch_connectors/src/default_implementations_v2.rs @@ -14,7 +14,7 @@ use hyperswitch_domain_models::{ payments::{ Approve, Authorize, AuthorizeSessionToken, CalculateTax, Capture, CompleteAuthorize, CreateConnectorCustomer, IncrementalAuthorization, PSync, PaymentMethodToken, - PostProcessing, PreProcessing, Reject, Session, SessionUpdate, SetupMandate, Void, + PostProcessing, PreProcessing, Reject, SdkSessionUpdate, Session, SetupMandate, Void, }, refunds::{Execute, RSync}, webhooks::VerifyWebhookSource, @@ -26,9 +26,9 @@ use hyperswitch_domain_models::{ MandateRevokeRequestData, PaymentMethodTokenizationData, PaymentsApproveData, PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, PaymentsIncrementalAuthorizationData, PaymentsPostProcessingData, - PaymentsPreProcessingData, PaymentsRejectData, PaymentsSessionData, - PaymentsSessionUpdateData, PaymentsSyncData, PaymentsTaxCalculationData, RefundsData, - RetrieveFileRequestData, SetupMandateRequestData, SubmitEvidenceRequestData, + PaymentsPreProcessingData, PaymentsRejectData, PaymentsSessionData, PaymentsSyncData, + PaymentsTaxCalculationData, RefundsData, RetrieveFileRequestData, + SdkPaymentsSessionUpdateData, SetupMandateRequestData, SubmitEvidenceRequestData, UploadFileRequestData, VerifyWebhookSourceRequestData, }, router_response_types::{ @@ -186,9 +186,9 @@ macro_rules! default_imp_for_new_connector_integration_payment { TaxCalculationResponseData, > for $path::$connector{} impl ConnectorIntegrationV2< - SessionUpdate, + SdkSessionUpdate, PaymentFlowData, - PaymentsSessionUpdateData, + SdkPaymentsSessionUpdateData, PaymentsResponseData, > for $path::$connector{} )* diff --git a/crates/hyperswitch_domain_models/src/router_flow_types/payments.rs b/crates/hyperswitch_domain_models/src/router_flow_types/payments.rs index 6c895134dd54..a0e6adc855a9 100644 --- a/crates/hyperswitch_domain_models/src/router_flow_types/payments.rs +++ b/crates/hyperswitch_domain_models/src/router_flow_types/payments.rs @@ -54,4 +54,4 @@ pub struct PostProcessing; pub struct CalculateTax; #[derive(Debug, Clone)] -pub struct SessionUpdate; +pub struct SdkSessionUpdate; diff --git a/crates/hyperswitch_domain_models/src/router_request_types.rs b/crates/hyperswitch_domain_models/src/router_request_types.rs index 3fd81070495a..d27af3b0c4ab 100644 --- a/crates/hyperswitch_domain_models/src/router_request_types.rs +++ b/crates/hyperswitch_domain_models/src/router_request_types.rs @@ -804,7 +804,7 @@ pub struct PaymentsTaxCalculationData { } #[derive(Debug, Clone, Default)] -pub struct PaymentsSessionUpdateData { +pub struct SdkPaymentsSessionUpdateData { pub order_tax_amount: MinorUnit, pub net_amount: MinorUnit, } diff --git a/crates/hyperswitch_interfaces/src/api/payments.rs b/crates/hyperswitch_interfaces/src/api/payments.rs index 1193de2a18c7..695a2bbd1d3f 100644 --- a/crates/hyperswitch_interfaces/src/api/payments.rs +++ b/crates/hyperswitch_interfaces/src/api/payments.rs @@ -4,15 +4,15 @@ use hyperswitch_domain_models::{ router_flow_types::payments::{ Approve, Authorize, AuthorizeSessionToken, CalculateTax, Capture, CompleteAuthorize, CreateConnectorCustomer, IncrementalAuthorization, PSync, PaymentMethodToken, - PostProcessing, PreProcessing, Reject, Session, SessionUpdate, SetupMandate, Void, + PostProcessing, PreProcessing, Reject, SdkSessionUpdate, Session, SetupMandate, Void, }, router_request_types::{ AuthorizeSessionTokenData, CompleteAuthorizeData, ConnectorCustomerData, PaymentMethodTokenizationData, PaymentsApproveData, PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, PaymentsIncrementalAuthorizationData, PaymentsPostProcessingData, PaymentsPreProcessingData, PaymentsRejectData, - PaymentsSessionData, PaymentsSessionUpdateData, PaymentsSyncData, - PaymentsTaxCalculationData, SetupMandateRequestData, + PaymentsSessionData, PaymentsSyncData, PaymentsTaxCalculationData, + SdkPaymentsSessionUpdateData, SetupMandateRequestData, }, router_response_types::{PaymentsResponseData, TaxCalculationResponseData}, }; @@ -121,7 +121,7 @@ pub trait PaymentTaxCalculation: /// trait SessionUpdate pub trait PaymentSessionUpdate: - api::ConnectorIntegration + api::ConnectorIntegration { } diff --git a/crates/hyperswitch_interfaces/src/api/payments_v2.rs b/crates/hyperswitch_interfaces/src/api/payments_v2.rs index dff425ce2bbd..29bc6eee0612 100644 --- a/crates/hyperswitch_interfaces/src/api/payments_v2.rs +++ b/crates/hyperswitch_interfaces/src/api/payments_v2.rs @@ -5,15 +5,15 @@ use hyperswitch_domain_models::{ router_flow_types::payments::{ Approve, Authorize, AuthorizeSessionToken, CalculateTax, Capture, CompleteAuthorize, CreateConnectorCustomer, IncrementalAuthorization, PSync, PaymentMethodToken, - PostProcessing, PreProcessing, Reject, Session, SessionUpdate, SetupMandate, Void, + PostProcessing, PreProcessing, Reject, SdkSessionUpdate, Session, SetupMandate, Void, }, router_request_types::{ AuthorizeSessionTokenData, CompleteAuthorizeData, ConnectorCustomerData, PaymentMethodTokenizationData, PaymentsApproveData, PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, PaymentsIncrementalAuthorizationData, PaymentsPostProcessingData, PaymentsPreProcessingData, PaymentsRejectData, - PaymentsSessionData, PaymentsSessionUpdateData, PaymentsSyncData, - PaymentsTaxCalculationData, SetupMandateRequestData, + PaymentsSessionData, PaymentsSyncData, PaymentsTaxCalculationData, + SdkPaymentsSessionUpdateData, SetupMandateRequestData, }, router_response_types::{PaymentsResponseData, TaxCalculationResponseData}, }; @@ -104,9 +104,9 @@ pub trait PaymentTaxCalculationV2: ///trait PaymentSessionUpdateV2 pub trait PaymentSessionUpdateV2: ConnectorIntegrationV2< - SessionUpdate, + SdkSessionUpdate, PaymentFlowData, - PaymentsSessionUpdateData, + SdkPaymentsSessionUpdateData, PaymentsResponseData, > { diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs index 205b7f1aa3bf..d36592bb5e06 100644 --- a/crates/router/src/core/payments.rs +++ b/crates/router/src/core/payments.rs @@ -192,29 +192,42 @@ where ) .await?; - let connector = if format!("{operation:?}").as_str() == "PaymentSessionUpdate" { - Some(ConnectorCallType::PreDetermined( - api::ConnectorData::get_connector_by_name( - &state.conf.connectors, - "klarna", - api::GetToken::Connector, - None, - )?, - )) - } else { - get_connector_choice( - &operation, - state, - &req, - &merchant_account, - &business_profile, - &key_store, - &mut payment_data, - eligible_connectors, - mandate_type, - ) - .await? - }; + // let connector = if format!("{operation:?}").as_str() == "PaymentSessionUpdate" { + // Some(ConnectorCallType::PreDetermined( + // api::ConnectorData::get_connector_by_name( + // &state.conf.connectors, + // "klarna", + // api::GetToken::Connector, + // None, + // )?, + // )) + // } else { + // get_connector_choice( + // &operation, + // state, + // &req, + // &merchant_account, + // &business_profile, + // &key_store, + // &mut payment_data, + // eligible_connectors, + // mandate_type, + // ) + // .await? + // }; + + let connector = get_connector_choice( + &operation, + state, + &req, + &merchant_account, + &business_profile, + &key_store, + &mut payment_data, + eligible_connectors, + mandate_type, + ) + .await?; let should_add_task_to_process_tracker = should_add_task_to_process_tracker(&payment_data); diff --git a/crates/router/src/core/payments/connector_integration_v2_impls.rs b/crates/router/src/core/payments/connector_integration_v2_impls.rs index 92bc23769952..9459b6ddc56b 100644 --- a/crates/router/src/core/payments/connector_integration_v2_impls.rs +++ b/crates/router/src/core/payments/connector_integration_v2_impls.rs @@ -196,9 +196,9 @@ mod dummy_connector_default_impl { } impl services::ConnectorIntegrationV2< - api::SessionUpdate, + api::SdkSessionUpdate, types::PaymentFlowData, - types::PaymentsSessionUpdateData, + types::SdkPaymentsSessionUpdateData, types::PaymentsResponseData, > for connector::DummyConnector { @@ -661,9 +661,9 @@ macro_rules! default_imp_for_new_connector_integration_payment { > for $path::$connector{} impl services::ConnectorIntegrationV2< - api::SessionUpdate, + api::SdkSessionUpdate, types::PaymentFlowData, - types::PaymentsSessionUpdateData, + types::SdkPaymentsSessionUpdateData, types::PaymentsResponseData, > for $path::$connector{} )* diff --git a/crates/router/src/core/payments/flows.rs b/crates/router/src/core/payments/flows.rs index db1eac607758..8090401a4dac 100644 --- a/crates/router/src/core/payments/flows.rs +++ b/crates/router/src/core/payments/flows.rs @@ -3287,8 +3287,8 @@ macro_rules! default_imp_for_session_update { $( impl api::PaymentSessionUpdate for $path::$connector {} impl services::ConnectorIntegration< - api::SessionUpdate, - types::PaymentsSessionUpdateData, + api::SdkSessionUpdate, + types::SdkPaymentsSessionUpdateData, types::PaymentsResponseData > for $path::$connector {} @@ -3300,8 +3300,8 @@ impl api::PaymentSessionUpdate for connector::DummyConnector {} #[cfg(feature = "dummy_connector")] impl services::ConnectorIntegration< - api::SessionUpdate, - types::PaymentsSessionUpdateData, + api::SdkSessionUpdate, + types::SdkPaymentsSessionUpdateData, types::PaymentsResponseData, > for connector::DummyConnector { diff --git a/crates/router/src/core/payments/flows/tax_calculation_flow.rs b/crates/router/src/core/payments/flows/tax_calculation_flow.rs index fa32b542bf6d..90be96bbfafa 100644 --- a/crates/router/src/core/payments/flows/tax_calculation_flow.rs +++ b/crates/router/src/core/payments/flows/tax_calculation_flow.rs @@ -14,10 +14,10 @@ use crate::{ #[async_trait] impl ConstructFlowSpecificData< - api::SessionUpdate, - types::PaymentsSessionUpdateData, + api::SdkSessionUpdate, + types::SdkPaymentsSessionUpdateData, types::PaymentsResponseData, - > for PaymentData + > for PaymentData { async fn construct_router_data<'a>( &self, @@ -28,11 +28,11 @@ impl customer: &Option, merchant_connector_account: &helpers::MerchantConnectorAccountType, _merchant_recipient_data: Option, - ) -> RouterResult { + ) -> RouterResult { Box::pin( transformers::construct_router_date_to_update_calculated_tax::< - api::SessionUpdate, - types::PaymentsSessionUpdateData, + api::SdkSessionUpdate, + types::SdkPaymentsSessionUpdateData, >( state, self.clone(), @@ -59,10 +59,10 @@ impl } #[async_trait] -impl Feature +impl Feature for types::RouterData< - api::SessionUpdate, - types::PaymentsSessionUpdateData, + api::SdkSessionUpdate, + types::SdkPaymentsSessionUpdateData, types::PaymentsResponseData, > { @@ -77,8 +77,8 @@ impl Feature ) -> RouterResult { if connector.connector_name == types::Connector::Klarna { let connector_integration: services::BoxedPaymentConnectorIntegrationInterface< - api::SessionUpdate, - types::PaymentsSessionUpdateData, + api::SdkSessionUpdate, + types::SdkPaymentsSessionUpdateData, types::PaymentsResponseData, > = connector.connector.get_connector_integration(); @@ -118,8 +118,8 @@ impl Feature let request = match call_connector_action { payments::CallConnectorAction::Trigger => { let connector_integration: services::BoxedPaymentConnectorIntegrationInterface< - api::SessionUpdate, - types::PaymentsSessionUpdateData, + api::SdkSessionUpdate, + types::SdkPaymentsSessionUpdateData, types::PaymentsResponseData, > = connector.connector.get_connector_integration(); diff --git a/crates/router/src/core/payments/operations/payment_response.rs b/crates/router/src/core/payments/operations/payment_response.rs index 3851841b51db..23cae3385bdd 100644 --- a/crates/router/src/core/payments/operations/payment_response.rs +++ b/crates/router/src/core/payments/operations/payment_response.rs @@ -45,7 +45,7 @@ use crate::{ #[derive(Debug, Clone, Copy, router_derive::PaymentOperation)] #[operation( operations = "post_update_tracker", - flow = "sync_data, cancel_data, authorize_data, capture_data, complete_authorize_data, approve_data, reject_data, setup_mandate_data, session_data,incremental_authorization_data, tax_calculation_data, session_update_data" + flow = "sync_data, cancel_data, authorize_data, capture_data, complete_authorize_data, approve_data, reject_data, setup_mandate_data, session_data,incremental_authorization_data, tax_calculation_data, sdk_session_update_data" )] pub struct PaymentResponse; @@ -524,7 +524,7 @@ impl PostUpdateTracker, types::PaymentsTaxCalculatio } #[async_trait] -impl PostUpdateTracker, types::PaymentsSessionUpdateData> +impl PostUpdateTracker, types::SdkPaymentsSessionUpdateData> for PaymentResponse { async fn update_tracker<'b>( @@ -534,7 +534,7 @@ impl PostUpdateTracker, types::PaymentsSessionUpdate mut payment_data: PaymentData, router_data: types::RouterData< F, - types::PaymentsSessionUpdateData, + types::SdkPaymentsSessionUpdateData, types::PaymentsResponseData, >, key_store: &domain::MerchantKeyStore, diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs index 2d2521f7c60b..237e805a5036 100644 --- a/crates/router/src/core/payments/transformers.rs +++ b/crates/router/src/core/payments/transformers.rs @@ -519,10 +519,7 @@ where amount = amount + order_tax_amount; } Ok(services::ApplicationResponse::JsonWithHeaders(( - Self { - // order_tax_amount: payment_data.amount, - net_amount: amount, - }, + Self { net_amount: amount }, vec![], ))) } @@ -1886,7 +1883,7 @@ impl TryFrom> for types::PaymentsApproveD } } -impl TryFrom> for types::PaymentsSessionUpdateData { +impl TryFrom> for types::SdkPaymentsSessionUpdateData { type Error = error_stack::Report; fn try_from(additional_data: PaymentAdditionalData<'_, F>) -> Result { diff --git a/crates/router/src/routes/lock_utils.rs b/crates/router/src/routes/lock_utils.rs index 23aca71ebef0..689263f6b644 100644 --- a/crates/router/src/routes/lock_utils.rs +++ b/crates/router/src/routes/lock_utils.rs @@ -134,7 +134,7 @@ impl From for ApiIdentifier { | Flow::GetExtendedCardInfo | Flow::PaymentsCompleteAuthorize | Flow::PaymentsManualUpdate - | Flow::PaymentsDynamicTaxCalculation => Self::Payments, + | Flow::SessionUpdateTaxCalculation => Self::Payments, Flow::PayoutsCreate | Flow::PayoutsRetrieve diff --git a/crates/router/src/routes/payments.rs b/crates/router/src/routes/payments.rs index da245c79d997..918952f5bd47 100644 --- a/crates/router/src/routes/payments.rs +++ b/crates/router/src/routes/payments.rs @@ -604,14 +604,14 @@ pub async fn payments_capture( operation_id = "Create Tax Calculation for a Payment", security(("publishable_key" = [])) )] -#[instrument(skip_all, fields(flow = ?Flow::PaymentsDynamicTaxCalculation, payment_id))] +#[instrument(skip_all, fields(flow = ?Flow::SessionUpdateTaxCalculation, payment_id))] pub async fn payments_dynamic_tax_calculation( state: web::Data, req: actix_web::HttpRequest, json_payload: web::Json, path: web::Path, ) -> impl Responder { - let flow = Flow::PaymentsDynamicTaxCalculation; + let flow = Flow::SessionUpdateTaxCalculation; let payment_id = path.into_inner(); let payload = payment_types::PaymentsDynamicTaxCalculationRequest { payment_id, @@ -636,7 +636,7 @@ pub async fn payments_dynamic_tax_calculation( payload, |state, auth, payload, req_state| { payments::payments_core::< - api_types::SessionUpdate, + api_types::SdkSessionUpdate, payment_types::PaymentsDynamicTaxCalculationResponse, _, _, diff --git a/crates/router/src/types.rs b/crates/router/src/types.rs index 3a6b736f6eac..7420e0c3210e 100644 --- a/crates/router/src/types.rs +++ b/crates/router/src/types.rs @@ -32,7 +32,7 @@ use hyperswitch_domain_models::router_flow_types::{ payments::{ Approve, Authorize, AuthorizeSessionToken, Balance, CalculateTax, Capture, CompleteAuthorize, CreateConnectorCustomer, IncrementalAuthorization, InitPayment, PSync, - PostProcessing, PreProcessing, Reject, Session, SessionUpdate, SetupMandate, Void, + PostProcessing, PreProcessing, Reject, SdkSessionUpdate, Session, SetupMandate, Void, }, refunds::{Execute, RSync}, webhooks::VerifyWebhookSource, @@ -57,9 +57,9 @@ pub use hyperswitch_domain_models::{ MultipleCaptureRequestData, PaymentMethodTokenizationData, PaymentsApproveData, PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, PaymentsIncrementalAuthorizationData, PaymentsPostProcessingData, - PaymentsPreProcessingData, PaymentsRejectData, PaymentsSessionData, - PaymentsSessionUpdateData, PaymentsSyncData, PaymentsTaxCalculationData, RefundsData, - ResponseId, RetrieveFileRequestData, SetupMandateRequestData, SubmitEvidenceRequestData, + PaymentsPreProcessingData, PaymentsRejectData, PaymentsSessionData, PaymentsSyncData, + PaymentsTaxCalculationData, RefundsData, ResponseId, RetrieveFileRequestData, + SdkPaymentsSessionUpdateData, SetupMandateRequestData, SubmitEvidenceRequestData, SyncRequestType, UploadFileRequestData, VerifyWebhookSourceRequestData, }, router_response_types::{ @@ -130,8 +130,8 @@ pub type PaymentsIncrementalAuthorizationRouterData = RouterData< pub type PaymentsTaxCalculationRouterData = RouterData; -pub type SessionUpdateRouterData = - RouterData; +pub type SdkSessionUpdateRouterData = + RouterData; pub type PaymentsCancelRouterData = RouterData; pub type PaymentsRejectRouterData = RouterData; @@ -370,7 +370,7 @@ impl Capturable for CompleteAuthorizeData { } impl Capturable for SetupMandateRequestData {} impl Capturable for PaymentsTaxCalculationData {} -impl Capturable for PaymentsSessionUpdateData {} +impl Capturable for SdkPaymentsSessionUpdateData {} impl Capturable for PaymentsCancelData { fn get_captured_amount(&self, payment_data: &PaymentData) -> Option where diff --git a/crates/router/src/types/api.rs b/crates/router/src/types/api.rs index 329e644f7a0e..0e36836c20ef 100644 --- a/crates/router/src/types/api.rs +++ b/crates/router/src/types/api.rs @@ -591,12 +591,12 @@ mod test { #[derive(Clone)] pub struct TaxCalculateConnectorData { pub connector: ConnectorEnum, - pub connector_name: enums::TaxCalculatorConnectors, + pub connector_name: enums::TaxConnectors, } impl TaxCalculateConnectorData { pub fn get_connector_by_name(name: &str) -> CustomResult { - let connector_name = enums::TaxCalculatorConnectors::from_str(name) + let connector_name = enums::TaxConnectors::from_str(name) .change_context(errors::ApiErrorResponse::IncorrectConnectorNameGiven) .attach_printable_lazy(|| format!("unable to parse connector: {name}"))?; let connector = Self::convert_connector(connector_name)?; @@ -607,10 +607,10 @@ impl TaxCalculateConnectorData { } fn convert_connector( - connector_name: enums::TaxCalculatorConnectors, + connector_name: enums::TaxConnectors, ) -> CustomResult { match connector_name { - enums::TaxCalculatorConnectors::Taxjar => { + enums::TaxConnectors::Taxjar => { Ok(ConnectorEnum::Old(Box::new(connector::Taxjar::new()))) } } diff --git a/crates/router/src/types/api/payments.rs b/crates/router/src/types/api/payments.rs index 101e09a82a1d..ce1432b2301b 100644 --- a/crates/router/src/types/api/payments.rs +++ b/crates/router/src/types/api/payments.rs @@ -19,7 +19,7 @@ use error_stack::ResultExt; pub use hyperswitch_domain_models::router_flow_types::payments::{ Approve, Authorize, AuthorizeSessionToken, Balance, CalculateTax, Capture, CompleteAuthorize, CreateConnectorCustomer, IncrementalAuthorization, InitPayment, PSync, PaymentMethodToken, - PostProcessing, PreProcessing, Reject, Session, SessionUpdate, SetupMandate, Void, + PostProcessing, PreProcessing, Reject, SdkSessionUpdate, Session, SetupMandate, Void, }; pub use hyperswitch_interfaces::api::payments::{ ConnectorCustomer, MandateSetup, Payment, PaymentApprove, PaymentAuthorize, diff --git a/crates/router/src/types/transformers.rs b/crates/router/src/types/transformers.rs index efd57731c4a1..b146feb9f558 100644 --- a/crates/router/src/types/transformers.rs +++ b/crates/router/src/types/transformers.rs @@ -356,11 +356,16 @@ impl ForeignTryFrom for common_enums::RoutableConnectors { api_enums::Connector::DummyConnector6 => Self::DummyConnector6, #[cfg(feature = "dummy_connector")] api_enums::Connector::DummyConnector7 => Self::DummyConnector7, - api_enums::Connector::Threedsecureio | api_enums::Connector::Taxjar => { + api_enums::Connector::Threedsecureio => { Err(common_utils::errors::ValidationError::InvalidValue { message: "threedsecureio is not a routable connector".to_string(), })? } + api_enums::Connector::Taxjar => { + Err(common_utils::errors::ValidationError::InvalidValue { + message: "Taxjar is not a routable connector".to_string(), + })? + } }) } } diff --git a/crates/router_derive/src/macros/operation.rs b/crates/router_derive/src/macros/operation.rs index 821db8659f09..e00efdb425fc 100644 --- a/crates/router_derive/src/macros/operation.rs +++ b/crates/router_derive/src/macros/operation.rs @@ -31,8 +31,8 @@ pub enum Derives { IncrementalAuthorizationData, TaxCalculation, TaxCalculationData, - SessionUpdate, - SessionUpdateData, + SdkSessionUpdate, + SdkSessionUpdateData, } impl Derives { @@ -113,11 +113,11 @@ impl Conversion { Derives::TaxCalculationData => { syn::Ident::new("PaymentsTaxCalculationData", Span::call_site()) } - Derives::SessionUpdate => { + Derives::SdkSessionUpdate => { syn::Ident::new("PaymentsDynamicTaxCalculationRequest", Span::call_site()) } - Derives::SessionUpdateData => { - syn::Ident::new("PaymentsSessionUpdateData", Span::call_site()) + Derives::SdkSessionUpdateData => { + syn::Ident::new("SdkPaymentsSessionUpdateData", Span::call_site()) } } } @@ -440,7 +440,7 @@ pub fn operation_derive_inner(input: DeriveInput) -> syn::Result Date: Mon, 2 Sep 2024 12:37:33 +0530 Subject: [PATCH 23/39] refactor: generate open-api --- api-reference-v2/openapi_spec.json | 4 +- api-reference/openapi_spec.json | 11 +- crates/api_models/src/admin.rs | 6 + crates/api_models/src/payments.rs | 1 + crates/diesel_models/src/payment_intent.rs | 6 +- crates/diesel_models/src/schema.rs | 2 +- crates/diesel_models/src/schema_v2.rs | 2 +- package-lock.json | 1006 +++++++------------- 8 files changed, 361 insertions(+), 677 deletions(-) diff --git a/api-reference-v2/openapi_spec.json b/api-reference-v2/openapi_spec.json index a37e2c3fbc9b..55b08031d830 100644 --- a/api-reference-v2/openapi_spec.json +++ b/api-reference-v2/openapi_spec.json @@ -4940,6 +4940,7 @@ "square", "stax", "stripe", + "taxjar", "threedsecureio", "trustpay", "tsys", @@ -5054,7 +5055,8 @@ "non_banking_finance", "payout_processor", "payment_method_auth", - "authentication_processor" + "authentication_processor", + "tax_processor" ] }, "ConnectorVolumeSplit": { diff --git a/api-reference/openapi_spec.json b/api-reference/openapi_spec.json index 705df161f752..31608c5c5052 100644 --- a/api-reference/openapi_spec.json +++ b/api-reference/openapi_spec.json @@ -8597,6 +8597,7 @@ "square", "stax", "stripe", + "taxjar", "threedsecureio", "trustpay", "tsys", @@ -8711,7 +8712,8 @@ "non_banking_finance", "payout_processor", "payment_method_auth", - "authentication_processor" + "authentication_processor", + "tax_processor" ] }, "ConnectorVolumeSplit": { @@ -17373,10 +17375,10 @@ }, "PaymentsDynamicTaxCalculationRequest": { "type": "object", - "description": "Request for calling tax jar API", "required": [ "shipping", - "client_secret" + "client_secret", + "payment_method_type" ], "properties": { "shipping": { @@ -17385,6 +17387,9 @@ "client_secret": { "type": "string", "description": "Client Secret" + }, + "payment_method_type": { + "$ref": "#/components/schemas/PaymentMethodType" } } }, diff --git a/crates/api_models/src/admin.rs b/crates/api_models/src/admin.rs index e759516707ff..5963caa76681 100644 --- a/crates/api_models/src/admin.rs +++ b/crates/api_models/src/admin.rs @@ -1962,6 +1962,7 @@ pub struct BusinessProfileCreate { pub outgoing_webhook_custom_http_headers: Option>, /// Merchant Connector id to be stored for tax_calculator connector + #[schema(value_type = Option)] pub tax_connector_id: Option, /// Indicates if tax_calculator connector is enabled or not. @@ -2065,6 +2066,7 @@ pub struct BusinessProfileCreate { pub outgoing_webhook_custom_http_headers: Option>, /// Merchant Connector id to be stored for tax_calculator connector + #[schema(value_type = Option)] pub tax_connector_id: Option, /// Indicates if tax_calculator connector is enabled or not. @@ -2185,6 +2187,7 @@ pub struct BusinessProfileResponse { pub outgoing_webhook_custom_http_headers: Option>>, /// Merchant Connector id to be stored for tax_calculator connector + #[schema(value_type = Option)] pub tax_connector_id: Option, /// Indicates if tax_calculator connector is enabled or not. @@ -2292,6 +2295,7 @@ pub struct BusinessProfileResponse { pub order_fulfillment_time_origin: Option, /// Merchant Connector id to be stored for tax_calculator connector + #[schema(value_type = Option)] pub tax_connector_id: Option, /// Indicates if tax_calculator connector is enabled or not. @@ -2403,6 +2407,7 @@ pub struct BusinessProfileUpdate { pub outgoing_webhook_custom_http_headers: Option>, /// Merchant Connector id to be stored for tax_calculator connector + #[schema(value_type = Option)] pub tax_connector_id: Option, /// Indicates if tax_calculator connector is enabled or not. @@ -2502,6 +2507,7 @@ pub struct BusinessProfileUpdate { pub outgoing_webhook_custom_http_headers: Option>, /// Merchant Connector id to be stored for tax_calculator connector + #[schema(value_type = Option)] pub tax_connector_id: Option, /// Indicates if tax_calculator connector is enabled or not. diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs index 794247c15613..21f6ea82328f 100644 --- a/crates/api_models/src/payments.rs +++ b/crates/api_models/src/payments.rs @@ -4458,6 +4458,7 @@ pub struct PaymentsDynamicTaxCalculationRequest { #[schema(value_type = String)] pub client_secret: String, /// Payment method type + #[schema(value_type = PaymentMethodType)] pub payment_method_type: api_enums::PaymentMethodType, } diff --git a/crates/diesel_models/src/payment_intent.rs b/crates/diesel_models/src/payment_intent.rs index 10d5b02312d9..4ffeaefd981a 100644 --- a/crates/diesel_models/src/payment_intent.rs +++ b/crates/diesel_models/src/payment_intent.rs @@ -70,8 +70,8 @@ pub struct PaymentIntent { pub merchant_order_reference_id: Option, pub shipping_details: Option, pub is_payment_processor_token_flow: Option, - pub organization_id: common_utils::id_type::OrganizationId, pub shipping_cost: Option, + pub organization_id: common_utils::id_type::OrganizationId, pub tax_details: Option, } @@ -134,8 +134,8 @@ pub struct PaymentIntent { pub merchant_order_reference_id: Option, pub shipping_details: Option, pub is_payment_processor_token_flow: Option, - pub organization_id: common_utils::id_type::OrganizationId, pub shipping_cost: Option, + pub organization_id: common_utils::id_type::OrganizationId, pub tax_details: Option, } @@ -217,8 +217,8 @@ pub struct PaymentIntentNew { pub merchant_order_reference_id: Option, pub shipping_details: Option, pub is_payment_processor_token_flow: Option, - pub organization_id: common_utils::id_type::OrganizationId, pub shipping_cost: Option, + pub organization_id: common_utils::id_type::OrganizationId, pub tax_details: Option, } diff --git a/crates/diesel_models/src/schema.rs b/crates/diesel_models/src/schema.rs index 08fa4e184a15..406db152edc1 100644 --- a/crates/diesel_models/src/schema.rs +++ b/crates/diesel_models/src/schema.rs @@ -914,9 +914,9 @@ diesel::table! { merchant_order_reference_id -> Nullable, shipping_details -> Nullable, is_payment_processor_token_flow -> Nullable, + shipping_cost -> Nullable, #[max_length = 32] organization_id -> Varchar, - shipping_cost -> Nullable, tax_details -> Nullable, } } diff --git a/crates/diesel_models/src/schema_v2.rs b/crates/diesel_models/src/schema_v2.rs index 94cb1fd43c25..731eec86080b 100644 --- a/crates/diesel_models/src/schema_v2.rs +++ b/crates/diesel_models/src/schema_v2.rs @@ -893,9 +893,9 @@ diesel::table! { merchant_order_reference_id -> Nullable, shipping_details -> Nullable, is_payment_processor_token_flow -> Nullable, + shipping_cost -> Nullable, #[max_length = 32] organization_id -> Varchar, - shipping_cost -> Nullable, tax_details -> Nullable, } } diff --git a/package-lock.json b/package-lock.json index d7c69792ce44..19a2d2fb02ed 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,855 +1,662 @@ { "name": "hyperswitch", "version": "0.0.0", - "lockfileVersion": 3, + "lockfileVersion": 1, "requires": true, - "packages": { - "": { - "name": "hyperswitch", - "version": "0.0.0", - "devDependencies": { - "newman": "git+ssh://git@github.com:knutties/newman.git#7106e194c15d49d066fa09d9a2f18b2238f3dba8" - } - }, - "node_modules/@colors/colors": { + "dependencies": { + "@colors/colors": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", "dev": true, - "optional": true, - "engines": { - "node": ">=0.1.90" - } + "optional": true }, - "node_modules/@faker-js/faker": { + "@faker-js/faker": { "version": "5.5.3", "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-5.5.3.tgz", "integrity": "sha512-R11tGE6yIFwqpaIqcfkcg7AICXzFg14+5h5v0TfF/9+RMDL6jhzCy/pxHVOfbALGdtVYdt6JdR21tuxEgl34dw==", "dev": true }, - "node_modules/@postman/form-data": { + "@postman/form-data": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/@postman/form-data/-/form-data-3.1.1.tgz", "integrity": "sha512-vjh8Q2a8S6UCm/KKs31XFJqEEgmbjBmpPNVV2eVav6905wyFAwaUOBGA1NPBI4ERH9MMZc6w0umFgM6WbEPMdg==", "dev": true, - "dependencies": { + "requires": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" } }, - "node_modules/@postman/tough-cookie": { + "@postman/tough-cookie": { "version": "4.1.3-postman.1", "resolved": "https://registry.npmjs.org/@postman/tough-cookie/-/tough-cookie-4.1.3-postman.1.tgz", "integrity": "sha512-txpgUqZOnWYnUHZpHjkfb0IwVH4qJmyq77pPnJLlfhMtdCLMFTEeQHlzQiK906aaNCe4NEB5fGJHo9uzGbFMeA==", "dev": true, - "dependencies": { + "requires": { "psl": "^1.1.33", "punycode": "^2.1.1", "universalify": "^0.2.0", "url-parse": "^1.5.3" - }, - "engines": { - "node": ">=6" } }, - "node_modules/@postman/tunnel-agent": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/@postman/tunnel-agent/-/tunnel-agent-0.6.3.tgz", - "integrity": "sha512-k57fzmAZ2PJGxfOA4SGR05ejorHbVAa/84Hxh/2nAztjNXc4ZjOm9NUIk6/Z6LCrBvJZqjRZbN8e/nROVUPVdg==", + "@postman/tunnel-agent": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@postman/tunnel-agent/-/tunnel-agent-0.6.4.tgz", + "integrity": "sha512-CJJlq8V7rNKhAw4sBfjixKpJW00SHqebqNUQKxMoepgeWZIbdPcD+rguRcivGhS4N12PymDcKgUgSD4rVC+RjQ==", "dev": true, - "dependencies": { + "requires": { "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" } }, - "node_modules/ajv": { + "ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, - "dependencies": { + "requires": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/ansi-regex": { + "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } + "dev": true }, - "node_modules/ansi-styles": { + "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, - "dependencies": { + "requires": { "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" } }, - "node_modules/array-back": { + "array-back": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", - "dev": true, - "engines": { - "node": ">=6" - } + "dev": true }, - "node_modules/asn1": { + "asn1": { "version": "0.2.6", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", "dev": true, - "dependencies": { + "requires": { "safer-buffer": "~2.1.0" } }, - "node_modules/assert-plus": { + "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", - "dev": true, - "engines": { - "node": ">=0.8" - } + "dev": true }, - "node_modules/async": { + "async": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", "dev": true }, - "node_modules/asynckit": { + "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "dev": true }, - "node_modules/aws-sign2": { + "aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", - "dev": true, - "engines": { - "node": "*" - } + "dev": true }, - "node_modules/aws4": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", - "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==", + "aws4": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz", + "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==", "dev": true }, - "node_modules/base64-js": { + "base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] + "dev": true }, - "node_modules/bcrypt-pbkdf": { + "bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", "dev": true, - "dependencies": { + "requires": { "tweetnacl": "^0.14.3" } }, - "node_modules/bluebird": { + "bluebird": { "version": "2.11.0", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz", "integrity": "sha512-UfFSr22dmHPQqPP9XWHRhq+gWnHCYguQGkXQlbyPtW5qTnhFWA8/iXg765tH0cAjy7l/zPJ1aBTO0g5XgA7kvQ==", "dev": true }, - "node_modules/brotli": { + "brotli": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/brotli/-/brotli-1.3.3.tgz", "integrity": "sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==", "dev": true, - "dependencies": { + "requires": { "base64-js": "^1.1.2" } }, - "node_modules/caseless": { + "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", "dev": true }, - "node_modules/chalk": { + "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, - "dependencies": { + "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" } }, - "node_modules/chardet": { + "chardet": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/chardet/-/chardet-1.6.0.tgz", "integrity": "sha512-+QOTw3otC4+FxdjK9RopGpNOglADbr4WPFi0SonkO99JbpkTPbMxmdm4NenhF5Zs+4gPXLI1+y2uazws5TMe8w==", "dev": true }, - "node_modules/charset": { + "charset": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/charset/-/charset-1.0.1.tgz", "integrity": "sha512-6dVyOOYjpfFcL1Y4qChrAoQLRHvj2ziyhcm0QJlhOcAhykL/k1kTUPbeo+87MNRTRdk2OIIsIXbuF3x2wi5EXg==", - "dev": true, - "engines": { - "node": ">=4.0.0" - } + "dev": true }, - "node_modules/cli-progress": { + "cli-progress": { "version": "3.12.0", "resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.12.0.tgz", "integrity": "sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==", "dev": true, - "dependencies": { + "requires": { "string-width": "^4.2.3" - }, - "engines": { - "node": ">=4" } }, - "node_modules/cli-table3": { + "cli-table3": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz", "integrity": "sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==", "dev": true, - "dependencies": { + "requires": { + "@colors/colors": "1.5.0", "string-width": "^4.2.0" - }, - "engines": { - "node": "10.* || >= 12.*" - }, - "optionalDependencies": { - "@colors/colors": "1.5.0" } }, - "node_modules/color-convert": { + "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, - "dependencies": { + "requires": { "color-name": "1.1.3" } }, - "node_modules/color-name": { + "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, - "node_modules/colors": { + "colors": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", - "dev": true, - "engines": { - "node": ">=0.1.90" - } + "dev": true }, - "node_modules/combined-stream": { + "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "dev": true, - "dependencies": { + "requires": { "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" } }, - "node_modules/command-line-args": { + "command-line-args": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz", "integrity": "sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==", "dev": true, - "dependencies": { + "requires": { "array-back": "^3.1.0", "find-replace": "^3.0.0", "lodash.camelcase": "^4.3.0", "typical": "^4.0.0" - }, - "engines": { - "node": ">=4.0.0" } }, - "node_modules/command-line-usage": { + "command-line-usage": { "version": "6.1.3", "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-6.1.3.tgz", "integrity": "sha512-sH5ZSPr+7UStsloltmDh7Ce5fb8XPlHyoPzTpyyMuYCtervL65+ubVZ6Q61cFtFl62UyJlc8/JwERRbAFPUqgw==", "dev": true, - "dependencies": { + "requires": { "array-back": "^4.0.2", "chalk": "^2.4.2", "table-layout": "^1.0.2", "typical": "^5.2.0" }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/command-line-usage/node_modules/array-back": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", - "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/command-line-usage/node_modules/typical": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", - "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", - "dev": true, - "engines": { - "node": ">=8" + "dependencies": { + "array-back": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", + "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", + "dev": true + }, + "typical": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", + "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", + "dev": true + } } }, - "node_modules/commander": { + "commander": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/commander/-/commander-11.0.0.tgz", "integrity": "sha512-9HMlXtt/BNoYr8ooyjjNRdIilOTkVJXB+GhxMTtOKwk0R4j4lS4NpjuqmRxroBfnfTSHQIHQB7wryHhXarNjmQ==", - "dev": true, - "engines": { - "node": ">=16" - } + "dev": true }, - "node_modules/core-util-is": { + "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", "dev": true }, - "node_modules/csv-parse": { + "csv-parse": { "version": "4.16.3", "resolved": "https://registry.npmjs.org/csv-parse/-/csv-parse-4.16.3.tgz", "integrity": "sha512-cO1I/zmz4w2dcKHVvpCr7JVRu8/FymG5OEpmvsZYlccYolPBLoVGKUHgNoc4ZGkFeFlWGEDmMyBM+TTqRdW/wg==", "dev": true }, - "node_modules/dashdash": { + "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", "dev": true, - "dependencies": { + "requires": { "assert-plus": "^1.0.0" - }, - "engines": { - "node": ">=0.10" } }, - "node_modules/deep-extend": { + "deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true, - "engines": { - "node": ">=4.0.0" - } + "dev": true }, - "node_modules/delayed-stream": { + "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } + "dev": true }, - "node_modules/des.js": { + "des.js": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.1.0.tgz", "integrity": "sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==", "dev": true, - "dependencies": { + "requires": { "inherits": "^2.0.1", "minimalistic-assert": "^1.0.0" } }, - "node_modules/directory-tree": { + "directory-tree": { "version": "3.5.1", "resolved": "https://registry.npmjs.org/directory-tree/-/directory-tree-3.5.1.tgz", "integrity": "sha512-HqjZ49fDzUnKYUhHxVw9eKBqbQ+lL0v4kSBInlDlaktmLtGoV9tC54a6A0ZfYeIrkMHWTE6MwwmUXP477+UEKQ==", "dev": true, - "dependencies": { + "requires": { "command-line-args": "^5.2.0", "command-line-usage": "^6.1.1" - }, - "bin": { - "directory-tree": "bin/index.js" - }, - "engines": { - "node": ">=10.0" } }, - "node_modules/ecc-jsbn": { + "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", "dev": true, - "dependencies": { + "requires": { "jsbn": "~0.1.0", "safer-buffer": "^2.1.0" } }, - "node_modules/emoji-regex": { + "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, - "node_modules/escape-string-regexp": { + "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } + "dev": true }, - "node_modules/eventemitter3": { + "eventemitter3": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", "dev": true }, - "node_modules/extend": { + "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", "dev": true }, - "node_modules/extsprintf": { + "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", - "dev": true, - "engines": [ - "node >=0.6.0" - ] + "dev": true }, - "node_modules/fast-deep-equal": { + "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, - "node_modules/fast-json-stable-stringify": { + "fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true }, - "node_modules/file-type": { + "file-type": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", "integrity": "sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "dev": true }, - "node_modules/filesize": { + "filesize": { "version": "10.0.12", "resolved": "https://registry.npmjs.org/filesize/-/filesize-10.0.12.tgz", "integrity": "sha512-6RS9gDchbn+qWmtV2uSjo5vmKizgfCQeb5jKmqx8HyzA3MoLqqyQxN+QcjkGBJt7FjJ9qFce67Auyya5rRRbpw==", - "dev": true, - "engines": { - "node": ">= 10.4.0" - } + "dev": true }, - "node_modules/find-replace": { + "find-replace": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", "dev": true, - "dependencies": { + "requires": { "array-back": "^3.0.1" - }, - "engines": { - "node": ">=4.0.0" } }, - "node_modules/flatted": { + "flatted": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.6.tgz", "integrity": "sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ==", "dev": true }, - "node_modules/forever-agent": { + "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", - "dev": true, - "engines": { - "node": "*" - } + "dev": true }, - "node_modules/getpass": { + "getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", "dev": true, - "dependencies": { + "requires": { "assert-plus": "^1.0.0" } }, - "node_modules/handlebars": { + "handlebars": { "version": "4.7.8", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", "dev": true, - "dependencies": { + "requires": { "minimist": "^1.2.5", "neo-async": "^2.6.2", "source-map": "^0.6.1", + "uglify-js": "^3.1.4", "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" - }, - "engines": { - "node": ">=0.4.7" - }, - "optionalDependencies": { - "uglify-js": "^3.1.4" } }, - "node_modules/har-schema": { + "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", - "dev": true, - "engines": { - "node": ">=4" - } + "dev": true }, - "node_modules/har-validator": { + "har-validator": { "version": "5.1.5", "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "deprecated": "this library is no longer supported", "dev": true, - "dependencies": { + "requires": { "ajv": "^6.12.3", "har-schema": "^2.0.0" - }, - "engines": { - "node": ">=6" } }, - "node_modules/has-flag": { + "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } + "dev": true }, - "node_modules/http-reasons": { + "http-reasons": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/http-reasons/-/http-reasons-0.1.0.tgz", "integrity": "sha512-P6kYh0lKZ+y29T2Gqz+RlC9WBLhKe8kDmcJ+A+611jFfxdPsbMRQ5aNmFRM3lENqFkK+HTTL+tlQviAiv0AbLQ==", "dev": true }, - "node_modules/http-signature": { + "http-signature": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.6.tgz", "integrity": "sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==", "dev": true, - "dependencies": { + "requires": { "assert-plus": "^1.0.0", "jsprim": "^2.0.2", "sshpk": "^1.14.1" - }, - "engines": { - "node": ">=0.10" } }, - "node_modules/httpntlm": { + "httpntlm": { "version": "1.8.13", "resolved": "https://registry.npmjs.org/httpntlm/-/httpntlm-1.8.13.tgz", "integrity": "sha512-2F2FDPiWT4rewPzNMg3uPhNkP3NExENlUGADRUDPQvuftuUTGW98nLZtGemCIW3G40VhWZYgkIDcQFAwZ3mf2Q==", "dev": true, - "funding": [ - { - "type": "paypal", - "url": "https://www.paypal.com/donate/?hosted_button_id=2CKNJLZJBW8ZC" - }, - { - "type": "buymeacoffee", - "url": "https://www.buymeacoffee.com/samdecrock" - } - ], - "dependencies": { + "requires": { "des.js": "^1.0.1", "httpreq": ">=0.4.22", "js-md4": "^0.3.2", "underscore": "~1.12.1" - }, - "engines": { - "node": ">=10.4.0" } }, - "node_modules/httpreq": { + "httpreq": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/httpreq/-/httpreq-1.1.1.tgz", "integrity": "sha512-uhSZLPPD2VXXOSN8Cni3kIsoFHaU2pT/nySEU/fHr/ePbqHYr0jeiQRmUKLEirC09SFPsdMoA7LU7UXMd/w0Kw==", - "dev": true, - "engines": { - "node": ">= 6.15.1" - } + "dev": true }, - "node_modules/iconv-lite": { + "iconv-lite": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "dev": true, - "dependencies": { + "requires": { "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" } }, - "node_modules/inherits": { + "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, - "node_modules/is-fullwidth-code-point": { + "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } + "dev": true }, - "node_modules/is-typedarray": { + "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", "dev": true }, - "node_modules/isstream": { + "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", "dev": true }, - "node_modules/jose": { + "jose": { "version": "4.14.4", "resolved": "https://registry.npmjs.org/jose/-/jose-4.14.4.tgz", "integrity": "sha512-j8GhLiKmUAh+dsFXlX1aJCbt5KMibuKb+d7j1JaOJG6s2UjX1PQlW+OKB/sD4a/5ZYF4RcmYmLSndOoU3Lt/3g==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/panva" - } + "dev": true }, - "node_modules/js-md4": { + "js-md4": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/js-md4/-/js-md4-0.3.2.tgz", "integrity": "sha512-/GDnfQYsltsjRswQhN9fhv3EMw2sCpUdrdxyWDOUK7eyD++r3gRhzgiQgc/x4MAv2i1iuQ4lxO5mvqM3vj4bwA==", "dev": true }, - "node_modules/js-sha512": { + "js-sha512": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/js-sha512/-/js-sha512-0.8.0.tgz", "integrity": "sha512-PWsmefG6Jkodqt+ePTvBZCSMFgN7Clckjd0O7su3I0+BW2QWUTJNzjktHsztGLhncP2h8mcF9V9Y2Ha59pAViQ==", "dev": true }, - "node_modules/jsbn": { + "jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", "dev": true }, - "node_modules/json-schema": { + "json-schema": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", "dev": true }, - "node_modules/json-schema-traverse": { + "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, - "node_modules/json-stringify-safe": { + "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", "dev": true }, - "node_modules/jsprim": { + "jsprim": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", "integrity": "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==", "dev": true, - "engines": [ - "node >=0.6.0" - ], - "dependencies": { + "requires": { "assert-plus": "1.0.0", "extsprintf": "1.3.0", "json-schema": "0.4.0", "verror": "1.10.0" } }, - "node_modules/liquid-json": { + "liquid-json": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/liquid-json/-/liquid-json-0.3.1.tgz", "integrity": "sha512-wUayTU8MS827Dam6MxgD72Ui+KOSF+u/eIqpatOtjnvgJ0+mnDq33uC2M7J0tPK+upe/DpUAuK4JUU89iBoNKQ==", - "dev": true, - "engines": { - "node": ">=4" - } + "dev": true }, - "node_modules/lodash": { + "lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, - "node_modules/lodash.camelcase": { + "lodash.camelcase": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", "dev": true }, - "node_modules/lru-cache": { + "lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, - "dependencies": { + "requires": { "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" } }, - "node_modules/mime-db": { + "mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } + "dev": true }, - "node_modules/mime-format": { + "mime-format": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/mime-format/-/mime-format-2.0.1.tgz", "integrity": "sha512-XxU3ngPbEnrYnNbIX+lYSaYg0M01v6p2ntd2YaFksTu0vayaw5OJvbdRyWs07EYRlLED5qadUZ+xo+XhOvFhwg==", "dev": true, - "dependencies": { + "requires": { "charset": "^1.0.0" } }, - "node_modules/mime-types": { + "mime-types": { "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dev": true, - "dependencies": { + "requires": { "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" } }, - "node_modules/minimalistic-assert": { + "minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", "dev": true }, - "node_modules/minimist": { + "minimist": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "dev": true }, - "node_modules/mkdirp": { + "mkdirp": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", - "dev": true, - "bin": { - "mkdirp": "dist/cjs/src/bin.js" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } + "dev": true }, - "node_modules/neo-async": { + "neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, - "node_modules/newman": { - "version": "6.0.0", - "resolved": "git+ssh://git@github.com/knutties/newman.git#7106e194c15d49d066fa09d9a2f18b2238f3dba8", - "integrity": "sha512-peCwAcRcwBCerxnYiEXAGHkO2ZxsmJyW7BH2/PigzO1qbWtD9FXOnDuwXmp6/Hnc9uxgKqokd2YKPjkHXU6qCw==", + "newman": { + "version": "git+ssh://git@github.com/knutties/newman.git#7106e194c15d49d066fa09d9a2f18b2238f3dba8", + "from": "git+ssh://git@github.com/knutties/newman.git#7106e194c15d49d066fa09d9a2f18b2238f3dba8", "dev": true, - "license": "Apache-2.0", - "dependencies": { + "requires": { "@postman/tough-cookie": "4.1.3-postman.1", "async": "3.2.4", "chardet": "1.6.0", @@ -873,59 +680,44 @@ "serialised-error": "1.1.3", "word-wrap": "1.2.5", "xmlbuilder": "15.1.1" - }, - "bin": { - "newman": "bin/newman.js" - }, - "engines": { - "node": ">=16" } }, - "node_modules/node-oauth1": { + "node-oauth1": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/node-oauth1/-/node-oauth1-1.3.0.tgz", "integrity": "sha512-0yggixNfrA1KcBwvh/Hy2xAS1Wfs9dcg6TdFf2zN7gilcAigMdrtZ4ybrBSXBgLvGDw9V1p2MRnGBMq7XjTWLg==", "dev": true }, - "node_modules/oauth-sign": { + "oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "dev": true, - "engines": { - "node": "*" - } + "dev": true }, - "node_modules/object-hash": { + "object-hash": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-1.3.1.tgz", "integrity": "sha512-OSuu/pU4ENM9kmREg0BdNrUDIl1heYa4mBZacJc+vVWz4GtAwu7jO8s4AIt2aGRUTqxykpWzI3Oqnsm13tTMDA==", - "dev": true, - "engines": { - "node": ">= 0.10.0" - } + "dev": true }, - "node_modules/parse-ms": { + "parse-ms": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-2.1.0.tgz", "integrity": "sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA==", - "dev": true, - "engines": { - "node": ">=6" - } + "dev": true }, - "node_modules/performance-now": { + "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", "dev": true }, - "node_modules/postman-collection": { + "postman-collection": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/postman-collection/-/postman-collection-4.2.1.tgz", "integrity": "sha512-DFLt3/yu8+ldtOTIzmBUctoupKJBOVK4NZO0t68K2lIir9smQg7OdQTBjOXYy+PDh7u0pSDvD66tm93eBHEPHA==", "dev": true, - "dependencies": { + "requires": { "@faker-js/faker": "5.5.3", "file-type": "3.9.0", "http-reasons": "0.1.0", @@ -937,45 +729,35 @@ "postman-url-encoder": "3.0.5", "semver": "7.5.4", "uuid": "8.3.2" - }, - "engines": { - "node": ">=10" } }, - "node_modules/postman-collection-transformer": { + "postman-collection-transformer": { "version": "4.1.7", "resolved": "https://registry.npmjs.org/postman-collection-transformer/-/postman-collection-transformer-4.1.7.tgz", "integrity": "sha512-SxJkm/LnlFZs2splUBnS4jQFicgBptghpm4voHtNnaum3Ad64E2MHLV4fJhv58dVUmFwdSwdQUN3m2q0iLecnQ==", "dev": true, - "dependencies": { + "requires": { "commander": "8.3.0", "inherits": "2.0.4", "lodash": "4.17.21", "semver": "7.5.4", "strip-json-comments": "3.1.1" }, - "bin": { - "postman-collection-transformer": "bin/transform-collection.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/postman-collection-transformer/node_modules/commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", - "dev": true, - "engines": { - "node": ">= 12" + "dependencies": { + "commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true + } } }, - "node_modules/postman-request": { + "postman-request": { "version": "2.88.1-postman.33", "resolved": "https://registry.npmjs.org/postman-request/-/postman-request-2.88.1-postman.33.tgz", "integrity": "sha512-uL9sCML4gPH6Z4hreDWbeinKU0p0Ke261nU7OvII95NU22HN6Dk7T/SaVPaj6T4TsQqGKIFw6/woLZnH7ugFNA==", "dev": true, - "dependencies": { + "requires": { "@postman/form-data": "~3.1.1", "@postman/tough-cookie": "~4.1.3-postman.1", "@postman/tunnel-agent": "^0.6.3", @@ -998,17 +780,14 @@ "safe-buffer": "^5.1.2", "stream-length": "^1.0.2", "uuid": "^8.3.2" - }, - "engines": { - "node": ">= 6" } }, - "node_modules/postman-runtime": { + "postman-runtime": { "version": "7.33.0", "resolved": "https://registry.npmjs.org/postman-runtime/-/postman-runtime-7.33.0.tgz", "integrity": "sha512-cYCb+5Y12FwZU/T3gOj2SKiOz38pisVLc0tdppb+ZlG7iqn5aLgxghJwhjG62pZCV6uixKiQX1hNdLSk9a9Xtw==", "dev": true, - "dependencies": { + "requires": { "@postman/tough-cookie": "4.1.3-postman.1", "async": "3.2.4", "aws4": "1.12.0", @@ -1028,218 +807,173 @@ "strip-json-comments": "3.1.1", "uuid": "8.3.2" }, - "engines": { - "node": ">=12" - } - }, - "node_modules/postman-runtime/node_modules/postman-collection": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postman-collection/-/postman-collection-4.2.0.tgz", - "integrity": "sha512-tvOLgN1h6Kab6dt43PmBoV5kYO/YUta3x0C2QqfmbzmHZe47VTpZ/+gIkGlbNhjKNPUUub5X6ehxYKoaTYdy1w==", - "dev": true, "dependencies": { - "@faker-js/faker": "5.5.3", - "file-type": "3.9.0", - "http-reasons": "0.1.0", - "iconv-lite": "0.6.3", - "liquid-json": "0.3.1", - "lodash": "4.17.21", - "mime-format": "2.0.1", - "mime-types": "2.1.35", - "postman-url-encoder": "3.0.5", - "semver": "7.5.4", - "uuid": "8.3.2" - }, - "engines": { - "node": ">=10" + "aws4": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", + "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==", + "dev": true + }, + "postman-collection": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postman-collection/-/postman-collection-4.2.0.tgz", + "integrity": "sha512-tvOLgN1h6Kab6dt43PmBoV5kYO/YUta3x0C2QqfmbzmHZe47VTpZ/+gIkGlbNhjKNPUUub5X6ehxYKoaTYdy1w==", + "dev": true, + "requires": { + "@faker-js/faker": "5.5.3", + "file-type": "3.9.0", + "http-reasons": "0.1.0", + "iconv-lite": "0.6.3", + "liquid-json": "0.3.1", + "lodash": "4.17.21", + "mime-format": "2.0.1", + "mime-types": "2.1.35", + "postman-url-encoder": "3.0.5", + "semver": "7.5.4", + "uuid": "8.3.2" + } + } } }, - "node_modules/postman-sandbox": { + "postman-sandbox": { "version": "4.2.7", "resolved": "https://registry.npmjs.org/postman-sandbox/-/postman-sandbox-4.2.7.tgz", "integrity": "sha512-/EcCrKnb/o+9iLS4u+H76E0kBomJFjPptVjoDiq1uZ7Es/4aTv0MAX+0aoDxdDO+0h9sl8vy65uKQwyjN7AOaw==", "dev": true, - "dependencies": { + "requires": { "lodash": "4.17.21", "postman-collection": "4.2.0", "teleport-javascript": "1.0.0", "uvm": "2.1.1" }, - "engines": { - "node": ">=10" - } - }, - "node_modules/postman-sandbox/node_modules/postman-collection": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postman-collection/-/postman-collection-4.2.0.tgz", - "integrity": "sha512-tvOLgN1h6Kab6dt43PmBoV5kYO/YUta3x0C2QqfmbzmHZe47VTpZ/+gIkGlbNhjKNPUUub5X6ehxYKoaTYdy1w==", - "dev": true, "dependencies": { - "@faker-js/faker": "5.5.3", - "file-type": "3.9.0", - "http-reasons": "0.1.0", - "iconv-lite": "0.6.3", - "liquid-json": "0.3.1", - "lodash": "4.17.21", - "mime-format": "2.0.1", - "mime-types": "2.1.35", - "postman-url-encoder": "3.0.5", - "semver": "7.5.4", - "uuid": "8.3.2" - }, - "engines": { - "node": ">=10" + "postman-collection": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postman-collection/-/postman-collection-4.2.0.tgz", + "integrity": "sha512-tvOLgN1h6Kab6dt43PmBoV5kYO/YUta3x0C2QqfmbzmHZe47VTpZ/+gIkGlbNhjKNPUUub5X6ehxYKoaTYdy1w==", + "dev": true, + "requires": { + "@faker-js/faker": "5.5.3", + "file-type": "3.9.0", + "http-reasons": "0.1.0", + "iconv-lite": "0.6.3", + "liquid-json": "0.3.1", + "lodash": "4.17.21", + "mime-format": "2.0.1", + "mime-types": "2.1.35", + "postman-url-encoder": "3.0.5", + "semver": "7.5.4", + "uuid": "8.3.2" + } + } } }, - "node_modules/postman-url-encoder": { + "postman-url-encoder": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/postman-url-encoder/-/postman-url-encoder-3.0.5.tgz", "integrity": "sha512-jOrdVvzUXBC7C+9gkIkpDJ3HIxOHTIqjpQ4C1EMt1ZGeMvSEpbFCKq23DEfgsj46vMnDgyQf+1ZLp2Wm+bKSsA==", "dev": true, - "dependencies": { + "requires": { "punycode": "^2.1.1" - }, - "engines": { - "node": ">=10" } }, - "node_modules/pretty-ms": { + "pretty-ms": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-7.0.1.tgz", "integrity": "sha512-973driJZvxiGOQ5ONsFhOF/DtzPMOMtgC11kCpUrPGMTgqp2q/1gwzCquocrN33is0VZ5GFHXZYMM9l6h67v2Q==", "dev": true, - "dependencies": { + "requires": { "parse-ms": "^2.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/psl": { + "psl": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", "dev": true }, - "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", - "dev": true, - "engines": { - "node": ">=6" - } + "punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true }, - "node_modules/qs": { + "qs": { "version": "6.5.3", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", - "dev": true, - "engines": { - "node": ">=0.6" - } + "dev": true }, - "node_modules/querystringify": { + "querystringify": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", "dev": true }, - "node_modules/reduce-flatten": { + "reduce-flatten": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-2.0.0.tgz", "integrity": "sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==", - "dev": true, - "engines": { - "node": ">=6" - } + "dev": true }, - "node_modules/requires-port": { + "requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", "dev": true }, - "node_modules/safe-buffer": { + "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] + "dev": true }, - "node_modules/safer-buffer": { + "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, - "node_modules/semver": { + "semver": { "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, - "dependencies": { + "requires": { "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" } }, - "node_modules/serialised-error": { + "serialised-error": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/serialised-error/-/serialised-error-1.1.3.tgz", "integrity": "sha512-vybp3GItaR1ZtO2nxZZo8eOo7fnVaNtP3XE2vJKgzkKR2bagCkdJ1EpYYhEMd3qu/80DwQk9KjsNSxE3fXWq0g==", "dev": true, - "dependencies": { + "requires": { "object-hash": "^1.1.2", "stack-trace": "0.0.9", "uuid": "^3.0.0" + }, + "dependencies": { + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + } } }, - "node_modules/serialised-error/node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "dev": true, - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/source-map": { + "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "dev": true }, - "node_modules/sshpk": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", - "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", + "sshpk": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", + "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", "dev": true, - "dependencies": { + "requires": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", "bcrypt-pbkdf": "^1.0.0", @@ -1249,267 +983,203 @@ "jsbn": "~0.1.0", "safer-buffer": "^2.0.2", "tweetnacl": "~0.14.0" - }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, - "engines": { - "node": ">=0.10.0" } }, - "node_modules/stack-trace": { + "stack-trace": { "version": "0.0.9", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.9.tgz", "integrity": "sha512-vjUc6sfgtgY0dxCdnc40mK6Oftjo9+2K8H/NG81TMhgL392FtiPA9tn9RLyTxXmTLPJPjF3VyzFp6bsWFLisMQ==", - "dev": true, - "engines": { - "node": "*" - } + "dev": true }, - "node_modules/stream-length": { + "stream-length": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/stream-length/-/stream-length-1.0.2.tgz", "integrity": "sha512-aI+qKFiwoDV4rsXiS7WRoCt+v2RX1nUj17+KJC5r2gfh5xoSJIfP6Y3Do/HtvesFcTSWthIuJ3l1cvKQY/+nZg==", "dev": true, - "dependencies": { + "requires": { "bluebird": "^2.6.2" } }, - "node_modules/string-width": { + "string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, - "dependencies": { + "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" } }, - "node_modules/strip-ansi": { + "strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, - "dependencies": { + "requires": { "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" } }, - "node_modules/strip-json-comments": { + "strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "dev": true }, - "node_modules/supports-color": { + "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, - "dependencies": { + "requires": { "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" } }, - "node_modules/table-layout": { + "table-layout": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-1.0.2.tgz", "integrity": "sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A==", "dev": true, - "dependencies": { + "requires": { "array-back": "^4.0.1", "deep-extend": "~0.6.0", "typical": "^5.2.0", "wordwrapjs": "^4.0.0" }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/table-layout/node_modules/array-back": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", - "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/table-layout/node_modules/typical": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", - "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", - "dev": true, - "engines": { - "node": ">=8" + "dependencies": { + "array-back": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", + "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", + "dev": true + }, + "typical": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", + "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", + "dev": true + } } }, - "node_modules/teleport-javascript": { + "teleport-javascript": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/teleport-javascript/-/teleport-javascript-1.0.0.tgz", "integrity": "sha512-j1llvWVFyEn/6XIFDfX5LAU43DXe0GCt3NfXDwJ8XpRRMkS+i50SAkonAONBy+vxwPFBd50MFU8a2uj8R/ccLg==", "dev": true }, - "node_modules/tweetnacl": { + "tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", "dev": true }, - "node_modules/typical": { + "typical": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", - "dev": true, - "engines": { - "node": ">=8" - } + "dev": true }, - "node_modules/uglify-js": { - "version": "3.17.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", - "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", + "uglify-js": { + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", "dev": true, - "optional": true, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" - } + "optional": true }, - "node_modules/underscore": { + "underscore": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==", "dev": true }, - "node_modules/universalify": { + "universalify": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } + "dev": true }, - "node_modules/uri-js": { + "uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, - "dependencies": { + "requires": { "punycode": "^2.1.0" } }, - "node_modules/url-parse": { + "url-parse": { "version": "1.5.10", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", "dev": true, - "dependencies": { + "requires": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" } }, - "node_modules/uuid": { + "uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, - "bin": { - "uuid": "dist/bin/uuid" - } + "dev": true }, - "node_modules/uvm": { + "uvm": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/uvm/-/uvm-2.1.1.tgz", "integrity": "sha512-BZ5w8adTpNNr+zczOBRpaX/hH8UPKAf7fmCnidrcsqt3bn8KT9bDIfuS7hgRU9RXgiN01su2pwysBONY6w8W5w==", "dev": true, - "dependencies": { + "requires": { "flatted": "3.2.6" - }, - "engines": { - "node": ">=10" } }, - "node_modules/verror": { + "verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", "dev": true, - "engines": [ - "node >=0.6.0" - ], - "dependencies": { + "requires": { "assert-plus": "^1.0.0", "core-util-is": "1.0.2", "extsprintf": "^1.2.0" } }, - "node_modules/word-wrap": { + "word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "dev": true }, - "node_modules/wordwrap": { + "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", "dev": true }, - "node_modules/wordwrapjs": { + "wordwrapjs": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-4.0.1.tgz", "integrity": "sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA==", "dev": true, - "dependencies": { + "requires": { "reduce-flatten": "^2.0.0", "typical": "^5.2.0" }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/wordwrapjs/node_modules/typical": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", - "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", - "dev": true, - "engines": { - "node": ">=8" + "dependencies": { + "typical": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", + "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", + "dev": true + } } }, - "node_modules/xmlbuilder": { + "xmlbuilder": { "version": "15.1.1", "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", - "dev": true, - "engines": { - "node": ">=8.0" - } + "dev": true }, - "node_modules/yallist": { + "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", From 7669161d5c01550166ebed714e37633c07076a64 Mon Sep 17 00:00:00 2001 From: swangi-kumari Date: Mon, 2 Sep 2024 19:14:19 +0530 Subject: [PATCH 24/39] refactor: clippy --- .../router/src/core/payments/operations/payment_response.rs | 2 +- crates/router/src/core/utils.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/router/src/core/payments/operations/payment_response.rs b/crates/router/src/core/payments/operations/payment_response.rs index 23cae3385bdd..9a97a3c71955 100644 --- a/crates/router/src/core/payments/operations/payment_response.rs +++ b/crates/router/src/core/payments/operations/payment_response.rs @@ -563,7 +563,7 @@ impl PostUpdateTracker, types::SdkPaymentsSessionUpd // let total_amount = MinorUnit::from(payment_data.amount) + pmt_amount; - // // if connector_ call successfull -> paymnet_intent.amount update + // // if connector_ call successful -> payment_intent.amount update // match router_data.response.clone() { // Err(_) => (None, None), // Ok(types::PaymentsResponseData::SessionUpdateResponse { status }) => { diff --git a/crates/router/src/core/utils.rs b/crates/router/src/core/utils.rs index 32a70a876813..e998a32d098d 100644 --- a/crates/router/src/core/utils.rs +++ b/crates/router/src/core/utils.rs @@ -4,7 +4,7 @@ use std::{collections::HashSet, marker::PhantomData, str::FromStr}; use api_models::payouts::PayoutVendorAccountDetails; use api_models::{ enums::{DisputeStage, DisputeStatus}, - payments::{Address, OrderDetailsWithAmount}, + payments::OrderDetailsWithAmount, }; use common_enums::{IntentStatus, RequestIncrementalAuthorization}; #[cfg(feature = "payouts")] @@ -105,7 +105,7 @@ pub async fn construct_payout_router_data<'a, F>( state: a.state.map(Encryptable::into_inner), }; - Address { + api_models::payments::Address { phone: Some(phone_details), address: Some(address_details), email: a.email.to_owned().map(Email::from), From 03a932bcd21493d44860a3408afff129cfb20732 Mon Sep 17 00:00:00 2001 From: swangi-kumari Date: Tue, 3 Sep 2024 12:25:34 +0530 Subject: [PATCH 25/39] refactor: resolve conflicts --- crates/api_models/src/payments.rs | 2 +- .../src/default_implementations.rs | 12 ++++++++++-- .../src/business_profile.rs | 4 ++-- crates/router/src/core/payments/flows.rs | 8 -------- .../src/core/payments/operations/payment_update.rs | 1 + .../src/core/payments/operations/tax_calculation.rs | 2 +- crates/router/src/core/payments/transformers.rs | 6 +++++- crates/router/src/core/utils.rs | 2 +- crates/router/src/routes/payments.rs | 6 +++--- 9 files changed, 24 insertions(+), 19 deletions(-) diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs index 68499013bad8..e9b702a0b7c0 100644 --- a/crates/api_models/src/payments.rs +++ b/crates/api_models/src/payments.rs @@ -4479,7 +4479,7 @@ pub struct PaymentsDynamicTaxCalculationRequest { /// The unique identifier for the payment #[serde(skip_deserializing)] #[schema(value_type = String)] - pub payment_id:id_type::PaymentId, + pub payment_id: id_type::PaymentId, /// The shipping address for the payment pub shipping: Address, /// Client Secret diff --git a/crates/hyperswitch_connectors/src/default_implementations.rs b/crates/hyperswitch_connectors/src/default_implementations.rs index 7ca7dcde1fd0..87b946fe1793 100644 --- a/crates/hyperswitch_connectors/src/default_implementations.rs +++ b/crates/hyperswitch_connectors/src/default_implementations.rs @@ -128,7 +128,11 @@ default_imp_for_calculate_tax!( connectors::Stax, connectors::Novalnet, connectors::Nexixpay, - connectors::Fiuu + connectors::Fiuu, + connectors::Globepay, + connectors::Worldline, + connectors::Powertranz, + connectors::Tsys ); macro_rules! default_imp_for_session_update { @@ -155,7 +159,11 @@ default_imp_for_session_update!( connectors::Taxjar, connectors::Novalnet, connectors::Nexixpay, - connectors::Fiuu + connectors::Fiuu, + connectors::Globepay, + connectors::Worldline, + connectors::Powertranz, + connectors::Tsys ); use crate::connectors; diff --git a/crates/hyperswitch_domain_models/src/business_profile.rs b/crates/hyperswitch_domain_models/src/business_profile.rs index e4f5233c8e43..25278aadae2f 100644 --- a/crates/hyperswitch_domain_models/src/business_profile.rs +++ b/crates/hyperswitch_domain_models/src/business_profile.rs @@ -54,7 +54,7 @@ pub struct BusinessProfile { pub outgoing_webhook_custom_http_headers: OptionalEncryptableValue, pub always_collect_billing_details_from_wallet_connector: Option, pub always_collect_shipping_details_from_wallet_connector: Option, - pub tax_connector_id: Option, + pub tax_connector_id: Option, pub is_tax_connector_enabled: bool, pub api_version: common_enums::ApiVersion, } @@ -631,7 +631,7 @@ pub struct BusinessProfileSetter { pub frm_routing_algorithm_id: Option, pub payout_routing_algorithm_id: Option, pub default_fallback_routing: Option, - pub tax_connector_id: Option, + pub tax_connector_id: Option, pub is_tax_connector_enabled: bool, } diff --git a/crates/router/src/core/payments/flows.rs b/crates/router/src/core/payments/flows.rs index 9b5b14751ca2..7d2556d2da71 100644 --- a/crates/router/src/core/payments/flows.rs +++ b/crates/router/src/core/payments/flows.rs @@ -3129,7 +3129,6 @@ default_imp_for_calculate_tax!( connector::Ebanx, connector::Forte, connector::Globalpay, - connector::Globepay, connector::Gocardless, connector::Gpayments, connector::Iatapay, @@ -3153,7 +3152,6 @@ default_imp_for_calculate_tax!( connector::Payu, connector::Placetopay, connector::Plaid, - connector::Powertranz, connector::Prophetpay, connector::Rapyd, connector::Razorpay, @@ -3164,12 +3162,10 @@ default_imp_for_calculate_tax!( connector::Shift4, connector::Threedsecureio, connector::Trustpay, - connector::Tsys, connector::Volt, connector::Wellsfargo, connector::Wellsfargopayout, connector::Wise, - connector::Worldline, connector::Worldpay, connector::Zen, connector::Zsl @@ -3222,7 +3218,6 @@ default_imp_for_session_update!( connector::Ebanx, connector::Forte, connector::Globalpay, - connector::Globepay, connector::Gocardless, connector::Gpayments, connector::Iatapay, @@ -3246,7 +3241,6 @@ default_imp_for_session_update!( connector::Payu, connector::Placetopay, connector::Plaid, - connector::Powertranz, connector::Prophetpay, connector::Rapyd, connector::Razorpay, @@ -3257,12 +3251,10 @@ default_imp_for_session_update!( connector::Shift4, connector::Threedsecureio, connector::Trustpay, - connector::Tsys, connector::Volt, connector::Wellsfargo, connector::Wellsfargopayout, connector::Wise, - connector::Worldline, connector::Worldpay, connector::Zen, connector::Zsl diff --git a/crates/router/src/core/payments/operations/payment_update.rs b/crates/router/src/core/payments/operations/payment_update.rs index 7c5f880bf0a8..1b81acc39c64 100644 --- a/crates/router/src/core/payments/operations/payment_update.rs +++ b/crates/router/src/core/payments/operations/payment_update.rs @@ -23,6 +23,7 @@ use crate::{ mandate::helpers as m_helpers, payment_methods::cards::create_encrypted_data, payments::{self, helpers, operations, CustomerDetails, PaymentAddress, PaymentData}, + utils as core_utils, }, routes::{app::ReqState, SessionState}, services, diff --git a/crates/router/src/core/payments/operations/tax_calculation.rs b/crates/router/src/core/payments/operations/tax_calculation.rs index 2546fc7e27a7..ebfce6e7af40 100644 --- a/crates/router/src/core/payments/operations/tax_calculation.rs +++ b/crates/router/src/core/payments/operations/tax_calculation.rs @@ -79,7 +79,7 @@ impl GetTracker, api::PaymentsDynamicTaxCalcu let payment_attempt = db .find_payment_attempt_by_payment_id_merchant_id_attempt_id( - payment_intent.payment_id.as_str(), + &payment_intent.payment_id, merchant_id, payment_intent.active_attempt.get_id().as_str(), storage_scheme, diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs index 270249ca0340..bea1db723293 100644 --- a/crates/router/src/core/payments/transformers.rs +++ b/crates/router/src/core/payments/transformers.rs @@ -123,7 +123,11 @@ where merchant_id: merchant_account.get_id().clone(), customer_id, connector: connector_id.to_owned(), - payment_id: payment_data.payment_attempt.payment_id.clone(), + payment_id: payment_data + .payment_attempt + .payment_id + .get_string_repr() + .to_owned(), attempt_id: payment_data.payment_attempt.attempt_id.clone(), status: payment_data.payment_attempt.status, payment_method: diesel_models::enums::PaymentMethod::default(), diff --git a/crates/router/src/core/utils.rs b/crates/router/src/core/utils.rs index 0b8642bfbd91..3fa093bb4718 100644 --- a/crates/router/src/core/utils.rs +++ b/crates/router/src/core/utils.rs @@ -962,7 +962,7 @@ pub async fn construct_payments_dynamic_tax_calculation_router_data<'a, F: Clone customer_id: payment_intent.customer_id.to_owned(), connector_customer: None, connector: mca.connector_name.clone(), - payment_id: payment_attempt.payment_id.clone(), + payment_id: payment_attempt.payment_id.get_string_repr().to_owned(), attempt_id: payment_attempt.attempt_id.clone(), status: payment_attempt.status, payment_method: diesel_models::enums::PaymentMethod::default(), diff --git a/crates/router/src/routes/payments.rs b/crates/router/src/routes/payments.rs index 12bfe822b313..aaea15ab4182 100644 --- a/crates/router/src/routes/payments.rs +++ b/crates/router/src/routes/payments.rs @@ -617,7 +617,7 @@ pub async fn payments_dynamic_tax_calculation( state: web::Data, req: actix_web::HttpRequest, json_payload: web::Json, - path: web::Path, + path: web::Path, ) -> impl Responder { let flow = Flow::SessionUpdateTaxCalculation; let payment_id = path.into_inner(); @@ -635,7 +635,7 @@ pub async fn payments_dynamic_tax_calculation( HeaderPayload::default() } }; - tracing::Span::current().record("payment_id", &payload.payment_id); + tracing::Span::current().record("payment_id", payload.payment_id.get_string_repr()); let locking_action = payload.get_locking_input(flow.clone()); Box::pin(api::server_wrap( flow, @@ -1831,7 +1831,7 @@ impl GetLockingInput for payment_types::PaymentsDynamicTaxCalculationRequest { { api_locking::LockAction::Hold { input: api_locking::LockingInput { - unique_locking_key: self.payment_id.to_owned(), + unique_locking_key: self.payment_id.get_string_repr().to_owned(), api_identifier: lock_utils::ApiIdentifier::from(flow), override_lock_retries: None, }, From 57f66788883672fe7dbeb180a41056a2196172bb Mon Sep 17 00:00:00 2001 From: swangi-kumari Date: Wed, 4 Sep 2024 01:31:57 +0530 Subject: [PATCH 26/39] refactor: resolve comments --- Cargo.lock | 1 - crates/api_models/src/events/payment.rs | 6 +- crates/diesel_models/Cargo.toml | 1 - crates/diesel_models/src/payment_intent.rs | 5 +- .../src/connectors/taxjar/transformers.rs | 1 - .../src/payments/payment_intent.rs | 6 +- .../src/router_response_types.rs | 1 - .../payments/operations/payment_create.rs | 3 +- .../payments/operations/payment_update.rs | 3 +- .../payments/operations/tax_calculation.rs | 3 +- crates/router/src/core/utils.rs | 59 ++++--------------- 11 files changed, 23 insertions(+), 66 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index db7b0347dafc..30eb871a67f0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2711,7 +2711,6 @@ dependencies = [ name = "diesel_models" version = "0.1.0" dependencies = [ - "api_models", "async-bb8-diesel", "common_enums", "common_utils", diff --git a/crates/api_models/src/events/payment.rs b/crates/api_models/src/events/payment.rs index a14b87b18235..aa8cd43ca97f 100644 --- a/crates/api_models/src/events/payment.rs +++ b/crates/api_models/src/events/payment.rs @@ -71,11 +71,7 @@ impl ApiEventMetric for PaymentsDynamicTaxCalculationRequest { } } -impl ApiEventMetric for PaymentsDynamicTaxCalculationResponse { - fn get_api_event_type(&self) -> Option { - Some(ApiEventsType::ResourceListAPI) - } -} +impl ApiEventMetric for PaymentsDynamicTaxCalculationResponse {} impl ApiEventMetric for PaymentsCancelRequest { fn get_api_event_type(&self) -> Option { diff --git a/crates/diesel_models/Cargo.toml b/crates/diesel_models/Cargo.toml index 344fb4b82aac..e95a39e0089d 100644 --- a/crates/diesel_models/Cargo.toml +++ b/crates/diesel_models/Cargo.toml @@ -19,7 +19,6 @@ merchant_connector_account_v2 = [] payment_v2 = [] [dependencies] -api_models = { version = "0.1.0", path = "../api_models", package = "api_models" } async-bb8-diesel = { git = "https://github.com/jarnura/async-bb8-diesel", rev = "53b4ab901aab7635c8215fd1c2d542c8db443094" } diesel = { version = "2.2.3", features = ["postgres", "serde_json", "time", "64-column-tables"] } error-stack = "0.4.1" diff --git a/crates/diesel_models/src/payment_intent.rs b/crates/diesel_models/src/payment_intent.rs index 85b8d389736c..1f1de0f98ce1 100644 --- a/crates/diesel_models/src/payment_intent.rs +++ b/crates/diesel_models/src/payment_intent.rs @@ -1,5 +1,4 @@ -use api_models::enums; -use common_enums::RequestIncrementalAuthorization; +use common_enums::{PaymentMethodType, RequestIncrementalAuthorization}; use common_utils::{encryption::Encryption, pii, types::MinorUnit}; use diesel::{AsChangeset, Identifiable, Insertable, Queryable, Selectable}; use serde::{Deserialize, Serialize}; @@ -151,7 +150,7 @@ common_utils::impl_to_sql_from_sql_json!(TaxDetails); #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct PmtTax { pub order_tax_amount: MinorUnit, - pub pmt: enums::PaymentMethodType, + pub pmt: PaymentMethodType, } #[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)] diff --git a/crates/hyperswitch_connectors/src/connectors/taxjar/transformers.rs b/crates/hyperswitch_connectors/src/connectors/taxjar/transformers.rs index 184a56ab053c..49caaad61e2f 100644 --- a/crates/hyperswitch_connectors/src/connectors/taxjar/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/taxjar/transformers.rs @@ -192,7 +192,6 @@ impl response: Ok(TaxCalculationResponseData { order_tax_amount: calculated_tax, net_amount: (total_amount + calculated_tax), - shipping_address: None, }), ..item.data }) diff --git a/crates/hyperswitch_domain_models/src/payments/payment_intent.rs b/crates/hyperswitch_domain_models/src/payments/payment_intent.rs index 3b1f749595ee..2b371ace6434 100644 --- a/crates/hyperswitch_domain_models/src/payments/payment_intent.rs +++ b/crates/hyperswitch_domain_models/src/payments/payment_intent.rs @@ -304,7 +304,7 @@ pub struct PaymentIntentUpdateInternal { pub merchant_order_reference_id: Option, pub shipping_details: Option>>, pub is_payment_processor_token_flow: Option, - pub tax_details: diesel_models::TaxDetails, + pub tax_details: Option, } impl From for PaymentIntentUpdateInternal { @@ -491,7 +491,7 @@ impl From for PaymentIntentUpdateInternal { tax_details, shipping_address_id, } => Self { - tax_details, + tax_details: Some(tax_details), shipping_address_id, ..Default::default() }, @@ -749,7 +749,7 @@ impl From for diesel_models::PaymentIntentUpdateInt merchant_order_reference_id, shipping_details: shipping_details.map(Encryption::from), is_payment_processor_token_flow, - tax_details: Some(tax_details), + tax_details, } } } diff --git a/crates/hyperswitch_domain_models/src/router_response_types.rs b/crates/hyperswitch_domain_models/src/router_response_types.rs index d81866b1199c..4012224e09c1 100644 --- a/crates/hyperswitch_domain_models/src/router_response_types.rs +++ b/crates/hyperswitch_domain_models/src/router_response_types.rs @@ -77,7 +77,6 @@ pub enum PaymentsResponseData { pub struct TaxCalculationResponseData { pub order_tax_amount: MinorUnit, pub net_amount: MinorUnit, - pub shipping_address: Option, } #[derive(serde::Serialize, Debug, Clone)] diff --git a/crates/router/src/core/payments/operations/payment_create.rs b/crates/router/src/core/payments/operations/payment_create.rs index 40c8a8063576..363696fb1b6c 100644 --- a/crates/router/src/core/payments/operations/payment_create.rs +++ b/crates/router/src/core/payments/operations/payment_create.rs @@ -661,7 +661,8 @@ impl Domain for PaymentCreate { None, ) .await - .change_context(errors::ApiErrorResponse::InternalServerError)?; + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Tax connector Response Failed")?; let tax_response = response diff --git a/crates/router/src/core/payments/operations/payment_update.rs b/crates/router/src/core/payments/operations/payment_update.rs index 1b81acc39c64..be83eb156c56 100644 --- a/crates/router/src/core/payments/operations/payment_update.rs +++ b/crates/router/src/core/payments/operations/payment_update.rs @@ -590,7 +590,8 @@ impl Domain for PaymentUpdate { None, ) .await - .change_context(errors::ApiErrorResponse::InternalServerError)?; + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Tax connector Response Failed")?; let tax_response = response diff --git a/crates/router/src/core/payments/operations/tax_calculation.rs b/crates/router/src/core/payments/operations/tax_calculation.rs index ebfce6e7af40..578762859bfe 100644 --- a/crates/router/src/core/payments/operations/tax_calculation.rs +++ b/crates/router/src/core/payments/operations/tax_calculation.rs @@ -282,7 +282,8 @@ impl Domain None, ) .await - .change_context(errors::ApiErrorResponse::InternalServerError)?; + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Tax connector Response Failed")?; let tax_response = response diff --git a/crates/router/src/core/utils.rs b/crates/router/src/core/utils.rs index 3fa093bb4718..22ba13e71c78 100644 --- a/crates/router/src/core/utils.rs +++ b/crates/router/src/core/utils.rs @@ -874,56 +874,18 @@ pub async fn construct_upload_file_router_data<'a>( pub async fn construct_payments_dynamic_tax_calculation_router_data<'a, F: Clone>( state: &'a SessionState, merchant_account: &domain::MerchantAccount, - key_store: &domain::MerchantKeyStore, + _key_store: &domain::MerchantKeyStore, payment_data: &mut PaymentData, - mca: &MerchantConnectorAccount, + merchant_connector_account: &MerchantConnectorAccount, ) -> RouterResult { let payment_intent = &payment_data.payment_intent.clone(); let payment_attempt = &payment_data.payment_attempt.clone(); - let key_manager_state: &KeyManagerState = &state.into(); - // If profile id is not passed, get it from the business_country and business_label - #[cfg(all( - any(feature = "v1", feature = "v2"), - not(feature = "merchant_account_v2") - ))] - let profile_id = get_profile_id_from_business_details( - key_manager_state, - key_store, - payment_intent.business_country, - payment_intent.business_label.as_ref(), - merchant_account, - payment_intent.profile_id.as_ref(), - &*state.store, - false, - ) - .await - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("profile_id is not set in payment_intent")?; - - // Profile id will be mandatory in v2 in the request / headers - #[cfg(all(feature = "v2", feature = "merchant_account_v2"))] - let profile_id = payment_intent - .profile_id - .clone() - .get_required_value("profile_id") - .attach_printable("Profile id is a mandatory parameter")?; - - let merchant_connector_account = helpers::get_merchant_connector_account( - state, - merchant_account.get_id(), - None, - key_store, - &profile_id, - &mca.connector_name, - payment_attempt.merchant_connector_id.as_ref(), - ) - .await?; - - let test_mode = merchant_connector_account.is_test_mode_on(); + let test_mode = merchant_connector_account.test_mode; let connector_auth_type: types::ConnectorAuthType = merchant_connector_account - .get_connector_account_details() + .connector_account_details + .clone() .parse_value("ConnectorAuthType") .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Failed while parsing value for ConnectorAuthType")?; @@ -961,7 +923,7 @@ pub async fn construct_payments_dynamic_tax_calculation_router_data<'a, F: Clone merchant_id: merchant_account.get_id().to_owned(), customer_id: payment_intent.customer_id.to_owned(), connector_customer: None, - connector: mca.connector_name.clone(), + connector: merchant_connector_account.connector_name.clone(), payment_id: payment_attempt.payment_id.get_string_repr().to_owned(), attempt_id: payment_attempt.attempt_id.clone(), status: payment_attempt.status, @@ -986,10 +948,11 @@ pub async fn construct_payments_dynamic_tax_calculation_router_data<'a, F: Clone connector_api_version: None, request: types::PaymentsTaxCalculationData { amount: payment_intent.amount, - shipping_cost: payment_intent - .shipping_cost - .ok_or(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Missing shipping_cost")?, + shipping_cost: payment_intent.shipping_cost.ok_or( + errors::ApiErrorResponse::MissingRequiredField { + field_name: "shipping_cost", + }, + )?, order_details, currency: payment_intent .currency From 090b3450fa7df09314ce718e9a4697883e67af16 Mon Sep 17 00:00:00 2001 From: swangi-kumari Date: Wed, 4 Sep 2024 01:53:03 +0530 Subject: [PATCH 27/39] refactor: add Dynamic Tax Calculation to openapi --- crates/openapi/src/routes/payments.rs | 18 ++++++++++++++++++ crates/router/src/routes/payments.rs | 12 ------------ 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/crates/openapi/src/routes/payments.rs b/crates/openapi/src/routes/payments.rs index 0e3bb9fe072f..1ed8c541bfd8 100644 --- a/crates/openapi/src/routes/payments.rs +++ b/crates/openapi/src/routes/payments.rs @@ -545,3 +545,21 @@ pub fn payments_external_authentication() {} security(("publishable_key" = [])) )] pub fn payments_complete_authorize() {} + +/// Dynamic Tax Calculation +/// +/// +#[utoipa::path( + post, + path = "/payments/{payment_id}/calculate_tax", + request_body=PaymentsDynamicTaxCalculationRequest, + responses( + (status = 200, description = "Tax Calculation is done", body = PaymentsDynamicTaxCalculationResponse), + (status = 400, description = "Missing mandatory fields") + ), + tag = "Payments", + operation_id = "Create Tax Calculation for a Payment", + security(("publishable_key" = [])) +)] + +pub fn payments_dynamic_tax_calculation() {} diff --git a/crates/router/src/routes/payments.rs b/crates/router/src/routes/payments.rs index aaea15ab4182..08e4ff63880e 100644 --- a/crates/router/src/routes/payments.rs +++ b/crates/router/src/routes/payments.rs @@ -600,18 +600,6 @@ pub async fn payments_capture( /// Dynamic Tax Calculation -#[utoipa::path( - post, - path = "/payments/{payment_id}/calculate_tax", - request_body=PaymentsDynamicTaxCalculationRequest, - responses( - (status = 200, description = "Tax Calculation is done", body = PaymentsDynamicTaxCalculationResponse), - (status = 400, description = "Missing mandatory fields") - ), - tag = "Payments", - operation_id = "Create Tax Calculation for a Payment", - security(("publishable_key" = [])) -)] #[instrument(skip_all, fields(flow = ?Flow::SessionUpdateTaxCalculation, payment_id))] pub async fn payments_dynamic_tax_calculation( state: web::Data, From 128e2fe433b5014fc7b867c430b3aeb17c6ae151 Mon Sep 17 00:00:00 2001 From: swangi-kumari Date: Wed, 4 Sep 2024 13:13:59 +0530 Subject: [PATCH 28/39] refactor: resolve comments --- crates/api_models/src/payments.rs | 1 + .../payments/operations/payment_create.rs | 145 ++++++++------- .../payments/operations/payment_response.rs | 50 ++---- .../payments/operations/payment_update.rs | 149 +++++++-------- .../payments/operations/tax_calculation.rs | 169 +++++++++--------- .../router/src/core/payments/transformers.rs | 3 +- crates/router/src/core/utils.rs | 4 +- 7 files changed, 259 insertions(+), 262 deletions(-) diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs index e9b702a0b7c0..b83a66b3633c 100644 --- a/crates/api_models/src/payments.rs +++ b/crates/api_models/src/payments.rs @@ -294,6 +294,7 @@ pub struct PaymentsRequest { #[schema(value_type = Option, example = 6540)] pub amount_to_capture: Option, + /// The shipping cost for the payment. This is required for tax calculation in some regions. #[schema(value_type = Option, example = 6540)] pub shipping_cost: Option, diff --git a/crates/router/src/core/payments/operations/payment_create.rs b/crates/router/src/core/payments/operations/payment_create.rs index 363696fb1b6c..c24c5ba0c4ce 100644 --- a/crates/router/src/core/payments/operations/payment_create.rs +++ b/crates/router/src/core/payments/operations/payment_create.rs @@ -598,91 +598,98 @@ impl Domain for PaymentCreate { key_store: &domain::MerchantKeyStore, merchant_account: &domain::MerchantAccount, ) -> CustomResult<(), errors::ApiErrorResponse> { - let db = state.store.as_ref(); + if business_profile.is_tax_connector_enabled { + let db = state.store.as_ref(); - let key_manager_state: &KeyManagerState = &state.into(); + let key_manager_state: &KeyManagerState = &state.into(); - let merchant_connector_id = business_profile - .tax_connector_id - .as_ref() - .ok_or(errors::ApiErrorResponse::InternalServerError) - .attach_printable("missing business_profile.tax_connector_id")?; + let merchant_connector_id = business_profile + .tax_connector_id + .as_ref() + .ok_or(errors::ApiErrorResponse::InternalServerError) + .attach_printable("missing business_profile.tax_connector_id")?; + + #[cfg(all( + any(feature = "v1", feature = "v2"), + not(feature = "merchant_connector_account_v2") + ))] + let mca = db + .find_by_merchant_connector_account_merchant_id_merchant_connector_id( + key_manager_state, + &business_profile.merchant_id, + merchant_connector_id, + key_store, + ) + .await + .to_not_found_response( + errors::ApiErrorResponse::MerchantConnectorAccountNotFound { + id: merchant_connector_id.get_string_repr().to_string(), + }, + )?; - #[cfg(all( - any(feature = "v1", feature = "v2"), - not(feature = "merchant_connector_account_v2") - ))] - let mca = db - .find_by_merchant_connector_account_merchant_id_merchant_connector_id( - key_manager_state, - &business_profile.merchant_id, - merchant_connector_id, + #[cfg(all(feature = "v2", feature = "merchant_connector_account_v2"))] + let mca = db + .find_merchant_connector_account_by_id( + key_manager_state, + merchant_connector_id, + key_store, + ) + .await + .to_not_found_response( + errors::ApiErrorResponse::MerchantConnectorAccountNotFound { + id: merchant_connector_id.get_string_repr().to_string(), + }, + )?; + + let connector_data = + api::TaxCalculateConnectorData::get_connector_by_name(&mca.connector_name)?; + + let router_data = core_utils::construct_payments_dynamic_tax_calculation_router_data( + state, + merchant_account, key_store, + payment_data, + &mca, ) - .await - .to_not_found_response(errors::ApiErrorResponse::MerchantConnectorAccountNotFound { - id: merchant_connector_id.get_string_repr().to_string(), - })?; + .await?; + let connector_integration: services::BoxedPaymentConnectorIntegrationInterface< + api::CalculateTax, + types::PaymentsTaxCalculationData, + types::TaxCalculationResponseData, + > = connector_data.connector.get_connector_integration(); - #[cfg(all(feature = "v2", feature = "merchant_connector_account_v2"))] - let mca = db - .find_merchant_connector_account_by_id( - key_manager_state, - merchant_connector_id, - key_store, + let response = services::execute_connector_processing_step( + state, + connector_integration, + &router_data, + payments::CallConnectorAction::Trigger, + None, ) .await - .to_not_found_response(errors::ApiErrorResponse::MerchantConnectorAccountNotFound { - id: merchant_connector_id.get_string_repr().to_string(), - })?; - - let connector_data = - api::TaxCalculateConnectorData::get_connector_by_name(&mca.connector_name)?; - - let router_data = core_utils::construct_payments_dynamic_tax_calculation_router_data( - state, - merchant_account, - key_store, - payment_data, - &mca, - ) - .await?; - let connector_integration: services::BoxedPaymentConnectorIntegrationInterface< - api::CalculateTax, - types::PaymentsTaxCalculationData, - types::TaxCalculationResponseData, - > = connector_data.connector.get_connector_integration(); - - let response = services::execute_connector_processing_step( - state, - connector_integration, - &router_data, - payments::CallConnectorAction::Trigger, - None, - ) - .await - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Tax connector Response Failed")?; + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Tax connector Response Failed")?; - let tax_response = - response - .response - .map_err(|err| errors::ApiErrorResponse::ExternalConnectorError { + let tax_response = response.response.map_err(|err| { + errors::ApiErrorResponse::ExternalConnectorError { code: err.code, message: err.message, connector: connector_data.connector_name.clone().to_string(), status_code: err.status_code, reason: err.reason, - })?; + } + })?; - payment_data.payment_intent.tax_details = Some(diesel_models::TaxDetails { - default: Some(diesel_models::DefaultTax { - order_tax_amount: tax_response.order_tax_amount, - }), - pmt: None, - }); + payment_data.payment_intent.tax_details = Some(diesel_models::TaxDetails { + default: Some(diesel_models::DefaultTax { + order_tax_amount: tax_response.order_tax_amount, + }), + pmt: None, + }); - Ok(()) + Ok(()) + } else { + Ok(()) + } } #[instrument(skip_all)] diff --git a/crates/router/src/core/payments/operations/payment_response.rs b/crates/router/src/core/payments/operations/payment_response.rs index 140c809e7702..b81d083a3934 100644 --- a/crates/router/src/core/payments/operations/payment_response.rs +++ b/crates/router/src/core/payments/operations/payment_response.rs @@ -494,32 +494,21 @@ impl PostUpdateTracker, types::PaymentsTaxCalculatio { async fn update_tracker<'b>( &'b self, - db: &'b SessionState, - payment_id: &api::PaymentIdType, - mut payment_data: PaymentData, - router_data: types::RouterData< + _db: &'b SessionState, + _payment_id: &api::PaymentIdType, + payment_data: PaymentData, + _router_data: types::RouterData< F, types::PaymentsTaxCalculationData, types::PaymentsResponseData, >, - key_store: &domain::MerchantKeyStore, - storage_scheme: enums::MerchantStorageScheme, - locale: &Option, + _key_store: &domain::MerchantKeyStore, + _storage_scheme: enums::MerchantStorageScheme, + _locale: &Option, ) -> RouterResult> where F: 'b + Send, { - payment_data = Box::pin(payment_response_update_tracker( - db, - payment_id, - payment_data, - router_data, - key_store, - storage_scheme, - locale, - )) - .await?; - Ok(payment_data) } } @@ -530,17 +519,17 @@ impl PostUpdateTracker, types::SdkPaymentsSessionUpd { async fn update_tracker<'b>( &'b self, - db: &'b SessionState, - payment_id: &api::PaymentIdType, - mut payment_data: PaymentData, - router_data: types::RouterData< + _db: &'b SessionState, + _payment_id: &api::PaymentIdType, + payment_data: PaymentData, + _router_data: types::RouterData< F, types::SdkPaymentsSessionUpdateData, types::PaymentsResponseData, >, - key_store: &domain::MerchantKeyStore, - storage_scheme: enums::MerchantStorageScheme, - locale: &Option, + _key_store: &domain::MerchantKeyStore, + _storage_scheme: enums::MerchantStorageScheme, + _locale: &Option, ) -> RouterResult> where F: 'b + Send, @@ -593,17 +582,6 @@ impl PostUpdateTracker, types::SdkPaymentsSessionUpd // let _shipping_address = payment_data.address.get_shipping(); // let _amount = payment_data.amount; - payment_data = Box::pin(payment_response_update_tracker( - db, - payment_id, - payment_data, - router_data, - key_store, - storage_scheme, - locale, - )) - .await?; - Ok(payment_data) } } diff --git a/crates/router/src/core/payments/operations/payment_update.rs b/crates/router/src/core/payments/operations/payment_update.rs index be83eb156c56..05f46384156f 100644 --- a/crates/router/src/core/payments/operations/payment_update.rs +++ b/crates/router/src/core/payments/operations/payment_update.rs @@ -528,90 +528,97 @@ impl Domain for PaymentUpdate { key_store: &domain::MerchantKeyStore, merchant_account: &domain::MerchantAccount, ) -> CustomResult<(), errors::ApiErrorResponse> { - let db = state.store.as_ref(); - let key_manager_state: &KeyManagerState = &state.into(); + if business_profile.is_tax_connector_enabled { + let db = state.store.as_ref(); + let key_manager_state: &KeyManagerState = &state.into(); - let merchant_connector_id = business_profile - .tax_connector_id - .as_ref() - .ok_or(errors::ApiErrorResponse::InternalServerError) - .attach_printable("missing business_profile.tax_connector_id")?; - - #[cfg(all( - any(feature = "v1", feature = "v2"), - not(feature = "merchant_connector_account_v2") - ))] - let mca = db - .find_by_merchant_connector_account_merchant_id_merchant_connector_id( - key_manager_state, - &business_profile.merchant_id, - merchant_connector_id, + let merchant_connector_id = business_profile + .tax_connector_id + .as_ref() + .ok_or(errors::ApiErrorResponse::InternalServerError) + .attach_printable("missing business_profile.tax_connector_id")?; + + #[cfg(all( + any(feature = "v1", feature = "v2"), + not(feature = "merchant_connector_account_v2") + ))] + let mca = db + .find_by_merchant_connector_account_merchant_id_merchant_connector_id( + key_manager_state, + &business_profile.merchant_id, + merchant_connector_id, + key_store, + ) + .await + .to_not_found_response( + errors::ApiErrorResponse::MerchantConnectorAccountNotFound { + id: merchant_connector_id.get_string_repr().to_string(), + }, + )?; + + #[cfg(all(feature = "v2", feature = "merchant_connector_account_v2"))] + let mca = db + .find_merchant_connector_account_by_id( + key_manager_state, + merchant_connector_id, + key_store, + ) + .await + .to_not_found_response( + errors::ApiErrorResponse::MerchantConnectorAccountNotFound { + id: merchant_connector_id.get_string_repr().to_string(), + }, + )?; + + let connector_data = + api::TaxCalculateConnectorData::get_connector_by_name(&mca.connector_name)?; + + let router_data = core_utils::construct_payments_dynamic_tax_calculation_router_data( + state, + merchant_account, key_store, + payment_data, + &mca, ) - .await - .to_not_found_response(errors::ApiErrorResponse::MerchantConnectorAccountNotFound { - id: merchant_connector_id.get_string_repr().to_string(), - })?; - - #[cfg(all(feature = "v2", feature = "merchant_connector_account_v2"))] - let mca = db - .find_merchant_connector_account_by_id( - key_manager_state, - merchant_connector_id, - key_store, + .await?; + let connector_integration: services::BoxedPaymentConnectorIntegrationInterface< + api::CalculateTax, + types::PaymentsTaxCalculationData, + types::TaxCalculationResponseData, + > = connector_data.connector.get_connector_integration(); + + let response = services::execute_connector_processing_step( + state, + connector_integration, + &router_data, + payments::CallConnectorAction::Trigger, + None, ) .await - .to_not_found_response(errors::ApiErrorResponse::MerchantConnectorAccountNotFound { - id: merchant_connector_id.get_string_repr().to_string(), - })?; - - let connector_data = - api::TaxCalculateConnectorData::get_connector_by_name(&mca.connector_name)?; - - let router_data = core_utils::construct_payments_dynamic_tax_calculation_router_data( - state, - merchant_account, - key_store, - payment_data, - &mca, - ) - .await?; - let connector_integration: services::BoxedPaymentConnectorIntegrationInterface< - api::CalculateTax, - types::PaymentsTaxCalculationData, - types::TaxCalculationResponseData, - > = connector_data.connector.get_connector_integration(); - - let response = services::execute_connector_processing_step( - state, - connector_integration, - &router_data, - payments::CallConnectorAction::Trigger, - None, - ) - .await - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Tax connector Response Failed")?; + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Tax connector Response Failed")?; - let tax_response = - response - .response - .map_err(|err| errors::ApiErrorResponse::ExternalConnectorError { + let tax_response = response.response.map_err(|err| { + errors::ApiErrorResponse::ExternalConnectorError { code: err.code, message: err.message, connector: connector_data.connector_name.clone().to_string(), status_code: err.status_code, reason: err.reason, - })?; + } + })?; - payment_data.payment_intent.tax_details = Some(diesel_models::TaxDetails { - default: Some(diesel_models::DefaultTax { - order_tax_amount: tax_response.order_tax_amount, - }), - pmt: None, - }); + payment_data.payment_intent.tax_details = Some(diesel_models::TaxDetails { + default: Some(diesel_models::DefaultTax { + order_tax_amount: tax_response.order_tax_amount, + }), + pmt: None, + }); - Ok(()) + Ok(()) + } else { + Ok(()) + } } #[instrument(skip_all)] diff --git a/crates/router/src/core/payments/operations/tax_calculation.rs b/crates/router/src/core/payments/operations/tax_calculation.rs index 578762859bfe..b9197ce74c2c 100644 --- a/crates/router/src/core/payments/operations/tax_calculation.rs +++ b/crates/router/src/core/payments/operations/tax_calculation.rs @@ -219,98 +219,105 @@ impl Domain key_store: &domain::MerchantKeyStore, merchant_account: &domain::MerchantAccount, ) -> errors::CustomResult<(), errors::ApiErrorResponse> { - *should_continue_confirm_transaction = false; - let db = state.store.as_ref(); - let key_manager_state: &KeyManagerState = &state.into(); - - let merchant_connector_id = business_profile - .tax_connector_id - .as_ref() - .ok_or(errors::ApiErrorResponse::InternalServerError) - .attach_printable("missing business_profile.tax_connector_id")?; - - #[cfg(all( - any(feature = "v1", feature = "v2"), - not(feature = "merchant_connector_account_v2") - ))] - let mca = db - .find_by_merchant_connector_account_merchant_id_merchant_connector_id( - key_manager_state, - &business_profile.merchant_id, - merchant_connector_id, + if business_profile.is_tax_connector_enabled { + *should_continue_confirm_transaction = false; + let db = state.store.as_ref(); + let key_manager_state: &KeyManagerState = &state.into(); + + let merchant_connector_id = business_profile + .tax_connector_id + .as_ref() + .ok_or(errors::ApiErrorResponse::InternalServerError) + .attach_printable("missing business_profile.tax_connector_id")?; + + #[cfg(all( + any(feature = "v1", feature = "v2"), + not(feature = "merchant_connector_account_v2") + ))] + let mca = db + .find_by_merchant_connector_account_merchant_id_merchant_connector_id( + key_manager_state, + &business_profile.merchant_id, + merchant_connector_id, + key_store, + ) + .await + .to_not_found_response( + errors::ApiErrorResponse::MerchantConnectorAccountNotFound { + id: merchant_connector_id.get_string_repr().to_string(), + }, + )?; + + #[cfg(all(feature = "v2", feature = "merchant_connector_account_v2"))] + let mca = db + .find_merchant_connector_account_by_id( + key_manager_state, + merchant_connector_id, + key_store, + ) + .await + .to_not_found_response( + errors::ApiErrorResponse::MerchantConnectorAccountNotFound { + id: merchant_connector_id.get_string_repr().to_string(), + }, + )?; + + let connector_data = + api::TaxCalculateConnectorData::get_connector_by_name(&mca.connector_name)?; + + let router_data = core_utils::construct_payments_dynamic_tax_calculation_router_data( + state, + merchant_account, key_store, + payment_data, + &mca, ) - .await - .to_not_found_response(errors::ApiErrorResponse::MerchantConnectorAccountNotFound { - id: merchant_connector_id.get_string_repr().to_string(), - })?; - - #[cfg(all(feature = "v2", feature = "merchant_connector_account_v2"))] - let mca = db - .find_merchant_connector_account_by_id( - key_manager_state, - merchant_connector_id, - key_store, + .await?; + let connector_integration: services::BoxedPaymentConnectorIntegrationInterface< + api::CalculateTax, + types::PaymentsTaxCalculationData, + types::TaxCalculationResponseData, + > = connector_data.connector.get_connector_integration(); + + let response = services::execute_connector_processing_step( + state, + connector_integration, + &router_data, + payments::CallConnectorAction::Trigger, + None, ) .await - .to_not_found_response(errors::ApiErrorResponse::MerchantConnectorAccountNotFound { - id: merchant_connector_id.get_string_repr().to_string(), - })?; - - let connector_data = - api::TaxCalculateConnectorData::get_connector_by_name(&mca.connector_name)?; - - let router_data = core_utils::construct_payments_dynamic_tax_calculation_router_data( - state, - merchant_account, - key_store, - payment_data, - &mca, - ) - .await?; - let connector_integration: services::BoxedPaymentConnectorIntegrationInterface< - api::CalculateTax, - types::PaymentsTaxCalculationData, - types::TaxCalculationResponseData, - > = connector_data.connector.get_connector_integration(); + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Tax connector Response Failed")?; - let response = services::execute_connector_processing_step( - state, - connector_integration, - &router_data, - payments::CallConnectorAction::Trigger, - None, - ) - .await - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Tax connector Response Failed")?; - - let tax_response = - response - .response - .map_err(|err| errors::ApiErrorResponse::ExternalConnectorError { + let tax_response = response.response.map_err(|err| { + errors::ApiErrorResponse::ExternalConnectorError { code: err.code, message: err.message, connector: connector_data.connector_name.clone().to_string(), status_code: err.status_code, reason: err.reason, - })?; + } + })?; - let payment_method_type = payment_data - .tax_data - .clone() - .map(|tax_data| tax_data.payment_method_type) - .ok_or(errors::ApiErrorResponse::InternalServerError) - .attach_printable("missing tax_data.payment_method_type")?; - - payment_data.payment_intent.tax_details = Some(diesel_models::TaxDetails { - pmt: Some(diesel_models::PmtTax { - order_tax_amount: tax_response.order_tax_amount, - pmt: payment_method_type, - }), - default: None, - }); - Ok(()) + let payment_method_type = payment_data + .tax_data + .clone() + .map(|tax_data| tax_data.payment_method_type) + .ok_or(errors::ApiErrorResponse::InternalServerError) + .attach_printable("missing tax_data.payment_method_type")?; + + payment_data.payment_intent.tax_details = Some(diesel_models::TaxDetails { + pmt: Some(diesel_models::PmtTax { + order_tax_amount: tax_response.order_tax_amount, + pmt: payment_method_type, + }), + default: None, + }); + Ok(()) + } else { + Ok(()) + } } #[instrument(skip_all)] diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs index bea1db723293..0775a92e9527 100644 --- a/crates/router/src/core/payments/transformers.rs +++ b/crates/router/src/core/payments/transformers.rs @@ -1901,8 +1901,7 @@ impl TryFrom> for types::SdkPaymentsSessi .tax_details .clone() .and_then(|tax| tax.pmt.map(|pmt| pmt.order_tax_amount)) - .ok_or(errors::ApiErrorResponse::InternalServerError) - .attach_printable("missing order_tax_amount")?; + .ok_or(errors::ApiErrorResponse::MissingRequiredField { field_name: "order_tax_amount" })?; let amount = MinorUnit::from(payment_data.amount); Ok(Self { diff --git a/crates/router/src/core/utils.rs b/crates/router/src/core/utils.rs index 22ba13e71c78..d5eb60cf16c6 100644 --- a/crates/router/src/core/utils.rs +++ b/crates/router/src/core/utils.rs @@ -954,9 +954,7 @@ pub async fn construct_payments_dynamic_tax_calculation_router_data<'a, F: Clone }, )?, order_details, - currency: payment_intent - .currency - .ok_or(errors::ApiErrorResponse::InternalServerError)?, + currency: payment_data.currency, shipping_address, }, response: Err(ErrorResponse::default()), From 4de2043c40ee27a7470299b5d609f742607c906f Mon Sep 17 00:00:00 2001 From: swangi-kumari Date: Wed, 4 Sep 2024 15:19:29 +0530 Subject: [PATCH 29/39] refactor: update payment_method_type in payment attempt of get tracker --- crates/router/src/core/payments.rs | 48 +++++-------------- .../payments/operations/tax_calculation.rs | 4 +- .../router/src/core/payments/transformers.rs | 4 +- 3 files changed, 18 insertions(+), 38 deletions(-) diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs index 0dcb2c70df3c..6423ca81081e 100644 --- a/crates/router/src/core/payments.rs +++ b/crates/router/src/core/payments.rs @@ -192,42 +192,18 @@ where ) .await?; - let connector = if format!("{operation:?}").as_str() == "PaymentSessionUpdate" { - Some(ConnectorCallType::PreDetermined( - api::ConnectorData::get_connector_by_name( - &state.conf.connectors, - "klarna", - api::GetToken::Connector, - None, - )?, - )) - } else { - get_connector_choice( - &operation, - state, - &req, - &merchant_account, - &business_profile, - &key_store, - &mut payment_data, - eligible_connectors, - mandate_type, - ) - .await? - }; - - // let connector = get_connector_choice( - // &operation, - // state, - // &req, - // &merchant_account, - // &business_profile, - // &key_store, - // &mut payment_data, - // eligible_connectors, - // mandate_type, - // ) - // .await?; + let connector = get_connector_choice( + &operation, + state, + &req, + &merchant_account, + &business_profile, + &key_store, + &mut payment_data, + eligible_connectors, + mandate_type, + ) + .await?; let should_add_task_to_process_tracker = should_add_task_to_process_tracker(&payment_data); diff --git a/crates/router/src/core/payments/operations/tax_calculation.rs b/crates/router/src/core/payments/operations/tax_calculation.rs index b9197ce74c2c..2af659b81bd2 100644 --- a/crates/router/src/core/payments/operations/tax_calculation.rs +++ b/crates/router/src/core/payments/operations/tax_calculation.rs @@ -77,7 +77,7 @@ impl GetTracker, api::PaymentsDynamicTaxCalcu helpers::authenticate_client_secret(Some(&request.client_secret), &payment_intent)?; - let payment_attempt = db + let mut payment_attempt = db .find_payment_attempt_by_payment_id_merchant_id_attempt_id( &payment_intent.payment_id, merchant_id, @@ -91,6 +91,8 @@ impl GetTracker, api::PaymentsDynamicTaxCalcu let amount = payment_attempt.get_total_amount().into(); + payment_attempt.payment_method_type = Some(request.payment_method_type.clone()); + let shipping_address = helpers::get_address_by_id( state, payment_intent.shipping_address_id.clone(), diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs index 0775a92e9527..07a687af5996 100644 --- a/crates/router/src/core/payments/transformers.rs +++ b/crates/router/src/core/payments/transformers.rs @@ -1901,7 +1901,9 @@ impl TryFrom> for types::SdkPaymentsSessi .tax_details .clone() .and_then(|tax| tax.pmt.map(|pmt| pmt.order_tax_amount)) - .ok_or(errors::ApiErrorResponse::MissingRequiredField { field_name: "order_tax_amount" })?; + .ok_or(errors::ApiErrorResponse::MissingRequiredField { + field_name: "order_tax_amount", + })?; let amount = MinorUnit::from(payment_data.amount); Ok(Self { From 47145152219d2307d3a905f79bc84f98e498bf98 Mon Sep 17 00:00:00 2001 From: swangi-kumari Date: Wed, 4 Sep 2024 16:11:19 +0530 Subject: [PATCH 30/39] refactor: amount changes --- crates/common_utils/src/types.rs | 2 +- .../src/connectors/taxjar/transformers.rs | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/crates/common_utils/src/types.rs b/crates/common_utils/src/types.rs index a7fda21eba56..f0ecb7085901 100644 --- a/crates/common_utils/src/types.rs +++ b/crates/common_utils/src/types.rs @@ -507,7 +507,7 @@ pub struct FloatMajorUnit(f64); impl FloatMajorUnit { /// forms a new major unit from amount - pub fn new(value: f64) -> Self { + fn new(value: f64) -> Self { Self(value) } diff --git a/crates/hyperswitch_connectors/src/connectors/taxjar/transformers.rs b/crates/hyperswitch_connectors/src/connectors/taxjar/transformers.rs index 49caaad61e2f..9098ba38a24e 100644 --- a/crates/hyperswitch_connectors/src/connectors/taxjar/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/taxjar/transformers.rs @@ -54,7 +54,7 @@ pub struct LineItem { id: Option, quantity: Option, product_tax_code: Option, - unit_price: Option, + unit_price: Option, } #[derive(Default, Debug, Serialize, Eq, PartialEq)] @@ -92,10 +92,11 @@ impl TryFrom<&TaxjarRouterData<&types::PaymentsTaxCalculationRouterData>> order_details .iter() .map(|line_item| { - let unit_price = - utils::get_amount_as_f64(currency_unit, line_item.amount, currency) - .map(FloatMajorUnit::new)?; - + let unit_price = utils::get_amount_as_f64( + currency_unit, + line_item.amount, + currency, + )?; Ok(LineItem { id: line_item.product_id.clone(), quantity: Some(line_item.quantity), From 59275e03bbbafcee7bcc16a3514e574a86da3034 Mon Sep 17 00:00:00 2001 From: swangi-kumari Date: Wed, 4 Sep 2024 18:44:56 +0530 Subject: [PATCH 31/39] refactor: resolve comments --- crates/diesel_models/src/payment_intent.rs | 4 +- .../src/connectors/taxjar/transformers.rs | 87 +------------------ .../src/payments/payment_intent.rs | 5 ++ .../src/router_response_types.rs | 1 - .../payments/flows/tax_calculation_flow.rs | 35 ++++---- .../payments/operations/payment_create.rs | 3 +- .../payments/operations/payment_update.rs | 3 +- .../payments/operations/tax_calculation.rs | 21 +++-- 8 files changed, 42 insertions(+), 117 deletions(-) diff --git a/crates/diesel_models/src/payment_intent.rs b/crates/diesel_models/src/payment_intent.rs index 1f1de0f98ce1..ca474c0d2f78 100644 --- a/crates/diesel_models/src/payment_intent.rs +++ b/crates/diesel_models/src/payment_intent.rs @@ -297,6 +297,7 @@ pub enum PaymentIntentUpdate { SessionResponseUpdate { tax_details: TaxDetails, shipping_address_id: Option, + updated_by: String, }, } @@ -1096,6 +1097,7 @@ impl From for PaymentIntentUpdateInternal { PaymentIntentUpdate::SessionResponseUpdate { tax_details, shipping_address_id, + updated_by, } => Self { shipping_address_id, amount: None, @@ -1120,7 +1122,7 @@ impl From for PaymentIntentUpdateInternal { attempt_count: None, merchant_decision: None, payment_confirm_source: None, - updated_by: String::default(), + updated_by, surcharge_applicable: None, incremental_authorization_allowed: None, authorization_count: None, diff --git a/crates/hyperswitch_connectors/src/connectors/taxjar/transformers.rs b/crates/hyperswitch_connectors/src/connectors/taxjar/transformers.rs index 9098ba38a24e..9b5c42c9953b 100644 --- a/crates/hyperswitch_connectors/src/connectors/taxjar/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/taxjar/transformers.rs @@ -152,8 +152,7 @@ pub struct TaxjarPaymentsResponse { #[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)] pub struct Tax { - order_total_amount: FloatMajorUnit, //amount + shipping_cost - amount_to_collect: FloatMajorUnit, //calculated_tax_amount + amount_to_collect: FloatMajorUnit, //calculated_tax_amount } impl @@ -177,105 +176,21 @@ impl ) -> Result { let currency = item.data.request.currency; let amount_to_collect = item.response.tax.amount_to_collect; - let order_total_amount = item.response.tax.order_total_amount; let calculated_tax = utils::convert_back_amount_to_minor_units( &FloatMajorUnitForConnector, amount_to_collect, currency, )?; - let total_amount = utils::convert_back_amount_to_minor_units( - &FloatMajorUnitForConnector, - order_total_amount, - currency, - )?; Ok(Self { response: Ok(TaxCalculationResponseData { order_tax_amount: calculated_tax, - net_amount: (total_amount + calculated_tax), }), ..item.data }) } } -//TODO: Fill the struct with respective fields -// REFUND : -// Type definition for RefundRequest -// #[derive(Default, Debug, Serialize)] -// pub struct TaxjarRefundRequest { -// pub amount: StringMinorUnit, -// } - -// impl TryFrom<&TaxjarRouterData<&RefundsRouterData>> for TaxjarRefundRequest { -// type Error = error_stack::Report; -// fn try_from(item: &TaxjarRouterData<&RefundsRouterData>) -> Result { -// Ok(Self { -// amount: item.amount.to_owned(), -// }) -// } -// } - -// Type definition for Refund Response - -// #[allow(dead_code)] -// #[derive(Debug, Serialize, Default, Deserialize, Clone)] -// pub enum RefundStatus { -// Succeeded, -// Failed, -// #[default] -// Processing, -// } - -// impl From for enums::RefundStatus { -// fn from(item: RefundStatus) -> Self { -// match item { -// RefundStatus::Succeeded => Self::Success, -// RefundStatus::Failed => Self::Failure, -// RefundStatus::Processing => Self::Pending, -// //TODO: Review mapping -// } -// } -// } - -//TODO: Fill the struct with respective fields -// #[derive(Default, Debug, Clone, Serialize, Deserialize)] -// pub struct RefundResponse { -// id: String, -// status: RefundStatus, -// } - -// impl TryFrom> for RefundsRouterData { -// type Error = error_stack::Report; -// fn try_from( -// item: RefundsResponseRouterData, -// ) -> Result { -// Ok(Self { -// response: Ok(RefundsResponseData { -// connector_refund_id: item.response.id.to_string(), -// refund_status: enums::RefundStatus::from(item.response.status), -// }), -// ..item.data -// }) -// } -// } - -// impl TryFrom> for RefundsRouterData { -// type Error = error_stack::Report; -// fn try_from( -// item: RefundsResponseRouterData, -// ) -> Result { -// Ok(Self { -// response: Ok(RefundsResponseData { -// connector_refund_id: item.response.id.to_string(), -// refund_status: enums::RefundStatus::from(item.response.status), -// }), -// ..item.data -// }) -// } -// } - -//TODO: Fill the struct with respective fields #[derive(Default, Debug, Serialize, Deserialize, PartialEq)] pub struct TaxjarErrorResponse { pub status: String, diff --git a/crates/hyperswitch_domain_models/src/payments/payment_intent.rs b/crates/hyperswitch_domain_models/src/payments/payment_intent.rs index 2b371ace6434..b0ca8c025dbe 100644 --- a/crates/hyperswitch_domain_models/src/payments/payment_intent.rs +++ b/crates/hyperswitch_domain_models/src/payments/payment_intent.rs @@ -261,6 +261,7 @@ pub enum PaymentIntentUpdate { SessionResponseUpdate { tax_details: diesel_models::TaxDetails, shipping_address_id: Option, + updated_by: String, }, } @@ -490,9 +491,11 @@ impl From for PaymentIntentUpdateInternal { PaymentIntentUpdate::SessionResponseUpdate { tax_details, shipping_address_id, + updated_by, } => Self { tax_details: Some(tax_details), shipping_address_id, + updated_by, ..Default::default() }, } @@ -662,9 +665,11 @@ impl From for DieselPaymentIntentUpdate { PaymentIntentUpdate::SessionResponseUpdate { tax_details, shipping_address_id, + updated_by, } => Self::SessionResponseUpdate { tax_details, shipping_address_id, + updated_by, }, } } diff --git a/crates/hyperswitch_domain_models/src/router_response_types.rs b/crates/hyperswitch_domain_models/src/router_response_types.rs index 4012224e09c1..cb682514c83b 100644 --- a/crates/hyperswitch_domain_models/src/router_response_types.rs +++ b/crates/hyperswitch_domain_models/src/router_response_types.rs @@ -76,7 +76,6 @@ pub enum PaymentsResponseData { #[derive(Debug, Clone)] pub struct TaxCalculationResponseData { pub order_tax_amount: MinorUnit, - pub net_amount: MinorUnit, } #[derive(serde::Serialize, Debug, Clone)] diff --git a/crates/router/src/core/payments/flows/tax_calculation_flow.rs b/crates/router/src/core/payments/flows/tax_calculation_flow.rs index 90be96bbfafa..38d1b5c6db89 100644 --- a/crates/router/src/core/payments/flows/tax_calculation_flow.rs +++ b/crates/router/src/core/payments/flows/tax_calculation_flow.rs @@ -75,27 +75,22 @@ impl Feature _business_profile: &domain::BusinessProfile, _header_payload: api_models::payments::HeaderPayload, ) -> RouterResult { - if connector.connector_name == types::Connector::Klarna { - let connector_integration: services::BoxedPaymentConnectorIntegrationInterface< - api::SdkSessionUpdate, - types::SdkPaymentsSessionUpdateData, - types::PaymentsResponseData, - > = connector.connector.get_connector_integration(); + let connector_integration: services::BoxedPaymentConnectorIntegrationInterface< + api::SdkSessionUpdate, + types::SdkPaymentsSessionUpdateData, + types::PaymentsResponseData, + > = connector.connector.get_connector_integration(); - let resp = services::execute_connector_processing_step( - state, - connector_integration, - &self, - call_connector_action, - connector_request, - ) - .await - .to_payment_failed_response()?; - - Ok(resp) - } else { - Ok(self) - } + let resp = services::execute_connector_processing_step( + state, + connector_integration, + &self, + call_connector_action, + connector_request, + ) + .await + .to_payment_failed_response()?; + Ok(resp) } async fn add_access_token<'a>( diff --git a/crates/router/src/core/payments/operations/payment_create.rs b/crates/router/src/core/payments/operations/payment_create.rs index c24c5ba0c4ce..0a48d8b9317f 100644 --- a/crates/router/src/core/payments/operations/payment_create.rs +++ b/crates/router/src/core/payments/operations/payment_create.rs @@ -606,8 +606,7 @@ impl Domain for PaymentCreate { let merchant_connector_id = business_profile .tax_connector_id .as_ref() - .ok_or(errors::ApiErrorResponse::InternalServerError) - .attach_printable("missing business_profile.tax_connector_id")?; + .get_required_value("business_profile.tax_connector_id")?; #[cfg(all( any(feature = "v1", feature = "v2"), diff --git a/crates/router/src/core/payments/operations/payment_update.rs b/crates/router/src/core/payments/operations/payment_update.rs index 05f46384156f..2b42254d5e64 100644 --- a/crates/router/src/core/payments/operations/payment_update.rs +++ b/crates/router/src/core/payments/operations/payment_update.rs @@ -535,8 +535,7 @@ impl Domain for PaymentUpdate { let merchant_connector_id = business_profile .tax_connector_id .as_ref() - .ok_or(errors::ApiErrorResponse::InternalServerError) - .attach_printable("missing business_profile.tax_connector_id")?; + .get_required_value("business_profile.tax_connector_id")?; #[cfg(all( any(feature = "v1", feature = "v2"), diff --git a/crates/router/src/core/payments/operations/tax_calculation.rs b/crates/router/src/core/payments/operations/tax_calculation.rs index 2af659b81bd2..4072073a9eb2 100644 --- a/crates/router/src/core/payments/operations/tax_calculation.rs +++ b/crates/router/src/core/payments/operations/tax_calculation.rs @@ -2,7 +2,7 @@ use std::marker::PhantomData; use api_models::enums::FrmSuggestion; use async_trait::async_trait; -use common_utils::types::keymanager::KeyManagerState; +use common_utils::{ext_traits::AsyncExt, types::keymanager::KeyManagerState}; use error_stack::ResultExt; use router_derive::PaymentOperation; use router_env::{instrument, tracing}; @@ -11,6 +11,7 @@ use super::{BoxedOperation, Domain, GetTracker, Operation, UpdateTracker, Valida use crate::{ core::{ errors::{self, RouterResult, StorageErrorExt}, + payment_methods::cards::create_encrypted_data, payments::{self, helpers, operations, PaymentData}, utils as core_utils, }, @@ -55,7 +56,7 @@ impl GetTracker, api::PaymentsDynamicTaxCalcu let merchant_id = merchant_account.get_id(); let storage_scheme = merchant_account.storage_scheme; - let payment_intent = db + let mut payment_intent = db .find_payment_intent_by_payment_id_merchant_id( &state.into(), &payment_id, @@ -91,7 +92,7 @@ impl GetTracker, api::PaymentsDynamicTaxCalcu let amount = payment_attempt.get_total_amount().into(); - payment_attempt.payment_method_type = Some(request.payment_method_type.clone()); + payment_attempt.payment_method_type = Some(request.payment_method_type); let shipping_address = helpers::get_address_by_id( state, @@ -103,6 +104,16 @@ impl GetTracker, api::PaymentsDynamicTaxCalcu ) .await?; + let shipping_details = shipping_address + .clone() + .async_map(|shipping_details| create_encrypted_data(state, key_store, shipping_details)) + .await + .transpose() + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Unable to encrypt shipping details")?; + + payment_intent.shipping_details = shipping_details; + let billing_address = helpers::get_address_by_id( state, payment_intent.billing_address_id.clone(), @@ -229,8 +240,7 @@ impl Domain let merchant_connector_id = business_profile .tax_connector_id .as_ref() - .ok_or(errors::ApiErrorResponse::InternalServerError) - .attach_printable("missing business_profile.tax_connector_id")?; + .get_required_value("business_profile.tax_connector_id")?; #[cfg(all( any(feature = "v1", feature = "v2"), @@ -405,6 +415,7 @@ impl UpdateTracker, api::PaymentsDynamicTaxCalculati let payment_intent_update = hyperswitch_domain_models::payments::payment_intent::PaymentIntentUpdate::SessionResponseUpdate { tax_details: payment_data.payment_intent.tax_details.clone().ok_or(errors::ApiErrorResponse::InternalServerError)?, shipping_address_id: shipping_address.map(|address| address.address_id), + updated_by: payment_data.payment_intent.updated_by.clone(), }; let db = &*state.store; From b645321819503edbc66fbdf67f7eff8165d79c9e Mon Sep 17 00:00:00 2001 From: swangi-kumari Date: Wed, 4 Sep 2024 19:20:33 +0530 Subject: [PATCH 32/39] refactor: add update_by and shipping details --- crates/diesel_models/src/payment_intent.rs | 4 ++- .../src/payments/payment_intent.rs | 5 ++++ .../payments/flows/tax_calculation_flow.rs | 2 +- .../payments/operations/tax_calculation.rs | 25 +++++++++---------- .../router/src/core/payments/transformers.rs | 2 +- 5 files changed, 22 insertions(+), 16 deletions(-) diff --git a/crates/diesel_models/src/payment_intent.rs b/crates/diesel_models/src/payment_intent.rs index ca474c0d2f78..91540b8e7a8b 100644 --- a/crates/diesel_models/src/payment_intent.rs +++ b/crates/diesel_models/src/payment_intent.rs @@ -298,6 +298,7 @@ pub enum PaymentIntentUpdate { tax_details: TaxDetails, shipping_address_id: Option, updated_by: String, + shipping_details: Option, }, } @@ -1098,6 +1099,7 @@ impl From for PaymentIntentUpdateInternal { tax_details, shipping_address_id, updated_by, + shipping_details, } => Self { shipping_address_id, amount: None, @@ -1133,7 +1135,7 @@ impl From for PaymentIntentUpdateInternal { customer_details: None, billing_details: None, merchant_order_reference_id: None, - shipping_details: None, + shipping_details, is_payment_processor_token_flow: None, }, } diff --git a/crates/hyperswitch_domain_models/src/payments/payment_intent.rs b/crates/hyperswitch_domain_models/src/payments/payment_intent.rs index b0ca8c025dbe..64403cf3b9cc 100644 --- a/crates/hyperswitch_domain_models/src/payments/payment_intent.rs +++ b/crates/hyperswitch_domain_models/src/payments/payment_intent.rs @@ -262,6 +262,7 @@ pub enum PaymentIntentUpdate { tax_details: diesel_models::TaxDetails, shipping_address_id: Option, updated_by: String, + shipping_details: Option>>, }, } @@ -492,10 +493,12 @@ impl From for PaymentIntentUpdateInternal { tax_details, shipping_address_id, updated_by, + shipping_details, } => Self { tax_details: Some(tax_details), shipping_address_id, updated_by, + shipping_details, ..Default::default() }, } @@ -666,10 +669,12 @@ impl From for DieselPaymentIntentUpdate { tax_details, shipping_address_id, updated_by, + shipping_details, } => Self::SessionResponseUpdate { tax_details, shipping_address_id, updated_by, + shipping_details: shipping_details.map(Encryption::from), }, } } diff --git a/crates/router/src/core/payments/flows/tax_calculation_flow.rs b/crates/router/src/core/payments/flows/tax_calculation_flow.rs index 38d1b5c6db89..1a8ebbccc71f 100644 --- a/crates/router/src/core/payments/flows/tax_calculation_flow.rs +++ b/crates/router/src/core/payments/flows/tax_calculation_flow.rs @@ -30,7 +30,7 @@ impl _merchant_recipient_data: Option, ) -> RouterResult { Box::pin( - transformers::construct_router_date_to_update_calculated_tax::< + transformers::construct_router_data_to_update_calculated_tax::< api::SdkSessionUpdate, types::SdkPaymentsSessionUpdateData, >( diff --git a/crates/router/src/core/payments/operations/tax_calculation.rs b/crates/router/src/core/payments/operations/tax_calculation.rs index 4072073a9eb2..89a80d264d70 100644 --- a/crates/router/src/core/payments/operations/tax_calculation.rs +++ b/crates/router/src/core/payments/operations/tax_calculation.rs @@ -56,7 +56,7 @@ impl GetTracker, api::PaymentsDynamicTaxCalcu let merchant_id = merchant_account.get_id(); let storage_scheme = merchant_account.storage_scheme; - let mut payment_intent = db + let payment_intent = db .find_payment_intent_by_payment_id_merchant_id( &state.into(), &payment_id, @@ -104,16 +104,6 @@ impl GetTracker, api::PaymentsDynamicTaxCalcu ) .await?; - let shipping_details = shipping_address - .clone() - .async_map(|shipping_details| create_encrypted_data(state, key_store, shipping_details)) - .await - .transpose() - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Unable to encrypt shipping details")?; - - payment_intent.shipping_details = shipping_details; - let billing_address = helpers::get_address_by_id( state, payment_intent.billing_address_id.clone(), @@ -395,14 +385,22 @@ impl UpdateTracker, api::PaymentsDynamicTaxCalculati where F: 'b + Send, { - let shipping_details = payment_data + let shipping_address = payment_data .tax_data .clone() .map(|tax_data| tax_data.shipping_details); + let shipping_details = shipping_address + .clone() + .async_map(|shipping_details| create_encrypted_data(state, key_store, shipping_details)) + .await + .transpose() + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Unable to encrypt shipping details")?; + let shipping_address = helpers::create_or_update_address_for_payment_by_request( state, - shipping_details.as_ref(), + shipping_address.as_ref(), payment_data.payment_intent.shipping_address_id.as_deref(), &payment_data.payment_intent.merchant_id, payment_data.payment_intent.customer_id.as_ref(), @@ -416,6 +414,7 @@ impl UpdateTracker, api::PaymentsDynamicTaxCalculati tax_details: payment_data.payment_intent.tax_details.clone().ok_or(errors::ApiErrorResponse::InternalServerError)?, shipping_address_id: shipping_address.map(|address| address.address_id), updated_by: payment_data.payment_intent.updated_by.clone(), + shipping_details, }; let db = &*state.store; diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs index 07a687af5996..1946756132e8 100644 --- a/crates/router/src/core/payments/transformers.rs +++ b/crates/router/src/core/payments/transformers.rs @@ -36,7 +36,7 @@ use crate::{ utils::{OptionExt, ValueExt}, }; -pub async fn construct_router_date_to_update_calculated_tax<'a, F, T>( +pub async fn construct_router_data_to_update_calculated_tax<'a, F, T>( state: &'a SessionState, payment_data: PaymentData, connector_id: &str, From 5636e60d2174243e42a94a2c5cb2e6afe0ac817e Mon Sep 17 00:00:00 2001 From: swangi-kumari Date: Wed, 4 Sep 2024 19:52:51 +0530 Subject: [PATCH 33/39] refactor: amount --- crates/router/src/core/payments/transformers.rs | 4 ++-- crates/router/src/core/utils.rs | 6 +----- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs index 1946756132e8..045aeb90f8c7 100644 --- a/crates/router/src/core/payments/transformers.rs +++ b/crates/router/src/core/payments/transformers.rs @@ -513,7 +513,7 @@ where _external_latency: Option, _is_latency_header_enabled: Option, ) -> RouterResponse { - let mut amount = MinorUnit::from(payment_data.amount); + let mut amount = payment_data.payment_intent.amount; let shipping_cost = payment_data.payment_intent.shipping_cost; let order_tax_amount = payment_data .payment_intent @@ -1904,7 +1904,7 @@ impl TryFrom> for types::SdkPaymentsSessi .ok_or(errors::ApiErrorResponse::MissingRequiredField { field_name: "order_tax_amount", })?; - let amount = MinorUnit::from(payment_data.amount); + let amount = payment_data.payment_intent.amount; Ok(Self { net_amount: amount + order_tax_amount, //need to change after we move to connector module diff --git a/crates/router/src/core/utils.rs b/crates/router/src/core/utils.rs index d5eb60cf16c6..995e19d98986 100644 --- a/crates/router/src/core/utils.rs +++ b/crates/router/src/core/utils.rs @@ -948,11 +948,7 @@ pub async fn construct_payments_dynamic_tax_calculation_router_data<'a, F: Clone connector_api_version: None, request: types::PaymentsTaxCalculationData { amount: payment_intent.amount, - shipping_cost: payment_intent.shipping_cost.ok_or( - errors::ApiErrorResponse::MissingRequiredField { - field_name: "shipping_cost", - }, - )?, + shipping_cost: payment_intent.shipping_cost.unwrap_or(MinorUnit::new(0)), order_details, currency: payment_data.currency, shipping_address, From b1e6041924b59b81339a9d439714bbf286209791 Mon Sep 17 00:00:00 2001 From: swangi-kumari Date: Wed, 4 Sep 2024 20:57:45 +0530 Subject: [PATCH 34/39] refactor: remove --- .../src/connectors/taxjar.rs | 4 +-- .../src/router_request_types.rs | 2 +- .../router/src/core/payments/transformers.rs | 25 ++++++++----------- crates/router/src/core/utils.rs | 14 +++++------ 4 files changed, 19 insertions(+), 26 deletions(-) diff --git a/crates/hyperswitch_connectors/src/connectors/taxjar.rs b/crates/hyperswitch_connectors/src/connectors/taxjar.rs index 8e464051ebee..ef8631004a69 100644 --- a/crates/hyperswitch_connectors/src/connectors/taxjar.rs +++ b/crates/hyperswitch_connectors/src/connectors/taxjar.rs @@ -4,7 +4,7 @@ use common_utils::{ errors::CustomResult, ext_traits::BytesExt, request::{Method, Request, RequestBuilder, RequestContent}, - types::{AmountConvertor, FloatMajorUnit, FloatMajorUnitForConnector}, + types::{AmountConvertor, FloatMajorUnit, FloatMajorUnitForConnector, MinorUnit}, }; use error_stack::{report, ResultExt}; use hyperswitch_domain_models::{ @@ -190,7 +190,7 @@ impl ConnectorIntegration, pub order_details: Option>, pub shipping_address: Address, } diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs index 045aeb90f8c7..a9a746f0a227 100644 --- a/crates/router/src/core/payments/transformers.rs +++ b/crates/router/src/core/payments/transformers.rs @@ -132,37 +132,32 @@ where status: payment_data.payment_attempt.status, payment_method: diesel_models::enums::PaymentMethod::default(), connector_auth_type: auth_type, - description: payment_data.payment_intent.description.clone(), - return_url: payment_data.payment_intent.return_url.clone(), + description: None, + return_url: None, address: unified_address, auth_type: payment_data .payment_attempt .authentication_type .unwrap_or_default(), connector_meta_data: None, - connector_wallets_details: merchant_connector_account.get_connector_wallets_details(), + connector_wallets_details: None, request: T::try_from(additional_data)?, response, - amount_captured: payment_data - .payment_intent - .amount_captured - .map(|amt| amt.get_amount_as_i64()), - minor_amount_captured: payment_data.payment_intent.amount_captured, + amount_captured: None, + minor_amount_captured: None, access_token: None, session_token: None, reference_id: None, - payment_method_status: payment_data.payment_method_info.map(|info| info.status), - payment_method_token: payment_data - .pm_token - .map(|token| types::PaymentMethodToken::Token(Secret::new(token))), - connector_customer: payment_data.connector_customer_id, - recurring_mandate_payment_data: payment_data.recurring_mandate_payment_data, + payment_method_status: None, + payment_method_token: None, + connector_customer: None, + recurring_mandate_payment_data: None, connector_request_reference_id: core_utils::get_connector_request_reference_id( &state.conf, merchant_account.get_id(), &payment_data.payment_attempt, ), - preprocessing_id: payment_data.payment_attempt.preprocessing_step_id, + preprocessing_id: None, #[cfg(feature = "payouts")] payout_method_data: None, #[cfg(feature = "payouts")] diff --git a/crates/router/src/core/utils.rs b/crates/router/src/core/utils.rs index 995e19d98986..b054b28df192 100644 --- a/crates/router/src/core/utils.rs +++ b/crates/router/src/core/utils.rs @@ -921,7 +921,7 @@ pub async fn construct_payments_dynamic_tax_calculation_router_data<'a, F: Clone let router_data = types::RouterData { flow: PhantomData, merchant_id: merchant_account.get_id().to_owned(), - customer_id: payment_intent.customer_id.to_owned(), + customer_id: None, connector_customer: None, connector: merchant_connector_account.connector_name.clone(), payment_id: payment_attempt.payment_id.get_string_repr().to_owned(), @@ -929,15 +929,13 @@ pub async fn construct_payments_dynamic_tax_calculation_router_data<'a, F: Clone status: payment_attempt.status, payment_method: diesel_models::enums::PaymentMethod::default(), connector_auth_type, - description: payment_intent.description.clone(), - return_url: payment_intent.return_url.clone(), + description: None, + return_url: None, address: add, auth_type: payment_attempt.authentication_type.unwrap_or_default(), connector_meta_data: None, connector_wallets_details: None, - amount_captured: payment_intent - .amount_captured - .map(|amt| amt.get_amount_as_i64()), + amount_captured: None, access_token: None, session_token: None, reference_id: None, @@ -948,7 +946,7 @@ pub async fn construct_payments_dynamic_tax_calculation_router_data<'a, F: Clone connector_api_version: None, request: types::PaymentsTaxCalculationData { amount: payment_intent.amount, - shipping_cost: payment_intent.shipping_cost.unwrap_or(MinorUnit::new(0)), + shipping_cost: payment_intent.shipping_cost, order_details, currency: payment_data.currency, shipping_address, @@ -972,7 +970,7 @@ pub async fn construct_payments_dynamic_tax_calculation_router_data<'a, F: Clone dispute_id: None, connector_response: None, payment_method_status: None, - minor_amount_captured: payment_intent.amount_captured, + minor_amount_captured: None, integrity_check: Ok(()), }; Ok(router_data) From 4b0d9aa7a6b2d585af5f1f06a4a4dd029ea51573 Mon Sep 17 00:00:00 2001 From: swangi-kumari Date: Thu, 5 Sep 2024 00:40:06 +0530 Subject: [PATCH 35/39] refactor: solve clippy --- .../src/default_implementations.rs | 6 ++-- .../payments/operations/payment_create.rs | 13 ++----- .../payments/operations/payment_update.rs | 7 ++-- .../payments/operations/tax_calculation.rs | 7 ++-- .../router/src/core/payments/transformers.rs | 35 ++++++++++--------- crates/router/src/core/utils.rs | 2 +- 6 files changed, 30 insertions(+), 40 deletions(-) diff --git a/crates/hyperswitch_connectors/src/default_implementations.rs b/crates/hyperswitch_connectors/src/default_implementations.rs index 3ac4fbc057c0..0210bfa551ac 100644 --- a/crates/hyperswitch_connectors/src/default_implementations.rs +++ b/crates/hyperswitch_connectors/src/default_implementations.rs @@ -133,7 +133,8 @@ default_imp_for_calculate_tax!( connectors::Globepay, connectors::Worldline, connectors::Powertranz, - connectors::Tsys + connectors::Tsys, + connectors::Deutschebank ); macro_rules! default_imp_for_session_update { @@ -164,7 +165,8 @@ default_imp_for_session_update!( connectors::Globepay, connectors::Worldline, connectors::Powertranz, - connectors::Tsys + connectors::Tsys, + connectors::Deutschebank ); use crate::connectors; diff --git a/crates/router/src/core/payments/operations/payment_create.rs b/crates/router/src/core/payments/operations/payment_create.rs index 23c0c0eac340..f3a75b3038a5 100644 --- a/crates/router/src/core/payments/operations/payment_create.rs +++ b/crates/router/src/core/payments/operations/payment_create.rs @@ -7,11 +7,7 @@ use api_models::{ use async_trait::async_trait; use common_utils::{ ext_traits::{AsyncExt, Encode, ValueExt}, - type_name, - types::{ - keymanager::{Identifier, KeyManagerState}, - MinorUnit, - }, + types::{keymanager::KeyManagerState, MinorUnit}, }; use diesel_models::ephemeral_key; use error_stack::{self, ResultExt}; @@ -601,10 +597,7 @@ impl Domain for PaymentCreate { .as_ref() .get_required_value("business_profile.tax_connector_id")?; - #[cfg(all( - any(feature = "v1", feature = "v2"), - not(feature = "merchant_connector_account_v2") - ))] + #[cfg(feature = "v1")] let mca = db .find_by_merchant_connector_account_merchant_id_merchant_connector_id( key_manager_state, @@ -619,7 +612,7 @@ impl Domain for PaymentCreate { }, )?; - #[cfg(all(feature = "v2", feature = "merchant_connector_account_v2"))] + #[cfg(feature = "v2")] let mca = db .find_merchant_connector_account_by_id( key_manager_state, diff --git a/crates/router/src/core/payments/operations/payment_update.rs b/crates/router/src/core/payments/operations/payment_update.rs index 2b42254d5e64..51356ce1ea75 100644 --- a/crates/router/src/core/payments/operations/payment_update.rs +++ b/crates/router/src/core/payments/operations/payment_update.rs @@ -537,10 +537,7 @@ impl Domain for PaymentUpdate { .as_ref() .get_required_value("business_profile.tax_connector_id")?; - #[cfg(all( - any(feature = "v1", feature = "v2"), - not(feature = "merchant_connector_account_v2") - ))] + #[cfg(feature = "v1")] let mca = db .find_by_merchant_connector_account_merchant_id_merchant_connector_id( key_manager_state, @@ -555,7 +552,7 @@ impl Domain for PaymentUpdate { }, )?; - #[cfg(all(feature = "v2", feature = "merchant_connector_account_v2"))] + #[cfg(feature = "v2")] let mca = db .find_merchant_connector_account_by_id( key_manager_state, diff --git a/crates/router/src/core/payments/operations/tax_calculation.rs b/crates/router/src/core/payments/operations/tax_calculation.rs index 89a80d264d70..21678f12c481 100644 --- a/crates/router/src/core/payments/operations/tax_calculation.rs +++ b/crates/router/src/core/payments/operations/tax_calculation.rs @@ -232,10 +232,7 @@ impl Domain .as_ref() .get_required_value("business_profile.tax_connector_id")?; - #[cfg(all( - any(feature = "v1", feature = "v2"), - not(feature = "merchant_connector_account_v2") - ))] + #[cfg(feature = "v1")] let mca = db .find_by_merchant_connector_account_merchant_id_merchant_connector_id( key_manager_state, @@ -250,7 +247,7 @@ impl Domain }, )?; - #[cfg(all(feature = "v2", feature = "merchant_connector_account_v2"))] + #[cfg(feature = "v2")] let mca = db .find_merchant_connector_account_by_id( key_manager_state, diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs index b4d7813502dd..4ee11c6afcd1 100644 --- a/crates/router/src/core/payments/transformers.rs +++ b/crates/router/src/core/payments/transformers.rs @@ -40,7 +40,7 @@ pub async fn construct_router_data_to_update_calculated_tax<'a, F, T>( payment_data: PaymentData, connector_id: &str, merchant_account: &domain::MerchantAccount, - key_store: &domain::MerchantKeyStore, + _key_store: &domain::MerchantKeyStore, customer: &'a Option, merchant_connector_account: &helpers::MerchantConnectorAccountType, ) -> RouterResult> @@ -100,22 +100,23 @@ where .map(|customer| customer.merchant_reference_id) .ok_or_else(|| errors::ApiErrorResponse::InternalServerError)?; - let unified_address = - if let Some(payment_method_info) = payment_data.payment_method_info.clone() { - let payment_method_billing = decrypt_generic_data::
( - state, - payment_method_info.payment_method_billing_address, - key_store, - ) - .await - .attach_printable("unable to decrypt payment method billing address details")?; - payment_data - .address - .clone() - .unify_with_payment_data_billing(payment_method_billing) - } else { - payment_data.address - }; + let unified_address = if let Some(payment_method_info) = + payment_data.payment_method_info.clone() + { + let payment_method_billing = payment_method_info + .payment_method_billing_address + .map(|decrypted_data| decrypted_data.into_inner().expose()) + .map(|decrypted_value| decrypted_value.parse_value("payment_method_billing_address")) + .transpose() + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("unable to parse payment_method_billing_address")?; + payment_data + .address + .clone() + .unify_with_payment_data_billing(payment_method_billing) + } else { + payment_data.address + }; let router_data = types::RouterData { flow: PhantomData, diff --git a/crates/router/src/core/utils.rs b/crates/router/src/core/utils.rs index 0165a0677380..43f5ab480648 100644 --- a/crates/router/src/core/utils.rs +++ b/crates/router/src/core/utils.rs @@ -881,7 +881,7 @@ pub async fn construct_payments_dynamic_tax_calculation_router_data<'a, F: Clone let payment_intent = &payment_data.payment_intent.clone(); let payment_attempt = &payment_data.payment_attempt.clone(); - let test_mode = merchant_connector_account.test_mode; + let test_mode: Option = merchant_connector_account.test_mode; let connector_auth_type: types::ConnectorAuthType = merchant_connector_account .connector_account_details From 0b69be0a4f982e4d5dd5abe8b9f60dc4628e00bb Mon Sep 17 00:00:00 2001 From: "hyperswitch-bot[bot]" <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Date: Wed, 4 Sep 2024 19:13:53 +0000 Subject: [PATCH 36/39] docs(openapi): re-generate OpenAPI specification --- api-reference-v2/openapi_spec.json | 4 ++++ api-reference/openapi_spec.json | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/api-reference-v2/openapi_spec.json b/api-reference-v2/openapi_spec.json index 21e2bc07a651..923950a08900 100644 --- a/api-reference-v2/openapi_spec.json +++ b/api-reference-v2/openapi_spec.json @@ -11595,6 +11595,7 @@ "shipping_cost": { "type": "integer", "format": "int64", + "description": "The shipping cost for the payment. This is required for tax calculation in some regions.", "example": 6540, "nullable": true }, @@ -11946,6 +11947,7 @@ "shipping_cost": { "type": "integer", "format": "int64", + "description": "The shipping cost for the payment. This is required for tax calculation in some regions.", "example": 6540, "nullable": true }, @@ -12925,6 +12927,7 @@ "shipping_cost": { "type": "integer", "format": "int64", + "description": "The shipping cost for the payment. This is required for tax calculation in some regions.", "example": 6540, "nullable": true }, @@ -14029,6 +14032,7 @@ "shipping_cost": { "type": "integer", "format": "int64", + "description": "The shipping cost for the payment. This is required for tax calculation in some regions.", "example": 6540, "nullable": true }, diff --git a/api-reference/openapi_spec.json b/api-reference/openapi_spec.json index 7d27b7a07c0f..2a758cc06d21 100644 --- a/api-reference/openapi_spec.json +++ b/api-reference/openapi_spec.json @@ -15598,6 +15598,7 @@ "shipping_cost": { "type": "integer", "format": "int64", + "description": "The shipping cost for the payment. This is required for tax calculation in some regions.", "example": 6540, "nullable": true }, @@ -15949,6 +15950,7 @@ "shipping_cost": { "type": "integer", "format": "int64", + "description": "The shipping cost for the payment. This is required for tax calculation in some regions.", "example": 6540, "nullable": true }, @@ -16948,6 +16950,7 @@ "shipping_cost": { "type": "integer", "format": "int64", + "description": "The shipping cost for the payment. This is required for tax calculation in some regions.", "example": 6540, "nullable": true }, @@ -18052,6 +18055,7 @@ "shipping_cost": { "type": "integer", "format": "int64", + "description": "The shipping cost for the payment. This is required for tax calculation in some regions.", "example": 6540, "nullable": true }, From 09d889080483f82fcb441d3ef07d95eac059609d Mon Sep 17 00:00:00 2001 From: swangi-kumari Date: Thu, 5 Sep 2024 11:51:14 +0530 Subject: [PATCH 37/39] refactor: resolve clippy_v2 --- crates/router/src/core/utils.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crates/router/src/core/utils.rs b/crates/router/src/core/utils.rs index 43f5ab480648..85cee465a735 100644 --- a/crates/router/src/core/utils.rs +++ b/crates/router/src/core/utils.rs @@ -881,8 +881,12 @@ pub async fn construct_payments_dynamic_tax_calculation_router_data<'a, F: Clone let payment_intent = &payment_data.payment_intent.clone(); let payment_attempt = &payment_data.payment_attempt.clone(); + #[cfg(feature = "v1")] let test_mode: Option = merchant_connector_account.test_mode; + #[cfg(feature = "v2")] + let test_mode = None; + let connector_auth_type: types::ConnectorAuthType = merchant_connector_account .connector_account_details .clone() From ee4782dd10436277921b0d965b046e80b9d6bf04 Mon Sep 17 00:00:00 2001 From: swangi-kumari Date: Thu, 5 Sep 2024 16:10:49 +0530 Subject: [PATCH 38/39] refactor: fix --- .../src/connectors/taxjar/transformers.rs | 12 +-------- .../src/api/payments.rs | 1 - .../payments/operations/payment_response.rs | 27 +------------------ .../payments/operations/tax_calculation.rs | 14 ++-------- .../router/src/core/payments/transformers.rs | 20 +------------- crates/router/src/core/utils.rs | 4 +-- crates/router/src/types/api.rs | 3 ++- crates/router_derive/src/macros/operation.rs | 9 ------- 8 files changed, 8 insertions(+), 82 deletions(-) diff --git a/crates/hyperswitch_connectors/src/connectors/taxjar/transformers.rs b/crates/hyperswitch_connectors/src/connectors/taxjar/transformers.rs index 9b5c42c9953b..53c120a2788b 100644 --- a/crates/hyperswitch_connectors/src/connectors/taxjar/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/taxjar/transformers.rs @@ -13,7 +13,7 @@ use serde::{Deserialize, Serialize}; use crate::{ types::ResponseRouterData, - utils::{self, AddressDetailsData, RouterData as _}, + utils::{self, AddressDetailsData}, }; pub struct TaxjarRouterData { @@ -34,11 +34,6 @@ impl From<(FloatMajorUnit, FloatMajorUnit, T)> for TaxjarRouterData { #[derive(Default, Debug, Serialize, PartialEq)] pub struct TaxjarPaymentsRequest { - from_country: enums::CountryAlpha2, - from_zip: Secret, - from_state: Secret, - from_city: Option, - from_street: Option>, to_country: enums::CountryAlpha2, to_zip: Secret, to_state: Secret, @@ -107,11 +102,6 @@ impl TryFrom<&TaxjarRouterData<&types::PaymentsTaxCalculationRouterData>> .collect(); Ok(Self { - from_country: item.router_data.get_billing_country()?, - from_zip: item.router_data.get_billing_zip()?, - from_state: item.router_data.get_billing_state_code()?, - from_city: item.router_data.get_optional_billing_city(), - from_street: item.router_data.get_optional_billing_line1(), to_country: shipping.get_country()?.to_owned(), to_zip: shipping.get_zip()?.to_owned(), to_state: shipping.to_state_code()?.to_owned(), diff --git a/crates/hyperswitch_interfaces/src/api/payments.rs b/crates/hyperswitch_interfaces/src/api/payments.rs index 695a2bbd1d3f..530dd5164543 100644 --- a/crates/hyperswitch_interfaces/src/api/payments.rs +++ b/crates/hyperswitch_interfaces/src/api/payments.rs @@ -38,7 +38,6 @@ pub trait Payment: + PaymentsPostProcessing + ConnectorCustomer + PaymentIncrementalAuthorization - + PaymentTaxCalculation + PaymentSessionUpdate { } diff --git a/crates/router/src/core/payments/operations/payment_response.rs b/crates/router/src/core/payments/operations/payment_response.rs index b7af0bcad3ed..548e9b1be88c 100644 --- a/crates/router/src/core/payments/operations/payment_response.rs +++ b/crates/router/src/core/payments/operations/payment_response.rs @@ -45,7 +45,7 @@ use crate::{ #[derive(Debug, Clone, Copy, router_derive::PaymentOperation)] #[operation( operations = "post_update_tracker", - flow = "sync_data, cancel_data, authorize_data, capture_data, complete_authorize_data, approve_data, reject_data, setup_mandate_data, session_data,incremental_authorization_data, tax_calculation_data, sdk_session_update_data" + flow = "sync_data, cancel_data, authorize_data, capture_data, complete_authorize_data, approve_data, reject_data, setup_mandate_data, session_data,incremental_authorization_data, sdk_session_update_data" )] pub struct PaymentResponse; @@ -489,31 +489,6 @@ impl PostUpdateTracker, types::PaymentsSessionData> } } -#[async_trait] -impl PostUpdateTracker, types::PaymentsTaxCalculationData> - for PaymentResponse -{ - async fn update_tracker<'b>( - &'b self, - _db: &'b SessionState, - _payment_id: &api::PaymentIdType, - payment_data: PaymentData, - _router_data: types::RouterData< - F, - types::PaymentsTaxCalculationData, - types::PaymentsResponseData, - >, - _key_store: &domain::MerchantKeyStore, - _storage_scheme: enums::MerchantStorageScheme, - _locale: &Option, - ) -> RouterResult> - where - F: 'b + Send, - { - Ok(payment_data) - } -} - #[async_trait] impl PostUpdateTracker, types::SdkPaymentsSessionUpdateData> for PaymentResponse diff --git a/crates/router/src/core/payments/operations/tax_calculation.rs b/crates/router/src/core/payments/operations/tax_calculation.rs index 21678f12c481..2b4389c9fed3 100644 --- a/crates/router/src/core/payments/operations/tax_calculation.rs +++ b/crates/router/src/core/payments/operations/tax_calculation.rs @@ -27,7 +27,7 @@ use crate::{ }; #[derive(Debug, Clone, Copy, PaymentOperation)] -#[operation(operations = "all", flow = "tax_calculation")] +#[operation(operations = "all", flow = "sdk_session_update")] pub struct PaymentSessionUpdate; #[async_trait] @@ -104,16 +104,6 @@ impl GetTracker, api::PaymentsDynamicTaxCalcu ) .await?; - let billing_address = helpers::get_address_by_id( - state, - payment_intent.billing_address_id.clone(), - key_store, - &payment_intent.payment_id, - merchant_id, - merchant_account.storage_scheme, - ) - .await?; - let profile_id = payment_intent .profile_id .as_ref() @@ -148,7 +138,7 @@ impl GetTracker, api::PaymentsDynamicTaxCalcu setup_mandate: None, address: payments::PaymentAddress::new( shipping_address.as_ref().map(From::from), - billing_address.as_ref().map(From::from), + None, None, business_profile.use_billing_as_payment_method_billing, ), diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs index 4ee11c6afcd1..559e7ebbe29d 100644 --- a/crates/router/src/core/payments/transformers.rs +++ b/crates/router/src/core/payments/transformers.rs @@ -100,24 +100,6 @@ where .map(|customer| customer.merchant_reference_id) .ok_or_else(|| errors::ApiErrorResponse::InternalServerError)?; - let unified_address = if let Some(payment_method_info) = - payment_data.payment_method_info.clone() - { - let payment_method_billing = payment_method_info - .payment_method_billing_address - .map(|decrypted_data| decrypted_data.into_inner().expose()) - .map(|decrypted_value| decrypted_value.parse_value("payment_method_billing_address")) - .transpose() - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("unable to parse payment_method_billing_address")?; - payment_data - .address - .clone() - .unify_with_payment_data_billing(payment_method_billing) - } else { - payment_data.address - }; - let router_data = types::RouterData { flow: PhantomData, merchant_id: merchant_account.get_id().clone(), @@ -134,7 +116,7 @@ where connector_auth_type: auth_type, description: None, return_url: None, - address: unified_address, + address: payment_data.address.clone(), auth_type: payment_data .payment_attempt .authentication_type diff --git a/crates/router/src/core/utils.rs b/crates/router/src/core/utils.rs index 85cee465a735..2faa69978cbf 100644 --- a/crates/router/src/core/utils.rs +++ b/crates/router/src/core/utils.rs @@ -894,8 +894,6 @@ pub async fn construct_payments_dynamic_tax_calculation_router_data<'a, F: Clone .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Failed while parsing value for ConnectorAuthType")?; - let add = payment_data.address.clone(); - let shipping_address = payment_data .tax_data .clone() @@ -935,7 +933,7 @@ pub async fn construct_payments_dynamic_tax_calculation_router_data<'a, F: Clone connector_auth_type, description: None, return_url: None, - address: add, + address: payment_data.address.clone(), auth_type: payment_attempt.authentication_type.unwrap_or_default(), connector_meta_data: None, connector_wallets_details: None, diff --git a/crates/router/src/types/api.rs b/crates/router/src/types/api.rs index f546196377e0..1c5e6eb5e951 100644 --- a/crates/router/src/types/api.rs +++ b/crates/router/src/types/api.rs @@ -140,7 +140,8 @@ impl< + ConnectorMandateRevoke + ConnectorMandateRevokeV2 + ExternalAuthentication - + ExternalAuthenticationV2, + + ExternalAuthenticationV2 + + PaymentTaxCalculation, > Connector for T { } diff --git a/crates/router_derive/src/macros/operation.rs b/crates/router_derive/src/macros/operation.rs index e00efdb425fc..e73fefb4b53d 100644 --- a/crates/router_derive/src/macros/operation.rs +++ b/crates/router_derive/src/macros/operation.rs @@ -29,8 +29,6 @@ pub enum Derives { SessionData, IncrementalAuthorization, IncrementalAuthorizationData, - TaxCalculation, - TaxCalculationData, SdkSessionUpdate, SdkSessionUpdateData, } @@ -107,12 +105,6 @@ impl Conversion { Derives::IncrementalAuthorizationData => { syn::Ident::new("PaymentsIncrementalAuthorizationData", Span::call_site()) } - Derives::TaxCalculation => { - syn::Ident::new("PaymentsDynamicTaxCalculationRequest", Span::call_site()) - } - Derives::TaxCalculationData => { - syn::Ident::new("PaymentsTaxCalculationData", Span::call_site()) - } Derives::SdkSessionUpdate => { syn::Ident::new("PaymentsDynamicTaxCalculationRequest", Span::call_site()) } @@ -439,7 +431,6 @@ pub fn operation_derive_inner(input: DeriveInput) -> syn::Result Date: Thu, 5 Sep 2024 19:23:53 +0530 Subject: [PATCH 39/39] refactor: resolve comments --- crates/api_models/src/payments.rs | 2 +- crates/diesel_models/src/payment_intent.rs | 4 ++-- .../core/payments/operations/payment_create.rs | 2 +- .../core/payments/operations/payment_update.rs | 2 +- .../core/payments/operations/tax_calculation.rs | 7 ++++--- crates/router/src/core/payments/transformers.rs | 15 +++------------ crates/router/src/routes/app.rs | 2 +- crates/router/src/services/api.rs | 2 +- 8 files changed, 14 insertions(+), 22 deletions(-) diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs index 8466d081724b..d512d487e5b6 100644 --- a/crates/api_models/src/payments.rs +++ b/crates/api_models/src/payments.rs @@ -4470,7 +4470,7 @@ pub struct PaymentsDynamicTaxCalculationRequest { pub shipping: Address, /// Client Secret #[schema(value_type = String)] - pub client_secret: String, + pub client_secret: Secret, /// Payment method type #[schema(value_type = PaymentMethodType)] pub payment_method_type: api_enums::PaymentMethodType, diff --git a/crates/diesel_models/src/payment_intent.rs b/crates/diesel_models/src/payment_intent.rs index 91540b8e7a8b..c80e9e5f4da4 100644 --- a/crates/diesel_models/src/payment_intent.rs +++ b/crates/diesel_models/src/payment_intent.rs @@ -142,13 +142,13 @@ pub struct PaymentIntent { #[diesel(sql_type = diesel::sql_types::Jsonb)] pub struct TaxDetails { pub default: Option, - pub pmt: Option, + pub payment_method_type: Option, } common_utils::impl_to_sql_from_sql_json!(TaxDetails); #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -pub struct PmtTax { +pub struct PaymentMethodTypeTax { pub order_tax_amount: MinorUnit, pub pmt: PaymentMethodType, } diff --git a/crates/router/src/core/payments/operations/payment_create.rs b/crates/router/src/core/payments/operations/payment_create.rs index f3a75b3038a5..257a3156bbce 100644 --- a/crates/router/src/core/payments/operations/payment_create.rs +++ b/crates/router/src/core/payments/operations/payment_create.rs @@ -668,7 +668,7 @@ impl Domain for PaymentCreate { default: Some(diesel_models::DefaultTax { order_tax_amount: tax_response.order_tax_amount, }), - pmt: None, + payment_method_type: None, }); Ok(()) diff --git a/crates/router/src/core/payments/operations/payment_update.rs b/crates/router/src/core/payments/operations/payment_update.rs index 51356ce1ea75..3a21475c64a9 100644 --- a/crates/router/src/core/payments/operations/payment_update.rs +++ b/crates/router/src/core/payments/operations/payment_update.rs @@ -608,7 +608,7 @@ impl Domain for PaymentUpdate { default: Some(diesel_models::DefaultTax { order_tax_amount: tax_response.order_tax_amount, }), - pmt: None, + payment_method_type: None, }); Ok(()) diff --git a/crates/router/src/core/payments/operations/tax_calculation.rs b/crates/router/src/core/payments/operations/tax_calculation.rs index 2b4389c9fed3..eec35f79b9d1 100644 --- a/crates/router/src/core/payments/operations/tax_calculation.rs +++ b/crates/router/src/core/payments/operations/tax_calculation.rs @@ -4,6 +4,7 @@ use api_models::enums::FrmSuggestion; use async_trait::async_trait; use common_utils::{ext_traits::AsyncExt, types::keymanager::KeyManagerState}; use error_stack::ResultExt; +use masking::PeekInterface; use router_derive::PaymentOperation; use router_env::{instrument, tracing}; @@ -76,7 +77,7 @@ impl GetTracker, api::PaymentsDynamicTaxCalcu "create a session update for", )?; - helpers::authenticate_client_secret(Some(&request.client_secret), &payment_intent)?; + helpers::authenticate_client_secret(Some(request.client_secret.peek()), &payment_intent)?; let mut payment_attempt = db .find_payment_attempt_by_payment_id_merchant_id_attempt_id( @@ -297,7 +298,7 @@ impl Domain .attach_printable("missing tax_data.payment_method_type")?; payment_data.payment_intent.tax_details = Some(diesel_models::TaxDetails { - pmt: Some(diesel_models::PmtTax { + payment_method_type: Some(diesel_models::PaymentMethodTypeTax { order_tax_amount: tax_response.order_tax_amount, pmt: payment_method_type, }), @@ -398,7 +399,7 @@ impl UpdateTracker, api::PaymentsDynamicTaxCalculati .await?; let payment_intent_update = hyperswitch_domain_models::payments::payment_intent::PaymentIntentUpdate::SessionResponseUpdate { - tax_details: payment_data.payment_intent.tax_details.clone().ok_or(errors::ApiErrorResponse::InternalServerError)?, + tax_details: payment_data.payment_intent.tax_details.clone().ok_or(errors::ApiErrorResponse::InternalServerError).attach_printable("payment_intent.tax_details not found")?, shipping_address_id: shipping_address.map(|address| address.address_id), updated_by: payment_data.payment_intent.updated_by.clone(), shipping_details, diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs index 559e7ebbe29d..2bcc80f2e8c5 100644 --- a/crates/router/src/core/payments/transformers.rs +++ b/crates/router/src/core/payments/transformers.rs @@ -91,19 +91,10 @@ where customer_data: customer, }; - #[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "customer_v2")))] - let customer_id = customer.to_owned().map(|customer| customer.customer_id); - - #[cfg(all(feature = "v2", feature = "customer_v2"))] - let customer_id = customer - .to_owned() - .map(|customer| customer.merchant_reference_id) - .ok_or_else(|| errors::ApiErrorResponse::InternalServerError)?; - let router_data = types::RouterData { flow: PhantomData, merchant_id: merchant_account.get_id().clone(), - customer_id, + customer_id: None, connector: connector_id.to_owned(), payment_id: payment_data .payment_attempt @@ -497,7 +488,7 @@ where .payment_intent .tax_details .clone() - .and_then(|tax| tax.pmt.map(|a| a.order_tax_amount)); + .and_then(|tax| tax.payment_method_type.map(|a| a.order_tax_amount)); if let Some(shipping_cost) = shipping_cost { amount = amount + shipping_cost; } @@ -1892,7 +1883,7 @@ impl TryFrom> for types::SdkPaymentsSessi .payment_intent .tax_details .clone() - .and_then(|tax| tax.pmt.map(|pmt| pmt.order_tax_amount)) + .and_then(|tax| tax.payment_method_type.map(|pmt| pmt.order_tax_amount)) .ok_or(errors::ApiErrorResponse::MissingRequiredField { field_name: "order_tax_amount", })?; diff --git a/crates/router/src/routes/app.rs b/crates/router/src/routes/app.rs index 80b9d91da5ac..f35783f1a0be 100644 --- a/crates/router/src/routes/app.rs +++ b/crates/router/src/routes/app.rs @@ -629,7 +629,7 @@ impl Payments { .service( web::resource("{payment_id}/calculate_tax") .route(web::post().to(payments_dynamic_tax_calculation)), - ); + ); } route } diff --git a/crates/router/src/services/api.rs b/crates/router/src/services/api.rs index 1cccb36983fb..8c74629d9abf 100644 --- a/crates/router/src/services/api.rs +++ b/crates/router/src/services/api.rs @@ -1244,7 +1244,7 @@ impl Authenticate for api_models::payments::PaymentsSessionRequest { } impl Authenticate for api_models::payments::PaymentsDynamicTaxCalculationRequest { fn get_client_secret(&self) -> Option<&String> { - Some(&self.client_secret) + Some(self.client_secret.peek()) } }