pub struct AttemptAmountDetailsSetter {
    /// The total amount for this payment attempt. This includes all the surcharge and tax amounts.
    pub net_amount: MinorUnit,
    /// The amount that has to be captured,
    pub amount_to_capture: Option<MinorUnit>,
    /// Surcharge amount for the payment attempt.
    /// This is either derived by surcharge rules, or sent by the merchant
    pub surcharge_amount: Option<MinorUnit>,
    /// Tax amount for the payment attempt
    /// This is either derived by surcharge rules, or sent by the merchant
    pub tax_on_surcharge: Option<MinorUnit>,
    /// The total amount that can be captured for this payment attempt.
    pub amount_capturable: MinorUnit,
    /// Shipping cost for the payment attempt.
    pub shipping_cost: Option<MinorUnit>,
    /// Tax amount for the order.
    /// This is either derived by calling an external tax processor, or sent by the merchant
    pub order_tax_amount: Option<MinorUnit>,
}


        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods.clone(),
            specific_features: None,
        },
    );
    aci_supported_payment_methods.add(
        enums::PaymentMethod::BankRedirect,
        enums::PaymentMethodType::Ideal,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods.clone(),
            specific_features: None,
        },
    );
    aci_supported_payment_methods.add(
        enums::PaymentMethod::BankRedirect,
        enums::PaymentMethodType::Giropay,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods.clone(),
            specific_features: None,
        },
    );
    aci_supported_payment_methods.add(
        enums::PaymentMethod::BankRedirect,
        enums::PaymentMethodType::Sofort,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods.clone(),
            specific_features: None,
        },
    );
    aci_supported_payment_methods.add(
        enums::PaymentMethod::BankRedirect,
        enums::PaymentMethodType::Interac,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods.clone(),
            specific_features: None,
        },
    );
    aci_supported_payment_methods.add(
        enums::PaymentMethod::BankRedirect,
        enums::PaymentMethodType::Przelewy24,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods.clone(),
            specific_features: None,
        },
    );
    aci_supported_payment_methods.add(
        enums::PaymentMethod::BankRedirect,
        enums::PaymentMethodType::Trustly,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods.clone(),
            specific_features: None,
        },
    );
    aci_supported_payment_methods.add(
        enums::PaymentMethod::PayLater,
        enums::PaymentMethodType::Klarna,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods.clone(),
            specific_features: None,
        },
    );
    aci_supported_payment_methods
});

static ACI_CONNECTOR_INFO: ConnectorInfo = ConnectorInfo {
    display_name: "ACI",
    description:
        "ACI Payments delivers secure, real-time electronic payment solutions for businesses, banks, and governments, enabling seamless transactions across channels.",
    connector_type: enums::HyperswitchConnectorCategory::PaymentGateway,
    integration_status: enums::ConnectorIntegrationStatus::Beta,
};

static ACI_SUPPORTED_WEBHOOK_FLOWS: [enums::EventClass; 0] = [];

impl ConnectorSpecifications for Aci {
    fn get_connector_about(&self) -> Option<&'static ConnectorInfo> {
        Some(&ACI_CONNECTOR_INFO)
    }

    fn get_supported_payment_methods(&self) -> Option<&'static SupportedPaymentMethods> {
        Some(&*ACI_SUPPORTED_PAYMENT_METHODS)
    }

    fn get_supported_webhook_flows(&self) -> Option<&'static [enums::EventClass]> {
        Some(&ACI_SUPPORTED_WEBHOOK_FLOWS)
    }
}


pub struct PollConfig {
    pub delay_in_secs: i8,
    pub frequency: i8,
}


pub struct KlarnaRefundRequest {
    refunded_amount: MinorUnit,
    reference: Option<String>,
}


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

- - -

## 2024.06.28.0

### Features

- **router:** Skip apple pay session call if the browser is not Safari ([#5136](https://github.com/juspay/hyperswitch/pull/5136)) ([`d4dba55`](https://github.com/juspay/hyperswitch/commit/d4dba55fedc37ba9d1d54d28456ca17851ab9881))

### Bug Fixes

- **opensearch:** Show search results only if user has access permission to the index ([#5097](https://github.com/juspay/hyperswitch/pull/5097)) ([`9c49ded`](https://github.com/juspay/hyperswitch/commit/9c49ded104b81f1aefcc288e3ded64ebbd4d466f))

### Miscellaneous Tasks

- **postman:** Update Postman collection files ([`aa1e8f2`](https://github.com/juspay/hyperswitch/commit/aa1e8f243f7e9e9e3b6e3f809fc404077af3057b))
- Use generic phone numbers instead ([#5142](https://github.com/juspay/hyperswitch/pull/5142)) ([`57055ec`](https://github.com/juspay/hyperswitch/commit/57055ecab2300c2284d0e674a22247fa65776ed8))

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

- - -

## 2024.06.27.0

### Features

- **email:** Add `auth_id` in email types and send `auth_id` in email URLs ([#5120](https://github.com/juspay/hyperswitch/pull/5120)) ([`4ccd25d`](https://github.com/juspay/hyperswitch/commit/4ccd25d0dc0703f9ac9ff441bedc8a9ce4ce78c6))
- **router:** Add payments manual-update api ([#5045](https://github.com/juspay/hyperswitch/pull/5045)) ([`ed021c1`](https://github.com/juspay/hyperswitch/commit/ed021c1d9961a2723c9b2fecf9f35ff16ef08294))
- **users:**
  - Implemented openidconnect ([#5124](https://github.com/juspay/hyperswitch/pull/5124)) ([`ce7d0d4`](https://github.com/juspay/hyperswitch/commit/ce7d0d427d817eb4199f2f6ea8ea86a04bd98a26))
  - Add endpoint for terminate auth select ([#5135](https://github.com/juspay/hyperswitch/pull/5135)) ([`eb6afd6`](https://github.com/juspay/hyperswitch/commit/eb6afd66f29ecbe17a8487d514b54ddaf1893af3))
- Realtime user analytics ([#5098](https://github.com/juspay/hyperswitch/pull/5098)) ([`cd5a1a3`](https://github.com/juspay/hyperswitch/commit/cd5a1a34c50d5249d17ec91998fb96cd19119b9d))

### Bug Fixes

- **connector:** [BOA/CYBS] make risk information message optional ([#5107](https://github.com/juspay/hyperswitch/pull/5107)) ([`ffe90a4`](https://github.com/juspay/hyperswitch/commit/ffe90a41125a0eb1e8a858b336120e355fd3b69e))
- **docs:** Open-api fix for payment response ([#5103](https://github.com/juspay/hyperswitch/pull/5103)) ([`2e1167a`](https://github.com/juspay/hyperswitch/commit/2e1167acbcc06022985ce761d2d4e624bbbc97c3))

### Refactors

- **connector:**
  - Add amount framework to payme & Trustpay with googlePay, ApplePay for bluesnap, Noon & Trustpay ([#4833](https://github.com/juspay/hyperswitch/pull/4833)) ([`e69a7bd`](https://github.com/juspay/hyperswitch/commit/e69a7bda52784a7d7166f19e745bab6df72c7430))
  - Added amount conversion framework for cashtocode ([#4857](https://github.com/juspay/hyperswitch/pull/4857)) ([`86f4060`](https://github.com/juspay/hyperswitch/commit/86f4060d332b3515a92010287be32fe69508d451))
  - [AdyenPlatform]Throw 4xx instead of 5xx for source_balance_account ([#4990](https://github.com/juspay/hyperswitch/pull/4990)) ([`1c464ac`](https://github.com/juspay/hyperswitch/commit/1c464acc566fde23c68c4b4b30354f17e56acd80))

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

- - -

## 2024.06.25.1

### Features

- **router:** Updated `last_used_at` field for apple pay and google pay for CITs ([#5087](https://github.com/juspay/hyperswitch/pull/5087)) ([`7c639bf`](https://github.com/juspay/hyperswitch/commit/7c639bf878a96212c6e5c03e86a3787c2bc1e151))

### Bug Fixes

- **payment_methods:** Use existing field value of `nick_name` in db if not sent during request ([#5105](https://github.com/juspay/hyperswitch/pull/5105)) ([`ea74f3e`](https://github.com/juspay/hyperswitch/commit/ea74f3e537aca44c42bd1e9c80eb7a1e220c295d))
- **router:** Skip serialize if none for assurance_details_required in googlepay session response ([#5118](https://github.com/juspay/hyperswitch/pull/5118)) ([`ec8a393`](https://github.com/juspay/hyperswitch/commit/ec8a39339d692ceb080d08f3e83667441909bf62))

### Refactors

- Separate DB queries and HTML creation for payout links ([#4967](https://github.com/juspay/hyperswitch/pull/4967)) ([`9e4b2d1`](https://github.com/juspay/hyperswitch/commit/9e4b2d1c11204b1c18bd97e586191b7518e6d91f))

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

- - -

## 2024.06.25.0

### Features

- **ci:** Add vector to handle logs pipeline ([#5021](https://github.com/juspay/hyperswitch/pull/5021)) ([`fed7b69`](https://github.com/juspay/hyperswitch/commit/fed7b697995b37bf3ef198121de571c6e338863c))
- **router:** Add support for googlepay step up flow ([#2744](https://github.com/juspay/hyperswitch/pull/2744)) ([`ff84d78`](https://github.com/juspay/hyperswitch/commit/ff84d78c6512f70d761148274e97286f5cf021dd))
- **users:** Decision manager flow changes for SSO ([#4995](https://github.com/juspay/hyperswitch/pull/4995)) ([`8ceaaa9`](https://github.com/juspay/hyperswitch/commit/8ceaaa9e3d95558a7252a9a986b39c8377426857))
- Added kafka events for authentication create and update ([#4991](https://github.com/juspay/hyperswitch/pull/4991)) ([`10e9121`](https://github.com/juspay/hyperswitch/commit/10e9121341fe25d195f4c9a25dcc383c2ffd0c95))

### Bug Fixes

- **access_token:** Use `merchant_connector_id` in access token ([#5106](https://github.com/juspay/hyperswitch/pull/5106)) ([`b7bf457`](https://github.com/juspay/hyperswitch/commit/b7bf457d0cdcc4d4947b5750a7982aca85d3a7e9))

### Refactors

- **core:** Introduce an interface to switch between old and new connector integration implementations on the connectors ([#5013](https://github.com/juspay/hyperswitch/pull/5013)) ([`e658899`](https://github.com/juspay/hyperswitch/commit/e658899c1406225bb905ce4fb76e13fa3609666e))
- **events:** Populate object identifiers in outgoing webhooks analytics events during retries ([#5067](https://github.com/juspay/hyperswitch/pull/5067)) ([`b878405`](https://github.com/juspay/hyperswitch/commit/b87840595d4bc325d37779512dc5504a8a613e5d))
- [Fiserv] Remove Default Case Handling ([#4767](https://github.com/juspay/hyperswitch/pull/4767)) ([`9caabef`](https://github.com/juspay/hyperswitch/commit/9caabeff86dfb93b29d6f734e6724f4d69bdda4e))

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

- - -

## 2024.06.24.0

### Features

- **payment_methods:** Implement Process tracker workflow for Payment method Status update ([#4668](https://github.com/juspay/hyperswitch/pull/4668)) ([`5cde7ee`](https://github.com/juspay/hyperswitch/commit/5cde7ee0344d4068a232c96f60b53629b8c17f7f))
- **users:** Setup user authentication methods schema and apis ([#4999](https://github.com/juspay/hyperswitch/pull/4999)) ([`2005d3d`](https://github.com/juspay/hyperswitch/commit/2005d3df9fc2e559ea65c57892ab940e38b9af50))

### Bug Fixes

- **router:** Avoid considering pre-routing results during `perform_session_token_routing` ([#5076](https://github.com/juspay/hyperswitch/pull/5076)) ([`a71fe03`](https://github.com/juspay/hyperswitch/commit/a71fe033e7de75171d140506ff4d51a362c185f4))

### Refactors

- **redis:** Spawn one subscriber thread for handling all the published messages to different channel ([#5064](https://github.com/juspay/hyperswitch/pull/5064)) ([`6a07e10`](https://github.com/juspay/hyperswitch/commit/6a07e10af379006c4643bb8f0a9cb2f46813ff8a))

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

- - -

## 2024.06.20.1

### Features

- **cypress:** Add 2 more payout connectors and bank transfer support for payout ([#4993](https://github.com/juspay/hyperswitch/pull/4993)) ([`45a908b`](https://github.com/juspay/hyperswitch/commit/45a908b4407db160b5f92b0bf84a9612cfaf44ef))

### Bug Fixes

- **cypress:** Address cypress skipping tests ([#5046](https://github.com/juspay/hyperswitch/pull/5046)) ([`973ecbf`](https://github.com/juspay/hyperswitch/commit/973ecbf84ec62d05556ccd568992243e460f8b10))
- **payment_methods:** Support last used for off session token payments ([#5039](https://github.com/juspay/hyperswitch/pull/5039)) ([`d98293a`](https://github.com/juspay/hyperswitch/commit/d98293ae9a01ccdcd62466d9c64c6b6f492f227b))

### Refactors

- **connector:** [Mifinity]dynamic fields for mifinity ([#5056](https://github.com/juspay/hyperswitch/pull/5056)) ([`6f58b4e`](https://github.com/juspay/hyperswitch/commit/6f58b4efbd111b2d0b8ef33cbcd377c434f181e2))
- **payment_method:** [Klarna] store and populate payment_type for klarna_sdk Paylater in response ([#4956](https://github.com/juspay/hyperswitch/pull/4956)) ([`c9bfb89`](https://github.com/juspay/hyperswitch/commit/c9bfb89f7eb03d73d5af3fe2bcd7632347ec17b4))
- Introduce ConnectorIntegrationNew and add default implementation for each Connector ([#4989](https://github.com/juspay/hyperswitch/pull/4989)) ([`84bed81`](https://github.com/juspay/hyperswitch/commit/84bed81defce0671274241318204029a2bb30a12))

### Miscellaneous Tasks

- **postman:** Update Postman collection files ([`d546415`](https://github.com/juspay/hyperswitch/commit/d546415c26c2727c22ad0e46dba1c0235501cd2e))

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

- - -

## 2024.06.20.0

### Features

- **core:** Add logger for sessions call failure ([#5036](https://github.com/juspay/hyperswitch/pull/5036)) ([`397d221`](https://github.com/juspay/hyperswitch/commit/397d2212405d63dab17272f8c26e4b3a5fc47aa8))
- **router:** Add payment method type duplication check for `google_pay` ([#5023](https://github.com/juspay/hyperswitch/pull/5023)) ([`7d46afd`](https://github.com/juspay/hyperswitch/commit/7d46afd9852a793befa5321835ae9413fafb3fd9))

### Bug Fixes

- **connector:** Add local bank redirect type in compatibility layer, default the country to AT for Local Bank Redirect and add creds_identifier in access token ([#5038](https://github.com/juspay/hyperswitch/pull/5038)) ([`655b81d`](https://github.com/juspay/hyperswitch/commit/655b81d69743e64fb982a1e222d7a102a4b3459f))
- **events:** Correct parsing of API events with user event_type for Clickhouse ([#5022](https://github.com/juspay/hyperswitch/pull/5022)) ([`2106a27`](https://github.com/juspay/hyperswitch/commit/2106a27f4059f7d562ae4c6d0d69cc3acbb43eca))
- **logging:** Fix stack overflow on recording restricted keys ([#4423](https://github.com/juspay/hyperswitch/pull/4423)) ([`7208ca4`](https://github.com/juspay/hyperswitch/commit/7208ca4db4876015c5beadeacdcbaeeaba3b56e9))

### Refactors

- **connector:** Add amount conversion framework for noon ([#4843](https://github.com/juspay/hyperswitch/pull/4843)) ([`8c7e1a3`](https://github.com/juspay/hyperswitch/commit/8c7e1a3b8bbb7ad7fef460659e9daaa13d71521b))
- **core:** Reverts the payment method list filtering using constraint graph ([#5044](https://github.com/juspay/hyperswitch/pull/5044)) ([`e486641`](https://github.com/juspay/hyperswitch/commit/e486641c97e0a00835ed49257c2665293591901c))
- **storage:** Remove `id` from payment intent, attempt and remove datamodel ext from payment intent ([#4923](https://github.com/juspay/hyperswitch/pull/4923)) ([`bec51a3`](https://github.com/juspay/hyperswitch/commit/bec51a35574fcee2473465dc30c8f0f85de18145))

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

- - -

## 2024.06.19.0

### Features

- **multitenancy:** Add tenant_id as a field for data pipeline and support individual database for clickhouse ([#4867](https://github.com/juspay/hyperswitch/pull/4867)) ([`776ddb8`](https://github.com/juspay/hyperswitch/commit/776ddb8c1afdd2f9f14980629a0a1d251df41fbc))
- **router:** Override the `setup_future_usage` to `on_session` based on the merchant config ([#5016](https://github.com/juspay/hyperswitch/pull/5016)) ([`a7ad790`](https://github.com/juspay/hyperswitch/commit/a7ad7906d7e84fa59df3cfffd16dea8db300e675))

### Bug Fixes

- **opensearch:** Handle index not present errors in search api ([#4965](https://github.com/juspay/hyperswitch/pull/4965)) ([`ae1edb0`](https://github.com/juspay/hyperswitch/commit/ae1edb061d38effeb12fd122b94e45fb768dd508))
- **payment_methods:** Populate card fields while saving card again during metadata change condition ([#5019](https://github.com/juspay/hyperswitch/pull/5019)) ([`010e6fe`](https://github.com/juspay/hyperswitch/commit/010e6fe3eef9398224b6e96b2469ac350d5e13c0))

### Refactors

- Move trait ConnectorIntegration to crate hyperswitch_interfaces ([#4946](https://github.com/juspay/hyperswitch/pull/4946)) ([`cbe3a6d`](https://github.com/juspay/hyperswitch/commit/cbe3a6d43e50ed5f13ecc5738c6a9ab2827b0a3c))
- Add basic counter metrics for IMC ([#5006](https://github.com/juspay/hyperswitch/pull/5006)) ([`d2092dc`](https://github.com/juspay/hyperswitch/commit/d2092dcb0a5ccddf8248ffb33fae91280268610e))

### Miscellaneous Tasks

- **docker-compose:** Pass correct configuration values for running SDK demo app ([#5012](https://github.com/juspay/hyperswitch/pull/5012)) ([`91c8af6`](https://github.com/juspay/hyperswitch/commit/91c8af6ef6d74cc3e0cb55c5f26ca1eae6907709))

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

- - -

## 2024.06.17.0

### Features

- **connector:** Added template code for datatrans ([#4890](https://github.com/juspay/hyperswitch/pull/4890)) ([`6582729`](https://github.com/juspay/hyperswitch/commit/658272904897f7cbc4d9a349278712f35a8d3e96))

### Bug Fixes

- **users:** Magic link is not expiring after one usage ([#4971](https://github.com/juspay/hyperswitch/pull/4971)) ([`2852a3b`](https://github.com/juspay/hyperswitch/commit/2852a3ba156e3e2bd89d0a116990134268e7bee8))

### Miscellaneous Tasks

- **process_tracker:** Use `const` instead of `String` for `business_status` ([#4849](https://github.com/juspay/hyperswitch/pull/4849)) ([`40dfad8`](https://github.com/juspay/hyperswitch/commit/40dfad89ac6e70a15321b3711ee4c05c3c2ff201))
- Introduce RouterDataNew and FlowSpecificData models ([#4961](https://github.com/juspay/hyperswitch/pull/4961)) ([`656fb3e`](https://github.com/juspay/hyperswitch/commit/656fb3e09a159d1cf67b2f494673bc8ded5a7ae8))
- Address Rust 1.79 clippy lints ([#5003](https://github.com/juspay/hyperswitch/pull/5003)) ([`edf919e`](https://github.com/juspay/hyperswitch/commit/edf919e142736a28588b0f7e40ce724ad0065777))

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

- - -

## 2024.06.14.0

### Features

- **connectors:** [Iatapay] add payment methods ([#4968](https://github.com/juspay/hyperswitch/pull/4968)) ([`0e059e7`](https://github.com/juspay/hyperswitch/commit/0e059e7d847b0c15ed120c72bb4902ac60e6f955))
- **payment_methods:** Use Ephemeral auth for pm list and pm delete ([#4996](https://github.com/juspay/hyperswitch/pull/4996)) ([`ad7886a`](https://github.com/juspay/hyperswitch/commit/ad7886a6ff636f99e62601483c907f5c90954eb4))
- **router:** Include the pre-routing connectors in Apple Pay retries ([#4952](https://github.com/juspay/hyperswitch/pull/4952)) ([`fb83661`](https://github.com/juspay/hyperswitch/commit/fb836618a66f57fca5c78aa1c2a255792ab1dfb4))

### Bug Fixes

- **cypress:** Add `jwt_token` and `cookie` for routing test ([#4953](https://github.com/juspay/hyperswitch/pull/4953)) ([`0a86cdb`](https://github.com/juspay/hyperswitch/commit/0a86cdb5060679e9609c2db6d2f82b8edda1b374))

### Refactors

- **core:** Make country aggregator nodes weak for list payment methods ([#4994](https://github.com/juspay/hyperswitch/pull/4994)) ([`18493bd`](https://github.com/juspay/hyperswitch/commit/18493bd8f03b933b15bc3c40b3501222587fc59f))

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

- - -

## 2024.06.13.0

### Features

- **connector:** [BOA/CYB] Make billTo fields optional ([#4951](https://github.com/juspay/hyperswitch/pull/4951)) ([`4651584`](https://github.com/juspay/hyperswitch/commit/4651584ecc25e40a285b3544315901145d8c6b4b))
- **events:** Add audit events payment capture ([#4913](https://github.com/juspay/hyperswitch/pull/4913)) ([`40a996e`](https://github.com/juspay/hyperswitch/commit/40a996e84c1d9ccc55b62c561cee443508e9e60f))
- **payouts:** Make payout_type optional in payouts table ([#4954](https://github.com/juspay/hyperswitch/pull/4954)) ([`b847606`](https://github.com/juspay/hyperswitch/commit/b847606d665388fba898425b31dd5f207f60a56e))

### Bug Fixes

- **core:** Fix the multitenancy prefix in routing cache ([#4963](https://github.com/juspay/hyperswitch/pull/4963)) ([`b420522`](https://github.com/juspay/hyperswitch/commit/b42052269455051fe15163217ee83d80a1470f84))

### Refactors

- **connector:**
  - Add amount conversion framework to bluesnap ([#4825](https://github.com/juspay/hyperswitch/pull/4825)) ([`fb0a7aa`](https://github.com/juspay/hyperswitch/commit/fb0a7aa556212af08f47ddc3c62bfbc918e3bf01))
  - [Mifinity]Move destination_account_number from pmd to Mifinity Metadata ([#4962](https://github.com/juspay/hyperswitch/pull/4962)) ([`5b21951`](https://github.com/juspay/hyperswitch/commit/5b21951102c54cee4b6d1d74ed6a7e7e9f3e192d))
- **payment_methods:** Enable deletion of default Payment Methods ([#4942](https://github.com/juspay/hyperswitch/pull/4942)) ([`cf3d039`](https://github.com/juspay/hyperswitch/commit/cf3d039efdbaa95ae9e75de60b3cea67e21d11db))

### Miscellaneous Tasks

- **env:** Revert typo in integ env ([#4958](https://github.com/juspay/hyperswitch/pull/4958)) ([`271b977`](https://github.com/juspay/hyperswitch/commit/271b977aa286e80cb09c6692c4cd470e3c6c741c))

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


File: crates/analytics/src/routing_events/core.rs
 Public functions: 1

use api_models::analytics::routing_events::RoutingEventsRequest;
use common_utils::errors::ReportSwitchExt;
use error_stack::ResultExt;

use super::events::{get_routing_events, RoutingEventsResult};
use crate::{errors::AnalyticsResult, types::FiltersError, AnalyticsProvider};

pub async fn routing_events_core(
    pool: &AnalyticsProvider,
    req: RoutingEventsRequest,
    merchant_id: &common_utils::id_type::MerchantId,
) -> AnalyticsResult<Vec<RoutingEventsResult>> {
    let data = match pool {
        AnalyticsProvider::Sqlx(_) => Err(FiltersError::NotImplemented(
            "Connector Events not implemented for SQLX",
        ))
        .attach_printable("SQL Analytics is not implemented for Connector Events"),
        AnalyticsProvider::Clickhouse(ckh_pool)
        | AnalyticsProvider::CombinedSqlx(_, ckh_pool)
        | AnalyticsProvider::CombinedCkh(_, ckh_pool) => {
            get_routing_events(merchant_id, req, ckh_pool).await
        }
    }
    .switch()?;
    Ok(data)
}


pub fn try_get_enum_variant(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
    let input = syn::parse_macro_input!(input as syn::DeriveInput);

    macros::try_get_enum::try_get_enum_variant(input)
        .unwrap_or_else(|error| error.into_compile_error())
        .into()
}


File: crates/api_models/src/lib.rs

pub mod admin;
pub mod analytics;
pub mod api_keys;
pub mod apple_pay_certificates_migration;
pub mod authentication;
pub mod blocklist;
pub mod cards_info;
pub mod chat;
pub mod conditional_configs;
pub mod connector_enums;
pub mod connector_onboarding;
pub mod consts;
pub mod currency;
pub mod customers;
pub mod disputes;
pub mod enums;
pub mod ephemeral_key;
#[cfg(feature = "errors")]
pub mod errors;
pub mod events;
pub mod external_service_auth;
pub mod feature_matrix;
pub mod files;
pub mod gsm;
pub mod health_check;
pub mod locker_migration;
pub mod mandates;
pub mod open_router;
pub mod organization;
pub mod payment_methods;
pub mod payments;
#[cfg(feature = "payouts")]
pub mod payouts;
pub mod pm_auth;
pub mod poll;
pub mod process_tracker;
pub mod profile_acquirer;
#[cfg(feature = "v2")]
pub mod proxy;
#[cfg(feature = "recon")]
pub mod recon;
pub mod refunds;
pub mod relay;
pub mod routing;
pub mod surcharge_decision_configs;
pub mod three_ds_decision_rule;
#[cfg(feature = "tokenization_v2")]
pub mod tokenization;
pub mod user;
pub mod user_role;
pub mod verifications;
pub mod verify_connector;
pub mod webhook_events;
pub mod webhooks;

pub trait ValidateFieldAndGet<Request> {
    fn validate_field_and_get(
        &self,
        request: &Request,
    ) -> common_utils::errors::CustomResult<Self, common_utils::errors::ValidationError>
    where
        Self: Sized;
}


pub struct OpayoAuthType {
    pub(super) api_key: Secret<String>,
}


pub async fn get_blocked_count_from_cache<A>(
    state: &A,
    cache_key: &str,
) -> RouterResult<Option<i32>>
where
    A: SessionStateInfo + Sync,
{
    let redis_conn = get_redis_connection(state)?;

    let value: Option<i32> = redis_conn
        .get_key(&cache_key.into())
        .await
        .change_context(ApiErrorResponse::InternalServerError)?;

    Ok(value)
}


pub async fn profile_delete(
    state: web::Data<AppState>,
    req: HttpRequest,
    path: web::Path<(
        common_utils::id_type::MerchantId,
        common_utils::id_type::ProfileId,
    )


impl api::PaymentSync for Worldpayvantiv {}

impl api::PaymentSync for for Worldpayvantiv


impl Role {
    fn get_entity_list(
        current_entity: EntityType,
        is_lineage_data_required: bool,
    ) -> Vec<EntityType> {
        is_lineage_data_required
            .then(|| {
                EntityType::iter()
                    .filter(|variant| *variant <= current_entity)
                    .collect()
            })
            .unwrap_or(vec![current_entity])
    }

    pub async fn find_by_role_id(conn: &PgPooledConn, role_id: &str) -> StorageResult<Self> {
        generics::generic_find_one::<<Self as HasTable>::Table, _, _>(
            conn,
            dsl::role_id.eq(role_id.to_owned()),
        )
        .await
    }

    pub async fn find_by_role_id_in_lineage(
        conn: &PgPooledConn,
        role_id: &str,
        merchant_id: &id_type::MerchantId,
        org_id: &id_type::OrganizationId,
        profile_id: &id_type::ProfileId,
        tenant_id: &id_type::TenantId,
    ) -> StorageResult<Self> {
        generics::generic_find_one::<<Self as HasTable>::Table, _, _>(
            conn,
            dsl::role_id
                .eq(role_id.to_owned())
                .and(dsl::tenant_id.eq(tenant_id.to_owned()))
                .and(dsl::org_id.eq(org_id.to_owned()))
                .and(
                    dsl::scope
                        .eq(RoleScope::Organization)
                        .or(dsl::merchant_id
                            .eq(merchant_id.to_owned())
                            .and(dsl::scope.eq(RoleScope::Merchant)))
                        .or(dsl::profile_id
                            .eq(profile_id.to_owned())
                            .and(dsl::scope.eq(RoleScope::Profile))),
                ),
        )
        .await
    }

    pub async fn find_by_role_id_org_id_tenant_id(
        conn: &PgPooledConn,
        role_id: &str,
        org_id: &id_type::OrganizationId,
        tenant_id: &id_type::TenantId,
    ) -> StorageResult<Self> {
        generics::generic_find_one::<<Self as HasTable>::Table, _, _>(
            conn,
            dsl::role_id
                .eq(role_id.to_owned())
                .and(dsl::tenant_id.eq(tenant_id.to_owned()))
                .and(dsl::org_id.eq(org_id.to_owned())),
        )
        .await
    }

    pub async fn update_by_role_id(
        conn: &PgPooledConn,
        role_id: &str,
        role_update: RoleUpdate,
    ) -> StorageResult<Self> {
        generics::generic_update_with_unique_predicate_get_result::<
            <Self as HasTable>::Table,
            _,
            _,
            _,
        >(
            conn,
            dsl::role_id.eq(role_id.to_owned()),
            RoleUpdateInternal::from(role_update),
        )
        .await
    }

    pub async fn delete_by_role_id(conn: &PgPooledConn, role_id: &str) -> StorageResult<Self> {
        generics::generic_delete_one_with_result::<<Self as HasTable>::Table, _, _>(
            conn,
            dsl::role_id.eq(role_id.to_owned()),
        )
        .await
    }

    //TODO: Remove once generic_list_roles_by_entity_type is stable
    pub async fn generic_roles_list_for_org(
        conn: &PgPooledConn,
        tenant_id: id_type::TenantId,
        org_id: id_type::OrganizationId,
        merchant_id: Option<id_type::MerchantId>,
        entity_type: Option<EntityType>,
        limit: Option<u32>,
    ) -> StorageResult<Vec<Self>> {
        let mut query = <Self as HasTable>::table()
            .filter(dsl::tenant_id.eq(tenant_id).and(dsl::org_id.eq(org_id)))
            .into_boxed();

        if let Some(merchant_id) = merchant_id {
            query = query.filter(
                (dsl::merchant_id
                    .eq(merchant_id)
                    .and(dsl::scope.eq(RoleScope::Merchant)))
                .or(dsl::scope.eq(RoleScope::Organization)),
            );
        }

        if let Some(entity_type) = entity_type {
            query = query.filter(dsl::entity_type.eq(entity_type))
        }

        if let Some(limit) = limit {
            query = query.limit(limit.into());
        }

        router_env::logger::debug!(query = %debug_query::<Pg,_>(&query).to_string());

        match generics::db_metrics::track_database_call::<Self, _, _>(
            query.get_results_async(conn),
            generics::db_metrics::DatabaseOperation::Filter,
        )
        .await
        {
            Ok(value) => Ok(value),
            Err(err) => match err {
                DieselError::NotFound => {
                    Err(report!(err)).change_context(errors::DatabaseError::NotFound)
                }
                _ => Err(report!(err)).change_context(errors::DatabaseError::Others),
            },
        }
    }

    pub async fn generic_list_roles_by_entity_type(
        conn: &PgPooledConn,
        payload: ListRolesByEntityPayload,
        is_lineage_data_required: bool,
        tenant_id: id_type::TenantId,
        org_id: id_type::OrganizationId,
    ) -> StorageResult<Vec<Self>> {
        let mut query = <Self as HasTable>::table()
            .into_boxed()
            .filter(dsl::tenant_id.eq(tenant_id))
            .filter(dsl::org_id.eq(org_id));

        match payload {
            ListRolesByEntityPayload::Organization => {
                let entity_in_vec =
                    Self::get_entity_list(EntityType::Organization, is_lineage_data_required);
                query = query.filter(dsl::entity_type.eq_any(entity_in_vec))
            }

            ListRolesByEntityPayload::Merchant(merchant_id) => {
                let entity_in_vec =
                    Self::get_entity_list(EntityType::Merchant, is_lineage_data_required);
                query = query
                    .filter(
                        dsl::scope
                            .eq(RoleScope::Organization)
                            .or(dsl::merchant_id.eq(merchant_id)),
                    )
                    .filter(dsl::entity_type.eq_any(entity_in_vec))
            }

            ListRolesByEntityPayload::Profile(merchant_id, profile_id) => {
                let entity_in_vec =
                    Self::get_entity_list(EntityType::Profile, is_lineage_data_required);
                query = query
                    .filter(
                        dsl::scope
                            .eq(RoleScope::Organization)
                            .or(dsl::scope
                                .eq(RoleScope::Merchant)
                                .and(dsl::merchant_id.eq(merchant_id.clone())))
                            .or(dsl::profile_id.eq(profile_id)),
                    )
                    .filter(dsl::entity_type.eq_any(entity_in_vec))
            }
        };

        router_env::logger::debug!(query = %debug_query::<Pg,_>(&query).to_string());

        match generics::db_metrics::track_database_call::<Self, _, _>(
            query.get_results_async(conn),
            generics::db_metrics::DatabaseOperation::Filter,
        )
        .await
        {
            Ok(value) => Ok(value),
            Err(err) => Err(report!(err)).change_context(errors::DatabaseError::Others),
        }
    }
}


Web Documentation: Run Hyperswitch Locally Using Docker | Hyperswitch
# Type: Web Doc

This setup automatically runs all three components of Hyperswitch (Backend, Control Center, and SDK) on your machine at once using Docker.
Setup using Docker
You can run Hyperswitch on your system using
Docker compose
. We recommend using Docker Desktop for Windows and Mac OS. On Linux, you can install Docker Engine directly.
You can alternatively use
Podman
or
Orbstack
(for macOS) instead of docker.
Once Docker is installed, launch the Docker desktop app, then use the following command at the command line.
git clone --depth 1 --branch latest
cd hyperswitch
scripts/setup.sh
The above command will:
Check for prerequisites (Docker Compose/Podman)
Set up necessary configurations (PostgreSQL, Redis)
Let you select a setup option:
Standard
: (Recommended) App server + Control Center + Web SDK
Full
: Standard + Monitoring + Scheduler
Standalone App Server
: Core services only App Server
Start the selected services
Provide link to access various components
If you're
looking to Contribute to Hyperswitch
, try
setting up a
development environment
using Docker Compose
.
Have Questions?
Join our
Slack Community
Prefer direct support? Use our
Contact Us
page to reach out.
Account setup
6 months ago
Was this helpful?


pub async fn profiles_list_at_profile_level(
    state: web::Data<AppState>,
    req: HttpRequest,
    path: web::Path<common_utils::id_type::MerchantId>,
) -> HttpResponse {
    let flow = Flow::ProfileList;
    let merchant_id = path.into_inner();

    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        merchant_id.clone(),
        |state, auth, merchant_id, _| {
            list_profile(
                state,
                merchant_id,
                auth.profile_id.map(|profile_id| vec![profile_id]),
            )
        },
        auth::auth_type(
            &auth::HeaderAuth(auth::ApiKeyAuthWithMerchantIdFromRoute(merchant_id.clone())),
            &auth::JWTAuthMerchantFromRoute {
                merchant_id,
                required_permission: permissions::Permission::ProfileAccountRead,
            },
            req.headers(),
        ),
        api_locking::LockAction::NotApplicable,
    ))
    .await
}


File: crates/kgraph_utils/src/lib.rs

pub mod error;
pub mod mca;
pub mod transformers;
pub mod types;


pub struct NexixpayPreProcessingResponse {
    operation: Operation,
    three_d_s_auth_result: ThreeDSAuthResult,
}


File: crates/analytics/src/payments/metrics/connector_success_rate.rs

use std::collections::HashSet;

use api_models::analytics::{
    payments::{PaymentDimensions, PaymentFilters, PaymentMetricsBucketIdentifier},
    Granularity, TimeRange,
};
use common_utils::errors::ReportSwitchExt;
use error_stack::ResultExt;
use time::PrimitiveDateTime;

use super::PaymentMetricRow;
use crate::{
    enums::AuthInfo,
    query::{
        Aggregate, FilterTypes, GroupByClause, QueryBuilder, QueryFilter, SeriesBucket, ToSql,
        Window,
    },
    types::{AnalyticsCollection, AnalyticsDataSource, MetricsError, MetricsResult},
};

#[derive(Default)]
pub(super) struct ConnectorSuccessRate;

#[async_trait::async_trait]
impl<T> super::PaymentMetric<T> for ConnectorSuccessRate
where
    T: AnalyticsDataSource + super::PaymentMetricAnalytics,
    PrimitiveDateTime: ToSql<T>,
    AnalyticsCollection: ToSql<T>,
    Granularity: GroupByClause<T>,
    Aggregate<&'static str>: ToSql<T>,
    Window<&'static str>: ToSql<T>,
{
    async fn load_metrics(
        &self,
        dimensions: &[PaymentDimensions],
        auth: &AuthInfo,
        filters: &PaymentFilters,
        granularity: Option<Granularity>,
        time_range: &TimeRange,
        pool: &T,
    ) -> MetricsResult<HashSet<(PaymentMetricsBucketIdentifier, PaymentMetricRow)>> {
        let mut query_builder: QueryBuilder<T> = QueryBuilder::new(AnalyticsCollection::Payment);
        let mut dimensions = dimensions.to_vec();

        dimensions.push(PaymentDimensions::PaymentStatus);

        for dim in dimensions.iter() {
            query_builder.add_select_column(dim).switch()?;
        }

        query_builder
            .add_select_column(Aggregate::Count {
                field: None,
                alias: Some("count"),
            })
            .switch()?;
        query_builder
            .add_select_column(Aggregate::Min {
                field: "created_at",
                alias: Some("start_bucket"),
            })
            .switch()?;
        query_builder
            .add_select_column(Aggregate::Max {
                field: "created_at",
                alias: Some("end_bucket"),
            })
            .switch()?;

        filters.set_filter_clause(&mut query_builder).switch()?;

        auth.set_filter_clause(&mut query_builder).switch()?;

        query_builder
            .add_custom_filter_clause(PaymentDimensions::Connector, "NULL", FilterTypes::IsNotNull)
            .switch()?;
        time_range
            .set_filter_clause(&mut query_builder)
            .attach_printable("Error filtering time range")
            .switch()?;

        for dim in dimensions.iter() {
            query_builder
                .add_group_by_clause(dim)
                .attach_printable("Error grouping by dimensions")
                .switch()?;
        }

        if let Some(granularity) = granularity {
            granularity
                .set_group_by_clause(&mut query_builder)
                .attach_printable("Error adding granularity")
                .switch()?;
        }

        query_builder
            .execute_query::<PaymentMetricRow, _>(pool)
            .await
            .change_context(MetricsError::QueryBuildingError)?
            .change_context(MetricsError::QueryExecutionFailure)?
            .into_iter()
            .map(|i| {
                Ok((
                    PaymentMetricsBucketIdentifier::new(
                        i.currency.as_ref().map(|i| i.0),
                        None,
                        i.connector.clone(),
                        i.authentication_type.as_ref().map(|i| i.0),
                        i.payment_method.clone(),
                        i.payment_method_type.clone(),
                        i.client_source.clone(),
                        i.client_version.clone(),
                        i.profile_id.clone(),
                        i.card_network.clone(),
                        i.merchant_id.clone(),
                        i.card_last_4.clone(),
                        i.card_issuer.clone(),
                        i.error_reason.clone(),
                        i.routing_approach.as_ref().map(|i| i.0.clone()),
                        i.signature_network.clone(),
                        i.is_issuer_regulated,
                        i.is_debit_routed,
                        TimeRange {
                            start_time: match (granularity, i.start_bucket) {
                                (Some(g), Some(st)) => g.clip_to_start(st)?,
                                _ => time_range.start_time,
                            },
                            end_time: granularity.as_ref().map_or_else(
                                || Ok(time_range.end_time),
                                |g| i.end_bucket.map(|et| g.clip_to_end(et)).transpose(),
                            )?,
                        },
                    ),
                    i,
                ))
            })
            .collect::<error_stack::Result<
                HashSet<(PaymentMetricsBucketIdentifier, PaymentMetricRow)>,
                crate::query::PostProcessingError,
            >>()
            .change_context(MetricsError::PostProcessingFailure)
    }
}


File: crates/diesel_models/src/query/authorization.rs
 Public functions: 3

use diesel::{associations::HasTable, BoolExpressionMethods, ExpressionMethods};

use super::generics;
use crate::{
    authorization::{
        Authorization, AuthorizationNew, AuthorizationUpdate, AuthorizationUpdateInternal,
    },
    errors,
    schema::incremental_authorization::dsl,
    PgPooledConn, StorageResult,
};

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

impl Authorization {
    pub async fn update_by_merchant_id_authorization_id(
        conn: &PgPooledConn,
        merchant_id: common_utils::id_type::MerchantId,
        authorization_id: String,
        authorization_update: AuthorizationUpdate,
    ) -> StorageResult<Self> {
        match generics::generic_update_with_unique_predicate_get_result::<
            <Self as HasTable>::Table,
            _,
            _,
            _,
        >(
            conn,
            dsl::merchant_id
                .eq(merchant_id.to_owned())
                .and(dsl::authorization_id.eq(authorization_id.to_owned())),
            AuthorizationUpdateInternal::from(authorization_update),
        )
        .await
        {
            Err(error) => match error.current_context() {
                errors::DatabaseError::NotFound => Err(error.attach_printable(
                    "Authorization with the given Authorization ID does not exist",
                )),
                errors::DatabaseError::NoFieldsToUpdate => {
                    generics::generic_find_one::<<Self as HasTable>::Table, _, _>(
                        conn,
                        dsl::merchant_id
                            .eq(merchant_id.to_owned())
                            .and(dsl::authorization_id.eq(authorization_id.to_owned())),
                    )
                    .await
                }
                _ => Err(error),
            },
            result => result,
        }
    }

    pub async fn find_by_merchant_id_payment_id(
        conn: &PgPooledConn,
        merchant_id: &common_utils::id_type::MerchantId,
        payment_id: &common_utils::id_type::PaymentId,
    ) -> StorageResult<Vec<Self>> {
        generics::generic_filter::<<Self as HasTable>::Table, _, _, _>(
            conn,
            dsl::merchant_id
                .eq(merchant_id.to_owned())
                .and(dsl::payment_id.eq(payment_id.to_owned())),
            None,
            None,
            Some(dsl::created_at.asc()),
        )
        .await
    }
}


impl api::PaymentCapture for Sift {}


impl ClientSecretFetch for PaymentMethodCreate {
    fn get_client_secret(&self) -> Option<&String> {
        self.client_secret.as_ref()
    }
}

impl ClientSecretFetch for for PaymentMethodCreate


impl api::PaymentCapture for Shift4 {}


pub async fn link_token_create(
    state: web::Data<AppState>,
    req: HttpRequest,
    json_payload: web::Json<api_types::pm_auth::LinkTokenCreateRequest>,
) -> impl Responder {
    let payload = json_payload.into_inner();
    let flow = Flow::PmAuthLinkTokenCreate;
    let api_auth = auth::ApiKeyAuth::default();

    let (auth, _) = match crate::services::authentication::check_client_secret_and_get_auth(
        req.headers(),
        &payload,
        api_auth,
    ) {
        Ok((auth, _auth_flow)) => (auth, _auth_flow),
        Err(e) => return api::log_and_return_error_response(e),
    };

    let header_payload =
        match hyperswitch_domain_models::payments::HeaderPayload::foreign_try_from(req.headers()) {
            Ok(headers) => headers,
            Err(err) => {
                return api::log_and_return_error_response(err);
            }
        };

    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        payload,
        |state, auth, payload, _| {
            let merchant_context = crate::types::domain::MerchantContext::NormalMerchant(Box::new(
                crate::types::domain::Context(auth.merchant_account, auth.key_store),
            ));
            crate::core::pm_auth::create_link_token(
                state,
                merchant_context,
                payload,
                Some(header_payload.clone()),
            )
        },
        &*auth,
        api_locking::LockAction::NotApplicable,
    ))
    .await
}


pub async fn list_blocklist_entries_for_merchant(
    state: &SessionState,
    merchant_id: &common_utils::id_type::MerchantId,
    query: api_blocklist::ListBlocklistQuery,
) -> RouterResult<Vec<api_blocklist::BlocklistResponse>> {
    state
        .store
        .list_blocklist_entries_by_merchant_id_data_kind(
            merchant_id,
            query.data_kind,
            query.limit.into(),
            query.offset.into(),
        )
        .await
        .to_not_found_response(errors::ApiErrorResponse::GenericNotFoundError {
            message: "no blocklist records found".to_string(),
        })
        .map(|v| v.into_iter().map(ForeignInto::foreign_into).collect())
}


pub fn apply_changeset(self, update_session: PaymentMethodsSessionUpdateInternal) -> Self {
        let Self {
            id,
            customer_id,
            billing,
            psp_tokenization,
            network_tokenization,
            tokenization_data,
            expires_at,
            return_url,
            associated_payment_methods,
            associated_payment,
            associated_token_id,
        } = self;

        Self {
            id,
            customer_id,
            billing: update_session.billing.or(billing),
            psp_tokenization: update_session.psp_tokenization.or(psp_tokenization),
            network_tokenization: update_session.network_tokenization.or(network_tokenization),
            tokenization_data: update_session.tokenzation_data.or(tokenization_data),
            expires_at,
            return_url,
            associated_payment_methods,
            associated_payment,
            associated_token_id,
        }
    }


File: crates/hyperswitch_connectors/src/connectors/coinbase/transformers.rs
 Public structs: 24

use std::collections::HashMap;

use common_enums::enums;
use common_utils::{pii, request::Method, types::StringMajorUnit};
use error_stack::ResultExt;
use hyperswitch_domain_models::{
    router_data::{ConnectorAuthType, RouterData},
    router_flow_types::refunds::{Execute, RSync},
    router_request_types::ResponseId,
    router_response_types::{PaymentsResponseData, RedirectForm},
    types::{self, PaymentsAuthorizeRouterData},
};
use hyperswitch_interfaces::errors;
use masking::Secret;
use serde::{Deserialize, Serialize};

use crate::{
    types::{RefundsResponseRouterData, ResponseRouterData},
    utils::{
        self, AddressDetailsData, PaymentsAuthorizeRequestData, RouterData as OtherRouterData,
    },
};

#[derive(Debug, Serialize)]
pub struct CoinbaseRouterData<T> {
    amount: StringMajorUnit,
    router_data: T,
}

impl<T> From<(StringMajorUnit, T)> for CoinbaseRouterData<T> {
    fn from((amount, item): (StringMajorUnit, T)) -> Self {
        Self {
            amount,
            router_data: item,
        }
    }
}

#[derive(Debug, Default, Eq, PartialEq, Serialize)]
pub struct LocalPrice {
    pub amount: StringMajorUnit,
    pub currency: String,
}

#[derive(Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
pub struct Metadata {
    pub customer_id: Option<String>,
    pub customer_name: Option<Secret<String>>,
}

#[derive(Default, Debug, Serialize, Eq, PartialEq)]
pub struct CoinbasePaymentsRequest {
    pub name: Option<Secret<String>>,
    pub description: Option<String>,
    pub pricing_type: String,
    pub local_price: LocalPrice,
    pub redirect_url: String,
    pub cancel_url: String,
}

impl TryFrom<&CoinbaseRouterData<&PaymentsAuthorizeRouterData>> for CoinbasePaymentsRequest {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: &CoinbaseRouterData<&PaymentsAuthorizeRouterData>,
    ) -> Result<Self, Self::Error> {
        get_crypto_specific_payment_data(item)
    }
}

// Auth Struct
pub struct CoinbaseAuthType {
    pub(super) api_key: Secret<String>,
}

impl TryFrom<&ConnectorAuthType> for CoinbaseAuthType {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(_auth_type: &ConnectorAuthType) -> Result<Self, Self::Error> {
        if let ConnectorAuthType::HeaderKey { api_key } = _auth_type {
            Ok(Self {
                api_key: api_key.to_owned(),
            })
        } else {
            Err(errors::ConnectorError::FailedToObtainAuthType.into())
        }
    }
}
// PaymentsResponse
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "UPPERCASE")]
pub enum CoinbasePaymentStatus {
    New,
    #[default]
    Pending,
    Completed,
    Expired,
    Unresolved,
    Resolved,
    Canceled,
    #[serde(rename = "PENDING REFUND")]
    PendingRefund,
    Refunded,
}

impl From<CoinbasePaymentStatus> for enums::AttemptStatus {
    fn from(item: CoinbasePaymentStatus) -> Self {
        match item {
            CoinbasePaymentStatus::Completed | CoinbasePaymentStatus::Resolved => Self::Charged,
            CoinbasePaymentStatus::Expired => Self::Failure,
            CoinbasePaymentStatus::New => Self::AuthenticationPending,
            CoinbasePaymentStatus::Unresolved => Self::Unresolved,
            CoinbasePaymentStatus::Canceled => Self::Voided,
            _ => Self::Pending,
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, strum::Display)]
#[serde(rename_all = "UPPERCASE")]
#[strum(serialize_all = "UPPERCASE")]
pub enum UnResolvedContext {
    Underpaid,
    Overpaid,
    Delayed,
}

#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Timeline {
    status: CoinbasePaymentStatus,
    context: Option<UnResolvedContext>,
    time: String,
    pub payment: Option<TimelinePayment>,
}

#[derive(Default, Debug, Serialize, Deserialize)]
pub struct CoinbasePaymentsResponse {
    // status: CoinbasePaymentStatus,
    // id: String,
    data: CoinbasePaymentResponseData,
}

impl<F, T> TryFrom<ResponseRouterData<F, CoinbasePaymentsResponse, T, PaymentsResponseData>>
    for RouterData<F, T, PaymentsResponseData>
{
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: ResponseRouterData<F, CoinbasePaymentsResponse, T, PaymentsResponseData>,
    ) -> Result<Self, Self::Error> {
        let form_fields = HashMap::new();
        let redirection_data = RedirectForm::Form {
            endpoint: item.response.data.hosted_url.to_string(),
            method: Method::Get,
            form_fields,
        };
        let timeline = item
            .response
            .data
            .timeline
            .last()
            .ok_or(errors::ConnectorError::ResponseHandlingFailed)?
            .clone();
        let connector_id = ResponseId::ConnectorTransactionId(item.response.data.id.clone());
        let attempt_status = timeline.status.clone();
        let response_data = timeline.context.map_or(
            Ok(PaymentsResponseData::TransactionResponse {
                resource_id: connector_id.clone(),
                redirection_data: Box::new(Some(redirection_data)),
                mandate_reference: Box::new(None),
                connector_metadata: None,
                network_txn_id: None,
                connector_response_reference_id: Some(item.response.data.id.clone()),
                incremental_authorization_allowed: None,
                charges: None,
            }),
            |context| {
                Ok(PaymentsResponseData::TransactionUnresolvedResponse{
                resource_id: connector_id,
                reason: Some(api_models::enums::UnresolvedResponseReason {
                code: context.to_string(),
                message: "Please check the transaction in coinbase dashboard and resolve manually"
                    .to_string(),
                }),
                connector_response_reference_id: Some(item.response.data.id),
            })
            },
        );
        Ok(Self {
            status: enums::AttemptStatus::from(attempt_status),
            response: response_data,
            ..item.data
        })
    }
}

// REFUND :
// Type definition for RefundRequest
#[derive(Default, Debug, Serialize)]
pub struct CoinbaseRefundRequest {}

impl<F> TryFrom<&types::RefundsRouterData<F>> for CoinbaseRefundRequest {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(_item: &types::RefundsRouterData<F>) -> Result<Self, Self::Error> {
        Err(errors::ConnectorError::NotImplemented("try_from RefundsRouterData".to_string()).into())
    }
}

// Type definition for Refund Response

#[allow(dead_code)]
#[derive(Debug, Serialize, Default, Deserialize, Clone)]
pub enum RefundStatus {
    Succeeded,
    Failed,
    #[default]
    Processing,
}

impl From<RefundStatus> for enums::RefundStatus {
    fn from(item: RefundStatus) -> Self {
        match item {
            RefundStatus::Succeeded => Self::Success,
            RefundStatus::Failed => Self::Failure,
            RefundStatus::Processing => Self::Pending,
        }
    }
}

#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct RefundResponse {}

impl TryFrom<RefundsResponseRouterData<Execute, RefundResponse>>
    for types::RefundsRouterData<Execute>
{
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        _item: RefundsResponseRouterData<Execute, RefundResponse>,
    ) -> Result<Self, Self::Error> {
        Err(errors::ConnectorError::NotImplemented(
            "try_from RefundsResponseRouterData".to_string(),
        )
        .into())
    }
}

impl TryFrom<RefundsResponseRouterData<RSync, RefundResponse>> for types::RefundsRouterData<RSync> {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        _item: RefundsResponseRouterData<RSync, RefundResponse>,
    ) -> Result<Self, Self::Error> {
        Err(errors::ConnectorError::NotImplemented(
            "try_from RefundsResponseRouterData".to_string(),
        )
        .into())
    }
}

#[derive(Debug, Deserialize, Serialize)]
pub struct CoinbaseErrorData {
    #[serde(rename = "type")]
    pub error_type: String,
    pub message: String,
    pub code: Option<String>,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct CoinbaseErrorResponse {
    pub error: CoinbaseErrorData,
}

#[derive(Default, Debug, Deserialize, PartialEq)]
pub struct CoinbaseConnectorMeta {
    pub pricing_type: String,
}

impl TryFrom<&Option<pii::SecretSerdeValue>> for CoinbaseConnectorMeta {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(meta_data: &Option<pii::SecretSerdeValue>) -> Result<Self, Self::Error> {
        utils::to_connector_meta_from_secret(meta_data.clone())
            .change_context(errors::ConnectorError::InvalidConnectorConfig { config: "metadata" })
    }
}

fn get_crypto_specific_payment_data(
    item: &CoinbaseRouterData<&PaymentsAuthorizeRouterData>,
) -> Result<CoinbasePaymentsRequest, error_stack::Report<errors::ConnectorError>> {
    let billing_address = item
        .router_data
        .get_billing()
        .ok()
        .and_then(|billing_address| billing_address.address.as_ref());
    let name =
        billing_address.and_then(|add| add.get_first_name().ok().map(|name| name.to_owned()));
    let description = item.router_data.get_description().ok();
    let connector_meta = CoinbaseConnectorMeta::try_from(&item.router_data.connector_meta_data)
        .change_context(errors::ConnectorError::InvalidConnectorConfig {
            config: "Merchant connector account metadata",
        })?;
    let pricing_type = connector_meta.pricing_type;
    let local_price = get_local_price(item);
    let redirect_url = item.router_data.request.get_router_return_url()?;
    let cancel_url = item.router_data.request.get_router_return_url()?;

    Ok(CoinbasePaymentsRequest {
        name,
        description,
        pricing_type,
        local_price,
        redirect_url,
        cancel_url,
    })
}

fn get_local_price(item: &CoinbaseRouterData<&PaymentsAuthorizeRouterData>) -> LocalPrice {
    LocalPrice {
        amount: item.amount.clone(),
        currency: item.router_data.request.currency.to_string(),
    }
}

#[derive(Debug, Serialize, Deserialize)]
pub struct CoinbaseWebhookDetails {
    pub attempt_number: i64,
    pub event: Event,
    pub id: String,
    pub scheduled_for: String,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Event {
    pub api_version: String,
    pub created_at: String,
    pub data: CoinbasePaymentResponseData,
    pub id: String,
    pub resource: String,
    #[serde(rename = "type")]
    pub event_type: WebhookEventType,
}

#[derive(Debug, Serialize, Deserialize)]
pub enum WebhookEventType {
    #[serde(rename = "charge:confirmed")]
    Confirmed,
    #[serde(rename = "charge:created")]
    Created,
    #[serde(rename = "charge:pending")]
    Pending,
    #[serde(rename = "charge:failed")]
    Failed,
    #[serde(rename = "charge:resolved")]
    Resolved,
    #[serde(other)]
    Unknown,
}

#[derive(Debug, Default, Serialize, Deserialize)]
pub struct Redirects {
    cancel_url: Option<String>,
    success_url: Option<String>,
    will_redirect_after_success: bool,
}

#[derive(Debug, Default, Serialize, Deserialize)]
pub struct CoinbasePaymentResponseData {
    pub id: String,
    pub code: String,
    pub name: Option<Secret<String>>,
    pub utxo: Option<bool>,
    pub pricing: HashMap<String, OverpaymentAbsoluteThreshold>,
    pub fee_rate: Option<f64>,
    pub logo_url: Option<String>,
    pub metadata: Option<Metadata>,
    pub payments: Vec<PaymentElement>,
    pub resource: Option<String>,
    pub timeline: Vec<Timeline>,
    pub pwcb_only: bool,
    pub created_at: String,
    pub expires_at: String,
    pub hosted_url: String,
    pub brand_color: String,
    pub description: Option<String>,
    pub confirmed_at: Option<String>,
    pub fees_settled: Option<bool>,
    pub pricing_type: String,
    pub redirects: Redirects,
    pub support_email: pii::Email,
    pub brand_logo_url: String,
    pub offchain_eligible: Option<bool>,
    pub organization_name: String,
    pub payment_threshold: Option<PaymentThreshold>,
    pub coinbase_managed_merchant: Option<bool>,
}

#[derive(Debug, Serialize, Default, Deserialize)]
pub struct PaymentThreshold {
    pub overpayment_absolute_threshold: OverpaymentAbsoluteThreshold,
    pub overpayment_relative_threshold: String,
    pub underpayment_absolute_threshold: OverpaymentAbsoluteThreshold,
    pub underpayment_relative_threshold: String,
}

#[derive(Debug, Clone, Serialize, Default, Deserialize, PartialEq, Eq)]
pub struct OverpaymentAbsoluteThreshold {
    pub amount: StringMajorUnit,
    pub currency: String,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct PaymentElement {
    pub net: CoinbaseProcessingFee,
    pub block: Block,
    pub value: CoinbaseProcessingFee,
    pub status: String,
    pub network: String,
    pub deposited: Deposited,
    pub payment_id: String,
    pub detected_at: String,
    pub transaction_id: String,
    pub coinbase_processing_fee: CoinbaseProcessingFee,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Block {
    pub hash: Option<String>,
    pub height: Option<i64>,
    pub confirmations: Option<i64>,
    pub confirmations_required: Option<i64>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct CoinbaseProcessingFee {
    pub local: Option<OverpaymentAbsoluteThreshold>,
    pub crypto: OverpaymentAbsoluteThreshold,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Deposited {
    pub amount: Amount,
    pub status: String,
    pub destination: String,
    pub exchange_rate: Option<serde_json::Value>,
    pub autoconversion_status: String,
    pub autoconversion_enabled: bool,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Amount {
    pub net: CoinbaseProcessingFee,
    pub gross: CoinbaseProcessingFee,
    pub coinbase_fee: CoinbaseProcessingFee,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct TimelinePayment {
    pub value: OverpaymentAbsoluteThreshold,
    pub network: String,
    pub transaction_id: String,
}


impl api::RefundExecute for Coingate {}

impl api::RefundExecute for for Coingate


impl Deref for Context {
    type Target = HashMap<String, Option<ValueType>>;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}


impl CtxValueKind<'_> {
    pub fn get_assertion(&self) -> Option<&dir::DirValue> {
        if let Self::Assertion(val) = self {
            Some(val)
        } else {
            None
        }
    }

    pub fn get_negation(&self) -> Option<&[dir::DirValue]> {
        if let Self::Negation(vals) = self {
            Some(vals)
        } else {
            None
        }
    }

    pub fn get_key(&self) -> Option<dir::DirKey> {
        match self {
            Self::Assertion(val) => Some(val.get_key()),
            Self::Negation(vals) => vals.first().map(|v| (*v).get_key()),
        }
    }
}


OpenAPI Block Path: paths."/payments/{payment_id}"
{
  "post": {
    "tags": [
      "Payments"
    ],
    "summary": "Payments - Update",
    "description": "To update the properties of a *PaymentIntent* object. This may include attaching a payment method, or attaching customer object or metadata fields after the Payment is created",
    "operationId": "Update a Payment",
    "parameters": [
      {
        "name": "payment_id",
        "in": "path",
        "description": "The identifier for payment",
        "required": true,
        "schema": {
          "type": "string"
        }
      }
    ],
    "requestBody": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/PaymentsUpdateRequest"
          },
          "examples": {
            "Update the payment amount": {
              "value": {
                "amount": 7654
              }
            },
            "Update the shipping address": {
              "value": {
                "shipping": {
                  "address": {
                    "city": "San Fransico",
                    "country": "US",
                    "first_name": "joseph",
                    "last_name": "Doe",
                    "line1": "1467",
                    "line2": "Harrison Street",
                    "line3": "Harrison Street",
                    "state": "California",
                    "zip": "94122"
                  },
                  "phone": {
                    "country_code": "+91",
                    "number": "9123456789"
                  }
                }
              }
            }
          }
        }
      },
      "required": true
    },
    "responses": {
      "200": {
        "description": "Payment updated",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/PaymentsCreateResponseOpenApi"
            }
          }
        }
      },
      "400": {
        "description": "Missing mandatory fields",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/GenericErrorResponseOpenApi"
            }
          }
        }
      }
    },
    "security": [
      {
        "api_key": []
      },
      {
        "publishable_key": []
      }
    ]
  },
  "get": {
    "tags": [
      "Payments"
    ],
    "summary": "Payments - Retrieve",
    "description": "Retrieves a Payment. This API can also be used to get the status of a previously initiated payment or next action for an ongoing payment",
    "operationId": "Retrieve a Payment",
    "parameters": [
      {
        "name": "payment_id",
        "in": "path",
        "description": "The identifier for payment",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      {
        "name": "force_sync",
        "in": "query",
        "description": "Decider to enable or disable the connector call for retrieve request",
        "required": false,
        "schema": {
          "type": "boolean",
          "nullable": true
        }
      },
      {
        "name": "client_secret",
        "in": "query",
        "description": "This is a token which expires after 15 minutes, used from the client to authenticate and create sessions from the SDK",
        "required": false,
        "schema": {
          "type": "string",
          "nullable": true
        }
      },
      {
        "name": "expand_attempts",
        "in": "query",
        "description": "If enabled provides list of attempts linked to payment intent",
        "required": false,
        "schema": {
          "type": "boolean",
          "nullable": true
        }
      },
      {
        "name": "expand_captures",
        "in": "query",
        "description": "If enabled provides list of captures linked to latest attempt",
        "required": false,
        "schema": {
          "type": "boolean",
          "nullable": true
        }
      }
    ],
    "responses": {
      "200": {
        "description": "Gets the payment with final status",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/PaymentsResponse"
            }
          }
        }
      },
      "404": {
        "description": "No payment found"
      }
    },
    "security": [
      {
        "api_key": []
      },
      {
        "publishable_key": []
      }
    ]
  }
}


pub async fn find_by_merchant_reference_id_merchant_id(
        conn: &PgPooledConn,
        merchant_reference_id: &str,
        merchant_id: &common_utils::id_type::MerchantId,
    ) -> StorageResult<Self> {
        generics::generic_find_one::<<Self as HasTable>::Table, _, _>(
            conn,
            dsl::merchant_id
                .eq(merchant_id.to_owned())
                .and(dsl::merchant_reference_id.eq(merchant_reference_id.to_owned())),
        )
        .await
    }


pub struct DwollaPaymentLinks {
    source: DwollaRequestLink,
    destination: DwollaRequestLink,
}


impl api::ConnectorMandateRevoke for Noon {}

impl api::ConnectorMandateRevoke for for Noon


impl api::PaymentSession for Fiserv {}


pub async fn get_disputes_filters_profile(
    state: web::Data<AppState>,
    req: HttpRequest,
) -> HttpResponse {
    let flow = Flow::DisputesFilters;
    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        (),
        |state, auth: auth::AuthenticationData, _, _| {
            let merchant_context = domain::MerchantContext::NormalMerchant(Box::new(
                domain::Context(auth.merchant_account, auth.key_store),
            ));
            disputes::get_filters_for_disputes(
                state,
                merchant_context,
                auth.profile_id.map(|profile_id| vec![profile_id]),
            )
        },
        auth::auth_type(
            &auth::HeaderAuth(auth::ApiKeyAuth {
                is_connected_allowed: false,
                is_platform_allowed: false,
            }),
            &auth::JWTAuth {
                permission: Permission::ProfileDisputeRead,
            },
            req.headers(),
        ),
        api_locking::LockAction::NotApplicable,
    ))
    .await
}


pub struct PaymentRequestBankTransfer {
    pub payment_method: TrustpayBankTransferPaymentMethod,
    pub merchant_identification: MerchantIdentification,
    pub payment_information: BankPaymentInformation,
    pub callback_urls: CallbackURLs,
}


pub struct Handler {
    inner: Arc<HandlerInner>,
}


impl<O> InterpreterBackend<O>
where
    O: Clone,
{
    fn eval_number_comparison_array(
        num: MinorUnit,
        array: &[ast::NumberComparison],
    ) -> Result<bool, types::InterpreterError> {
        for comparison in array {
            let other = comparison.number;
            let res = match comparison.comparison_type {
                ast::ComparisonType::GreaterThan => num > other,
                ast::ComparisonType::LessThan => num < other,
                ast::ComparisonType::LessThanEqual => num <= other,
                ast::ComparisonType::GreaterThanEqual => num >= other,
                ast::ComparisonType::Equal => num == other,
                ast::ComparisonType::NotEqual => num != other,
            };

            if res {
                return Ok(true);
            }
        }

        Ok(false)
    }

    fn eval_comparison(
        comparison: &ast::Comparison,
        ctx: &types::Context,
    ) -> Result<bool, types::InterpreterError> {
        use ast::{ComparisonType::*, ValueType::*};

        let value = ctx
            .get(&comparison.lhs)
            .ok_or_else(|| types::InterpreterError {
                error_type: types::InterpreterErrorType::InvalidKey(comparison.lhs.clone()),
                metadata: comparison.metadata.clone(),
            })?;

        if let Some(val) = value {
            match (val, &comparison.comparison, &comparison.value) {
                (EnumVariant(e1), Equal, EnumVariant(e2)) => Ok(e1 == e2),
                (EnumVariant(e1), NotEqual, EnumVariant(e2)) => Ok(e1 != e2),
                (EnumVariant(e), Equal, EnumVariantArray(evec)) => Ok(evec.iter().any(|v| e == v)),
                (EnumVariant(e), NotEqual, EnumVariantArray(evec)) => {
                    Ok(evec.iter().all(|v| e != v))
                }
                (Number(n1), Equal, Number(n2)) => Ok(n1 == n2),
                (Number(n1), NotEqual, Number(n2)) => Ok(n1 != n2),
                (Number(n1), LessThanEqual, Number(n2)) => Ok(n1 <= n2),
                (Number(n1), GreaterThanEqual, Number(n2)) => Ok(n1 >= n2),
                (Number(n1), LessThan, Number(n2)) => Ok(n1 < n2),
                (Number(n1), GreaterThan, Number(n2)) => Ok(n1 > n2),
                (Number(n), Equal, NumberArray(nvec)) => Ok(nvec.iter().any(|v| v == n)),
                (Number(n), NotEqual, NumberArray(nvec)) => Ok(nvec.iter().all(|v| v != n)),
                (Number(n), Equal, NumberComparisonArray(ncvec)) => {
                    Self::eval_number_comparison_array(*n, ncvec)
                }
                _ => Err(types::InterpreterError {
                    error_type: types::InterpreterErrorType::InvalidComparison,
                    metadata: comparison.metadata.clone(),
                }),
            }
        } else {
            Ok(false)
        }
    }

    fn eval_if_condition(
        condition: &ast::IfCondition,
        ctx: &types::Context,
    ) -> Result<bool, types::InterpreterError> {
        for comparison in condition {
            let res = Self::eval_comparison(comparison, ctx)?;

            if !res {
                return Ok(false);
            }
        }

        Ok(true)
    }

    fn eval_if_statement(
        stmt: &ast::IfStatement,
        ctx: &types::Context,
    ) -> Result<bool, types::InterpreterError> {
        let cond_res = Self::eval_if_condition(&stmt.condition, ctx)?;

        if !cond_res {
            return Ok(false);
        }

        if let Some(ref nested) = stmt.nested {
            for nested_if in nested {
                let res = Self::eval_if_statement(nested_if, ctx)?;

                if res {
                    return Ok(true);
                }
            }

            return Ok(false);
        }

        Ok(true)
    }

    fn eval_rule_statements(
        statements: &[ast::IfStatement],
        ctx: &types::Context,
    ) -> Result<bool, types::InterpreterError> {
        for stmt in statements {
            let res = Self::eval_if_statement(stmt, ctx)?;

            if res {
                return Ok(true);
            }
        }

        Ok(false)
    }

    #[inline]
    fn eval_rule(
        rule: &ast::Rule<O>,
        ctx: &types::Context,
    ) -> Result<bool, types::InterpreterError> {
        Self::eval_rule_statements(&rule.statements, ctx)
    }

    fn eval_program(
        program: &ast::Program<O>,
        ctx: &types::Context,
    ) -> Result<backend::BackendOutput<O>, types::InterpreterError> {
        for rule in &program.rules {
            let res = Self::eval_rule(rule, ctx)?;

            if res {
                return Ok(backend::BackendOutput {
                    connector_selection: rule.connector_selection.clone(),
                    rule_name: Some(rule.name.clone()),
                });
            }
        }

        Ok(backend::BackendOutput {
            connector_selection: program.default_selection.clone(),
            rule_name: None,
        })
    }
}


pub struct PaymeAuthType {
    #[allow(dead_code)]
    pub(super) payme_public_key: Secret<String>,
    pub(super) seller_payme_id: Secret<String>,
    pub(super) payme_merchant_id: Option<Secret<String>>,
}


impl api::MandateSetup for Trustpayments {}

impl api::MandateSetup for for Trustpayments


File: crates/openapi/src/routes/gsm.rs
 Public functions: 4

/// Gsm - Create
///
/// Creates a GSM (Global Status Mapping) Rule. A GSM rule is used to map a connector's error message/error code combination during a particular payments flow/sub-flow to Hyperswitch's unified status/error code/error message combination. It is also used to decide the next action in the flow - retry/requeue/do_default
#[utoipa::path(
    post,
    path = "/gsm",
    request_body(
        content = GsmCreateRequest,
    ),
    responses(
        (status = 200, description = "Gsm created", body = GsmResponse),
        (status = 400, description = "Missing Mandatory fields")
    ),
    tag = "Gsm",
    operation_id = "Create Gsm Rule",
    security(("admin_api_key" = [])),
)]
pub async fn create_gsm_rule() {}

/// Gsm - Get
///
/// Retrieves a Gsm Rule
#[utoipa::path(
    post,
    path = "/gsm/get",
    request_body(
        content = GsmRetrieveRequest,
    ),
    responses(
        (status = 200, description = "Gsm retrieved", body = GsmResponse),
        (status = 400, description = "Missing Mandatory fields")
    ),
    tag = "Gsm",
    operation_id = "Retrieve Gsm Rule",
    security(("admin_api_key" = [])),
)]
pub async fn get_gsm_rule() {}

/// Gsm - Update
///
/// Updates a Gsm Rule
#[utoipa::path(
    post,
    path = "/gsm/update",
    request_body(
        content = GsmUpdateRequest,
    ),
    responses(
        (status = 200, description = "Gsm updated", body = GsmResponse),
        (status = 400, description = "Missing Mandatory fields")
    ),
    tag = "Gsm",
    operation_id = "Update Gsm Rule",
    security(("admin_api_key" = [])),
)]
pub async fn update_gsm_rule() {}

/// Gsm - Delete
///
/// Deletes a Gsm Rule
#[utoipa::path(
    post,
    path = "/gsm/delete",
    request_body(
        content = GsmDeleteRequest,
    ),
    responses(
        (status = 200, description = "Gsm deleted", body = GsmDeleteResponse),
        (status = 400, description = "Missing Mandatory fields")
    ),
    tag = "Gsm",
    operation_id = "Delete Gsm Rule",
    security(("admin_api_key" = [])),
)]
pub async fn delete_gsm_rule() {}


pub struct ThunesPaymentsResponse {
    status: ThunesPaymentStatus,
    id: String,
}


impl api::PaymentSession for Payme {}


impl Capturable for PaymentsIncrementalAuthorizationData {
    fn get_amount_capturable<F>(
        &self,
        _payment_data: &PaymentData<F>,
        amount_capturable: Option<i64>,
        _attempt_status: common_enums::AttemptStatus,
    ) -> Option<i64>
    where
        F: Clone,
    {
        amount_capturable.or(Some(self.total_amount))
    }
}

impl Capturable for for PaymentsIncrementalAuthorizationData


pub fn get_inner(&self) -> &pii::Email {
        &self.0
    }


pub struct MerchantData {
    /// ID of the merchant. This value will be used to find merchant information from the configuration.
    /// From the merchant configuration the 3DS Server can fill the other values (mcc, merchantCountryCode and merchantName), if provided.
    ///
    /// This field can be left out if merchant information are provided in the request.
    pub merchant_configuration_id: Option<String>,

    /// Merchant Category Code. This is the DS-specific code describing the Merchant's type of business, product or service.
    /// The field is limited to 4 characters. The value correlates to the Merchant Category Code as defined by each Payment System or DS.
    ///
    /// If not present in the request it will be filled from the merchant configuration referenced by the merchantConfigurationId.
    ///
    /// This field is required for messageCategory=01 (PA) and optional, but strongly recommended for 02 (NPA).
    #[serde(skip_serializing_if = "Option::is_none")]
    pub mcc: Option<String>,

    /// Country code for the merchant. This value correlates to the Merchant Country Code as defined by each Payment System or DS.
    /// The field is limited to 3 characters accepting ISO 3166-1 format, except 901-999.
    ///
    /// If not present in the request it will be filled from the merchant configuration referenced by the merchantConfigurationId.
    ///
    /// This field is required for messageCategory=01 (PA) and optional, but strongly recommended for 02 (NPA).
    #[serde(skip_serializing_if = "Option::is_none")]
    pub merchant_country_code: Option<String>,

    /// Merchant name assigned by the Acquirer or Payment System. This field is limited to maximum 40 characters,
    /// and it is the same name used in the authorisation message as defined in ISO 8583.
    ///
    /// If not present in the request it will be filled from the merchant configuration referenced by the merchantConfigurationId.
    ///
    /// This field is required for messageCategory=01 (PA) and optional, but strongly recommended for 02 (NPA).
    #[serde(skip_serializing_if = "Option::is_none")]
    pub merchant_name: Option<String>,

    /// Fully qualified URL of the merchant that receives the CRes message or Error Message.
    /// Incorrect formatting will result in a failure to deliver the notification of the final CRes message.
    /// This field is limited to 256 characters.
    ///
    /// This field should be present if the merchant will receive the final CRes message and the device channel is BROWSER.
    /// If not present in the request it will be filled from the notificationURL configured in the XML or database configuration.
    #[serde(rename = "notificationURL")]
    #[serde(skip_serializing_if = "Option::is_none")]
    pub notification_url: Option<String>,

    /// Each DS provides rules for the 3DS Requestor ID. The 3DS Requestor is responsible for providing the 3DS Requestor ID according to the DS rules.
    ///
    /// This value is mandatory, therefore it should be either configured for each Merchant Acquirer, or should be
    /// passed in the transaction payload as part of the Merchant data.
    #[serde(rename = "threeDSRequestorId")]
    #[serde(skip_serializing_if = "Option::is_none")]
    pub three_ds_requestor_id: Option<String>,

    /// Each DS provides rules for the 3DS Requestor Name. The 3DS Requestor is responsible for providing the 3DS Requestor Name according to the DS rules.
    ///
    /// This value is mandatory, therefore it should be either configured for each Merchant Acquirer, or should be
    /// passed in the transaction payload as part of the Merchant data.
    #[serde(rename = "threeDSRequestorName")]
    #[serde(skip_serializing_if = "Option::is_none")]
    pub three_ds_requestor_name: Option<String>,

    /// Set whitelisting status of the merchant.
    ///
    /// The field is optional and if value is not present, the whitelist remains unchanged.
    /// This field is only available for supporting EMV 3DS 2.2.0.
    pub white_list_status: Option<WhitelistStatus>,

    /// Set trustlisting status of the merchant.
    ///
    /// The field is optional and if value is not present, the trustlist remains unchanged.
    /// From EMV 3DS 2.3.1 this field replaces whiteListStatus.
    pub trust_list_status: Option<WhitelistStatus>,

    /// Additional transaction information for transactions where merchants submit transaction details on behalf of another entity.
    /// The accepted value length is 1-50 elements.
    ///
    /// This field is optional.
    pub seller_info: Option<Vec<SellerInfo>>,

    /// Fully qualified URL of the merchant that receives the RRes message or Error Message.
    /// Incorrect formatting will result in a failure to deliver the notification of the final RRes message.
    /// This field is limited to 256 characters.
    ///
    /// This field is not mandatory and could be present if the Results Response (in case of a challenge transaction)
    /// should be sent to a dynamic URL different from the one present in the configuration, only if dynamic provision
    /// of the Results Response notification URL is allowed per the license.
    ///
    /// If not present in the request it will be filled from the notificationURL configured in the XML or database
    /// configuration.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub results_response_notification_url: Option<String>,
}


impl ConnectorSpecifications for Bitpay {
    fn get_connector_about(&self) -> Option<&'static ConnectorInfo> {
        Some(&BITPAY_CONNECTOR_INFO)
    }

    fn get_supported_payment_methods(&self) -> Option<&'static SupportedPaymentMethods> {
        Some(&*BITPAY_SUPPORTED_PAYMENT_METHODS)
    }

    fn get_supported_webhook_flows(&self) -> Option<&'static [enums::EventClass]> {
        Some(&BITPAY_SUPPORTED_WEBHOOK_FLOWS)
    }
}

impl ConnectorSpecifications for for Bitpay


pub struct SiftPaymentsResponse {
    status: SiftPaymentStatus,
    id: String,
}


pub fn get_id(&self) -> id_type::MerchantConnectorAccountId {
        self.merchant_connector_id.clone()
    }