Repository: juspay/hyperswitch
File: crates/api_models/src/subscription.rs (Rust)

Code before:
}

#[derive(serde::Deserialize, serde::Serialize, Debug, ToSchema)]
pub struct GetPlansQuery {
    #[schema(value_type = Option<String>)]
    /// This is a token which expires after 15 minutes, used from the client to authenticate and create sessions from the SDK
    pub client_secret: Option<ClientSecret>,
    pub limit: Option<u32>,
    pub offset: Option<u32>,
}

impl ApiEventMetric for SubscriptionResponse {}
impl ApiEventMetric for CreateSubscriptionRequest {}
impl ApiEventMetric for GetPlansQuery {}
impl ApiEventMetric for GetPlansResponse {}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct ConfirmSubscriptionPaymentDetails {
    pub shipping: Option<Address>,
    pub billing: Option<Address>,
    pub payment_method: PaymentMethod,
    pub payment_method_type: Option<PaymentMethodType>,
    pub payment_method_data: Option<PaymentMethodDataRequest>,
    pub customer_acceptance: Option<CustomerAcceptance>,
    pub payment_type: Option<PaymentType>,
    pub payment_token: Option<String>,
}

impl ConfirmSubscriptionPaymentDetails {
    pub fn validate(&self) -> Result<(), error_stack::Report<ValidationError>> {
        fp_utils::when(
            self.payment_method_data.is_none() && self.payment_token.is_none(),
            || {
                Err(ValidationError::MissingRequiredField {
                    field_name: String::from(
                        "either of payment_method_data or payment_token must be present",
                    ),
                }
                .into())
            },
        )
    }
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct CreateSubscriptionPaymentDetails {
    /// The url to which user must be redirected to after completion of the purchase
    #[schema(value_type = String)]
    pub return_url: Url,
    pub setup_future_usage: Option<FutureUsage>,
    pub capture_method: Option<CaptureMethod>,

Review comment (security):
```suggestion
    pub payment_token: Option<Secret<String>>,
```

Code after:
}

#[derive(serde::Deserialize, serde::Serialize, Debug, ToSchema)]
pub struct GetPlansQuery {
    #[schema(value_type = Option<String>)]
    /// This is a token which expires after 15 minutes, used from the client to authenticate and create sessions from the SDK
    pub client_secret: Option<ClientSecret>,
    pub limit: Option<u32>,
    pub offset: Option<u32>,
}

impl ApiEventMetric for SubscriptionResponse {}
impl ApiEventMetric for CreateSubscriptionRequest {}
impl ApiEventMetric for GetPlansQuery {}
impl ApiEventMetric for GetPlansResponse {}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct ConfirmSubscriptionPaymentDetails {
    pub shipping: Option<Address>,
    pub billing: Option<Address>,
    pub payment_method: PaymentMethod,
    pub payment_method_type: Option<PaymentMethodType>,
    pub payment_method_data: Option<PaymentMethodDataRequest>,
    pub customer_acceptance: Option<CustomerAcceptance>,
    pub payment_type: Option<PaymentType>,
    #[schema(value_type = Option<String>, example = "token_sxJdmpUnpNsJk5VWzcjl")]
    pub payment_token: Option<Secret<String>>,
}

impl ConfirmSubscriptionPaymentDetails {
    pub fn validate(&self) -> Result<(), error_stack::Report<ValidationError>> {
        fp_utils::when(
            self.payment_method_data.is_none() && self.payment_token.is_none(),
            || {
                Err(ValidationError::MissingRequiredField {
                    field_name: String::from(
                        "Either payment_method_data or payment_token must be present",
                    ),
                }
                .into())
            },
        )
    }
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct CreateSubscriptionPaymentDetails {
    /// The url to which user must be redirected to after completion of the purchase
    #[schema(value_type = String)]
    pub return_url: Url,
    pub setup_future_usage: Option<FutureUsage>,