From 34206a871f8a4a368609aca3491528511257e373 Mon Sep 17 00:00:00 2001 From: Sanchith Hegde Date: Wed, 13 Nov 2024 03:10:38 +0530 Subject: [PATCH 01/19] feat(hyperswitch_domain_models): introduce `EncryptedJsonType` to handle JSON serialization and encryption --- .../src/type_encryption.rs | 274 +++++++++++++++++- 1 file changed, 261 insertions(+), 13 deletions(-) diff --git a/crates/hyperswitch_domain_models/src/type_encryption.rs b/crates/hyperswitch_domain_models/src/type_encryption.rs index 983528dee981..89cd01a085ff 100644 --- a/crates/hyperswitch_domain_models/src/type_encryption.rs +++ b/crates/hyperswitch_domain_models/src/type_encryption.rs @@ -18,6 +18,7 @@ mod encrypt { crypto, encryption::Encryption, errors::{self, CustomResult}, + ext_traits::ByteSliceExt, keymanager::call_encryption_service, transformers::{ForeignFrom, ForeignTryFrom}, types::keymanager::{ @@ -32,7 +33,7 @@ mod encrypt { use router_env::{instrument, logger, tracing}; use rustc_hash::FxHashMap; - use super::metrics; + use super::{metrics, EncryptedJsonType}; #[async_trait] pub trait TypeEncryption< @@ -116,7 +117,6 @@ mod encrypt { > TypeEncryption for crypto::Encryptable> { #[instrument(skip_all)] - #[allow(unused_variables)] async fn encrypt_via_api( state: &KeyManagerState, masked_data: Secret, @@ -151,7 +151,6 @@ mod encrypt { } #[instrument(skip_all)] - #[allow(unused_variables)] async fn decrypt_via_api( state: &KeyManagerState, encrypted_data: Encryption, @@ -194,6 +193,7 @@ mod encrypt { } } + #[instrument(skip_all)] async fn encrypt( masked_data: Secret, key: &[u8], @@ -204,6 +204,7 @@ mod encrypt { Ok(Self::new(masked_data, encrypted_data.into())) } + #[instrument(skip_all)] async fn decrypt( encrypted_data: Encryption, key: &[u8], @@ -220,7 +221,7 @@ mod encrypt { Ok(Self::new(value.into(), encrypted)) } - #[allow(unused_variables)] + #[instrument(skip_all)] async fn batch_encrypt_via_api( state: &KeyManagerState, masked_data: FxHashMap>, @@ -254,7 +255,7 @@ mod encrypt { } } - #[allow(unused_variables)] + #[instrument(skip_all)] async fn batch_decrypt_via_api( state: &KeyManagerState, encrypted_data: FxHashMap, @@ -296,6 +297,7 @@ mod encrypt { } } + #[instrument(skip_all)] async fn batch_encrypt( masked_data: FxHashMap>, key: &[u8], @@ -316,6 +318,7 @@ mod encrypt { .collect() } + #[instrument(skip_all)] async fn batch_decrypt( encrypted_data: FxHashMap, key: &[u8], @@ -343,7 +346,6 @@ mod encrypt { for crypto::Encryptable> { #[instrument(skip_all)] - #[allow(unused_variables)] async fn encrypt_via_api( state: &KeyManagerState, masked_data: Secret, @@ -378,7 +380,6 @@ mod encrypt { } #[instrument(skip_all)] - #[allow(unused_variables)] async fn decrypt_via_api( state: &KeyManagerState, encrypted_data: Encryption, @@ -448,7 +449,7 @@ mod encrypt { Ok(Self::new(value.into(), encrypted)) } - #[allow(unused_variables)] + #[instrument(skip_all)] async fn batch_encrypt_via_api( state: &KeyManagerState, masked_data: FxHashMap>, @@ -482,7 +483,7 @@ mod encrypt { } } - #[allow(unused_variables)] + #[instrument(skip_all)] async fn batch_decrypt_via_api( state: &KeyManagerState, encrypted_data: FxHashMap, @@ -524,6 +525,7 @@ mod encrypt { } } + #[instrument(skip_all)] async fn batch_encrypt( masked_data: FxHashMap>, key: &[u8], @@ -543,6 +545,7 @@ mod encrypt { .collect() } + #[instrument(skip_all)] async fn batch_decrypt( encrypted_data: FxHashMap, key: &[u8], @@ -562,6 +565,235 @@ mod encrypt { } } + impl EncryptedJsonType + where + T: std::fmt::Debug + Clone + serde::Serialize + serde::de::DeserializeOwned, + { + fn serialize_json_bytes(&self) -> CustomResult>, errors::CryptoError> { + common_utils::ext_traits::Encode::encode_to_vec(self.inner()) + .change_context(errors::CryptoError::EncodingFailed) + .attach_printable("Failed to JSON serialize data before encryption") + .map(Secret::new) + } + + fn deserialize_json_bytes( + bytes: Secret>, + ) -> CustomResult, errors::ParsingError> + where + S: masking::Strategy, + { + bytes + .peek() + .as_slice() + .parse_struct::(std::any::type_name::()) + .map(|result| Secret::new(Self::from(result))) + .attach_printable("Failed to JSON deserialize data after decryption") + } + } + + #[async_trait] + impl< + T: std::fmt::Debug + Clone + serde::Serialize + serde::de::DeserializeOwned + Send, + V: crypto::DecodeMessage + crypto::EncodeMessage + Send + 'static, + S: masking::Strategy> + Send + Sync, + > TypeEncryption, V, S> + for crypto::Encryptable, S>> + { + #[instrument(skip_all)] + async fn encrypt_via_api( + state: &KeyManagerState, + masked_data: Secret, S>, + identifier: Identifier, + key: &[u8], + crypt_algo: V, + ) -> CustomResult { + let data_bytes = EncryptedJsonType::serialize_json_bytes(masked_data.peek())?; + let result: crypto::Encryptable>> = + TypeEncryption::encrypt_via_api(state, data_bytes, identifier, key, crypt_algo) + .await?; + Ok(Self::new(masked_data, result.into_encrypted())) + } + + #[instrument(skip_all)] + async fn decrypt_via_api( + state: &KeyManagerState, + encrypted_data: Encryption, + identifier: Identifier, + key: &[u8], + crypt_algo: V, + ) -> CustomResult { + let result: crypto::Encryptable>> = + TypeEncryption::decrypt_via_api(state, encrypted_data, identifier, key, crypt_algo) + .await?; + result + .deserialize_inner_value(EncryptedJsonType::deserialize_json_bytes) + .change_context(errors::CryptoError::DecodingFailed) + } + + #[instrument(skip_all)] + async fn encrypt( + masked_data: Secret, S>, + key: &[u8], + crypt_algo: V, + ) -> CustomResult { + let data_bytes = EncryptedJsonType::serialize_json_bytes(masked_data.peek())?; + let result: crypto::Encryptable>> = + TypeEncryption::encrypt(data_bytes, key, crypt_algo).await?; + Ok(Self::new(masked_data, result.into_encrypted())) + } + + #[instrument(skip_all)] + async fn decrypt( + encrypted_data: Encryption, + key: &[u8], + crypt_algo: V, + ) -> CustomResult { + let result: crypto::Encryptable>> = + TypeEncryption::decrypt(encrypted_data, key, crypt_algo).await?; + result + .deserialize_inner_value(EncryptedJsonType::deserialize_json_bytes) + .change_context(errors::CryptoError::DecodingFailed) + } + + #[instrument(skip_all)] + async fn batch_encrypt_via_api( + state: &KeyManagerState, + masked_data: FxHashMap, S>>, + identifier: Identifier, + key: &[u8], + crypt_algo: V, + ) -> CustomResult, errors::CryptoError> { + let hashmap_capacity = masked_data.len(); + let data_bytes = masked_data.iter().try_fold( + FxHashMap::with_capacity_and_hasher(hashmap_capacity, Default::default()), + |mut map, (key, value)| { + let value_bytes = EncryptedJsonType::serialize_json_bytes(value.peek())?; + map.insert(key.to_owned(), value_bytes); + Ok::<_, error_stack::Report>(map) + }, + )?; + + let result: FxHashMap>>> = + TypeEncryption::batch_encrypt_via_api( + state, data_bytes, identifier, key, crypt_algo, + ) + .await?; + let result_hashmap = result.into_iter().try_fold( + FxHashMap::with_capacity_and_hasher(hashmap_capacity, Default::default()), + |mut map, (key, value)| { + let original_value = masked_data + .get(&key) + .ok_or(errors::CryptoError::EncodingFailed) + .attach_printable_lazy(|| { + format!("Failed to find {key} in input hashmap") + })?; + map.insert( + key, + Self::new(original_value.clone(), value.into_encrypted()), + ); + Ok::<_, error_stack::Report>(map) + }, + )?; + + Ok(result_hashmap) + } + + #[instrument(skip_all)] + async fn batch_decrypt_via_api( + state: &KeyManagerState, + encrypted_data: FxHashMap, + identifier: Identifier, + key: &[u8], + crypt_algo: V, + ) -> CustomResult, errors::CryptoError> { + let result: FxHashMap>>> = + TypeEncryption::batch_decrypt_via_api( + state, + encrypted_data, + identifier, + key, + crypt_algo, + ) + .await?; + + let hashmap_capacity = result.len(); + let result_hashmap = result.into_iter().try_fold( + FxHashMap::with_capacity_and_hasher(hashmap_capacity, Default::default()), + |mut map, (key, value)| { + let deserialized_value = value + .deserialize_inner_value(EncryptedJsonType::deserialize_json_bytes) + .change_context(errors::CryptoError::DecodingFailed)?; + map.insert(key, deserialized_value); + Ok::<_, error_stack::Report>(map) + }, + )?; + + Ok(result_hashmap) + } + + #[instrument(skip_all)] + async fn batch_encrypt( + masked_data: FxHashMap, S>>, + key: &[u8], + crypt_algo: V, + ) -> CustomResult, errors::CryptoError> { + let hashmap_capacity = masked_data.len(); + let data_bytes = masked_data.iter().try_fold( + FxHashMap::with_capacity_and_hasher(hashmap_capacity, Default::default()), + |mut map, (key, value)| { + let value_bytes = EncryptedJsonType::serialize_json_bytes(value.peek())?; + map.insert(key.to_owned(), value_bytes); + Ok::<_, error_stack::Report>(map) + }, + )?; + + let result: FxHashMap>>> = + TypeEncryption::batch_encrypt(data_bytes, key, crypt_algo).await?; + let result_hashmap = result.into_iter().try_fold( + FxHashMap::with_capacity_and_hasher(hashmap_capacity, Default::default()), + |mut map, (key, value)| { + let original_value = masked_data + .get(&key) + .ok_or(errors::CryptoError::EncodingFailed) + .attach_printable_lazy(|| { + format!("Failed to find {key} in input hashmap") + })?; + map.insert( + key, + Self::new(original_value.clone(), value.into_encrypted()), + ); + Ok::<_, error_stack::Report>(map) + }, + )?; + + Ok(result_hashmap) + } + + #[instrument(skip_all)] + async fn batch_decrypt( + encrypted_data: FxHashMap, + key: &[u8], + crypt_algo: V, + ) -> CustomResult, errors::CryptoError> { + let result: FxHashMap>>> = + TypeEncryption::batch_decrypt(encrypted_data, key, crypt_algo).await?; + + let hashmap_capacity = result.len(); + let result_hashmap = result.into_iter().try_fold( + FxHashMap::with_capacity_and_hasher(hashmap_capacity, Default::default()), + |mut map, (key, value)| { + let deserialized_value = value + .deserialize_inner_value(EncryptedJsonType::deserialize_json_bytes) + .change_context(errors::CryptoError::DecodingFailed)?; + map.insert(key, deserialized_value); + Ok::<_, error_stack::Report>(map) + }, + )?; + + Ok(result_hashmap) + } + } + #[async_trait] impl< V: crypto::DecodeMessage + crypto::EncodeMessage + Send + 'static, @@ -569,7 +801,6 @@ mod encrypt { > TypeEncryption, V, S> for crypto::Encryptable, S>> { #[instrument(skip_all)] - #[allow(unused_variables)] async fn encrypt_via_api( state: &KeyManagerState, masked_data: Secret, S>, @@ -604,7 +835,6 @@ mod encrypt { } #[instrument(skip_all)] - #[allow(unused_variables)] async fn decrypt_via_api( state: &KeyManagerState, encrypted_data: Encryption, @@ -669,7 +899,7 @@ mod encrypt { Ok(Self::new(data.into(), encrypted)) } - #[allow(unused_variables)] + #[instrument(skip_all)] async fn batch_encrypt_via_api( state: &KeyManagerState, masked_data: FxHashMap, S>>, @@ -703,7 +933,7 @@ mod encrypt { } } - #[allow(unused_variables)] + #[instrument(skip_all)] async fn batch_decrypt_via_api( state: &KeyManagerState, encrypted_data: FxHashMap, @@ -745,6 +975,7 @@ mod encrypt { } } + #[instrument(skip_all)] async fn batch_encrypt( masked_data: FxHashMap, S>>, key: &[u8], @@ -762,6 +993,7 @@ mod encrypt { .collect() } + #[instrument(skip_all)] async fn batch_decrypt( encrypted_data: FxHashMap, key: &[u8], @@ -785,6 +1017,22 @@ mod encrypt { } } } + +#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] +pub struct EncryptedJsonType(T); + +impl From for EncryptedJsonType { + fn from(value: T) -> Self { + Self(value) + } +} + +impl EncryptedJsonType { + pub(crate) fn inner(&self) -> &T { + &self.0 + } +} + pub trait Lift { type SelfWrapper; type OtherWrapper; From 471974034ea068f49355436b10acf7e1a5fdaf67 Mon Sep 17 00:00:00 2001 From: Narayan Bhat Date: Sun, 17 Nov 2024 11:09:18 +0530 Subject: [PATCH 02/19] feat: add domain address --- .../hyperswitch_domain_models/src/address.rs | 157 ++++++++++++++++++ crates/hyperswitch_domain_models/src/lib.rs | 1 + 2 files changed, 158 insertions(+) create mode 100644 crates/hyperswitch_domain_models/src/address.rs diff --git a/crates/hyperswitch_domain_models/src/address.rs b/crates/hyperswitch_domain_models/src/address.rs new file mode 100644 index 000000000000..d4649a27db92 --- /dev/null +++ b/crates/hyperswitch_domain_models/src/address.rs @@ -0,0 +1,157 @@ +use masking::{PeekInterface, Secret}; + +#[derive(Default, Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] +pub struct Address { + pub address: Option, + pub phone: Option, + pub email: Option, +} + +impl Address { + /// Unify the address, giving priority to `self` when details are present in both + pub fn unify_address(self, other: Option<&Self>) -> Self { + let other_address_details = other.and_then(|address| address.address.as_ref()); + Self { + address: self + .address + .map(|address| address.unify_address_details(other_address_details)) + .or(other_address_details.cloned()), + email: self.email.or(other.and_then(|other| other.email.clone())), + phone: self.phone.or(other.and_then(|other| other.phone.clone())), + } + } +} + +#[derive(Clone, Default, Debug, Eq, serde::Deserialize, serde::Serialize, PartialEq)] +pub struct AddressDetails { + pub city: Option, + pub country: Option, + pub line1: Option>, + pub line2: Option>, + pub line3: Option>, + pub zip: Option>, + pub state: Option>, + pub first_name: Option>, + pub last_name: Option>, +} + +impl AddressDetails { + pub fn get_optional_full_name(&self) -> Option> { + match (self.first_name.as_ref(), self.last_name.as_ref()) { + (Some(first_name), Some(last_name)) => Some(Secret::new(format!( + "{} {}", + first_name.peek(), + last_name.peek() + ))), + (Some(name), None) | (None, Some(name)) => Some(name.to_owned()), + _ => None, + } + } + + /// Unify the address details, giving priority to `self` when details are present in both + pub fn unify_address_details(self, other: Option<&Self>) -> Self { + if let Some(other) = other { + let (first_name, last_name) = if self + .first_name + .as_ref() + .is_some_and(|first_name| !first_name.peek().trim().is_empty()) + { + (self.first_name, self.last_name) + } else { + (other.first_name.clone(), other.last_name.clone()) + }; + + Self { + first_name, + last_name, + city: self.city.or(other.city.clone()), + country: self.country.or(other.country), + line1: self.line1.or(other.line1.clone()), + line2: self.line2.or(other.line2.clone()), + line3: self.line3.or(other.line3.clone()), + zip: self.zip.or(other.zip.clone()), + state: self.state.or(other.state.clone()), + } + } else { + self + } + } +} + +#[derive(Debug, Clone, Default, Eq, PartialEq, serde::Deserialize, serde::Serialize)] +pub struct PhoneDetails { + pub number: Option>, + pub country_code: Option, +} + +impl From for Address { + fn from(address: api_models::payments::Address) -> Self { + Self { + address: address.address.map(AddressDetails::from), + phone: address.phone.map(PhoneDetails::from), + email: address.email, + } + } +} + +impl From for AddressDetails { + fn from(address: api_models::payments::AddressDetails) -> Self { + Self { + city: address.city, + country: address.country, + line1: address.line1, + line2: address.line2, + line3: address.line3, + zip: address.zip, + state: address.state, + first_name: address.first_name, + last_name: address.last_name, + } + } +} + +impl From for PhoneDetails { + fn from(phone: api_models::payments::PhoneDetails) -> Self { + Self { + number: phone.number, + country_code: phone.country_code, + } + } +} + +impl From
for api_models::payments::Address { + fn from(address: Address) -> Self { + Self { + address: address + .address + .map(api_models::payments::AddressDetails::from), + phone: address.phone.map(api_models::payments::PhoneDetails::from), + email: address.email, + } + } +} + +impl From for api_models::payments::AddressDetails { + fn from(address: AddressDetails) -> Self { + Self { + city: address.city, + country: address.country, + line1: address.line1, + line2: address.line2, + line3: address.line3, + zip: address.zip, + state: address.state, + first_name: address.first_name, + last_name: address.last_name, + } + } +} + +impl From for api_models::payments::PhoneDetails { + fn from(phone: PhoneDetails) -> Self { + Self { + number: phone.number, + country_code: phone.country_code, + } + } +} diff --git a/crates/hyperswitch_domain_models/src/lib.rs b/crates/hyperswitch_domain_models/src/lib.rs index 02795481ad9c..6cc498870d52 100644 --- a/crates/hyperswitch_domain_models/src/lib.rs +++ b/crates/hyperswitch_domain_models/src/lib.rs @@ -1,3 +1,4 @@ +pub mod address; pub mod api; pub mod behaviour; pub mod business_profile; From 8b47104ef4948f6a7cc6bbbeebd668cca50eb23b Mon Sep 17 00:00:00 2001 From: Narayan Bhat Date: Sun, 17 Nov 2024 13:21:54 +0530 Subject: [PATCH 03/19] refactor: add batch encryption to payment intent --- .../hyperswitch_domain_models/src/address.rs | 2 + .../hyperswitch_domain_models/src/payments.rs | 38 +++++++--- .../operations/payment_create_intent.rs | 71 ++++++++----------- .../router/src/core/payments/transformers.rs | 6 +- 4 files changed, 65 insertions(+), 52 deletions(-) diff --git a/crates/hyperswitch_domain_models/src/address.rs b/crates/hyperswitch_domain_models/src/address.rs index d4649a27db92..85595c1ad9e3 100644 --- a/crates/hyperswitch_domain_models/src/address.rs +++ b/crates/hyperswitch_domain_models/src/address.rs @@ -7,6 +7,8 @@ pub struct Address { pub email: Option, } +impl masking::SerializableSecret for Address {} + impl Address { /// Unify the address, giving priority to `self` when details are present in both pub fn unify_address(self, other: Option<&Self>) -> Self { diff --git a/crates/hyperswitch_domain_models/src/payments.rs b/crates/hyperswitch_domain_models/src/payments.rs index 5c629f6198ed..960f835b22a8 100644 --- a/crates/hyperswitch_domain_models/src/payments.rs +++ b/crates/hyperswitch_domain_models/src/payments.rs @@ -2,12 +2,12 @@ use std::marker::PhantomData; #[cfg(feature = "v2")] -use api_models::payments::Address; use common_utils::{ self, crypto::Encryptable, encryption::Encryption, errors::CustomResult, + ext_traits::ValueExt, id_type, pii, types::{keymanager::ToEncryptable, MinorUnit}, }; @@ -30,9 +30,10 @@ use diesel_models::types::{FeatureMetadata, OrderDetailsWithAmount}; use self::payment_attempt::PaymentAttempt; use crate::RemoteStorageObject; #[cfg(feature = "v2")] -use crate::{business_profile, merchant_account}; -#[cfg(feature = "v2")] -use crate::{errors, payment_method_data, ApiModelToDieselModelConvertor}; +use crate::{ + address::Address, business_profile, errors, merchant_account, payment_method_data, + ApiModelToDieselModelConvertor, +}; #[cfg(feature = "v1")] #[derive(Clone, Debug, PartialEq, serde::Serialize, ToEncryption)] @@ -348,10 +349,10 @@ pub struct PaymentIntent { pub merchant_reference_id: Option, /// The billing address for the order in a denormalized form. #[encrypt(ty = Value)] - pub billing_address: Option>>, + pub billing_address: Option>, /// The shipping address for the order in a denormalized form. #[encrypt(ty = Value)] - pub shipping_address: Option>>, + pub shipping_address: Option>, /// Capture method for the payment pub capture_method: storage_enums::CaptureMethod, /// Authentication type that is requested by the merchant for this payment. @@ -415,8 +416,7 @@ impl PaymentIntent { merchant_account: &merchant_account::MerchantAccount, profile: &business_profile::Profile, request: api_models::payments::PaymentsCreateIntentRequest, - billing_address: Option>>, - shipping_address: Option>>, + decrypted_payment_intent: DecryptedPaymentIntent, ) -> CustomResult { let connector_metadata = request .get_connector_metadata_as_value() @@ -479,8 +479,26 @@ impl PaymentIntent { frm_metadata: request.frm_metadata, customer_details: None, merchant_reference_id: request.merchant_reference_id, - billing_address, - shipping_address, + billing_address: decrypted_payment_intent + .billing_address + .as_ref() + .map(|data| { + data.clone() + .deserialize_inner_value(|value| value.parse_value("Address")) + }) + .transpose() + .change_context(errors::api_error_response::ApiErrorResponse::InternalServerError) + .attach_printable("Unable to decode billing address")?, + shipping_address: decrypted_payment_intent + .shipping_address + .as_ref() + .map(|data| { + data.clone() + .deserialize_inner_value(|value| value.parse_value("Address")) + }) + .transpose() + .change_context(errors::api_error_response::ApiErrorResponse::InternalServerError) + .attach_printable("Unable to decode shipping address")?, capture_method: request.capture_method.unwrap_or_default(), authentication_type: request.authentication_type.unwrap_or_default(), prerouting_algorithm: None, diff --git a/crates/router/src/core/payments/operations/payment_create_intent.rs b/crates/router/src/core/payments/operations/payment_create_intent.rs index b46992a6aed6..bf5b4fb80c9e 100644 --- a/crates/router/src/core/payments/operations/payment_create_intent.rs +++ b/crates/router/src/core/payments/operations/payment_create_intent.rs @@ -4,9 +4,11 @@ use api_models::{enums::FrmSuggestion, payments::PaymentsCreateIntentRequest}; use async_trait::async_trait; use common_utils::{ errors::CustomResult, - ext_traits::{AsyncExt, ValueExt}, + ext_traits::{AsyncExt, Encode, ValueExt}, + types::keymanager::ToEncryptable, }; use error_stack::ResultExt; +use masking::PeekInterface; use router_env::{instrument, tracing}; use super::{BoxedOperation, Domain, GetTracker, Operation, UpdateTracker, ValidateRequest}; @@ -18,7 +20,8 @@ use crate::{ routes::{app::ReqState, SessionState}, services, types::{ - api, domain, + api, + domain::{self, types as domain_types}, storage::{self, enums}, }, }; @@ -100,51 +103,39 @@ impl GetTracker, PaymentsCrea let key_manager_state = &state.into(); let storage_scheme = merchant_account.storage_scheme; - // Derivation of directly supplied Billing Address data in our Payment Create Request - // Encrypting our Billing Address Details to be stored in Payment Intent - let billing_address = request - .billing - .clone() - .async_map(|billing_details| { - create_encrypted_data(key_manager_state, key_store, billing_details) - }) - .await - .transpose() - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Unable to encrypt billing details")? - .map(|encrypted_value| { - encrypted_value.deserialize_inner_value(|value| value.parse_value("Address")) - }) - .transpose() - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Unable to deserialize decrypted value to Address")?; - // 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_address = request - .shipping - .clone() - .async_map(|shipping_details| { - create_encrypted_data(key_manager_state, key_store, shipping_details) - }) - .await - .transpose() - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Unable to encrypt shipping details")? - .map(|encrypted_value| { - encrypted_value.deserialize_inner_value(|value| value.parse_value("Address")) - }) - .transpose() - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Unable to deserialize decrypted value to Address")?; + let batch_encrypted_data = domain_types::crypto_operation( + key_manager_state, + common_utils::type_name!(hyperswitch_domain_models::payments::PaymentIntent), + domain_types::CryptoOperation::BatchEncrypt( + hyperswitch_domain_models::payments::FromRequestEncryptablePaymentIntent::to_encryptable( + hyperswitch_domain_models::payments::FromRequestEncryptablePaymentIntent { + shipping_address: request.shipping.clone().map(|address| address.encode_to_value()).transpose().change_context(errors::ApiErrorResponse::InternalServerError).attach_printable("Failed to encode shipping address")?.map(masking::Secret::new), + billing_address: request.billing.clone().map(|address| address.encode_to_value()).transpose().change_context(errors::ApiErrorResponse::InternalServerError).attach_printable("Failed to encode billing address")?.map(masking::Secret::new), + customer_details: None, + }, + ), + ), + common_utils::types::keymanager::Identifier::Merchant(merchant_account.get_id().to_owned()), + key_store.key.peek(), + ) + .await + .and_then(|val| val.try_into_batchoperation()) + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Failed while encrypting payment intent details".to_string())?; + + let encrypted_data = + hyperswitch_domain_models::payments::FromRequestEncryptablePaymentIntent::from_encryptable(batch_encrypted_data) + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Failed while encrypting payment intent details")?; + let payment_intent_domain = hyperswitch_domain_models::payments::PaymentIntent::create_domain_model_from_request( payment_id, merchant_account, profile, request.clone(), - billing_address, - shipping_address, + encrypted_data, ) .await?; diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs index b09034e28cb3..6721d5395134 100644 --- a/crates/router/src/core/payments/transformers.rs +++ b/crates/router/src/core/payments/transformers.rs @@ -943,11 +943,13 @@ where billing: payment_intent .billing_address .clone() - .map(|billing| billing.into_inner().expose()), + .map(|billing| billing.into_inner()) + .map(From::from), shipping: payment_intent .shipping_address .clone() - .map(|shipping| shipping.into_inner().expose()), + .map(|shipping| shipping.into_inner()) + .map(From::from), customer_id: payment_intent.customer_id.clone(), customer_present: payment_intent.customer_present.clone(), description: payment_intent.description.clone(), From 7464faa3b486b3581e6b874a128339549ad457a9 Mon Sep 17 00:00:00 2001 From: Narayan Bhat Date: Sun, 17 Nov 2024 17:12:29 +0530 Subject: [PATCH 04/19] refactor: fix operation macro and batch encrypt pa --- .../src/payments/payment_attempt.rs | 72 ++++++++++++------- .../operations/payment_confirm_intent.rs | 30 +++++++- .../src/macros/to_encryptable.rs | 16 +++-- 3 files changed, 84 insertions(+), 34 deletions(-) diff --git a/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs b/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs index db3ae20177c9..92b2a03e5010 100644 --- a/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs +++ b/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs @@ -1,6 +1,11 @@ #[cfg(all(feature = "v1", feature = "olap"))] use api_models::enums::Connector; use common_enums as storage_enums; +#[cfg(feature = "v2")] +use common_utils::{ + crypto::Encryptable, encryption::Encryption, ext_traits::ValueExt, + types::keymanager::ToEncryptable, +}; use common_utils::{ errors::{CustomResult, ValidationError}, id_type, pii, @@ -18,19 +23,23 @@ use error_stack::ResultExt; #[cfg(feature = "v2")] use masking::PeekInterface; use masking::Secret; +#[cfg(feature = "v2")] +use rustc_hash::FxHashMap; use serde::{Deserialize, Serialize}; +#[cfg(feature = "v2")] +use serde_json::Value; use time::PrimitiveDateTime; #[cfg(all(feature = "v1", feature = "olap"))] use super::PaymentIntent; #[cfg(feature = "v2")] -use crate::merchant_key_store::MerchantKeyStore; -#[cfg(feature = "v2")] -use crate::router_response_types; +use crate::{address::Address, merchant_key_store::MerchantKeyStore, router_response_types}; use crate::{ behaviour, errors, mandates::{MandateDataType, MandateDetails}, - router_request_types, ForeignIDRef, + router_request_types, + type_encryption::{crypto_operation, CryptoOperation}, + ForeignIDRef, }; #[async_trait::async_trait] @@ -212,7 +221,7 @@ pub struct ErrorDetails { /// Few fields which are related are grouped together for better readability and understandability. /// These fields will be flattened and stored in the database in individual columns #[cfg(feature = "v2")] -#[derive(Clone, Debug, PartialEq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, serde::Serialize, router_derive::ToEncryption)] pub struct PaymentAttempt { /// Payment id for the payment attempt pub payment_id: id_type::GlobalPaymentId, @@ -249,7 +258,6 @@ pub struct PaymentAttempt { pub connector_metadata: Option, pub payment_experience: Option, /// The insensitive data of the payment method data is stored here - // TODO: evaluate what details should be stored here. Use a domain type instead of serde_json::Value pub payment_method_data: Option, /// The result of the routing algorithm. /// This will store the list of connectors and other related information that was used to route the payment. @@ -296,8 +304,8 @@ pub struct PaymentAttempt { /// A reference to the payment at connector side. This is returned by the connector pub external_reference_id: Option, /// The billing address for the payment method - // TODO: use a type here instead of value - pub payment_method_billing_address: common_utils::crypto::OptionalEncryptableValue, + #[encrypt(ty = Value)] + pub payment_method_billing_address: Option>, /// The global identifier for the payment attempt pub id: id_type::GlobalAttemptId, /// The connector mandate details which are stored temporarily @@ -354,6 +362,7 @@ impl PaymentAttempt { cell_id: id_type::CellId, storage_scheme: storage_enums::MerchantStorageScheme, request: &api_models::payments::PaymentsConfirmIntentRequest, + encrypted_data: DecryptedPaymentAttempt, ) -> CustomResult { let id = id_type::GlobalAttemptId::generate(&cell_id); let intent_amount_details = payment_intent.amount_details.clone(); @@ -1744,13 +1753,39 @@ impl behaviour::Conversion for PaymentAttempt { where Self: Sized, { - use crate::type_encryption; - async { let connector_payment_id = storage_model .get_optional_connector_transaction_id() .cloned(); + let decrypted_data = crypto_operation( + state, + common_utils::type_name!(Self::DstType), + CryptoOperation::BatchDecrypt(EncryptedPaymentAttempt::to_encryptable( + EncryptedPaymentAttempt { + payment_method_billing_address: storage_model + .payment_method_billing_address, + }, + )), + key_manager_identifier, + key.peek(), + ) + .await + .and_then(|val| val.try_into_batchoperation())?; + + let decrypted_data = EncryptedPaymentAttempt::from_encryptable(decrypted_data) + .change_context(common_utils::errors::CryptoError::DecodingFailed) + .attach_printable("Invalid batch operation data")?; + + let payment_method_billing_address = decrypted_data + .payment_method_billing_address + .map(|billing| { + billing.deserialize_inner_value(|value| value.parse_value("Address")) + }) + .transpose() + .change_context(common_utils::errors::CryptoError::DecodingFailed) + .attach_printable("Error while deserializing Address")?; + let amount_details = AttemptAmountDetails { net_amount: storage_model.net_amount, tax_on_surcharge: storage_model.tax_on_surcharge, @@ -1761,18 +1796,6 @@ impl behaviour::Conversion for PaymentAttempt { amount_to_capture: storage_model.amount_to_capture, }; - let inner_decrypt = |inner| async { - type_encryption::crypto_operation( - state, - common_utils::type_name!(Self::DstType), - type_encryption::CryptoOperation::DecryptOptional(inner), - key_manager_identifier.clone(), - key.peek(), - ) - .await - .and_then(|val| val.try_into_optionaloperation()) - }; - let error = storage_model .error_code .zip(storage_model.error_message) @@ -1827,10 +1850,7 @@ impl behaviour::Conversion for PaymentAttempt { authentication_applied: storage_model.authentication_applied, external_reference_id: storage_model.external_reference_id, connector: storage_model.connector, - payment_method_billing_address: inner_decrypt( - storage_model.payment_method_billing_address, - ) - .await?, + payment_method_billing_address, connector_mandate_detail: storage_model.connector_mandate_detail, }) } diff --git a/crates/router/src/core/payments/operations/payment_confirm_intent.rs b/crates/router/src/core/payments/operations/payment_confirm_intent.rs index 0a03fc741f02..5965bdc88503 100644 --- a/crates/router/src/core/payments/operations/payment_confirm_intent.rs +++ b/crates/router/src/core/payments/operations/payment_confirm_intent.rs @@ -4,8 +4,10 @@ use api_models::{ payments::{ExtendedCardInfo, GetAddressFromPaymentMethodData, PaymentsConfirmIntentRequest}, }; use async_trait::async_trait; +use common_utils::{ext_traits::Encode, types::keymanager::ToEncryptable}; use error_stack::ResultExt; use hyperswitch_domain_models::payments::PaymentConfirmData; +use masking::PeekInterface; use router_env::{instrument, tracing}; use tracing_futures::Instrument; @@ -26,7 +28,7 @@ use crate::{ types::{ self, api::{self, ConnectorCallType, PaymentIdTypeExt}, - domain::{self}, + domain::{self, types as domain_types}, storage::{self, enums as storage_enums}, }, utils::{self, OptionExt}, @@ -176,12 +178,36 @@ impl GetTracker, PaymentsConfirmIntent let cell_id = state.conf.cell_information.id.clone(); + let batch_encrypted_data = domain_types::crypto_operation( + key_manager_state, + common_utils::type_name!(hyperswitch_domain_models::payments::payment_attempt::PaymentAttempt), + domain_types::CryptoOperation::BatchEncrypt( + hyperswitch_domain_models::payments::payment_attempt::FromRequestEncryptablePaymentAttempt::to_encryptable( + hyperswitch_domain_models::payments::payment_attempt::FromRequestEncryptablePaymentAttempt { + payment_method_billing_address: request.payment_method_data.billing.as_ref().map(|address| address.clone().encode_to_value()).transpose().change_context(errors::ApiErrorResponse::InternalServerError).attach_printable("Failed to encode payment_method_billing address")?.map(masking::Secret::new), + }, + ), + ), + common_utils::types::keymanager::Identifier::Merchant(merchant_account.get_id().to_owned()), + key_store.key.peek(), + ) + .await + .and_then(|val| val.try_into_batchoperation()) + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Failed while encrypting payment intent details".to_string())?; + + let encrypted_data = + hyperswitch_domain_models::payments::payment_attempt::FromRequestEncryptablePaymentAttempt::from_encryptable(batch_encrypted_data) + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Failed while encrypting payment intent details")?; + let payment_attempt_domain_model = hyperswitch_domain_models::payments::payment_attempt::PaymentAttempt::create_domain_model( &payment_intent, cell_id, storage_scheme, - request + request, + encrypted_data ) .await?; diff --git a/crates/router_derive/src/macros/to_encryptable.rs b/crates/router_derive/src/macros/to_encryptable.rs index dfcfb72169b3..561c3a723719 100644 --- a/crates/router_derive/src/macros/to_encryptable.rs +++ b/crates/router_derive/src/macros/to_encryptable.rs @@ -242,13 +242,17 @@ fn generate_to_encryptable( let inner_types = get_field_and_inner_types(&fields); - let inner_type = inner_types.first().map(|(_, ty)| ty).ok_or_else(|| { + let inner_type = inner_types.first().ok_or_else(|| { syn::Error::new( proc_macro2::Span::call_site(), "Please use the macro with attribute #[encrypt] on the fields you want to encrypt", ) })?; + let provided_ty = get_encryption_ty_meta(&inner_type.0) + .map(|ty| ty.value.clone()) + .unwrap_or(inner_type.1.clone()); + let structs = struct_types.iter().map(|(prefix, struct_type)| { let name = format_ident!("{}{}", prefix, struct_name); let temp_fields = struct_type.generate_struct_fields(&inner_types); @@ -275,15 +279,15 @@ fn generate_to_encryptable( let decrypted_name = format_ident!("Decrypted{}", struct_name); ( quote! { #decrypted_name }, - quote! { Secret<#inner_type> }, - quote! { Secret<#inner_type> }, + quote! { Secret<#provided_ty> }, + quote! { Secret<#provided_ty> }, ) } StructType::Encrypted => { let decrypted_name = format_ident!("Decrypted{}", struct_name); ( quote! { #decrypted_name }, - quote! { Secret<#inner_type> }, + quote! { Secret<#provided_ty> }, quote! { Encryption }, ) } @@ -291,8 +295,8 @@ fn generate_to_encryptable( let decrypted_update_name = format_ident!("DecryptedUpdate{}", struct_name); ( quote! { #decrypted_update_name }, - quote! { Secret<#inner_type> }, - quote! { Secret<#inner_type> }, + quote! { Secret<#provided_ty> }, + quote! { Secret<#provided_ty> }, ) } //Unreachable statement From 19462aec853f94c979c24fe010e320b002566817 Mon Sep 17 00:00:00 2001 From: Narayan Bhat Date: Sun, 17 Nov 2024 17:13:50 +0530 Subject: [PATCH 05/19] chore: cargo clippy_v2 --- .../hyperswitch_domain_models/src/payments/payment_attempt.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs b/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs index 92b2a03e5010..7cb6c4bf3ed3 100644 --- a/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs +++ b/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs @@ -262,7 +262,7 @@ pub struct PaymentAttempt { /// The result of the routing algorithm. /// This will store the list of connectors and other related information that was used to route the payment. // TODO: change this to type instead of serde_json::Value - pub routing_result: Option, + pub routing_result: Option, pub preprocessing_step_id: Option, /// Number of captures that have happened for the payment attempt pub multiple_capture_count: Option, From 487a682ec9c7ab2e8eb4677916e9013c88e2786d Mon Sep 17 00:00:00 2001 From: Narayan Bhat Date: Sun, 17 Nov 2024 18:52:16 +0530 Subject: [PATCH 06/19] refactor: change address to domain address --- .../src/connectors/dlocal/transformers.rs | 5 +- .../src/connectors/mollie/transformers.rs | 2 +- .../src/connectors/shift4/transformers.rs | 4 +- .../src/connectors/worldline/transformers.rs | 17 ++++--- .../src/connectors/worldpay/transformers.rs | 11 +++-- crates/hyperswitch_connectors/src/utils.rs | 3 +- .../src/payment_address.rs | 2 +- .../src/router_request_types.rs | 5 +- .../router_request_types/authentication.rs | 6 +-- .../src/connector/adyen/transformers.rs | 14 ++++-- .../connector/bankofamerica/transformers.rs | 2 +- .../src/connector/bluesnap/transformers.rs | 2 +- .../src/connector/cybersource/transformers.rs | 11 +++-- .../src/connector/gocardless/transformers.rs | 7 +-- .../src/connector/klarna/transformers.rs | 2 +- .../connector/netcetera/netcetera_types.rs | 16 +++--- .../src/connector/paypal/transformers.rs | 4 +- .../connector/riskified/transformers/api.rs | 6 ++- crates/router/src/connector/utils.rs | 49 ++++++++++++------- .../src/connector/wellsfargo/transformers.rs | 6 ++- .../router/src/connector/wise/transformers.rs | 4 +- crates/router/src/core/authentication.rs | 4 +- .../src/core/authentication/transformers.rs | 4 +- crates/router/src/core/payments.rs | 10 ++-- crates/router/tests/connectors/dlocal.rs | 2 +- 25 files changed, 116 insertions(+), 82 deletions(-) diff --git a/crates/hyperswitch_connectors/src/connectors/dlocal/transformers.rs b/crates/hyperswitch_connectors/src/connectors/dlocal/transformers.rs index d5a7f981a1b1..433308059ae9 100644 --- a/crates/hyperswitch_connectors/src/connectors/dlocal/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/dlocal/transformers.rs @@ -1,4 +1,3 @@ -use api_models::payments::AddressDetails; use common_enums::enums; use common_utils::{pii::Email, request::Method}; use error_stack::ResultExt; @@ -182,7 +181,9 @@ impl TryFrom<&DlocalRouterData<&types::PaymentsAuthorizeRouterData>> for DlocalP } } -fn get_payer_name(address: &AddressDetails) -> Option> { +fn get_payer_name( + address: &hyperswitch_domain_models::address::AddressDetails, +) -> Option> { let first_name = address .first_name .clone() diff --git a/crates/hyperswitch_connectors/src/connectors/mollie/transformers.rs b/crates/hyperswitch_connectors/src/connectors/mollie/transformers.rs index cef3d684e7b0..bbfa0598cfa1 100644 --- a/crates/hyperswitch_connectors/src/connectors/mollie/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/mollie/transformers.rs @@ -354,7 +354,7 @@ fn get_billing_details( } fn get_address_details( - address: Option<&api_models::payments::AddressDetails>, + address: Option<&hyperswitch_domain_models::address::AddressDetails>, ) -> Result, Error> { let address_details = match address { Some(address) => { diff --git a/crates/hyperswitch_connectors/src/connectors/shift4/transformers.rs b/crates/hyperswitch_connectors/src/connectors/shift4/transformers.rs index 540bcaebaaeb..a336696c2a50 100644 --- a/crates/hyperswitch_connectors/src/connectors/shift4/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/shift4/transformers.rs @@ -555,7 +555,9 @@ where } } -fn get_address_details(address_details: Option<&AddressDetails>) -> Option
{ +fn get_address_details( + address_details: Option<&hyperswitch_domain_models::address::AddressDetails>, +) -> Option
{ address_details.map(|address| Address { line1: address.line1.clone(), line2: address.line1.clone(), diff --git a/crates/hyperswitch_connectors/src/connectors/worldline/transformers.rs b/crates/hyperswitch_connectors/src/connectors/worldline/transformers.rs index 89ee8d1b29b6..673d6045bc1b 100644 --- a/crates/hyperswitch_connectors/src/connectors/worldline/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/worldline/transformers.rs @@ -418,15 +418,18 @@ fn make_bank_redirect_request( } fn get_address( - billing: &payments::Address, -) -> Option<(&payments::Address, &payments::AddressDetails)> { + billing: &hyperswitch_domain_models::address::Address, +) -> Option<( + &hyperswitch_domain_models::address::Address, + &hyperswitch_domain_models::address::AddressDetails, +)> { let address = billing.address.as_ref()?; address.country.as_ref()?; Some((billing, address)) } fn build_customer_info( - billing_address: &payments::Address, + billing_address: &hyperswitch_domain_models::address::Address, email: &Option, ) -> Result> { let (billing, address) = @@ -454,8 +457,8 @@ fn build_customer_info( }) } -impl From for BillingAddress { - fn from(value: payments::AddressDetails) -> Self { +impl From for BillingAddress { + fn from(value: hyperswitch_domain_models::address::AddressDetails) -> Self { Self { city: value.city, country_code: value.country, @@ -466,8 +469,8 @@ impl From for BillingAddress { } } -impl From for Shipping { - fn from(value: payments::AddressDetails) -> Self { +impl From for Shipping { + fn from(value: hyperswitch_domain_models::address::AddressDetails) -> Self { Self { city: value.city, country_code: value.country, diff --git a/crates/hyperswitch_connectors/src/connectors/worldpay/transformers.rs b/crates/hyperswitch_connectors/src/connectors/worldpay/transformers.rs index fba589a48955..d041b3b4b814 100644 --- a/crates/hyperswitch_connectors/src/connectors/worldpay/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/worldpay/transformers.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; -use api_models::payments::{Address, MandateIds, MandateReferenceId}; +use api_models::payments::{MandateIds, MandateReferenceId}; use base64::Engine; use common_enums::enums; use common_utils::{ @@ -8,6 +8,7 @@ use common_utils::{ }; use error_stack::ResultExt; use hyperswitch_domain_models::{ + address, payment_method_data::{PaymentMethodData, WalletData}, router_data::{ConnectorAuthType, ErrorResponse, RouterData}, router_flow_types::{Authorize, SetupMandate}, @@ -70,7 +71,7 @@ impl TryFrom> for WorldpayConnectorMetadataObject fn fetch_payment_instrument( payment_method: PaymentMethodData, - billing_address: Option<&Address>, + billing_address: Option<&address::Address>, mandate_ids: Option, ) -> CustomResult { match payment_method { @@ -232,7 +233,7 @@ trait WorldpayPaymentsRequestData { fn get_off_session(&self) -> Option; fn get_mandate_id(&self) -> Option; fn get_currency(&self) -> enums::Currency; - fn get_optional_billing_address(&self) -> Option<&Address>; + fn get_optional_billing_address(&self) -> Option<&address::Address>; fn get_connector_meta_data(&self) -> Option<&pii::SecretSerdeValue>; fn get_payment_method(&self) -> enums::PaymentMethod; fn get_payment_method_type(&self) -> Option; @@ -278,7 +279,7 @@ impl WorldpayPaymentsRequestData self.request.currency } - fn get_optional_billing_address(&self) -> Option<&Address> { + fn get_optional_billing_address(&self) -> Option<&address::Address> { self.get_optional_billing() } @@ -338,7 +339,7 @@ impl WorldpayPaymentsRequestData self.request.currency } - fn get_optional_billing_address(&self) -> Option<&Address> { + fn get_optional_billing_address(&self) -> Option<&address::Address> { self.get_optional_billing() } diff --git a/crates/hyperswitch_connectors/src/utils.rs b/crates/hyperswitch_connectors/src/utils.rs index 14596c0f2a21..77d014ef605f 100644 --- a/crates/hyperswitch_connectors/src/utils.rs +++ b/crates/hyperswitch_connectors/src/utils.rs @@ -1,6 +1,6 @@ use std::collections::{HashMap, HashSet}; -use api_models::payments::{self, Address, AddressDetails, PhoneDetails}; +use api_models::payments; use base64::Engine; use common_enums::{ enums, @@ -16,6 +16,7 @@ use common_utils::{ }; use error_stack::{report, ResultExt}; use hyperswitch_domain_models::{ + address::{Address, AddressDetails, PhoneDetails}, payment_method_data::{Card, PaymentMethodData}, router_data::{ ApplePayPredecryptData, ErrorResponse, PaymentMethodToken, RecurringMandatePaymentData, diff --git a/crates/hyperswitch_domain_models/src/payment_address.rs b/crates/hyperswitch_domain_models/src/payment_address.rs index 548dd0c54166..176bef0c88bb 100644 --- a/crates/hyperswitch_domain_models/src/payment_address.rs +++ b/crates/hyperswitch_domain_models/src/payment_address.rs @@ -1,4 +1,4 @@ -use api_models::payments::Address; +use crate::address::Address; #[derive(Clone, Default, Debug)] pub struct PaymentAddress { diff --git a/crates/hyperswitch_domain_models/src/router_request_types.rs b/crates/hyperswitch_domain_models/src/router_request_types.rs index c645d0b4b532..d56926723ff7 100644 --- a/crates/hyperswitch_domain_models/src/router_request_types.rs +++ b/crates/hyperswitch_domain_models/src/router_request_types.rs @@ -1,6 +1,6 @@ pub mod authentication; pub mod fraud_check; -use api_models::payments::{AdditionalPaymentData, Address, RequestSurchargeDetails}; +use api_models::payments::{AdditionalPaymentData, RequestSurchargeDetails}; use common_utils::{ consts, errors, ext_traits::OptionExt, @@ -15,6 +15,7 @@ use serde_with::serde_as; use super::payment_method_data::PaymentMethodData; use crate::{ + address, errors::api_error_response::ApiErrorResponse, mandates, payments, router_data::{self, RouterData}, @@ -835,7 +836,7 @@ pub struct PaymentsTaxCalculationData { pub currency: storage_enums::Currency, pub shipping_cost: Option, pub order_details: Option>, - pub shipping_address: Address, + pub shipping_address: address::Address, } #[derive(Debug, Clone, Default)] diff --git a/crates/hyperswitch_domain_models/src/router_request_types/authentication.rs b/crates/hyperswitch_domain_models/src/router_request_types/authentication.rs index ab36deb425f5..067c6042ec20 100644 --- a/crates/hyperswitch_domain_models/src/router_request_types/authentication.rs +++ b/crates/hyperswitch_domain_models/src/router_request_types/authentication.rs @@ -4,7 +4,7 @@ use error_stack::{Report, ResultExt}; use serde::{Deserialize, Serialize}; use crate::{ - errors::api_error_response::ApiErrorResponse, payment_method_data::PaymentMethodData, + address, errors::api_error_response::ApiErrorResponse, payment_method_data::PaymentMethodData, router_request_types::BrowserInformation, }; @@ -77,8 +77,8 @@ pub struct PreAuthNRequestData { #[derive(Clone, Debug)] pub struct ConnectorAuthenticationRequestData { pub payment_method_data: PaymentMethodData, - pub billing_address: api_models::payments::Address, - pub shipping_address: Option, + pub billing_address: address::Address, + pub shipping_address: Option, pub browser_details: Option, pub amount: Option, pub currency: Option, diff --git a/crates/router/src/connector/adyen/transformers.rs b/crates/router/src/connector/adyen/transformers.rs index ec97b6ebad54..f73eabe3b3b1 100644 --- a/crates/router/src/connector/adyen/transformers.rs +++ b/crates/router/src/connector/adyen/transformers.rs @@ -1757,7 +1757,7 @@ fn get_amount_data(item: &AdyenRouterData<&types::PaymentsAuthorizeRouterData>) } pub fn get_address_info( - address: Option<&payments::Address>, + address: Option<&hyperswitch_domain_models::address::Address>, ) -> Option>> { address.and_then(|add| { add.address.as_ref().map( @@ -1819,7 +1819,9 @@ fn get_telephone_number(item: &types::PaymentsAuthorizeRouterData) -> Option) -> Option { +fn get_shopper_name( + address: Option<&hyperswitch_domain_models::address::Address>, +) -> Option { let billing = address.and_then(|billing| billing.address.as_ref()); Some(ShopperName { first_name: billing.and_then(|a| a.first_name.clone()), @@ -1827,7 +1829,9 @@ fn get_shopper_name(address: Option<&payments::Address>) -> Option }) } -fn get_country_code(address: Option<&payments::Address>) -> Option { +fn get_country_code( + address: Option<&hyperswitch_domain_models::address::Address>, +) -> Option { address.and_then(|billing| billing.address.as_ref().and_then(|address| address.country)) } @@ -4824,7 +4828,7 @@ impl TryFrom<&AdyenRouterData<&types::PayoutsRouterData>> for AdyenPayoutC })?, }; let bank_data = PayoutBankData { bank: bank_details }; - let address: &payments::AddressDetails = item.router_data.get_billing_address()?; + let address = item.router_data.get_billing_address()?; Ok(Self { amount: Amount { value: item.amount.to_owned(), @@ -4866,7 +4870,7 @@ impl TryFrom<&AdyenRouterData<&types::PayoutsRouterData>> for AdyenPayoutC })? } }; - let address: &payments::AddressDetails = item.router_data.get_billing_address()?; + let address = item.router_data.get_billing_address()?; let payout_wallet = PayoutWalletData { selected_brand: PayoutBrand::Paypal, additional_data, diff --git a/crates/router/src/connector/bankofamerica/transformers.rs b/crates/router/src/connector/bankofamerica/transformers.rs index 1530cbd82f83..921be995514e 100644 --- a/crates/router/src/connector/bankofamerica/transformers.rs +++ b/crates/router/src/connector/bankofamerica/transformers.rs @@ -494,7 +494,7 @@ impl // } fn build_bill_to( - address_details: Option<&payments::Address>, + address_details: Option<&hyperswitch_domain_models::address::Address>, email: pii::Email, ) -> Result> { let default_address = BillTo { diff --git a/crates/router/src/connector/bluesnap/transformers.rs b/crates/router/src/connector/bluesnap/transformers.rs index 022512ea1c19..d3fc0779e255 100644 --- a/crates/router/src/connector/bluesnap/transformers.rs +++ b/crates/router/src/connector/bluesnap/transformers.rs @@ -1125,7 +1125,7 @@ pub enum BluesnapErrors { } fn get_card_holder_info( - address: &api::AddressDetails, + address: &hyperswitch_domain_models::address::AddressDetails, email: Email, ) -> CustomResult, errors::ConnectorError> { let first_name = address.get_first_name()?; diff --git a/crates/router/src/connector/cybersource/transformers.rs b/crates/router/src/connector/cybersource/transformers.rs index c9ebba4a10d8..e4bdc6990efd 100644 --- a/crates/router/src/connector/cybersource/transformers.rs +++ b/crates/router/src/connector/cybersource/transformers.rs @@ -1,9 +1,10 @@ use api_models::payments; #[cfg(feature = "payouts")] -use api_models::{ - payments::{AddressDetails, PhoneDetails}, - payouts::PayoutMethodData, -}; +use api_models::payouts::PayoutMethodData; + +#[cfg(feature = "payouts")] +use hyperswitch_domain_models::address::{AddressDetails, PhoneDetails}; + use base64::Engine; use common_enums::FutureUsage; use common_utils::{ @@ -1102,7 +1103,7 @@ impl // } fn build_bill_to( - address_details: Option<&payments::Address>, + address_details: Option<&hyperswitch_domain_models::address::Address>, email: pii::Email, ) -> Result> { let default_address = BillTo { diff --git a/crates/router/src/connector/gocardless/transformers.rs b/crates/router/src/connector/gocardless/transformers.rs index c5c34574433d..579bd77d4d63 100644 --- a/crates/router/src/connector/gocardless/transformers.rs +++ b/crates/router/src/connector/gocardless/transformers.rs @@ -1,7 +1,4 @@ -use api_models::{ - enums::{CountryAlpha2, UsStatesAbbreviation}, - payments::AddressDetails, -}; +use api_models::enums::{CountryAlpha2, UsStatesAbbreviation}; use common_utils::{ id_type, pii::{self, IpAddress}, @@ -105,7 +102,7 @@ impl TryFrom<&types::ConnectorCustomerRouterData> for GocardlessCustomerRequest } fn get_region( - address_details: &AddressDetails, + address_details: &hyperswitch_domain_models::address::AddressDetails, ) -> Result>, error_stack::Report> { match address_details.country { Some(CountryAlpha2::US) => { diff --git a/crates/router/src/connector/klarna/transformers.rs b/crates/router/src/connector/klarna/transformers.rs index 62a5cef0bcae..803dc4a428d2 100644 --- a/crates/router/src/connector/klarna/transformers.rs +++ b/crates/router/src/connector/klarna/transformers.rs @@ -218,7 +218,7 @@ impl TryFrom<&KlarnaRouterData<&types::PaymentsAuthorizeRouterData>> for KlarnaP } fn get_address_info( - address: Option<&payments::Address>, + address: Option<&hyperswitch_domain_models::address::Address>, ) -> Option>> { address.and_then(|add| { add.address.as_ref().map( diff --git a/crates/router/src/connector/netcetera/netcetera_types.rs b/crates/router/src/connector/netcetera/netcetera_types.rs index 2718fb3b238a..1fc38591d6e1 100644 --- a/crates/router/src/connector/netcetera/netcetera_types.rs +++ b/crates/router/src/connector/netcetera/netcetera_types.rs @@ -208,7 +208,7 @@ pub struct ThreeDSRequestorAuthenticationInformation { /// card to a wallet. /// /// This field is optional. The accepted values are: -/// +/// /// - 01 -> No preference /// - 02 -> No challenge requested /// - 03 -> Challenge requested: 3DS Requestor Preference @@ -686,15 +686,15 @@ pub struct Cardholder { impl TryFrom<( - api_models::payments::Address, - Option, + hyperswitch_domain_models::address::Address, + Option, )> for Cardholder { type Error = error_stack::Report; fn try_from( (billing_address, shipping_address): ( - api_models::payments::Address, - Option, + hyperswitch_domain_models::address::Address, + Option, ), ) -> Result { Ok(Self { @@ -801,9 +801,11 @@ pub struct PhoneNumber { subscriber: Option>, } -impl TryFrom for PhoneNumber { +impl TryFrom for PhoneNumber { type Error = error_stack::Report; - fn try_from(value: api_models::payments::PhoneDetails) -> Result { + fn try_from( + value: hyperswitch_domain_models::address::PhoneDetails, + ) -> Result { Ok(Self { country_code: Some(value.extract_country_code()?), subscriber: value.number, diff --git a/crates/router/src/connector/paypal/transformers.rs b/crates/router/src/connector/paypal/transformers.rs index ed8369607df7..d204ca24cb28 100644 --- a/crates/router/src/connector/paypal/transformers.rs +++ b/crates/router/src/connector/paypal/transformers.rs @@ -527,7 +527,9 @@ pub struct PaypalPaymentsRequest { payment_source: Option, } -fn get_address_info(payment_address: Option<&api_models::payments::Address>) -> Option
{ +fn get_address_info( + payment_address: Option<&hyperswitch_domain_models::address::Address>, +) -> Option
{ let address = payment_address.and_then(|payment_address| payment_address.address.as_ref()); match address { Some(address) => address.get_optional_country().map(|country| Address { diff --git a/crates/router/src/connector/riskified/transformers/api.rs b/crates/router/src/connector/riskified/transformers/api.rs index cfa183e9e833..803a9d84bedd 100644 --- a/crates/router/src/connector/riskified/transformers/api.rs +++ b/crates/router/src/connector/riskified/transformers/api.rs @@ -572,9 +572,11 @@ pub struct ErrorData { pub message: String, } -impl TryFrom<&api_models::payments::Address> for OrderAddress { +impl TryFrom<&hyperswitch_domain_models::address::Address> for OrderAddress { type Error = Error; - fn try_from(address_info: &api_models::payments::Address) -> Result { + fn try_from( + address_info: &hyperswitch_domain_models::address::Address, + ) -> Result { let address = address_info .clone() diff --git a/crates/router/src/connector/utils.rs b/crates/router/src/connector/utils.rs index 687edd5aa238..ab2f9cbb46be 100644 --- a/crates/router/src/connector/utils.rs +++ b/crates/router/src/connector/utils.rs @@ -79,14 +79,21 @@ impl AccessTokenRequestInfo for types::RefreshTokenRouterData { } pub trait RouterData { - fn get_billing(&self) -> Result<&api::Address, Error>; + fn get_billing(&self) -> Result<&hyperswitch_domain_models::address::Address, Error>; fn get_billing_country(&self) -> Result; - fn get_billing_phone(&self) -> Result<&api::PhoneDetails, Error>; + fn get_billing_phone(&self) + -> Result<&hyperswitch_domain_models::address::PhoneDetails, Error>; fn get_description(&self) -> Result; fn get_return_url(&self) -> Result; - fn get_billing_address(&self) -> Result<&api::AddressDetails, Error>; - fn get_shipping_address(&self) -> Result<&api::AddressDetails, Error>; - fn get_shipping_address_with_phone_number(&self) -> Result<&api::Address, Error>; + fn get_billing_address( + &self, + ) -> Result<&hyperswitch_domain_models::address::AddressDetails, Error>; + fn get_shipping_address( + &self, + ) -> Result<&hyperswitch_domain_models::address::AddressDetails, Error>; + fn get_shipping_address_with_phone_number( + &self, + ) -> Result<&hyperswitch_domain_models::address::Address, Error>; fn get_connector_meta(&self) -> Result; fn get_session_token(&self) -> Result; fn get_billing_first_name(&self) -> Result, Error>; @@ -112,8 +119,8 @@ pub trait RouterData { #[cfg(feature = "payouts")] fn get_quote_id(&self) -> Result; - fn get_optional_billing(&self) -> Option<&api::Address>; - fn get_optional_shipping(&self) -> Option<&api::Address>; + fn get_optional_billing(&self) -> Option<&hyperswitch_domain_models::address::Address>; + fn get_optional_shipping(&self) -> Option<&hyperswitch_domain_models::address::Address>; fn get_optional_shipping_line1(&self) -> Option>; fn get_optional_shipping_line2(&self) -> Option>; fn get_optional_shipping_city(&self) -> Option; @@ -191,7 +198,7 @@ pub fn get_unimplemented_payment_method_error_message(connector: &str) -> String } impl RouterData for types::RouterData { - fn get_billing(&self) -> Result<&api::Address, Error> { + fn get_billing(&self) -> Result<&hyperswitch_domain_models::address::Address, Error> { self.address .get_payment_method_billing() .ok_or_else(missing_field_err("billing")) @@ -207,18 +214,20 @@ impl RouterData for types::RouterData Result<&api::PhoneDetails, Error> { + fn get_billing_phone( + &self, + ) -> Result<&hyperswitch_domain_models::address::PhoneDetails, Error> { self.address .get_payment_method_billing() .and_then(|a| a.phone.as_ref()) .ok_or_else(missing_field_err("billing.phone")) } - fn get_optional_billing(&self) -> Option<&api::Address> { + fn get_optional_billing(&self) -> Option<&hyperswitch_domain_models::address::Address> { self.address.get_payment_method_billing() } - fn get_optional_shipping(&self) -> Option<&api::Address> { + fn get_optional_shipping(&self) -> Option<&hyperswitch_domain_models::address::Address> { self.address.get_shipping() } @@ -317,7 +326,9 @@ impl RouterData for types::RouterData Result<&api::AddressDetails, Error> { + fn get_billing_address( + &self, + ) -> Result<&hyperswitch_domain_models::address::AddressDetails, Error> { self.address .get_payment_method_billing() .as_ref() @@ -534,14 +545,18 @@ impl RouterData for types::RouterData Result<&api::AddressDetails, Error> { + fn get_shipping_address( + &self, + ) -> Result<&hyperswitch_domain_models::address::AddressDetails, Error> { self.address .get_shipping() .and_then(|a| a.address.as_ref()) .ok_or_else(missing_field_err("shipping.address")) } - fn get_shipping_address_with_phone_number(&self) -> Result<&api::Address, Error> { + fn get_shipping_address_with_phone_number( + &self, + ) -> Result<&hyperswitch_domain_models::address::Address, Error> { self.address .get_shipping() .ok_or_else(missing_field_err("shipping")) @@ -602,7 +617,7 @@ pub trait AddressData { fn get_optional_full_name(&self) -> Option>; } -impl AddressData for api::Address { +impl AddressData for hyperswitch_domain_models::address::Address { fn get_email(&self) -> Result { self.email.clone().ok_or_else(missing_field_err("email")) } @@ -1762,7 +1777,7 @@ pub trait PhoneDetailsData { fn extract_country_code(&self) -> Result; } -impl PhoneDetailsData for api::PhoneDetails { +impl PhoneDetailsData for hyperswitch_domain_models::address::PhoneDetails { fn get_country_code(&self) -> Result { self.country_code .clone() @@ -1811,7 +1826,7 @@ pub trait AddressDetailsData { fn get_optional_country(&self) -> Option; } -impl AddressDetailsData for api::AddressDetails { +impl AddressDetailsData for hyperswitch_domain_models::address::AddressDetails { fn get_first_name(&self) -> Result<&Secret, Error> { self.first_name .as_ref() diff --git a/crates/router/src/connector/wellsfargo/transformers.rs b/crates/router/src/connector/wellsfargo/transformers.rs index 3a2e35190e60..42ee4acadef1 100644 --- a/crates/router/src/connector/wellsfargo/transformers.rs +++ b/crates/router/src/connector/wellsfargo/transformers.rs @@ -802,7 +802,9 @@ impl } } -fn get_phone_number(item: Option<&payments::Address>) -> Option> { +fn get_phone_number( + item: Option<&hyperswitch_domain_models::address::Address>, +) -> Option> { item.as_ref() .and_then(|billing| billing.phone.as_ref()) .and_then(|phone| { @@ -816,7 +818,7 @@ fn get_phone_number(item: Option<&payments::Address>) -> Option> } fn build_bill_to( - address_details: Option<&payments::Address>, + address_details: Option<&hyperswitch_domain_models::address::Address>, email: pii::Email, ) -> Result> { let phone_number = get_phone_number(address_details); diff --git a/crates/router/src/connector/wise/transformers.rs b/crates/router/src/connector/wise/transformers.rs index 94849f2b1ca7..513a762bfd3c 100644 --- a/crates/router/src/connector/wise/transformers.rs +++ b/crates/router/src/connector/wise/transformers.rs @@ -306,7 +306,7 @@ pub enum WiseStatus { #[cfg(feature = "payouts")] fn get_payout_address_details( - address: Option<&api_models::payments::Address>, + address: Option<&hyperswitch_domain_models::address::Address>, ) -> Option { address.and_then(|add| { add.address.as_ref().map(|a| WiseAddressDetails { @@ -323,7 +323,7 @@ fn get_payout_address_details( #[cfg(feature = "payouts")] fn get_payout_bank_details( payout_method_data: PayoutMethodData, - address: Option<&api_models::payments::Address>, + address: Option<&hyperswitch_domain_models::address::Address>, entity_type: PayoutEntityType, ) -> Result { let wise_address_details = match get_payout_address_details(address) { diff --git a/crates/router/src/core/authentication.rs b/crates/router/src/core/authentication.rs index 29508b5c0f55..5672f1e39cb4 100644 --- a/crates/router/src/core/authentication.rs +++ b/crates/router/src/core/authentication.rs @@ -24,8 +24,8 @@ pub async fn perform_authentication( authentication_connector: String, payment_method_data: domain::PaymentMethodData, payment_method: common_enums::PaymentMethod, - billing_address: payments::Address, - shipping_address: Option, + billing_address: hyperswitch_domain_models::address::Address, + shipping_address: Option, browser_details: Option, merchant_connector_account: payments_core::helpers::MerchantConnectorAccountType, amount: Option, diff --git a/crates/router/src/core/authentication/transformers.rs b/crates/router/src/core/authentication/transformers.rs index 6b8a378a0701..201c4cf2a6da 100644 --- a/crates/router/src/core/authentication/transformers.rs +++ b/crates/router/src/core/authentication/transformers.rs @@ -28,8 +28,8 @@ pub fn construct_authentication_router_data( authentication_connector: String, payment_method_data: domain::PaymentMethodData, payment_method: PaymentMethod, - billing_address: payments::Address, - shipping_address: Option, + billing_address: hyperswitch_domain_models::address::Address, + shipping_address: Option, browser_details: Option, amount: Option, currency: Option, diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs index ed41650840a4..042f4fc3ccbf 100644 --- a/crates/router/src/core/payments.rs +++ b/crates/router/src/core/payments.rs @@ -6566,7 +6566,7 @@ pub trait OperationSessionGetters { fn get_currency(&self) -> storage_enums::Currency; fn get_amount(&self) -> api::Amount; fn get_payment_attempt_connector(&self) -> Option<&str>; - fn get_billing_address(&self) -> Option; + fn get_billing_address(&self) -> Option; fn get_payment_method_data(&self) -> Option<&domain::PaymentMethodData>; fn get_sessions_token(&self) -> Vec; fn get_token_data(&self) -> Option<&storage::PaymentTokenData>; @@ -6720,7 +6720,7 @@ impl OperationSessionGetters for PaymentData { self.payment_attempt.connector.as_deref() } - fn get_billing_address(&self) -> Option { + fn get_billing_address(&self) -> Option { self.address.get_payment_method_billing().cloned() } @@ -6962,7 +6962,7 @@ impl OperationSessionGetters for PaymentIntentData { todo!() } - fn get_billing_address(&self) -> Option { + fn get_billing_address(&self) -> Option { todo!() } @@ -7176,7 +7176,7 @@ impl OperationSessionGetters for PaymentConfirmData { todo!() } - fn get_billing_address(&self) -> Option { + fn get_billing_address(&self) -> Option { todo!() } @@ -7392,7 +7392,7 @@ impl OperationSessionGetters for PaymentStatusData { todo!() } - fn get_billing_address(&self) -> Option { + fn get_billing_address(&self) -> Option { todo!() } diff --git a/crates/router/tests/connectors/dlocal.rs b/crates/router/tests/connectors/dlocal.rs index 62278d30ca75..c8cb24486add 100644 --- a/crates/router/tests/connectors/dlocal.rs +++ b/crates/router/tests/connectors/dlocal.rs @@ -2,7 +2,7 @@ use std::str::FromStr; -use api_models::payments::Address; +use hyperswitch_domain_models::address::Address; use masking::Secret; use router::types::{self, api, domain, storage::enums, PaymentAddress}; From 73b5be9e10df1fe4b3e82f26a6337839629b698a Mon Sep 17 00:00:00 2001 From: Narayan Bhat Date: Mon, 18 Nov 2024 19:40:36 +0530 Subject: [PATCH 07/19] refactor: change address to domain address fix v1 errors --- crates/hyperswitch_domain_models/src/payments.rs | 1 - .../compatibility/stripe/payment_intents/types.rs | 9 +++++---- crates/router/src/core/payment_methods.rs | 5 +++-- .../payment_methods/surcharge_decision_configs.rs | 4 ++-- crates/router/src/core/payments.rs | 6 +++--- .../core/payments/operations/payment_confirm.rs | 3 ++- .../core/payments/operations/payment_create.rs | 3 ++- .../core/payments/operations/payment_response.rs | 2 +- .../core/payments/operations/tax_calculation.rs | 4 ++-- crates/router/src/core/payments/routing.rs | 4 +++- crates/router/src/core/payments/tokenization.rs | 2 +- crates/router/src/core/payments/transformers.rs | 15 ++++++++++++--- crates/router/src/core/payout_link.rs | 5 ++++- crates/router/src/core/payouts.rs | 9 +++++++-- crates/router/src/core/utils.rs | 2 +- crates/router/src/types/transformers.rs | 14 +++++++++----- 16 files changed, 57 insertions(+), 31 deletions(-) diff --git a/crates/hyperswitch_domain_models/src/payments.rs b/crates/hyperswitch_domain_models/src/payments.rs index 960f835b22a8..534a479cc4a5 100644 --- a/crates/hyperswitch_domain_models/src/payments.rs +++ b/crates/hyperswitch_domain_models/src/payments.rs @@ -1,7 +1,6 @@ #[cfg(feature = "v2")] use std::marker::PhantomData; -#[cfg(feature = "v2")] use common_utils::{ self, crypto::Encryptable, diff --git a/crates/router/src/compatibility/stripe/payment_intents/types.rs b/crates/router/src/compatibility/stripe/payment_intents/types.rs index 55516eeb3bcf..545c058ce1cd 100644 --- a/crates/router/src/compatibility/stripe/payment_intents/types.rs +++ b/crates/router/src/compatibility/stripe/payment_intents/types.rs @@ -321,9 +321,10 @@ impl TryFrom for payments::PaymentsRequest { let billing = pmd.billing_details.clone().map(payments::Address::from); let payment_method_data = match pmd.payment_method_details.as_ref() { Some(spmd) => Some(payments::PaymentMethodData::from(spmd.to_owned())), - None => { - get_pmd_based_on_payment_method_type(item.payment_method_types, billing.clone()) - } + None => get_pmd_based_on_payment_method_type( + item.payment_method_types, + billing.clone().map(From::from), + ), }; payments::PaymentMethodDataRequest { @@ -911,7 +912,7 @@ pub struct StripePaymentRetrieveBody { //To handle payment types that have empty payment method data fn get_pmd_based_on_payment_method_type( payment_method_type: Option, - billing_details: Option, + billing_details: Option, ) -> Option { match payment_method_type { Some(api_enums::PaymentMethodType::UpiIntent) => Some(payments::PaymentMethodData::Upi( diff --git a/crates/router/src/core/payment_methods.rs b/crates/router/src/core/payment_methods.rs index 932a4a26ee09..2a04b237136a 100644 --- a/crates/router/src/core/payment_methods.rs +++ b/crates/router/src/core/payment_methods.rs @@ -754,7 +754,7 @@ pub(crate) async fn get_payment_method_create_request( payment_method_type: Option, customer_id: &Option, billing_name: Option>, - payment_method_billing_address: Option<&api_models::payments::Address>, + payment_method_billing_address: Option<&hyperswitch_domain_models::address::Address>, ) -> RouterResult { match payment_method_data { Some(pm_data) => match payment_method { @@ -789,7 +789,8 @@ pub(crate) async fn get_payment_method_create_request( .map(|card_network| card_network.to_string()), client_secret: None, payment_method_data: None, - billing: payment_method_billing_address.cloned(), + //TODO: why are we using api model in router internally + billing: payment_method_billing_address.cloned().map(From::from), connector_mandate_details: None, network_transaction_id: None, }; diff --git a/crates/router/src/core/payment_methods/surcharge_decision_configs.rs b/crates/router/src/core/payment_methods/surcharge_decision_configs.rs index ca1cdf06768d..85aecc322749 100644 --- a/crates/router/src/core/payment_methods/surcharge_decision_configs.rs +++ b/crates/router/src/core/payment_methods/surcharge_decision_configs.rs @@ -122,7 +122,7 @@ pub async fn perform_surcharge_decision_management_for_payment_method_list( algorithm_ref: routing::RoutingAlgorithmRef, payment_attempt: &storage::PaymentAttempt, payment_intent: &storage::PaymentIntent, - billing_address: Option, + billing_address: Option, response_payment_method_types: &mut [api_models::payment_methods::ResponsePaymentMethodsEnabled], ) -> ConditionalConfigResult<( types::SurchargeMetadata, @@ -242,7 +242,7 @@ pub async fn perform_surcharge_decision_management_for_session_flow( algorithm_ref: routing::RoutingAlgorithmRef, payment_attempt: &storage::PaymentAttempt, payment_intent: &storage::PaymentIntent, - billing_address: Option, + billing_address: Option, payment_method_type_list: &Vec, ) -> ConditionalConfigResult { let mut surcharge_metadata = types::SurchargeMetadata::new(payment_attempt.attempt_id.clone()); diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs index 042f4fc3ccbf..274400e9d4e4 100644 --- a/crates/router/src/core/payments.rs +++ b/crates/router/src/core/payments.rs @@ -1219,7 +1219,7 @@ pub async fn call_surcharge_decision_management_for_session_flow( _business_profile: &domain::Profile, _payment_attempt: &storage::PaymentAttempt, _payment_intent: &storage::PaymentIntent, - _billing_address: Option, + _billing_address: Option, _session_connector_data: &[api::SessionConnectorData], ) -> RouterResult> { todo!() @@ -1233,7 +1233,7 @@ pub async fn call_surcharge_decision_management_for_session_flow( _business_profile: &domain::Profile, payment_attempt: &storage::PaymentAttempt, payment_intent: &storage::PaymentIntent, - billing_address: Option, + billing_address: Option, session_connector_data: &[api::SessionConnectorData], ) -> RouterResult> { if let Some(surcharge_amount) = payment_attempt.net_amount.get_surcharge_amount() { @@ -4134,7 +4134,7 @@ where #[derive(Clone, serde::Serialize, Debug)] pub struct TaxData { - pub shipping_details: api_models::payments::Address, + pub shipping_details: hyperswitch_domain_models::address::Address, pub payment_method_type: enums::PaymentMethodType, } diff --git a/crates/router/src/core/payments/operations/payment_confirm.rs b/crates/router/src/core/payments/operations/payment_confirm.rs index 9bbe7cca3912..c8b0f93ccce1 100644 --- a/crates/router/src/core/payments/operations/payment_confirm.rs +++ b/crates/router/src/core/payments/operations/payment_confirm.rs @@ -704,7 +704,8 @@ impl GetTracker, api::PaymentsRequest> for Pa .and_then(|pmd| pmd.payment_method_data.as_ref()) .and_then(|payment_method_data_billing| { payment_method_data_billing.get_billing_address() - }); + }) + .map(From::from); let unified_address = address.unify_with_payment_method_data_billing(payment_method_data_billing); diff --git a/crates/router/src/core/payments/operations/payment_create.rs b/crates/router/src/core/payments/operations/payment_create.rs index 1f0884fe3849..71bcfa932357 100644 --- a/crates/router/src/core/payments/operations/payment_create.rs +++ b/crates/router/src/core/payments/operations/payment_create.rs @@ -566,7 +566,8 @@ impl GetTracker, api::PaymentsRequest> for Pa .and_then(|pmd| pmd.payment_method_data.as_ref()) .and_then(|payment_method_data_billing| { payment_method_data_billing.get_billing_address() - }); + }) + .map(From::from); let unified_address = address.unify_with_payment_method_data_billing(payment_method_data_billing); diff --git a/crates/router/src/core/payments/operations/payment_response.rs b/crates/router/src/core/payments/operations/payment_response.rs index 8fb36764c970..6b3fe0cfd2ab 100644 --- a/crates/router/src/core/payments/operations/payment_response.rs +++ b/crates/router/src/core/payments/operations/payment_response.rs @@ -718,7 +718,7 @@ impl PostUpdateTracker, types::SdkPaymentsSessionUpd let shipping_address = payments_helpers::create_or_update_address_for_payment_by_request( db, - shipping_address.as_ref(), + shipping_address.map(From::from).as_ref(), payment_data.payment_intent.shipping_address_id.as_deref(), &payment_data.payment_intent.merchant_id, payment_data.payment_intent.customer_id.as_ref(), diff --git a/crates/router/src/core/payments/operations/tax_calculation.rs b/crates/router/src/core/payments/operations/tax_calculation.rs index 2d4054a60bed..c615e2eb1744 100644 --- a/crates/router/src/core/payments/operations/tax_calculation.rs +++ b/crates/router/src/core/payments/operations/tax_calculation.rs @@ -129,7 +129,7 @@ impl GetTracker, api::PaymentsDynamicTaxCalcu })?; let tax_data = payments::TaxData { - shipping_details: request.shipping.clone(), + shipping_details: request.shipping.clone().into(), payment_method_type: request.payment_method_type, }; @@ -403,7 +403,7 @@ impl UpdateTracker, api::PaymentsDynamicTaxCalculati let shipping_address = helpers::create_or_update_address_for_payment_by_request( state, - shipping_address.as_ref(), + shipping_address.map(From::from).as_ref(), payment_data.payment_intent.shipping_address_id.as_deref(), &payment_data.payment_intent.merchant_id, payment_data.payment_intent.customer_id.as_ref(), diff --git a/crates/router/src/core/payments/routing.rs b/crates/router/src/core/payments/routing.rs index 28321529ef2d..8cc210d2f46d 100644 --- a/crates/router/src/core/payments/routing.rs +++ b/crates/router/src/core/payments/routing.rs @@ -12,7 +12,6 @@ use api_models::routing as api_routing; use api_models::{ admin as admin_api, enums::{self as api_enums, CountryAlpha2}, - payments::Address, routing::ConnectorSelection, }; use diesel_models::enums as storage_enums; @@ -27,6 +26,9 @@ use euclid::{ use external_services::grpc_client::dynamic_routing::{ success_rate::CalSuccessRateResponse, SuccessBasedDynamicRouting, }; + +use hyperswitch_domain_models::address::Address; + use kgraph_utils::{ mca as mca_graph, transformers::{IntoContext, IntoDirValue}, diff --git a/crates/router/src/core/payments/tokenization.rs b/crates/router/src/core/payments/tokenization.rs index 6f01af96bb8e..cbb97941f3c2 100644 --- a/crates/router/src/core/payments/tokenization.rs +++ b/crates/router/src/core/payments/tokenization.rs @@ -78,7 +78,7 @@ pub async fn save_payment_method( payment_method_type: Option, key_store: &domain::MerchantKeyStore, billing_name: Option>, - payment_method_billing_address: Option<&api::Address>, + payment_method_billing_address: Option<&hyperswitch_domain_models::address::Address>, business_profile: &domain::Profile, mut original_connector_mandate_reference_id: Option, ) -> RouterResult diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs index 6721d5395134..41499a44310c 100644 --- a/crates/router/src/core/payments/transformers.rs +++ b/crates/router/src/core/payments/transformers.rs @@ -1453,7 +1453,8 @@ where billing: payment_data .get_address() .get_request_payment_method_billing() - .cloned(), + .cloned() + .map(From::from), }); let mut headers = connector_http_status_code @@ -1815,8 +1816,16 @@ where payment_method: payment_attempt.payment_method, payment_method_data: payment_method_data_response, payment_token: payment_attempt.payment_token, - shipping: payment_data.get_address().get_shipping().cloned(), - billing: payment_data.get_address().get_payment_billing().cloned(), + shipping: payment_data + .get_address() + .get_shipping() + .cloned() + .map(From::from), + billing: payment_data + .get_address() + .get_payment_billing() + .cloned() + .map(From::from), order_details: payment_intent.order_details, email: customer .as_ref() diff --git a/crates/router/src/core/payout_link.rs b/crates/router/src/core/payout_link.rs index 31e65e8e0a79..223db5b9f908 100644 --- a/crates/router/src/core/payout_link.rs +++ b/crates/router/src/core/payout_link.rs @@ -214,7 +214,10 @@ pub async fn initiate_payout_link( }); let required_field_override = api::RequiredFieldsOverrideRequest { - billing: address.as_ref().map(From::from), + billing: address + .as_ref() + .map(hyperswitch_domain_models::address::Address::from) + .map(From::from), }; let enabled_payment_methods_with_required_fields = ForeignFrom::foreign_from(( diff --git a/crates/router/src/core/payouts.rs b/crates/router/src/core/payouts.rs index adf3c51fd80b..d239638c0c60 100644 --- a/crates/router/src/core/payouts.rs +++ b/crates/router/src/core/payouts.rs @@ -852,7 +852,9 @@ pub async fn payouts_list_core( logger::warn!(?err, err_msg); }) .ok() - .map(payment_enums::Address::foreign_from) + .as_ref() + .map(hyperswitch_domain_models::address::Address::from) + .map(payment_enums::Address::from) }); pi_pa_tuple_vec.push(( @@ -2354,7 +2356,10 @@ pub async fn response_handler( let billing_address = payout_data.billing_address.to_owned(); let customer_details = payout_data.customer_details.to_owned(); let customer_id = payouts.customer_id; - let billing = billing_address.as_ref().map(From::from); + let billing = billing_address + .as_ref() + .map(hyperswitch_domain_models::address::Address::from) + .map(From::from); let translated_unified_message = helpers::get_translated_unified_code_and_message( state, diff --git a/crates/router/src/core/utils.rs b/crates/router/src/core/utils.rs index fea112bc3b8b..1853e6119388 100644 --- a/crates/router/src/core/utils.rs +++ b/crates/router/src/core/utils.rs @@ -108,7 +108,7 @@ pub async fn construct_payout_router_data<'a, F>( } }); - let address = PaymentAddress::new(None, billing_address, None, None); + let address = PaymentAddress::new(None, billing_address.map(From::from), None, None); let test_mode: Option = merchant_connector_account.is_test_mode_on(); let payouts = &payout_data.payouts; diff --git a/crates/router/src/types/transformers.rs b/crates/router/src/types/transformers.rs index c97084a22977..e04d5b1dfd16 100644 --- a/crates/router/src/types/transformers.rs +++ b/crates/router/src/types/transformers.rs @@ -706,7 +706,7 @@ impl<'a> ForeignFrom<&'a api_types::ConfigUpdate> for storage::ConfigUpdate { } } -impl<'a> From<&'a domain::Address> for api_types::Address { +impl<'a> From<&'a domain::Address> for hyperswitch_domain_models::address::Address { fn from(address: &domain::Address) -> Self { // If all the fields of address are none, then pass the address as None let address_details = if address.city.is_none() @@ -721,7 +721,7 @@ impl<'a> From<&'a domain::Address> for api_types::Address { { None } else { - Some(api_types::AddressDetails { + Some(hyperswitch_domain_models::address::AddressDetails { city: address.city.clone(), country: address.country, line1: address.line1.clone().map(Encryptable::into_inner), @@ -738,7 +738,7 @@ impl<'a> From<&'a domain::Address> for api_types::Address { let phone_details = if address.phone_number.is_none() && address.country_code.is_none() { None } else { - Some(api_types::PhoneDetails { + Some(hyperswitch_domain_models::address::PhoneDetails { number: address.phone_number.clone().map(Encryptable::into_inner), country_code: address.country_code.clone(), }) @@ -1596,7 +1596,9 @@ impl field_name: "customer_details", })?; - let mut billing_address = billing.map(api_types::Address::from); + let mut billing_address = billing + .map(hyperswitch_domain_models::address::Address::from) + .map(api_types::Address::from); // This change is to fix a merchant integration // If billing.email is not passed by the merchant, and if the customer email is present, then use the `customer.email` as the billing email @@ -1625,7 +1627,9 @@ impl Ok(Self { currency: payment_attempt.map(|pa| pa.currency.unwrap_or_default()), - shipping: shipping.map(api_types::Address::from), + shipping: shipping + .map(hyperswitch_domain_models::address::Address::from) + .map(api_types::Address::from), billing: billing_address, amount: payment_attempt .map(|pa| api_types::Amount::from(pa.net_amount.get_order_amount())), From 609f499065d68544845d6a2b7b1564638267863a Mon Sep 17 00:00:00 2001 From: Narayan Bhat Date: Tue, 19 Nov 2024 00:31:34 +0530 Subject: [PATCH 08/19] chore: fix errors in connector tests crate --- crates/router/tests/connectors/aci.rs | 3 ++- crates/router/tests/connectors/adyen.rs | 6 ++++-- crates/router/tests/connectors/airwallex.rs | 3 ++- crates/router/tests/connectors/bitpay.rs | 3 ++- crates/router/tests/connectors/bluesnap.rs | 3 ++- crates/router/tests/connectors/cashtocode.rs | 3 ++- crates/router/tests/connectors/coinbase.rs | 3 ++- crates/router/tests/connectors/cryptopay.rs | 3 ++- crates/router/tests/connectors/cybersource.rs | 3 ++- crates/router/tests/connectors/dlocal.rs | 3 ++- crates/router/tests/connectors/forte.rs | 3 ++- crates/router/tests/connectors/globalpay.rs | 3 ++- crates/router/tests/connectors/iatapay.rs | 3 ++- crates/router/tests/connectors/multisafepay.rs | 3 ++- crates/router/tests/connectors/opennode.rs | 3 ++- crates/router/tests/connectors/payeezy.rs | 3 ++- crates/router/tests/connectors/payme.rs | 3 ++- crates/router/tests/connectors/trustpay.rs | 3 ++- crates/router/tests/connectors/utils.rs | 3 ++- crates/router/tests/connectors/wise.rs | 3 ++- crates/router/tests/connectors/worldline.rs | 3 ++- 21 files changed, 44 insertions(+), 22 deletions(-) diff --git a/crates/router/tests/connectors/aci.rs b/crates/router/tests/connectors/aci.rs index 6f4855d1e22a..4d4053d17f73 100644 --- a/crates/router/tests/connectors/aci.rs +++ b/crates/router/tests/connectors/aci.rs @@ -96,7 +96,8 @@ fn construct_payment_router_data() -> types::PaymentsAuthorizeRouterData { country_code: Some("+351".to_string()), }), email: None, - }), + }) + .map(From::from), None, ), connector_meta_data: None, diff --git a/crates/router/tests/connectors/adyen.rs b/crates/router/tests/connectors/adyen.rs index 2e8d4ab6862a..59d27b1904e9 100644 --- a/crates/router/tests/connectors/adyen.rs +++ b/crates/router/tests/connectors/adyen.rs @@ -70,7 +70,8 @@ impl AdyenTest { country_code: Some("+351".to_string()), }), email: None, - }), + }) + .map(From::from), None, None, )), @@ -98,7 +99,8 @@ impl AdyenTest { }), phone: None, email: None, - }), + }) + .map(From::from), None, None, )), diff --git a/crates/router/tests/connectors/airwallex.rs b/crates/router/tests/connectors/airwallex.rs index f46a0cf7597f..a3daf2756652 100644 --- a/crates/router/tests/connectors/airwallex.rs +++ b/crates/router/tests/connectors/airwallex.rs @@ -63,7 +63,8 @@ fn get_default_payment_info() -> Option { }), phone: None, email: None, - }), + }) + .map(From::from), None, )), ..Default::default() diff --git a/crates/router/tests/connectors/bitpay.rs b/crates/router/tests/connectors/bitpay.rs index 43959fa683cb..58877786da25 100644 --- a/crates/router/tests/connectors/bitpay.rs +++ b/crates/router/tests/connectors/bitpay.rs @@ -56,7 +56,8 @@ fn get_default_payment_info() -> Option { country_code: Some("+91".to_string()), }), email: None, - }), + }) + .map(From::from), None, None, )), diff --git a/crates/router/tests/connectors/bluesnap.rs b/crates/router/tests/connectors/bluesnap.rs index 73799693d74b..07272084cf70 100644 --- a/crates/router/tests/connectors/bluesnap.rs +++ b/crates/router/tests/connectors/bluesnap.rs @@ -56,7 +56,8 @@ fn get_payment_info() -> Option { }), phone: None, email: None, - }), + }) + .map(From::from), None, None, )), diff --git a/crates/router/tests/connectors/cashtocode.rs b/crates/router/tests/connectors/cashtocode.rs index 7656cd67de51..5aa67b223db7 100644 --- a/crates/router/tests/connectors/cashtocode.rs +++ b/crates/router/tests/connectors/cashtocode.rs @@ -89,7 +89,8 @@ impl CashtocodeTest { }), phone: None, email: None, - }), + }) + .map(From::from), None, None, )), diff --git a/crates/router/tests/connectors/coinbase.rs b/crates/router/tests/connectors/coinbase.rs index 20be2e502baf..f00825f1f008 100644 --- a/crates/router/tests/connectors/coinbase.rs +++ b/crates/router/tests/connectors/coinbase.rs @@ -57,7 +57,8 @@ fn get_default_payment_info() -> Option { country_code: Some("+91".to_string()), }), email: None, - }), + }) + .map(From::from), None, None, )), diff --git a/crates/router/tests/connectors/cryptopay.rs b/crates/router/tests/connectors/cryptopay.rs index b5f57f7d6f5c..59ddd0199742 100644 --- a/crates/router/tests/connectors/cryptopay.rs +++ b/crates/router/tests/connectors/cryptopay.rs @@ -56,7 +56,8 @@ fn get_default_payment_info() -> Option { country_code: Some("+91".to_string()), }), email: None, - }), + }) + .map(From::from), None, None, )), diff --git a/crates/router/tests/connectors/cybersource.rs b/crates/router/tests/connectors/cybersource.rs index 0116b52f4edc..bbd1fb4f429f 100644 --- a/crates/router/tests/connectors/cybersource.rs +++ b/crates/router/tests/connectors/cybersource.rs @@ -53,7 +53,8 @@ fn get_default_payment_info() -> Option { country_code: Some("+91".to_string()), }), email: None, - }), + }) + .map(From::from), None, None, )), diff --git a/crates/router/tests/connectors/dlocal.rs b/crates/router/tests/connectors/dlocal.rs index c8cb24486add..e61ec14354fa 100644 --- a/crates/router/tests/connectors/dlocal.rs +++ b/crates/router/tests/connectors/dlocal.rs @@ -436,7 +436,8 @@ pub fn get_payment_info() -> PaymentInfo { state: None, first_name: None, last_name: None, - }), + }) + .map(From::from), email: None, }), None, diff --git a/crates/router/tests/connectors/forte.rs b/crates/router/tests/connectors/forte.rs index fa084fc4b2c7..0272da6e0621 100644 --- a/crates/router/tests/connectors/forte.rs +++ b/crates/router/tests/connectors/forte.rs @@ -70,7 +70,8 @@ fn get_default_payment_info() -> Option { country_code: Some("+91".to_string()), }), email: None, - }), + }) + .map(From::from), None, None, )), diff --git a/crates/router/tests/connectors/globalpay.rs b/crates/router/tests/connectors/globalpay.rs index 8879631d1e3d..ba6ffed1198a 100644 --- a/crates/router/tests/connectors/globalpay.rs +++ b/crates/router/tests/connectors/globalpay.rs @@ -66,7 +66,8 @@ impl Globalpay { }), phone: None, ..Default::default() - }), + }) + .map(From::from), None, None, )), diff --git a/crates/router/tests/connectors/iatapay.rs b/crates/router/tests/connectors/iatapay.rs index 577da6ce6852..193a371fd22d 100644 --- a/crates/router/tests/connectors/iatapay.rs +++ b/crates/router/tests/connectors/iatapay.rs @@ -73,7 +73,8 @@ fn get_default_payment_info() -> Option { country_code: Some("+91".to_string()), }), email: None, - }), + }) + .map(From::from), None, None, )), diff --git a/crates/router/tests/connectors/multisafepay.rs b/crates/router/tests/connectors/multisafepay.rs index 0d5af818c358..430a3f0c10b7 100644 --- a/crates/router/tests/connectors/multisafepay.rs +++ b/crates/router/tests/connectors/multisafepay.rs @@ -54,7 +54,8 @@ fn get_default_payment_info() -> Option { }), phone: None, email: None, - }), + }) + .map(From::from), None, None, )); diff --git a/crates/router/tests/connectors/opennode.rs b/crates/router/tests/connectors/opennode.rs index e8778f9f4233..fb997b20fac4 100644 --- a/crates/router/tests/connectors/opennode.rs +++ b/crates/router/tests/connectors/opennode.rs @@ -56,7 +56,8 @@ fn get_default_payment_info() -> Option { country_code: Some("+91".to_string()), }), email: None, - }), + }) + .map(From::from), None, None, )), diff --git a/crates/router/tests/connectors/payeezy.rs b/crates/router/tests/connectors/payeezy.rs index 1bc81ebfe257..3a904ca633b4 100644 --- a/crates/router/tests/connectors/payeezy.rs +++ b/crates/router/tests/connectors/payeezy.rs @@ -64,7 +64,8 @@ impl PayeezyTest { }), phone: None, email: None, - }), + }) + .map(From::from), None, None, )), diff --git a/crates/router/tests/connectors/payme.rs b/crates/router/tests/connectors/payme.rs index dbc3795e7f15..80d2c79ce1a8 100644 --- a/crates/router/tests/connectors/payme.rs +++ b/crates/router/tests/connectors/payme.rs @@ -59,7 +59,8 @@ fn get_default_payment_info() -> Option { }), phone: None, email: None, - }), + }) + .map(From::from), None, None, )), diff --git a/crates/router/tests/connectors/trustpay.rs b/crates/router/tests/connectors/trustpay.rs index bae62913a9a3..6685d863d6c9 100644 --- a/crates/router/tests/connectors/trustpay.rs +++ b/crates/router/tests/connectors/trustpay.rs @@ -82,7 +82,8 @@ fn get_default_payment_info() -> Option { }), phone: None, email: None, - }), + }) + .map(From::from), None, None, )), diff --git a/crates/router/tests/connectors/utils.rs b/crates/router/tests/connectors/utils.rs index 52218b211ac1..c7e60eea600f 100644 --- a/crates/router/tests/connectors/utils.rs +++ b/crates/router/tests/connectors/utils.rs @@ -86,7 +86,8 @@ impl PaymentInfo { }), phone: None, email: None, - }), + }) + .map(From::from), None, )), ..Default::default() diff --git a/crates/router/tests/connectors/wise.rs b/crates/router/tests/connectors/wise.rs index 984a43d48a76..846a78a55be1 100644 --- a/crates/router/tests/connectors/wise.rs +++ b/crates/router/tests/connectors/wise.rs @@ -65,7 +65,8 @@ impl WiseTest { }), phone: None, email: None, - }), + }) + .map(From::from), None, None, )), diff --git a/crates/router/tests/connectors/worldline.rs b/crates/router/tests/connectors/worldline.rs index 73e710eb2f19..871c0833586a 100644 --- a/crates/router/tests/connectors/worldline.rs +++ b/crates/router/tests/connectors/worldline.rs @@ -54,7 +54,8 @@ impl WorldlineTest { }), phone: None, email: None, - }), + }) + .map(From::from), None, None, )), From bb1b27cb440f72939b6f40f015632bb14fb56f2d Mon Sep 17 00:00:00 2001 From: Narayan Bhat Date: Tue, 19 Nov 2024 12:57:55 +0530 Subject: [PATCH 09/19] chore: cargo clippy --- crates/hyperswitch_domain_models/src/payments.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/hyperswitch_domain_models/src/payments.rs b/crates/hyperswitch_domain_models/src/payments.rs index 960f835b22a8..534a479cc4a5 100644 --- a/crates/hyperswitch_domain_models/src/payments.rs +++ b/crates/hyperswitch_domain_models/src/payments.rs @@ -1,7 +1,6 @@ #[cfg(feature = "v2")] use std::marker::PhantomData; -#[cfg(feature = "v2")] use common_utils::{ self, crypto::Encryptable, From b3cf0c7f801b7860fd19fc57da199abf527230b8 Mon Sep 17 00:00:00 2001 From: Narayan Bhat Date: Tue, 19 Nov 2024 13:26:48 +0530 Subject: [PATCH 10/19] chore: cargo clippy_v2 --- crates/hyperswitch_domain_models/src/payments.rs | 7 ++++++- .../src/payments/payment_attempt.rs | 7 ++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/crates/hyperswitch_domain_models/src/payments.rs b/crates/hyperswitch_domain_models/src/payments.rs index 534a479cc4a5..468a40e9a5aa 100644 --- a/crates/hyperswitch_domain_models/src/payments.rs +++ b/crates/hyperswitch_domain_models/src/payments.rs @@ -6,10 +6,13 @@ use common_utils::{ crypto::Encryptable, encryption::Encryption, errors::CustomResult, - ext_traits::ValueExt, id_type, pii, types::{keymanager::ToEncryptable, MinorUnit}, }; + +#[cfg(feature = "v2")] +use common_utils::ext_traits::ValueExt; + use diesel_models::payment_intent::TaxDetails; #[cfg(feature = "v2")] use error_stack::ResultExt; @@ -27,6 +30,8 @@ use common_enums as storage_enums; use diesel_models::types::{FeatureMetadata, OrderDetailsWithAmount}; use self::payment_attempt::PaymentAttempt; + +#[cfg(feature = "v1")] use crate::RemoteStorageObject; #[cfg(feature = "v2")] use crate::{ diff --git a/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs b/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs index 7cb6c4bf3ed3..3f07fa2d8dcd 100644 --- a/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs +++ b/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs @@ -37,11 +37,12 @@ use crate::{address::Address, merchant_key_store::MerchantKeyStore, router_respo use crate::{ behaviour, errors, mandates::{MandateDataType, MandateDetails}, - router_request_types, - type_encryption::{crypto_operation, CryptoOperation}, - ForeignIDRef, + router_request_types, ForeignIDRef, }; +#[cfg(feature = "v2")] +use crate::type_encryption::{crypto_operation, CryptoOperation}; + #[async_trait::async_trait] pub trait PaymentAttemptInterface { #[cfg(feature = "v1")] From c3de460821778a5f8f102c4aa42f2cc9aa9634e6 Mon Sep 17 00:00:00 2001 From: "hyperswitch-bot[bot]" <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Date: Tue, 19 Nov 2024 10:49:20 +0000 Subject: [PATCH 11/19] chore: run formatter --- crates/hyperswitch_domain_models/src/payments.rs | 7 ++----- .../src/payments/payment_attempt.rs | 5 ++--- crates/router/src/connector/cybersource/transformers.rs | 6 ++---- crates/router/src/core/payments/routing.rs | 2 -- 4 files changed, 6 insertions(+), 14 deletions(-) diff --git a/crates/hyperswitch_domain_models/src/payments.rs b/crates/hyperswitch_domain_models/src/payments.rs index 468a40e9a5aa..da9a161fb129 100644 --- a/crates/hyperswitch_domain_models/src/payments.rs +++ b/crates/hyperswitch_domain_models/src/payments.rs @@ -1,6 +1,8 @@ #[cfg(feature = "v2")] use std::marker::PhantomData; +#[cfg(feature = "v2")] +use common_utils::ext_traits::ValueExt; use common_utils::{ self, crypto::Encryptable, @@ -9,10 +11,6 @@ use common_utils::{ id_type, pii, types::{keymanager::ToEncryptable, MinorUnit}, }; - -#[cfg(feature = "v2")] -use common_utils::ext_traits::ValueExt; - use diesel_models::payment_intent::TaxDetails; #[cfg(feature = "v2")] use error_stack::ResultExt; @@ -30,7 +28,6 @@ use common_enums as storage_enums; use diesel_models::types::{FeatureMetadata, OrderDetailsWithAmount}; use self::payment_attempt::PaymentAttempt; - #[cfg(feature = "v1")] use crate::RemoteStorageObject; #[cfg(feature = "v2")] diff --git a/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs b/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs index 3f07fa2d8dcd..ad87e9bca8ec 100644 --- a/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs +++ b/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs @@ -33,6 +33,8 @@ use time::PrimitiveDateTime; #[cfg(all(feature = "v1", feature = "olap"))] use super::PaymentIntent; #[cfg(feature = "v2")] +use crate::type_encryption::{crypto_operation, CryptoOperation}; +#[cfg(feature = "v2")] use crate::{address::Address, merchant_key_store::MerchantKeyStore, router_response_types}; use crate::{ behaviour, errors, @@ -40,9 +42,6 @@ use crate::{ router_request_types, ForeignIDRef, }; -#[cfg(feature = "v2")] -use crate::type_encryption::{crypto_operation, CryptoOperation}; - #[async_trait::async_trait] pub trait PaymentAttemptInterface { #[cfg(feature = "v1")] diff --git a/crates/router/src/connector/cybersource/transformers.rs b/crates/router/src/connector/cybersource/transformers.rs index e4bdc6990efd..441b8490ca78 100644 --- a/crates/router/src/connector/cybersource/transformers.rs +++ b/crates/router/src/connector/cybersource/transformers.rs @@ -1,10 +1,6 @@ use api_models::payments; #[cfg(feature = "payouts")] use api_models::payouts::PayoutMethodData; - -#[cfg(feature = "payouts")] -use hyperswitch_domain_models::address::{AddressDetails, PhoneDetails}; - use base64::Engine; use common_enums::FutureUsage; use common_utils::{ @@ -13,6 +9,8 @@ use common_utils::{ types::SemanticVersion, }; use error_stack::ResultExt; +#[cfg(feature = "payouts")] +use hyperswitch_domain_models::address::{AddressDetails, PhoneDetails}; use masking::{ExposeInterface, PeekInterface, Secret}; use serde::{Deserialize, Serialize}; use serde_json::Value; diff --git a/crates/router/src/core/payments/routing.rs b/crates/router/src/core/payments/routing.rs index 8cc210d2f46d..83989f61fe78 100644 --- a/crates/router/src/core/payments/routing.rs +++ b/crates/router/src/core/payments/routing.rs @@ -26,9 +26,7 @@ use euclid::{ use external_services::grpc_client::dynamic_routing::{ success_rate::CalSuccessRateResponse, SuccessBasedDynamicRouting, }; - use hyperswitch_domain_models::address::Address; - use kgraph_utils::{ mca as mca_graph, transformers::{IntoContext, IntoDirValue}, From 1eb84e5b912169b1e591ba178a4004f63418f9ba Mon Sep 17 00:00:00 2001 From: Narayan Bhat Date: Wed, 20 Nov 2024 13:16:57 +0530 Subject: [PATCH 12/19] refactor: add a method to sessiongetters to get payment_method_billing --- .../hyperswitch_domain_models/src/address.rs | 33 ++++---- .../hyperswitch_domain_models/src/payments.rs | 4 +- crates/router/src/core/payments.rs | 75 ++++++++++++++++--- .../router/src/core/payments/transformers.rs | 26 +------ crates/router/src/types.rs | 4 + 5 files changed, 90 insertions(+), 52 deletions(-) diff --git a/crates/hyperswitch_domain_models/src/address.rs b/crates/hyperswitch_domain_models/src/address.rs index 85595c1ad9e3..e42dc2370cfc 100644 --- a/crates/hyperswitch_domain_models/src/address.rs +++ b/crates/hyperswitch_domain_models/src/address.rs @@ -11,15 +11,22 @@ impl masking::SerializableSecret for Address {} impl Address { /// Unify the address, giving priority to `self` when details are present in both - pub fn unify_address(self, other: Option<&Self>) -> Self { + pub fn unify_address(&self, other: Option<&Self>) -> Self { let other_address_details = other.and_then(|address| address.address.as_ref()); Self { address: self .address + .as_ref() .map(|address| address.unify_address_details(other_address_details)) .or(other_address_details.cloned()), - email: self.email.or(other.and_then(|other| other.email.clone())), - phone: self.phone.or(other.and_then(|other| other.phone.clone())), + email: self + .email + .clone() + .or(other.and_then(|other| other.email.clone())), + phone: self + .phone + .clone() + .or(other.and_then(|other| other.phone.clone())), } } } @@ -51,14 +58,14 @@ impl AddressDetails { } /// Unify the address details, giving priority to `self` when details are present in both - pub fn unify_address_details(self, other: Option<&Self>) -> Self { + pub fn unify_address_details(&self, other: Option<&Self>) -> Self { if let Some(other) = other { let (first_name, last_name) = if self .first_name .as_ref() .is_some_and(|first_name| !first_name.peek().trim().is_empty()) { - (self.first_name, self.last_name) + (self.first_name.clone(), self.last_name.clone()) } else { (other.first_name.clone(), other.last_name.clone()) }; @@ -66,16 +73,16 @@ impl AddressDetails { Self { first_name, last_name, - city: self.city.or(other.city.clone()), - country: self.country.or(other.country), - line1: self.line1.or(other.line1.clone()), - line2: self.line2.or(other.line2.clone()), - line3: self.line3.or(other.line3.clone()), - zip: self.zip.or(other.zip.clone()), - state: self.state.or(other.state.clone()), + city: self.city.clone().or(other.city.clone()), + country: self.country.clone().or(other.country), + line1: self.line1.clone().or(other.line1.clone()), + line2: self.line2.clone().or(other.line2.clone()), + line3: self.line3.clone().or(other.line3.clone()), + zip: self.zip.clone().or(other.zip.clone()), + state: self.state.clone().or(other.state.clone()), } } else { - self + self.clone() } } } diff --git a/crates/hyperswitch_domain_models/src/payments.rs b/crates/hyperswitch_domain_models/src/payments.rs index da9a161fb129..670ed516825e 100644 --- a/crates/hyperswitch_domain_models/src/payments.rs +++ b/crates/hyperswitch_domain_models/src/payments.rs @@ -32,8 +32,8 @@ use self::payment_attempt::PaymentAttempt; use crate::RemoteStorageObject; #[cfg(feature = "v2")] use crate::{ - address::Address, business_profile, errors, merchant_account, payment_method_data, - ApiModelToDieselModelConvertor, + address::Address, business_profile, errors, merchant_account, payment_address, + payment_method_data, ApiModelToDieselModelConvertor, }; #[cfg(feature = "v1")] diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs index 274400e9d4e4..6df6bb4caabf 100644 --- a/crates/router/src/core/payments.rs +++ b/crates/router/src/core/payments.rs @@ -6567,6 +6567,10 @@ pub trait OperationSessionGetters { fn get_amount(&self) -> api::Amount; fn get_payment_attempt_connector(&self) -> Option<&str>; fn get_billing_address(&self) -> Option; + #[cfg(feature = "v2")] + fn get_payment_method_billing_address( + &self, + ) -> Option; fn get_payment_method_data(&self) -> Option<&domain::PaymentMethodData>; fn get_sessions_token(&self) -> Vec; fn get_token_data(&self) -> Option<&storage::PaymentTokenData>; @@ -6620,6 +6624,7 @@ pub trait OperationSessionSetters { fn set_connector_in_payment_attempt(&mut self, connector: Option); } +#[cfg(feature = "v1")] impl OperationSessionGetters for PaymentData { fn get_payment_attempt(&self) -> &storage::PaymentAttempt { &self.payment_attempt @@ -6749,15 +6754,15 @@ impl OperationSessionGetters for PaymentData { self.payment_attempt.capture_method } - #[cfg(feature = "v2")] - fn get_capture_method(&self) -> Option { - Some(self.payment_intent.capture_method) - } + // #[cfg(feature = "v2")] + // fn get_capture_method(&self) -> Option { + // Some(self.payment_intent.capture_method) + // } - #[cfg(feature = "v2")] - fn get_optional_payment_attempt(&self) -> Option<&storage::PaymentAttempt> { - todo!(); - } + // #[cfg(feature = "v2")] + // fn get_optional_payment_attempt(&self) -> Option<&storage::PaymentAttempt> { + // todo!(); + // } } #[cfg(feature = "v1")] @@ -6990,10 +6995,16 @@ impl OperationSessionGetters for PaymentIntentData { todo!() } - #[cfg(feature = "v2")] fn get_optional_payment_attempt(&self) -> Option<&storage::PaymentAttempt> { todo!(); } + + fn get_payment_method_billing_address( + &self, + ) -> Option { + // We will not have payment method billing address in this case since confirm has not happened yet + None + } } #[cfg(feature = "v2")] @@ -7204,9 +7215,29 @@ impl OperationSessionGetters for PaymentConfirmData { todo!() } - #[cfg(feature = "v2")] fn get_optional_payment_attempt(&self) -> Option<&storage::PaymentAttempt> { - todo!(); + Some(&self.payment_attempt) + } + + fn get_payment_method_billing_address( + &self, + ) -> Option { + let optional_billing_address = self + .payment_intent + .billing_address + .as_ref() + .map(|address| address.get_inner()); + + let optional_payment_method_billing_address = self + .payment_attempt + .payment_method_billing_address + .as_ref() + .map(|address| address.get_inner()); + + // Unify the addresses, give priority to payment_method_billing_address + optional_payment_method_billing_address.map(|payment_method_billing_address| { + payment_method_billing_address.unify_address(optional_billing_address) + }) } } @@ -7420,10 +7451,30 @@ impl OperationSessionGetters for PaymentStatusData { todo!() } - #[cfg(feature = "v2")] fn get_optional_payment_attempt(&self) -> Option<&storage::PaymentAttempt> { self.payment_attempt.as_ref() } + + fn get_payment_method_billing_address( + &self, + ) -> Option { + let optional_billing_address = self + .payment_intent + .billing_address + .as_ref() + .map(|address| address.get_inner()); + + let optional_payment_method_billing_address = self + .payment_attempt + .as_ref() + .and_then(|payment_attempt| payment_attempt.payment_method_billing_address.as_ref()) + .map(|address| address.get_inner()); + + // Unify the addresses, give priority to payment_method_billing_address + optional_payment_method_billing_address.map(|payment_method_billing_address| { + payment_method_billing_address.unify_address(optional_billing_address) + }) + } } #[cfg(feature = "v2")] diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs index 41499a44310c..59636913e27c 100644 --- a/crates/router/src/core/payments/transformers.rs +++ b/crates/router/src/core/payments/transformers.rs @@ -432,7 +432,7 @@ pub async fn construct_router_data_for_psync<'a>( sync_type: types::SyncRequestType::SinglePaymentSync, payment_method_type: Some(attempt.payment_method_subtype), currency: payment_intent.amount_details.currency, - // TODO: Get the charges object from + // TODO: Get the charges object from feature metadata charges: None, payment_experience: None, }; @@ -507,30 +507,6 @@ pub async fn construct_router_data_for_psync<'a>( Ok(router_data) } -#[cfg(feature = "v2")] -#[instrument(skip_all)] -#[allow(clippy::too_many_arguments)] -pub async fn construct_payment_router_data<'a, F, T>( - state: &'a SessionState, - payment_data: PaymentData, - connector_id: &str, - merchant_account: &domain::MerchantAccount, - _key_store: &domain::MerchantKeyStore, - customer: &'a Option, - merchant_connector_account: &helpers::MerchantConnectorAccountType, - merchant_recipient_data: Option, - header_payload: Option, -) -> RouterResult> -where - T: TryFrom>, - types::RouterData: Feature, - F: Clone, - error_stack::Report: - From<>>::Error>, -{ - todo!() -} - #[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "customer_v2")))] #[instrument(skip_all)] #[allow(clippy::too_many_arguments)] diff --git a/crates/router/src/types.rs b/crates/router/src/types.rs index bea009949f94..a245fd91fef1 100644 --- a/crates/router/src/types.rs +++ b/crates/router/src/types.rs @@ -258,6 +258,7 @@ pub trait Capturable { } } +#[cfg(feature = "v1")] impl Capturable for PaymentsAuthorizeData { fn get_captured_amount(&self, payment_data: &PaymentData) -> Option where @@ -306,6 +307,7 @@ impl Capturable for PaymentsAuthorizeData { } } +#[cfg(feature = "v1")] impl Capturable for PaymentsCaptureData { fn get_captured_amount(&self, _payment_data: &PaymentData) -> Option where @@ -338,6 +340,7 @@ impl Capturable for PaymentsCaptureData { } } +#[cfg(feature = "v1")] impl Capturable for CompleteAuthorizeData { fn get_captured_amount(&self, payment_data: &PaymentData) -> Option where @@ -386,6 +389,7 @@ impl Capturable for CompleteAuthorizeData { } } } + impl Capturable for SetupMandateRequestData {} impl Capturable for PaymentsTaxCalculationData {} impl Capturable for SdkPaymentsSessionUpdateData {} From d2ad9699fc17efc9d2c16d82721a245e7a41b6a7 Mon Sep 17 00:00:00 2001 From: Narayan Bhat Date: Thu, 21 Nov 2024 13:07:12 +0530 Subject: [PATCH 13/19] refactor: pass address to connector module --- .../src/connectors/shift4/transformers.rs | 2 +- .../src/connectors/worldline/transformers.rs | 1 - .../hyperswitch_domain_models/src/address.rs | 2 +- .../hyperswitch_domain_models/src/payments.rs | 1 + .../connector/bankofamerica/transformers.rs | 1 - crates/router/src/core/payments.rs | 55 +------------------ .../operations/payment_confirm_intent.rs | 17 ++++++ .../router/src/core/payments/transformers.rs | 2 +- crates/router/tests/connectors/aci.rs | 5 +- crates/router/tests/connectors/adyen.rs | 8 +-- crates/router/tests/connectors/airwallex.rs | 5 +- crates/router/tests/connectors/bitpay.rs | 11 ++-- crates/router/tests/connectors/bluesnap.rs | 5 +- crates/router/tests/connectors/cashtocode.rs | 5 +- crates/router/tests/connectors/coinbase.rs | 11 ++-- crates/router/tests/connectors/cryptopay.rs | 11 ++-- crates/router/tests/connectors/cybersource.rs | 11 ++-- crates/router/tests/connectors/dlocal.rs | 7 +-- crates/router/tests/connectors/forte.rs | 11 ++-- crates/router/tests/connectors/globalpay.rs | 9 +-- crates/router/tests/connectors/iatapay.rs | 11 ++-- .../router/tests/connectors/multisafepay.rs | 5 +- crates/router/tests/connectors/opennode.rs | 11 ++-- crates/router/tests/connectors/payeezy.rs | 5 +- crates/router/tests/connectors/payme.rs | 5 +- crates/router/tests/connectors/trustpay.rs | 9 +-- crates/router/tests/connectors/utils.rs | 7 +-- crates/router/tests/connectors/wise.rs | 5 +- crates/router/tests/connectors/worldline.rs | 5 +- 29 files changed, 101 insertions(+), 142 deletions(-) diff --git a/crates/hyperswitch_connectors/src/connectors/shift4/transformers.rs b/crates/hyperswitch_connectors/src/connectors/shift4/transformers.rs index a336696c2a50..1973e622be1b 100644 --- a/crates/hyperswitch_connectors/src/connectors/shift4/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/shift4/transformers.rs @@ -1,4 +1,4 @@ -use api_models::{payments::AddressDetails, webhooks::IncomingWebhookEvent}; +use api_models::webhooks::IncomingWebhookEvent; use cards::CardNumber; use common_enums::enums; use common_utils::{ diff --git a/crates/hyperswitch_connectors/src/connectors/worldline/transformers.rs b/crates/hyperswitch_connectors/src/connectors/worldline/transformers.rs index 673d6045bc1b..e3ebcf490de1 100644 --- a/crates/hyperswitch_connectors/src/connectors/worldline/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/worldline/transformers.rs @@ -1,4 +1,3 @@ -use api_models::payments; use common_enums::enums::{AttemptStatus, BankNames, CaptureMethod, CountryAlpha2, Currency}; use common_utils::{pii::Email, request::Method}; use hyperswitch_domain_models::{ diff --git a/crates/hyperswitch_domain_models/src/address.rs b/crates/hyperswitch_domain_models/src/address.rs index e42dc2370cfc..c9beb359c433 100644 --- a/crates/hyperswitch_domain_models/src/address.rs +++ b/crates/hyperswitch_domain_models/src/address.rs @@ -74,7 +74,7 @@ impl AddressDetails { first_name, last_name, city: self.city.clone().or(other.city.clone()), - country: self.country.clone().or(other.country), + country: self.country.or(other.country), line1: self.line1.clone().or(other.line1.clone()), line2: self.line2.clone().or(other.line2.clone()), line3: self.line3.clone().or(other.line3.clone()), diff --git a/crates/hyperswitch_domain_models/src/payments.rs b/crates/hyperswitch_domain_models/src/payments.rs index 670ed516825e..40e84bde2546 100644 --- a/crates/hyperswitch_domain_models/src/payments.rs +++ b/crates/hyperswitch_domain_models/src/payments.rs @@ -578,6 +578,7 @@ where pub payment_intent: PaymentIntent, pub payment_attempt: PaymentAttempt, pub payment_method_data: Option, + pub payment_address: payment_address::PaymentAddress, } #[cfg(feature = "v2")] diff --git a/crates/router/src/connector/bankofamerica/transformers.rs b/crates/router/src/connector/bankofamerica/transformers.rs index 921be995514e..71cc006700e4 100644 --- a/crates/router/src/connector/bankofamerica/transformers.rs +++ b/crates/router/src/connector/bankofamerica/transformers.rs @@ -1,4 +1,3 @@ -use api_models::payments; use base64::Engine; use common_utils::pii; use masking::{ExposeInterface, PeekInterface, Secret}; diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs index 6df6bb4caabf..28230fa37bfe 100644 --- a/crates/router/src/core/payments.rs +++ b/crates/router/src/core/payments.rs @@ -1480,7 +1480,7 @@ where F: Send + Clone + Sync, Req: Send + Sync, FData: Send + Sync + Clone, - Op: Operation + Send + Sync + Clone, + Op: Operation + ValidateStatusForOperation + Send + Sync + Clone, Req: Debug, D: OperationSessionGetters + OperationSessionSetters + Send + Sync + Clone, Res: transformers::ToResponse, @@ -6567,10 +6567,6 @@ pub trait OperationSessionGetters { fn get_amount(&self) -> api::Amount; fn get_payment_attempt_connector(&self) -> Option<&str>; fn get_billing_address(&self) -> Option; - #[cfg(feature = "v2")] - fn get_payment_method_billing_address( - &self, - ) -> Option; fn get_payment_method_data(&self) -> Option<&domain::PaymentMethodData>; fn get_sessions_token(&self) -> Vec; fn get_token_data(&self) -> Option<&storage::PaymentTokenData>; @@ -6998,13 +6994,6 @@ impl OperationSessionGetters for PaymentIntentData { fn get_optional_payment_attempt(&self) -> Option<&storage::PaymentAttempt> { todo!(); } - - fn get_payment_method_billing_address( - &self, - ) -> Option { - // We will not have payment method billing address in this case since confirm has not happened yet - None - } } #[cfg(feature = "v2")] @@ -7218,27 +7207,6 @@ impl OperationSessionGetters for PaymentConfirmData { fn get_optional_payment_attempt(&self) -> Option<&storage::PaymentAttempt> { Some(&self.payment_attempt) } - - fn get_payment_method_billing_address( - &self, - ) -> Option { - let optional_billing_address = self - .payment_intent - .billing_address - .as_ref() - .map(|address| address.get_inner()); - - let optional_payment_method_billing_address = self - .payment_attempt - .payment_method_billing_address - .as_ref() - .map(|address| address.get_inner()); - - // Unify the addresses, give priority to payment_method_billing_address - optional_payment_method_billing_address.map(|payment_method_billing_address| { - payment_method_billing_address.unify_address(optional_billing_address) - }) - } } #[cfg(feature = "v2")] @@ -7454,27 +7422,6 @@ impl OperationSessionGetters for PaymentStatusData { fn get_optional_payment_attempt(&self) -> Option<&storage::PaymentAttempt> { self.payment_attempt.as_ref() } - - fn get_payment_method_billing_address( - &self, - ) -> Option { - let optional_billing_address = self - .payment_intent - .billing_address - .as_ref() - .map(|address| address.get_inner()); - - let optional_payment_method_billing_address = self - .payment_attempt - .as_ref() - .and_then(|payment_attempt| payment_attempt.payment_method_billing_address.as_ref()) - .map(|address| address.get_inner()); - - // Unify the addresses, give priority to payment_method_billing_address - optional_payment_method_billing_address.map(|payment_method_billing_address| { - payment_method_billing_address.unify_address(optional_billing_address) - }) - } } #[cfg(feature = "v2")] diff --git a/crates/router/src/core/payments/operations/payment_confirm_intent.rs b/crates/router/src/core/payments/operations/payment_confirm_intent.rs index 5965bdc88503..05c901025655 100644 --- a/crates/router/src/core/payments/operations/payment_confirm_intent.rs +++ b/crates/router/src/core/payments/operations/payment_confirm_intent.rs @@ -228,11 +228,28 @@ impl GetTracker, PaymentsConfirmIntent .clone() .map(hyperswitch_domain_models::payment_method_data::PaymentMethodData::from); + let payment_address = hyperswitch_domain_models::payment_address::PaymentAddress::new( + payment_intent + .shipping_address + .clone() + .map(|address| address.into_inner()), + payment_intent + .billing_address + .clone() + .map(|address| address.into_inner()), + payment_attempt + .payment_method_billing_address + .clone() + .map(|address| address.into_inner()), + Some(true), + ); + let payment_data = PaymentConfirmData { flow: std::marker::PhantomData, payment_intent, payment_attempt, payment_method_data, + payment_address, }; let get_trackers_response = operations::GetTrackerResponse { payment_data }; diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs index 59636913e27c..31577f598444 100644 --- a/crates/router/src/core/payments/transformers.rs +++ b/crates/router/src/core/payments/transformers.rs @@ -332,7 +332,7 @@ pub async fn construct_payment_router_data_for_authorize<'a>( .map(|description| description.get_string_repr()) .map(ToOwned::to_owned), // TODO: Create unified address - address: hyperswitch_domain_models::payment_address::PaymentAddress::default(), + address: payment_data.payment_address.clone(), auth_type: payment_data.payment_attempt.authentication_type, connector_meta_data: None, connector_wallets_details: None, diff --git a/crates/router/tests/connectors/aci.rs b/crates/router/tests/connectors/aci.rs index 4d4053d17f73..4fd740e9c4b2 100644 --- a/crates/router/tests/connectors/aci.rs +++ b/crates/router/tests/connectors/aci.rs @@ -2,8 +2,8 @@ use std::{borrow::Cow, marker::PhantomData, str::FromStr, sync::Arc}; -use api_models::payments::{Address, AddressDetails, PhoneDetails}; use common_utils::id_type; +use hyperswitch_domain_models::address::{Address, AddressDetails, PhoneDetails}; use masking::Secret; use router::{ configs::settings::Settings, @@ -96,8 +96,7 @@ fn construct_payment_router_data() -> types::PaymentsAuthorizeRouterData { country_code: Some("+351".to_string()), }), email: None, - }) - .map(From::from), + }), None, ), connector_meta_data: None, diff --git a/crates/router/tests/connectors/adyen.rs b/crates/router/tests/connectors/adyen.rs index 59d27b1904e9..2146d9590020 100644 --- a/crates/router/tests/connectors/adyen.rs +++ b/crates/router/tests/connectors/adyen.rs @@ -1,6 +1,6 @@ use std::str::FromStr; -use api_models::payments::{Address, AddressDetails, PhoneDetails}; +use hyperswitch_domain_models::address::{Address, AddressDetails, PhoneDetails}; use masking::Secret; use router::types::{self, storage::enums, PaymentAddress}; @@ -70,8 +70,7 @@ impl AdyenTest { country_code: Some("+351".to_string()), }), email: None, - }) - .map(From::from), + }), None, None, )), @@ -99,8 +98,7 @@ impl AdyenTest { }), phone: None, email: None, - }) - .map(From::from), + }), None, None, )), diff --git a/crates/router/tests/connectors/airwallex.rs b/crates/router/tests/connectors/airwallex.rs index a3daf2756652..bbc387a0b226 100644 --- a/crates/router/tests/connectors/airwallex.rs +++ b/crates/router/tests/connectors/airwallex.rs @@ -1,6 +1,6 @@ use std::str::FromStr; -use api_models::payments::{Address, AddressDetails}; +use hyperswitch_domain_models::address::{Address, AddressDetails}; use masking::{PeekInterface, Secret}; use router::types::{self, domain, storage::enums, AccessToken}; @@ -63,8 +63,7 @@ fn get_default_payment_info() -> Option { }), phone: None, email: None, - }) - .map(From::from), + }), None, )), ..Default::default() diff --git a/crates/router/tests/connectors/bitpay.rs b/crates/router/tests/connectors/bitpay.rs index 58877786da25..1e6b787984e4 100644 --- a/crates/router/tests/connectors/bitpay.rs +++ b/crates/router/tests/connectors/bitpay.rs @@ -1,6 +1,8 @@ use masking::Secret; use router::types::{self, api, domain, storage::enums, PaymentAddress}; +use hyperswitch_domain_models::address::{Address, AddressDetails, PhoneDetails}; + use crate::{ connector_auth, utils::{self, ConnectorActions}, @@ -40,8 +42,8 @@ fn get_default_payment_info() -> Option { Some(utils::PaymentInfo { address: Some(PaymentAddress::new( None, - Some(api::Address { - address: Some(api::AddressDetails { + Some(Address { + address: Some(AddressDetails { first_name: Some(Secret::new("first".to_string())), last_name: Some(Secret::new("last".to_string())), line1: Some(Secret::new("line1".to_string())), @@ -51,13 +53,12 @@ fn get_default_payment_info() -> Option { country: Some(api_models::enums::CountryAlpha2::IN), ..Default::default() }), - phone: Some(api::PhoneDetails { + phone: Some(PhoneDetails { number: Some(Secret::new("9123456789".to_string())), country_code: Some("+91".to_string()), }), email: None, - }) - .map(From::from), + }), None, None, )), diff --git a/crates/router/tests/connectors/bluesnap.rs b/crates/router/tests/connectors/bluesnap.rs index 07272084cf70..d6df20d7ee0e 100644 --- a/crates/router/tests/connectors/bluesnap.rs +++ b/crates/router/tests/connectors/bluesnap.rs @@ -1,7 +1,7 @@ use std::str::FromStr; -use api_models::payments::{Address, AddressDetails}; use common_utils::pii::Email; +use hyperswitch_domain_models::address::{Address, AddressDetails}; use masking::Secret; use router::types::{self, domain, storage::enums, ConnectorAuthType, PaymentAddress}; @@ -56,8 +56,7 @@ fn get_payment_info() -> Option { }), phone: None, email: None, - }) - .map(From::from), + }), None, None, )), diff --git a/crates/router/tests/connectors/cashtocode.rs b/crates/router/tests/connectors/cashtocode.rs index 5aa67b223db7..50c93f05a6b8 100644 --- a/crates/router/tests/connectors/cashtocode.rs +++ b/crates/router/tests/connectors/cashtocode.rs @@ -1,5 +1,5 @@ -use api_models::payments::{Address, AddressDetails}; use common_utils::id_type; +use hyperswitch_domain_models::address::{Address, AddressDetails}; use router::types::{self, domain, storage::enums}; use crate::{ @@ -89,8 +89,7 @@ impl CashtocodeTest { }), phone: None, email: None, - }) - .map(From::from), + }), None, None, )), diff --git a/crates/router/tests/connectors/coinbase.rs b/crates/router/tests/connectors/coinbase.rs index f00825f1f008..86f5c41928ad 100644 --- a/crates/router/tests/connectors/coinbase.rs +++ b/crates/router/tests/connectors/coinbase.rs @@ -2,6 +2,8 @@ use masking::Secret; use router::types::{self, api, domain, storage::enums, PaymentAddress}; use serde_json::json; +use hyperswitch_domain_models::address::{Address, AddressDetails, PhoneDetails}; + use crate::{ connector_auth, utils::{self, ConnectorActions}, @@ -41,8 +43,8 @@ fn get_default_payment_info() -> Option { Some(utils::PaymentInfo { address: Some(PaymentAddress::new( None, - Some(api::Address { - address: Some(api::AddressDetails { + Some(Address { + address: Some(AddressDetails { first_name: Some(Secret::new("first".to_string())), last_name: Some(Secret::new("last".to_string())), line1: Some(Secret::new("line1".to_string())), @@ -52,13 +54,12 @@ fn get_default_payment_info() -> Option { country: Some(api_models::enums::CountryAlpha2::IN), ..Default::default() }), - phone: Some(api::PhoneDetails { + phone: Some(PhoneDetails { number: Some(Secret::new("9123456789".to_string())), country_code: Some("+91".to_string()), }), email: None, - }) - .map(From::from), + }), None, None, )), diff --git a/crates/router/tests/connectors/cryptopay.rs b/crates/router/tests/connectors/cryptopay.rs index 59ddd0199742..f7f2edacc2d2 100644 --- a/crates/router/tests/connectors/cryptopay.rs +++ b/crates/router/tests/connectors/cryptopay.rs @@ -1,6 +1,8 @@ use masking::Secret; use router::types::{self, api, domain, storage::enums, PaymentAddress}; +use hyperswitch_domain_models::address::{Address, AddressDetails, PhoneDetails}; + use crate::{ connector_auth, utils::{self, ConnectorActions}, @@ -40,8 +42,8 @@ fn get_default_payment_info() -> Option { Some(utils::PaymentInfo { address: Some(PaymentAddress::new( None, - Some(api::Address { - address: Some(api::AddressDetails { + Some(Address { + address: Some(AddressDetails { first_name: Some(Secret::new("first".to_string())), last_name: Some(Secret::new("last".to_string())), line1: Some(Secret::new("line1".to_string())), @@ -51,13 +53,12 @@ fn get_default_payment_info() -> Option { country: Some(api_models::enums::CountryAlpha2::IN), ..Default::default() }), - phone: Some(api::PhoneDetails { + phone: Some(PhoneDetails { number: Some(Secret::new("9123456789".to_string())), country_code: Some("+91".to_string()), }), email: None, - }) - .map(From::from), + }), None, None, )), diff --git a/crates/router/tests/connectors/cybersource.rs b/crates/router/tests/connectors/cybersource.rs index bbd1fb4f429f..de11c931b5a5 100644 --- a/crates/router/tests/connectors/cybersource.rs +++ b/crates/router/tests/connectors/cybersource.rs @@ -4,6 +4,8 @@ use common_utils::pii::Email; use masking::Secret; use router::types::{self, api, domain, storage::enums}; +use hyperswitch_domain_models::address::{Address, AddressDetails, PhoneDetails}; + use crate::{ connector_auth, utils::{self, ConnectorActions, PaymentAuthorizeType}, @@ -37,8 +39,8 @@ fn get_default_payment_info() -> Option { Some(utils::PaymentInfo { address: Some(types::PaymentAddress::new( None, - Some(api::Address { - address: Some(api::AddressDetails { + Some(Address { + address: Some(AddressDetails { first_name: Some(Secret::new("first".to_string())), last_name: Some(Secret::new("last".to_string())), line1: Some(Secret::new("line1".to_string())), @@ -48,13 +50,12 @@ fn get_default_payment_info() -> Option { country: Some(api_models::enums::CountryAlpha2::IN), ..Default::default() }), - phone: Some(api::PhoneDetails { + phone: Some(PhoneDetails { number: Some(Secret::new("9123456789".to_string())), country_code: Some("+91".to_string()), }), email: None, - }) - .map(From::from), + }), None, None, )), diff --git a/crates/router/tests/connectors/dlocal.rs b/crates/router/tests/connectors/dlocal.rs index e61ec14354fa..3022f1f0b1d8 100644 --- a/crates/router/tests/connectors/dlocal.rs +++ b/crates/router/tests/connectors/dlocal.rs @@ -2,7 +2,7 @@ use std::str::FromStr; -use hyperswitch_domain_models::address::Address; +use hyperswitch_domain_models::address::{Address, AddressDetails}; use masking::Secret; use router::types::{self, api, domain, storage::enums, PaymentAddress}; @@ -426,7 +426,7 @@ pub fn get_payment_info() -> PaymentInfo { None, Some(Address { phone: None, - address: Some(api::AddressDetails { + address: Some(AddressDetails { city: None, country: Some(api_models::enums::CountryAlpha2::PA), line1: None, @@ -436,8 +436,7 @@ pub fn get_payment_info() -> PaymentInfo { state: None, first_name: None, last_name: None, - }) - .map(From::from), + }), email: None, }), None, diff --git a/crates/router/tests/connectors/forte.rs b/crates/router/tests/connectors/forte.rs index 0272da6e0621..6ea0f8a82897 100644 --- a/crates/router/tests/connectors/forte.rs +++ b/crates/router/tests/connectors/forte.rs @@ -5,6 +5,8 @@ use common_utils::types::MinorUnit; use masking::Secret; use router::types::{self, api, domain, storage::enums}; +use hyperswitch_domain_models::address::{Address, AddressDetails, PhoneDetails}; + use crate::{ connector_auth, utils::{self, ConnectorActions}, @@ -54,8 +56,8 @@ fn get_default_payment_info() -> Option { Some(utils::PaymentInfo { address: Some(types::PaymentAddress::new( None, - Some(api::Address { - address: Some(api::AddressDetails { + Some(Address { + address: Some(AddressDetails { first_name: Some(Secret::new("first".to_string())), last_name: Some(Secret::new("last".to_string())), line1: Some(Secret::new("line1".to_string())), @@ -65,13 +67,12 @@ fn get_default_payment_info() -> Option { country: Some(api_models::enums::CountryAlpha2::IN), ..Default::default() }), - phone: Some(api::PhoneDetails { + phone: Some(PhoneDetails { number: Some(Secret::new("9123456789".to_string())), country_code: Some("+91".to_string()), }), email: None, - }) - .map(From::from), + }), None, None, )), diff --git a/crates/router/tests/connectors/globalpay.rs b/crates/router/tests/connectors/globalpay.rs index ba6ffed1198a..a79cb84b0718 100644 --- a/crates/router/tests/connectors/globalpay.rs +++ b/crates/router/tests/connectors/globalpay.rs @@ -4,6 +4,8 @@ use masking::Secret; use router::types::{self, api, domain, storage::enums, AccessToken, ConnectorAuthType}; use serde_json::json; +use hyperswitch_domain_models::address::{Address, AddressDetails}; + use crate::{ connector_auth, utils::{self, Connector, ConnectorActions, PaymentInfo}, @@ -59,15 +61,14 @@ impl Globalpay { Some(PaymentInfo { address: Some(types::PaymentAddress::new( None, - Some(api::Address { - address: Some(api::AddressDetails { + Some(Address { + address: Some(AddressDetails { country: Some(api_models::enums::CountryAlpha2::US), ..Default::default() }), phone: None, ..Default::default() - }) - .map(From::from), + }), None, None, )), diff --git a/crates/router/tests/connectors/iatapay.rs b/crates/router/tests/connectors/iatapay.rs index 193a371fd22d..186a372b13fb 100644 --- a/crates/router/tests/connectors/iatapay.rs +++ b/crates/router/tests/connectors/iatapay.rs @@ -8,6 +8,8 @@ use crate::{ }, }; +use hyperswitch_domain_models::address::{Address, AddressDetails, PhoneDetails}; + #[derive(Clone, Copy)] struct IatapayTest; impl ConnectorActions for IatapayTest {} @@ -57,8 +59,8 @@ fn get_default_payment_info() -> Option { Some(utils::PaymentInfo { address: Some(types::PaymentAddress::new( None, - Some(api::Address { - address: Some(api::AddressDetails { + Some(Address { + address: Some(AddressDetails { first_name: Some(Secret::new("first".to_string())), last_name: Some(Secret::new("last".to_string())), line1: Some(Secret::new("line1".to_string())), @@ -68,13 +70,12 @@ fn get_default_payment_info() -> Option { country: Some(api_models::enums::CountryAlpha2::NL), ..Default::default() }), - phone: Some(api::PhoneDetails { + phone: Some(PhoneDetails { number: Some(Secret::new("9123456789".to_string())), country_code: Some("+91".to_string()), }), email: None, - }) - .map(From::from), + }), None, None, )), diff --git a/crates/router/tests/connectors/multisafepay.rs b/crates/router/tests/connectors/multisafepay.rs index 430a3f0c10b7..1a81b00116fa 100644 --- a/crates/router/tests/connectors/multisafepay.rs +++ b/crates/router/tests/connectors/multisafepay.rs @@ -1,4 +1,4 @@ -use api_models::payments::{Address, AddressDetails}; +use hyperswitch_domain_models::address::{Address, AddressDetails}; use masking::Secret; use router::types::{self, domain, storage::enums, PaymentAddress}; @@ -54,8 +54,7 @@ fn get_default_payment_info() -> Option { }), phone: None, email: None, - }) - .map(From::from), + }), None, None, )); diff --git a/crates/router/tests/connectors/opennode.rs b/crates/router/tests/connectors/opennode.rs index fb997b20fac4..e5ae0ffd3d9b 100644 --- a/crates/router/tests/connectors/opennode.rs +++ b/crates/router/tests/connectors/opennode.rs @@ -6,6 +6,8 @@ use crate::{ utils::{self, ConnectorActions}, }; +use hyperswitch_domain_models::address::{Address, AddressDetails, PhoneDetails}; + #[derive(Clone, Copy)] struct OpennodeTest; impl ConnectorActions for OpennodeTest {} @@ -40,8 +42,8 @@ fn get_default_payment_info() -> Option { Some(utils::PaymentInfo { address: Some(types::PaymentAddress::new( None, - Some(api::Address { - address: Some(api::AddressDetails { + Some(Address { + address: Some(AddressDetails { first_name: Some(Secret::new("first".to_string())), last_name: Some(Secret::new("last".to_string())), line1: Some(Secret::new("line1".to_string())), @@ -51,13 +53,12 @@ fn get_default_payment_info() -> Option { country: Some(api_models::enums::CountryAlpha2::IN), ..Default::default() }), - phone: Some(api::PhoneDetails { + phone: Some(PhoneDetails { number: Some(Secret::new("9123456789".to_string())), country_code: Some("+91".to_string()), }), email: None, - }) - .map(From::from), + }), None, None, )), diff --git a/crates/router/tests/connectors/payeezy.rs b/crates/router/tests/connectors/payeezy.rs index 3a904ca633b4..49f7085bda49 100644 --- a/crates/router/tests/connectors/payeezy.rs +++ b/crates/router/tests/connectors/payeezy.rs @@ -1,7 +1,7 @@ use std::str::FromStr; -use api_models::payments::{Address, AddressDetails}; use cards::CardNumber; +use hyperswitch_domain_models::address::{Address, AddressDetails}; use masking::Secret; use router::{ core::errors, @@ -64,8 +64,7 @@ impl PayeezyTest { }), phone: None, email: None, - }) - .map(From::from), + }), None, None, )), diff --git a/crates/router/tests/connectors/payme.rs b/crates/router/tests/connectors/payme.rs index 80d2c79ce1a8..1994acb6a659 100644 --- a/crates/router/tests/connectors/payme.rs +++ b/crates/router/tests/connectors/payme.rs @@ -1,8 +1,8 @@ use std::str::FromStr; -use api_models::payments::{Address, AddressDetails}; use common_utils::{pii::Email, types::MinorUnit}; use diesel_models::types::OrderDetailsWithAmount; +use hyperswitch_domain_models::address::{Address, AddressDetails}; use masking::Secret; use router::types::{self, domain, storage::enums, PaymentAddress}; @@ -59,8 +59,7 @@ fn get_default_payment_info() -> Option { }), phone: None, email: None, - }) - .map(From::from), + }), None, None, )), diff --git a/crates/router/tests/connectors/trustpay.rs b/crates/router/tests/connectors/trustpay.rs index 6685d863d6c9..d8d31837baaf 100644 --- a/crates/router/tests/connectors/trustpay.rs +++ b/crates/router/tests/connectors/trustpay.rs @@ -8,6 +8,8 @@ use crate::{ utils::{self, ConnectorActions}, }; +use hyperswitch_domain_models::address::{Address, AddressDetails}; + #[derive(Clone, Copy)] struct TrustpayTest; impl ConnectorActions for TrustpayTest {} @@ -69,8 +71,8 @@ fn get_default_payment_info() -> Option { Some(utils::PaymentInfo { address: Some(types::PaymentAddress::new( None, - Some(api::Address { - address: Some(api::AddressDetails { + Some(Address { + address: Some(AddressDetails { first_name: Some(Secret::new("first".to_string())), last_name: Some(Secret::new("last".to_string())), line1: Some(Secret::new("line1".to_string())), @@ -82,8 +84,7 @@ fn get_default_payment_info() -> Option { }), phone: None, email: None, - }) - .map(From::from), + }), None, None, )), diff --git a/crates/router/tests/connectors/utils.rs b/crates/router/tests/connectors/utils.rs index c7e60eea600f..93b4c8db97a7 100644 --- a/crates/router/tests/connectors/utils.rs +++ b/crates/router/tests/connectors/utils.rs @@ -78,16 +78,15 @@ impl PaymentInfo { address: Some(PaymentAddress::new( None, None, - Some(types::api::Address { - address: Some(types::api::AddressDetails { + Some(hyperswitch_domain_models::address::Address { + address: Some(hyperswitch_domain_models::address::AddressDetails { first_name: Some(Secret::new("John".to_string())), last_name: Some(Secret::new("Doe".to_string())), ..Default::default() }), phone: None, email: None, - }) - .map(From::from), + }), None, )), ..Default::default() diff --git a/crates/router/tests/connectors/wise.rs b/crates/router/tests/connectors/wise.rs index 846a78a55be1..2156cfb1476c 100644 --- a/crates/router/tests/connectors/wise.rs +++ b/crates/router/tests/connectors/wise.rs @@ -1,4 +1,4 @@ -use api_models::payments::{Address, AddressDetails}; +use hyperswitch_domain_models::address::{Address, AddressDetails}; use masking::Secret; use router::{ types, @@ -65,8 +65,7 @@ impl WiseTest { }), phone: None, email: None, - }) - .map(From::from), + }), None, None, )), diff --git a/crates/router/tests/connectors/worldline.rs b/crates/router/tests/connectors/worldline.rs index 871c0833586a..c1be90b59fde 100644 --- a/crates/router/tests/connectors/worldline.rs +++ b/crates/router/tests/connectors/worldline.rs @@ -1,6 +1,6 @@ use std::str::FromStr; -use api_models::payments::{Address, AddressDetails}; +use hyperswitch_domain_models::address::{Address, AddressDetails}; use masking::Secret; use router::{ connector::Worldline, @@ -54,8 +54,7 @@ impl WorldlineTest { }), phone: None, email: None, - }) - .map(From::from), + }), None, None, )), From 4eafc74c09f2c0de5e127d7a2077ce5c86f30397 Mon Sep 17 00:00:00 2001 From: "hyperswitch-bot[bot]" <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Date: Thu, 21 Nov 2024 07:38:04 +0000 Subject: [PATCH 14/19] chore: run formatter --- crates/router/tests/connectors/bitpay.rs | 3 +-- crates/router/tests/connectors/coinbase.rs | 3 +-- crates/router/tests/connectors/cryptopay.rs | 3 +-- crates/router/tests/connectors/cybersource.rs | 3 +-- crates/router/tests/connectors/forte.rs | 3 +-- crates/router/tests/connectors/globalpay.rs | 3 +-- crates/router/tests/connectors/iatapay.rs | 3 +-- crates/router/tests/connectors/opennode.rs | 3 +-- crates/router/tests/connectors/trustpay.rs | 3 +-- 9 files changed, 9 insertions(+), 18 deletions(-) diff --git a/crates/router/tests/connectors/bitpay.rs b/crates/router/tests/connectors/bitpay.rs index 1e6b787984e4..70af3b752127 100644 --- a/crates/router/tests/connectors/bitpay.rs +++ b/crates/router/tests/connectors/bitpay.rs @@ -1,8 +1,7 @@ +use hyperswitch_domain_models::address::{Address, AddressDetails, PhoneDetails}; use masking::Secret; use router::types::{self, api, domain, storage::enums, PaymentAddress}; -use hyperswitch_domain_models::address::{Address, AddressDetails, PhoneDetails}; - use crate::{ connector_auth, utils::{self, ConnectorActions}, diff --git a/crates/router/tests/connectors/coinbase.rs b/crates/router/tests/connectors/coinbase.rs index 86f5c41928ad..7320b875ca25 100644 --- a/crates/router/tests/connectors/coinbase.rs +++ b/crates/router/tests/connectors/coinbase.rs @@ -1,9 +1,8 @@ +use hyperswitch_domain_models::address::{Address, AddressDetails, PhoneDetails}; use masking::Secret; use router::types::{self, api, domain, storage::enums, PaymentAddress}; use serde_json::json; -use hyperswitch_domain_models::address::{Address, AddressDetails, PhoneDetails}; - use crate::{ connector_auth, utils::{self, ConnectorActions}, diff --git a/crates/router/tests/connectors/cryptopay.rs b/crates/router/tests/connectors/cryptopay.rs index f7f2edacc2d2..2ecc7869bcd2 100644 --- a/crates/router/tests/connectors/cryptopay.rs +++ b/crates/router/tests/connectors/cryptopay.rs @@ -1,8 +1,7 @@ +use hyperswitch_domain_models::address::{Address, AddressDetails, PhoneDetails}; use masking::Secret; use router::types::{self, api, domain, storage::enums, PaymentAddress}; -use hyperswitch_domain_models::address::{Address, AddressDetails, PhoneDetails}; - use crate::{ connector_auth, utils::{self, ConnectorActions}, diff --git a/crates/router/tests/connectors/cybersource.rs b/crates/router/tests/connectors/cybersource.rs index de11c931b5a5..411ff3ee2e35 100644 --- a/crates/router/tests/connectors/cybersource.rs +++ b/crates/router/tests/connectors/cybersource.rs @@ -1,11 +1,10 @@ use std::str::FromStr; use common_utils::pii::Email; +use hyperswitch_domain_models::address::{Address, AddressDetails, PhoneDetails}; use masking::Secret; use router::types::{self, api, domain, storage::enums}; -use hyperswitch_domain_models::address::{Address, AddressDetails, PhoneDetails}; - use crate::{ connector_auth, utils::{self, ConnectorActions, PaymentAuthorizeType}, diff --git a/crates/router/tests/connectors/forte.rs b/crates/router/tests/connectors/forte.rs index 6ea0f8a82897..3c5cde492c0c 100644 --- a/crates/router/tests/connectors/forte.rs +++ b/crates/router/tests/connectors/forte.rs @@ -2,11 +2,10 @@ use std::{str::FromStr, time::Duration}; use cards::CardNumber; use common_utils::types::MinorUnit; +use hyperswitch_domain_models::address::{Address, AddressDetails, PhoneDetails}; use masking::Secret; use router::types::{self, api, domain, storage::enums}; -use hyperswitch_domain_models::address::{Address, AddressDetails, PhoneDetails}; - use crate::{ connector_auth, utils::{self, ConnectorActions}, diff --git a/crates/router/tests/connectors/globalpay.rs b/crates/router/tests/connectors/globalpay.rs index a79cb84b0718..cd7e6c6b7991 100644 --- a/crates/router/tests/connectors/globalpay.rs +++ b/crates/router/tests/connectors/globalpay.rs @@ -1,11 +1,10 @@ use std::str::FromStr; +use hyperswitch_domain_models::address::{Address, AddressDetails}; use masking::Secret; use router::types::{self, api, domain, storage::enums, AccessToken, ConnectorAuthType}; use serde_json::json; -use hyperswitch_domain_models::address::{Address, AddressDetails}; - use crate::{ connector_auth, utils::{self, Connector, ConnectorActions, PaymentInfo}, diff --git a/crates/router/tests/connectors/iatapay.rs b/crates/router/tests/connectors/iatapay.rs index 186a372b13fb..d216f6063f6d 100644 --- a/crates/router/tests/connectors/iatapay.rs +++ b/crates/router/tests/connectors/iatapay.rs @@ -1,3 +1,4 @@ +use hyperswitch_domain_models::address::{Address, AddressDetails, PhoneDetails}; use masking::Secret; use router::types::{self, api, storage::enums, AccessToken}; @@ -8,8 +9,6 @@ use crate::{ }, }; -use hyperswitch_domain_models::address::{Address, AddressDetails, PhoneDetails}; - #[derive(Clone, Copy)] struct IatapayTest; impl ConnectorActions for IatapayTest {} diff --git a/crates/router/tests/connectors/opennode.rs b/crates/router/tests/connectors/opennode.rs index e5ae0ffd3d9b..d2629e287ca6 100644 --- a/crates/router/tests/connectors/opennode.rs +++ b/crates/router/tests/connectors/opennode.rs @@ -1,3 +1,4 @@ +use hyperswitch_domain_models::address::{Address, AddressDetails, PhoneDetails}; use masking::Secret; use router::types::{self, api, domain, storage::enums}; @@ -6,8 +7,6 @@ use crate::{ utils::{self, ConnectorActions}, }; -use hyperswitch_domain_models::address::{Address, AddressDetails, PhoneDetails}; - #[derive(Clone, Copy)] struct OpennodeTest; impl ConnectorActions for OpennodeTest {} diff --git a/crates/router/tests/connectors/trustpay.rs b/crates/router/tests/connectors/trustpay.rs index d8d31837baaf..308bf5135855 100644 --- a/crates/router/tests/connectors/trustpay.rs +++ b/crates/router/tests/connectors/trustpay.rs @@ -1,5 +1,6 @@ use std::str::FromStr; +use hyperswitch_domain_models::address::{Address, AddressDetails}; use masking::Secret; use router::types::{self, api, domain, storage::enums, BrowserInformation}; @@ -8,8 +9,6 @@ use crate::{ utils::{self, ConnectorActions}, }; -use hyperswitch_domain_models::address::{Address, AddressDetails}; - #[derive(Clone, Copy)] struct TrustpayTest; impl ConnectorActions for TrustpayTest {} From b3bac538b20ccbdecadf8fe437adb9225e6e54b1 Mon Sep 17 00:00:00 2001 From: Narayan Bhat Date: Thu, 21 Nov 2024 16:41:03 +0530 Subject: [PATCH 15/19] refactor: add address to payment_attempt --- crates/api_models/src/payments.rs | 12 ++++-- crates/common_enums/src/enums.rs | 2 + .../hyperswitch_domain_models/src/payments.rs | 1 + .../src/payments/payment_attempt.rs | 14 ++++++- crates/router/src/core/payments.rs | 3 +- .../core/payments/operations/payment_get.rs | 18 +++++++++ .../router/src/core/payments/transformers.rs | 39 +++++++++++++++---- 7 files changed, 73 insertions(+), 16 deletions(-) diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs index 75dda21097ad..e3d0cf5c9175 100644 --- a/crates/api_models/src/payments.rs +++ b/crates/api_models/src/payments.rs @@ -315,6 +315,10 @@ pub struct PaymentsIntentResponse { #[schema(value_type = String, example = "pay_U42c409qyHwOkWo3vK60_secret_el9ksDkiB8hi6j9N78yo")] pub client_secret: common_utils::types::ClientSecret, + /// The identifier for the profile. This is inferred from the `x-profile-id` header + #[schema(value_type = String)] + pub profile_id: id_type::ProfileId, + /// Unique identifier for the payment. This ensures idempotency for multiple payments /// that have been done by a single merchant. #[schema( @@ -475,10 +479,10 @@ pub struct AmountDetailsResponse { pub order_tax_amount: Option, /// The action to whether calculate tax by calling external tax provider or not #[schema(value_type = TaxCalculationOverride)] - pub skip_external_tax_calculation: common_enums::TaxCalculationOverride, + pub external_tax_calculation: common_enums::TaxCalculationOverride, /// The action to whether calculate surcharge or not #[schema(value_type = SurchargeCalculationOverride)] - pub skip_surcharge_calculation: common_enums::SurchargeCalculationOverride, + pub surcharge_calculation: common_enums::SurchargeCalculationOverride, /// The surcharge amount to be added to the order, collected from the merchant pub surcharge_amount: Option, /// tax on surcharge amount @@ -501,10 +505,10 @@ pub struct ConfirmIntentAmountDetailsResponse { pub order_tax_amount: Option, /// The action to whether calculate tax by calling external tax provider or not #[schema(value_type = TaxCalculationOverride)] - pub skip_external_tax_calculation: common_enums::TaxCalculationOverride, + pub external_tax_calculation: common_enums::TaxCalculationOverride, /// The action to whether calculate surcharge or not #[schema(value_type = SurchargeCalculationOverride)] - pub skip_surcharge_calculation: common_enums::SurchargeCalculationOverride, + pub surcharge_calculation: common_enums::SurchargeCalculationOverride, /// The surcharge amount to be added to the order, collected from the merchant pub surcharge_amount: Option, /// tax on surcharge amount diff --git a/crates/common_enums/src/enums.rs b/crates/common_enums/src/enums.rs index 23dbab778256..0acaf297f9dc 100644 --- a/crates/common_enums/src/enums.rs +++ b/crates/common_enums/src/enums.rs @@ -3305,6 +3305,7 @@ pub enum PresenceOfCustomerDuringPayment { } #[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize, Default, ToSchema)] +#[serde(rename_all = "snake_case")] pub enum TaxCalculationOverride { /// Skip calling the external tax provider #[default] @@ -3314,6 +3315,7 @@ pub enum TaxCalculationOverride { } #[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize, Default, ToSchema)] +#[serde(rename_all = "snake_case")] pub enum SurchargeCalculationOverride { /// Skip calculating surcharge #[default] diff --git a/crates/hyperswitch_domain_models/src/payments.rs b/crates/hyperswitch_domain_models/src/payments.rs index 40e84bde2546..3f6359874da2 100644 --- a/crates/hyperswitch_domain_models/src/payments.rs +++ b/crates/hyperswitch_domain_models/src/payments.rs @@ -590,6 +590,7 @@ where pub flow: PhantomData, pub payment_intent: PaymentIntent, pub payment_attempt: Option, + pub payment_address: payment_address::PaymentAddress, /// Should the payment status be synced with connector /// This will depend on the payment status and the force sync flag in the request pub should_sync_with_connector: bool, diff --git a/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs b/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs index ad87e9bca8ec..55aa2cbbb15a 100644 --- a/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs +++ b/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs @@ -371,6 +371,17 @@ impl PaymentAttempt { let now = common_utils::date_time::now(); + let payment_method_billing_address = encrypted_data + .payment_method_billing_address + .as_ref() + .map(|data| { + data.clone() + .deserialize_inner_value(|value| value.parse_value("Address")) + }) + .transpose() + .change_context(errors::api_error_response::ApiErrorResponse::InternalServerError) + .attach_printable("Unable to decode billing address")?; + Ok(Self { payment_id: payment_intent.id.clone(), merchant_id: payment_intent.merchant_id.clone(), @@ -413,8 +424,7 @@ impl PaymentAttempt { payment_method_subtype: request.payment_method_subtype, authentication_applied: None, external_reference_id: None, - // TODO: encrypt and store this - payment_method_billing_address: None, + payment_method_billing_address, error: None, connector_mandate_detail: None, id, diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs index 28230fa37bfe..90948d3f289a 100644 --- a/crates/router/src/core/payments.rs +++ b/crates/router/src/core/payments.rs @@ -7314,9 +7314,8 @@ impl OperationSessionGetters for PaymentStatusData { todo!() } - // what is this address find out and not required remove this fn get_address(&self) -> &PaymentAddress { - todo!() + &self.payment_address } fn get_creds_identifier(&self) -> Option<&str> { diff --git a/crates/router/src/core/payments/operations/payment_get.rs b/crates/router/src/core/payments/operations/payment_get.rs index a69c3187c781..60b262aca54b 100644 --- a/crates/router/src/core/payments/operations/payment_get.rs +++ b/crates/router/src/core/payments/operations/payment_get.rs @@ -163,10 +163,28 @@ impl GetTracker, PaymentsRetrieveReques let should_sync_with_connector = request.force_sync && payment_intent.status.should_force_sync_with_connector(); + let payment_address = hyperswitch_domain_models::payment_address::PaymentAddress::new( + payment_intent + .shipping_address + .clone() + .map(|address| address.into_inner()), + payment_intent + .billing_address + .clone() + .map(|address| address.into_inner()), + payment_attempt + .as_ref() + .and_then(|payment_attempt| payment_attempt.payment_method_billing_address.as_ref()) + .cloned() + .map(|address| address.into_inner()), + Some(true), + ); + let payment_data = PaymentStatusData { flow: std::marker::PhantomData, payment_intent, payment_attempt, + payment_address, should_sync_with_connector, }; diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs index 31577f598444..fa024bfdf3e4 100644 --- a/crates/router/src/core/payments/transformers.rs +++ b/crates/router/src/core/payments/transformers.rs @@ -907,6 +907,7 @@ where Ok(services::ApplicationResponse::JsonWithHeaders(( Self { id: payment_intent.id.clone(), + profile_id: payment_intent.profile_id.clone(), status: payment_intent.status, amount_details: api_models::payments::AmountDetailsResponse::foreign_from( payment_intent.amount_details.clone(), @@ -1009,6 +1010,17 @@ where .clone() .map(api_models::payments::ErrorDetails::foreign_from); + let payment_address = payment_data.get_address(); + + let payment_method_data = + Some(api_models::payments::PaymentMethodDataResponseWithBilling { + payment_method_data: None, + billing: payment_address + .get_request_payment_method_billing() + .cloned() + .map(From::from), + }); + // TODO: Add support for other next actions, currently only supporting redirect to url let redirect_to_url = payment_intent .create_start_redirection_url(base_url, merchant_account.publishable_key.clone())?; @@ -1024,7 +1036,7 @@ where connector, client_secret: payment_intent.client_secret.clone(), created: payment_intent.created_at, - payment_method_data: None, + payment_method_data, payment_method_type: payment_attempt.payment_method_type, payment_method_subtype: payment_attempt.payment_method_subtype, next_action, @@ -1079,6 +1091,17 @@ where .and_then(|payment_attempt| payment_attempt.error.clone()) .map(api_models::payments::ErrorDetails::foreign_from); + let payment_address = payment_data.get_address(); + + let payment_method_data = + Some(api_models::payments::PaymentMethodDataResponseWithBilling { + payment_method_data: None, + billing: payment_address + .get_request_payment_method_billing() + .cloned() + .map(From::from), + }); + let response = Self { id: payment_intent.id.clone(), status: payment_intent.status, @@ -1086,7 +1109,7 @@ where connector, client_secret: payment_intent.client_secret.clone(), created: payment_intent.created_at, - payment_method_data: None, + payment_method_data, payment_method_type: payment_attempt.map(|attempt| attempt.payment_method_type), payment_method_subtype: payment_attempt.map(|attempt| attempt.payment_method_subtype), connector_transaction_id: payment_attempt @@ -3320,10 +3343,10 @@ impl currency: intent_amount_details.currency, shipping_cost: attempt_amount_details.shipping_cost, order_tax_amount: attempt_amount_details.order_tax_amount, - skip_external_tax_calculation: common_enums::TaxCalculationOverride::foreign_from( + external_tax_calculation: common_enums::TaxCalculationOverride::foreign_from( intent_amount_details.skip_external_tax_calculation, ), - skip_surcharge_calculation: common_enums::SurchargeCalculationOverride::foreign_from( + surcharge_calculation: common_enums::SurchargeCalculationOverride::foreign_from( intent_amount_details.skip_surcharge_calculation, ), surcharge_amount: attempt_amount_details.surcharge_amount, @@ -3363,10 +3386,10 @@ impl .tax_details .as_ref() .and_then(|tax_details| tax_details.get_default_tax_amount())), - skip_external_tax_calculation: common_enums::TaxCalculationOverride::foreign_from( + external_tax_calculation: common_enums::TaxCalculationOverride::foreign_from( intent_amount_details.skip_external_tax_calculation, ), - skip_surcharge_calculation: common_enums::SurchargeCalculationOverride::foreign_from( + surcharge_calculation: common_enums::SurchargeCalculationOverride::foreign_from( intent_amount_details.skip_surcharge_calculation, ), surcharge_amount: attempt_amount_details @@ -3423,10 +3446,10 @@ impl ForeignFrom order_tax_amount: amount_details.tax_details.and_then(|tax_details| { tax_details.default.map(|default| default.order_tax_amount) }), - skip_external_tax_calculation: common_enums::TaxCalculationOverride::foreign_from( + external_tax_calculation: common_enums::TaxCalculationOverride::foreign_from( amount_details.skip_external_tax_calculation, ), - skip_surcharge_calculation: common_enums::SurchargeCalculationOverride::foreign_from( + surcharge_calculation: common_enums::SurchargeCalculationOverride::foreign_from( amount_details.skip_surcharge_calculation, ), surcharge_amount: amount_details.surcharge_amount, From f0d25596ec7d96add4f40cafa975030bb28d9e82 Mon Sep 17 00:00:00 2001 From: "hyperswitch-bot[bot]" <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:14:18 +0000 Subject: [PATCH 16/19] docs(openapi): re-generate OpenAPI specification --- api-reference-v2/openapi_spec.json | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/api-reference-v2/openapi_spec.json b/api-reference-v2/openapi_spec.json index d2fa50d86293..01619b130af8 100644 --- a/api-reference-v2/openapi_spec.json +++ b/api-reference-v2/openapi_spec.json @@ -2646,8 +2646,8 @@ "required": [ "order_amount", "currency", - "skip_external_tax_calculation", - "skip_surcharge_calculation" + "external_tax_calculation", + "surcharge_calculation" ], "properties": { "order_amount": { @@ -2676,10 +2676,10 @@ ], "nullable": true }, - "skip_external_tax_calculation": { + "external_tax_calculation": { "$ref": "#/components/schemas/TaxCalculationOverride" }, - "skip_surcharge_calculation": { + "surcharge_calculation": { "$ref": "#/components/schemas/SurchargeCalculationOverride" }, "surcharge_amount": { @@ -5717,8 +5717,8 @@ "type": "object", "required": [ "currency", - "skip_external_tax_calculation", - "skip_surcharge_calculation", + "external_tax_calculation", + "surcharge_calculation", "net_amount", "amount_capturable" ], @@ -5749,10 +5749,10 @@ ], "nullable": true }, - "skip_external_tax_calculation": { + "external_tax_calculation": { "$ref": "#/components/schemas/TaxCalculationOverride" }, - "skip_surcharge_calculation": { + "surcharge_calculation": { "$ref": "#/components/schemas/SurchargeCalculationOverride" }, "surcharge_amount": { @@ -14504,6 +14504,7 @@ "status", "amount_details", "client_secret", + "profile_id", "capture_method", "authentication_type", "customer_present", @@ -14530,6 +14531,10 @@ "description": "It's a token used for client side verification.", "example": "pay_U42c409qyHwOkWo3vK60_secret_el9ksDkiB8hi6j9N78yo" }, + "profile_id": { + "type": "string", + "description": "The identifier for the profile. This is inferred from the `x-profile-id` header" + }, "merchant_reference_id": { "type": "string", "description": "Unique identifier for the payment. This ensures idempotency for multiple payments\nthat have been done by a single merchant.", @@ -19098,8 +19103,8 @@ "SurchargeCalculationOverride": { "type": "string", "enum": [ - "Skip", - "Calculate" + "skip", + "calculate" ] }, "SurchargeDetailsResponse": { @@ -19200,8 +19205,8 @@ "TaxCalculationOverride": { "type": "string", "enum": [ - "Skip", - "Calculate" + "skip", + "calculate" ] }, "ThirdPartySdkSessionResponse": { From 2b7921ccc8053e1c15d161f54d911e71ee787f7e Mon Sep 17 00:00:00 2001 From: Narayan Bhat Date: Thu, 21 Nov 2024 17:12:26 +0530 Subject: [PATCH 17/19] refactor: add shipping and billing to response --- crates/api_models/src/payments.rs | 6 ++++++ crates/router/src/core/payments.rs | 3 +-- crates/router/src/core/payments/transformers.rs | 5 +++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs index e3d0cf5c9175..56c17bbf2d48 100644 --- a/crates/api_models/src/payments.rs +++ b/crates/api_models/src/payments.rs @@ -4716,6 +4716,12 @@ pub struct PaymentsRetrieveResponse { /// Error details for the payment if any pub error: Option, + + /// The shipping address associated with the payment intent + pub shipping: Option
, + + /// The billing address associated with the payment intent + pub billing: Option
, } #[derive(Debug, serde::Deserialize, serde::Serialize, Clone)] diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs index 90948d3f289a..acad4cb265d0 100644 --- a/crates/router/src/core/payments.rs +++ b/crates/router/src/core/payments.rs @@ -7099,9 +7099,8 @@ impl OperationSessionGetters for PaymentConfirmData { todo!() } - // what is this address find out and not required remove this fn get_address(&self) -> &PaymentAddress { - todo!() + &self.payment_address } fn get_creds_identifier(&self) -> Option<&str> { diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs index fa024bfdf3e4..1c915cdd02de 100644 --- a/crates/router/src/core/payments/transformers.rs +++ b/crates/router/src/core/payments/transformers.rs @@ -1107,6 +1107,11 @@ where status: payment_intent.status, amount, connector, + billing: payment_address + .get_payment_billing() + .cloned() + .map(From::from), + shipping: payment_address.get_shipping().cloned().map(From::from), client_secret: payment_intent.client_secret.clone(), created: payment_intent.created_at, payment_method_data, From 8abb1590c393af6b91db92e130c30c64f64d0799 Mon Sep 17 00:00:00 2001 From: "hyperswitch-bot[bot]" <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:45:28 +0000 Subject: [PATCH 18/19] docs(openapi): re-generate OpenAPI specification --- api-reference-v2/openapi_spec.json | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/api-reference-v2/openapi_spec.json b/api-reference-v2/openapi_spec.json index 01619b130af8..41d6e9caa354 100644 --- a/api-reference-v2/openapi_spec.json +++ b/api-reference-v2/openapi_spec.json @@ -15354,6 +15354,22 @@ } ], "nullable": true + }, + "shipping": { + "allOf": [ + { + "$ref": "#/components/schemas/Address" + } + ], + "nullable": true + }, + "billing": { + "allOf": [ + { + "$ref": "#/components/schemas/Address" + } + ], + "nullable": true } } }, From 654abc7d987bca9adea191b19cbf033d10f66b48 Mon Sep 17 00:00:00 2001 From: Narayan Bhat Date: Wed, 27 Nov 2024 21:57:21 +0530 Subject: [PATCH 19/19] chore: cargo clippy_v2 --- .../core/payments/operations/payment_get.rs | 1 + .../router/src/core/webhooks/incoming_v2.rs | 20 +++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/crates/router/src/core/payments/operations/payment_get.rs b/crates/router/src/core/payments/operations/payment_get.rs index 60b262aca54b..f66186c7c571 100644 --- a/crates/router/src/core/payments/operations/payment_get.rs +++ b/crates/router/src/core/payments/operations/payment_get.rs @@ -163,6 +163,7 @@ impl GetTracker, PaymentsRetrieveReques let should_sync_with_connector = request.force_sync && payment_intent.status.should_force_sync_with_connector(); + // We need the address here to send it in the response let payment_address = hyperswitch_domain_models::payment_address::PaymentAddress::new( payment_intent .shipping_address diff --git a/crates/router/src/core/webhooks/incoming_v2.rs b/crates/router/src/core/webhooks/incoming_v2.rs index 0deb91efaa8d..2e8de1d2592d 100644 --- a/crates/router/src/core/webhooks/incoming_v2.rs +++ b/crates/router/src/core/webhooks/incoming_v2.rs @@ -614,12 +614,32 @@ where } api_models::payments::PaymentIdType::PreprocessingId(ref _id) => todo!(), }; + + // We need the address here to send it in the response + // In case we need to send an outgoing webhook, we might have to send the billing address and shipping address + let payment_address = hyperswitch_domain_models::payment_address::PaymentAddress::new( + payment_intent + .shipping_address + .clone() + .map(|address| address.into_inner()), + payment_intent + .billing_address + .clone() + .map(|address| address.into_inner()), + payment_attempt + .payment_method_billing_address + .clone() + .map(|address| address.into_inner()), + Some(true), + ); + Ok(payments::operations::GetTrackerResponse { payment_data: PaymentStatusData { flow: PhantomData, payment_intent, payment_attempt: Some(payment_attempt), should_sync_with_connector: true, + payment_address, }, }) }