mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-30 01:27:31 +08:00
477 lines
20 KiB
Rust
477 lines
20 KiB
Rust
#[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<Vec<storage_enums::Currency>>,
|
|
pub scheme: Option<String>,
|
|
pub token: Option<String>,
|
|
pub cardholder_name: Option<Secret<String>>,
|
|
pub issuer_name: Option<String>,
|
|
pub issuer_country: Option<String>,
|
|
pub payer_country: Option<Vec<String>>,
|
|
pub is_stored: Option<bool>,
|
|
pub swift_code: Option<String>,
|
|
pub direct_debit_token: Option<String>,
|
|
pub created_at: PrimitiveDateTime,
|
|
pub last_modified: PrimitiveDateTime,
|
|
pub payment_method: Option<storage_enums::PaymentMethod>,
|
|
pub payment_method_type: Option<storage_enums::PaymentMethodType>,
|
|
pub payment_method_issuer: Option<String>,
|
|
pub payment_method_issuer_code: Option<storage_enums::PaymentMethodIssuerCode>,
|
|
pub metadata: Option<pii::SecretSerdeValue>,
|
|
pub payment_method_data: OptionalEncryptableValue,
|
|
pub locker_id: Option<String>,
|
|
pub last_used_at: PrimitiveDateTime,
|
|
pub connector_mandate_details: Option<serde_json::Value>,
|
|
pub customer_acceptance: Option<pii::SecretSerdeValue>,
|
|
pub status: storage_enums::PaymentMethodStatus,
|
|
pub network_transaction_id: Option<String>,
|
|
pub client_secret: Option<String>,
|
|
pub payment_method_billing_address: OptionalEncryptableValue,
|
|
pub updated_by: Option<String>,
|
|
pub version: common_enums::ApiVersion,
|
|
pub network_token_requestor_reference_id: Option<String>,
|
|
pub network_token_locker_id: Option<String>,
|
|
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<storage_enums::PaymentMethod>,
|
|
pub payment_method_subtype: Option<storage_enums::PaymentMethodType>,
|
|
pub payment_method_data:
|
|
OptionalEncryptableJsonType<api_models::payment_methods::PaymentMethodsData>,
|
|
pub locker_id: Option<VaultId>,
|
|
pub last_used_at: PrimitiveDateTime,
|
|
pub connector_mandate_details: Option<diesel_models::PaymentsMandateReference>,
|
|
pub customer_acceptance: Option<pii::SecretSerdeValue>,
|
|
pub status: storage_enums::PaymentMethodStatus,
|
|
pub network_transaction_id: Option<String>,
|
|
pub client_secret: Option<String>,
|
|
pub payment_method_billing_address: OptionalEncryptableValue,
|
|
pub updated_by: Option<String>,
|
|
pub locker_fingerprint_id: Option<String>,
|
|
pub id: common_utils::id_type::GlobalPaymentMethodId,
|
|
pub version: common_enums::ApiVersion,
|
|
pub network_token_requestor_reference_id: Option<String>,
|
|
pub network_token_locker_id: Option<String>,
|
|
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<storage_enums::PaymentMethod> {
|
|
self.payment_method
|
|
}
|
|
|
|
#[cfg(all(feature = "v2", feature = "payment_methods_v2"))]
|
|
pub fn get_payment_method_type(&self) -> Option<storage_enums::PaymentMethod> {
|
|
self.payment_method_type
|
|
}
|
|
|
|
#[cfg(all(
|
|
any(feature = "v1", feature = "v2"),
|
|
not(feature = "payment_methods_v2")
|
|
))]
|
|
pub fn get_payment_method_subtype(&self) -> Option<storage_enums::PaymentMethodType> {
|
|
self.payment_method_type
|
|
}
|
|
|
|
#[cfg(all(feature = "v2", feature = "payment_methods_v2"))]
|
|
pub fn get_payment_method_subtype(&self) -> Option<storage_enums::PaymentMethodType> {
|
|
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<Self::DstType, ValidationError> {
|
|
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<Vec<u8>>,
|
|
key_manager_identifier: keymanager::Identifier,
|
|
) -> CustomResult<Self, ValidationError>
|
|
where
|
|
Self: Sized,
|
|
{
|
|
async {
|
|
Ok::<Self, error_stack::Report<common_utils::errors::CryptoError>>(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<Self::NewDstType, ValidationError> {
|
|
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<Self::DstType, ValidationError> {
|
|
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<Vec<u8>>,
|
|
key_manager_identifier: keymanager::Identifier,
|
|
) -> CustomResult<Self, ValidationError>
|
|
where
|
|
Self: Sized,
|
|
{
|
|
async {
|
|
Ok::<Self, error_stack::Report<common_utils::errors::CryptoError>>(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<Self::NewDstType, ValidationError> {
|
|
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()),
|
|
})
|
|
}
|
|
}
|