mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-29 17:19:15 +08:00
feat(compatibility): add support for stripe compatible webhooks (#1728)
This commit is contained in:
committed by
GitHub
parent
14c2d72509
commit
87ae99f7f2
@ -1,7 +1,6 @@
|
||||
pub mod transformers;
|
||||
pub mod types;
|
||||
pub mod utils;
|
||||
|
||||
use common_utils::{crypto::SignMessage, ext_traits};
|
||||
use error_stack::{report, IntoReport, ResultExt};
|
||||
use masking::ExposeInterface;
|
||||
use router_env::{instrument, tracing};
|
||||
@ -14,11 +13,11 @@ use crate::{
|
||||
errors::{self, CustomResult, RouterResponse},
|
||||
payments, refunds,
|
||||
},
|
||||
headers, logger,
|
||||
logger,
|
||||
routes::AppState,
|
||||
services,
|
||||
types::{
|
||||
self, api, domain,
|
||||
self as router_types, api, domain,
|
||||
storage::{self, enums},
|
||||
transformers::{ForeignInto, ForeignTryInto},
|
||||
},
|
||||
@ -29,7 +28,7 @@ const OUTGOING_WEBHOOK_TIMEOUT_SECS: u64 = 5;
|
||||
const MERCHANT_ID: &str = "merchant_id";
|
||||
|
||||
#[instrument(skip_all)]
|
||||
pub async fn payments_incoming_webhook_flow<W: api::OutgoingWebhookType>(
|
||||
pub async fn payments_incoming_webhook_flow<W: types::OutgoingWebhookType>(
|
||||
state: AppState,
|
||||
merchant_account: domain::MerchantAccount,
|
||||
key_store: domain::MerchantKeyStore,
|
||||
@ -108,7 +107,7 @@ pub async fn payments_incoming_webhook_flow<W: api::OutgoingWebhookType>(
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
pub async fn refunds_incoming_webhook_flow<W: api::OutgoingWebhookType>(
|
||||
pub async fn refunds_incoming_webhook_flow<W: types::OutgoingWebhookType>(
|
||||
state: AppState,
|
||||
merchant_account: domain::MerchantAccount,
|
||||
key_store: domain::MerchantKeyStore,
|
||||
@ -325,7 +324,7 @@ pub async fn get_or_update_dispute_object(
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
pub async fn disputes_incoming_webhook_flow<W: api::OutgoingWebhookType>(
|
||||
pub async fn disputes_incoming_webhook_flow<W: types::OutgoingWebhookType>(
|
||||
state: AppState,
|
||||
merchant_account: domain::MerchantAccount,
|
||||
webhook_details: api::IncomingWebhookDetails,
|
||||
@ -388,7 +387,7 @@ pub async fn disputes_incoming_webhook_flow<W: api::OutgoingWebhookType>(
|
||||
}
|
||||
}
|
||||
|
||||
async fn bank_transfer_webhook_flow<W: api::OutgoingWebhookType>(
|
||||
async fn bank_transfer_webhook_flow<W: types::OutgoingWebhookType>(
|
||||
state: AppState,
|
||||
merchant_account: domain::MerchantAccount,
|
||||
key_store: domain::MerchantKeyStore,
|
||||
@ -465,7 +464,7 @@ async fn bank_transfer_webhook_flow<W: api::OutgoingWebhookType>(
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
#[instrument(skip_all)]
|
||||
pub async fn create_event_and_trigger_outgoing_webhook<W: api::OutgoingWebhookType>(
|
||||
pub async fn create_event_and_trigger_outgoing_webhook<W: types::OutgoingWebhookType>(
|
||||
state: AppState,
|
||||
merchant_account: domain::MerchantAccount,
|
||||
event_type: enums::EventType,
|
||||
@ -506,34 +505,9 @@ pub async fn create_event_and_trigger_outgoing_webhook<W: api::OutgoingWebhookTy
|
||||
timestamp: event.created_at,
|
||||
};
|
||||
|
||||
let webhook_signature_payload =
|
||||
ext_traits::Encode::<serde_json::Value>::encode_to_string_of_json(&outgoing_webhook)
|
||||
.change_context(errors::ApiErrorResponse::WebhookProcessingFailure)
|
||||
.attach_printable("failed encoding outgoing webhook payload")?;
|
||||
|
||||
let outgoing_webhooks_signature = merchant_account
|
||||
.payment_response_hash_key
|
||||
.clone()
|
||||
.map(|key| {
|
||||
common_utils::crypto::HmacSha512::sign_message(
|
||||
&common_utils::crypto::HmacSha512,
|
||||
key.as_bytes(),
|
||||
webhook_signature_payload.as_bytes(),
|
||||
)
|
||||
})
|
||||
.transpose()
|
||||
.change_context(errors::ApiErrorResponse::WebhookProcessingFailure)
|
||||
.attach_printable("Failed to sign the message")?
|
||||
.map(hex::encode);
|
||||
|
||||
arbiter.spawn(async move {
|
||||
let result = trigger_webhook_to_merchant::<W>(
|
||||
merchant_account,
|
||||
outgoing_webhook,
|
||||
outgoing_webhooks_signature,
|
||||
&state,
|
||||
)
|
||||
.await;
|
||||
let result =
|
||||
trigger_webhook_to_merchant::<W>(merchant_account, outgoing_webhook, &state).await;
|
||||
|
||||
if let Err(e) = result {
|
||||
logger::error!(?e);
|
||||
@ -544,10 +518,9 @@ pub async fn create_event_and_trigger_outgoing_webhook<W: api::OutgoingWebhookTy
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn trigger_webhook_to_merchant<W: api::OutgoingWebhookType>(
|
||||
pub async fn trigger_webhook_to_merchant<W: types::OutgoingWebhookType>(
|
||||
merchant_account: domain::MerchantAccount,
|
||||
webhook: api::OutgoingWebhook,
|
||||
outgoing_webhooks_signature: Option<String>,
|
||||
state: &AppState,
|
||||
) -> CustomResult<(), errors::WebhooksFlowError> {
|
||||
let webhook_details_json = merchant_account
|
||||
@ -570,7 +543,10 @@ pub async fn trigger_webhook_to_merchant<W: api::OutgoingWebhookType>(
|
||||
|
||||
let transformed_outgoing_webhook = W::from(webhook);
|
||||
|
||||
let transformed_outgoing_webhook_string = types::RequestBody::log_and_get_request_body(
|
||||
let outgoing_webhooks_signature = transformed_outgoing_webhook
|
||||
.get_outgoing_webhooks_signature(merchant_account.payment_response_hash_key.clone())?;
|
||||
|
||||
let transformed_outgoing_webhook_string = router_types::RequestBody::log_and_get_request_body(
|
||||
&transformed_outgoing_webhook,
|
||||
Encode::<serde_json::Value>::encode_to_string_of_json,
|
||||
)
|
||||
@ -583,7 +559,7 @@ pub async fn trigger_webhook_to_merchant<W: api::OutgoingWebhookType>(
|
||||
)];
|
||||
|
||||
if let Some(signature) = outgoing_webhooks_signature {
|
||||
header.push((headers::X_WEBHOOK_SIGNATURE.to_string(), signature.into()))
|
||||
W::add_webhook_header(&mut header, signature)
|
||||
}
|
||||
|
||||
let request = services::RequestBuilder::new()
|
||||
@ -649,7 +625,7 @@ pub async fn trigger_webhook_to_merchant<W: api::OutgoingWebhookType>(
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
pub async fn webhooks_core<W: api::OutgoingWebhookType>(
|
||||
pub async fn webhooks_core<W: types::OutgoingWebhookType>(
|
||||
state: &AppState,
|
||||
req: &actix_web::HttpRequest,
|
||||
merchant_account: domain::MerchantAccount,
|
||||
|
||||
Reference in New Issue
Block a user