Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(payment_methods_v2): refactor network tokenization flow for v2 #7309

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions crates/hyperswitch_domain_models/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ pub mod router_request_types;
pub mod router_response_types;
pub mod type_encryption;
pub mod types;
#[cfg(all(feature = "v2", feature = "payment_methods_v2"))]
pub mod vault;

#[cfg(not(feature = "payouts"))]
pub trait PayoutAttemptInterface {}
Expand Down
215 changes: 0 additions & 215 deletions crates/hyperswitch_domain_models/src/network_tokenization.rs
Original file line number Diff line number Diff line change
@@ -1,225 +1,10 @@
use std::fmt::Debug;

use api_models::enums as api_enums;
#[cfg(all(
any(feature = "v1", feature = "v2"),
not(feature = "payment_methods_v2")
))]
use cards::CardNumber;
#[cfg(all(feature = "v2", feature = "payment_methods_v2"))]
use cards::{CardNumber, NetworkToken};
use common_utils::id_type;
use masking::Secret;
use serde::{Deserialize, Serialize};

#[cfg(all(
any(feature = "v1", feature = "v2"),
not(feature = "payment_methods_v2")
))]
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CardData {
pub card_number: CardNumber,
pub exp_month: Secret<String>,
pub exp_year: Secret<String>,
pub card_security_code: Secret<String>,
}

#[cfg(all(feature = "v2", feature = "payment_methods_v2"))]
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CardData {
pub card_number: CardNumber,
pub exp_month: Secret<String>,
pub exp_year: Secret<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub card_security_code: Option<Secret<String>>,
}

#[cfg(all(
any(feature = "v1", feature = "v2"),
not(feature = "payment_methods_v2")
))]
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct OrderData {
pub consent_id: String,
pub customer_id: id_type::CustomerId,
}

#[cfg(all(feature = "v2", feature = "payment_methods_v2"))]
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct OrderData {
pub consent_id: String,
pub customer_id: id_type::GlobalCustomerId,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ApiPayload {
pub service: String,
pub card_data: Secret<String>, //encrypted card data
pub order_data: OrderData,
pub key_id: String,
pub should_send_token: bool,
}

#[derive(Debug, Deserialize, Eq, PartialEq)]
pub struct CardNetworkTokenResponse {
pub payload: Secret<String>, //encrypted payload
}

#[cfg(all(
any(feature = "v1", feature = "v2"),
not(feature = "payment_methods_v2")
))]
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CardNetworkTokenResponsePayload {
pub card_brand: api_enums::CardNetwork,
pub card_fingerprint: Option<Secret<String>>,
pub card_reference: String,
pub correlation_id: String,
pub customer_id: String,
pub par: String,
pub token: CardNumber,
pub token_expiry_month: Secret<String>,
pub token_expiry_year: Secret<String>,
pub token_isin: String,
pub token_last_four: String,
pub token_status: String,
}

#[cfg(all(feature = "v2", feature = "payment_methods_v2"))]
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GenerateNetworkTokenResponsePayload {
pub card_brand: api_enums::CardNetwork,
pub card_fingerprint: Option<Secret<String>>,
pub card_reference: String,
pub correlation_id: String,
pub customer_id: String,
pub par: String,
pub token: NetworkToken,
pub token_expiry_month: Secret<String>,
pub token_expiry_year: Secret<String>,
pub token_isin: String,
pub token_last_four: String,
pub token_status: String,
}

#[cfg(all(
any(feature = "v1", feature = "v2"),
not(feature = "payment_methods_v2")
))]
#[derive(Debug, Serialize)]
pub struct GetCardToken {
pub card_reference: String,
pub customer_id: id_type::CustomerId,
}

#[cfg(all(feature = "v2", feature = "payment_methods_v2"))]
#[derive(Debug, Serialize)]
pub struct GetCardToken {
pub card_reference: String,
pub customer_id: id_type::GlobalCustomerId,
}
#[derive(Debug, Deserialize)]
pub struct AuthenticationDetails {
pub cryptogram: Secret<String>,
pub token: CardNumber, //network token
}

#[derive(Debug, Serialize, Deserialize)]
pub struct TokenDetails {
pub exp_month: Secret<String>,
pub exp_year: Secret<String>,
}

#[derive(Debug, Deserialize)]
pub struct TokenResponse {
pub authentication_details: AuthenticationDetails,
pub network: api_enums::CardNetwork,
pub token_details: TokenDetails,
}

#[cfg(all(
any(feature = "v1", feature = "v2"),
not(feature = "payment_methods_v2")
))]
#[derive(Debug, Serialize, Deserialize)]
pub struct DeleteCardToken {
pub card_reference: String, //network token requestor ref id
pub customer_id: id_type::CustomerId,
}

#[cfg(all(feature = "v2", feature = "payment_methods_v2"))]
#[derive(Debug, Serialize, Deserialize)]
pub struct DeleteCardToken {
pub card_reference: String, //network token requestor ref id
pub customer_id: id_type::GlobalCustomerId,
}

#[derive(Debug, Deserialize, Eq, PartialEq)]
#[serde(rename_all = "UPPERCASE")]
pub enum DeleteNetworkTokenStatus {
Success,
}

#[derive(Debug, Deserialize, Eq, PartialEq)]
pub struct NetworkTokenErrorInfo {
pub code: String,
pub developer_message: String,
}

#[derive(Debug, Deserialize, Eq, PartialEq)]
pub struct NetworkTokenErrorResponse {
pub error_message: String,
pub error_info: NetworkTokenErrorInfo,
}

#[derive(Debug, Deserialize, Eq, PartialEq)]
pub struct DeleteNetworkTokenResponse {
pub status: DeleteNetworkTokenStatus,
}

#[cfg(all(
any(feature = "v1", feature = "v2"),
not(feature = "payment_methods_v2")
))]
#[derive(Debug, Serialize, Deserialize)]
pub struct CheckTokenStatus {
pub card_reference: String,
pub customer_id: id_type::CustomerId,
}

#[cfg(all(feature = "v2", feature = "payment_methods_v2"))]
#[derive(Debug, Serialize, Deserialize)]
pub struct CheckTokenStatus {
pub card_reference: String,
pub customer_id: id_type::GlobalCustomerId,
}

#[derive(Debug, Deserialize)]
#[serde(rename_all = "UPPERCASE")]
pub enum TokenStatus {
Active,
Inactive,
}

#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CheckTokenStatusResponsePayload {
pub token_expiry_month: Secret<String>,
pub token_expiry_year: Secret<String>,
pub token_status: TokenStatus,
}

#[derive(Debug, Deserialize)]
pub struct CheckTokenStatusResponse {
pub payload: CheckTokenStatusResponsePayload,
}

#[cfg(all(
any(feature = "v1", feature = "v2"),
Expand Down
56 changes: 56 additions & 0 deletions crates/hyperswitch_domain_models/src/vault.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
use std::fmt::Debug;

use api_models::payment_methods;
use serde::{Deserialize, Serialize};

use crate::payment_method_data;

#[derive(Debug, Deserialize, Serialize, Clone)]
pub enum PaymentMethodVaultingData {
Card(payment_methods::CardDetail),
NetworkToken(payment_method_data::NetworkTokenDetails),
}

impl PaymentMethodVaultingData {
pub fn get_card(&self) -> Option<&payment_methods::CardDetail> {
match self {
Self::Card(card) => Some(card),
_ => None,
}
}
pub fn get_payment_methods_data(&self) -> payment_method_data::PaymentMethodsData {
match self {
Self::Card(card) => payment_method_data::PaymentMethodsData::Card(
payment_method_data::CardDetailsPaymentMethod::from(card.clone()),
),
Self::NetworkToken(network_token) => {
payment_method_data::PaymentMethodsData::NetworkToken(
payment_method_data::NetworkTokenDetailsPaymentMethod::from(
network_token.clone(),
),
)
}
}
}
}

pub trait VaultingDataInterface {
fn get_vaulting_data_key(&self) -> String;
}

impl VaultingDataInterface for PaymentMethodVaultingData {
fn get_vaulting_data_key(&self) -> String {
match &self {
Self::Card(card) => card.card_number.to_string(),
Self::NetworkToken(network_token) => network_token.network_token.to_string(),
}
}
}

impl From<payment_methods::PaymentMethodCreateData> for PaymentMethodVaultingData {
fn from(item: payment_methods::PaymentMethodCreateData) -> Self {
match item {
payment_methods::PaymentMethodCreateData::Card(card) => Self::Card(card),
}
}
}
6 changes: 6 additions & 0 deletions crates/router/src/core/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -444,4 +444,10 @@ pub enum NetworkTokenizationError {
NetworkTokenizationServiceNotConfigured,
#[error("Failed while calling Network Token Service API")]
ApiError,
#[error("Network Tokenization is not enabled for profile")]
NetworkTokenizationNotEnabledForProfile,
#[error("Network Tokenization is not supported for {message}")]
NotSupported { message: String },
#[error("Failed to encrypt the NetworkToken payment method details")]
NetworkTokenDetailsEncryptionFailed,
}
Loading
Loading