Skip to content

Commit

Permalink
feat(router): revert support for co-badged cards (#6142)
Browse files Browse the repository at this point in the history
  • Loading branch information
AkshayaFoiger committed Sep 27, 2024
1 parent 67d6d22 commit 70f4d4b
Show file tree
Hide file tree
Showing 12 changed files with 150 additions and 394 deletions.
1 change: 0 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

39 changes: 13 additions & 26 deletions crates/api_models/src/payments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ use cards::CardNumber;
use common_utils::{
consts::default_payments_list_limit,
crypto,
errors::ValidationError,
ext_traits::{ConfigExt, Encode, ValueExt},
hashing::HashedString,
id_type,
Expand Down Expand Up @@ -1397,23 +1396,8 @@ impl GetAddressFromPaymentMethodData for Card {
}

impl Card {
fn apply_additional_card_info(
&self,
additional_card_info: AdditionalCardInfo,
) -> Result<Self, error_stack::Report<ValidationError>> {
let card_network = self
.card_network
.clone()
.or(additional_card_info.card_network.clone())
.map(|network| match self.card_number.is_cobadged_card() {
Ok(true) => Ok(Some(network)),
Ok(false) => Ok(None),
Err(e) => Err(e),
})
.transpose()?
.flatten();

Ok(Self {
fn apply_additional_card_info(&self, additional_card_info: AdditionalCardInfo) -> Self {
Self {
card_number: self.card_number.clone(),
card_exp_month: self.card_exp_month.clone(),
card_exp_year: self.card_exp_year.clone(),
Expand All @@ -1423,15 +1407,18 @@ impl Card {
.card_issuer
.clone()
.or(additional_card_info.card_issuer),
card_network,
card_network: self
.card_network
.clone()
.or(additional_card_info.card_network),
card_type: self.card_type.clone().or(additional_card_info.card_type),
card_issuing_country: self
.card_issuing_country
.clone()
.or(additional_card_info.card_issuing_country),
bank_code: self.bank_code.clone().or(additional_card_info.bank_code),
nick_name: self.nick_name.clone(),
})
}
}
}

Expand Down Expand Up @@ -1871,16 +1858,16 @@ impl PaymentMethodData {
pub fn apply_additional_payment_data(
&self,
additional_payment_data: AdditionalPaymentData,
) -> Result<Self, error_stack::Report<ValidationError>> {
) -> Self {
if let AdditionalPaymentData::Card(additional_card_info) = additional_payment_data {
match self {
Self::Card(card) => Ok(Self::Card(
card.apply_additional_card_info(*additional_card_info)?,
)),
_ => Ok(self.to_owned()),
Self::Card(card) => {
Self::Card(card.apply_additional_card_info(*additional_card_info))
}
_ => self.to_owned(),
}
} else {
Ok(self.to_owned())
self.to_owned()
}
}

Expand Down
1 change: 0 additions & 1 deletion crates/cards/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ error-stack = "0.4.1"
serde = { version = "1.0.197", features = ["derive"] }
thiserror = "1.0.58"
time = "0.3.35"
regex = "1.10.4"

# First party crates
common_utils = { version = "0.1.0", path = "../common_utils" }
Expand Down
54 changes: 1 addition & 53 deletions crates/cards/src/validate.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
use std::{collections::HashMap, fmt, ops::Deref, str::FromStr};
use std::{fmt, ops::Deref, str::FromStr};

use common_utils::errors::ValidationError;
use error_stack::report;
use masking::{PeekInterface, Strategy, StrongSecret, WithType};
use regex::Regex;
use router_env::once_cell::sync::Lazy;
#[cfg(not(target_arch = "wasm32"))]
use router_env::{logger, which as router_env_which, Env};
use serde::{Deserialize, Deserializer, Serialize};
Expand Down Expand Up @@ -50,54 +46,6 @@ impl CardNumber {
.rev()
.collect::<String>()
}
pub fn is_cobadged_card(&self) -> Result<bool, error_stack::Report<ValidationError>> {
/// Regex to identify card networks
static CARD_NETWORK_REGEX: Lazy<HashMap<&str, Result<Regex, regex::Error>>> = Lazy::new(
|| {
let mut map = HashMap::new();
map.insert("Mastercard", Regex::new(r"^(5[1-5][0-9]{14}|2(2(2[1-9]|[3-9][0-9])|[3-6][0-9][0-9]|7([0-1][0-9]|20))[0-9]{12})$"));
map.insert("American Express", Regex::new(r"^3[47][0-9]{13}$"));
map.insert("Visa", Regex::new(r"^4[0-9]{12}(?:[0-9]{3})?$"));
map.insert("Discover", Regex::new(r"^65[4-9][0-9]{13}|64[4-9][0-9]{13}|6011[0-9]{12}|(622(?:12[6-9]|1[3-9][0-9]|[2-8][0-9][0-9]|9[01][0-9]|92[0-5])[0-9]{10})$"));
map.insert(
"Maestro",
Regex::new(r"^(5018|5081|5044|504681|504993|5020|502260|5038|603845|603123|6304|6759|676[1-3]|6220|504834|504817|504645|504775|600206|627741)"),
);
map.insert(
"RuPay",
Regex::new(r"^(508227|508[5-9]|603741|60698[5-9]|60699|607[0-8]|6079[0-7]|60798[0-4]|60800[1-9]|6080[1-9]|608[1-4]|608500|6521[5-9]|652[2-9]|6530|6531[0-4]|817290|817368|817378|353800)"),
);
map.insert("Diners Club", Regex::new(r"^(36|38|30[0-5])"));
map.insert(
"JCB",
Regex::new(r"^(3(?:088|096|112|158|337|5(?:2[89]|[3-8][0-9]))\d{12})$"),
);
map.insert("CarteBlanche", Regex::new(r"^389[0-9]{11}$"));
map.insert("Sodex", Regex::new(r"^(637513)"));
map.insert("BAJAJ", Regex::new(r"^(203040)"));
map
},
);
let mut no_of_supported_card_networks = 0;

let card_number_str = self.get_card_no();
for (_, regex) in CARD_NETWORK_REGEX.iter() {
let card_regex = match regex.as_ref() {
Ok(regex) => Ok(regex),
Err(_) => Err(report!(ValidationError::InvalidValue {
message: "Invalid regex expression".into(),
})),
}?;

if card_regex.is_match(&card_number_str) {
no_of_supported_card_networks += 1;
if no_of_supported_card_networks > 1 {
break;
}
}
}
Ok(no_of_supported_card_networks > 1)
}
}

impl FromStr for CardNumber {
Expand Down
64 changes: 4 additions & 60 deletions crates/router/src/connector/adyen/transformers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1112,38 +1112,6 @@ pub enum CardBrand {
Visa,
MC,
Amex,
Argencard,
Bcmc,
Bijcard,
Cabal,
Cartebancaire,
Codensa,
Cup,
Dankort,
Diners,
Discover,
Electron,
Elo,
Forbrugsforeningen,
Hiper,
Hipercard,
Jcb,
Karenmillen,
Laser,
Maestro,
Maestrouk,
Mcalphabankbonus,
Mir,
Naranja,
Oasis,
Rupay,
Shopping,
Solo,
Troy,
Uatp,
Visaalphabankbonus,
Visadankort,
Warehouse,
}

#[derive(Default, Debug, Serialize, Deserialize)]
Expand Down Expand Up @@ -1963,22 +1931,6 @@ impl<'a> TryFrom<&domain::GiftCardData> for AdyenPaymentMethod<'a> {
}
}

fn get_adyen_card_network(card_network: common_enums::CardNetwork) -> Option<CardBrand> {
match card_network {
common_enums::CardNetwork::Visa => Some(CardBrand::Visa),
common_enums::CardNetwork::Mastercard => Some(CardBrand::MC),
common_enums::CardNetwork::CartesBancaires => Some(CardBrand::Cartebancaire),
common_enums::CardNetwork::AmericanExpress => Some(CardBrand::Amex),
common_enums::CardNetwork::JCB => Some(CardBrand::Jcb),
common_enums::CardNetwork::DinersClub => Some(CardBrand::Diners),
common_enums::CardNetwork::Discover => Some(CardBrand::Discover),
common_enums::CardNetwork::UnionPay => Some(CardBrand::Cup),
common_enums::CardNetwork::RuPay => Some(CardBrand::Rupay),
common_enums::CardNetwork::Maestro => Some(CardBrand::Maestro),
common_enums::CardNetwork::Interac => None,
}
}

impl<'a> TryFrom<(&domain::Card, Option<Secret<String>>)> for AdyenPaymentMethod<'a> {
type Error = Error;
fn try_from(
Expand All @@ -1991,7 +1943,7 @@ impl<'a> TryFrom<(&domain::Card, Option<Secret<String>>)> for AdyenPaymentMethod
expiry_year: card.get_expiry_year_4_digit(),
cvc: Some(card.card_cvc.clone()),
holder_name: card_holder_name,
brand: card.card_network.clone().and_then(get_adyen_card_network),
brand: None,
network_payment_reference: None,
};
Ok(AdyenPaymentMethod::AdyenCard(Box::new(adyen_card)))
Expand Down Expand Up @@ -2046,11 +1998,7 @@ impl TryFrom<&utils::CardIssuer> for CardBrand {
utils::CardIssuer::AmericanExpress => Ok(Self::Amex),
utils::CardIssuer::Master => Ok(Self::MC),
utils::CardIssuer::Visa => Ok(Self::Visa),
utils::CardIssuer::Maestro => Ok(Self::Maestro),
utils::CardIssuer::Discover => Ok(Self::Discover),
utils::CardIssuer::DinersClub => Ok(Self::Diners),
utils::CardIssuer::JCB => Ok(Self::Jcb),
utils::CardIssuer::CarteBlanche => Ok(Self::Cartebancaire),
_ => Err(errors::ConnectorError::NotImplemented("CardBrand".to_string()).into()),
}
}
}
Expand Down Expand Up @@ -2581,12 +2529,8 @@ impl<'a>
payments::MandateReferenceId::NetworkMandateId(network_mandate_id) => {
match item.router_data.request.payment_method_data {
domain::PaymentMethodData::Card(ref card) => {
let brand = match card.card_network.clone().and_then(get_adyen_card_network)
{
Some(card_network) => card_network,
None => CardBrand::try_from(&card.get_card_issuer()?)?,
};

let card_issuer = card.get_card_issuer()?;
let brand = CardBrand::try_from(&card_issuer)?;
let card_holder_name = item.router_data.get_optional_billing_full_name();
let adyen_card = AdyenCard {
payment_type: PaymentType::Scheme,
Expand Down
23 changes: 4 additions & 19 deletions crates/router/src/connector/bankofamerica/transformers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -535,22 +535,6 @@ impl From<CardIssuer> for String {
}
}

fn get_boa_card_type(card_network: common_enums::CardNetwork) -> Option<&'static str> {
match card_network {
common_enums::CardNetwork::Visa => Some("001"),
common_enums::CardNetwork::Mastercard => Some("002"),
common_enums::CardNetwork::AmericanExpress => Some("003"),
common_enums::CardNetwork::JCB => Some("007"),
common_enums::CardNetwork::DinersClub => Some("005"),
common_enums::CardNetwork::Discover => Some("004"),
common_enums::CardNetwork::CartesBancaires => Some("006"),
common_enums::CardNetwork::UnionPay => Some("062"),
//"042" is the type code for Masetro Cards(International). For Maestro Cards(UK-Domestic) the mapping should be "024"
common_enums::CardNetwork::Maestro => Some("042"),
common_enums::CardNetwork::Interac | common_enums::CardNetwork::RuPay => None,
}
}

#[derive(Debug, Serialize)]
pub enum PaymentSolution {
ApplePay,
Expand Down Expand Up @@ -2434,9 +2418,10 @@ impl TryFrom<&domain::Card> for PaymentInformation {
type Error = error_stack::Report<errors::ConnectorError>;

fn try_from(ccard: &domain::Card) -> Result<Self, Self::Error> {
let card_type = match ccard.card_network.clone().and_then(get_boa_card_type) {
Some(card_network) => Some(card_network.to_string()),
None => ccard.get_card_issuer().ok().map(String::from),
let card_issuer = ccard.get_card_issuer();
let card_type = match card_issuer {
Ok(issuer) => Some(String::from(issuer)),
Err(_) => None,
};
Ok(Self::Cards(Box::new(CardPaymentInformation {
card: Card {
Expand Down
Loading

0 comments on commit 70f4d4b

Please sign in to comment.