From adb9b11f69ee4ab2f79af83aa5124b994840d9a0 Mon Sep 17 00:00:00 2001 From: DEEPANSHU BANSAL <41580413+deepanshu-iiitu@users.noreply.github.com> Date: Mon, 10 Jun 2024 17:19:44 +0530 Subject: [PATCH] refactor(connector): [CRYPTOPAY] amount conversion framework added (#4928) Co-authored-by: Sahkal Poddar Co-authored-by: Deepanshu Bansal --- crates/router/src/connector/cryptopay.rs | 49 ++++++++++++----- .../src/connector/cryptopay/transformers.rs | 54 +++++++------------ crates/router/src/types/api.rs | 2 +- crates/router/tests/connectors/cryptopay.rs | 2 +- 4 files changed, 59 insertions(+), 48 deletions(-) diff --git a/crates/router/src/connector/cryptopay.rs b/crates/router/src/connector/cryptopay.rs index f7d137eff2..a3e0844842 100644 --- a/crates/router/src/connector/cryptopay.rs +++ b/crates/router/src/connector/cryptopay.rs @@ -1,13 +1,12 @@ pub mod transformers; -use std::fmt::Debug; - use base64::Engine; use common_utils::{ crypto::{self, GenerateDigest, SignMessage}, date_time, ext_traits::ByteSliceExt, request::RequestContent, + types::{AmountConvertor, StringMajorUnit, StringMajorUnitForConnector}, }; use error_stack::ResultExt; use hex::encode; @@ -36,8 +35,18 @@ use crate::{ utils::BytesExt, }; -#[derive(Debug, Clone)] -pub struct Cryptopay; +#[derive(Clone)] +pub struct Cryptopay { + amount_converter: &'static (dyn AmountConvertor + Sync), +} + +impl Cryptopay { + pub fn new() -> &'static Self { + &Self { + amount_converter: &StringMajorUnitForConnector, + } + } +} impl api::Payment for Cryptopay {} impl api::PaymentSession for Cryptopay {} @@ -123,7 +132,7 @@ where (headers::DATE.to_string(), date.into()), ( headers::CONTENT_TYPE.to_string(), - Self.get_content_type().to_string().into(), + self.get_content_type().to_string().into(), ), ]; Ok(headers) @@ -244,12 +253,12 @@ impl ConnectorIntegration CustomResult { - let connector_router_data = cryptopay::CryptopayRouterData::try_from(( - &self.get_currency_unit(), + let amount = utils::convert_amount( + self.amount_converter, + req.request.minor_amount, req.request.currency, - req.request.amount, - req, - ))?; + )?; + let connector_router_data = cryptopay::CryptopayRouterData::from((amount, req)); let connector_req = cryptopay::CryptopayPaymentsRequest::try_from(&connector_router_data)?; Ok(RequestContent::Json(Box::new(connector_req))) } @@ -288,13 +297,21 @@ impl ConnectorIntegration Some(utils::convert_back( + self.amount_converter, + amount.clone(), + data.request.currency, + )?), + None => None, + }; types::RouterData::foreign_try_from(( types::ResponseRouterData { response, data: data.clone(), http_code: res.status_code, }, - data.request.currency, + capture_amount_in_minor_units, )) } @@ -375,13 +392,21 @@ impl ConnectorIntegration Some(utils::convert_back( + self.amount_converter, + amount.clone(), + data.request.currency, + )?), + None => None, + }; types::RouterData::foreign_try_from(( types::ResponseRouterData { response, data: data.clone(), http_code: res.status_code, }, - data.request.currency, + capture_amount_in_minor_units, )) } diff --git a/crates/router/src/connector/cryptopay/transformers.rs b/crates/router/src/connector/cryptopay/transformers.rs index bcbc9a043a..6c99972784 100644 --- a/crates/router/src/connector/cryptopay/transformers.rs +++ b/crates/router/src/connector/cryptopay/transformers.rs @@ -1,10 +1,11 @@ -use common_utils::pii; -use error_stack::ResultExt; +use common_utils::{ + pii, + types::{MinorUnit, StringMajorUnit}, +}; use masking::Secret; use reqwest::Url; use serde::{Deserialize, Serialize}; -use super::utils as connector_utils; use crate::{ connector::utils::{self, is_payment_failure, CryptoData, PaymentsAuthorizeRequestData}, consts, @@ -15,31 +16,22 @@ use crate::{ #[derive(Debug, Serialize)] pub struct CryptopayRouterData { - pub amount: String, + pub amount: StringMajorUnit, pub router_data: T, } -impl TryFrom<(&types::api::CurrencyUnit, enums::Currency, i64, T)> for CryptopayRouterData { - type Error = error_stack::Report; - fn try_from( - (currency_unit, currency, amount, item): ( - &types::api::CurrencyUnit, - enums::Currency, - i64, - T, - ), - ) -> Result { - let amount = utils::get_amount_as_string(currency_unit, amount, currency)?; - Ok(Self { +impl From<(StringMajorUnit, T)> for CryptopayRouterData { + fn from((amount, item): (StringMajorUnit, T)) -> Self { + Self { amount, router_data: item, - }) + } } } #[derive(Default, Debug, Serialize)] pub struct CryptopayPaymentsRequest { - price_amount: String, + price_amount: StringMajorUnit, price_currency: enums::Currency, pay_currency: String, #[serde(skip_serializing_if = "Option::is_none")] @@ -62,7 +54,7 @@ impl TryFrom<&CryptopayRouterData<&types::PaymentsAuthorizeRouterData>> domain::PaymentMethodData::Crypto(ref cryptodata) => { let pay_currency = cryptodata.get_pay_currency()?; Ok(Self { - price_amount: item.amount.to_owned(), + price_amount: item.amount.clone(), price_currency: item.router_data.request.currency, pay_currency, network: cryptodata.network.to_owned(), @@ -140,20 +132,20 @@ impl From for enums::AttemptStatus { #[derive(Debug, Serialize, Deserialize)] pub struct CryptopayPaymentsResponse { - data: CryptopayPaymentResponseData, + pub data: CryptopayPaymentResponseData, } impl ForeignTryFrom<( types::ResponseRouterData, - diesel_models::enums::Currency, + Option, )> for types::RouterData { type Error = error_stack::Report; fn foreign_try_from( - (item, currency): ( + (item, amount_captured_in_minor_units): ( types::ResponseRouterData, - diesel_models::enums::Currency, + Option, ), ) -> Result { let status = enums::AttemptStatus::from(item.response.data.status.clone()); @@ -196,15 +188,9 @@ impl charge_id: None, }) }; - - match item.response.data.price_amount { - Some(price_amount) => { - let amount_captured = Some( - connector_utils::to_currency_lower_unit(price_amount, currency)? - .parse::() - .change_context(errors::ConnectorError::ParsingFailed)?, - ); - + match amount_captured_in_minor_units { + Some(minor_amount) => { + let amount_captured = Some(minor_amount.get_amount_as_i64()); Ok(Self { status, response, @@ -243,9 +229,9 @@ pub struct CryptopayPaymentResponseData { pub address: Option>, pub network: Option, pub uri: Option, - pub price_amount: Option, + pub price_amount: Option, pub price_currency: Option, - pub pay_amount: Option, + pub pay_amount: Option, pub pay_currency: Option, pub fee: Option, pub fee_currency: Option, diff --git a/crates/router/src/types/api.rs b/crates/router/src/types/api.rs index ee62b2ce55..498da04c6a 100644 --- a/crates/router/src/types/api.rs +++ b/crates/router/src/types/api.rs @@ -329,7 +329,7 @@ impl ConnectorData { enums::Connector::Cashtocode => Ok(Box::new(&connector::Cashtocode)), enums::Connector::Checkout => Ok(Box::new(&connector::Checkout)), enums::Connector::Coinbase => Ok(Box::new(&connector::Coinbase)), - enums::Connector::Cryptopay => Ok(Box::new(&connector::Cryptopay)), + enums::Connector::Cryptopay => Ok(Box::new(connector::Cryptopay::new())), enums::Connector::Cybersource => Ok(Box::new(&connector::Cybersource)), enums::Connector::Dlocal => Ok(Box::new(&connector::Dlocal)), #[cfg(feature = "dummy_connector")] diff --git a/crates/router/tests/connectors/cryptopay.rs b/crates/router/tests/connectors/cryptopay.rs index 20c727756e..988c704249 100644 --- a/crates/router/tests/connectors/cryptopay.rs +++ b/crates/router/tests/connectors/cryptopay.rs @@ -13,7 +13,7 @@ impl utils::Connector for CryptopayTest { fn get_data(&self) -> api::ConnectorData { use router::connector::Cryptopay; api::ConnectorData { - connector: Box::new(&Cryptopay), + connector: Box::new(Cryptopay::new()), connector_name: types::Connector::Cryptopay, get_token: api::GetToken::Connector, merchant_connector_id: None,