From 47741b47fae9a671a3178c5cb7699f9bb656025c Mon Sep 17 00:00:00 2001 From: ItsMeShashank Date: Wed, 21 Dec 2022 14:36:37 +0530 Subject: [PATCH] feat(router): use payment confirm for confirmed payments in payments create and update (#165) Co-authored-by: Arun Raj M --- crates/router/src/core/payments.rs | 23 +++++++++++-------- .../payments/operations/payment_confirm.rs | 12 ++++++++-- .../payments/operations/payment_create.rs | 14 ++++++++--- .../payments/operations/payment_update.rs | 22 ++++++++++++++---- crates/storage_models/src/payment_attempt.rs | 9 ++++++++ 5 files changed, 62 insertions(+), 18 deletions(-) diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs index ffc1bc4012..2e19674e86 100644 --- a/crates/router/src/core/payments.rs +++ b/crates/router/src/core/payments.rs @@ -482,6 +482,7 @@ pub struct CustomerDetails { pub fn if_not_create_change_operation<'a, Op, F>( is_update: bool, status: storage_enums::IntentStatus, + confirm: Option, current: &'a Op, ) -> BoxedOperation where @@ -489,17 +490,21 @@ where Op: Operation + Send + Sync, &'a Op: Operation, { - match status { - storage_enums::IntentStatus::RequiresConfirmation - | storage_enums::IntentStatus::RequiresCustomerAction - | storage_enums::IntentStatus::RequiresPaymentMethod => { - if is_update { - Box::new(&PaymentUpdate) - } else { - Box::new(current) + if confirm.unwrap_or(false) { + Box::new(PaymentConfirm) + } else { + match status { + storage_enums::IntentStatus::RequiresConfirmation + | storage_enums::IntentStatus::RequiresCustomerAction + | storage_enums::IntentStatus::RequiresPaymentMethod => { + if is_update { + Box::new(&PaymentUpdate) + } else { + Box::new(current) + } } + _ => Box::new(&PaymentStatus), } - _ => Box::new(&PaymentStatus), } } diff --git a/crates/router/src/core/payments/operations/payment_confirm.rs b/crates/router/src/core/payments/operations/payment_confirm.rs index c77c1b1dd4..cccd491965 100644 --- a/crates/router/src/core/payments/operations/payment_confirm.rs +++ b/crates/router/src/core/payments/operations/payment_confirm.rs @@ -257,7 +257,7 @@ impl UpdateTracker, api::PaymentsRequest> for Paymen db: &dyn StorageInterface, _payment_id: &api::PaymentIdType, mut payment_data: PaymentData, - _customer: Option, + customer: Option, storage_scheme: enums::MerchantStorageScheme, ) -> RouterResult<(BoxedOperation<'b, F, api::PaymentsRequest>, PaymentData)> where @@ -285,8 +285,11 @@ impl UpdateTracker, api::PaymentsRequest> for Paymen .update_payment_attempt( payment_data.payment_attempt, storage::PaymentAttemptUpdate::ConfirmUpdate { + amount: payment_data.amount.into(), + currency: payment_data.currency, status: attempt_status, payment_method, + authentication_type: None, browser_info, connector, payment_token, @@ -303,11 +306,16 @@ impl UpdateTracker, api::PaymentsRequest> for Paymen payment_data.payment_intent.billing_address_id.clone(), ); + let customer_id = customer.map(|c| c.customer_id); + payment_data.payment_intent = db .update_payment_intent( payment_data.payment_intent, - storage::PaymentIntentUpdate::MerchantStatusUpdate { + storage::PaymentIntentUpdate::Update { + amount: payment_data.amount.into(), + currency: payment_data.currency, status: intent_status, + customer_id, shipping_address_id: shipping_address, billing_address_id: billing_address, }, diff --git a/crates/router/src/core/payments/operations/payment_create.rs b/crates/router/src/core/payments/operations/payment_create.rs index 926e12eb43..99f57c7478 100644 --- a/crates/router/src/core/payments/operations/payment_create.rs +++ b/crates/router/src/core/payments/operations/payment_create.rs @@ -185,6 +185,7 @@ impl GetTracker, api::PaymentsRequest> for Pa let operation = payments::if_not_create_change_operation::<_, F>( is_update, payment_intent.status, + request.confirm, self, ); @@ -280,10 +281,10 @@ impl Domain for PaymentCreate { #[instrument(skip_all)] async fn add_task_to_process_tracker<'a>( &'a self, - state: &'a AppState, - payment_attempt: &storage::PaymentAttempt, + _state: &'a AppState, + _payment_attempt: &storage::PaymentAttempt, ) -> CustomResult<(), errors::ApiErrorResponse> { - helpers::add_domain_task_to_pt(self, state, payment_attempt).await + Ok(()) } async fn get_connector<'a>( @@ -388,6 +389,13 @@ impl ValidateRequest for PaymentCreate None => None, }; + if let Some(true) = request.confirm { + helpers::validate_pm_or_token_given( + &request.payment_token, + &request.payment_method_data, + )?; + } + let request_merchant_id = request.merchant_id.as_deref(); helpers::validate_merchant_id(&merchant_account.merchant_id, request_merchant_id) .change_context(errors::ApiErrorResponse::MerchantAccountNotFound)?; diff --git a/crates/router/src/core/payments/operations/payment_update.rs b/crates/router/src/core/payments/operations/payment_update.rs index e828b275e7..1f826c6574 100644 --- a/crates/router/src/core/payments/operations/payment_update.rs +++ b/crates/router/src/core/payments/operations/payment_update.rs @@ -126,6 +126,13 @@ impl GetTracker, api::PaymentsRequest> for Pa .attach_printable("Database error when finding connector response") })?; + let next_operation: BoxedOperation<'a, F, api::PaymentsRequest> = + if request.confirm.unwrap_or(false) { + Box::new(operations::PaymentConfirm) + } else { + Box::new(self) + }; + match payment_intent.status { enums::IntentStatus::Succeeded | enums::IntentStatus::Failed => { Err(report!(errors::ApiErrorResponse::PreconditionFailed { @@ -135,7 +142,7 @@ impl GetTracker, api::PaymentsRequest> for Pa })) } _ => Ok(( - Box::new(self), + next_operation, PaymentData { flow: PhantomData, payment_intent, @@ -227,10 +234,10 @@ impl Domain for PaymentUpdate { #[instrument(skip_all)] async fn add_task_to_process_tracker<'a>( &'a self, - state: &'a AppState, - payment_attempt: &storage::PaymentAttempt, + _state: &'a AppState, + _payment_attempt: &storage::PaymentAttempt, ) -> CustomResult<(), errors::ApiErrorResponse> { - helpers::add_domain_task_to_pt(self, state, payment_attempt).await + Ok(()) } async fn get_connector<'a>( @@ -352,6 +359,13 @@ impl ValidateRequest for PaymentUpdate None => None, }; + if let Some(true) = request.confirm { + helpers::validate_pm_or_token_given( + &request.payment_token, + &request.payment_method_data, + )?; + } + let request_merchant_id = request.merchant_id.as_deref(); helpers::validate_merchant_id(&merchant_account.merchant_id, request_merchant_id) .change_context(errors::ApiErrorResponse::InvalidDataFormat { diff --git a/crates/storage_models/src/payment_attempt.rs b/crates/storage_models/src/payment_attempt.rs index e36f06c1a5..597eef050a 100644 --- a/crates/storage_models/src/payment_attempt.rs +++ b/crates/storage_models/src/payment_attempt.rs @@ -95,7 +95,10 @@ pub enum PaymentAttemptUpdate { authentication_type: storage_enums::AuthenticationType, }, ConfirmUpdate { + amount: i64, + currency: storage_enums::Currency, status: storage_enums::AttemptStatus, + authentication_type: Option, payment_method: Option, browser_info: Option, connector: Option, @@ -199,12 +202,18 @@ impl From for PaymentAttemptUpdateInternal { ..Default::default() }, PaymentAttemptUpdate::ConfirmUpdate { + amount, + currency, + authentication_type, status, payment_method, browser_info, connector, payment_token, } => Self { + amount: Some(amount), + currency: Some(currency), + authentication_type, status: Some(status), payment_method, modified_at: Some(common_utils::date_time::now()),