-
Notifications
You must be signed in to change notification settings - Fork 4.2k
feat(core): Altered the amount field in DisputePayload to StringMinorUnit #8131
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
} | ||
|
||
impl Adyen { | ||
pub const fn new() -> &'static Self { | ||
&Self { | ||
amount_converter: &MinorUnitForConnector, | ||
amount_converter_string_major_unit: &StringMinorUnitForConnector, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can u rename it to flow basis as having two amount converter creates confusion
crates/common_utils/src/types.rs
Outdated
impl Display for StringMinorUnit { | ||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
write!(f, "{}", self.0) | ||
} | ||
} | ||
|
||
impl<DB> FromSql<sql_types::Text, DB> for StringMinorUnit | ||
where | ||
DB: Backend, | ||
String: FromSql<sql_types::Text, DB>, | ||
{ | ||
fn from_sql(value: DB::RawValue<'_>) -> deserialize::Result<Self> { | ||
let val = String::from_sql(value)?; | ||
Ok(Self(val)) | ||
} | ||
} | ||
|
||
impl<DB> ToSql<sql_types::Text, DB> for StringMinorUnit | ||
where | ||
DB: Backend, | ||
String: ToSql<sql_types::Text, DB>, | ||
{ | ||
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, DB>) -> diesel::serialize::Result { | ||
self.0.to_sql(out) | ||
} | ||
} | ||
|
||
impl<DB> Queryable<sql_types::Text, DB> for StringMinorUnit | ||
where | ||
DB: Backend, | ||
Self: FromSql<sql_types::Text, DB>, | ||
{ | ||
type Row = Self; | ||
|
||
fn build(row: Self::Row) -> deserialize::Result<Self> { | ||
Ok(row) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please move these impl below the struct for better visibility
@@ -1064,8 +1075,13 @@ impl IncomingWebhook for Airwallex { | |||
.object | |||
.parse_value("AirwallexDisputeObject") | |||
.change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?; | |||
let amount = convert_amount( | |||
self.amount_converter, | |||
MinorUnit::new(dispute_details.dispute_amount), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
instead of creating MinorUnit::new()
we can change AirwallexDisputeObject
itself to accept MinorUnit
amount_converter_1: &'static (dyn AmountConvertor<Output = StringMinorUnit> + Sync), | ||
amount_converter_webhooks: &'static (dyn AmountConvertor<Output = FloatMajorUnit> + Sync), | ||
} | ||
|
||
impl Bluesnap { | ||
pub fn new() -> &'static Self { | ||
&Self { | ||
amount_converter: &StringMajorUnitForConnector, | ||
amount_converter_1: &StringMinorUnitForConnector, | ||
amount_converter_webhooks: &FloatMajorUnitForConnector, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please fix the naming convention amount_converter_1
doesn't make any sense
dispute_data.amount_disputed.to_string(), | ||
amount: convert_amount( | ||
self.amount_converter_webhooks, | ||
MinorUnit::new(dispute_data.amount_disputed), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 on accepting domain amount type in struct instead of creating new domain types on fly!
amount: webhook_object.price.to_string(), | ||
amount: utils::convert_amount( | ||
self.amount_converter_1, | ||
MinorUnit::new(webhook_object.price), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 struct handling
@@ -1187,7 +1192,18 @@ async fn get_or_update_dispute_object( | |||
profile_id: Some(business_profile.get_id().to_owned()), | |||
evidence: None, | |||
merchant_connector_id: payment_attempt.merchant_connector_id.clone(), | |||
dispute_amount: dispute_details.amount.parse::<i64>().unwrap_or(0), | |||
dispute_amount: MinorUnit::get_amount_as_i64( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
change dispute_amount
to MinorUnit
dispute_id: &dispute.dispute_id, | ||
dispute_amount: dispute.amount.parse::<i64>().unwrap_or_default(), | ||
currency: dispute.dispute_currency.unwrap_or( | ||
dispute | ||
.currency | ||
.to_uppercase() | ||
.parse_enum("Currency") | ||
.unwrap_or_default(), | ||
), | ||
dispute_amount: StringMinorUnitForConnector::convert_back( | ||
&StringMinorUnitForConnector, | ||
dispute.amount.clone(), | ||
currency, | ||
) | ||
.map(MinorUnit::get_amount_as_i64) | ||
.unwrap_or_else(|e| { | ||
router_env::logger::error!("Failed to convert dispute amount: {e:?}"); | ||
0 | ||
}), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
change dispute.rs to MinorUnit
.to_uppercase() | ||
.parse_enum("Currency") | ||
.unwrap_or_default(), | ||
); | ||
Self { | ||
dispute_id: &dispute.dispute_id, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
disputes_count += 1; | ||
let currency = payment_intent | ||
.currency | ||
.unwrap_or(common_enums::Currency::USD); | ||
Some(DisputeNew { | ||
dispute_id: common_utils::generate_id_with_default_len("test"), | ||
amount: (amount * 100).to_string(), | ||
currency: payment_intent | ||
.currency | ||
.unwrap_or(common_enums::Currency::USD) | ||
.to_string(), | ||
amount: StringMinorUnitForConnector::convert( | ||
&StringMinorUnitForConnector, | ||
MinorUnit::new(amount * 100), | ||
payment_intent.currency.unwrap_or(currency), | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why are we evaluating currency twice?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
because in the amount field we want currency as an Enum type and in the currency field we want it as string type
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can reuse the existing currency evaluation
@@ -1064,8 +1075,13 @@ impl IncomingWebhook for Airwallex { | |||
.object | |||
.parse_value("AirwallexDisputeObject") | |||
.change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?; | |||
let amount = convert_amount( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do it for other flows aswell
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no other flow in Airwallex.rs is converting amount
|
||
let amount = utils::convert_amount( | ||
self.amount_converter_1, | ||
MinorUnit::new(i64::from(dispute_details.data.amount)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please make the appropiate struct changes
@@ -86,12 +89,14 @@ use crate::{ | |||
#[derive(Clone)] | |||
pub struct Paypal { | |||
amount_converter: &'static (dyn AmountConvertor<Output = StringMajorUnit> + Sync), | |||
amount_converter_1: &'static (dyn AmountConvertor<Output = StringMinorUnit> + Sync), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
@@ -60,11 +63,13 @@ use crate::{ | |||
#[derive(Clone)] | |||
pub struct Rapyd { | |||
amount_converter: &'static (dyn AmountConvertor<Output = FloatMajorUnit> + Sync), | |||
amount_converter_1: &'static (dyn AmountConvertor<Output = StringMinorUnit> + Sync), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
amount: webhook_dispute_data.amount.to_string(), | ||
amount: convert_amount( | ||
self.amount_converter_1, | ||
MinorUnit::new(webhook_dispute_data.amount), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
appropiate struct change please
disputes_count += 1; | ||
let currency = payment_intent | ||
.currency | ||
.unwrap_or(common_enums::Currency::USD); | ||
Some(DisputeNew { | ||
dispute_id: common_utils::generate_id_with_default_len("test"), | ||
amount: (amount * 100).to_string(), | ||
currency: payment_intent | ||
.currency | ||
.unwrap_or(common_enums::Currency::USD) | ||
.to_string(), | ||
amount: StringMinorUnitForConnector::convert( | ||
&StringMinorUnitForConnector, | ||
MinorUnit::new(amount * 100), | ||
payment_intent.currency.unwrap_or(currency), | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can reuse the existing currency evaluation
Type of Change
Description
The amount field in DisputePayload in
crates/hyperswitch_interfaces/src/disputes.rs
was String. Changed it to StringMinorUnit.Made changes in the following connectors : Adyen, Airwallex, Bluesnap, Braintree, Checkout, Novalnet, Payme, Paypal, Rapyd, Stripe, Trustpay.
In the Dispute table, changed the amount field from String to StringMinorUnit and dispute_amount from i64 to MinorUnit.
Dispute Webhooks need to be tested for all the above mentioned connectors.
Additional Changes
Motivation and Context
How did you test it?
run these on stripe cli
brew install stripe/stripe-cli/stripe
stripe login --api-key <stripe_api_key>
stripe listen --events charge.dispute.created \ --forward-to localhost:8080/webhook
stripe listen --forward-to http://localhost:8080/webhooks/<merchant_id>/<merchant_connector_id>
This will initiate a dispute and you will either accept it or counter it and hence will receive incoming webhooks
cURL :
After this head to Checkout Dashboard and you'll see this being marked as
Dispute Resolved
and you'll receive Dispute Webhooks too.Manually sent incoming webhooks to Hyperswitch
https://developer.novalnet.com/asynchronousnotification/parameterspassed?payment=chargeback_creditcard_chargeback#parameter-list
Used Novalnet's Webhook simulator to send webhooks to Hyperswitch.
Payment Access Key
will bekey1
of Hyperswitch andTID
will beconnector_transaction_id
with which a successful payment was made previously.Checklist
cargo +nightly fmt --all
cargo clippy