use std::str::FromStr; pub use common_enums::*; use utoipa::ToSchema; #[derive( Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, strum::Display, strum::EnumString, )] /// The routing algorithm to be used to process the incoming request from merchant to outgoing payment processor or payment method. The default is 'Custom' #[serde(rename_all = "snake_case")] #[strum(serialize_all = "snake_case")] pub enum RoutingAlgorithm { RoundRobin, MaxConversion, MinCost, Custom, } /// A connector is an integration to fulfill payments #[derive( Clone, Copy, Debug, Eq, PartialEq, ToSchema, serde::Deserialize, serde::Serialize, strum::VariantNames, strum::EnumIter, strum::Display, strum::EnumString, Hash, )] #[serde(rename_all = "snake_case")] #[strum(serialize_all = "snake_case")] pub enum Connector { #[cfg(feature = "dummy_connector")] #[serde(rename = "phonypay")] #[strum(serialize = "phonypay")] DummyConnector1, #[cfg(feature = "dummy_connector")] #[serde(rename = "fauxpay")] #[strum(serialize = "fauxpay")] DummyConnector2, #[cfg(feature = "dummy_connector")] #[serde(rename = "pretendpay")] #[strum(serialize = "pretendpay")] DummyConnector3, #[cfg(feature = "dummy_connector")] #[serde(rename = "stripe_test")] #[strum(serialize = "stripe_test")] DummyConnector4, #[cfg(feature = "dummy_connector")] #[serde(rename = "adyen_test")] #[strum(serialize = "adyen_test")] DummyConnector5, #[cfg(feature = "dummy_connector")] #[serde(rename = "checkout_test")] #[strum(serialize = "checkout_test")] DummyConnector6, #[cfg(feature = "dummy_connector")] #[serde(rename = "paypal_test")] #[strum(serialize = "paypal_test")] DummyConnector7, Aci, Adyen, Airwallex, Authorizedotnet, Bambora, Bankofamerica, Billwerk, Bitpay, Bluesnap, Boku, Braintree, Cashtocode, Checkout, Coinbase, Cryptopay, Cybersource, Dlocal, Ebanx, Fiserv, Forte, Globalpay, Globepay, Gocardless, // Gpayments, Added as template code for future usage Helcim, Iatapay, Klarna, // Mifinity, Added as template code for future usage Mollie, Multisafepay, Netcetera, Nexinets, Nmi, Noon, Nuvei, // Opayo, added as template code for future usage Opennode, // Payeezy, As psync and rsync are not supported by this connector, it is added as template code for future usage Payme, // Payone, added as template code for future usage Paypal, Payu, Placetopay, Powertranz, Prophetpay, Rapyd, Shift4, Square, Stax, Stripe, Threedsecureio, Trustpay, // Tsys, Tsys, Volt, Wise, Worldline, Worldpay, Signifyd, Plaid, Riskified, Zen, Zsl, } impl Connector { #[cfg(feature = "payouts")] pub fn supports_instant_payout(&self, payout_method: PayoutType) -> bool { matches!( (self, payout_method), (Self::Paypal, PayoutType::Wallet) | (_, PayoutType::Card) ) } #[cfg(feature = "payouts")] pub fn supports_create_recipient(&self, payout_method: PayoutType) -> bool { matches!((self, payout_method), (_, PayoutType::Bank)) } #[cfg(feature = "payouts")] pub fn supports_payout_eligibility(&self, payout_method: PayoutType) -> bool { matches!((self, payout_method), (_, PayoutType::Card)) } #[cfg(feature = "payouts")] pub fn supports_access_token_for_payout(&self, payout_method: PayoutType) -> bool { matches!((self, payout_method), (Self::Paypal, _)) } #[cfg(feature = "payouts")] pub fn supports_vendor_disburse_account_create_for_payout(&self) -> bool { matches!(self, Self::Stripe) } pub fn supports_access_token(&self, payment_method: PaymentMethod) -> bool { matches!( (self, payment_method), (Self::Airwallex, _) | (Self::Globalpay, _) | (Self::Paypal, _) | (Self::Payu, _) | (Self::Trustpay, PaymentMethod::BankRedirect) | (Self::Iatapay, _) | (Self::Volt, _) ) } pub fn supports_file_storage_module(&self) -> bool { matches!(self, Self::Stripe | Self::Checkout) } pub fn requires_defend_dispute(&self) -> bool { matches!(self, Self::Checkout) } pub fn is_separate_authentication_supported(&self) -> bool { match self { #[cfg(feature = "dummy_connector")] Self::DummyConnector1 | Self::DummyConnector2 | Self::DummyConnector3 | Self::DummyConnector4 | Self::DummyConnector5 | Self::DummyConnector6 | Self::DummyConnector7 => false, Self::Aci | Self::Adyen | Self::Airwallex | Self::Authorizedotnet | Self::Bambora | Self::Bankofamerica | Self::Billwerk | Self::Bitpay | Self::Bluesnap | Self::Boku | Self::Braintree | Self::Cashtocode | Self::Coinbase | Self::Cryptopay | Self::Dlocal | Self::Ebanx | Self::Fiserv | Self::Forte | Self::Globalpay | Self::Globepay | Self::Gocardless // | Self::Gpayments Added as template code for future usage | Self::Helcim | Self::Iatapay | Self::Klarna // | Self::Mifinity Added as template code for future usage | Self::Mollie | Self::Multisafepay | Self::Nexinets | Self::Nuvei | Self::Opennode | Self::Payme // | Self::Payone Added as a template code for future usage | Self::Paypal | Self::Payu | Self::Placetopay | Self::Powertranz | Self::Prophetpay | Self::Rapyd | Self::Shift4 | Self::Square | Self::Stax | Self::Trustpay | Self::Tsys | Self::Volt | Self::Wise | Self::Worldline | Self::Worldpay | Self::Zen | Self::Zsl | Self::Signifyd | Self::Plaid | Self::Riskified | Self::Threedsecureio | Self::Netcetera | Self::Cybersource | Self::Noon | Self::Stripe => false, Self::Checkout | Self::Nmi => true, } } } #[derive( Clone, Copy, Debug, Eq, Hash, PartialEq, serde::Serialize, serde::Deserialize, strum::Display, strum::EnumString, ToSchema, )] #[serde(rename_all = "snake_case")] #[strum(serialize_all = "snake_case")] pub enum AuthenticationConnectors { Threedsecureio, Netcetera, Gpayments, } impl AuthenticationConnectors { pub fn is_separate_version_call_required(&self) -> bool { match self { Self::Threedsecureio | Self::Netcetera => false, Self::Gpayments => true, } } } #[cfg(feature = "payouts")] #[derive( Clone, Copy, Debug, Eq, Hash, PartialEq, serde::Serialize, serde::Deserialize, strum::Display, strum::EnumString, ToSchema, )] #[serde(rename_all = "snake_case")] #[strum(serialize_all = "snake_case")] pub enum PayoutConnectors { Adyen, Stripe, Wise, Paypal, Ebanx, Cybersource, } #[cfg(feature = "payouts")] impl From for RoutableConnectors { fn from(value: PayoutConnectors) -> Self { match value { PayoutConnectors::Adyen => Self::Adyen, PayoutConnectors::Stripe => Self::Stripe, PayoutConnectors::Wise => Self::Wise, PayoutConnectors::Paypal => Self::Paypal, PayoutConnectors::Ebanx => Self::Ebanx, PayoutConnectors::Cybersource => Self::Cybersource, } } } #[cfg(feature = "payouts")] impl From for Connector { fn from(value: PayoutConnectors) -> Self { match value { PayoutConnectors::Adyen => Self::Adyen, PayoutConnectors::Stripe => Self::Stripe, PayoutConnectors::Wise => Self::Wise, PayoutConnectors::Paypal => Self::Paypal, PayoutConnectors::Ebanx => Self::Ebanx, PayoutConnectors::Cybersource => Self::Cybersource, } } } #[cfg(feature = "payouts")] impl TryFrom for PayoutConnectors { type Error = String; fn try_from(value: Connector) -> Result { match value { Connector::Adyen => Ok(Self::Adyen), Connector::Stripe => Ok(Self::Stripe), Connector::Wise => Ok(Self::Wise), Connector::Paypal => Ok(Self::Paypal), Connector::Ebanx => Ok(Self::Ebanx), Connector::Cybersource => Ok(Self::Cybersource), _ => Err(format!("Invalid payout connector {}", value)), } } } #[cfg(feature = "frm")] #[derive( Clone, Copy, Debug, Eq, Hash, PartialEq, serde::Serialize, serde::Deserialize, strum::Display, strum::EnumString, ToSchema, )] #[serde(rename_all = "snake_case")] #[strum(serialize_all = "snake_case")] pub enum FrmConnectors { /// Signifyd Risk Manager. Official docs: https://docs.signifyd.com/ Signifyd, Riskified, } #[derive( Clone, Debug, serde::Deserialize, serde::Serialize, strum::Display, strum::EnumString, ToSchema, )] #[strum(serialize_all = "snake_case")] #[serde(rename_all = "snake_case")] pub enum FrmAction { CancelTxn, AutoRefund, ManualReview, } #[derive( Clone, Debug, serde::Deserialize, serde::Serialize, strum::Display, strum::EnumString, ToSchema, )] #[strum(serialize_all = "snake_case")] #[serde(rename_all = "snake_case")] pub enum FrmPreferredFlowTypes { Pre, Post, } #[derive(Debug, Eq, PartialEq, Clone, serde::Serialize, serde::Deserialize)] pub struct UnresolvedResponseReason { pub code: String, /// A message to merchant to give hint on next action he/she should do to resolve pub message: String, } /// Possible field type of required fields in payment_method_data #[derive( Clone, Debug, Eq, serde::Deserialize, serde::Serialize, strum::Display, strum::EnumString, ToSchema, )] #[serde(rename_all = "snake_case")] #[strum(serialize_all = "snake_case")] pub enum FieldType { UserCardNumber, UserCardExpiryMonth, UserCardExpiryYear, UserCardCvc, UserFullName, UserEmailAddress, UserPhoneNumber, UserCountryCode, //phone number's country code UserCountry { options: Vec }, //for country inside payment method data ex- bank redirect UserCurrency { options: Vec }, UserBillingName, UserAddressLine1, UserAddressLine2, UserAddressCity, UserAddressPincode, UserAddressState, UserAddressCountry { options: Vec }, UserShippingName, UserShippingAddressLine1, UserShippingAddressLine2, UserShippingAddressCity, UserShippingAddressPincode, UserShippingAddressState, UserShippingAddressCountry { options: Vec }, UserBlikCode, UserBank, Text, DropDown { options: Vec }, } impl FieldType { pub fn get_billing_variants() -> Vec { vec![ Self::UserBillingName, Self::UserAddressLine1, Self::UserAddressLine2, Self::UserAddressCity, Self::UserAddressPincode, Self::UserAddressState, Self::UserAddressCountry { options: vec![] }, ] } pub fn get_shipping_variants() -> Vec { vec![ Self::UserShippingName, Self::UserShippingAddressLine1, Self::UserShippingAddressLine2, Self::UserShippingAddressCity, Self::UserShippingAddressPincode, Self::UserShippingAddressState, Self::UserShippingAddressCountry { options: vec![] }, ] } } /// This implementatiobn is to ignore the inner value of UserAddressCountry enum while comparing impl PartialEq for FieldType { fn eq(&self, other: &Self) -> bool { match (self, other) { (Self::UserCardNumber, Self::UserCardNumber) => true, (Self::UserCardExpiryMonth, Self::UserCardExpiryMonth) => true, (Self::UserCardExpiryYear, Self::UserCardExpiryYear) => true, (Self::UserCardCvc, Self::UserCardCvc) => true, (Self::UserFullName, Self::UserFullName) => true, (Self::UserEmailAddress, Self::UserEmailAddress) => true, (Self::UserPhoneNumber, Self::UserPhoneNumber) => true, (Self::UserCountryCode, Self::UserCountryCode) => true, ( Self::UserCountry { options: options_self, }, Self::UserCountry { options: options_other, }, ) => options_self.eq(options_other), ( Self::UserCurrency { options: options_self, }, Self::UserCurrency { options: options_other, }, ) => options_self.eq(options_other), (Self::UserBillingName, Self::UserBillingName) => true, (Self::UserAddressLine1, Self::UserAddressLine1) => true, (Self::UserAddressLine2, Self::UserAddressLine2) => true, (Self::UserAddressCity, Self::UserAddressCity) => true, (Self::UserAddressPincode, Self::UserAddressPincode) => true, (Self::UserAddressState, Self::UserAddressState) => true, (Self::UserAddressCountry { .. }, Self::UserAddressCountry { .. }) => true, (Self::UserShippingName, Self::UserShippingName) => true, (Self::UserShippingAddressLine1, Self::UserShippingAddressLine1) => true, (Self::UserShippingAddressLine2, Self::UserShippingAddressLine2) => true, (Self::UserShippingAddressCity, Self::UserShippingAddressCity) => true, (Self::UserShippingAddressPincode, Self::UserShippingAddressPincode) => true, (Self::UserShippingAddressState, Self::UserShippingAddressState) => true, (Self::UserShippingAddressCountry { .. }, Self::UserShippingAddressCountry { .. }) => { true } (Self::UserBlikCode, Self::UserBlikCode) => true, (Self::UserBank, Self::UserBank) => true, (Self::Text, Self::Text) => true, ( Self::DropDown { options: options_self, }, Self::DropDown { options: options_other, }, ) => options_self.eq(options_other), _unused => false, } } } #[cfg(test)] mod test { use super::*; #[test] fn test_partialeq_for_field_type() { let user_address_country_is_us = FieldType::UserAddressCountry { options: vec!["US".to_string()], }; let user_address_country_is_all = FieldType::UserAddressCountry { options: vec!["ALL".to_string()], }; assert!(user_address_country_is_us.eq(&user_address_country_is_all)) } } #[derive( Debug, serde::Deserialize, serde::Serialize, strum::Display, strum::EnumString, Clone, PartialEq, Eq, ToSchema, )] #[serde(rename_all = "snake_case")] #[strum(serialize_all = "snake_case")] pub enum RetryAction { /// Payment can be retried from the client side until the payment is successful or payment expires or the attempts(configured by the merchant) for payment are exhausted ManualRetry, /// Denotes that the payment is requeued Requeue, } #[derive(Clone, Copy)] pub enum LockerChoice { HyperswitchCardVault, } #[derive( Clone, Copy, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, strum::Display, strum::EnumString, frunk::LabelledGeneric, ToSchema, )] #[serde(rename_all = "snake_case")] #[strum(serialize_all = "snake_case")] pub enum PmAuthConnectors { Plaid, } pub fn convert_pm_auth_connector(connector_name: &str) -> Option { PmAuthConnectors::from_str(connector_name).ok() } pub fn convert_authentication_connector(connector_name: &str) -> Option { AuthenticationConnectors::from_str(connector_name).ok() } #[derive( Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, strum::Display, strum::EnumString, ToSchema, Hash, )] pub enum PaymentChargeType { #[serde(untagged)] Stripe(StripeChargeType), } impl Default for PaymentChargeType { fn default() -> Self { Self::Stripe(StripeChargeType::default()) } } #[derive( Clone, Debug, Default, Hash, Eq, PartialEq, ToSchema, serde::Serialize, serde::Deserialize, strum::Display, strum::EnumString, )] #[serde(rename_all = "lowercase")] #[strum(serialize_all = "lowercase")] pub enum StripeChargeType { #[default] Direct, Destination, } #[cfg(feature = "frm")] pub fn convert_frm_connector(connector_name: &str) -> Option { FrmConnectors::from_str(connector_name).ok() }