diff --git a/api-reference/v1/openapi_spec_v1.json b/api-reference/v1/openapi_spec_v1.json index 11e15b3737..4dfec0daef 100644 --- a/api-reference/v1/openapi_spec_v1.json +++ b/api-reference/v1/openapi_spec_v1.json @@ -11462,6 +11462,7 @@ "fiserv", "fiservemea", "fiuu", + "flexiti", "forte", "getnet", "globalpay", @@ -19474,6 +19475,18 @@ } } }, + { + "type": "object", + "required": [ + "flexiti_redirect" + ], + "properties": { + "flexiti_redirect": { + "type": "object", + "description": "For Flexiti Redirect as PayLater long term finance Option" + } + } + }, { "type": "object", "required": [ @@ -21360,6 +21373,7 @@ "efecty", "eft", "eps", + "flexiti", "fps", "evoucher", "giropay", @@ -28871,6 +28885,7 @@ "fiserv", "fiservemea", "fiuu", + "flexiti", "forte", "getnet", "globalpay", diff --git a/api-reference/v2/openapi_spec_v2.json b/api-reference/v2/openapi_spec_v2.json index a8bacd04ad..3dcaf86d16 100644 --- a/api-reference/v2/openapi_spec_v2.json +++ b/api-reference/v2/openapi_spec_v2.json @@ -8261,6 +8261,7 @@ "fiserv", "fiservemea", "fiuu", + "flexiti", "forte", "getnet", "globalpay", @@ -15459,6 +15460,18 @@ } } }, + { + "type": "object", + "required": [ + "flexiti_redirect" + ], + "properties": { + "flexiti_redirect": { + "type": "object", + "description": "For Flexiti Redirect as PayLater long term finance Option" + } + } + }, { "type": "object", "required": [ @@ -17863,6 +17876,7 @@ "efecty", "eft", "eps", + "flexiti", "fps", "evoucher", "giropay", @@ -22961,6 +22975,7 @@ "fiserv", "fiservemea", "fiuu", + "flexiti", "forte", "getnet", "globalpay", diff --git a/config/config.example.toml b/config/config.example.toml index 8ccd7ccf42..602f6a0a1d 100644 --- a/config/config.example.toml +++ b/config/config.example.toml @@ -756,6 +756,9 @@ sofort = { country = "AT,BE,DE,ES,IT,NL", currency = "EUR" } [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" } +[pm_filters.flexiti] +flexiti = { country = "CA", currency = "CAD" } + [pm_filters.nexixpay] credit = { country = "AT,BE,CY,EE,FI,FR,DE,GR,IE,IT,LV,LT,LU,MT,NL,PT,SK,SI,ES,BG,HR,DK,GB,NO,PL,CZ,RO,SE,CH,HU,AU,BR,US", currency = "ARS,AUD,BHD,CAD,CLP,CNY,COP,HRK,CZK,DKK,HKD,HUF,INR,JPY,KZT,JOD,KRW,KWD,MYR,MXN,NGN,NOK,PHP,QAR,RUB,SAR,SGD,VND,ZAR,SEK,CHF,THB,AED,EGP,GBP,USD,TWD,BYN,RSD,AZN,RON,TRY,AOA,BGN,EUR,UAH,PLN,BRL" } debit = { country = "AT,BE,CY,EE,FI,FR,DE,GR,IE,IT,LV,LT,LU,MT,NL,PT,SK,SI,ES,BG,HR,DK,GB,NO,PL,CZ,RO,SE,CH,HU,AU,BR,US", currency = "ARS,AUD,BHD,CAD,CLP,CNY,COP,HRK,CZK,DKK,HKD,HUF,INR,JPY,KZT,JOD,KRW,KWD,MYR,MXN,NGN,NOK,PHP,QAR,RUB,SAR,SGD,VND,ZAR,SEK,CHF,THB,AED,EGP,GBP,USD,TWD,BYN,RSD,AZN,RON,TRY,AOA,BGN,EUR,UAH,PLN,BRL" } diff --git a/config/deployments/integration_test.toml b/config/deployments/integration_test.toml index 662674331b..cc000bba6f 100644 --- a/config/deployments/integration_test.toml +++ b/config/deployments/integration_test.toml @@ -449,6 +449,9 @@ direct_carrier_billing = {country = "MA, CM, ZA, EG, SN, DZ, TN, ML, GN, GH, LY, [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" } +[pm_filters.flexiti] +flexiti = { country = "CA", currency = "CAD" } + [pm_filters.mifinity] mifinity = { country = "BR,CN,SG,MY,DE,CH,DK,GB,ES,AD,GI,FI,FR,GR,HR,IT,JP,MX,AR,CO,CL,PE,VE,UY,PY,BO,EC,GT,HN,SV,NI,CR,PA,DO,CU,PR,NL,NO,PL,PT,SE,RU,TR,TW,HK,MO,AX,AL,DZ,AS,AO,AI,AG,AM,AW,AU,AT,AZ,BS,BH,BD,BB,BE,BZ,BJ,BM,BT,BQ,BA,BW,IO,BN,BG,BF,BI,KH,CM,CA,CV,KY,CF,TD,CX,CC,KM,CG,CK,CI,CW,CY,CZ,DJ,DM,EG,GQ,ER,EE,ET,FK,FO,FJ,GF,PF,TF,GA,GM,GE,GH,GL,GD,GP,GU,GG,GN,GW,GY,HT,HM,VA,IS,IN,ID,IE,IM,IL,JE,JO,KZ,KE,KI,KW,KG,LA,LV,LB,LS,LI,LT,LU,MK,MG,MW,MV,ML,MT,MH,MQ,MR,MU,YT,FM,MD,MC,MN,ME,MS,MA,MZ,NA,NR,NP,NC,NZ,NE,NG,NU,NF,MP,OM,PK,PW,PS,PG,PH,PN,QA,RE,RO,RW,BL,SH,KN,LC,MF,PM,VC,WS,SM,ST,SA,SN,RS,SC,SL,SX,SK,SI,SB,SO,ZA,GS,KR,LK,SR,SJ,SZ,TH,TL,TG,TK,TO,TT,TN,TM,TC,TV,UG,UA,AE,UZ,VU,VN,VG,VI,WF,EH,ZM", currency = "AUD,CAD,CHF,CNY,CZK,DKK,EUR,GBP,INR,JPY,NOK,NZD,PLN,RUB,SEK,ZAR,USD,EGP,UYU,UZS" } diff --git a/config/deployments/production.toml b/config/deployments/production.toml index d7021cad93..189b0e951c 100644 --- a/config/deployments/production.toml +++ b/config/deployments/production.toml @@ -527,6 +527,9 @@ direct_carrier_billing = {country = "MA, CM, ZA, EG, SN, DZ, TN, ML, GN, GH, LY, [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" } +[pm_filters.flexiti] +flexiti = { country = "CA", currency = "CAD" } + [pm_filters.mifinity] mifinity = { country = "BR,CN,SG,MY,DE,CH,DK,GB,ES,AD,GI,FI,FR,GR,HR,IT,JP,MX,AR,CO,CL,PE,VE,UY,PY,BO,EC,GT,HN,SV,NI,CR,PA,DO,CU,PR,NL,NO,PL,PT,SE,RU,TR,TW,HK,MO,AX,AL,DZ,AS,AO,AI,AG,AM,AW,AU,AT,AZ,BS,BH,BD,BB,BE,BZ,BJ,BM,BT,BQ,BA,BW,IO,BN,BG,BF,BI,KH,CM,CA,CV,KY,CF,TD,CX,CC,KM,CG,CK,CI,CW,CY,CZ,DJ,DM,EG,GQ,ER,EE,ET,FK,FO,FJ,GF,PF,TF,GA,GM,GE,GH,GL,GD,GP,GU,GG,GN,GW,GY,HT,HM,VA,IS,IN,ID,IE,IM,IL,JE,JO,KZ,KE,KI,KW,KG,LA,LV,LB,LS,LI,LT,LU,MK,MG,MW,MV,ML,MT,MH,MQ,MR,MU,YT,FM,MD,MC,MN,ME,MS,MA,MZ,NA,NR,NP,NC,NZ,NE,NG,NU,NF,MP,OM,PK,PW,PS,PG,PH,PN,QA,RE,RO,RW,BL,SH,KN,LC,MF,PM,VC,WS,SM,ST,SA,SN,RS,SC,SL,SX,SK,SI,SB,SO,ZA,GS,KR,LK,SR,SJ,SZ,TH,TL,TG,TK,TO,TT,TN,TM,TC,TV,UG,UA,AE,UZ,VU,VN,VG,VI,WF,EH,ZM", currency = "AUD,CAD,CHF,CNY,CZK,DKK,EUR,GBP,INR,JPY,NOK,NZD,PLN,RUB,SEK,ZAR,USD,EGP,UYU,UZS" } diff --git a/config/deployments/sandbox.toml b/config/deployments/sandbox.toml index 6add5cd4c4..1096a37646 100644 --- a/config/deployments/sandbox.toml +++ b/config/deployments/sandbox.toml @@ -536,6 +536,9 @@ credit = { country = "FR", currency = "CAD, AUD, EUR, USD" } [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" } +[pm_filters.flexiti] +flexiti = { country = "CA", currency = "CAD" } + [pm_filters.mifinity] mifinity = { country = "BR,CN,SG,MY,DE,CH,DK,GB,ES,AD,GI,FI,FR,GR,HR,IT,JP,MX,AR,CO,CL,PE,VE,UY,PY,BO,EC,GT,HN,SV,NI,CR,PA,DO,CU,PR,NL,NO,PL,PT,SE,RU,TR,TW,HK,MO,AX,AL,DZ,AS,AO,AI,AG,AM,AW,AU,AT,AZ,BS,BH,BD,BB,BE,BZ,BJ,BM,BT,BQ,BA,BW,IO,BN,BG,BF,BI,KH,CM,CA,CV,KY,CF,TD,CX,CC,KM,CG,CK,CI,CW,CY,CZ,DJ,DM,EG,GQ,ER,EE,ET,FK,FO,FJ,GF,PF,TF,GA,GM,GE,GH,GL,GD,GP,GU,GG,GN,GW,GY,HT,HM,VA,IS,IN,ID,IE,IM,IL,JE,JO,KZ,KE,KI,KW,KG,LA,LV,LB,LS,LI,LT,LU,MK,MG,MW,MV,ML,MT,MH,MQ,MR,MU,YT,FM,MD,MC,MN,ME,MS,MA,MZ,NA,NR,NP,NC,NZ,NE,NG,NU,NF,MP,OM,PK,PW,PS,PG,PH,PN,QA,RE,RO,RW,BL,SH,KN,LC,MF,PM,VC,WS,SM,ST,SA,SN,RS,SC,SL,SX,SK,SI,SB,SO,ZA,GS,KR,LK,SR,SJ,SZ,TH,TL,TG,TK,TO,TT,TN,TM,TC,TV,UG,UA,AE,UZ,VU,VN,VG,VI,WF,EH,ZM", currency = "AUD,CAD,CHF,CNY,CZK,DKK,EUR,GBP,INR,JPY,NOK,NZD,PLN,RUB,SEK,ZAR,USD,EGP,UYU,UZS" } diff --git a/config/development.toml b/config/development.toml index 0a4ef25114..c94d40d825 100644 --- a/config/development.toml +++ b/config/development.toml @@ -696,6 +696,9 @@ google_pay = { country = "AL, DZ, AS, AO, AR, AU, AZ, BH, BY, BR, BG, CA, CL, CO [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 = "AUD,EUR,EUR,CAD,CZK,DKK,EUR,EUR,EUR,EUR,EUR,EUR,EUR,NZD,NOK,PLN,EUR,EUR,SEK,CHF,GBP,USD" } +[pm_filters.flexiti] +flexiti = { country = "CA", currency = "CAD" } + [pm_filters.mifinity] mifinity = { country = "BR,CN,SG,MY,DE,CH,DK,GB,ES,AD,GI,FI,FR,GR,HR,IT,JP,MX,AR,CO,CL,PE,VE,UY,PY,BO,EC,GT,HN,SV,NI,CR,PA,DO,CU,PR,NL,NO,PL,PT,SE,RU,TR,TW,HK,MO,AX,AL,DZ,AS,AO,AI,AG,AM,AW,AU,AT,AZ,BS,BH,BD,BB,BE,BZ,BJ,BM,BT,BQ,BA,BW,IO,BN,BG,BF,BI,KH,CM,CA,CV,KY,CF,TD,CX,CC,KM,CG,CK,CI,CW,CY,CZ,DJ,DM,EG,GQ,ER,EE,ET,FK,FO,FJ,GF,PF,TF,GA,GM,GE,GH,GL,GD,GP,GU,GG,GN,GW,GY,HT,HM,VA,IS,IN,ID,IE,IM,IL,JE,JO,KZ,KE,KI,KW,KG,LA,LV,LB,LS,LI,LT,LU,MK,MG,MW,MV,ML,MT,MH,MQ,MR,MU,YT,FM,MD,MC,MN,ME,MS,MA,MZ,NA,NR,NP,NC,NZ,NE,NG,NU,NF,MP,OM,PK,PW,PS,PG,PH,PN,QA,RE,RO,RW,BL,SH,KN,LC,MF,PM,VC,WS,SM,ST,SA,SN,RS,SC,SL,SX,SK,SI,SB,SO,ZA,GS,KR,LK,SR,SJ,SZ,TH,TL,TG,TK,TO,TT,TN,TM,TC,TV,UG,UA,AE,UZ,VU,VN,VG,VI,WF,EH,ZM", currency = "AUD,CAD,CHF,CNY,CZK,DKK,EUR,GBP,INR,JPY,NOK,NZD,PLN,RUB,SEK,ZAR,USD,EGP,UYU,UZS" } diff --git a/config/docker_compose.toml b/config/docker_compose.toml index a5d8958254..4c26568df3 100644 --- a/config/docker_compose.toml +++ b/config/docker_compose.toml @@ -703,6 +703,9 @@ sofort = { country = "AT,BE,DE,ES,IT,NL", currency = "EUR" } [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" } +[pm_filters.flexiti] +flexiti = { country = "CA", currency = "CAD" } + [pm_filters.mifinity] mifinity = { country = "BR,CN,SG,MY,DE,CH,DK,GB,ES,AD,GI,FI,FR,GR,HR,IT,JP,MX,AR,CO,CL,PE,VE,UY,PY,BO,EC,GT,HN,SV,NI,CR,PA,DO,CU,PR,NL,NO,PL,PT,SE,RU,TR,TW,HK,MO,AX,AL,DZ,AS,AO,AI,AG,AM,AW,AU,AT,AZ,BS,BH,BD,BB,BE,BZ,BJ,BM,BT,BQ,BA,BW,IO,BN,BG,BF,BI,KH,CM,CA,CV,KY,CF,TD,CX,CC,KM,CG,CK,CI,CW,CY,CZ,DJ,DM,EG,GQ,ER,EE,ET,FK,FO,FJ,GF,PF,TF,GA,GM,GE,GH,GL,GD,GP,GU,GG,GN,GW,GY,HT,HM,VA,IS,IN,ID,IE,IM,IL,JE,JO,KZ,KE,KI,KW,KG,LA,LV,LB,LS,LI,LT,LU,MK,MG,MW,MV,ML,MT,MH,MQ,MR,MU,YT,FM,MD,MC,MN,ME,MS,MA,MZ,NA,NR,NP,NC,NZ,NE,NG,NU,NF,MP,OM,PK,PW,PS,PG,PH,PN,QA,RE,RO,RW,BL,SH,KN,LC,MF,PM,VC,WS,SM,ST,SA,SN,RS,SC,SL,SX,SK,SI,SB,SO,ZA,GS,KR,LK,SR,SJ,SZ,TH,TL,TG,TK,TO,TT,TN,TM,TC,TV,UG,UA,AE,UZ,VU,VN,VG,VI,WF,EH,ZM", currency = "AUD,CAD,CHF,CNY,CZK,DKK,EUR,GBP,INR,JPY,NOK,NZD,PLN,RUB,SEK,ZAR,USD,EGP,UYU,UZS" } diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs index fed4f29c4d..a3e7cc9d51 100644 --- a/crates/api_models/src/payments.rs +++ b/crates/api_models/src/payments.rs @@ -2192,6 +2192,8 @@ pub enum PayLaterData { }, /// For PayBright Redirect as PayLater Option PayBrightRedirect {}, + /// For Flexiti Redirect as PayLater long term finance Option + FlexitiRedirect {}, /// For WalleyRedirect as PayLater Option WalleyRedirect {}, /// For Alma Redirection as PayLater Option @@ -2234,6 +2236,7 @@ impl GetAddressFromPaymentMethodData for PayLaterData { }) } Self::PayBrightRedirect {} + | Self::FlexitiRedirect {} | Self::WalleyRedirect {} | Self::AlmaRedirect {} | Self::KlarnaSdk { .. } @@ -2706,6 +2709,7 @@ impl GetPaymentMethodType for PayLaterData { Self::AffirmRedirect {} => api_enums::PaymentMethodType::Affirm, Self::AfterpayClearpayRedirect { .. } => api_enums::PaymentMethodType::AfterpayClearpay, Self::PayBrightRedirect {} => api_enums::PaymentMethodType::PayBright, + Self::FlexitiRedirect {} => api_enums::PaymentMethodType::Flexiti, Self::WalleyRedirect {} => api_enums::PaymentMethodType::Walley, Self::AlmaRedirect {} => api_enums::PaymentMethodType::Alma, Self::AtomeRedirect {} => api_enums::PaymentMethodType::Atome, diff --git a/crates/common_enums/src/connector_enums.rs b/crates/common_enums/src/connector_enums.rs index 5d8dabda9c..8d5b737b8b 100644 --- a/crates/common_enums/src/connector_enums.rs +++ b/crates/common_enums/src/connector_enums.rs @@ -97,6 +97,7 @@ pub enum RoutableConnectors { Fiserv, Fiservemea, Fiuu, + Flexiti, Forte, Getnet, Globalpay, @@ -262,6 +263,7 @@ pub enum Connector { Fiserv, Fiservemea, Fiuu, + Flexiti, Forte, Getnet, Globalpay, @@ -447,6 +449,7 @@ impl Connector { | Self::Fiserv | Self::Fiservemea | Self::Fiuu + | Self::Flexiti | Self::Forte | Self::Getnet | Self::Globalpay @@ -617,6 +620,7 @@ impl From for Connector { RoutableConnectors::Fiserv => Self::Fiserv, RoutableConnectors::Fiservemea => Self::Fiservemea, RoutableConnectors::Fiuu => Self::Fiuu, + RoutableConnectors::Flexiti => Self::Flexiti, RoutableConnectors::Forte => Self::Forte, RoutableConnectors::Getnet => Self::Getnet, RoutableConnectors::Globalpay => Self::Globalpay, @@ -744,6 +748,7 @@ impl TryFrom for RoutableConnectors { Connector::Fiserv => Ok(Self::Fiserv), Connector::Fiservemea => Ok(Self::Fiservemea), Connector::Fiuu => Ok(Self::Fiuu), + Connector::Flexiti => Ok(Self::Flexiti), Connector::Forte => Ok(Self::Forte), Connector::Globalpay => Ok(Self::Globalpay), Connector::Globepay => Ok(Self::Globepay), diff --git a/crates/common_enums/src/enums.rs b/crates/common_enums/src/enums.rs index a2912e73c4..423677ead9 100644 --- a/crates/common_enums/src/enums.rs +++ b/crates/common_enums/src/enums.rs @@ -1921,6 +1921,7 @@ pub enum PaymentMethodType { Efecty, Eft, Eps, + Flexiti, Fps, Evoucher, Giropay, @@ -2041,6 +2042,7 @@ impl PaymentMethodType { Self::Efecty => "Efecty", Self::Eft => "EFT", Self::Eps => "EPS", + Self::Flexiti => "Flexiti", Self::Fps => "FPS", Self::Evoucher => "Evoucher", Self::Giropay => "Giropay", diff --git a/crates/common_enums/src/transformers.rs b/crates/common_enums/src/transformers.rs index 549be0e0dc..3e5c50f220 100644 --- a/crates/common_enums/src/transformers.rs +++ b/crates/common_enums/src/transformers.rs @@ -1826,6 +1826,7 @@ impl From for PaymentMethod { PaymentMethodType::Dana => Self::Wallet, PaymentMethodType::DanamonVa => Self::BankTransfer, PaymentMethodType::Debit => Self::Card, + PaymentMethodType::Flexiti => Self::PayLater, PaymentMethodType::Fps => Self::RealTimePayment, PaymentMethodType::DuitNow => Self::RealTimePayment, PaymentMethodType::Eft => Self::BankRedirect, diff --git a/crates/connector_configs/src/connector.rs b/crates/connector_configs/src/connector.rs index 75e64aee9a..13111c8406 100644 --- a/crates/connector_configs/src/connector.rs +++ b/crates/connector_configs/src/connector.rs @@ -418,6 +418,7 @@ impl ConnectorConfig { Connector::Fiserv => Ok(connector_data.fiserv), Connector::Fiservemea => Ok(connector_data.fiservemea), Connector::Fiuu => Ok(connector_data.fiuu), + Connector::Flexiti => Ok(connector_data.flexiti), Connector::Forte => Ok(connector_data.forte), Connector::Getnet => Ok(connector_data.getnet), Connector::Globalpay => Ok(connector_data.globalpay), diff --git a/crates/connector_configs/toml/development.toml b/crates/connector_configs/toml/development.toml index 90aae59361..fbd76d7bf9 100644 --- a/crates/connector_configs/toml/development.toml +++ b/crates/connector_configs/toml/development.toml @@ -6451,10 +6451,6 @@ api_key = "API Key" api_key = "API Key" key1 = "API Secret" -[flexiti] -[flexiti.connector_auth.HeaderKey] -api_key = "API Key" - [mpgs] [mpgs.connector_auth.HeaderKey] api_key = "API Key" @@ -6462,3 +6458,12 @@ api_key = "API Key" [bluecode] [bluecode.connector_auth.HeaderKey] api_key = "API Key" + +[flexiti] +[flexiti.connector_auth.bodykey] +api_key = "Client id" +key1 = "Client secret" +[[flexiti.pay_later]] +payment_method_type = "flexiti" +payment_experience = "redirect_to_url" + diff --git a/crates/connector_configs/toml/production.toml b/crates/connector_configs/toml/production.toml index 704d85ea66..ca3f066395 100644 --- a/crates/connector_configs/toml/production.toml +++ b/crates/connector_configs/toml/production.toml @@ -5059,16 +5059,19 @@ api_key = "API Key" [blackhawknetwork.connector_auth.HeaderKey] api_key = "API Key" +[flexiti] +[flexiti.connector_auth.bodykey] +api_key = "Client id" +key1 = "Client secret" +[[flexiti.pay_later]] +payment_method_type = "flexiti" +payment_experience = "redirect_to_url" + [breadpay] [breadpay.connector_auth.BodyKey] api_key = "API Key" key1 = "API Secret" - -[flexiti] -[flexiti.connector_auth.HeaderKey] -api_key = "API Key" - [mpgs] [mpgs.connector_auth.HeaderKey] api_key = "API Key" diff --git a/crates/connector_configs/toml/sandbox.toml b/crates/connector_configs/toml/sandbox.toml index 22819c5d4b..e4327c88e5 100644 --- a/crates/connector_configs/toml/sandbox.toml +++ b/crates/connector_configs/toml/sandbox.toml @@ -6432,10 +6432,6 @@ api_key = "API Key" api_key = "API Key" key1 = "API Secret" -[flexiti] -[flexiti.connector_auth.HeaderKey] -api_key = "API Key" - [mpgs] [mpgs.connector_auth.HeaderKey] api_key = "API Key" @@ -6443,3 +6439,12 @@ api_key = "API Key" [bluecode] [bluecode.connector_auth.HeaderKey] api_key = "API Key" + +[flexiti] +[flexiti.connector_auth.bodykey] +api_key = "Client id" +key1 = "Client secret" +[[flexiti.pay_later]] +payment_method_type = "flexiti" +payment_experience = "redirect_to_url" + diff --git a/crates/euclid/src/frontend/dir/enums.rs b/crates/euclid/src/frontend/dir/enums.rs index 677a3068ee..af30a30a3e 100644 --- a/crates/euclid/src/frontend/dir/enums.rs +++ b/crates/euclid/src/frontend/dir/enums.rs @@ -55,6 +55,7 @@ pub enum PayLaterType { Klarna, PayBright, Walley, + Flexiti, Atome, Breadpay, } diff --git a/crates/euclid/src/frontend/dir/lowering.rs b/crates/euclid/src/frontend/dir/lowering.rs index d0e8477336..3bd8dda085 100644 --- a/crates/euclid/src/frontend/dir/lowering.rs +++ b/crates/euclid/src/frontend/dir/lowering.rs @@ -28,6 +28,7 @@ impl From for global_enums::PaymentMethodType { enums::PayLaterType::Affirm => Self::Affirm, enums::PayLaterType::AfterpayClearpay => Self::AfterpayClearpay, enums::PayLaterType::Alma => Self::Alma, + enums::PayLaterType::Flexiti => Self::Flexiti, enums::PayLaterType::Klarna => Self::Klarna, enums::PayLaterType::PayBright => Self::PayBright, enums::PayLaterType::Walley => Self::Walley, diff --git a/crates/euclid/src/frontend/dir/transformers.rs b/crates/euclid/src/frontend/dir/transformers.rs index 757616b797..d707b8ef5b 100644 --- a/crates/euclid/src/frontend/dir/transformers.rs +++ b/crates/euclid/src/frontend/dir/transformers.rs @@ -102,6 +102,7 @@ impl IntoDirValue for (global_enums::PaymentMethodType, global_enums::PaymentMet global_enums::PaymentMethodType::Bizum => Ok(dirval!(BankRedirectType = Bizum)), global_enums::PaymentMethodType::PayBright => Ok(dirval!(PayLaterType = PayBright)), + global_enums::PaymentMethodType::Flexiti => Ok(dirval!(PayLaterType = Flexiti)), global_enums::PaymentMethodType::Walley => Ok(dirval!(PayLaterType = Walley)), global_enums::PaymentMethodType::Breadpay => Ok(dirval!(PayLaterType = Breadpay)), global_enums::PaymentMethodType::Przelewy24 => { diff --git a/crates/hyperswitch_connectors/src/connectors/adyen.rs b/crates/hyperswitch_connectors/src/connectors/adyen.rs index 6ece7d16e0..ce9f42f933 100644 --- a/crates/hyperswitch_connectors/src/connectors/adyen.rs +++ b/crates/hyperswitch_connectors/src/connectors/adyen.rs @@ -340,6 +340,7 @@ impl ConnectorValidation for Adyen { | PaymentMethodType::InstantBankTransferPoland | PaymentMethodType::IndonesianBankTransfer | PaymentMethodType::SepaBankTransfer + | PaymentMethodType::Flexiti | PaymentMethodType::RevolutPay => { capture_method_not_supported!(connector, capture_method, payment_method_type) } diff --git a/crates/hyperswitch_connectors/src/connectors/adyen/transformers.rs b/crates/hyperswitch_connectors/src/connectors/adyen/transformers.rs index 5b424ec5d4..18f120c7c5 100644 --- a/crates/hyperswitch_connectors/src/connectors/adyen/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/adyen/transformers.rs @@ -2430,12 +2430,12 @@ impl check_required_field(billing_address, "billing")?; Ok(AdyenPaymentMethod::Atome) } - PayLaterData::KlarnaSdk { .. } | PayLaterData::BreadpayRedirect {} => { - Err(errors::ConnectorError::NotImplemented( - utils::get_unimplemented_payment_method_error_message("Adyen"), - ) - .into()) - } + PayLaterData::KlarnaSdk { .. } + | PayLaterData::BreadpayRedirect {} + | PayLaterData::FlexitiRedirect {} => Err(errors::ConnectorError::NotImplemented( + utils::get_unimplemented_payment_method_error_message("Adyen"), + ) + .into()), } } } diff --git a/crates/hyperswitch_connectors/src/connectors/breadpay/transformers.rs b/crates/hyperswitch_connectors/src/connectors/breadpay/transformers.rs index a62881ca6d..9230c6f5f5 100644 --- a/crates/hyperswitch_connectors/src/connectors/breadpay/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/breadpay/transformers.rs @@ -91,6 +91,7 @@ impl TryFrom<&BreadpayRouterData<&PaymentsAuthorizeRouterData>> for BreadpayCart hyperswitch_domain_models::payment_method_data::PayLaterData::WalleyRedirect { } | hyperswitch_domain_models::payment_method_data::PayLaterData::KlarnaSdk { .. } | hyperswitch_domain_models::payment_method_data::PayLaterData::AffirmRedirect { } | + hyperswitch_domain_models::payment_method_data::PayLaterData::FlexitiRedirect { } | hyperswitch_domain_models::payment_method_data::PayLaterData::AfterpayClearpayRedirect { } | hyperswitch_domain_models::payment_method_data::PayLaterData::PayBrightRedirect { } | hyperswitch_domain_models::payment_method_data::PayLaterData::AlmaRedirect { } | diff --git a/crates/hyperswitch_connectors/src/connectors/flexiti.rs b/crates/hyperswitch_connectors/src/connectors/flexiti.rs index 29c1f2c8cf..b14094ca06 100644 --- a/crates/hyperswitch_connectors/src/connectors/flexiti.rs +++ b/crates/hyperswitch_connectors/src/connectors/flexiti.rs @@ -7,7 +7,7 @@ use common_utils::{ errors::CustomResult, ext_traits::BytesExt, request::{Method, Request, RequestBuilder, RequestContent}, - types::{AmountConvertor, StringMinorUnit, StringMinorUnitForConnector}, + types::{AmountConvertor, FloatMajorUnit, FloatMajorUnitForConnector}, }; use error_stack::{report, ResultExt}; use hyperswitch_domain_models::{ @@ -24,7 +24,8 @@ use hyperswitch_domain_models::{ RefundsData, SetupMandateRequestData, }, router_response_types::{ - ConnectorInfo, PaymentsResponseData, RefundsResponseData, SupportedPaymentMethods, + ConnectorInfo, PaymentMethodDetails, PaymentsResponseData, RefundsResponseData, + SupportedPaymentMethods, SupportedPaymentMethodsExt, }, types::{ PaymentsAuthorizeRouterData, PaymentsCaptureRouterData, PaymentsSyncRouterData, @@ -42,20 +43,26 @@ use hyperswitch_interfaces::{ types::{self, Response}, webhooks, }; -use masking::{ExposeInterface, Mask}; +use masking::PeekInterface; use transformers as flexiti; +use uuid::Uuid; -use crate::{constants::headers, types::ResponseRouterData, utils}; +use crate::{ + capture_method_not_supported, + constants::headers, + types::{RefreshTokenRouterData, ResponseRouterData}, + utils, +}; #[derive(Clone)] pub struct Flexiti { - amount_converter: &'static (dyn AmountConvertor + Sync), + amount_converter: &'static (dyn AmountConvertor + Sync), } impl Flexiti { pub fn new() -> &'static Self { &Self { - amount_converter: &StringMinorUnitForConnector, + amount_converter: &FloatMajorUnitForConnector, } } } @@ -79,6 +86,15 @@ impl ConnectorIntegration (String, masking::Maskable) { + ( + "x-reference-id".to_string(), + Uuid::new_v4().to_string().into(), + ) + } +} + impl ConnectorCommonExt for Flexiti where Self: ConnectorIntegration, @@ -88,12 +104,15 @@ where req: &RouterData, _connectors: &Connectors, ) -> CustomResult)>, errors::ConnectorError> { + let access_token = req + .access_token + .clone() + .ok_or(errors::ConnectorError::FailedToObtainAuthType)?; let mut header = vec![( - headers::CONTENT_TYPE.to_string(), - self.get_content_type().to_string().into(), + headers::AUTHORIZATION.to_string(), + format!("Bearer {}", access_token.token.peek()).into(), )]; - let mut api_key = self.get_auth_header(&req.connector_auth_type)?; - header.append(&mut api_key); + header.push(Self::get_default_header()); Ok(header) } } @@ -105,13 +124,10 @@ impl ConnectorCommon for Flexiti { fn get_currency_unit(&self) -> api::CurrencyUnit { api::CurrencyUnit::Base - // TODO! Check connector documentation, on which unit they are processing the currency. - // If the connector accepts amount in lower unit ( i.e cents for USD) then return api::CurrencyUnit::Minor, - // if connector accepts amount in base unit (i.e dollars for USD) then return api::CurrencyUnit::Base } fn common_get_content_type(&self) -> &'static str { - "application/json" + "application/x-www-form-urlencoded" } fn base_url<'a>(&self, connectors: &'a Connectors) -> &'a str { @@ -120,14 +136,9 @@ impl ConnectorCommon for Flexiti { fn get_auth_header( &self, - auth_type: &ConnectorAuthType, + _auth_type: &ConnectorAuthType, ) -> CustomResult)>, errors::ConnectorError> { - let auth = flexiti::FlexitiAuthType::try_from(auth_type) - .change_context(errors::ConnectorError::FailedToObtainAuthType)?; - Ok(vec![( - headers::AUTHORIZATION.to_string(), - auth.api_key.expose().into_masked(), - )]) + Ok(vec![]) } fn build_error_response( @@ -145,9 +156,9 @@ impl ConnectorCommon for Flexiti { Ok(ErrorResponse { status_code: res.status_code, - code: response.code, - message: response.message, - reason: response.reason, + code: response.error.to_owned(), + message: response.message.to_owned(), + reason: Some(response.message.to_owned()), attempt_status: None, connector_transaction_id: None, network_advice_code: None, @@ -172,6 +183,35 @@ impl ConnectorValidation for Flexiti { } } + fn validate_connector_against_payment_request( + &self, + capture_method: Option, + _payment_method: common_enums::PaymentMethod, + pmt: Option, + ) -> CustomResult<(), errors::ConnectorError> { + let capture_method = capture_method.unwrap_or_default(); + + match capture_method { + enums::CaptureMethod::Manual => Ok(()), + enums::CaptureMethod::Automatic + | enums::CaptureMethod::SequentialAutomatic + | enums::CaptureMethod::ManualMultiple + | enums::CaptureMethod::Scheduled => { + let connector = self.id(); + match pmt { + Some(payment_method_type) => { + capture_method_not_supported!( + connector, + capture_method, + payment_method_type + ) + } + None => capture_method_not_supported!(connector, capture_method), + } + } + } + } + fn validate_psync_reference_id( &self, _data: &PaymentsSyncData, @@ -183,12 +223,87 @@ impl ConnectorValidation for Flexiti { } } +impl ConnectorIntegration for Flexiti { + fn get_url( + &self, + _req: &RefreshTokenRouterData, + connectors: &Connectors, + ) -> CustomResult { + Ok(format!("{}oauth/token", self.base_url(connectors))) + } + fn get_content_type(&self) -> &'static str { + "application/x-www-form-urlencoded" + } + fn get_headers( + &self, + _req: &RefreshTokenRouterData, + _connectors: &Connectors, + ) -> CustomResult)>, errors::ConnectorError> { + Ok(vec![(Self::get_default_header())]) + } + fn get_request_body( + &self, + req: &RefreshTokenRouterData, + _connectors: &Connectors, + ) -> CustomResult { + let connector_req = flexiti::FlexitiAccessTokenRequest::try_from(req)?; + Ok(RequestContent::FormUrlEncoded(Box::new(connector_req))) + } + + fn build_request( + &self, + req: &RefreshTokenRouterData, + connectors: &Connectors, + ) -> CustomResult, errors::ConnectorError> { + let req = Some( + RequestBuilder::new() + .method(Method::Post) + .attach_default_headers() + .headers(types::RefreshTokenType::get_headers(self, req, connectors)?) + .url(&types::RefreshTokenType::get_url(self, req, connectors)?) + .set_body(types::RefreshTokenType::get_request_body( + self, req, connectors, + )?) + .build(), + ); + + Ok(req) + } + + fn handle_response( + &self, + data: &RefreshTokenRouterData, + event_builder: Option<&mut ConnectorEvent>, + res: Response, + ) -> CustomResult { + let response: flexiti::FlexitiAccessTokenResponse = res + .response + .parse_struct("FlexitiAccessTokenResponse") + .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; + + event_builder.map(|i| i.set_response_body(&response)); + router_env::logger::info!(connector_response=?response); + + RouterData::try_from(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 Flexiti { //TODO: implement sessions flow } -impl ConnectorIntegration for Flexiti {} - impl ConnectorIntegration for Flexiti {} impl ConnectorIntegration for Flexiti { @@ -206,10 +321,15 @@ impl ConnectorIntegration CustomResult { - Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into()) + let auth_details = flexiti::FlexitiAuthType::try_from(&req.connector_auth_type)?; + Ok(format!( + "{}online/v2/client-id/{:?}/systems/init", + self.base_url(connectors), + auth_details.client_id.peek() + )) } fn get_request_body( @@ -293,10 +413,21 @@ impl ConnectorIntegration for Fle fn get_url( &self, - _req: &PaymentsSyncRouterData, - _connectors: &Connectors, + req: &PaymentsSyncRouterData, + connectors: &Connectors, ) -> CustomResult { - Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into()) + let auth_details = flexiti::FlexitiAuthType::try_from(&req.connector_auth_type.to_owned())?; + let order_id = req + .request + .connector_transaction_id + .get_connector_transaction_id() + .change_context(errors::ConnectorError::RequestEncodingFailed)?; + Ok(format!( + "{}online/client-id/{}/notifications/order-id/{}", + self.base_url(connectors), + auth_details.client_id.peek(), + order_id + )) } fn build_request( @@ -320,9 +451,9 @@ impl ConnectorIntegration for Fle event_builder: Option<&mut ConnectorEvent>, res: Response, ) -> CustomResult { - let response: flexiti::FlexitiPaymentsResponse = res + let response: flexiti::FlexitiSyncResponse = res .response - .parse_struct("flexiti PaymentsSyncResponse") + .parse_struct("flexiti FlexitiSyncResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; event_builder.map(|i| i.set_response_body(&response)); router_env::logger::info!(connector_response=?response); @@ -596,8 +727,23 @@ impl webhooks::IncomingWebhook for Flexiti { } } -static FLEXITI_SUPPORTED_PAYMENT_METHODS: LazyLock = - LazyLock::new(SupportedPaymentMethods::new); +static FLEXITI_SUPPORTED_PAYMENT_METHODS: LazyLock = LazyLock::new(|| { + let supported_capture_methods = vec![enums::CaptureMethod::Manual]; + let mut flexiti_supported_payment_methods = SupportedPaymentMethods::new(); + + flexiti_supported_payment_methods.add( + enums::PaymentMethod::PayLater, + enums::PaymentMethodType::Klarna, + PaymentMethodDetails { + mandates: enums::FeatureStatus::NotSupported, + refunds: enums::FeatureStatus::NotSupported, + supported_capture_methods, + specific_features: None, + }, + ); + + flexiti_supported_payment_methods +}); static FLEXITI_CONNECTOR_INFO: ConnectorInfo = ConnectorInfo { display_name: "Flexiti", diff --git a/crates/hyperswitch_connectors/src/connectors/flexiti/transformers.rs b/crates/hyperswitch_connectors/src/connectors/flexiti/transformers.rs index df706398ed..666c800cbf 100644 --- a/crates/hyperswitch_connectors/src/connectors/flexiti/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/flexiti/transformers.rs @@ -1,28 +1,32 @@ use common_enums::enums; -use common_utils::types::StringMinorUnit; +use common_utils::{pii::Email, request::Method, types::FloatMajorUnit}; use hyperswitch_domain_models::{ payment_method_data::PaymentMethodData, - router_data::{ConnectorAuthType, RouterData}, + router_data::{AccessToken, ConnectorAuthType, RouterData}, router_flow_types::refunds::{Execute, RSync}, router_request_types::ResponseId, - router_response_types::{PaymentsResponseData, RefundsResponseData}, + router_response_types::{PaymentsResponseData, RedirectForm, RefundsResponseData}, types::{PaymentsAuthorizeRouterData, RefundsRouterData}, }; use hyperswitch_interfaces::errors; use masking::Secret; use serde::{Deserialize, Serialize}; -use crate::types::{RefundsResponseRouterData, ResponseRouterData}; +use crate::{ + types::{self, RefundsResponseRouterData, ResponseRouterData}, + utils::{ + self, AddressDetailsData, BrowserInformationData, PaymentsAuthorizeRequestData, + RouterData as _, + }, +}; -//TODO: Fill the struct with respective fields pub struct FlexitiRouterData { - pub amount: StringMinorUnit, // The type of amount that a connector accepts, for example, String, i64, f64, etc. + pub amount: FloatMajorUnit, // The type of amount that a connector accepts, for example, String, i64, f64, etc. pub router_data: T, } -impl From<(StringMinorUnit, T)> for FlexitiRouterData { - fn from((amount, item): (StringMinorUnit, T)) -> Self { - //Todo : use utils to convert the amount to the type of amount that a connector accepts +impl From<(FloatMajorUnit, T)> for FlexitiRouterData { + fn from((amount, item): (FloatMajorUnit, T)) -> Self { Self { amount, router_data: item, @@ -30,20 +34,46 @@ impl From<(StringMinorUnit, T)> for FlexitiRouterData { } } -//TODO: Fill the struct with respective fields -#[derive(Default, Debug, Serialize, PartialEq)] +#[derive(Debug, Serialize)] pub struct FlexitiPaymentsRequest { - amount: StringMinorUnit, - card: FlexitiCard, + merchant_order_id: Option, + lang: String, + flow: FlexitiFlow, + amount_requested: FloatMajorUnit, + email: Option, + fname: Secret, + billing_information: BillingInformation, + shipping_information: ShippingInformation, } -#[derive(Default, Debug, Serialize, Eq, PartialEq)] -pub struct FlexitiCard { - number: cards::CardNumber, - expiry_month: Secret, - expiry_year: Secret, - cvc: Secret, - complete: bool, +#[derive(Debug, Serialize)] +#[serde(rename_all = "snake_case")] +pub enum FlexitiFlow { + #[serde(rename = "apply/buy")] + ApplyAndBuy, + Apply, + Buy, +} +#[derive(Debug, Serialize)] +pub struct BillingInformation { + first_name: Secret, + last_name: Secret, + address_1: Secret, + address_2: Secret, + city: Secret, + postal_code: Secret, + province: Secret, +} + +#[derive(Debug, Serialize)] +pub struct ShippingInformation { + first_name: Secret, + last_name: Secret, + address_1: Secret, + address_2: Secret, + city: Secret, + postal_code: Secret, + province: Secret, } impl TryFrom<&FlexitiRouterData<&PaymentsAuthorizeRouterData>> for FlexitiPaymentsRequest { @@ -52,58 +82,185 @@ impl TryFrom<&FlexitiRouterData<&PaymentsAuthorizeRouterData>> for FlexitiPaymen item: &FlexitiRouterData<&PaymentsAuthorizeRouterData>, ) -> Result { match item.router_data.request.payment_method_data.clone() { - PaymentMethodData::Card(_) => Err(errors::ConnectorError::NotImplemented( - "Card payment method not implemented".to_string(), - ) - .into()), + PaymentMethodData::PayLater(pay_later_data) => match pay_later_data { + hyperswitch_domain_models::payment_method_data::PayLaterData::FlexitiRedirect { } => { + let shipping_address = item.router_data.get_shipping_address()?; + let shipping_information = ShippingInformation { + first_name: shipping_address.get_first_name()?.to_owned(), + last_name: shipping_address.get_last_name()?.to_owned(), + address_1: shipping_address.get_line1()?.to_owned(), + address_2: shipping_address.get_line2()?.to_owned(), + city: shipping_address.get_city()?.to_owned().into(), + postal_code: shipping_address.get_zip()?.to_owned(), + province: shipping_address.to_state_code()?, + }; + let billing_information = BillingInformation { + first_name: item.router_data.get_billing_first_name()?, + last_name: item.router_data.get_billing_last_name()?, + address_1: item.router_data.get_billing_line1()?, + address_2: item.router_data.get_billing_line2()?, + city: item.router_data.get_billing_city()?.into(), + postal_code: item.router_data.get_billing_zip()?, + province: item.router_data.get_billing_state_code()?, + }; + Ok(Self { + merchant_order_id: item.router_data.request.merchant_order_reference_id.to_owned(), + lang: item.router_data.request.get_browser_info()?.get_language()?, + flow: FlexitiFlow::ApplyAndBuy, + amount_requested: item.amount.to_owned(), + email: item.router_data.get_optional_billing_email(), + fname: item.router_data.get_billing_first_name()?, + billing_information, + shipping_information, + }) + }, + hyperswitch_domain_models::payment_method_data::PayLaterData::KlarnaRedirect { } | + hyperswitch_domain_models::payment_method_data::PayLaterData::KlarnaSdk { .. } | + hyperswitch_domain_models::payment_method_data::PayLaterData::AffirmRedirect { } | + hyperswitch_domain_models::payment_method_data::PayLaterData::BreadpayRedirect { } | + hyperswitch_domain_models::payment_method_data::PayLaterData::AfterpayClearpayRedirect { } | + hyperswitch_domain_models::payment_method_data::PayLaterData::PayBrightRedirect { } | + hyperswitch_domain_models::payment_method_data::PayLaterData::WalleyRedirect { } | + hyperswitch_domain_models::payment_method_data::PayLaterData::AlmaRedirect { } | + hyperswitch_domain_models::payment_method_data::PayLaterData::AtomeRedirect { } => { + Err(errors::ConnectorError::NotImplemented( + utils::get_unimplemented_payment_method_error_message("flexiti"), + )) + }?, + } _ => Err(errors::ConnectorError::NotImplemented("Payment method".to_string()).into()), } } } -//TODO: Fill the struct with respective fields +#[derive(Debug, Serialize)] +pub struct FlexitiAccessTokenRequest { + client_id: Secret, + client_secret: Secret, + grant_type: FlexitiGranttype, +} + +#[derive(Debug, Serialize)] +#[serde(rename_all = "snake_case")] +pub enum FlexitiGranttype { + Password, + RefreshToken, + ClientCredentials, +} + +impl TryFrom<&types::RefreshTokenRouterData> for FlexitiAccessTokenRequest { + type Error = error_stack::Report; + fn try_from(item: &types::RefreshTokenRouterData) -> Result { + let auth_details = FlexitiAuthType::try_from(&item.connector_auth_type)?; + + Ok(Self { + client_id: auth_details.client_id, + client_secret: auth_details.client_secret, + grant_type: FlexitiGranttype::ClientCredentials, + }) + } +} + +impl TryFrom> + for RouterData +{ + type Error = error_stack::Report; + fn try_from( + item: ResponseRouterData, + ) -> Result { + Ok(Self { + response: Ok(AccessToken { + token: item.response.access_token, + expires: item.response.expires_in, + }), + ..item.data + }) + } +} + // Auth Struct pub struct FlexitiAuthType { - pub(super) api_key: Secret, + pub(super) client_id: Secret, + pub(super) client_secret: Secret, } impl TryFrom<&ConnectorAuthType> for FlexitiAuthType { 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(), + ConnectorAuthType::BodyKey { api_key, key1 } => Ok(Self { + client_id: api_key.to_owned(), + client_secret: key1.to_owned(), }), _ => Err(errors::ConnectorError::FailedToObtainAuthType.into()), } } } -// PaymentsResponse -//TODO: Append the remaining status flags -#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq)] -#[serde(rename_all = "lowercase")] -pub enum FlexitiPaymentStatus { - Succeeded, - Failed, - #[default] - Processing, + +#[derive(Debug, Serialize, Deserialize)] +pub struct FlexitiAccessTokenResponse { + access_token: Secret, + expires_in: i64, } -impl From for common_enums::AttemptStatus { - fn from(item: FlexitiPaymentStatus) -> Self { +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct FlexitiPaymentsResponse { + redirection_url: url::Url, + online_order_id: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct FlexitiSyncResponse { + transaction_id: String, + purchase: FlexitiPurchase, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct FlexitiPurchase { + status: FlexitiPurchaseStatus, +} + +// Since this is an alpha integration, we don't have access to all the status mapping. This needs to be updated. +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum FlexitiPurchaseStatus { + Success, + Failed, +} + +// Since this is an alpha integration, we don't have access to all the status mapping. This needs to be updated. +impl From for common_enums::AttemptStatus { + fn from(item: FlexitiPurchaseStatus) -> Self { match item { - FlexitiPaymentStatus::Succeeded => Self::Charged, - FlexitiPaymentStatus::Failed => Self::Failure, - FlexitiPaymentStatus::Processing => Self::Authorizing, + FlexitiPurchaseStatus::Success => Self::Authorized, + FlexitiPurchaseStatus::Failed => Self::Failure, } } } -//TODO: Fill the struct with respective fields -#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)] -pub struct FlexitiPaymentsResponse { - status: FlexitiPaymentStatus, - id: String, +impl TryFrom> + for RouterData +{ + type Error = error_stack::Report; + fn try_from( + item: ResponseRouterData, + ) -> Result { + Ok(Self { + status: common_enums::AttemptStatus::from(item.response.purchase.status), + response: Ok(PaymentsResponseData::TransactionResponse { + resource_id: ResponseId::ConnectorTransactionId( + item.response.transaction_id.to_owned(), + ), + redirection_data: Box::new(None), + mandate_reference: Box::new(None), + connector_metadata: None, + network_txn_id: None, + connector_response_reference_id: None, + incremental_authorization_allowed: None, + charges: None, + }), + ..item.data + }) + } } impl TryFrom> @@ -114,10 +271,15 @@ impl TryFrom, ) -> Result { Ok(Self { - status: common_enums::AttemptStatus::from(item.response.status), + status: common_enums::AttemptStatus::AuthenticationPending, response: Ok(PaymentsResponseData::TransactionResponse { - resource_id: ResponseId::ConnectorTransactionId(item.response.id), - redirection_data: Box::new(None), + resource_id: ResponseId::ConnectorTransactionId( + item.response.online_order_id.to_owned(), + ), + redirection_data: Box::new(Some(RedirectForm::from(( + item.response.redirection_url, + Method::Get, + )))), mandate_reference: Box::new(None), connector_metadata: None, network_txn_id: None, @@ -135,7 +297,7 @@ impl TryFrom TryFrom<&FlexitiRouterData<&RefundsRouterData>> for FlexitiRefundRequest { @@ -206,14 +368,8 @@ impl TryFrom> for RefundsRouter } } -//TODO: Fill the struct with respective fields -#[derive(Default, Debug, Serialize, Deserialize, PartialEq)] +#[derive(Debug, Serialize, Deserialize)] pub struct FlexitiErrorResponse { - pub status_code: u16, - pub code: String, pub message: String, - pub reason: Option, - pub network_advice_code: Option, - pub network_decline_code: Option, - pub network_error_message: Option, + pub error: String, } diff --git a/crates/hyperswitch_connectors/src/connectors/klarna.rs b/crates/hyperswitch_connectors/src/connectors/klarna.rs index 4adec86a57..adb79c08e7 100644 --- a/crates/hyperswitch_connectors/src/connectors/klarna.rs +++ b/crates/hyperswitch_connectors/src/connectors/klarna.rs @@ -644,6 +644,7 @@ impl ConnectorIntegration> PayLaterData::KlarnaRedirect {} => item.router_data.get_billing_email()?, PayLaterData::KlarnaSdk { token: _ } | PayLaterData::AffirmRedirect {} + | PayLaterData::FlexitiRedirect {} | PayLaterData::AfterpayClearpayRedirect {} | PayLaterData::PayBrightRedirect {} | PayLaterData::WalleyRedirect {} diff --git a/crates/hyperswitch_connectors/src/connectors/nuvei/transformers.rs b/crates/hyperswitch_connectors/src/connectors/nuvei/transformers.rs index 986d7ec7f0..b68ecb83f3 100644 --- a/crates/hyperswitch_connectors/src/connectors/nuvei/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/nuvei/transformers.rs @@ -1006,6 +1006,7 @@ where get_pay_later_info(AlternativePaymentMethodType::AfterPay, item) } PayLaterData::KlarnaSdk { .. } + | PayLaterData::FlexitiRedirect {} | PayLaterData::AffirmRedirect {} | PayLaterData::PayBrightRedirect {} | PayLaterData::WalleyRedirect {} diff --git a/crates/hyperswitch_connectors/src/connectors/paypal/transformers.rs b/crates/hyperswitch_connectors/src/connectors/paypal/transformers.rs index 9ffc5a0c13..6d93ad4cf4 100644 --- a/crates/hyperswitch_connectors/src/connectors/paypal/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/paypal/transformers.rs @@ -1264,6 +1264,7 @@ impl TryFrom<&PaypalRouterData<&PaymentsAuthorizeRouterData>> for PaypalPayments | enums::PaymentMethodType::Mifinity | enums::PaymentMethodType::Paze | enums::PaymentMethodType::IndonesianBankTransfer + | enums::PaymentMethodType::Flexiti | enums::PaymentMethodType::RevolutPay | enums::PaymentMethodType::Breadpay => { Err(errors::ConnectorError::NotImplemented( @@ -1321,6 +1322,7 @@ impl TryFrom<&PayLaterData> for PaypalPaymentsRequest { | PayLaterData::AfterpayClearpayRedirect { .. } | PayLaterData::PayBrightRedirect {} | PayLaterData::WalleyRedirect {} + | PayLaterData::FlexitiRedirect {} | PayLaterData::AlmaRedirect {} | PayLaterData::AtomeRedirect {} | PayLaterData::BreadpayRedirect {} => Err(errors::ConnectorError::NotImplemented( diff --git a/crates/hyperswitch_connectors/src/connectors/shift4/transformers.rs b/crates/hyperswitch_connectors/src/connectors/shift4/transformers.rs index b66edc9bf7..2370330d17 100644 --- a/crates/hyperswitch_connectors/src/connectors/shift4/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/shift4/transformers.rs @@ -296,6 +296,7 @@ impl TryFrom<&PayLaterData> for PaymentMethodType { | PayLaterData::WalleyRedirect { .. } | PayLaterData::AlmaRedirect { .. } | PayLaterData::AtomeRedirect { .. } + | PayLaterData::FlexitiRedirect { .. } | PayLaterData::KlarnaSdk { .. } | PayLaterData::BreadpayRedirect { .. } => Err(errors::ConnectorError::NotImplemented( utils::get_unimplemented_payment_method_error_message("Shift4"), diff --git a/crates/hyperswitch_connectors/src/connectors/square/transformers.rs b/crates/hyperswitch_connectors/src/connectors/square/transformers.rs index fb6a345899..76f70a5b6f 100644 --- a/crates/hyperswitch_connectors/src/connectors/square/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/square/transformers.rs @@ -89,6 +89,7 @@ impl TryFrom<(&types::TokenizationRouterData, PayLaterData)> for SquareTokenRequ | PayLaterData::PayBrightRedirect { .. } | PayLaterData::WalleyRedirect { .. } | PayLaterData::AlmaRedirect { .. } + | PayLaterData::FlexitiRedirect { .. } | PayLaterData::AtomeRedirect { .. } | PayLaterData::BreadpayRedirect { .. } => { Err(errors::ConnectorError::NotImplemented( diff --git a/crates/hyperswitch_connectors/src/connectors/stripe/transformers.rs b/crates/hyperswitch_connectors/src/connectors/stripe/transformers.rs index d566b0548d..016a4f23f5 100644 --- a/crates/hyperswitch_connectors/src/connectors/stripe/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/stripe/transformers.rs @@ -833,6 +833,7 @@ impl TryFrom for StripePaymentMethodType { | enums::PaymentMethodType::PromptPay | enums::PaymentMethodType::VietQr | enums::PaymentMethodType::IndonesianBankTransfer + | enums::PaymentMethodType::Flexiti | enums::PaymentMethodType::Mifinity | enums::PaymentMethodType::Breadpay => Err(ConnectorError::NotImplemented( get_unimplemented_payment_method_error_message("stripe"), @@ -1069,6 +1070,7 @@ impl TryFrom<&PayLaterData> for StripePaymentMethodType { | PayLaterData::PayBrightRedirect {} | PayLaterData::WalleyRedirect {} | PayLaterData::AlmaRedirect {} + | PayLaterData::FlexitiRedirect { .. } | PayLaterData::AtomeRedirect {} | PayLaterData::BreadpayRedirect {} => Err(ConnectorError::NotImplemented( get_unimplemented_payment_method_error_message("stripe"), diff --git a/crates/hyperswitch_connectors/src/connectors/zen/transformers.rs b/crates/hyperswitch_connectors/src/connectors/zen/transformers.rs index 9af9745f2e..7aa2b8d865 100644 --- a/crates/hyperswitch_connectors/src/connectors/zen/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/zen/transformers.rs @@ -765,6 +765,7 @@ impl TryFrom<&PayLaterData> for ZenPaymentsRequest { | PayLaterData::PayBrightRedirect {} | PayLaterData::WalleyRedirect {} | PayLaterData::AlmaRedirect {} + | PayLaterData::FlexitiRedirect {} | PayLaterData::AtomeRedirect {} | PayLaterData::BreadpayRedirect {} => Err(errors::ConnectorError::NotImplemented( utils::get_unimplemented_payment_method_error_message("Zen"), diff --git a/crates/hyperswitch_connectors/src/utils.rs b/crates/hyperswitch_connectors/src/utils.rs index 428329680c..bb157a0fc3 100644 --- a/crates/hyperswitch_connectors/src/utils.rs +++ b/crates/hyperswitch_connectors/src/utils.rs @@ -5486,6 +5486,7 @@ pub enum PaymentMethodDataType { AlmaRedirect, AtomeRedirect, Breadpay, + FlexitiRedirect, BancontactCard, Bizum, Blik, @@ -5618,6 +5619,7 @@ impl From for PaymentMethodDataType { payment_method_data::PayLaterData::AfterpayClearpayRedirect { .. } => { Self::AfterpayClearpayRedirect } + payment_method_data::PayLaterData::FlexitiRedirect { .. } => Self::FlexitiRedirect, payment_method_data::PayLaterData::PayBrightRedirect {} => Self::PayBrightRedirect, payment_method_data::PayLaterData::WalleyRedirect {} => Self::WalleyRedirect, payment_method_data::PayLaterData::AlmaRedirect {} => Self::AlmaRedirect, diff --git a/crates/hyperswitch_domain_models/src/payment_method_data.rs b/crates/hyperswitch_domain_models/src/payment_method_data.rs index 6b11233dbf..ae167b3a28 100644 --- a/crates/hyperswitch_domain_models/src/payment_method_data.rs +++ b/crates/hyperswitch_domain_models/src/payment_method_data.rs @@ -240,6 +240,7 @@ pub enum PayLaterData { AfterpayClearpayRedirect {}, PayBrightRedirect {}, WalleyRedirect {}, + FlexitiRedirect {}, AlmaRedirect {}, AtomeRedirect {}, BreadpayRedirect {}, @@ -1190,6 +1191,7 @@ impl From for PayLaterData { api_models::payments::PayLaterData::KlarnaRedirect { .. } => Self::KlarnaRedirect {}, api_models::payments::PayLaterData::KlarnaSdk { token } => Self::KlarnaSdk { token }, api_models::payments::PayLaterData::AffirmRedirect {} => Self::AffirmRedirect {}, + api_models::payments::PayLaterData::FlexitiRedirect {} => Self::FlexitiRedirect {}, api_models::payments::PayLaterData::AfterpayClearpayRedirect { .. } => { Self::AfterpayClearpayRedirect {} } @@ -1888,6 +1890,7 @@ impl GetPaymentMethodType for PayLaterData { match self { Self::KlarnaRedirect { .. } => api_enums::PaymentMethodType::Klarna, Self::KlarnaSdk { .. } => api_enums::PaymentMethodType::Klarna, + Self::FlexitiRedirect { .. } => api_enums::PaymentMethodType::Flexiti, Self::AffirmRedirect {} => api_enums::PaymentMethodType::Affirm, Self::AfterpayClearpayRedirect { .. } => api_enums::PaymentMethodType::AfterpayClearpay, Self::PayBrightRedirect {} => api_enums::PaymentMethodType::PayBright, diff --git a/crates/kgraph_utils/src/mca.rs b/crates/kgraph_utils/src/mca.rs index 4c648f8e5d..f0f45a2cae 100644 --- a/crates/kgraph_utils/src/mca.rs +++ b/crates/kgraph_utils/src/mca.rs @@ -34,6 +34,7 @@ fn get_dir_value_payment_method( api_enums::PaymentMethodType::Eps => Ok(dirval!(BankRedirectType = Eps)), api_enums::PaymentMethodType::Eft => Ok(dirval!(BankRedirectType = Eft)), api_enums::PaymentMethodType::Klarna => Ok(dirval!(PayLaterType = Klarna)), + api_enums::PaymentMethodType::Flexiti => Ok(dirval!(PayLaterType = Flexiti)), api_enums::PaymentMethodType::Affirm => Ok(dirval!(PayLaterType = Affirm)), api_enums::PaymentMethodType::AfterpayClearpay => { Ok(dirval!(PayLaterType = AfterpayClearpay)) diff --git a/crates/kgraph_utils/src/transformers.rs b/crates/kgraph_utils/src/transformers.rs index d9a9aee272..8261a3645d 100644 --- a/crates/kgraph_utils/src/transformers.rs +++ b/crates/kgraph_utils/src/transformers.rs @@ -226,6 +226,7 @@ impl IntoDirValue for (api_enums::PaymentMethodType, api_enums::PaymentMethod) { api_enums::PaymentMethodType::Trustly => Ok(dirval!(BankRedirectType = Trustly)), api_enums::PaymentMethodType::Bizum => Ok(dirval!(BankRedirectType = Bizum)), api_enums::PaymentMethodType::PayBright => Ok(dirval!(PayLaterType = PayBright)), + api_enums::PaymentMethodType::Flexiti => Ok(dirval!(PayLaterType = Flexiti)), api_enums::PaymentMethodType::Walley => Ok(dirval!(PayLaterType = Walley)), api_enums::PaymentMethodType::Breadpay => Ok(dirval!(PayLaterType = Breadpay)), api_enums::PaymentMethodType::Przelewy24 => Ok(dirval!(BankRedirectType = Przelewy24)), diff --git a/crates/payment_methods/src/configs/payment_connector_required_fields.rs b/crates/payment_methods/src/configs/payment_connector_required_fields.rs index bc38786c9e..801b02c920 100644 --- a/crates/payment_methods/src/configs/payment_connector_required_fields.rs +++ b/crates/payment_methods/src/configs/payment_connector_required_fields.rs @@ -2733,6 +2733,33 @@ fn get_pay_later_required_fields() -> HashMap matches!( payment_method_type, diff --git a/crates/router/src/connector/utils.rs b/crates/router/src/connector/utils.rs index 02839ee8d7..653cc01e1f 100644 --- a/crates/router/src/connector/utils.rs +++ b/crates/router/src/connector/utils.rs @@ -2463,6 +2463,7 @@ pub enum PaymentMethodDataType { AlmaRedirect, AtomeRedirect, BreadpayRedirect, + FlexitiRedirect, BancontactCard, Bizum, Blik, @@ -2597,6 +2598,7 @@ impl From for PaymentMethodDataType { domain::payments::PayLaterData::PayBrightRedirect {} => Self::PayBrightRedirect, domain::payments::PayLaterData::WalleyRedirect {} => Self::WalleyRedirect, domain::payments::PayLaterData::AlmaRedirect {} => Self::AlmaRedirect, + domain::payments::PayLaterData::FlexitiRedirect {} => Self::FlexitiRedirect, domain::payments::PayLaterData::AtomeRedirect {} => Self::AtomeRedirect, domain::payments::PayLaterData::BreadpayRedirect {} => Self::BreadpayRedirect, }, diff --git a/crates/router/src/core/connector_validation.rs b/crates/router/src/core/connector_validation.rs index 7d18e8927a..ccf9ee5e9d 100644 --- a/crates/router/src/core/connector_validation.rs +++ b/crates/router/src/core/connector_validation.rs @@ -236,6 +236,10 @@ impl ConnectorAuthTypeAndMetadataValidation<'_> { fiuu::transformers::FiuuAuthType::try_from(self.auth_type)?; Ok(()) } + api_enums::Connector::Flexiti => { + flexiti::transformers::FlexitiAuthType::try_from(self.auth_type)?; + Ok(()) + } api_enums::Connector::Forte => { forte::transformers::ForteAuthType::try_from(self.auth_type)?; Ok(()) diff --git a/crates/router/src/types/api/connector_mapping.rs b/crates/router/src/types/api/connector_mapping.rs index aca02ede25..06094e6d86 100644 --- a/crates/router/src/types/api/connector_mapping.rs +++ b/crates/router/src/types/api/connector_mapping.rs @@ -251,6 +251,9 @@ impl ConnectorData { Ok(ConnectorEnum::Old(Box::new(connector::Fiservemea::new()))) } enums::Connector::Fiuu => Ok(ConnectorEnum::Old(Box::new(connector::Fiuu::new()))), + enums::Connector::Flexiti => { + Ok(ConnectorEnum::Old(Box::new(connector::Flexiti::new()))) + } enums::Connector::Forte => { Ok(ConnectorEnum::Old(Box::new(connector::Forte::new()))) } diff --git a/crates/router/src/types/connector_transformers.rs b/crates/router/src/types/connector_transformers.rs index a6e43d7aed..52479a4f03 100644 --- a/crates/router/src/types/connector_transformers.rs +++ b/crates/router/src/types/connector_transformers.rs @@ -57,6 +57,7 @@ impl ForeignTryFrom for common_enums::RoutableConnectors { api_enums::Connector::Fiserv => Self::Fiserv, api_enums::Connector::Fiservemea => Self::Fiservemea, api_enums::Connector::Fiuu => Self::Fiuu, + api_enums::Connector::Flexiti => Self::Flexiti, api_enums::Connector::Forte => Self::Forte, api_enums::Connector::Getnet => Self::Getnet, api_enums::Connector::Globalpay => Self::Globalpay, diff --git a/crates/router/src/types/transformers.rs b/crates/router/src/types/transformers.rs index daf630e689..7b38342a74 100644 --- a/crates/router/src/types/transformers.rs +++ b/crates/router/src/types/transformers.rs @@ -295,6 +295,7 @@ impl ForeignFrom for api_enums::PaymentMethod { | api_enums::PaymentMethodType::Alma | api_enums::PaymentMethodType::AfterpayClearpay | api_enums::PaymentMethodType::Klarna + | api_enums::PaymentMethodType::Flexiti | api_enums::PaymentMethodType::PayBright | api_enums::PaymentMethodType::Atome | api_enums::PaymentMethodType::Walley diff --git a/loadtest/config/development.toml b/loadtest/config/development.toml index 08904ba688..77a5f69a1e 100644 --- a/loadtest/config/development.toml +++ b/loadtest/config/development.toml @@ -510,6 +510,9 @@ crypto_currency = { country = "US, CA, GB, AU, BR, MX, SG, PH, NZ, ZA, JP, AT, B [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" } +[pm_filters.flexiti] +flexiti = { country = "CA", currency = "CAD" } + [pm_filters.bluesnap] credit = { country = "AD,AE,AG,AL,AM,AO,AR,AT,AU,AZ,BA,BB,BD,BE,BG,BH,BI,BJ,BN,BO,BR,BS,BT,BW,BY,BZ,CA,CD,CF,CG,CH,CI,CL,CM,CN,CO,CR,CV,CY,CZ,DE,DK,DJ,DM,DO,DZ,EC,EE,EG,ER,ES,ET,FI,FJ,FM,FR,GA,GB,GD,GE,GG,GH,GM,GN,GQ,GR,GT,GW,GY,HN,HR,HT,HU,ID,IE,IL,IN,IS,IT,JM,JP,JO,KE,KG,KH,KI,KM,KN,KR,KW,KZ,LA,LB,LC,LI,LK,LR,LS,LT,LU,LV,MA,MC,MD,ME,MG,MH,MK,ML,MM,MN,MR,MT,MU,MV,MW,MX,MY,MZ,NA,NE,NG,NI,NL,NO,NP,NR,NZ,OM,PA,PE,PG,PH,PK,PL,PS,PT,PW,PY,QA,RO,RS,RW,SA,SB,SC,SE,SG,SI,SK,SL,SM,SN,SO,SR,SS,ST,SV,SZ,TD,TG,TH,TJ,TL,TM,TN,TO,TR,TT,TV,TZ,UA,UG,US,UY,UZ,VA,VC,VE,VN,VU,WS,ZA,ZM,ZW", currency = "AED,AFN,ALL,AMD,ANG,ARS,AUD,AWG,BAM,BBD,BGN,BHD,BMD,BND,BOB,BRL,BSD,BWP,CAD,CHF,CLP,CNY,COP,CRC,CZK,DKK,DOP,DZD,EGP,EUR,FJD,GBP,GEL,GIP,GTQ,HKD,HUF,IDR,ILS,INR,ISK,JMD,JPY,KES,KHR,KRW,KWD,KYD,KZT,LBP,LKR,MAD,MDL,MKD,MUR,MWK,MXN,MYR,NAD,NGN,NOK,NPR,NZD,OMR,PAB,PEN,PGK,PHP,PLN,PKR,QAR,RON,RSD,RUB,SAR,SCR,SDG,SEK,SGD,THB,TND,TRY,TTD,TWD,TZS,UAH,USD,UYU,UZS,VND,XAF,XCD,XOF,ZAR"} google_pay = { country = "AL, DZ, AS, AO, AG, AR, AU, AT, AZ, BH, BY, BE, BR, BG, 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, US, UY, VN", currency = "ALL, DZD, USD, XCD, ARS, AUD, EUR, BHD, BRL, BGN, CAD, CLP, COP, CZK, DKK, DOP, EGP, HKD, HUF, INR, IDR, ILS, JPY, KZT, KES, KWD, LBP, MYR, MXN, NZD, NOK, OMR, PKR, PAB, PEN, PHP, PLN, QAR, RON, RUB, SAR, SGD, ZAR, LKR, SEK, CHF, TWD, THB, TRY, UAH, AED, GBP, UYU, VND"}