feat: Implement subscription create for Chargebee (#9303)

Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
This commit is contained in:
Gaurav Rawat
2025-09-19 19:03:31 +05:30
committed by GitHub
parent e29a121bfd
commit d978afdc5d
15 changed files with 455 additions and 31 deletions

View File

@ -16,30 +16,38 @@ use error_stack::ResultExt;
use hyperswitch_domain_models::{revenue_recovery, router_data_v2::RouterDataV2};
use hyperswitch_domain_models::{
router_data::{AccessToken, ConnectorAuthType, ErrorResponse, RouterData},
router_data_v2::flow_common_types::SubscriptionCreateData,
router_flow_types::{
access_token_auth::AccessTokenAuth,
payments::{Authorize, Capture, PSync, PaymentMethodToken, Session, SetupMandate, Void},
refunds::{Execute, RSync},
revenue_recovery::InvoiceRecordBack,
subscriptions::{GetSubscriptionPlanPrices, GetSubscriptionPlans},
subscriptions::{GetSubscriptionPlanPrices, GetSubscriptionPlans, SubscriptionCreate},
CreateConnectorCustomer,
},
router_request_types::{
revenue_recovery::InvoiceRecordBackRequest,
subscriptions::{GetSubscriptionPlanPricesRequest, GetSubscriptionPlansRequest},
subscriptions::{
GetSubscriptionPlanPricesRequest, GetSubscriptionPlansRequest,
SubscriptionCreateRequest,
},
AccessTokenRequestData, ConnectorCustomerData, PaymentMethodTokenizationData,
PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, PaymentsSessionData,
PaymentsSyncData, RefundsData, SetupMandateRequestData,
},
router_response_types::{
revenue_recovery::InvoiceRecordBackResponse,
subscriptions::{GetSubscriptionPlanPricesResponse, GetSubscriptionPlansResponse},
subscriptions::{
GetSubscriptionPlanPricesResponse, GetSubscriptionPlansResponse,
SubscriptionCreateResponse,
},
ConnectorInfo, PaymentsResponseData, RefundsResponseData,
},
types::{
ConnectorCustomerRouterData, GetSubscriptionPlanPricesRouterData,
GetSubscriptionPlansRouterData, InvoiceRecordBackRouterData, PaymentsAuthorizeRouterData,
PaymentsCaptureRouterData, PaymentsSyncRouterData, RefundSyncRouterData, RefundsRouterData,
SubscriptionCreateRouterData,
},
};
use hyperswitch_interfaces::{
@ -94,10 +102,117 @@ impl api::Refund for Chargebee {}
impl api::RefundExecute for Chargebee {}
impl api::RefundSync for Chargebee {}
impl api::PaymentToken for Chargebee {}
impl api::subscriptions::Subscriptions for Chargebee {}
#[cfg(all(feature = "v2", feature = "revenue_recovery"))]
impl api::revenue_recovery::RevenueRecoveryRecordBack for Chargebee {}
impl api::subscriptions::SubscriptionCreate for Chargebee {}
impl ConnectorIntegration<SubscriptionCreate, SubscriptionCreateRequest, SubscriptionCreateResponse>
for Chargebee
{
fn get_headers(
&self,
req: &SubscriptionCreateRouterData,
connectors: &Connectors,
) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
self.build_headers(req, connectors)
}
fn get_url(
&self,
req: &SubscriptionCreateRouterData,
connectors: &Connectors,
) -> CustomResult<String, errors::ConnectorError> {
let metadata: chargebee::ChargebeeMetadata =
utils::to_connector_meta_from_secret(req.connector_meta_data.clone())?;
let url = self
.base_url(connectors)
.to_string()
.replace("{{merchant_endpoint_prefix}}", metadata.site.peek());
let customer_id = &req.request.customer_id.get_string_repr().to_string();
Ok(format!(
"{url}v2/customers/{customer_id}/subscription_for_items"
))
}
fn get_content_type(&self) -> &'static str {
self.common_get_content_type()
}
fn get_request_body(
&self,
req: &SubscriptionCreateRouterData,
_connectors: &Connectors,
) -> CustomResult<RequestContent, errors::ConnectorError> {
let connector_router_data = chargebee::ChargebeeRouterData::from((MinorUnit::new(0), req));
let connector_req =
chargebee::ChargebeeSubscriptionCreateRequest::try_from(&connector_router_data)?;
Ok(RequestContent::FormUrlEncoded(Box::new(connector_req)))
}
fn build_request(
&self,
req: &SubscriptionCreateRouterData,
connectors: &Connectors,
) -> CustomResult<Option<Request>, errors::ConnectorError> {
Ok(Some(
RequestBuilder::new()
.method(Method::Post)
.url(&types::SubscriptionCreateType::get_url(
self, req, connectors,
)?)
.attach_default_headers()
.headers(types::SubscriptionCreateType::get_headers(
self, req, connectors,
)?)
.set_body(types::SubscriptionCreateType::get_request_body(
self, req, connectors,
)?)
.build(),
))
}
fn handle_response(
&self,
data: &SubscriptionCreateRouterData,
event_builder: Option<&mut ConnectorEvent>,
res: Response,
) -> CustomResult<SubscriptionCreateRouterData, errors::ConnectorError> {
let response: chargebee::ChargebeeSubscriptionCreateResponse = res
.response
.parse_struct("chargebee ChargebeeSubscriptionCreateResponse")
.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<ErrorResponse, errors::ConnectorError> {
self.build_error_response(res, event_builder)
}
}
impl
ConnectorIntegrationV2<
SubscriptionCreate,
SubscriptionCreateData,
SubscriptionCreateRequest,
SubscriptionCreateResponse,
> for Chargebee
{
// Not Implemented (R)
}
impl ConnectorIntegration<PaymentMethodToken, PaymentMethodTokenizationData, PaymentsResponseData>
for Chargebee
{
@ -689,7 +804,6 @@ fn get_chargebee_plans_query_params(
Ok(param)
}
impl api::subscriptions::Subscriptions for Chargebee {}
impl api::subscriptions::GetSubscriptionPlansFlow for Chargebee {}
impl

View File

@ -5,7 +5,7 @@ use common_enums::enums;
use common_utils::{
errors::CustomResult,
ext_traits::ByteSliceExt,
id_type::CustomerId,
id_type::{CustomerId, SubscriptionId},
pii::{self, Email},
types::MinorUnit,
};
@ -17,14 +17,20 @@ use hyperswitch_domain_models::{
router_data::{ConnectorAuthType, RouterData},
router_flow_types::{
refunds::{Execute, RSync},
subscriptions::SubscriptionCreate,
CreateConnectorCustomer, InvoiceRecordBack,
},
router_request_types::{
revenue_recovery::InvoiceRecordBackRequest, ConnectorCustomerData, ResponseId,
revenue_recovery::InvoiceRecordBackRequest,
subscriptions::{SubscriptionAutoCollection, SubscriptionCreateRequest},
ConnectorCustomerData, ResponseId,
},
router_response_types::{
revenue_recovery::InvoiceRecordBackResponse,
subscriptions::{self, GetSubscriptionPlanPricesResponse, GetSubscriptionPlansResponse},
subscriptions::{
self, GetSubscriptionPlanPricesResponse, GetSubscriptionPlansResponse,
SubscriptionCreateResponse, SubscriptionStatus,
},
ConnectorCustomerResponseData, PaymentsResponseData, RefundsResponseData,
},
types::{InvoiceRecordBackRouterData, PaymentsAuthorizeRouterData, RefundsRouterData},
@ -36,9 +42,158 @@ use time::PrimitiveDateTime;
use crate::{
types::{RefundsResponseRouterData, ResponseRouterData},
utils::{self, PaymentsAuthorizeRequestData},
utils::{self, PaymentsAuthorizeRequestData, RouterData as OtherRouterData},
};
// SubscriptionCreate structures
#[derive(Debug, Serialize)]
pub struct ChargebeeSubscriptionCreateRequest {
#[serde(rename = "id")]
pub subscription_id: SubscriptionId,
#[serde(rename = "subscription_items[item_price_id][0]")]
pub item_price_id: String,
#[serde(rename = "subscription_items[quantity][0]")]
pub quantity: Option<u32>,
#[serde(rename = "billing_address[line1]")]
pub billing_address_line1: Option<Secret<String>>,
#[serde(rename = "billing_address[city]")]
pub billing_address_city: Option<String>,
#[serde(rename = "billing_address[state]")]
pub billing_address_state: Option<Secret<String>>,
#[serde(rename = "billing_address[zip]")]
pub billing_address_zip: Option<Secret<String>>,
#[serde(rename = "billing_address[country]")]
pub billing_address_country: Option<common_enums::CountryAlpha2>,
pub auto_collection: ChargebeeAutoCollection,
}
#[derive(Debug, Deserialize, Serialize, Clone)]
#[serde(rename_all = "snake_case")]
pub enum ChargebeeAutoCollection {
On,
Off,
}
impl From<SubscriptionAutoCollection> for ChargebeeAutoCollection {
fn from(auto_collection: SubscriptionAutoCollection) -> Self {
match auto_collection {
SubscriptionAutoCollection::On => Self::On,
SubscriptionAutoCollection::Off => Self::Off,
}
}
}
impl TryFrom<&ChargebeeRouterData<&hyperswitch_domain_models::types::SubscriptionCreateRouterData>>
for ChargebeeSubscriptionCreateRequest
{
type Error = error_stack::Report<errors::ConnectorError>;
fn try_from(
item: &ChargebeeRouterData<&hyperswitch_domain_models::types::SubscriptionCreateRouterData>,
) -> Result<Self, Self::Error> {
let req = &item.router_data.request;
let first_item =
req.subscription_items
.first()
.ok_or(errors::ConnectorError::MissingRequiredField {
field_name: "subscription_items",
})?;
Ok(Self {
subscription_id: req.subscription_id.clone(),
item_price_id: first_item.item_price_id.clone(),
quantity: first_item.quantity,
billing_address_line1: item.router_data.get_optional_billing_line1(),
billing_address_city: item.router_data.get_optional_billing_city(),
billing_address_state: item.router_data.get_optional_billing_state(),
billing_address_zip: item.router_data.get_optional_billing_zip(),
billing_address_country: item.router_data.get_optional_billing_country(),
auto_collection: req.auto_collection.clone().into(),
})
}
}
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct ChargebeeSubscriptionCreateResponse {
pub subscription: ChargebeeSubscriptionDetails,
}
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct ChargebeeSubscriptionDetails {
pub id: SubscriptionId,
pub status: ChargebeeSubscriptionStatus,
pub customer_id: CustomerId,
pub currency_code: enums::Currency,
pub total_dues: Option<MinorUnit>,
#[serde(default, with = "common_utils::custom_serde::timestamp::option")]
pub next_billing_at: Option<PrimitiveDateTime>,
#[serde(default, with = "common_utils::custom_serde::timestamp::option")]
pub created_at: Option<PrimitiveDateTime>,
}
#[derive(Debug, Deserialize, Serialize, Clone)]
#[serde(rename_all = "snake_case")]
pub enum ChargebeeSubscriptionStatus {
Future,
#[serde(rename = "in_trial")]
InTrial,
Active,
#[serde(rename = "non_renewing")]
NonRenewing,
Paused,
Cancelled,
Transferred,
}
impl From<ChargebeeSubscriptionStatus> for SubscriptionStatus {
fn from(status: ChargebeeSubscriptionStatus) -> Self {
match status {
ChargebeeSubscriptionStatus::Future => Self::Pending,
ChargebeeSubscriptionStatus::InTrial => Self::Trial,
ChargebeeSubscriptionStatus::Active => Self::Active,
ChargebeeSubscriptionStatus::NonRenewing => Self::Onetime,
ChargebeeSubscriptionStatus::Paused => Self::Paused,
ChargebeeSubscriptionStatus::Cancelled => Self::Cancelled,
ChargebeeSubscriptionStatus::Transferred => Self::Cancelled,
}
}
}
impl
TryFrom<
ResponseRouterData<
SubscriptionCreate,
ChargebeeSubscriptionCreateResponse,
SubscriptionCreateRequest,
SubscriptionCreateResponse,
>,
> for hyperswitch_domain_models::types::SubscriptionCreateRouterData
{
type Error = error_stack::Report<errors::ConnectorError>;
fn try_from(
item: ResponseRouterData<
SubscriptionCreate,
ChargebeeSubscriptionCreateResponse,
SubscriptionCreateRequest,
SubscriptionCreateResponse,
>,
) -> Result<Self, Self::Error> {
let subscription = &item.response.subscription;
Ok(Self {
response: Ok(SubscriptionCreateResponse {
subscription_id: subscription.id.clone(),
status: subscription.status.clone().into(),
customer_id: subscription.customer_id.clone(),
currency_code: subscription.currency_code,
total_amount: subscription.total_dues.unwrap_or(MinorUnit::new(0)),
next_billing_at: subscription.next_billing_at,
created_at: subscription.created_at,
}),
..item.data
})
}
}
//TODO: Fill the struct with respective fields
pub struct ChargebeeRouterData<T> {
pub amount: MinorUnit, // The type of amount that a connector accepts, for example, String, i64, f64, etc.

View File

@ -10,17 +10,22 @@ use error_stack::ResultExt;
use hyperswitch_domain_models::{
router_data::{ConnectorAuthType, ErrorResponse},
router_data_v2::{
flow_common_types::{GetSubscriptionPlanPricesData, GetSubscriptionPlansData},
flow_common_types::{
GetSubscriptionPlanPricesData, GetSubscriptionPlansData, SubscriptionCreateData,
},
UasFlowData,
},
router_flow_types::{
subscriptions::{GetSubscriptionPlanPrices, GetSubscriptionPlans},
subscriptions::{GetSubscriptionPlanPrices, GetSubscriptionPlans, SubscriptionCreate},
unified_authentication_service::{
Authenticate, AuthenticationConfirmation, PostAuthenticate, PreAuthenticate,
},
},
router_request_types::{
subscriptions::{GetSubscriptionPlanPricesRequest, GetSubscriptionPlansRequest},
subscriptions::{
GetSubscriptionPlanPricesRequest, GetSubscriptionPlansRequest,
SubscriptionCreateRequest,
},
unified_authentication_service::{
UasAuthenticationRequestData, UasAuthenticationResponseData,
UasConfirmationRequestData, UasPostAuthenticationRequestData,
@ -28,7 +33,7 @@ use hyperswitch_domain_models::{
},
},
router_response_types::subscriptions::{
GetSubscriptionPlanPricesResponse, GetSubscriptionPlansResponse,
GetSubscriptionPlanPricesResponse, GetSubscriptionPlansResponse, SubscriptionCreateResponse,
},
};
#[cfg(all(feature = "v2", feature = "revenue_recovery"))]
@ -168,6 +173,16 @@ impl
> for Recurly
{
}
impl api::subscriptions_v2::SubscriptionsCreateV2 for Recurly {}
impl
ConnectorIntegrationV2<
SubscriptionCreate,
SubscriptionCreateData,
SubscriptionCreateRequest,
SubscriptionCreateResponse,
> for Recurly
{
}
#[cfg(all(feature = "v2", feature = "revenue_recovery"))]
impl api::revenue_recovery_v2::RevenueRecoveryRecordBackV2 for Recurly {}
#[cfg(all(feature = "v2", feature = "revenue_recovery"))]

View File

@ -44,10 +44,14 @@ use hyperswitch_domain_models::{
AccessTokenAuthentication, Authenticate, AuthenticationConfirmation,
ExternalVaultCreateFlow, ExternalVaultDeleteFlow, ExternalVaultInsertFlow,
ExternalVaultProxy, ExternalVaultRetrieveFlow, PostAuthenticate, PreAuthenticate,
SubscriptionCreate as SubscriptionCreateFlow,
},
router_request_types::{
authentication,
subscriptions::{GetSubscriptionPlanPricesRequest, GetSubscriptionPlansRequest},
subscriptions::{
GetSubscriptionPlanPricesRequest, GetSubscriptionPlansRequest,
SubscriptionCreateRequest,
},
unified_authentication_service::{
UasAuthenticationRequestData, UasAuthenticationResponseData,
UasConfirmationRequestData, UasPostAuthenticationRequestData,
@ -66,7 +70,10 @@ use hyperswitch_domain_models::{
VerifyWebhookSourceRequestData,
},
router_response_types::{
subscriptions::{GetSubscriptionPlanPricesResponse, GetSubscriptionPlansResponse},
subscriptions::{
GetSubscriptionPlanPricesResponse, GetSubscriptionPlansResponse,
SubscriptionCreateResponse,
},
AcceptDisputeResponse, AuthenticationResponseData, DefendDisputeResponse,
DisputeSyncResponse, FetchDisputesResponse, GiftCardBalanceCheckResponseData,
MandateRevokeResponseData, PaymentsResponseData, RetrieveFileResponse,
@ -130,7 +137,10 @@ use hyperswitch_interfaces::{
PaymentsPreAuthenticate, PaymentsPreProcessing, TaxCalculation,
},
revenue_recovery::RevenueRecovery,
subscriptions::{GetSubscriptionPlanPricesFlow, GetSubscriptionPlansFlow, Subscriptions},
subscriptions::{
GetSubscriptionPlanPricesFlow, GetSubscriptionPlansFlow, SubscriptionCreate,
Subscriptions,
},
vault::{
ExternalVault, ExternalVaultCreate, ExternalVaultDelete, ExternalVaultInsert,
ExternalVaultRetrieve,
@ -6941,6 +6951,7 @@ macro_rules! default_imp_for_subscriptions {
($($path:ident::$connector:ident),*) => {
$( impl Subscriptions for $path::$connector {}
impl GetSubscriptionPlansFlow for $path::$connector {}
impl SubscriptionCreate for $path::$connector {}
impl
ConnectorIntegration<
GetSubscriptionPlans,
@ -6956,6 +6967,12 @@ macro_rules! default_imp_for_subscriptions {
GetSubscriptionPlanPricesResponse
> for $path::$connector
{}
impl
ConnectorIntegration<
SubscriptionCreateFlow,
SubscriptionCreateRequest,
SubscriptionCreateResponse,
> for $path::$connector {}
)*
};
}
@ -9253,3 +9270,16 @@ impl<const T: u8>
> for connectors::DummyConnector<T>
{
}
#[cfg(feature = "dummy_connector")]
impl<const T: u8> SubscriptionCreate for connectors::DummyConnector<T> {}
#[cfg(feature = "dummy_connector")]
impl<const T: u8>
ConnectorIntegration<
SubscriptionCreateFlow,
SubscriptionCreateRequest,
SubscriptionCreateResponse,
> for connectors::DummyConnector<T>
{
}

View File

@ -150,6 +150,9 @@ pub struct FilesFlowData {
#[derive(Debug, Clone)]
pub struct InvoiceRecordBackData;
#[derive(Debug, Clone)]
pub struct SubscriptionCreateData;
#[derive(Debug, Clone)]
pub struct GetSubscriptionPlansData;

View File

@ -20,6 +20,7 @@ pub use payments::*;
pub use payouts::*;
pub use refunds::*;
pub use revenue_recovery::*;
pub use subscriptions::*;
pub use unified_authentication_service::*;
pub use vault::*;
pub use webhooks::*;

View File

@ -1,4 +1,6 @@
#[derive(Debug, Clone)]
pub struct SubscriptionCreate;
#[derive(Debug, Clone)]
pub struct GetSubscriptionPlans;
#[derive(Debug, Clone)]

View File

@ -1,3 +1,28 @@
use api_models::payments::Address;
use common_utils::id_type;
use crate::connector_endpoints;
#[derive(Debug, Clone)]
pub struct SubscriptionItem {
pub item_price_id: String,
pub quantity: Option<u32>,
}
#[derive(Debug, Clone)]
pub struct SubscriptionCreateRequest {
pub customer_id: id_type::CustomerId,
pub subscription_id: id_type::SubscriptionId,
pub subscription_items: Vec<SubscriptionItem>,
pub billing_address: Address,
pub auto_collection: SubscriptionAutoCollection,
pub connector_params: connector_endpoints::ConnectorParams,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SubscriptionAutoCollection {
On,
Off,
}
#[derive(Debug, Clone)]
pub struct GetSubscriptionPlansRequest {
pub limit: Option<u32>,

View File

@ -1,4 +1,29 @@
use common_enums::Currency;
use common_utils::{id_type, types::MinorUnit};
use time::PrimitiveDateTime;
#[derive(Debug, Clone)]
pub struct SubscriptionCreateResponse {
pub subscription_id: id_type::SubscriptionId,
pub status: SubscriptionStatus,
pub customer_id: id_type::CustomerId,
pub currency_code: Currency,
pub total_amount: MinorUnit,
pub next_billing_at: Option<PrimitiveDateTime>,
pub created_at: Option<PrimitiveDateTime>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SubscriptionStatus {
Pending,
Trial,
Active,
Paused,
Unpaid,
Onetime,
Cancelled,
Failed,
}
#[derive(Debug, Clone)]
pub struct GetSubscriptionPlansResponse {
@ -21,7 +46,7 @@ pub struct GetSubscriptionPlanPricesResponse {
pub struct SubscriptionPlanPrices {
pub price_id: String,
pub plan_id: Option<String>,
pub amount: common_utils::types::MinorUnit,
pub amount: MinorUnit,
pub currency: Currency,
pub interval: PeriodUnit,
pub interval_count: i64,

View File

@ -6,7 +6,7 @@ use crate::{
router_flow_types::{
mandate_revoke::MandateRevoke,
revenue_recovery::InvoiceRecordBack,
subscriptions::{GetSubscriptionPlanPrices, GetSubscriptionPlans},
subscriptions::{GetSubscriptionPlanPrices, GetSubscriptionPlans, SubscriptionCreate},
AccessTokenAuth, AccessTokenAuthentication, Authenticate, AuthenticationConfirmation,
Authorize, AuthorizeSessionToken, BillingConnectorInvoiceSync,
BillingConnectorPaymentsSync, CalculateTax, Capture, CompleteAuthorize,
@ -20,7 +20,10 @@ use crate::{
BillingConnectorInvoiceSyncRequest, BillingConnectorPaymentsSyncRequest,
InvoiceRecordBackRequest,
},
subscriptions::{GetSubscriptionPlanPricesRequest, GetSubscriptionPlansRequest},
subscriptions::{
GetSubscriptionPlanPricesRequest, GetSubscriptionPlansRequest,
SubscriptionCreateRequest,
},
unified_authentication_service::{
UasAuthenticationRequestData, UasAuthenticationResponseData,
UasConfirmationRequestData, UasPostAuthenticationRequestData,
@ -42,7 +45,10 @@ use crate::{
BillingConnectorInvoiceSyncResponse, BillingConnectorPaymentsSyncResponse,
InvoiceRecordBackResponse,
},
subscriptions::{GetSubscriptionPlanPricesResponse, GetSubscriptionPlansResponse},
subscriptions::{
GetSubscriptionPlanPricesResponse, GetSubscriptionPlansResponse,
SubscriptionCreateResponse,
},
GiftCardBalanceCheckResponseData, MandateRevokeResponseData, PaymentsResponseData,
RefundsResponseData, TaxCalculationResponseData, VaultResponseData,
VerifyWebhookSourceResponseData,
@ -195,3 +201,6 @@ pub type ExternalVaultProxyPaymentsRouterDataV2 = RouterDataV2<
ExternalVaultProxyPaymentsData,
PaymentsResponseData,
>;
pub type SubscriptionCreateRouterData =
RouterData<SubscriptionCreate, SubscriptionCreateRequest, SubscriptionCreateResponse>;

View File

@ -1,12 +1,13 @@
//! Subscriptions Interface for V1
#[cfg(feature = "v1")]
use hyperswitch_domain_models::{
router_flow_types::subscriptions::SubscriptionCreate as SubscriptionCreateFlow,
router_flow_types::subscriptions::{GetSubscriptionPlanPrices, GetSubscriptionPlans},
router_request_types::subscriptions::{
GetSubscriptionPlanPricesRequest, GetSubscriptionPlansRequest,
GetSubscriptionPlanPricesRequest, GetSubscriptionPlansRequest, SubscriptionCreateRequest,
},
router_response_types::subscriptions::{
GetSubscriptionPlanPricesResponse, GetSubscriptionPlansResponse,
GetSubscriptionPlanPricesResponse, GetSubscriptionPlansResponse, SubscriptionCreateResponse,
},
};
@ -37,12 +38,20 @@ pub trait GetSubscriptionPlanPricesFlow:
{
}
#[cfg(feature = "v1")]
/// trait SubscriptionCreate
pub trait SubscriptionCreate:
ConnectorIntegration<SubscriptionCreateFlow, SubscriptionCreateRequest, SubscriptionCreateResponse>
{
}
/// trait Subscriptions
#[cfg(feature = "v1")]
pub trait Subscriptions:
ConnectorCommon
+ GetSubscriptionPlansFlow
+ GetSubscriptionPlanPricesFlow
+ SubscriptionCreate
+ PaymentsConnectorCustomer
{
}
@ -62,3 +71,7 @@ pub trait GetSubscriptionPlanPricesFlow {}
#[cfg(not(feature = "v1"))]
/// trait CreateCustomer (disabled when not V1)
pub trait ConnectorCustomer {}
/// trait SubscriptionCreate
#[cfg(not(feature = "v1"))]
pub trait SubscriptionCreate {}

View File

@ -1,12 +1,16 @@
//! SubscriptionsV2
use hyperswitch_domain_models::{
router_data_v2::flow_common_types::{GetSubscriptionPlanPricesData, GetSubscriptionPlansData},
router_flow_types::subscriptions::{GetSubscriptionPlanPrices, GetSubscriptionPlans},
router_data_v2::flow_common_types::{
GetSubscriptionPlanPricesData, GetSubscriptionPlansData, SubscriptionCreateData,
},
router_flow_types::subscriptions::{
GetSubscriptionPlanPrices, GetSubscriptionPlans, SubscriptionCreate,
},
router_request_types::subscriptions::{
GetSubscriptionPlanPricesRequest, GetSubscriptionPlansRequest,
GetSubscriptionPlanPricesRequest, GetSubscriptionPlansRequest, SubscriptionCreateRequest,
},
router_response_types::subscriptions::{
GetSubscriptionPlanPricesResponse, GetSubscriptionPlansResponse,
GetSubscriptionPlanPricesResponse, GetSubscriptionPlansResponse, SubscriptionCreateResponse,
},
};
@ -15,7 +19,7 @@ use crate::connector_integration_v2::ConnectorIntegrationV2;
/// trait SubscriptionsV2
pub trait SubscriptionsV2:
GetSubscriptionPlansV2 + ConnectorCustomerV2 + GetSubscriptionPlanPricesV2
GetSubscriptionPlansV2 + SubscriptionsCreateV2 + ConnectorCustomerV2 + GetSubscriptionPlanPricesV2
{
}
@ -40,3 +44,14 @@ pub trait GetSubscriptionPlanPricesV2:
>
{
}
/// trait SubscriptionsCreateV2
pub trait SubscriptionsCreateV2:
ConnectorIntegrationV2<
SubscriptionCreate,
SubscriptionCreateData,
SubscriptionCreateRequest,
SubscriptionCreateResponse,
>
{
}

View File

@ -13,8 +13,8 @@ use hyperswitch_domain_models::{
BillingConnectorPaymentsSyncFlowData, DisputesFlowData, ExternalAuthenticationFlowData,
ExternalVaultProxyFlowData, FilesFlowData, GetSubscriptionPlanPricesData,
GetSubscriptionPlansData, GiftCardBalanceCheckFlowData, InvoiceRecordBackData,
MandateRevokeFlowData, PaymentFlowData, RefundFlowData, UasFlowData,
VaultConnectorFlowData, WebhookSourceVerifyData,
MandateRevokeFlowData, PaymentFlowData, RefundFlowData, SubscriptionCreateData,
UasFlowData, VaultConnectorFlowData, WebhookSourceVerifyData,
},
RouterDataV2,
},
@ -878,6 +878,7 @@ macro_rules! default_router_data_conversion {
}
default_router_data_conversion!(GetSubscriptionPlansData);
default_router_data_conversion!(GetSubscriptionPlanPricesData);
default_router_data_conversion!(SubscriptionCreateData);
impl<T, Req: Clone, Resp: Clone> RouterDataConversion<T, Req, Resp> for UasFlowData {
fn from_old_router_data(

View File

@ -16,7 +16,7 @@ use hyperswitch_domain_models::{
},
refunds::{Execute, RSync},
revenue_recovery::{BillingConnectorPaymentsSync, InvoiceRecordBack},
subscriptions::{GetSubscriptionPlanPrices, GetSubscriptionPlans},
subscriptions::{GetSubscriptionPlanPrices, GetSubscriptionPlans, SubscriptionCreate},
unified_authentication_service::{
Authenticate, AuthenticationConfirmation, PostAuthenticate, PreAuthenticate,
},
@ -32,7 +32,10 @@ use hyperswitch_domain_models::{
BillingConnectorInvoiceSyncRequest, BillingConnectorPaymentsSyncRequest,
InvoiceRecordBackRequest,
},
subscriptions::{GetSubscriptionPlanPricesRequest, GetSubscriptionPlansRequest},
subscriptions::{
GetSubscriptionPlanPricesRequest, GetSubscriptionPlansRequest,
SubscriptionCreateRequest,
},
unified_authentication_service::{
UasAuthenticationRequestData, UasAuthenticationResponseData,
UasConfirmationRequestData, UasPostAuthenticationRequestData,
@ -57,7 +60,10 @@ use hyperswitch_domain_models::{
BillingConnectorInvoiceSyncResponse, BillingConnectorPaymentsSyncResponse,
InvoiceRecordBackResponse,
},
subscriptions::{GetSubscriptionPlanPricesResponse, GetSubscriptionPlansResponse},
subscriptions::{
GetSubscriptionPlanPricesResponse, GetSubscriptionPlansResponse,
SubscriptionCreateResponse,
},
AcceptDisputeResponse, DefendDisputeResponse, DisputeSyncResponse, FetchDisputesResponse,
GiftCardBalanceCheckResponseData, MandateRevokeResponseData, PaymentsResponseData,
RefundsResponseData, RetrieveFileResponse, SubmitEvidenceResponse,
@ -303,6 +309,13 @@ pub type InvoiceRecordBackType = dyn ConnectorIntegration<
InvoiceRecordBackResponse,
>;
/// Type alias for `ConnectorIntegration<SubscriptionCreate, SubscriptionCreateRequest, SubscriptionCreateResponse>`
pub type SubscriptionCreateType = dyn ConnectorIntegration<
SubscriptionCreate,
SubscriptionCreateRequest,
SubscriptionCreateResponse,
>;
/// Type alias for `ConnectorIntegration<BillingConnectorPaymentsSync, BillingConnectorPaymentsSyncRequest, BillingConnectorPaymentsSyncResponse>`
pub type BillingConnectorPaymentsSyncType = dyn ConnectorIntegration<
BillingConnectorPaymentsSync,

View File

@ -211,6 +211,9 @@ where
Ok(())
}
pub type BoxedSubscriptionConnectorIntegrationInterface<T, Req, Res> =
BoxedConnectorIntegrationInterface<T, common_types::SubscriptionCreateData, Req, Res>;
/// Handle the flow by interacting with connector module
/// `connector_request` is applicable only in case if the `CallConnectorAction` is `Trigger`
/// In other cases, It will be created if required, even if it is not passed