diff --git a/crates/router/src/connector/bankofamerica/transformers.rs b/crates/router/src/connector/bankofamerica/transformers.rs index 0b8158c10af..08ca4e0b7bf 100644 --- a/crates/router/src/connector/bankofamerica/transformers.rs +++ b/crates/router/src/connector/bankofamerica/transformers.rs @@ -1446,9 +1446,9 @@ impl resource_id: types::ResponseId::NoResponseId, redirection_data, mandate_reference: None, - connector_metadata: Some( - serde_json::json!({"three_ds_data":three_ds_data}), - ), + connector_metadata: Some(serde_json::json!({ + "three_ds_data": three_ds_data + })), network_txn_id: None, connector_response_reference_id, incremental_authorization_allowed: None, diff --git a/crates/router/src/connector/cryptopay/transformers.rs b/crates/router/src/connector/cryptopay/transformers.rs index fb806fda68f..d4697e3ba14 100644 --- a/crates/router/src/connector/cryptopay/transformers.rs +++ b/crates/router/src/connector/cryptopay/transformers.rs @@ -4,7 +4,8 @@ use reqwest::Url; use serde::{Deserialize, Serialize}; use crate::{ - connector::utils::{self, CryptoData}, + connector::utils::{self, is_payment_failure, CryptoData}, + consts, core::errors, services, types::{self, api, storage::enums}, @@ -155,14 +156,30 @@ impl types::PaymentsResponseData, >, ) -> Result { - let redirection_data = item - .response - .data - .hosted_page_url - .map(|x| services::RedirectForm::from((x, services::Method::Get))); - Ok(Self { - status: enums::AttemptStatus::from(item.response.data.status), - response: Ok(types::PaymentsResponseData::TransactionResponse { + let status = enums::AttemptStatus::from(item.response.data.status.clone()); + let response = if is_payment_failure(status) { + let payment_response = &item.response.data; + Err(types::ErrorResponse { + code: payment_response + .name + .clone() + .unwrap_or(consts::NO_ERROR_CODE.to_string()), + message: payment_response + .status_context + .clone() + .unwrap_or(consts::NO_ERROR_MESSAGE.to_string()), + reason: payment_response.status_context.clone(), + status_code: item.http_code, + attempt_status: None, + connector_transaction_id: Some(payment_response.id.clone()), + }) + } else { + let redirection_data = item + .response + .data + .hosted_page_url + .map(|x| services::RedirectForm::from((x, services::Method::Get))); + Ok(types::PaymentsResponseData::TransactionResponse { resource_id: types::ResponseId::ConnectorTransactionId( item.response.data.id.clone(), ), @@ -176,7 +193,11 @@ impl .custom_id .or(Some(item.response.data.id)), incremental_authorization_allowed: None, - }), + }) + }; + Ok(Self { + status, + response, ..item.data }) } diff --git a/crates/router/src/connector/noon/transformers.rs b/crates/router/src/connector/noon/transformers.rs index 5818c10eea6..793578cb4e1 100644 --- a/crates/router/src/connector/noon/transformers.rs +++ b/crates/router/src/connector/noon/transformers.rs @@ -5,8 +5,8 @@ use serde::{Deserialize, Serialize}; use crate::{ connector::utils::{ - self as conn_utils, CardData, PaymentsAuthorizeRequestData, RevokeMandateRequestData, - RouterData, WalletData, + self as conn_utils, is_refund_failure, CardData, PaymentsAuthorizeRequestData, + RevokeMandateRequestData, RouterData, WalletData, }, core::{errors, mandate::MandateBehaviour}, services, @@ -555,6 +555,8 @@ impl fn try_from( item: types::ResponseRouterData, ) -> Result { + let order = item.response.result.order; + let status = enums::AttemptStatus::foreign_from((order.status, item.data.status)); let redirection_data = item.response.result.checkout_data.map(|redirection_data| { services::RedirectForm::Form { endpoint: redirection_data.post_url.to_string(), @@ -570,17 +572,16 @@ impl connector_mandate_id: Some(subscription_data.identifier), payment_method_id: None, }); - let order = item.response.result.order; Ok(Self { - status: enums::AttemptStatus::foreign_from((order.status, item.data.status)), + status, response: match order.error_message { Some(error_message) => Err(ErrorResponse { code: order.error_code.to_string(), message: error_message.clone(), reason: Some(error_message), status_code: item.http_code, - attempt_status: None, - connector_transaction_id: None, + attempt_status: Some(status), + connector_transaction_id: Some(order.id.to_string()), }), _ => { let connector_response_reference_id = @@ -784,13 +785,18 @@ pub struct NoonPaymentsTransactionResponse { } #[derive(Default, Debug, Deserialize)] +#[serde(rename_all = "camelCase")] pub struct NoonRefundResponseResult { transaction: NoonPaymentsTransactionResponse, } #[derive(Default, Debug, Deserialize)] +#[serde(rename_all = "camelCase")] pub struct RefundResponse { result: NoonRefundResponseResult, + result_code: u32, + class_description: String, + message: String, } impl TryFrom> @@ -800,11 +806,26 @@ impl TryFrom> fn try_from( item: types::RefundsResponseRouterData, ) -> Result { - Ok(Self { - response: Ok(types::RefundsResponseData { + let response = &item.response; + let refund_status = + enums::RefundStatus::from(response.result.transaction.status.to_owned()); + let response = if is_refund_failure(refund_status) { + Err(ErrorResponse { + status_code: item.http_code, + code: response.result_code.to_string(), + message: response.class_description.clone(), + reason: Some(response.message.clone()), + attempt_status: None, + connector_transaction_id: Some(response.result.transaction.id.clone()), + }) + } else { + Ok(types::RefundsResponseData { connector_refund_id: item.response.result.transaction.id, - refund_status: enums::RefundStatus::from(item.response.result.transaction.status), - }), + refund_status, + }) + }; + Ok(Self { + response, ..item.data }) } @@ -819,13 +840,18 @@ pub struct NoonRefundResponseTransactions { } #[derive(Default, Debug, Deserialize)] +#[serde(rename_all = "camelCase")] pub struct NoonRefundSyncResponseResult { transactions: Vec, } #[derive(Default, Debug, Deserialize)] +#[serde(rename_all = "camelCase")] pub struct RefundSyncResponse { result: NoonRefundSyncResponseResult, + result_code: u32, + class_description: String, + message: String, } impl TryFrom> @@ -849,12 +875,25 @@ impl TryFrom> }) }) .ok_or(errors::ConnectorError::ResponseHandlingFailed)?; - - Ok(Self { - response: Ok(types::RefundsResponseData { + let refund_status = enums::RefundStatus::from(noon_transaction.status.to_owned()); + let response = if is_refund_failure(refund_status) { + let response = &item.response; + Err(ErrorResponse { + status_code: item.http_code, + code: response.result_code.to_string(), + message: response.class_description.clone(), + reason: Some(response.message.clone()), + attempt_status: None, + connector_transaction_id: Some(noon_transaction.id.clone()), + }) + } else { + Ok(types::RefundsResponseData { connector_refund_id: noon_transaction.id.to_owned(), - refund_status: enums::RefundStatus::from(noon_transaction.status.to_owned()), - }), + refund_status, + }) + }; + Ok(Self { + response, ..item.data }) } diff --git a/crates/router/src/connector/payme/transformers.rs b/crates/router/src/connector/payme/transformers.rs index a7b21ce292d..f4e34c084d9 100644 --- a/crates/router/src/connector/payme/transformers.rs +++ b/crates/router/src/connector/payme/transformers.rs @@ -12,9 +12,9 @@ use url::Url; use crate::{ connector::utils::{ - self, missing_field_err, AddressDetailsData, CardData, PaymentsAuthorizeRequestData, - PaymentsCompleteAuthorizeRequestData, PaymentsPreProcessingData, PaymentsSyncRequestData, - RouterData, + self, is_payment_failure, is_refund_failure, missing_field_err, AddressDetailsData, + CardData, PaymentsAuthorizeRequestData, PaymentsCompleteAuthorizeRequestData, + PaymentsPreProcessingData, PaymentsSyncRequestData, RouterData, }, consts, core::errors, @@ -198,14 +198,15 @@ impl fn try_from( item: types::ResponseRouterData, ) -> Result { - let response = if item.response.sale_status == SaleStatus::Failed { + let status = enums::AttemptStatus::from(item.response.sale_status.clone()); + let response = if is_payment_failure(status) { // To populate error message in case of failure Err(types::ErrorResponse::from((&item.response, item.http_code))) } else { Ok(types::PaymentsResponseData::try_from(&item.response)?) }; Ok(Self { - status: enums::AttemptStatus::from(item.response.sale_status), + status, response, ..item.data }) @@ -227,7 +228,7 @@ impl From<(&PaymePaySaleResponse, u16)> for types::ErrorResponse { reason: pay_sale_response.status_error_details.to_owned(), status_code: http_code, attempt_status: None, - connector_transaction_id: None, + connector_transaction_id: Some(pay_sale_response.payme_sale_id.clone()), } } } @@ -281,7 +282,8 @@ impl TryFrom TryFrom for types::ErrorResponse { reason: sale_query_response.sale_error_text.clone(), status_code: http_code, attempt_status: None, - connector_transaction_id: None, + connector_transaction_id: Some(sale_query_response.sale_payme_id.clone()), } } } @@ -982,6 +984,7 @@ impl TryFrom for enums::RefundStatus { pub struct PaymeRefundResponse { sale_status: SaleStatus, payme_transaction_id: String, + status_error_code: i64, } impl TryFrom> @@ -991,11 +994,25 @@ impl TryFrom fn try_from( item: types::RefundsResponseRouterData, ) -> Result { - Ok(Self { - response: Ok(types::RefundsResponseData { + let refund_status = enums::RefundStatus::try_from(item.response.sale_status.clone())?; + let response = if is_refund_failure(refund_status) { + let payme_response = &item.response; + Err(types::ErrorResponse { + code: payme_response.status_error_code.to_string(), + message: payme_response.status_error_code.to_string(), + reason: Some(payme_response.status_error_code.to_string()), + status_code: item.http_code, + attempt_status: None, + connector_transaction_id: Some(payme_response.payme_transaction_id.clone()), + }) + } else { + Ok(types::RefundsResponseData { connector_refund_id: item.response.payme_transaction_id, - refund_status: enums::RefundStatus::try_from(item.response.sale_status)?, - }), + refund_status, + }) + }; + Ok(Self { + response, ..item.data }) } @@ -1031,13 +1048,24 @@ impl .items .first() .ok_or(errors::ConnectorError::ResponseHandlingFailed)?; - Ok(Self { - response: Ok(types::RefundsResponseData { - refund_status: enums::RefundStatus::try_from( - pay_sale_response.sale_status.clone(), - )?, + let refund_status = enums::RefundStatus::try_from(pay_sale_response.sale_status.clone())?; + let response = if is_refund_failure(refund_status) { + Err(types::ErrorResponse { + code: consts::NO_ERROR_CODE.to_string(), + message: consts::NO_ERROR_CODE.to_string(), + reason: None, + status_code: item.http_code, + attempt_status: None, + connector_transaction_id: Some(pay_sale_response.payme_transaction_id.clone()), + }) + } else { + Ok(types::RefundsResponseData { + refund_status, connector_refund_id: pay_sale_response.payme_transaction_id.clone(), - }), + }) + }; + Ok(Self { + response, ..item.data }) } diff --git a/crates/router/src/connector/utils.rs b/crates/router/src/connector/utils.rs index 87d50bb68a2..7951246790f 100644 --- a/crates/router/src/connector/utils.rs +++ b/crates/router/src/connector/utils.rs @@ -1786,6 +1786,7 @@ pub fn is_refund_failure(status: enums::RefundStatus) -> bool { | common_enums::RefundStatus::Success => false, } } + #[cfg(test)] mod error_code_error_message_tests { #![allow(clippy::unwrap_used)]