Repository: juspay/hyperswitch
File: crates/api_models/src/payments.rs (Rust)

Code before:
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct GpayMetadata {
    pub merchant_info: GpayMerchantInfo,
    pub allowed_payment_methods: Vec<GpayAllowedPaymentMethods>,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct GpaySessionTokenData {
    pub gpay: GpayMetadata,
}

#[derive(Debug, Clone, serde::Serialize)]
#[serde(tag = "wallet_name")]
#[serde(rename_all = "lowercase")]
pub enum SessionToken {
    Gpay {
        allowed_payment_methods: Vec<GpayAllowedPaymentMethods>,
        transaction_info: GpayTransactionInfo,
    },
    Klarna {
        session_token: String,
        session_id: String,
    },
    Paypal {
        session_token: String,
    },
    Applepay {
        epoch_timestamp: u64,
        expires_at: u64,
        merchant_session_identifier: String,
        nonce: String,
        merchant_identifier: String,
        domain_name: String,
        display_name: String,
        signature: String,
        operational_analytics_identifier: String,
        retries: u8,
        psp_id: String,
    },
}

#[derive(Default, Debug, serde::Serialize, Clone)]
pub struct PaymentsSessionResponse {
    pub payment_id: String,
    pub client_secret: Secret<String, pii::ClientSecret>,
    pub session_token: Vec<SessionToken>,
}

#[derive(Default, Debug, serde::Deserialize, serde::Serialize, Clone)]

Review comment (refactor):
**✅ Good Practice - Struct Flattening**

Nice refactoring! This change:
- ✅ Removes code duplication (`allowed_payment_methods` was redundant)
- ✅ Makes the structure cleaner by flattening `GpayMetadata` 
- ✅ Keeps `transaction_info` separate as it needs different handling

This follows the DRY principle and makes the enum variant more maintainable.

Code after:
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
#[serde(rename_all(serialize = "camelCase"))]
pub struct GpayMerchantInfo {
    pub merchant_name: String,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
#[serde(rename_all(serialize = "camelCase"))]
pub struct GpayMetadata {
    pub merchant_info: GpayMerchantInfo,
    pub allowed_payment_methods: Vec<GpayAllowedPaymentMethods>,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct GpaySessionTokenData {
    pub gpay: GpayMetadata,
}

#[derive(Debug, Clone, serde::Serialize)]
#[serde(tag = "wallet_name")]
#[serde(rename_all = "lowercase")]
pub enum SessionToken {
    Gpay {
        #[serde(flatten)]
        gpay_token: GpayMetadata,
        #[serde(rename(serialize = "transactionInfo"))]
        transaction_info: GpayTransactionInfo,
    },
    Klarna {
        session_token: String,
        session_id: String,
    },
    Paypal {
        session_token: String,
    },
    Applepay {
        epoch_timestamp: u64,
        expires_at: u64,
        merchant_session_identifier: String,
        nonce: String,
        merchant_identifier: String,
        domain_name: String,
        display_name: String,
        signature: String,
        operational_analytics_identifier: String,
        retries: u8,
        psp_id: String,
    },
}