From d33e344f82ca63e217c54893816218d60166a6cd Mon Sep 17 00:00:00 2001 From: Sahkal Poddar Date: Thu, 12 Jun 2025 17:39:15 +0530 Subject: [PATCH] feat(authentication): create api for update profile acquirer (#8307) Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com> --- api-reference/openapi_spec.json | 112 ++++++++++++++- crates/api_models/src/admin.rs | 5 +- crates/api_models/src/profile_acquirer.rs | 51 ++++++- .../src/id_type/profile_acquirer.rs | 12 ++ .../src/errors/api_error_response.rs | 8 ++ crates/openapi/src/openapi.rs | 2 + crates/openapi/src/routes/profile_acquirer.rs | 23 +++ .../router/src/compatibility/stripe/errors.rs | 6 + crates/router/src/core/profile_acquirer.rs | 132 ++++++++++++++++-- crates/router/src/routes/app.rs | 4 + crates/router/src/routes/lock_utils.rs | 2 +- crates/router/src/routes/profile_acquirer.rs | 49 ++++++- crates/router/src/types/api/admin.rs | 34 ++++- crates/router_env/src/logger/types.rs | 1 + 14 files changed, 417 insertions(+), 24 deletions(-) diff --git a/api-reference/openapi_spec.json b/api-reference/openapi_spec.json index c80a698d62..d12b7b3be1 100644 --- a/api-reference/openapi_spec.json +++ b/api-reference/openapi_spec.json @@ -5997,6 +5997,66 @@ ] } }, + "/profile_acquirers/{profile_id}/{profile_acquirer_id}": { + "post": { + "tags": [ + "Profile Acquirer" + ], + "summary": "Profile Acquirer - Update", + "description": "Update a Profile Acquirer for accessing our APIs from your servers.", + "operationId": "Update a Profile Acquirer", + "parameters": [ + { + "name": "profile_id", + "in": "path", + "description": "The unique identifier for the Profile", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "profile_acquirer_id", + "in": "path", + "description": "The unique identifier for the Profile Acquirer", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProfileAcquirerUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Profile Acquirer updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProfileAcquirerResponse" + } + } + } + }, + "400": { + "description": "Invalid data" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, "/three_ds_decision/execute": { "post": { "tags": [ @@ -25552,6 +25612,48 @@ } } }, + "ProfileAcquirerUpdate": { + "type": "object", + "properties": { + "acquirer_assigned_merchant_id": { + "type": "string", + "example": "M987654321", + "nullable": true + }, + "merchant_name": { + "type": "string", + "example": "Updated Retailer Name", + "nullable": true + }, + "merchant_country_code": { + "type": "string", + "example": "CA", + "nullable": true + }, + "network": { + "type": "string", + "example": "MASTERCARD", + "nullable": true + }, + "acquirer_bin": { + "type": "string", + "example": "987654", + "nullable": true + }, + "acquirer_ica": { + "type": "string", + "example": "501299", + "nullable": true + }, + "acquirer_fraud_rate": { + "type": "number", + "format": "double", + "example": "0.02", + "nullable": true + } + }, + "additionalProperties": false + }, "ProfileCreate": { "type": "object", "properties": { @@ -26083,11 +26185,11 @@ "example": false }, "acquirer_configs": { - "allOf": [ - { - "$ref": "#/components/schemas/AcquirerConfigMap" - } - ], + "type": "array", + "items": { + "$ref": "#/components/schemas/ProfileAcquirerResponse" + }, + "description": "Acquirer configs", "nullable": true }, "is_iframe_redirection_enabled": { diff --git a/crates/api_models/src/admin.rs b/crates/api_models/src/admin.rs index d30abfe813..50ae919d4f 100644 --- a/crates/api_models/src/admin.rs +++ b/crates/api_models/src/admin.rs @@ -22,6 +22,7 @@ use crate::routing; use crate::{ consts::{MAX_ORDER_FULFILLMENT_EXPIRY, MIN_ORDER_FULFILLMENT_EXPIRY}, enums as api_enums, payment_methods, + profile_acquirer::ProfileAcquirerResponse, }; #[derive(Clone, Debug, Deserialize, ToSchema, Serialize)] @@ -2436,8 +2437,8 @@ pub struct ProfileResponse { pub is_pre_network_tokenization_enabled: bool, /// Acquirer configs - #[schema(value_type = Option)] - pub acquirer_configs: Option, + #[schema(value_type = Option>)] + pub acquirer_configs: Option>, /// Indicates if the redirection has to open in the iframe #[schema(example = false)] diff --git a/crates/api_models/src/profile_acquirer.rs b/crates/api_models/src/profile_acquirer.rs index 86f36db104..9b53c1844b 100644 --- a/crates/api_models/src/profile_acquirer.rs +++ b/crates/api_models/src/profile_acquirer.rs @@ -31,7 +31,7 @@ pub struct ProfileAcquirerCreate { pub profile_id: common_utils::id_type::ProfileId, } -#[derive(Debug, Serialize, Deserialize, ToSchema)] +#[derive(Debug, Serialize, Deserialize, ToSchema, Clone)] pub struct ProfileAcquirerResponse { /// The unique identifier of the profile acquirer #[schema(value_type= String,example = "pro_acq_LCRdERuylQvNQ4qh3QE0")] @@ -64,3 +64,52 @@ pub struct ProfileAcquirerResponse { impl common_utils::events::ApiEventMetric for ProfileAcquirerCreate {} impl common_utils::events::ApiEventMetric for ProfileAcquirerResponse {} + +impl + From<( + common_utils::id_type::ProfileAcquirerId, + &common_utils::id_type::ProfileId, + &common_types::domain::AcquirerConfig, + )> for ProfileAcquirerResponse +{ + fn from( + (profile_acquirer_id, profile_id, acquirer_config): ( + common_utils::id_type::ProfileAcquirerId, + &common_utils::id_type::ProfileId, + &common_types::domain::AcquirerConfig, + ), + ) -> Self { + Self { + profile_acquirer_id, + profile_id: profile_id.clone(), + acquirer_assigned_merchant_id: acquirer_config.acquirer_assigned_merchant_id.clone(), + merchant_name: acquirer_config.merchant_name.clone(), + merchant_country_code: acquirer_config.merchant_country_code, + network: acquirer_config.network.clone(), + acquirer_bin: acquirer_config.acquirer_bin.clone(), + acquirer_ica: acquirer_config.acquirer_ica.clone(), + acquirer_fraud_rate: acquirer_config.acquirer_fraud_rate, + } + } +} + +#[derive(Debug, Serialize, Deserialize, ToSchema)] +#[serde(deny_unknown_fields)] +pub struct ProfileAcquirerUpdate { + #[schema(value_type = Option, example = "M987654321")] + pub acquirer_assigned_merchant_id: Option, + #[schema(value_type = Option, example = "Updated Retailer Name")] + pub merchant_name: Option, + #[schema(value_type = Option, example = "CA")] + pub merchant_country_code: Option, + #[schema(value_type = Option, example = "MASTERCARD")] + pub network: Option, + #[schema(value_type = Option, example = "987654")] + pub acquirer_bin: Option, + #[schema(value_type = Option, example = "501299")] + pub acquirer_ica: Option, + #[schema(value_type = Option, example = "0.02")] + pub acquirer_fraud_rate: Option, +} + +impl common_utils::events::ApiEventMetric for ProfileAcquirerUpdate {} diff --git a/crates/common_utils/src/id_type/profile_acquirer.rs b/crates/common_utils/src/id_type/profile_acquirer.rs index ac5f09646b..8541e04dee 100644 --- a/crates/common_utils/src/id_type/profile_acquirer.rs +++ b/crates/common_utils/src/id_type/profile_acquirer.rs @@ -15,6 +15,18 @@ crate::impl_serializable_secret_id_type!(ProfileAcquirerId); crate::impl_queryable_id_type!(ProfileAcquirerId); crate::impl_to_sql_from_sql_id_type!(ProfileAcquirerId); +impl Ord for ProfileAcquirerId { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.0 .0 .0.cmp(&other.0 .0 .0) + } +} + +impl PartialOrd for ProfileAcquirerId { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + impl crate::events::ApiEventMetric for ProfileAcquirerId { fn get_api_event_type(&self) -> Option { Some(crate::events::ApiEventsType::ProfileAcquirer { diff --git a/crates/hyperswitch_domain_models/src/errors/api_error_response.rs b/crates/hyperswitch_domain_models/src/errors/api_error_response.rs index 6066674bd2..86e12d2aca 100644 --- a/crates/hyperswitch_domain_models/src/errors/api_error_response.rs +++ b/crates/hyperswitch_domain_models/src/errors/api_error_response.rs @@ -101,6 +101,11 @@ pub enum ApiErrorResponse { MerchantConnectorAccountNotFound { id: String }, #[error(error_type = ErrorType::ObjectNotFound, code = "HE_02", message = "Business profile with the given id '{id}' does not exist in our records")] ProfileNotFound { id: String }, + #[error(error_type = ErrorType::ObjectNotFound, code = "HE_02", message = "Profile acquirer with id '{profile_acquirer_id}' not found for profile '{profile_id}'.")] + ProfileAcquirerNotFound { + profile_acquirer_id: String, + profile_id: String, + }, #[error(error_type = ErrorType::ObjectNotFound, code = "HE_02", message = "Poll with the given id '{id}' does not exist in our records")] PollNotFound { id: String }, #[error(error_type = ErrorType::ObjectNotFound, code = "HE_02", message = "Resource ID does not exist in our records")] @@ -421,6 +426,9 @@ impl ErrorSwitch for ApiErrorRespon Self::ProfileNotFound { id } => { AER::NotFound(ApiError::new("HE", 2, format!("Business profile with the given id {id} does not exist"), None)) } + Self::ProfileAcquirerNotFound { profile_acquirer_id, profile_id } => { + AER::NotFound(ApiError::new("HE", 2, format!("Profile acquirer with id '{profile_acquirer_id}' not found for profile '{profile_id}'."), None)) + } Self::PollNotFound { .. } => { AER::NotFound(ApiError::new("HE", 2, "Poll does not exist in our records", None)) }, diff --git a/crates/openapi/src/openapi.rs b/crates/openapi/src/openapi.rs index 6738824b05..03b70f0b78 100644 --- a/crates/openapi/src/openapi.rs +++ b/crates/openapi/src/openapi.rs @@ -205,6 +205,7 @@ Never share your secret api keys. Keep them guarded and secure. // Routes for profile acquirer account routes::profile_acquirer::profile_acquirer_create, + routes::profile_acquirer::profile_acquirer_update, // Routes for 3DS Decision Rule routes::three_ds_decision_rule::three_ds_decision_rule_execute, @@ -781,6 +782,7 @@ Never share your secret api keys. Keep them guarded and secure. api_models::open_router::DecisionEngineSRSubLevelInputConfig, api_models::open_router::DecisionEngineEliminationData, api_models::profile_acquirer::ProfileAcquirerCreate, + api_models::profile_acquirer::ProfileAcquirerUpdate, api_models::profile_acquirer::ProfileAcquirerResponse, euclid::frontend::dir::enums::CustomerDevicePlatform, euclid::frontend::dir::enums::CustomerDeviceType, diff --git a/crates/openapi/src/routes/profile_acquirer.rs b/crates/openapi/src/routes/profile_acquirer.rs index 2c3467aeb6..3270eff846 100644 --- a/crates/openapi/src/routes/profile_acquirer.rs +++ b/crates/openapi/src/routes/profile_acquirer.rs @@ -16,3 +16,26 @@ )] pub async fn profile_acquirer_create() { /* … */ } + +#[cfg(feature = "v1")] +/// Profile Acquirer - Update +/// +/// Update a Profile Acquirer for accessing our APIs from your servers. +#[utoipa::path( + post, + path = "/profile_acquirers/{profile_id}/{profile_acquirer_id}", + params ( + ("profile_id" = String, Path, description = "The unique identifier for the Profile"), + ("profile_acquirer_id" = String, Path, description = "The unique identifier for the Profile Acquirer") + ), + request_body = ProfileAcquirerUpdate, + responses( + (status = 200, description = "Profile Acquirer updated", body = ProfileAcquirerResponse), + (status = 400, description = "Invalid data") + ), + tag = "Profile Acquirer", + operation_id = "Update a Profile Acquirer", + security(("api_key" = [])) +)] +pub async fn profile_acquirer_update() { /* … */ +} diff --git a/crates/router/src/compatibility/stripe/errors.rs b/crates/router/src/compatibility/stripe/errors.rs index 9fcfbcde5c..016e06198c 100644 --- a/crates/router/src/compatibility/stripe/errors.rs +++ b/crates/router/src/compatibility/stripe/errors.rs @@ -285,6 +285,8 @@ pub enum StripeErrorCode { PlatformBadRequest, #[error(error_type = StripeErrorType::HyperswitchError, code = "", message = "Platform Unauthorized Request")] PlatformUnauthorizedRequest, + #[error(error_type = StripeErrorType::HyperswitchError, code = "", message = "Profile Acquirer not found")] + ProfileAcquirerNotFound, // [#216]: https://github.com/juspay/hyperswitch/issues/216 // Implement the remaining stripe error codes @@ -688,6 +690,9 @@ impl From for StripeErrorCode { } errors::ApiErrorResponse::PlatformAccountAuthNotSupported => Self::PlatformBadRequest, errors::ApiErrorResponse::InvalidPlatformOperation => Self::PlatformUnauthorizedRequest, + errors::ApiErrorResponse::ProfileAcquirerNotFound { .. } => { + Self::ProfileAcquirerNotFound + } } } } @@ -782,6 +787,7 @@ impl actix_web::ResponseError for StripeErrorCode { StatusCode::from_u16(*code).unwrap_or(StatusCode::OK) } Self::LockTimeout => StatusCode::LOCKED, + Self::ProfileAcquirerNotFound => StatusCode::NOT_FOUND, } } diff --git a/crates/router/src/core/profile_acquirer.rs b/crates/router/src/core/profile_acquirer.rs index 747059e540..2e8424c1b2 100644 --- a/crates/router/src/core/profile_acquirer.rs +++ b/crates/router/src/core/profile_acquirer.rs @@ -96,19 +96,127 @@ pub async fn create_profile_acquirer( .ok_or(errors::ApiErrorResponse::InternalServerError) .attach_printable("Failed to get updated acquirer config")?; - let response = profile_acquirer::ProfileAcquirerResponse { + let response = profile_acquirer::ProfileAcquirerResponse::from(( profile_acquirer_id, - profile_id: request.profile_id.clone(), - acquirer_assigned_merchant_id: updated_acquire_details - .acquirer_assigned_merchant_id - .clone(), - merchant_name: updated_acquire_details.merchant_name.clone(), - merchant_country_code: updated_acquire_details.merchant_country_code, - network: updated_acquire_details.network.clone(), - acquirer_bin: updated_acquire_details.acquirer_bin.clone(), - acquirer_ica: updated_acquire_details.acquirer_ica.clone(), - acquirer_fraud_rate: updated_acquire_details.acquirer_fraud_rate, - }; + &request.profile_id, + updated_acquire_details, + )); + + Ok(api::ApplicationResponse::Json(response)) +} + +#[cfg(all(feature = "olap", feature = "v1"))] +pub async fn update_profile_acquirer_config( + state: SessionState, + profile_id: common_utils::id_type::ProfileId, + profile_acquirer_id: common_utils::id_type::ProfileAcquirerId, + request: profile_acquirer::ProfileAcquirerUpdate, + merchant_context: domain::MerchantContext, +) -> RouterResponse { + let db = state.store.as_ref(); + let key_manager_state = (&state).into(); + let merchant_key_store = merchant_context.get_merchant_key_store(); + + let mut business_profile = db + .find_business_profile_by_profile_id(&key_manager_state, merchant_key_store, &profile_id) + .await + .to_not_found_response(errors::ApiErrorResponse::ProfileNotFound { + id: profile_id.get_string_repr().to_owned(), + })?; + + let acquirer_config_map = business_profile + .acquirer_config_map + .as_mut() + .ok_or(errors::ApiErrorResponse::ProfileAcquirerNotFound { + profile_id: profile_id.get_string_repr().to_owned(), + profile_acquirer_id: profile_acquirer_id.get_string_repr().to_owned(), + }) + .attach_printable("no acquirer config found in business profile")?; + + let mut potential_updated_config = acquirer_config_map + .0 + .get(&profile_acquirer_id) + .ok_or_else(|| errors::ApiErrorResponse::ProfileAcquirerNotFound { + profile_id: profile_id.get_string_repr().to_owned(), + profile_acquirer_id: profile_acquirer_id.get_string_repr().to_owned(), + })? + .clone(); + + // updating value in existing acquirer config + request + .acquirer_assigned_merchant_id + .map(|val| potential_updated_config.acquirer_assigned_merchant_id = val); + request + .merchant_name + .map(|val| potential_updated_config.merchant_name = val); + request + .merchant_country_code + .map(|val| potential_updated_config.merchant_country_code = val); + request + .network + .map(|val| potential_updated_config.network = val); + request + .acquirer_bin + .map(|val| potential_updated_config.acquirer_bin = val); + request + .acquirer_ica + .map(|val| potential_updated_config.acquirer_ica = Some(val.clone())); + request + .acquirer_fraud_rate + .map(|val| potential_updated_config.acquirer_fraud_rate = val); + + // checking for duplicates in the acquirerConfigMap + match acquirer_config_map + .0 + .iter() + .find(|(_existing_id, existing_config_val_ref)| { + **existing_config_val_ref == potential_updated_config + }) { + Some((conflicting_id_of_found_item, _)) => { + Err(error_stack::report!(errors::ApiErrorResponse::GenericDuplicateError { + message: format!( + "Duplicate acquirer configuration. This configuration already exists for profile_acquirer_id '{}' under profile_id '{}'.", + conflicting_id_of_found_item.get_string_repr(), + profile_id.get_string_repr() + ), + })) + } + None => Ok(()), + }?; + + acquirer_config_map + .0 + .insert(profile_acquirer_id.clone(), potential_updated_config); + + let updated_map_for_db_update = business_profile.acquirer_config_map.clone(); + + let profile_update = domain::ProfileUpdate::AcquirerConfigMapUpdate { + acquirer_config_map: updated_map_for_db_update, + }; + + let updated_business_profile = db + .update_profile_by_profile_id( + &key_manager_state, + merchant_key_store, + business_profile, + profile_update, + ) + .await + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Failed to update business profile with updated acquirer config")?; + + let final_acquirer_details = updated_business_profile + .acquirer_config_map + .as_ref() + .and_then(|configs_wrapper| configs_wrapper.0.get(&profile_acquirer_id)) + .ok_or(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Failed to get updated acquirer config after DB update")?; + + let response = profile_acquirer::ProfileAcquirerResponse::from(( + profile_acquirer_id, + &profile_id, + final_acquirer_details, + )); Ok(api::ApplicationResponse::Json(response)) } diff --git a/crates/router/src/routes/app.rs b/crates/router/src/routes/app.rs index a22d71a5d6..0ae900f50b 100644 --- a/crates/router/src/routes/app.rs +++ b/crates/router/src/routes/app.rs @@ -2634,5 +2634,9 @@ impl ProfileAcquirer { .service( web::resource("").route(web::post().to(profile_acquirer::create_profile_acquirer)), ) + .service( + web::resource("/{profile_id}/{profile_acquirer_id}") + .route(web::post().to(profile_acquirer::profile_acquirer_update)), + ) } } diff --git a/crates/router/src/routes/lock_utils.rs b/crates/router/src/routes/lock_utils.rs index 9f64e31dcf..1f67e3093f 100644 --- a/crates/router/src/routes/lock_utils.rs +++ b/crates/router/src/routes/lock_utils.rs @@ -346,7 +346,7 @@ impl From for ApiIdentifier { Flow::RevenueRecoveryRetrieve => Self::ProcessTracker, Flow::Proxy => Self::Proxy, - Flow::ProfileAcquirerCreate => Self::ProfileAcquirer, + Flow::ProfileAcquirerCreate | Flow::ProfileAcquirerUpdate => Self::ProfileAcquirer, Flow::ThreeDsDecisionRuleExecute => Self::ThreeDsDecisionRule, Flow::TokenizationCreate | Flow::TokenizationRetrieve => Self::GenericTokenization, } diff --git a/crates/router/src/routes/profile_acquirer.rs b/crates/router/src/routes/profile_acquirer.rs index 4e8a5eeffa..4b11914b93 100644 --- a/crates/router/src/routes/profile_acquirer.rs +++ b/crates/router/src/routes/profile_acquirer.rs @@ -1,5 +1,5 @@ use actix_web::{web, HttpRequest, HttpResponse}; -use api_models::profile_acquirer::ProfileAcquirerCreate; +use api_models::profile_acquirer::{ProfileAcquirerCreate, ProfileAcquirerUpdate}; use router_env::{instrument, tracing, Flow}; use super::app::AppState; @@ -48,3 +48,50 @@ pub async fn create_profile_acquirer( )) .await } + +#[cfg(all(feature = "olap", feature = "v1"))] +#[instrument(skip_all, fields(flow = ?Flow::ProfileAcquirerUpdate))] +pub async fn profile_acquirer_update( + state: web::Data, + req: HttpRequest, + path: web::Path<( + common_utils::id_type::ProfileId, + common_utils::id_type::ProfileAcquirerId, + )>, + json_payload: web::Json, +) -> HttpResponse { + let flow = Flow::ProfileAcquirerUpdate; + let (profile_id, profile_acquirer_id) = path.into_inner(); + let payload = json_payload.into_inner(); + + Box::pin(api::server_wrap( + flow, + state, + &req, + payload, + |state: super::SessionState, auth_data, req, _| { + let merchant_context = domain::MerchantContext::NormalMerchant(Box::new( + domain::Context(auth_data.merchant_account, auth_data.key_store), + )); + crate::core::profile_acquirer::update_profile_acquirer_config( + state, + profile_id.clone(), + profile_acquirer_id.clone(), + req, + merchant_context.clone(), + ) + }, + auth::auth_type( + &auth::HeaderAuth(auth::ApiKeyAuth { + is_connected_allowed: false, + is_platform_allowed: true, + }), + &auth::JWTAuth { + permission: Permission::ProfileAccountWrite, + }, + req.headers(), + ), + api_locking::LockAction::NotApplicable, + )) + .await +} diff --git a/crates/router/src/types/api/admin.rs b/crates/router/src/types/api/admin.rs index ac46c1dde0..17dca9947f 100644 --- a/crates/router/src/types/api/admin.rs +++ b/crates/router/src/types/api/admin.rs @@ -36,6 +36,32 @@ use crate::{ utils, }; +#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)] +pub struct ProfileAcquirerConfigs { + pub acquirer_config_map: Option, + pub profile_id: common_utils::id_type::ProfileId, +} + +impl From + for Option> +{ + fn from(item: ProfileAcquirerConfigs) -> Self { + item.acquirer_config_map.map(|config_map_val| { + let mut vec: Vec<_> = config_map_val.0.into_iter().collect(); + vec.sort_by_key(|k| k.0.clone()); + vec.into_iter() + .map(|(profile_acquirer_id, acquirer_config)| { + api_models::profile_acquirer::ProfileAcquirerResponse::from(( + profile_acquirer_id, + &item.profile_id, + &acquirer_config, + )) + }) + .collect::>() + }) + } +} + impl ForeignFrom for OrganizationResponse { fn foreign_from(org: diesel_models::organization::Organization) -> Self { Self { @@ -148,7 +174,7 @@ impl ForeignTryFrom for ProfileResponse { Ok(Self { merchant_id: item.merchant_id, - profile_id, + profile_id: profile_id.clone(), profile_name: item.profile_name, return_url: item.return_url, enable_payment_response_hash: item.enable_payment_response_hash, @@ -197,7 +223,11 @@ impl ForeignTryFrom for ProfileResponse { is_debit_routing_enabled: Some(item.is_debit_routing_enabled), merchant_business_country: item.merchant_business_country, is_pre_network_tokenization_enabled: item.is_pre_network_tokenization_enabled, - acquirer_configs: item.acquirer_config_map, + acquirer_configs: ProfileAcquirerConfigs { + acquirer_config_map: item.acquirer_config_map.clone(), + profile_id: profile_id.clone(), + } + .into(), is_iframe_redirection_enabled: item.is_iframe_redirection_enabled, merchant_category_code: item.merchant_category_code, }) diff --git a/crates/router_env/src/logger/types.rs b/crates/router_env/src/logger/types.rs index 27ab6dd7c1..198b7d6bfd 100644 --- a/crates/router_env/src/logger/types.rs +++ b/crates/router_env/src/logger/types.rs @@ -595,6 +595,7 @@ pub enum Flow { ///Proxy Flow Proxy, ProfileAcquirerCreate, + ProfileAcquirerUpdate, /// ThreeDs Decision Rule Execute flow ThreeDsDecisionRuleExecute, }