                )?)
                .build(),
        ))
    }

    fn handle_response(
        &self,
        data: &PaymentsPreProcessingRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PaymentsPreProcessingRouterData, errors::ConnectorError> {
        let response: adyen::AdyenBalanceResponse = res
            .response
            .parse_struct("AdyenBalanceResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
        event_builder.map(|i| i.set_response_body(&response));
        router_env::logger::info!(connector_response=?response);

        let currency = match data.request.currency {
            Some(currency) => currency,
            None => Err(errors::ConnectorError::MissingRequiredField {
                field_name: "currency",
            })?,
        };
        let amount = match data.request.minor_amount {
            Some(amount) => amount,
            None => Err(errors::ConnectorError::MissingRequiredField {
                field_name: "amount",
            })?,
        };

        let amount = convert_amount(self.amount_converter, amount, currency)?;

        if response.balance.currency != currency || response.balance.value < amount {
            Ok(RouterData {
                response: Err(ErrorResponse {
                    code: NO_ERROR_CODE.to_string(),
                    message: NO_ERROR_MESSAGE.to_string(),
                    reason: Some(constants::LOW_BALANCE_ERROR_MESSAGE.to_string()),
                    status_code: res.status_code,
                    attempt_status: Some(enums::AttemptStatus::Failure),
                    connector_transaction_id: Some(response.psp_reference),
                    network_advice_code: None,
                    network_decline_code: None,
                    network_error_message: None,
                    connector_metadata: None,
                }),
                ..data.clone()
            })
        } else {
            RouterData::try_from(ResponseRouterData {
                response,
                data: data.clone(),
                http_code: res.status_code,
            })
            .change_context(errors::ConnectorError::ResponseHandlingFailed)
        }
    }

    fn get_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        self.build_error_response(res, event_builder)
    }

    fn get_5xx_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        self.build_error_response(res, event_builder)
    }
}

impl ConnectorIntegration<Void, PaymentsCancelData, PaymentsResponseData> for Adyen {
    fn get_headers(
        &self,
        req: &PaymentsCancelRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<Vec<(String, Maskable<String>)>, errors::ConnectorError> {
        let mut header = vec![(
            headers::CONTENT_TYPE.to_string(),
            PaymentsAuthorizeType::get_content_type(self)
                .to_string()
                .into(),
        )];
        let mut api_key = self.get_auth_header(&req.connector_auth_type)?;
        header.append(&mut api_key);
        Ok(header)
    }

    fn get_url(
        &self,
        req: &PaymentsCancelRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        let id = req.request.connector_transaction_id.clone();

        let endpoint = build_env_specific_endpoint(
            self.base_url(connectors),
            req.test_mode,
            &req.connector_meta_data,
        )?;
        Ok(format!(
            "{endpoint}{ADYEN_API_VERSION}/payments/{id}/cancels",
        ))
    }

    fn get_request_body(
        &self,
        req: &PaymentsCancelRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let connector_req = adyen::AdyenCancelRequest::try_from(req)?;

        Ok(RequestContent::Json(Box::new(connector_req)))
    }
    fn build_request(
        &self,
        req: &PaymentsCancelRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        Ok(Some(
            RequestBuilder::new()
                .method(Method::Post)
                .url(&PaymentsVoidType::get_url(self, req, connectors)?)
                .attach_default_headers()
                .headers(PaymentsVoidType::get_headers(self, req, connectors)?)
                .set_body(PaymentsVoidType::get_request_body(self, req, connectors)?)
                .build(),
        ))
    }

    fn handle_response(
        &self,
        data: &PaymentsCancelRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PaymentsCancelRouterData, errors::ConnectorError> {
        let response: adyen::AdyenCancelResponse = res
            .response
            .parse_struct("AdyenCancelResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
        event_builder.map(|i| i.set_response_body(&response));
        router_env::logger::info!(connector_response=?response);
        RouterData::try_from(ResponseRouterData {
            response,
            data: data.clone(),
            http_code: res.status_code,
        })
        .change_context(errors::ConnectorError::ResponseHandlingFailed)
    }

    fn get_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        self.build_error_response(res, event_builder)
    }
    fn get_5xx_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        self.build_error_response(res, event_builder)
    }
}

impl
    ConnectorIntegration<
        GiftCardBalanceCheck,
        GiftCardBalanceCheckRequestData,
        GiftCardBalanceCheckResponseData,
    > for Adyen
{
    fn get_headers(
        &self,
        req: &PaymentsGiftCardBalanceCheckRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<Vec<(String, Maskable<String>)>, errors::ConnectorError> {
        let mut header = vec![(
            headers::CONTENT_TYPE.to_string(),
            PaymentsGiftCardBalanceCheckType::get_content_type(self)
                .to_string()
                .into(),
        )];
        let mut api_key = self.get_auth_header(&req.connector_auth_type)?;
        header.append(&mut api_key);
        Ok(header)
    }

    fn get_url(
        &self,
        req: &PaymentsGiftCardBalanceCheckRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        let endpoint = build_env_specific_endpoint(
            self.base_url(connectors),
            req.test_mode,
            &req.connector_meta_data,
        )?;
        Ok(format!(
            "{endpoint}{ADYEN_API_VERSION}/paymentMethods/balance",
        ))
    }

    fn get_request_body(
        &self,
        req: &PaymentsGiftCardBalanceCheckRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let connector_req = adyen::AdyenBalanceRequest::try_from(req)?;

        Ok(RequestContent::Json(Box::new(connector_req)))
    }

    fn build_request(
        &self,
        req: &PaymentsGiftCardBalanceCheckRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        Ok(Some(
            RequestBuilder::new()
                .method(Method::Post)
                .url(&PaymentsGiftCardBalanceCheckType::get_url(
                    self, req, connectors,
                )?)
                .attach_default_headers()
                .headers(PaymentsGiftCardBalanceCheckType::get_headers(
                    self, req, connectors,
                )?)
                .set_body(PaymentsGiftCardBalanceCheckType::get_request_body(
                    self, req, connectors,
                )?)
                .build(),
        ))
    }

    fn handle_response(
        &self,
        data: &PaymentsGiftCardBalanceCheckRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PaymentsGiftCardBalanceCheckRouterData, errors::ConnectorError> {
        let response: adyen::AdyenBalanceResponse = res
            .response
            .parse_struct("AdyenBalanceResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
        event_builder.map(|i| i.set_response_body(&response));
        router_env::logger::info!(connector_response=?response);

        RouterData::try_from(ResponseRouterData {
            response,
            data: data.clone(),
            http_code: res.status_code,
        })
        .change_context(errors::ConnectorError::ResponseHandlingFailed)
    }

    fn get_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        self.build_error_response(res, event_builder)
    }

    fn get_5xx_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        self.build_error_response(res, event_builder)
    }
}

impl api::Payouts for Adyen {}
#[cfg(feature = "payouts")]
impl api::PayoutCancel for Adyen {}
#[cfg(feature = "payouts")]
impl api::PayoutCreate for Adyen {}
#[cfg(feature = "payouts")]
impl api::PayoutEligibility for Adyen {}
#[cfg(feature = "payouts")]
impl api::PayoutFulfill for Adyen {}

#[cfg(feature = "payouts")]
impl ConnectorIntegration<PoCancel, PayoutsData, PayoutsResponseData> for Adyen {
    fn get_url(
        &self,
        req: &PayoutsRouterData<PoCancel>,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        let endpoint = build_env_specific_endpoint(
            connectors.adyen.payout_base_url.as_str(),
            req.test_mode,
            &req.connector_meta_data,
        )?;
        Ok(format!(
            "{endpoint}pal/servlet/Payout/{ADYEN_API_VERSION}/declineThirdParty",
        ))
    }

    fn get_headers(
        &self,
        req: &PayoutsRouterData<PoCancel>,
        _connectors: &Connectors,
    ) -> CustomResult<Vec<(String, Maskable<String>)>, errors::ConnectorError> {
        let mut header = vec![(
            headers::CONTENT_TYPE.to_string(),
            PayoutCancelType::get_content_type(self).to_string().into(),
        )];
        let auth = adyen::AdyenAuthType::try_from(&req.connector_auth_type)
            .change_context(errors::ConnectorError::FailedToObtainAuthType)?;
        let mut api_key = vec![(
            headers::X_API_KEY.to_string(),
            auth.review_key.unwrap_or(auth.api_key).into_masked(),
        )];
        header.append(&mut api_key);
        Ok(header)
    }

    fn get_request_body(
        &self,
        req: &PayoutsRouterData<PoCancel>,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let connector_req = adyen::AdyenPayoutCancelRequest::try_from(req)?;
        Ok(RequestContent::Json(Box::new(connector_req)))
    }

    fn build_request(
        &self,
        req: &PayoutsRouterData<PoCancel>,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        let request = RequestBuilder::new()
            .method(Method::Post)
            .url(&PayoutCancelType::get_url(self, req, connectors)?)
            .attach_default_headers()
            .headers(PayoutCancelType::get_headers(self, req, connectors)?)
            .set_body(PayoutCancelType::get_request_body(self, req, connectors)?)
            .build();

        Ok(Some(request))
    }

    #[instrument(skip_all)]
    fn handle_response(
        &self,
        data: &PayoutsRouterData<PoCancel>,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PayoutsRouterData<PoCancel>, errors::ConnectorError> {
        let response: adyen::AdyenPayoutResponse = res
            .response
            .parse_struct("AdyenPayoutResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
        event_builder.map(|i| i.set_response_body(&response));
        router_env::logger::info!(connector_response=?response);
        RouterData::try_from(ResponseRouterData {
            response,
            data: data.clone(),
            http_code: res.status_code,
        })
    }

    fn get_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        self.build_error_response(res, event_builder)
    }
    fn get_5xx_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        self.build_error_response(res, event_builder)
    }
}

#[cfg(feature = "payouts")]
impl ConnectorIntegration<PoCreate, PayoutsData, PayoutsResponseData> for Adyen {
    fn get_url(
        &self,
        req: &PayoutsRouterData<PoCreate>,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        let endpoint = build_env_specific_endpoint(
            connectors.adyen.payout_base_url.as_str(),
            req.test_mode,
            &req.connector_meta_data,
        )?;
        Ok(format!(
            "{endpoint}pal/servlet/Payout/{ADYEN_API_VERSION}/storeDetailAndSubmitThirdParty",
        ))
    }

    fn get_headers(
        &self,
        req: &PayoutsRouterData<PoCreate>,
        _connectors: &Connectors,
    ) -> CustomResult<Vec<(String, Maskable<String>)>, errors::ConnectorError> {
        let mut header = vec![(
            headers::CONTENT_TYPE.to_string(),
            PayoutCreateType::get_content_type(self).to_string().into(),
        )];
        let mut api_key = self.get_auth_header(&req.connector_auth_type)?;
        header.append(&mut api_key);
        Ok(header)
    }

    fn get_request_body(
        &self,
        req: &PayoutsRouterData<PoCreate>,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let amount = convert_amount(
            self.amount_converter,
            req.request.minor_amount,
            req.request.destination_currency,
        )?;
        let connector_router_data = adyen::AdyenRouterData::try_from((amount, req))?;
        let connector_req = adyen::AdyenPayoutCreateRequest::try_from(&connector_router_data)?;
        Ok(RequestContent::Json(Box::new(connector_req)))
    }

    fn build_request(
        &self,
        req: &PayoutsRouterData<PoCreate>,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        let request = RequestBuilder::new()
            .method(Method::Post)
            .url(&PayoutCreateType::get_url(self, req, connectors)?)
            .attach_default_headers()
            .headers(PayoutCreateType::get_headers(self, req, connectors)?)
            .set_body(PayoutCreateType::get_request_body(self, req, connectors)?)
            .build();

        Ok(Some(request))
    }

    #[instrument(skip_all)]
    fn handle_response(
        &self,
        data: &PayoutsRouterData<PoCreate>,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PayoutsRouterData<PoCreate>, errors::ConnectorError> {
        let response: adyen::AdyenPayoutResponse = res
            .response
            .parse_struct("AdyenPayoutResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
        event_builder.map(|i| i.set_response_body(&response));
        router_env::logger::info!(connector_response=?response);
        RouterData::try_from(ResponseRouterData {
            response,
            data: data.clone(),
            http_code: res.status_code,
        })
    }

    fn get_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        self.build_error_response(res, event_builder)
    }
    fn get_5xx_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        self.build_error_response(res, event_builder)
    }
}

#[cfg(feature = "payouts")]
impl ConnectorIntegration<PoEligibility, PayoutsData, PayoutsResponseData> for Adyen {
    fn get_url(
        &self,
        req: &PayoutsRouterData<PoEligibility>,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        let endpoint = build_env_specific_endpoint(
            self.base_url(connectors),
            req.test_mode,
            &req.connector_meta_data,
        )?;
        Ok(format!("{endpoint}{ADYEN_API_VERSION}/payments"))
    }

    fn get_headers(
        &self,
        req: &PayoutsRouterData<PoEligibility>,
        _connectors: &Connectors,
    ) -> CustomResult<Vec<(String, Maskable<String>)>, errors::ConnectorError> {
        let mut header = vec![(
            headers::CONTENT_TYPE.to_string(),
            PayoutEligibilityType::get_content_type(self)
                .to_string()
                .into(),
        )];
        let mut api_key = self.get_auth_header(&req.connector_auth_type)?;
        header.append(&mut api_key);
        Ok(header)
    }

    fn get_request_body(
        &self,
        req: &PayoutsRouterData<PoEligibility>,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let amount = convert_amount(
            self.amount_converter,
            req.request.minor_amount,
            req.request.destination_currency,
        )?;

        let connector_router_data = adyen::AdyenRouterData::try_from((amount, req))?;
        let connector_req = adyen::AdyenPayoutEligibilityRequest::try_from(&connector_router_data)?;
        Ok(RequestContent::Json(Box::new(connector_req)))
    }

    fn build_request(
        &self,
        req: &PayoutsRouterData<PoEligibility>,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        let request = RequestBuilder::new()
            .method(Method::Post)
            .url(&PayoutEligibilityType::get_url(self, req, connectors)?)
            .attach_default_headers()
            .headers(PayoutEligibilityType::get_headers(self, req, connectors)?)
            .set_body(PayoutEligibilityType::get_request_body(
                self, req, connectors,
            )?)
            .build();

        Ok(Some(request))
    }

    #[instrument(skip_all)]
    fn handle_response(
        &self,
        data: &PayoutsRouterData<PoEligibility>,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PayoutsRouterData<PoEligibility>, errors::ConnectorError> {
        let response: adyen::AdyenPayoutResponse = res
            .response
            .parse_struct("AdyenPayoutResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
        event_builder.map(|i| i.set_response_body(&response));
        router_env::logger::info!(connector_response=?response);
        RouterData::try_from(ResponseRouterData {
            response,
            data: data.clone(),
            http_code: res.status_code,
        })
    }

    fn get_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        self.build_error_response(res, event_builder)
    }
    fn get_5xx_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        self.build_error_response(res, event_builder)
    }
}

#[cfg(feature = "payouts")]
impl ConnectorIntegration<PoFulfill, PayoutsData, PayoutsResponseData> for Adyen {
    fn get_url(
        &self,
        req: &PayoutsRouterData<PoFulfill>,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        let endpoint = build_env_specific_endpoint(
            connectors.adyen.payout_base_url.as_str(),
            req.test_mode,
            &req.connector_meta_data,
        )?;
        let payout_type = req.request.get_payout_type()?;
        Ok(format!(
            "{}pal/servlet/Payout/{}/{}",
            endpoint,
            ADYEN_API_VERSION,
            match payout_type {
                enums::PayoutType::Bank | enums::PayoutType::Wallet =>
                    "confirmThirdParty".to_string(),
                enums::PayoutType::Card => "payout".to_string(),
            }
        ))
    }

    fn get_headers(
        &self,
        req: &PayoutsRouterData<PoFulfill>,
        _connectors: &Connectors,
    ) -> CustomResult<Vec<(String, Maskable<String>)>, errors::ConnectorError> {
        let mut header = vec![(
            headers::CONTENT_TYPE.to_string(),
            PayoutFulfillType::get_content_type(self).to_string().into(),
        )];
        let auth = adyen::AdyenAuthType::try_from(&req.connector_auth_type)
            .change_context(errors::ConnectorError::FailedToObtainAuthType)?;
        let payout_type = req
            .request
            .payout_type
            .to_owned()
            .get_required_value("payout_type")
            .change_context(errors::ConnectorError::MissingRequiredField {
                field_name: "payout_type",
            })?;
        let mut api_key = vec![(
            headers::X_API_KEY.to_string(),
            match payout_type {
                enums::PayoutType::Bank | enums::PayoutType::Wallet => {
                    auth.review_key.unwrap_or(auth.api_key).into_masked()
                }
                enums::PayoutType::Card => auth.api_key.into_masked(),
            },
        )];
        header.append(&mut api_key);
        Ok(header)
    }

    fn get_request_body(
        &self,
        req: &PayoutsRouterData<PoFulfill>,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let amount = convert_amount(
            self.amount_converter,
            req.request.minor_amount,
            req.request.destination_currency,
        )?;

        let connector_router_data = adyen::AdyenRouterData::try_from((amount, req))?;
        let connector_req = adyen::AdyenPayoutFulfillRequest::try_from(&connector_router_data)?;
        Ok(RequestContent::Json(Box::new(connector_req)))
    }

    fn build_request(
        &self,
        req: &PayoutsRouterData<PoFulfill>,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        let request = RequestBuilder::new()
            .method(Method::Post)
            .url(&PayoutFulfillType::get_url(self, req, connectors)?)
            .attach_default_headers()
            .headers(PayoutFulfillType::get_headers(self, req, connectors)?)
            .set_body(PayoutFulfillType::get_request_body(self, req, connectors)?)
            .build();

        Ok(Some(request))
    }

    #[instrument(skip_all)]
    fn handle_response(
        &self,
        data: &PayoutsRouterData<PoFulfill>,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PayoutsRouterData<PoFulfill>, errors::ConnectorError> {
        let response: adyen::AdyenPayoutResponse = res
            .response
            .parse_struct("AdyenPayoutResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
        event_builder.map(|i| i.set_response_body(&response));
        router_env::logger::info!(connector_response=?response);
        RouterData::try_from(ResponseRouterData {
            response,
            data: data.clone(),
            http_code: res.status_code,
        })
    }

    fn get_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        self.build_error_response(res, event_builder)
    }
    fn get_5xx_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        self.build_error_response(res, event_builder)
    }
}

impl api::Refund for Adyen {}
impl api::RefundExecute for Adyen {}
impl api::RefundSync for Adyen {}

impl ConnectorIntegration<Execute, RefundsData, RefundsResponseData> for Adyen {
    fn get_headers(
        &self,
        req: &RefundsRouterData<Execute>,
        _connectors: &Connectors,
    ) -> CustomResult<Vec<(String, Maskable<String>)>, errors::ConnectorError> {
        let mut header = vec![(
            headers::CONTENT_TYPE.to_string(),
            RefundExecuteType::get_content_type(self).to_string().into(),
        )];
        let mut api_header = self.get_auth_header(&req.connector_auth_type)?;
        header.append(&mut api_header);
        Ok(header)
    }

    fn get_url(
        &self,
        req: &RefundsRouterData<Execute>,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        let connector_payment_id = req.request.connector_transaction_id.clone();

        let endpoint = build_env_specific_endpoint(
            self.base_url(connectors),
            req.test_mode,
            &req.connector_meta_data,
        )?;
        Ok(format!(
            "{endpoint}{ADYEN_API_VERSION}/payments/{connector_payment_id}/refunds",
        ))
    }

    fn get_request_body(
        &self,
        req: &RefundsRouterData<Execute>,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let refund_amount = convert_amount(
            self.amount_converter,
            req.request.minor_refund_amount,
            req.request.currency,
        )?;
        let connector_router_data = adyen::AdyenRouterData::try_from((refund_amount, req))?;
        let connector_req = adyen::AdyenRefundRequest::try_from(&connector_router_data)?;

        Ok(RequestContent::Json(Box::new(connector_req)))
    }

    fn build_request(
        &self,
        req: &RefundsRouterData<Execute>,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        Ok(Some(
            RequestBuilder::new()
                .method(Method::Post)
                .url(&RefundExecuteType::get_url(self, req, connectors)?)
                .attach_default_headers()
                .headers(RefundExecuteType::get_headers(self, req, connectors)?)
                .set_body(RefundExecuteType::get_request_body(self, req, connectors)?)
                .build(),
        ))
    }

    #[instrument(skip_all)]
    fn handle_response(
        &self,
        data: &RefundsRouterData<Execute>,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<RefundsRouterData<Execute>, errors::ConnectorError> {
        let response: adyen::AdyenRefundResponse = res
            .response
            .parse_struct("AdyenRefundResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
        event_builder.map(|i| i.set_response_body(&response));
        router_env::logger::info!(connector_response=?response);
        RouterData::try_from(ResponseRouterData {
            response,
            data: data.clone(),
            http_code: res.status_code,
        })
        .change_context(errors::ConnectorError::ResponseHandlingFailed)
    }

    fn get_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        self.build_error_response(res, event_builder)
    }
    fn get_5xx_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        self.build_error_response(res, event_builder)
    }
}

impl ConnectorIntegration<RSync, RefundsData, RefundsResponseData> for Adyen {}

fn get_webhook_object_from_body(
    body: &[u8],
) -> CustomResult<adyen::AdyenNotificationRequestItemWH, common_utils::errors::ParsingError> {
    let mut webhook: adyen::AdyenIncomingWebhook = body.parse_struct("AdyenIncomingWebhook")?;

    let item_object = webhook
        .notification_items
        .drain(..)
        .next()
        // TODO: ParsingError doesn't seem to be an apt error for this case
        .ok_or(common_utils::errors::ParsingError::UnknownError)?;

    Ok(item_object.notification_request_item)
}

#[async_trait::async_trait]
impl IncomingWebhook for Adyen {
    fn get_webhook_source_verification_algorithm(
        &self,
        _request: &IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<Box<dyn common_utils::crypto::VerifySignature + Send>, errors::ConnectorError>
    {
        Ok(Box::new(common_utils::crypto::HmacSha256))
    }

    fn get_webhook_source_verification_signature(
        &self,
        request: &IncomingWebhookRequestDetails<'_>,
        _connector_webhook_secrets: &api_models::webhooks::ConnectorWebhookSecrets,
    ) -> CustomResult<Vec<u8>, errors::ConnectorError> {
        let notif_item = get_webhook_object_from_body(request.body)
            .change_context(errors::ConnectorError::WebhookSourceVerificationFailed)?;

        let base64_signature = notif_item.additional_data.hmac_signature.expose();
        Ok(base64_signature.as_bytes().to_vec())
    }

    fn get_webhook_source_verification_message(
        &self,
        request: &IncomingWebhookRequestDetails<'_>,
        _merchant_id: &common_utils::id_type::MerchantId,
        _connector_webhook_secrets: &api_models::webhooks::ConnectorWebhookSecrets,
    ) -> CustomResult<Vec<u8>, errors::ConnectorError> {
        let notif = get_webhook_object_from_body(request.body)
            .change_context(errors::ConnectorError::WebhookSourceVerificationFailed)?;

        let message = format!(
            "{}:{}:{}:{}:{}:{}:{}:{}",
            notif.psp_reference,
            notif.original_reference.unwrap_or_default(),
            notif.merchant_account_code,
            notif.merchant_reference,
            notif.amount.value,
            notif.amount.currency,
            notif.event_code,
            notif.success
        );

        Ok(message.into_bytes())
    }

    async fn verify_webhook_source(
        &self,
        request: &IncomingWebhookRequestDetails<'_>,
        merchant_id: &common_utils::id_type::MerchantId,
        connector_webhook_details: Option<common_utils::pii::SecretSerdeValue>,
        _connector_account_details: common_utils::crypto::Encryptable<Secret<serde_json::Value>>,
        connector_label: &str,
    ) -> CustomResult<bool, errors::ConnectorError> {
        let connector_webhook_secrets = self
            .get_webhook_source_verification_merchant_secret(
                merchant_id,
                connector_label,
                connector_webhook_details,
            )
            .await
            .change_context(errors::ConnectorError::WebhookSourceVerificationFailed)?;

        let signature = self
            .get_webhook_source_verification_signature(request, &connector_webhook_secrets)
            .change_context(errors::ConnectorError::WebhookSourceVerificationFailed)?;

        let message = self
            .get_webhook_source_verification_message(
                request,
                merchant_id,
                &connector_webhook_secrets,
            )
            .change_context(errors::ConnectorError::WebhookSourceVerificationFailed)?;

        let raw_key = hex::decode(connector_webhook_secrets.secret)
            .change_context(errors::ConnectorError::WebhookVerificationSecretInvalid)?;

        let signing_key = hmac::Key::new(hmac::HMAC_SHA256, &raw_key);
        let signed_messaged = hmac::sign(&signing_key, &message);
        let payload_sign = consts::BASE64_ENGINE.encode(signed_messaged.as_ref());
        Ok(payload_sign.as_bytes().eq(&signature))
    }

    fn get_webhook_object_reference_id(
        &self,
        request: &IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<api_models::webhooks::ObjectReferenceId, errors::ConnectorError> {
        let notif = get_webhook_object_from_body(request.body)
            .change_context(errors::ConnectorError::WebhookReferenceIdNotFound)?;
        // for capture_event, original_reference field will have the authorized payment's PSP reference
        if adyen::is_capture_or_cancel_event(&notif.event_code) {
            return Ok(api_models::webhooks::ObjectReferenceId::PaymentId(
                api_models::payments::PaymentIdType::ConnectorTransactionId(
                    notif
                        .original_reference
                        .ok_or(errors::ConnectorError::WebhookReferenceIdNotFound)?,
                ),
            ));
        }
        if adyen::is_transaction_event(&notif.event_code) {
            return Ok(api_models::webhooks::ObjectReferenceId::PaymentId(
                api_models::payments::PaymentIdType::PaymentAttemptId(notif.merchant_reference),
            ));
        }
        if adyen::is_refund_event(&notif.event_code) {
            return Ok(api_models::webhooks::ObjectReferenceId::RefundId(
                api_models::webhooks::RefundIdType::RefundId(notif.merchant_reference),
            ));
        }
        if adyen::is_chargeback_event(&notif.event_code) {
            return Ok(api_models::webhooks::ObjectReferenceId::PaymentId(
                api_models::payments::PaymentIdType::ConnectorTransactionId(
                    notif
                        .original_reference
                        .ok_or(errors::ConnectorError::WebhookReferenceIdNotFound)?,
                ),
            ));
        }
        #[cfg(feature = "payouts")]
        if adyen::is_payout_event(&notif.event_code) {
            return Ok(api_models::webhooks::ObjectReferenceId::PayoutId(
                api_models::webhooks::PayoutIdType::PayoutAttemptId(notif.merchant_reference),
            ));
        }
        Err(report!(errors::ConnectorError::WebhookReferenceIdNotFound))
    }

    fn get_webhook_event_type(
        &self,
        request: &IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<api_models::webhooks::IncomingWebhookEvent, errors::ConnectorError> {
        let notif = get_webhook_object_from_body(request.body)
            .change_context(errors::ConnectorError::WebhookEventTypeNotFound)?;

        Ok(transformers::get_adyen_webhook_event(
            notif.event_code,
            notif.success,
            notif.additional_data.dispute_status,
        ))
    }

    fn get_webhook_resource_object(
        &self,
        request: &IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<Box<dyn masking::ErasedMaskSerialize>, errors::ConnectorError> {
        let notif = get_webhook_object_from_body(request.body)
            .change_context(errors::ConnectorError::WebhookEventTypeNotFound)?;

        let response = adyen::AdyenWebhookResponse::from(notif);

        Ok(Box::new(response))
    }

    fn get_webhook_api_response(
        &self,
        _request: &IncomingWebhookRequestDetails<'_>,
        _error_kind: Option<IncomingWebhookFlowError>,
    ) -> CustomResult<ApplicationResponse<serde_json::Value>, errors::ConnectorError> {
        Ok(ApplicationResponse::TextPlain("[accepted]".to_string()))
    }

    fn get_dispute_details(
        &self,
        request: &IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<disputes::DisputePayload, errors::ConnectorError> {
        let notif = get_webhook_object_from_body(request.body)
            .change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?;

        let amount = convert_amount(
            self.amount_converter_webhooks,
            notif.amount.value,
            notif.amount.currency,
        )?;
        Ok(disputes::DisputePayload {
            amount,
            currency: notif.amount.currency,
            dispute_stage: api_models::enums::DisputeStage::from(notif.event_code.clone()),
            connector_dispute_id: notif.psp_reference,
            connector_reason: notif.reason,
            connector_reason_code: notif.additional_data.chargeback_reason_code,
            challenge_required_by: notif.additional_data.defense_period_ends_at,
            connector_status: notif.event_code.to_string(),


// Implementation: impl TrustpaymentsPaymentResponseData
// File: crates/hyperswitch_connectors/src/connectors/trustpayments/transformers.rs
// Module: hyperswitch_connectors
// Methods: 4 total (4 public)

impl TrustpaymentsPaymentResponseData


// Struct: StoredCredentialMode
// File: crates/hyperswitch_connectors/src/connectors/nuvei/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 1

pub struct StoredCredentialMode


// Implementation: impl RoutingEvent
// File: crates/hyperswitch_interfaces/src/events/routing_api_logs.rs
// Module: hyperswitch_interfaces
// Methods: 16 total (12 public)

impl RoutingEvent


// File: crates/router/src/core/mandate.rs
// Module: router
// Public functions: 6

pub mod helpers;
pub mod utils;
use api_models::payments;
use common_types::payments as common_payments_types;
use common_utils::{ext_traits::Encode, id_type};
use diesel_models::enums as storage_enums;
use error_stack::{report, ResultExt};
use futures::future;
use router_env::{instrument, logger, tracing};

use super::payments::helpers as payment_helper;
use crate::{
    core::{
        errors::{self, RouterResponse, StorageErrorExt},
        payments::CallConnectorAction,
    },
    db::StorageInterface,
    routes::{metrics, SessionState},
    services,
    types::{
        self,
        api::{
            mandates::{self, MandateResponseExt},
            ConnectorData, GetToken,
        },
        domain,
        storage::{self, enums::MerchantStorageScheme},
        transformers::ForeignFrom,
    },
    utils::OptionExt,
};

#[instrument(skip(state))]
pub async fn get_mandate(
    state: SessionState,
    merchant_context: domain::MerchantContext,
    req: mandates::MandateId,
) -> RouterResponse<mandates::MandateResponse> {
    let mandate = state
        .store
        .as_ref()
        .find_mandate_by_merchant_id_mandate_id(
            merchant_context.get_merchant_account().get_id(),
            &req.mandate_id,
            merchant_context.get_merchant_account().storage_scheme,
        )
        .await
        .to_not_found_response(errors::ApiErrorResponse::MandateNotFound)?;
    Ok(services::ApplicationResponse::Json(
        mandates::MandateResponse::from_db_mandate(
            &state,
            merchant_context.get_merchant_key_store().clone(),
            mandate,
            merchant_context.get_merchant_account(),
        )
        .await?,
    ))
}

#[cfg(feature = "v1")]
#[instrument(skip(state))]
pub async fn revoke_mandate(
    state: SessionState,
    merchant_context: domain::MerchantContext,
    req: mandates::MandateId,
) -> RouterResponse<mandates::MandateRevokedResponse> {
    let db = state.store.as_ref();
    let mandate = db
        .find_mandate_by_merchant_id_mandate_id(
            merchant_context.get_merchant_account().get_id(),
            &req.mandate_id,
            merchant_context.get_merchant_account().storage_scheme,
        )
        .await
        .to_not_found_response(errors::ApiErrorResponse::MandateNotFound)?;
    match mandate.mandate_status {
        common_enums::MandateStatus::Active
        | common_enums::MandateStatus::Inactive
        | common_enums::MandateStatus::Pending => {
            let profile_id =
                helpers::get_profile_id_for_mandate(&state, &merchant_context, mandate.clone())
                    .await?;

            let merchant_connector_account = payment_helper::get_merchant_connector_account(
                &state,
                merchant_context.get_merchant_account().get_id(),
                None,
                merchant_context.get_merchant_key_store(),
                &profile_id,
                &mandate.connector.clone(),
                mandate.merchant_connector_id.as_ref(),
            )
            .await?;

            let connector_data = ConnectorData::get_connector_by_name(
                &state.conf.connectors,
                &mandate.connector,
                GetToken::Connector,
                mandate.merchant_connector_id.clone(),
            )?;
            let connector_integration: services::BoxedMandateRevokeConnectorIntegrationInterface<
                types::api::MandateRevoke,
                types::MandateRevokeRequestData,
                types::MandateRevokeResponseData,
            > = connector_data.connector.get_connector_integration();

            let router_data = utils::construct_mandate_revoke_router_data(
                &state,
                merchant_connector_account,
                &merchant_context,
                mandate.clone(),
            )
            .await?;

            let response = services::execute_connector_processing_step(
                &state,
                connector_integration,
                &router_data,
                CallConnectorAction::Trigger,
                None,
                None,
            )
            .await
            .change_context(errors::ApiErrorResponse::InternalServerError)?;

            match response.response {
                Ok(_) => {
                    let update_mandate = db
                        .update_mandate_by_merchant_id_mandate_id(
                            merchant_context.get_merchant_account().get_id(),
                            &req.mandate_id,
                            storage::MandateUpdate::StatusUpdate {
                                mandate_status: storage::enums::MandateStatus::Revoked,
                            },
                            mandate,
                            merchant_context.get_merchant_account().storage_scheme,
                        )
                        .await
                        .to_not_found_response(errors::ApiErrorResponse::MandateNotFound)?;
                    Ok(services::ApplicationResponse::Json(
                        mandates::MandateRevokedResponse {
                            mandate_id: update_mandate.mandate_id,
                            status: update_mandate.mandate_status,
                            error_code: None,
                            error_message: None,
                        },
                    ))
                }

                Err(err) => Err(errors::ApiErrorResponse::ExternalConnectorError {
                    code: err.code,
                    message: err.message,
                    connector: mandate.connector,
                    status_code: err.status_code,
                    reason: err.reason,
                }
                .into()),
            }
        }
        common_enums::MandateStatus::Revoked => {
            Err(errors::ApiErrorResponse::MandateValidationFailed {
                reason: "Mandate has already been revoked".to_string(),
            }
            .into())
        }
    }
}

#[instrument(skip(db))]
pub async fn update_connector_mandate_id(
    db: &dyn StorageInterface,
    merchant_id: &id_type::MerchantId,
    mandate_ids_opt: Option<String>,
    payment_method_id: Option<String>,
    resp: Result<types::PaymentsResponseData, types::ErrorResponse>,
    storage_scheme: MerchantStorageScheme,
) -> RouterResponse<mandates::MandateResponse> {
    let mandate_details = Option::foreign_from(resp);
    let connector_mandate_id = mandate_details
        .clone()
        .map(|md| {
            md.encode_to_value()
                .change_context(errors::ApiErrorResponse::InternalServerError)
                .map(masking::Secret::new)
        })
        .transpose()?;

    //Ignore updation if the payment_attempt mandate_id or connector_mandate_id is not present
    if let Some((mandate_id, connector_id)) = mandate_ids_opt.zip(connector_mandate_id) {
        let mandate = db
            .find_mandate_by_merchant_id_mandate_id(merchant_id, &mandate_id, storage_scheme)
            .await
            .change_context(errors::ApiErrorResponse::MandateNotFound)?;

        let update_mandate_details = match payment_method_id {
            Some(pmd_id) => storage::MandateUpdate::ConnectorMandateIdUpdate {
                connector_mandate_id: mandate_details
                    .and_then(|mandate_reference| mandate_reference.connector_mandate_id),
                connector_mandate_ids: Some(connector_id),
                payment_method_id: pmd_id,
                original_payment_id: None,
            },
            None => storage::MandateUpdate::ConnectorReferenceUpdate {
                connector_mandate_ids: Some(connector_id),
            },
        };

        // only update the connector_mandate_id if existing is none
        if mandate.connector_mandate_id.is_none() {
            db.update_mandate_by_merchant_id_mandate_id(
                merchant_id,
                &mandate_id,
                update_mandate_details,
                mandate,
                storage_scheme,
            )
            .await
            .change_context(errors::ApiErrorResponse::MandateUpdateFailed)?;
        }
    }
    Ok(services::ApplicationResponse::StatusOk)
}
#[cfg(feature = "v1")]
#[instrument(skip(state))]
pub async fn get_customer_mandates(
    state: SessionState,
    merchant_context: domain::MerchantContext,
    customer_id: id_type::CustomerId,
) -> RouterResponse<Vec<mandates::MandateResponse>> {
    let mandates = state
        .store
        .find_mandate_by_merchant_id_customer_id(
            merchant_context.get_merchant_account().get_id(),
            &customer_id,
        )
        .await
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable_lazy(|| {
            format!(
                "Failed while finding mandate: merchant_id: {:?}, customer_id: {:?}",
                merchant_context.get_merchant_account().get_id(),
                customer_id,
            )
        })?;

    if mandates.is_empty() {
        Err(report!(errors::ApiErrorResponse::MandateNotFound).attach_printable("No Mandate found"))
    } else {
        let mut response_vec = Vec::with_capacity(mandates.len());
        for mandate in mandates {
            response_vec.push(
                mandates::MandateResponse::from_db_mandate(
                    &state,
                    merchant_context.get_merchant_key_store().clone(),
                    mandate,
                    merchant_context.get_merchant_account(),
                )
                .await?,
            );
        }
        Ok(services::ApplicationResponse::Json(response_vec))
    }
}

fn get_insensitive_payment_method_data_if_exists<F, FData>(
    router_data: &types::RouterData<F, FData, types::PaymentsResponseData>,
) -> Option<domain::PaymentMethodData>
where
    FData: MandateBehaviour,
{
    match &router_data.request.get_payment_method_data() {
        domain::PaymentMethodData::Card(_) => None,
        _ => Some(router_data.request.get_payment_method_data()),
    }
}

pub async fn mandate_procedure<F, FData>(
    state: &SessionState,
    resp: &types::RouterData<F, FData, types::PaymentsResponseData>,
    customer_id: &Option<id_type::CustomerId>,
    pm_id: Option<String>,
    merchant_connector_id: Option<id_type::MerchantConnectorAccountId>,
    storage_scheme: MerchantStorageScheme,
    payment_id: &id_type::PaymentId,
) -> errors::RouterResult<Option<String>>
where
    FData: MandateBehaviour,
{
    let Ok(ref response) = resp.response else {
        return Ok(None);
    };

    match resp.request.get_mandate_id() {
        Some(mandate_id) => {
            let Some(ref mandate_id) = mandate_id.mandate_id else {
                return Ok(None);
            };
            let orig_mandate = state
                .store
                .find_mandate_by_merchant_id_mandate_id(
                    &resp.merchant_id,
                    mandate_id,
                    storage_scheme,
                )
                .await
                .to_not_found_response(errors::ApiErrorResponse::MandateNotFound)?;
            let mandate = match orig_mandate.mandate_type {
                storage_enums::MandateType::SingleUse => state
                    .store
                    .update_mandate_by_merchant_id_mandate_id(
                        &resp.merchant_id,
                        mandate_id,
                        storage::MandateUpdate::StatusUpdate {
                            mandate_status: storage_enums::MandateStatus::Revoked,
                        },
                        orig_mandate,
                        storage_scheme,
                    )
                    .await
                    .change_context(errors::ApiErrorResponse::MandateUpdateFailed),
                storage_enums::MandateType::MultiUse => state
                    .store
                    .update_mandate_by_merchant_id_mandate_id(
                        &resp.merchant_id,
                        mandate_id,
                        storage::MandateUpdate::CaptureAmountUpdate {
                            amount_captured: Some(
                                orig_mandate.amount_captured.unwrap_or(0)
                                    + resp.request.get_amount(),
                            ),
                        },
                        orig_mandate,
                        storage_scheme,
                    )
                    .await
                    .change_context(errors::ApiErrorResponse::MandateUpdateFailed),
            }?;
            metrics::SUBSEQUENT_MANDATE_PAYMENT.add(
                1,
                router_env::metric_attributes!(("connector", mandate.connector)),
            );
            Ok(Some(mandate_id.clone()))
        }
        None => {
            let Some(_mandate_details) = resp.request.get_setup_mandate_details() else {
                return Ok(None);
            };
            let (mandate_reference, network_txn_id) = match &response {
                types::PaymentsResponseData::TransactionResponse {
                    mandate_reference,
                    network_txn_id,
                    ..
                } => (mandate_reference.clone(), network_txn_id.clone()),
                _ => (Box::new(None), None),
            };

            let mandate_ids = (*mandate_reference)
                .as_ref()
                .map(|md| {
                    md.encode_to_value()
                        .change_context(errors::ApiErrorResponse::MandateSerializationFailed)
                        .map(masking::Secret::new)
                })
                .transpose()?;

            let Some(new_mandate_data) = payment_helper::generate_mandate(
                resp.merchant_id.clone(),
                payment_id.to_owned(),
                resp.connector.clone(),
                resp.request.get_setup_mandate_details().cloned(),
                customer_id,
                pm_id.get_required_value("payment_method_id")?,
                mandate_ids,
                network_txn_id,
                get_insensitive_payment_method_data_if_exists(resp),
                *mandate_reference,
                merchant_connector_id,
            )?
            else {
                return Ok(None);
            };

            let connector = new_mandate_data.connector.clone();
            logger::debug!("{:?}", new_mandate_data);

            let res_mandate_id = new_mandate_data.mandate_id.clone();

            state
                .store
                .insert_mandate(new_mandate_data, storage_scheme)
                .await
                .to_duplicate_response(errors::ApiErrorResponse::DuplicateMandate)?;
            metrics::MANDATE_COUNT.add(1, router_env::metric_attributes!(("connector", connector)));
            Ok(Some(res_mandate_id))
        }
    }
}

#[instrument(skip(state))]
pub async fn retrieve_mandates_list(
    state: SessionState,
    merchant_context: domain::MerchantContext,
    constraints: api_models::mandates::MandateListConstraints,
) -> RouterResponse<Vec<api_models::mandates::MandateResponse>> {
    let mandates = state
        .store
        .as_ref()
        .find_mandates_by_merchant_id(
            merchant_context.get_merchant_account().get_id(),
            constraints,
        )
        .await
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Unable to retrieve mandates")?;
    let mandates_list = future::try_join_all(mandates.into_iter().map(|mandate| {
        mandates::MandateResponse::from_db_mandate(
            &state,
            merchant_context.get_merchant_key_store().clone(),
            mandate,
            merchant_context.get_merchant_account(),
        )
    }))
    .await?;
    Ok(services::ApplicationResponse::Json(mandates_list))
}

impl ForeignFrom<Result<types::PaymentsResponseData, types::ErrorResponse>>
    for Option<types::MandateReference>
{
    fn foreign_from(resp: Result<types::PaymentsResponseData, types::ErrorResponse>) -> Self {
        match resp {
            Ok(types::PaymentsResponseData::TransactionResponse {
                mandate_reference, ..
            }) => *mandate_reference,
            _ => None,
        }
    }
}

pub trait MandateBehaviour {
    fn get_amount(&self) -> i64;
    fn get_setup_future_usage(&self) -> Option<diesel_models::enums::FutureUsage>;
    fn get_mandate_id(&self) -> Option<&payments::MandateIds>;
    fn set_mandate_id(&mut self, new_mandate_id: Option<payments::MandateIds>);
    fn get_payment_method_data(&self) -> domain::payments::PaymentMethodData;
    fn get_setup_mandate_details(
        &self,
    ) -> Option<&hyperswitch_domain_models::mandates::MandateData>;
    fn get_customer_acceptance(&self) -> Option<common_payments_types::CustomerAcceptance>;
}


// Function: payouts_cancel
// File: crates/router/src/routes/payouts.rs
// Module: router

pub fn payouts_cancel(
    state: web::Data<AppState>,
    req: HttpRequest,
    path: web::Path<id_type::PayoutId>,
) -> HttpResponse


// Struct: GenericTokenizationResponse
// File: crates/api_models/src/tokenization.rs
// Module: api_models
// Implementations: 0

pub struct GenericTokenizationResponse


// Struct: EmailToken
// File: crates/router/src/services/email/types.rs
// Module: router
// Implementations: 1

pub struct EmailToken


// Implementation: impl api::PaymentVoid for for Itaubank
// File: crates/hyperswitch_connectors/src/connectors/itaubank.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::PaymentVoid for for Itaubank


// Struct: AuthorizedotnetNonZeroMandateResponse
// File: crates/hyperswitch_connectors/src/connectors/authorizedotnet/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct AuthorizedotnetNonZeroMandateResponse


// Struct: SubscriptionLineItem
// File: crates/hyperswitch_domain_models/src/router_response_types/subscriptions.rs
// Module: hyperswitch_domain_models
// Implementations: 0

pub struct SubscriptionLineItem


// Function: build_query
// File: crates/analytics/src/query.rs
// Module: analytics

pub fn build_query(&mut self) -> QueryResult<String>
    where
        Aggregate<&'static str>: ToSql<T>,
        Window<&'static str>: ToSql<T>,


// Function: get_amount_captured
// File: crates/hyperswitch_connectors/src/connectors/nuvei/transformers.rs
// Module: hyperswitch_connectors

pub fn get_amount_captured(
    partial_approval_data: Option<NuveiPartialApproval>,
    transaction_type: Option<NuveiTransactionType>,
) -> Result<(Option<i64>, Option<MinorUnit>), error_stack::Report<errors::ConnectorError>>


// Function: generate_signature
// File: crates/hyperswitch_connectors/src/connectors/barclaycard.rs
// Module: hyperswitch_connectors

pub fn generate_signature(
        &self,
        auth: barclaycard::BarclaycardAuthType,
        host: String,
        resource: &str,
        payload: &String,
        date: OffsetDateTime,
        http_method: Method,
    ) -> CustomResult<String, errors::ConnectorError>


// Struct: RelayRetrieveBody
// File: crates/api_models/src/relay.rs
// Module: api_models
// Implementations: 1
// Traits: common_utils::events::ApiEventMetric

pub struct RelayRetrieveBody


// Struct: PaymentsVoidRequest
// File: crates/hyperswitch_connectors/src/connectors/elavon/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct PaymentsVoidRequest


// Function: payments_update_metadata
// File: crates/router/src/routes/payments.rs
// Module: router

pub fn payments_update_metadata(
    state: web::Data<app::AppState>,
    req: actix_web::HttpRequest,
    json_payload: web::Json<payment_types::PaymentsUpdateMetadataRequest>,
    path: web::Path<common_utils::id_type::PaymentId>,
) -> impl Responder


// Struct: BankOfAmericaErrorInformation
// File: crates/hyperswitch_connectors/src/connectors/bankofamerica/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct BankOfAmericaErrorInformation


// Struct: EliminationAnalyserConfig
// File: crates/api_models/src/routing.rs
// Module: api_models
// Implementations: 1

pub struct EliminationAnalyserConfig


// Struct: CustomerUpdateRequestInternal
// File: crates/api_models/src/customers.rs
// Module: api_models
// Implementations: 0

pub struct CustomerUpdateRequestInternal


// Struct: LineItem
// File: crates/hyperswitch_connectors/src/connectors/taxjar/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct LineItem


// File: crates/router/src/services/kafka/authentication.rs
// Module: router
// Public functions: 1
// Public structs: 1

use diesel_models::{authentication::Authentication, enums as storage_enums};
use time::OffsetDateTime;

#[derive(serde::Serialize, Debug)]
pub struct KafkaAuthentication<'a> {
    pub authentication_id: &'a common_utils::id_type::AuthenticationId,
    pub merchant_id: &'a common_utils::id_type::MerchantId,
    pub authentication_connector: Option<&'a String>,
    pub connector_authentication_id: Option<&'a String>,
    pub authentication_data: Option<serde_json::Value>,
    pub payment_method_id: &'a String,
    pub authentication_type: Option<storage_enums::DecoupledAuthenticationType>,
    pub authentication_status: storage_enums::AuthenticationStatus,
    pub authentication_lifecycle_status: storage_enums::AuthenticationLifecycleStatus,
    #[serde(default, with = "time::serde::timestamp::milliseconds")]
    pub created_at: OffsetDateTime,
    #[serde(default, with = "time::serde::timestamp::milliseconds")]
    pub modified_at: OffsetDateTime,
    pub error_message: Option<&'a String>,
    pub error_code: Option<&'a String>,
    pub connector_metadata: Option<serde_json::Value>,
    pub maximum_supported_version: Option<common_utils::types::SemanticVersion>,
    pub threeds_server_transaction_id: Option<&'a String>,
    pub cavv: Option<&'a String>,
    pub authentication_flow_type: Option<&'a String>,
    pub message_version: Option<common_utils::types::SemanticVersion>,
    pub eci: Option<&'a String>,
    pub trans_status: Option<storage_enums::TransactionStatus>,
    pub acquirer_bin: Option<&'a String>,
    pub acquirer_merchant_id: Option<&'a String>,
    pub three_ds_method_data: Option<&'a String>,
    pub three_ds_method_url: Option<&'a String>,
    pub acs_url: Option<&'a String>,
    pub challenge_request: Option<&'a String>,
    pub acs_reference_number: Option<&'a String>,
    pub acs_trans_id: Option<&'a String>,
    pub acs_signed_content: Option<&'a String>,
    pub profile_id: &'a common_utils::id_type::ProfileId,
    pub payment_id: Option<&'a common_utils::id_type::PaymentId>,
    pub merchant_connector_id: Option<&'a common_utils::id_type::MerchantConnectorAccountId>,
    pub ds_trans_id: Option<&'a String>,
    pub directory_server_id: Option<&'a String>,
    pub acquirer_country_code: Option<&'a String>,
    pub organization_id: &'a common_utils::id_type::OrganizationId,
}

impl<'a> KafkaAuthentication<'a> {
    pub fn from_storage(authentication: &'a Authentication) -> Self {
        Self {
            created_at: authentication.created_at.assume_utc(),
            modified_at: authentication.modified_at.assume_utc(),
            authentication_id: &authentication.authentication_id,
            merchant_id: &authentication.merchant_id,
            authentication_status: authentication.authentication_status,
            authentication_connector: authentication.authentication_connector.as_ref(),
            connector_authentication_id: authentication.connector_authentication_id.as_ref(),
            authentication_data: authentication.authentication_data.clone(),
            payment_method_id: &authentication.payment_method_id,
            authentication_type: authentication.authentication_type,
            authentication_lifecycle_status: authentication.authentication_lifecycle_status,
            error_code: authentication.error_code.as_ref(),
            error_message: authentication.error_message.as_ref(),
            connector_metadata: authentication.connector_metadata.clone(),
            maximum_supported_version: authentication.maximum_supported_version.clone(),
            threeds_server_transaction_id: authentication.threeds_server_transaction_id.as_ref(),
            cavv: authentication.cavv.as_ref(),
            authentication_flow_type: authentication.authentication_flow_type.as_ref(),
            message_version: authentication.message_version.clone(),
            eci: authentication.eci.as_ref(),
            trans_status: authentication.trans_status.clone(),
            acquirer_bin: authentication.acquirer_bin.as_ref(),
            acquirer_merchant_id: authentication.acquirer_merchant_id.as_ref(),
            three_ds_method_data: authentication.three_ds_method_data.as_ref(),
            three_ds_method_url: authentication.three_ds_method_url.as_ref(),
            acs_url: authentication.acs_url.as_ref(),
            challenge_request: authentication.challenge_request.as_ref(),
            acs_reference_number: authentication.acs_reference_number.as_ref(),
            acs_trans_id: authentication.acs_trans_id.as_ref(),
            acs_signed_content: authentication.acs_signed_content.as_ref(),
            profile_id: &authentication.profile_id,
            payment_id: authentication.payment_id.as_ref(),
            merchant_connector_id: authentication.merchant_connector_id.as_ref(),
            ds_trans_id: authentication.ds_trans_id.as_ref(),
            directory_server_id: authentication.directory_server_id.as_ref(),
            acquirer_country_code: authentication.acquirer_country_code.as_ref(),
            organization_id: &authentication.organization_id,
        }
    }
}

impl super::KafkaMessage for KafkaAuthentication<'_> {
    fn key(&self) -> String {
        format!(
            "{}_{}",
            self.merchant_id.get_string_repr(),
            self.authentication_id.get_string_repr()
        )
    }

    fn event_type(&self) -> crate::events::EventType {
        crate::events::EventType::Authentication
    }
}


// Module Structure
// File: crates/external_services/src/lib.rs
// Module: external_services

// Public submodules:
pub mod email;
pub mod aws_kms;
pub mod file_storage;
pub mod hashicorp_vault;
pub mod no_encryption;
pub mod grpc_client;
pub mod http_client;
pub mod hubspot_proxy;
pub mod managers;
pub mod crm;
pub mod utils;


// Struct: MandateBodyResponse
// File: crates/hyperswitch_connectors/src/connectors/bamboraapac/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct MandateBodyResponse


// Function: get_metrics
// File: crates/analytics/src/active_payments/core.rs
// Module: analytics

pub fn get_metrics(
    pool: &AnalyticsProvider,
    publishable_key: &String,
    merchant_id: &common_utils::id_type::MerchantId,
    req: GetActivePaymentsMetricRequest,
) -> AnalyticsResult<MetricsResponse<MetricsBucketResponse>>


// Function: payments_to_payments_response
// File: crates/router/src/core/payments/transformers.rs
// Module: router

pub fn payments_to_payments_response<Op, F: Clone, D>(
    payment_data: D,
    captures: Option<Vec<storage::Capture>>,
    customer: Option<domain::Customer>,
    _auth_flow: services::AuthFlow,
    base_url: &str,
    operation: &Op,
    connector_request_reference_id_config: &ConnectorRequestReferenceIdConfig,
    connector_http_status_code: Option<u16>,
    external_latency: Option<u128>,
    _is_latency_header_enabled: Option<bool>,
) -> RouterResponse<api::PaymentsResponse>
where
    Op: Debug,
    D: OperationSessionGetters<F>,


// Implementation: impl api::RefundExecute for for Sift
// File: crates/hyperswitch_connectors/src/connectors/sift.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::RefundExecute for for Sift


// Function: add_outer_select_column
// File: crates/analytics/src/query.rs
// Module: analytics

pub fn add_outer_select_column(&mut self, column: impl ToSql<T>) -> QueryResult<()>


// Function: get_total_count_of_payouts
// File: crates/diesel_models/src/query/payouts.rs
// Module: diesel_models

pub fn get_total_count_of_payouts(
        conn: &PgPooledConn,
        merchant_id: &common_utils::id_type::MerchantId,
        active_payout_ids: &[common_utils::id_type::PayoutId],
        connector: Option<Vec<String>>,
        currency: Option<Vec<enums::Currency>>,
        status: Option<Vec<enums::PayoutStatus>>,
        payout_type: Option<Vec<enums::PayoutType>>,
    ) -> StorageResult<i64>


// Implementation: impl AttemptAmountDetails
// File: crates/hyperswitch_domain_models/src/payments/payment_attempt.rs
// Module: hyperswitch_domain_models
// Methods: 9 total (9 public)

impl AttemptAmountDetails


// Struct: NuveiInitPaymentRequest
// File: crates/hyperswitch_connectors/src/connectors/nuvei/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct NuveiInitPaymentRequest


// Function: insert
// File: crates/diesel_models/src/query/organization.rs
// Module: diesel_models

pub fn insert(self, conn: &PgPooledConn) -> StorageResult<Organization>


// Function: get_error_reason
// File: crates/hyperswitch_connectors/src/connectors/barclaycard/transformers.rs
// Module: hyperswitch_connectors

pub fn get_error_reason(
    error_info: Option<String>,
    detailed_error_info: Option<String>,
    avs_error_info: Option<String>,
) -> Option<String>


// Implementation: impl Responder
// File: crates/router/src/routes/payments.rs
// Module: router
// Methods: 0 total (0 public)

impl Responder


// Struct: NuveiVoidRequest
// File: crates/hyperswitch_connectors/src/connectors/nuvei/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct NuveiVoidRequest


// Struct: MerchantAccountMetadata
// File: crates/api_models/src/admin.rs
// Module: api_models
// Implementations: 0

pub struct MerchantAccountMetadata


// Struct: MerchantAccount
// File: crates/router/src/routes/app.rs
// Module: router
// Implementations: 2

pub struct MerchantAccount


// Struct: AttributeResponse
// File: crates/hyperswitch_connectors/src/connectors/paypal/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct AttributeResponse


// Struct: Void
// File: crates/hyperswitch_connectors/src/connectors/worldpayvantiv/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct Void


// Function: files_retrieve
// File: crates/router/src/routes/files.rs
// Module: router

pub fn files_retrieve(
    state: web::Data<AppState>,
    req: HttpRequest,
    path: web::Path<String>,
    json_payload: web::Query<file_types::FileRetrieveQuery>,
) -> HttpResponse


// Function: do_list_customer_pm_fetch_customer_if_not_passed
// File: crates/router/src/core/payment_methods/cards.rs
// Module: router

pub fn do_list_customer_pm_fetch_customer_if_not_passed(
    state: routes::SessionState,
    merchant_context: domain::MerchantContext,
    req: Option<api::PaymentMethodListRequest>,
    customer_id: Option<&id_type::CustomerId>,
    ephemeral_api_key: Option<&str>,
) -> errors::RouterResponse<api::CustomerPaymentMethodsListResponse>


// Struct: AmazonpayRouterData
// File: crates/hyperswitch_connectors/src/connectors/amazonpay/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct AmazonpayRouterData<T>


// File: crates/test_utils/tests/connectors/aci_ui.rs
// Module: test_utils

use serial_test::serial;
use thirtyfour::{prelude::*, WebDriver};

use crate::{selenium::*, tester};

struct AciSeleniumTest;

impl SeleniumTest for AciSeleniumTest {
    fn get_connector_name(&self) -> String {
        "aci".to_string()
    }
}

async fn should_make_aci_card_mandate_payment(web_driver: WebDriver) -> Result<(), WebDriverError> {
    let conn = AciSeleniumTest {};
    conn.make_redirection_payment(
        web_driver,
        vec![
            Event::Trigger(Trigger::Goto(&format!("{CHECKOUT_BASE_URL}/saved/180"))),
            Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))),
            Event::Assert(Assert::IsPresent("succeeded")),
            Event::Assert(Assert::IsPresent("Mandate ID")),
            Event::Assert(Assert::IsPresent("man_")), // mandate id starting with man_
            Event::Trigger(Trigger::Click(By::Css("a.btn"))),
            Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))),
            Event::Assert(Assert::IsPresent("succeeded")),
        ],
    )
    .await?;
    Ok(())
}

async fn should_make_aci_alipay_payment(web_driver: WebDriver) -> Result<(), WebDriverError> {
    let conn = AciSeleniumTest {};
    conn.make_redirection_payment(
        web_driver,
        vec![
            Event::Trigger(Trigger::Goto(&format!("{CHECKOUT_BASE_URL}/saved/213"))),
            Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))),
            Event::Trigger(Trigger::Click(By::Id("submit-success"))),
            Event::Assert(Assert::IsPresent("succeeded")),
        ],
    )
    .await?;
    Ok(())
}

async fn should_make_aci_interac_payment(web_driver: WebDriver) -> Result<(), WebDriverError> {
    let conn = AciSeleniumTest {};
    conn.make_redirection_payment(
        web_driver,
        vec![
            Event::Trigger(Trigger::Goto(&format!("{CHECKOUT_BASE_URL}/saved/14"))),
            Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))),
            Event::Trigger(Trigger::Click(By::Css("input[value='Continue payment']"))),
            Event::Trigger(Trigger::Click(By::Css("input[value='Confirm']"))),
            Event::Assert(Assert::IsPresent("succeeded")),
        ],
    )
    .await?;
    Ok(())
}

async fn should_make_aci_eps_payment(web_driver: WebDriver) -> Result<(), WebDriverError> {
    let conn = AciSeleniumTest {};
    conn.make_redirection_payment(
        web_driver,
        vec![
            Event::Trigger(Trigger::Goto(&format!("{CHECKOUT_BASE_URL}/saved/208"))),
            Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))),
            Event::Trigger(Trigger::Click(By::Css("input.button-body.button-short"))),
            Event::Trigger(Trigger::Click(By::Css("input.button-body.button-short"))),
            Event::Trigger(Trigger::Click(By::Css("input.button-body.button-short"))),
            Event::Trigger(Trigger::Click(By::Css("input.button-body.button-middle"))),
            Event::Assert(Assert::IsPresent("succeeded")),
        ],
    )
    .await?;
    Ok(())
}

async fn should_make_aci_ideal_payment(web_driver: WebDriver) -> Result<(), WebDriverError> {
    let conn = AciSeleniumTest {};
    conn.make_redirection_payment(
        web_driver,
        vec![
            Event::Trigger(Trigger::Goto(&format!("{CHECKOUT_BASE_URL}/saved/211"))),
            Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))),
            Event::Trigger(Trigger::Click(By::Css("input.pps-button"))),
            Event::Assert(Assert::IsPresent("succeeded")),
        ],
    )
    .await?;
    Ok(())
}

async fn should_make_aci_sofort_payment(web_driver: WebDriver) -> Result<(), WebDriverError> {
    let conn = AciSeleniumTest {};
    conn.make_redirection_payment(
        web_driver,
        vec![
            Event::Trigger(Trigger::Goto(&format!("{CHECKOUT_BASE_URL}/saved/212"))),
            Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))),
            Event::Trigger(Trigger::Click(By::Css(
                "button.large.button.primary.expand.form-submitter",
            ))),
            Event::Trigger(Trigger::Click(By::Css(
                "button.large.button.primary.expand.form-submitter",
            ))),
            Event::Trigger(Trigger::Click(By::Css(
                "button.large.button.primary.expand.form-submitter",
            ))),
            Event::Trigger(Trigger::Click(By::Css(
                "button.large.button.primary.expand.form-submitter",
            ))),
            Event::Assert(Assert::IsPresent("succeeded")),
        ],
    )
    .await?;
    Ok(())
}

async fn should_make_aci_giropay_payment(web_driver: WebDriver) -> Result<(), WebDriverError> {
    let conn = AciSeleniumTest {};
    conn.make_redirection_payment(
        web_driver,
        vec![
            Event::Trigger(Trigger::Goto(&format!("{CHECKOUT_BASE_URL}/saved/209"))),
            Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))),
            Event::Trigger(Trigger::SendKeys(By::Name("sc"), "10")),
            Event::Trigger(Trigger::SendKeys(By::Name("extensionSc"), "4000")),
            Event::Trigger(Trigger::SendKeys(By::Name("customerName1"), "Hopper")),
            Event::Trigger(Trigger::Click(By::Css("input[value='Absenden']"))),
            Event::Assert(Assert::IsPresent("succeeded")),
        ],
    )
    .await?;
    Ok(())
}

async fn should_make_aci_trustly_payment(web_driver: WebDriver) -> Result<(), WebDriverError> {
    let conn = AciSeleniumTest {};
    conn.make_redirection_payment(
        web_driver,
        vec![
            Event::Trigger(Trigger::Goto(&format!("{CHECKOUT_BASE_URL}/saved/13"))),
            Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))),
            Event::Trigger(Trigger::Sleep(2)),
            Event::Trigger(Trigger::Click(By::XPath(
                r#"//*[@id="app"]/div[1]/div/div[2]/div/ul/div[4]/div/div[1]/div[2]/div[1]/span"#,
            ))),
            Event::Trigger(Trigger::Click(By::Css(
                "button.sc-eJocfa.sc-oeezt.cDgdS.bptgBT",
            ))),
            Event::Trigger(Trigger::SendKeys(
                By::Css("input.sc-fXgAZx.hkChHq"),
                "123456789",
            )),
            Event::Trigger(Trigger::Click(By::Css(
                "button.sc-eJocfa.sc-oeezt.cDgdS.bptgBT",
            ))),
            Event::Trigger(Trigger::SendKeys(
                By::Css("input.sc-fXgAZx.hkChHq"),
                "783213",
            )),
            Event::Trigger(Trigger::Click(By::Css(
                "button.sc-eJocfa.sc-oeezt.cDgdS.bptgBT",
            ))),
            Event::Trigger(Trigger::Click(By::Css("div.sc-jJMGnK.laKGqb"))),
            Event::Trigger(Trigger::Click(By::Css(
                "button.sc-eJocfa.sc-oeezt.cDgdS.bptgBT",
            ))),
            Event::Trigger(Trigger::SendKeys(
                By::Css("input.sc-fXgAZx.hkChHq"),
                "355508",
            )),
            Event::Trigger(Trigger::Click(By::Css(
                "button.sc-eJocfa.sc-oeezt.cDgdS.bptgBT",
            ))),
            Event::Assert(Assert::IsPresent("succeeded")),
        ],
    )
    .await?;
    Ok(())
}

async fn should_make_aci_przelewy24_payment(web_driver: WebDriver) -> Result<(), WebDriverError> {
    let conn = AciSeleniumTest {};
    conn.make_redirection_payment(
        web_driver,
        vec![
            Event::Trigger(Trigger::Goto(&format!("{CHECKOUT_BASE_URL}/saved/12"))),
            Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))),
            Event::Trigger(Trigger::Click(By::Id("pf31"))),
            Event::Trigger(Trigger::Click(By::Css(
                "button.btn.btn-lg.btn-info.btn-block",
            ))),
            Event::Trigger(Trigger::Click(By::Css(
                "button.btn.btn-success.btn-lg.accept-button",
            ))),
            Event::Assert(Assert::IsPresent("succeeded")),
        ],
    )
    .await?;
    Ok(())
}

#[test]
#[serial]
fn should_make_aci_card_mandate_payment_test() {
    tester!(should_make_aci_card_mandate_payment);
}

#[test]
#[serial]
fn should_make_aci_alipay_payment_test() {
    tester!(should_make_aci_alipay_payment);
}

#[test]
#[serial]
fn should_make_aci_interac_payment_test() {
    tester!(should_make_aci_interac_payment);
}

#[test]
#[serial]
fn should_make_aci_eps_payment_test() {
    tester!(should_make_aci_eps_payment);
}

#[test]
#[serial]
fn should_make_aci_ideal_payment_test() {
    tester!(should_make_aci_ideal_payment);
}

#[test]
#[serial]
fn should_make_aci_sofort_payment_test() {
    tester!(should_make_aci_sofort_payment);
}

#[test]
#[serial]
fn should_make_aci_giropay_payment_test() {
    tester!(should_make_aci_giropay_payment);
}

#[test]
#[serial]
fn should_make_aci_trustly_payment_test() {
    tester!(should_make_aci_trustly_payment);
}

#[test]
#[serial]
fn should_make_aci_przelewy24_payment_test() {
    tester!(should_make_aci_przelewy24_payment);
}


// Function: relay_retrieve
// File: crates/router/src/core/relay.rs
// Module: router

pub fn relay_retrieve(
    state: SessionState,
    merchant_context: domain::MerchantContext,
    profile_id_optional: Option<id_type::ProfileId>,
    req: relay_api_models::RelayRetrieveRequest,
) -> RouterResponse<relay_api_models::RelayResponse>


// Implementation: impl api::PaymentCapture for for Santander
// File: crates/hyperswitch_connectors/src/connectors/santander.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::PaymentCapture for for Santander