mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-27 19:46:48 +08:00
feat(subscription): Add endpoint to get Subscription estimate (#9637)
Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Co-authored-by: Gaurav Rawat <104276743+GauravRawat369@users.noreply.github.com>
This commit is contained in:
@ -44,7 +44,6 @@ pub mod relay;
|
|||||||
#[cfg(feature = "v2")]
|
#[cfg(feature = "v2")]
|
||||||
pub mod revenue_recovery_data_backfill;
|
pub mod revenue_recovery_data_backfill;
|
||||||
pub mod routing;
|
pub mod routing;
|
||||||
#[cfg(feature = "v1")]
|
|
||||||
pub mod subscription;
|
pub mod subscription;
|
||||||
pub mod surcharge_decision_configs;
|
pub mod surcharge_decision_configs;
|
||||||
pub mod three_ds_decision_rule;
|
pub mod three_ds_decision_rule;
|
||||||
|
|||||||
@ -446,3 +446,52 @@ pub struct Invoice {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ApiEventMetric for ConfirmSubscriptionResponse {}
|
impl ApiEventMetric for ConfirmSubscriptionResponse {}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
|
||||||
|
pub struct EstimateSubscriptionQuery {
|
||||||
|
/// Identifier for the associated subscription plan.
|
||||||
|
pub plan_id: Option<String>,
|
||||||
|
|
||||||
|
/// Identifier for the associated item_price_id for the subscription.
|
||||||
|
pub item_price_id: String,
|
||||||
|
|
||||||
|
/// Idenctifier for the coupon code for the subscription.
|
||||||
|
pub coupon_code: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ApiEventMetric for EstimateSubscriptionQuery {}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, serde::Serialize, ToSchema)]
|
||||||
|
pub struct EstimateSubscriptionResponse {
|
||||||
|
/// Estimated amount to be charged for the invoice.
|
||||||
|
pub amount: MinorUnit,
|
||||||
|
/// Currency for the amount.
|
||||||
|
pub currency: api_enums::Currency,
|
||||||
|
/// Identifier for the associated plan_id.
|
||||||
|
pub plan_id: Option<String>,
|
||||||
|
/// Identifier for the associated item_price_id for the subscription.
|
||||||
|
pub item_price_id: Option<String>,
|
||||||
|
/// Idenctifier for the coupon code for the subscription.
|
||||||
|
pub coupon_code: Option<String>,
|
||||||
|
/// Identifier for customer.
|
||||||
|
pub customer_id: Option<common_utils::id_type::CustomerId>,
|
||||||
|
pub line_items: Vec<SubscriptionLineItem>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, serde::Serialize, ToSchema)]
|
||||||
|
pub struct SubscriptionLineItem {
|
||||||
|
/// Unique identifier for the line item.
|
||||||
|
pub item_id: String,
|
||||||
|
/// Type of the line item.
|
||||||
|
pub item_type: String,
|
||||||
|
/// Description of the line item.
|
||||||
|
pub description: String,
|
||||||
|
/// Amount for the line item.
|
||||||
|
pub amount: MinorUnit,
|
||||||
|
/// Currency for the line item
|
||||||
|
pub currency: common_enums::Currency,
|
||||||
|
/// Quantity of the line item.
|
||||||
|
pub quantity: i64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ApiEventMetric for EstimateSubscriptionResponse {}
|
||||||
|
|||||||
@ -1212,11 +1212,26 @@ impl
|
|||||||
) -> CustomResult<String, errors::ConnectorError> {
|
) -> CustomResult<String, errors::ConnectorError> {
|
||||||
let metadata: chargebee::ChargebeeMetadata =
|
let metadata: chargebee::ChargebeeMetadata =
|
||||||
utils::to_connector_meta_from_secret(req.connector_meta_data.clone())?;
|
utils::to_connector_meta_from_secret(req.connector_meta_data.clone())?;
|
||||||
let url = self
|
|
||||||
.base_url(connectors)
|
let site = metadata.site.peek();
|
||||||
.to_string()
|
|
||||||
.replace("{{merchant_endpoint_prefix}}", metadata.site.peek());
|
let mut base = self.base_url(connectors).to_string();
|
||||||
Ok(format!("{url}v2/estimates/create_subscription_for_items"))
|
|
||||||
|
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('/');
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(format!("{base}v2/estimates/create_subscription_for_items"))
|
||||||
}
|
}
|
||||||
fn get_content_type(&self) -> &'static str {
|
fn get_content_type(&self) -> &'static str {
|
||||||
self.common_get_content_type()
|
self.common_get_content_type()
|
||||||
|
|||||||
@ -1036,6 +1036,7 @@ impl<F, T>
|
|||||||
currency: estimate.subscription_estimate.currency_code,
|
currency: estimate.subscription_estimate.currency_code,
|
||||||
next_billing_at: estimate.subscription_estimate.next_billing_at,
|
next_billing_at: estimate.subscription_estimate.next_billing_at,
|
||||||
credits_applied: Some(estimate.invoice_estimate.credits_applied),
|
credits_applied: Some(estimate.invoice_estimate.credits_applied),
|
||||||
|
customer_id: Some(estimate.invoice_estimate.customer_id),
|
||||||
line_items: estimate
|
line_items: estimate
|
||||||
.invoice_estimate
|
.invoice_estimate
|
||||||
.line_items
|
.line_items
|
||||||
@ -1215,6 +1216,7 @@ impl
|
|||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct ChargebeeSubscriptionEstimateRequest {
|
pub struct ChargebeeSubscriptionEstimateRequest {
|
||||||
|
#[serde(rename = "subscription_items[item_price_id][0]")]
|
||||||
pub price_id: String,
|
pub price_id: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1351,8 +1353,8 @@ pub struct SubscriptionEstimate {
|
|||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct InvoiceEstimate {
|
pub struct InvoiceEstimate {
|
||||||
pub recurring: bool,
|
pub recurring: bool,
|
||||||
#[serde(with = "common_utils::custom_serde::iso8601")]
|
#[serde(default, with = "common_utils::custom_serde::timestamp::option")]
|
||||||
pub date: PrimitiveDateTime,
|
pub date: Option<PrimitiveDateTime>,
|
||||||
pub price_type: String,
|
pub price_type: String,
|
||||||
pub sub_total: MinorUnit,
|
pub sub_total: MinorUnit,
|
||||||
pub total: MinorUnit,
|
pub total: MinorUnit,
|
||||||
@ -1361,7 +1363,7 @@ pub struct InvoiceEstimate {
|
|||||||
pub amount_due: MinorUnit,
|
pub amount_due: MinorUnit,
|
||||||
/// type of the object will be `invoice_estimate`
|
/// type of the object will be `invoice_estimate`
|
||||||
pub object: String,
|
pub object: String,
|
||||||
pub customer_id: String,
|
pub customer_id: CustomerId,
|
||||||
pub line_items: Vec<LineItem>,
|
pub line_items: Vec<LineItem>,
|
||||||
pub currency_code: enums::Currency,
|
pub currency_code: enums::Currency,
|
||||||
pub round_off_amount: MinorUnit,
|
pub round_off_amount: MinorUnit,
|
||||||
@ -1370,10 +1372,10 @@ pub struct InvoiceEstimate {
|
|||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct LineItem {
|
pub struct LineItem {
|
||||||
pub id: String,
|
pub id: String,
|
||||||
#[serde(with = "common_utils::custom_serde::iso8601")]
|
#[serde(default, with = "common_utils::custom_serde::timestamp::option")]
|
||||||
pub date_from: PrimitiveDateTime,
|
pub date_from: Option<PrimitiveDateTime>,
|
||||||
#[serde(with = "common_utils::custom_serde::iso8601")]
|
#[serde(default, with = "common_utils::custom_serde::timestamp::option")]
|
||||||
pub date_to: PrimitiveDateTime,
|
pub date_to: Option<PrimitiveDateTime>,
|
||||||
pub unit_amount: MinorUnit,
|
pub unit_amount: MinorUnit,
|
||||||
pub quantity: i64,
|
pub quantity: i64,
|
||||||
pub amount: MinorUnit,
|
pub amount: MinorUnit,
|
||||||
|
|||||||
@ -174,7 +174,9 @@ pub struct GetSubscriptionPlanPricesData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct GetSubscriptionEstimateData;
|
pub struct GetSubscriptionEstimateData {
|
||||||
|
pub connector_meta_data: Option<pii::SecretSerdeValue>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct UasFlowData {
|
pub struct UasFlowData {
|
||||||
|
|||||||
@ -36,7 +36,6 @@ pub enum SubscriptionStatus {
|
|||||||
Created,
|
Created,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "v1")]
|
|
||||||
impl From<SubscriptionStatus> for api_models::subscription::SubscriptionStatus {
|
impl From<SubscriptionStatus> for api_models::subscription::SubscriptionStatus {
|
||||||
fn from(status: SubscriptionStatus) -> Self {
|
fn from(status: SubscriptionStatus) -> Self {
|
||||||
match status {
|
match status {
|
||||||
@ -82,7 +81,6 @@ pub struct SubscriptionPlanPrices {
|
|||||||
pub trial_period_unit: Option<PeriodUnit>,
|
pub trial_period_unit: Option<PeriodUnit>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "v1")]
|
|
||||||
impl From<SubscriptionPlanPrices> for api_models::subscription::SubscriptionPlanPrices {
|
impl From<SubscriptionPlanPrices> for api_models::subscription::SubscriptionPlanPrices {
|
||||||
fn from(item: SubscriptionPlanPrices) -> Self {
|
fn from(item: SubscriptionPlanPrices) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@ -106,7 +104,6 @@ pub enum PeriodUnit {
|
|||||||
Year,
|
Year,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "v1")]
|
|
||||||
impl From<PeriodUnit> for api_models::subscription::PeriodUnit {
|
impl From<PeriodUnit> for api_models::subscription::PeriodUnit {
|
||||||
fn from(unit: PeriodUnit) -> Self {
|
fn from(unit: PeriodUnit) -> Self {
|
||||||
match unit {
|
match unit {
|
||||||
@ -128,8 +125,28 @@ pub struct GetSubscriptionEstimateResponse {
|
|||||||
pub currency: Currency,
|
pub currency: Currency,
|
||||||
pub next_billing_at: Option<PrimitiveDateTime>,
|
pub next_billing_at: Option<PrimitiveDateTime>,
|
||||||
pub line_items: Vec<SubscriptionLineItem>,
|
pub line_items: Vec<SubscriptionLineItem>,
|
||||||
|
pub customer_id: Option<id_type::CustomerId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<GetSubscriptionEstimateResponse>
|
||||||
|
for api_models::subscription::EstimateSubscriptionResponse
|
||||||
|
{
|
||||||
|
fn from(value: GetSubscriptionEstimateResponse) -> Self {
|
||||||
|
Self {
|
||||||
|
amount: value.total,
|
||||||
|
currency: value.currency,
|
||||||
|
plan_id: None,
|
||||||
|
item_price_id: None,
|
||||||
|
coupon_code: None,
|
||||||
|
customer_id: value.customer_id,
|
||||||
|
line_items: value
|
||||||
|
.line_items
|
||||||
|
.into_iter()
|
||||||
|
.map(api_models::subscription::SubscriptionLineItem::from)
|
||||||
|
.collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct SubscriptionLineItem {
|
pub struct SubscriptionLineItem {
|
||||||
pub item_id: String,
|
pub item_id: String,
|
||||||
@ -141,3 +158,16 @@ pub struct SubscriptionLineItem {
|
|||||||
pub quantity: i64,
|
pub quantity: i64,
|
||||||
pub pricing_model: Option<String>,
|
pub pricing_model: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<SubscriptionLineItem> for api_models::subscription::SubscriptionLineItem {
|
||||||
|
fn from(value: SubscriptionLineItem) -> Self {
|
||||||
|
Self {
|
||||||
|
item_id: value.item_id,
|
||||||
|
description: value.description,
|
||||||
|
item_type: value.item_type,
|
||||||
|
amount: value.amount,
|
||||||
|
currency: value.currency,
|
||||||
|
quantity: value.quantity,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -11,10 +11,11 @@ use hyperswitch_domain_models::{
|
|||||||
flow_common_types::{
|
flow_common_types::{
|
||||||
AccessTokenFlowData, AuthenticationTokenFlowData, BillingConnectorInvoiceSyncFlowData,
|
AccessTokenFlowData, AuthenticationTokenFlowData, BillingConnectorInvoiceSyncFlowData,
|
||||||
BillingConnectorPaymentsSyncFlowData, DisputesFlowData, ExternalAuthenticationFlowData,
|
BillingConnectorPaymentsSyncFlowData, DisputesFlowData, ExternalAuthenticationFlowData,
|
||||||
ExternalVaultProxyFlowData, FilesFlowData, GetSubscriptionPlanPricesData,
|
ExternalVaultProxyFlowData, FilesFlowData, GetSubscriptionEstimateData,
|
||||||
GetSubscriptionPlansData, GiftCardBalanceCheckFlowData, InvoiceRecordBackData,
|
GetSubscriptionPlanPricesData, GetSubscriptionPlansData, GiftCardBalanceCheckFlowData,
|
||||||
MandateRevokeFlowData, PaymentFlowData, RefundFlowData, SubscriptionCreateData,
|
InvoiceRecordBackData, MandateRevokeFlowData, PaymentFlowData, RefundFlowData,
|
||||||
SubscriptionCustomerData, UasFlowData, VaultConnectorFlowData, WebhookSourceVerifyData,
|
SubscriptionCreateData, SubscriptionCustomerData, UasFlowData, VaultConnectorFlowData,
|
||||||
|
WebhookSourceVerifyData,
|
||||||
},
|
},
|
||||||
RouterDataV2,
|
RouterDataV2,
|
||||||
},
|
},
|
||||||
@ -895,6 +896,7 @@ default_router_data_conversion!(GetSubscriptionPlansData);
|
|||||||
default_router_data_conversion!(GetSubscriptionPlanPricesData);
|
default_router_data_conversion!(GetSubscriptionPlanPricesData);
|
||||||
default_router_data_conversion!(SubscriptionCreateData);
|
default_router_data_conversion!(SubscriptionCreateData);
|
||||||
default_router_data_conversion!(SubscriptionCustomerData);
|
default_router_data_conversion!(SubscriptionCustomerData);
|
||||||
|
default_router_data_conversion!(GetSubscriptionEstimateData);
|
||||||
|
|
||||||
impl<T, Req: Clone, Resp: Clone> RouterDataConversion<T, Req, Resp> for UasFlowData {
|
impl<T, Req: Clone, Resp: Clone> RouterDataConversion<T, Req, Resp> for UasFlowData {
|
||||||
fn from_old_router_data(
|
fn from_old_router_data(
|
||||||
|
|||||||
@ -422,3 +422,27 @@ pub async fn get_subscription(
|
|||||||
subscription.to_subscription_response(),
|
subscription.to_subscription_response(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn get_estimate(
|
||||||
|
state: SessionState,
|
||||||
|
merchant_context: MerchantContext,
|
||||||
|
profile_id: common_utils::id_type::ProfileId,
|
||||||
|
query: subscription_types::EstimateSubscriptionQuery,
|
||||||
|
) -> RouterResponse<subscription_types::EstimateSubscriptionResponse> {
|
||||||
|
let profile =
|
||||||
|
SubscriptionHandler::find_business_profile(&state, &merchant_context, &profile_id)
|
||||||
|
.await
|
||||||
|
.attach_printable("subscriptions: failed to find business profile in get_estimate")?;
|
||||||
|
let billing_handler = BillingHandler::create(
|
||||||
|
&state,
|
||||||
|
merchant_context.get_merchant_account(),
|
||||||
|
merchant_context.get_merchant_key_store(),
|
||||||
|
None,
|
||||||
|
profile,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
let estimate = billing_handler
|
||||||
|
.get_subscription_estimate(&state, query)
|
||||||
|
.await?;
|
||||||
|
Ok(ApplicationResponse::Json(estimate.into()))
|
||||||
|
}
|
||||||
|
|||||||
@ -5,8 +5,8 @@ use common_utils::{ext_traits::ValueExt, pii};
|
|||||||
use error_stack::ResultExt;
|
use error_stack::ResultExt;
|
||||||
use hyperswitch_domain_models::{
|
use hyperswitch_domain_models::{
|
||||||
router_data_v2::flow_common_types::{
|
router_data_v2::flow_common_types::{
|
||||||
GetSubscriptionPlanPricesData, GetSubscriptionPlansData, InvoiceRecordBackData,
|
GetSubscriptionEstimateData, GetSubscriptionPlanPricesData, GetSubscriptionPlansData,
|
||||||
SubscriptionCreateData, SubscriptionCustomerData,
|
InvoiceRecordBackData, SubscriptionCreateData, SubscriptionCustomerData,
|
||||||
},
|
},
|
||||||
router_request_types::{
|
router_request_types::{
|
||||||
revenue_recovery::InvoiceRecordBackRequest, subscriptions as subscription_request_types,
|
revenue_recovery::InvoiceRecordBackRequest, subscriptions as subscription_request_types,
|
||||||
@ -20,7 +20,10 @@ use hyperswitch_domain_models::{
|
|||||||
|
|
||||||
use super::errors;
|
use super::errors;
|
||||||
use crate::{
|
use crate::{
|
||||||
core::payments as payments_core, routes::SessionState, services, types::api as api_types,
|
core::{payments as payments_core, subscription::subscription_types},
|
||||||
|
routes::SessionState,
|
||||||
|
services,
|
||||||
|
types::api as api_types,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct BillingHandler {
|
pub struct BillingHandler {
|
||||||
@ -283,6 +286,45 @@ impl BillingHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn get_subscription_estimate(
|
||||||
|
&self,
|
||||||
|
state: &SessionState,
|
||||||
|
estimate_request: subscription_types::EstimateSubscriptionQuery,
|
||||||
|
) -> errors::RouterResult<subscription_response_types::GetSubscriptionEstimateResponse> {
|
||||||
|
let estimate_req = subscription_request_types::GetSubscriptionEstimateRequest {
|
||||||
|
price_id: estimate_request.item_price_id.clone(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let router_data = self.build_router_data(
|
||||||
|
state,
|
||||||
|
estimate_req,
|
||||||
|
GetSubscriptionEstimateData {
|
||||||
|
connector_meta_data: self.connector_metadata.clone(),
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
let connector_integration = self.connector_data.connector.get_connector_integration();
|
||||||
|
|
||||||
|
let response = Box::pin(self.call_connector(
|
||||||
|
state,
|
||||||
|
router_data,
|
||||||
|
"get subscription estimate from connector",
|
||||||
|
connector_integration,
|
||||||
|
))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
match response {
|
||||||
|
Ok(response_data) => Ok(response_data),
|
||||||
|
Err(err) => Err(errors::ApiErrorResponse::ExternalConnectorError {
|
||||||
|
code: err.code,
|
||||||
|
message: err.message,
|
||||||
|
connector: self.connector_data.connector_name.to_string(),
|
||||||
|
status_code: err.status_code,
|
||||||
|
reason: err.reason,
|
||||||
|
}
|
||||||
|
.into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn get_subscription_plans(
|
pub async fn get_subscription_plans(
|
||||||
&self,
|
&self,
|
||||||
state: &SessionState,
|
state: &SessionState,
|
||||||
|
|||||||
@ -1187,6 +1187,7 @@ impl Subscription {
|
|||||||
subscription::create_subscription(state, req, payload)
|
subscription::create_subscription(state, req, payload)
|
||||||
}),
|
}),
|
||||||
))
|
))
|
||||||
|
.service(web::resource("/estimate").route(web::get().to(subscription::get_estimate)))
|
||||||
.service(
|
.service(
|
||||||
web::resource("/plans").route(web::get().to(subscription::get_subscription_plans)),
|
web::resource("/plans").route(web::get().to(subscription::get_subscription_plans)),
|
||||||
)
|
)
|
||||||
|
|||||||
@ -91,6 +91,7 @@ impl From<Flow> for ApiIdentifier {
|
|||||||
| Flow::ConfirmSubscription
|
| Flow::ConfirmSubscription
|
||||||
| Flow::CreateAndConfirmSubscription
|
| Flow::CreateAndConfirmSubscription
|
||||||
| Flow::GetSubscription
|
| Flow::GetSubscription
|
||||||
|
| Flow::GetSubscriptionEstimate
|
||||||
| Flow::GetPlansForSubscription => Self::Subscription,
|
| Flow::GetPlansForSubscription => Self::Subscription,
|
||||||
Flow::RetrieveForexFlow => Self::Forex,
|
Flow::RetrieveForexFlow => Self::Forex,
|
||||||
Flow::AddToBlocklist => Self::Blocklist,
|
Flow::AddToBlocklist => Self::Blocklist,
|
||||||
|
|||||||
@ -7,6 +7,7 @@ use std::str::FromStr;
|
|||||||
|
|
||||||
use actix_web::{web, HttpRequest, HttpResponse, Responder};
|
use actix_web::{web, HttpRequest, HttpResponse, Responder};
|
||||||
use api_models::subscription as subscription_types;
|
use api_models::subscription as subscription_types;
|
||||||
|
use error_stack::report;
|
||||||
use hyperswitch_domain_models::errors;
|
use hyperswitch_domain_models::errors;
|
||||||
use router_env::{
|
use router_env::{
|
||||||
tracing::{self, instrument},
|
tracing::{self, instrument},
|
||||||
@ -252,3 +253,40 @@ pub async fn create_and_confirm_subscription(
|
|||||||
))
|
))
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// add support for get subscription estimate
|
||||||
|
#[instrument(skip_all)]
|
||||||
|
pub async fn get_estimate(
|
||||||
|
state: web::Data<AppState>,
|
||||||
|
req: HttpRequest,
|
||||||
|
query: web::Query<subscription_types::EstimateSubscriptionQuery>,
|
||||||
|
) -> impl Responder {
|
||||||
|
let flow = Flow::GetSubscriptionEstimate;
|
||||||
|
let profile_id = match extract_profile_id(&req) {
|
||||||
|
Ok(id) => id,
|
||||||
|
Err(response) => return response,
|
||||||
|
};
|
||||||
|
let api_auth = auth::ApiKeyAuth {
|
||||||
|
is_connected_allowed: false,
|
||||||
|
is_platform_allowed: false,
|
||||||
|
};
|
||||||
|
let (auth_type, _auth_flow) = match auth::get_auth_type_and_flow(req.headers(), api_auth) {
|
||||||
|
Ok(auth) => auth,
|
||||||
|
Err(err) => return oss_api::log_and_return_error_response(report!(err)),
|
||||||
|
};
|
||||||
|
Box::pin(oss_api::server_wrap(
|
||||||
|
flow,
|
||||||
|
state,
|
||||||
|
&req,
|
||||||
|
query.into_inner(),
|
||||||
|
|state, auth: auth::AuthenticationData, query, _| {
|
||||||
|
let merchant_context = domain::MerchantContext::NormalMerchant(Box::new(
|
||||||
|
domain::Context(auth.merchant_account, auth.key_store),
|
||||||
|
));
|
||||||
|
subscription::get_estimate(state, merchant_context, profile_id.clone(), query)
|
||||||
|
},
|
||||||
|
&*auth_type,
|
||||||
|
api_locking::LockAction::NotApplicable,
|
||||||
|
))
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|||||||
@ -273,6 +273,8 @@ pub enum Flow {
|
|||||||
CreateAndConfirmSubscription,
|
CreateAndConfirmSubscription,
|
||||||
/// Get Subscription flow
|
/// Get Subscription flow
|
||||||
GetSubscription,
|
GetSubscription,
|
||||||
|
/// Get Subscription estimate flow
|
||||||
|
GetSubscriptionEstimate,
|
||||||
/// Create dynamic routing
|
/// Create dynamic routing
|
||||||
CreateDynamicRoutingConfig,
|
CreateDynamicRoutingConfig,
|
||||||
/// Toggle dynamic routing
|
/// Toggle dynamic routing
|
||||||
|
|||||||
Reference in New Issue
Block a user