From e56ad0d6884c6505d73df048e73d6210db3aae46 Mon Sep 17 00:00:00 2001 From: Sanchith Hegde <22217505+SanchithHegde@users.noreply.github.com> Date: Thu, 8 Aug 2024 15:39:02 +0530 Subject: [PATCH] refactor: use business profile domain models instead of diesel models (#5566) --- crates/api_models/src/admin.rs | 2 +- crates/common_utils/src/types/keymanager.rs | 2 +- crates/diesel_models/src/business_profile.rs | 469 +----------------- .../src/query/business_profile.rs | 8 +- .../hyperswitch_domain_models/src/customer.rs | 2 +- .../src/merchant_account.rs | 9 +- crates/router/Cargo.toml | 2 +- .../src/connector/braintree/transformers.rs | 6 - crates/router/src/core/admin.rs | 182 ++++--- crates/router/src/core/authentication.rs | 4 +- .../src/core/authentication/transformers.rs | 4 +- .../router/src/core/authentication/utils.rs | 2 +- crates/router/src/core/payment_link.rs | 10 +- crates/router/src/core/payment_methods.rs | 2 +- .../router/src/core/payment_methods/cards.rs | 52 +- crates/router/src/core/payments.rs | 50 +- crates/router/src/core/payments/flows.rs | 4 +- .../src/core/payments/flows/approve_flow.rs | 4 +- .../src/core/payments/flows/authorize_flow.rs | 4 +- .../src/core/payments/flows/cancel_flow.rs | 4 +- .../src/core/payments/flows/capture_flow.rs | 4 +- .../payments/flows/complete_authorize_flow.rs | 4 +- .../flows/incremental_authorization_flow.rs | 4 +- .../src/core/payments/flows/psync_flow.rs | 4 +- .../src/core/payments/flows/reject_flow.rs | 4 +- .../src/core/payments/flows/session_flow.rs | 14 +- .../core/payments/flows/setup_mandate_flow.rs | 4 +- crates/router/src/core/payments/helpers.rs | 14 +- crates/router/src/core/payments/operations.rs | 18 +- .../payments/operations/payment_approve.rs | 5 +- .../payments/operations/payment_cancel.rs | 6 +- .../payments/operations/payment_capture.rs | 6 +- .../operations/payment_complete_authorize.rs | 8 +- .../payments/operations/payment_confirm.rs | 18 +- .../payments/operations/payment_create.rs | 29 +- .../payments/operations/payment_reject.rs | 6 +- .../payments/operations/payment_response.rs | 8 +- .../payments/operations/payment_session.rs | 5 +- .../core/payments/operations/payment_start.rs | 7 +- .../payments/operations/payment_status.rs | 5 +- .../payments/operations/payment_update.rs | 7 +- .../payments_incremental_authorization.rs | 6 +- crates/router/src/core/payments/retry.rs | 4 +- crates/router/src/core/payments/routing.rs | 6 +- .../router/src/core/payments/tokenization.rs | 2 +- crates/router/src/core/payments/types.rs | 2 +- crates/router/src/core/payouts.rs | 25 +- crates/router/src/core/payouts/helpers.rs | 1 - crates/router/src/core/payouts/validator.rs | 3 + crates/router/src/core/routing.rs | 78 ++- crates/router/src/core/routing/helpers.rs | 26 +- crates/router/src/core/utils.rs | 25 +- crates/router/src/core/webhooks/incoming.rs | 22 +- crates/router/src/core/webhooks/outgoing.rs | 97 ++-- .../src/core/webhooks/webhook_events.rs | 12 +- crates/router/src/db/business_profile.rs | 309 +++++++++--- crates/router/src/db/kafka_store.rs | 56 ++- crates/router/src/routes/admin.rs | 6 +- crates/router/src/routes/routing.rs | 21 +- crates/router/src/routes/webhook_events.rs | 24 +- crates/router/src/services/authentication.rs | 2 + crates/router/src/types.rs | 4 +- crates/router/src/types/api/admin.rs | 134 +++-- crates/router/src/types/domain.rs | 12 +- .../src/types/storage/business_profile.rs | 3 +- crates/router/src/utils.rs | 2 +- crates/router/src/utils/user/sample_data.rs | 4 +- .../src/workflows/outgoing_webhook_retry.rs | 9 +- crates/router/src/workflows/payment_sync.rs | 6 +- 69 files changed, 913 insertions(+), 990 deletions(-) diff --git a/crates/api_models/src/admin.rs b/crates/api_models/src/admin.rs index 2ce1935bfb..9371e8ed07 100644 --- a/crates/api_models/src/admin.rs +++ b/crates/api_models/src/admin.rs @@ -2028,7 +2028,7 @@ pub struct BusinessProfileResponse { /// These key-value pairs are sent as additional custom headers in the outgoing webhook request. #[schema(value_type = Option, example = r#"{ "key1": "value-1", "key2": "value-2" }"#)] - pub outgoing_webhook_custom_http_headers: Option>, + pub outgoing_webhook_custom_http_headers: Option>>, } #[derive(Clone, Debug, Deserialize, ToSchema, Serialize)] diff --git a/crates/common_utils/src/types/keymanager.rs b/crates/common_utils/src/types/keymanager.rs index e263f3d578..05305b5370 100644 --- a/crates/common_utils/src/types/keymanager.rs +++ b/crates/common_utils/src/types/keymanager.rs @@ -21,7 +21,7 @@ use crate::{ transformers::{ForeignFrom, ForeignTryFrom}, }; -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct KeyManagerState { pub enabled: Option, pub url: String, diff --git a/crates/diesel_models/src/business_profile.rs b/crates/diesel_models/src/business_profile.rs index 6de77d5c5f..b6efa7ea27 100644 --- a/crates/diesel_models/src/business_profile.rs +++ b/crates/diesel_models/src/business_profile.rs @@ -135,258 +135,9 @@ pub struct BusinessProfileUpdateInternal { any(feature = "v1", feature = "v2"), not(feature = "business_profile_v2") ))] -#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] -pub struct BusinessProfileGeneralUpdate { - pub profile_name: Option, - pub return_url: Option, - pub enable_payment_response_hash: Option, - pub payment_response_hash_key: Option, - pub redirect_to_merchant_with_http_post: Option, - pub webhook_details: Option, - pub metadata: Option, - pub routing_algorithm: Option, - pub intent_fulfillment_time: Option, - pub frm_routing_algorithm: Option, - pub payout_routing_algorithm: Option, - pub is_recon_enabled: Option, - pub applepay_verified_domains: Option>, - pub payment_link_config: Option, - pub session_expiry: Option, - pub authentication_connector_details: Option, - pub payout_link_config: Option, - pub extended_card_info_config: Option, - pub use_billing_as_payment_method_billing: Option, - pub collect_shipping_details_from_wallet_connector: Option, - pub collect_billing_details_from_wallet_connector: Option, - pub is_connector_agnostic_mit_enabled: Option, - pub outgoing_webhook_custom_http_headers: Option, -} - -#[cfg(all( - any(feature = "v1", feature = "v2"), - not(feature = "business_profile_v2") -))] -#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] -pub enum BusinessProfileUpdate { - Update(Box), - RoutingAlgorithmUpdate { - routing_algorithm: Option, - payout_routing_algorithm: Option, - }, - ExtendedCardInfoUpdate { - is_extended_card_info_enabled: Option, - }, - ConnectorAgnosticMitUpdate { - is_connector_agnostic_mit_enabled: Option, - }, -} - -#[cfg(all( - any(feature = "v1", feature = "v2"), - not(feature = "business_profile_v2") -))] -impl From for BusinessProfileUpdateInternal { - fn from(business_profile_update: BusinessProfileUpdate) -> Self { - let now = common_utils::date_time::now(); - - match business_profile_update { - BusinessProfileUpdate::Update(update) => { - let BusinessProfileGeneralUpdate { - profile_name, - return_url, - enable_payment_response_hash, - payment_response_hash_key, - redirect_to_merchant_with_http_post, - webhook_details, - metadata, - routing_algorithm, - intent_fulfillment_time, - frm_routing_algorithm, - payout_routing_algorithm, - is_recon_enabled, - applepay_verified_domains, - payment_link_config, - session_expiry, - authentication_connector_details, - payout_link_config, - extended_card_info_config, - use_billing_as_payment_method_billing, - collect_shipping_details_from_wallet_connector, - collect_billing_details_from_wallet_connector, - is_connector_agnostic_mit_enabled, - outgoing_webhook_custom_http_headers, - } = *update; - Self { - profile_name, - modified_at: now, - return_url, - enable_payment_response_hash, - payment_response_hash_key, - redirect_to_merchant_with_http_post, - webhook_details, - metadata, - routing_algorithm, - intent_fulfillment_time, - frm_routing_algorithm, - payout_routing_algorithm, - is_recon_enabled, - applepay_verified_domains, - payment_link_config, - session_expiry, - authentication_connector_details, - payout_link_config, - is_extended_card_info_enabled: None, - extended_card_info_config, - use_billing_as_payment_method_billing, - collect_shipping_details_from_wallet_connector, - collect_billing_details_from_wallet_connector, - is_connector_agnostic_mit_enabled, - outgoing_webhook_custom_http_headers, - } - } - BusinessProfileUpdate::RoutingAlgorithmUpdate { - routing_algorithm, - payout_routing_algorithm, - } => Self { - profile_name: None, - modified_at: now, - return_url: None, - enable_payment_response_hash: None, - payment_response_hash_key: None, - redirect_to_merchant_with_http_post: None, - webhook_details: None, - metadata: None, - routing_algorithm, - intent_fulfillment_time: None, - frm_routing_algorithm: None, - payout_routing_algorithm, - is_recon_enabled: None, - applepay_verified_domains: None, - payment_link_config: None, - session_expiry: None, - authentication_connector_details: None, - payout_link_config: None, - is_extended_card_info_enabled: None, - extended_card_info_config: None, - is_connector_agnostic_mit_enabled: None, - use_billing_as_payment_method_billing: None, - collect_shipping_details_from_wallet_connector: None, - collect_billing_details_from_wallet_connector: None, - outgoing_webhook_custom_http_headers: None, - }, - BusinessProfileUpdate::ExtendedCardInfoUpdate { - is_extended_card_info_enabled, - } => Self { - profile_name: None, - modified_at: now, - return_url: None, - enable_payment_response_hash: None, - payment_response_hash_key: None, - redirect_to_merchant_with_http_post: None, - webhook_details: None, - metadata: None, - routing_algorithm: None, - intent_fulfillment_time: None, - frm_routing_algorithm: None, - payout_routing_algorithm: None, - is_recon_enabled: None, - applepay_verified_domains: None, - payment_link_config: None, - session_expiry: None, - authentication_connector_details: None, - payout_link_config: None, - is_extended_card_info_enabled, - extended_card_info_config: None, - is_connector_agnostic_mit_enabled: None, - use_billing_as_payment_method_billing: None, - collect_shipping_details_from_wallet_connector: None, - collect_billing_details_from_wallet_connector: None, - outgoing_webhook_custom_http_headers: None, - }, - BusinessProfileUpdate::ConnectorAgnosticMitUpdate { - is_connector_agnostic_mit_enabled, - } => Self { - profile_name: None, - modified_at: now, - return_url: None, - enable_payment_response_hash: None, - payment_response_hash_key: None, - redirect_to_merchant_with_http_post: None, - webhook_details: None, - metadata: None, - routing_algorithm: None, - intent_fulfillment_time: None, - frm_routing_algorithm: None, - payout_routing_algorithm: None, - is_recon_enabled: None, - applepay_verified_domains: None, - payment_link_config: None, - session_expiry: None, - authentication_connector_details: None, - payout_link_config: None, - is_extended_card_info_enabled: None, - extended_card_info_config: None, - is_connector_agnostic_mit_enabled, - use_billing_as_payment_method_billing: None, - collect_shipping_details_from_wallet_connector: None, - collect_billing_details_from_wallet_connector: None, - outgoing_webhook_custom_http_headers: None, - }, - } - } -} - -// This is being used only in the `BusinessProfileInterface` implementation for `MockDb`. -// This can be removed once the `BusinessProfileInterface` trait has been updated to use the domain -// model instead. -#[cfg(all( - any(feature = "v1", feature = "v2"), - not(feature = "business_profile_v2") -))] -impl From for BusinessProfile { - fn from(new: BusinessProfileNew) -> Self { - Self { - profile_id: new.profile_id, - merchant_id: new.merchant_id, - profile_name: new.profile_name, - created_at: new.created_at, - modified_at: new.modified_at, - return_url: new.return_url, - enable_payment_response_hash: new.enable_payment_response_hash, - payment_response_hash_key: new.payment_response_hash_key, - redirect_to_merchant_with_http_post: new.redirect_to_merchant_with_http_post, - webhook_details: new.webhook_details, - metadata: new.metadata, - routing_algorithm: new.routing_algorithm, - intent_fulfillment_time: new.intent_fulfillment_time, - frm_routing_algorithm: new.frm_routing_algorithm, - payout_routing_algorithm: new.payout_routing_algorithm, - is_recon_enabled: new.is_recon_enabled, - applepay_verified_domains: new.applepay_verified_domains, - payment_link_config: new.payment_link_config, - session_expiry: new.session_expiry, - authentication_connector_details: new.authentication_connector_details, - payout_link_config: new.payout_link_config, - is_connector_agnostic_mit_enabled: new.is_connector_agnostic_mit_enabled, - is_extended_card_info_enabled: new.is_extended_card_info_enabled, - extended_card_info_config: new.extended_card_info_config, - use_billing_as_payment_method_billing: new.use_billing_as_payment_method_billing, - collect_shipping_details_from_wallet_connector: new - .collect_shipping_details_from_wallet_connector, - collect_billing_details_from_wallet_connector: new - .collect_billing_details_from_wallet_connector, - outgoing_webhook_custom_http_headers: new.outgoing_webhook_custom_http_headers, - } - } -} - -#[cfg(all( - any(feature = "v1", feature = "v2"), - not(feature = "business_profile_v2") -))] -impl BusinessProfileUpdate { +impl BusinessProfileUpdateInternal { pub fn apply_changeset(self, source: BusinessProfile) -> BusinessProfile { - let BusinessProfileUpdateInternal { + let Self { profile_name, modified_at, return_url, @@ -412,7 +163,7 @@ impl BusinessProfileUpdate { collect_shipping_details_from_wallet_connector, collect_billing_details_from_wallet_connector, outgoing_webhook_custom_http_headers, - } = self.into(); + } = self; BusinessProfile { profile_id: source.profile_id, merchant_id: source.merchant_id, @@ -574,217 +325,9 @@ pub struct BusinessProfileUpdateInternal { } #[cfg(all(feature = "v2", feature = "business_profile_v2"))] -#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] -pub struct BusinessProfileGeneralUpdate { - pub profile_name: Option, - pub return_url: Option, - pub enable_payment_response_hash: Option, - pub payment_response_hash_key: Option, - pub redirect_to_merchant_with_http_post: Option, - pub webhook_details: Option, - pub metadata: Option, - pub is_recon_enabled: Option, - pub applepay_verified_domains: Option>, - pub payment_link_config: Option, - pub session_expiry: Option, - pub authentication_connector_details: Option, - pub payout_link_config: Option, - pub extended_card_info_config: Option, - pub use_billing_as_payment_method_billing: Option, - pub collect_shipping_details_from_wallet_connector: Option, - pub collect_billing_details_from_wallet_connector: Option, - pub is_connector_agnostic_mit_enabled: Option, - pub outgoing_webhook_custom_http_headers: Option, - pub routing_algorithm_id: Option, - pub order_fulfillment_time: Option, - pub order_fulfillment_time_origin: Option, - pub frm_routing_algorithm_id: Option, - pub payout_routing_algorithm_id: Option, - pub default_fallback_routing: Option, -} - -#[cfg(all(feature = "v2", feature = "business_profile_v2"))] -#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] -pub enum BusinessProfileUpdate { - Update(Box), - RoutingAlgorithmUpdate { - routing_algorithm_id: Option, - payout_routing_algorithm_id: Option, - }, - ExtendedCardInfoUpdate { - is_extended_card_info_enabled: Option, - }, - ConnectorAgnosticMitUpdate { - is_connector_agnostic_mit_enabled: Option, - }, -} - -#[cfg(all(feature = "v2", feature = "business_profile_v2"))] -impl From for BusinessProfileUpdateInternal { - fn from(business_profile_update: BusinessProfileUpdate) -> Self { - let now = common_utils::date_time::now(); - - match business_profile_update { - BusinessProfileUpdate::Update(update) => { - let BusinessProfileGeneralUpdate { - profile_name, - return_url, - enable_payment_response_hash, - payment_response_hash_key, - redirect_to_merchant_with_http_post, - webhook_details, - metadata, - is_recon_enabled, - applepay_verified_domains, - payment_link_config, - session_expiry, - authentication_connector_details, - payout_link_config, - extended_card_info_config, - use_billing_as_payment_method_billing, - collect_shipping_details_from_wallet_connector, - collect_billing_details_from_wallet_connector, - is_connector_agnostic_mit_enabled, - outgoing_webhook_custom_http_headers, - routing_algorithm_id, - order_fulfillment_time, - order_fulfillment_time_origin, - frm_routing_algorithm_id, - payout_routing_algorithm_id, - default_fallback_routing, - } = *update; - Self { - profile_name, - modified_at: now, - return_url, - enable_payment_response_hash, - payment_response_hash_key, - redirect_to_merchant_with_http_post, - webhook_details, - metadata, - is_recon_enabled, - applepay_verified_domains, - payment_link_config, - session_expiry, - authentication_connector_details, - payout_link_config, - is_extended_card_info_enabled: None, - extended_card_info_config, - use_billing_as_payment_method_billing, - collect_shipping_details_from_wallet_connector, - collect_billing_details_from_wallet_connector, - is_connector_agnostic_mit_enabled, - outgoing_webhook_custom_http_headers, - routing_algorithm_id, - order_fulfillment_time, - order_fulfillment_time_origin, - frm_routing_algorithm_id, - payout_routing_algorithm_id, - default_fallback_routing, - } - } - BusinessProfileUpdate::RoutingAlgorithmUpdate { - routing_algorithm_id, - payout_routing_algorithm_id, - } => Self { - profile_name: None, - modified_at: now, - return_url: None, - enable_payment_response_hash: None, - payment_response_hash_key: None, - redirect_to_merchant_with_http_post: None, - webhook_details: None, - metadata: None, - is_recon_enabled: None, - applepay_verified_domains: None, - payment_link_config: None, - session_expiry: None, - authentication_connector_details: None, - payout_link_config: None, - is_extended_card_info_enabled: None, - extended_card_info_config: None, - is_connector_agnostic_mit_enabled: None, - use_billing_as_payment_method_billing: None, - collect_shipping_details_from_wallet_connector: None, - collect_billing_details_from_wallet_connector: None, - outgoing_webhook_custom_http_headers: None, - routing_algorithm_id, - order_fulfillment_time: None, - order_fulfillment_time_origin: None, - frm_routing_algorithm_id: None, - payout_routing_algorithm_id, - default_fallback_routing: None, - }, - BusinessProfileUpdate::ExtendedCardInfoUpdate { - is_extended_card_info_enabled, - } => Self { - profile_name: None, - modified_at: now, - return_url: None, - enable_payment_response_hash: None, - payment_response_hash_key: None, - redirect_to_merchant_with_http_post: None, - webhook_details: None, - metadata: None, - is_recon_enabled: None, - applepay_verified_domains: None, - payment_link_config: None, - session_expiry: None, - authentication_connector_details: None, - payout_link_config: None, - is_extended_card_info_enabled, - extended_card_info_config: None, - is_connector_agnostic_mit_enabled: None, - use_billing_as_payment_method_billing: None, - collect_shipping_details_from_wallet_connector: None, - collect_billing_details_from_wallet_connector: None, - outgoing_webhook_custom_http_headers: None, - routing_algorithm_id: None, - order_fulfillment_time: None, - order_fulfillment_time_origin: None, - frm_routing_algorithm_id: None, - payout_routing_algorithm_id: None, - default_fallback_routing: None, - }, - BusinessProfileUpdate::ConnectorAgnosticMitUpdate { - is_connector_agnostic_mit_enabled, - } => Self { - profile_name: None, - modified_at: now, - return_url: None, - enable_payment_response_hash: None, - payment_response_hash_key: None, - redirect_to_merchant_with_http_post: None, - webhook_details: None, - metadata: None, - is_recon_enabled: None, - applepay_verified_domains: None, - payment_link_config: None, - session_expiry: None, - authentication_connector_details: None, - payout_link_config: None, - is_extended_card_info_enabled: None, - extended_card_info_config: None, - is_connector_agnostic_mit_enabled, - use_billing_as_payment_method_billing: None, - collect_shipping_details_from_wallet_connector: None, - collect_billing_details_from_wallet_connector: None, - outgoing_webhook_custom_http_headers: None, - routing_algorithm_id: None, - order_fulfillment_time: None, - order_fulfillment_time_origin: None, - frm_routing_algorithm_id: None, - payout_routing_algorithm_id: None, - default_fallback_routing: None, - }, - } - } -} - -#[cfg(all(feature = "v2", feature = "business_profile_v2"))] -impl BusinessProfileUpdate { +impl BusinessProfileUpdateInternal { pub fn apply_changeset(self, source: BusinessProfile) -> BusinessProfile { - let BusinessProfileUpdateInternal { + let Self { profile_name, modified_at, return_url, @@ -812,7 +355,7 @@ impl BusinessProfileUpdate { frm_routing_algorithm_id, payout_routing_algorithm_id, default_fallback_routing, - } = self.into(); + } = self; BusinessProfile { profile_id: source.profile_id, merchant_id: source.merchant_id, diff --git a/crates/diesel_models/src/query/business_profile.rs b/crates/diesel_models/src/query/business_profile.rs index 1b8e54e018..09fa700dae 100644 --- a/crates/diesel_models/src/query/business_profile.rs +++ b/crates/diesel_models/src/query/business_profile.rs @@ -9,9 +9,7 @@ use crate::schema::business_profile::dsl; #[cfg(all(feature = "v2", feature = "business_profile_v2"))] use crate::schema_v2::business_profile::dsl; use crate::{ - business_profile::{ - BusinessProfile, BusinessProfileNew, BusinessProfileUpdate, BusinessProfileUpdateInternal, - }, + business_profile::{BusinessProfile, BusinessProfileNew, BusinessProfileUpdateInternal}, errors, PgPooledConn, StorageResult, }; @@ -25,12 +23,12 @@ impl BusinessProfile { pub async fn update_by_profile_id( self, conn: &PgPooledConn, - business_profile: BusinessProfileUpdate, + business_profile: BusinessProfileUpdateInternal, ) -> StorageResult { match generics::generic_update_by_id::<::Table, _, _, _>( conn, self.profile_id.clone(), - BusinessProfileUpdateInternal::from(business_profile), + business_profile, ) .await { diff --git a/crates/hyperswitch_domain_models/src/customer.rs b/crates/hyperswitch_domain_models/src/customer.rs index 42c66b74c0..b1a8f8dfdb 100644 --- a/crates/hyperswitch_domain_models/src/customer.rs +++ b/crates/hyperswitch_domain_models/src/customer.rs @@ -212,7 +212,7 @@ impl super::behaviour::Conversion for Customer { { let decrypted = types::crypto_operation( state, - type_name!(Self::DstType), + common_utils::type_name!(Self::DstType), types::CryptoOperation::BatchDecrypt(CustomerRequestWithEncryption::to_encryptable( CustomerRequestWithEncryption { name: item.name.clone(), diff --git a/crates/hyperswitch_domain_models/src/merchant_account.rs b/crates/hyperswitch_domain_models/src/merchant_account.rs index 8ce0b3a5e4..27592e84a4 100644 --- a/crates/hyperswitch_domain_models/src/merchant_account.rs +++ b/crates/hyperswitch_domain_models/src/merchant_account.rs @@ -8,8 +8,7 @@ use common_utils::{ types::keymanager::{self}, }; use diesel_models::{ - business_profile::WebhookDetails, enums::MerchantStorageScheme, - merchant_account::MerchantAccountUpdateInternal, + enums::MerchantStorageScheme, merchant_account::MerchantAccountUpdateInternal, }; use error_stack::ResultExt; use masking::{PeekInterface, Secret}; @@ -30,7 +29,7 @@ pub struct MerchantAccount { pub redirect_to_merchant_with_http_post: bool, pub merchant_name: OptionalEncryptableName, pub merchant_details: OptionalEncryptableValue, - pub webhook_details: Option, + pub webhook_details: Option, pub sub_merchants_enabled: Option, pub parent_merchant_id: Option, pub publishable_key: String, @@ -66,7 +65,7 @@ pub struct MerchantAccountSetter { pub redirect_to_merchant_with_http_post: bool, pub merchant_name: OptionalEncryptableName, pub merchant_details: OptionalEncryptableValue, - pub webhook_details: Option, + pub webhook_details: Option, pub sub_merchants_enabled: Option, pub parent_merchant_id: Option, pub publishable_key: String, @@ -227,7 +226,7 @@ pub enum MerchantAccountUpdate { merchant_name: OptionalEncryptableName, merchant_details: OptionalEncryptableValue, return_url: Option, - webhook_details: Option, + webhook_details: Option, sub_merchants_enabled: Option, parent_merchant_id: Option, enable_payment_response_hash: Option, diff --git a/crates/router/Cargo.toml b/crates/router/Cargo.toml index 78e5c74fc0..3e0470cc08 100644 --- a/crates/router/Cargo.toml +++ b/crates/router/Cargo.toml @@ -34,7 +34,7 @@ retry = [] v2 = ["api_models/v2", "diesel_models/v2", "hyperswitch_domain_models/v2", "storage_impl/v2", "kgraph_utils/v2"] v1 = ["api_models/v1", "diesel_models/v1", "hyperswitch_domain_models/v1", "storage_impl/v1", "hyperswitch_interfaces/v1", "kgraph_utils/v1"] # business_profile_v2 = ["api_models/business_profile_v2", "diesel_models/business_profile_v2", "hyperswitch_domain_models/business_profile_v2"] -customer_v2 = ["api_models/customer_v2", "diesel_models/customer_v2", "hyperswitch_domain_models/customer_v2"] +customer_v2 = ["api_models/customer_v2", "diesel_models/customer_v2", "hyperswitch_domain_models/customer_v2", "storage_impl/customer_v2"] merchant_account_v2 = ["api_models/merchant_account_v2", "diesel_models/merchant_account_v2", "hyperswitch_domain_models/merchant_account_v2"] payment_v2 = ["api_models/payment_v2", "diesel_models/payment_v2", "hyperswitch_domain_models/payment_v2"] payment_methods_v2 = ["api_models/payment_methods_v2"] diff --git a/crates/router/src/connector/braintree/transformers.rs b/crates/router/src/connector/braintree/transformers.rs index 8a4ce8126d..e5f97dc333 100644 --- a/crates/router/src/connector/braintree/transformers.rs +++ b/crates/router/src/connector/braintree/transformers.rs @@ -1203,12 +1203,6 @@ pub struct CaptureInputData { transaction: CaptureTransactionBody, } -#[derive(Debug, Clone, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct PsyncInputData { - transaction_id: String, -} - impl TryFrom<&BraintreeRouterData<&types::PaymentsCaptureRouterData>> for BraintreeCaptureRequest { type Error = error_stack::Report; fn try_from( diff --git a/crates/router/src/core/admin.rs b/crates/router/src/core/admin.rs index a1cf93a0ac..736360edf0 100644 --- a/crates/router/src/core/admin.rs +++ b/crates/router/src/core/admin.rs @@ -561,7 +561,7 @@ impl CreateBusinessProfile { state: &SessionState, merchant_account: domain::MerchantAccount, key_store: &domain::MerchantKeyStore, - ) -> RouterResult { + ) -> RouterResult { let business_profile = create_and_insert_business_profile( state, api_models::admin::BusinessProfileCreate::default(), @@ -581,7 +581,7 @@ impl CreateBusinessProfile { merchant_account: domain::MerchantAccount, primary_business_details: &Vec, key_store: &domain::MerchantKeyStore, - ) -> RouterResult> { + ) -> RouterResult> { let mut business_profiles_vector = Vec::with_capacity(primary_business_details.len()); // This must ideally be run in a transaction, @@ -898,6 +898,8 @@ impl MerchantAccountUpdateBridge for api::MerchantAccountUpdate { // Validate whether profile_id passed in request is valid and is linked to the merchant core_utils::validate_and_get_business_profile( state.store.as_ref(), + key_manager_state, + key_store, Some(profile_id), merchant_id, ) @@ -1016,25 +1018,31 @@ impl MerchantAccountUpdateBridge for api::MerchantAccountUpdate { merchant_name: self .merchant_name .map(Secret::new) - .async_lift(|inner| { - domain_types::encrypt_optional( + .async_lift(|inner| async { + domain_types::crypto_operation( key_manager_state, - inner, + type_name!(storage::MerchantAccount), + domain_types::CryptoOperation::EncryptOptional(inner), identifier.clone(), key, ) + .await + .and_then(|val| val.try_into_optionaloperation()) }) .await .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Unable to encrypt merchant name")?, merchant_details: merchant_details - .async_lift(|inner| { - domain_types::encrypt_optional( + .async_lift(|inner| async { + domain_types::crypto_operation( key_manager_state, - inner, - km_types::Identifier::Merchant(key_store.merchant_id.clone()), + type_name!(storage::MerchantAccount), + domain_types::CryptoOperation::EncryptOptional(inner), + identifier.clone(), key, ) + .await + .and_then(|val| val.try_into_optionaloperation()) }) .await .change_context(errors::ApiErrorResponse::InternalServerError) @@ -2031,7 +2039,7 @@ impl MerchantConnectorAccountUpdateBridge for api_models::admin::MerchantConnect domain_types::crypto_operation( key_manager_state, type_name!(storage::MerchantConnectorAccount), - domai_types::CryptoOperation::EncryptOptional(inner), + domain_types::CryptoOperation::EncryptOptional(inner), km_types::Identifier::Merchant(key_store.merchant_id.clone()), key_store.key.get_inner().peek(), ) @@ -2210,7 +2218,7 @@ trait MerchantConnectorAccountCreateBridge { self, state: &SessionState, key_store: domain::MerchantKeyStore, - business_profile: &storage::business_profile::BusinessProfile, + business_profile: &domain::BusinessProfile, key_manager_state: &KeyManagerState, ) -> RouterResult; @@ -2218,6 +2226,8 @@ trait MerchantConnectorAccountCreateBridge { self, merchant_account: &domain::MerchantAccount, db: &dyn StorageInterface, + key_manager_state: &KeyManagerState, + key_store: &domain::MerchantKeyStore, should_validate: bool, ) -> RouterResult; } @@ -2234,7 +2244,7 @@ impl MerchantConnectorAccountCreateBridge for api::MerchantConnectorCreate { self, state: &SessionState, key_store: domain::MerchantKeyStore, - business_profile: &storage::business_profile::BusinessProfile, + business_profile: &domain::BusinessProfile, key_manager_state: &KeyManagerState, ) -> RouterResult { // If connector label is not passed in the request, generate one @@ -2358,6 +2368,8 @@ impl MerchantConnectorAccountCreateBridge for api::MerchantConnectorCreate { self, merchant_account: &domain::MerchantAccount, db: &dyn StorageInterface, + key_manager_state: &KeyManagerState, + key_store: &domain::MerchantKeyStore, should_validate: bool, ) -> RouterResult { match self.profile_id { @@ -2366,6 +2378,8 @@ impl MerchantConnectorAccountCreateBridge for api::MerchantConnectorCreate { if should_validate { let _ = core_utils::validate_and_get_business_profile( db, + key_manager_state, + key_store, Some(&profile_id), merchant_account.get_id(), ) @@ -2391,7 +2405,7 @@ impl MerchantConnectorAccountCreateBridge for api::MerchantConnectorCreate { self, state: &SessionState, key_store: domain::MerchantKeyStore, - business_profile: &storage::business_profile::BusinessProfile, + business_profile: &domain::BusinessProfile, key_manager_state: &KeyManagerState, ) -> RouterResult { // If connector label is not passed in the request, generate one @@ -2532,6 +2546,8 @@ impl MerchantConnectorAccountCreateBridge for api::MerchantConnectorCreate { self, merchant_account: &domain::MerchantAccount, db: &dyn StorageInterface, + key_manager_state: &KeyManagerState, + key_store: &domain::MerchantKeyStore, should_validate: bool, ) -> RouterResult { match self.profile_id.or(merchant_account.default_profile.clone()) { @@ -2540,6 +2556,8 @@ impl MerchantConnectorAccountCreateBridge for api::MerchantConnectorCreate { if should_validate { let _ = core_utils::validate_and_get_business_profile( db, + key_manager_state, + key_store, Some(&profile_id), merchant_account.get_id(), ) @@ -2552,6 +2570,8 @@ impl MerchantConnectorAccountCreateBridge for api::MerchantConnectorCreate { let profile_name = format!("{business_country}_{business_label}"); let business_profile = db .find_business_profile_by_profile_name_merchant_id( + key_manager_state, + key_store, &profile_name, merchant_account.get_id(), ) @@ -2618,7 +2638,13 @@ pub async fn create_connector( let profile_id = req .clone() - .validate_and_get_profile_id(&merchant_account, store, true) + .validate_and_get_profile_id( + &merchant_account, + store, + key_manager_state, + &key_store, + true, + ) .await?; let pm_auth_config_validation = PMAuthConfigValidation { @@ -2634,7 +2660,7 @@ pub async fn create_connector( let business_profile = state .store - .find_business_profile_by_profile_id(&profile_id) + .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_owned(), @@ -3257,7 +3283,7 @@ pub async fn create_and_insert_business_profile( request: api::BusinessProfileCreate, merchant_account: domain::MerchantAccount, key_store: &domain::MerchantKeyStore, -) -> RouterResult { +) -> RouterResult { #[cfg(all( any(feature = "v1", feature = "v2"), not(feature = "merchant_account_v2") @@ -3275,7 +3301,7 @@ pub async fn create_and_insert_business_profile( state .store - .insert_business_profile(business_profile_new) + .insert_business_profile(&state.into(), key_store, business_profile_new) .await .to_duplicate_response(errors::ApiErrorResponse::GenericDuplicateError { message: format!( @@ -3347,10 +3373,9 @@ pub async fn create_business_profile( } Ok(service_api::ApplicationResponse::Json( - admin::business_profile_response(&state, business_profile, &key_store) + api_models::admin::BusinessProfileResponse::foreign_try_from(business_profile) .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Failed to parse business profile details") - .await?, + .attach_printable("Failed to parse business profile details")?, )) } @@ -3377,16 +3402,16 @@ pub async fn list_business_profile( .await .to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?; let profiles = db - .list_business_profile_by_merchant_id(&merchant_id) + .list_business_profile_by_merchant_id(&(&state).into(), &key_store, &merchant_id) .await .to_not_found_response(errors::ApiErrorResponse::InternalServerError)? .clone(); let mut business_profiles = Vec::new(); for profile in profiles { - let business_profile = admin::business_profile_response(&state, profile, &key_store) - .await - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Failed to parse business profile details")?; + let business_profile = + api_models::admin::BusinessProfileResponse::foreign_try_from(profile) + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Failed to parse business profile details")?; business_profiles.push(business_profile); } @@ -3408,17 +3433,16 @@ pub async fn retrieve_business_profile( .await .to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?; let business_profile = db - .find_business_profile_by_profile_id(&profile_id) + .find_business_profile_by_profile_id(&(&state).into(), &key_store, &profile_id) .await .to_not_found_response(errors::ApiErrorResponse::BusinessProfileNotFound { id: profile_id, })?; Ok(service_api::ApplicationResponse::Json( - admin::business_profile_response(&state, business_profile, &key_store) + api_models::admin::BusinessProfileResponse::foreign_try_from(business_profile) .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Failed to parse business profile details") - .await?, + .attach_printable("Failed to parse business profile details")?, )) } @@ -3445,12 +3469,6 @@ pub async fn update_business_profile( request: api::BusinessProfileUpdate, ) -> RouterResponse { let db = state.store.as_ref(); - let business_profile = db - .find_business_profile_by_profile_id(profile_id) - .await - .to_not_found_response(errors::ApiErrorResponse::BusinessProfileNotFound { - id: profile_id.to_owned(), - })?; let key_store = db .get_merchant_key_store_by_merchant_id( &(&state).into(), @@ -3460,6 +3478,14 @@ pub async fn update_business_profile( .await .to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound) .attach_printable("Error while fetching the key store by merchant_id")?; + let key_manager_state = &(&state).into(); + + 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_owned(), + })?; if business_profile.merchant_id != *merchant_id { Err(errors::ApiErrorResponse::AccessForbidden { @@ -3528,7 +3554,7 @@ pub async fn update_business_profile( .transpose()?; let business_profile_update = - storage::BusinessProfileUpdate::Update(Box::new(storage::BusinessProfileGeneralUpdate { + domain::BusinessProfileUpdate::Update(Box::new(domain::BusinessProfileGeneralUpdate { profile_name: request.profile_name, return_url: request.return_url.map(|return_url| return_url.to_string()), enable_payment_response_hash: request.enable_payment_response_hash, @@ -3563,28 +3589,45 @@ pub async fn update_business_profile( })); let updated_business_profile = db - .update_business_profile_by_profile_id(business_profile, business_profile_update) + .update_business_profile_by_profile_id( + key_manager_state, + &key_store, + business_profile, + business_profile_update, + ) .await .to_not_found_response(errors::ApiErrorResponse::BusinessProfileNotFound { id: profile_id.to_owned(), })?; Ok(service_api::ApplicationResponse::Json( - admin::business_profile_response(&state, updated_business_profile, &key_store) + api_models::admin::BusinessProfileResponse::foreign_try_from(updated_business_profile) .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Failed to parse business profile details") - .await?, + .attach_printable("Failed to parse business profile details")?, )) } pub async fn extended_card_info_toggle( state: SessionState, + merchant_id: &id_type::MerchantId, profile_id: &str, ext_card_info_choice: admin_types::ExtendedCardInfoChoice, ) -> RouterResponse { let db = state.store.as_ref(); + let key_manager_state = &(&state).into(); + + let key_store = db + .get_merchant_key_store_by_merchant_id( + key_manager_state, + merchant_id, + &state.store.get_master_key().to_vec().into(), + ) + .await + .to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound) + .attach_printable("Error while fetching the key store by merchant_id")?; + let business_profile = db - .find_business_profile_by_profile_id(profile_id) + .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(), @@ -3595,16 +3638,20 @@ pub async fn extended_card_info_toggle( .is_extended_card_info_enabled .is_some_and(|existing_config| existing_config != ext_card_info_choice.enabled) { - let business_profile_update = - storage::business_profile::BusinessProfileUpdate::ExtendedCardInfoUpdate { - is_extended_card_info_enabled: Some(ext_card_info_choice.enabled), - }; + let business_profile_update = domain::BusinessProfileUpdate::ExtendedCardInfoUpdate { + is_extended_card_info_enabled: Some(ext_card_info_choice.enabled), + }; - db.update_business_profile_by_profile_id(business_profile, business_profile_update) - .await - .to_not_found_response(errors::ApiErrorResponse::BusinessProfileNotFound { - id: profile_id.to_owned(), - })?; + db.update_business_profile_by_profile_id( + key_manager_state, + &key_store, + business_profile, + business_profile_update, + ) + .await + .to_not_found_response(errors::ApiErrorResponse::BusinessProfileNotFound { + id: profile_id.to_owned(), + })?; } Ok(service_api::ApplicationResponse::Json(ext_card_info_choice)) @@ -3617,9 +3664,20 @@ pub async fn connector_agnostic_mit_toggle( connector_agnostic_mit_choice: admin_types::ConnectorAgnosticMitChoice, ) -> RouterResponse { let db = state.store.as_ref(); + let key_manager_state = &(&state).into(); + + let key_store = db + .get_merchant_key_store_by_merchant_id( + key_manager_state, + merchant_id, + &state.store.get_master_key().to_vec().into(), + ) + .await + .to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound) + .attach_printable("Error while fetching the key store by merchant_id")?; let business_profile = db - .find_business_profile_by_profile_id(profile_id) + .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(), @@ -3634,16 +3692,20 @@ pub async fn connector_agnostic_mit_toggle( if business_profile.is_connector_agnostic_mit_enabled != Some(connector_agnostic_mit_choice.enabled) { - let business_profile_update = - storage::business_profile::BusinessProfileUpdate::ConnectorAgnosticMitUpdate { - is_connector_agnostic_mit_enabled: Some(connector_agnostic_mit_choice.enabled), - }; + let business_profile_update = domain::BusinessProfileUpdate::ConnectorAgnosticMitUpdate { + is_connector_agnostic_mit_enabled: Some(connector_agnostic_mit_choice.enabled), + }; - db.update_business_profile_by_profile_id(business_profile, business_profile_update) - .await - .to_not_found_response(errors::ApiErrorResponse::BusinessProfileNotFound { - id: profile_id.to_owned(), - })?; + db.update_business_profile_by_profile_id( + key_manager_state, + &key_store, + business_profile, + business_profile_update, + ) + .await + .to_not_found_response(errors::ApiErrorResponse::BusinessProfileNotFound { + id: profile_id.to_owned(), + })?; } Ok(service_api::ApplicationResponse::Json( diff --git a/crates/router/src/core/authentication.rs b/crates/router/src/core/authentication.rs index 7cc03ab9ea..2e292d1609 100644 --- a/crates/router/src/core/authentication.rs +++ b/crates/router/src/core/authentication.rs @@ -80,7 +80,7 @@ pub async fn perform_authentication( pub async fn perform_post_authentication( state: &SessionState, key_store: &domain::MerchantKeyStore, - business_profile: storage::BusinessProfile, + business_profile: domain::BusinessProfile, authentication_id: String, ) -> CustomResult { let (authentication_connector, three_ds_connector_account) = @@ -121,7 +121,7 @@ pub async fn perform_pre_authentication( key_store: &domain::MerchantKeyStore, card_number: cards::CardNumber, token: String, - business_profile: &storage::BusinessProfile, + business_profile: &domain::BusinessProfile, acquirer_details: Option, payment_id: Option, ) -> CustomResult { diff --git a/crates/router/src/core/authentication/transformers.rs b/crates/router/src/core/authentication/transformers.rs index 569f2beea5..5ca3d05f12 100644 --- a/crates/router/src/core/authentication/transformers.rs +++ b/crates/router/src/core/authentication/transformers.rs @@ -11,7 +11,7 @@ use crate::{ payments::helpers as payments_helpers, }, types::{ - self, storage, + self, domain, storage, transformers::{ForeignFrom, ForeignTryFrom}, }, utils::ext_traits::OptionExt, @@ -77,7 +77,7 @@ pub fn construct_authentication_router_data( pub fn construct_post_authentication_router_data( authentication_connector: String, - business_profile: storage::BusinessProfile, + business_profile: domain::BusinessProfile, merchant_connector_account: payments_helpers::MerchantConnectorAccountType, authentication_data: &storage::Authentication, ) -> RouterResult { diff --git a/crates/router/src/core/authentication/utils.rs b/crates/router/src/core/authentication/utils.rs index ebfa603747..87235582c0 100644 --- a/crates/router/src/core/authentication/utils.rs +++ b/crates/router/src/core/authentication/utils.rs @@ -266,7 +266,7 @@ where pub async fn get_authentication_connector_data( state: &SessionState, key_store: &domain::MerchantKeyStore, - business_profile: &storage::BusinessProfile, + business_profile: &domain::BusinessProfile, ) -> RouterResult<( common_enums::AuthenticationConnectors, payments::helpers::MerchantConnectorAccountType, diff --git a/crates/router/src/core/payment_link.rs b/crates/router/src/core/payment_link.rs index bbb2b5d69f..299ae97d3a 100644 --- a/crates/router/src/core/payment_link.rs +++ b/crates/router/src/core/payment_link.rs @@ -68,6 +68,8 @@ pub async fn form_payment_link_data( locale: Option, ) -> RouterResult<(PaymentLink, PaymentLinkData, PaymentLinkConfig)> { let db = &*state.store; + let key_manager_state = &state.into(); + let payment_intent = db .find_payment_intent_by_payment_id_merchant_id( &(state).into(), @@ -118,7 +120,7 @@ pub async fn form_payment_link_data( .attach_printable("Profile id missing in payment link and payment intent")?; let business_profile = db - .find_business_profile_by_profile_id(&profile_id) + .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(), @@ -636,9 +638,11 @@ pub async fn get_payment_link_status( let locale = get_header_value_by_key(ACCEPT_LANGUAGE.into(), request_headers)? .map(|val| val.to_string()); let db = &*state.store; + let key_manager_state = &(&state).into(); + let payment_intent = db .find_payment_intent_by_payment_id_merchant_id( - &(&state).into(), + key_manager_state, &payment_id, &merchant_id, &key_store, @@ -714,7 +718,7 @@ pub async fn get_payment_link_status( .attach_printable("Profile id missing in payment link and payment intent")?; let business_profile = db - .find_business_profile_by_profile_id(&profile_id) + .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(), diff --git a/crates/router/src/core/payment_methods.rs b/crates/router/src/core/payment_methods.rs index 48bf88bc44..09b36946b7 100644 --- a/crates/router/src/core/payment_methods.rs +++ b/crates/router/src/core/payment_methods.rs @@ -51,7 +51,7 @@ pub async fn retrieve_payment_method( payment_intent: &PaymentIntent, payment_attempt: &PaymentAttempt, merchant_key_store: &domain::MerchantKeyStore, - business_profile: Option<&diesel_models::business_profile::BusinessProfile>, + business_profile: Option<&domain::BusinessProfile>, ) -> RouterResult<(Option, Option)> { match pm_data { pm_opt @ Some(pm @ api::PaymentMethodData::Card(_)) => { diff --git a/crates/router/src/core/payment_methods/cards.rs b/crates/router/src/core/payment_methods/cards.rs index 0c507550f8..fa01437e5e 100644 --- a/crates/router/src/core/payment_methods/cards.rs +++ b/crates/router/src/core/payment_methods/cards.rs @@ -31,7 +31,7 @@ use common_utils::{ MinorUnit, }, }; -use diesel_models::{business_profile::BusinessProfile, payment_method}; +use diesel_models::payment_method; use domain::CustomerUpdate; use error_stack::{report, ResultExt}; use euclid::{ @@ -76,7 +76,7 @@ use crate::{ services, types::{ api::{self, routing as routing_types, PaymentMethodCreateExt}, - domain, + domain::{self, BusinessProfile}, storage::{self, enums, PaymentMethodListContext, PaymentTokenData}, transformers::{ForeignFrom, ForeignTryFrom}, }, @@ -2351,7 +2351,7 @@ pub async fn list_payment_methods( let profile_id = payment_intent .as_ref() - .async_map(|payment_intent| async { + .map(|payment_intent| { payment_intent .profile_id .clone() @@ -2359,10 +2359,11 @@ pub async fn list_payment_methods( .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("profile_id is not set in payment_intent") }) - .await .transpose()?; let business_profile = core_utils::validate_and_get_business_profile( db, + key_manager_state, + &key_store, profile_id.as_ref(), merchant_account.get_id(), ) @@ -3768,6 +3769,7 @@ pub async fn list_customer_payment_method( limit: Option, ) -> errors::RouterResponse { let db = &*state.store; + let key_manager_state = &state.into(); let off_session_payment_flag = payment_intent .as_ref() .map(|pi| { @@ -3814,7 +3816,7 @@ pub async fn list_customer_payment_method( let profile_id = payment_intent .as_ref() - .async_map(|payment_intent| async { + .map(|payment_intent| { payment_intent .profile_id .clone() @@ -3822,11 +3824,12 @@ pub async fn list_customer_payment_method( .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("profile_id is not set in payment_intent") }) - .await .transpose()?; let business_profile = core_utils::validate_and_get_business_profile( db, + key_manager_state, + &key_store, profile_id.as_ref(), merchant_account.get_id(), ) @@ -4141,10 +4144,16 @@ impl SavedPMLPaymentsInfo { payment_intent: storage::PaymentIntent, merchant_account: &domain::MerchantAccount, db: &dyn db::StorageInterface, + key_manager_state: &KeyManagerState, + key_store: &domain::MerchantKeyStore, ) -> errors::RouterResult { let requires_cvv = db .find_config_by_key_unwrap_or( - format!("{}_requires_cvv", merchant_account.get_id()).as_str(), + format!( + "{}_requires_cvv", + merchant_account.get_id().get_string_repr() + ) + .as_str(), Some("true".to_string()), ) .await @@ -4158,19 +4167,18 @@ impl SavedPMLPaymentsInfo { Some(common_enums::FutureUsage::OffSession) ); - let profile_id = core_utils::get_profile_id_from_business_details( - payment_intent.business_country, - payment_intent.business_label.as_ref(), - merchant_account, - payment_intent.profile_id.as_ref(), - db, - false, - ) - .await - .attach_printable("Could not find profile id from business details")?; + let profile_id = payment_intent + .profile_id + .as_ref() + .get_required_value("profile_id") + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("profile_id is not set in payment_intent")? + .clone(); let business_profile = core_utils::validate_and_get_business_profile( db, + key_manager_state, + key_store, Some(profile_id).as_ref(), merchant_account.get_id(), ) @@ -4273,7 +4281,15 @@ pub async fn list_customer_payment_method( .to_not_found_response(errors::ApiErrorResponse::CustomerNotFound)?; let payments_info = payment_intent - .async_map(|pi| SavedPMLPaymentsInfo::form_payments_info(pi, &merchant_account, db)) + .async_map(|pi| { + SavedPMLPaymentsInfo::form_payments_info( + pi, + &merchant_account, + db, + key_manager_state, + &key_store, + ) + }) .await .transpose()?; diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs index 4f36782fb7..2b92cc3c7e 100644 --- a/crates/router/src/core/payments.rs +++ b/crates/router/src/core/payments.rs @@ -977,6 +977,8 @@ impl PaymentRedirectFlow for PaymentRedirectCompleteAuthorize { _connector: String, _payment_id: String, ) -> RouterResult { + let key_manager_state = &state.into(); + let payment_confirm_req = api::PaymentsRequest { payment_id: Some(req.resource_id.clone()), merchant_id: req.merchant_id.clone(), @@ -1000,7 +1002,7 @@ impl PaymentRedirectFlow for PaymentRedirectCompleteAuthorize { req_state, merchant_account, None, - merchant_key_store, + merchant_key_store.clone(), payment_complete_authorize::CompleteAuthorize, payment_confirm_req, services::api::AuthFlow::Merchant, @@ -1021,7 +1023,7 @@ impl PaymentRedirectFlow for PaymentRedirectCompleteAuthorize { .get_required_value("profile_id")?; let business_profile = state .store - .find_business_profile_by_profile_id(profile_id) + .find_business_profile_by_profile_id(key_manager_state, &merchant_key_store, profile_id) .await .to_not_found_response(errors::ApiErrorResponse::BusinessProfileNotFound { id: profile_id.to_string(), @@ -1111,6 +1113,8 @@ impl PaymentRedirectFlow for PaymentRedirectSync { _connector: String, _payment_id: String, ) -> RouterResult { + let key_manager_state = &state.into(); + let payment_sync_req = api::PaymentsRetrieveRequest { resource_id: req.resource_id, merchant_id: req.merchant_id, @@ -1132,7 +1136,7 @@ impl PaymentRedirectFlow for PaymentRedirectSync { req_state, merchant_account, None, - merchant_key_store, + merchant_key_store.clone(), PaymentStatus, payment_sync_req, services::api::AuthFlow::Merchant, @@ -1153,7 +1157,7 @@ impl PaymentRedirectFlow for PaymentRedirectSync { .get_required_value("profile_id")?; let business_profile = state .store - .find_business_profile_by_profile_id(profile_id) + .find_business_profile_by_profile_id(key_manager_state, &merchant_key_store, profile_id) .await .to_not_found_response(errors::ApiErrorResponse::BusinessProfileNotFound { id: profile_id.to_string(), @@ -1204,10 +1208,12 @@ impl PaymentRedirectFlow for PaymentAuthenticateCompleteAuthorize { payment_id: String, ) -> RouterResult { let merchant_id = merchant_account.get_id().clone(); + let key_manager_state = &state.into(); + let payment_intent = state .store .find_payment_intent_by_payment_id_merchant_id( - &state.into(), + key_manager_state, &payment_id, &merchant_id, &merchant_key_store, @@ -1290,7 +1296,7 @@ impl PaymentRedirectFlow for PaymentAuthenticateCompleteAuthorize { req_state, merchant_account, None, - merchant_key_store, + merchant_key_store.clone(), PaymentConfirm, payment_confirm_req, services::api::AuthFlow::Merchant, @@ -1321,7 +1327,7 @@ impl PaymentRedirectFlow for PaymentAuthenticateCompleteAuthorize { req_state, merchant_account.clone(), None, - merchant_key_store, + merchant_key_store.clone(), PaymentStatus, payment_sync_req, services::api::AuthFlow::Merchant, @@ -1382,7 +1388,7 @@ impl PaymentRedirectFlow for PaymentAuthenticateCompleteAuthorize { .get_required_value("profile_id")?; let business_profile = state .store - .find_business_profile_by_profile_id(profile_id) + .find_business_profile_by_profile_id(key_manager_state, &merchant_key_store, profile_id) .await .to_not_found_response(errors::ApiErrorResponse::BusinessProfileNotFound { id: profile_id.to_string(), @@ -1444,7 +1450,7 @@ pub async fn call_connector_service( schedule_time: Option, header_payload: HeaderPayload, frm_suggestion: Option, - business_profile: &storage::business_profile::BusinessProfile, + business_profile: &domain::BusinessProfile, is_retry_payment: bool, ) -> RouterResult<( RouterData, @@ -1810,7 +1816,7 @@ pub async fn call_multiple_connectors_service( mut payment_data: PaymentData, customer: &Option, session_surcharge_details: Option, - business_profile: &storage::business_profile::BusinessProfile, + business_profile: &domain::BusinessProfile, header_payload: HeaderPayload, ) -> RouterResult> where @@ -2501,7 +2507,7 @@ pub async fn get_connector_tokenization_action_when_confirm_true( merchant_connector_account: &helpers::MerchantConnectorAccountType, merchant_key_store: &domain::MerchantKeyStore, customer: &Option, - business_profile: Option<&diesel_models::business_profile::BusinessProfile>, + business_profile: Option<&domain::BusinessProfile>, ) -> RouterResult<(PaymentData, TokenizationAction)> where F: Send + Clone, @@ -2629,7 +2635,7 @@ pub async fn tokenize_in_router_when_confirm_false_or_external_authentication, - business_profile: Option<&diesel_models::business_profile::BusinessProfile>, + business_profile: Option<&domain::BusinessProfile>, ) -> RouterResult> where F: Send + Clone, @@ -3192,7 +3198,7 @@ pub async fn get_connector_choice( state: &SessionState, req: &Req, merchant_account: &domain::MerchantAccount, - business_profile: &storage::business_profile::BusinessProfile, + business_profile: &domain::BusinessProfile, key_store: &domain::MerchantKeyStore, payment_data: &mut PaymentData, eligible_connectors: Option>, @@ -3270,7 +3276,7 @@ where pub async fn connector_selection( state: &SessionState, merchant_account: &domain::MerchantAccount, - business_profile: &storage::business_profile::BusinessProfile, + business_profile: &domain::BusinessProfile, key_store: &domain::MerchantKeyStore, payment_data: &mut PaymentData, request_straight_through: Option, @@ -3338,7 +3344,7 @@ where pub async fn decide_connector( state: SessionState, merchant_account: &domain::MerchantAccount, - business_profile: &storage::business_profile::BusinessProfile, + business_profile: &domain::BusinessProfile, key_store: &domain::MerchantKeyStore, payment_data: &mut PaymentData, request_straight_through: Option, @@ -3903,7 +3909,7 @@ where pub async fn route_connector_v1( state: &SessionState, merchant_account: &domain::MerchantAccount, - business_profile: &storage::business_profile::BusinessProfile, + business_profile: &domain::BusinessProfile, key_store: &domain::MerchantKeyStore, transaction_data: TransactionData<'_, F>, routing_data: &mut storage::RoutingData, @@ -4007,12 +4013,14 @@ pub async fn payment_external_authentication( req: api_models::payments::PaymentsExternalAuthenticationRequest, ) -> RouterResponse { let db = &*state.store; + let key_manager_state = &(&state).into(); + let merchant_id = merchant_account.get_id(); let storage_scheme = merchant_account.storage_scheme; let payment_id = req.payment_id; let payment_intent = db .find_payment_intent_by_payment_id_merchant_id( - &(&state).into(), + key_manager_state, &payment_id, merchant_id, &key_store, @@ -4046,7 +4054,7 @@ pub async fn payment_external_authentication( state .store .find_customer_by_customer_id_merchant_id( - &(&state).into(), + key_manager_state, customer_id, merchant_account.get_id(), &key_store, @@ -4150,7 +4158,7 @@ pub async fn payment_external_authentication( let business_profile = state .store - .find_business_profile_by_profile_id(profile_id) + .find_business_profile_by_profile_id(key_manager_state, &key_store, profile_id) .await .change_context(errors::ApiErrorResponse::BusinessProfileNotFound { id: profile_id.to_string(), @@ -4277,7 +4285,7 @@ pub async fn payments_manual_update( let payment_intent = state .store .find_payment_intent_by_payment_id_merchant_id( - &(&state).into(), + key_manager_state, &payment_id, merchant_account.get_id(), &key_store, @@ -4333,7 +4341,7 @@ pub async fn payments_manual_update( state .store .update_payment_intent( - &(&state).into(), + key_manager_state, payment_intent, payment_intent_update, &key_store, diff --git a/crates/router/src/core/payments/flows.rs b/crates/router/src/core/payments/flows.rs index 72264c4eff..893cc957bb 100644 --- a/crates/router/src/core/payments/flows.rs +++ b/crates/router/src/core/payments/flows.rs @@ -21,7 +21,7 @@ use crate::{ }, routes::SessionState, services, - types::{self, api, domain, storage}, + types::{self, api, domain}, }; #[async_trait] @@ -57,7 +57,7 @@ pub trait Feature { connector: &api::ConnectorData, call_connector_action: payments::CallConnectorAction, connector_request: Option, - business_profile: &storage::business_profile::BusinessProfile, + business_profile: &domain::BusinessProfile, header_payload: api_models::payments::HeaderPayload, ) -> RouterResult where diff --git a/crates/router/src/core/payments/flows/approve_flow.rs b/crates/router/src/core/payments/flows/approve_flow.rs index 63224f5b0c..694b8d40fc 100644 --- a/crates/router/src/core/payments/flows/approve_flow.rs +++ b/crates/router/src/core/payments/flows/approve_flow.rs @@ -8,7 +8,7 @@ use crate::{ }, routes::SessionState, services, - types::{self, api, domain, storage}, + types::{self, api, domain}, }; #[async_trait] @@ -64,7 +64,7 @@ impl Feature _connector: &api::ConnectorData, _call_connector_action: payments::CallConnectorAction, _connector_request: Option, - _business_profile: &storage::business_profile::BusinessProfile, + _business_profile: &domain::BusinessProfile, _header_payload: api_models::payments::HeaderPayload, ) -> RouterResult { Err(ApiErrorResponse::NotImplemented { diff --git a/crates/router/src/core/payments/flows/authorize_flow.rs b/crates/router/src/core/payments/flows/authorize_flow.rs index db34c40d92..21f55cce31 100644 --- a/crates/router/src/core/payments/flows/authorize_flow.rs +++ b/crates/router/src/core/payments/flows/authorize_flow.rs @@ -16,7 +16,7 @@ use crate::{ routes::{metrics, SessionState}, services, services::api::ConnectorValidation, - types::{self, api, domain, storage, transformers::ForeignFrom}, + types::{self, api, domain, transformers::ForeignFrom}, utils::OptionExt, }; @@ -97,7 +97,7 @@ impl Feature for types::PaymentsAu connector: &api::ConnectorData, call_connector_action: payments::CallConnectorAction, connector_request: Option, - _business_profile: &storage::business_profile::BusinessProfile, + _business_profile: &domain::BusinessProfile, _header_payload: api_models::payments::HeaderPayload, ) -> RouterResult { let connector_integration: services::BoxedPaymentConnectorIntegrationInterface< diff --git a/crates/router/src/core/payments/flows/cancel_flow.rs b/crates/router/src/core/payments/flows/cancel_flow.rs index 486e8bb75d..488818021e 100644 --- a/crates/router/src/core/payments/flows/cancel_flow.rs +++ b/crates/router/src/core/payments/flows/cancel_flow.rs @@ -9,7 +9,7 @@ use crate::{ }, routes::{metrics, SessionState}, services, - types::{self, api, domain, storage}, + types::{self, api, domain}, }; #[async_trait] @@ -64,7 +64,7 @@ impl Feature connector: &api::ConnectorData, call_connector_action: payments::CallConnectorAction, connector_request: Option, - _business_profile: &storage::business_profile::BusinessProfile, + _business_profile: &domain::BusinessProfile, _header_payload: api_models::payments::HeaderPayload, ) -> RouterResult { metrics::PAYMENT_CANCEL_COUNT.add( diff --git a/crates/router/src/core/payments/flows/capture_flow.rs b/crates/router/src/core/payments/flows/capture_flow.rs index a7f30f2a41..c22f9e0b21 100644 --- a/crates/router/src/core/payments/flows/capture_flow.rs +++ b/crates/router/src/core/payments/flows/capture_flow.rs @@ -8,7 +8,7 @@ use crate::{ }, routes::SessionState, services, - types::{self, api, domain, storage}, + types::{self, api, domain}, }; #[async_trait] @@ -64,7 +64,7 @@ impl Feature connector: &api::ConnectorData, call_connector_action: payments::CallConnectorAction, connector_request: Option, - _business_profile: &storage::business_profile::BusinessProfile, + _business_profile: &domain::BusinessProfile, _header_payload: api_models::payments::HeaderPayload, ) -> RouterResult { let connector_integration: services::BoxedPaymentConnectorIntegrationInterface< diff --git a/crates/router/src/core/payments/flows/complete_authorize_flow.rs b/crates/router/src/core/payments/flows/complete_authorize_flow.rs index d3ae67f46c..bd7307eb4c 100644 --- a/crates/router/src/core/payments/flows/complete_authorize_flow.rs +++ b/crates/router/src/core/payments/flows/complete_authorize_flow.rs @@ -9,7 +9,7 @@ use crate::{ }, routes::{metrics, SessionState}, services, - types::{self, api, domain, storage}, + types::{self, api, domain}, }; #[async_trait] @@ -78,7 +78,7 @@ impl Feature connector: &api::ConnectorData, call_connector_action: payments::CallConnectorAction, connector_request: Option, - _business_profile: &storage::business_profile::BusinessProfile, + _business_profile: &domain::BusinessProfile, _header_payload: api_models::payments::HeaderPayload, ) -> RouterResult { let connector_integration: services::BoxedPaymentConnectorIntegrationInterface< diff --git a/crates/router/src/core/payments/flows/incremental_authorization_flow.rs b/crates/router/src/core/payments/flows/incremental_authorization_flow.rs index 3bc05cedb4..8cdb07d390 100644 --- a/crates/router/src/core/payments/flows/incremental_authorization_flow.rs +++ b/crates/router/src/core/payments/flows/incremental_authorization_flow.rs @@ -8,7 +8,7 @@ use crate::{ }, routes::SessionState, services, - types::{self, api, domain, storage}, + types::{self, api, domain}, }; #[async_trait] @@ -71,7 +71,7 @@ impl Feature, - _business_profile: &storage::business_profile::BusinessProfile, + _business_profile: &domain::BusinessProfile, _header_payload: api_models::payments::HeaderPayload, ) -> RouterResult { let connector_integration: services::BoxedPaymentConnectorIntegrationInterface< diff --git a/crates/router/src/core/payments/flows/psync_flow.rs b/crates/router/src/core/payments/flows/psync_flow.rs index ab53aee86d..f862fd5711 100644 --- a/crates/router/src/core/payments/flows/psync_flow.rs +++ b/crates/router/src/core/payments/flows/psync_flow.rs @@ -11,7 +11,7 @@ use crate::{ }, routes::SessionState, services::{self, api::ConnectorValidation, logger}, - types::{self, api, domain, storage}, + types::{self, api, domain}, }; #[async_trait] impl ConstructFlowSpecificData @@ -67,7 +67,7 @@ impl Feature connector: &api::ConnectorData, call_connector_action: payments::CallConnectorAction, connector_request: Option, - _business_profile: &storage::business_profile::BusinessProfile, + _business_profile: &domain::BusinessProfile, _header_payload: api_models::payments::HeaderPayload, ) -> RouterResult { let connector_integration: services::BoxedPaymentConnectorIntegrationInterface< diff --git a/crates/router/src/core/payments/flows/reject_flow.rs b/crates/router/src/core/payments/flows/reject_flow.rs index 501c0a40da..f54b8d14dd 100644 --- a/crates/router/src/core/payments/flows/reject_flow.rs +++ b/crates/router/src/core/payments/flows/reject_flow.rs @@ -8,7 +8,7 @@ use crate::{ }, routes::SessionState, services, - types::{self, api, domain, storage}, + types::{self, api, domain}, }; #[async_trait] @@ -63,7 +63,7 @@ impl Feature _connector: &api::ConnectorData, _call_connector_action: payments::CallConnectorAction, _connector_request: Option, - _business_profile: &storage::business_profile::BusinessProfile, + _business_profile: &domain::BusinessProfile, _header_payload: api_models::payments::HeaderPayload, ) -> RouterResult { Err(ApiErrorResponse::NotImplemented { diff --git a/crates/router/src/core/payments/flows/session_flow.rs b/crates/router/src/core/payments/flows/session_flow.rs index 4441e349d9..cdd8452fdb 100644 --- a/crates/router/src/core/payments/flows/session_flow.rs +++ b/crates/router/src/core/payments/flows/session_flow.rs @@ -21,7 +21,7 @@ use crate::{ types::{ self, api::{self, enums}, - domain, storage, + domain, }, utils::OptionExt, }; @@ -77,7 +77,7 @@ impl Feature for types::PaymentsSessio connector: &api::ConnectorData, call_connector_action: payments::CallConnectorAction, _connector_request: Option, - business_profile: &storage::business_profile::BusinessProfile, + business_profile: &domain::BusinessProfile, header_payload: api_models::payments::HeaderPayload, ) -> RouterResult { metrics::SESSION_TOKEN_CREATED.add( @@ -169,7 +169,7 @@ async fn create_applepay_session_token( state: &routes::SessionState, router_data: &types::PaymentsSessionRouterData, connector: &api::ConnectorData, - business_profile: &storage::business_profile::BusinessProfile, + business_profile: &domain::BusinessProfile, header_payload: api_models::payments::HeaderPayload, ) -> RouterResult { let delayed_response = is_session_response_delayed(state, connector); @@ -621,7 +621,7 @@ fn create_gpay_session_token( state: &routes::SessionState, router_data: &types::PaymentsSessionRouterData, connector: &api::ConnectorData, - business_profile: &storage::business_profile::BusinessProfile, + business_profile: &domain::BusinessProfile, ) -> RouterResult { let connector_metadata = router_data.connector_meta_data.clone(); let delayed_response = is_session_response_delayed(state, connector); @@ -792,7 +792,7 @@ where connector: &api::ConnectorData, _confirm: Option, call_connector_action: payments::CallConnectorAction, - business_profile: &storage::business_profile::BusinessProfile, + business_profile: &domain::BusinessProfile, header_payload: api_models::payments::HeaderPayload, ) -> RouterResult; } @@ -801,7 +801,7 @@ fn create_paypal_sdk_session_token( _state: &routes::SessionState, router_data: &types::PaymentsSessionRouterData, connector: &api::ConnectorData, - _business_profile: &storage::business_profile::BusinessProfile, + _business_profile: &domain::BusinessProfile, ) -> RouterResult { let connector_metadata = router_data.connector_meta_data.clone(); @@ -841,7 +841,7 @@ impl RouterDataSession for types::PaymentsSessionRouterData { connector: &api::ConnectorData, _confirm: Option, call_connector_action: payments::CallConnectorAction, - business_profile: &storage::business_profile::BusinessProfile, + business_profile: &domain::BusinessProfile, header_payload: api_models::payments::HeaderPayload, ) -> RouterResult { match connector.get_token { diff --git a/crates/router/src/core/payments/flows/setup_mandate_flow.rs b/crates/router/src/core/payments/flows/setup_mandate_flow.rs index 0d4648b81f..fb7719725f 100644 --- a/crates/router/src/core/payments/flows/setup_mandate_flow.rs +++ b/crates/router/src/core/payments/flows/setup_mandate_flow.rs @@ -12,7 +12,7 @@ use crate::{ }, routes::SessionState, services, - types::{self, api, domain, storage}, + types::{self, api, domain}, }; #[async_trait] @@ -69,7 +69,7 @@ impl Feature for types::Setup connector: &api::ConnectorData, call_connector_action: payments::CallConnectorAction, connector_request: Option, - _business_profile: &storage::business_profile::BusinessProfile, + _business_profile: &domain::BusinessProfile, _header_payload: api_models::payments::HeaderPayload, ) -> RouterResult { let connector_integration: services::BoxedPaymentConnectorIntegrationInterface< diff --git a/crates/router/src/core/payments/helpers.rs b/crates/router/src/core/payments/helpers.rs index 1563e3734f..91b7a5fc3f 100644 --- a/crates/router/src/core/payments/helpers.rs +++ b/crates/router/src/core/payments/helpers.rs @@ -2006,7 +2006,7 @@ pub async fn make_pm_data<'a, F: Clone, R>( merchant_key_store: &domain::MerchantKeyStore, customer: &Option, storage_scheme: common_enums::enums::MerchantStorageScheme, - business_profile: Option<&diesel_models::business_profile::BusinessProfile>, + business_profile: Option<&domain::BusinessProfile>, ) -> RouterResult<( BoxedOperation<'a, F, R>, Option, @@ -2106,7 +2106,7 @@ pub async fn store_in_vault_and_generate_ppmt( payment_attempt: &PaymentAttempt, payment_method: enums::PaymentMethod, merchant_key_store: &domain::MerchantKeyStore, - business_profile: Option<&diesel_models::business_profile::BusinessProfile>, + business_profile: Option<&domain::BusinessProfile>, ) -> RouterResult { let router_token = vault::Vault::store_payment_method_data_in_locker( state, @@ -2148,7 +2148,7 @@ pub async fn store_payment_method_data_in_vault( payment_method: enums::PaymentMethod, payment_method_data: &api::PaymentMethodData, merchant_key_store: &domain::MerchantKeyStore, - business_profile: Option<&diesel_models::business_profile::BusinessProfile>, + business_profile: Option<&domain::BusinessProfile>, ) -> RouterResult> { if should_store_payment_method_data_in_vault( &state.conf.temp_locker_enable_config, @@ -2566,7 +2566,7 @@ pub(super) fn validate_payment_list_request_for_joins( pub fn get_handle_response_url( payment_id: String, - business_profile: &diesel_models::business_profile::BusinessProfile, + business_profile: &domain::BusinessProfile, response: &api::PaymentsResponse, connector: String, ) -> RouterResult { @@ -2587,7 +2587,7 @@ pub fn get_handle_response_url( } pub fn make_merchant_url_with_response( - business_profile: &diesel_models::business_profile::BusinessProfile, + business_profile: &domain::BusinessProfile, redirection_response: api::PgRedirectResponse, request_return_url: Option<&String>, client_secret: Option<&masking::Secret>, @@ -2696,7 +2696,7 @@ pub fn make_pg_redirect_response( pub fn make_url_with_signature( redirect_url: &str, - business_profile: &diesel_models::business_profile::BusinessProfile, + business_profile: &domain::BusinessProfile, ) -> RouterResult { let mut url = url::Url::parse(redirect_url) .change_context(errors::ApiErrorResponse::InternalServerError) @@ -4979,7 +4979,7 @@ pub enum PaymentExternalAuthenticationFlow { pub async fn get_payment_external_authentication_flow_during_confirm( state: &SessionState, key_store: &domain::MerchantKeyStore, - business_profile: &storage::BusinessProfile, + business_profile: &domain::BusinessProfile, payment_data: &mut PaymentData, connector_call_type: &api::ConnectorCallType, ) -> RouterResult> { diff --git a/crates/router/src/core/payments/operations.rs b/crates/router/src/core/payments/operations.rs index fc2ab1c110..cd932fd54a 100644 --- a/crates/router/src/core/payments/operations.rs +++ b/crates/router/src/core/payments/operations.rs @@ -92,7 +92,7 @@ pub struct GetTrackerResponse<'a, F: Clone, R> { pub operation: BoxedOperation<'a, F, R>, pub customer_details: Option, pub payment_data: PaymentData, - pub business_profile: storage::business_profile::BusinessProfile, + pub business_profile: domain::BusinessProfile, pub mandate_type: Option, } @@ -131,7 +131,7 @@ pub trait Domain: Send + Sync { storage_scheme: enums::MerchantStorageScheme, merchant_key_store: &domain::MerchantKeyStore, customer: &Option, - business_profile: Option<&diesel_models::business_profile::BusinessProfile>, + business_profile: Option<&domain::BusinessProfile>, ) -> RouterResult<( BoxedOperation<'a, F, R>, Option, @@ -172,7 +172,7 @@ pub trait Domain: Send + Sync { _payment_data: &mut PaymentData, _should_continue_confirm_transaction: &mut bool, _connector_call_type: &ConnectorCallType, - _merchant_account: &storage::BusinessProfile, + _merchant_account: &domain::BusinessProfile, _key_store: &domain::MerchantKeyStore, ) -> CustomResult<(), errors::ApiErrorResponse> { Ok(()) @@ -193,7 +193,7 @@ pub trait Domain: Send + Sync { &'a self, _state: &SessionState, _payment_id: &str, - _business_profile: &storage::BusinessProfile, + _business_profile: &domain::BusinessProfile, _payment_method_data: &Option, ) -> CustomResult<(), errors::ApiErrorResponse> { Ok(()) @@ -240,7 +240,7 @@ pub trait PostUpdateTracker: Send { _merchant_account: &domain::MerchantAccount, _key_store: &domain::MerchantKeyStore, _payment_data: &mut PaymentData, - _business_profile: &storage::business_profile::BusinessProfile, + _business_profile: &domain::BusinessProfile, ) -> CustomResult<(), errors::ApiErrorResponse> where F: 'b + Clone + Send + Sync, @@ -303,7 +303,7 @@ where _storage_scheme: enums::MerchantStorageScheme, _merchant_key_store: &domain::MerchantKeyStore, _customer: &Option, - _business_profile: Option<&diesel_models::business_profile::BusinessProfile>, + _business_profile: Option<&domain::BusinessProfile>, ) -> RouterResult<( BoxedOperation<'a, F, api::PaymentsRetrieveRequest>, Option, @@ -366,7 +366,7 @@ where _storage_scheme: enums::MerchantStorageScheme, _merchant_key_store: &domain::MerchantKeyStore, _customer: &Option, - _business_profile: Option<&diesel_models::business_profile::BusinessProfile>, + _business_profile: Option<&domain::BusinessProfile>, ) -> RouterResult<( BoxedOperation<'a, F, api::PaymentsCaptureRequest>, Option, @@ -441,7 +441,7 @@ where _storage_scheme: enums::MerchantStorageScheme, _merchant_key_store: &domain::MerchantKeyStore, _customer: &Option, - _business_profile: Option<&diesel_models::business_profile::BusinessProfile>, + _business_profile: Option<&domain::BusinessProfile>, ) -> RouterResult<( BoxedOperation<'a, F, api::PaymentsCancelRequest>, Option, @@ -505,7 +505,7 @@ where _storage_scheme: enums::MerchantStorageScheme, _merchant_key_store: &domain::MerchantKeyStore, _customer: &Option, - _business_profile: Option<&diesel_models::business_profile::BusinessProfile>, + _business_profile: Option<&domain::BusinessProfile>, ) -> RouterResult<( BoxedOperation<'a, F, api::PaymentsRejectRequest>, Option, diff --git a/crates/router/src/core/payments/operations/payment_approve.rs b/crates/router/src/core/payments/operations/payment_approve.rs index 15560b2d6f..401e1c2c7a 100644 --- a/crates/router/src/core/payments/operations/payment_approve.rs +++ b/crates/router/src/core/payments/operations/payment_approve.rs @@ -43,6 +43,7 @@ impl GetTracker, api::PaymentsCaptureRequest> _header_payload: &api::HeaderPayload, ) -> RouterResult> { let db = &*state.store; + let key_manager_state = &state.into(); let merchant_id = merchant_account.get_id(); let storage_scheme = merchant_account.storage_scheme; let (mut payment_intent, payment_attempt, currency, amount); @@ -53,7 +54,7 @@ impl GetTracker, api::PaymentsCaptureRequest> payment_intent = db .find_payment_intent_by_payment_id_merchant_id( - &state.into(), + key_manager_state, &payment_id, merchant_id, key_store, @@ -77,7 +78,7 @@ impl GetTracker, api::PaymentsCaptureRequest> let business_profile = state .store - .find_business_profile_by_profile_id(profile_id) + .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(), diff --git a/crates/router/src/core/payments/operations/payment_cancel.rs b/crates/router/src/core/payments/operations/payment_cancel.rs index 2e9f070140..84eaf97bfa 100644 --- a/crates/router/src/core/payments/operations/payment_cancel.rs +++ b/crates/router/src/core/payments/operations/payment_cancel.rs @@ -43,6 +43,8 @@ impl GetTracker, api::PaymentsCancelRequest> _header_payload: &api::HeaderPayload, ) -> RouterResult> { let db = &*state.store; + let key_manager_state = &state.into(); + let merchant_id = merchant_account.get_id(); let storage_scheme = merchant_account.storage_scheme; let payment_id = payment_id @@ -51,7 +53,7 @@ impl GetTracker, api::PaymentsCancelRequest> let payment_intent = db .find_payment_intent_by_payment_id_merchant_id( - &state.into(), + key_manager_state, &payment_id, merchant_id, key_store, @@ -145,7 +147,7 @@ impl GetTracker, api::PaymentsCancelRequest> .attach_printable("'profile_id' not set in payment intent")?; let business_profile = db - .find_business_profile_by_profile_id(profile_id) + .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(), diff --git a/crates/router/src/core/payments/operations/payment_capture.rs b/crates/router/src/core/payments/operations/payment_capture.rs index d0e8e0605c..0d096e1d3a 100644 --- a/crates/router/src/core/payments/operations/payment_capture.rs +++ b/crates/router/src/core/payments/operations/payment_capture.rs @@ -44,6 +44,8 @@ impl GetTracker, api::PaymentsCaptu _header_payload: &api::HeaderPayload, ) -> RouterResult> { let db = &*state.store; + let key_manager_state = &state.into(); + let merchant_id = merchant_account.get_id(); let storage_scheme = merchant_account.storage_scheme; let (payment_intent, mut payment_attempt, currency, amount); @@ -54,7 +56,7 @@ impl GetTracker, api::PaymentsCaptu payment_intent = db .find_payment_intent_by_payment_id_merchant_id( - &state.into(), + key_manager_state, &payment_id, merchant_id, key_store, @@ -191,7 +193,7 @@ impl GetTracker, api::PaymentsCaptu .attach_printable("'profile_id' not set in payment intent")?; let business_profile = db - .find_business_profile_by_profile_id(profile_id) + .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(), 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 5e2b9e7552..598c2216fb 100644 --- a/crates/router/src/core/payments/operations/payment_complete_authorize.rs +++ b/crates/router/src/core/payments/operations/payment_complete_authorize.rs @@ -45,6 +45,8 @@ impl GetTracker, api::PaymentsRequest> for Co _header_payload: &api::HeaderPayload, ) -> RouterResult> { let db = &*state.store; + let key_manager_state = &state.into(); + let merchant_id = merchant_account.get_id(); let storage_scheme = merchant_account.storage_scheme; let (mut payment_intent, mut payment_attempt, currency, amount); @@ -55,7 +57,7 @@ impl GetTracker, api::PaymentsRequest> for Co payment_intent = db .find_payment_intent_by_payment_id_merchant_id( - &state.into(), + key_manager_state, &payment_id, merchant_id, key_store, @@ -285,7 +287,7 @@ impl GetTracker, api::PaymentsRequest> for Co .attach_printable("'profile_id' not set in payment intent")?; let business_profile = db - .find_business_profile_by_profile_id(profile_id) + .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(), @@ -396,7 +398,7 @@ impl Domain for CompleteAuthorize { storage_scheme: storage_enums::MerchantStorageScheme, merchant_key_store: &domain::MerchantKeyStore, customer: &Option, - business_profile: Option<&diesel_models::business_profile::BusinessProfile>, + business_profile: Option<&domain::BusinessProfile>, ) -> RouterResult<( BoxedOperation<'a, F, api::PaymentsRequest>, Option, diff --git a/crates/router/src/core/payments/operations/payment_confirm.rs b/crates/router/src/core/payments/operations/payment_confirm.rs index 10aad010d1..747be6a5ca 100644 --- a/crates/router/src/core/payments/operations/payment_confirm.rs +++ b/crates/router/src/core/payments/operations/payment_confirm.rs @@ -65,6 +65,8 @@ impl GetTracker, api::PaymentsRequest> for Pa auth_flow: services::AuthFlow, header_payload: &api::HeaderPayload, ) -> RouterResult> { + let key_manager_state = &state.into(); + let merchant_id = merchant_account.get_id(); let storage_scheme = merchant_account.storage_scheme; let (currency, amount); @@ -80,7 +82,7 @@ impl GetTracker, api::PaymentsRequest> for Pa // Parallel calls - level 0 let mut payment_intent = store .find_payment_intent_by_payment_id_merchant_id( - &state.into(), + key_manager_state, &payment_id, &m_merchant_id, key_store, @@ -145,11 +147,17 @@ impl GetTracker, api::PaymentsRequest> for Pa .attach_printable("'profile_id' not set in payment intent")?; let store = state.store.clone(); + let key_manager_state_clone = key_manager_state.clone(); + let key_store_clone = key_store.clone(); let business_profile_fut = tokio::spawn( async move { store - .find_business_profile_by_profile_id(&profile_id) + .find_business_profile_by_profile_id( + &key_manager_state_clone, + &key_store_clone, + &profile_id, + ) .map(|business_profile_result| { business_profile_result.to_not_found_response( errors::ApiErrorResponse::BusinessProfileNotFound { @@ -726,7 +734,7 @@ impl Domain for PaymentConfirm { storage_scheme: storage_enums::MerchantStorageScheme, key_store: &domain::MerchantKeyStore, customer: &Option, - business_profile: Option<&diesel_models::business_profile::BusinessProfile>, + business_profile: Option<&domain::BusinessProfile>, ) -> RouterResult<( BoxedOperation<'a, F, api::PaymentsRequest>, Option, @@ -810,7 +818,7 @@ impl Domain for PaymentConfirm { payment_data: &mut PaymentData, should_continue_confirm_transaction: &mut bool, connector_call_type: &ConnectorCallType, - business_profile: &storage::BusinessProfile, + business_profile: &domain::BusinessProfile, key_store: &domain::MerchantKeyStore, ) -> CustomResult<(), errors::ApiErrorResponse> { let external_authentication_flow = @@ -912,7 +920,7 @@ impl Domain for PaymentConfirm { &'a self, state: &SessionState, payment_id: &str, - business_profile: &storage::BusinessProfile, + business_profile: &domain::BusinessProfile, payment_method_data: &Option, ) -> CustomResult<(), errors::ApiErrorResponse> { if let (Some(true), Some(api::PaymentMethodData::Card(card)), Some(merchant_config)) = ( diff --git a/crates/router/src/core/payments/operations/payment_create.rs b/crates/router/src/core/payments/operations/payment_create.rs index 9f5035de79..160e3d080f 100644 --- a/crates/router/src/core/payments/operations/payment_create.rs +++ b/crates/router/src/core/payments/operations/payment_create.rs @@ -70,6 +70,7 @@ impl GetTracker, api::PaymentsRequest> for Pa header_payload: &api::HeaderPayload, ) -> RouterResult> { let db = &*state.store; + let key_manager_state = &state.into(); let ephemeral_key = Self::get_ephemeral_key(request, state, merchant_account).await; let merchant_id = merchant_account.get_id(); let storage_scheme = merchant_account.storage_scheme; @@ -97,6 +98,8 @@ impl GetTracker, api::PaymentsRequest> for Pa not(feature = "merchant_account_v2") ))] let profile_id = core_utils::get_profile_id_from_business_details( + key_manager_state, + merchant_key_store, request.business_country, request.business_label.as_ref(), merchant_account, @@ -117,16 +120,28 @@ impl GetTracker, api::PaymentsRequest> for Pa // TODO: eliminate a redundant db call to fetch the business profile // Validate whether profile_id passed in request is valid and is linked to the merchant let business_profile = if let Some(business_profile) = - core_utils::validate_and_get_business_profile(db, Some(&profile_id), merchant_id) - .await? + core_utils::validate_and_get_business_profile( + db, + key_manager_state, + merchant_key_store, + Some(&profile_id), + merchant_id, + ) + .await? { business_profile } else { - db.find_business_profile_by_profile_id(&profile_id) - .await - .to_not_found_response(errors::ApiErrorResponse::BusinessProfileNotFound { + db.find_business_profile_by_profile_id( + key_manager_state, + merchant_key_store, + &profile_id, + ) + .await + .to_not_found_response( + errors::ApiErrorResponse::BusinessProfileNotFound { id: profile_id.to_string(), - })? + }, + )? }; let customer_acceptance = request.customer_acceptance.clone().map(From::from); @@ -535,7 +550,7 @@ impl Domain for PaymentCreate { storage_scheme: enums::MerchantStorageScheme, merchant_key_store: &domain::MerchantKeyStore, customer: &Option, - business_profile: Option<&diesel_models::business_profile::BusinessProfile>, + business_profile: Option<&domain::BusinessProfile>, ) -> RouterResult<( BoxedOperation<'a, F, api::PaymentsRequest>, Option, diff --git a/crates/router/src/core/payments/operations/payment_reject.rs b/crates/router/src/core/payments/operations/payment_reject.rs index c8da548916..a5d0b95a67 100644 --- a/crates/router/src/core/payments/operations/payment_reject.rs +++ b/crates/router/src/core/payments/operations/payment_reject.rs @@ -40,6 +40,8 @@ impl GetTracker, PaymentsCancelRequest> for P _header_payload: &api::HeaderPayload, ) -> RouterResult> { let db = &*state.store; + let key_manager_state = &state.into(); + let merchant_id = merchant_account.get_id(); let storage_scheme = merchant_account.storage_scheme; let payment_id = payment_id @@ -48,7 +50,7 @@ impl GetTracker, PaymentsCancelRequest> for P let payment_intent = db .find_payment_intent_by_payment_id_merchant_id( - &state.into(), + key_manager_state, &payment_id, merchant_id, key_store, @@ -129,7 +131,7 @@ impl GetTracker, PaymentsCancelRequest> for P let business_profile = state .store - .find_business_profile_by_profile_id(profile_id) + .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(), diff --git a/crates/router/src/core/payments/operations/payment_response.rs b/crates/router/src/core/payments/operations/payment_response.rs index d7cebc7d9e..fee90d8c42 100644 --- a/crates/router/src/core/payments/operations/payment_response.rs +++ b/crates/router/src/core/payments/operations/payment_response.rs @@ -92,7 +92,7 @@ impl PostUpdateTracker, types::PaymentsAuthor merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, payment_data: &mut PaymentData, - business_profile: &storage::business_profile::BusinessProfile, + business_profile: &domain::BusinessProfile, ) -> CustomResult<(), errors::ApiErrorResponse> where F: 'b + Clone + Send + Sync, @@ -431,7 +431,7 @@ impl PostUpdateTracker, types::PaymentsSyncData> for merchant_account: &domain::MerchantAccount, _key_store: &domain::MerchantKeyStore, payment_data: &mut PaymentData, - business_profile: &storage::business_profile::BusinessProfile, + business_profile: &domain::BusinessProfile, ) -> CustomResult<(), errors::ApiErrorResponse> where F: 'b + Clone + Send + Sync, @@ -640,7 +640,7 @@ impl PostUpdateTracker, types::SetupMandateRequestDa merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, payment_data: &mut PaymentData, - business_profile: &storage::business_profile::BusinessProfile, + business_profile: &domain::BusinessProfile, ) -> CustomResult<(), errors::ApiErrorResponse> where F: 'b + Clone + Send + Sync, @@ -731,7 +731,7 @@ impl PostUpdateTracker, types::CompleteAuthorizeData merchant_account: &domain::MerchantAccount, _key_store: &domain::MerchantKeyStore, payment_data: &mut PaymentData, - business_profile: &storage::business_profile::BusinessProfile, + business_profile: &domain::BusinessProfile, ) -> CustomResult<(), errors::ApiErrorResponse> where F: 'b + Clone + Send + Sync, diff --git a/crates/router/src/core/payments/operations/payment_session.rs b/crates/router/src/core/payments/operations/payment_session.rs index 479ae21092..cae11d7afd 100644 --- a/crates/router/src/core/payments/operations/payment_session.rs +++ b/crates/router/src/core/payments/operations/payment_session.rs @@ -47,6 +47,7 @@ impl GetTracker, api::PaymentsSessionRequest> .change_context(errors::ApiErrorResponse::PaymentNotFound)?; let db = &*state.store; + let key_manager_state = &state.into(); let merchant_id = merchant_account.get_id(); let storage_scheme = merchant_account.storage_scheme; @@ -155,7 +156,7 @@ impl GetTracker, api::PaymentsSessionRequest> .attach_printable("'profile_id' not set in payment intent")?; let business_profile = db - .find_business_profile_by_profile_id(profile_id) + .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(), @@ -328,7 +329,7 @@ where _storage_scheme: storage_enums::MerchantStorageScheme, _merchant_key_store: &domain::MerchantKeyStore, _customer: &Option, - _business_profile: Option<&diesel_models::business_profile::BusinessProfile>, + _business_profile: Option<&domain::BusinessProfile>, ) -> RouterResult<( BoxedOperation<'b, F, api::PaymentsSessionRequest>, Option, diff --git a/crates/router/src/core/payments/operations/payment_start.rs b/crates/router/src/core/payments/operations/payment_start.rs index 728b7b538a..c500336efd 100644 --- a/crates/router/src/core/payments/operations/payment_start.rs +++ b/crates/router/src/core/payments/operations/payment_start.rs @@ -41,6 +41,7 @@ impl GetTracker, api::PaymentsStartRequest> f ) -> RouterResult> { let (mut payment_intent, payment_attempt, currency, amount); let db = &*state.store; + let key_manager_state = &state.into(); let merchant_id = merchant_account.get_id(); let storage_scheme = merchant_account.storage_scheme; @@ -50,7 +51,7 @@ impl GetTracker, api::PaymentsStartRequest> f payment_intent = db .find_payment_intent_by_payment_id_merchant_id( - &state.into(), + key_manager_state, &payment_id, merchant_id, key_store, @@ -140,7 +141,7 @@ impl GetTracker, api::PaymentsStartRequest> f .attach_printable("'profile_id' not set in payment intent")?; let business_profile = db - .find_business_profile_by_profile_id(profile_id) + .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(), @@ -300,7 +301,7 @@ where storage_scheme: storage_enums::MerchantStorageScheme, merchant_key_store: &domain::MerchantKeyStore, customer: &Option, - business_profile: Option<&diesel_models::business_profile::BusinessProfile>, + business_profile: Option<&domain::BusinessProfile>, ) -> RouterResult<( BoxedOperation<'a, F, api::PaymentsStartRequest>, Option, diff --git a/crates/router/src/core/payments/operations/payment_status.rs b/crates/router/src/core/payments/operations/payment_status.rs index 44a08e9163..84abf71d07 100644 --- a/crates/router/src/core/payments/operations/payment_status.rs +++ b/crates/router/src/core/payments/operations/payment_status.rs @@ -89,7 +89,7 @@ impl Domain for PaymentStatus { _storage_scheme: enums::MerchantStorageScheme, _merchant_key_store: &domain::MerchantKeyStore, _customer: &Option, - _business_profile: Option<&diesel_models::business_profile::BusinessProfile>, + _business_profile: Option<&domain::BusinessProfile>, ) -> RouterResult<( BoxedOperation<'a, F, api::PaymentsRequest>, Option, @@ -267,6 +267,7 @@ async fn get_tracker_for_sync< payment_attempt.encoded_data.clone_from(&request.param); let db = &*state.store; + let key_manager_state = &state.into(); let attempts = match request.expand_attempts { Some(true) => { Some(db @@ -372,7 +373,7 @@ async fn get_tracker_for_sync< .attach_printable("'profile_id' not set in payment intent")?; let business_profile = db - .find_business_profile_by_profile_id(profile_id) + .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(), diff --git a/crates/router/src/core/payments/operations/payment_update.rs b/crates/router/src/core/payments/operations/payment_update.rs index e73d2ef6be..8ead378362 100644 --- a/crates/router/src/core/payments/operations/payment_update.rs +++ b/crates/router/src/core/payments/operations/payment_update.rs @@ -61,10 +61,11 @@ impl GetTracker, api::PaymentsRequest> for Pa let storage_scheme = merchant_account.storage_scheme; let db = &*state.store; + let key_manager_state = &state.into(); payment_intent = db .find_payment_intent_by_payment_id_merchant_id( - &state.into(), + key_manager_state, &payment_id, merchant_id, key_store, @@ -417,7 +418,7 @@ impl GetTracker, api::PaymentsRequest> for Pa .attach_printable("'profile_id' not set in payment intent")?; let business_profile = db - .find_business_profile_by_profile_id(profile_id) + .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(), @@ -524,7 +525,7 @@ impl Domain for PaymentUpdate { storage_scheme: storage_enums::MerchantStorageScheme, merchant_key_store: &domain::MerchantKeyStore, customer: &Option, - business_profile: Option<&diesel_models::business_profile::BusinessProfile>, + business_profile: Option<&domain::BusinessProfile>, ) -> RouterResult<( BoxedOperation<'a, F, api::PaymentsRequest>, Option, 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 996e30e31f..f027b7e0a9 100644 --- a/crates/router/src/core/payments/operations/payments_incremental_authorization.rs +++ b/crates/router/src/core/payments/operations/payments_incremental_authorization.rs @@ -48,6 +48,8 @@ impl ) -> RouterResult> { let db = &*state.store; + let key_manager_state = &state.into(); + let merchant_id = merchant_account.get_id(); let storage_scheme = merchant_account.storage_scheme; let payment_id = payment_id @@ -107,7 +109,7 @@ impl let business_profile = state .store - .find_business_profile_by_profile_id(profile_id) + .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(), @@ -317,7 +319,7 @@ impl Domain _storage_scheme: enums::MerchantStorageScheme, _merchant_key_store: &domain::MerchantKeyStore, _customer: &Option, - _business_profile: Option<&diesel_models::business_profile::BusinessProfile>, + _business_profile: Option<&domain::BusinessProfile>, ) -> RouterResult<( BoxedOperation<'a, F, PaymentsIncrementalAuthorizationRequest>, Option, diff --git a/crates/router/src/core/payments/retry.rs b/crates/router/src/core/payments/retry.rs index 29512c2139..e67f30a2f7 100644 --- a/crates/router/src/core/payments/retry.rs +++ b/crates/router/src/core/payments/retry.rs @@ -44,7 +44,7 @@ pub async fn do_gsm_actions( validate_result: &operations::ValidateResult, schedule_time: Option, frm_suggestion: Option, - business_profile: &storage::business_profile::BusinessProfile, + business_profile: &domain::BusinessProfile, ) -> RouterResult> where F: Clone + Send + Sync, @@ -283,7 +283,7 @@ pub async fn do_retry( schedule_time: Option, is_step_up: bool, frm_suggestion: Option, - business_profile: &storage::business_profile::BusinessProfile, + business_profile: &domain::BusinessProfile, ) -> RouterResult> where F: Clone + Send + Sync, diff --git a/crates/router/src/core/payments/routing.rs b/crates/router/src/core/payments/routing.rs index a0b98b02cb..455fa4cea5 100644 --- a/crates/router/src/core/payments/routing.rs +++ b/crates/router/src/core/payments/routing.rs @@ -801,7 +801,11 @@ pub async fn perform_session_flow_routing( let business_profile = session_input .state .store - .find_business_profile_by_profile_id(&profile_id) + .find_business_profile_by_profile_id( + &session_input.state.into(), + session_input.key_store, + &profile_id, + ) .await .change_context(errors::RoutingError::ProfileNotFound)?; diff --git a/crates/router/src/core/payments/tokenization.rs b/crates/router/src/core/payments/tokenization.rs index ecbfbf03a6..e9ebeafafd 100644 --- a/crates/router/src/core/payments/tokenization.rs +++ b/crates/router/src/core/payments/tokenization.rs @@ -69,7 +69,7 @@ pub async fn save_payment_method( currency: Option, billing_name: Option>, payment_method_billing_address: Option<&api::Address>, - business_profile: &storage::business_profile::BusinessProfile, + business_profile: &domain::BusinessProfile, ) -> RouterResult<(Option, Option)> where FData: mandate::MandateBehaviour + Clone, diff --git a/crates/router/src/core/payments/types.rs b/crates/router/src/core/payments/types.rs index 71460a1119..3775c8b4e2 100644 --- a/crates/router/src/core/payments/types.rs +++ b/crates/router/src/core/payments/types.rs @@ -6,7 +6,6 @@ use common_utils::{ ext_traits::{Encode, OptionExt}, types as common_types, }; -use diesel_models::business_profile::BusinessProfile; use error_stack::ResultExt; use hyperswitch_domain_models::payments::payment_attempt::PaymentAttempt; pub use hyperswitch_domain_models::router_request_types::{ @@ -20,6 +19,7 @@ use crate::{ core::errors::{self, RouterResult}, routes::SessionState, types::{ + domain::BusinessProfile, storage::{self, enums as storage_enums}, transformers::ForeignTryFrom, }, diff --git a/crates/router/src/core/payouts.rs b/crates/router/src/core/payouts.rs index 065b0bbbaa..92763e43d2 100644 --- a/crates/router/src/core/payouts.rs +++ b/crates/router/src/core/payouts.rs @@ -61,7 +61,7 @@ use crate::{ #[derive(Clone)] pub struct PayoutData { pub billing_address: Option, - pub business_profile: storage::BusinessProfile, + pub business_profile: domain::BusinessProfile, pub customer_details: Option, pub merchant_connector_account: Option, pub payouts: storage::Payouts, @@ -2179,7 +2179,7 @@ pub async fn payout_create_db_entries( // Validate whether profile_id passed in request is valid and is linked to the merchant let business_profile = - validate_and_get_business_profile(state, profile_id, merchant_id).await?; + validate_and_get_business_profile(state, key_store, profile_id, merchant_id).await?; let payout_link = match req.payout_link { Some(true) => Some( @@ -2385,7 +2385,7 @@ pub async fn make_payout_data( // Validate whether profile_id passed in request is valid and is linked to the merchant let business_profile = - validate_and_get_business_profile(state, &profile_id, merchant_id).await?; + validate_and_get_business_profile(state, key_store, &profile_id, merchant_id).await?; let payout_method_data = match req { payouts::PayoutRequest::PayoutCreateRequest(r) => r.payout_method_data.to_owned(), payouts::PayoutRequest::PayoutActionRequest(_) => { @@ -2475,16 +2475,25 @@ pub async fn add_external_account_addition_task( async fn validate_and_get_business_profile( state: &SessionState, + merchant_key_store: &domain::MerchantKeyStore, profile_id: &String, merchant_id: &common_utils::id_type::MerchantId, -) -> RouterResult { +) -> RouterResult { let db = &*state.store; - if let Some(business_profile) = - core_utils::validate_and_get_business_profile(db, Some(profile_id), merchant_id).await? + let key_manager_state = &state.into(); + + if let Some(business_profile) = core_utils::validate_and_get_business_profile( + db, + key_manager_state, + merchant_key_store, + Some(profile_id), + merchant_id, + ) + .await? { Ok(business_profile) } else { - db.find_business_profile_by_profile_id(profile_id) + db.find_business_profile_by_profile_id(key_manager_state, merchant_key_store, profile_id) .await .to_not_found_response(errors::ApiErrorResponse::BusinessProfileNotFound { id: profile_id.to_string(), @@ -2495,7 +2504,7 @@ async fn validate_and_get_business_profile( #[allow(clippy::too_many_arguments)] pub async fn create_payout_link( state: &SessionState, - business_profile: &storage::BusinessProfile, + business_profile: &domain::BusinessProfile, customer_id: &CustomerId, merchant_id: &common_utils::id_type::MerchantId, req: &payouts::PayoutCreateRequest, diff --git a/crates/router/src/core/payouts/helpers.rs b/crates/router/src/core/payouts/helpers.rs index 6b0f202647..b17ea43756 100644 --- a/crates/router/src/core/payouts/helpers.rs +++ b/crates/router/src/core/payouts/helpers.rs @@ -14,7 +14,6 @@ use common_utils::{ #[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "customer_v2")))] use common_utils::{generate_customer_id_of_default_length, types::keymanager::ToEncryptable}; use error_stack::{report, ResultExt}; -#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "customer_v2")))] use hyperswitch_domain_models::type_encryption::{crypto_operation, CryptoOperation}; use masking::{PeekInterface, Secret}; use router_env::logger; diff --git a/crates/router/src/core/payouts/validator.rs b/crates/router/src/core/payouts/validator.rs index 8dbdc73cea..d8cb20aac0 100644 --- a/crates/router/src/core/payouts/validator.rs +++ b/crates/router/src/core/payouts/validator.rs @@ -74,6 +74,7 @@ pub async fn validate_create_request( // Payout ID let db: &dyn StorageInterface = &*state.store; + let key_manager_state = &state.into(); let payout_id = core_utils::get_or_generate_uuid("payout_id", req.payout_id.as_ref())?; match validate_uniqueness_of_payout_id_against_merchant_id( db, @@ -123,6 +124,8 @@ pub async fn validate_create_request( not(feature = "merchant_account_v2") ))] let profile_id = core_utils::get_profile_id_from_business_details( + key_manager_state, + merchant_key_store, req.business_country, req.business_label.as_ref(), merchant_account, diff --git a/crates/router/src/core/routing.rs b/crates/router/src/core/routing.rs index cb7cf344e8..3992438a74 100644 --- a/crates/router/src/core/routing.rs +++ b/crates/router/src/core/routing.rs @@ -149,9 +149,12 @@ pub async fn create_routing_config( ) -> RouterResponse { metrics::ROUTING_CREATE_REQUEST_RECEIVED.add(&metrics::CONTEXT, 1, &[]); let db = &*state.store; + let key_manager_state = &(&state).into(); let business_profile = core_utils::validate_and_get_business_profile( db, + key_manager_state, + &key_store, Some(&request.profile_id), merchant_account.get_id(), ) @@ -167,7 +170,7 @@ pub async fn create_routing_config( let name_mca_id_set = helpers::ConnectNameAndMCAIdForProfile( all_mcas.filter_by_profile(&business_profile.profile_id, |mca| { - (&mca.connector_name, &mca.merchant_connector_id) + (&mca.connector_name, &mca.id) }), ); @@ -213,6 +216,8 @@ pub async fn create_routing_config( ) -> RouterResponse { metrics::ROUTING_CREATE_REQUEST_RECEIVED.add(&metrics::CONTEXT, 1, &[]); let db = state.store.as_ref(); + let key_manager_state = &(&state).into(); + let name = request .name .get_required_value("name") @@ -248,8 +253,14 @@ pub async fn create_routing_config( }) .attach_printable("Profile_id not provided")?; - core_utils::validate_and_get_business_profile(db, Some(&profile_id), merchant_account.get_id()) - .await?; + core_utils::validate_and_get_business_profile( + db, + key_manager_state, + &key_store, + Some(&profile_id), + merchant_account.get_id(), + ) + .await?; helpers::validate_connectors_in_routing_config( &state, @@ -288,12 +299,14 @@ pub async fn create_routing_config( pub async fn link_routing_config( state: SessionState, merchant_account: domain::MerchantAccount, + key_store: domain::MerchantKeyStore, profile_id: String, algorithm_id: String, transaction_type: &enums::TransactionType, ) -> RouterResponse { metrics::ROUTING_LINK_CONFIG.add(&metrics::CONTEXT, 1, &[]); let db = state.store.as_ref(); + let key_manager_state = &(&state).into(); let routing_algorithm = RoutingAlgorithmUpdate::fetch_routing_algo(merchant_account.get_id(), &algorithm_id, db) @@ -307,6 +320,8 @@ pub async fn link_routing_config( let business_profile = core_utils::validate_and_get_business_profile( db, + key_manager_state, + &key_store, Some(&profile_id), merchant_account.get_id(), ) @@ -322,9 +337,10 @@ pub async fn link_routing_config( routing_algorithm.update_routing_ref_with_algorithm_id(transaction_type, &mut routing_ref)?; - // TODO move to business profile helpers::update_business_profile_active_algorithm_ref( db, + key_manager_state, + &key_store, business_profile, routing_ref, transaction_type, @@ -340,11 +356,13 @@ pub async fn link_routing_config( pub async fn link_routing_config( state: SessionState, merchant_account: domain::MerchantAccount, + key_store: domain::MerchantKeyStore, algorithm_id: String, transaction_type: &enums::TransactionType, ) -> RouterResponse { metrics::ROUTING_LINK_CONFIG.add(&metrics::CONTEXT, 1, &[]); let db = state.store.as_ref(); + let key_manager_state = &(&state).into(); let routing_algorithm = db .find_routing_algorithm_by_algorithm_id_merchant_id( @@ -356,6 +374,8 @@ pub async fn link_routing_config( let business_profile = core_utils::validate_and_get_business_profile( db, + key_manager_state, + &key_store, Some(&routing_algorithm.profile_id), merchant_account.get_id(), ) @@ -394,6 +414,8 @@ pub async fn link_routing_config( routing_ref.update_algorithm_id(algorithm_id); helpers::update_business_profile_active_algorithm_ref( db, + key_manager_state, + &key_store, business_profile, routing_ref, transaction_type, @@ -410,17 +432,20 @@ pub async fn link_routing_config( pub async fn retrieve_routing_config( state: SessionState, merchant_account: domain::MerchantAccount, + key_store: domain::MerchantKeyStore, algorithm_id: routing_types::RoutingAlgorithmId, ) -> RouterResponse { metrics::ROUTING_RETRIEVE_CONFIG.add(&metrics::CONTEXT, 1, &[]); let db = state.store.as_ref(); + let key_manager_state = &(&state).into(); let routing_algorithm = RoutingAlgorithmUpdate::fetch_routing_algo(merchant_account.get_id(), &algorithm_id.0, db) .await?; - // TODO: Move to domain types of Business Profile core_utils::validate_and_get_business_profile( db, + key_manager_state, + &key_store, Some(&routing_algorithm.0.profile_id), merchant_account.get_id(), ) @@ -440,10 +465,12 @@ pub async fn retrieve_routing_config( pub async fn retrieve_routing_config( state: SessionState, merchant_account: domain::MerchantAccount, + key_store: domain::MerchantKeyStore, algorithm_id: routing_types::RoutingAlgorithmId, ) -> RouterResponse { metrics::ROUTING_RETRIEVE_CONFIG.add(&metrics::CONTEXT, 1, &[]); let db = state.store.as_ref(); + let key_manager_state = &(&state).into(); let routing_algorithm = db .find_routing_algorithm_by_algorithm_id_merchant_id( @@ -455,6 +482,8 @@ pub async fn retrieve_routing_config( core_utils::validate_and_get_business_profile( db, + key_manager_state, + &key_store, Some(&routing_algorithm.profile_id), merchant_account.get_id(), ) @@ -474,14 +503,18 @@ pub async fn retrieve_routing_config( pub async fn unlink_routing_config( state: SessionState, merchant_account: domain::MerchantAccount, + key_store: domain::MerchantKeyStore, profile_id: String, transaction_type: &enums::TransactionType, ) -> RouterResponse { metrics::ROUTING_UNLINK_CONFIG.add(&metrics::CONTEXT, 1, &[]); let db = state.store.as_ref(); + let key_manager_state = &(&state).into(); let business_profile = core_utils::validate_and_get_business_profile( db, + key_manager_state, + &key_store, Some(&profile_id), merchant_account.get_id(), ) @@ -518,6 +551,8 @@ pub async fn unlink_routing_config( let response = record.0.foreign_into(); helpers::update_business_profile_active_algorithm_ref( db, + key_manager_state, + &key_store, business_profile, routing_algorithm, transaction_type, @@ -537,11 +572,14 @@ pub async fn unlink_routing_config( pub async fn unlink_routing_config( state: SessionState, merchant_account: domain::MerchantAccount, + key_store: domain::MerchantKeyStore, request: routing_types::RoutingConfigRequest, transaction_type: &enums::TransactionType, ) -> RouterResponse { metrics::ROUTING_UNLINK_CONFIG.add(&metrics::CONTEXT, 1, &[]); let db = state.store.as_ref(); + let key_manager_state = &(&state).into(); + let profile_id = request .profile_id .get_required_value("profile_id") @@ -551,6 +589,8 @@ pub async fn unlink_routing_config( .attach_printable("Profile_id not provided")?; let business_profile = core_utils::validate_and_get_business_profile( db, + key_manager_state, + &key_store, Some(&profile_id), merchant_account.get_id(), ) @@ -590,6 +630,8 @@ pub async fn unlink_routing_config( let response = record.foreign_into(); helpers::update_business_profile_active_algorithm_ref( db, + key_manager_state, + &key_store, business_profile, routing_algorithm, transaction_type, @@ -687,15 +729,19 @@ pub async fn retrieve_default_routing_config( pub async fn retrieve_linked_routing_config( state: SessionState, merchant_account: domain::MerchantAccount, + key_store: domain::MerchantKeyStore, query_params: RoutingRetrieveLinkQuery, transaction_type: &enums::TransactionType, ) -> RouterResponse { metrics::ROUTING_RETRIEVE_LINK_CONFIG.add(&metrics::CONTEXT, 1, &[]); let db = state.store.as_ref(); + let key_manager_state = &(&state).into(); let business_profiles = if let Some(profile_id) = query_params.profile_id { core_utils::validate_and_get_business_profile( db, + key_manager_state, + &key_store, Some(&profile_id), merchant_account.get_id(), ) @@ -704,9 +750,13 @@ pub async fn retrieve_linked_routing_config( .get_required_value("BusinessProfile") .change_context(errors::ApiErrorResponse::BusinessProfileNotFound { id: profile_id })? } else { - db.list_business_profile_by_merchant_id(merchant_account.get_id()) - .await - .to_not_found_response(errors::ApiErrorResponse::ResourceIdNotFound)? + db.list_business_profile_by_merchant_id( + key_manager_state, + &key_store, + merchant_account.get_id(), + ) + .await + .to_not_found_response(errors::ApiErrorResponse::ResourceIdNotFound)? }; let mut active_algorithms = Vec::new(); @@ -746,13 +796,19 @@ pub async fn retrieve_linked_routing_config( pub async fn retrieve_default_routing_config_for_profiles( state: SessionState, merchant_account: domain::MerchantAccount, + key_store: domain::MerchantKeyStore, transaction_type: &enums::TransactionType, ) -> RouterResponse> { metrics::ROUTING_RETRIEVE_CONFIG_FOR_PROFILE.add(&metrics::CONTEXT, 1, &[]); let db = state.store.as_ref(); + let key_manager_state = &(&state).into(); let all_profiles = db - .list_business_profile_by_merchant_id(merchant_account.get_id()) + .list_business_profile_by_merchant_id( + key_manager_state, + &key_store, + merchant_account.get_id(), + ) .await .to_not_found_response(errors::ApiErrorResponse::ResourceIdNotFound) .attach_printable("error retrieving all business profiles for merchant")?; @@ -785,15 +841,19 @@ pub async fn retrieve_default_routing_config_for_profiles( pub async fn update_default_routing_config_for_profile( state: SessionState, merchant_account: domain::MerchantAccount, + key_store: domain::MerchantKeyStore, updated_config: Vec, profile_id: String, transaction_type: &enums::TransactionType, ) -> RouterResponse { metrics::ROUTING_UPDATE_CONFIG_FOR_PROFILE.add(&metrics::CONTEXT, 1, &[]); let db = state.store.as_ref(); + let key_manager_state = &(&state).into(); let business_profile = core_utils::validate_and_get_business_profile( db, + key_manager_state, + &key_store, Some(&profile_id), merchant_account.get_id(), ) diff --git a/crates/router/src/core/routing/helpers.rs b/crates/router/src/core/routing/helpers.rs index 6444f6bc45..8cfb710a8c 100644 --- a/crates/router/src/core/routing/helpers.rs +++ b/crates/router/src/core/routing/helpers.rs @@ -3,11 +3,8 @@ //! Functions that are used to perform the retrieval of merchant's //! routing dict, configs, defaults use api_models::routing as routing_types; -use common_utils::ext_traits::Encode; -use diesel_models::{ - business_profile::{BusinessProfile, BusinessProfileUpdate}, - configs, -}; +use common_utils::{ext_traits::Encode, types::keymanager::KeyManagerState}; +use diesel_models::configs; use error_stack::ResultExt; use rustc_hash::FxHashSet; use storage_impl::redis::cache; @@ -190,7 +187,9 @@ pub async fn update_merchant_active_algorithm_ref( pub async fn update_business_profile_active_algorithm_ref( db: &dyn StorageInterface, - current_business_profile: BusinessProfile, + key_manager_state: &KeyManagerState, + merchant_key_store: &domain::MerchantKeyStore, + current_business_profile: domain::BusinessProfile, algorithm_id: routing_types::RoutingAlgorithmRef, transaction_type: &storage::enums::TransactionType, ) -> RouterResult<()> { @@ -217,15 +216,20 @@ pub async fn update_business_profile_active_algorithm_ref( storage::enums::TransactionType::Payout => (None, Some(ref_val)), }; - let business_profile_update = BusinessProfileUpdate::RoutingAlgorithmUpdate { + let business_profile_update = domain::BusinessProfileUpdate::RoutingAlgorithmUpdate { routing_algorithm, payout_routing_algorithm, }; - db.update_business_profile_by_profile_id(current_business_profile, business_profile_update) - .await - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Failed to update routing algorithm ref in business profile")?; + db.update_business_profile_by_profile_id( + key_manager_state, + merchant_key_store, + current_business_profile, + business_profile_update, + ) + .await + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Failed to update routing algorithm ref in business profile")?; cache::publish_into_redact_channel(db.get_cache_store().as_ref(), [routing_cache_key]) .await diff --git a/crates/router/src/core/utils.rs b/crates/router/src/core/utils.rs index 7a648f1376..acedad05b6 100644 --- a/crates/router/src/core/utils.rs +++ b/crates/router/src/core/utils.rs @@ -1010,16 +1010,22 @@ 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, + merchant_key_store: &domain::MerchantKeyStore, profile_id: Option<&String>, merchant_id: &common_utils::id_type::MerchantId, -) -> RouterResult> { +) -> RouterResult> { profile_id .async_map(|profile_id| async { - db.find_business_profile_by_profile_id(profile_id) - .await - .to_not_found_response(errors::ApiErrorResponse::BusinessProfileNotFound { - id: profile_id.to_owned(), - }) + db.find_business_profile_by_profile_id( + key_manager_state, + merchant_key_store, + profile_id, + ) + .await + .to_not_found_response(errors::ApiErrorResponse::BusinessProfileNotFound { + id: profile_id.to_owned(), + }) }) .await .transpose()? @@ -1082,7 +1088,10 @@ pub fn get_connector_label( /// If profile_id is not passed, use default profile if available, or /// If business_details (business_country and business_label) are passed, get the business_profile /// 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, + merchant_key_store: &domain::MerchantKeyStore, business_country: Option, business_label: Option<&String>, merchant_account: &domain::MerchantAccount, @@ -1096,6 +1105,8 @@ pub async fn get_profile_id_from_business_details( if should_validate { let _ = validate_and_get_business_profile( db, + key_manager_state, + merchant_key_store, Some(profile_id), merchant_account.get_id(), ) @@ -1108,6 +1119,8 @@ pub async fn get_profile_id_from_business_details( let profile_name = format!("{business_country}_{business_label}"); let business_profile = db .find_business_profile_by_profile_name_merchant_id( + key_manager_state, + merchant_key_store, &profile_name, merchant_account.get_id(), ) diff --git a/crates/router/src/core/webhooks/incoming.rs b/crates/router/src/core/webhooks/incoming.rs index 22d295b116..223acf48b5 100644 --- a/crates/router/src/core/webhooks/incoming.rs +++ b/crates/router/src/core/webhooks/incoming.rs @@ -130,6 +130,8 @@ async fn incoming_webhooks_core( WebhookResponseTracker, serde_json::Value, )> { + let key_manager_state = &(&state).into(); + metrics::WEBHOOK_INCOMING_COUNT.add( &metrics::CONTEXT, 1, @@ -354,7 +356,7 @@ async fn incoming_webhooks_core( let business_profile = state .store - .find_business_profile_by_profile_id(profile_id) + .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(), @@ -501,7 +503,7 @@ async fn payments_incoming_webhook_flow( state: SessionState, req_state: ReqState, merchant_account: domain::MerchantAccount, - business_profile: diesel_models::business_profile::BusinessProfile, + business_profile: domain::BusinessProfile, key_store: domain::MerchantKeyStore, webhook_details: api::IncomingWebhookDetails, source_verified: bool, @@ -643,7 +645,7 @@ async fn payments_incoming_webhook_flow( async fn payouts_incoming_webhook_flow( state: SessionState, merchant_account: domain::MerchantAccount, - business_profile: diesel_models::business_profile::BusinessProfile, + business_profile: domain::BusinessProfile, key_store: domain::MerchantKeyStore, webhook_details: api::IncomingWebhookDetails, event_type: webhooks::IncomingWebhookEvent, @@ -768,7 +770,7 @@ async fn payouts_incoming_webhook_flow( async fn refunds_incoming_webhook_flow( state: SessionState, merchant_account: domain::MerchantAccount, - business_profile: diesel_models::business_profile::BusinessProfile, + business_profile: domain::BusinessProfile, key_store: domain::MerchantKeyStore, webhook_details: api::IncomingWebhookDetails, connector_name: &str, @@ -911,7 +913,7 @@ async fn get_or_update_dispute_object( merchant_id: &common_utils::id_type::MerchantId, payment_attempt: &hyperswitch_domain_models::payments::payment_attempt::PaymentAttempt, event_type: webhooks::IncomingWebhookEvent, - business_profile: &diesel_models::business_profile::BusinessProfile, + business_profile: &domain::BusinessProfile, connector_name: &str, ) -> CustomResult { let db = &*state.store; @@ -991,7 +993,7 @@ async fn external_authentication_incoming_webhook_flow( request_details: &IncomingWebhookRequestDetails<'_>, connector: &ConnectorEnum, object_ref_id: api::ObjectReferenceId, - business_profile: diesel_models::business_profile::BusinessProfile, + business_profile: domain::BusinessProfile, merchant_connector_account: domain::MerchantConnectorAccount, ) -> CustomResult { if source_verified { @@ -1160,7 +1162,7 @@ async fn external_authentication_incoming_webhook_flow( async fn mandates_incoming_webhook_flow( state: SessionState, merchant_account: domain::MerchantAccount, - business_profile: diesel_models::business_profile::BusinessProfile, + business_profile: domain::BusinessProfile, key_store: domain::MerchantKeyStore, webhook_details: api::IncomingWebhookDetails, source_verified: bool, @@ -1253,7 +1255,7 @@ async fn frm_incoming_webhook_flow( source_verified: bool, event_type: webhooks::IncomingWebhookEvent, object_ref_id: api::ObjectReferenceId, - business_profile: diesel_models::business_profile::BusinessProfile, + business_profile: domain::BusinessProfile, ) -> CustomResult { if source_verified { let payment_attempt = @@ -1362,7 +1364,7 @@ async fn frm_incoming_webhook_flow( async fn disputes_incoming_webhook_flow( state: SessionState, merchant_account: domain::MerchantAccount, - business_profile: diesel_models::business_profile::BusinessProfile, + business_profile: domain::BusinessProfile, key_store: domain::MerchantKeyStore, webhook_details: api::IncomingWebhookDetails, source_verified: bool, @@ -1434,7 +1436,7 @@ async fn bank_transfer_webhook_flow( state: SessionState, req_state: ReqState, merchant_account: domain::MerchantAccount, - business_profile: diesel_models::business_profile::BusinessProfile, + business_profile: domain::BusinessProfile, key_store: domain::MerchantKeyStore, webhook_details: api::IncomingWebhookDetails, source_verified: bool, diff --git a/crates/router/src/core/webhooks/outgoing.rs b/crates/router/src/core/webhooks/outgoing.rs index 25c93f8465..86ba886924 100644 --- a/crates/router/src/core/webhooks/outgoing.rs +++ b/crates/router/src/core/webhooks/outgoing.rs @@ -48,7 +48,7 @@ const OUTGOING_WEBHOOK_TIMEOUT_SECS: u64 = 5; pub(crate) async fn create_event_and_trigger_outgoing_webhook( state: SessionState, merchant_account: domain::MerchantAccount, - business_profile: diesel_models::business_profile::BusinessProfile, + business_profile: domain::BusinessProfile, merchant_key_store: &domain::MerchantKeyStore, event_type: enums::EventType, event_class: enums::EventClass, @@ -87,16 +87,10 @@ pub(crate) async fn create_event_and_trigger_outgoing_webhook( timestamp: now, }; - let request_content = get_outgoing_webhook_request( - &state, - &merchant_account, - outgoing_webhook, - &business_profile, - merchant_key_store, - ) - .await - .change_context(errors::ApiErrorResponse::WebhookProcessingFailure) - .attach_printable("Failed to construct outgoing webhook request content")?; + let request_content = + get_outgoing_webhook_request(&merchant_account, outgoing_webhook, &business_profile) + .change_context(errors::ApiErrorResponse::WebhookProcessingFailure) + .attach_printable("Failed to construct outgoing webhook request content")?; let event_metadata = storage::EventMetadata::foreign_from((&content, &primary_object_id)); let key_manager_state = &(&state).into(); @@ -199,7 +193,7 @@ pub(crate) async fn create_event_and_trigger_outgoing_webhook( #[instrument(skip_all)] pub(crate) async fn trigger_webhook_and_raise_event( state: SessionState, - business_profile: diesel_models::business_profile::BusinessProfile, + business_profile: domain::BusinessProfile, merchant_key_store: &domain::MerchantKeyStore, event: domain::Event, request_content: OutgoingWebhookRequestContent, @@ -231,7 +225,7 @@ pub(crate) async fn trigger_webhook_and_raise_event( async fn trigger_webhook_to_merchant( state: SessionState, - business_profile: diesel_models::business_profile::BusinessProfile, + business_profile: domain::BusinessProfile, merchant_key_store: &domain::MerchantKeyStore, event: domain::Event, request_content: OutgoingWebhookRequestContent, @@ -475,7 +469,7 @@ fn raise_webhooks_analytics_event( pub(crate) async fn add_outgoing_webhook_retry_task_to_process_tracker( db: &dyn StorageInterface, - business_profile: &diesel_models::business_profile::BusinessProfile, + business_profile: &domain::BusinessProfile, event: &domain::Event, ) -> CustomResult { let schedule_time = outgoing_webhook_retry::get_webhook_delivery_retry_schedule_time( @@ -539,7 +533,7 @@ pub(crate) async fn add_outgoing_webhook_retry_task_to_process_tracker( } fn get_webhook_url_from_business_profile( - business_profile: &diesel_models::business_profile::BusinessProfile, + business_profile: &domain::BusinessProfile, ) -> CustomResult { let webhook_details = business_profile .webhook_details @@ -554,19 +548,15 @@ fn get_webhook_url_from_business_profile( .map(ExposeInterface::expose) } -pub(crate) async fn get_outgoing_webhook_request( - state: &SessionState, +pub(crate) fn get_outgoing_webhook_request( merchant_account: &domain::MerchantAccount, outgoing_webhook: api::OutgoingWebhook, - business_profile: &diesel_models::business_profile::BusinessProfile, - key_store: &domain::MerchantKeyStore, + business_profile: &domain::BusinessProfile, ) -> CustomResult { #[inline] - async fn get_outgoing_webhook_request_inner( - state: &SessionState, + fn get_outgoing_webhook_request_inner( outgoing_webhook: api::OutgoingWebhook, - business_profile: &diesel_models::business_profile::BusinessProfile, - key_store: &domain::MerchantKeyStore, + business_profile: &domain::BusinessProfile, ) -> CustomResult { let mut headers = vec![( reqwest::header::CONTENT_TYPE.to_string(), @@ -575,30 +565,18 @@ pub(crate) async fn get_outgoing_webhook_request( let transformed_outgoing_webhook = WebhookType::from(outgoing_webhook); let payment_response_hash_key = business_profile.payment_response_hash_key.clone(); - let custom_headers = crypto_operation::( - &state.into(), - type_name!(domain::Event), - CryptoOperation::DecryptOptional( - business_profile - .outgoing_webhook_custom_http_headers - .clone(), - ), - Identifier::Merchant(key_store.merchant_id.clone()), - key_store.key.get_inner().peek(), - ) - .await - .and_then(|val| val.try_into_optionaloperation()) - .change_context(errors::WebhooksFlowError::OutgoingWebhookEncodingFailed) - .attach_printable("Failed to decrypt outgoing webhook custom HTTP headers")? - .map(|decrypted_value| { - decrypted_value - .into_inner() - .expose() - .parse_value::>("HashMap") - .change_context(errors::WebhooksFlowError::OutgoingWebhookEncodingFailed) - .attach_printable("Failed to deserialize outgoing webhook custom HTTP headers") - }) - .transpose()?; + let custom_headers = business_profile + .outgoing_webhook_custom_http_headers + .clone() + .map(|headers| { + headers + .into_inner() + .expose() + .parse_value::>("HashMap") + .change_context(errors::WebhooksFlowError::OutgoingWebhookEncodingFailed) + .attach_printable("Failed to deserialize outgoing webhook custom HTTP headers") + }) + .transpose()?; if let Some(ref map) = custom_headers { headers.extend( map.iter() @@ -623,24 +601,13 @@ pub(crate) async fn get_outgoing_webhook_request( match merchant_account.get_compatible_connector() { #[cfg(feature = "stripe")] - Some(api_models::enums::Connector::Stripe) => { - get_outgoing_webhook_request_inner::( - state, - outgoing_webhook, - business_profile, - key_store, - ) - .await - } - _ => { - get_outgoing_webhook_request_inner::( - state, - outgoing_webhook, - business_profile, - key_store, - ) - .await - } + Some(api_models::enums::Connector::Stripe) => get_outgoing_webhook_request_inner::< + stripe_webhooks::StripeOutgoingWebhook, + >(outgoing_webhook, business_profile), + _ => get_outgoing_webhook_request_inner::( + outgoing_webhook, + business_profile, + ), } } diff --git a/crates/router/src/core/webhooks/webhook_events.rs b/crates/router/src/core/webhooks/webhook_events.rs index f8799ca82d..e7d0483a76 100644 --- a/crates/router/src/core/webhooks/webhook_events.rs +++ b/crates/router/src/core/webhooks/webhook_events.rs @@ -15,7 +15,8 @@ const INITIAL_DELIVERY_ATTEMPTS_LIST_MAX_LIMIT: i64 = 100; #[derive(Debug)] enum MerchantAccountOrBusinessProfile { MerchantAccount(domain::MerchantAccount), - BusinessProfile(storage::BusinessProfile), + #[allow(dead_code)] + BusinessProfile(domain::BusinessProfile), } #[instrument(skip(state))] @@ -186,7 +187,11 @@ pub async fn retry_delivery_attempt( .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Failed to read business profile ID from event to retry")?; store - .find_business_profile_by_profile_id(&business_profile_id) + .find_business_profile_by_profile_id( + key_manager_state, + &key_store, + &business_profile_id, + ) .await .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Failed to find business profile") @@ -301,6 +306,7 @@ async fn determine_identifier_and_get_key_store( )) } + /* // Since no merchant key store was found with `merchant_id` = `merchant_id_or_profile_id`, // `merchant_id_or_profile_id` is not a valid merchant ID. // Assuming that `merchant_id_or_profile_id` is a business profile ID, try to find a @@ -333,7 +339,7 @@ async fn determine_identifier_and_get_key_store( key_store, )) } - + */ Err(error) => Err(error) .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Failed to find merchant key store by merchant ID"), diff --git a/crates/router/src/db/business_profile.rs b/crates/router/src/db/business_profile.rs index 099cad9b80..7b7de43d60 100644 --- a/crates/router/src/db/business_profile.rs +++ b/crates/router/src/db/business_profile.rs @@ -1,4 +1,5 @@ -use error_stack::report; +use common_utils::{ext_traits::AsyncExt, types::keymanager::KeyManagerState}; +use error_stack::{report, ResultExt}; use router_env::{instrument, tracing}; use super::Store; @@ -6,32 +7,50 @@ use crate::{ connection, core::errors::{self, CustomResult}, db::MockDb, - types::storage::business_profile, + types::{ + domain::{ + self, + behaviour::{Conversion, ReverseConversion}, + }, + storage, + }, }; #[async_trait::async_trait] -pub trait BusinessProfileInterface { +pub trait BusinessProfileInterface +where + domain::BusinessProfile: + Conversion, +{ async fn insert_business_profile( &self, - business_profile: business_profile::BusinessProfileNew, - ) -> CustomResult; + key_manager_state: &KeyManagerState, + merchant_key_store: &domain::MerchantKeyStore, + business_profile: domain::BusinessProfile, + ) -> CustomResult; async fn find_business_profile_by_profile_id( &self, + key_manager_state: &KeyManagerState, + merchant_key_store: &domain::MerchantKeyStore, profile_id: &str, - ) -> CustomResult; + ) -> CustomResult; async fn find_business_profile_by_profile_name_merchant_id( &self, + key_manager_state: &KeyManagerState, + merchant_key_store: &domain::MerchantKeyStore, profile_name: &str, merchant_id: &common_utils::id_type::MerchantId, - ) -> CustomResult; + ) -> CustomResult; async fn update_business_profile_by_profile_id( &self, - current_state: business_profile::BusinessProfile, - business_profile_update: business_profile::BusinessProfileUpdate, - ) -> CustomResult; + key_manager_state: &KeyManagerState, + merchant_key_store: &domain::MerchantKeyStore, + current_state: domain::BusinessProfile, + business_profile_update: domain::BusinessProfileUpdate, + ) -> CustomResult; async fn delete_business_profile_by_profile_id_merchant_id( &self, @@ -41,8 +60,10 @@ pub trait BusinessProfileInterface { async fn list_business_profile_by_merchant_id( &self, + key_manager_state: &KeyManagerState, + merchant_key_store: &domain::MerchantKeyStore, merchant_id: &common_utils::id_type::MerchantId, - ) -> CustomResult, errors::StorageError>; + ) -> CustomResult, errors::StorageError>; } #[async_trait::async_trait] @@ -50,56 +71,93 @@ impl BusinessProfileInterface for Store { #[instrument(skip_all)] async fn insert_business_profile( &self, - business_profile: business_profile::BusinessProfileNew, - ) -> CustomResult { + key_manager_state: &KeyManagerState, + merchant_key_store: &domain::MerchantKeyStore, + business_profile: domain::BusinessProfile, + ) -> CustomResult { let conn = connection::pg_connection_write(self).await?; business_profile + .construct_new() + .await + .change_context(errors::StorageError::EncryptionError)? .insert(&conn) .await - .map_err(|error| report!(errors::StorageError::from(error))) + .map_err(|error| report!(errors::StorageError::from(error)))? + .convert( + key_manager_state, + merchant_key_store.key.get_inner(), + merchant_key_store.merchant_id.clone().into(), + ) + .await + .change_context(errors::StorageError::DecryptionError) } #[instrument(skip_all)] async fn find_business_profile_by_profile_id( &self, + key_manager_state: &KeyManagerState, + merchant_key_store: &domain::MerchantKeyStore, profile_id: &str, - ) -> CustomResult { + ) -> CustomResult { let conn = connection::pg_connection_read(self).await?; - business_profile::BusinessProfile::find_by_profile_id(&conn, profile_id) + storage::BusinessProfile::find_by_profile_id(&conn, profile_id) .await - .map_err(|error| report!(errors::StorageError::from(error))) + .map_err(|error| report!(errors::StorageError::from(error)))? + .convert( + key_manager_state, + merchant_key_store.key.get_inner(), + merchant_key_store.merchant_id.clone().into(), + ) + .await + .change_context(errors::StorageError::DecryptionError) } #[instrument(skip_all)] async fn find_business_profile_by_profile_name_merchant_id( &self, + key_manager_state: &KeyManagerState, + merchant_key_store: &domain::MerchantKeyStore, profile_name: &str, merchant_id: &common_utils::id_type::MerchantId, - ) -> CustomResult { + ) -> CustomResult { let conn = connection::pg_connection_read(self).await?; - business_profile::BusinessProfile::find_by_profile_name_merchant_id( - &conn, - profile_name, - merchant_id, - ) - .await - .map_err(|error| report!(errors::StorageError::from(error))) + storage::BusinessProfile::find_by_profile_name_merchant_id(&conn, profile_name, merchant_id) + .await + .map_err(|error| report!(errors::StorageError::from(error)))? + .convert( + key_manager_state, + merchant_key_store.key.get_inner(), + merchant_key_store.merchant_id.clone().into(), + ) + .await + .change_context(errors::StorageError::DecryptionError) } #[instrument(skip_all)] async fn update_business_profile_by_profile_id( &self, - current_state: business_profile::BusinessProfile, - business_profile_update: business_profile::BusinessProfileUpdate, - ) -> CustomResult { + key_manager_state: &KeyManagerState, + merchant_key_store: &domain::MerchantKeyStore, + current_state: domain::BusinessProfile, + business_profile_update: domain::BusinessProfileUpdate, + ) -> CustomResult { let conn = connection::pg_connection_write(self).await?; - business_profile::BusinessProfile::update_by_profile_id( - current_state, - &conn, - business_profile_update, - ) - .await - .map_err(|error| report!(errors::StorageError::from(error))) + Conversion::convert(current_state) + .await + .change_context(errors::StorageError::EncryptionError)? + .update_by_profile_id( + &conn, + storage::BusinessProfileUpdateInternal::from(business_profile_update), + ) + .await + .map_err(|error| report!(errors::StorageError::from(error)))? + .convert( + key_manager_state, + merchant_key_store.key.get_inner(), + merchant_key_store.merchant_id.clone().into(), + ) + .await + .change_context(errors::StorageError::DecryptionError) } #[instrument(skip_all)] @@ -109,24 +167,39 @@ impl BusinessProfileInterface for Store { merchant_id: &common_utils::id_type::MerchantId, ) -> CustomResult { let conn = connection::pg_connection_write(self).await?; - business_profile::BusinessProfile::delete_by_profile_id_merchant_id( - &conn, - profile_id, - merchant_id, - ) - .await - .map_err(|error| report!(errors::StorageError::from(error))) + storage::BusinessProfile::delete_by_profile_id_merchant_id(&conn, profile_id, merchant_id) + .await + .map_err(|error| report!(errors::StorageError::from(error))) } #[instrument(skip_all)] async fn list_business_profile_by_merchant_id( &self, + key_manager_state: &KeyManagerState, + merchant_key_store: &domain::MerchantKeyStore, merchant_id: &common_utils::id_type::MerchantId, - ) -> CustomResult, errors::StorageError> { + ) -> CustomResult, errors::StorageError> { let conn = connection::pg_connection_read(self).await?; - business_profile::BusinessProfile::list_business_profile_by_merchant_id(&conn, merchant_id) + storage::BusinessProfile::list_business_profile_by_merchant_id(&conn, merchant_id) .await .map_err(|error| report!(errors::StorageError::from(error))) + .async_and_then(|business_profiles| async { + let mut domain_business_profiles = Vec::with_capacity(business_profiles.len()); + for business_profile in business_profiles.into_iter() { + domain_business_profiles.push( + business_profile + .convert( + key_manager_state, + merchant_key_store.key.get_inner(), + merchant_key_store.merchant_id.clone().into(), + ) + .await + .change_context(errors::StorageError::DecryptionError)?, + ); + } + Ok(domain_business_profiles) + }) + .await } } @@ -134,55 +207,98 @@ impl BusinessProfileInterface for Store { impl BusinessProfileInterface for MockDb { async fn insert_business_profile( &self, - business_profile: business_profile::BusinessProfileNew, - ) -> CustomResult { - let business_profile_insert = business_profile::BusinessProfile::from(business_profile); + key_manager_state: &KeyManagerState, + merchant_key_store: &domain::MerchantKeyStore, + business_profile: domain::BusinessProfile, + ) -> CustomResult { + let stored_business_profile = Conversion::convert(business_profile) + .await + .change_context(errors::StorageError::EncryptionError)?; + self.business_profiles .lock() .await - .push(business_profile_insert.clone()); - Ok(business_profile_insert) + .push(stored_business_profile.clone()); + + stored_business_profile + .convert( + key_manager_state, + merchant_key_store.key.get_inner(), + merchant_key_store.merchant_id.clone().into(), + ) + .await + .change_context(errors::StorageError::DecryptionError) } async fn find_business_profile_by_profile_id( &self, + key_manager_state: &KeyManagerState, + merchant_key_store: &domain::MerchantKeyStore, profile_id: &str, - ) -> CustomResult { + ) -> CustomResult { self.business_profiles .lock() .await .iter() .find(|business_profile| business_profile.profile_id == profile_id) + .cloned() + .async_map(|business_profile| async { + business_profile + .convert( + key_manager_state, + merchant_key_store.key.get_inner(), + merchant_key_store.merchant_id.clone().into(), + ) + .await + .change_context(errors::StorageError::DecryptionError) + }) + .await + .transpose()? .ok_or( errors::StorageError::ValueNotFound(format!( - "No business profile found for profile_id = {}", - profile_id + "No business profile found for profile_id = {profile_id}" )) .into(), ) - .cloned() } async fn update_business_profile_by_profile_id( &self, - current_state: business_profile::BusinessProfile, - business_profile_update: business_profile::BusinessProfileUpdate, - ) -> CustomResult { + key_manager_state: &KeyManagerState, + merchant_key_store: &domain::MerchantKeyStore, + current_state: domain::BusinessProfile, + business_profile_update: domain::BusinessProfileUpdate, + ) -> CustomResult { + let profile_id = current_state.profile_id.clone(); self.business_profiles .lock() .await .iter_mut() - .find(|bp| bp.profile_id == current_state.profile_id) - .map(|bp| { + .find(|business_profile| business_profile.profile_id == profile_id) + .async_map(|business_profile| async { let business_profile_updated = - business_profile_update.apply_changeset(current_state.clone()); - *bp = business_profile_updated.clone(); + storage::BusinessProfileUpdateInternal::from(business_profile_update) + .apply_changeset( + Conversion::convert(current_state) + .await + .change_context(errors::StorageError::EncryptionError)?, + ); + *business_profile = business_profile_updated.clone(); + business_profile_updated + .convert( + key_manager_state, + merchant_key_store.key.get_inner(), + merchant_key_store.merchant_id.clone().into(), + ) + .await + .change_context(errors::StorageError::DecryptionError) }) + .await + .transpose()? .ok_or( errors::StorageError::ValueNotFound(format!( - "No business profile found for profile_id = {}", - current_state.profile_id + "No business profile found for profile_id = {profile_id}" )) .into(), ) @@ -196,10 +312,12 @@ impl BusinessProfileInterface for MockDb { let mut business_profiles = self.business_profiles.lock().await; let index = business_profiles .iter() - .position(|bp| bp.profile_id == profile_id && bp.merchant_id == *merchant_id) + .position(|business_profile| { + business_profile.profile_id == profile_id + && business_profile.merchant_id == *merchant_id + }) .ok_or::(errors::StorageError::ValueNotFound(format!( - "No business profile found for profile_id = {} and merchant_id = {:?}", - profile_id, merchant_id + "No business profile found for profile_id = {profile_id} and merchant_id = {merchant_id:?}" )))?; business_profiles.remove(index); Ok(true) @@ -207,25 +325,70 @@ impl BusinessProfileInterface for MockDb { async fn list_business_profile_by_merchant_id( &self, + key_manager_state: &KeyManagerState, + merchant_key_store: &domain::MerchantKeyStore, merchant_id: &common_utils::id_type::MerchantId, - ) -> CustomResult, errors::StorageError> { - let business_profile_by_merchant_id = self + ) -> CustomResult, errors::StorageError> { + let business_profiles = self .business_profiles .lock() .await .iter() .filter(|business_profile| business_profile.merchant_id == *merchant_id) .cloned() - .collect(); + .collect::>(); - Ok(business_profile_by_merchant_id) + let mut domain_business_profiles = Vec::with_capacity(business_profiles.len()); + + for business_profile in business_profiles { + let domain_profile = business_profile + .convert( + key_manager_state, + merchant_key_store.key.get_inner(), + merchant_key_store.merchant_id.clone().into(), + ) + .await + .change_context(errors::StorageError::DecryptionError)?; + domain_business_profiles.push(domain_profile); + } + + Ok(domain_business_profiles) } async fn find_business_profile_by_profile_name_merchant_id( &self, - _profile_name: &str, - _merchant_id: &common_utils::id_type::MerchantId, - ) -> CustomResult { - Err(errors::StorageError::MockDbError)? + key_manager_state: &KeyManagerState, + merchant_key_store: &domain::MerchantKeyStore, + profile_name: &str, + merchant_id: &common_utils::id_type::MerchantId, + ) -> CustomResult { + self.business_profiles + .lock() + .await + .iter() + .find(|business_profile| { + business_profile.profile_name == profile_name + && business_profile.merchant_id == *merchant_id + }) + .cloned() + .async_map(|business_profile| async { + business_profile + .convert( + key_manager_state, + merchant_key_store.key.get_inner(), + merchant_key_store.merchant_id.clone().into(), + ) + .await + .change_context(errors::StorageError::DecryptionError) + }) + .await + .transpose()? + .ok_or( + errors::StorageError::ValueNotFound(format!( + "No business profile found for profile_name = {profile_name} and merchant_id = {merchant_id:?}" + + )) + .into(), + ) } } diff --git a/crates/router/src/db/kafka_store.rs b/crates/router/src/db/kafka_store.rs index 6b52887b92..9e102e61e1 100644 --- a/crates/router/src/db/kafka_store.rs +++ b/crates/router/src/db/kafka_store.rs @@ -71,11 +71,7 @@ use crate::{ CommonStorageInterface, GlobalStorageInterface, MasterKeyInterface, StorageInterface, }, services::{authentication, kafka::KafkaProducer, Store}, - types::{ - domain, - storage::{self, business_profile}, - AccessToken, - }, + types::{domain, storage, AccessToken}, }; #[derive(Debug, Clone, Serialize)] @@ -2254,29 +2250,40 @@ impl MerchantKeyStoreInterface for KafkaStore { impl BusinessProfileInterface for KafkaStore { async fn insert_business_profile( &self, - business_profile: business_profile::BusinessProfileNew, - ) -> CustomResult { + key_manager_state: &KeyManagerState, + merchant_key_store: &domain::MerchantKeyStore, + business_profile: domain::BusinessProfile, + ) -> CustomResult { self.diesel_store - .insert_business_profile(business_profile) + .insert_business_profile(key_manager_state, merchant_key_store, business_profile) .await } async fn find_business_profile_by_profile_id( &self, + key_manager_state: &KeyManagerState, + merchant_key_store: &domain::MerchantKeyStore, profile_id: &str, - ) -> CustomResult { + ) -> CustomResult { self.diesel_store - .find_business_profile_by_profile_id(profile_id) + .find_business_profile_by_profile_id(key_manager_state, merchant_key_store, profile_id) .await } async fn update_business_profile_by_profile_id( &self, - current_state: business_profile::BusinessProfile, - business_profile_update: business_profile::BusinessProfileUpdate, - ) -> CustomResult { + key_manager_state: &KeyManagerState, + merchant_key_store: &domain::MerchantKeyStore, + current_state: domain::BusinessProfile, + business_profile_update: domain::BusinessProfileUpdate, + ) -> CustomResult { self.diesel_store - .update_business_profile_by_profile_id(current_state, business_profile_update) + .update_business_profile_by_profile_id( + key_manager_state, + merchant_key_store, + current_state, + business_profile_update, + ) .await } @@ -2292,20 +2299,33 @@ impl BusinessProfileInterface for KafkaStore { async fn list_business_profile_by_merchant_id( &self, + key_manager_state: &KeyManagerState, + merchant_key_store: &domain::MerchantKeyStore, merchant_id: &id_type::MerchantId, - ) -> CustomResult, errors::StorageError> { + ) -> CustomResult, errors::StorageError> { self.diesel_store - .list_business_profile_by_merchant_id(merchant_id) + .list_business_profile_by_merchant_id( + key_manager_state, + merchant_key_store, + merchant_id, + ) .await } async fn find_business_profile_by_profile_name_merchant_id( &self, + key_manager_state: &KeyManagerState, + merchant_key_store: &domain::MerchantKeyStore, profile_name: &str, merchant_id: &id_type::MerchantId, - ) -> CustomResult { + ) -> CustomResult { self.diesel_store - .find_business_profile_by_profile_name_merchant_id(profile_name, merchant_id) + .find_business_profile_by_profile_name_merchant_id( + key_manager_state, + merchant_key_store, + profile_name, + merchant_id, + ) .await } } diff --git a/crates/router/src/routes/admin.rs b/crates/router/src/routes/admin.rs index 92640d80b3..a28324ee59 100644 --- a/crates/router/src/routes/admin.rs +++ b/crates/router/src/routes/admin.rs @@ -1011,18 +1011,18 @@ pub async fn merchant_account_transfer_keys( pub async fn toggle_extended_card_info( state: web::Data, req: HttpRequest, - path: web::Path<(String, String)>, + path: web::Path<(common_utils::id_type::MerchantId, String)>, json_payload: web::Json, ) -> HttpResponse { let flow = Flow::ToggleExtendedCardInfo; - let (_, profile_id) = path.into_inner(); + let (merchant_id, profile_id) = path.into_inner(); Box::pin(api::server_wrap( flow, state, &req, json_payload.into_inner(), - |state, _, req, _| extended_card_info_toggle(state, &profile_id, req), + |state, _, req, _| extended_card_info_toggle(state, &merchant_id, &profile_id, req), &auth::AdminApiAuth, api_locking::LockAction::NotApplicable, )) diff --git a/crates/router/src/routes/routing.rs b/crates/router/src/routes/routing.rs index 8e37589837..3705b0313d 100644 --- a/crates/router/src/routes/routing.rs +++ b/crates/router/src/routes/routing.rs @@ -76,6 +76,7 @@ pub async fn routing_link_config( routing::link_routing_config( state, auth.merchant_account, + auth.key_store, algorithm_id.0, transaction_type, ) @@ -117,6 +118,7 @@ pub async fn routing_link_config( routing::link_routing_config( state, auth.merchant_account, + auth.key_store, wrapper.profile_id, wrapper.algorithm_id.0, transaction_type, @@ -150,7 +152,12 @@ pub async fn routing_retrieve_config( &req, algorithm_id, |state, auth: auth::AuthenticationData, algorithm_id, _| { - routing::retrieve_routing_config(state, auth.merchant_account, algorithm_id) + routing::retrieve_routing_config( + state, + auth.merchant_account, + auth.key_store, + algorithm_id, + ) }, #[cfg(not(feature = "release"))] auth::auth_type( @@ -215,7 +222,13 @@ pub async fn routing_unlink_config( &req, path.into_inner(), |state, auth: auth::AuthenticationData, path, _| { - routing::unlink_routing_config(state, auth.merchant_account, path, transaction_type) + routing::unlink_routing_config( + state, + auth.merchant_account, + auth.key_store, + path, + transaction_type, + ) }, #[cfg(not(feature = "release"))] auth::auth_type( @@ -252,6 +265,7 @@ pub async fn routing_unlink_config( routing::unlink_routing_config( state, auth.merchant_account, + auth.key_store, payload_req, transaction_type, ) @@ -540,6 +554,7 @@ pub async fn routing_retrieve_linked_config( routing::retrieve_linked_routing_config( state, auth.merchant_account, + auth.key_store, query_params, transaction_type, ) @@ -573,6 +588,7 @@ pub async fn routing_retrieve_default_config_for_profiles( routing::retrieve_default_routing_config_for_profiles( state, auth.merchant_account, + auth.key_store, transaction_type, ) }, @@ -615,6 +631,7 @@ pub async fn routing_update_default_config_for_profile( routing::update_default_routing_config_for_profile( state, auth.merchant_account, + auth.key_store, wrapper.updated_config, wrapper.profile_id, transaction_type, diff --git a/crates/router/src/routes/webhook_events.rs b/crates/router/src/routes/webhook_events.rs index b4839f5bd0..548ee65259 100644 --- a/crates/router/src/routes/webhook_events.rs +++ b/crates/router/src/routes/webhook_events.rs @@ -15,7 +15,7 @@ use crate::{ pub async fn list_initial_webhook_delivery_attempts( state: web::Data, req: HttpRequest, - path: web::Path, + path: web::Path, query: web::Query, ) -> impl Responder { let flow = Flow::WebhookEventInitialDeliveryAttemptList; @@ -23,7 +23,7 @@ pub async fn list_initial_webhook_delivery_attempts( let constraints = query.into_inner(); let request_internal = EventListRequestInternal { - merchant_id_or_profile_id: merchant_id_or_profile_id.clone(), + merchant_id_or_profile_id: merchant_id_or_profile_id.get_string_repr().to_string(), constraints, }; @@ -41,8 +41,8 @@ pub async fn list_initial_webhook_delivery_attempts( }, auth::auth_type( &auth::AdminApiAuth, - &auth::JWTAuthMerchantOrProfileFromRoute { - merchant_id_or_profile_id, + &auth::JWTAuthMerchantFromRoute { + merchant_id: merchant_id_or_profile_id, required_permission: Permission::WebhookEventRead, }, req.headers(), @@ -56,13 +56,13 @@ pub async fn list_initial_webhook_delivery_attempts( pub async fn list_webhook_delivery_attempts( state: web::Data, req: HttpRequest, - path: web::Path<(String, String)>, + path: web::Path<(common_utils::id_type::MerchantId, String)>, ) -> impl Responder { let flow = Flow::WebhookEventDeliveryAttemptList; let (merchant_id_or_profile_id, initial_attempt_id) = path.into_inner(); let request_internal = WebhookDeliveryAttemptListRequestInternal { - merchant_id_or_profile_id: merchant_id_or_profile_id.clone(), + merchant_id_or_profile_id: merchant_id_or_profile_id.get_string_repr().to_string(), initial_attempt_id, }; @@ -80,8 +80,8 @@ pub async fn list_webhook_delivery_attempts( }, auth::auth_type( &auth::AdminApiAuth, - &auth::JWTAuthMerchantOrProfileFromRoute { - merchant_id_or_profile_id, + &auth::JWTAuthMerchantFromRoute { + merchant_id: merchant_id_or_profile_id, required_permission: Permission::WebhookEventRead, }, req.headers(), @@ -95,13 +95,13 @@ pub async fn list_webhook_delivery_attempts( pub async fn retry_webhook_delivery_attempt( state: web::Data, req: HttpRequest, - path: web::Path<(String, String)>, + path: web::Path<(common_utils::id_type::MerchantId, String)>, ) -> impl Responder { let flow = Flow::WebhookEventDeliveryRetry; let (merchant_id_or_profile_id, event_id) = path.into_inner(); let request_internal = WebhookDeliveryRetryRequestInternal { - merchant_id_or_profile_id: merchant_id_or_profile_id.clone(), + merchant_id_or_profile_id: merchant_id_or_profile_id.get_string_repr().to_string(), event_id, }; @@ -119,8 +119,8 @@ pub async fn retry_webhook_delivery_attempt( }, auth::auth_type( &auth::AdminApiAuth, - &auth::JWTAuthMerchantOrProfileFromRoute { - merchant_id_or_profile_id, + &auth::JWTAuthMerchantFromRoute { + merchant_id: merchant_id_or_profile_id, required_permission: Permission::WebhookEventWrite, }, req.headers(), diff --git a/crates/router/src/services/authentication.rs b/crates/router/src/services/authentication.rs index a82306fd13..7e7e7b8b40 100644 --- a/crates/router/src/services/authentication.rs +++ b/crates/router/src/services/authentication.rs @@ -1033,6 +1033,7 @@ where } } +/* pub struct JWTAuthMerchantOrProfileFromRoute { pub merchant_id_or_profile_id: String, pub required_permission: Permission, @@ -1094,6 +1095,7 @@ where } } } +*/ pub async fn parse_jwt_payload(headers: &HeaderMap, state: &A) -> RouterResult where diff --git a/crates/router/src/types.rs b/crates/router/src/types.rs index d3c5d7c256..2bd6e27aca 100644 --- a/crates/router/src/types.rs +++ b/crates/router/src/types.rs @@ -479,14 +479,14 @@ impl Default for PollConfig { #[derive(Clone, Debug)] pub struct RedirectPaymentFlowResponse { pub payments_response: api_models::payments::PaymentsResponse, - pub business_profile: diesel_models::business_profile::BusinessProfile, + pub business_profile: domain::BusinessProfile, } #[derive(Clone, Debug)] pub struct AuthenticatePaymentFlowResponse { pub payments_response: api_models::payments::PaymentsResponse, pub poll_config: PollConfig, - pub business_profile: diesel_models::business_profile::BusinessProfile, + pub business_profile: domain::BusinessProfile, } #[derive(Debug, Clone, Default, serde::Deserialize, serde::Serialize)] diff --git a/crates/router/src/types/api/admin.rs b/crates/router/src/types/api/admin.rs index c899c54b79..1217ae66bd 100644 --- a/crates/router/src/types/api/admin.rs +++ b/crates/router/src/types/api/admin.rs @@ -11,20 +11,17 @@ pub use api_models::{ }, organization::{OrganizationId, OrganizationRequest, OrganizationResponse}, }; -use common_utils::{ext_traits::ValueExt, type_name, types::keymanager::Identifier}; +use common_utils::ext_traits::ValueExt; use diesel_models::organization::OrganizationBridge; use error_stack::ResultExt; -use hyperswitch_domain_models::{ - merchant_key_store::MerchantKeyStore, - type_encryption::{crypto_operation, CryptoOperation}, -}; -use masking::{ExposeInterface, PeekInterface}; +use hyperswitch_domain_models::merchant_key_store::MerchantKeyStore; +use masking::{ExposeInterface, Secret}; use crate::{ core::errors, routes::SessionState, types::{ - domain, storage, + domain, transformers::{ForeignInto, ForeignTryFrom}, ForeignFrom, }, @@ -113,79 +110,65 @@ impl ForeignTryFrom for MerchantAccountResponse { } } -pub async fn business_profile_response( - state: &SessionState, - item: storage::business_profile::BusinessProfile, - key_store: &MerchantKeyStore, -) -> Result> { - let outgoing_webhook_custom_http_headers = - crypto_operation::( - &state.into(), - type_name!(storage::business_profile::BusinessProfile), - CryptoOperation::DecryptOptional(item.outgoing_webhook_custom_http_headers.clone()), - Identifier::Merchant(key_store.merchant_id.clone()), - key_store.key.get_inner().peek(), - ) - .await - .and_then(|val| val.try_into_optionaloperation()) - .change_context(errors::ParsingError::StructParseFailure( - "Outgoing webhook custom HTTP headers", - )) - .attach_printable("Failed to decrypt outgoing webhook custom HTTP headers")? - .map(|decrypted_value| { - decrypted_value - .into_inner() - .expose() - .parse_value::>("HashMap") - }) - .transpose()?; +impl ForeignTryFrom for BusinessProfileResponse { + type Error = error_stack::Report; - Ok(BusinessProfileResponse { - merchant_id: item.merchant_id, - profile_id: item.profile_id, - profile_name: item.profile_name, - return_url: item.return_url, - enable_payment_response_hash: item.enable_payment_response_hash, - payment_response_hash_key: item.payment_response_hash_key, - redirect_to_merchant_with_http_post: item.redirect_to_merchant_with_http_post, - webhook_details: item.webhook_details.map(ForeignInto::foreign_into), - metadata: item.metadata, - routing_algorithm: item.routing_algorithm, - intent_fulfillment_time: item.intent_fulfillment_time, - frm_routing_algorithm: item.frm_routing_algorithm, - #[cfg(feature = "payouts")] - payout_routing_algorithm: item.payout_routing_algorithm, - applepay_verified_domains: item.applepay_verified_domains, - payment_link_config: item.payment_link_config.map(ForeignInto::foreign_into), - session_expiry: item.session_expiry, - authentication_connector_details: item - .authentication_connector_details - .map(ForeignInto::foreign_into), - payout_link_config: item.payout_link_config.map(ForeignInto::foreign_into), - use_billing_as_payment_method_billing: item.use_billing_as_payment_method_billing, - extended_card_info_config: item - .extended_card_info_config - .map(|config| config.expose().parse_value("ExtendedCardInfoConfig")) - .transpose()?, - collect_shipping_details_from_wallet_connector: item - .collect_shipping_details_from_wallet_connector, - collect_billing_details_from_wallet_connector: item - .collect_billing_details_from_wallet_connector, - is_connector_agnostic_mit_enabled: item.is_connector_agnostic_mit_enabled, - outgoing_webhook_custom_http_headers, - }) + fn foreign_try_from(item: domain::BusinessProfile) -> Result { + let outgoing_webhook_custom_http_headers = item + .outgoing_webhook_custom_http_headers + .map(|headers| { + headers + .into_inner() + .expose() + .parse_value::>>( + "HashMap>", + ) + }) + .transpose()?; + + Ok(Self { + merchant_id: item.merchant_id, + profile_id: item.profile_id, + profile_name: item.profile_name, + return_url: item.return_url, + enable_payment_response_hash: item.enable_payment_response_hash, + payment_response_hash_key: item.payment_response_hash_key, + redirect_to_merchant_with_http_post: item.redirect_to_merchant_with_http_post, + webhook_details: item.webhook_details.map(ForeignInto::foreign_into), + metadata: item.metadata, + routing_algorithm: item.routing_algorithm, + intent_fulfillment_time: item.intent_fulfillment_time, + frm_routing_algorithm: item.frm_routing_algorithm, + #[cfg(feature = "payouts")] + payout_routing_algorithm: item.payout_routing_algorithm, + applepay_verified_domains: item.applepay_verified_domains, + payment_link_config: item.payment_link_config.map(ForeignInto::foreign_into), + session_expiry: item.session_expiry, + authentication_connector_details: item + .authentication_connector_details + .map(ForeignInto::foreign_into), + payout_link_config: item.payout_link_config.map(ForeignInto::foreign_into), + use_billing_as_payment_method_billing: item.use_billing_as_payment_method_billing, + extended_card_info_config: item + .extended_card_info_config + .map(|config| config.expose().parse_value("ExtendedCardInfoConfig")) + .transpose()?, + collect_shipping_details_from_wallet_connector: item + .collect_shipping_details_from_wallet_connector, + collect_billing_details_from_wallet_connector: item + .collect_billing_details_from_wallet_connector, + is_connector_agnostic_mit_enabled: item.is_connector_agnostic_mit_enabled, + outgoing_webhook_custom_http_headers, + }) + } } #[cfg(all(feature = "v2", feature = "merchant_account_v2"))] - pub async fn create_business_profile( _state: &SessionState, _request: BusinessProfileCreate, _key_store: &MerchantKeyStore, -) -> Result< - storage::business_profile::BusinessProfileNew, - error_stack::Report, -> { +) -> Result> { todo!() } @@ -198,10 +181,7 @@ pub async fn create_business_profile( merchant_account: domain::MerchantAccount, request: BusinessProfileCreate, key_store: &MerchantKeyStore, -) -> Result< - storage::business_profile::BusinessProfileNew, - error_stack::Report, -> { +) -> Result> { use common_utils::ext_traits::AsyncExt; use crate::core; @@ -242,7 +222,7 @@ pub async fn create_business_profile( }) .transpose()?; - Ok(storage::business_profile::BusinessProfileNew { + Ok(domain::BusinessProfile { profile_id, merchant_id, profile_name: request.profile_name.unwrap_or("default".to_string()), diff --git a/crates/router/src/types/domain.rs b/crates/router/src/types/domain.rs index 041f7517f0..011da36be3 100644 --- a/crates/router/src/types/domain.rs +++ b/crates/router/src/types/domain.rs @@ -1,14 +1,18 @@ -mod address; pub mod behaviour { pub use hyperswitch_domain_models::behaviour::{Conversion, ReverseConversion}; } -pub mod merchant_account { +mod merchant_account { pub use hyperswitch_domain_models::merchant_account::*; } -pub use merchant_account::*; +mod business_profile { + pub use hyperswitch_domain_models::business_profile::{ + BusinessProfile, BusinessProfileGeneralUpdate, BusinessProfileUpdate, + }; +} +mod address; mod customer; mod event; mod merchant_connector_account; @@ -22,8 +26,10 @@ pub mod user; pub mod user_key_store; pub use address::*; +pub use business_profile::*; pub use customer::*; pub use event::*; +pub use merchant_account::*; pub use merchant_connector_account::*; pub use merchant_key_store::*; pub use payments::*; diff --git a/crates/router/src/types/storage/business_profile.rs b/crates/router/src/types/storage/business_profile.rs index 4780b3d032..2ab7597bcd 100644 --- a/crates/router/src/types/storage/business_profile.rs +++ b/crates/router/src/types/storage/business_profile.rs @@ -1,4 +1,3 @@ pub use diesel_models::business_profile::{ - BusinessProfile, BusinessProfileGeneralUpdate, BusinessProfileNew, BusinessProfileUpdate, - BusinessProfileUpdateInternal, + BusinessProfile, BusinessProfileNew, BusinessProfileUpdateInternal, }; diff --git a/crates/router/src/utils.rs b/crates/router/src/utils.rs index 44396de7ac..e71bc04930 100644 --- a/crates/router/src/utils.rs +++ b/crates/router/src/utils.rs @@ -1000,7 +1000,7 @@ pub fn check_if_pull_mechanism_for_external_3ds_enabled_from_connector_metadata( #[allow(clippy::too_many_arguments)] pub async fn trigger_payments_webhook( merchant_account: domain::MerchantAccount, - business_profile: diesel_models::business_profile::BusinessProfile, + business_profile: domain::BusinessProfile, key_store: &domain::MerchantKeyStore, payment_data: crate::core::payments::PaymentData, customer: Option, diff --git a/crates/router/src/utils/user/sample_data.rs b/crates/router/src/utils/user/sample_data.rs index 303f02acc6..628e4d573e 100644 --- a/crates/router/src/utils/user/sample_data.rs +++ b/crates/router/src/utils/user/sample_data.rs @@ -58,6 +58,8 @@ pub async fn generate_sample_data( let business_label_default = merchant_parsed_details.first().map(|x| x.business.clone()); let profile_id = crate::core::utils::get_profile_id_from_business_details( + key_manager_state, + &key_store, business_country_default, business_label_default.as_ref(), &merchant_from_db, @@ -89,7 +91,7 @@ pub async fn generate_sample_data( state .store - .list_business_profile_by_merchant_id(merchant_id) + .list_business_profile_by_merchant_id(key_manager_state, &key_store, merchant_id) .await .change_context(SampleDataError::InternalServerError) .attach_printable("Failed to get business profile")? diff --git a/crates/router/src/workflows/outgoing_webhook_retry.rs b/crates/router/src/workflows/outgoing_webhook_retry.rs index df9f00a2e0..c6cf82d784 100644 --- a/crates/router/src/workflows/outgoing_webhook_retry.rs +++ b/crates/router/src/workflows/outgoing_webhook_retry.rs @@ -52,7 +52,11 @@ impl ProcessTrackerWorkflow for OutgoingWebhookRetryWorkflow { ) .await?; let business_profile = db - .find_business_profile_by_profile_id(&tracking_data.business_profile_id) + .find_business_profile_by_profile_id( + key_manager_state, + &key_store, + &tracking_data.business_profile_id, + ) .await?; let event_id = webhooks_core::utils::generate_event_id(); @@ -170,13 +174,10 @@ impl ProcessTrackerWorkflow for OutgoingWebhookRetryWorkflow { }; let request_content = webhooks_core::get_outgoing_webhook_request( - state, &merchant_account, outgoing_webhook, &business_profile, - &key_store, ) - .await .map_err(|error| { logger::error!( ?error, diff --git a/crates/router/src/workflows/payment_sync.rs b/crates/router/src/workflows/payment_sync.rs index ebac4e08d5..5d93849b20 100644 --- a/crates/router/src/workflows/payment_sync.rs +++ b/crates/router/src/workflows/payment_sync.rs @@ -168,7 +168,11 @@ impl ProcessTrackerWorkflow for PaymentsSyncWorkflow { .attach_printable("Could not find profile_id in payment intent")?; let business_profile = db - .find_business_profile_by_profile_id(profile_id) + .find_business_profile_by_profile_id( + key_manager_state, + &key_store, + profile_id, + ) .await .to_not_found_response( errors::ApiErrorResponse::BusinessProfileNotFound {