mirror of
				https://github.com/juspay/hyperswitch.git
				synced 2025-10-31 01:57:45 +08:00 
			
		
		
		
	feat(connector): [CYBERSOURCE] Refactor cybersource (#3215)
Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
This commit is contained in:
		| @ -446,6 +446,27 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme | |||||||
|     ) -> CustomResult<types::ErrorResponse, errors::ConnectorError> { |     ) -> CustomResult<types::ErrorResponse, errors::ConnectorError> { | ||||||
|         self.build_error_response(res) |         self.build_error_response(res) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     fn get_5xx_error_response( | ||||||
|  |         &self, | ||||||
|  |         res: types::Response, | ||||||
|  |     ) -> CustomResult<types::ErrorResponse, errors::ConnectorError> { | ||||||
|  |         let response: cybersource::CybersourceServerErrorResponse = res | ||||||
|  |             .response | ||||||
|  |             .parse_struct("CybersourceServerErrorResponse") | ||||||
|  |             .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; | ||||||
|  |  | ||||||
|  |         Ok(types::ErrorResponse { | ||||||
|  |             status_code: res.status_code, | ||||||
|  |             reason: response.status.clone(), | ||||||
|  |             code: response.status.unwrap_or(consts::NO_ERROR_CODE.to_string()), | ||||||
|  |             message: response | ||||||
|  |                 .message | ||||||
|  |                 .unwrap_or(consts::NO_ERROR_MESSAGE.to_string()), | ||||||
|  |             attempt_status: None, | ||||||
|  |             connector_transaction_id: None, | ||||||
|  |         }) | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| impl ConnectorIntegration<api::PSync, types::PaymentsSyncData, types::PaymentsResponseData> | impl ConnectorIntegration<api::PSync, types::PaymentsSyncData, types::PaymentsResponseData> | ||||||
| @ -606,6 +627,33 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P | |||||||
|     ) -> CustomResult<types::ErrorResponse, errors::ConnectorError> { |     ) -> CustomResult<types::ErrorResponse, errors::ConnectorError> { | ||||||
|         self.build_error_response(res) |         self.build_error_response(res) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     fn get_5xx_error_response( | ||||||
|  |         &self, | ||||||
|  |         res: types::Response, | ||||||
|  |     ) -> CustomResult<types::ErrorResponse, errors::ConnectorError> { | ||||||
|  |         let response: cybersource::CybersourceServerErrorResponse = res | ||||||
|  |             .response | ||||||
|  |             .parse_struct("CybersourceServerErrorResponse") | ||||||
|  |             .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; | ||||||
|  |         let attempt_status = match response.reason { | ||||||
|  |             Some(reason) => match reason { | ||||||
|  |                 transformers::Reason::SystemError => Some(enums::AttemptStatus::Failure), | ||||||
|  |                 transformers::Reason::ServerTimeout | transformers::Reason::ServiceTimeout => None, | ||||||
|  |             }, | ||||||
|  |             None => None, | ||||||
|  |         }; | ||||||
|  |         Ok(types::ErrorResponse { | ||||||
|  |             status_code: res.status_code, | ||||||
|  |             reason: response.status.clone(), | ||||||
|  |             code: response.status.unwrap_or(consts::NO_ERROR_CODE.to_string()), | ||||||
|  |             message: response | ||||||
|  |                 .message | ||||||
|  |                 .unwrap_or(consts::NO_ERROR_MESSAGE.to_string()), | ||||||
|  |             attempt_status, | ||||||
|  |             connector_transaction_id: None, | ||||||
|  |         }) | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsResponseData> | impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsResponseData> | ||||||
| @ -626,9 +674,8 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR | |||||||
|     ) -> CustomResult<String, errors::ConnectorError> { |     ) -> CustomResult<String, errors::ConnectorError> { | ||||||
|         let connector_payment_id = req.request.connector_transaction_id.clone(); |         let connector_payment_id = req.request.connector_transaction_id.clone(); | ||||||
|         Ok(format!( |         Ok(format!( | ||||||
|             "{}pts/v2/payments/{}/voids", |             "{}pts/v2/payments/{connector_payment_id}/reversals", | ||||||
|             self.base_url(connectors), |             self.base_url(connectors) | ||||||
|             connector_payment_id |  | ||||||
|         )) |         )) | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @ -638,10 +685,26 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR | |||||||
|  |  | ||||||
|     fn get_request_body( |     fn get_request_body( | ||||||
|         &self, |         &self, | ||||||
|         _req: &types::PaymentsCancelRouterData, |         req: &types::PaymentsCancelRouterData, | ||||||
|         _connectors: &settings::Connectors, |         _connectors: &settings::Connectors, | ||||||
|     ) -> CustomResult<RequestContent, errors::ConnectorError> { |     ) -> CustomResult<RequestContent, errors::ConnectorError> { | ||||||
|         Ok(RequestContent::Json(Box::new(serde_json::json!({})))) |         let connector_router_data = cybersource::CybersourceRouterData::try_from(( | ||||||
|  |             &self.get_currency_unit(), | ||||||
|  |             req.request | ||||||
|  |                 .currency | ||||||
|  |                 .ok_or(errors::ConnectorError::MissingRequiredField { | ||||||
|  |                     field_name: "Currency", | ||||||
|  |                 })?, | ||||||
|  |             req.request | ||||||
|  |                 .amount | ||||||
|  |                 .ok_or(errors::ConnectorError::MissingRequiredField { | ||||||
|  |                     field_name: "Amount", | ||||||
|  |                 })?, | ||||||
|  |             req, | ||||||
|  |         ))?; | ||||||
|  |         let connector_req = cybersource::CybersourceVoidRequest::try_from(&connector_router_data)?; | ||||||
|  |  | ||||||
|  |         Ok(RequestContent::Json(Box::new(connector_req))) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn build_request( |     fn build_request( | ||||||
| @ -682,6 +745,27 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR | |||||||
|     ) -> CustomResult<types::ErrorResponse, errors::ConnectorError> { |     ) -> CustomResult<types::ErrorResponse, errors::ConnectorError> { | ||||||
|         self.build_error_response(res) |         self.build_error_response(res) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     fn get_5xx_error_response( | ||||||
|  |         &self, | ||||||
|  |         res: types::Response, | ||||||
|  |     ) -> CustomResult<types::ErrorResponse, errors::ConnectorError> { | ||||||
|  |         let response: cybersource::CybersourceServerErrorResponse = res | ||||||
|  |             .response | ||||||
|  |             .parse_struct("CybersourceServerErrorResponse") | ||||||
|  |             .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; | ||||||
|  |  | ||||||
|  |         Ok(types::ErrorResponse { | ||||||
|  |             status_code: res.status_code, | ||||||
|  |             reason: response.status.clone(), | ||||||
|  |             code: response.status.unwrap_or(consts::NO_ERROR_CODE.to_string()), | ||||||
|  |             message: response | ||||||
|  |                 .message | ||||||
|  |                 .unwrap_or(consts::NO_ERROR_MESSAGE.to_string()), | ||||||
|  |             attempt_status: None, | ||||||
|  |             connector_transaction_id: None, | ||||||
|  |         }) | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| impl api::Refund for Cybersource {} | impl api::Refund for Cybersource {} | ||||||
|  | |||||||
| @ -1,8 +1,11 @@ | |||||||
|  | use std::collections::HashMap; | ||||||
|  |  | ||||||
| use api_models::payments; | use api_models::payments; | ||||||
| use base64::Engine; | use base64::Engine; | ||||||
| use common_utils::pii; | use common_utils::pii; | ||||||
| use masking::{PeekInterface, Secret}; | use masking::{PeekInterface, Secret}; | ||||||
| use serde::{Deserialize, Serialize}; | use serde::{Deserialize, Serialize}; | ||||||
|  | use serde_json::Value; | ||||||
|  |  | ||||||
| use crate::{ | use crate::{ | ||||||
|     connector::utils::{ |     connector::utils::{ | ||||||
| @ -134,6 +137,8 @@ pub struct CybersourcePaymentsRequest { | |||||||
|     payment_information: PaymentInformation, |     payment_information: PaymentInformation, | ||||||
|     order_information: OrderInformationWithBill, |     order_information: OrderInformationWithBill, | ||||||
|     client_reference_information: ClientReferenceInformation, |     client_reference_information: ClientReferenceInformation, | ||||||
|  |     #[serde(skip_serializing_if = "Option::is_none")] | ||||||
|  |     merchant_defined_information: Option<Vec<MerchantDefinedInformation>>, | ||||||
| } | } | ||||||
|  |  | ||||||
| #[derive(Debug, Serialize)] | #[derive(Debug, Serialize)] | ||||||
| @ -148,6 +153,13 @@ pub struct ProcessingInformation { | |||||||
|     payment_solution: Option<String>, |     payment_solution: Option<String>, | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #[derive(Debug, Serialize)] | ||||||
|  | #[serde(rename_all = "camelCase")] | ||||||
|  | pub struct MerchantDefinedInformation { | ||||||
|  |     key: u8, | ||||||
|  |     value: String, | ||||||
|  | } | ||||||
|  |  | ||||||
| #[derive(Debug, Serialize)] | #[derive(Debug, Serialize)] | ||||||
| #[serde(rename_all = "SCREAMING_SNAKE_CASE")] | #[serde(rename_all = "SCREAMING_SNAKE_CASE")] | ||||||
| pub enum CybersourceActionsList { | pub enum CybersourceActionsList { | ||||||
| @ -218,6 +230,19 @@ pub struct TokenizedCard { | |||||||
|     transaction_type: TransactionType, |     transaction_type: TransactionType, | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #[derive(Debug, Serialize)] | ||||||
|  | #[serde(rename_all = "camelCase")] | ||||||
|  | pub struct ApplePayTokenizedCard { | ||||||
|  |     transaction_type: TransactionType, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #[derive(Debug, Serialize)] | ||||||
|  | #[serde(rename_all = "camelCase")] | ||||||
|  | pub struct ApplePayTokenPaymentInformation { | ||||||
|  |     fluid_data: FluidData, | ||||||
|  |     tokenized_card: ApplePayTokenizedCard, | ||||||
|  | } | ||||||
|  |  | ||||||
| #[derive(Debug, Serialize)] | #[derive(Debug, Serialize)] | ||||||
| #[serde(rename_all = "camelCase")] | #[serde(rename_all = "camelCase")] | ||||||
| pub struct ApplePayPaymentInformation { | pub struct ApplePayPaymentInformation { | ||||||
| @ -242,6 +267,7 @@ pub enum PaymentInformation { | |||||||
|     Cards(CardPaymentInformation), |     Cards(CardPaymentInformation), | ||||||
|     GooglePay(GooglePayPaymentInformation), |     GooglePay(GooglePayPaymentInformation), | ||||||
|     ApplePay(ApplePayPaymentInformation), |     ApplePay(ApplePayPaymentInformation), | ||||||
|  |     ApplePayToken(ApplePayTokenPaymentInformation), | ||||||
| } | } | ||||||
|  |  | ||||||
| #[derive(Debug, Clone, Serialize, Deserialize)] | #[derive(Debug, Clone, Serialize, Deserialize)] | ||||||
| @ -441,6 +467,23 @@ fn build_bill_to( | |||||||
|     }) |     }) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | impl ForeignFrom<Value> for Vec<MerchantDefinedInformation> { | ||||||
|  |     fn foreign_from(metadata: Value) -> Self { | ||||||
|  |         let hashmap: HashMap<String, Value> = | ||||||
|  |             serde_json::from_str(&metadata.to_string()).unwrap_or(HashMap::new()); | ||||||
|  |         let mut vector: Self = Self::new(); | ||||||
|  |         let mut iter = 1; | ||||||
|  |         for (key, value) in hashmap { | ||||||
|  |             vector.push(MerchantDefinedInformation { | ||||||
|  |                 key: iter, | ||||||
|  |                 value: format!("{key}={value}"), | ||||||
|  |             }); | ||||||
|  |             iter += 1; | ||||||
|  |         } | ||||||
|  |         vector | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| impl | impl | ||||||
|     TryFrom<( |     TryFrom<( | ||||||
|         &CybersourceRouterData<&types::PaymentsAuthorizeRouterData>, |         &CybersourceRouterData<&types::PaymentsAuthorizeRouterData>, | ||||||
| @ -491,15 +534,19 @@ impl | |||||||
|             card, |             card, | ||||||
|             instrument_identifier, |             instrument_identifier, | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
|         let processing_information = ProcessingInformation::from((item, None)); |         let processing_information = ProcessingInformation::from((item, None)); | ||||||
|         let client_reference_information = ClientReferenceInformation::from(item); |         let client_reference_information = ClientReferenceInformation::from(item); | ||||||
|  |         let merchant_defined_information = | ||||||
|  |             item.router_data.request.metadata.clone().map(|metadata| { | ||||||
|  |                 Vec::<MerchantDefinedInformation>::foreign_from(metadata.peek().to_owned()) | ||||||
|  |             }); | ||||||
|  |  | ||||||
|         Ok(Self { |         Ok(Self { | ||||||
|             processing_information, |             processing_information, | ||||||
|             payment_information, |             payment_information, | ||||||
|             order_information, |             order_information, | ||||||
|             client_reference_information, |             client_reference_information, | ||||||
|  |             merchant_defined_information, | ||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @ -525,7 +572,6 @@ impl | |||||||
|         let client_reference_information = ClientReferenceInformation::from(item); |         let client_reference_information = ClientReferenceInformation::from(item); | ||||||
|         let expiration_month = apple_pay_data.get_expiry_month()?; |         let expiration_month = apple_pay_data.get_expiry_month()?; | ||||||
|         let expiration_year = apple_pay_data.get_four_digit_expiry_year()?; |         let expiration_year = apple_pay_data.get_four_digit_expiry_year()?; | ||||||
|  |  | ||||||
|         let payment_information = PaymentInformation::ApplePay(ApplePayPaymentInformation { |         let payment_information = PaymentInformation::ApplePay(ApplePayPaymentInformation { | ||||||
|             tokenized_card: TokenizedCard { |             tokenized_card: TokenizedCard { | ||||||
|                 number: apple_pay_data.application_primary_account_number, |                 number: apple_pay_data.application_primary_account_number, | ||||||
| @ -535,12 +581,17 @@ impl | |||||||
|                 expiration_month, |                 expiration_month, | ||||||
|             }, |             }, | ||||||
|         }); |         }); | ||||||
|  |         let merchant_defined_information = | ||||||
|  |             item.router_data.request.metadata.clone().map(|metadata| { | ||||||
|  |                 Vec::<MerchantDefinedInformation>::foreign_from(metadata.peek().to_owned()) | ||||||
|  |             }); | ||||||
|  |  | ||||||
|         Ok(Self { |         Ok(Self { | ||||||
|             processing_information, |             processing_information, | ||||||
|             payment_information, |             payment_information, | ||||||
|             order_information, |             order_information, | ||||||
|             client_reference_information, |             client_reference_information, | ||||||
|  |             merchant_defined_information, | ||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @ -569,16 +620,20 @@ impl | |||||||
|                 ), |                 ), | ||||||
|             }, |             }, | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
|         let processing_information = |         let processing_information = | ||||||
|             ProcessingInformation::from((item, Some(PaymentSolution::GooglePay))); |             ProcessingInformation::from((item, Some(PaymentSolution::GooglePay))); | ||||||
|         let client_reference_information = ClientReferenceInformation::from(item); |         let client_reference_information = ClientReferenceInformation::from(item); | ||||||
|  |         let merchant_defined_information = | ||||||
|  |             item.router_data.request.metadata.clone().map(|metadata| { | ||||||
|  |                 Vec::<MerchantDefinedInformation>::foreign_from(metadata.peek().to_owned()) | ||||||
|  |             }); | ||||||
|  |  | ||||||
|         Ok(Self { |         Ok(Self { | ||||||
|             processing_information, |             processing_information, | ||||||
|             payment_information, |             payment_information, | ||||||
|             order_information, |             order_information, | ||||||
|             client_reference_information, |             client_reference_information, | ||||||
|  |             merchant_defined_information, | ||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @ -593,15 +648,51 @@ impl TryFrom<&CybersourceRouterData<&types::PaymentsAuthorizeRouterData>> | |||||||
|         match item.router_data.request.payment_method_data.clone() { |         match item.router_data.request.payment_method_data.clone() { | ||||||
|             payments::PaymentMethodData::Card(ccard) => Self::try_from((item, ccard)), |             payments::PaymentMethodData::Card(ccard) => Self::try_from((item, ccard)), | ||||||
|             payments::PaymentMethodData::Wallet(wallet_data) => match wallet_data { |             payments::PaymentMethodData::Wallet(wallet_data) => match wallet_data { | ||||||
|                 payments::WalletData::ApplePay(_) => { |                 payments::WalletData::ApplePay(apple_pay_data) => { | ||||||
|                     let payment_method_token = item.router_data.get_payment_method_token()?; |                     match item.router_data.payment_method_token.clone() { | ||||||
|                     match payment_method_token { |                         Some(payment_method_token) => match payment_method_token { | ||||||
|                             types::PaymentMethodToken::ApplePayDecrypt(decrypt_data) => { |                             types::PaymentMethodToken::ApplePayDecrypt(decrypt_data) => { | ||||||
|                                 Self::try_from((item, decrypt_data)) |                                 Self::try_from((item, decrypt_data)) | ||||||
|                             } |                             } | ||||||
|                             types::PaymentMethodToken::Token(_) => { |                             types::PaymentMethodToken::Token(_) => { | ||||||
|                                 Err(errors::ConnectorError::InvalidWalletToken)? |                                 Err(errors::ConnectorError::InvalidWalletToken)? | ||||||
|                             } |                             } | ||||||
|  |                         }, | ||||||
|  |                         None => { | ||||||
|  |                             let email = item.router_data.request.get_email()?; | ||||||
|  |                             let bill_to = build_bill_to(item.router_data.get_billing()?, email)?; | ||||||
|  |                             let order_information = OrderInformationWithBill::from((item, bill_to)); | ||||||
|  |                             let processing_information = ProcessingInformation::from(( | ||||||
|  |                                 item, | ||||||
|  |                                 Some(PaymentSolution::ApplePay), | ||||||
|  |                             )); | ||||||
|  |                             let client_reference_information = | ||||||
|  |                                 ClientReferenceInformation::from(item); | ||||||
|  |                             let payment_information = PaymentInformation::ApplePayToken( | ||||||
|  |                                 ApplePayTokenPaymentInformation { | ||||||
|  |                                     fluid_data: FluidData { | ||||||
|  |                                         value: Secret::from(apple_pay_data.payment_data), | ||||||
|  |                                     }, | ||||||
|  |                                     tokenized_card: ApplePayTokenizedCard { | ||||||
|  |                                         transaction_type: TransactionType::ApplePay, | ||||||
|  |                                     }, | ||||||
|  |                                 }, | ||||||
|  |                             ); | ||||||
|  |                             let merchant_defined_information = | ||||||
|  |                                 item.router_data.request.metadata.clone().map(|metadata| { | ||||||
|  |                                     Vec::<MerchantDefinedInformation>::foreign_from( | ||||||
|  |                                         metadata.peek().to_owned(), | ||||||
|  |                                     ) | ||||||
|  |                                 }); | ||||||
|  |  | ||||||
|  |                             Ok(Self { | ||||||
|  |                                 processing_information, | ||||||
|  |                                 payment_information, | ||||||
|  |                                 order_information, | ||||||
|  |                                 client_reference_information, | ||||||
|  |                                 merchant_defined_information, | ||||||
|  |                             }) | ||||||
|  |                         } | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 payments::WalletData::GooglePay(google_pay_data) => { |                 payments::WalletData::GooglePay(google_pay_data) => { | ||||||
| @ -737,6 +828,51 @@ impl TryFrom<&CybersourceRouterData<&types::PaymentsIncrementalAuthorizationRout | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #[derive(Debug, Serialize)] | ||||||
|  | #[serde(rename_all = "camelCase")] | ||||||
|  | pub struct CybersourceVoidRequest { | ||||||
|  |     client_reference_information: ClientReferenceInformation, | ||||||
|  |     reversal_information: ReversalInformation, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #[derive(Debug, Serialize)] | ||||||
|  | #[serde(rename_all = "camelCase")] | ||||||
|  | pub struct ReversalInformation { | ||||||
|  |     amount_details: Amount, | ||||||
|  |     reason: String, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | impl TryFrom<&CybersourceRouterData<&types::PaymentsCancelRouterData>> for CybersourceVoidRequest { | ||||||
|  |     type Error = error_stack::Report<errors::ConnectorError>; | ||||||
|  |     fn try_from( | ||||||
|  |         value: &CybersourceRouterData<&types::PaymentsCancelRouterData>, | ||||||
|  |     ) -> Result<Self, Self::Error> { | ||||||
|  |         Ok(Self { | ||||||
|  |             client_reference_information: ClientReferenceInformation { | ||||||
|  |                 code: Some(value.router_data.connector_request_reference_id.clone()), | ||||||
|  |             }, | ||||||
|  |             reversal_information: ReversalInformation { | ||||||
|  |                 amount_details: Amount { | ||||||
|  |                     total_amount: value.amount.to_owned(), | ||||||
|  |                     currency: value.router_data.request.currency.ok_or( | ||||||
|  |                         errors::ConnectorError::MissingRequiredField { | ||||||
|  |                             field_name: "Currency", | ||||||
|  |                         }, | ||||||
|  |                     )?, | ||||||
|  |                 }, | ||||||
|  |                 reason: value | ||||||
|  |                     .router_data | ||||||
|  |                     .request | ||||||
|  |                     .cancellation_reason | ||||||
|  |                     .clone() | ||||||
|  |                     .ok_or(errors::ConnectorError::MissingRequiredField { | ||||||
|  |                         field_name: "Cancellation Reason", | ||||||
|  |                     })?, | ||||||
|  |             }, | ||||||
|  |         }) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| pub struct CybersourceAuthType { | pub struct CybersourceAuthType { | ||||||
|     pub(super) api_key: Secret<String>, |     pub(super) api_key: Secret<String>, | ||||||
|     pub(super) merchant_account: Secret<String>, |     pub(super) merchant_account: Secret<String>, | ||||||
| @ -1079,9 +1215,21 @@ impl<F> | |||||||
|                     ..item.data |                     ..item.data | ||||||
|                 }) |                 }) | ||||||
|             } |             } | ||||||
|             CybersourcePaymentsResponse::ErrorInformation(ref error_response) => { |             CybersourcePaymentsResponse::ErrorInformation(error_response) => Ok(Self { | ||||||
|                 Ok(Self::from((&error_response.clone(), item))) |                 response: Err(types::ErrorResponse { | ||||||
|             } |                     code: consts::NO_ERROR_CODE.to_string(), | ||||||
|  |                     message: error_response | ||||||
|  |                         .error_information | ||||||
|  |                         .message | ||||||
|  |                         .unwrap_or(consts::NO_ERROR_MESSAGE.to_string()), | ||||||
|  |                     reason: error_response.error_information.reason, | ||||||
|  |                     status_code: item.http_code, | ||||||
|  |                     attempt_status: None, | ||||||
|  |                     connector_transaction_id: Some(error_response.id.clone()), | ||||||
|  |                 }), | ||||||
|  |                 status: enums::AttemptStatus::Failure, | ||||||
|  |                 ..item.data | ||||||
|  |             }), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @ -1496,6 +1644,22 @@ pub struct CybersourceStandardErrorResponse { | |||||||
|     pub details: Option<Vec<Details>>, |     pub details: Option<Vec<Details>>, | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #[derive(Debug, Deserialize)] | ||||||
|  | #[serde(rename_all = "camelCase")] | ||||||
|  | pub struct CybersourceServerErrorResponse { | ||||||
|  |     pub status: Option<String>, | ||||||
|  |     pub message: Option<String>, | ||||||
|  |     pub reason: Option<Reason>, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #[derive(Debug, Deserialize)] | ||||||
|  | #[serde(rename_all = "SCREAMING_SNAKE_CASE")] | ||||||
|  | pub enum Reason { | ||||||
|  |     SystemError, | ||||||
|  |     ServerTimeout, | ||||||
|  |     ServiceTimeout, | ||||||
|  | } | ||||||
|  |  | ||||||
| #[derive(Debug, Deserialize)] | #[derive(Debug, Deserialize)] | ||||||
| pub struct CybersourceAuthenticationErrorResponse { | pub struct CybersourceAuthenticationErrorResponse { | ||||||
|     pub response: AuthenticationErrorInformation, |     pub response: AuthenticationErrorInformation, | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 DEEPANSHU BANSAL
					DEEPANSHU BANSAL