mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-29 00:49:42 +08:00
refactor(router): infer ip address for online mandates from request headers if absent (#1419)
This commit is contained in:
@ -432,7 +432,7 @@ pub enum AcceptanceType {
|
||||
pub struct OnlineMandate {
|
||||
/// Ip address of the customer machine from which the mandate was created
|
||||
#[schema(value_type = String, example = "123.32.25.123")]
|
||||
pub ip_address: Secret<String, pii::IpAddress>,
|
||||
pub ip_address: Option<Secret<String, pii::IpAddress>>,
|
||||
/// The user-agent of the customer's browser
|
||||
pub user_agent: String,
|
||||
}
|
||||
|
||||
@ -615,7 +615,7 @@ impl ForeignTryFrom<(Option<MandateOption>, Option<String>)> for Option<payments
|
||||
acceptance_type: payments::AcceptanceType::Online,
|
||||
accepted_at: mandate.accepted_at,
|
||||
online: Some(payments::OnlineMandate {
|
||||
ip_address: mandate.ip_address.unwrap_or_default(),
|
||||
ip_address: mandate.ip_address,
|
||||
user_agent: mandate.user_agent.unwrap_or_default(),
|
||||
}),
|
||||
}),
|
||||
|
||||
@ -1254,8 +1254,8 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for PaymentIntentRequest {
|
||||
_ => payment_data,
|
||||
};
|
||||
|
||||
let setup_mandate_details =
|
||||
item.request
|
||||
let setup_mandate_details = item
|
||||
.request
|
||||
.setup_mandate_details
|
||||
.as_ref()
|
||||
.and_then(|mandate_details| {
|
||||
@ -1264,12 +1264,21 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for PaymentIntentRequest {
|
||||
.as_ref()?
|
||||
.online
|
||||
.as_ref()
|
||||
.map(|online_details| StripeMandateRequest {
|
||||
.map(|online_details| {
|
||||
Ok::<_, error_stack::Report<errors::ConnectorError>>(StripeMandateRequest {
|
||||
mandate_type: StripeMandateType::Online,
|
||||
ip_address: online_details.ip_address.to_owned(),
|
||||
ip_address: online_details
|
||||
.ip_address
|
||||
.clone()
|
||||
.get_required_value("ip_address")
|
||||
.change_context(errors::ConnectorError::MissingRequiredField {
|
||||
field_name: "ip_address",
|
||||
})?,
|
||||
user_agent: online_details.user_agent.to_owned(),
|
||||
})
|
||||
});
|
||||
})
|
||||
})
|
||||
.transpose()?;
|
||||
|
||||
Ok(Self {
|
||||
amount: item.request.amount, //hopefully we don't loose some cents here
|
||||
|
||||
@ -3,13 +3,13 @@ use error_stack::ResultExt;
|
||||
use crate::{
|
||||
core::errors::{self, RouterResult},
|
||||
headers, logger,
|
||||
types::{self, api::payments as payment_types},
|
||||
types::{self, api},
|
||||
utils::{Encode, ValueExt},
|
||||
};
|
||||
|
||||
pub fn populate_ip_into_browser_info(
|
||||
req: &actix_web::HttpRequest,
|
||||
payload: &mut payment_types::PaymentsRequest,
|
||||
payload: &mut api::PaymentsRequest,
|
||||
) -> RouterResult<()> {
|
||||
let mut browser_info: types::BrowserInformation = payload
|
||||
.browser_info
|
||||
@ -32,14 +32,11 @@ pub fn populate_ip_into_browser_info(
|
||||
ip_address: None,
|
||||
});
|
||||
|
||||
browser_info.ip_address = browser_info
|
||||
.ip_address
|
||||
.or_else(|| {
|
||||
// Parse the IP Address from the "X-Forwarded-For" header
|
||||
// This header will contain multiple IP addresses for each ALB hop which has
|
||||
// a comma separated list of IP addresses: 'X.X.X.X, Y.Y.Y.Y, Z.Z.Z.Z'
|
||||
// The first one here will be the client IP which we want to retrieve
|
||||
req.headers()
|
||||
let ip_address_from_header = req.headers()
|
||||
.get(headers::X_FORWARDED_FOR)
|
||||
.map(|val| val.to_str())
|
||||
.transpose()
|
||||
@ -47,7 +44,10 @@ pub fn populate_ip_into_browser_info(
|
||||
logger::error!(error=?e, message="failed to retrieve ip address from X-Forwarded-For header");
|
||||
None
|
||||
})
|
||||
.and_then(|ips| ips.split(',').next())
|
||||
.and_then(|ips| ips.split(',').next());
|
||||
|
||||
browser_info.ip_address = browser_info.ip_address.or_else(|| {
|
||||
ip_address_from_header
|
||||
.map(|ip| ip.parse())
|
||||
.transpose()
|
||||
.unwrap_or_else(|e| {
|
||||
@ -56,6 +56,23 @@ pub fn populate_ip_into_browser_info(
|
||||
})
|
||||
});
|
||||
|
||||
if let Some(api::MandateData {
|
||||
customer_acceptance:
|
||||
Some(api::CustomerAcceptance {
|
||||
online:
|
||||
Some(api::OnlineMandate {
|
||||
ip_address: req_ip, ..
|
||||
}),
|
||||
..
|
||||
}),
|
||||
..
|
||||
}) = &mut payload.mandate_data
|
||||
{
|
||||
*req_ip = req_ip
|
||||
.clone()
|
||||
.or_else(|| ip_address_from_header.map(|ip| masking::Secret::new(ip.to_string())));
|
||||
}
|
||||
|
||||
let encoded = Encode::<types::BrowserInformation>::encode_to_value(&browser_info)
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable(
|
||||
|
||||
@ -73,7 +73,7 @@ impl MandateResponseExt for MandateResponse {
|
||||
},
|
||||
accepted_at: mandate.customer_accepted_at,
|
||||
online: Some(api::payments::OnlineMandate {
|
||||
ip_address: mandate.customer_ip_address.unwrap_or_default(),
|
||||
ip_address: mandate.customer_ip_address,
|
||||
user_agent: mandate.customer_user_agent.unwrap_or_default(),
|
||||
}),
|
||||
}),
|
||||
|
||||
@ -43,7 +43,7 @@ impl CustomerAcceptanceExt for CustomerAcceptance {
|
||||
fn get_ip_address(&self) -> Option<String> {
|
||||
self.online
|
||||
.as_ref()
|
||||
.map(|data| data.ip_address.peek().to_owned())
|
||||
.and_then(|data| data.ip_address.as_ref().map(|ip| ip.peek().to_owned()))
|
||||
}
|
||||
|
||||
fn get_user_agent(&self) -> Option<String> {
|
||||
|
||||
Reference in New Issue
Block a user