Bug: [REFACTOR]: [FISERV] Add amount conversion framework to Fiserv



### :memo: Feature Description

Currently, amounts are represented as `i64` values throughout the application. We want to introduce a `Unit` struct that explicitly states the denomination. A new type, `MinorUnit`, has been added to standardize the flow of amounts across the application. This type will now be used by all the connector flows.

Rather than handling conversions in each connector, we will centralize the conversion logic in one place within the core of the application.

### :hammer: Possible Implementation

- For each connector, we need to create an amount conversion function. Connectors will specify the format they require, and the core framework will handle the conversion accordingly.
- Connectors should invoke the `convert` function to receive the amount in their required format.
- Refer to the [connector documentation](https://docs.fiserv.dev/public/reference/createpaymenturl) to determine the required amount format for each connector.
- You can refer [this PR](https://github.com/juspay/hyperswitch/pull/4825) for more context.


🔖 Note: All the changes needed should be contained within `hyperswitch/crates/router/src/connector/` , `crates/router/src/types/api.rs` , `crates/router/tests/connectors/`


### :package: Have you spent some time checking if this feature request has been raised before?

- [X] I checked and didn't find a similar issue

### :package: Have you read the Contributing Guidelines?

- [X] I have read the [Contributing Guidelines](https://github.com/juspay/hyperswitch/blob/main/docs/CONTRIBUTING.md)

###  :sparkles: Are you willing to submit a PR?

### Submission Process:
- Ask the maintainers for assignment of the issue, you can request for assignment by commenting on the issue itself.
- Once assigned, submit a pull request (PR).
- Maintainers will review and provide feedback, if any. 
- Maintainers can unassign issues due to inactivity, [read more here](https://github.com/juspay/hyperswitch/wiki/Hacktoberfest-Contribution-Rules).

Refer [here](https://github.com/juspay/hyperswitch/blob/main/docs/TERMS_OF_CONTEST.md) for Terms and conditions for the contest.

diff --git a/crates/hyperswitch_connectors/src/connectors/fiserv.rs b/crates/hyperswitch_connectors/src/connectors/fiserv.rs
index e80c57454a0..50eebb99518 100644
--- a/crates/hyperswitch_connectors/src/connectors/fiserv.rs
+++ b/crates/hyperswitch_connectors/src/connectors/fiserv.rs
@@ -1,13 +1,12 @@
 pub mod transformers;
 
-use std::fmt::Debug;
-
 use base64::Engine;
 use common_enums::enums;
 use common_utils::{
     errors::CustomResult,
     ext_traits::BytesExt,
     request::{Method, Request, RequestBuilder, RequestContent},
+    types::{AmountConvertor, FloatMajorUnit, FloatMajorUnitForConnector},
 };
 use error_stack::{report, ResultExt};
 use hyperswitch_domain_models::{
@@ -44,12 +43,23 @@ use time::OffsetDateTime;
 use transformers as fiserv;
 use uuid::Uuid;
 
-use crate::{constants::headers, types::ResponseRouterData, utils};
+use crate::{
+    constants::headers,
+    types::ResponseRouterData,
+    utils::{construct_not_implemented_error_report, convert_amount},
+};
 
-#[derive(Debug, Clone)]
-pub struct Fiserv;
+#[derive(Clone)]
+pub struct Fiserv {
+    amount_converter: &'static (dyn AmountConvertor<Output = FloatMajorUnit> + Sync),
+}
 
 impl Fiserv {
+    pub fn new() -> &'static Self {
+        &Self {
+            amount_converter: &FloatMajorUnitForConnector,
+        }
+    }
     pub fn generate_authorization_signature(
         &self,
         auth: fiserv::FiservAuthType,
@@ -194,7 +204,7 @@ impl ConnectorValidation for Fiserv {
             | enums::CaptureMethod::Manual
             | enums::CaptureMethod::SequentialAutomatic => Ok(()),
             enums::CaptureMethod::ManualMultiple | enums::CaptureMethod::Scheduled => Err(
-                utils::construct_not_implemented_error_report(capture_method, self.id()),
+                construct_not_implemented_error_report(capture_method, self.id()),
             ),
         }
     }
@@ -421,12 +431,12 @@ impl ConnectorIntegration<Capture, PaymentsCaptureData, PaymentsResponseData> fo
         req: &PaymentsCaptureRouterData,
         _connectors: &Connectors,
     ) -> CustomResult<RequestContent, errors::ConnectorError> {
-        let router_obj = fiserv::FiservRouterData::try_from((
-            &self.get_currency_unit(),
+        let amount_to_capture = convert_amount(
+            self.amount_converter,
+            req.request.minor_amount_to_capture,
             req.request.currency,
-            req.request.amount_to_capture,
-            req,
-        ))?;
+        )?;
+        let router_obj = fiserv::FiservRouterData::try_from((amount_to_capture, req))?;
         let connector_req = fiserv::FiservCaptureRequest::try_from(&router_obj)?;
         Ok(RequestContent::Json(Box::new(connector_req)))
     }
@@ -530,12 +540,12 @@ impl ConnectorIntegration<Authorize, PaymentsAuthorizeData, PaymentsResponseData
         req: &PaymentsAuthorizeRouterData,
         _connectors: &Connectors,
     ) -> CustomResult<RequestContent, errors::ConnectorError> {
-        let router_obj = fiserv::FiservRouterData::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 router_obj = fiserv::FiservRouterData::try_from((amount, req))?;
         let connector_req = fiserv::FiservPaymentsRequest::try_from(&router_obj)?;
         Ok(RequestContent::Json(Box::new(connector_req)))
     }
@@ -624,12 +634,12 @@ impl ConnectorIntegration<Execute, RefundsData, RefundsResponseData> for Fiserv
         req: &RefundsRouterData<Execute>,
         _connectors: &Connectors,
     ) -> CustomResult<RequestContent, errors::ConnectorError> {
-        let router_obj = fiserv::FiservRouterData::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 router_obj = fiserv::FiservRouterData::try_from((refund_amount, req))?;
         let connector_req = fiserv::FiservRefundRequest::try_from(&router_obj)?;
         Ok(RequestContent::Json(Box::new(connector_req)))
     }
diff --git a/crates/hyperswitch_connectors/src/connectors/fiserv/transformers.rs b/crates/hyperswitch_connectors/src/connectors/fiserv/transformers.rs
index d6e2cd54db7..8f9a15e49c2 100644
--- a/crates/hyperswitch_connectors/src/connectors/fiserv/transformers.rs
+++ b/crates/hyperswitch_connectors/src/connectors/fiserv/transformers.rs
@@ -1,5 +1,5 @@
 use common_enums::enums;
-use common_utils::{ext_traits::ValueExt, pii};
+use common_utils::{ext_traits::ValueExt, pii, types::FloatMajorUnit};
 use error_stack::ResultExt;
 use hyperswitch_domain_models::{
     payment_method_data::PaymentMethodData,
@@ -9,7 +9,7 @@ use hyperswitch_domain_models::{
     router_response_types::{PaymentsResponseData, RefundsResponseData},
     types,
 };
-use hyperswitch_interfaces::{api, errors};
+use hyperswitch_interfaces::errors;
 use masking::Secret;
 use serde::{Deserialize, Serialize};
 
@@ -23,22 +23,14 @@ use crate::{
 
 #[derive(Debug, Serialize)]
 pub struct FiservRouterData<T> {
-    pub amount: String,
+    pub amount: FloatMajorUnit,
     pub router_data: T,
 }
 
-impl<T> TryFrom<(&api::CurrencyUnit, enums::Currency, i64, T)> for FiservRouterData<T> {
+impl<T> TryFrom<(FloatMajorUnit, T)> for FiservRouterData<T> {
     type Error = error_stack::Report<errors::ConnectorError>;
 
-    fn try_from(
-        (currency_unit, currency, amount, router_data): (
-            &api::CurrencyUnit,
-            enums::Currency,
-            i64,
-            T,
-        ),
-    ) -> Result<Self, Self::Error> {
-        let amount = utils::get_amount_as_string(currency_unit, amount, currency)?;
+    fn try_from((amount, router_data): (FloatMajorUnit, T)) -> Result<Self, Self::Error> {
         Ok(Self {
             amount,
             router_data,
@@ -89,8 +81,7 @@ pub struct GooglePayToken {
 
 #[derive(Default, Debug, Serialize)]
 pub struct Amount {
-    #[serde(serialize_with = "utils::str_to_f32")]
-    total: String,
+    total: FloatMajorUnit,
     currency: String,
 }
 
@@ -143,7 +134,7 @@ impl TryFrom<&FiservRouterData<&types::PaymentsAuthorizeRouterData>> for FiservP
     ) -> Result<Self, Self::Error> {
         let auth: FiservAuthType = FiservAuthType::try_from(&item.router_data.connector_auth_type)?;
         let amount = Amount {
-            total: item.amount.clone(),
+            total: item.amount,
             currency: item.router_data.request.currency.to_string(),
         };
         let transaction_details = TransactionDetails {
@@ -484,7 +475,7 @@ impl TryFrom<&FiservRouterData<&types::PaymentsCaptureRouterData>> for FiservCap
             })?;
         Ok(Self {
             amount: Amount {
-                total: item.amount.clone(),
+                total: item.amount,
                 currency: item.router_data.request.currency.to_string(),
             },
             transaction_details: TransactionDetails {
@@ -579,7 +570,7 @@ impl<F> TryFrom<&FiservRouterData<&types::RefundsRouterData<F>>> for FiservRefun
             })?;
         Ok(Self {
             amount: Amount {
-                total: item.amount.clone(),
+                total: item.amount,
                 currency: item.router_data.request.currency.to_string(),
             },
             merchant_details: MerchantDetails {
diff --git a/crates/hyperswitch_connectors/src/connectors/helcim.rs b/crates/hyperswitch_connectors/src/connectors/helcim.rs
index 844eab7825f..79b950063c3 100644
--- a/crates/hyperswitch_connectors/src/connectors/helcim.rs
+++ b/crates/hyperswitch_connectors/src/connectors/helcim.rs
@@ -1,5 +1,4 @@
 pub mod transformers;
-use std::fmt::Debug;
 
 use api_models::webhooks::IncomingWebhookEvent;
 use common_enums::enums;
@@ -7,6 +6,7 @@ use common_utils::{
     errors::CustomResult,
     ext_traits::BytesExt,
     request::{Method, Request, RequestBuilder, RequestContent},
+    types::{AmountConvertor, FloatMajorUnit, FloatMajorUnitForConnector},
 };
 use error_stack::{report, ResultExt};
 use hyperswitch_domain_models::{
@@ -49,11 +49,21 @@ use transformers as helcim;
 use crate::{
     constants::headers,
     types::ResponseRouterData,
-    utils::{to_connector_meta, PaymentsAuthorizeRequestData},
+    utils::{convert_amount, to_connector_meta, PaymentsAuthorizeRequestData},
 };
 
-#[derive(Debug, Clone)]
-pub struct Helcim;
+#[derive(Clone)]
+pub struct Helcim {
+    amount_convertor: &'static (dyn AmountConvertor<Output = FloatMajorUnit> + Sync),
+}
+
+impl Helcim {
+    pub fn new() -> &'static Self {
+        &Self {
+            amount_convertor: &FloatMajorUnitForConnector,
+        }
+    }
+}
 
 impl api::Payment for Helcim {}
 impl api::PaymentSession for Helcim {}
@@ -305,13 +315,13 @@ impl ConnectorIntegration<Authorize, PaymentsAuthorizeData, PaymentsResponseData
         req: &PaymentsAuthorizeRouterData,
         _connectors: &Connectors,
     ) -> CustomResult<RequestContent, errors::ConnectorError> {
-        let connector_router_data = helcim::HelcimRouterData::try_from((
-            &self.get_currency_unit(),
+        let connector_router_data = convert_amount(
+            self.amount_convertor,
+            req.request.minor_amount,
             req.request.currency,
-            req.request.amount,
-            req,
-        ))?;
-        let connector_req = helcim::HelcimPaymentsRequest::try_from(&connector_router_data)?;
+        )?;
+        let router_obj = helcim::HelcimRouterData::try_from((connector_router_data, req))?;
+        let connector_req = helcim::HelcimPaymentsRequest::try_from(&router_obj)?;
         Ok(RequestContent::Json(Box::new(connector_req)))
     }
 
@@ -484,13 +494,13 @@ impl ConnectorIntegration<Capture, PaymentsCaptureData, PaymentsResponseData> fo
         req: &PaymentsCaptureRouterData,
         _connectors: &Connectors,
     ) -> CustomResult<RequestContent, errors::ConnectorError> {
-        let connector_router_data = helcim::HelcimRouterData::try_from((
-            &self.get_currency_unit(),
+        let connector_router_data = convert_amount(
+            self.amount_convertor,
+            req.request.minor_amount_to_capture,
             req.request.currency,
-            req.request.amount_to_capture,
-            req,
-        ))?;
-        let connector_req = helcim::HelcimCaptureRequest::try_from(&connector_router_data)?;
+        )?;
+        let router_obj = helcim::HelcimRouterData::try_from((connector_router_data, req))?;
+        let connector_req = helcim::HelcimCaptureRequest::try_from(&router_obj)?;
         Ok(RequestContent::Json(Box::new(connector_req)))
     }
 
@@ -651,13 +661,13 @@ impl ConnectorIntegration<Execute, RefundsData, RefundsResponseData> for Helcim
         req: &RefundsRouterData<Execute>,
         _connectors: &Connectors,
     ) -> CustomResult<RequestContent, errors::ConnectorError> {
-        let connector_router_data = helcim::HelcimRouterData::try_from((
-            &self.get_currency_unit(),
+        let connector_router_data = convert_amount(
+            self.amount_convertor,
+            req.request.minor_refund_amount,
             req.request.currency,
-            req.request.refund_amount,
-            req,
-        ))?;
-        let connector_req = helcim::HelcimRefundRequest::try_from(&connector_router_data)?;
+        )?;
+        let router_obj = helcim::HelcimRouterData::try_from((connector_router_data, req))?;
+        let connector_req = helcim::HelcimRefundRequest::try_from(&router_obj)?;
         Ok(RequestContent::Json(Box::new(connector_req)))
     }
 
diff --git a/crates/hyperswitch_connectors/src/connectors/helcim/transformers.rs b/crates/hyperswitch_connectors/src/connectors/helcim/transformers.rs
index 0a5453a49d0..d890bd88ac3 100644
--- a/crates/hyperswitch_connectors/src/connectors/helcim/transformers.rs
+++ b/crates/hyperswitch_connectors/src/connectors/helcim/transformers.rs
@@ -1,5 +1,8 @@
 use common_enums::enums;
-use common_utils::pii::{Email, IpAddress};
+use common_utils::{
+    pii::{Email, IpAddress},
+    types::FloatMajorUnit,
+};
 use error_stack::ResultExt;
 use hyperswitch_domain_models::{
     payment_method_data::{Card, PaymentMethodData},
@@ -15,10 +18,7 @@ use hyperswitch_domain_models::{
         RefundsRouterData, SetupMandateRouterData,
     },
 };
-use hyperswitch_interfaces::{
-    api::{self},
-    errors,
-};
+use hyperswitch_interfaces::errors;
 use masking::Secret;
 use serde::{Deserialize, Serialize};
 
@@ -33,16 +33,13 @@ use crate::{
 
 #[derive(Debug, Serialize)]
 pub struct HelcimRouterData<T> {
-    pub amount: f64,
+    pub amount: FloatMajorUnit,
     pub router_data: T,
 }
 
-impl<T> TryFrom<(&api::CurrencyUnit, enums::Currency, i64, T)> for HelcimRouterData<T> {
+impl<T> TryFrom<(FloatMajorUnit, T)> for HelcimRouterData<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> {
-        let amount = crate::utils::get_amount_as_f64(currency_unit, amount, currency)?;
+    fn try_from((amount, item): (FloatMajorUnit, T)) -> Result<Self, Self::Error> {
         Ok(Self {
             amount,
             router_data: item,
@@ -77,7 +74,7 @@ pub struct HelcimVerifyRequest {
 #[derive(Debug, Serialize)]
 #[serde(rename_all = "camelCase")]
 pub struct HelcimPaymentsRequest {
-    amount: f64,
+    amount: FloatMajorUnit,
     currency: enums::Currency,
     ip_address: Secret<String, IpAddress>,
     card_data: HelcimCard,
@@ -115,8 +112,8 @@ pub struct HelcimInvoice {
 pub struct HelcimLineItems {
     description: String,
     quantity: u8,
-    price: f64,
-    total: f64,
+    price: FloatMajorUnit,
+    total: FloatMajorUnit,
 }
 
 #[derive(Debug, Serialize)]
@@ -514,7 +511,7 @@ impl<F>
 #[serde(rename_all = "camelCase")]
 pub struct HelcimCaptureRequest {
     pre_auth_transaction_id: u64,
-    amount: f64,
+    amount: FloatMajorUnit,
     ip_address: Secret<String, IpAddress>,
     #[serde(skip_serializing_if = "Option::is_none")]
     ecommerce: Option<bool>,
@@ -637,7 +634,7 @@ impl<F>
 #[derive(Debug, Serialize)]
 #[serde(rename_all = "camelCase")]
 pub struct HelcimRefundRequest {
-    amount: f64,
+    amount: FloatMajorUnit,
     original_transaction_id: u64,
     ip_address: Secret<String, IpAddress>,
     #[serde(skip_serializing_if = "Option::is_none")]
diff --git a/crates/hyperswitch_connectors/src/utils.rs b/crates/hyperswitch_connectors/src/utils.rs
index ce40e373462..fd26e459539 100644
--- a/crates/hyperswitch_connectors/src/utils.rs
+++ b/crates/hyperswitch_connectors/src/utils.rs
@@ -57,7 +57,6 @@ use masking::{ExposeInterface, PeekInterface, Secret};
 use once_cell::sync::Lazy;
 use regex::Regex;
 use router_env::logger;
-use serde::Serializer;
 use serde_json::Value;
 use time::PrimitiveDateTime;
 
@@ -344,16 +343,6 @@ pub(crate) fn construct_not_implemented_error_report(
         .into()
 }
 
-pub(crate) fn str_to_f32<S>(value: &str, serializer: S) -> Result<S::Ok, S::Error>
-where
-    S: Serializer,
-{
-    let float_value = value.parse::<f64>().map_err(|_| {
-        serde::ser::Error::custom("Invalid string, cannot be converted to float value")
-    })?;
-    serializer.serialize_f64(float_value)
-}
-
 pub(crate) const SELECTED_PAYMENT_METHOD: &str = "Selected payment method";
 
 pub(crate) fn get_unimplemented_payment_method_error_message(connector: &str) -> String {
diff --git a/crates/router/src/types/api.rs b/crates/router/src/types/api.rs
index 99d577c657b..3247395ad7e 100644
--- a/crates/router/src/types/api.rs
+++ b/crates/router/src/types/api.rs
@@ -432,7 +432,9 @@ impl ConnectorData {
                 enums::Connector::Elavon => {
                     Ok(ConnectorEnum::Old(Box::new(connector::Elavon::new())))
                 }
-                enums::Connector::Fiserv => Ok(ConnectorEnum::Old(Box::new(&connector::Fiserv))),
+                enums::Connector::Fiserv => {
+                    Ok(ConnectorEnum::Old(Box::new(connector::Fiserv::new())))
+                }
                 enums::Connector::Fiservemea => {
                     Ok(ConnectorEnum::Old(Box::new(connector::Fiservemea::new())))
                 }
@@ -453,7 +455,9 @@ impl ConnectorData {
                     Ok(ConnectorEnum::Old(Box::new(&connector::Gocardless)))
                 }
                 // enums::Connector::Hipay => Ok(ConnectorEnum::Old(Box::new(connector::Hipay))),
-                enums::Connector::Helcim => Ok(ConnectorEnum::Old(Box::new(&connector::Helcim))),
+                enums::Connector::Helcim => {
+                    Ok(ConnectorEnum::Old(Box::new(connector::Helcim::new())))
+                }
                 enums::Connector::Iatapay => {
                     Ok(ConnectorEnum::Old(Box::new(connector::Iatapay::new())))
                 }
diff --git a/crates/router/tests/connectors/fiserv.rs b/crates/router/tests/connectors/fiserv.rs
index 7f13de31004..78235278ed9 100644
--- a/crates/router/tests/connectors/fiserv.rs
+++ b/crates/router/tests/connectors/fiserv.rs
@@ -16,7 +16,7 @@ impl utils::Connector for FiservTest {
     fn get_data(&self) -> types::api::ConnectorData {
         use router::connector::Fiserv;
         utils::construct_connector_data_old(
-            Box::new(&Fiserv),
+            Box::new(Fiserv::new()),
             types::Connector::Fiserv,
             types::api::GetToken::Connector,
             None,
diff --git a/crates/router/tests/connectors/helcim.rs b/crates/router/tests/connectors/helcim.rs
index 761b07736ce..5b02e2f8431 100644
--- a/crates/router/tests/connectors/helcim.rs
+++ b/crates/router/tests/connectors/helcim.rs
@@ -11,7 +11,7 @@ impl utils::Connector for HelcimTest {
     fn get_data(&self) -> types::api::ConnectorData {
         use router::connector::Helcim;
         utils::construct_connector_data_old(
-            Box::new(&Helcim),
+            Box::new(Helcim::new()),
             types::Connector::Helcim,
             types::api::GetToken::Connector,
             None,

## Type of Change
<!-- Put an `x` in the boxes that apply -->

- [ ] Bugfix
- [ ] New feature
- [ ] Enhancement
- [x] Refactoring
- [ ] Dependency updates
- [ ] Documentation
- [ ] CI/CD

## Description
<!-- Describe your changes in detail -->
added **FloatMajorUnit** for amount conversion for **Fiserv**
added **FloatMajorUnit** for amount conversion for **Helcim**

### Additional Changes

- [ ] This PR modifies the API contract
- [ ] This PR modifies the database schema
- [ ] This PR modifies application configuration/environment variables

<!--
Provide links to the files with corresponding changes.

Following are the paths where you can find config files:
1. `config`
2. `crates/router/src/configs`
3. `loadtest/config`
-->


## Motivation and Context
<!--
Why is this change required? What problem does it solve?
If it fixes an open issue, please link to the issue here.

If you don't have an issue, we'd recommend starting with one first so the PR
can focus on the implementation (unless it is an obvious bug or documentation fix
that will have little conversation).
-->
fixes #6256 and #6019

## How did you test it?
<!--
Did you write an integration/unit/API test to verify the code changes?
Or did you test this change manually (provide relevant screenshots)?
-->
Tested through postman:

- Create a MCA for **fiserv**:
- Create a Payment with **fiserv**:

request:
```
{
    "amount": 10000,
    "currency": "USD",
    "amount_to_capture": 10000,
    "confirm": true,
    "profile_id": {{profile_id}},
    "capture_method": "automatic",
    "capture_on": "2022-09-10T10:11:12Z",
    "authentication_type": "no_three_ds",
    "setup_future_usage": "on_session",
    "customer": {
        "id": "customer123",
        "name": "John Doe",
        "email": "customer@gmail.com",
        "phone": "9999999999",
        "phone_country_code": "+1"
    },
    "customer_id": "customer123",
    "phone_country_code": "+1",
    "description": "Its my first payment request",
    "return_url": "https://google.com",
    "payment_method": "card",
    "payment_method_type": "credit",
    "payment_method_data": { 
        "card": {
            "card_number": "4147463011110083",
            "card_exp_month": "10",
            "card_exp_year": "25",
            "card_holder_name": "joseph Doe",
            "card_cvc": "123"
        }
    },
    "billing": {
        "address": {
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "city": "San Fransico",
            "state": "California",
            "zip": "94122",
            "country": "US",
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": {
            "number": "9999999999",
            "country_code": "+91"
        },
        "email": "guest@example.com"
    },
    "shipping": {
        "address": {
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "city": "San Fransico",
            "state": "California",
            "zip": "94122",
            "country": "US",
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": {
            "number": "9999999999",
            "country_code": "+91"
        },
        "email": "guest@example.com"
    },
    "statement_descriptor_name": "joseph",
    "statement_descriptor_suffix": "JS",
    "order_details": [
        {
            "product_name": "Apple iphone 15",
            "quantity": 1,
            "amount": 6540,
            "account_name": "transaction_processing"
        }
    ],
    "metadata": {
        "udf1": "value1",
        "new_customer": "true",
        "login_date": "2019-09-10T10:11:12Z"
    },
    "browser_info": {
        "user_agent": "Mozilla\/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/70.0.3538.110 Safari\/537.36",
        "accept_header": "text\/html,application\/xhtml+xml,application\/xml;q=0.9,image\/webp,image\/apng,*\/*;q=0.8",
        "language": "nl-NL",
        "color_depth": 24,
        "screen_height": 723,
        "screen_width": 1536,
        "time_zone": 0,
        "java_enabled": true,
        "java_script_enabled": true,
        "ip_address": "128.0.0.1"
    },
    "customer_acceptance": {
        "acceptance_type": "offline",
        "accepted_at": "1963-05-03T04:07:52.723Z",
        "online": {
            "ip_address": "125.0.0.1",
            "user_agent": "amet irure esse"
        }
    },
    //Some connectors like Apple Pay, Airwallex and Noon might require some additional information, find more in the doc.
    "connector_metadata": {
        "noon": {
            "order_category": "pay"
        }
    },
    "payment_link": false,
    "payment_link_config": {
        "theme": "",
        "logo": "",
        "seller_name": "",
        "sdk_layout": "",
        "display_sdk_only": false,
        "enabled_saved_payment_method": false
    },
    "payment_type": "normal", 
    "request_incremental_authorization": false,
    "merchant_order_reference_id": "test_ord",
    "session_expiry": 900 
}
```
response: - The payment should be succeeded 
```
{
    "payment_id": "pay_9mnPycKv5V2w9aNCHyO8",
    "merchant_id": "merchant_1740127595",
    "status": "succeeded",
    "amount": 10000,
    "net_amount": 10000,
    "shipping_cost": null,
    "amount_capturable": 0,
    "amount_received": 10000,
    "connector": "fiserv",
    "client_secret": "pay_9mnPycKv5V2w9aNCHyO8_secret_X4CTRqm4Ldyx6L7s2OPa",
    "created": "2025-02-21T08:46:50.624Z",
    "currency": "USD",
    "customer_id": "customer123",
    "customer": {
        "id": "customer123",
        "name": "John Doe",
        "email": "customer@gmail.com",
        "phone": "9999999999",
        "phone_country_code": "+1"
    },
    "description": "Its my first payment request",
    "refunds": null,
    "disputes": null,
    "mandate_id": null,
    "mandate_data": null,
    "setup_future_usage": "on_session",
    "off_session": null,
    "capture_on": null,
    "capture_method": "automatic",
    "payment_method": "card",
    "payment_method_data": {
        "card": {
            "last4": "0083",
            "card_type": null,
            "card_network": null,
            "card_issuer": null,
            "card_issuing_country": null,
            "card_isin": "414746",
            "card_extended_bin": null,
            "card_exp_month": "10",
            "card_exp_year": "25",
            "card_holder_name": "joseph Doe",
            "payment_checks": null,
            "authentication_data": null
        },
        "billing": null
    },
    "payment_token": null,
    "shipping": {
        "address": {
            "city": "San Fransico",
            "country": "US",
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "zip": "94122",
            "state": "California",
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": {
            "number": "9999999999",
            "country_code": "+91"
        },
        "email": "guest@example.com"
    },
    "billing": {
        "address": {
            "city": "San Fransico",
            "country": "US",
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "zip": "94122",
            "state": "California",
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": {
            "number": "9999999999",
            "country_code": "+91"
        },
        "email": "guest@example.com"
    },
    "order_details": [
        {
            "brand": null,
            "amount": 6540,
            "category": null,
            "quantity": 1,
            "tax_rate": null,
            "product_id": null,
            "product_name": "Apple iphone 15",
            "product_type": null,
            "sub_category": null,
            "product_img_link": null,
            "product_tax_code": null,
            "total_tax_amount": null,
            "requires_shipping": null
        }
    ],
    "email": "customer@gmail.com",
    "name": "John Doe",
    "phone": "9999999999",
    "return_url": "https://google.com/",
    "authentication_type": "no_three_ds",
    "statement_descriptor_name": "joseph",
    "statement_descriptor_suffix": "JS",
    "next_action": null,
    "cancellation_reason": null,
    "error_code": null,
    "error_message": null,
    "unified_code": null,
    "unified_message": null,
    "payment_experience": null,
    "payment_method_type": "credit",
    "connector_label": null,
    "business_country": null,
    "business_label": "default",
    "business_sub_label": null,
    "allowed_payment_method_types": null,
    "ephemeral_key": {
        "customer_id": "customer123",
        "created_at": 1740127610,
        "expires": 1740131210,
        "secret": "epk_a6328125a3ad471d88ef13493272c1cc"
    },
    "manual_retry_allowed": false,
    "connector_transaction_id": "6f2fdeb7a1884bc0957c0f977644c30c",
    "frm_message": null,
    "metadata": {
        "udf1": "value1",
        "login_date": "2019-09-10T10:11:12Z",
        "new_customer": "true"
    },
    "connector_metadata": {
        "apple_pay": null,
        "airwallex": null,
        "noon": {
            "order_category": "pay"
        }
    },
    "feature_metadata": null,
    "reference_id": "CHG015117c1ffa76779d655a830730d7add1a",
    "payment_link": null,
    "profile_id": "pro_IxmWaGQVX320n30wDNuM",
    "surcharge_details": null,
    "attempt_count": 1,
    "merchant_decision": null,
    "merchant_connector_id": "mca_o2Tw2yV2oWr4vEC5b22q",
    "incremental_authorization_allowed": false,
    "authorization_count": null,
    "incremental_authorizations": null,
    "external_authentication_details": null,
    "external_3ds_authentication_attempted": false,
    "expires_on": "2025-02-21T09:01:50.623Z",
    "fingerprint": null,
    "browser_info": {
        "language": "nl-NL",
        "time_zone": 0,
        "ip_address": "128.0.0.1",
        "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36",
        "color_depth": 24,
        "java_enabled": true,
        "screen_width": 1536,
        "accept_header": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
        "screen_height": 723,
        "java_script_enabled": true
    },
    "payment_method_id": null,
    "payment_method_status": null,
    "updated": "2025-02-21T08:46:54.326Z",
    "split_payments": null,
    "frm_metadata": null,
    "extended_authorization_applied": null,
    "capture_before": null,
    "merchant_order_reference_id": "test_ord",
    "order_tax_amount": null,
    "connector_mandate_id": null,
    "card_discovery": "manual"
}
```
using curl : 
<img width="614" alt="Screenshot 2025-03-11 at 10 48 50 PM" src="https://github.com/user-attachments/assets/da58c0b9-6dbf-4bab-94d3-37817eac3479" />
<img width="1496" alt="Screenshot 2025-03-11 at 10 51 03 PM" src="https://github.com/user-attachments/assets/e2f6e5f6-40d6-4253-ac82-9ea6da361eac" />

- Create a MCA for **helcim**:
- Create a Payment with **helcim**:

```
{
    "amount": 100,
    "currency": "USD",
    "confirm": true,
    "capture_method": "automatic",
    "capture_on": "2022-09-10T10:11:12Z",
    "amount_to_capture": 100,
    "customer_id": "helcim",
    "email": "guest@example.com",
    "name": "John Doe",
    "phone": "999999999",
    "phone_country_code": "+1",
    "description": "Its my first payment request",
    "authentication_type": "no_three_ds",
    "return_url": "https://google.com",
    "payment_method": "card",
    "payment_method_type": "credit",
    "payment_method_data": {
        "card": {
            "card_number": "5413330089099130",
            "card_exp_month": "01",
            "card_exp_year": "28",
            "card_holder_name": "joseph Doe",
            "card_cvc": "100"
        }
    },
    "billing": {
        "address": {
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "city": "San Fransico",
            "state": "California",
            "zip": "94122",
            "country": "US",
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": {
            "number": "8056594427",
            "country_code": "+91"
        }
    },
    "shipping": {
        "address": {
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "city": "San Fransico",
            "state": "California",
            "zip": "94122",
            "country": "US",
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": {
            "number": "8056594427",
            "country_code": "+91"
        }
    },
    "statement_descriptor_name": "joseph",
    "statement_descriptor_suffix": "JS",
    "metadata": {
        "udf1": "value1",
        "new_customer": "true",
        "login_date": "2019-09-10T10:11:12Z"
    },
    "browser_info": {
        "color_depth": 24,
        "java_enabled": true,
        "java_script_enabled": true,
        "language": "en-US",
        "screen_height": 1080,
        "screen_width": 1920,
        "time_zone": 123,
        "ip_address": "192.168.1.1",
        "accept_header": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
        "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36",
        "os_type": "Windows",
        "os_version": "10",
        "device_model": "Desktop"
    },
    "order_details": [{
        "product_name":"something",
        "quantity": 4, 
        "amount" : 400
    }]
}
```
response: - The payment should be succeeded 
```
{
    "payment_id": "pay_TORNbtguEZUEleC3kYt5",
    "merchant_id": "merchant_1740386925",
    "status": "succeeded",
    "amount": 100,
    "net_amount": 100,
    "shipping_cost": null,
    "amount_capturable": 0,
    "amount_received": 100,
    "connector": "helcim",
    "client_secret": "pay_TORNbtguEZUEleC3kYt5_secret_PLV79VNxPEreoif4WfRh",
    "created": "2025-02-24T08:49:05.760Z",
    "currency": "USD",
    "customer_id": "helcim",
    "customer": {
        "id": "helcim",
        "name": "John Doe",
        "email": "guest@example.com",
        "phone": "999999999",
        "phone_country_code": "+1"
    },
    "description": "Its my first payment request",
    "refunds": null,
    "disputes": null,
    "mandate_id": null,
    "mandate_data": null,
    "setup_future_usage": null,
    "off_session": null,
    "capture_on": null,
    "capture_method": "automatic",
    "payment_method": "card",
    "payment_method_data": {
        "card": {
            "last4": "9130",
            "card_type": null,
            "card_network": null,
            "card_issuer": null,
            "card_issuing_country": null,
            "card_isin": "541333",
            "card_extended_bin": null,
            "card_exp_month": "01",
            "card_exp_year": "28",
            "card_holder_name": "joseph Doe",
            "payment_checks": null,
            "authentication_data": null
        },
        "billing": null
    },
    "payment_token": null,
    "shipping": {
        "address": {
            "city": "San Fransico",
            "country": "US",
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "zip": "94122",
            "state": "California",
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": {
            "number": "8056594427",
            "country_code": "+91"
        },
        "email": null
    },
    "billing": {
        "address": {
            "city": "San Fransico",
            "country": "US",
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "zip": "94122",
            "state": "California",
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": {
            "number": "8056594427",
            "country_code": "+91"
        },
        "email": null
    },
    "order_details": [
        {
            "brand": null,
            "amount": 400,
            "category": null,
            "quantity": 4,
            "tax_rate": null,
            "product_id": null,
            "product_name": "something",
            "product_type": null,
            "sub_category": null,
            "product_img_link": null,
            "product_tax_code": null,
            "total_tax_amount": null,
            "requires_shipping": null
        }
    ],
    "email": "guest@example.com",
    "name": "John Doe",
    "phone": "999999999",
    "return_url": "https://google.com/",
    "authentication_type": "no_three_ds",
    "statement_descriptor_name": "joseph",
    "statement_descriptor_suffix": "JS",
    "next_action": null,
    "cancellation_reason": null,
    "error_code": null,
    "error_message": null,
    "unified_code": null,
    "unified_message": null,
    "payment_experience": null,
    "payment_method_type": "credit",
    "connector_label": null,
    "business_country": null,
    "business_label": "default",
    "business_sub_label": null,
    "allowed_payment_method_types": null,
    "ephemeral_key": {
        "customer_id": "helcim",
        "created_at": 1740386945,
        "expires": 1740390545,
        "secret": "epk_79d58a8d4ee84ef7bd0e66d4ffa2d471"
    },
    "manual_retry_allowed": false,
    "connector_transaction_id": "32476974",
    "frm_message": null,
    "metadata": {
        "udf1": "value1",
        "login_date": "2019-09-10T10:11:12Z",
        "new_customer": "true"
    },
    "connector_metadata": null,
    "feature_metadata": null,
    "reference_id": "pay_TORNbtguEZUEleC3kYt5_1",
    "payment_link": null,
    "profile_id": "pro_1daddCjtZeUez131YwqB",
    "surcharge_details": null,
    "attempt_count": 1,
    "merchant_decision": null,
    "merchant_connector_id": "mca_b16Kuzg7hY5sPy9NgQUV",
    "incremental_authorization_allowed": null,
    "authorization_count": null,
    "incremental_authorizations": null,
    "external_authentication_details": null,
    "external_3ds_authentication_attempted": false,
    "expires_on": "2025-02-24T09:04:05.759Z",
    "fingerprint": null,
    "browser_info": {
        "os_type": "Windows",
        "language": "en-US",
        "time_zone": 123,
        "ip_address": "192.168.1.1",
        "os_version": "10",
        "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36",
        "color_depth": 24,
        "device_model": "Desktop",
        "java_enabled": true,
        "screen_width": 1920,
        "accept_header": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
        "screen_height": 1080,
        "java_script_enabled": true
    },
    "payment_method_id": null,
    "payment_method_status": null,
    "updated": "2025-02-24T08:49:09.053Z",
    "split_payments": null,
    "frm_metadata": null,
    "extended_authorization_applied": null,
    "capture_before": null,
    "merchant_order_reference_id": null,
    "order_tax_amount": null,
    "connector_mandate_id": null,
    "card_discovery": "manual"
}
```
using curl :
<img width="1168" alt="Screenshot 2025-03-11 at 11 09 50 PM" src="https://github.com/user-attachments/assets/48ee3269-56fe-45ce-85ac-8a57a72b0640" />
<img width="1496" alt="Screenshot 2025-03-11 at 11 10 41 PM" src="https://github.com/user-attachments/assets/860742b5-d26b-4c4d-91dd-325a39ee5082" />


## Checklist
<!-- Put an `x` in the boxes that apply -->

- [x] I formatted the code `cargo +nightly fmt --all`
- [x] I addressed lints thrown by `cargo clippy`
- [ ] I reviewed the submitted code
- [ ] I added unit tests for my changes where possible