diff --git a/CHANGELOG.md b/CHANGELOG.md index 2957f0749ca9..de6c7d7acb02 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,53 @@ All notable changes to HyperSwitch will be documented here. - - - +## 2024.04.08.0 + +### Features + +- **users:** Implemented cookie parsing for auth ([#4298](https://github.com/juspay/hyperswitch/pull/4298)) ([`2d394f9`](https://github.com/juspay/hyperswitch/commit/2d394f98e96d0beafca24abe2ac9f10a05460993)) + +### Bug Fixes + +- **locker:** Handle card duplication in payouts flow ([#4013](https://github.com/juspay/hyperswitch/pull/4013)) ([`2fac436`](https://github.com/juspay/hyperswitch/commit/2fac436683060b8e7c81b210dfdf468f5194f24c)) +- **mandates:** Store network transaction id only when `pg_agnostic` config is enabled in the `authorize_flow` ([#4318](https://github.com/juspay/hyperswitch/pull/4318)) ([`7b4c4fe`](https://github.com/juspay/hyperswitch/commit/7b4c4fea332d56f81a73b496fa0fefdbb64b3648)) +- **redis_interface:** Remove mget function from redis interface ([#4303](https://github.com/juspay/hyperswitch/pull/4303)) ([`14035d2`](https://github.com/juspay/hyperswitch/commit/14035d2f838d88c56fe37f78caab6c88bc8b33e4)) + +### Refactors + +- **payment_methods:** Add PayLater payment method data to new domain type to be used in connector module ([#4165](https://github.com/juspay/hyperswitch/pull/4165)) ([`6694852`](https://github.com/juspay/hyperswitch/commit/669485275db192b0e8e30f3528c0d61150d91847)) + +**Full Changelog:** [`2024.04.05.0...2024.04.08.0`](https://github.com/juspay/hyperswitch/compare/2024.04.05.0...2024.04.08.0) + +- - - + +## 2024.04.05.0 + +### Features + +- **payout-events:** Add kafka events for payout analytics ([#4211](https://github.com/juspay/hyperswitch/pull/4211)) ([`bc25f3f`](https://github.com/juspay/hyperswitch/commit/bc25f3fa40e807cc92d2d53a2287b92eff727d3c)) +- **router:** + - Store `network_reference_id` against the `payment_method_id` in the `payment_method_table` ([#4041](https://github.com/juspay/hyperswitch/pull/4041)) ([`21e2d78`](https://github.com/juspay/hyperswitch/commit/21e2d78117a9e25708b8c6a2280f6a836ee86072)) + - Use `NTID` in `MIT` payments if the `pg_agnostic_mit` config is enabled ([#4113](https://github.com/juspay/hyperswitch/pull/4113)) ([`b58d7a8`](https://github.com/juspay/hyperswitch/commit/b58d7a8e62eef9880f717731063101bf92af3f34)) + - Add NTID flow for cybersource ([#4193](https://github.com/juspay/hyperswitch/pull/4193)) ([`071462f`](https://github.com/juspay/hyperswitch/commit/071462f2af8efeb16e48d351bbae68fd2fd64179)) +- **webhooks:** Allow manually retrying delivery of outgoing webhooks ([#4176](https://github.com/juspay/hyperswitch/pull/4176)) ([`63d2b68`](https://github.com/juspay/hyperswitch/commit/63d2b6855acee1adeae2efff10f424e056af0bcb)) + +### Bug Fixes + +- **payouts:** Persist status updates in payouts table ([#4280](https://github.com/juspay/hyperswitch/pull/4280)) ([`02ffe7e`](https://github.com/juspay/hyperswitch/commit/02ffe7e48068a43d319d67e0e976420d201776db)) + +### Refactors + +- **connector:** + - [Multisafepay] handle authorize and psync 2xx failure error response ([#4124](https://github.com/juspay/hyperswitch/pull/4124)) ([`9ebe0f4`](https://github.com/juspay/hyperswitch/commit/9ebe0f4371f13c7527972242424af2d926c84b5e)) + - Add support for GooglePay recurring payments ([#4300](https://github.com/juspay/hyperswitch/pull/4300)) ([`622aac3`](https://github.com/juspay/hyperswitch/commit/622aac3015e95de55e83abd047b5c680ecd8d662)) +- **core:** Log the appropriate error message if the card fails to get saved in locker ([#4296](https://github.com/juspay/hyperswitch/pull/4296)) ([`9de3cdb`](https://github.com/juspay/hyperswitch/commit/9de3cdb7d37dd1d18c6a84368e70ceb52b7ae53a)) +- **payment_link:** Decouple shimmer css from main payment_link css for better performance ([#4286](https://github.com/juspay/hyperswitch/pull/4286)) ([`9453e8f`](https://github.com/juspay/hyperswitch/commit/9453e8fcfac49fc399343ee7c4c1598412b370c7)) + +**Full Changelog:** [`2024.04.04.0...2024.04.05.0`](https://github.com/juspay/hyperswitch/compare/2024.04.04.0...2024.04.05.0) + +- - - + ## 2024.04.04.0 ### Features diff --git a/config/config.example.toml b/config/config.example.toml index 0ed971c18bd9..ebb58b430538 100644 --- a/config/config.example.toml +++ b/config/config.example.toml @@ -185,6 +185,7 @@ cryptopay.base_url = "https://business-sandbox.cryptopay.me" cybersource.base_url = "https://apitest.cybersource.com/" dlocal.base_url = "https://sandbox.dlocal.com/" dummyconnector.base_url = "http://localhost:8080/dummy-connector" +ebanx.base_url = "https://sandbox.ebanxpay.com/" fiserv.base_url = "https://cert.api.fiservapps.com/" forte.base_url = "https://sandbox.forte.net/api/v3" globalpay.base_url = "https://apis.sandbox.globalpay.com/ucp/" diff --git a/config/deployments/production.toml b/config/deployments/production.toml index d0981c0f6135..aec8707bd069 100644 --- a/config/deployments/production.toml +++ b/config/deployments/production.toml @@ -39,6 +39,7 @@ cryptopay.base_url = "https://business.cryptopay.me/" cybersource.base_url = "https://api.cybersource.com/" dlocal.base_url = "https://sandbox.dlocal.com/" dummyconnector.base_url = "http://localhost:8080/dummy-connector" +ebanx.base_url = "https://sandbox.ebanxpay.com/" fiserv.base_url = "https://cert.api.fiservapps.com/" forte.base_url = "https://sandbox.forte.net/api/v3" globalpay.base_url = "https://apis.sandbox.globalpay.com/ucp/" diff --git a/config/deployments/sandbox.toml b/config/deployments/sandbox.toml index c8972c83602b..a0d0de0ad665 100644 --- a/config/deployments/sandbox.toml +++ b/config/deployments/sandbox.toml @@ -39,6 +39,7 @@ cryptopay.base_url = "https://business-sandbox.cryptopay.me" cybersource.base_url = "https://apitest.cybersource.com/" dlocal.base_url = "https://sandbox.dlocal.com/" dummyconnector.base_url = "http://localhost:8080/dummy-connector" +ebanx.base_url = "https://sandbox.ebanxpay.com/" fiserv.base_url = "https://cert.api.fiservapps.com/" forte.base_url = "https://sandbox.forte.net/api/v3" globalpay.base_url = "https://apis.sandbox.globalpay.com/ucp/" diff --git a/config/development.toml b/config/development.toml index 3b62ec3ca58d..7a6da9896b3d 100644 --- a/config/development.toml +++ b/config/development.toml @@ -108,6 +108,7 @@ cards = [ "cybersource", "dlocal", "dummyconnector", + "ebanx", "fiserv", "forte", "globalpay", @@ -181,6 +182,7 @@ cryptopay.base_url = "https://business-sandbox.cryptopay.me" cybersource.base_url = "https://apitest.cybersource.com/" dlocal.base_url = "https://sandbox.dlocal.com/" dummyconnector.base_url = "http://localhost:8080/dummy-connector" +ebanx.base_url = "https://sandbox.ebanxpay.com/" fiserv.base_url = "https://cert.api.fiservapps.com/" forte.base_url = "https://sandbox.forte.net/api/v3" globalpay.base_url = "https://apis.sandbox.globalpay.com/ucp/" diff --git a/config/docker_compose.toml b/config/docker_compose.toml index 769fdd8f842d..44594cd765ad 100644 --- a/config/docker_compose.toml +++ b/config/docker_compose.toml @@ -119,6 +119,7 @@ cryptopay.base_url = "https://business-sandbox.cryptopay.me" cybersource.base_url = "https://apitest.cybersource.com/" dlocal.base_url = "https://sandbox.dlocal.com/" dummyconnector.base_url = "http://localhost:8080/dummy-connector" +ebanx.base_url = "https://sandbox.ebanxpay.com/" fiserv.base_url = "https://cert.api.fiservapps.com/" forte.base_url = "https://sandbox.forte.net/api/v3" globalpay.base_url = "https://apis.sandbox.globalpay.com/ucp/" @@ -189,6 +190,7 @@ cards = [ "cybersource", "dlocal", "dummyconnector", + "ebanx", "fiserv", "forte", "globalpay", diff --git a/crates/api_models/src/enums.rs b/crates/api_models/src/enums.rs index e93371ef947c..60d8a9a98426 100644 --- a/crates/api_models/src/enums.rs +++ b/crates/api_models/src/enums.rs @@ -89,6 +89,7 @@ pub enum Connector { Cryptopay, Cybersource, Dlocal, + // Ebanx, Fiserv, Forte, Globalpay, diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs index de8142ddde26..6805363b2658 100644 --- a/crates/api_models/src/payments.rs +++ b/crates/api_models/src/payments.rs @@ -39,7 +39,7 @@ pub struct BankData { #[derive(serde::Deserialize)] pub struct BankCodeInformation { - pub bank_name: api_enums::BankNames, + pub bank_name: common_enums::BankNames, pub connector_codes: Vec, } @@ -51,7 +51,7 @@ pub struct ConnectorCode { #[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema, PartialEq, Eq)] pub struct BankCodeResponse { - pub bank_name: Vec, + pub bank_name: Vec, pub eligible_connectors: Vec, } @@ -1465,6 +1465,7 @@ impl GetPaymentMethodType for BankTransferData { Self::MandiriVaBankTransfer { .. } => api_enums::PaymentMethodType::MandiriVa, Self::Pix {} => api_enums::PaymentMethodType::Pix, Self::Pse {} => api_enums::PaymentMethodType::Pse, + Self::LocalBankTransfer { .. } => api_enums::PaymentMethodType::LocalBankTransfer, } } } @@ -1571,7 +1572,7 @@ pub struct AdditionalCardInfo { pub enum AdditionalPaymentData { Card(Box), BankRedirect { - bank_name: Option, + bank_name: Option, }, Wallet { apple_pay: Option, @@ -1622,7 +1623,7 @@ pub enum BankRedirectData { /// The hyperswitch bank code for eps #[schema(value_type = BankNames, example = "triodos_bank")] - bank_name: Option, + bank_name: Option, /// The country for bank payment #[schema(value_type = CountryAlpha2, example = "US")] @@ -1651,7 +1652,7 @@ pub enum BankRedirectData { /// The hyperswitch bank code for ideal #[schema(value_type = BankNames, example = "abn_amro")] - bank_name: Option, + bank_name: Option, /// The country for bank payment #[schema(value_type = CountryAlpha2, example = "US")] @@ -1668,7 +1669,7 @@ pub enum BankRedirectData { OnlineBankingCzechRepublic { // Issuer banks #[schema(value_type = BankNames)] - issuer: api_enums::BankNames, + issuer: common_enums::BankNames, }, OnlineBankingFinland { // Shopper Email @@ -1678,17 +1679,17 @@ pub enum BankRedirectData { OnlineBankingPoland { // Issuer banks #[schema(value_type = BankNames)] - issuer: api_enums::BankNames, + issuer: common_enums::BankNames, }, OnlineBankingSlovakia { // Issuer value corresponds to the bank #[schema(value_type = BankNames)] - issuer: api_enums::BankNames, + issuer: common_enums::BankNames, }, OpenBankingUk { // Issuer banks #[schema(value_type = BankNames)] - issuer: Option, + issuer: Option, /// The country for bank payment #[schema(value_type = CountryAlpha2, example = "US")] country: Option, @@ -1696,7 +1697,7 @@ pub enum BankRedirectData { Przelewy24 { //Issuer banks #[schema(value_type = Option)] - bank_name: Option, + bank_name: Option, // The billing details for bank redirect billing_details: BankRedirectBilling, @@ -1721,11 +1722,11 @@ pub enum BankRedirectData { OnlineBankingFpx { // Issuer banks #[schema(value_type = BankNames)] - issuer: api_enums::BankNames, + issuer: common_enums::BankNames, }, OnlineBankingThailand { #[schema(value_type = BankNames)] - issuer: api_enums::BankNames, + issuer: common_enums::BankNames, }, } @@ -2029,6 +2030,9 @@ pub enum BankTransferData { }, Pix {}, Pse {}, + LocalBankTransfer { + bank_code: Option, + }, } impl GetAddressFromPaymentMethodData for BankTransferData { @@ -2079,7 +2083,7 @@ impl GetAddressFromPaymentMethodData for BankTransferData { phone: None, email: Some(billing_details.email.clone()), }), - Self::Pix {} | Self::Pse {} => None, + Self::LocalBankTransfer { .. } | Self::Pix {} | Self::Pse {} => None, } } } diff --git a/crates/api_models/src/payouts.rs b/crates/api_models/src/payouts.rs index 1cdbfe41ebcc..4e2d9192554f 100644 --- a/crates/api_models/src/payouts.rs +++ b/crates/api_models/src/payouts.rs @@ -437,8 +437,6 @@ pub struct PayoutAttemptResponse { pub connector_transaction_id: Option, /// If the payout was cancelled the reason provided here pub cancellation_reason: Option, - /// Provide a reference to a stored payout method - pub payout_token: Option, /// error code unified across the connectors is received here if there was an error while calling connector pub unified_code: Option, /// error message unified across the connectors is received here if there was an error while calling connector diff --git a/crates/common_enums/src/enums.rs b/crates/common_enums/src/enums.rs index fefe0a93af2f..1134d072c2cf 100644 --- a/crates/common_enums/src/enums.rs +++ b/crates/common_enums/src/enums.rs @@ -2,6 +2,7 @@ use std::num::{ParseFloatError, TryFromIntError}; use serde::{Deserialize, Serialize}; use utoipa::ToSchema; + #[doc(hidden)] pub mod diesel_exports { pub use super::{ @@ -127,6 +128,7 @@ pub enum RoutableConnectors { Cryptopay, Cybersource, Dlocal, + // Ebanx, Fiserv, Forte, Globalpay, @@ -1421,6 +1423,7 @@ pub enum PaymentMethodType { FamilyMart, Seicomart, PayEasy, + LocalBankTransfer, } /// Indicates the type of payment method. Eg: 'card', 'wallet', etc. diff --git a/crates/common_enums/src/transformers.rs b/crates/common_enums/src/transformers.rs index 63abfdb3f73a..922d2a71c1bb 100644 --- a/crates/common_enums/src/transformers.rs +++ b/crates/common_enums/src/transformers.rs @@ -1842,6 +1842,7 @@ impl From for PaymentMethod { PaymentMethodType::PermataBankTransfer => Self::BankTransfer, PaymentMethodType::Pix => Self::BankTransfer, PaymentMethodType::Pse => Self::BankTransfer, + PaymentMethodType::LocalBankTransfer => Self::BankTransfer, PaymentMethodType::PayBright => Self::PayLater, PaymentMethodType::Paypal => Self::Wallet, PaymentMethodType::PaySafeCard => Self::GiftCard, diff --git a/crates/data_models/src/payouts/payouts.rs b/crates/data_models/src/payouts/payouts.rs index e5a95108ef26..4d70b6aaf5ed 100644 --- a/crates/data_models/src/payouts/payouts.rs +++ b/crates/data_models/src/payouts/payouts.rs @@ -51,7 +51,10 @@ pub trait PayoutsInterface { _merchant_id: &str, _filters: &PayoutFetchConstraints, _storage_scheme: MerchantStorageScheme, - ) -> error_stack::Result, errors::StorageError>; + ) -> error_stack::Result< + Vec<(Payouts, PayoutAttempt, diesel_models::Customer)>, + errors::StorageError, + >; #[cfg(feature = "olap")] async fn filter_payouts_by_time_range_constraints( @@ -155,7 +158,7 @@ pub enum PayoutsUpdate { status: Option, }, PayoutMethodIdUpdate { - payout_method_id: Option, + payout_method_id: String, }, RecurringUpdate { recurring: bool, @@ -163,6 +166,9 @@ pub enum PayoutsUpdate { AttemptCountUpdate { attempt_count: i16, }, + StatusUpdate { + status: storage_enums::PayoutStatus, + }, } #[derive(Clone, Debug, Default)] @@ -212,7 +218,7 @@ impl From for PayoutsUpdateInternal { ..Default::default() }, PayoutsUpdate::PayoutMethodIdUpdate { payout_method_id } => Self { - payout_method_id, + payout_method_id: Some(payout_method_id), ..Default::default() }, PayoutsUpdate::RecurringUpdate { recurring } => Self { @@ -223,6 +229,10 @@ impl From for PayoutsUpdateInternal { attempt_count: Some(attempt_count), ..Default::default() }, + PayoutsUpdate::StatusUpdate { status } => Self { + status: Some(status), + ..Default::default() + }, } } } diff --git a/crates/diesel_models/src/payouts.rs b/crates/diesel_models/src/payouts.rs index aa3eabf6d4e0..7cc348d445d0 100644 --- a/crates/diesel_models/src/payouts.rs +++ b/crates/diesel_models/src/payouts.rs @@ -88,7 +88,7 @@ pub enum PayoutsUpdate { status: Option, }, PayoutMethodIdUpdate { - payout_method_id: Option, + payout_method_id: String, }, RecurringUpdate { recurring: bool, @@ -96,6 +96,9 @@ pub enum PayoutsUpdate { AttemptCountUpdate { attempt_count: i16, }, + StatusUpdate { + status: storage_enums::PayoutStatus, + }, } #[derive(Clone, Debug, AsChangeset, router_derive::DebugAsDisplay)] @@ -168,7 +171,7 @@ impl From for PayoutsUpdateInternal { ..Default::default() }, PayoutsUpdate::PayoutMethodIdUpdate { payout_method_id } => Self { - payout_method_id, + payout_method_id: Some(payout_method_id), ..Default::default() }, PayoutsUpdate::RecurringUpdate { recurring } => Self { @@ -179,6 +182,10 @@ impl From for PayoutsUpdateInternal { attempt_count: Some(attempt_count), ..Default::default() }, + PayoutsUpdate::StatusUpdate { status } => Self { + status: Some(status), + ..Default::default() + }, } } } diff --git a/crates/euclid/src/frontend/dir/enums.rs b/crates/euclid/src/frontend/dir/enums.rs index ee64c4ca3333..22ab02358662 100644 --- a/crates/euclid/src/frontend/dir/enums.rs +++ b/crates/euclid/src/frontend/dir/enums.rs @@ -186,6 +186,7 @@ pub enum BankTransferType { PermataBankTransfer, Pix, Pse, + LocalBankTransfer, } #[derive( diff --git a/crates/euclid/src/frontend/dir/lowering.rs b/crates/euclid/src/frontend/dir/lowering.rs index b1f03e8dd557..f89877ca21a7 100644 --- a/crates/euclid/src/frontend/dir/lowering.rs +++ b/crates/euclid/src/frontend/dir/lowering.rs @@ -115,6 +115,7 @@ impl From for global_enums::PaymentMethodType { enums::BankTransferType::DanamonVa => Self::DanamonVa, enums::BankTransferType::MandiriVa => Self::MandiriVa, enums::BankTransferType::PermataBankTransfer => Self::PermataBankTransfer, + enums::BankTransferType::LocalBankTransfer => Self::LocalBankTransfer, } } } diff --git a/crates/euclid/src/frontend/dir/transformers.rs b/crates/euclid/src/frontend/dir/transformers.rs index c99b39e36f46..929b878f2c2f 100644 --- a/crates/euclid/src/frontend/dir/transformers.rs +++ b/crates/euclid/src/frontend/dir/transformers.rs @@ -143,6 +143,9 @@ impl IntoDirValue for (global_enums::PaymentMethodType, global_enums::PaymentMet global_enums::PaymentMethodType::DanamonVa => Ok(dirval!(BankTransferType = DanamonVa)), global_enums::PaymentMethodType::Indomaret => Ok(dirval!(VoucherType = Indomaret)), global_enums::PaymentMethodType::MandiriVa => Ok(dirval!(BankTransferType = MandiriVa)), + global_enums::PaymentMethodType::LocalBankTransfer => { + Ok(dirval!(BankTransferType = LocalBankTransfer)) + } global_enums::PaymentMethodType::PermataBankTransfer => { Ok(dirval!(BankTransferType = PermataBankTransfer)) } diff --git a/crates/kgraph_utils/src/transformers.rs b/crates/kgraph_utils/src/transformers.rs index 5bcb64fd8755..000a16a26348 100644 --- a/crates/kgraph_utils/src/transformers.rs +++ b/crates/kgraph_utils/src/transformers.rs @@ -262,6 +262,9 @@ impl IntoDirValue for (api_enums::PaymentMethodType, api_enums::PaymentMethod) { api_enums::PaymentMethodType::DanamonVa => Ok(dirval!(BankTransferType = DanamonVa)), api_enums::PaymentMethodType::Indomaret => Ok(dirval!(VoucherType = Indomaret)), api_enums::PaymentMethodType::MandiriVa => Ok(dirval!(BankTransferType = MandiriVa)), + api_enums::PaymentMethodType::LocalBankTransfer => { + Ok(dirval!(BankTransferType = LocalBankTransfer)) + } api_enums::PaymentMethodType::PermataBankTransfer => { Ok(dirval!(BankTransferType = PermataBankTransfer)) } diff --git a/crates/redis_interface/src/commands.rs b/crates/redis_interface/src/commands.rs index 21630fc3c087..d9b7072ff8c6 100644 --- a/crates/redis_interface/src/commands.rs +++ b/crates/redis_interface/src/commands.rs @@ -306,45 +306,6 @@ impl super::RedisConnectionPool { .await } - #[instrument(level = "DEBUG", skip(self))] - pub async fn get_multiple_keys( - &self, - keys: K, - ) -> CustomResult>, errors::RedisError> - where - V: FromRedis + Unpin + Send + 'static, - K: Into + Send + Debug, - { - self.pool - .mget(keys) - .await - .change_context(errors::RedisError::GetFailed) - } - - #[instrument(level = "DEBUG", skip(self))] - pub async fn get_and_deserialize_multiple_keys( - &self, - keys: K, - type_name: &'static str, - ) -> CustomResult>, errors::RedisError> - where - K: Into + Send + Debug, - V: serde::de::DeserializeOwned, - { - let data = self.get_multiple_keys::>(keys).await?; - data.into_iter() - .map(|value_bytes| { - value_bytes - .map(|bytes| { - bytes - .parse_struct(type_name) - .change_context(errors::RedisError::JsonSerializationFailed) - }) - .transpose() - }) - .collect() - } - #[instrument(level = "DEBUG", skip(self))] pub async fn serialize_and_set_multiple_hash_field_if_not_exist( &self, diff --git a/crates/router/build.rs b/crates/router/build.rs index b33c168833d2..99d6de0fda4d 100644 --- a/crates/router/build.rs +++ b/crates/router/build.rs @@ -2,7 +2,7 @@ fn main() { // Set thread stack size to 8 MiB for debug builds // Reference: https://doc.rust-lang.org/std/thread/#stack-size #[cfg(debug_assertions)] - println!("cargo:rustc-env=RUST_MIN_STACK=8388608"); // 8 * 1024 * 1024 = 8 MiB + println!("cargo:rustc-env=RUST_MIN_STACK=18388608"); // 8 * 1024 * 1024 = 8 MiB #[cfg(feature = "vergen")] router_env::vergen::generate_cargo_instructions(); diff --git a/crates/router/src/compatibility/stripe/errors.rs b/crates/router/src/compatibility/stripe/errors.rs index 0181ec4e7998..a7c54ef8f344 100644 --- a/crates/router/src/compatibility/stripe/errors.rs +++ b/crates/router/src/compatibility/stripe/errors.rs @@ -427,6 +427,7 @@ impl From for StripeErrorCode { | errors::ApiErrorResponse::InvalidJwtToken | errors::ApiErrorResponse::GenericUnauthorized { .. } | errors::ApiErrorResponse::AccessForbidden { .. } + | errors::ApiErrorResponse::InvalidCookie | errors::ApiErrorResponse::InvalidEphemeralKey => Self::Unauthorized, errors::ApiErrorResponse::InvalidRequestUrl | errors::ApiErrorResponse::InvalidHttpMethod diff --git a/crates/router/src/configs/settings.rs b/crates/router/src/configs/settings.rs index a0dce9912958..a15f9a11153c 100644 --- a/crates/router/src/configs/settings.rs +++ b/crates/router/src/configs/settings.rs @@ -323,7 +323,7 @@ pub struct ConnectorBankNames(pub HashMap); #[derive(Debug, Deserialize, Clone)] pub struct BanksVector { #[serde(deserialize_with = "deserialize_hashset")] - pub banks: HashSet, + pub banks: HashSet, } #[derive(Debug, Deserialize, Clone, Default)] @@ -500,6 +500,7 @@ pub struct Connectors { pub dlocal: ConnectorParams, #[cfg(feature = "dummy_connector")] pub dummyconnector: ConnectorParams, + pub ebanx: ConnectorParams, pub fiserv: ConnectorParams, pub forte: ConnectorParams, pub globalpay: ConnectorParams, diff --git a/crates/router/src/connector.rs b/crates/router/src/connector.rs index d786ed4e31b7..3c63aab54be0 100644 --- a/crates/router/src/connector.rs +++ b/crates/router/src/connector.rs @@ -17,6 +17,7 @@ pub mod cybersource; pub mod dlocal; #[cfg(feature = "dummy_connector")] pub mod dummyconnector; +pub mod ebanx; pub mod fiserv; pub mod forte; pub mod globalpay; @@ -64,12 +65,12 @@ pub use self::{ bambora::Bambora, bankofamerica::Bankofamerica, billwerk::Billwerk, bitpay::Bitpay, bluesnap::Bluesnap, boku::Boku, braintree::Braintree, cashtocode::Cashtocode, checkout::Checkout, coinbase::Coinbase, cryptopay::Cryptopay, cybersource::Cybersource, - dlocal::Dlocal, fiserv::Fiserv, forte::Forte, globalpay::Globalpay, globepay::Globepay, - gocardless::Gocardless, helcim::Helcim, iatapay::Iatapay, klarna::Klarna, mollie::Mollie, - multisafepay::Multisafepay, nexinets::Nexinets, nmi::Nmi, noon::Noon, nuvei::Nuvei, - opayo::Opayo, opennode::Opennode, payeezy::Payeezy, payme::Payme, paypal::Paypal, payu::Payu, - placetopay::Placetopay, powertranz::Powertranz, prophetpay::Prophetpay, rapyd::Rapyd, - riskified::Riskified, shift4::Shift4, signifyd::Signifyd, square::Square, stax::Stax, - stripe::Stripe, threedsecureio::Threedsecureio, trustpay::Trustpay, tsys::Tsys, volt::Volt, - wise::Wise, worldline::Worldline, worldpay::Worldpay, zen::Zen, + dlocal::Dlocal, ebanx::Ebanx, fiserv::Fiserv, forte::Forte, globalpay::Globalpay, + globepay::Globepay, gocardless::Gocardless, helcim::Helcim, iatapay::Iatapay, klarna::Klarna, + mollie::Mollie, multisafepay::Multisafepay, nexinets::Nexinets, nmi::Nmi, noon::Noon, + nuvei::Nuvei, opayo::Opayo, opennode::Opennode, payeezy::Payeezy, payme::Payme, paypal::Paypal, + payu::Payu, placetopay::Placetopay, powertranz::Powertranz, prophetpay::Prophetpay, + rapyd::Rapyd, riskified::Riskified, shift4::Shift4, signifyd::Signifyd, square::Square, + stax::Stax, stripe::Stripe, threedsecureio::Threedsecureio, trustpay::Trustpay, tsys::Tsys, + volt::Volt, wise::Wise, worldline::Worldline, worldpay::Worldpay, zen::Zen, }; diff --git a/crates/router/src/connector/aci/transformers.rs b/crates/router/src/connector/aci/transformers.rs index 846f619d1d02..b8f3af691451 100644 --- a/crates/router/src/connector/aci/transformers.rs +++ b/crates/router/src/connector/aci/transformers.rs @@ -1,6 +1,5 @@ use std::str::FromStr; -use api_models::enums::BankNames; use common_utils::pii::Email; use error_stack::report; use masking::{ExposeInterface, Secret}; @@ -153,19 +152,19 @@ impl TryFrom<&domain::WalletData> for PaymentDetails { impl TryFrom<( &AciRouterData<&types::PaymentsAuthorizeRouterData>, - &api_models::payments::BankRedirectData, + &domain::BankRedirectData, )> for PaymentDetails { type Error = Error; fn try_from( value: ( &AciRouterData<&types::PaymentsAuthorizeRouterData>, - &api_models::payments::BankRedirectData, + &domain::BankRedirectData, ), ) -> Result { let (item, bank_redirect_data) = value; let payment_data = match bank_redirect_data { - api_models::payments::BankRedirectData::Eps { country, .. } => { + domain::BankRedirectData::Eps { country, .. } => { Self::BankRedirect(Box::new(BankRedirectionPMData { payment_brand: PaymentBrand::Eps, bank_account_country: Some(country.ok_or( @@ -182,7 +181,7 @@ impl customer_email: None, })) } - api_models::payments::BankRedirectData::Giropay { + domain::BankRedirectData::Giropay { bank_account_bic, bank_account_iban, country, @@ -202,7 +201,7 @@ impl merchant_transaction_id: None, customer_email: None, })), - api_models::payments::BankRedirectData::Ideal { + domain::BankRedirectData::Ideal { bank_name, country, .. } => Self::BankRedirect(Box::new(BankRedirectionPMData { payment_brand: PaymentBrand::Ideal, @@ -223,7 +222,7 @@ impl merchant_transaction_id: None, customer_email: None, })), - api_models::payments::BankRedirectData::Sofort { country, .. } => { + domain::BankRedirectData::Sofort { country, .. } => { Self::BankRedirect(Box::new(BankRedirectionPMData { payment_brand: PaymentBrand::Sofortueberweisung, bank_account_country: Some(country.to_owned().ok_or( @@ -240,7 +239,7 @@ impl customer_email: None, })) } - api_models::payments::BankRedirectData::Przelewy24 { + domain::BankRedirectData::Przelewy24 { billing_details, .. } => Self::BankRedirect(Box::new(BankRedirectionPMData { payment_brand: PaymentBrand::Przelewy, @@ -253,7 +252,7 @@ impl merchant_transaction_id: None, customer_email: billing_details.email.to_owned(), })), - api_models::payments::BankRedirectData::Interac { email, country } => { + domain::BankRedirectData::Interac { email, country } => { Self::BankRedirect(Box::new(BankRedirectionPMData { payment_brand: PaymentBrand::InteracOnline, bank_account_country: Some(country.to_owned()), @@ -266,7 +265,7 @@ impl customer_email: Some(email.to_owned()), })) } - api_models::payments::BankRedirectData::Trustly { country } => { + domain::BankRedirectData::Trustly { country } => { Self::BankRedirect(Box::new(BankRedirectionPMData { payment_brand: PaymentBrand::Trustly, bank_account_country: None, @@ -281,16 +280,16 @@ impl customer_email: None, })) } - api_models::payments::BankRedirectData::Bizum { .. } - | api_models::payments::BankRedirectData::Blik { .. } - | api_models::payments::BankRedirectData::BancontactCard { .. } - | api_models::payments::BankRedirectData::OnlineBankingCzechRepublic { .. } - | api_models::payments::BankRedirectData::OnlineBankingFinland { .. } - | api_models::payments::BankRedirectData::OnlineBankingFpx { .. } - | api_models::payments::BankRedirectData::OnlineBankingPoland { .. } - | api_models::payments::BankRedirectData::OnlineBankingSlovakia { .. } - | api_models::payments::BankRedirectData::OnlineBankingThailand { .. } - | api_models::payments::BankRedirectData::OpenBankingUk { .. } => Err( + domain::BankRedirectData::Bizum { .. } + | domain::BankRedirectData::Blik { .. } + | domain::BankRedirectData::BancontactCard { .. } + | domain::BankRedirectData::OnlineBankingCzechRepublic { .. } + | domain::BankRedirectData::OnlineBankingFinland { .. } + | domain::BankRedirectData::OnlineBankingFpx { .. } + | domain::BankRedirectData::OnlineBankingPoland { .. } + | domain::BankRedirectData::OnlineBankingSlovakia { .. } + | domain::BankRedirectData::OnlineBankingThailand { .. } + | domain::BankRedirectData::OpenBankingUk { .. } => Err( errors::ConnectorError::NotImplemented("Payment method".to_string()), )?, }; @@ -320,7 +319,7 @@ pub struct BankRedirectionPMData { #[serde(rename = "bankAccount.country")] bank_account_country: Option, #[serde(rename = "bankAccount.bankName")] - bank_account_bank_name: Option, + bank_account_bank_name: Option, #[serde(rename = "bankAccount.bic")] bank_account_bic: Option>, #[serde(rename = "bankAccount.iban")] @@ -501,14 +500,14 @@ impl impl TryFrom<( &AciRouterData<&types::PaymentsAuthorizeRouterData>, - &api_models::payments::BankRedirectData, + &domain::BankRedirectData, )> for AciPaymentsRequest { type Error = Error; fn try_from( value: ( &AciRouterData<&types::PaymentsAuthorizeRouterData>, - &api_models::payments::BankRedirectData, + &domain::BankRedirectData, ), ) -> Result { let (item, bank_redirect_data) = value; @@ -527,14 +526,14 @@ impl impl TryFrom<( &AciRouterData<&types::PaymentsAuthorizeRouterData>, - &api_models::payments::PayLaterData, + &domain::payments::PayLaterData, )> for AciPaymentsRequest { type Error = Error; fn try_from( value: ( &AciRouterData<&types::PaymentsAuthorizeRouterData>, - &api_models::payments::PayLaterData, + &domain::payments::PayLaterData, ), ) -> Result { let (item, _pay_later_data) = value; diff --git a/crates/router/src/connector/adyen.rs b/crates/router/src/connector/adyen.rs index 44e889ed9db8..481eba0df702 100644 --- a/crates/router/src/connector/adyen.rs +++ b/crates/router/src/connector/adyen.rs @@ -202,6 +202,7 @@ impl ConnectorValidation for Adyen { | PaymentMethodType::Becs | PaymentMethodType::ClassicReward | PaymentMethodType::Pse + | PaymentMethodType::LocalBankTransfer | PaymentMethodType::Efecty | PaymentMethodType::PagoEfectivo | PaymentMethodType::RedCompra diff --git a/crates/router/src/connector/adyen/transformers.rs b/crates/router/src/connector/adyen/transformers.rs index a8bd1ccff30c..e47b570a062f 100644 --- a/crates/router/src/connector/adyen/transformers.rs +++ b/crates/router/src/connector/adyen/transformers.rs @@ -20,7 +20,7 @@ use crate::{ services, types::{ self, - api::{self, enums as api_enums}, + api::enums as api_enums, domain, storage::enums as storage_enums, transformers::{ForeignFrom, ForeignTryFrom}, @@ -746,13 +746,13 @@ impl TryFrom<&Box> for JCSVoucherData { } } -impl TryFrom<&api_enums::BankNames> for OnlineBankingCzechRepublicBanks { +impl TryFrom<&common_enums::BankNames> for OnlineBankingCzechRepublicBanks { type Error = Error; - fn try_from(bank_name: &api_enums::BankNames) -> Result { + fn try_from(bank_name: &common_enums::BankNames) -> Result { match bank_name { - api::enums::BankNames::KomercniBanka => Ok(Self::KB), - api::enums::BankNames::CeskaSporitelna => Ok(Self::CS), - api::enums::BankNames::PlatnoscOnlineKartaPlatnicza => Ok(Self::C), + common_enums::BankNames::KomercniBanka => Ok(Self::KB), + common_enums::BankNames::CeskaSporitelna => Ok(Self::CS), + common_enums::BankNames::PlatnoscOnlineKartaPlatnicza => Ok(Self::C), _ => Err(errors::ConnectorError::NotImplemented( utils::get_unimplemented_payment_method_error_message("Adyen"), ))?, @@ -809,29 +809,29 @@ pub enum OnlineBankingPolandBanks { ETransferPocztowy24, } -impl TryFrom<&api_enums::BankNames> for OnlineBankingPolandBanks { +impl TryFrom<&common_enums::BankNames> for OnlineBankingPolandBanks { type Error = Error; - fn try_from(bank_name: &api_enums::BankNames) -> Result { + fn try_from(bank_name: &common_enums::BankNames) -> Result { match bank_name { - api_models::enums::BankNames::BlikPSP => Ok(Self::BlikPSP), - api_models::enums::BankNames::PlaceZIPKO => Ok(Self::PlaceZIPKO), - api_models::enums::BankNames::MBank => Ok(Self::MBank), - api_models::enums::BankNames::PayWithING => Ok(Self::PayWithING), - api_models::enums::BankNames::SantanderPrzelew24 => Ok(Self::SantanderPrzelew24), - api_models::enums::BankNames::BankPEKAOSA => Ok(Self::BankPEKAOSA), - api_models::enums::BankNames::BankMillennium => Ok(Self::BankMillennium), - api_models::enums::BankNames::PayWithAliorBank => Ok(Self::PayWithAliorBank), - api_models::enums::BankNames::BankiSpoldzielcze => Ok(Self::BankiSpoldzielcze), - api_models::enums::BankNames::PayWithInteligo => Ok(Self::PayWithInteligo), - api_models::enums::BankNames::BNPParibasPoland => Ok(Self::BNPParibasPoland), - api_models::enums::BankNames::BankNowySA => Ok(Self::BankNowySA), - api_models::enums::BankNames::CreditAgricole => Ok(Self::CreditAgricole), - api_models::enums::BankNames::PayWithBOS => Ok(Self::PayWithBOS), - api_models::enums::BankNames::PayWithCitiHandlowy => Ok(Self::PayWithCitiHandlowy), - api_models::enums::BankNames::PayWithPlusBank => Ok(Self::PayWithPlusBank), - api_models::enums::BankNames::ToyotaBank => Ok(Self::ToyotaBank), - api_models::enums::BankNames::VeloBank => Ok(Self::VeloBank), - api_models::enums::BankNames::ETransferPocztowy24 => Ok(Self::ETransferPocztowy24), + common_enums::BankNames::BlikPSP => Ok(Self::BlikPSP), + common_enums::BankNames::PlaceZIPKO => Ok(Self::PlaceZIPKO), + common_enums::BankNames::MBank => Ok(Self::MBank), + common_enums::BankNames::PayWithING => Ok(Self::PayWithING), + common_enums::BankNames::SantanderPrzelew24 => Ok(Self::SantanderPrzelew24), + common_enums::BankNames::BankPEKAOSA => Ok(Self::BankPEKAOSA), + common_enums::BankNames::BankMillennium => Ok(Self::BankMillennium), + common_enums::BankNames::PayWithAliorBank => Ok(Self::PayWithAliorBank), + common_enums::BankNames::BankiSpoldzielcze => Ok(Self::BankiSpoldzielcze), + common_enums::BankNames::PayWithInteligo => Ok(Self::PayWithInteligo), + common_enums::BankNames::BNPParibasPoland => Ok(Self::BNPParibasPoland), + common_enums::BankNames::BankNowySA => Ok(Self::BankNowySA), + common_enums::BankNames::CreditAgricole => Ok(Self::CreditAgricole), + common_enums::BankNames::PayWithBOS => Ok(Self::PayWithBOS), + common_enums::BankNames::PayWithCitiHandlowy => Ok(Self::PayWithCitiHandlowy), + common_enums::BankNames::PayWithPlusBank => Ok(Self::PayWithPlusBank), + common_enums::BankNames::ToyotaBank => Ok(Self::ToyotaBank), + common_enums::BankNames::VeloBank => Ok(Self::VeloBank), + common_enums::BankNames::ETransferPocztowy24 => Ok(Self::ETransferPocztowy24), _ => Err(errors::ConnectorError::NotImplemented( utils::get_unimplemented_payment_method_error_message("Adyen"), ))?, @@ -874,15 +874,15 @@ pub enum OnlineBankingSlovakiaBanks { Viamo, } -impl TryFrom<&api_enums::BankNames> for OnlineBankingSlovakiaBanks { +impl TryFrom<&common_enums::BankNames> for OnlineBankingSlovakiaBanks { type Error = Error; - fn try_from(bank_name: &api_enums::BankNames) -> Result { + fn try_from(bank_name: &common_enums::BankNames) -> Result { match bank_name { - api::enums::BankNames::EPlatbyVUB => Ok(Self::Vub), - api::enums::BankNames::PostovaBanka => Ok(Self::Posto), - api::enums::BankNames::SporoPay => Ok(Self::Sporo), - api::enums::BankNames::TatraPay => Ok(Self::Tatra), - api::enums::BankNames::Viamo => Ok(Self::Viamo), + common_enums::BankNames::EPlatbyVUB => Ok(Self::Vub), + common_enums::BankNames::PostovaBanka => Ok(Self::Posto), + common_enums::BankNames::SporoPay => Ok(Self::Sporo), + common_enums::BankNames::TatraPay => Ok(Self::Tatra), + common_enums::BankNames::Viamo => Ok(Self::Viamo), _ => Err(errors::ConnectorError::NotImplemented( utils::get_unimplemented_payment_method_error_message("Adyen"), ))?, @@ -890,28 +890,28 @@ impl TryFrom<&api_enums::BankNames> for OnlineBankingSlovakiaBanks { } } -impl TryFrom<&api_enums::BankNames> for OnlineBankingFpxIssuer { +impl TryFrom<&common_enums::BankNames> for OnlineBankingFpxIssuer { type Error = Error; - fn try_from(bank_name: &api_enums::BankNames) -> Result { + fn try_from(bank_name: &common_enums::BankNames) -> Result { match bank_name { - api::enums::BankNames::AffinBank => Ok(Self::FpxAbb), - api::enums::BankNames::AgroBank => Ok(Self::FpxAgrobank), - api::enums::BankNames::AllianceBank => Ok(Self::FpxAbmb), - api::enums::BankNames::AmBank => Ok(Self::FpxAmb), - api::enums::BankNames::BankIslam => Ok(Self::FpxBimb), - api::enums::BankNames::BankMuamalat => Ok(Self::FpxBmmb), - api::enums::BankNames::BankRakyat => Ok(Self::FpxBkrm), - api::enums::BankNames::BankSimpananNasional => Ok(Self::FpxBsn), - api::enums::BankNames::CimbBank => Ok(Self::FpxCimbclicks), - api::enums::BankNames::HongLeongBank => Ok(Self::FpxHlb), - api::enums::BankNames::HsbcBank => Ok(Self::FpxHsbc), - api::enums::BankNames::KuwaitFinanceHouse => Ok(Self::FpxKfh), - api::enums::BankNames::Maybank => Ok(Self::FpxMb2u), - api::enums::BankNames::OcbcBank => Ok(Self::FpxOcbc), - api::enums::BankNames::PublicBank => Ok(Self::FpxPbb), - api::enums::BankNames::RhbBank => Ok(Self::FpxRhb), - api::enums::BankNames::StandardCharteredBank => Ok(Self::FpxScb), - api::enums::BankNames::UobBank => Ok(Self::FpxUob), + common_enums::BankNames::AffinBank => Ok(Self::FpxAbb), + common_enums::BankNames::AgroBank => Ok(Self::FpxAgrobank), + common_enums::BankNames::AllianceBank => Ok(Self::FpxAbmb), + common_enums::BankNames::AmBank => Ok(Self::FpxAmb), + common_enums::BankNames::BankIslam => Ok(Self::FpxBimb), + common_enums::BankNames::BankMuamalat => Ok(Self::FpxBmmb), + common_enums::BankNames::BankRakyat => Ok(Self::FpxBkrm), + common_enums::BankNames::BankSimpananNasional => Ok(Self::FpxBsn), + common_enums::BankNames::CimbBank => Ok(Self::FpxCimbclicks), + common_enums::BankNames::HongLeongBank => Ok(Self::FpxHlb), + common_enums::BankNames::HsbcBank => Ok(Self::FpxHsbc), + common_enums::BankNames::KuwaitFinanceHouse => Ok(Self::FpxKfh), + common_enums::BankNames::Maybank => Ok(Self::FpxMb2u), + common_enums::BankNames::OcbcBank => Ok(Self::FpxOcbc), + common_enums::BankNames::PublicBank => Ok(Self::FpxPbb), + common_enums::BankNames::RhbBank => Ok(Self::FpxRhb), + common_enums::BankNames::StandardCharteredBank => Ok(Self::FpxScb), + common_enums::BankNames::UobBank => Ok(Self::FpxUob), _ => Err(errors::ConnectorError::NotImplemented( utils::get_unimplemented_payment_method_error_message("Adyen"), ))?, @@ -919,15 +919,15 @@ impl TryFrom<&api_enums::BankNames> for OnlineBankingFpxIssuer { } } -impl TryFrom<&api_enums::BankNames> for OnlineBankingThailandIssuer { +impl TryFrom<&common_enums::BankNames> for OnlineBankingThailandIssuer { type Error = Error; - fn try_from(bank_name: &api_enums::BankNames) -> Result { + fn try_from(bank_name: &common_enums::BankNames) -> Result { match bank_name { - api::enums::BankNames::BangkokBank => Ok(Self::Bangkokbank), - api::enums::BankNames::KrungsriBank => Ok(Self::Krungsribank), - api::enums::BankNames::KrungThaiBank => Ok(Self::Krungthaibank), - api::enums::BankNames::TheSiamCommercialBank => Ok(Self::Siamcommercialbank), - api::enums::BankNames::KasikornBank => Ok(Self::Kbank), + common_enums::BankNames::BangkokBank => Ok(Self::Bangkokbank), + common_enums::BankNames::KrungsriBank => Ok(Self::Krungsribank), + common_enums::BankNames::KrungThaiBank => Ok(Self::Krungthaibank), + common_enums::BankNames::TheSiamCommercialBank => Ok(Self::Siamcommercialbank), + common_enums::BankNames::KasikornBank => Ok(Self::Kbank), _ => Err(errors::ConnectorError::NotImplemented( utils::get_unimplemented_payment_method_error_message("Adyen"), ))?, @@ -935,157 +935,159 @@ impl TryFrom<&api_enums::BankNames> for OnlineBankingThailandIssuer { } } -impl TryFrom<&api_enums::BankNames> for OpenBankingUKIssuer { +impl TryFrom<&common_enums::BankNames> for OpenBankingUKIssuer { type Error = Error; - fn try_from(bank_name: &api_enums::BankNames) -> Result { + fn try_from(bank_name: &common_enums::BankNames) -> Result { match bank_name { - api::enums::BankNames::OpenBankSuccess => Ok(Self::RedirectSuccess), - api::enums::BankNames::OpenBankFailure => Ok(Self::RedirectFailure), - api::enums::BankNames::OpenBankCancelled => Ok(Self::RedirectCancelled), - api::enums::BankNames::Aib => Ok(Self::Aib), - api::enums::BankNames::BankOfScotland => Ok(Self::BankOfScotland), - api::enums::BankNames::Barclays => Ok(Self::Barclays), - api::enums::BankNames::DanskeBank => Ok(Self::DanskeBank), - api::enums::BankNames::FirstDirect => Ok(Self::FirstDirect), - api::enums::BankNames::FirstTrust => Ok(Self::FirstTrust), - api::enums::BankNames::HsbcBank => Ok(Self::HsbcBank), - api::enums::BankNames::Halifax => Ok(Self::Halifax), - api::enums::BankNames::Lloyds => Ok(Self::Lloyds), - api::enums::BankNames::Monzo => Ok(Self::Monzo), - api::enums::BankNames::NatWest => Ok(Self::NatWest), - api::enums::BankNames::NationwideBank => Ok(Self::NationwideBank), - api::enums::BankNames::Revolut => Ok(Self::Revolut), - api::enums::BankNames::RoyalBankOfScotland => Ok(Self::RoyalBankOfScotland), - api::enums::BankNames::SantanderPrzelew24 => Ok(Self::SantanderPrzelew24), - api::enums::BankNames::Starling => Ok(Self::Starling), - api::enums::BankNames::TsbBank => Ok(Self::TsbBank), - api::enums::BankNames::TescoBank => Ok(Self::TescoBank), - api::enums::BankNames::UlsterBank => Ok(Self::UlsterBank), - enums::BankNames::AmericanExpress - | enums::BankNames::AffinBank - | enums::BankNames::AgroBank - | enums::BankNames::AllianceBank - | enums::BankNames::AmBank - | enums::BankNames::BankOfAmerica - | enums::BankNames::BankIslam - | enums::BankNames::BankMuamalat - | enums::BankNames::BankRakyat - | enums::BankNames::BankSimpananNasional - | enums::BankNames::BlikPSP - | enums::BankNames::CapitalOne - | enums::BankNames::Chase - | enums::BankNames::Citi - | enums::BankNames::CimbBank - | enums::BankNames::Discover - | enums::BankNames::NavyFederalCreditUnion - | enums::BankNames::PentagonFederalCreditUnion - | enums::BankNames::SynchronyBank - | enums::BankNames::WellsFargo - | enums::BankNames::AbnAmro - | enums::BankNames::AsnBank - | enums::BankNames::Bunq - | enums::BankNames::Handelsbanken - | enums::BankNames::HongLeongBank - | enums::BankNames::Ing - | enums::BankNames::Knab - | enums::BankNames::KuwaitFinanceHouse - | enums::BankNames::Moneyou - | enums::BankNames::Rabobank - | enums::BankNames::Regiobank - | enums::BankNames::SnsBank - | enums::BankNames::TriodosBank - | enums::BankNames::VanLanschot - | enums::BankNames::ArzteUndApothekerBank - | enums::BankNames::AustrianAnadiBankAg - | enums::BankNames::BankAustria - | enums::BankNames::Bank99Ag - | enums::BankNames::BankhausCarlSpangler - | enums::BankNames::BankhausSchelhammerUndSchatteraAg - | enums::BankNames::BankMillennium - | enums::BankNames::BankPEKAOSA - | enums::BankNames::BawagPskAg - | enums::BankNames::BksBankAg - | enums::BankNames::BrullKallmusBankAg - | enums::BankNames::BtvVierLanderBank - | enums::BankNames::CapitalBankGraweGruppeAg - | enums::BankNames::CeskaSporitelna - | enums::BankNames::Dolomitenbank - | enums::BankNames::EasybankAg - | enums::BankNames::EPlatbyVUB - | enums::BankNames::ErsteBankUndSparkassen - | enums::BankNames::FrieslandBank - | enums::BankNames::HypoAlpeadriabankInternationalAg - | enums::BankNames::HypoNoeLbFurNiederosterreichUWien - | enums::BankNames::HypoOberosterreichSalzburgSteiermark - | enums::BankNames::HypoTirolBankAg - | enums::BankNames::HypoVorarlbergBankAg - | enums::BankNames::HypoBankBurgenlandAktiengesellschaft - | enums::BankNames::KomercniBanka - | enums::BankNames::MBank - | enums::BankNames::MarchfelderBank - | enums::BankNames::Maybank - | enums::BankNames::OberbankAg - | enums::BankNames::OsterreichischeArzteUndApothekerbank - | enums::BankNames::OcbcBank - | enums::BankNames::PayWithING - | enums::BankNames::PlaceZIPKO - | enums::BankNames::PlatnoscOnlineKartaPlatnicza - | enums::BankNames::PosojilnicaBankEGen - | enums::BankNames::PostovaBanka - | enums::BankNames::PublicBank - | enums::BankNames::RaiffeisenBankengruppeOsterreich - | enums::BankNames::RhbBank - | enums::BankNames::SchelhammerCapitalBankAg - | enums::BankNames::StandardCharteredBank - | enums::BankNames::SchoellerbankAg - | enums::BankNames::SpardaBankWien - | enums::BankNames::SporoPay - | enums::BankNames::TatraPay - | enums::BankNames::Viamo - | enums::BankNames::VolksbankGruppe - | enums::BankNames::VolkskreditbankAg - | enums::BankNames::VrBankBraunau - | enums::BankNames::UobBank - | enums::BankNames::PayWithAliorBank - | enums::BankNames::BankiSpoldzielcze - | enums::BankNames::PayWithInteligo - | enums::BankNames::BNPParibasPoland - | enums::BankNames::BankNowySA - | enums::BankNames::CreditAgricole - | enums::BankNames::PayWithBOS - | enums::BankNames::PayWithCitiHandlowy - | enums::BankNames::PayWithPlusBank - | enums::BankNames::ToyotaBank - | enums::BankNames::VeloBank - | enums::BankNames::ETransferPocztowy24 - | enums::BankNames::PlusBank - | enums::BankNames::EtransferPocztowy24 - | enums::BankNames::BankiSpbdzielcze - | enums::BankNames::BankNowyBfgSa - | enums::BankNames::GetinBank - | enums::BankNames::Blik - | enums::BankNames::NoblePay - | enums::BankNames::IdeaBank - | enums::BankNames::EnveloBank - | enums::BankNames::NestPrzelew - | enums::BankNames::MbankMtransfer - | enums::BankNames::Inteligo - | enums::BankNames::PbacZIpko - | enums::BankNames::BnpParibas - | enums::BankNames::BankPekaoSa - | enums::BankNames::VolkswagenBank - | enums::BankNames::AliorBank - | enums::BankNames::Boz - | enums::BankNames::BangkokBank - | enums::BankNames::KrungsriBank - | enums::BankNames::KrungThaiBank - | enums::BankNames::TheSiamCommercialBank - | enums::BankNames::Yoursafe - | enums::BankNames::N26 - | enums::BankNames::NationaleNederlanden - | enums::BankNames::KasikornBank => Err(errors::ConnectorError::NotImplemented( - utils::get_unimplemented_payment_method_error_message("Adyen"), - ))?, + common_enums::BankNames::OpenBankSuccess => Ok(Self::RedirectSuccess), + common_enums::BankNames::OpenBankFailure => Ok(Self::RedirectFailure), + common_enums::BankNames::OpenBankCancelled => Ok(Self::RedirectCancelled), + common_enums::BankNames::Aib => Ok(Self::Aib), + common_enums::BankNames::BankOfScotland => Ok(Self::BankOfScotland), + common_enums::BankNames::Barclays => Ok(Self::Barclays), + common_enums::BankNames::DanskeBank => Ok(Self::DanskeBank), + common_enums::BankNames::FirstDirect => Ok(Self::FirstDirect), + common_enums::BankNames::FirstTrust => Ok(Self::FirstTrust), + common_enums::BankNames::HsbcBank => Ok(Self::HsbcBank), + common_enums::BankNames::Halifax => Ok(Self::Halifax), + common_enums::BankNames::Lloyds => Ok(Self::Lloyds), + common_enums::BankNames::Monzo => Ok(Self::Monzo), + common_enums::BankNames::NatWest => Ok(Self::NatWest), + common_enums::BankNames::NationwideBank => Ok(Self::NationwideBank), + common_enums::BankNames::Revolut => Ok(Self::Revolut), + common_enums::BankNames::RoyalBankOfScotland => Ok(Self::RoyalBankOfScotland), + common_enums::BankNames::SantanderPrzelew24 => Ok(Self::SantanderPrzelew24), + common_enums::BankNames::Starling => Ok(Self::Starling), + common_enums::BankNames::TsbBank => Ok(Self::TsbBank), + common_enums::BankNames::TescoBank => Ok(Self::TescoBank), + common_enums::BankNames::UlsterBank => Ok(Self::UlsterBank), + common_enums::BankNames::AmericanExpress + | common_enums::BankNames::AffinBank + | common_enums::BankNames::AgroBank + | common_enums::BankNames::AllianceBank + | common_enums::BankNames::AmBank + | common_enums::BankNames::BankOfAmerica + | common_enums::BankNames::BankIslam + | common_enums::BankNames::BankMuamalat + | common_enums::BankNames::BankRakyat + | common_enums::BankNames::BankSimpananNasional + | common_enums::BankNames::BlikPSP + | common_enums::BankNames::CapitalOne + | common_enums::BankNames::Chase + | common_enums::BankNames::Citi + | common_enums::BankNames::CimbBank + | common_enums::BankNames::Discover + | common_enums::BankNames::NavyFederalCreditUnion + | common_enums::BankNames::PentagonFederalCreditUnion + | common_enums::BankNames::SynchronyBank + | common_enums::BankNames::WellsFargo + | common_enums::BankNames::AbnAmro + | common_enums::BankNames::AsnBank + | common_enums::BankNames::Bunq + | common_enums::BankNames::Handelsbanken + | common_enums::BankNames::HongLeongBank + | common_enums::BankNames::Ing + | common_enums::BankNames::Knab + | common_enums::BankNames::KuwaitFinanceHouse + | common_enums::BankNames::Moneyou + | common_enums::BankNames::Rabobank + | common_enums::BankNames::Regiobank + | common_enums::BankNames::SnsBank + | common_enums::BankNames::TriodosBank + | common_enums::BankNames::VanLanschot + | common_enums::BankNames::ArzteUndApothekerBank + | common_enums::BankNames::AustrianAnadiBankAg + | common_enums::BankNames::BankAustria + | common_enums::BankNames::Bank99Ag + | common_enums::BankNames::BankhausCarlSpangler + | common_enums::BankNames::BankhausSchelhammerUndSchatteraAg + | common_enums::BankNames::BankMillennium + | common_enums::BankNames::BankPEKAOSA + | common_enums::BankNames::BawagPskAg + | common_enums::BankNames::BksBankAg + | common_enums::BankNames::BrullKallmusBankAg + | common_enums::BankNames::BtvVierLanderBank + | common_enums::BankNames::CapitalBankGraweGruppeAg + | common_enums::BankNames::CeskaSporitelna + | common_enums::BankNames::Dolomitenbank + | common_enums::BankNames::EasybankAg + | common_enums::BankNames::EPlatbyVUB + | common_enums::BankNames::ErsteBankUndSparkassen + | common_enums::BankNames::FrieslandBank + | common_enums::BankNames::HypoAlpeadriabankInternationalAg + | common_enums::BankNames::HypoNoeLbFurNiederosterreichUWien + | common_enums::BankNames::HypoOberosterreichSalzburgSteiermark + | common_enums::BankNames::HypoTirolBankAg + | common_enums::BankNames::HypoVorarlbergBankAg + | common_enums::BankNames::HypoBankBurgenlandAktiengesellschaft + | common_enums::BankNames::KomercniBanka + | common_enums::BankNames::MBank + | common_enums::BankNames::MarchfelderBank + | common_enums::BankNames::Maybank + | common_enums::BankNames::OberbankAg + | common_enums::BankNames::OsterreichischeArzteUndApothekerbank + | common_enums::BankNames::OcbcBank + | common_enums::BankNames::PayWithING + | common_enums::BankNames::PlaceZIPKO + | common_enums::BankNames::PlatnoscOnlineKartaPlatnicza + | common_enums::BankNames::PosojilnicaBankEGen + | common_enums::BankNames::PostovaBanka + | common_enums::BankNames::PublicBank + | common_enums::BankNames::RaiffeisenBankengruppeOsterreich + | common_enums::BankNames::RhbBank + | common_enums::BankNames::SchelhammerCapitalBankAg + | common_enums::BankNames::StandardCharteredBank + | common_enums::BankNames::SchoellerbankAg + | common_enums::BankNames::SpardaBankWien + | common_enums::BankNames::SporoPay + | common_enums::BankNames::TatraPay + | common_enums::BankNames::Viamo + | common_enums::BankNames::VolksbankGruppe + | common_enums::BankNames::VolkskreditbankAg + | common_enums::BankNames::VrBankBraunau + | common_enums::BankNames::UobBank + | common_enums::BankNames::PayWithAliorBank + | common_enums::BankNames::BankiSpoldzielcze + | common_enums::BankNames::PayWithInteligo + | common_enums::BankNames::BNPParibasPoland + | common_enums::BankNames::BankNowySA + | common_enums::BankNames::CreditAgricole + | common_enums::BankNames::PayWithBOS + | common_enums::BankNames::PayWithCitiHandlowy + | common_enums::BankNames::PayWithPlusBank + | common_enums::BankNames::ToyotaBank + | common_enums::BankNames::VeloBank + | common_enums::BankNames::ETransferPocztowy24 + | common_enums::BankNames::PlusBank + | common_enums::BankNames::EtransferPocztowy24 + | common_enums::BankNames::BankiSpbdzielcze + | common_enums::BankNames::BankNowyBfgSa + | common_enums::BankNames::GetinBank + | common_enums::BankNames::Blik + | common_enums::BankNames::NoblePay + | common_enums::BankNames::IdeaBank + | common_enums::BankNames::EnveloBank + | common_enums::BankNames::NestPrzelew + | common_enums::BankNames::MbankMtransfer + | common_enums::BankNames::Inteligo + | common_enums::BankNames::PbacZIpko + | common_enums::BankNames::BnpParibas + | common_enums::BankNames::BankPekaoSa + | common_enums::BankNames::VolkswagenBank + | common_enums::BankNames::AliorBank + | common_enums::BankNames::Boz + | common_enums::BankNames::BangkokBank + | common_enums::BankNames::KrungsriBank + | common_enums::BankNames::KrungThaiBank + | common_enums::BankNames::TheSiamCommercialBank + | common_enums::BankNames::Yoursafe + | common_enums::BankNames::N26 + | common_enums::BankNames::NationaleNederlanden + | common_enums::BankNames::KasikornBank => { + Err(errors::ConnectorError::NotImplemented( + utils::get_unimplemented_payment_method_error_message("Adyen"), + ))? + } } } } @@ -1426,58 +1428,48 @@ pub enum OpenBankingUKIssuer { pub struct AdyenTestBankNames<'a>(&'a str); -impl<'a> TryFrom<&api_enums::BankNames> for AdyenTestBankNames<'a> { +impl<'a> TryFrom<&common_enums::BankNames> for AdyenTestBankNames<'a> { type Error = Error; - fn try_from(bank: &api_enums::BankNames) -> Result { + fn try_from(bank: &common_enums::BankNames) -> Result { Ok(match bank { - api_models::enums::BankNames::AbnAmro => Self("1121"), - api_models::enums::BankNames::AsnBank => Self("1151"), - api_models::enums::BankNames::Bunq => Self("1152"), - api_models::enums::BankNames::Ing => Self("1154"), - api_models::enums::BankNames::Knab => Self("1155"), - api_models::enums::BankNames::N26 => Self("1156"), - api_models::enums::BankNames::NationaleNederlanden => Self("1157"), - api_models::enums::BankNames::Rabobank => Self("1157"), - api_models::enums::BankNames::Regiobank => Self("1158"), - api_models::enums::BankNames::Revolut => Self("1159"), - api_models::enums::BankNames::SnsBank => Self("1159"), - api_models::enums::BankNames::TriodosBank => Self("1159"), - api_models::enums::BankNames::VanLanschot => Self("1159"), - api_models::enums::BankNames::Yoursafe => Self("1159"), - api_models::enums::BankNames::BankAustria => { - Self("e6819e7a-f663-414b-92ec-cf7c82d2f4e5") - } - api_models::enums::BankNames::BawagPskAg => { - Self("ba7199cc-f057-42f2-9856-2378abf21638") - } - api_models::enums::BankNames::Dolomitenbank => { - Self("d5d5b133-1c0d-4c08-b2be-3c9b116dc326") - } - api_models::enums::BankNames::EasybankAg => { - Self("eff103e6-843d-48b7-a6e6-fbd88f511b11") - } - api_models::enums::BankNames::ErsteBankUndSparkassen => { + common_enums::BankNames::AbnAmro => Self("1121"), + common_enums::BankNames::AsnBank => Self("1151"), + common_enums::BankNames::Bunq => Self("1152"), + common_enums::BankNames::Ing => Self("1154"), + common_enums::BankNames::Knab => Self("1155"), + common_enums::BankNames::N26 => Self("1156"), + common_enums::BankNames::NationaleNederlanden => Self("1157"), + common_enums::BankNames::Rabobank => Self("1157"), + common_enums::BankNames::Regiobank => Self("1158"), + common_enums::BankNames::Revolut => Self("1159"), + common_enums::BankNames::SnsBank => Self("1159"), + common_enums::BankNames::TriodosBank => Self("1159"), + common_enums::BankNames::VanLanschot => Self("1159"), + common_enums::BankNames::Yoursafe => Self("1159"), + common_enums::BankNames::BankAustria => Self("e6819e7a-f663-414b-92ec-cf7c82d2f4e5"), + common_enums::BankNames::BawagPskAg => Self("ba7199cc-f057-42f2-9856-2378abf21638"), + common_enums::BankNames::Dolomitenbank => Self("d5d5b133-1c0d-4c08-b2be-3c9b116dc326"), + common_enums::BankNames::EasybankAg => Self("eff103e6-843d-48b7-a6e6-fbd88f511b11"), + common_enums::BankNames::ErsteBankUndSparkassen => { Self("3fdc41fc-3d3d-4ee3-a1fe-cd79cfd58ea3") } - api_models::enums::BankNames::HypoTirolBankAg => { + common_enums::BankNames::HypoTirolBankAg => { Self("6765e225-a0dc-4481-9666-e26303d4f221") } - api_models::enums::BankNames::PosojilnicaBankEGen => { + common_enums::BankNames::PosojilnicaBankEGen => { Self("65ef4682-4944-499f-828f-5d74ad288376") } - api_models::enums::BankNames::RaiffeisenBankengruppeOsterreich => { + common_enums::BankNames::RaiffeisenBankengruppeOsterreich => { Self("ee9fc487-ebe0-486c-8101-17dce5141a67") } - api_models::enums::BankNames::SchoellerbankAg => { + common_enums::BankNames::SchoellerbankAg => { Self("1190c4d1-b37a-487e-9355-e0a067f54a9f") } - api_models::enums::BankNames::SpardaBankWien => { - Self("8b0bfeea-fbb0-4337-b3a1-0e25c0f060fc") - } - api_models::enums::BankNames::VolksbankGruppe => { + common_enums::BankNames::SpardaBankWien => Self("8b0bfeea-fbb0-4337-b3a1-0e25c0f060fc"), + common_enums::BankNames::VolksbankGruppe => { Self("e2e97aaa-de4c-4e18-9431-d99790773433") } - api_models::enums::BankNames::VolkskreditbankAg => { + common_enums::BankNames::VolkskreditbankAg => { Self("4a0a975b-0594-4b40-9068-39f77b3a91f9") } _ => Err(errors::ConnectorError::NotImplemented( @@ -1489,24 +1481,24 @@ impl<'a> TryFrom<&api_enums::BankNames> for AdyenTestBankNames<'a> { pub struct AdyenBankNames<'a>(&'a str); -impl<'a> TryFrom<&api_enums::BankNames> for AdyenBankNames<'a> { +impl<'a> TryFrom<&common_enums::BankNames> for AdyenBankNames<'a> { type Error = Error; - fn try_from(bank: &api_enums::BankNames) -> Result { + fn try_from(bank: &common_enums::BankNames) -> Result { Ok(match bank { - api_models::enums::BankNames::AbnAmro => Self("0031"), - api_models::enums::BankNames::AsnBank => Self("0761"), - api_models::enums::BankNames::Bunq => Self("0802"), - api_models::enums::BankNames::Ing => Self("0721"), - api_models::enums::BankNames::Knab => Self("0801"), - api_models::enums::BankNames::N26 => Self("0807"), - api_models::enums::BankNames::NationaleNederlanden => Self("0808"), - api_models::enums::BankNames::Rabobank => Self("0021"), - api_models::enums::BankNames::Regiobank => Self("0771"), - api_models::enums::BankNames::Revolut => Self("0805"), - api_models::enums::BankNames::SnsBank => Self("0751"), - api_models::enums::BankNames::TriodosBank => Self("0511"), - api_models::enums::BankNames::VanLanschot => Self("0161"), - api_models::enums::BankNames::Yoursafe => Self("0806"), + common_enums::BankNames::AbnAmro => Self("0031"), + common_enums::BankNames::AsnBank => Self("0761"), + common_enums::BankNames::Bunq => Self("0802"), + common_enums::BankNames::Ing => Self("0721"), + common_enums::BankNames::Knab => Self("0801"), + common_enums::BankNames::N26 => Self("0807"), + common_enums::BankNames::NationaleNederlanden => Self("0808"), + common_enums::BankNames::Rabobank => Self("0021"), + common_enums::BankNames::Regiobank => Self("0771"), + common_enums::BankNames::Revolut => Self("0805"), + common_enums::BankNames::SnsBank => Self("0751"), + common_enums::BankNames::TriodosBank => Self("0511"), + common_enums::BankNames::VanLanschot => Self("0161"), + common_enums::BankNames::Yoursafe => Self("0806"), _ => Err(errors::ConnectorError::NotSupported { message: String::from("BankRedirect"), connector: "Adyen", @@ -2143,7 +2135,7 @@ pub fn check_required_field<'a, T>( impl<'a> TryFrom<( - &api::PayLaterData, + &domain::PayLaterData, &Option, &Option, &Option, @@ -2156,7 +2148,7 @@ impl<'a> type Error = Error; fn try_from( value: ( - &api::PayLaterData, + &domain::PayLaterData, &Option, &Option, &Option, @@ -2177,7 +2169,7 @@ impl<'a> delivery_address, ) = value; match pay_later_data { - api_models::payments::PayLaterData::KlarnaRedirect { .. } => { + domain::payments::PayLaterData::KlarnaRedirect { .. } => { let klarna = PmdForPaymentType { payment_type: PaymentType::Klarna, }; @@ -2187,7 +2179,7 @@ impl<'a> Ok(AdyenPaymentMethod::AdyenKlarna(Box::new(klarna))) } - api_models::payments::PayLaterData::AffirmRedirect { .. } => { + domain::payments::PayLaterData::AffirmRedirect { .. } => { check_required_field(shopper_email, "email")?; check_required_field(shopper_name, "billing.first_name, billing.last_name")?; check_required_field(telephone_number, "billing.phone")?; @@ -2199,7 +2191,7 @@ impl<'a> }, ))) } - api_models::payments::PayLaterData::AfterpayClearpayRedirect { .. } => { + domain::payments::PayLaterData::AfterpayClearpayRedirect { .. } => { check_required_field(shopper_email, "email")?; check_required_field(shopper_name, "billing.first_name, billing.last_name")?; check_required_field(delivery_address, "shipping")?; @@ -2221,7 +2213,7 @@ impl<'a> })? } } - api_models::payments::PayLaterData::PayBrightRedirect { .. } => { + domain::payments::PayLaterData::PayBrightRedirect { .. } => { check_required_field(shopper_name, "billing.first_name, billing.last_name")?; check_required_field(telephone_number, "billing.phone")?; check_required_field(shopper_email, "email")?; @@ -2230,13 +2222,13 @@ impl<'a> check_required_field(country_code, "billing.country")?; Ok(AdyenPaymentMethod::PayBright) } - api_models::payments::PayLaterData::WalleyRedirect { .. } => { + domain::payments::PayLaterData::WalleyRedirect { .. } => { //[TODO: Line items specific sub-fields are mandatory] check_required_field(telephone_number, "billing.phone")?; check_required_field(shopper_email, "email")?; Ok(AdyenPaymentMethod::Walley) } - api_models::payments::PayLaterData::AlmaRedirect { .. } => { + domain::payments::PayLaterData::AlmaRedirect { .. } => { check_required_field(telephone_number, "billing.phone")?; check_required_field(shopper_email, "email")?; check_required_field(billing_address, "billing")?; @@ -2247,14 +2239,14 @@ impl<'a> }, ))) } - api_models::payments::PayLaterData::AtomeRedirect { .. } => { + domain::payments::PayLaterData::AtomeRedirect { .. } => { check_required_field(shopper_email, "email")?; check_required_field(shopper_name, "billing.first_name, billing.last_name")?; check_required_field(telephone_number, "billing.phone")?; check_required_field(billing_address, "billing")?; Ok(AdyenPaymentMethod::Atome) } - payments::PayLaterData::KlarnaSdk { .. } => { + domain::payments::PayLaterData::KlarnaSdk { .. } => { Err(errors::ConnectorError::NotImplemented( utils::get_unimplemented_payment_method_error_message("Adyen"), ) @@ -2264,15 +2256,13 @@ impl<'a> } } -impl<'a> TryFrom<(&api_models::payments::BankRedirectData, Option)> - for AdyenPaymentMethod<'a> -{ +impl<'a> TryFrom<(&domain::BankRedirectData, Option)> for AdyenPaymentMethod<'a> { type Error = Error; fn try_from( - (bank_redirect_data, test_mode): (&api_models::payments::BankRedirectData, Option), + (bank_redirect_data, test_mode): (&domain::BankRedirectData, Option), ) -> Result { match bank_redirect_data { - api_models::payments::BankRedirectData::BancontactCard { + domain::BankRedirectData::BancontactCard { card_number, card_exp_month, card_exp_year, @@ -2308,12 +2298,12 @@ impl<'a> TryFrom<(&api_models::payments::BankRedirectData, Option)> .clone(), }, ))), - api_models::payments::BankRedirectData::Bizum { .. } => { + domain::BankRedirectData::Bizum { .. } => { Ok(AdyenPaymentMethod::Bizum(Box::new(PmdForPaymentType { payment_type: PaymentType::Bizum, }))) } - api_models::payments::BankRedirectData::Blik { blik_code } => { + domain::BankRedirectData::Blik { blik_code } => { Ok(AdyenPaymentMethod::Blik(Box::new(BlikRedirectionData { payment_type: PaymentType::Blik, blik_code: Secret::new(blik_code.clone().ok_or( @@ -2323,8 +2313,8 @@ impl<'a> TryFrom<(&api_models::payments::BankRedirectData, Option)> )?), }))) } - api_models::payments::BankRedirectData::Eps { bank_name, .. } => Ok( - AdyenPaymentMethod::Eps(Box::new(BankRedirectionWithIssuer { + domain::BankRedirectData::Eps { bank_name, .. } => Ok(AdyenPaymentMethod::Eps( + Box::new(BankRedirectionWithIssuer { payment_type: PaymentType::Eps, issuer: Some( AdyenTestBankNames::try_from(&bank_name.ok_or( @@ -2334,14 +2324,14 @@ impl<'a> TryFrom<(&api_models::payments::BankRedirectData, Option)> )?)? .0, ), - })), - ), - api_models::payments::BankRedirectData::Giropay { .. } => { + }), + )), + domain::BankRedirectData::Giropay { .. } => { Ok(AdyenPaymentMethod::Giropay(Box::new(PmdForPaymentType { payment_type: PaymentType::Giropay, }))) } - api_models::payments::BankRedirectData::Ideal { bank_name, .. } => { + domain::BankRedirectData::Ideal { bank_name, .. } => { let issuer = if test_mode.unwrap_or(true) { Some( AdyenTestBankNames::try_from(&bank_name.ok_or( @@ -2368,7 +2358,7 @@ impl<'a> TryFrom<(&api_models::payments::BankRedirectData, Option)> }, ))) } - api_models::payments::BankRedirectData::OnlineBankingCzechRepublic { issuer } => { + domain::BankRedirectData::OnlineBankingCzechRepublic { issuer } => { Ok(AdyenPaymentMethod::OnlineBankingCzechRepublic(Box::new( OnlineBankingCzechRepublicData { payment_type: PaymentType::OnlineBankingCzechRepublic, @@ -2376,34 +2366,34 @@ impl<'a> TryFrom<(&api_models::payments::BankRedirectData, Option)> }, ))) } - api_models::payments::BankRedirectData::OnlineBankingFinland { .. } => Ok( + domain::BankRedirectData::OnlineBankingFinland { .. } => Ok( AdyenPaymentMethod::OnlineBankingFinland(Box::new(PmdForPaymentType { payment_type: PaymentType::OnlineBankingFinland, })), ), - api_models::payments::BankRedirectData::OnlineBankingPoland { issuer } => Ok( + domain::BankRedirectData::OnlineBankingPoland { issuer } => Ok( AdyenPaymentMethod::OnlineBankingPoland(Box::new(OnlineBankingPolandData { payment_type: PaymentType::OnlineBankingPoland, issuer: OnlineBankingPolandBanks::try_from(issuer)?, })), ), - api_models::payments::BankRedirectData::OnlineBankingSlovakia { issuer } => Ok( + domain::BankRedirectData::OnlineBankingSlovakia { issuer } => Ok( AdyenPaymentMethod::OnlineBankingSlovakia(Box::new(OnlineBankingSlovakiaData { payment_type: PaymentType::OnlineBankingSlovakia, issuer: OnlineBankingSlovakiaBanks::try_from(issuer)?, })), ), - api_models::payments::BankRedirectData::OnlineBankingFpx { issuer } => Ok( + domain::BankRedirectData::OnlineBankingFpx { issuer } => Ok( AdyenPaymentMethod::OnlineBankingFpx(Box::new(OnlineBankingFpxData { issuer: OnlineBankingFpxIssuer::try_from(issuer)?, })), ), - api_models::payments::BankRedirectData::OnlineBankingThailand { issuer } => Ok( + domain::BankRedirectData::OnlineBankingThailand { issuer } => Ok( AdyenPaymentMethod::OnlineBankingThailand(Box::new(OnlineBankingThailandData { issuer: OnlineBankingThailandIssuer::try_from(issuer)?, })), ), - api_models::payments::BankRedirectData::OpenBankingUk { issuer, .. } => Ok( + domain::BankRedirectData::OpenBankingUk { issuer, .. } => Ok( AdyenPaymentMethod::OpenBankingUK(Box::new(OpenBankingUKData { issuer: match issuer { Some(bank_name) => OpenBankingUKIssuer::try_from(bank_name)?, @@ -2413,12 +2403,10 @@ impl<'a> TryFrom<(&api_models::payments::BankRedirectData, Option)> }, })), ), - api_models::payments::BankRedirectData::Sofort { .. } => Ok(AdyenPaymentMethod::Sofort), - api_models::payments::BankRedirectData::Trustly { .. } => { - Ok(AdyenPaymentMethod::Trustly) - } - payments::BankRedirectData::Interac { .. } - | payments::BankRedirectData::Przelewy24 { .. } => { + domain::BankRedirectData::Sofort { .. } => Ok(AdyenPaymentMethod::Sofort), + domain::BankRedirectData::Trustly { .. } => Ok(AdyenPaymentMethod::Trustly), + domain::BankRedirectData::Interac { .. } + | domain::BankRedirectData::Przelewy24 { .. } => { Err(errors::ConnectorError::NotImplemented( utils::get_unimplemented_payment_method_error_message("Adyen"), ) @@ -2496,6 +2484,7 @@ impl<'a> TryFrom<&api_models::payments::BankTransferData> for AdyenPaymentMethod | api_models::payments::BankTransferData::SepaBankTransfer { .. } | api_models::payments::BankTransferData::BacsBankTransfer { .. } | api_models::payments::BankTransferData::MultibancoBankTransfer { .. } + | api_models::payments::BankTransferData::LocalBankTransfer { .. } | payments::BankTransferData::Pse {} => Err(errors::ConnectorError::NotImplemented( utils::get_unimplemented_payment_method_error_message("Adyen"), ) @@ -2902,14 +2891,14 @@ impl<'a> impl<'a> TryFrom<( &AdyenRouterData<&types::PaymentsAuthorizeRouterData>, - &api_models::payments::BankRedirectData, + &domain::BankRedirectData, )> for AdyenPaymentRequest<'a> { type Error = Error; fn try_from( value: ( &AdyenRouterData<&types::PaymentsAuthorizeRouterData>, - &api_models::payments::BankRedirectData, + &domain::BankRedirectData, ), ) -> Result { let (item, bank_redirect_data) = value; @@ -2960,12 +2949,12 @@ fn get_redirect_extra_details( ) -> Result<(Option, Option), errors::ConnectorError> { match item.request.payment_method_data { domain::PaymentMethodData::BankRedirect(ref redirect_data) => match redirect_data { - api_models::payments::BankRedirectData::Sofort { + domain::BankRedirectData::Sofort { country, preferred_language, .. } => Ok((preferred_language.clone(), *country)), - api_models::payments::BankRedirectData::OpenBankingUk { country, .. } => { + domain::BankRedirectData::OpenBankingUk { country, .. } => { let country = country.ok_or(errors::ConnectorError::MissingRequiredField { field_name: "country", })?; @@ -3053,14 +3042,14 @@ impl<'a> impl<'a> TryFrom<( &AdyenRouterData<&types::PaymentsAuthorizeRouterData>, - &api::PayLaterData, + &domain::PayLaterData, )> for AdyenPaymentRequest<'a> { type Error = Error; fn try_from( value: ( &AdyenRouterData<&types::PaymentsAuthorizeRouterData>, - &api::PayLaterData, + &domain::PayLaterData, ), ) -> Result { let (item, paylater_data) = value; diff --git a/crates/router/src/connector/cybersource/transformers.rs b/crates/router/src/connector/cybersource/transformers.rs index 6a51e1e8cd4e..346d21276494 100644 --- a/crates/router/src/connector/cybersource/transformers.rs +++ b/crates/router/src/connector/cybersource/transformers.rs @@ -297,6 +297,7 @@ pub struct CybersourceAuthorizationOptions { #[serde(rename_all = "camelCase")] pub struct MerchantInitiatedTransaction { reason: Option, + previous_transaction_id: Option>, //Required for recurring mandates payment original_authorized_amount: Option, } @@ -314,6 +315,7 @@ pub struct CybersourcePaymentInitiator { #[serde(rename_all = "camelCase")] pub enum CybersourcePaymentInitiatorTypes { Customer, + Merchant, } #[derive(Debug, Serialize)] @@ -503,6 +505,24 @@ impl Option, ), ) -> Result { + let mut commerce_indicator = solution + .as_ref() + .map(|pm_solution| match pm_solution { + PaymentSolution::ApplePay => network + .as_ref() + .map(|card_network| match card_network.to_lowercase().as_str() { + "amex" => "aesk", + "discover" => "dipb", + "mastercard" => "spa", + "visa" => "internet", + _ => "internet", + }) + .unwrap_or("internet"), + PaymentSolution::GooglePay => "internet", + }) + .unwrap_or("internet") + .to_string(); + let (action_list, action_token_types, authorization_options) = if item .router_data .request @@ -531,44 +551,113 @@ impl merchant_intitiated_transaction: None, }), ) - } 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 + } else if item.router_data.request.mandate_id.is_some() { + match item .router_data - .get_recurring_mandate_payment_data()? - .get_original_payment_currency()?; - ( - None, - None, - Some(CybersourceAuthorizationOptions { - initiator: None, - merchant_intitiated_transaction: Some(MerchantInitiatedTransaction { - reason: None, - original_authorized_amount: Some(utils::get_amount_as_string( - &types::api::CurrencyUnit::Base, - original_amount, - original_currency, - )?), - }), - }), - ) + .request + .mandate_id + .clone() + .and_then(|mandate_id| mandate_id.mandate_reference_id) + { + Some(api_models::payments::MandateReferenceId::ConnectorMandateId(_)) => { + 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(CybersourceAuthorizationOptions { + initiator: None, + merchant_intitiated_transaction: Some(MerchantInitiatedTransaction { + reason: None, + original_authorized_amount: Some(utils::get_amount_as_string( + &types::api::CurrencyUnit::Base, + original_amount, + original_currency, + )?), + previous_transaction_id: None, + }), + }), + ) + } + Some(api_models::payments::MandateReferenceId::NetworkMandateId( + network_transaction_id, + )) => { + let (original_amount, original_currency) = match network + .clone() + .map(|network| network.to_lowercase()) + .as_deref() + { + Some("discover") => { + let original_amount = Some( + item.router_data + .get_recurring_mandate_payment_data()? + .get_original_payment_amount()?, + ); + let original_currency = Some( + item.router_data + .get_recurring_mandate_payment_data()? + .get_original_payment_currency()?, + ); + (original_amount, original_currency) + } + _ => { + let original_amount = item + .router_data + .recurring_mandate_payment_data + .as_ref() + .and_then(|recurring_mandate_payment_data| { + recurring_mandate_payment_data + .original_payment_authorized_amount + }); + + let original_currency = item + .router_data + .recurring_mandate_payment_data + .as_ref() + .and_then(|recurring_mandate_payment_data| { + recurring_mandate_payment_data + .original_payment_authorized_currency + }); + + (original_amount, original_currency) + } + }; + + let original_authorized_amount = match (original_amount, original_currency) { + (Some(original_amount), Some(original_currency)) => Some( + utils::to_currency_base_unit(original_amount, original_currency)?, + ), + _ => None, + }; + commerce_indicator = "recurring".to_string(); + ( + None, + None, + Some(CybersourceAuthorizationOptions { + initiator: Some(CybersourcePaymentInitiator { + initiator_type: Some(CybersourcePaymentInitiatorTypes::Merchant), + credential_stored_on_file: None, + stored_credential_used: Some(true), + }), + merchant_intitiated_transaction: Some(MerchantInitiatedTransaction { + reason: Some("7".to_string()), + original_authorized_amount, + previous_transaction_id: Some(Secret::new(network_transaction_id)), + }), + }), + ) + } + None => (None, None, None), + } } else { (None, None, None) }; - let commerce_indicator = match network { - Some(card_network) => match card_network.to_lowercase().as_str() { - "amex" => "aesk", - "discover" => "dipb", - "mastercard" => "spa", - "visa" => "internet", - _ => "internet", - }, - None => "internet", - } - .to_string(); Ok(Self { capture: Some(matches!( item.router_data.request.capture_method, @@ -754,11 +843,11 @@ impl expiration_month: ccard.card_exp_month, expiration_year: ccard.card_exp_year, security_code: ccard.card_cvc, - card_type, + card_type: card_type.clone(), }, }); - let processing_information = ProcessingInformation::try_from((item, None, None))?; + let processing_information = ProcessingInformation::try_from((item, None, card_type))?; let client_reference_information = ClientReferenceInformation::from(item); let merchant_defined_information = item.router_data.request.metadata.clone().map(|metadata| { @@ -1287,6 +1376,7 @@ impl TryFrom<&CybersourceRouterData<&types::PaymentsIncrementalAuthorizationRout }), merchant_intitiated_transaction: Some(MerchantInitiatedTransaction { reason: Some("5".to_owned()), + previous_transaction_id: None, original_authorized_amount: None, }), }), @@ -1537,6 +1627,7 @@ pub struct ClientReferenceInformation { #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ClientProcessorInformation { + network_transaction_id: Option, avs: Option, } @@ -1667,7 +1758,7 @@ fn get_payment_response( .processor_information .as_ref() .map(|processor_information| serde_json::json!({"avs_response": processor_information.avs})), - network_txn_id: None, + network_txn_id: info_response.processor_information.as_ref().and_then(|processor_information| processor_information.network_transaction_id.clone()), connector_response_reference_id: Some( info_response .client_reference_information @@ -2281,6 +2372,7 @@ impl } } +// zero dollar response impl TryFrom< types::ResponseRouterData< @@ -2328,7 +2420,11 @@ impl redirection_data: None, mandate_reference, connector_metadata: None, - network_txn_id: None, + network_txn_id: info_response.processor_information.as_ref().and_then( + |processor_information| { + processor_information.network_transaction_id.clone() + }, + ), connector_response_reference_id: Some( info_response .client_reference_information diff --git a/crates/router/src/connector/dummyconnector/transformers.rs b/crates/router/src/connector/dummyconnector/transformers.rs index cf4e19b8e50d..ed579f7a1c13 100644 --- a/crates/router/src/connector/dummyconnector/transformers.rs +++ b/crates/router/src/connector/dummyconnector/transformers.rs @@ -130,13 +130,13 @@ pub enum DummyConnectorPayLater { AfterPayClearPay, } -impl TryFrom for DummyConnectorPayLater { +impl TryFrom for DummyConnectorPayLater { type Error = error_stack::Report; - fn try_from(value: api_models::payments::PayLaterData) -> Result { + fn try_from(value: domain::payments::PayLaterData) -> Result { match value { - api_models::payments::PayLaterData::KlarnaRedirect { .. } => Ok(Self::Klarna), - api_models::payments::PayLaterData::AffirmRedirect {} => Ok(Self::Affirm), - api_models::payments::PayLaterData::AfterpayClearpayRedirect { .. } => { + domain::payments::PayLaterData::KlarnaRedirect { .. } => Ok(Self::Klarna), + domain::payments::PayLaterData::AffirmRedirect {} => Ok(Self::Affirm), + domain::payments::PayLaterData::AfterpayClearpayRedirect { .. } => { Ok(Self::AfterPayClearPay) } _ => Err(errors::ConnectorError::NotImplemented("Dummy pay later".to_string()).into()), diff --git a/crates/router/src/connector/ebanx.rs b/crates/router/src/connector/ebanx.rs new file mode 100644 index 000000000000..284b592cd077 --- /dev/null +++ b/crates/router/src/connector/ebanx.rs @@ -0,0 +1,559 @@ +pub mod transformers; + +use std::fmt::Debug; + +use error_stack::{report, ResultExt}; +use masking::ExposeInterface; +use transformers as ebanx; + +use crate::{ + configs::settings, + core::errors::{self, CustomResult}, + events::connector_api_logs::ConnectorEvent, + headers, + services::{ + self, + request::{self, Mask}, + ConnectorIntegration, ConnectorValidation, + }, + types::{ + self, + api::{self, ConnectorCommon, ConnectorCommonExt}, + ErrorResponse, RequestContent, Response, + }, + utils::BytesExt, +}; + +#[derive(Debug, Clone)] +pub struct Ebanx; + +impl api::Payment for Ebanx {} +impl api::PaymentSession for Ebanx {} +impl api::ConnectorAccessToken for Ebanx {} +impl api::MandateSetup for Ebanx {} +impl api::PaymentAuthorize for Ebanx {} +impl api::PaymentSync for Ebanx {} +impl api::PaymentCapture for Ebanx {} +impl api::PaymentVoid for Ebanx {} +impl api::Refund for Ebanx {} +impl api::RefundExecute for Ebanx {} +impl api::RefundSync for Ebanx {} +impl api::PaymentToken for Ebanx {} + +impl + ConnectorIntegration< + api::PaymentMethodToken, + types::PaymentMethodTokenizationData, + types::PaymentsResponseData, + > for Ebanx +{ + // Not Implemented (R) +} + +impl ConnectorCommonExt for Ebanx +where + Self: ConnectorIntegration, +{ + fn build_headers( + &self, + req: &types::RouterData, + _connectors: &settings::Connectors, + ) -> CustomResult)>, errors::ConnectorError> { + let mut header = vec![( + headers::CONTENT_TYPE.to_string(), + self.get_content_type().to_string().into(), + )]; + let mut api_key = self.get_auth_header(&req.connector_auth_type)?; + header.append(&mut api_key); + Ok(header) + } +} + +impl ConnectorCommon for Ebanx { + fn id(&self) -> &'static str { + "ebanx" + } + + fn get_currency_unit(&self) -> api::CurrencyUnit { + api::CurrencyUnit::Base + } + + fn common_get_content_type(&self) -> &'static str { + "application/json" + } + + fn base_url<'a>(&self, connectors: &'a settings::Connectors) -> &'a str { + connectors.ebanx.base_url.as_ref() + } + + fn get_auth_header( + &self, + auth_type: &types::ConnectorAuthType, + ) -> CustomResult)>, errors::ConnectorError> { + let auth = ebanx::EbanxAuthType::try_from(auth_type) + .change_context(errors::ConnectorError::FailedToObtainAuthType)?; + Ok(vec![( + headers::AUTHORIZATION.to_string(), + auth.api_key.expose().into_masked(), + )]) + } + + fn build_error_response( + &self, + res: Response, + event_builder: Option<&mut ConnectorEvent>, + ) -> CustomResult { + let response: ebanx::EbanxErrorResponse = + res.response + .parse_struct("EbanxErrorResponse") + .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; + + event_builder.map(|i| i.set_response_body(&response)); + router_env::logger::info!(connector_response=?response); + + Ok(ErrorResponse { + status_code: res.status_code, + code: response.code, + message: response.message, + reason: response.reason, + attempt_status: None, + connector_transaction_id: None, + }) + } +} + +impl ConnectorValidation for Ebanx { + //TODO: implement functions when support enabled +} + +impl ConnectorIntegration + for Ebanx +{ + //TODO: implement sessions flow +} + +impl ConnectorIntegration + for Ebanx +{ +} + +impl + ConnectorIntegration< + api::SetupMandate, + types::SetupMandateRequestData, + types::PaymentsResponseData, + > for Ebanx +{ +} + +impl ConnectorIntegration + for Ebanx +{ + fn get_headers( + &self, + req: &types::PaymentsAuthorizeRouterData, + connectors: &settings::Connectors, + ) -> CustomResult)>, errors::ConnectorError> { + self.build_headers(req, connectors) + } + + fn get_content_type(&self) -> &'static str { + self.common_get_content_type() + } + + fn get_url( + &self, + _req: &types::PaymentsAuthorizeRouterData, + _connectors: &settings::Connectors, + ) -> CustomResult { + Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into()) + } + + fn get_request_body( + &self, + req: &types::PaymentsAuthorizeRouterData, + _connectors: &settings::Connectors, + ) -> CustomResult { + let connector_router_data = ebanx::EbanxRouterData::try_from(( + &self.get_currency_unit(), + req.request.currency, + req.request.amount, + req, + ))?; + let connector_req = ebanx::EbanxPaymentsRequest::try_from(&connector_router_data)?; + Ok(RequestContent::Json(Box::new(connector_req))) + } + + fn build_request( + &self, + req: &types::PaymentsAuthorizeRouterData, + connectors: &settings::Connectors, + ) -> CustomResult, errors::ConnectorError> { + Ok(Some( + services::RequestBuilder::new() + .method(services::Method::Post) + .url(&types::PaymentsAuthorizeType::get_url( + self, req, connectors, + )?) + .attach_default_headers() + .headers(types::PaymentsAuthorizeType::get_headers( + self, req, connectors, + )?) + .set_body(types::PaymentsAuthorizeType::get_request_body( + self, req, connectors, + )?) + .build(), + )) + } + + fn handle_response( + &self, + data: &types::PaymentsAuthorizeRouterData, + event_builder: Option<&mut ConnectorEvent>, + res: Response, + ) -> CustomResult { + let response: ebanx::EbanxPaymentsResponse = res + .response + .parse_struct("Ebanx PaymentsAuthorizeResponse") + .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; + event_builder.map(|i| i.set_response_body(&response)); + router_env::logger::info!(connector_response=?response); + types::RouterData::try_from(types::ResponseRouterData { + response, + data: data.clone(), + http_code: res.status_code, + }) + } + + fn get_error_response( + &self, + res: Response, + event_builder: Option<&mut ConnectorEvent>, + ) -> CustomResult { + self.build_error_response(res, event_builder) + } +} + +impl ConnectorIntegration + for Ebanx +{ + fn get_headers( + &self, + req: &types::PaymentsSyncRouterData, + connectors: &settings::Connectors, + ) -> CustomResult)>, errors::ConnectorError> { + self.build_headers(req, connectors) + } + + fn get_content_type(&self) -> &'static str { + self.common_get_content_type() + } + + fn get_url( + &self, + _req: &types::PaymentsSyncRouterData, + _connectors: &settings::Connectors, + ) -> CustomResult { + Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into()) + } + + fn build_request( + &self, + req: &types::PaymentsSyncRouterData, + connectors: &settings::Connectors, + ) -> CustomResult, errors::ConnectorError> { + Ok(Some( + services::RequestBuilder::new() + .method(services::Method::Get) + .url(&types::PaymentsSyncType::get_url(self, req, connectors)?) + .attach_default_headers() + .headers(types::PaymentsSyncType::get_headers(self, req, connectors)?) + .build(), + )) + } + + fn handle_response( + &self, + data: &types::PaymentsSyncRouterData, + event_builder: Option<&mut ConnectorEvent>, + res: Response, + ) -> CustomResult { + let response: ebanx::EbanxPaymentsResponse = res + .response + .parse_struct("ebanx PaymentsSyncResponse") + .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; + event_builder.map(|i| i.set_response_body(&response)); + router_env::logger::info!(connector_response=?response); + types::RouterData::try_from(types::ResponseRouterData { + response, + data: data.clone(), + http_code: res.status_code, + }) + } + + fn get_error_response( + &self, + res: Response, + event_builder: Option<&mut ConnectorEvent>, + ) -> CustomResult { + self.build_error_response(res, event_builder) + } +} + +impl ConnectorIntegration + for Ebanx +{ + fn get_headers( + &self, + req: &types::PaymentsCaptureRouterData, + connectors: &settings::Connectors, + ) -> CustomResult)>, errors::ConnectorError> { + self.build_headers(req, connectors) + } + + fn get_content_type(&self) -> &'static str { + self.common_get_content_type() + } + + fn get_url( + &self, + _req: &types::PaymentsCaptureRouterData, + _connectors: &settings::Connectors, + ) -> CustomResult { + Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into()) + } + + fn get_request_body( + &self, + _req: &types::PaymentsCaptureRouterData, + _connectors: &settings::Connectors, + ) -> CustomResult { + Err(errors::ConnectorError::NotImplemented("get_request_body method".to_string()).into()) + } + + fn build_request( + &self, + req: &types::PaymentsCaptureRouterData, + connectors: &settings::Connectors, + ) -> CustomResult, errors::ConnectorError> { + Ok(Some( + services::RequestBuilder::new() + .method(services::Method::Post) + .url(&types::PaymentsCaptureType::get_url(self, req, connectors)?) + .attach_default_headers() + .headers(types::PaymentsCaptureType::get_headers( + self, req, connectors, + )?) + .set_body(types::PaymentsCaptureType::get_request_body( + self, req, connectors, + )?) + .build(), + )) + } + + fn handle_response( + &self, + data: &types::PaymentsCaptureRouterData, + event_builder: Option<&mut ConnectorEvent>, + res: Response, + ) -> CustomResult { + let response: ebanx::EbanxPaymentsResponse = res + .response + .parse_struct("Ebanx PaymentsCaptureResponse") + .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; + event_builder.map(|i| i.set_response_body(&response)); + router_env::logger::info!(connector_response=?response); + types::RouterData::try_from(types::ResponseRouterData { + response, + data: data.clone(), + http_code: res.status_code, + }) + } + + fn get_error_response( + &self, + res: Response, + event_builder: Option<&mut ConnectorEvent>, + ) -> CustomResult { + self.build_error_response(res, event_builder) + } +} + +impl ConnectorIntegration + for Ebanx +{ +} + +impl ConnectorIntegration for Ebanx { + fn get_headers( + &self, + req: &types::RefundsRouterData, + connectors: &settings::Connectors, + ) -> CustomResult)>, errors::ConnectorError> { + self.build_headers(req, connectors) + } + + fn get_content_type(&self) -> &'static str { + self.common_get_content_type() + } + + fn get_url( + &self, + _req: &types::RefundsRouterData, + _connectors: &settings::Connectors, + ) -> CustomResult { + Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into()) + } + + fn get_request_body( + &self, + req: &types::RefundsRouterData, + _connectors: &settings::Connectors, + ) -> CustomResult { + let connector_router_data = ebanx::EbanxRouterData::try_from(( + &self.get_currency_unit(), + req.request.currency, + req.request.refund_amount, + req, + ))?; + let connector_req = ebanx::EbanxRefundRequest::try_from(&connector_router_data)?; + Ok(RequestContent::Json(Box::new(connector_req))) + } + + fn build_request( + &self, + req: &types::RefundsRouterData, + connectors: &settings::Connectors, + ) -> CustomResult, errors::ConnectorError> { + let request = services::RequestBuilder::new() + .method(services::Method::Post) + .url(&types::RefundExecuteType::get_url(self, req, connectors)?) + .attach_default_headers() + .headers(types::RefundExecuteType::get_headers( + self, req, connectors, + )?) + .set_body(types::RefundExecuteType::get_request_body( + self, req, connectors, + )?) + .build(); + Ok(Some(request)) + } + + fn handle_response( + &self, + data: &types::RefundsRouterData, + event_builder: Option<&mut ConnectorEvent>, + res: Response, + ) -> CustomResult, errors::ConnectorError> { + let response: ebanx::RefundResponse = res + .response + .parse_struct("ebanx RefundResponse") + .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; + event_builder.map(|i| i.set_response_body(&response)); + router_env::logger::info!(connector_response=?response); + types::RouterData::try_from(types::ResponseRouterData { + response, + data: data.clone(), + http_code: res.status_code, + }) + } + + fn get_error_response( + &self, + res: Response, + event_builder: Option<&mut ConnectorEvent>, + ) -> CustomResult { + self.build_error_response(res, event_builder) + } +} + +impl ConnectorIntegration for Ebanx { + fn get_headers( + &self, + req: &types::RefundSyncRouterData, + connectors: &settings::Connectors, + ) -> CustomResult)>, errors::ConnectorError> { + self.build_headers(req, connectors) + } + + fn get_content_type(&self) -> &'static str { + self.common_get_content_type() + } + + fn get_url( + &self, + _req: &types::RefundSyncRouterData, + _connectors: &settings::Connectors, + ) -> CustomResult { + Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into()) + } + + fn build_request( + &self, + req: &types::RefundSyncRouterData, + connectors: &settings::Connectors, + ) -> CustomResult, errors::ConnectorError> { + Ok(Some( + services::RequestBuilder::new() + .method(services::Method::Get) + .url(&types::RefundSyncType::get_url(self, req, connectors)?) + .attach_default_headers() + .headers(types::RefundSyncType::get_headers(self, req, connectors)?) + .set_body(types::RefundSyncType::get_request_body( + self, req, connectors, + )?) + .build(), + )) + } + + fn handle_response( + &self, + data: &types::RefundSyncRouterData, + event_builder: Option<&mut ConnectorEvent>, + res: Response, + ) -> CustomResult { + let response: ebanx::RefundResponse = res + .response + .parse_struct("ebanx RefundSyncResponse") + .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; + event_builder.map(|i| i.set_response_body(&response)); + router_env::logger::info!(connector_response=?response); + types::RouterData::try_from(types::ResponseRouterData { + response, + data: data.clone(), + http_code: res.status_code, + }) + } + + fn get_error_response( + &self, + res: Response, + event_builder: Option<&mut ConnectorEvent>, + ) -> CustomResult { + self.build_error_response(res, event_builder) + } +} + +#[async_trait::async_trait] +impl api::IncomingWebhook for Ebanx { + fn get_webhook_object_reference_id( + &self, + _request: &api::IncomingWebhookRequestDetails<'_>, + ) -> CustomResult { + Err(report!(errors::ConnectorError::WebhooksNotImplemented)) + } + + fn get_webhook_event_type( + &self, + _request: &api::IncomingWebhookRequestDetails<'_>, + ) -> CustomResult { + Err(report!(errors::ConnectorError::WebhooksNotImplemented)) + } + + fn get_webhook_resource_object( + &self, + _request: &api::IncomingWebhookRequestDetails<'_>, + ) -> CustomResult, errors::ConnectorError> { + Err(report!(errors::ConnectorError::WebhooksNotImplemented)) + } +} diff --git a/crates/router/src/connector/ebanx/transformers.rs b/crates/router/src/connector/ebanx/transformers.rs new file mode 100644 index 000000000000..e27fba788dca --- /dev/null +++ b/crates/router/src/connector/ebanx/transformers.rs @@ -0,0 +1,237 @@ +use masking::Secret; +use serde::{Deserialize, Serialize}; + +use crate::{ + connector::utils::PaymentsAuthorizeRequestData, + core::errors, + types::{self, api, domain, storage::enums}, +}; + +//TODO: Fill the struct with respective fields +pub struct EbanxRouterData { + pub amount: i64, // The type of amount that a connector accepts, for example, String, i64, f64, etc. + pub router_data: T, +} + +impl + TryFrom<( + &types::api::CurrencyUnit, + types::storage::enums::Currency, + i64, + T, + )> for EbanxRouterData +{ + type Error = error_stack::Report; + fn try_from( + (_currency_unit, _currency, amount, item): ( + &types::api::CurrencyUnit, + types::storage::enums::Currency, + i64, + T, + ), + ) -> Result { + //Todo : use utils to convert the amount to the type of amount that a connector accepts + Ok(Self { + amount, + router_data: item, + }) + } +} + +//TODO: Fill the struct with respective fields +#[derive(Default, Debug, Serialize, Eq, PartialEq)] +pub struct EbanxPaymentsRequest { + amount: i64, + card: EbanxCard, +} + +#[derive(Default, Debug, Serialize, Eq, PartialEq)] +pub struct EbanxCard { + number: cards::CardNumber, + expiry_month: Secret, + expiry_year: Secret, + cvc: Secret, + complete: bool, +} + +impl TryFrom<&EbanxRouterData<&types::PaymentsAuthorizeRouterData>> for EbanxPaymentsRequest { + type Error = error_stack::Report; + fn try_from( + item: &EbanxRouterData<&types::PaymentsAuthorizeRouterData>, + ) -> Result { + match item.router_data.request.payment_method_data.clone() { + domain::payments::PaymentMethodData::Card(req_card) => { + let card = EbanxCard { + number: req_card.card_number, + expiry_month: req_card.card_exp_month, + expiry_year: req_card.card_exp_year, + cvc: req_card.card_cvc, + complete: item.router_data.request.is_auto_capture()?, + }; + Ok(Self { + amount: item.amount.to_owned(), + card, + }) + } + _ => Err(errors::ConnectorError::NotImplemented("Payment methods".to_string()).into()), + } + } +} + +//TODO: Fill the struct with respective fields +// Auth Struct +pub struct EbanxAuthType { + pub(super) api_key: Secret, +} + +impl TryFrom<&types::ConnectorAuthType> for EbanxAuthType { + type Error = error_stack::Report; + fn try_from(auth_type: &types::ConnectorAuthType) -> Result { + match auth_type { + types::ConnectorAuthType::HeaderKey { api_key } => Ok(Self { + api_key: api_key.to_owned(), + }), + _ => Err(errors::ConnectorError::FailedToObtainAuthType.into()), + } + } +} +// PaymentsResponse +//TODO: Append the remaining status flags +#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)] +#[serde(rename_all = "lowercase")] +pub enum EbanxPaymentStatus { + Succeeded, + Failed, + #[default] + Processing, +} + +impl From for enums::AttemptStatus { + fn from(item: EbanxPaymentStatus) -> Self { + match item { + EbanxPaymentStatus::Succeeded => Self::Charged, + EbanxPaymentStatus::Failed => Self::Failure, + EbanxPaymentStatus::Processing => Self::Authorizing, + } + } +} + +//TODO: Fill the struct with respective fields +#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)] +pub struct EbanxPaymentsResponse { + status: EbanxPaymentStatus, + id: String, +} + +impl + TryFrom> + for types::RouterData +{ + type Error = error_stack::Report; + fn try_from( + item: types::ResponseRouterData, + ) -> Result { + Ok(Self { + status: enums::AttemptStatus::from(item.response.status), + response: Ok(types::PaymentsResponseData::TransactionResponse { + resource_id: types::ResponseId::ConnectorTransactionId(item.response.id), + redirection_data: None, + mandate_reference: None, + connector_metadata: None, + network_txn_id: None, + connector_response_reference_id: None, + incremental_authorization_allowed: None, + }), + ..item.data + }) + } +} + +//TODO: Fill the struct with respective fields +// REFUND : +// Type definition for RefundRequest +#[derive(Default, Debug, Serialize)] +pub struct EbanxRefundRequest { + pub amount: i64, +} + +impl TryFrom<&EbanxRouterData<&types::RefundsRouterData>> for EbanxRefundRequest { + type Error = error_stack::Report; + fn try_from(item: &EbanxRouterData<&types::RefundsRouterData>) -> Result { + Ok(Self { + amount: item.amount.to_owned(), + }) + } +} + +// Type definition for Refund Response + +#[allow(dead_code)] +#[derive(Debug, Serialize, Default, Deserialize, Clone)] +pub enum RefundStatus { + Succeeded, + Failed, + #[default] + Processing, +} + +impl From for enums::RefundStatus { + fn from(item: RefundStatus) -> Self { + match item { + RefundStatus::Succeeded => Self::Success, + RefundStatus::Failed => Self::Failure, + RefundStatus::Processing => Self::Pending, + //TODO: Review mapping + } + } +} + +//TODO: Fill the struct with respective fields +#[derive(Default, Debug, Clone, Serialize, Deserialize)] +pub struct RefundResponse { + id: String, + status: RefundStatus, +} + +impl TryFrom> + for types::RefundsRouterData +{ + type Error = error_stack::Report; + fn try_from( + item: types::RefundsResponseRouterData, + ) -> Result { + Ok(Self { + response: Ok(types::RefundsResponseData { + connector_refund_id: item.response.id.to_string(), + refund_status: enums::RefundStatus::from(item.response.status), + }), + ..item.data + }) + } +} + +impl TryFrom> + for types::RefundsRouterData +{ + type Error = error_stack::Report; + fn try_from( + item: types::RefundsResponseRouterData, + ) -> Result { + Ok(Self { + response: Ok(types::RefundsResponseData { + connector_refund_id: item.response.id.to_string(), + refund_status: enums::RefundStatus::from(item.response.status), + }), + ..item.data + }) + } +} + +//TODO: Fill the struct with respective fields +#[derive(Default, Debug, Serialize, Deserialize, PartialEq)] +pub struct EbanxErrorResponse { + pub status_code: u16, + pub code: String, + pub message: String, + pub reason: Option, +} diff --git a/crates/router/src/connector/globalpay/transformers.rs b/crates/router/src/connector/globalpay/transformers.rs index b361aca79fa1..cfb822715bf5 100644 --- a/crates/router/src/connector/globalpay/transformers.rs +++ b/crates/router/src/connector/globalpay/transformers.rs @@ -462,22 +462,20 @@ fn get_wallet_data(wallet_data: &domain::WalletData) -> Result for PaymentMethodData { +impl TryFrom<&domain::BankRedirectData> for PaymentMethodData { type Error = Error; - fn try_from(value: &api_models::payments::BankRedirectData) -> Result { + fn try_from(value: &domain::BankRedirectData) -> Result { match value { - api_models::payments::BankRedirectData::Eps { .. } => Ok(Self::Apm(requests::Apm { + domain::BankRedirectData::Eps { .. } => Ok(Self::Apm(requests::Apm { provider: Some(ApmProvider::Eps), })), - api_models::payments::BankRedirectData::Giropay { .. } => { - Ok(Self::Apm(requests::Apm { - provider: Some(ApmProvider::Giropay), - })) - } - api_models::payments::BankRedirectData::Ideal { .. } => Ok(Self::Apm(requests::Apm { + domain::BankRedirectData::Giropay { .. } => Ok(Self::Apm(requests::Apm { + provider: Some(ApmProvider::Giropay), + })), + domain::BankRedirectData::Ideal { .. } => Ok(Self::Apm(requests::Apm { provider: Some(ApmProvider::Ideal), })), - api_models::payments::BankRedirectData::Sofort { .. } => Ok(Self::Apm(requests::Apm { + domain::BankRedirectData::Sofort { .. } => Ok(Self::Apm(requests::Apm { provider: Some(ApmProvider::Sofort), })), _ => Err(errors::ConnectorError::NotImplemented("Payment method".to_string()).into()), diff --git a/crates/router/src/connector/klarna.rs b/crates/router/src/connector/klarna.rs index 0d1a37d1a44f..814bd68da688 100644 --- a/crates/router/src/connector/klarna.rs +++ b/crates/router/src/connector/klarna.rs @@ -21,7 +21,6 @@ use crate::{ self, api::{self, ConnectorCommon}, domain, - storage::enums as storage_enums, }, utils::BytesExt, }; @@ -307,113 +306,114 @@ impl .ok_or_else(connector_utils::missing_field_err("payment_method_type"))?; match payment_method_data { - domain::PaymentMethodData::PayLater( - api_models::payments::PayLaterData::KlarnaSdk { token }, - ) => match (payment_experience, payment_method_type) { - ( - storage_enums::PaymentExperience::InvokeSdkClient, - storage_enums::PaymentMethodType::Klarna, - ) => Ok(format!( - "{}payments/v1/authorizations/{}/order", - self.base_url(connectors), - token - )), - ( - storage_enums::PaymentExperience::DisplayQrCode - | storage_enums::PaymentExperience::DisplayWaitScreen - | storage_enums::PaymentExperience::InvokePaymentApp - | storage_enums::PaymentExperience::InvokeSdkClient - | storage_enums::PaymentExperience::LinkWallet - | storage_enums::PaymentExperience::OneClick - | storage_enums::PaymentExperience::RedirectToUrl, - api_models::enums::PaymentMethodType::Ach - | api_models::enums::PaymentMethodType::Affirm - | api_models::enums::PaymentMethodType::AfterpayClearpay - | api_models::enums::PaymentMethodType::Alfamart - | api_models::enums::PaymentMethodType::AliPay - | api_models::enums::PaymentMethodType::AliPayHk - | api_models::enums::PaymentMethodType::Alma - | api_models::enums::PaymentMethodType::ApplePay - | api_models::enums::PaymentMethodType::Atome - | api_models::enums::PaymentMethodType::Bacs - | api_models::enums::PaymentMethodType::BancontactCard - | api_models::enums::PaymentMethodType::Becs - | api_models::enums::PaymentMethodType::Benefit - | api_models::enums::PaymentMethodType::Bizum - | api_models::enums::PaymentMethodType::Blik - | api_models::enums::PaymentMethodType::Boleto - | api_models::enums::PaymentMethodType::BcaBankTransfer - | api_models::enums::PaymentMethodType::BniVa - | api_models::enums::PaymentMethodType::BriVa - | api_models::enums::PaymentMethodType::CardRedirect - | api_models::enums::PaymentMethodType::CimbVa - | api_models::enums::PaymentMethodType::ClassicReward - | api_models::enums::PaymentMethodType::Credit - | api_models::enums::PaymentMethodType::CryptoCurrency - | api_models::enums::PaymentMethodType::Cashapp - | api_models::enums::PaymentMethodType::Dana - | api_models::enums::PaymentMethodType::DanamonVa - | api_models::enums::PaymentMethodType::Debit - | api_models::enums::PaymentMethodType::Efecty - | api_models::enums::PaymentMethodType::Eps - | api_models::enums::PaymentMethodType::Evoucher - | api_models::enums::PaymentMethodType::Giropay - | api_models::enums::PaymentMethodType::Givex - | api_models::enums::PaymentMethodType::GooglePay - | api_models::enums::PaymentMethodType::GoPay - | api_models::enums::PaymentMethodType::Gcash - | api_models::enums::PaymentMethodType::Ideal - | api_models::enums::PaymentMethodType::Interac - | api_models::enums::PaymentMethodType::Indomaret - | api_models::enums::PaymentMethodType::Klarna - | api_models::enums::PaymentMethodType::KakaoPay - | api_models::enums::PaymentMethodType::MandiriVa - | api_models::enums::PaymentMethodType::Knet - | api_models::enums::PaymentMethodType::MbWay - | api_models::enums::PaymentMethodType::MobilePay - | api_models::enums::PaymentMethodType::Momo - | api_models::enums::PaymentMethodType::MomoAtm - | api_models::enums::PaymentMethodType::Multibanco - | api_models::enums::PaymentMethodType::OnlineBankingThailand - | api_models::enums::PaymentMethodType::OnlineBankingCzechRepublic - | api_models::enums::PaymentMethodType::OnlineBankingFinland - | api_models::enums::PaymentMethodType::OnlineBankingFpx - | api_models::enums::PaymentMethodType::OnlineBankingPoland - | api_models::enums::PaymentMethodType::OnlineBankingSlovakia - | api_models::enums::PaymentMethodType::Oxxo - | api_models::enums::PaymentMethodType::PagoEfectivo - | api_models::enums::PaymentMethodType::PermataBankTransfer - | api_models::enums::PaymentMethodType::OpenBankingUk - | api_models::enums::PaymentMethodType::PayBright - | api_models::enums::PaymentMethodType::Paypal - | api_models::enums::PaymentMethodType::Pix - | api_models::enums::PaymentMethodType::PaySafeCard - | api_models::enums::PaymentMethodType::Przelewy24 - | api_models::enums::PaymentMethodType::Pse - | api_models::enums::PaymentMethodType::RedCompra - | api_models::enums::PaymentMethodType::RedPagos - | api_models::enums::PaymentMethodType::SamsungPay - | api_models::enums::PaymentMethodType::Sepa - | api_models::enums::PaymentMethodType::Sofort - | api_models::enums::PaymentMethodType::Swish - | api_models::enums::PaymentMethodType::TouchNGo - | api_models::enums::PaymentMethodType::Trustly - | api_models::enums::PaymentMethodType::Twint - | api_models::enums::PaymentMethodType::UpiCollect - | api_models::enums::PaymentMethodType::Vipps - | api_models::enums::PaymentMethodType::Walley - | api_models::enums::PaymentMethodType::WeChatPay - | api_models::enums::PaymentMethodType::SevenEleven - | api_models::enums::PaymentMethodType::Lawson - | api_models::enums::PaymentMethodType::MiniStop - | api_models::enums::PaymentMethodType::FamilyMart - | api_models::enums::PaymentMethodType::Seicomart - | api_models::enums::PaymentMethodType::PayEasy, - ) => Err(error_stack::report!(errors::ConnectorError::NotSupported { - message: payment_method_type.to_string(), - connector: "klarna", - })), - }, + domain::PaymentMethodData::PayLater(domain::PayLaterData::KlarnaSdk { token }) => { + match (payment_experience, payment_method_type) { + ( + common_enums::PaymentExperience::InvokeSdkClient, + common_enums::PaymentMethodType::Klarna, + ) => Ok(format!( + "{}payments/v1/authorizations/{}/order", + self.base_url(connectors), + token + )), + ( + common_enums::PaymentExperience::DisplayQrCode + | common_enums::PaymentExperience::DisplayWaitScreen + | common_enums::PaymentExperience::InvokePaymentApp + | common_enums::PaymentExperience::InvokeSdkClient + | common_enums::PaymentExperience::LinkWallet + | common_enums::PaymentExperience::OneClick + | common_enums::PaymentExperience::RedirectToUrl, + common_enums::PaymentMethodType::Ach + | common_enums::PaymentMethodType::Affirm + | common_enums::PaymentMethodType::AfterpayClearpay + | common_enums::PaymentMethodType::Alfamart + | common_enums::PaymentMethodType::AliPay + | common_enums::PaymentMethodType::AliPayHk + | common_enums::PaymentMethodType::Alma + | common_enums::PaymentMethodType::ApplePay + | common_enums::PaymentMethodType::Atome + | common_enums::PaymentMethodType::Bacs + | common_enums::PaymentMethodType::BancontactCard + | common_enums::PaymentMethodType::Becs + | common_enums::PaymentMethodType::Benefit + | common_enums::PaymentMethodType::Bizum + | common_enums::PaymentMethodType::Blik + | common_enums::PaymentMethodType::Boleto + | common_enums::PaymentMethodType::BcaBankTransfer + | common_enums::PaymentMethodType::BniVa + | common_enums::PaymentMethodType::BriVa + | common_enums::PaymentMethodType::CardRedirect + | common_enums::PaymentMethodType::CimbVa + | common_enums::PaymentMethodType::ClassicReward + | common_enums::PaymentMethodType::Credit + | common_enums::PaymentMethodType::CryptoCurrency + | common_enums::PaymentMethodType::Cashapp + | common_enums::PaymentMethodType::Dana + | common_enums::PaymentMethodType::DanamonVa + | common_enums::PaymentMethodType::Debit + | common_enums::PaymentMethodType::Efecty + | common_enums::PaymentMethodType::Eps + | common_enums::PaymentMethodType::Evoucher + | common_enums::PaymentMethodType::Giropay + | common_enums::PaymentMethodType::Givex + | common_enums::PaymentMethodType::GooglePay + | common_enums::PaymentMethodType::GoPay + | common_enums::PaymentMethodType::Gcash + | common_enums::PaymentMethodType::Ideal + | common_enums::PaymentMethodType::Interac + | common_enums::PaymentMethodType::Indomaret + | common_enums::PaymentMethodType::Klarna + | common_enums::PaymentMethodType::KakaoPay + | common_enums::PaymentMethodType::MandiriVa + | common_enums::PaymentMethodType::Knet + | common_enums::PaymentMethodType::MbWay + | common_enums::PaymentMethodType::MobilePay + | common_enums::PaymentMethodType::Momo + | common_enums::PaymentMethodType::MomoAtm + | common_enums::PaymentMethodType::Multibanco + | common_enums::PaymentMethodType::OnlineBankingThailand + | common_enums::PaymentMethodType::OnlineBankingCzechRepublic + | common_enums::PaymentMethodType::OnlineBankingFinland + | common_enums::PaymentMethodType::OnlineBankingFpx + | common_enums::PaymentMethodType::OnlineBankingPoland + | common_enums::PaymentMethodType::OnlineBankingSlovakia + | common_enums::PaymentMethodType::Oxxo + | common_enums::PaymentMethodType::PagoEfectivo + | common_enums::PaymentMethodType::PermataBankTransfer + | common_enums::PaymentMethodType::OpenBankingUk + | common_enums::PaymentMethodType::PayBright + | common_enums::PaymentMethodType::Paypal + | common_enums::PaymentMethodType::Pix + | common_enums::PaymentMethodType::PaySafeCard + | common_enums::PaymentMethodType::Przelewy24 + | common_enums::PaymentMethodType::Pse + | common_enums::PaymentMethodType::RedCompra + | common_enums::PaymentMethodType::RedPagos + | common_enums::PaymentMethodType::SamsungPay + | common_enums::PaymentMethodType::Sepa + | common_enums::PaymentMethodType::Sofort + | common_enums::PaymentMethodType::Swish + | common_enums::PaymentMethodType::TouchNGo + | common_enums::PaymentMethodType::Trustly + | common_enums::PaymentMethodType::Twint + | common_enums::PaymentMethodType::UpiCollect + | common_enums::PaymentMethodType::Vipps + | common_enums::PaymentMethodType::Walley + | common_enums::PaymentMethodType::WeChatPay + | common_enums::PaymentMethodType::SevenEleven + | common_enums::PaymentMethodType::Lawson + | common_enums::PaymentMethodType::LocalBankTransfer + | common_enums::PaymentMethodType::MiniStop + | common_enums::PaymentMethodType::FamilyMart + | common_enums::PaymentMethodType::Seicomart + | common_enums::PaymentMethodType::PayEasy, + ) => Err(error_stack::report!(errors::ConnectorError::NotSupported { + message: payment_method_type.to_string(), + connector: "klarna", + })), + } + } domain::PaymentMethodData::Card(_) | domain::PaymentMethodData::CardRedirect(_) diff --git a/crates/router/src/connector/mollie/transformers.rs b/crates/router/src/connector/mollie/transformers.rs index 68ea3ab58681..359320eb0850 100644 --- a/crates/router/src/connector/mollie/transformers.rs +++ b/crates/router/src/connector/mollie/transformers.rs @@ -230,25 +230,25 @@ impl TryFrom<&MollieRouterData<&types::PaymentsAuthorizeRouterData>> for MollieP } } -impl TryFrom<&api_models::payments::BankRedirectData> for PaymentMethodData { +impl TryFrom<&domain::BankRedirectData> for PaymentMethodData { type Error = Error; - fn try_from(value: &api_models::payments::BankRedirectData) -> Result { + fn try_from(value: &domain::BankRedirectData) -> Result { match value { - api_models::payments::BankRedirectData::Eps { .. } => Ok(Self::Eps), - api_models::payments::BankRedirectData::Giropay { .. } => Ok(Self::Giropay), - api_models::payments::BankRedirectData::Ideal { .. } => { + domain::BankRedirectData::Eps { .. } => Ok(Self::Eps), + domain::BankRedirectData::Giropay { .. } => Ok(Self::Giropay), + domain::BankRedirectData::Ideal { .. } => { Ok(Self::Ideal(Box::new(IdealMethodData { // To do if possible this should be from the payment request issuer: None, }))) } - api_models::payments::BankRedirectData::Sofort { .. } => Ok(Self::Sofort), - api_models::payments::BankRedirectData::Przelewy24 { + domain::BankRedirectData::Sofort { .. } => Ok(Self::Sofort), + domain::BankRedirectData::Przelewy24 { billing_details, .. } => Ok(Self::Przelewy24(Box::new(Przelewy24MethodData { billing_email: billing_details.email.clone(), }))), - api_models::payments::BankRedirectData::BancontactCard { .. } => Ok(Self::Bancontact), + domain::BankRedirectData::BancontactCard { .. } => Ok(Self::Bancontact), _ => Err(errors::ConnectorError::NotImplemented("Payment method".to_string()).into()), } } diff --git a/crates/router/src/connector/multisafepay/transformers.rs b/crates/router/src/connector/multisafepay/transformers.rs index b26c260f9360..39433c38aabb 100644 --- a/crates/router/src/connector/multisafepay/transformers.rs +++ b/crates/router/src/connector/multisafepay/transformers.rs @@ -349,12 +349,10 @@ impl TryFrom<&MultisafepayRouterData<&types::PaymentsAuthorizeRouterData>> utils::get_unimplemented_payment_method_error_message("multisafepay"), ))?, }), - domain::PaymentMethodData::PayLater( - api_models::payments::PayLaterData::KlarnaRedirect { - billing_email: _, - billing_country: _, - }, - ) => Some(Gateway::Klarna), + domain::PaymentMethodData::PayLater(domain::PayLaterData::KlarnaRedirect { + billing_email: _, + billing_country: _, + }) => Some(Gateway::Klarna), domain::PaymentMethodData::MandatePayment => None, domain::PaymentMethodData::CardRedirect(_) | domain::PaymentMethodData::PayLater(_) @@ -482,20 +480,19 @@ impl TryFrom<&MultisafepayRouterData<&types::PaymentsAuthorizeRouterData>> domain::PaymentMethodData::PayLater(ref paylater) => { Some(GatewayInfo::PayLater(PayLaterInfo { email: Some(match paylater { - api_models::payments::PayLaterData::KlarnaRedirect { - billing_email, - .. - } => billing_email.clone(), - api_models::payments::PayLaterData::KlarnaSdk { token: _ } - | api_models::payments::PayLaterData::AffirmRedirect {} - | api_models::payments::PayLaterData::AfterpayClearpayRedirect { + domain::PayLaterData::KlarnaRedirect { billing_email, .. } => { + billing_email.clone() + } + domain::PayLaterData::KlarnaSdk { token: _ } + | domain::PayLaterData::AffirmRedirect {} + | domain::PayLaterData::AfterpayClearpayRedirect { billing_email: _, billing_name: _, } - | api_models::payments::PayLaterData::PayBrightRedirect {} - | api_models::payments::PayLaterData::WalleyRedirect {} - | api_models::payments::PayLaterData::AlmaRedirect {} - | api_models::payments::PayLaterData::AtomeRedirect {} => { + | domain::PayLaterData::PayBrightRedirect {} + | domain::PayLaterData::WalleyRedirect {} + | domain::PayLaterData::AlmaRedirect {} + | domain::PayLaterData::AtomeRedirect {} => { Err(errors::ConnectorError::NotImplemented( utils::get_unimplemented_payment_method_error_message( "multisafepay", diff --git a/crates/router/src/connector/nexinets/transformers.rs b/crates/router/src/connector/nexinets/transformers.rs index 693e7671ec95..c6ef4ea1ba82 100644 --- a/crates/router/src/connector/nexinets/transformers.rs +++ b/crates/router/src/connector/nexinets/transformers.rs @@ -252,20 +252,20 @@ impl ForeignFrom<(NexinetsPaymentStatus, NexinetsTransactionType)> for enums::At } } -impl TryFrom<&api_models::enums::BankNames> for NexinetsBIC { +impl TryFrom<&common_enums::enums::BankNames> for NexinetsBIC { type Error = error_stack::Report; - fn try_from(bank: &api_models::enums::BankNames) -> Result { + fn try_from(bank: &common_enums::enums::BankNames) -> Result { match bank { - api_models::enums::BankNames::AbnAmro => Ok(Self::AbnAmro), - api_models::enums::BankNames::AsnBank => Ok(Self::AsnBank), - api_models::enums::BankNames::Bunq => Ok(Self::Bunq), - api_models::enums::BankNames::Ing => Ok(Self::Ing), - api_models::enums::BankNames::Knab => Ok(Self::Knab), - api_models::enums::BankNames::Rabobank => Ok(Self::Rabobank), - api_models::enums::BankNames::Regiobank => Ok(Self::Regiobank), - api_models::enums::BankNames::SnsBank => Ok(Self::SnsBank), - api_models::enums::BankNames::TriodosBank => Ok(Self::TriodosBank), - api_models::enums::BankNames::VanLanschot => Ok(Self::VanLanschot), + common_enums::enums::BankNames::AbnAmro => Ok(Self::AbnAmro), + common_enums::enums::BankNames::AsnBank => Ok(Self::AsnBank), + common_enums::enums::BankNames::Bunq => Ok(Self::Bunq), + common_enums::enums::BankNames::Ing => Ok(Self::Ing), + common_enums::enums::BankNames::Knab => Ok(Self::Knab), + common_enums::enums::BankNames::Rabobank => Ok(Self::Rabobank), + common_enums::enums::BankNames::Regiobank => Ok(Self::Regiobank), + common_enums::enums::BankNames::SnsBank => Ok(Self::SnsBank), + common_enums::enums::BankNames::TriodosBank => Ok(Self::TriodosBank), + common_enums::enums::BankNames::VanLanschot => Ok(Self::VanLanschot), _ => Err(errors::ConnectorError::FlowNotSupported { flow: bank.to_string(), connector: "Nexinets".to_string(), @@ -580,11 +580,9 @@ fn get_payment_details_and_product( )), PaymentMethodData::Wallet(wallet) => Ok(get_wallet_details(wallet)?), PaymentMethodData::BankRedirect(bank_redirect) => match bank_redirect { - api_models::payments::BankRedirectData::Eps { .. } => Ok((None, NexinetsProduct::Eps)), - api_models::payments::BankRedirectData::Giropay { .. } => { - Ok((None, NexinetsProduct::Giropay)) - } - api_models::payments::BankRedirectData::Ideal { bank_name, .. } => Ok(( + domain::BankRedirectData::Eps { .. } => Ok((None, NexinetsProduct::Eps)), + domain::BankRedirectData::Giropay { .. } => Ok((None, NexinetsProduct::Giropay)), + domain::BankRedirectData::Ideal { bank_name, .. } => Ok(( Some(NexinetsPaymentDetails::BankRedirects(Box::new( NexinetsBankRedirects { bic: bank_name @@ -594,22 +592,20 @@ fn get_payment_details_and_product( ))), NexinetsProduct::Ideal, )), - api_models::payments::BankRedirectData::Sofort { .. } => { - Ok((None, NexinetsProduct::Sofort)) - } - api_models::payments::BankRedirectData::BancontactCard { .. } - | api_models::payments::BankRedirectData::Blik { .. } - | api_models::payments::BankRedirectData::Bizum { .. } - | api_models::payments::BankRedirectData::Interac { .. } - | api_models::payments::BankRedirectData::OnlineBankingCzechRepublic { .. } - | api_models::payments::BankRedirectData::OnlineBankingFinland { .. } - | api_models::payments::BankRedirectData::OnlineBankingPoland { .. } - | api_models::payments::BankRedirectData::OnlineBankingSlovakia { .. } - | api_models::payments::BankRedirectData::OpenBankingUk { .. } - | api_models::payments::BankRedirectData::Przelewy24 { .. } - | api_models::payments::BankRedirectData::Trustly { .. } - | api_models::payments::BankRedirectData::OnlineBankingFpx { .. } - | api_models::payments::BankRedirectData::OnlineBankingThailand { .. } => { + domain::BankRedirectData::Sofort { .. } => Ok((None, NexinetsProduct::Sofort)), + domain::BankRedirectData::BancontactCard { .. } + | domain::BankRedirectData::Blik { .. } + | domain::BankRedirectData::Bizum { .. } + | domain::BankRedirectData::Interac { .. } + | domain::BankRedirectData::OnlineBankingCzechRepublic { .. } + | domain::BankRedirectData::OnlineBankingFinland { .. } + | domain::BankRedirectData::OnlineBankingPoland { .. } + | domain::BankRedirectData::OnlineBankingSlovakia { .. } + | domain::BankRedirectData::OpenBankingUk { .. } + | domain::BankRedirectData::Przelewy24 { .. } + | domain::BankRedirectData::Trustly { .. } + | domain::BankRedirectData::OnlineBankingFpx { .. } + | domain::BankRedirectData::OnlineBankingThailand { .. } => { Err(errors::ConnectorError::NotImplemented( utils::get_unimplemented_payment_method_error_message("nexinets"), ))? diff --git a/crates/router/src/connector/nuvei/transformers.rs b/crates/router/src/connector/nuvei/transformers.rs index ece7c2dcedcc..08c3b8fbc9fe 100644 --- a/crates/router/src/connector/nuvei/transformers.rs +++ b/crates/router/src/connector/nuvei/transformers.rs @@ -1,4 +1,3 @@ -use api_models::payments; use common_utils::{ crypto::{self, GenerateDigest}, date_time, @@ -470,156 +469,156 @@ impl From for NuveiPaymentsRequest { } } -impl TryFrom for NuveiBIC { +impl TryFrom for NuveiBIC { type Error = error_stack::Report; - fn try_from(bank: api_models::enums::BankNames) -> Result { + fn try_from(bank: common_enums::enums::BankNames) -> Result { match bank { - api_models::enums::BankNames::AbnAmro => Ok(Self::Abnamro), - api_models::enums::BankNames::AsnBank => Ok(Self::ASNBank), - api_models::enums::BankNames::Bunq => Ok(Self::Bunq), - api_models::enums::BankNames::Ing => Ok(Self::Ing), - api_models::enums::BankNames::Knab => Ok(Self::Knab), - api_models::enums::BankNames::Rabobank => Ok(Self::Rabobank), - api_models::enums::BankNames::SnsBank => Ok(Self::SNSBank), - api_models::enums::BankNames::TriodosBank => Ok(Self::TriodosBank), - api_models::enums::BankNames::VanLanschot => Ok(Self::VanLanschotBankiers), - api_models::enums::BankNames::Moneyou => Ok(Self::Moneyou), - - api_models::enums::BankNames::AmericanExpress - | api_models::enums::BankNames::AffinBank - | api_models::enums::BankNames::AgroBank - | api_models::enums::BankNames::AllianceBank - | api_models::enums::BankNames::AmBank - | api_models::enums::BankNames::BankOfAmerica - | api_models::enums::BankNames::BankIslam - | api_models::enums::BankNames::BankMuamalat - | api_models::enums::BankNames::BankRakyat - | api_models::enums::BankNames::BankSimpananNasional - | api_models::enums::BankNames::Barclays - | api_models::enums::BankNames::BlikPSP - | api_models::enums::BankNames::CapitalOne - | api_models::enums::BankNames::Chase - | api_models::enums::BankNames::Citi - | api_models::enums::BankNames::CimbBank - | api_models::enums::BankNames::Discover - | api_models::enums::BankNames::NavyFederalCreditUnion - | api_models::enums::BankNames::PentagonFederalCreditUnion - | api_models::enums::BankNames::SynchronyBank - | api_models::enums::BankNames::WellsFargo - | api_models::enums::BankNames::Handelsbanken - | api_models::enums::BankNames::HongLeongBank - | api_models::enums::BankNames::HsbcBank - | api_models::enums::BankNames::KuwaitFinanceHouse - | api_models::enums::BankNames::Regiobank - | api_models::enums::BankNames::Revolut - | api_models::enums::BankNames::ArzteUndApothekerBank - | api_models::enums::BankNames::AustrianAnadiBankAg - | api_models::enums::BankNames::BankAustria - | api_models::enums::BankNames::Bank99Ag - | api_models::enums::BankNames::BankhausCarlSpangler - | api_models::enums::BankNames::BankhausSchelhammerUndSchatteraAg - | api_models::enums::BankNames::BankMillennium - | api_models::enums::BankNames::BankPEKAOSA - | api_models::enums::BankNames::BawagPskAg - | api_models::enums::BankNames::BksBankAg - | api_models::enums::BankNames::BrullKallmusBankAg - | api_models::enums::BankNames::BtvVierLanderBank - | api_models::enums::BankNames::CapitalBankGraweGruppeAg - | api_models::enums::BankNames::CeskaSporitelna - | api_models::enums::BankNames::Dolomitenbank - | api_models::enums::BankNames::EasybankAg - | api_models::enums::BankNames::EPlatbyVUB - | api_models::enums::BankNames::ErsteBankUndSparkassen - | api_models::enums::BankNames::FrieslandBank - | api_models::enums::BankNames::HypoAlpeadriabankInternationalAg - | api_models::enums::BankNames::HypoNoeLbFurNiederosterreichUWien - | api_models::enums::BankNames::HypoOberosterreichSalzburgSteiermark - | api_models::enums::BankNames::HypoTirolBankAg - | api_models::enums::BankNames::HypoVorarlbergBankAg - | api_models::enums::BankNames::HypoBankBurgenlandAktiengesellschaft - | api_models::enums::BankNames::KomercniBanka - | api_models::enums::BankNames::MBank - | api_models::enums::BankNames::MarchfelderBank - | api_models::enums::BankNames::Maybank - | api_models::enums::BankNames::OberbankAg - | api_models::enums::BankNames::OsterreichischeArzteUndApothekerbank - | api_models::enums::BankNames::OcbcBank - | api_models::enums::BankNames::PayWithING - | api_models::enums::BankNames::PlaceZIPKO - | api_models::enums::BankNames::PlatnoscOnlineKartaPlatnicza - | api_models::enums::BankNames::PosojilnicaBankEGen - | api_models::enums::BankNames::PostovaBanka - | api_models::enums::BankNames::PublicBank - | api_models::enums::BankNames::RaiffeisenBankengruppeOsterreich - | api_models::enums::BankNames::RhbBank - | api_models::enums::BankNames::SchelhammerCapitalBankAg - | api_models::enums::BankNames::StandardCharteredBank - | api_models::enums::BankNames::SchoellerbankAg - | api_models::enums::BankNames::SpardaBankWien - | api_models::enums::BankNames::SporoPay - | api_models::enums::BankNames::SantanderPrzelew24 - | api_models::enums::BankNames::TatraPay - | api_models::enums::BankNames::Viamo - | api_models::enums::BankNames::VolksbankGruppe - | api_models::enums::BankNames::VolkskreditbankAg - | api_models::enums::BankNames::VrBankBraunau - | api_models::enums::BankNames::UobBank - | api_models::enums::BankNames::PayWithAliorBank - | api_models::enums::BankNames::BankiSpoldzielcze - | api_models::enums::BankNames::PayWithInteligo - | api_models::enums::BankNames::BNPParibasPoland - | api_models::enums::BankNames::BankNowySA - | api_models::enums::BankNames::CreditAgricole - | api_models::enums::BankNames::PayWithBOS - | api_models::enums::BankNames::PayWithCitiHandlowy - | api_models::enums::BankNames::PayWithPlusBank - | api_models::enums::BankNames::ToyotaBank - | api_models::enums::BankNames::VeloBank - | api_models::enums::BankNames::ETransferPocztowy24 - | api_models::enums::BankNames::PlusBank - | api_models::enums::BankNames::EtransferPocztowy24 - | api_models::enums::BankNames::BankiSpbdzielcze - | api_models::enums::BankNames::BankNowyBfgSa - | api_models::enums::BankNames::GetinBank - | api_models::enums::BankNames::Blik - | api_models::enums::BankNames::NoblePay - | api_models::enums::BankNames::IdeaBank - | api_models::enums::BankNames::EnveloBank - | api_models::enums::BankNames::NestPrzelew - | api_models::enums::BankNames::MbankMtransfer - | api_models::enums::BankNames::Inteligo - | api_models::enums::BankNames::PbacZIpko - | api_models::enums::BankNames::BnpParibas - | api_models::enums::BankNames::BankPekaoSa - | api_models::enums::BankNames::VolkswagenBank - | api_models::enums::BankNames::AliorBank - | api_models::enums::BankNames::Boz - | api_models::enums::BankNames::BangkokBank - | api_models::enums::BankNames::KrungsriBank - | api_models::enums::BankNames::KrungThaiBank - | api_models::enums::BankNames::TheSiamCommercialBank - | api_models::enums::BankNames::KasikornBank - | api_models::enums::BankNames::OpenBankSuccess - | api_models::enums::BankNames::OpenBankFailure - | api_models::enums::BankNames::OpenBankCancelled - | api_models::enums::BankNames::Aib - | api_models::enums::BankNames::BankOfScotland - | api_models::enums::BankNames::DanskeBank - | api_models::enums::BankNames::FirstDirect - | api_models::enums::BankNames::FirstTrust - | api_models::enums::BankNames::Halifax - | api_models::enums::BankNames::Lloyds - | api_models::enums::BankNames::Monzo - | api_models::enums::BankNames::NatWest - | api_models::enums::BankNames::NationwideBank - | api_models::enums::BankNames::RoyalBankOfScotland - | api_models::enums::BankNames::Starling - | api_models::enums::BankNames::TsbBank - | api_models::enums::BankNames::TescoBank - | api_models::enums::BankNames::Yoursafe - | api_models::enums::BankNames::N26 - | api_models::enums::BankNames::NationaleNederlanden - | api_models::enums::BankNames::UlsterBank => { + common_enums::enums::BankNames::AbnAmro => Ok(Self::Abnamro), + common_enums::enums::BankNames::AsnBank => Ok(Self::ASNBank), + common_enums::enums::BankNames::Bunq => Ok(Self::Bunq), + common_enums::enums::BankNames::Ing => Ok(Self::Ing), + common_enums::enums::BankNames::Knab => Ok(Self::Knab), + common_enums::enums::BankNames::Rabobank => Ok(Self::Rabobank), + common_enums::enums::BankNames::SnsBank => Ok(Self::SNSBank), + common_enums::enums::BankNames::TriodosBank => Ok(Self::TriodosBank), + common_enums::enums::BankNames::VanLanschot => Ok(Self::VanLanschotBankiers), + common_enums::enums::BankNames::Moneyou => Ok(Self::Moneyou), + + common_enums::enums::BankNames::AmericanExpress + | common_enums::enums::BankNames::AffinBank + | common_enums::enums::BankNames::AgroBank + | common_enums::enums::BankNames::AllianceBank + | common_enums::enums::BankNames::AmBank + | common_enums::enums::BankNames::BankOfAmerica + | common_enums::enums::BankNames::BankIslam + | common_enums::enums::BankNames::BankMuamalat + | common_enums::enums::BankNames::BankRakyat + | common_enums::enums::BankNames::BankSimpananNasional + | common_enums::enums::BankNames::Barclays + | common_enums::enums::BankNames::BlikPSP + | common_enums::enums::BankNames::CapitalOne + | common_enums::enums::BankNames::Chase + | common_enums::enums::BankNames::Citi + | common_enums::enums::BankNames::CimbBank + | common_enums::enums::BankNames::Discover + | common_enums::enums::BankNames::NavyFederalCreditUnion + | common_enums::enums::BankNames::PentagonFederalCreditUnion + | common_enums::enums::BankNames::SynchronyBank + | common_enums::enums::BankNames::WellsFargo + | common_enums::enums::BankNames::Handelsbanken + | common_enums::enums::BankNames::HongLeongBank + | common_enums::enums::BankNames::HsbcBank + | common_enums::enums::BankNames::KuwaitFinanceHouse + | common_enums::enums::BankNames::Regiobank + | common_enums::enums::BankNames::Revolut + | common_enums::enums::BankNames::ArzteUndApothekerBank + | common_enums::enums::BankNames::AustrianAnadiBankAg + | common_enums::enums::BankNames::BankAustria + | common_enums::enums::BankNames::Bank99Ag + | common_enums::enums::BankNames::BankhausCarlSpangler + | common_enums::enums::BankNames::BankhausSchelhammerUndSchatteraAg + | common_enums::enums::BankNames::BankMillennium + | common_enums::enums::BankNames::BankPEKAOSA + | common_enums::enums::BankNames::BawagPskAg + | common_enums::enums::BankNames::BksBankAg + | common_enums::enums::BankNames::BrullKallmusBankAg + | common_enums::enums::BankNames::BtvVierLanderBank + | common_enums::enums::BankNames::CapitalBankGraweGruppeAg + | common_enums::enums::BankNames::CeskaSporitelna + | common_enums::enums::BankNames::Dolomitenbank + | common_enums::enums::BankNames::EasybankAg + | common_enums::enums::BankNames::EPlatbyVUB + | common_enums::enums::BankNames::ErsteBankUndSparkassen + | common_enums::enums::BankNames::FrieslandBank + | common_enums::enums::BankNames::HypoAlpeadriabankInternationalAg + | common_enums::enums::BankNames::HypoNoeLbFurNiederosterreichUWien + | common_enums::enums::BankNames::HypoOberosterreichSalzburgSteiermark + | common_enums::enums::BankNames::HypoTirolBankAg + | common_enums::enums::BankNames::HypoVorarlbergBankAg + | common_enums::enums::BankNames::HypoBankBurgenlandAktiengesellschaft + | common_enums::enums::BankNames::KomercniBanka + | common_enums::enums::BankNames::MBank + | common_enums::enums::BankNames::MarchfelderBank + | common_enums::enums::BankNames::Maybank + | common_enums::enums::BankNames::OberbankAg + | common_enums::enums::BankNames::OsterreichischeArzteUndApothekerbank + | common_enums::enums::BankNames::OcbcBank + | common_enums::enums::BankNames::PayWithING + | common_enums::enums::BankNames::PlaceZIPKO + | common_enums::enums::BankNames::PlatnoscOnlineKartaPlatnicza + | common_enums::enums::BankNames::PosojilnicaBankEGen + | common_enums::enums::BankNames::PostovaBanka + | common_enums::enums::BankNames::PublicBank + | common_enums::enums::BankNames::RaiffeisenBankengruppeOsterreich + | common_enums::enums::BankNames::RhbBank + | common_enums::enums::BankNames::SchelhammerCapitalBankAg + | common_enums::enums::BankNames::StandardCharteredBank + | common_enums::enums::BankNames::SchoellerbankAg + | common_enums::enums::BankNames::SpardaBankWien + | common_enums::enums::BankNames::SporoPay + | common_enums::enums::BankNames::SantanderPrzelew24 + | common_enums::enums::BankNames::TatraPay + | common_enums::enums::BankNames::Viamo + | common_enums::enums::BankNames::VolksbankGruppe + | common_enums::enums::BankNames::VolkskreditbankAg + | common_enums::enums::BankNames::VrBankBraunau + | common_enums::enums::BankNames::UobBank + | common_enums::enums::BankNames::PayWithAliorBank + | common_enums::enums::BankNames::BankiSpoldzielcze + | common_enums::enums::BankNames::PayWithInteligo + | common_enums::enums::BankNames::BNPParibasPoland + | common_enums::enums::BankNames::BankNowySA + | common_enums::enums::BankNames::CreditAgricole + | common_enums::enums::BankNames::PayWithBOS + | common_enums::enums::BankNames::PayWithCitiHandlowy + | common_enums::enums::BankNames::PayWithPlusBank + | common_enums::enums::BankNames::ToyotaBank + | common_enums::enums::BankNames::VeloBank + | common_enums::enums::BankNames::ETransferPocztowy24 + | common_enums::enums::BankNames::PlusBank + | common_enums::enums::BankNames::EtransferPocztowy24 + | common_enums::enums::BankNames::BankiSpbdzielcze + | common_enums::enums::BankNames::BankNowyBfgSa + | common_enums::enums::BankNames::GetinBank + | common_enums::enums::BankNames::Blik + | common_enums::enums::BankNames::NoblePay + | common_enums::enums::BankNames::IdeaBank + | common_enums::enums::BankNames::EnveloBank + | common_enums::enums::BankNames::NestPrzelew + | common_enums::enums::BankNames::MbankMtransfer + | common_enums::enums::BankNames::Inteligo + | common_enums::enums::BankNames::PbacZIpko + | common_enums::enums::BankNames::BnpParibas + | common_enums::enums::BankNames::BankPekaoSa + | common_enums::enums::BankNames::VolkswagenBank + | common_enums::enums::BankNames::AliorBank + | common_enums::enums::BankNames::Boz + | common_enums::enums::BankNames::BangkokBank + | common_enums::enums::BankNames::KrungsriBank + | common_enums::enums::BankNames::KrungThaiBank + | common_enums::enums::BankNames::TheSiamCommercialBank + | common_enums::enums::BankNames::KasikornBank + | common_enums::enums::BankNames::OpenBankSuccess + | common_enums::enums::BankNames::OpenBankFailure + | common_enums::enums::BankNames::OpenBankCancelled + | common_enums::enums::BankNames::Aib + | common_enums::enums::BankNames::BankOfScotland + | common_enums::enums::BankNames::DanskeBank + | common_enums::enums::BankNames::FirstDirect + | common_enums::enums::BankNames::FirstTrust + | common_enums::enums::BankNames::Halifax + | common_enums::enums::BankNames::Lloyds + | common_enums::enums::BankNames::Monzo + | common_enums::enums::BankNames::NatWest + | common_enums::enums::BankNames::NationwideBank + | common_enums::enums::BankNames::RoyalBankOfScotland + | common_enums::enums::BankNames::Starling + | common_enums::enums::BankNames::TsbBank + | common_enums::enums::BankNames::TescoBank + | common_enums::enums::BankNames::Yoursafe + | common_enums::enums::BankNames::N26 + | common_enums::enums::BankNames::NationaleNederlanden + | common_enums::enums::BankNames::UlsterBank => { Err(errors::ConnectorError::NotImplemented( utils::get_unimplemented_payment_method_error_message("Nuvei"), ))? @@ -631,7 +630,7 @@ impl TryFrom for NuveiBIC { impl ForeignTryFrom<( AlternativePaymentMethodType, - Option, + Option, &types::RouterData, )> for NuveiPaymentsRequest { @@ -639,7 +638,7 @@ impl fn foreign_try_from( data: ( AlternativePaymentMethodType, - Option, + Option, &types::RouterData, ), ) -> Result { @@ -675,7 +674,7 @@ impl } ( AlternativePaymentMethodType::Ideal, - Some(payments::BankRedirectData::Ideal { bank_name, .. }), + Some(domain::BankRedirectData::Ideal { bank_name, .. }), ) => { let address = item.get_billing_address()?; ( @@ -789,39 +788,39 @@ impl } }, domain::PaymentMethodData::BankRedirect(redirect) => match redirect { - payments::BankRedirectData::Eps { .. } => Self::foreign_try_from(( + domain::BankRedirectData::Eps { .. } => Self::foreign_try_from(( AlternativePaymentMethodType::Eps, Some(redirect), item, )), - payments::BankRedirectData::Giropay { .. } => Self::foreign_try_from(( + domain::BankRedirectData::Giropay { .. } => Self::foreign_try_from(( AlternativePaymentMethodType::Giropay, Some(redirect), item, )), - payments::BankRedirectData::Ideal { .. } => Self::foreign_try_from(( + domain::BankRedirectData::Ideal { .. } => Self::foreign_try_from(( AlternativePaymentMethodType::Ideal, Some(redirect), item, )), - payments::BankRedirectData::Sofort { .. } => Self::foreign_try_from(( + domain::BankRedirectData::Sofort { .. } => Self::foreign_try_from(( AlternativePaymentMethodType::Sofort, Some(redirect), item, )), - payments::BankRedirectData::BancontactCard { .. } - | payments::BankRedirectData::Bizum {} - | payments::BankRedirectData::Blik { .. } - | payments::BankRedirectData::Interac { .. } - | payments::BankRedirectData::OnlineBankingCzechRepublic { .. } - | payments::BankRedirectData::OnlineBankingFinland { .. } - | payments::BankRedirectData::OnlineBankingPoland { .. } - | payments::BankRedirectData::OnlineBankingSlovakia { .. } - | payments::BankRedirectData::Przelewy24 { .. } - | payments::BankRedirectData::Trustly { .. } - | payments::BankRedirectData::OnlineBankingFpx { .. } - | payments::BankRedirectData::OnlineBankingThailand { .. } - | payments::BankRedirectData::OpenBankingUk { .. } => { + domain::BankRedirectData::BancontactCard { .. } + | domain::BankRedirectData::Bizum {} + | domain::BankRedirectData::Blik { .. } + | domain::BankRedirectData::Interac { .. } + | domain::BankRedirectData::OnlineBankingCzechRepublic { .. } + | domain::BankRedirectData::OnlineBankingFinland { .. } + | domain::BankRedirectData::OnlineBankingPoland { .. } + | domain::BankRedirectData::OnlineBankingSlovakia { .. } + | domain::BankRedirectData::Przelewy24 { .. } + | domain::BankRedirectData::Trustly { .. } + | domain::BankRedirectData::OnlineBankingFpx { .. } + | domain::BankRedirectData::OnlineBankingThailand { .. } + | domain::BankRedirectData::OpenBankingUk { .. } => { Err(errors::ConnectorError::NotImplemented( utils::get_unimplemented_payment_method_error_message("nuvei"), ) @@ -829,18 +828,18 @@ impl } }, domain::PaymentMethodData::PayLater(pay_later_data) => match pay_later_data { - payments::PayLaterData::KlarnaRedirect { .. } => { + domain::PayLaterData::KlarnaRedirect { .. } => { get_pay_later_info(AlternativePaymentMethodType::Klarna, item) } - payments::PayLaterData::AfterpayClearpayRedirect { .. } => { + domain::PayLaterData::AfterpayClearpayRedirect { .. } => { get_pay_later_info(AlternativePaymentMethodType::AfterPay, item) } - payments::PayLaterData::KlarnaSdk { .. } - | payments::PayLaterData::AffirmRedirect {} - | payments::PayLaterData::PayBrightRedirect {} - | payments::PayLaterData::WalleyRedirect {} - | payments::PayLaterData::AlmaRedirect {} - | payments::PayLaterData::AtomeRedirect {} => { + domain::PayLaterData::KlarnaSdk { .. } + | domain::PayLaterData::AffirmRedirect {} + | domain::PayLaterData::PayBrightRedirect {} + | domain::PayLaterData::WalleyRedirect {} + | domain::PayLaterData::AlmaRedirect {} + | domain::PayLaterData::AtomeRedirect {} => { Err(errors::ConnectorError::NotImplemented( utils::get_unimplemented_payment_method_error_message("nuvei"), ) diff --git a/crates/router/src/connector/paypal/transformers.rs b/crates/router/src/connector/paypal/transformers.rs index c9cbae957359..6a3d396c8358 100644 --- a/crates/router/src/connector/paypal/transformers.rs +++ b/crates/router/src/connector/paypal/transformers.rs @@ -1,4 +1,4 @@ -use api_models::{enums, payments::BankRedirectData}; +use api_models::enums; use base64::Engine; use common_utils::errors::CustomResult; use error_stack::ResultExt; @@ -280,10 +280,10 @@ fn get_address_info( } fn get_payment_source( item: &types::PaymentsAuthorizeRouterData, - bank_redirection_data: &BankRedirectData, + bank_redirection_data: &domain::BankRedirectData, ) -> Result> { match bank_redirection_data { - BankRedirectData::Eps { + domain::BankRedirectData::Eps { billing_details, bank_name: _, country, @@ -308,7 +308,7 @@ fn get_payment_source( user_action: Some(UserAction::PayNow), }, })), - BankRedirectData::Giropay { + domain::BankRedirectData::Giropay { billing_details, country, .. @@ -333,7 +333,7 @@ fn get_payment_source( user_action: Some(UserAction::PayNow), }, })), - BankRedirectData::Ideal { + domain::BankRedirectData::Ideal { billing_details, bank_name: _, country, @@ -358,7 +358,7 @@ fn get_payment_source( user_action: Some(UserAction::PayNow), }, })), - BankRedirectData::Sofort { + domain::BankRedirectData::Sofort { country, preferred_language: _, billing_details, @@ -383,22 +383,24 @@ fn get_payment_source( user_action: Some(UserAction::PayNow), }, })), - BankRedirectData::BancontactCard { .. } - | BankRedirectData::Blik { .. } - | BankRedirectData::Przelewy24 { .. } => Err(errors::ConnectorError::NotImplemented( - utils::get_unimplemented_payment_method_error_message("Paypal"), - ) - .into()), - BankRedirectData::Bizum {} - | BankRedirectData::Interac { .. } - | BankRedirectData::OnlineBankingCzechRepublic { .. } - | BankRedirectData::OnlineBankingFinland { .. } - | BankRedirectData::OnlineBankingPoland { .. } - | BankRedirectData::OnlineBankingSlovakia { .. } - | BankRedirectData::OpenBankingUk { .. } - | BankRedirectData::Trustly { .. } - | BankRedirectData::OnlineBankingFpx { .. } - | BankRedirectData::OnlineBankingThailand { .. } => { + domain::BankRedirectData::BancontactCard { .. } + | domain::BankRedirectData::Blik { .. } + | domain::BankRedirectData::Przelewy24 { .. } => { + Err(errors::ConnectorError::NotImplemented( + utils::get_unimplemented_payment_method_error_message("Paypal"), + ) + .into()) + } + domain::BankRedirectData::Bizum {} + | domain::BankRedirectData::Interac { .. } + | domain::BankRedirectData::OnlineBankingCzechRepublic { .. } + | domain::BankRedirectData::OnlineBankingFinland { .. } + | domain::BankRedirectData::OnlineBankingPoland { .. } + | domain::BankRedirectData::OnlineBankingSlovakia { .. } + | domain::BankRedirectData::OpenBankingUk { .. } + | domain::BankRedirectData::Trustly { .. } + | domain::BankRedirectData::OnlineBankingFpx { .. } + | domain::BankRedirectData::OnlineBankingThailand { .. } => { Err(errors::ConnectorError::NotImplemented( utils::get_unimplemented_payment_method_error_message("Paypal"), ))? @@ -634,18 +636,18 @@ impl TryFrom<&domain::payments::CardRedirectData> for PaypalPaymentsRequest { } } -impl TryFrom<&api_models::payments::PayLaterData> for PaypalPaymentsRequest { +impl TryFrom<&domain::PayLaterData> for PaypalPaymentsRequest { type Error = error_stack::Report; - fn try_from(value: &api_models::payments::PayLaterData) -> Result { + fn try_from(value: &domain::PayLaterData) -> Result { match value { - api_models::payments::PayLaterData::KlarnaRedirect { .. } - | api_models::payments::PayLaterData::KlarnaSdk { .. } - | api_models::payments::PayLaterData::AffirmRedirect {} - | api_models::payments::PayLaterData::AfterpayClearpayRedirect { .. } - | api_models::payments::PayLaterData::PayBrightRedirect {} - | api_models::payments::PayLaterData::WalleyRedirect {} - | api_models::payments::PayLaterData::AlmaRedirect {} - | api_models::payments::PayLaterData::AtomeRedirect {} => { + domain::PayLaterData::KlarnaRedirect { .. } + | domain::PayLaterData::KlarnaSdk { .. } + | domain::PayLaterData::AffirmRedirect {} + | domain::PayLaterData::AfterpayClearpayRedirect { .. } + | domain::PayLaterData::PayBrightRedirect {} + | domain::PayLaterData::WalleyRedirect {} + | domain::PayLaterData::AlmaRedirect {} + | domain::PayLaterData::AtomeRedirect {} => { Err(errors::ConnectorError::NotImplemented( utils::get_unimplemented_payment_method_error_message("Paypal"), ) @@ -688,7 +690,8 @@ impl TryFrom<&api_models::payments::BankTransferData> for PaypalPaymentsRequest | api_models::payments::BankTransferData::DanamonVaBankTransfer { .. } | api_models::payments::BankTransferData::MandiriVaBankTransfer { .. } | api_models::payments::BankTransferData::Pix {} - | api_models::payments::BankTransferData::Pse {} => { + | api_models::payments::BankTransferData::Pse {} + | api_models::payments::BankTransferData::LocalBankTransfer { .. } => { Err(errors::ConnectorError::NotImplemented( utils::get_unimplemented_payment_method_error_message("Paypal"), ) diff --git a/crates/router/src/connector/shift4/transformers.rs b/crates/router/src/connector/shift4/transformers.rs index 924081da4a90..1137fa58e86f 100644 --- a/crates/router/src/connector/shift4/transformers.rs +++ b/crates/router/src/connector/shift4/transformers.rs @@ -232,10 +232,13 @@ impl TryFrom<&api_models::payments::BankTransferData> for Shift4PaymentMethod { | payments::BankTransferData::DanamonVaBankTransfer { .. } | payments::BankTransferData::MandiriVaBankTransfer { .. } | payments::BankTransferData::Pix {} - | payments::BankTransferData::Pse {} => Err(errors::ConnectorError::NotImplemented( - utils::get_unimplemented_payment_method_error_message("Shift4"), - ) - .into()), + | payments::BankTransferData::Pse {} + | payments::BankTransferData::LocalBankTransfer { .. } => { + Err(errors::ConnectorError::NotImplemented( + utils::get_unimplemented_payment_method_error_message("Shift4"), + ) + .into()) + } } } } @@ -324,14 +327,14 @@ impl impl TryFrom<( &types::RouterData, - &payments::BankRedirectData, + &domain::BankRedirectData, )> for Shift4PaymentMethod { type Error = Error; fn try_from( (item, redirect_data): ( &types::RouterData, - &payments::BankRedirectData, + &domain::BankRedirectData, ), ) -> Result { let flow = Flow::try_from(&item.request.router_return_url)?; @@ -392,27 +395,27 @@ impl TryFrom<&types::RouterData for PaymentMethodType { +impl TryFrom<&domain::BankRedirectData> for PaymentMethodType { type Error = Error; - fn try_from(value: &payments::BankRedirectData) -> Result { + fn try_from(value: &domain::BankRedirectData) -> Result { match value { - payments::BankRedirectData::Eps { .. } => Ok(Self::Eps), - payments::BankRedirectData::Giropay { .. } => Ok(Self::Giropay), - payments::BankRedirectData::Ideal { .. } => Ok(Self::Ideal), - payments::BankRedirectData::Sofort { .. } => Ok(Self::Sofort), - payments::BankRedirectData::BancontactCard { .. } - | payments::BankRedirectData::Blik { .. } - | payments::BankRedirectData::Trustly { .. } - | payments::BankRedirectData::Przelewy24 { .. } - | payments::BankRedirectData::Bizum {} - | payments::BankRedirectData::Interac { .. } - | payments::BankRedirectData::OnlineBankingCzechRepublic { .. } - | payments::BankRedirectData::OnlineBankingFinland { .. } - | payments::BankRedirectData::OnlineBankingPoland { .. } - | payments::BankRedirectData::OnlineBankingSlovakia { .. } - | payments::BankRedirectData::OpenBankingUk { .. } - | payments::BankRedirectData::OnlineBankingFpx { .. } - | payments::BankRedirectData::OnlineBankingThailand { .. } => { + domain::BankRedirectData::Eps { .. } => Ok(Self::Eps), + domain::BankRedirectData::Giropay { .. } => Ok(Self::Giropay), + domain::BankRedirectData::Ideal { .. } => Ok(Self::Ideal), + domain::BankRedirectData::Sofort { .. } => Ok(Self::Sofort), + domain::BankRedirectData::BancontactCard { .. } + | domain::BankRedirectData::Blik { .. } + | domain::BankRedirectData::Trustly { .. } + | domain::BankRedirectData::Przelewy24 { .. } + | domain::BankRedirectData::Bizum {} + | domain::BankRedirectData::Interac { .. } + | domain::BankRedirectData::OnlineBankingCzechRepublic { .. } + | domain::BankRedirectData::OnlineBankingFinland { .. } + | domain::BankRedirectData::OnlineBankingPoland { .. } + | domain::BankRedirectData::OnlineBankingSlovakia { .. } + | domain::BankRedirectData::OpenBankingUk { .. } + | domain::BankRedirectData::OnlineBankingFpx { .. } + | domain::BankRedirectData::OnlineBankingThailand { .. } => { Err(errors::ConnectorError::NotImplemented( utils::get_unimplemented_payment_method_error_message("Shift4"), ) diff --git a/crates/router/src/connector/square/transformers.rs b/crates/router/src/connector/square/transformers.rs index abb2f69a42b3..ce7c0c2796e8 100644 --- a/crates/router/src/connector/square/transformers.rs +++ b/crates/router/src/connector/square/transformers.rs @@ -1,4 +1,4 @@ -use api_models::payments::{BankDebitData, PayLaterData}; +use api_models::payments::BankDebitData; use error_stack::ResultExt; use masking::{ExposeInterface, PeekInterface, Secret}; use serde::{Deserialize, Serialize}; @@ -71,23 +71,25 @@ impl TryFrom<(&types::TokenizationRouterData, domain::Card)> for SquareTokenRequ } } -impl TryFrom<(&types::TokenizationRouterData, PayLaterData)> for SquareTokenRequest { +impl TryFrom<(&types::TokenizationRouterData, domain::PayLaterData)> for SquareTokenRequest { type Error = error_stack::Report; fn try_from( - value: (&types::TokenizationRouterData, PayLaterData), + value: (&types::TokenizationRouterData, domain::PayLaterData), ) -> Result { let (_item, pay_later_data) = value; match pay_later_data { - PayLaterData::AfterpayClearpayRedirect { .. } - | PayLaterData::KlarnaRedirect { .. } - | PayLaterData::KlarnaSdk { .. } - | PayLaterData::AffirmRedirect { .. } - | PayLaterData::PayBrightRedirect { .. } - | PayLaterData::WalleyRedirect { .. } - | PayLaterData::AlmaRedirect { .. } - | PayLaterData::AtomeRedirect { .. } => Err(errors::ConnectorError::NotImplemented( - utils::get_unimplemented_payment_method_error_message("Square"), - ))?, + domain::PayLaterData::AfterpayClearpayRedirect { .. } + | domain::PayLaterData::KlarnaRedirect { .. } + | domain::PayLaterData::KlarnaSdk { .. } + | domain::PayLaterData::AffirmRedirect { .. } + | domain::PayLaterData::PayBrightRedirect { .. } + | domain::PayLaterData::WalleyRedirect { .. } + | domain::PayLaterData::AlmaRedirect { .. } + | domain::PayLaterData::AtomeRedirect { .. } => { + Err(errors::ConnectorError::NotImplemented( + utils::get_unimplemented_payment_method_error_message("Square"), + ))? + } } } } diff --git a/crates/router/src/connector/stripe/transformers.rs b/crates/router/src/connector/stripe/transformers.rs index 45aeb1e90742..7c5ef36127cd 100644 --- a/crates/router/src/connector/stripe/transformers.rs +++ b/crates/router/src/connector/stripe/transformers.rs @@ -136,6 +136,7 @@ pub struct PaymentIntentRequest { #[serde(flatten)] pub payment_data: Option, pub capture_method: StripeCaptureMethod, + #[serde(flatten)] pub payment_method_options: Option, // For mandate txns using network_txns_id, needs to be validated pub setup_future_usage: Option, pub off_session: Option, @@ -189,9 +190,9 @@ pub struct StripeCardData { #[serde(rename = "payment_method_data[card][exp_year]")] pub payment_method_data_card_exp_year: Secret, #[serde(rename = "payment_method_data[card][cvc]")] - pub payment_method_data_card_cvc: Secret, + pub payment_method_data_card_cvc: Option>, #[serde(rename = "payment_method_options[card][request_three_d_secure]")] - pub payment_method_auth_type: Auth3ds, + pub payment_method_auth_type: Option, } #[derive(Debug, Eq, PartialEq, Serialize)] pub struct StripePayLaterData { @@ -637,10 +638,11 @@ impl TryFrom for StripePaymentMethodType { enums::PaymentMethodType::Blik => Ok(Self::Blik), enums::PaymentMethodType::AliPay => Ok(Self::Alipay), enums::PaymentMethodType::Przelewy24 => Ok(Self::Przelewy24), + // Stripe expects PMT as Card for Recurring Mandates Payments + enums::PaymentMethodType::GooglePay => Ok(Self::Card), enums::PaymentMethodType::Boleto | enums::PaymentMethodType::CardRedirect | enums::PaymentMethodType::CryptoCurrency - | enums::PaymentMethodType::GooglePay | enums::PaymentMethodType::Multibanco | enums::PaymentMethodType::OnlineBankingFpx | enums::PaymentMethodType::Paypal @@ -703,6 +705,7 @@ impl TryFrom for StripePaymentMethodType { | enums::PaymentMethodType::FamilyMart | enums::PaymentMethodType::Seicomart | enums::PaymentMethodType::PayEasy + | enums::PaymentMethodType::LocalBankTransfer | enums::PaymentMethodType::Walley => Err(errors::ConnectorError::NotImplemented( connector_util::get_unimplemented_payment_method_error_message("stripe"), ) @@ -812,84 +815,84 @@ impl From for api_models::webhooks::IncomingWebhookEvent { } } -impl TryFrom<&api_models::enums::BankNames> for StripeBankNames { +impl TryFrom<&common_enums::enums::BankNames> for StripeBankNames { type Error = errors::ConnectorError; - fn try_from(bank: &api_models::enums::BankNames) -> Result { + fn try_from(bank: &common_enums::enums::BankNames) -> Result { Ok(match bank { - api_models::enums::BankNames::AbnAmro => Self::AbnAmro, - api_models::enums::BankNames::ArzteUndApothekerBank => Self::ArzteUndApothekerBank, - api_models::enums::BankNames::AsnBank => Self::AsnBank, - api_models::enums::BankNames::AustrianAnadiBankAg => Self::AustrianAnadiBankAg, - api_models::enums::BankNames::BankAustria => Self::BankAustria, - api_models::enums::BankNames::BankhausCarlSpangler => Self::BankhausCarlSpangler, - api_models::enums::BankNames::BankhausSchelhammerUndSchatteraAg => { + common_enums::enums::BankNames::AbnAmro => Self::AbnAmro, + common_enums::enums::BankNames::ArzteUndApothekerBank => Self::ArzteUndApothekerBank, + common_enums::enums::BankNames::AsnBank => Self::AsnBank, + common_enums::enums::BankNames::AustrianAnadiBankAg => Self::AustrianAnadiBankAg, + common_enums::enums::BankNames::BankAustria => Self::BankAustria, + common_enums::enums::BankNames::BankhausCarlSpangler => Self::BankhausCarlSpangler, + common_enums::enums::BankNames::BankhausSchelhammerUndSchatteraAg => { Self::BankhausSchelhammerUndSchatteraAg } - api_models::enums::BankNames::BawagPskAg => Self::BawagPskAg, - api_models::enums::BankNames::BksBankAg => Self::BksBankAg, - api_models::enums::BankNames::BrullKallmusBankAg => Self::BrullKallmusBankAg, - api_models::enums::BankNames::BtvVierLanderBank => Self::BtvVierLanderBank, - api_models::enums::BankNames::Bunq => Self::Bunq, - api_models::enums::BankNames::CapitalBankGraweGruppeAg => { + common_enums::enums::BankNames::BawagPskAg => Self::BawagPskAg, + common_enums::enums::BankNames::BksBankAg => Self::BksBankAg, + common_enums::enums::BankNames::BrullKallmusBankAg => Self::BrullKallmusBankAg, + common_enums::enums::BankNames::BtvVierLanderBank => Self::BtvVierLanderBank, + common_enums::enums::BankNames::Bunq => Self::Bunq, + common_enums::enums::BankNames::CapitalBankGraweGruppeAg => { Self::CapitalBankGraweGruppeAg } - api_models::enums::BankNames::Citi => Self::CitiHandlowy, - api_models::enums::BankNames::Dolomitenbank => Self::Dolomitenbank, - api_models::enums::BankNames::EasybankAg => Self::EasybankAg, - api_models::enums::BankNames::ErsteBankUndSparkassen => Self::ErsteBankUndSparkassen, - api_models::enums::BankNames::Handelsbanken => Self::Handelsbanken, - api_models::enums::BankNames::HypoAlpeadriabankInternationalAg => { + common_enums::enums::BankNames::Citi => Self::CitiHandlowy, + common_enums::enums::BankNames::Dolomitenbank => Self::Dolomitenbank, + common_enums::enums::BankNames::EasybankAg => Self::EasybankAg, + common_enums::enums::BankNames::ErsteBankUndSparkassen => Self::ErsteBankUndSparkassen, + common_enums::enums::BankNames::Handelsbanken => Self::Handelsbanken, + common_enums::enums::BankNames::HypoAlpeadriabankInternationalAg => { Self::HypoAlpeadriabankInternationalAg } - api_models::enums::BankNames::HypoNoeLbFurNiederosterreichUWien => { + common_enums::enums::BankNames::HypoNoeLbFurNiederosterreichUWien => { Self::HypoNoeLbFurNiederosterreichUWien } - api_models::enums::BankNames::HypoOberosterreichSalzburgSteiermark => { + common_enums::enums::BankNames::HypoOberosterreichSalzburgSteiermark => { Self::HypoOberosterreichSalzburgSteiermark } - api_models::enums::BankNames::HypoTirolBankAg => Self::HypoTirolBankAg, - api_models::enums::BankNames::HypoVorarlbergBankAg => Self::HypoVorarlbergBankAg, - api_models::enums::BankNames::HypoBankBurgenlandAktiengesellschaft => { + common_enums::enums::BankNames::HypoTirolBankAg => Self::HypoTirolBankAg, + common_enums::enums::BankNames::HypoVorarlbergBankAg => Self::HypoVorarlbergBankAg, + common_enums::enums::BankNames::HypoBankBurgenlandAktiengesellschaft => { Self::HypoBankBurgenlandAktiengesellschaft } - api_models::enums::BankNames::Ing => Self::Ing, - api_models::enums::BankNames::Knab => Self::Knab, - api_models::enums::BankNames::MarchfelderBank => Self::MarchfelderBank, - api_models::enums::BankNames::OberbankAg => Self::OberbankAg, - api_models::enums::BankNames::RaiffeisenBankengruppeOsterreich => { + common_enums::enums::BankNames::Ing => Self::Ing, + common_enums::enums::BankNames::Knab => Self::Knab, + common_enums::enums::BankNames::MarchfelderBank => Self::MarchfelderBank, + common_enums::enums::BankNames::OberbankAg => Self::OberbankAg, + common_enums::enums::BankNames::RaiffeisenBankengruppeOsterreich => { Self::RaiffeisenBankengruppeOsterreich } - api_models::enums::BankNames::Rabobank => Self::Rabobank, - api_models::enums::BankNames::Regiobank => Self::Regiobank, - api_models::enums::BankNames::Revolut => Self::Revolut, - api_models::enums::BankNames::SnsBank => Self::SnsBank, - api_models::enums::BankNames::TriodosBank => Self::TriodosBank, - api_models::enums::BankNames::VanLanschot => Self::VanLanschot, - api_models::enums::BankNames::Moneyou => Self::Moneyou, - api_models::enums::BankNames::SchoellerbankAg => Self::SchoellerbankAg, - api_models::enums::BankNames::SpardaBankWien => Self::SpardaBankWien, - api_models::enums::BankNames::VolksbankGruppe => Self::VolksbankGruppe, - api_models::enums::BankNames::VolkskreditbankAg => Self::VolkskreditbankAg, - api_models::enums::BankNames::VrBankBraunau => Self::VrBankBraunau, - api_models::enums::BankNames::PlusBank => Self::PlusBank, - api_models::enums::BankNames::EtransferPocztowy24 => Self::EtransferPocztowy24, - api_models::enums::BankNames::BankiSpbdzielcze => Self::BankiSpbdzielcze, - api_models::enums::BankNames::BankNowyBfgSa => Self::BankNowyBfgSa, - api_models::enums::BankNames::GetinBank => Self::GetinBank, - api_models::enums::BankNames::Blik => Self::Blik, - api_models::enums::BankNames::NoblePay => Self::NoblePay, - api_models::enums::BankNames::IdeaBank => Self::IdeaBank, - api_models::enums::BankNames::EnveloBank => Self::EnveloBank, - api_models::enums::BankNames::NestPrzelew => Self::NestPrzelew, - api_models::enums::BankNames::MbankMtransfer => Self::MbankMtransfer, - api_models::enums::BankNames::Inteligo => Self::Inteligo, - api_models::enums::BankNames::PbacZIpko => Self::PbacZIpko, - api_models::enums::BankNames::BnpParibas => Self::BnpParibas, - api_models::enums::BankNames::BankPekaoSa => Self::BankPekaoSa, - api_models::enums::BankNames::VolkswagenBank => Self::VolkswagenBank, - api_models::enums::BankNames::AliorBank => Self::AliorBank, - api_models::enums::BankNames::Boz => Self::Boz, + common_enums::enums::BankNames::Rabobank => Self::Rabobank, + common_enums::enums::BankNames::Regiobank => Self::Regiobank, + common_enums::enums::BankNames::Revolut => Self::Revolut, + common_enums::enums::BankNames::SnsBank => Self::SnsBank, + common_enums::enums::BankNames::TriodosBank => Self::TriodosBank, + common_enums::enums::BankNames::VanLanschot => Self::VanLanschot, + common_enums::enums::BankNames::Moneyou => Self::Moneyou, + common_enums::enums::BankNames::SchoellerbankAg => Self::SchoellerbankAg, + common_enums::enums::BankNames::SpardaBankWien => Self::SpardaBankWien, + common_enums::enums::BankNames::VolksbankGruppe => Self::VolksbankGruppe, + common_enums::enums::BankNames::VolkskreditbankAg => Self::VolkskreditbankAg, + common_enums::enums::BankNames::VrBankBraunau => Self::VrBankBraunau, + common_enums::enums::BankNames::PlusBank => Self::PlusBank, + common_enums::enums::BankNames::EtransferPocztowy24 => Self::EtransferPocztowy24, + common_enums::enums::BankNames::BankiSpbdzielcze => Self::BankiSpbdzielcze, + common_enums::enums::BankNames::BankNowyBfgSa => Self::BankNowyBfgSa, + common_enums::enums::BankNames::GetinBank => Self::GetinBank, + common_enums::enums::BankNames::Blik => Self::Blik, + common_enums::enums::BankNames::NoblePay => Self::NoblePay, + common_enums::enums::BankNames::IdeaBank => Self::IdeaBank, + common_enums::enums::BankNames::EnveloBank => Self::EnveloBank, + common_enums::enums::BankNames::NestPrzelew => Self::NestPrzelew, + common_enums::enums::BankNames::MbankMtransfer => Self::MbankMtransfer, + common_enums::enums::BankNames::Inteligo => Self::Inteligo, + common_enums::enums::BankNames::PbacZIpko => Self::PbacZIpko, + common_enums::enums::BankNames::BnpParibas => Self::BnpParibas, + common_enums::enums::BankNames::BankPekaoSa => Self::BankPekaoSa, + common_enums::enums::BankNames::VolkswagenBank => Self::VolkswagenBank, + common_enums::enums::BankNames::AliorBank => Self::AliorBank, + common_enums::enums::BankNames::Boz => Self::Boz, _ => Err(errors::ConnectorError::NotImplemented( connector_util::get_unimplemented_payment_method_error_message("stripe"), @@ -928,21 +931,21 @@ fn validate_shipping_address_against_payment_method( } } -impl TryFrom<&api_models::payments::PayLaterData> for StripePaymentMethodType { +impl TryFrom<&domain::payments::PayLaterData> for StripePaymentMethodType { type Error = errors::ConnectorError; - fn try_from(pay_later_data: &api_models::payments::PayLaterData) -> Result { + fn try_from(pay_later_data: &domain::payments::PayLaterData) -> Result { match pay_later_data { - api_models::payments::PayLaterData::KlarnaRedirect { .. } => Ok(Self::Klarna), - api_models::payments::PayLaterData::AffirmRedirect {} => Ok(Self::Affirm), - api_models::payments::PayLaterData::AfterpayClearpayRedirect { .. } => { + domain::payments::PayLaterData::KlarnaRedirect { .. } => Ok(Self::Klarna), + domain::payments::PayLaterData::AffirmRedirect {} => Ok(Self::Affirm), + domain::payments::PayLaterData::AfterpayClearpayRedirect { .. } => { Ok(Self::AfterpayClearpay) } - payments::PayLaterData::KlarnaSdk { .. } - | payments::PayLaterData::PayBrightRedirect {} - | payments::PayLaterData::WalleyRedirect {} - | payments::PayLaterData::AlmaRedirect {} - | payments::PayLaterData::AtomeRedirect {} => { + domain::PayLaterData::KlarnaSdk { .. } + | domain::PayLaterData::PayBrightRedirect {} + | domain::PayLaterData::WalleyRedirect {} + | domain::PayLaterData::AlmaRedirect {} + | domain::PayLaterData::AtomeRedirect {} => { Err(errors::ConnectorError::NotImplemented( connector_util::get_unimplemented_payment_method_error_message("stripe"), )) @@ -951,31 +954,31 @@ impl TryFrom<&api_models::payments::PayLaterData> for StripePaymentMethodType { } } -impl TryFrom<&payments::BankRedirectData> for StripePaymentMethodType { +impl TryFrom<&domain::BankRedirectData> for StripePaymentMethodType { type Error = errors::ConnectorError; - fn try_from(bank_redirect_data: &payments::BankRedirectData) -> Result { + fn try_from(bank_redirect_data: &domain::BankRedirectData) -> Result { match bank_redirect_data { - payments::BankRedirectData::Giropay { .. } => Ok(Self::Giropay), - payments::BankRedirectData::Ideal { .. } => Ok(Self::Ideal), - payments::BankRedirectData::Sofort { .. } => Ok(Self::Sofort), - payments::BankRedirectData::BancontactCard { .. } => Ok(Self::Bancontact), - payments::BankRedirectData::Przelewy24 { .. } => Ok(Self::Przelewy24), - payments::BankRedirectData::Eps { .. } => Ok(Self::Eps), - payments::BankRedirectData::Blik { .. } => Ok(Self::Blik), - payments::BankRedirectData::OnlineBankingFpx { .. } => { + domain::BankRedirectData::Giropay { .. } => Ok(Self::Giropay), + domain::BankRedirectData::Ideal { .. } => Ok(Self::Ideal), + domain::BankRedirectData::Sofort { .. } => Ok(Self::Sofort), + domain::BankRedirectData::BancontactCard { .. } => Ok(Self::Bancontact), + domain::BankRedirectData::Przelewy24 { .. } => Ok(Self::Przelewy24), + domain::BankRedirectData::Eps { .. } => Ok(Self::Eps), + domain::BankRedirectData::Blik { .. } => Ok(Self::Blik), + domain::BankRedirectData::OnlineBankingFpx { .. } => { Err(errors::ConnectorError::NotImplemented( connector_util::get_unimplemented_payment_method_error_message("stripe"), )) } - payments::BankRedirectData::Bizum {} - | payments::BankRedirectData::Interac { .. } - | payments::BankRedirectData::OnlineBankingCzechRepublic { .. } - | payments::BankRedirectData::OnlineBankingFinland { .. } - | payments::BankRedirectData::OnlineBankingPoland { .. } - | payments::BankRedirectData::OnlineBankingSlovakia { .. } - | payments::BankRedirectData::OnlineBankingThailand { .. } - | payments::BankRedirectData::OpenBankingUk { .. } - | payments::BankRedirectData::Trustly { .. } => { + domain::BankRedirectData::Bizum {} + | domain::BankRedirectData::Interac { .. } + | domain::BankRedirectData::OnlineBankingCzechRepublic { .. } + | domain::BankRedirectData::OnlineBankingFinland { .. } + | domain::BankRedirectData::OnlineBankingPoland { .. } + | domain::BankRedirectData::OnlineBankingSlovakia { .. } + | domain::BankRedirectData::OnlineBankingThailand { .. } + | domain::BankRedirectData::OpenBankingUk { .. } + | domain::BankRedirectData::Trustly { .. } => { Err(errors::ConnectorError::NotImplemented( connector_util::get_unimplemented_payment_method_error_message("stripe"), )) @@ -1037,17 +1040,15 @@ impl From<&payments::BankDebitData> for StripePaymentMethodType { } } -impl TryFrom<(&api_models::payments::PayLaterData, StripePaymentMethodType)> - for StripeBillingAddress -{ +impl TryFrom<(&domain::payments::PayLaterData, StripePaymentMethodType)> for StripeBillingAddress { type Error = errors::ConnectorError; fn try_from( - (pay_later_data, pm_type): (&api_models::payments::PayLaterData, StripePaymentMethodType), + (pay_later_data, pm_type): (&domain::payments::PayLaterData, StripePaymentMethodType), ) -> Result { match (pay_later_data, pm_type) { ( - payments::PayLaterData::KlarnaRedirect { + domain::payments::PayLaterData::KlarnaRedirect { billing_email, billing_country, }, @@ -1057,11 +1058,12 @@ impl TryFrom<(&api_models::payments::PayLaterData, StripePaymentMethodType)> country: Some(billing_country.to_owned()), ..Self::default() }), - (payments::PayLaterData::AffirmRedirect {}, StripePaymentMethodType::Affirm) => { - Ok(Self::default()) - } ( - payments::PayLaterData::AfterpayClearpayRedirect { + domain::payments::PayLaterData::AffirmRedirect {}, + StripePaymentMethodType::Affirm, + ) => Ok(Self::default()), + ( + domain::payments::PayLaterData::AfterpayClearpayRedirect { billing_email, billing_name, }, @@ -1107,17 +1109,17 @@ impl From<&payments::BankDebitBilling> for StripeBillingAddress { } } -impl TryFrom<(&payments::BankRedirectData, Option)> for StripeBillingAddress { +impl TryFrom<(&domain::BankRedirectData, Option)> for StripeBillingAddress { type Error = error_stack::Report; fn try_from( (bank_redirection_data, is_customer_initiated_mandate_payment): ( - &payments::BankRedirectData, + &domain::BankRedirectData, Option, ), ) -> Result { match bank_redirection_data { - payments::BankRedirectData::Eps { + domain::BankRedirectData::Eps { billing_details, .. } => Ok({ let billing_data = billing_details.clone().ok_or( @@ -1132,7 +1134,7 @@ impl TryFrom<(&payments::BankRedirectData, Option)> for StripeBillingAddre ..Self::default() } }), - payments::BankRedirectData::Giropay { + domain::BankRedirectData::Giropay { billing_details, .. } => Ok(Self { name: Some( @@ -1145,19 +1147,19 @@ impl TryFrom<(&payments::BankRedirectData, Option)> for StripeBillingAddre ), ..Self::default() }), - payments::BankRedirectData::Ideal { + domain::BankRedirectData::Ideal { billing_details, .. } => Ok(get_stripe_sepa_dd_mandate_billing_details( billing_details, is_customer_initiated_mandate_payment, )?), - payments::BankRedirectData::Przelewy24 { + domain::BankRedirectData::Przelewy24 { billing_details, .. } => Ok(Self { email: billing_details.email.clone(), ..Self::default() }), - payments::BankRedirectData::BancontactCard { + domain::BankRedirectData::BancontactCard { billing_details, .. } => { let billing_details = billing_details.as_ref().ok_or( @@ -1187,24 +1189,24 @@ impl TryFrom<(&payments::BankRedirectData, Option)> for StripeBillingAddre ..Self::default() }) } - payments::BankRedirectData::Sofort { + domain::BankRedirectData::Sofort { billing_details, .. } => Ok(get_stripe_sepa_dd_mandate_billing_details( billing_details, is_customer_initiated_mandate_payment, )?), - payments::BankRedirectData::Bizum {} - | payments::BankRedirectData::Blik { .. } - | payments::BankRedirectData::Interac { .. } - | payments::BankRedirectData::OnlineBankingCzechRepublic { .. } - | payments::BankRedirectData::OnlineBankingFinland { .. } - | payments::BankRedirectData::OnlineBankingPoland { .. } - | payments::BankRedirectData::OnlineBankingSlovakia { .. } - | payments::BankRedirectData::Trustly { .. } - | payments::BankRedirectData::OnlineBankingFpx { .. } - | payments::BankRedirectData::OnlineBankingThailand { .. } - | payments::BankRedirectData::OpenBankingUk { .. } => Ok(Self::default()), + domain::BankRedirectData::Bizum {} + | domain::BankRedirectData::Blik { .. } + | domain::BankRedirectData::Interac { .. } + | domain::BankRedirectData::OnlineBankingCzechRepublic { .. } + | domain::BankRedirectData::OnlineBankingFinland { .. } + | domain::BankRedirectData::OnlineBankingPoland { .. } + | domain::BankRedirectData::OnlineBankingSlovakia { .. } + | domain::BankRedirectData::Trustly { .. } + | domain::BankRedirectData::OnlineBankingFpx { .. } + | domain::BankRedirectData::OnlineBankingThailand { .. } + | domain::BankRedirectData::OpenBankingUk { .. } => Ok(Self::default()), } } } @@ -1412,6 +1414,7 @@ fn create_stripe_payment_method( ) .into()), payments::BankTransferData::Pse {} + | payments::BankTransferData::LocalBankTransfer { .. } | payments::BankTransferData::PermataBankTransfer { .. } | payments::BankTransferData::BcaBankTransfer { .. } | payments::BankTransferData::BniVaBankTransfer { .. } @@ -1498,8 +1501,8 @@ impl TryFrom<(&domain::Card, Auth3ds)> for StripePaymentMethodData { payment_method_data_card_number: card.card_number.clone(), payment_method_data_card_exp_month: card.card_exp_month.clone(), payment_method_data_card_exp_year: card.card_exp_year.clone(), - payment_method_data_card_cvc: card.card_cvc.clone(), - payment_method_auth_type, + payment_method_data_card_cvc: Some(card.card_cvc.clone()), + payment_method_auth_type: Some(payment_method_auth_type), })) } } @@ -1607,17 +1610,17 @@ impl TryFrom<(&domain::WalletData, Option)> for Strip } } -impl TryFrom<&payments::BankRedirectData> for StripePaymentMethodData { +impl TryFrom<&domain::BankRedirectData> for StripePaymentMethodData { type Error = error_stack::Report; - fn try_from(bank_redirect_data: &payments::BankRedirectData) -> Result { + fn try_from(bank_redirect_data: &domain::BankRedirectData) -> Result { let payment_method_data_type = StripePaymentMethodType::try_from(bank_redirect_data)?; match bank_redirect_data { - payments::BankRedirectData::BancontactCard { .. } => Ok(Self::BankRedirect( + domain::BankRedirectData::BancontactCard { .. } => Ok(Self::BankRedirect( StripeBankRedirectData::StripeBancontactCard(Box::new(StripeBancontactCard { payment_method_data_type, })), )), - payments::BankRedirectData::Blik { blik_code } => Ok(Self::BankRedirect( + domain::BankRedirectData::Blik { blik_code } => Ok(Self::BankRedirect( StripeBankRedirectData::StripeBlik(Box::new(StripeBlik { payment_method_data_type, code: Secret::new(blik_code.clone().ok_or( @@ -1627,7 +1630,7 @@ impl TryFrom<&payments::BankRedirectData> for StripePaymentMethodData { )?), })), )), - payments::BankRedirectData::Eps { bank_name, .. } => Ok(Self::BankRedirect( + domain::BankRedirectData::Eps { bank_name, .. } => Ok(Self::BankRedirect( StripeBankRedirectData::StripeEps(Box::new(StripeEps { payment_method_data_type, bank_name: bank_name @@ -1635,12 +1638,12 @@ impl TryFrom<&payments::BankRedirectData> for StripePaymentMethodData { .transpose()?, })), )), - payments::BankRedirectData::Giropay { .. } => Ok(Self::BankRedirect( + domain::BankRedirectData::Giropay { .. } => Ok(Self::BankRedirect( StripeBankRedirectData::StripeGiropay(Box::new(StripeGiropay { payment_method_data_type, })), )), - payments::BankRedirectData::Ideal { bank_name, .. } => { + domain::BankRedirectData::Ideal { bank_name, .. } => { let bank_name = bank_name .map(|bank_name| StripeBankNames::try_from(&bank_name)) .transpose()?; @@ -1651,7 +1654,7 @@ impl TryFrom<&payments::BankRedirectData> for StripePaymentMethodData { }), ))) } - payments::BankRedirectData::Przelewy24 { bank_name, .. } => { + domain::BankRedirectData::Przelewy24 { bank_name, .. } => { let bank_name = bank_name .map(|bank_name| StripeBankNames::try_from(&bank_name)) .transpose()?; @@ -1662,7 +1665,7 @@ impl TryFrom<&payments::BankRedirectData> for StripePaymentMethodData { })), )) } - payments::BankRedirectData::Sofort { + domain::BankRedirectData::Sofort { country, preferred_language, .. @@ -1675,21 +1678,21 @@ impl TryFrom<&payments::BankRedirectData> for StripePaymentMethodData { preferred_language: preferred_language.clone(), }), ))), - payments::BankRedirectData::OnlineBankingFpx { .. } => { + domain::BankRedirectData::OnlineBankingFpx { .. } => { Err(errors::ConnectorError::NotImplemented( connector_util::get_unimplemented_payment_method_error_message("stripe"), ) .into()) } - payments::BankRedirectData::Bizum {} - | payments::BankRedirectData::Interac { .. } - | payments::BankRedirectData::OnlineBankingCzechRepublic { .. } - | payments::BankRedirectData::OnlineBankingFinland { .. } - | payments::BankRedirectData::OnlineBankingPoland { .. } - | payments::BankRedirectData::OnlineBankingSlovakia { .. } - | payments::BankRedirectData::OnlineBankingThailand { .. } - | payments::BankRedirectData::OpenBankingUk { .. } - | payments::BankRedirectData::Trustly { .. } => { + domain::BankRedirectData::Bizum {} + | domain::BankRedirectData::Interac { .. } + | domain::BankRedirectData::OnlineBankingCzechRepublic { .. } + | domain::BankRedirectData::OnlineBankingFinland { .. } + | domain::BankRedirectData::OnlineBankingPoland { .. } + | domain::BankRedirectData::OnlineBankingSlovakia { .. } + | domain::BankRedirectData::OnlineBankingThailand { .. } + | domain::BankRedirectData::OpenBankingUk { .. } + | domain::BankRedirectData::Trustly { .. } => { Err(errors::ConnectorError::NotImplemented( connector_util::get_unimplemented_payment_method_error_message("stripe"), ) @@ -1821,7 +1824,44 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for PaymentIntentRequest { network_transaction_id: Secret::new(network_transaction_id), }), }); - (None, None, StripeBillingAddress::default(), None) + + let payment_data = match item.request.payment_method_data { + domain::payments::PaymentMethodData::Card(ref card) => { + StripePaymentMethodData::Card(StripeCardData { + payment_method_data_type: StripePaymentMethodType::Card, + payment_method_data_card_number: card.card_number.clone(), + payment_method_data_card_exp_month: card.card_exp_month.clone(), + payment_method_data_card_exp_year: card.card_exp_year.clone(), + payment_method_data_card_cvc: None, + payment_method_auth_type: None, + }) + } + domain::payments::PaymentMethodData::CardRedirect(_) + | domain::payments::PaymentMethodData::Wallet(_) + | domain::payments::PaymentMethodData::PayLater(_) + | domain::payments::PaymentMethodData::BankRedirect(_) + | domain::payments::PaymentMethodData::BankDebit(_) + | domain::payments::PaymentMethodData::BankTransfer(_) + | domain::payments::PaymentMethodData::Crypto(_) + | domain::payments::PaymentMethodData::MandatePayment + | domain::payments::PaymentMethodData::Reward + | domain::payments::PaymentMethodData::Upi(_) + | domain::payments::PaymentMethodData::Voucher(_) + | domain::payments::PaymentMethodData::GiftCard(_) + | domain::payments::PaymentMethodData::CardToken(_) => { + Err(errors::ConnectorError::NotSupported { + message: "Network tokenization for payment method".to_string(), + connector: "Stripe", + })? + } + }; + + ( + Some(payment_data), + None, + StripeBillingAddress::default(), + None, + ) } _ => { let (payment_method_data, payment_method_type, billing_address) = @@ -2625,12 +2665,23 @@ impl item.response.id.clone(), )) } else { + let network_transaction_id = match item.response.latest_charge.clone() { + Some(StripeChargeEnum::ChargeObject(charge_object)) => charge_object + .payment_method_details + .and_then(|payment_method_details| match payment_method_details { + StripePaymentMethodDetailsResponse::Card { card } => { + card.network_transaction_id + } + _ => None, + }), + _ => None, + }; Ok(types::PaymentsResponseData::TransactionResponse { resource_id: types::ResponseId::ConnectorTransactionId(item.response.id.clone()), redirection_data, mandate_reference, connector_metadata, - network_txn_id: None, + network_txn_id: network_transaction_id, connector_response_reference_id: Some(item.response.id.clone()), incremental_authorization_allowed: None, }) @@ -3105,10 +3156,13 @@ impl TryFrom<&types::PaymentsCancelRouterData> for CancelRequest { #[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)] #[non_exhaustive] #[serde(rename_all = "snake_case")] +#[serde(untagged)] pub enum StripePaymentMethodOptions { Card { mandate_options: Option, + #[serde(rename = "payment_method_options[card][network_transaction_id]")] network_transaction_id: Option>, + #[serde(flatten)] mit_exemption: Option, // To be used for MIT mandate txns }, Klarna {}, @@ -3139,6 +3193,7 @@ pub enum StripePaymentMethodOptions { #[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] pub struct MitExemption { + #[serde(rename = "payment_method_options[card][mit_exemption][network_transaction_id]")] pub network_transaction_id: Secret, } @@ -3213,6 +3268,7 @@ impl TryFrom<&types::PaymentsPreProcessingRouterData> for StripeCreditTransferSo | payments::BankTransferData::CimbVaBankTransfer { .. } | payments::BankTransferData::DanamonVaBankTransfer { .. } | payments::BankTransferData::MandiriVaBankTransfer { .. } + | payments::BankTransferData::LocalBankTransfer { .. } | payments::BankTransferData::Pix { .. } | payments::BankTransferData::Pse { .. } => { Err(errors::ConnectorError::NotImplemented( @@ -3670,6 +3726,7 @@ impl | payments::BankTransferData::BriVaBankTransfer { .. } | payments::BankTransferData::CimbVaBankTransfer { .. } | payments::BankTransferData::DanamonVaBankTransfer { .. } + | payments::BankTransferData::LocalBankTransfer { .. } | payments::BankTransferData::MandiriVaBankTransfer { .. } => { Err(errors::ConnectorError::NotImplemented( connector_util::get_unimplemented_payment_method_error_message("stripe"), @@ -3790,7 +3847,7 @@ pub struct Evidence { // Mandates for bank redirects - ideal and sofort happens through sepa direct debit in stripe fn get_stripe_sepa_dd_mandate_billing_details( - billing_details: &Option, + billing_details: &Option, is_customer_initiated_mandate_payment: Option, ) -> Result { let billing_name = billing_details diff --git a/crates/router/src/connector/trustpay/transformers.rs b/crates/router/src/connector/trustpay/transformers.rs index e7e9a759d57b..79396f12c69d 100644 --- a/crates/router/src/connector/trustpay/transformers.rs +++ b/crates/router/src/connector/trustpay/transformers.rs @@ -1,6 +1,5 @@ use std::collections::HashMap; -use api_models::payments::BankRedirectData; use common_utils::{ errors::CustomResult, pii::{self, Email}, @@ -229,27 +228,27 @@ pub struct TrustpayMandatoryParams { pub billing_first_name: Secret, } -impl TryFrom<&BankRedirectData> for TrustpayPaymentMethod { +impl TryFrom<&domain::BankRedirectData> for TrustpayPaymentMethod { type Error = Error; - fn try_from(value: &BankRedirectData) -> Result { + fn try_from(value: &domain::BankRedirectData) -> Result { match value { - api_models::payments::BankRedirectData::Giropay { .. } => Ok(Self::Giropay), - api_models::payments::BankRedirectData::Eps { .. } => Ok(Self::Eps), - api_models::payments::BankRedirectData::Ideal { .. } => Ok(Self::IDeal), - api_models::payments::BankRedirectData::Sofort { .. } => Ok(Self::Sofort), - api_models::payments::BankRedirectData::Blik { .. } => Ok(Self::Blik), - api_models::payments::BankRedirectData::BancontactCard { .. } - | api_models::payments::BankRedirectData::Bizum {} - | api_models::payments::BankRedirectData::Interac { .. } - | api_models::payments::BankRedirectData::OnlineBankingCzechRepublic { .. } - | api_models::payments::BankRedirectData::OnlineBankingFinland { .. } - | api_models::payments::BankRedirectData::OnlineBankingPoland { .. } - | api_models::payments::BankRedirectData::OnlineBankingSlovakia { .. } - | api_models::payments::BankRedirectData::OpenBankingUk { .. } - | api_models::payments::BankRedirectData::Przelewy24 { .. } - | api_models::payments::BankRedirectData::Trustly { .. } - | api_models::payments::BankRedirectData::OnlineBankingFpx { .. } - | api_models::payments::BankRedirectData::OnlineBankingThailand { .. } => { + domain::BankRedirectData::Giropay { .. } => Ok(Self::Giropay), + domain::BankRedirectData::Eps { .. } => Ok(Self::Eps), + domain::BankRedirectData::Ideal { .. } => Ok(Self::IDeal), + domain::BankRedirectData::Sofort { .. } => Ok(Self::Sofort), + domain::BankRedirectData::Blik { .. } => Ok(Self::Blik), + domain::BankRedirectData::BancontactCard { .. } + | domain::BankRedirectData::Bizum {} + | domain::BankRedirectData::Interac { .. } + | domain::BankRedirectData::OnlineBankingCzechRepublic { .. } + | domain::BankRedirectData::OnlineBankingFinland { .. } + | domain::BankRedirectData::OnlineBankingPoland { .. } + | domain::BankRedirectData::OnlineBankingSlovakia { .. } + | domain::BankRedirectData::OpenBankingUk { .. } + | domain::BankRedirectData::Przelewy24 { .. } + | domain::BankRedirectData::Trustly { .. } + | domain::BankRedirectData::OnlineBankingFpx { .. } + | domain::BankRedirectData::OnlineBankingThailand { .. } => { Err(errors::ConnectorError::NotImplemented( utils::get_unimplemented_payment_method_error_message("trustpay"), ) @@ -358,7 +357,7 @@ fn get_debtor_info( fn get_bank_redirection_request_data( item: &types::PaymentsAuthorizeRouterData, - bank_redirection_data: &BankRedirectData, + bank_redirection_data: &domain::BankRedirectData, params: TrustpayMandatoryParams, amount: String, auth: TrustpayAuthType, diff --git a/crates/router/src/connector/utils.rs b/crates/router/src/connector/utils.rs index 645d850ebe74..b0c0fe8e68fb 100644 --- a/crates/router/src/connector/utils.rs +++ b/crates/router/src/connector/utils.rs @@ -1235,7 +1235,7 @@ pub trait BankRedirectBillingData { fn get_billing_name(&self) -> Result, Error>; } -impl BankRedirectBillingData for payments::BankRedirectBilling { +impl BankRedirectBillingData for domain::BankRedirectBilling { fn get_billing_name(&self) -> Result, Error> { self.billing_name .clone() diff --git a/crates/router/src/connector/volt/transformers.rs b/crates/router/src/connector/volt/transformers.rs index 47c29767d82e..8c64398bd5fe 100644 --- a/crates/router/src/connector/volt/transformers.rs +++ b/crates/router/src/connector/volt/transformers.rs @@ -88,7 +88,7 @@ impl TryFrom<&VoltRouterData<&types::PaymentsAuthorizeRouterData>> for VoltPayme ) -> Result { match item.router_data.request.payment_method_data.clone() { domain::PaymentMethodData::BankRedirect(ref bank_redirect) => match bank_redirect { - api_models::payments::BankRedirectData::OpenBankingUk { .. } => { + domain::BankRedirectData::OpenBankingUk { .. } => { let amount = item.amount; let currency_code = item.router_data.request.currency; let merchant_internal_reference = @@ -118,22 +118,22 @@ impl TryFrom<&VoltRouterData<&types::PaymentsAuthorizeRouterData>> for VoltPayme transaction_type, }) } - api_models::payments::BankRedirectData::BancontactCard { .. } - | api_models::payments::BankRedirectData::Bizum {} - | api_models::payments::BankRedirectData::Blik { .. } - | api_models::payments::BankRedirectData::Eps { .. } - | api_models::payments::BankRedirectData::Giropay { .. } - | api_models::payments::BankRedirectData::Ideal { .. } - | api_models::payments::BankRedirectData::Interac { .. } - | api_models::payments::BankRedirectData::OnlineBankingCzechRepublic { .. } - | api_models::payments::BankRedirectData::OnlineBankingFinland { .. } - | api_models::payments::BankRedirectData::OnlineBankingPoland { .. } - | api_models::payments::BankRedirectData::OnlineBankingSlovakia { .. } - | api_models::payments::BankRedirectData::Przelewy24 { .. } - | api_models::payments::BankRedirectData::Sofort { .. } - | api_models::payments::BankRedirectData::Trustly { .. } - | api_models::payments::BankRedirectData::OnlineBankingFpx { .. } - | api_models::payments::BankRedirectData::OnlineBankingThailand { .. } => { + domain::BankRedirectData::BancontactCard { .. } + | domain::BankRedirectData::Bizum {} + | domain::BankRedirectData::Blik { .. } + | domain::BankRedirectData::Eps { .. } + | domain::BankRedirectData::Giropay { .. } + | domain::BankRedirectData::Ideal { .. } + | domain::BankRedirectData::Interac { .. } + | domain::BankRedirectData::OnlineBankingCzechRepublic { .. } + | domain::BankRedirectData::OnlineBankingFinland { .. } + | domain::BankRedirectData::OnlineBankingPoland { .. } + | domain::BankRedirectData::OnlineBankingSlovakia { .. } + | domain::BankRedirectData::Przelewy24 { .. } + | domain::BankRedirectData::Sofort { .. } + | domain::BankRedirectData::Trustly { .. } + | domain::BankRedirectData::OnlineBankingFpx { .. } + | domain::BankRedirectData::OnlineBankingThailand { .. } => { Err(errors::ConnectorError::NotImplemented( utils::get_unimplemented_payment_method_error_message("Volt"), ) diff --git a/crates/router/src/connector/worldline/transformers.rs b/crates/router/src/connector/worldline/transformers.rs index 9a8297dd3253..490c4994045c 100644 --- a/crates/router/src/connector/worldline/transformers.rs +++ b/crates/router/src/connector/worldline/transformers.rs @@ -317,20 +317,20 @@ impl TryFrom for Gateway { } } -impl TryFrom<&api_models::enums::BankNames> for WorldlineBic { +impl TryFrom<&common_enums::enums::BankNames> for WorldlineBic { type Error = error_stack::Report; - fn try_from(bank: &api_models::enums::BankNames) -> Result { + fn try_from(bank: &common_enums::enums::BankNames) -> Result { match bank { - api_models::enums::BankNames::AbnAmro => Ok(Self::Abnamro), - api_models::enums::BankNames::AsnBank => Ok(Self::Asn), - api_models::enums::BankNames::Ing => Ok(Self::Ing), - api_models::enums::BankNames::Knab => Ok(Self::Knab), - api_models::enums::BankNames::Rabobank => Ok(Self::Rabobank), - api_models::enums::BankNames::Regiobank => Ok(Self::Regiobank), - api_models::enums::BankNames::SnsBank => Ok(Self::Sns), - api_models::enums::BankNames::TriodosBank => Ok(Self::Triodos), - api_models::enums::BankNames::VanLanschot => Ok(Self::Vanlanschot), - api_models::enums::BankNames::FrieslandBank => Ok(Self::Friesland), + common_enums::enums::BankNames::AbnAmro => Ok(Self::Abnamro), + common_enums::enums::BankNames::AsnBank => Ok(Self::Asn), + common_enums::enums::BankNames::Ing => Ok(Self::Ing), + common_enums::enums::BankNames::Knab => Ok(Self::Knab), + common_enums::enums::BankNames::Rabobank => Ok(Self::Rabobank), + common_enums::enums::BankNames::Regiobank => Ok(Self::Regiobank), + common_enums::enums::BankNames::SnsBank => Ok(Self::Sns), + common_enums::enums::BankNames::TriodosBank => Ok(Self::Triodos), + common_enums::enums::BankNames::VanLanschot => Ok(Self::Vanlanschot), + common_enums::enums::BankNames::FrieslandBank => Ok(Self::Friesland), _ => Err(errors::ConnectorError::FlowNotSupported { flow: bank.to_string(), connector: "Worldline".to_string(), @@ -374,12 +374,12 @@ fn make_card_request( fn make_bank_redirect_request( req: &PaymentsAuthorizeData, - bank_redirect: &payments::BankRedirectData, + bank_redirect: &domain::BankRedirectData, ) -> Result> { let return_url = req.router_return_url.clone(); let redirection_data = RedirectionData { return_url }; let (payment_method_specific_data, payment_product_id) = match bank_redirect { - payments::BankRedirectData::Giropay { + domain::BankRedirectData::Giropay { billing_details, bank_account_iban, .. @@ -399,7 +399,7 @@ fn make_bank_redirect_request( }, 816, ), - payments::BankRedirectData::Ideal { bank_name, .. } => ( + domain::BankRedirectData::Ideal { bank_name, .. } => ( { PaymentMethodSpecificData::PaymentProduct809SpecificInput(Box::new(Ideal { issuer_id: bank_name @@ -409,21 +409,21 @@ fn make_bank_redirect_request( }, 809, ), - payments::BankRedirectData::BancontactCard { .. } - | payments::BankRedirectData::Bizum {} - | payments::BankRedirectData::Blik { .. } - | payments::BankRedirectData::Eps { .. } - | payments::BankRedirectData::Interac { .. } - | payments::BankRedirectData::OnlineBankingCzechRepublic { .. } - | payments::BankRedirectData::OnlineBankingFinland { .. } - | payments::BankRedirectData::OnlineBankingPoland { .. } - | payments::BankRedirectData::OnlineBankingSlovakia { .. } - | payments::BankRedirectData::OpenBankingUk { .. } - | payments::BankRedirectData::Przelewy24 { .. } - | payments::BankRedirectData::Sofort { .. } - | payments::BankRedirectData::Trustly { .. } - | payments::BankRedirectData::OnlineBankingFpx { .. } - | payments::BankRedirectData::OnlineBankingThailand { .. } => { + domain::BankRedirectData::BancontactCard { .. } + | domain::BankRedirectData::Bizum {} + | domain::BankRedirectData::Blik { .. } + | domain::BankRedirectData::Eps { .. } + | domain::BankRedirectData::Interac { .. } + | domain::BankRedirectData::OnlineBankingCzechRepublic { .. } + | domain::BankRedirectData::OnlineBankingFinland { .. } + | domain::BankRedirectData::OnlineBankingPoland { .. } + | domain::BankRedirectData::OnlineBankingSlovakia { .. } + | domain::BankRedirectData::OpenBankingUk { .. } + | domain::BankRedirectData::Przelewy24 { .. } + | domain::BankRedirectData::Sofort { .. } + | domain::BankRedirectData::Trustly { .. } + | domain::BankRedirectData::OnlineBankingFpx { .. } + | domain::BankRedirectData::OnlineBankingThailand { .. } => { return Err(errors::ConnectorError::NotImplemented( utils::get_unimplemented_payment_method_error_message("worldline"), ) diff --git a/crates/router/src/connector/zen/transformers.rs b/crates/router/src/connector/zen/transformers.rs index e6ead170d9f7..4f11af6a33af 100644 --- a/crates/router/src/connector/zen/transformers.rs +++ b/crates/router/src/connector/zen/transformers.rs @@ -358,6 +358,7 @@ impl | api_models::payments::BankTransferData::BriVaBankTransfer { .. } | api_models::payments::BankTransferData::CimbVaBankTransfer { .. } | api_models::payments::BankTransferData::DanamonVaBankTransfer { .. } + | api_models::payments::BankTransferData::LocalBankTransfer { .. } | api_models::payments::BankTransferData::MandiriVaBankTransfer { .. } => { Err(errors::ConnectorError::NotImplemented( utils::get_unimplemented_payment_method_error_message("Zen"), @@ -724,27 +725,27 @@ impl TryFrom<&ZenRouterData<&types::PaymentsAuthorizeRouterData>> for ZenPayment } } -impl TryFrom<&api_models::payments::BankRedirectData> for ZenPaymentsRequest { +impl TryFrom<&domain::BankRedirectData> for ZenPaymentsRequest { type Error = error_stack::Report; - fn try_from(value: &api_models::payments::BankRedirectData) -> Result { + fn try_from(value: &domain::BankRedirectData) -> Result { match value { - api_models::payments::BankRedirectData::Ideal { .. } - | api_models::payments::BankRedirectData::Sofort { .. } - | api_models::payments::BankRedirectData::BancontactCard { .. } - | api_models::payments::BankRedirectData::Blik { .. } - | api_models::payments::BankRedirectData::Trustly { .. } - | api_models::payments::BankRedirectData::Eps { .. } - | api_models::payments::BankRedirectData::Giropay { .. } - | api_models::payments::BankRedirectData::Przelewy24 { .. } - | api_models::payments::BankRedirectData::Bizum {} - | api_models::payments::BankRedirectData::Interac { .. } - | api_models::payments::BankRedirectData::OnlineBankingCzechRepublic { .. } - | api_models::payments::BankRedirectData::OnlineBankingFinland { .. } - | api_models::payments::BankRedirectData::OnlineBankingPoland { .. } - | api_models::payments::BankRedirectData::OnlineBankingSlovakia { .. } - | api_models::payments::BankRedirectData::OpenBankingUk { .. } - | api_models::payments::BankRedirectData::OnlineBankingFpx { .. } - | api_models::payments::BankRedirectData::OnlineBankingThailand { .. } => { + domain::BankRedirectData::Ideal { .. } + | domain::BankRedirectData::Sofort { .. } + | domain::BankRedirectData::BancontactCard { .. } + | domain::BankRedirectData::Blik { .. } + | domain::BankRedirectData::Trustly { .. } + | domain::BankRedirectData::Eps { .. } + | domain::BankRedirectData::Giropay { .. } + | domain::BankRedirectData::Przelewy24 { .. } + | domain::BankRedirectData::Bizum {} + | domain::BankRedirectData::Interac { .. } + | domain::BankRedirectData::OnlineBankingCzechRepublic { .. } + | domain::BankRedirectData::OnlineBankingFinland { .. } + | domain::BankRedirectData::OnlineBankingPoland { .. } + | domain::BankRedirectData::OnlineBankingSlovakia { .. } + | domain::BankRedirectData::OpenBankingUk { .. } + | domain::BankRedirectData::OnlineBankingFpx { .. } + | domain::BankRedirectData::OnlineBankingThailand { .. } => { Err(errors::ConnectorError::NotImplemented( utils::get_unimplemented_payment_method_error_message("Zen"), ) @@ -754,18 +755,18 @@ impl TryFrom<&api_models::payments::BankRedirectData> for ZenPaymentsRequest { } } -impl TryFrom<&api_models::payments::PayLaterData> for ZenPaymentsRequest { +impl TryFrom<&domain::payments::PayLaterData> for ZenPaymentsRequest { type Error = error_stack::Report; - fn try_from(value: &api_models::payments::PayLaterData) -> Result { + fn try_from(value: &domain::payments::PayLaterData) -> Result { match value { - api_models::payments::PayLaterData::KlarnaRedirect { .. } - | api_models::payments::PayLaterData::KlarnaSdk { .. } - | api_models::payments::PayLaterData::AffirmRedirect {} - | api_models::payments::PayLaterData::AfterpayClearpayRedirect { .. } - | api_models::payments::PayLaterData::PayBrightRedirect {} - | api_models::payments::PayLaterData::WalleyRedirect {} - | api_models::payments::PayLaterData::AlmaRedirect {} - | api_models::payments::PayLaterData::AtomeRedirect {} => { + domain::payments::PayLaterData::KlarnaRedirect { .. } + | domain::payments::PayLaterData::KlarnaSdk { .. } + | domain::payments::PayLaterData::AffirmRedirect {} + | domain::payments::PayLaterData::AfterpayClearpayRedirect { .. } + | domain::payments::PayLaterData::PayBrightRedirect {} + | domain::payments::PayLaterData::WalleyRedirect {} + | domain::payments::PayLaterData::AlmaRedirect {} + | domain::payments::PayLaterData::AtomeRedirect {} => { Err(errors::ConnectorError::NotImplemented( utils::get_unimplemented_payment_method_error_message("Zen"), ) diff --git a/crates/router/src/core/errors/api_error_response.rs b/crates/router/src/core/errors/api_error_response.rs index b3fbbaaf141f..dc3e19cb7254 100644 --- a/crates/router/src/core/errors/api_error_response.rs +++ b/crates/router/src/core/errors/api_error_response.rs @@ -260,6 +260,11 @@ pub enum ApiErrorResponse { CurrencyConversionFailed, #[error(error_type = ErrorType::InvalidRequestError, code = "IR_25", message = "Cannot delete the default payment method")] PaymentMethodDeleteFailed, + #[error( + error_type = ErrorType::InvalidRequestError, code = "IR_26", + message = "Invalid Cookie" + )] + InvalidCookie, } impl PTError for ApiErrorResponse { diff --git a/crates/router/src/core/errors/transformers.rs b/crates/router/src/core/errors/transformers.rs index 110feb22df3c..7c06fc92c994 100644 --- a/crates/router/src/core/errors/transformers.rs +++ b/crates/router/src/core/errors/transformers.rs @@ -292,6 +292,9 @@ impl ErrorSwitch for ApiErrorRespon Self::PaymentMethodDeleteFailed => { AER::BadRequest(ApiError::new("IR", 25, "Cannot delete the default payment method", None)) } + Self::InvalidCookie => { + AER::BadRequest(ApiError::new("IR", 26, "Invalid Cookie", None)) + } } } } diff --git a/crates/router/src/core/payment_methods/cards.rs b/crates/router/src/core/payment_methods/cards.rs index d94864c75b55..fc933ea28d7c 100644 --- a/crates/router/src/core/payment_methods/cards.rs +++ b/crates/router/src/core/payment_methods/cards.rs @@ -1127,10 +1127,11 @@ pub async fn mock_delete_card<'a>( //------------------------------------------------------------------------------ pub fn get_banks( state: &routes::AppState, - pm_type: api_enums::PaymentMethodType, + pm_type: common_enums::enums::PaymentMethodType, connectors: Vec, ) -> Result, errors::ApiErrorResponse> { - let mut bank_names_hm: HashMap> = HashMap::new(); + let mut bank_names_hm: HashMap> = + HashMap::new(); if matches!( pm_type, @@ -1296,7 +1297,7 @@ pub async fn list_payment_methods( Some(api::MandateTransactionType::RecurringMandateTransaction) } else if pa.mandate_details.is_some() || setup_future_usage - .map(|future_usage| future_usage == api_enums::FutureUsage::OffSession) + .map(|future_usage| future_usage == common_enums::enums::FutureUsage::OffSession) .unwrap_or(false) { Some(api::MandateTransactionType::NewMandateTransaction) diff --git a/crates/router/src/core/payment_methods/transformers.rs b/crates/router/src/core/payment_methods/transformers.rs index f639aa592187..357f077332df 100644 --- a/crates/router/src/core/payment_methods/transformers.rs +++ b/crates/router/src/core/payment_methods/transformers.rs @@ -27,6 +27,15 @@ pub enum StoreLockerReq<'a> { LockerGeneric(StoreGenericReq<'a>), } +impl StoreLockerReq<'_> { + pub fn update_requestor_card_reference(&mut self, card_reference: Option) { + match self { + Self::LockerCard(c) => c.requestor_card_reference = card_reference, + Self::LockerGeneric(_) => (), + } + } +} + #[derive(Debug, Deserialize, Serialize)] pub struct StoreCardReq<'a> { pub merchant_id: &'a str, diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs index e7ec99f61b62..91b1d7f3190d 100644 --- a/crates/router/src/core/payments.rs +++ b/crates/router/src/core/payments.rs @@ -1347,6 +1347,7 @@ where merchant_account, connector_request, key_store, + payment_data.payment_intent.profile_id.clone(), ) .await } else { @@ -1475,6 +1476,7 @@ where merchant_account, None, key_store, + payment_data.payment_intent.profile_id.clone(), ); join_handlers.push(res); @@ -2929,10 +2931,12 @@ where .attach_printable("Invalid connector name received")?; return decide_multiplex_connector_for_normal_or_recurring_payment( + &state, payment_data, routing_data, connector_data, - ); + ) + .await; } if let Some(ref routing_algorithm) = routing_data.routing_info.algorithm { @@ -2983,10 +2987,12 @@ where .attach_printable("Invalid connector name received")?; return decide_multiplex_connector_for_normal_or_recurring_payment( + &state, payment_data, routing_data, connector_data, - ); + ) + .await; } route_connector_v1( @@ -3001,7 +3007,8 @@ where .await } -pub fn decide_multiplex_connector_for_normal_or_recurring_payment( +pub async fn decide_multiplex_connector_for_normal_or_recurring_payment( + state: &AppState, payment_data: &mut PaymentData, routing_data: &mut storage::RoutingData, connectors: Vec, @@ -3010,9 +3017,11 @@ pub fn decide_multiplex_connector_for_normal_or_recurring_payment( payment_data.payment_intent.setup_future_usage, payment_data.token_data.as_ref(), payment_data.recurring_details.as_ref(), + payment_data.payment_intent.off_session, ) { - (Some(storage_enums::FutureUsage::OffSession), Some(_), None) - | (None, None, Some(RecurringDetails::PaymentMethodId(_))) => { + (Some(storage_enums::FutureUsage::OffSession), Some(_), None, None) + | (None, None, Some(RecurringDetails::PaymentMethodId(_)), Some(true)) + | (None, Some(_), None, Some(true)) => { logger::debug!("performing routing for token-based MIT flow"); let payment_method_info = payment_data @@ -3020,32 +3029,109 @@ pub fn decide_multiplex_connector_for_normal_or_recurring_payment( .as_ref() .get_required_value("payment_method_info")?; - let connector_mandate_details = payment_method_info - .connector_mandate_details - .clone() - .map(|details| { - details.parse_value::("connector_mandate_details") - }) - .transpose() - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("unable to deserialize connector mandate details")? - .get_required_value("connector_mandate_details") - .change_context(errors::ApiErrorResponse::IncorrectPaymentMethodConfiguration) - .attach_printable("no eligible connector found for token-based MIT flow since there were no connector mandate details")?; + let connector_mandate_details = &payment_method_info + .connector_mandate_details + .clone() + .map(|details| { + details.parse_value::( + "connector_mandate_details", + ) + }) + .transpose() + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("unable to deserialize connector mandate details")?; + + let profile_id = payment_data + .payment_intent + .profile_id + .as_ref() + .ok_or(errors::ApiErrorResponse::ResourceIdNotFound)?; + + let pg_agnostic = state + .store + .find_config_by_key_unwrap_or( + &format!("pg_agnostic_mandate_{}", profile_id), + Some("false".to_string()), + ) + .await + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("The pg_agnostic config was not found in the DB")?; let mut connector_choice = None; + for connector_data in connectors { - if let Some(merchant_connector_id) = connector_data.merchant_connector_id.as_ref() { - if let Some(mandate_reference_record) = - connector_mandate_details.get(merchant_connector_id) + let merchant_connector_id = connector_data + .merchant_connector_id + .as_ref() + .ok_or(errors::ApiErrorResponse::InternalServerError)?; + + if is_network_transaction_id_flow( + state, + &pg_agnostic.config, + connector_data.connector_name, + payment_method_info, + ) { + logger::info!("using network_transaction_id for MIT flow"); + let network_transaction_id = payment_method_info + .network_transaction_id + .as_ref() + .ok_or(errors::ApiErrorResponse::InternalServerError)?; + + let mandate_reference_id = + Some(payments_api::MandateReferenceId::NetworkMandateId( + network_transaction_id.to_string(), + )); + + connector_choice = Some((connector_data, mandate_reference_id.clone())); + break; + } else if connector_mandate_details + .clone() + .map(|connector_mandate_details| { + connector_mandate_details.contains_key(merchant_connector_id) + }) + .unwrap_or(false) + { + if let Some(merchant_connector_id) = + connector_data.merchant_connector_id.as_ref() { - connector_choice = Some((connector_data, mandate_reference_record.clone())); - break; + if let Some(mandate_reference_record) = connector_mandate_details.clone() + .get_required_value("connector_mandate_details") + .change_context(errors::ApiErrorResponse::IncorrectPaymentMethodConfiguration) + .attach_printable("no eligible connector found for token-based MIT flow since there were no connector mandate details")? + .get(merchant_connector_id) + { + let mandate_reference_id = + Some(payments_api::MandateReferenceId::ConnectorMandateId( + payments_api::ConnectorMandateReferenceId { + connector_mandate_id: Some( + mandate_reference_record.connector_mandate_id.clone(), + ), + payment_method_id: Some( + payment_method_info.payment_method_id.clone(), + ), + update_history: None, + }, + )); + payment_data.recurring_mandate_payment_data = + Some(RecurringMandatePaymentData { + payment_method_type: mandate_reference_record + .payment_method_type, + original_payment_authorized_amount: mandate_reference_record + .original_payment_authorized_amount, + original_payment_authorized_currency: mandate_reference_record + .original_payment_authorized_currency, + }); + + connector_choice = Some((connector_data, mandate_reference_id.clone())); + break; + } } + } else { + continue; } } - let (chosen_connector_data, mandate_reference_record) = connector_choice + let (chosen_connector_data, mandate_reference_id) = connector_choice .get_required_value("connector_choice") .change_context(errors::ApiErrorResponse::IncorrectPaymentMethodConfiguration) .attach_printable("no eligible connector found for token-based MIT payment")?; @@ -3056,26 +3142,16 @@ pub fn decide_multiplex_connector_for_normal_or_recurring_payment( routing_data.merchant_connector_id = chosen_connector_data.merchant_connector_id.clone(); } + routing_data.routed_through = Some(chosen_connector_data.connector_name.to_string()); + #[cfg(feature = "connector_choice_mca_id")] + { + routing_data.merchant_connector_id = + chosen_connector_data.merchant_connector_id.clone(); + } payment_data.mandate_id = Some(payments_api::MandateIds { mandate_id: None, - mandate_reference_id: Some(payments_api::MandateReferenceId::ConnectorMandateId( - payments_api::ConnectorMandateReferenceId { - connector_mandate_id: Some( - mandate_reference_record.connector_mandate_id.clone(), - ), - payment_method_id: Some(payment_method_info.payment_method_id.clone()), - update_history: None, - }, - )), - }); - - payment_data.recurring_mandate_payment_data = Some(RecurringMandatePaymentData { - payment_method_type: mandate_reference_record.payment_method_type, - original_payment_authorized_amount: mandate_reference_record - .original_payment_authorized_amount, - original_payment_authorized_currency: mandate_reference_record - .original_payment_authorized_currency, + mandate_reference_id, }); Ok(api::ConnectorCallType::PreDetermined(chosen_connector_data)) @@ -3098,6 +3174,23 @@ pub fn decide_multiplex_connector_for_normal_or_recurring_payment( } } +pub fn is_network_transaction_id_flow( + state: &AppState, + pg_agnostic: &String, + connector: enums::Connector, + payment_method_info: &storage::PaymentMethod, +) -> bool { + let ntid_supported_connectors = &state + .conf + .network_transaction_id_supported_connectors + .connector_list; + + pg_agnostic == "true" + && payment_method_info.payment_method == storage_enums::PaymentMethod::Card + && ntid_supported_connectors.contains(&connector) + && payment_method_info.network_transaction_id.is_some() +} + pub fn should_add_task_to_process_tracker(payment_data: &PaymentData) -> bool { let connector = payment_data.payment_attempt.connector.as_deref(); @@ -3315,10 +3408,12 @@ where match transaction_data { TransactionData::Payment(payment_data) => { decide_multiplex_connector_for_normal_or_recurring_payment( + state, payment_data, routing_data, connector_data, ) + .await } #[cfg(feature = "payouts")] diff --git a/crates/router/src/core/payments/flows.rs b/crates/router/src/core/payments/flows.rs index 6c952dc2593c..2e8713fbdb88 100644 --- a/crates/router/src/core/payments/flows.rs +++ b/crates/router/src/core/payments/flows.rs @@ -49,6 +49,7 @@ pub trait Feature { merchant_account: &domain::MerchantAccount, connector_request: Option, key_store: &domain::MerchantKeyStore, + profile_id: Option, ) -> RouterResult where Self: Sized, @@ -155,6 +156,7 @@ default_imp_for_complete_authorize!( connector::Coinbase, connector::Cryptopay, connector::Dlocal, + connector::Ebanx, connector::Fiserv, connector::Forte, connector::Globepay, @@ -229,6 +231,7 @@ default_imp_for_webhook_source_verification!( connector::Cryptopay, connector::Cybersource, connector::Dlocal, + connector::Ebanx, connector::Fiserv, connector::Forte, connector::Globalpay, @@ -313,6 +316,7 @@ default_imp_for_create_customer!( connector::Cryptopay, connector::Cybersource, connector::Dlocal, + connector::Ebanx, connector::Fiserv, connector::Forte, connector::Globalpay, @@ -391,6 +395,7 @@ default_imp_for_connector_redirect_response!( connector::Cryptopay, connector::Cybersource, connector::Dlocal, + connector::Ebanx, connector::Fiserv, connector::Forte, connector::Globepay, @@ -450,6 +455,7 @@ default_imp_for_connector_request_id!( connector::Cryptopay, connector::Cybersource, connector::Dlocal, + connector::Ebanx, connector::Fiserv, connector::Forte, connector::Globalpay, @@ -535,6 +541,7 @@ default_imp_for_accept_dispute!( connector::Cryptopay, connector::Cybersource, connector::Dlocal, + connector::Ebanx, connector::Fiserv, connector::Forte, connector::Globalpay, @@ -641,6 +648,7 @@ default_imp_for_file_upload!( connector::Cryptopay, connector::Cybersource, connector::Dlocal, + connector::Ebanx, connector::Fiserv, connector::Forte, connector::Globalpay, @@ -724,6 +732,7 @@ default_imp_for_submit_evidence!( connector::Coinbase, connector::Cryptopay, connector::Dlocal, + connector::Ebanx, connector::Fiserv, connector::Forte, connector::Globalpay, @@ -807,6 +816,7 @@ default_imp_for_defend_dispute!( connector::Coinbase, connector::Cryptopay, connector::Dlocal, + connector::Ebanx, connector::Fiserv, connector::Globepay, connector::Forte, @@ -889,6 +899,7 @@ default_imp_for_pre_processing_steps!( connector::Coinbase, connector::Cryptopay, connector::Dlocal, + connector::Ebanx, connector::Iatapay, connector::Fiserv, connector::Forte, @@ -951,6 +962,7 @@ default_imp_for_payouts!( connector::Cybersource, connector::Coinbase, connector::Dlocal, + connector::Ebanx, connector::Fiserv, connector::Forte, connector::Globalpay, @@ -1035,6 +1047,7 @@ default_imp_for_payouts_create!( connector::Cybersource, connector::Coinbase, connector::Dlocal, + connector::Ebanx, connector::Fiserv, connector::Forte, connector::Globalpay, @@ -1122,6 +1135,7 @@ default_imp_for_payouts_eligibility!( connector::Cybersource, connector::Coinbase, connector::Dlocal, + connector::Ebanx, connector::Fiserv, connector::Forte, connector::Globalpay, @@ -1206,6 +1220,7 @@ default_imp_for_payouts_fulfill!( connector::Cybersource, connector::Coinbase, connector::Dlocal, + connector::Ebanx, connector::Fiserv, connector::Forte, connector::Globalpay, @@ -1290,6 +1305,7 @@ default_imp_for_payouts_cancel!( connector::Cybersource, connector::Coinbase, connector::Dlocal, + connector::Ebanx, connector::Fiserv, connector::Forte, connector::Globalpay, @@ -1375,6 +1391,7 @@ default_imp_for_payouts_quote!( connector::Cybersource, connector::Coinbase, connector::Dlocal, + connector::Ebanx, connector::Fiserv, connector::Forte, connector::Globalpay, @@ -1460,6 +1477,7 @@ default_imp_for_payouts_recipient!( connector::Cybersource, connector::Coinbase, connector::Dlocal, + connector::Ebanx, connector::Fiserv, connector::Forte, connector::Globalpay, @@ -1544,6 +1562,7 @@ default_imp_for_approve!( connector::Cybersource, connector::Coinbase, connector::Dlocal, + connector::Ebanx, connector::Fiserv, connector::Forte, connector::Globalpay, @@ -1629,6 +1648,7 @@ default_imp_for_reject!( connector::Cybersource, connector::Coinbase, connector::Dlocal, + connector::Ebanx, connector::Fiserv, connector::Forte, connector::Globalpay, @@ -1698,6 +1718,7 @@ default_imp_for_fraud_check!( connector::Cybersource, connector::Coinbase, connector::Dlocal, + connector::Ebanx, connector::Fiserv, connector::Forte, connector::Globalpay, @@ -1783,6 +1804,7 @@ default_imp_for_frm_sale!( connector::Cybersource, connector::Coinbase, connector::Dlocal, + connector::Ebanx, connector::Fiserv, connector::Forte, connector::Globalpay, @@ -1868,6 +1890,7 @@ default_imp_for_frm_checkout!( connector::Cybersource, connector::Coinbase, connector::Dlocal, + connector::Ebanx, connector::Fiserv, connector::Forte, connector::Globalpay, @@ -1953,6 +1976,7 @@ default_imp_for_frm_transaction!( connector::Cybersource, connector::Coinbase, connector::Dlocal, + connector::Ebanx, connector::Fiserv, connector::Forte, connector::Globalpay, @@ -2038,6 +2062,7 @@ default_imp_for_frm_fulfillment!( connector::Cybersource, connector::Coinbase, connector::Dlocal, + connector::Ebanx, connector::Fiserv, connector::Forte, connector::Globalpay, @@ -2123,6 +2148,7 @@ default_imp_for_frm_record_return!( connector::Cybersource, connector::Coinbase, connector::Dlocal, + connector::Ebanx, connector::Fiserv, connector::Forte, connector::Globalpay, @@ -2205,6 +2231,7 @@ default_imp_for_incremental_authorization!( connector::Cryptopay, connector::Coinbase, connector::Dlocal, + connector::Ebanx, connector::Fiserv, connector::Forte, connector::Globalpay, @@ -2287,6 +2314,7 @@ default_imp_for_revoking_mandates!( connector::Cryptopay, connector::Coinbase, connector::Dlocal, + connector::Ebanx, connector::Fiserv, connector::Forte, connector::Globalpay, @@ -2411,6 +2439,7 @@ default_imp_for_connector_authentication!( connector::Coinbase, connector::Cybersource, connector::Dlocal, + connector::Ebanx, connector::Fiserv, connector::Forte, connector::Globalpay, diff --git a/crates/router/src/core/payments/flows/approve_flow.rs b/crates/router/src/core/payments/flows/approve_flow.rs index 14b710de914a..43e36847eb91 100644 --- a/crates/router/src/core/payments/flows/approve_flow.rs +++ b/crates/router/src/core/payments/flows/approve_flow.rs @@ -54,6 +54,7 @@ impl Feature _merchant_account: &domain::MerchantAccount, _connector_request: Option, _key_store: &domain::MerchantKeyStore, + _profile_id: Option, ) -> RouterResult { Err(ApiErrorResponse::NotImplemented { message: NotImplementedMessage::Reason("Flow not supported".to_string()), diff --git a/crates/router/src/core/payments/flows/authorize_flow.rs b/crates/router/src/core/payments/flows/authorize_flow.rs index a5132e4a3464..cccfab5a74b0 100644 --- a/crates/router/src/core/payments/flows/authorize_flow.rs +++ b/crates/router/src/core/payments/flows/authorize_flow.rs @@ -66,6 +66,7 @@ impl Feature for types::PaymentsAu merchant_account: &domain::MerchantAccount, connector_request: Option, key_store: &domain::MerchantKeyStore, + profile_id: Option, ) -> RouterResult { let connector_integration: services::BoxedConnectorIntegration< '_, @@ -103,6 +104,7 @@ impl Feature for types::PaymentsAu key_store, Some(resp.request.amount), Some(resp.request.currency), + profile_id, )) .await?; @@ -132,6 +134,7 @@ impl Feature for types::PaymentsAu key_store, Some(resp.request.amount), Some(resp.request.currency), + profile_id, )) .await; @@ -140,7 +143,7 @@ impl Feature for types::PaymentsAu resp.payment_method_id = payment_method_id.clone(); resp.payment_method_status = payment_method_status; } - Err(_) => logger::error!("Save pm to locker failed"), + Err(err) => logger::error!("Save pm to locker failed : {err:?}"), } Ok(resp) diff --git a/crates/router/src/core/payments/flows/cancel_flow.rs b/crates/router/src/core/payments/flows/cancel_flow.rs index 5918380ee0b2..5814b1cafb18 100644 --- a/crates/router/src/core/payments/flows/cancel_flow.rs +++ b/crates/router/src/core/payments/flows/cancel_flow.rs @@ -53,6 +53,7 @@ impl Feature _merchant_account: &domain::MerchantAccount, connector_request: Option, _key_store: &domain::MerchantKeyStore, + _profile_id: Option, ) -> RouterResult { metrics::PAYMENT_CANCEL_COUNT.add( &metrics::CONTEXT, diff --git a/crates/router/src/core/payments/flows/capture_flow.rs b/crates/router/src/core/payments/flows/capture_flow.rs index d2b7c8e91bdb..5f64014bce70 100644 --- a/crates/router/src/core/payments/flows/capture_flow.rs +++ b/crates/router/src/core/payments/flows/capture_flow.rs @@ -54,6 +54,7 @@ impl Feature _merchant_account: &domain::MerchantAccount, connector_request: Option, _key_store: &domain::MerchantKeyStore, + _profile_id: Option, ) -> RouterResult { let connector_integration: services::BoxedConnectorIntegration< '_, diff --git a/crates/router/src/core/payments/flows/complete_authorize_flow.rs b/crates/router/src/core/payments/flows/complete_authorize_flow.rs index 68d0ee8d475f..e64240387d2e 100644 --- a/crates/router/src/core/payments/flows/complete_authorize_flow.rs +++ b/crates/router/src/core/payments/flows/complete_authorize_flow.rs @@ -68,6 +68,7 @@ impl Feature _merchant_account: &domain::MerchantAccount, connector_request: Option, _key_store: &domain::MerchantKeyStore, + _profile_id: Option, ) -> RouterResult { let connector_integration: services::BoxedConnectorIntegration< '_, diff --git a/crates/router/src/core/payments/flows/incremental_authorization_flow.rs b/crates/router/src/core/payments/flows/incremental_authorization_flow.rs index 387916bab7c9..99f8e4831bba 100644 --- a/crates/router/src/core/payments/flows/incremental_authorization_flow.rs +++ b/crates/router/src/core/payments/flows/incremental_authorization_flow.rs @@ -61,6 +61,7 @@ impl Feature, _key_store: &domain::MerchantKeyStore, + _profile_id: Option, ) -> RouterResult { let connector_integration: services::BoxedConnectorIntegration< '_, diff --git a/crates/router/src/core/payments/flows/psync_flow.rs b/crates/router/src/core/payments/flows/psync_flow.rs index cb7a764985d1..6463e87279b0 100644 --- a/crates/router/src/core/payments/flows/psync_flow.rs +++ b/crates/router/src/core/payments/flows/psync_flow.rs @@ -57,6 +57,7 @@ impl Feature _merchant_account: &domain::MerchantAccount, connector_request: Option, _key_store: &domain::MerchantKeyStore, + _profile_id: Option, ) -> RouterResult { let connector_integration: services::BoxedConnectorIntegration< '_, diff --git a/crates/router/src/core/payments/flows/reject_flow.rs b/crates/router/src/core/payments/flows/reject_flow.rs index 910cc955e633..4157edf8d0a1 100644 --- a/crates/router/src/core/payments/flows/reject_flow.rs +++ b/crates/router/src/core/payments/flows/reject_flow.rs @@ -53,6 +53,7 @@ impl Feature _merchant_account: &domain::MerchantAccount, _connector_request: Option, _key_store: &domain::MerchantKeyStore, + _profile_id: Option, ) -> RouterResult { Err(ApiErrorResponse::NotImplemented { message: NotImplementedMessage::Reason("Flow not supported".to_string()), diff --git a/crates/router/src/core/payments/flows/session_flow.rs b/crates/router/src/core/payments/flows/session_flow.rs index 349c76cd23a8..1ab72dff15b4 100644 --- a/crates/router/src/core/payments/flows/session_flow.rs +++ b/crates/router/src/core/payments/flows/session_flow.rs @@ -58,6 +58,7 @@ impl Feature for types::PaymentsSessio _merchant_account: &domain::MerchantAccount, _connector_request: Option, _key_store: &domain::MerchantKeyStore, + _profile_id: Option, ) -> RouterResult { metrics::SESSION_TOKEN_CREATED.add( &metrics::CONTEXT, diff --git a/crates/router/src/core/payments/flows/setup_mandate_flow.rs b/crates/router/src/core/payments/flows/setup_mandate_flow.rs index 27204450a0a8..d8acfe98f3b6 100644 --- a/crates/router/src/core/payments/flows/setup_mandate_flow.rs +++ b/crates/router/src/core/payments/flows/setup_mandate_flow.rs @@ -62,6 +62,7 @@ impl Feature for types::Setup merchant_account: &domain::MerchantAccount, connector_request: Option, key_store: &domain::MerchantKeyStore, + profile_id: Option, ) -> RouterResult { if let Some(mandate_id) = self .request @@ -79,6 +80,7 @@ impl Feature for types::Setup &state.conf.mandates.update_mandate_supported, connector_request, maybe_customer, + profile_id, )) .await } else { @@ -109,6 +111,7 @@ impl Feature for types::Setup key_store, resp.request.amount, Some(resp.request.currency), + profile_id, )) .await?; @@ -217,6 +220,7 @@ impl types::SetupMandateRouterData { call_connector_action: payments::CallConnectorAction, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, + profile_id: Option, ) -> RouterResult { match confirm { Some(true) => { @@ -248,6 +252,7 @@ impl types::SetupMandateRouterData { key_store, resp.request.amount, Some(resp.request.currency), + profile_id, )) .await?; @@ -278,6 +283,7 @@ impl types::SetupMandateRouterData { supported_connectors_for_update_mandate: &settings::SupportedPaymentMethodsForMandate, connector_request: Option, maybe_customer: &Option, + profile_id: Option, ) -> RouterResult { let payment_method_type = self.request.payment_method_type; @@ -336,6 +342,7 @@ impl types::SetupMandateRouterData { key_store, resp.request.amount, Some(resp.request.currency), + profile_id, )) .await? .0; diff --git a/crates/router/src/core/payments/helpers.rs b/crates/router/src/core/payments/helpers.rs index 51b950418989..9ec570b441e7 100644 --- a/crates/router/src/core/payments/helpers.rs +++ b/crates/router/src/core/payments/helpers.rs @@ -2204,6 +2204,7 @@ pub fn validate_payment_method_type_against_payment_method( | api_enums::PaymentMethodType::CimbVa | api_enums::PaymentMethodType::DanamonVa | api_enums::PaymentMethodType::MandiriVa + | api_enums::PaymentMethodType::LocalBankTransfer ), api_enums::PaymentMethod::BankDebit => matches!( payment_method_type, diff --git a/crates/router/src/core/payments/operations/payment_confirm.rs b/crates/router/src/core/payments/operations/payment_confirm.rs index 4eac9c1f4dec..5214ce3f7a79 100644 --- a/crates/router/src/core/payments/operations/payment_confirm.rs +++ b/crates/router/src/core/payments/operations/payment_confirm.rs @@ -413,8 +413,11 @@ impl payment_attempt.payment_method = payment_method.or(payment_attempt.payment_method); payment_attempt.browser_info = browser_info; - payment_attempt.payment_method_type = - payment_method_type.or(payment_attempt.payment_method_type); + payment_attempt.payment_method_type = payment_method_type + .or(payment_attempt.payment_method_type) + .or(payment_method_info + .as_ref() + .and_then(|pm_info| pm_info.payment_method_type)); payment_attempt.payment_experience = request .payment_experience diff --git a/crates/router/src/core/payments/operations/payment_response.rs b/crates/router/src/core/payments/operations/payment_response.rs index f418b660380b..aeb4d6e5b1cd 100644 --- a/crates/router/src/core/payments/operations/payment_response.rs +++ b/crates/router/src/core/payments/operations/payment_response.rs @@ -972,18 +972,47 @@ async fn update_payment_method_status_and_ntid( .find_payment_method(id) .await .to_not_found_response(errors::ApiErrorResponse::PaymentMethodNotFound)?; - let network_transaction_id = payment_response - .map(|resp| match resp { - crate::types::PaymentsResponseData::TransactionResponse { network_txn_id, .. } => { - network_txn_id.to_owned() + + let pm_resp_network_transaction_id = payment_response + .map(|resp| if let types::PaymentsResponseData::TransactionResponse { network_txn_id: network_transaction_id, .. } = resp { + network_transaction_id + } else {None}) + .map_err(|err| { + logger::error!(error=?err, "Failed to obtain the network_transaction_id from payment response"); + }) + .ok() + .flatten(); + + let network_transaction_id = + if let Some(network_transaction_id) = pm_resp_network_transaction_id { + let profile_id = payment_data + .payment_intent + .profile_id + .as_ref() + .ok_or(errors::ApiErrorResponse::ResourceIdNotFound)?; + + let pg_agnostic = state + .store + .find_config_by_key_unwrap_or( + &format!("pg_agnostic_mandate_{}", profile_id), + Some("false".to_string()), + ) + .await + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("The pg_agnostic config was not found in the DB")?; + + if &pg_agnostic.config == "true" + && payment_data.payment_intent.setup_future_usage + == Some(diesel_models::enums::FutureUsage::OffSession) + { + Some(network_transaction_id) + } else { + logger::info!("Skip storing network transaction id"); + None } - _ => None, - }) - .map_err(|err| { - logger::error!(error=?err, "Failed to obtain the network_transaction_id from payment response"); - }) - .ok() - .flatten(); + } else { + None + }; let pm_update = if pm.status != common_enums::PaymentMethodStatus::Active && pm.status != attempt_status.into() diff --git a/crates/router/src/core/payments/operations/payment_status.rs b/crates/router/src/core/payments/operations/payment_status.rs index 7a8f487d73ab..f25b89977f6c 100644 --- a/crates/router/src/core/payments/operations/payment_status.rs +++ b/crates/router/src/core/payments/operations/payment_status.rs @@ -5,7 +5,7 @@ use async_trait::async_trait; use common_utils::ext_traits::AsyncExt; use error_stack::ResultExt; use router_derive::PaymentOperation; -use router_env::{instrument, tracing}; +use router_env::{instrument, logger, tracing}; use super::{BoxedOperation, Domain, GetTracker, Operation, UpdateTracker, ValidateRequest}; use crate::{ @@ -399,14 +399,22 @@ async fn get_tracker_for_sync< .to_not_found_response(errors::ApiErrorResponse::BusinessProfileNotFound { id: profile_id.to_string(), })?; + let payment_method_info = if let Some(ref payment_method_id) = payment_attempt.payment_method_id.clone() { - Some( - db.find_payment_method(payment_method_id) - .await - .to_not_found_response(errors::ApiErrorResponse::PaymentMethodNotFound) - .attach_printable("error retrieving payment method from DB")?, - ) + match db.find_payment_method(payment_method_id).await { + Ok(payment_method) => Some(payment_method), + Err(error) => { + if error.current_context().is_db_not_found() { + logger::info!("Payment Method not found in db {:?}", error); + None + } else { + Err(error) + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Error retrieving payment method from db")? + } + } + } } else { None }; diff --git a/crates/router/src/core/payments/tokenization.rs b/crates/router/src/core/payments/tokenization.rs index 47cd1cd9eb7b..3f24c55c9982 100644 --- a/crates/router/src/core/payments/tokenization.rs +++ b/crates/router/src/core/payments/tokenization.rs @@ -41,6 +41,7 @@ pub async fn save_payment_method( key_store: &domain::MerchantKeyStore, amount: Option, currency: Option, + profile_id: Option, ) -> RouterResult<(Option, Option)> where FData: mandate::MandateBehaviour, @@ -64,6 +65,35 @@ where _ => None, }; + let network_transaction_id = + if let Some(network_transaction_id) = network_transaction_id { + let profile_id = profile_id + .as_ref() + .ok_or(errors::ApiErrorResponse::ResourceIdNotFound)?; + + let pg_agnostic = state + .store + .find_config_by_key_unwrap_or( + &format!("pg_agnostic_mandate_{}", profile_id), + Some("false".to_string()), + ) + .await + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("The pg_agnostic config was not found in the DB")?; + + if &pg_agnostic.config == "true" + && resp.request.get_setup_future_usage() + == Some(storage_enums::FutureUsage::OffSession) + { + Some(network_transaction_id) + } else { + logger::info!("Skip storing network transaction id"); + None + } + } else { + None + }; + let connector_token = if token_store { let tokens = resp .payment_method_token diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs index 0c7869fa3cbf..595ca3f94a9b 100644 --- a/crates/router/src/core/payments/transformers.rs +++ b/crates/router/src/core/payments/transformers.rs @@ -883,23 +883,23 @@ impl ForeignFrom<(storage::PaymentIntent, storage::PaymentAttempt)> for api::Pay } #[cfg(feature = "payouts")] -impl ForeignFrom<(storage::Payouts, storage::PayoutAttempt)> for api::PayoutCreateResponse { - fn foreign_from(item: (storage::Payouts, storage::PayoutAttempt)) -> Self { - let payout = item.0; - let payout_attempt = item.1; +impl ForeignFrom<(storage::Payouts, storage::PayoutAttempt, domain::Customer)> + for api::PayoutCreateResponse +{ + fn foreign_from(item: (storage::Payouts, storage::PayoutAttempt, domain::Customer)) -> Self { + let (payout, payout_attempt, customer) = item; let attempt = PayoutAttemptResponse { attempt_id: payout_attempt.payout_attempt_id, status: payout_attempt.status, amount: payout.amount, currency: Some(payout.destination_currency), connector: payout_attempt.connector.clone(), - error_code: payout_attempt.error_code, - error_message: payout_attempt.error_message, + error_code: payout_attempt.error_code.clone(), + error_message: payout_attempt.error_message.clone(), payment_method: Some(payout.payout_type), payout_method_type: None, connector_transaction_id: Some(payout_attempt.connector_payout_id), cancellation_reason: None, - payout_token: payout_attempt.payout_token, unified_code: None, unified_message: None, }; @@ -907,20 +907,31 @@ impl ForeignFrom<(storage::Payouts, storage::PayoutAttempt)> for api::PayoutCrea Self { payout_id: payout.payout_id, merchant_id: payout.merchant_id, - status: payout.status, amount: payout.amount, - created: Some(payout.created_at), currency: payout.destination_currency, - description: payout.description, - metadata: payout.metadata, - customer_id: payout.customer_id, connector: payout_attempt.connector, payout_type: payout.payout_type, - business_label: payout_attempt.business_label, + customer_id: customer.customer_id, + auto_fulfill: payout.auto_fulfill, + email: customer.email, + name: customer.name, + phone: customer.phone, + phone_country_code: customer.phone_country_code, + return_url: payout.return_url, business_country: payout_attempt.business_country, + business_label: payout_attempt.business_label, + description: payout.description, + entity_type: payout.entity_type, recurring: payout.recurring, + metadata: payout.metadata, + status: payout_attempt.status, + error_message: payout_attempt.error_message, + error_code: payout_attempt.error_code, + profile_id: payout.profile_id, + created: Some(payout.created_at), attempts: Some(attempts), - ..Default::default() + billing: None, + client_secret: None, } } } diff --git a/crates/router/src/core/payouts.rs b/crates/router/src/core/payouts.rs index 566caa7acc58..0f435a2e266f 100644 --- a/crates/router/src/core/payouts.rs +++ b/crates/router/src/core/payouts.rs @@ -20,7 +20,7 @@ use serde_json; use super::errors::{ConnectorErrorExt, StorageErrorExt}; #[cfg(feature = "olap")] -use crate::types::transformers::ForeignFrom; +use crate::types::{domain::behaviour::Conversion, transformers::ForeignFrom}; use crate::{ core::{ errors::{self, RouterResponse, RouterResult}, @@ -504,9 +504,10 @@ pub async fn payouts_cancel_core( // Make local cancellation } else if helpers::is_eligible_for_local_payout_cancellation(status) { + let status = storage_enums::PayoutStatus::Cancelled; let updated_payout_attempt = storage::PayoutAttemptUpdate::StatusUpdate { connector_payout_id: connector_payout_id.to_owned(), - status: storage_enums::PayoutStatus::Cancelled, + status, error_message: Some("Cancelled by user".to_string()), error_code: None, is_eligible: None, @@ -521,6 +522,16 @@ pub async fn payouts_cancel_core( .await .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Error updating payout_attempt in db")?; + payout_data.payouts = state + .store + .update_payout( + &payout_data.payouts, + storage::PayoutsUpdate::StatusUpdate { status }, + merchant_account.storage_scheme, + ) + .await + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Error updating payouts in db")?; // Trigger connector's cancellation } else { @@ -661,6 +672,7 @@ pub async fn payouts_fulfill_core( pub async fn payouts_list_core( state: AppState, merchant_account: domain::MerchantAccount, + key_store: domain::MerchantKeyStore, constraints: payouts::PayoutListConstraints, ) -> RouterResponse { validator::validate_payout_list_request(&constraints)?; @@ -684,7 +696,34 @@ pub async fn payouts_list_core( ) .await { - Ok(payout_attempt) => Some(Ok((payouts, payout_attempt))), + Ok(payout_attempt) => { + match db + .find_customer_by_customer_id_merchant_id( + &payouts.customer_id, + merchant_id, + &key_store, + ) + .await + { + Ok(customer) => Some(Ok((payouts, payout_attempt, customer))), + Err(error) => { + if matches!( + error.current_context(), + storage_impl::errors::StorageError::ValueNotFound(_) + ) { + logger::warn!( + ?error, + "customer missing for customer_id : {}", + payouts.customer_id, + ); + return None; + } + Some(Err(error.change_context(StorageError::ValueNotFound( + format!("customer missing for customer_id : {}", payouts.customer_id), + )))) + } + } + } Err(error) => { if matches!(error.current_context(), StorageError::ValueNotFound(_)) { logger::warn!( @@ -699,12 +738,14 @@ pub async fn payouts_list_core( } }); - let pi_pa_tuple_vec: Result, _> = - join_all(collected_futures) - .await - .into_iter() - .flatten() - .collect::, _>>(); + let pi_pa_tuple_vec: Result< + Vec<(storage::Payouts, storage::PayoutAttempt, domain::Customer)>, + _, + > = join_all(collected_futures) + .await + .into_iter() + .flatten() + .collect::, _>>(); let data: Vec = pi_pa_tuple_vec .change_context(errors::ApiErrorResponse::InternalServerError)? @@ -724,12 +765,17 @@ pub async fn payouts_list_core( pub async fn payouts_filtered_list_core( state: AppState, merchant_account: domain::MerchantAccount, + key_store: domain::MerchantKeyStore, filters: payouts::PayoutListFilterConstraints, ) -> RouterResponse { let limit = &filters.limit; validator::validate_payout_list_request_for_joins(*limit)?; let db = state.store.as_ref(); - let list: Vec<(storage::Payouts, storage::PayoutAttempt)> = db + let list: Vec<( + storage::Payouts, + storage::PayoutAttempt, + diesel_models::Customer, + )> = db .filter_payouts_and_attempts( &merchant_account.merchant_id, &filters.clone().into(), @@ -738,8 +784,20 @@ pub async fn payouts_filtered_list_core( .await .to_not_found_response(errors::ApiErrorResponse::PayoutNotFound)?; - let data: Vec = - list.into_iter().map(ForeignFrom::foreign_from).collect(); + let data: Vec = join_all(list.into_iter().map(|(p, pa, c)| async { + match domain::Customer::convert_back(c, &key_store.key).await { + Ok(domain_cust) => Some((p, pa, domain_cust)), + Err(err) => { + logger::warn!(?err, "failed to convert customer for id: {}", p.customer_id); + None + } + } + })) + .await + .into_iter() + .flatten() + .map(ForeignFrom::foreign_from) + .collect(); Ok(services::ApplicationResponse::Json( api::PayoutListResponse { @@ -1075,6 +1133,15 @@ pub async fn check_payout_eligibility( .await .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Error updating payout_attempt in db")?; + payout_data.payouts = db + .update_payout( + &payout_data.payouts, + storage::PayoutsUpdate::StatusUpdate { status }, + merchant_account.storage_scheme, + ) + .await + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Error updating payouts in db")?; if helpers::is_payout_err_state(status) { return Err(report!(errors::ApiErrorResponse::PayoutFailed { data: Some( @@ -1084,9 +1151,10 @@ pub async fn check_payout_eligibility( } } Err(err) => { + let status = storage_enums::PayoutStatus::Failed; let updated_payout_attempt = storage::PayoutAttemptUpdate::StatusUpdate { connector_payout_id: String::default(), - status: storage_enums::PayoutStatus::Failed, + status, error_code: Some(err.code), error_message: Some(err.message), is_eligible: Some(false), @@ -1100,6 +1168,15 @@ pub async fn check_payout_eligibility( .await .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Error updating payout_attempt in db")?; + payout_data.payouts = db + .update_payout( + &payout_data.payouts, + storage::PayoutsUpdate::StatusUpdate { status }, + merchant_account.storage_scheme, + ) + .await + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Error updating payouts in db")?; } }; @@ -1174,6 +1251,15 @@ pub async fn create_payout( .await .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Error updating payout_attempt in db")?; + payout_data.payouts = db + .update_payout( + &payout_data.payouts, + storage::PayoutsUpdate::StatusUpdate { status }, + merchant_account.storage_scheme, + ) + .await + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Error updating payouts in db")?; if helpers::is_payout_err_state(status) { return Err(report!(errors::ApiErrorResponse::PayoutFailed { data: Some( @@ -1183,9 +1269,10 @@ pub async fn create_payout( } } Err(err) => { + let status = storage_enums::PayoutStatus::Failed; let updated_payout_attempt = storage::PayoutAttemptUpdate::StatusUpdate { connector_payout_id: String::default(), - status: storage_enums::PayoutStatus::Failed, + status, error_code: Some(err.code), error_message: Some(err.message), is_eligible: None, @@ -1199,6 +1286,15 @@ pub async fn create_payout( .await .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Error updating payout_attempt in db")?; + payout_data.payouts = db + .update_payout( + &payout_data.payouts, + storage::PayoutsUpdate::StatusUpdate { status }, + merchant_account.storage_scheme, + ) + .await + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Error updating payouts in db")?; } }; @@ -1265,12 +1361,22 @@ pub async fn cancel_payout( ) .await .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Error updating payout_attempt in db")? + .attach_printable("Error updating payout_attempt in db")?; + payout_data.payouts = db + .update_payout( + &payout_data.payouts, + storage::PayoutsUpdate::StatusUpdate { status }, + merchant_account.storage_scheme, + ) + .await + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Error updating payouts in db")?; } Err(err) => { + let status = storage_enums::PayoutStatus::Failed; let updated_payout_attempt = storage::PayoutAttemptUpdate::StatusUpdate { connector_payout_id: String::default(), - status: storage_enums::PayoutStatus::Failed, + status, error_code: Some(err.code), error_message: Some(err.message), is_eligible: None, @@ -1283,7 +1389,16 @@ pub async fn cancel_payout( ) .await .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Error updating payout_attempt in db")? + .attach_printable("Error updating payout_attempt in db")?; + payout_data.payouts = db + .update_payout( + &payout_data.payouts, + storage::PayoutsUpdate::StatusUpdate { status }, + merchant_account.storage_scheme, + ) + .await + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Error updating payouts in db")?; } }; @@ -1337,7 +1452,10 @@ pub async fn fulfill_payout( .status .unwrap_or(payout_attempt.status.to_owned()); payout_data.payouts.status = status; - if payout_data.payouts.recurring && payout_data.payouts.payout_method_id.is_none() { + if payout_data.payouts.recurring + && payout_data.payouts.payout_method_id.is_none() + && !helpers::is_payout_err_state(status) + { helpers::save_payout_data_to_locker( state, payout_data, @@ -1366,6 +1484,15 @@ pub async fn fulfill_payout( .await .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Error updating payout_attempt in db")?; + payout_data.payouts = db + .update_payout( + &payout_data.payouts, + storage::PayoutsUpdate::StatusUpdate { status }, + merchant_account.storage_scheme, + ) + .await + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Error updating payouts in db")?; if helpers::is_payout_err_state(status) { return Err(report!(errors::ApiErrorResponse::PayoutFailed { data: Some( @@ -1375,9 +1502,10 @@ pub async fn fulfill_payout( } } Err(err) => { + let status = storage_enums::PayoutStatus::Failed; let updated_payout_attempt = storage::PayoutAttemptUpdate::StatusUpdate { connector_payout_id: String::default(), - status: storage_enums::PayoutStatus::Failed, + status, error_code: Some(err.code), error_message: Some(err.message), is_eligible: None, @@ -1390,7 +1518,16 @@ pub async fn fulfill_payout( ) .await .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Error updating payout_attempt in db")? + .attach_printable("Error updating payout_attempt in db")?; + payout_data.payouts = db + .update_payout( + &payout_data.payouts, + storage::PayoutsUpdate::StatusUpdate { status }, + merchant_account.storage_scheme, + ) + .await + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Error updating payouts in db")?; } }; diff --git a/crates/router/src/core/payouts/helpers.rs b/crates/router/src/core/payouts/helpers.rs index 6efe6ee9a77c..9b54bb03d17f 100644 --- a/crates/router/src/core/payouts/helpers.rs +++ b/crates/router/src/core/payouts/helpers.rs @@ -1,4 +1,4 @@ -use api_models::enums::PayoutConnectors; +use api_models::{enums, payouts}; use common_utils::{ errors::CustomResult, ext_traits::{AsyncExt, StringExt}, @@ -11,10 +11,12 @@ use router_env::logger; use super::PayoutData; use crate::{ core::{ - errors::{self, RouterResult}, + errors::{self, RouterResult, StorageErrorExt}, payment_methods::{ cards, - transformers::{self, StoreCardReq, StoreGenericReq, StoreLockerReq}, + transformers::{ + self, DataDuplicationCheck, StoreCardReq, StoreGenericReq, StoreLockerReq, + }, vault, }, payments::{ @@ -191,9 +193,9 @@ pub async fn save_payout_data_to_locker( key_store: &domain::MerchantKeyStore, ) -> RouterResult<()> { let payout_attempt = &payout_data.payout_attempt; - let (locker_req, card_details, bank_details, wallet_details, payment_method_type) = + let (mut locker_req, card_details, bank_details, wallet_details, payment_method_type) = match payout_method_data { - api_models::payouts::PayoutMethodData::Card(card) => { + payouts::PayoutMethodData::Card(card) => { let card_detail = api::CardDetail { card_number: card.card_number.to_owned(), card_holder_name: card.card_holder_name.to_owned(), @@ -206,7 +208,7 @@ pub async fn save_payout_data_to_locker( card_type: None, }; let payload = StoreLockerReq::LockerCard(StoreCardReq { - merchant_id: &merchant_account.merchant_id, + merchant_id: merchant_account.merchant_id.as_ref(), merchant_customer_id: payout_attempt.customer_id.to_owned(), card: transformers::Card { card_number: card.card_number.to_owned(), @@ -250,31 +252,32 @@ pub async fn save_payout_data_to_locker( Ok(hex::encode(e.peek())) })?; let payload = StoreLockerReq::LockerGeneric(StoreGenericReq { - merchant_id: &merchant_account.merchant_id, + merchant_id: merchant_account.merchant_id.as_ref(), merchant_customer_id: payout_attempt.customer_id.to_owned(), enc_data, }); match payout_method_data { - api_models::payouts::PayoutMethodData::Bank(bank) => ( + payouts::PayoutMethodData::Bank(bank) => ( payload, None, Some(bank.to_owned()), None, api_enums::PaymentMethodType::foreign_from(bank.to_owned()), ), - api_models::payouts::PayoutMethodData::Wallet(wallet) => ( + payouts::PayoutMethodData::Wallet(wallet) => ( payload, None, None, Some(wallet.to_owned()), api_enums::PaymentMethodType::foreign_from(wallet.to_owned()), ), - api_models::payouts::PayoutMethodData::Card(_) => { + payouts::PayoutMethodData::Card(_) => { Err(errors::ApiErrorResponse::InternalServerError)? } } } }; + // Store payout method in locker let stored_resp = cards::call_to_locker_hs( state, @@ -285,113 +288,272 @@ pub async fn save_payout_data_to_locker( .await .change_context(errors::ApiErrorResponse::InternalServerError)?; - // Store card_reference in payouts table let db = &*state.store; - let updated_payout = storage::PayoutsUpdate::PayoutMethodIdUpdate { - payout_method_id: Some(stored_resp.card_reference.to_owned()), + + // Handle duplicates + let (should_insert_in_pm_table, metadata_update) = match stored_resp.duplication_check { + // Check if equivalent entry exists in payment_methods + Some(duplication_check) => { + let locker_ref = stored_resp.card_reference.clone(); + + // Use locker ref as payment_method_id + let existing_pm_by_pmid = db.find_payment_method(&locker_ref).await; + + match existing_pm_by_pmid { + // If found, update locker's metadata [DELETE + INSERT OP], don't insert in payment_method's table + Ok(pm) => ( + false, + if duplication_check == DataDuplicationCheck::MetaDataChanged { + Some(pm.clone()) + } else { + None + }, + ), + + // If not found, use locker ref as locker_id + Err(err) => { + if err.current_context().is_db_not_found() { + match db.find_payment_method_by_locker_id(&locker_ref).await { + // If found, update locker's metadata [DELETE + INSERT OP], don't insert in payment_methods table + Ok(pm) => ( + false, + if duplication_check == DataDuplicationCheck::MetaDataChanged { + Some(pm.clone()) + } else { + None + }, + ), + Err(err) => { + // If not found, update locker's metadata [DELETE + INSERT OP], and insert in payment_methods table + if err.current_context().is_db_not_found() { + (true, None) + + // Misc. DB errors + } else { + Err(err) + .change_context( + errors::ApiErrorResponse::InternalServerError, + ) + .attach_printable( + "DB failures while finding payment method by locker ID", + )? + } + } + } + // Misc. DB errors + } else { + Err(err) + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("DB failures while finding payment method by pm ID")? + } + } + } + } + + // Not duplicate, should be inserted in payment_methods table + None => (true, None), }; - db.update_payout( - &payout_data.payouts, - updated_payout, - merchant_account.storage_scheme, - ) - .await - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Error updating payouts in saved payout method")?; - // fetch card info from db - let card_isin = card_details - .as_ref() - .map(|c| c.card_number.clone().get_card_isin()); + // Form payment method entry and card's metadata whenever insertion or metadata update is required + let (card_details_encrypted, new_payment_method) = + if let (api::PayoutMethodData::Card(_), true, _) + | (api::PayoutMethodData::Card(_), _, Some(_)) = ( + payout_method_data, + should_insert_in_pm_table, + metadata_update.as_ref(), + ) { + // Fetch card info from db + let card_isin = card_details + .as_ref() + .map(|c| c.card_number.clone().get_card_isin()); + + let mut payment_method = api::PaymentMethodCreate { + payment_method: api_enums::PaymentMethod::foreign_from( + payout_method_data.to_owned(), + ), + payment_method_type: Some(payment_method_type), + payment_method_issuer: None, + payment_method_issuer_code: None, + bank_transfer: None, + card: card_details.clone(), + wallet: None, + metadata: None, + customer_id: Some(payout_attempt.customer_id.to_owned()), + card_network: None, + }; - let pm_data = card_isin - .clone() - .async_and_then(|card_isin| async move { - db.get_card_info(&card_isin) + let pm_data = card_isin + .clone() + .async_and_then(|card_isin| async move { + db.get_card_info(&card_isin) + .await + .map_err(|error| services::logger::warn!(card_info_error=?error)) + .ok() + }) .await - .map_err(|error| services::logger::warn!(card_info_error=?error)) - .ok() - }) - .await - .flatten() - .map(|card_info| { - api::payment_methods::PaymentMethodsData::Card( - api::payment_methods::CardDetailsPaymentMethod { - last4_digits: card_details - .as_ref() - .map(|c| c.card_number.clone().get_last4()), - issuer_country: card_info.card_issuing_country, - expiry_month: card_details.as_ref().map(|c| c.card_exp_month.clone()), - expiry_year: card_details.as_ref().map(|c| c.card_exp_year.clone()), - nick_name: card_details.as_ref().and_then(|c| c.nick_name.clone()), - card_holder_name: card_details - .as_ref() - .and_then(|c| c.card_holder_name.clone()), - - card_isin: card_isin.clone(), - card_issuer: card_info.card_issuer, - card_network: card_info.card_network, - card_type: card_info.card_type, - saved_to_locker: true, - }, + .flatten() + .map(|card_info| { + payment_method.payment_method_issuer = card_info.card_issuer.clone(); + payment_method.card_network = + card_info.card_network.clone().map(|cn| cn.to_string()); + api::payment_methods::PaymentMethodsData::Card( + api::payment_methods::CardDetailsPaymentMethod { + last4_digits: card_details + .as_ref() + .map(|c| c.card_number.clone().get_last4()), + issuer_country: card_info.card_issuing_country, + expiry_month: card_details.as_ref().map(|c| c.card_exp_month.clone()), + expiry_year: card_details.as_ref().map(|c| c.card_exp_year.clone()), + nick_name: card_details.as_ref().and_then(|c| c.nick_name.clone()), + card_holder_name: card_details + .as_ref() + .and_then(|c| c.card_holder_name.clone()), + + card_isin: card_isin.clone(), + card_issuer: card_info.card_issuer, + card_network: card_info.card_network, + card_type: card_info.card_type, + saved_to_locker: true, + }, + ) + }) + .unwrap_or_else(|| { + api::payment_methods::PaymentMethodsData::Card( + api::payment_methods::CardDetailsPaymentMethod { + last4_digits: card_details + .as_ref() + .map(|c| c.card_number.clone().get_last4()), + issuer_country: None, + expiry_month: card_details.as_ref().map(|c| c.card_exp_month.clone()), + expiry_year: card_details.as_ref().map(|c| c.card_exp_year.clone()), + nick_name: card_details.as_ref().and_then(|c| c.nick_name.clone()), + card_holder_name: card_details + .as_ref() + .and_then(|c| c.card_holder_name.clone()), + + card_isin: card_isin.clone(), + card_issuer: None, + card_network: None, + card_type: None, + saved_to_locker: true, + }, + ) + }); + ( + cards::create_encrypted_payment_method_data(key_store, Some(pm_data)).await, + payment_method, ) - }) - .unwrap_or_else(|| { - api::payment_methods::PaymentMethodsData::Card( - api::payment_methods::CardDetailsPaymentMethod { - last4_digits: card_details - .as_ref() - .map(|c| c.card_number.clone().get_last4()), - issuer_country: None, - expiry_month: card_details.as_ref().map(|c| c.card_exp_month.clone()), - expiry_year: card_details.as_ref().map(|c| c.card_exp_year.clone()), - nick_name: card_details.as_ref().and_then(|c| c.nick_name.clone()), - card_holder_name: card_details - .as_ref() - .and_then(|c| c.card_holder_name.clone()), - - card_isin: card_isin.clone(), - card_issuer: None, + } else { + ( + None, + api::PaymentMethodCreate { + payment_method: api_enums::PaymentMethod::foreign_from( + payout_method_data.to_owned(), + ), + payment_method_type: Some(payment_method_type), + payment_method_issuer: None, + payment_method_issuer_code: None, + bank_transfer: bank_details, + card: None, + wallet: wallet_details, + metadata: None, + customer_id: Some(payout_attempt.customer_id.to_owned()), card_network: None, - card_type: None, - saved_to_locker: true, }, ) - }); - - let card_details_encrypted = - cards::create_encrypted_payment_method_data(key_store, Some(pm_data)).await; - - // Insert in payment_method table - let payment_method = api::PaymentMethodCreate { - payment_method: api_enums::PaymentMethod::foreign_from(payout_method_data.to_owned()), - payment_method_type: Some(payment_method_type), - payment_method_issuer: None, - payment_method_issuer_code: None, - bank_transfer: bank_details, - card: card_details, - wallet: wallet_details, - metadata: None, - customer_id: Some(payout_attempt.customer_id.to_owned()), - card_network: None, + }; + + // Insert new entry in payment_methods table + if should_insert_in_pm_table { + let payment_method_id = common_utils::generate_id(crate::consts::ID_LENGTH, "pm"); + cards::create_payment_method( + db, + &new_payment_method, + &payout_attempt.customer_id, + &payment_method_id, + Some(stored_resp.card_reference.clone()), + &merchant_account.merchant_id, + None, + None, + card_details_encrypted.clone(), + key_store, + None, + None, + ) + .await?; + } + + /* 1. Delete from locker + * 2. Create new entry in locker + * 3. Handle creation response from locker + * 4. Update card's metadata in payment_methods table + */ + if let Some(existing_pm) = metadata_update { + let card_reference = &existing_pm + .locker_id + .clone() + .unwrap_or(existing_pm.payment_method_id.clone()); + // Delete from locker + cards::delete_card_from_hs_locker( + state, + &payout_attempt.customer_id, + &merchant_account.merchant_id, + card_reference, + ) + .await + .attach_printable( + "Failed to delete PMD from locker as a part of metadata update operation", + )?; + + locker_req.update_requestor_card_reference(Some(card_reference.to_string())); + + // Store in locker + let stored_resp = cards::call_to_locker_hs( + state, + &locker_req, + &payout_attempt.customer_id, + api_enums::LockerChoice::HyperswitchCardVault, + ) + .await + .change_context(errors::ApiErrorResponse::InternalServerError); + + // Check if locker operation was successful or not, if not, delete the entry from payment_methods table + if let Err(err) = stored_resp { + logger::error!(vault_err=?err); + db.delete_payment_method_by_merchant_id_payment_method_id( + &merchant_account.merchant_id, + &existing_pm.payment_method_id, + ) + .await + .to_not_found_response(errors::ApiErrorResponse::PaymentMethodNotFound)?; + + Err(errors::ApiErrorResponse::InternalServerError).attach_printable( + "Failed to insert PMD from locker as a part of metadata update operation", + )? + }; + + // Update card's metadata in payment_methods table + let pm_update = storage::PaymentMethodUpdate::PaymentMethodDataUpdate { + payment_method_data: card_details_encrypted, + }; + db.update_payment_method(existing_pm, pm_update) + .await + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Failed to add payment method in db")?; }; - let payment_method_id = common_utils::generate_id(crate::consts::ID_LENGTH, "pm"); - cards::create_payment_method( - db, - &payment_method, - &payout_attempt.customer_id, - &payment_method_id, - Some(stored_resp.card_reference), - &merchant_account.merchant_id, - None, - None, - card_details_encrypted, - key_store, - None, - None, + // Store card_reference in payouts table + let updated_payout = storage::PayoutsUpdate::PayoutMethodIdUpdate { + payout_method_id: stored_resp.card_reference.to_owned(), + }; + db.update_payout( + &payout_data.payouts, + updated_payout, + merchant_account.storage_scheme, ) - .await?; + .await + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Error updating payouts in saved payout method")?; Ok(()) } @@ -626,7 +788,7 @@ pub fn should_call_payout_connector_create_customer<'a>( connector_label: &str, ) -> (bool, Option<&'a str>) { // Check if create customer is required for the connector - match PayoutConnectors::try_from(connector.connector_name) { + match enums::PayoutConnectors::try_from(connector.connector_name) { Ok(connector) => { let connector_needs_customer = state .conf diff --git a/crates/router/src/db/kafka_store.rs b/crates/router/src/db/kafka_store.rs index 427c66daa077..e24dde449d39 100644 --- a/crates/router/src/db/kafka_store.rs +++ b/crates/router/src/db/kafka_store.rs @@ -1608,8 +1608,14 @@ impl PayoutsInterface for KafkaStore { merchant_id: &str, filters: &data_models::payouts::PayoutFetchConstraints, storage_scheme: MerchantStorageScheme, - ) -> CustomResult, errors::DataStorageError> - { + ) -> CustomResult< + Vec<( + storage::Payouts, + storage::PayoutAttempt, + diesel_models::Customer, + )>, + errors::DataStorageError, + > { self.diesel_store .filter_payouts_and_attempts(merchant_id, filters, storage_scheme) .await diff --git a/crates/router/src/routes/payouts.rs b/crates/router/src/routes/payouts.rs index 0eeb0f27f076..2a429126c850 100644 --- a/crates/router/src/routes/payouts.rs +++ b/crates/router/src/routes/payouts.rs @@ -228,7 +228,7 @@ pub async fn payouts_list( state, &req, payload, - |state, auth, req| payouts_list_core(state, auth.merchant_account, req), + |state, auth, req| payouts_list_core(state, auth.merchant_account, auth.key_store, req), auth::auth_type( &auth::ApiKeyAuth, &auth::JWTAuth(Permission::PayoutRead), @@ -266,7 +266,9 @@ pub async fn payouts_list_by_filter( state, &req, payload, - |state, auth, req| payouts_filtered_list_core(state, auth.merchant_account, req), + |state, auth, req| { + payouts_filtered_list_core(state, auth.merchant_account, auth.key_store, req) + }, auth::auth_type( &auth::ApiKeyAuth, &auth::JWTAuth(Permission::PayoutRead), diff --git a/crates/router/src/services/authentication.rs b/crates/router/src/services/authentication.rs index d2247150d3c5..f7acbe6f933c 100644 --- a/crates/router/src/services/authentication.rs +++ b/crates/router/src/services/authentication.rs @@ -5,6 +5,7 @@ use common_utils::date_time; use error_stack::{report, ResultExt}; use jsonwebtoken::{decode, Algorithm, DecodingKey, Validation}; use masking::PeekInterface; +use router_env::logger; use serde::Serialize; use self::blacklist::BlackList; @@ -33,7 +34,6 @@ use crate::{ utils::OptionExt, }; pub mod blacklist; -#[cfg(feature = "olap")] pub mod cookies; #[derive(Clone, Debug)] @@ -598,6 +598,15 @@ where A: AppStateInfo + Sync, { let token = get_jwt_from_authorization_header(headers)?; + if let Some(token_from_cookies) = get_cookie_from_header(headers) + .ok() + .and_then(|cookies| cookies::parse_cookie(cookies).ok()) + { + logger::info!( + "Cookie header and authorization header JWT comparison result: {}", + token == token_from_cookies + ); + } let payload = decode_jwt(token, state).await?; Ok(payload) @@ -959,6 +968,13 @@ pub fn get_jwt_from_authorization_header(headers: &HeaderMap) -> RouterResult<&s .ok_or(errors::ApiErrorResponse::InvalidJwtToken.into()) } +pub fn get_cookie_from_header(headers: &HeaderMap) -> RouterResult<&str> { + headers + .get(cookies::get_cookie_header()) + .and_then(|header_value| header_value.to_str().ok()) + .ok_or(errors::ApiErrorResponse::InvalidCookie.into()) +} + pub fn strip_jwt_token(token: &str) -> RouterResult<&str> { token .strip_prefix("Bearer ") diff --git a/crates/router/src/services/authentication/cookies.rs b/crates/router/src/services/authentication/cookies.rs index d7fc4c10315d..965188408004 100644 --- a/crates/router/src/services/authentication/cookies.rs +++ b/crates/router/src/services/authentication/cookies.rs @@ -1,15 +1,27 @@ +use cookie::Cookie; +#[cfg(feature = "olap")] use cookie::{ time::{Duration, OffsetDateTime}, - Cookie, SameSite, + SameSite, }; -use masking::{ExposeInterface, Mask, Secret}; +use error_stack::{report, ResultExt}; +#[cfg(feature = "olap")] +use masking::Mask; +#[cfg(feature = "olap")] +use masking::{ExposeInterface, Secret}; use crate::{ - consts::{JWT_TOKEN_COOKIE_NAME, JWT_TOKEN_TIME_IN_SECS}, + consts::JWT_TOKEN_COOKIE_NAME, + core::errors::{ApiErrorResponse, RouterResult}, +}; +#[cfg(feature = "olap")] +use crate::{ + consts::JWT_TOKEN_TIME_IN_SECS, core::errors::{UserErrors, UserResponse}, services::ApplicationResponse, }; +#[cfg(feature = "olap")] pub fn set_cookie_response(response: R, token: Secret) -> UserResponse { let jwt_expiry_in_seconds = JWT_TOKEN_TIME_IN_SECS .try_into() @@ -19,16 +31,17 @@ pub fn set_cookie_response(response: R, token: Secret) -> UserRespons let header_value = create_cookie(token, expiry, max_age) .to_string() .into_masked(); - let header_key = get_cookie_header(); + let header_key = get_set_cookie_header(); let header = vec![(header_key, header_value)]; Ok(ApplicationResponse::JsonWithHeaders((response, header))) } +#[cfg(feature = "olap")] pub fn remove_cookie_response() -> UserResponse<()> { let (expiry, max_age) = get_expiry_and_max_age_from_seconds(0); - let header_key = get_cookie_header(); + let header_key = get_set_cookie_header(); let header_value = create_cookie("".to_string().into(), expiry, max_age) .to_string() .into_masked(); @@ -36,6 +49,19 @@ pub fn remove_cookie_response() -> UserResponse<()> { Ok(ApplicationResponse::JsonWithHeaders(((), header))) } +pub fn parse_cookie(cookies: &str) -> RouterResult { + Cookie::split_parse(cookies) + .find_map(|cookie| { + cookie + .ok() + .filter(|parsed_cookie| parsed_cookie.name() == JWT_TOKEN_COOKIE_NAME) + .map(|parsed_cookie| parsed_cookie.value().to_owned()) + }) + .ok_or(report!(ApiErrorResponse::InvalidCookie)) + .attach_printable("Cookie Parsing Failed") +} + +#[cfg(feature = "olap")] fn create_cookie<'c>( token: Secret, expires: OffsetDateTime, @@ -51,12 +77,18 @@ fn create_cookie<'c>( .build() } +#[cfg(feature = "olap")] fn get_expiry_and_max_age_from_seconds(seconds: i64) -> (OffsetDateTime, Duration) { let max_age = Duration::seconds(seconds); let expiry = OffsetDateTime::now_utc().saturating_add(max_age); (expiry, max_age) } -fn get_cookie_header() -> String { +#[cfg(feature = "olap")] +fn get_set_cookie_header() -> String { actix_http::header::SET_COOKIE.to_string() } + +pub fn get_cookie_header() -> String { + actix_http::header::COOKIE.to_string() +} diff --git a/crates/router/src/types/domain/payments.rs b/crates/router/src/types/domain/payments.rs index 0ec67ffa91c8..b8285fbdc9a6 100644 --- a/crates/router/src/types/domain/payments.rs +++ b/crates/router/src/types/domain/payments.rs @@ -10,8 +10,8 @@ pub enum PaymentMethodData { Card(Card), CardRedirect(CardRedirectData), Wallet(WalletData), - PayLater(api_models::payments::PayLaterData), - BankRedirect(api_models::payments::BankRedirectData), + PayLater(PayLaterData), + BankRedirect(BankRedirectData), BankDebit(api_models::payments::BankDebitData), BankTransfer(Box), Crypto(api_models::payments::CryptoData), @@ -66,7 +66,7 @@ pub enum CardRedirectData { CardRedirect {}, } -#[derive(Eq, PartialEq, Clone, Debug)] +#[derive(Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)] pub enum PayLaterData { KlarnaRedirect { billing_email: Email, @@ -243,7 +243,7 @@ pub struct ApplepayPaymentMethod { pub pm_type: String, } -#[derive(Debug, Clone, Eq, PartialEq)] +#[derive(Debug, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize, ToSchema)] pub enum BankRedirectData { BancontactCard { @@ -313,7 +313,7 @@ pub enum BankRedirectData { }, } -#[derive(Debug, Clone, Eq, PartialEq)] +#[derive(Debug, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize, ToSchema)] pub struct BankRedirectBilling { pub billing_name: Option>, pub email: Option, @@ -332,10 +332,10 @@ impl From for PaymentMethodData { Self::Wallet(From::from(wallet_data)) } api_models::payments::PaymentMethodData::PayLater(pay_later_data) => { - Self::PayLater(pay_later_data) + Self::PayLater(From::from(pay_later_data)) } api_models::payments::PaymentMethodData::BankRedirect(bank_redirect_data) => { - Self::BankRedirect(bank_redirect_data) + Self::BankRedirect(From::from(bank_redirect_data)) } api_models::payments::PaymentMethodData::BankDebit(bank_debit_data) => { Self::BankDebit(bank_debit_data) @@ -518,3 +518,136 @@ impl From for ApplePayWalletData { } } } + +impl From for PayLaterData { + fn from(value: api_models::payments::PayLaterData) -> Self { + match value { + api_models::payments::PayLaterData::KlarnaRedirect { + billing_email, + billing_country, + } => Self::KlarnaRedirect { + billing_email, + billing_country, + }, + api_models::payments::PayLaterData::KlarnaSdk { token } => Self::KlarnaSdk { token }, + api_models::payments::PayLaterData::AffirmRedirect {} => Self::AffirmRedirect {}, + api_models::payments::PayLaterData::AfterpayClearpayRedirect { + billing_email, + billing_name, + } => Self::AfterpayClearpayRedirect { + billing_email, + billing_name, + }, + api_models::payments::PayLaterData::PayBrightRedirect {} => Self::PayBrightRedirect {}, + api_models::payments::PayLaterData::WalleyRedirect {} => Self::WalleyRedirect {}, + api_models::payments::PayLaterData::AlmaRedirect {} => Self::AlmaRedirect {}, + api_models::payments::PayLaterData::AtomeRedirect {} => Self::AtomeRedirect {}, + } + } +} + +impl From for BankRedirectData { + fn from(value: api_models::payments::BankRedirectData) -> Self { + match value { + api_models::payments::BankRedirectData::BancontactCard { + card_number, + card_exp_month, + card_exp_year, + card_holder_name, + billing_details, + } => Self::BancontactCard { + card_number, + card_exp_month, + card_exp_year, + card_holder_name, + billing_details: billing_details.map(BankRedirectBilling::from), + }, + api_models::payments::BankRedirectData::Bizum {} => Self::Bizum {}, + api_models::payments::BankRedirectData::Blik { blik_code } => Self::Blik { blik_code }, + api_models::payments::BankRedirectData::Eps { + billing_details, + bank_name, + country, + } => Self::Eps { + billing_details: billing_details.map(BankRedirectBilling::from), + bank_name, + country, + }, + api_models::payments::BankRedirectData::Giropay { + billing_details, + bank_account_bic, + bank_account_iban, + country, + } => Self::Giropay { + billing_details: billing_details.map(BankRedirectBilling::from), + bank_account_bic, + bank_account_iban, + country, + }, + api_models::payments::BankRedirectData::Ideal { + billing_details, + bank_name, + country, + } => Self::Ideal { + billing_details: billing_details.map(BankRedirectBilling::from), + bank_name, + country, + }, + api_models::payments::BankRedirectData::Interac { country, email } => { + Self::Interac { country, email } + } + api_models::payments::BankRedirectData::OnlineBankingCzechRepublic { issuer } => { + Self::OnlineBankingCzechRepublic { issuer } + } + api_models::payments::BankRedirectData::OnlineBankingFinland { email } => { + Self::OnlineBankingFinland { email } + } + api_models::payments::BankRedirectData::OnlineBankingPoland { issuer } => { + Self::OnlineBankingPoland { issuer } + } + api_models::payments::BankRedirectData::OnlineBankingSlovakia { issuer } => { + Self::OnlineBankingSlovakia { issuer } + } + api_models::payments::BankRedirectData::OpenBankingUk { issuer, country } => { + Self::OpenBankingUk { issuer, country } + } + api_models::payments::BankRedirectData::Przelewy24 { + bank_name, + billing_details, + } => Self::Przelewy24 { + bank_name, + billing_details: BankRedirectBilling { + billing_name: billing_details.billing_name, + email: billing_details.email, + }, + }, + api_models::payments::BankRedirectData::Sofort { + billing_details, + country, + preferred_language, + } => Self::Sofort { + billing_details: billing_details.map(BankRedirectBilling::from), + country, + preferred_language, + }, + api_models::payments::BankRedirectData::Trustly { country } => { + Self::Trustly { country } + } + api_models::payments::BankRedirectData::OnlineBankingFpx { issuer } => { + Self::OnlineBankingFpx { issuer } + } + api_models::payments::BankRedirectData::OnlineBankingThailand { issuer } => { + Self::OnlineBankingThailand { issuer } + } + } + } +} + +impl From for BankRedirectBilling { + fn from(billing: api_models::payments::BankRedirectBilling) -> Self { + Self { + billing_name: billing.billing_name, + email: billing.email, + } + } +} diff --git a/crates/router/src/types/transformers.rs b/crates/router/src/types/transformers.rs index 3362aad6fc55..c5250b0cc73b 100644 --- a/crates/router/src/types/transformers.rs +++ b/crates/router/src/types/transformers.rs @@ -453,6 +453,7 @@ impl ForeignFrom for api_enums::PaymentMethod { | api_enums::PaymentMethodType::CimbVa | api_enums::PaymentMethodType::DanamonVa | api_enums::PaymentMethodType::MandiriVa + | api_enums::PaymentMethodType::LocalBankTransfer | api_enums::PaymentMethodType::Pix => Self::BankTransfer, api_enums::PaymentMethodType::Givex | api_enums::PaymentMethodType::PaySafeCard => { Self::GiftCard diff --git a/crates/router/tests/connectors/ebanx.rs b/crates/router/tests/connectors/ebanx.rs new file mode 100644 index 000000000000..5ef703469eaa --- /dev/null +++ b/crates/router/tests/connectors/ebanx.rs @@ -0,0 +1,437 @@ +use masking::Secret; +use router::types::{self, storage::enums}; +use test_utils::connector_auth; + +use crate::utils::{self, ConnectorActions}; + +#[derive(Clone, Copy)] +struct EbanxTest; +impl ConnectorActions for EbanxTest {} +impl utils::Connector for EbanxTest { + fn get_data(&self) -> types::api::ConnectorData { + use router::connector::Ebanx; + types::api::ConnectorData { + connector: Box::new(&Ebanx), + connector_name: types::Connector::Adyen, + get_token: types::api::GetToken::Connector, + merchant_connector_id: None, + } + } + + #[cfg(feature = "payouts")] + fn get_payout_data(&self) -> Option { + use router::connector::Ebanx; + Some(types::api::ConnectorData { + connector: Box::new(&Ebanx), + connector_name: types::Connector::Adyen, + get_token: types::api::GetToken::Connector, + merchant_connector_id: None, + }) + } + + fn get_auth_token(&self) -> types::ConnectorAuthType { + utils::to_connector_auth_type( + connector_auth::ConnectorAuthentication::new() + .ebanx + .expect("Missing connector authentication configuration") + .into(), + ) + } + + fn get_name(&self) -> String { + "ebanx".to_string() + } +} + +static CONNECTOR: EbanxTest = EbanxTest {}; + +fn get_default_payment_info() -> Option { + None +} + +fn payment_method_details() -> Option { + None +} + +// Cards Positive Tests +// Creates a payment using the manual capture flow (Non 3DS). +#[actix_web::test] +async fn should_only_authorize_payment() { + let response = CONNECTOR + .authorize_payment(payment_method_details(), get_default_payment_info()) + .await + .expect("Authorize payment response"); + assert_eq!(response.status, enums::AttemptStatus::Authorized); +} + +// Captures a payment using the manual capture flow (Non 3DS). +#[actix_web::test] +async fn should_capture_authorized_payment() { + let response = CONNECTOR + .authorize_and_capture_payment(payment_method_details(), None, get_default_payment_info()) + .await + .expect("Capture payment response"); + assert_eq!(response.status, enums::AttemptStatus::Charged); +} + +// Partially captures a payment using the manual capture flow (Non 3DS). +#[actix_web::test] +async fn should_partially_capture_authorized_payment() { + let response = CONNECTOR + .authorize_and_capture_payment( + payment_method_details(), + Some(types::PaymentsCaptureData { + amount_to_capture: 50, + ..utils::PaymentCaptureType::default().0 + }), + get_default_payment_info(), + ) + .await + .expect("Capture payment response"); + assert_eq!(response.status, enums::AttemptStatus::Charged); +} + +// Synchronizes a payment using the manual capture flow (Non 3DS). +#[actix_web::test] +async fn should_sync_authorized_payment() { + let authorize_response = CONNECTOR + .authorize_payment(payment_method_details(), get_default_payment_info()) + .await + .expect("Authorize payment response"); + let txn_id = utils::get_connector_transaction_id(authorize_response.response); + let response = CONNECTOR + .psync_retry_till_status_matches( + enums::AttemptStatus::Authorized, + Some(types::PaymentsSyncData { + connector_transaction_id: router::types::ResponseId::ConnectorTransactionId( + txn_id.unwrap(), + ), + ..Default::default() + }), + get_default_payment_info(), + ) + .await + .expect("PSync response"); + assert_eq!(response.status, enums::AttemptStatus::Authorized,); +} + +// Voids a payment using the manual capture flow (Non 3DS). +#[actix_web::test] +async fn should_void_authorized_payment() { + let response = CONNECTOR + .authorize_and_void_payment( + payment_method_details(), + Some(types::PaymentsCancelData { + connector_transaction_id: String::from(""), + cancellation_reason: Some("requested_by_customer".to_string()), + ..Default::default() + }), + get_default_payment_info(), + ) + .await + .expect("Void payment response"); + assert_eq!(response.status, enums::AttemptStatus::Voided); +} + +// Refunds a payment using the manual capture flow (Non 3DS). +#[actix_web::test] +async fn should_refund_manually_captured_payment() { + let response = CONNECTOR + .capture_payment_and_refund( + payment_method_details(), + None, + None, + get_default_payment_info(), + ) + .await + .unwrap(); + assert_eq!( + response.response.unwrap().refund_status, + enums::RefundStatus::Success, + ); +} + +// Partially refunds a payment using the manual capture flow (Non 3DS). +#[actix_web::test] +async fn should_partially_refund_manually_captured_payment() { + let response = CONNECTOR + .capture_payment_and_refund( + payment_method_details(), + None, + Some(types::RefundsData { + refund_amount: 50, + ..utils::PaymentRefundType::default().0 + }), + get_default_payment_info(), + ) + .await + .unwrap(); + assert_eq!( + response.response.unwrap().refund_status, + enums::RefundStatus::Success, + ); +} + +// Synchronizes a refund using the manual capture flow (Non 3DS). +#[actix_web::test] +async fn should_sync_manually_captured_refund() { + let refund_response = CONNECTOR + .capture_payment_and_refund( + payment_method_details(), + None, + None, + get_default_payment_info(), + ) + .await + .unwrap(); + let response = CONNECTOR + .rsync_retry_till_status_matches( + enums::RefundStatus::Success, + refund_response.response.unwrap().connector_refund_id, + None, + get_default_payment_info(), + ) + .await + .unwrap(); + assert_eq!( + response.response.unwrap().refund_status, + enums::RefundStatus::Success, + ); +} + +// Creates a payment using the automatic capture flow (Non 3DS). +#[actix_web::test] +async fn should_make_payment() { + let authorize_response = CONNECTOR + .make_payment(payment_method_details(), get_default_payment_info()) + .await + .unwrap(); + assert_eq!(authorize_response.status, enums::AttemptStatus::Charged); +} + +// Synchronizes a payment using the automatic capture flow (Non 3DS). +#[actix_web::test] +async fn should_sync_auto_captured_payment() { + let authorize_response = CONNECTOR + .make_payment(payment_method_details(), get_default_payment_info()) + .await + .unwrap(); + assert_eq!(authorize_response.status, enums::AttemptStatus::Charged); + let txn_id = utils::get_connector_transaction_id(authorize_response.response); + assert_ne!(txn_id, None, "Empty connector transaction id"); + let response = CONNECTOR + .psync_retry_till_status_matches( + enums::AttemptStatus::Charged, + Some(types::PaymentsSyncData { + connector_transaction_id: router::types::ResponseId::ConnectorTransactionId( + txn_id.unwrap(), + ), + capture_method: Some(enums::CaptureMethod::Automatic), + ..Default::default() + }), + get_default_payment_info(), + ) + .await + .unwrap(); + assert_eq!(response.status, enums::AttemptStatus::Charged,); +} + +// Refunds a payment using the automatic capture flow (Non 3DS). +#[actix_web::test] +async fn should_refund_auto_captured_payment() { + let response = CONNECTOR + .make_payment_and_refund(payment_method_details(), None, get_default_payment_info()) + .await + .unwrap(); + assert_eq!( + response.response.unwrap().refund_status, + enums::RefundStatus::Success, + ); +} + +// Partially refunds a payment using the automatic capture flow (Non 3DS). +#[actix_web::test] +async fn should_partially_refund_succeeded_payment() { + let refund_response = CONNECTOR + .make_payment_and_refund( + payment_method_details(), + Some(types::RefundsData { + refund_amount: 50, + ..utils::PaymentRefundType::default().0 + }), + get_default_payment_info(), + ) + .await + .unwrap(); + assert_eq!( + refund_response.response.unwrap().refund_status, + enums::RefundStatus::Success, + ); +} + +// Creates multiple refunds against a payment using the automatic capture flow (Non 3DS). +#[actix_web::test] +async fn should_refund_succeeded_payment_multiple_times() { + CONNECTOR + .make_payment_and_multiple_refund( + payment_method_details(), + Some(types::RefundsData { + refund_amount: 50, + ..utils::PaymentRefundType::default().0 + }), + get_default_payment_info(), + ) + .await; +} + +// Synchronizes a refund using the automatic capture flow (Non 3DS). +#[actix_web::test] +async fn should_sync_refund() { + let refund_response = CONNECTOR + .make_payment_and_refund(payment_method_details(), None, get_default_payment_info()) + .await + .unwrap(); + let response = CONNECTOR + .rsync_retry_till_status_matches( + enums::RefundStatus::Success, + refund_response.response.unwrap().connector_refund_id, + None, + get_default_payment_info(), + ) + .await + .unwrap(); + assert_eq!( + response.response.unwrap().refund_status, + enums::RefundStatus::Success, + ); +} + +// Cards Negative scenerios +// Creates a payment with incorrect CVC. +#[actix_web::test] +async fn should_fail_payment_for_incorrect_cvc() { + let response = CONNECTOR + .make_payment( + Some(types::PaymentsAuthorizeData { + payment_method_data: types::domain::payments::PaymentMethodData::Card( + types::domain::Card { + card_cvc: Secret::new("12345".to_string()), + ..utils::CCardType::default().0 + }, + ), + ..utils::PaymentAuthorizeType::default().0 + }), + get_default_payment_info(), + ) + .await + .unwrap(); + assert_eq!( + response.response.unwrap_err().message, + "Your card's security code is invalid.".to_string(), + ); +} + +// Creates a payment with incorrect expiry month. +#[actix_web::test] +async fn should_fail_payment_for_invalid_exp_month() { + let response = CONNECTOR + .make_payment( + Some(types::PaymentsAuthorizeData { + payment_method_data: types::domain::payments::PaymentMethodData::Card( + types::domain::Card { + card_exp_month: Secret::new("20".to_string()), + ..utils::CCardType::default().0 + }, + ), + ..utils::PaymentAuthorizeType::default().0 + }), + get_default_payment_info(), + ) + .await + .unwrap(); + assert_eq!( + response.response.unwrap_err().message, + "Your card's expiration month is invalid.".to_string(), + ); +} + +// Creates a payment with incorrect expiry year. +#[actix_web::test] +async fn should_fail_payment_for_incorrect_expiry_year() { + let response = CONNECTOR + .make_payment( + Some(types::PaymentsAuthorizeData { + payment_method_data: types::domain::payments::PaymentMethodData::Card( + types::domain::Card { + card_exp_year: Secret::new("2000".to_string()), + ..utils::CCardType::default().0 + }, + ), + ..utils::PaymentAuthorizeType::default().0 + }), + get_default_payment_info(), + ) + .await + .unwrap(); + assert_eq!( + response.response.unwrap_err().message, + "Your card's expiration year is invalid.".to_string(), + ); +} + +// Voids a payment using automatic capture flow (Non 3DS). +#[actix_web::test] +async fn should_fail_void_payment_for_auto_capture() { + let authorize_response = CONNECTOR + .make_payment(payment_method_details(), get_default_payment_info()) + .await + .unwrap(); + assert_eq!(authorize_response.status, enums::AttemptStatus::Charged); + let txn_id = utils::get_connector_transaction_id(authorize_response.response); + assert_ne!(txn_id, None, "Empty connector transaction id"); + let void_response = CONNECTOR + .void_payment(txn_id.unwrap(), None, get_default_payment_info()) + .await + .unwrap(); + assert_eq!( + void_response.response.unwrap_err().message, + "You cannot cancel this PaymentIntent because it has a status of succeeded." + ); +} + +// Captures a payment using invalid connector payment id. +#[actix_web::test] +async fn should_fail_capture_for_invalid_payment() { + let capture_response = CONNECTOR + .capture_payment("123456789".to_string(), None, get_default_payment_info()) + .await + .unwrap(); + assert_eq!( + capture_response.response.unwrap_err().message, + String::from("No such payment_intent: '123456789'") + ); +} + +// Refunds a payment with refund amount higher than payment amount. +#[actix_web::test] +async fn should_fail_for_refund_amount_higher_than_payment_amount() { + let response = CONNECTOR + .make_payment_and_refund( + payment_method_details(), + Some(types::RefundsData { + refund_amount: 150, + ..utils::PaymentRefundType::default().0 + }), + get_default_payment_info(), + ) + .await + .unwrap(); + assert_eq!( + response.response.unwrap_err().message, + "Refund amount (₹1.50) is greater than charge amount (₹1.00)", + ); +} + +// Connector dependent test cases goes here + +// [#478]: add unit tests for non 3DS, wallets & webhooks in connector tests diff --git a/crates/router/tests/connectors/main.rs b/crates/router/tests/connectors/main.rs index eb428a36cb95..1033953776b3 100644 --- a/crates/router/tests/connectors/main.rs +++ b/crates/router/tests/connectors/main.rs @@ -26,6 +26,7 @@ mod cybersource; mod dlocal; #[cfg(feature = "dummy_connector")] mod dummyconnector; +mod ebanx; mod fiserv; mod forte; mod globalpay; diff --git a/crates/router/tests/connectors/sample_auth.toml b/crates/router/tests/connectors/sample_auth.toml index bd17f279c2d0..5502629a8af7 100644 --- a/crates/router/tests/connectors/sample_auth.toml +++ b/crates/router/tests/connectors/sample_auth.toml @@ -202,3 +202,7 @@ api_key="API Key" [billwerk] api_key="API Key" + + +[ebanx] +api_key="API Key" diff --git a/crates/storage_impl/src/mock_db/payouts.rs b/crates/storage_impl/src/mock_db/payouts.rs index 1af052836963..323f3e11ac01 100644 --- a/crates/storage_impl/src/mock_db/payouts.rs +++ b/crates/storage_impl/src/mock_db/payouts.rs @@ -67,7 +67,7 @@ impl PayoutsInterface for MockDb { _merchant_id: &str, _filters: &data_models::payouts::PayoutFetchConstraints, _storage_scheme: storage_enums::MerchantStorageScheme, - ) -> CustomResult, StorageError> { + ) -> CustomResult, StorageError> { // TODO: Implement function for `MockDb` Err(StorageError::MockDbError)? } diff --git a/crates/storage_impl/src/payouts/payouts.rs b/crates/storage_impl/src/payouts/payouts.rs index c6ff6250d486..fd4dbc8e3aac 100644 --- a/crates/storage_impl/src/payouts/payouts.rs +++ b/crates/storage_impl/src/payouts/payouts.rs @@ -9,6 +9,13 @@ use data_models::{ }; #[cfg(feature = "olap")] use diesel::{associations::HasTable, ExpressionMethods, JoinOnDsl, QueryDsl}; +#[cfg(feature = "olap")] +use diesel_models::{ + customers::Customer as DieselCustomer, + payout_attempt::PayoutAttempt as DieselPayoutAttempt, + query::generics::db_metrics, + schema::{customers::dsl as cust_dsl, payout_attempt::dsl as poa_dsl, payouts::dsl as po_dsl}, +}; use diesel_models::{ enums::MerchantStorageScheme, kv, @@ -17,12 +24,6 @@ use diesel_models::{ PayoutsUpdate as DieselPayoutsUpdate, }, }; -#[cfg(feature = "olap")] -use diesel_models::{ - payout_attempt::PayoutAttempt as DieselPayoutAttempt, - query::generics::db_metrics, - schema::{payout_attempt::dsl as poa_dsl, payouts::dsl as po_dsl}, -}; use error_stack::ResultExt; use redis_interface::HsetnxReply; #[cfg(feature = "olap")] @@ -270,7 +271,8 @@ impl PayoutsInterface for KVRouterStore { merchant_id: &str, filters: &PayoutFetchConstraints, storage_scheme: MerchantStorageScheme, - ) -> error_stack::Result, StorageError> { + ) -> error_stack::Result, StorageError> + { self.router_store .filter_payouts_and_attempts(merchant_id, filters, storage_scheme) .await @@ -485,7 +487,7 @@ impl PayoutsInterface for crate::RouterStore { merchant_id: &str, filters: &PayoutFetchConstraints, storage_scheme: MerchantStorageScheme, - ) -> error_stack::Result, StorageError> { + ) -> error_stack::Result, StorageError> { use common_utils::errors::ReportSwitchExt; let conn = connection::pg_connection_read(self).await.switch()?; @@ -495,6 +497,10 @@ impl PayoutsInterface for crate::RouterStore { diesel_models::schema::payout_attempt::table .on(poa_dsl::payout_id.eq(po_dsl::payout_id)), ) + .inner_join( + diesel_models::schema::customers::table + .on(cust_dsl::customer_id.eq(po_dsl::customer_id)), + ) .filter(po_dsl::merchant_id.eq(merchant_id.to_owned())) .order(po_dsl::created_at.desc()) .into_boxed(); @@ -585,15 +591,16 @@ impl PayoutsInterface for crate::RouterStore { logger::debug!(filter = %diesel::debug_query::(&query).to_string()); query - .get_results_async::<(DieselPayouts, DieselPayoutAttempt)>(conn) + .get_results_async::<(DieselPayouts, DieselPayoutAttempt, DieselCustomer)>(conn) .await .map(|results| { results .into_iter() - .map(|(pi, pa)| { + .map(|(pi, pa, c)| { ( Payouts::from_storage_model(pi), PayoutAttempt::from_storage_model(pa), + c, ) }) .collect() @@ -765,6 +772,7 @@ impl DataModelExt for PayoutsUpdate { Self::AttemptCountUpdate { attempt_count } => { DieselPayoutsUpdate::AttemptCountUpdate { attempt_count } } + Self::StatusUpdate { status } => DieselPayoutsUpdate::StatusUpdate { status }, } } diff --git a/crates/test_utils/src/connector_auth.rs b/crates/test_utils/src/connector_auth.rs index 34a5e35928df..6666f9883f8d 100644 --- a/crates/test_utils/src/connector_auth.rs +++ b/crates/test_utils/src/connector_auth.rs @@ -30,6 +30,7 @@ pub struct ConnectorAuthentication { pub dlocal: Option, #[cfg(feature = "dummy_connector")] pub dummyconnector: Option, + pub ebanx: Option, pub fiserv: Option, pub forte: Option, pub globalpay: Option, diff --git a/loadtest/config/development.toml b/loadtest/config/development.toml index a37fc6de0589..3a71072910b7 100644 --- a/loadtest/config/development.toml +++ b/loadtest/config/development.toml @@ -86,6 +86,7 @@ cryptopay.base_url = "https://business-sandbox.cryptopay.me" cybersource.base_url = "https://apitest.cybersource.com/" dlocal.base_url = "https://sandbox.dlocal.com/" dummyconnector.base_url = "http://localhost:8080/dummy-connector" +ebanx.base_url = "https://sandbox.ebanxpay.com/" fiserv.base_url = "https://cert.api.fiservapps.com/" forte.base_url = "https://sandbox.forte.net/api/v3" globalpay.base_url = "https://apis.sandbox.globalpay.com/ucp/" @@ -155,6 +156,7 @@ cards = [ "cybersource", "dlocal", "dummyconnector", + "ebanx", "fiserv", "forte", "globalpay", diff --git a/openapi/openapi_spec.json b/openapi/openapi_spec.json index 46687fcc9cb7..1af82da7f591 100644 --- a/openapi/openapi_spec.json +++ b/openapi/openapi_spec.json @@ -6242,6 +6242,23 @@ "type": "object" } } + }, + { + "type": "object", + "required": [ + "local_bank_transfer" + ], + "properties": { + "local_bank_transfer": { + "type": "object", + "properties": { + "bank_code": { + "type": "string", + "nullable": true + } + } + } + } } ] }, @@ -12870,7 +12887,8 @@ "mini_stop", "family_mart", "seicomart", - "pay_easy" + "pay_easy", + "local_bank_transfer" ] }, "PaymentMethodUpdate": { @@ -15430,11 +15448,6 @@ "description": "If the payout was cancelled the reason provided here", "nullable": true }, - "payout_token": { - "type": "string", - "description": "Provide a reference to a stored payout method", - "nullable": true - }, "unified_code": { "type": "string", "description": "error code unified across the connectors is received here if there was an error while calling connector", diff --git a/scripts/add_connector.sh b/scripts/add_connector.sh index 9098be40e218..c05eb558afa2 100755 --- a/scripts/add_connector.sh +++ b/scripts/add_connector.sh @@ -6,7 +6,7 @@ function find_prev_connector() { git checkout $self cp $self $self.tmp # Add new connector to existing list and sort it - connectors=(aci adyen airwallex applepay authorizedotnet bambora bankofamerica billwerk bitpay bluesnap boku braintree cashtocode checkout coinbase cryptopay cybersource dlocal dummyconnector fiserv forte globalpay globepay gocardless helcim iatapay klarna mollie multisafepay nexinets noon nuvei opayo opennode payeezy payme paypal payu placetopay powertranz prophetpay rapyd shift4 square stax stripe threedsecureio trustpay tsys volt wise worldline worldpay "$1") + connectors=(aci adyen airwallex applepay authorizedotnet bambora bankofamerica billwerk bitpay bluesnap boku braintree cashtocode checkout coinbase cryptopay cybersource dlocal dummyconnector ebanx fiserv forte globalpay globepay gocardless helcim iatapay klarna mollie multisafepay nexinets noon nuvei opayo opennode payeezy payme paypal payu placetopay powertranz prophetpay rapyd shift4 square stax stripe threedsecureio trustpay tsys volt wise worldline worldpay "$1") IFS=$'\n' sorted=($(sort <<<"${connectors[*]}")); unset IFS res=`echo ${sorted[@]}` sed -i'' -e "s/^ connectors=.*/ connectors=($res \"\$1\")/" $self.tmp