mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-27 19:46:48 +08:00
fix: Resolved issue of webhooks response from ucs (#9021)
This commit is contained in:
@ -4263,7 +4263,13 @@ where
|
||||
services::api::ConnectorIntegration<F, RouterDReq, router_types::PaymentsResponseData>,
|
||||
{
|
||||
record_time_taken_with(|| async {
|
||||
if should_call_unified_connector_service(
|
||||
if !matches!(
|
||||
call_connector_action,
|
||||
CallConnectorAction::UCSHandleResponse(_)
|
||||
) && !matches!(
|
||||
call_connector_action,
|
||||
CallConnectorAction::HandleResponse(_),
|
||||
) && should_call_unified_connector_service(
|
||||
state,
|
||||
merchant_context,
|
||||
&router_data,
|
||||
|
||||
@ -1220,6 +1220,7 @@ impl ForeignTryFrom<&hyperswitch_interfaces::webhooks::IncomingWebhookRequestDet
|
||||
}
|
||||
|
||||
/// Webhook transform data structure containing UCS response information
|
||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||
pub struct WebhookTransformData {
|
||||
pub event_type: api_models::webhooks::IncomingWebhookEvent,
|
||||
pub source_verified: bool,
|
||||
@ -1231,16 +1232,8 @@ pub struct WebhookTransformData {
|
||||
pub fn transform_ucs_webhook_response(
|
||||
response: PaymentServiceTransformResponse,
|
||||
) -> Result<WebhookTransformData, error_stack::Report<errors::ApiErrorResponse>> {
|
||||
let event_type = match response.event_type {
|
||||
0 => api_models::webhooks::IncomingWebhookEvent::PaymentIntentSuccess,
|
||||
1 => api_models::webhooks::IncomingWebhookEvent::PaymentIntentFailure,
|
||||
2 => api_models::webhooks::IncomingWebhookEvent::PaymentIntentProcessing,
|
||||
3 => api_models::webhooks::IncomingWebhookEvent::PaymentIntentCancelled,
|
||||
4 => api_models::webhooks::IncomingWebhookEvent::RefundSuccess,
|
||||
5 => api_models::webhooks::IncomingWebhookEvent::RefundFailure,
|
||||
6 => api_models::webhooks::IncomingWebhookEvent::MandateRevoked,
|
||||
_ => api_models::webhooks::IncomingWebhookEvent::EventNotSupported,
|
||||
};
|
||||
let event_type =
|
||||
api_models::webhooks::IncomingWebhookEvent::from_ucs_event_type(response.event_type);
|
||||
|
||||
Ok(WebhookTransformData {
|
||||
event_type,
|
||||
|
||||
@ -695,6 +695,7 @@ async fn process_webhook_business_logic(
|
||||
connector,
|
||||
request_details,
|
||||
event_type,
|
||||
webhook_transform_data,
|
||||
))
|
||||
.await
|
||||
.attach_printable("Incoming webhook flow for payments failed"),
|
||||
@ -931,9 +932,22 @@ async fn payments_incoming_webhook_flow(
|
||||
connector: &ConnectorEnum,
|
||||
request_details: &IncomingWebhookRequestDetails<'_>,
|
||||
event_type: webhooks::IncomingWebhookEvent,
|
||||
webhook_transform_data: &Option<Box<unified_connector_service::WebhookTransformData>>,
|
||||
) -> CustomResult<WebhookResponseTracker, errors::ApiErrorResponse> {
|
||||
let consume_or_trigger_flow = if source_verified {
|
||||
payments::CallConnectorAction::HandleResponse(webhook_details.resource_object)
|
||||
// Determine the appropriate action based on UCS availability
|
||||
let resource_object = webhook_details.resource_object;
|
||||
|
||||
match webhook_transform_data.as_ref() {
|
||||
Some(transform_data) => {
|
||||
// Serialize the transform data to pass to UCS handler
|
||||
let transform_data_bytes = serde_json::to_vec(transform_data.as_ref())
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Failed to serialize UCS webhook transform data")?;
|
||||
payments::CallConnectorAction::UCSHandleResponse(transform_data_bytes)
|
||||
}
|
||||
None => payments::CallConnectorAction::HandleResponse(resource_object),
|
||||
}
|
||||
} else {
|
||||
payments::CallConnectorAction::Trigger
|
||||
};
|
||||
|
||||
@ -61,7 +61,7 @@ use crate::{
|
||||
core::{
|
||||
api_locking,
|
||||
errors::{self, CustomResult},
|
||||
payments,
|
||||
payments, unified_connector_service,
|
||||
},
|
||||
events::{
|
||||
api_logs::{ApiEvent, ApiEventMetric, ApiEventsType},
|
||||
@ -127,6 +127,62 @@ pub type BoxedBillingConnectorPaymentsSyncIntegrationInterface<T, Req, Res> =
|
||||
pub type BoxedVaultConnectorIntegrationInterface<T, Req, Res> =
|
||||
BoxedConnectorIntegrationInterface<T, common_types::VaultConnectorFlowData, Req, Res>;
|
||||
|
||||
/// Handle UCS webhook response processing
|
||||
fn handle_ucs_response<T, Req, Resp>(
|
||||
router_data: types::RouterData<T, Req, Resp>,
|
||||
transform_data_bytes: Vec<u8>,
|
||||
) -> CustomResult<types::RouterData<T, Req, Resp>, errors::ConnectorError>
|
||||
where
|
||||
T: Clone + Debug + 'static,
|
||||
Req: Debug + Clone + 'static,
|
||||
Resp: Debug + Clone + 'static,
|
||||
{
|
||||
let webhook_transform_data: unified_connector_service::WebhookTransformData =
|
||||
serde_json::from_slice(&transform_data_bytes)
|
||||
.change_context(errors::ConnectorError::ResponseDeserializationFailed)
|
||||
.attach_printable("Failed to deserialize UCS webhook transform data")?;
|
||||
|
||||
let webhook_content = webhook_transform_data
|
||||
.webhook_content
|
||||
.ok_or(errors::ConnectorError::ResponseDeserializationFailed)
|
||||
.attach_printable("UCS webhook transform data missing webhook_content")?;
|
||||
|
||||
let payment_get_response = match webhook_content.content {
|
||||
Some(unified_connector_service_client::payments::webhook_response_content::Content::PaymentsResponse(payments_response)) => {
|
||||
Ok(payments_response)
|
||||
},
|
||||
Some(unified_connector_service_client::payments::webhook_response_content::Content::RefundsResponse(_)) => {
|
||||
Err(errors::ConnectorError::ProcessingStepFailed(Some("UCS webhook contains refund response but payment processing was expected".to_string().into())).into())
|
||||
},
|
||||
Some(unified_connector_service_client::payments::webhook_response_content::Content::DisputesResponse(_)) => {
|
||||
Err(errors::ConnectorError::ProcessingStepFailed(Some("UCS webhook contains dispute response but payment processing was expected".to_string().into())).into())
|
||||
},
|
||||
None => {
|
||||
Err(errors::ConnectorError::ResponseDeserializationFailed)
|
||||
.attach_printable("UCS webhook content missing payments_response")
|
||||
}
|
||||
}?;
|
||||
|
||||
let (status, router_data_response, status_code) =
|
||||
unified_connector_service::handle_unified_connector_service_response_for_payment_get(
|
||||
payment_get_response.clone(),
|
||||
)
|
||||
.change_context(errors::ConnectorError::ProcessingStepFailed(None))
|
||||
.attach_printable("Failed to process UCS webhook response using PSync handler")?;
|
||||
|
||||
let mut updated_router_data = router_data;
|
||||
updated_router_data.status = status;
|
||||
|
||||
let _ = router_data_response.map_err(|error_response| {
|
||||
updated_router_data.response = Err(error_response);
|
||||
});
|
||||
updated_router_data.raw_connector_response =
|
||||
payment_get_response.raw_connector_response.map(Secret::new);
|
||||
updated_router_data.connector_http_status_code = Some(status_code);
|
||||
|
||||
Ok(updated_router_data)
|
||||
}
|
||||
|
||||
fn store_raw_connector_response_if_required<T, Req, Resp>(
|
||||
return_raw_connector_response: Option<bool>,
|
||||
router_data: &mut types::RouterData<T, Req, Resp>,
|
||||
@ -186,6 +242,9 @@ where
|
||||
};
|
||||
connector_integration.handle_response(req, None, response)
|
||||
}
|
||||
payments::CallConnectorAction::UCSHandleResponse(transform_data_bytes) => {
|
||||
handle_ucs_response(router_data, transform_data_bytes)
|
||||
}
|
||||
payments::CallConnectorAction::Avoid => Ok(router_data),
|
||||
payments::CallConnectorAction::StatusUpdate {
|
||||
status,
|
||||
|
||||
Reference in New Issue
Block a user