diff --git a/crates/hyperswitch_connectors/src/connectors/chargebee.rs b/crates/hyperswitch_connectors/src/connectors/chargebee.rs index 5e2e23a8a9..7f64c2f299 100644 --- a/crates/hyperswitch_connectors/src/connectors/chargebee.rs +++ b/crates/hyperswitch_connectors/src/connectors/chargebee.rs @@ -21,28 +21,30 @@ use hyperswitch_domain_models::{ payments::{Authorize, Capture, PSync, PaymentMethodToken, Session, SetupMandate, Void}, refunds::{Execute, RSync}, revenue_recovery::InvoiceRecordBack, + subscriptions::GetSubscriptionPlans, }, router_request_types::{ - revenue_recovery::InvoiceRecordBackRequest, AccessTokenRequestData, - PaymentMethodTokenizationData, PaymentsAuthorizeData, PaymentsCancelData, - PaymentsCaptureData, PaymentsSessionData, PaymentsSyncData, RefundsData, - SetupMandateRequestData, + revenue_recovery::InvoiceRecordBackRequest, subscriptions::GetSubscriptionPlansRequest, + AccessTokenRequestData, PaymentMethodTokenizationData, PaymentsAuthorizeData, + PaymentsCancelData, PaymentsCaptureData, PaymentsSessionData, PaymentsSyncData, + RefundsData, SetupMandateRequestData, }, router_response_types::{ - revenue_recovery::InvoiceRecordBackResponse, ConnectorInfo, PaymentsResponseData, - RefundsResponseData, + revenue_recovery::InvoiceRecordBackResponse, subscriptions::GetSubscriptionPlansResponse, + ConnectorInfo, PaymentsResponseData, RefundsResponseData, }, types::{ - InvoiceRecordBackRouterData, PaymentsAuthorizeRouterData, PaymentsCaptureRouterData, - PaymentsSyncRouterData, RefundSyncRouterData, RefundsRouterData, + GetSubscriptionPlansRouterData, InvoiceRecordBackRouterData, PaymentsAuthorizeRouterData, + PaymentsCaptureRouterData, PaymentsSyncRouterData, RefundSyncRouterData, RefundsRouterData, }, }; use hyperswitch_interfaces::{ api::{ - self, ConnectorCommon, ConnectorCommonExt, ConnectorIntegration, ConnectorSpecifications, - ConnectorValidation, + self, subscriptions_v2::GetSubscriptionPlansV2, ConnectorCommon, ConnectorCommonExt, + ConnectorIntegration, ConnectorSpecifications, ConnectorValidation, }, configs::Connectors, + connector_integration_v2::ConnectorIntegrationV2, errors, events::connector_api_logs::ConnectorEvent, types::{self, Response}, @@ -51,7 +53,12 @@ use hyperswitch_interfaces::{ use masking::{Mask, PeekInterface, Secret}; use transformers as chargebee; -use crate::{constants::headers, types::ResponseRouterData, utils}; +use crate::{ + connectors::chargebee::transformers::ChargebeeListPlansResponse, + constants::{self, headers}, + types::ResponseRouterData, + utils, +}; #[derive(Clone)] pub struct Chargebee { @@ -659,6 +666,132 @@ impl ConnectorIntegration, +) -> CustomResult { + // Try to get limit from request, else default to 10 + let limit = _req.request.limit.unwrap_or(10); + let param = format!("?limit={}&type[is]={}", limit, constants::PLAN_ITEM_TYPE); + Ok(param) +} + +impl api::subscriptions::Subscriptions for Chargebee {} +impl api::subscriptions::GetSubscriptionPlansFlow for Chargebee {} + +impl + ConnectorIntegration< + GetSubscriptionPlans, + GetSubscriptionPlansRequest, + GetSubscriptionPlansResponse, + > for Chargebee +{ + fn get_headers( + &self, + req: &GetSubscriptionPlansRouterData, + connectors: &Connectors, + ) -> CustomResult)>, errors::ConnectorError> { + self.build_headers(req, connectors) + } + + fn get_url( + &self, + req: &GetSubscriptionPlansRouterData, + connectors: &Connectors, + ) -> CustomResult { + let query_params = get_chargebee_plans_query_params(req)?; + let metadata: chargebee::ChargebeeMetadata = + utils::to_connector_meta_from_secret(req.connector_meta_data.clone())?; + + let site = metadata.site.peek(); + + let mut base = self.base_url(connectors).to_string(); + + base = base.replace("{{merchant_endpoint_prefix}}", site); + base = base.replace("$", site); + + if base.contains("{{merchant_endpoint_prefix}}") || base.contains('$') { + return Err(errors::ConnectorError::InvalidConnectorConfig { + config: "Chargebee base_url has an unresolved placeholder (expected `$` or `{{merchant_endpoint_prefix}}`).", + } + .into()); + } + + if !base.ends_with('/') { + base.push('/'); + } + + let url = format!("{base}v2/items{query_params}"); + Ok(url) + } + + fn get_content_type(&self) -> &'static str { + self.common_get_content_type() + } + + fn build_request( + &self, + req: &GetSubscriptionPlansRouterData, + connectors: &Connectors, + ) -> CustomResult, errors::ConnectorError> { + Ok(Some( + RequestBuilder::new() + .method(Method::Get) + .url(&types::GetSubscriptionPlansType::get_url( + self, req, connectors, + )?) + .attach_default_headers() + .headers(types::GetSubscriptionPlansType::get_headers( + self, req, connectors, + )?) + .build(), + )) + } + + fn handle_response( + &self, + data: &GetSubscriptionPlansRouterData, + event_builder: Option<&mut ConnectorEvent>, + res: Response, + ) -> CustomResult { + let response: ChargebeeListPlansResponse = res + .response + .parse_struct("ChargebeeListPlansResponse") + .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) + } +} + +impl GetSubscriptionPlansV2 for Chargebee {} + +impl + ConnectorIntegrationV2< + GetSubscriptionPlans, + hyperswitch_domain_models::router_data_v2::flow_common_types::GetSubscriptionPlansData, + GetSubscriptionPlansRequest, + GetSubscriptionPlansResponse, + > for Chargebee +{ + // Not implemented (R) +} + #[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 83e4795f3e..721f50a52f 100644 --- a/crates/hyperswitch_connectors/src/connectors/chargebee/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/chargebee/transformers.rs @@ -15,7 +15,8 @@ use hyperswitch_domain_models::{ }, router_request_types::{revenue_recovery::InvoiceRecordBackRequest, ResponseId}, router_response_types::{ - revenue_recovery::InvoiceRecordBackResponse, PaymentsResponseData, RefundsResponseData, + revenue_recovery::InvoiceRecordBackResponse, subscriptions::GetSubscriptionPlansResponse, + PaymentsResponseData, RefundsResponseData, }, types::{InvoiceRecordBackRouterData, PaymentsAuthorizeRouterData, RefundsRouterData}, }; @@ -769,3 +770,54 @@ impl }) } } + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ChargebeeListPlansResponse { + pub list: Vec, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ChargebeeItemList { + pub item: ChargebeeItem, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ChargebeeItem { + pub id: String, + pub name: String, + #[serde(rename = "type")] + pub plan_type: String, + pub is_giftable: bool, + pub enabled_for_checkout: bool, + pub enabled_in_portal: bool, + pub metered: bool, + pub deleted: bool, + pub description: Option, +} + +impl + TryFrom> + for RouterData +{ + type Error = error_stack::Report; + fn try_from( + item: ResponseRouterData, + ) -> Result { + let plans = item + .response + .list + .into_iter() + .map(|plan| { + hyperswitch_domain_models::router_response_types::subscriptions::SubscriptionPlans { + subscription_provider_plan_id: plan.item.id, + name: plan.item.name, + description: plan.item.description, + } + }) + .collect(); + Ok(Self { + response: Ok(GetSubscriptionPlansResponse { list: plans }), + ..item.data + }) + } +} diff --git a/crates/hyperswitch_connectors/src/connectors/recurly.rs b/crates/hyperswitch_connectors/src/connectors/recurly.rs index 693095cfeb..769d987909 100644 --- a/crates/hyperswitch_connectors/src/connectors/recurly.rs +++ b/crates/hyperswitch_connectors/src/connectors/recurly.rs @@ -9,14 +9,22 @@ use error_stack::report; use error_stack::ResultExt; use hyperswitch_domain_models::{ router_data::{ConnectorAuthType, ErrorResponse}, - router_data_v2::UasFlowData, - router_flow_types::unified_authentication_service::{ - Authenticate, AuthenticationConfirmation, PostAuthenticate, PreAuthenticate, + router_data_v2::{flow_common_types::GetSubscriptionPlansData, UasFlowData}, + router_flow_types::{ + subscriptions::GetSubscriptionPlans, + unified_authentication_service::{ + Authenticate, AuthenticationConfirmation, PostAuthenticate, PreAuthenticate, + }, }, - router_request_types::unified_authentication_service::{ - UasAuthenticationRequestData, UasAuthenticationResponseData, UasConfirmationRequestData, - UasPostAuthenticationRequestData, UasPreAuthenticationRequestData, + router_request_types::{ + subscriptions::GetSubscriptionPlansRequest, + unified_authentication_service::{ + UasAuthenticationRequestData, UasAuthenticationResponseData, + UasConfirmationRequestData, UasPostAuthenticationRequestData, + UasPreAuthenticationRequestData, + }, }, + router_response_types::subscriptions::GetSubscriptionPlansResponse, }; #[cfg(all(feature = "v2", feature = "revenue_recovery"))] use hyperswitch_domain_models::{ @@ -131,6 +139,18 @@ impl } impl api::revenue_recovery_v2::RevenueRecoveryV2 for Recurly {} +impl api::subscriptions_v2::SubscriptionsV2 for Recurly {} +impl api::subscriptions_v2::GetSubscriptionPlansV2 for Recurly {} + +impl + ConnectorIntegrationV2< + GetSubscriptionPlans, + GetSubscriptionPlansData, + GetSubscriptionPlansRequest, + GetSubscriptionPlansResponse, + > for Recurly +{ +} #[cfg(all(feature = "v2", feature = "revenue_recovery"))] impl api::revenue_recovery_v2::RevenueRecoveryRecordBackV2 for Recurly {} #[cfg(all(feature = "v2", feature = "revenue_recovery"))] diff --git a/crates/hyperswitch_connectors/src/constants.rs b/crates/hyperswitch_connectors/src/constants.rs index 223d7a37f7..4bfd7c9055 100644 --- a/crates/hyperswitch_connectors/src/constants.rs +++ b/crates/hyperswitch_connectors/src/constants.rs @@ -56,3 +56,5 @@ pub(crate) const CANNOT_CONTINUE_AUTH: &str = #[cfg(feature = "payouts")] pub(crate) const DEFAULT_NOTIFICATION_SCRIPT_LANGUAGE: &str = "en-US"; + +pub(crate) const PLAN_ITEM_TYPE: &str = "plan"; diff --git a/crates/hyperswitch_connectors/src/default_implementations.rs b/crates/hyperswitch_connectors/src/default_implementations.rs index a6f46e0c2a..1e404df7f9 100644 --- a/crates/hyperswitch_connectors/src/default_implementations.rs +++ b/crates/hyperswitch_connectors/src/default_implementations.rs @@ -39,6 +39,7 @@ use hyperswitch_domain_models::{ PostProcessing, PostSessionTokens, PreProcessing, Reject, SdkSessionUpdate, UpdateMetadata, }, + subscriptions::GetSubscriptionPlans, webhooks::VerifyWebhookSource, AccessTokenAuthentication, Authenticate, AuthenticationConfirmation, ExternalVaultCreateFlow, ExternalVaultDeleteFlow, ExternalVaultInsertFlow, @@ -46,6 +47,7 @@ use hyperswitch_domain_models::{ }, router_request_types::{ authentication, + subscriptions::GetSubscriptionPlansRequest, unified_authentication_service::{ UasAuthenticationRequestData, UasAuthenticationResponseData, UasConfirmationRequestData, UasPostAuthenticationRequestData, @@ -64,11 +66,11 @@ use hyperswitch_domain_models::{ VerifyWebhookSourceRequestData, }, router_response_types::{ - AcceptDisputeResponse, AuthenticationResponseData, DefendDisputeResponse, - DisputeSyncResponse, FetchDisputesResponse, MandateRevokeResponseData, - PaymentsResponseData, RetrieveFileResponse, SubmitEvidenceResponse, - TaxCalculationResponseData, UploadFileResponse, VaultResponseData, - VerifyWebhookSourceResponseData, + subscriptions::GetSubscriptionPlansResponse, AcceptDisputeResponse, + AuthenticationResponseData, DefendDisputeResponse, DisputeSyncResponse, + FetchDisputesResponse, MandateRevokeResponseData, PaymentsResponseData, + RetrieveFileResponse, SubmitEvidenceResponse, TaxCalculationResponseData, + UploadFileResponse, VaultResponseData, VerifyWebhookSourceResponseData, }, }; #[cfg(feature = "frm")] @@ -127,6 +129,7 @@ use hyperswitch_interfaces::{ PaymentsPreProcessing, TaxCalculation, }, revenue_recovery::RevenueRecovery, + subscriptions::{GetSubscriptionPlansFlow, Subscriptions}, vault::{ ExternalVault, ExternalVaultCreate, ExternalVaultDelete, ExternalVaultInsert, ExternalVaultRetrieve, @@ -6934,6 +6937,150 @@ default_imp_for_revenue_recovery!( connectors::Zsl ); +macro_rules! default_imp_for_subscriptions { + ($($path:ident::$connector:ident),*) => { + $( impl Subscriptions for $path::$connector {} + impl GetSubscriptionPlansFlow for $path::$connector {} + impl + ConnectorIntegration< + GetSubscriptionPlans, + GetSubscriptionPlansRequest, + GetSubscriptionPlansResponse + > for $path::$connector + {} + )* + }; +} + +default_imp_for_subscriptions!( + connectors::Vgs, + connectors::Aci, + connectors::Adyen, + connectors::Adyenplatform, + connectors::Affirm, + connectors::Airwallex, + connectors::Amazonpay, + connectors::Archipel, + connectors::Authipay, + connectors::Authorizedotnet, + connectors::Bambora, + connectors::Bamboraapac, + connectors::Bankofamerica, + connectors::Barclaycard, + connectors::Billwerk, + connectors::Bluesnap, + connectors::Bitpay, + connectors::Blackhawknetwork, + connectors::Bluecode, + connectors::Braintree, + connectors::Boku, + connectors::Breadpay, + connectors::Cashtocode, + connectors::Celero, + connectors::Checkbook, + connectors::Checkout, + connectors::Coinbase, + connectors::Coingate, + connectors::Cryptopay, + connectors::CtpMastercard, + connectors::Custombilling, + connectors::Cybersource, + connectors::Datatrans, + connectors::Deutschebank, + connectors::Digitalvirgo, + connectors::Dlocal, + connectors::Dwolla, + connectors::Ebanx, + connectors::Elavon, + connectors::Facilitapay, + connectors::Fiserv, + connectors::Fiservemea, + connectors::Fiuu, + connectors::Flexiti, + connectors::Forte, + connectors::Getnet, + connectors::Globalpay, + connectors::Globepay, + connectors::Gocardless, + connectors::Gpayments, + connectors::Hipay, + connectors::Helcim, + connectors::HyperswitchVault, + connectors::Hyperwallet, + connectors::Iatapay, + connectors::Inespay, + connectors::Itaubank, + connectors::Jpmorgan, + connectors::Juspaythreedsserver, + connectors::Katapult, + connectors::Klarna, + connectors::Netcetera, + connectors::Nmi, + connectors::Nomupay, + connectors::Noon, + connectors::Nordea, + connectors::Novalnet, + connectors::Nexinets, + connectors::Nexixpay, + connectors::Nuvei, + connectors::Opayo, + connectors::Opennode, + connectors::Payeezy, + connectors::Payload, + connectors::Paysafe, + connectors::Paystack, + connectors::Paytm, + connectors::Payu, + connectors::Peachpayments, + connectors::Phonepe, + connectors::Paypal, + connectors::Powertranz, + connectors::Prophetpay, + connectors::Mifinity, + connectors::Mollie, + connectors::Moneris, + connectors::Mpgs, + connectors::Multisafepay, + connectors::Paybox, + connectors::Payme, + connectors::Payone, + connectors::Placetopay, + connectors::Plaid, + connectors::Rapyd, + connectors::Razorpay, + connectors::Recurly, + connectors::Redsys, + connectors::Riskified, + connectors::Santander, + connectors::Shift4, + connectors::Sift, + connectors::Silverflow, + connectors::Signifyd, + connectors::Stax, + connectors::Stripe, + connectors::Square, + connectors::Stripebilling, + connectors::Taxjar, + connectors::Threedsecureio, + connectors::Thunes, + connectors::Tokenio, + connectors::Trustpay, + connectors::Trustpayments, + connectors::Tsys, + connectors::UnifiedAuthenticationService, + connectors::Wise, + connectors::Worldline, + connectors::Worldpay, + connectors::Worldpayvantiv, + connectors::Worldpayxml, + connectors::Wellsfargo, + connectors::Wellsfargopayout, + connectors::Volt, + connectors::Xendit, + connectors::Zen, + connectors::Zsl +); + #[cfg(all(feature = "v2", feature = "revenue_recovery"))] macro_rules! default_imp_for_billing_connector_payment_sync { ($($path:ident::$connector:ident),*) => { @@ -8916,3 +9063,18 @@ impl for connectors::DummyConnector { } + +#[cfg(feature = "dummy_connector")] +impl GetSubscriptionPlansFlow for connectors::DummyConnector {} +#[cfg(feature = "dummy_connector")] +impl + ConnectorIntegration< + GetSubscriptionPlans, + GetSubscriptionPlansRequest, + GetSubscriptionPlansResponse, + > for connectors::DummyConnector +{ +} + +#[cfg(feature = "dummy_connector")] +impl Subscriptions for connectors::DummyConnector {} diff --git a/crates/hyperswitch_domain_models/src/router_data_v2/flow_common_types.rs b/crates/hyperswitch_domain_models/src/router_data_v2/flow_common_types.rs index 1b5c48df92..7e72bfa023 100644 --- a/crates/hyperswitch_domain_models/src/router_data_v2/flow_common_types.rs +++ b/crates/hyperswitch_domain_models/src/router_data_v2/flow_common_types.rs @@ -150,6 +150,9 @@ pub struct FilesFlowData { #[derive(Debug, Clone)] pub struct InvoiceRecordBackData; +#[derive(Debug, Clone)] +pub struct GetSubscriptionPlansData; + #[derive(Debug, Clone)] pub struct UasFlowData { pub authenticate_by: String, diff --git a/crates/hyperswitch_domain_models/src/router_flow_types.rs b/crates/hyperswitch_domain_models/src/router_flow_types.rs index 887babd5fc..f8b10105b4 100644 --- a/crates/hyperswitch_domain_models/src/router_flow_types.rs +++ b/crates/hyperswitch_domain_models/src/router_flow_types.rs @@ -8,6 +8,7 @@ pub mod payments; pub mod payouts; pub mod refunds; pub mod revenue_recovery; +pub mod subscriptions; pub mod unified_authentication_service; pub mod vault; pub mod webhooks; diff --git a/crates/hyperswitch_domain_models/src/router_flow_types/subscriptions.rs b/crates/hyperswitch_domain_models/src/router_flow_types/subscriptions.rs new file mode 100644 index 0000000000..a71b81e7d3 --- /dev/null +++ b/crates/hyperswitch_domain_models/src/router_flow_types/subscriptions.rs @@ -0,0 +1,2 @@ +#[derive(Debug, Clone)] +pub struct GetSubscriptionPlans; diff --git a/crates/hyperswitch_domain_models/src/router_request_types.rs b/crates/hyperswitch_domain_models/src/router_request_types.rs index a2a869bf66..b97675006e 100644 --- a/crates/hyperswitch_domain_models/src/router_request_types.rs +++ b/crates/hyperswitch_domain_models/src/router_request_types.rs @@ -1,6 +1,7 @@ pub mod authentication; pub mod fraud_check; pub mod revenue_recovery; +pub mod subscriptions; pub mod unified_authentication_service; use api_models::payments::{AdditionalPaymentData, RequestSurchargeDetails}; use common_types::payments as common_payments_types; diff --git a/crates/hyperswitch_domain_models/src/router_request_types/subscriptions.rs b/crates/hyperswitch_domain_models/src/router_request_types/subscriptions.rs new file mode 100644 index 0000000000..19751de25f --- /dev/null +++ b/crates/hyperswitch_domain_models/src/router_request_types/subscriptions.rs @@ -0,0 +1,5 @@ +#[derive(Debug, Clone)] +pub struct GetSubscriptionPlansRequest { + pub limit: Option, + pub offset: Option, +} diff --git a/crates/hyperswitch_domain_models/src/router_response_types.rs b/crates/hyperswitch_domain_models/src/router_response_types.rs index 17c268fb60..cc766a00ba 100644 --- a/crates/hyperswitch_domain_models/src/router_response_types.rs +++ b/crates/hyperswitch_domain_models/src/router_response_types.rs @@ -1,6 +1,7 @@ pub mod disputes; pub mod fraud_check; pub mod revenue_recovery; +pub mod subscriptions; use std::collections::HashMap; use common_utils::{pii, request::Method, types::MinorUnit}; diff --git a/crates/hyperswitch_domain_models/src/router_response_types/subscriptions.rs b/crates/hyperswitch_domain_models/src/router_response_types/subscriptions.rs new file mode 100644 index 0000000000..fd6fd7965b --- /dev/null +++ b/crates/hyperswitch_domain_models/src/router_response_types/subscriptions.rs @@ -0,0 +1,11 @@ +#[derive(Debug, Clone)] +pub struct GetSubscriptionPlansResponse { + pub list: Vec, +} + +#[derive(Debug, Clone)] +pub struct SubscriptionPlans { + pub subscription_provider_plan_id: String, + pub name: String, + pub description: Option, +} diff --git a/crates/hyperswitch_domain_models/src/types.rs b/crates/hyperswitch_domain_models/src/types.rs index 362f8571b6..683e284283 100644 --- a/crates/hyperswitch_domain_models/src/types.rs +++ b/crates/hyperswitch_domain_models/src/types.rs @@ -4,19 +4,21 @@ use crate::{ router_data::{AccessToken, AccessTokenAuthenticationResponse, RouterData}, router_data_v2::{self, RouterDataV2}, router_flow_types::{ - mandate_revoke::MandateRevoke, revenue_recovery::InvoiceRecordBack, AccessTokenAuth, - AccessTokenAuthentication, Authenticate, AuthenticationConfirmation, Authorize, - AuthorizeSessionToken, BillingConnectorInvoiceSync, BillingConnectorPaymentsSync, - CalculateTax, Capture, CompleteAuthorize, CreateConnectorCustomer, CreateOrder, Execute, - ExternalVaultProxy, IncrementalAuthorization, PSync, PaymentMethodToken, PostAuthenticate, - PostCaptureVoid, PostSessionTokens, PreAuthenticate, PreProcessing, RSync, - SdkSessionUpdate, Session, SetupMandate, UpdateMetadata, VerifyWebhookSource, Void, + mandate_revoke::MandateRevoke, revenue_recovery::InvoiceRecordBack, + subscriptions::GetSubscriptionPlans, AccessTokenAuth, AccessTokenAuthentication, + Authenticate, AuthenticationConfirmation, Authorize, AuthorizeSessionToken, + BillingConnectorInvoiceSync, BillingConnectorPaymentsSync, CalculateTax, Capture, + CompleteAuthorize, CreateConnectorCustomer, CreateOrder, Execute, ExternalVaultProxy, + IncrementalAuthorization, PSync, PaymentMethodToken, PostAuthenticate, PostCaptureVoid, + PostSessionTokens, PreAuthenticate, PreProcessing, RSync, SdkSessionUpdate, Session, + SetupMandate, UpdateMetadata, VerifyWebhookSource, Void, }, router_request_types::{ revenue_recovery::{ BillingConnectorInvoiceSyncRequest, BillingConnectorPaymentsSyncRequest, InvoiceRecordBackRequest, }, + subscriptions::GetSubscriptionPlansRequest, unified_authentication_service::{ UasAuthenticationRequestData, UasAuthenticationResponseData, UasConfirmationRequestData, UasPostAuthenticationRequestData, @@ -38,6 +40,7 @@ use crate::{ BillingConnectorInvoiceSyncResponse, BillingConnectorPaymentsSyncResponse, InvoiceRecordBackResponse, }, + subscriptions::GetSubscriptionPlansResponse, MandateRevokeResponseData, PaymentsResponseData, RefundsResponseData, TaxCalculationResponseData, VaultResponseData, VerifyWebhookSourceResponseData, }, @@ -124,6 +127,9 @@ pub type PayoutsRouterData = RouterData; pub type InvoiceRecordBackRouterData = RouterData; +pub type GetSubscriptionPlansRouterData = + RouterData; + pub type UasAuthenticationRouterData = RouterData; diff --git a/crates/hyperswitch_interfaces/src/api.rs b/crates/hyperswitch_interfaces/src/api.rs index c4d427a8f9..fe16681d4c 100644 --- a/crates/hyperswitch_interfaces/src/api.rs +++ b/crates/hyperswitch_interfaces/src/api.rs @@ -22,6 +22,8 @@ pub mod refunds; pub mod refunds_v2; pub mod revenue_recovery; pub mod revenue_recovery_v2; +pub mod subscriptions; +pub mod subscriptions_v2; pub mod vault; pub mod vault_v2; @@ -104,6 +106,7 @@ pub trait Connector: + UnifiedAuthenticationService + revenue_recovery::RevenueRecovery + ExternalVault + + subscriptions::Subscriptions { } @@ -126,7 +129,8 @@ impl< + TaxCalculation + UnifiedAuthenticationService + revenue_recovery::RevenueRecovery - + ExternalVault, + + ExternalVault + + subscriptions::Subscriptions, > Connector for T { } diff --git a/crates/hyperswitch_interfaces/src/api/subscriptions.rs b/crates/hyperswitch_interfaces/src/api/subscriptions.rs new file mode 100644 index 0000000000..a9e53ec560 --- /dev/null +++ b/crates/hyperswitch_interfaces/src/api/subscriptions.rs @@ -0,0 +1,33 @@ +//! Subscriptions Interface for V1 +#[cfg(feature = "v1")] +use hyperswitch_domain_models::{ + router_flow_types::subscriptions::GetSubscriptionPlans, + router_request_types::subscriptions::GetSubscriptionPlansRequest, + router_response_types::subscriptions::GetSubscriptionPlansResponse, +}; + +#[cfg(feature = "v1")] +use super::{ConnectorCommon, ConnectorIntegration}; + +#[cfg(feature = "v1")] +/// trait GetSubscriptionPlans for V1 +pub trait GetSubscriptionPlansFlow: + ConnectorIntegration< + GetSubscriptionPlans, + GetSubscriptionPlansRequest, + GetSubscriptionPlansResponse, +> +{ +} + +/// trait Subscriptions +#[cfg(feature = "v1")] +pub trait Subscriptions: ConnectorCommon + GetSubscriptionPlansFlow {} + +/// trait Subscriptions (disabled when not V1) +#[cfg(not(feature = "v1"))] +pub trait Subscriptions {} + +/// trait GetSubscriptionPlansFlow (disabled when not V1) +#[cfg(not(feature = "v1"))] +pub trait GetSubscriptionPlansFlow {} diff --git a/crates/hyperswitch_interfaces/src/api/subscriptions_v2.rs b/crates/hyperswitch_interfaces/src/api/subscriptions_v2.rs new file mode 100644 index 0000000000..5a37b013ef --- /dev/null +++ b/crates/hyperswitch_interfaces/src/api/subscriptions_v2.rs @@ -0,0 +1,23 @@ +//! SubscriptionsV2 +use hyperswitch_domain_models::{ + router_data_v2::flow_common_types::GetSubscriptionPlansData, + router_flow_types::subscriptions::GetSubscriptionPlans, + router_request_types::subscriptions::GetSubscriptionPlansRequest, + router_response_types::subscriptions::GetSubscriptionPlansResponse, +}; + +use crate::connector_integration_v2::ConnectorIntegrationV2; + +/// trait SubscriptionsV2 +pub trait SubscriptionsV2: GetSubscriptionPlansV2 {} + +/// trait GetSubscriptionPlans for V1 +pub trait GetSubscriptionPlansV2: + ConnectorIntegrationV2< + GetSubscriptionPlans, + GetSubscriptionPlansData, + GetSubscriptionPlansRequest, + GetSubscriptionPlansResponse, +> +{ +} diff --git a/crates/hyperswitch_interfaces/src/connector_integration_v2.rs b/crates/hyperswitch_interfaces/src/connector_integration_v2.rs index aa4bc72f61..1b870646dd 100644 --- a/crates/hyperswitch_interfaces/src/connector_integration_v2.rs +++ b/crates/hyperswitch_interfaces/src/connector_integration_v2.rs @@ -9,7 +9,7 @@ use masking::Maskable; use serde_json::json; use crate::{ - api::{self, CaptureSyncMethod}, + api::{self, subscriptions_v2, CaptureSyncMethod}, errors, events::connector_api_logs::ConnectorEvent, metrics, types, webhooks, @@ -35,6 +35,7 @@ pub trait ConnectorV2: + api::UnifiedAuthenticationServiceV2 + api::revenue_recovery_v2::RevenueRecoveryV2 + api::ExternalVaultV2 + + subscriptions_v2::SubscriptionsV2 { } impl< @@ -55,7 +56,8 @@ impl< + api::authentication_v2::ExternalAuthenticationV2 + api::UnifiedAuthenticationServiceV2 + api::revenue_recovery_v2::RevenueRecoveryV2 - + api::ExternalVaultV2, + + api::ExternalVaultV2 + + subscriptions_v2::SubscriptionsV2, > ConnectorV2 for T { } diff --git a/crates/hyperswitch_interfaces/src/conversion_impls.rs b/crates/hyperswitch_interfaces/src/conversion_impls.rs index d061217256..288ec0db95 100644 --- a/crates/hyperswitch_interfaces/src/conversion_impls.rs +++ b/crates/hyperswitch_interfaces/src/conversion_impls.rs @@ -11,9 +11,9 @@ use hyperswitch_domain_models::{ flow_common_types::{ AccessTokenFlowData, AuthenticationTokenFlowData, BillingConnectorInvoiceSyncFlowData, BillingConnectorPaymentsSyncFlowData, DisputesFlowData, ExternalAuthenticationFlowData, - ExternalVaultProxyFlowData, FilesFlowData, InvoiceRecordBackData, - MandateRevokeFlowData, PaymentFlowData, RefundFlowData, UasFlowData, - VaultConnectorFlowData, WebhookSourceVerifyData, + ExternalVaultProxyFlowData, FilesFlowData, GetSubscriptionPlansData, + InvoiceRecordBackData, MandateRevokeFlowData, PaymentFlowData, RefundFlowData, + UasFlowData, VaultConnectorFlowData, WebhookSourceVerifyData, }, RouterDataV2, }, @@ -796,6 +796,43 @@ impl RouterDataConversion for InvoiceR } } +impl RouterDataConversion for GetSubscriptionPlansData { + fn from_old_router_data( + old_router_data: &RouterData, + ) -> CustomResult, 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, + ) -> CustomResult, ConnectorError> + where + Self: Sized, + { + let router_data = get_default_router_data( + new_router_data.tenant_id.clone(), + "get_subscription_plans", + new_router_data.request, + new_router_data.response, + ); + Ok(RouterData { + connector_auth_type: new_router_data.connector_auth_type.clone(), + ..router_data + }) + } +} + impl RouterDataConversion for UasFlowData { fn from_old_router_data( old_router_data: &RouterData, diff --git a/crates/hyperswitch_interfaces/src/types.rs b/crates/hyperswitch_interfaces/src/types.rs index 2f0d77f7c4..e263735b8a 100644 --- a/crates/hyperswitch_interfaces/src/types.rs +++ b/crates/hyperswitch_interfaces/src/types.rs @@ -16,6 +16,7 @@ use hyperswitch_domain_models::{ }, refunds::{Execute, RSync}, revenue_recovery::{BillingConnectorPaymentsSync, InvoiceRecordBack}, + subscriptions::GetSubscriptionPlans, unified_authentication_service::{ Authenticate, AuthenticationConfirmation, PostAuthenticate, PreAuthenticate, }, @@ -31,6 +32,7 @@ use hyperswitch_domain_models::{ BillingConnectorInvoiceSyncRequest, BillingConnectorPaymentsSyncRequest, InvoiceRecordBackRequest, }, + subscriptions::GetSubscriptionPlansRequest, unified_authentication_service::{ UasAuthenticationRequestData, UasAuthenticationResponseData, UasConfirmationRequestData, UasPostAuthenticationRequestData, @@ -54,6 +56,7 @@ use hyperswitch_domain_models::{ BillingConnectorInvoiceSyncResponse, BillingConnectorPaymentsSyncResponse, InvoiceRecordBackResponse, }, + subscriptions::GetSubscriptionPlansResponse, AcceptDisputeResponse, DefendDisputeResponse, DisputeSyncResponse, FetchDisputesResponse, MandateRevokeResponseData, PaymentsResponseData, RefundsResponseData, RetrieveFileResponse, SubmitEvidenceResponse, TaxCalculationResponseData, UploadFileResponse, VaultResponseData, @@ -323,6 +326,13 @@ pub type BillingConnectorInvoiceSyncTypeV2 = dyn ConnectorIntegrationV2< BillingConnectorInvoiceSyncResponse, >; +/// Type alias for `ConnectorIntegration` +pub type GetSubscriptionPlansType = dyn ConnectorIntegration< + GetSubscriptionPlans, + GetSubscriptionPlansRequest, + GetSubscriptionPlansResponse, +>; + /// Type alias for `ConnectorIntegration` pub type ExternalVaultInsertType = dyn ConnectorIntegration; diff --git a/crates/router/src/core/connector_validation.rs b/crates/router/src/core/connector_validation.rs index 8df3036e35..5ff6937754 100644 --- a/crates/router/src/core/connector_validation.rs +++ b/crates/router/src/core/connector_validation.rs @@ -161,6 +161,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::Celero => { diff --git a/crates/router/src/services/api.rs b/crates/router/src/services/api.rs index 7d59a1cad3..2892830764 100644 --- a/crates/router/src/services/api.rs +++ b/crates/router/src/services/api.rs @@ -106,6 +106,8 @@ pub type BoxedFilesConnectorIntegrationInterface = BoxedConnectorIntegrationInterface; pub type BoxedRevenueRecoveryRecordBackInterface = BoxedConnectorIntegrationInterface; +pub type BoxedGetSubscriptionPlansInterface = + BoxedConnectorIntegrationInterface; pub type BoxedBillingConnectorInvoiceSyncIntegrationInterface = BoxedConnectorIntegrationInterface< T,