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

Code before:
        .attach_printable("Failed to get redis connection")?;

    let key = format!("pm_token_{payment_token}_{payment_method}_hyperswitch_cvc");

    let payload_to_be_encrypted = TemporaryVaultCvc { card_cvc };

    let payload = payload_to_be_encrypted
        .encode_to_string_of_json()
        .change_context(errors::ApiErrorResponse::InternalServerError)?;

    // Encrypt the CVC and store it in Redis
    let encrypted_payload = GcmAes256
        .encode_message(encryption_key.peek().as_ref(), payload.as_bytes())
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Failed to encode TemporaryVaultCvc for vault")?;

    redis_conn
        .set_key_with_expiry(
            &key.as_str().into(),
            bytes::Bytes::from(encrypted_payload),
            fulfillment_time,
        )
        .await
        .change_context(errors::StorageError::KVError)
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Failed to add token in redis")?;

    let card_token_cvc_storage =
        api_models::payment_methods::CardCVCTokenStorageDetails::generate_expiry_timestamp(
            fulfillment_time,
        );

    Ok(card_token_cvc_storage)
}

#[cfg(feature = "v2")]
#[instrument(skip_all)]
pub async fn retrieve_and_delete_cvc_from_payment_token(
    state: &routes::SessionState,
    payment_token: &String,
    payment_method: common_enums::PaymentMethod,
    encryption_key: &masking::Secret<Vec<u8>>,
) -> RouterResult<masking::Secret<String>> {
    let redis_conn = state
        .store
        .get_redis_conn()
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Failed to get redis connection")?;

    let key = format!("pm_token_{payment_token}_{payment_method}_hyperswitch_cvc",);


Review comment (bug):
```suggestion
        .attach_printable("Failed to add encrypted cvc in redis")?;
```

Code after:

    let payload = payload_to_be_encrypted
        .encode_to_string_of_json()
        .change_context(errors::ApiErrorResponse::InternalServerError)?;

    // Encrypt the CVC and store it in Redis
    let encrypted_payload =
        pm_cards::create_encrypted_data(&(state.into()), key_store, payload.as_bytes())
            .await
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable("Failed to encrypt TemporaryVaultCvc for vault")?
            .encode_to_vec()
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable("Failed to encode TemporaryVaultCvc to bytes for vault")?;

    redis_conn
        .set_key_with_expiry(
            &key.as_str().into(),
            bytes::Bytes::from(encrypted_payload),
            fulfillment_time,
        )
        .await
        .change_context(errors::StorageError::KVError)
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Failed to add encrypted cvc in redis")?;

    let card_token_cvc_storage =
        api_models::payment_methods::CardCVCTokenStorageDetails::generate_expiry_timestamp(
            fulfillment_time,
        );

    Ok(card_token_cvc_storage)
}

#[cfg(feature = "v2")]
#[instrument(skip_all)]
pub async fn retrieve_and_delete_cvc_from_payment_token(
    state: &routes::SessionState,
    payment_token: &String,
    payment_method: common_enums::PaymentMethod,
    encryption_key: &masking::Secret<Vec<u8>>,
) -> RouterResult<masking::Secret<String>> {
    let redis_conn = state
        .store
        .get_redis_conn()
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Failed to get redis connection")?;

    let key = format!("pm_token_{payment_token}_hyperswitch_cvc");

    let data = redis_conn