diff --git a/crates/common_enums/src/connector_enums.rs b/crates/common_enums/src/connector_enums.rs index 518d89b5e5..9490221d90 100644 --- a/crates/common_enums/src/connector_enums.rs +++ b/crates/common_enums/src/connector_enums.rs @@ -426,7 +426,10 @@ impl Connector { ) } pub fn requires_order_creation_before_payment(self, payment_method: PaymentMethod) -> bool { - matches!((self, payment_method), (Self::Razorpay, PaymentMethod::Upi)) + matches!( + (self, payment_method), + (Self::Razorpay, PaymentMethod::Upi) | (Self::Airwallex, PaymentMethod::Card) + ) } pub fn supports_file_storage_module(self) -> bool { matches!(self, Self::Stripe | Self::Checkout | Self::Worldpayvantiv) @@ -575,10 +578,6 @@ impl Connector { } } - pub fn is_pre_processing_required_before_authorize(self) -> bool { - matches!(self, Self::Airwallex) - } - pub fn get_payment_methods_supporting_extended_authorization(self) -> HashSet { HashSet::from([PaymentMethod::Card]) } diff --git a/crates/hyperswitch_connectors/src/connectors/airwallex.rs b/crates/hyperswitch_connectors/src/connectors/airwallex.rs index 750ebdf84a..7b1e14b035 100644 --- a/crates/hyperswitch_connectors/src/connectors/airwallex.rs +++ b/crates/hyperswitch_connectors/src/connectors/airwallex.rs @@ -19,23 +19,26 @@ use hyperswitch_domain_models::{ router_data::{AccessToken, ErrorResponse, RouterData}, router_flow_types::{ access_token_auth::AccessTokenAuth, - payments::{Authorize, Capture, PSync, PaymentMethodToken, Session, SetupMandate, Void}, + payments::{ + Authorize, Capture, CreateOrder, PSync, PaymentMethodToken, Session, SetupMandate, Void, + }, refunds::{Execute, RSync}, - CompleteAuthorize, PreProcessing, + CompleteAuthorize, }, router_request_types::{ - AccessTokenRequestData, CompleteAuthorizeData, PaymentMethodTokenizationData, - PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, PaymentsPreProcessingData, - PaymentsSessionData, PaymentsSyncData, RefundsData, SetupMandateRequestData, + AccessTokenRequestData, CompleteAuthorizeData, CreateOrderRequestData, + PaymentMethodTokenizationData, PaymentsAuthorizeData, PaymentsCancelData, + PaymentsCaptureData, PaymentsSessionData, PaymentsSyncData, RefundsData, + SetupMandateRequestData, }, router_response_types::{ ConnectorInfo, PaymentMethodDetails, PaymentsResponseData, RefundsResponseData, SupportedPaymentMethods, SupportedPaymentMethodsExt, }, types::{ - PaymentsAuthorizeRouterData, PaymentsCancelRouterData, PaymentsCaptureRouterData, - PaymentsCompleteAuthorizeRouterData, PaymentsPreProcessingRouterData, - PaymentsSyncRouterData, RefundSyncRouterData, RefundsRouterData, SetupMandateRouterData, + CreateOrderRouterData, PaymentsAuthorizeRouterData, PaymentsCancelRouterData, + PaymentsCaptureRouterData, PaymentsCompleteAuthorizeRouterData, PaymentsSyncRouterData, + RefundSyncRouterData, RefundsRouterData, SetupMandateRouterData, }, }; use hyperswitch_interfaces::{ @@ -47,7 +50,7 @@ use hyperswitch_interfaces::{ disputes::DisputePayload, errors, events::connector_api_logs::ConnectorEvent, - types::{self, Response}, + types::{self, CreateOrderType, Response}, webhooks::{IncomingWebhook, IncomingWebhookRequestDetails}, }; use masking::{Mask, PeekInterface}; @@ -58,7 +61,10 @@ use crate::{ connectors::airwallex::transformers::AirwallexAuthorizeResponse, constants::headers, types::{RefreshTokenRouterData, ResponseRouterData}, - utils::{convert_amount, AccessTokenRequestInfo, ForeignTryFrom, RefundsRequestData}, + utils::{ + convert_amount, AccessTokenRequestInfo, ForeignTryFrom, PaymentsAuthorizeRequestData, + RefundsRequestData, + }, }; #[derive(Clone)] @@ -154,8 +160,8 @@ impl ConnectorCommon for Airwallex { impl ConnectorValidation for Airwallex {} impl api::Payment for Airwallex {} -impl api::PaymentsPreProcessing for Airwallex {} impl api::PaymentsCompleteAuthorize for Airwallex {} +impl api::PaymentsCreateOrder for Airwallex {} impl api::MandateSetup for Airwallex {} impl ConnectorIntegration for Airwallex @@ -262,12 +268,10 @@ impl ConnectorIntegration } } -impl ConnectorIntegration - for Airwallex -{ +impl ConnectorIntegration for Airwallex { fn get_headers( &self, - req: &PaymentsPreProcessingRouterData, + req: &CreateOrderRouterData, connectors: &Connectors, ) -> CustomResult)>, errors::ConnectorError> { self.build_headers(req, connectors) @@ -279,7 +283,7 @@ impl ConnectorIntegration CustomResult { Ok(format!( @@ -291,22 +295,13 @@ impl ConnectorIntegration CustomResult { - let amount_in_minor_unit = MinorUnit::new(req.request.amount.ok_or( - errors::ConnectorError::MissingRequiredField { - field_name: "amount", - }, - )?); let amount = convert_amount( self.amount_converter, - amount_in_minor_unit, - req.request - .currency - .ok_or(errors::ConnectorError::MissingRequiredField { - field_name: "currency", - })?, + req.request.minor_amount, + req.request.currency, )?; let connector_router_data = airwallex::AirwallexRouterData::try_from((amount, req))?; let connector_req = airwallex::AirwallexIntentRequest::try_from(&connector_router_data)?; @@ -315,35 +310,29 @@ impl ConnectorIntegration CustomResult, errors::ConnectorError> { Ok(Some( RequestBuilder::new() .method(Method::Post) - .url(&types::PaymentsPreProcessingType::get_url( - self, req, connectors, - )?) + .url(&CreateOrderType::get_url(self, req, connectors)?) .attach_default_headers() - .headers(types::PaymentsPreProcessingType::get_headers( - self, req, connectors, - )?) - .set_body(types::PaymentsPreProcessingType::get_request_body( - self, req, connectors, - )?) + .headers(CreateOrderType::get_headers(self, req, connectors)?) + .set_body(CreateOrderType::get_request_body(self, req, connectors)?) .build(), )) } fn handle_response( &self, - data: &PaymentsPreProcessingRouterData, + data: &CreateOrderRouterData, event_builder: Option<&mut ConnectorEvent>, res: Response, - ) -> CustomResult { - let response: airwallex::AirwallexPaymentsResponse = res + ) -> CustomResult { + let response: airwallex::AirwallexOrderResponse = res .response - .parse_struct("airwallex AirwallexPaymentsResponse") + .parse_struct("airwallex AirwallexOrderResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; event_builder.map(|i| i.set_response_body(&response)); @@ -391,9 +380,7 @@ impl ConnectorIntegration, } -impl TryFrom<&AirwallexRouterData<&types::PaymentsPreProcessingRouterData>> - for AirwallexIntentRequest -{ +impl TryFrom<&AirwallexRouterData<&types::CreateOrderRouterData>> for AirwallexIntentRequest { type Error = error_stack::Report; fn try_from( - item: &AirwallexRouterData<&types::PaymentsPreProcessingRouterData>, + item: &AirwallexRouterData<&types::CreateOrderRouterData>, ) -> Result { let referrer_data = ReferrerData { r_type: "hyperswitch".to_string(), version: "1.0.0".to_string(), }; let amount = item.amount.clone(); - let currency = item.router_data.request.currency.ok_or( - errors::ConnectorError::MissingRequiredField { - field_name: "currency", - }, - )?; + let currency = item.router_data.request.currency; let order = match item.router_data.request.payment_method_data { Some(PaymentMethodData::PayLater(_)) => Some( @@ -137,6 +131,30 @@ impl TryFrom<&AirwallexRouterData<&types::PaymentsPreProcessingRouterData>> } } +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] +pub struct AirwallexOrderResponse { + pub status: AirwallexPaymentStatus, + pub id: String, + pub payment_consent_id: Option>, + pub next_action: Option, +} + +impl TryFrom> + for types::CreateOrderRouterData +{ + type Error = error_stack::Report; + fn try_from( + item: CreateOrderResponseRouterData, + ) -> Result { + Ok(Self { + response: Ok(PaymentsResponseData::PaymentsCreateOrderResponse { + order_id: item.response.id.clone(), + }), + ..item.data + }) + } +} + #[derive(Debug, Serialize)] pub struct AirwallexRouterData { pub amount: StringMajorUnit, diff --git a/crates/hyperswitch_connectors/src/default_implementations.rs b/crates/hyperswitch_connectors/src/default_implementations.rs index 2ea8e3faec..fc6a2ac246 100644 --- a/crates/hyperswitch_connectors/src/default_implementations.rs +++ b/crates/hyperswitch_connectors/src/default_implementations.rs @@ -768,7 +768,6 @@ default_imp_for_create_order!( connectors::Adyen, connectors::Adyenplatform, connectors::Affirm, - connectors::Airwallex, connectors::Amazonpay, connectors::Archipel, connectors::Authipay, @@ -2359,6 +2358,7 @@ default_imp_for_pre_processing_steps!( connectors::Aci, connectors::Adyenplatform, connectors::Affirm, + connectors::Airwallex, connectors::Amazonpay, connectors::Archipel, connectors::Authipay, diff --git a/crates/hyperswitch_domain_models/src/router_request_types.rs b/crates/hyperswitch_domain_models/src/router_request_types.rs index 063868b034..9a6271f6f6 100644 --- a/crates/hyperswitch_domain_models/src/router_request_types.rs +++ b/crates/hyperswitch_domain_models/src/router_request_types.rs @@ -517,6 +517,8 @@ impl TryFrom for PaymentMethodTokenizationData { pub struct CreateOrderRequestData { pub minor_amount: MinorUnit, pub currency: storage_enums::Currency, + pub payment_method_data: Option, + pub order_details: Option>, } impl TryFrom for CreateOrderRequestData { @@ -526,6 +528,8 @@ impl TryFrom for CreateOrderRequestData { Ok(Self { minor_amount: data.minor_amount, currency: data.currency, + payment_method_data: Some(data.payment_method_data), + order_details: data.order_details, }) } } @@ -537,6 +541,8 @@ impl TryFrom for CreateOrderRequestData { Ok(Self { minor_amount: data.minor_amount, currency: data.currency, + payment_method_data: None, + order_details: data.order_details, }) } } diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs index 2f42eb33ad..4059d315a9 100644 --- a/crates/router/src/core/payments.rs +++ b/crates/router/src/core/payments.rs @@ -6655,14 +6655,6 @@ where dyn api::Connector: services::api::ConnectorIntegration, { - if !is_operation_complete_authorize(&operation) - && connector - .connector_name - .is_pre_processing_required_before_authorize() - { - router_data = router_data.preprocessing_steps(state, connector).await?; - return Ok((router_data, should_continue_payment)); - } //TODO: For ACH transfers, if preprocessing_step is not required for connectors encountered in future, add the check let router_data_and_should_continue_payment = match payment_data.get_payment_method_data() { Some(domain::PaymentMethodData::BankTransfer(_)) => (router_data, should_continue_payment), diff --git a/crates/router/src/core/payments/flows/authorize_flow.rs b/crates/router/src/core/payments/flows/authorize_flow.rs index 4a42366335..6e790c9c57 100644 --- a/crates/router/src/core/payments/flows/authorize_flow.rs +++ b/crates/router/src/core/payments/flows/authorize_flow.rs @@ -711,9 +711,7 @@ pub async fn authorize_preprocessing_steps( router_data.request.to_owned(), resp.response.clone(), ); - if connector.connector_name == api_models::enums::Connector::Airwallex { - authorize_router_data.reference_id = resp.reference_id; - } else if connector.connector_name == api_models::enums::Connector::Nuvei { + if connector.connector_name == api_models::enums::Connector::Nuvei { let (enrolled_for_3ds, related_transaction_id) = match &authorize_router_data.response { Ok(types::PaymentsResponseData::ThreeDSEnrollmentResponse { enrolled_v2,