Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(router): add unified_code, unified_message in payments response #2918

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions crates/api_models/src/gsm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ pub struct GsmCreateRequest {
pub router_error: Option<String>,
pub decision: GsmDecision,
pub step_up_possible: bool,
pub unified_code: Option<String>,
pub unified_message: Option<String>,
}

#[derive(Debug, serde::Deserialize, serde::Serialize, ToSchema)]
Expand Down Expand Up @@ -57,6 +59,8 @@ pub struct GsmUpdateRequest {
pub router_error: Option<String>,
pub decision: Option<GsmDecision>,
pub step_up_possible: Option<bool>,
pub unified_code: Option<String>,
pub unified_message: Option<String>,
}

#[derive(Debug, serde::Deserialize, serde::Serialize, ToSchema)]
Expand Down Expand Up @@ -88,4 +92,6 @@ pub struct GsmResponse {
pub router_error: Option<String>,
pub decision: String,
pub step_up_possible: bool,
pub unified_code: Option<String>,
pub unified_message: Option<String>,
}
10 changes: 10 additions & 0 deletions crates/api_models/src/payments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,10 @@ pub struct PaymentAttemptResponse {
/// reference to the payment at connector side
#[schema(value_type = Option<String>, example = "993672945374576J")]
pub reference_id: 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>,
sai-harsha-vardhan marked this conversation as resolved.
Show resolved Hide resolved
}

#[derive(
Expand Down Expand Up @@ -2089,6 +2093,12 @@ pub struct PaymentsResponse {
#[schema(example = "Failed while verifying the card")]
pub error_message: 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>,

/// Payment Experience for the current payment
#[schema(value_type = Option<PaymentExperience>, example = "redirect_to_url")]
pub payment_experience: Option<api_enums::PaymentExperience>,
Expand Down
8 changes: 8 additions & 0 deletions crates/data_models/src/payments/payment_attempt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ pub struct PaymentAttempt {
pub authentication_data: Option<serde_json::Value>,
pub encoded_data: Option<String>,
pub merchant_connector_id: Option<String>,
pub unified_code: Option<String>,
pub unified_message: Option<String>,
}

#[derive(Clone, Debug, Eq, PartialEq)]
Expand Down Expand Up @@ -207,6 +209,8 @@ pub struct PaymentAttemptNew {
pub authentication_data: Option<serde_json::Value>,
pub encoded_data: Option<String>,
pub merchant_connector_id: Option<String>,
pub unified_code: Option<String>,
pub unified_message: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
Expand Down Expand Up @@ -292,6 +296,8 @@ pub enum PaymentAttemptUpdate {
updated_by: String,
authentication_data: Option<serde_json::Value>,
encoded_data: Option<String>,
unified_code: Option<Option<String>>,
unified_message: Option<Option<String>>,
},
UnresolvedResponseUpdate {
status: storage_enums::AttemptStatus,
Expand All @@ -316,6 +322,8 @@ pub enum PaymentAttemptUpdate {
error_reason: Option<Option<String>>,
amount_capturable: Option<i64>,
updated_by: String,
unified_code: Option<Option<String>>,
unified_message: Option<Option<String>>,
},
MultipleCaptureCountUpdate {
multiple_capture_count: i16,
Expand Down
12 changes: 12 additions & 0 deletions crates/diesel_models/src/gsm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ pub struct GatewayStatusMap {
#[serde(with = "custom_serde::iso8601")]
pub last_modified: PrimitiveDateTime,
pub step_up_possible: bool,
pub unified_code: Option<String>,
pub unified_message: Option<String>,
}

#[derive(Clone, Debug, Eq, PartialEq, Insertable)]
Expand All @@ -48,6 +50,8 @@ pub struct GatewayStatusMappingNew {
pub router_error: Option<String>,
pub decision: String,
pub step_up_possible: bool,
pub unified_code: Option<String>,
pub unified_message: Option<String>,
}

#[derive(
Expand All @@ -71,6 +75,8 @@ pub struct GatewayStatusMapperUpdateInternal {
pub router_error: Option<Option<String>>,
pub decision: Option<String>,
pub step_up_possible: Option<bool>,
pub unified_code: Option<String>,
pub unified_message: Option<String>,
}

#[derive(Debug)]
Expand All @@ -79,6 +85,8 @@ pub struct GatewayStatusMappingUpdate {
pub router_error: Option<Option<String>>,
pub decision: Option<String>,
pub step_up_possible: Option<bool>,
pub unified_code: Option<String>,
pub unified_message: Option<String>,
}

impl From<GatewayStatusMappingUpdate> for GatewayStatusMapperUpdateInternal {
Expand All @@ -88,12 +96,16 @@ impl From<GatewayStatusMappingUpdate> for GatewayStatusMapperUpdateInternal {
status,
router_error,
step_up_possible,
unified_code,
unified_message,
} = value;
Self {
status,
router_error,
decision,
step_up_possible,
unified_code,
unified_message,
..Default::default()
}
}
Expand Down
20 changes: 20 additions & 0 deletions crates/diesel_models/src/payment_attempt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ pub struct PaymentAttempt {
pub merchant_connector_id: Option<String>,
pub authentication_data: Option<serde_json::Value>,
pub encoded_data: Option<String>,
pub unified_code: Option<String>,
pub unified_message: Option<String>,
}

#[derive(Clone, Debug, Eq, PartialEq, Queryable, Serialize, Deserialize)]
Expand Down Expand Up @@ -124,6 +126,8 @@ pub struct PaymentAttemptNew {
pub merchant_connector_id: Option<String>,
pub authentication_data: Option<serde_json::Value>,
pub encoded_data: Option<String>,
pub unified_code: Option<String>,
pub unified_message: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
Expand Down Expand Up @@ -209,6 +213,8 @@ pub enum PaymentAttemptUpdate {
updated_by: String,
authentication_data: Option<serde_json::Value>,
encoded_data: Option<String>,
unified_code: Option<Option<String>>,
unified_message: Option<Option<String>>,
},
UnresolvedResponseUpdate {
status: storage_enums::AttemptStatus,
Expand All @@ -233,6 +239,8 @@ pub enum PaymentAttemptUpdate {
error_reason: Option<Option<String>>,
amount_capturable: Option<i64>,
updated_by: String,
unified_code: Option<Option<String>>,
unified_message: Option<Option<String>>,
},
MultipleCaptureCountUpdate {
multiple_capture_count: i16,
Expand Down Expand Up @@ -298,6 +306,8 @@ pub struct PaymentAttemptUpdateInternal {
merchant_connector_id: Option<String>,
authentication_data: Option<serde_json::Value>,
encoded_data: Option<String>,
unified_code: Option<Option<String>>,
unified_message: Option<Option<String>>,
}

impl PaymentAttemptUpdate {
Expand Down Expand Up @@ -352,6 +362,8 @@ impl PaymentAttemptUpdate {
merchant_connector_id: pa_update.merchant_connector_id,
authentication_data: pa_update.authentication_data.or(source.authentication_data),
encoded_data: pa_update.encoded_data.or(source.encoded_data),
unified_code: pa_update.unified_code.unwrap_or(source.unified_code),
unified_message: pa_update.unified_message.unwrap_or(source.unified_message),
..source
}
}
Expand Down Expand Up @@ -488,6 +500,8 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
updated_by,
authentication_data,
encoded_data,
unified_code,
unified_message,
} => Self {
status: Some(status),
connector,
Expand All @@ -508,6 +522,8 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
tax_amount,
authentication_data,
encoded_data,
unified_code,
unified_message,
..Default::default()
},
PaymentAttemptUpdate::ErrorUpdate {
Expand All @@ -518,6 +534,8 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
error_reason,
amount_capturable,
updated_by,
unified_code,
unified_message,
} => Self {
connector,
status: Some(status),
Expand All @@ -527,6 +545,8 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
error_reason,
amount_capturable,
updated_by,
unified_code,
unified_message,
..Default::default()
},
PaymentAttemptUpdate::StatusUpdate { status, updated_by } => Self {
Expand Down
8 changes: 8 additions & 0 deletions crates/diesel_models/src/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,10 @@ diesel::table! {
created_at -> Timestamp,
last_modified -> Timestamp,
step_up_possible -> Bool,
#[max_length = 255]
unified_code -> Nullable<Varchar>,
#[max_length = 1024]
unified_message -> Nullable<Varchar>,
}
}

Expand Down Expand Up @@ -584,6 +588,10 @@ diesel::table! {
merchant_connector_id -> Nullable<Varchar>,
authentication_data -> Nullable<Json>,
encoded_data -> Nullable<Text>,
#[max_length = 255]
unified_code -> Nullable<Varchar>,
#[max_length = 1024]
unified_message -> Nullable<Varchar>,
}
}

Expand Down
4 changes: 4 additions & 0 deletions crates/router/src/core/gsm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ pub async fn update_gsm_rule(
status,
router_error,
step_up_possible,
unified_code,
unified_message,
} = gsm_request;
GsmInterface::update_gsm_rule(
db,
Expand All @@ -78,6 +80,8 @@ pub async fn update_gsm_rule(
status,
router_error: Some(router_error),
step_up_possible,
unified_code,
unified_message,
},
)
.await
Expand Down
45 changes: 45 additions & 0 deletions crates/router/src/core/payments/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2943,6 +2943,8 @@ impl AttemptType {
authentication_data: None,
encoded_data: None,
merchant_connector_id: None,
unified_code: None,
unified_message: None,
}
}

Expand Down Expand Up @@ -3433,3 +3435,46 @@ pub fn validate_payment_link_request(
}
Ok(())
}

pub async fn get_gsm_record(
state: &AppState,
error_code: Option<String>,
error_message: Option<String>,
connector_name: String,
flow: String,
) -> Option<storage::gsm::GatewayStatusMap> {
let get_gsm = || async {
state.store.find_gsm_rule(
connector_name.clone(),
flow.clone(),
"sub_flow".to_string(),
error_code.clone().unwrap_or_default(), // TODO: make changes in connector to get a mandatory code in case of success or error response
error_message.clone().unwrap_or_default(),
)
.await
.map_err(|err| {
if err.current_context().is_db_not_found() {
logger::warn!(
"GSM miss for connector - {}, flow - {}, error_code - {:?}, error_message - {:?}",
connector_name,
flow,
error_code,
error_message
);
metrics::AUTO_RETRY_GSM_MISS_COUNT.add(&metrics::CONTEXT, 1, &[]);
} else {
metrics::AUTO_RETRY_GSM_FETCH_FAILURE_COUNT.add(&metrics::CONTEXT, 1, &[]);
};
err.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("failed to fetch decision from gsm")
})
};
get_gsm()
.await
.map_err(|err| {
// warn log should suffice here because we are not propagating this error
logger::warn!(get_gsm_decision_fetch_error=?err, "error fetching gsm decision");
err
})
.ok()
}
17 changes: 15 additions & 2 deletions crates/router/src/core/payments/operations/payment_response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use crate::{
errors::{self, RouterResult, StorageErrorExt},
mandate,
payment_methods::PaymentMethodRetrieve,
payments::{types::MultipleCaptureData, PaymentData},
payments::{helpers as payments_helpers, types::MultipleCaptureData, PaymentData},
utils as core_utils,
},
routes::{metrics, AppState},
Expand Down Expand Up @@ -331,7 +331,16 @@ async fn payment_response_update_tracker<F: Clone, T: types::Capturable>(
(Some((multiple_capture_data, capture_update_list)), None)
}
None => {
let connector_name = router_data.connector.to_string();
let flow_name = core_utils::get_flow_name::<F>()?;
let option_gsm = payments_helpers::get_gsm_record(
state,
Some(err.code.clone()),
Some(err.message.clone()),
connector_name,
flow_name.clone(),
)
.await;
let status =
// mark previous attempt status for technical failures in PSync flow
if flow_name == "PSync" {
Expand Down Expand Up @@ -364,6 +373,8 @@ async fn payment_response_update_tracker<F: Clone, T: types::Capturable>(
None
},
updated_by: storage_scheme.to_string(),
unified_code: option_gsm.clone().map(|gsm| gsm.unified_code),
unified_message: option_gsm.map(|gsm| gsm.unified_message),
}),
)
}
Expand Down Expand Up @@ -470,7 +481,9 @@ async fn payment_response_update_tracker<F: Clone, T: types::Capturable>(
payment_token: None,
error_code: error_status.clone(),
error_message: error_status.clone(),
error_reason: error_status,
error_reason: error_status.clone(),
unified_code: error_status.clone(),
unified_message: error_status,
connector_response_reference_id,
amount_capturable: if router_data.status.is_terminal_status()
|| router_data
Expand Down
Loading
Loading