Repository: juspay/hyperswitch
File: crates/router/src/core/payments/helpers.rs (Rust)

Code before:
}

pub fn update_additional_payment_data_with_connector_response_pm_data(
    additional_payment_data: Option<serde_json::Value>,
    connector_response_pm_data: Option<AdditionalPaymentMethodConnectorResponse>,
) -> RouterResult<Option<serde_json::Value>> {
    let parsed_additional_payment_method_data = additional_payment_data
        .as_ref()
        .map(|payment_method_data| {
            payment_method_data
                .clone()
                .parse_value::<api_models::payments::AdditionalPaymentData>(
                    "additional_payment_method_data",
                )
        })
        .transpose()
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("unable to parse value into additional_payment_method_data")?;

    let additional_payment_method_data = match (
        parsed_additional_payment_method_data,
        connector_response_pm_data,
    ) {
        (Some(additional_pm_data), Some(connector_response_pm_data)) => {
            // Handle UPI upi_mode override for v2 - extract upi_mode before moving
            #[cfg(feature = "v2")]
            let upi_mode_override =
                if let AdditionalPaymentMethodConnectorResponse::Upi { upi_mode } =
                    &connector_response_pm_data
                {
                    upi_mode.clone()
                } else {
                    None
                };

            let additional_pm_data = add_connector_response_to_additional_payment_data(
                additional_pm_data,
                connector_response_pm_data,
            );
            // Apply UPI mode override if present
            #[cfg(feature = "v2")]
            let mut additional_pm_data = additional_pm_data;
            #[cfg(feature = "v2")]
            if let Some(ref mode) = upi_mode_override {
                override_upi_source_in_additional_payment_data(&mut additional_pm_data, mode);
            }

            Some(additional_pm_data)
        }
        (Some(additional_pm_data), None) => Some(additional_pm_data),
        (None, _) => None,

Review comment (suggestion):
We should not add feature level branching within functions, why can't we re-use existing functionality? You can create a new `add_connector_response_to_additional_payment_data` for V2 

Code after:
                        upi_source,
                    }))
                }
            };
            api_models::payments::AdditionalPaymentData::Upi {
                details: Some(updated_details),
            }
        }

        _ => additional_payment_data,
    }
}

#[cfg(feature = "v1")]
pub async fn get_payment_method_data_and_encrypted_payment_method_data(
    payment_attempt: &PaymentAttempt,
    key_manager_state: &KeyManagerState,
    key_store: &domain::MerchantKeyStore,
    additional_payment_method_data_intermediate: Option<serde_json::Value>,
) -> CustomResult<
    (
        Option<serde_json::Value>,
        Option<Encryptable<masking::Secret<serde_json::Value>>>,
    ),
    errors::ApiErrorResponse,
> {
    if payment_attempt
        .payment_method
        .as_ref()
        .map(|payment_method| payment_method.is_additional_payment_method_data_sensitive())
        .unwrap_or(false)
    {
        let encrypted_payment_method_data = additional_payment_method_data_intermediate
            .clone()
            .async_map(|additional_payment_method_data_intermediate| {
                create_encrypted_data(
                    key_manager_state,
                    key_store,
                    additional_payment_method_data_intermediate,
                )
            })
            .await
            .transpose()
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable("Unable to encrypt additional_payment_method_data")?;
        Ok((None, encrypted_payment_method_data))
    } else {
        Ok((additional_payment_method_data_intermediate, None))
    }
}