diff --git a/api-reference/openapi_spec.json b/api-reference/openapi_spec.json index 64893d291c47..1e62053dde18 100644 --- a/api-reference/openapi_spec.json +++ b/api-reference/openapi_spec.json @@ -7265,7 +7265,11 @@ "nullable": true }, "payment_link_config": { - "description": "Default Payment Link config for all payment links created under this business profile", + "allOf": [ + { + "$ref": "#/components/schemas/BusinessPaymentLinkConfig" + } + ], "nullable": true }, "authentication_connector_details": { diff --git a/crates/api_models/src/admin.rs b/crates/api_models/src/admin.rs index c6a6fe17222a..dc0d3248b25d 100644 --- a/crates/api_models/src/admin.rs +++ b/crates/api_models/src/admin.rs @@ -167,15 +167,6 @@ impl MerchantAccountCreate { .transpose() } - pub fn get_webhook_details_as_value( - &self, - ) -> CustomResult, errors::ParsingError> { - self.webhook_details - .as_ref() - .map(|webhook_details| webhook_details.encode_to_value()) - .transpose() - } - pub fn parse_routing_algorithm(&self) -> CustomResult<(), errors::ParsingError> { match self.routing_algorithm { Some(ref routing_algorithm) => { @@ -248,7 +239,7 @@ impl MerchantAccountCreate { pub struct AuthenticationConnectorDetails { /// List of authentication connectors #[schema(value_type = Vec)] - pub authentication_connectors: Vec, + pub authentication_connectors: Vec, /// URL of the (customer service) website that will be shown to the shopper in case of technical errors during the 3D Secure 2 process. pub three_ds_requestor_url: String, } @@ -483,8 +474,7 @@ pub struct MerchantAccountResponse { pub merchant_details: Option>, /// Webhook related details - #[schema(value_type = Option)] - pub webhook_details: Option, + pub webhook_details: Option, /// The routing algorithm to be used to process the incoming request from merchant to outgoing payment processor or payment method. The default is 'Custom' #[serde(skip)] @@ -1948,8 +1938,7 @@ pub struct BusinessProfileResponse { pub redirect_to_merchant_with_http_post: bool, /// Webhook related details - #[schema(value_type = Option)] - pub webhook_details: Option, + pub webhook_details: Option, /// Metadata is useful for storing additional, unstructured information on an object. #[schema(value_type = Option, example = r#"{ "city": "NY", "unit": "245" }"#)] @@ -1980,7 +1969,8 @@ pub struct BusinessProfileResponse { pub session_expiry: Option, /// Default Payment Link config for all payment links created under this business profile - pub payment_link_config: Option, + #[schema(value_type = Option)] + pub payment_link_config: Option, /// External 3DS authentication details pub authentication_connector_details: Option, diff --git a/crates/api_models/src/enums.rs b/crates/api_models/src/enums.rs index 01a428a12f39..eed29b1aa0d9 100644 --- a/crates/api_models/src/enums.rs +++ b/crates/api_models/src/enums.rs @@ -303,36 +303,6 @@ impl Connector { } } -#[derive( - Clone, - Copy, - Debug, - Eq, - Hash, - PartialEq, - serde::Serialize, - serde::Deserialize, - strum::Display, - strum::EnumString, - ToSchema, -)] -#[serde(rename_all = "snake_case")] -#[strum(serialize_all = "snake_case")] -pub enum AuthenticationConnectors { - Threedsecureio, - Netcetera, - Gpayments, -} - -impl AuthenticationConnectors { - pub fn is_separate_version_call_required(&self) -> bool { - match self { - Self::Threedsecureio | Self::Netcetera => false, - Self::Gpayments => true, - } - } -} - #[cfg(feature = "payouts")] #[derive( Clone, diff --git a/crates/common_enums/src/enums.rs b/crates/common_enums/src/enums.rs index f80dc9698dea..8c9fc2f06c9e 100644 --- a/crates/common_enums/src/enums.rs +++ b/crates/common_enums/src/enums.rs @@ -2517,6 +2517,36 @@ pub enum ReconStatus { Disabled, } +#[derive( + Clone, + Copy, + Debug, + Eq, + Hash, + PartialEq, + serde::Serialize, + serde::Deserialize, + strum::Display, + strum::EnumString, + ToSchema, +)] +#[serde(rename_all = "snake_case")] +#[strum(serialize_all = "snake_case")] +pub enum AuthenticationConnectors { + Threedsecureio, + Netcetera, + Gpayments, +} + +impl AuthenticationConnectors { + pub fn is_separate_version_call_required(&self) -> bool { + match self { + Self::Threedsecureio | Self::Netcetera => false, + Self::Gpayments => true, + } + } +} + #[derive( Clone, Debug, diff --git a/crates/common_enums/src/lib.rs b/crates/common_enums/src/lib.rs index b2dce21d2e66..14966d15b5f5 100644 --- a/crates/common_enums/src/lib.rs +++ b/crates/common_enums/src/lib.rs @@ -1,4 +1,5 @@ pub mod enums; -pub use enums::*; pub mod transformers; + +pub use enums::*; pub use transformers::*; diff --git a/crates/diesel_models/src/business_profile.rs b/crates/diesel_models/src/business_profile.rs index cc4dbe6b605e..6de77d5c5fde 100644 --- a/crates/diesel_models/src/business_profile.rs +++ b/crates/diesel_models/src/business_profile.rs @@ -1,7 +1,11 @@ +use std::collections::{HashMap, HashSet}; + +use common_enums::AuthenticationConnectors; #[cfg(all(feature = "v2", feature = "business_profile_v2"))] use common_enums::OrderFulfillmentTimeOrigin; use common_utils::{encryption::Encryption, pii}; use diesel::{AsChangeset, Identifiable, Insertable, Queryable, Selectable}; +use masking::Secret; #[cfg(all( any(feature = "v1", feature = "v2"), @@ -20,16 +24,7 @@ use crate::schema_v2::business_profile; any(feature = "v1", feature = "v2"), not(feature = "business_profile_v2") ))] -#[derive( - Clone, - Debug, - serde::Deserialize, - serde::Serialize, - Identifiable, - Queryable, - Selectable, - router_derive::DebugAsDisplay, -)] +#[derive(Clone, Debug, Identifiable, Queryable, Selectable, router_derive::DebugAsDisplay)] #[diesel(table_name = business_profile, primary_key(profile_id), check_for_backend(diesel::pg::Pg))] pub struct BusinessProfile { pub profile_id: String, @@ -41,7 +36,7 @@ pub struct BusinessProfile { pub enable_payment_response_hash: bool, pub payment_response_hash_key: Option, pub redirect_to_merchant_with_http_post: bool, - pub webhook_details: Option, + pub webhook_details: Option, pub metadata: Option, pub routing_algorithm: Option, pub intent_fulfillment_time: Option, @@ -50,10 +45,10 @@ pub struct BusinessProfile { pub is_recon_enabled: bool, #[diesel(deserialize_as = super::OptionalDieselArray)] pub applepay_verified_domains: Option>, - pub payment_link_config: Option, + pub payment_link_config: Option, pub session_expiry: Option, - pub authentication_connector_details: Option, - pub payout_link_config: Option, + pub authentication_connector_details: Option, + pub payout_link_config: Option, pub is_extended_card_info_enabled: Option, pub extended_card_info_config: Option, pub is_connector_agnostic_mit_enabled: Option, @@ -79,7 +74,7 @@ pub struct BusinessProfileNew { pub enable_payment_response_hash: bool, pub payment_response_hash_key: Option, pub redirect_to_merchant_with_http_post: bool, - pub webhook_details: Option, + pub webhook_details: Option, pub metadata: Option, pub routing_algorithm: Option, pub intent_fulfillment_time: Option, @@ -88,10 +83,10 @@ pub struct BusinessProfileNew { pub is_recon_enabled: bool, #[diesel(deserialize_as = super::OptionalDieselArray)] pub applepay_verified_domains: Option>, - pub payment_link_config: Option, + pub payment_link_config: Option, pub session_expiry: Option, - pub authentication_connector_details: Option, - pub payout_link_config: Option, + pub authentication_connector_details: Option, + pub payout_link_config: Option, pub is_extended_card_info_enabled: Option, pub extended_card_info_config: Option, pub is_connector_agnostic_mit_enabled: Option, @@ -114,7 +109,7 @@ pub struct BusinessProfileUpdateInternal { 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 webhook_details: Option, pub metadata: Option, pub routing_algorithm: Option, pub intent_fulfillment_time: Option, @@ -123,10 +118,10 @@ pub struct BusinessProfileUpdateInternal { pub is_recon_enabled: Option, #[diesel(deserialize_as = super::OptionalDieselArray)] pub applepay_verified_domains: Option>, - pub payment_link_config: Option, + pub payment_link_config: Option, pub session_expiry: Option, - pub authentication_connector_details: Option, - pub payout_link_config: Option, + pub authentication_connector_details: Option, + pub payout_link_config: Option, pub is_extended_card_info_enabled: Option, pub extended_card_info_config: Option, pub is_connector_agnostic_mit_enabled: Option, @@ -136,37 +131,44 @@ pub struct BusinessProfileUpdateInternal { 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 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 { - profile_name: Option, - return_url: Option, - enable_payment_response_hash: Option, - payment_response_hash_key: Option, - redirect_to_merchant_with_http_post: Option, - webhook_details: Option, - metadata: Option, - routing_algorithm: Option, - intent_fulfillment_time: Option, - frm_routing_algorithm: Option, - payout_routing_algorithm: Option, - is_recon_enabled: Option, - applepay_verified_domains: Option>, - payment_link_config: Option, - session_expiry: Option, - authentication_connector_details: Option, - payout_link_config: Option, - extended_card_info_config: Option, - use_billing_as_payment_method_billing: Option, - collect_shipping_details_from_wallet_connector: Option, - collect_billing_details_from_wallet_connector: Option, - is_connector_agnostic_mit_enabled: Option, - outgoing_webhook_custom_http_headers: Option, - }, + Update(Box), RoutingAlgorithmUpdate { routing_algorithm: Option, payout_routing_algorithm: Option, @@ -188,57 +190,60 @@ impl From for BusinessProfileUpdateInternal { let now = common_utils::date_time::now(); match business_profile_update { - BusinessProfileUpdate::Update { - 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, - } => 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::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, @@ -461,16 +466,7 @@ impl BusinessProfileUpdate { /// If two adjacent columns have the same type, then the compiler will not throw any error, but the /// fields read / written will be interchanged #[cfg(all(feature = "v2", feature = "business_profile_v2"))] -#[derive( - Clone, - Debug, - serde::Deserialize, - serde::Serialize, - Identifiable, - Queryable, - Selectable, - router_derive::DebugAsDisplay, -)] +#[derive(Clone, Debug, Identifiable, Queryable, Selectable, router_derive::DebugAsDisplay)] #[diesel(table_name = business_profile, primary_key(profile_id), check_for_backend(diesel::pg::Pg))] pub struct BusinessProfile { pub profile_id: String, @@ -482,15 +478,15 @@ pub struct BusinessProfile { pub enable_payment_response_hash: bool, pub payment_response_hash_key: Option, pub redirect_to_merchant_with_http_post: bool, - pub webhook_details: Option, + pub webhook_details: Option, pub metadata: Option, pub is_recon_enabled: bool, #[diesel(deserialize_as = super::OptionalDieselArray)] pub applepay_verified_domains: Option>, - pub payment_link_config: Option, + pub payment_link_config: Option, pub session_expiry: Option, - pub authentication_connector_details: Option, - pub payout_link_config: Option, + pub authentication_connector_details: Option, + pub payout_link_config: Option, pub is_extended_card_info_enabled: Option, pub extended_card_info_config: Option, pub is_connector_agnostic_mit_enabled: Option, @@ -519,15 +515,15 @@ pub struct BusinessProfileNew { pub enable_payment_response_hash: bool, pub payment_response_hash_key: Option, pub redirect_to_merchant_with_http_post: bool, - pub webhook_details: Option, + pub webhook_details: Option, pub metadata: Option, pub is_recon_enabled: bool, #[diesel(deserialize_as = super::OptionalDieselArray)] pub applepay_verified_domains: Option>, - pub payment_link_config: Option, + pub payment_link_config: Option, pub session_expiry: Option, - pub authentication_connector_details: Option, - pub payout_link_config: Option, + pub authentication_connector_details: Option, + pub payout_link_config: Option, pub is_extended_card_info_enabled: Option, pub extended_card_info_config: Option, pub is_connector_agnostic_mit_enabled: Option, @@ -553,15 +549,15 @@ pub struct BusinessProfileUpdateInternal { 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 webhook_details: Option, pub metadata: Option, pub is_recon_enabled: Option, #[diesel(deserialize_as = super::OptionalDieselArray)] pub applepay_verified_domains: Option>, - pub payment_link_config: Option, + pub payment_link_config: Option, pub session_expiry: Option, - pub authentication_connector_details: Option, - pub payout_link_config: Option, + pub authentication_connector_details: Option, + pub payout_link_config: Option, pub is_extended_card_info_enabled: Option, pub extended_card_info_config: Option, pub is_connector_agnostic_mit_enabled: Option, @@ -577,36 +573,40 @@ pub struct BusinessProfileUpdateInternal { pub default_fallback_routing: Option, } +#[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 { - profile_name: Option, - return_url: Option, - enable_payment_response_hash: Option, - payment_response_hash_key: Option, - redirect_to_merchant_with_http_post: Option, - webhook_details: Option, - metadata: Option, - is_recon_enabled: Option, - applepay_verified_domains: Option>, - payment_link_config: Option, - session_expiry: Option, - authentication_connector_details: Option, - payout_link_config: Option, - extended_card_info_config: Option, - use_billing_as_payment_method_billing: Option, - collect_shipping_details_from_wallet_connector: Option, - collect_billing_details_from_wallet_connector: Option, - is_connector_agnostic_mit_enabled: Option, - outgoing_webhook_custom_http_headers: Option, - routing_algorithm_id: Option, - order_fulfillment_time: Option, - order_fulfillment_time_origin: Option, - frm_routing_algorithm_id: Option, - payout_routing_algorithm_id: Option, - default_fallback_routing: Option, - }, + Update(Box), RoutingAlgorithmUpdate { routing_algorithm_id: Option, payout_routing_algorithm_id: Option, @@ -625,61 +625,64 @@ impl From for BusinessProfileUpdateInternal { let now = common_utils::date_time::now(); match business_profile_update { - BusinessProfileUpdate::Update { - 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, - } => 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::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, @@ -903,3 +906,65 @@ impl From for BusinessProfile { } } } + +#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, diesel::AsExpression)] +#[diesel(sql_type = diesel::sql_types::Jsonb)] +pub struct AuthenticationConnectorDetails { + pub authentication_connectors: Vec, + pub three_ds_requestor_url: String, +} + +common_utils::impl_to_sql_from_sql_json!(AuthenticationConnectorDetails); + +#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, diesel::AsExpression)] +#[diesel(sql_type = diesel::sql_types::Json)] +pub struct WebhookDetails { + pub webhook_version: Option, + pub webhook_username: Option, + pub webhook_password: Option>, + pub webhook_url: Option>, + pub payment_created_enabled: Option, + pub payment_succeeded_enabled: Option, + pub payment_failed_enabled: Option, +} + +common_utils::impl_to_sql_from_sql_json!(WebhookDetails); + +#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, diesel::AsExpression)] +#[diesel(sql_type = diesel::sql_types::Jsonb)] +pub struct BusinessPaymentLinkConfig { + pub domain_name: Option, + #[serde(flatten)] + pub default_config: Option, + pub business_specific_configs: Option>, + pub allowed_domains: Option>, +} + +#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] +pub struct PaymentLinkConfigRequest { + pub theme: Option, + pub logo: Option, + pub seller_name: Option, + pub sdk_layout: Option, + pub display_sdk_only: Option, + pub enabled_saved_payment_method: Option, +} + +common_utils::impl_to_sql_from_sql_json!(BusinessPaymentLinkConfig); + +#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, diesel::AsExpression)] +#[diesel(sql_type = diesel::sql_types::Jsonb)] +pub struct BusinessPayoutLinkConfig { + #[serde(flatten)] + pub config: BusinessGenericLinkConfig, +} + +#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] +pub struct BusinessGenericLinkConfig { + pub domain_name: Option, + pub allowed_domains: HashSet, + #[serde(flatten)] + pub ui_config: common_utils::link_utils::GenericLinkUiConfig, +} + +common_utils::impl_to_sql_from_sql_json!(BusinessPayoutLinkConfig); diff --git a/crates/diesel_models/src/merchant_account.rs b/crates/diesel_models/src/merchant_account.rs index 907162da7c21..0f87748d2769 100644 --- a/crates/diesel_models/src/merchant_account.rs +++ b/crates/diesel_models/src/merchant_account.rs @@ -36,7 +36,7 @@ pub struct MerchantAccount { pub redirect_to_merchant_with_http_post: bool, pub merchant_name: Option, pub merchant_details: Option, - pub webhook_details: Option, + pub webhook_details: Option, pub sub_merchants_enabled: Option, pub parent_merchant_id: Option, pub publishable_key: Option, @@ -70,7 +70,7 @@ pub struct MerchantAccountSetter { pub redirect_to_merchant_with_http_post: bool, pub merchant_name: Option, pub merchant_details: Option, - pub webhook_details: Option, + pub webhook_details: Option, pub sub_merchants_enabled: Option, pub parent_merchant_id: Option, pub publishable_key: Option, @@ -226,7 +226,7 @@ pub struct MerchantAccountNew { pub merchant_name: Option, pub merchant_details: Option, pub return_url: Option, - pub webhook_details: Option, + pub webhook_details: Option, pub sub_merchants_enabled: Option, pub parent_merchant_id: Option, pub enable_payment_response_hash: Option, @@ -295,7 +295,7 @@ pub struct MerchantAccountUpdateInternal { pub merchant_name: Option, pub merchant_details: Option, pub return_url: Option, - pub webhook_details: Option, + pub webhook_details: Option, pub sub_merchants_enabled: Option, pub parent_merchant_id: Option, pub enable_payment_response_hash: Option, diff --git a/crates/hyperswitch_domain_models/src/business_profile.rs b/crates/hyperswitch_domain_models/src/business_profile.rs index e6b2bcbe5b11..779dcdb2fbb1 100644 --- a/crates/hyperswitch_domain_models/src/business_profile.rs +++ b/crates/hyperswitch_domain_models/src/business_profile.rs @@ -8,7 +8,10 @@ use common_utils::{ pii, types::keymanager, }; -use diesel_models::business_profile::BusinessProfileUpdateInternal; +use diesel_models::business_profile::{ + AuthenticationConnectorDetails, BusinessPaymentLinkConfig, BusinessPayoutLinkConfig, + BusinessProfileUpdateInternal, WebhookDetails, +}; use error_stack::ResultExt; use masking::{PeekInterface, Secret}; @@ -29,7 +32,7 @@ pub struct BusinessProfile { pub enable_payment_response_hash: bool, pub payment_response_hash_key: Option, pub redirect_to_merchant_with_http_post: bool, - pub webhook_details: Option, + pub webhook_details: Option, pub metadata: Option, pub routing_algorithm: Option, pub intent_fulfillment_time: Option, @@ -37,10 +40,10 @@ pub struct BusinessProfile { pub payout_routing_algorithm: Option, pub is_recon_enabled: bool, pub applepay_verified_domains: Option>, - pub payment_link_config: Option, + pub payment_link_config: Option, pub session_expiry: Option, - pub authentication_connector_details: Option, - pub payout_link_config: Option, + pub authentication_connector_details: Option, + pub payout_link_config: Option, pub is_extended_card_info_enabled: Option, pub extended_card_info_config: Option, pub is_connector_agnostic_mit_enabled: Option, @@ -50,37 +53,44 @@ pub struct BusinessProfile { pub outgoing_webhook_custom_http_headers: OptionalEncryptableValue, } +#[cfg(all( + any(feature = "v1", feature = "v2"), + not(feature = "business_profile_v2") +))] +#[derive(Debug)] +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: OptionalEncryptableValue, +} + #[cfg(all( any(feature = "v1", feature = "v2"), not(feature = "business_profile_v2") ))] #[derive(Debug)] pub enum BusinessProfileUpdate { - Update { - profile_name: Option, - return_url: Option, - enable_payment_response_hash: Option, - payment_response_hash_key: Option, - redirect_to_merchant_with_http_post: Option, - webhook_details: Option, - metadata: Option, - routing_algorithm: Option, - intent_fulfillment_time: Option, - frm_routing_algorithm: Option, - payout_routing_algorithm: Option, - is_recon_enabled: Option, - applepay_verified_domains: Option>, - payment_link_config: Option, - session_expiry: Option, - authentication_connector_details: Option, - payout_link_config: Option, - extended_card_info_config: Option, - use_billing_as_payment_method_billing: Option, - collect_shipping_details_from_wallet_connector: Option, - collect_billing_details_from_wallet_connector: Option, - is_connector_agnostic_mit_enabled: Option, - outgoing_webhook_custom_http_headers: OptionalEncryptableValue, - }, + Update(Box), RoutingAlgorithmUpdate { routing_algorithm: Option, payout_routing_algorithm: Option, @@ -102,58 +112,62 @@ impl From for BusinessProfileUpdateInternal { let now = date_time::now(); match business_profile_update { - BusinessProfileUpdate::Update { - 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, - } => 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, - is_connector_agnostic_mit_enabled, - use_billing_as_payment_method_billing, - collect_shipping_details_from_wallet_connector, - collect_billing_details_from_wallet_connector, - outgoing_webhook_custom_http_headers: outgoing_webhook_custom_http_headers - .map(Encryption::from), - }, + 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, + is_connector_agnostic_mit_enabled, + use_billing_as_payment_method_billing, + collect_shipping_details_from_wallet_connector, + collect_billing_details_from_wallet_connector, + outgoing_webhook_custom_http_headers: outgoing_webhook_custom_http_headers + .map(Encryption::from), + } + } BusinessProfileUpdate::RoutingAlgorithmUpdate { routing_algorithm, payout_routing_algorithm, @@ -396,14 +410,14 @@ pub struct BusinessProfile { pub enable_payment_response_hash: bool, pub payment_response_hash_key: Option, pub redirect_to_merchant_with_http_post: bool, - pub webhook_details: Option, + pub webhook_details: Option, pub metadata: Option, pub is_recon_enabled: bool, pub applepay_verified_domains: Option>, - pub payment_link_config: Option, + pub payment_link_config: Option, pub session_expiry: Option, - pub authentication_connector_details: Option, - pub payout_link_config: Option, + pub authentication_connector_details: Option, + pub payout_link_config: Option, pub is_extended_card_info_enabled: Option, pub extended_card_info_config: Option, pub is_connector_agnostic_mit_enabled: Option, @@ -419,36 +433,40 @@ pub struct BusinessProfile { pub default_fallback_routing: Option, } +#[cfg(all(feature = "v2", feature = "business_profile_v2"))] +#[derive(Debug)] +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: OptionalEncryptableValue, + 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)] pub enum BusinessProfileUpdate { - Update { - profile_name: Option, - return_url: Option, - enable_payment_response_hash: Option, - payment_response_hash_key: Option, - redirect_to_merchant_with_http_post: Option, - webhook_details: Option, - metadata: Option, - is_recon_enabled: Option, - applepay_verified_domains: Option>, - payment_link_config: Option, - session_expiry: Option, - authentication_connector_details: Option, - payout_link_config: Option, - extended_card_info_config: Option, - use_billing_as_payment_method_billing: Option, - collect_shipping_details_from_wallet_connector: Option, - collect_billing_details_from_wallet_connector: Option, - is_connector_agnostic_mit_enabled: Option, - outgoing_webhook_custom_http_headers: OptionalEncryptableValue, - routing_algorithm_id: Option, - order_fulfillment_time: Option, - order_fulfillment_time_origin: Option, - frm_routing_algorithm_id: Option, - payout_routing_algorithm_id: Option, - default_fallback_routing: Option, - }, + Update(Box), RoutingAlgorithmUpdate { routing_algorithm_id: Option, payout_routing_algorithm_id: Option, @@ -467,62 +485,65 @@ impl From for BusinessProfileUpdateInternal { let now = date_time::now(); match business_profile_update { - BusinessProfileUpdate::Update { - 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, - } => 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, - is_connector_agnostic_mit_enabled, - use_billing_as_payment_method_billing, - collect_shipping_details_from_wallet_connector, - collect_billing_details_from_wallet_connector, - outgoing_webhook_custom_http_headers: outgoing_webhook_custom_http_headers - .map(Encryption::from), - routing_algorithm_id, - order_fulfillment_time, - order_fulfillment_time_origin, - frm_routing_algorithm_id, - payout_routing_algorithm_id, - default_fallback_routing, - }, + 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, + is_connector_agnostic_mit_enabled, + use_billing_as_payment_method_billing, + collect_shipping_details_from_wallet_connector, + collect_billing_details_from_wallet_connector, + outgoing_webhook_custom_http_headers: outgoing_webhook_custom_http_headers + .map(Encryption::from), + 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, diff --git a/crates/hyperswitch_domain_models/src/merchant_account.rs b/crates/hyperswitch_domain_models/src/merchant_account.rs index 2452e5091fd4..1697b78275c6 100644 --- a/crates/hyperswitch_domain_models/src/merchant_account.rs +++ b/crates/hyperswitch_domain_models/src/merchant_account.rs @@ -8,7 +8,8 @@ use common_utils::{ types::keymanager::{self}, }; use diesel_models::{ - enums::MerchantStorageScheme, merchant_account::MerchantAccountUpdateInternal, + business_profile::WebhookDetails, enums::MerchantStorageScheme, + merchant_account::MerchantAccountUpdateInternal, }; use error_stack::ResultExt; use masking::{PeekInterface, Secret}; @@ -29,7 +30,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, @@ -65,7 +66,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, @@ -226,7 +227,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/src/core/admin.rs b/crates/router/src/core/admin.rs index dabdf4bd32fe..820a0a965c63 100644 --- a/crates/router/src/core/admin.rs +++ b/crates/router/src/core/admin.rs @@ -48,7 +48,7 @@ use crate::{ types::{self as domain_types, AsyncLift}, }, storage::{self, enums::MerchantStorageScheme}, - transformers::{ForeignTryFrom, ForeignTryInto}, + transformers::{ForeignInto, ForeignTryFrom, ForeignTryInto}, }, utils, }; @@ -289,11 +289,7 @@ impl MerchantAccountCreateBridge for api::MerchantAccountCreate { }, )?; - let webhook_details = self.get_webhook_details_as_value().change_context( - errors::ApiErrorResponse::InvalidDataValue { - field_name: "webhook details", - }, - )?; + let webhook_details = self.webhook_details.clone().map(ForeignInto::foreign_into); let pm_collect_link_config = self.get_pm_link_config_as_value().change_context( errors::ApiErrorResponse::InvalidDataValue { @@ -871,11 +867,7 @@ impl MerchantAccountUpdateBridge for api::MerchantAccountUpdate { }, )?; - let webhook_details = self.get_webhook_details_as_value().change_context( - errors::ApiErrorResponse::InvalidDataValue { - field_name: "webhook_details", - }, - )?; + let webhook_details = self.webhook_details.map(ForeignInto::foreign_into); let parent_merchant_id = get_parent_merchant( state, @@ -3375,17 +3367,7 @@ pub async fn update_business_profile( helpers::validate_intent_fulfillment_expiry(intent_fulfillment_expiry.to_owned())?; } - let webhook_details = request - .webhook_details - .as_ref() - .map(|webhook_details| { - webhook_details.encode_to_value().change_context( - errors::ApiErrorResponse::InvalidDataValue { - field_name: "webhook details", - }, - ) - }) - .transpose()?; + let webhook_details = request.webhook_details.map(ForeignInto::foreign_into); if let Some(ref routing_algorithm) = request.routing_algorithm { let _: api_models::routing::RoutingAlgorithm = routing_algorithm @@ -3399,13 +3381,8 @@ pub async fn update_business_profile( let payment_link_config = request .payment_link_config - .as_ref() .map(|payment_link_conf| match payment_link_conf.validate() { - Ok(_) => payment_link_conf.encode_to_value().change_context( - errors::ApiErrorResponse::InvalidDataValue { - field_name: "payment_link_config", - }, - ), + Ok(_) => Ok(payment_link_conf.foreign_into()), Err(e) => Err(report!(errors::ApiErrorResponse::InvalidRequestData { message: e.to_string() })), @@ -3434,56 +3411,48 @@ pub async fn update_business_profile( let payout_link_config = request .payout_link_config - .as_ref() .map(|payout_conf| match payout_conf.config.validate() { - Ok(_) => payout_conf.encode_to_value().change_context( - errors::ApiErrorResponse::InvalidDataValue { - field_name: "payout_link_config", - }, - ), + Ok(_) => Ok(payout_conf.foreign_into()), Err(e) => Err(report!(errors::ApiErrorResponse::InvalidRequestData { message: e.to_string() })), }) .transpose()?; - let business_profile_update = storage::business_profile::BusinessProfileUpdate::Update { - 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, - payment_response_hash_key: request.payment_response_hash_key, - redirect_to_merchant_with_http_post: request.redirect_to_merchant_with_http_post, - webhook_details, - metadata: request.metadata, - routing_algorithm: request.routing_algorithm, - intent_fulfillment_time: request.intent_fulfillment_time.map(i64::from), - frm_routing_algorithm: request.frm_routing_algorithm, - #[cfg(feature = "payouts")] - payout_routing_algorithm: request.payout_routing_algorithm, - #[cfg(not(feature = "payouts"))] - payout_routing_algorithm: None, - is_recon_enabled: None, - applepay_verified_domains: request.applepay_verified_domains, - payment_link_config, - session_expiry: request.session_expiry.map(i64::from), - authentication_connector_details: request - .authentication_connector_details - .as_ref() - .map(Encode::encode_to_value) - .transpose() - .change_context(errors::ApiErrorResponse::InvalidDataValue { - field_name: "authentication_connector_details", - })?, - payout_link_config, - extended_card_info_config, - use_billing_as_payment_method_billing: request.use_billing_as_payment_method_billing, - collect_shipping_details_from_wallet_connector: request - .collect_shipping_details_from_wallet_connector, - collect_billing_details_from_wallet_connector: request - .collect_billing_details_from_wallet_connector, - is_connector_agnostic_mit_enabled: request.is_connector_agnostic_mit_enabled, - outgoing_webhook_custom_http_headers: outgoing_webhook_custom_http_headers.map(Into::into), - }; + let business_profile_update = + storage::BusinessProfileUpdate::Update(Box::new(storage::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, + payment_response_hash_key: request.payment_response_hash_key, + redirect_to_merchant_with_http_post: request.redirect_to_merchant_with_http_post, + webhook_details, + metadata: request.metadata, + routing_algorithm: request.routing_algorithm, + intent_fulfillment_time: request.intent_fulfillment_time.map(i64::from), + frm_routing_algorithm: request.frm_routing_algorithm, + #[cfg(feature = "payouts")] + payout_routing_algorithm: request.payout_routing_algorithm, + #[cfg(not(feature = "payouts"))] + payout_routing_algorithm: None, + is_recon_enabled: None, + applepay_verified_domains: request.applepay_verified_domains, + payment_link_config, + session_expiry: request.session_expiry.map(i64::from), + authentication_connector_details: request + .authentication_connector_details + .map(ForeignInto::foreign_into), + payout_link_config, + extended_card_info_config, + use_billing_as_payment_method_billing: request.use_billing_as_payment_method_billing, + collect_shipping_details_from_wallet_connector: request + .collect_shipping_details_from_wallet_connector, + collect_billing_details_from_wallet_connector: request + .collect_billing_details_from_wallet_connector, + is_connector_agnostic_mit_enabled: request.is_connector_agnostic_mit_enabled, + outgoing_webhook_custom_http_headers: outgoing_webhook_custom_http_headers + .map(Into::into), + })); let updated_business_profile = db .update_business_profile_by_profile_id(business_profile, business_profile_update) diff --git a/crates/router/src/core/authentication/utils.rs b/crates/router/src/core/authentication/utils.rs index 0ed55999831d..ebfa60374761 100644 --- a/crates/router/src/core/authentication/utils.rs +++ b/crates/router/src/core/authentication/utils.rs @@ -1,4 +1,3 @@ -use common_utils::ext_traits::ValueExt; use error_stack::ResultExt; use hyperswitch_domain_models::router_data_v2::ExternalAuthenticationFlowData; @@ -269,24 +268,17 @@ pub async fn get_authentication_connector_data( key_store: &domain::MerchantKeyStore, business_profile: &storage::BusinessProfile, ) -> RouterResult<( - api_models::enums::AuthenticationConnectors, + common_enums::AuthenticationConnectors, payments::helpers::MerchantConnectorAccountType, )> { - let authentication_details: api_models::admin::AuthenticationConnectorDetails = - business_profile - .authentication_connector_details - .clone() - .get_required_value("authentication_details") - .change_context(errors::ApiErrorResponse::UnprocessableEntity { - message: "authentication_connector_details is not available in business profile" - .into(), - }) - .attach_printable("authentication_connector_details not configured by the merchant")? - .parse_value("AuthenticationConnectorDetails") - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable( - "Error while parsing authentication_connector_details from business_profile", - )?; + let authentication_details = business_profile + .authentication_connector_details + .clone() + .get_required_value("authentication_details") + .change_context(errors::ApiErrorResponse::UnprocessableEntity { + message: "authentication_connector_details is not available in business profile".into(), + }) + .attach_printable("authentication_connector_details not configured by the merchant")?; let authentication_connector = authentication_details .authentication_connectors .first() diff --git a/crates/router/src/core/payment_link.rs b/crates/router/src/core/payment_link.rs index ef39a34a11e6..7b95edbda975 100644 --- a/crates/router/src/core/payment_link.rs +++ b/crates/router/src/core/payment_link.rs @@ -526,39 +526,33 @@ pub fn extract_payment_link_config( pub fn get_payment_link_config_based_on_priority( payment_create_link_config: Option, - business_link_config: Option, + business_link_config: Option, merchant_name: String, default_domain_name: String, payment_link_config_id: Option, ) -> Result<(PaymentLinkConfig, String), error_stack::Report> { let (domain_name, business_theme_configs, allowed_domains) = if let Some(business_config) = business_link_config { - let extracted_value: api_models::admin::BusinessPaymentLinkConfig = business_config - .parse_value("BusinessPaymentLinkConfig") - .change_context(errors::ApiErrorResponse::InvalidDataValue { - field_name: "payment_link_config", - }) - .attach_printable("Invalid payment_link_config given in business config")?; logger::info!( "domain name set to custom domain https://{:?}", - extracted_value.domain_name + business_config.domain_name ); ( - extracted_value + business_config .domain_name .clone() .map(|d_name| format!("https://{}", d_name)) .unwrap_or_else(|| default_domain_name.clone()), payment_link_config_id .and_then(|id| { - extracted_value + business_config .business_specific_configs .as_ref() .and_then(|specific_configs| specific_configs.get(&id).cloned()) }) - .or(extracted_value.default_config), - extracted_value.allowed_domains, + .or(business_config.default_config), + business_config.allowed_domains, ) } else { (default_domain_name, None, None) diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs index 8d7266c499e8..34a5c337ce43 100644 --- a/crates/router/src/core/payments.rs +++ b/crates/router/src/core/payments.rs @@ -4156,19 +4156,11 @@ pub async fn payment_external_authentication( id: profile_id.to_string(), })?; - let authentication_details: api_models::admin::AuthenticationConnectorDetails = - business_profile - .authentication_connector_details - .clone() - .get_required_value("authentication_connector_details") - .attach_printable("authentication_connector_details not configured by the merchant")? - .parse_value("AuthenticationConnectorDetails") - .change_context(errors::ApiErrorResponse::UnprocessableEntity { - message: "Invalid data format found for authentication_connector_details".into(), - }) - .attach_printable( - "Error while parsing authentication_connector_details from business_profile", - )?; + let authentication_details = business_profile + .authentication_connector_details + .clone() + .get_required_value("authentication_connector_details") + .attach_printable("authentication_connector_details not configured by the merchant")?; let authentication_response = Box::pin(authentication_core::perform_authentication( &state, diff --git a/crates/router/src/core/payouts.rs b/crates/router/src/core/payouts.rs index 75756a963909..1350bf00c2b7 100644 --- a/crates/router/src/core/payouts.rs +++ b/crates/router/src/core/payouts.rs @@ -5,7 +5,7 @@ pub mod retry; pub mod validator; use std::vec::IntoIter; -use api_models::{self, admin, enums as api_enums, payouts::PayoutLinkResponse}; +use api_models::{self, enums as api_enums, payouts::PayoutLinkResponse}; #[cfg(feature = "payout_retry")] use common_enums::PayoutRetryType; use common_utils::{ @@ -2505,18 +2505,7 @@ pub async fn create_payout_link( // Fetch all configs let default_config = &state.conf.generic_link.payout_link; - let profile_config = business_profile - .payout_link_config - .as_ref() - .map(|config| { - config - .clone() - .parse_value::("BusinessPayoutLinkConfig") - }) - .transpose() - .change_context(errors::ApiErrorResponse::InvalidDataValue { - field_name: "payout_link_config in business_profile", - })?; + let profile_config = &business_profile.payout_link_config; let profile_ui_config = profile_config.as_ref().map(|c| c.config.ui_config.clone()); let ui_config = payout_link_config_req .as_ref() diff --git a/crates/router/src/core/webhooks/outgoing.rs b/crates/router/src/core/webhooks/outgoing.rs index 39b9fac33b3e..416075050b3d 100644 --- a/crates/router/src/core/webhooks/outgoing.rs +++ b/crates/router/src/core/webhooks/outgoing.rs @@ -536,17 +536,12 @@ 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, ) -> CustomResult { - let webhook_details_json = business_profile + let webhook_details = business_profile .webhook_details .clone() .get_required_value("webhook_details") .change_context(errors::WebhooksFlowError::MerchantWebhookDetailsNotFound)?; - let webhook_details: api::WebhookDetails = - webhook_details_json - .parse_value("WebhookDetails") - .change_context(errors::WebhooksFlowError::MerchantWebhookDetailsNotFound)?; - webhook_details .webhook_url .get_required_value("webhook_url") diff --git a/crates/router/src/types/api/admin.rs b/crates/router/src/types/api/admin.rs index 683bbd895caf..e7127e5d53bc 100644 --- a/crates/router/src/types/api/admin.rs +++ b/crates/router/src/types/api/admin.rs @@ -17,12 +17,16 @@ use error_stack::ResultExt; use hyperswitch_domain_models::{ merchant_key_store::MerchantKeyStore, type_encryption::decrypt_optional, }; -use masking::{ExposeInterface, PeekInterface, Secret}; +use masking::{ExposeInterface, PeekInterface}; use crate::{ core::errors, routes::SessionState, - types::{domain, storage, transformers::ForeignTryFrom, ForeignFrom}, + types::{ + domain, storage, + transformers::{ForeignInto, ForeignTryFrom}, + ForeignFrom, + }, }; impl ForeignFrom for OrganizationResponse { @@ -63,7 +67,7 @@ impl ForeignTryFrom for MerchantAccountResponse { payment_response_hash_key: item.payment_response_hash_key, redirect_to_merchant_with_http_post: item.redirect_to_merchant_with_http_post, merchant_details: item.merchant_details, - webhook_details: item.webhook_details, + webhook_details: item.webhook_details.clone().map(ForeignInto::foreign_into), routing_algorithm: item.routing_algorithm, sub_merchants_enabled: item.sub_merchants_enabled, parent_merchant_id: item.parent_merchant_id, @@ -141,7 +145,7 @@ pub async fn business_profile_response( 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(Secret::new), + webhook_details: item.webhook_details.map(ForeignInto::foreign_into), metadata: item.metadata, routing_algorithm: item.routing_algorithm, intent_fulfillment_time: item.intent_fulfillment_time, @@ -149,18 +153,12 @@ pub async fn business_profile_response( #[cfg(feature = "payouts")] payout_routing_algorithm: item.payout_routing_algorithm, applepay_verified_domains: item.applepay_verified_domains, - payment_link_config: item.payment_link_config, + payment_link_config: item.payment_link_config.map(ForeignInto::foreign_into), session_expiry: item.session_expiry, authentication_connector_details: item .authentication_connector_details - .map(|authentication_connector_details| { - authentication_connector_details.parse_value("AuthenticationDetails") - }) - .transpose()?, - payout_link_config: item - .payout_link_config - .map(|payout_link_config| payout_link_config.parse_value("BusinessPayoutLinkConfig")) - .transpose()?, + .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 @@ -201,7 +199,7 @@ pub async fn create_business_profile( storage::business_profile::BusinessProfileNew, error_stack::Report, > { - use common_utils::ext_traits::{AsyncExt, Encode}; + use common_utils::ext_traits::AsyncExt; use crate::core; @@ -211,33 +209,14 @@ pub async fn create_business_profile( let current_time = common_utils::date_time::now(); - let webhook_details = request - .webhook_details - .as_ref() - .map(|webhook_details| { - webhook_details.encode_to_value().change_context( - errors::ApiErrorResponse::InvalidDataValue { - field_name: "webhook details", - }, - ) - }) - .transpose()?; + let webhook_details = request.webhook_details.map(ForeignInto::foreign_into); let payment_response_hash_key = request .payment_response_hash_key .or(merchant_account.payment_response_hash_key) .unwrap_or(common_utils::crypto::generate_cryptographically_secure_random_string(64)); - let payment_link_config_value = request - .payment_link_config - .map(|pl_config| { - pl_config - .encode_to_value() - .change_context(errors::ApiErrorResponse::InvalidDataValue { - field_name: "payment_link_config_value", - }) - }) - .transpose()?; + let payment_link_config_value = request.payment_link_config.map(ForeignInto::foreign_into); let outgoing_webhook_custom_http_headers = request .outgoing_webhook_custom_http_headers .async_map(|headers| { @@ -250,13 +229,8 @@ pub async fn create_business_profile( let payout_link_config = request .payout_link_config - .as_ref() .map(|payout_conf| match payout_conf.config.validate() { - Ok(_) => payout_conf.encode_to_value().change_context( - errors::ApiErrorResponse::InvalidDataValue { - field_name: "payout_link_config", - }, - ), + Ok(_) => Ok(payout_conf.foreign_into()), Err(e) => Err(error_stack::report!( errors::ApiErrorResponse::InvalidRequestData { message: e.to_string() @@ -311,12 +285,7 @@ pub async fn create_business_profile( .or(Some(common_utils::consts::DEFAULT_SESSION_EXPIRY)), authentication_connector_details: request .authentication_connector_details - .as_ref() - .map(Encode::encode_to_value) - .transpose() - .change_context(errors::ApiErrorResponse::InvalidDataValue { - field_name: "authentication_connector_details", - })?, + .map(ForeignInto::foreign_into), payout_link_config, is_connector_agnostic_mit_enabled: request.is_connector_agnostic_mit_enabled, is_extended_card_info_enabled: None, diff --git a/crates/router/src/types/storage/business_profile.rs b/crates/router/src/types/storage/business_profile.rs index d7c7d66b99ef..4780b3d032fd 100644 --- a/crates/router/src/types/storage/business_profile.rs +++ b/crates/router/src/types/storage/business_profile.rs @@ -1,3 +1,4 @@ pub use diesel_models::business_profile::{ - BusinessProfile, BusinessProfileNew, BusinessProfileUpdate, BusinessProfileUpdateInternal, + BusinessProfile, BusinessProfileGeneralUpdate, BusinessProfileNew, BusinessProfileUpdate, + BusinessProfileUpdateInternal, }; diff --git a/crates/router/src/types/transformers.rs b/crates/router/src/types/transformers.rs index 467867ef8406..da6f35305b6d 100644 --- a/crates/router/src/types/transformers.rs +++ b/crates/router/src/types/transformers.rs @@ -1622,3 +1622,165 @@ impl TryFrom for api_models::webhook_events::EventRetrieveRespons }) } } + +impl ForeignFrom + for diesel_models::business_profile::AuthenticationConnectorDetails +{ + fn foreign_from(item: api_models::admin::AuthenticationConnectorDetails) -> Self { + Self { + authentication_connectors: item.authentication_connectors, + three_ds_requestor_url: item.three_ds_requestor_url, + } + } +} + +impl ForeignFrom + for api_models::admin::AuthenticationConnectorDetails +{ + fn foreign_from(item: diesel_models::business_profile::AuthenticationConnectorDetails) -> Self { + Self { + authentication_connectors: item.authentication_connectors, + three_ds_requestor_url: item.three_ds_requestor_url, + } + } +} + +impl ForeignFrom + for diesel_models::business_profile::WebhookDetails +{ + fn foreign_from(item: api_models::admin::WebhookDetails) -> Self { + Self { + webhook_version: item.webhook_version, + webhook_username: item.webhook_username, + webhook_password: item.webhook_password, + webhook_url: item.webhook_url, + payment_created_enabled: item.payment_created_enabled, + payment_succeeded_enabled: item.payment_succeeded_enabled, + payment_failed_enabled: item.payment_failed_enabled, + } + } +} + +impl ForeignFrom + for api_models::admin::WebhookDetails +{ + fn foreign_from(item: diesel_models::business_profile::WebhookDetails) -> Self { + Self { + webhook_version: item.webhook_version, + webhook_username: item.webhook_username, + webhook_password: item.webhook_password, + webhook_url: item.webhook_url, + payment_created_enabled: item.payment_created_enabled, + payment_succeeded_enabled: item.payment_succeeded_enabled, + payment_failed_enabled: item.payment_failed_enabled, + } + } +} + +impl ForeignFrom + for diesel_models::business_profile::BusinessPaymentLinkConfig +{ + fn foreign_from(item: api_models::admin::BusinessPaymentLinkConfig) -> Self { + Self { + domain_name: item.domain_name, + default_config: item.default_config.map(ForeignInto::foreign_into), + business_specific_configs: item.business_specific_configs.map(|map| { + map.into_iter() + .map(|(k, v)| (k, v.foreign_into())) + .collect() + }), + allowed_domains: item.allowed_domains, + } + } +} + +impl ForeignFrom + for api_models::admin::BusinessPaymentLinkConfig +{ + fn foreign_from(item: diesel_models::business_profile::BusinessPaymentLinkConfig) -> Self { + Self { + domain_name: item.domain_name, + default_config: item.default_config.map(ForeignInto::foreign_into), + business_specific_configs: item.business_specific_configs.map(|map| { + map.into_iter() + .map(|(k, v)| (k, v.foreign_into())) + .collect() + }), + allowed_domains: item.allowed_domains, + } + } +} + +impl ForeignFrom + for diesel_models::business_profile::PaymentLinkConfigRequest +{ + fn foreign_from(item: api_models::admin::PaymentLinkConfigRequest) -> Self { + Self { + theme: item.theme, + logo: item.logo, + seller_name: item.seller_name, + sdk_layout: item.sdk_layout, + display_sdk_only: item.display_sdk_only, + enabled_saved_payment_method: item.enabled_saved_payment_method, + } + } +} + +impl ForeignFrom + for api_models::admin::PaymentLinkConfigRequest +{ + fn foreign_from(item: diesel_models::business_profile::PaymentLinkConfigRequest) -> Self { + Self { + theme: item.theme, + logo: item.logo, + seller_name: item.seller_name, + sdk_layout: item.sdk_layout, + display_sdk_only: item.display_sdk_only, + enabled_saved_payment_method: item.enabled_saved_payment_method, + } + } +} + +impl ForeignFrom + for diesel_models::business_profile::BusinessPayoutLinkConfig +{ + fn foreign_from(item: api_models::admin::BusinessPayoutLinkConfig) -> Self { + Self { + config: item.config.foreign_into(), + } + } +} + +impl ForeignFrom + for api_models::admin::BusinessPayoutLinkConfig +{ + fn foreign_from(item: diesel_models::business_profile::BusinessPayoutLinkConfig) -> Self { + Self { + config: item.config.foreign_into(), + } + } +} + +impl ForeignFrom + for diesel_models::business_profile::BusinessGenericLinkConfig +{ + fn foreign_from(item: api_models::admin::BusinessGenericLinkConfig) -> Self { + Self { + domain_name: item.domain_name, + allowed_domains: item.allowed_domains, + ui_config: item.ui_config, + } + } +} + +impl ForeignFrom + for api_models::admin::BusinessGenericLinkConfig +{ + fn foreign_from(item: diesel_models::business_profile::BusinessGenericLinkConfig) -> Self { + Self { + domain_name: item.domain_name, + allowed_domains: item.allowed_domains, + ui_config: item.ui_config, + } + } +}