Files
Prasunna Soppa 000aa23c10 refactor(router): Remove payment_methods_v2 and customer_v2 feature flag (#8236)
Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
2025-06-11 18:37:24 +00:00

266 lines
9.5 KiB
Rust

use std::fmt::Debug;
#[cfg(feature = "payouts")]
use api_models::payouts;
use api_models::{enums as api_enums, payment_methods as api};
use common_enums::enums as common_enums;
#[cfg(feature = "v2")]
use common_utils::encryption;
use common_utils::{crypto, ext_traits, id_type, type_name, types::keymanager};
use error_stack::ResultExt;
use hyperswitch_domain_models::{merchant_key_store, payment_methods, type_encryption};
use masking::{PeekInterface, Secret};
use scheduler::errors as sch_errors;
use serde::{Deserialize, Serialize};
use storage_impl::{errors as storage_errors, payment_method};
use crate::core::errors;
#[derive(Debug, Deserialize, Serialize)]
pub struct DeleteCardResp {
pub status: String,
pub error_message: Option<String>,
pub error_code: Option<String>,
}
#[derive(Debug, Deserialize, Serialize, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum DataDuplicationCheck {
Duplicated,
MetaDataChanged,
}
#[async_trait::async_trait]
pub trait PaymentMethodsController {
#[cfg(feature = "v1")]
#[allow(clippy::too_many_arguments)]
async fn create_payment_method(
&self,
req: &api::PaymentMethodCreate,
customer_id: &id_type::CustomerId,
payment_method_id: &str,
locker_id: Option<String>,
merchant_id: &id_type::MerchantId,
pm_metadata: Option<serde_json::Value>,
customer_acceptance: Option<serde_json::Value>,
payment_method_data: crypto::OptionalEncryptableValue,
connector_mandate_details: Option<serde_json::Value>,
status: Option<common_enums::PaymentMethodStatus>,
network_transaction_id: Option<String>,
payment_method_billing_address: crypto::OptionalEncryptableValue,
card_scheme: Option<String>,
network_token_requestor_reference_id: Option<String>,
network_token_locker_id: Option<String>,
network_token_payment_method_data: crypto::OptionalEncryptableValue,
) -> errors::PmResult<payment_methods::PaymentMethod>;
#[cfg(feature = "v1")]
#[allow(clippy::too_many_arguments)]
async fn insert_payment_method(
&self,
resp: &api::PaymentMethodResponse,
req: &api::PaymentMethodCreate,
key_store: &merchant_key_store::MerchantKeyStore,
merchant_id: &id_type::MerchantId,
customer_id: &id_type::CustomerId,
pm_metadata: Option<serde_json::Value>,
customer_acceptance: Option<serde_json::Value>,
locker_id: Option<String>,
connector_mandate_details: Option<serde_json::Value>,
network_transaction_id: Option<String>,
payment_method_billing_address: crypto::OptionalEncryptableValue,
network_token_requestor_reference_id: Option<String>,
network_token_locker_id: Option<String>,
network_token_payment_method_data: crypto::OptionalEncryptableValue,
) -> errors::PmResult<payment_methods::PaymentMethod>;
#[cfg(feature = "v2")]
#[allow(clippy::too_many_arguments)]
async fn insert_payment_method(
&self,
resp: &api::PaymentMethodResponse,
req: &api::PaymentMethodCreate,
key_store: &merchant_key_store::MerchantKeyStore,
merchant_id: &id_type::MerchantId,
customer_id: &id_type::CustomerId,
pm_metadata: Option<serde_json::Value>,
customer_acceptance: Option<serde_json::Value>,
locker_id: Option<String>,
connector_mandate_details: Option<serde_json::Value>,
network_transaction_id: Option<String>,
payment_method_billing_address: Option<encryption::Encryption>,
) -> errors::PmResult<payment_methods::PaymentMethod>;
#[cfg(feature = "v1")]
async fn add_payment_method(
&self,
req: &api::PaymentMethodCreate,
) -> errors::PmResponse<api::PaymentMethodResponse>;
#[cfg(feature = "v1")]
async fn retrieve_payment_method(
&self,
pm: api::PaymentMethodId,
) -> errors::PmResponse<api::PaymentMethodResponse>;
#[cfg(feature = "v1")]
async fn delete_payment_method(
&self,
pm_id: api::PaymentMethodId,
) -> errors::PmResponse<api::PaymentMethodDeleteResponse>;
async fn add_card_hs(
&self,
req: api::PaymentMethodCreate,
card: &api::CardDetail,
customer_id: &id_type::CustomerId,
locker_choice: api_enums::LockerChoice,
card_reference: Option<&str>,
) -> errors::VaultResult<(api::PaymentMethodResponse, Option<DataDuplicationCheck>)>;
/// The response will be the tuple of PaymentMethodResponse and the duplication check of payment_method
async fn add_card_to_locker(
&self,
req: api::PaymentMethodCreate,
card: &api::CardDetail,
customer_id: &id_type::CustomerId,
card_reference: Option<&str>,
) -> errors::VaultResult<(api::PaymentMethodResponse, Option<DataDuplicationCheck>)>;
#[cfg(feature = "payouts")]
async fn add_bank_to_locker(
&self,
req: api::PaymentMethodCreate,
key_store: &merchant_key_store::MerchantKeyStore,
bank: &payouts::Bank,
customer_id: &id_type::CustomerId,
) -> errors::VaultResult<(api::PaymentMethodResponse, Option<DataDuplicationCheck>)>;
#[cfg(feature = "v1")]
async fn get_or_insert_payment_method(
&self,
req: api::PaymentMethodCreate,
resp: &mut api::PaymentMethodResponse,
customer_id: &id_type::CustomerId,
key_store: &merchant_key_store::MerchantKeyStore,
) -> errors::PmResult<payment_methods::PaymentMethod>;
#[cfg(feature = "v2")]
async fn get_or_insert_payment_method(
&self,
req: api::PaymentMethodCreate,
resp: &mut api::PaymentMethodResponse,
customer_id: &id_type::CustomerId,
key_store: &merchant_key_store::MerchantKeyStore,
) -> errors::PmResult<payment_methods::PaymentMethod> {
todo!()
}
#[cfg(feature = "v1")]
async fn get_card_details_with_locker_fallback(
&self,
pm: &payment_methods::PaymentMethod,
) -> errors::PmResult<Option<api::CardDetailFromLocker>>;
#[cfg(feature = "v1")]
async fn get_card_details_without_locker_fallback(
&self,
pm: &payment_methods::PaymentMethod,
) -> errors::PmResult<api::CardDetailFromLocker>;
async fn delete_card_from_locker(
&self,
customer_id: &id_type::CustomerId,
merchant_id: &id_type::MerchantId,
card_reference: &str,
) -> errors::PmResult<DeleteCardResp>;
#[cfg(feature = "v1")]
fn store_default_payment_method(
&self,
req: &api::PaymentMethodCreate,
customer_id: &id_type::CustomerId,
merchant_id: &id_type::MerchantId,
) -> (api::PaymentMethodResponse, Option<DataDuplicationCheck>);
#[cfg(feature = "v2")]
fn store_default_payment_method(
&self,
req: &api::PaymentMethodCreate,
customer_id: &id_type::CustomerId,
merchant_id: &id_type::MerchantId,
) -> (api::PaymentMethodResponse, Option<DataDuplicationCheck>);
#[cfg(feature = "v1")]
#[allow(clippy::too_many_arguments)]
async fn save_network_token_and_update_payment_method(
&self,
req: &api::PaymentMethodMigrate,
key_store: &merchant_key_store::MerchantKeyStore,
network_token_data: &api_models::payment_methods::MigrateNetworkTokenData,
network_token_requestor_ref_id: String,
pm_id: String,
) -> errors::PmResult<bool>;
#[cfg(feature = "v1")]
async fn set_default_payment_method(
&self,
merchant_id: &id_type::MerchantId,
customer_id: &id_type::CustomerId,
payment_method_id: String,
) -> errors::PmResponse<api_models::payment_methods::CustomerDefaultPaymentMethodResponse>;
#[cfg(feature = "v1")]
async fn add_payment_method_status_update_task(
&self,
payment_method: &payment_methods::PaymentMethod,
prev_status: common_enums::PaymentMethodStatus,
curr_status: common_enums::PaymentMethodStatus,
merchant_id: &id_type::MerchantId,
) -> Result<(), sch_errors::ProcessTrackerError>;
#[cfg(feature = "v1")]
async fn validate_merchant_connector_ids_in_connector_mandate_details(
&self,
key_store: &merchant_key_store::MerchantKeyStore,
connector_mandate_details: &api_models::payment_methods::CommonMandateReference,
merchant_id: &id_type::MerchantId,
card_network: Option<common_enums::CardNetwork>,
) -> errors::PmResult<()>;
}
pub async fn create_encrypted_data<T>(
key_manager_state: &keymanager::KeyManagerState,
key_store: &merchant_key_store::MerchantKeyStore,
data: T,
) -> Result<
crypto::Encryptable<Secret<serde_json::Value>>,
error_stack::Report<storage_errors::StorageError>,
>
where
T: Debug + Serialize,
{
let key = key_store.key.get_inner().peek();
let identifier = keymanager::Identifier::Merchant(key_store.merchant_id.clone());
let encoded_data = ext_traits::Encode::encode_to_value(&data)
.change_context(storage_errors::StorageError::SerializationFailed)
.attach_printable("Unable to encode data")?;
let secret_data = Secret::<_, masking::WithType>::new(encoded_data);
let encrypted_data = type_encryption::crypto_operation(
key_manager_state,
type_name!(payment_method::PaymentMethod),
type_encryption::CryptoOperation::Encrypt(secret_data),
identifier.clone(),
key,
)
.await
.and_then(|val| val.try_into_operation())
.change_context(storage_errors::StorageError::EncryptionError)
.attach_printable("Unable to encrypt data")?;
Ok(encrypted_data)
}