fix(netcetera): handle non-ascii characters for cardholdername, error message and send missing fields (#4755)

Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
This commit is contained in:
Sai Harsha Vardhan
2024-05-30 20:27:59 +05:30
committed by GitHub
parent 61e67e4272
commit 5d1900e1d9
5 changed files with 47 additions and 28 deletions

7
Cargo.lock generated
View File

@ -5750,6 +5750,7 @@ dependencies = [
"totp-rs", "totp-rs",
"tracing-futures", "tracing-futures",
"unicode-segmentation", "unicode-segmentation",
"unidecode",
"url", "url",
"utoipa", "utoipa",
"uuid", "uuid",
@ -7853,6 +7854,12 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e"
[[package]]
name = "unidecode"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "402bb19d8e03f1d1a7450e2bd613980869438e0666331be3e073089124aa1adc"
[[package]] [[package]]
name = "untrusted" name = "untrusted"
version = "0.7.1" version = "0.7.1"

View File

@ -128,6 +128,7 @@ actix-http = "3.6.0"
events = { version = "0.1.0", path = "../events" } events = { version = "0.1.0", path = "../events" }
totp-rs = { version = "5.5.1", features = ["gen_secret", "otpauth"]} totp-rs = { version = "5.5.1", features = ["gen_secret", "otpauth"]}
serde_repr = "0.1.19" serde_repr = "0.1.19"
unidecode = "0.3.0"
[build-dependencies] [build-dependencies]
router_env = { version = "0.1.0", path = "../router_env", default-features = false } router_env = { version = "0.1.0", path = "../router_env", default-features = false }

View File

@ -1,7 +1,9 @@
use std::collections::HashMap; use std::collections::HashMap;
use common_utils::pii::Email; use common_utils::pii::Email;
use masking::ExposeInterface;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use unidecode::unidecode;
use crate::{ use crate::{
connector::utils::{AddressDetailsData, PhoneDetailsData}, connector::utils::{AddressDetailsData, PhoneDetailsData},
@ -701,7 +703,13 @@ impl
.address .address
.as_ref() .as_ref()
.and_then(|add| add.city.clone()), .and_then(|add| add.city.clone()),
bill_addr_country: None, bill_addr_country: billing_address.address.as_ref().and_then(|add| {
add.country.map(|country| {
common_enums::Country::from_alpha2(country)
.to_numeric()
.to_string()
})
}),
bill_addr_line1: billing_address bill_addr_line1: billing_address
.address .address
.as_ref() .as_ref()
@ -739,15 +747,25 @@ impl
.clone() .clone()
.map(PhoneNumber::try_from) .map(PhoneNumber::try_from)
.transpose()?, .transpose()?,
cardholder_name: billing_address cardholder_name: billing_address.address.and_then(|address| {
.address address
.as_ref() .get_optional_full_name()
.and_then(|add| add.first_name.clone()), .map(|name| masking::Secret::new(unidecode(&name.expose())))
}),
ship_addr_city: shipping_address ship_addr_city: shipping_address
.as_ref() .as_ref()
.and_then(|shipping_add| shipping_add.address.as_ref()) .and_then(|shipping_add| shipping_add.address.as_ref())
.and_then(|add| add.city.clone()), .and_then(|add| add.city.clone()),
ship_addr_country: None, ship_addr_country: shipping_address
.as_ref()
.and_then(|shipping_add| shipping_add.address.as_ref())
.and_then(|add| {
add.country.map(|country| {
common_enums::Country::from_alpha2(country)
.to_numeric()
.to_string()
})
}),
ship_addr_line1: shipping_address ship_addr_line1: shipping_address
.as_ref() .as_ref()
.and_then(|shipping_add| shipping_add.address.as_ref()) .and_then(|shipping_add| shipping_add.address.as_ref())
@ -1313,7 +1331,7 @@ pub struct Browser {
/// - with message version = 2.1.0 and deviceChannel = 02 (BRW). /// - with message version = 2.1.0 and deviceChannel = 02 (BRW).
/// - with message version = 2.2.0 and deviceChannel = 02 (BRW) and browserJavascriptEnabled = true. /// - with message version = 2.2.0 and deviceChannel = 02 (BRW) and browserJavascriptEnabled = true.
#[serde(rename = "browserTZ")] #[serde(rename = "browserTZ")]
browser_tz: Option<u32>, browser_tz: Option<i32>,
/// Exact content of the HTTP user-agent header. The field is limited to maximum 2048 characters. If the total length of /// Exact content of the HTTP user-agent header. The field is limited to maximum 2048 characters. If the total length of
/// the User-Agent sent by the browser exceeds 2048 characters, the 3DS Server truncates the excess portion. /// the User-Agent sent by the browser exceeds 2048 characters, the 3DS Server truncates the excess portion.
@ -1364,7 +1382,7 @@ impl From<crate::types::BrowserInformation> for Browser {
browser_color_depth: value.color_depth.map(|cd| cd.to_string()), browser_color_depth: value.color_depth.map(|cd| cd.to_string()),
browser_screen_height: value.screen_height, browser_screen_height: value.screen_height,
browser_screen_width: value.screen_width, browser_screen_width: value.screen_width,
browser_tz: Some(1), browser_tz: value.time_zone,
browser_user_agent: value.user_agent, browser_user_agent: value.user_agent,
challenge_window_size: Some(ChallengeWindowSizeEnum::FullScreen), challenge_window_size: Some(ChallengeWindowSizeEnum::FullScreen),
browser_javascript_enabled: value.java_script_enabled, browser_javascript_enabled: value.java_script_enabled,

View File

@ -454,27 +454,12 @@ impl TryFrom<&NetceteraRouterData<&types::authentication::ConnectorAuthenticatio
item: &NetceteraRouterData<&types::authentication::ConnectorAuthenticationRouterData>, item: &NetceteraRouterData<&types::authentication::ConnectorAuthenticationRouterData>,
) -> Result<Self, Self::Error> { ) -> Result<Self, Self::Error> {
let now = common_utils::date_time::now(); let now = common_utils::date_time::now();
let three_ds_req_auth_timestamp = common_utils::date_time::format_date(
now,
common_utils::date_time::DateFormat::YYYYMMDDHHmm,
)
.change_context(errors::ConnectorError::RequestEncodingFailedWithReason(
"Failed to format Date".to_string(),
))?;
let request = item.router_data.request.clone(); let request = item.router_data.request.clone();
let pre_authn_data = request.pre_authentication_data.clone(); let pre_authn_data = request.pre_authentication_data.clone();
let three_ds_requestor = netcetera_types::ThreeDSRequestor { let three_ds_requestor = netcetera_types::ThreeDSRequestor {
three_ds_requestor_authentication_ind: three_ds_requestor_authentication_ind:
netcetera_types::ThreeDSRequestorAuthenticationIndicator::Payment, netcetera_types::ThreeDSRequestorAuthenticationIndicator::Payment,
three_ds_requestor_authentication_info: Some( three_ds_requestor_authentication_info: None,
netcetera_types::SingleOrListElement::new_single(
netcetera_types::ThreeDSRequestorAuthenticationInformation {
three_ds_req_auth_method: netcetera_types::ThreeDSReqAuthMethod::Guest,
three_ds_req_auth_timestamp,
three_ds_req_auth_data: None,
},
),
),
three_ds_requestor_challenge_ind: None, three_ds_requestor_challenge_ind: None,
three_ds_requestor_prior_authentication_info: None, three_ds_requestor_prior_authentication_info: None,
three_ds_requestor_dec_req_ind: None, three_ds_requestor_dec_req_ind: None,
@ -518,8 +503,8 @@ impl TryFrom<&NetceteraRouterData<&types::authentication::ConnectorAuthenticatio
), ),
)?, )?,
), ),
recurring_expiry: Some("20240401".to_string()), recurring_expiry: None,
recurring_frequency: Some(1), recurring_frequency: None,
trans_type: None, trans_type: None,
recurring_amount: None, recurring_amount: None,
recurring_currency: None, recurring_currency: None,
@ -558,7 +543,12 @@ impl TryFrom<&NetceteraRouterData<&types::authentication::ConnectorAuthenticatio
} }
api_models::payments::DeviceChannel::App => None, api_models::payments::DeviceChannel::App => None,
}; };
let sdk_information = request.sdk_information.map(netcetera_types::Sdk::from); let sdk_information = match request.device_channel {
api_models::payments::DeviceChannel::App => {
request.sdk_information.map(netcetera_types::Sdk::from)
}
api_models::payments::DeviceChannel::Browser => None,
};
let device_render_options = match request.device_channel { let device_render_options = match request.device_channel {
api_models::payments::DeviceChannel::App => { api_models::payments::DeviceChannel::App => {
Some(netcetera_types::DeviceRenderingOptionsSupported { Some(netcetera_types::DeviceRenderingOptionsSupported {

View File

@ -141,7 +141,10 @@ pub async fn update_trackers<F: Clone, Req>(
Err(error) => storage::AuthenticationUpdate::ErrorUpdate { Err(error) => storage::AuthenticationUpdate::ErrorUpdate {
connector_authentication_id: error.connector_transaction_id, connector_authentication_id: error.connector_transaction_id,
authentication_status: common_enums::AuthenticationStatus::Failed, authentication_status: common_enums::AuthenticationStatus::Failed,
error_message: Some(error.message), error_message: error
.reason
.map(|reason| format!("message: {}, reason: {}", error.message, reason))
.or(Some(error.message)),
error_code: Some(error.code), error_code: Some(error.code),
}, },
}; };