diff --git a/api-reference-v2/api-reference/payment-methods/payment-method--payment-methods-list.mdx b/api-reference-v2/api-reference/payment-methods/payment-method--payment-methods-list.mdx new file mode 100644 index 000000000000..7131915402ac --- /dev/null +++ b/api-reference-v2/api-reference/payment-methods/payment-method--payment-methods-list.mdx @@ -0,0 +1,3 @@ +--- +openapi: get /v2/payment-methods/{id}/list-payment-methods +--- \ No newline at end of file diff --git a/api-reference-v2/mint.json b/api-reference-v2/mint.json index 080adae5ad1c..706f90b97088 100644 --- a/api-reference-v2/mint.json +++ b/api-reference-v2/mint.json @@ -49,13 +49,13 @@ "group": "Payment Methods", "pages": [ "api-reference/payment-methods/payment-method--create", - "api-reference/payment-methods/payment-method--retrieve", - "api-reference/payment-methods/payment-method--update", - "api-reference/payment-methods/payment-method--delete", "api-reference/payment-methods/payment-method--create-intent", + "api-reference/payment-methods/payment-method--payment-methods-list", "api-reference/payment-methods/payment-method--confirm-intent", - "api-reference/payment-methods/list-customer-saved-payment-methods-for-a-payment", - "api-reference/payment-methods/list-payment-methods-for-a-customer" + "api-reference/payment-methods/payment-method--update", + "api-reference/payment-methods/payment-method--retrieve", + "api-reference/payment-methods/payment-method--delete", + "api-reference/payment-methods/list-saved-payment-methods-for-a-customer" ] }, { diff --git a/api-reference-v2/openapi_spec.json b/api-reference-v2/openapi_spec.json index f1caede89ccc..139d2c85d133 100644 --- a/api-reference-v2/openapi_spec.json +++ b/api-reference-v2/openapi_spec.json @@ -2190,62 +2190,19 @@ ] } }, - "/v2/payments/{id}/saved-payment-methods": { - "get": { - "tags": [ - "Payment Methods" - ], - "summary": "List customer saved payment methods for a payment", - "description": "To filter and list the applicable payment methods for a particular Customer ID, is to be associated with a payment", - "operationId": "List all Payment Methods for a Customer", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PaymentMethodListRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Payment Methods retrieved for customer tied to its respective client-secret passed in the param", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CustomerPaymentMethodsListResponse" - } - } - } - }, - "400": { - "description": "Invalid Data" - }, - "404": { - "description": "Payment Methods does not exist in records" - } - }, - "security": [ - { - "publishable_key": [] - } - ] - } - }, - "/v2/customers/{id}/saved-payment-methods": { - "get": { + "/v2/payment-methods": { + "post": { "tags": [ "Payment Methods" ], - "summary": "List saved payment methods for a Customer", - "description": "To filter and list the applicable payment methods for a particular Customer ID, to be used in a non-payments context", - "operationId": "List all Payment Methods for a Customer", + "summary": "Payment Method - Create", + "description": "Creates and stores a payment method against a customer. In case of cards, this API should be used only by PCI compliant merchants.", + "operationId": "Create Payment Method", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/PaymentMethodListRequest" + "$ref": "#/components/schemas/PaymentMethodCreate" } } }, @@ -2253,20 +2210,17 @@ }, "responses": { "200": { - "description": "Payment Methods retrieved", + "description": "Payment Method Created", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CustomerPaymentMethodsListResponse" + "$ref": "#/components/schemas/PaymentMethodResponse" } } } }, "400": { "description": "Invalid Data" - }, - "404": { - "description": "Payment Methods does not exist in records" } }, "security": [ @@ -2276,19 +2230,19 @@ ] } }, - "/v2/payment-methods": { + "/v2/payment-methods/create-intent": { "post": { "tags": [ "Payment Methods" ], - "summary": "Payment Method - Create", - "description": "Creates and stores a payment method against a customer. In case of cards, this API should be used only by PCI compliant merchants.", - "operationId": "Create Payment Method", + "summary": "Payment Method - Create Intent", + "description": "Creates a payment method for customer with billing information and other metadata.", + "operationId": "Create Payment Method Intent", "requestBody": { "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/PaymentMethodCreate" + "$ref": "#/components/schemas/PaymentMethodIntentCreate" } } }, @@ -2296,7 +2250,7 @@ }, "responses": { "200": { - "description": "Payment Method Created", + "description": "Payment Method Intent Created", "content": { "application/json": { "schema": { @@ -2316,42 +2270,56 @@ ] } }, - "/v2/payment-methods/create-intent": { - "post": { + "/v2/payment-methods/{id}/list-payment-methods": { + "get": { "tags": [ "Payment Methods" ], - "summary": "Payment Method - Create Intent", - "description": "Creates a payment method for customer with billing information and other metadata.", - "operationId": "Create Payment Method Intent", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PaymentMethodIntentCreate" - } + "summary": "Payment Methods - Payment Methods List", + "description": "List the payment methods eligible for a payment. This endpoint also returns the saved payment methods for the customer.", + "operationId": "List Payment methods for a Payment Method Intent", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The global payment method id", + "required": true, + "schema": { + "type": "string" } }, - "required": true - }, + { + "name": "X-Profile-Id", + "in": "header", + "description": "Profile ID associated to the payment method intent", + "required": true, + "schema": { + "type": "string" + }, + "example": { + "X-Profile-Id": "pro_abcdefghijklmnop" + } + } + ], "responses": { "200": { - "description": "Payment Method Intent Created", + "description": "Get the payment methods", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/PaymentMethodResponse" + "$ref": "#/components/schemas/PaymentMethodListResponseForPayments" } } } }, - "400": { - "description": "Invalid Data" + "404": { + "description": "No payment method found with the given id" } }, "security": [ { - "api_key": [] + "api_key": [], + "ephemeral_key": [] } ] } @@ -6612,7 +6580,6 @@ }, "Connector": { "type": "string", - "description": "A connector is an integration to fulfill payments", "enum": [ "adyenplatform", "phonypay", @@ -7461,39 +7428,6 @@ }, "additionalProperties": false }, - "CustomerDefaultPaymentMethodResponse": { - "type": "object", - "required": [ - "customer_id", - "payment_method" - ], - "properties": { - "default_payment_method_id": { - "type": "string", - "description": "The unique identifier of the Payment method", - "example": "card_rGK4Vi5iSW70MY7J2mIg", - "nullable": true - }, - "customer_id": { - "type": "string", - "description": "The unique identifier of the customer.", - "example": "cus_y3oqhf46pyzuxjbcn2giaqnb44", - "maxLength": 64, - "minLength": 1 - }, - "payment_method": { - "$ref": "#/components/schemas/PaymentMethod" - }, - "payment_method_type": { - "allOf": [ - { - "$ref": "#/components/schemas/PaymentMethodType" - } - ], - "nullable": true - } - } - }, "CustomerDeleteResponse": { "type": "object", "required": [ @@ -7994,24 +7928,6 @@ "frictionless" ] }, - "DefaultPaymentMethod": { - "type": "object", - "required": [ - "customer_id", - "payment_method_id" - ], - "properties": { - "customer_id": { - "type": "string", - "example": "cus_y3oqhf46pyzuxjbcn2giaqnb44", - "maxLength": 64, - "minLength": 1 - }, - "payment_method_id": { - "type": "string" - } - } - }, "DeviceChannel": { "type": "string", "description": "Device Channel indicating whether request is coming from App or Browser", @@ -13896,13 +13812,13 @@ "PaymentMethodDeleteResponse": { "type": "object", "required": [ - "payment_method_id" + "id" ], "properties": { - "payment_method_id": { + "id": { "type": "string", "description": "The unique identifier of the Payment method", - "example": "card_rGK4Vi5iSW70MY7J2mIg" + "example": "12345_pm_01926c58bc6e77c09e809964e72af8c8" } } }, @@ -14079,67 +13995,15 @@ "PaymentMethodListResponse": { "type": "object", "required": [ - "currency", - "payment_methods", - "mandate_payment", - "show_surcharge_breakup_screen", - "request_external_three_ds_authentication", - "is_tax_calculation_enabled" + "payment_methods_enabled" ], "properties": { - "redirect_url": { - "type": "string", - "description": "Redirect URL of the merchant", - "example": "https://www.google.com", - "nullable": true - }, - "currency": { - "$ref": "#/components/schemas/Currency" - }, - "payment_methods": { + "payment_methods_enabled": { "type": "array", "items": { - "$ref": "#/components/schemas/ResponsePaymentMethodsEnabled" + "$ref": "#/components/schemas/ResponsePaymentMethodTypes" }, - "description": "Information about the payment method" - }, - "mandate_payment": { - "$ref": "#/components/schemas/MandateType" - }, - "merchant_name": { - "type": "string", - "nullable": true - }, - "show_surcharge_breakup_screen": { - "type": "boolean", - "description": "flag to indicate if surcharge and tax breakup screen should be shown or not" - }, - "payment_type": { - "allOf": [ - { - "$ref": "#/components/schemas/PaymentType" - } - ], - "nullable": true - }, - "request_external_three_ds_authentication": { - "type": "boolean", - "description": "flag to indicate whether to perform external 3ds authentication", - "example": true - }, - "collect_shipping_details_from_wallets": { - "type": "boolean", - "description": "flag that indicates whether to collect shipping details from wallets or from the customer", - "nullable": true - }, - "collect_billing_details_from_wallets": { - "type": "boolean", - "description": "flag that indicates whether to collect billing details from wallets or from the customer", - "nullable": true - }, - "is_tax_calculation_enabled": { - "type": "boolean", - "description": "flag that indicates whether to calculate tax on the order amount" + "description": "The list of payment methods that are enabled for the business profile" } } }, @@ -14152,7 +14016,7 @@ "payment_methods_enabled": { "type": "array", "items": { - "$ref": "#/components/schemas/ResponsePaymentMethodTypes" + "$ref": "#/components/schemas/ResponsePaymentMethodTypesForPayments" }, "description": "The list of payment methods that are enabled for the business profile" }, @@ -14169,13 +14033,18 @@ "PaymentMethodResponse": { "type": "object", "required": [ + "id", "merchant_id", "customer_id", - "payment_method_id", "payment_method_type", "recurring_enabled" ], "properties": { + "id": { + "type": "string", + "description": "The unique identifier of the Payment method", + "example": "12345_pm_01926c58bc6e77c09e809964e72af8c8" + }, "merchant_id": { "type": "string", "description": "Unique identifier for a merchant", @@ -14188,11 +14057,6 @@ "maxLength": 64, "minLength": 32 }, - "payment_method_id": { - "type": "string", - "description": "The unique identifier of the Payment method", - "example": "card_rGK4Vi5iSW70MY7J2mIg" - }, "payment_method_type": { "$ref": "#/components/schemas/PaymentMethod" }, @@ -14266,6 +14130,7 @@ "oneOf": [ { "type": "object", + "title": "card", "required": [ "card_networks" ], @@ -14280,6 +14145,7 @@ }, { "type": "object", + "title": "bank", "required": [ "bank_names" ], @@ -19194,21 +19060,56 @@ "type": "object", "required": [ "payment_method_type", - "payment_method_subtype" + "payment_method_subtype", + "required_fields" ], "properties": { "payment_method_type": { - "$ref": "#/components/schemas/PaymentMethodType" + "$ref": "#/components/schemas/PaymentMethod" }, "payment_method_subtype": { "$ref": "#/components/schemas/PaymentMethodType" }, "required_fields": { - "type": "object", - "description": "Required fields for the payment_method_type.\nThis is the union of all the required fields for the payment method type enabled in all the connectors.", - "additionalProperties": { + "type": "array", + "items": { "$ref": "#/components/schemas/RequiredFieldInfo" }, + "description": "Required fields for the payment_method_type.\nThis is the union of all the required fields for the payment method type enabled in all the connectors." + } + } + } + ] + }, + "ResponsePaymentMethodTypesForPayments": { + "allOf": [ + { + "allOf": [ + { + "$ref": "#/components/schemas/PaymentMethodSubtypeSpecificData" + } + ], + "nullable": true + }, + { + "type": "object", + "required": [ + "payment_method_type", + "payment_method_subtype" + ], + "properties": { + "payment_method_type": { + "$ref": "#/components/schemas/PaymentMethod" + }, + "payment_method_subtype": { + "$ref": "#/components/schemas/PaymentMethodType" + }, + "required_fields": { + "allOf": [ + { + "$ref": "#/components/schemas/RequiredFieldInfo" + } + ], "nullable": true }, "surcharge_details": { @@ -19441,7 +19342,7 @@ }, "RoutableConnectors": { "type": "string", - "description": "Connectors eligible for payments routing", + "description": "RoutableConnectors are the subset of Connectors that are eligible for payments routing", "enum": [ "adyenplatform", "phonypay", @@ -19519,7 +19420,6 @@ "wise", "worldline", "worldpay", - "xendit", "zen", "plaid", "zsl" diff --git a/api-reference/openapi_spec.json b/api-reference/openapi_spec.json index df7e96431dbc..ea07204088f1 100644 --- a/api-reference/openapi_spec.json +++ b/api-reference/openapi_spec.json @@ -9233,7 +9233,6 @@ }, "Connector": { "type": "string", - "description": "A connector is an integration to fulfill payments", "enum": [ "adyenplatform", "phonypay", @@ -23888,7 +23887,7 @@ }, "RoutableConnectors": { "type": "string", - "description": "Connectors eligible for payments routing", + "description": "RoutableConnectors are the subset of Connectors that are eligible for payments routing", "enum": [ "adyenplatform", "phonypay", @@ -23966,7 +23965,6 @@ "wise", "worldline", "worldpay", - "xendit", "zen", "plaid", "zsl" diff --git a/config/development.toml b/config/development.toml index e3631b96b173..08520a2a859d 100644 --- a/config/development.toml +++ b/config/development.toml @@ -229,8 +229,8 @@ elavon.base_url = "https://api.demo.convergepay.com/VirtualMerchantDemo/" fiserv.base_url = "https://cert.api.fiservapps.com/" fiservemea.base_url = "https://prod.emea.api.fiservapps.com/sandbox" fiuu.base_url = "https://sandbox.merchant.razer.com/" -fiuu.secondary_base_url="https://sandbox.merchant.razer.com/" -fiuu.third_base_url="https://api.merchant.razer.com/" +fiuu.secondary_base_url = "https://sandbox.merchant.razer.com/" +fiuu.third_base_url = "https://api.merchant.razer.com/" forte.base_url = "https://sandbox.forte.net/api/v3" globalpay.base_url = "https://apis.sandbox.globalpay.com/ucp/" globepay.base_url = "https://pay.globepay.co/" @@ -241,7 +241,7 @@ iatapay.base_url = "https://sandbox.iata-pay.iata.org/api/v1" inespay.base_url = "https://apiflow.inespay.com/san/v21" itaubank.base_url = "https://sandbox.devportal.itau.com.br/" jpmorgan.base_url = "https://api-mock.payments.jpmorgan.com/api/v2" -jpmorgan.secondary_base_url= "https://id.payments.jpmorgan.com" +jpmorgan.secondary_base_url = "https://id.payments.jpmorgan.com" klarna.base_url = "https://api{{klarna_region}}.playground.klarna.com/" mifinity.base_url = "https://demo.mifinity.com/" mollie.base_url = "https://api.mollie.com/v2/" @@ -259,7 +259,7 @@ nuvei.base_url = "https://ppp-test.nuvei.com/" opayo.base_url = "https://pi-test.sagepay.com/" opennode.base_url = "https://dev-api.opennode.com" paybox.base_url = "https://preprod-ppps.paybox.com/PPPS.php" -paybox.secondary_base_url="https://preprod-tpeweb.paybox.com/" +paybox.secondary_base_url = "https://preprod-tpeweb.paybox.com/" payeezy.base_url = "https://api-cert.payeezy.com/" payme.base_url = "https://sandbox.payme.io/" payone.base_url = "https://payment.preprod.payone.com/" @@ -343,7 +343,7 @@ adyen = { banks = "bank_austria,bawag_psk_ag,dolomitenbank,easybank_ag,erste_ban [bank_config.ideal] stripe = { banks = "abn_amro,asn_bank,bunq,handelsbanken,ing,knab,moneyou,rabobank,regiobank,revolut,sns_bank,triodos_bank,van_lanschot" } adyen = { banks = "abn_amro,asn_bank,bunq,ing,knab,n26,nationale_nederlanden,rabobank,regiobank,revolut,sns_bank,triodos_bank,van_lanschot, yoursafe" } -multisafepay = { banks="abn_amro, asn_bank, bunq, handelsbanken, nationale_nederlanden, n26, ing, knab, rabobank, regiobank, revolut, sns_bank,triodos_bank, van_lanschot, yoursafe" } +multisafepay = { banks = "abn_amro, asn_bank, bunq, handelsbanken, nationale_nederlanden, n26, ing, knab, rabobank, regiobank, revolut, sns_bank,triodos_bank, van_lanschot, yoursafe" } [bank_config.online_banking_czech_republic] adyen = { banks = "ceska_sporitelna,komercni_banka,platnosc_online_karta_platnicza" } @@ -395,10 +395,10 @@ cashapp = { country = "US", currency = "USD" } open_banking_uk = { country = "DE,GB,AT,BE,CY,EE,ES,FI,FR,GR,HR,IE,IT,LT,LU,LV,MT,NL,PT,SI,SK,BG,CZ,DK,HU,NO,PL,RO,SE,AU,BR", currency = "EUR,GBP,DKK,NOK,PLN,SEK,AUD,BRL" } [pm_filters.razorpay] -upi_collect = {country = "IN", currency = "INR"} +upi_collect = { country = "IN", currency = "INR" } [pm_filters.plaid] -open_banking_pis = {currency = "EUR,GBP"} +open_banking_pis = { currency = "EUR,GBP" } [pm_filters.adyen] google_pay = { country = "AU,NZ,JP,HK,SG,MY,TH,VN,BH,AE,KW,BR,ES,GB,SE,NO,SK,AT,NL,DE,HU,CY,LU,CH,BE,FR,DK,RO,HR,LI,MT,SI,GR,PT,IE,CZ,EE,LT,LV,IT,PL,TR,IS,CA,US", currency = "AED,ALL,AMD,ANG,AOA,ARS,AUD,AWG,AZN,BAM,BBD,BDT,BGN,BHD,BMD,BND,BOB,BRL,BSD,BWP,BYN,BZD,CAD,CHF,CLP,CNY,COP,CRC,CUP,CVE,CZK,DJF,DKK,DOP,DZD,EGP,ETB,EUR,FJD,FKP,GBP,GEL,GHS,GIP,GMD,GNF,GTQ,GYD,HKD,HNL,HTG,HUF,IDR,ILS,INR,IQD,JMD,JOD,JPY,KES,KGS,KHR,KMF,KRW,KWD,KYD,KZT,LAK,LBP,LKR,LYD,MAD,MDL,MKD,MMK,MNT,MOP,MRU,MUR,MVR,MWK,MXN,MYR,MZN,NAD,NGN,NIO,NOK,NPR,NZD,OMR,PAB,PEN,PGK,PHP,PKR,PLN,PYG,QAR,RON,RSD,RUB,RWF,SAR,SBD,SCR,SEK,SGD,SHP,SLE,SOS,SRD,STN,SVC,SZL,THB,TND,TOP,TRY,TTD,TWD,TZS,UAH,UGX,USD,UYU,UZS,VES,VND,VUV,WST,XAF,XCD,XOF,XPF,YER,ZAR,ZMW" } @@ -483,11 +483,11 @@ credit = { country = "AT,BE,CY,EE,FI,FR,DE,GR,IE,IT,LV,LT,LU,MT,NL,PT,SK,SI,ES,B 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", 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" } [pm_filters.novalnet] -credit = { country = "AD,AE,AL,AM,AR,AT,AU,AZ,BA,BB,BD,BE,BG,BH,BI,BM,BN,BO,BR,BS,BW,BY,BZ,CA,CD,CH,CL,CN,CO,CR,CU,CY,CZ,DE,DJ,DK,DO,DZ,EE,EG,ET,ES,FI,FJ,FR,GB,GE,GH,GI,GM,GR,GT,GY,HK,HN,HR,HU,ID,IE,IL,IN,IS,IT,JM,JO,JP,KE,KH,KR,KW,KY,KZ,LB,LK,LT,LV,LY,MA,MC,MD,ME,MG,MK,MN,MO,MT,MV,MW,MX,MY,NG,NI,NO,NP,NL,NZ,OM,PA,PE,PG,PH,PK,PL,PT,PY,QA,RO,RS,RU,RW,SA,SB,SC,SE,SG,SH,SI,SK,SL,SO,SM,SR,ST,SV,SY,TH,TJ,TN,TO,TR,TW,TZ,UA,UG,US,UY,UZ,VE,VA,VN,VU,WS,CF,AG,DM,GD,KN,LC,VC,YE,ZA,ZM", currency = "AED,ALL,AMD,ARS,AUD,AZN,BAM,BBD,BDT,BGN,BHD,BIF,BMD,BND,BOB,BRL,BSD,BWP,BYN,BZD,CAD,CDF,CHF,CLP,CNY,COP,CRC,CUP,CZK,DJF,DKK,DOP,DZD,EGP,ETB,EUR,FJD,GBP,GEL,GHS,GIP,GMD,GTQ,GYD,HKD,HNL,HRK,HUF,IDR,ILS,INR,ISK,JMD,JOD,JPY,KES,KHR,KRW,KWD,KYD,KZT,LBP,LKR,LYD,MAD,MDL,MGA,MKD,MNT,MOP,MVR,MWK,MXN,MYR,NGN,NIO,NOK,NPR,NZD,OMR,PAB,PEN,PGK,PHP,PKR,PLN,PYG,QAR,RON,RSD,RUB,RWF,SAR,SBD,SCR,SEK,SGD,SHP,SLL,SOS,SRD,STN,SVC,SYP,THB,TJS,TND,TOP,TRY,TWD,TZS,UAH,UGX,USD,UYU,UZS,VES,VND,VUV,WST,XAF,XCD,YER,ZAR,ZMW"} -debit = { country = "AD,AE,AL,AM,AR,AT,AU,AZ,BA,BB,BD,BE,BG,BH,BI,BM,BN,BO,BR,BS,BW,BY,BZ,CA,CD,CH,CL,CN,CO,CR,CU,CY,CZ,DE,DJ,DK,DO,DZ,EE,EG,ET,ES,FI,FJ,FR,GB,GE,GH,GI,GM,GR,GT,GY,HK,HN,HR,HU,ID,IE,IL,IN,IS,IT,JM,JO,JP,KE,KH,KR,KW,KY,KZ,LB,LK,LT,LV,LY,MA,MC,MD,ME,MG,MK,MN,MO,MT,MV,MW,MX,MY,NG,NI,NO,NP,NL,NZ,OM,PA,PE,PG,PH,PK,PL,PT,PY,QA,RO,RS,RU,RW,SA,SB,SC,SE,SG,SH,SI,SK,SL,SO,SM,SR,ST,SV,SY,TH,TJ,TN,TO,TR,TW,TZ,UA,UG,US,UY,UZ,VE,VA,VN,VU,WS,CF,AG,DM,GD,KN,LC,VC,YE,ZA,ZM", currency = "AED,ALL,AMD,ARS,AUD,AZN,BAM,BBD,BDT,BGN,BHD,BIF,BMD,BND,BOB,BRL,BSD,BWP,BYN,BZD,CAD,CDF,CHF,CLP,CNY,COP,CRC,CUP,CZK,DJF,DKK,DOP,DZD,EGP,ETB,EUR,FJD,GBP,GEL,GHS,GIP,GMD,GTQ,GYD,HKD,HNL,HRK,HUF,IDR,ILS,INR,ISK,JMD,JOD,JPY,KES,KHR,KRW,KWD,KYD,KZT,LBP,LKR,LYD,MAD,MDL,MGA,MKD,MNT,MOP,MVR,MWK,MXN,MYR,NGN,NIO,NOK,NPR,NZD,OMR,PAB,PEN,PGK,PHP,PKR,PLN,PYG,QAR,RON,RSD,RUB,RWF,SAR,SBD,SCR,SEK,SGD,SHP,SLL,SOS,SRD,STN,SVC,SYP,THB,TJS,TND,TOP,TRY,TWD,TZS,UAH,UGX,USD,UYU,UZS,VES,VND,VUV,WST,XAF,XCD,YER,ZAR,ZMW"} -apple_pay = { country = "AD,AE,AL,AM,AR,AT,AU,AZ,BA,BB,BD,BE,BG,BH,BI,BM,BN,BO,BR,BS,BW,BY,BZ,CA,CD,CH,CL,CN,CO,CR,CU,CY,CZ,DE,DJ,DK,DO,DZ,EE,EG,ET,ES,FI,FJ,FR,GB,GE,GH,GI,GM,GR,GT,GY,HK,HN,HR,HU,ID,IE,IL,IN,IS,IT,JM,JO,JP,KE,KH,KR,KW,KY,KZ,LB,LK,LT,LV,LY,MA,MC,MD,ME,MG,MK,MN,MO,MT,MV,MW,MX,MY,NG,NI,NO,NP,NL,NZ,OM,PA,PE,PG,PH,PK,PL,PT,PY,QA,RO,RS,RU,RW,SA,SB,SC,SE,SG,SH,SI,SK,SL,SO,SM,SR,ST,SV,SY,TH,TJ,TN,TO,TR,TW,TZ,UA,UG,US,UY,UZ,VE,VA,VN,VU,WS,CF,AG,DM,GD,KN,LC,VC,YE,ZA,ZM", currency = "AED,ALL,AMD,ARS,AUD,AZN,BAM,BBD,BDT,BGN,BHD,BIF,BMD,BND,BOB,BRL,BSD,BWP,BYN,BZD,CAD,CDF,CHF,CLP,CNY,COP,CRC,CUP,CZK,DJF,DKK,DOP,DZD,EGP,ETB,EUR,FJD,GBP,GEL,GHS,GIP,GMD,GTQ,GYD,HKD,HNL,HRK,HUF,IDR,ILS,INR,ISK,JMD,JOD,JPY,KES,KHR,KRW,KWD,KYD,KZT,LBP,LKR,LYD,MAD,MDL,MGA,MKD,MNT,MOP,MVR,MWK,MXN,MYR,NGN,NIO,NOK,NPR,NZD,OMR,PAB,PEN,PGK,PHP,PKR,PLN,PYG,QAR,RON,RSD,RUB,RWF,SAR,SBD,SCR,SEK,SGD,SHP,SLL,SOS,SRD,STN,SVC,SYP,THB,TJS,TND,TOP,TRY,TWD,TZS,UAH,UGX,USD,UYU,UZS,VES,VND,VUV,WST,XAF,XCD,YER,ZAR,ZMW"} -google_pay = { country = "AD,AE,AL,AM,AR,AT,AU,AZ,BA,BB,BD,BE,BG,BH,BI,BM,BN,BO,BR,BS,BW,BY,BZ,CA,CD,CH,CL,CN,CO,CR,CU,CY,CZ,DE,DJ,DK,DO,DZ,EE,EG,ET,ES,FI,FJ,FR,GB,GE,GH,GI,GM,GR,GT,GY,HK,HN,HR,HU,ID,IE,IL,IN,IS,IT,JM,JO,JP,KE,KH,KR,KW,KY,KZ,LB,LK,LT,LV,LY,MA,MC,MD,ME,MG,MK,MN,MO,MT,MV,MW,MX,MY,NG,NI,NO,NP,NL,NZ,OM,PA,PE,PG,PH,PK,PL,PT,PY,QA,RO,RS,RU,RW,SA,SB,SC,SE,SG,SH,SI,SK,SL,SO,SM,SR,ST,SV,SY,TH,TJ,TN,TO,TR,TW,TZ,UA,UG,US,UY,UZ,VE,VA,VN,VU,WS,CF,AG,DM,GD,KN,LC,VC,YE,ZA,ZM", currency = "AED,ALL,AMD,ARS,AUD,AZN,BAM,BBD,BDT,BGN,BHD,BIF,BMD,BND,BOB,BRL,BSD,BWP,BYN,BZD,CAD,CDF,CHF,CLP,CNY,COP,CRC,CUP,CZK,DJF,DKK,DOP,DZD,EGP,ETB,EUR,FJD,GBP,GEL,GHS,GIP,GMD,GTQ,GYD,HKD,HNL,HRK,HUF,IDR,ILS,INR,ISK,JMD,JOD,JPY,KES,KHR,KRW,KWD,KYD,KZT,LBP,LKR,LYD,MAD,MDL,MGA,MKD,MNT,MOP,MVR,MWK,MXN,MYR,NGN,NIO,NOK,NPR,NZD,OMR,PAB,PEN,PGK,PHP,PKR,PLN,PYG,QAR,RON,RSD,RUB,RWF,SAR,SBD,SCR,SEK,SGD,SHP,SLL,SOS,SRD,STN,SVC,SYP,THB,TJS,TND,TOP,TRY,TWD,TZS,UAH,UGX,USD,UYU,UZS,VES,VND,VUV,WST,XAF,XCD,YER,ZAR,ZMW"} -paypal = { country = "AD,AE,AL,AM,AR,AT,AU,AZ,BA,BB,BD,BE,BG,BH,BI,BM,BN,BO,BR,BS,BW,BY,BZ,CA,CD,CH,CL,CN,CO,CR,CU,CY,CZ,DE,DJ,DK,DO,DZ,EE,EG,ET,ES,FI,FJ,FR,GB,GE,GH,GI,GM,GR,GT,GY,HK,HN,HR,HU,ID,IE,IL,IN,IS,IT,JM,JO,JP,KE,KH,KR,KW,KY,KZ,LB,LK,LT,LV,LY,MA,MC,MD,ME,MG,MK,MN,MO,MT,MV,MW,MX,MY,NG,NI,NO,NP,NL,NZ,OM,PA,PE,PG,PH,PK,PL,PT,PY,QA,RO,RS,RU,RW,SA,SB,SC,SE,SG,SH,SI,SK,SL,SO,SM,SR,ST,SV,SY,TH,TJ,TN,TO,TR,TW,TZ,UA,UG,US,UY,UZ,VE,VA,VN,VU,WS,CF,AG,DM,GD,KN,LC,VC,YE,ZA,ZM", currency = "AED,ALL,AMD,ARS,AUD,AZN,BAM,BBD,BDT,BGN,BHD,BIF,BMD,BND,BOB,BRL,BSD,BWP,BYN,BZD,CAD,CDF,CHF,CLP,CNY,COP,CRC,CUP,CZK,DJF,DKK,DOP,DZD,EGP,ETB,EUR,FJD,GBP,GEL,GHS,GIP,GMD,GTQ,GYD,HKD,HNL,HRK,HUF,IDR,ILS,INR,ISK,JMD,JOD,JPY,KES,KHR,KRW,KWD,KYD,KZT,LBP,LKR,LYD,MAD,MDL,MGA,MKD,MNT,MOP,MVR,MWK,MXN,MYR,NGN,NIO,NOK,NPR,NZD,OMR,PAB,PEN,PGK,PHP,PKR,PLN,PYG,QAR,RON,RSD,RUB,RWF,SAR,SBD,SCR,SEK,SGD,SHP,SLL,SOS,SRD,STN,SVC,SYP,THB,TJS,TND,TOP,TRY,TWD,TZS,UAH,UGX,USD,UYU,UZS,VES,VND,VUV,WST,XAF,XCD,YER,ZAR,ZMW"} +credit = { country = "AD,AE,AL,AM,AR,AT,AU,AZ,BA,BB,BD,BE,BG,BH,BI,BM,BN,BO,BR,BS,BW,BY,BZ,CA,CD,CH,CL,CN,CO,CR,CU,CY,CZ,DE,DJ,DK,DO,DZ,EE,EG,ET,ES,FI,FJ,FR,GB,GE,GH,GI,GM,GR,GT,GY,HK,HN,HR,HU,ID,IE,IL,IN,IS,IT,JM,JO,JP,KE,KH,KR,KW,KY,KZ,LB,LK,LT,LV,LY,MA,MC,MD,ME,MG,MK,MN,MO,MT,MV,MW,MX,MY,NG,NI,NO,NP,NL,NZ,OM,PA,PE,PG,PH,PK,PL,PT,PY,QA,RO,RS,RU,RW,SA,SB,SC,SE,SG,SH,SI,SK,SL,SO,SM,SR,ST,SV,SY,TH,TJ,TN,TO,TR,TW,TZ,UA,UG,US,UY,UZ,VE,VA,VN,VU,WS,CF,AG,DM,GD,KN,LC,VC,YE,ZA,ZM", currency = "AED,ALL,AMD,ARS,AUD,AZN,BAM,BBD,BDT,BGN,BHD,BIF,BMD,BND,BOB,BRL,BSD,BWP,BYN,BZD,CAD,CDF,CHF,CLP,CNY,COP,CRC,CUP,CZK,DJF,DKK,DOP,DZD,EGP,ETB,EUR,FJD,GBP,GEL,GHS,GIP,GMD,GTQ,GYD,HKD,HNL,HRK,HUF,IDR,ILS,INR,ISK,JMD,JOD,JPY,KES,KHR,KRW,KWD,KYD,KZT,LBP,LKR,LYD,MAD,MDL,MGA,MKD,MNT,MOP,MVR,MWK,MXN,MYR,NGN,NIO,NOK,NPR,NZD,OMR,PAB,PEN,PGK,PHP,PKR,PLN,PYG,QAR,RON,RSD,RUB,RWF,SAR,SBD,SCR,SEK,SGD,SHP,SLL,SOS,SRD,STN,SVC,SYP,THB,TJS,TND,TOP,TRY,TWD,TZS,UAH,UGX,USD,UYU,UZS,VES,VND,VUV,WST,XAF,XCD,YER,ZAR,ZMW" } +debit = { country = "AD,AE,AL,AM,AR,AT,AU,AZ,BA,BB,BD,BE,BG,BH,BI,BM,BN,BO,BR,BS,BW,BY,BZ,CA,CD,CH,CL,CN,CO,CR,CU,CY,CZ,DE,DJ,DK,DO,DZ,EE,EG,ET,ES,FI,FJ,FR,GB,GE,GH,GI,GM,GR,GT,GY,HK,HN,HR,HU,ID,IE,IL,IN,IS,IT,JM,JO,JP,KE,KH,KR,KW,KY,KZ,LB,LK,LT,LV,LY,MA,MC,MD,ME,MG,MK,MN,MO,MT,MV,MW,MX,MY,NG,NI,NO,NP,NL,NZ,OM,PA,PE,PG,PH,PK,PL,PT,PY,QA,RO,RS,RU,RW,SA,SB,SC,SE,SG,SH,SI,SK,SL,SO,SM,SR,ST,SV,SY,TH,TJ,TN,TO,TR,TW,TZ,UA,UG,US,UY,UZ,VE,VA,VN,VU,WS,CF,AG,DM,GD,KN,LC,VC,YE,ZA,ZM", currency = "AED,ALL,AMD,ARS,AUD,AZN,BAM,BBD,BDT,BGN,BHD,BIF,BMD,BND,BOB,BRL,BSD,BWP,BYN,BZD,CAD,CDF,CHF,CLP,CNY,COP,CRC,CUP,CZK,DJF,DKK,DOP,DZD,EGP,ETB,EUR,FJD,GBP,GEL,GHS,GIP,GMD,GTQ,GYD,HKD,HNL,HRK,HUF,IDR,ILS,INR,ISK,JMD,JOD,JPY,KES,KHR,KRW,KWD,KYD,KZT,LBP,LKR,LYD,MAD,MDL,MGA,MKD,MNT,MOP,MVR,MWK,MXN,MYR,NGN,NIO,NOK,NPR,NZD,OMR,PAB,PEN,PGK,PHP,PKR,PLN,PYG,QAR,RON,RSD,RUB,RWF,SAR,SBD,SCR,SEK,SGD,SHP,SLL,SOS,SRD,STN,SVC,SYP,THB,TJS,TND,TOP,TRY,TWD,TZS,UAH,UGX,USD,UYU,UZS,VES,VND,VUV,WST,XAF,XCD,YER,ZAR,ZMW" } +apple_pay = { country = "AD,AE,AL,AM,AR,AT,AU,AZ,BA,BB,BD,BE,BG,BH,BI,BM,BN,BO,BR,BS,BW,BY,BZ,CA,CD,CH,CL,CN,CO,CR,CU,CY,CZ,DE,DJ,DK,DO,DZ,EE,EG,ET,ES,FI,FJ,FR,GB,GE,GH,GI,GM,GR,GT,GY,HK,HN,HR,HU,ID,IE,IL,IN,IS,IT,JM,JO,JP,KE,KH,KR,KW,KY,KZ,LB,LK,LT,LV,LY,MA,MC,MD,ME,MG,MK,MN,MO,MT,MV,MW,MX,MY,NG,NI,NO,NP,NL,NZ,OM,PA,PE,PG,PH,PK,PL,PT,PY,QA,RO,RS,RU,RW,SA,SB,SC,SE,SG,SH,SI,SK,SL,SO,SM,SR,ST,SV,SY,TH,TJ,TN,TO,TR,TW,TZ,UA,UG,US,UY,UZ,VE,VA,VN,VU,WS,CF,AG,DM,GD,KN,LC,VC,YE,ZA,ZM", currency = "AED,ALL,AMD,ARS,AUD,AZN,BAM,BBD,BDT,BGN,BHD,BIF,BMD,BND,BOB,BRL,BSD,BWP,BYN,BZD,CAD,CDF,CHF,CLP,CNY,COP,CRC,CUP,CZK,DJF,DKK,DOP,DZD,EGP,ETB,EUR,FJD,GBP,GEL,GHS,GIP,GMD,GTQ,GYD,HKD,HNL,HRK,HUF,IDR,ILS,INR,ISK,JMD,JOD,JPY,KES,KHR,KRW,KWD,KYD,KZT,LBP,LKR,LYD,MAD,MDL,MGA,MKD,MNT,MOP,MVR,MWK,MXN,MYR,NGN,NIO,NOK,NPR,NZD,OMR,PAB,PEN,PGK,PHP,PKR,PLN,PYG,QAR,RON,RSD,RUB,RWF,SAR,SBD,SCR,SEK,SGD,SHP,SLL,SOS,SRD,STN,SVC,SYP,THB,TJS,TND,TOP,TRY,TWD,TZS,UAH,UGX,USD,UYU,UZS,VES,VND,VUV,WST,XAF,XCD,YER,ZAR,ZMW" } +google_pay = { country = "AD,AE,AL,AM,AR,AT,AU,AZ,BA,BB,BD,BE,BG,BH,BI,BM,BN,BO,BR,BS,BW,BY,BZ,CA,CD,CH,CL,CN,CO,CR,CU,CY,CZ,DE,DJ,DK,DO,DZ,EE,EG,ET,ES,FI,FJ,FR,GB,GE,GH,GI,GM,GR,GT,GY,HK,HN,HR,HU,ID,IE,IL,IN,IS,IT,JM,JO,JP,KE,KH,KR,KW,KY,KZ,LB,LK,LT,LV,LY,MA,MC,MD,ME,MG,MK,MN,MO,MT,MV,MW,MX,MY,NG,NI,NO,NP,NL,NZ,OM,PA,PE,PG,PH,PK,PL,PT,PY,QA,RO,RS,RU,RW,SA,SB,SC,SE,SG,SH,SI,SK,SL,SO,SM,SR,ST,SV,SY,TH,TJ,TN,TO,TR,TW,TZ,UA,UG,US,UY,UZ,VE,VA,VN,VU,WS,CF,AG,DM,GD,KN,LC,VC,YE,ZA,ZM", currency = "AED,ALL,AMD,ARS,AUD,AZN,BAM,BBD,BDT,BGN,BHD,BIF,BMD,BND,BOB,BRL,BSD,BWP,BYN,BZD,CAD,CDF,CHF,CLP,CNY,COP,CRC,CUP,CZK,DJF,DKK,DOP,DZD,EGP,ETB,EUR,FJD,GBP,GEL,GHS,GIP,GMD,GTQ,GYD,HKD,HNL,HRK,HUF,IDR,ILS,INR,ISK,JMD,JOD,JPY,KES,KHR,KRW,KWD,KYD,KZT,LBP,LKR,LYD,MAD,MDL,MGA,MKD,MNT,MOP,MVR,MWK,MXN,MYR,NGN,NIO,NOK,NPR,NZD,OMR,PAB,PEN,PGK,PHP,PKR,PLN,PYG,QAR,RON,RSD,RUB,RWF,SAR,SBD,SCR,SEK,SGD,SHP,SLL,SOS,SRD,STN,SVC,SYP,THB,TJS,TND,TOP,TRY,TWD,TZS,UAH,UGX,USD,UYU,UZS,VES,VND,VUV,WST,XAF,XCD,YER,ZAR,ZMW" } +paypal = { country = "AD,AE,AL,AM,AR,AT,AU,AZ,BA,BB,BD,BE,BG,BH,BI,BM,BN,BO,BR,BS,BW,BY,BZ,CA,CD,CH,CL,CN,CO,CR,CU,CY,CZ,DE,DJ,DK,DO,DZ,EE,EG,ET,ES,FI,FJ,FR,GB,GE,GH,GI,GM,GR,GT,GY,HK,HN,HR,HU,ID,IE,IL,IN,IS,IT,JM,JO,JP,KE,KH,KR,KW,KY,KZ,LB,LK,LT,LV,LY,MA,MC,MD,ME,MG,MK,MN,MO,MT,MV,MW,MX,MY,NG,NI,NO,NP,NL,NZ,OM,PA,PE,PG,PH,PK,PL,PT,PY,QA,RO,RS,RU,RW,SA,SB,SC,SE,SG,SH,SI,SK,SL,SO,SM,SR,ST,SV,SY,TH,TJ,TN,TO,TR,TW,TZ,UA,UG,US,UY,UZ,VE,VA,VN,VU,WS,CF,AG,DM,GD,KN,LC,VC,YE,ZA,ZM", currency = "AED,ALL,AMD,ARS,AUD,AZN,BAM,BBD,BDT,BGN,BHD,BIF,BMD,BND,BOB,BRL,BSD,BWP,BYN,BZD,CAD,CDF,CHF,CLP,CNY,COP,CRC,CUP,CZK,DJF,DKK,DOP,DZD,EGP,ETB,EUR,FJD,GBP,GEL,GHS,GIP,GMD,GTQ,GYD,HKD,HNL,HRK,HUF,IDR,ILS,INR,ISK,JMD,JOD,JPY,KES,KHR,KRW,KWD,KYD,KZT,LBP,LKR,LYD,MAD,MDL,MGA,MKD,MNT,MOP,MVR,MWK,MXN,MYR,NGN,NIO,NOK,NPR,NZD,OMR,PAB,PEN,PGK,PHP,PKR,PLN,PYG,QAR,RON,RSD,RUB,RWF,SAR,SBD,SCR,SEK,SGD,SHP,SLL,SOS,SRD,STN,SVC,SYP,THB,TJS,TND,TOP,TRY,TWD,TZS,UAH,UGX,USD,UYU,UZS,VES,VND,VUV,WST,XAF,XCD,YER,ZAR,ZMW" } [pm_filters.braintree] paypal = { currency = "AUD,BRL,CAD,CNY,CZK,DKK,EUR,HKD,HUF,ILS,JPY,MYR,MXN,TWD,NZD,NOK,PHP,PLN,GBP,RUB,SGD,SEK,CHF,THB,USD" } @@ -526,7 +526,6 @@ credit = { not_available_flows = { capture_method = "manual" } } debit = { not_available_flows = { capture_method = "manual" } } - [pm_filters.mollie] credit = { not_available_flows = { capture_method = "manual" } } debit = { not_available_flows = { capture_method = "manual" } } @@ -566,7 +565,7 @@ credit = { currency = "USD" } debit = { currency = "USD" } [pm_filters.fiuu] -duit_now = { country ="MY", currency = "MYR" } +duit_now = { country = "MY", currency = "MYR" } [tokenization] stripe = { long_lived_token = false, payment_method = "wallet", payment_method_type = { type = "disable_only", list = "google_pay" } } @@ -623,16 +622,16 @@ connectors_with_delayed_session_response = "trustpay,payme" connectors_with_webhook_source_verification_call = "paypal" [mandates.supported_payment_methods] -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,globalpay,worldpay,multisafepay,nmi,nexinets,noon,bankofamerica,braintree,nuvei,payme,wellsfargo,bamboraapac,elavon,fiuu,nexixpay,novalnet,paybox,paypal" -card.debit.connector_list = "stripe,adyen,authorizedotnet,cybersource,globalpay,worldpay,multisafepay,nmi,nexinets,noon,bankofamerica,braintree,nuvei,payme,wellsfargo,bamboraapac,elavon,fiuu,nexixpay,novalnet,paybox,paypal" -pay_later.klarna.connector_list = "adyen" -wallet.apple_pay.connector_list = "stripe,adyen,cybersource,noon,bankofamerica,nexinets,novalnet" -wallet.google_pay.connector_list = "stripe,adyen,cybersource,bankofamerica,noon,globalpay,multisafepay,novalnet" -wallet.paypal.connector_list = "adyen,globalpay,nexinets,novalnet,paypal" +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,globalpay,worldpay,multisafepay,nmi,nexinets,noon,bankofamerica,braintree,nuvei,payme,wellsfargo,bamboraapac,elavon,fiuu,nexixpay,novalnet,paybox,paypal" +card.debit.connector_list = "stripe,adyen,authorizedotnet,cybersource,globalpay,worldpay,multisafepay,nmi,nexinets,noon,bankofamerica,braintree,nuvei,payme,wellsfargo,bamboraapac,elavon,fiuu,nexixpay,novalnet,paybox,paypal" +pay_later.klarna.connector_list = "adyen" +wallet.apple_pay.connector_list = "stripe,adyen,cybersource,noon,bankofamerica,nexinets,novalnet" +wallet.google_pay.connector_list = "stripe,adyen,cybersource,bankofamerica,noon,globalpay,multisafepay,novalnet" +wallet.paypal.connector_list = "adyen,globalpay,nexinets,novalnet,paypal" wallet.momo.connector_list = "adyen" wallet.kakao_pay.connector_list = "adyen" wallet.go_pay.connector_list = "adyen" @@ -641,13 +640,13 @@ wallet.dana.connector_list = "adyen" wallet.twint.connector_list = "adyen" wallet.vipps.connector_list = "adyen" -bank_redirect.ideal.connector_list = "stripe,adyen,globalpay,multisafepay,nexinets" -bank_redirect.sofort.connector_list = "stripe,adyen,globalpay" -bank_redirect.giropay.connector_list = "adyen,globalpay,multisafepay,nexinets" -bank_redirect.bancontact_card.connector_list="adyen,stripe" -bank_redirect.trustly.connector_list="adyen" -bank_redirect.open_banking_uk.connector_list="adyen" -bank_redirect.eps.connector_list="globalpay,nexinets" +bank_redirect.ideal.connector_list = "stripe,adyen,globalpay,multisafepay,nexinets" +bank_redirect.sofort.connector_list = "stripe,adyen,globalpay" +bank_redirect.giropay.connector_list = "adyen,globalpay,multisafepay,nexinets" +bank_redirect.bancontact_card.connector_list = "adyen,stripe" +bank_redirect.trustly.connector_list = "adyen" +bank_redirect.open_banking_uk.connector_list = "adyen" +bank_redirect.eps.connector_list = "globalpay,nexinets" [mandates.update_mandate_supported] card.credit = { connector_list = "cybersource" } @@ -697,7 +696,7 @@ merchant_name = "HyperSwitch" card = "credit,debit" [payout_method_filters.adyenplatform] -sepa = { country = "ES,SK,AT,NL,DE,BE,FR,FI,PT,IE,EE,LT,LV,IT,CZ,DE,HU,NO,PL,SE,GB,CH" , currency = "EUR,CZK,DKK,HUF,NOK,PLN,SEK,GBP,CHF" } +sepa = { country = "ES,SK,AT,NL,DE,BE,FR,FI,PT,IE,EE,LT,LV,IT,CZ,DE,HU,NO,PL,SE,GB,CH", currency = "EUR,CZK,DKK,HUF,NOK,PLN,SEK,GBP,CHF" } [payout_method_filters.stripe] ach = { country = "US", currency = "USD" } @@ -725,7 +724,7 @@ source = "logs" [events.kafka] brokers = ["localhost:9092"] -fraud_check_analytics_topic= "hyperswitch-fraud-check-events" +fraud_check_analytics_topic = "hyperswitch-fraud-check-events" intent_analytics_topic = "hyperswitch-payment-intent-events" attempt_analytics_topic = "hyperswitch-payment-attempt-events" refund_analytics_topic = "hyperswitch-refund-events" @@ -794,7 +793,7 @@ sdk_eligible_payment_methods = "card" [multitenancy] enabled = false -global_tenant = { tenant_id = "global" ,schema = "public", redis_key_prefix = "global", clickhouse_database = "default"} +global_tenant = { tenant_id = "global", schema = "public", redis_key_prefix = "global", clickhouse_database = "default" } [multitenancy.tenants.public] base_url = "http://localhost:8080" @@ -803,7 +802,7 @@ redis_key_prefix = "" clickhouse_database = "default" [multitenancy.tenants.public.user] -control_center_url = "http://localhost:9000" +control_center_url = "http://localhost:9000" [user_auth_methods] encryption_key = "A8EF32E029BC3342E54BF2E172A4D7AA43E8EF9D2C3A624A9F04E2EF79DC698F" diff --git a/config/payment_required_fields_v2.toml b/config/payment_required_fields_v2.toml new file mode 100644 index 000000000000..8cc5e62c3561 --- /dev/null +++ b/config/payment_required_fields_v2.toml @@ -0,0 +1,16 @@ +[[required_fields.card.credit.fields.stripe.common]] +required_field = "payment_method_data.card.card_number" +display_name = "card_number" +field_type = "user_card_number" +[[required_fields.card.credit.fields.stripe.common]] +required_field = "payment_method_data.card.card_exp_year" +display_name = "card_exp_year" +field_type = "user_card_expiry_year" +[[required_fields.card.credit.fields.stripe.common]] +required_field = "payment_method_data.card.card_cvc" +display_name = "card_cvc" +field_type = "user_card_cvc" +[[required_fields.card.credit.fields.stripe.common]] +required_field = "payment_method_data.card.card_exp_month" +display_name = "card_exp_month" +field_type = "user_card_expiry_month" diff --git a/crates/api_models/src/admin.rs b/crates/api_models/src/admin.rs index ef25a4350d95..cbd44c15699b 100644 --- a/crates/api_models/src/admin.rs +++ b/crates/api_models/src/admin.rs @@ -1009,9 +1009,10 @@ pub struct MerchantConnectorResponse { /// Type of the Connector for the financial use case. Could range from Payments to Accounting to Banking. #[schema(value_type = ConnectorType, example = "payment_processor")] pub connector_type: api_enums::ConnectorType, + /// Name of the Connector #[schema(value_type = Connector, example = "stripe")] - pub connector_name: String, + pub connector_name: common_enums::connector_enums::Connector, /// A unique label to identify the connector account created under a profile #[schema(example = "stripe_US_travel")] @@ -1310,9 +1311,10 @@ pub struct MerchantConnectorListResponse { /// Type of the Connector for the financial use case. Could range from Payments to Accounting to Banking. #[schema(value_type = ConnectorType, example = "payment_processor")] pub connector_type: api_enums::ConnectorType, + /// Name of the Connector #[schema(value_type = Connector, example = "stripe")] - pub connector_name: String, + pub connector_name: common_enums::connector_enums::Connector, /// A unique label to identify the connector account created under a profile #[schema(example = "stripe_US_travel")] diff --git a/crates/api_models/src/connector_enums.rs b/crates/api_models/src/connector_enums.rs index 3a3fe5e8f429..668c62c0c3ab 100644 --- a/crates/api_models/src/connector_enums.rs +++ b/crates/api_models/src/connector_enums.rs @@ -1,320 +1 @@ -pub use common_enums::enums::{PaymentMethod, PayoutType}; -#[cfg(feature = "dummy_connector")] -use common_utils::errors; -use utoipa::ToSchema; - -/// 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 { - Adyenplatform, - #[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, - // Amazonpay, - Authorizedotnet, - Bambora, - Bamboraapac, - Bankofamerica, - Billwerk, - Bitpay, - Bluesnap, - Boku, - Braintree, - Cashtocode, - Checkout, - Coinbase, - Cryptopay, - CtpMastercard, - Cybersource, - Datatrans, - Deutschebank, - Digitalvirgo, - Dlocal, - Ebanx, - Elavon, - Fiserv, - Fiservemea, - Fiuu, - Forte, - Globalpay, - Globepay, - Gocardless, - Gpayments, - Helcim, - // Inespay, - Iatapay, - Itaubank, - Jpmorgan, - Klarna, - Mifinity, - Mollie, - Multisafepay, - Netcetera, - Nexinets, - Nexixpay, - Nmi, - // Nomupay, - Noon, - Novalnet, - Nuvei, - // Opayo, added as template code for future usage - Opennode, - Paybox, - // Payeezy, As psync and rsync are not supported by this connector, it is added as template code for future usage - Payme, - Payone, - Paypal, - Payu, - Placetopay, - Powertranz, - Prophetpay, - Rapyd, - Razorpay, - // Redsys, - Shift4, - Square, - Stax, - Stripe, - Taxjar, - Threedsecureio, - //Thunes, - Trustpay, - Tsys, - // UnifiedAuthenticationService, - Volt, - Wellsfargo, - // Wellsfargopayout, - Wise, - Worldline, - Worldpay, - Signifyd, - Plaid, - Riskified, - // Xendit, - Zen, - Zsl, -} - -impl Connector { - #[cfg(feature = "payouts")] - pub fn supports_instant_payout(self, payout_method: Option) -> bool { - matches!( - (self, payout_method), - (Self::Paypal, Some(PayoutType::Wallet)) - | (_, Some(PayoutType::Card)) - | (Self::Adyenplatform, _) - ) - } - #[cfg(feature = "payouts")] - pub fn supports_create_recipient(self, payout_method: Option) -> bool { - matches!((self, payout_method), (_, Some(PayoutType::Bank))) - } - #[cfg(feature = "payouts")] - pub fn supports_payout_eligibility(self, payout_method: Option) -> bool { - matches!((self, payout_method), (_, Some(PayoutType::Card))) - } - #[cfg(feature = "payouts")] - pub fn is_payout_quote_call_required(self) -> bool { - matches!(self, Self::Wise) - } - #[cfg(feature = "payouts")] - pub fn supports_access_token_for_payout(self, payout_method: Option) -> 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::Deutschebank, _) - | (Self::Globalpay, _) - | (Self::Jpmorgan, _) - | (Self::Paypal, _) - | (Self::Payu, _) - | (Self::Trustpay, PaymentMethod::BankRedirect) - | (Self::Iatapay, _) - | (Self::Volt, _) - | (Self::Itaubank, _) - ) - } - 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 - // Add Separate authentication support for connectors - | Self::Adyen - | Self::Adyenplatform - | Self::Airwallex - // | Self::Amazonpay - | Self::Authorizedotnet - | Self::Bambora - | Self::Bamboraapac - | Self::Bankofamerica - | Self::Billwerk - | Self::Bitpay - | Self::Bluesnap - | Self::Boku - | Self::Braintree - | Self::Cashtocode - | Self::Coinbase - | Self::Cryptopay - | Self::Deutschebank - | Self::Digitalvirgo - | Self::Dlocal - | Self::Ebanx - | Self::Elavon - | Self::Fiserv - | Self::Fiservemea - | Self::Fiuu - | Self::Forte - | Self::Globalpay - | Self::Globepay - | Self::Gocardless - | Self::Gpayments - | Self::Helcim - | Self::Iatapay - // | Self::Inespay - | Self::Itaubank - | Self::Jpmorgan - | Self::Klarna - | Self::Mifinity - | Self::Mollie - | Self::Multisafepay - | Self::Nexinets - | Self::Nexixpay - // | Self::Nomupay - | Self::Novalnet - | Self::Nuvei - | Self::Opennode - | Self::Paybox - | Self::Payme - | Self::Payone - | Self::Paypal - | Self::Payu - | Self::Placetopay - | Self::Powertranz - | Self::Prophetpay - | Self::Rapyd - // | Self::Redsys - | Self::Shift4 - | Self::Square - | Self::Stax - | Self::Taxjar - // | Self::Thunes - | Self::Trustpay - | Self::Tsys - // | Self::UnifiedAuthenticationService - | Self::Volt - | Self::Wellsfargo - // | Self::Wellsfargopayout - | Self::Wise - | Self::Worldline - | Self::Worldpay - // | Self::Xendit - | Self::Zen - | Self::Zsl - | Self::Signifyd - | Self::Plaid - | Self::Razorpay - | Self::Riskified - | Self::Threedsecureio - | Self::Datatrans - | Self::Netcetera - | Self::CtpMastercard - | Self::Noon - | Self::Stripe => false, - Self::Checkout | Self::Nmi | Self::Cybersource => true, - } - } - pub fn is_pre_processing_required_before_authorize(self) -> bool { - matches!(self, Self::Airwallex) - } - pub fn should_acknowledge_webhook_for_resource_not_found_errors(self) -> bool { - matches!(self, Self::Adyenplatform) - } - #[cfg(feature = "dummy_connector")] - pub fn validate_dummy_connector_enabled( - self, - is_dummy_connector_enabled: bool, - ) -> errors::CustomResult<(), errors::ValidationError> { - if !is_dummy_connector_enabled - && matches!( - self, - Self::DummyConnector1 - | Self::DummyConnector2 - | Self::DummyConnector3 - | Self::DummyConnector4 - | Self::DummyConnector5 - | Self::DummyConnector6 - | Self::DummyConnector7 - ) - { - Err(errors::ValidationError::InvalidValue { - message: "Invalid connector name".to_string(), - } - .into()) - } else { - Ok(()) - } - } -} +pub use common_enums::connector_enums::Connector; diff --git a/crates/api_models/src/events.rs b/crates/api_models/src/events.rs index 72a0d592513f..ea173d5b6303 100644 --- a/crates/api_models/src/events.rs +++ b/crates/api_models/src/events.rs @@ -184,8 +184,8 @@ impl ApiEventMetric for PaymentMethodIntentConfirmInternal { fn get_api_event_type(&self) -> Option { Some(ApiEventsType::PaymentMethod { payment_method_id: self.id.clone(), - payment_method: Some(self.payment_method_type), - payment_method_type: Some(self.payment_method_subtype), + payment_method_type: Some(self.payment_method_type), + payment_method_subtype: Some(self.payment_method_subtype), }) } } diff --git a/crates/api_models/src/events/payment.rs b/crates/api_models/src/events/payment.rs index c242788e090b..e6de6190b83d 100644 --- a/crates/api_models/src/events/payment.rs +++ b/crates/api_models/src/events/payment.rs @@ -14,11 +14,11 @@ use crate::payment_methods::CustomerPaymentMethodsListResponse; use crate::{events, payment_methods::CustomerPaymentMethodsListResponse}; use crate::{ payment_methods::{ - CustomerDefaultPaymentMethodResponse, DefaultPaymentMethod, ListCountriesCurrenciesRequest, - ListCountriesCurrenciesResponse, PaymentMethodCollectLinkRenderRequest, - PaymentMethodCollectLinkRequest, PaymentMethodCollectLinkResponse, - PaymentMethodDeleteResponse, PaymentMethodListRequest, PaymentMethodListResponse, - PaymentMethodMigrateResponse, PaymentMethodResponse, PaymentMethodUpdate, + self, ListCountriesCurrenciesRequest, ListCountriesCurrenciesResponse, + PaymentMethodCollectLinkRenderRequest, PaymentMethodCollectLinkRequest, + PaymentMethodCollectLinkResponse, PaymentMethodDeleteResponse, PaymentMethodListRequest, + PaymentMethodListResponse, PaymentMethodMigrateResponse, PaymentMethodResponse, + PaymentMethodUpdate, }, payments::{ self, ExtendedCardInfoResponse, PaymentIdType, PaymentListConstraints, @@ -211,9 +211,9 @@ impl ApiEventMetric for PaymentMethodResponse { #[cfg(all(feature = "v2", feature = "payment_methods_v2"))] fn get_api_event_type(&self) -> Option { Some(ApiEventsType::PaymentMethod { - payment_method_id: self.payment_method_id.clone(), - payment_method: self.payment_method_type, - payment_method_type: self.payment_method_subtype, + payment_method_id: self.id.clone(), + payment_method_type: self.payment_method_type, + payment_method_subtype: self.payment_method_subtype, }) } } @@ -234,16 +234,17 @@ impl ApiEventMetric for PaymentMethodMigrateResponse { #[cfg(all(feature = "v2", feature = "payment_methods_v2"))] fn get_api_event_type(&self) -> Option { Some(ApiEventsType::PaymentMethod { - payment_method_id: self.payment_method_response.payment_method_id.clone(), - payment_method: self.payment_method_response.payment_method_type, - payment_method_type: self.payment_method_response.payment_method_subtype, + payment_method_id: self.payment_method_response.id.clone(), + payment_method_type: self.payment_method_response.payment_method_type, + payment_method_subtype: self.payment_method_response.payment_method_subtype, }) } } impl ApiEventMetric for PaymentMethodUpdate {} -impl ApiEventMetric for DefaultPaymentMethod { +#[cfg(feature = "v1")] +impl ApiEventMetric for payment_methods::DefaultPaymentMethod { fn get_api_event_type(&self) -> Option { Some(ApiEventsType::PaymentMethod { payment_method_id: self.payment_method_id.clone(), @@ -253,6 +254,18 @@ impl ApiEventMetric for DefaultPaymentMethod { } } +#[cfg(feature = "v2")] +impl ApiEventMetric for PaymentMethodDeleteResponse { + fn get_api_event_type(&self) -> Option { + Some(ApiEventsType::PaymentMethod { + payment_method_id: self.id.clone(), + payment_method_type: None, + payment_method_subtype: None, + }) + } +} + +#[cfg(feature = "v1")] impl ApiEventMetric for PaymentMethodDeleteResponse { fn get_api_event_type(&self) -> Option { Some(ApiEventsType::PaymentMethod { @@ -282,7 +295,8 @@ impl ApiEventMetric for ListCountriesCurrenciesRequest {} impl ApiEventMetric for ListCountriesCurrenciesResponse {} impl ApiEventMetric for PaymentMethodListResponse {} -impl ApiEventMetric for CustomerDefaultPaymentMethodResponse { +#[cfg(feature = "v1")] +impl ApiEventMetric for payment_methods::CustomerDefaultPaymentMethodResponse { fn get_api_event_type(&self) -> Option { Some(ApiEventsType::PaymentMethod { payment_method_id: self.default_payment_method_id.clone().unwrap_or_default(), diff --git a/crates/api_models/src/payment_methods.rs b/crates/api_models/src/payment_methods.rs index 18d18f08fd24..057c20f1b188 100644 --- a/crates/api_models/src/payment_methods.rs +++ b/crates/api_models/src/payment_methods.rs @@ -194,25 +194,14 @@ impl PaymentMethodIntentConfirm { } } +/// This struct is used internally only #[cfg(all(feature = "v2", feature = "payment_methods_v2"))] -#[derive(Debug, serde::Deserialize, serde::Serialize, Clone, ToSchema)] -#[serde(deny_unknown_fields)] +#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)] pub struct PaymentMethodIntentConfirmInternal { - #[schema(value_type = Option, max_length = 64, min_length = 1, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")] - pub id: String, - /// The type of payment method use for the payment. - #[schema(value_type = PaymentMethod,example = "card")] + pub id: id_type::GlobalPaymentMethodId, pub payment_method_type: api_enums::PaymentMethod, - - /// This is a sub-category of payment method. - #[schema(value_type = PaymentMethodType,example = "credit")] pub payment_method_subtype: api_enums::PaymentMethodType, - - /// The unique identifier of the customer. - #[schema(value_type = Option, max_length = 64, min_length = 1, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")] pub customer_id: Option, - - /// Payment method data to be passed pub payment_method_data: PaymentMethodCreateData, } @@ -776,6 +765,10 @@ pub struct PaymentMethodResponse { #[cfg(all(feature = "v2", feature = "payment_methods_v2"))] #[derive(Debug, serde::Deserialize, serde::Serialize, ToSchema, Clone)] pub struct PaymentMethodResponse { + /// The unique identifier of the Payment method + #[schema(value_type = String, example = "12345_pm_01926c58bc6e77c09e809964e72af8c8")] + pub id: id_type::GlobalPaymentMethodId, + /// Unique identifier for a merchant #[schema(value_type = String, example = "merchant_1671528864")] pub merchant_id: id_type::MerchantId, @@ -789,10 +782,6 @@ pub struct PaymentMethodResponse { )] pub customer_id: id_type::GlobalCustomerId, - /// The unique identifier of the Payment method - #[schema(example = "card_rGK4Vi5iSW70MY7J2mIg")] - pub payment_method_id: String, - /// The type of payment method use for the payment. #[schema(value_type = PaymentMethod, example = "card")] pub payment_method_type: Option, @@ -1043,6 +1032,13 @@ impl From for payments::AdditionalCardInfo { } } +#[cfg(feature = "v2")] +#[derive(Debug, serde::Serialize, ToSchema)] +pub struct PaymentMethodListResponse { + /// The list of payment methods that are enabled for the business profile + pub payment_methods_enabled: Vec, +} + #[cfg(all( any(feature = "v1", feature = "v2"), not(feature = "payment_methods_v2") @@ -1246,19 +1242,19 @@ pub struct ResponsePaymentMethodTypes { #[derive(Debug, Clone, serde::Serialize, ToSchema, PartialEq)] #[serde(untagged)] // Untagged used for serialization only pub enum PaymentMethodSubtypeSpecificData { + #[schema(title = "card")] Card { card_networks: Vec, }, - Bank { - bank_names: Vec, - }, + #[schema(title = "bank")] + Bank { bank_names: Vec }, } #[cfg(all(feature = "v2", feature = "payment_methods_v2"))] #[derive(Debug, Clone, serde::Serialize, ToSchema, PartialEq)] pub struct ResponsePaymentMethodTypes { /// The payment method type enabled - #[schema(example = "klarna", value_type = PaymentMethodType)] + #[schema(example = "pay_later", value_type = PaymentMethod)] pub payment_method_type: common_enums::PaymentMethod, /// The payment method subtype enabled @@ -1271,10 +1267,7 @@ pub struct ResponsePaymentMethodTypes { /// Required fields for the payment_method_type. /// This is the union of all the required fields for the payment method type enabled in all the connectors. - pub required_fields: Option>, - - /// surcharge details for this payment method type if exists - pub surcharge_details: Option, + pub required_fields: Vec, } #[derive(Clone, Debug, PartialEq, serde::Serialize, ToSchema)] @@ -1678,6 +1671,7 @@ fn set_or_reject_duplicate( } } +#[cfg(feature = "v1")] #[derive(Debug, serde::Serialize, ToSchema)] pub struct PaymentMethodListResponse { /// Redirect URL of the merchant @@ -1758,9 +1752,11 @@ pub struct PaymentMethodDeleteResponse { #[derive(Debug, serde::Serialize, ToSchema)] pub struct PaymentMethodDeleteResponse { /// The unique identifier of the Payment method - #[schema(example = "card_rGK4Vi5iSW70MY7J2mIg")] - pub payment_method_id: String, + #[schema(value_type = String, example = "12345_pm_01926c58bc6e77c09e809964e72af8c8")] + pub id: id_type::GlobalPaymentMethodId, } + +#[cfg(feature = "v1")] #[derive(Debug, serde::Serialize, ToSchema)] pub struct CustomerDefaultPaymentMethodResponse { /// The unique identifier of the Payment method @@ -2046,12 +2042,14 @@ pub struct PaymentMethodId { pub payment_method_id: String, } +#[cfg(feature = "v1")] #[derive(Debug, serde::Serialize, serde::Deserialize, Clone, ToSchema)] pub struct DefaultPaymentMethod { #[schema(value_type = String, max_length = 64, min_length = 1, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")] pub customer_id: id_type::CustomerId, pub payment_method_id: String, } + //------------------------------------------------TokenizeService------------------------------------------------ #[derive(Debug, serde::Serialize, serde::Deserialize)] pub struct TokenizePayloadEncrypted { diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs index 816c085b8fac..b6152cc97874 100644 --- a/crates/api_models/src/payments.rs +++ b/crates/api_models/src/payments.rs @@ -6558,8 +6558,7 @@ pub struct PaymentMethodsListRequest {} #[derive(Debug, serde::Serialize, ToSchema)] pub struct PaymentMethodListResponseForPayments { /// The list of payment methods that are enabled for the business profile - #[schema(value_type = Vec)] - pub payment_methods_enabled: Vec, + pub payment_methods_enabled: Vec, /// The list of payment methods that are saved by the given customer /// This field is only returned if the customer_id is provided in the request @@ -6567,6 +6566,32 @@ pub struct PaymentMethodListResponseForPayments { pub customer_payment_methods: Option>, } +#[cfg(all(feature = "v2", feature = "payment_methods_v2"))] +#[derive(Debug, Clone, serde::Serialize, ToSchema, PartialEq)] +pub struct ResponsePaymentMethodTypesForPayments { + /// The payment method type enabled + #[schema(example = "pay_later", value_type = PaymentMethod)] + pub payment_method_type: common_enums::PaymentMethod, + + /// The payment method subtype enabled + #[schema(example = "klarna", value_type = PaymentMethodType)] + pub payment_method_subtype: common_enums::PaymentMethodType, + + /// payment method subtype specific information + #[serde(flatten)] + #[schema(value_type = Option)] + pub extra_information: Option, + + /// Required fields for the payment_method_type. + /// This is the union of all the required fields for the payment method type enabled in all the connectors. + #[schema(value_type = Option)] + pub required_fields: Option>, + + /// surcharge details for this payment method type if exists + #[schema(value_type = Option)] + pub surcharge_details: Option, +} + #[derive(Debug, serde::Serialize, serde::Deserialize, Clone, ToSchema)] pub struct PaymentsExternalAuthenticationResponse { /// Indicates the transaction status diff --git a/crates/common_enums/src/connector_enums.rs b/crates/common_enums/src/connector_enums.rs index 127d5a9901c6..e3a634eb4e21 100644 --- a/crates/common_enums/src/connector_enums.rs +++ b/crates/common_enums/src/connector_enums.rs @@ -1,4 +1,7 @@ use utoipa::ToSchema; + +pub use super::enums::{PaymentMethod, PayoutType}; + #[derive( Clone, Copy, @@ -17,7 +20,7 @@ use utoipa::ToSchema; #[router_derive::diesel_enum(storage_type = "db_enum")] #[serde(rename_all = "snake_case")] #[strum(serialize_all = "snake_case")] -/// Connectors eligible for payments routing +/// RoutableConnectors are the subset of Connectors that are eligible for payments routing pub enum RoutableConnectors { Adyenplatform, #[cfg(feature = "dummy_connector")] @@ -127,8 +130,412 @@ pub enum RoutableConnectors { Wise, Worldline, Worldpay, - Xendit, + // Xendit, Zen, Plaid, Zsl, } + +// 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, +)] +#[router_derive::diesel_enum(storage_type = "text")] +#[serde(rename_all = "snake_case")] +#[strum(serialize_all = "snake_case")] +pub enum Connector { + Adyenplatform, + #[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, + // Amazonpay, + Authorizedotnet, + Bambora, + Bamboraapac, + Bankofamerica, + Billwerk, + Bitpay, + Bluesnap, + Boku, + Braintree, + Cashtocode, + Checkout, + Coinbase, + Cryptopay, + CtpMastercard, + Cybersource, + Datatrans, + Deutschebank, + Digitalvirgo, + Dlocal, + Ebanx, + Elavon, + Fiserv, + Fiservemea, + Fiuu, + Forte, + Globalpay, + Globepay, + Gocardless, + Gpayments, + Helcim, + // Inespay, + Iatapay, + Itaubank, + Jpmorgan, + Klarna, + Mifinity, + Mollie, + Multisafepay, + Netcetera, + Nexinets, + Nexixpay, + Nmi, + // Nomupay, + Noon, + Novalnet, + Nuvei, + // Opayo, added as template code for future usage + Opennode, + Paybox, + // Payeezy, As psync and rsync are not supported by this connector, it is added as template code for future usage + Payme, + Payone, + Paypal, + Payu, + Placetopay, + Powertranz, + Prophetpay, + Rapyd, + Razorpay, + // Redsys, + Shift4, + Square, + Stax, + Stripe, + Taxjar, + Threedsecureio, + //Thunes, + Trustpay, + Tsys, + // UnifiedAuthenticationService, + Volt, + Wellsfargo, + // Wellsfargopayout, + Wise, + Worldline, + Worldpay, + Signifyd, + Plaid, + Riskified, + // Xendit, + Zen, + Zsl, +} + +impl Connector { + #[cfg(feature = "payouts")] + pub fn supports_instant_payout(self, payout_method: Option) -> bool { + matches!( + (self, payout_method), + (Self::Paypal, Some(PayoutType::Wallet)) + | (_, Some(PayoutType::Card)) + | (Self::Adyenplatform, _) + ) + } + #[cfg(feature = "payouts")] + pub fn supports_create_recipient(self, payout_method: Option) -> bool { + matches!((self, payout_method), (_, Some(PayoutType::Bank))) + } + #[cfg(feature = "payouts")] + pub fn supports_payout_eligibility(self, payout_method: Option) -> bool { + matches!((self, payout_method), (_, Some(PayoutType::Card))) + } + #[cfg(feature = "payouts")] + pub fn is_payout_quote_call_required(self) -> bool { + matches!(self, Self::Wise) + } + #[cfg(feature = "payouts")] + pub fn supports_access_token_for_payout(self, payout_method: Option) -> 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::Deutschebank, _) + | (Self::Globalpay, _) + | (Self::Jpmorgan, _) + | (Self::Paypal, _) + | (Self::Payu, _) + | (Self::Trustpay, PaymentMethod::BankRedirect) + | (Self::Iatapay, _) + | (Self::Volt, _) + | (Self::Itaubank, _) + ) + } + 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 + // Add Separate authentication support for connectors + | Self::Adyen + | Self::Adyenplatform + | Self::Airwallex + // | Self::Amazonpay + | Self::Authorizedotnet + | Self::Bambora + | Self::Bamboraapac + | Self::Bankofamerica + | Self::Billwerk + | Self::Bitpay + | Self::Bluesnap + | Self::Boku + | Self::Braintree + | Self::Cashtocode + | Self::Coinbase + | Self::Cryptopay + | Self::Deutschebank + | Self::Digitalvirgo + | Self::Dlocal + | Self::Ebanx + | Self::Elavon + | Self::Fiserv + | Self::Fiservemea + | Self::Fiuu + | Self::Forte + | Self::Globalpay + | Self::Globepay + | Self::Gocardless + | Self::Gpayments + | Self::Helcim + | Self::Iatapay + // | Self::Inespay + | Self::Itaubank + | Self::Jpmorgan + | Self::Klarna + | Self::Mifinity + | Self::Mollie + | Self::Multisafepay + | Self::Nexinets + | Self::Nexixpay + // | Self::Nomupay + | Self::Novalnet + | Self::Nuvei + | Self::Opennode + | Self::Paybox + | Self::Payme + | Self::Payone + | Self::Paypal + | Self::Payu + | Self::Placetopay + | Self::Powertranz + | Self::Prophetpay + | Self::Rapyd + // | Self::Redsys + | Self::Shift4 + | Self::Square + | Self::Stax + | Self::Taxjar + // | Self::Thunes + | Self::Trustpay + | Self::Tsys + // | Self::UnifiedAuthenticationService + | Self::Volt + | Self::Wellsfargo + // | Self::Wellsfargopayout + | Self::Wise + | Self::Worldline + | Self::Worldpay + // | Self::Xendit + | Self::Zen + | Self::Zsl + | Self::Signifyd + | Self::Plaid + | Self::Razorpay + | Self::Riskified + | Self::Threedsecureio + | Self::Datatrans + | Self::Netcetera + | Self::CtpMastercard + | Self::Noon + | Self::Stripe => false, + Self::Checkout | Self::Nmi | Self::Cybersource => true, + } + } + + pub fn is_pre_processing_required_before_authorize(self) -> bool { + matches!(self, Self::Airwallex) + } + + pub fn should_acknowledge_webhook_for_resource_not_found_errors(self) -> bool { + matches!(self, Self::Adyenplatform) + } + + /// Validates if dummy connector can be created + /// Dummy connectors can be created only if dummy_connector feature is enabled in the configs + #[cfg(feature = "dummy_connector")] + pub fn validate_dummy_connector_create(self, is_dummy_connector_enabled: bool) -> bool { + matches!( + self, + Self::DummyConnector1 + | Self::DummyConnector2 + | Self::DummyConnector3 + | Self::DummyConnector4 + | Self::DummyConnector5 + | Self::DummyConnector6 + | Self::DummyConnector7 + ) && !is_dummy_connector_enabled + } +} + +/// Convert the RoutableConnectors to Connector +impl From for Connector { + fn from(routable_connector: RoutableConnectors) -> Self { + match routable_connector { + RoutableConnectors::Adyenplatform => Self::Adyenplatform, + #[cfg(feature = "dummy_connector")] + RoutableConnectors::DummyConnector1 => Self::DummyConnector1, + #[cfg(feature = "dummy_connector")] + RoutableConnectors::DummyConnector2 => Self::DummyConnector2, + #[cfg(feature = "dummy_connector")] + RoutableConnectors::DummyConnector3 => Self::DummyConnector3, + #[cfg(feature = "dummy_connector")] + RoutableConnectors::DummyConnector4 => Self::DummyConnector4, + #[cfg(feature = "dummy_connector")] + RoutableConnectors::DummyConnector5 => Self::DummyConnector5, + #[cfg(feature = "dummy_connector")] + RoutableConnectors::DummyConnector6 => Self::DummyConnector6, + #[cfg(feature = "dummy_connector")] + RoutableConnectors::DummyConnector7 => Self::DummyConnector7, + RoutableConnectors::Aci => Self::Aci, + RoutableConnectors::Adyen => Self::Adyen, + RoutableConnectors::Airwallex => Self::Airwallex, + RoutableConnectors::Authorizedotnet => Self::Authorizedotnet, + RoutableConnectors::Bankofamerica => Self::Bankofamerica, + RoutableConnectors::Billwerk => Self::Billwerk, + RoutableConnectors::Bitpay => Self::Bitpay, + RoutableConnectors::Bambora => Self::Bambora, + RoutableConnectors::Bamboraapac => Self::Bamboraapac, + RoutableConnectors::Bluesnap => Self::Bluesnap, + RoutableConnectors::Boku => Self::Boku, + RoutableConnectors::Braintree => Self::Braintree, + RoutableConnectors::Cashtocode => Self::Cashtocode, + RoutableConnectors::Checkout => Self::Checkout, + RoutableConnectors::Coinbase => Self::Coinbase, + RoutableConnectors::Cryptopay => Self::Cryptopay, + RoutableConnectors::Cybersource => Self::Cybersource, + RoutableConnectors::Datatrans => Self::Datatrans, + RoutableConnectors::Deutschebank => Self::Deutschebank, + RoutableConnectors::Digitalvirgo => Self::Digitalvirgo, + RoutableConnectors::Dlocal => Self::Dlocal, + RoutableConnectors::Ebanx => Self::Ebanx, + RoutableConnectors::Elavon => Self::Elavon, + RoutableConnectors::Fiserv => Self::Fiserv, + RoutableConnectors::Fiservemea => Self::Fiservemea, + RoutableConnectors::Fiuu => Self::Fiuu, + RoutableConnectors::Forte => Self::Forte, + RoutableConnectors::Globalpay => Self::Globalpay, + RoutableConnectors::Globepay => Self::Globepay, + RoutableConnectors::Gocardless => Self::Gocardless, + RoutableConnectors::Helcim => Self::Helcim, + RoutableConnectors::Iatapay => Self::Iatapay, + RoutableConnectors::Itaubank => Self::Itaubank, + RoutableConnectors::Jpmorgan => Self::Jpmorgan, + RoutableConnectors::Klarna => Self::Klarna, + RoutableConnectors::Mifinity => Self::Mifinity, + RoutableConnectors::Mollie => Self::Mollie, + RoutableConnectors::Multisafepay => Self::Multisafepay, + RoutableConnectors::Nexinets => Self::Nexinets, + RoutableConnectors::Nexixpay => Self::Nexixpay, + RoutableConnectors::Nmi => Self::Nmi, + RoutableConnectors::Noon => Self::Noon, + RoutableConnectors::Novalnet => Self::Novalnet, + RoutableConnectors::Nuvei => Self::Nuvei, + RoutableConnectors::Opennode => Self::Opennode, + RoutableConnectors::Paybox => Self::Paybox, + RoutableConnectors::Payme => Self::Payme, + RoutableConnectors::Payone => Self::Payone, + RoutableConnectors::Paypal => Self::Paypal, + RoutableConnectors::Payu => Self::Payu, + RoutableConnectors::Placetopay => Self::Placetopay, + RoutableConnectors::Powertranz => Self::Powertranz, + RoutableConnectors::Prophetpay => Self::Prophetpay, + RoutableConnectors::Rapyd => Self::Rapyd, + RoutableConnectors::Razorpay => Self::Razorpay, + RoutableConnectors::Riskified => Self::Riskified, + RoutableConnectors::Shift4 => Self::Shift4, + RoutableConnectors::Signifyd => Self::Signifyd, + RoutableConnectors::Square => Self::Square, + RoutableConnectors::Stax => Self::Stax, + RoutableConnectors::Stripe => Self::Stripe, + RoutableConnectors::Trustpay => Self::Trustpay, + RoutableConnectors::Tsys => Self::Tsys, + RoutableConnectors::Volt => Self::Volt, + RoutableConnectors::Wellsfargo => Self::Wellsfargo, + RoutableConnectors::Wise => Self::Wise, + RoutableConnectors::Worldline => Self::Worldline, + RoutableConnectors::Worldpay => Self::Worldpay, + RoutableConnectors::Zen => Self::Zen, + RoutableConnectors::Plaid => Self::Plaid, + RoutableConnectors::Zsl => Self::Zsl, + } + } +} diff --git a/crates/common_utils/src/events.rs b/crates/common_utils/src/events.rs index 9494b8209e75..bae525f4562f 100644 --- a/crates/common_utils/src/events.rs +++ b/crates/common_utils/src/events.rs @@ -1,4 +1,3 @@ -use common_enums::{PaymentMethod, PaymentMethodType}; use serde::Serialize; use crate::{id_type, types::TimeRange}; @@ -33,10 +32,17 @@ pub enum ApiEventsType { payment_id: id_type::GlobalPaymentId, refund_id: id_type::GlobalRefundId, }, + #[cfg(feature = "v1")] PaymentMethod { payment_method_id: String, - payment_method: Option, - payment_method_type: Option, + payment_method: Option, + payment_method_type: Option, + }, + #[cfg(feature = "v2")] + PaymentMethod { + payment_method_id: id_type::GlobalPaymentMethodId, + payment_method_type: Option, + payment_method_subtype: Option, }, #[cfg(all(feature = "v2", feature = "payment_methods_v2"))] PaymentMethodCreate, @@ -60,6 +66,10 @@ pub enum ApiEventsType { PaymentMethodList { payment_id: Option, }, + #[cfg(feature = "v2")] + PaymentMethodListForPaymentMethods { + payment_method_id: id_type::GlobalPaymentMethodId, + }, #[cfg(feature = "v1")] Webhooks { connector: String, diff --git a/crates/common_utils/src/id_type/global_id/payment_methods.rs b/crates/common_utils/src/id_type/global_id/payment_methods.rs index 40bd6ec0df4a..a4fec5e836ae 100644 --- a/crates/common_utils/src/id_type/global_id/payment_methods.rs +++ b/crates/common_utils/src/id_type/global_id/payment_methods.rs @@ -1,9 +1,8 @@ use error_stack::ResultExt; use crate::{ - errors, errors::CustomResult, - id_type::global_id::{CellId, GlobalEntity, GlobalId, GlobalIdError}, + id_type::global_id::{CellId, GlobalEntity, GlobalId}, }; /// A global id that can be used to identify a payment method @@ -26,6 +25,16 @@ pub enum GlobalPaymentMethodIdError { ConstructionError, } +impl crate::events::ApiEventMetric for GlobalPaymentMethodId { + fn get_api_event_type(&self) -> Option { + Some( + crate::events::ApiEventsType::PaymentMethodListForPaymentMethods { + payment_method_id: self.clone(), + }, + ) + } +} + impl GlobalPaymentMethodId { /// Create a new GlobalPaymentMethodId from cell id information pub fn generate(cell_id: &CellId) -> error_stack::Result { diff --git a/crates/diesel_models/src/merchant_connector_account.rs b/crates/diesel_models/src/merchant_connector_account.rs index 1ecff0fc70a0..e536648a6d72 100644 --- a/crates/diesel_models/src/merchant_connector_account.rs +++ b/crates/diesel_models/src/merchant_connector_account.rs @@ -73,7 +73,7 @@ impl MerchantConnectorAccount { #[diesel(table_name = merchant_connector_account, check_for_backend(diesel::pg::Pg))] pub struct MerchantConnectorAccount { pub merchant_id: id_type::MerchantId, - pub connector_name: String, + pub connector_name: common_enums::connector_enums::Connector, pub connector_account_details: Encryption, pub disabled: Option, #[diesel(deserialize_as = super::OptionalDieselArray)] @@ -143,7 +143,7 @@ pub struct MerchantConnectorAccountNew { pub struct MerchantConnectorAccountNew { pub merchant_id: Option, pub connector_type: Option, - pub connector_name: Option, + pub connector_name: Option, pub connector_account_details: Option, pub disabled: Option, #[diesel(deserialize_as = super::OptionalDieselArray)] diff --git a/crates/hyperswitch_domain_models/src/merchant_connector_account.rs b/crates/hyperswitch_domain_models/src/merchant_connector_account.rs index 7789c05e9902..a25b99799627 100644 --- a/crates/hyperswitch_domain_models/src/merchant_connector_account.rs +++ b/crates/hyperswitch_domain_models/src/merchant_connector_account.rs @@ -1,5 +1,3 @@ -#[cfg(feature = "v2")] -use api_models::admin; use common_utils::{ crypto::Encryptable, date_time, @@ -12,14 +10,10 @@ use common_utils::{ use diesel_models::{enums, merchant_connector_account::MerchantConnectorAccountUpdateInternal}; use error_stack::ResultExt; use masking::{PeekInterface, Secret}; -#[cfg(feature = "v2")] -use router_env::logger; use rustc_hash::FxHashMap; use serde_json::Value; use super::behaviour; -#[cfg(feature = "v2")] -use crate::errors::api_error_response::ApiErrorResponse; use crate::{ router_data, type_encryption::{crypto_operation, CryptoOperation}, @@ -82,7 +76,7 @@ impl MerchantConnectorAccount { pub struct MerchantConnectorAccount { pub id: id_type::MerchantConnectorAccountId, pub merchant_id: id_type::MerchantId, - pub connector_name: String, + pub connector_name: common_enums::connector_enums::Connector, #[encrypt] pub connector_account_details: Encryptable>, pub disabled: Option, @@ -142,7 +136,7 @@ impl MerchantConnectorAccount { pub struct PaymentMethodsEnabledForConnector { pub payment_methods_enabled: common_types::payment_methods::RequestPaymentMethodTypes, pub payment_method: common_enums::PaymentMethod, - pub connector: String, + pub connector: common_enums::connector_enums::Connector, } #[cfg(feature = "v2")] @@ -172,11 +166,8 @@ impl FlattenedPaymentMethodsEnabled { payment_method.payment_method_subtypes.unwrap_or_default(); let length = request_payment_methods_enabled.len(); request_payment_methods_enabled.into_iter().zip( - std::iter::repeat(( - connector_name.clone(), - payment_method.payment_method_type, - )) - .take(length), + std::iter::repeat((connector_name, payment_method.payment_method_type)) + .take(length), ) }) }) @@ -184,7 +175,7 @@ impl FlattenedPaymentMethodsEnabled { |(request_payment_methods, (connector_name, payment_method))| { PaymentMethodsEnabledForConnector { payment_methods_enabled: request_payment_methods, - connector: connector_name.clone(), + connector: connector_name, payment_method, } }, diff --git a/crates/openapi/src/openapi.rs b/crates/openapi/src/openapi.rs index 2f068b5609b8..32c2402e1081 100644 --- a/crates/openapi/src/openapi.rs +++ b/crates/openapi/src/openapi.rs @@ -85,8 +85,8 @@ Never share your secret api keys. Keep them guarded and secure. routes::payments::payments_post_session_tokens, // Routes for relay - routes::relay, - routes::relay_retrieve, + routes::relay::relay, + routes::relay::relay_retrieve, // Routes for refunds routes::refunds::refunds_create, diff --git a/crates/openapi/src/openapi_v2.rs b/crates/openapi/src/openapi_v2.rs index 12b0fd003559..5b4c89c3f4a6 100644 --- a/crates/openapi/src/openapi_v2.rs +++ b/crates/openapi/src/openapi_v2.rs @@ -128,15 +128,14 @@ Never share your secret api keys. Keep them guarded and secure. routes::payments::list_payment_methods, //Routes for payment methods - routes::payment_method::list_customer_payment_method_for_payment, - routes::payment_method::list_customer_payment_method_api, routes::payment_method::create_payment_method_api, routes::payment_method::create_payment_method_intent_api, + routes::payment_method::list_payment_methods, routes::payment_method::confirm_payment_method_intent_api, routes::payment_method::payment_method_update_api, routes::payment_method::payment_method_retrieve_api, routes::payment_method::payment_method_delete_api, - + // routes::payment_method::list_customer_payment_method_api, //Routes for refunds routes::refunds::refunds_create, @@ -208,7 +207,6 @@ Never share your secret api keys. Keep them guarded and secure. api_models::payment_methods::PaymentMethodDeleteResponse, api_models::payment_methods::PaymentMethodUpdate, api_models::payment_methods::PaymentMethodUpdateData, - api_models::payment_methods::CustomerDefaultPaymentMethodResponse, api_models::payment_methods::CardDetailFromLocker, api_models::payment_methods::PaymentMethodCreateData, api_models::payment_methods::CardDetail, @@ -477,14 +475,15 @@ Never share your secret api keys. Keep them guarded and secure. api_models::payments::AmountDetailsResponse, api_models::payments::BankCodeResponse, api_models::payments::PaymentMethodListResponseForPayments, + api_models::payments::ResponsePaymentMethodTypesForPayments, api_models::payment_methods::RequiredFieldInfo, - api_models::payment_methods::DefaultPaymentMethod, api_models::payment_methods::MaskedBankDetails, api_models::payment_methods::SurchargeDetailsResponse, api_models::payment_methods::SurchargeResponse, api_models::payment_methods::SurchargePercentage, api_models::payment_methods::PaymentMethodCollectLinkRequest, api_models::payment_methods::PaymentMethodCollectLinkResponse, + api_models::payment_methods::PaymentMethodSubtypeSpecificData, api_models::payments::PaymentsRetrieveResponse, api_models::refunds::RefundListRequest, api_models::refunds::RefundListResponse, diff --git a/crates/openapi/src/routes.rs b/crates/openapi/src/routes.rs index 2c1c58244124..4486df82b00b 100644 --- a/crates/openapi/src/routes.rs +++ b/crates/openapi/src/routes.rs @@ -19,8 +19,3 @@ pub mod refunds; pub mod relay; pub mod routing; pub mod webhook_events; - -pub use self::{ - customers::*, mandates::*, merchant_account::*, merchant_connector_account::*, organization::*, - payment_method::*, payments::*, poll::*, refunds::*, relay::*, routing::*, webhook_events::*, -}; diff --git a/crates/openapi/src/routes/payment_method.rs b/crates/openapi/src/routes/payment_method.rs index b38a23426788..e3596a8325b0 100644 --- a/crates/openapi/src/routes/payment_method.rs +++ b/crates/openapi/src/routes/payment_method.rs @@ -322,46 +322,49 @@ pub async fn payment_method_update_api() {} #[cfg(feature = "v2")] pub async fn payment_method_delete_api() {} -/// List customer saved payment methods for a payment +/// List saved payment methods for a Customer /// -/// To filter and list the applicable payment methods for a particular Customer ID, is to be associated with a payment +/// To filter and list the applicable payment methods for a particular Customer ID, to be used in a non-payments context #[utoipa::path( get, - path = "/v2/payments/{id}/saved-payment-methods", + path = "/v2/customers/{id}/saved-payment-methods", request_body( content = PaymentMethodListRequest, // TODO: Add examples and add param for customer_id ), responses( - (status = 200, description = "Payment Methods retrieved for customer tied to its respective client-secret passed in the param", body = CustomerPaymentMethodsListResponse), + (status = 200, description = "Payment Methods retrieved", body = CustomerPaymentMethodsListResponse), (status = 400, description = "Invalid Data"), (status = 404, description = "Payment Methods does not exist in records") ), tag = "Payment Methods", operation_id = "List all Payment Methods for a Customer", - security(("publishable_key" = [])) + security(("api_key" = [])) )] #[cfg(feature = "v2")] -pub async fn list_customer_payment_method_for_payment() {} +pub async fn list_customer_payment_method_api() {} -/// List saved payment methods for a Customer +/// Payment Methods - Payment Methods List /// -/// To filter and list the applicable payment methods for a particular Customer ID, to be used in a non-payments context +/// List the payment methods eligible for a payment. This endpoint also returns the saved payment methods for the customer. +#[cfg(feature = "v2")] #[utoipa::path( get, - path = "/v2/customers/{id}/saved-payment-methods", - request_body( - content = PaymentMethodListRequest, - // TODO: Add examples and add param for customer_id + path = "/v2/payment-methods/{id}/list-payment-methods", + params( + ("id" = String, Path, description = "The global payment method id"), + ( + "X-Profile-Id" = String, Header, + description = "Profile ID associated to the payment method intent", + example = json!({"X-Profile-Id": "pro_abcdefghijklmnop"}) + ), ), responses( - (status = 200, description = "Payment Methods retrieved", body = CustomerPaymentMethodsListResponse), - (status = 400, description = "Invalid Data"), - (status = 404, description = "Payment Methods does not exist in records") + (status = 200, description = "Get the payment methods", body = PaymentMethodListResponseForPayments), + (status = 404, description = "No payment method found with the given id") ), tag = "Payment Methods", - operation_id = "List all Payment Methods for a Customer", - security(("api_key" = [])) + operation_id = "List Payment methods for a Payment Method Intent", + security(("api_key" = [], "ephemeral_key" = [])) )] -#[cfg(feature = "v2")] -pub async fn list_customer_payment_method_api() {} +pub fn list_payment_methods() {} diff --git a/crates/router/Cargo.toml b/crates/router/Cargo.toml index 619d2fb19375..db65482628fd 100644 --- a/crates/router/Cargo.toml +++ b/crates/router/Cargo.toml @@ -17,7 +17,7 @@ email = ["external_services/email", "scheduler/email", "olap"] # keymanager_create, keymanager_mtls, encryption_service should not be removed or added to default feature. Once this features were enabled it can't be disabled as these are breaking changes. keymanager_create = [] keymanager_mtls = ["reqwest/rustls-tls", "common_utils/keymanager_mtls"] -encryption_service = ["keymanager_create","hyperswitch_domain_models/encryption_service", "common_utils/encryption_service"] +encryption_service = ["keymanager_create", "hyperswitch_domain_models/encryption_service", "common_utils/encryption_service"] km_forward_x_request_id = ["common_utils/km_forward_x_request_id"] frm = ["api_models/frm", "hyperswitch_domain_models/frm", "hyperswitch_connectors/frm", "hyperswitch_interfaces/frm"] stripe = [] diff --git a/crates/router/src/configs/defaults/payment_connector_required_fields.rs b/crates/router/src/configs/defaults/payment_connector_required_fields.rs index 9e42aec4a51d..e0b43af45ae9 100644 --- a/crates/router/src/configs/defaults/payment_connector_required_fields.rs +++ b/crates/router/src/configs/defaults/payment_connector_required_fields.rs @@ -105,6 +105,7 @@ impl Default for Mandates { } } +#[cfg(feature = "v1")] impl Default for settings::RequiredFields { fn default() -> Self { Self(HashMap::from([ @@ -1019,7 +1020,7 @@ impl Default for settings::RequiredFields { common:HashMap::new(), } ), - #[cfg(feature = "dummy_connector")] + #[cfg(feature = "dummy_connector")] ( enums::Connector::DummyConnector1, RequiredFieldFinal { @@ -9750,7 +9751,7 @@ impl Default for settings::RequiredFields { "VI".to_string(), "WF".to_string(), "EH".to_string(), - "ZM".to_string(), + "ZM".to_string(), ] }, value: None, @@ -12528,7 +12529,7 @@ impl Default for settings::RequiredFields { "ES".to_string(), "FR".to_string(), "IE".to_string(), - "NL".to_string(), + "NL".to_string(), ], }, value: None, diff --git a/crates/router/src/configs/defaults/payout_required_fields.rs b/crates/router/src/configs/defaults/payout_required_fields.rs index 0b8d380f7a31..5ec8161c5948 100644 --- a/crates/router/src/configs/defaults/payout_required_fields.rs +++ b/crates/router/src/configs/defaults/payout_required_fields.rs @@ -14,6 +14,7 @@ use crate::settings::{ RequiredFieldFinal, }; +#[cfg(feature = "v1")] impl Default for PayoutRequiredFields { fn default() -> Self { Self(HashMap::from([ @@ -65,6 +66,7 @@ impl Default for PayoutRequiredFields { } } +#[cfg(feature = "v1")] fn get_connector_payment_method_type_fields( connector: PayoutConnectors, payment_method_type: PaymentMethodType, diff --git a/crates/router/src/configs/settings.rs b/crates/router/src/configs/settings.rs index 737f8dfb980e..9d606a9e6074 100644 --- a/crates/router/src/configs/settings.rs +++ b/crates/router/src/configs/settings.rs @@ -39,6 +39,8 @@ use crate::{ events::EventsConfig, }; +pub const REQUIRED_FIELDS_CONFIG_FILE: &str = "payment_required_fields_v2.toml"; + #[derive(clap::Parser, Default)] #[cfg_attr(feature = "vergen", command(version = router_env::version!()))] pub struct CmdLineConf { @@ -537,9 +539,11 @@ pub struct NotAvailableFlows { #[cfg(feature = "payouts")] #[derive(Debug, Deserialize, Clone)] +#[cfg_attr(feature = "v2", derive(Default))] // Configs are read from the config file in config/payout_required_fields.toml pub struct PayoutRequiredFields(pub HashMap); #[derive(Debug, Deserialize, Clone)] +#[cfg_attr(feature = "v2", derive(Default))] // Configs are read from the config file in config/payment_required_fields.toml pub struct RequiredFields(pub HashMap); #[derive(Debug, Deserialize, Clone)] @@ -550,6 +554,7 @@ pub struct ConnectorFields { pub fields: HashMap, } +#[cfg(feature = "v1")] #[derive(Debug, Deserialize, Clone)] pub struct RequiredFieldFinal { pub mandate: HashMap, @@ -557,6 +562,14 @@ pub struct RequiredFieldFinal { pub common: HashMap, } +#[cfg(feature = "v2")] +#[derive(Debug, Deserialize, Clone)] +pub struct RequiredFieldFinal { + pub mandate: Option>, + pub non_mandate: Option>, + pub common: Option>, +} + #[derive(Debug, Default, Deserialize, Clone)] #[serde(default)] pub struct Secrets { @@ -797,7 +810,16 @@ impl Settings { let config = router_env::Config::builder(&environment.to_string()) .change_context(ApplicationError::ConfigurationError)? - .add_source(File::from(config_path).required(false)) + .add_source(File::from(config_path).required(false)); + + #[cfg(feature = "v2")] + let config = { + let required_fields_config_file = + router_env::Config::get_config_directory().join(REQUIRED_FIELDS_CONFIG_FILE); + config.add_source(File::from(required_fields_config_file).required(false)) + }; + + let config = config .add_source( Environment::with_prefix("ROUTER") .try_parsing(true) diff --git a/crates/router/src/core/admin.rs b/crates/router/src/core/admin.rs index 19c3e6c1e228..35df1ca8df3e 100644 --- a/crates/router/src/core/admin.rs +++ b/crates/router/src/core/admin.rs @@ -7,7 +7,7 @@ use api_models::{ use common_utils::{ date_time, ext_traits::{AsyncExt, Encode, OptionExt, ValueExt}, - id_type, pii, type_name, + fp_utils, id_type, pii, type_name, types::keymanager::{self as km_types, KeyManagerState, ToEncryptable}, }; use diesel_models::configs; @@ -2111,19 +2111,12 @@ impl MerchantConnectorAccountUpdateBridge for api_models::admin::MerchantConnect let metadata = self.metadata.clone().or(mca.metadata.clone()); - let connector_name = mca.connector_name.as_ref(); - let connector_enum = api_models::enums::Connector::from_str(connector_name) - .change_context(errors::ApiErrorResponse::InvalidDataValue { - field_name: "connector", - }) - .attach_printable_lazy(|| { - format!("unable to parse connector name {connector_name:?}") - })?; let connector_auth_type_and_metadata_validation = ConnectorAuthTypeAndMetadataValidation { - connector_name: &connector_enum, + connector_name: &mca.connector_name, auth_type: &auth, connector_meta_data: &metadata, }; + connector_auth_type_and_metadata_validation.validate_auth_and_metadata_type()?; let connector_status_and_disabled_validation = ConnectorStatusAndDisabledValidation { status: &self.status, @@ -2131,6 +2124,7 @@ impl MerchantConnectorAccountUpdateBridge for api_models::admin::MerchantConnect auth: &auth, current_status: &mca.status, }; + let (connector_status, disabled) = connector_status_and_disabled_validation.validate_status_and_disabled()?; @@ -2153,7 +2147,7 @@ impl MerchantConnectorAccountUpdateBridge for api_models::admin::MerchantConnect merchant_account.get_id(), &auth, &self.connector_type, - &connector_enum, + &mca.connector_name, types::AdditionalMerchantData::foreign_from(data.clone()), ) .await?, @@ -2520,7 +2514,7 @@ impl MerchantConnectorAccountCreateBridge for api::MerchantConnectorCreate { Ok(domain::MerchantConnectorAccount { merchant_id: business_profile.merchant_id.clone(), connector_type: self.connector_type, - connector_name: self.connector_name.to_string(), + connector_name: self.connector_name, connector_account_details: encrypted_data.connector_account_details, payment_methods_enabled, disabled, @@ -2819,11 +2813,16 @@ pub async fn create_connector( let store = state.store.as_ref(); let key_manager_state = &(&state).into(); #[cfg(feature = "dummy_connector")] - req.connector_name - .validate_dummy_connector_enabled(state.conf.dummy_connector.enabled) - .change_context(errors::ApiErrorResponse::InvalidRequestData { - message: "Invalid connector name".to_string(), - })?; + fp_utils::when( + req.connector_name + .validate_dummy_connector_create(state.conf.dummy_connector.enabled), + || { + Err(errors::ApiErrorResponse::InvalidRequestData { + message: "Invalid connector name".to_string(), + }) + }, + )?; + let connector_metadata = ConnectorMetadata { connector_metadata: &req.metadata, }; @@ -3331,11 +3330,11 @@ pub async fn delete_connector( let merchant_default_config_delete = DefaultFallbackRoutingConfigUpdate { routable_connector: &Some( - common_enums::RoutableConnectors::from_str(&mca.connector_name).map_err(|_| { - errors::ApiErrorResponse::InvalidDataValue { + common_enums::RoutableConnectors::from_str(&mca.connector_name.to_string()).map_err( + |_| errors::ApiErrorResponse::InvalidDataValue { field_name: "connector_name", - } - })?, + }, + )?, ), merchant_connector_id: &mca.get_id(), store: db, diff --git a/crates/router/src/core/apple_pay_certificates_migration.rs b/crates/router/src/core/apple_pay_certificates_migration.rs index 44be8f33bbec..21f38e59566a 100644 --- a/crates/router/src/core/apple_pay_certificates_migration.rs +++ b/crates/router/src/core/apple_pay_certificates_migration.rs @@ -13,6 +13,7 @@ use crate::{ types::{domain::types as domain_types, storage}, }; +#[cfg(feature = "v1")] pub async fn apple_pay_certificates_migration( state: SessionState, req: &apple_pay_certificates_migration::ApplePayCertificatesMigrationRequest, diff --git a/crates/router/src/core/disputes.rs b/crates/router/src/core/disputes.rs index 15bdbafb135b..c450139fc5cc 100644 --- a/crates/router/src/core/disputes.rs +++ b/crates/router/src/core/disputes.rs @@ -79,6 +79,7 @@ pub async fn accept_dispute( todo!() } +#[cfg(feature = "v1")] #[instrument(skip(state))] pub async fn get_filters_for_disputes( state: SessionState, diff --git a/crates/router/src/core/payment_methods.rs b/crates/router/src/core/payment_methods.rs index 6cdadf07320c..7f3c30cf48bd 100644 --- a/crates/router/src/core/payment_methods.rs +++ b/crates/router/src/core/payment_methods.rs @@ -1025,15 +1025,12 @@ pub async fn payment_method_intent_confirm( req: api::PaymentMethodIntentConfirm, merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, - pm_id: String, + pm_id: id_type::GlobalPaymentMethodId, ) -> RouterResponse { let key_manager_state = &(state).into(); req.validate()?; let db = &*state.store; - let pm_id = id_type::GlobalPaymentMethodId::generate_from_string(pm_id) - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Unable to generate GlobalPaymentMethodId")?; let payment_method = db .find_payment_method( @@ -1131,6 +1128,199 @@ pub async fn payment_method_intent_confirm( Ok(services::ApplicationResponse::Json(response)) } +#[cfg(feature = "v2")] +trait PerformFilteringOnEnabledPaymentMethods { + fn perform_filtering(self) -> FilteredPaymentMethodsEnabled; +} + +#[cfg(feature = "v2")] +impl PerformFilteringOnEnabledPaymentMethods + for hyperswitch_domain_models::merchant_connector_account::FlattenedPaymentMethodsEnabled +{ + fn perform_filtering(self) -> FilteredPaymentMethodsEnabled { + FilteredPaymentMethodsEnabled(self.payment_methods_enabled) + } +} + +#[cfg(feature = "v2")] +/// Container for the inputs required for the required fields +struct RequiredFieldsInput { + required_fields_config: settings::RequiredFields, +} + +#[cfg(feature = "v2")] +impl RequiredFieldsInput { + fn new(required_fields_config: settings::RequiredFields) -> Self { + Self { + required_fields_config, + } + } +} + +#[cfg(feature = "v2")] +/// Container for the filtered payment methods +struct FilteredPaymentMethodsEnabled( + Vec, +); + +#[cfg(feature = "v2")] +trait GetRequiredFields { + fn get_required_fields( + &self, + payment_method_enabled: &hyperswitch_domain_models::merchant_connector_account::PaymentMethodsEnabledForConnector, + ) -> Option<&settings::RequiredFieldFinal>; +} + +#[cfg(feature = "v2")] +impl GetRequiredFields for settings::RequiredFields { + fn get_required_fields( + &self, + payment_method_enabled: &hyperswitch_domain_models::merchant_connector_account::PaymentMethodsEnabledForConnector, + ) -> Option<&settings::RequiredFieldFinal> { + self.0 + .get(&payment_method_enabled.payment_method) + .and_then(|required_fields_for_payment_method| { + required_fields_for_payment_method.0.get( + &payment_method_enabled + .payment_methods_enabled + .payment_method_subtype, + ) + }) + .map(|connector_fields| &connector_fields.fields) + .and_then(|connector_hashmap| connector_hashmap.get(&payment_method_enabled.connector)) + } +} + +#[cfg(feature = "v2")] +impl FilteredPaymentMethodsEnabled { + fn get_required_fields( + self, + input: RequiredFieldsInput, + ) -> RequiredFieldsForEnabledPaymentMethodTypes { + let required_fields_config = input.required_fields_config; + + let required_fields_info = self + .0 + .into_iter() + .map(|payment_methods_enabled| { + let required_fields = + required_fields_config.get_required_fields(&payment_methods_enabled); + + let required_fields = required_fields + .map(|required_fields| { + let common_required_fields = required_fields + .common + .iter() + .flatten() + .map(ToOwned::to_owned); + + // Collect mandate required fields because this is for zero auth mandates only + let mandate_required_fields = required_fields + .mandate + .iter() + .flatten() + .map(ToOwned::to_owned); + + // Combine both common and mandate required fields + common_required_fields + .chain(mandate_required_fields) + .collect::>() + }) + .unwrap_or_default(); + + RequiredFieldsForEnabledPaymentMethod { + required_fields, + payment_method_type: payment_methods_enabled.payment_method, + payment_method_subtype: payment_methods_enabled + .payment_methods_enabled + .payment_method_subtype, + } + }) + .collect(); + + RequiredFieldsForEnabledPaymentMethodTypes(required_fields_info) + } +} + +#[cfg(feature = "v2")] +/// Element container to hold the filtered payment methods with required fields +struct RequiredFieldsForEnabledPaymentMethod { + required_fields: Vec, + payment_method_subtype: common_enums::PaymentMethodType, + payment_method_type: common_enums::PaymentMethod, +} + +#[cfg(feature = "v2")] +/// Container to hold the filtered payment methods enabled with required fields +struct RequiredFieldsForEnabledPaymentMethodTypes(Vec); + +#[cfg(feature = "v2")] +impl RequiredFieldsForEnabledPaymentMethodTypes { + fn generate_response(self) -> payment_methods::PaymentMethodListResponse { + let response_payment_methods = self + .0 + .into_iter() + .map( + |payment_methods_enabled| payment_methods::ResponsePaymentMethodTypes { + payment_method_type: payment_methods_enabled.payment_method_type, + payment_method_subtype: payment_methods_enabled.payment_method_subtype, + required_fields: payment_methods_enabled.required_fields, + extra_information: None, + }, + ) + .collect(); + + payment_methods::PaymentMethodListResponse { + payment_methods_enabled: response_payment_methods, + } + } +} + +#[cfg(all(feature = "v2", feature = "payment_methods_v2"))] +#[instrument(skip_all)] +pub async fn list_payment_methods( + state: SessionState, + merchant_account: domain::MerchantAccount, + key_store: domain::MerchantKeyStore, + profile: domain::Profile, + payment_method_id: id_type::GlobalPaymentMethodId, +) -> RouterResponse { + let key_manager_state = &(&state).into(); + + let db = &*state.store; + + db.find_payment_method( + key_manager_state, + &key_store, + &payment_method_id, + merchant_account.storage_scheme, + ) + .await + .change_context(errors::ApiErrorResponse::PaymentMethodNotFound) + .attach_printable("Unable to find payment method")?; + + let payment_connector_accounts = db + .list_enabled_connector_accounts_by_profile_id( + key_manager_state, + profile.get_id(), + &key_store, + common_enums::ConnectorType::PaymentProcessor, + ) + .await + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("error when fetching merchant connector accounts")?; + + let response = + hyperswitch_domain_models::merchant_connector_account::FlattenedPaymentMethodsEnabled::from_payment_connectors_list(payment_connector_accounts) + .perform_filtering() + .get_required_fields(RequiredFieldsInput::new(state.conf.required_fields.clone())) + .generate_response(); + + Ok(hyperswitch_domain_models::api::ApplicationResponse::Json( + response, + )) +} + #[cfg(all( feature = "v2", feature = "payment_methods_v2", @@ -1787,7 +1977,7 @@ pub async fn retrieve_payment_method( let resp = api::PaymentMethodResponse { merchant_id: payment_method.merchant_id.to_owned(), customer_id: payment_method.customer_id.to_owned(), - payment_method_id: payment_method.id.get_string_repr().to_string(), + id: payment_method.id.to_owned(), payment_method_type: payment_method.get_payment_method_type(), payment_method_subtype: payment_method.get_payment_method_subtype(), created: Some(payment_method.created_at), @@ -1955,9 +2145,7 @@ pub async fn delete_payment_method( .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Failed to delete payment method from vault")?; - let response = api::PaymentMethodDeleteResponse { - payment_method_id: pm_id.get_string_repr().to_string(), - }; + let response = api::PaymentMethodDeleteResponse { id: pm_id }; Ok(services::ApplicationResponse::Json(response)) } diff --git a/crates/router/src/core/payment_methods/cards.rs b/crates/router/src/core/payment_methods/cards.rs index 164c0e9557af..82240a265d1b 100644 --- a/crates/router/src/core/payment_methods/cards.rs +++ b/crates/router/src/core/payment_methods/cards.rs @@ -13,10 +13,9 @@ use api_models::{ enums as api_enums, payment_methods::{ BankAccountTokenData, Card, CardDetailUpdate, CardDetailsPaymentMethod, CardNetworkTypes, - CountryCodeWithName, CustomerDefaultPaymentMethodResponse, ListCountriesCurrenciesRequest, - ListCountriesCurrenciesResponse, MaskedBankDetails, PaymentExperienceTypes, - PaymentMethodsData, RequestPaymentMethodTypes, RequiredFieldInfo, - ResponsePaymentMethodIntermediate, ResponsePaymentMethodTypes, + CountryCodeWithName, ListCountriesCurrenciesRequest, ListCountriesCurrenciesResponse, + MaskedBankDetails, PaymentExperienceTypes, PaymentMethodsData, RequestPaymentMethodTypes, + RequiredFieldInfo, ResponsePaymentMethodIntermediate, ResponsePaymentMethodTypes, ResponsePaymentMethodsEnabled, }, payments::BankCodeResponse, @@ -5511,18 +5510,6 @@ pub async fn get_bank_account_connector_details( } } -#[cfg(all(feature = "v2", feature = "customer_v2"))] -pub async fn set_default_payment_method( - _state: &routes::SessionState, - _merchant_id: &id_type::MerchantId, - _key_store: domain::MerchantKeyStore, - _customer_id: &id_type::CustomerId, - _payment_method_id: String, - _storage_scheme: MerchantStorageScheme, -) -> errors::RouterResponse { - todo!() -} - #[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "customer_v2")))] pub async fn set_default_payment_method( state: &routes::SessionState, @@ -5531,7 +5518,7 @@ pub async fn set_default_payment_method( customer_id: &id_type::CustomerId, payment_method_id: String, storage_scheme: MerchantStorageScheme, -) -> errors::RouterResponse { +) -> errors::RouterResponse { let db = &*state.store; let key_manager_state = &state.into(); // check for the customer @@ -5599,7 +5586,7 @@ pub async fn set_default_payment_method( .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Failed to update the default payment method id for the customer")?; - let resp = CustomerDefaultPaymentMethodResponse { + let resp = api_models::payment_methods::CustomerDefaultPaymentMethodResponse { default_payment_method_id: updated_customer_details.default_payment_method_id, customer_id, payment_method_type: payment_method.get_payment_method_subtype(), diff --git a/crates/router/src/core/payment_methods/transformers.rs b/crates/router/src/core/payment_methods/transformers.rs index ce95096a0fb3..4a43eef1ed66 100644 --- a/crates/router/src/core/payment_methods/transformers.rs +++ b/crates/router/src/core/payment_methods/transformers.rs @@ -567,7 +567,7 @@ pub fn generate_payment_method_response( let resp = api::PaymentMethodResponse { merchant_id: pm.merchant_id.to_owned(), customer_id: pm.customer_id.to_owned(), - payment_method_id: pm.id.get_string_repr().to_owned(), + id: pm.id.to_owned(), payment_method_type: pm.get_payment_method_type(), payment_method_subtype: pm.get_payment_method_subtype(), created: Some(pm.created_at), diff --git a/crates/router/src/core/payments/flows/session_flow.rs b/crates/router/src/core/payments/flows/session_flow.rs index 1e3432220ac1..65688c5d465c 100644 --- a/crates/router/src/core/payments/flows/session_flow.rs +++ b/crates/router/src/core/payments/flows/session_flow.rs @@ -156,6 +156,7 @@ impl Feature for types::PaymentsSessio /// This function checks if for a given connector, payment_method and payment_method_type, /// the list of required_field_type is present in dynamic fields +#[cfg(feature = "v1")] fn is_dynamic_fields_required( required_fields: &settings::RequiredFields, payment_method: enums::PaymentMethod, @@ -187,6 +188,43 @@ fn is_dynamic_fields_required( .unwrap_or(false) } +/// This function checks if for a given connector, payment_method and payment_method_type, +/// the list of required_field_type is present in dynamic fields +#[cfg(feature = "v2")] +fn is_dynamic_fields_required( + required_fields: &settings::RequiredFields, + payment_method: enums::PaymentMethod, + payment_method_type: enums::PaymentMethodType, + connector: types::Connector, + required_field_type: Vec, +) -> bool { + required_fields + .0 + .get(&payment_method) + .and_then(|pm_type| pm_type.0.get(&payment_method_type)) + .and_then(|required_fields_for_connector| { + required_fields_for_connector.fields.get(&connector) + }) + .map(|required_fields_final| { + required_fields_final + .non_mandate + .iter() + .flatten() + .any(|field_info| required_field_type.contains(&field_info.field_type)) + || required_fields_final + .mandate + .iter() + .flatten() + .any(|field_info| required_field_type.contains(&field_info.field_type)) + || required_fields_final + .common + .iter() + .flatten() + .any(|field_info| required_field_type.contains(&field_info.field_type)) + }) + .unwrap_or(false) +} + fn build_apple_pay_session_request( state: &routes::SessionState, request: payment_types::ApplepaySessionRequest, diff --git a/crates/router/src/core/payments/helpers.rs b/crates/router/src/core/payments/helpers.rs index b2c90e03b589..b3d1fbadf3e0 100644 --- a/crates/router/src/core/payments/helpers.rs +++ b/crates/router/src/core/payments/helpers.rs @@ -5108,7 +5108,7 @@ pub fn get_applepay_metadata( }) } -#[cfg(feature = "retry")] +#[cfg(all(feature = "retry", feature = "v1"))] pub async fn get_apple_pay_retryable_connectors( state: &SessionState, merchant_account: &domain::MerchantAccount, @@ -6166,6 +6166,7 @@ where Ok(()) } +#[cfg(feature = "v1")] pub async fn validate_merchant_connector_ids_in_connector_mandate_details( state: &SessionState, key_store: &domain::MerchantKeyStore, diff --git a/crates/router/src/core/payments/payment_methods.rs b/crates/router/src/core/payments/payment_methods.rs index 6ed436ae3c77..df100d2e9b63 100644 --- a/crates/router/src/core/payments/payment_methods.rs +++ b/crates/router/src/core/payments/payment_methods.rs @@ -34,7 +34,7 @@ pub async fn list_payment_methods( .await .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?; - validate_payment_status(payment_intent.status)?; + validate_payment_status_for_payment_method_list(payment_intent.status)?; let client_secret = header_payload .client_secret @@ -108,8 +108,7 @@ impl FilteredPaymentMethodsEnabled { /// Element container to hold the filtered payment methods with required fields struct RequiredFieldsForEnabledPaymentMethod { - required_field: - Option>, + required_field: Option>, payment_method_subtype: common_enums::PaymentMethodType, payment_method_type: common_enums::PaymentMethod, } @@ -119,8 +118,7 @@ struct RequiredFieldsForEnabledPaymentMethodTypes(Vec>, + required_field: Option>, payment_method_subtype: common_enums::PaymentMethodType, payment_method_type: common_enums::PaymentMethod, surcharge: Option, @@ -137,7 +135,7 @@ impl RequiredFieldsAndSurchargeForEnabledPaymentMethodTypes { .0 .into_iter() .map(|payment_methods_enabled| { - api_models::payment_methods::ResponsePaymentMethodTypes { + api_models::payments::ResponsePaymentMethodTypesForPayments { payment_method_type: payment_methods_enabled.payment_method_type, payment_method_subtype: payment_methods_enabled.payment_method_subtype, required_fields: payment_methods_enabled.required_field, @@ -188,7 +186,7 @@ impl PerformFilteringOnPaymentMethodsEnabled } /// Validate if payment methods list can be performed on the current status of payment intent -fn validate_payment_status( +fn validate_payment_status_for_payment_method_list( intent_status: common_enums::IntentStatus, ) -> Result<(), errors::ApiErrorResponse> { match intent_status { diff --git a/crates/router/src/core/payouts/transformers.rs b/crates/router/src/core/payouts/transformers.rs index c1f314043053..b4e41ecb09d6 100644 --- a/crates/router/src/core/payouts/transformers.rs +++ b/crates/router/src/core/payouts/transformers.rs @@ -119,6 +119,7 @@ impl } } +#[cfg(feature = "v1")] impl ForeignFrom<( &PayoutRequiredFields, diff --git a/crates/router/src/core/relay.rs b/crates/router/src/core/relay.rs index d25296635ad1..9492816452ae 100644 --- a/crates/router/src/core/relay.rs +++ b/crates/router/src/core/relay.rs @@ -109,9 +109,15 @@ pub async fn relay_refund( let merchant_id = merchant_account.get_id(); + #[cfg(feature = "v1")] + let connector_name = &connector_account.connector_name; + + #[cfg(feature = "v2")] + let connector_name = &connector_account.connector_name.to_string(); + let connector_data = api::ConnectorData::get_connector_by_name( &state.conf.connectors, - &connector_account.connector_name, + connector_name, api::GetToken::Connector, Some(connector_id.clone()), )?; @@ -124,7 +130,6 @@ pub async fn relay_refund( let router_data = utils::construct_relay_refund_router_data( state, - &connector_account.connector_name, merchant_id, &connector_account, relay_record, @@ -289,9 +294,15 @@ pub async fn sync_relay_refund_with_gateway( let connector_id = &relay_record.connector_id; let merchant_id = merchant_account.get_id(); + #[cfg(feature = "v1")] + let connector_name = &connector_account.connector_name; + + #[cfg(feature = "v2")] + let connector_name = &connector_account.connector_name.to_string(); + let connector_data: api::ConnectorData = api::ConnectorData::get_connector_by_name( &state.conf.connectors, - &connector_account.connector_name, + connector_name, api::GetToken::Connector, Some(connector_id.clone()), ) @@ -300,7 +311,6 @@ pub async fn sync_relay_refund_with_gateway( let router_data = utils::construct_relay_refund_router_data( state, - &connector_account.connector_name, merchant_id, &connector_account, relay_record, diff --git a/crates/router/src/core/relay/utils.rs b/crates/router/src/core/relay/utils.rs index 946f8df7d64e..37d11924a6c4 100644 --- a/crates/router/src/core/relay/utils.rs +++ b/crates/router/src/core/relay/utils.rs @@ -19,7 +19,6 @@ const IRRELEVANT_PAYMENT_ATTEMPT_ID: &str = "irrelevant_payment_attempt_id"; pub async fn construct_relay_refund_router_data<'a, F>( state: &'a SessionState, - connector_name: &str, merchant_id: &id_type::MerchantId, connector_account: &domain::MerchantConnectorAccount, relay_record: &hyperswitch_domain_models::relay::Relay, @@ -29,6 +28,12 @@ pub async fn construct_relay_refund_router_data<'a, F>( .change_context(errors::ApiErrorResponse::InternalServerError) .attach_printable("Failed while parsing value for ConnectorAuthType")?; + #[cfg(feature = "v2")] + let connector_name = &connector_account.connector_name.to_string(); + + #[cfg(feature = "v1")] + let connector_name = &connector_account.connector_name; + let webhook_url = Some(payments::helpers::create_webhook_url( &state.base_url.clone(), merchant_id, diff --git a/crates/router/src/core/routing/helpers.rs b/crates/router/src/core/routing/helpers.rs index 159def38621a..6f739c48ae3f 100644 --- a/crates/router/src/core/routing/helpers.rs +++ b/crates/router/src/core/routing/helpers.rs @@ -300,10 +300,13 @@ pub struct RoutingAlgorithmHelpers<'h> { #[derive(Clone, Debug)] pub struct ConnectNameAndMCAIdForProfile<'a>( - pub FxHashSet<(&'a String, id_type::MerchantConnectorAccountId)>, + pub FxHashSet<( + &'a common_enums::connector_enums::Connector, + id_type::MerchantConnectorAccountId, + )>, ); #[derive(Clone, Debug)] -pub struct ConnectNameForProfile<'a>(pub FxHashSet<&'a String>); +pub struct ConnectNameForProfile<'a>(pub FxHashSet<&'a common_enums::connector_enums::Connector>); #[cfg(feature = "v2")] #[derive(Clone, Debug)] @@ -368,23 +371,25 @@ impl RoutingAlgorithmHelpers<'_> { choice: &routing_types::RoutableConnectorChoice, ) -> RouterResult<()> { if let Some(ref mca_id) = choice.merchant_connector_id { + let connector_choice = common_enums::connector_enums::Connector::from(choice.connector); error_stack::ensure!( - self.name_mca_id_set.0.contains(&(&choice.connector.to_string(), mca_id.clone())), - errors::ApiErrorResponse::InvalidRequestData { - message: format!( - "connector with name '{}' and merchant connector account id '{:?}' not found for the given profile", - choice.connector, - mca_id, - ) - } - ); + self.name_mca_id_set.0.contains(&(&connector_choice, mca_id.clone())), + errors::ApiErrorResponse::InvalidRequestData { + message: format!( + "connector with name '{}' and merchant connector account id '{:?}' not found for the given profile", + connector_choice, + mca_id, + ) + } + ); } else { + let connector_choice = common_enums::connector_enums::Connector::from(choice.connector); error_stack::ensure!( - self.name_set.0.contains(&choice.connector.to_string()), + self.name_set.0.contains(&connector_choice), errors::ApiErrorResponse::InvalidRequestData { message: format!( "connector with name '{}' not found for the given profile", - choice.connector, + connector_choice, ) } ); diff --git a/crates/router/src/core/user/dashboard_metadata.rs b/crates/router/src/core/user/dashboard_metadata.rs index aa67a70223ff..689762c1f43b 100644 --- a/crates/router/src/core/user/dashboard_metadata.rs +++ b/crates/router/src/core/user/dashboard_metadata.rs @@ -34,6 +34,7 @@ pub async fn set_metadata( Ok(ApplicationResponse::StatusOk) } +#[cfg(feature = "v1")] pub async fn get_multiple_metadata( state: SessionState, user: UserFromToken, @@ -622,6 +623,7 @@ async fn fetch_metadata( Ok(dashboard_metadata) } +#[cfg(feature = "v1")] pub async fn backfill_metadata( state: &SessionState, user: &UserFromToken, diff --git a/crates/router/src/core/webhooks/incoming_v2.rs b/crates/router/src/core/webhooks/incoming_v2.rs index 569cd330a079..01f8ee5e11af 100644 --- a/crates/router/src/core/webhooks/incoming_v2.rs +++ b/crates/router/src/core/webhooks/incoming_v2.rs @@ -755,8 +755,11 @@ async fn fetch_mca_and_connector( }) .attach_printable("error while fetching merchant_connector_account from connector_id")?; - let (connector, connector_name) = - get_connector_by_connector_name(state, &mca.connector_name, Some(mca.get_id()))?; + let (connector, connector_name) = get_connector_by_connector_name( + state, + &mca.connector_name.to_string(), + Some(mca.get_id()), + )?; Ok((mca, connector, connector_name)) } diff --git a/crates/router/src/db/merchant_connector_account.rs b/crates/router/src/db/merchant_connector_account.rs index 0abbccd2cb35..0cd496686771 100644 --- a/crates/router/src/db/merchant_connector_account.rs +++ b/crates/router/src/db/merchant_connector_account.rs @@ -627,7 +627,12 @@ impl MerchantConnectorAccountInterface for Store { for (merchant_connector_account, update_merchant_connector_account) in merchant_connector_accounts { + #[cfg(feature = "v1")] let _connector_name = merchant_connector_account.connector_name.clone(); + + #[cfg(feature = "v2")] + let _connector_name = merchant_connector_account.connector_name.to_string(); + let _profile_id = merchant_connector_account.profile_id.clone(); let _merchant_id = merchant_connector_account.merchant_id.clone(); @@ -791,7 +796,7 @@ impl MerchantConnectorAccountInterface for Store { merchant_connector_account: storage::MerchantConnectorAccountUpdateInternal, key_store: &domain::MerchantKeyStore, ) -> CustomResult { - let _connector_name = this.connector_name.clone(); + let _connector_name = this.connector_name; let _profile_id = this.profile_id.clone(); let _merchant_id = this.merchant_id.clone(); @@ -1805,7 +1810,7 @@ mod merchant_connector_account_cache_tests { let mca = domain::MerchantConnectorAccount { id: id.clone(), merchant_id: merchant_id.clone(), - connector_name: "stripe".to_string(), + connector_name: common_enums::connector_enums::Connector::Stripe, connector_account_details: domain::types::crypto_operation( key_manager_state, type_name!(domain::MerchantConnectorAccount), diff --git a/crates/router/src/routes/app.rs b/crates/router/src/routes/app.rs index f9dbec774528..65e53a47f2b4 100644 --- a/crates/router/src/routes/app.rs +++ b/crates/router/src/routes/app.rs @@ -33,7 +33,7 @@ use super::dummy_connector::*; #[cfg(all(any(feature = "v1", feature = "v2"), feature = "oltp"))] use super::ephemeral_key::*; #[cfg(any(feature = "olap", feature = "oltp"))] -use super::payment_methods::*; +use super::payment_methods; #[cfg(feature = "payouts")] use super::payout_link::*; #[cfg(feature = "payouts")] @@ -59,7 +59,7 @@ use super::{ #[cfg(feature = "v1")] use super::{apple_pay_certificates_migration, blocklist, payment_link, webhook_events}; #[cfg(any(feature = "olap", feature = "oltp"))] -use super::{configs::*, customers::*, payments}; +use super::{configs::*, customers, payments}; #[cfg(all(any(feature = "olap", feature = "oltp"), feature = "v1"))] use super::{mandates::*, refunds::*}; #[cfg(feature = "olap")] @@ -987,24 +987,25 @@ impl Customers { let mut route = web::scope("/v2/customers").app_data(web::Data::new(state)); #[cfg(all(feature = "olap", feature = "v2", feature = "customer_v2"))] { - route = route.service(web::resource("/list").route(web::get().to(customers_list))) + route = route + .service(web::resource("/list").route(web::get().to(customers::customers_list))) } #[cfg(all(feature = "oltp", feature = "v2", feature = "customer_v2"))] { route = route - .service(web::resource("").route(web::post().to(customers_create))) + .service(web::resource("").route(web::post().to(customers::customers_create))) .service( web::resource("/{id}") - .route(web::put().to(customers_update)) - .route(web::get().to(customers_retrieve)) - .route(web::delete().to(customers_delete)), + .route(web::put().to(customers::customers_update)) + .route(web::get().to(customers::customers_retrieve)) + .route(web::delete().to(customers::customers_delete)), ) } #[cfg(all(feature = "oltp", feature = "v2", feature = "payment_methods_v2"))] { route = route.service( web::resource("/{customer_id}/saved-payment-methods") - .route(web::get().to(list_customer_payment_method_api)), + .route(web::get().to(payment_methods::list_customer_payment_method_api)), ); } route @@ -1026,32 +1027,33 @@ impl Customers { route = route .service( web::resource("/{customer_id}/mandates") - .route(web::get().to(get_customer_mandates)), + .route(web::get().to(customers::get_customer_mandates)), ) - .service(web::resource("/list").route(web::get().to(customers_list))) + .service(web::resource("/list").route(web::get().to(customers::customers_list))) } #[cfg(feature = "oltp")] { route = route - .service(web::resource("").route(web::post().to(customers_create))) + .service(web::resource("").route(web::post().to(customers::customers_create))) .service( - web::resource("/payment_methods") - .route(web::get().to(list_customer_payment_method_api_client)), + web::resource("/payment_methods").route( + web::get().to(payment_methods::list_customer_payment_method_api_client), + ), ) .service( web::resource("/{customer_id}/payment_methods") - .route(web::get().to(list_customer_payment_method_api)), + .route(web::get().to(payment_methods::list_customer_payment_method_api)), ) .service( web::resource("/{customer_id}/payment_methods/{payment_method_id}/default") - .route(web::post().to(default_payment_method_set_api)), + .route(web::post().to(payment_methods::default_payment_method_set_api)), ) .service( web::resource("/{customer_id}") - .route(web::get().to(customers_retrieve)) - .route(web::post().to(customers_update)) - .route(web::delete().to(customers_delete)), + .route(web::get().to(customers::customers_retrieve)) + .route(web::post().to(customers::customers_update)) + .route(web::delete().to(customers::customers_delete)), ) } @@ -1150,25 +1152,35 @@ impl PaymentMethods { pub fn server(state: AppState) -> Scope { let mut route = web::scope("/v2/payment-methods").app_data(web::Data::new(state)); route = route - .service(web::resource("").route(web::post().to(create_payment_method_api))) - .service( - web::resource("/create-intent") - .route(web::post().to(create_payment_method_intent_api)), - ) - .service( - web::resource("/{id}/confirm-intent") - .route(web::post().to(confirm_payment_method_intent_api)), - ) .service( - web::resource("/{id}/update-saved-payment-method") - .route(web::patch().to(payment_method_update_api)), + web::resource("").route(web::post().to(payment_methods::create_payment_method_api)), ) .service( - web::resource("/{id}") - .route(web::get().to(payment_method_retrieve_api)) - .route(web::delete().to(payment_method_delete_api)), + web::resource("/create-intent") + .route(web::post().to(payment_methods::create_payment_method_intent_api)), ); + route = route.service( + web::scope("/{id}") + .service( + web::resource("") + .route(web::get().to(payment_methods::payment_method_retrieve_api)) + .route(web::delete().to(payment_methods::payment_method_delete_api)), + ) + .service( + web::resource("/list-payment-methods") + .route(web::get().to(payment_methods::list_payment_methods)), + ) + .service( + web::resource("/confirm-intent") + .route(web::post().to(payment_methods::confirm_payment_method_intent_api)), + ) + .service( + web::resource("/update-saved-payment-method") + .route(web::put().to(payment_methods::payment_method_update_api)), + ), + ); + route } } @@ -1184,44 +1196,49 @@ impl PaymentMethods { let mut route = web::scope("/payment_methods").app_data(web::Data::new(state)); #[cfg(feature = "olap")] { - route = route.service( - web::resource("/filter") - .route(web::get().to(list_countries_currencies_for_connector_payment_method)), - ); + route = + route.service(web::resource("/filter").route( + web::get().to( + payment_methods::list_countries_currencies_for_connector_payment_method, + ), + )); } #[cfg(feature = "oltp")] { route = route .service( web::resource("") - .route(web::post().to(create_payment_method_api)) - .route(web::get().to(list_payment_method_api)), // TODO : added for sdk compatibility for now, need to deprecate this later + .route(web::post().to(payment_methods::create_payment_method_api)) + .route(web::get().to(payment_methods::list_payment_method_api)), // TODO : added for sdk compatibility for now, need to deprecate this later ) .service( - web::resource("/migrate").route(web::post().to(migrate_payment_method_api)), + web::resource("/migrate") + .route(web::post().to(payment_methods::migrate_payment_method_api)), ) .service( - web::resource("/migrate-batch").route(web::post().to(migrate_payment_methods)), + web::resource("/migrate-batch") + .route(web::post().to(payment_methods::migrate_payment_methods)), ) .service( - web::resource("/collect").route(web::post().to(initiate_pm_collect_link_flow)), + web::resource("/collect") + .route(web::post().to(payment_methods::initiate_pm_collect_link_flow)), ) .service( web::resource("/collect/{merchant_id}/{collect_id}") - .route(web::get().to(render_pm_collect_link)), + .route(web::get().to(payment_methods::render_pm_collect_link)), ) .service( web::resource("/{payment_method_id}") - .route(web::get().to(payment_method_retrieve_api)) - .route(web::delete().to(payment_method_delete_api)), + .route(web::get().to(payment_methods::payment_method_retrieve_api)) + .route(web::delete().to(payment_methods::payment_method_delete_api)), ) .service( web::resource("/{payment_method_id}/update") - .route(web::post().to(payment_method_update_api)), + .route(web::post().to(payment_methods::payment_method_update_api)), ) .service( web::resource("/{payment_method_id}/save") - .route(web::post().to(save_payment_method_api)), + .route(web::post().to(payment_methods::save_payment_method_api)), ) .service( web::resource("/auth/link").route(web::post().to(pm_auth::link_token_create)), @@ -1424,7 +1441,8 @@ impl MerchantConnectorAccount { #[cfg(feature = "oltp")] { route = route.service( - web::resource("/payment_methods").route(web::get().to(list_payment_method_api)), + web::resource("/payment_methods") + .route(web::get().to(payment_methods::list_payment_method_api)), ); } route diff --git a/crates/router/src/routes/disputes.rs b/crates/router/src/routes/disputes.rs index 1935b8cd00ec..c919bfcd40ea 100644 --- a/crates/router/src/routes/disputes.rs +++ b/crates/router/src/routes/disputes.rs @@ -168,6 +168,7 @@ pub async fn retrieve_disputes_list_profile( .await } +#[cfg(feature = "v1")] /// Disputes - Disputes Filters #[utoipa::path( get, diff --git a/crates/router/src/routes/payment_methods.rs b/crates/router/src/routes/payment_methods.rs index d8dfb7320618..c20ccf5be3bf 100644 --- a/crates/router/src/routes/payment_methods.rs +++ b/crates/router/src/routes/payment_methods.rs @@ -135,7 +135,7 @@ pub async fn confirm_payment_method_intent_api( state: web::Data, req: HttpRequest, json_payload: web::Json, - path: web::Path, + path: web::Path, ) -> HttpResponse { let flow = Flow::PaymentMethodsCreate; let pm_id = path.into_inner(); @@ -147,7 +147,7 @@ pub async fn confirm_payment_method_intent_api( }; let inner_payload = payment_methods::PaymentMethodIntentConfirmInternal { - id: pm_id.clone(), + id: pm_id.to_owned(), payment_method_type: payload.payment_method_type, payment_method_subtype: payload.payment_method_subtype, customer_id: payload.customer_id.to_owned(), @@ -178,6 +178,41 @@ pub async fn confirm_payment_method_intent_api( .await } +#[cfg(all(feature = "v2", feature = "payment_methods_v2"))] +#[instrument(skip_all, fields(flow = ?Flow::PaymentMethodsList))] +pub async fn list_payment_methods( + state: web::Data, + req: HttpRequest, + path: web::Path, +) -> HttpResponse { + let flow = Flow::PaymentMethodsList; + let payment_method_id = path.into_inner(); + + let auth = match auth::is_ephemeral_or_publishible_auth(req.headers()) { + Ok(auth) => auth, + Err(e) => return api::log_and_return_error_response(e), + }; + + Box::pin(api::server_wrap( + flow, + state, + &req, + payment_method_id, + |state, auth: auth::AuthenticationData, payment_method_id, _| { + payment_methods_routes::list_payment_methods( + state, + auth.merchant_account, + auth.key_store, + auth.profile, + payment_method_id, + ) + }, + &*auth, + api_locking::LockAction::NotApplicable, + )) + .await +} + #[cfg(all(feature = "v2", feature = "payment_methods_v2"))] #[instrument(skip_all, fields(flow = ?Flow::PaymentMethodsUpdate))] pub async fn payment_method_update_api( @@ -521,7 +556,7 @@ pub async fn list_customer_payment_method_api( state: web::Data, customer_id: web::Path, req: HttpRequest, - query_payload: web::Query, + query_payload: web::Query, ) -> HttpResponse { let flow = Flow::CustomerPaymentMethodsList; let payload = query_payload.into_inner(); diff --git a/crates/router/src/routes/user.rs b/crates/router/src/routes/user.rs index d075048ddb6b..1af22d0338ac 100644 --- a/crates/router/src/routes/user.rs +++ b/crates/router/src/routes/user.rs @@ -197,6 +197,7 @@ pub async fn set_dashboard_metadata( .await } +#[cfg(feature = "v1")] pub async fn get_multiple_dashboard_metadata( state: web::Data, req: HttpRequest, diff --git a/crates/router/src/types/api/payment_methods.rs b/crates/router/src/types/api/payment_methods.rs index 25227ae5383a..e4d9adbd90bb 100644 --- a/crates/router/src/types/api/payment_methods.rs +++ b/crates/router/src/types/api/payment_methods.rs @@ -1,8 +1,8 @@ #[cfg(all(feature = "v2", feature = "payment_methods_v2"))] pub use api_models::payment_methods::{ CardDetail, CardDetailFromLocker, CardDetailsPaymentMethod, CardType, CustomerPaymentMethod, - CustomerPaymentMethodsListResponse, DefaultPaymentMethod, DeleteTokenizeByTokenRequest, - GetTokenizePayloadRequest, GetTokenizePayloadResponse, ListCountriesCurrenciesRequest, + CustomerPaymentMethodsListResponse, DeleteTokenizeByTokenRequest, GetTokenizePayloadRequest, + GetTokenizePayloadResponse, ListCountriesCurrenciesRequest, PaymentMethodCollectLinkRenderRequest, PaymentMethodCollectLinkRequest, PaymentMethodCreate, PaymentMethodCreateData, PaymentMethodDeleteResponse, PaymentMethodId, PaymentMethodIntentConfirm, PaymentMethodIntentConfirmInternal, PaymentMethodIntentCreate, diff --git a/crates/router_env/src/logger/config.rs b/crates/router_env/src/logger/config.rs index 431fb5a6368e..a7bdbe0696a2 100644 --- a/crates/router_env/src/logger/config.rs +++ b/crates/router_env/src/logger/config.rs @@ -175,18 +175,29 @@ impl Config { if let Some(explicit_config_path_val) = explicit_config_path { config_path.push(explicit_config_path_val); } else { - let config_directory = - std::env::var(crate::env::vars::CONFIG_DIR).unwrap_or_else(|_| "config".into()); let config_file_name = match environment { "production" => "production.toml", "sandbox" => "sandbox.toml", _ => "development.toml", }; - config_path.push(crate::env::workspace_path()); + let config_directory = Self::get_config_directory(); config_path.push(config_directory); config_path.push(config_file_name); } config_path } + + /// Get the Directory for the config file + /// Read the env variable `CONFIG_DIR` or fallback to `config` + pub fn get_config_directory() -> PathBuf { + let mut config_path = PathBuf::new(); + + let config_directory = + std::env::var(crate::env::vars::CONFIG_DIR).unwrap_or_else(|_| "config".into()); + + config_path.push(crate::env::workspace_path()); + config_path.push(config_directory); + config_path + } }