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

feat(router): Add support for network token migration #6300

Open
wants to merge 18 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 8 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
12 changes: 11 additions & 1 deletion crates/api_models/src/events/payment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use crate::{
ListCountriesCurrenciesResponse, PaymentMethodCollectLinkRenderRequest,
PaymentMethodCollectLinkRequest, PaymentMethodCollectLinkResponse,
PaymentMethodDeleteResponse, PaymentMethodListRequest, PaymentMethodListResponse,
PaymentMethodResponse, PaymentMethodUpdate,
PaymentMethodMigrateResponse, PaymentMethodResponse, PaymentMethodUpdate,
},
payments::{
self, ExtendedCardInfoResponse, PaymentIdType, PaymentListConstraints,
Expand Down Expand Up @@ -196,6 +196,16 @@ impl ApiEventMetric for PaymentMethodResponse {
}
}

impl ApiEventMetric for PaymentMethodMigrateResponse {
fn get_api_event_type(&self) -> Option<ApiEventsType> {
Some(ApiEventsType::PaymentMethod {
payment_method_id: self.payment_method_response.payment_method_id.clone(),
payment_method: self.payment_method_response.payment_method,
payment_method_type: self.payment_method_response.payment_method_type,
})
}
}

impl ApiEventMetric for PaymentMethodUpdate {}

impl ApiEventMetric for DefaultPaymentMethod {
Expand Down
110 changes: 104 additions & 6 deletions crates/api_models/src/payment_methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,9 @@ pub struct PaymentMethodMigrate {
/// Card Details
pub card: Option<MigrateCardDetail>,

/// Network token details
pub network_token: Option<MigrateNetworkTokenDetail>,

/// You can specify up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. Metadata is useful for storing additional, structured information on an object.
pub metadata: Option<pii::SecretSerdeValue>,

Expand Down Expand Up @@ -276,6 +279,24 @@ pub struct PaymentMethodMigrate {
pub network_transaction_id: Option<String>,
}

#[derive(Debug, serde::Deserialize, serde::Serialize, ToSchema)]
pub struct PaymentMethodMigrateResponse {
//payment method response when payment method entry is created
pub payment_method_response: PaymentMethodResponse,

//card data migration status
pub card_migrated: Option<bool>,

//network token data migration status
pub network_token_migrated: Option<bool>,

//connector mandate details migration status
pub connector_mandate_details_migrated: Option<bool>,

//network transaction id migration status
pub network_transaction_id_migrated: Option<bool>,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct PaymentsMandateReference(
pub HashMap<id_type::MerchantConnectorAccountId, PaymentsMandateReferenceRecord>,
Expand Down Expand Up @@ -539,6 +560,53 @@ pub struct MigrateCardDetail {
pub card_type: Option<String>,
}

#[derive(Debug, serde::Deserialize, serde::Serialize, Clone, ToSchema)]
#[serde(deny_unknown_fields)]
pub struct MigrateNetworkTokenData {
/// Token Number
prasunna09 marked this conversation as resolved.
Show resolved Hide resolved
#[schema(value_type = String,example = "4111111145551142")]
pub network_token_number: masking::Secret<String>,
prasunna09 marked this conversation as resolved.
Show resolved Hide resolved

/// Token Expiry Month
prasunna09 marked this conversation as resolved.
Show resolved Hide resolved
#[schema(value_type = String,example = "10")]
pub network_token_exp_month: masking::Secret<String>,

/// Card Expiry Year
prasunna09 marked this conversation as resolved.
Show resolved Hide resolved
#[schema(value_type = String,example = "25")]
pub network_token_exp_year: masking::Secret<String>,

/// Card Holder Name
#[schema(value_type = String,example = "John Doe")]
pub card_holder_name: Option<masking::Secret<String>>,

/// Card Holder's Nick Name
#[schema(value_type = Option<String>,example = "John Doe")]
pub nick_name: Option<masking::Secret<String>>,

/// Card Issuing Country
pub card_issuing_country: Option<String>,

/// Card's Network
#[schema(value_type = Option<CardNetwork>)]
pub card_network: Option<api_enums::CardNetwork>,

/// Issuer Bank for Card
pub card_issuer: Option<String>,

/// Card Type
pub card_type: Option<String>,
}

#[derive(Debug, serde::Deserialize, serde::Serialize, Clone, ToSchema)]
#[serde(deny_unknown_fields)]
pub struct MigrateNetworkTokenDetail {
/// Network token details
pub network_token_data: MigrateNetworkTokenData,

/// Network token requestor reference id
pub network_token_requestor_ref_id: String,
}

#[cfg(all(
any(feature = "v1", feature = "v2"),
not(feature = "payment_methods_v2")
Expand Down Expand Up @@ -2091,6 +2159,10 @@ pub struct PaymentMethodRecord {
pub original_transaction_amount: Option<i64>,
pub original_transaction_currency: Option<common_enums::Currency>,
pub line_number: Option<i64>,
pub network_token_number: Option<masking::Secret<String>>,
pub network_token_expiry_month: Option<masking::Secret<String>>,
pub network_token_expiry_year: Option<masking::Secret<String>>,
pub network_token_requestor_ref_id: Option<String>,
}

#[derive(Debug, Default, serde::Serialize)]
Expand All @@ -2107,6 +2179,10 @@ pub struct PaymentMethodMigrationResponse {
#[serde(skip_serializing_if = "Option::is_none")]
pub migration_error: Option<String>,
pub card_number_masked: Option<masking::Secret<String>>,
pub card_migrated: Option<bool>,
pub network_token_migrated: Option<bool>,
pub connector_mandate_details_migrated: Option<bool>,
pub network_transaction_id_migrated: Option<bool>,
}

#[derive(Debug, Default, serde::Serialize)]
Expand All @@ -2116,8 +2192,10 @@ pub enum MigrationStatus {
Failed,
}

type PaymentMethodMigrationResponseType =
(Result<PaymentMethodResponse, String>, PaymentMethodRecord);
type PaymentMethodMigrationResponseType = (
Result<PaymentMethodMigrateResponse, String>,
PaymentMethodRecord,
);
#[cfg(all(
any(feature = "v2", feature = "v1"),
not(feature = "payment_methods_v2")
Expand All @@ -2126,14 +2204,18 @@ impl From<PaymentMethodMigrationResponseType> for PaymentMethodMigrationResponse
fn from((response, record): PaymentMethodMigrationResponseType) -> Self {
match response {
Ok(res) => Self {
payment_method_id: Some(res.payment_method_id),
payment_method: res.payment_method,
payment_method_type: res.payment_method_type,
customer_id: res.customer_id,
payment_method_id: Some(res.payment_method_response.payment_method_id),
payment_method: res.payment_method_response.payment_method,
payment_method_type: res.payment_method_response.payment_method_type,
customer_id: res.payment_method_response.customer_id,
migration_status: MigrationStatus::Success,
migration_error: None,
card_number_masked: Some(record.card_number_masked),
line_number: record.line_number,
card_migrated: res.card_migrated,
network_token_migrated: res.network_token_migrated,
connector_mandate_details_migrated: res.connector_mandate_details_migrated,
network_transaction_id_migrated: res.network_transaction_id_migrated,
},
Err(e) => Self {
customer_id: Some(record.customer_id),
Expand Down Expand Up @@ -2222,6 +2304,22 @@ impl
card_issuing_country: None,
nick_name: Some(record.nick_name.clone()),
}),
network_token: Some(MigrateNetworkTokenDetail {
network_token_data: MigrateNetworkTokenData {
network_token_number: record.network_token_number.unwrap_or_default(),
network_token_exp_month: record.network_token_expiry_month.unwrap_or_default(),
network_token_exp_year: record.network_token_expiry_year.unwrap_or_default(),
card_holder_name: record.name,
nick_name: Some(record.nick_name.clone()),
card_issuing_country: None,
card_network: None,
card_issuer: None,
card_type: None,
},
network_token_requestor_ref_id: record
.network_token_requestor_ref_id
.unwrap_or_default(),
}),
payment_method: record.payment_method,
payment_method_type: record.payment_method_type,
payment_method_issuer: None,
Expand Down
26 changes: 26 additions & 0 deletions crates/diesel_models/src/payment_method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,11 @@ pub enum PaymentMethodUpdate {
ConnectorMandateDetailsUpdate {
connector_mandate_details: Option<serde_json::Value>,
},
NetworkTokenDataUpdate {
network_token_requestor_reference_id: Option<String>,
network_token_locker_id: Option<String>,
network_token_payment_method_data: Option<Encryption>,
},
}

#[cfg(all(feature = "v2", feature = "payment_methods_v2"))]
Expand Down Expand Up @@ -589,6 +594,27 @@ impl From<PaymentMethodUpdate> for PaymentMethodUpdateInternal {
network_token_locker_id: None,
network_token_payment_method_data: None,
},
PaymentMethodUpdate::NetworkTokenDataUpdate {
network_token_requestor_reference_id,
network_token_locker_id,
network_token_payment_method_data,
} => Self {
metadata: None,
payment_method_data: None,
last_used_at: None,
status: None,
locker_id: None,
payment_method: None,
connector_mandate_details: None,
updated_by: None,
payment_method_issuer: None,
payment_method_type: None,
last_modified: common_utils::date_time::now(),
network_transaction_id: None,
network_token_requestor_reference_id,
network_token_locker_id,
network_token_payment_method_data,
},
}
}
}
Expand Down
Loading
Loading