diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs index 69b4700acb..2dc578ef75 100644 --- a/crates/api_models/src/payments.rs +++ b/crates/api_models/src/payments.rs @@ -1148,7 +1148,7 @@ pub enum BankDebitData { /// Payment Method data for Ach bank debit AchBankDebit { /// Billing details for bank debit - billing_details: BankDebitBilling, + billing_details: Option, /// Account number for ach bank debit payment #[schema(value_type = String, example = "000123456789")] account_number: Secret, @@ -1173,7 +1173,7 @@ pub enum BankDebitData { }, SepaBankDebit { /// Billing details for bank debit - billing_details: BankDebitBilling, + billing_details: Option, /// International bank account number (iban) for SEPA #[schema(value_type = String, example = "DE89370400440532013000")] iban: Secret, @@ -1183,7 +1183,7 @@ pub enum BankDebitData { }, BecsBankDebit { /// Billing details for bank debit - billing_details: BankDebitBilling, + billing_details: Option, /// Account number for Becs payment method #[schema(value_type = String, example = "000123456")] account_number: Secret, @@ -1196,7 +1196,7 @@ pub enum BankDebitData { }, BacsBankDebit { /// Billing details for bank debit - billing_details: BankDebitBilling, + billing_details: Option, /// Account number for Bacs payment method #[schema(value_type = String, example = "00012345")] account_number: Secret, @@ -1212,11 +1212,12 @@ pub enum BankDebitData { impl GetAddressFromPaymentMethodData for BankDebitData { fn get_billing_address(&self) -> Option
{ fn get_billing_address_inner( - bank_debit_billing: &BankDebitBilling, + bank_debit_billing: Option<&BankDebitBilling>, bank_account_holder_name: Option<&Secret>, ) -> Option
{ // We will always have address here - let mut address = bank_debit_billing.get_billing_address()?; + let mut address = bank_debit_billing + .and_then(GetAddressFromPaymentMethodData::get_billing_address)?; // Prefer `account_holder_name` over `name` address.address.as_mut().map(|address| { @@ -1248,7 +1249,10 @@ impl GetAddressFromPaymentMethodData for BankDebitData { billing_details, bank_account_holder_name, .. - } => get_billing_address_inner(billing_details, bank_account_holder_name.as_ref()), + } => get_billing_address_inner( + billing_details.as_ref(), + bank_account_holder_name.as_ref(), + ), } } } @@ -1447,7 +1451,7 @@ impl GetAddressFromPaymentMethodData for PaymentMethodData { Self::Wallet(wallet_data) => wallet_data.get_billing_address(), Self::PayLater(pay_later) => pay_later.get_billing_address(), Self::BankRedirect(_) => None, - Self::BankDebit(_) => None, + Self::BankDebit(bank_debit_data) => bank_debit_data.get_billing_address(), Self::BankTransfer(_) => None, Self::Voucher(voucher_data) => voucher_data.get_billing_address(), Self::Crypto(_) @@ -2241,11 +2245,11 @@ impl GetAddressFromPaymentMethodData for BankTransferData { #[derive(serde::Deserialize, serde::Serialize, Debug, Clone, ToSchema, Eq, PartialEq)] pub struct BankDebitBilling { /// The billing name for bank debits - #[schema(value_type = String, example = "John Doe")] - pub name: Secret, + #[schema(value_type = Option, example = "John Doe")] + pub name: Option>, /// The billing email for bank debits - #[schema(value_type = String, example = "example@example.com")] - pub email: Email, + #[schema(value_type = Option, example = "example@example.com")] + pub email: Option, /// The billing address for bank debits pub address: Option, } @@ -2253,19 +2257,19 @@ pub struct BankDebitBilling { impl GetAddressFromPaymentMethodData for BankDebitBilling { fn get_billing_address(&self) -> Option
{ let address = if let Some(mut address) = self.address.clone() { - address.first_name = Some(self.name.clone()); + address.first_name = self.name.clone().or(address.first_name); Address { address: Some(address), - email: Some(self.email.clone()), + email: self.email.clone(), phone: None, } } else { Address { address: Some(AddressDetails { - first_name: Some(self.name.clone()), + first_name: self.name.clone(), ..AddressDetails::default() }), - email: Some(self.email.clone()), + email: self.email.clone(), phone: None, } }; @@ -4898,14 +4902,14 @@ mod billing_from_payment_method_data { let test_first_name = Secret::new(String::from("Chaser")); let bank_redirect_billing = BankDebitBilling { - name: test_first_name.clone(), + name: Some(test_first_name.clone()), address: None, - email: test_email.clone(), + email: Some(test_email.clone()), }; let ach_bank_debit_payment_method_data = PaymentMethodData::BankDebit(BankDebitData::AchBankDebit { - billing_details: bank_redirect_billing, + billing_details: Some(bank_redirect_billing), account_number: Secret::new("1234".to_string()), routing_number: Secret::new("1235".to_string()), card_holder_name: None, diff --git a/crates/router/src/connector/adyen/transformers.rs b/crates/router/src/connector/adyen/transformers.rs index 77abaacf40..c911af50e5 100644 --- a/crates/router/src/connector/adyen/transformers.rs +++ b/crates/router/src/connector/adyen/transformers.rs @@ -1820,56 +1820,42 @@ fn build_shopper_reference(customer_id: &Option, merchant_id: String) -> .map(|c_id| format!("{}_{}", merchant_id, c_id)) } -impl<'a> TryFrom<&domain::BankDebitData> for AdyenPaymentMethod<'a> { +impl<'a> TryFrom<(&domain::BankDebitData, &types::PaymentsAuthorizeRouterData)> + for AdyenPaymentMethod<'a> +{ type Error = Error; - fn try_from(bank_debit_data: &domain::BankDebitData) -> Result { + fn try_from( + (bank_debit_data, item): (&domain::BankDebitData, &types::PaymentsAuthorizeRouterData), + ) -> Result { match bank_debit_data { domain::BankDebitData::AchBankDebit { account_number, routing_number, - card_holder_name, .. } => Ok(AdyenPaymentMethod::AchDirectDebit(Box::new( AchDirectDebitData { payment_type: PaymentType::AchDirectDebit, bank_account_number: account_number.clone(), bank_location_id: routing_number.clone(), - owner_name: card_holder_name.clone().ok_or( - errors::ConnectorError::MissingRequiredField { - field_name: "card_holder_name", - }, - )?, + owner_name: item.get_billing_full_name()?, }, ))), - domain::BankDebitData::SepaBankDebit { - iban, - bank_account_holder_name, - .. - } => Ok(AdyenPaymentMethod::SepaDirectDebit(Box::new( - SepaDirectDebitData { - owner_name: bank_account_holder_name.clone().ok_or( - errors::ConnectorError::MissingRequiredField { - field_name: "bank_account_holder_name", - }, - )?, + domain::BankDebitData::SepaBankDebit { iban, .. } => Ok( + AdyenPaymentMethod::SepaDirectDebit(Box::new(SepaDirectDebitData { + owner_name: item.get_billing_full_name()?, iban_number: iban.clone(), - }, - ))), + })), + ), domain::BankDebitData::BacsBankDebit { account_number, sort_code, - bank_account_holder_name, .. } => Ok(AdyenPaymentMethod::BacsDirectDebit(Box::new( BacsDirectDebitData { payment_type: PaymentType::BacsDirectDebit, bank_account_number: account_number.clone(), bank_location_id: sort_code.clone(), - holder_name: bank_account_holder_name.clone().ok_or( - errors::ConnectorError::MissingRequiredField { - field_name: "bank_account_holder_name", - }, - )?, + holder_name: item.get_billing_full_name()?, }, ))), domain::BankDebitData::BecsBankDebit { .. } => { @@ -2713,7 +2699,7 @@ impl<'a> let browser_info = get_browser_info(item.router_data)?; let additional_data = get_additional_data(item.router_data); let return_url = item.router_data.request.get_return_url()?; - let payment_method = AdyenPaymentMethod::try_from(bank_debit_data)?; + let payment_method = AdyenPaymentMethod::try_from((bank_debit_data, item.router_data))?; let country_code = get_country_code(item.router_data.get_optional_billing()); let request = AdyenPaymentRequest { amount, diff --git a/crates/router/src/connector/gocardless/transformers.rs b/crates/router/src/connector/gocardless/transformers.rs index e05f1b469a..97f1146b50 100644 --- a/crates/router/src/connector/gocardless/transformers.rs +++ b/crates/router/src/connector/gocardless/transformers.rs @@ -8,9 +8,8 @@ use serde::{Deserialize, Serialize}; use crate::{ connector::utils::{ - self, AddressDetailsData, BankDirectDebitBillingData, BrowserInformationData, - ConnectorCustomerData, PaymentsAuthorizeRequestData, PaymentsSetupMandateRequestData, - RouterData, + self, AddressDetailsData, BrowserInformationData, ConnectorCustomerData, + PaymentsAuthorizeRequestData, PaymentsSetupMandateRequestData, RouterData, }, core::errors, types::{ @@ -67,64 +66,19 @@ impl TryFrom<&types::ConnectorCustomerRouterData> for GocardlessCustomerRequest type Error = error_stack::Report; fn try_from(item: &types::ConnectorCustomerRouterData) -> Result { let email = item.request.get_email()?; - let billing_details = match &item.request.payment_method_data { - domain::PaymentMethodData::BankDebit(bank_debit_data) => { - match bank_debit_data.clone() { - domain::BankDebitData::AchBankDebit { - billing_details, .. - } => Ok(billing_details), - domain::BankDebitData::SepaBankDebit { - billing_details, .. - } => Ok(billing_details), - domain::BankDebitData::BecsBankDebit { - billing_details, .. - } => Ok(billing_details), - domain::BankDebitData::BacsBankDebit { .. } => { - Err(errors::ConnectorError::NotImplemented( - utils::get_unimplemented_payment_method_error_message("Gocardless"), - )) - } - } - } - domain::PaymentMethodData::Card(_) - | domain::PaymentMethodData::CardRedirect(_) - | domain::PaymentMethodData::Wallet(_) - | domain::PaymentMethodData::PayLater(_) - | domain::PaymentMethodData::BankRedirect(_) - | domain::PaymentMethodData::BankTransfer(_) - | domain::PaymentMethodData::Crypto(_) - | domain::PaymentMethodData::MandatePayment - | domain::PaymentMethodData::Reward - | domain::PaymentMethodData::Upi(_) - | domain::PaymentMethodData::Voucher(_) - | domain::PaymentMethodData::GiftCard(_) - | domain::PaymentMethodData::CardToken(_) => { - Err(errors::ConnectorError::NotImplemented( - utils::get_unimplemented_payment_method_error_message("Gocardless"), - )) - } - }?; + let billing_details_name = item.get_billing_full_name()?.expose(); - let billing_details_name = billing_details.name.expose(); - - if billing_details_name.is_empty() { - Err(errors::ConnectorError::MissingRequiredField { - field_name: "billing_details.name", - })? - } let (given_name, family_name) = billing_details_name .trim() .rsplit_once(' ') .unwrap_or((&billing_details_name, &billing_details_name)); - let billing_address = billing_details - .address - .ok_or_else(utils::missing_field_err("billing_details.address"))?; + let billing_address = item.get_billing_address()?; let metadata = CustomerMetaData { crm_id: item.customer_id.clone().map(Secret::new), }; - let region = get_region(&billing_address)?; + let region = get_region(billing_address)?; Ok(Self { customers: GocardlessCustomer { email, @@ -141,7 +95,7 @@ impl TryFrom<&types::ConnectorCustomerRouterData> for GocardlessCustomerRequest postal_code: billing_address.zip.to_owned(), // Should be populated based on the billing country swedish_identity_number: None, - city: billing_address.city.map(Secret::new), + city: billing_address.city.clone().map(Secret::new), }, }) } @@ -274,7 +228,7 @@ impl TryFrom<&types::TokenizationRouterData> for CustomerBankAccount { fn try_from(item: &types::TokenizationRouterData) -> Result { match &item.request.payment_method_data { domain::PaymentMethodData::BankDebit(bank_debit_data) => { - Self::try_from(bank_debit_data) + Self::try_from((bank_debit_data, item)) } domain::PaymentMethodData::Card(_) | domain::PaymentMethodData::CardRedirect(_) @@ -298,26 +252,21 @@ impl TryFrom<&types::TokenizationRouterData> for CustomerBankAccount { } } -impl TryFrom<&domain::BankDebitData> for CustomerBankAccount { +impl TryFrom<(&domain::BankDebitData, &types::TokenizationRouterData)> for CustomerBankAccount { type Error = error_stack::Report; - fn try_from(item: &domain::BankDebitData) -> Result { - match item { + fn try_from( + (bank_debit_data, item): (&domain::BankDebitData, &types::TokenizationRouterData), + ) -> Result { + match bank_debit_data { domain::BankDebitData::AchBankDebit { - billing_details, account_number, routing_number, bank_type, - bank_account_holder_name, .. } => { let bank_type = bank_type.ok_or_else(utils::missing_field_err("bank_type"))?; - let country_code = billing_details.get_billing_country()?; - let account_holder_name = - bank_account_holder_name - .clone() - .ok_or_else(utils::missing_field_err( - "payment_method_data.bank_debit.ach_bank_debit.bank_account_holder_name", - ))?; + let country_code = item.get_billing_country()?; + let account_holder_name = item.get_billing_full_name()?; let us_bank_account = USBankAccount { country_code, account_number: account_number.clone(), @@ -328,18 +277,11 @@ impl TryFrom<&domain::BankDebitData> for CustomerBankAccount { Ok(Self::USBankAccount(us_bank_account)) } domain::BankDebitData::BecsBankDebit { - billing_details, account_number, bsb_number, - bank_account_holder_name, } => { - let country_code = billing_details.get_billing_country()?; - let account_holder_name = - bank_account_holder_name - .clone() - .ok_or_else(utils::missing_field_err( - "payment_method_data.bank_debit.becs_bank_debit.bank_account_holder_name", - ))?; + let country_code = item.get_billing_country()?; + let account_holder_name = item.get_billing_full_name()?; let au_bank_account = AUBankAccount { country_code, account_number: account_number.clone(), @@ -348,17 +290,8 @@ impl TryFrom<&domain::BankDebitData> for CustomerBankAccount { }; Ok(Self::AUBankAccount(au_bank_account)) } - domain::BankDebitData::SepaBankDebit { - iban, - bank_account_holder_name, - .. - } => { - let account_holder_name = - bank_account_holder_name - .clone() - .ok_or_else(utils::missing_field_err( - "payment_method_data.bank_debit.sepa_bank_debit.bank_account_holder_name", - ))?; + domain::BankDebitData::SepaBankDebit { iban, .. } => { + let account_holder_name = item.get_billing_full_name()?; let international_bank_account = InternationalBankAccount { iban: iban.clone(), account_holder_name, diff --git a/crates/router/src/connector/mollie/transformers.rs b/crates/router/src/connector/mollie/transformers.rs index b61122fbfa..e2c3fc6699 100644 --- a/crates/router/src/connector/mollie/transformers.rs +++ b/crates/router/src/connector/mollie/transformers.rs @@ -195,7 +195,7 @@ impl TryFrom<&MollieRouterData<&types::PaymentsAuthorizeRouterData>> for MollieP get_payment_method_for_wallet(item.router_data, wallet_data) } domain::PaymentMethodData::BankDebit(ref directdebit_data) => { - PaymentMethodData::try_from(directdebit_data) + PaymentMethodData::try_from((directdebit_data, item.router_data)) } _ => Err( errors::ConnectorError::NotImplemented("Payment Method".to_string()).into(), @@ -254,18 +254,18 @@ impl TryFrom<&domain::BankRedirectData> for PaymentMethodData { } } -impl TryFrom<&domain::BankDebitData> for PaymentMethodData { +impl TryFrom<(&domain::BankDebitData, &types::PaymentsAuthorizeRouterData)> for PaymentMethodData { type Error = Error; - fn try_from(value: &domain::BankDebitData) -> Result { - match value { - domain::BankDebitData::SepaBankDebit { - bank_account_holder_name, - iban, - .. - } => Ok(Self::DirectDebit(Box::new(DirectDebitMethodData { - consumer_name: bank_account_holder_name.clone(), - consumer_account: iban.clone(), - }))), + fn try_from( + (bank_debit_data, item): (&domain::BankDebitData, &types::PaymentsAuthorizeRouterData), + ) -> Result { + match bank_debit_data { + domain::BankDebitData::SepaBankDebit { iban, .. } => { + Ok(Self::DirectDebit(Box::new(DirectDebitMethodData { + consumer_name: item.get_optional_billing_full_name(), + consumer_account: iban.clone(), + }))) + } _ => Err(errors::ConnectorError::NotImplemented("Payment method".to_string()).into()), } } diff --git a/crates/router/src/connector/stax/transformers.rs b/crates/router/src/connector/stax/transformers.rs index d48a2b1e82..95e5dbe4f4 100644 --- a/crates/router/src/connector/stax/transformers.rs +++ b/crates/router/src/connector/stax/transformers.rs @@ -227,7 +227,6 @@ impl TryFrom<&types::TokenizationRouterData> for StaxTokenRequest { Ok(Self::Card(stax_card_data)) } domain::PaymentMethodData::BankDebit(domain::BankDebitData::AchBankDebit { - billing_details, account_number, routing_number, bank_name, @@ -236,7 +235,7 @@ impl TryFrom<&types::TokenizationRouterData> for StaxTokenRequest { .. }) => { let stax_bank_data = StaxBankTokenizeData { - person_name: billing_details.name, + person_name: item.get_billing_full_name()?, bank_account: account_number, bank_routing: routing_number, bank_name: bank_name.ok_or_else(missing_field_err("bank_name"))?, diff --git a/crates/router/src/connector/stripe/transformers.rs b/crates/router/src/connector/stripe/transformers.rs index 6b82c87b5d..6c8277288c 100644 --- a/crates/router/src/connector/stripe/transformers.rs +++ b/crates/router/src/connector/stripe/transformers.rs @@ -1057,37 +1057,6 @@ impl From<&domain::BankDebitData> for StripePaymentMethodType { } } -impl From<&domain::BankDebitBilling> for StripeBillingAddress { - fn from(item: &domain::BankDebitBilling) -> Self { - Self { - email: Some(item.email.to_owned()), - country: item - .address - .as_ref() - .and_then(|address| address.country.to_owned()), - name: Some(item.name.to_owned()), - city: item - .address - .as_ref() - .and_then(|address| address.city.to_owned()), - address_line1: item - .address - .as_ref() - .and_then(|address| address.line1.to_owned()), - address_line2: item - .address - .as_ref() - .and_then(|address| address.line2.to_owned()), - zip_code: item - .address - .as_ref() - .and_then(|address| address.zip.to_owned()), - state: None, - phone: None, - } - } -} - impl TryFrom<(&domain::BankRedirectData, Option)> for StripeBillingAddress { type Error = error_stack::Report; @@ -1190,10 +1159,9 @@ impl TryFrom<(&domain::BankRedirectData, Option)> for StripeBillingAddress fn get_bank_debit_data( bank_debit_data: &domain::BankDebitData, -) -> (StripePaymentMethodType, BankDebitData, StripeBillingAddress) { +) -> (StripePaymentMethodType, BankDebitData) { match bank_debit_data { domain::BankDebitData::AchBankDebit { - billing_details, account_number, routing_number, .. @@ -1203,24 +1171,15 @@ fn get_bank_debit_data( account_number: account_number.to_owned(), routing_number: routing_number.to_owned(), }; - - let billing_data = StripeBillingAddress::from(billing_details); - (StripePaymentMethodType::Ach, ach_data, billing_data) + (StripePaymentMethodType::Ach, ach_data) } - domain::BankDebitData::SepaBankDebit { - billing_details, - iban, - .. - } => { + domain::BankDebitData::SepaBankDebit { iban, .. } => { let sepa_data = BankDebitData::Sepa { iban: iban.to_owned(), }; - - let billing_data = StripeBillingAddress::from(billing_details); - (StripePaymentMethodType::Sepa, sepa_data, billing_data) + (StripePaymentMethodType::Sepa, sepa_data) } domain::BankDebitData::BecsBankDebit { - billing_details, account_number, bsb_number, .. @@ -1229,12 +1188,9 @@ fn get_bank_debit_data( account_number: account_number.to_owned(), bsb_number: bsb_number.to_owned(), }; - - let billing_data = StripeBillingAddress::from(billing_details); - (StripePaymentMethodType::Becs, becs_data, billing_data) + (StripePaymentMethodType::Becs, becs_data) } domain::BankDebitData::BacsBankDebit { - billing_details, account_number, sort_code, .. @@ -1243,9 +1199,7 @@ fn get_bank_debit_data( account_number: account_number.to_owned(), sort_code: Secret::new(sort_code.clone().expose().replace('-', "")), }; - - let billing_data = StripeBillingAddress::from(billing_details); - (StripePaymentMethodType::Bacs, bacs_data, billing_data) + (StripePaymentMethodType::Bacs, bacs_data) } } } @@ -1308,7 +1262,7 @@ fn create_stripe_payment_method( )) } domain::PaymentMethodData::BankDebit(bank_debit_data) => { - let (pm_type, bank_debit_data, billing_address) = get_bank_debit_data(bank_debit_data); + let (pm_type, bank_debit_data) = get_bank_debit_data(bank_debit_data); let pm_data = StripePaymentMethodData::BankDebit(StripeBankDebitData { bank_specific_data: bank_debit_data, @@ -3680,7 +3634,7 @@ impl Ok(Self::try_from((wallet_data, None))?) } domain::PaymentMethodData::BankDebit(bank_debit_data) => { - let (_pm_type, bank_data, _) = get_bank_debit_data(&bank_debit_data); + let (_pm_type, bank_data) = get_bank_debit_data(&bank_debit_data); Ok(Self::BankDebit(StripeBankDebitData { bank_specific_data: bank_data, diff --git a/crates/router/src/connector/utils.rs b/crates/router/src/connector/utils.rs index 5a5b124261..872d287e87 100644 --- a/crates/router/src/connector/utils.rs +++ b/crates/router/src/connector/utils.rs @@ -75,6 +75,7 @@ pub trait RouterData { fn get_connector_meta(&self) -> Result; fn get_session_token(&self) -> Result; fn get_billing_first_name(&self) -> Result, Error>; + fn get_billing_full_name(&self) -> Result, Error>; fn get_billing_email(&self) -> Result; fn get_billing_phone_number(&self) -> Result, Error>; fn to_connector_meta(&self) -> Result @@ -171,7 +172,9 @@ impl RouterData for types::RouterData Result<&api::PhoneDetails, Error> { @@ -233,6 +236,15 @@ impl RouterData for types::RouterData Result, Error> { + self.get_optional_billing() + .and_then(|billing_details| billing_details.address.as_ref()) + .and_then(|billing_address| billing_address.get_optional_full_name()) + .ok_or_else(missing_field_err( + "payment_method_data.billing.address.first_name", + )) + } + fn get_billing_email(&self) -> Result { self.address .get_payment_method_billing() @@ -1502,19 +1514,6 @@ impl BankRedirectBillingData for domain::BankRedirectBilling { } } -pub trait BankDirectDebitBillingData { - fn get_billing_country(&self) -> Result; -} - -impl BankDirectDebitBillingData for domain::BankDebitBilling { - fn get_billing_country(&self) -> Result { - self.address - .as_ref() - .and_then(|address| address.country) - .ok_or_else(missing_field_err("billing_details.country")) - } -} - pub trait MandateData { fn get_end_date(&self, format: date_time::DateFormat) -> Result; fn get_metadata(&self) -> Result; diff --git a/crates/router/src/core/pm_auth.rs b/crates/router/src/core/pm_auth.rs index 88138d7909..1de52e940e 100644 --- a/crates/router/src/core/pm_auth.rs +++ b/crates/router/src/core/pm_auth.rs @@ -751,15 +751,15 @@ pub async fn retrieve_payment_method_from_auth_service( .get_required_value("email")?; let billing_details = BankDebitBilling { - name, - email, + name: Some(name), + email: Some(email), address: address_details, }; let payment_method_data = match &bank_account.account_details { pm_auth_types::PaymentMethodTypeDetails::Ach(ach) => { PaymentMethodData::BankDebit(BankDebitData::AchBankDebit { - billing_details, + billing_details: Some(billing_details), account_number: ach.account_number.clone(), routing_number: ach.routing_number.clone(), card_holder_name: None, @@ -771,7 +771,7 @@ pub async fn retrieve_payment_method_from_auth_service( } pm_auth_types::PaymentMethodTypeDetails::Bacs(bacs) => { PaymentMethodData::BankDebit(BankDebitData::BacsBankDebit { - billing_details, + billing_details: Some(billing_details), account_number: bacs.account_number.clone(), sort_code: bacs.sort_code.clone(), bank_account_holder_name: None, @@ -779,7 +779,7 @@ pub async fn retrieve_payment_method_from_auth_service( } pm_auth_types::PaymentMethodTypeDetails::Sepa(sepa) => { PaymentMethodData::BankDebit(BankDebitData::SepaBankDebit { - billing_details, + billing_details: Some(billing_details), iban: sepa.iban.clone(), bank_account_holder_name: None, }) diff --git a/crates/router/src/types/domain/payments.rs b/crates/router/src/types/domain/payments.rs index 58f2fa98ee..195681ff91 100644 --- a/crates/router/src/types/domain/payments.rs +++ b/crates/router/src/types/domain/payments.rs @@ -382,41 +382,25 @@ pub struct CardToken { #[serde(rename_all = "snake_case")] pub enum BankDebitData { AchBankDebit { - billing_details: BankDebitBilling, account_number: Secret, routing_number: Secret, - card_holder_name: Option>, - bank_account_holder_name: Option>, bank_name: Option, bank_type: Option, bank_holder_type: Option, }, SepaBankDebit { - billing_details: BankDebitBilling, iban: Secret, - bank_account_holder_name: Option>, }, BecsBankDebit { - billing_details: BankDebitBilling, account_number: Secret, bsb_number: Secret, - bank_account_holder_name: Option>, }, BacsBankDebit { - billing_details: BankDebitBilling, account_number: Secret, sort_code: Secret, - bank_account_holder_name: Option>, }, } -#[derive(serde::Deserialize, serde::Serialize, Debug, Clone, Eq, PartialEq)] -pub struct BankDebitBilling { - pub name: Secret, - pub email: Email, - pub address: Option, -} - #[derive(Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize)] #[serde(rename_all = "snake_case")] pub enum BankTransferData { @@ -899,70 +883,37 @@ impl From for BankDebitData { fn from(value: api_models::payments::BankDebitData) -> Self { match value { api_models::payments::BankDebitData::AchBankDebit { - billing_details, account_number, routing_number, - card_holder_name, - bank_account_holder_name, bank_name, bank_type, bank_holder_type, + .. } => Self::AchBankDebit { - billing_details: BankDebitBilling { - name: billing_details.name, - email: billing_details.email, - address: billing_details.address, - }, account_number, routing_number, - card_holder_name, - bank_account_holder_name, bank_name, bank_type, bank_holder_type, }, - api_models::payments::BankDebitData::SepaBankDebit { - billing_details, - iban, - bank_account_holder_name, - } => Self::SepaBankDebit { - billing_details: BankDebitBilling { - name: billing_details.name, - email: billing_details.email, - address: billing_details.address, - }, - iban, - bank_account_holder_name, - }, + api_models::payments::BankDebitData::SepaBankDebit { iban, .. } => { + Self::SepaBankDebit { iban } + } api_models::payments::BankDebitData::BecsBankDebit { - billing_details, account_number, bsb_number, - bank_account_holder_name, + .. } => Self::BecsBankDebit { - billing_details: BankDebitBilling { - name: billing_details.name, - email: billing_details.email, - address: billing_details.address, - }, account_number, bsb_number, - bank_account_holder_name, }, api_models::payments::BankDebitData::BacsBankDebit { - billing_details, account_number, sort_code, - bank_account_holder_name, + .. } => Self::BacsBankDebit { - billing_details: BankDebitBilling { - name: billing_details.name, - email: billing_details.email, - address: billing_details.address, - }, account_number, sort_code, - bank_account_holder_name, }, } } diff --git a/openapi/openapi_spec.json b/openapi/openapi_spec.json index c330816cea..391a917669 100644 --- a/openapi/openapi_spec.json +++ b/openapi/openapi_spec.json @@ -5272,20 +5272,18 @@ }, "BankDebitBilling": { "type": "object", - "required": [ - "name", - "email" - ], "properties": { "name": { "type": "string", "description": "The billing name for bank debits", - "example": "John Doe" + "example": "John Doe", + "nullable": true }, "email": { "type": "string", "description": "The billing email for bank debits", - "example": "example@example.com" + "example": "example@example.com", + "nullable": true }, "address": { "allOf": [ @@ -5309,7 +5307,6 @@ "type": "object", "description": "Payment Method data for Ach bank debit", "required": [ - "billing_details", "account_number", "routing_number", "card_holder_name", @@ -5320,7 +5317,12 @@ ], "properties": { "billing_details": { - "$ref": "#/components/schemas/BankDebitBilling" + "allOf": [ + { + "$ref": "#/components/schemas/BankDebitBilling" + } + ], + "nullable": true }, "account_number": { "type": "string", @@ -5365,13 +5367,17 @@ "sepa_bank_debit": { "type": "object", "required": [ - "billing_details", "iban", "bank_account_holder_name" ], "properties": { "billing_details": { - "$ref": "#/components/schemas/BankDebitBilling" + "allOf": [ + { + "$ref": "#/components/schemas/BankDebitBilling" + } + ], + "nullable": true }, "iban": { "type": "string", @@ -5396,13 +5402,17 @@ "becs_bank_debit": { "type": "object", "required": [ - "billing_details", "account_number", "bsb_number" ], "properties": { "billing_details": { - "$ref": "#/components/schemas/BankDebitBilling" + "allOf": [ + { + "$ref": "#/components/schemas/BankDebitBilling" + } + ], + "nullable": true }, "account_number": { "type": "string", @@ -5433,14 +5443,18 @@ "bacs_bank_debit": { "type": "object", "required": [ - "billing_details", "account_number", "sort_code", "bank_account_holder_name" ], "properties": { "billing_details": { - "$ref": "#/components/schemas/BankDebitBilling" + "allOf": [ + { + "$ref": "#/components/schemas/BankDebitBilling" + } + ], + "nullable": true }, "account_number": { "type": "string", diff --git a/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario20-Bank Debit-ach/Payments - Create/request.json b/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario20-Bank Debit-ach/Payments - Create/request.json index 78d949505f..53fe9371e4 100644 --- a/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario20-Bank Debit-ach/Payments - Create/request.json +++ b/postman/collection-dir/stripe/Flow Testcases/Happy Cases/Scenario20-Bank Debit-ach/Payments - Create/request.json @@ -75,6 +75,19 @@ } } }, + "billing": { + "address": { + "line1": "1467", + "line2": "HarrisonStreet", + "line3": "HarrisonStreet", + "city": "SanFransico", + "state": "California", + "zip": "94122", + "country": "US", + "first_name": "Swangi", + "last_name": "Kumari" + } + }, "metadata": { "order_details": { "product_name": "Apple iphone 15", diff --git a/postman/collection-json/stripe.postman_collection.json b/postman/collection-json/stripe.postman_collection.json index d4ed3bd3ae..09fec42b0b 100644 --- a/postman/collection-json/stripe.postman_collection.json +++ b/postman/collection-json/stripe.postman_collection.json @@ -16707,7 +16707,7 @@ "language": "json" } }, - "raw": "{\"amount\":1800,\"currency\":\"USD\",\"confirm\":true,\"business_label\":\"default\",\"capture_method\":\"automatic\",\"connector\":[\"stripe\"],\"customer_id\":\"klarna\",\"capture_on\":\"2022-09-10T10:11:12Z\",\"authentication_type\":\"three_ds\",\"email\":\"guest@example.com\",\"name\":\"John Doe\",\"phone\":\"999999999\",\"phone_country_code\":\"+65\",\"description\":\"Its my first payment request\",\"return_url\":\"https://google.com\",\"statement_descriptor_name\":\"Juspay\",\"statement_descriptor_suffix\":\"Router\",\"setup_future_usage\":\"off_session\",\"business_country\":\"US\",\"mandate_data\":{\"customer_acceptance\":{\"acceptance_type\":\"online\",\"accepted_at\":\"2022-09-10T10:11:12Z\",\"online\":{\"ip_address\":\"123.32.25.123\",\"user_agent\":\"Mozilla/5.0 (Linux; Android 12; SM-S906N Build/QP1A.190711.020; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/80.0.3987.119 Mobile Safari/537.36\"}},\"mandate_type\":{\"single_use\":{\"amount\":6540,\"currency\":\"USD\"}}},\"customer_acceptance\":{\"acceptance_type\":\"online\",\"accepted_at\":\"2022-09-10T10:11:12Z\",\"online\":{\"ip_address\":\"123.32.25.123\",\"user_agent\":\"Mozilla/5.0 (Linux; Android 12; SM-S906N Build/QP1A.190711.020; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/80.0.3987.119 Mobile Safari/537.36\"}},\"payment_method\":\"bank_debit\",\"payment_method_type\":\"ach\",\"payment_method_data\":{\"bank_debit\":{\"ach_bank_debit\":{\"billing_details\":{\"name\":\"John Doe\",\"email\":\"johndoe@example.com\"},\"account_number\":\"000123456789\",\"routing_number\":\"110000000\"}}},\"metadata\":{\"order_details\":{\"product_name\":\"Apple iphone 15\",\"quantity\":1,\"amount\":1800,\"account_name\":\"transaction_processing\"}},\"routing\":{\"type\":\"single\",\"data\":\"stripe\"}}" + "raw": "{\"amount\":1800,\"currency\":\"USD\",\"confirm\":true,\"business_label\":\"default\",\"capture_method\":\"automatic\",\"connector\":[\"stripe\"],\"customer_id\":\"klarna\",\"capture_on\":\"2022-09-10T10:11:12Z\",\"authentication_type\":\"three_ds\",\"email\":\"guest@example.com\",\"name\":\"JohnDoe\",\"phone\":\"999999999\",\"phone_country_code\":\"+65\",\"description\":\"Itsmyfirstpaymentrequest\",\"return_url\":\"https://google.com\",\"statement_descriptor_name\":\"Juspay\",\"statement_descriptor_suffix\":\"Router\",\"setup_future_usage\":\"off_session\",\"business_country\":\"US\",\"mandate_data\":{\"customer_acceptance\":{\"acceptance_type\":\"online\",\"accepted_at\":\"2022-09-10T10:11:12Z\",\"online\":{\"ip_address\":\"123.32.25.123\",\"user_agent\":\"Mozilla/5.0(Linux;Android12;SM-S906NBuild/QP1A.190711.020;wv)AppleWebKit/537.36(KHTML,likeGecko)Version/4.0Chrome/80.0.3987.119MobileSafari/537.36\"}},\"mandate_type\":{\"single_use\":{\"amount\":6540,\"currency\":\"USD\"}}},\"customer_acceptance\":{\"acceptance_type\":\"online\",\"accepted_at\":\"2022-09-10T10:11:12Z\",\"online\":{\"ip_address\":\"123.32.25.123\",\"user_agent\":\"Mozilla/5.0(Linux;Android12;SM-S906NBuild/QP1A.190711.020;wv)AppleWebKit/537.36(KHTML,likeGecko)Version/4.0Chrome/80.0.3987.119MobileSafari/537.36\"}},\"payment_method\":\"bank_debit\",\"payment_method_type\":\"ach\",\"payment_method_data\":{\"bank_debit\":{\"ach_bank_debit\":{\"billing_details\":{\"name\":\"JohnDoe\",\"email\":\"johndoe@example.com\"},\"account_number\":\"000123456789\",\"routing_number\":\"110000000\"}}},\"billing\":{\"address\":{\"line1\":\"1467\",\"line2\":\"HarrisonStreet\",\"line3\":\"HarrisonStreet\",\"city\":\"SanFransico\",\"state\":\"California\",\"zip\":\"94122\",\"country\":\"US\",\"first_name\":\"Swangi\",\"last_name\":\"Kumari\"}},\"metadata\":{\"order_details\":{\"product_name\":\"Appleiphone15\",\"quantity\":1,\"amount\":1800,\"account_name\":\"transaction_processing\"}},\"routing\":{\"type\":\"single\",\"data\":\"stripe\"}}" }, "url": { "raw": "{{baseUrl}}/payments",