            .is_customer_initiated_mandate_payment()
        {
            item.router_data.customer_id.as_ref().and_then(|customer| {
                let customer_id = customer.get_string_repr();
                (customer_id.len() <= MAX_ID_LENGTH).then_some(CustomerDetails {
                    id: customer_id.to_string(),
                    email: item.router_data.request.get_optional_email(),
                })
            })
        } else {
            None
        };

        Ok(Self {
            transaction_type: TransactionType::try_from(item.router_data.request.capture_method)?,
            amount: item.amount,
            currency_code: item.router_data.request.currency,
            payment: Some(PaymentDetails::CreditCard(CreditCardDetails {
                card_number: (*ccard.card_number).clone(),
                expiration_date: ccard.get_expiry_date_as_yyyymm("-"),
                card_code: Some(ccard.card_cvc.clone()),
            })),
            profile,
            order: Order {
                invoice_number: match &item.router_data.request.merchant_order_reference_id {
                    Some(merchant_order_reference_id) => {
                        if merchant_order_reference_id.len() <= MAX_ID_LENGTH {
                            merchant_order_reference_id.to_string()
                        } else {
                            get_random_string()
                        }
                    }
                    None => get_random_string(),
                },

                description: item.router_data.connector_request_reference_id.clone(),
            },
            customer,
            bill_to: item
                .router_data
                .get_optional_billing()
                .and_then(|billing_address| billing_address.address.as_ref())
                .map(|address| BillTo {
                    first_name: address.first_name.clone(),
                    last_name: address.last_name.clone(),
                    address: address.line1.clone(),
                    city: address.city.clone(),
                    state: address.state.clone(),
                    zip: address.zip.clone(),
                    country: address.country,
                }),
            user_fields: match item.router_data.request.metadata.clone() {
                Some(metadata) => Some(UserFields {
                    user_field: Vec::<UserField>::foreign_try_from(metadata)?,
                }),
                None => None,
            },
            processing_options: None,
            subsequent_auth_information: None,
            authorization_indicator_type: match item.router_data.request.capture_method {
                Some(capture_method) => Some(AuthorizationIndicator {
                    authorization_indicator: capture_method.try_into()?,
                }),
                None => None,
            },
        })
    }
}

impl
    TryFrom<(
        &AuthorizedotnetRouterData<&PaymentsAuthorizeRouterData>,
        &WalletData,
    )> for TransactionRequest
{
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        (item, wallet_data): (
            &AuthorizedotnetRouterData<&PaymentsAuthorizeRouterData>,
            &WalletData,
        ),
    ) -> Result<Self, Self::Error> {
        let profile = if item
            .router_data
            .request
            .is_customer_initiated_mandate_payment()
        {
            let connector_customer_id =
                Secret::new(item.router_data.connector_customer.clone().ok_or(
                    errors::ConnectorError::MissingConnectorRelatedTransactionID {
                        id: "connector_customer_id".to_string(),
                    },
                )?);
            Some(ProfileDetails::CreateProfileDetails(CreateProfileDetails {
                create_profile: true,
                customer_profile_id: Some(connector_customer_id),
            }))
        } else {
            None
        };

        let customer = if !item
            .router_data
            .request
            .is_customer_initiated_mandate_payment()
        {
            item.router_data.customer_id.as_ref().and_then(|customer| {
                let customer_id = customer.get_string_repr();
                (customer_id.len() <= MAX_ID_LENGTH).then_some(CustomerDetails {
                    id: customer_id.to_string(),
                    email: item.router_data.request.get_optional_email(),
                })
            })
        } else {
            None
        };

        Ok(Self {
            transaction_type: TransactionType::try_from(item.router_data.request.capture_method)?,
            amount: item.amount,
            currency_code: item.router_data.request.currency,
            payment: Some(get_wallet_data(
                wallet_data,
                &item.router_data.request.complete_authorize_url,
            )?),
            profile,
            order: Order {
                invoice_number: match &item.router_data.request.merchant_order_reference_id {
                    Some(merchant_order_reference_id) => {
                        if merchant_order_reference_id.len() <= MAX_ID_LENGTH {
                            merchant_order_reference_id.to_string()
                        } else {
                            get_random_string()
                        }
                    }
                    None => get_random_string(),
                },

                description: item.router_data.connector_request_reference_id.clone(),
            },
            customer,
            bill_to: item
                .router_data
                .get_optional_billing()
                .and_then(|billing_address| billing_address.address.as_ref())
                .map(|address| BillTo {
                    first_name: address.first_name.clone(),
                    last_name: address.last_name.clone(),
                    address: address.line1.clone(),
                    city: address.city.clone(),
                    state: address.state.clone(),
                    zip: address.zip.clone(),
                    country: address.country,
                }),
            user_fields: match item.router_data.request.metadata.clone() {
                Some(metadata) => Some(UserFields {
                    user_field: Vec::<UserField>::foreign_try_from(metadata)?,
                }),
                None => None,
            },
            processing_options: None,
            subsequent_auth_information: None,
            authorization_indicator_type: match item.router_data.request.capture_method {
                Some(capture_method) => Some(AuthorizationIndicator {
                    authorization_indicator: capture_method.try_into()?,
                }),
                None => None,
            },
        })
    }
}

impl TryFrom<&PaymentsCancelRouterData> for CancelOrCaptureTransactionRequest {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(item: &PaymentsCancelRouterData) -> Result<Self, Self::Error> {
        let transaction_request = TransactionVoidOrCaptureRequest {
            amount: None, //amount is not required for void
            transaction_type: TransactionType::Void,
            ref_trans_id: item.request.connector_transaction_id.to_string(),
        };

        let merchant_authentication = AuthorizedotnetAuthType::try_from(&item.connector_auth_type)?;

        Ok(Self {
            create_transaction_request: AuthorizedotnetPaymentCancelOrCaptureRequest {
                merchant_authentication,
                transaction_request,
            },
        })
    }
}

impl TryFrom<&AuthorizedotnetRouterData<&PaymentsCaptureRouterData>>
    for CancelOrCaptureTransactionRequest
{
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: &AuthorizedotnetRouterData<&PaymentsCaptureRouterData>,
    ) -> Result<Self, Self::Error> {
        let transaction_request = TransactionVoidOrCaptureRequest {
            amount: Some(item.amount),
            transaction_type: TransactionType::Capture,
            ref_trans_id: item
                .router_data
                .request
                .connector_transaction_id
                .to_string(),
        };

        let merchant_authentication =
            AuthorizedotnetAuthType::try_from(&item.router_data.connector_auth_type)?;

        Ok(Self {
            create_transaction_request: AuthorizedotnetPaymentCancelOrCaptureRequest {
                merchant_authentication,
                transaction_request,
            },
        })
    }
}

#[derive(Debug, Clone, Default, serde::Deserialize, serde::Serialize)]
pub enum AuthorizedotnetPaymentStatus {
    #[serde(rename = "1")]
    Approved,
    #[serde(rename = "2")]
    Declined,
    #[serde(rename = "3")]
    Error,
    #[serde(rename = "4")]
    #[default]
    HeldForReview,
    #[serde(rename = "5")]
    RequiresAction,
}

#[derive(Debug, Clone, serde::Deserialize, Serialize)]
pub enum AuthorizedotnetRefundStatus {
    #[serde(rename = "1")]
    Approved,
    #[serde(rename = "2")]
    Declined,
    #[serde(rename = "3")]
    Error,
    #[serde(rename = "4")]
    HeldForReview,
}

fn get_payment_status(
    (item, auto_capture): (AuthorizedotnetPaymentStatus, bool),
) -> enums::AttemptStatus {
    match item {
        AuthorizedotnetPaymentStatus::Approved => {
            if auto_capture {
                enums::AttemptStatus::Charged
            } else {
                enums::AttemptStatus::Authorized
            }
        }
        AuthorizedotnetPaymentStatus::Declined | AuthorizedotnetPaymentStatus::Error => {
            enums::AttemptStatus::Failure
        }
        AuthorizedotnetPaymentStatus::RequiresAction => enums::AttemptStatus::AuthenticationPending,
        AuthorizedotnetPaymentStatus::HeldForReview => enums::AttemptStatus::Pending,
    }
}

#[derive(Debug, Default, Clone, Deserialize, PartialEq, Serialize)]
pub struct ResponseMessage {
    code: String,
    pub text: String,
}

#[derive(Debug, Default, Clone, Deserialize, PartialEq, Serialize, strum::Display)]
enum ResultCode {
    #[default]
    Ok,
    Error,
}

#[derive(Debug, Default, Clone, Deserialize, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ResponseMessages {
    result_code: ResultCode,
    pub message: Vec<ResponseMessage>,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ErrorMessage {
    pub error_code: String,
    pub error_text: String,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(untagged)]
pub enum TransactionResponse {
    AuthorizedotnetTransactionResponse(Box<AuthorizedotnetTransactionResponse>),
    AuthorizedotnetTransactionResponseError(Box<AuthorizedotnetTransactionResponseError>),
}

#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(rename_all = "PascalCase")]
pub struct AuthorizedotnetTransactionResponseError {
    _supplemental_data_qualification_indicator: i64,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct AuthorizedotnetTransactionResponse {
    response_code: AuthorizedotnetPaymentStatus,
    #[serde(rename = "transId")]
    transaction_id: String,
    network_trans_id: Option<Secret<String>>,
    pub(super) account_number: Option<Secret<String>>,
    pub(super) errors: Option<Vec<ErrorMessage>>,
    secure_acceptance: Option<SecureAcceptance>,
    avs_result_code: Option<String>,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct RefundResponse {
    response_code: AuthorizedotnetRefundStatus,
    #[serde(rename = "transId")]
    transaction_id: String,
    #[allow(dead_code)]
    network_trans_id: Option<Secret<String>>,
    pub account_number: Option<Secret<String>>,
    pub errors: Option<Vec<ErrorMessage>>,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(rename_all = "PascalCase")]
pub struct SecureAcceptance {
    secure_acceptance_url: Option<url::Url>,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct AuthorizedotnetPaymentsResponse {
    pub transaction_response: Option<TransactionResponse>,
    pub profile_response: Option<AuthorizedotnetNonZeroMandateResponse>,
    pub messages: ResponseMessages,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct AuthorizedotnetNonZeroMandateResponse {
    customer_profile_id: Option<String>,
    customer_payment_profile_id_list: Option<Vec<String>>,
    pub messages: ResponseMessages,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct AuthorizedotnetVoidResponse {
    pub transaction_response: Option<VoidResponse>,
    pub messages: ResponseMessages,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct VoidResponse {
    response_code: AuthorizedotnetVoidStatus,
    #[serde(rename = "transId")]
    transaction_id: String,
    network_trans_id: Option<Secret<String>>,
    pub account_number: Option<Secret<String>>,
    pub errors: Option<Vec<ErrorMessage>>,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
pub enum AuthorizedotnetVoidStatus {
    #[serde(rename = "1")]
    Approved,
    #[serde(rename = "2")]
    Declined,
    #[serde(rename = "3")]
    Error,
    #[serde(rename = "4")]
    HeldForReview,
}

impl From<AuthorizedotnetVoidStatus> for enums::AttemptStatus {
    fn from(item: AuthorizedotnetVoidStatus) -> Self {
        match item {
            AuthorizedotnetVoidStatus::Approved => Self::Voided,
            AuthorizedotnetVoidStatus::Declined | AuthorizedotnetVoidStatus::Error => {
                Self::VoidFailed
            }
            AuthorizedotnetVoidStatus::HeldForReview => Self::VoidInitiated,
        }
    }
}

fn get_avs_response_description(code: &str) -> Option<&'static str> {
    match code {
        "A" => Some("The street address matched, but the postal code did not."),
        "B" => Some("No address information was provided."),
        "E" => Some(
            "AVS data provided is invalid or AVS is not allowed for the card type that was used.",
        ),
        "G" => Some("The card was issued by a bank outside the U.S. and does not support AVS."),
        "N" => Some("Neither the street address nor postal code matched."),
        "P" => Some("AVS is not applicable for this transaction."),
        "R" => Some("Retry — AVS was unavailable or timed out."),
        "S" => Some("AVS is not supported by card issuer."),
        "U" => Some("Address information is unavailable."),
        "W" => Some("The US ZIP+4 code matches, but the street address does not."),
        "X" => Some("Both the street address and the US ZIP+4 code matched."),
        "Y" => Some("The street address and postal code matched."),
        "Z" => Some("The postal code matched, but the street address did not."),
        _ => None,
    }
}

fn convert_to_additional_payment_method_connector_response(
    transaction_response: &AuthorizedotnetTransactionResponse,
) -> Option<AdditionalPaymentMethodConnectorResponse> {
    match transaction_response.avs_result_code.as_deref() {
        Some("P") | None => None,
        Some(code) => {
            let description = get_avs_response_description(code);
            let payment_checks = serde_json::json!({
                "avs_result_code": code,
                "description": description
            });
            Some(AdditionalPaymentMethodConnectorResponse::Card {
                authentication_data: None,
                payment_checks: Some(payment_checks),
                card_network: None,
                domestic_network: None,
            })
        }
    }
}

impl<F, T>
    ForeignTryFrom<(
        ResponseRouterData<F, AuthorizedotnetPaymentsResponse, T, PaymentsResponseData>,
        bool,
    )> for RouterData<F, T, PaymentsResponseData>
{
    type Error = error_stack::Report<errors::ConnectorError>;
    fn foreign_try_from(
        (item, is_auto_capture): (
            ResponseRouterData<F, AuthorizedotnetPaymentsResponse, T, PaymentsResponseData>,
            bool,
        ),
    ) -> Result<Self, Self::Error> {
        match &item.response.transaction_response {
            Some(TransactionResponse::AuthorizedotnetTransactionResponse(transaction_response)) => {
                let status = get_payment_status((
                    transaction_response.response_code.clone(),
                    is_auto_capture,
                ));
                let error = transaction_response.errors.as_ref().and_then(|errors| {
                    errors.iter().next().map(|error| ErrorResponse {
                        code: error.error_code.clone(),
                        message: error.error_text.clone(),
                        reason: Some(error.error_text.clone()),
                        status_code: item.http_code,
                        attempt_status: None,
                        connector_transaction_id: Some(transaction_response.transaction_id.clone()),
                        network_advice_code: None,
                        network_decline_code: None,
                        network_error_message: None,
                        connector_metadata: None,
                    })
                });
                let metadata = transaction_response
                    .account_number
                    .as_ref()
                    .map(|acc_no| {
                        construct_refund_payment_details(PaymentDetailAccountNumber::Masked(
                            acc_no.clone().expose(),
                        ))
                        .encode_to_value()
                    })
                    .transpose()
                    .change_context(errors::ConnectorError::MissingRequiredField {
                        field_name: "connector_metadata",
                    })?;

                let connector_response_data =
                    convert_to_additional_payment_method_connector_response(transaction_response)
                        .map(ConnectorResponseData::with_additional_payment_method_data);

                let url = transaction_response
                    .secure_acceptance
                    .as_ref()
                    .and_then(|x| x.secure_acceptance_url.to_owned());
                let redirection_data = url.map(|url| RedirectForm::from((url, Method::Get)));
                let mandate_reference = item.response.profile_response.map(|profile_response| {
                    let payment_profile_id = profile_response
                        .customer_payment_profile_id_list
                        .and_then(|customer_payment_profile_id_list| {
                            customer_payment_profile_id_list.first().cloned()
                        });
                    MandateReference {
                        connector_mandate_id: profile_response.customer_profile_id.and_then(
                            |customer_profile_id| {
                                payment_profile_id.map(|payment_profile_id| {
                                    format!("{customer_profile_id}-{payment_profile_id}")
                                })
                            },
                        ),
                        payment_method_id: None,
                        mandate_metadata: None,
                        connector_mandate_request_reference_id: None,
                    }
                });

                Ok(Self {
                    status,
                    response: match error {
                        Some(err) => Err(err),
                        None => Ok(PaymentsResponseData::TransactionResponse {
                            resource_id: ResponseId::ConnectorTransactionId(
                                transaction_response.transaction_id.clone(),
                            ),
                            redirection_data: Box::new(redirection_data),
                            mandate_reference: Box::new(mandate_reference),
                            connector_metadata: metadata,
                            network_txn_id: transaction_response
                                .network_trans_id
                                .clone()
                                .map(|network_trans_id| network_trans_id.expose()),
                            connector_response_reference_id: Some(
                                transaction_response.transaction_id.clone(),
                            ),
                            incremental_authorization_allowed: None,
                            charges: None,
                        }),
                    },
                    connector_response: connector_response_data,
                    ..item.data
                })
            }
            Some(TransactionResponse::AuthorizedotnetTransactionResponseError(_)) | None => {
                Ok(Self {
                    status: enums::AttemptStatus::Failure,
                    response: Err(get_err_response(item.http_code, item.response.messages)?),
                    ..item.data
                })
            }
        }
    }
}

impl<F, T> TryFrom<ResponseRouterData<F, AuthorizedotnetVoidResponse, T, PaymentsResponseData>>
    for RouterData<F, T, PaymentsResponseData>
{
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: ResponseRouterData<F, AuthorizedotnetVoidResponse, T, PaymentsResponseData>,
    ) -> Result<Self, Self::Error> {
        match &item.response.transaction_response {
            Some(transaction_response) => {
                let status = enums::AttemptStatus::from(transaction_response.response_code.clone());
                let error = transaction_response.errors.as_ref().and_then(|errors| {
                    errors.iter().next().map(|error| ErrorResponse {
                        code: error.error_code.clone(),
                        message: error.error_text.clone(),
                        reason: Some(error.error_text.clone()),
                        status_code: item.http_code,
                        attempt_status: None,
                        connector_transaction_id: Some(transaction_response.transaction_id.clone()),
                        network_advice_code: None,
                        network_decline_code: None,
                        network_error_message: None,
                        connector_metadata: None,
                    })
                });
                let metadata = transaction_response
                    .account_number
                    .as_ref()
                    .map(|acc_no| {
                        construct_refund_payment_details(PaymentDetailAccountNumber::Masked(
                            acc_no.clone().expose(),
                        ))
                        .encode_to_value()
                    })
                    .transpose()
                    .change_context(errors::ConnectorError::MissingRequiredField {
                        field_name: "connector_metadata",
                    })?;
                Ok(Self {
                    status,
                    response: match error {
                        Some(err) => Err(err),
                        None => Ok(PaymentsResponseData::TransactionResponse {
                            resource_id: ResponseId::ConnectorTransactionId(
                                transaction_response.transaction_id.clone(),
                            ),
                            redirection_data: Box::new(None),
                            mandate_reference: Box::new(None),
                            connector_metadata: metadata,
                            network_txn_id: transaction_response
                                .network_trans_id
                                .clone()
                                .map(|network_trans_id| network_trans_id.expose()),
                            connector_response_reference_id: Some(
                                transaction_response.transaction_id.clone(),
                            ),
                            incremental_authorization_allowed: None,
                            charges: None,
                        }),
                    },
                    ..item.data
                })
            }
            None => Ok(Self {
                status: enums::AttemptStatus::Failure,
                response: Err(get_err_response(item.http_code, item.response.messages)?),
                ..item.data
            }),
        }
    }
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
struct RefundTransactionRequest {
    transaction_type: TransactionType,
    amount: FloatMajorUnit,
    currency_code: String,
    payment: PaymentDetails,
    #[serde(rename = "refTransId")]
    reference_transaction_id: String,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct AuthorizedotnetRefundRequest {
    merchant_authentication: AuthorizedotnetAuthType,
    transaction_request: RefundTransactionRequest,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
// The connector enforces field ordering, it expects fields to be in the same order as in their API documentation
pub struct CreateRefundRequest {
    create_transaction_request: AuthorizedotnetRefundRequest,
}

impl<F> TryFrom<&AuthorizedotnetRouterData<&RefundsRouterData<F>>> for CreateRefundRequest {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: &AuthorizedotnetRouterData<&RefundsRouterData<F>>,
    ) -> Result<Self, Self::Error> {
        let merchant_authentication =
            AuthorizedotnetAuthType::try_from(&item.router_data.connector_auth_type)?;

        let transaction_request = RefundTransactionRequest {
            transaction_type: TransactionType::Refund,
            amount: item.amount,
            payment: get_refund_metadata(
                &item.router_data.request.connector_metadata,
                &item.router_data.request.additional_payment_method_data,
            )?,
            currency_code: item.router_data.request.currency.to_string(),
            reference_transaction_id: item.router_data.request.connector_transaction_id.clone(),
        };

        Ok(Self {
            create_transaction_request: AuthorizedotnetRefundRequest {
                merchant_authentication,
                transaction_request,
            },
        })
    }
}

fn get_refund_metadata(
    connector_metadata: &Option<Value>,
    additional_payment_method: &Option<AdditionalPaymentData>,
) -> Result<PaymentDetails, error_stack::Report<errors::ConnectorError>> {
    let payment_details_from_metadata = connector_metadata
        .as_ref()
        .get_required_value("connector_metadata")
        .ok()
        .and_then(|value| {
            value
                .clone()
                .parse_value::<PaymentDetails>("PaymentDetails")
                .ok()
        });
    let payment_details_from_additional_payment_method = match additional_payment_method {
        Some(AdditionalPaymentData::Card(additional_card_info)) => {
            additional_card_info.last4.clone().map(|last4| {
                construct_refund_payment_details(PaymentDetailAccountNumber::UnMasked(
                    last4.to_string(),
                ))
            })
        }
        _ => None,
    };
    match (
        payment_details_from_metadata,
        payment_details_from_additional_payment_method,
    ) {
        (Some(payment_detail), _) => Ok(payment_detail),
        (_, Some(payment_detail)) => Ok(payment_detail),
        (None, None) => Err(errors::ConnectorError::MissingRequiredField {
            field_name: "payment_details",
        }
        .into()),
    }
}
impl From<AuthorizedotnetRefundStatus> for enums::RefundStatus {
    fn from(item: AuthorizedotnetRefundStatus) -> Self {
        match item {
            AuthorizedotnetRefundStatus::Declined | AuthorizedotnetRefundStatus::Error => {
                Self::Failure
            }
            AuthorizedotnetRefundStatus::Approved | AuthorizedotnetRefundStatus::HeldForReview => {
                Self::Pending
            }
        }
    }
}

#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct AuthorizedotnetRefundResponse {
    pub transaction_response: RefundResponse,
    pub messages: ResponseMessages,
}

impl<F> TryFrom<RefundsResponseRouterData<F, AuthorizedotnetRefundResponse>>
    for RefundsRouterData<F>
{
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: RefundsResponseRouterData<F, AuthorizedotnetRefundResponse>,
    ) -> Result<Self, Self::Error> {
        let transaction_response = &item.response.transaction_response;
        let refund_status = enums::RefundStatus::from(transaction_response.response_code.clone());
        let error = transaction_response.errors.clone().and_then(|errors| {
            errors.first().map(|error| ErrorResponse {
                code: error.error_code.clone(),
                message: error.error_text.clone(),
                reason: Some(error.error_text.clone()),
                status_code: item.http_code,
                attempt_status: None,
                connector_transaction_id: Some(transaction_response.transaction_id.clone()),
                network_advice_code: None,
                network_decline_code: None,
                network_error_message: None,
                connector_metadata: None,
            })
        });

        Ok(Self {
            response: match error {
                Some(err) => Err(err),
                None => Ok(RefundsResponseData {
                    connector_refund_id: transaction_response.transaction_id.clone(),
                    refund_status,
                }),
            },
            ..item.data
        })
    }
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct TransactionDetails {
    merchant_authentication: AuthorizedotnetAuthType,
    #[serde(rename = "transId")]
    transaction_id: Option<String>,
}
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct AuthorizedotnetCreateSyncRequest {
    get_transaction_details_request: TransactionDetails,
}

impl<F> TryFrom<&AuthorizedotnetRouterData<&RefundsRouterData<F>>>
    for AuthorizedotnetCreateSyncRequest
{
    type Error = error_stack::Report<errors::ConnectorError>;

    fn try_from(
        item: &AuthorizedotnetRouterData<&RefundsRouterData<F>>,
    ) -> Result<Self, Self::Error> {
        let transaction_id = item.router_data.request.get_connector_refund_id()?;
        let merchant_authentication =
            AuthorizedotnetAuthType::try_from(&item.router_data.connector_auth_type)?;

        let payload = Self {
            get_transaction_details_request: TransactionDetails {
                merchant_authentication,
                transaction_id: Some(transaction_id),
            },
        };
        Ok(payload)
    }
}

impl TryFrom<&PaymentsSyncRouterData> for AuthorizedotnetCreateSyncRequest {
    type Error = error_stack::Report<errors::ConnectorError>;

    fn try_from(item: &PaymentsSyncRouterData) -> Result<Self, Self::Error> {
        let transaction_id = Some(
            item.request
                .get_connector_transaction_id()
                .change_context(errors::ConnectorError::MissingConnectorTransactionID)?,
        );

        let merchant_authentication = AuthorizedotnetAuthType::try_from(&item.connector_auth_type)?;

        let payload = Self {
            get_transaction_details_request: TransactionDetails {
                merchant_authentication,
                transaction_id,
            },
        };
        Ok(payload)
    }
}

#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub enum SyncStatus {
    RefundSettledSuccessfully,
    RefundPendingSettlement,
    AuthorizedPendingCapture,
    CapturedPendingSettlement,
    SettledSuccessfully,
    Declined,
    Voided,
    CouldNotVoid,
    GeneralError,
    #[serde(rename = "FDSPendingReview")]
    FDSPendingReview,
}

#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub enum RSyncStatus {
    RefundSettledSuccessfully,
    RefundPendingSettlement,
    Declined,
    GeneralError,
    Voided,
}

#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SyncTransactionResponse {
    #[serde(rename = "transId")]
    transaction_id: String,
    transaction_status: SyncStatus,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct AuthorizedotnetSyncResponse {
    transaction: Option<SyncTransactionResponse>,
    messages: ResponseMessages,
}

#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct RSyncTransactionResponse {
    #[serde(rename = "transId")]
    transaction_id: String,
    transaction_status: RSyncStatus,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct AuthorizedotnetRSyncResponse {
    transaction: Option<RSyncTransactionResponse>,
    messages: ResponseMessages,
}

impl From<SyncStatus> for enums::AttemptStatus {
    fn from(transaction_status: SyncStatus) -> Self {
        match transaction_status {
            SyncStatus::SettledSuccessfully | SyncStatus::CapturedPendingSettlement => {
                Self::Charged
            }
            SyncStatus::AuthorizedPendingCapture => Self::Authorized,
            SyncStatus::Declined => Self::AuthenticationFailed,
            SyncStatus::Voided => Self::Voided,
            SyncStatus::CouldNotVoid => Self::VoidFailed,
            SyncStatus::GeneralError => Self::Failure,
            SyncStatus::RefundSettledSuccessfully
            | SyncStatus::RefundPendingSettlement
            | SyncStatus::FDSPendingReview => Self::Pending,
        }
    }
}

impl From<RSyncStatus> for enums::RefundStatus {
    fn from(transaction_status: RSyncStatus) -> Self {
        match transaction_status {
            RSyncStatus::RefundSettledSuccessfully => Self::Success,
            RSyncStatus::RefundPendingSettlement => Self::Pending,
            RSyncStatus::Declined | RSyncStatus::GeneralError | RSyncStatus::Voided => {
                Self::Failure
            }
        }
    }
}

impl TryFrom<RefundsResponseRouterData<RSync, AuthorizedotnetRSyncResponse>>
    for RefundsRouterData<RSync>
{
    type Error = error_stack::Report<errors::ConnectorError>;

    fn try_from(
        item: RefundsResponseRouterData<RSync, AuthorizedotnetRSyncResponse>,
    ) -> Result<Self, Self::Error> {
        match item.response.transaction {
            Some(transaction) => {
                let refund_status = enums::RefundStatus::from(transaction.transaction_status);
                Ok(Self {
                    response: Ok(RefundsResponseData {
                        connector_refund_id: transaction.transaction_id,
                        refund_status,
                    }),
                    ..item.data
                })
            }
            None => Ok(Self {
                response: Err(get_err_response(item.http_code, item.response.messages)?),
                ..item.data
            }),
        }
    }
}

impl<F, Req> TryFrom<ResponseRouterData<F, AuthorizedotnetSyncResponse, Req, PaymentsResponseData>>
    for RouterData<F, Req, PaymentsResponseData>
{
    type Error = error_stack::Report<errors::ConnectorError>;

    fn try_from(
        item: ResponseRouterData<F, AuthorizedotnetSyncResponse, Req, PaymentsResponseData>,
    ) -> Result<Self, Self::Error> {
        match item.response.transaction {
            Some(transaction) => {
                let payment_status = enums::AttemptStatus::from(transaction.transaction_status);
                Ok(Self {
                    response: Ok(PaymentsResponseData::TransactionResponse {
                        resource_id: ResponseId::ConnectorTransactionId(
                            transaction.transaction_id.clone(),
                        ),
                        redirection_data: Box::new(None),
                        mandate_reference: Box::new(None),
                        connector_metadata: None,
                        network_txn_id: None,
                        connector_response_reference_id: Some(transaction.transaction_id.clone()),
                        incremental_authorization_allowed: None,
                        charges: None,
                    }),
                    status: payment_status,
                    ..item.data
                })
            }

            // E00053 indicates "server too busy"
            // If the server is too busy, we return the already available data
            None => match item
                .response
                .messages
                .message
                .iter()
                .find(|msg| msg.code == "E00053")
            {
                Some(_) => Ok(item.data),
                None => Ok(Self {
                    response: Err(get_err_response(item.http_code, item.response.messages)?),
                    ..item.data
                }),
            },
        }
    }
}

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

#[derive(Default, Debug, Deserialize, Serialize)]
pub struct AuthorizedotnetErrorResponse {
    pub error: ErrorDetails,
}
enum PaymentDetailAccountNumber {
    Masked(String),
    UnMasked(String),
}
fn construct_refund_payment_details(detail: PaymentDetailAccountNumber) -> PaymentDetails {
    PaymentDetails::CreditCard(CreditCardDetails {
        card_number: match detail {
            PaymentDetailAccountNumber::Masked(masked) => masked.into(),
            PaymentDetailAccountNumber::UnMasked(unmasked) => format!("XXXX{:}", unmasked).into(),
        },
        expiration_date: "XXXX".to_string().into(),
        card_code: None,
    })
}

impl TryFrom<Option<enums::CaptureMethod>> for TransactionType {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(capture_method: Option<enums::CaptureMethod>) -> Result<Self, Self::Error> {
        match capture_method {
            Some(enums::CaptureMethod::Manual) => Ok(Self::Authorization),
            Some(enums::CaptureMethod::SequentialAutomatic)
            | Some(enums::CaptureMethod::Automatic)
            | None => Ok(Self::Payment),
            Some(enums::CaptureMethod::ManualMultiple) => {
                Err(utils::construct_not_supported_error_report(
                    enums::CaptureMethod::ManualMultiple,
                    "authorizedotnet",
                ))?
            }
            Some(enums::CaptureMethod::Scheduled) => {
                Err(utils::construct_not_supported_error_report(
                    enums::CaptureMethod::Scheduled,
                    "authorizedotnet",
                ))?
            }
        }
    }
}

fn get_err_response(
    status_code: u16,
    message: ResponseMessages,
) -> Result<ErrorResponse, errors::ConnectorError> {
    let response_message = message
        .message
        .first()
        .ok_or(errors::ConnectorError::ResponseDeserializationFailed)?;
    Ok(ErrorResponse {
        code: response_message.code.clone(),
        message: response_message.text.clone(),
        reason: Some(response_message.text.clone()),
        status_code,
        attempt_status: None,
        connector_transaction_id: None,
        network_advice_code: None,
        network_decline_code: None,
        network_error_message: None,
        connector_metadata: None,
    })
}

#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AuthorizedotnetWebhookObjectId {
    pub webhook_id: String,
    pub event_type: AuthorizedotnetWebhookEvent,
    pub payload: AuthorizedotnetWebhookPayload,
}

#[derive(Debug, Deserialize)]
pub struct AuthorizedotnetWebhookPayload {
    pub id: Option<String>,
}

#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AuthorizedotnetWebhookEventType {
    pub event_type: AuthorizedotnetIncomingWebhookEventType,
}

#[derive(Debug, Deserialize)]
pub enum AuthorizedotnetWebhookEvent {
    #[serde(rename = "net.authorize.payment.authorization.created")]
    AuthorizationCreated,
    #[serde(rename = "net.authorize.payment.priorAuthCapture.created")]
    PriorAuthCapture,
    #[serde(rename = "net.authorize.payment.authcapture.created")]
    AuthCapCreated,
    #[serde(rename = "net.authorize.payment.capture.created")]
    CaptureCreated,
    #[serde(rename = "net.authorize.payment.void.created")]
    VoidCreated,
    #[serde(rename = "net.authorize.payment.refund.created")]
    RefundCreated,
}
///Including Unknown to map unknown webhook events
#[derive(Debug, Deserialize)]
pub enum AuthorizedotnetIncomingWebhookEventType {
    #[serde(rename = "net.authorize.payment.authorization.created")]
    AuthorizationCreated,
    #[serde(rename = "net.authorize.payment.priorAuthCapture.created")]
    PriorAuthCapture,
    #[serde(rename = "net.authorize.payment.authcapture.created")]
    AuthCapCreated,
    #[serde(rename = "net.authorize.payment.capture.created")]
    CaptureCreated,
    #[serde(rename = "net.authorize.payment.void.created")]
    VoidCreated,
    #[serde(rename = "net.authorize.payment.refund.created")]
    RefundCreated,
    #[serde(other)]
    Unknown,
}

impl From<AuthorizedotnetIncomingWebhookEventType> for IncomingWebhookEvent {
    fn from(event_type: AuthorizedotnetIncomingWebhookEventType) -> Self {
        match event_type {
            AuthorizedotnetIncomingWebhookEventType::AuthorizationCreated
            | AuthorizedotnetIncomingWebhookEventType::PriorAuthCapture
            | AuthorizedotnetIncomingWebhookEventType::AuthCapCreated
            | AuthorizedotnetIncomingWebhookEventType::CaptureCreated
            | AuthorizedotnetIncomingWebhookEventType::VoidCreated => Self::PaymentIntentSuccess,
            AuthorizedotnetIncomingWebhookEventType::RefundCreated => Self::RefundSuccess,
            AuthorizedotnetIncomingWebhookEventType::Unknown => Self::EventNotSupported,
        }
    }
}

impl From<AuthorizedotnetWebhookEvent> for SyncStatus {
    // status mapping reference https://developer.authorize.net/api/reference/features/webhooks.html#Event_Types_and_Payloads
    fn from(event_type: AuthorizedotnetWebhookEvent) -> Self {
        match event_type {
            AuthorizedotnetWebhookEvent::AuthorizationCreated => Self::AuthorizedPendingCapture,
            AuthorizedotnetWebhookEvent::CaptureCreated
            | AuthorizedotnetWebhookEvent::AuthCapCreated => Self::CapturedPendingSettlement,
            AuthorizedotnetWebhookEvent::PriorAuthCapture => Self::SettledSuccessfully,
            AuthorizedotnetWebhookEvent::VoidCreated => Self::Voided,


// File: crates/hyperswitch_connectors/src/connectors/stripe.rs
// Module: hyperswitch_connectors
// Public structs: 1

pub mod transformers;

use std::{collections::HashMap, sync::LazyLock};

use api_models::webhooks::IncomingWebhookEvent;
use common_enums::{
    CallConnectorAction, CaptureMethod, PaymentAction, PaymentChargeType, PaymentMethodType,
    PaymentResourceUpdateStatus, StripeChargeType,
};
use common_utils::{
    crypto,
    errors::CustomResult,
    ext_traits::{ByteSliceExt as _, BytesExt},
    request::{Method, Request, RequestBuilder, RequestContent},
    types::{
        AmountConvertor, MinorUnit, MinorUnitForConnector, StringMinorUnit,
        StringMinorUnitForConnector,
    },
};
use error_stack::ResultExt;
use hyperswitch_domain_models::{
    payment_method_data::PaymentMethodData,
    router_data::{AccessToken, ConnectorAuthType, ErrorResponse, RouterData},
    router_flow_types::{
        AccessTokenAuth, Authorize, Capture, CreateConnectorCustomer, Evidence, Execute,
        IncrementalAuthorization, PSync, PaymentMethodToken, RSync, Retrieve, Session,
        SetupMandate, UpdateMetadata, Upload, Void,
    },
    router_request_types::{
        AccessTokenRequestData, ConnectorCustomerData, PaymentMethodTokenizationData,
        PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData,
        PaymentsIncrementalAuthorizationData, PaymentsSessionData, PaymentsSyncData,
        PaymentsUpdateMetadataData, RefundsData, RetrieveFileRequestData, SetupMandateRequestData,
        SplitRefundsRequest, SubmitEvidenceRequestData, UploadFileRequestData,
    },
    router_response_types::{
        ConnectorInfo, PaymentMethodDetails, PaymentsResponseData, RefundsResponseData,
        RetrieveFileResponse, SubmitEvidenceResponse, SupportedPaymentMethods,
        SupportedPaymentMethodsExt, UploadFileResponse,
    },
    types::{
        ConnectorCustomerRouterData, PaymentsAuthorizeRouterData, PaymentsCancelRouterData,
        PaymentsCaptureRouterData, PaymentsIncrementalAuthorizationRouterData,
        PaymentsSyncRouterData, PaymentsUpdateMetadataRouterData, RefundsRouterData,
        TokenizationRouterData,
    },
};
#[cfg(feature = "payouts")]
use hyperswitch_domain_models::{
    router_flow_types::{PoCancel, PoCreate, PoFulfill, PoRecipient, PoRecipientAccount},
    types::{PayoutsData, PayoutsResponseData, PayoutsRouterData},
};
#[cfg(feature = "payouts")]
use hyperswitch_interfaces::types::{
    PayoutCancelType, PayoutCreateType, PayoutFulfillType, PayoutRecipientAccountType,
    PayoutRecipientType,
};
use hyperswitch_interfaces::{
    api::{
        self,
        disputes::SubmitEvidence,
        files::{FilePurpose, FileUpload, RetrieveFile, UploadFile},
        ConnectorCommon, ConnectorCommonExt, ConnectorIntegration, ConnectorRedirectResponse,
        ConnectorSpecifications, ConnectorValidation, PaymentIncrementalAuthorization,
    },
    configs::Connectors,
    consts::{NO_ERROR_CODE, NO_ERROR_MESSAGE},
    disputes::DisputePayload,
    errors::ConnectorError,
    events::connector_api_logs::ConnectorEvent,
    types::{
        ConnectorCustomerType, IncrementalAuthorizationType, PaymentsAuthorizeType,
        PaymentsCaptureType, PaymentsSyncType, PaymentsUpdateMetadataType, PaymentsVoidType,
        RefundExecuteType, RefundSyncType, Response, RetrieveFileType, SubmitEvidenceType,
        TokenizationType, UploadFileType,
    },
    webhooks::{IncomingWebhook, IncomingWebhookRequestDetails},
};
use masking::{Mask as _, Maskable, PeekInterface};
use router_env::{instrument, tracing};
use stripe::auth_headers;

use self::transformers as stripe;
#[cfg(feature = "payouts")]
use crate::utils::{PayoutsData as OtherPayoutsData, RouterData as OtherRouterData};
use crate::{
    constants::headers::{AUTHORIZATION, CONTENT_TYPE, STRIPE_COMPATIBLE_CONNECT_ACCOUNT},
    types::{
        ResponseRouterData, RetrieveFileRouterData, SubmitEvidenceRouterData, UploadFileRouterData,
    },
    utils::{
        self, get_authorise_integrity_object, get_capture_integrity_object,
        get_refund_integrity_object, get_sync_integrity_object, PaymentMethodDataType,
        RefundsRequestData as OtherRefundsRequestData,
    },
};
#[derive(Clone)]
pub struct Stripe {
    amount_converter: &'static (dyn AmountConvertor<Output = MinorUnit> + Sync),
    amount_converter_webhooks: &'static (dyn AmountConvertor<Output = StringMinorUnit> + Sync),
}

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

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

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

    fn common_get_content_type(&self) -> &'static str {
        "application/x-www-form-urlencoded"
    }

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

    fn get_auth_header(
        &self,
        auth_type: &ConnectorAuthType,
    ) -> CustomResult<Vec<(String, Maskable<String>)>, ConnectorError> {
        let auth = stripe::StripeAuthType::try_from(auth_type)
            .change_context(ConnectorError::FailedToObtainAuthType)?;
        Ok(vec![
            (
                AUTHORIZATION.to_string(),
                format!("Bearer {}", auth.api_key.peek()).into_masked(),
            ),
            (
                auth_headers::STRIPE_API_VERSION.to_string(),
                auth_headers::STRIPE_VERSION.to_string().into_masked(),
            ),
        ])
    }

    #[cfg(feature = "payouts")]
    fn build_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, ConnectorError> {
        use hyperswitch_interfaces::consts::NO_ERROR_CODE;

        let response: stripe::StripeConnectErrorResponse = res
            .response
            .parse_struct("StripeConnectErrorResponse")
            .change_context(ConnectorError::ResponseDeserializationFailed)?;
        event_builder.map(|i| i.set_error_response_body(&response));
        Ok(ErrorResponse {
            status_code: res.status_code,
            code: response
                .error
                .code
                .clone()
                .unwrap_or_else(|| NO_ERROR_CODE.to_string()),
            message: response
                .error
                .code
                .unwrap_or_else(|| NO_ERROR_MESSAGE.to_string()),
            reason: response.error.message,
            attempt_status: None,
            connector_transaction_id: response.error.payment_intent.map(|pi| pi.id),
            network_advice_code: response.error.network_advice_code,
            network_decline_code: response.error.network_decline_code,
            network_error_message: response.error.decline_code.or(response.error.advice_code),
            connector_metadata: None,
        })
    }
}

impl ConnectorValidation for Stripe {
    fn validate_connector_against_payment_request(
        &self,
        capture_method: Option<CaptureMethod>,
        _payment_method: common_enums::PaymentMethod,
        _pmt: Option<PaymentMethodType>,
    ) -> CustomResult<(), ConnectorError> {
        let capture_method = capture_method.unwrap_or_default();
        match capture_method {
            CaptureMethod::SequentialAutomatic
            | CaptureMethod::Automatic
            | CaptureMethod::Manual => Ok(()),
            CaptureMethod::ManualMultiple | CaptureMethod::Scheduled => Err(
                utils::construct_not_supported_error_report(capture_method, self.id()),
            ),
        }
    }

    fn validate_mandate_payment(
        &self,
        pm_type: Option<PaymentMethodType>,
        pm_data: PaymentMethodData,
    ) -> CustomResult<(), ConnectorError> {
        let mandate_supported_pmd = std::collections::HashSet::from([
            PaymentMethodDataType::Card,
            PaymentMethodDataType::ApplePay,
            PaymentMethodDataType::GooglePay,
            PaymentMethodDataType::AchBankDebit,
            PaymentMethodDataType::BacsBankDebit,
            PaymentMethodDataType::BecsBankDebit,
            PaymentMethodDataType::SepaBankDebit,
            PaymentMethodDataType::Sofort,
            PaymentMethodDataType::Ideal,
            PaymentMethodDataType::BancontactCard,
        ]);
        utils::is_mandate_supported(pm_data, pm_type, mandate_supported_pmd, self.id())
    }
}

impl api::Payment for Stripe {}

impl api::PaymentAuthorize for Stripe {}
impl api::PaymentUpdateMetadata for Stripe {}
impl api::PaymentSync for Stripe {}
impl api::PaymentVoid for Stripe {}
impl api::PaymentCapture for Stripe {}
impl api::PaymentSession for Stripe {}
impl api::ConnectorAccessToken for Stripe {}

impl ConnectorIntegration<AccessTokenAuth, AccessTokenRequestData, AccessToken> for Stripe {
    // Not Implemented (R)
}

impl ConnectorIntegration<Session, PaymentsSessionData, PaymentsResponseData> for Stripe {
    // Not Implemented (R)
}

impl api::ConnectorCustomer for Stripe {}

impl ConnectorIntegration<CreateConnectorCustomer, ConnectorCustomerData, PaymentsResponseData>
    for Stripe
{
    fn get_headers(
        &self,
        req: &ConnectorCustomerRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<Vec<(String, Maskable<String>)>, ConnectorError> {
        let mut header = vec![(
            CONTENT_TYPE.to_string(),
            ConnectorCustomerType::get_content_type(self)
                .to_string()
                .into(),
        )];
        if let Some(common_types::payments::SplitPaymentsRequest::StripeSplitPayment(
            stripe_split_payment,
        )) = &req.request.split_payments
        {
            if stripe_split_payment.charge_type
                == PaymentChargeType::Stripe(StripeChargeType::Direct)
            {
                let mut customer_account_header = vec![(
                    STRIPE_COMPATIBLE_CONNECT_ACCOUNT.to_string(),
                    stripe_split_payment
                        .transfer_account_id
                        .clone()
                        .into_masked(),
                )];
                header.append(&mut customer_account_header);
            }
        }
        let mut api_key = self.get_auth_header(&req.connector_auth_type)?;
        header.append(&mut api_key);
        Ok(header)
    }

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

    fn get_url(
        &self,
        _req: &ConnectorCustomerRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, ConnectorError> {
        Ok(format!("{}{}", self.base_url(connectors), "v1/customers"))
    }

    fn get_request_body(
        &self,
        req: &ConnectorCustomerRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, ConnectorError> {
        let connector_req = stripe::CustomerRequest::try_from(req)?;
        Ok(RequestContent::FormUrlEncoded(Box::new(connector_req)))
    }

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

    fn handle_response(
        &self,
        data: &ConnectorCustomerRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<ConnectorCustomerRouterData, ConnectorError>
    where
        PaymentsResponseData: Clone,
    {
        let response: stripe::StripeCustomerResponse = res
            .response
            .parse_struct("StripeCustomerResponse")
            .change_context(ConnectorError::ResponseDeserializationFailed)?;

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

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

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

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

        Ok(ErrorResponse {
            status_code: res.status_code,
            code: response
                .error
                .code
                .clone()
                .unwrap_or_else(|| NO_ERROR_CODE.to_string()),
            message: response
                .error
                .code
                .unwrap_or_else(|| NO_ERROR_MESSAGE.to_string()),
            reason: response.error.message.map(|message| {
                response
                    .error
                    .decline_code
                    .clone()
                    .map(|decline_code| {
                        format!("message - {message}, decline_code - {decline_code}")
                    })
                    .unwrap_or(message)
            }),
            attempt_status: None,
            connector_transaction_id: response.error.payment_intent.map(|pi| pi.id),
            network_advice_code: response.error.network_advice_code,
            network_decline_code: response.error.network_decline_code,
            network_error_message: response.error.decline_code.or(response.error.advice_code),
            connector_metadata: None,
        })
    }
}

impl api::PaymentToken for Stripe {}

impl ConnectorIntegration<PaymentMethodToken, PaymentMethodTokenizationData, PaymentsResponseData>
    for Stripe
{
    fn get_headers(
        &self,
        req: &TokenizationRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<Vec<(String, Maskable<String>)>, ConnectorError> {
        let mut header = vec![(
            CONTENT_TYPE.to_string(),
            TokenizationType::get_content_type(self).to_string().into(),
        )];
        if let Some(common_types::payments::SplitPaymentsRequest::StripeSplitPayment(
            stripe_split_payment,
        )) = &req.request.split_payments
        {
            if stripe_split_payment.charge_type
                == PaymentChargeType::Stripe(StripeChargeType::Direct)
            {
                let mut customer_account_header = vec![(
                    STRIPE_COMPATIBLE_CONNECT_ACCOUNT.to_string(),
                    stripe_split_payment
                        .transfer_account_id
                        .clone()
                        .into_masked(),
                )];
                header.append(&mut customer_account_header);
            }
        }
        let mut api_key = self.get_auth_header(&req.connector_auth_type)?;
        header.append(&mut api_key);
        Ok(header)
    }

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

    fn get_url(
        &self,
        req: &TokenizationRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, ConnectorError> {
        if matches!(
            req.request.split_payments,
            Some(common_types::payments::SplitPaymentsRequest::StripeSplitPayment(_))
        ) {
            return Ok(format!(
                "{}{}",
                self.base_url(connectors),
                "v1/payment_methods"
            ));
        }
        Ok(format!("{}{}", self.base_url(connectors), "v1/tokens"))
    }

    fn get_request_body(
        &self,
        req: &TokenizationRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, ConnectorError> {
        let connector_req = stripe::TokenRequest::try_from(req)?;
        Ok(RequestContent::FormUrlEncoded(Box::new(connector_req)))
    }

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

    fn handle_response(
        &self,
        data: &TokenizationRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<TokenizationRouterData, ConnectorError>
    where
        PaymentsResponseData: Clone,
    {
        let response: stripe::StripeTokenResponse = res
            .response
            .parse_struct("StripeTokenResponse")
            .change_context(ConnectorError::ResponseDeserializationFailed)?;

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

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

    fn get_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, ConnectorError> {
        let response: stripe::ErrorResponse = res
            .response
            .parse_struct("ErrorResponse")
            .change_context(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
                .error
                .code
                .clone()
                .unwrap_or_else(|| NO_ERROR_CODE.to_string()),
            message: response
                .error
                .code
                .unwrap_or_else(|| NO_ERROR_MESSAGE.to_string()),
            reason: response.error.message.map(|message| {
                response
                    .error
                    .decline_code
                    .clone()
                    .map(|decline_code| {
                        format!("message - {message}, decline_code - {decline_code}")
                    })
                    .unwrap_or(message)
            }),
            attempt_status: None,
            connector_transaction_id: response.error.payment_intent.map(|pi| pi.id),
            network_advice_code: response.error.network_advice_code,
            network_decline_code: response.error.network_decline_code,
            network_error_message: response.error.decline_code.or(response.error.advice_code),
            connector_metadata: None,
        })
    }
}

impl api::MandateSetup for Stripe {}

impl ConnectorIntegration<Capture, PaymentsCaptureData, PaymentsResponseData> for Stripe {
    fn get_headers(
        &self,
        req: &PaymentsCaptureRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<Vec<(String, Maskable<String>)>, ConnectorError> {
        let mut header = vec![(
            CONTENT_TYPE.to_string(),
            Self::common_get_content_type(self).to_string().into(),
        )];
        let mut api_key = self.get_auth_header(&req.connector_auth_type)?;
        header.append(&mut api_key);
        Ok(header)
    }

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

    fn get_url(
        &self,
        req: &PaymentsCaptureRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, ConnectorError> {
        let id = req.request.connector_transaction_id.as_str();
        Ok(format!(
            "{}{}/{}/capture",
            self.base_url(connectors),
            "v1/payment_intents",
            id
        ))
    }

    fn get_request_body(
        &self,
        req: &PaymentsCaptureRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, ConnectorError> {
        let amount = utils::convert_amount(
            self.amount_converter,
            req.request.minor_amount_to_capture,
            req.request.currency,
        )?;
        let connector_req = stripe::CaptureRequest::try_from(amount)?;
        Ok(RequestContent::FormUrlEncoded(Box::new(connector_req)))
    }

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

    fn handle_response(
        &self,
        data: &PaymentsCaptureRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PaymentsCaptureRouterData, ConnectorError>
    where
        PaymentsCaptureData: Clone,
        PaymentsResponseData: Clone,
    {
        let response: stripe::PaymentIntentResponse = res
            .response
            .parse_struct("PaymentIntentResponse")
            .change_context(ConnectorError::ResponseDeserializationFailed)?;

        let response_integrity_object = get_capture_integrity_object(
            self.amount_converter,
            response.amount_received,
            response.currency.clone(),
        )?;

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

        let new_router_data = RouterData::try_from(ResponseRouterData {
            response,
            data: data.clone(),
            http_code: res.status_code,
        })
        .change_context(ConnectorError::ResponseHandlingFailed);

        new_router_data.map(|mut router_data| {
            router_data.request.integrity_object = Some(response_integrity_object);
            router_data
        })
    }

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

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

        Ok(ErrorResponse {
            status_code: res.status_code,
            code: response
                .error
                .code
                .clone()
                .unwrap_or_else(|| NO_ERROR_CODE.to_string()),
            message: response
                .error
                .code
                .unwrap_or_else(|| NO_ERROR_MESSAGE.to_string()),
            reason: response.error.message.map(|message| {
                response
                    .error
                    .decline_code
                    .clone()
                    .map(|decline_code| {
                        format!("message - {message}, decline_code - {decline_code}")
                    })
                    .unwrap_or(message)
            }),
            attempt_status: None,
            connector_transaction_id: response.error.payment_intent.map(|pi| pi.id),
            network_advice_code: response.error.network_advice_code,
            network_decline_code: response.error.network_decline_code,
            network_error_message: response.error.decline_code.or(response.error.advice_code),
            connector_metadata: None,
        })
    }
}

impl ConnectorIntegration<PSync, PaymentsSyncData, PaymentsResponseData> for Stripe {
    fn get_headers(
        &self,
        req: &PaymentsSyncRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<Vec<(String, Maskable<String>)>, ConnectorError> {
        let mut header = vec![(
            CONTENT_TYPE.to_string(),
            PaymentsSyncType::get_content_type(self).to_string().into(),
        )];
        let mut api_key = self.get_auth_header(&req.connector_auth_type)?;
        header.append(&mut api_key);

        if let Some(common_types::payments::SplitPaymentsRequest::StripeSplitPayment(
            stripe_split_payment,
        )) = &req.request.split_payments
        {
            transformers::transform_headers_for_connect_platform(
                stripe_split_payment.charge_type.clone(),
                stripe_split_payment.transfer_account_id.clone(),
                &mut header,
            );
        }
        Ok(header)
    }

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

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

        match id.get_connector_transaction_id() {
            Ok(x) if x.starts_with("set") => Ok(format!(
                "{}{}/{}?expand[0]=latest_attempt", // expand latest attempt to extract payment checks and three_d_secure data
                self.base_url(connectors),
                "v1/setup_intents",
                x,
            )),
            Ok(x) => Ok(format!(
                "{}{}/{}{}",
                self.base_url(connectors),
                "v1/payment_intents",
                x,
                "?expand[0]=latest_charge" //updated payment_id(if present) reside inside latest_charge field
            )),
            x => x.change_context(ConnectorError::MissingConnectorTransactionID),
        }
    }

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

    fn handle_response(
        &self,
        data: &PaymentsSyncRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PaymentsSyncRouterData, ConnectorError>
    where
        PaymentsResponseData: Clone,
    {
        let id = data.request.connector_transaction_id.clone();
        match id.get_connector_transaction_id() {
            Ok(x) if x.starts_with("set") => {
                let response: stripe::SetupIntentResponse = res
                    .response
                    .parse_struct("SetupIntentSyncResponse")
                    .change_context(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,
                })
            }
            Ok(_) => {
                let response: stripe::PaymentIntentSyncResponse = res
                    .response
                    .parse_struct("PaymentIntentSyncResponse")
                    .change_context(ConnectorError::ResponseDeserializationFailed)?;

                let response_integrity_object = get_sync_integrity_object(
                    self.amount_converter,
                    response.amount,
                    response.currency.clone(),
                )?;

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

                let new_router_data = RouterData::try_from(ResponseRouterData {
                    response,
                    data: data.clone(),
                    http_code: res.status_code,
                });
                new_router_data.map(|mut router_data| {
                    router_data.request.integrity_object = Some(response_integrity_object);
                    router_data
                })
            }
            Err(err) => Err(err).change_context(ConnectorError::MissingConnectorTransactionID),
        }
    }

    fn get_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, ConnectorError> {
        let response: stripe::ErrorResponse = res
            .response
            .parse_struct("ErrorResponse")
            .change_context(ConnectorError::ResponseDeserializationFailed)?;
        event_builder.map(|i| i.set_error_response_body(&response));
        router_env::logger::info!(connector_response=?response);

        Ok(ErrorResponse {
            status_code: res.status_code,
            code: response
                .error
                .code
                .clone()
                .unwrap_or_else(|| NO_ERROR_CODE.to_string()),
            message: response
                .error
                .code
                .unwrap_or_else(|| NO_ERROR_MESSAGE.to_string()),
            reason: response.error.message.map(|message| {
                response
                    .error
                    .decline_code
                    .clone()
                    .map(|decline_code| {
                        format!("message - {message}, decline_code - {decline_code}")
                    })
                    .unwrap_or(message)
            }),
            attempt_status: None,
            connector_transaction_id: response.error.payment_intent.map(|pi| pi.id),
            network_advice_code: response.error.network_advice_code,
            network_decline_code: response.error.network_decline_code,
            network_error_message: response.error.decline_code.or(response.error.advice_code),
            connector_metadata: None,
        })
    }
}

#[async_trait::async_trait]
impl ConnectorIntegration<Authorize, PaymentsAuthorizeData, PaymentsResponseData> for Stripe {
    fn get_headers(
        &self,
        req: &PaymentsAuthorizeRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<Vec<(String, Maskable<String>)>, ConnectorError> {
        let mut header = vec![(
            CONTENT_TYPE.to_string(),
            PaymentsAuthorizeType::get_content_type(self)
                .to_string()
                .into(),
        )];

        let mut api_key = self.get_auth_header(&req.connector_auth_type)?;
        header.append(&mut api_key);

        let stripe_split_payment_metadata = stripe::StripeSplitPaymentRequest::try_from(req)?;

        // if the request has split payment object, then append the transfer account id in headers in charge_type is Direct
        if let Some(common_types::payments::SplitPaymentsRequest::StripeSplitPayment(
            stripe_split_payment,
        )) = &req.request.split_payments
        {
            if stripe_split_payment.charge_type
                == PaymentChargeType::Stripe(StripeChargeType::Direct)
            {
                let mut customer_account_header = vec![(
                    STRIPE_COMPATIBLE_CONNECT_ACCOUNT.to_string(),
                    stripe_split_payment
                        .transfer_account_id
                        .clone()
                        .into_masked(),
                )];
                header.append(&mut customer_account_header);
            }
        }
        // if request doesn't have transfer_account_id, but stripe_split_payment_metadata has it, append it
        else if let Some(transfer_account_id) =
            stripe_split_payment_metadata.transfer_account_id.clone()
        {
            let mut customer_account_header = vec![(
                STRIPE_COMPATIBLE_CONNECT_ACCOUNT.to_string(),
                transfer_account_id.into_masked(),
            )];
            header.append(&mut customer_account_header);
        }
        Ok(header)
    }

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

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

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

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

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

    fn handle_response(
        &self,
        data: &PaymentsAuthorizeRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PaymentsAuthorizeRouterData, ConnectorError> {
        let response: stripe::PaymentIntentResponse = res
            .response
            .parse_struct("PaymentIntentResponse")
            .change_context(ConnectorError::ResponseDeserializationFailed)?;

        let response_integrity_object = get_authorise_integrity_object(
            self.amount_converter,
            response.amount,
            response.currency.clone(),
        )?;

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

        let new_router_data = RouterData::try_from(ResponseRouterData {
            response,
            data: data.clone(),
            http_code: res.status_code,
        })
        .change_context(ConnectorError::ResponseHandlingFailed);

        new_router_data.map(|mut router_data| {
            router_data.request.integrity_object = Some(response_integrity_object);
            router_data
        })
    }

    fn get_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, ConnectorError> {
        let response: stripe::ErrorResponse = res
            .response
            .parse_struct("ErrorResponse")
            .change_context(ConnectorError::ResponseDeserializationFailed)?;
        event_builder.map(|i| i.set_error_response_body(&response));
        router_env::logger::info!(connector_response=?response);
        Ok(ErrorResponse {
            status_code: res.status_code,
            code: response
                .error
                .code
                .clone()
                .unwrap_or_else(|| NO_ERROR_CODE.to_string()),
            message: response
                .error
                .code
                .unwrap_or_else(|| NO_ERROR_MESSAGE.to_string()),
            reason: response.error.message.map(|message| {
                response
                    .error
                    .decline_code
                    .clone()
                    .map(|decline_code| {
                        format!("message - {message}, decline_code - {decline_code}")
                    })
                    .unwrap_or(message)
            }),
            attempt_status: None,
            connector_transaction_id: response.error.payment_intent.map(|pi| pi.id),
            network_advice_code: response.error.network_advice_code,
            network_decline_code: response.error.network_decline_code,
            network_error_message: response.error.decline_code.or(response.error.advice_code),
            connector_metadata: None,
        })
    }
}

impl PaymentIncrementalAuthorization for Stripe {}

impl
    ConnectorIntegration<
        IncrementalAuthorization,
        PaymentsIncrementalAuthorizationData,
        PaymentsResponseData,
    > for Stripe
{
    fn get_headers(
        &self,
        req: &PaymentsIncrementalAuthorizationRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, Maskable<String>)>, ConnectorError> {
        self.build_headers(req, connectors)
    }

    fn get_http_method(&self) -> Method {
        Method::Post
    }

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

    fn get_url(
        &self,
        req: &PaymentsIncrementalAuthorizationRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, ConnectorError> {
        Ok(format!(
            "{}v1/payment_intents/{}/increment_authorization",
            self.base_url(connectors),
            req.request.connector_transaction_id,
        ))
    }

    fn get_request_body(
        &self,
        req: &PaymentsIncrementalAuthorizationRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, ConnectorError> {
        let amount = utils::convert_amount(
            self.amount_converter,
            MinorUnit::new(req.request.total_amount),
            req.request.currency,
        )?;
        let connector_req = stripe::StripeIncrementalAuthRequest { amount }; // Incremental authorization can be done a maximum of 10 times in Stripe

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

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

    fn handle_response(
        &self,
        data: &PaymentsIncrementalAuthorizationRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<
        RouterData<
            IncrementalAuthorization,
            PaymentsIncrementalAuthorizationData,
            PaymentsResponseData,
        >,
        ConnectorError,
    > {
        let response: stripe::PaymentIntentResponse = res


// Implementation: impl ConnectorRedirectResponse for for Breadpay
// File: crates/hyperswitch_connectors/src/connectors/breadpay.rs
// Module: hyperswitch_connectors
// Methods: 1 total (0 public)

impl ConnectorRedirectResponse for for Breadpay


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

pub struct EphemeralKeyCreateRequest


// File: crates/router/src/core/verify_connector.rs
// Module: router
// Public functions: 1

use api_models::{enums::Connector, verify_connector::VerifyConnectorRequest};
use error_stack::ResultExt;

use crate::{
    connector,
    core::errors,
    services,
    types::{
        api::{
            self,
            verify_connector::{self as types, VerifyConnector},
        },
        transformers::ForeignInto,
    },
    utils::verify_connector as utils,
    SessionState,
};

pub async fn verify_connector_credentials(
    state: SessionState,
    req: VerifyConnectorRequest,
    _profile_id: Option<common_utils::id_type::ProfileId>,
) -> errors::RouterResponse<()> {
    let boxed_connector = api::ConnectorData::get_connector_by_name(
        &state.conf.connectors,
        &req.connector_name.to_string(),
        api::GetToken::Connector,
        None,
    )
    .change_context(errors::ApiErrorResponse::IncorrectConnectorNameGiven)?;

    let card_details = utils::get_test_card_details(req.connector_name)?.ok_or(
        errors::ApiErrorResponse::FlowNotSupported {
            flow: "Verify credentials".to_string(),
            connector: req.connector_name.to_string(),
        },
    )?;

    match req.connector_name {
        Connector::Stripe => {
            connector::Stripe::verify(
                &state,
                types::VerifyConnectorData {
                    connector: boxed_connector.connector,
                    connector_auth: req.connector_account_details.foreign_into(),
                    card_details,
                },
            )
            .await
        }
        Connector::Paypal => connector::Paypal::get_access_token(
            &state,
            types::VerifyConnectorData {
                connector: boxed_connector.connector,
                connector_auth: req.connector_account_details.foreign_into(),
                card_details,
            },
        )
        .await
        .map(|_| services::ApplicationResponse::StatusOk),
        _ => Err(errors::ApiErrorResponse::FlowNotSupported {
            flow: "Verify credentials".to_string(),
            connector: req.connector_name.to_string(),
        }
        .into()),
    }
}


// Struct: TrustpaymentsPaymentsResponse
// File: crates/hyperswitch_connectors/src/connectors/trustpayments/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct TrustpaymentsPaymentsResponse


// Function: collect
// File: crates/analytics/src/frm/accumulator.rs
// Module: analytics

pub fn collect(self) -> FrmMetricsBucketValue


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

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


// Implementation: impl api::RefundSync for for CtpMastercard
// File: crates/hyperswitch_connectors/src/connectors/ctp_mastercard.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::RefundSync for for CtpMastercard


// Function: normalize_retry_window
// File: crates/router/src/types/storage/revenue_recovery_redis_operation.rs
// Module: router

// Documentation: Normalize retry window to exactly `RETRY_WINDOW_DAYS` days (today to `RETRY_WINDOW_DAYS - 1` days ago).

pub fn normalize_retry_window(
        payment_processor_token: &mut PaymentProcessorTokenStatus,
        today: Date,
    )


// Struct: BillTo
// File: crates/hyperswitch_connectors/src/connectors/wellsfargo/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct BillTo


// Function: payments_incremental_authorization
// File: crates/openapi/src/routes/payments.rs
// Module: openapi

pub fn payments_incremental_authorization()


// Function: trigger_payments_webhook
// File: crates/router/src/utils.rs
// Module: router

pub fn trigger_payments_webhook<F, Op, D>(
    merchant_context: domain::MerchantContext,
    business_profile: domain::Profile,
    payment_data: D,
    customer: Option<domain::Customer>,
    state: &SessionState,
    operation: Op,
) -> RouterResult<()>
where
    F: Send + Clone + Sync,
    Op: Debug,
    D: payments_core::OperationSessionGetters<F>,


// Struct: MigrateCardResponse
// File: crates/api_models/src/locker_migration.rs
// Module: api_models
// Implementations: 0

pub struct MigrateCardResponse


// Implementation: impl api::PayoutFulfill for for Cybersource
// File: crates/hyperswitch_connectors/src/connectors/cybersource.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::PayoutFulfill for for Cybersource


// Struct: StaxAuthType
// File: crates/hyperswitch_connectors/src/connectors/stax/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct StaxAuthType


// Function: perform_surcharge_decision_management_for_saved_cards
// File: crates/router/src/core/payment_methods/surcharge_decision_configs.rs
// Module: router

pub fn perform_surcharge_decision_management_for_saved_cards(
    state: &SessionState,
    algorithm_ref: routing::RoutingAlgorithmRef,
    payment_attempt: &storage::PaymentAttempt,
    payment_intent: &storage::PaymentIntent,
    customer_payment_method_list: &mut [api_models::payment_methods::CustomerPaymentMethod],
) -> ConditionalConfigResult<types::SurchargeMetadata>


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

impl api::RefundExecute for for Paysafe


// Function: delete_by_payment_method_id
// File: crates/diesel_models/src/query/payment_method.rs
// Module: diesel_models

pub fn delete_by_payment_method_id(
        conn: &PgPooledConn,
        payment_method_id: String,
    ) -> StorageResult<Self>


// Struct: ConnectorParamsWithSecondaryBaseUrl
// File: crates/hyperswitch_domain_models/src/connector_endpoints.rs
// Module: hyperswitch_domain_models
// Implementations: 0

pub struct ConnectorParamsWithSecondaryBaseUrl


// File: crates/router/src/core/utils/refunds_transformers.rs
// Module: router
// Public structs: 1

pub struct SplitRefundInput {
    pub refund_request: Option<common_types::refunds::SplitRefund>,
    pub payment_charges: Option<common_types::payments::ConnectorChargeResponseData>,
    pub split_payment_request: Option<common_types::payments::SplitPaymentsRequest>,
    pub charge_id: Option<String>,
}


// Function: new
// File: crates/common_utils/src/encryption.rs
// Module: common_utils

pub fn new(item: Secret<Vec<u8>, EncryptionStrategy>) -> Self


// Function: get_refund_update_for_refund_response_data
// File: crates/router/src/core/refunds_v2.rs
// Module: router

pub fn get_refund_update_for_refund_response_data(
    router_data: RouterData<api::Execute, types::RefundsData, types::RefundsResponseData>,
    connector: &api::ConnectorData,
    refund_response_data: types::RefundsResponseData,
    storage_scheme: &enums::MerchantStorageScheme,
    merchant_context: &domain::MerchantContext,
) -> diesel_refund::RefundUpdate


// Function: update_by_merchant_id_event_id
// File: crates/diesel_models/src/query/events.rs
// Module: diesel_models

pub fn update_by_merchant_id_event_id(
        conn: &PgPooledConn,
        merchant_id: &common_utils::id_type::MerchantId,
        event_id: &str,
        event: EventUpdateInternal,
    ) -> StorageResult<Self>