diff --git a/Cargo.lock b/Cargo.lock index d835074cfe..4b51d433be 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8379,6 +8379,7 @@ dependencies = [ "async-trait", "base64 0.22.1", "clap", + "common_enums", "masking", "rand 0.8.5", "regex", diff --git a/config/config.example.toml b/config/config.example.toml index 602f6a0a1d..5967731b9a 100644 --- a/config/config.example.toml +++ b/config/config.example.toml @@ -735,6 +735,10 @@ crypto_currency = { country = "US, CA, GB, AT, BE, BG, HR, CY, CZ, DK, EE, FI, F debit = { country = "FR", currency = "CAD, AUD, EUR, USD" } credit = { country = "FR", currency = "CAD, AUD, EUR, USD" } +[pm_filters.payload] +debit = { currency = "USD,CAD" } +credit = { currency = "USD,CAD" } + [pm_filters.digitalvirgo] direct_carrier_billing = {country = "MA, CM, ZA, EG, SN, DZ, TN, ML, GN, GH, LY, GA, CG, MG, BW, SD, NG, ID, SG, AZ, TR, FR, ES, PL, GB, PT, DE, IT, BE, IE, SK, GR, NL, CH, BR, MX, AR, CL, AE, IQ, KW, BH, SA, QA, PS, JO, OM, RU" , currency = "MAD, XOF, XAF, ZAR, EGP, DZD, TND, GNF, GHS, LYD, XAF, CDF, MGA, BWP, SDG, NGN, IDR, SGD, RUB, AZN, TRY, EUR, PLN, GBP, CHF, BRL, MXN, ARS, CLP, AED, IQD, KWD, BHD, SAR, QAR, ILS, JOD, OMR" } diff --git a/config/deployments/integration_test.toml b/config/deployments/integration_test.toml index cc000bba6f..9ef3b802fa 100644 --- a/config/deployments/integration_test.toml +++ b/config/deployments/integration_test.toml @@ -223,8 +223,8 @@ bank_debit.ach = { connector_list = "gocardless,adyen,stripe" } bank_debit.becs = { connector_list = "gocardless,stripe,adyen" } bank_debit.bacs = { connector_list = "stripe,gocardless" } bank_debit.sepa = { connector_list = "gocardless,adyen,stripe,deutschebank" } -card.credit.connector_list = "stripe,adyen,authorizedotnet,cybersource,datatrans,globalpay,worldpay,multisafepay,nmi,nexinets,noon,bankofamerica,braintree,nuvei,payme,wellsfargo,bamboraapac,elavon,fiuu,nexixpay,novalnet,paybox,paypal,xendit,moneris,archipel,worldpayvantiv" -card.debit.connector_list = "stripe,adyen,authorizedotnet,cybersource,datatrans,globalpay,worldpay,multisafepay,nmi,nexinets,noon,bankofamerica,braintree,nuvei,payme,wellsfargo,bamboraapac,elavon,fiuu,nexixpay,novalnet,paybox,paypal,xendit,moneris,archipel,worldpayvantiv" +card.credit.connector_list = "stripe,adyen,authorizedotnet,cybersource,datatrans,globalpay,worldpay,multisafepay,nmi,nexinets,noon,bankofamerica,braintree,nuvei,payme,wellsfargo,bamboraapac,elavon,fiuu,nexixpay,novalnet,paybox,paypal,xendit,moneris,archipel,worldpayvantiv,payload" +card.debit.connector_list = "stripe,adyen,authorizedotnet,cybersource,datatrans,globalpay,worldpay,multisafepay,nmi,nexinets,noon,bankofamerica,braintree,nuvei,payme,wellsfargo,bamboraapac,elavon,fiuu,nexixpay,novalnet,paybox,paypal,xendit,moneris,archipel,worldpayvantiv,payload" pay_later.klarna.connector_list = "adyen,aci" wallet.apple_pay.connector_list = "stripe,adyen,cybersource,noon,bankofamerica,nexinets,novalnet,authorizedotnet,wellsfargo" wallet.samsung_pay.connector_list = "cybersource" @@ -443,6 +443,10 @@ crypto_currency = { country = "US, CA, GB, AT, BE, BG, HR, CY, CZ, DK, EE, FI, F debit = { country = "FR", currency = "CAD, AUD, EUR, USD" } credit = { country = "FR", currency = "CAD, AUD, EUR, USD" } +[pm_filters.payload] +debit = { currency = "USD,CAD" } +credit = { currency = "USD,CAD" } + [pm_filters.digitalvirgo] direct_carrier_billing = {country = "MA, CM, ZA, EG, SN, DZ, TN, ML, GN, GH, LY, GA, CG, MG, BW, SD, NG, ID, SG, AZ, TR, FR, ES, PL, GB, PT, DE, IT, BE, IE, SK, GR, NL, CH, BR, MX, AR, CL, AE, IQ, KW, BH, SA, QA, PS, JO, OM, RU" , currency = "MAD, XOF, XAF, ZAR, EGP, DZD, TND, GNF, GHS, LYD, XAF, CDF, MGA, BWP, SDG, NGN, IDR, SGD, RUB, AZN, TRY, EUR, PLN, GBP, CHF, BRL, MXN, ARS, CLP, AED, IQD, KWD, BHD, SAR, QAR, ILS, JOD, OMR" } diff --git a/config/deployments/production.toml b/config/deployments/production.toml index 189b0e951c..b95384f66e 100644 --- a/config/deployments/production.toml +++ b/config/deployments/production.toml @@ -223,8 +223,8 @@ bank_debit.ach = { connector_list = "gocardless,adyen,stripe" } bank_debit.becs = { connector_list = "gocardless,stripe,adyen" } bank_debit.bacs = { connector_list = "stripe,gocardless" } bank_debit.sepa = { connector_list = "gocardless,adyen,stripe,deutschebank" } -card.credit.connector_list = "stripe,adyen,authorizedotnet,cybersource,datatrans,globalpay,worldpay,multisafepay,nmi,nexinets,noon,bankofamerica,braintree,nuvei,payme,wellsfargo,bamboraapac,elavon,fiuu,nexixpay,novalnet,paybox,paypal,xendit,moneris,archipel,worldpayvantiv" -card.debit.connector_list = "stripe,adyen,authorizedotnet,cybersource,datatrans,globalpay,worldpay,multisafepay,nmi,nexinets,noon,bankofamerica,braintree,nuvei,payme,wellsfargo,bamboraapac,elavon,fiuu,nexixpay,novalnet,paybox,paypal,xendit,moneris,archipel,worldpayvantiv" +card.credit.connector_list = "stripe,adyen,authorizedotnet,cybersource,datatrans,globalpay,worldpay,multisafepay,nmi,nexinets,noon,bankofamerica,braintree,nuvei,payme,wellsfargo,bamboraapac,elavon,fiuu,nexixpay,novalnet,paybox,paypal,xendit,moneris,archipel,worldpayvantiv,payload" +card.debit.connector_list = "stripe,adyen,authorizedotnet,cybersource,datatrans,globalpay,worldpay,multisafepay,nmi,nexinets,noon,bankofamerica,braintree,nuvei,payme,wellsfargo,bamboraapac,elavon,fiuu,nexixpay,novalnet,paybox,paypal,xendit,moneris,archipel,worldpayvantiv,payload" pay_later.klarna.connector_list = "adyen,aci" wallet.apple_pay.connector_list = "stripe,adyen,cybersource,noon,bankofamerica,nexinets,novalnet,authorizedotnet,wellsfargo" wallet.samsung_pay.connector_list = "cybersource" @@ -521,6 +521,10 @@ crypto_currency = { country = "US, CA, GB, AT, BE, BG, HR, CY, CZ, DK, EE, FI, F debit = { country = "FR", currency = "CAD, AUD, EUR, USD" } credit = { country = "FR", currency = "CAD, AUD, EUR, USD" } +[pm_filters.payload] +debit = { currency = "USD,CAD" } +credit = { currency = "USD,CAD" } + [pm_filters.digitalvirgo] direct_carrier_billing = {country = "MA, CM, ZA, EG, SN, DZ, TN, ML, GN, GH, LY, GA, CG, MG, BW, SD, NG, ID, SG, AZ, TR, FR, ES, PL, GB, PT, DE, IT, BE, IE, SK, GR, NL, CH, BR, MX, AR, CL, AE, IQ, KW, BH, SA, QA, PS, JO, OM, RU" , currency = "MAD, XOF, XAF, ZAR, EGP, DZD, TND, GNF, GHS, LYD, XAF, CDF, MGA, BWP, SDG, NGN, IDR, SGD, RUB, AZN, TRY, EUR, PLN, GBP, CHF, BRL, MXN, ARS, CLP, AED, IQD, KWD, BHD, SAR, QAR, ILS, JOD, OMR" } diff --git a/config/deployments/sandbox.toml b/config/deployments/sandbox.toml index 1096a37646..42b2db3250 100644 --- a/config/deployments/sandbox.toml +++ b/config/deployments/sandbox.toml @@ -230,8 +230,8 @@ bank_debit.ach = { connector_list = "gocardless,adyen,stripe" } bank_debit.becs = { connector_list = "gocardless,stripe,adyen" } bank_debit.bacs = { connector_list = "stripe,gocardless" } bank_debit.sepa = { connector_list = "gocardless,adyen,stripe,deutschebank" } -card.credit.connector_list = "stripe,adyen,authorizedotnet,cybersource,datatrans,globalpay,worldpay,multisafepay,nmi,nexinets,noon,bankofamerica,braintree,nuvei,payme,wellsfargo,bamboraapac,elavon,fiuu,nexixpay,novalnet,paybox,paypal,xendit,moneris,archipel,worldpayvantiv" -card.debit.connector_list = "stripe,adyen,authorizedotnet,cybersource,datatrans,globalpay,worldpay,multisafepay,nmi,nexinets,noon,bankofamerica,braintree,nuvei,payme,wellsfargo,bamboraapac,elavon,fiuu,nexixpay,novalnet,paybox,paypal,xendit,moneris,archipel,worldpayvantiv" +card.credit.connector_list = "stripe,adyen,authorizedotnet,cybersource,datatrans,globalpay,worldpay,multisafepay,nmi,nexinets,noon,bankofamerica,braintree,nuvei,payme,wellsfargo,bamboraapac,elavon,fiuu,nexixpay,novalnet,paybox,paypal,xendit,moneris,archipel,worldpayvantiv,payload" +card.debit.connector_list = "stripe,adyen,authorizedotnet,cybersource,datatrans,globalpay,worldpay,multisafepay,nmi,nexinets,noon,bankofamerica,braintree,nuvei,payme,wellsfargo,bamboraapac,elavon,fiuu,nexixpay,novalnet,paybox,paypal,xendit,moneris,archipel,worldpayvantiv,payload" pay_later.klarna.connector_list = "adyen,aci" wallet.apple_pay.connector_list = "stripe,adyen,cybersource,noon,bankofamerica,nexinets,novalnet,authorizedotnet,wellsfargo" wallet.samsung_pay.connector_list = "cybersource" @@ -533,6 +533,10 @@ direct_carrier_billing = {country = "MA, CM, ZA, EG, SN, DZ, TN, ML, GN, GH, LY, debit = { country = "FR", currency = "CAD, AUD, EUR, USD" } credit = { country = "FR", currency = "CAD, AUD, EUR, USD" } +[pm_filters.payload] +debit = { currency = "USD,CAD" } +credit = { currency = "USD,CAD" } + [pm_filters.klarna] klarna = { country = "AU,AT,BE,CA,CZ,DK,FI,FR,DE,GR,IE,IT,NL,NZ,NO,PL,PT,ES,SE,CH,GB,US", currency = "CHF,DKK,EUR,GBP,NOK,PLN,SEK,USD,AUD,NZD,CAD" } diff --git a/config/development.toml b/config/development.toml index c94d40d825..b3ebb0bcb3 100644 --- a/config/development.toml +++ b/config/development.toml @@ -685,6 +685,10 @@ crypto_currency = { country = "US, CA, GB, AT, BE, BG, HR, CY, CZ, DK, EE, FI, F debit = { country = "FR", currency = "CAD, AUD, EUR, USD" } credit = { country = "FR", currency = "CAD, AUD, EUR, USD" } +[pm_filters.payload] +debit = { currency = "USD,CAD" } +credit = { currency = "USD,CAD" } + [pm_filters.digitalvirgo] direct_carrier_billing = {country = "MA, CM, ZA, EG, SN, DZ, TN, ML, GN, GH, LY, GA, CG, MG, BW, SD, NG, ID, SG, AZ, TR, FR, ES, PL, GB, PT, DE, IT, BE, IE, SK, GR, NL, CH, BR, MX, AR, CL, AE, IQ, KW, BH, SA, QA, PS, JO, OM, RU" , currency = "MAD, XOF, XAF, ZAR, EGP, DZD, TND, GNF, GHS, LYD, XAF, CDF, MGA, BWP, SDG, NGN, IDR, SGD, RUB, AZN, TRY, EUR, PLN, GBP, CHF, BRL, MXN, ARS, CLP, AED, IQD, KWD, BHD, SAR, QAR, ILS, JOD, OMR" } @@ -989,8 +993,8 @@ bank_debit.ach = { connector_list = "gocardless,adyen,stripe" } bank_debit.becs = { connector_list = "gocardless,stripe,adyen" } bank_debit.bacs = { connector_list = "stripe,gocardless" } bank_debit.sepa = { connector_list = "gocardless,adyen,stripe,deutschebank" } -card.credit.connector_list = "stripe,adyen,authorizedotnet,cybersource,datatrans,globalpay,worldpay,multisafepay,nmi,nexinets,noon,bankofamerica,braintree,nuvei,payme,wellsfargo,bamboraapac,elavon,fiuu,nexixpay,novalnet,paybox,paypal,xendit,moneris,archipel,worldpayvantiv" -card.debit.connector_list = "stripe,adyen,authorizedotnet,cybersource,datatrans,globalpay,worldpay,multisafepay,nmi,nexinets,noon,bankofamerica,braintree,nuvei,payme,wellsfargo,bamboraapac,elavon,fiuu,nexixpay,novalnet,paybox,paypal,xendit,moneris,archipel,worldpayvantiv" +card.credit.connector_list = "stripe,adyen,authorizedotnet,cybersource,datatrans,globalpay,worldpay,multisafepay,nmi,nexinets,noon,bankofamerica,braintree,nuvei,payme,wellsfargo,bamboraapac,elavon,fiuu,nexixpay,novalnet,paybox,paypal,xendit,moneris,archipel,worldpayvantiv,payload" +card.debit.connector_list = "stripe,adyen,authorizedotnet,cybersource,datatrans,globalpay,worldpay,multisafepay,nmi,nexinets,noon,bankofamerica,braintree,nuvei,payme,wellsfargo,bamboraapac,elavon,fiuu,nexixpay,novalnet,paybox,paypal,xendit,moneris,archipel,worldpayvantiv,payload" pay_later.klarna.connector_list = "adyen,aci" wallet.apple_pay.connector_list = "stripe,adyen,cybersource,noon,bankofamerica,nexinets,novalnet,authorizedotnet,wellsfargo" wallet.samsung_pay.connector_list = "cybersource" diff --git a/config/docker_compose.toml b/config/docker_compose.toml index 4c26568df3..f22680dd37 100644 --- a/config/docker_compose.toml +++ b/config/docker_compose.toml @@ -576,6 +576,10 @@ crypto_currency = { country = "US, CA, GB, AT, BE, BG, HR, CY, CZ, DK, EE, FI, F debit = { country = "FR", currency = "CAD, AUD, EUR, USD" } credit = { country = "FR", currency = "CAD, AUD, EUR, USD" } +[pm_filters.payload] +debit = { currency = "USD,CAD" } +credit = { currency = "USD,CAD" } + [pm_filters.digitalvirgo] direct_carrier_billing = {country = "MA, CM, ZA, EG, SN, DZ, TN, ML, GN, GH, LY, GA, CG, MG, BW, SD, NG, ID, SG, AZ, TR, FR, ES, PL, GB, PT, DE, IT, BE, IE, SK, GR, NL, CH, BR, MX, AR, CL, AE, IQ, KW, BH, SA, QA, PS, JO, OM, RU" , currency = "MAD, XOF, XAF, ZAR, EGP, DZD, TND, GNF, GHS, LYD, XAF, CDF, MGA, BWP, SDG, NGN, IDR, SGD, RUB, AZN, TRY, EUR, PLN, GBP, CHF, BRL, MXN, ARS, CLP, AED, IQD, KWD, BHD, SAR, QAR, ILS, JOD, OMR" } @@ -911,8 +915,8 @@ wallet.google_pay = { connector_list = "stripe,adyen,bankofamerica,authorizedotn wallet.apple_pay = { connector_list = "stripe,adyen,cybersource,noon,bankofamerica,authorizedotnet,novalnet,multisafepay,wellsfargo" } wallet.samsung_pay = { connector_list = "cybersource" } wallet.paypal = { connector_list = "adyen,novalnet,authorizedotnet" } -card.credit = { connector_list = "stripe,adyen,authorizedotnet,cybersource,datatrans,globalpay,worldpay,multisafepay,nmi,nexinets,noon,bankofamerica,elavon,xendit,novalnet,bamboraapac,archipel,wellsfargo,worldpayvantiv" } -card.debit = { connector_list = "stripe,adyen,authorizedotnet,cybersource,datatrans,globalpay,worldpay,multisafepay,nmi,nexinets,noon,bankofamerica,elavon,xendit,novalnet,bamboraapac,archipel,wellsfargo,worldpayvantiv" } +card.credit = { connector_list = "stripe,adyen,authorizedotnet,cybersource,datatrans,globalpay,worldpay,multisafepay,nmi,nexinets,noon,bankofamerica,elavon,xendit,novalnet,bamboraapac,archipel,wellsfargo,worldpayvantiv,payload" } +card.debit = { connector_list = "stripe,adyen,authorizedotnet,cybersource,datatrans,globalpay,worldpay,multisafepay,nmi,nexinets,noon,bankofamerica,elavon,xendit,novalnet,bamboraapac,archipel,wellsfargo,worldpayvantiv,payload" } bank_debit.ach = { connector_list = "gocardless,adyen" } bank_debit.becs = { connector_list = "gocardless" } bank_debit.bacs = { connector_list = "adyen" } diff --git a/crates/connector_configs/toml/development.toml b/crates/connector_configs/toml/development.toml index fbd76d7bf9..57632d00a4 100644 --- a/crates/connector_configs/toml/development.toml +++ b/crates/connector_configs/toml/development.toml @@ -6415,9 +6415,14 @@ type="Text" payment_method_type = "Mastercard" [[payload.debit]] payment_method_type = "Visa" -[payload.connector_auth.HeaderKey] -api_key="API Key" +[payload.connector_auth.CurrencyAuthKey.auth_key_map.USD] + processing_account_id = "processing_account_id" + api_key = "API Key" +[payload.connector_auth.CurrencyAuthKey.auth_key_map.CAD] + processing_account_id = "processing_account_id" + api_key = "API Key" + [silverflow] [[silverflow.credit]] payment_method_type = "Mastercard" diff --git a/crates/connector_configs/toml/production.toml b/crates/connector_configs/toml/production.toml index ca3f066395..8f61879891 100644 --- a/crates/connector_configs/toml/production.toml +++ b/crates/connector_configs/toml/production.toml @@ -5028,7 +5028,12 @@ payment_method_type = "Discover" payment_method_type = "Mastercard" [[payload.debit]] payment_method_type = "Visa" -[payload.connector_auth.HeaderKey] + +[payload.connector_auth.CurrencyAuthKey.auth_key_map.USD] +processing_account_id = "processing_account_id" +api_key = "API Key" +[payload.connector_auth.CurrencyAuthKey.auth_key_map.CAD] +processing_account_id = "processing_account_id" api_key = "API Key" [silverflow] diff --git a/crates/connector_configs/toml/sandbox.toml b/crates/connector_configs/toml/sandbox.toml index e4327c88e5..7322b7bd10 100644 --- a/crates/connector_configs/toml/sandbox.toml +++ b/crates/connector_configs/toml/sandbox.toml @@ -6396,7 +6396,12 @@ payment_method_type = "Discover" payment_method_type = "Mastercard" [[payload.debit]] payment_method_type = "Visa" -[payload.connector_auth.HeaderKey] + +[payload.connector_auth.CurrencyAuthKey.auth_key_map.USD] +processing_account_id = "processing_account_id" +api_key = "API Key" +[payload.connector_auth.CurrencyAuthKey.auth_key_map.CAD] +processing_account_id = "processing_account_id" api_key = "API Key" [silverflow] diff --git a/crates/hyperswitch_connectors/src/connectors/payload.rs b/crates/hyperswitch_connectors/src/connectors/payload.rs index 03c41d367a..ce4086a5e9 100644 --- a/crates/hyperswitch_connectors/src/connectors/payload.rs +++ b/crates/hyperswitch_connectors/src/connectors/payload.rs @@ -126,7 +126,16 @@ impl ConnectorCommon for Payload { ) -> CustomResult)>, errors::ConnectorError> { let auth = payload::PayloadAuthType::try_from(auth_type) .change_context(errors::ConnectorError::FailedToObtainAuthType)?; - let encoded_api_key = BASE64_ENGINE.encode(format!("{}:", auth.api_key.expose())); + // The API key is the same for all currencies, so we can take any. + let api_key = auth + .auths + .values() + .next() + .ok_or(errors::ConnectorError::FailedToObtainAuthType)? + .api_key + .clone(); + + let encoded_api_key = BASE64_ENGINE.encode(format!("{}:", api_key.expose())); Ok(vec![( headers::AUTHORIZATION.to_string(), format!("Basic {encoded_api_key}").into_masked(), @@ -166,32 +175,16 @@ impl ConnectorCommon for Payload { impl ConnectorValidation for Payload { fn validate_mandate_payment( &self, - _pm_type: Option, + pm_type: Option, pm_data: PaymentMethodData, ) -> CustomResult<(), errors::ConnectorError> { - match pm_data { - PaymentMethodData::Card(_) => Err(errors::ConnectorError::NotImplemented( - "validate_mandate_payment does not support cards".to_string(), - ) - .into()), - _ => Ok(()), - } - } - - fn validate_psync_reference_id( - &self, - _data: &PaymentsSyncData, - _is_three_ds: bool, - _status: enums::AttemptStatus, - _connector_meta_data: Option, - ) -> CustomResult<(), errors::ConnectorError> { - Ok(()) + let mandate_supported_pmd = + std::collections::HashSet::from([utils::PaymentMethodDataType::Card]); + utils::is_mandate_supported(pm_data, pm_type, mandate_supported_pmd, self.id()) } } -impl ConnectorIntegration for Payload { - //TODO: implement sessions flow -} +impl ConnectorIntegration for Payload {} impl ConnectorIntegration for Payload {} @@ -822,7 +815,7 @@ static PAYLOAD_SUPPORTED_PAYMENT_METHODS: LazyLock = La enums::PaymentMethod::Card, enums::PaymentMethodType::Credit, PaymentMethodDetails { - mandates: enums::FeatureStatus::NotSupported, + mandates: enums::FeatureStatus::Supported, refunds: enums::FeatureStatus::Supported, supported_capture_methods: supported_capture_methods.clone(), specific_features: Some( @@ -840,7 +833,7 @@ static PAYLOAD_SUPPORTED_PAYMENT_METHODS: LazyLock = La enums::PaymentMethod::Card, enums::PaymentMethodType::Debit, PaymentMethodDetails { - mandates: enums::FeatureStatus::NotSupported, + mandates: enums::FeatureStatus::Supported, refunds: enums::FeatureStatus::Supported, supported_capture_methods: supported_capture_methods.clone(), specific_features: Some( diff --git a/crates/hyperswitch_connectors/src/connectors/payload/requests.rs b/crates/hyperswitch_connectors/src/connectors/payload/requests.rs index 6f1bc122af..a2185ba9d3 100644 --- a/crates/hyperswitch_connectors/src/connectors/payload/requests.rs +++ b/crates/hyperswitch_connectors/src/connectors/payload/requests.rs @@ -7,7 +7,8 @@ use crate::connectors::payload::responses; #[derive(Debug, Serialize, PartialEq)] #[serde(untagged)] pub enum PayloadPaymentsRequest { - PayloadCardsRequest(PayloadCardsRequestData), + PayloadCardsRequest(Box), + PayloadMandateRequest(Box), } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] @@ -51,6 +52,24 @@ pub struct PayloadCardsRequestData { // Billing address fields are for AVS validation #[serde(flatten)] pub billing_address: BillingAddress, + pub processing_id: Option>, + /// Allows one-time payment by customer without saving their payment method + /// This is true by default + #[serde(rename = "payment_method[keep_active]")] + pub keep_active: bool, +} + +#[derive(Debug, Clone, Serialize, PartialEq)] +pub struct PayloadMandateRequestData { + pub amount: StringMajorUnit, + #[serde(rename = "type")] + pub transaction_types: TransactionTypes, + // Based on the connectors' response, we can do recurring payment either based on a default payment method id saved in the customer profile or a specific payment method id + // Connector by default, saves every payment method + pub payment_method_id: Secret, + // For manual capture, set status to "authorized", otherwise omit + #[serde(skip_serializing_if = "Option::is_none")] + pub status: Option, } #[derive(Default, Clone, Debug, Serialize, Eq, PartialEq)] diff --git a/crates/hyperswitch_connectors/src/connectors/payload/responses.rs b/crates/hyperswitch_connectors/src/connectors/payload/responses.rs index 444e794e6b..888213be52 100644 --- a/crates/hyperswitch_connectors/src/connectors/payload/responses.rs +++ b/crates/hyperswitch_connectors/src/connectors/payload/responses.rs @@ -34,12 +34,12 @@ pub enum AvsResponse { pub struct PayloadCardsResponseData { pub amount: f64, pub avs: Option, - pub customer_id: Option, + pub customer_id: Option>, #[serde(rename = "id")] pub transaction_id: String, - pub payment_method_id: Option>, - // Connector customer id - pub processing_id: Option, + #[serde(rename = "payment_method_id")] + pub connector_payment_method_id: Option>, + pub processing_id: Option>, pub processing_method_id: Option, pub ref_number: Option, pub status: PayloadPaymentStatus, @@ -84,9 +84,9 @@ pub struct PayloadRefundResponse { #[serde(rename = "id")] pub transaction_id: String, pub ledger: Vec, - pub payment_method_id: Option>, - // Connector customer id - pub processing_id: Option, + #[serde(rename = "payment_method_id")] + pub connector_payment_method_id: Option>, + pub processing_id: Option>, pub ref_number: Option, pub status: RefundStatus, pub status_code: Option, diff --git a/crates/hyperswitch_connectors/src/connectors/payload/transformers.rs b/crates/hyperswitch_connectors/src/connectors/payload/transformers.rs index 707a8db936..9b4b969be8 100644 --- a/crates/hyperswitch_connectors/src/connectors/payload/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/payload/transformers.rs @@ -1,26 +1,35 @@ +use std::collections::HashMap; + use api_models::webhooks::IncomingWebhookEvent; use common_enums::enums; -use common_utils::types::StringMajorUnit; +use common_utils::{ext_traits::ValueExt, types::StringMajorUnit}; +use error_stack::ResultExt; use hyperswitch_domain_models::{ payment_method_data::PaymentMethodData, router_data::{ConnectorAuthType, ErrorResponse, RouterData}, router_flow_types::refunds::{Execute, RSync}, - router_request_types::ResponseId, - router_response_types::{PaymentsResponseData, RefundsResponseData}, + router_request_types::{PaymentsAuthorizeData, ResponseId}, + router_response_types::{MandateReference, PaymentsResponseData, RefundsResponseData}, types::{PaymentsAuthorizeRouterData, PaymentsCaptureRouterData, RefundsRouterData}, }; use hyperswitch_interfaces::{ consts::{NO_ERROR_CODE, NO_ERROR_MESSAGE}, errors, }; -use masking::Secret; +use masking::{ExposeOptionInterface, Secret}; +use serde::Deserialize; use super::{requests, responses}; use crate::{ types::{RefundsResponseRouterData, ResponseRouterData}, - utils::{is_manual_capture, AddressDetailsData, CardData, RouterData as OtherRouterData}, + utils::{ + is_manual_capture, AddressDetailsData, CardData, PaymentsAuthorizeRequestData, + RouterData as OtherRouterData, + }, }; +type Error = error_stack::Report; + //TODO: Fill the struct with respective fields pub struct PayloadRouterData { pub amount: StringMajorUnit, // The type of amount that a connector accepts, for example, String, i64, f64, etc. @@ -36,10 +45,69 @@ impl From<(StringMajorUnit, T)> for PayloadRouterData { } } +// Auth Struct +#[derive(Debug, Clone, Deserialize)] +pub struct PayloadAuth { + pub api_key: Secret, + pub processing_account_id: Option>, +} + +#[derive(Debug, Clone)] +pub struct PayloadAuthType { + pub auths: HashMap, +} + +impl TryFrom<(&ConnectorAuthType, enums::Currency)> for PayloadAuth { + type Error = Error; + fn try_from(value: (&ConnectorAuthType, enums::Currency)) -> Result { + let (auth_type, currency) = value; + match auth_type { + ConnectorAuthType::CurrencyAuthKey { auth_key_map } => { + let auth_key = auth_key_map.get(¤cy).ok_or( + errors::ConnectorError::CurrencyNotSupported { + message: currency.to_string(), + connector: "Payload", + }, + )?; + + auth_key + .to_owned() + .parse_value("PayloadAuth") + .change_context(errors::ConnectorError::FailedToObtainAuthType) + } + _ => Err(errors::ConnectorError::FailedToObtainAuthType.into()), + } + } +} + +impl TryFrom<&ConnectorAuthType> for PayloadAuthType { + type Error = Error; + fn try_from(auth_type: &ConnectorAuthType) -> Result { + match auth_type { + ConnectorAuthType::CurrencyAuthKey { auth_key_map } => { + let auths = auth_key_map + .iter() + .map(|(currency, auth_key)| { + let auth: PayloadAuth = auth_key + .to_owned() + .parse_value("PayloadAuth") + .change_context(errors::ConnectorError::InvalidDataFormat { + field_name: "auth_key_map", + })?; + Ok((*currency, auth)) + }) + .collect::>()?; + Ok(Self { auths }) + } + _ => Err(errors::ConnectorError::FailedToObtainAuthType.into()), + } + } +} + impl TryFrom<&PayloadRouterData<&PaymentsAuthorizeRouterData>> for requests::PayloadPaymentsRequest { - type Error = error_stack::Report; + type Error = Error; fn try_from( item: &PayloadRouterData<&PaymentsAuthorizeRouterData>, ) -> Result { @@ -52,6 +120,10 @@ impl TryFrom<&PayloadRouterData<&PaymentsAuthorizeRouterData>> match item.router_data.request.payment_method_data.clone() { PaymentMethodData::Card(req_card) => { + let payload_auth = PayloadAuth::try_from(( + &item.router_data.connector_auth_type, + item.router_data.request.currency, + ))?; let card = requests::PayloadCard { number: req_card.clone().card_number, expiry: req_card @@ -59,6 +131,7 @@ impl TryFrom<&PayloadRouterData<&PaymentsAuthorizeRouterData>> .get_card_expiry_month_year_2_digit_with_delimiter("/".to_owned())?, cvc: req_card.card_cvc, }; + let is_mandate = item.router_data.request.is_mandate_payment(); let address = item.router_data.get_billing_address()?; // Check for required fields and fail if they're missing @@ -83,7 +156,7 @@ impl TryFrom<&PayloadRouterData<&PaymentsAuthorizeRouterData>> None }; - Ok(Self::PayloadCardsRequest( + Ok(Self::PayloadCardsRequest(Box::new( requests::PayloadCardsRequestData { amount: item.amount.clone(), card, @@ -91,31 +164,35 @@ impl TryFrom<&PayloadRouterData<&PaymentsAuthorizeRouterData>> payment_method_type: "card".to_string(), status, billing_address, + processing_id: payload_auth.processing_account_id, + keep_active: is_mandate, }, - )) + ))) + } + PaymentMethodData::MandatePayment => { + // For manual capture, set status to "authorized" + let status = if is_manual_capture(item.router_data.request.capture_method) { + Some(responses::PayloadPaymentStatus::Authorized) + } else { + None + }; + + Ok(Self::PayloadMandateRequest(Box::new( + requests::PayloadMandateRequestData { + amount: item.amount.clone(), + transaction_types: requests::TransactionTypes::Payment, + payment_method_id: Secret::new( + item.router_data.request.get_connector_mandate_id()?, + ), + status, + }, + ))) } _ => Err(errors::ConnectorError::NotImplemented("Payment method".to_string()).into()), } } } -// Auth Struct -pub struct PayloadAuthType { - pub(super) api_key: Secret, -} - -impl TryFrom<&ConnectorAuthType> for PayloadAuthType { - type Error = error_stack::Report; - fn try_from(auth_type: &ConnectorAuthType) -> Result { - match auth_type { - ConnectorAuthType::HeaderKey { api_key } => Ok(Self { - api_key: api_key.to_owned(), - }), - _ => Err(errors::ConnectorError::FailedToObtainAuthType.into()), - } - } -} - impl From for common_enums::AttemptStatus { fn from(item: responses::PayloadPaymentStatus) -> Self { match item { @@ -132,15 +209,39 @@ impl From for common_enums::AttemptStatus { impl TryFrom> for RouterData +where + T: 'static, { - type Error = error_stack::Report; + type Error = Error; fn try_from( item: ResponseRouterData, ) -> Result { match item.response.clone() { responses::PayloadPaymentsResponse::PayloadCardsResponse(response) => { let status = enums::AttemptStatus::from(response.status); - let connector_customer = response.processing_id.clone(); + + let request_any: &dyn std::any::Any = &item.data.request; + let is_mandate_payment = request_any + .downcast_ref::() + .is_some_and(|req| req.is_mandate_payment()); + + let mandate_reference = if is_mandate_payment { + let connector_payment_method_id = + response.connector_payment_method_id.clone().expose_option(); + if connector_payment_method_id.is_some() { + Some(MandateReference { + connector_mandate_id: connector_payment_method_id, + payment_method_id: None, + mandate_metadata: None, + connector_mandate_request_reference_id: None, + }) + } else { + None + } + } else { + None + }; + let response_result = if status == enums::AttemptStatus::Failure { Err(ErrorResponse { attempt_status: None, @@ -163,7 +264,7 @@ impl Ok(PaymentsResponseData::TransactionResponse { resource_id: ResponseId::ConnectorTransactionId(response.transaction_id), redirection_data: Box::new(None), - mandate_reference: Box::new(None), + mandate_reference: Box::new(mandate_reference), connector_metadata: None, network_txn_id: None, connector_response_reference_id: response.ref_number, @@ -174,7 +275,6 @@ impl Ok(Self { status, response: response_result, - connector_customer, ..item.data }) } @@ -183,7 +283,7 @@ impl } impl TryFrom<&PayloadRouterData> for requests::PayloadCancelRequest { - type Error = error_stack::Report; + type Error = Error; fn try_from(_item: &PayloadRouterData) -> Result { Ok(Self { status: responses::PayloadPaymentStatus::Voided, @@ -192,7 +292,7 @@ impl TryFrom<&PayloadRouterData> for requests::PayloadCancelRequest { } impl TryFrom<&PayloadRouterData<&PaymentsCaptureRouterData>> for requests::PayloadCaptureRequest { - type Error = error_stack::Report; + type Error = Error; fn try_from( _item: &PayloadRouterData<&PaymentsCaptureRouterData>, ) -> Result { @@ -203,7 +303,7 @@ impl TryFrom<&PayloadRouterData<&PaymentsCaptureRouterData>> for requests::Paylo } impl TryFrom<&PayloadRouterData<&RefundsRouterData>> for requests::PayloadRefundRequest { - type Error = error_stack::Report; + type Error = Error; fn try_from(item: &PayloadRouterData<&RefundsRouterData>) -> Result { let connector_transaction_id = item.router_data.request.connector_transaction_id.clone(); @@ -228,7 +328,7 @@ impl From for enums::RefundStatus { impl TryFrom> for RefundsRouterData { - type Error = error_stack::Report; + type Error = Error; fn try_from( item: RefundsResponseRouterData, ) -> Result { @@ -245,7 +345,7 @@ impl TryFrom> for RefundsRouterData { - type Error = error_stack::Report; + type Error = Error; fn try_from( item: RefundsResponseRouterData, ) -> Result { diff --git a/crates/hyperswitch_connectors/src/default_implementations.rs b/crates/hyperswitch_connectors/src/default_implementations.rs index d0becd7e26..7e2a94b797 100644 --- a/crates/hyperswitch_connectors/src/default_implementations.rs +++ b/crates/hyperswitch_connectors/src/default_implementations.rs @@ -1282,8 +1282,8 @@ default_imp_for_create_customer!( connectors::Nuvei, connectors::Paybox, connectors::Payeezy, - connectors::Payload, connectors::Payme, + connectors::Payload, connectors::Payone, connectors::Paypal, connectors::Paystack, diff --git a/crates/hyperswitch_connectors/src/utils.rs b/crates/hyperswitch_connectors/src/utils.rs index bb157a0fc3..3c581988c2 100644 --- a/crates/hyperswitch_connectors/src/utils.rs +++ b/crates/hyperswitch_connectors/src/utils.rs @@ -1677,13 +1677,21 @@ impl PayoutFulfillRequestData for hyperswitch_domain_models::router_request_type pub trait CustomerData { fn get_email(&self) -> Result; + fn is_mandate_payment(&self) -> bool; } impl CustomerData for ConnectorCustomerData { fn get_email(&self) -> Result { self.email.clone().ok_or_else(missing_field_err("email")) } + fn is_mandate_payment(&self) -> bool { + // We only need to check if the customer acceptance or setup mandate details are present and if the setup future usage is OffSession. + // mandate_reference_id is not needed here as we do not need to check for existing mandates. + self.customer_acceptance.is_some() + && self.setup_future_usage == Some(FutureUsage::OffSession) + } } + pub trait PaymentsAuthorizeRequestData { fn get_optional_language_from_browser_info(&self) -> Option; fn is_auto_capture(&self) -> Result; diff --git a/crates/hyperswitch_domain_models/src/router_request_types.rs b/crates/hyperswitch_domain_models/src/router_request_types.rs index 1c238ae50d..754157db05 100644 --- a/crates/hyperswitch_domain_models/src/router_request_types.rs +++ b/crates/hyperswitch_domain_models/src/router_request_types.rs @@ -182,6 +182,9 @@ pub struct ConnectorCustomerData { pub preprocessing_id: Option, pub payment_method_data: Option, pub split_payments: Option, + // Mandates + pub setup_future_usage: Option, + pub customer_acceptance: Option, } impl TryFrom for ConnectorCustomerData { @@ -195,6 +198,8 @@ impl TryFrom for ConnectorCustomerData { name: None, preprocessing_id: None, split_payments: None, + setup_future_usage: data.setup_future_usage, + customer_acceptance: data.customer_acceptance, }) } } @@ -220,6 +225,8 @@ impl name: data.request.customer_name.clone(), preprocessing_id: data.preprocessing_id.clone(), split_payments: data.request.split_payments.clone(), + setup_future_usage: data.request.setup_future_usage, + customer_acceptance: data.request.customer_acceptance.clone(), }) } } @@ -244,6 +251,8 @@ impl TryFrom<&RouterData, pub paybox: Option, pub payeezy: Option, - pub payload: Option, + pub payload: Option, pub payme: Option, pub payone: Option, pub paypal: Option, @@ -220,54 +220,78 @@ impl ConnectorAuthenticationMap { .into_iter() .map(|(connector_name, config)| { let auth_type = match config { - toml::Value::Table(table) => { - match ( - table.get("api_key"), - table.get("key1"), - table.get("api_secret"), - table.get("key2"), - ) { - (Some(api_key), None, None, None) => ConnectorAuthType::HeaderKey { - api_key: Secret::new( - api_key.as_str().unwrap_or_default().to_string(), - ), - }, - (Some(api_key), Some(key1), None, None) => ConnectorAuthType::BodyKey { - api_key: Secret::new( - api_key.as_str().unwrap_or_default().to_string(), - ), - key1: Secret::new(key1.as_str().unwrap_or_default().to_string()), - }, - (Some(api_key), Some(key1), Some(api_secret), None) => { - ConnectorAuthType::SignatureKey { + toml::Value::Table(mut table) => { + if let Some(auth_key_map_value) = table.remove("auth_key_map") { + // This is a CurrencyAuthKey + if let toml::Value::Table(auth_key_map_table) = auth_key_map_value { + let mut parsed_auth_map = HashMap::new(); + for (currency, val) in auth_key_map_table { + if let Ok(currency_enum) = + currency.parse::() + { + parsed_auth_map + .insert(currency_enum, Secret::new(val.to_string())); + } + } + ConnectorAuthType::CurrencyAuthKey { + auth_key_map: parsed_auth_map, + } + } else { + ConnectorAuthType::NoKey + } + } else { + match ( + table.get("api_key"), + table.get("key1"), + table.get("api_secret"), + table.get("key2"), + ) { + (Some(api_key), None, None, None) => ConnectorAuthType::HeaderKey { api_key: Secret::new( api_key.as_str().unwrap_or_default().to_string(), ), - key1: Secret::new( - key1.as_str().unwrap_or_default().to_string(), - ), - api_secret: Secret::new( - api_secret.as_str().unwrap_or_default().to_string(), - ), + }, + (Some(api_key), Some(key1), None, None) => { + ConnectorAuthType::BodyKey { + api_key: Secret::new( + api_key.as_str().unwrap_or_default().to_string(), + ), + key1: Secret::new( + key1.as_str().unwrap_or_default().to_string(), + ), + } } - } - (Some(api_key), Some(key1), Some(api_secret), Some(key2)) => { - ConnectorAuthType::MultiAuthKey { - api_key: Secret::new( - api_key.as_str().unwrap_or_default().to_string(), - ), - key1: Secret::new( - key1.as_str().unwrap_or_default().to_string(), - ), - api_secret: Secret::new( - api_secret.as_str().unwrap_or_default().to_string(), - ), - key2: Secret::new( - key2.as_str().unwrap_or_default().to_string(), - ), + (Some(api_key), Some(key1), Some(api_secret), None) => { + ConnectorAuthType::SignatureKey { + api_key: Secret::new( + api_key.as_str().unwrap_or_default().to_string(), + ), + key1: Secret::new( + key1.as_str().unwrap_or_default().to_string(), + ), + api_secret: Secret::new( + api_secret.as_str().unwrap_or_default().to_string(), + ), + } } + (Some(api_key), Some(key1), Some(api_secret), Some(key2)) => { + ConnectorAuthType::MultiAuthKey { + api_key: Secret::new( + api_key.as_str().unwrap_or_default().to_string(), + ), + key1: Secret::new( + key1.as_str().unwrap_or_default().to_string(), + ), + api_secret: Secret::new( + api_secret.as_str().unwrap_or_default().to_string(), + ), + key2: Secret::new( + key2.as_str().unwrap_or_default().to_string(), + ), + } + } + _ => ConnectorAuthType::NoKey, } - _ => ConnectorAuthType::NoKey, } } _ => ConnectorAuthType::NoKey, @@ -275,7 +299,6 @@ impl ConnectorAuthenticationMap { (connector_name, auth_type) }) .collect(); - Self(auth_map) } } @@ -344,6 +367,25 @@ impl From for ConnectorAuthType { } } +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct CurrencyAuthKey { + pub auth_key_map: HashMap, +} + +impl From for ConnectorAuthType { + fn from(key: CurrencyAuthKey) -> Self { + let mut auth_map = HashMap::new(); + for (currency, auth_data) in key.auth_key_map { + if let Ok(currency_enum) = currency.parse::() { + auth_map.insert(currency_enum, Secret::new(auth_data.to_string())); + } + } + Self::CurrencyAuthKey { + auth_key_map: auth_map, + } + } +} + #[derive(Debug, Serialize, Deserialize, Clone)] pub struct NoKey {} @@ -396,6 +438,9 @@ pub enum ConnectorAuthType { api_secret: Secret, key2: Secret, }, + CurrencyAuthKey { + auth_key_map: HashMap>, + }, #[default] NoKey, } diff --git a/cypress-tests/cypress/e2e/configs/Payment/Payload.js b/cypress-tests/cypress/e2e/configs/Payment/Payload.js index 6f45a71e50..76096d4df0 100644 --- a/cypress-tests/cypress/e2e/configs/Payment/Payload.js +++ b/cypress-tests/cypress/e2e/configs/Payment/Payload.js @@ -1,8 +1,12 @@ import { customerAcceptance, + connectorDetails as commonConnectorDetails, singleUseMandateData, multiUseMandateData, } from "./Commons"; +import { getCustomExchange } from "./Modifiers"; + +const DUPLICATION_TIMEOUT = 30000; // 30 seconds const successfulNo3DSCardDetails = { card_number: "4242424242424242", @@ -24,24 +28,6 @@ const failedNo3DSCardDetails = { card_cvc: "123", }; -const payment_method_data_no3ds = { - card: { - last4: "4242", - card_type: "CREDIT", - card_network: "Visa", - card_issuer: "STRIPE PAYMENTS UK LIMITED", - card_issuing_country: "UNITEDKINGDOM", - card_isin: "424242", - card_extended_bin: null, - card_exp_month: "12", - card_exp_year: "25", - card_holder_name: "John Doe", - payment_checks: null, - authentication_data: null, - }, - billing: null, -}; - export const connectorDetails = { card_pm: { PaymentIntent: { @@ -179,7 +165,7 @@ export const connectorDetails = { Configs: { DELAY: { STATUS: true, - TIMEOUT: 15000, + TIMEOUT: DUPLICATION_TIMEOUT / 2, // 15 seconds }, }, Request: { @@ -313,7 +299,7 @@ export const connectorDetails = { Configs: { DELAY: { STATUS: true, - TIMEOUT: 15000, + TIMEOUT: DUPLICATION_TIMEOUT / 2, // 15 seconds }, }, Request: { @@ -336,7 +322,7 @@ export const connectorDetails = { Configs: { DELAY: { STATUS: true, - TIMEOUT: 15000, + TIMEOUT: DUPLICATION_TIMEOUT / 2, // 15 seconds }, }, Request: { @@ -359,7 +345,7 @@ export const connectorDetails = { Configs: { DELAY: { STATUS: true, - TIMEOUT: 15000, + TIMEOUT: DUPLICATION_TIMEOUT / 2, // 15 seconds }, TRIGGER_SKIP: true, }, @@ -383,7 +369,7 @@ export const connectorDetails = { Configs: { DELAY: { STATUS: true, - TIMEOUT: 15000, + TIMEOUT: DUPLICATION_TIMEOUT / 2, // 15 seconds }, }, Request: { @@ -430,7 +416,7 @@ export const connectorDetails = { Configs: { DELAY: { STATUS: true, - TIMEOUT: 15000, + TIMEOUT: DUPLICATION_TIMEOUT / 2, // 15 seconds }, }, Request: { @@ -452,7 +438,7 @@ export const connectorDetails = { Configs: { DELAY: { STATUS: true, - TIMEOUT: 15000, + TIMEOUT: DUPLICATION_TIMEOUT / 2, // 15 seconds }, }, Request: { @@ -469,7 +455,7 @@ export const connectorDetails = { Configs: { DELAY: { STATUS: true, - TIMEOUT: 15000, + TIMEOUT: DUPLICATION_TIMEOUT / 2, // 15 seconds }, }, Request: { @@ -486,7 +472,7 @@ export const connectorDetails = { Configs: { DELAY: { STATUS: true, - TIMEOUT: 15000, + TIMEOUT: DUPLICATION_TIMEOUT / 2, // 15 seconds }, }, Request: { @@ -504,9 +490,8 @@ export const connectorDetails = { Configs: { DELAY: { STATUS: true, - TIMEOUT: 15000, + TIMEOUT: DUPLICATION_TIMEOUT, }, - TRIGGER_SKIP: true, }, Request: { payment_method: "card", @@ -528,9 +513,8 @@ export const connectorDetails = { Configs: { DELAY: { STATUS: true, - TIMEOUT: 15000, + TIMEOUT: DUPLICATION_TIMEOUT, }, - TRIGGER_SKIP: true, }, Request: { payment_method: "card", @@ -544,10 +528,6 @@ export const connectorDetails = { status: 200, body: { status: "succeeded", - mandate_id: null, - payment_method_data: payment_method_data_no3ds, - payment_method: "card", - connector: "payload", }, }, }, @@ -555,9 +535,8 @@ export const connectorDetails = { Configs: { DELAY: { STATUS: true, - TIMEOUT: 15000, + TIMEOUT: DUPLICATION_TIMEOUT, }, - TRIGGER_SKIP: true, }, Request: { payment_method: "card", @@ -571,10 +550,6 @@ export const connectorDetails = { status: 200, body: { status: "requires_capture", - mandate_id: null, - payment_method_data: payment_method_data_no3ds, - payment_method: "card", - connector: "payload", }, }, }, @@ -582,9 +557,8 @@ export const connectorDetails = { Configs: { DELAY: { STATUS: true, - TIMEOUT: 15000, + TIMEOUT: DUPLICATION_TIMEOUT, }, - TRIGGER_SKIP: true, }, Request: { payment_method: "card", @@ -598,9 +572,6 @@ export const connectorDetails = { status: 200, body: { status: "succeeded", - payment_method_data: payment_method_data_no3ds, - payment_method: "card", - connector: "payload", }, }, }, @@ -608,9 +579,8 @@ export const connectorDetails = { Configs: { DELAY: { STATUS: true, - TIMEOUT: 15000, + TIMEOUT: DUPLICATION_TIMEOUT, }, - TRIGGER_SKIP: true, }, Request: { payment_method: "card", @@ -624,9 +594,6 @@ export const connectorDetails = { status: 200, body: { status: "requires_capture", - payment_method_data: payment_method_data_no3ds, - payment_method: "card", - connector: "payload", }, }, }, @@ -634,9 +601,8 @@ export const connectorDetails = { Configs: { DELAY: { STATUS: true, - TIMEOUT: 15000, + TIMEOUT: DUPLICATION_TIMEOUT, }, - TRIGGER_SKIP: true, }, Request: { currency: "BRL", @@ -652,9 +618,8 @@ export const connectorDetails = { Configs: { DELAY: { STATUS: true, - TIMEOUT: 15000, + TIMEOUT: DUPLICATION_TIMEOUT, }, - TRIGGER_SKIP: true, }, Request: { payment_method: "card", @@ -673,5 +638,30 @@ export const connectorDetails = { }, }, }, + + MITAutoCapture: getCustomExchange({ + Configs: { + DELAY: { + STATUS: true, + TIMEOUT: DUPLICATION_TIMEOUT, + }, + }, + ...commonConnectorDetails.card_pm.MITAutoCapture, + }), + MITManualCapture: { + Configs: { + DELAY: { + STATUS: true, + TIMEOUT: DUPLICATION_TIMEOUT, + }, + }, + Request: {}, + Response: { + status: 200, + body: { + status: "requires_capture", + }, + }, + }, }, }; diff --git a/loadtest/config/development.toml b/loadtest/config/development.toml index 77a5f69a1e..64ad0ee79c 100644 --- a/loadtest/config/development.toml +++ b/loadtest/config/development.toml @@ -377,6 +377,10 @@ apple_pay = { country = "AU, HK, JP, NZ, SG, TW, AT, BY, BE, BG, HR, CY, CZ, DK, google_pay = { country = "AL, DZ, AO, AG, AR, AU, AT, AZ, BH, BY, BE, BR, BG, CA, CL, CO, HR, CZ, DK, DO, EG, EE, FI, FR, DE, GR, HK, HU, IN, ID, IE, IL, IT, JP, JO, KZ, KE, KW, LV, LB, LT, LU, MY, MX, NL, NZ, NO, OM, PK, PA, PE, PH, PL, PT, QA, RO, RU, SA, SG, SK, ZA, ES, LK, SE, CH, TW, TH, TR, UA, AE, GB, UY, VN",currency = "ALL, DZD, USD, ARS, AUD, EUR, AZN, BHD, BYN, BRL, BGN, CAD, CLP, COP, CZK, DKK, DOP, HKD, HUF, INR, IDR, JPY, JOD, KZT, KES, KWD, LBP, MYR, MXN, NZD, NOK, OMR, PKR, PEN, PHP, PLN, QAR, RON, RUB, SAR, SGD, ZAR, LKR, SEK, CHF, TWD, THB, TRY, UAH, AED, GBP, UYU, VND" } paypal = { country = "AU,CA,GB,IN,JP,NZ,PH,SG,TH,US",currency = "AED,AMD,ARS,AUD,AZN,BAM,BDT,BGN,BHD,BMD,BND,BRL,BYN,CAD,CHF,CLP,CNY,COP,CRC,CZK,DKK,DOP,DZD,EGP,EUR,GBP,GEL,GHS,GTQ,HKD,HUF,IDR,INR,IQD,ISK,JOD,JPY,KES,KGS,KRW,KWD,KYD,KZT,LBP,LKR,MAD,MDL,MKD,MMK,MNT,MUR,MWK,MXN,MYR,MZN,NAD,NGN,NOK,NZD,OMR,PEN,PHP,PKR,PLN,PYG,QAR,RON,RSD,RUB,SAR,SEK,SGD,SOS,THB,TND,TOP,TRY,TTD,TWD,UAH,UGX,USD,UYU,UZS,VND,XAF,YER,ZAR" } +[pm_filters.payload] +debit = { currency = "USD,CAD" } +credit = { currency = "USD,CAD" } + [pm_filters.prophetpay] card_redirect = { country = "US", currency = "USD" } @@ -632,8 +636,8 @@ bank_debit.ach = { connector_list = "gocardless,adyen,stripe" } bank_debit.becs = { connector_list = "gocardless,stripe,adyen" } bank_debit.bacs = { connector_list = "stripe,gocardless" } bank_debit.sepa = { connector_list = "gocardless,adyen,stripe,deutschebank" } -card.credit.connector_list = "stripe,adyen,authorizedotnet,cybersource,datatrans,globalpay,worldpay,multisafepay,nmi,nexinets,noon,bankofamerica,braintree,nuvei,payme,wellsfargo,bamboraapac,elavon,fiuu,nexixpay,novalnet,paybox,paypal,xendit,moneris,worldpayvantiv" -card.debit.connector_list = "stripe,adyen,authorizedotnet,cybersource,datatrans,globalpay,worldpay,multisafepay,nmi,nexinets,noon,bankofamerica,braintree,nuvei,payme,wellsfargo,bamboraapac,elavon,fiuu,nexixpay,novalnet,paybox,paypal,xendit,moneris,worldpayvantiv" +card.credit.connector_list = "stripe,adyen,authorizedotnet,cybersource,datatrans,globalpay,worldpay,multisafepay,nmi,nexinets,noon,bankofamerica,braintree,nuvei,payme,wellsfargo,bamboraapac,elavon,fiuu,nexixpay,novalnet,paybox,paypal,xendit,moneris,worldpayvantiv,payload" +card.debit.connector_list = "stripe,adyen,authorizedotnet,cybersource,datatrans,globalpay,worldpay,multisafepay,nmi,nexinets,noon,bankofamerica,braintree,nuvei,payme,wellsfargo,bamboraapac,elavon,fiuu,nexixpay,novalnet,paybox,paypal,xendit,moneris,worldpayvantiv,payload" pay_later.klarna.connector_list = "adyen,aci" wallet.apple_pay.connector_list = "stripe,adyen,cybersource,noon,bankofamerica,nexinets,novalnet,authorizedotnet" wallet.samsung_pay.connector_list = "cybersource"