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 26, 2024
1 parent a423ff5 commit d5df68d
Show file tree
Hide file tree
Showing 14 changed files with 193 additions and 42 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
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 = 64]
unified_code -> Nullable<Varchar>,
#[max_length = 1024]
unified_message -> Nullable<Varchar>,
}
}

Expand Down
4 changes: 4 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,10 @@ diesel::table! {
#[max_length = 512]
connector_transaction_data -> Nullable<Varchar>,
split_refunds -> Nullable<Jsonb>,
#[max_length = 64]
unified_code -> Nullable<Varchar>,
#[max_length = 1024]
unified_message -> Nullable<Varchar>,
}
}

Expand Down
3 changes: 3 additions & 0 deletions crates/router/src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,3 +210,6 @@ pub const DYNAMIC_ROUTING_MAX_VOLUME: u8 = 100;

/// Click To Pay
pub const CLICK_TO_PAY: &str = "click_to_pay";

/// Refund flow identifier used for performing GSM operations
pub const REFUND_FLOW_STR: &str = "refund_flow";
72 changes: 61 additions & 11 deletions crates/router/src/core/refunds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,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 +116,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 +237,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 +251,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 +288,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(),
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.get_request_headers();
let locale = utils::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 +361,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 +505,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 +661,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 +691,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 +1247,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
28 changes: 27 additions & 1 deletion crates/router/src/routes/app.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{collections::HashMap, sync::Arc};

use actix_web::{web, Scope};
use actix_web::{http::header::HeaderMap, web, Scope};
#[cfg(all(feature = "olap", feature = "v1"))]
use api_models::routing::RoutingRetrieveQuery;
#[cfg(feature = "olap")]
Expand Down Expand Up @@ -112,6 +112,7 @@ pub struct SessionState {
pub opensearch_client: Arc<OpenSearchClient>,
pub grpc_client: Arc<GrpcClients>,
pub theme_storage_client: Arc<dyn FileStorageInterface>,
pub request_headers: Option<HeaderMap>,
}
impl scheduler::SchedulerSessionState for SessionState {
fn get_db(&self) -> Box<dyn SchedulerInterface> {
Expand All @@ -130,6 +131,14 @@ impl SessionState {
request_id: self.request_id.map(|req_id| (*req_id).to_string()),
}
}

pub fn get_request_headers(&self) -> &Option<HeaderMap> {
&self.request_headers
}

pub fn set_request_headers(&mut self, headers: HeaderMap) {
self.request_headers.replace(headers);
}
}

pub trait SessionStateInfo {
Expand All @@ -141,6 +150,8 @@ pub trait SessionStateInfo {
#[cfg(feature = "partial-auth")]
fn get_detached_auth(&self) -> RouterResult<(Blake3, &[u8])>;
fn session_state(&self) -> SessionState;
fn get_header_map(&self) -> Option<HeaderMap>;
fn add_header_map(&mut self, header_map: HeaderMap);
}

impl SessionStateInfo for SessionState {
Expand All @@ -161,6 +172,12 @@ impl SessionStateInfo for SessionState {
self.store.add_request_id(request_id.to_string());
self.request_id.replace(request_id);
}
fn get_header_map(&self) -> Option<HeaderMap> {
self.api_client.get_header_map()
}
fn add_header_map(&mut self, header_map: HeaderMap) {
self.api_client.add_header_map(header_map);
}

#[cfg(feature = "partial-auth")]
fn get_detached_auth(&self) -> RouterResult<(Blake3, &[u8])> {
Expand Down Expand Up @@ -231,6 +248,8 @@ pub trait AppStateInfo {
fn add_request_id(&mut self, request_id: RequestId);
fn add_flow_name(&mut self, flow_name: String);
fn get_request_id(&self) -> Option<String>;
fn get_header_map(&self) -> Option<HeaderMap>;
fn add_header_map(&mut self, header_map: HeaderMap);
}

#[cfg(feature = "partial-auth")]
Expand Down Expand Up @@ -261,6 +280,12 @@ impl AppStateInfo for AppState {
fn get_request_id(&self) -> Option<String> {
self.api_client.get_request_id()
}
fn get_header_map(&self) -> Option<HeaderMap> {
self.api_client.get_header_map()
}
fn add_header_map(&mut self, header_map: HeaderMap) {
self.api_client.add_header_map(header_map);
}
}

impl AsRef<Self> for AppState {
Expand Down Expand Up @@ -484,6 +509,7 @@ impl AppState {
opensearch_client: Arc::clone(&self.opensearch_client),
grpc_client: Arc::clone(&self.grpc_client),
theme_storage_client: self.theme_storage_client.clone(),
request_headers: None,
})
}
}
Expand Down
Loading

0 comments on commit d5df68d

Please sign in to comment.