Repository: juspay/hyperswitch
File: crates/hyperswitch_connectors/src/connectors/aci/transformers.rs (Rust)

Code before:
    pub challenge_indicator: Option<String>,
    #[serde(rename = "recurringType")]
    pub recurring_type: Option<AciRecurringType>,
}

fn get_three_ds_data(
    item: &PaymentsAuthorizeRouterData,
) -> (
    Option<String>,
    Option<String>,
    Option<bool>,
    Option<AciRecurringType>,
) {
    if item.is_three_ds() {
        let metadata = item.request.metadata.as_ref();
        let three_ds_two_flow = metadata.and_then(|meta| get_str("three_ds_flow", meta));
        let challenge_indicator =
            metadata.and_then(|meta| get_str("challenge_indicator", meta));
        let three_ds_two_enrolled = Some(item.request.enrolled_for_3ds);
        let recurring_type = determine_recurring_type_for_3ds(item);
        (
            three_ds_two_flow,
            challenge_indicator,
            three_ds_two_enrolled,
            recurring_type,
        )
    } else {
        (None, None, None, None)
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TransactionDetails {
    pub entity_id: Secret<String>,
    pub amount: StringMajorUnit,
    pub currency: String,
    pub payment_type: AciPaymentType,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct AciCancelRequest {
    pub entity_id: Secret<String>,
    pub payment_type: AciPaymentType,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct AciMandateRequest {
    pub entity_id: Secret<String>,

Review comment (suggestion):
@sai-harsha-vardhan Should we populate these 3DS values (`three_ds_two_flow` and `challenge_indicator`) using metadata, or calculate them internally?
CC: @dgeee13 

Code after:

#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct AciMandateResponse {
    pub id: String,
    pub result: ResultCode,
    pub build_number: String,
    pub timestamp: String,
}

#[derive(Debug, Clone, Serialize)]
#[serde(untagged)]
pub enum PaymentDetails {
    #[serde(rename = "card")]
    AciCard(Box<CardDetails>),
    BankRedirect(Box<BankRedirectionPMData>),
    Wallet(Box<WalletPMData>),
    Klarna,
    Mandate,
    AciNetworkToken(Box<AciNetworkTokenData>),
}

impl TryFrom<(&WalletData, &PaymentsAuthorizeRouterData)> for PaymentDetails {
    type Error = Error;
    fn try_from(value: (&WalletData, &PaymentsAuthorizeRouterData)) -> Result<Self, Self::Error> {
        let (wallet_data, item) = value;
        let payment_data = match wallet_data {
            WalletData::MbWayRedirect(_) => {
                let phone_details = item.get_billing_phone()?;
                Self::Wallet(Box::new(WalletPMData {
                    payment_brand: PaymentBrand::Mbway,
                    account_id: Some(phone_details.get_number_with_hash_country_code()?),
                }))
            }
            WalletData::AliPayRedirect { .. } => Self::Wallet(Box::new(WalletPMData {
                payment_brand: PaymentBrand::AliPay,
                account_id: None,
            })),
            WalletData::AliPayHkRedirect(_)
            | WalletData::AmazonPayRedirect(_)
            | WalletData::Paysera(_)
            | WalletData::Skrill(_)
            | WalletData::MomoRedirect(_)
            | WalletData::KakaoPayRedirect(_)
            | WalletData::GoPayRedirect(_)
            | WalletData::GcashRedirect(_)
            | WalletData::AmazonPay(_)
            | WalletData::ApplePay(_)
            | WalletData::ApplePayThirdPartySdk(_)
            | WalletData::DanaRedirect { .. }
            | WalletData::GooglePay(_)