From 90765bece1b12b208192e7ae4d54f4c70a301cea Mon Sep 17 00:00:00 2001 From: Gaurav Ghodinde <65962770+gauravghodinde@users.noreply.github.com> Date: Fri, 25 Oct 2024 16:27:11 +0530 Subject: [PATCH] refactor(connector): add amount conversion framework to tsys (#6282) Co-authored-by: DEEPANSHU BANSAL <41580413+deepanshu-iiitu@users.noreply.github.com> --- .../src/connectors/tsys.rs | 43 +++++++++++++--- .../src/connectors/tsys/transformers.rs | 49 +++++++++++++------ crates/router/src/types/api.rs | 2 +- crates/router/tests/connectors/tsys.rs | 2 +- 4 files changed, 72 insertions(+), 24 deletions(-) diff --git a/crates/hyperswitch_connectors/src/connectors/tsys.rs b/crates/hyperswitch_connectors/src/connectors/tsys.rs index ec53a99316..25b47981de 100644 --- a/crates/hyperswitch_connectors/src/connectors/tsys.rs +++ b/crates/hyperswitch_connectors/src/connectors/tsys.rs @@ -1,12 +1,11 @@ pub mod transformers; -use std::fmt::Debug; - use common_enums::enums; use common_utils::{ errors::CustomResult, ext_traits::BytesExt, request::{Method, Request, RequestBuilder, RequestContent}, + types::{AmountConvertor, StringMinorUnit, StringMinorUnitForConnector}, }; use error_stack::{report, ResultExt}; use hyperswitch_domain_models::{ @@ -41,10 +40,18 @@ use hyperswitch_interfaces::{ use transformers as tsys; use crate::{constants::headers, types::ResponseRouterData, utils}; +#[derive(Clone)] +pub struct Tsys { + amount_converter: &'static (dyn AmountConvertor + Sync), +} -#[derive(Debug, Clone)] -pub struct Tsys; - +impl Tsys { + pub fn new() -> &'static Self { + &Self { + amount_converter: &StringMinorUnitForConnector, + } + } +} impl api::Payment for Tsys {} impl api::PaymentSession for Tsys {} impl api::ConnectorAccessToken for Tsys {} @@ -156,7 +163,14 @@ impl ConnectorIntegration CustomResult { - let connector_req = tsys::TsysPaymentsRequest::try_from(req)?; + let amount = utils::convert_amount( + self.amount_converter, + req.request.minor_amount, + req.request.currency, + )?; + let connector_router_data = tsys::TsysRouterData::from((amount, req)); + let connector_req: transformers::TsysPaymentsRequest = + tsys::TsysPaymentsRequest::try_from(&connector_router_data)?; Ok(RequestContent::Json(Box::new(connector_req))) } @@ -316,7 +330,13 @@ impl ConnectorIntegration fo req: &PaymentsCaptureRouterData, _connectors: &Connectors, ) -> CustomResult { - let connector_req = tsys::TsysPaymentsCaptureRequest::try_from(req)?; + let amount = utils::convert_amount( + self.amount_converter, + req.request.minor_amount_to_capture, + req.request.currency, + )?; + let connector_router_data = tsys::TsysRouterData::from((amount, req)); + let connector_req = tsys::TsysPaymentsCaptureRequest::try_from(&connector_router_data)?; Ok(RequestContent::Json(Box::new(connector_req))) } @@ -473,7 +493,14 @@ impl ConnectorIntegration for Tsys { req: &RefundsRouterData, _connectors: &Connectors, ) -> CustomResult { - let connector_req = tsys::TsysRefundRequest::try_from(req)?; + let amount = utils::convert_amount( + self.amount_converter, + req.request.minor_refund_amount, + req.request.currency, + )?; + let connector_router_data = tsys::TsysRouterData::from((amount, req)); + + let connector_req = tsys::TsysRefundRequest::try_from(&connector_router_data)?; Ok(RequestContent::Json(Box::new(connector_req))) } diff --git a/crates/hyperswitch_connectors/src/connectors/tsys/transformers.rs b/crates/hyperswitch_connectors/src/connectors/tsys/transformers.rs index fc485e6572..c867adaa23 100644 --- a/crates/hyperswitch_connectors/src/connectors/tsys/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/tsys/transformers.rs @@ -1,4 +1,5 @@ use common_enums::enums; +use common_utils::types::StringMinorUnit; use error_stack::ResultExt; use hyperswitch_domain_models::{ payment_method_data::PaymentMethodData, @@ -7,13 +8,26 @@ use hyperswitch_domain_models::{ router_request_types::ResponseId, router_response_types::{PaymentsResponseData, RefundsResponseData}, types::{ - self, PaymentsCancelRouterData, PaymentsCaptureRouterData, PaymentsSyncRouterData, - RefundSyncRouterData, RefundsRouterData, + self, PaymentsCancelRouterData, PaymentsSyncRouterData, RefundSyncRouterData, + RefundsRouterData, }, }; use hyperswitch_interfaces::errors; use masking::Secret; use serde::{Deserialize, Serialize}; +pub struct TsysRouterData { + pub amount: StringMinorUnit, + pub router_data: T, +} + +impl From<(StringMinorUnit, T)> for TsysRouterData { + fn from((amount, router_data): (StringMinorUnit, T)) -> Self { + Self { + amount, + router_data, + } + } +} use crate::{ types::{RefundsResponseRouterData, ResponseRouterData}, @@ -33,7 +47,7 @@ pub struct TsysPaymentAuthSaleRequest { device_id: Secret, transaction_key: Secret, card_data_source: String, - transaction_amount: String, + transaction_amount: StringMinorUnit, currency_code: enums::Currency, card_number: cards::CardNumber, expiration_date: Secret, @@ -46,9 +60,12 @@ pub struct TsysPaymentAuthSaleRequest { order_number: String, } -impl TryFrom<&types::PaymentsAuthorizeRouterData> for TsysPaymentsRequest { +impl TryFrom<&TsysRouterData<&types::PaymentsAuthorizeRouterData>> for TsysPaymentsRequest { type Error = error_stack::Report; - fn try_from(item: &types::PaymentsAuthorizeRouterData) -> Result { + fn try_from( + item_data: &TsysRouterData<&types::PaymentsAuthorizeRouterData>, + ) -> Result { + let item = item_data.router_data.clone(); match item.request.payment_method_data.clone() { PaymentMethodData::Card(ccard) => { let connector_auth: TsysAuthType = @@ -57,7 +74,7 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for TsysPaymentsRequest { device_id: connector_auth.device_id, transaction_key: connector_auth.transaction_key, card_data_source: "INTERNET".to_string(), - transaction_amount: item.request.amount.to_string(), + transaction_amount: item_data.amount.clone(), currency_code: item.request.currency, card_number: ccard.card_number.clone(), expiration_date: ccard @@ -430,7 +447,7 @@ pub struct TsysCaptureRequest { #[serde(rename = "deviceID")] device_id: Secret, transaction_key: Secret, - transaction_amount: String, + transaction_amount: StringMinorUnit, #[serde(rename = "transactionID")] transaction_id: String, #[serde(rename = "developerID")] @@ -444,16 +461,19 @@ pub struct TsysPaymentsCaptureRequest { capture: TsysCaptureRequest, } -impl TryFrom<&PaymentsCaptureRouterData> for TsysPaymentsCaptureRequest { +impl TryFrom<&TsysRouterData<&types::PaymentsCaptureRouterData>> for TsysPaymentsCaptureRequest { type Error = error_stack::Report; - fn try_from(item: &PaymentsCaptureRouterData) -> Result { + fn try_from( + item_data: &TsysRouterData<&types::PaymentsCaptureRouterData>, + ) -> Result { + let item = item_data.router_data.clone(); let connector_auth: TsysAuthType = TsysAuthType::try_from(&item.connector_auth_type)?; let capture = TsysCaptureRequest { device_id: connector_auth.device_id, transaction_key: connector_auth.transaction_key, transaction_id: item.request.connector_transaction_id.clone(), developer_id: connector_auth.developer_id, - transaction_amount: item.request.amount_to_capture.to_string(), + transaction_amount: item_data.amount.clone(), }; Ok(Self { capture }) } @@ -466,7 +486,7 @@ pub struct TsysReturnRequest { #[serde(rename = "deviceID")] device_id: Secret, transaction_key: Secret, - transaction_amount: String, + transaction_amount: StringMinorUnit, #[serde(rename = "transactionID")] transaction_id: String, } @@ -478,14 +498,15 @@ pub struct TsysRefundRequest { return_request: TsysReturnRequest, } -impl TryFrom<&RefundsRouterData> for TsysRefundRequest { +impl TryFrom<&TsysRouterData<&RefundsRouterData>> for TsysRefundRequest { type Error = error_stack::Report; - fn try_from(item: &RefundsRouterData) -> Result { + fn try_from(item_data: &TsysRouterData<&RefundsRouterData>) -> Result { + let item = item_data.router_data; let connector_auth: TsysAuthType = TsysAuthType::try_from(&item.connector_auth_type)?; let return_request = TsysReturnRequest { device_id: connector_auth.device_id, transaction_key: connector_auth.transaction_key, - transaction_amount: item.request.refund_amount.to_string(), + transaction_amount: item_data.amount.clone(), transaction_id: item.request.connector_transaction_id.clone(), }; Ok(Self { return_request }) diff --git a/crates/router/src/types/api.rs b/crates/router/src/types/api.rs index 434352fa11..198d400b85 100644 --- a/crates/router/src/types/api.rs +++ b/crates/router/src/types/api.rs @@ -507,7 +507,7 @@ impl ConnectorData { enums::Connector::Trustpay => { Ok(ConnectorEnum::Old(Box::new(connector::Trustpay::new()))) } - enums::Connector::Tsys => Ok(ConnectorEnum::Old(Box::new(&connector::Tsys))), + enums::Connector::Tsys => Ok(ConnectorEnum::Old(Box::new(connector::Tsys::new()))), enums::Connector::Volt => Ok(ConnectorEnum::Old(Box::new(connector::Volt::new()))), enums::Connector::Wellsfargo => { diff --git a/crates/router/tests/connectors/tsys.rs b/crates/router/tests/connectors/tsys.rs index 4cda0b479b..6a4843ac2c 100644 --- a/crates/router/tests/connectors/tsys.rs +++ b/crates/router/tests/connectors/tsys.rs @@ -16,7 +16,7 @@ impl utils::Connector for TsysTest { fn get_data(&self) -> types::api::ConnectorData { use router::connector::Tsys; utils::construct_connector_data_old( - Box::new(&Tsys), + Box::new(Tsys::new()), types::Connector::Tsys, types::api::GetToken::Connector, None,