Skip to content

Commit 2807622

Browse files
KiranKBRhyperswitch-bot[bot]swangi-kumari
authored
refactor(connector): added amount conversion framework for klarna and change type of amount to MinorUnit for OrderDetailsWithAmount (#4979)
Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Co-authored-by: swangi-kumari <[email protected]> Co-authored-by: Swangi Kumari <[email protected]>
1 parent d58f706 commit 2807622

File tree

21 files changed

+122
-95
lines changed

21 files changed

+122
-95
lines changed

api-reference-v2/openapi_spec.json

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10977,9 +10977,7 @@
1097710977
"minimum": 0
1097810978
},
1097910979
"amount": {
10980-
"type": "integer",
10981-
"format": "int64",
10982-
"description": "the amount per quantity of product"
10980+
"$ref": "#/components/schemas/MinorUnit"
1098310981
},
1098410982
"requires_shipping": {
1098510983
"type": "boolean",

api-reference/openapi_spec.json

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14219,9 +14219,7 @@
1421914219
"minimum": 0
1422014220
},
1422114221
"amount": {
14222-
"type": "integer",
14223-
"format": "int64",
14224-
"description": "the amount per quantity of product"
14222+
"$ref": "#/components/schemas/MinorUnit"
1422514223
},
1422614224
"requires_shipping": {
1422714225
"type": "boolean",

crates/api_models/src/payments.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5080,7 +5080,7 @@ pub struct OrderDetailsWithAmount {
50805080
#[schema(example = 1)]
50815081
pub quantity: u16,
50825082
/// the amount per quantity of product
5083-
pub amount: i64,
5083+
pub amount: MinorUnit,
50845084
// Does the order includes shipping
50855085
pub requires_shipping: Option<bool>,
50865086
/// The image URL of the product

crates/common_utils/src/types.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ pub mod authentication;
77
use std::{
88
borrow::Cow,
99
fmt::Display,
10-
ops::{Add, Sub},
10+
iter::Sum,
11+
ops::{Add, Mul, Sub},
1112
primitive::i64,
1213
str::FromStr,
1314
};
@@ -483,6 +484,20 @@ impl Sub for MinorUnit {
483484
}
484485
}
485486

487+
impl Mul<u16> for MinorUnit {
488+
type Output = Self;
489+
490+
fn mul(self, a2: u16) -> Self::Output {
491+
Self(self.0 * i64::from(a2))
492+
}
493+
}
494+
495+
impl Sum for MinorUnit {
496+
fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
497+
iter.fold(Self(0), |a, b| a + b)
498+
}
499+
}
500+
486501
/// Connector specific types to send
487502
488503
#[derive(Default, Debug, serde::Deserialize, serde::Serialize, Clone, PartialEq)]

crates/hyperswitch_connectors/src/connectors/taxjar.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,11 +190,22 @@ impl ConnectorIntegration<CalculateTax, PaymentsTaxCalculationData, TaxCalculati
190190

191191
let shipping = utils::convert_amount(
192192
self.amount_converter,
193-
req.request.shipping_cost.unwrap_or(MinorUnit::new(0)),
193+
req.request.shipping_cost.unwrap_or(MinorUnit::zero()),
194194
req.request.currency,
195195
)?;
196196

197-
let connector_router_data = taxjar::TaxjarRouterData::from((amount, shipping, req));
197+
let order_amount = utils::convert_amount(
198+
self.amount_converter,
199+
req.request
200+
.order_details
201+
.as_ref()
202+
.map(|details| details.iter().map(|item| item.amount).sum())
203+
.unwrap_or(MinorUnit::zero()),
204+
req.request.currency,
205+
)?;
206+
207+
let connector_router_data =
208+
taxjar::TaxjarRouterData::from((amount, order_amount, shipping, req));
198209
let connector_req = taxjar::TaxjarPaymentsRequest::try_from(&connector_router_data)?;
199210
Ok(RequestContent::Json(Box::new(connector_req)))
200211
}

crates/hyperswitch_connectors/src/connectors/taxjar/transformers.rs

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use hyperswitch_domain_models::{
77
router_response_types::TaxCalculationResponseData,
88
types,
99
};
10-
use hyperswitch_interfaces::{api, errors};
10+
use hyperswitch_interfaces::errors;
1111
use masking::Secret;
1212
use serde::{Deserialize, Serialize};
1313

@@ -18,14 +18,18 @@ use crate::{
1818

1919
pub struct TaxjarRouterData<T> {
2020
pub amount: FloatMajorUnit, // The type of amount that a connector accepts, for example, String, i64, f64, etc.
21+
pub order_amount: FloatMajorUnit,
2122
pub shipping: FloatMajorUnit,
2223
pub router_data: T,
2324
}
2425

25-
impl<T> From<(FloatMajorUnit, FloatMajorUnit, T)> for TaxjarRouterData<T> {
26-
fn from((amount, shipping, item): (FloatMajorUnit, FloatMajorUnit, T)) -> Self {
26+
impl<T> From<(FloatMajorUnit, FloatMajorUnit, FloatMajorUnit, T)> for TaxjarRouterData<T> {
27+
fn from(
28+
(amount, order_amount, shipping, item): (FloatMajorUnit, FloatMajorUnit, FloatMajorUnit, T),
29+
) -> Self {
2730
Self {
2831
amount,
32+
order_amount,
2933
shipping,
3034
router_data: item,
3135
}
@@ -49,7 +53,7 @@ pub struct LineItem {
4953
id: Option<String>,
5054
quantity: Option<u16>,
5155
product_tax_code: Option<String>,
52-
unit_price: Option<f64>,
56+
unit_price: Option<FloatMajorUnit>,
5357
}
5458

5559
#[derive(Default, Debug, Serialize, Eq, PartialEq)]
@@ -69,8 +73,6 @@ impl TryFrom<&TaxjarRouterData<&types::PaymentsTaxCalculationRouterData>>
6973
item: &TaxjarRouterData<&types::PaymentsTaxCalculationRouterData>,
7074
) -> Result<Self, Self::Error> {
7175
let request = &item.router_data.request;
72-
let currency = item.router_data.request.currency;
73-
let currency_unit = &api::CurrencyUnit::Base;
7476
let shipping = &item
7577
.router_data
7678
.request
@@ -87,16 +89,11 @@ impl TryFrom<&TaxjarRouterData<&types::PaymentsTaxCalculationRouterData>>
8789
order_details
8890
.iter()
8991
.map(|line_item| {
90-
let unit_price = utils::get_amount_as_f64(
91-
currency_unit,
92-
line_item.amount,
93-
currency,
94-
)?;
9592
Ok(LineItem {
9693
id: line_item.product_id.clone(),
9794
quantity: Some(line_item.quantity),
9895
product_tax_code: line_item.product_tax_code.clone(),
99-
unit_price: Some(unit_price),
96+
unit_price: Some(item.order_amount),
10097
})
10198
})
10299
.collect();

crates/hyperswitch_connectors/src/connectors/zen/transformers.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -624,11 +624,14 @@ fn get_item_object(
624624
name: data.product_name.clone(),
625625
quantity: data.quantity,
626626
price: utils::to_currency_base_unit_with_zero_decimal_check(
627-
data.amount,
627+
data.amount.get_amount_as_i64(), // This should be changed to MinorUnit when we implement amount conversion for this connector. Additionally, the function get_amount_as_i64() should be avoided in the future.
628628
item.request.currency,
629629
)?,
630630
line_amount_total: (f64::from(data.quantity)
631-
* utils::to_currency_base_unit_asf64(data.amount, item.request.currency)?)
631+
* utils::to_currency_base_unit_asf64(
632+
data.amount.get_amount_as_i64(), // This should be changed to MinorUnit when we implement amount conversion for this connector. Additionally, the function get_amount_as_i64() should be avoided in the future.
633+
item.request.currency,
634+
)?)
632635
.to_string(),
633636
})
634637
})

crates/router/src/connector/adyen/transformers.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1770,8 +1770,8 @@ fn get_line_items(item: &AdyenRouterData<&types::PaymentsAuthorizeRouterData>) -
17701770
.iter()
17711771
.enumerate()
17721772
.map(|(i, data)| LineItem {
1773-
amount_including_tax: Some(MinorUnit::new(data.amount)),
1774-
amount_excluding_tax: Some(MinorUnit::new(data.amount)),
1773+
amount_including_tax: Some(data.amount),
1774+
amount_excluding_tax: Some(data.amount),
17751775
description: Some(data.product_name.clone()),
17761776
id: Some(format!("Items #{i}")),
17771777
tax_amount: None,

crates/router/src/connector/klarna.rs

Lines changed: 36 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
pub mod transformers;
2-
use std::fmt::Debug;
32

43
use api_models::enums;
54
use base64::Engine;
6-
use common_utils::request::RequestContent;
5+
use common_utils::{
6+
request::RequestContent,
7+
types::{AmountConvertor, MinorUnit, MinorUnitForConnector},
8+
};
79
use error_stack::{report, ResultExt};
810
use masking::PeekInterface;
911
use router_env::logger;
@@ -29,8 +31,18 @@ use crate::{
2931
utils::BytesExt,
3032
};
3133

32-
#[derive(Debug, Clone)]
33-
pub struct Klarna;
34+
#[derive(Clone)]
35+
pub struct Klarna {
36+
amount_converter: &'static (dyn AmountConvertor<Output = MinorUnit> + Sync),
37+
}
38+
39+
impl Klarna {
40+
pub fn new() -> &'static Self {
41+
&Self {
42+
amount_converter: &MinorUnitForConnector,
43+
}
44+
}
45+
}
3446

3547
impl ConnectorCommon for Klarna {
3648
fn id(&self) -> &'static str {
@@ -215,12 +227,12 @@ impl
215227
req: &types::PaymentsSessionRouterData,
216228
_connectors: &settings::Connectors,
217229
) -> CustomResult<RequestContent, errors::ConnectorError> {
218-
let connector_router_data = klarna::KlarnaRouterData::try_from((
219-
&self.get_currency_unit(),
230+
let amount = connector_utils::convert_amount(
231+
self.amount_converter,
232+
req.request.minor_amount,
220233
req.request.currency,
221-
req.request.amount,
222-
req,
223-
))?;
234+
)?;
235+
let connector_router_data = klarna::KlarnaRouterData::from((amount, req));
224236

225237
let connector_req = klarna::KlarnaSessionRequest::try_from(&connector_router_data)?;
226238
// encode only for for urlencoded things.
@@ -342,12 +354,12 @@ impl
342354
req: &types::PaymentsCaptureRouterData,
343355
_connectors: &settings::Connectors,
344356
) -> CustomResult<RequestContent, errors::ConnectorError> {
345-
let connector_router_data = klarna::KlarnaRouterData::try_from((
346-
&self.get_currency_unit(),
357+
let amount = connector_utils::convert_amount(
358+
self.amount_converter,
359+
req.request.minor_amount_to_capture,
347360
req.request.currency,
348-
req.request.amount_to_capture,
349-
req,
350-
))?;
361+
)?;
362+
let connector_router_data = klarna::KlarnaRouterData::from((amount, req));
351363
let connector_req = klarna::KlarnaCaptureRequest::try_from(&connector_router_data)?;
352364
Ok(RequestContent::Json(Box::new(connector_req)))
353365
}
@@ -670,12 +682,12 @@ impl
670682
req: &types::PaymentsAuthorizeRouterData,
671683
_connectors: &settings::Connectors,
672684
) -> CustomResult<RequestContent, errors::ConnectorError> {
673-
let connector_router_data = klarna::KlarnaRouterData::try_from((
674-
&self.get_currency_unit(),
685+
let amount = connector_utils::convert_amount(
686+
self.amount_converter,
687+
req.request.minor_amount,
675688
req.request.currency,
676-
req.request.amount,
677-
req,
678-
))?;
689+
)?;
690+
let connector_router_data = klarna::KlarnaRouterData::from((amount, req));
679691
let connector_req = klarna::KlarnaPaymentsRequest::try_from(&connector_router_data)?;
680692

681693
Ok(RequestContent::Json(Box::new(connector_req)))
@@ -847,12 +859,12 @@ impl services::ConnectorIntegration<api::Execute, types::RefundsData, types::Ref
847859
req: &types::RefundsRouterData<api::Execute>,
848860
_connectors: &settings::Connectors,
849861
) -> CustomResult<RequestContent, errors::ConnectorError> {
850-
let connector_router_data = klarna::KlarnaRouterData::try_from((
851-
&self.get_currency_unit(),
862+
let amount = connector_utils::convert_amount(
863+
self.amount_converter,
864+
req.request.minor_refund_amount,
852865
req.request.currency,
853-
req.request.refund_amount,
854-
req,
855-
))?;
866+
)?;
867+
let connector_router_data = klarna::KlarnaRouterData::from((amount, req));
856868
let connector_req = klarna::KlarnaRefundRequest::try_from(&connector_router_data)?;
857869
Ok(RequestContent::Json(Box::new(connector_req)))
858870
}

crates/router/src/connector/klarna/transformers.rs

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use api_models::payments;
2-
use common_utils::pii;
2+
use common_utils::{pii, types::MinorUnit};
33
use error_stack::{report, ResultExt};
44
use hyperswitch_domain_models::router_data::KlarnaSdkResponse;
55
use masking::{ExposeInterface, Secret};
@@ -15,25 +15,16 @@ use crate::{
1515

1616
#[derive(Debug, Serialize)]
1717
pub struct KlarnaRouterData<T> {
18-
amount: i64,
18+
amount: MinorUnit,
1919
router_data: T,
2020
}
2121

22-
impl<T> TryFrom<(&api::CurrencyUnit, enums::Currency, i64, T)> for KlarnaRouterData<T> {
23-
type Error = error_stack::Report<errors::ConnectorError>;
24-
25-
fn try_from(
26-
(_currency_unit, _currency, amount, router_data): (
27-
&api::CurrencyUnit,
28-
enums::Currency,
29-
i64,
30-
T,
31-
),
32-
) -> Result<Self, Self::Error> {
33-
Ok(Self {
22+
impl<T> From<(MinorUnit, T)> for KlarnaRouterData<T> {
23+
fn from((amount, router_data): (MinorUnit, T)) -> Self {
24+
Self {
3425
amount,
3526
router_data,
36-
})
27+
}
3728
}
3829
}
3930

@@ -74,7 +65,7 @@ impl TryFrom<&Option<pii::SecretSerdeValue>> for KlarnaConnectorMetadataObject {
7465
pub struct KlarnaPaymentsRequest {
7566
auto_capture: bool,
7667
order_lines: Vec<OrderLines>,
77-
order_amount: i64,
68+
order_amount: MinorUnit,
7869
purchase_country: enums::CountryAlpha2,
7970
purchase_currency: enums::Currency,
8071
merchant_reference1: Option<String>,
@@ -110,7 +101,7 @@ pub struct KlarnaSessionRequest {
110101
intent: KlarnaSessionIntent,
111102
purchase_country: enums::CountryAlpha2,
112103
purchase_currency: enums::Currency,
113-
order_amount: i64,
104+
order_amount: MinorUnit,
114105
order_lines: Vec<OrderLines>,
115106
shipping_address: Option<KlarnaShippingAddress>,
116107
}
@@ -157,7 +148,7 @@ impl TryFrom<&KlarnaRouterData<&types::PaymentsSessionRouterData>> for KlarnaSes
157148
name: data.product_name.clone(),
158149
quantity: data.quantity,
159150
unit_price: data.amount,
160-
total_amount: i64::from(data.quantity) * (data.amount),
151+
total_amount: data.amount * data.quantity,
161152
})
162153
.collect(),
163154
shipping_address: get_address_info(item.router_data.get_optional_shipping())
@@ -210,7 +201,7 @@ impl TryFrom<&KlarnaRouterData<&types::PaymentsAuthorizeRouterData>> for KlarnaP
210201
name: data.product_name.clone(),
211202
quantity: data.quantity,
212203
unit_price: data.amount,
213-
total_amount: i64::from(data.quantity) * (data.amount),
204+
total_amount: data.amount * data.quantity,
214205
})
215206
.collect(),
216207
merchant_reference1: Some(item.router_data.connector_request_reference_id.clone()),
@@ -294,8 +285,8 @@ impl TryFrom<types::PaymentsResponseRouterData<KlarnaPaymentsResponse>>
294285
pub struct OrderLines {
295286
name: String,
296287
quantity: u16,
297-
unit_price: i64,
298-
total_amount: i64,
288+
unit_price: MinorUnit,
289+
total_amount: MinorUnit,
299290
}
300291

301292
#[derive(Debug, Serialize)]
@@ -412,7 +403,7 @@ impl<F, T>
412403

413404
#[derive(Debug, Serialize)]
414405
pub struct KlarnaCaptureRequest {
415-
captured_amount: i64,
406+
captured_amount: MinorUnit,
416407
reference: Option<String>,
417408
}
418409

@@ -490,7 +481,7 @@ impl<F>
490481

491482
#[derive(Default, Debug, Serialize)]
492483
pub struct KlarnaRefundRequest {
493-
refunded_amount: i64,
484+
refunded_amount: MinorUnit,
494485
reference: Option<String>,
495486
}
496487

0 commit comments

Comments
 (0)