Skip to content

Commit 84aa7e6

Browse files
Sayak BhattacharyaSayak Bhattacharya
authored andcommitted
fix: added checks for billing address fields
1 parent 2bdcaa6 commit 84aa7e6

File tree

6 files changed

+300
-31
lines changed

6 files changed

+300
-31
lines changed

crates/hyperswitch_connectors/src/connectors/nexixpay/transformers.rs

Lines changed: 276 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ use crate::{
4242
};
4343

4444
const MAX_ORDER_ID_LENGTH: usize = 18;
45+
const MAX_CARD_HOLDER_LENGTH: usize = 255;
46+
const MAX_BILLING_ADDRESS_NAME_LENGTH: usize = 50;
47+
const MAX_BILLING_ADDRESS_STREET_LENGTH: usize = 50;
48+
const MAX_BILLING_ADDRESS_CITY_LENGTH: usize = 40;
49+
const MAX_BILLING_ADDRESS_POST_CODE_LENGTH: usize = 16;
50+
const MAX_BILLING_ADDRESS_COUNTRY_LENGTH: usize = 3;
4551

4652
fn get_random_string() -> String {
4753
Alphanumeric.sample_string(&mut rand::thread_rng(), MAX_ORDER_ID_LENGTH)
@@ -506,16 +512,80 @@ impl TryFrom<&NexixpayRouterData<&PaymentsAuthorizeRouterData>> for NexixpayPaym
506512
(None, Some(line2)) => Some(line2),
507513
(None, None) => None,
508514
};
515+
509516
let billing_address = item
510517
.router_data
511518
.get_optional_billing()
512-
.map(|_| BillingAddress {
513-
name: item.router_data.get_optional_billing_full_name(),
514-
street: billing_address_street,
515-
city: item.router_data.get_optional_billing_city(),
516-
post_code: item.router_data.get_optional_billing_zip(),
517-
country: item.router_data.get_optional_billing_country(),
518-
});
519+
.map(|_| {
520+
let name = item.router_data.get_optional_billing_full_name();
521+
if let Some(ref val) = name {
522+
if val.clone().expose().len() > MAX_BILLING_ADDRESS_NAME_LENGTH {
523+
return Err(error_stack::Report::from(
524+
errors::ConnectorError::MaxFieldLengthViolated {
525+
field_name: "Billing Name".to_string(),
526+
connector: "Nexixpay".to_string(),
527+
},
528+
));
529+
}
530+
}
531+
532+
if let Some(ref val) = billing_address_street {
533+
if val.clone().expose().len() > MAX_BILLING_ADDRESS_STREET_LENGTH {
534+
return Err(error_stack::Report::from(
535+
errors::ConnectorError::MaxFieldLengthViolated {
536+
field_name: "Billing Street".to_string(),
537+
connector: "Nexixpay".to_string(),
538+
},
539+
));
540+
}
541+
}
542+
543+
let city = item.router_data.get_optional_billing_city();
544+
if let Some(ref val) = city {
545+
if val.len() > MAX_BILLING_ADDRESS_CITY_LENGTH {
546+
return Err(error_stack::Report::from(
547+
errors::ConnectorError::MaxFieldLengthViolated {
548+
field_name: "Billing City".to_string(),
549+
connector: "Nexixpay".to_string(),
550+
},
551+
));
552+
}
553+
}
554+
555+
let post_code = item.router_data.get_optional_billing_zip();
556+
if let Some(ref val) = post_code {
557+
if val.clone().expose().len() > MAX_BILLING_ADDRESS_POST_CODE_LENGTH {
558+
return Err(error_stack::Report::from(
559+
errors::ConnectorError::MaxFieldLengthViolated {
560+
field_name: "Billing Postal Code".to_string(),
561+
connector: "Nexixpay".to_string(),
562+
},
563+
));
564+
}
565+
}
566+
567+
let country = item.router_data.get_optional_billing_country();
568+
if let Some(ref val) = country {
569+
if val.to_string().len() > MAX_BILLING_ADDRESS_COUNTRY_LENGTH {
570+
return Err(error_stack::Report::from(
571+
errors::ConnectorError::MaxFieldLengthViolated {
572+
field_name: "Billing Country".to_string(),
573+
connector: "Nexixpay".to_string(),
574+
},
575+
));
576+
}
577+
}
578+
579+
Ok(BillingAddress {
580+
name,
581+
street: billing_address_street,
582+
city,
583+
post_code,
584+
country,
585+
})
586+
})
587+
.transpose()?;
588+
519589
let shipping_address_street = match (
520590
item.router_data.get_optional_shipping_line1(),
521591
item.router_data.get_optional_shipping_line2(),
@@ -533,23 +603,85 @@ impl TryFrom<&NexixpayRouterData<&PaymentsAuthorizeRouterData>> for NexixpayPaym
533603
let shipping_address = item
534604
.router_data
535605
.get_optional_shipping()
536-
.map(|_| ShippingAddress {
537-
name: item.router_data.get_optional_shipping_full_name(),
538-
street: shipping_address_street,
539-
city: item.router_data.get_optional_shipping_city(),
540-
post_code: item.router_data.get_optional_shipping_zip(),
541-
country: item.router_data.get_optional_shipping_country(),
542-
});
606+
.map(|_| {
607+
let name = item.router_data.get_optional_shipping_full_name();
608+
if let Some(ref val) = name {
609+
if val.clone().expose().len() > MAX_BILLING_ADDRESS_NAME_LENGTH {
610+
return Err(error_stack::Report::from(
611+
errors::ConnectorError::MaxFieldLengthViolated {
612+
field_name: "Shipping Name".to_string(),
613+
connector: "Nexixpay".to_string(),
614+
},
615+
));
616+
}
617+
}
618+
619+
if let Some(ref val) = shipping_address_street {
620+
if val.clone().expose().len() > MAX_BILLING_ADDRESS_STREET_LENGTH {
621+
return Err(error_stack::Report::from(
622+
errors::ConnectorError::MaxFieldLengthViolated {
623+
field_name: "Shipping Street".to_string(),
624+
connector: "Nexixpay".to_string(),
625+
},
626+
));
627+
}
628+
}
629+
630+
let city = item.router_data.get_optional_shipping_city();
631+
if let Some(ref val) = city {
632+
if val.len() > MAX_BILLING_ADDRESS_CITY_LENGTH {
633+
return Err(error_stack::Report::from(
634+
errors::ConnectorError::MaxFieldLengthViolated {
635+
field_name: "Shipping City".to_string(),
636+
connector: "Nexixpay".to_string(),
637+
},
638+
));
639+
}
640+
}
641+
642+
let post_code = item.router_data.get_optional_shipping_zip();
643+
if let Some(ref val) = post_code {
644+
if val.clone().expose().len() > MAX_BILLING_ADDRESS_POST_CODE_LENGTH {
645+
return Err(error_stack::Report::from(
646+
errors::ConnectorError::MaxFieldLengthViolated {
647+
field_name: "Shipping Postal Code".to_string(),
648+
connector: "Nexixpay".to_string(),
649+
},
650+
));
651+
}
652+
}
653+
654+
let country = item.router_data.get_optional_shipping_country();
655+
656+
Ok(ShippingAddress {
657+
name,
658+
street: shipping_address_street,
659+
city,
660+
post_code,
661+
country,
662+
})
663+
})
664+
.transpose()?;
543665
let customer_info = CustomerInfo {
544-
card_holder_name: item.router_data.get_billing_full_name()?,
666+
card_holder_name: match item.router_data.get_billing_full_name()? {
667+
name if name.clone().expose().len() <= MAX_CARD_HOLDER_LENGTH => name,
668+
_ => {
669+
return Err(error_stack::Report::from(
670+
errors::ConnectorError::MaxFieldLengthViolated {
671+
field_name: "Card Holder Name".to_string(),
672+
connector: "Nexixpay".to_string(),
673+
},
674+
))
675+
}
676+
},
545677
billing_address: billing_address.clone(),
546678
shipping_address: shipping_address.clone(),
547679
};
548680
let order = Order {
549681
order_id,
550682
amount: item.amount.clone(),
551683
currency: item.router_data.request.currency,
552-
description: item.router_data.description.clone(),
684+
description: item.router_data.description.clone(), //check for description length already in core
553685
customer_info,
554686
};
555687
let payment_data = NexixpayPaymentsRequestData::try_from(item)?;
@@ -1125,13 +1257,75 @@ impl TryFrom<&NexixpayRouterData<&PaymentsCompleteAuthorizeRouterData>>
11251257
let billing_address = item
11261258
.router_data
11271259
.get_optional_billing()
1128-
.map(|_| BillingAddress {
1129-
name: item.router_data.get_optional_billing_full_name(),
1130-
street: billing_address_street,
1131-
city: item.router_data.get_optional_billing_city(),
1132-
post_code: item.router_data.get_optional_billing_zip(),
1133-
country: item.router_data.get_optional_billing_country(),
1134-
});
1260+
.map(|_| {
1261+
let name = item.router_data.get_optional_billing_full_name();
1262+
if let Some(ref val) = name {
1263+
if val.clone().expose().len() > MAX_BILLING_ADDRESS_NAME_LENGTH {
1264+
return Err(error_stack::Report::from(
1265+
errors::ConnectorError::MaxFieldLengthViolated {
1266+
field_name: "Billing Name".to_string(),
1267+
connector: "Nexixpay".to_string(),
1268+
},
1269+
));
1270+
}
1271+
}
1272+
1273+
if let Some(ref val) = billing_address_street {
1274+
if val.clone().expose().len() > MAX_BILLING_ADDRESS_STREET_LENGTH {
1275+
return Err(error_stack::Report::from(
1276+
errors::ConnectorError::MaxFieldLengthViolated {
1277+
field_name: "Billing Street".to_string(),
1278+
connector: "Nexixpay".to_string(),
1279+
},
1280+
));
1281+
}
1282+
}
1283+
1284+
let city = item.router_data.get_optional_billing_city();
1285+
if let Some(ref val) = city {
1286+
if val.len() > MAX_BILLING_ADDRESS_CITY_LENGTH {
1287+
return Err(error_stack::Report::from(
1288+
errors::ConnectorError::MaxFieldLengthViolated {
1289+
field_name: "Billing City".to_string(),
1290+
connector: "Nexixpay".to_string(),
1291+
},
1292+
));
1293+
}
1294+
}
1295+
1296+
let post_code = item.router_data.get_optional_billing_zip();
1297+
if let Some(ref val) = post_code {
1298+
if val.clone().expose().len() > MAX_BILLING_ADDRESS_POST_CODE_LENGTH {
1299+
return Err(error_stack::Report::from(
1300+
errors::ConnectorError::MaxFieldLengthViolated {
1301+
field_name: "Billing Postal Code".to_string(),
1302+
connector: "Nexixpay".to_string(),
1303+
},
1304+
));
1305+
}
1306+
}
1307+
1308+
let country = item.router_data.get_optional_billing_country();
1309+
if let Some(ref val) = country {
1310+
if val.to_string().len() > MAX_BILLING_ADDRESS_COUNTRY_LENGTH {
1311+
return Err(error_stack::Report::from(
1312+
errors::ConnectorError::MaxFieldLengthViolated {
1313+
field_name: "Billing Country".to_string(),
1314+
connector: "Nexixpay".to_string(),
1315+
},
1316+
));
1317+
}
1318+
}
1319+
1320+
Ok(BillingAddress {
1321+
name,
1322+
street: billing_address_street,
1323+
city,
1324+
post_code,
1325+
country,
1326+
})
1327+
})
1328+
.transpose()?;
11351329
let shipping_address_street = match (
11361330
item.router_data.get_optional_shipping_line1(),
11371331
item.router_data.get_optional_shipping_line2(),
@@ -1149,13 +1343,65 @@ impl TryFrom<&NexixpayRouterData<&PaymentsCompleteAuthorizeRouterData>>
11491343
let shipping_address = item
11501344
.router_data
11511345
.get_optional_shipping()
1152-
.map(|_| ShippingAddress {
1153-
name: item.router_data.get_optional_shipping_full_name(),
1154-
street: shipping_address_street,
1155-
city: item.router_data.get_optional_shipping_city(),
1156-
post_code: item.router_data.get_optional_shipping_zip(),
1157-
country: item.router_data.get_optional_shipping_country(),
1158-
});
1346+
.map(|_| {
1347+
let name = item.router_data.get_optional_shipping_full_name();
1348+
if let Some(ref val) = name {
1349+
if val.clone().expose().len() > MAX_BILLING_ADDRESS_NAME_LENGTH {
1350+
return Err(error_stack::Report::from(
1351+
errors::ConnectorError::MaxFieldLengthViolated {
1352+
field_name: "Shipping Name".to_string(),
1353+
connector: "Nexixpay".to_string(),
1354+
},
1355+
));
1356+
}
1357+
}
1358+
1359+
if let Some(ref val) = shipping_address_street {
1360+
if val.clone().expose().len() > MAX_BILLING_ADDRESS_STREET_LENGTH {
1361+
return Err(error_stack::Report::from(
1362+
errors::ConnectorError::MaxFieldLengthViolated {
1363+
field_name: "Shipping Street".to_string(),
1364+
connector: "Nexixpay".to_string(),
1365+
},
1366+
));
1367+
}
1368+
}
1369+
1370+
let city = item.router_data.get_optional_shipping_city();
1371+
if let Some(ref val) = city {
1372+
if val.len() > MAX_BILLING_ADDRESS_CITY_LENGTH {
1373+
return Err(error_stack::Report::from(
1374+
errors::ConnectorError::MaxFieldLengthViolated {
1375+
field_name: "Shipping City".to_string(),
1376+
connector: "Nexixpay".to_string(),
1377+
},
1378+
));
1379+
}
1380+
}
1381+
1382+
let post_code = item.router_data.get_optional_shipping_zip();
1383+
if let Some(ref val) = post_code {
1384+
if val.clone().expose().len() > MAX_BILLING_ADDRESS_POST_CODE_LENGTH {
1385+
return Err(error_stack::Report::from(
1386+
errors::ConnectorError::MaxFieldLengthViolated {
1387+
field_name: "Shipping Postal Code".to_string(),
1388+
connector: "Nexixpay".to_string(),
1389+
},
1390+
));
1391+
}
1392+
}
1393+
1394+
let country = item.router_data.get_optional_shipping_country();
1395+
1396+
Ok(ShippingAddress {
1397+
name,
1398+
street: shipping_address_street,
1399+
city,
1400+
post_code,
1401+
country,
1402+
})
1403+
})
1404+
.transpose()?;
11591405
let customer_info = CustomerInfo {
11601406
card_holder_name: item.router_data.get_billing_full_name()?,
11611407
billing_address: billing_address.clone(),

crates/hyperswitch_domain_models/src/errors/api_error_response.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,11 @@ pub enum ApiErrorResponse {
290290
InvalidPlatformOperation,
291291
#[error(error_type = ErrorType::InvalidRequestError, code = "IR_45", message = "External vault failed during processing with connector")]
292292
ExternalVaultFailed,
293+
#[error(error_type = ErrorType::InvalidRequestError, code = "IR_47", message = "Field '{field_name}' is too long for connector '{connector}'")]
294+
MaxFieldLengthViolated {
295+
field_name: String,
296+
connector: String,
297+
},
293298
#[error(error_type = ErrorType::InvalidRequestError, code = "WE_01", message = "Failed to authenticate the webhook")]
294299
WebhookAuthenticationFailed,
295300
#[error(error_type = ErrorType::InvalidRequestError, code = "WE_02", message = "Bad request received in webhook")]
@@ -651,7 +656,9 @@ impl ErrorSwitch<api_models::errors::types::ApiErrorResponse> for ApiErrorRespon
651656
Self::ExternalVaultFailed => {
652657
AER::BadRequest(ApiError::new("IR", 45, "External Vault failed while processing with connector.", None))
653658
},
654-
659+
Self::MaxFieldLengthViolated { field_name, connector } => {
660+
AER::BadRequest(ApiError::new("IR", 47, format!("Field '{field_name}' is too long for connector '{connector}'"), Some(Extra {connector: Some(connector.to_string()), ..Default::default()})))
661+
}
655662
Self::WebhookAuthenticationFailed => {
656663
AER::Unauthorized(ApiError::new("WE", 1, "Webhook authentication failed", None))
657664
}

crates/hyperswitch_interfaces/src/errors.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,11 @@ pub enum ConnectorError {
125125
error_message: String,
126126
error_object: serde_json::Value,
127127
},
128+
#[error("Field '{field_name}' is too long for connector '{connector}'")]
129+
MaxFieldLengthViolated {
130+
field_name: String,
131+
connector: String,
132+
},
128133
}
129134

130135
impl ConnectorError {

crates/router/src/compatibility/stripe/errors.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,7 @@ impl From<errors::ApiErrorResponse> for StripeErrorCode {
600600
errors::ApiErrorResponse::AddressNotFound => Self::AddressNotFound,
601601
errors::ApiErrorResponse::NotImplemented { .. } => Self::Unauthorized,
602602
errors::ApiErrorResponse::FlowNotSupported { .. } => Self::InternalServerError,
603+
errors::ApiErrorResponse::MaxFieldLengthViolated { .. } => Self::PlatformBadRequest,
603604
errors::ApiErrorResponse::PaymentUnexpectedState {
604605
current_flow,
605606
field_name,

0 commit comments

Comments
 (0)