mirror of
				https://github.com/juspay/hyperswitch.git
				synced 2025-11-01 02:57:02 +08:00 
			
		
		
		
	fix(connector): convert cents to dollar before sending to connector (#699)
Co-authored-by: Jagan Elavarasan <jaganelavarasan@gmail.com> Co-authored-by: Arjun Karthik <m.arjunkarthik@gmail.com> Co-authored-by: Arun Raj M <jarnura47@gmail.com>
This commit is contained in:
		| @ -4,6 +4,7 @@ use url::Url; | ||||
| use uuid::Uuid; | ||||
|  | ||||
| use crate::{ | ||||
|     connector::utils, | ||||
|     core::errors, | ||||
|     pii::{self, Secret}, | ||||
|     services, | ||||
| @ -14,7 +15,7 @@ use crate::{ | ||||
| pub struct AirwallexIntentRequest { | ||||
|     // Unique ID to be sent for each transaction/operation request to the connector | ||||
|     request_id: String, | ||||
|     amount: i64, | ||||
|     amount: String, | ||||
|     currency: enums::Currency, | ||||
|     //ID created in merchant's order system that corresponds to this PaymentIntent. | ||||
|     merchant_order_id: String, | ||||
| @ -26,7 +27,7 @@ impl TryFrom<&types::PaymentsAuthorizeSessionTokenRouterData> for AirwallexInten | ||||
|     ) -> Result<Self, Self::Error> { | ||||
|         Ok(Self { | ||||
|             request_id: Uuid::new_v4().to_string(), | ||||
|             amount: item.request.amount, | ||||
|             amount: utils::to_currency_base_unit(item.request.amount, item.request.currency)?, | ||||
|             currency: item.request.currency, | ||||
|             merchant_order_id: item.payment_id.clone(), | ||||
|         }) | ||||
| @ -145,7 +146,7 @@ impl<F, T> TryFrom<types::ResponseRouterData<F, AirwallexAuthUpdateResponse, T, | ||||
| pub struct AirwallexPaymentsCaptureRequest { | ||||
|     // Unique ID to be sent for each transaction/operation request to the connector | ||||
|     request_id: String, | ||||
|     amount: Option<i64>, | ||||
|     amount: Option<String>, | ||||
| } | ||||
|  | ||||
| impl TryFrom<&types::PaymentsCaptureRouterData> for AirwallexPaymentsCaptureRequest { | ||||
| @ -153,7 +154,13 @@ impl TryFrom<&types::PaymentsCaptureRouterData> for AirwallexPaymentsCaptureRequ | ||||
|     fn try_from(item: &types::PaymentsCaptureRouterData) -> Result<Self, Self::Error> { | ||||
|         Ok(Self { | ||||
|             request_id: Uuid::new_v4().to_string(), | ||||
|             amount: item.request.amount_to_capture, | ||||
|             amount: match item.request.amount_to_capture { | ||||
|                 Some(_a) => Some(utils::to_currency_base_unit( | ||||
|                     item.request.amount, | ||||
|                     item.request.currency, | ||||
|                 )?), | ||||
|                 _ => None, | ||||
|             }, | ||||
|         }) | ||||
|     } | ||||
| } | ||||
| @ -224,7 +231,7 @@ pub struct AirwallexPaymentsResponse { | ||||
|     status: AirwallexPaymentStatus, | ||||
|     //Unique identifier for the PaymentIntent | ||||
|     id: String, | ||||
|     amount: Option<i64>, | ||||
|     amount: Option<f32>, | ||||
|     //ID of the PaymentConsent related to this PaymentIntent | ||||
|     payment_consent_id: Option<String>, | ||||
|     next_action: Option<AirwallexPaymentsNextAction>, | ||||
| @ -277,18 +284,21 @@ impl<F, T> | ||||
| pub struct AirwallexRefundRequest { | ||||
|     // Unique ID to be sent for each transaction/operation request to the connector | ||||
|     request_id: String, | ||||
|     amount: Option<i64>, | ||||
|     amount: Option<String>, | ||||
|     reason: Option<String>, | ||||
|     //Identifier for the PaymentIntent for which Refund is requested | ||||
|     payment_intent_id: String, | ||||
| } | ||||
|  | ||||
| impl<F> TryFrom<&types::RefundsRouterData<F>> for AirwallexRefundRequest { | ||||
|     type Error = error_stack::Report<errors::ParsingError>; | ||||
|     type Error = error_stack::Report<errors::ConnectorError>; | ||||
|     fn try_from(item: &types::RefundsRouterData<F>) -> Result<Self, Self::Error> { | ||||
|         Ok(Self { | ||||
|             request_id: Uuid::new_v4().to_string(), | ||||
|             amount: Some(item.request.refund_amount), | ||||
|             amount: Some(utils::to_currency_base_unit( | ||||
|                 item.request.refund_amount, | ||||
|                 item.request.currency, | ||||
|             )?), | ||||
|             reason: item.request.reason.clone(), | ||||
|             payment_intent_id: item.request.connector_transaction_id.clone(), | ||||
|         }) | ||||
| @ -320,7 +330,7 @@ impl From<RefundStatus> for enums::RefundStatus { | ||||
| pub struct RefundResponse { | ||||
|     //A unique number that tags a credit or debit card transaction when it goes from the merchant's bank through to the cardholder's bank. | ||||
|     acquirer_reference_number: String, | ||||
|     amount: i64, | ||||
|     amount: f32, | ||||
|     //Unique identifier for the Refund | ||||
|     id: String, | ||||
|     status: RefundStatus, | ||||
|  | ||||
| @ -3,7 +3,7 @@ use common_utils::ext_traits::ValueExt; | ||||
| use error_stack::ResultExt; | ||||
| use masking::{Deserialize, Serialize}; | ||||
|  | ||||
| use crate::{core::errors, types, utils::OptionExt}; | ||||
| use crate::{connector::utils, core::errors, types, utils::OptionExt}; | ||||
|  | ||||
| #[derive(Debug, Serialize)] | ||||
| #[serde(rename_all = "camelCase")] | ||||
| @ -134,7 +134,10 @@ impl<F> | ||||
|         let amount_info = AmountInfo { | ||||
|             label: metadata.payment_request_data.label, | ||||
|             label_type: "final".to_string(), | ||||
|             amount: (item.data.request.amount / 100).to_string(), | ||||
|             amount: utils::to_currency_base_unit( | ||||
|                 item.data.request.amount, | ||||
|                 item.data.request.currency, | ||||
|             )?, | ||||
|         }; | ||||
|  | ||||
|         let payment_request = PaymentRequest { | ||||
|  | ||||
| @ -1,6 +1,7 @@ | ||||
| use serde::{Deserialize, Serialize}; | ||||
|  | ||||
| use crate::{ | ||||
|     connector::utils, | ||||
|     core::errors, | ||||
|     pii::{self, Secret}, | ||||
|     types::{self, api, storage::enums, transformers::ForeignTryFrom}, | ||||
| @ -9,11 +10,10 @@ use crate::{ | ||||
| #[derive(Debug, Serialize, PartialEq)] | ||||
| #[serde(rename_all = "camelCase")] | ||||
| pub struct BluesnapPaymentsRequest { | ||||
|     amount: i64, | ||||
|     amount: String, | ||||
|     #[serde(flatten)] | ||||
|     payment_method: PaymentMethodDetails, | ||||
|     currency: enums::Currency, | ||||
|     soft_descriptor: Option<String>, | ||||
|     card_transaction_type: BluesnapTxnType, | ||||
| } | ||||
|  | ||||
| @ -51,10 +51,9 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for BluesnapPaymentsRequest { | ||||
|             )), | ||||
|         }?; | ||||
|         Ok(Self { | ||||
|             amount: item.request.amount, | ||||
|             amount: utils::to_currency_base_unit(item.request.amount, item.request.currency)?, | ||||
|             payment_method, | ||||
|             currency: item.request.currency, | ||||
|             soft_descriptor: item.description.clone(), | ||||
|             card_transaction_type: auth_mode, | ||||
|         }) | ||||
|     } | ||||
| @ -84,7 +83,7 @@ impl TryFrom<&types::PaymentsCancelRouterData> for BluesnapVoidRequest { | ||||
| pub struct BluesnapCaptureRequest { | ||||
|     card_transaction_type: BluesnapTxnType, | ||||
|     transaction_id: String, | ||||
|     amount: Option<i64>, | ||||
|     amount: Option<String>, | ||||
| } | ||||
|  | ||||
| impl TryFrom<&types::PaymentsCaptureRouterData> for BluesnapCaptureRequest { | ||||
| @ -92,10 +91,14 @@ impl TryFrom<&types::PaymentsCaptureRouterData> for BluesnapCaptureRequest { | ||||
|     fn try_from(item: &types::PaymentsCaptureRouterData) -> Result<Self, Self::Error> { | ||||
|         let card_transaction_type = BluesnapTxnType::Capture; | ||||
|         let transaction_id = item.request.connector_transaction_id.to_string(); | ||||
|         let amount = utils::to_currency_base_unit_from_optional_amount( | ||||
|             item.request.amount_to_capture, | ||||
|             item.request.currency, | ||||
|         )?; | ||||
|         Ok(Self { | ||||
|             card_transaction_type, | ||||
|             transaction_id, | ||||
|             amount: item.request.amount_to_capture, | ||||
|             amount: Some(amount), | ||||
|         }) | ||||
|     } | ||||
| } | ||||
| @ -232,7 +235,7 @@ impl<F, T> | ||||
|  | ||||
| #[derive(Default, Debug, Eq, PartialEq, Serialize)] | ||||
| pub struct BluesnapRefundRequest { | ||||
|     amount: Option<i64>, | ||||
|     amount: Option<String>, | ||||
|     reason: Option<String>, | ||||
| } | ||||
|  | ||||
| @ -241,7 +244,10 @@ impl<F> TryFrom<&types::RefundsRouterData<F>> for BluesnapRefundRequest { | ||||
|     fn try_from(item: &types::RefundsRouterData<F>) -> Result<Self, Self::Error> { | ||||
|         Ok(Self { | ||||
|             reason: item.request.reason.clone(), | ||||
|             amount: Some(item.request.refund_amount), | ||||
|             amount: Some(utils::to_currency_base_unit( | ||||
|                 item.request.refund_amount, | ||||
|                 item.request.currency, | ||||
|             )?), | ||||
|         }) | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -4,6 +4,7 @@ use masking::Secret; | ||||
| use serde::{Deserialize, Serialize}; | ||||
|  | ||||
| use crate::{ | ||||
|     connector::utils, | ||||
|     consts, | ||||
|     core::errors, | ||||
|     types::{self, api, storage::enums}, | ||||
| @ -91,7 +92,7 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for BraintreePaymentsRequest { | ||||
|             Some(enums::CaptureMethod::Automatic) | None | ||||
|         ); | ||||
|  | ||||
|         let amount = item.request.amount.to_string(); | ||||
|         let amount = utils::to_currency_base_unit(item.request.amount, item.request.currency)?; | ||||
|         let device_data = DeviceData {}; | ||||
|         let options = PaymentOptions { | ||||
|             submit_for_settlement, | ||||
|  | ||||
| @ -596,30 +596,42 @@ impl TryFrom<types::RefundsResponseRouterData<api::Execute, NuveiPaymentsRespons | ||||
|     fn try_from( | ||||
|         item: types::RefundsResponseRouterData<api::Execute, NuveiPaymentsResponse>, | ||||
|     ) -> Result<Self, Self::Error> { | ||||
|         let refund_status = item | ||||
|             .response | ||||
|         let response = item.response; | ||||
|         let http_code = item.http_code; | ||||
|         let refund_status = response | ||||
|             .transaction_status | ||||
|             .clone() | ||||
|             .map(|a| a.into()) | ||||
|             .unwrap_or_else(|| enums::RefundStatus::Failure); | ||||
|         let refund_response = match item.response.status { | ||||
|             .unwrap_or(enums::RefundStatus::Failure); | ||||
|         let refund_response = match response.status { | ||||
|             NuveiPaymentStatus::Error => Err(types::ErrorResponse { | ||||
|                 code: item | ||||
|                     .response | ||||
|                 code: response | ||||
|                     .err_code | ||||
|                     .map(|c| c.to_string()) | ||||
|                     .unwrap_or_else(|| consts::NO_ERROR_CODE.to_string()), | ||||
|                 message: item | ||||
|                     .response | ||||
|                 message: response | ||||
|                     .reason | ||||
|                     .unwrap_or_else(|| consts::NO_ERROR_MESSAGE.to_string()), | ||||
|                 reason: None, | ||||
|                 status_code: item.http_code, | ||||
|                 status_code: http_code, | ||||
|             }), | ||||
|             _ => match response.transaction_status { | ||||
|                 Some(NuveiTransactionStatus::Error) => Err(types::ErrorResponse { | ||||
|                     code: response | ||||
|                         .gw_error_code | ||||
|                         .map(|c| c.to_string()) | ||||
|                         .unwrap_or_else(|| consts::NO_ERROR_CODE.to_string()), | ||||
|                     message: response | ||||
|                         .gw_error_reason | ||||
|                         .unwrap_or_else(|| consts::NO_ERROR_MESSAGE.to_string()), | ||||
|                     reason: None, | ||||
|                     status_code: http_code, | ||||
|                 }), | ||||
|                 _ => Ok(types::RefundsResponseData { | ||||
|                 connector_refund_id: item.response.transaction_id.ok_or(errors::ParsingError)?, | ||||
|                     connector_refund_id: response.transaction_id.ok_or(errors::ParsingError)?, | ||||
|                     refund_status, | ||||
|                 }), | ||||
|             }, | ||||
|         }; | ||||
|         Ok(Self { | ||||
|             response: refund_response, | ||||
| @ -635,30 +647,42 @@ impl TryFrom<types::RefundsResponseRouterData<api::RSync, NuveiPaymentsResponse> | ||||
|     fn try_from( | ||||
|         item: types::RefundsResponseRouterData<api::RSync, NuveiPaymentsResponse>, | ||||
|     ) -> Result<Self, Self::Error> { | ||||
|         let refund_status = item | ||||
|             .response | ||||
|         let response = item.response; | ||||
|         let http_code = item.http_code; | ||||
|         let refund_status = response | ||||
|             .transaction_status | ||||
|             .clone() | ||||
|             .map(|a| a.into()) | ||||
|             .unwrap_or(enums::RefundStatus::Failure); | ||||
|         let refund_response = match item.response.status { | ||||
|         let refund_response = match response.status { | ||||
|             NuveiPaymentStatus::Error => Err(types::ErrorResponse { | ||||
|                 code: item | ||||
|                     .response | ||||
|                 code: response | ||||
|                     .err_code | ||||
|                     .map(|c| c.to_string()) | ||||
|                     .unwrap_or_else(|| consts::NO_ERROR_CODE.to_string()), | ||||
|                 message: item | ||||
|                     .response | ||||
|                 message: response | ||||
|                     .reason | ||||
|                     .unwrap_or_else(|| consts::NO_ERROR_MESSAGE.to_string()), | ||||
|                 reason: None, | ||||
|                 status_code: item.http_code, | ||||
|                 status_code: http_code, | ||||
|             }), | ||||
|             _ => match response.transaction_status { | ||||
|                 Some(NuveiTransactionStatus::Error) => Err(types::ErrorResponse { | ||||
|                     code: response | ||||
|                         .gw_error_code | ||||
|                         .map(|c| c.to_string()) | ||||
|                         .unwrap_or_else(|| consts::NO_ERROR_CODE.to_string()), | ||||
|                     message: response | ||||
|                         .gw_error_reason | ||||
|                         .unwrap_or_else(|| consts::NO_ERROR_MESSAGE.to_string()), | ||||
|                     reason: None, | ||||
|                     status_code: http_code, | ||||
|                 }), | ||||
|                 _ => Ok(types::RefundsResponseData { | ||||
|                 connector_refund_id: item.response.transaction_id.ok_or(errors::ParsingError)?, | ||||
|                     connector_refund_id: response.transaction_id.ok_or(errors::ParsingError)?, | ||||
|                     refund_status, | ||||
|                 }), | ||||
|             }, | ||||
|         }; | ||||
|         Ok(Self { | ||||
|             response: refund_response, | ||||
|  | ||||
| @ -323,3 +323,35 @@ pub fn get_header_key_value<'a>( | ||||
|             errors::ConnectorError::WebhookSourceVerificationFailed | ||||
|         ))? | ||||
| } | ||||
|  | ||||
| pub fn to_currency_base_unit_from_optional_amount( | ||||
|     amount: Option<i64>, | ||||
|     currency: storage_models::enums::Currency, | ||||
| ) -> Result<String, error_stack::Report<errors::ConnectorError>> { | ||||
|     match amount { | ||||
|         Some(a) => to_currency_base_unit(a, currency), | ||||
|         _ => Err(errors::ConnectorError::MissingRequiredField { | ||||
|             field_name: "amount", | ||||
|         } | ||||
|         .into()), | ||||
|     } | ||||
| } | ||||
|  | ||||
| pub fn to_currency_base_unit( | ||||
|     amount: i64, | ||||
|     currency: storage_models::enums::Currency, | ||||
| ) -> Result<String, error_stack::Report<errors::ConnectorError>> { | ||||
|     let amount_u32 = u32::try_from(amount) | ||||
|         .into_report() | ||||
|         .change_context(errors::ConnectorError::RequestEncodingFailed)?; | ||||
|     match currency { | ||||
|         storage_models::enums::Currency::JPY | storage_models::enums::Currency::KRW => { | ||||
|             Ok(amount.to_string()) | ||||
|         } | ||||
|         storage_models::enums::Currency::BHD | ||||
|         | storage_models::enums::Currency::JOD | ||||
|         | storage_models::enums::Currency::KWD | ||||
|         | storage_models::enums::Currency::OMR => Ok((f64::from(amount_u32) / 1000.0).to_string()), | ||||
|         _ => Ok((f64::from(amount_u32) / 100.0).to_string()), | ||||
|     } | ||||
| } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 SamraatBansal
					SamraatBansal