Skip to content

Commit 5628985

Browse files
authored
feat(router): add card_info in payment_attempt table if not provided in request (#1538)
Co-authored-by: Sahkal Poddar <[email protected]>
1 parent cf7b672 commit 5628985

File tree

23 files changed

+230
-46
lines changed

23 files changed

+230
-46
lines changed

crates/api_models/src/payments.rs

Lines changed: 12 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,14 @@ pub struct Card {
551551
#[schema(value_type = Option<CardNetwork>, example = "Visa")]
552552
pub card_network: Option<api_enums::CardNetwork>,
553553

554+
#[schema(example = "CREDIT")]
555+
pub card_type: Option<String>,
556+
557+
#[schema(example = "INDIA")]
558+
pub card_issuing_country: Option<String>,
559+
560+
#[schema(example = "JP_AMEX")]
561+
pub bank_code: Option<String>,
554562
/// The card holder's nick name
555563
#[schema(value_type = Option<String>, example = "John Test")]
556564
pub nick_name: Option<Secret<String>>,
@@ -663,7 +671,10 @@ pub enum PaymentMethodData {
663671
pub enum AdditionalPaymentData {
664672
Card {
665673
card_issuer: Option<String>,
666-
card_network: Option<String>,
674+
card_network: Option<api_enums::CardNetwork>,
675+
card_type: Option<String>,
676+
card_issuing_country: Option<String>,
677+
bank_code: Option<String>,
667678
},
668679
BankRedirect {
669680
bank_name: Option<api_enums::BankNames>,
@@ -678,37 +689,6 @@ pub enum AdditionalPaymentData {
678689
Upi {},
679690
}
680691

681-
impl From<&PaymentMethodData> for AdditionalPaymentData {
682-
fn from(pm_data: &PaymentMethodData) -> Self {
683-
match pm_data {
684-
PaymentMethodData::Card(card_data) => Self::Card {
685-
card_issuer: card_data.card_issuer.to_owned(),
686-
card_network: card_data
687-
.card_network
688-
.as_ref()
689-
.map(|card_network| card_network.to_string()),
690-
},
691-
PaymentMethodData::BankRedirect(bank_redirect_data) => match bank_redirect_data {
692-
BankRedirectData::Eps { bank_name, .. } => Self::BankRedirect {
693-
bank_name: bank_name.to_owned(),
694-
},
695-
BankRedirectData::Ideal { bank_name, .. } => Self::BankRedirect {
696-
bank_name: bank_name.to_owned(),
697-
},
698-
_ => Self::BankRedirect { bank_name: None },
699-
},
700-
PaymentMethodData::Wallet(_) => Self::Wallet {},
701-
PaymentMethodData::PayLater(_) => Self::PayLater {},
702-
PaymentMethodData::BankTransfer(_) => Self::BankTransfer {},
703-
PaymentMethodData::Crypto(_) => Self::Crypto {},
704-
PaymentMethodData::BankDebit(_) => Self::BankDebit {},
705-
PaymentMethodData::MandatePayment => Self::MandatePayment {},
706-
PaymentMethodData::Reward(_) => Self::Reward {},
707-
PaymentMethodData::Upi(_) => Self::Upi {},
708-
}
709-
}
710-
}
711-
712692
#[derive(Debug, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize, ToSchema)]
713693
#[serde(rename_all = "snake_case")]
714694
pub enum BankRedirectData {

crates/cards/src/validate.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::{fmt, ops::Deref, str::FromStr};
22

3-
use masking::{Strategy, StrongSecret, WithType};
3+
use masking::{PeekInterface, Strategy, StrongSecret, WithType};
44
use serde::{Deserialize, Deserializer, Serialize};
55
use thiserror::Error;
66

@@ -18,6 +18,12 @@ impl From<core::convert::Infallible> for CCValError {
1818
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize)]
1919
pub struct CardNumber(StrongSecret<String, CardNumberStrategy>);
2020

21+
impl CardNumber {
22+
pub fn get_card_isin(self) -> String {
23+
self.0.peek().chars().take(6).collect::<String>()
24+
}
25+
}
26+
2127
impl FromStr for CardNumber {
2228
type Err = CCValError;
2329

crates/router/src/compatibility/stripe/payment_intents/types.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,9 @@ impl From<StripeCard> for payments::Card {
9898
card_cvc: card.cvc,
9999
card_issuer: None,
100100
card_network: None,
101+
bank_code: None,
102+
card_issuing_country: None,
103+
card_type: None,
101104
nick_name: None,
102105
}
103106
}

crates/router/src/compatibility/stripe/setup_intents/types.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ impl From<StripeCard> for payments::Card {
8989
card_cvc: card.cvc,
9090
card_issuer: None,
9191
card_network: None,
92+
bank_code: None,
93+
card_issuing_country: None,
94+
card_type: None,
9295
nick_name: None,
9396
}
9497
}

crates/router/src/core/payment_methods/vault.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,9 @@ impl Vaultable for api::Card {
106106
card_cvc: value2.card_security_code.unwrap_or_default().into(),
107107
card_issuer: None,
108108
card_network: None,
109+
bank_code: None,
110+
card_issuing_country: None,
111+
card_type: None,
109112
nick_name: value1.nickname.map(masking::Secret::new),
110113
};
111114

crates/router/src/core/payments/helpers.rs

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2449,3 +2449,93 @@ mod test {
24492449
);
24502450
}
24512451
}
2452+
2453+
pub async fn get_additional_payment_data(
2454+
pm_data: &api_models::payments::PaymentMethodData,
2455+
db: &dyn StorageInterface,
2456+
) -> api_models::payments::AdditionalPaymentData {
2457+
match pm_data {
2458+
api_models::payments::PaymentMethodData::Card(card_data) => {
2459+
if card_data.card_issuer.is_some()
2460+
&& card_data.card_network.is_some()
2461+
&& card_data.card_type.is_some()
2462+
&& card_data.card_issuing_country.is_some()
2463+
&& card_data.bank_code.is_some()
2464+
{
2465+
api_models::payments::AdditionalPaymentData::Card {
2466+
card_issuer: card_data.card_issuer.to_owned(),
2467+
card_network: card_data.card_network.clone(),
2468+
card_type: card_data.card_type.to_owned(),
2469+
card_issuing_country: card_data.card_issuing_country.to_owned(),
2470+
bank_code: card_data.bank_code.to_owned(),
2471+
}
2472+
} else {
2473+
let card_number = card_data.clone().card_number;
2474+
let card_info = db
2475+
.get_card_info(&card_number.get_card_isin())
2476+
.await
2477+
.map_err(|error| services::logger::warn!(card_info_error=?error))
2478+
.ok()
2479+
.flatten()
2480+
.map(
2481+
|card_info| api_models::payments::AdditionalPaymentData::Card {
2482+
card_issuer: card_info.card_issuer,
2483+
card_network: card_info
2484+
.card_network
2485+
.clone()
2486+
.map(|network| network.foreign_into()),
2487+
bank_code: card_info.bank_code,
2488+
card_type: card_info.card_type,
2489+
card_issuing_country: card_info.card_issuing_country,
2490+
},
2491+
);
2492+
card_info.unwrap_or(api_models::payments::AdditionalPaymentData::Card {
2493+
card_issuer: None,
2494+
card_network: None,
2495+
bank_code: None,
2496+
card_type: None,
2497+
card_issuing_country: None,
2498+
})
2499+
}
2500+
}
2501+
api_models::payments::PaymentMethodData::BankRedirect(bank_redirect_data) => {
2502+
match bank_redirect_data {
2503+
api_models::payments::BankRedirectData::Eps { bank_name, .. } => {
2504+
api_models::payments::AdditionalPaymentData::BankRedirect {
2505+
bank_name: bank_name.to_owned(),
2506+
}
2507+
}
2508+
api_models::payments::BankRedirectData::Ideal { bank_name, .. } => {
2509+
api_models::payments::AdditionalPaymentData::BankRedirect {
2510+
bank_name: bank_name.to_owned(),
2511+
}
2512+
}
2513+
_ => api_models::payments::AdditionalPaymentData::BankRedirect { bank_name: None },
2514+
}
2515+
}
2516+
api_models::payments::PaymentMethodData::Wallet(_) => {
2517+
api_models::payments::AdditionalPaymentData::Wallet {}
2518+
}
2519+
api_models::payments::PaymentMethodData::PayLater(_) => {
2520+
api_models::payments::AdditionalPaymentData::PayLater {}
2521+
}
2522+
api_models::payments::PaymentMethodData::BankTransfer(_) => {
2523+
api_models::payments::AdditionalPaymentData::BankTransfer {}
2524+
}
2525+
api_models::payments::PaymentMethodData::Crypto(_) => {
2526+
api_models::payments::AdditionalPaymentData::Crypto {}
2527+
}
2528+
api_models::payments::PaymentMethodData::BankDebit(_) => {
2529+
api_models::payments::AdditionalPaymentData::BankDebit {}
2530+
}
2531+
api_models::payments::PaymentMethodData::MandatePayment => {
2532+
api_models::payments::AdditionalPaymentData::MandatePayment {}
2533+
}
2534+
api_models::payments::PaymentMethodData::Reward(_) => {
2535+
api_models::payments::AdditionalPaymentData::Reward {}
2536+
}
2537+
api_models::payments::PaymentMethodData::Upi(_) => {
2538+
api_models::payments::AdditionalPaymentData::Upi {}
2539+
}
2540+
}
2541+
}

crates/router/src/core/payments/operations/payment_confirm.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,10 @@ impl<F: Clone> UpdateTracker<F, PaymentData<F>, api::PaymentsRequest> for Paymen
397397
let additional_pm_data = payment_data
398398
.payment_method_data
399399
.as_ref()
400-
.map(api_models::payments::AdditionalPaymentData::from)
400+
.async_map(|payment_method_data| async {
401+
helpers::get_additional_payment_data(payment_method_data, db).await
402+
})
403+
.await
401404
.as_ref()
402405
.map(Encode::<api_models::payments::AdditionalPaymentData>::encode_to_value)
403406
.transpose()

crates/router/src/core/payments/operations/payment_create.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa
5555
let ephemeral_key = Self::get_ephemeral_key(request, state, merchant_account).await;
5656
let merchant_id = &merchant_account.merchant_id;
5757
let storage_scheme = merchant_account.storage_scheme;
58-
5958
let (payment_intent, payment_attempt, connector_response);
6059

6160
let money @ (amount, currency) = payments_create_request_validation(request)?;
@@ -116,7 +115,9 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa
116115
payment_method_type,
117116
request,
118117
browser_info,
119-
)?,
118+
db,
119+
)
120+
.await?,
120121
storage_scheme,
121122
)
122123
.await
@@ -486,14 +487,16 @@ impl<F: Send + Clone> ValidateRequest<F, api::PaymentsRequest> for PaymentCreate
486487

487488
impl PaymentCreate {
488489
#[instrument(skip_all)]
489-
fn make_payment_attempt(
490+
#[allow(clippy::too_many_arguments)]
491+
pub async fn make_payment_attempt(
490492
payment_id: &str,
491493
merchant_id: &str,
492494
money: (api::Amount, enums::Currency),
493495
payment_method: Option<enums::PaymentMethod>,
494496
payment_method_type: Option<enums::PaymentMethodType>,
495497
request: &api::PaymentsRequest,
496498
browser_info: Option<serde_json::Value>,
499+
db: &dyn StorageInterface,
497500
) -> RouterResult<storage::PaymentAttemptNew> {
498501
let created_at @ modified_at @ last_synced = Some(common_utils::date_time::now());
499502
let status =
@@ -503,7 +506,10 @@ impl PaymentCreate {
503506
let additional_pm_data = request
504507
.payment_method_data
505508
.as_ref()
506-
.map(api_models::payments::AdditionalPaymentData::from)
509+
.async_map(|payment_method_data| async {
510+
helpers::get_additional_payment_data(payment_method_data, db).await
511+
})
512+
.await
507513
.as_ref()
508514
.map(Encode::<api_models::payments::AdditionalPaymentData>::encode_to_value)
509515
.transpose()

crates/router/src/core/payments/operations/payment_update.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,10 @@ impl<F: Clone> UpdateTracker<F, PaymentData<F>, api::PaymentsRequest> for Paymen
429429
let additional_pm_data = payment_data
430430
.payment_method_data
431431
.as_ref()
432-
.map(api_models::payments::AdditionalPaymentData::from)
432+
.async_map(|payment_method_data| async {
433+
helpers::get_additional_payment_data(payment_method_data, db).await
434+
})
435+
.await
433436
.as_ref()
434437
.map(Encode::<api_models::payments::AdditionalPaymentData>::encode_to_value)
435438
.transpose()

crates/router/src/types/api/payments.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,9 @@ mod payments_test {
233233
card_cvc: "123".to_string().into(),
234234
card_issuer: Some("HDFC".to_string()),
235235
card_network: Some(api_models::enums::CardNetwork::Visa),
236+
bank_code: None,
237+
card_issuing_country: None,
238+
card_type: None,
236239
nick_name: Some(masking::Secret::new("nick_name".into())),
237240
}
238241
}

0 commit comments

Comments
 (0)