#[cfg(all(feature = "v2", feature = "payment_methods_v2"))] use common_utils::crypto::Encryptable; use common_utils::{ crypto::OptionalEncryptableValue, errors::{CustomResult, ValidationError}, pii, type_name, types::keymanager, }; use diesel_models::enums as storage_enums; use error_stack::ResultExt; use masking::{PeekInterface, Secret}; use time::PrimitiveDateTime; #[cfg(all(feature = "v2", feature = "payment_methods_v2"))] use crate::type_encryption::OptionalEncryptableJsonType; use crate::type_encryption::{crypto_operation, AsyncLift, CryptoOperation}; #[cfg(all(feature = "v2", feature = "payment_methods_v2"))] #[derive(Debug, serde::Deserialize, serde::Serialize, Clone)] pub struct VaultId(String); #[cfg(all(feature = "v2", feature = "payment_methods_v2"))] impl VaultId { pub fn get_string_repr(&self) -> &String { &self.0 } pub fn generate(id: String) -> Self { Self(id) } } #[cfg(all( any(feature = "v1", feature = "v2"), not(feature = "payment_methods_v2") ))] #[derive(Clone, Debug)] pub struct PaymentMethod { pub customer_id: common_utils::id_type::CustomerId, pub merchant_id: common_utils::id_type::MerchantId, pub payment_method_id: String, pub accepted_currency: Option>, pub scheme: Option, pub token: Option, pub cardholder_name: Option>, pub issuer_name: Option, pub issuer_country: Option, pub payer_country: Option>, pub is_stored: Option, pub swift_code: Option, pub direct_debit_token: Option, pub created_at: PrimitiveDateTime, pub last_modified: PrimitiveDateTime, pub payment_method: Option, pub payment_method_type: Option, pub payment_method_issuer: Option, pub payment_method_issuer_code: Option, pub metadata: Option, pub payment_method_data: OptionalEncryptableValue, pub locker_id: Option, pub last_used_at: PrimitiveDateTime, pub connector_mandate_details: Option, pub customer_acceptance: Option, pub status: storage_enums::PaymentMethodStatus, pub network_transaction_id: Option, pub client_secret: Option, pub payment_method_billing_address: OptionalEncryptableValue, pub updated_by: Option, pub version: common_enums::ApiVersion, pub network_token_requestor_reference_id: Option, pub network_token_locker_id: Option, pub network_token_payment_method_data: OptionalEncryptableValue, } #[cfg(all(feature = "v2", feature = "payment_methods_v2"))] #[derive(Clone, Debug)] pub struct PaymentMethod { pub customer_id: common_utils::id_type::GlobalCustomerId, pub merchant_id: common_utils::id_type::MerchantId, pub created_at: PrimitiveDateTime, pub last_modified: PrimitiveDateTime, pub payment_method_type: Option, pub payment_method_subtype: Option, pub payment_method_data: OptionalEncryptableJsonType, pub locker_id: Option, pub last_used_at: PrimitiveDateTime, pub connector_mandate_details: Option, pub customer_acceptance: Option, pub status: storage_enums::PaymentMethodStatus, pub network_transaction_id: Option, pub client_secret: Option, pub payment_method_billing_address: OptionalEncryptableValue, pub updated_by: Option, pub locker_fingerprint_id: Option, pub id: common_utils::id_type::GlobalPaymentMethodId, pub version: common_enums::ApiVersion, pub network_token_requestor_reference_id: Option, pub network_token_locker_id: Option, pub network_token_payment_method_data: OptionalEncryptableValue, } impl PaymentMethod { #[cfg(all( any(feature = "v1", feature = "v2"), not(feature = "payment_methods_v2") ))] pub fn get_id(&self) -> &String { &self.payment_method_id } #[cfg(all(feature = "v2", feature = "payment_methods_v2"))] pub fn get_id(&self) -> &common_utils::id_type::GlobalPaymentMethodId { &self.id } #[cfg(all( any(feature = "v1", feature = "v2"), not(feature = "payment_methods_v2") ))] pub fn get_payment_method_type(&self) -> Option { self.payment_method } #[cfg(all(feature = "v2", feature = "payment_methods_v2"))] pub fn get_payment_method_type(&self) -> Option { self.payment_method_type } #[cfg(all( any(feature = "v1", feature = "v2"), not(feature = "payment_methods_v2") ))] pub fn get_payment_method_subtype(&self) -> Option { self.payment_method_type } #[cfg(all(feature = "v2", feature = "payment_methods_v2"))] pub fn get_payment_method_subtype(&self) -> Option { self.payment_method_subtype } } #[cfg(all( any(feature = "v1", feature = "v2"), not(feature = "payment_methods_v2") ))] #[async_trait::async_trait] impl super::behaviour::Conversion for PaymentMethod { type DstType = diesel_models::payment_method::PaymentMethod; type NewDstType = diesel_models::payment_method::PaymentMethodNew; async fn convert(self) -> CustomResult { Ok(Self::DstType { customer_id: self.customer_id, merchant_id: self.merchant_id, payment_method_id: self.payment_method_id, accepted_currency: self.accepted_currency, scheme: self.scheme, token: self.token, cardholder_name: self.cardholder_name, issuer_name: self.issuer_name, issuer_country: self.issuer_country, payer_country: self.payer_country, is_stored: self.is_stored, swift_code: self.swift_code, direct_debit_token: self.direct_debit_token, created_at: self.created_at, last_modified: self.last_modified, payment_method: self.payment_method, payment_method_type: self.payment_method_type, payment_method_issuer: self.payment_method_issuer, payment_method_issuer_code: self.payment_method_issuer_code, metadata: self.metadata, payment_method_data: self.payment_method_data.map(|val| val.into()), locker_id: self.locker_id, last_used_at: self.last_used_at, connector_mandate_details: self.connector_mandate_details, customer_acceptance: self.customer_acceptance, status: self.status, network_transaction_id: self.network_transaction_id, client_secret: self.client_secret, payment_method_billing_address: self .payment_method_billing_address .map(|val| val.into()), updated_by: self.updated_by, version: self.version, network_token_requestor_reference_id: self.network_token_requestor_reference_id, network_token_locker_id: self.network_token_locker_id, network_token_payment_method_data: self .network_token_payment_method_data .map(|val| val.into()), }) } async fn convert_back( state: &keymanager::KeyManagerState, item: Self::DstType, key: &Secret>, key_manager_identifier: keymanager::Identifier, ) -> CustomResult where Self: Sized, { async { Ok::>(Self { customer_id: item.customer_id, merchant_id: item.merchant_id, payment_method_id: item.payment_method_id, accepted_currency: item.accepted_currency, scheme: item.scheme, token: item.token, cardholder_name: item.cardholder_name, issuer_name: item.issuer_name, issuer_country: item.issuer_country, payer_country: item.payer_country, is_stored: item.is_stored, swift_code: item.swift_code, direct_debit_token: item.direct_debit_token, created_at: item.created_at, last_modified: item.last_modified, payment_method: item.payment_method, payment_method_type: item.payment_method_type, payment_method_issuer: item.payment_method_issuer, payment_method_issuer_code: item.payment_method_issuer_code, metadata: item.metadata, payment_method_data: item .payment_method_data .async_lift(|inner| async { crypto_operation( state, type_name!(Self::DstType), CryptoOperation::DecryptOptional(inner), key_manager_identifier.clone(), key.peek(), ) .await .and_then(|val| val.try_into_optionaloperation()) }) .await?, locker_id: item.locker_id, last_used_at: item.last_used_at, connector_mandate_details: item.connector_mandate_details, customer_acceptance: item.customer_acceptance, status: item.status, network_transaction_id: item.network_transaction_id, client_secret: item.client_secret, payment_method_billing_address: item .payment_method_billing_address .async_lift(|inner| async { crypto_operation( state, type_name!(Self::DstType), CryptoOperation::DecryptOptional(inner), key_manager_identifier.clone(), key.peek(), ) .await .and_then(|val| val.try_into_optionaloperation()) }) .await?, updated_by: item.updated_by, version: item.version, network_token_requestor_reference_id: item.network_token_requestor_reference_id, network_token_locker_id: item.network_token_locker_id, network_token_payment_method_data: item .network_token_payment_method_data .async_lift(|inner| async { crypto_operation( state, type_name!(Self::DstType), CryptoOperation::DecryptOptional(inner), key_manager_identifier.clone(), key.peek(), ) .await .and_then(|val| val.try_into_optionaloperation()) }) .await?, }) } .await .change_context(ValidationError::InvalidValue { message: "Failed while decrypting payment method data".to_string(), }) } async fn construct_new(self) -> CustomResult { Ok(Self::NewDstType { customer_id: self.customer_id, merchant_id: self.merchant_id, payment_method_id: self.payment_method_id, accepted_currency: self.accepted_currency, scheme: self.scheme, token: self.token, cardholder_name: self.cardholder_name, issuer_name: self.issuer_name, issuer_country: self.issuer_country, payer_country: self.payer_country, is_stored: self.is_stored, swift_code: self.swift_code, direct_debit_token: self.direct_debit_token, created_at: self.created_at, last_modified: self.last_modified, payment_method: self.payment_method, payment_method_type: self.payment_method_type, payment_method_issuer: self.payment_method_issuer, payment_method_issuer_code: self.payment_method_issuer_code, metadata: self.metadata, payment_method_data: self.payment_method_data.map(|val| val.into()), locker_id: self.locker_id, last_used_at: self.last_used_at, connector_mandate_details: self.connector_mandate_details, customer_acceptance: self.customer_acceptance, status: self.status, network_transaction_id: self.network_transaction_id, client_secret: self.client_secret, payment_method_billing_address: self .payment_method_billing_address .map(|val| val.into()), updated_by: self.updated_by, version: self.version, network_token_requestor_reference_id: self.network_token_requestor_reference_id, network_token_locker_id: self.network_token_locker_id, network_token_payment_method_data: self .network_token_payment_method_data .map(|val| val.into()), }) } } #[cfg(all(feature = "v2", feature = "payment_methods_v2"))] #[async_trait::async_trait] impl super::behaviour::Conversion for PaymentMethod { type DstType = diesel_models::payment_method::PaymentMethod; type NewDstType = diesel_models::payment_method::PaymentMethodNew; async fn convert(self) -> CustomResult { Ok(Self::DstType { customer_id: self.customer_id, merchant_id: self.merchant_id, id: self.id, created_at: self.created_at, last_modified: self.last_modified, payment_method_type_v2: self.payment_method_type, payment_method_subtype: self.payment_method_subtype, payment_method_data: self.payment_method_data.map(|val| val.into()), locker_id: self.locker_id.map(|id| id.get_string_repr().clone()), last_used_at: self.last_used_at, connector_mandate_details: self.connector_mandate_details, customer_acceptance: self.customer_acceptance, status: self.status, network_transaction_id: self.network_transaction_id, client_secret: self.client_secret, payment_method_billing_address: self .payment_method_billing_address .map(|val| val.into()), updated_by: self.updated_by, locker_fingerprint_id: self.locker_fingerprint_id, version: self.version, network_token_requestor_reference_id: self.network_token_requestor_reference_id, network_token_locker_id: self.network_token_locker_id, network_token_payment_method_data: self .network_token_payment_method_data .map(|val| val.into()), }) } async fn convert_back( state: &keymanager::KeyManagerState, item: Self::DstType, key: &Secret>, key_manager_identifier: keymanager::Identifier, ) -> CustomResult where Self: Sized, { async { Ok::>(Self { customer_id: item.customer_id, merchant_id: item.merchant_id, id: item.id, created_at: item.created_at, last_modified: item.last_modified, payment_method_type: item.payment_method_type_v2, payment_method_subtype: item.payment_method_subtype, payment_method_data: item .payment_method_data .async_lift(|inner| async { crypto_operation( state, type_name!(Self::DstType), CryptoOperation::DecryptOptional(inner), key_manager_identifier.clone(), key.peek(), ) .await .and_then(|val| val.try_into_optionaloperation()) }) .await?, locker_id: item.locker_id.map(VaultId::generate), last_used_at: item.last_used_at, connector_mandate_details: item.connector_mandate_details, customer_acceptance: item.customer_acceptance, status: item.status, network_transaction_id: item.network_transaction_id, client_secret: item.client_secret, payment_method_billing_address: item .payment_method_billing_address .async_lift(|inner| async { crypto_operation( state, type_name!(Self::DstType), CryptoOperation::DecryptOptional(inner), key_manager_identifier.clone(), key.peek(), ) .await .and_then(|val| val.try_into_optionaloperation()) }) .await?, updated_by: item.updated_by, locker_fingerprint_id: item.locker_fingerprint_id, version: item.version, network_token_requestor_reference_id: item.network_token_requestor_reference_id, network_token_locker_id: item.network_token_locker_id, network_token_payment_method_data: item .network_token_payment_method_data .async_lift(|inner| async { crypto_operation( state, type_name!(Self::DstType), CryptoOperation::DecryptOptional(inner), key_manager_identifier.clone(), key.peek(), ) .await .and_then(|val| val.try_into_optionaloperation()) }) .await?, }) } .await .change_context(ValidationError::InvalidValue { message: "Failed while decrypting payment method data".to_string(), }) } async fn construct_new(self) -> CustomResult { Ok(Self::NewDstType { customer_id: self.customer_id, merchant_id: self.merchant_id, id: self.id, created_at: self.created_at, last_modified: self.last_modified, payment_method_type_v2: self.payment_method_type, payment_method_subtype: self.payment_method_subtype, payment_method_data: self.payment_method_data.map(|val| val.into()), locker_id: self.locker_id.map(|id| id.get_string_repr().clone()), last_used_at: self.last_used_at, connector_mandate_details: self.connector_mandate_details, customer_acceptance: self.customer_acceptance, status: self.status, network_transaction_id: self.network_transaction_id, client_secret: self.client_secret, payment_method_billing_address: self .payment_method_billing_address .map(|val| val.into()), updated_by: self.updated_by, locker_fingerprint_id: self.locker_fingerprint_id, version: self.version, network_token_requestor_reference_id: self.network_token_requestor_reference_id, network_token_locker_id: self.network_token_locker_id, network_token_payment_method_data: self .network_token_payment_method_data .map(|val| val.into()), }) } }