chore: code refinement

This commit is contained in:
Amitsingh Tanwar
2025-10-28 15:32:31 +05:30
parent fdd4154a8c
commit 184fea4d04
8 changed files with 168 additions and 127 deletions

View File

@ -934,15 +934,13 @@ async fn call_unified_connector_service_authorize(
let payment_authorize_response = response.into_inner();
let (router_data_response, status_code) =
handle_unified_connector_service_response_for_payment_authorize(
&mut router_data,
payment_authorize_response.clone(),
)
.change_context(ApiErrorResponse::InternalServerError)
.attach_printable("Failed to deserialize UCS response")?;
let ucs_data = handle_unified_connector_service_response_for_payment_authorize(
payment_authorize_response.clone(),
)
.change_context(ApiErrorResponse::InternalServerError)
.attach_printable("Failed to deserialize UCS response")?;
let router_data_response = router_data_response.map(|(response, status)| {
let router_data_response = ucs_data.router_data_response.map(|(response, status)| {
router_data.status = status;
response
});
@ -951,7 +949,16 @@ async fn call_unified_connector_service_authorize(
.raw_connector_response
.clone()
.map(|raw_connector_response| raw_connector_response.expose().into());
router_data.connector_http_status_code = Some(status_code);
router_data.connector_http_status_code = Some(ucs_data.status_code);
// Populate connector_customer_id if present
ucs_data.connector_customer_id.map(|connector_customer_id| {
router_data.connector_customer = Some(connector_customer_id);
});
ucs_data.connector_response.map(|customer_response| {
router_data.connector_response = Some(customer_response);
});
Ok((router_data, payment_authorize_response))
},
@ -1028,15 +1035,13 @@ async fn call_unified_connector_service_repeat_payment(
let payment_repeat_response = response.into_inner();
let (router_data_response, status_code) =
handle_unified_connector_service_response_for_payment_repeat(
&mut router_data,
payment_repeat_response.clone(),
)
.change_context(ApiErrorResponse::InternalServerError)
.attach_printable("Failed to deserialize UCS response")?;
let ucs_data = handle_unified_connector_service_response_for_payment_repeat(
payment_repeat_response.clone(),
)
.change_context(ApiErrorResponse::InternalServerError)
.attach_printable("Failed to deserialize UCS response")?;
let router_data_response = router_data_response.map(|(response, status)| {
let router_data_response = ucs_data.router_data_response.map(|(response, status)| {
router_data.status = status;
response
});
@ -1045,7 +1050,17 @@ async fn call_unified_connector_service_repeat_payment(
.raw_connector_response
.clone()
.map(|raw_connector_response| raw_connector_response.expose().into());
router_data.connector_http_status_code = Some(status_code);
router_data.connector_http_status_code = Some(ucs_data.status_code);
// Populate connector_customer_id if present
ucs_data.connector_customer_id.map(|connector_customer_id| {
router_data.connector_customer = Some(connector_customer_id);
});
// Populate connector_response if present
ucs_data.connector_response.map(|connector_response| {
router_data.connector_response = Some(connector_response);
});
Ok((router_data, payment_repeat_response))
},

View File

@ -229,19 +229,19 @@ impl Feature<api::Void, types::PaymentsCancelData>
let payment_void_response = response.into_inner();
let (router_data_response, status_code) =
handle_unified_connector_service_response_for_payment_cancel(
payment_void_response.clone(),
)
.change_context(ApiErrorResponse::InternalServerError)
.attach_printable("Failed to deserialize UCS response")?;
let ucs_data = handle_unified_connector_service_response_for_payment_cancel(
payment_void_response.clone(),
)
.change_context(ApiErrorResponse::InternalServerError)
.attach_printable("Failed to deserialize UCS response")?;
let router_data_response = router_data_response.map(|(response, status)| {
router_data.status = status;
response
});
let router_data_response =
ucs_data.router_data_response.map(|(response, status)| {
router_data.status = status;
response
});
router_data.response = router_data_response;
router_data.connector_http_status_code = Some(status_code);
router_data.connector_http_status_code = Some(ucs_data.status_code);
Ok((router_data, payment_void_response))
},

View File

@ -239,23 +239,23 @@ impl Feature<api::Capture, types::PaymentsCaptureData>
let payment_capture_response = response.into_inner();
let (router_data_response, status_code) =
handle_unified_connector_service_response_for_payment_capture(
payment_capture_response.clone(),
)
.change_context(ApiErrorResponse::InternalServerError)
.attach_printable("Failed to deserialize UCS response")?;
let ucs_data = handle_unified_connector_service_response_for_payment_capture(
payment_capture_response.clone(),
)
.change_context(ApiErrorResponse::InternalServerError)
.attach_printable("Failed to deserialize UCS response")?;
let router_data_response = router_data_response.map(|(response, status)| {
router_data.status = status;
response
});
let router_data_response =
ucs_data.router_data_response.map(|(response, status)| {
router_data.status = status;
response
});
router_data.response = router_data_response;
router_data.amount_captured = payment_capture_response.captured_amount;
router_data.minor_amount_captured = payment_capture_response
.minor_captured_amount
.map(MinorUnit::new);
router_data.connector_http_status_code = Some(status_code);
router_data.connector_http_status_code = Some(ucs_data.status_code);
Ok((router_data, payment_capture_response))
},

View File

@ -436,15 +436,14 @@ impl Feature<api::ExternalVaultProxy, types::ExternalVaultProxyPaymentsData>
let payment_authorize_response = response.into_inner();
let (router_data_response, status_code) =
let ucs_data =
unified_connector_service::handle_unified_connector_service_response_for_payment_authorize(
&mut router_data,
payment_authorize_response.clone(),
)
.change_context(ApiErrorResponse::InternalServerError)
.attach_printable("Failed to deserialize UCS response")?;
let router_data_response = router_data_response.map(|(response, status)|{
let router_data_response = ucs_data.router_data_response.map(|(response, status)|{
router_data.status = status;
response
});
@ -453,7 +452,7 @@ impl Feature<api::ExternalVaultProxy, types::ExternalVaultProxyPaymentsData>
.raw_connector_response
.clone()
.map(|raw_connector_response| raw_connector_response.expose().into());
router_data.connector_http_status_code = Some(status_code);
router_data.connector_http_status_code = Some(ucs_data.status_code);
Ok((router_data, payment_authorize_response))
}

View File

@ -342,20 +342,26 @@ impl Feature<api::SetupMandate, types::SetupMandateRequestData> for types::Setup
let payment_register_response = response.into_inner();
let (router_data_response, status_code) =
handle_unified_connector_service_response_for_payment_register(
&mut router_data,
payment_register_response.clone(),
)
.change_context(ApiErrorResponse::InternalServerError)
.attach_printable("Failed to deserialize UCS response")?;
let ucs_data = handle_unified_connector_service_response_for_payment_register(
payment_register_response.clone(),
)
.change_context(ApiErrorResponse::InternalServerError)
.attach_printable("Failed to deserialize UCS response")?;
let router_data_response = router_data_response.map(|(response, status)| {
router_data.status = status;
response
});
let router_data_response =
ucs_data.router_data_response.map(|(response, status)| {
router_data.status = status;
response
});
router_data.response = router_data_response;
router_data.connector_http_status_code = Some(status_code);
router_data.connector_http_status_code = Some(ucs_data.status_code);
// Populate connector_customer_id if present
ucs_data.connector_customer_id.map(|connector_customer_id| {
router_data.connector_customer = Some(connector_customer_id);
});
// Note: Register flow doesn't populate connector_response
Ok((router_data, payment_register_response))
},

View File

@ -7905,18 +7905,17 @@ where
/// Helper function to populate connector_customer_id from database before calling UCS
/// This checks if a connector_customer_id already exists in the database and populates it into router_data
/// Returns true if connector_customer_id was found and populated from DB, false otherwise
async fn populate_connector_customer_from_db_before_ucs<F, Req, D>(
async fn populate_connector_customer_from_db_before_ucs<D, F>(
state: &SessionState,
router_data: &mut RouterData<F, Req, PaymentsResponseData>,
connector_label: Option<&str>,
payment_data: &D,
customer: &Option<domain::Customer>,
merchant_connector_account: &MerchantConnectorAccountType,
) -> RouterResult<bool>
) -> RouterResult<Option<String>>
where
D: OperationSessionGetters<F>,
{
let mut connector_customer_id_was_populated = false;
let mut connector_customer_id_was_populated = None;
if let (Some(connector_label), Some(connector_name)) = (
connector_label,
@ -7955,8 +7954,7 @@ where
payment_data.get_payment_intent().payment_id.get_string_repr(),
connector_label
);
router_data.connector_customer = Some(connector_customer_id.to_string());
connector_customer_id_was_populated = true;
connector_customer_id_was_populated = Some(connector_customer_id.to_string());
}
None => {
router_env::logger::info!(
@ -7978,14 +7976,14 @@ where
async fn save_connector_customer_id_after_ucs<F, Req>(
state: &SessionState,
router_data: &RouterData<F, Req, PaymentsResponseData>,
connector_customer_id_was_populated_from_db: bool,
connector_customer_id_was_populated_from_db: Option<String>,
connector_label: &Option<String>,
customer: &Option<domain::Customer>,
merchant_context: &domain::MerchantContext,
payment_id: String,
) -> RouterResult<()> {
// Process only if connector_customer_id was NOT already in DB
if !connector_customer_id_was_populated_from_db {
if !connector_customer_id_was_populated_from_db.is_some() {
// Extract necessary fields and save if both are present
match (&router_data.connector_customer, connector_label.as_ref()) {
(Some(connector_customer_id), Some(connector_label_str)) => {
@ -8019,7 +8017,6 @@ async fn save_connector_customer_id_after_ucs<F, Req>(
payment_id
);
}
Ok(())
}
@ -8188,7 +8185,6 @@ where
let connector_customer_id_was_populated_from_db =
populate_connector_customer_from_db_before_ucs(
state,
&mut router_data,
connector_label.as_deref(),
payment_data,
customer,
@ -8196,6 +8192,12 @@ where
)
.await?;
connector_customer_id_was_populated_from_db
.as_ref()
.map(|id| {
router_data.connector_customer = Some(id.clone());
});
// Based on the preprocessing response, decide whether to continue with UCS call
if should_continue {
router_data
@ -8380,17 +8382,20 @@ where
// Populate connector_customer_id from database for shadow UCS call
// Use the pre-calculated connector_label
// Track whether ID was found in DB to avoid redundant save later
let _connector_customer_id_was_populated_from_db =
let connector_customer_id_was_populated_from_db =
populate_connector_customer_from_db_before_ucs(
state,
&mut unified_connector_service_router_data,
unified_connector_service_connector_label.as_deref(),
payment_data,
customer,
&merchant_connector_account,
)
.await
.unwrap_or(false); // Don't fail the main flow if shadow UCS populate fails
.unwrap_or_default(); // Don't fail the main flow if shadow UCS populate fails
connector_customer_id_was_populated_from_db.map(|id| {
unified_connector_service_router_data.connector_customer = Some(id);
});
let lineage_ids = grpc_client::LineageIds::new(
business_profile.merchant_id.clone(),

View File

@ -60,7 +60,7 @@ use crate::{
events::connector_api_logs::ConnectorEvent,
headers::{CONTENT_TYPE, X_REQUEST_ID},
routes::SessionState,
types::transformers::ForeignTryFrom,
types::{transformers::ForeignTryFrom, UcsResponseData},
};
pub mod transformers;
@ -69,13 +69,7 @@ pub mod transformers;
pub use transformers::{WebhookTransformData, WebhookTransformationStatus};
/// Type alias for return type used by unified connector service response handlers
type UnifiedConnectorServiceResult = CustomResult<
(
Result<(PaymentsResponseData, AttemptStatus), ErrorResponse>,
u16,
),
UnifiedConnectorServiceError,
>;
type UnifiedConnectorServiceResult = CustomResult<UcsResponseData, UnifiedConnectorServiceError>;
/// Checks if the Unified Connector Service (UCS) is available for use
async fn check_ucs_availability(state: &SessionState) -> UcsAvailability {
@ -759,8 +753,7 @@ pub fn build_unified_connector_service_external_vault_proxy_metadata(
}
}
pub fn handle_unified_connector_service_response_for_payment_authorize<F, Req>(
router_data: &mut RouterData<F, Req, PaymentsResponseData>,
pub fn handle_unified_connector_service_response_for_payment_authorize(
response: PaymentServiceAuthorizeResponse,
) -> UnifiedConnectorServiceResult {
let status_code = transformers::convert_connector_service_status_code(response.status_code)?;
@ -770,17 +763,17 @@ pub fn handle_unified_connector_service_response_for_payment_authorize<F, Req>(
response.clone(),
)?;
// Populate connector_customer_id from UCS state
populate_connector_customer_id_from_ucs_state(router_data, response.state.as_ref());
let connector_customer_id =
extract_connector_customer_id_from_ucs_state(response.state.as_ref());
let connector_response =
extract_connector_response_from_ucs(response.connector_response.as_ref());
// Populate connector_response from UCS response (log errors, don't fail)
populate_connector_response_from_ucs(router_data, response.connector_response.as_ref())
.inspect_err(|err| {
router_env::logger::warn!("Failed to populate connector_response from UCS: {:?}", err);
})
.ok();
Ok((router_data_response, status_code))
Ok(UcsResponseData {
router_data_response,
status_code,
connector_customer_id,
connector_response,
})
}
pub fn handle_unified_connector_service_response_for_payment_capture(
@ -791,11 +784,15 @@ pub fn handle_unified_connector_service_response_for_payment_capture(
let router_data_response =
Result::<(PaymentsResponseData, AttemptStatus), ErrorResponse>::foreign_try_from(response)?;
Ok((router_data_response, status_code))
Ok(UcsResponseData {
router_data_response,
status_code,
connector_customer_id: None,
connector_response: None,
})
}
pub fn handle_unified_connector_service_response_for_payment_register<F, Req>(
router_data: &mut RouterData<F, Req, PaymentsResponseData>,
pub fn handle_unified_connector_service_response_for_payment_register(
response: payments_grpc::PaymentServiceRegisterResponse,
) -> UnifiedConnectorServiceResult {
let status_code = transformers::convert_connector_service_status_code(response.status_code)?;
@ -805,14 +802,18 @@ pub fn handle_unified_connector_service_response_for_payment_register<F, Req>(
response.clone(),
)?;
// Populate connector_customer_id from UCS state
populate_connector_customer_id_from_ucs_state(router_data, response.state.as_ref());
let connector_customer_id =
extract_connector_customer_id_from_ucs_state(response.state.as_ref());
Ok((router_data_response, status_code))
Ok(UcsResponseData {
router_data_response,
status_code,
connector_customer_id,
connector_response: None, // Register doesn't need connector_response
})
}
pub fn handle_unified_connector_service_response_for_payment_repeat<F, Req>(
router_data: &mut RouterData<F, Req, PaymentsResponseData>,
pub fn handle_unified_connector_service_response_for_payment_repeat(
response: payments_grpc::PaymentServiceRepeatEverythingResponse,
) -> UnifiedConnectorServiceResult {
let status_code = transformers::convert_connector_service_status_code(response.status_code)?;
@ -822,45 +823,46 @@ pub fn handle_unified_connector_service_response_for_payment_repeat<F, Req>(
response.clone(),
)?;
// Populate connector_customer_id from UCS state
populate_connector_customer_id_from_ucs_state(router_data, response.state.as_ref());
let connector_customer_id =
extract_connector_customer_id_from_ucs_state(response.state.as_ref());
let connector_response =
extract_connector_response_from_ucs(response.connector_response.as_ref());
// Populate connector_response from UCS response (log errors, don't fail)
populate_connector_response_from_ucs(router_data, response.connector_response.as_ref())
.inspect_err(|err| {
router_env::logger::warn!("Failed to populate connector_response from UCS: {:?}", err);
})
.ok();
Ok((router_data_response, status_code))
Ok(UcsResponseData {
router_data_response,
status_code,
connector_customer_id,
connector_response,
})
}
/// Extracts and populates connector_customer_id from UCS state into router_data
pub fn populate_connector_customer_id_from_ucs_state<F, Req, Resp>(
router_data: &mut RouterData<F, Req, Resp>,
/// Extracts connector_customer_id from UCS state
pub fn extract_connector_customer_id_from_ucs_state(
ucs_state: Option<&payments_grpc::ConnectorState>,
) {
ucs_state.map(|state| {
) -> Option<String> {
ucs_state.and_then(|state| {
state
.connector_customer_id
.as_ref()
.map(|id| router_data.connector_customer = Some(id.to_string()));
});
.map(|id| id.to_string())
})
}
/// Extracts and populates connector_response from UCS response into router_data
pub fn populate_connector_response_from_ucs<F, Req, Resp>(
router_data: &mut RouterData<F, Req, Resp>,
/// Extracts connector_response from UCS response
pub fn extract_connector_response_from_ucs(
connector_response: Option<&payments_grpc::ConnectorResponseData>,
) -> RouterResult<()> {
router_data.connector_response = connector_response
.map(|data| {
<hyperswitch_domain_models::router_data::ConnectorResponseData as hyperswitch_interfaces::helpers::ForeignTryFrom<payments_grpc::ConnectorResponseData>>::foreign_try_from(data.clone())
})
.transpose()
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Failed to deserialize connector_response from UCS")?;
Ok(())
) -> Option<hyperswitch_domain_models::router_data::ConnectorResponseData> {
connector_response.and_then(|data| {
<hyperswitch_domain_models::router_data::ConnectorResponseData as hyperswitch_interfaces::helpers::ForeignTryFrom<payments_grpc::ConnectorResponseData>>::foreign_try_from(data.clone())
.map_err(|e| {
logger::warn!(
error=?e,
"Failed to deserialize connector_response from UCS"
);
e
})
.ok()
})
}
pub fn handle_unified_connector_service_response_for_payment_cancel(
@ -871,7 +873,12 @@ pub fn handle_unified_connector_service_response_for_payment_cancel(
let router_data_response =
Result::<(PaymentsResponseData, AttemptStatus), ErrorResponse>::foreign_try_from(response)?;
Ok((router_data_response, status_code))
Ok(UcsResponseData {
router_data_response,
status_code,
connector_customer_id: None,
connector_response: None,
})
}
pub fn build_webhook_secrets_from_merchant_connector_account(

View File

@ -721,6 +721,15 @@ pub struct PspTokenResult {
pub token: Result<String, ErrorResponse>,
}
/// Data extracted from UCS response
pub struct UcsResponseData {
pub router_data_response:
Result<(PaymentsResponseData, common_enums::AttemptStatus), ErrorResponse>,
pub status_code: u16,
pub connector_customer_id: Option<String>,
pub connector_response: Option<ConnectorResponseData>,
}
#[derive(Debug, Clone, Copy)]
pub enum Redirection {
Redirect,