Skip to content

Commit

Permalink
feat(router): add unified_code, unified_message in payments response (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
sai-harsha-vardhan authored Nov 20, 2023
1 parent efeebc0 commit 3954001
Show file tree
Hide file tree
Showing 20 changed files with 242 additions and 45 deletions.
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>,
}

#[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 @@ -585,6 +589,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 @@ -3026,6 +3026,8 @@ impl AttemptType {
authentication_data: None,
encoded_data: None,
merchant_connector_id: None,
unified_code: None,
unified_message: None,
}
}

Expand Down Expand Up @@ -3516,3 +3518,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

0 comments on commit 3954001

Please sign in to comment.