diff --git a/crates/common_enums/src/enums.rs b/crates/common_enums/src/enums.rs index 01e3859f2d..21badc9b80 100644 --- a/crates/common_enums/src/enums.rs +++ b/crates/common_enums/src/enums.rs @@ -387,6 +387,226 @@ impl Currency { Self::ZAR => "710", } } + + pub fn is_zero_decimal_currency(self) -> bool { + match self { + Self::JPY | Self::KRW => true, + Self::AED + | Self::ALL + | Self::AMD + | Self::ANG + | Self::ARS + | Self::AUD + | Self::AWG + | Self::AZN + | Self::BBD + | Self::BDT + | Self::BHD + | Self::BMD + | Self::BND + | Self::BOB + | Self::BRL + | Self::BSD + | Self::BWP + | Self::BZD + | Self::CAD + | Self::CHF + | Self::CNY + | Self::COP + | Self::CRC + | Self::CUP + | Self::CZK + | Self::DKK + | Self::DOP + | Self::DZD + | Self::EGP + | Self::ETB + | Self::EUR + | Self::FJD + | Self::GBP + | Self::GHS + | Self::GIP + | Self::GMD + | Self::GTQ + | Self::GYD + | Self::HKD + | Self::HNL + | Self::HRK + | Self::HTG + | Self::HUF + | Self::IDR + | Self::ILS + | Self::INR + | Self::JMD + | Self::JOD + | Self::KES + | Self::KGS + | Self::KHR + | Self::KWD + | Self::KYD + | Self::KZT + | Self::LAK + | Self::LBP + | Self::LKR + | Self::LRD + | Self::LSL + | Self::MAD + | Self::MDL + | Self::MKD + | Self::MMK + | Self::MNT + | Self::MOP + | Self::MUR + | Self::MVR + | Self::MWK + | Self::MXN + | Self::MYR + | Self::NAD + | Self::NGN + | Self::NIO + | Self::NOK + | Self::NPR + | Self::NZD + | Self::OMR + | Self::PEN + | Self::PGK + | Self::PHP + | Self::PKR + | Self::PLN + | Self::QAR + | Self::RON + | Self::RUB + | Self::SAR + | Self::SCR + | Self::SEK + | Self::SGD + | Self::SLL + | Self::SOS + | Self::SSP + | Self::SVC + | Self::SZL + | Self::THB + | Self::TRY + | Self::TTD + | Self::TWD + | Self::TZS + | Self::USD + | Self::UYU + | Self::UZS + | Self::VND + | Self::YER + | Self::ZAR => false, + } + } + + pub fn is_three_decimal_currency(self) -> bool { + match self { + Self::BHD | Self::JOD | Self::KWD | Self::OMR => true, + Self::AED + | Self::ALL + | Self::AMD + | Self::ANG + | Self::ARS + | Self::AUD + | Self::AWG + | Self::AZN + | Self::BBD + | Self::BDT + | Self::BMD + | Self::BND + | Self::BOB + | Self::BRL + | Self::BSD + | Self::BWP + | Self::BZD + | Self::CAD + | Self::CHF + | Self::CNY + | Self::COP + | Self::CRC + | Self::CUP + | Self::CZK + | Self::DKK + | Self::DOP + | Self::DZD + | Self::EGP + | Self::ETB + | Self::EUR + | Self::FJD + | Self::GBP + | Self::GHS + | Self::GIP + | Self::GMD + | Self::GTQ + | Self::GYD + | Self::HKD + | Self::HNL + | Self::HRK + | Self::HTG + | Self::HUF + | Self::IDR + | Self::ILS + | Self::INR + | Self::JMD + | Self::JPY + | Self::KES + | Self::KGS + | Self::KHR + | Self::KRW + | Self::KYD + | Self::KZT + | Self::LAK + | Self::LBP + | Self::LKR + | Self::LRD + | Self::LSL + | Self::MAD + | Self::MDL + | Self::MKD + | Self::MMK + | Self::MNT + | Self::MOP + | Self::MUR + | Self::MVR + | Self::MWK + | Self::MXN + | Self::MYR + | Self::NAD + | Self::NGN + | Self::NIO + | Self::NOK + | Self::NPR + | Self::NZD + | Self::PEN + | Self::PGK + | Self::PHP + | Self::PKR + | Self::PLN + | Self::QAR + | Self::RON + | Self::RUB + | Self::SAR + | Self::SCR + | Self::SEK + | Self::SGD + | Self::SLL + | Self::SOS + | Self::SSP + | Self::SVC + | Self::SZL + | Self::THB + | Self::TRY + | Self::TTD + | Self::TWD + | Self::TZS + | Self::USD + | Self::UYU + | Self::UZS + | Self::VND + | Self::YER + | Self::ZAR => false, + } + } } #[derive( diff --git a/crates/router/src/connector/paypal/transformers.rs b/crates/router/src/connector/paypal/transformers.rs index 855199cb3c..32824e3cb8 100644 --- a/crates/router/src/connector/paypal/transformers.rs +++ b/crates/router/src/connector/paypal/transformers.rs @@ -5,7 +5,7 @@ use url::Url; use crate::{ connector::utils::{ - to_connector_meta, AccessTokenRequestInfo, AddressDetailsData, CardData, + self, to_connector_meta, AccessTokenRequestInfo, AddressDetailsData, CardData, PaymentsAuthorizeRequestData, }, core::errors, @@ -105,7 +105,10 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for PaypalPaymentsRequest { }; let amount = OrderAmount { currency_code: item.request.currency, - value: item.request.amount.to_string(), + value: utils::to_currency_base_unit_with_zero_decimal_check( + item.request.amount, + item.request.currency, + )?, }; let reference_id = item.attempt_id.clone(); @@ -135,7 +138,10 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for PaypalPaymentsRequest { let intent = PaypalPaymentIntent::Capture; let amount = OrderAmount { currency_code: item.request.currency, - value: item.request.amount.to_string(), + value: utils::to_currency_base_unit_with_zero_decimal_check( + item.request.amount, + item.request.currency, + )?, }; let reference_id = item.attempt_id.clone(); let purchase_units = vec![PurchaseUnitRequest { @@ -500,7 +506,10 @@ impl TryFrom<&types::PaymentsCaptureRouterData> for PaypalPaymentsCaptureRequest fn try_from(item: &types::PaymentsCaptureRouterData) -> Result { let amount = OrderAmount { currency_code: item.request.currency, - value: item.request.amount_to_capture.to_string(), + value: utils::to_currency_base_unit_with_zero_decimal_check( + item.request.amount_to_capture, + item.request.currency, + )?, }; Ok(Self { amount, @@ -636,7 +645,10 @@ impl TryFrom<&types::RefundsRouterData> for PaypalRefundRequest { Ok(Self { amount: OrderAmount { currency_code: item.request.currency, - value: item.request.refund_amount.to_string(), + value: utils::to_currency_base_unit_with_zero_decimal_check( + item.request.refund_amount, + item.request.currency, + )?, }, }) } diff --git a/crates/router/src/connector/utils.rs b/crates/router/src/connector/utils.rs index 66c980d2d3..f9c73255d6 100644 --- a/crates/router/src/connector/utils.rs +++ b/crates/router/src/connector/utils.rs @@ -928,6 +928,14 @@ pub fn to_currency_base_unit( .change_context(errors::ConnectorError::RequestEncodingFailed) } +pub fn to_currency_base_unit_with_zero_decimal_check( + amount: i64, + currency: diesel_models::enums::Currency, +) -> Result> { + utils::to_currency_base_unit_with_zero_decimal_check(amount, currency) + .change_context(errors::ConnectorError::RequestEncodingFailed) +} + pub fn to_currency_base_unit_asf64( amount: i64, currency: diesel_models::enums::Currency, diff --git a/crates/router/src/utils.rs b/crates/router/src/utils.rs index 371a8ca564..763062fddf 100644 --- a/crates/router/src/utils.rs +++ b/crates/router/src/utils.rs @@ -138,6 +138,21 @@ pub fn to_currency_base_unit( Ok(format!("{amount_f64:.2}")) } +/// Convert the amount to its base denomination based on Currency and check for zero decimal currency and return String +/// Paypal Connector accepts Zero and Two decimal currency but not three decimal and it should be updated as required for 3 decimal currencies. +/// Paypal Ref - https://developer.paypal.com/docs/reports/reference/paypal-supported-currencies/ +pub fn to_currency_base_unit_with_zero_decimal_check( + amount: i64, + currency: diesel_models::enums::Currency, +) -> Result> { + let amount_f64 = to_currency_base_unit_asf64(amount, currency)?; + if currency.is_zero_decimal_currency() { + Ok(amount_f64.to_string()) + } else { + Ok(format!("{amount_f64:.2}")) + } +} + /// Convert the amount to its base denomination based on Currency and return f64 pub fn to_currency_base_unit_asf64( amount: i64, @@ -149,13 +164,12 @@ pub fn to_currency_base_unit_asf64( }, )?; let amount_f64 = f64::from(amount_u32); - let amount = match currency { - diesel_models::enums::Currency::JPY | diesel_models::enums::Currency::KRW => amount_f64, - diesel_models::enums::Currency::BHD - | diesel_models::enums::Currency::JOD - | diesel_models::enums::Currency::KWD - | diesel_models::enums::Currency::OMR => amount_f64 / 1000.00, - _ => amount_f64 / 100.00, + let amount = if currency.is_zero_decimal_currency() { + amount_f64 + } else if currency.is_three_decimal_currency() { + amount_f64 / 1000.00 + } else { + amount_f64 / 100.00 }; Ok(amount) }