From b28bd2977816b4a0fd3f77912e946c17d91afb50 Mon Sep 17 00:00:00 2001 From: Debarati Date: Tue, 24 Dec 2024 16:37:08 +0530 Subject: [PATCH] add unified error code and error message for refund table --- crates/api_models/src/refunds.rs | 4 + crates/common_utils/src/consts.rs | 3 + crates/diesel_models/src/refund.rs | 26 +++++++ crates/diesel_models/src/schema.rs | 4 + crates/diesel_models/src/schema_v2.rs | 2 + crates/router/src/core/payments/helpers.rs | 16 +++- crates/router/src/core/payouts/helpers.rs | 16 +++- crates/router/src/core/refunds.rs | 73 ++++++++++++++++--- crates/router/src/db/refund.rs | 4 + crates/router/src/routes/app.rs | 18 ++++- crates/router/src/routes/payouts.rs | 37 ++++------ crates/router/src/services/api.rs | 1 + crates/router/src/services/api/client.rs | 19 +++++ .../down.sql | 3 + .../up.sql | 3 + 15 files changed, 191 insertions(+), 38 deletions(-) create mode 100644 migrations/2024-12-24-115958_add-unified-code-and-message-in-refunds/down.sql create mode 100644 migrations/2024-12-24-115958_add-unified-code-and-message-in-refunds/up.sql diff --git a/crates/api_models/src/refunds.rs b/crates/api_models/src/refunds.rs index 36a92e3ab03d..9fd123d5f3ab 100644 --- a/crates/api_models/src/refunds.rs +++ b/crates/api_models/src/refunds.rs @@ -188,6 +188,10 @@ pub struct RefundResponse { pub error_message: Option, /// The code for the error pub error_code: Option, + /// error code unified across the connectors is received here if there was an error while calling connector + pub unified_code: Option, + /// error message unified across the connectors is received here if there was an error while calling connector + pub unified_message: Option, /// The timestamp at which refund is created #[serde(with = "common_utils::custom_serde::iso8601::option")] pub created_at: Option, diff --git a/crates/common_utils/src/consts.rs b/crates/common_utils/src/consts.rs index 3b437b703bef..3cd941196028 100644 --- a/crates/common_utils/src/consts.rs +++ b/crates/common_utils/src/consts.rs @@ -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"; diff --git a/crates/diesel_models/src/refund.rs b/crates/diesel_models/src/refund.rs index 758eba7255ae..b929481d64d5 100644 --- a/crates/diesel_models/src/refund.rs +++ b/crates/diesel_models/src/refund.rs @@ -54,6 +54,8 @@ pub struct Refund { pub connector_refund_data: Option, pub connector_transaction_data: Option, pub split_refunds: Option, + pub unified_code: Option, + pub unified_message: Option, } #[derive( @@ -132,6 +134,8 @@ pub enum RefundUpdate { updated_by: String, connector_refund_id: Option, connector_refund_data: Option, + unified_code: Option, + unified_message: Option, }, ManualUpdate { refund_status: Option, @@ -155,6 +159,8 @@ pub struct RefundUpdateInternal { updated_by: String, modified_at: PrimitiveDateTime, connector_refund_data: Option, + unified_code: Option, + unified_message: Option, } impl RefundUpdateInternal { @@ -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 } } @@ -199,6 +207,8 @@ impl From 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, @@ -216,6 +226,8 @@ impl From 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, @@ -235,11 +247,15 @@ impl From 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, @@ -255,6 +271,8 @@ impl From for RefundUpdateInternal { metadata: None, refund_reason: None, modified_at: common_utils::date_time::now(), + unified_code, + unified_message, }, RefundUpdate::ManualUpdate { refund_status, @@ -273,6 +291,8 @@ impl From for RefundUpdateInternal { refund_reason: None, modified_at: common_utils::date_time::now(), connector_refund_data: None, + unified_code: None, + unified_message: None, }, } } @@ -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), @@ -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 } } @@ -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::(serialized_refund); diff --git a/crates/diesel_models/src/schema.rs b/crates/diesel_models/src/schema.rs index 95bb714cb711..3e865eba69d2 100644 --- a/crates/diesel_models/src/schema.rs +++ b/crates/diesel_models/src/schema.rs @@ -1235,6 +1235,10 @@ diesel::table! { #[max_length = 512] connector_transaction_data -> Nullable, split_refunds -> Nullable, + #[max_length = 255] + unified_code -> Nullable, + #[max_length = 255] + unified_message -> Nullable, } } diff --git a/crates/diesel_models/src/schema_v2.rs b/crates/diesel_models/src/schema_v2.rs index 8bbb4baf9d74..c8c872ac6373 100644 --- a/crates/diesel_models/src/schema_v2.rs +++ b/crates/diesel_models/src/schema_v2.rs @@ -1181,6 +1181,8 @@ diesel::table! { #[max_length = 512] connector_transaction_data -> Nullable, split_refunds -> Nullable, + unified_code -> Nullable, + unified_message -> Nullable, } } diff --git a/crates/router/src/core/payments/helpers.rs b/crates/router/src/core/payments/helpers.rs index eda869c3a6ca..c7dd18eb776a 100644 --- a/crates/router/src/core/payments/helpers.rs +++ b/crates/router/src/core/payments/helpers.rs @@ -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}, @@ -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, @@ -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}, @@ -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()) +} diff --git a/crates/router/src/core/payouts/helpers.rs b/crates/router/src/core/payouts/helpers.rs index b07094c321cc..1ddb6ff6964f 100644 --- a/crates/router/src/core/payouts/helpers.rs +++ b/crates/router/src/core/payouts/helpers.rs @@ -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, @@ -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}, @@ -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()) +} diff --git a/crates/router/src/core/refunds.rs b/crates/router/src/core/refunds.rs index 373a268d6918..24d84b4f1083 100644 --- a/crates/router/src/core/refunds.rs +++ b/crates/router/src/core/refunds.rs @@ -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}, }; @@ -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, }, @@ -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()?; @@ -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 } => { @@ -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, @@ -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() { @@ -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(()) => { @@ -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()?; @@ -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() { @@ -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(()) => { @@ -1199,6 +1248,8 @@ impl ForeignFrom 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, } } } diff --git a/crates/router/src/db/refund.rs b/crates/router/src/db/refund.rs index 3a5c8b7da1ee..88962f73233a 100644 --- a/crates/router/src/db/refund.rs +++ b/crates/router/src/db/refund.rs @@ -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!( @@ -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) diff --git a/crates/router/src/routes/app.rs b/crates/router/src/routes/app.rs index f9dbec774528..7bc9837b3506 100644 --- a/crates/router/src/routes/app.rs +++ b/crates/router/src/routes/app.rs @@ -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")] @@ -141,6 +141,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; + fn add_header_map(&mut self, header_map: HeaderMap); } impl SessionStateInfo for SessionState { @@ -161,6 +163,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 { + 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])> { @@ -231,6 +239,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; + fn get_header_map(&self) -> Option; + fn add_header_map(&mut self, header_map: HeaderMap); } #[cfg(feature = "partial-auth")] @@ -261,6 +271,12 @@ impl AppStateInfo for AppState { fn get_request_id(&self) -> Option { self.api_client.get_request_id() } + fn get_header_map(&self) -> Option { + 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 for AppState { diff --git a/crates/router/src/routes/payouts.rs b/crates/router/src/routes/payouts.rs index 2329a48ef2bc..4459a9a489bf 100644 --- a/crates/router/src/routes/payouts.rs +++ b/crates/router/src/routes/payouts.rs @@ -1,31 +1,20 @@ use actix_web::{ body::{BoxBody, MessageBody}, - http::header::HeaderMap, web, HttpRequest, HttpResponse, Responder, }; -use common_utils::consts; use router_env::{instrument, tracing, Flow}; use super::app::AppState; use crate::{ core::{api_locking, payouts::*}, - headers::ACCEPT_LANGUAGE, services::{ api, - authentication::{self as auth, get_header_value_by_key}, + authentication::{self as auth}, authorization::permissions::Permission, }, types::api::payouts as payout_types, }; -fn get_locale_from_header(headers: &HeaderMap) -> String { - get_header_value_by_key(ACCEPT_LANGUAGE.into(), headers) - .ok() - .flatten() - .map(|val| val.to_string()) - .unwrap_or(consts::DEFAULT_LOCALE.to_string()) -} - /// Payouts - Create #[instrument(skip_all, fields(flow = ?Flow::PayoutsCreate))] pub async fn payouts_create( @@ -34,7 +23,7 @@ pub async fn payouts_create( json_payload: web::Json, ) -> HttpResponse { let flow = Flow::PayoutsCreate; - let locale = get_locale_from_header(req.headers()); + let locale = helpers::get_locale_from_header(Some(req.headers())); Box::pin(api::server_wrap( flow, @@ -65,7 +54,7 @@ pub async fn payouts_retrieve( merchant_id: query_params.merchant_id.to_owned(), }; let flow = Flow::PayoutsRetrieve; - let locale = get_locale_from_header(req.headers()); + let locale = helpers::get_locale_from_header(Some(req.headers())); Box::pin(api::server_wrap( flow, @@ -102,7 +91,7 @@ pub async fn payouts_update( json_payload: web::Json, ) -> HttpResponse { let flow = Flow::PayoutsUpdate; - let locale = get_locale_from_header(req.headers()); + let locale = helpers::get_locale_from_header(Some(req.headers())); let payout_id = path.into_inner(); let mut payout_update_payload = json_payload.into_inner(); payout_update_payload.payout_id = Some(payout_id); @@ -138,7 +127,7 @@ pub async fn payouts_confirm( Ok(auth) => auth, Err(e) => return api::log_and_return_error_response(e), }; - let locale = get_locale_from_header(req.headers()); + let locale = helpers::get_locale_from_header(Some(req.headers())); Box::pin(api::server_wrap( flow, @@ -165,7 +154,7 @@ pub async fn payouts_cancel( let flow = Flow::PayoutsCancel; let mut payload = json_payload.into_inner(); payload.payout_id = path.into_inner(); - let locale = get_locale_from_header(req.headers()); + let locale = helpers::get_locale_from_header(Some(req.headers())); Box::pin(api::server_wrap( flow, @@ -191,7 +180,7 @@ pub async fn payouts_fulfill( let flow = Flow::PayoutsFulfill; let mut payload = json_payload.into_inner(); payload.payout_id = path.into_inner(); - let locale = get_locale_from_header(req.headers()); + let locale = helpers::get_locale_from_header(Some(req.headers())); Box::pin(api::server_wrap( flow, @@ -217,7 +206,7 @@ pub async fn payouts_list( ) -> HttpResponse { let flow = Flow::PayoutsList; let payload = json_payload.into_inner(); - let locale = get_locale_from_header(req.headers()); + let locale = helpers::get_locale_from_header(Some(req.headers())); Box::pin(api::server_wrap( flow, @@ -256,7 +245,7 @@ pub async fn payouts_list_profile( ) -> HttpResponse { let flow = Flow::PayoutsList; let payload = json_payload.into_inner(); - let locale = get_locale_from_header(req.headers()); + let locale = helpers::get_locale_from_header(Some(req.headers())); Box::pin(api::server_wrap( flow, @@ -295,7 +284,7 @@ pub async fn payouts_list_by_filter( ) -> HttpResponse { let flow = Flow::PayoutsList; let payload = json_payload.into_inner(); - let locale = get_locale_from_header(req.headers()); + let locale = helpers::get_locale_from_header(Some(req.headers())); Box::pin(api::server_wrap( flow, @@ -334,7 +323,7 @@ pub async fn payouts_list_by_filter_profile( ) -> HttpResponse { let flow = Flow::PayoutsList; let payload = json_payload.into_inner(); - let locale = get_locale_from_header(req.headers()); + let locale = helpers::get_locale_from_header(Some(req.headers())); Box::pin(api::server_wrap( flow, @@ -373,7 +362,7 @@ pub async fn payouts_list_available_filters_for_merchant( ) -> HttpResponse { let flow = Flow::PayoutsFilter; let payload = json_payload.into_inner(); - let locale = get_locale_from_header(req.headers()); + let locale = helpers::get_locale_from_header(Some(req.headers())); Box::pin(api::server_wrap( flow, @@ -405,7 +394,7 @@ pub async fn payouts_list_available_filters_for_profile( ) -> HttpResponse { let flow = Flow::PayoutsFilter; let payload = json_payload.into_inner(); - let locale = get_locale_from_header(req.headers()); + let locale = helpers::get_locale_from_header(Some(req.headers())); Box::pin(api::server_wrap( flow, diff --git a/crates/router/src/services/api.rs b/crates/router/src/services/api.rs index cac856b2c48b..2f9ad069dc33 100644 --- a/crates/router/src/services/api.rs +++ b/crates/router/src/services/api.rs @@ -766,6 +766,7 @@ where .switch() })?; session_state.add_request_id(request_id); + session_state.add_header_map(incoming_request_header.clone()); let mut request_state = session_state.get_req_state(); request_state.event_context.record_info(request_id); diff --git a/crates/router/src/services/api/client.rs b/crates/router/src/services/api/client.rs index 9a496c18d9a6..a17d08a5e94b 100644 --- a/crates/router/src/services/api/client.rs +++ b/crates/router/src/services/api/client.rs @@ -1,5 +1,6 @@ use std::time::Duration; +use actix_web::http::header::HeaderMap; use base64::Engine; use error_stack::ResultExt; use http::{HeaderValue, Method}; @@ -220,6 +221,8 @@ where fn add_request_id(&mut self, request_id: RequestId); fn get_request_id(&self) -> Option; fn add_flow_name(&mut self, flow_name: String); + fn get_header_map(&self) -> Option; + fn add_header_map(&mut self, header_map: HeaderMap); } dyn_clone::clone_trait_object!(ApiClient); @@ -230,6 +233,7 @@ pub struct ProxyClient { non_proxy_client: reqwest::Client, whitelisted_urls: Vec, request_id: Option, + header_map: Option, } impl ProxyClient { @@ -267,6 +271,7 @@ impl ProxyClient { non_proxy_client, whitelisted_urls, request_id: None, + header_map: None, }) } @@ -400,6 +405,14 @@ impl ApiClient for ProxyClient { self.request_id.clone() } + fn get_header_map(&self) -> Option { + self.header_map.clone() + } + + fn add_header_map(&mut self, header_map: HeaderMap) { + self.header_map.replace(header_map); + } + fn add_flow_name(&mut self, _flow_name: String) {} } @@ -449,5 +462,11 @@ impl ApiClient for MockApiClient { None } + fn get_header_map(&self) -> Option { + None + } + + fn add_header_map(&mut self, _header_map: HeaderMap) {} + fn add_flow_name(&mut self, _flow_name: String) {} } diff --git a/migrations/2024-12-24-115958_add-unified-code-and-message-in-refunds/down.sql b/migrations/2024-12-24-115958_add-unified-code-and-message-in-refunds/down.sql new file mode 100644 index 000000000000..74679837d38c --- /dev/null +++ b/migrations/2024-12-24-115958_add-unified-code-and-message-in-refunds/down.sql @@ -0,0 +1,3 @@ +-- This file should undo anything in `up.sql` +ALTER TABLE refund DROP COLUMN IF EXISTS unified_code; +ALTER TABLE refund DROP COLUMN IF EXISTS unified_message; \ No newline at end of file diff --git a/migrations/2024-12-24-115958_add-unified-code-and-message-in-refunds/up.sql b/migrations/2024-12-24-115958_add-unified-code-and-message-in-refunds/up.sql new file mode 100644 index 000000000000..0856f47ad686 --- /dev/null +++ b/migrations/2024-12-24-115958_add-unified-code-and-message-in-refunds/up.sql @@ -0,0 +1,3 @@ +-- Your SQL goes here +ALTER TABLE refund ADD COLUMN IF NOT EXISTS unified_code VARCHAR(255); +ALTER TABLE refund ADD COLUMN IF NOT EXISTS unified_message VARCHAR(255); \ No newline at end of file