From dea21c65ffc872394caa39e29bcd6674d2e4f174 Mon Sep 17 00:00:00 2001 From: Sampras Lopes Date: Mon, 15 Apr 2024 16:05:40 +0530 Subject: [PATCH] feat(events): Add payment cancel events (#4166) Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com> --- crates/analytics/src/lib.rs | 32 +++++++++++ crates/data_models/src/payments.rs | 4 ++ crates/events/Cargo.toml | 4 +- crates/events/src/actix.rs | 15 ++++++ crates/events/src/lib.rs | 5 +- crates/router/src/analytics.rs | 2 +- .../compatibility/stripe/payment_intents.rs | 21 +++++--- .../src/compatibility/stripe/setup_intents.rs | 12 +++-- crates/router/src/core/payments.rs | 48 ++++++++++++++++- crates/router/src/core/payments/operations.rs | 3 +- .../payments/operations/payment_approve.rs | 3 +- .../payments/operations/payment_cancel.rs | 13 ++++- .../payments/operations/payment_capture.rs | 3 +- .../operations/payment_complete_authorize.rs | 3 +- .../payments/operations/payment_confirm.rs | 3 +- .../payments/operations/payment_create.rs | 3 +- .../payments/operations/payment_reject.rs | 3 +- .../payments/operations/payment_session.rs | 3 +- .../core/payments/operations/payment_start.rs | 3 +- .../payments/operations/payment_status.rs | 4 +- .../payments/operations/payment_update.rs | 3 +- .../payments_incremental_authorization.rs | 6 ++- crates/router/src/core/payments/retry.rs | 16 ++++-- crates/router/src/core/webhooks.rs | 17 +++++- crates/router/src/events/audit_events.rs | 2 + crates/router/src/routes/payments.rs | 53 +++++++++++++------ crates/router/src/routes/webhooks.rs | 3 +- crates/router/src/services/api.rs | 10 +++- crates/router/src/services/authentication.rs | 11 ++++ .../src/workflows/outgoing_webhook_retry.rs | 6 ++- crates/router/src/workflows/payment_sync.rs | 2 + crates/router/tests/payments.rs | 6 ++- crates/router/tests/payments2.rs | 6 ++- crates/router_env/src/lib.rs | 32 ----------- 34 files changed, 269 insertions(+), 91 deletions(-) create mode 100644 crates/events/src/actix.rs diff --git a/crates/analytics/src/lib.rs b/crates/analytics/src/lib.rs index 3b3cbc9c03..eb08d8549d 100644 --- a/crates/analytics/src/lib.rs +++ b/crates/analytics/src/lib.rs @@ -47,8 +47,10 @@ use error_stack::report; use router_env::{ logger, tracing::{self, instrument}, + types::FlowMetric, }; use storage_impl::config::Database; +use strum::Display; use self::{ payments::{ @@ -706,3 +708,33 @@ impl Default for OpensearchConfig { } } } + +/// Analytics Flow routes Enums +/// Info - Dimensions and filters available for the domain +/// Filters - Set of values present for the dimension +/// Metrics - Analytical data on dimensions and metrics +#[derive(Debug, Display, Clone, PartialEq, Eq)] +pub enum AnalyticsFlow { + GetInfo, + GetPaymentMetrics, + GetRefundsMetrics, + GetSdkMetrics, + GetPaymentFilters, + GetRefundFilters, + GetSdkEventFilters, + GetApiEvents, + GetSdkEvents, + GeneratePaymentReport, + GenerateDisputeReport, + GenerateRefundReport, + GetApiEventMetrics, + GetApiEventFilters, + GetConnectorEvents, + GetOutgoingWebhookEvents, + GetGlobalSearchResults, + GetSearchResults, + GetDisputeFilters, + GetDisputeMetrics, +} + +impl FlowMetric for AnalyticsFlow {} diff --git a/crates/data_models/src/payments.rs b/crates/data_models/src/payments.rs index a6df7ede41..8a7dfad5fc 100644 --- a/crates/data_models/src/payments.rs +++ b/crates/data_models/src/payments.rs @@ -27,8 +27,11 @@ pub struct PaymentIntent { pub billing_address_id: Option, pub statement_descriptor_name: Option, pub statement_descriptor_suffix: Option, + #[serde(with = "common_utils::custom_serde::iso8601")] pub created_at: PrimitiveDateTime, + #[serde(with = "common_utils::custom_serde::iso8601")] pub modified_at: PrimitiveDateTime, + #[serde(with = "common_utils::custom_serde::iso8601::option")] pub last_synced: Option, pub setup_future_usage: Option, pub off_session: Option, @@ -54,6 +57,7 @@ pub struct PaymentIntent { pub incremental_authorization_allowed: Option, pub authorization_count: Option, pub fingerprint_id: Option, + #[serde(with = "common_utils::custom_serde::iso8601::option")] pub session_expiry: Option, pub request_external_three_ds_authentication: Option, } diff --git a/crates/events/Cargo.toml b/crates/events/Cargo.toml index b0d352f81e..228fba60a6 100644 --- a/crates/events/Cargo.toml +++ b/crates/events/Cargo.toml @@ -7,9 +7,9 @@ rust-version.workspace = true license.workspace = true [dependencies] -# First Party crates +# First Party crates masking = { version = "0.1.0", path = "../masking" } -router_env = { version = "0.1.0", path = "../router_env" } +router_env = { version = "0.1.0", path = "../router_env", features = ["log_extra_implicit_fields", "log_custom_entries_to_extra"]} # Third Party crates error-stack = "0.4.1" diff --git a/crates/events/src/actix.rs b/crates/events/src/actix.rs new file mode 100644 index 0000000000..094336640e --- /dev/null +++ b/crates/events/src/actix.rs @@ -0,0 +1,15 @@ +use router_env::tracing_actix_web::RequestId; + +use crate::EventInfo; + +impl EventInfo for RequestId { + type Data = String; + + fn data(&self) -> error_stack::Result { + Ok(self.as_hyphenated().to_string()) + } + + fn key(&self) -> String { + "request_id".to_string() + } +} diff --git a/crates/events/src/lib.rs b/crates/events/src/lib.rs index 03bccbb517..0136b64a0f 100644 --- a/crates/events/src/lib.rs +++ b/crates/events/src/lib.rs @@ -12,6 +12,8 @@ //! Event: A trait that defines the event itself. This trait is used to define the data that is sent with the event and defines the event's type & identifier. //! +mod actix; + use std::{collections::HashMap, sync::Arc}; use error_stack::{Result, ResultExt}; @@ -60,7 +62,7 @@ where } /// intermediary structure to build events with in-place info. -#[must_use] +#[must_use = "make sure to call `emit` or `try_emit` to actually emit the event"] pub struct EventBuilder where A: MessagingInterface, @@ -105,7 +107,6 @@ where } /// Emit the event. - #[must_use = "make sure to call `emit` to actually emit the event"] pub fn try_emit(self) -> Result<(), EventsError> { let ts = self.event.timestamp(); self.message_sink diff --git a/crates/router/src/analytics.rs b/crates/router/src/analytics.rs index b3e72008cc..0aec94c205 100644 --- a/crates/router/src/analytics.rs +++ b/crates/router/src/analytics.rs @@ -6,6 +6,7 @@ pub mod routes { api_event::api_events_core, connector_events::connector_events_core, errors::AnalyticsError, lambda_utils::invoke_lambda, outgoing_webhook_event::outgoing_webhook_events_core, sdk_events::sdk_events_core, + AnalyticsFlow, }; use api_models::analytics::{ search::{ @@ -17,7 +18,6 @@ pub mod routes { GetSdkEventMetricRequest, ReportRequest, }; use error_stack::ResultExt; - use router_env::AnalyticsFlow; use crate::{ core::api_locking, diff --git a/crates/router/src/compatibility/stripe/payment_intents.rs b/crates/router/src/compatibility/stripe/payment_intents.rs index 415aaadcbb..d67e10a96e 100644 --- a/crates/router/src/compatibility/stripe/payment_intents.rs +++ b/crates/router/src/compatibility/stripe/payment_intents.rs @@ -56,10 +56,11 @@ pub async fn payment_intents_create( state.into_inner(), &req, create_payment_req, - |state, auth, req, _| { + |state, auth, req, req_state| { let eligible_connectors = req.connector.clone(); payments::payments_core::( state, + req_state, auth.merchant_account, auth.key_store, payments::PaymentCreate, @@ -116,9 +117,10 @@ pub async fn payment_intents_retrieve( state.into_inner(), &req, payload, - |state, auth, payload, _| { + |state, auth, payload, req_state| { payments::payments_core::( state, + req_state, auth.merchant_account, auth.key_store, payments::PaymentStatus, @@ -185,9 +187,10 @@ pub async fn payment_intents_retrieve_with_gateway_creds( state.into_inner(), &req, payload, - |state, auth, req, _| { + |state, auth, req, req_state| { payments::payments_core::( state, + req_state, auth.merchant_account, auth.key_store, payments::PaymentStatus, @@ -249,10 +252,11 @@ pub async fn payment_intents_update( state.into_inner(), &req, payload, - |state, auth, req, _| { + |state, auth, req, req_state| { let eligible_connectors = req.connector.clone(); payments::payments_core::( state, + req_state, auth.merchant_account, auth.key_store, payments::PaymentUpdate, @@ -320,10 +324,11 @@ pub async fn payment_intents_confirm( state.into_inner(), &req, payload, - |state, auth, req, _| { + |state, auth, req, req_state| { let eligible_connectors = req.connector.clone(); payments::payments_core::( state, + req_state, auth.merchant_account, auth.key_store, payments::PaymentConfirm, @@ -381,9 +386,10 @@ pub async fn payment_intents_capture( state.into_inner(), &req, payload, - |state, auth, payload, _| { + |state, auth, payload, req_state| { payments::payments_core::( state, + req_state, auth.merchant_account, auth.key_store, payments::PaymentCapture, @@ -445,9 +451,10 @@ pub async fn payment_intents_cancel( state.into_inner(), &req, payload, - |state, auth, req, _| { + |state, auth, req, req_state| { payments::payments_core::( state, + req_state, auth.merchant_account, auth.key_store, payments::PaymentCancel, diff --git a/crates/router/src/compatibility/stripe/setup_intents.rs b/crates/router/src/compatibility/stripe/setup_intents.rs index d56937e91c..60627ee564 100644 --- a/crates/router/src/compatibility/stripe/setup_intents.rs +++ b/crates/router/src/compatibility/stripe/setup_intents.rs @@ -52,7 +52,7 @@ pub async fn setup_intents_create( state.into_inner(), &req, create_payment_req, - |state, auth, req, _| { + |state, auth, req, req_state| { payments::payments_core::< api_types::SetupMandate, api_types::PaymentsResponse, @@ -62,6 +62,7 @@ pub async fn setup_intents_create( Oss, >( state, + req_state, auth.merchant_account, auth.key_store, payments::PaymentCreate, @@ -118,9 +119,10 @@ pub async fn setup_intents_retrieve( state.into_inner(), &req, payload, - |state, auth, payload, _| { + |state, auth, payload, req_state| { payments::payments_core::( state, + req_state, auth.merchant_account, auth.key_store, payments::PaymentStatus, @@ -183,7 +185,7 @@ pub async fn setup_intents_update( state.into_inner(), &req, payload, - |state, auth, req, _| { + |state, auth, req, req_state| { payments::payments_core::< api_types::SetupMandate, api_types::PaymentsResponse, @@ -193,6 +195,7 @@ pub async fn setup_intents_update( Oss, >( state, + req_state, auth.merchant_account, auth.key_store, payments::PaymentUpdate, @@ -256,7 +259,7 @@ pub async fn setup_intents_confirm( state.into_inner(), &req, payload, - |state, auth, req, _| { + |state, auth, req, req_state| { payments::payments_core::< api_types::SetupMandate, api_types::PaymentsResponse, @@ -266,6 +269,7 @@ pub async fn setup_intents_confirm( Oss, >( state, + req_state, auth.merchant_account, auth.key_store, payments::PaymentConfirm, diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs index 17237c625e..4c087671a2 100644 --- a/crates/router/src/core/payments.rs +++ b/crates/router/src/core/payments.rs @@ -22,6 +22,7 @@ use common_utils::{ext_traits::AsyncExt, pii, types::Surcharge}; use data_models::mandates::{CustomerAcceptance, MandateData}; use diesel_models::{ephemeral_key, fraud_check::FraudCheck}; use error_stack::{report, ResultExt}; +use events::EventInfo; use futures::future::join_all; use helpers::ApplePayData; use masking::Secret; @@ -61,7 +62,7 @@ use crate::{ }, db::StorageInterface, logger, - routes::{metrics, payment_methods::ParentPaymentMethodToken, AppState}, + routes::{app::ReqState, metrics, payment_methods::ParentPaymentMethodToken, AppState}, services::{self, api::Authenticate}, types::{ self as router_types, @@ -82,6 +83,7 @@ use crate::{ #[instrument(skip_all, fields(payment_id, merchant_id))] pub async fn payments_operation_core( state: &AppState, + req_state: ReqState, merchant_account: domain::MerchantAccount, key_store: domain::MerchantKeyStore, operation: Op, @@ -263,6 +265,7 @@ where }; let router_data = call_connector_service( state, + req_state, &merchant_account, &key_store, connector, @@ -318,6 +321,7 @@ where }; let router_data = call_connector_service( state, + req_state.clone(), &merchant_account, &key_store, connector_data.clone(), @@ -349,6 +353,7 @@ where if config_bool && router_data.should_call_gsm() { router_data = retry::do_gsm_actions( state, + req_state, &mut payment_data, connectors, connector_data, @@ -431,6 +436,7 @@ where .to_update_tracker()? .update_trackers( state, + req_state, payment_data.clone(), customer.clone(), validate_result.storage_scheme, @@ -464,6 +470,7 @@ where .to_update_tracker()? .update_trackers( state, + req_state, payment_data.clone(), customer.clone(), validate_result.storage_scheme, @@ -673,6 +680,7 @@ where #[allow(clippy::too_many_arguments)] pub async fn payments_core( state: AppState, + req_state: ReqState, merchant_account: domain::MerchantAccount, key_store: domain::MerchantKeyStore, operation: Op, @@ -709,6 +717,7 @@ where let (payment_data, _req, customer, connector_http_status_code, external_latency) = payments_operation_core::<_, _, _, _, Ctx>( &state, + req_state, merchant_account, key_store, operation.clone(), @@ -753,6 +762,7 @@ pub trait PaymentRedirectFlow: Sync { async fn call_payment_flow( &self, state: &AppState, + req_state: ReqState, merchant_account: domain::MerchantAccount, merchant_key_store: domain::MerchantKeyStore, req: PaymentsRedirectResponseData, @@ -773,6 +783,7 @@ pub trait PaymentRedirectFlow: Sync { async fn handle_payments_redirect_response( &self, state: AppState, + req_state: ReqState, merchant_account: domain::MerchantAccount, key_store: domain::MerchantKeyStore, req: PaymentsRedirectResponseData, @@ -822,6 +833,7 @@ pub trait PaymentRedirectFlow: Sync { let response = self .call_payment_flow( &state, + req_state, merchant_account.clone(), key_store, req.clone(), @@ -861,6 +873,7 @@ impl PaymentRedirectFlow for PaymentRedirectCom async fn call_payment_flow( &self, state: &AppState, + req_state: ReqState, merchant_account: domain::MerchantAccount, merchant_key_store: domain::MerchantKeyStore, req: PaymentsRedirectResponseData, @@ -886,6 +899,7 @@ impl PaymentRedirectFlow for PaymentRedirectCom Ctx, >( state.clone(), + req_state, merchant_account, merchant_key_store, payment_complete_authorize::CompleteAuthorize, @@ -964,6 +978,7 @@ impl PaymentRedirectFlow for PaymentRedirectSyn async fn call_payment_flow( &self, state: &AppState, + req_state: ReqState, merchant_account: domain::MerchantAccount, merchant_key_store: domain::MerchantKeyStore, req: PaymentsRedirectResponseData, @@ -994,6 +1009,7 @@ impl PaymentRedirectFlow for PaymentRedirectSyn Ctx, >( state.clone(), + req_state, merchant_account, merchant_key_store, PaymentStatus, @@ -1035,6 +1051,7 @@ impl PaymentRedirectFlow for PaymentAuthenticat async fn call_payment_flow( &self, state: &AppState, + req_state: ReqState, merchant_account: domain::MerchantAccount, merchant_key_store: domain::MerchantKeyStore, req: PaymentsRedirectResponseData, @@ -1060,6 +1077,7 @@ impl PaymentRedirectFlow for PaymentAuthenticat Ctx, >( state.clone(), + req_state, merchant_account, merchant_key_store, PaymentConfirm, @@ -1133,6 +1151,7 @@ impl PaymentRedirectFlow for PaymentAuthenticat #[instrument(skip_all)] pub async fn call_connector_service( state: &AppState, + req_state: ReqState, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, connector: api::ConnectorData, @@ -1324,6 +1343,7 @@ where .to_update_tracker()? .update_trackers( state, + req_state, payment_data.clone(), customer.clone(), merchant_account.storage_scheme, @@ -2292,6 +2312,32 @@ where pub recurring_details: Option, } +#[derive(Clone, serde::Serialize, Debug)] +pub struct PaymentEvent { + payment_intent: storage::PaymentIntent, + payment_attempt: storage::PaymentAttempt, +} + +impl PaymentData { + fn to_event(&self) -> PaymentEvent { + PaymentEvent { + payment_intent: self.payment_intent.clone(), + payment_attempt: self.payment_attempt.clone(), + } + } +} + +impl EventInfo for PaymentEvent { + type Data = Self; + fn data(&self) -> error_stack::Result { + Ok(self.clone()) + } + + fn key(&self) -> String { + "payment".to_string() + } +} + #[derive(Debug, Default, Clone)] pub struct IncrementalAuthorizationDetails { pub additional_amount: i64, diff --git a/crates/router/src/core/payments/operations.rs b/crates/router/src/core/payments/operations.rs index 3c5757ec24..6b04c500dc 100644 --- a/crates/router/src/core/payments/operations.rs +++ b/crates/router/src/core/payments/operations.rs @@ -32,7 +32,7 @@ use crate::{ payment_methods::PaymentMethodRetrieve, }, db::StorageInterface, - routes::AppState, + routes::{app::ReqState, AppState}, services, types::{ self, @@ -198,6 +198,7 @@ pub trait UpdateTracker: Send { async fn update_trackers<'b>( &'b self, db: &'b AppState, + req_state: ReqState, payment_data: D, customer: Option, storage_scheme: enums::MerchantStorageScheme, diff --git a/crates/router/src/core/payments/operations/payment_approve.rs b/crates/router/src/core/payments/operations/payment_approve.rs index b47608eba9..be73d0836d 100644 --- a/crates/router/src/core/payments/operations/payment_approve.rs +++ b/crates/router/src/core/payments/operations/payment_approve.rs @@ -13,7 +13,7 @@ use crate::{ payment_methods::PaymentMethodRetrieve, payments::{helpers, operations, PaymentData}, }, - routes::AppState, + routes::{app::ReqState, AppState}, services, types::{ api::{self, PaymentIdTypeExt}, @@ -200,6 +200,7 @@ impl async fn update_trackers<'b>( &'b self, db: &'b AppState, + _req_state: ReqState, mut payment_data: PaymentData, _customer: Option, storage_scheme: storage_enums::MerchantStorageScheme, diff --git a/crates/router/src/core/payments/operations/payment_cancel.rs b/crates/router/src/core/payments/operations/payment_cancel.rs index 9cd9ba9f6d..cb1b2fbd67 100644 --- a/crates/router/src/core/payments/operations/payment_cancel.rs +++ b/crates/router/src/core/payments/operations/payment_cancel.rs @@ -14,7 +14,8 @@ use crate::{ payment_methods::PaymentMethodRetrieve, payments::{helpers, operations, PaymentData}, }, - routes::AppState, + events::audit_events::{AuditEvent, AuditEventType}, + routes::{app::ReqState, AppState}, services, types::{ self as core_types, @@ -209,6 +210,7 @@ impl async fn update_trackers<'b>( &'b self, db: &'b AppState, + req_state: ReqState, mut payment_data: PaymentData, _customer: Option, storage_scheme: enums::MerchantStorageScheme, @@ -253,13 +255,20 @@ impl payment_data.payment_attempt.clone(), storage::PaymentAttemptUpdate::VoidUpdate { status: attempt_status_update, - cancellation_reason, + cancellation_reason: cancellation_reason.clone(), updated_by: storage_scheme.to_string(), }, storage_scheme, ) .await .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?; + req_state + .event_context + .event(AuditEvent::new(AuditEventType::PaymentCancelled { + cancellation_reason, + })) + .with(payment_data.to_event()) + .emit(); Ok((Box::new(self), payment_data)) } } diff --git a/crates/router/src/core/payments/operations/payment_capture.rs b/crates/router/src/core/payments/operations/payment_capture.rs index c6dfe6bd3c..a20358cb95 100644 --- a/crates/router/src/core/payments/operations/payment_capture.rs +++ b/crates/router/src/core/payments/operations/payment_capture.rs @@ -13,7 +13,7 @@ use crate::{ payment_methods::PaymentMethodRetrieve, payments::{self, helpers, operations, types::MultipleCaptureData}, }, - routes::AppState, + routes::{app::ReqState, AppState}, services, types::{ self as core_types, @@ -254,6 +254,7 @@ impl async fn update_trackers<'b>( &'b self, db: &'b AppState, + _req_state: ReqState, mut payment_data: payments::PaymentData, _customer: Option, storage_scheme: enums::MerchantStorageScheme, diff --git a/crates/router/src/core/payments/operations/payment_complete_authorize.rs b/crates/router/src/core/payments/operations/payment_complete_authorize.rs index c4da9ca687..e9e0ec36a7 100644 --- a/crates/router/src/core/payments/operations/payment_complete_authorize.rs +++ b/crates/router/src/core/payments/operations/payment_complete_authorize.rs @@ -16,7 +16,7 @@ use crate::{ utils as core_utils, }, db::StorageInterface, - routes::AppState, + routes::{app::ReqState, AppState}, services, types::{ api::{self, PaymentIdTypeExt}, @@ -427,6 +427,7 @@ impl async fn update_trackers<'b>( &'b self, _state: &'b AppState, + _req_state: ReqState, payment_data: PaymentData, _customer: Option, _storage_scheme: storage_enums::MerchantStorageScheme, diff --git a/crates/router/src/core/payments/operations/payment_confirm.rs b/crates/router/src/core/payments/operations/payment_confirm.rs index bdc724a1d2..7af7e13b9f 100644 --- a/crates/router/src/core/payments/operations/payment_confirm.rs +++ b/crates/router/src/core/payments/operations/payment_confirm.rs @@ -24,7 +24,7 @@ use crate::{ utils as core_utils, }, db::StorageInterface, - routes::AppState, + routes::{app::ReqState, AppState}, services, types::{ api::{self, ConnectorCallType, PaymentIdTypeExt}, @@ -903,6 +903,7 @@ impl async fn update_trackers<'b>( &'b self, state: &'b AppState, + _req_state: ReqState, mut payment_data: PaymentData, customer: Option, storage_scheme: storage_enums::MerchantStorageScheme, diff --git a/crates/router/src/core/payments/operations/payment_create.rs b/crates/router/src/core/payments/operations/payment_create.rs index 37f2e67a77..5c5eeb046f 100644 --- a/crates/router/src/core/payments/operations/payment_create.rs +++ b/crates/router/src/core/payments/operations/payment_create.rs @@ -28,7 +28,7 @@ use crate::{ utils as core_utils, }, db::StorageInterface, - routes::AppState, + routes::{app::ReqState, AppState}, services, types::{ self, @@ -556,6 +556,7 @@ impl async fn update_trackers<'b>( &'b self, state: &'b AppState, + _req_state: ReqState, mut payment_data: PaymentData, _customer: Option, storage_scheme: enums::MerchantStorageScheme, diff --git a/crates/router/src/core/payments/operations/payment_reject.rs b/crates/router/src/core/payments/operations/payment_reject.rs index 506f372e94..413a6fb4f0 100644 --- a/crates/router/src/core/payments/operations/payment_reject.rs +++ b/crates/router/src/core/payments/operations/payment_reject.rs @@ -13,7 +13,7 @@ use crate::{ payment_methods::PaymentMethodRetrieve, payments::{helpers, operations, PaymentAddress, PaymentData}, }, - routes::AppState, + routes::{app::ReqState, AppState}, services, types::{ api::{self, PaymentIdTypeExt}, @@ -196,6 +196,7 @@ impl async fn update_trackers<'b>( &'b self, state: &'b AppState, + _req_state: ReqState, mut payment_data: PaymentData, _customer: Option, storage_scheme: enums::MerchantStorageScheme, diff --git a/crates/router/src/core/payments/operations/payment_session.rs b/crates/router/src/core/payments/operations/payment_session.rs index bdae419d21..d963c6864b 100644 --- a/crates/router/src/core/payments/operations/payment_session.rs +++ b/crates/router/src/core/payments/operations/payment_session.rs @@ -15,7 +15,7 @@ use crate::{ payments::{self, helpers, operations, PaymentData}, }, db::StorageInterface, - routes::AppState, + routes::{app::ReqState, AppState}, services, types::{ api::{self, PaymentIdTypeExt}, @@ -221,6 +221,7 @@ impl async fn update_trackers<'b>( &'b self, state: &'b AppState, + _req_state: ReqState, mut payment_data: PaymentData, _customer: Option, storage_scheme: storage_enums::MerchantStorageScheme, diff --git a/crates/router/src/core/payments/operations/payment_start.rs b/crates/router/src/core/payments/operations/payment_start.rs index 29573bc0a3..70fb33851d 100644 --- a/crates/router/src/core/payments/operations/payment_start.rs +++ b/crates/router/src/core/payments/operations/payment_start.rs @@ -14,7 +14,7 @@ use crate::{ payments::{helpers, operations, CustomerDetails, PaymentAddress, PaymentData}, }, db::StorageInterface, - routes::AppState, + routes::{app::ReqState, AppState}, services, types::{ api::{self, PaymentIdTypeExt}, @@ -208,6 +208,7 @@ impl async fn update_trackers<'b>( &'b self, _state: &'b AppState, + _req_state: ReqState, payment_data: PaymentData, _customer: Option, _storage_scheme: storage_enums::MerchantStorageScheme, diff --git a/crates/router/src/core/payments/operations/payment_status.rs b/crates/router/src/core/payments/operations/payment_status.rs index b48fc20d90..c079f93caa 100644 --- a/crates/router/src/core/payments/operations/payment_status.rs +++ b/crates/router/src/core/payments/operations/payment_status.rs @@ -18,7 +18,7 @@ use crate::{ }, }, db::StorageInterface, - routes::AppState, + routes::{app::ReqState, AppState}, services, types::{ api, domain, @@ -155,6 +155,7 @@ impl async fn update_trackers<'b>( &'b self, _state: &'b AppState, + _req_state: ReqState, payment_data: PaymentData, _customer: Option, _storage_scheme: enums::MerchantStorageScheme, @@ -180,6 +181,7 @@ impl async fn update_trackers<'b>( &'b self, _state: &'b AppState, + _req_state: ReqState, payment_data: PaymentData, _customer: Option, _storage_scheme: enums::MerchantStorageScheme, diff --git a/crates/router/src/core/payments/operations/payment_update.rs b/crates/router/src/core/payments/operations/payment_update.rs index efe4501e94..e722a05f76 100644 --- a/crates/router/src/core/payments/operations/payment_update.rs +++ b/crates/router/src/core/payments/operations/payment_update.rs @@ -19,7 +19,7 @@ use crate::{ utils as core_utils, }, db::StorageInterface, - routes::AppState, + routes::{app::ReqState, AppState}, services, types::{ api::{self, PaymentIdTypeExt}, @@ -562,6 +562,7 @@ impl async fn update_trackers<'b>( &'b self, state: &'b AppState, + _req_state: ReqState, mut payment_data: PaymentData, customer: Option, storage_scheme: storage_enums::MerchantStorageScheme, diff --git a/crates/router/src/core/payments/operations/payments_incremental_authorization.rs b/crates/router/src/core/payments/operations/payments_incremental_authorization.rs index 4ce65c991b..7f2311eb88 100644 --- a/crates/router/src/core/payments/operations/payments_incremental_authorization.rs +++ b/crates/router/src/core/payments/operations/payments_incremental_authorization.rs @@ -17,7 +17,10 @@ use crate::{ PaymentAddress, }, }, - routes::{app::StorageInterface, AppState}, + routes::{ + app::{ReqState, StorageInterface}, + AppState, + }, services, types::{ api::{self, PaymentIdTypeExt}, @@ -175,6 +178,7 @@ impl async fn update_trackers<'b>( &'b self, db: &'b AppState, + _req_state: ReqState, mut payment_data: payments::PaymentData, _customer: Option, storage_scheme: enums::MerchantStorageScheme, diff --git a/crates/router/src/core/payments/retry.rs b/crates/router/src/core/payments/retry.rs index 3eeecdba3a..71cded04e1 100644 --- a/crates/router/src/core/payments/retry.rs +++ b/crates/router/src/core/payments/retry.rs @@ -19,10 +19,13 @@ use crate::{ }, }, db::StorageInterface, - routes, - routes::{app, metrics}, - services, types, - types::{api, domain, storage}, + routes::{ + self, + app::{self, ReqState}, + metrics, + }, + services, + types::{self, api, domain, storage}, utils, }; @@ -30,6 +33,7 @@ use crate::{ #[allow(clippy::too_many_arguments)] pub async fn do_gsm_actions( state: &app::AppState, + req_state: ReqState, payment_data: &mut payments::PaymentData, mut connectors: IntoIter, original_connector_data: api::ConnectorData, @@ -81,6 +85,7 @@ where if should_step_up { router_data = do_retry( &state.clone(), + req_state.clone(), original_connector_data, operation, customer, @@ -124,6 +129,7 @@ where router_data = do_retry( &state.clone(), + req_state.clone(), connector, operation, customer, @@ -263,6 +269,7 @@ fn get_flow_name() -> RouterResult { #[instrument(skip_all)] pub async fn do_retry( state: &routes::AppState, + req_state: ReqState, connector: api::ConnectorData, operation: &operations::BoxedOperation<'_, F, ApiRequest, Ctx>, customer: &Option, @@ -299,6 +306,7 @@ where payments::call_connector_service( state, + req_state, merchant_account, key_store, connector, diff --git a/crates/router/src/core/webhooks.rs b/crates/router/src/core/webhooks.rs index 558eed0fef..278ac8f970 100644 --- a/crates/router/src/core/webhooks.rs +++ b/crates/router/src/core/webhooks.rs @@ -39,7 +39,12 @@ use crate::{ outgoing_webhook_logs::{OutgoingWebhookEvent, OutgoingWebhookEventMetric}, }, logger, - routes::{app::AppStateInfo, lock_utils, metrics::request::add_attributes, AppState}, + routes::{ + app::{AppStateInfo, ReqState}, + lock_utils, + metrics::request::add_attributes, + AppState, + }, services::{self, authentication as auth}, types::{ api::{self, mandates::MandateResponseExt}, @@ -56,6 +61,7 @@ const MERCHANT_ID: &str = "merchant_id"; pub async fn payments_incoming_webhook_flow( state: AppState, + req_state: ReqState, merchant_account: domain::MerchantAccount, business_profile: diesel_models::business_profile::BusinessProfile, key_store: domain::MerchantKeyStore, @@ -99,6 +105,7 @@ pub async fn payments_incoming_webhook_flow( Ctx, >( state.clone(), + req_state, merchant_account.clone(), key_store.clone(), payments::operations::PaymentStatus, @@ -564,6 +571,7 @@ pub async fn disputes_incoming_webhook_flow( async fn bank_transfer_webhook_flow( state: AppState, + req_state: ReqState, merchant_account: domain::MerchantAccount, business_profile: diesel_models::business_profile::BusinessProfile, key_store: domain::MerchantKeyStore, @@ -594,6 +602,7 @@ async fn bank_transfer_webhook_flow( Ctx, >( state.clone(), + req_state, merchant_account.to_owned(), key_store.clone(), payments::PaymentConfirm, @@ -1255,9 +1264,11 @@ fn raise_webhooks_analytics_event( state.event_handler().log_event(&webhook_event); } +#[allow(clippy::too_many_arguments)] pub async fn webhooks_wrapper( flow: &impl router_env::types::FlowMetric, state: AppState, + req_state: ReqState, req: &actix_web::HttpRequest, merchant_account: domain::MerchantAccount, key_store: domain::MerchantKeyStore, @@ -1268,6 +1279,7 @@ pub async fn webhooks_wrapper( state.clone(), + req_state, req, merchant_account.clone(), key_store, @@ -1318,6 +1330,7 @@ pub async fn webhooks_wrapper( state: AppState, + req_state: ReqState, req: &actix_web::HttpRequest, merchant_account: domain::MerchantAccount, key_store: domain::MerchantKeyStore, @@ -1558,6 +1571,7 @@ pub async fn webhooks_core Box::pin(payments_incoming_webhook_flow::( state.clone(), + req_state, merchant_account, business_profile, key_store, @@ -1596,6 +1610,7 @@ pub async fn webhooks_core Box::pin(bank_transfer_webhook_flow::( state.clone(), + req_state, merchant_account, business_profile, key_store, diff --git a/crates/router/src/events/audit_events.rs b/crates/router/src/events/audit_events.rs index 90fc8cfe76..0f186e691b 100644 --- a/crates/router/src/events/audit_events.rs +++ b/crates/router/src/events/audit_events.rs @@ -3,6 +3,7 @@ use serde::Serialize; use time::PrimitiveDateTime; #[derive(Debug, Clone, Serialize)] +#[serde(tag = "event_type")] pub enum AuditEventType { Error { error_message: String }, PaymentCreated, @@ -16,6 +17,7 @@ pub enum AuditEventType { #[derive(Debug, Clone, Serialize)] pub struct AuditEvent { + #[serde(flatten)] event_type: AuditEventType, #[serde(with = "common_utils::custom_serde::iso8601")] created_at: PrimitiveDateTime, diff --git a/crates/router/src/routes/payments.rs b/crates/router/src/routes/payments.rs index cf12878c2f..ac45228f90 100644 --- a/crates/router/src/routes/payments.rs +++ b/crates/router/src/routes/payments.rs @@ -9,6 +9,7 @@ use api_models::payments::HeaderPayload; use error_stack::report; use router_env::{env, instrument, tracing, types, Flow}; +use super::app::ReqState; use crate::{ self as app, core::{ @@ -123,10 +124,11 @@ pub async fn payments_create( state, &req, payload, - |state, auth, req, _| { + |state, auth, req, req_state| { authorize_verify_select::<_, Oss>( payments::PaymentCreate, state, + req_state, auth.merchant_account, auth.key_store, payment_types::HeaderPayload::default(), @@ -186,7 +188,7 @@ pub async fn payments_start( state, &req, payload, - |state, auth, req, _| { + |state, auth, req, req_state| { payments::payments_core::< api_types::Authorize, payment_types::PaymentsResponse, @@ -196,6 +198,7 @@ pub async fn payments_start( Oss, >( state, + req_state, auth.merchant_account, auth.key_store, payments::operations::PaymentStart, @@ -267,9 +270,10 @@ pub async fn payments_retrieve( state, &req, payload, - |state, auth, req, _| { + |state, auth, req, req_state| { payments::payments_core::( state, + req_state, auth.merchant_account, auth.key_store, payments::PaymentStatus, @@ -339,9 +343,10 @@ pub async fn payments_retrieve_with_gateway_creds( state, &req, payload, - |state, auth, req, _| { + |state, auth, req, req_state| { payments::payments_core::( state, + req_state, auth.merchant_account, auth.key_store, payments::PaymentStatus, @@ -408,10 +413,11 @@ pub async fn payments_update( state, &req, payload, - |state, auth, req, _| { + |state, auth, req, req_state| { authorize_verify_select::<_, Oss>( payments::PaymentUpdate, state, + req_state, auth.merchant_account, auth.key_store, payment_types::HeaderPayload::default(), @@ -485,10 +491,11 @@ pub async fn payments_confirm( state, &req, payload, - |state, auth, req, _| { + |state, auth, req, req_state| { authorize_verify_select::<_, Oss>( payments::PaymentConfirm, state, + req_state, auth.merchant_account, auth.key_store, header_payload, @@ -543,7 +550,7 @@ pub async fn payments_capture( state, &req, payload, - |state, auth, payload, _| { + |state, auth, payload, req_state| { payments::payments_core::< api_types::Capture, payment_types::PaymentsResponse, @@ -553,6 +560,7 @@ pub async fn payments_capture( Oss, >( state, + req_state, auth.merchant_account, auth.key_store, payments::PaymentCapture, @@ -601,7 +609,7 @@ pub async fn payments_connector_session( state, &req, payload, - |state, auth, payload, _| { + |state, auth, payload, req_state| { payments::payments_core::< api_types::Session, payment_types::PaymentsSessionResponse, @@ -611,6 +619,7 @@ pub async fn payments_connector_session( Oss, >( state, + req_state, auth.merchant_account, auth.key_store, payments::PaymentSession, @@ -672,10 +681,11 @@ pub async fn payments_redirect_response( state, &req, payload, - |state, auth, req, _| { + |state, auth, req, req_state| { >::handle_payments_redirect_response( &payments::PaymentRedirectSync {}, state, + req_state, auth.merchant_account, auth.key_store, req, @@ -732,10 +742,11 @@ pub async fn payments_redirect_response_with_creds_identifier( state, &req, payload, - |state, auth, req, _| { + |state, auth, req, req_state| { >::handle_payments_redirect_response( &payments::PaymentRedirectSync {}, state, + req_state, auth.merchant_account, auth.key_store, req, @@ -774,11 +785,12 @@ pub async fn payments_complete_authorize( state, &req, payload, - |state, auth, req, _| { + |state, auth, req, req_state| { >::handle_payments_redirect_response( &payments::PaymentRedirectCompleteAuthorize {}, state, + req_state, auth.merchant_account, auth.key_store, req, @@ -828,9 +840,10 @@ pub async fn payments_cancel( state, &req, payload, - |state, auth, req, _| { + |state, auth, req, req_state| { payments::payments_core::( state, + req_state, auth.merchant_account, auth.key_store, payments::PaymentCancel, @@ -970,7 +983,7 @@ pub async fn payments_approve( state, &http_req, payload.clone(), - |state, auth, req, _| { + |state, auth, req, req_state| { payments::payments_core::< api_types::Capture, payment_types::PaymentsResponse, @@ -980,6 +993,7 @@ pub async fn payments_approve( Oss, >( state, + req_state, auth.merchant_account, auth.key_store, payments::PaymentApprove, @@ -1030,7 +1044,7 @@ pub async fn payments_reject( state, &http_req, payload.clone(), - |state, auth, req, _| { + |state, auth, req, req_state| { payments::payments_core::< api_types::Void, payment_types::PaymentsResponse, @@ -1040,6 +1054,7 @@ pub async fn payments_reject( Oss, >( state, + req_state, auth.merchant_account, auth.key_store, payments::PaymentReject, @@ -1067,9 +1082,11 @@ pub async fn payments_reject( .await } +#[allow(clippy::too_many_arguments)] async fn authorize_verify_select( operation: Op, state: app::AppState, + req_state: ReqState, merchant_account: domain::MerchantAccount, key_store: domain::MerchantKeyStore, header_payload: HeaderPayload, @@ -1111,6 +1128,7 @@ where Ctx, >( state, + req_state, merchant_account, key_store, operation, @@ -1132,6 +1150,7 @@ where Ctx, >( state, + req_state, merchant_account, key_store, operation, @@ -1184,7 +1203,7 @@ pub async fn payments_incremental_authorization( state, &req, payload, - |state, auth, req, _| { + |state, auth, req, req_state| { payments::payments_core::< api_types::IncrementalAuthorization, payment_types::PaymentsResponse, @@ -1194,6 +1213,7 @@ pub async fn payments_incremental_authorization( Oss, >( state, + req_state, auth.merchant_account, auth.key_store, payments::PaymentIncrementalAuthorization, @@ -1306,10 +1326,11 @@ pub async fn post_3ds_payments_authorize( state, &req, payload, - |state, auth, req, _| { + |state, auth, req, req_state| { >::handle_payments_redirect_response( &payments::PaymentAuthenticateCompleteAuthorize {}, state, + req_state, auth.merchant_account, auth.key_store, req, diff --git a/crates/router/src/routes/webhooks.rs b/crates/router/src/routes/webhooks.rs index b9be68bbd5..03fe6a1d75 100644 --- a/crates/router/src/routes/webhooks.rs +++ b/crates/router/src/routes/webhooks.rs @@ -26,10 +26,11 @@ pub async fn receive_incoming_webhook( state, &req, WebhookBytes(body), - |state, auth, payload, _| { + |state, auth, payload, req_state| { webhooks::webhooks_wrapper::( &flow, state.to_owned(), + req_state, &req, auth.merchant_account, auth.key_store, diff --git a/crates/router/src/services/api.rs b/crates/router/src/services/api.rs index 854574069f..1a6246d559 100644 --- a/crates/router/src/services/api.rs +++ b/crates/router/src/services/api.rs @@ -951,7 +951,7 @@ pub enum AuthFlow { pub async fn server_wrap_util<'a, 'b, U, T, Q, F, Fut, E, OErr>( flow: &'a impl router_env::types::FlowMetric, state: web::Data, - request_state: ReqState, + mut request_state: ReqState, request: &'a HttpRequest, payload: T, func: F, @@ -973,6 +973,12 @@ where .attach_printable("Unable to extract request id from request") .change_context(errors::ApiErrorResponse::InternalServerError.switch())?; + request_state.event_context.record_info(request_id); + request_state + .event_context + .record_info(("flow".to_string(), flow.to_string())); + // request_state.event_context.record_info(request.clone()); + let mut app_state = state.get_ref().clone(); app_state.add_request_id(request_id); @@ -989,6 +995,8 @@ where .await .switch()?; + request_state.event_context.record_info(auth_type.clone()); + let merchant_id = auth_type .get_merchant_id() .unwrap_or("MERCHANT_ID_NOT_FOUND") diff --git a/crates/router/src/services/authentication.rs b/crates/router/src/services/authentication.rs index f7acbe6f93..748b6753f5 100644 --- a/crates/router/src/services/authentication.rs +++ b/crates/router/src/services/authentication.rs @@ -73,6 +73,17 @@ pub enum AuthenticationType { NoAuth, } +impl events::EventInfo for AuthenticationType { + type Data = Self; + fn data(&self) -> error_stack::Result { + Ok(self.clone()) + } + + fn key(&self) -> String { + "auth_info".to_string() + } +} + impl AuthenticationType { pub fn get_merchant_id(&self) -> Option<&str> { match self { diff --git a/crates/router/src/workflows/outgoing_webhook_retry.rs b/crates/router/src/workflows/outgoing_webhook_retry.rs index 0d40705bec..760993decb 100644 --- a/crates/router/src/workflows/outgoing_webhook_retry.rs +++ b/crates/router/src/workflows/outgoing_webhook_retry.rs @@ -17,7 +17,7 @@ use crate::{ core::webhooks::{self as webhooks_core, types::OutgoingWebhookTrackingData}, db::StorageInterface, errors, logger, - routes::AppState, + routes::{app::ReqState, AppState}, types::{domain, storage}, }; @@ -134,8 +134,10 @@ impl ProcessTrackerWorkflow for OutgoingWebhookRetryWorkflow { .find_merchant_account_by_merchant_id(&tracking_data.merchant_id, &key_store) .await?; + // TODO: Add request state for the PT flows as well let (content, event_type) = get_outgoing_webhook_content_and_event_type( state.clone(), + state.get_req_state(), merchant_account.clone(), key_store.clone(), &tracking_data, @@ -312,6 +314,7 @@ pub(crate) async fn retry_webhook_delivery_task( #[instrument(skip_all)] async fn get_outgoing_webhook_content_and_event_type( state: AppState, + req_state: ReqState, merchant_account: domain::MerchantAccount, key_store: domain::MerchantKeyStore, tracking_data: &OutgoingWebhookTrackingData, @@ -350,6 +353,7 @@ async fn get_outgoing_webhook_content_and_event_type( let payments_response = match Box::pin(payments_core::( state, + req_state, merchant_account, key_store, PaymentStatus, diff --git a/crates/router/src/workflows/payment_sync.rs b/crates/router/src/workflows/payment_sync.rs index 5b290786ef..4b35e4d73b 100644 --- a/crates/router/src/workflows/payment_sync.rs +++ b/crates/router/src/workflows/payment_sync.rs @@ -59,6 +59,7 @@ impl ProcessTrackerWorkflow for PaymentsSyncWorkflow { ) .await?; + // TODO: Add support for ReqState in PT flows let (mut payment_data, _, customer, _, _) = Box::pin(payment_flows::payments_operation_core::< api::PSync, @@ -68,6 +69,7 @@ impl ProcessTrackerWorkflow for PaymentsSyncWorkflow { Oss, >( state, + state.get_req_state(), merchant_account.clone(), key_store.clone(), operations::PaymentStatus, diff --git a/crates/router/tests/payments.rs b/crates/router/tests/payments.rs index 1108a0b4b8..7a990464da 100644 --- a/crates/router/tests/payments.rs +++ b/crates/router/tests/payments.rs @@ -373,7 +373,8 @@ async fn payments_create_core() { _, Oss, >( - state, + state.clone(), + state.get_req_state(), merchant_account, key_store, payments::PaymentCreate, @@ -555,7 +556,8 @@ async fn payments_create_core_adyen_no_redirect() { _, Oss, >( - state, + state.clone(), + state.get_req_state(), merchant_account, key_store, payments::PaymentCreate, diff --git a/crates/router/tests/payments2.rs b/crates/router/tests/payments2.rs index 5718b964ff..cce589fb03 100644 --- a/crates/router/tests/payments2.rs +++ b/crates/router/tests/payments2.rs @@ -133,7 +133,8 @@ async fn payments_create_core() { _, Oss, >( - state, + state.clone(), + state.get_req_state(), merchant_account, key_store, payments::PaymentCreate, @@ -323,7 +324,8 @@ async fn payments_create_core_adyen_no_redirect() { _, Oss, >( - state, + state.clone(), + state.get_req_state(), merchant_account, key_store, payments::PaymentCreate, diff --git a/crates/router_env/src/lib.rs b/crates/router_env/src/lib.rs index 5ad0f70670..20518a9807 100644 --- a/crates/router_env/src/lib.rs +++ b/crates/router_env/src/lib.rs @@ -22,7 +22,6 @@ pub mod vergen; pub use logger::*; pub use once_cell; pub use opentelemetry; -use strum::Display; pub use tracing; #[cfg(feature = "actix_web")] pub use tracing_actix_web; @@ -30,34 +29,3 @@ pub use tracing_appender; #[doc(inline)] pub use self::env::*; -use crate::types::FlowMetric; - -/// Analytics Flow routes Enums -/// Info - Dimensions and filters available for the domain -/// Filters - Set of values present for the dimension -/// Metrics - Analytical data on dimensions and metrics -#[derive(Debug, Display, Clone, PartialEq, Eq)] -pub enum AnalyticsFlow { - GetInfo, - GetPaymentMetrics, - GetRefundsMetrics, - GetSdkMetrics, - GetPaymentFilters, - GetRefundFilters, - GetSdkEventFilters, - GetApiEvents, - GetSdkEvents, - GeneratePaymentReport, - GenerateDisputeReport, - GenerateRefundReport, - GetApiEventMetrics, - GetApiEventFilters, - GetConnectorEvents, - GetOutgoingWebhookEvents, - GetGlobalSearchResults, - GetSearchResults, - GetDisputeFilters, - GetDisputeMetrics, -} - -impl FlowMetric for AnalyticsFlow {}