mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-11-02 04:04:43 +08:00
feat(core): addition of shipping address details in payment intent (#5112)
Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Co-authored-by: Sampras Lopes <Sampras.lopes@juspay.in>
This commit is contained in:
@ -224,7 +224,7 @@ impl<Flow, Request, Response> RouterData for types::RouterData<Flow, Request, Re
|
||||
shipping_address
|
||||
.clone()
|
||||
.address
|
||||
.and_then(|shipping_address_details| shipping_address_details.first_name)
|
||||
.and_then(|shipping_details| shipping_details.first_name)
|
||||
})
|
||||
}
|
||||
|
||||
@ -233,7 +233,7 @@ impl<Flow, Request, Response> RouterData for types::RouterData<Flow, Request, Re
|
||||
shipping_address
|
||||
.clone()
|
||||
.address
|
||||
.and_then(|shipping_address_details| shipping_address_details.last_name)
|
||||
.and_then(|shipping_details| shipping_details.last_name)
|
||||
})
|
||||
}
|
||||
|
||||
@ -242,7 +242,7 @@ impl<Flow, Request, Response> RouterData for types::RouterData<Flow, Request, Re
|
||||
shipping_address
|
||||
.clone()
|
||||
.address
|
||||
.and_then(|shipping_address_details| shipping_address_details.line1)
|
||||
.and_then(|shipping_details| shipping_details.line1)
|
||||
})
|
||||
}
|
||||
|
||||
@ -251,7 +251,7 @@ impl<Flow, Request, Response> RouterData for types::RouterData<Flow, Request, Re
|
||||
shipping_address
|
||||
.clone()
|
||||
.address
|
||||
.and_then(|shipping_address_details| shipping_address_details.line2)
|
||||
.and_then(|shipping_details| shipping_details.line2)
|
||||
})
|
||||
}
|
||||
|
||||
@ -260,7 +260,7 @@ impl<Flow, Request, Response> RouterData for types::RouterData<Flow, Request, Re
|
||||
shipping_address
|
||||
.clone()
|
||||
.address
|
||||
.and_then(|shipping_address_details| shipping_address_details.city)
|
||||
.and_then(|shipping_details| shipping_details.city)
|
||||
})
|
||||
}
|
||||
|
||||
@ -269,7 +269,7 @@ impl<Flow, Request, Response> RouterData for types::RouterData<Flow, Request, Re
|
||||
shipping_address
|
||||
.clone()
|
||||
.address
|
||||
.and_then(|shipping_address_details| shipping_address_details.state)
|
||||
.and_then(|shipping_details| shipping_details.state)
|
||||
})
|
||||
}
|
||||
|
||||
@ -278,7 +278,7 @@ impl<Flow, Request, Response> RouterData for types::RouterData<Flow, Request, Re
|
||||
shipping_address
|
||||
.clone()
|
||||
.address
|
||||
.and_then(|shipping_address_details| shipping_address_details.country)
|
||||
.and_then(|shipping_details| shipping_details.country)
|
||||
})
|
||||
}
|
||||
|
||||
@ -287,7 +287,7 @@ impl<Flow, Request, Response> RouterData for types::RouterData<Flow, Request, Re
|
||||
shipping_address
|
||||
.clone()
|
||||
.address
|
||||
.and_then(|shipping_address_details| shipping_address_details.zip)
|
||||
.and_then(|shipping_details| shipping_details.zip)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -3161,6 +3161,7 @@ mod tests {
|
||||
customer_details: None,
|
||||
billing_details: None,
|
||||
merchant_order_reference_id: None,
|
||||
shipping_details: None,
|
||||
};
|
||||
let req_cs = Some("1".to_string());
|
||||
assert!(authenticate_client_secret(req_cs.as_ref(), &payment_intent).is_ok());
|
||||
@ -3224,6 +3225,7 @@ mod tests {
|
||||
customer_details: None,
|
||||
billing_details: None,
|
||||
merchant_order_reference_id: None,
|
||||
shipping_details: None,
|
||||
};
|
||||
let req_cs = Some("1".to_string());
|
||||
assert!(authenticate_client_secret(req_cs.as_ref(), &payment_intent,).is_err())
|
||||
@ -3285,6 +3287,7 @@ mod tests {
|
||||
customer_details: None,
|
||||
billing_details: None,
|
||||
merchant_order_reference_id: None,
|
||||
shipping_details: None,
|
||||
};
|
||||
let req_cs = Some("1".to_string());
|
||||
assert!(authenticate_client_secret(req_cs.as_ref(), &payment_intent).is_err())
|
||||
|
||||
@ -10,6 +10,7 @@ use async_trait::async_trait;
|
||||
use common_utils::ext_traits::{AsyncExt, Encode, StringExt, ValueExt};
|
||||
use error_stack::{report, ResultExt};
|
||||
use futures::FutureExt;
|
||||
use hyperswitch_domain_models::payments::payment_intent::PaymentIntentUpdateFields;
|
||||
use masking::{ExposeInterface, PeekInterface};
|
||||
use router_derive::PaymentOperation;
|
||||
use router_env::{instrument, logger, tracing};
|
||||
@ -1223,6 +1224,10 @@ impl<F: Clone> UpdateTracker<F, PaymentData<F>, api::PaymentsRequest> for Paymen
|
||||
let billing_details = billing_address
|
||||
.async_and_then(|_| async { create_encrypted_data(key_store, billing_address).await })
|
||||
.await;
|
||||
let shipping_address = payment_data.address.get_shipping();
|
||||
let shipping_details = shipping_address
|
||||
.async_and_then(|_| async { create_encrypted_data(key_store, shipping_address).await })
|
||||
.await;
|
||||
let m_payment_data_payment_intent = payment_data.payment_intent.clone();
|
||||
let m_customer_id = customer_id.clone();
|
||||
let m_shipping_address_id = shipping_address_id.clone();
|
||||
@ -1244,7 +1249,7 @@ impl<F: Clone> UpdateTracker<F, PaymentData<F>, api::PaymentsRequest> for Paymen
|
||||
async move {
|
||||
m_db.update_payment_intent(
|
||||
m_payment_data_payment_intent,
|
||||
storage::PaymentIntentUpdate::Update {
|
||||
storage::PaymentIntentUpdate::Update(Box::new(PaymentIntentUpdateFields {
|
||||
amount: payment_data.payment_intent.amount,
|
||||
currency: payment_data.currency,
|
||||
setup_future_usage,
|
||||
@ -1269,7 +1274,8 @@ impl<F: Clone> UpdateTracker<F, PaymentData<F>, api::PaymentsRequest> for Paymen
|
||||
customer_details,
|
||||
merchant_order_reference_id: None,
|
||||
billing_details,
|
||||
},
|
||||
shipping_details,
|
||||
})),
|
||||
&m_key_store,
|
||||
storage_scheme,
|
||||
)
|
||||
|
||||
@ -1055,6 +1055,16 @@ impl PaymentCreate {
|
||||
})
|
||||
.await;
|
||||
|
||||
// Derivation of directly supplied Shipping Address data in our Payment Create Request
|
||||
// Encrypting our Shipping Address Details to be stored in Payment Intent
|
||||
let shipping_details = request
|
||||
.shipping
|
||||
.clone()
|
||||
.async_and_then(|_| async {
|
||||
create_encrypted_data(key_store, request.shipping.clone()).await
|
||||
})
|
||||
.await;
|
||||
|
||||
// Derivation of directly supplied Customer data in our Payment Create Request
|
||||
let raw_customer_details = if request.customer_id.is_none()
|
||||
&& (request.name.is_some()
|
||||
@ -1129,6 +1139,7 @@ impl PaymentCreate {
|
||||
billing_details,
|
||||
customer_details,
|
||||
merchant_order_reference_id: request.merchant_order_reference_id.clone(),
|
||||
shipping_details,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -1,9 +1,7 @@
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use api_models::{
|
||||
enums::FrmSuggestion,
|
||||
mandates::RecurringDetails,
|
||||
payments::{Address, RequestSurchargeDetails},
|
||||
enums::FrmSuggestion, mandates::RecurringDetails, payments::RequestSurchargeDetails,
|
||||
};
|
||||
use async_trait::async_trait;
|
||||
use common_utils::{
|
||||
@ -11,7 +9,9 @@ use common_utils::{
|
||||
pii::Email,
|
||||
};
|
||||
use error_stack::{report, ResultExt};
|
||||
use hyperswitch_domain_models::payments::payment_intent::CustomerData;
|
||||
use hyperswitch_domain_models::payments::payment_intent::{
|
||||
CustomerData, PaymentIntentUpdateFields,
|
||||
};
|
||||
use router_derive::PaymentOperation;
|
||||
use router_env::{instrument, tracing};
|
||||
|
||||
@ -221,14 +221,6 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa
|
||||
)
|
||||
.await?;
|
||||
|
||||
let billing_details: Option<Address> = billing_address.as_ref().map(From::from);
|
||||
payment_intent.billing_details = billing_details
|
||||
.clone()
|
||||
.async_and_then(|_| async {
|
||||
create_encrypted_data(key_store, billing_details.clone()).await
|
||||
})
|
||||
.await;
|
||||
|
||||
let payment_method_billing = helpers::create_or_update_address_for_payment_by_request(
|
||||
db,
|
||||
request
|
||||
@ -449,7 +441,7 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa
|
||||
customer_acceptance,
|
||||
address: PaymentAddress::new(
|
||||
shipping_address.as_ref().map(From::from),
|
||||
billing_details,
|
||||
billing_address.as_ref().map(From::from),
|
||||
payment_method_billing.as_ref().map(From::from),
|
||||
business_profile.use_billing_as_payment_method_billing,
|
||||
),
|
||||
@ -719,6 +711,26 @@ impl<F: Clone> UpdateTracker<F, PaymentData<F>, api::PaymentsRequest> for Paymen
|
||||
.payment_intent
|
||||
.statement_descriptor_suffix
|
||||
.clone();
|
||||
|
||||
let billing_details = payment_data
|
||||
.address
|
||||
.get_payment_billing()
|
||||
.async_and_then(|_| async {
|
||||
create_encrypted_data(
|
||||
key_store,
|
||||
payment_data.address.get_payment_billing().cloned(),
|
||||
)
|
||||
.await
|
||||
})
|
||||
.await;
|
||||
|
||||
let shipping_details = payment_data
|
||||
.address
|
||||
.get_shipping()
|
||||
.async_and_then(|_| async {
|
||||
create_encrypted_data(key_store, payment_data.address.get_shipping().cloned()).await
|
||||
})
|
||||
.await;
|
||||
let order_details = payment_data.payment_intent.order_details.clone();
|
||||
let metadata = payment_data.payment_intent.metadata.clone();
|
||||
let frm_metadata = payment_data.payment_intent.frm_metadata.clone();
|
||||
@ -727,12 +739,11 @@ impl<F: Clone> UpdateTracker<F, PaymentData<F>, api::PaymentsRequest> for Paymen
|
||||
.payment_intent
|
||||
.merchant_order_reference_id
|
||||
.clone();
|
||||
let billing_details = payment_data.payment_intent.billing_details.clone();
|
||||
payment_data.payment_intent = state
|
||||
.store
|
||||
.update_payment_intent(
|
||||
payment_data.payment_intent.clone(),
|
||||
storage::PaymentIntentUpdate::Update {
|
||||
storage::PaymentIntentUpdate::Update(Box::new(PaymentIntentUpdateFields {
|
||||
amount: payment_data.amount.into(),
|
||||
currency: payment_data.currency,
|
||||
setup_future_usage,
|
||||
@ -759,7 +770,8 @@ impl<F: Clone> UpdateTracker<F, PaymentData<F>, api::PaymentsRequest> for Paymen
|
||||
customer_details,
|
||||
merchant_order_reference_id,
|
||||
billing_details,
|
||||
},
|
||||
shipping_details,
|
||||
})),
|
||||
key_store,
|
||||
storage_scheme,
|
||||
)
|
||||
|
||||
@ -34,10 +34,11 @@ pub struct KafkaPaymentIntent<'a> {
|
||||
pub business_label: Option<&'a String>,
|
||||
pub attempt_count: i16,
|
||||
pub payment_confirm_source: Option<storage_enums::PaymentSource>,
|
||||
pub billing_details: Option<Encryptable<Secret<Value>>>,
|
||||
pub shipping_details: Option<Encryptable<Secret<Value>>>,
|
||||
pub customer_email: Option<HashedString<pii::EmailStrategy>>,
|
||||
pub feature_metadata: Option<&'a Value>,
|
||||
pub merchant_order_reference_id: Option<&'a String>,
|
||||
pub billing_details: Option<Encryptable<Secret<Value>>>,
|
||||
}
|
||||
|
||||
impl<'a> KafkaPaymentIntent<'a> {
|
||||
@ -67,6 +68,9 @@ impl<'a> KafkaPaymentIntent<'a> {
|
||||
business_label: intent.business_label.as_ref(),
|
||||
attempt_count: intent.attempt_count,
|
||||
payment_confirm_source: intent.payment_confirm_source,
|
||||
// TODO: use typed information here to avoid PII logging
|
||||
billing_details: None,
|
||||
shipping_details: None,
|
||||
customer_email: intent
|
||||
.customer_details
|
||||
.as_ref()
|
||||
@ -76,7 +80,6 @@ impl<'a> KafkaPaymentIntent<'a> {
|
||||
.map(|email| HashedString::from(Secret::new(email.to_string()))),
|
||||
feature_metadata: intent.feature_metadata.as_ref(),
|
||||
merchant_order_reference_id: intent.merchant_order_reference_id.as_ref(),
|
||||
billing_details: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,10 +35,11 @@ pub struct KafkaPaymentIntentEvent<'a> {
|
||||
pub business_label: Option<&'a String>,
|
||||
pub attempt_count: i16,
|
||||
pub payment_confirm_source: Option<storage_enums::PaymentSource>,
|
||||
pub billing_details: Option<Encryptable<Secret<Value>>>,
|
||||
pub shipping_details: Option<Encryptable<Secret<Value>>>,
|
||||
pub customer_email: Option<HashedString<pii::EmailStrategy>>,
|
||||
pub feature_metadata: Option<&'a Value>,
|
||||
pub merchant_order_reference_id: Option<&'a String>,
|
||||
pub billing_details: Option<Encryptable<Secret<Value>>>,
|
||||
}
|
||||
|
||||
impl<'a> KafkaPaymentIntentEvent<'a> {
|
||||
@ -68,6 +69,9 @@ impl<'a> KafkaPaymentIntentEvent<'a> {
|
||||
business_label: intent.business_label.as_ref(),
|
||||
attempt_count: intent.attempt_count,
|
||||
payment_confirm_source: intent.payment_confirm_source,
|
||||
// TODO: use typed information here to avoid PII logging
|
||||
billing_details: None,
|
||||
shipping_details: None,
|
||||
customer_email: intent
|
||||
.customer_details
|
||||
.as_ref()
|
||||
@ -77,7 +81,6 @@ impl<'a> KafkaPaymentIntentEvent<'a> {
|
||||
.map(|email| HashedString::from(Secret::new(email.to_string()))),
|
||||
feature_metadata: intent.feature_metadata.as_ref(),
|
||||
merchant_order_reference_id: intent.merchant_order_reference_id.as_ref(),
|
||||
billing_details: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,7 +47,7 @@ pub use diesel_models::{
|
||||
};
|
||||
pub use hyperswitch_domain_models::payments::{
|
||||
payment_attempt::{PaymentAttempt, PaymentAttemptNew, PaymentAttemptUpdate},
|
||||
payment_intent::{PaymentIntentNew, PaymentIntentUpdate},
|
||||
payment_intent::{PaymentIntentNew, PaymentIntentUpdate, PaymentIntentUpdateFields},
|
||||
PaymentIntent,
|
||||
};
|
||||
#[cfg(feature = "payouts")]
|
||||
|
||||
@ -228,6 +228,7 @@ pub async fn generate_sample_data(
|
||||
customer_details: None,
|
||||
billing_details: None,
|
||||
merchant_order_reference_id: Default::default(),
|
||||
shipping_details: None,
|
||||
};
|
||||
let payment_attempt = PaymentAttemptBatchNew {
|
||||
attempt_id: attempt_id.clone(),
|
||||
|
||||
Reference in New Issue
Block a user