mirror of
				https://github.com/juspay/hyperswitch.git
				synced 2025-10-31 01:57:45 +08:00 
			
		
		
		
	refactor(router): include currency conversion utility functions as Currency methods (#1790)
				
					
				
			This commit is contained in:
		| @ -1,3 +1,5 @@ | |||||||
|  | use std::num::TryFromIntError; | ||||||
|  |  | ||||||
| use router_derive; | use router_derive; | ||||||
| use serde::{Deserialize, Serialize}; | use serde::{Deserialize, Serialize}; | ||||||
| use utoipa::ToSchema; | use utoipa::ToSchema; | ||||||
| @ -289,6 +291,40 @@ pub enum Currency { | |||||||
| } | } | ||||||
|  |  | ||||||
| impl Currency { | impl Currency { | ||||||
|  |     /// Convert the amount to its base denomination based on Currency and return String | ||||||
|  |     pub fn to_currency_base_unit(&self, amount: i64) -> Result<String, TryFromIntError> { | ||||||
|  |         let amount_f64 = self.to_currency_base_unit_asf64(amount)?; | ||||||
|  |         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(&self, amount: i64) -> Result<f64, TryFromIntError> { | ||||||
|  |         let amount_f64: f64 = u32::try_from(amount)?.into(); | ||||||
|  |         let amount = if self.is_zero_decimal_currency() { | ||||||
|  |             amount_f64 | ||||||
|  |         } else if self.is_three_decimal_currency() { | ||||||
|  |             amount_f64 / 1000.00 | ||||||
|  |         } else { | ||||||
|  |             amount_f64 / 100.00 | ||||||
|  |         }; | ||||||
|  |         Ok(amount) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /// 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( | ||||||
|  |         &self, | ||||||
|  |         amount: i64, | ||||||
|  |     ) -> Result<String, TryFromIntError> { | ||||||
|  |         let amount_f64 = self.to_currency_base_unit_asf64(amount)?; | ||||||
|  |         if self.is_zero_decimal_currency() { | ||||||
|  |             Ok(amount_f64.to_string()) | ||||||
|  |         } else { | ||||||
|  |             Ok(format!("{amount_f64:.2}")) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     pub fn iso_4217(&self) -> &'static str { |     pub fn iso_4217(&self) -> &'static str { | ||||||
|         match *self { |         match *self { | ||||||
|             Self::AED => "784", |             Self::AED => "784", | ||||||
|  | |||||||
| @ -21,7 +21,7 @@ use crate::{ | |||||||
|     core::errors::{self, CustomResult}, |     core::errors::{self, CustomResult}, | ||||||
|     pii::PeekInterface, |     pii::PeekInterface, | ||||||
|     types::{self, api, transformers::ForeignTryFrom, PaymentsCancelData, ResponseId}, |     types::{self, api, transformers::ForeignTryFrom, PaymentsCancelData, ResponseId}, | ||||||
|     utils::{self, OptionExt, ValueExt}, |     utils::{OptionExt, ValueExt}, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| pub fn missing_field_err( | pub fn missing_field_err( | ||||||
| @ -924,7 +924,9 @@ pub fn to_currency_base_unit( | |||||||
|     amount: i64, |     amount: i64, | ||||||
|     currency: diesel_models::enums::Currency, |     currency: diesel_models::enums::Currency, | ||||||
| ) -> Result<String, error_stack::Report<errors::ConnectorError>> { | ) -> Result<String, error_stack::Report<errors::ConnectorError>> { | ||||||
|     utils::to_currency_base_unit(amount, currency) |     currency | ||||||
|  |         .to_currency_base_unit(amount) | ||||||
|  |         .into_report() | ||||||
|         .change_context(errors::ConnectorError::RequestEncodingFailed) |         .change_context(errors::ConnectorError::RequestEncodingFailed) | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -932,7 +934,9 @@ pub fn to_currency_base_unit_with_zero_decimal_check( | |||||||
|     amount: i64, |     amount: i64, | ||||||
|     currency: diesel_models::enums::Currency, |     currency: diesel_models::enums::Currency, | ||||||
| ) -> Result<String, error_stack::Report<errors::ConnectorError>> { | ) -> Result<String, error_stack::Report<errors::ConnectorError>> { | ||||||
|     utils::to_currency_base_unit_with_zero_decimal_check(amount, currency) |     currency | ||||||
|  |         .to_currency_base_unit_with_zero_decimal_check(amount) | ||||||
|  |         .into_report() | ||||||
|         .change_context(errors::ConnectorError::RequestEncodingFailed) |         .change_context(errors::ConnectorError::RequestEncodingFailed) | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -940,7 +944,9 @@ pub fn to_currency_base_unit_asf64( | |||||||
|     amount: i64, |     amount: i64, | ||||||
|     currency: diesel_models::enums::Currency, |     currency: diesel_models::enums::Currency, | ||||||
| ) -> Result<f64, error_stack::Report<errors::ConnectorError>> { | ) -> Result<f64, error_stack::Report<errors::ConnectorError>> { | ||||||
|     utils::to_currency_base_unit_asf64(amount, currency) |     currency | ||||||
|  |         .to_currency_base_unit_asf64(amount) | ||||||
|  |         .into_report() | ||||||
|         .change_context(errors::ConnectorError::RequestEncodingFailed) |         .change_context(errors::ConnectorError::RequestEncodingFailed) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | |||||||
| @ -1,11 +1,10 @@ | |||||||
| use api_models::payments as payment_types; | use api_models::payments as payment_types; | ||||||
| use async_trait::async_trait; | use async_trait::async_trait; | ||||||
| use common_utils::ext_traits::ByteSliceExt; | use common_utils::ext_traits::ByteSliceExt; | ||||||
| use error_stack::{Report, ResultExt}; | use error_stack::{IntoReport, Report, ResultExt}; | ||||||
|  |  | ||||||
| use super::{ConstructFlowSpecificData, Feature}; | use super::{ConstructFlowSpecificData, Feature}; | ||||||
| use crate::{ | use crate::{ | ||||||
|     connector, |  | ||||||
|     core::{ |     core::{ | ||||||
|         errors::{self, ConnectorErrorExt, RouterResult}, |         errors::{self, ConnectorErrorExt, RouterResult}, | ||||||
|         payments::{self, access_token, transformers, PaymentData}, |         payments::{self, access_token, transformers, PaymentData}, | ||||||
| @ -172,13 +171,14 @@ async fn create_applepay_session_token( | |||||||
|         let amount_info = payment_types::AmountInfo { |         let amount_info = payment_types::AmountInfo { | ||||||
|             label: applepay_metadata.data.payment_request_data.label, |             label: applepay_metadata.data.payment_request_data.label, | ||||||
|             total_type: Some("final".to_string()), |             total_type: Some("final".to_string()), | ||||||
|             amount: connector::utils::to_currency_base_unit( |             amount: router_data | ||||||
|                 router_data.request.amount, |                 .request | ||||||
|                 router_data.request.currency, |                 .currency | ||||||
|             ) |                 .to_currency_base_unit(router_data.request.amount) | ||||||
|             .change_context(errors::ApiErrorResponse::PreconditionFailed { |                 .into_report() | ||||||
|                 message: "Failed to convert currency to base unit".to_string(), |                 .change_context(errors::ApiErrorResponse::PreconditionFailed { | ||||||
|             })?, |                     message: "Failed to convert currency to base unit".to_string(), | ||||||
|  |                 })?, | ||||||
|         }; |         }; | ||||||
|  |  | ||||||
|         let applepay_payment_request = payment_types::ApplePayPaymentRequest { |         let applepay_payment_request = payment_types::ApplePayPaymentRequest { | ||||||
| @ -324,16 +324,17 @@ fn create_gpay_session_token( | |||||||
|             country_code: session_data.country.unwrap_or_default(), |             country_code: session_data.country.unwrap_or_default(), | ||||||
|             currency_code: router_data.request.currency, |             currency_code: router_data.request.currency, | ||||||
|             total_price_status: "Final".to_string(), |             total_price_status: "Final".to_string(), | ||||||
|             total_price: utils::to_currency_base_unit( |             total_price: router_data | ||||||
|                 router_data.request.amount, |                 .request | ||||||
|                 router_data.request.currency, |                 .currency | ||||||
|             ) |                 .to_currency_base_unit(router_data.request.amount) | ||||||
|             .attach_printable( |                 .into_report() | ||||||
|                 "Cannot convert given amount to base currency denomination".to_string(), |                 .attach_printable( | ||||||
|             ) |                     "Cannot convert given amount to base currency denomination".to_string(), | ||||||
|             .change_context(errors::ApiErrorResponse::InvalidDataValue { |                 ) | ||||||
|                 field_name: "amount", |                 .change_context(errors::ApiErrorResponse::InvalidDataValue { | ||||||
|             })?, |                     field_name: "amount", | ||||||
|  |                 })?, | ||||||
|         }; |         }; | ||||||
|  |  | ||||||
|         Ok(types::PaymentsSessionRouterData { |         Ok(types::PaymentsSessionRouterData { | ||||||
|  | |||||||
| @ -2,7 +2,7 @@ use std::{fmt::Debug, marker::PhantomData}; | |||||||
|  |  | ||||||
| use common_utils::fp_utils; | use common_utils::fp_utils; | ||||||
| use diesel_models::{ephemeral_key, payment_attempt::PaymentListFilters}; | use diesel_models::{ephemeral_key, payment_attempt::PaymentListFilters}; | ||||||
| use error_stack::ResultExt; | use error_stack::{IntoReport, ResultExt}; | ||||||
| use router_env::{instrument, tracing}; | use router_env::{instrument, tracing}; | ||||||
|  |  | ||||||
| use super::{flows::Feature, PaymentAddress, PaymentData}; | use super::{flows::Feature, PaymentAddress, PaymentData}; | ||||||
| @ -21,7 +21,7 @@ use crate::{ | |||||||
|         storage::{self, enums}, |         storage::{self, enums}, | ||||||
|         transformers::{ForeignFrom, ForeignInto}, |         transformers::{ForeignFrom, ForeignInto}, | ||||||
|     }, |     }, | ||||||
|     utils::{self, OptionExt, ValueExt}, |     utils::{OptionExt, ValueExt}, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #[instrument(skip_all)] | #[instrument(skip_all)] | ||||||
| @ -303,11 +303,12 @@ where | |||||||
|         .currency |         .currency | ||||||
|         .as_ref() |         .as_ref() | ||||||
|         .get_required_value("currency")?; |         .get_required_value("currency")?; | ||||||
|     let amount = utils::to_currency_base_unit(payment_attempt.amount, *currency).change_context( |     let amount = currency | ||||||
|         errors::ApiErrorResponse::InvalidDataValue { |         .to_currency_base_unit(payment_attempt.amount) | ||||||
|  |         .into_report() | ||||||
|  |         .change_context(errors::ApiErrorResponse::InvalidDataValue { | ||||||
|             field_name: "amount", |             field_name: "amount", | ||||||
|         }, |         })?; | ||||||
|     )?; |  | ||||||
|     let mandate_id = payment_attempt.mandate_id.clone(); |     let mandate_id = payment_attempt.mandate_id.clone(); | ||||||
|     let refunds_response = if refunds.is_empty() { |     let refunds_response = if refunds.is_empty() { | ||||||
|         None |         None | ||||||
|  | |||||||
| @ -129,51 +129,6 @@ impl<E> ConnectorResponseExt | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| /// Convert the amount to its base denomination based on Currency and return String |  | ||||||
| pub fn to_currency_base_unit( |  | ||||||
|     amount: i64, |  | ||||||
|     currency: diesel_models::enums::Currency, |  | ||||||
| ) -> Result<String, error_stack::Report<errors::ValidationError>> { |  | ||||||
|     let amount_f64 = to_currency_base_unit_asf64(amount, currency)?; |  | ||||||
|     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<String, error_stack::Report<errors::ValidationError>> { |  | ||||||
|     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, |  | ||||||
|     currency: diesel_models::enums::Currency, |  | ||||||
| ) -> Result<f64, error_stack::Report<errors::ValidationError>> { |  | ||||||
|     let amount_u32 = u32::try_from(amount).into_report().change_context( |  | ||||||
|         errors::ValidationError::InvalidValue { |  | ||||||
|             message: amount.to_string(), |  | ||||||
|         }, |  | ||||||
|     )?; |  | ||||||
|     let amount_f64 = f64::from(amount_u32); |  | ||||||
|     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) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| #[inline] | #[inline] | ||||||
| pub fn get_payment_attempt_id(payment_id: impl std::fmt::Display, attempt_count: i16) -> String { | pub fn get_payment_attempt_id(payment_id: impl std::fmt::Display, attempt_count: i16) -> String { | ||||||
|     format!("{payment_id}_{attempt_count}") |     format!("{payment_id}_{attempt_count}") | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 udev
					udev