    /// The time range for which objects are needed. TimeRange has two fields start_time and end_time from which objects can be filtered as per required scenarios (created_at, time less than, greater than etc).
    #[serde(flatten)]
    pub time_range: Option<common_utils::types::TimeRange>,
    /// The list of connectors to filter payments list
    pub connector: Option<Vec<api_enums::Connector>>,
    /// The list of currencies to filter payments list
    pub currency: Option<Vec<enums::Currency>>,
    /// The list of payment status to filter payments list
    pub status: Option<Vec<enums::IntentStatus>>,
    /// The list of payment methods to filter payments list
    pub payment_method: Option<Vec<enums::PaymentMethod>>,
    /// The list of payment method types to filter payments list
    pub payment_method_type: Option<Vec<enums::PaymentMethodType>>,
    /// The list of authentication types to filter payments list
    pub authentication_type: Option<Vec<enums::AuthenticationType>>,
    /// The list of merchant connector ids to filter payments list for selected label
    pub merchant_connector_id: Option<Vec<id_type::MerchantConnectorAccountId>>,
    /// The order in which payments list should be sorted
    #[serde(default)]
    pub order: Order,
    /// The List of all the card networks to filter payments list
    pub card_network: Option<Vec<enums::CardNetwork>>,
    /// The identifier for merchant order reference id
    pub merchant_order_reference_id: Option<String>,
    /// Indicates the method by which a card is discovered during a payment
    pub card_discovery: Option<Vec<enums::CardDiscovery>>,
}

#[cfg(feature = "v1")]
impl PaymentListFilterConstraints {
    pub fn has_no_attempt_filters(&self) -> bool {
        self.connector.is_none()
            && self.payment_method.is_none()
            && self.payment_method_type.is_none()
            && self.authentication_type.is_none()
            && self.merchant_connector_id.is_none()
            && self.card_network.is_none()
            && self.card_discovery.is_none()
    }
}

#[derive(Clone, Debug, serde::Serialize)]
pub struct PaymentListFilters {
    /// The list of available connector filters
    pub connector: Vec<String>,
    /// The list of available currency filters
    pub currency: Vec<enums::Currency>,
    /// The list of available payment status filters
    pub status: Vec<enums::IntentStatus>,
    /// The list of available payment method filters
    pub payment_method: Vec<enums::PaymentMethod>,
    /// The list of available payment method types
    pub payment_method_type: Vec<enums::PaymentMethodType>,
    /// The list of available authentication types
    pub authentication_type: Vec<enums::AuthenticationType>,
}

#[derive(Clone, Debug, serde::Serialize)]
pub struct PaymentListFiltersV2 {
    /// The list of available connector filters
    pub connector: HashMap<String, Vec<MerchantConnectorInfo>>,
    /// The list of available currency filters
    pub currency: Vec<enums::Currency>,
    /// The list of available payment status filters
    pub status: Vec<enums::IntentStatus>,
    /// The list payment method and their corresponding types
    pub payment_method: HashMap<enums::PaymentMethod, HashSet<enums::PaymentMethodType>>,
    /// The list of available authentication types
    pub authentication_type: Vec<enums::AuthenticationType>,
    /// The list of available card networks
    pub card_network: Vec<enums::CardNetwork>,
    /// The list of available Card discovery methods
    pub card_discovery: Vec<enums::CardDiscovery>,
}

#[derive(Clone, Debug, serde::Serialize)]
pub struct PaymentsAggregateResponse {
    /// The list of intent status with their count
    pub status_with_count: HashMap<enums::IntentStatus, i64>,
}

#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, ToSchema)]
pub struct AmountFilter {
    /// The start amount to filter list of transactions which are greater than or equal to the start amount
    pub start_amount: Option<i64>,
    /// The end amount to filter list of transactions which are less than or equal to the end amount
    pub end_amount: Option<i64>,
}

#[derive(Clone, Debug, Default, Eq, PartialEq, serde::Deserialize, serde::Serialize, ToSchema)]
pub struct Order {
    /// The field to sort, such as Amount or Created etc.
    pub on: SortOn,
    /// The order in which to sort the items, either Ascending or Descending
    pub by: SortBy,
}

#[derive(Clone, Debug, Default, Eq, PartialEq, serde::Deserialize, serde::Serialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum SortOn {
    /// Sort by the amount field
    Amount,
    /// Sort by the created_at field
    #[default]
    Created,
}

#[derive(Clone, Debug, Default, Eq, PartialEq, serde::Deserialize, serde::Serialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum SortBy {
    /// Sort in ascending order
    Asc,
    /// Sort in descending order
    #[default]
    Desc,
}

#[derive(Setter, Clone, Default, Debug, PartialEq, serde::Serialize)]
pub struct VerifyResponse {
    pub verify_id: Option<id_type::PaymentId>,
    pub merchant_id: Option<id_type::MerchantId>,
    // pub status: enums::VerifyStatus,
    pub client_secret: Option<Secret<String>>,
    pub customer_id: Option<id_type::CustomerId>,
    pub email: crypto::OptionalEncryptableEmail,
    pub name: crypto::OptionalEncryptableName,
    pub phone: crypto::OptionalEncryptablePhone,
    pub mandate_id: Option<String>,
    #[auth_based]
    pub payment_method: Option<api_enums::PaymentMethod>,
    #[auth_based]
    pub payment_method_data: Option<PaymentMethodDataResponse>,
    pub payment_token: Option<String>,
    pub error_code: Option<String>,
    pub error_message: Option<String>,
}

#[derive(Default, Debug, serde::Deserialize, serde::Serialize)]
pub struct PaymentsRedirectionResponse {
    pub redirect_url: String,
}

pub struct MandateValidationFields {
    pub recurring_details: Option<RecurringDetails>,
    pub confirm: Option<bool>,
    pub customer_id: Option<id_type::CustomerId>,
    pub mandate_data: Option<MandateData>,
    pub setup_future_usage: Option<api_enums::FutureUsage>,
    pub off_session: Option<bool>,
}

#[cfg(feature = "v1")]
impl From<&PaymentsRequest> for MandateValidationFields {
    fn from(req: &PaymentsRequest) -> Self {
        let recurring_details = req
            .mandate_id
            .clone()
            .map(RecurringDetails::MandateId)
            .or(req.recurring_details.clone());

        Self {
            recurring_details,
            confirm: req.confirm,
            customer_id: req
                .customer
                .as_ref()
                .map(|customer_details| &customer_details.id)
                .or(req.customer_id.as_ref())
                .map(ToOwned::to_owned),
            mandate_data: req.mandate_data.clone(),
            setup_future_usage: req.setup_future_usage,
            off_session: req.off_session,
        }
    }
}

impl From<&VerifyRequest> for MandateValidationFields {
    fn from(req: &VerifyRequest) -> Self {
        Self {
            recurring_details: None,
            confirm: Some(true),
            customer_id: req.customer_id.clone(),
            mandate_data: req.mandate_data.clone(),
            off_session: req.off_session,
            setup_future_usage: req.setup_future_usage,
        }
    }
}

// #[cfg(all(feature = "v2", feature = "payment_v2"))]
// impl From<PaymentsSessionRequest> for PaymentsSessionResponse {
//     fn from(item: PaymentsSessionRequest) -> Self {
//         let client_secret: Secret<String, pii::ClientSecret> = Secret::new(item.client_secret);
//         Self {
//             session_token: vec![],
//             payment_id: item.payment_id,
//             client_secret,
//         }
//     }
// }

#[cfg(feature = "v1")]
impl From<PaymentsSessionRequest> for PaymentsSessionResponse {
    fn from(item: PaymentsSessionRequest) -> Self {
        let client_secret: Secret<String, pii::ClientSecret> = Secret::new(item.client_secret);
        Self {
            session_token: vec![],
            payment_id: item.payment_id,
            client_secret,
        }
    }
}

#[cfg(feature = "v1")]
impl From<PaymentsStartRequest> for PaymentsRequest {
    fn from(item: PaymentsStartRequest) -> Self {
        Self {
            payment_id: Some(PaymentIdType::PaymentIntentId(item.payment_id)),
            merchant_id: Some(item.merchant_id),
            ..Default::default()
        }
    }
}

impl From<AdditionalCardInfo> for CardResponse {
    fn from(card: AdditionalCardInfo) -> Self {
        Self {
            last4: card.last4,
            card_type: card.card_type,
            card_network: card.card_network,
            card_issuer: card.card_issuer,
            card_issuing_country: card.card_issuing_country,
            card_isin: card.card_isin,
            card_extended_bin: card.card_extended_bin,
            card_exp_month: card.card_exp_month,
            card_exp_year: card.card_exp_year,
            card_holder_name: card.card_holder_name,
            payment_checks: card.payment_checks,
            authentication_data: card.authentication_data,
        }
    }
}

impl From<KlarnaSdkPaymentMethod> for PaylaterResponse {
    fn from(klarna_sdk: KlarnaSdkPaymentMethod) -> Self {
        Self {
            klarna_sdk: Some(KlarnaSdkPaymentMethodResponse {
                payment_type: klarna_sdk.payment_type,
            }),
        }
    }
}

impl From<AdditionalPaymentData> for PaymentMethodDataResponse {
    fn from(payment_method_data: AdditionalPaymentData) -> Self {
        match payment_method_data {
            AdditionalPaymentData::Card(card) => Self::Card(Box::new(CardResponse::from(*card))),
            AdditionalPaymentData::PayLater { klarna_sdk } => match klarna_sdk {
                Some(sdk) => Self::PayLater(Box::new(PaylaterResponse::from(sdk))),
                None => Self::PayLater(Box::new(PaylaterResponse { klarna_sdk: None })),
            },
            AdditionalPaymentData::Wallet {
                apple_pay,
                google_pay,
                samsung_pay,
            } => match (apple_pay, google_pay, samsung_pay) {
                (Some(apple_pay_pm), _, _) => Self::Wallet(Box::new(WalletResponse {
                    details: Some(WalletResponseData::ApplePay(Box::new(
                        additional_info::WalletAdditionalDataForCard {
                            last4: apple_pay_pm
                                .display_name
                                .clone()
                                .chars()
                                .rev()
                                .take(4)
                                .collect::<String>()
                                .chars()
                                .rev()
                                .collect::<String>(),
                            card_network: apple_pay_pm.network.clone(),
                            card_type: Some(apple_pay_pm.pm_type.clone()),
                        },
                    ))),
                })),
                (_, Some(google_pay_pm), _) => Self::Wallet(Box::new(WalletResponse {
                    details: Some(WalletResponseData::GooglePay(Box::new(google_pay_pm))),
                })),
                (_, _, Some(samsung_pay_pm)) => Self::Wallet(Box::new(WalletResponse {
                    details: Some(WalletResponseData::SamsungPay(Box::new(samsung_pay_pm))),
                })),
                _ => Self::Wallet(Box::new(WalletResponse { details: None })),
            },
            AdditionalPaymentData::BankRedirect { bank_name, details } => {
                Self::BankRedirect(Box::new(BankRedirectResponse { bank_name, details }))
            }
            AdditionalPaymentData::Crypto { details } => {
                Self::Crypto(Box::new(CryptoResponse { details }))
            }
            AdditionalPaymentData::BankDebit { details } => {
                Self::BankDebit(Box::new(BankDebitResponse { details }))
            }
            AdditionalPaymentData::MandatePayment {} => Self::MandatePayment {},
            AdditionalPaymentData::Reward {} => Self::Reward {},
            AdditionalPaymentData::RealTimePayment { details } => {
                Self::RealTimePayment(Box::new(RealTimePaymentDataResponse { details }))
            }
            AdditionalPaymentData::Upi { details } => Self::Upi(Box::new(UpiResponse { details })),
            AdditionalPaymentData::BankTransfer { details } => {
                Self::BankTransfer(Box::new(BankTransferResponse { details }))
            }
            AdditionalPaymentData::Voucher { details } => {
                Self::Voucher(Box::new(VoucherResponse { details }))
            }
            AdditionalPaymentData::GiftCard { details } => {
                Self::GiftCard(Box::new(GiftCardResponse { details }))
            }
            AdditionalPaymentData::CardRedirect { details } => {
                Self::CardRedirect(Box::new(CardRedirectResponse { details }))
            }
            AdditionalPaymentData::CardToken { details } => {
                Self::CardToken(Box::new(CardTokenResponse { details }))
            }
            AdditionalPaymentData::OpenBanking { details } => {
                Self::OpenBanking(Box::new(OpenBankingResponse { details }))
            }
            AdditionalPaymentData::MobilePayment { details } => {
                Self::MobilePayment(Box::new(MobilePaymentResponse { details }))
            }
        }
    }
}

#[derive(Debug, Clone, serde::Serialize)]
pub struct PgRedirectResponse {
    pub payment_id: id_type::PaymentId,
    pub status: api_enums::IntentStatus,
    pub gateway_id: String,
    pub customer_id: Option<id_type::CustomerId>,
    pub amount: Option<MinorUnit>,
}

#[cfg(feature = "v1")]
#[derive(Debug, serde::Serialize, PartialEq, Eq, serde::Deserialize)]
pub struct RedirectionResponse {
    pub return_url: String,
    pub params: Vec<(String, String)>,
    pub return_url_with_query_params: String,
    pub http_method: String,
    pub headers: Vec<(String, String)>,
}

#[cfg(feature = "v2")]
#[derive(Debug, serde::Serialize, PartialEq, Eq, serde::Deserialize)]
pub struct RedirectionResponse {
    pub return_url_with_query_params: String,
}

#[derive(Debug, serde::Deserialize)]
pub struct PaymentsResponseForm {
    pub transaction_id: String,
    // pub transaction_reference_id: String,
    pub merchant_id: id_type::MerchantId,
    pub order_id: String,
}

#[cfg(feature = "v1")]
#[derive(Default, Debug, serde::Deserialize, serde::Serialize, Clone, ToSchema)]
pub struct PaymentsRetrieveRequest {
    /// The type of ID (ex: payment intent id, payment attempt id or connector txn id)
    #[schema(value_type = String)]
    pub resource_id: PaymentIdType,
    /// The identifier for the Merchant Account.
    #[schema(value_type = Option<String>)]
    pub merchant_id: Option<id_type::MerchantId>,
    /// Decider to enable or disable the connector call for retrieve request
    pub force_sync: bool,
    /// Optional query parameters that might be specific to a connector or flow, passed through during the retrieve operation. Use with caution and refer to specific connector documentation if applicable.
    pub param: Option<String>,
    /// Optionally specifies the connector to be used for a 'force_sync' retrieve operation. If provided, Hyperswitch will attempt to sync the payment status from this specific connector.
    pub connector: Option<String>,
    /// Merchant connector details used to make payments.
    #[schema(value_type = Option<MerchantConnectorDetailsWrap>)]
    pub merchant_connector_details: Option<admin::MerchantConnectorDetailsWrap>,
    /// 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<String>,
    /// If enabled provides list of captures linked to latest attempt
    pub expand_captures: Option<bool>,
    /// If enabled provides list of attempts linked to payment intent
    pub expand_attempts: Option<bool>,
    /// If enabled, provides whole connector response
    pub all_keys_required: Option<bool>,
}

#[derive(Debug, Default, PartialEq, serde::Deserialize, serde::Serialize, Clone, ToSchema)]
pub struct OrderDetailsWithAmount {
    /// Name of the product that is being purchased
    #[schema(max_length = 255, example = "shirt")]
    pub product_name: String,
    /// The quantity of the product to be purchased
    #[schema(example = 1)]
    pub quantity: u16,
    /// the amount per quantity of product
    #[schema(value_type = i64)]
    pub amount: MinorUnit,
    /// tax rate applicable to the product
    pub tax_rate: Option<f64>,
    /// total tax amount applicable to the product
    #[schema(value_type = Option<i64>)]
    pub total_tax_amount: Option<MinorUnit>,
    // Does the order includes shipping
    pub requires_shipping: Option<bool>,
    /// The image URL of the product
    pub product_img_link: Option<String>,
    /// ID of the product that is being purchased
    pub product_id: Option<String>,
    /// Category of the product that is being purchased
    pub category: Option<String>,
    /// Sub category of the product that is being purchased
    pub sub_category: Option<String>,
    /// Brand of the product that is being purchased
    pub brand: Option<String>,
    /// Type of the product that is being purchased
    pub product_type: Option<ProductType>,
    /// The tax code for the product
    pub product_tax_code: Option<String>,
    /// Description for the item
    pub description: Option<String>,
    /// Stock Keeping Unit (SKU) or the item identifier for this item.
    pub sku: Option<String>,
    /// Universal Product Code for the item.
    pub upc: Option<String>,
    /// Code describing a commodity or a group of commodities pertaining to goods classification.
    pub commodity_code: Option<String>,
    /// Unit of measure used for the item quantity.
    pub unit_of_measure: Option<String>,
    /// Total amount for the item.
    #[schema(value_type = Option<i64>)]
    pub total_amount: Option<MinorUnit>, // total_amount,
    /// Discount amount applied to this item.
    #[schema(value_type = Option<i64>)]
    pub unit_discount_amount: Option<MinorUnit>,
}

impl masking::SerializableSecret for OrderDetailsWithAmount {}

#[derive(Default, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, Clone, ToSchema)]
pub struct RedirectResponse {
    #[schema(value_type = Option<String>)]
    pub param: Option<Secret<String>>,
    #[schema(value_type = Option<Object>)]
    pub json_payload: Option<pii::SecretSerdeValue>,
}

#[cfg(feature = "v2")]
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone, ToSchema)]
pub struct PaymentsSessionRequest {}

#[cfg(feature = "v1")]
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone, ToSchema)]
pub struct PaymentsSessionRequest {
    /// The identifier for the payment
    #[schema(value_type = String)]
    pub payment_id: id_type::PaymentId,
    /// This is a token which expires after 15 minutes, used from the client to authenticate and create sessions from the SDK
    pub client_secret: String,
    /// The list of the supported wallets
    #[schema(value_type = Vec<PaymentMethodType>)]
    pub wallets: Vec<api_enums::PaymentMethodType>,
    /// Merchant connector details used to make payments.
    #[schema(value_type = Option<MerchantConnectorDetailsWrap>)]
    pub merchant_connector_details: Option<admin::MerchantConnectorDetailsWrap>,
}

#[derive(Debug, serde::Deserialize, serde::Serialize, Clone, ToSchema)]
#[serde(deny_unknown_fields)]
pub struct PaymentsUpdateMetadataRequest {
    /// The unique identifier for the payment
    #[serde(skip_deserializing)]
    #[schema(value_type = String)]
    pub payment_id: id_type::PaymentId,
    /// Metadata is useful for storing additional, unstructured information on an object.
    #[schema(value_type = Object, example = r#"{ "udf1": "some-value", "udf2": "some-value" }"#)]
    pub metadata: pii::SecretSerdeValue,
}

#[derive(Debug, serde::Serialize, Clone, ToSchema)]
pub struct PaymentsUpdateMetadataResponse {
    /// The identifier for the payment
    #[schema(value_type = String)]
    pub payment_id: id_type::PaymentId,
    /// Metadata is useful for storing additional, unstructured information on an object.
    #[schema(value_type = Option<Object>, example = r#"{ "udf1": "some-value", "udf2": "some-value" }"#)]
    pub metadata: Option<pii::SecretSerdeValue>,
}

#[derive(Debug, serde::Deserialize, serde::Serialize, Clone, ToSchema)]
pub struct PaymentsPostSessionTokensRequest {
    /// The unique identifier for the payment
    #[serde(skip_deserializing)]
    #[schema(value_type = String)]
    pub payment_id: id_type::PaymentId,
    /// It's a token used for client side verification.
    #[schema(value_type = String)]
    pub client_secret: Secret<String>,
    /// Payment method type
    #[schema(value_type = PaymentMethodType)]
    pub payment_method_type: api_enums::PaymentMethodType,
    /// The payment method that is to be used for the payment
    #[schema(value_type = PaymentMethod, example = "card")]
    pub payment_method: api_enums::PaymentMethod,
}

#[derive(Debug, serde::Serialize, Clone, ToSchema)]
pub struct PaymentsPostSessionTokensResponse {
    /// The identifier for the payment
    #[schema(value_type = String)]
    pub payment_id: id_type::PaymentId,
    /// Additional information required for redirection
    pub next_action: Option<NextActionData>,
    #[schema(value_type = IntentStatus, example = "failed", default = "requires_confirmation")]
    pub status: api_enums::IntentStatus,
}

#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, ToSchema)]
pub struct PaymentsDynamicTaxCalculationRequest {
    /// The unique identifier for the payment
    #[serde(skip_deserializing)]
    #[schema(value_type = String)]
    pub payment_id: id_type::PaymentId,
    /// The shipping address for the payment
    pub shipping: Address,
    /// Client Secret
    #[schema(value_type = String)]
    pub client_secret: Secret<String>,
    /// Payment method type
    #[schema(value_type = PaymentMethodType)]
    pub payment_method_type: api_enums::PaymentMethodType,
    /// Session Id
    pub session_id: Option<String>,
}

#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, ToSchema)]
pub struct PaymentsDynamicTaxCalculationResponse {
    /// The identifier for the payment
    #[schema(value_type = String)]
    pub payment_id: id_type::PaymentId,
    /// net amount = amount + order_tax_amount + shipping_cost
    pub net_amount: MinorUnit,
    /// order tax amount calculated by tax connectors
    pub order_tax_amount: Option<MinorUnit>,
    /// shipping cost for the order
    pub shipping_cost: Option<MinorUnit>,
    /// amount in Base Unit display format
    pub display_amount: DisplayAmountOnSdk,
}

#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, ToSchema)]
pub struct DisplayAmountOnSdk {
    /// net amount = amount + order_tax_amount + shipping_cost
    #[schema(value_type = String)]
    pub net_amount: StringMajorUnit,
    /// order tax amount calculated by tax connectors
    #[schema(value_type = String)]
    pub order_tax_amount: Option<StringMajorUnit>,
    /// shipping cost for the order
    #[schema(value_type = String)]
    pub shipping_cost: Option<StringMajorUnit>,
}

#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct GpayAllowedMethodsParameters {
    /// The list of allowed auth methods (ex: 3DS, No3DS, PAN_ONLY etc)
    pub allowed_auth_methods: Vec<String>,
    /// The list of allowed card networks (ex: AMEX,JCB etc)
    pub allowed_card_networks: Vec<String>,
    /// Is billing address required
    #[serde(skip_serializing_if = "Option::is_none")]
    pub billing_address_required: Option<bool>,
    /// Billing address parameters
    #[serde(skip_serializing_if = "Option::is_none")]
    pub billing_address_parameters: Option<GpayBillingAddressParameters>,
    /// Whether assurance details are required
    #[serde(skip_serializing_if = "Option::is_none")]
    pub assurance_details_required: Option<bool>,
}

#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct GpayBillingAddressParameters {
    /// Is billing phone number required
    pub phone_number_required: bool,
    /// Billing address format
    pub format: GpayBillingAddressFormat,
}

#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, serde::Deserialize, ToSchema)]
pub enum GpayBillingAddressFormat {
    FULL,
    MIN,
}

#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct GpayTokenParameters {
    /// The name of the connector
    #[serde(skip_serializing_if = "Option::is_none")]
    pub gateway: Option<String>,
    /// The merchant ID registered in the connector associated
    #[serde(skip_serializing_if = "Option::is_none")]
    pub gateway_merchant_id: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none", rename = "stripe:version")]
    pub stripe_version: Option<String>,
    #[serde(
        skip_serializing_if = "Option::is_none",
        rename = "stripe:publishableKey"
    )]
    pub stripe_publishable_key: Option<String>,
    /// The protocol version for encryption
    #[serde(skip_serializing_if = "Option::is_none")]
    pub protocol_version: Option<String>,
    /// The public key provided by the merchant
    #[serde(skip_serializing_if = "Option::is_none")]
    #[schema(value_type = Option<String>)]
    pub public_key: Option<Secret<String>>,
}

#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct GpayTokenizationSpecification {
    /// The token specification type(ex: PAYMENT_GATEWAY)
    #[serde(rename = "type")]
    pub token_specification_type: String,
    /// The parameters for the token specification Google Pay
    pub parameters: GpayTokenParameters,
}

#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct GpayAllowedPaymentMethods {
    /// The type of payment method
    #[serde(rename = "type")]
    pub payment_method_type: String,
    /// The parameters Google Pay requires
    pub parameters: GpayAllowedMethodsParameters,
    /// The tokenization specification for Google Pay
    pub tokenization_specification: GpayTokenizationSpecification,
}

#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct GpayTransactionInfo {
    /// The country code
    #[schema(value_type = CountryAlpha2, example = "US")]
    pub country_code: api_enums::CountryAlpha2,
    /// The currency code
    #[schema(value_type = Currency, example = "USD")]
    pub currency_code: api_enums::Currency,
    /// The total price status (ex: 'FINAL')
    pub total_price_status: String,
    /// The total price
    #[schema(value_type = String, example = "38.02")]
    pub total_price: StringMajorUnit,
}

#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct GpayMerchantInfo {
    /// The merchant Identifier that needs to be passed while invoking Gpay SDK
    #[serde(skip_serializing_if = "Option::is_none")]
    pub merchant_id: Option<String>,
    /// The name of the merchant that needs to be displayed on Gpay PopUp
    pub merchant_name: String,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct GpayMetaData {
    pub merchant_info: GpayMerchantInfo,
    pub allowed_payment_methods: Vec<GpayAllowedPaymentMethods>,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct GpaySessionTokenData {
    #[serde(rename = "google_pay")]
    pub data: GpayMetaData,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct PazeSessionTokenData {
    #[serde(rename = "paze")]
    pub data: PazeMetadata,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct PazeMetadata {
    pub client_id: String,
    pub client_name: String,
    pub client_profile_id: String,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum SamsungPayCombinedMetadata {
    // This is to support the Samsung Pay decryption flow with application credentials,
    // where the private key, certificates, or any other information required for decryption
    // will be obtained from the application configuration.
    ApplicationCredentials(SamsungPayApplicationCredentials),
    MerchantCredentials(SamsungPayMerchantCredentials),
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct SamsungPaySessionTokenData {
    #[serde(rename = "samsung_pay")]
    pub data: SamsungPayCombinedMetadata,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct SamsungPayMerchantCredentials {
    pub service_id: String,
    pub merchant_display_name: String,
    pub merchant_business_country: api_enums::CountryAlpha2,
    pub allowed_brands: Vec<String>,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct SamsungPayApplicationCredentials {
    pub merchant_display_name: String,
    pub merchant_business_country: api_enums::CountryAlpha2,
    pub allowed_brands: Vec<String>,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct PaypalSdkMetaData {
    pub client_id: String,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct PaypalSdkSessionTokenData {
    #[serde(rename = "paypal_sdk")]
    pub data: PaypalSdkMetaData,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ApplepaySessionRequest {
    pub merchant_identifier: String,
    pub display_name: String,
    pub initiative: String,
    pub initiative_context: String,
}

/// Some connectors like Apple Pay, Airwallex and Noon might require some additional information, find specific details in the child attributes below.
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct ConnectorMetadata {
    pub apple_pay: Option<ApplepayConnectorMetadataRequest>,
    pub airwallex: Option<AirwallexData>,
    pub noon: Option<NoonData>,
    pub braintree: Option<BraintreeData>,
    pub adyen: Option<AdyenConnectorMetadata>,
}

impl ConnectorMetadata {
    pub fn from_value(
        value: pii::SecretSerdeValue,
    ) -> common_utils::errors::CustomResult<Self, common_utils::errors::ParsingError> {
        value
            .parse_value::<Self>("ConnectorMetadata")
            .change_context(common_utils::errors::ParsingError::StructParseFailure(
                "Metadata",
            ))
    }
    pub fn get_apple_pay_certificates(self) -> Option<(Secret<String>, Secret<String>)> {
        self.apple_pay.and_then(|applepay_metadata| {
            applepay_metadata
                .session_token_data
                .map(|session_token_data| {
                    let SessionTokenInfo {
                        certificate,
                        certificate_keys,
                        ..
                    } = session_token_data;
                    (certificate, certificate_keys)
                })
        })
    }
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct AirwallexData {
    /// payload required by airwallex
    payload: Option<String>,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct NoonData {
    /// Information about the order category that merchant wants to specify at connector level. (e.g. In Noon Payments it can take values like "pay", "food", or any other custom string set by the merchant in Noon's Dashboard)
    pub order_category: Option<String>,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct BraintreeData {
    /// Information about the merchant_account_id that merchant wants to specify at connector level.
    #[schema(value_type = String)]
    pub merchant_account_id: Option<Secret<String>>,
    /// Information about the merchant_config_currency that merchant wants to specify at connector level.
    #[schema(value_type = String)]
    pub merchant_config_currency: Option<api_enums::Currency>,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct AdyenConnectorMetadata {
    pub testing: AdyenTestingData,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct AdyenTestingData {
    /// Holder name to be sent to Adyen for a card payment(CIT) or a generic payment(MIT). This value overrides the values for card.card_holder_name and applies during both CIT and MIT payment transactions.
    #[schema(value_type = String)]
    pub holder_name: Option<Secret<String>>,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct ApplepayConnectorMetadataRequest {
    pub session_token_data: Option<SessionTokenInfo>,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct ApplepaySessionTokenData {
    pub apple_pay: ApplePayMetadata,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct ApplepayCombinedSessionTokenData {
    pub apple_pay_combined: ApplePayCombinedMetadata,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ApplepaySessionTokenMetadata {
    ApplePayCombined(ApplePayCombinedMetadata),
    ApplePay(ApplePayMetadata),
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct ApplePayMetadata {
    pub payment_request_data: PaymentRequestMetadata,
    pub session_token_data: SessionTokenInfo,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ApplePayCombinedMetadata {
    Simplified {
        payment_request_data: PaymentRequestMetadata,
        session_token_data: SessionTokenForSimplifiedApplePay,
    },
    Manual {
        payment_request_data: PaymentRequestMetadata,
        session_token_data: SessionTokenInfo,
    },
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct PaymentRequestMetadata {
    pub supported_networks: Vec<String>,
    pub merchant_capabilities: Vec<String>,
    pub label: String,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct SessionTokenInfo {
    #[schema(value_type = String)]
    pub certificate: Secret<String>,
    #[schema(value_type = String)]
    pub certificate_keys: Secret<String>,
    pub merchant_identifier: String,
    pub display_name: String,
    pub initiative: ApplepayInitiative,
    pub initiative_context: Option<String>,
    #[schema(value_type = Option<CountryAlpha2>)]
    pub merchant_business_country: Option<api_enums::CountryAlpha2>,
    #[serde(flatten)]
    pub payment_processing_details_at: Option<PaymentProcessingDetailsAt>,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Display, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum ApplepayInitiative {
    Web,
    Ios,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
#[serde(tag = "payment_processing_details_at")]
pub enum PaymentProcessingDetailsAt {
    Hyperswitch(PaymentProcessingDetails),
    Connector,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq, ToSchema)]
pub struct PaymentProcessingDetails {
    #[schema(value_type = String)]
    pub payment_processing_certificate: Secret<String>,
    #[schema(value_type = String)]
    pub payment_processing_certificate_key: Secret<String>,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct SessionTokenForSimplifiedApplePay {
    pub initiative_context: String,
    #[schema(value_type = Option<CountryAlpha2>)]
    pub merchant_business_country: Option<api_enums::CountryAlpha2>,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct GooglePayWalletDetails {
    pub google_pay: GooglePayDetails,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct GooglePayDetails {
    pub provider_details: GooglePayProviderDetails,
    pub cards: GpayAllowedMethodsParameters,
}

// Google Pay Provider Details can of two types: GooglePayMerchantDetails or GooglePayHyperSwitchDetails
// GooglePayHyperSwitchDetails is not implemented yet
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
#[serde(untagged)]
pub enum GooglePayProviderDetails {
    GooglePayMerchantDetails(GooglePayMerchantDetails),
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct GooglePayMerchantDetails {
    pub merchant_info: GooglePayMerchantInfo,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct GooglePayMerchantInfo {
    pub merchant_name: String,
    pub merchant_id: Option<String>,
    pub tokenization_specification: GooglePayTokenizationSpecification,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct GooglePayTokenizationSpecification {
    #[serde(rename = "type")]
    pub tokenization_type: GooglePayTokenizationType,
    pub parameters: GooglePayTokenizationParameters,
}


pub struct PaymentMethodBalance {
    pub amount: MinorUnit,
    pub currency: common_enums::enums::Currency,
}


pub struct SwitchOrganizationRequest {
    pub org_id: id_type::OrganizationId,
}


/// Create a new Instance of IntermediateString using a string
    pub fn new(inner: String) -> Self {
        Self(inner)
    }


pub async fn list_roles_with_info(
    state: web::Data<AppState>,
    req: HttpRequest,
    query: web::Query<role_api::ListRolesQueryParams>,
) -> HttpResponse {
    let flow = Flow::ListRolesV2;

    Box::pin(api::server_wrap(
        flow,
        state.clone(),
        &req,
        query.into_inner(),
        |state, user_from_token, request, _| {
            role_core::list_roles_with_info(state, user_from_token, request)
        },
        &auth::JWTAuth {
            permission: Permission::ProfileUserRead,
        },
        api_locking::LockAction::NotApplicable,
    ))
    .await
}


pub async fn perform_contract_based_routing<F, D>(
    state: &SessionState,
    routable_connectors: Vec<api_routing::RoutableConnectorChoice>,
    profile_id: &common_utils::id_type::ProfileId,
    merchant_id: &common_utils::id_type::MerchantId,
    payment_id: &common_utils::id_type::PaymentId,
    _dynamic_routing_config_params_interpolator: routing::helpers::DynamicRoutingConfigParamsInterpolator,
    contract_based_algo_ref: api_routing::ContractRoutingAlgorithm,
    payment_data: &mut D,
) -> RoutingResult<Vec<api_routing::RoutableConnectorChoice>>
where
    F: Send + Clone,
    D: OperationSessionGetters<F> + OperationSessionSetters<F> + Send + Sync + Clone,
{
    if contract_based_algo_ref.enabled_feature
        == api_routing::DynamicRoutingFeatures::DynamicConnectorSelection
    {
        logger::debug!(
            "performing contract_based_routing for profile {}",
            profile_id.get_string_repr()
        );
        let client = &state
            .grpc_client
            .dynamic_routing
            .as_ref()
            .ok_or(errors::RoutingError::ContractRoutingClientInitializationError)
            .attach_printable("dynamic routing gRPC client not found")?
            .contract_based_client;

        let contract_based_routing_configs = routing::helpers::fetch_dynamic_routing_configs::<
            api_routing::ContractBasedRoutingConfig,
        >(
            state,
            profile_id,
            contract_based_algo_ref
                .algorithm_id_with_timestamp
                .algorithm_id
                .ok_or(errors::RoutingError::GenericNotFoundError {
                    field: "contract_based_routing_algorithm_id".to_string(),
                })
                .attach_printable("contract_based_routing_algorithm_id not found in profile_id")?,
        )
        .await
        .change_context(errors::RoutingError::ContractBasedRoutingConfigError)
        .attach_printable("unable to fetch contract based dynamic routing configs")?;

        let label_info = contract_based_routing_configs
            .label_info
            .clone()
            .ok_or(errors::RoutingError::ContractBasedRoutingConfigError)
            .attach_printable("Label information not found in contract routing configs")?;

        let contract_based_connectors = routable_connectors
            .clone()
            .into_iter()
            .filter(|conn| {
                label_info
                    .iter()
                    .any(|info| Some(info.mca_id.clone()) == conn.merchant_connector_id.clone())
            })
            .collect::<Vec<_>>();

        let mut other_connectors = routable_connectors
            .into_iter()
            .filter(|conn| {
                label_info
                    .iter()
                    .all(|info| Some(info.mca_id.clone()) != conn.merchant_connector_id.clone())
            })
            .collect::<Vec<_>>();

        let event_request = utils::CalContractScoreEventRequest {
            id: profile_id.get_string_repr().to_string(),
            params: "".to_string(),
            labels: contract_based_connectors
                .iter()
                .map(|conn_choice| conn_choice.to_string())
                .collect::<Vec<_>>(),
            config: Some(contract_based_routing_configs.clone()),
        };

        let routing_events_wrapper = utils::RoutingEventsWrapper::new(
            state.tenant.tenant_id.clone(),
            state.request_id,
            payment_id.get_string_repr().to_string(),
            profile_id.to_owned(),
            merchant_id.to_owned(),
            "IntelligentRouter: PerformContractRouting".to_string(),
            Some(event_request.clone()),
            true,
            false,
        );

        let closure = || async {
            let contract_based_connectors_result = client
                .calculate_contract_score(
                    profile_id.get_string_repr().into(),
                    contract_based_routing_configs.clone(),
                    "".to_string(),
                    contract_based_connectors,
                    state.get_grpc_headers(),
                )
                .await
                .attach_printable(
                    "unable to calculate/fetch contract score from dynamic routing service",
                );

            let contract_based_connectors = match contract_based_connectors_result {
                Ok(resp) => Some(utils::CalContractScoreEventResponse::from(&resp)),
                Err(err) => match err.current_context() {
                    DynamicRoutingError::ContractNotFound => {
                        client
                            .update_contracts(
                                profile_id.get_string_repr().into(),
                                label_info,
                                "".to_string(),
                                vec![],
                                u64::default(),
                                state.get_grpc_headers(),
                            )
                            .await
                            .change_context(errors::RoutingError::ContractScoreUpdationError)
                            .attach_printable(
                                "unable to update contract based routing window in dynamic routing service",
                            )?;
                        return Err((errors::RoutingError::ContractScoreCalculationError {
                            err: err.to_string(),
                        })
                        .into());
                    }
                    _ => {
                        return Err((errors::RoutingError::ContractScoreCalculationError {
                            err: err.to_string(),
                        })
                        .into())
                    }
                },
            };

            Ok(contract_based_connectors)
        };

        let events_response = routing_events_wrapper
            .construct_event_builder(
                "ContractScoreCalculator.FetchContractScore".to_string(),
                RoutingEngine::IntelligentRouter,
                ApiMethod::Grpc,
            )?
            .trigger_event(state, closure)
            .await?;

        let contract_based_connectors: utils::CalContractScoreEventResponse = events_response
            .response
            .ok_or(errors::RoutingError::ContractScoreCalculationError {
                err: "CalContractScoreEventResponse not found".to_string(),
            })?;

        let mut routing_event = events_response
            .event
            .ok_or(errors::RoutingError::RoutingEventsError {
            message:
                "ContractRouting-Intelligent-Router: RoutingEvent not found in RoutingEventsResponse"
                    .to_string(),
            status_code: 500,
        })?;

        payment_data.set_routing_approach_in_attempt(Some(
            common_enums::RoutingApproach::ContractBasedRouting,
        ));

        let mut connectors = Vec::with_capacity(contract_based_connectors.labels_with_score.len());

        for label_with_score in contract_based_connectors.labels_with_score {
            let (connector, merchant_connector_id) = label_with_score.label
                .split_once(':')
                .ok_or(errors::RoutingError::InvalidContractBasedConnectorLabel(label_with_score.label.to_string()))
                .attach_printable(
                    "unable to split connector_name and mca_id from the label obtained by the dynamic routing service",
                )?;

            connectors.push(api_routing::RoutableConnectorChoice {
                choice_kind: api_routing::RoutableChoiceKind::FullStruct,
                connector: common_enums::RoutableConnectors::from_str(connector)
                    .change_context(errors::RoutingError::GenericConversionError {
                        from: "String".to_string(),
                        to: "RoutableConnectors".to_string(),
                    })
                    .attach_printable("unable to convert String to RoutableConnectors")?,
                merchant_connector_id: Some(
                    common_utils::id_type::MerchantConnectorAccountId::wrap(
                        merchant_connector_id.to_string(),
                    )
                    .change_context(errors::RoutingError::GenericConversionError {
                        from: "String".to_string(),
                        to: "MerchantConnectorAccountId".to_string(),
                    })
                    .attach_printable("unable to convert MerchantConnectorAccountId from string")?,
                ),
            });
        }

        connectors.append(&mut other_connectors);

        logger::debug!(contract_based_routing_connectors=?connectors);

        routing_event.set_status_code(200);
        routing_event.set_routable_connectors(connectors.clone());
        routing_event.set_routing_approach(api_routing::RoutingApproach::ContractBased.to_string());
        state.event_handler().log_event(&routing_event);
        Ok(connectors)
    } else {
        Ok(routable_connectors)
    }
}


pub fn reverse_string(s: &str) -> String {
    s.chars().rev().collect()
}


pub async fn find_user_scoped_dashboard_metadata(
        conn: &PgPooledConn,
        user_id: String,
        merchant_id: id_type::MerchantId,
        org_id: id_type::OrganizationId,
        data_types: Vec<enums::DashboardMetadata>,
    ) -> StorageResult<Vec<Self>> {
        let predicate = dsl::user_id
            .eq(user_id)
            .and(dsl::merchant_id.eq(merchant_id))
            .and(dsl::org_id.eq(org_id))
            .and(dsl::data_key.eq_any(data_types));

        generics::generic_filter::<<Self as HasTable>::Table, _, _, _>(
            conn,
            predicate,
            None,
            None,
            Some(dsl::last_modified_at.asc()),
        )
        .await
    }


pub struct ProfileDefaultRoutingConfig {
    #[schema(value_type = String)]
    pub profile_id: common_utils::id_type::ProfileId,
    pub connectors: Vec<RoutableConnectorChoice>,
}


File: crates/router/src/compatibility/stripe/setup_intents.rs
 Public functions: 4

pub mod types;
#[cfg(feature = "v1")]
use actix_web::{web, HttpRequest, HttpResponse};
#[cfg(feature = "v1")]
use api_models::payments as payment_types;
#[cfg(feature = "v1")]
use error_stack::report;
#[cfg(feature = "v1")]
use router_env::{instrument, tracing, Flow};

#[cfg(feature = "v1")]
use crate::{
    compatibility::{
        stripe::{errors, payment_intents::types as stripe_payment_types},
        wrap,
    },
    core::{api_locking, payments},
    routes,
    services::{api, authentication as auth},
    types::{api as api_types, domain},
};

#[cfg(feature = "v1")]
#[instrument(skip_all, fields(flow = ?Flow::PaymentsCreate))]
pub async fn setup_intents_create(
    state: web::Data<routes::AppState>,
    qs_config: web::Data<serde_qs::Config>,
    req: HttpRequest,
    form_payload: web::Bytes,
) -> HttpResponse {
    let payload: types::StripeSetupIntentRequest = match qs_config.deserialize_bytes(&form_payload)
    {
        Ok(p) => p,
        Err(err) => {
            return api::log_and_return_error_response(report!(errors::StripeErrorCode::from(err)))
        }
    };

    let create_payment_req: payment_types::PaymentsRequest =
        match payment_types::PaymentsRequest::try_from(payload) {
            Ok(req) => req,
            Err(err) => return api::log_and_return_error_response(err),
        };

    let flow = Flow::PaymentsCreate;

    Box::pin(wrap::compatibility_api_wrap::<
        _,
        _,
        _,
        _,
        _,
        types::StripeSetupIntentResponse,
        errors::StripeErrorCode,
        _,
    >(
        flow,
        state.into_inner(),
        &req,
        create_payment_req,
        |state, auth: auth::AuthenticationData, req, req_state| {
            let merchant_context = domain::MerchantContext::NormalMerchant(Box::new(
                domain::Context(auth.merchant_account, auth.key_store),
            ));
            payments::payments_core::<
                api_types::SetupMandate,
                api_types::PaymentsResponse,
                _,
                _,
                _,
                payments::PaymentData<api_types::SetupMandate>,
            >(
                state,
                req_state,
                merchant_context,
                None,
                payments::PaymentCreate,
                req,
                api::AuthFlow::Merchant,
                payments::CallConnectorAction::Trigger,
                None,
                hyperswitch_domain_models::payments::HeaderPayload::default(),
            )
        },
        &auth::HeaderAuth(auth::ApiKeyAuth {
            is_connected_allowed: false,
            is_platform_allowed: false,
        }),
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

#[cfg(feature = "v1")]
#[instrument(skip_all, fields(flow = ?Flow::PaymentsRetrieveForceSync))]
pub async fn setup_intents_retrieve(
    state: web::Data<routes::AppState>,
    req: HttpRequest,
    path: web::Path<common_utils::id_type::PaymentId>,
    query_payload: web::Query<stripe_payment_types::StripePaymentRetrieveBody>,
) -> HttpResponse {
    let payload = payment_types::PaymentsRetrieveRequest {
        resource_id: api_types::PaymentIdType::PaymentIntentId(path.into_inner()),
        merchant_id: None,
        force_sync: true,
        connector: None,
        param: None,
        merchant_connector_details: None,
        client_secret: query_payload.client_secret.clone(),
        expand_attempts: None,
        expand_captures: None,
        all_keys_required: None,
    };

    let api_auth = auth::ApiKeyAuth {
        is_connected_allowed: false,
        is_platform_allowed: false,
    };

    let (auth_type, auth_flow) =
        match auth::check_client_secret_and_get_auth(req.headers(), &payload, api_auth) {
            Ok(auth) => auth,
            Err(err) => return api::log_and_return_error_response(report!(err)),
        };

    let flow = Flow::PaymentsRetrieveForceSync;

    Box::pin(wrap::compatibility_api_wrap::<
        _,
        _,
        _,
        _,
        _,
        types::StripeSetupIntentResponse,
        errors::StripeErrorCode,
        _,
    >(
        flow,
        state.into_inner(),
        &req,
        payload,
        |state, auth, payload, req_state| {
            let merchant_context = domain::MerchantContext::NormalMerchant(Box::new(
                domain::Context(auth.merchant_account, auth.key_store),
            ));
            payments::payments_core::<
                api_types::PSync,
                api_types::PaymentsResponse,
                _,
                _,
                _,
                payments::PaymentData<api_types::PSync>,
            >(
                state,
                req_state,
                merchant_context,
                None,
                payments::PaymentStatus,
                payload,
                auth_flow,
                payments::CallConnectorAction::Trigger,
                None,
                hyperswitch_domain_models::payments::HeaderPayload::default(),
            )
        },
        &*auth_type,
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

#[cfg(feature = "v1")]
#[instrument(skip_all, fields(flow = ?Flow::PaymentsUpdate))]
pub async fn setup_intents_update(
    state: web::Data<routes::AppState>,
    qs_config: web::Data<serde_qs::Config>,
    req: HttpRequest,
    form_payload: web::Bytes,
    path: web::Path<common_utils::id_type::PaymentId>,
) -> HttpResponse {
    let setup_id = path.into_inner();
    let stripe_payload: types::StripeSetupIntentRequest = match qs_config
        .deserialize_bytes(&form_payload)
    {
        Ok(p) => p,
        Err(err) => {
            return api::log_and_return_error_response(report!(errors::StripeErrorCode::from(err)))
        }
    };

    let mut payload: payment_types::PaymentsRequest =
        match payment_types::PaymentsRequest::try_from(stripe_payload) {
            Ok(req) => req,
            Err(err) => return api::log_and_return_error_response(err),
        };
    payload.payment_id = Some(api_types::PaymentIdType::PaymentIntentId(setup_id));

    let api_auth = auth::ApiKeyAuth {
        is_connected_allowed: false,
        is_platform_allowed: false,
    };

    let (auth_type, auth_flow) =
        match auth::check_client_secret_and_get_auth(req.headers(), &payload, api_auth) {
            Ok(auth) => auth,
            Err(err) => return api::log_and_return_error_response(err),
        };

    let flow = Flow::PaymentsUpdate;

    Box::pin(wrap::compatibility_api_wrap::<
        _,
        _,
        _,
        _,
        _,
        types::StripeSetupIntentResponse,
        errors::StripeErrorCode,
        _,
    >(
        flow,
        state.into_inner(),
        &req,
        payload,
        |state, auth, req, req_state| {
            let merchant_context = domain::MerchantContext::NormalMerchant(Box::new(
                domain::Context(auth.merchant_account, auth.key_store),
            ));
            payments::payments_core::<
                api_types::SetupMandate,
                api_types::PaymentsResponse,
                _,
                _,
                _,
                payments::PaymentData<api_types::SetupMandate>,
            >(
                state,
                req_state,
                merchant_context,
                None,
                payments::PaymentUpdate,
                req,
                auth_flow,
                payments::CallConnectorAction::Trigger,
                None,
                hyperswitch_domain_models::payments::HeaderPayload::default(),
            )
        },
        &*auth_type,
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

#[cfg(feature = "v1")]
#[instrument(skip_all, fields(flow = ?Flow::PaymentsConfirm))]
pub async fn setup_intents_confirm(
    state: web::Data<routes::AppState>,
    qs_config: web::Data<serde_qs::Config>,
    req: HttpRequest,
    form_payload: web::Bytes,
    path: web::Path<common_utils::id_type::PaymentId>,
) -> HttpResponse {
    let setup_id = path.into_inner();
    let stripe_payload: types::StripeSetupIntentRequest = match qs_config
        .deserialize_bytes(&form_payload)
    {
        Ok(p) => p,
        Err(err) => {
            return api::log_and_return_error_response(report!(errors::StripeErrorCode::from(err)))
        }
    };

    let mut payload: payment_types::PaymentsRequest =
        match payment_types::PaymentsRequest::try_from(stripe_payload) {
            Ok(req) => req,
            Err(err) => return api::log_and_return_error_response(err),
        };
    payload.payment_id = Some(api_types::PaymentIdType::PaymentIntentId(setup_id));
    payload.confirm = Some(true);

    let api_auth = auth::ApiKeyAuth {
        is_connected_allowed: false,
        is_platform_allowed: false,
    };

    let (auth_type, auth_flow) =
        match auth::check_client_secret_and_get_auth(req.headers(), &payload, api_auth) {
            Ok(auth) => auth,
            Err(err) => return api::log_and_return_error_response(err),
        };

    let flow = Flow::PaymentsConfirm;

    Box::pin(wrap::compatibility_api_wrap::<
        _,
        _,
        _,
        _,
        _,
        types::StripeSetupIntentResponse,
        errors::StripeErrorCode,
        _,
    >(
        flow,
        state.into_inner(),
        &req,
        payload,
        |state, auth, req, req_state| {
            let merchant_context = domain::MerchantContext::NormalMerchant(Box::new(
                domain::Context(auth.merchant_account, auth.key_store),
            ));
            payments::payments_core::<
                api_types::SetupMandate,
                api_types::PaymentsResponse,
                _,
                _,
                _,
                payments::PaymentData<api_types::SetupMandate>,
            >(
                state,
                req_state,
                merchant_context,
                None,
                payments::PaymentConfirm,
                req,
                auth_flow,
                payments::CallConnectorAction::Trigger,
                None,
                hyperswitch_domain_models::payments::HeaderPayload::default(),
            )
        },
        &*auth_type,
        api_locking::LockAction::NotApplicable,
    ))
    .await
}


impl api::RefundSync for Rapyd {}


File: crates/masking/src/bytes.rs
 Public functions: 1
 Public structs: 1

//! Optional `Secret` wrapper type for the `bytes::BytesMut` crate.

use core::fmt;

use bytes::BytesMut;
#[cfg(all(feature = "bytes", feature = "serde"))]
use serde::de::{self, Deserialize};

use super::{PeekInterface, ZeroizableSecret};

/// Instance of [`BytesMut`] protected by a type that impls the [`ExposeInterface`]
/// trait like `Secret<T>`.
///
/// Because of the nature of how the `BytesMut` type works, it needs some special
/// care in order to have a proper zeroizing drop handler.
#[derive(Clone)]
#[cfg_attr(docsrs, cfg(feature = "bytes"))]
pub struct SecretBytesMut(BytesMut);

impl SecretBytesMut {
    /// Wrap bytes in `SecretBytesMut`
    pub fn new(bytes: impl Into<BytesMut>) -> Self {
        Self(bytes.into())
    }
}

impl PeekInterface<BytesMut> for SecretBytesMut {
    fn peek(&self) -> &BytesMut {
        &self.0
    }

    fn peek_mut(&mut self) -> &mut BytesMut {
        &mut self.0
    }
}

impl fmt::Debug for SecretBytesMut {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "SecretBytesMut([REDACTED])")
    }
}

impl From<BytesMut> for SecretBytesMut {
    fn from(bytes: BytesMut) -> Self {
        Self::new(bytes)
    }
}

impl Drop for SecretBytesMut {
    fn drop(&mut self) {
        self.0.resize(self.0.capacity(), 0);
        self.0.as_mut().zeroize();
        debug_assert!(self.0.as_ref().iter().all(|b| *b == 0));
    }
}

#[cfg(all(feature = "bytes", feature = "serde"))]
impl<'de> Deserialize<'de> for SecretBytesMut {
    fn deserialize<D: de::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
        struct SecretBytesVisitor;

        impl<'de> de::Visitor<'de> for SecretBytesVisitor {
            type Value = SecretBytesMut;

            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
                formatter.write_str("byte array")
            }

            #[inline]
            fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
            where
                E: de::Error,
            {
                let mut bytes = BytesMut::with_capacity(v.len());
                bytes.extend_from_slice(v);
                Ok(SecretBytesMut(bytes))
            }

            #[inline]
            fn visit_seq<V>(self, mut seq: V) -> Result<Self::Value, V::Error>
            where
                V: de::SeqAccess<'de>,
            {
                // 4096 is cargo culted from upstream
                let len = core::cmp::min(seq.size_hint().unwrap_or(0), 4096);
                let mut bytes = BytesMut::with_capacity(len);

                use bytes::BufMut;

                while let Some(value) = seq.next_element()? {
                    bytes.put_u8(value);
                }

                Ok(SecretBytesMut(bytes))
            }
        }

        deserializer.deserialize_bytes(SecretBytesVisitor)
    }
}


impl SubscriptionNew {
    pub async fn insert(self, conn: &PgPooledConn) -> StorageResult<Subscription> {
        generics::generic_insert(conn, self).await
    }
}


pub struct ZslPaymentsResponse {
    process_type: ProcessType,
    process_code: ProcessCode,
    status: String,
    mer_ref: String,
    mer_id: String,
    enctype: EncodingType,
    txn_url: String,
    signature: Secret<String>,
}


pub struct NovalnetRawCardDetails {
    card_number: CardNumber,
    card_expiry_month: Secret<String>,
    card_expiry_year: Secret<String>,
}


impl api::Refund for Aci {}


pub struct AppState {
    pub conf: Arc<Settings<RawSecret>>,
    pub encryption_client: Arc<dyn EncryptionManagementInterface>,
}


OpenAPI Block Path: components.schemas.AuthenticationConnectors
{
  "type": "string",
  "enum": [
    "threedsecureio",
    "netcetera",
    "gpayments",
    "ctp_mastercard",
    "unified_authentication_service",
    "juspaythreedsserver",
    "ctp_visa"
  ]
}


pub fn collect(self) -> RefundMetricsBucketValue {
        let (successful_refunds, total_refunds, refund_success_rate) =
            self.refund_success_rate.collect();
        let (refund_processed_amount, refund_processed_count, refund_processed_amount_in_usd) =
            self.processed_amount.collect();
        RefundMetricsBucketValue {
            successful_refunds,
            total_refunds,
            refund_success_rate,
            refund_count: self.refund_count.collect(),
            refund_success_count: self.refund_success.collect(),
            refund_processed_amount,
            refund_processed_amount_in_usd,
            refund_processed_count,
            refund_reason_distribution: self.refund_reason_distribution.collect(),
            refund_error_message_distribution: self.refund_error_message_distribution.collect(),
            refund_reason_count: self.refund_reason.collect(),
            refund_error_message_count: self.refund_error_message.collect(),
        }
    }


Documentation: api-reference/v2/customers/customers--list.mdx
# Type: Doc File

---
openapi: get /v2/customers/list
---


pub struct FiuuPaymentRequest {
    #[serde(rename = "MerchantID")]
    merchant_id: Secret<String>,
    reference_no: String,
    txn_type: TxnType,
    txn_currency: Currency,
    txn_amount: StringMajorUnit,
    signature: Secret<String>,
    #[serde(rename = "ReturnURL")]
    return_url: Option<String>,
    #[serde(rename = "NotificationURL")]
    notification_url: Option<Url>,
    #[serde(flatten)]
    payment_method_data: FiuuPaymentMethodData,
}


/// Set the private fields of merchant account
pub struct MerchantAccountSetter {
    pub id: common_utils::id_type::MerchantId,
    pub merchant_name: OptionalEncryptableName,
    pub merchant_details: OptionalEncryptableValue,
    pub publishable_key: String,
    pub storage_scheme: MerchantStorageScheme,
    pub metadata: Option<pii::SecretSerdeValue>,
    pub created_at: time::PrimitiveDateTime,
    pub modified_at: time::PrimitiveDateTime,
    pub organization_id: common_utils::id_type::OrganizationId,
    pub recon_status: diesel_models::enums::ReconStatus,
    pub is_platform_account: bool,
    pub version: common_enums::ApiVersion,
    pub product_type: Option<common_enums::MerchantProductType>,
    pub merchant_account_type: common_enums::MerchantAccountType,
}


/// Trait to convert the raw data to the required format for encryption service request
pub trait ConvertRaw {
    /// Return type of the convert_raw function
    type Output: serde::Serialize;
    /// Function to convert the raw data to the required format for encryption service request
    fn convert_raw(self) -> Result<Self::Output, errors::KeyManagerClientError>;
}


/// Retains the connector name and payment method in every flattened element
    pub fn from_payment_connectors_list(payment_connectors: Vec<MerchantConnectorAccount>) -> Self {
        let payment_methods_enabled_flattened_with_connector = payment_connectors
            .into_iter()
            .map(|connector| {
                (
                    connector
                        .payment_methods_enabled
                        .clone()
                        .unwrap_or_default(),
                    connector.connector_name,
                    connector.get_id(),
                )
            })
            .flat_map(
                |(payment_method_enabled, connector, merchant_connector_id)| {
                    payment_method_enabled
                        .into_iter()
                        .flat_map(move |payment_method| {
                            let request_payment_methods_enabled =
                                payment_method.payment_method_subtypes.unwrap_or_default();
                            let length = request_payment_methods_enabled.len();
                            request_payment_methods_enabled.into_iter().zip(
                                std::iter::repeat((
                                    connector,
                                    merchant_connector_id.clone(),
                                    payment_method.payment_method_type,
                                ))
                                .take(length),
                            )
                        })
                },
            )
            .map(
                |(request_payment_methods, (connector, merchant_connector_id, payment_method))| {
                    PaymentMethodsEnabledForConnector {
                        payment_methods_enabled: request_payment_methods,
                        connector,
                        payment_method,
                        merchant_connector_id,
                    }
                },
            )
            .collect();

        Self {
            payment_methods_enabled: payment_methods_enabled_flattened_with_connector,
        }
    }


pub struct DwollaErrorResponse {
    pub code: String,
    pub message: String,
    pub _embedded: Option<Vec<DwollaErrorDetails>>,
    pub reason: Option<String>,
}


File: crates/router/src/core/payments/operations/payment_reject.rs
 Public structs: 1

use std::marker::PhantomData;

use api_models::{enums::FrmSuggestion, payments::PaymentsCancelRequest};
use async_trait::async_trait;
use error_stack::ResultExt;
use router_derive;
use router_env::{instrument, tracing};

use super::{BoxedOperation, Domain, GetTracker, Operation, UpdateTracker, ValidateRequest};
use crate::{
    core::{
        errors::{self, RouterResult, StorageErrorExt},
        payments::{helpers, operations, PaymentAddress, PaymentData},
    },
    events::audit_events::{AuditEvent, AuditEventType},
    routes::{app::ReqState, SessionState},
    services,
    types::{
        api::{self, PaymentIdTypeExt},
        domain,
        storage::{self, enums},
    },
    utils::OptionExt,
};

#[derive(Debug, Clone, Copy, router_derive::PaymentOperation)]
#[operation(operations = "all", flow = "cancel")]
pub struct PaymentReject;

type PaymentRejectOperation<'b, F> = BoxedOperation<'b, F, PaymentsCancelRequest, PaymentData<F>>;

#[async_trait]
impl<F: Send + Clone + Sync> GetTracker<F, PaymentData<F>, PaymentsCancelRequest>
    for PaymentReject
{
    #[instrument(skip_all)]
    async fn get_trackers<'a>(
        &'a self,
        state: &'a SessionState,
        payment_id: &api::PaymentIdType,
        _request: &PaymentsCancelRequest,
        merchant_context: &domain::MerchantContext,
        _auth_flow: services::AuthFlow,
        _header_payload: &hyperswitch_domain_models::payments::HeaderPayload,
    ) -> RouterResult<operations::GetTrackerResponse<'a, F, PaymentsCancelRequest, PaymentData<F>>>
    {
        let db = &*state.store;
        let key_manager_state = &state.into();

        let merchant_id = merchant_context.get_merchant_account().get_id();
        let storage_scheme = merchant_context.get_merchant_account().storage_scheme;
        let payment_id = payment_id
            .get_payment_intent_id()
            .change_context(errors::ApiErrorResponse::PaymentNotFound)?;

        let payment_intent = db
            .find_payment_intent_by_payment_id_merchant_id(
                key_manager_state,
                &payment_id,
                merchant_id,
                merchant_context.get_merchant_key_store(),
                storage_scheme,
            )
            .await
            .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?;

        helpers::validate_payment_status_against_not_allowed_statuses(
            payment_intent.status,
            &[
                enums::IntentStatus::Cancelled,
                enums::IntentStatus::Failed,
                enums::IntentStatus::Succeeded,
                enums::IntentStatus::Processing,
            ],
            "reject",
        )?;

        let attempt_id = payment_intent.active_attempt.get_id().clone();
        let payment_attempt = db
            .find_payment_attempt_by_payment_id_merchant_id_attempt_id(
                &payment_intent.payment_id,
                merchant_id,
                attempt_id.clone().as_str(),
                storage_scheme,
            )
            .await
            .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?;

        let shipping_address = helpers::get_address_by_id(
            state,
            payment_intent.shipping_address_id.clone(),
            merchant_context.get_merchant_key_store(),
            &payment_intent.payment_id,
            merchant_id,
            merchant_context.get_merchant_account().storage_scheme,
        )
        .await?;

        let billing_address = helpers::get_address_by_id(
            state,
            payment_intent.billing_address_id.clone(),
            merchant_context.get_merchant_key_store(),
            &payment_intent.payment_id,
            merchant_id,
            merchant_context.get_merchant_account().storage_scheme,
        )
        .await?;

        let payment_method_billing = helpers::get_address_by_id(
            state,
            payment_attempt.payment_method_billing_address_id.clone(),
            merchant_context.get_merchant_key_store(),
            &payment_intent.payment_id,
            merchant_id,
            merchant_context.get_merchant_account().storage_scheme,
        )
        .await?;

        let currency = payment_attempt.currency.get_required_value("currency")?;
        let amount = payment_attempt.get_total_amount().into();

        let frm_response = if cfg!(feature = "frm") {
            db.find_fraud_check_by_payment_id(payment_intent.payment_id.clone(), merchant_context.get_merchant_account().get_id().clone())
                .await
                .change_context(errors::ApiErrorResponse::PaymentNotFound)
                .attach_printable_lazy(|| {
                    format!("Error while retrieving frm_response, merchant_id: {:?}, payment_id: {attempt_id}", merchant_context.get_merchant_account().get_id())
                })
                .ok()
        } else {
            None
        };

        let profile_id = payment_intent
            .profile_id
            .as_ref()
            .get_required_value("profile_id")
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable("'profile_id' not set in payment intent")?;

        let business_profile = state
            .store
            .find_business_profile_by_profile_id(
                key_manager_state,
                merchant_context.get_merchant_key_store(),
                profile_id,
            )
            .await
            .to_not_found_response(errors::ApiErrorResponse::ProfileNotFound {
                id: profile_id.get_string_repr().to_owned(),
            })?;

        let payment_data = PaymentData {
            flow: PhantomData,
            payment_intent,
            payment_attempt,
            currency,
            amount,
            email: None,
            mandate_id: None,
            mandate_connector: None,
            setup_mandate: None,
            customer_acceptance: None,
            token: None,
            address: PaymentAddress::new(
                shipping_address.as_ref().map(From::from),
                billing_address.as_ref().map(From::from),
                payment_method_billing.as_ref().map(From::from),
                business_profile.use_billing_as_payment_method_billing,
            ),
            token_data: None,
            confirm: None,
            payment_method_data: None,
            payment_method_token: None,
            payment_method_info: None,
            force_sync: None,
            all_keys_required: None,
            refunds: vec![],
            disputes: vec![],
            attempts: None,
            sessions_token: vec![],
            card_cvc: None,
            creds_identifier: None,
            pm_token: None,
            connector_customer_id: None,
            recurring_mandate_payment_data: None,
            ephemeral_key: None,
            multiple_capture_data: None,
            redirect_response: None,
            surcharge_details: None,
            frm_message: frm_response,
            payment_link_data: None,
            incremental_authorization_details: None,
            authorizations: vec![],
            authentication: None,
            recurring_details: None,
            poll_config: None,
            tax_data: None,
            session_id: None,
            service_details: None,
            card_testing_guard_data: None,
            vault_operation: None,
            threeds_method_comp_ind: None,
            whole_connector_response: None,
        };

        let get_trackers_response = operations::GetTrackerResponse {
            operation: Box::new(self),
            customer_details: None,
            payment_data,
            business_profile,
            mandate_type: None,
        };

        Ok(get_trackers_response)
    }
}

#[async_trait]
impl<F: Clone + Sync> UpdateTracker<F, PaymentData<F>, PaymentsCancelRequest> for PaymentReject {
    #[instrument(skip_all)]
    async fn update_trackers<'b>(
        &'b self,
        state: &'b SessionState,
        req_state: ReqState,
        mut payment_data: PaymentData<F>,
        _customer: Option<domain::Customer>,
        storage_scheme: enums::MerchantStorageScheme,
        _updated_customer: Option<storage::CustomerUpdate>,
        key_store: &domain::MerchantKeyStore,
        _should_decline_transaction: Option<FrmSuggestion>,
        _header_payload: hyperswitch_domain_models::payments::HeaderPayload,
    ) -> RouterResult<(PaymentRejectOperation<'b, F>, PaymentData<F>)>
    where
        F: 'b + Send,
    {
        let intent_status_update = storage::PaymentIntentUpdate::RejectUpdate {
            status: enums::IntentStatus::Failed,
            merchant_decision: Some(enums::MerchantDecision::Rejected.to_string()),
            updated_by: storage_scheme.to_string(),
        };
        let (error_code, error_message) =
            payment_data
                .frm_message
                .clone()
                .map_or((None, None), |fraud_check| {
                    (
                        Some(Some(fraud_check.frm_status.to_string())),
                        Some(fraud_check.frm_reason.map(|reason| reason.to_string())),
                    )
                });
        let attempt_status_update = storage::PaymentAttemptUpdate::RejectUpdate {
            status: enums::AttemptStatus::Failure,
            error_code,
            error_message,
            updated_by: storage_scheme.to_string(),
        };

        payment_data.payment_intent = state
            .store
            .update_payment_intent(
                &state.into(),
                payment_data.payment_intent,
                intent_status_update,
                key_store,
                storage_scheme,
            )
            .await
            .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?;

        payment_data.payment_attempt = state
            .store
            .update_payment_attempt_with_attempt_id(
                payment_data.payment_attempt.clone(),
                attempt_status_update,
                storage_scheme,
            )
            .await
            .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?;
        let error_code = payment_data.payment_attempt.error_code.clone();
        let error_message = payment_data.payment_attempt.error_message.clone();
        req_state
            .event_context
            .event(AuditEvent::new(AuditEventType::PaymentReject {
                error_code,
                error_message,
            }))
            .with(payment_data.to_event())
            .emit();

        Ok((Box::new(self), payment_data))
    }
}

impl<F: Send + Clone + Sync> ValidateRequest<F, PaymentsCancelRequest, PaymentData<F>>
    for PaymentReject
{
    #[instrument(skip_all)]
    fn validate_request<'a, 'b>(
        &'b self,
        request: &PaymentsCancelRequest,
        merchant_context: &'a domain::MerchantContext,
    ) -> RouterResult<(PaymentRejectOperation<'b, F>, operations::ValidateResult)> {
        Ok((
            Box::new(self),
            operations::ValidateResult {
                merchant_id: merchant_context.get_merchant_account().get_id().to_owned(),
                payment_id: api::PaymentIdType::PaymentIntentId(request.payment_id.to_owned()),
                storage_scheme: merchant_context.get_merchant_account().storage_scheme,
                requeue: false,
            },
        ))
    }
}


pub async fn payment_method_retrieve_api() {}


**Full Changelog:** [`2024.08.02.0...2024.08.05.0`](https://github.com/juspay/hyperswitch/compare/2024.08.02.0...2024.08.05.0)

- - -

## 2024.08.02.0

### Features

- **auth:**
  - Add support for partial-auth, by facilitating injection of authentication parameters in headers ([#4802](https://github.com/juspay/hyperswitch/pull/4802)) ([`1d4c87a`](https://github.com/juspay/hyperswitch/commit/1d4c87a9e37ab1fc05754208ba4fbbcf15ad895a))
  - Add `profile_id` in `AuthenticationData` ([#5492](https://github.com/juspay/hyperswitch/pull/5492)) ([`b4eb601`](https://github.com/juspay/hyperswitch/commit/b4eb6016a4e696acf155732592a6571363c24e64))
- **business_profile:** Introduce domain models for business profile v1 and v2 APIs ([#5497](https://github.com/juspay/hyperswitch/pull/5497)) ([`537630f`](https://github.com/juspay/hyperswitch/commit/537630f00482939d4c0b49c643dee3763fe0e046))
- **connector:** [Paybox] add connector template code ([#5485](https://github.com/juspay/hyperswitch/pull/5485)) ([`5e1eb4a`](https://github.com/juspay/hyperswitch/commit/5e1eb4af863265c94299189de983e02a255e7e62))
- **core:** Accept business profile in core functions for payments, refund, payout and disputes ([#5498](https://github.com/juspay/hyperswitch/pull/5498)) ([`fb32b61`](https://github.com/juspay/hyperswitch/commit/fb32b61edfa2b4190a5717850aeca6b3b0d7db54))
- **cypress:** Add corner cases ([#5481](https://github.com/juspay/hyperswitch/pull/5481)) ([`c0f4577`](https://github.com/juspay/hyperswitch/commit/c0f45771b0b4d7d60918ae03aca9f14162ff3218))
- **opensearch:** Updated status filter field name to match index and added time-range based search ([#5468](https://github.com/juspay/hyperswitch/pull/5468)) ([`625f5ae`](https://github.com/juspay/hyperswitch/commit/625f5ae289ca93a1a6d469d6a0f71d7492f22bc5))

### Bug Fixes

- **open_payment_links:** Send displaySavedPaymentMethods as false explicitly for open payment links ([#5501](https://github.com/juspay/hyperswitch/pull/5501)) ([`b4e7717`](https://github.com/juspay/hyperswitch/commit/b4e77170559d5912758f18d2db46bf25eb5277b2))

### Refactors

- **role:** Determine level of role entity ([#5488](https://github.com/juspay/hyperswitch/pull/5488)) ([`c036fd7`](https://github.com/juspay/hyperswitch/commit/c036fd7f41a21eb481859671db672b0bcebdca97))
- **router:** Domain and diesel model changes for merchant_connector_account create v2 flow ([#5462](https://github.com/juspay/hyperswitch/pull/5462)) ([`85209d1`](https://github.com/juspay/hyperswitch/commit/85209d12ae3439b555983d62b2cc3bf764c1b441))
- **routing:** Api v2 for routing create and activate endpoints ([#5423](https://github.com/juspay/hyperswitch/pull/5423)) ([`6140cfe`](https://github.com/juspay/hyperswitch/commit/6140cfe04ea7b3f895f8989dbf2803a06b1a6dd2))

**Full Changelog:** [`2024.08.01.0...2024.08.02.0`](https://github.com/juspay/hyperswitch/compare/2024.08.01.0...2024.08.02.0)

- - -

## 2024.08.01.0

### Bug Fixes

- **payment_link:** Move redirection fn to global scope for open links ([#5494](https://github.com/juspay/hyperswitch/pull/5494)) ([`7ddfbf5`](https://github.com/juspay/hyperswitch/commit/7ddfbf51c3c3db99041e3d175a9100a60a339fe8))

### Documentation

- API-Ref changes for Payouts ([#5236](https://github.com/juspay/hyperswitch/pull/5236)) ([`540ef07`](https://github.com/juspay/hyperswitch/commit/540ef071cb238a56d52d06687226aab7fd0dfe68))

**Full Changelog:** [`2024.07.31.0...2024.08.01.0`](https://github.com/juspay/hyperswitch/compare/2024.07.31.0...2024.08.01.0)

- - -

## 2024.07.31.0

### Features

- **connector:** [BAMBORA, BITPAY, STAX] Move connector to hyperswitch_connectors ([#5450](https://github.com/juspay/hyperswitch/pull/5450)) ([`827fa07`](https://github.com/juspay/hyperswitch/commit/827fa07418b0514cbc5a43af2e4c7a88d1b7b4e7))
- **payment_link:** Add provision for secured payment links ([#5357](https://github.com/juspay/hyperswitch/pull/5357)) ([`043abb5`](https://github.com/juspay/hyperswitch/commit/043abb59b9291e18824d16363f60657f22bd33e1))
- Rename columns in organization for v2 ([#5424](https://github.com/juspay/hyperswitch/pull/5424)) ([`a791391`](https://github.com/juspay/hyperswitch/commit/a791391e2ac125ef7bb6a92de5f1419e673bdfe0))

### Bug Fixes

- **connector:** [Pix] convert data type of pix fields ([#5476](https://github.com/juspay/hyperswitch/pull/5476)) ([`be9347b`](https://github.com/juspay/hyperswitch/commit/be9347b8d56c0a6cf0d04cf51c75dd6426d3a21a))

### Refactors

- **configs:** Include env for cybersource in integration_test ([#5474](https://github.com/juspay/hyperswitch/pull/5474)) ([`b3b71b1`](https://github.com/juspay/hyperswitch/commit/b3b71b10c3627868420648e70913a0620dcb3b6e))
- **id_type:** Use macros for defining ID types and implementing common traits ([#5471](https://github.com/juspay/hyperswitch/pull/5471)) ([`1d4fb1d`](https://github.com/juspay/hyperswitch/commit/1d4fb1d2474190ea0a70810e416c61883fab34b8))

### Documentation

- Update postgreSQL database url ([#5482](https://github.com/juspay/hyperswitch/pull/5482)) ([`ef7fa0d`](https://github.com/juspay/hyperswitch/commit/ef7fa0d16ebe12bd86572c7ab80e7caa70d75578))

**Full Changelog:** [`2024.07.30.0...2024.07.31.0`](https://github.com/juspay/hyperswitch/compare/2024.07.30.0...2024.07.31.0)

- - -

## 2024.07.30.0

### Features

- Add env variable for enable key manager service ([#5442](https://github.com/juspay/hyperswitch/pull/5442)) ([`db26d32`](https://github.com/juspay/hyperswitch/commit/db26d32d8465e20cf3835fbfe6d0a19688078b8c))

### Refactors

- **router:** Remove `connector_account_details` and `connector_webhook_details` in merchant_connector_account list response ([#5457](https://github.com/juspay/hyperswitch/pull/5457)) ([`45a1494`](https://github.com/juspay/hyperswitch/commit/45a149418f1dad0cd27f975dc3dd56c68172b9dd))

**Full Changelog:** [`2024.07.29.0...2024.07.30.0`](https://github.com/juspay/hyperswitch/compare/2024.07.29.0...2024.07.30.0)

- - -

## 2024.07.29.0

### Features

- **connector:**
  - [FISERV] Move connector to hyperswitch_connectors ([#5441](https://github.com/juspay/hyperswitch/pull/5441)) ([`2bee694`](https://github.com/juspay/hyperswitch/commit/2bee694d5bb7393c11817bbee26b459609f6dd8c))
  - [Bambora APAC] add mandate flow ([#5376](https://github.com/juspay/hyperswitch/pull/5376)) ([`dbfa006`](https://github.com/juspay/hyperswitch/commit/dbfa006b475736bf415588680d7fc1a16bf16891))
- **payments:** Support sort criteria in payments list ([#5389](https://github.com/juspay/hyperswitch/pull/5389)) ([`043ea6d`](https://github.com/juspay/hyperswitch/commit/043ea6d8dc9fe8108e0b7eb8113217bc37fa488a))

### Bug Fixes

- Added created at and modified at keys in PaymentAttemptResponse ([#5412](https://github.com/juspay/hyperswitch/pull/5412)) ([`9795397`](https://github.com/juspay/hyperswitch/commit/979539702190363c67045d509be04498efd9a1fa))

### Refactors

- **connector:** Add amount conversion framework to placetopay ([#4988](https://github.com/juspay/hyperswitch/pull/4988)) ([`08334da`](https://github.com/juspay/hyperswitch/commit/08334dae82145e1fd699e0008fedcbd8bb7b23c7))
- **merchant_account_v2:** Recreate id for `merchant_account` v2 ([#5439](https://github.com/juspay/hyperswitch/pull/5439)) ([`93976db`](https://github.com/juspay/hyperswitch/commit/93976db30a91b3e67d854681fb4b9db8eea7e295))
- **opensearch:** Add Error Handling for Empty Query and Filters in Request ([#5432](https://github.com/juspay/hyperswitch/pull/5432)) ([`b60933e`](https://github.com/juspay/hyperswitch/commit/b60933e310abb4ee56355f28dfb56d9c60083f04))

### Miscellaneous Tasks

- Address Rust 1.80 clippy lints ([#5447](https://github.com/juspay/hyperswitch/pull/5447)) ([`074e90c`](https://github.com/juspay/hyperswitch/commit/074e90c9f9fbc26255ed27400a6a781aa6958339))

**Full Changelog:** [`2024.07.26.0...2024.07.29.0`](https://github.com/juspay/hyperswitch/compare/2024.07.26.0...2024.07.29.0)

- - -

## 2024.07.26.0

### Features

- **connector:** [HELCIM] Move connector to hyperswitch_connectors ([#5287](https://github.com/juspay/hyperswitch/pull/5287)) ([`0f89a0a`](https://github.com/juspay/hyperswitch/commit/0f89a0acbfc2d55f415e0daeb27e8d9022e6a862))
- **events:** Forward the tenant configuration as part of the kafka message ([#5224](https://github.com/juspay/hyperswitch/pull/5224)) ([`623cf4c`](https://github.com/juspay/hyperswitch/commit/623cf4c841847f109597ee50017d6cfc0b4d9982))

### Bug Fixes

- **cypress:** Fix cypress tests, failing due to error codes being recently changed ([#5425](https://github.com/juspay/hyperswitch/pull/5425)) ([`7228a87`](https://github.com/juspay/hyperswitch/commit/7228a874a3db43b89ae07941b04396215db394ef))
- **euclid:** Change the address taken in SessionFlowRouting from shipping to billing address ([#5435](https://github.com/juspay/hyperswitch/pull/5435)) ([`9ca9545`](https://github.com/juspay/hyperswitch/commit/9ca9545318d8e62d62b4dc58a09b90fcdeb58870))

### Refactors

- **connector:** Add amount conversion framework to payone ([#4981](https://github.com/juspay/hyperswitch/pull/4981)) ([`5eccffa`](https://github.com/juspay/hyperswitch/commit/5eccffac9d9f2b3e38ad07f6e12907e2c135b840))
- **user_roles:** Make org and merchant id nullable ([#5353](https://github.com/juspay/hyperswitch/pull/5353)) ([`0330aff`](https://github.com/juspay/hyperswitch/commit/0330aff958b80872fbd6a6fccc61ff1984c59511))

**Full Changelog:** [`2024.07.25.0...2024.07.26.0`](https://github.com/juspay/hyperswitch/compare/2024.07.25.0...2024.07.26.0)

- - -

## 2024.07.25.0

### Features

- **connector:** [Itaubank] Add refund and rsync flow ([#5420](https://github.com/juspay/hyperswitch/pull/5420)) ([`920b323`](https://github.com/juspay/hyperswitch/commit/920b3236ee132dac446fc73de82d24806c6b5148))
- **router:** Add merchant_connector_account create v2 api flow ([#5385](https://github.com/juspay/hyperswitch/pull/5385)) ([`98349a0`](https://github.com/juspay/hyperswitch/commit/98349a0c3bbc438e541a03e7fe1c005e5751e6e0))
- Add create retrieve and update api endpoints for organization resource ([#5361](https://github.com/juspay/hyperswitch/pull/5361)) ([`26b8783`](https://github.com/juspay/hyperswitch/commit/26b878308f7e493d6adb8c08b54a5498406eb28a))
- Create additional columns in organization table ([#5380](https://github.com/juspay/hyperswitch/pull/5380)) ([`65471da`](https://github.com/juspay/hyperswitch/commit/65471da57b19c8eb2922fba0350e06b37b53f45f))

### Bug Fixes

- **euclid:** Remove business_profile routing feature flag ([#5430](https://github.com/juspay/hyperswitch/pull/5430)) ([`e18ea7a`](https://github.com/juspay/hyperswitch/commit/e18ea7a7bab257a6082639e84da8d9e44f31168f))

### Refactors

- **connector:**
  - Added amount conversion framework for billwerk ([#4972](https://github.com/juspay/hyperswitch/pull/4972)) ([`9d9dce9`](https://github.com/juspay/hyperswitch/commit/9d9dce90fc3dc2a51afa2b11035c4ae729329df4))
  - Added amount conversion framework for bitpay ([#4973](https://github.com/juspay/hyperswitch/pull/4973)) ([`83dbb7a`](https://github.com/juspay/hyperswitch/commit/83dbb7a8daf44bdd3d8c0e98973bba4b90eb5861))
- **core:** Patch file for removal of id from schema ([#5398](https://github.com/juspay/hyperswitch/pull/5398)) ([`ff3b9a2`](https://github.com/juspay/hyperswitch/commit/ff3b9a2a12cd7f7e6c20f81777f6862b1f229bd4))
- **merchant_id:** Create domain type for `merchant_id` ([#5408](https://github.com/juspay/hyperswitch/pull/5408)) ([`7068fbf`](https://github.com/juspay/hyperswitch/commit/7068fbfbe2f561f71c2358d8d2a744d28672a892))

**Full Changelog:** [`2024.07.24.0...2024.07.25.0`](https://github.com/juspay/hyperswitch/compare/2024.07.24.0...2024.07.25.0)

- - -

## 2024.07.24.0

### Features

- **connector:** [WELLSFARGO] Add template code ([#5333](https://github.com/juspay/hyperswitch/pull/5333)) ([`94bb3e7`](https://github.com/juspay/hyperswitch/commit/94bb3e78fddf310d9ee3211f98a386e4f8261242))
- **customer:** Customer v2 refactor for customer create end point ([#5350](https://github.com/juspay/hyperswitch/pull/5350)) ([`aaf1f2b`](https://github.com/juspay/hyperswitch/commit/aaf1f2b1e5e1f473154a57af0d1b9402bd238ec4))

### Bug Fixes

- **connector:** [Datatrans] Handling for 4-Digit YYYY input and Correct 3DS Routing to no_3ds ([#5410](https://github.com/juspay/hyperswitch/pull/5410)) ([`3e16219`](https://github.com/juspay/hyperswitch/commit/3e1621944562a0fca3014a190393b744d235bc4c))

### Refactors

- **connector:**
  - Add amount conversion framework to volt ([#4985](https://github.com/juspay/hyperswitch/pull/4985)) ([`e4b3982`](https://github.com/juspay/hyperswitch/commit/e4b3982c13cedf0f7feaec22df414761e22d98df))
  - [Itaubank] add dynamic fields for pix ([#5419](https://github.com/juspay/hyperswitch/pull/5419)) ([`afae590`](https://github.com/juspay/hyperswitch/commit/afae5906a8d6ceab136393c7588bfc447e822ddc))

### Miscellaneous Tasks

- **users:** Email templates footer icon style enhance ([#5375](https://github.com/juspay/hyperswitch/pull/5375)) ([`876eeea`](https://github.com/juspay/hyperswitch/commit/876eeea0f426f63d0419021ba85372a016d46e27))

**Full Changelog:** [`2024.07.23.0...2024.07.24.0`](https://github.com/juspay/hyperswitch/compare/2024.07.23.0...2024.07.24.0)

- - -

## 2024.07.23.0

### Features

- **connector:** [Itau Bank] Add payment and sync flow for Pix ([#5342](https://github.com/juspay/hyperswitch/pull/5342)) ([`3fef96e`](https://github.com/juspay/hyperswitch/commit/3fef96e727ebb411d5699b8b37bdec30a2606da0))

### Bug Fixes

- **router:** Store `network_transaction_id` in stripe `authorize` flow ([#5399](https://github.com/juspay/hyperswitch/pull/5399)) ([`be78dfc`](https://github.com/juspay/hyperswitch/commit/be78dfc04eff671fb0b4e6037c84aee8ab367e70))
- Add offset and limit to key transfer API ([#5358](https://github.com/juspay/hyperswitch/pull/5358)) ([`b393803`](https://github.com/juspay/hyperswitch/commit/b393803a6199a12f86d7bbdc998e5a0d8366c000))

### Refactors

- **connector:** Add billing_country in klarna dynamic fields ([#5373](https://github.com/juspay/hyperswitch/pull/5373)) ([`4838a86`](https://github.com/juspay/hyperswitch/commit/4838a86ebcb5000e65293e0d095e5de95e3a64a0))
- **core:** Change primary keys in payment_methods table ([#5393](https://github.com/juspay/hyperswitch/pull/5393)) ([`ca749b3`](https://github.com/juspay/hyperswitch/commit/ca749b32591edcbf4676da4327f8b6ccbc839d4b))
- **dashboard_metadata:** Alter query for merchant scoped metadata ([#5397](https://github.com/juspay/hyperswitch/pull/5397)) ([`eaa391a`](https://github.com/juspay/hyperswitch/commit/eaa391a959076424399fb9331a78a16eaf790478))
- **router:** Make `original_payment_authorized_currency` and `original_payment_authorized_amount` mandatory fields for `Discover` cards and `Cybersource` connector during payment method migration. ([#5370](https://github.com/juspay/hyperswitch/pull/5370)) ([`06f1406`](https://github.com/juspay/hyperswitch/commit/06f1406cbc350a71f961a19dc2a6cfef2ceeb3a1))

### Miscellaneous Tasks

- Add missing logs for surcharge flow ([#5258](https://github.com/juspay/hyperswitch/pull/5258)) ([`bc19fca`](https://github.com/juspay/hyperswitch/commit/bc19fca1f4e76be6131e9c870b8aa1c709fef578))
- Add customer, shipping and billing details to payment_response for payment list api ([#5401](https://github.com/juspay/hyperswitch/pull/5401)) ([`fa6c63b`](https://github.com/juspay/hyperswitch/commit/fa6c63bd5409ec45f23ddf4616c5eb3cf399aa1b))

**Full Changelog:** [`2024.07.20.0...2024.07.23.0`](https://github.com/juspay/hyperswitch/compare/2024.07.20.0...2024.07.23.0)

- - -

## 2024.07.20.0

### Features

- **merchant_account_v2:** Add merchant_account_v2 domain and diesel models ([#5365](https://github.com/juspay/hyperswitch/pull/5365)) ([`5861c5a`](https://github.com/juspay/hyperswitch/commit/5861c5a63b3ab228d886888962e5734b9018eab9))

### Bug Fixes

- Use encrypt api for all encryption and decryption ([#5379](https://github.com/juspay/hyperswitch/pull/5379)) ([`83849a5`](https://github.com/juspay/hyperswitch/commit/83849a5f3cbb1843013535b0631e6e3d38d037b7))

### Refactors

- **core:** Change primary keys in user, user_roles and roles tables ([#5374](https://github.com/juspay/hyperswitch/pull/5374)) ([`b51c8e1`](https://github.com/juspay/hyperswitch/commit/b51c8e1d12c2f0012b8210a6c25c989f9dd89c3b))

**Full Changelog:** [`2024.07.19.1...2024.07.20.0`](https://github.com/juspay/hyperswitch/compare/2024.07.19.1...2024.07.20.0)

- - -

## 2024.07.19.1

### Features

- **connector:** Plaid connector Integration ([#3952](https://github.com/juspay/hyperswitch/pull/3952)) ([`eb01680`](https://github.com/juspay/hyperswitch/commit/eb01680284fea4d61ef95418878d49104885352e))
- Encryption service integration to support batch encryption and decryption ([#5164](https://github.com/juspay/hyperswitch/pull/5164)) ([`33298b3`](https://github.com/juspay/hyperswitch/commit/33298b38081c46fe4ee38f8ad6ddffd2b98a1d5c))

### Refactors

- **connector:** Make the `original_authorized_amount` optional for MITs with `connector_mandate_details` ([#5311](https://github.com/juspay/hyperswitch/pull/5311)) ([`a8e2f3e`](https://github.com/juspay/hyperswitch/commit/a8e2f3ebc9da60ef41459b080d8856d3cadf8c41))
- **core:** Change primary key of refund table ([#5367](https://github.com/juspay/hyperswitch/pull/5367)) ([`c698921`](https://github.com/juspay/hyperswitch/commit/c698921c417da4f6f74887224818ccb5d92b9fc3))

**Full Changelog:** [`2024.07.19.0...2024.07.19.1`](https://github.com/juspay/hyperswitch/compare/2024.07.19.0...2024.07.19.1)

- - -

## 2024.07.19.0

### Features

- **connector:** [Itau Bank] Template for payment flows ([#5304](https://github.com/juspay/hyperswitch/pull/5304)) ([`ef1418f`](https://github.com/juspay/hyperswitch/commit/ef1418f978835a8df149181bc5e19053775490f2))

### Bug Fixes

- **core:** [payouts] failure of payout retrieve when token is expired ([#5362](https://github.com/juspay/hyperswitch/pull/5362)) ([`817d06c`](https://github.com/juspay/hyperswitch/commit/817d06c7faa14493674931ba51ab6c32769602d1))

### Refactors