From 0f0919963fd1c887d3315039420a939bb377e738 Mon Sep 17 00:00:00 2001 From: AkshayaFoiger <131388445+AkshayaFoiger@users.noreply.github.com> Date: Thu, 3 Aug 2023 12:16:37 +0530 Subject: [PATCH] feat(connector): [Adyen] implement PaySafe (#1805) Co-authored-by: Sangamesh Co-authored-by: Sk Sakil Mostak Co-authored-by: Pa1NarK <69745008+pixincreate@users.noreply.github.com> --- config/config.example.toml | 1 + config/development.toml | 1 + config/docker_compose.toml | 1 + crates/api_models/src/payments.rs | 21 +++--- crates/common_enums/src/enums.rs | 1 + crates/common_enums/src/transformers.rs | 1 + .../src/connector/adyen/transformers.rs | 72 ++++++++++++++++++- crates/router/src/core/payments/helpers.rs | 6 +- crates/router/src/types/transformers.rs | 1 + openapi/openapi_spec.json | 50 +++++++++---- 10 files changed, 130 insertions(+), 25 deletions(-) diff --git a/config/config.example.toml b/config/config.example.toml index e687fd0ed2..b909d3581d 100644 --- a/config/config.example.toml +++ b/config/config.example.toml @@ -341,6 +341,7 @@ danamon_va = {country = "ID", currency = "IDR"} mandiri_va = {country = "ID", currency = "IDR"} alfamart = {country = "ID", currency = "IDR"} indomaret = {country = "ID", currency = "IDR"} +pay_safe_card = {country = "AT,AU,BE,BR,BE,CA,HR,CY,CZ,DK,FI,FR,GE,DE,GI,HU,IS,IE,KW,LV,IE,LI,LT,LU,MT,MX,MD,ME,NL,NZ,NO,PY,PE,PL,PT,RO,SA,RS,SK,SI,ES,SE,CH,TR,UAE,UK,US,UY", currency = "EUR,AUD,BRL,CAD,CZK,DKK,GEL,GIP,HUF,ISK,KWD,CHF,MXN,MDL,NZD,NOK,PYG,PEN,PLN,RON,SAR,RSD,SEK,TRY,AED,GBP,USD,UYU"} [pm_filters.zen] credit = { not_available_flows = { capture_method = "manual" } } diff --git a/config/development.toml b/config/development.toml index c021c7df09..ef8b5fc1dd 100644 --- a/config/development.toml +++ b/config/development.toml @@ -275,6 +275,7 @@ danamon_va = {country = "ID", currency = "IDR"} mandiri_va = {country = "ID", currency = "IDR"} alfamart = {country = "ID", currency = "IDR"} indomaret = {country = "ID", currency = "IDR"} +pay_safe_card = {country = "AT,AU,BE,BR,BE,CA,HR,CY,CZ,DK,FI,FR,GE,DE,GI,HU,IS,IE,KW,LV,IE,LI,LT,LU,MT,MX,MD,ME,NL,NZ,NO,PY,PE,PL,PT,RO,SA,RS,SK,SI,ES,SE,CH,TR,UAE,UK,US,UY", currency = "EUR,AUD,BRL,CAD,CZK,DKK,GEL,GIP,HUF,ISK,KWD,CHF,MXN,MDL,NZD,NOK,PYG,PEN,PLN,RON,SAR,RSD,SEK,TRY,AED,GBP,USD,UYU"} [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" } diff --git a/config/docker_compose.toml b/config/docker_compose.toml index 4cfc054491..97cbf89639 100644 --- a/config/docker_compose.toml +++ b/config/docker_compose.toml @@ -224,6 +224,7 @@ danamon_va = {country = "ID", currency = "IDR"} mandiri_va = {country = "ID", currency = "IDR"} alfamart = {country = "ID", currency = "IDR"} indomaret = {country = "ID", currency = "IDR"} +pay_safe_card = {country = "AT,AU,BE,BR,BE,CA,HR,CY,CZ,DK,FI,FR,GE,DE,GI,HU,IS,IE,KW,LV,IE,LI,LT,LU,MT,MX,MD,ME,NL,NZ,NO,PY,PE,PL,PT,RO,SA,RS,SK,SI,ES,SE,CH,TR,UAE,UK,US,UY", currency = "EUR,AUD,BRL,CAD,CZK,DKK,GEL,GIP,HUF,ISK,KWD,CHF,MXN,MDL,NZD,NOK,PYG,PEN,PLN,RON,SAR,RSD,SEK,TRY,AED,GBP,USD,UYU"} [pm_filters.zen] credit = { not_available_flows = { capture_method = "manual" } } diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs index b05f028ccc..af9b738774 100644 --- a/crates/api_models/src/payments.rs +++ b/crates/api_models/src/payments.rs @@ -725,14 +725,19 @@ pub enum PaymentMethodData { GiftCard(Box), } -#[derive(Debug, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize, ToSchema)] -pub struct GiftCardData { - /// The gift card number - #[schema(value_type = String)] - pub number: Secret, - /// The card verification code. - #[schema(value_type = String)] - pub cvc: Secret, +#[derive(serde::Deserialize, serde::Serialize, Debug, Clone, ToSchema, Eq, PartialEq)] +#[serde(rename_all = "snake_case")] + +pub enum GiftCardData { + BabyGiftCard { + /// The gift card number + #[schema(value_type = String)] + number: Secret, + /// The card verification code. + #[schema(value_type = String)] + cvc: Secret, + }, + PaySafeCard {}, } #[derive(Default, Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)] diff --git a/crates/common_enums/src/enums.rs b/crates/common_enums/src/enums.rs index 7ce5cfebe5..a59e0c9eea 100644 --- a/crates/common_enums/src/enums.rs +++ b/crates/common_enums/src/enums.rs @@ -921,6 +921,7 @@ pub enum PaymentMethodType { PayBright, Paypal, Pix, + PaySafeCard, Przelewy24, Pse, RedCompra, diff --git a/crates/common_enums/src/transformers.rs b/crates/common_enums/src/transformers.rs index 05ec65eba6..80eb61a99f 100644 --- a/crates/common_enums/src/transformers.rs +++ b/crates/common_enums/src/transformers.rs @@ -1585,6 +1585,7 @@ impl From for PaymentMethod { PaymentMethodType::Pse => Self::BankTransfer, PaymentMethodType::PayBright => Self::PayLater, PaymentMethodType::Paypal => Self::Wallet, + PaymentMethodType::PaySafeCard => Self::GiftCard, PaymentMethodType::Przelewy24 => Self::BankRedirect, PaymentMethodType::SamsungPay => Self::Wallet, PaymentMethodType::Sepa => Self::BankDebit, diff --git a/crates/router/src/connector/adyen/transformers.rs b/crates/router/src/connector/adyen/transformers.rs index bd17ca674b..e3c5cb7da0 100644 --- a/crates/router/src/connector/adyen/transformers.rs +++ b/crates/router/src/connector/adyen/transformers.rs @@ -394,6 +394,8 @@ pub enum AdyenPaymentMethod<'a> { OnlineBankingFpx(Box), #[serde(rename = "molpay_ebanking_TH")] OnlineBankingThailand(Box), + #[serde(rename = "paysafecard")] + PaySafeCard, #[serde(rename = "paybright")] PayBright, #[serde(rename = "doku_permata_lite_atm")] @@ -938,6 +940,8 @@ pub enum PaymentType { OnlineBankingFpx, #[serde(rename = "molpay_ebanking_TH")] OnlineBankingThailand, + #[serde(rename = "paysafecard")] + PaySafeCard, PayBright, Paypal, Scheme, @@ -1132,6 +1136,9 @@ impl<'a> TryFrom<&types::PaymentsAuthorizeRouterData> for AdyenPaymentRequest<'a api_models::payments::PaymentMethodData::Voucher(ref voucher_data) => { AdyenPaymentRequest::try_from((item, voucher_data)) } + api_models::payments::PaymentMethodData::GiftCard(ref gift_card) => { + AdyenPaymentRequest::try_from((item, gift_card.as_ref())) + } _ => Err(errors::ConnectorError::NotSupported { message: format!("{:?}", item.request.payment_method_type), connector: "Adyen", @@ -1418,6 +1425,18 @@ impl<'a> TryFrom<&api_models::payments::VoucherData> for AdyenPaymentMethod<'a> } } +impl<'a> TryFrom<&api_models::payments::GiftCardData> for AdyenPaymentMethod<'a> { + type Error = Error; + fn try_from(gift_card_data: &api_models::payments::GiftCardData) -> Result { + match gift_card_data { + payments::GiftCardData::PaySafeCard {} => Ok(AdyenPaymentMethod::PaySafeCard), + payments::GiftCardData::BabyGiftCard { .. } => { + Err(errors::ConnectorError::NotImplemented("Payment method".to_string()).into()) + } + } + } +} + impl<'a> TryFrom<&api::Card> for AdyenPaymentMethod<'a> { type Error = Error; fn try_from(card: &api::Card) -> Result { @@ -2100,6 +2119,53 @@ impl<'a> } } +impl<'a> + TryFrom<( + &types::PaymentsAuthorizeRouterData, + &api_models::payments::GiftCardData, + )> for AdyenPaymentRequest<'a> +{ + type Error = Error; + + fn try_from( + value: ( + &types::PaymentsAuthorizeRouterData, + &api_models::payments::GiftCardData, + ), + ) -> Result { + let (item, gift_card_data) = value; + let amount = get_amount_data(item); + let auth_type = AdyenAuthType::try_from(&item.connector_auth_type)?; + let shopper_interaction = AdyenShopperInteraction::from(item); + let return_url = item.request.get_router_return_url()?; + let payment_method = AdyenPaymentMethod::try_from(gift_card_data)?; + let request = AdyenPaymentRequest { + amount, + merchant_account: auth_type.merchant_account, + payment_method, + reference: item.payment_id.to_string(), + return_url, + browser_info: None, + shopper_interaction, + recurring_processing_model: None, + additional_data: None, + shopper_name: None, + shopper_locale: None, + shopper_email: item.request.email.clone(), + telephone_number: None, + billing_address: None, + delivery_address: None, + country_code: None, + line_items: None, + shopper_reference: None, + store_payment_method: None, + channel: None, + social_security_number: None, + }; + Ok(request) + } +} + impl<'a> TryFrom<( &types::PaymentsAuthorizeRouterData, @@ -2668,7 +2734,8 @@ pub fn get_wait_screen_metadata( | PaymentType::BriVa | PaymentType::CimbVa | PaymentType::DanamonVa - | PaymentType::MandiriVa => Ok(None), + | PaymentType::MandiriVa + | PaymentType::PaySafeCard => Ok(None), } } @@ -2755,7 +2822,8 @@ pub fn get_present_to_shopper_metadata( | PaymentType::Samsungpay | PaymentType::Twint | PaymentType::Vipps - | PaymentType::Swish => Ok(None), + | PaymentType::Swish + | PaymentType::PaySafeCard => Ok(None), } } diff --git a/crates/router/src/core/payments/helpers.rs b/crates/router/src/core/payments/helpers.rs index 468cf11030..f37e940fb0 100644 --- a/crates/router/src/core/payments/helpers.rs +++ b/crates/router/src/core/payments/helpers.rs @@ -1415,7 +1415,6 @@ pub(crate) fn validate_payment_method_fields_present( }) }, )?; - utils::when( req.payment_method.is_some() && req.payment_method_type.is_some(), || { @@ -1571,7 +1570,10 @@ pub fn validate_payment_method_type_against_payment_method( | api_enums::PaymentMethodType::Indomaret | api_enums::PaymentMethodType::Alfamart ), - api_enums::PaymentMethod::GiftCard => false, + api_enums::PaymentMethod::GiftCard => matches!( + payment_method_type, + api_enums::PaymentMethodType::PaySafeCard + ), } } diff --git a/crates/router/src/types/transformers.rs b/crates/router/src/types/transformers.rs index ef7c3801a0..5e94a1545c 100644 --- a/crates/router/src/types/transformers.rs +++ b/crates/router/src/types/transformers.rs @@ -236,6 +236,7 @@ impl ForeignFrom for api_enums::PaymentMethod { | api_enums::PaymentMethodType::DanamonVa | api_enums::PaymentMethodType::MandiriVa | api_enums::PaymentMethodType::Pix => Self::BankTransfer, + api_enums::PaymentMethodType::PaySafeCard => Self::GiftCard, } } } diff --git a/openapi/openapi_spec.json b/openapi/openapi_spec.json index ec72b900c5..5334bf3d63 100644 --- a/openapi/openapi_spec.json +++ b/openapi/openapi_spec.json @@ -5026,21 +5026,44 @@ "type": "object" }, "GiftCardData": { - "type": "object", - "required": [ - "number", - "cvc" - ], - "properties": { - "number": { - "type": "string", - "description": "The gift card number" + "oneOf": [ + { + "type": "object", + "required": [ + "baby_gift_card" + ], + "properties": { + "baby_gift_card": { + "type": "object", + "required": [ + "number", + "cvc" + ], + "properties": { + "number": { + "type": "string", + "description": "The gift card number" + }, + "cvc": { + "type": "string", + "description": "The card verification code." + } + } + } + } }, - "cvc": { - "type": "string", - "description": "The card verification code." + { + "type": "object", + "required": [ + "pay_safe_card" + ], + "properties": { + "pay_safe_card": { + "type": "object" + } + } } - } + ] }, "GoPayRedirection": { "type": "object" @@ -7691,6 +7714,7 @@ "pay_bright", "paypal", "pix", + "pay_safe_card", "przelewy24", "pse", "red_compra",