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

Code before:
                pm_transforms::generate_pm_vaulting_req_from_update_request(
                    pmd,
                    payment_method_data,
                )
            })
            .ok_or(errors::ApiErrorResponse::MissingRequiredField {
                field_name: "payment_method_data",
            })?;

        let current_vault_id = self.payment_method.locker_id.clone();

        let fingerprint_id_from_vault = vault::get_fingerprint_id_from_vault(
            self.state,
            &vault_request_data,
            self.payment_method
                .customer_id
                .clone()
                .get_required_value("GlobalCustomerId")?
                .get_string_repr()
                .to_owned(),
        )
        .await
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Failed to get fingerprint_id from vault")?;

        let is_stored_payment_method_same_as_in_request = self
            .payment_method
            .locker_fingerprint_id
            .clone()
            .map(|data| data == fingerprint_id_from_vault);

        match is_stored_payment_method_same_as_in_request {
            Some(true) => {
                logger::info!(
                    "Payment method vault data is same as in request, skipping vault update"
                );
                Ok((None, None))
            }
            Some(false) | None => {
                logger::info!("Payment method vault data is different from request, proceeding with vault update");
                let (vault_response, _) = vault_payment_method(
                    self.state,
                    &vault_request_data,
                    self.platform,
                    self.profile,
                    current_vault_id,
                    fingerprint_id_from_vault,
                    &self
                        .payment_method
                        .customer_id
                        .to_owned()

Review comment (performance):
Adding an early return would introduce additional complexity:
1. It makes the code harder to read.
2. If this piece of code is moved or misplaced in the future, payment_method_data could unintentionally be treated as mandatory in the update request.

Code after:
            .async_map(|cvc| {
                vault::insert_cvc_using_payment_token(
                    self.state,
                    self.payment_method.get_id(),
                    cvc,
                    common_utils::consts::DEFAULT_INTENT_FULFILLMENT_TIME,
                    self.platform.get_provider().get_key_store(),
                )
            })
            .await
            .transpose()
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable("Failed to insert encrypted cvc in redis")?;

        Ok(card_cvc_token_details)
    }

    pub async fn perform_vaulting_operations_if_required(
        &self,
    ) -> RouterResult<(
        Option<domain::PaymentMethodVaultingData>,
        Option<pm_types::AddVaultResponse>,
    )> {
        if !self.request.is_payment_method_metadata_update() {
            return Ok((None, None));
        }

        let pmd: domain::PaymentMethodVaultingData = vault::retrieve_payment_method_from_vault(
            self.state,
            self.platform,
            self.profile,
            &self.payment_method,
        )
        .await
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Failed to retrieve payment method from vault")?
        .data;

        let vault_request_data = self
            .request
            .payment_method_data
            .clone()
            .map(|payment_method_data| {
                pm_transforms::generate_pm_vaulting_req_from_update_request(
                    pmd,
                    payment_method_data,
                )
            })
            .ok_or(errors::ApiErrorResponse::MissingRequiredField {
                field_name: "payment_method_data",
            })?;