File: crates/hyperswitch_connectors/src/connectors/bankofamerica/transformers.rs
 Public functions: 1
 Public structs: 76

use base64::Engine;
use common_enums::{enums, FutureUsage};
use common_types::payments::ApplePayPredecryptData;
use common_utils::{consts, ext_traits::OptionExt, pii, types::StringMajorUnit};
use hyperswitch_domain_models::{
    payment_method_data::{
        ApplePayWalletData, GooglePayWalletData, PaymentMethodData, SamsungPayWalletData,
        WalletData,
    },
    router_data::{
        AdditionalPaymentMethodConnectorResponse, ConnectorAuthType, ConnectorResponseData,
        ErrorResponse, PaymentMethodToken, RouterData,
    },
    router_flow_types::refunds::{Execute, RSync},
    router_request_types::{
        PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, PaymentsSyncData,
        ResponseId,
    },
    router_response_types::{MandateReference, PaymentsResponseData, RefundsResponseData},
    types::{
        PaymentsAuthorizeRouterData, PaymentsCancelRouterData, PaymentsCaptureRouterData,
        RefundsRouterData, SetupMandateRouterData,
    },
};
use hyperswitch_interfaces::{api, errors};
use masking::{ExposeInterface, PeekInterface, Secret};
use serde::{Deserialize, Serialize};
use serde_json::Value;

use crate::{
    constants,
    types::{RefundsResponseRouterData, ResponseRouterData},
    unimplemented_payment_method,
    utils::{
        self, AddressDetailsData, CardData, PaymentsAuthorizeRequestData,
        PaymentsSetupMandateRequestData, PaymentsSyncRequestData, RecurringMandateData,
        RouterData as OtherRouterData,
    },
};
pub struct BankOfAmericaAuthType {
    pub(super) api_key: Secret<String>,
    pub(super) merchant_account: Secret<String>,
    pub(super) api_secret: Secret<String>,
}

impl TryFrom<&ConnectorAuthType> for BankOfAmericaAuthType {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(auth_type: &ConnectorAuthType) -> Result<Self, Self::Error> {
        if let ConnectorAuthType::SignatureKey {
            api_key,
            key1,
            api_secret,
        } = auth_type
        {
            Ok(Self {
                api_key: api_key.to_owned(),
                merchant_account: key1.to_owned(),
                api_secret: api_secret.to_owned(),
            })
        } else {
            Err(errors::ConnectorError::FailedToObtainAuthType)?
        }
    }
}

pub struct BankOfAmericaRouterData<T> {
    pub amount: StringMajorUnit,
    pub router_data: T,
}

impl<T> TryFrom<(StringMajorUnit, T)> for BankOfAmericaRouterData<T> {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from((amount, item): (StringMajorUnit, T)) -> Result<Self, Self::Error> {
        Ok(Self {
            amount,
            router_data: item,
        })
    }
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct BankOfAmericaPaymentsRequest {
    processing_information: ProcessingInformation,
    payment_information: PaymentInformation,
    order_information: OrderInformationWithBill,
    client_reference_information: ClientReferenceInformation,
    #[serde(skip_serializing_if = "Option::is_none")]
    consumer_authentication_information: Option<BankOfAmericaConsumerAuthInformation>,
    #[serde(skip_serializing_if = "Option::is_none")]
    merchant_defined_information: Option<Vec<MerchantDefinedInformation>>,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ProcessingInformation {
    action_list: Option<Vec<BankOfAmericaActionsList>>,
    action_token_types: Option<Vec<BankOfAmericaActionsTokenType>>,
    authorization_options: Option<BankOfAmericaAuthorizationOptions>,
    commerce_indicator: String,
    capture: Option<bool>,
    capture_options: Option<CaptureOptions>,
    payment_solution: Option<String>,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum BankOfAmericaActionsList {
    TokenCreate,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub enum BankOfAmericaActionsTokenType {
    PaymentInstrument,
    Customer,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct BankOfAmericaAuthorizationOptions {
    initiator: Option<BankOfAmericaPaymentInitiator>,
    merchant_intitiated_transaction: Option<MerchantInitiatedTransaction>,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct BankOfAmericaPaymentInitiator {
    #[serde(rename = "type")]
    initiator_type: Option<BankOfAmericaPaymentInitiatorTypes>,
    credential_stored_on_file: Option<bool>,
    stored_credential_used: Option<bool>,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub enum BankOfAmericaPaymentInitiatorTypes {
    Customer,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct MerchantInitiatedTransaction {
    reason: Option<String>,
    //Required for recurring mandates payment
    original_authorized_amount: Option<String>,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct MerchantDefinedInformation {
    key: u8,
    value: String,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct BankOfAmericaConsumerAuthInformation {
    ucaf_collection_indicator: Option<String>,
    cavv: Option<String>,
    ucaf_authentication_data: Option<Secret<String>>,
    xid: Option<String>,
    directory_server_transaction_id: Option<Secret<String>>,
    specification_version: Option<String>,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CaptureOptions {
    capture_sequence_number: u32,
    total_capture_count: u32,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BankOfAmericaPaymentInstrument {
    id: Secret<String>,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CardPaymentInformation {
    card: Card,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct GooglePayPaymentInformation {
    fluid_data: FluidData,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ApplePayTokenizedCard {
    transaction_type: TransactionType,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ApplePayTokenPaymentInformation {
    fluid_data: FluidData,
    tokenized_card: ApplePayTokenizedCard,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ApplePayPaymentInformation {
    tokenized_card: TokenizedCard,
}

#[derive(Debug, Serialize)]
#[serde(untagged)]
pub enum PaymentInformation {
    Cards(Box<CardPaymentInformation>),
    GooglePay(Box<GooglePayPaymentInformation>),
    ApplePay(Box<ApplePayPaymentInformation>),
    ApplePayToken(Box<ApplePayTokenPaymentInformation>),
    MandatePayment(Box<MandatePaymentInformation>),
    SamsungPay(Box<SamsungPayPaymentInformation>),
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct MandatePaymentInformation {
    payment_instrument: BankOfAmericaPaymentInstrument,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Card {
    number: cards::CardNumber,
    expiration_month: Secret<String>,
    expiration_year: Secret<String>,
    security_code: Secret<String>,
    #[serde(rename = "type")]
    card_type: Option<String>,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct TokenizedCard {
    number: cards::CardNumber,
    expiration_month: Secret<String>,
    expiration_year: Secret<String>,
    cryptogram: Secret<String>,
    transaction_type: TransactionType,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct FluidData {
    value: Secret<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    descriptor: Option<String>,
}

pub const FLUID_DATA_DESCRIPTOR_FOR_SAMSUNG_PAY: &str = "FID=COMMON.SAMSUNG.INAPP.PAYMENT";

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct OrderInformationWithBill {
    amount_details: Amount,
    bill_to: Option<BillTo>,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Amount {
    total_amount: StringMajorUnit,
    currency: api_models::enums::Currency,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct BillTo {
    first_name: Option<Secret<String>>,
    last_name: Option<Secret<String>>,
    address1: Option<Secret<String>>,
    locality: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    administrative_area: Option<Secret<String>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    postal_code: Option<Secret<String>>,
    country: Option<enums::CountryAlpha2>,
    email: pii::Email,
}

impl TryFrom<&SetupMandateRouterData> for BankOfAmericaPaymentsRequest {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(item: &SetupMandateRouterData) -> Result<Self, Self::Error> {
        match item.request.payment_method_data.clone() {
            PaymentMethodData::Card(card_data) => Self::try_from((item, card_data)),
            PaymentMethodData::Wallet(wallet_data) => match wallet_data {
                WalletData::ApplePay(apple_pay_data) => Self::try_from((item, apple_pay_data)),
                WalletData::GooglePay(google_pay_data) => Self::try_from((item, google_pay_data)),
                WalletData::AliPayQr(_)
                | WalletData::AliPayRedirect(_)
                | WalletData::AliPayHkRedirect(_)
                | WalletData::AmazonPayRedirect(_)
                | WalletData::Paysera(_)
                | WalletData::Skrill(_)
                | WalletData::BluecodeRedirect {}
                | WalletData::MomoRedirect(_)
                | WalletData::KakaoPayRedirect(_)
                | WalletData::GoPayRedirect(_)
                | WalletData::GcashRedirect(_)
                | WalletData::ApplePayRedirect(_)
                | WalletData::ApplePayThirdPartySdk(_)
                | WalletData::DanaRedirect {}
                | WalletData::GooglePayRedirect(_)
                | WalletData::GooglePayThirdPartySdk(_)
                | WalletData::MbWayRedirect(_)
                | WalletData::MobilePayRedirect(_)
                | WalletData::PaypalRedirect(_)
                | WalletData::PaypalSdk(_)
                | WalletData::Paze(_)
                | WalletData::SamsungPay(_)
                | WalletData::AmazonPay(_)
                | WalletData::TwintRedirect {}
                | WalletData::VippsRedirect {}
                | WalletData::TouchNGoRedirect(_)
                | WalletData::WeChatPayRedirect(_)
                | WalletData::WeChatPayQr(_)
                | WalletData::CashappQr(_)
                | WalletData::SwishQr(_)
                | WalletData::Mifinity(_)
                | WalletData::RevolutPay(_) => Err(errors::ConnectorError::NotImplemented(
                    utils::get_unimplemented_payment_method_error_message("BankOfAmerica"),
                ))?,
            },
            PaymentMethodData::CardRedirect(_)
            | PaymentMethodData::PayLater(_)
            | PaymentMethodData::BankRedirect(_)
            | PaymentMethodData::BankDebit(_)
            | PaymentMethodData::BankTransfer(_)
            | PaymentMethodData::Crypto(_)
            | PaymentMethodData::MandatePayment
            | PaymentMethodData::Reward
            | PaymentMethodData::RealTimePayment(_)
            | PaymentMethodData::MobilePayment(_)
            | PaymentMethodData::Upi(_)
            | PaymentMethodData::Voucher(_)
            | PaymentMethodData::GiftCard(_)
            | PaymentMethodData::OpenBanking(_)
            | PaymentMethodData::CardToken(_)
            | PaymentMethodData::NetworkToken(_)
            | PaymentMethodData::CardDetailsForNetworkTransactionId(_) => {
                Err(errors::ConnectorError::NotImplemented(
                    utils::get_unimplemented_payment_method_error_message("BankOfAmerica"),
                ))?
            }
        }
    }
}

impl<F, T>
    TryFrom<ResponseRouterData<F, BankOfAmericaSetupMandatesResponse, T, PaymentsResponseData>>
    for RouterData<F, T, PaymentsResponseData>
{
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: ResponseRouterData<F, BankOfAmericaSetupMandatesResponse, T, PaymentsResponseData>,
    ) -> Result<Self, Self::Error> {
        match item.response {
            BankOfAmericaSetupMandatesResponse::ClientReferenceInformation(info_response) => {
                let mandate_reference =
                    info_response
                        .token_information
                        .clone()
                        .map(|token_info| MandateReference {
                            connector_mandate_id: token_info
                                .payment_instrument
                                .map(|payment_instrument| payment_instrument.id.expose()),
                            payment_method_id: None,
                            mandate_metadata: None,
                            connector_mandate_request_reference_id: None,
                        });
                let mut mandate_status =
                    map_boa_attempt_status((info_response.status.clone(), false));
                if matches!(mandate_status, enums::AttemptStatus::Authorized) {
                    //In case of zero auth mandates we want to make the payment reach the terminal status so we are converting the authorized status to charged as well.
                    mandate_status = enums::AttemptStatus::Charged
                }
                let error_response =
                    get_error_response_if_failure((&info_response, mandate_status, item.http_code));

                let connector_response = match item.data.payment_method {
                    common_enums::PaymentMethod::Card => info_response
                        .processor_information
                        .as_ref()
                        .and_then(|processor_information| {
                            info_response
                                .consumer_authentication_information
                                .as_ref()
                                .map(|consumer_auth_information| {
                                    convert_to_additional_payment_method_connector_response(
                                        processor_information,
                                        consumer_auth_information,
                                    )
                                })
                        })
                        .map(ConnectorResponseData::with_additional_payment_method_data),
                    common_enums::PaymentMethod::CardRedirect
                    | common_enums::PaymentMethod::PayLater
                    | common_enums::PaymentMethod::Wallet
                    | common_enums::PaymentMethod::BankRedirect
                    | common_enums::PaymentMethod::BankTransfer
                    | common_enums::PaymentMethod::Crypto
                    | common_enums::PaymentMethod::BankDebit
                    | common_enums::PaymentMethod::Reward
                    | common_enums::PaymentMethod::RealTimePayment
                    | common_enums::PaymentMethod::MobilePayment
                    | common_enums::PaymentMethod::Upi
                    | common_enums::PaymentMethod::Voucher
                    | common_enums::PaymentMethod::OpenBanking
                    | common_enums::PaymentMethod::GiftCard => None,
                };

                Ok(Self {
                    status: mandate_status,
                    response: match error_response {
                        Some(error) => Err(error),
                        None => Ok(PaymentsResponseData::TransactionResponse {
                            resource_id: ResponseId::ConnectorTransactionId(
                                info_response.id.clone(),
                            ),
                            redirection_data: Box::new(None),
                            mandate_reference: Box::new(mandate_reference),
                            connector_metadata: None,
                            network_txn_id: None,
                            connector_response_reference_id: Some(
                                info_response
                                    .client_reference_information
                                    .code
                                    .clone()
                                    .unwrap_or(info_response.id),
                            ),
                            incremental_authorization_allowed: None,
                            charges: None,
                        }),
                    },
                    connector_response,
                    ..item.data
                })
            }
            BankOfAmericaSetupMandatesResponse::ErrorInformation(error_response) => {
                let response = Err(convert_to_error_response_from_error_info(
                    &error_response,
                    item.http_code,
                ));
                Ok(Self {
                    response,
                    status: enums::AttemptStatus::Failure,
                    ..item.data
                })
            }
        }
    }
}

// for bankofamerica each item in Billing is mandatory
// fn build_bill_to(
//     address_details: &payments::Address,
//     email: pii::Email,
// ) -> Result<BillTo, error_stack::Report<errors::ConnectorError>> {
//     let address = address_details
//         .address
//         .as_ref()
//         .ok_or_else(utils::missing_field_err("billing.address"))?;

//     let country = address.get_country()?.to_owned();
//     let first_name = address.get_first_name()?;

//     let (administrative_area, postal_code) =
//         if country == api_enums::CountryAlpha2::US || country == api_enums::CountryAlpha2::CA {
//             let mut state = address.to_state_code()?.peek().clone();
//             state.truncate(20);
//             (
//                 Some(Secret::from(state)),
//                 Some(address.get_zip()?.to_owned()),
//             )
//         } else {
//             let zip = address.zip.clone();
//             let mut_state = address.state.clone().map(|state| state.expose());
//             match mut_state {
//                 Some(mut state) => {
//                     state.truncate(20);
//                     (Some(Secret::from(state)), zip)
//                 }
//                 None => (None, zip),
//             }
//         };
//     Ok(BillTo {
//         first_name: first_name.clone(),
//         last_name: address.get_last_name().unwrap_or(first_name).clone(),
//         address1: address.get_line1()?.to_owned(),
//         locality: Secret::new(address.get_city()?.to_owned()),
//         administrative_area,
//         postal_code,
//         country,
//         email,
//     })
// }

fn build_bill_to(
    address_details: Option<&hyperswitch_domain_models::address::Address>,
    email: pii::Email,
) -> Result<BillTo, error_stack::Report<errors::ConnectorError>> {
    let default_address = BillTo {
        first_name: None,
        last_name: None,
        address1: None,
        locality: None,
        administrative_area: None,
        postal_code: None,
        country: None,
        email: email.clone(),
    };

    Ok(address_details
        .and_then(|addr| {
            addr.address.as_ref().map(|addr| {
                let administrative_area = addr.to_state_code_as_optional().unwrap_or_else(|_| {
                    addr.state
                        .clone()
                        .map(|state| Secret::new(format!("{:.20}", state.expose())))
                });

                BillTo {
                    first_name: addr.first_name.clone(),
                    last_name: addr.last_name.clone(),
                    address1: addr.line1.clone(),
                    locality: addr.city.clone(),
                    administrative_area,
                    postal_code: addr.zip.clone(),
                    country: addr.country,
                    email,
                }
            })
        })
        .unwrap_or(default_address))
}

fn get_boa_card_type(card_network: common_enums::CardNetwork) -> Option<&'static str> {
    match card_network {
        common_enums::CardNetwork::Visa => Some("001"),
        common_enums::CardNetwork::Mastercard => Some("002"),
        common_enums::CardNetwork::AmericanExpress => Some("003"),
        common_enums::CardNetwork::JCB => Some("007"),
        common_enums::CardNetwork::DinersClub => Some("005"),
        common_enums::CardNetwork::Discover => Some("004"),
        common_enums::CardNetwork::CartesBancaires => Some("006"),
        common_enums::CardNetwork::UnionPay => Some("062"),
        //"042" is the type code for Masetro Cards(International). For Maestro Cards(UK-Domestic) the mapping should be "024"
        common_enums::CardNetwork::Maestro => Some("042"),
        common_enums::CardNetwork::Interac
        | common_enums::CardNetwork::RuPay
        | common_enums::CardNetwork::Star
        | common_enums::CardNetwork::Accel
        | common_enums::CardNetwork::Pulse
        | common_enums::CardNetwork::Nyce => None,
    }
}

#[derive(Debug, Serialize)]
pub enum PaymentSolution {
    ApplePay,
    GooglePay,
    SamsungPay,
}

impl From<PaymentSolution> for String {
    fn from(solution: PaymentSolution) -> Self {
        let payment_solution = match solution {
            PaymentSolution::ApplePay => "001",
            PaymentSolution::GooglePay => "012",
            PaymentSolution::SamsungPay => "008",
        };
        payment_solution.to_string()
    }
}

#[derive(Debug, Serialize)]
pub enum TransactionType {
    #[serde(rename = "1")]
    ApplePay,
    #[serde(rename = "1")]
    SamsungPay,
}

impl
    From<(
        &BankOfAmericaRouterData<&PaymentsAuthorizeRouterData>,
        Option<BillTo>,
    )> for OrderInformationWithBill
{
    fn from(
        (item, bill_to): (
            &BankOfAmericaRouterData<&PaymentsAuthorizeRouterData>,
            Option<BillTo>,
        ),
    ) -> Self {
        Self {
            amount_details: Amount {
                total_amount: item.amount.to_owned(),
                currency: item.router_data.request.currency,
            },
            bill_to,
        }
    }
}

impl
    TryFrom<(
        &BankOfAmericaRouterData<&PaymentsAuthorizeRouterData>,
        Option<PaymentSolution>,
        Option<String>,
    )> for ProcessingInformation
{
    type Error = error_stack::Report<errors::ConnectorError>;

    fn try_from(
        (item, solution, network): (
            &BankOfAmericaRouterData<&PaymentsAuthorizeRouterData>,
            Option<PaymentSolution>,
            Option<String>,
        ),
    ) -> Result<Self, Self::Error> {
        let (action_list, action_token_types, authorization_options) =
            if item.router_data.request.setup_future_usage == Some(FutureUsage::OffSession)
                && (item.router_data.request.customer_acceptance.is_some()
                    || item
                        .router_data
                        .request
                        .setup_mandate_details
                        .clone()
                        .is_some_and(|mandate_details| {
                            mandate_details.customer_acceptance.is_some()
                        }))
            {
                get_boa_mandate_action_details()
            } else if item.router_data.request.connector_mandate_id().is_some() {
                let original_amount = item
                    .router_data
                    .get_recurring_mandate_payment_data()?
                    .get_original_payment_amount()?;
                let original_currency = item
                    .router_data
                    .get_recurring_mandate_payment_data()?
                    .get_original_payment_currency()?;
                (
                    None,
                    None,
                    Some(BankOfAmericaAuthorizationOptions {
                        initiator: None,
                        merchant_intitiated_transaction: Some(MerchantInitiatedTransaction {
                            reason: None,
                            original_authorized_amount: Some(utils::get_amount_as_string(
                                &api::CurrencyUnit::Base,
                                original_amount,
                                original_currency,
                            )?),
                        }),
                    }),
                )
            } else {
                (None, None, None)
            };

        let commerce_indicator = get_commerce_indicator(network);

        Ok(Self {
            capture: Some(matches!(
                item.router_data.request.capture_method,
                Some(enums::CaptureMethod::Automatic) | None
            )),
            payment_solution: solution.map(String::from),
            action_list,
            action_token_types,
            authorization_options,
            capture_options: None,
            commerce_indicator,
        })
    }
}

impl From<&BankOfAmericaRouterData<&PaymentsAuthorizeRouterData>> for ClientReferenceInformation {
    fn from(item: &BankOfAmericaRouterData<&PaymentsAuthorizeRouterData>) -> Self {
        Self {
            code: Some(item.router_data.connector_request_reference_id.clone()),
        }
    }
}

impl From<&SetupMandateRouterData> for ClientReferenceInformation {
    fn from(item: &SetupMandateRouterData) -> Self {
        Self {
            code: Some(item.connector_request_reference_id.clone()),
        }
    }
}

fn convert_metadata_to_merchant_defined_info(metadata: Value) -> Vec<MerchantDefinedInformation> {
    let hashmap: std::collections::BTreeMap<String, Value> =
        serde_json::from_str(&metadata.to_string()).unwrap_or(std::collections::BTreeMap::new());
    let mut vector = Vec::new();
    let mut iter = 1;
    for (key, value) in hashmap {
        vector.push(MerchantDefinedInformation {
            key: iter,
            value: format!("{key}={value}"),
        });
        iter += 1;
    }
    vector
}

#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ClientReferenceInformation {
    code: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ClientProcessorInformation {
    avs: Option<Avs>,
    card_verification: Option<CardVerification>,
    processor: Option<ProcessorResponse>,
    network_transaction_id: Option<Secret<String>>,
    approval_code: Option<String>,
    merchant_advice: Option<MerchantAdvice>,
    response_code: Option<String>,
    ach_verification: Option<AchVerification>,
    system_trace_audit_number: Option<String>,
    event_status: Option<String>,
    retrieval_reference_number: Option<String>,
    consumer_authentication_response: Option<ConsumerAuthenticationResponse>,
    response_details: Option<String>,
    transaction_id: Option<Secret<String>>,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct MerchantAdvice {
    code: Option<String>,
    code_raw: Option<String>,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ConsumerAuthenticationResponse {
    code: Option<String>,
    code_raw: Option<String>,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct AchVerification {
    result_code_raw: Option<String>,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ProcessorResponse {
    name: Option<String>,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CardVerification {
    result_code: Option<String>,
    result_code_raw: Option<String>,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ClientRiskInformation {
    rules: Option<Vec<ClientRiskInformationRules>>,
    profile: Option<Profile>,
    score: Option<Score>,
    info_codes: Option<InfoCodes>,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct InfoCodes {
    address: Option<Vec<String>>,
    identity_change: Option<Vec<String>>,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Score {
    factor_codes: Option<Vec<String>>,
    result: Option<RiskResult>,
    model_used: Option<String>,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(untagged)]
pub enum RiskResult {
    StringVariant(String),
    IntVariant(u64),
}

#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Profile {
    early_decision: Option<String>,
    name: Option<String>,
    decision: Option<String>,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct ClientRiskInformationRules {
    name: Option<Secret<String>>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Avs {
    code: Option<String>,
    code_raw: Option<String>,
}

impl
    TryFrom<(
        &BankOfAmericaRouterData<&PaymentsAuthorizeRouterData>,
        hyperswitch_domain_models::payment_method_data::Card,
    )> for BankOfAmericaPaymentsRequest
{
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        (item, ccard): (
            &BankOfAmericaRouterData<&PaymentsAuthorizeRouterData>,
            hyperswitch_domain_models::payment_method_data::Card,
        ),
    ) -> Result<Self, Self::Error> {
        if item.router_data.is_three_ds() {
            Err(errors::ConnectorError::NotSupported {
                message: "Card 3DS".to_string(),
                connector: "BankOfAmerica",
            })?
        };

        let email = item.router_data.request.get_email()?;
        let bill_to = build_bill_to(item.router_data.get_optional_billing(), email)?;
        let order_information = OrderInformationWithBill::from((item, Some(bill_to)));
        let payment_information = PaymentInformation::try_from(&ccard)?;
        let processing_information = ProcessingInformation::try_from((item, None, None))?;
        let client_reference_information = ClientReferenceInformation::from(item);
        let merchant_defined_information = item
            .router_data
            .request
            .metadata
            .clone()
            .map(convert_metadata_to_merchant_defined_info);

        Ok(Self {
            processing_information,
            payment_information,
            order_information,
            client_reference_information,
            merchant_defined_information,
            consumer_authentication_information: None,
        })
    }
}

impl
    TryFrom<(
        &BankOfAmericaRouterData<&PaymentsAuthorizeRouterData>,
        Box<ApplePayPredecryptData>,
        ApplePayWalletData,
    )> for BankOfAmericaPaymentsRequest
{
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        (item, apple_pay_data, apple_pay_wallet_data): (
            &BankOfAmericaRouterData<&PaymentsAuthorizeRouterData>,
            Box<ApplePayPredecryptData>,
            ApplePayWalletData,
        ),
    ) -> Result<Self, Self::Error> {
        let email = item.router_data.request.get_email()?;
        let bill_to = build_bill_to(item.router_data.get_optional_billing(), email)?;
        let order_information = OrderInformationWithBill::from((item, Some(bill_to)));
        let processing_information = ProcessingInformation::try_from((
            item,
            Some(PaymentSolution::ApplePay),
            Some(apple_pay_wallet_data.payment_method.network.clone()),
        ))?;
        let client_reference_information = ClientReferenceInformation::from(item);
        let payment_information = PaymentInformation::try_from(&apple_pay_data)?;
        let merchant_defined_information = item
            .router_data
            .request
            .metadata
            .clone()
            .map(convert_metadata_to_merchant_defined_info);
        let ucaf_collection_indicator = match apple_pay_wallet_data
            .payment_method
            .network
            .to_lowercase()
            .as_str()
        {
            "mastercard" => Some("2".to_string()),
            _ => None,
        };
        Ok(Self {
            processing_information,
            payment_information,
            order_information,
            client_reference_information,
            merchant_defined_information,
            consumer_authentication_information: Some(BankOfAmericaConsumerAuthInformation {
                ucaf_collection_indicator,
                cavv: None,
                ucaf_authentication_data: None,
                xid: None,
                directory_server_transaction_id: None,
                specification_version: None,
            }),
        })
    }
}

impl
    TryFrom<(
        &BankOfAmericaRouterData<&PaymentsAuthorizeRouterData>,
        GooglePayWalletData,
    )> for BankOfAmericaPaymentsRequest
{
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        (item, google_pay_data): (
            &BankOfAmericaRouterData<&PaymentsAuthorizeRouterData>,
            GooglePayWalletData,
        ),
    ) -> Result<Self, Self::Error> {
        let email = item.router_data.request.get_email()?;
        let bill_to = build_bill_to(item.router_data.get_optional_billing(), email)?;
        let order_information = OrderInformationWithBill::from((item, Some(bill_to)));
        let payment_information = PaymentInformation::try_from(&google_pay_data)?;
        let processing_information =
            ProcessingInformation::try_from((item, Some(PaymentSolution::GooglePay), None))?;
        let client_reference_information = ClientReferenceInformation::from(item);
        let merchant_defined_information = item
            .router_data
            .request
            .metadata
            .clone()
            .map(convert_metadata_to_merchant_defined_info);

        Ok(Self {
            processing_information,
            payment_information,
            order_information,
            client_reference_information,
            merchant_defined_information,
            consumer_authentication_information: None,
        })
    }
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SamsungPayTokenizedCard {
    transaction_type: TransactionType,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SamsungPayPaymentInformation {
    fluid_data: FluidData,
    tokenized_card: SamsungPayTokenizedCard,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SamsungPayFluidDataValue {
    public_key_hash: Secret<String>,
    version: String,
    data: Secret<String>,
}

impl TryFrom<&BankOfAmericaRouterData<&PaymentsAuthorizeRouterData>>
    for BankOfAmericaPaymentsRequest
{
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: &BankOfAmericaRouterData<&PaymentsAuthorizeRouterData>,
    ) -> Result<Self, Self::Error> {
        match item.router_data.request.connector_mandate_id() {
            Some(connector_mandate_id) => Self::try_from((item, connector_mandate_id)),
            None => {
                match item.router_data.request.payment_method_data.clone() {
                    PaymentMethodData::Card(ccard) => Self::try_from((item, ccard)),
                    PaymentMethodData::Wallet(wallet_data) => match wallet_data {
                        WalletData::ApplePay(apple_pay_data) => {
                            match item.router_data.payment_method_token.clone() {
                                Some(payment_method_token) => match payment_method_token {
                                    PaymentMethodToken::ApplePayDecrypt(decrypt_data) => {
                                        Self::try_from((item, decrypt_data, apple_pay_data))
                                    }
                                    PaymentMethodToken::Token(_) => {
                                        Err(unimplemented_payment_method!(
                                            "Apple Pay",
                                            "Manual",
                                            "Bank Of America"
                                        ))?
                                    }
                                    PaymentMethodToken::PazeDecrypt(_) => Err(
                                        unimplemented_payment_method!("Paze", "Bank Of America"),
                                    )?,
                                    PaymentMethodToken::GooglePayDecrypt(_) => {
                                        Err(unimplemented_payment_method!(
                                            "Google Pay",
                                            "Bank Of America"
                                        ))?
                                    }
                                },
                                None => {
                                    let email = item.router_data.request.get_email()?;
                                    let bill_to = build_bill_to(
                                        item.router_data.get_optional_billing(),
                                        email,
                                    )?;
                                    let order_information: OrderInformationWithBill =
                                        OrderInformationWithBill::from((item, Some(bill_to)));
                                    let processing_information =
                                        ProcessingInformation::try_from((
                                            item,
                                            Some(PaymentSolution::ApplePay),
                                            Some(apple_pay_data.payment_method.network.clone()),
                                        ))?;
                                    let client_reference_information =
                                        ClientReferenceInformation::from(item);
                                    let payment_information =
                                        PaymentInformation::try_from(&apple_pay_data)?;
                                    let merchant_defined_information = item
                                        .router_data
                                        .request
                                        .metadata
                                        .clone()
                                        .map(convert_metadata_to_merchant_defined_info);
                                    let ucaf_collection_indicator = match apple_pay_data
                                        .payment_method
                                        .network
                                        .to_lowercase()
                                        .as_str()
                                    {
                                        "mastercard" => Some("2".to_string()),
                                        _ => None,
                                    };
                                    Ok(Self {
                                        processing_information,
                                        payment_information,
                                        order_information,
                                        merchant_defined_information,
                                        client_reference_information,
                                        consumer_authentication_information: Some(
                                            BankOfAmericaConsumerAuthInformation {
                                                ucaf_collection_indicator,
                                                cavv: None,
                                                ucaf_authentication_data: None,
                                                xid: None,
                                                directory_server_transaction_id: None,
                                                specification_version: None,
                                            },
                                        ),
                                    })
                                }
                            }
                        }
                        WalletData::GooglePay(google_pay_data) => {
                            Self::try_from((item, google_pay_data))
                        }
                        WalletData::SamsungPay(samsung_pay_data) => {
                            Self::try_from((item, samsung_pay_data))
                        }

                        WalletData::AliPayQr(_)
                        | WalletData::AliPayRedirect(_)
                        | WalletData::AliPayHkRedirect(_)
                        | WalletData::AmazonPayRedirect(_)
                        | WalletData::Paysera(_)
                        | WalletData::Skrill(_)
                        | WalletData::BluecodeRedirect {}
                        | WalletData::MomoRedirect(_)
                        | WalletData::KakaoPayRedirect(_)
                        | WalletData::GoPayRedirect(_)
                        | WalletData::GcashRedirect(_)
                        | WalletData::ApplePayRedirect(_)
                        | WalletData::ApplePayThirdPartySdk(_)
                        | WalletData::DanaRedirect {}
                        | WalletData::GooglePayRedirect(_)
                        | WalletData::GooglePayThirdPartySdk(_)
                        | WalletData::MbWayRedirect(_)
                        | WalletData::MobilePayRedirect(_)
                        | WalletData::PaypalRedirect(_)
                        | WalletData::PaypalSdk(_)
                        | WalletData::Paze(_)
                        | WalletData::AmazonPay(_)
                        | WalletData::TwintRedirect {}
                        | WalletData::VippsRedirect {}
                        | WalletData::TouchNGoRedirect(_)
                        | WalletData::WeChatPayRedirect(_)
                        | WalletData::WeChatPayQr(_)
                        | WalletData::CashappQr(_)
                        | WalletData::SwishQr(_)
                        | WalletData::Mifinity(_)
                        | WalletData::RevolutPay(_) => Err(errors::ConnectorError::NotImplemented(
                            utils::get_unimplemented_payment_method_error_message(
                                "Bank of America",
                            ),
                        )


pub struct NordeaOAuthRequest {
    /// Country is a mandatory parameter with possible values FI, DK, NO or SE
    pub country: api_models::enums::CountryAlpha2,
    /// Duration of access authorization in minutes. range: 1 to 259200 minutes (180 days).
    /// Duration should be left empty if the request includes PAYMENTS_SINGLE_SCA scope.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub duration: Option<i32>,
    /// Maximum transaction history in months. Optional if ACCOUNTS_TRANSACTIONS scope is requested. Default=2 months. range: 1 to 18 months
    #[serde(rename = "max_tx_history")]
    #[serde(skip_serializing_if = "Option::is_none")]
    pub maximum_transaction_history: Option<i32>,
    /// Redirect URI you used when this application was registered with Nordea.
    pub redirect_uri: String,
    pub scope: Vec<AccessScope>,
    /// The OAuth2 state parameter. This is a nonce and should be used to prevent CSRF attacks.
    pub state: Secret<String>,
}


pub async fn apple_pay_certificates_migration(
    state: SessionState,
    req: &apple_pay_certificates_migration::ApplePayCertificatesMigrationRequest,
) -> CustomResult<
    services::ApplicationResponse<
        apple_pay_certificates_migration::ApplePayCertificatesMigrationResponse,
    >,
    errors::ApiErrorResponse,
> {
    let db = state.store.as_ref();

    let merchant_id_list = &req.merchant_ids;

    let mut migration_successful_merchant_ids = vec![];
    let mut migration_failed_merchant_ids = vec![];
    let key_manager_state = &(&state).into();
    for merchant_id in merchant_id_list {
        let key_store = state
            .store
            .get_merchant_key_store_by_merchant_id(
                key_manager_state,
                merchant_id,
                &state.store.get_master_key().to_vec().into(),
            )
            .await
            .change_context(errors::ApiErrorResponse::InternalServerError)?;

        let merchant_connector_accounts = db
            .find_merchant_connector_account_by_merchant_id_and_disabled_list(
                key_manager_state,
                merchant_id,
                true,
                &key_store,
            )
            .await
            .to_not_found_response(errors::ApiErrorResponse::InternalServerError)?;

        let mut mca_to_update = vec![];

        for connector_account in merchant_connector_accounts {
            let connector_apple_pay_metadata =
                helpers::get_applepay_metadata(connector_account.clone().metadata)
                    .map_err(|error| {
                        logger::error!(
                "Apple pay metadata parsing failed for {:?} in certificates migrations api {:?}",
                connector_account.clone().connector_name,
                error
            )
                    })
                    .ok();
            if let Some(apple_pay_metadata) = connector_apple_pay_metadata {
                let encrypted_apple_pay_metadata = domain_types::crypto_operation(
                    &(&state).into(),
                    type_name!(storage::MerchantConnectorAccount),
                    domain_types::CryptoOperation::Encrypt(Secret::new(
                        serde_json::to_value(apple_pay_metadata)
                            .change_context(errors::ApiErrorResponse::InternalServerError)
                            .attach_printable("Failed to serialize apple pay metadata as JSON")?,
                    )),
                    Identifier::Merchant(merchant_id.clone()),
                    key_store.key.get_inner().peek(),
                )
                .await
                .and_then(|val| val.try_into_operation())
                .change_context(errors::ApiErrorResponse::InternalServerError)
                .attach_printable("Unable to encrypt connector apple pay metadata")?;

                let updated_mca =
                    storage::MerchantConnectorAccountUpdate::ConnectorWalletDetailsUpdate {
                        connector_wallets_details: encrypted_apple_pay_metadata,
                    };

                mca_to_update.push((connector_account, updated_mca.into()));
            }
        }

        let merchant_connector_accounts_update = db
            .update_multiple_merchant_connector_accounts(mca_to_update)
            .await;

        match merchant_connector_accounts_update {
            Ok(_) => {
                logger::debug!(
                    "Merchant connector accounts updated for merchant id {merchant_id:?}"
                );
                migration_successful_merchant_ids.push(merchant_id.clone());
            }
            Err(error) => {
                logger::debug!(
                    "Merchant connector accounts update failed with error {error} for merchant id {merchant_id:?}");
                migration_failed_merchant_ids.push(merchant_id.clone());
            }
        };
    }

    Ok(services::api::ApplicationResponse::Json(
        apple_pay_certificates_migration::ApplePayCertificatesMigrationResponse {
            migration_successful: migration_successful_merchant_ids,
            migration_failed: migration_failed_merchant_ids,
        },
    ))
}


pub struct WisePayoutFulfillRequest {
    #[serde(rename = "type")]
    fund_type: FundType,
}


OpenAPI Block Path: components.schemas.NextAction
{
  "type": "object",
  "required": [
    "url",
    "http_method"
  ],
  "properties": {
    "url": {
      "type": "string",
      "description": "The URL for authenticatating the user."
    },
    "http_method": {
      "$ref": "#/components/schemas/Method"
    }
  }
}


pub struct PaymeQueryTransactionRequest {
    payme_transaction_id: String,
    seller_payme_id: Secret<String>,
}


impl api::PaymentCapture for Facilitapay {}

impl api::PaymentCapture for for Facilitapay


OpenAPI Block Path: components.schemas.SamsungPayAppWalletData
{
  "type": "object",
  "required": [
    "3_d_s",
    "payment_card_brand",
    "payment_currency_type",
    "payment_last4_fpan"
  ],
  "properties": {
    "3_d_s": {
      "$ref": "#/components/schemas/SamsungPayTokenData"
    },
    "payment_card_brand": {
      "$ref": "#/components/schemas/SamsungPayCardBrand"
    },
    "payment_currency_type": {
      "type": "string",
      "description": "Currency type of the payment"
    },
    "payment_last4_dpan": {
      "type": "string",
      "description": "Last 4 digits of the device specific card number",
      "nullable": true
    },
    "payment_last4_fpan": {
      "type": "string",
      "description": "Last 4 digits of the card number"
    },
    "merchant_ref": {
      "type": "string",
      "description": "Merchant reference id that was passed in the session call request",
      "nullable": true
    },
    "method": {
      "type": "string",
      "description": "Specifies authentication method used",
      "nullable": true
    },
    "recurring_payment": {
      "type": "boolean",
      "description": "Value if credential is enabled for recurring payment",
      "nullable": true
    }
  }
}


pub struct Activity {
    pub activity_date: Option<String>,
    pub activity_type: Option<String>,
    pub from_queue: Option<String>,
    pub to_queue: Option<String>,
    pub notes: Option<String>,
}


pub struct BluesnapRefundRequest {
    amount: Option<StringMajorUnit>,
    reason: Option<String>,
}


pub struct Reason {
    pub code: Option<String>,
    pub reject_reason: Option<String>,
}


pub trait PaymentIntentMetricAnalytics: LoadRow<PaymentIntentMetricRow> {}


pub async fn trigger_refund_execute_workflow(
    state: &SessionState,
    refund_tracker: &storage::ProcessTracker,
) -> Result<(), errors::ProcessTrackerError> {
    let db = &*state.store;
    let refund_core = serde_json::from_value::<diesel_refund::RefundCoreWorkflow>(
        refund_tracker.tracking_data.clone(),
    )
    .change_context(errors::ApiErrorResponse::InternalServerError)
    .attach_printable_lazy(|| {
        format!(
            "unable to convert into refund_core {:?}",
            refund_tracker.tracking_data
        )
    })?;
    let key_manager_state = &state.into();
    let key_store = state
        .store
        .get_merchant_key_store_by_merchant_id(
            key_manager_state,
            &refund_core.merchant_id,
            &state.store.get_master_key().to_vec().into(),
        )
        .await?;

    let merchant_account = db
        .find_merchant_account_by_merchant_id(
            key_manager_state,
            &refund_core.merchant_id,
            &key_store,
        )
        .await
        .to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?;

    let merchant_context = domain::MerchantContext::NormalMerchant(Box::new(domain::Context(
        merchant_account.clone(),
        key_store.clone(),
    )));
    let refund = db
        .find_refund_by_internal_reference_id_merchant_id(
            &refund_core.refund_internal_reference_id,
            &refund_core.merchant_id,
            merchant_account.storage_scheme,
        )
        .await
        .to_not_found_response(errors::ApiErrorResponse::RefundNotFound)?;
    match (&refund.sent_to_gateway, &refund.refund_status) {
        (false, enums::RefundStatus::Pending) => {
            let merchant_account = db
                .find_merchant_account_by_merchant_id(
                    key_manager_state,
                    &refund.merchant_id,
                    &key_store,
                )
                .await
                .to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?;

            let payment_attempt = db
                .find_payment_attempt_by_connector_transaction_id_payment_id_merchant_id(
                    &refund.connector_transaction_id,
                    &refund_core.payment_id,
                    &refund.merchant_id,
                    merchant_account.storage_scheme,
                )
                .await
                .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?;

            let payment_intent = db
                .find_payment_intent_by_payment_id_merchant_id(
                    &(state.into()),
                    &payment_attempt.payment_id,
                    &refund.merchant_id,
                    &key_store,
                    merchant_account.storage_scheme,
                )
                .await
                .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?;
            let split_refunds = core_utils::get_split_refunds(SplitRefundInput {
                split_payment_request: payment_intent.split_payments.clone(),
                payment_charges: payment_attempt.charges.clone(),
                charge_id: payment_attempt.charge_id.clone(),
                refund_request: refund.split_refunds.clone(),
            })?;

            //trigger refund request to gateway
            let updated_refund = Box::pin(trigger_refund_to_gateway(
                state,
                &refund,
                &merchant_context,
                &payment_attempt,
                &payment_intent,
                None,
                split_refunds,
            ))
            .await?;
            add_refund_sync_task(
                db,
                &updated_refund,
                storage::ProcessTrackerRunner::RefundWorkflowRouter,
            )
            .await?;
        }
        (true, enums::RefundStatus::Pending) => {
            // create sync task
            add_refund_sync_task(
                db,
                &refund,
                storage::ProcessTrackerRunner::RefundWorkflowRouter,
            )
            .await?;
        }
        (_, _) => {
            //mark task as finished
            db.as_scheduler()
                .finish_process_with_business_status(
                    refund_tracker.clone(),
                    business_status::COMPLETED_BY_PT,
                )
                .await?;
        }
    };
    Ok(())
}


impl ConnectorNetworkTxnId {
    pub fn new(txn_id: masking::Secret<String>) -> Self {
        Self(txn_id)
    }
    pub fn get_id(&self) -> &masking::Secret<String> {
        &self.0
    }
}


impl ClientSecretType {
    pub fn generate_secret_key(&self) -> String {
        format!("cs_{}", self.secret.peek())
    }
}


impl api::RefundSync for Celero {}


OpenAPI Block Path: paths."/profile_acquirers"
{
  "post": {
    "tags": [
      "Profile Acquirer"
    ],
    "summary": "Profile Acquirer - Create",
    "description": "Create a new Profile Acquirer for accessing our APIs from your servers.",
    "operationId": "Create a Profile Acquirer",
    "requestBody": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/ProfileAcquirerCreate"
          }
        }
      },
      "required": true
    },
    "responses": {
      "200": {
        "description": "Profile Acquirer created",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ProfileAcquirerResponse"
            }
          }
        }
      },
      "400": {
        "description": "Invalid data"
      }
    },
    "security": [
      {
        "api_key": []
      }
    ]
  }
}


impl api::PayoutFulfill for Adyenplatform {}

impl api::PayoutFulfill for for Adyenplatform


    pub iban: Secret<String>,
    #[schema(value_type = String, example = "U2PVVSEV4V9Y")]
    pub reference: Secret<String>,
}

#[derive(Clone, Debug, serde::Deserialize)]
pub struct PaymentsConnectorThreeDsInvokeData {
    pub directory_server_id: String,
    pub three_ds_method_url: String,
    pub three_ds_method_data: String,
    pub message_version: Option<String>,
    pub three_ds_method_data_submission: bool,
}

#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, ToSchema)]
pub struct BacsBankTransferInstructions {
    #[schema(value_type = String, example = "Jane Doe")]
    pub account_holder_name: Secret<String>,
    #[schema(value_type = String, example = "10244123908")]
    pub account_number: Secret<String>,
    #[schema(value_type = String, example = "012")]
    pub sort_code: Secret<String>,
}

#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct MultibancoTransferInstructions {
    #[schema(value_type = String, example = "122385736258")]
    pub reference: Secret<String>,
    #[schema(value_type = String, example = "12345")]
    pub entity: String,
}

#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct DokuBankTransferInstructions {
    #[schema(value_type = String, example = "1707091200000")]
    pub expires_at: Option<i64>,
    #[schema(value_type = String, example = "122385736258")]
    pub reference: Secret<String>,
    #[schema(value_type = String)]
    pub instructions_url: Option<Url>,
}

#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct AchTransfer {
    #[schema(value_type = String, example = "122385736258")]
    pub account_number: Secret<String>,
    pub bank_name: String,
    #[schema(value_type = String, example = "012")]
    pub routing_number: Secret<String>,
    #[schema(value_type = String, example = "234")]
    pub swift_code: Secret<String>,
}

#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct ReceiverDetails {
    /// The amount received by receiver
    amount_received: i64,
    /// The amount charged by ACH
    amount_charged: Option<i64>,
    /// The amount remaining to be sent via ACH
    amount_remaining: Option<i64>,
}

#[cfg(feature = "v1")]
#[derive(Clone, Debug, PartialEq, serde::Serialize, ToSchema, router_derive::PolymorphicSchema)]
#[generate_schemas(PaymentsCreateResponseOpenApi)]
pub struct PaymentsResponse {
    /// Unique identifier for the payment. This ensures idempotency for multiple payments
    /// that have been done by a single merchant.
    #[schema(
        min_length = 30,
        max_length = 30,
        example = "pay_mbabizu24mvu3mela5njyhpit4",
        value_type = String,
    )]
    pub payment_id: id_type::PaymentId,

    /// This is an identifier for the merchant account. This is inferred from the API key
    /// provided during the request
    #[schema(max_length = 255, example = "merchant_1668273825", value_type = String)]
    pub merchant_id: id_type::MerchantId,

    #[schema(value_type = IntentStatus, example = "failed", default = "requires_confirmation")]
    pub status: api_enums::IntentStatus,

    /// The payment amount. Amount for the payment in lowest denomination of the currency. (i.e) in cents for USD denomination, in paisa for INR denomination etc.,
    #[schema(value_type = i64, example = 6540)]
    pub amount: MinorUnit,

    /// The payment net amount. net_amount = amount + surcharge_details.surcharge_amount + surcharge_details.tax_amount + shipping_cost + order_tax_amount,
    /// If no surcharge_details, shipping_cost, order_tax_amount, net_amount = amount
    #[schema(value_type = i64, example = 6540)]
    pub net_amount: MinorUnit,

    /// The shipping cost for the payment.
    #[schema(value_type = Option<i64>, example = 6540)]
    pub shipping_cost: Option<MinorUnit>,

    /// The amount (in minor units) that can still be captured for this payment. This is relevant when `capture_method` is `manual`. Once fully captured, or if `capture_method` is `automatic` and payment succeeded, this will be 0.
    #[schema(value_type = i64, minimum = 100, example = 6540)]
    pub amount_capturable: MinorUnit,

    /// The total amount (in minor units) that has been captured for this payment. For `fauxpay` sandbox connector, this might reflect the authorized amount if `status` is `succeeded` even if `capture_method` was `manual`.
    #[schema(value_type = Option<i64>, example = 6540)]
    pub amount_received: Option<MinorUnit>,

    /// The name of the payment connector (e.g., 'stripe', 'adyen') that processed or is processing this payment.
    #[schema(example = "stripe")]
    pub connector: Option<String>,

    /// A secret token unique to this payment intent. It is primarily used by client-side applications (e.g., Hyperswitch SDKs) to authenticate actions like confirming the payment or handling next actions. This secret should be handled carefully and not exposed publicly beyond its intended client-side use.
    #[schema(value_type = Option<String>, example = "pay_U42c409qyHwOkWo3vK60_secret_el9ksDkiB8hi6j9N78yo")]
    pub client_secret: Option<Secret<String>>,

    /// Timestamp indicating when this payment intent was created, in ISO 8601 format.
    #[schema(example = "2022-09-10T10:11:12Z")]
    #[serde(with = "common_utils::custom_serde::iso8601::option")]
    pub created: Option<PrimitiveDateTime>,

    /// Three-letter ISO currency code (e.g., USD, EUR) for the payment amount.
    #[schema(value_type = Currency, example = "USD")]
    pub currency: String,

    /// The identifier for the customer object. If not provided the customer ID will be autogenerated.
    /// This field will be deprecated soon. Please refer to `customer.id`
    #[schema(
        max_length = 64,
        min_length = 1,
        example = "cus_y3oqhf46pyzuxjbcn2giaqnb44",
        deprecated,
        value_type = Option<String>,
    )]
    pub customer_id: Option<id_type::CustomerId>,

    pub customer: Option<CustomerDetailsResponse>,

    /// An arbitrary string providing a description for the payment, often useful for display or internal record-keeping.
    #[schema(example = "It's my first payment request")]
    pub description: Option<String>,

    /// An array of refund objects associated with this payment. Empty or null if no refunds have been processed.
    #[schema(value_type = Option<Vec<RefundResponse>>)]
    pub refunds: Option<Vec<refunds::RefundResponse>>,

    /// List of disputes that happened on this intent
    #[schema(value_type = Option<Vec<DisputeResponsePaymentsRetrieve>>)]
    pub disputes: Option<Vec<disputes::DisputeResponsePaymentsRetrieve>>,

    /// List of attempts that happened on this intent
    #[schema(value_type = Option<Vec<PaymentAttemptResponse>>)]
    #[serde(skip_serializing_if = "Option::is_none")]
    pub attempts: Option<Vec<PaymentAttemptResponse>>,

    /// List of captures done on latest attempt
    #[schema(value_type = Option<Vec<CaptureResponse>>)]
    #[serde(skip_serializing_if = "Option::is_none")]
    pub captures: Option<Vec<CaptureResponse>>,

    /// A unique identifier to link the payment to a mandate, can be used instead of payment_method_data, in case of setting up recurring payments
    #[schema(max_length = 255, example = "mandate_iwer89rnjef349dni3")]
    pub mandate_id: Option<String>,

    /// Provided mandate information for creating a mandate
    pub mandate_data: Option<MandateData>,

    /// Indicates that you intend to make future payments with this Payment’s payment method. Providing this parameter will attach the payment method to the Customer, if present, after the Payment is confirmed and any required actions from the user are complete.
    #[schema(value_type = Option<FutureUsage>, example = "off_session")]
    pub setup_future_usage: Option<api_enums::FutureUsage>,

    /// Set to true to indicate that the customer is not in your checkout flow during this payment, and therefore is unable to authenticate. This parameter is intended for scenarios where you collect card details and charge them later. This parameter can only be used with confirm=true.
    #[schema(example = true)]
    pub off_session: Option<bool>,

    /// A timestamp (ISO 8601 code) that determines when the payment should be captured.
    /// Providing this field will automatically set `capture` to true
    #[schema(example = "2022-09-10T10:11:12Z")]
    #[serde(with = "common_utils::custom_serde::iso8601::option")]
    #[remove_in(PaymentsCreateResponseOpenApi)]
    pub capture_on: Option<PrimitiveDateTime>,

    /// This is the instruction for capture/ debit the money from the users' card. On the other hand authorization refers to blocking the amount on the users' payment method.
    #[schema(value_type = Option<CaptureMethod>, example = "automatic")]
    pub capture_method: Option<api_enums::CaptureMethod>,

    /// The payment method that is to be used
    #[schema(value_type = PaymentMethod, example = "bank_transfer")]
    pub payment_method: Option<api_enums::PaymentMethod>,

    /// The payment method information provided for making a payment
    #[schema(value_type = Option<PaymentMethodDataResponseWithBilling>, example = "bank_transfer")]
    #[serde(serialize_with = "serialize_payment_method_data_response")]
    pub payment_method_data: Option<PaymentMethodDataResponseWithBilling>,

    /// Provide a reference to a stored payment method
    #[schema(example = "187282ab-40ef-47a9-9206-5099ba31e432")]
    pub payment_token: Option<String>,

    /// The shipping address for the payment
    pub shipping: Option<Address>,

    /// The billing address for the payment
    pub billing: Option<Address>,

    /// Information about the product , quantity and amount for connectors. (e.g. Klarna)
    #[schema(value_type = Option<Vec<OrderDetailsWithAmount>>, example = r#"[{
        "product_name": "gillete creme",
        "quantity": 15,
        "amount" : 900
    }]"#)]
    pub order_details: Option<Vec<pii::SecretSerdeValue>>,

    /// description: The customer's email address
    /// This field will be deprecated soon. Please refer to `customer.email` object
    #[schema(max_length = 255, value_type = Option<String>, example = "johntest@test.com", deprecated)]
    pub email: crypto::OptionalEncryptableEmail,

    /// description: The customer's name
    /// This field will be deprecated soon. Please refer to `customer.name` object
    #[schema(value_type = Option<String>, max_length = 255, example = "John Test", deprecated)]
    pub name: crypto::OptionalEncryptableName,

    /// The customer's phone number
    /// This field will be deprecated soon. Please refer to `customer.phone` object
    #[schema(value_type = Option<String>, max_length = 255, example = "9123456789", deprecated)]
    pub phone: crypto::OptionalEncryptablePhone,

    /// The URL to redirect after the completion of the operation
    #[schema(example = "https://hyperswitch.io")]
    pub return_url: Option<String>,

    /// The transaction authentication can be set to undergo payer authentication. By default, the authentication will be marked as NO_THREE_DS, as the 3DS method helps with more robust payer authentication
    #[schema(value_type = Option<AuthenticationType>, example = "no_three_ds", default = "three_ds")]
    pub authentication_type: Option<api_enums::AuthenticationType>,

    /// For non-card charges, you can use this value as the complete description that appears on your customers’ statements. Must contain at least one letter, maximum 22 characters.
    #[schema(max_length = 255, example = "Hyperswitch Router")]
    pub statement_descriptor_name: Option<String>,

    /// Provides information about a card payment that customers see on their statements. Concatenated with the prefix (shortened descriptor) or statement descriptor that’s set on the account to form the complete statement descriptor. Maximum 255 characters for the concatenated descriptor.
    #[schema(max_length = 255, example = "Payment for shoes purchase")]
    pub statement_descriptor_suffix: Option<String>,

    /// If the payment requires further action from the customer (e.g., 3DS authentication, redirect to a bank page), this object will contain the necessary information for the client to proceed. Null if no further action is needed from the customer at this stage.
    pub next_action: Option<NextActionData>,

    /// If the payment intent was cancelled, this field provides a textual reason for the cancellation (e.g., "requested_by_customer", "abandoned").
    pub cancellation_reason: Option<String>,

    /// The connector-specific error code from the last failed payment attempt associated with this payment intent.
    #[schema(example = "E0001")]
    pub error_code: Option<String>,

    /// A human-readable error message from the last failed payment attempt associated with this payment intent.
    #[schema(example = "Failed while verifying the card")]
    pub error_message: Option<String>,

    /// error code unified across the connectors is received here if there was an error while calling connector
    #[remove_in(PaymentsCreateResponseOpenApi)]
    pub unified_code: Option<String>,

    /// error message unified across the connectors is received here if there was an error while calling connector
    #[remove_in(PaymentsCreateResponseOpenApi)]
    pub unified_message: Option<String>,

    /// Describes the type of payment flow experienced by the customer (e.g., 'redirect_to_url', 'invoke_sdk', 'display_qr_code').
    #[schema(value_type = Option<PaymentExperience>, example = "redirect_to_url")]
    pub payment_experience: Option<api_enums::PaymentExperience>,

    /// The specific payment method subtype used for this payment (e.g., 'credit_card', 'klarna', 'gpay'). This provides more granularity than the 'payment_method' field.
    #[schema(value_type = Option<PaymentMethodType>, example = "gpay")]
    pub payment_method_type: Option<api_enums::PaymentMethodType>,

    /// A label identifying the specific merchant connector account (MCA) used for this payment. This often combines the connector name, business country, and a custom label (e.g., "stripe_US_primary").
    #[schema(example = "stripe_US_food")]
    pub connector_label: Option<String>,

    /// The two-letter ISO country code (e.g., US, GB) of the business unit or profile under which this payment was processed.
    #[schema(value_type = Option<CountryAlpha2>, example = "US")]
    pub business_country: Option<api_enums::CountryAlpha2>,

    /// The label identifying the specific business unit or profile under which this payment was processed by the merchant.
    pub business_label: Option<String>,

    /// An optional sub-label for further categorization of the business unit or profile used for this payment.
    pub business_sub_label: Option<String>,

    /// Allowed Payment Method Types for a given PaymentIntent
    #[schema(value_type = Option<Vec<PaymentMethodType>>)]
    pub allowed_payment_method_types: Option<serde_json::Value>,

    /// ephemeral_key for the customer_id mentioned
    pub ephemeral_key: Option<EphemeralKeyCreateResponse>,

    /// If true the payment can be retried with same or different payment method which means the confirm call can be made again.
    pub manual_retry_allowed: Option<bool>,

    /// A unique identifier for a payment provided by the connector
    #[schema(value_type = Option<String>, example = "993672945374576J")]
    pub connector_transaction_id: Option<String>,

    /// Frm message contains information about the frm response
    pub frm_message: Option<FrmMessage>,

    /// You can specify up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. Metadata is useful for storing additional, structured information on an object.
    #[schema(value_type = Option<Object>, example = r#"{ "udf1": "some-value", "udf2": "some-value" }"#)]
    pub metadata: Option<serde_json::Value>,

    /// Additional data related to some connectors
    #[schema(value_type = Option<ConnectorMetadata>)]
    pub connector_metadata: Option<serde_json::Value>, // This is Value because it is fetched from DB and before putting in DB the type is validated

    /// Additional data that might be required by hyperswitch, to enable some specific features.
    #[schema(value_type = Option<FeatureMetadata>)]
    pub feature_metadata: Option<serde_json::Value>, // This is Value because it is fetched from DB and before putting in DB the type is validated

    /// reference(Identifier) to the payment at connector side
    #[schema(value_type = Option<String>, example = "993672945374576J")]
    pub reference_id: Option<String>,

    /// Details for Payment link
    pub payment_link: Option<PaymentLinkResponse>,
    /// The business profile that is associated with this payment
    #[schema(value_type = Option<String>)]
    pub profile_id: Option<id_type::ProfileId>,

    /// Details of surcharge applied on this payment
    pub surcharge_details: Option<RequestSurchargeDetails>,

    /// Total number of attempts associated with this payment
    pub attempt_count: i16,

    /// Denotes the action(approve or reject) taken by merchant in case of manual review. Manual review can occur when the transaction is marked as risky by the frm_processor, payment processor or when there is underpayment/over payment incase of crypto payment
    pub merchant_decision: Option<String>,

    /// Identifier of the connector ( merchant connector account ) which was chosen to make the payment
    #[schema(value_type = Option<String>)]
    pub merchant_connector_id: Option<id_type::MerchantConnectorAccountId>,

    /// If true, incremental authorization can be performed on this payment, in case the funds authorized initially fall short.
    pub incremental_authorization_allowed: Option<bool>,

    /// Total number of authorizations happened in an incremental_authorization payment
    pub authorization_count: Option<i32>,

    /// List of incremental authorizations happened to the payment
    pub incremental_authorizations: Option<Vec<IncrementalAuthorizationResponse>>,

    /// Details of external authentication
    pub external_authentication_details: Option<ExternalAuthenticationDetailsResponse>,

    /// Flag indicating if external 3ds authentication is made or not
    pub external_3ds_authentication_attempted: Option<bool>,

    /// Date Time for expiry of the payment
    #[schema(example = "2022-09-10T10:11:12Z")]
    #[serde(default, with = "common_utils::custom_serde::iso8601::option")]
    pub expires_on: Option<PrimitiveDateTime>,

    /// Payment Fingerprint, to identify a particular card.
    /// It is a 20 character long alphanumeric code.
    pub fingerprint: Option<String>,

    #[schema(value_type = Option<BrowserInformation>)]
    /// The browser information used for this payment
    pub browser_info: Option<serde_json::Value>,

    /// Indicates how the payment was initiated (e.g., ecommerce, mail, or telephone).
    #[schema(value_type = Option<PaymentChannel>)]
    pub payment_channel: Option<common_enums::PaymentChannel>,

    /// A unique identifier for the payment method used in this payment. If the payment method was saved or tokenized, this ID can be used to reference it for future transactions or recurring payments.
    pub payment_method_id: Option<String>,

    /// The network transaction ID is a unique identifier for the transaction as recognized by the payment network (e.g., Visa, Mastercard), this ID can be used to reference it for future transactions or recurring payments.
    pub network_transaction_id: Option<String>,

    /// Payment Method Status, refers to the status of the payment method used for this payment.
    #[schema(value_type = Option<PaymentMethodStatus>)]
    pub payment_method_status: Option<common_enums::PaymentMethodStatus>,

    /// Date time at which payment was updated
    #[schema(example = "2022-09-10T10:11:12Z")]
    #[serde(default, with = "common_utils::custom_serde::iso8601::option")]
    pub updated: Option<PrimitiveDateTime>,

    /// Fee information to be charged on the payment being collected
    #[schema(value_type = Option<ConnectorChargeResponseData>)]
    pub split_payments: Option<common_types::payments::ConnectorChargeResponseData>,

    /// You can specify up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. FRM Metadata is useful for storing additional, structured information on an object related to FRM.
    #[schema(value_type = Option<Object>, example = r#"{ "fulfillment_method" : "deliver", "coverage_request" : "fraud" }"#)]
    pub frm_metadata: Option<pii::SecretSerdeValue>,

    /// flag that indicates if extended authorization is applied on this payment or not
    #[schema(value_type = Option<bool>)]
    pub extended_authorization_applied: Option<ExtendedAuthorizationAppliedBool>,

    /// date and time after which this payment cannot be captured
    #[serde(default, with = "common_utils::custom_serde::iso8601::option")]
    pub capture_before: Option<PrimitiveDateTime>,

    /// Merchant's identifier for the payment/invoice. This will be sent to the connector
    /// if the connector provides support to accept multiple reference ids.
    /// In case the connector supports only one reference id, Hyperswitch's Payment ID will be sent as reference.
    #[schema(
        value_type = Option<String>,
        max_length = 255,
        example = "Custom_Order_id_123"
    )]
    pub merchant_order_reference_id: Option<String>,
    /// order tax amount calculated by tax connectors
    pub order_tax_amount: Option<MinorUnit>,

    /// Connector Identifier for the payment method
    pub connector_mandate_id: Option<String>,

    /// Method through which card was discovered
    #[schema(value_type = Option<CardDiscovery>, example = "manual")]
    pub card_discovery: Option<enums::CardDiscovery>,

    /// Indicates if 3ds challenge is forced
    pub force_3ds_challenge: Option<bool>,

    /// Indicates if 3ds challenge is triggered
    pub force_3ds_challenge_trigger: Option<bool>,

    /// Error code received from the issuer in case of failed payments
    pub issuer_error_code: Option<String>,

    /// Error message received from the issuer in case of failed payments
    pub issuer_error_message: Option<String>,

    /// Indicates if the redirection has to open in the iframe
    pub is_iframe_redirection_enabled: Option<bool>,

    /// Contains whole connector response
    #[schema(value_type = Option<String>)]
    pub whole_connector_response: Option<Secret<String>>,

    /// Allow partial authorization for this payment
    pub enable_partial_authorization: Option<bool>,
}

#[cfg(feature = "v2")]
#[derive(Clone, Debug, serde::Serialize, ToSchema)]
pub struct PaymentsListResponseItem {
    /// Unique identifier for the payment
    #[schema(
        min_length = 32,
        max_length = 64,
        example = "12345_pay_01926c58bc6e77c09e809964e72af8c8",
        value_type = String,
    )]
    pub id: id_type::GlobalPaymentId,

    /// This is an identifier for the merchant account. This is inferred from the API key
    /// provided during the request
    #[schema(max_length = 255, example = "merchant_1668273825", value_type = String)]
    pub merchant_id: id_type::MerchantId,

    /// The business profile that is associated with this payment
    #[schema(value_type = String)]
    pub profile_id: id_type::ProfileId,

    /// The identifier for the customer
    #[schema(
        min_length = 32,
        max_length = 64,
        example = "12345_cus_01926c58bc6e77c09e809964e72af8c8",
        value_type = Option<String>
    )]
    pub customer_id: Option<id_type::GlobalCustomerId>,

    /// Identifier for Payment Method used for the payment
    #[schema(value_type = Option<String>)]
    pub payment_method_id: Option<id_type::GlobalPaymentMethodId>,

    /// Status of the payment
    #[schema(value_type = IntentStatus, example = "failed", default = "requires_confirmation")]
    pub status: api_enums::IntentStatus,

    /// Amount related information for this payment and attempt
    pub amount: PaymentAmountDetailsResponse,

    /// Time when the payment was created
    #[schema(example = "2022-09-10T10:11:12Z")]
    #[serde(with = "common_utils::custom_serde::iso8601")]
    pub created: PrimitiveDateTime,

    /// The payment method type for this payment attempt
    #[schema(value_type = Option<PaymentMethod>, example = "wallet")]
    pub payment_method_type: Option<api_enums::PaymentMethod>,

    #[schema(value_type = Option<PaymentMethodType>, example = "apple_pay")]
    pub payment_method_subtype: Option<api_enums::PaymentMethodType>,

    /// The connector used for the payment
    #[schema(value_type = Option<Connector>, example = "stripe")]
    pub connector: Option<String>,

    /// Identifier of the connector ( merchant connector account ) which was chosen to make the payment
    #[schema(value_type = Option<String>)]
    pub merchant_connector_id: Option<id_type::MerchantConnectorAccountId>,

    /// Details of the customer
    pub customer: Option<CustomerDetailsResponse>,

    /// The reference id for the order in the merchant's system. This value can be passed by the merchant.
    #[schema(value_type = Option<String>)]
    pub merchant_reference_id: Option<id_type::PaymentReferenceId>,

    /// A unique identifier for a payment provided by the connector
    #[schema(value_type = Option<String>, example = "993672945374576J")]
    pub connector_payment_id: Option<String>,

    /// Reference to the capture at connector side
    pub connector_response_reference_id: Option<String>,

    /// Metadata is useful for storing additional, unstructured information on an object.
    #[schema(value_type = Option<Object>, example = r#"{ "udf1": "some-value", "udf2": "some-value" }"#)]
    pub metadata: Option<Secret<serde_json::Value>>,

    /// A description of the payment
    #[schema(example = "It's my first payment request")]
    pub description: Option<String>,

    /// The transaction authentication can be set to undergo payer authentication. By default, the authentication will be marked as NO_THREE_DS
    #[schema(value_type = Option<AuthenticationType>, example = "no_three_ds", default = "three_ds")]
    pub authentication_type: Option<api_enums::AuthenticationType>,

    /// This is the instruction for capture/ debit the money from the users' card. On the other hand authorization refers to blocking the amount on the users' payment method.
    #[schema(value_type = Option<CaptureMethod>, example = "automatic")]
    pub capture_method: Option<api_enums::CaptureMethod>,

    /// Indicates that you intend to make future payments with this Payment’s payment method. Providing this parameter will attach the payment method to the Customer, if present, after the Payment is confirmed and any required actions from the user are complete.
    #[schema(value_type = Option<FutureUsage>, example = "off_session")]
    pub setup_future_usage: Option<api_enums::FutureUsage>,

    /// Total number of attempts associated with this payment
    pub attempt_count: i16,

    /// Error details for the payment if any
    pub error: Option<ErrorDetails>,

    /// If the payment was cancelled the reason will be provided here
    pub cancellation_reason: Option<String>,

    /// Information about the product , quantity and amount for connectors. (e.g. Klarna)
    #[schema(value_type = Option<Vec<OrderDetailsWithAmount>>, example = r#"[{
        "product_name": "gillete creme",
        "quantity": 15,
        "amount" : 900
    }]"#)]
    pub order_details: Option<Vec<Secret<OrderDetailsWithAmount>>>,

    /// The URL to redirect after the completion of the operation
    #[schema(value_type = String, example = "https://hyperswitch.io")]
    pub return_url: Option<common_utils::types::Url>,

    /// For non-card charges, you can use this value as the complete description that appears on your customers’ statements. Must contain at least one letter, maximum 22 characters.
    #[schema(value_type = Option<String>, max_length = 255, example = "Hyperswitch Router")]
    pub statement_descriptor: Option<common_utils::types::StatementDescriptor>,

    /// Allowed Payment Method Types for a given PaymentIntent
    #[schema(value_type = Option<Vec<PaymentMethodType>>)]
    pub allowed_payment_method_types: Option<Vec<common_enums::PaymentMethodType>>,

    /// Total number of authorizations happened in an incremental_authorization payment
    pub authorization_count: Option<i32>,

    /// Date time at which payment was updated
    #[schema(example = "2022-09-10T10:11:12Z")]
    #[serde(default, with = "common_utils::custom_serde::iso8601::option")]
    pub modified_at: Option<PrimitiveDateTime>,
}

// Serialize is implemented because, this will be serialized in the api events.
// Usually request types should not have serialize implemented.
//
/// Request for Payment Intent Confirm
#[cfg(feature = "v2")]
#[derive(Debug, serde::Deserialize, serde::Serialize, ToSchema)]
#[serde(deny_unknown_fields)]
pub struct PaymentsConfirmIntentRequest {
    /// The URL to which you want the user to be redirected after the completion of the payment operation
    /// If this url is not passed, the url configured in the business profile will be used
    #[schema(value_type = Option<String>, example = "https://hyperswitch.io")]
    pub return_url: Option<common_utils::types::Url>,

    /// The payment instrument data to be used for the payment
    pub payment_method_data: PaymentMethodDataRequest,

    /// The payment method type to be used for the payment. This should match with the `payment_method_data` provided
    #[schema(value_type = PaymentMethod, example = "card")]
    pub payment_method_type: api_enums::PaymentMethod,

    /// The payment method subtype to be used for the payment. This should match with the `payment_method_data` provided
    #[schema(value_type = PaymentMethodType, example = "apple_pay")]
    pub payment_method_subtype: api_enums::PaymentMethodType,

    /// The shipping address for the payment. This will override the shipping address provided in the create-intent request
    pub shipping: Option<Address>,

    /// This "CustomerAcceptance" object is passed during Payments-Confirm request, it enlists the type, time, and mode of acceptance properties related to an acceptance done by the customer. The customer_acceptance sub object is usually passed by the SDK or client.
    #[schema(value_type = Option<CustomerAcceptance>)]
    pub customer_acceptance: Option<common_payments_types::CustomerAcceptance>,

    /// Additional details required by 3DS 2.0
    #[schema(value_type = Option<BrowserInformation>)]
    pub browser_info: Option<common_utils::types::BrowserInformation>,

    /// The payment_method_id to be associated with the payment
    #[schema(value_type = Option<String>)]
    pub payment_method_id: Option<id_type::GlobalPaymentMethodId>,

    #[schema(example = "187282ab-40ef-47a9-9206-5099ba31e432")]
    pub payment_token: Option<String>,

    /// Merchant connector details used to make payments.
    #[schema(value_type = Option<MerchantConnectorAuthDetails>)]
    pub merchant_connector_details: Option<common_types::domain::MerchantConnectorAuthDetails>,

    /// If true, returns stringified connector raw response body
    pub return_raw_connector_response: Option<bool>,
}

#[cfg(feature = "v2")]
#[derive(Debug, serde::Deserialize, serde::Serialize, ToSchema)]
#[serde(deny_unknown_fields)]
pub struct ProxyPaymentsRequest {
    /// The URL to which you want the user to be redirected after the completion of the payment operation
    /// If this url is not passed, the url configured in the business profile will be used
    #[schema(value_type = Option<String>, example = "https://hyperswitch.io")]
    pub return_url: Option<common_utils::types::Url>,

    pub amount: AmountDetails,

    pub recurring_details: mandates::ProcessorPaymentToken,

    pub shipping: Option<Address>,

    /// Additional details required by 3DS 2.0
    #[schema(value_type = Option<BrowserInformation>)]
    pub browser_info: Option<common_utils::types::BrowserInformation>,

    #[schema(example = "stripe")]
    pub connector: String,

    #[schema(value_type = String)]
    pub merchant_connector_id: id_type::MerchantConnectorAccountId,
}

#[derive(Clone, Debug, serde::Serialize, serde::Deserialize, ToSchema)]
#[serde(deny_unknown_fields)]
#[cfg(feature = "v2")]
pub struct ExternalVaultProxyPaymentsRequest {
    /// The URL to which you want the user to be redirected after the completion of the payment operation
    /// If this url is not passed, the url configured in the business profile will be used
    #[schema(value_type = Option<String>, example = "https://hyperswitch.io")]
    pub return_url: Option<common_utils::types::Url>,

    /// The payment instrument data to be used for the payment
    pub payment_method_data: ProxyPaymentMethodDataRequest,

    /// The payment method type to be used for the payment. This should match with the `payment_method_data` provided
    #[schema(value_type = PaymentMethod, example = "card")]
    pub payment_method_type: api_enums::PaymentMethod,

    /// The payment method subtype to be used for the payment. This should match with the `payment_method_data` provided
    #[schema(value_type = PaymentMethodType, example = "apple_pay")]
    pub payment_method_subtype: api_enums::PaymentMethodType,

    /// The shipping address for the payment. This will override the shipping address provided in the create-intent request
    pub shipping: Option<Address>,

    /// This "CustomerAcceptance" object is passed during Payments-Confirm request, it enlists the type, time, and mode of acceptance properties related to an acceptance done by the customer. The customer_acceptance sub object is usually passed by the SDK or client.
    #[schema(value_type = Option<CustomerAcceptance>)]
    pub customer_acceptance: Option<common_payments_types::CustomerAcceptance>,

    /// Additional details required by 3DS 2.0
    #[schema(value_type = Option<BrowserInformation>)]
    pub browser_info: Option<common_utils::types::BrowserInformation>,

    /// The payment_method_id to be associated with the payment
    #[schema(value_type = Option<String>)]
    pub payment_method_id: Option<id_type::GlobalPaymentMethodId>,

    #[schema(example = "187282ab-40ef-47a9-9206-5099ba31e432")]
    pub payment_token: Option<String>,

    /// Merchant connector details used to make payments.
    #[schema(value_type = Option<MerchantConnectorAuthDetails>)]


/// fn to get click to pay connector_account_id
    pub fn get_click_to_pay_connector_account_id(
        &self,
    ) -> Result<common_utils::id_type::MerchantConnectorAccountId, errors::ValidationError> {
        self.0
            .get(&enums::AuthenticationProduct::ClickToPay)
            .ok_or(errors::ValidationError::MissingRequiredField {
                field_name: "authentication_product_id.click_to_pay".to_string(),
            })
            .map_err(Report::from)
            .cloned()
    }


pub struct VgsErrorItem {
    pub status: u16,
    pub code: String,
    pub detail: Option<String>,
}


impl webhooks::IncomingWebhook for Digitalvirgo {
    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 Digitalvirgo


pub struct ApplepayMerchantVerificationRequest {
    pub domain_names: Vec<String>,
    pub merchant_connector_account_id: id_type::MerchantConnectorAccountId,
}


impl api::PaymentToken for Tsys {}


impl EventsConfig {
    pub async fn get_event_handler(&self) -> StorageResult<EventsHandler> {
        Ok(match self {
            Self::Kafka { kafka } => EventsHandler::Kafka(
                KafkaProducer::create(kafka)
                    .await
                    .change_context(StorageError::InitializationError)?,
            ),
            Self::Logs => EventsHandler::Logs(event_logger::EventLogger::default()),
        })
    }

    pub fn validate(&self) -> Result<(), ApplicationError> {
        match self {
            Self::Kafka { kafka } => kafka.validate(),
            Self::Logs => Ok(()),
        }
    }
}


pub fn get_secret(&self) -> String {
        self.0.clone()
    }