From 5ccffaac64bf6a95c9f04362b2b751fad2eeb192 Mon Sep 17 00:00:00 2001 From: nithin Date: Thu, 8 May 2025 14:17:32 +0530 Subject: [PATCH 1/3] Update Metadata --- .../payments/flows/update_metadata_flow.rs | 25 ++- .../router/src/core/payments/transformers.rs | 189 ++++++++++++++++++ 2 files changed, 201 insertions(+), 13 deletions(-) diff --git a/crates/router/src/core/payments/flows/update_metadata_flow.rs b/crates/router/src/core/payments/flows/update_metadata_flow.rs index 9281775e393..f9a6790356a 100644 --- a/crates/router/src/core/payments/flows/update_metadata_flow.rs +++ b/crates/router/src/core/payments/flows/update_metadata_flow.rs @@ -30,19 +30,18 @@ impl merchant_recipient_data: Option, header_payload: Option, ) -> RouterResult { - Box::pin(transformers::construct_payment_router_data::< - api::UpdateMetadata, - types::PaymentsUpdateMetadataData, - >( - state, - self.clone(), - connector_id, - merchant_context, - customer, - merchant_connector_account, - merchant_recipient_data, - header_payload, - )) + Box::pin( + transformers::construct_payment_router_data_for_update_metadata( + state, + self.clone(), + connector_id, + merchant_context, + customer, + merchant_connector_account, + merchant_recipient_data, + header_payload, + ), + ) .await } diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs index ac7b4cb00b1..bab9aa6c8d5 100644 --- a/crates/router/src/core/payments/transformers.rs +++ b/crates/router/src/core/payments/transformers.rs @@ -1247,6 +1247,195 @@ where Ok(router_data) } +#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "customer_v2")))] +#[instrument(skip_all)] +#[allow(clippy::too_many_arguments)] +pub async fn construct_payment_router_data_for_update_metadata<'a>( + state: &'a SessionState, + payment_data: PaymentData, + connector_id: &str, + merchant_context: &domain::MerchantContext, + customer: &'a Option, + merchant_connector_account: &helpers::MerchantConnectorAccountType, + merchant_recipient_data: Option, + header_payload: Option, +) -> RouterResult< + types::RouterData< + api::UpdateMetadata, + types::PaymentsUpdateMetadataData, + types::PaymentsResponseData, + >, +> { + let (payment_method, router_data); + + fp_utils::when(merchant_connector_account.is_disabled(), || { + Err(errors::ApiErrorResponse::MerchantConnectorAccountDisabled) + })?; + + let test_mode = merchant_connector_account.is_test_mode_on(); + + let auth_type: types::ConnectorAuthType = merchant_connector_account + .get_connector_account_details() + .parse_value("ConnectorAuthType") + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Failed while parsing value for ConnectorAuthType")?; + + payment_method = payment_data + .payment_attempt + .payment_method + .or(payment_data.payment_attempt.payment_method) + .get_required_value("payment_method_type")?; + + // [#44]: why should response be filled during request + let response = Err(hyperswitch_domain_models::router_data::ErrorResponse { + code: "IR_29".to_string(), + message: "Update metadata is not implemented for this connector".to_string(), + reason: None, + status_code: http::StatusCode::UNPROCESSABLE_ENTITY.as_u16(), + attempt_status: None, + connector_transaction_id: None, + network_decline_code: None, + network_advice_code: None, + network_error_message: None, + }); + + let additional_data = PaymentAdditionalData { + router_base_url: state.base_url.clone(), + connector_name: connector_id.to_string(), + payment_data: payment_data.clone(), + state, + customer_data: customer, + }; + + let customer_id = customer.to_owned().map(|customer| customer.customer_id); + + let supported_connector = &state + .conf + .multiple_api_version_supported_connectors + .supported_connectors; + let connector_enum = api_models::enums::Connector::from_str(connector_id) + .change_context(errors::ConnectorError::InvalidConnectorName) + .change_context(errors::ApiErrorResponse::InvalidDataValue { + field_name: "connector", + }) + .attach_printable_lazy(|| format!("unable to parse connector name {connector_id:?}"))?; + + let connector_api_version = if supported_connector.contains(&connector_enum) { + state + .store + .find_config_by_key(&format!("connector_api_version_{connector_id}")) + .await + .map(|value| value.config) + .ok() + } else { + None + }; + + let apple_pay_flow = payments::decide_apple_pay_flow( + state, + payment_data.payment_attempt.payment_method_type, + Some(merchant_connector_account), + ); + + let unified_address = if let Some(payment_method_info) = + payment_data.payment_method_info.clone() + { + let payment_method_billing = payment_method_info + .payment_method_billing_address + .map(|decrypted_data| decrypted_data.into_inner().expose()) + .map(|decrypted_value| decrypted_value.parse_value("payment_method_billing_address")) + .transpose() + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("unable to parse payment_method_billing_address")?; + payment_data + .address + .clone() + .unify_with_payment_data_billing(payment_method_billing) + } else { + payment_data.address + }; + let connector_mandate_request_reference_id = payment_data + .payment_attempt + .connector_mandate_detail + .as_ref() + .and_then(|detail| detail.get_connector_mandate_request_reference_id()); + + crate::logger::debug!("unified address details {:?}", unified_address); + + router_data = types::RouterData { + flow: PhantomData, + merchant_id: merchant_context.get_merchant_account().get_id().clone(), + customer_id, + tenant_id: state.tenant.tenant_id.clone(), + connector: connector_id.to_owned(), + payment_id: payment_data + .payment_attempt + .payment_id + .get_string_repr() + .to_owned(), + attempt_id: payment_data.payment_attempt.attempt_id.clone(), + status: payment_data.payment_attempt.status, + payment_method, + connector_auth_type: auth_type, + description: payment_data.payment_intent.description.clone(), + address: unified_address, + auth_type: payment_data + .payment_attempt + .authentication_type + .unwrap_or_default(), + connector_meta_data: merchant_connector_account.get_metadata(), + connector_wallets_details: merchant_connector_account.get_connector_wallets_details(), + request: types::PaymentsUpdateMetadataData::try_from(additional_data)?, + response, + amount_captured: payment_data + .payment_intent + .amount_captured + .map(|amt| amt.get_amount_as_i64()), + minor_amount_captured: payment_data.payment_intent.amount_captured, + access_token: None, + session_token: None, + reference_id: None, + payment_method_status: payment_data.payment_method_info.map(|info| info.status), + payment_method_token: payment_data + .pm_token + .map(|token| types::PaymentMethodToken::Token(Secret::new(token))), + connector_customer: payment_data.connector_customer_id, + recurring_mandate_payment_data: payment_data.recurring_mandate_payment_data, + connector_request_reference_id: core_utils::get_connector_request_reference_id( + &state.conf, + merchant_context.get_merchant_account().get_id(), + &payment_data.payment_attempt, + ), + preprocessing_id: payment_data.payment_attempt.preprocessing_step_id, + #[cfg(feature = "payouts")] + payout_method_data: None, + #[cfg(feature = "payouts")] + quote_id: None, + test_mode, + payment_method_balance: None, + connector_api_version, + connector_http_status_code: None, + external_latency: None, + apple_pay_flow, + frm_metadata: None, + refund_id: None, + dispute_id: None, + connector_response: None, + integrity_check: Ok(()), + additional_merchant_data: merchant_recipient_data.map(|data| { + api_models::admin::AdditionalMerchantData::foreign_from( + types::AdditionalMerchantData::OpenBankingRecipientData(data), + ) + }), + header_payload, + connector_mandate_request_reference_id, + authentication_id: None, + psd2_sca_exemption_type: payment_data.payment_intent.psd2_sca_exemption_type, + }; + + Ok(router_data) +} + pub trait ToResponse where Self: Sized, From aff79e9d18bb8abe2ae1516548bc21b20ef9eed9 Mon Sep 17 00:00:00 2001 From: nithin Date: Thu, 8 May 2025 15:14:20 +0530 Subject: [PATCH 2/3] bad request --- crates/router/src/core/payments/transformers.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs index bab9aa6c8d5..b7a2ad28ce4 100644 --- a/crates/router/src/core/payments/transformers.rs +++ b/crates/router/src/core/payments/transformers.rs @@ -1291,7 +1291,7 @@ pub async fn construct_payment_router_data_for_update_metadata<'a>( code: "IR_29".to_string(), message: "Update metadata is not implemented for this connector".to_string(), reason: None, - status_code: http::StatusCode::UNPROCESSABLE_ENTITY.as_u16(), + status_code: http::StatusCode::BAD_REQUEST.as_u16(), attempt_status: None, connector_transaction_id: None, network_decline_code: None, From be0198ebf896cd96fca39afe2654253d9f317902 Mon Sep 17 00:00:00 2001 From: nithin Date: Thu, 8 May 2025 15:16:18 +0530 Subject: [PATCH 3/3] IR_20 --- crates/router/src/core/payments/transformers.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs index b7a2ad28ce4..211be32ce9f 100644 --- a/crates/router/src/core/payments/transformers.rs +++ b/crates/router/src/core/payments/transformers.rs @@ -1288,7 +1288,7 @@ pub async fn construct_payment_router_data_for_update_metadata<'a>( // [#44]: why should response be filled during request let response = Err(hyperswitch_domain_models::router_data::ErrorResponse { - code: "IR_29".to_string(), + code: "IR_20".to_string(), message: "Update metadata is not implemented for this connector".to_string(), reason: None, status_code: http::StatusCode::BAD_REQUEST.as_u16(),