mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-11-02 12:06:56 +08:00
refactor: Move trait IncomingWebhook to hyperswitch_interfaces (#5191)
This commit is contained in:
@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user