Skip to content

Commit

Permalink
refactor(connector): add amount conversion framework to cybersource (#…
Browse files Browse the repository at this point in the history
…6335)

Co-authored-by: DEEPANSHU BANSAL <[email protected]>
  • Loading branch information
gauravghodinde and deepanshu-iiitu authored Nov 4, 2024
1 parent 19cf0f7 commit f34072b
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 74 deletions.
7 changes: 6 additions & 1 deletion crates/common_utils/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -568,7 +568,7 @@ pub struct StringMajorUnit(String);

impl StringMajorUnit {
/// forms a new major unit from amount
fn new(value: String) -> Self {
pub fn new(value: String) -> Self {
Self(value)
}

Expand Down Expand Up @@ -600,6 +600,11 @@ impl StringMajorUnit {
Self("0".to_string())
}

/// forms a new StringMajorUnit default unit i.e zero
pub fn zero() -> Self {
Self("0".to_string())
}

/// Get string amount from struct to be removed in future
pub fn get_amount_as_string(&self) -> String {
self.0.clone()
Expand Down
125 changes: 69 additions & 56 deletions crates/router/src/connector/cybersource.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
pub mod transformers;

use std::fmt::Debug;

use base64::Engine;
use common_utils::request::RequestContent;
use common_utils::{
request::RequestContent,
types::{AmountConvertor, MinorUnit, StringMajorUnit, StringMajorUnitForConnector},
};
use diesel_models::enums;
use error_stack::{report, Report, ResultExt};
use masking::{ExposeInterface, PeekInterface};
Expand All @@ -12,7 +13,7 @@ use time::OffsetDateTime;
use transformers as cybersource;
use url::Url;

use super::utils::{PaymentsAuthorizeRequestData, RouterData};
use super::utils::{convert_amount, PaymentsAuthorizeRequestData, RouterData};
use crate::{
configs::settings,
connector::{
Expand All @@ -36,9 +37,18 @@ use crate::{
utils::BytesExt,
};

#[derive(Debug, Clone)]
pub struct Cybersource;
#[derive(Clone)]
pub struct Cybersource {
amount_converter: &'static (dyn AmountConvertor<Output = StringMajorUnit> + Sync),
}

impl Cybersource {
pub fn new() -> &'static Self {
&Self {
amount_converter: &StringMajorUnitForConnector,
}
}
}
impl Cybersource {
pub fn generate_digest(&self, payload: &[u8]) -> String {
let payload_digest = digest::digest(&digest::SHA256, payload);
Expand Down Expand Up @@ -617,20 +627,20 @@ impl
req: &types::PaymentsPreProcessingRouterData,
_connectors: &settings::Connectors,
) -> CustomResult<RequestContent, errors::ConnectorError> {
let connector_router_data = cybersource::CybersourceRouterData::try_from((
&self.get_currency_unit(),
let minor_amount =
req.request
.currency
.minor_amount
.ok_or(errors::ConnectorError::MissingRequiredField {
field_name: "currency",
})?,
field_name: "minor_amount",
})?;
let currency =
req.request
.amount
.currency
.ok_or(errors::ConnectorError::MissingRequiredField {
field_name: "amount",
})?,
req,
))?;
field_name: "currency",
})?;
let amount = convert_amount(self.amount_converter, minor_amount, currency)?;
let connector_router_data = cybersource::CybersourceRouterData::from((amount, req));
let connector_req =
cybersource::CybersourcePreProcessingRequest::try_from(&connector_router_data)?;
Ok(RequestContent::Json(Box::new(connector_req)))
Expand Down Expand Up @@ -718,12 +728,12 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
req: &types::PaymentsCaptureRouterData,
_connectors: &settings::Connectors,
) -> CustomResult<RequestContent, errors::ConnectorError> {
let connector_router_data = cybersource::CybersourceRouterData::try_from((
&self.get_currency_unit(),
let amount = convert_amount(
self.amount_converter,
req.request.minor_amount_to_capture,
req.request.currency,
req.request.amount_to_capture,
req,
))?;
)?;
let connector_router_data = cybersource::CybersourceRouterData::from((amount, req));
let connector_req =
cybersource::CybersourcePaymentsCaptureRequest::try_from(&connector_router_data)?;
Ok(RequestContent::Json(Box::new(connector_req)))
Expand Down Expand Up @@ -922,12 +932,12 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
req: &types::PaymentsAuthorizeRouterData,
_connectors: &settings::Connectors,
) -> CustomResult<RequestContent, errors::ConnectorError> {
let connector_router_data = cybersource::CybersourceRouterData::try_from((
&self.get_currency_unit(),
let amount = convert_amount(
self.amount_converter,
req.request.minor_amount,
req.request.currency,
req.request.amount,
req,
))?;
)?;
let connector_router_data = cybersource::CybersourceRouterData::from((amount, req));
if req.is_three_ds()
&& req.request.is_card()
&& (req.request.connector_mandate_id().is_none()
Expand Down Expand Up @@ -1068,12 +1078,12 @@ impl ConnectorIntegration<api::PoFulfill, types::PayoutsData, types::PayoutsResp
req: &types::PayoutsRouterData<api::PoFulfill>,
_connectors: &settings::Connectors,
) -> CustomResult<RequestContent, errors::ConnectorError> {
let connector_router_data = cybersource::CybersourceRouterData::try_from((
&self.get_currency_unit(),
let amount = convert_amount(
self.amount_converter,
req.request.minor_amount,
req.request.destination_currency,
req.request.amount,
req,
))?;
)?;
let connector_router_data = cybersource::CybersourceRouterData::from((amount, req));
let connector_req =
cybersource::CybersourcePayoutFulfillRequest::try_from(&connector_router_data)?;
Ok(RequestContent::Json(Box::new(connector_req)))
Expand Down Expand Up @@ -1193,12 +1203,12 @@ impl
req: &types::PaymentsCompleteAuthorizeRouterData,
_connectors: &settings::Connectors,
) -> CustomResult<RequestContent, errors::ConnectorError> {
let connector_router_data = cybersource::CybersourceRouterData::try_from((
&self.get_currency_unit(),
let amount = convert_amount(
self.amount_converter,
req.request.minor_amount,
req.request.currency,
req.request.amount,
req,
))?;
)?;
let connector_router_data = cybersource::CybersourceRouterData::from((amount, req));
let connector_req =
cybersource::CybersourcePaymentsRequest::try_from(&connector_router_data)?;
Ok(RequestContent::Json(Box::new(connector_req)))
Expand Down Expand Up @@ -1317,20 +1327,21 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR
req: &types::PaymentsCancelRouterData,
_connectors: &settings::Connectors,
) -> CustomResult<RequestContent, errors::ConnectorError> {
let connector_router_data = cybersource::CybersourceRouterData::try_from((
&self.get_currency_unit(),
let minor_amount =
req.request
.currency
.minor_amount
.ok_or(errors::ConnectorError::MissingRequiredField {
field_name: "Currency",
})?,
field_name: "Amount",
})?;
let currency =
req.request
.amount
.currency
.ok_or(errors::ConnectorError::MissingRequiredField {
field_name: "Amount",
})?,
req,
))?;
field_name: "Currency",
})?;
let amount = convert_amount(self.amount_converter, minor_amount, currency)?;
let connector_router_data = cybersource::CybersourceRouterData::from((amount, req));

let connector_req = cybersource::CybersourceVoidRequest::try_from(&connector_router_data)?;

Ok(RequestContent::Json(Box::new(connector_req)))
Expand Down Expand Up @@ -1443,12 +1454,12 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
req: &types::RefundExecuteRouterData,
_connectors: &settings::Connectors,
) -> CustomResult<RequestContent, errors::ConnectorError> {
let connector_router_data = cybersource::CybersourceRouterData::try_from((
&self.get_currency_unit(),
let refund_amount = convert_amount(
self.amount_converter,
req.request.minor_refund_amount,
req.request.currency,
req.request.refund_amount,
req,
))?;
)?;
let connector_router_data = cybersource::CybersourceRouterData::from((refund_amount, req));
let connector_req =
cybersource::CybersourceRefundRequest::try_from(&connector_router_data)?;
Ok(RequestContent::Json(Box::new(connector_req)))
Expand Down Expand Up @@ -1609,12 +1620,14 @@ impl
req: &types::PaymentsIncrementalAuthorizationRouterData,
_connectors: &settings::Connectors,
) -> CustomResult<RequestContent, errors::ConnectorError> {
let connector_router_data = cybersource::CybersourceRouterData::try_from((
&self.get_currency_unit(),
let minor_additional_amount = MinorUnit::new(req.request.additional_amount);
let additional_amount = convert_amount(
self.amount_converter,
minor_additional_amount,
req.request.currency,
req.request.additional_amount,
req,
))?;
)?;
let connector_router_data =
cybersource::CybersourceRouterData::from((additional_amount, req));
let connector_request =
cybersource::CybersourcePaymentsIncrementalAuthorizationRequest::try_from(
&connector_router_data,
Expand Down
25 changes: 10 additions & 15 deletions crates/router/src/connector/cybersource/transformers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use common_enums::FutureUsage;
use common_utils::{
ext_traits::{OptionExt, ValueExt},
pii,
types::SemanticVersion,
types::{SemanticVersion, StringMajorUnit},
};
use error_stack::ResultExt;
use masking::{ExposeInterface, PeekInterface, Secret};
Expand Down Expand Up @@ -41,21 +41,16 @@ use crate::{

#[derive(Debug, Serialize)]
pub struct CybersourceRouterData<T> {
pub amount: String,
pub amount: StringMajorUnit,
pub router_data: T,
}

impl<T> TryFrom<(&api::CurrencyUnit, enums::Currency, i64, T)> for CybersourceRouterData<T> {
type Error = error_stack::Report<errors::ConnectorError>;
fn try_from(
(currency_unit, currency, amount, item): (&api::CurrencyUnit, enums::Currency, i64, T),
) -> Result<Self, Self::Error> {
// This conversion function is used at different places in the file, if updating this, keep a check for those
let amount = utils::get_amount_as_string(currency_unit, amount, currency)?;
Ok(Self {
impl<T> From<(StringMajorUnit, T)> for CybersourceRouterData<T> {
fn from((amount, router_data): (StringMajorUnit, T)) -> Self {
Self {
amount,
router_data: item,
})
router_data,
}
}
}

Expand Down Expand Up @@ -93,7 +88,7 @@ impl TryFrom<&types::SetupMandateRouterData> for CybersourceZeroMandateRequest {

let order_information = OrderInformationWithBill {
amount_details: Amount {
total_amount: "0".to_string(),
total_amount: StringMajorUnit::new("0".to_string()),
currency: item.request.currency,
},
bill_to: Some(bill_to),
Expand Down Expand Up @@ -525,14 +520,14 @@ pub struct OrderInformation {
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Amount {
total_amount: String,
total_amount: StringMajorUnit,
currency: api_models::enums::Currency,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct AdditionalAmount {
additional_amount: String,
additional_amount: StringMajorUnit,
currency: String,
}

Expand Down
2 changes: 1 addition & 1 deletion crates/router/src/types/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ impl ConnectorData {
Ok(ConnectorEnum::Old(Box::new(connector::Cryptopay::new())))
}
enums::Connector::Cybersource => {
Ok(ConnectorEnum::Old(Box::new(&connector::Cybersource)))
Ok(ConnectorEnum::Old(Box::new(connector::Cybersource::new())))
}
enums::Connector::Datatrans => {
Ok(ConnectorEnum::Old(Box::new(connector::Datatrans::new())))
Expand Down
2 changes: 1 addition & 1 deletion crates/router/tests/connectors/cybersource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ impl utils::Connector for Cybersource {
fn get_data(&self) -> api::ConnectorData {
use router::connector::Cybersource;
utils::construct_connector_data_old(
Box::new(&Cybersource),
Box::new(Cybersource::new()),
types::Connector::Cybersource,
api::GetToken::Connector,
None,
Expand Down

0 comments on commit f34072b

Please sign in to comment.