mirror of
				https://github.com/juspay/hyperswitch.git
				synced 2025-10-31 18:17:13 +08:00 
			
		
		
		
	fix(webhook): provide acknowledgment for webhooks with unsupported event types (#1815)
This commit is contained in:
		| @ -1,3 +1,5 @@ | |||||||
|  | use common_utils::errors::CustomResult; | ||||||
|  |  | ||||||
| use crate::{core::errors, logger}; | use crate::{core::errors, logger}; | ||||||
|  |  | ||||||
| pub trait StorageErrorExt<T, E> { | pub trait StorageErrorExt<T, E> { | ||||||
| @ -55,6 +57,13 @@ pub trait ConnectorErrorExt<T> { | |||||||
|     #[cfg(feature = "payouts")] |     #[cfg(feature = "payouts")] | ||||||
|     #[track_caller] |     #[track_caller] | ||||||
|     fn to_payout_failed_response(self) -> error_stack::Result<T, errors::ApiErrorResponse>; |     fn to_payout_failed_response(self) -> error_stack::Result<T, errors::ApiErrorResponse>; | ||||||
|  |  | ||||||
|  |     // 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<Option<T>, errors::ConnectorError>; | ||||||
| } | } | ||||||
|  |  | ||||||
| impl<T> ConnectorErrorExt<T> for error_stack::Result<T, errors::ConnectorError> { | impl<T> ConnectorErrorExt<T> for error_stack::Result<T, errors::ConnectorError> { | ||||||
| @ -230,4 +239,14 @@ impl<T> ConnectorErrorExt<T> for error_stack::Result<T, errors::ConnectorError> | |||||||
|             err.change_context(error) |             err.change_context(error) | ||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     fn allow_webhook_event_type_not_found(self) -> CustomResult<Option<T>, errors::ConnectorError> { | ||||||
|  |         match self { | ||||||
|  |             Ok(event_type) => Ok(Some(event_type)), | ||||||
|  |             Err(error) => match error.current_context() { | ||||||
|  |                 errors::ConnectorError::WebhookEventTypeNotFound => Ok(None), | ||||||
|  |                 _ => Err(error), | ||||||
|  |             }, | ||||||
|  |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -39,3 +39,7 @@ counter_metric!(WEBHOOK_SOURCE_VERIFIED_COUNT, GLOBAL_METER); | |||||||
| counter_metric!(WEBHOOK_OUTGOING_COUNT, GLOBAL_METER); | counter_metric!(WEBHOOK_OUTGOING_COUNT, GLOBAL_METER); | ||||||
| counter_metric!(WEBHOOK_OUTGOING_RECEIVED_COUNT, GLOBAL_METER); | counter_metric!(WEBHOOK_OUTGOING_RECEIVED_COUNT, GLOBAL_METER); | ||||||
| counter_metric!(WEBHOOK_OUTGOING_NOT_RECEIVED_COUNT, GLOBAL_METER); | counter_metric!(WEBHOOK_OUTGOING_NOT_RECEIVED_COUNT, GLOBAL_METER); | ||||||
|  | counter_metric!( | ||||||
|  |     WEBHOOK_EVENT_TYPE_IDENTIFICATION_FAILURE_COUNT, | ||||||
|  |     GLOBAL_METER | ||||||
|  | ); | ||||||
|  | |||||||
| @ -10,7 +10,7 @@ use super::{errors::StorageErrorExt, metrics}; | |||||||
| use crate::{ | use crate::{ | ||||||
|     consts, |     consts, | ||||||
|     core::{ |     core::{ | ||||||
|         errors::{self, CustomResult, RouterResponse}, |         errors::{self, ConnectorErrorExt, CustomResult, RouterResponse}, | ||||||
|         payments, refunds, |         payments, refunds, | ||||||
|     }, |     }, | ||||||
|     logger, |     logger, | ||||||
| @ -672,10 +672,35 @@ pub async fn webhooks_core<W: types::OutgoingWebhookType>( | |||||||
|  |  | ||||||
|     request_details.body = &decoded_body; |     request_details.body = &decoded_body; | ||||||
|  |  | ||||||
|     let event_type = connector |     let event_type = match connector | ||||||
|         .get_webhook_event_type(&request_details) |         .get_webhook_event_type(&request_details) | ||||||
|  |         .allow_webhook_event_type_not_found() | ||||||
|         .switch() |         .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( |     let process_webhook_further = utils::lookup_webhook_event( | ||||||
|         &*state.store, |         &*state.store, | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 Nishant Joshi
					Nishant Joshi