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

Code before:
    //TODO: update the payment method session with the payment id and payment method id
    let payment_method_session_response = transformers::generate_payment_method_session_response(
        payment_method_session,
        Secret::new("CLIENT_SECRET_REDACTED".to_string()),
        payments_response,
        (tokenization_response.flatten()),
        payment_method_response.storage_type,
        payment_method_response.card_cvc_token_storage,
        None,
    );

    Ok(services::ApplicationResponse::Json(
        payment_method_session_response,
    ))
}

#[cfg(feature = "v2")]
pub fn get_storage_type_for_payment_method_create(
    request_storage_type: Option<enums::StorageType>,
    session_storage_type: enums::StorageType,
) -> RouterResult<Option<enums::StorageType>> {
    // If session storage type is volatile, ignore request storage type and always use volatile
    // If session storage type is persistent, use whatever request storage type is sent
    match session_storage_type {
        enums::StorageType::Volatile => Ok(Some(enums::StorageType::Volatile)),
        enums::StorageType::Persistent => Ok(request_storage_type),
    }
}

#[cfg(feature = "v2")]
impl pm_types::SavedPMLPaymentsInfo {
    pub async fn form_payments_info(
        payment_intent: PaymentIntent,
        platform: &domain::Platform,
        profile: domain::Profile,
        db: &dyn StorageInterface,
        key_manager_state: &util_types::keymanager::KeyManagerState,
    ) -> RouterResult<Self> {
        let collect_cvv_during_payment = profile.should_collect_cvv_during_payment;

        let off_session_payment_flag = matches!(
            payment_intent.setup_future_usage,
            common_enums::FutureUsage::OffSession
        );

        let is_connector_agnostic_mit_enabled =
            profile.is_connector_agnostic_mit_enabled.unwrap_or(false);

        Ok(Self {
            payment_intent,
            profile,

Review comment (suggestion):
request_storage_type should be mandatory in the session confirm required value if session create storage type is `Persistent`. And storage type from confirm call should take precedence

Code after:
        .attach_printable("Unexpected response from payments core")
}

#[cfg(feature = "v2")]
pub async fn payment_methods_session_confirm(
    state: SessionState,
    req_state: routes::app::ReqState,
    platform: domain::Platform,
    profile: domain::Profile,
    payment_method_session_id: id_type::GlobalPaymentMethodSessionId,
    request: payment_methods::PaymentMethodSessionConfirmRequest,
) -> RouterResponse<payment_methods::PaymentMethodSessionResponse> {
    let db: &dyn StorageInterface = state.store.as_ref();
    request.validate()?;

    // Validate if the session still exists
    let payment_method_session = db
        .get_payment_methods_session(
            platform.get_provider().get_key_store(),
            &payment_method_session_id,
        )
        .await
        .to_not_found_response(errors::ApiErrorResponse::GenericNotFoundError {
            message: "payment methods session does not exist or has expired".to_string(),
        })
        .attach_printable("Failed to retrieve payment methods session from db")?;

    let payment_method_session_billing = payment_method_session
        .billing
        .clone()
        .map(|billing| billing.into_inner())
        .map(From::from);

    // Unify the billing address that we receive from the session and from the confirm request
    let unified_billing_address = request
        .payment_method_data
        .billing
        .clone()
        .map(|payment_method_billing| {
            payment_method_billing.unify_address(payment_method_session_billing.as_ref())
        })
        .or_else(|| payment_method_session_billing.clone());

    let storage_type = get_storage_type_for_payment_method_create(
        request.storage_type,
        payment_method_session.storage_type,
    )?;

    let create_payment_method_request = get_payment_method_create_request(
        request
            .payment_method_data