Skip to content

Commit 0476361

Browse files
bsayak03Sayak Bhattacharya
andauthored
feat(core): Altered the amount field in DisputePayload to StringMinorUnit (#8131)
Co-authored-by: Sayak Bhattacharya <[email protected]>
1 parent 25dfa0e commit 0476361

File tree

37 files changed

+356
-126
lines changed

37 files changed

+356
-126
lines changed

api-reference-v2/openapi_spec.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10015,8 +10015,7 @@
1001510015
"description": "The identifier for payment_attempt"
1001610016
},
1001710017
"amount": {
10018-
"type": "string",
10019-
"description": "The dispute amount"
10018+
"$ref": "#/components/schemas/StringMinorUnit"
1002010019
},
1002110020
"currency": {
1002210021
"$ref": "#/components/schemas/Currency"
@@ -23299,6 +23298,10 @@
2329923298
"propertyName": "type"
2330023299
}
2330123300
},
23301+
"StringMinorUnit": {
23302+
"type": "string",
23303+
"description": "Connector specific types to send"
23304+
},
2330223305
"StripeChargeResponseData": {
2330323306
"type": "object",
2330423307
"description": "Fee information to be charged on the payment being collected via Stripe",

api-reference/openapi_spec.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11909,8 +11909,7 @@
1190911909
"description": "The identifier for payment_attempt"
1191011910
},
1191111911
"amount": {
11912-
"type": "string",
11913-
"description": "The dispute amount"
11912+
"$ref": "#/components/schemas/StringMinorUnit"
1191411913
},
1191511914
"currency": {
1191611915
"$ref": "#/components/schemas/Currency"
@@ -27341,6 +27340,10 @@
2734127340
"propertyName": "type"
2734227341
}
2734327342
},
27343+
"StringMinorUnit": {
27344+
"type": "string",
27345+
"description": "Connector specific types to send"
27346+
},
2734427347
"StripeChargeResponseData": {
2734527348
"type": "object",
2734627349
"description": "Fee information to be charged on the payment being collected via Stripe",

crates/api_models/src/disputes.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::collections::HashMap;
22

3-
use common_utils::types::TimeRange;
3+
use common_utils::types::{StringMinorUnit, TimeRange};
44
use masking::{Deserialize, Serialize};
55
use serde::de::Error;
66
use time::PrimitiveDateTime;
@@ -19,7 +19,7 @@ pub struct DisputeResponse {
1919
/// The identifier for payment_attempt
2020
pub attempt_id: String,
2121
/// The dispute amount
22-
pub amount: String,
22+
pub amount: StringMinorUnit,
2323
/// The three-letter ISO currency code
2424
#[schema(value_type = Currency)]
2525
pub currency: Currency,

crates/common_utils/src/types.rs

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,20 @@ impl Sum for MinorUnit {
520520
}
521521

522522
/// Connector specific types to send
523-
#[derive(Default, Debug, serde::Deserialize, serde::Serialize, Clone, PartialEq)]
523+
#[derive(
524+
Default,
525+
Debug,
526+
serde::Deserialize,
527+
AsExpression,
528+
serde::Serialize,
529+
Clone,
530+
PartialEq,
531+
Eq,
532+
Hash,
533+
ToSchema,
534+
PartialOrd,
535+
)]
536+
#[diesel(sql_type = sql_types::Text)]
524537
pub struct StringMinorUnit(String);
525538

526539
impl StringMinorUnit {
@@ -544,6 +557,45 @@ impl StringMinorUnit {
544557
}
545558
}
546559

560+
impl Display for StringMinorUnit {
561+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
562+
write!(f, "{}", self.0)
563+
}
564+
}
565+
566+
impl<DB> FromSql<sql_types::Text, DB> for StringMinorUnit
567+
where
568+
DB: Backend,
569+
String: FromSql<sql_types::Text, DB>,
570+
{
571+
fn from_sql(value: DB::RawValue<'_>) -> deserialize::Result<Self> {
572+
let val = String::from_sql(value)?;
573+
Ok(Self(val))
574+
}
575+
}
576+
577+
impl<DB> ToSql<sql_types::Text, DB> for StringMinorUnit
578+
where
579+
DB: Backend,
580+
String: ToSql<sql_types::Text, DB>,
581+
{
582+
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, DB>) -> diesel::serialize::Result {
583+
self.0.to_sql(out)
584+
}
585+
}
586+
587+
impl<DB> Queryable<sql_types::Text, DB> for StringMinorUnit
588+
where
589+
DB: Backend,
590+
Self: FromSql<sql_types::Text, DB>,
591+
{
592+
type Row = Self;
593+
594+
fn build(row: Self::Row) -> deserialize::Result<Self> {
595+
Ok(row)
596+
}
597+
}
598+
547599
/// Connector specific types to send
548600
#[derive(Default, Debug, serde::Deserialize, serde::Serialize, Clone, Copy, PartialEq)]
549601
pub struct FloatMajorUnit(f64);

crates/diesel_models/src/dispute.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
use common_utils::custom_serde;
1+
use common_utils::{
2+
custom_serde,
3+
types::{MinorUnit, StringMinorUnit},
4+
};
25
use diesel::{AsChangeset, Identifiable, Insertable, Queryable, Selectable};
36
use masking::Secret;
47
use serde::Serialize;
@@ -11,7 +14,7 @@ use crate::{enums as storage_enums, schema::dispute};
1114
#[serde(deny_unknown_fields)]
1215
pub struct DisputeNew {
1316
pub dispute_id: String,
14-
pub amount: String,
17+
pub amount: StringMinorUnit,
1518
pub currency: String,
1619
pub dispute_stage: storage_enums::DisputeStage,
1720
pub dispute_status: storage_enums::DisputeStatus,
@@ -29,7 +32,7 @@ pub struct DisputeNew {
2932
pub evidence: Option<Secret<serde_json::Value>>,
3033
pub profile_id: Option<common_utils::id_type::ProfileId>,
3134
pub merchant_connector_id: Option<common_utils::id_type::MerchantConnectorAccountId>,
32-
pub dispute_amount: i64,
35+
pub dispute_amount: MinorUnit,
3336
pub organization_id: common_utils::id_type::OrganizationId,
3437
pub dispute_currency: Option<storage_enums::Currency>,
3538
}
@@ -38,7 +41,7 @@ pub struct DisputeNew {
3841
#[diesel(table_name = dispute, primary_key(dispute_id), check_for_backend(diesel::pg::Pg))]
3942
pub struct Dispute {
4043
pub dispute_id: String,
41-
pub amount: String,
44+
pub amount: StringMinorUnit,
4245
pub currency: String,
4346
pub dispute_stage: storage_enums::DisputeStage,
4447
pub dispute_status: storage_enums::DisputeStatus,
@@ -60,7 +63,7 @@ pub struct Dispute {
6063
pub evidence: Secret<serde_json::Value>,
6164
pub profile_id: Option<common_utils::id_type::ProfileId>,
6265
pub merchant_connector_id: Option<common_utils::id_type::MerchantConnectorAccountId>,
63-
pub dispute_amount: i64,
66+
pub dispute_amount: MinorUnit,
6467
pub organization_id: common_utils::id_type::OrganizationId,
6568
pub dispute_currency: Option<storage_enums::Currency>,
6669
}

crates/hyperswitch_connectors/src/connectors/adyen.rs

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ use common_utils::{
88
errors::CustomResult,
99
ext_traits::{ByteSliceExt, OptionExt},
1010
request::{Method, Request, RequestBuilder, RequestContent},
11-
types::{AmountConvertor, MinorUnit, MinorUnitForConnector},
11+
types::{
12+
AmountConvertor, MinorUnit, MinorUnitForConnector, StringMinorUnit,
13+
StringMinorUnitForConnector,
14+
},
1215
};
1316
use error_stack::{report, ResultExt};
1417
use hyperswitch_domain_models::{
@@ -86,7 +89,7 @@ use crate::{
8689
SubmitEvidenceRouterData,
8790
},
8891
utils::{
89-
self as connector_utils, convert_payment_authorize_router_response,
92+
convert_amount, convert_payment_authorize_router_response,
9093
convert_setup_mandate_router_data_to_authorize_router_data, is_mandate_supported,
9194
ForeignTryFrom, PaymentMethodDataType,
9295
},
@@ -96,12 +99,14 @@ const ADYEN_API_VERSION: &str = "v68";
9699
#[derive(Clone)]
97100
pub struct Adyen {
98101
amount_converter: &'static (dyn AmountConvertor<Output = MinorUnit> + Sync),
102+
amount_converter_webhooks: &'static (dyn AmountConvertor<Output = StringMinorUnit> + Sync),
99103
}
100104

101105
impl Adyen {
102106
pub const fn new() -> &'static Self {
103107
&Self {
104108
amount_converter: &MinorUnitForConnector,
109+
amount_converter_webhooks: &StringMinorUnitForConnector,
105110
}
106111
}
107112
}
@@ -467,7 +472,7 @@ impl ConnectorIntegration<SetupMandate, SetupMandateRequestData, PaymentsRespons
467472
convert_setup_mandate_router_data_to_authorize_router_data(req),
468473
));
469474

470-
let amount = connector_utils::convert_amount(
475+
let amount = convert_amount(
471476
self.amount_converter,
472477
authorize_req.request.minor_amount,
473478
authorize_req.request.currency,
@@ -584,7 +589,7 @@ impl ConnectorIntegration<Capture, PaymentsCaptureData, PaymentsResponseData> fo
584589
req: &PaymentsCaptureRouterData,
585590
_connectors: &Connectors,
586591
) -> CustomResult<RequestContent, errors::ConnectorError> {
587-
let amount_to_capture = connector_utils::convert_amount(
592+
let amount_to_capture = convert_amount(
588593
self.amount_converter,
589594
req.request.minor_amount_to_capture,
590595
req.request.currency,
@@ -850,7 +855,7 @@ impl ConnectorIntegration<Authorize, PaymentsAuthorizeData, PaymentsResponseData
850855
req: &PaymentsAuthorizeRouterData,
851856
_connectors: &Connectors,
852857
) -> CustomResult<RequestContent, errors::ConnectorError> {
853-
let amount = connector_utils::convert_amount(
858+
let amount = convert_amount(
854859
self.amount_converter,
855860
req.request.minor_amount,
856861
req.request.currency,
@@ -1013,7 +1018,7 @@ impl ConnectorIntegration<PreProcessing, PaymentsPreProcessingData, PaymentsResp
10131018
})?,
10141019
};
10151020

1016-
let amount = connector_utils::convert_amount(self.amount_converter, amount, currency)?;
1021+
let amount = convert_amount(self.amount_converter, amount, currency)?;
10171022

10181023
if response.balance.currency != currency || response.balance.value < amount {
10191024
Ok(RouterData {
@@ -1298,7 +1303,7 @@ impl ConnectorIntegration<PoCreate, PayoutsData, PayoutsResponseData> for Adyen
12981303
req: &PayoutsRouterData<PoCreate>,
12991304
_connectors: &Connectors,
13001305
) -> CustomResult<RequestContent, errors::ConnectorError> {
1301-
let amount = connector_utils::convert_amount(
1306+
let amount = convert_amount(
13021307
self.amount_converter,
13031308
req.request.minor_amount,
13041309
req.request.destination_currency,
@@ -1396,7 +1401,7 @@ impl ConnectorIntegration<PoEligibility, PayoutsData, PayoutsResponseData> for A
13961401
req: &PayoutsRouterData<PoEligibility>,
13971402
_connectors: &Connectors,
13981403
) -> CustomResult<RequestContent, errors::ConnectorError> {
1399-
let amount = connector_utils::convert_amount(
1404+
let amount = convert_amount(
14001405
self.amount_converter,
14011406
req.request.minor_amount,
14021407
req.request.destination_currency,
@@ -1523,7 +1528,7 @@ impl ConnectorIntegration<PoFulfill, PayoutsData, PayoutsResponseData> for Adyen
15231528
req: &PayoutsRouterData<PoFulfill>,
15241529
_connectors: &Connectors,
15251530
) -> CustomResult<RequestContent, errors::ConnectorError> {
1526-
let amount = connector_utils::convert_amount(
1531+
let amount = convert_amount(
15271532
self.amount_converter,
15281533
req.request.minor_amount,
15291534
req.request.destination_currency,
@@ -1628,7 +1633,7 @@ impl ConnectorIntegration<Execute, RefundsData, RefundsResponseData> for Adyen {
16281633
req: &RefundsRouterData<Execute>,
16291634
_connectors: &Connectors,
16301635
) -> CustomResult<RequestContent, errors::ConnectorError> {
1631-
let refund_amount = connector_utils::convert_amount(
1636+
let refund_amount = convert_amount(
16321637
self.amount_converter,
16331638
req.request.minor_refund_amount,
16341639
req.request.currency,
@@ -1876,8 +1881,14 @@ impl IncomingWebhook for Adyen {
18761881
) -> CustomResult<disputes::DisputePayload, errors::ConnectorError> {
18771882
let notif = get_webhook_object_from_body(request.body)
18781883
.change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?;
1884+
1885+
let amount = convert_amount(
1886+
self.amount_converter_webhooks,
1887+
notif.amount.value,
1888+
notif.amount.currency,
1889+
)?;
18791890
Ok(disputes::DisputePayload {
1880-
amount: notif.amount.value.to_string(),
1891+
amount,
18811892
currency: notif.amount.currency,
18821893
dispute_stage: api_models::enums::DisputeStage::from(notif.event_code.clone()),
18831894
connector_dispute_id: notif.psp_reference,

crates/hyperswitch_connectors/src/connectors/airwallex.rs

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
pub mod transformers;
22

3-
use std::{fmt::Debug, sync::LazyLock};
3+
use std::sync::LazyLock;
44

55
use api_models::webhooks::IncomingWebhookEvent;
66
use common_enums::{enums, CallConnectorAction, PaymentAction};
@@ -9,6 +9,7 @@ use common_utils::{
99
errors::CustomResult,
1010
ext_traits::{ByteSliceExt, BytesExt, ValueExt},
1111
request::{Method, Request, RequestBuilder, RequestContent},
12+
types::{AmountConvertor, StringMinorUnit, StringMinorUnitForConnector},
1213
};
1314
use error_stack::{report, ResultExt};
1415
use hyperswitch_domain_models::{
@@ -53,11 +54,21 @@ use transformers as airwallex;
5354
use crate::{
5455
constants::headers,
5556
types::{RefreshTokenRouterData, ResponseRouterData},
56-
utils::{AccessTokenRequestInfo, RefundsRequestData},
57+
utils::{convert_amount, AccessTokenRequestInfo, RefundsRequestData},
5758
};
5859

59-
#[derive(Debug, Clone)]
60-
pub struct Airwallex;
60+
#[derive(Clone)]
61+
pub struct Airwallex {
62+
amount_converter: &'static (dyn AmountConvertor<Output = StringMinorUnit> + Sync),
63+
}
64+
65+
impl Airwallex {
66+
pub const fn new() -> &'static Self {
67+
&Self {
68+
amount_converter: &StringMinorUnitForConnector,
69+
}
70+
}
71+
}
6172

6273
impl<Flow, Request, Response> ConnectorCommonExt<Flow, Request, Response> for Airwallex
6374
where
@@ -1064,8 +1075,13 @@ impl IncomingWebhook for Airwallex {
10641075
.object
10651076
.parse_value("AirwallexDisputeObject")
10661077
.change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?;
1078+
let amount = convert_amount(
1079+
self.amount_converter,
1080+
dispute_details.dispute_amount,
1081+
dispute_details.dispute_currency,
1082+
)?;
10671083
Ok(DisputePayload {
1068-
amount: dispute_details.dispute_amount.to_string(),
1084+
amount,
10691085
currency: dispute_details.dispute_currency,
10701086
dispute_stage: api_models::enums::DisputeStage::from(dispute_details.stage.clone()),
10711087
connector_dispute_id: dispute_details.dispute_id,

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use common_enums::enums;
2-
use common_utils::{errors::ParsingError, pii::IpAddress, request::Method};
2+
use common_utils::{errors::ParsingError, pii::IpAddress, request::Method, types::MinorUnit};
33
use error_stack::ResultExt;
44
use hyperswitch_domain_models::{
55
payment_method_data::{PaymentMethodData, WalletData},
@@ -914,7 +914,7 @@ pub struct AirwallexObjectData {
914914
#[derive(Debug, Deserialize)]
915915
pub struct AirwallexDisputeObject {
916916
pub payment_intent_id: String,
917-
pub dispute_amount: i64,
917+
pub dispute_amount: MinorUnit,
918918
pub dispute_currency: enums::Currency,
919919
pub stage: AirwallexDisputeStage,
920920
pub dispute_id: String,

0 commit comments

Comments
 (0)