Skip to content

Commit

Permalink
refactor(core): add error handling wrapper to wehbook (#6636)
Browse files Browse the repository at this point in the history
  • Loading branch information
Sakilmostak committed Nov 27, 2024
1 parent 0855a9e commit 17c5aa4
Show file tree
Hide file tree
Showing 12 changed files with 151 additions and 33 deletions.
3 changes: 3 additions & 0 deletions crates/api_models/src/connector_enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,9 @@ impl Connector {
pub fn is_pre_processing_required_before_authorize(&self) -> bool {
matches!(self, Self::Airwallex)
}
pub fn should_acknowledge_webhook_for_resource_not_found_errors(&self) -> bool {
matches!(self, Self::Adyenplatform)
}
#[cfg(feature = "dummy_connector")]
pub fn validate_dummy_connector_enabled(
&self,
Expand Down
3 changes: 2 additions & 1 deletion crates/hyperswitch_connectors/src/connectors/cashtocode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use hyperswitch_interfaces::{
errors,
events::connector_api_logs::ConnectorEvent,
types::{PaymentsAuthorizeType, Response},
webhooks,
webhooks::{self, IncomingWebhookFlowError},
};
use masking::{Mask, PeekInterface, Secret};
use transformers as cashtocode;
Expand Down Expand Up @@ -420,6 +420,7 @@ impl webhooks::IncomingWebhook for Cashtocode {
fn get_webhook_api_response(
&self,
request: &webhooks::IncomingWebhookRequestDetails<'_>,
_error_kind: Option<IncomingWebhookFlowError>,
) -> CustomResult<ApplicationResponse<serde_json::Value>, errors::ConnectorError> {
let status = "EXECUTED".to_string();
let obj: transformers::CashtocodePaymentsSyncResponse = request
Expand Down
3 changes: 2 additions & 1 deletion crates/hyperswitch_connectors/src/connectors/worldline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ use hyperswitch_interfaces::{
PaymentsAuthorizeType, PaymentsCaptureType, PaymentsSyncType, PaymentsVoidType,
RefundExecuteType, RefundSyncType, Response,
},
webhooks,
webhooks::{self, IncomingWebhookFlowError},
};
use masking::{ExposeInterface, Mask, PeekInterface};
use ring::hmac;
Expand Down Expand Up @@ -814,6 +814,7 @@ impl webhooks::IncomingWebhook for Worldline {
fn get_webhook_api_response(
&self,
request: &webhooks::IncomingWebhookRequestDetails<'_>,
_error_kind: Option<IncomingWebhookFlowError>,
) -> CustomResult<
hyperswitch_domain_models::api::ApplicationResponse<serde_json::Value>,
errors::ConnectorError,
Expand Down
3 changes: 2 additions & 1 deletion crates/hyperswitch_connectors/src/connectors/zen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ use hyperswitch_interfaces::{
errors,
events::connector_api_logs::ConnectorEvent,
types::{PaymentsAuthorizeType, PaymentsSyncType, RefundExecuteType, RefundSyncType, Response},
webhooks::{IncomingWebhook, IncomingWebhookRequestDetails},
webhooks::{IncomingWebhook, IncomingWebhookFlowError, IncomingWebhookRequestDetails},
};
use masking::{Mask, PeekInterface, Secret};
use transformers::{self as zen, ZenPaymentStatus, ZenWebhookTxnType};
Expand Down Expand Up @@ -671,6 +671,7 @@ impl IncomingWebhook for Zen {
fn get_webhook_api_response(
&self,
_request: &IncomingWebhookRequestDetails<'_>,
_error_kind: Option<IncomingWebhookFlowError>,
) -> CustomResult<ApplicationResponse<serde_json::Value>, errors::ConnectorError> {
Ok(ApplicationResponse::Json(serde_json::json!({
"status": "ok"
Expand Down
3 changes: 2 additions & 1 deletion crates/hyperswitch_connectors/src/connectors/zsl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ use hyperswitch_interfaces::{
errors,
events::connector_api_logs::ConnectorEvent,
types::{self, Response},
webhooks::{IncomingWebhook, IncomingWebhookRequestDetails},
webhooks::{IncomingWebhook, IncomingWebhookFlowError, IncomingWebhookRequestDetails},
};
use masking::{ExposeInterface, Secret};
use transformers::{self as zsl, get_status};
Expand Down Expand Up @@ -442,6 +442,7 @@ impl IncomingWebhook for Zsl {
fn get_webhook_api_response(
&self,
_request: &IncomingWebhookRequestDetails<'_>,
_error_kind: Option<IncomingWebhookFlowError>,
) -> CustomResult<ApplicationResponse<serde_json::Value>, errors::ConnectorError> {
Ok(ApplicationResponse::TextPlain("CALLBACK-OK".to_string()))
}
Expand Down
29 changes: 28 additions & 1 deletion crates/hyperswitch_interfaces/src/webhooks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
use common_utils::{crypto, errors::CustomResult, ext_traits::ValueExt};
use error_stack::ResultExt;
use hyperswitch_domain_models::api::ApplicationResponse;
use hyperswitch_domain_models::{
api::ApplicationResponse, errors::api_error_response::ApiErrorResponse,
};
use masking::{ExposeInterface, Secret};

use crate::{api::ConnectorCommon, errors};
Expand All @@ -22,6 +24,30 @@ pub struct IncomingWebhookRequestDetails<'a> {
pub query_params: String,
}

/// IncomingWebhookFlowError enum defining the error type for incoming webhook
#[derive(Debug)]
pub enum IncomingWebhookFlowError {
/// Resource not found for the webhook
ResourceNotFound,
/// Internal error for the webhook
InternalError,
}

impl From<&ApiErrorResponse> for IncomingWebhookFlowError {
fn from(api_error_response: &ApiErrorResponse) -> Self {
match api_error_response {
ApiErrorResponse::WebhookResourceNotFound
| ApiErrorResponse::DisputeNotFound { .. }
| ApiErrorResponse::PayoutNotFound
| ApiErrorResponse::MandateNotFound
| ApiErrorResponse::PaymentNotFound
| ApiErrorResponse::RefundNotFound
| ApiErrorResponse::AuthenticationNotFound { .. } => Self::ResourceNotFound,
_ => Self::InternalError,
}
}
}

/// Trait defining incoming webhook
#[async_trait::async_trait]
pub trait IncomingWebhook: ConnectorCommon + Sync {
Expand Down Expand Up @@ -203,6 +229,7 @@ pub trait IncomingWebhook: ConnectorCommon + Sync {
fn get_webhook_api_response(
&self,
_request: &IncomingWebhookRequestDetails<'_>,
_error_kind: Option<IncomingWebhookFlowError>,
) -> CustomResult<ApplicationResponse<serde_json::Value>, errors::ConnectorError> {
Ok(ApplicationResponse::StatusOk)
}
Expand Down
2 changes: 2 additions & 0 deletions crates/router/src/connector/adyen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use common_utils::{
};
use diesel_models::{enums as storage_enums, enums};
use error_stack::{report, ResultExt};
use hyperswitch_interfaces::webhooks::IncomingWebhookFlowError;
use masking::{ExposeInterface, Secret};
use ring::hmac;
use router_env::{instrument, tracing};
Expand Down Expand Up @@ -1880,6 +1881,7 @@ impl api::IncomingWebhook for Adyen {
fn get_webhook_api_response(
&self,
_request: &api::IncomingWebhookRequestDetails<'_>,
_error_kind: Option<IncomingWebhookFlowError>,
) -> CustomResult<services::api::ApplicationResponse<serde_json::Value>, errors::ConnectorError>
{
Ok(services::api::ApplicationResponse::TextPlain(
Expand Down
31 changes: 24 additions & 7 deletions crates/router/src/connector/adyenplatform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ use error_stack::report;
use error_stack::ResultExt;
#[cfg(feature = "payouts")]
use http::HeaderName;
use hyperswitch_interfaces::webhooks::IncomingWebhookFlowError;
use masking::Maskable;
#[cfg(feature = "payouts")]
use masking::Secret;
#[cfg(feature = "payouts")]
Expand All @@ -27,11 +29,7 @@ use crate::{
configs::settings,
core::errors::{self, CustomResult},
headers,
services::{
self,
request::{self, Mask},
ConnectorValidation,
},
services::{self, request::Mask, ConnectorValidation},
types::{
self,
api::{self, ConnectorCommon},
Expand Down Expand Up @@ -67,7 +65,7 @@ impl ConnectorCommon for Adyenplatform {
fn get_auth_header(
&self,
auth_type: &types::ConnectorAuthType,
) -> CustomResult<Vec<(String, request::Maskable<String>)>, errors::ConnectorError> {
) -> CustomResult<Vec<(String, Maskable<String>)>, errors::ConnectorError> {
let auth = adyenplatform::AdyenplatformAuthType::try_from(auth_type)
.change_context(errors::ConnectorError::FailedToObtainAuthType)?;
Ok(vec![(
Expand Down Expand Up @@ -209,7 +207,7 @@ impl services::ConnectorIntegration<api::PoFulfill, types::PayoutsData, types::P
&self,
req: &types::PayoutsRouterData<api::PoFulfill>,
_connectors: &settings::Connectors,
) -> CustomResult<Vec<(String, request::Maskable<String>)>, errors::ConnectorError> {
) -> CustomResult<Vec<(String, Maskable<String>)>, errors::ConnectorError> {
let mut header = vec![(
headers::CONTENT_TYPE.to_string(),
types::PayoutFulfillType::get_content_type(self)
Expand Down Expand Up @@ -401,6 +399,25 @@ impl api::IncomingWebhook for Adyenplatform {
}
}

fn get_webhook_api_response(
&self,
_request: &api::IncomingWebhookRequestDetails<'_>,
error_kind: Option<IncomingWebhookFlowError>,
) -> CustomResult<services::api::ApplicationResponse<serde_json::Value>, errors::ConnectorError>
{
if error_kind.is_some() {
Ok(services::api::ApplicationResponse::JsonWithHeaders((
serde_json::Value::Null,
vec![(
"x-http-code".to_string(),
Maskable::Masked(Secret::new("404".to_string())),
)],
)))
} else {
Ok(services::api::ApplicationResponse::StatusOk)
}
}

fn get_webhook_event_type(
&self,
#[cfg(feature = "payouts")] request: &api::IncomingWebhookRequestDetails<'_>,
Expand Down
2 changes: 2 additions & 0 deletions crates/router/src/connector/braintree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use common_utils::{
};
use diesel_models::enums;
use error_stack::{report, Report, ResultExt};
use hyperswitch_interfaces::webhooks::IncomingWebhookFlowError;
use masking::{ExposeInterface, PeekInterface, Secret};
use ring::hmac;
use sha1::{Digest, Sha1};
Expand Down Expand Up @@ -980,6 +981,7 @@ impl api::IncomingWebhook for Braintree {
fn get_webhook_api_response(
&self,
_request: &api::IncomingWebhookRequestDetails<'_>,
_error_kind: Option<IncomingWebhookFlowError>,
) -> CustomResult<services::api::ApplicationResponse<serde_json::Value>, errors::ConnectorError>
{
Ok(services::api::ApplicationResponse::TextPlain(
Expand Down
Loading

0 comments on commit 17c5aa4

Please sign in to comment.