diff --git a/api-reference-v2/openapi_spec.json b/api-reference-v2/openapi_spec.json index 388ccb79a660..44ac1d3e08dc 100644 --- a/api-reference-v2/openapi_spec.json +++ b/api-reference-v2/openapi_spec.json @@ -5592,6 +5592,11 @@ "type": "object", "description": "This field contains the Samsung Pay certificates and credentials", "nullable": true + }, + "paze": { + "type": "object", + "description": "This field contains the Paze certificates and credentials", + "nullable": true } }, "additionalProperties": false @@ -12548,6 +12553,7 @@ "open_banking_uk", "pay_bright", "paypal", + "paze", "pix", "pay_safe_card", "przelewy24", @@ -17138,6 +17144,39 @@ } } }, + "PazeSessionTokenResponse": { + "type": "object", + "required": [ + "client_id", + "client_name", + "client_profile_id" + ], + "properties": { + "client_id": { + "type": "string", + "description": "Paze Client ID" + }, + "client_name": { + "type": "string", + "description": "Client Name to be displayed on the Paze screen" + }, + "client_profile_id": { + "type": "string", + "description": "Paze Client Profile ID" + } + } + }, + "PazeWalletData": { + "type": "object", + "required": [ + "complete_response" + ], + "properties": { + "complete_response": { + "type": "string" + } + } + }, "PhoneDetails": { "type": "object", "properties": { @@ -19377,6 +19416,27 @@ } ] }, + { + "allOf": [ + { + "$ref": "#/components/schemas/PazeSessionTokenResponse" + }, + { + "type": "object", + "required": [ + "wallet_name" + ], + "properties": { + "wallet_name": { + "type": "string", + "enum": [ + "paze" + ] + } + } + } + ] + }, { "type": "object", "required": [ @@ -20551,6 +20611,17 @@ } } }, + { + "type": "object", + "required": [ + "paze" + ], + "properties": { + "paze": { + "$ref": "#/components/schemas/PazeWalletData" + } + } + }, { "type": "object", "required": [ diff --git a/api-reference/openapi_spec.json b/api-reference/openapi_spec.json index d0e6c6ad0aaa..90239bb8a0a2 100644 --- a/api-reference/openapi_spec.json +++ b/api-reference/openapi_spec.json @@ -8884,6 +8884,11 @@ "type": "object", "description": "This field contains the Samsung Pay certificates and credentials", "nullable": true + }, + "paze": { + "type": "object", + "description": "This field contains the Paze certificates and credentials", + "nullable": true } }, "additionalProperties": false @@ -16185,6 +16190,7 @@ "open_banking_uk", "pay_bright", "paypal", + "paze", "pix", "pay_safe_card", "przelewy24", @@ -20883,6 +20889,39 @@ } } }, + "PazeSessionTokenResponse": { + "type": "object", + "required": [ + "client_id", + "client_name", + "client_profile_id" + ], + "properties": { + "client_id": { + "type": "string", + "description": "Paze Client ID" + }, + "client_name": { + "type": "string", + "description": "Client Name to be displayed on the Paze screen" + }, + "client_profile_id": { + "type": "string", + "description": "Paze Client Profile ID" + } + } + }, + "PazeWalletData": { + "type": "object", + "required": [ + "complete_response" + ], + "properties": { + "complete_response": { + "type": "string" + } + } + }, "PhoneDetails": { "type": "object", "properties": { @@ -23139,6 +23178,27 @@ } ] }, + { + "allOf": [ + { + "$ref": "#/components/schemas/PazeSessionTokenResponse" + }, + { + "type": "object", + "required": [ + "wallet_name" + ], + "properties": { + "wallet_name": { + "type": "string", + "enum": [ + "paze" + ] + } + } + } + ] + }, { "type": "object", "required": [ @@ -24395,6 +24455,17 @@ } } }, + { + "type": "object", + "required": [ + "paze" + ], + "properties": { + "paze": { + "$ref": "#/components/schemas/PazeWalletData" + } + } + }, { "type": "object", "required": [ diff --git a/config/config.example.toml b/config/config.example.toml index 54f0d1a27a47..c0358d91a26c 100644 --- a/config/config.example.toml +++ b/config/config.example.toml @@ -540,6 +540,7 @@ debit = { currency = "USD,GBP,EUR" } apple_pay = { currency = "USD,GBP,EUR" } google_pay = { currency = "USD,GBP,EUR" } samsung_pay = { currency = "USD,GBP,EUR" } +paze = { currency = "USD" } [pm_filters.stax] credit = { currency = "USD" } @@ -581,6 +582,10 @@ apple_pay_ppc_key = "APPLE_PAY_PAYMENT_PROCESSING_CERTIFICATE_KEY" # Private key apple_pay_merchant_cert = "APPLE_PAY_MERCHNAT_CERTIFICATE" # Merchant Certificate provided by Apple Pay (https://developer.apple.com/) Certificates, Identifiers & Profiles > Apple Pay Merchant Identity Certificate apple_pay_merchant_cert_key = "APPLE_PAY_MERCHNAT_CERTIFICATE_KEY" # Private key generated by RSA:2048 algorithm. Refer Hyperswitch Docs (https://docs.hyperswitch.io/hyperswitch-cloud/payment-methods-setup/wallets/apple-pay/ios-application/) to generate the private key +[paze_decrypt_keys] +paze_private_key = "PAZE_PRIVATE_KEY" # Base 64 Encoded Private Key File cakey.pem generated for Paze -> Command to create private key: openssl req -newkey rsa:2048 -x509 -keyout cakey.pem -out cacert.pem -days 365 +paze_private_key_passphrase = "PAZE_PRIVATE_KEY_PASSPHRASE" # PEM Passphrase used for generating Private Key File cakey.pem + [applepay_merchant_configs] # Run below command to get common merchant identifier for applepay in shell # diff --git a/config/deployments/env_specific.toml b/config/deployments/env_specific.toml index db43cac979b7..5dce5be9c960 100644 --- a/config/deployments/env_specific.toml +++ b/config/deployments/env_specific.toml @@ -29,6 +29,10 @@ apple_pay_ppc_key = "APPLE_PAY_PAYMENT_PROCESSING_CERTIFICATE_KEY" # Private key apple_pay_merchant_cert = "APPLE_PAY_MERCHNAT_CERTIFICATE" # Merchant Certificate provided by Apple Pay (https://developer.apple.com/) Certificates, Identifiers & Profiles > Apple Pay Merchant Identity Certificate apple_pay_merchant_cert_key = "APPLE_PAY_MERCHNAT_CERTIFICATE_KEY" # Private key generated by RSA:2048 algorithm. Refer Hyperswitch Docs (https://docs.hyperswitch.io/hyperswitch-cloud/payment-methods-setup/wallets/apple-pay/ios-application/) to generate the private key +[paze_decrypt_keys] +paze_private_key = "PAZE_PRIVATE_KEY" # Base 64 Encoded Private Key File cakey.pem generated for Paze -> Command to create private key: openssl req -newkey rsa:2048 -x509 -keyout cakey.pem -out cacert.pem -days 365 +paze_private_key_passphrase = "PAZE_PRIVATE_KEY_PASSPHRASE" # PEM Passphrase used for generating Private Key File cakey.pem + [applepay_merchant_configs] common_merchant_identifier = "APPLE_PAY_COMMON_MERCHANT_IDENTIFIER" # Refer to config.example.toml to learn how you can generate this value merchant_cert = "APPLE_PAY_MERCHANT_CERTIFICATE" # Merchant Certificate provided by Apple Pay (https://developer.apple.com/) Certificates, Identifiers & Profiles > Apple Pay Merchant Identity Certificate diff --git a/config/deployments/integration_test.toml b/config/deployments/integration_test.toml index dbb4161ec5d8..4f742a61698b 100644 --- a/config/deployments/integration_test.toml +++ b/config/deployments/integration_test.toml @@ -307,6 +307,7 @@ debit = { currency = "USD,GBP,EUR" } apple_pay = { currency = "USD,GBP,EUR" } google_pay = { currency = "USD,GBP,EUR" } samsung_pay = { currency = "USD,GBP,EUR" } +paze = { currency = "USD" } [pm_filters.nexixpay] credit = { country = "AT,BE,CY,EE,FI,FR,DE,GR,IE,IT,LV,LT,LU,MT,NL,PT,SK,SI,ES,BG,HR,DK,GB,NO,PL,CZ,RO,SE,CH,HU", currency = "ARS,AUD,BHD,CAD,CLP,CNY,COP,HRK,CZK,DKK,HKD,HUF,INR,JPY,KZT,JOD,KRW,KWD,MYR,MXN,NGN,NOK,PHP,QAR,RUB,SAR,SGD,VND,ZAR,SEK,CHF,THB,AED,EGP,GBP,USD,TWD,BYN,RSD,AZN,RON,TRY,AOA,BGN,EUR,UAH,PLN,BRL" } diff --git a/config/deployments/production.toml b/config/deployments/production.toml index c100ccf46de6..c25b70d6ba08 100644 --- a/config/deployments/production.toml +++ b/config/deployments/production.toml @@ -281,6 +281,7 @@ debit = { currency = "USD,GBP,EUR" } apple_pay = { currency = "USD,GBP,EUR" } google_pay = { currency = "USD,GBP,EUR" } samsung_pay = { currency = "USD,GBP,EUR" } +paze = { currency = "USD" } [pm_filters.nexixpay] credit = { country = "AT,BE,CY,EE,FI,FR,DE,GR,IE,IT,LV,LT,LU,MT,NL,PT,SK,SI,ES,BG,HR,DK,GB,NO,PL,CZ,RO,SE,CH,HU", currency = "ARS,AUD,BHD,CAD,CLP,CNY,COP,HRK,CZK,DKK,HKD,HUF,INR,JPY,KZT,JOD,KRW,KWD,MYR,MXN,NGN,NOK,PHP,QAR,RUB,SAR,SGD,VND,ZAR,SEK,CHF,THB,AED,EGP,GBP,USD,TWD,BYN,RSD,AZN,RON,TRY,AOA,BGN,EUR,UAH,PLN,BRL" } diff --git a/config/deployments/sandbox.toml b/config/deployments/sandbox.toml index 89aea2827647..28f5a4e05759 100644 --- a/config/deployments/sandbox.toml +++ b/config/deployments/sandbox.toml @@ -284,6 +284,7 @@ debit = { currency = "USD,GBP,EUR" } apple_pay = { currency = "USD,GBP,EUR" } google_pay = { currency = "USD,GBP,EUR" } samsung_pay = { currency = "USD,GBP,EUR" } +paze = { currency = "USD" } [pm_filters.nexixpay] credit = { country = "AT,BE,CY,EE,FI,FR,DE,GR,IE,IT,LV,LT,LU,MT,NL,PT,SK,SI,ES,BG,HR,DK,GB,NO,PL,CZ,RO,SE,CH,HU", currency = "ARS,AUD,BHD,CAD,CLP,CNY,COP,HRK,CZK,DKK,HKD,HUF,INR,JPY,KZT,JOD,KRW,KWD,MYR,MXN,NGN,NOK,PHP,QAR,RUB,SAR,SGD,VND,ZAR,SEK,CHF,THB,AED,EGP,GBP,USD,TWD,BYN,RSD,AZN,RON,TRY,AOA,BGN,EUR,UAH,PLN,BRL" } diff --git a/config/development.toml b/config/development.toml index f0e261725145..0153c6ef102d 100644 --- a/config/development.toml +++ b/config/development.toml @@ -453,6 +453,7 @@ debit = { currency = "USD,GBP,EUR" } apple_pay = { currency = "USD,GBP,EUR" } google_pay = { currency = "USD,GBP,EUR" } samsung_pay = { currency = "USD,GBP,EUR" } +paze = { currency = "USD" } [pm_filters.nexixpay] credit = { country = "AT,BE,CY,EE,FI,FR,DE,GR,IE,IT,LV,LT,LU,MT,NL,PT,SK,SI,ES,BG,HR,DK,GB,NO,PL,CZ,RO,SE,CH,HU", 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" } @@ -617,6 +618,10 @@ apple_pay_ppc_key = "APPLE_PAY_PAYMENT_PROCESSING_CERTIFICATE_KEY" apple_pay_merchant_cert = "APPLE_PAY_MERCHNAT_CERTIFICATE" apple_pay_merchant_cert_key = "APPLE_PAY_MERCHNAT_CERTIFICATE_KEY" +[paze_decrypt_keys] +paze_private_key = "PAZE_PRIVATE_KEY" +paze_private_key_passphrase = "PAZE_PRIVATE_KEY_PASSPHRASE" + [generic_link] [generic_link.payment_method_collect] sdk_url = "http://localhost:9050/HyperLoader.js" diff --git a/config/docker_compose.toml b/config/docker_compose.toml index 1b9ef294dc09..5ffe5df138ff 100644 --- a/config/docker_compose.toml +++ b/config/docker_compose.toml @@ -420,6 +420,7 @@ debit = { currency = "USD,GBP,EUR" } apple_pay = { currency = "USD,GBP,EUR" } google_pay = { currency = "USD,GBP,EUR" } samsung_pay = { currency = "USD,GBP,EUR" } +paze = { currency = "USD" } [pm_filters.nexixpay] credit = { country = "AT,BE,CY,EE,FI,FR,DE,GR,IE,IT,LV,LT,LU,MT,NL,PT,SK,SI,ES,BG,HR,DK,GB,NO,PL,CZ,RO,SE,CH,HU", currency = "ARS,AUD,BHD,CAD,CLP,CNY,COP,HRK,CZK,DKK,HKD,HUF,INR,JPY,KZT,JOD,KRW,KWD,MYR,MXN,NGN,NOK,PHP,QAR,RUB,SAR,SGD,VND,ZAR,SEK,CHF,THB,AED,EGP,GBP,USD,TWD,BYN,RSD,AZN,RON,TRY,AOA,BGN,EUR,UAH,PLN,BRL" } diff --git a/crates/api_models/src/admin.rs b/crates/api_models/src/admin.rs index 6e7f4f29d036..8f24bdf65bc5 100644 --- a/crates/api_models/src/admin.rs +++ b/crates/api_models/src/admin.rs @@ -1558,6 +1558,10 @@ pub struct ConnectorWalletDetails { #[serde(skip_serializing_if = "Option::is_none")] #[schema(value_type = Option)] pub samsung_pay: Option, + /// This field contains the Paze certificates and credentials + #[serde(skip_serializing_if = "Option::is_none")] + #[schema(value_type = Option)] + pub paze: Option, } /// Create a new Merchant Connector for the merchant account. The connector could be a payment processor / facilitator / acquirer or specialized services like Fraud / Accounting etc." diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs index 9cafc37af540..a758d4578582 100644 --- a/crates/api_models/src/payments.rs +++ b/crates/api_models/src/payments.rs @@ -1930,6 +1930,7 @@ impl GetPaymentMethodType for WalletData { Self::MbWayRedirect(_) => api_enums::PaymentMethodType::MbWay, Self::MobilePayRedirect(_) => api_enums::PaymentMethodType::MobilePay, Self::PaypalRedirect(_) | Self::PaypalSdk(_) => api_enums::PaymentMethodType::Paypal, + Self::Paze(_) => api_enums::PaymentMethodType::Paze, Self::SamsungPay(_) => api_enums::PaymentMethodType::SamsungPay, Self::TwintRedirect {} => api_enums::PaymentMethodType::Twint, Self::VippsRedirect {} => api_enums::PaymentMethodType::Vipps, @@ -2819,6 +2820,8 @@ pub enum WalletData { PaypalRedirect(PaypalRedirection), /// The wallet data for Paypal PaypalSdk(PayPalWalletData), + /// The wallet data for Paze + Paze(PazeWalletData), /// The wallet data for Samsung Pay SamsungPay(Box), /// Wallet data for Twint Redirection @@ -2879,6 +2882,7 @@ impl GetAddressFromPaymentMethodData for WalletData { | Self::GooglePayRedirect(_) | Self::GooglePayThirdPartySdk(_) | Self::PaypalSdk(_) + | Self::Paze(_) | Self::SamsungPay(_) | Self::TwintRedirect {} | Self::VippsRedirect {} @@ -2891,6 +2895,13 @@ impl GetAddressFromPaymentMethodData for WalletData { } } +#[derive(Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)] +#[serde(rename_all = "snake_case")] +pub struct PazeWalletData { + #[schema(value_type = String)] + pub complete_response: Secret, +} + #[derive(Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)] #[serde(rename_all = "snake_case")] pub struct SamsungPayWalletData { @@ -4932,6 +4943,19 @@ pub struct GpaySessionTokenData { pub data: GpayMetaData, } +#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] +pub struct PazeSessionTokenData { + #[serde(rename = "paze")] + pub data: PazeMetadata, +} + +#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] +pub struct PazeMetadata { + pub client_id: String, + pub client_name: String, + pub client_profile_id: String, +} + #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] #[serde(rename_all = "snake_case")] pub enum SamsungPayCombinedMetadata { @@ -5138,10 +5162,23 @@ pub enum SessionToken { ApplePay(Box), /// Session token for OpenBanking PIS flow OpenBanking(OpenBankingSessionToken), + /// The session response structure for Paze + Paze(Box), /// Whenever there is no session token response or an error in session response NoSessionTokenReceived, } +#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, ToSchema)] +#[serde(rename_all = "lowercase")] +pub struct PazeSessionTokenResponse { + /// Paze Client ID + pub client_id: String, + /// Client Name to be displayed on the Paze screen + pub client_name: String, + /// Paze Client Profile ID + pub client_profile_id: String, +} + #[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, ToSchema)] #[serde(untagged)] pub enum GpaySessionTokenResponse { diff --git a/crates/common_enums/src/enums.rs b/crates/common_enums/src/enums.rs index 528f38ac61ae..5ab05c9a6884 100644 --- a/crates/common_enums/src/enums.rs +++ b/crates/common_enums/src/enums.rs @@ -1593,6 +1593,7 @@ pub enum PaymentMethodType { OpenBankingUk, PayBright, Paypal, + Paze, Pix, PaySafeCard, Przelewy24, diff --git a/crates/common_enums/src/transformers.rs b/crates/common_enums/src/transformers.rs index db4162a8bb18..4fba749ef637 100644 --- a/crates/common_enums/src/transformers.rs +++ b/crates/common_enums/src/transformers.rs @@ -1843,6 +1843,7 @@ impl From for PaymentMethod { PaymentMethodType::OnlineBankingThailand => Self::BankRedirect, PaymentMethodType::OnlineBankingPoland => Self::BankRedirect, PaymentMethodType::OnlineBankingSlovakia => Self::BankRedirect, + PaymentMethodType::Paze => Self::Wallet, PaymentMethodType::PermataBankTransfer => Self::BankTransfer, PaymentMethodType::Pix => Self::BankTransfer, PaymentMethodType::Pse => Self::BankTransfer, diff --git a/crates/connector_configs/src/transformer.rs b/crates/connector_configs/src/transformer.rs index 68ade2909b46..88997691eb61 100644 --- a/crates/connector_configs/src/transformer.rs +++ b/crates/connector_configs/src/transformer.rs @@ -56,7 +56,10 @@ impl DashboardRequestPayload { | (Connector::Stripe, WeChatPay) => { Some(api_models::enums::PaymentExperience::DisplayQrCode) } - (_, GooglePay) | (_, ApplePay) | (_, PaymentMethodType::SamsungPay) => { + (_, GooglePay) + | (_, ApplePay) + | (_, PaymentMethodType::SamsungPay) + | (_, PaymentMethodType::Paze) => { Some(api_models::enums::PaymentExperience::InvokeSdkClient) } _ => Some(api_models::enums::PaymentExperience::RedirectToUrl), diff --git a/crates/euclid/src/frontend/dir/enums.rs b/crates/euclid/src/frontend/dir/enums.rs index 0d2f959c702c..136cdf4d9817 100644 --- a/crates/euclid/src/frontend/dir/enums.rs +++ b/crates/euclid/src/frontend/dir/enums.rs @@ -91,6 +91,7 @@ pub enum WalletType { Cashapp, Venmo, Mifinity, + Paze, } #[derive( diff --git a/crates/euclid/src/frontend/dir/lowering.rs b/crates/euclid/src/frontend/dir/lowering.rs index 33d368e96961..da589ec3748e 100644 --- a/crates/euclid/src/frontend/dir/lowering.rs +++ b/crates/euclid/src/frontend/dir/lowering.rs @@ -58,6 +58,7 @@ impl From for global_enums::PaymentMethodType { enums::WalletType::Cashapp => Self::Cashapp, enums::WalletType::Venmo => Self::Venmo, enums::WalletType::Mifinity => Self::Mifinity, + enums::WalletType::Paze => Self::Paze, } } } diff --git a/crates/euclid/src/frontend/dir/transformers.rs b/crates/euclid/src/frontend/dir/transformers.rs index 3e35bcd391c4..de0b619b1203 100644 --- a/crates/euclid/src/frontend/dir/transformers.rs +++ b/crates/euclid/src/frontend/dir/transformers.rs @@ -188,6 +188,7 @@ impl IntoDirValue for (global_enums::PaymentMethodType, global_enums::PaymentMet global_enums::PaymentMethodType::OpenBankingPIS => { Ok(dirval!(OpenBankingType = OpenBankingPIS)) } + global_enums::PaymentMethodType::Paze => Ok(dirval!(WalletType = Paze)), } } } diff --git a/crates/hyperswitch_connectors/src/connectors/fiuu/transformers.rs b/crates/hyperswitch_connectors/src/connectors/fiuu/transformers.rs index eab8d878f055..c4ca017cec7c 100644 --- a/crates/hyperswitch_connectors/src/connectors/fiuu/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/fiuu/transformers.rs @@ -366,6 +366,9 @@ impl TryFrom<&FiuuRouterData<&PaymentsAuthorizeRouterData>> for FiuuPaymentReque PaymentMethodToken::ApplePayDecrypt(decrypt_data) => { FiuuPaymentMethodData::try_from(decrypt_data) } + PaymentMethodToken::PazeDecrypt(_) => { + Err(unimplemented_payment_method!("Paze", "Fiuu"))? + } } } WalletData::AliPayQr(_) @@ -384,6 +387,7 @@ impl TryFrom<&FiuuRouterData<&PaymentsAuthorizeRouterData>> for FiuuPaymentReque | WalletData::MobilePayRedirect(_) | WalletData::PaypalRedirect(_) | WalletData::PaypalSdk(_) + | WalletData::Paze(_) | WalletData::SamsungPay(_) | WalletData::TwintRedirect {} | WalletData::VippsRedirect {} diff --git a/crates/hyperswitch_connectors/src/connectors/globepay/transformers.rs b/crates/hyperswitch_connectors/src/connectors/globepay/transformers.rs index 4986e8d5f32e..772f2af209e0 100644 --- a/crates/hyperswitch_connectors/src/connectors/globepay/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/globepay/transformers.rs @@ -74,6 +74,7 @@ impl TryFrom<&GlobepayRouterData<&types::PaymentsAuthorizeRouterData>> for Globe | WalletData::MobilePayRedirect(_) | WalletData::PaypalRedirect(_) | WalletData::PaypalSdk(_) + | WalletData::Paze(_) | WalletData::SamsungPay(_) | WalletData::TwintRedirect {} | WalletData::VippsRedirect {} diff --git a/crates/hyperswitch_connectors/src/connectors/mollie/transformers.rs b/crates/hyperswitch_connectors/src/connectors/mollie/transformers.rs index d05259216321..a12434a460a7 100644 --- a/crates/hyperswitch_connectors/src/connectors/mollie/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/mollie/transformers.rs @@ -182,6 +182,9 @@ impl TryFrom<&MollieRouterData<&types::PaymentsAuthorizeRouterData>> for MollieP "Mollie" ))? } + PaymentMethodToken::PazeDecrypt(_) => { + Err(unimplemented_payment_method!("Paze", "Mollie"))? + } }), }, ))) diff --git a/crates/hyperswitch_connectors/src/connectors/square/transformers.rs b/crates/hyperswitch_connectors/src/connectors/square/transformers.rs index 4e2b30a574b3..ad09e7445d4f 100644 --- a/crates/hyperswitch_connectors/src/connectors/square/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/square/transformers.rs @@ -119,6 +119,7 @@ impl TryFrom<(&types::TokenizationRouterData, WalletData)> for SquareTokenReques | WalletData::MobilePayRedirect(_) | WalletData::PaypalRedirect(_) | WalletData::PaypalSdk(_) + | WalletData::Paze(_) | WalletData::SamsungPay(_) | WalletData::TwintRedirect {} | WalletData::VippsRedirect {} @@ -263,6 +264,9 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for SquarePaymentsRequest { PaymentMethodToken::ApplePayDecrypt(_) => Err( unimplemented_payment_method!("Apple Pay", "Simplified", "Square"), )?, + PaymentMethodToken::PazeDecrypt(_) => { + Err(unimplemented_payment_method!("Paze", "Square"))? + } }, amount_money: SquarePaymentsAmountData { amount: item.request.amount, diff --git a/crates/hyperswitch_connectors/src/connectors/stax/transformers.rs b/crates/hyperswitch_connectors/src/connectors/stax/transformers.rs index f7b2016a3705..686178e9621e 100644 --- a/crates/hyperswitch_connectors/src/connectors/stax/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/stax/transformers.rs @@ -82,6 +82,9 @@ impl TryFrom<&StaxRouterData<&types::PaymentsAuthorizeRouterData>> for StaxPayme PaymentMethodToken::ApplePayDecrypt(_) => Err( unimplemented_payment_method!("Apple Pay", "Simplified", "Stax"), )?, + PaymentMethodToken::PazeDecrypt(_) => { + Err(unimplemented_payment_method!("Paze", "Stax"))? + } }, idempotency_id: Some(item.router_data.connector_request_reference_id.clone()), }) @@ -99,6 +102,9 @@ impl TryFrom<&StaxRouterData<&types::PaymentsAuthorizeRouterData>> for StaxPayme PaymentMethodToken::ApplePayDecrypt(_) => Err( unimplemented_payment_method!("Apple Pay", "Simplified", "Stax"), )?, + PaymentMethodToken::PazeDecrypt(_) => { + Err(unimplemented_payment_method!("Paze", "Stax"))? + } }, idempotency_id: Some(item.router_data.connector_request_reference_id.clone()), }) diff --git a/crates/hyperswitch_connectors/src/utils.rs b/crates/hyperswitch_connectors/src/utils.rs index 4c7c9adaf8ee..66b8081b0f2f 100644 --- a/crates/hyperswitch_connectors/src/utils.rs +++ b/crates/hyperswitch_connectors/src/utils.rs @@ -1781,6 +1781,7 @@ pub enum PaymentMethodDataType { MobilePayRedirect, PaypalRedirect, PaypalSdk, + Paze, SamsungPay, TwintRedirect, VippsRedirect, @@ -1898,6 +1899,7 @@ impl From for PaymentMethodDataType { hyperswitch_domain_models::payment_method_data::WalletData::MobilePayRedirect(_) => Self::MobilePayRedirect, hyperswitch_domain_models::payment_method_data::WalletData::PaypalRedirect(_) => Self::PaypalRedirect, hyperswitch_domain_models::payment_method_data::WalletData::PaypalSdk(_) => Self::PaypalSdk, + hyperswitch_domain_models::payment_method_data::WalletData::Paze(_) => Self::Paze, hyperswitch_domain_models::payment_method_data::WalletData::SamsungPay(_) => Self::SamsungPay, hyperswitch_domain_models::payment_method_data::WalletData::TwintRedirect {} => Self::TwintRedirect, hyperswitch_domain_models::payment_method_data::WalletData::VippsRedirect {} => Self::VippsRedirect, diff --git a/crates/hyperswitch_domain_models/src/payment_method_data.rs b/crates/hyperswitch_domain_models/src/payment_method_data.rs index 9f505f267120..3ccfabf021cd 100644 --- a/crates/hyperswitch_domain_models/src/payment_method_data.rs +++ b/crates/hyperswitch_domain_models/src/payment_method_data.rs @@ -117,6 +117,7 @@ pub enum WalletData { MobilePayRedirect(Box), PaypalRedirect(PaypalRedirection), PaypalSdk(PayPalWalletData), + Paze(PazeWalletData), SamsungPay(Box), TwintRedirect {}, VippsRedirect {}, @@ -134,6 +135,12 @@ pub struct MifinityData { pub language_preference: Option, } +#[derive(Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize)] +#[serde(rename_all = "snake_case")] +pub struct PazeWalletData { + pub complete_response: Secret, +} + #[derive(Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize)] #[serde(rename_all = "snake_case")] pub struct SamsungPayWalletData { @@ -689,6 +696,9 @@ impl From for WalletData { token: paypal_sdk_data.token, }) } + api_models::payments::WalletData::Paze(paze_data) => { + Self::Paze(PazeWalletData::from(paze_data)) + } api_models::payments::WalletData::SamsungPay(samsung_pay_data) => { Self::SamsungPay(Box::new(SamsungPayWalletData::from(samsung_pay_data))) } @@ -754,6 +764,14 @@ impl From for ApplePayWalletData { } } +impl From for PazeWalletData { + fn from(value: api_models::payments::PazeWalletData) -> Self { + Self { + complete_response: value.complete_response, + } + } +} + impl From> for SamsungPayWalletData { fn from(value: Box) -> Self { Self { @@ -1388,6 +1406,7 @@ impl GetPaymentMethodType for WalletData { Self::MbWayRedirect(_) => api_enums::PaymentMethodType::MbWay, Self::MobilePayRedirect(_) => api_enums::PaymentMethodType::MobilePay, Self::PaypalRedirect(_) | Self::PaypalSdk(_) => api_enums::PaymentMethodType::Paypal, + Self::Paze(_) => api_enums::PaymentMethodType::Paze, Self::SamsungPay(_) => api_enums::PaymentMethodType::SamsungPay, Self::TwintRedirect {} => api_enums::PaymentMethodType::Twint, Self::VippsRedirect {} => api_enums::PaymentMethodType::Vipps, diff --git a/crates/hyperswitch_domain_models/src/router_data.rs b/crates/hyperswitch_domain_models/src/router_data.rs index cd8ac85594e7..b41b42eaa2d2 100644 --- a/crates/hyperswitch_domain_models/src/router_data.rs +++ b/crates/hyperswitch_domain_models/src/router_data.rs @@ -220,6 +220,7 @@ pub struct AccessToken { pub enum PaymentMethodToken { Token(Secret), ApplePayDecrypt(Box), + PazeDecrypt(Box), } #[derive(Debug, Clone, serde::Deserialize)] @@ -241,6 +242,69 @@ pub struct ApplePayCryptogramData { pub eci_indicator: Option, } +#[derive(Debug, Clone, serde::Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PazeDecryptedData { + pub client_id: Secret, + pub profile_id: String, + pub token: PazeToken, + pub payment_card_network: common_enums::enums::CardNetwork, + pub dynamic_data: Vec, + pub billing_address: PazeAddress, + pub consumer: PazeConsumer, + pub eci: Option, +} + +#[derive(Debug, Clone, serde::Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PazeToken { + pub payment_token: cards::CardNumber, + pub token_expiration_month: Secret, + pub token_expiration_year: Secret, + pub payment_account_reference: Secret, +} + +#[derive(Debug, Clone, serde::Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PazeDynamicData { + pub dynamic_data_value: Option>, + pub dynamic_data_type: Option, + pub dynamic_data_expiration: Option, +} + +#[derive(Debug, Clone, serde::Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PazeAddress { + pub name: Option>, + pub line1: Option>, + pub line2: Option>, + pub line3: Option>, + pub city: Option>, + pub state: Option>, + pub zip: Option>, + pub country_code: Option, +} + +#[derive(Debug, Clone, serde::Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PazeConsumer { + // This is consumer data not customer data. + pub first_name: Option>, + pub last_name: Option>, + pub full_name: Secret, + pub email_address: common_utils::pii::Email, + pub mobile_number: Option, + pub country_code: Option, + pub language_code: Option, +} + +#[derive(Debug, Clone, serde::Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct PazePhoneNumber { + pub country_code: Secret, + pub phone_number: Secret, +} + #[derive(Debug, Default, Clone)] pub struct RecurringMandatePaymentData { pub payment_method_type: Option, //required for making recurring payment using saved payment method through stripe diff --git a/crates/kgraph_utils/src/mca.rs b/crates/kgraph_utils/src/mca.rs index 2ec0cbe8031b..e897292d6ff1 100644 --- a/crates/kgraph_utils/src/mca.rs +++ b/crates/kgraph_utils/src/mca.rs @@ -146,6 +146,7 @@ fn get_dir_value_payment_method( api_enums::PaymentMethodType::OpenBankingPIS => { Ok(dirval!(OpenBankingType = OpenBankingPIS)) } + api_enums::PaymentMethodType::Paze => Ok(dirval!(WalletType = Paze)), } } diff --git a/crates/kgraph_utils/src/transformers.rs b/crates/kgraph_utils/src/transformers.rs index 758a0dd3de03..1a340aa91d31 100644 --- a/crates/kgraph_utils/src/transformers.rs +++ b/crates/kgraph_utils/src/transformers.rs @@ -307,6 +307,7 @@ impl IntoDirValue for (api_enums::PaymentMethodType, api_enums::PaymentMethod) { api_enums::PaymentMethodType::OpenBankingPIS => { Ok(dirval!(OpenBankingType = OpenBankingPIS)) } + api_enums::PaymentMethodType::Paze => Ok(dirval!(WalletType = Paze)), } } } diff --git a/crates/openapi/src/openapi.rs b/crates/openapi/src/openapi.rs index a76726eb8ac7..24fbadc0a596 100644 --- a/crates/openapi/src/openapi.rs +++ b/crates/openapi/src/openapi.rs @@ -389,6 +389,7 @@ Never share your secret api keys. Keep them guarded and secure. api_models::payments::PaymentsCaptureRequest, api_models::payments::PaymentsSessionRequest, api_models::payments::PaymentsSessionResponse, + api_models::payments::PazeWalletData, api_models::payments::SessionToken, api_models::payments::ApplePaySessionResponse, api_models::payments::ThirdPartySdkSessionResponse, @@ -445,6 +446,7 @@ Never share your secret api keys. Keep them guarded and secure. api_models::payments::GooglePayRedirectData, api_models::payments::GooglePayThirdPartySdk, api_models::payments::GooglePaySessionResponse, + api_models::payments::PazeSessionTokenResponse, api_models::payments::SamsungPaySessionTokenResponse, api_models::payments::SamsungPayMerchantPaymentInformation, api_models::payments::SamsungPayAmountDetails, diff --git a/crates/openapi/src/openapi_v2.rs b/crates/openapi/src/openapi_v2.rs index 05a2c72ba941..bc44068030b4 100644 --- a/crates/openapi/src/openapi_v2.rs +++ b/crates/openapi/src/openapi_v2.rs @@ -323,6 +323,7 @@ Never share your secret api keys. Keep them guarded and secure. api_models::payments::PaymentsSessionResponse, api_models::payments::PaymentsCreateIntentRequest, api_models::payments::PaymentsCreateIntentResponse, + api_models::payments::PazeWalletData, api_models::payments::AmountDetails, api_models::payments::SessionToken, api_models::payments::ApplePaySessionResponse, @@ -358,6 +359,7 @@ Never share your secret api keys. Keep them guarded and secure. api_models::payments::GooglePayPaymentMethodInfo, api_models::payments::ApplePayWalletData, api_models::payments::ApplepayPaymentMethod, + api_models::payments::PazeSessionTokenResponse, api_models::payments::SamsungPaySessionTokenResponse, api_models::payments::SamsungPayMerchantPaymentInformation, api_models::payments::SamsungPayAmountDetails, diff --git a/crates/router/src/configs/secrets_transformers.rs b/crates/router/src/configs/secrets_transformers.rs index 0f25477802ce..dbdba189ed19 100644 --- a/crates/router/src/configs/secrets_transformers.rs +++ b/crates/router/src/configs/secrets_transformers.rs @@ -178,6 +178,27 @@ impl SecretsHandler for settings::ApplePayDecryptConfig { } } +#[async_trait::async_trait] +impl SecretsHandler for settings::PazeDecryptConfig { + async fn convert_to_raw_secret( + value: SecretStateContainer, + secret_management_client: &dyn SecretManagementInterface, + ) -> CustomResult, SecretsManagementError> { + let paze_decrypt_keys = value.get_inner(); + + let (paze_private_key, paze_private_key_passphrase) = tokio::try_join!( + secret_management_client.get_secret(paze_decrypt_keys.paze_private_key.clone()), + secret_management_client + .get_secret(paze_decrypt_keys.paze_private_key_passphrase.clone()), + )?; + + Ok(value.transition_state(|_| Self { + paze_private_key, + paze_private_key_passphrase, + })) + } +} + #[async_trait::async_trait] impl SecretsHandler for settings::ApplepayMerchantConfigs { async fn convert_to_raw_secret( @@ -388,6 +409,17 @@ pub(crate) async fn fetch_raw_secrets( .await .expect("Failed to decrypt applepay decrypt configs"); + #[allow(clippy::expect_used)] + let paze_decrypt_keys = if let Some(paze_keys) = conf.paze_decrypt_keys { + Some( + settings::PazeDecryptConfig::convert_to_raw_secret(paze_keys, secret_management_client) + .await + .expect("Failed to decrypt paze decrypt configs"), + ) + } else { + None + }; + #[allow(clippy::expect_used)] let applepay_merchant_configs = settings::ApplepayMerchantConfigs::convert_to_raw_secret( conf.applepay_merchant_configs, @@ -479,6 +511,7 @@ pub(crate) async fn fetch_raw_secrets( #[cfg(feature = "payouts")] payouts: conf.payouts, applepay_decrypt_keys, + paze_decrypt_keys, multiple_api_version_supported_connectors: conf.multiple_api_version_supported_connectors, applepay_merchant_configs, lock_settings: conf.lock_settings, diff --git a/crates/router/src/configs/settings.rs b/crates/router/src/configs/settings.rs index 1124423714bf..149ee2b84562 100644 --- a/crates/router/src/configs/settings.rs +++ b/crates/router/src/configs/settings.rs @@ -96,6 +96,7 @@ pub struct Settings { pub payouts: Payouts, pub payout_method_filters: ConnectorFilters, pub applepay_decrypt_keys: SecretStateContainer, + pub paze_decrypt_keys: Option>, pub multiple_api_version_supported_connectors: MultipleApiVersionSupportedConnectors, pub applepay_merchant_configs: SecretStateContainer, pub lock_settings: LockSettings, @@ -723,6 +724,12 @@ pub struct ApplePayDecryptConfig { pub apple_pay_merchant_cert_key: Secret, } +#[derive(Debug, Deserialize, Clone, Default)] +pub struct PazeDecryptConfig { + pub paze_private_key: Secret, + pub paze_private_key_passphrase: Secret, +} + #[derive(Debug, Deserialize, Clone, Default)] #[serde(default)] pub struct LockerBasedRecipientConnectorList { @@ -864,6 +871,11 @@ impl Settings { .map(|x| x.get_inner().validate()) .transpose()?; + self.paze_decrypt_keys + .as_ref() + .map(|x| x.get_inner().validate()) + .transpose()?; + self.key_manager.get_inner().validate()?; Ok(()) diff --git a/crates/router/src/configs/validations.rs b/crates/router/src/configs/validations.rs index f109fe3f773a..7040998ccf01 100644 --- a/crates/router/src/configs/validations.rs +++ b/crates/router/src/configs/validations.rs @@ -236,6 +236,27 @@ impl super::settings::NetworkTokenizationService { } } +impl super::settings::PazeDecryptConfig { + pub fn validate(&self) -> Result<(), ApplicationError> { + use common_utils::fp_utils::when; + + when(self.paze_private_key.is_default_or_empty(), || { + Err(ApplicationError::InvalidConfigurationValueError( + "paze_private_key must not be empty".into(), + )) + })?; + + when( + self.paze_private_key_passphrase.is_default_or_empty(), + || { + Err(ApplicationError::InvalidConfigurationValueError( + "paze_private_key_passphrase must not be empty".into(), + )) + }, + ) + } +} + impl super::settings::KeyManagerConfig { pub fn validate(&self) -> Result<(), ApplicationError> { use common_utils::fp_utils::when; diff --git a/crates/router/src/connector/aci/transformers.rs b/crates/router/src/connector/aci/transformers.rs index 46f312b38f26..abd99fae18ca 100644 --- a/crates/router/src/connector/aci/transformers.rs +++ b/crates/router/src/connector/aci/transformers.rs @@ -120,6 +120,7 @@ impl TryFrom<(&domain::WalletData, &types::PaymentsAuthorizeRouterData)> for Pay | domain::WalletData::MobilePayRedirect(_) | domain::WalletData::PaypalRedirect(_) | domain::WalletData::PaypalSdk(_) + | domain::WalletData::Paze(_) | domain::WalletData::SamsungPay(_) | domain::WalletData::TwintRedirect { .. } | domain::WalletData::VippsRedirect { .. } diff --git a/crates/router/src/connector/adyen.rs b/crates/router/src/connector/adyen.rs index 810551e0cb7b..e5215022e944 100644 --- a/crates/router/src/connector/adyen.rs +++ b/crates/router/src/connector/adyen.rs @@ -218,6 +218,7 @@ impl ConnectorValidation for Adyen { | PaymentMethodType::Pse | PaymentMethodType::LocalBankTransfer | PaymentMethodType::Efecty + | PaymentMethodType::Paze | PaymentMethodType::PagoEfectivo | PaymentMethodType::PromptPay | PaymentMethodType::RedCompra diff --git a/crates/router/src/connector/adyen/transformers.rs b/crates/router/src/connector/adyen/transformers.rs index 50ce6aea0f4c..4cc392c57bc2 100644 --- a/crates/router/src/connector/adyen/transformers.rs +++ b/crates/router/src/connector/adyen/transformers.rs @@ -2149,6 +2149,7 @@ impl<'a> TryFrom<(&domain::WalletData, &types::PaymentsAuthorizeRouterData)> | domain::WalletData::GooglePayRedirect(_) | domain::WalletData::GooglePayThirdPartySdk(_) | domain::WalletData::PaypalSdk(_) + | domain::WalletData::Paze(_) | domain::WalletData::WeChatPayQr(_) | domain::WalletData::CashappQr(_) | domain::WalletData::Mifinity(_) => Err(errors::ConnectorError::NotImplemented( diff --git a/crates/router/src/connector/airwallex/transformers.rs b/crates/router/src/connector/airwallex/transformers.rs index 4d84f64534e8..868a4767c319 100644 --- a/crates/router/src/connector/airwallex/transformers.rs +++ b/crates/router/src/connector/airwallex/transformers.rs @@ -254,6 +254,7 @@ fn get_wallet_details( | domain::WalletData::MobilePayRedirect(_) | domain::WalletData::PaypalRedirect(_) | domain::WalletData::PaypalSdk(_) + | domain::WalletData::Paze(_) | domain::WalletData::SamsungPay(_) | domain::WalletData::TwintRedirect {} | domain::WalletData::VippsRedirect {} diff --git a/crates/router/src/connector/authorizedotnet/transformers.rs b/crates/router/src/connector/authorizedotnet/transformers.rs index 868409dafc79..e352d8b79bc1 100644 --- a/crates/router/src/connector/authorizedotnet/transformers.rs +++ b/crates/router/src/connector/authorizedotnet/transformers.rs @@ -1747,6 +1747,7 @@ fn get_wallet_data( | domain::WalletData::MbWayRedirect(_) | domain::WalletData::MobilePayRedirect(_) | domain::WalletData::PaypalSdk(_) + | domain::WalletData::Paze(_) | domain::WalletData::SamsungPay(_) | domain::WalletData::TwintRedirect {} | domain::WalletData::VippsRedirect {} diff --git a/crates/router/src/connector/bankofamerica/transformers.rs b/crates/router/src/connector/bankofamerica/transformers.rs index b987a6717a16..ab6367eeb6ee 100644 --- a/crates/router/src/connector/bankofamerica/transformers.rs +++ b/crates/router/src/connector/bankofamerica/transformers.rs @@ -297,6 +297,7 @@ impl TryFrom<&types::SetupMandateRouterData> for BankOfAmericaPaymentsRequest { | domain::WalletData::MobilePayRedirect(_) | domain::WalletData::PaypalRedirect(_) | domain::WalletData::PaypalSdk(_) + | domain::WalletData::Paze(_) | domain::WalletData::SamsungPay(_) | domain::WalletData::TwintRedirect {} | domain::WalletData::VippsRedirect {} @@ -977,6 +978,9 @@ impl TryFrom<&BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>> "Bank Of America" ))? } + types::PaymentMethodToken::PazeDecrypt(_) => Err( + unimplemented_payment_method!("Paze", "Bank Of America"), + )?, }, None => { let email = item.router_data.request.get_email()?; @@ -1051,6 +1055,7 @@ impl TryFrom<&BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>> | domain::WalletData::MobilePayRedirect(_) | domain::WalletData::PaypalRedirect(_) | domain::WalletData::PaypalSdk(_) + | domain::WalletData::Paze(_) | domain::WalletData::SamsungPay(_) | domain::WalletData::TwintRedirect {} | domain::WalletData::VippsRedirect {} @@ -2328,6 +2333,9 @@ impl TryFrom<(&types::SetupMandateRouterData, domain::ApplePayWalletData)> "Manual", "Bank Of America" ))?, + types::PaymentMethodToken::PazeDecrypt(_) => { + Err(unimplemented_payment_method!("Paze", "Bank Of America"))? + } }, None => PaymentInformation::from(&apple_pay_data), }; diff --git a/crates/router/src/connector/bluesnap/transformers.rs b/crates/router/src/connector/bluesnap/transformers.rs index 6ebcdf0e765b..b156aafb6ef7 100644 --- a/crates/router/src/connector/bluesnap/transformers.rs +++ b/crates/router/src/connector/bluesnap/transformers.rs @@ -369,6 +369,7 @@ impl TryFrom<&BluesnapRouterData<&types::PaymentsAuthorizeRouterData>> for Blues | domain::WalletData::MobilePayRedirect(_) | domain::WalletData::PaypalRedirect(_) | domain::WalletData::PaypalSdk(_) + | domain::WalletData::Paze(_) | domain::WalletData::SamsungPay(_) | domain::WalletData::TwintRedirect {} | domain::WalletData::VippsRedirect {} diff --git a/crates/router/src/connector/boku/transformers.rs b/crates/router/src/connector/boku/transformers.rs index 5fd6b0e6a2eb..a48e49a10cc0 100644 --- a/crates/router/src/connector/boku/transformers.rs +++ b/crates/router/src/connector/boku/transformers.rs @@ -180,6 +180,7 @@ fn get_wallet_type(wallet_data: &domain::WalletData) -> Result Err( unimplemented_payment_method!("Apple Pay", "Simplified", "Braintree"), )?, + types::PaymentMethodToken::PazeDecrypt(_) => { + Err(unimplemented_payment_method!("Paze", "Braintree"))? + } }, transaction: transaction_body, }, @@ -1689,6 +1692,9 @@ fn get_braintree_redirect_form( "Simplified", "Braintree" ))?, + types::PaymentMethodToken::PazeDecrypt(_) => { + Err(unimplemented_payment_method!("Paze", "Braintree"))? + } }, bin: match card_details { domain::PaymentMethodData::Card(card_details) => { diff --git a/crates/router/src/connector/checkout/transformers.rs b/crates/router/src/connector/checkout/transformers.rs index 223256155cfd..2950fdb6bd1a 100644 --- a/crates/router/src/connector/checkout/transformers.rs +++ b/crates/router/src/connector/checkout/transformers.rs @@ -106,6 +106,7 @@ impl TryFrom<&types::TokenizationRouterData> for TokenRequest { | domain::WalletData::MobilePayRedirect(_) | domain::WalletData::PaypalRedirect(_) | domain::WalletData::PaypalSdk(_) + | domain::WalletData::Paze(_) | domain::WalletData::SamsungPay(_) | domain::WalletData::TwintRedirect {} | domain::WalletData::VippsRedirect {} @@ -301,6 +302,9 @@ impl TryFrom<&CheckoutRouterData<&types::PaymentsAuthorizeRouterData>> for Payme types::PaymentMethodToken::ApplePayDecrypt(_) => Err( unimplemented_payment_method!("Apple Pay", "Simplified", "Checkout"), )?, + types::PaymentMethodToken::PazeDecrypt(_) => { + Err(unimplemented_payment_method!("Paze", "Checkout"))? + } }, })), domain::WalletData::ApplePay(_) => { @@ -327,6 +331,9 @@ impl TryFrom<&CheckoutRouterData<&types::PaymentsAuthorizeRouterData>> for Payme }, ))) } + types::PaymentMethodToken::PazeDecrypt(_) => { + Err(unimplemented_payment_method!("Paze", "Checkout"))? + } } } domain::WalletData::AliPayQr(_) @@ -345,6 +352,7 @@ impl TryFrom<&CheckoutRouterData<&types::PaymentsAuthorizeRouterData>> for Payme | domain::WalletData::MobilePayRedirect(_) | domain::WalletData::PaypalRedirect(_) | domain::WalletData::PaypalSdk(_) + | domain::WalletData::Paze(_) | domain::WalletData::SamsungPay(_) | domain::WalletData::TwintRedirect {} | domain::WalletData::VippsRedirect {} diff --git a/crates/router/src/connector/cybersource/transformers.rs b/crates/router/src/connector/cybersource/transformers.rs index 38bb016ff258..8a6c3c075ff1 100644 --- a/crates/router/src/connector/cybersource/transformers.rs +++ b/crates/router/src/connector/cybersource/transformers.rs @@ -176,6 +176,9 @@ impl TryFrom<&types::SetupMandateRouterData> for CybersourceZeroMandateRequest { types::PaymentMethodToken::Token(_) => Err( unimplemented_payment_method!("Apple Pay", "Manual", "Cybersource"), )?, + types::PaymentMethodToken::PazeDecrypt(_) => { + Err(unimplemented_payment_method!("Paze", "Cybersource"))? + } }, None => ( PaymentInformation::ApplePayToken(Box::new( @@ -221,6 +224,7 @@ impl TryFrom<&types::SetupMandateRouterData> for CybersourceZeroMandateRequest { | domain::WalletData::MobilePayRedirect(_) | domain::WalletData::PaypalRedirect(_) | domain::WalletData::PaypalSdk(_) + | domain::WalletData::Paze(_) | domain::WalletData::SamsungPay(_) | domain::WalletData::TwintRedirect {} | domain::WalletData::VippsRedirect {} @@ -1322,6 +1326,92 @@ impl } } +impl + TryFrom<( + &CybersourceRouterData<&types::PaymentsAuthorizeRouterData>, + Box, + )> for CybersourcePaymentsRequest +{ + type Error = error_stack::Report; + fn try_from( + (item, paze_data): ( + &CybersourceRouterData<&types::PaymentsAuthorizeRouterData>, + Box, + ), + ) -> Result { + let email = item.router_data.request.get_email()?; + let (first_name, last_name) = match paze_data.billing_address.name { + Some(name) => { + let (first_name, last_name) = name + .peek() + .split_once(' ') + .map(|(first, last)| (first.to_string(), last.to_string())) + .ok_or(errors::ConnectorError::MissingRequiredField { + field_name: "billing_address.name", + })?; + (Secret::from(first_name), Secret::from(last_name)) + } + None => ( + item.router_data.get_billing_first_name()?, + item.router_data.get_billing_last_name()?, + ), + }; + let bill_to = BillTo { + first_name: Some(first_name), + last_name: Some(last_name), + address1: paze_data.billing_address.line1, + locality: paze_data.billing_address.city.map(|city| city.expose()), + administrative_area: Some(Secret::from( + //Paze wallet is currently supported in US only + common_enums::UsStatesAbbreviation::foreign_try_from( + paze_data + .billing_address + .state + .ok_or(errors::ConnectorError::MissingRequiredField { + field_name: "billing_address.state", + })? + .peek() + .to_owned(), + )? + .to_string(), + )), + postal_code: paze_data.billing_address.zip, + country: paze_data.billing_address.country_code, + email, + }; + let order_information = OrderInformationWithBill::from((item, Some(bill_to))); + + let payment_information = + PaymentInformation::NetworkToken(Box::new(NetworkTokenPaymentInformation { + tokenized_card: NetworkTokenizedCard { + number: paze_data.token.payment_token, + expiration_month: paze_data.token.token_expiration_month, + expiration_year: paze_data.token.token_expiration_year, + cryptogram: Some(paze_data.token.payment_account_reference), + transaction_type: "1".to_string(), + }, + })); + + let processing_information = ProcessingInformation::try_from((item, None, None))?; + let client_reference_information = ClientReferenceInformation::from(item); + let merchant_defined_information = item + .router_data + .request + .metadata + .clone() + .map(Vec::::foreign_from); + + Ok(Self { + processing_information, + payment_information, + order_information, + client_reference_information, + consumer_authentication_information: None, + merchant_defined_information, + }) + } +} + impl TryFrom<( &CybersourceRouterData<&types::PaymentsCompleteAuthorizeRouterData>, @@ -1645,6 +1735,9 @@ impl TryFrom<&CybersourceRouterData<&types::PaymentsAuthorizeRouterData>> "Cybersource" ))? } + types::PaymentMethodToken::PazeDecrypt(_) => { + Err(unimplemented_payment_method!("Paze", "Cybersource"))? + } }, None => { let email = item @@ -1719,6 +1812,19 @@ impl TryFrom<&CybersourceRouterData<&types::PaymentsAuthorizeRouterData>> domain::WalletData::SamsungPay(samsung_pay_data) => { Self::try_from((item, samsung_pay_data)) } + domain::WalletData::Paze(_) => { + match item.router_data.payment_method_token.clone() { + Some(types::PaymentMethodToken::PazeDecrypt( + paze_decrypted_data, + )) => Self::try_from((item, paze_decrypted_data)), + _ => Err(errors::ConnectorError::NotImplemented( + utils::get_unimplemented_payment_method_error_message( + "Cybersource", + ), + ) + .into()), + } + } domain::WalletData::AliPayQr(_) | domain::WalletData::AliPayRedirect(_) | domain::WalletData::AliPayHkRedirect(_) diff --git a/crates/router/src/connector/gocardless/transformers.rs b/crates/router/src/connector/gocardless/transformers.rs index ff2f9d95026e..4982aaf4d887 100644 --- a/crates/router/src/connector/gocardless/transformers.rs +++ b/crates/router/src/connector/gocardless/transformers.rs @@ -429,7 +429,8 @@ impl TryFrom<&types::SetupMandateRouterData> for GocardlessMandateRequest { let payment_method_token = item.get_payment_method_token()?; let customer_bank_account = match payment_method_token { types::PaymentMethodToken::Token(token) => Ok(token), - types::PaymentMethodToken::ApplePayDecrypt(_) => { + types::PaymentMethodToken::ApplePayDecrypt(_) + | types::PaymentMethodToken::PazeDecrypt(_) => { Err(errors::ConnectorError::NotImplemented( "Setup Mandate flow for selected payment method through Gocardless".to_string(), )) diff --git a/crates/router/src/connector/klarna.rs b/crates/router/src/connector/klarna.rs index 0e6fab805848..2c3d3651284f 100644 --- a/crates/router/src/connector/klarna.rs +++ b/crates/router/src/connector/klarna.rs @@ -598,6 +598,7 @@ impl | common_enums::PaymentMethodType::OpenBankingUk | common_enums::PaymentMethodType::PayBright | common_enums::PaymentMethodType::Paypal + | common_enums::PaymentMethodType::Paze | common_enums::PaymentMethodType::Pix | common_enums::PaymentMethodType::PaySafeCard | common_enums::PaymentMethodType::Przelewy24 diff --git a/crates/router/src/connector/mifinity/transformers.rs b/crates/router/src/connector/mifinity/transformers.rs index 0af3826c877f..92b6b45785d3 100644 --- a/crates/router/src/connector/mifinity/transformers.rs +++ b/crates/router/src/connector/mifinity/transformers.rs @@ -169,6 +169,7 @@ impl TryFrom<&MifinityRouterData<&types::PaymentsAuthorizeRouterData>> for Mifin | domain::WalletData::MobilePayRedirect(_) | domain::WalletData::PaypalRedirect(_) | domain::WalletData::PaypalSdk(_) + | domain::WalletData::Paze(_) | domain::WalletData::SamsungPay(_) | domain::WalletData::TwintRedirect {} | domain::WalletData::VippsRedirect {} diff --git a/crates/router/src/connector/multisafepay/transformers.rs b/crates/router/src/connector/multisafepay/transformers.rs index 547a38ad8498..e0146bf2edad 100644 --- a/crates/router/src/connector/multisafepay/transformers.rs +++ b/crates/router/src/connector/multisafepay/transformers.rs @@ -493,6 +493,7 @@ impl TryFrom<&MultisafepayRouterData<&types::PaymentsAuthorizeRouterData>> | domain::WalletData::MbWayRedirect(_) | domain::WalletData::MobilePayRedirect(_) | domain::WalletData::PaypalSdk(_) + | domain::WalletData::Paze(_) | domain::WalletData::SamsungPay(_) | domain::WalletData::TwintRedirect {} | domain::WalletData::VippsRedirect {} @@ -556,6 +557,7 @@ impl TryFrom<&MultisafepayRouterData<&types::PaymentsAuthorizeRouterData>> | domain::WalletData::MbWayRedirect(_) | domain::WalletData::MobilePayRedirect(_) | domain::WalletData::PaypalSdk(_) + | domain::WalletData::Paze(_) | domain::WalletData::SamsungPay(_) | domain::WalletData::TwintRedirect {} | domain::WalletData::VippsRedirect {} @@ -714,6 +716,7 @@ impl TryFrom<&MultisafepayRouterData<&types::PaymentsAuthorizeRouterData>> | domain::WalletData::MbWayRedirect(_) | domain::WalletData::MobilePayRedirect(_) | domain::WalletData::PaypalSdk(_) + | domain::WalletData::Paze(_) | domain::WalletData::SamsungPay(_) | domain::WalletData::TwintRedirect {} | domain::WalletData::VippsRedirect {} diff --git a/crates/router/src/connector/nexinets/transformers.rs b/crates/router/src/connector/nexinets/transformers.rs index 55b2fbe41763..5bf721333840 100644 --- a/crates/router/src/connector/nexinets/transformers.rs +++ b/crates/router/src/connector/nexinets/transformers.rs @@ -722,6 +722,7 @@ fn get_wallet_details( | domain::WalletData::MbWayRedirect(_) | domain::WalletData::MobilePayRedirect(_) | domain::WalletData::PaypalSdk(_) + | domain::WalletData::Paze(_) | domain::WalletData::SamsungPay(_) | domain::WalletData::TwintRedirect { .. } | domain::WalletData::VippsRedirect { .. } diff --git a/crates/router/src/connector/nmi/transformers.rs b/crates/router/src/connector/nmi/transformers.rs index 069a51ae52e7..57b04cdca17b 100644 --- a/crates/router/src/connector/nmi/transformers.rs +++ b/crates/router/src/connector/nmi/transformers.rs @@ -558,6 +558,7 @@ impl | domain::WalletData::MobilePayRedirect(_) | domain::WalletData::PaypalRedirect(_) | domain::WalletData::PaypalSdk(_) + | domain::WalletData::Paze(_) | domain::WalletData::SamsungPay(_) | domain::WalletData::TwintRedirect {} | domain::WalletData::VippsRedirect {} diff --git a/crates/router/src/connector/noon/transformers.rs b/crates/router/src/connector/noon/transformers.rs index 5d9871742730..99e04018632c 100644 --- a/crates/router/src/connector/noon/transformers.rs +++ b/crates/router/src/connector/noon/transformers.rs @@ -326,6 +326,7 @@ impl TryFrom<&NoonRouterData<&types::PaymentsAuthorizeRouterData>> for NoonPayme | domain::WalletData::MbWayRedirect(_) | domain::WalletData::MobilePayRedirect(_) | domain::WalletData::PaypalSdk(_) + | domain::WalletData::Paze(_) | domain::WalletData::SamsungPay(_) | domain::WalletData::TwintRedirect {} | domain::WalletData::VippsRedirect {} diff --git a/crates/router/src/connector/nuvei/transformers.rs b/crates/router/src/connector/nuvei/transformers.rs index f280d3a42a2a..d9728174f843 100644 --- a/crates/router/src/connector/nuvei/transformers.rs +++ b/crates/router/src/connector/nuvei/transformers.rs @@ -914,6 +914,7 @@ where | domain::WalletData::MbWayRedirect(_) | domain::WalletData::MobilePayRedirect(_) | domain::WalletData::PaypalSdk(_) + | domain::WalletData::Paze(_) | domain::WalletData::SamsungPay(_) | domain::WalletData::TwintRedirect {} | domain::WalletData::VippsRedirect {} diff --git a/crates/router/src/connector/payme/transformers.rs b/crates/router/src/connector/payme/transformers.rs index e0ab598d76d6..b4aa66a1c493 100644 --- a/crates/router/src/connector/payme/transformers.rs +++ b/crates/router/src/connector/payme/transformers.rs @@ -403,6 +403,7 @@ impl TryFrom<&PaymentMethodData> for SalePaymentMethod { | domain::WalletData::MobilePayRedirect(_) | domain::WalletData::PaypalRedirect(_) | domain::WalletData::PaypalSdk(_) + | domain::WalletData::Paze(_) | domain::WalletData::SamsungPay(_) | domain::WalletData::TwintRedirect {} | domain::WalletData::VippsRedirect {} @@ -715,6 +716,9 @@ impl TryFrom<&types::PaymentsCompleteAuthorizeRouterData> for Pay3dsRequest { types::PaymentMethodToken::ApplePayDecrypt(_) => Err( unimplemented_payment_method!("Apple Pay", "Simplified", "Payme"), )?, + types::PaymentMethodToken::PazeDecrypt(_) => { + Err(unimplemented_payment_method!("Paze", "Payme"))? + } }; Ok(Self { buyer_email, diff --git a/crates/router/src/connector/paypal/transformers.rs b/crates/router/src/connector/paypal/transformers.rs index 4f5ab1337355..41fd533309e5 100644 --- a/crates/router/src/connector/paypal/transformers.rs +++ b/crates/router/src/connector/paypal/transformers.rs @@ -490,6 +490,7 @@ impl TryFrom<&PaypalRouterData<&types::PaymentsAuthorizeRouterData>> for PaypalP | domain::WalletData::GooglePayThirdPartySdk(_) | domain::WalletData::MbWayRedirect(_) | domain::WalletData::MobilePayRedirect(_) + | domain::WalletData::Paze(_) | domain::WalletData::SamsungPay(_) | domain::WalletData::TwintRedirect {} | domain::WalletData::VippsRedirect {} diff --git a/crates/router/src/connector/shift4/transformers.rs b/crates/router/src/connector/shift4/transformers.rs index 13c0395cf9f4..e206fe0e0aea 100644 --- a/crates/router/src/connector/shift4/transformers.rs +++ b/crates/router/src/connector/shift4/transformers.rs @@ -282,6 +282,7 @@ impl TryFrom<&domain::WalletData> for Shift4PaymentMethod { | domain::WalletData::MobilePayRedirect(_) | domain::WalletData::PaypalRedirect(_) | domain::WalletData::PaypalSdk(_) + | domain::WalletData::Paze(_) | domain::WalletData::SamsungPay(_) | domain::WalletData::TwintRedirect {} | domain::WalletData::VippsRedirect {} diff --git a/crates/router/src/connector/stripe/transformers.rs b/crates/router/src/connector/stripe/transformers.rs index f9fd519241ab..68bab815d65b 100644 --- a/crates/router/src/connector/stripe/transformers.rs +++ b/crates/router/src/connector/stripe/transformers.rs @@ -737,6 +737,7 @@ impl TryFrom for StripePaymentMethodType { | enums::PaymentMethodType::MandiriVa | enums::PaymentMethodType::PermataBankTransfer | enums::PaymentMethodType::PaySafeCard + | enums::PaymentMethodType::Paze | enums::PaymentMethodType::Givex | enums::PaymentMethodType::Benefit | enums::PaymentMethodType::Knet @@ -1062,6 +1063,7 @@ impl ForeignTryFrom<&domain::WalletData> for Option { | domain::WalletData::GooglePayThirdPartySdk(_) | domain::WalletData::MbWayRedirect(_) | domain::WalletData::PaypalSdk(_) + | domain::WalletData::Paze(_) | domain::WalletData::SamsungPay(_) | domain::WalletData::TwintRedirect {} | domain::WalletData::VippsRedirect {} @@ -1478,6 +1480,7 @@ impl TryFrom<(&domain::WalletData, Option)> for Strip | domain::WalletData::GooglePayThirdPartySdk(_) | domain::WalletData::MbWayRedirect(_) | domain::WalletData::PaypalSdk(_) + | domain::WalletData::Paze(_) | domain::WalletData::SamsungPay(_) | domain::WalletData::TwintRedirect {} | domain::WalletData::VippsRedirect {} @@ -1809,6 +1812,9 @@ impl TryFrom<(&types::PaymentsAuthorizeRouterData, MinorUnit)> for PaymentIntent wallet_name: "Apple Pay".to_string(), })? } + types::PaymentMethodToken::PazeDecrypt(_) => { + Err(crate::unimplemented_payment_method!("Paze", "Stripe"))? + } }; Some(StripePaymentMethodData::Wallet( StripeWallet::ApplepayPayment(ApplepayPayment { diff --git a/crates/router/src/connector/utils.rs b/crates/router/src/connector/utils.rs index c66e1f2f65cb..31afb0adf117 100644 --- a/crates/router/src/connector/utils.rs +++ b/crates/router/src/connector/utils.rs @@ -2638,6 +2638,7 @@ pub enum PaymentMethodDataType { MobilePayRedirect, PaypalRedirect, PaypalSdk, + Paze, SamsungPay, TwintRedirect, VippsRedirect, @@ -2755,6 +2756,7 @@ impl From for PaymentMethodDataType { domain::payments::WalletData::MobilePayRedirect(_) => Self::MobilePayRedirect, domain::payments::WalletData::PaypalRedirect(_) => Self::PaypalRedirect, domain::payments::WalletData::PaypalSdk(_) => Self::PaypalSdk, + domain::payments::WalletData::Paze(_) => Self::Paze, domain::payments::WalletData::SamsungPay(_) => Self::SamsungPay, domain::payments::WalletData::TwintRedirect {} => Self::TwintRedirect, domain::payments::WalletData::VippsRedirect {} => Self::VippsRedirect, diff --git a/crates/router/src/connector/wellsfargo/transformers.rs b/crates/router/src/connector/wellsfargo/transformers.rs index be3cf4a1cef9..ee34c26d6709 100644 --- a/crates/router/src/connector/wellsfargo/transformers.rs +++ b/crates/router/src/connector/wellsfargo/transformers.rs @@ -135,6 +135,9 @@ impl TryFrom<&types::SetupMandateRouterData> for WellsfargoZeroMandateRequest { types::PaymentMethodToken::Token(_) => Err( unimplemented_payment_method!("Apple Pay", "Manual", "Wellsfargo"), )?, + types::PaymentMethodToken::PazeDecrypt(_) => { + Err(unimplemented_payment_method!("Paze", "Wellsfargo"))? + } }, None => ( PaymentInformation::ApplePayToken(Box::new( @@ -180,6 +183,7 @@ impl TryFrom<&types::SetupMandateRouterData> for WellsfargoZeroMandateRequest { | domain::WalletData::MobilePayRedirect(_) | domain::WalletData::PaypalRedirect(_) | domain::WalletData::PaypalSdk(_) + | domain::WalletData::Paze(_) | domain::WalletData::SamsungPay(_) | domain::WalletData::TwintRedirect {} | domain::WalletData::VippsRedirect {} @@ -1158,6 +1162,9 @@ impl TryFrom<&WellsfargoRouterData<&types::PaymentsAuthorizeRouterData>> "Wellsfargo" ))? } + types::PaymentMethodToken::PazeDecrypt(_) => { + Err(unimplemented_payment_method!("Paze", "Wellsfargo"))? + } }, None => { let email = item.router_data.request.get_email()?; @@ -1242,6 +1249,7 @@ impl TryFrom<&WellsfargoRouterData<&types::PaymentsAuthorizeRouterData>> | domain::WalletData::MobilePayRedirect(_) | domain::WalletData::PaypalRedirect(_) | domain::WalletData::PaypalSdk(_) + | domain::WalletData::Paze(_) | domain::WalletData::SamsungPay(_) | domain::WalletData::TwintRedirect {} | domain::WalletData::VippsRedirect {} diff --git a/crates/router/src/connector/worldpay/transformers.rs b/crates/router/src/connector/worldpay/transformers.rs index de82e11548ca..467a1cba9025 100644 --- a/crates/router/src/connector/worldpay/transformers.rs +++ b/crates/router/src/connector/worldpay/transformers.rs @@ -83,6 +83,7 @@ fn fetch_payment_instrument( | domain::WalletData::MobilePayRedirect(_) | domain::WalletData::PaypalRedirect(_) | domain::WalletData::PaypalSdk(_) + | domain::WalletData::Paze(_) | domain::WalletData::SamsungPay(_) | domain::WalletData::TwintRedirect {} | domain::WalletData::VippsRedirect {} diff --git a/crates/router/src/connector/zen/transformers.rs b/crates/router/src/connector/zen/transformers.rs index d2e8ce40283b..2b2e7e889e2c 100644 --- a/crates/router/src/connector/zen/transformers.rs +++ b/crates/router/src/connector/zen/transformers.rs @@ -486,6 +486,7 @@ impl | domain::WalletData::MbWayRedirect(_) | domain::WalletData::MobilePayRedirect(_) | domain::WalletData::PaypalSdk(_) + | domain::WalletData::Paze(_) | domain::WalletData::SamsungPay(_) | domain::WalletData::TwintRedirect {} | domain::WalletData::VippsRedirect {} diff --git a/crates/router/src/core/errors.rs b/crates/router/src/core/errors.rs index c56bfaca9135..aa4ff406a2ce 100644 --- a/crates/router/src/core/errors.rs +++ b/crates/router/src/core/errors.rs @@ -234,6 +234,16 @@ pub enum ApplePayDecryptionError { DerivingSharedSecretKeyFailed, } +#[derive(Debug, thiserror::Error)] +pub enum PazeDecryptionError { + #[error("Failed to base64 decode input data")] + Base64DecodingFailed, + #[error("Failed to decrypt input data")] + DecryptionFailed, + #[error("Certificate parsing failed")] + CertificateParsingFailed, +} + #[cfg(feature = "detailed_errors")] pub mod error_stack_parsing { diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs index 9f9041161716..363d52cd8bf5 100644 --- a/crates/router/src/core/payments.rs +++ b/crates/router/src/core/payments.rs @@ -34,13 +34,13 @@ use diesel_models::{ephemeral_key, fraud_check::FraudCheck}; use error_stack::{report, ResultExt}; use events::EventInfo; use futures::future::join_all; -use helpers::ApplePayData; +use helpers::{decrypt_paze_token, ApplePayData}; #[cfg(feature = "v2")] use hyperswitch_domain_models::payments::PaymentIntentData; pub use hyperswitch_domain_models::{ mandates::{CustomerAcceptance, MandateData}, payment_address::PaymentAddress, - router_data::RouterData, + router_data::{PaymentMethodToken, RouterData}, router_request_types::CustomerDetails, }; use masking::{ExposeInterface, PeekInterface, Secret}; @@ -1710,42 +1710,12 @@ where &call_connector_action, ); - // Tokenization Action will be DecryptApplePayToken, only when payment method type is Apple Pay - // and the connector supports Apple Pay predecrypt - match &tokenization_action { - TokenizationAction::DecryptApplePayToken(payment_processing_details) - | TokenizationAction::TokenizeInConnectorAndApplepayPreDecrypt( - payment_processing_details, - ) => { - let apple_pay_data = match payment_data.get_payment_method_data() { - Some(domain::PaymentMethodData::Wallet(domain::WalletData::ApplePay( - wallet_data, - ))) => Some( - ApplePayData::token_json(domain::WalletData::ApplePay(wallet_data.clone())) - .change_context(errors::ApiErrorResponse::InternalServerError)? - .decrypt( - &payment_processing_details.payment_processing_certificate, - &payment_processing_details.payment_processing_certificate_key, - ) - .await - .change_context(errors::ApiErrorResponse::InternalServerError)?, - ), - _ => None, - }; - - let apple_pay_predecrypt = apple_pay_data - .parse_value::( - "ApplePayPredecryptData", - ) - .change_context(errors::ApiErrorResponse::InternalServerError)?; - - router_data.payment_method_token = Some( - hyperswitch_domain_models::router_data::PaymentMethodToken::ApplePayDecrypt( - Box::new(apple_pay_predecrypt), - ), - ); - } - _ => (), + router_data.payment_method_token = if let Some(decrypted_token) = + add_decrypted_payment_method_token(tokenization_action.clone(), payment_data).await? + { + Some(decrypted_token) + } else { + router_data.payment_method_token }; let payment_method_token_response = router_data @@ -1853,6 +1823,83 @@ where Ok((router_data, merchant_connector_account)) } +pub async fn add_decrypted_payment_method_token( + tokenization_action: TokenizationAction, + payment_data: &D, +) -> CustomResult, errors::ApiErrorResponse> +where + F: Send + Clone + Sync, + D: OperationSessionGetters + Send + Sync + Clone, +{ + // Tokenization Action will be DecryptApplePayToken, only when payment method type is Apple Pay + // and the connector supports Apple Pay predecrypt + match &tokenization_action { + TokenizationAction::DecryptApplePayToken(payment_processing_details) + | TokenizationAction::TokenizeInConnectorAndApplepayPreDecrypt( + payment_processing_details, + ) => { + let apple_pay_data = match payment_data.get_payment_method_data() { + Some(domain::PaymentMethodData::Wallet(domain::WalletData::ApplePay( + wallet_data, + ))) => Some( + ApplePayData::token_json(domain::WalletData::ApplePay(wallet_data.clone())) + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("failed to parse apple pay token to json")? + .decrypt( + &payment_processing_details.payment_processing_certificate, + &payment_processing_details.payment_processing_certificate_key, + ) + .await + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("failed to decrypt apple pay token")?, + ), + _ => None, + }; + + let apple_pay_predecrypt = apple_pay_data + .parse_value::( + "ApplePayPredecryptData", + ) + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable( + "failed to parse decrypted apple pay response to ApplePayPredecryptData", + )?; + + Ok(Some(PaymentMethodToken::ApplePayDecrypt(Box::new( + apple_pay_predecrypt, + )))) + } + TokenizationAction::DecryptPazeToken(payment_processing_details) => { + let paze_data = match payment_data.get_payment_method_data() { + Some(domain::PaymentMethodData::Wallet(domain::WalletData::Paze(wallet_data))) => { + Some( + decrypt_paze_token( + wallet_data.clone(), + payment_processing_details.paze_private_key.clone(), + payment_processing_details + .paze_private_key_passphrase + .clone(), + ) + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("failed to decrypt paze token")?, + ) + } + _ => None, + }; + let paze_decrypted_data = paze_data + .parse_value::( + "PazeDecryptedData", + ) + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("failed to parse PazeDecryptedData")?; + Ok(Some(PaymentMethodToken::PazeDecrypt(Box::new( + paze_decrypted_data, + )))) + } + _ => Ok(None), + } +} + pub async fn get_merchant_bank_data_for_open_banking_connectors( merchant_connector_account: &helpers::MerchantConnectorAccountType, key_store: &domain::MerchantKeyStore, @@ -2642,59 +2689,87 @@ async fn decide_payment_method_tokenize_action( pm_parent_token: Option<&str>, is_connector_tokenization_enabled: bool, apple_pay_flow: Option, + payment_method_type: Option, ) -> RouterResult { - match pm_parent_token { - None => Ok(match (is_connector_tokenization_enabled, apple_pay_flow) { - (true, Some(domain::ApplePayFlow::Simplified(payment_processing_details))) => { - TokenizationAction::TokenizeInConnectorAndApplepayPreDecrypt( - payment_processing_details, - ) - } - (true, _) => TokenizationAction::TokenizeInConnectorAndRouter, - (false, Some(domain::ApplePayFlow::Simplified(payment_processing_details))) => { - TokenizationAction::DecryptApplePayToken(payment_processing_details) - } - (false, _) => TokenizationAction::TokenizeInRouter, - }), - Some(token) => { - let redis_conn = state - .store - .get_redis_conn() - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Failed to get redis connection")?; - - let key = format!( - "pm_token_{}_{}_{}", - token.to_owned(), - payment_method, - connector_name - ); + if let Some(storage_enums::PaymentMethodType::Paze) = payment_method_type { + // Paze generates a one time use network token which should not be tokenized in the connector or router. + match &state.conf.paze_decrypt_keys { + Some(paze_keys) => Ok(TokenizationAction::DecryptPazeToken( + PazePaymentProcessingDetails { + paze_private_key: paze_keys.get_inner().paze_private_key.clone(), + paze_private_key_passphrase: paze_keys + .get_inner() + .paze_private_key_passphrase + .clone(), + }, + )), + None => Err(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Failed to fetch Paze configs"), + } + } else { + match pm_parent_token { + None => Ok(match (is_connector_tokenization_enabled, apple_pay_flow) { + (true, Some(domain::ApplePayFlow::Simplified(payment_processing_details))) => { + TokenizationAction::TokenizeInConnectorAndApplepayPreDecrypt( + payment_processing_details, + ) + } + (true, _) => TokenizationAction::TokenizeInConnectorAndRouter, + (false, Some(domain::ApplePayFlow::Simplified(payment_processing_details))) => { + TokenizationAction::DecryptApplePayToken(payment_processing_details) + } + (false, _) => TokenizationAction::TokenizeInRouter, + }), + Some(token) => { + let redis_conn = state + .store + .get_redis_conn() + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Failed to get redis connection")?; + + let key = format!( + "pm_token_{}_{}_{}", + token.to_owned(), + payment_method, + connector_name + ); - let connector_token_option = redis_conn - .get_key::>(&key) - .await - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Failed to fetch the token from redis")?; + let connector_token_option = redis_conn + .get_key::>(&key) + .await + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Failed to fetch the token from redis")?; - match connector_token_option { - Some(connector_token) => Ok(TokenizationAction::ConnectorToken(connector_token)), - None => Ok(match (is_connector_tokenization_enabled, apple_pay_flow) { - (true, Some(domain::ApplePayFlow::Simplified(payment_processing_details))) => { - TokenizationAction::TokenizeInConnectorAndApplepayPreDecrypt( - payment_processing_details, - ) - } - (true, _) => TokenizationAction::TokenizeInConnectorAndRouter, - (false, Some(domain::ApplePayFlow::Simplified(payment_processing_details))) => { - TokenizationAction::DecryptApplePayToken(payment_processing_details) + match connector_token_option { + Some(connector_token) => { + Ok(TokenizationAction::ConnectorToken(connector_token)) } - (false, _) => TokenizationAction::TokenizeInRouter, - }), + None => Ok(match (is_connector_tokenization_enabled, apple_pay_flow) { + ( + true, + Some(domain::ApplePayFlow::Simplified(payment_processing_details)), + ) => TokenizationAction::TokenizeInConnectorAndApplepayPreDecrypt( + payment_processing_details, + ), + (true, _) => TokenizationAction::TokenizeInConnectorAndRouter, + ( + false, + Some(domain::ApplePayFlow::Simplified(payment_processing_details)), + ) => TokenizationAction::DecryptApplePayToken(payment_processing_details), + (false, _) => TokenizationAction::TokenizeInRouter, + }), + } } } } } +#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq)] +pub struct PazePaymentProcessingDetails { + pub paze_private_key: Secret, + pub paze_private_key_passphrase: Secret, +} + #[derive(Clone, Debug)] pub enum TokenizationAction { TokenizeInRouter, @@ -2704,6 +2779,7 @@ pub enum TokenizationAction { SkipConnectorTokenization, DecryptApplePayToken(payments_api::PaymentProcessingDetails), TokenizeInConnectorAndApplepayPreDecrypt(payments_api::PaymentProcessingDetails), + DecryptPazeToken(PazePaymentProcessingDetails), } #[cfg(feature = "v2")] @@ -2791,6 +2867,7 @@ where payment_data.get_token(), is_connector_tokenization_enabled, apple_pay_flow, + *payment_method_type, ) .await?; @@ -2846,6 +2923,9 @@ where ) => TokenizationAction::TokenizeInConnectorAndApplepayPreDecrypt( payment_processing_details, ), + TokenizationAction::DecryptPazeToken(paze_payment_processing_details) => { + TokenizationAction::DecryptPazeToken(paze_payment_processing_details) + } }; (payment_data.to_owned(), connector_tokenization_action) } diff --git a/crates/router/src/core/payments/flows/session_flow.rs b/crates/router/src/core/payments/flows/session_flow.rs index ee657bc39495..1785eee87c5a 100644 --- a/crates/router/src/core/payments/flows/session_flow.rs +++ b/crates/router/src/core/payments/flows/session_flow.rs @@ -498,6 +498,34 @@ async fn create_applepay_session_token( } } +fn create_paze_session_token( + router_data: &types::PaymentsSessionRouterData, + _header_payload: api_models::payments::HeaderPayload, +) -> RouterResult { + let paze_wallet_details = router_data + .connector_wallets_details + .clone() + .parse_value::("PazeSessionTokenData") + .change_context(errors::ConnectorError::NoConnectorWalletDetails) + .change_context(errors::ApiErrorResponse::InvalidDataFormat { + field_name: "connector_wallets_details".to_string(), + expected_format: "paze_metadata_format".to_string(), + })?; + + Ok(types::PaymentsSessionRouterData { + response: Ok(types::PaymentsResponseData::SessionResponse { + session_token: payment_types::SessionToken::Paze(Box::new( + payment_types::PazeSessionTokenResponse { + client_id: paze_wallet_details.data.client_id, + client_name: paze_wallet_details.data.client_name, + client_profile_id: paze_wallet_details.data.client_profile_id, + }, + )), + }), + ..router_data.clone() + }) +} + fn create_samsung_pay_session_token( router_data: &types::PaymentsSessionRouterData, header_payload: api_models::payments::HeaderPayload, @@ -967,6 +995,7 @@ impl RouterDataSession for types::PaymentsSessionRouterData { api::GetToken::PaypalSdkMetadata => { create_paypal_sdk_session_token(state, self, connector, business_profile) } + api::GetToken::PazeMetadata => create_paze_session_token(self, header_payload), api::GetToken::Connector => { let connector_integration: services::BoxedPaymentConnectorIntegrationInterface< api::Session, diff --git a/crates/router/src/core/payments/helpers.rs b/crates/router/src/core/payments/helpers.rs index fbd1170ebadc..a39b151bd27b 100644 --- a/crates/router/src/core/payments/helpers.rs +++ b/crates/router/src/core/payments/helpers.rs @@ -30,7 +30,7 @@ use futures::future::Either; use hyperswitch_domain_models::payments::payment_intent::CustomerData; use hyperswitch_domain_models::{ mandates::MandateData, - payment_method_data::GetPaymentMethodType, + payment_method_data::{GetPaymentMethodType, PazeWalletData}, payments::{ payment_attempt::PaymentAttempt, payment_intent::PaymentIntentFetchConstraints, PaymentIntent, @@ -2545,6 +2545,7 @@ pub fn validate_payment_method_type_against_payment_method( | api_enums::PaymentMethodType::KakaoPay | api_enums::PaymentMethodType::Cashapp | api_enums::PaymentMethodType::Mifinity + | api_enums::PaymentMethodType::Paze ), api_enums::PaymentMethod::BankRedirect => matches!( payment_method_type, @@ -4624,6 +4625,9 @@ async fn get_and_merge_apple_pay_metadata( samsung_pay: connector_wallets_details_optional .as_ref() .and_then(|d| d.samsung_pay.clone()), + paze: connector_wallets_details_optional + .as_ref() + .and_then(|d| d.paze.clone()), } } api_models::payments::ApplepaySessionTokenMetadata::ApplePay(apple_pay_metadata) => { @@ -4639,6 +4643,9 @@ async fn get_and_merge_apple_pay_metadata( samsung_pay: connector_wallets_details_optional .as_ref() .and_then(|d| d.samsung_pay.clone()), + paze: connector_wallets_details_optional + .as_ref() + .and_then(|d| d.paze.clone()), } } }; @@ -4980,6 +4987,71 @@ impl ApplePayData { } } +pub fn decrypt_paze_token( + paze_wallet_data: PazeWalletData, + paze_private_key: masking::Secret, + paze_private_key_passphrase: masking::Secret, +) -> CustomResult { + let decoded_paze_private_key = BASE64_ENGINE + .decode(paze_private_key.expose().as_bytes()) + .change_context(errors::PazeDecryptionError::Base64DecodingFailed)?; + let decrypted_private_key = openssl::rsa::Rsa::private_key_from_pem_passphrase( + decoded_paze_private_key.as_slice(), + paze_private_key_passphrase.expose().as_bytes(), + ) + .change_context(errors::PazeDecryptionError::CertificateParsingFailed)?; + let decrypted_private_key_pem = String::from_utf8( + decrypted_private_key + .private_key_to_pem() + .change_context(errors::PazeDecryptionError::CertificateParsingFailed)?, + ) + .change_context(errors::PazeDecryptionError::CertificateParsingFailed)?; + let decrypter = jwe::RSA_OAEP_256 + .decrypter_from_pem(decrypted_private_key_pem) + .change_context(errors::PazeDecryptionError::CertificateParsingFailed)?; + + let paze_complete_response: Vec<&str> = paze_wallet_data + .complete_response + .peek() + .split('.') + .collect(); + let encrypted_jwe_key = paze_complete_response + .get(1) + .ok_or(errors::PazeDecryptionError::DecryptionFailed)? + .to_string(); + let decoded_jwe_key = base64::engine::general_purpose::URL_SAFE_NO_PAD + .decode(encrypted_jwe_key) + .change_context(errors::PazeDecryptionError::Base64DecodingFailed)?; + let jws_body: JwsBody = serde_json::from_slice(&decoded_jwe_key) + .change_context(errors::PazeDecryptionError::DecryptionFailed)?; + + let (deserialized_payload, _deserialized_header) = + jwe::deserialize_compact(jws_body.secured_payload.peek(), &decrypter) + .change_context(errors::PazeDecryptionError::DecryptionFailed)?; + let encoded_secured_payload_element = String::from_utf8(deserialized_payload) + .change_context(errors::PazeDecryptionError::DecryptionFailed)? + .split('.') + .collect::>() + .get(1) + .ok_or(errors::PazeDecryptionError::DecryptionFailed)? + .to_string(); + let decoded_secured_payload_element = base64::engine::general_purpose::URL_SAFE_NO_PAD + .decode(encoded_secured_payload_element) + .change_context(errors::PazeDecryptionError::Base64DecodingFailed)?; + let parsed_decrypted: serde_json::Value = + serde_json::from_slice(&decoded_secured_payload_element) + .change_context(errors::PazeDecryptionError::DecryptionFailed)?; + Ok(parsed_decrypted) +} + +#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct JwsBody { + pub payload_id: String, + pub session_id: String, + pub secured_payload: masking::Secret, +} + pub fn get_key_params_for_surcharge_details( payment_method_data: &domain::PaymentMethodData, ) -> Option<( diff --git a/crates/router/src/core/payments/operations/payment_session.rs b/crates/router/src/core/payments/operations/payment_session.rs index cc8b839cc809..2e37d26cdec5 100644 --- a/crates/router/src/core/payments/operations/payment_session.rs +++ b/crates/router/src/core/payments/operations/payment_session.rs @@ -492,6 +492,7 @@ impl From for api::GetToken { api_models::enums::PaymentMethodType::ApplePay => Self::ApplePayMetadata, api_models::enums::PaymentMethodType::SamsungPay => Self::SamsungPayMetadata, api_models::enums::PaymentMethodType::Paypal => Self::PaypalSdkMetadata, + api_models::enums::PaymentMethodType::Paze => Self::PazeMetadata, _ => Self::Connector, } } diff --git a/crates/router/src/core/payments/tokenization.rs b/crates/router/src/core/payments/tokenization.rs index 6815d2dfc4fe..ee75536e7c96 100644 --- a/crates/router/src/core/payments/tokenization.rs +++ b/crates/router/src/core/payments/tokenization.rs @@ -133,6 +133,11 @@ where message: "Apple Pay Decrypt token is not supported".to_string(), })? } + types::PaymentMethodToken::PazeDecrypt(_) => { + Err(errors::ApiErrorResponse::NotSupported { + message: "Paze Decrypt token is not supported".to_string(), + })? + } }; Some((connector_name, token)) } else { diff --git a/crates/router/src/types/api.rs b/crates/router/src/types/api.rs index c2ed06d9bad4..e115558995d8 100644 --- a/crates/router/src/types/api.rs +++ b/crates/router/src/types/api.rs @@ -177,6 +177,7 @@ pub enum GetToken { SamsungPayMetadata, ApplePayMetadata, PaypalSdkMetadata, + PazeMetadata, Connector, } diff --git a/crates/router/src/types/transformers.rs b/crates/router/src/types/transformers.rs index a75ef879daf4..49d8d50442eb 100644 --- a/crates/router/src/types/transformers.rs +++ b/crates/router/src/types/transformers.rs @@ -476,6 +476,7 @@ impl ForeignFrom for api_enums::PaymentMethod { | api_enums::PaymentMethodType::Dana | api_enums::PaymentMethodType::MbWay | api_enums::PaymentMethodType::MobilePay + | api_enums::PaymentMethodType::Paze | api_enums::PaymentMethodType::SamsungPay | api_enums::PaymentMethodType::Twint | api_enums::PaymentMethodType::Vipps