mirror of
https://github.com/juspay/hyperswitch.git
synced 2026-03-13 09:02:06 +08:00
refactor(billing): store payment_method_data_billing for recurring payments (#4513)
Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
This commit is contained in:
@@ -951,6 +951,10 @@ pub struct CustomerPaymentMethod {
|
||||
/// Indicates if the payment method has been set to default or not
|
||||
#[schema(example = true)]
|
||||
pub default_payment_method_set: bool,
|
||||
|
||||
/// The billing details of the payment method
|
||||
#[schema(value_type = Option<Address>)]
|
||||
pub billing: Option<payments::Address>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
|
||||
|
||||
@@ -40,6 +40,7 @@ pub struct PaymentMethod {
|
||||
pub status: storage_enums::PaymentMethodStatus,
|
||||
pub network_transaction_id: Option<String>,
|
||||
pub client_secret: Option<String>,
|
||||
pub payment_method_billing_address: Option<Encryption>,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
@@ -75,43 +76,7 @@ pub struct PaymentMethodNew {
|
||||
pub status: storage_enums::PaymentMethodStatus,
|
||||
pub network_transaction_id: Option<String>,
|
||||
pub client_secret: Option<String>,
|
||||
}
|
||||
|
||||
impl Default for PaymentMethodNew {
|
||||
fn default() -> Self {
|
||||
let now = common_utils::date_time::now();
|
||||
|
||||
Self {
|
||||
customer_id: String::default(),
|
||||
merchant_id: String::default(),
|
||||
payment_method_id: String::default(),
|
||||
locker_id: Option::default(),
|
||||
payment_method: Option::default(),
|
||||
payment_method_type: Option::default(),
|
||||
payment_method_issuer: Option::default(),
|
||||
payment_method_issuer_code: Option::default(),
|
||||
accepted_currency: Option::default(),
|
||||
scheme: Option::default(),
|
||||
token: Option::default(),
|
||||
cardholder_name: Option::default(),
|
||||
issuer_name: Option::default(),
|
||||
issuer_country: Option::default(),
|
||||
payer_country: Option::default(),
|
||||
is_stored: Option::default(),
|
||||
swift_code: Option::default(),
|
||||
direct_debit_token: Option::default(),
|
||||
created_at: now,
|
||||
last_modified: now,
|
||||
metadata: Option::default(),
|
||||
payment_method_data: Option::default(),
|
||||
last_used_at: now,
|
||||
connector_mandate_details: Option::default(),
|
||||
customer_acceptance: Option::default(),
|
||||
status: storage_enums::PaymentMethodStatus::Active,
|
||||
network_transaction_id: Option::default(),
|
||||
client_secret: Option::default(),
|
||||
}
|
||||
}
|
||||
pub payment_method_billing_address: Option<Encryption>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Deserialize, Serialize)]
|
||||
@@ -337,6 +302,9 @@ impl From<&PaymentMethodNew> for PaymentMethod {
|
||||
status: payment_method_new.status,
|
||||
network_transaction_id: payment_method_new.network_transaction_id.clone(),
|
||||
client_secret: payment_method_new.client_secret.clone(),
|
||||
payment_method_billing_address: payment_method_new
|
||||
.payment_method_billing_address
|
||||
.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -926,6 +926,7 @@ diesel::table! {
|
||||
network_transaction_id -> Nullable<Varchar>,
|
||||
#[max_length = 128]
|
||||
client_secret -> Nullable<Varchar>,
|
||||
payment_method_billing_address -> Nullable<Bytea>,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
fmt::Debug,
|
||||
str::FromStr,
|
||||
};
|
||||
|
||||
@@ -88,6 +89,7 @@ pub async fn create_payment_method(
|
||||
status: Option<enums::PaymentMethodStatus>,
|
||||
network_transaction_id: Option<String>,
|
||||
storage_scheme: MerchantStorageScheme,
|
||||
payment_method_billing_address: Option<Encryption>,
|
||||
) -> errors::CustomResult<storage::PaymentMethod, errors::ApiErrorResponse> {
|
||||
let customer = db
|
||||
.find_customer_by_customer_id_merchant_id(
|
||||
@@ -104,6 +106,8 @@ pub async fn create_payment_method(
|
||||
format!("{payment_method_id}_secret").as_str(),
|
||||
);
|
||||
|
||||
let current_time = common_utils::date_time::now();
|
||||
|
||||
let response = db
|
||||
.insert_payment_method(
|
||||
storage::PaymentMethodNew {
|
||||
@@ -122,7 +126,20 @@ pub async fn create_payment_method(
|
||||
client_secret: Some(client_secret),
|
||||
status: status.unwrap_or(enums::PaymentMethodStatus::Active),
|
||||
network_transaction_id: network_transaction_id.to_owned(),
|
||||
..storage::PaymentMethodNew::default()
|
||||
payment_method_issuer_code: None,
|
||||
accepted_currency: None,
|
||||
token: None,
|
||||
cardholder_name: None,
|
||||
issuer_name: None,
|
||||
issuer_country: None,
|
||||
payer_country: None,
|
||||
is_stored: None,
|
||||
swift_code: None,
|
||||
direct_debit_token: None,
|
||||
created_at: current_time,
|
||||
last_modified: current_time,
|
||||
last_used_at: current_time,
|
||||
payment_method_billing_address,
|
||||
},
|
||||
storage_scheme,
|
||||
)
|
||||
@@ -231,6 +248,7 @@ pub async fn get_or_insert_payment_method(
|
||||
None,
|
||||
None,
|
||||
merchant_account.storage_scheme,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
} else {
|
||||
@@ -278,6 +296,7 @@ pub async fn get_client_secret_or_add_payment_method(
|
||||
Some(enums::PaymentMethodStatus::AwaitingData),
|
||||
None,
|
||||
merchant_account.storage_scheme,
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
|
||||
@@ -434,7 +453,7 @@ pub async fn add_payment_method_data(
|
||||
|
||||
let updated_pmd = Some(PaymentMethodsData::Card(updated_card));
|
||||
let pm_data_encrypted =
|
||||
create_encrypted_payment_method_data(&key_store, updated_pmd).await;
|
||||
create_encrypted_data(&key_store, updated_pmd).await;
|
||||
|
||||
let pm_update = storage::PaymentMethodUpdate::AdditionalDataUpdate {
|
||||
payment_method_data: pm_data_encrypted,
|
||||
@@ -644,8 +663,7 @@ pub async fn add_payment_method(
|
||||
let updated_pmd = updated_card.as_ref().map(|card| {
|
||||
PaymentMethodsData::Card(CardDetailsPaymentMethod::from(card.clone()))
|
||||
});
|
||||
let pm_data_encrypted =
|
||||
create_encrypted_payment_method_data(key_store, updated_pmd).await;
|
||||
let pm_data_encrypted = create_encrypted_data(key_store, updated_pmd).await;
|
||||
|
||||
let pm_update = storage::PaymentMethodUpdate::PaymentMethodDataUpdate {
|
||||
payment_method_data: pm_data_encrypted,
|
||||
@@ -688,6 +706,7 @@ pub async fn add_payment_method(
|
||||
None,
|
||||
None,
|
||||
merchant_account.storage_scheme,
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
|
||||
@@ -712,12 +731,13 @@ pub async fn insert_payment_method(
|
||||
connector_mandate_details: Option<serde_json::Value>,
|
||||
network_transaction_id: Option<String>,
|
||||
storage_scheme: MerchantStorageScheme,
|
||||
payment_method_billing_address: Option<Encryption>,
|
||||
) -> errors::RouterResult<diesel_models::PaymentMethod> {
|
||||
let pm_card_details = resp
|
||||
.card
|
||||
.as_ref()
|
||||
.map(|card| PaymentMethodsData::Card(CardDetailsPaymentMethod::from(card.clone())));
|
||||
let pm_data_encrypted = create_encrypted_payment_method_data(key_store, pm_card_details).await;
|
||||
let pm_data_encrypted = create_encrypted_data(key_store, pm_card_details).await;
|
||||
create_payment_method(
|
||||
db,
|
||||
&req,
|
||||
@@ -733,6 +753,7 @@ pub async fn insert_payment_method(
|
||||
None,
|
||||
network_transaction_id,
|
||||
storage_scheme,
|
||||
payment_method_billing_address,
|
||||
)
|
||||
.await
|
||||
}
|
||||
@@ -891,8 +912,7 @@ pub async fn update_customer_payment_method(
|
||||
let updated_pmd = updated_card
|
||||
.as_ref()
|
||||
.map(|card| PaymentMethodsData::Card(CardDetailsPaymentMethod::from(card.clone())));
|
||||
let pm_data_encrypted =
|
||||
create_encrypted_payment_method_data(&key_store, updated_pmd).await;
|
||||
let pm_data_encrypted = create_encrypted_data(&key_store, updated_pmd).await;
|
||||
|
||||
let pm_update = storage::PaymentMethodUpdate::PaymentMethodDataUpdate {
|
||||
payment_method_data: pm_data_encrypted,
|
||||
@@ -3463,8 +3483,14 @@ pub async fn list_customer_payment_method(
|
||||
None
|
||||
};
|
||||
|
||||
//Need validation for enabled payment method ,querying MCA
|
||||
let payment_method_billing = decrypt_generic_data::<api_models::payments::Address>(
|
||||
pm.payment_method_billing_address,
|
||||
key,
|
||||
)
|
||||
.await
|
||||
.attach_printable("unable to decrypt payment method billing address details")?;
|
||||
|
||||
// Need validation for enabled payment method ,querying MCA
|
||||
let pma = api::CustomerPaymentMethod {
|
||||
payment_token: parent_payment_method_token.to_owned(),
|
||||
payment_method_id: pm.payment_method_id.clone(),
|
||||
@@ -3488,6 +3514,7 @@ pub async fn list_customer_payment_method(
|
||||
last_used_at: Some(pm.last_used_at),
|
||||
default_payment_method_set: customer.default_payment_method_id.is_some()
|
||||
&& customer.default_payment_method_id == Some(pm.payment_method_id),
|
||||
billing: payment_method_billing,
|
||||
};
|
||||
customer_pms.push(pma.to_owned());
|
||||
|
||||
@@ -3605,6 +3632,27 @@ pub async fn list_customer_payment_method(
|
||||
Ok(services::ApplicationResponse::Json(response))
|
||||
}
|
||||
|
||||
pub async fn decrypt_generic_data<T>(
|
||||
data: Option<Encryption>,
|
||||
key: &[u8],
|
||||
) -> errors::RouterResult<Option<T>>
|
||||
where
|
||||
T: serde::de::DeserializeOwned,
|
||||
{
|
||||
let decrypted_data = decrypt::<serde_json::Value, masking::WithType>(data, key)
|
||||
.await
|
||||
.change_context(errors::StorageError::DecryptionError)
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("unable to decrypt data")?;
|
||||
|
||||
decrypted_data
|
||||
.map(|decrypted_data| decrypted_data.into_inner().expose())
|
||||
.map(|decrypted_value| decrypted_value.parse_value("generic_data"))
|
||||
.transpose()
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("unable to parse generic data value")
|
||||
}
|
||||
|
||||
pub async fn get_card_details_with_locker_fallback(
|
||||
pm: &payment_method::PaymentMethod,
|
||||
key: &[u8],
|
||||
@@ -4171,18 +4219,21 @@ pub async fn delete_payment_method(
|
||||
))
|
||||
}
|
||||
|
||||
pub async fn create_encrypted_payment_method_data(
|
||||
pub async fn create_encrypted_data<T>(
|
||||
key_store: &domain::MerchantKeyStore,
|
||||
pm_data: Option<PaymentMethodsData>,
|
||||
) -> Option<Encryption> {
|
||||
data: Option<T>,
|
||||
) -> Option<Encryption>
|
||||
where
|
||||
T: Debug + serde::Serialize,
|
||||
{
|
||||
let key = key_store.key.get_inner().peek();
|
||||
|
||||
let pm_data_encrypted: Option<Encryption> = pm_data
|
||||
let encrypted_data: Option<Encryption> = data
|
||||
.as_ref()
|
||||
.map(Encode::encode_to_value)
|
||||
.transpose()
|
||||
.change_context(errors::StorageError::SerializationFailed)
|
||||
.attach_printable("Unable to convert payment method data to a value")
|
||||
.attach_printable("Unable to convert data to a value")
|
||||
.unwrap_or_else(|err| {
|
||||
logger::error!(err=?err);
|
||||
None
|
||||
@@ -4191,14 +4242,14 @@ pub async fn create_encrypted_payment_method_data(
|
||||
.async_lift(|inner| encrypt_optional(inner, key))
|
||||
.await
|
||||
.change_context(errors::StorageError::EncryptionError)
|
||||
.attach_printable("Unable to encrypt payment method data")
|
||||
.attach_printable("Unable to encrypt data")
|
||||
.unwrap_or_else(|err| {
|
||||
logger::error!(err=?err);
|
||||
None
|
||||
})
|
||||
.map(|details| details.into());
|
||||
|
||||
pm_data_encrypted
|
||||
encrypted_data
|
||||
}
|
||||
|
||||
pub async fn list_countries_currencies_for_connector_payment_method(
|
||||
|
||||
@@ -214,6 +214,7 @@ pub async fn create_or_update_address_for_payment_by_request(
|
||||
storage_scheme,
|
||||
)
|
||||
.await
|
||||
.map(|payment_address| payment_address.address)
|
||||
.to_not_found_response(errors::ApiErrorResponse::AddressNotFound)?,
|
||||
)
|
||||
}
|
||||
@@ -225,38 +226,39 @@ pub async fn create_or_update_address_for_payment_by_request(
|
||||
merchant_key_store,
|
||||
storage_scheme,
|
||||
)
|
||||
.await,
|
||||
.await
|
||||
.map(|payment_address| payment_address.address),
|
||||
)
|
||||
.transpose()
|
||||
.to_not_found_response(errors::ApiErrorResponse::AddressNotFound)?,
|
||||
},
|
||||
None => match req_address {
|
||||
Some(address) => {
|
||||
// generate a new address here
|
||||
let address_details = address.address.clone().unwrap_or_default();
|
||||
let address = get_domain_address(address, merchant_id, key, storage_scheme)
|
||||
.await
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Failed while encrypting address while insert")?;
|
||||
|
||||
let payment_address = domain::PaymentAddress {
|
||||
address,
|
||||
payment_id: payment_id.to_string(),
|
||||
customer_id: customer_id.cloned(),
|
||||
};
|
||||
|
||||
Some(
|
||||
db.insert_address_for_payments(
|
||||
payment_id,
|
||||
get_domain_address_for_payments(
|
||||
address_details,
|
||||
address,
|
||||
merchant_id,
|
||||
customer_id,
|
||||
payment_id,
|
||||
key,
|
||||
storage_scheme,
|
||||
)
|
||||
.await
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Failed while encrypting address while insert")?,
|
||||
payment_address,
|
||||
merchant_key_store,
|
||||
storage_scheme,
|
||||
)
|
||||
.await
|
||||
.map(|payment_address| payment_address.address)
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Failed while inserting new address")?,
|
||||
)
|
||||
}
|
||||
|
||||
None => None,
|
||||
},
|
||||
})
|
||||
@@ -285,34 +287,34 @@ pub async fn create_or_find_address_for_payment_by_request(
|
||||
merchant_key_store,
|
||||
storage_scheme,
|
||||
)
|
||||
.await,
|
||||
.await
|
||||
.map(|payment_address| payment_address.address),
|
||||
)
|
||||
.transpose()
|
||||
.to_not_found_response(errors::ApiErrorResponse::AddressNotFound)?,
|
||||
None => match req_address {
|
||||
Some(address) => {
|
||||
// generate a new address here
|
||||
let address = get_domain_address(address, merchant_id, key, storage_scheme)
|
||||
.await
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Failed while encrypting address while insert")?;
|
||||
|
||||
let payment_address = domain::PaymentAddress {
|
||||
address,
|
||||
payment_id: payment_id.to_string(),
|
||||
customer_id: customer_id.cloned(),
|
||||
};
|
||||
|
||||
let address_details = address.address.clone().unwrap_or_default();
|
||||
Some(
|
||||
db.insert_address_for_payments(
|
||||
payment_id,
|
||||
get_domain_address_for_payments(
|
||||
address_details,
|
||||
address,
|
||||
merchant_id,
|
||||
customer_id,
|
||||
payment_id,
|
||||
key,
|
||||
storage_scheme,
|
||||
)
|
||||
.await
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Failed while encrypting address while insert")?,
|
||||
payment_address,
|
||||
merchant_key_store,
|
||||
storage_scheme,
|
||||
)
|
||||
.await
|
||||
.map(|payment_address| payment_address.address)
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Failed while inserting new address")?,
|
||||
)
|
||||
@@ -322,16 +324,14 @@ pub async fn create_or_find_address_for_payment_by_request(
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn get_domain_address_for_payments(
|
||||
address_details: api_models::payments::AddressDetails,
|
||||
pub async fn get_domain_address(
|
||||
address: &api_models::payments::Address,
|
||||
merchant_id: &str,
|
||||
customer_id: Option<&String>,
|
||||
payment_id: &str,
|
||||
key: &[u8],
|
||||
storage_scheme: enums::MerchantStorageScheme,
|
||||
) -> CustomResult<domain::Address, common_utils::errors::CryptoError> {
|
||||
async {
|
||||
let address_details = address.address.as_ref();
|
||||
Ok(domain::Address {
|
||||
id: None,
|
||||
phone_number: address
|
||||
@@ -341,42 +341,40 @@ pub async fn get_domain_address_for_payments(
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
country_code: address.phone.as_ref().and_then(|a| a.country_code.clone()),
|
||||
customer_id: customer_id.cloned(),
|
||||
merchant_id: merchant_id.to_string(),
|
||||
address_id: generate_id(consts::ID_LENGTH, "add"),
|
||||
city: address_details.city,
|
||||
country: address_details.country,
|
||||
city: address_details.and_then(|address_details| address_details.city.clone()),
|
||||
country: address_details.and_then(|address_details| address_details.country),
|
||||
line1: address_details
|
||||
.line1
|
||||
.and_then(|address_details| address_details.line1.clone())
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
line2: address_details
|
||||
.line2
|
||||
.and_then(|address_details| address_details.line2.clone())
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
line3: address_details
|
||||
.line3
|
||||
.and_then(|address_details| address_details.line3.clone())
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
state: address_details
|
||||
.state
|
||||
.and_then(|address_details| address_details.state.clone())
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
created_at: common_utils::date_time::now(),
|
||||
first_name: address_details
|
||||
.first_name
|
||||
.and_then(|address_details| address_details.first_name.clone())
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
last_name: address_details
|
||||
.last_name
|
||||
.and_then(|address_details| address_details.last_name.clone())
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
modified_at: common_utils::date_time::now(),
|
||||
zip: address_details
|
||||
.zip
|
||||
.and_then(|address_details| address_details.zip.clone())
|
||||
.async_lift(|inner| types::encrypt_optional(inner, key))
|
||||
.await?,
|
||||
payment_id: Some(payment_id.to_owned()),
|
||||
updated_by: storage_scheme.to_string(),
|
||||
email: address
|
||||
.email
|
||||
@@ -408,6 +406,7 @@ pub async fn get_address_by_id(
|
||||
storage_scheme,
|
||||
)
|
||||
.await
|
||||
.map(|payment_address| payment_address.address)
|
||||
.ok()),
|
||||
}
|
||||
}
|
||||
@@ -461,7 +460,7 @@ pub async fn get_token_pm_type_mandate_details(
|
||||
None,
|
||||
mandate_generic_data.recurring_mandate_payment_data,
|
||||
mandate_generic_data.mandate_connector,
|
||||
None,
|
||||
mandate_generic_data.payment_method_info,
|
||||
)
|
||||
}
|
||||
RecurringDetails::PaymentMethodId(payment_method_id) => {
|
||||
@@ -515,7 +514,7 @@ pub async fn get_token_pm_type_mandate_details(
|
||||
None,
|
||||
mandate_generic_data.recurring_mandate_payment_data,
|
||||
mandate_generic_data.mandate_connector,
|
||||
None,
|
||||
mandate_generic_data.payment_method_info,
|
||||
)
|
||||
} else {
|
||||
(
|
||||
@@ -673,7 +672,7 @@ pub async fn get_token_for_recurring_mandate(
|
||||
payment_method_type: payment_method.payment_method_type,
|
||||
mandate_connector: Some(mandate_connector_details),
|
||||
mandate_data: None,
|
||||
payment_method_info: None,
|
||||
payment_method_info: Some(payment_method),
|
||||
})
|
||||
} else {
|
||||
Ok(MandateGenericData {
|
||||
@@ -687,7 +686,7 @@ pub async fn get_token_for_recurring_mandate(
|
||||
payment_method_type: payment_method.payment_method_type,
|
||||
mandate_connector: Some(mandate_connector_details),
|
||||
mandate_data: None,
|
||||
payment_method_info: None,
|
||||
payment_method_info: Some(payment_method),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -471,6 +471,7 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
|
||||
}
|
||||
.in_current_span(),
|
||||
);
|
||||
|
||||
let mandate_type = m_helpers::get_mandate_type(
|
||||
request.mandate_data.clone(),
|
||||
request.off_session,
|
||||
@@ -560,6 +561,7 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
|
||||
} else {
|
||||
(None, payment_method_info)
|
||||
};
|
||||
|
||||
// The operation merges mandate data from both request and payment_attempt
|
||||
let setup_mandate = mandate_data.map(|mut sm| {
|
||||
sm.mandate_type = payment_attempt.mandate_details.clone().or(sm.mandate_type);
|
||||
|
||||
@@ -95,6 +95,7 @@ impl<F: Send + Clone> PostUpdateTracker<F, PaymentData<F>, types::PaymentsAuthor
|
||||
{
|
||||
let customer_id = payment_data.payment_intent.customer_id.clone();
|
||||
let save_payment_data = tokenization::SavePaymentMethodData::from(resp);
|
||||
let payment_method_billing_address = payment_data.address.get_payment_method_billing();
|
||||
|
||||
let connector_name = payment_data
|
||||
.payment_attempt
|
||||
@@ -125,6 +126,7 @@ impl<F: Send + Clone> PostUpdateTracker<F, PaymentData<F>, types::PaymentsAuthor
|
||||
Some(resp.request.amount),
|
||||
Some(resp.request.currency),
|
||||
billing_name.clone(),
|
||||
payment_method_billing_address,
|
||||
business_profile,
|
||||
));
|
||||
|
||||
@@ -178,6 +180,7 @@ impl<F: Send + Clone> PostUpdateTracker<F, PaymentData<F>, types::PaymentsAuthor
|
||||
let currency = resp.request.currency;
|
||||
let payment_method_type = resp.request.payment_method_type;
|
||||
let storage_scheme = merchant_account.clone().storage_scheme;
|
||||
let payment_method_billing_address = payment_method_billing_address.cloned();
|
||||
|
||||
logger::info!("Call to save_payment_method in locker");
|
||||
let _task_handle = tokio::spawn(
|
||||
@@ -196,6 +199,7 @@ impl<F: Send + Clone> PostUpdateTracker<F, PaymentData<F>, types::PaymentsAuthor
|
||||
Some(amount),
|
||||
Some(currency),
|
||||
billing_name,
|
||||
payment_method_billing_address.as_ref(),
|
||||
&business_profile,
|
||||
))
|
||||
.await;
|
||||
@@ -599,6 +603,7 @@ impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::SetupMandateRequestDa
|
||||
.get_payment_method_billing()
|
||||
.and_then(|billing_details| billing_details.address.as_ref())
|
||||
.and_then(|address| address.get_optional_full_name());
|
||||
|
||||
let save_payment_data = tokenization::SavePaymentMethodData::from(resp);
|
||||
let customer_id = payment_data.payment_intent.customer_id.clone();
|
||||
let connector_name = payment_data
|
||||
@@ -625,6 +630,7 @@ impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::SetupMandateRequestDa
|
||||
resp.request.amount,
|
||||
Some(resp.request.currency),
|
||||
billing_name,
|
||||
None,
|
||||
business_profile,
|
||||
))
|
||||
.await?;
|
||||
|
||||
@@ -65,6 +65,7 @@ pub async fn save_payment_method<FData>(
|
||||
amount: Option<i64>,
|
||||
currency: Option<storage_enums::Currency>,
|
||||
billing_name: Option<masking::Secret<String>>,
|
||||
payment_method_billing_address: Option<&api::Address>,
|
||||
business_profile: &storage::business_profile::BusinessProfile,
|
||||
) -> RouterResult<(Option<String>, Option<common_enums::PaymentMethodStatus>)>
|
||||
where
|
||||
@@ -209,9 +210,12 @@ where
|
||||
});
|
||||
|
||||
let pm_data_encrypted =
|
||||
payment_methods::cards::create_encrypted_payment_method_data(
|
||||
payment_methods::cards::create_encrypted_data(key_store, pm_card_details).await;
|
||||
|
||||
let encrypted_payment_method_billing_address =
|
||||
payment_methods::cards::create_encrypted_data(
|
||||
key_store,
|
||||
pm_card_details,
|
||||
payment_method_billing_address,
|
||||
)
|
||||
.await;
|
||||
|
||||
@@ -315,6 +319,7 @@ where
|
||||
None,
|
||||
network_transaction_id,
|
||||
merchant_account.storage_scheme,
|
||||
encrypted_payment_method_billing_address,
|
||||
)
|
||||
.await
|
||||
} else {
|
||||
@@ -404,6 +409,7 @@ where
|
||||
connector_mandate_details,
|
||||
network_transaction_id,
|
||||
merchant_account.storage_scheme,
|
||||
encrypted_payment_method_billing_address,
|
||||
)
|
||||
.await
|
||||
} else {
|
||||
@@ -486,7 +492,7 @@ where
|
||||
))
|
||||
});
|
||||
let pm_data_encrypted =
|
||||
payment_methods::cards::create_encrypted_payment_method_data(
|
||||
payment_methods::cards::create_encrypted_data(
|
||||
key_store,
|
||||
updated_pmd,
|
||||
)
|
||||
@@ -535,6 +541,7 @@ where
|
||||
None,
|
||||
network_transaction_id,
|
||||
merchant_account.storage_scheme,
|
||||
encrypted_payment_method_billing_address,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
||||
@@ -452,7 +452,7 @@ pub async fn save_payout_data_to_locker(
|
||||
)
|
||||
});
|
||||
(
|
||||
cards::create_encrypted_payment_method_data(key_store, Some(pm_data)).await,
|
||||
cards::create_encrypted_data(key_store, Some(pm_data)).await,
|
||||
payment_method,
|
||||
)
|
||||
} else {
|
||||
@@ -495,6 +495,7 @@ pub async fn save_payout_data_to_locker(
|
||||
None,
|
||||
None,
|
||||
merchant_account.storage_scheme,
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
||||
@@ -420,7 +420,7 @@ async fn store_bank_details_in_payment_methods(
|
||||
|
||||
let payment_method_data = payment_methods::PaymentMethodsData::BankDetails(pmd);
|
||||
let encrypted_data =
|
||||
cards::create_encrypted_payment_method_data(&key_store, Some(payment_method_data))
|
||||
cards::create_encrypted_data(&key_store, Some(payment_method_data))
|
||||
.await
|
||||
.ok_or(ApiErrorResponse::InternalServerError)?;
|
||||
let pm_update = storage::PaymentMethodUpdate::PaymentMethodDataUpdate {
|
||||
@@ -431,21 +431,42 @@ async fn store_bank_details_in_payment_methods(
|
||||
} else {
|
||||
let payment_method_data = payment_methods::PaymentMethodsData::BankDetails(pmd);
|
||||
let encrypted_data =
|
||||
cards::create_encrypted_payment_method_data(&key_store, Some(payment_method_data))
|
||||
cards::create_encrypted_data(&key_store, Some(payment_method_data))
|
||||
.await
|
||||
.ok_or(ApiErrorResponse::InternalServerError)?;
|
||||
let pm_id = generate_id(consts::ID_LENGTH, "pm");
|
||||
let now = common_utils::date_time::now();
|
||||
let pm_new = storage::PaymentMethodNew {
|
||||
customer_id: customer_id.clone(),
|
||||
merchant_id: merchant_account.merchant_id.clone(),
|
||||
payment_method_id: pm_id,
|
||||
payment_method: Some(enums::PaymentMethod::BankDebit),
|
||||
payment_method_type: Some(creds.payment_method_type),
|
||||
status: enums::PaymentMethodStatus::Active,
|
||||
payment_method_issuer: None,
|
||||
scheme: None,
|
||||
metadata: None,
|
||||
payment_method_data: Some(encrypted_data),
|
||||
..storage::PaymentMethodNew::default()
|
||||
payment_method_issuer_code: None,
|
||||
accepted_currency: None,
|
||||
token: None,
|
||||
cardholder_name: None,
|
||||
issuer_name: None,
|
||||
issuer_country: None,
|
||||
payer_country: None,
|
||||
is_stored: None,
|
||||
swift_code: None,
|
||||
direct_debit_token: None,
|
||||
created_at: now,
|
||||
last_modified: now,
|
||||
locker_id: None,
|
||||
last_used_at: now,
|
||||
connector_mandate_details: None,
|
||||
customer_acceptance: None,
|
||||
|
||||
network_transaction_id: None,
|
||||
client_secret: None,
|
||||
payment_method_billing_address: None,
|
||||
};
|
||||
|
||||
new_entries.push(pm_new);
|
||||
|
||||
@@ -28,12 +28,12 @@ where
|
||||
|
||||
async fn update_address_for_payments(
|
||||
&self,
|
||||
this: domain::Address,
|
||||
this: domain::PaymentAddress,
|
||||
address: domain::AddressUpdate,
|
||||
payment_id: String,
|
||||
key_store: &domain::MerchantKeyStore,
|
||||
storage_scheme: MerchantStorageScheme,
|
||||
) -> CustomResult<domain::Address, errors::StorageError>;
|
||||
) -> CustomResult<domain::PaymentAddress, errors::StorageError>;
|
||||
|
||||
async fn find_address_by_address_id(
|
||||
&self,
|
||||
@@ -44,14 +44,14 @@ where
|
||||
async fn insert_address_for_payments(
|
||||
&self,
|
||||
payment_id: &str,
|
||||
address: domain::Address,
|
||||
address: domain::PaymentAddress,
|
||||
key_store: &domain::MerchantKeyStore,
|
||||
storage_scheme: MerchantStorageScheme,
|
||||
) -> CustomResult<domain::Address, errors::StorageError>;
|
||||
) -> CustomResult<domain::PaymentAddress, errors::StorageError>;
|
||||
|
||||
async fn insert_address_for_customers(
|
||||
&self,
|
||||
address: domain::Address,
|
||||
address: domain::CustomerAddress,
|
||||
key_store: &domain::MerchantKeyStore,
|
||||
) -> CustomResult<domain::Address, errors::StorageError>;
|
||||
|
||||
@@ -62,7 +62,7 @@ where
|
||||
address_id: &str,
|
||||
key_store: &domain::MerchantKeyStore,
|
||||
storage_scheme: MerchantStorageScheme,
|
||||
) -> CustomResult<domain::Address, errors::StorageError>;
|
||||
) -> CustomResult<domain::PaymentAddress, errors::StorageError>;
|
||||
|
||||
async fn update_address_by_merchant_id_customer_id(
|
||||
&self,
|
||||
@@ -121,7 +121,7 @@ mod storage {
|
||||
address_id: &str,
|
||||
key_store: &domain::MerchantKeyStore,
|
||||
_storage_scheme: MerchantStorageScheme,
|
||||
) -> CustomResult<domain::Address, errors::StorageError> {
|
||||
) -> CustomResult<domain::PaymentAddress, errors::StorageError> {
|
||||
let conn = connection::pg_connection_read(self).await?;
|
||||
storage_types::Address::find_by_merchant_id_payment_id_address_id(
|
||||
&conn,
|
||||
@@ -163,12 +163,12 @@ mod storage {
|
||||
#[instrument(skip_all)]
|
||||
async fn update_address_for_payments(
|
||||
&self,
|
||||
this: domain::Address,
|
||||
this: domain::PaymentAddress,
|
||||
address_update: domain::AddressUpdate,
|
||||
_payment_id: String,
|
||||
key_store: &domain::MerchantKeyStore,
|
||||
_storage_scheme: MerchantStorageScheme,
|
||||
) -> CustomResult<domain::Address, errors::StorageError> {
|
||||
) -> CustomResult<domain::PaymentAddress, errors::StorageError> {
|
||||
let conn = connection::pg_connection_write(self).await?;
|
||||
let address = Conversion::convert(this)
|
||||
.await
|
||||
@@ -190,10 +190,10 @@ mod storage {
|
||||
async fn insert_address_for_payments(
|
||||
&self,
|
||||
_payment_id: &str,
|
||||
address: domain::Address,
|
||||
address: domain::PaymentAddress,
|
||||
key_store: &domain::MerchantKeyStore,
|
||||
_storage_scheme: MerchantStorageScheme,
|
||||
) -> CustomResult<domain::Address, errors::StorageError> {
|
||||
) -> CustomResult<domain::PaymentAddress, errors::StorageError> {
|
||||
let conn = connection::pg_connection_write(self).await?;
|
||||
address
|
||||
.construct_new()
|
||||
@@ -214,7 +214,7 @@ mod storage {
|
||||
#[instrument(skip_all)]
|
||||
async fn insert_address_for_customers(
|
||||
&self,
|
||||
address: domain::Address,
|
||||
address: domain::CustomerAddress,
|
||||
key_store: &domain::MerchantKeyStore,
|
||||
) -> CustomResult<domain::Address, errors::StorageError> {
|
||||
let conn = connection::pg_connection_write(self).await?;
|
||||
@@ -320,7 +320,7 @@ mod storage {
|
||||
address_id: &str,
|
||||
key_store: &domain::MerchantKeyStore,
|
||||
storage_scheme: MerchantStorageScheme,
|
||||
) -> CustomResult<domain::Address, errors::StorageError> {
|
||||
) -> CustomResult<domain::PaymentAddress, errors::StorageError> {
|
||||
let conn = connection::pg_connection_read(self).await?;
|
||||
let database_call = || async {
|
||||
storage_types::Address::find_by_merchant_id_payment_id_address_id(
|
||||
@@ -384,12 +384,12 @@ mod storage {
|
||||
#[instrument(skip_all)]
|
||||
async fn update_address_for_payments(
|
||||
&self,
|
||||
this: domain::Address,
|
||||
this: domain::PaymentAddress,
|
||||
address_update: domain::AddressUpdate,
|
||||
payment_id: String,
|
||||
key_store: &domain::MerchantKeyStore,
|
||||
storage_scheme: MerchantStorageScheme,
|
||||
) -> CustomResult<domain::Address, errors::StorageError> {
|
||||
) -> CustomResult<domain::PaymentAddress, errors::StorageError> {
|
||||
let conn = connection::pg_connection_write(self).await?;
|
||||
let address = Conversion::convert(this)
|
||||
.await
|
||||
@@ -456,10 +456,10 @@ mod storage {
|
||||
async fn insert_address_for_payments(
|
||||
&self,
|
||||
payment_id: &str,
|
||||
address: domain::Address,
|
||||
address: domain::PaymentAddress,
|
||||
key_store: &domain::MerchantKeyStore,
|
||||
storage_scheme: MerchantStorageScheme,
|
||||
) -> CustomResult<domain::Address, errors::StorageError> {
|
||||
) -> CustomResult<domain::PaymentAddress, errors::StorageError> {
|
||||
let address_new = address
|
||||
.clone()
|
||||
.construct_new()
|
||||
@@ -547,7 +547,7 @@ mod storage {
|
||||
#[instrument(skip_all)]
|
||||
async fn insert_address_for_customers(
|
||||
&self,
|
||||
address: domain::Address,
|
||||
address: domain::CustomerAddress,
|
||||
key_store: &domain::MerchantKeyStore,
|
||||
) -> CustomResult<domain::Address, errors::StorageError> {
|
||||
let conn = connection::pg_connection_write(self).await?;
|
||||
@@ -635,7 +635,7 @@ impl AddressInterface for MockDb {
|
||||
address_id: &str,
|
||||
key_store: &domain::MerchantKeyStore,
|
||||
_storage_scheme: MerchantStorageScheme,
|
||||
) -> CustomResult<domain::Address, errors::StorageError> {
|
||||
) -> CustomResult<domain::PaymentAddress, errors::StorageError> {
|
||||
match self
|
||||
.addresses
|
||||
.lock()
|
||||
@@ -688,18 +688,18 @@ impl AddressInterface for MockDb {
|
||||
|
||||
async fn update_address_for_payments(
|
||||
&self,
|
||||
this: domain::Address,
|
||||
this: domain::PaymentAddress,
|
||||
address_update: domain::AddressUpdate,
|
||||
_payment_id: String,
|
||||
key_store: &domain::MerchantKeyStore,
|
||||
_storage_scheme: MerchantStorageScheme,
|
||||
) -> CustomResult<domain::Address, errors::StorageError> {
|
||||
) -> CustomResult<domain::PaymentAddress, errors::StorageError> {
|
||||
let updated_addr = self
|
||||
.addresses
|
||||
.lock()
|
||||
.await
|
||||
.iter_mut()
|
||||
.find(|address| address.address_id == this.address_id)
|
||||
.find(|address| address.address_id == this.address.address_id)
|
||||
.map(|a| {
|
||||
let address_updated =
|
||||
AddressUpdateInternal::from(address_update).create_address(a.clone());
|
||||
@@ -721,10 +721,10 @@ impl AddressInterface for MockDb {
|
||||
async fn insert_address_for_payments(
|
||||
&self,
|
||||
_payment_id: &str,
|
||||
address_new: domain::Address,
|
||||
address_new: domain::PaymentAddress,
|
||||
key_store: &domain::MerchantKeyStore,
|
||||
_storage_scheme: MerchantStorageScheme,
|
||||
) -> CustomResult<domain::Address, errors::StorageError> {
|
||||
) -> CustomResult<domain::PaymentAddress, errors::StorageError> {
|
||||
let mut addresses = self.addresses.lock().await;
|
||||
|
||||
let address = Conversion::convert(address_new)
|
||||
@@ -741,7 +741,7 @@ impl AddressInterface for MockDb {
|
||||
|
||||
async fn insert_address_for_customers(
|
||||
&self,
|
||||
address_new: domain::Address,
|
||||
address_new: domain::CustomerAddress,
|
||||
key_store: &domain::MerchantKeyStore,
|
||||
) -> CustomResult<domain::Address, errors::StorageError> {
|
||||
let mut addresses = self.addresses.lock().await;
|
||||
|
||||
@@ -121,12 +121,12 @@ impl AddressInterface for KafkaStore {
|
||||
|
||||
async fn update_address_for_payments(
|
||||
&self,
|
||||
this: domain::Address,
|
||||
this: domain::PaymentAddress,
|
||||
address: domain::AddressUpdate,
|
||||
payment_id: String,
|
||||
key_store: &domain::MerchantKeyStore,
|
||||
storage_scheme: MerchantStorageScheme,
|
||||
) -> CustomResult<domain::Address, errors::StorageError> {
|
||||
) -> CustomResult<domain::PaymentAddress, errors::StorageError> {
|
||||
self.diesel_store
|
||||
.update_address_for_payments(this, address, payment_id, key_store, storage_scheme)
|
||||
.await
|
||||
@@ -135,10 +135,10 @@ impl AddressInterface for KafkaStore {
|
||||
async fn insert_address_for_payments(
|
||||
&self,
|
||||
payment_id: &str,
|
||||
address: domain::Address,
|
||||
address: domain::PaymentAddress,
|
||||
key_store: &domain::MerchantKeyStore,
|
||||
storage_scheme: MerchantStorageScheme,
|
||||
) -> CustomResult<domain::Address, errors::StorageError> {
|
||||
) -> CustomResult<domain::PaymentAddress, errors::StorageError> {
|
||||
self.diesel_store
|
||||
.insert_address_for_payments(payment_id, address, key_store, storage_scheme)
|
||||
.await
|
||||
@@ -151,7 +151,7 @@ impl AddressInterface for KafkaStore {
|
||||
address_id: &str,
|
||||
key_store: &domain::MerchantKeyStore,
|
||||
storage_scheme: MerchantStorageScheme,
|
||||
) -> CustomResult<domain::Address, errors::StorageError> {
|
||||
) -> CustomResult<domain::PaymentAddress, errors::StorageError> {
|
||||
self.diesel_store
|
||||
.find_address_by_merchant_id_payment_id_address_id(
|
||||
merchant_id,
|
||||
@@ -165,7 +165,7 @@ impl AddressInterface for KafkaStore {
|
||||
|
||||
async fn insert_address_for_customers(
|
||||
&self,
|
||||
address: domain::Address,
|
||||
address: domain::CustomerAddress,
|
||||
key_store: &domain::MerchantKeyStore,
|
||||
) -> CustomResult<domain::Address, errors::StorageError> {
|
||||
self.diesel_store
|
||||
|
||||
@@ -662,6 +662,7 @@ impl PaymentMethodInterface for MockDb {
|
||||
status: payment_method_new.status,
|
||||
client_secret: payment_method_new.client_secret,
|
||||
network_transaction_id: payment_method_new.network_transaction_id,
|
||||
payment_method_billing_address: payment_method_new.payment_method_billing_address,
|
||||
};
|
||||
payment_methods.push(payment_method.clone());
|
||||
Ok(payment_method)
|
||||
|
||||
@@ -35,13 +35,119 @@ pub struct Address {
|
||||
#[serde(skip_serializing)]
|
||||
#[serde(with = "custom_serde::iso8601")]
|
||||
pub modified_at: PrimitiveDateTime,
|
||||
pub customer_id: Option<String>,
|
||||
pub merchant_id: String,
|
||||
pub payment_id: Option<String>,
|
||||
pub updated_by: String,
|
||||
pub email: crypto::OptionalEncryptableEmail,
|
||||
}
|
||||
|
||||
/// Based on the flow, appropriate address has to be used
|
||||
/// In case of Payments, The `PaymentAddress`[PaymentAddress] has to be used
|
||||
/// which contains only the `Address`[Address] object and `payment_id` and optional `customer_id`
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PaymentAddress {
|
||||
pub address: Address,
|
||||
pub payment_id: String,
|
||||
// This is present in `PaymentAddress` because even `payouts` uses `PaymentAddress`
|
||||
pub customer_id: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CustomerAddress {
|
||||
pub address: Address,
|
||||
pub customer_id: String,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl behaviour::Conversion for CustomerAddress {
|
||||
type DstType = diesel_models::address::Address;
|
||||
type NewDstType = diesel_models::address::AddressNew;
|
||||
|
||||
async fn convert(self) -> CustomResult<Self::DstType, ValidationError> {
|
||||
let converted_address = Address::convert(self.address).await?;
|
||||
Ok(diesel_models::address::Address {
|
||||
customer_id: Some(self.customer_id),
|
||||
payment_id: None,
|
||||
..converted_address
|
||||
})
|
||||
}
|
||||
|
||||
async fn convert_back(
|
||||
other: Self::DstType,
|
||||
key: &Secret<Vec<u8>>,
|
||||
) -> CustomResult<Self, ValidationError> {
|
||||
let customer_id =
|
||||
other
|
||||
.customer_id
|
||||
.clone()
|
||||
.ok_or(ValidationError::MissingRequiredField {
|
||||
field_name: "cutomer_id".to_string(),
|
||||
})?;
|
||||
|
||||
let address = Address::convert_back(other, key).await?;
|
||||
|
||||
Ok(Self {
|
||||
address,
|
||||
customer_id,
|
||||
})
|
||||
}
|
||||
|
||||
async fn construct_new(self) -> CustomResult<Self::NewDstType, ValidationError> {
|
||||
let address_new = Address::construct_new(self.address).await?;
|
||||
|
||||
Ok(Self::NewDstType {
|
||||
customer_id: Some(self.customer_id),
|
||||
payment_id: None,
|
||||
..address_new
|
||||
})
|
||||
}
|
||||
}
|
||||
#[async_trait]
|
||||
impl behaviour::Conversion for PaymentAddress {
|
||||
type DstType = diesel_models::address::Address;
|
||||
type NewDstType = diesel_models::address::AddressNew;
|
||||
|
||||
async fn convert(self) -> CustomResult<Self::DstType, ValidationError> {
|
||||
let converted_address = Address::convert(self.address).await?;
|
||||
Ok(diesel_models::address::Address {
|
||||
customer_id: self.customer_id,
|
||||
payment_id: Some(self.payment_id),
|
||||
..converted_address
|
||||
})
|
||||
}
|
||||
|
||||
async fn convert_back(
|
||||
other: Self::DstType,
|
||||
key: &Secret<Vec<u8>>,
|
||||
) -> CustomResult<Self, ValidationError> {
|
||||
let payment_id = other
|
||||
.payment_id
|
||||
.clone()
|
||||
.ok_or(ValidationError::MissingRequiredField {
|
||||
field_name: "payment_id".to_string(),
|
||||
})?;
|
||||
|
||||
let customer_id = other.customer_id.clone();
|
||||
|
||||
let address = Address::convert_back(other, key).await?;
|
||||
|
||||
Ok(Self {
|
||||
address,
|
||||
payment_id,
|
||||
customer_id,
|
||||
})
|
||||
}
|
||||
|
||||
async fn construct_new(self) -> CustomResult<Self::NewDstType, ValidationError> {
|
||||
let address_new = Address::construct_new(self.address).await?;
|
||||
|
||||
Ok(Self::NewDstType {
|
||||
customer_id: self.customer_id,
|
||||
payment_id: Some(self.payment_id),
|
||||
..address_new
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl behaviour::Conversion for Address {
|
||||
type DstType = diesel_models::address::Address;
|
||||
@@ -64,11 +170,11 @@ impl behaviour::Conversion for Address {
|
||||
country_code: self.country_code,
|
||||
created_at: self.created_at,
|
||||
modified_at: self.modified_at,
|
||||
customer_id: self.customer_id,
|
||||
merchant_id: self.merchant_id,
|
||||
payment_id: self.payment_id,
|
||||
updated_by: self.updated_by,
|
||||
email: self.email.map(Encryption::from),
|
||||
payment_id: None,
|
||||
customer_id: None,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -95,10 +201,8 @@ impl behaviour::Conversion for Address {
|
||||
country_code: other.country_code,
|
||||
created_at: other.created_at,
|
||||
modified_at: other.modified_at,
|
||||
customer_id: other.customer_id,
|
||||
merchant_id: other.merchant_id,
|
||||
payment_id: other.payment_id,
|
||||
updated_by: other.updated_by,
|
||||
merchant_id: other.merchant_id,
|
||||
email: other.email.async_lift(inner_decrypt_email).await?,
|
||||
})
|
||||
}
|
||||
@@ -123,13 +227,13 @@ impl behaviour::Conversion for Address {
|
||||
last_name: self.last_name.map(Encryption::from),
|
||||
phone_number: self.phone_number.map(Encryption::from),
|
||||
country_code: self.country_code,
|
||||
customer_id: self.customer_id,
|
||||
merchant_id: self.merchant_id,
|
||||
payment_id: self.payment_id,
|
||||
created_at: now,
|
||||
modified_at: now,
|
||||
updated_by: self.updated_by,
|
||||
email: self.email.map(Encryption::from),
|
||||
customer_id: None,
|
||||
payment_id: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -577,7 +577,7 @@ pub trait CustomerAddress {
|
||||
customer_id: &str,
|
||||
key: &[u8],
|
||||
storage_scheme: storage::enums::MerchantStorageScheme,
|
||||
) -> CustomResult<domain::Address, common_utils::errors::CryptoError>;
|
||||
) -> CustomResult<domain::CustomerAddress, common_utils::errors::CryptoError>;
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
@@ -645,9 +645,9 @@ impl CustomerAddress for api_models::customers::CustomerRequest {
|
||||
customer_id: &str,
|
||||
key: &[u8],
|
||||
storage_scheme: storage::enums::MerchantStorageScheme,
|
||||
) -> CustomResult<domain::Address, common_utils::errors::CryptoError> {
|
||||
) -> CustomResult<domain::CustomerAddress, common_utils::errors::CryptoError> {
|
||||
async {
|
||||
Ok(domain::Address {
|
||||
let address = domain::Address {
|
||||
id: None,
|
||||
city: address_details.city,
|
||||
country: address_details.country,
|
||||
@@ -685,10 +685,8 @@ impl CustomerAddress for api_models::customers::CustomerRequest {
|
||||
.async_lift(|inner| encrypt_optional(inner, key))
|
||||
.await?,
|
||||
country_code: self.phone_country_code.clone(),
|
||||
customer_id: Some(customer_id.to_string()),
|
||||
merchant_id: merchant_id.to_string(),
|
||||
address_id: generate_id(consts::ID_LENGTH, "add"),
|
||||
payment_id: None,
|
||||
created_at: common_utils::date_time::now(),
|
||||
modified_at: common_utils::date_time::now(),
|
||||
updated_by: storage_scheme.to_string(),
|
||||
@@ -698,6 +696,11 @@ impl CustomerAddress for api_models::customers::CustomerRequest {
|
||||
.cloned()
|
||||
.async_lift(|inner| encrypt_optional(inner.map(|inner| inner.expose()), key))
|
||||
.await?,
|
||||
};
|
||||
|
||||
Ok(domain::CustomerAddress {
|
||||
address,
|
||||
customer_id: customer_id.to_string(),
|
||||
})
|
||||
}
|
||||
.await
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
-- This file should undo anything in `up.sql`
|
||||
ALTER TABLE payment_methods DROP COLUMN IF EXISTS payment_method_billing_address;
|
||||
@@ -0,0 +1,3 @@
|
||||
-- Your SQL goes here
|
||||
ALTER TABLE payment_methods
|
||||
ADD COLUMN IF NOT EXISTS payment_method_billing_address BYTEA;
|
||||
@@ -8162,6 +8162,14 @@
|
||||
"type": "boolean",
|
||||
"description": "Indicates if the payment method has been set to default or not",
|
||||
"example": true
|
||||
},
|
||||
"billing": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/Address"
|
||||
}
|
||||
],
|
||||
"nullable": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user