fix(router/webhooks): correct webhook error mapping and make source verification optional for all connectors (#1333)

This commit is contained in:
ItsMeShashank
2023-06-02 15:30:37 +05:30
committed by GitHub
parent b681f78d96
commit 71315097dd
23 changed files with 191 additions and 114 deletions

10
Cargo.lock generated
View File

@ -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",

View File

@ -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(

View File

@ -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(

View File

@ -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) => {

View File

@ -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(

View File

@ -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()
} }
} }

View File

@ -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) => {

View File

@ -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(

View File

@ -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()
} }
} }

View File

@ -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()
} }
} }

View File

@ -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(

View File

@ -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(

View File

@ -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(

View File

@ -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(

View File

@ -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(

View File

@ -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(

View File

@ -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(

View File

@ -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}")
}

View File

@ -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(

View File

@ -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(

View File

@ -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(

View File

@ -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(

View File

@ -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)
} }