Skip to content

Commit

Permalink
add unified error code and error message for refund table
Browse files Browse the repository at this point in the history
  • Loading branch information
cookieg13 committed Dec 24, 2024
1 parent a423ff5 commit b28bd29
Show file tree
Hide file tree
Showing 15 changed files with 191 additions and 38 deletions.
4 changes: 4 additions & 0 deletions crates/api_models/src/refunds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,10 @@ pub struct RefundResponse {
pub error_message: Option<String>,
/// The code for the error
pub error_code: Option<String>,
/// error code unified across the connectors is received here if there was an error while calling connector
pub unified_code: Option<String>,
/// error message unified across the connectors is received here if there was an error while calling connector
pub unified_message: Option<String>,
/// The timestamp at which refund is created
#[serde(with = "common_utils::custom_serde::iso8601::option")]
pub created_at: Option<PrimitiveDateTime>,
Expand Down
3 changes: 3 additions & 0 deletions crates/common_utils/src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,3 +149,6 @@ pub const APPLEPAY_VALIDATION_URL: &str =

/// Request ID
pub const X_REQUEST_ID: &str = "x-request-id";

/// Refund flow identifier used for performing GSM operations
pub const REFUND_FLOW_STR: &str = "refund_flow";
26 changes: 26 additions & 0 deletions crates/diesel_models/src/refund.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ pub struct Refund {
pub connector_refund_data: Option<String>,
pub connector_transaction_data: Option<String>,
pub split_refunds: Option<common_types::refunds::SplitRefund>,
pub unified_code: Option<String>,
pub unified_message: Option<String>,
}

#[derive(
Expand Down Expand Up @@ -132,6 +134,8 @@ pub enum RefundUpdate {
updated_by: String,
connector_refund_id: Option<ConnectorTransactionId>,
connector_refund_data: Option<String>,
unified_code: Option<String>,
unified_message: Option<String>,
},
ManualUpdate {
refund_status: Option<storage_enums::RefundStatus>,
Expand All @@ -155,6 +159,8 @@ pub struct RefundUpdateInternal {
updated_by: String,
modified_at: PrimitiveDateTime,
connector_refund_data: Option<String>,
unified_code: Option<String>,
unified_message: Option<String>,
}

impl RefundUpdateInternal {
Expand All @@ -171,6 +177,8 @@ impl RefundUpdateInternal {
updated_by: self.updated_by,
modified_at: self.modified_at,
connector_refund_data: self.connector_refund_data,
unified_code: self.unified_code,
unified_message: self.unified_message,
..source
}
}
Expand Down Expand Up @@ -199,6 +207,8 @@ impl From<RefundUpdate> for RefundUpdateInternal {
refund_reason: None,
refund_error_code: None,
modified_at: common_utils::date_time::now(),
unified_code: None,
unified_message: None,
},
RefundUpdate::MetadataAndReasonUpdate {
metadata,
Expand All @@ -216,6 +226,8 @@ impl From<RefundUpdate> for RefundUpdateInternal {
refund_error_code: None,
modified_at: common_utils::date_time::now(),
connector_refund_data: None,
unified_code: None,
unified_message: None,
},
RefundUpdate::StatusUpdate {
connector_refund_id,
Expand All @@ -235,11 +247,15 @@ impl From<RefundUpdate> for RefundUpdateInternal {
refund_reason: None,
refund_error_code: None,
modified_at: common_utils::date_time::now(),
unified_code: None,
unified_message: None,
},
RefundUpdate::ErrorUpdate {
refund_status,
refund_error_message,
refund_error_code,
unified_code,
unified_message,
updated_by,
connector_refund_id,
connector_refund_data,
Expand All @@ -255,6 +271,8 @@ impl From<RefundUpdate> for RefundUpdateInternal {
metadata: None,
refund_reason: None,
modified_at: common_utils::date_time::now(),
unified_code,
unified_message,
},
RefundUpdate::ManualUpdate {
refund_status,
Expand All @@ -273,6 +291,8 @@ impl From<RefundUpdate> for RefundUpdateInternal {
refund_reason: None,
modified_at: common_utils::date_time::now(),
connector_refund_data: None,
unified_code: None,
unified_message: None,
},
}
}
Expand All @@ -292,6 +312,8 @@ impl RefundUpdate {
updated_by,
modified_at: _,
connector_refund_data,
unified_code,
unified_message,
} = self.into();
Refund {
connector_refund_id: connector_refund_id.or(source.connector_refund_id),
Expand All @@ -305,6 +327,8 @@ impl RefundUpdate {
updated_by,
modified_at: common_utils::date_time::now(),
connector_refund_data: connector_refund_data.or(source.connector_refund_data),
unified_code: unified_code.or(source.unified_code),
unified_message: unified_message.or(source.unified_message),
..source
}
}
Expand Down Expand Up @@ -392,6 +416,8 @@ mod tests {
"merchant_connector_id": null,
"charges": null,
"connector_transaction_data": null
"unified_code": null,
"unified_message": null,
}"#;
let deserialized = serde_json::from_str::<super::Refund>(serialized_refund);

Expand Down
4 changes: 4 additions & 0 deletions crates/diesel_models/src/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1235,6 +1235,10 @@ diesel::table! {
#[max_length = 512]
connector_transaction_data -> Nullable<Varchar>,
split_refunds -> Nullable<Jsonb>,
#[max_length = 255]
unified_code -> Nullable<Varchar>,
#[max_length = 255]
unified_message -> Nullable<Varchar>,
}
}

Expand Down
2 changes: 2 additions & 0 deletions crates/diesel_models/src/schema_v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1181,6 +1181,8 @@ diesel::table! {
#[max_length = 512]
connector_transaction_data -> Nullable<Varchar>,
split_refunds -> Nullable<Jsonb>,
unified_code -> Nullable<Varchar>,
unified_message -> Nullable<Varchar>,
}
}

Expand Down
16 changes: 15 additions & 1 deletion crates/router/src/core/payments/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::{borrow::Cow, str::FromStr};

#[cfg(feature = "v2")]
use api_models::ephemeral_key::EphemeralKeyResponse;
use actix_web::http::header::HeaderMap;
use api_models::{
mandates::RecurringDetails,
payments::{additional_info as payment_additional_types, RequestSurchargeDetails},
Expand All @@ -11,6 +12,7 @@ use common_enums::ConnectorType;
#[cfg(feature = "v2")]
use common_utils::id_type::GenerateId;
use common_utils::{
consts as common_consts,
crypto::Encryptable,
ext_traits::{AsyncExt, ByteSliceExt, Encode, ValueExt},
fp_utils, generate_id, id_type,
Expand Down Expand Up @@ -71,8 +73,9 @@ use crate::{
pm_auth::retrieve_payment_method_from_auth_service,
},
db::StorageInterface,
headers::ACCEPT_LANGUAGE,
routes::{metrics, payment_methods as payment_methods_handler, SessionState},
services,
services::{self, authentication::get_header_value_by_key},
types::{
api::{self, admin, enums as api_enums, MandateValidationFieldsExt},
domain::{self, types},
Expand Down Expand Up @@ -6269,3 +6272,14 @@ pub fn validate_platform_fees_for_marketplace(
}
Ok(())
}

pub fn get_locale_from_header(headers: Option<&HeaderMap>) -> String {
headers
.and_then(|headers| {
get_header_value_by_key(ACCEPT_LANGUAGE.into(), headers)
.ok()
.flatten()
.map(|val| val.to_string())
})
.unwrap_or_else(|| common_consts::DEFAULT_LOCALE.to_string())
}
16 changes: 15 additions & 1 deletion crates/router/src/core/payouts/helpers.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use actix_web::http::header::HeaderMap;
use api_models::{enums, payment_methods::Card, payouts};
use common_utils::{
consts as common_consts,
crypto::Encryptable,
encryption::Encryption,
errors::CustomResult,
Expand Down Expand Up @@ -37,8 +39,9 @@ use crate::{
utils as core_utils,
},
db::StorageInterface,
headers::ACCEPT_LANGUAGE,
routes::{metrics, SessionState},
services,
services::{self, authentication::get_header_value_by_key},
types::{
api::{self, enums as api_enums},
domain::{self, types::AsyncLift},
Expand Down Expand Up @@ -1389,3 +1392,14 @@ pub async fn get_additional_payout_data(
}
}
}

pub fn get_locale_from_header(headers: Option<&HeaderMap>) -> String {
headers
.and_then(|headers| {
get_header_value_by_key(ACCEPT_LANGUAGE.into(), headers)
.ok()
.flatten()
.map(|val| val.to_string())
})
.unwrap_or_else(|| common_consts::DEFAULT_LOCALE.to_string())
}
73 changes: 62 additions & 11 deletions crates/router/src/core/refunds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use std::collections::HashMap;
#[cfg(feature = "olap")]
use api_models::admin::MerchantConnectorInfo;
use common_utils::{
consts as common_consts,
ext_traits::AsyncExt,
types::{ConnectorTransactionId, MinorUnit},
};
Expand All @@ -26,7 +27,7 @@ use crate::{
consts,
core::{
errors::{self, ConnectorErrorExt, RouterResponse, RouterResult, StorageErrorExt},
payments::{self, access_token},
payments::{self, access_token, helpers},
refunds::transformers::SplitRefundInput,
utils as core_utils,
},
Expand Down Expand Up @@ -116,7 +117,7 @@ pub async fn refund_create_core(
req.merchant_connector_details
.to_owned()
.async_map(|mcd| async {
payments::helpers::insert_merchant_connector_creds_to_config(db, merchant_id, mcd).await
helpers::insert_merchant_connector_creds_to_config(db, merchant_id, mcd).await
})
.await
.transpose()?;
Expand Down Expand Up @@ -237,6 +238,8 @@ pub async fn trigger_refund_to_gateway(
updated_by: storage_scheme.to_string(),
connector_refund_id: None,
connector_refund_data: None,
unified_code: None,
unified_message: None,
})
}
errors::ConnectorError::NotSupported { message, connector } => {
Expand All @@ -249,6 +252,8 @@ pub async fn trigger_refund_to_gateway(
updated_by: storage_scheme.to_string(),
connector_refund_id: None,
connector_refund_data: None,
unified_code: None,
unified_message: None,
})
}
_ => None,
Expand Down Expand Up @@ -284,14 +289,52 @@ pub async fn trigger_refund_to_gateway(
};

let refund_update = match router_data_res.response {
Err(err) => storage::RefundUpdate::ErrorUpdate {
refund_status: Some(enums::RefundStatus::Failure),
refund_error_message: err.reason.or(Some(err.message)),
refund_error_code: Some(err.code),
updated_by: storage_scheme.to_string(),
connector_refund_id: None,
connector_refund_data: None,
},
Err(err) => {
let option_gsm = helpers::get_gsm_record(
state,
Some(err.code.clone()),
Some(err.message.clone()),
connector.connector_name.to_string(),
common_consts::REFUND_FLOW_STR.to_string(),
)
.await;

let gsm_unified_code = option_gsm.as_ref().and_then(|gsm| gsm.unified_code.clone());
let gsm_unified_message = option_gsm.and_then(|gsm| gsm.unified_message);

let (unified_code, unified_message) = if let Some((code, message)) =
gsm_unified_code.as_ref().zip(gsm_unified_message.as_ref())
{
(code.to_owned(), message.to_owned())
} else {
(
consts::DEFAULT_UNIFIED_ERROR_CODE.to_owned(),
consts::DEFAULT_UNIFIED_ERROR_MESSAGE.to_owned(),
)
};
let header_map = &state.api_client.get_header_map();
let locale = helpers::get_locale_from_header(header_map.as_ref());

let unified_translated_message = helpers::get_unified_translation(
state,
unified_code.to_owned(),
unified_message.to_owned(),
locale.to_owned(),
)
.await
.or(Some(unified_message));

storage::RefundUpdate::ErrorUpdate {
refund_status: Some(enums::RefundStatus::Failure),
refund_error_message: err.reason.or(Some(err.message)),
refund_error_code: Some(err.code),
updated_by: storage_scheme.to_string(),
connector_refund_id: None,
connector_refund_data: None,
unified_code: Some(unified_code),
unified_message: unified_translated_message,
}
}
Ok(response) => {
// match on connector integrity checks
match router_data_res.integrity_check.clone() {
Expand Down Expand Up @@ -319,6 +362,8 @@ pub async fn trigger_refund_to_gateway(
updated_by: storage_scheme.to_string(),
connector_refund_id: refund_connector_transaction_id,
connector_refund_data,
unified_code: None,
unified_message: None,
}
}
Ok(()) => {
Expand Down Expand Up @@ -461,7 +506,7 @@ pub async fn refund_retrieve_core(
.merchant_connector_details
.to_owned()
.async_map(|mcd| async {
payments::helpers::insert_merchant_connector_creds_to_config(db, merchant_id, mcd).await
helpers::insert_merchant_connector_creds_to_config(db, merchant_id, mcd).await
})
.await
.transpose()?;
Expand Down Expand Up @@ -617,6 +662,8 @@ pub async fn sync_refund_with_gateway(
updated_by: storage_scheme.to_string(),
connector_refund_id: None,
connector_refund_data: None,
unified_code: None,
unified_message: None,
}
}
Ok(response) => match router_data_res.integrity_check.clone() {
Expand Down Expand Up @@ -645,6 +692,8 @@ pub async fn sync_refund_with_gateway(
updated_by: storage_scheme.to_string(),
connector_refund_id: refund_connector_transaction_id,
connector_refund_data,
unified_code: None,
unified_message: None,
}
}
Ok(()) => {
Expand Down Expand Up @@ -1199,6 +1248,8 @@ impl ForeignFrom<storage::Refund> for api::RefundResponse {
connector: refund.connector,
merchant_connector_id: refund.merchant_connector_id,
split_refunds: refund.split_refunds,
unified_code: refund.unified_code,
unified_message: refund.unified_message,
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions crates/router/src/db/refund.rs
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,8 @@ mod storage {
organization_id: new.organization_id.clone(),
connector_refund_data: new.connector_refund_data.clone(),
connector_transaction_data: new.connector_transaction_data.clone(),
unified_code: None,
unified_message: None,
};

let field = format!(
Expand Down Expand Up @@ -932,6 +934,8 @@ impl RefundInterface for MockDb {
organization_id: new.organization_id,
connector_refund_data: new.connector_refund_data,
connector_transaction_data: new.connector_transaction_data,
unified_code: None,
unified_message: None,
};
refunds.push(refund.clone());
Ok(refund)
Expand Down
Loading

0 comments on commit b28bd29

Please sign in to comment.