From a2a6bab56cc70463d25232ce40ca4f115bee24e0 Mon Sep 17 00:00:00 2001 From: Prajjwal Kumar Date: Tue, 9 May 2023 19:50:05 +0530 Subject: [PATCH] feat: Allow payment cancels for more statuses (#1027) Co-authored-by: Sanchith Hegde <22217505+SanchithHegde@users.noreply.github.com> --- .../payments/operations/payment_cancel.rs | 118 +++++++++++------- crates/router/src/routes/payments.rs | 1 - 2 files changed, 70 insertions(+), 49 deletions(-) diff --git a/crates/router/src/core/payments/operations/payment_cancel.rs b/crates/router/src/core/payments/operations/payment_cancel.rs index f589b61745..9c613cf782 100644 --- a/crates/router/src/core/payments/operations/payment_cancel.rs +++ b/crates/router/src/core/payments/operations/payment_cancel.rs @@ -53,6 +53,18 @@ impl GetTracker, api::PaymentsCancelRequest> .await .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?; + helpers::validate_payment_status_against_not_allowed_statuses( + &payment_intent.status, + &[ + enums::IntentStatus::Failed, + enums::IntentStatus::Succeeded, + enums::IntentStatus::Cancelled, + enums::IntentStatus::Processing, + enums::IntentStatus::RequiresMerchantAction, + ], + "cancelled", + )?; + let mut payment_attempt = db .find_payment_attempt_by_payment_id_merchant_id_attempt_id( payment_intent.payment_id.as_str(), @@ -112,44 +124,35 @@ impl GetTracker, api::PaymentsCancelRequest> .await .transpose()?; - match payment_intent.status { - status if status != enums::IntentStatus::RequiresCapture => { - Err(errors::ApiErrorResponse::InvalidRequestData { - message: "You cannot cancel the payment that has not been authorized" - .to_string(), - } - .into()) - } - _ => Ok(( - Box::new(self), - PaymentData { - flow: PhantomData, - payment_intent, - payment_attempt, - currency, - amount, - email: None, - mandate_id: None, - setup_mandate: None, - token: None, - address: PaymentAddress { - shipping: shipping_address.as_ref().map(|a| a.foreign_into()), - billing: billing_address.as_ref().map(|a| a.foreign_into()), - }, - confirm: None, - payment_method_data: None, - force_sync: None, - refunds: vec![], - connector_response, - sessions_token: vec![], - card_cvc: None, - creds_identifier, - pm_token: None, - connector_customer_id: None, + Ok(( + Box::new(self), + PaymentData { + flow: PhantomData, + payment_intent, + payment_attempt, + currency, + amount, + email: None, + mandate_id: None, + setup_mandate: None, + token: None, + address: PaymentAddress { + shipping: shipping_address.as_ref().map(|a| a.foreign_into()), + billing: billing_address.as_ref().map(|a| a.foreign_into()), }, - None, - )), - } + confirm: None, + payment_method_data: None, + force_sync: None, + refunds: vec![], + connector_response, + sessions_token: vec![], + card_cvc: None, + creds_identifier, + pm_token: None, + connector_customer_id: None, + }, + None, + )) } } @@ -172,18 +175,37 @@ impl UpdateTracker, api::PaymentsCancelRequest> for F: 'b + Send, { let cancellation_reason = payment_data.payment_attempt.cancellation_reason.clone(); - payment_data.payment_attempt = db - .update_payment_attempt_with_attempt_id( - payment_data.payment_attempt, - storage::PaymentAttemptUpdate::VoidUpdate { - status: enums::AttemptStatus::VoidInitiated, - cancellation_reason, - }, - storage_scheme, - ) - .await - .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?; + let (intent_status_update, attempt_status_update) = + if payment_data.payment_intent.status != enums::IntentStatus::RequiresCapture { + let payment_intent_update = storage::PaymentIntentUpdate::PGStatusUpdate { + status: enums::IntentStatus::Cancelled, + }; + (Some(payment_intent_update), enums::AttemptStatus::Voided) + } else { + (None, enums::AttemptStatus::VoidInitiated) + }; + if let Some(payment_intent_update) = intent_status_update { + payment_data.payment_intent = db + .update_payment_intent( + payment_data.payment_intent, + payment_intent_update, + storage_scheme, + ) + .await + .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?; + } + + db.update_payment_attempt_with_attempt_id( + payment_data.payment_attempt.clone(), + storage::PaymentAttemptUpdate::VoidUpdate { + status: attempt_status_update, + cancellation_reason, + }, + storage_scheme, + ) + .await + .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?; Ok((Box::new(self), payment_data)) } } diff --git a/crates/router/src/routes/payments.rs b/crates/router/src/routes/payments.rs index 4d985c095a..92030dcaea 100644 --- a/crates/router/src/routes/payments.rs +++ b/crates/router/src/routes/payments.rs @@ -623,7 +623,6 @@ pub async fn payments_cancel( let mut payload = json_payload.into_inner(); let payment_id = path.into_inner(); payload.payment_id = payment_id; - api::server_wrap( flow, state.get_ref(),