From d6bbdde18c31cff43584d4758fb2182afb976065 Mon Sep 17 00:00:00 2001 From: Hrithikesh <61539176+hrithikesh026@users.noreply.github.com> Date: Wed, 29 Oct 2025 10:10:31 +0530 Subject: [PATCH] feat(ucs): call pre-authentication during authorize as per connector (#9949) Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com> --- .../grpc_client/unified_connector_service.rs | 32 ++ .../src/connectors/cybersource.rs | 7 +- .../connectors/cybersource/transformers.rs | 11 +- .../src/router_request_types.rs | 21 +- .../unified_connector_service/transformers.rs | 4 + .../src/core/payments/flows/authorize_flow.rs | 136 +++++- .../src/core/unified_connector_service.rs | 11 + .../unified_connector_service/transformers.rs | 451 ++++++++++++++---- crates/router/src/types.rs | 12 +- crates/router/src/types/api.rs | 1 + 10 files changed, 558 insertions(+), 128 deletions(-) diff --git a/crates/external_services/src/grpc_client/unified_connector_service.rs b/crates/external_services/src/grpc_client/unified_connector_service.rs index d78e5e8981..301f94704e 100644 --- a/crates/external_services/src/grpc_client/unified_connector_service.rs +++ b/crates/external_services/src/grpc_client/unified_connector_service.rs @@ -138,6 +138,38 @@ impl UnifiedConnectorServiceClient { } } + /// Performs Payment Pre Authenticate + pub async fn payment_pre_authenticate( + &self, + payment_pre_authenticate_request: payments_grpc::PaymentServicePreAuthenticateRequest, + connector_auth_metadata: ConnectorAuthMetadata, + grpc_headers: GrpcHeadersUcs, + ) -> UnifiedConnectorServiceResult< + tonic::Response, + > { + let mut request = tonic::Request::new(payment_pre_authenticate_request); + + let connector_name = connector_auth_metadata.connector_name.clone(); + let metadata = + build_unified_connector_service_grpc_headers(connector_auth_metadata, grpc_headers)?; + + *request.metadata_mut() = metadata; + + self.client + .clone() + .pre_authenticate(request) + .await + .change_context(UnifiedConnectorServiceError::PaymentPreAuthenticateFailure) + .inspect_err(|error| { + logger::error!( + grpc_error=?error, + method="payment_pre_authenticate", + connector_name=?connector_name, + "UCS payment pre authenticate gRPC call failed" + ) + }) + } + /// Performs Payment Authorize pub async fn payment_authorize( &self, diff --git a/crates/hyperswitch_connectors/src/connectors/cybersource.rs b/crates/hyperswitch_connectors/src/connectors/cybersource.rs index f485af538c..945d127d18 100644 --- a/crates/hyperswitch_connectors/src/connectors/cybersource.rs +++ b/crates/hyperswitch_connectors/src/connectors/cybersource.rs @@ -753,12 +753,7 @@ impl ConnectorIntegration CustomResult { - let minor_amount = - req.request - .minor_amount - .ok_or(errors::ConnectorError::MissingRequiredField { - field_name: "minor_amount", - })?; + let minor_amount = req.request.minor_amount; let currency = req.request .currency diff --git a/crates/hyperswitch_connectors/src/connectors/cybersource/transformers.rs b/crates/hyperswitch_connectors/src/connectors/cybersource/transformers.rs index 2c0ac8192c..b6fa387f09 100644 --- a/crates/hyperswitch_connectors/src/connectors/cybersource/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/cybersource/transformers.rs @@ -2698,16 +2698,9 @@ impl TryFrom<&CybersourceRouterData<&PaymentsPreAuthenticateRouterData>> fn try_from( item: &CybersourceRouterData<&PaymentsPreAuthenticateRouterData>, ) -> Result { - let payment_method_data = item - .router_data - .request - .payment_method_data - .as_ref() - .ok_or(errors::ConnectorError::MissingRequiredField { - field_name: "payment_method_data", - })?; + let payment_method_data = item.router_data.request.payment_method_data.clone(); - match payment_method_data.clone() { + match payment_method_data { PaymentMethodData::Card(ccard) => { let card_type = match ccard .card_network diff --git a/crates/hyperswitch_domain_models/src/router_request_types.rs b/crates/hyperswitch_domain_models/src/router_request_types.rs index 9a6271f6f6..fdfcee54c7 100644 --- a/crates/hyperswitch_domain_models/src/router_request_types.rs +++ b/crates/hyperswitch_domain_models/src/router_request_types.rs @@ -618,20 +618,19 @@ impl TryFrom for PaymentsPreProcessingData { #[derive(Debug, Clone, Serialize)] pub struct PaymentsPreAuthenticateData { - pub payment_method_data: Option, - pub amount: Option, + pub payment_method_data: PaymentMethodData, + pub amount: i64, pub email: Option, pub currency: Option, pub payment_method_type: Option, pub router_return_url: Option, pub complete_authorize_url: Option, pub browser_info: Option, - pub connector_transaction_id: Option, pub enrolled_for_3ds: bool, - pub redirect_response: Option, - + pub customer_name: Option>, + pub metadata: Option, // New amount for amount frame work - pub minor_amount: Option, + pub minor_amount: MinorUnit, } impl TryFrom for PaymentsPreAuthenticateData { @@ -639,17 +638,17 @@ impl TryFrom for PaymentsPreAuthenticateData { fn try_from(data: PaymentsAuthorizeData) -> Result { Ok(Self { - payment_method_data: Some(data.payment_method_data), - amount: Some(data.amount), - minor_amount: Some(data.minor_amount), + payment_method_data: data.payment_method_data, + customer_name: data.customer_name, + metadata: data.metadata.map(Secret::new), + amount: data.amount, + minor_amount: data.minor_amount, email: data.email, currency: Some(data.currency), payment_method_type: data.payment_method_type, router_return_url: data.router_return_url, complete_authorize_url: data.complete_authorize_url, browser_info: data.browser_info, - connector_transaction_id: None, - redirect_response: None, enrolled_for_3ds: data.enrolled_for_3ds, }) } diff --git a/crates/hyperswitch_interfaces/src/unified_connector_service/transformers.rs b/crates/hyperswitch_interfaces/src/unified_connector_service/transformers.rs index 65a64a4a2d..fbadb7470c 100644 --- a/crates/hyperswitch_interfaces/src/unified_connector_service/transformers.rs +++ b/crates/hyperswitch_interfaces/src/unified_connector_service/transformers.rs @@ -77,6 +77,10 @@ pub enum UnifiedConnectorServiceError { #[error("Failed to perform Payment Authorize from gRPC Server")] PaymentAuthorizeFailure, + /// Failed to perform Payment Authenticate from gRPC Server + #[error("Failed to perform Payment Pre Authenticate from gRPC Server")] + PaymentPreAuthenticateFailure, + /// Failed to perform Payment Get from gRPC Server #[error("Failed to perform Payment Get from gRPC Server")] PaymentGetFailure, diff --git a/crates/router/src/core/payments/flows/authorize_flow.rs b/crates/router/src/core/payments/flows/authorize_flow.rs index 6e790c9c57..f1654ae984 100644 --- a/crates/router/src/core/payments/flows/authorize_flow.rs +++ b/crates/router/src/core/payments/flows/authorize_flow.rs @@ -26,7 +26,7 @@ use crate::{ self, access_token, customers, helpers, tokenization, transformers, PaymentData, }, unified_connector_service::{ - build_unified_connector_service_auth_metadata, + self, build_unified_connector_service_auth_metadata, handle_unified_connector_service_response_for_payment_authorize, handle_unified_connector_service_response_for_payment_repeat, ucs_logging_wrapper, }, @@ -565,7 +565,46 @@ impl Feature for types::PaymentsAu ); match alternate_flow { Some(api_interface::AlternateFlow::PreAuthenticate) => { - // Todo: Call UCS PreAuthenticate here + let authorize_request_data = self.request.clone(); + let pre_authneticate_request_data = + types::PaymentsPreAuthenticateData::try_from(self.request.to_owned())?; + let pre_authneticate_response_data: Result< + types::PaymentsResponseData, + types::ErrorResponse, + > = Err(types::ErrorResponse::default()); + let mut pre_authenticate_router_data = helpers::router_data_type_conversion::< + _, + api::PreAuthenticate, + _, + _, + _, + _, + >( + self.clone(), + pre_authneticate_request_data, + pre_authneticate_response_data, + ); + let _ = call_unified_connector_service_pre_authenticate( + &mut pre_authenticate_router_data, + state, + header_payload, + lineage_ids, + merchant_connector_account, + merchant_context, + unified_connector_service_execution_mode, + merchant_order_reference_id, + ) + .await; + // Convert back to authorize router data while preserving preprocessing response data. + let pre_authenticate_response = pre_authenticate_router_data.response.clone(); + let authorize_router_data = + helpers::router_data_type_conversion::<_, api::Authorize, _, _, _, _>( + pre_authenticate_router_data, + authorize_request_data, + pre_authenticate_response, + ); + *self = authorize_router_data; + Ok(()) } None => { @@ -962,6 +1001,99 @@ async fn call_unified_connector_service_authorize( Ok(()) } +#[allow(clippy::too_many_arguments)] +async fn call_unified_connector_service_pre_authenticate( + router_data: &mut types::RouterData< + api::PreAuthenticate, + types::PaymentsPreAuthenticateData, + types::PaymentsResponseData, + >, + state: &SessionState, + header_payload: &domain_payments::HeaderPayload, + lineage_ids: grpc_client::LineageIds, + #[cfg(feature = "v1")] merchant_connector_account: helpers::MerchantConnectorAccountType, + #[cfg(feature = "v2")] merchant_connector_account: domain::MerchantConnectorAccountTypeDetails, + merchant_context: &domain::MerchantContext, + unified_connector_service_execution_mode: enums::ExecutionMode, + merchant_order_reference_id: Option, +) -> RouterResult<()> { + let client = state + .grpc_client + .unified_connector_service_client + .clone() + .ok_or(ApiErrorResponse::InternalServerError) + .attach_printable("Failed to fetch Unified Connector Service client")?; + + let payment_pre_authenticate_request = + payments_grpc::PaymentServicePreAuthenticateRequest::foreign_try_from(&*router_data) + .change_context(ApiErrorResponse::InternalServerError) + .attach_printable("Failed to construct Payment Authorize Request")?; + + let connector_auth_metadata = + build_unified_connector_service_auth_metadata(merchant_connector_account, merchant_context) + .change_context(ApiErrorResponse::InternalServerError) + .attach_printable("Failed to construct request metadata")?; + let merchant_reference_id = header_payload + .x_reference_id + .clone() + .or(merchant_order_reference_id) + .map(|id| id_type::PaymentReferenceId::from_str(id.as_str())) + .transpose() + .inspect_err(|err| logger::warn!(error=?err, "Invalid Merchant ReferenceId found")) + .ok() + .flatten() + .map(ucs_types::UcsReferenceId::Payment); + let headers_builder = state + .get_grpc_headers_ucs(unified_connector_service_execution_mode) + .external_vault_proxy_metadata(None) + .merchant_reference_id(merchant_reference_id) + .lineage_ids(lineage_ids); + let updated_router_data = Box::pin(ucs_logging_wrapper( + router_data.clone(), + state, + payment_pre_authenticate_request, + headers_builder, + |mut router_data, payment_pre_authenticate_request, grpc_headers| async move { + let response = client + .payment_pre_authenticate( + payment_pre_authenticate_request, + connector_auth_metadata, + grpc_headers, + ) + .await + .change_context(ApiErrorResponse::InternalServerError) + .attach_printable("Failed to authorize payment")?; + + let payment_pre_authenticate_response = response.into_inner(); + + let (router_data_response, status_code) = + unified_connector_service::handle_unified_connector_service_response_for_payment_pre_authenticate( + payment_pre_authenticate_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 + }); + router_data.response = router_data_response; + router_data.raw_connector_response = payment_pre_authenticate_response + .raw_connector_response + .clone() + .map(|raw_connector_response| raw_connector_response.expose().into()); + router_data.connector_http_status_code = Some(status_code); + + Ok((router_data, payment_pre_authenticate_response)) + }, + )) + .await?; + + // Copy back the updated data + *router_data = updated_router_data; + Ok(()) +} + #[allow(clippy::too_many_arguments)] async fn call_unified_connector_service_repeat_payment( router_data: &mut types::RouterData< diff --git a/crates/router/src/core/unified_connector_service.rs b/crates/router/src/core/unified_connector_service.rs index 2339d62dc9..5748e0ad6d 100644 --- a/crates/router/src/core/unified_connector_service.rs +++ b/crates/router/src/core/unified_connector_service.rs @@ -770,6 +770,17 @@ pub fn handle_unified_connector_service_response_for_payment_authorize( Ok((router_data_response, status_code)) } +pub fn handle_unified_connector_service_response_for_payment_pre_authenticate( + response: payments_grpc::PaymentServicePreAuthenticateResponse, +) -> UnifiedConnectorServiceResult { + let status_code = transformers::convert_connector_service_status_code(response.status_code)?; + + let router_data_response = + Result::<(PaymentsResponseData, AttemptStatus), ErrorResponse>::foreign_try_from(response)?; + + Ok((router_data_response, status_code)) +} + pub fn handle_unified_connector_service_response_for_payment_capture( response: payments_grpc::PaymentServiceCaptureResponse, ) -> UnifiedConnectorServiceResult { diff --git a/crates/router/src/core/unified_connector_service/transformers.rs b/crates/router/src/core/unified_connector_service/transformers.rs index 1f90deec2c..eefc4e6d11 100644 --- a/crates/router/src/core/unified_connector_service/transformers.rs +++ b/crates/router/src/core/unified_connector_service/transformers.rs @@ -9,10 +9,10 @@ use hyperswitch_domain_models::{ router_data::{ErrorResponse, RouterData}, router_flow_types::{ payments::{Authorize, Capture, PSync, SetupMandate}, - ExternalVaultProxy, + unified_authentication_service as uas_flows, ExternalVaultProxy, }, router_request_types::{ - AuthenticationData, ExternalVaultProxyPaymentsData, PaymentsAuthorizeData, + self, AuthenticationData, ExternalVaultProxyPaymentsData, PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, PaymentsSyncData, SetupMandateRequestData, }, router_response_types::{PaymentsResponseData, RedirectForm}, @@ -118,6 +118,101 @@ impl } } +impl + transformers::ForeignTryFrom< + &RouterData< + uas_flows::PreAuthenticate, + router_request_types::PaymentsPreAuthenticateData, + PaymentsResponseData, + >, + > for payments_grpc::PaymentServicePreAuthenticateRequest +{ + type Error = error_stack::Report; + fn foreign_try_from( + router_data: &RouterData< + uas_flows::PreAuthenticate, + router_request_types::PaymentsPreAuthenticateData, + PaymentsResponseData, + >, + ) -> Result { + let currency = payments_grpc::Currency::foreign_try_from( + router_data.request.currency.unwrap_or_default(), + )?; + + let payment_method = router_data + .request + .payment_method_type + .map(|payment_method_type| { + unified_connector_service::build_unified_connector_service_payment_method( + router_data.request.payment_method_data.clone(), + payment_method_type, + ) + }) + .transpose()?; + + let address = payments_grpc::PaymentAddress::foreign_try_from(router_data.address.clone())?; + let connector_metadata_string = router_data + .connector_meta_data + .as_ref() + .map(|metadata| metadata.encode_to_string_of_json()) + .transpose() + .change_context( + UnifiedConnectorServiceError::RequestEncodingFailedWithReason( + "Failed to serialize router_data.connector_meta_data to string of json" + .to_string(), + ), + )?; + let mut metadata = router_data + .request + .metadata + .as_ref() + .and_then(|val| val.peek().as_object()) + .map(|map| { + map.iter() + .filter_map(|(k, v)| v.as_str().map(|s| (k.clone(), s.to_string()))) + .collect::>() + }) + .unwrap_or_default(); + metadata.extend( + connector_metadata_string + .map(|connector_metadata| ("connector_meta_data".to_string(), connector_metadata)), + ); + Ok(Self { + request_ref_id: Some(Identifier { + id_type: Some(payments_grpc::identifier::IdType::Id( + router_data.connector_request_reference_id.clone(), + )), + }), + amount: router_data.request.amount, + currency: currency.into(), + minor_amount: router_data.request.minor_amount.get_amount_as_i64(), + payment_method, + email: router_data + .request + .email + .clone() + .map(|e| e.expose().expose().into()), + customer_name: router_data + .request + .customer_name + .clone() + .map(|customer_name| customer_name.peek().to_owned()), + address: Some(address), + enrolled_for_3ds: router_data.request.enrolled_for_3ds, + metadata, + return_url: router_data.request.router_return_url.clone(), + continue_redirection_url: router_data.request.complete_authorize_url.clone(), + access_token: None, + browser_info: router_data + .request + .browser_info + .clone() + .map(payments_grpc::BrowserInformation::foreign_try_from) + .transpose()?, + }) + } +} + impl transformers::ForeignTryFrom<&RouterData> for payments_grpc::PaymentServiceCaptureRequest { @@ -229,7 +324,32 @@ impl .clone() .map(payments_grpc::AuthenticationData::foreign_try_from) .transpose()?; - + let connector_metadata_string = router_data + .connector_meta_data + .as_ref() + .map(|metadata| metadata.encode_to_string_of_json()) + .transpose() + .change_context( + UnifiedConnectorServiceError::RequestEncodingFailedWithReason( + "Failed to serialize router_data.connector_meta_data to string of json" + .to_string(), + ), + )?; + let mut metadata = router_data + .request + .metadata + .as_ref() + .and_then(|val| val.as_object()) + .map(|map| { + map.iter() + .filter_map(|(k, v)| v.as_str().map(|s| (k.clone(), s.to_string()))) + .collect::>() + }) + .unwrap_or_default(); + metadata.extend( + connector_metadata_string + .map(|connector_metadata| ("connector_meta_data".to_string(), connector_metadata)), + ); Ok(Self { amount: router_data.request.amount, currency: currency.into(), @@ -287,17 +407,7 @@ impl .customer_id .as_ref() .map(|id| id.get_string_repr().to_string()), - metadata: router_data - .request - .metadata - .as_ref() - .and_then(|val| val.as_object()) - .map(|map| { - map.iter() - .filter_map(|(k, v)| v.as_str().map(|s| (k.clone(), s.to_string()))) - .collect::>() - }) - .unwrap_or_default(), + metadata, test_mode: router_data.test_mode, connector_customer_id: router_data.connector_customer.clone(), merchant_account_metadata: HashMap::new(), @@ -629,6 +739,111 @@ impl } } +impl transformers::ForeignTryFrom + for Result<(PaymentsResponseData, AttemptStatus), ErrorResponse> +{ + type Error = error_stack::Report; + fn foreign_try_from( + response: payments_grpc::PaymentServicePreAuthenticateResponse, + ) -> Result { + let connector_response_reference_id = + response.response_ref_id.as_ref().and_then(|identifier| { + identifier + .id_type + .clone() + .and_then(|id_type| match id_type { + payments_grpc::identifier::IdType::Id(id) => Some(id), + payments_grpc::identifier::IdType::EncodedData(encoded_data) => { + Some(encoded_data) + } + payments_grpc::identifier::IdType::NoResponseIdMarker(_) => None, + }) + }); + + let resource_id: router_request_types::ResponseId = match response + .transaction_id + .as_ref() + .and_then(|id| id.id_type.clone()) + { + Some(payments_grpc::identifier::IdType::Id(id)) => { + router_request_types::ResponseId::ConnectorTransactionId(id) + } + Some(payments_grpc::identifier::IdType::EncodedData(encoded_data)) => { + router_request_types::ResponseId::EncodedData(encoded_data) + } + Some(payments_grpc::identifier::IdType::NoResponseIdMarker(_)) | None => { + router_request_types::ResponseId::NoResponseId + } + }; + + let (connector_metadata, redirection_data) = match response.redirection_data.clone() { + Some(redirection_data) => match redirection_data.form_type { + Some(ref form_type) => match form_type { + payments_grpc::redirect_form::FormType::Uri(uri) => { + // For UPI intent, store the URI in connector_metadata for SDK UPI intent pattern + let sdk_uri_info = api_models::payments::SdkUpiIntentInformation { + sdk_uri: Url::parse(&uri.uri) + .change_context(UnifiedConnectorServiceError::ParsingFailed)?, + }; + ( + Some(sdk_uri_info.encode_to_value()) + .transpose() + .change_context(UnifiedConnectorServiceError::ParsingFailed)?, + None, + ) + } + _ => ( + None, + Some(RedirectForm::foreign_try_from(redirection_data)).transpose()?, + ), + }, + None => (None, None), + }, + None => (None, None), + }; + + let status_code = convert_connector_service_status_code(response.status_code)?; + + let response = if response.error_code.is_some() { + let attempt_status = match response.status() { + payments_grpc::PaymentStatus::AttemptStatusUnspecified => None, + _ => Some(AttemptStatus::foreign_try_from(response.status())?), + }; + + Err(ErrorResponse { + code: response.error_code().to_owned(), + message: response.error_message().to_owned(), + reason: Some(response.error_message().to_owned()), + status_code, + attempt_status, + connector_transaction_id: connector_response_reference_id, + network_decline_code: None, + network_advice_code: None, + network_error_message: None, + connector_metadata: None, + }) + } else { + let status = AttemptStatus::foreign_try_from(response.status())?; + + Ok(( + PaymentsResponseData::TransactionResponse { + resource_id, + redirection_data: Box::new(redirection_data), + mandate_reference: Box::new(None), + connector_metadata, + network_txn_id: response.network_txn_id.clone(), + connector_response_reference_id, + incremental_authorization_allowed: None, + charges: None, + }, + status, + )) + }; + + Ok(response) + } +} + impl transformers::ForeignTryFrom for Result<(PaymentsResponseData, AttemptStatus), ErrorResponse> { @@ -651,10 +866,20 @@ impl transformers::ForeignTryFrom hyperswitch_domain_models::router_request_types::ResponseId::ConnectorTransactionId(id), - Some(payments_grpc::identifier::IdType::EncodedData(encoded_data)) => hyperswitch_domain_models::router_request_types::ResponseId::EncodedData(encoded_data), - Some(payments_grpc::identifier::IdType::NoResponseIdMarker(_)) | None => hyperswitch_domain_models::router_request_types::ResponseId::NoResponseId, + let resource_id: router_request_types::ResponseId = match response + .transaction_id + .as_ref() + .and_then(|id| id.id_type.clone()) + { + Some(payments_grpc::identifier::IdType::Id(id)) => { + router_request_types::ResponseId::ConnectorTransactionId(id) + } + Some(payments_grpc::identifier::IdType::EncodedData(encoded_data)) => { + router_request_types::ResponseId::EncodedData(encoded_data) + } + Some(payments_grpc::identifier::IdType::NoResponseIdMarker(_)) | None => { + router_request_types::ResponseId::NoResponseId + } }; let (connector_metadata, redirection_data) = match response.redirection_data.clone() { @@ -749,10 +974,20 @@ impl transformers::ForeignTryFrom let status_code = convert_connector_service_status_code(response.status_code)?; - let resource_id: hyperswitch_domain_models::router_request_types::ResponseId = match response.transaction_id.as_ref().and_then(|id| id.id_type.clone()) { - Some(payments_grpc::identifier::IdType::Id(id)) => hyperswitch_domain_models::router_request_types::ResponseId::ConnectorTransactionId(id), - Some(payments_grpc::identifier::IdType::EncodedData(encoded_data)) => hyperswitch_domain_models::router_request_types::ResponseId::EncodedData(encoded_data), - Some(payments_grpc::identifier::IdType::NoResponseIdMarker(_)) | None => hyperswitch_domain_models::router_request_types::ResponseId::NoResponseId, + let resource_id: router_request_types::ResponseId = match response + .transaction_id + .as_ref() + .and_then(|id| id.id_type.clone()) + { + Some(payments_grpc::identifier::IdType::Id(id)) => { + router_request_types::ResponseId::ConnectorTransactionId(id) + } + Some(payments_grpc::identifier::IdType::EncodedData(encoded_data)) => { + router_request_types::ResponseId::EncodedData(encoded_data) + } + Some(payments_grpc::identifier::IdType::NoResponseIdMarker(_)) | None => { + router_request_types::ResponseId::NoResponseId + } }; let response = if response.error_code.is_some() { @@ -846,44 +1081,57 @@ impl transformers::ForeignTryFrom } else { let status = AttemptStatus::foreign_try_from(response.status())?; - Ok((PaymentsResponseData::TransactionResponse { - resource_id: response.registration_id.as_ref().and_then(|identifier| { - identifier - .id_type - .clone() - .and_then(|id_type| match id_type { - payments_grpc::identifier::IdType::Id(id) => Some( - hyperswitch_domain_models::router_request_types::ResponseId::ConnectorTransactionId(id), - ), - payments_grpc::identifier::IdType::EncodedData(encoded_data) => Some( - hyperswitch_domain_models::router_request_types::ResponseId::ConnectorTransactionId(encoded_data), - ), - payments_grpc::identifier::IdType::NoResponseIdMarker(_) => None, + Ok(( + PaymentsResponseData::TransactionResponse { + resource_id: response + .registration_id + .as_ref() + .and_then(|identifier| { + identifier + .id_type + .clone() + .and_then(|id_type| match id_type { + payments_grpc::identifier::IdType::Id(id) => Some( + router_request_types::ResponseId::ConnectorTransactionId( + id, + ), + ), + payments_grpc::identifier::IdType::EncodedData( + encoded_data, + ) => Some( + router_request_types::ResponseId::ConnectorTransactionId( + encoded_data, + ), + ), + payments_grpc::identifier::IdType::NoResponseIdMarker(_) => { + None + } + }) }) - }).unwrap_or(hyperswitch_domain_models::router_request_types::ResponseId::NoResponseId), - redirection_data: Box::new( - response - .redirection_data - .clone() - .map(RedirectForm::foreign_try_from) - .transpose()? - ), - mandate_reference: Box::new( - response.mandate_reference.map(|grpc_mandate| { + .unwrap_or(router_request_types::ResponseId::NoResponseId), + redirection_data: Box::new( + response + .redirection_data + .clone() + .map(RedirectForm::foreign_try_from) + .transpose()?, + ), + mandate_reference: Box::new(response.mandate_reference.map(|grpc_mandate| { hyperswitch_domain_models::router_response_types::MandateReference { connector_mandate_id: grpc_mandate.mandate_id, payment_method_id: grpc_mandate.payment_method_id, mandate_metadata: None, connector_mandate_request_reference_id: None, } - }) - ), - connector_metadata: None, - network_txn_id: response.network_txn_id, - connector_response_reference_id, - incremental_authorization_allowed: response.incremental_authorization_allowed, - charges: None, - }, status)) + })), + connector_metadata: None, + network_txn_id: response.network_txn_id, + connector_response_reference_id, + incremental_authorization_allowed: response.incremental_authorization_allowed, + charges: None, + }, + status, + )) }; Ok(response) @@ -942,19 +1190,26 @@ impl transformers::ForeignTryFrom hyperswitch_domain_models::router_request_types::ResponseId::ConnectorTransactionId(transaction_id.clone()), - None => hyperswitch_domain_models::router_request_types::ResponseId::NoResponseId, + Ok(( + PaymentsResponseData::TransactionResponse { + resource_id: match transaction_id.as_ref() { + Some(transaction_id) => { + router_request_types::ResponseId::ConnectorTransactionId( + transaction_id.clone(), + ) + } + None => router_request_types::ResponseId::NoResponseId, + }, + redirection_data: Box::new(None), + mandate_reference: Box::new(None), + connector_metadata: None, + network_txn_id: response.network_txn_id.clone(), + connector_response_reference_id, + incremental_authorization_allowed: None, + charges: None, }, - redirection_data: Box::new(None), - mandate_reference: Box::new(None), - connector_metadata: None, - network_txn_id: response.network_txn_id.clone(), - connector_response_reference_id, - incremental_authorization_allowed: None, - charges: None, - }, status)) + status, + )) }; Ok(response) @@ -1132,15 +1387,13 @@ impl transformers::ForeignTryFrom for payments_grpc::Authent } } -impl - transformers::ForeignTryFrom< - hyperswitch_domain_models::router_request_types::BrowserInformation, - > for payments_grpc::BrowserInformation +impl transformers::ForeignTryFrom + for payments_grpc::BrowserInformation { type Error = error_stack::Report; fn foreign_try_from( - browser_info: hyperswitch_domain_models::router_request_types::BrowserInformation, + browser_info: router_request_types::BrowserInformation, ) -> Result { Ok(Self { color_depth: browser_info.color_depth.map(|v| v.into()), @@ -1497,31 +1750,41 @@ impl transformers::ForeignTryFrom Ok(( PaymentsResponseData::TransactionResponse { - resource_id: response.transaction_id.as_ref().and_then(|identifier| { - identifier - .id_type - .clone() - .and_then(|id_type| match id_type { - payments_grpc::identifier::IdType::Id(id) => Some( - hyperswitch_domain_models::router_request_types::ResponseId::ConnectorTransactionId(id), - ), - payments_grpc::identifier::IdType::EncodedData(encoded_data) => Some( - hyperswitch_domain_models::router_request_types::ResponseId::ConnectorTransactionId(encoded_data), - ), - payments_grpc::identifier::IdType::NoResponseIdMarker(_) => None, - }) - }).unwrap_or(hyperswitch_domain_models::router_request_types::ResponseId::NoResponseId), - redirection_data: Box::new(None), - mandate_reference: Box::new( - response.mandate_reference.map(|grpc_mandate| { - hyperswitch_domain_models::router_response_types::MandateReference { - connector_mandate_id: grpc_mandate.mandate_id, - payment_method_id: grpc_mandate.payment_method_id, - mandate_metadata: None, - connector_mandate_request_reference_id: None, - } + resource_id: response + .transaction_id + .as_ref() + .and_then(|identifier| { + identifier + .id_type + .clone() + .and_then(|id_type| match id_type { + payments_grpc::identifier::IdType::Id(id) => Some( + router_request_types::ResponseId::ConnectorTransactionId( + id, + ), + ), + payments_grpc::identifier::IdType::EncodedData( + encoded_data, + ) => Some( + router_request_types::ResponseId::ConnectorTransactionId( + encoded_data, + ), + ), + payments_grpc::identifier::IdType::NoResponseIdMarker(_) => { + None + } + }) }) - ), + .unwrap_or(router_request_types::ResponseId::NoResponseId), + redirection_data: Box::new(None), + mandate_reference: Box::new(response.mandate_reference.map(|grpc_mandate| { + hyperswitch_domain_models::router_response_types::MandateReference { + connector_mandate_id: grpc_mandate.mandate_id, + payment_method_id: grpc_mandate.payment_method_id, + mandate_metadata: None, + connector_mandate_request_reference_id: None, + } + })), connector_metadata: None, network_txn_id: None, connector_response_reference_id, diff --git a/crates/router/src/types.rs b/crates/router/src/types.rs index 0292595897..d0d30db0a4 100644 --- a/crates/router/src/types.rs +++ b/crates/router/src/types.rs @@ -77,12 +77,12 @@ pub use hyperswitch_domain_models::{ PaymentMethodTokenizationData, PaymentsApproveData, PaymentsAuthorizeData, PaymentsCancelData, PaymentsCancelPostCaptureData, PaymentsCaptureData, PaymentsExtendAuthorizationData, PaymentsIncrementalAuthorizationData, - PaymentsPostProcessingData, PaymentsPostSessionTokensData, PaymentsPreProcessingData, - PaymentsRejectData, PaymentsSessionData, PaymentsSyncData, PaymentsTaxCalculationData, - PaymentsUpdateMetadataData, RefundsData, ResponseId, RetrieveFileRequestData, - SdkPaymentsSessionUpdateData, SetupMandateRequestData, SplitRefundsRequest, - SubmitEvidenceRequestData, SyncRequestType, UploadFileRequestData, VaultRequestData, - VerifyWebhookSourceRequestData, + PaymentsPostProcessingData, PaymentsPostSessionTokensData, PaymentsPreAuthenticateData, + PaymentsPreProcessingData, PaymentsRejectData, PaymentsSessionData, PaymentsSyncData, + PaymentsTaxCalculationData, PaymentsUpdateMetadataData, RefundsData, ResponseId, + RetrieveFileRequestData, SdkPaymentsSessionUpdateData, SetupMandateRequestData, + SplitRefundsRequest, SubmitEvidenceRequestData, SyncRequestType, UploadFileRequestData, + VaultRequestData, VerifyWebhookSourceRequestData, }, router_response_types::{ revenue_recovery::{ diff --git a/crates/router/src/types/api.rs b/crates/router/src/types/api.rs index c54241e6b5..f3ebd63097 100644 --- a/crates/router/src/types/api.rs +++ b/crates/router/src/types/api.rs @@ -46,6 +46,7 @@ use error_stack::ResultExt; pub use hyperswitch_domain_models::router_flow_types::{ access_token_auth::{AccessTokenAuth, AccessTokenAuthentication}, mandate_revoke::MandateRevoke, + unified_authentication_service::*, webhooks::VerifyWebhookSource, }; pub use hyperswitch_interfaces::{