mirror of
				https://github.com/juspay/hyperswitch.git
				synced 2025-10-31 01:57:45 +08:00 
			
		
		
		
	fix(connector): implement ConnectorErrorExt for error_stack::Result<T, ConnectorError> (#1382)
Co-authored-by: Narayan Bhat <48803246+Narayanbhat166@users.noreply.github.com>
This commit is contained in:
		 Abhishek Marrivagu
					Abhishek Marrivagu
				
			
				
					committed by
					
						 GitHub
						GitHub
					
				
			
			
				
	
			
			
			 GitHub
						GitHub
					
				
			
						parent
						
							a7ac4af5d9
						
					
				
				
					commit
					3ef1d2935e
				
			| @ -129,7 +129,7 @@ pub async fn accept_dispute( | ||||
|         payments::CallConnectorAction::Trigger, | ||||
|     ) | ||||
|     .await | ||||
|     .map_err(|error| error.to_dispute_failed_response()) | ||||
|     .to_dispute_failed_response() | ||||
|     .attach_printable("Failed while calling accept dispute connector api")?; | ||||
|     let accept_dispute_response = | ||||
|         response | ||||
| @ -236,7 +236,7 @@ pub async fn submit_evidence( | ||||
|         payments::CallConnectorAction::Trigger, | ||||
|     ) | ||||
|     .await | ||||
|     .map_err(|error| error.to_payment_failed_response()) | ||||
|     .to_dispute_failed_response() | ||||
|     .attach_printable("Failed while calling submit evidence connector api")?; | ||||
|     let submit_evidence_response = | ||||
|         response | ||||
| @ -272,7 +272,7 @@ pub async fn submit_evidence( | ||||
|                 payments::CallConnectorAction::Trigger, | ||||
|             ) | ||||
|             .await | ||||
|             .map_err(|error| error.to_payment_failed_response()) | ||||
|             .to_dispute_failed_response() | ||||
|             .attach_printable("Failed while calling defend dispute connector api")?; | ||||
|             let defend_dispute_response = defend_response.response.map_err(|err| { | ||||
|                 errors::ApiErrorResponse::ExternalConnectorError { | ||||
|  | ||||
| @ -43,143 +43,153 @@ impl<T> StorageErrorExt<T, errors::ApiErrorResponse> | ||||
|     } | ||||
| } | ||||
|  | ||||
| pub trait ConnectorErrorExt { | ||||
| pub trait ConnectorErrorExt<T> { | ||||
|     #[track_caller] | ||||
|     fn to_refund_failed_response(self) -> error_stack::Report<errors::ApiErrorResponse>; | ||||
|     fn to_refund_failed_response(self) -> error_stack::Result<T, errors::ApiErrorResponse>; | ||||
|     #[track_caller] | ||||
|     fn to_payment_failed_response(self) -> error_stack::Report<errors::ApiErrorResponse>; | ||||
|     fn to_payment_failed_response(self) -> error_stack::Result<T, errors::ApiErrorResponse>; | ||||
|     #[track_caller] | ||||
|     fn to_verify_failed_response(self) -> error_stack::Report<errors::ApiErrorResponse>; | ||||
|     fn to_verify_failed_response(self) -> error_stack::Result<T, errors::ApiErrorResponse>; | ||||
|     #[track_caller] | ||||
|     fn to_dispute_failed_response(self) -> error_stack::Report<errors::ApiErrorResponse>; | ||||
|     fn to_dispute_failed_response(self) -> error_stack::Result<T, errors::ApiErrorResponse>; | ||||
| } | ||||
|  | ||||
| impl ConnectorErrorExt for error_stack::Report<errors::ConnectorError> { | ||||
|     fn to_refund_failed_response(self) -> error_stack::Report<errors::ApiErrorResponse> { | ||||
|         let data = match self.current_context() { | ||||
|             errors::ConnectorError::ProcessingStepFailed(Some(bytes)) => { | ||||
|                 let response_str = std::str::from_utf8(bytes); | ||||
|                 match response_str { | ||||
|                     Ok(s) => serde_json::from_str(s) | ||||
|                         .map_err( | ||||
|                             |error| logger::error!(%error,"Failed to convert response to JSON"), | ||||
|                         ) | ||||
|                         .ok(), | ||||
|                     Err(error) => { | ||||
|                         logger::error!(%error,"Failed to convert response to UTF8 string"); | ||||
|                         None | ||||
| impl<T> ConnectorErrorExt<T> for error_stack::Result<T, errors::ConnectorError> { | ||||
|     fn to_refund_failed_response(self) -> error_stack::Result<T, errors::ApiErrorResponse> { | ||||
|         self.map_err(|err| { | ||||
|             let data = match err.current_context() { | ||||
|                 errors::ConnectorError::ProcessingStepFailed(Some(bytes)) => { | ||||
|                     let response_str = std::str::from_utf8(bytes); | ||||
|                     match response_str { | ||||
|                         Ok(s) => serde_json::from_str(s) | ||||
|                             .map_err( | ||||
|                                 |error| logger::error!(%error,"Failed to convert response to JSON"), | ||||
|                             ) | ||||
|                             .ok(), | ||||
|                         Err(error) => { | ||||
|                             logger::error!(%error,"Failed to convert response to UTF8 string"); | ||||
|                             None | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             _ => None, | ||||
|         }; | ||||
|         self.change_context(errors::ApiErrorResponse::RefundFailed { data }) | ||||
|                 _ => None, | ||||
|             }; | ||||
|             err.change_context(errors::ApiErrorResponse::RefundFailed { data }) | ||||
|         }) | ||||
|     } | ||||
|  | ||||
|     fn to_payment_failed_response(self) -> error_stack::Report<errors::ApiErrorResponse> { | ||||
|         let error = match self.current_context() { | ||||
|             errors::ConnectorError::ProcessingStepFailed(Some(bytes)) => { | ||||
|                 let response_str = std::str::from_utf8(bytes); | ||||
|                 let data = match response_str { | ||||
|                     Ok(s) => serde_json::from_str(s) | ||||
|                         .map_err( | ||||
|                             |error| logger::error!(%error,"Failed to convert response to JSON"), | ||||
|                         ) | ||||
|                         .ok(), | ||||
|                     Err(error) => { | ||||
|                         logger::error!(%error,"Failed to convert response to UTF8 string"); | ||||
|                         None | ||||
|     fn to_payment_failed_response(self) -> error_stack::Result<T, errors::ApiErrorResponse> { | ||||
|         self.map_err(|err| { | ||||
|             let error = match err.current_context() { | ||||
|                 errors::ConnectorError::ProcessingStepFailed(Some(bytes)) => { | ||||
|                     let response_str = std::str::from_utf8(bytes); | ||||
|                     let data = match response_str { | ||||
|                         Ok(s) => serde_json::from_str(s) | ||||
|                             .map_err( | ||||
|                                 |error| logger::error!(%error,"Failed to convert response to JSON"), | ||||
|                             ) | ||||
|                             .ok(), | ||||
|                         Err(error) => { | ||||
|                             logger::error!(%error,"Failed to convert response to UTF8 string"); | ||||
|                             None | ||||
|                         } | ||||
|                     }; | ||||
|                     errors::ApiErrorResponse::PaymentAuthorizationFailed { data } | ||||
|                 } | ||||
|                 errors::ConnectorError::MissingRequiredField { field_name } => { | ||||
|                     errors::ApiErrorResponse::MissingRequiredField { field_name } | ||||
|                 } | ||||
|                 errors::ConnectorError::MissingRequiredFields { field_names } => { | ||||
|                     errors::ApiErrorResponse::MissingRequiredFields { field_names: field_names.to_vec() } | ||||
|                 } | ||||
|                 errors::ConnectorError::NotImplemented(reason) => { | ||||
|                     errors::ApiErrorResponse::NotImplemented { | ||||
|                         message: errors::api_error_response::NotImplementedMessage::Reason( | ||||
|                             reason.to_string(), | ||||
|                         ), | ||||
|                     } | ||||
|                 }; | ||||
|                 errors::ApiErrorResponse::PaymentAuthorizationFailed { data } | ||||
|             } | ||||
|             errors::ConnectorError::MissingRequiredField { field_name } => { | ||||
|                 errors::ApiErrorResponse::MissingRequiredField { field_name } | ||||
|             } | ||||
|             errors::ConnectorError::MissingRequiredFields { field_names } => { | ||||
|                 errors::ApiErrorResponse::MissingRequiredFields { field_names: field_names.to_vec() } | ||||
|             } | ||||
|             errors::ConnectorError::NotImplemented(reason) => { | ||||
|                 errors::ApiErrorResponse::NotImplemented { | ||||
|                     message: errors::api_error_response::NotImplementedMessage::Reason( | ||||
|                         reason.to_string(), | ||||
|                     ), | ||||
|                 } | ||||
|             } | ||||
|             errors::ConnectorError::MismatchedPaymentData => { | ||||
|                 errors::ApiErrorResponse::InvalidDataValue { | ||||
|                     field_name: | ||||
|                         "payment_method_data, payment_method_type and payment_experience does not match", | ||||
|                 errors::ConnectorError::MismatchedPaymentData => { | ||||
|                     errors::ApiErrorResponse::InvalidDataValue { | ||||
|                         field_name: | ||||
|                             "payment_method_data, payment_method_type and payment_experience does not match", | ||||
|                     } | ||||
|                 }, | ||||
|                 errors::ConnectorError::NotSupported { message, connector, payment_experience } => { | ||||
|                     errors::ApiErrorResponse::NotSupported { message: format!("{message} is not supported by {connector} through payment experience {payment_experience}") } | ||||
|                 }, | ||||
|                 errors::ConnectorError::FlowNotSupported{ flow, connector } => { | ||||
|                     errors::ApiErrorResponse::FlowNotSupported { flow: flow.to_owned(), connector: connector.to_owned() } | ||||
|                 } | ||||
|             }, | ||||
|             errors::ConnectorError::NotSupported { message, connector, payment_experience } => { | ||||
|                 errors::ApiErrorResponse::NotSupported { message: format!("{message} is not supported by {connector} through payment experience {payment_experience}") } | ||||
|             }, | ||||
|             errors::ConnectorError::FlowNotSupported{ flow, connector } => { | ||||
|                 errors::ApiErrorResponse::FlowNotSupported { flow: flow.to_owned(), connector: connector.to_owned() } | ||||
|             } | ||||
|             _ => errors::ApiErrorResponse::InternalServerError, | ||||
|         }; | ||||
|         self.change_context(error) | ||||
|                 _ => errors::ApiErrorResponse::InternalServerError, | ||||
|             }; | ||||
|             err.change_context(error) | ||||
|         }) | ||||
|     } | ||||
|  | ||||
|     fn to_verify_failed_response(self) -> error_stack::Report<errors::ApiErrorResponse> { | ||||
|         let error = self.current_context(); | ||||
|         let data = match error { | ||||
|             errors::ConnectorError::ProcessingStepFailed(Some(bytes)) => { | ||||
|                 let response_str = std::str::from_utf8(bytes); | ||||
|                 let error_response = match response_str { | ||||
|                     Ok(s) => serde_json::from_str(s) | ||||
|                         .map_err(|err| logger::error!(%err, "Failed to convert response to JSON")) | ||||
|                         .ok(), | ||||
|                     Err(err) => { | ||||
|                         logger::error!(%err, "Failed to convert response to UTF8 string"); | ||||
|                         None | ||||
|     fn to_verify_failed_response(self) -> error_stack::Result<T, errors::ApiErrorResponse> { | ||||
|         self.map_err(|err| { | ||||
|             let error = err.current_context(); | ||||
|             let data = match error { | ||||
|                 errors::ConnectorError::ProcessingStepFailed(Some(bytes)) => { | ||||
|                     let response_str = std::str::from_utf8(bytes); | ||||
|                     let error_response = match response_str { | ||||
|                         Ok(s) => serde_json::from_str(s) | ||||
|                             .map_err( | ||||
|                                 |err| logger::error!(%err, "Failed to convert response to JSON"), | ||||
|                             ) | ||||
|                             .ok(), | ||||
|                         Err(err) => { | ||||
|                             logger::error!(%err, "Failed to convert response to UTF8 string"); | ||||
|                             None | ||||
|                         } | ||||
|                     }; | ||||
|                     errors::ApiErrorResponse::PaymentAuthorizationFailed { | ||||
|                         data: error_response, | ||||
|                     } | ||||
|                 }; | ||||
|                 errors::ApiErrorResponse::PaymentAuthorizationFailed { | ||||
|                     data: error_response, | ||||
|                 } | ||||
|             } | ||||
|             errors::ConnectorError::MissingRequiredField { field_name } => { | ||||
|                 errors::ApiErrorResponse::MissingRequiredField { field_name } | ||||
|             } | ||||
|             _ => { | ||||
|                 logger::error!(%error,"Verify flow failed"); | ||||
|                 errors::ApiErrorResponse::PaymentAuthorizationFailed { data: None } | ||||
|             } | ||||
|         }; | ||||
|         self.change_context(data) | ||||
|                 errors::ConnectorError::MissingRequiredField { field_name } => { | ||||
|                     errors::ApiErrorResponse::MissingRequiredField { field_name } | ||||
|                 } | ||||
|                 _ => { | ||||
|                     logger::error!(%error,"Verify flow failed"); | ||||
|                     errors::ApiErrorResponse::PaymentAuthorizationFailed { data: None } | ||||
|                 } | ||||
|             }; | ||||
|             err.change_context(data) | ||||
|         }) | ||||
|     } | ||||
|  | ||||
|     fn to_dispute_failed_response(self) -> error_stack::Report<errors::ApiErrorResponse> { | ||||
|         let error = match self.current_context() { | ||||
|             errors::ConnectorError::ProcessingStepFailed(Some(bytes)) => { | ||||
|                 let response_str = std::str::from_utf8(bytes); | ||||
|                 let data = match response_str { | ||||
|                     Ok(s) => serde_json::from_str(s) | ||||
|                         .map_err( | ||||
|                             |error| logger::error!(%error,"Failed to convert response to JSON"), | ||||
|                         ) | ||||
|                         .ok(), | ||||
|                     Err(error) => { | ||||
|                         logger::error!(%error,"Failed to convert response to UTF8 string"); | ||||
|                         None | ||||
|                     } | ||||
|                 }; | ||||
|                 errors::ApiErrorResponse::DisputeFailed { data } | ||||
|             } | ||||
|             errors::ConnectorError::MissingRequiredField { field_name } => { | ||||
|                 errors::ApiErrorResponse::MissingRequiredField { field_name } | ||||
|             } | ||||
|             errors::ConnectorError::MissingRequiredFields { field_names } => { | ||||
|                 errors::ApiErrorResponse::MissingRequiredFields { | ||||
|                     field_names: field_names.to_vec(), | ||||
|     fn to_dispute_failed_response(self) -> error_stack::Result<T, errors::ApiErrorResponse> { | ||||
|         self.map_err(|err| { | ||||
|             let error = match err.current_context() { | ||||
|                 errors::ConnectorError::ProcessingStepFailed(Some(bytes)) => { | ||||
|                     let response_str = std::str::from_utf8(bytes); | ||||
|                     let data = match response_str { | ||||
|                         Ok(s) => serde_json::from_str(s) | ||||
|                             .map_err( | ||||
|                                 |error| logger::error!(%error,"Failed to convert response to JSON"), | ||||
|                             ) | ||||
|                             .ok(), | ||||
|                         Err(error) => { | ||||
|                             logger::error!(%error,"Failed to convert response to UTF8 string"); | ||||
|                             None | ||||
|                         } | ||||
|                     }; | ||||
|                     errors::ApiErrorResponse::DisputeFailed { data } | ||||
|                 } | ||||
|             } | ||||
|             _ => errors::ApiErrorResponse::InternalServerError, | ||||
|         }; | ||||
|         self.change_context(error) | ||||
|                 errors::ConnectorError::MissingRequiredField { field_name } => { | ||||
|                     errors::ApiErrorResponse::MissingRequiredField { field_name } | ||||
|                 } | ||||
|                 errors::ConnectorError::MissingRequiredFields { field_names } => { | ||||
|                     errors::ApiErrorResponse::MissingRequiredFields { | ||||
|                         field_names: field_names.to_vec(), | ||||
|                     } | ||||
|                 } | ||||
|                 _ => errors::ApiErrorResponse::InternalServerError, | ||||
|             }; | ||||
|             err.change_context(error) | ||||
|         }) | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| @ -48,7 +48,7 @@ pub async fn create_connector_customer<F: Clone, T: Clone>( | ||||
|         payments::CallConnectorAction::Trigger, | ||||
|     ) | ||||
|     .await | ||||
|     .map_err(|error| error.to_payment_failed_response())?; | ||||
|     .to_payment_failed_response()?; | ||||
|  | ||||
|     metrics::CONNECTOR_CUSTOMER_CREATE.add( | ||||
|         &metrics::CONTEXT, | ||||
|  | ||||
| @ -140,7 +140,7 @@ impl types::PaymentsAuthorizeRouterData { | ||||
|                 connector_integration | ||||
|                     .execute_pretasks(self, state) | ||||
|                     .await | ||||
|                     .map_err(|error| error.to_payment_failed_response())?; | ||||
|                     .to_payment_failed_response()?; | ||||
|  | ||||
|                 metrics::EXECUTE_PRETASK_COUNT.add( | ||||
|                     &metrics::CONTEXT, | ||||
| @ -165,7 +165,7 @@ impl types::PaymentsAuthorizeRouterData { | ||||
|                         call_connector_action, | ||||
|                     ) | ||||
|                     .await | ||||
|                     .map_err(|error| error.to_payment_failed_response())?; | ||||
|                     .to_payment_failed_response()?; | ||||
|  | ||||
|                     let pm_id = tokenization::save_payment_method( | ||||
|                         state, | ||||
| @ -266,7 +266,7 @@ pub async fn authorize_preprocessing_steps<F: Clone>( | ||||
|             payments::CallConnectorAction::Trigger, | ||||
|         ) | ||||
|         .await | ||||
|         .map_err(|error| error.to_payment_failed_response())?; | ||||
|         .to_payment_failed_response()?; | ||||
|  | ||||
|         metrics::PREPROCESSING_STEPS_COUNT.add( | ||||
|             &metrics::CONTEXT, | ||||
|  | ||||
| @ -96,7 +96,7 @@ impl types::PaymentsCancelRouterData { | ||||
|             call_connector_action, | ||||
|         ) | ||||
|         .await | ||||
|         .map_err(|error| error.to_payment_failed_response())?; | ||||
|         .to_payment_failed_response()?; | ||||
|  | ||||
|         Ok(resp) | ||||
|     } | ||||
|  | ||||
| @ -89,7 +89,7 @@ impl types::PaymentsCaptureRouterData { | ||||
|             call_connector_action, | ||||
|         ) | ||||
|         .await | ||||
|         .map_err(|error| error.to_payment_failed_response())?; | ||||
|         .to_payment_failed_response()?; | ||||
|  | ||||
|         Ok(resp) | ||||
|     } | ||||
|  | ||||
| @ -104,7 +104,7 @@ impl types::PaymentsCompleteAuthorizeRouterData { | ||||
|             call_connector_action, | ||||
|         ) | ||||
|         .await | ||||
|         .map_err(|error| error.to_payment_failed_response())?; | ||||
|         .to_payment_failed_response()?; | ||||
|  | ||||
|         Ok(resp) | ||||
|     } | ||||
|  | ||||
| @ -89,7 +89,7 @@ impl types::PaymentsSyncRouterData { | ||||
|             call_connector_action, | ||||
|         ) | ||||
|         .await | ||||
|         .map_err(|error| error.to_payment_failed_response())?; | ||||
|         .to_payment_failed_response()?; | ||||
|  | ||||
|         Ok(resp) | ||||
|     } | ||||
|  | ||||
| @ -306,7 +306,7 @@ impl types::PaymentsSessionRouterData { | ||||
|                     call_connector_action, | ||||
|                 ) | ||||
|                 .await | ||||
|                 .map_err(|error| error.to_payment_failed_response())?; | ||||
|                 .to_payment_failed_response()?; | ||||
|  | ||||
|                 Ok(resp) | ||||
|             } | ||||
|  | ||||
| @ -133,7 +133,7 @@ impl types::VerifyRouterData { | ||||
|                     call_connector_action, | ||||
|                 ) | ||||
|                 .await | ||||
|                 .map_err(|err| err.to_verify_failed_response())?; | ||||
|                 .to_verify_failed_response()?; | ||||
|  | ||||
|                 let pm_id = tokenization::save_payment_method( | ||||
|                     state, | ||||
|  | ||||
| @ -229,7 +229,7 @@ pub async fn add_payment_method_token<F: Clone, T: Clone>( | ||||
|                 payments::CallConnectorAction::Trigger, | ||||
|             ) | ||||
|             .await | ||||
|             .map_err(|error| error.to_payment_failed_response())?; | ||||
|             .to_payment_failed_response()?; | ||||
|  | ||||
|             metrics::CONNECTOR_PAYMENT_METHOD_TOKENIZATION.add( | ||||
|                 &metrics::CONTEXT, | ||||
|  | ||||
| @ -191,7 +191,7 @@ pub async fn trigger_refund_to_gateway( | ||||
|             payments::CallConnectorAction::Trigger, | ||||
|         ) | ||||
|         .await | ||||
|         .map_err(|error| error.to_refund_failed_response())? | ||||
|         .to_refund_failed_response()? | ||||
|     } else { | ||||
|         router_data | ||||
|     }; | ||||
| @ -410,7 +410,7 @@ pub async fn sync_refund_with_gateway( | ||||
|             payments::CallConnectorAction::Trigger, | ||||
|         ) | ||||
|         .await | ||||
|         .map_err(|error| error.to_refund_failed_response())? | ||||
|         .to_refund_failed_response()? | ||||
|     } else { | ||||
|         router_data | ||||
|     }; | ||||
|  | ||||
		Reference in New Issue
	
	Block a user