From f1c53366b28a89c82db0416ffe3e56b8a704afdf Mon Sep 17 00:00:00 2001 From: chikke srujan <121822803+srujanchikke@users.noreply.github.com> Date: Thu, 26 Jun 2025 03:23:07 -0700 Subject: [PATCH] fix(recovery): Populate connector request reference id in revenue recovery record attempt flow. (#8434) Co-authored-by: Chikke Srujan Co-authored-by: Nishanth Challa Co-authored-by: Aprabhat19 Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com> --- .../src/payments/payment_attempt.rs | 8 ++++--- crates/router/src/core/payments.rs | 10 +++++++++ .../operations/proxy_payments_intent.rs | 21 +++++++++++++++++- crates/router/src/routes/payments.rs | 5 ++++- crates/router/src/services/authentication.rs | 22 ++++++++++++++++++- 5 files changed, 60 insertions(+), 6 deletions(-) diff --git a/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs b/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs index 2a8e8daa67..3a2692e583 100644 --- a/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs +++ b/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs @@ -646,7 +646,6 @@ impl PaymentAttempt { let payment_method_type_data = payment_intent.get_payment_method_type(); let payment_method_subtype_data = payment_intent.get_payment_method_sub_type(); - let authentication_type = payment_intent.authentication_type.unwrap_or_default(); Ok(Self { payment_id: payment_intent.id.clone(), @@ -752,7 +751,10 @@ impl PaymentAttempt { .as_ref() .map(|txn_id| txn_id.get_id().clone()); let connector = request.connector.map(|connector| connector.to_string()); - + let connector_request_reference_id = payment_intent + .merchant_reference_id + .as_ref() + .map(|id| id.get_string_repr().to_owned()); Ok(Self { payment_id: payment_intent.id.clone(), merchant_id: payment_intent.merchant_id.clone(), @@ -804,7 +806,7 @@ impl PaymentAttempt { charges: None, processor_merchant_id: payment_intent.merchant_id.clone(), created_by: None, - connector_request_reference_id: None, + connector_request_reference_id, }) } diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs index 69488c44a2..7037eba17b 100644 --- a/crates/router/src/core/payments.rs +++ b/crates/router/src/core/payments.rs @@ -4044,6 +4044,16 @@ where ) .await?, )); + operation + .to_domain()? + .populate_payment_data( + state, + payment_data, + merchant_context, + business_profile, + &connector, + ) + .await?; let mut router_data = payment_data .construct_router_data( diff --git a/crates/router/src/core/payments/operations/proxy_payments_intent.rs b/crates/router/src/core/payments/operations/proxy_payments_intent.rs index 838cbf9ded..a65f4cdd99 100644 --- a/crates/router/src/core/payments/operations/proxy_payments_intent.rs +++ b/crates/router/src/core/payments/operations/proxy_payments_intent.rs @@ -6,6 +6,7 @@ use error_stack::ResultExt; use hyperswitch_domain_models::{ payment_method_data::PaymentMethodData, payments::PaymentConfirmData, }; +use hyperswitch_interfaces::api::ConnectorSpecifications; use masking::PeekInterface; use router_env::{instrument, tracing}; @@ -15,7 +16,7 @@ use crate::{ errors::{self, CustomResult, RouterResult, StorageErrorExt}, payments::{ operations::{self, ValidateStatusForOperation}, - OperationSessionGetters, + OperationSessionGetters, OperationSessionSetters, }, }, routes::{app::ReqState, SessionState}, @@ -303,6 +304,24 @@ impl Domain { Ok((Box::new(self), None, None)) } + #[instrument(skip_all)] + async fn populate_payment_data<'a>( + &'a self, + _state: &SessionState, + payment_data: &mut PaymentConfirmData, + _merchant_context: &domain::MerchantContext, + _business_profile: &domain::Profile, + connector_data: &api::ConnectorData, + ) -> CustomResult<(), errors::ApiErrorResponse> { + let connector_request_reference_id = connector_data + .connector + .generate_connector_request_reference_id( + &payment_data.payment_intent, + &payment_data.payment_attempt, + ); + payment_data.set_connector_request_reference_id(Some(connector_request_reference_id)); + Ok(()) + } async fn perform_routing<'a>( &'a self, diff --git a/crates/router/src/routes/payments.rs b/crates/router/src/routes/payments.rs index 020a1fbf71..e2363633da 100644 --- a/crates/router/src/routes/payments.rs +++ b/crates/router/src/routes/payments.rs @@ -232,7 +232,7 @@ pub async fn payments_get_intent( header_payload.clone(), ) }, - auth::api_or_client_auth( + auth::api_or_client_or_jwt_auth( &auth::V2ApiKeyAuth { is_connected_allowed: false, is_platform_allowed: false, @@ -240,6 +240,9 @@ pub async fn payments_get_intent( &auth::V2ClientAuth(common_utils::types::authentication::ResourceId::Payment( global_payment_id.clone(), )), + &auth::JWTAuth { + permission: Permission::ProfileRevenueRecoveryRead, + }, req.headers(), ), api_locking::LockAction::NotApplicable, diff --git a/crates/router/src/services/authentication.rs b/crates/router/src/services/authentication.rs index 41b7bd3d87..d16063939a 100644 --- a/crates/router/src/services/authentication.rs +++ b/crates/router/src/services/authentication.rs @@ -2698,7 +2698,27 @@ where api_auth } } - +#[cfg(feature = "v2")] +pub fn api_or_client_or_jwt_auth<'a, T, A>( + api_auth: &'a dyn AuthenticateAndFetch, + client_auth: &'a dyn AuthenticateAndFetch, + jwt_auth: &'a dyn AuthenticateAndFetch, + headers: &HeaderMap, +) -> &'a dyn AuthenticateAndFetch +where +{ + if let Ok(val) = HeaderMapStruct::new(headers).get_auth_string_from_header() { + if val.trim().starts_with("api-key=") { + api_auth + } else if is_jwt_auth(headers) { + jwt_auth + } else { + client_auth + } + } else { + api_auth + } +} #[derive(Debug)] pub struct PublishableKeyAuth;