diff --git a/crates/router/src/core/errors/utils.rs b/crates/router/src/core/errors/utils.rs index 118b5320ad..f5ff829b48 100644 --- a/crates/router/src/core/errors/utils.rs +++ b/crates/router/src/core/errors/utils.rs @@ -1,3 +1,5 @@ +use common_utils::errors::CustomResult; + use crate::{core::errors, logger}; pub trait StorageErrorExt { @@ -55,6 +57,13 @@ pub trait ConnectorErrorExt { #[cfg(feature = "payouts")] #[track_caller] fn to_payout_failed_response(self) -> error_stack::Result; + + // Validates if the result, is Ok(..) or WebhookEventTypeNotFound all the other error variants + // are cascaded while these two event types are handled via `Option` + #[track_caller] + fn allow_webhook_event_type_not_found( + self, + ) -> error_stack::Result, errors::ConnectorError>; } impl ConnectorErrorExt for error_stack::Result { @@ -230,4 +239,14 @@ impl ConnectorErrorExt for error_stack::Result err.change_context(error) }) } + + fn allow_webhook_event_type_not_found(self) -> CustomResult, errors::ConnectorError> { + match self { + Ok(event_type) => Ok(Some(event_type)), + Err(error) => match error.current_context() { + errors::ConnectorError::WebhookEventTypeNotFound => Ok(None), + _ => Err(error), + }, + } + } } diff --git a/crates/router/src/core/metrics.rs b/crates/router/src/core/metrics.rs index d9dcd56547..e26683b338 100644 --- a/crates/router/src/core/metrics.rs +++ b/crates/router/src/core/metrics.rs @@ -39,3 +39,7 @@ counter_metric!(WEBHOOK_SOURCE_VERIFIED_COUNT, GLOBAL_METER); counter_metric!(WEBHOOK_OUTGOING_COUNT, GLOBAL_METER); counter_metric!(WEBHOOK_OUTGOING_RECEIVED_COUNT, GLOBAL_METER); counter_metric!(WEBHOOK_OUTGOING_NOT_RECEIVED_COUNT, GLOBAL_METER); +counter_metric!( + WEBHOOK_EVENT_TYPE_IDENTIFICATION_FAILURE_COUNT, + GLOBAL_METER +); diff --git a/crates/router/src/core/webhooks.rs b/crates/router/src/core/webhooks.rs index af4e1a2be4..ffa4daa89f 100644 --- a/crates/router/src/core/webhooks.rs +++ b/crates/router/src/core/webhooks.rs @@ -10,7 +10,7 @@ use super::{errors::StorageErrorExt, metrics}; use crate::{ consts, core::{ - errors::{self, CustomResult, RouterResponse}, + errors::{self, ConnectorErrorExt, CustomResult, RouterResponse}, payments, refunds, }, logger, @@ -672,10 +672,35 @@ pub async fn webhooks_core( request_details.body = &decoded_body; - let event_type = connector + let event_type = match connector .get_webhook_event_type(&request_details) + .allow_webhook_event_type_not_found() .switch() - .attach_printable("Could not find event type in incoming webhook body")?; + .attach_printable("Could not find event type in incoming webhook body")? + { + Some(event_type) => event_type, + // Early return allows us to acknowledge the webhooks that we do not support + None => { + logger::error!( + webhook_payload =? request_details.body, + "Failed while identifying the event type", + ); + + metrics::WEBHOOK_EVENT_TYPE_IDENTIFICATION_FAILURE_COUNT.add( + &metrics::CONTEXT, + 1, + &[ + metrics::KeyValue::new(MERCHANT_ID, merchant_account.merchant_id.clone()), + metrics::KeyValue::new("connector", connector_name.to_string()), + ], + ); + + return connector + .get_webhook_api_response(&request_details) + .switch() + .attach_printable("Failed while early return in case of event type parsing"); + } + }; let process_webhook_further = utils::lookup_webhook_event( &*state.store,