fix(router): update last used when the customer acceptance is passed in the recurring payment (#5116)

This commit is contained in:
Shankar Singh C
2024-07-02 17:29:06 +05:30
committed by GitHub
parent e3470a240d
commit b2e0caf6d9
4 changed files with 85 additions and 32 deletions

View File

@ -96,8 +96,13 @@ pub struct TokenizeCoreWorkflow {
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub enum PaymentMethodUpdate { pub enum PaymentMethodUpdate {
MetadataUpdate { MetadataUpdateAndLastUsed {
metadata: Option<serde_json::Value>, metadata: Option<serde_json::Value>,
last_used_at: PrimitiveDateTime,
},
UpdatePaymentMethodDataAndLastUsed {
payment_method_data: Option<Encryption>,
last_used_at: PrimitiveDateTime,
}, },
PaymentMethodDataUpdate { PaymentMethodDataUpdate {
payment_method_data: Option<Encryption>, payment_method_data: Option<Encryption>,
@ -191,10 +196,13 @@ impl PaymentMethodUpdateInternal {
impl From<PaymentMethodUpdate> for PaymentMethodUpdateInternal { impl From<PaymentMethodUpdate> for PaymentMethodUpdateInternal {
fn from(payment_method_update: PaymentMethodUpdate) -> Self { fn from(payment_method_update: PaymentMethodUpdate) -> Self {
match payment_method_update { match payment_method_update {
PaymentMethodUpdate::MetadataUpdate { metadata } => Self { PaymentMethodUpdate::MetadataUpdateAndLastUsed {
metadata,
last_used_at,
} => Self {
metadata, metadata,
payment_method_data: None, payment_method_data: None,
last_used_at: None, last_used_at: Some(last_used_at),
network_transaction_id: None, network_transaction_id: None,
status: None, status: None,
locker_id: None, locker_id: None,
@ -232,6 +240,22 @@ impl From<PaymentMethodUpdate> for PaymentMethodUpdateInternal {
payment_method_issuer: None, payment_method_issuer: None,
payment_method_type: None, payment_method_type: None,
}, },
PaymentMethodUpdate::UpdatePaymentMethodDataAndLastUsed {
payment_method_data,
last_used_at,
} => Self {
metadata: None,
payment_method_data,
last_used_at: Some(last_used_at),
network_transaction_id: None,
status: None,
locker_id: None,
payment_method: None,
connector_mandate_details: None,
updated_by: None,
payment_method_issuer: None,
payment_method_type: None,
},
PaymentMethodUpdate::NetworkTransactionIdAndStatusUpdate { PaymentMethodUpdate::NetworkTransactionIdAndStatusUpdate {
network_transaction_id, network_transaction_id,
status, status,

View File

@ -1407,14 +1407,31 @@ pub async fn call_to_locker_hs<'a>(
Ok(stored_card) Ok(stored_card)
} }
pub async fn update_payment_method( pub async fn update_payment_method_metadata_and_last_used(
db: &dyn db::StorageInterface, db: &dyn db::StorageInterface,
pm: payment_method::PaymentMethod, pm: payment_method::PaymentMethod,
pm_metadata: serde_json::Value, pm_metadata: Option<serde_json::Value>,
storage_scheme: MerchantStorageScheme, storage_scheme: MerchantStorageScheme,
) -> errors::CustomResult<(), errors::VaultError> { ) -> errors::CustomResult<(), errors::VaultError> {
let pm_update = payment_method::PaymentMethodUpdate::MetadataUpdate { let pm_update = payment_method::PaymentMethodUpdate::MetadataUpdateAndLastUsed {
metadata: Some(pm_metadata), metadata: pm_metadata,
last_used_at: common_utils::date_time::now(),
};
db.update_payment_method(pm, pm_update, storage_scheme)
.await
.change_context(errors::VaultError::UpdateInPaymentMethodDataTableFailed)?;
Ok(())
}
pub async fn update_payment_method_and_last_used(
db: &dyn db::StorageInterface,
pm: payment_method::PaymentMethod,
payment_method_update: Option<Encryption>,
storage_scheme: MerchantStorageScheme,
) -> errors::CustomResult<(), errors::VaultError> {
let pm_update = payment_method::PaymentMethodUpdate::UpdatePaymentMethodDataAndLastUsed {
payment_method_data: payment_method_update,
last_used_at: common_utils::date_time::now(),
}; };
db.update_payment_method(pm, pm_update, storage_scheme) db.update_payment_method(pm, pm_update, storage_scheme)
.await .await

View File

@ -114,9 +114,14 @@ impl<F: Send + Clone> PostUpdateTracker<F, PaymentData<F>, types::PaymentsAuthor
.get_payment_method_billing() .get_payment_method_billing()
.and_then(|billing_details| billing_details.address.as_ref()) .and_then(|billing_details| billing_details.address.as_ref())
.and_then(|address| address.get_optional_full_name()); .and_then(|address| address.get_optional_full_name());
let mut should_avoid_saving = false;
if let Some(payment_method_info) = &payment_data.payment_method_info { if let Some(payment_method_info) = &payment_data.payment_method_info {
if payment_data.payment_intent.off_session.is_none() && resp.response.is_ok() { if payment_data.payment_intent.off_session.is_none() && resp.response.is_ok() {
should_avoid_saving = resp.request.payment_method_type
== Some(enums::PaymentMethodType::ApplePay)
|| resp.request.payment_method_type
== Some(enums::PaymentMethodType::GooglePay);
payment_methods::cards::update_last_used_at( payment_methods::cards::update_last_used_at(
payment_method_info, payment_method_info,
state, state,
@ -179,6 +184,12 @@ impl<F: Send + Clone> PostUpdateTracker<F, PaymentData<F>, types::PaymentsAuthor
let (payment_method_id, _payment_method_status) = save_payment_call_future.await?; let (payment_method_id, _payment_method_status) = save_payment_call_future.await?;
payment_data.payment_attempt.payment_method_id = payment_method_id; payment_data.payment_attempt.payment_method_id = payment_method_id;
Ok(()) Ok(())
} else if should_avoid_saving {
if let Some(pm_info) = &payment_data.payment_method_info {
payment_data.payment_attempt.payment_method_id =
Some(pm_info.payment_method_id.clone());
};
Ok(())
} else { } else {
// Save card flow // Save card flow
let save_payment_data = tokenization::SavePaymentMethodData::from(resp); let save_payment_data = tokenization::SavePaymentMethodData::from(resp);

View File

@ -272,20 +272,15 @@ where
pm.metadata.as_ref(), pm.metadata.as_ref(),
connector_token, connector_token,
)?; )?;
if let Some(metadata) = pm_metadata { payment_methods::cards::update_payment_method_metadata_and_last_used(
payment_methods::cards::update_payment_method(
db, db,
pm.clone(), pm.clone(),
metadata, pm_metadata,
merchant_account.storage_scheme, merchant_account.storage_scheme,
) )
.await .await
.change_context( .change_context(errors::ApiErrorResponse::InternalServerError)
errors::ApiErrorResponse::InternalServerError,
)
.attach_printable("Failed to add payment method in db")?; .attach_printable("Failed to add payment method in db")?;
};
// update if its a off-session mit payment
if check_for_mit_mandates { if check_for_mit_mandates {
let connector_mandate_details = let connector_mandate_details =
update_connector_mandate_details_in_payment_method( update_connector_mandate_details_in_payment_method(
@ -515,14 +510,10 @@ where
.await .await
.map(|details| details.into()); .map(|details| details.into());
let pm_update = payment_methods::cards::update_payment_method_and_last_used(
storage::PaymentMethodUpdate::PaymentMethodDataUpdate { db,
payment_method_data: pm_data_encrypted,
};
db.update_payment_method(
existing_pm, existing_pm,
pm_update, pm_data_encrypted,
merchant_account.storage_scheme, merchant_account.storage_scheme,
) )
.await .await
@ -532,7 +523,7 @@ where
} }
}, },
None => { None => {
let customer_saved_pm_id_option = if payment_method_type let customer_saved_pm_option = if payment_method_type
== Some(api_models::enums::PaymentMethodType::ApplePay) == Some(api_models::enums::PaymentMethodType::ApplePay)
|| payment_method_type || payment_method_type
== Some(api_models::enums::PaymentMethodType::GooglePay) == Some(api_models::enums::PaymentMethodType::GooglePay)
@ -551,7 +542,7 @@ where
.find(|payment_method| { .find(|payment_method| {
payment_method.payment_method_type == payment_method_type payment_method.payment_method_type == payment_method_type
}) })
.map(|pm| pm.payment_method_id.clone())), .cloned()),
Err(error) => { Err(error) => {
if error.current_context().is_db_not_found() { if error.current_context().is_db_not_found() {
Ok(None) Ok(None)
@ -570,8 +561,18 @@ where
Ok(None) Ok(None)
}?; }?;
if let Some(customer_saved_pm_id) = customer_saved_pm_id_option { if let Some(customer_saved_pm) = customer_saved_pm_option {
resp.payment_method_id = customer_saved_pm_id; payment_methods::cards::update_last_used_at(
&customer_saved_pm,
state,
merchant_account.storage_scheme,
)
.await
.map_err(|e| {
logger::error!("Failed to update last used at: {:?}", e);
})
.ok();
resp.payment_method_id = customer_saved_pm.payment_method_id;
} else { } else {
let pm_metadata = let pm_metadata =
create_payment_method_metadata(None, connector_token)?; create_payment_method_metadata(None, connector_token)?;