File: crates/hyperswitch_connectors/src/connectors/inespay.rs
 Public functions: 1
 Public structs: 1

pub mod transformers;

use std::sync::LazyLock;

use base64::Engine;
use common_enums::enums;
use common_utils::{
    consts::BASE64_ENGINE,
    crypto,
    errors::CustomResult,
    ext_traits::{ByteSliceExt, BytesExt},
    request::{Method, Request, RequestBuilder, RequestContent},
    types::{AmountConvertor, StringMinorUnit, StringMinorUnitForConnector},
};
use error_stack::ResultExt;
use hyperswitch_domain_models::{
    router_data::{AccessToken, ConnectorAuthType, ErrorResponse, RouterData},
    router_flow_types::{
        access_token_auth::AccessTokenAuth,
        payments::{Authorize, Capture, PSync, PaymentMethodToken, Session, SetupMandate, Void},
        refunds::{Execute, RSync},
    },
    router_request_types::{
        AccessTokenRequestData, PaymentMethodTokenizationData, PaymentsAuthorizeData,
        PaymentsCancelData, PaymentsCaptureData, PaymentsSessionData, PaymentsSyncData,
        RefundsData, SetupMandateRequestData,
    },
    router_response_types::{
        ConnectorInfo, PaymentMethodDetails, PaymentsResponseData, RefundsResponseData,
        SupportedPaymentMethods, SupportedPaymentMethodsExt,
    },
    types::{
        PaymentsAuthorizeRouterData, PaymentsCaptureRouterData, PaymentsSyncRouterData,
        RefundSyncRouterData, RefundsRouterData,
    },
};
use hyperswitch_interfaces::{
    api::{
        self, ConnectorCommon, ConnectorCommonExt, ConnectorIntegration, ConnectorSpecifications,
        ConnectorValidation,
    },
    configs::Connectors,
    errors,
    events::connector_api_logs::ConnectorEvent,
    types::{self, Response},
    webhooks,
};
use masking::{ExposeInterface, Mask, Secret};
use ring::hmac;
use transformers as inespay;

use crate::{constants::headers, types::ResponseRouterData, utils};

#[derive(Clone)]
pub struct Inespay {
    amount_converter: &'static (dyn AmountConvertor<Output = StringMinorUnit> + Sync),
}

impl Inespay {
    pub fn new() -> &'static Self {
        &Self {
            amount_converter: &StringMinorUnitForConnector,
        }
    }
}

impl api::Payment for Inespay {}
impl api::PaymentSession for Inespay {}
impl api::ConnectorAccessToken for Inespay {}
impl api::MandateSetup for Inespay {}
impl api::PaymentAuthorize for Inespay {}
impl api::PaymentSync for Inespay {}
impl api::PaymentCapture for Inespay {}
impl api::PaymentVoid for Inespay {}
impl api::Refund for Inespay {}
impl api::RefundExecute for Inespay {}
impl api::RefundSync for Inespay {}
impl api::PaymentToken for Inespay {}

impl ConnectorIntegration<PaymentMethodToken, PaymentMethodTokenizationData, PaymentsResponseData>
    for Inespay
{
    // Not Implemented (R)
}

impl<Flow, Request, Response> ConnectorCommonExt<Flow, Request, Response> for Inespay
where
    Self: ConnectorIntegration<Flow, Request, Response>,
{
    fn build_headers(
        &self,
        req: &RouterData<Flow, Request, Response>,
        _connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        let mut header = vec![(
            headers::CONTENT_TYPE.to_string(),
            self.get_content_type().to_string().into(),
        )];
        let mut auth_headers = self.get_auth_header(&req.connector_auth_type)?;
        header.append(&mut auth_headers);
        Ok(header)
    }
}

impl ConnectorCommon for Inespay {
    fn id(&self) -> &'static str {
        "inespay"
    }

    fn get_currency_unit(&self) -> api::CurrencyUnit {
        api::CurrencyUnit::Minor
    }

    fn common_get_content_type(&self) -> &'static str {
        "application/json"
    }

    fn base_url<'a>(&self, connectors: &'a Connectors) -> &'a str {
        connectors.inespay.base_url.as_ref()
    }

    fn get_auth_header(
        &self,
        auth_type: &ConnectorAuthType,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        let auth = inespay::InespayAuthType::try_from(auth_type)
            .change_context(errors::ConnectorError::FailedToObtainAuthType)?;
        Ok(vec![
            (
                headers::AUTHORIZATION.to_string(),
                auth.authorization.expose().into_masked(),
            ),
            (
                headers::X_API_KEY.to_string(),
                auth.api_key.expose().into_masked(),
            ),
        ])
    }

    fn build_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        let response: inespay::InespayErrorResponse = res
            .response
            .parse_struct("InespayErrorResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;

        event_builder.map(|i| i.set_response_body(&response));
        router_env::logger::info!(connector_response=?response);

        Ok(ErrorResponse {
            status_code: res.status_code,
            code: response.status,
            message: response.status_desc,
            reason: None,
            attempt_status: None,
            connector_transaction_id: None,
            network_advice_code: None,
            network_decline_code: None,
            network_error_message: None,
            connector_metadata: None,
        })
    }
}

impl ConnectorValidation for Inespay {
    //TODO: implement functions when support enabled
}

impl ConnectorIntegration<Session, PaymentsSessionData, PaymentsResponseData> for Inespay {
    //TODO: implement sessions flow
}

impl ConnectorIntegration<AccessTokenAuth, AccessTokenRequestData, AccessToken> for Inespay {}

impl ConnectorIntegration<SetupMandate, SetupMandateRequestData, PaymentsResponseData> for Inespay {}

impl ConnectorIntegration<Authorize, PaymentsAuthorizeData, PaymentsResponseData> for Inespay {
    fn get_headers(
        &self,
        req: &PaymentsAuthorizeRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        self.build_headers(req, connectors)
    }

    fn get_content_type(&self) -> &'static str {
        self.common_get_content_type()
    }

    fn get_url(
        &self,
        _req: &PaymentsAuthorizeRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        Ok(format!("{}/payins/single/init", self.base_url(connectors)))
    }

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

        match req.request.currency {
            common_enums::Currency::EUR => {
                let connector_router_data = inespay::InespayRouterData::from((amount, req));
                let connector_req =
                    inespay::InespayPaymentsRequest::try_from(&connector_router_data)?;
                Ok(RequestContent::Json(Box::new(connector_req)))
            }
            _ => Err(errors::ConnectorError::CurrencyNotSupported {
                message: req.request.currency.to_string(),
                connector: "Inespay",
            }
            .into()),
        }
    }

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

    fn handle_response(
        &self,
        data: &PaymentsAuthorizeRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PaymentsAuthorizeRouterData, errors::ConnectorError> {
        let response: inespay::InespayPaymentsResponse = res
            .response
            .parse_struct("Inespay PaymentsAuthorizeResponse")
            .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)
    }
}

impl ConnectorIntegration<PSync, PaymentsSyncData, PaymentsResponseData> for Inespay {
    fn get_headers(
        &self,
        req: &PaymentsSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        self.build_headers(req, connectors)
    }

    fn get_content_type(&self) -> &'static str {
        self.common_get_content_type()
    }

    fn get_url(
        &self,
        req: &PaymentsSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        let connector_payment_id = req
            .request
            .connector_transaction_id
            .get_connector_transaction_id()
            .change_context(errors::ConnectorError::MissingConnectorTransactionID)?;
        Ok(format!(
            "{}{}{}",
            self.base_url(connectors),
            "/payins/single/",
            connector_payment_id,
        ))
    }

    fn build_request(
        &self,
        req: &PaymentsSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        Ok(Some(
            RequestBuilder::new()
                .method(Method::Get)
                .url(&types::PaymentsSyncType::get_url(self, req, connectors)?)
                .attach_default_headers()
                .headers(types::PaymentsSyncType::get_headers(self, req, connectors)?)
                .build(),
        ))
    }

    fn handle_response(
        &self,
        data: &PaymentsSyncRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PaymentsSyncRouterData, errors::ConnectorError> {
        let response: inespay::InespayPSyncResponse = res
            .response
            .parse_struct("inespay PaymentsSyncResponse")
            .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)
    }
}

impl ConnectorIntegration<Capture, PaymentsCaptureData, PaymentsResponseData> for Inespay {
    fn get_headers(
        &self,
        req: &PaymentsCaptureRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        self.build_headers(req, connectors)
    }

    fn get_content_type(&self) -> &'static str {
        self.common_get_content_type()
    }

    fn get_url(
        &self,
        _req: &PaymentsCaptureRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into())
    }

    fn get_request_body(
        &self,
        _req: &PaymentsCaptureRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        Err(errors::ConnectorError::NotImplemented("get_request_body method".to_string()).into())
    }

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

    fn handle_response(
        &self,
        data: &PaymentsCaptureRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PaymentsCaptureRouterData, errors::ConnectorError> {
        let response: inespay::InespayPaymentsResponse = res
            .response
            .parse_struct("Inespay PaymentsCaptureResponse")
            .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)
    }
}

impl ConnectorIntegration<Void, PaymentsCancelData, PaymentsResponseData> for Inespay {}

impl ConnectorIntegration<Execute, RefundsData, RefundsResponseData> for Inespay {
    fn get_headers(
        &self,
        req: &RefundsRouterData<Execute>,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        self.build_headers(req, connectors)
    }

    fn get_content_type(&self) -> &'static str {
        self.common_get_content_type()
    }

    fn get_url(
        &self,
        _req: &RefundsRouterData<Execute>,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        Ok(format!("{}/refunds/init", self.base_url(connectors)))
    }

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

        let connector_router_data = inespay::InespayRouterData::from((refund_amount, req));
        let connector_req = inespay::InespayRefundRequest::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> {
        let request = RequestBuilder::new()
            .method(Method::Post)
            .url(&types::RefundExecuteType::get_url(self, req, connectors)?)
            .attach_default_headers()
            .headers(types::RefundExecuteType::get_headers(
                self, req, connectors,
            )?)
            .set_body(types::RefundExecuteType::get_request_body(
                self, req, connectors,
            )?)
            .build();
        Ok(Some(request))
    }

    fn handle_response(
        &self,
        data: &RefundsRouterData<Execute>,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<RefundsRouterData<Execute>, errors::ConnectorError> {
        let response: inespay::InespayRefundsResponse = res
            .response
            .parse_struct("inespay InespayRefundsResponse")
            .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)
    }
}

impl ConnectorIntegration<RSync, RefundsData, RefundsResponseData> for Inespay {
    fn get_headers(
        &self,
        req: &RefundSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        self.build_headers(req, connectors)
    }

    fn get_content_type(&self) -> &'static str {
        self.common_get_content_type()
    }

    fn get_url(
        &self,
        req: &RefundSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        let connector_refund_id = req
            .request
            .connector_refund_id
            .clone()
            .ok_or(errors::ConnectorError::MissingConnectorRefundID)?;
        Ok(format!(
            "{}{}{}",
            self.base_url(connectors),
            "/refunds/",
            connector_refund_id,
        ))
    }

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

    fn handle_response(
        &self,
        data: &RefundSyncRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<RefundSyncRouterData, errors::ConnectorError> {
        let response: inespay::InespayRSyncResponse = res
            .response
            .parse_struct("inespay RefundSyncResponse")
            .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_webhook_body(
    body: &[u8],
) -> CustomResult<inespay::InespayWebhookEventData, errors::ConnectorError> {
    let notif_item: inespay::InespayWebhookEvent =
        serde_urlencoded::from_bytes::<inespay::InespayWebhookEvent>(body)
            .change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?;
    let encoded_data_return = notif_item.data_return;
    let decoded_data_return = BASE64_ENGINE
        .decode(encoded_data_return)
        .change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?;
    let data_return: inespay::InespayWebhookEventData = decoded_data_return
        .parse_struct("inespay InespayWebhookEventData")
        .change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?;
    Ok(data_return)
}

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

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

        Ok(notif_item.signature_data_return.as_bytes().to_owned())
    }

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

        Ok(notif_item.data_return.into_bytes())
    }

    async fn verify_webhook_source(
        &self,
        request: &webhooks::IncomingWebhookRequestDetails<'_>,
        merchant_id: &common_utils::id_type::MerchantId,
        connector_webhook_details: Option<common_utils::pii::SecretSerdeValue>,
        _connector_account_details: 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?;
        let signature =
            self.get_webhook_source_verification_signature(request, &connector_webhook_secrets)?;

        let message = self.get_webhook_source_verification_message(
            request,
            merchant_id,
            &connector_webhook_secrets,
        )?;
        let secret = connector_webhook_secrets.secret;

        let signing_key = hmac::Key::new(hmac::HMAC_SHA256, &secret);
        let signed_message = hmac::sign(&signing_key, &message);
        let computed_signature = hex::encode(signed_message.as_ref());
        let payload_sign = BASE64_ENGINE.encode(computed_signature);
        Ok(payload_sign.as_bytes().eq(&signature))
    }

    fn get_webhook_object_reference_id(
        &self,
        request: &webhooks::IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<api_models::webhooks::ObjectReferenceId, errors::ConnectorError> {
        let data_return = get_webhook_body(request.body)
            .change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?;
        match data_return {
            inespay::InespayWebhookEventData::Payment(data) => {
                Ok(api_models::webhooks::ObjectReferenceId::PaymentId(
                    api_models::payments::PaymentIdType::ConnectorTransactionId(
                        data.single_payin_id,
                    ),
                ))
            }
            inespay::InespayWebhookEventData::Refund(data) => {
                Ok(api_models::webhooks::ObjectReferenceId::RefundId(
                    api_models::webhooks::RefundIdType::ConnectorRefundId(data.refund_id),
                ))
            }
        }
    }

    fn get_webhook_event_type(
        &self,
        request: &webhooks::IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<api_models::webhooks::IncomingWebhookEvent, errors::ConnectorError> {
        let data_return = get_webhook_body(request.body)
            .change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?;
        Ok(api_models::webhooks::IncomingWebhookEvent::from(
            data_return,
        ))
    }

    fn get_webhook_resource_object(
        &self,
        request: &webhooks::IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<Box<dyn masking::ErasedMaskSerialize>, errors::ConnectorError> {
        let data_return = get_webhook_body(request.body)
            .change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?;
        Ok(match data_return {
            inespay::InespayWebhookEventData::Payment(payment_webhook_data) => {
                Box::new(payment_webhook_data)
            }
            inespay::InespayWebhookEventData::Refund(refund_webhook_data) => {
                Box::new(refund_webhook_data)
            }
        })
    }
}

static INESPAY_SUPPORTED_PAYMENT_METHODS: LazyLock<SupportedPaymentMethods> = LazyLock::new(|| {
    let supported_capture_methods = vec![enums::CaptureMethod::Automatic];
    let mut inespay_supported_payment_methods = SupportedPaymentMethods::new();

    inespay_supported_payment_methods.add(
        enums::PaymentMethod::BankDebit,
        enums::PaymentMethodType::Sepa,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods.clone(),
            specific_features: None,
        },
    );

    inespay_supported_payment_methods
});

static INESPAY_CONNECTOR_INFO: ConnectorInfo = ConnectorInfo {
    display_name: "Inespay",
    description:
        "INESPAY is a payment method system that allows online shops to receive money in their bank accounts through a SEPA bank transfer ",
    connector_type: enums::HyperswitchConnectorCategory::BankAcquirer,
    integration_status: enums::ConnectorIntegrationStatus::Sandbox,
};

static INESPAY_SUPPORTED_WEBHOOK_FLOWS: [enums::EventClass; 2] =
    [enums::EventClass::Payments, enums::EventClass::Refunds];

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

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

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


pub async fn call_connector_service_prerequisites_for_external_vault_proxy<
    F,
    RouterDReq,
    ApiRequest,
    D,
>(
    state: &SessionState,
    req_state: ReqState,
    merchant_context: &domain::MerchantContext,
    connector: api::ConnectorData,
    operation: &BoxedOperation<'_, F, ApiRequest, D>,
    payment_data: &mut D,
    customer: &Option<domain::Customer>,
    call_connector_action: CallConnectorAction,
    schedule_time: Option<time::PrimitiveDateTime>,
    header_payload: HeaderPayload,
    frm_suggestion: Option<storage_enums::FrmSuggestion>,
    business_profile: &domain::Profile,
    is_retry_payment: bool,
    should_retry_with_pan: bool,
    all_keys_required: Option<bool>,
) -> RouterResult<(
    domain::MerchantConnectorAccountTypeDetails,
    domain::MerchantConnectorAccountTypeDetails,
    Option<storage::CustomerUpdate>,
    RouterData<F, RouterDReq, router_types::PaymentsResponseData>,
)>
where
    F: Send + Clone + Sync,
    RouterDReq: Send + Sync,

    // To create connector flow specific interface data
    D: OperationSessionGetters<F> + OperationSessionSetters<F> + Send + Sync + Clone,
    D: ConstructFlowSpecificData<F, RouterDReq, router_types::PaymentsResponseData>,
    RouterData<F, RouterDReq, router_types::PaymentsResponseData>: Feature<F, RouterDReq> + Send,
    // To construct connector flow specific api
    dyn api::Connector:
        services::api::ConnectorIntegration<F, RouterDReq, router_types::PaymentsResponseData>,
{
    // get merchant connector account related to external vault
    let external_vault_source: id_type::MerchantConnectorAccountId = business_profile
        .external_vault_connector_details
        .clone()
        .map(|connector_details| connector_details.vault_connector_id.clone())
        .ok_or(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("mca_id not present for external vault")?;

    let external_vault_merchant_connector_account_type_details =
        domain::MerchantConnectorAccountTypeDetails::MerchantConnectorAccount(Box::new(
            helpers::get_merchant_connector_account_v2(
                state,
                merchant_context.get_merchant_key_store(),
                Some(&external_vault_source),
            )
            .await?,
        ));

    let (merchant_connector_account_type_details, updated_customer, router_data) =
        call_connector_service_prerequisites(
            state,
            req_state,
            merchant_context,
            connector,
            operation,
            payment_data,
            customer,
            call_connector_action,
            schedule_time,
            header_payload,
            frm_suggestion,
            business_profile,
            is_retry_payment,
            should_retry_with_pan,
            all_keys_required,
        )
        .await?;
    Ok((
        merchant_connector_account_type_details,
        external_vault_merchant_connector_account_type_details,
        updated_customer,
        router_data,
    ))
}


Documentation: api-reference/_snippets/snippet-example.mdx
# Type: Doc File

## My Snippet

<Info>This is an example of a reusable snippet</Info>


impl ApplePayWalletData {
    pub fn get_payment_method_type(&self) -> Option<api_enums::PaymentMethodType> {
        self.payment_method
            .pm_type
            .clone()
            .parse_enum("ApplePayPaymentMethodType")
            .ok()
            .and_then(|payment_type| match payment_type {
                common_enums::ApplePayPaymentMethodType::Debit => {
                    Some(api_enums::PaymentMethodType::Debit)
                }
                common_enums::ApplePayPaymentMethodType::Credit => {
                    Some(api_enums::PaymentMethodType::Credit)
                }
                common_enums::ApplePayPaymentMethodType::Prepaid
                | common_enums::ApplePayPaymentMethodType::Store => None,
            })
    }
}


pub async fn update(
        self,
        conn: &PgPooledConn,
        merchant_account: MerchantAccountUpdateInternal,
    ) -> StorageResult<Self> {
        match generics::generic_update_by_id::<<Self as HasTable>::Table, _, _, _>(
            conn,
            self.get_id().to_owned(),
            merchant_account,
        )
        .await
        {
            Err(error) => match error.current_context() {
                errors::DatabaseError::NoFieldsToUpdate => Ok(self),
                _ => Err(error),
            },
            result => result,
        }
    }


pub struct BamboraRouterData<T> {
    pub amount: FloatMajorUnit,
    pub router_data: T,
}


File: crates/router/src/routes/dummy_connector.rs
 Public functions: 6

use actix_web::web;
use router_env::{instrument, tracing};

use super::app;
use crate::{
    core::api_locking,
    services::{api, authentication as auth},
};

mod consts;
mod core;
mod errors;
pub mod types;
mod utils;

#[cfg(all(feature = "dummy_connector", feature = "v1"))]
#[instrument(skip_all, fields(flow = ?types::Flow::DummyPaymentCreate))]
pub async fn dummy_connector_authorize_payment(
    state: web::Data<app::AppState>,
    req: actix_web::HttpRequest,
    path: web::Path<String>,
) -> impl actix_web::Responder {
    let flow = types::Flow::DummyPaymentAuthorize;
    let attempt_id = path.into_inner();
    let payload = types::DummyConnectorPaymentConfirmRequest { attempt_id };
    api::server_wrap(
        flow,
        state,
        &req,
        payload,
        |state, _: (), req, _| core::payment_authorize(state, req),
        &auth::NoAuth,
        api_locking::LockAction::NotApplicable,
    )
    .await
}

#[cfg(all(feature = "dummy_connector", feature = "v1"))]
#[instrument(skip_all, fields(flow = ?types::Flow::DummyPaymentCreate))]
pub async fn dummy_connector_complete_payment(
    state: web::Data<app::AppState>,
    req: actix_web::HttpRequest,
    path: web::Path<String>,
    json_payload: web::Query<types::DummyConnectorPaymentCompleteBody>,
) -> impl actix_web::Responder {
    let flow = types::Flow::DummyPaymentComplete;
    let attempt_id = path.into_inner();
    let payload = types::DummyConnectorPaymentCompleteRequest {
        attempt_id,
        confirm: json_payload.confirm,
    };
    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        payload,
        |state, _: (), req, _| core::payment_complete(state, req),
        &auth::NoAuth,
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

#[cfg(feature = "dummy_connector")]
#[instrument(skip_all, fields(flow = ?types::Flow::DummyPaymentCreate))]
pub async fn dummy_connector_payment(
    state: web::Data<app::AppState>,
    req: actix_web::HttpRequest,
    json_payload: web::Json<types::DummyConnectorPaymentRequest>,
) -> impl actix_web::Responder {
    let payload = json_payload.into_inner();
    let flow = types::Flow::DummyPaymentCreate;
    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        payload,
        |state, _: (), req, _| core::payment(state, req),
        &auth::NoAuth,
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

#[cfg(feature = "dummy_connector")]
#[instrument(skip_all, fields(flow = ?types::Flow::DummyPaymentRetrieve))]
pub async fn dummy_connector_payment_data(
    state: web::Data<app::AppState>,
    req: actix_web::HttpRequest,
    path: web::Path<String>,
) -> impl actix_web::Responder {
    let flow = types::Flow::DummyPaymentRetrieve;
    let payment_id = path.into_inner();
    let payload = types::DummyConnectorPaymentRetrieveRequest { payment_id };
    api::server_wrap(
        flow,
        state,
        &req,
        payload,
        |state, _: (), req, _| core::payment_data(state, req),
        &auth::NoAuth,
        api_locking::LockAction::NotApplicable,
    )
    .await
}

#[cfg(all(feature = "dummy_connector", feature = "v1"))]
#[instrument(skip_all, fields(flow = ?types::Flow::DummyRefundCreate))]
pub async fn dummy_connector_refund(
    state: web::Data<app::AppState>,
    req: actix_web::HttpRequest,
    json_payload: web::Json<types::DummyConnectorRefundRequest>,
    path: web::Path<common_utils::id_type::PaymentId>,
) -> impl actix_web::Responder {
    let flow = types::Flow::DummyRefundCreate;
    let mut payload = json_payload.into_inner();
    payload.payment_id = Some(path.into_inner());
    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        payload,
        |state, _: (), req, _| core::refund_payment(state, req),
        &auth::NoAuth,
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

#[cfg(all(feature = "dummy_connector", feature = "v1"))]
#[instrument(skip_all, fields(flow = ?types::Flow::DummyRefundRetrieve))]
pub async fn dummy_connector_refund_data(
    state: web::Data<app::AppState>,
    req: actix_web::HttpRequest,
    path: web::Path<String>,
) -> impl actix_web::Responder {
    let flow = types::Flow::DummyRefundRetrieve;
    let refund_id = path.into_inner();
    let payload = types::DummyConnectorRefundRetrieveRequest { refund_id };
    api::server_wrap(
        flow,
        state,
        &req,
        payload,
        |state, _: (), req, _| core::refund_data(state, req),
        &auth::NoAuth,
        api_locking::LockAction::NotApplicable,
    )
    .await
}


pub async fn update_business_profile_active_dynamic_algorithm_ref(
    db: &dyn StorageInterface,
    key_manager_state: &KeyManagerState,
    merchant_key_store: &domain::MerchantKeyStore,
    current_business_profile: domain::Profile,
    dynamic_routing_algorithm_ref: routing_types::DynamicRoutingAlgorithmRef,
) -> RouterResult<()> {
    let ref_val = dynamic_routing_algorithm_ref
        .encode_to_value()
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Failed to convert dynamic routing ref to value")?;
    let business_profile_update = domain::ProfileUpdate::DynamicRoutingAlgorithmUpdate {
        dynamic_routing_algorithm: Some(ref_val),
    };
    db.update_profile_by_profile_id(
        key_manager_state,
        merchant_key_store,
        current_business_profile,
        business_profile_update,
    )
    .await
    .change_context(errors::ApiErrorResponse::InternalServerError)
    .attach_printable("Failed to update dynamic routing algorithm ref in business profile")?;
    Ok(())
}


pub fn set_billing_data(mut self, address: Option<&Address>) -> Result<Self, Error> {
        self.billing_data = address
            .and_then(|address| {
                address.address.as_ref().map(|address_details| {
                    let state = address_details
                        .get_optional_state()
                        .map(Self::get_state_code)
                        .transpose();

                    match state {
                        Ok(bill_addr_state) => Ok(BillingData {
                            bill_addr_city: address_details.get_optional_city(),
                            bill_addr_country: address_details.get_optional_country().map(
                                |country| {
                                    common_enums::CountryAlpha2::from_alpha2_to_alpha3(country)
                                        .to_string()
                                },
                            ),
                            bill_addr_line1: address_details.get_optional_line1(),
                            bill_addr_line2: address_details.get_optional_line2(),
                            bill_addr_line3: address_details.get_optional_line3(),
                            bill_addr_postal_code: address_details.get_optional_zip(),
                            bill_addr_state,
                        }),
                        Err(err) => Err(err),
                    }
                })
            })
            .transpose()?;
        Ok(self)
    }


impl ConnectorCommon for Tsys {
    fn id(&self) -> &'static str {
        "tsys"
    }

    fn common_get_content_type(&self) -> &'static str {
        "application/json"
    }

    fn base_url<'a>(&self, connectors: &'a Connectors) -> &'a str {
        connectors.tsys.base_url.as_ref()
    }
}


impl api::PaymentAuthorize for Bamboraapac {}

impl api::PaymentAuthorize for for Bamboraapac


pub fn get_billing_required_fields() -> HashMap<String, RequiredFieldInfo> {
    HashMap::from([
        RequiredField::BillingFirstName("billing_first_name", FieldType::UserBillingName)
            .to_tuple(),
        RequiredField::BillingLastName("billing_last_name", FieldType::UserBillingName).to_tuple(),
        RequiredField::BillingAddressCity.to_tuple(),
        RequiredField::BillingAddressState.to_tuple(),
        RequiredField::BillingAddressZip.to_tuple(),
        RequiredField::BillingAddressCountries(vec!["ALL"]).to_tuple(),
        RequiredField::BillingAddressLine1.to_tuple(),
        RequiredField::BillingAddressLine2.to_tuple(),
        RequiredField::BillingPhone.to_tuple(),
        RequiredField::BillingPhoneCountryCode.to_tuple(),
        RequiredField::BillingEmail.to_tuple(),
    ])
}


impl webhooks::IncomingWebhook for Nomupay {
    fn get_webhook_object_reference_id(
        &self,
        _request: &webhooks::IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<api_models::webhooks::ObjectReferenceId, errors::ConnectorError> {
        Err(report!(errors::ConnectorError::WebhooksNotImplemented))
    }

    fn get_webhook_event_type(
        &self,
        _request: &webhooks::IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<api_models::webhooks::IncomingWebhookEvent, errors::ConnectorError> {
        Err(report!(errors::ConnectorError::WebhooksNotImplemented))
    }

    fn get_webhook_resource_object(
        &self,
        _request: &webhooks::IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<Box<dyn masking::ErasedMaskSerialize>, errors::ConnectorError> {
        Err(report!(errors::ConnectorError::WebhooksNotImplemented))
    }
}

impl webhooks::IncomingWebhook for for Nomupay


pub struct PlacetopayAuth {
    login: Secret<String>,
    tran_key: Secret<String>,
    nonce: Secret<String>,
    seed: String,
}


pub struct RedsysSyncResponseData {
    ds_order: String,
    ds_transactiontype: String,
    ds_amount: Option<String>,
    ds_currency: Option<String>,
    ds_securepayment: Option<String>,
    ds_state: Option<String>,
    ds_response: Option<DsResponse>,
}


pub fn get_card_bin_and_last4_digits_for_masked_card(
    masked_card_number: &str,
) -> Result<(String, String), cards::CardNumberValidationErr> {
    let last4_digits = masked_card_number
        .chars()
        .rev()
        .take(4)
        .collect::<String>()
        .chars()
        .rev()
        .collect::<String>();

    let card_isin = masked_card_number.chars().take(6).collect::<String>();

    cards::validate::validate_card_number_chars(&card_isin)
        .and_then(|_| cards::validate::validate_card_number_chars(&last4_digits))?;

    Ok((card_isin, last4_digits))
}


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


pub struct AchBankTransfer {
    /// Bank name
    #[schema(value_type = Option<String>, example = "Deutsche Bank")]
    pub bank_name: Option<String>,

    /// Bank country code
    #[schema(value_type = Option<CountryAlpha2>, example = "US")]
    pub bank_country_code: Option<api_enums::CountryAlpha2>,

    /// Bank city
    #[schema(value_type = Option<String>, example = "California")]
    pub bank_city: Option<String>,

    /// Bank account number is an unique identifier assigned by a bank to a customer.
    #[schema(value_type = String, example = "000123456")]
    pub bank_account_number: Secret<String>,

    /// [9 digits] Routing number - used in USA for identifying a specific bank.
    #[schema(value_type = String, example = "110000000")]
    pub bank_routing_number: Secret<String>,
}


pub struct AnalyticsMetadata {
    pub current_time_range: TimeRange,
}


pub struct UnifiedTranslationsUpdate {
    pub translation: Option<String>,
}


pub(crate) fn diesel_enum_text_derive_inner(ast: &DeriveInput) -> syn::Result<TokenStream> {
    let name = &ast.ident;
    let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();

    match &ast.data {
        Data::Enum(_) => (),
        _ => return Err(helpers::non_enum_error()),
    };

    Ok(quote! {

        #[automatically_derived]
        impl #impl_generics ::diesel::serialize::ToSql<::diesel::sql_types::Text, ::diesel::pg::Pg> for #name #ty_generics
        #where_clause
        {
            fn to_sql<'b>(&'b self, out: &mut ::diesel::serialize::Output<'b, '_, ::diesel::pg::Pg>) -> ::diesel::serialize::Result {
                use ::std::io::Write;

                out.write_all(self.to_string().as_bytes())?;
                Ok(::diesel::serialize::IsNull::No)
            }
        }

        #[automatically_derived]
        impl #impl_generics ::diesel::deserialize::FromSql<::diesel::sql_types::Text, ::diesel::pg::Pg> for #name #ty_generics
        #where_clause
        {
            fn from_sql(value: ::diesel::pg::PgValue) -> diesel::deserialize::Result<Self> {
                use ::core::str::FromStr;

                Self::from_str(::core::str::from_utf8(value.as_bytes())?)
                    .map_err(|_| "Unrecognized enum variant".into())
            }
        }
    })
}


impl Nexinets {
    pub fn connector_transaction_id(
        &self,
        connector_meta: Option<&serde_json::Value>,
    ) -> CustomResult<Option<String>, errors::ConnectorError> {
        let meta: nexinets::NexinetsPaymentsMetadata = to_connector_meta(connector_meta.cloned())?;
        Ok(meta.transaction_id)
    }
}


pub struct PaymentMethodDataWalletInfo {
    /// Last 4 digits of the card number
    pub last4: String,
    /// The information of the payment method
    pub card_network: String,
    /// The type of payment method
    #[serde(rename = "type")]
    pub card_type: Option<String>,
}


pub fn new(routable_connector_choice: RoutableConnectorChoice, status: bool) -> Self {
        Self {
            routable_connector_choice,
            status,
        }
    }


pub trait PayoutsInterface {
    type Error;
    async fn insert_payout(
        &self,
        _payout: PayoutsNew,
        _storage_scheme: MerchantStorageScheme,
    ) -> error_stack::Result<Payouts, Self::Error>;

    async fn find_payout_by_merchant_id_payout_id(
        &self,
        _merchant_id: &id_type::MerchantId,
        _payout_id: &id_type::PayoutId,
        _storage_scheme: MerchantStorageScheme,
    ) -> error_stack::Result<Payouts, Self::Error>;

    async fn update_payout(
        &self,
        _this: &Payouts,
        _payout: PayoutsUpdate,
        _payout_attempt: &PayoutAttempt,
        _storage_scheme: MerchantStorageScheme,
    ) -> error_stack::Result<Payouts, Self::Error>;

    async fn find_optional_payout_by_merchant_id_payout_id(
        &self,
        _merchant_id: &id_type::MerchantId,
        _payout_id: &id_type::PayoutId,
        _storage_scheme: MerchantStorageScheme,
    ) -> error_stack::Result<Option<Payouts>, Self::Error>;

    #[cfg(feature = "olap")]
    async fn filter_payouts_by_constraints(
        &self,
        _merchant_id: &id_type::MerchantId,
        _filters: &PayoutFetchConstraints,
        _storage_scheme: MerchantStorageScheme,
    ) -> error_stack::Result<Vec<Payouts>, Self::Error>;

    #[cfg(feature = "olap")]
    async fn filter_payouts_and_attempts(
        &self,
        _merchant_id: &id_type::MerchantId,
        _filters: &PayoutFetchConstraints,
        _storage_scheme: MerchantStorageScheme,
    ) -> error_stack::Result<
        Vec<(
            Payouts,
            PayoutAttempt,
            Option<diesel_models::Customer>,
            Option<diesel_models::Address>,
        )>,
        Self::Error,
    >;

    #[cfg(feature = "olap")]
    async fn filter_payouts_by_time_range_constraints(
        &self,
        _merchant_id: &id_type::MerchantId,
        _time_range: &common_utils::types::TimeRange,
        _storage_scheme: MerchantStorageScheme,
    ) -> error_stack::Result<Vec<Payouts>, Self::Error>;

    #[cfg(feature = "olap")]
    #[allow(clippy::too_many_arguments)]
    async fn get_total_count_of_filtered_payouts(
        &self,
        _merchant_id: &id_type::MerchantId,
        _active_payout_ids: &[id_type::PayoutId],
        _connector: Option<Vec<api_models::enums::PayoutConnectors>>,
        _currency: Option<Vec<storage_enums::Currency>>,
        _status: Option<Vec<storage_enums::PayoutStatus>>,
        _payout_method: Option<Vec<storage_enums::PayoutType>>,
    ) -> error_stack::Result<i64, Self::Error>;

    #[cfg(feature = "olap")]
    async fn filter_active_payout_ids_by_constraints(
        &self,
        _merchant_id: &id_type::MerchantId,
        _constraints: &PayoutFetchConstraints,
    ) -> error_stack::Result<Vec<id_type::PayoutId>, Self::Error>;
}


- **connector:** [Novalnet] add Recurring payment flow for cards ([#5921](https://github.com/juspay/hyperswitch/pull/5921)) ([`6a6ce17`](https://github.com/juspay/hyperswitch/commit/6a6ce17506932e0843140ef5b02ed201d0524d5d))
- **cypress-v2:** Add cypress v2 core flow tests ([#5791](https://github.com/juspay/hyperswitch/pull/5791)) ([`82574c0`](https://github.com/juspay/hyperswitch/commit/82574c0e8e7eb69e9f21eedc765145c724960cd5))
- **payments:** Store and propagate additional wallet pm details in payments response ([#5869](https://github.com/juspay/hyperswitch/pull/5869)) ([`8320dc0`](https://github.com/juspay/hyperswitch/commit/8320dc07fe1b8b1c9427f70dcb9d952eef01a63b))
- **payout:** Add unified error code and messages along with translation ([#5810](https://github.com/juspay/hyperswitch/pull/5810)) ([`a0f4bb7`](https://github.com/juspay/hyperswitch/commit/a0f4bb771b583a8dad2a58158c64b7a8baff24d5))

### Bug Fixes

- **cypress:** Fix user login in routing cypress framework ([#5950](https://github.com/juspay/hyperswitch/pull/5950)) ([`90949d9`](https://github.com/juspay/hyperswitch/commit/90949d94cf3cdfba7ae4deb7d931b0a40e330310))
- **payments:** Add time range in list payment attempts query ([#5959](https://github.com/juspay/hyperswitch/pull/5959)) ([`156a161`](https://github.com/juspay/hyperswitch/commit/156a161f3eb0553dcfcc1f361e42ec7713f0fbb4))

### Refactors

- **dynamic_fields:** Populate `billing.email` with customer email if not present ([#5962](https://github.com/juspay/hyperswitch/pull/5962)) ([`f4fa4cd`](https://github.com/juspay/hyperswitch/commit/f4fa4cdab478d33b6e9528c3649197bc5331cecd))
- **email:** Add recipient emails in email config ([#5964](https://github.com/juspay/hyperswitch/pull/5964)) ([`5942e05`](https://github.com/juspay/hyperswitch/commit/5942e059e9efa3fa71a13cacc896509515e2f976))
- **recon:** Use AuthDataWithUser and use JWTAuth for token verif… ([#5829](https://github.com/juspay/hyperswitch/pull/5829)) ([`30dd7ce`](https://github.com/juspay/hyperswitch/commit/30dd7ceb5f38849faacee5409112a8857df71972))
- **router:** Add `phone` and `country_code` in dynamic fields ([#5968](https://github.com/juspay/hyperswitch/pull/5968)) ([`1151d21`](https://github.com/juspay/hyperswitch/commit/1151d215a620b1a58e48adbef6b3a39196bc91e1))
- Rename business profile to profiles in api, diesel, domain, interface and error types ([#5877](https://github.com/juspay/hyperswitch/pull/5877)) ([`dee91b3`](https://github.com/juspay/hyperswitch/commit/dee91b366aacd2a75ca69ae95f2eea9ef4749d20))

### Miscellaneous Tasks

- Remove network tokenization service config in docker compose config ([#5953](https://github.com/juspay/hyperswitch/pull/5953)) ([`c7f7d3c`](https://github.com/juspay/hyperswitch/commit/c7f7d3c16abfec84b7ec36b1b5ea75823b40a983))

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

- - -

## 2024.09.19.1

### Refactors

- **router:** Handle connector errors for tax calculation flow ([#5949](https://github.com/juspay/hyperswitch/pull/5949)) ([`776b548`](https://github.com/juspay/hyperswitch/commit/776b5482e9315e5040066ad9623509f3a0f10ce0))

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

- - -

## 2024.09.19.0

### Features

- **disputes:** Add support for disputes aggregate ([#5896](https://github.com/juspay/hyperswitch/pull/5896)) ([`0a0c93e`](https://github.com/juspay/hyperswitch/commit/0a0c93e102dc3183627db3b871370d7b5661f151))
- **payment_methods_v2:** Payment method Create API ([#5812](https://github.com/juspay/hyperswitch/pull/5812)) ([`be902ff`](https://github.com/juspay/hyperswitch/commit/be902ffa5328d32efe70c40c36f86d8fbfa01c79))
- **routing:** Build gRPC Client Interface to initiate communication with other gRPC services ([#5835](https://github.com/juspay/hyperswitch/pull/5835)) ([`99f5933`](https://github.com/juspay/hyperswitch/commit/99f593389451c13e81ba6d019e9f3ca4361942ed))

### Bug Fixes

- **merchant_account_v2:** Remove compatible_connector field in metadata ([#5935](https://github.com/juspay/hyperswitch/pull/5935)) ([`8c99db7`](https://github.com/juspay/hyperswitch/commit/8c99db72adbd2b5f03c37fa5b1fa82b9c77ce2c5))

### Documentation

- Add openapi docs for customers v2 ([#5926](https://github.com/juspay/hyperswitch/pull/5926)) ([`2bc8756`](https://github.com/juspay/hyperswitch/commit/2bc8756e061e9e0e705ce2c6b533c3583f3efa8b))
- Api-reference changes for customers and admin list apis for v2 ([#5936](https://github.com/juspay/hyperswitch/pull/5936)) ([`ed13146`](https://github.com/juspay/hyperswitch/commit/ed13146b8088e1fcd6df8b820fa8c7b4a9e400a3))

### Miscellaneous Tasks

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

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

- - -

## 2024.09.18.0

### Features

- **router:** Add admin list apis for v2 ([#5883](https://github.com/juspay/hyperswitch/pull/5883)) ([`bc6c460`](https://github.com/juspay/hyperswitch/commit/bc6c460ca9767d3b80604166ce2cbd98550d175a))

### Bug Fixes

- **connector:** Add field types for bank debits ([#5908](https://github.com/juspay/hyperswitch/pull/5908)) ([`90e8de1`](https://github.com/juspay/hyperswitch/commit/90e8de18a854a7f83470e84a954ed365078c24c2))
- **frm:** Add feature flag for querying FRM data ([#5889](https://github.com/juspay/hyperswitch/pull/5889)) ([`75400a3`](https://github.com/juspay/hyperswitch/commit/75400a3af7aaff87e03dbab4e00be8b00ed5a70e))
- **router:**
  - Cache invalidation in merchant_connector_update flow for v2 ([#5918](https://github.com/juspay/hyperswitch/pull/5918)) ([`66de680`](https://github.com/juspay/hyperswitch/commit/66de680e6fcaa318694df48dafdaabfceb745961))
  - [stripe] remove passing of customer_acceptance from Mandate Payment Request ([#5920](https://github.com/juspay/hyperswitch/pull/5920)) ([`97c8e98`](https://github.com/juspay/hyperswitch/commit/97c8e98a48f514b0ba36b109971dd479ae84861e))

### Refactors

- **connector:** Move connector Volt and Mollie from Router to HyperswitchConnector Trait ([#5612](https://github.com/juspay/hyperswitch/pull/5612)) ([`1d9e639`](https://github.com/juspay/hyperswitch/commit/1d9e6396522fc0b6cbe0b7ff1be2377098655690))
- Add encryption support to payment attempt domain model ([#5882](https://github.com/juspay/hyperswitch/pull/5882)) ([`f72abe4`](https://github.com/juspay/hyperswitch/commit/f72abe4b979873b06d75553c7412f8072c29c8a9))

### Miscellaneous Tasks

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

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

- - -

## 2024.09.17.0

### Features

- **connector:** Wasm changes for Taxjar ([#5879](https://github.com/juspay/hyperswitch/pull/5879)) ([`90ebd54`](https://github.com/juspay/hyperswitch/commit/90ebd54ec9dfabf03ee85c0d0e7d96755a135083))
- **core:** Add support for card network tokenization ([#5599](https://github.com/juspay/hyperswitch/pull/5599)) ([`61e2ca9`](https://github.com/juspay/hyperswitch/commit/61e2ca9b1779887f6bd5f567806d891e0204e217))
- **router:** Default configs and toggle api for dynamic routing feature ([#5830](https://github.com/juspay/hyperswitch/pull/5830)) ([`9f9a414`](https://github.com/juspay/hyperswitch/commit/9f9a41404228e98d63ca79784cbca69f410927ea))

### Bug Fixes

- **process:** Add process tracker support for instant refunds ([#5818](https://github.com/juspay/hyperswitch/pull/5818)) ([`6e74b80`](https://github.com/juspay/hyperswitch/commit/6e74b800986c609664a9c12cfb27e0d6b2adcc17))
- **user_roles:** Populate `profile_id` from token in update user role API ([#5907](https://github.com/juspay/hyperswitch/pull/5907)) ([`a258602`](https://github.com/juspay/hyperswitch/commit/a258602ff161bcd21381f53a717c819ea38f832e))

### Refactors

- **connector:** [Paybox] Fix Error Handling/Datetime format ([#5905](https://github.com/juspay/hyperswitch/pull/5905)) ([`00a7865`](https://github.com/juspay/hyperswitch/commit/00a78655766fc3fa78bbb844ab80f8d4bb67ff03))
- **core:** Update response for PaymentsDynamicTaxCalculationResponse ([#5909](https://github.com/juspay/hyperswitch/pull/5909)) ([`45c19a1`](https://github.com/juspay/hyperswitch/commit/45c19a1729af3f4b80bde2661868cb213138df86))
- **payment_methods:** Unify locker api function call ([#5863](https://github.com/juspay/hyperswitch/pull/5863)) ([`4137d7b`](https://github.com/juspay/hyperswitch/commit/4137d7b48a95647646853f7b346a525642d5c04c))

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

- - -

## 2024.09.16.0

### Features

- **connector:**
  - [Fiuu] ADD Wasm Configs ([#5874](https://github.com/juspay/hyperswitch/pull/5874)) ([`71bf627`](https://github.com/juspay/hyperswitch/commit/71bf627fbcdab6263e837fb851b77cefef833ea1))
  - [DEUTSCHEBANK] Integrate SEPA Payments ([#5826](https://github.com/juspay/hyperswitch/pull/5826)) ([`6fc2060`](https://github.com/juspay/hyperswitch/commit/6fc20606202749fd671a25071793900dc5577da6))
- **payments_v2:** Payment intent diesel and domain models changes v2 ([#5783](https://github.com/juspay/hyperswitch/pull/5783)) ([`10ac089`](https://github.com/juspay/hyperswitch/commit/10ac08944986a1fd101f8f05263e92ed7ebbba94))

### Refactors

- **user_roles:** Populate role names and entity names in user role APIs ([#5861](https://github.com/juspay/hyperswitch/pull/5861)) ([`4d28cf2`](https://github.com/juspay/hyperswitch/commit/4d28cf276f8c350d6c1aaf073a138ce7ae3eddd8))

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

- - -

## 2024.09.13.0

### Features

- **connector:** [Novalnet] add Payment flows for cards ([#5726](https://github.com/juspay/hyperswitch/pull/5726)) ([`246fdc8`](https://github.com/juspay/hyperswitch/commit/246fdc84064367885596b33f5e0e66af78a97a3c))
- **refunds:** Refunds aggregate api ([#5795](https://github.com/juspay/hyperswitch/pull/5795)) ([`00386f3`](https://github.com/juspay/hyperswitch/commit/00386f32954a6f9a3f71388e9cad7fbdb8824206))

### Bug Fixes

- **connector:** [ZSL] compare consr_paid_amt with the total amount for identifying partial payments ([#5873](https://github.com/juspay/hyperswitch/pull/5873)) ([`985761c`](https://github.com/juspay/hyperswitch/commit/985761cfb31539ca51c66832a7f2cca458640c78))
- **router:** Add payment_method check in `get_mandate_type` ([#5828](https://github.com/juspay/hyperswitch/pull/5828)) ([`1929f56`](https://github.com/juspay/hyperswitch/commit/1929f56e2ab65fc8570eb492ebc4f254bd5092d0))

### Refactors

- **core:** Update shipping_cost and order_tax_amount to net_amount of payment_attempt ([#5844](https://github.com/juspay/hyperswitch/pull/5844)) ([`840609a`](https://github.com/juspay/hyperswitch/commit/840609af61ad1441ca95ebb7294196b35e7b875b))
- **payment_links:** Update API contract for dynamic transaction details and upgrade UI ([#5849](https://github.com/juspay/hyperswitch/pull/5849)) ([`a96e9f3`](https://github.com/juspay/hyperswitch/commit/a96e9f3e22ca24ffb96af3e469cace543dc03796))
- Handle redirections for iframed content ([#5591](https://github.com/juspay/hyperswitch/pull/5591)) ([`1bb8f5e`](https://github.com/juspay/hyperswitch/commit/1bb8f5e8ebd817ac7e04e2e9dd2ae9e422313bc3))
- Return optional request body from build_request_v2 in ConnectorIntegrationV2 trait ([#5865](https://github.com/juspay/hyperswitch/pull/5865)) ([`608676c`](https://github.com/juspay/hyperswitch/commit/608676c8e26d73b191914960dbcc8b84effb6c7d))

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

- - -

## 2024.09.12.0

### Features

- **connector:** [Fiuu] Add DuitNow/FPX PaymentMethod ([#5841](https://github.com/juspay/hyperswitch/pull/5841)) ([`8c0fec9`](https://github.com/juspay/hyperswitch/commit/8c0fec9dc317ed8753d0341f01e0174f5a701edc))
- **opensearch:** Add profile_id and organization_id to /search APIs ([#5705](https://github.com/juspay/hyperswitch/pull/5705)) ([`7eb5354`](https://github.com/juspay/hyperswitch/commit/7eb5354efe7b4790cb8e2a6ebac23126f3233add))
- **payment_method_data:** Populate additional payment method data fields across all the methods in payments response ([#5788](https://github.com/juspay/hyperswitch/pull/5788)) ([`034f736`](https://github.com/juspay/hyperswitch/commit/034f736ea6e25ae2c75e74dedc12ac54f5979d68))
- **payments:** Add support for profile aggregates ([#5845](https://github.com/juspay/hyperswitch/pull/5845)) ([`b7b0a08`](https://github.com/juspay/hyperswitch/commit/b7b0a08114eb73b167b07c297ca5422e43a51e21))

### Bug Fixes

- **router:** Return `collect_billing_details_from_wallet_connector` if `always_collect_billing_details_from_wallet_connector ` is false in merchant payment method list ([#5854](https://github.com/juspay/hyperswitch/pull/5854)) ([`a90e406`](https://github.com/juspay/hyperswitch/commit/a90e4062761cb8b9b71daa5bb2f07901cbb2f8f9))
- Fix `status_code` being logged as string instead of number in logs ([#5850](https://github.com/juspay/hyperswitch/pull/5850)) ([`75e8f35`](https://github.com/juspay/hyperswitch/commit/75e8f354314edb5d35fc5036e39a7aec4ec23485))

### Refactors

- Add a GAT Data to Operation trait ([#5825](https://github.com/juspay/hyperswitch/pull/5825)) ([`418ea4e`](https://github.com/juspay/hyperswitch/commit/418ea4e2c6ce49323dc63ccf311a606ca6eec73f))
- Remove unwanted commented lines ([#5851](https://github.com/juspay/hyperswitch/pull/5851)) ([`4a9fd7e`](https://github.com/juspay/hyperswitch/commit/4a9fd7e0bf46a05d27e58e0febde8442f94acba6))

### Documentation

- Correction for JPY in API Ref ([#5853](https://github.com/juspay/hyperswitch/pull/5853)) ([`be346e5`](https://github.com/juspay/hyperswitch/commit/be346e5d963925ecbe1bbb77aa024f7eed66019e))

### Miscellaneous Tasks

- Remove Connectors enum dependency from ConnectorIntegrationV2 trait ([#5840](https://github.com/juspay/hyperswitch/pull/5840)) ([`296ca31`](https://github.com/juspay/hyperswitch/commit/296ca311c96cc032aaa9ad846299db24bacaeb56))

### Build System / Dependencies

- **deps:** Bump `sqlx` to `0.8.2` ([#5859](https://github.com/juspay/hyperswitch/pull/5859)) ([`b72c770`](https://github.com/juspay/hyperswitch/commit/b72c77075e6847d5cce3066b9bc88df1127fbfb2))

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

- - -

## 2024.09.11.0

### Features

- **analytics:**
  - Revert api_event metrics and filters back to merchant_id authentication ([#5821](https://github.com/juspay/hyperswitch/pull/5821)) ([`283154d`](https://github.com/juspay/hyperswitch/commit/283154d3f66ae26a0d9644ed50547ad1407bd924))
  - Add card_network as a field in payment_attempts clickhouse table ([#5807](https://github.com/juspay/hyperswitch/pull/5807)) ([`bf1797f`](https://github.com/juspay/hyperswitch/commit/bf1797fe7cf769eb6e89f75b132a35a6cd9003df))
- **connector:** [THUNES] Add template code ([#5775](https://github.com/juspay/hyperswitch/pull/5775)) ([`9b508a8`](https://github.com/juspay/hyperswitch/commit/9b508a838d68d14517477d41f2fc60168703d001))
- **core:** [Payouts] Add billing address to payout list ([#5004](https://github.com/juspay/hyperswitch/pull/5004)) ([`49a60bf`](https://github.com/juspay/hyperswitch/commit/49a60bf14725d67bc4f8c5814dc5ca27b7f57712))
- **payment_methods_list:** Add is_tax_connector_enabled boolean value in payment_methods_list call response ([#5707](https://github.com/juspay/hyperswitch/pull/5707)) ([`3a5fb53`](https://github.com/juspay/hyperswitch/commit/3a5fb532de39e033feff7e8de126c5e5bf12eb36))
- **payout:** Add dynamic fields for payout links ([#5764](https://github.com/juspay/hyperswitch/pull/5764)) ([`f4ad657`](https://github.com/juspay/hyperswitch/commit/f4ad6579cc317b32599d28dbb6164be6e20804fa))
- **router:** Mask keys in `connector_account_details` for merchant_connector_response in mca retrieve flow ([#5848](https://github.com/juspay/hyperswitch/pull/5848)) ([`71b5202`](https://github.com/juspay/hyperswitch/commit/71b52024c296548156cd80950010a2f1266906fb))
- **users:** New profile level roles ([#5843](https://github.com/juspay/hyperswitch/pull/5843)) ([`3cb0f24`](https://github.com/juspay/hyperswitch/commit/3cb0f2405303f9abbf15fff2b31ad617c1a6ca91))

### Bug Fixes

- **router:** [Stripe/Itau/Paypal/Bambora/Cybersource] prevent partial submission of billing address and add required fields for all payment methods ([#5752](https://github.com/juspay/hyperswitch/pull/5752)) ([`ad40ced`](https://github.com/juspay/hyperswitch/commit/ad40cedf5cf70337c0ec49e3fa6306fe25badc39))

### Refactors

- Add hgetall command to redis interface ([#5727](https://github.com/juspay/hyperswitch/pull/5727)) ([`74ec3f3`](https://github.com/juspay/hyperswitch/commit/74ec3f3df33de8c418efa859789365627c12b93d))

### Miscellaneous Tasks

- Address Rust 1.81.0 clippy lints ([#5832](https://github.com/juspay/hyperswitch/pull/5832)) ([`933cef4`](https://github.com/juspay/hyperswitch/commit/933cef425fed2e324474f4015dd728bde2612cb2))
- Make kms decryption optional if partial auth not enabled ([#5779](https://github.com/juspay/hyperswitch/pull/5779)) ([`aaeb192`](https://github.com/juspay/hyperswitch/commit/aaeb1925767b08e35decb913e3867cd6415f0abd))

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

- - -

## 2024.09.10.0

### Features

- Enable payment and refund filter at DB query level ([#5827](https://github.com/juspay/hyperswitch/pull/5827)) ([`21352cf`](https://github.com/juspay/hyperswitch/commit/21352cf875e360c808562a15fcbb8d8c6a27ae50))

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

- - -

## 2024.09.09.0

### Features


OpenAPI Block Path: components.schemas.ProfileAcquirerCreate
{
  "type": "object",
  "required": [
    "acquirer_assigned_merchant_id",
    "merchant_name",
    "network",
    "acquirer_bin",
    "acquirer_fraud_rate",
    "profile_id"
  ],
  "properties": {
    "acquirer_assigned_merchant_id": {
      "type": "string",
      "description": "The merchant id assigned by the acquirer",
      "example": "M123456789"
    },
    "merchant_name": {
      "type": "string",
      "description": "merchant name",
      "example": "NewAge Retailer"
    },
    "network": {
      "type": "string",
      "description": "Network provider",
      "example": "VISA"
    },
    "acquirer_bin": {
      "type": "string",
      "description": "Acquirer bin",
      "example": "456789"
    },
    "acquirer_ica": {
      "type": "string",
      "description": "Acquirer ica provided by acquirer",
      "example": "401288",
      "nullable": true
    },
    "acquirer_fraud_rate": {
      "type": "number",
      "format": "double",
      "description": "Fraud rate for the particular acquirer configuration",
      "example": 0.01
    },
    "profile_id": {
      "type": "string",
      "description": "Parent profile id to link the acquirer account with",
      "example": "pro_ky0yNyOXXlA5hF8JzE5q"
    }
  }
}


pub struct Razorpay {
    amount_converter: &'static (dyn AmountConvertor<Output = MinorUnit> + Sync),
}


File: crates/router_env/src/logger/types.rs

//! Types.

use serde::Deserialize;
use strum::{Display, EnumString};
pub use tracing::{
    field::{Field, Visit},
    Level, Value,
};

/// Category and tag of log event.
///
/// Don't hesitate to add your variant if it is missing here.
#[derive(Debug, Default, Deserialize, Clone, Display, EnumString)]
pub enum Tag {
    /// General.
    #[default]
    General,

    /// Redis: get.
    RedisGet,
    /// Redis: set.
    RedisSet,

    /// API: incoming web request.
    ApiIncomingRequest,
    /// API: outgoing web request.
    ApiOutgoingRequest,

    /// Data base: create.
    DbCreate,
    /// Data base: read.
    DbRead,
    /// Data base: updare.
    DbUpdate,
    /// Data base: delete.
    DbDelete,
    /// Begin Request
    BeginRequest,
    /// End Request
    EndRequest,

    /// Call initiated to connector.
    InitiatedToConnector,

    /// Event: general.
    Event,

    /// Compatibility Layer Request
    CompatibilityLayerRequest,
}

/// API Flow
#[derive(Debug, Display, Clone, PartialEq, Eq)]
pub enum Flow {
    /// Health check
    HealthCheck,
    /// Deep health Check
    DeepHealthCheck,
    /// Organization create flow
    OrganizationCreate,
    /// Organization retrieve flow
    OrganizationRetrieve,
    /// Organization update flow
    OrganizationUpdate,
    /// Merchants account create flow.
    MerchantsAccountCreate,
    /// Merchants account retrieve flow.
    MerchantsAccountRetrieve,
    /// Merchants account update flow.
    MerchantsAccountUpdate,
    /// Merchants account delete flow.
    MerchantsAccountDelete,
    /// Merchant Connectors create flow.
    MerchantConnectorsCreate,
    /// Merchant Connectors retrieve flow.
    MerchantConnectorsRetrieve,
    /// Merchant account list
    MerchantAccountList,
    /// Merchant Connectors update flow.
    MerchantConnectorsUpdate,
    /// Merchant Connectors delete flow.
    MerchantConnectorsDelete,
    /// Merchant Connectors list flow.
    MerchantConnectorsList,
    /// Merchant Transfer Keys
    MerchantTransferKey,
    /// ConfigKey create flow.
    ConfigKeyCreate,
    /// ConfigKey fetch flow.
    ConfigKeyFetch,
    /// Enable platform account flow.
    EnablePlatformAccount,
    /// ConfigKey Update flow.
    ConfigKeyUpdate,
    /// ConfigKey Delete flow.
    ConfigKeyDelete,
    /// Customers create flow.
    CustomersCreate,
    /// Customers retrieve flow.
    CustomersRetrieve,
    /// Customers update flow.
    CustomersUpdate,
    /// Customers delete flow.
    CustomersDelete,
    /// Customers get mandates flow.
    CustomersGetMandates,
    /// Create an Ephemeral Key.
    EphemeralKeyCreate,
    /// Delete an Ephemeral Key.
    EphemeralKeyDelete,
    /// Mandates retrieve flow.
    MandatesRetrieve,
    /// Mandates revoke flow.
    MandatesRevoke,
    /// Mandates list flow.
    MandatesList,
    /// Payment methods create flow.
    PaymentMethodsCreate,
    /// Payment methods migrate flow.
    PaymentMethodsMigrate,
    /// Payment methods batch update flow.
    PaymentMethodsBatchUpdate,
    /// Payment methods list flow.
    PaymentMethodsList,
    /// Payment method save flow
    PaymentMethodSave,
    /// Customer payment methods list flow.
    CustomerPaymentMethodsList,
    /// Payment methods token data get flow.
    GetPaymentMethodTokenData,
    /// List Customers for a merchant
    CustomersList,
    /// Retrieve countries and currencies for connector and payment method
    ListCountriesCurrencies,
    /// Payment method create collect link flow.
    PaymentMethodCollectLink,
    /// Payment methods retrieve flow.
    PaymentMethodsRetrieve,
    /// Payment methods update flow.
    PaymentMethodsUpdate,
    /// Payment methods delete flow.
    PaymentMethodsDelete,
    /// Default Payment method flow.
    DefaultPaymentMethodsSet,
    /// Payments create flow.
    PaymentsCreate,
    /// Payments Retrieve flow.
    PaymentsRetrieve,
    /// Payments Retrieve force sync flow.
    PaymentsRetrieveForceSync,
    /// Payments Retrieve using merchant reference id
    PaymentsRetrieveUsingMerchantReferenceId,
    /// Payments update flow.
    PaymentsUpdate,
    /// Payments confirm flow.
    PaymentsConfirm,
    /// Payments capture flow.
    PaymentsCapture,
    /// Payments cancel flow.
    PaymentsCancel,
    /// Payments cancel post capture flow.
    PaymentsCancelPostCapture,
    /// Payments approve flow.
    PaymentsApprove,
    /// Payments reject flow.
    PaymentsReject,
    /// Payments Session Token flow
    PaymentsSessionToken,
    /// Payments start flow.
    PaymentsStart,
    /// Payments list flow.
    PaymentsList,
    /// Payments filters flow
    PaymentsFilters,
    /// Payments aggregates flow
    PaymentsAggregate,
    /// Payments Create Intent flow
    PaymentsCreateIntent,
    /// Payments Get Intent flow
    PaymentsGetIntent,
    /// Payments Update Intent flow
    PaymentsUpdateIntent,
    /// Payments confirm intent flow
    PaymentsConfirmIntent,
    /// Payments create and confirm intent flow
    PaymentsCreateAndConfirmIntent,
    /// Payment attempt list flow
    PaymentAttemptsList,
    #[cfg(feature = "payouts")]
    /// Payouts create flow
    PayoutsCreate,
    #[cfg(feature = "payouts")]
    /// Payouts retrieve flow.
    PayoutsRetrieve,
    #[cfg(feature = "payouts")]
    /// Payouts update flow.
    PayoutsUpdate,
    /// Payouts confirm flow.
    PayoutsConfirm,
    #[cfg(feature = "payouts")]
    /// Payouts cancel flow.
    PayoutsCancel,
    #[cfg(feature = "payouts")]
    /// Payouts fulfill flow.
    PayoutsFulfill,
    #[cfg(feature = "payouts")]
    /// Payouts list flow.
    PayoutsList,
    #[cfg(feature = "payouts")]
    /// Payouts filter flow.
    PayoutsFilter,
    /// Payouts accounts flow.
    PayoutsAccounts,
    /// Payout link initiate flow
    PayoutLinkInitiate,
    /// Payments Redirect flow
    PaymentsRedirect,
    /// Payemnts Complete Authorize Flow
    PaymentsCompleteAuthorize,
    /// Refunds create flow.
    RefundsCreate,
    /// Refunds retrieve flow.
    RefundsRetrieve,
    /// Refunds retrieve force sync flow.
    RefundsRetrieveForceSync,
    /// Refunds update flow.
    RefundsUpdate,
    /// Refunds list flow.
    RefundsList,
    /// Refunds filters flow
    RefundsFilters,
    /// Refunds aggregates flow
    RefundsAggregate,
    // Retrieve forex flow.
    RetrieveForexFlow,
    /// Toggles recon service for a merchant.
    ReconMerchantUpdate,
    /// Recon token request flow.
    ReconTokenRequest,
    /// Initial request for recon service.
    ReconServiceRequest,
    /// Recon token verification flow
    ReconVerifyToken,
    /// Routing create flow,
    RoutingCreateConfig,
    /// Routing link config
    RoutingLinkConfig,
    /// Routing link config
    RoutingUnlinkConfig,
    /// Routing retrieve config
    RoutingRetrieveConfig,
    /// Routing retrieve active config
    RoutingRetrieveActiveConfig,
    /// Routing retrieve default config
    RoutingRetrieveDefaultConfig,
    /// Routing retrieve dictionary
    RoutingRetrieveDictionary,
    /// Rule migration for decision-engine
    DecisionEngineRuleMigration,
    /// Routing update config
    RoutingUpdateConfig,
    /// Routing update default config
    RoutingUpdateDefaultConfig,
    /// Routing delete config
    RoutingDeleteConfig,
    /// Create dynamic routing
    CreateDynamicRoutingConfig,
    /// Toggle dynamic routing
    ToggleDynamicRouting,
    /// Update dynamic routing config
    UpdateDynamicRoutingConfigs,
    /// Add record to blocklist
    AddToBlocklist,
    /// Delete record from blocklist
    DeleteFromBlocklist,
    /// List entries from blocklist
    ListBlocklist,
    /// Toggle blocklist for merchant
    ToggleBlocklistGuard,
    /// Incoming Webhook Receive
    IncomingWebhookReceive,
    /// Recovery incoming webhook receive
    RecoveryIncomingWebhookReceive,
    /// Validate payment method flow
    ValidatePaymentMethod,
    /// API Key create flow
    ApiKeyCreate,
    /// API Key retrieve flow
    ApiKeyRetrieve,
    /// API Key update flow
    ApiKeyUpdate,
    /// API Key revoke flow
    ApiKeyRevoke,
    /// API Key list flow
    ApiKeyList,
    /// Dispute Retrieve flow
    DisputesRetrieve,
    /// Dispute List flow
    DisputesList,
    /// Dispute Filters flow
    DisputesFilters,
    /// Cards Info flow
    CardsInfo,
    /// Create File flow
    CreateFile,
    /// Delete File flow
    DeleteFile,
    /// Retrieve File flow
    RetrieveFile,
    /// Dispute Evidence submission flow
    DisputesEvidenceSubmit,
    /// Create Config Key flow
    CreateConfigKey,
    /// Attach Dispute Evidence flow
    AttachDisputeEvidence,
    /// Delete Dispute Evidence flow
    DeleteDisputeEvidence,
    /// Disputes aggregate flow
    DisputesAggregate,
    /// Retrieve Dispute Evidence flow
    RetrieveDisputeEvidence,
    /// Invalidate cache flow
    CacheInvalidate,
    /// Payment Link Retrieve flow
    PaymentLinkRetrieve,
    /// payment Link Initiate flow
    PaymentLinkInitiate,
    /// payment Link Initiate flow
    PaymentSecureLinkInitiate,
    /// Payment Link List flow
    PaymentLinkList,
    /// Payment Link Status
    PaymentLinkStatus,
    /// Create a profile
    ProfileCreate,
    /// Update a profile
    ProfileUpdate,
    /// Retrieve a profile
    ProfileRetrieve,
    /// Delete a profile
    ProfileDelete,
    /// List all the profiles for a merchant
    ProfileList,
    /// Different verification flows
    Verification,
    /// Rust locker migration
    RustLockerMigration,
    /// Gsm Rule Creation flow
    GsmRuleCreate,
    /// Gsm Rule Retrieve flow
    GsmRuleRetrieve,
    /// Gsm Rule Update flow
    GsmRuleUpdate,
    /// Apple pay certificates migration
    ApplePayCertificatesMigration,
    /// Gsm Rule Delete flow
    GsmRuleDelete,
    /// Get data from embedded flow
    GetDataFromHyperswitchAiFlow,
    /// User Sign Up
    UserSignUp,
    /// User Sign Up
    UserSignUpWithMerchantId,
    /// User Sign In
    UserSignIn,
    /// User transfer key
    UserTransferKey,
    /// User connect account
    UserConnectAccount,
    /// Upsert Decision Manager Config
    DecisionManagerUpsertConfig,
    /// Delete Decision Manager Config
    DecisionManagerDeleteConfig,
    /// Retrieve Decision Manager Config
    DecisionManagerRetrieveConfig,
    /// Manual payment fulfillment acknowledgement
    FrmFulfillment,
    /// Get connectors feature matrix
    FeatureMatrix,
    /// Change password flow
    ChangePassword,
    /// Signout flow
    Signout,
    /// Set Dashboard Metadata flow
    SetDashboardMetadata,
    /// Get Multiple Dashboard Metadata flow
    GetMultipleDashboardMetadata,
    /// Payment Connector Verify
    VerifyPaymentConnector,
    /// Internal user signup
    InternalUserSignup,
    /// Create tenant level user
    TenantUserCreate,
    /// Switch org
    SwitchOrg,
    /// Switch merchant v2
    SwitchMerchantV2,
    /// Switch profile
    SwitchProfile,
    /// Get permission info
    GetAuthorizationInfo,
    /// Get Roles info
    GetRolesInfo,
    /// Get Parent Group Info
    GetParentGroupInfo,
    /// List roles v2
    ListRolesV2,
    /// List invitable roles at entity level
    ListInvitableRolesAtEntityLevel,
    /// List updatable roles at entity level
    ListUpdatableRolesAtEntityLevel,
    /// Get role
    GetRole,
    /// Get parent info for role
    GetRoleV2,
    /// Get role from token
    GetRoleFromToken,
    /// Get resources and groups for role from token
    GetRoleFromTokenV2,
    /// Update user role
    UpdateUserRole,
    /// Create merchant account for user in a org
    UserMerchantAccountCreate,
    /// Create Platform
    CreatePlatformAccount,
    /// Create Org in a given tenancy
    UserOrgMerchantCreate,
    /// Generate Sample Data
    GenerateSampleData,
    /// Delete Sample Data
    DeleteSampleData,
    /// Get details of a user
    GetUserDetails,
    /// Get details of a user role in a merchant account
    GetUserRoleDetails,
    /// PaymentMethodAuth Link token create
    PmAuthLinkTokenCreate,
    /// PaymentMethodAuth Exchange token create
    PmAuthExchangeToken,
    /// Get reset password link
    ForgotPassword,
    /// Reset password using link
    ResetPassword,
    /// Force set or force change password
    RotatePassword,
    /// Invite multiple users
    InviteMultipleUser,
    /// Reinvite user
    ReInviteUser,
    /// Accept invite from email
    AcceptInviteFromEmail,
    /// Delete user role
    DeleteUserRole,
    /// Incremental Authorization flow
    PaymentsIncrementalAuthorization,
    /// Get action URL for connector onboarding
    GetActionUrl,
    /// Sync connector onboarding status
    SyncOnboardingStatus,
    /// Reset tracking id
    ResetTrackingId,
    /// Verify email Token
    VerifyEmail,
    /// Send verify email
    VerifyEmailRequest,
    /// Update user account details
    UpdateUserAccountDetails,
    /// Accept user invitation using entities
    AcceptInvitationsV2,
    /// Accept user invitation using entities before user login
    AcceptInvitationsPreAuth,
    /// Initiate external authentication for a payment
    PaymentsExternalAuthentication,
    /// Authorize the payment after external 3ds authentication
    PaymentsAuthorize,
    /// Create Role
    CreateRole,
    /// Create Role V2
    CreateRoleV2,
    /// Update Role
    UpdateRole,
    /// User email flow start
    UserFromEmail,
    /// Begin TOTP
    TotpBegin,
    /// Reset TOTP
    TotpReset,
    /// Verify TOTP
    TotpVerify,
    /// Update TOTP secret
    TotpUpdate,
    /// Verify Access Code
    RecoveryCodeVerify,
    /// Generate or Regenerate recovery codes
    RecoveryCodesGenerate,
    /// Terminate two factor authentication
    TerminateTwoFactorAuth,
    /// Check 2FA status
    TwoFactorAuthStatus,
    /// Create user authentication method
    CreateUserAuthenticationMethod,
    /// Update user authentication method
    UpdateUserAuthenticationMethod,
    /// List user authentication methods
    ListUserAuthenticationMethods,
    /// Get sso auth url
    GetSsoAuthUrl,
    /// Signin with SSO
    SignInWithSso,
    /// Auth Select
    AuthSelect,
    /// List Orgs for user
    ListOrgForUser,
    /// List Merchants for user in org
    ListMerchantsForUserInOrg,
    /// List Profile for user in org and merchant
    ListProfileForUserInOrgAndMerchant,
    /// List Users in Org
    ListUsersInLineage,
    /// List invitations for user
    ListInvitationsForUser,
    /// Get theme using lineage
    GetThemeUsingLineage,
    /// Get theme using theme id
    GetThemeUsingThemeId,
    /// Upload file to theme storage
    UploadFileToThemeStorage,
    /// Create theme
    CreateTheme,
    /// Update theme
    UpdateTheme,
    /// Delete theme
    DeleteTheme,
    /// Create user theme
    CreateUserTheme,
    /// Update user theme
    UpdateUserTheme,
    /// Delete user theme
    DeleteUserTheme,
    /// Upload file to user theme storage
    UploadFileToUserThemeStorage,
    /// Get user theme using theme id
    GetUserThemeUsingThemeId,
    ///List All Themes In Lineage
    ListAllThemesInLineage,
    /// Get user theme using lineage
    GetUserThemeUsingLineage,
    /// List initial webhook delivery attempts
    WebhookEventInitialDeliveryAttemptList,
    /// List delivery attempts for a webhook event
    WebhookEventDeliveryAttemptList,
    /// Manually retry the delivery for a webhook event
    WebhookEventDeliveryRetry,
    /// Retrieve status of the Poll
    RetrievePollStatus,
    /// Toggles the extended card info feature in profile level
    ToggleExtendedCardInfo,
    /// Toggles the extended card info feature in profile level
    ToggleConnectorAgnosticMit,
    /// Get the extended card info associated to a payment_id
    GetExtendedCardInfo,
    /// Manually update the refund details like status, error code, error message etc.
    RefundsManualUpdate,
    /// Manually update the payment details like status, error code, error message etc.
    PaymentsManualUpdate,
    /// Dynamic Tax Calcultion
    SessionUpdateTaxCalculation,
    ProxyConfirmIntent,
    /// Payments post session tokens flow
    PaymentsPostSessionTokens,
    /// Payments Update Metadata
    PaymentsUpdateMetadata,
    /// Payments start redirection flow
    PaymentStartRedirection,
    /// Volume split on the routing type
    VolumeSplitOnRoutingType,
    /// Routing evaluate rule flow
    RoutingEvaluateRule,
    /// Relay flow
    Relay,
    /// Relay retrieve flow
    RelayRetrieve,
    /// Card tokenization flow
    TokenizeCard,
    /// Card tokenization using payment method flow
    TokenizeCardUsingPaymentMethodId,
    /// Cards batch tokenization flow
    TokenizeCardBatch,
    /// Incoming Relay Webhook Receive
    IncomingRelayWebhookReceive,
    /// Generate Hypersense Token
    HypersenseTokenRequest,
    /// Verify Hypersense Token
    HypersenseVerifyToken,
    /// Signout Hypersense Token
    HypersenseSignoutToken,
    /// Payment Method Session Create
    PaymentMethodSessionCreate,
    /// Payment Method Session Retrieve
    PaymentMethodSessionRetrieve,
    // Payment Method Session Update
    PaymentMethodSessionUpdate,
    /// Update a saved payment method using the payment methods session
    PaymentMethodSessionUpdateSavedPaymentMethod,
    /// Delete a saved payment method using the payment methods session
    PaymentMethodSessionDeleteSavedPaymentMethod,
    /// Confirm a payment method session with payment method data
    PaymentMethodSessionConfirm,
    /// Create Cards Info flow
    CardsInfoCreate,
    /// Update Cards Info flow
    CardsInfoUpdate,
    /// Cards Info migrate flow
    CardsInfoMigrate,
    ///Total payment method count for merchant
    TotalPaymentMethodCount,
    /// Process Tracker Revenue Recovery Workflow Retrieve
    RevenueRecoveryRetrieve,
    /// Tokenization flow
    TokenizationCreate,
    /// Tokenization retrieve flow
    TokenizationRetrieve,
    /// Clone Connector flow
    CloneConnector,
    /// Authentication Create flow
    AuthenticationCreate,
    /// Authentication Eligibility flow
    AuthenticationEligibility,
    /// Authentication Sync flow
    AuthenticationSync,
    /// Authentication Sync Post Update flow
    AuthenticationSyncPostUpdate,
    /// Authentication Authenticate flow
    AuthenticationAuthenticate,
    ///Proxy Flow
    Proxy,
    /// Profile Acquirer Create flow
    ProfileAcquirerCreate,
    /// Profile Acquirer Update flow
    ProfileAcquirerUpdate,
    /// ThreeDs Decision Rule Execute flow
    ThreeDsDecisionRuleExecute,
    /// Incoming Network Token Webhook Receive
    IncomingNetworkTokenWebhookReceive,
    /// Decision Engine Decide Gateway Call
    DecisionEngineDecideGatewayCall,
    /// Decision Engine Gateway Feedback Call
    DecisionEngineGatewayFeedbackCall,
    /// Recovery payments create flow.
    RecoveryPaymentsCreate,
    /// Tokenization delete flow
    TokenizationDelete,
}

/// Trait for providing generic behaviour to flow metric
pub trait FlowMetric: ToString + std::fmt::Debug + Clone {}
impl FlowMetric for Flow {}

/// Category of log event.
#[derive(Debug)]
pub enum Category {
    /// Redis: general.
    Redis,
    /// API: general.
    Api,
    /// Database: general.
    Store,
    /// Event: general.
    Event,
    /// General: general.
    General,
}


pub struct Coupons {
    pub allow: Option<Vec<Secret<String>>>,
}


pub struct ChallengeSuccessCount;


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

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

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

impl ConnectorSpecifications for for Novalnet


OpenAPI Block Path: components.schemas.StripeChargeResponseData
{
  "type": "object",
  "description": "Fee information to be charged on the payment being collected via Stripe",
  "required": [
    "charge_type",
    "application_fees",
    "transfer_account_id"
  ],
  "properties": {
    "charge_id": {
      "type": "string",
      "description": "Identifier for charge created for the payment",
      "nullable": true
    },
    "charge_type": {
      "$ref": "#/components/schemas/PaymentChargeType"
    },
    "application_fees": {
      "type": "integer",
      "format": "int64",
      "description": "Platform fees collected on the payment",
      "example": 6540
    },
    "transfer_account_id": {
      "type": "string",
      "description": "Identifier for the reseller's account where the funds were transferred"
    }
  },
  "additionalProperties": false
}


pub struct SecureAcceptance {
    secure_acceptance_url: Option<url::Url>,
}


impl EphemeralKeyInterface for KafkaStore {
    #[cfg(feature = "v1")]
    async fn create_ephemeral_key(
        &self,
        ek: EphemeralKeyNew,
        validity: i64,
    ) -> CustomResult<EphemeralKey, errors::StorageError> {
        self.diesel_store.create_ephemeral_key(ek, validity).await
    }

    #[cfg(feature = "v1")]
    async fn get_ephemeral_key(
        &self,
        key: &str,
    ) -> CustomResult<EphemeralKey, errors::StorageError> {
        self.diesel_store.get_ephemeral_key(key).await
    }

    #[cfg(feature = "v1")]
    async fn delete_ephemeral_key(
        &self,
        id: &str,
    ) -> CustomResult<EphemeralKey, errors::StorageError> {
        self.diesel_store.delete_ephemeral_key(id).await
    }
}

impl EphemeralKeyInterface for for KafkaStore


pub struct PaymentsSuccessRate;


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

---
openapi: get /v2/api-keys/list
---


pub struct PayloadCancelRequest {
    pub status: responses::PayloadPaymentStatus,
}


File: crates/common_utils/src/transformers.rs

//! Utilities for converting between foreign types

/// Trait for converting from one foreign type to another
pub trait ForeignFrom<F> {
    /// Convert from a foreign type to the current type
    fn foreign_from(from: F) -> Self;
}

/// Trait for converting from one foreign type to another
pub trait ForeignTryFrom<F>: Sized {
    /// Custom error for conversion failure
    type Error;
    /// Convert from a foreign type to the current type and return an error if the conversion fails
    fn foreign_try_from(from: F) -> Result<Self, Self::Error>;
}


impl Responder {
        // safety: This shouldn't panic owing to the data type
        #[allow(clippy::expect_used)]
        let payload = json_payload
            .into_inner()
            .to_vec()
            .pop()
            .expect("Couldn't get GetPaymentMetricRequest");
        let flow = AnalyticsFlow::GetPaymentMetrics;
        Box::pin(api::server_wrap(
            flow,
            state,
            &req,
            payload,
            |state, auth: AuthenticationData, req, _| async move {
                let org_id = auth.merchant_account.get_org_id();
                let merchant_id = auth.merchant_account.get_id();
                let profile_id = auth
                    .profile_id
                    .ok_or(report!(UserErrors::JwtProfileIdMissing))
                    .change_context(AnalyticsError::AccessForbiddenError)?;
                let auth: AuthInfo = AuthInfo::ProfileLevel {
                    org_id: org_id.clone(),
                    merchant_id: merchant_id.clone(),
                    profile_ids: vec![profile_id.clone()],
                };

                let validator_response = request_validator(
                    AnalyticsRequest {
                        payment_attempt: Some(req.clone()),
                        ..Default::default()
                    },
                    &state,
                )
                .await?;
                let ex_rates = validator_response;
                analytics::payments::get_metrics(&state.pool, &ex_rates, &auth, req)
                    .await
                    .map(ApplicationResponse::Json)
            },
            &auth::JWTAuth {
                permission: Permission::ProfileAnalyticsRead,
            },
            api_locking::LockAction::NotApplicable,
        ))
        .await
    }


pub struct MultisafepayRefundRequest {
    pub currency: enums::Currency,
    pub amount: MinorUnit,
    pub description: Option<String>,
    pub refund_order_id: Option<String>,
    pub checkout_data: Option<ShoppingCart>,
}


pub async fn ephemeral_key_delete(
    state: web::Data<AppState>,
    req: HttpRequest,
    path: web::Path<String>,
) -> HttpResponse {
    let flow = Flow::EphemeralKeyDelete;
    let payload = path.into_inner();
    api::server_wrap(
        flow,
        state,
        &req,
        payload,
        |state, _: auth::AuthenticationData, req, _| helpers::delete_ephemeral_key(state, req),
        &auth::HeaderAuth(auth::ApiKeyAuth {
            is_connected_allowed: false,
            is_platform_allowed: false,
        }),
        api_locking::LockAction::NotApplicable,
    )
    .await
}


pub fn new() -> &'static Self {
        &Self {
            amount_converter: &MinorUnitForConnector,
            amount_converter_webhooks: &StringMinorUnitForConnector,
        }
    }


impl api::PaymentCapture for Fiserv {}


File: crates/diesel_models/src/query/merchant_key_store.rs
 Public functions: 5

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

use super::generics;
use crate::{
    merchant_key_store::{MerchantKeyStore, MerchantKeyStoreNew},
    schema::merchant_key_store::dsl,
    PgPooledConn, StorageResult,
};

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

impl MerchantKeyStore {
    pub async fn find_by_merchant_id(
        conn: &PgPooledConn,
        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()),
        )
        .await
    }

    pub async fn delete_by_merchant_id(
        conn: &PgPooledConn,
        merchant_id: &common_utils::id_type::MerchantId,
    ) -> StorageResult<bool> {
        generics::generic_delete::<<Self as HasTable>::Table, _>(
            conn,
            dsl::merchant_id.eq(merchant_id.to_owned()),
        )
        .await
    }

    pub async fn list_multiple_key_stores(
        conn: &PgPooledConn,
        merchant_ids: Vec<common_utils::id_type::MerchantId>,
    ) -> StorageResult<Vec<Self>> {
        generics::generic_filter::<
            <Self as HasTable>::Table,
            _,
            <<Self as HasTable>::Table as diesel::Table>::PrimaryKey,
            _,
        >(
            conn,
            dsl::merchant_id.eq_any(merchant_ids),
            None,
            None,
            None,
        )
        .await
    }

    pub async fn list_all_key_stores(
        conn: &PgPooledConn,
        from: u32,
        limit: u32,
    ) -> StorageResult<Vec<Self>> {
        generics::generic_filter::<
            <Self as HasTable>::Table,
            _,
            <<Self as HasTable>::Table as diesel::Table>::PrimaryKey,
            _,
        >(
            conn,
            dsl::merchant_id.ne_all(vec!["".to_string()]),
            Some(limit.into()),
            Some(from.into()),
            None,
        )
        .await
    }
}


pub fn update_from_request(self, req: &api_models::payments::AmountDetailsUpdate) -> Self {
        Self {
            order_amount: req
                .order_amount()
                .unwrap_or(self.order_amount.into())
                .into(),
            currency: req.currency().unwrap_or(self.currency),
            shipping_cost: req.shipping_cost().or(self.shipping_cost),
            tax_details: req
                .order_tax_amount()
                .map(|order_tax_amount| TaxDetails {
                    default: Some(diesel_models::DefaultTax { order_tax_amount }),
                    payment_method_type: None,
                })
                .or(self.tax_details),
            skip_external_tax_calculation: req
                .skip_external_tax_calculation()
                .unwrap_or(self.skip_external_tax_calculation),
            skip_surcharge_calculation: req
                .skip_surcharge_calculation()
                .unwrap_or(self.skip_surcharge_calculation),
            surcharge_amount: req.surcharge_amount().or(self.surcharge_amount),
            tax_on_surcharge: req.tax_on_surcharge().or(self.tax_on_surcharge),
            amount_captured: self.amount_captured,
        }
    }


impl api::PaymentVoid for Placetopay {}

impl api::PaymentVoid for for Placetopay


pub struct AddressUpdateMems {
    pub orig: Address,
    pub update_data: AddressUpdateInternal,
}