mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-11-03 21:37:41 +08:00
refactor(router): send 200 response for 5xx status codes received from connector (#1440)
This commit is contained in:
committed by
GitHub
parent
ee5466a3b0
commit
1e5d2a28f6
@ -2072,6 +2072,7 @@ impl AttemptType {
|
|||||||
straight_through_algorithm: old_payment_attempt.straight_through_algorithm,
|
straight_through_algorithm: old_payment_attempt.straight_through_algorithm,
|
||||||
mandate_details: old_payment_attempt.mandate_details,
|
mandate_details: old_payment_attempt.mandate_details,
|
||||||
preprocessing_step_id: None,
|
preprocessing_step_id: None,
|
||||||
|
error_reason: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -64,7 +64,10 @@ impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::PaymentsAuthorizeData
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
router_response.map(|_| ()).or_else(|error_response| {
|
router_response.map(|_| ()).or_else(|error_response| {
|
||||||
fp_utils::when(!(200..300).contains(&error_response.status_code), || {
|
fp_utils::when(
|
||||||
|
!(200..300).contains(&error_response.status_code)
|
||||||
|
&& !(500..=511).contains(&error_response.status_code),
|
||||||
|
|| {
|
||||||
Err(errors::ApiErrorResponse::ExternalConnectorError {
|
Err(errors::ApiErrorResponse::ExternalConnectorError {
|
||||||
code: error_response.code,
|
code: error_response.code,
|
||||||
message: error_response.message,
|
message: error_response.message,
|
||||||
@ -72,7 +75,8 @@ impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::PaymentsAuthorizeData
|
|||||||
status_code: error_response.status_code,
|
status_code: error_response.status_code,
|
||||||
reason: error_response.reason,
|
reason: error_response.reason,
|
||||||
})
|
})
|
||||||
})
|
},
|
||||||
|
)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(payment_data)
|
Ok(payment_data)
|
||||||
@ -295,9 +299,13 @@ async fn payment_response_update_tracker<F: Clone, T: types::Capturable>(
|
|||||||
Err(err) => (
|
Err(err) => (
|
||||||
Some(storage::PaymentAttemptUpdate::ErrorUpdate {
|
Some(storage::PaymentAttemptUpdate::ErrorUpdate {
|
||||||
connector: None,
|
connector: None,
|
||||||
status: storage::enums::AttemptStatus::Failure,
|
status: match err.status_code {
|
||||||
|
400..=499 => storage::enums::AttemptStatus::Failure,
|
||||||
|
_ => storage::enums::AttemptStatus::Pending,
|
||||||
|
},
|
||||||
error_message: Some(Some(err.message)),
|
error_message: Some(Some(err.message)),
|
||||||
error_code: Some(Some(err.code)),
|
error_code: Some(Some(err.code)),
|
||||||
|
error_reason: Some(err.reason),
|
||||||
}),
|
}),
|
||||||
Some(storage::ConnectorResponseUpdate::ErrorUpdate {
|
Some(storage::ConnectorResponseUpdate::ErrorUpdate {
|
||||||
connector_name: Some(router_data.connector.clone()),
|
connector_name: Some(router_data.connector.clone()),
|
||||||
@ -361,7 +369,8 @@ async fn payment_response_update_tracker<F: Clone, T: types::Capturable>(
|
|||||||
connector_metadata,
|
connector_metadata,
|
||||||
payment_token: None,
|
payment_token: None,
|
||||||
error_code: error_status.clone(),
|
error_code: error_status.clone(),
|
||||||
error_message: error_status,
|
error_message: error_status.clone(),
|
||||||
|
error_reason: error_status,
|
||||||
};
|
};
|
||||||
|
|
||||||
let connector_response_update = storage::ConnectorResponseUpdate::ResponseUpdate {
|
let connector_response_update = storage::ConnectorResponseUpdate::ResponseUpdate {
|
||||||
@ -392,7 +401,8 @@ async fn payment_response_update_tracker<F: Clone, T: types::Capturable>(
|
|||||||
connector_transaction_id,
|
connector_transaction_id,
|
||||||
payment_method_id: Some(router_data.payment_method_id),
|
payment_method_id: Some(router_data.payment_method_id),
|
||||||
error_code: Some(reason.clone().map(|cd| cd.code)),
|
error_code: Some(reason.clone().map(|cd| cd.code)),
|
||||||
error_message: Some(reason.map(|cd| cd.message)),
|
error_message: Some(reason.clone().map(|cd| cd.message)),
|
||||||
|
error_reason: Some(reason.map(|cd| cd.message)),
|
||||||
}),
|
}),
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
@ -437,9 +447,12 @@ async fn payment_response_update_tracker<F: Clone, T: types::Capturable>(
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
let payment_intent_update = match router_data.response {
|
let payment_intent_update = match &router_data.response {
|
||||||
Err(_) => storage::PaymentIntentUpdate::PGStatusUpdate {
|
Err(err) => storage::PaymentIntentUpdate::PGStatusUpdate {
|
||||||
status: enums::IntentStatus::Failed,
|
status: match err.status_code {
|
||||||
|
400..=499 => enums::IntentStatus::Failed,
|
||||||
|
_ => enums::IntentStatus::Processing,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Ok(_) => storage::PaymentIntentUpdate::ResponseUpdate {
|
Ok(_) => storage::PaymentIntentUpdate::ResponseUpdate {
|
||||||
status: router_data.status.foreign_into(),
|
status: router_data.status.foreign_into(),
|
||||||
|
|||||||
@ -406,7 +406,7 @@ where
|
|||||||
auth_flow == services::AuthFlow::Merchant,
|
auth_flow == services::AuthFlow::Merchant,
|
||||||
)
|
)
|
||||||
.set_payment_token(payment_attempt.payment_token)
|
.set_payment_token(payment_attempt.payment_token)
|
||||||
.set_error_message(payment_attempt.error_message)
|
.set_error_message(payment_attempt.error_reason)
|
||||||
.set_error_code(payment_attempt.error_code)
|
.set_error_code(payment_attempt.error_code)
|
||||||
.set_shipping(address.shipping)
|
.set_shipping(address.shipping)
|
||||||
.set_billing(address.billing)
|
.set_billing(address.billing)
|
||||||
|
|||||||
@ -303,6 +303,7 @@ impl PaymentAttemptInterface for MockDb {
|
|||||||
straight_through_algorithm: payment_attempt.straight_through_algorithm,
|
straight_through_algorithm: payment_attempt.straight_through_algorithm,
|
||||||
mandate_details: payment_attempt.mandate_details,
|
mandate_details: payment_attempt.mandate_details,
|
||||||
preprocessing_step_id: payment_attempt.preprocessing_step_id,
|
preprocessing_step_id: payment_attempt.preprocessing_step_id,
|
||||||
|
error_reason: payment_attempt.error_reason,
|
||||||
};
|
};
|
||||||
payment_attempts.push(payment_attempt.clone());
|
payment_attempts.push(payment_attempt.clone());
|
||||||
Ok(payment_attempt)
|
Ok(payment_attempt)
|
||||||
@ -440,6 +441,7 @@ mod storage {
|
|||||||
.clone(),
|
.clone(),
|
||||||
mandate_details: payment_attempt.mandate_details.clone(),
|
mandate_details: payment_attempt.mandate_details.clone(),
|
||||||
preprocessing_step_id: payment_attempt.preprocessing_step_id.clone(),
|
preprocessing_step_id: payment_attempt.preprocessing_step_id.clone(),
|
||||||
|
error_reason: payment_attempt.error_reason.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let field = format!("pa_{}", created_attempt.attempt_id);
|
let field = format!("pa_{}", created_attempt.attempt_id);
|
||||||
|
|||||||
@ -145,6 +145,32 @@ pub trait ConnectorIntegration<T, Req, Resp>: ConnectorIntegrationAny<T, Req, Re
|
|||||||
Ok(ErrorResponse::get_not_implemented())
|
Ok(ErrorResponse::get_not_implemented())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_5xx_error_response(
|
||||||
|
&self,
|
||||||
|
res: types::Response,
|
||||||
|
) -> CustomResult<ErrorResponse, errors::ConnectorError> {
|
||||||
|
let error_message = match res.status_code {
|
||||||
|
500 => "internal_server_error",
|
||||||
|
501 => "not_implemented",
|
||||||
|
502 => "bad_gateway",
|
||||||
|
503 => "service_unavailable",
|
||||||
|
504 => "gateway_timeout",
|
||||||
|
505 => "http_version_not_supported",
|
||||||
|
506 => "variant_also_negotiates",
|
||||||
|
507 => "insufficient_storage",
|
||||||
|
508 => "loop_detected",
|
||||||
|
510 => "not_extended",
|
||||||
|
511 => "network_authentication_required",
|
||||||
|
_ => "unknown_error",
|
||||||
|
};
|
||||||
|
Ok(ErrorResponse {
|
||||||
|
code: res.status_code.to_string(),
|
||||||
|
message: error_message.to_string(),
|
||||||
|
reason: String::from_utf8(res.response.to_vec()).ok(),
|
||||||
|
status_code: res.status_code,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn get_certificate(
|
fn get_certificate(
|
||||||
&self,
|
&self,
|
||||||
_req: &types::RouterData<T, Req, Resp>,
|
_req: &types::RouterData<T, Req, Resp>,
|
||||||
@ -278,7 +304,13 @@ where
|
|||||||
req.connector.clone(),
|
req.connector.clone(),
|
||||||
)],
|
)],
|
||||||
);
|
);
|
||||||
let error = connector_integration.get_error_response(body)?;
|
let error = match body.status_code {
|
||||||
|
500..=511 => {
|
||||||
|
connector_integration.get_5xx_error_response(body)?
|
||||||
|
}
|
||||||
|
_ => connector_integration.get_error_response(body)?,
|
||||||
|
};
|
||||||
|
|
||||||
router_data.response = Err(error);
|
router_data.response = Err(error);
|
||||||
|
|
||||||
router_data
|
router_data
|
||||||
|
|||||||
@ -49,6 +49,7 @@ pub struct PaymentAttempt {
|
|||||||
pub preprocessing_step_id: Option<String>,
|
pub preprocessing_step_id: Option<String>,
|
||||||
// providing a location to store mandate details intermediately for transaction
|
// providing a location to store mandate details intermediately for transaction
|
||||||
pub mandate_details: Option<storage_enums::MandateDataType>,
|
pub mandate_details: Option<storage_enums::MandateDataType>,
|
||||||
|
pub error_reason: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
@ -96,6 +97,7 @@ pub struct PaymentAttemptNew {
|
|||||||
pub straight_through_algorithm: Option<serde_json::Value>,
|
pub straight_through_algorithm: Option<serde_json::Value>,
|
||||||
pub preprocessing_step_id: Option<String>,
|
pub preprocessing_step_id: Option<String>,
|
||||||
pub mandate_details: Option<storage_enums::MandateDataType>,
|
pub mandate_details: Option<storage_enums::MandateDataType>,
|
||||||
|
pub error_reason: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
@ -150,6 +152,7 @@ pub enum PaymentAttemptUpdate {
|
|||||||
payment_token: Option<String>,
|
payment_token: Option<String>,
|
||||||
error_code: Option<Option<String>>,
|
error_code: Option<Option<String>>,
|
||||||
error_message: Option<Option<String>>,
|
error_message: Option<Option<String>>,
|
||||||
|
error_reason: Option<Option<String>>,
|
||||||
},
|
},
|
||||||
UnresolvedResponseUpdate {
|
UnresolvedResponseUpdate {
|
||||||
status: storage_enums::AttemptStatus,
|
status: storage_enums::AttemptStatus,
|
||||||
@ -158,6 +161,7 @@ pub enum PaymentAttemptUpdate {
|
|||||||
payment_method_id: Option<Option<String>>,
|
payment_method_id: Option<Option<String>>,
|
||||||
error_code: Option<Option<String>>,
|
error_code: Option<Option<String>>,
|
||||||
error_message: Option<Option<String>>,
|
error_message: Option<Option<String>>,
|
||||||
|
error_reason: Option<Option<String>>,
|
||||||
},
|
},
|
||||||
StatusUpdate {
|
StatusUpdate {
|
||||||
status: storage_enums::AttemptStatus,
|
status: storage_enums::AttemptStatus,
|
||||||
@ -167,6 +171,7 @@ pub enum PaymentAttemptUpdate {
|
|||||||
status: storage_enums::AttemptStatus,
|
status: storage_enums::AttemptStatus,
|
||||||
error_code: Option<Option<String>>,
|
error_code: Option<Option<String>>,
|
||||||
error_message: Option<Option<String>>,
|
error_message: Option<Option<String>>,
|
||||||
|
error_reason: Option<Option<String>>,
|
||||||
},
|
},
|
||||||
PreprocessingUpdate {
|
PreprocessingUpdate {
|
||||||
status: storage_enums::AttemptStatus,
|
status: storage_enums::AttemptStatus,
|
||||||
@ -201,6 +206,7 @@ pub struct PaymentAttemptUpdateInternal {
|
|||||||
business_sub_label: Option<String>,
|
business_sub_label: Option<String>,
|
||||||
straight_through_algorithm: Option<serde_json::Value>,
|
straight_through_algorithm: Option<serde_json::Value>,
|
||||||
preprocessing_step_id: Option<String>,
|
preprocessing_step_id: Option<String>,
|
||||||
|
error_reason: Option<Option<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PaymentAttemptUpdate {
|
impl PaymentAttemptUpdate {
|
||||||
@ -319,6 +325,7 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
|
|||||||
payment_token,
|
payment_token,
|
||||||
error_code,
|
error_code,
|
||||||
error_message,
|
error_message,
|
||||||
|
error_reason,
|
||||||
} => Self {
|
} => Self {
|
||||||
status: Some(status),
|
status: Some(status),
|
||||||
connector,
|
connector,
|
||||||
@ -331,6 +338,7 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
|
|||||||
error_code,
|
error_code,
|
||||||
error_message,
|
error_message,
|
||||||
payment_token,
|
payment_token,
|
||||||
|
error_reason,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
PaymentAttemptUpdate::ErrorUpdate {
|
PaymentAttemptUpdate::ErrorUpdate {
|
||||||
@ -338,12 +346,14 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
|
|||||||
status,
|
status,
|
||||||
error_code,
|
error_code,
|
||||||
error_message,
|
error_message,
|
||||||
|
error_reason,
|
||||||
} => Self {
|
} => Self {
|
||||||
connector,
|
connector,
|
||||||
status: Some(status),
|
status: Some(status),
|
||||||
error_message,
|
error_message,
|
||||||
error_code,
|
error_code,
|
||||||
modified_at: Some(common_utils::date_time::now()),
|
modified_at: Some(common_utils::date_time::now()),
|
||||||
|
error_reason,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
PaymentAttemptUpdate::StatusUpdate { status } => Self {
|
PaymentAttemptUpdate::StatusUpdate { status } => Self {
|
||||||
@ -367,6 +377,7 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
|
|||||||
payment_method_id,
|
payment_method_id,
|
||||||
error_code,
|
error_code,
|
||||||
error_message,
|
error_message,
|
||||||
|
error_reason,
|
||||||
} => Self {
|
} => Self {
|
||||||
status: Some(status),
|
status: Some(status),
|
||||||
connector,
|
connector,
|
||||||
@ -375,6 +386,7 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
|
|||||||
modified_at: Some(common_utils::date_time::now()),
|
modified_at: Some(common_utils::date_time::now()),
|
||||||
error_code,
|
error_code,
|
||||||
error_message,
|
error_message,
|
||||||
|
error_reason,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
PaymentAttemptUpdate::PreprocessingUpdate {
|
PaymentAttemptUpdate::PreprocessingUpdate {
|
||||||
|
|||||||
@ -429,6 +429,7 @@ diesel::table! {
|
|||||||
straight_through_algorithm -> Nullable<Jsonb>,
|
straight_through_algorithm -> Nullable<Jsonb>,
|
||||||
preprocessing_step_id -> Nullable<Varchar>,
|
preprocessing_step_id -> Nullable<Varchar>,
|
||||||
mandate_details -> Nullable<Jsonb>,
|
mandate_details -> Nullable<Jsonb>,
|
||||||
|
error_reason -> Nullable<Text>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,3 @@
|
|||||||
|
-- This file should undo anything in `up.sql`
|
||||||
|
ALTER TABLE payment_attempt
|
||||||
|
DROP COLUMN error_reason;
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE payment_attempt
|
||||||
|
ADD COLUMN error_reason TEXT;
|
||||||
Reference in New Issue
Block a user