From 2d4f6b3fa004a3f03beaa604e2dbfe95fcbe22a6 Mon Sep 17 00:00:00 2001 From: Narayan Bhat <48803246+Narayanbhat166@users.noreply.github.com> Date: Thu, 15 Feb 2024 12:46:06 +0530 Subject: [PATCH] refactor(webhooks): check event type not supported before checking for profile_id (#3543) --- crates/router/src/core/webhooks.rs | 66 ++++++++++--------------- crates/router/src/utils.rs | 79 ++++++++++++++++++++++++------ 2 files changed, 89 insertions(+), 56 deletions(-) diff --git a/crates/router/src/core/webhooks.rs b/crates/router/src/core/webhooks.rs index 1557e4bdee..ef313b6222 100644 --- a/crates/router/src/core/webhooks.rs +++ b/crates/router/src/core/webhooks.rs @@ -984,16 +984,15 @@ pub async fn webhooks_core merchant_connector_account, + None => { + helper_utils::get_mca_from_object_reference_id( + &*state.clone().store, + object_ref_id.clone(), + &merchant_account, + &connector_name, + &key_store, + ) + .await? + } + }; + let source_verified = if connectors_with_source_verification_call .connectors_with_webhook_source_verification_call .contains(&connector_enum) @@ -1311,14 +1324,17 @@ pub async fn get_payment_id( .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound) } -async fn fetch_mca_and_connector( +/// This function fetches the merchant connector account ( if the url used is /{merchant_connector_id}) +/// if merchant connector id is not passed in the request, then this will return None for mca +async fn fetch_optional_mca_and_connector( state: &AppState, merchant_account: &domain::MerchantAccount, connector_name_or_mca_id: &str, key_store: &domain::MerchantKeyStore, - request_details: &api::IncomingWebhookRequestDetails<'_>, -) -> CustomResult<(domain::MerchantConnectorAccount, api::ConnectorData), errors::ApiErrorResponse> -{ +) -> CustomResult< + (Option, api::ConnectorData), + errors::ApiErrorResponse, +> { let db = &state.store; if connector_name_or_mca_id.starts_with("mca_") { let mca = db @@ -1346,7 +1362,7 @@ async fn fetch_mca_and_connector( }) .attach_printable("Failed construction of ConnectorData")?; - Ok((mca, connector)) + Ok((Some(mca), connector)) } else { // Merchant connector account is already being queried, it is safe to set connector id as None let connector = api::ConnectorData::get_connector_by_name( @@ -1360,38 +1376,6 @@ async fn fetch_mca_and_connector( }) .attach_printable("Failed construction of ConnectorData")?; - let object_ref_id = connector - .connector - .get_webhook_object_reference_id(request_details) - .switch() - .attach_printable("Could not find object reference id in incoming webhook body")?; - - let profile_id = helper_utils::get_profile_id_using_object_reference_id( - &*state.store, - object_ref_id, - merchant_account, - connector_name_or_mca_id, - ) - .await - .change_context(errors::ApiErrorResponse::InvalidDataValue { - field_name: "object reference id", - }) - .attach_printable("Could not find profile id from object reference id")?; - - let mca = db - .find_merchant_connector_account_by_profile_id_connector_name( - &profile_id, - connector_name_or_mca_id, - key_store, - ) - .await - .to_not_found_response(errors::ApiErrorResponse::MerchantConnectorAccountNotFound { - id: format!( - "profile_id {profile_id} and connector name {connector_name_or_mca_id}" - ), - }) - .attach_printable("error while fetching merchant_connector_account from profile_id")?; - - Ok((mca, connector)) + Ok((None, connector)) } } diff --git a/crates/router/src/utils.rs b/crates/router/src/utils.rs index 68909d1127..f9511a76d8 100644 --- a/crates/router/src/utils.rs +++ b/crates/router/src/utils.rs @@ -326,14 +326,26 @@ pub async fn find_payment_intent_from_mandate_id_type( .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound) } -pub async fn get_profile_id_using_object_reference_id( +pub async fn get_mca_from_object_reference_id( db: &dyn StorageInterface, object_reference_id: webhooks::ObjectReferenceId, merchant_account: &domain::MerchantAccount, connector_name: &str, -) -> CustomResult { + key_store: &domain::MerchantKeyStore, +) -> CustomResult { + let merchant_id = merchant_account.merchant_id.clone(); + match merchant_account.default_profile.as_ref() { - Some(profile_id) => Ok(profile_id.clone()), + Some(profile_id) => db + .find_merchant_connector_account_by_profile_id_connector_name( + profile_id, + connector_name, + key_store, + ) + .await + .to_not_found_response(errors::ApiErrorResponse::MerchantConnectorAccountNotFound { + id: format!("profile_id {profile_id} and connector_name {connector_name}"), + }), _ => { let payment_intent = match object_reference_id { webhooks::ObjectReferenceId::PaymentId(payment_id_type) => { @@ -355,19 +367,56 @@ pub async fn get_profile_id_using_object_reference_id( } }; - let profile_id = utils::get_profile_id_from_business_details( - payment_intent.business_country, - payment_intent.business_label.as_ref(), - merchant_account, - payment_intent.profile_id.as_ref(), - db, - false, - ) - .await - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("profile_id is not set in payment_intent")?; + let payment_attempt = db + .find_payment_attempt_by_attempt_id_merchant_id( + &payment_intent.active_attempt.get_id(), + &merchant_id, + merchant_account.storage_scheme, + ) + .await + .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?; - Ok(profile_id) + match payment_attempt.merchant_connector_id { + Some(merchant_connector_id) => db + .find_by_merchant_connector_account_merchant_id_merchant_connector_id( + &merchant_id, + &merchant_connector_id, + key_store, + ) + .await + .to_not_found_response( + errors::ApiErrorResponse::MerchantConnectorAccountNotFound { + id: merchant_connector_id, + }, + ), + None => { + let profile_id = utils::get_profile_id_from_business_details( + payment_intent.business_country, + payment_intent.business_label.as_ref(), + merchant_account, + payment_intent.profile_id.as_ref(), + db, + false, + ) + .await + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("profile_id is not set in payment_intent")?; + + db.find_merchant_connector_account_by_profile_id_connector_name( + &profile_id, + connector_name, + key_store, + ) + .await + .to_not_found_response( + errors::ApiErrorResponse::MerchantConnectorAccountNotFound { + id: format!( + "profile_id {profile_id} and connector_name {connector_name}" + ), + }, + ) + } + } } } }