diff --git a/api-reference-v2/openapi_spec.json b/api-reference-v2/openapi_spec.json index 2ea0f42a7f..6c3e9f5072 100644 --- a/api-reference-v2/openapi_spec.json +++ b/api-reference-v2/openapi_spec.json @@ -17762,6 +17762,11 @@ "description": "Indicates if click to pay is enabled or not.", "default": false, "example": false + }, + "authentication_product_ids": { + "type": "object", + "description": "Product authentication ids", + "nullable": true } }, "additionalProperties": false @@ -17981,6 +17986,11 @@ "description": "Indicates if click to pay is enabled or not.", "default": false, "example": false + }, + "authentication_product_ids": { + "type": "object", + "description": "Product authentication ids", + "nullable": true } } }, diff --git a/api-reference/openapi_spec.json b/api-reference/openapi_spec.json index 832f8da9c4..ce383f2406 100644 --- a/api-reference/openapi_spec.json +++ b/api-reference/openapi_spec.json @@ -21748,6 +21748,11 @@ "is_click_to_pay_enabled": { "type": "boolean", "description": "Indicates if click to pay is enabled or not." + }, + "authentication_product_ids": { + "type": "object", + "description": "Product authentication ids", + "nullable": true } }, "additionalProperties": false @@ -21984,6 +21989,11 @@ "description": "Indicates if click to pay is enabled or not.", "default": false, "example": false + }, + "authentication_product_ids": { + "type": "object", + "description": "Product authentication ids", + "nullable": true } } }, diff --git a/crates/api_models/src/admin.rs b/crates/api_models/src/admin.rs index 53ce867896..769ef59280 100644 --- a/crates/api_models/src/admin.rs +++ b/crates/api_models/src/admin.rs @@ -1970,6 +1970,10 @@ pub struct ProfileCreate { /// Indicates if click to pay is enabled or not. #[serde(default)] pub is_click_to_pay_enabled: bool, + + /// Product authentication ids + #[schema(value_type = Option, example = r#"{ "key1": "value-1", "key2": "value-2" }"#)] + pub authentication_product_ids: Option>, } #[nutype::nutype( @@ -2082,6 +2086,10 @@ pub struct ProfileCreate { /// Indicates if click to pay is enabled or not. #[schema(default = false, example = false)] pub is_click_to_pay_enabled: bool, + + /// Product authentication ids + #[schema(value_type = Option, example = r#"{ "key1": "value-1", "key2": "value-2" }"#)] + pub authentication_product_ids: Option>, } #[cfg(feature = "v1")] @@ -2214,6 +2222,10 @@ pub struct ProfileResponse { /// Indicates if click to pay is enabled or not. #[schema(default = false, example = false)] pub is_click_to_pay_enabled: bool, + + /// Product authentication ids + #[schema(value_type = Option, example = r#"{ "key1": "value-1", "key2": "value-2" }"#)] + pub authentication_product_ids: Option, } #[cfg(feature = "v2")] @@ -2333,6 +2345,10 @@ pub struct ProfileResponse { /// Indicates if click to pay is enabled or not. #[schema(default = false, example = false)] pub is_click_to_pay_enabled: bool, + + /// Product authentication ids + #[schema(value_type = Option, example = r#"{ "key1": "value-1", "key2": "value-2" }"#)] + pub authentication_product_ids: Option, } #[cfg(feature = "v1")] @@ -2459,6 +2475,10 @@ pub struct ProfileUpdate { /// Indicates if click to pay is enabled or not. #[schema(default = false, example = false)] pub is_click_to_pay_enabled: Option, + + /// Product authentication ids + #[schema(value_type = Option, example = r#"{ "key1": "value-1", "key2": "value-2" }"#)] + pub authentication_product_ids: Option>, } #[cfg(feature = "v2")] @@ -2566,6 +2586,10 @@ pub struct ProfileUpdate { /// Indicates if click to pay is enabled or not. #[schema(default = false, example = false)] pub is_click_to_pay_enabled: Option, + + /// Product authentication ids + #[schema(value_type = Option, example = r#"{ "key1": "value-1", "key2": "value-2" }"#)] + pub authentication_product_ids: Option>, } #[derive(Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)] diff --git a/crates/diesel_models/src/business_profile.rs b/crates/diesel_models/src/business_profile.rs index 484a1c0c69..0cae67873d 100644 --- a/crates/diesel_models/src/business_profile.rs +++ b/crates/diesel_models/src/business_profile.rs @@ -58,6 +58,7 @@ pub struct Profile { pub is_auto_retries_enabled: Option, pub max_auto_retries_enabled: Option, pub is_click_to_pay_enabled: bool, + pub authentication_product_ids: Option, } #[cfg(feature = "v1")] @@ -102,6 +103,7 @@ pub struct ProfileNew { pub is_auto_retries_enabled: Option, pub max_auto_retries_enabled: Option, pub is_click_to_pay_enabled: bool, + pub authentication_product_ids: Option, } #[cfg(feature = "v1")] @@ -143,6 +145,7 @@ pub struct ProfileUpdateInternal { pub is_auto_retries_enabled: Option, pub max_auto_retries_enabled: Option, pub is_click_to_pay_enabled: Option, + pub authentication_product_ids: Option, } #[cfg(feature = "v1")] @@ -183,6 +186,7 @@ impl ProfileUpdateInternal { is_auto_retries_enabled, max_auto_retries_enabled, is_click_to_pay_enabled, + authentication_product_ids, } = self; Profile { profile_id: source.profile_id, @@ -244,6 +248,8 @@ impl ProfileUpdateInternal { max_auto_retries_enabled: max_auto_retries_enabled.or(source.max_auto_retries_enabled), is_click_to_pay_enabled: is_click_to_pay_enabled .unwrap_or(source.is_click_to_pay_enabled), + authentication_product_ids: authentication_product_ids + .or(source.authentication_product_ids), } } } @@ -299,6 +305,7 @@ pub struct Profile { pub is_auto_retries_enabled: Option, pub max_auto_retries_enabled: Option, pub is_click_to_pay_enabled: bool, + pub authentication_product_ids: Option, } impl Profile { @@ -358,6 +365,7 @@ pub struct ProfileNew { pub is_auto_retries_enabled: Option, pub max_auto_retries_enabled: Option, pub is_click_to_pay_enabled: bool, + pub authentication_product_ids: Option, } #[cfg(feature = "v2")] @@ -401,6 +409,7 @@ pub struct ProfileUpdateInternal { pub is_auto_retries_enabled: Option, pub max_auto_retries_enabled: Option, pub is_click_to_pay_enabled: Option, + pub authentication_product_ids: Option, } #[cfg(feature = "v2")] @@ -443,6 +452,7 @@ impl ProfileUpdateInternal { is_auto_retries_enabled, max_auto_retries_enabled, is_click_to_pay_enabled, + authentication_product_ids, } = self; Profile { id: source.id, @@ -509,6 +519,8 @@ impl ProfileUpdateInternal { max_auto_retries_enabled: max_auto_retries_enabled.or(source.max_auto_retries_enabled), is_click_to_pay_enabled: is_click_to_pay_enabled .unwrap_or(source.is_click_to_pay_enabled), + authentication_product_ids: authentication_product_ids + .or(source.authentication_product_ids), } } } diff --git a/crates/diesel_models/src/schema.rs b/crates/diesel_models/src/schema.rs index 82f1ffed1d..bb2aea0701 100644 --- a/crates/diesel_models/src/schema.rs +++ b/crates/diesel_models/src/schema.rs @@ -215,6 +215,7 @@ diesel::table! { is_auto_retries_enabled -> Nullable, max_auto_retries_enabled -> Nullable, is_click_to_pay_enabled -> Bool, + authentication_product_ids -> Nullable, } } diff --git a/crates/diesel_models/src/schema_v2.rs b/crates/diesel_models/src/schema_v2.rs index 6c91e258de..9960b136e7 100644 --- a/crates/diesel_models/src/schema_v2.rs +++ b/crates/diesel_models/src/schema_v2.rs @@ -223,6 +223,7 @@ diesel::table! { is_auto_retries_enabled -> Nullable, max_auto_retries_enabled -> Nullable, is_click_to_pay_enabled -> Bool, + authentication_product_ids -> Nullable, } } diff --git a/crates/hyperswitch_domain_models/src/business_profile.rs b/crates/hyperswitch_domain_models/src/business_profile.rs index 433353b2f8..1df474f18d 100644 --- a/crates/hyperswitch_domain_models/src/business_profile.rs +++ b/crates/hyperswitch_domain_models/src/business_profile.rs @@ -59,6 +59,7 @@ pub struct Profile { pub is_auto_retries_enabled: bool, pub max_auto_retries_enabled: Option, pub is_click_to_pay_enabled: bool, + pub authentication_product_ids: Option, } #[cfg(feature = "v1")] @@ -100,6 +101,7 @@ pub struct ProfileSetter { pub is_auto_retries_enabled: bool, pub max_auto_retries_enabled: Option, pub is_click_to_pay_enabled: bool, + pub authentication_product_ids: Option, } #[cfg(feature = "v1")] @@ -148,6 +150,7 @@ impl From for Profile { is_auto_retries_enabled: value.is_auto_retries_enabled, max_auto_retries_enabled: value.max_auto_retries_enabled, is_click_to_pay_enabled: value.is_click_to_pay_enabled, + authentication_product_ids: value.authentication_product_ids, } } } @@ -198,6 +201,7 @@ pub struct ProfileGeneralUpdate { pub is_auto_retries_enabled: Option, pub max_auto_retries_enabled: Option, pub is_click_to_pay_enabled: Option, + pub authentication_product_ids: Option, } #[cfg(feature = "v1")] @@ -261,6 +265,7 @@ impl From for ProfileUpdateInternal { is_auto_retries_enabled, max_auto_retries_enabled, is_click_to_pay_enabled, + authentication_product_ids, } = *update; Self { @@ -299,6 +304,7 @@ impl From for ProfileUpdateInternal { is_auto_retries_enabled, max_auto_retries_enabled, is_click_to_pay_enabled, + authentication_product_ids, } } ProfileUpdate::RoutingAlgorithmUpdate { @@ -339,6 +345,7 @@ impl From for ProfileUpdateInternal { is_auto_retries_enabled: None, max_auto_retries_enabled: None, is_click_to_pay_enabled: None, + authentication_product_ids: None, }, ProfileUpdate::DynamicRoutingAlgorithmUpdate { dynamic_routing_algorithm, @@ -377,6 +384,7 @@ impl From for ProfileUpdateInternal { is_auto_retries_enabled: None, max_auto_retries_enabled: None, is_click_to_pay_enabled: None, + authentication_product_ids: None, }, ProfileUpdate::ExtendedCardInfoUpdate { is_extended_card_info_enabled, @@ -415,6 +423,7 @@ impl From for ProfileUpdateInternal { is_auto_retries_enabled: None, max_auto_retries_enabled: None, is_click_to_pay_enabled: None, + authentication_product_ids: None, }, ProfileUpdate::ConnectorAgnosticMitUpdate { is_connector_agnostic_mit_enabled, @@ -453,6 +462,7 @@ impl From for ProfileUpdateInternal { is_auto_retries_enabled: None, max_auto_retries_enabled: None, is_click_to_pay_enabled: None, + authentication_product_ids: None, }, ProfileUpdate::NetworkTokenizationUpdate { is_network_tokenization_enabled, @@ -491,6 +501,7 @@ impl From for ProfileUpdateInternal { is_auto_retries_enabled: None, max_auto_retries_enabled: None, is_click_to_pay_enabled: None, + authentication_product_ids: None, }, } } @@ -548,6 +559,7 @@ impl super::behaviour::Conversion for Profile { is_auto_retries_enabled: Some(self.is_auto_retries_enabled), max_auto_retries_enabled: self.max_auto_retries_enabled, is_click_to_pay_enabled: self.is_click_to_pay_enabled, + authentication_product_ids: self.authentication_product_ids, }) } @@ -617,6 +629,7 @@ impl super::behaviour::Conversion for Profile { is_auto_retries_enabled: item.is_auto_retries_enabled.unwrap_or(false), max_auto_retries_enabled: item.max_auto_retries_enabled, is_click_to_pay_enabled: item.is_click_to_pay_enabled, + authentication_product_ids: item.authentication_product_ids, }) } .await @@ -670,6 +683,7 @@ impl super::behaviour::Conversion for Profile { is_auto_retries_enabled: Some(self.is_auto_retries_enabled), max_auto_retries_enabled: self.max_auto_retries_enabled, is_click_to_pay_enabled: self.is_click_to_pay_enabled, + authentication_product_ids: self.authentication_product_ids, }) } } @@ -715,6 +729,7 @@ pub struct Profile { pub version: common_enums::ApiVersion, pub is_network_tokenization_enabled: bool, pub is_click_to_pay_enabled: bool, + pub authentication_product_ids: Option, } #[cfg(feature = "v2")] @@ -756,6 +771,7 @@ pub struct ProfileSetter { pub is_tax_connector_enabled: bool, pub is_network_tokenization_enabled: bool, pub is_click_to_pay_enabled: bool, + pub authentication_product_ids: Option, } #[cfg(feature = "v2")] @@ -804,6 +820,7 @@ impl From for Profile { version: consts::API_VERSION, is_network_tokenization_enabled: value.is_network_tokenization_enabled, is_click_to_pay_enabled: value.is_click_to_pay_enabled, + authentication_product_ids: value.authentication_product_ids, } } } @@ -855,6 +872,7 @@ pub struct ProfileGeneralUpdate { pub order_fulfillment_time_origin: Option, pub is_network_tokenization_enabled: Option, pub is_click_to_pay_enabled: Option, + pub authentication_product_ids: Option, } #[cfg(feature = "v2")] @@ -914,6 +932,7 @@ impl From for ProfileUpdateInternal { order_fulfillment_time_origin, is_network_tokenization_enabled, is_click_to_pay_enabled, + authentication_product_ids, } = *update; Self { profile_name, @@ -952,7 +971,8 @@ impl From for ProfileUpdateInternal { is_network_tokenization_enabled, is_auto_retries_enabled: None, max_auto_retries_enabled: None, - is_click_to_pay_enabled, + is_click_to_pay_enabled: None, + authentication_product_ids, } } ProfileUpdate::RoutingAlgorithmUpdate { @@ -995,6 +1015,7 @@ impl From for ProfileUpdateInternal { is_auto_retries_enabled: None, max_auto_retries_enabled: None, is_click_to_pay_enabled: None, + authentication_product_ids: None, }, ProfileUpdate::ExtendedCardInfoUpdate { is_extended_card_info_enabled, @@ -1035,6 +1056,7 @@ impl From for ProfileUpdateInternal { is_auto_retries_enabled: None, max_auto_retries_enabled: None, is_click_to_pay_enabled: None, + authentication_product_ids: None, }, ProfileUpdate::ConnectorAgnosticMitUpdate { is_connector_agnostic_mit_enabled, @@ -1075,6 +1097,7 @@ impl From for ProfileUpdateInternal { is_auto_retries_enabled: None, max_auto_retries_enabled: None, is_click_to_pay_enabled: None, + authentication_product_ids: None, }, ProfileUpdate::DefaultRoutingFallbackUpdate { default_fallback_routing, @@ -1115,6 +1138,7 @@ impl From for ProfileUpdateInternal { is_auto_retries_enabled: None, max_auto_retries_enabled: None, is_click_to_pay_enabled: None, + authentication_product_ids: None, }, ProfileUpdate::NetworkTokenizationUpdate { is_network_tokenization_enabled, @@ -1155,6 +1179,7 @@ impl From for ProfileUpdateInternal { is_auto_retries_enabled: None, max_auto_retries_enabled: None, is_click_to_pay_enabled: None, + authentication_product_ids: None, }, ProfileUpdate::CollectCvvDuringPaymentUpdate { should_collect_cvv_during_payment, @@ -1195,6 +1220,7 @@ impl From for ProfileUpdateInternal { is_auto_retries_enabled: None, max_auto_retries_enabled: None, is_click_to_pay_enabled: None, + authentication_product_ids: None, }, } } @@ -1255,6 +1281,7 @@ impl super::behaviour::Conversion for Profile { is_auto_retries_enabled: None, max_auto_retries_enabled: None, is_click_to_pay_enabled: self.is_click_to_pay_enabled, + authentication_product_ids: self.authentication_product_ids, }) } @@ -1324,6 +1351,7 @@ impl super::behaviour::Conversion for Profile { version: item.version, is_network_tokenization_enabled: item.is_network_tokenization_enabled, is_click_to_pay_enabled: item.is_click_to_pay_enabled, + authentication_product_ids: item.authentication_product_ids, }) } .await @@ -1380,6 +1408,7 @@ impl super::behaviour::Conversion for Profile { is_auto_retries_enabled: None, max_auto_retries_enabled: None, is_click_to_pay_enabled: self.is_click_to_pay_enabled, + authentication_product_ids: self.authentication_product_ids, }) } } diff --git a/crates/router/src/core/admin.rs b/crates/router/src/core/admin.rs index 8e21450711..6cca6e9001 100644 --- a/crates/router/src/core/admin.rs +++ b/crates/router/src/core/admin.rs @@ -3622,6 +3622,13 @@ impl ProfileCreateBridge for api::ProfileCreate { }) .transpose()?; + let authentication_product_ids = self + .authentication_product_ids + .map(serde_json::to_value) + .transpose() + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("failed to parse product authentication id's to value")?; + Ok(domain::Profile::from(domain::ProfileSetter { profile_id, merchant_id: merchant_account.get_id().clone(), @@ -3692,6 +3699,7 @@ impl ProfileCreateBridge for api::ProfileCreate { is_auto_retries_enabled: self.is_auto_retries_enabled.unwrap_or_default(), max_auto_retries_enabled: self.max_auto_retries_enabled.map(i16::from), is_click_to_pay_enabled: self.is_click_to_pay_enabled, + authentication_product_ids, })) } @@ -3743,6 +3751,13 @@ impl ProfileCreateBridge for api::ProfileCreate { }) .transpose()?; + let authentication_product_ids = self + .authentication_product_ids + .map(serde_json::to_value) + .transpose() + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("failed to parse product authentication id's to value")?; + Ok(domain::Profile::from(domain::ProfileSetter { id: profile_id, merchant_id: merchant_id.clone(), @@ -3800,6 +3815,7 @@ impl ProfileCreateBridge for api::ProfileCreate { is_tax_connector_enabled: self.is_tax_connector_enabled, is_network_tokenization_enabled: self.is_network_tokenization_enabled, is_click_to_pay_enabled: self.is_click_to_pay_enabled, + authentication_product_ids, })) } } @@ -4007,6 +4023,13 @@ impl ProfileUpdateBridge for api::ProfileUpdate { }) .transpose()?; + let authentication_product_ids = self + .authentication_product_ids + .map(serde_json::to_value) + .transpose() + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("failed to parse product authentication id's to value")?; + Ok(domain::ProfileUpdate::Update(Box::new( domain::ProfileGeneralUpdate { profile_name: self.profile_name, @@ -4050,6 +4073,7 @@ impl ProfileUpdateBridge for api::ProfileUpdate { is_auto_retries_enabled: self.is_auto_retries_enabled, max_auto_retries_enabled: self.max_auto_retries_enabled.map(i16::from), is_click_to_pay_enabled: self.is_click_to_pay_enabled, + authentication_product_ids, }, ))) } @@ -4112,6 +4136,13 @@ impl ProfileUpdateBridge for api::ProfileUpdate { }) .transpose()?; + let authentication_product_ids = self + .authentication_product_ids + .map(serde_json::to_value) + .transpose() + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("failed to parse product authentication id's to value")?; + Ok(domain::ProfileUpdate::Update(Box::new( domain::ProfileGeneralUpdate { profile_name: self.profile_name, @@ -4147,6 +4178,7 @@ impl ProfileUpdateBridge for api::ProfileUpdate { .always_collect_shipping_details_from_wallet_connector, is_network_tokenization_enabled: self.is_network_tokenization_enabled, is_click_to_pay_enabled: self.is_click_to_pay_enabled, + authentication_product_ids, }, ))) } diff --git a/crates/router/src/types/api/admin.rs b/crates/router/src/types/api/admin.rs index 7207f63aa0..40d90125ba 100644 --- a/crates/router/src/types/api/admin.rs +++ b/crates/router/src/types/api/admin.rs @@ -175,6 +175,7 @@ impl ForeignTryFrom for ProfileResponse { is_auto_retries_enabled: item.is_auto_retries_enabled, max_auto_retries_enabled: item.max_auto_retries_enabled, is_click_to_pay_enabled: item.is_click_to_pay_enabled, + authentication_product_ids: item.authentication_product_ids, }) } } @@ -243,6 +244,7 @@ impl ForeignTryFrom for ProfileResponse { is_tax_connector_enabled: item.is_tax_connector_enabled, is_network_tokenization_enabled: item.is_network_tokenization_enabled, is_click_to_pay_enabled: item.is_click_to_pay_enabled, + authentication_product_ids: item.authentication_product_ids, }) } } @@ -299,6 +301,13 @@ pub async fn create_profile_from_merchant_account( }) .transpose()?; + let authentication_product_ids = request + .authentication_product_ids + .map(serde_json::to_value) + .transpose() + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("failed to parse product authentication id's to value")?; + Ok(domain::Profile::from(domain::ProfileSetter { profile_id, merchant_id, @@ -370,5 +379,6 @@ pub async fn create_profile_from_merchant_account( is_auto_retries_enabled: request.is_auto_retries_enabled.unwrap_or_default(), max_auto_retries_enabled: request.max_auto_retries_enabled.map(i16::from), is_click_to_pay_enabled: request.is_click_to_pay_enabled, + authentication_product_ids, })) } diff --git a/migrations/2024-12-11-092649_add-authentication-product-ids-in-business-profile/down.sql b/migrations/2024-12-11-092649_add-authentication-product-ids-in-business-profile/down.sql new file mode 100644 index 0000000000..a353beb4e4 --- /dev/null +++ b/migrations/2024-12-11-092649_add-authentication-product-ids-in-business-profile/down.sql @@ -0,0 +1,3 @@ +-- This file should undo anything in `up.sql` +ALTER TABLE business_profile +DROP COLUMN IF EXISTS authentication_product_ids diff --git a/migrations/2024-12-11-092649_add-authentication-product-ids-in-business-profile/up.sql b/migrations/2024-12-11-092649_add-authentication-product-ids-in-business-profile/up.sql new file mode 100644 index 0000000000..4e94da05c0 --- /dev/null +++ b/migrations/2024-12-11-092649_add-authentication-product-ids-in-business-profile/up.sql @@ -0,0 +1,3 @@ +-- Your SQL goes here +ALTER TABLE business_profile +ADD COLUMN IF NOT EXISTS authentication_product_ids JSONB NULL;