refactor: Move trait IncomingWebhook to hyperswitch_interfaces (#5191)

This commit is contained in:
DEEPANSHU BANSAL
2024-07-11 16:01:31 +05:30
committed by GitHub
parent 3312e787f9
commit 35d502e3da
27 changed files with 612 additions and 573 deletions

View File

@ -9,6 +9,11 @@ use api_models::{
};
use common_utils::{errors::ReportSwitchExt, events::ApiEventsType};
use error_stack::{report, ResultExt};
use hyperswitch_domain_models::{
router_request_types::VerifyWebhookSourceRequestData,
router_response_types::{VerifyWebhookSourceResponseData, VerifyWebhookStatus},
};
use hyperswitch_interfaces::webhooks::IncomingWebhookRequestDetails;
use masking::ExposeInterface;
use router_env::{instrument, metrics::add_attributes, tracing, tracing_actix_web::RequestId};
@ -19,6 +24,7 @@ use crate::{
api_locking,
errors::{self, ConnectorErrorExt, CustomResult, RouterResponse, StorageErrorExt},
metrics, payments, refunds, utils as core_utils,
webhooks::utils::construct_webhook_router_data,
},
db::StorageInterface,
events::api_logs::ApiEvent,
@ -32,7 +38,10 @@ use crate::{
ConnectorValidation,
},
types::{
api::{self, mandates::MandateResponseExt, ConnectorCommon, IncomingWebhook},
api::{
self, mandates::MandateResponseExt, ConnectorCommon, ConnectorData, GetToken,
IncomingWebhook,
},
domain,
storage::{self, enums},
transformers::{ForeignFrom, ForeignInto, ForeignTryFrom},
@ -129,7 +138,7 @@ async fn incoming_webhooks_core<W: types::OutgoingWebhookType>(
merchant_account.merchant_id.clone(),
)],
);
let mut request_details = api::IncomingWebhookRequestDetails {
let mut request_details = IncomingWebhookRequestDetails {
method: req.method().clone(),
uri: req.uri().clone(),
headers: req.headers(),
@ -150,9 +159,14 @@ async fn incoming_webhooks_core<W: types::OutgoingWebhookType>(
let decoded_body = connector
.decode_webhook_body(
&*state.clone().store,
&request_details,
&merchant_account.merchant_id,
merchant_connector_account
.clone()
.and_then(|merchant_connector_account| {
merchant_connector_account.connector_webhook_details
}),
connector_name.as_str(),
)
.await
.switch()
@ -258,30 +272,32 @@ async fn incoming_webhooks_core<W: types::OutgoingWebhookType>(
.connectors_with_webhook_source_verification_call
.contains(&connector_enum)
{
connector
.verify_webhook_source_verification_call(
&state,
&merchant_account,
merchant_connector_account.clone(),
&connector_name,
&request_details,
)
.await
.or_else(|error| match error.current_context() {
errors::ConnectorError::WebhookSourceVerificationFailed => {
logger::error!(?error, "Source Verification Failed");
Ok(false)
}
_ => Err(error),
})
.switch()
.attach_printable("There was an issue in incoming webhook source verification")?
verify_webhook_source_verification_call(
connector.clone(),
&state,
&merchant_account,
merchant_connector_account.clone(),
&connector_name,
&request_details,
)
.await
.or_else(|error| match error.current_context() {
errors::ConnectorError::WebhookSourceVerificationFailed => {
logger::error!(?error, "Source Verification Failed");
Ok(false)
}
_ => Err(error),
})
.switch()
.attach_printable("There was an issue in incoming webhook source verification")?
} else {
connector
.clone()
.verify_webhook_source(
&request_details,
&merchant_account,
merchant_connector_account.clone(),
&merchant_account.merchant_id,
merchant_connector_account.connector_webhook_details.clone(),
merchant_connector_account.connector_account_details.clone(),
connector_name.as_str(),
)
.await
@ -970,7 +986,7 @@ async fn external_authentication_incoming_webhook_flow(
key_store: domain::MerchantKeyStore,
source_verified: bool,
event_type: webhooks::IncomingWebhookEvent,
request_details: &api::IncomingWebhookRequestDetails<'_>,
request_details: &IncomingWebhookRequestDetails<'_>,
connector: &ConnectorEnum,
object_ref_id: api::ObjectReferenceId,
business_profile: diesel_models::business_profile::BusinessProfile,
@ -1346,7 +1362,7 @@ async fn disputes_incoming_webhook_flow(
webhook_details: api::IncomingWebhookDetails,
source_verified: bool,
connector: &ConnectorEnum,
request_details: &api::IncomingWebhookRequestDetails<'_>,
request_details: &IncomingWebhookRequestDetails<'_>,
event_type: webhooks::IncomingWebhookEvent,
) -> CustomResult<WebhookResponseTracker, errors::ApiErrorResponse> {
metrics::INCOMING_DISPUTE_WEBHOOK_METRIC.add(&metrics::CONTEXT, 1, &[]);
@ -1534,6 +1550,66 @@ async fn get_payment_id(
.to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)
}
#[inline]
async fn verify_webhook_source_verification_call(
connector: ConnectorEnum,
state: &SessionState,
merchant_account: &domain::MerchantAccount,
merchant_connector_account: domain::MerchantConnectorAccount,
connector_name: &str,
request_details: &IncomingWebhookRequestDetails<'_>,
) -> CustomResult<bool, errors::ConnectorError> {
let connector_data = ConnectorData::get_connector_by_name(
&state.conf.connectors,
connector_name,
GetToken::Connector,
None,
)
.change_context(errors::ConnectorError::WebhookSourceVerificationFailed)
.attach_printable("invalid connector name received in payment attempt")?;
let connector_integration: services::BoxedWebhookSourceVerificationConnectorIntegrationInterface<
hyperswitch_domain_models::router_flow_types::VerifyWebhookSource,
VerifyWebhookSourceRequestData,
VerifyWebhookSourceResponseData,
> = connector_data.connector.get_connector_integration();
let connector_webhook_secrets = connector
.get_webhook_source_verification_merchant_secret(
&merchant_account.merchant_id,
connector_name,
merchant_connector_account.connector_webhook_details.clone(),
)
.await
.change_context(errors::ConnectorError::WebhookSourceVerificationFailed)?;
let router_data = construct_webhook_router_data(
connector_name,
merchant_connector_account,
merchant_account,
&connector_webhook_secrets,
request_details,
)
.await
.change_context(errors::ConnectorError::WebhookSourceVerificationFailed)
.attach_printable("Failed while constructing webhook router data")?;
let response = services::execute_connector_processing_step(
state,
connector_integration,
&router_data,
payments::CallConnectorAction::Trigger,
None,
)
.await?;
let verification_result = response
.response
.map(|response| response.verify_webhook_status);
match verification_result {
Ok(VerifyWebhookStatus::SourceVerified) => Ok(true),
_ => Ok(false),
}
}
fn get_connector_by_connector_name(
state: &SessionState,
connector_name: &str,
@ -1562,10 +1638,10 @@ fn get_connector_by_connector_name(
authentication_connector_data.connector_name.to_string(),
)
} else {
let connector_data = api::ConnectorData::get_connector_by_name(
let connector_data = ConnectorData::get_connector_by_name(
&state.conf.connectors,
connector_name,
api::GetToken::Connector,
GetToken::Connector,
merchant_connector_id,
)
.change_context(errors::ApiErrorResponse::InvalidRequestData {