mirror of
				https://github.com/juspay/hyperswitch.git
				synced 2025-10-31 10:06:32 +08:00 
			
		
		
		
	fix(router/webhooks): correct webhook error mapping and make source verification optional for all connectors (#1333)
This commit is contained in:
		
							
								
								
									
										10
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										10
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							| @ -3058,7 +3058,7 @@ dependencies = [ | |||||||
| [[package]] | [[package]] | ||||||
| name = "opentelemetry" | name = "opentelemetry" | ||||||
| version = "0.18.0" | version = "0.18.0" | ||||||
| source = "git+https://github.com/open-telemetry/opentelemetry-rust?rev=44b90202fd744598db8b0ace5b8f0bad7ec45658#44b90202fd744598db8b0ace5b8f0bad7ec45658" | source = "git+https://github.com/open-telemetry/opentelemetry-rust/?rev=44b90202fd744598db8b0ace5b8f0bad7ec45658#44b90202fd744598db8b0ace5b8f0bad7ec45658" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "opentelemetry_api", |  "opentelemetry_api", | ||||||
|  "opentelemetry_sdk", |  "opentelemetry_sdk", | ||||||
| @ -3067,7 +3067,7 @@ dependencies = [ | |||||||
| [[package]] | [[package]] | ||||||
| name = "opentelemetry-otlp" | name = "opentelemetry-otlp" | ||||||
| version = "0.11.0" | version = "0.11.0" | ||||||
| source = "git+https://github.com/open-telemetry/opentelemetry-rust?rev=44b90202fd744598db8b0ace5b8f0bad7ec45658#44b90202fd744598db8b0ace5b8f0bad7ec45658" | source = "git+https://github.com/open-telemetry/opentelemetry-rust/?rev=44b90202fd744598db8b0ace5b8f0bad7ec45658#44b90202fd744598db8b0ace5b8f0bad7ec45658" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "async-trait", |  "async-trait", | ||||||
|  "futures", |  "futures", | ||||||
| @ -3084,7 +3084,7 @@ dependencies = [ | |||||||
| [[package]] | [[package]] | ||||||
| name = "opentelemetry-proto" | name = "opentelemetry-proto" | ||||||
| version = "0.1.0" | version = "0.1.0" | ||||||
| source = "git+https://github.com/open-telemetry/opentelemetry-rust?rev=44b90202fd744598db8b0ace5b8f0bad7ec45658#44b90202fd744598db8b0ace5b8f0bad7ec45658" | source = "git+https://github.com/open-telemetry/opentelemetry-rust/?rev=44b90202fd744598db8b0ace5b8f0bad7ec45658#44b90202fd744598db8b0ace5b8f0bad7ec45658" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "futures", |  "futures", | ||||||
|  "futures-util", |  "futures-util", | ||||||
| @ -3096,7 +3096,7 @@ dependencies = [ | |||||||
| [[package]] | [[package]] | ||||||
| name = "opentelemetry_api" | name = "opentelemetry_api" | ||||||
| version = "0.18.0" | version = "0.18.0" | ||||||
| source = "git+https://github.com/open-telemetry/opentelemetry-rust?rev=44b90202fd744598db8b0ace5b8f0bad7ec45658#44b90202fd744598db8b0ace5b8f0bad7ec45658" | source = "git+https://github.com/open-telemetry/opentelemetry-rust/?rev=44b90202fd744598db8b0ace5b8f0bad7ec45658#44b90202fd744598db8b0ace5b8f0bad7ec45658" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "fnv", |  "fnv", | ||||||
|  "futures-channel", |  "futures-channel", | ||||||
| @ -3111,7 +3111,7 @@ dependencies = [ | |||||||
| [[package]] | [[package]] | ||||||
| name = "opentelemetry_sdk" | name = "opentelemetry_sdk" | ||||||
| version = "0.18.0" | version = "0.18.0" | ||||||
| source = "git+https://github.com/open-telemetry/opentelemetry-rust?rev=44b90202fd744598db8b0ace5b8f0bad7ec45658#44b90202fd744598db8b0ace5b8f0bad7ec45658" | source = "git+https://github.com/open-telemetry/opentelemetry-rust/?rev=44b90202fd744598db8b0ace5b8f0bad7ec45658#44b90202fd744598db8b0ace5b8f0bad7ec45658" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "async-trait", |  "async-trait", | ||||||
|  "crossbeam-channel", |  "crossbeam-channel", | ||||||
|  | |||||||
| @ -11,6 +11,7 @@ use storage_models::enums as storage_enums; | |||||||
| use self::transformers as adyen; | use self::transformers as adyen; | ||||||
| use crate::{ | use crate::{ | ||||||
|     configs::settings, |     configs::settings, | ||||||
|  |     connector::utils as conn_utils, | ||||||
|     consts, |     consts, | ||||||
|     core::errors::{self, CustomResult}, |     core::errors::{self, CustomResult}, | ||||||
|     db::StorageInterface, |     db::StorageInterface, | ||||||
| @ -797,13 +798,17 @@ impl api::IncomingWebhook for Adyen { | |||||||
|         db: &dyn StorageInterface, |         db: &dyn StorageInterface, | ||||||
|         merchant_id: &str, |         merchant_id: &str, | ||||||
|     ) -> CustomResult<Vec<u8>, errors::ConnectorError> { |     ) -> CustomResult<Vec<u8>, errors::ConnectorError> { | ||||||
|         let key = format!("whsec_verification_{}_{}", self.id(), merchant_id); |         let key = conn_utils::get_webhook_merchant_secret_key(self.id(), merchant_id); | ||||||
|         let secret = db |         let secret = match db.find_config_by_key(&key).await { | ||||||
|             .get_key(&key) |             Ok(config) => Some(config), | ||||||
|             .await |             Err(e) => { | ||||||
|             .change_context(errors::ConnectorError::WebhookVerificationSecretNotFound)?; |                 crate::logger::warn!("Unable to fetch merchant webhook secret from DB: {:#?}", e); | ||||||
|  |                 None | ||||||
|         Ok(secret) |             } | ||||||
|  |         }; | ||||||
|  |         Ok(secret | ||||||
|  |             .map(|conf| conf.config.into_bytes()) | ||||||
|  |             .unwrap_or_default()) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn get_webhook_object_reference_id( |     fn get_webhook_object_reference_id( | ||||||
|  | |||||||
| @ -9,6 +9,7 @@ use transformers as airwallex; | |||||||
| use super::utils::{AccessTokenRequestInfo, RefundsRequestData}; | use super::utils::{AccessTokenRequestInfo, RefundsRequestData}; | ||||||
| use crate::{ | use crate::{ | ||||||
|     configs::settings, |     configs::settings, | ||||||
|  |     connector::utils as conn_utils, | ||||||
|     core::{ |     core::{ | ||||||
|         errors::{self, CustomResult}, |         errors::{self, CustomResult}, | ||||||
|         payments, |         payments, | ||||||
| @ -947,12 +948,17 @@ impl api::IncomingWebhook for Airwallex { | |||||||
|         db: &dyn StorageInterface, |         db: &dyn StorageInterface, | ||||||
|         merchant_id: &str, |         merchant_id: &str, | ||||||
|     ) -> CustomResult<Vec<u8>, errors::ConnectorError> { |     ) -> CustomResult<Vec<u8>, errors::ConnectorError> { | ||||||
|         let key = format!("whsec_verification_{}_{}", self.id(), merchant_id); |         let key = conn_utils::get_webhook_merchant_secret_key(self.id(), merchant_id); | ||||||
|         let secret = db |         let secret = match db.find_config_by_key(&key).await { | ||||||
|             .find_config_by_key(&key) |             Ok(config) => Some(config), | ||||||
|             .await |             Err(e) => { | ||||||
|             .change_context(errors::ConnectorError::WebhookVerificationSecretNotFound)?; |                 crate::logger::warn!("Unable to fetch merchant webhook secret from DB: {:#?}", e); | ||||||
|         Ok(secret.config.into_bytes()) |                 None | ||||||
|  |             } | ||||||
|  |         }; | ||||||
|  |         Ok(secret | ||||||
|  |             .map(|conf| conf.config.into_bytes()) | ||||||
|  |             .unwrap_or_default()) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn get_webhook_object_reference_id( |     fn get_webhook_object_reference_id( | ||||||
|  | |||||||
| @ -9,6 +9,7 @@ use transformers as authorizedotnet; | |||||||
|  |  | ||||||
| use crate::{ | use crate::{ | ||||||
|     configs::settings, |     configs::settings, | ||||||
|  |     connector::utils as conn_utils, | ||||||
|     consts, |     consts, | ||||||
|     core::errors::{self, CustomResult}, |     core::errors::{self, CustomResult}, | ||||||
|     db::StorageInterface, |     db::StorageInterface, | ||||||
| @ -684,7 +685,7 @@ impl api::IncomingWebhook for Authorizedotnet { | |||||||
|         db: &dyn StorageInterface, |         db: &dyn StorageInterface, | ||||||
|         merchant_id: &str, |         merchant_id: &str, | ||||||
|     ) -> CustomResult<Vec<u8>, errors::ConnectorError> { |     ) -> CustomResult<Vec<u8>, errors::ConnectorError> { | ||||||
|         let key = format!("whsec_verification_{}_{}", self.id(), merchant_id); |         let key = conn_utils::get_webhook_merchant_secret_key(self.id(), merchant_id); | ||||||
|         let secret = match db.find_config_by_key(&key).await { |         let secret = match db.find_config_by_key(&key).await { | ||||||
|             Ok(config) => Some(config), |             Ok(config) => Some(config), | ||||||
|             Err(e) => { |             Err(e) => { | ||||||
|  | |||||||
| @ -15,6 +15,7 @@ use super::utils::{ | |||||||
| }; | }; | ||||||
| use crate::{ | use crate::{ | ||||||
|     configs::settings, |     configs::settings, | ||||||
|  |     connector::utils as conn_utils, | ||||||
|     consts, |     consts, | ||||||
|     core::{ |     core::{ | ||||||
|         errors::{self, CustomResult}, |         errors::{self, CustomResult}, | ||||||
| @ -975,13 +976,17 @@ impl api::IncomingWebhook for Bluesnap { | |||||||
|         db: &dyn StorageInterface, |         db: &dyn StorageInterface, | ||||||
|         merchant_id: &str, |         merchant_id: &str, | ||||||
|     ) -> CustomResult<Vec<u8>, errors::ConnectorError> { |     ) -> CustomResult<Vec<u8>, errors::ConnectorError> { | ||||||
|         let key = format!("whsec_verification_{}_{}", self.id(), merchant_id); |         let key = conn_utils::get_webhook_merchant_secret_key(self.id(), merchant_id); | ||||||
|         let secret = db |         let secret = match db.find_config_by_key(&key).await { | ||||||
|             .find_config_by_key(&key) |             Ok(config) => Some(config), | ||||||
|             .await |             Err(e) => { | ||||||
|             .change_context(errors::ConnectorError::WebhookVerificationSecretNotFound)?; |                 crate::logger::warn!("Unable to fetch merchant webhook secret from DB: {:#?}", e); | ||||||
|  |                 None | ||||||
|         Ok(secret.config.into_bytes()) |             } | ||||||
|  |         }; | ||||||
|  |         Ok(secret | ||||||
|  |             .map(|conf| conf.config.into_bytes()) | ||||||
|  |             .unwrap_or_default()) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async fn verify_webhook_source( |     async fn verify_webhook_source( | ||||||
|  | |||||||
| @ -2,7 +2,7 @@ mod transformers; | |||||||
|  |  | ||||||
| use std::fmt::Debug; | use std::fmt::Debug; | ||||||
|  |  | ||||||
| use error_stack::ResultExt; | use error_stack::{IntoReport, ResultExt}; | ||||||
|  |  | ||||||
| use self::transformers as braintree; | use self::transformers as braintree; | ||||||
| use crate::{ | use crate::{ | ||||||
| @ -688,20 +688,20 @@ impl api::IncomingWebhook for Braintree { | |||||||
|         &self, |         &self, | ||||||
|         _request: &api::IncomingWebhookRequestDetails<'_>, |         _request: &api::IncomingWebhookRequestDetails<'_>, | ||||||
|     ) -> CustomResult<api_models::webhooks::ObjectReferenceId, errors::ConnectorError> { |     ) -> CustomResult<api_models::webhooks::ObjectReferenceId, errors::ConnectorError> { | ||||||
|         Err(errors::ConnectorError::NotImplemented("braintree".to_string()).into()) |         Err(errors::ConnectorError::WebhooksNotImplemented).into_report() | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn get_webhook_event_type( |     fn get_webhook_event_type( | ||||||
|         &self, |         &self, | ||||||
|         _request: &api::IncomingWebhookRequestDetails<'_>, |         _request: &api::IncomingWebhookRequestDetails<'_>, | ||||||
|     ) -> CustomResult<api::IncomingWebhookEvent, errors::ConnectorError> { |     ) -> CustomResult<api::IncomingWebhookEvent, errors::ConnectorError> { | ||||||
|         Err(errors::ConnectorError::NotImplemented("braintree".to_string()).into()) |         Err(errors::ConnectorError::WebhooksNotImplemented).into_report() | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn get_webhook_resource_object( |     fn get_webhook_resource_object( | ||||||
|         &self, |         &self, | ||||||
|         _request: &api::IncomingWebhookRequestDetails<'_>, |         _request: &api::IncomingWebhookRequestDetails<'_>, | ||||||
|     ) -> CustomResult<serde_json::Value, errors::ConnectorError> { |     ) -> CustomResult<serde_json::Value, errors::ConnectorError> { | ||||||
|         Err(errors::ConnectorError::NotImplemented("braintree".to_string()).into()) |         Err(errors::ConnectorError::WebhooksNotImplemented).into_report() | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -1079,7 +1079,7 @@ impl api::IncomingWebhook for Checkout { | |||||||
|         db: &dyn StorageInterface, |         db: &dyn StorageInterface, | ||||||
|         merchant_id: &str, |         merchant_id: &str, | ||||||
|     ) -> CustomResult<Vec<u8>, errors::ConnectorError> { |     ) -> CustomResult<Vec<u8>, errors::ConnectorError> { | ||||||
|         let key = format!("whsec_verification_{}_{}", self.id(), merchant_id); |         let key = conn_utils::get_webhook_merchant_secret_key(self.id(), merchant_id); | ||||||
|         let secret = match db.find_config_by_key(&key).await { |         let secret = match db.find_config_by_key(&key).await { | ||||||
|             Ok(config) => Some(config), |             Ok(config) => Some(config), | ||||||
|             Err(e) => { |             Err(e) => { | ||||||
|  | |||||||
| @ -523,13 +523,17 @@ impl api::IncomingWebhook for Coinbase { | |||||||
|         db: &dyn db::StorageInterface, |         db: &dyn db::StorageInterface, | ||||||
|         merchant_id: &str, |         merchant_id: &str, | ||||||
|     ) -> CustomResult<Vec<u8>, errors::ConnectorError> { |     ) -> CustomResult<Vec<u8>, errors::ConnectorError> { | ||||||
|         let key = format!("whsec_verification_{}_{}", self.id(), merchant_id); |         let key = utils::get_webhook_merchant_secret_key(self.id(), merchant_id); | ||||||
|         let secret = db |         let secret = match db.find_config_by_key(&key).await { | ||||||
|             .get_key(&key) |             Ok(config) => Some(config), | ||||||
|             .await |             Err(e) => { | ||||||
|             .change_context(errors::ConnectorError::WebhookVerificationSecretNotFound)?; |                 crate::logger::warn!("Unable to fetch merchant webhook secret from DB: {:#?}", e); | ||||||
|  |                 None | ||||||
|         Ok(secret) |             } | ||||||
|  |         }; | ||||||
|  |         Ok(secret | ||||||
|  |             .map(|conf| conf.config.into_bytes()) | ||||||
|  |             .unwrap_or_default()) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn get_webhook_object_reference_id( |     fn get_webhook_object_reference_id( | ||||||
|  | |||||||
| @ -717,20 +717,20 @@ impl api::IncomingWebhook for Cybersource { | |||||||
|         &self, |         &self, | ||||||
|         _request: &api::IncomingWebhookRequestDetails<'_>, |         _request: &api::IncomingWebhookRequestDetails<'_>, | ||||||
|     ) -> CustomResult<api_models::webhooks::ObjectReferenceId, errors::ConnectorError> { |     ) -> CustomResult<api_models::webhooks::ObjectReferenceId, errors::ConnectorError> { | ||||||
|         Err(errors::ConnectorError::NotImplemented("cybersource".to_string()).into()) |         Err(errors::ConnectorError::WebhooksNotImplemented).into_report() | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn get_webhook_event_type( |     fn get_webhook_event_type( | ||||||
|         &self, |         &self, | ||||||
|         _request: &api::IncomingWebhookRequestDetails<'_>, |         _request: &api::IncomingWebhookRequestDetails<'_>, | ||||||
|     ) -> CustomResult<api::IncomingWebhookEvent, errors::ConnectorError> { |     ) -> CustomResult<api::IncomingWebhookEvent, errors::ConnectorError> { | ||||||
|         Err(errors::ConnectorError::NotImplemented("cybersource".to_string()).into()) |         Err(errors::ConnectorError::WebhooksNotImplemented).into_report() | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn get_webhook_resource_object( |     fn get_webhook_resource_object( | ||||||
|         &self, |         &self, | ||||||
|         _request: &api::IncomingWebhookRequestDetails<'_>, |         _request: &api::IncomingWebhookRequestDetails<'_>, | ||||||
|     ) -> CustomResult<serde_json::Value, errors::ConnectorError> { |     ) -> CustomResult<serde_json::Value, errors::ConnectorError> { | ||||||
|         Err(errors::ConnectorError::NotImplemented("cybersource".to_string()).into()) |         Err(errors::ConnectorError::WebhooksNotImplemented).into_report() | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -3,7 +3,7 @@ mod transformers; | |||||||
| use std::fmt::Debug; | use std::fmt::Debug; | ||||||
|  |  | ||||||
| use base64::Engine; | use base64::Engine; | ||||||
| use error_stack::ResultExt; | use error_stack::{IntoReport, ResultExt}; | ||||||
| use ring::hmac; | use ring::hmac; | ||||||
| use time::OffsetDateTime; | use time::OffsetDateTime; | ||||||
| use transformers as fiserv; | use transformers as fiserv; | ||||||
| @ -684,20 +684,20 @@ impl api::IncomingWebhook for Fiserv { | |||||||
|         &self, |         &self, | ||||||
|         _request: &api::IncomingWebhookRequestDetails<'_>, |         _request: &api::IncomingWebhookRequestDetails<'_>, | ||||||
|     ) -> CustomResult<api_models::webhooks::ObjectReferenceId, errors::ConnectorError> { |     ) -> CustomResult<api_models::webhooks::ObjectReferenceId, errors::ConnectorError> { | ||||||
|         Err(errors::ConnectorError::NotImplemented("fiserv".to_string()).into()) |         Err(errors::ConnectorError::WebhooksNotImplemented).into_report() | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn get_webhook_event_type( |     fn get_webhook_event_type( | ||||||
|         &self, |         &self, | ||||||
|         _request: &api::IncomingWebhookRequestDetails<'_>, |         _request: &api::IncomingWebhookRequestDetails<'_>, | ||||||
|     ) -> CustomResult<api::IncomingWebhookEvent, errors::ConnectorError> { |     ) -> CustomResult<api::IncomingWebhookEvent, errors::ConnectorError> { | ||||||
|         Err(errors::ConnectorError::NotImplemented("fiserv".to_string()).into()) |         Err(errors::ConnectorError::WebhooksNotImplemented).into_report() | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn get_webhook_resource_object( |     fn get_webhook_resource_object( | ||||||
|         &self, |         &self, | ||||||
|         _request: &api::IncomingWebhookRequestDetails<'_>, |         _request: &api::IncomingWebhookRequestDetails<'_>, | ||||||
|     ) -> CustomResult<serde_json::Value, errors::ConnectorError> { |     ) -> CustomResult<serde_json::Value, errors::ConnectorError> { | ||||||
|         Err(errors::ConnectorError::NotImplemented("fiserv".to_string()).into()) |         Err(errors::ConnectorError::WebhooksNotImplemented).into_report() | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -808,12 +808,17 @@ impl api::IncomingWebhook for Globalpay { | |||||||
|         db: &dyn db::StorageInterface, |         db: &dyn db::StorageInterface, | ||||||
|         merchant_id: &str, |         merchant_id: &str, | ||||||
|     ) -> CustomResult<Vec<u8>, errors::ConnectorError> { |     ) -> CustomResult<Vec<u8>, errors::ConnectorError> { | ||||||
|         let key = format!("whsec_verification_{}_{}", self.id(), merchant_id); |         let key = conn_utils::get_webhook_merchant_secret_key(self.id(), merchant_id); | ||||||
|         let secret = db |         let secret = match db.find_config_by_key(&key).await { | ||||||
|             .find_config_by_key(&key) |             Ok(config) => Some(config), | ||||||
|             .await |             Err(e) => { | ||||||
|             .change_context(errors::ConnectorError::WebhookVerificationSecretNotFound)?; |                 crate::logger::warn!("Unable to fetch merchant webhook secret from DB: {:#?}", e); | ||||||
|         Ok(secret.config.into_bytes()) |                 None | ||||||
|  |             } | ||||||
|  |         }; | ||||||
|  |         Ok(secret | ||||||
|  |             .map(|conf| conf.config.into_bytes()) | ||||||
|  |             .unwrap_or_default()) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn get_webhook_source_verification_signature( |     fn get_webhook_source_verification_signature( | ||||||
|  | |||||||
| @ -633,13 +633,17 @@ impl api::IncomingWebhook for Iatapay { | |||||||
|         db: &dyn db::StorageInterface, |         db: &dyn db::StorageInterface, | ||||||
|         merchant_id: &str, |         merchant_id: &str, | ||||||
|     ) -> CustomResult<Vec<u8>, errors::ConnectorError> { |     ) -> CustomResult<Vec<u8>, errors::ConnectorError> { | ||||||
|         let key = format!("whsec_verification_{}_{}", self.id(), merchant_id); |         let key = utils::get_webhook_merchant_secret_key(self.id(), merchant_id); | ||||||
|         let secret = db |         let secret = match db.find_config_by_key(&key).await { | ||||||
|             .get_key(&key) |             Ok(config) => Some(config), | ||||||
|             .await |             Err(e) => { | ||||||
|             .change_context(errors::ConnectorError::WebhookVerificationSecretNotFound)?; |                 crate::logger::warn!("Unable to fetch merchant webhook secret from DB: {:#?}", e); | ||||||
|  |                 None | ||||||
|         Ok(secret) |             } | ||||||
|  |         }; | ||||||
|  |         Ok(secret | ||||||
|  |             .map(|conf| conf.config.into_bytes()) | ||||||
|  |             .unwrap_or_default()) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn get_webhook_object_reference_id( |     fn get_webhook_object_reference_id( | ||||||
|  | |||||||
| @ -852,12 +852,17 @@ impl api::IncomingWebhook for Nuvei { | |||||||
|         db: &dyn StorageInterface, |         db: &dyn StorageInterface, | ||||||
|         merchant_id: &str, |         merchant_id: &str, | ||||||
|     ) -> CustomResult<Vec<u8>, errors::ConnectorError> { |     ) -> CustomResult<Vec<u8>, errors::ConnectorError> { | ||||||
|         let key = format!("wh_mer_sec_verification_{}_{}", self.id(), merchant_id); |         let key = utils::get_webhook_merchant_secret_key(self.id(), merchant_id); | ||||||
|         let secret = db |         let secret = match db.find_config_by_key(&key).await { | ||||||
|             .get_key(&key) |             Ok(config) => Some(config), | ||||||
|             .await |             Err(e) => { | ||||||
|             .change_context(errors::ConnectorError::WebhookVerificationSecretNotFound)?; |                 crate::logger::warn!("Unable to fetch merchant webhook secret from DB: {:#?}", e); | ||||||
|         Ok(secret) |                 None | ||||||
|  |             } | ||||||
|  |         }; | ||||||
|  |         Ok(secret | ||||||
|  |             .map(|conf| conf.config.into_bytes()) | ||||||
|  |             .unwrap_or_default()) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn get_webhook_source_verification_message( |     fn get_webhook_source_verification_message( | ||||||
|  | |||||||
| @ -9,6 +9,7 @@ use transformers as opennode; | |||||||
| use self::opennode::OpennodeWebhookDetails; | use self::opennode::OpennodeWebhookDetails; | ||||||
| use crate::{ | use crate::{ | ||||||
|     configs::settings, |     configs::settings, | ||||||
|  |     connector::utils as conn_utils, | ||||||
|     core::errors::{self, CustomResult}, |     core::errors::{self, CustomResult}, | ||||||
|     db, headers, |     db, headers, | ||||||
|     services::{self, ConnectorIntegration}, |     services::{self, ConnectorIntegration}, | ||||||
| @ -527,13 +528,17 @@ impl api::IncomingWebhook for Opennode { | |||||||
|         db: &dyn db::StorageInterface, |         db: &dyn db::StorageInterface, | ||||||
|         merchant_id: &str, |         merchant_id: &str, | ||||||
|     ) -> CustomResult<Vec<u8>, errors::ConnectorError> { |     ) -> CustomResult<Vec<u8>, errors::ConnectorError> { | ||||||
|         let key = format!("whsec_verification_{}_{}", self.id(), merchant_id); |         let key = conn_utils::get_webhook_merchant_secret_key(self.id(), merchant_id); | ||||||
|         let secret = db |         let secret = match db.find_config_by_key(&key).await { | ||||||
|             .get_key(&key) |             Ok(config) => Some(config), | ||||||
|             .await |             Err(e) => { | ||||||
|             .change_context(errors::ConnectorError::WebhookVerificationSecretNotFound)?; |                 crate::logger::warn!("Unable to fetch merchant webhook secret from DB: {:#?}", e); | ||||||
|  |                 None | ||||||
|         Ok(secret) |             } | ||||||
|  |         }; | ||||||
|  |         Ok(secret | ||||||
|  |             .map(|conf| conf.config.into_bytes()) | ||||||
|  |             .unwrap_or_default()) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn get_webhook_object_reference_id( |     fn get_webhook_object_reference_id( | ||||||
|  | |||||||
| @ -702,13 +702,17 @@ impl api::IncomingWebhook for Rapyd { | |||||||
|         db: &dyn StorageInterface, |         db: &dyn StorageInterface, | ||||||
|         merchant_id: &str, |         merchant_id: &str, | ||||||
|     ) -> CustomResult<Vec<u8>, errors::ConnectorError> { |     ) -> CustomResult<Vec<u8>, errors::ConnectorError> { | ||||||
|         let key = format!("wh_mer_sec_verification_{}_{}", self.id(), merchant_id); |         let key = conn_utils::get_webhook_merchant_secret_key(self.id(), merchant_id); | ||||||
|         let secret = db |         let secret = match db.find_config_by_key(&key).await { | ||||||
|             .get_key(&key) |             Ok(config) => Some(config), | ||||||
|             .await |             Err(e) => { | ||||||
|             .change_context(errors::ConnectorError::WebhookVerificationSecretNotFound)?; |                 crate::logger::warn!("Unable to fetch merchant webhook secret from DB: {:#?}", e); | ||||||
|  |                 None | ||||||
|         Ok(secret) |             } | ||||||
|  |         }; | ||||||
|  |         Ok(secret | ||||||
|  |             .map(|conf| conf.config.into_bytes()) | ||||||
|  |             .unwrap_or_default()) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn get_webhook_source_verification_message( |     fn get_webhook_source_verification_message( | ||||||
|  | |||||||
| @ -10,6 +10,7 @@ use self::transformers as stripe; | |||||||
| use super::utils::RefundsRequestData; | use super::utils::RefundsRequestData; | ||||||
| use crate::{ | use crate::{ | ||||||
|     configs::settings, |     configs::settings, | ||||||
|  |     connector::utils as conn_utils, | ||||||
|     consts, |     consts, | ||||||
|     core::{ |     core::{ | ||||||
|         errors::{self, CustomResult}, |         errors::{self, CustomResult}, | ||||||
| @ -1620,13 +1621,17 @@ impl api::IncomingWebhook for Stripe { | |||||||
|         db: &dyn StorageInterface, |         db: &dyn StorageInterface, | ||||||
|         merchant_id: &str, |         merchant_id: &str, | ||||||
|     ) -> CustomResult<Vec<u8>, errors::ConnectorError> { |     ) -> CustomResult<Vec<u8>, errors::ConnectorError> { | ||||||
|         let key = format!("whsec_verification_{}_{}", self.id(), merchant_id); |         let key = conn_utils::get_webhook_merchant_secret_key(self.id(), merchant_id); | ||||||
|         let secret = db |         let secret = match db.find_config_by_key(&key).await { | ||||||
|             .get_key(&key) |             Ok(config) => Some(config), | ||||||
|             .await |             Err(e) => { | ||||||
|             .change_context(errors::ConnectorError::WebhookVerificationSecretNotFound)?; |                 crate::logger::warn!("Unable to fetch merchant webhook secret from DB: {:#?}", e); | ||||||
|  |                 None | ||||||
|         Ok(secret) |             } | ||||||
|  |         }; | ||||||
|  |         Ok(secret | ||||||
|  |             .map(|conf| conf.config.into_bytes()) | ||||||
|  |             .unwrap_or_default()) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn get_webhook_object_reference_id( |     fn get_webhook_object_reference_id( | ||||||
|  | |||||||
| @ -10,6 +10,7 @@ use transformers as trustpay; | |||||||
| use super::utils::collect_and_sort_values_by_removing_signature; | use super::utils::collect_and_sort_values_by_removing_signature; | ||||||
| use crate::{ | use crate::{ | ||||||
|     configs::settings, |     configs::settings, | ||||||
|  |     connector::utils as conn_utils, | ||||||
|     consts, |     consts, | ||||||
|     core::{ |     core::{ | ||||||
|         errors::{self, CustomResult}, |         errors::{self, CustomResult}, | ||||||
| @ -729,12 +730,17 @@ impl api::IncomingWebhook for Trustpay { | |||||||
|         db: &dyn crate::db::StorageInterface, |         db: &dyn crate::db::StorageInterface, | ||||||
|         merchant_id: &str, |         merchant_id: &str, | ||||||
|     ) -> CustomResult<Vec<u8>, errors::ConnectorError> { |     ) -> CustomResult<Vec<u8>, errors::ConnectorError> { | ||||||
|         let key = format!("whsec_verification_{}_{}", self.id(), merchant_id); |         let key = conn_utils::get_webhook_merchant_secret_key(self.id(), merchant_id); | ||||||
|         let secret = db |         let secret = match db.find_config_by_key(&key).await { | ||||||
|             .get_key(&key) |             Ok(config) => Some(config), | ||||||
|             .await |             Err(e) => { | ||||||
|             .change_context(errors::ConnectorError::WebhookVerificationSecretNotFound)?; |                 crate::logger::warn!("Unable to fetch merchant webhook secret from DB: {:#?}", e); | ||||||
|         Ok(secret) |                 None | ||||||
|  |             } | ||||||
|  |         }; | ||||||
|  |         Ok(secret | ||||||
|  |             .map(|conf| conf.config.into_bytes()) | ||||||
|  |             .unwrap_or_default()) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn get_dispute_details( |     fn get_dispute_details( | ||||||
|  | |||||||
| @ -793,3 +793,8 @@ pub fn collect_and_sort_values_by_removing_signature( | |||||||
|     values.sort(); |     values.sort(); | ||||||
|     values |     values | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #[inline] | ||||||
|  | pub fn get_webhook_merchant_secret_key(connector: &str, merchant_id: &str) -> String { | ||||||
|  |     format!("whsec_verification_{connector}_{merchant_id}") | ||||||
|  | } | ||||||
|  | |||||||
| @ -713,13 +713,17 @@ impl api::IncomingWebhook for Worldline { | |||||||
|         db: &dyn StorageInterface, |         db: &dyn StorageInterface, | ||||||
|         merchant_id: &str, |         merchant_id: &str, | ||||||
|     ) -> CustomResult<Vec<u8>, errors::ConnectorError> { |     ) -> CustomResult<Vec<u8>, errors::ConnectorError> { | ||||||
|         let key = format!("whsec_verification_{}_{}", self.id(), merchant_id); |         let key = conn_utils::get_webhook_merchant_secret_key(self.id(), merchant_id); | ||||||
|         let secret = db |         let secret = match db.find_config_by_key(&key).await { | ||||||
|             .get_key(&key) |             Ok(config) => Some(config), | ||||||
|             .await |             Err(e) => { | ||||||
|             .change_context(errors::ConnectorError::WebhookVerificationSecretNotFound)?; |                 crate::logger::warn!("Unable to fetch merchant webhook secret from DB: {:#?}", e); | ||||||
|  |                 None | ||||||
|         Ok(secret) |             } | ||||||
|  |         }; | ||||||
|  |         Ok(secret | ||||||
|  |             .map(|conf| conf.config.into_bytes()) | ||||||
|  |             .unwrap_or_default()) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn get_webhook_object_reference_id( |     fn get_webhook_object_reference_id( | ||||||
|  | |||||||
| @ -641,12 +641,17 @@ impl api::IncomingWebhook for Worldpay { | |||||||
|         db: &dyn StorageInterface, |         db: &dyn StorageInterface, | ||||||
|         merchant_id: &str, |         merchant_id: &str, | ||||||
|     ) -> CustomResult<Vec<u8>, errors::ConnectorError> { |     ) -> CustomResult<Vec<u8>, errors::ConnectorError> { | ||||||
|         let key = format!("wh_mer_sec_verification_{}_{}", self.id(), merchant_id); |         let key = utils::get_webhook_merchant_secret_key(self.id(), merchant_id); | ||||||
|         let secret = db |         let secret = match db.find_config_by_key(&key).await { | ||||||
|             .get_key(&key) |             Ok(config) => Some(config), | ||||||
|             .await |             Err(e) => { | ||||||
|             .change_context(errors::ConnectorError::WebhookVerificationSecretNotFound)?; |                 crate::logger::warn!("Unable to fetch merchant webhook secret from DB: {:#?}", e); | ||||||
|         Ok(secret) |                 None | ||||||
|  |             } | ||||||
|  |         }; | ||||||
|  |         Ok(secret | ||||||
|  |             .map(|conf| conf.config.into_bytes()) | ||||||
|  |             .unwrap_or_default()) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn get_webhook_source_verification_message( |     fn get_webhook_source_verification_message( | ||||||
|  | |||||||
| @ -11,6 +11,7 @@ use self::transformers::{ZenPaymentStatus, ZenWebhookTxnType}; | |||||||
| use super::utils::RefundsRequestData; | use super::utils::RefundsRequestData; | ||||||
| use crate::{ | use crate::{ | ||||||
|     configs::settings, |     configs::settings, | ||||||
|  |     connector::utils as conn_utils, | ||||||
|     core::{ |     core::{ | ||||||
|         errors::{self, CustomResult}, |         errors::{self, CustomResult}, | ||||||
|         payments, |         payments, | ||||||
| @ -477,13 +478,17 @@ impl api::IncomingWebhook for Zen { | |||||||
|         db: &dyn StorageInterface, |         db: &dyn StorageInterface, | ||||||
|         merchant_id: &str, |         merchant_id: &str, | ||||||
|     ) -> CustomResult<Vec<u8>, errors::ConnectorError> { |     ) -> CustomResult<Vec<u8>, errors::ConnectorError> { | ||||||
|         let key = format!("whsec_verification_{}_{}", self.id(), merchant_id); |         let key = conn_utils::get_webhook_merchant_secret_key(self.id(), merchant_id); | ||||||
|         let secret = db |         let secret = match db.find_config_by_key(&key).await { | ||||||
|             .find_config_by_key(&key) |             Ok(config) => Some(config), | ||||||
|             .await |             Err(e) => { | ||||||
|             .change_context(errors::ConnectorError::WebhookVerificationSecretNotFound)?; |                 crate::logger::warn!("Unable to fetch merchant webhook secret from DB: {:#?}", e); | ||||||
|  |                 None | ||||||
|         Ok(secret.config.into_bytes()) |             } | ||||||
|  |         }; | ||||||
|  |         Ok(secret | ||||||
|  |             .map(|conf| conf.config.into_bytes()) | ||||||
|  |             .unwrap_or_default()) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async fn verify_webhook_source( |     async fn verify_webhook_source( | ||||||
|  | |||||||
| @ -629,7 +629,9 @@ pub async fn webhooks_core<W: api::OutgoingWebhookType>( | |||||||
|         connector_name, |         connector_name, | ||||||
|         api::GetToken::Connector, |         api::GetToken::Connector, | ||||||
|     ) |     ) | ||||||
|     .change_context(errors::ApiErrorResponse::InternalServerError) |     .change_context(errors::ApiErrorResponse::InvalidRequestData { | ||||||
|  |         message: "invalid connnector name received".to_string(), | ||||||
|  |     }) | ||||||
|     .attach_printable("Failed construction of ConnectorData")?; |     .attach_printable("Failed construction of ConnectorData")?; | ||||||
|  |  | ||||||
|     let connector = connector.connector; |     let connector = connector.connector; | ||||||
| @ -654,7 +656,7 @@ pub async fn webhooks_core<W: api::OutgoingWebhookType>( | |||||||
|  |  | ||||||
|     let event_type = connector |     let event_type = connector | ||||||
|         .get_webhook_event_type(&request_details) |         .get_webhook_event_type(&request_details) | ||||||
|         .change_context(errors::ApiErrorResponse::InternalServerError) |         .switch() | ||||||
|         .attach_printable("Could not find event type in incoming webhook body")?; |         .attach_printable("Could not find event type in incoming webhook body")?; | ||||||
|  |  | ||||||
|     let process_webhook_further = utils::lookup_webhook_event( |     let process_webhook_further = utils::lookup_webhook_event( | ||||||
|  | |||||||
| @ -66,7 +66,8 @@ impl<T> WebhookApiErrorSwitch<T> for errors::CustomResult<T, errors::ConnectorEr | |||||||
|                 | errors::ConnectorError::WebhookReferenceIdNotFound |                 | errors::ConnectorError::WebhookReferenceIdNotFound | ||||||
|                 | errors::ConnectorError::WebhookEventTypeNotFound |                 | errors::ConnectorError::WebhookEventTypeNotFound | ||||||
|                 | errors::ConnectorError::WebhookResourceObjectNotFound |                 | errors::ConnectorError::WebhookResourceObjectNotFound | ||||||
|                 | errors::ConnectorError::WebhookBodyDecodingFailed => { |                 | errors::ConnectorError::WebhookBodyDecodingFailed | ||||||
|  |                 | errors::ConnectorError::WebhooksNotImplemented => { | ||||||
|                     Err(e).change_context(errors::ApiErrorResponse::WebhookBadRequest) |                     Err(e).change_context(errors::ApiErrorResponse::WebhookBadRequest) | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 ItsMeShashank
					ItsMeShashank