diff --git a/crates/hyperswitch_connectors/src/connectors/chargebee.rs b/crates/hyperswitch_connectors/src/connectors/chargebee.rs index bde9a165b2..6ab449de24 100644 --- a/crates/hyperswitch_connectors/src/connectors/chargebee.rs +++ b/crates/hyperswitch_connectors/src/connectors/chargebee.rs @@ -1,15 +1,23 @@ pub mod transformers; use base64::Engine; +#[cfg(all(feature = "revenue_recovery", feature = "v2"))] +use common_utils::types::{StringMinorUnit, StringMinorUnitForConnector}; use common_utils::{ + consts::BASE64_ENGINE, errors::CustomResult, ext_traits::BytesExt, request::{Method, Request, RequestBuilder, RequestContent}, - types::{AmountConvertor, StringMinorUnit, StringMinorUnitForConnector}, + types::{AmountConvertor, MinorUnit, MinorUnitForConnector}, }; use error_stack::{report, ResultExt}; -#[cfg(all(feature = "revenue_recovery", feature = "v2"))] -use hyperswitch_domain_models::revenue_recovery; +#[cfg(all(feature = "v2", feature = "revenue_recovery"))] +use hyperswitch_domain_models::{ + revenue_recovery, router_flow_types::revenue_recovery::RecoveryRecordBack, + router_request_types::revenue_recovery::RevenueRecoveryRecordBackRequest, + router_response_types::revenue_recovery::RevenueRecoveryRecordBackResponse, + types::RevenueRecoveryRecordBackRouterData, +}; use hyperswitch_domain_models::{ router_data::{AccessToken, ConnectorAuthType, ErrorResponse, RouterData}, router_flow_types::{ @@ -39,20 +47,22 @@ use hyperswitch_interfaces::{ types::{self, Response}, webhooks, }; -use masking::{ExposeInterface, Mask, PeekInterface, Secret}; +#[cfg(all(feature = "revenue_recovery", feature = "v2"))] +use masking::ExposeInterface; +use masking::{Mask, PeekInterface, Secret}; use transformers as chargebee; use crate::{constants::headers, types::ResponseRouterData, utils}; #[derive(Clone)] pub struct Chargebee { - amount_converter: &'static (dyn AmountConvertor + Sync), + amount_converter: &'static (dyn AmountConvertor + Sync), } impl Chargebee { pub fn new() -> &'static Self { &Self { - amount_converter: &StringMinorUnitForConnector, + amount_converter: &MinorUnitForConnector, } } } @@ -69,6 +79,8 @@ impl api::Refund for Chargebee {} impl api::RefundExecute for Chargebee {} impl api::RefundSync for Chargebee {} impl api::PaymentToken for Chargebee {} +#[cfg(all(feature = "v2", feature = "revenue_recovery"))] +impl api::revenue_recovery::RevenueRecoveryRecordBack for Chargebee {} impl ConnectorIntegration for Chargebee @@ -87,7 +99,7 @@ where ) -> CustomResult)>, errors::ConnectorError> { let mut header = vec![( headers::CONTENT_TYPE.to_string(), - self.get_content_type().to_string().into(), + self.common_get_content_type().to_string().into(), )]; let mut api_key = self.get_auth_header(&req.connector_auth_type)?; header.append(&mut api_key); @@ -105,7 +117,7 @@ impl ConnectorCommon for Chargebee { } fn common_get_content_type(&self) -> &'static str { - "application/json" + "application/x-www-form-urlencoded" } fn base_url<'a>(&self, connectors: &'a Connectors) -> &'a str { @@ -118,9 +130,10 @@ impl ConnectorCommon for Chargebee { ) -> CustomResult)>, errors::ConnectorError> { let auth = chargebee::ChargebeeAuthType::try_from(auth_type) .change_context(errors::ConnectorError::FailedToObtainAuthType)?; + let encoded_api_key = BASE64_ENGINE.encode(auth.full_access_key_v1.peek()); Ok(vec![( headers::AUTHORIZATION.to_string(), - auth.api_key.expose().into_masked(), + format!("Basic {encoded_api_key}").into_masked(), )]) } @@ -139,9 +152,9 @@ impl ConnectorCommon for Chargebee { Ok(ErrorResponse { status_code: res.status_code, - code: response.code, - message: response.message, - reason: response.reason, + code: response.api_error_code.clone(), + message: response.api_error_code.clone(), + reason: Some(response.message), attempt_status: None, connector_transaction_id: None, issuer_error_code: None, @@ -546,6 +559,110 @@ impl ConnectorIntegration for Chargebee } } +#[cfg(all(feature = "v2", feature = "revenue_recovery"))] +impl + ConnectorIntegration< + RecoveryRecordBack, + RevenueRecoveryRecordBackRequest, + RevenueRecoveryRecordBackResponse, + > for Chargebee +{ + fn get_headers( + &self, + req: &RevenueRecoveryRecordBackRouterData, + connectors: &Connectors, + ) -> CustomResult)>, errors::ConnectorError> { + self.build_headers(req, connectors) + } + fn get_url( + &self, + req: &RevenueRecoveryRecordBackRouterData, + connectors: &Connectors, + ) -> CustomResult { + let metadata: chargebee::ChargebeeMetadata = + utils::to_connector_meta_from_secret(req.connector_meta_data.clone())?; + let url = self + .base_url(connectors) + .to_string() + .replace("$", metadata.site.peek()); + let invoice_id = req + .request + .merchant_reference_id + .get_string_repr() + .to_string(); + Ok(format!("{url}v2/invoices/{invoice_id}/record_payment")) + } + + fn get_content_type(&self) -> &'static str { + self.common_get_content_type() + } + + fn get_request_body( + &self, + req: &RevenueRecoveryRecordBackRouterData, + _connectors: &Connectors, + ) -> CustomResult { + let amount = utils::convert_amount( + self.amount_converter, + req.request.amount, + req.request.currency, + )?; + let connector_router_data = chargebee::ChargebeeRouterData::from((amount, req)); + let connector_req = + chargebee::ChargebeeRecordPaymentRequest::try_from(&connector_router_data)?; + Ok(RequestContent::FormUrlEncoded(Box::new(connector_req))) + } + + fn build_request( + &self, + req: &RevenueRecoveryRecordBackRouterData, + connectors: &Connectors, + ) -> CustomResult, errors::ConnectorError> { + Ok(Some( + RequestBuilder::new() + .method(Method::Post) + .url(&types::RevenueRecoveryRecordBackType::get_url( + self, req, connectors, + )?) + .attach_default_headers() + .headers(types::RevenueRecoveryRecordBackType::get_headers( + self, req, connectors, + )?) + .set_body(types::RevenueRecoveryRecordBackType::get_request_body( + self, req, connectors, + )?) + .build(), + )) + } + + fn handle_response( + &self, + data: &RevenueRecoveryRecordBackRouterData, + event_builder: Option<&mut ConnectorEvent>, + res: Response, + ) -> CustomResult { + let response: chargebee::ChargebeeRecordbackResponse = res + .response + .parse_struct("chargebee ChargebeeRecordbackResponse") + .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; + event_builder.map(|i| i.set_response_body(&response)); + router_env::logger::info!(connector_response=?response); + RouterData::try_from(ResponseRouterData { + response, + data: data.clone(), + http_code: res.status_code, + }) + } + + fn get_error_response( + &self, + res: Response, + event_builder: Option<&mut ConnectorEvent>, + ) -> CustomResult { + self.build_error_response(res, event_builder) + } +} + #[async_trait::async_trait] impl webhooks::IncomingWebhook for Chargebee { fn get_webhook_source_verification_signature( diff --git a/crates/hyperswitch_connectors/src/connectors/chargebee/transformers.rs b/crates/hyperswitch_connectors/src/connectors/chargebee/transformers.rs index f5b16695c1..e6e8e1b123 100644 --- a/crates/hyperswitch_connectors/src/connectors/chargebee/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/chargebee/transformers.rs @@ -2,21 +2,23 @@ use std::str::FromStr; use common_enums::enums; -use common_utils::{ - errors::CustomResult, - ext_traits::ByteSliceExt, - types::{MinorUnit, StringMinorUnit}, -}; +use common_utils::{errors::CustomResult, ext_traits::ByteSliceExt, pii, types::MinorUnit}; use error_stack::ResultExt; #[cfg(all(feature = "revenue_recovery", feature = "v2"))] use hyperswitch_domain_models::revenue_recovery; use hyperswitch_domain_models::{ payment_method_data::PaymentMethodData, router_data::{ConnectorAuthType, RouterData}, - router_flow_types::refunds::{Execute, RSync}, - router_request_types::ResponseId, - router_response_types::{PaymentsResponseData, RefundsResponseData}, - types::{PaymentsAuthorizeRouterData, RefundsRouterData}, + router_flow_types::{ + refunds::{Execute, RSync}, + RecoveryRecordBack, + }, + router_request_types::{revenue_recovery::RevenueRecoveryRecordBackRequest, ResponseId}, + router_response_types::{ + revenue_recovery::RevenueRecoveryRecordBackResponse, PaymentsResponseData, + RefundsResponseData, + }, + types::{PaymentsAuthorizeRouterData, RefundsRouterData, RevenueRecoveryRecordBackRouterData}, }; use hyperswitch_interfaces::errors; use masking::Secret; @@ -25,18 +27,17 @@ use time::PrimitiveDateTime; use crate::{ types::{RefundsResponseRouterData, ResponseRouterData}, - utils::PaymentsAuthorizeRequestData, + utils::{self, PaymentsAuthorizeRequestData}, }; //TODO: Fill the struct with respective fields pub struct ChargebeeRouterData { - pub amount: StringMinorUnit, // The type of amount that a connector accepts, for example, String, i64, f64, etc. + pub amount: MinorUnit, // The type of amount that a connector accepts, for example, String, i64, f64, etc. pub router_data: T, } -impl From<(StringMinorUnit, T)> for ChargebeeRouterData { - fn from((amount, item): (StringMinorUnit, T)) -> Self { - //Todo : use utils to convert the amount to the type of amount that a connector accepts +impl From<(MinorUnit, T)> for ChargebeeRouterData { + fn from((amount, item): (MinorUnit, T)) -> Self { Self { amount, router_data: item, @@ -47,7 +48,7 @@ impl From<(StringMinorUnit, T)> for ChargebeeRouterData { //TODO: Fill the struct with respective fields #[derive(Default, Debug, Serialize, PartialEq)] pub struct ChargebeePaymentsRequest { - amount: StringMinorUnit, + amount: MinorUnit, card: ChargebeeCard, } @@ -75,7 +76,7 @@ impl TryFrom<&ChargebeeRouterData<&PaymentsAuthorizeRouterData>> for ChargebeePa complete: item.router_data.request.is_auto_capture()?, }; Ok(Self { - amount: item.amount.clone(), + amount: item.amount, card, }) } @@ -84,10 +85,25 @@ impl TryFrom<&ChargebeeRouterData<&PaymentsAuthorizeRouterData>> for ChargebeePa } } -//TODO: Fill the struct with respective fields // Auth Struct pub struct ChargebeeAuthType { - pub(super) api_key: Secret, + pub(super) full_access_key_v1: Secret, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct ChargebeeMetadata { + pub(super) site: Secret, +} + +impl TryFrom<&Option> for ChargebeeMetadata { + type Error = error_stack::Report; + fn try_from(meta_data: &Option) -> Result { + let metadata: Self = utils::to_connector_meta_from_secret::(meta_data.clone()) + .change_context(errors::ConnectorError::InvalidConnectorConfig { + config: "metadata", + })?; + Ok(metadata) + } } impl TryFrom<&ConnectorAuthType> for ChargebeeAuthType { @@ -95,7 +111,7 @@ impl TryFrom<&ConnectorAuthType> for ChargebeeAuthType { fn try_from(auth_type: &ConnectorAuthType) -> Result { match auth_type { ConnectorAuthType::HeaderKey { api_key } => Ok(Self { - api_key: api_key.to_owned(), + full_access_key_v1: api_key.clone(), }), _ => Err(errors::ConnectorError::FailedToObtainAuthType.into()), } @@ -158,7 +174,7 @@ impl TryFrom TryFrom<&ChargebeeRouterData<&RefundsRouterData>> for ChargebeeRefundRequest { @@ -229,13 +245,10 @@ impl TryFrom> for RefundsRouter } } -//TODO: Fill the struct with respective fields #[derive(Default, Debug, Serialize, Deserialize, PartialEq)] pub struct ChargebeeErrorResponse { - pub status_code: u16, - pub code: String, + pub api_error_code: String, pub message: String, - pub reason: Option, } #[derive(Serialize, Deserialize, Debug)] @@ -508,3 +521,127 @@ impl TryFrom for revenue_recovery::RevenueRecoveryInvoiceD }) } } + +#[derive(Debug, Serialize)] +pub struct ChargebeeRecordPaymentRequest { + #[serde(rename = "transaction[amount]")] + pub amount: MinorUnit, + #[serde(rename = "transaction[payment_method]")] + pub payment_method: ChargebeeRecordPaymentMethod, + #[serde(rename = "transaction[id_at_gateway]")] + pub connector_payment_id: Option, + #[serde(rename = "transaction[status]")] + pub status: ChargebeeRecordStatus, +} + +#[derive(Debug, Serialize, Clone, Copy)] +#[serde(rename_all = "snake_case")] +pub enum ChargebeeRecordPaymentMethod { + Other, +} + +#[derive(Debug, Serialize, Clone, Copy)] +#[serde(rename_all = "snake_case")] +pub enum ChargebeeRecordStatus { + Success, + Failure, +} + +#[cfg(all(feature = "v2", feature = "revenue_recovery"))] +impl TryFrom<&ChargebeeRouterData<&RevenueRecoveryRecordBackRouterData>> + for ChargebeeRecordPaymentRequest +{ + type Error = error_stack::Report; + fn try_from( + item: &ChargebeeRouterData<&RevenueRecoveryRecordBackRouterData>, + ) -> Result { + let req = &item.router_data.request; + Ok(Self { + amount: req.amount, + payment_method: ChargebeeRecordPaymentMethod::Other, + connector_payment_id: req + .connector_transaction_id + .as_ref() + .map(|connector_payment_id| connector_payment_id.get_id().to_string()), + status: ChargebeeRecordStatus::try_from(req.attempt_status)?, + }) + } +} + +#[cfg(all(feature = "v2", feature = "revenue_recovery"))] +impl TryFrom for ChargebeeRecordStatus { + type Error = error_stack::Report; + fn try_from(status: enums::AttemptStatus) -> Result { + match status { + enums::AttemptStatus::Charged + | enums::AttemptStatus::PartialCharged + | enums::AttemptStatus::PartialChargedAndChargeable => Ok(Self::Success), + enums::AttemptStatus::Failure + | enums::AttemptStatus::CaptureFailed + | enums::AttemptStatus::RouterDeclined => Ok(Self::Failure), + enums::AttemptStatus::AuthenticationFailed + | enums::AttemptStatus::Started + | enums::AttemptStatus::AuthenticationPending + | enums::AttemptStatus::AuthenticationSuccessful + | enums::AttemptStatus::Authorized + | enums::AttemptStatus::AuthorizationFailed + | enums::AttemptStatus::Authorizing + | enums::AttemptStatus::CodInitiated + | enums::AttemptStatus::Voided + | enums::AttemptStatus::VoidInitiated + | enums::AttemptStatus::CaptureInitiated + | enums::AttemptStatus::VoidFailed + | enums::AttemptStatus::AutoRefunded + | enums::AttemptStatus::Unresolved + | enums::AttemptStatus::Pending + | enums::AttemptStatus::PaymentMethodAwaited + | enums::AttemptStatus::ConfirmationAwaited + | enums::AttemptStatus::DeviceDataCollectionPending => { + Err(errors::ConnectorError::NotSupported { + message: "Record back flow is only supported for terminal status".to_string(), + connector: "chargebee", + } + .into()) + } + } + } +} + +#[derive(Debug, Deserialize, Serialize, Clone)] +pub struct ChargebeeRecordbackResponse { + pub invoice: ChargebeeRecordbackInvoice, +} + +#[derive(Debug, Deserialize, Serialize, Clone)] +pub struct ChargebeeRecordbackInvoice { + pub id: common_utils::id_type::PaymentReferenceId, +} + +impl + TryFrom< + ResponseRouterData< + RecoveryRecordBack, + ChargebeeRecordbackResponse, + RevenueRecoveryRecordBackRequest, + RevenueRecoveryRecordBackResponse, + >, + > for RevenueRecoveryRecordBackRouterData +{ + type Error = error_stack::Report; + fn try_from( + item: ResponseRouterData< + RecoveryRecordBack, + ChargebeeRecordbackResponse, + RevenueRecoveryRecordBackRequest, + RevenueRecoveryRecordBackResponse, + >, + ) -> Result { + let merchant_reference_id = item.response.invoice.id; + Ok(Self { + response: Ok(RevenueRecoveryRecordBackResponse { + merchant_reference_id, + }), + ..item.data + }) + } +} diff --git a/crates/hyperswitch_connectors/src/default_implementations.rs b/crates/hyperswitch_connectors/src/default_implementations.rs index 23b9602b0a..e2faeaa1a3 100644 --- a/crates/hyperswitch_connectors/src/default_implementations.rs +++ b/crates/hyperswitch_connectors/src/default_implementations.rs @@ -22,6 +22,18 @@ use hyperswitch_domain_models::{ router_request_types::PayoutsData, router_response_types::PayoutsResponseData, }; +#[cfg(all(feature = "v2", feature = "revenue_recovery"))] +use hyperswitch_domain_models::{ + router_flow_types::revenue_recovery::{ + GetAdditionalRevenueRecoveryDetails, RecoveryRecordBack, + }, + router_request_types::revenue_recovery::{ + GetAdditionalRevenueRecoveryRequestData, RevenueRecoveryRecordBackRequest, + }, + router_response_types::revenue_recovery::{ + GetAdditionalRevenueRecoveryResponseData, RevenueRecoveryRecordBackResponse, + }, +}; use hyperswitch_domain_models::{ router_flow_types::{ dispute::{Accept, Defend, Evidence}, @@ -32,15 +44,10 @@ use hyperswitch_domain_models::{ CreateConnectorCustomer, IncrementalAuthorization, PostProcessing, PostSessionTokens, PreProcessing, Reject, SdkSessionUpdate, }, - revenue_recovery::RecoveryRecordBack, webhooks::VerifyWebhookSource, - Authenticate, AuthenticationConfirmation, GetAdditionalRevenueRecoveryDetails, - PostAuthenticate, PreAuthenticate, + Authenticate, AuthenticationConfirmation, PostAuthenticate, PreAuthenticate, }, router_request_types::{ - revenue_recovery::{ - GetAdditionalRevenueRecoveryRequestData, RevenueRecoveryRecordBackRequest, - }, unified_authentication_service::{ UasAuthenticationRequestData, UasAuthenticationResponseData, UasConfirmationRequestData, UasPostAuthenticationRequestData, @@ -54,9 +61,6 @@ use hyperswitch_domain_models::{ SubmitEvidenceRequestData, UploadFileRequestData, VerifyWebhookSourceRequestData, }, router_response_types::{ - revenue_recovery::{ - GetAdditionalRevenueRecoveryResponseData, RevenueRecoveryRecordBackResponse, - }, AcceptDisputeResponse, DefendDisputeResponse, MandateRevokeResponseData, PaymentsResponseData, RetrieveFileResponse, SubmitEvidenceResponse, TaxCalculationResponseData, UploadFileResponse, VerifyWebhookSourceResponseData, @@ -72,6 +76,10 @@ use hyperswitch_interfaces::api::payouts::{ PayoutCancel, PayoutCreate, PayoutEligibility, PayoutFulfill, PayoutQuote, PayoutRecipient, PayoutRecipientAccount, PayoutSync, }; +#[cfg(all(feature = "v2", feature = "revenue_recovery"))] +use hyperswitch_interfaces::api::revenue_recovery::{ + AdditionalRevenueRecovery, RevenueRecoveryRecordBack, +}; use hyperswitch_interfaces::{ api::{ self, @@ -83,7 +91,7 @@ use hyperswitch_interfaces::{ PaymentSessionUpdate, PaymentsCompleteAuthorize, PaymentsPostProcessing, PaymentsPreProcessing, TaxCalculation, }, - revenue_recovery::{AdditionalRevenueRecovery, RevenueRecovery, RevenueRecoveryRecordBack}, + revenue_recovery::RevenueRecovery, ConnectorIntegration, ConnectorMandateRevoke, ConnectorRedirectResponse, UasAuthentication, UasAuthenticationConfirmation, UasPostAuthentication, UasPreAuthentication, UnifiedAuthenticationService, @@ -3651,6 +3659,7 @@ default_imp_for_uas_authentication_confirmation!( connectors::Zsl ); +#[cfg(all(feature = "v2", feature = "revenue_recovery"))] macro_rules! default_imp_for_revenue_recovery_record_back { ($($path:ident::$connector:ident),*) => { $( impl RevenueRecoveryRecordBack for $path::$connector {} @@ -3665,6 +3674,7 @@ macro_rules! default_imp_for_revenue_recovery_record_back { }; } +#[cfg(all(feature = "v2", feature = "revenue_recovery"))] default_imp_for_revenue_recovery_record_back!( connectors::Aci, connectors::Adyen, @@ -3680,7 +3690,6 @@ default_imp_for_revenue_recovery_record_back!( connectors::Braintree, connectors::Boku, connectors::Cashtocode, - connectors::Chargebee, connectors::Checkout, connectors::Coinbase, connectors::Coingate, @@ -3751,10 +3760,10 @@ default_imp_for_revenue_recovery_record_back!( connectors::Zsl ); +#[cfg(all(feature = "v2", feature = "revenue_recovery"))] macro_rules! default_imp_for_additional_revenue_recovery_call { ($($path:ident::$connector:ident),*) => { $( - impl RevenueRecovery for $path::$connector {} impl AdditionalRevenueRecovery for $path::$connector {} impl ConnectorIntegration< @@ -3767,6 +3776,7 @@ macro_rules! default_imp_for_additional_revenue_recovery_call { }; } +#[cfg(all(feature = "v2", feature = "revenue_recovery"))] default_imp_for_additional_revenue_recovery_call!( connectors::Aci, connectors::Adyen, @@ -3852,3 +3862,97 @@ default_imp_for_additional_revenue_recovery_call!( connectors::Zen, connectors::Zsl ); + +macro_rules! default_imp_for_revenue_recovery { + ($($path:ident::$connector:ident),*) => { + $( + impl RevenueRecovery for $path::$connector {} + )* + }; +} + +default_imp_for_revenue_recovery!( + connectors::Aci, + connectors::Adyen, + connectors::Airwallex, + connectors::Amazonpay, + connectors::Authorizedotnet, + connectors::Bambora, + connectors::Bamboraapac, + connectors::Bankofamerica, + connectors::Billwerk, + connectors::Bluesnap, + connectors::Bitpay, + connectors::Braintree, + connectors::Boku, + connectors::Cashtocode, + connectors::Chargebee, + connectors::Checkout, + connectors::Coinbase, + connectors::Coingate, + connectors::Cryptopay, + connectors::CtpMastercard, + connectors::Cybersource, + connectors::Datatrans, + connectors::Deutschebank, + connectors::Digitalvirgo, + connectors::Dlocal, + connectors::Elavon, + connectors::Fiserv, + connectors::Fiservemea, + connectors::Fiuu, + connectors::Forte, + connectors::Getnet, + connectors::Globalpay, + connectors::Globepay, + connectors::Gocardless, + connectors::Hipay, + connectors::Helcim, + connectors::Iatapay, + connectors::Inespay, + connectors::Itaubank, + connectors::Jpmorgan, + connectors::Juspaythreedsserver, + connectors::Klarna, + connectors::Nomupay, + connectors::Noon, + connectors::Novalnet, + connectors::Nexinets, + connectors::Nexixpay, + connectors::Nuvei, + connectors::Opayo, + connectors::Opennode, + connectors::Payeezy, + connectors::Paypal, + connectors::Paystack, + connectors::Payu, + connectors::Powertranz, + connectors::Prophetpay, + connectors::Mifinity, + connectors::Mollie, + connectors::Moneris, + connectors::Multisafepay, + connectors::Paybox, + connectors::Payme, + connectors::Placetopay, + connectors::Rapyd, + connectors::Razorpay, + connectors::Recurly, + connectors::Redsys, + connectors::Shift4, + connectors::Stax, + connectors::Square, + connectors::Stripebilling, + connectors::Taxjar, + connectors::Thunes, + connectors::Trustpay, + connectors::Tsys, + connectors::UnifiedAuthenticationService, + connectors::Worldline, + connectors::Worldpay, + connectors::Wellsfargo, + connectors::Volt, + connectors::Xendit, + connectors::Zen, + connectors::Zsl +); diff --git a/crates/hyperswitch_domain_models/src/router_flow_types/revenue_recovery.rs b/crates/hyperswitch_domain_models/src/router_flow_types/revenue_recovery.rs index c6583811bc..b73ce53350 100644 --- a/crates/hyperswitch_domain_models/src/router_flow_types/revenue_recovery.rs +++ b/crates/hyperswitch_domain_models/src/router_flow_types/revenue_recovery.rs @@ -1,2 +1,3 @@ pub struct GetAdditionalRevenueRecoveryDetails; +#[derive(Debug, Clone)] pub struct RecoveryRecordBack; diff --git a/crates/hyperswitch_interfaces/src/api/revenue_recovery.rs b/crates/hyperswitch_interfaces/src/api/revenue_recovery.rs index 778a13cbae..1a84b65c09 100644 --- a/crates/hyperswitch_interfaces/src/api/revenue_recovery.rs +++ b/crates/hyperswitch_interfaces/src/api/revenue_recovery.rs @@ -10,8 +10,11 @@ use hyperswitch_domain_models::{ }, }; -use super::{ConnectorCommon, ConnectorIntegration}; +#[cfg(all(feature = "v2", feature = "revenue_recovery"))] +use super::ConnectorCommon; +use super::ConnectorIntegration; /// trait RevenueRecovery +#[cfg(all(feature = "v2", feature = "revenue_recovery"))] pub trait RevenueRecovery: ConnectorCommon + AdditionalRevenueRecovery + RevenueRecoveryRecordBack { @@ -36,3 +39,7 @@ pub trait RevenueRecoveryRecordBack: > { } + +#[cfg(not(all(feature = "v2", feature = "revenue_recovery")))] +/// trait RevenueRecovery +pub trait RevenueRecovery {} diff --git a/crates/router/src/core/admin.rs b/crates/router/src/core/admin.rs index 454a090b63..52301b6e0f 100644 --- a/crates/router/src/core/admin.rs +++ b/crates/router/src/core/admin.rs @@ -1314,6 +1314,7 @@ impl ConnectorAuthTypeAndMetadataValidation<'_> { } api_enums::Connector::Chargebee => { chargebee::transformers::ChargebeeAuthType::try_from(self.auth_type)?; + chargebee::transformers::ChargebeeMetadata::try_from(self.connector_meta_data)?; Ok(()) } api_enums::Connector::Checkout => { diff --git a/crates/router/src/core/payments/flows.rs b/crates/router/src/core/payments/flows.rs index 5f72756231..abb6247762 100644 --- a/crates/router/src/core/payments/flows.rs +++ b/crates/router/src/core/payments/flows.rs @@ -12,11 +12,14 @@ pub mod session_update_flow; pub mod setup_mandate_flow; use async_trait::async_trait; +#[cfg(all(feature = "v2", feature = "revenue_recovery"))] +use hyperswitch_domain_models::router_flow_types::{ + revenue_recovery::RecoveryRecordBack, GetAdditionalRevenueRecoveryDetails, +}; use hyperswitch_domain_models::{ mandates::CustomerAcceptance, router_flow_types::{ - revenue_recovery::RecoveryRecordBack, Authenticate, AuthenticationConfirmation, - GetAdditionalRevenueRecoveryDetails, PostAuthenticate, PreAuthenticate, + Authenticate, AuthenticationConfirmation, PostAuthenticate, PreAuthenticate, }, router_request_types::PaymentsCaptureData, }; @@ -2216,6 +2219,7 @@ fn handle_post_capture_response( } } +#[cfg(all(feature = "v2", feature = "revenue_recovery"))] macro_rules! default_imp_for_revenue_recovery_record_back { ($($path:ident::$connector:ident),*) => { $( @@ -2231,8 +2235,10 @@ macro_rules! default_imp_for_revenue_recovery_record_back { }; } +#[cfg(all(feature = "v2", feature = "revenue_recovery"))] #[cfg(feature = "dummy_connector")] impl api::RevenueRecoveryRecordBack for connector::DummyConnector {} +#[cfg(all(feature = "v2", feature = "revenue_recovery"))] #[cfg(feature = "dummy_connector")] impl services::ConnectorIntegration< @@ -2242,7 +2248,7 @@ impl > for connector::DummyConnector { } - +#[cfg(all(feature = "v2", feature = "revenue_recovery"))] default_imp_for_revenue_recovery_record_back!( connector::Adyenplatform, connector::Ebanx, @@ -2259,9 +2265,36 @@ default_imp_for_revenue_recovery_record_back!( connector::Wise ); -macro_rules! default_imp_for_additional_revenue_recovery_call { +macro_rules! default_imp_for_revenue_recovery { ($($path:ident::$connector:ident),*) => { $( impl api::RevenueRecovery for $path::$connector {} + )* + }; +} + +#[cfg(feature = "dummy_connector")] +impl api::RevenueRecovery for connector::DummyConnector {} + +default_imp_for_revenue_recovery! { + connector::Adyenplatform, + connector::Ebanx, + connector::Gpayments, + connector::Netcetera, + connector::Nmi, + connector::Payone, + connector::Plaid, + connector::Riskified, + connector::Signifyd, + connector::Stripe, + connector::Threedsecureio, + connector::Wellsfargopayout, + connector::Wise +} + +#[cfg(all(feature = "v2", feature = "revenue_recovery"))] +macro_rules! default_imp_for_additional_revenue_recovery_call { + ($($path:ident::$connector:ident),*) => { + $( impl api::AdditionalRevenueRecovery for $path::$connector {} impl services::ConnectorIntegration< @@ -2274,9 +2307,10 @@ macro_rules! default_imp_for_additional_revenue_recovery_call { }; } +#[cfg(all(feature = "v2", feature = "revenue_recovery"))] #[cfg(feature = "dummy_connector")] -impl api::RevenueRecovery for connector::DummyConnector {} impl api::AdditionalRevenueRecovery for connector::DummyConnector {} +#[cfg(all(feature = "v2", feature = "revenue_recovery"))] #[cfg(feature = "dummy_connector")] impl services::ConnectorIntegration< @@ -2287,6 +2321,7 @@ impl { } +#[cfg(all(feature = "v2", feature = "revenue_recovery"))] default_imp_for_additional_revenue_recovery_call!( connector::Adyenplatform, connector::Ebanx, diff --git a/crates/router/src/services/conversion_impls.rs b/crates/router/src/services/conversion_impls.rs index 8572add041..e3c00d82d5 100644 --- a/crates/router/src/services/conversion_impls.rs +++ b/crates/router/src/services/conversion_impls.rs @@ -10,8 +10,8 @@ use hyperswitch_domain_models::{ router_data_v2::{ flow_common_types::{ AccessTokenFlowData, DisputesFlowData, ExternalAuthenticationFlowData, FilesFlowData, - MandateRevokeFlowData, PaymentFlowData, RefundFlowData, UasFlowData, - WebhookSourceVerifyData, + MandateRevokeFlowData, PaymentFlowData, RefundFlowData, RevenueRecoveryRecordBackData, + UasFlowData, WebhookSourceVerifyData, }, RouterDataV2, }, @@ -715,6 +715,42 @@ impl RouterDataConversion } } +impl RouterDataConversion + for RevenueRecoveryRecordBackData +{ + fn from_old_router_data( + old_router_data: &RouterData, + ) -> errors::CustomResult, errors::ConnectorError> + where + Self: Sized, + { + let resource_common_data = Self {}; + Ok(RouterDataV2 { + flow: std::marker::PhantomData, + tenant_id: old_router_data.tenant_id.clone(), + resource_common_data, + connector_auth_type: old_router_data.connector_auth_type.clone(), + request: old_router_data.request.clone(), + response: old_router_data.response.clone(), + }) + } + + fn to_old_router_data( + new_router_data: RouterDataV2, + ) -> errors::CustomResult, errors::ConnectorError> + where + Self: Sized, + { + let router_data = get_default_router_data( + new_router_data.tenant_id.clone(), + "recovery_record_back", + new_router_data.request, + new_router_data.response, + ); + Ok(router_data) + } +} + impl RouterDataConversion for UasFlowData { fn from_old_router_data( old_router_data: &RouterData,