Bug: [BUG] [BAMBORA] Payments Failing Due to Wrong Card Expiry Year



### Bug Description

Payments are failing for connector Bambora due to wrong format of card expiry year.

### Expected Behavior

Only 2 digit i.e. `25` for `2025` card expiry year should be passed in Bambora Payments Request.

### Actual Behavior

The system is allowing both 2 digit and 4 digit card expiry year in Bambora Payments Request.

### Steps To Reproduce

Provide an unambiguous set of steps to reproduce this bug. Include code or configuration to reproduce, if relevant.
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'


### Context For The Bug


### Environment

Are you using hyperswitch hosted version? Yes/No
If yes, please provide the value of the `x-request-id` response header to help us debug your issue.

If not (or if building/running locally), please provide the following details:
1. Operating System or Linux distribution:
2. Rust version (output of `rustc --version`): ``
3. App version (output of `cargo r --features vergen -- --version`): ``


### Have you spent some time checking if this bug has been raised before?

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

### Have you read the Contributing Guidelines?

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

### Are you willing to submit a PR?

Yes, I am willing to submit a PR!
diff --git a/crates/router/src/connector/bambora.rs b/crates/router/src/connector/bambora.rs
index 0717b997bad..7ff352416cd 100644
--- a/crates/router/src/connector/bambora.rs
+++ b/crates/router/src/connector/bambora.rs
@@ -62,6 +62,10 @@ impl ConnectorCommon for Bambora {
         "bambora"
     }
 
+    fn get_currency_unit(&self) -> api::CurrencyUnit {
+        api::CurrencyUnit::Base
+    }
+
     fn common_get_content_type(&self) -> &'static str {
         "application/json"
     }
@@ -187,7 +191,7 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR
             "{}/v1/payments/{}{}",
             self.base_url(connectors),
             connector_payment_id,
-            "/completions"
+            "/void"
         ))
     }
 
@@ -196,7 +200,22 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR
         req: &types::PaymentsCancelRouterData,
         _connectors: &settings::Connectors,
     ) -> CustomResult<RequestContent, errors::ConnectorError> {
-        let connector_req = bambora::BamboraPaymentsRequest::try_from(req)?;
+        let connector_router_data = bambora::BamboraRouterData::try_from((
+            &self.get_currency_unit(),
+            req.request
+                .currency
+                .ok_or(errors::ConnectorError::MissingRequiredField {
+                    field_name: "Currency",
+                })?,
+            req.request
+                .amount
+                .ok_or(errors::ConnectorError::MissingRequiredField {
+                    field_name: "Amount",
+                })?,
+            req,
+        ))?;
+
+        let connector_req = bambora::BamboraVoidRequest::try_from(connector_router_data)?;
 
         Ok(RequestContent::Json(Box::new(connector_req)))
     }
@@ -376,7 +395,15 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
         req: &types::PaymentsCaptureRouterData,
         _connectors: &settings::Connectors,
     ) -> CustomResult<RequestContent, errors::ConnectorError> {
-        let connector_req = bambora::BamboraPaymentsCaptureRequest::try_from(req)?;
+        let connector_router_data = bambora::BamboraRouterData::try_from((
+            &self.get_currency_unit(),
+            req.request.currency,
+            req.request.amount_to_capture,
+            req,
+        ))?;
+
+        let connector_req =
+            bambora::BamboraPaymentsCaptureRequest::try_from(connector_router_data)?;
         Ok(RequestContent::Json(Box::new(connector_req)))
     }
 
@@ -470,7 +497,14 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
         req: &types::PaymentsAuthorizeRouterData,
         _connectors: &settings::Connectors,
     ) -> CustomResult<RequestContent, errors::ConnectorError> {
-        let connector_req = bambora::BamboraPaymentsRequest::try_from(req)?;
+        let connector_router_data = bambora::BamboraRouterData::try_from((
+            &self.get_currency_unit(),
+            req.request.currency,
+            req.request.amount,
+            req,
+        ))?;
+
+        let connector_req = bambora::BamboraPaymentsRequest::try_from(connector_router_data)?;
 
         Ok(RequestContent::Json(Box::new(connector_req)))
     }
@@ -569,7 +603,13 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
         req: &types::RefundsRouterData<api::Execute>,
         _connectors: &settings::Connectors,
     ) -> CustomResult<RequestContent, errors::ConnectorError> {
-        let connector_req = bambora::BamboraRefundRequest::try_from(req)?;
+        let connector_router_data = bambora::BamboraRouterData::try_from((
+            &self.get_currency_unit(),
+            req.request.currency,
+            req.request.refund_amount,
+            req,
+        ))?;
+        let connector_req = bambora::BamboraRefundRequest::try_from(connector_router_data)?;
         Ok(RequestContent::Json(Box::new(connector_req)))
     }
 
diff --git a/crates/router/src/connector/bambora/transformers.rs b/crates/router/src/connector/bambora/transformers.rs
index 3115f04f483..dbb655c6ca0 100644
--- a/crates/router/src/connector/bambora/transformers.rs
+++ b/crates/router/src/connector/bambora/transformers.rs
@@ -5,13 +5,46 @@ use masking::{ExposeInterface, PeekInterface, Secret};
 use serde::{Deserialize, Deserializer, Serialize};
 
 use crate::{
-    connector::utils::{BrowserInformationData, PaymentsAuthorizeRequestData, RouterData},
+    connector::utils::{
+        AddressDetailsData, BrowserInformationData, CardData as OtherCardData,
+        PaymentsAuthorizeRequestData, RouterData,
+    },
     consts,
     core::errors,
     services,
     types::{self, api, domain, storage::enums},
 };
 
+pub struct BamboraRouterData<T> {
+    pub amount: f64,
+    pub router_data: T,
+}
+
+impl<T>
+    TryFrom<(
+        &types::api::CurrencyUnit,
+        types::storage::enums::Currency,
+        i64,
+        T,
+    )> for BamboraRouterData<T>
+{
+    type Error = error_stack::Report<errors::ConnectorError>;
+    fn try_from(
+        (currency_unit, currency, amount, item): (
+            &types::api::CurrencyUnit,
+            types::storage::enums::Currency,
+            i64,
+            T,
+        ),
+    ) -> Result<Self, Self::Error> {
+        let amount = crate::connector::utils::get_amount_as_f64(currency_unit, amount, currency)?;
+        Ok(Self {
+            amount,
+            router_data: item,
+        })
+    }
+}
+
 #[derive(Default, Debug, Serialize, Eq, PartialEq)]
 pub struct BamboraCard {
     name: Secret<String>,
@@ -46,16 +79,21 @@ pub struct BamboraBrowserInfo {
     javascript_enabled: bool,
 }
 
-#[derive(Default, Debug, Serialize, Eq, PartialEq)]
+#[derive(Default, Debug, Serialize)]
 pub struct BamboraPaymentsRequest {
     order_number: String,
-    amount: i64,
+    amount: f64,
     payment_method: PaymentMethod,
     customer_ip: Option<Secret<String, IpAddress>>,
     term_url: Option<String>,
     card: BamboraCard,
 }
 
+#[derive(Default, Debug, Serialize)]
+pub struct BamboraVoidRequest {
+    amount: f64,
+}
+
 fn get_browser_info(
     item: &types::PaymentsAuthorizeRouterData,
 ) -> Result<Option<BamboraBrowserInfo>, error_stack::Report<errors::ConnectorError>> {
@@ -102,41 +140,41 @@ impl TryFrom<&types::CompleteAuthorizeData> for BamboraThreedsContinueRequest {
     }
 }
 
-impl TryFrom<&types::PaymentsAuthorizeRouterData> for BamboraPaymentsRequest {
+impl TryFrom<BamboraRouterData<&types::PaymentsAuthorizeRouterData>> for BamboraPaymentsRequest {
     type Error = error_stack::Report<errors::ConnectorError>;
-    fn try_from(item: &types::PaymentsAuthorizeRouterData) -> Result<Self, Self::Error> {
-        match item.request.payment_method_data.clone() {
+    fn try_from(
+        item: BamboraRouterData<&types::PaymentsAuthorizeRouterData>,
+    ) -> Result<Self, Self::Error> {
+        match item.router_data.request.payment_method_data.clone() {
             domain::PaymentMethodData::Card(req_card) => {
-                let three_ds = match item.auth_type {
+                let three_ds = match item.router_data.auth_type {
                     enums::AuthenticationType::ThreeDs => Some(ThreeDSecure {
                         enabled: true,
-                        browser: get_browser_info(item)?,
+                        browser: get_browser_info(item.router_data)?,
                         version: Some(2),
                         auth_required: Some(true),
                     }),
                     enums::AuthenticationType::NoThreeDs => None,
                 };
                 let bambora_card = BamboraCard {
-                    name: item
-                        .get_optional_billing_full_name()
-                        .unwrap_or(Secret::new("".to_string())),
+                    name: item.router_data.get_billing_address()?.get_full_name()?,
+                    expiry_year: req_card.get_card_expiry_year_2_digit()?,
                     number: req_card.card_number,
                     expiry_month: req_card.card_exp_month,
-                    expiry_year: req_card.card_exp_year,
                     cvd: req_card.card_cvc,
                     three_d_secure: three_ds,
-                    complete: item.request.is_auto_capture()?,
+                    complete: item.router_data.request.is_auto_capture()?,
                 };
-                let browser_info = item.request.get_browser_info()?;
+                let browser_info = item.router_data.request.get_browser_info()?;
                 Ok(Self {
-                    order_number: item.connector_request_reference_id.clone(),
-                    amount: item.request.amount,
+                    order_number: item.router_data.connector_request_reference_id.clone(),
+                    amount: item.amount,
                     payment_method: PaymentMethod::Card,
                     card: bambora_card,
                     customer_ip: browser_info
                         .ip_address
                         .map(|ip_address| Secret::new(format!("{ip_address}"))),
-                    term_url: item.request.complete_authorize_url.clone(),
+                    term_url: item.router_data.request.complete_authorize_url.clone(),
                 })
             }
             _ => Err(errors::ConnectorError::NotImplemented("Payment methods".to_string()).into()),
@@ -144,12 +182,13 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for BamboraPaymentsRequest {
     }
 }
 
-impl TryFrom<&types::PaymentsCancelRouterData> for BamboraPaymentsRequest {
+impl TryFrom<BamboraRouterData<&types::PaymentsCancelRouterData>> for BamboraVoidRequest {
     type Error = error_stack::Report<errors::ConnectorError>;
-    fn try_from(_item: &types::PaymentsCancelRouterData) -> Result<Self, Self::Error> {
+    fn try_from(
+        item: BamboraRouterData<&types::PaymentsCancelRouterData>,
+    ) -> Result<Self, Self::Error> {
         Ok(Self {
-            amount: 0,
-            ..Default::default()
+            amount: item.amount,
         })
     }
 }
@@ -417,15 +456,19 @@ pub enum PaymentMethod {
 // Capture
 #[derive(Default, Debug, Clone, Serialize, PartialEq)]
 pub struct BamboraPaymentsCaptureRequest {
-    amount: Option<i64>,
+    amount: Option<f64>,
     payment_method: PaymentMethod,
 }
 
-impl TryFrom<&types::PaymentsCaptureRouterData> for BamboraPaymentsCaptureRequest {
+impl TryFrom<BamboraRouterData<&types::PaymentsCaptureRouterData>>
+    for BamboraPaymentsCaptureRequest
+{
     type Error = error_stack::Report<errors::ConnectorError>;
-    fn try_from(item: &types::PaymentsCaptureRouterData) -> Result<Self, Self::Error> {
+    fn try_from(
+        item: BamboraRouterData<&types::PaymentsCaptureRouterData>,
+    ) -> Result<Self, Self::Error> {
         Ok(Self {
-            amount: Some(item.request.amount_to_capture),
+            amount: Some(item.amount),
             payment_method: PaymentMethod::Card,
         })
     }
@@ -433,16 +476,18 @@ impl TryFrom<&types::PaymentsCaptureRouterData> for BamboraPaymentsCaptureReques
 
 // REFUND :
 // Type definition for RefundRequest
-#[derive(Default, Debug, Serialize, Eq, PartialEq)]
+#[derive(Default, Debug, Serialize)]
 pub struct BamboraRefundRequest {
-    amount: i64,
+    amount: f64,
 }
 
-impl<F> TryFrom<&types::RefundsRouterData<F>> for BamboraRefundRequest {
+impl<F> TryFrom<BamboraRouterData<&types::RefundsRouterData<F>>> for BamboraRefundRequest {
     type Error = error_stack::Report<errors::ConnectorError>;
-    fn try_from(item: &types::RefundsRouterData<F>) -> Result<Self, Self::Error> {
+    fn try_from(
+        item: BamboraRouterData<&types::RefundsRouterData<F>>,
+    ) -> Result<Self, Self::Error> {
         Ok(Self {
-            amount: item.request.refund_amount,
+            amount: item.amount,
         })
     }
 }

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

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

## Description
<!-- Describe your changes in detail -->
This PR contains the following changes for connector Bambora:

- Only 2 digit i.e. `25` for `2025` card expiry year will be allowed be pass in Bambora Payments Request.
- Amount will be passed in decimal format for Authorize, Capture and Refund requests.
- Fix Void Flow.

### 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).
-->
https://github.com/juspay/hyperswitch/issues/4534
https://github.com/juspay/hyperswitch/issues/4538

## 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)?
-->

- Payments (Manual):
Request:
```
curl --location 'http://localhost:8080/payments' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: API_KEY_HERE' \
--data '{
  "amount": 2500,
  "currency": "USD",
  "confirm": true,
  "customer_id": "StripeCustomer",
  "capture_method": "manual",
  "authentication_type": "no_three_ds",
  "payment_method": "card",
  "payment_method_type": "credit",
  "payment_method_data": {
    "card": {
      "card_number": "4030000010001234",
      "card_exp_month": "10",
      "card_exp_year": "2024",
      "card_holder_name": "Sundari Doe",
      "card_cvc": "123"
    }
  },
  "billing": {
    "address": {
      "first_name": "joseph",
      "last_name": "Doe"
    }
  },
  "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": "127.0.0.1"
  }
}'
```
Response:
```
{
    "payment_id": "pay_LKthlJrz33C1pr55C7ib",
    "merchant_id": "merchant_1714730521",
    "status": "requires_capture",
    "amount": 2500,
    "net_amount": 2500,
    "amount_capturable": 2500,
    "amount_received": null,
    "connector": "bambora",
    "client_secret": "pay_LKthlJrz33C1pr55C7ib_secret_BaVLQyDPAxLkJFEXfCXD",
    "created": "2024-05-03T11:30:29.586Z",
    "currency": "USD",
    "customer_id": "StripeCustomer",
    "customer": {
        "id": "StripeCustomer",
        "name": "John Doe",
        "email": "guest@example.com",
        "phone": "999999999",
        "phone_country_code": "+1"
    },
    "description": null,
    "refunds": null,
    "disputes": null,
    "mandate_id": null,
    "mandate_data": null,
    "setup_future_usage": null,
    "off_session": null,
    "capture_on": null,
    "capture_method": "manual",
    "payment_method": "card",
    "payment_method_data": {
        "card": {
            "last4": "1234",
            "card_type": null,
            "card_network": null,
            "card_issuer": null,
            "card_issuing_country": null,
            "card_isin": "403000",
            "card_extended_bin": "40300000",
            "card_exp_month": "10",
            "card_exp_year": "2024",
            "card_holder_name": "Sundari Doe",
            "payment_checks": null,
            "authentication_data": null
        },
        "billing": null
    },
    "payment_token": null,
    "shipping": null,
    "billing": {
        "address": {
            "city": null,
            "country": null,
            "line1": null,
            "line2": null,
            "line3": null,
            "zip": null,
            "state": null,
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": null,
        "email": null
    },
    "order_details": null,
    "email": "guest@example.com",
    "name": "John Doe",
    "phone": "999999999",
    "return_url": null,
    "authentication_type": "no_three_ds",
    "statement_descriptor_name": null,
    "statement_descriptor_suffix": null,
    "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": "StripeCustomer",
        "created_at": 1714735829,
        "expires": 1714739429,
        "secret": "epk_74a8cad9f3c64a229b4236f6999b8c67"
    },
    "manual_retry_allowed": false,
    "connector_transaction_id": "10004723",
    "frm_message": null,
    "metadata": null,
    "connector_metadata": null,
    "feature_metadata": null,
    "reference_id": "pay_LKthlJrz33C1pr55C7ib_1",
    "payment_link": null,
    "profile_id": "pro_l8ERwD92l71RbPpGZZz9",
    "surcharge_details": null,
    "attempt_count": 1,
    "merchant_decision": null,
    "merchant_connector_id": "mca_ybl21De1o5q31x82RpEj",
    "incremental_authorization_allowed": null,
    "authorization_count": null,
    "incremental_authorizations": null,
    "external_authentication_details": null,
    "external_3ds_authentication_attempted": false,
    "expires_on": "2024-05-03T11:45:29.586Z",
    "fingerprint": null,
    "browser_info": {
        "language": "nl-NL",
        "time_zone": 0,
        "ip_address": "127.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": "2024-05-03T11:30:31.543Z"
}
```

- Capture:
Request:
```
curl --location 'http://localhost:8080/payments/pay_Bnr8RRNohtyOwlEvTOjg/capture' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: API_KEY_HERE' \
--data '{
  "statement_descriptor_name": "Joseph",
  "statement_descriptor_suffix": "JS"
}'
```

Response:
```
{
    "payment_id": "pay_Bnr8RRNohtyOwlEvTOjg",
    "merchant_id": "merchant_1714730521",
    "status": "succeeded",
    "amount": 2500,
    "net_amount": 2500,
    "amount_capturable": 0,
    "amount_received": 2500,
    "connector": "bambora",
    "client_secret": "pay_Bnr8RRNohtyOwlEvTOjg_secret_F7JoawvBWk3zzTJ9o3a8",
    "created": "2024-05-03T11:27:21.382Z",
    "currency": "USD",
    "customer_id": "StripeCustomer",
    "customer": {
        "id": "StripeCustomer",
        "name": "John Doe",
        "email": "guest@example.com",
        "phone": "999999999",
        "phone_country_code": "+1"
    },
    "description": null,
    "refunds": null,
    "disputes": null,
    "mandate_id": null,
    "mandate_data": null,
    "setup_future_usage": null,
    "off_session": null,
    "capture_on": null,
    "capture_method": "manual",
    "payment_method": "card",
    "payment_method_data": {
        "card": {
            "last4": "1234",
            "card_type": null,
            "card_network": null,
            "card_issuer": null,
            "card_issuing_country": null,
            "card_isin": "403000",
            "card_extended_bin": "40300000",
            "card_exp_month": "10",
            "card_exp_year": "2024",
            "card_holder_name": "Sundari Doe",
            "payment_checks": null,
            "authentication_data": null
        },
        "billing": null
    },
    "payment_token": null,
    "shipping": null,
    "billing": {
        "address": {
            "city": null,
            "country": null,
            "line1": null,
            "line2": null,
            "line3": null,
            "zip": null,
            "state": null,
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": null,
        "email": null
    },
    "order_details": null,
    "email": "guest@example.com",
    "name": "John Doe",
    "phone": "999999999",
    "return_url": null,
    "authentication_type": "no_three_ds",
    "statement_descriptor_name": null,
    "statement_descriptor_suffix": null,
    "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": null,
    "manual_retry_allowed": false,
    "connector_transaction_id": "10004714",
    "frm_message": null,
    "metadata": null,
    "connector_metadata": null,
    "feature_metadata": null,
    "reference_id": "pay_Bnr8RRNohtyOwlEvTOjg_1",
    "payment_link": null,
    "profile_id": "pro_l8ERwD92l71RbPpGZZz9",
    "surcharge_details": null,
    "attempt_count": 1,
    "merchant_decision": null,
    "merchant_connector_id": "mca_ybl21De1o5q31x82RpEj",
    "incremental_authorization_allowed": null,
    "authorization_count": null,
    "incremental_authorizations": null,
    "external_authentication_details": null,
    "external_3ds_authentication_attempted": false,
    "expires_on": "2024-05-03T11:42:21.382Z",
    "fingerprint": null,
    "browser_info": {
        "language": "nl-NL",
        "time_zone": 0,
        "ip_address": "127.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": "2024-05-03T11:27:32.674Z"
}
```

- Payments (Automatic Capture):
Request:
```
curl --location 'http://localhost:8080/payments' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: API_KEY_HERE' \
--data '{
  "amount": 2500,
  "currency": "USD",
  "confirm": true,
  "customer_id": "StripeCustomer",
  "capture_method": "automatic",
  "authentication_type": "no_three_ds",
  "payment_method": "card",
  "payment_method_type": "credit",
  "payment_method_data": {
    "card": {
      "card_number": "4030000010001234",
      "card_exp_month": "10",
      "card_exp_year": "2024",
      "card_holder_name": "Sundari Doe",
      "card_cvc": "123"
    }
  },
  "billing": {
    "address": {
      "first_name": "joseph",
      "last_name": "Doe"
    }
  },
  "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": "127.0.0.1"
  }
}'
```
Response:
```
{
    "payment_id": "pay_7KsO7eanoa25U0NUwGMy",
    "merchant_id": "merchant_1714730521",
    "status": "succeeded",
    "amount": 2500,
    "net_amount": 2500,
    "amount_capturable": 0,
    "amount_received": 2500,
    "connector": "bambora",
    "client_secret": "pay_7KsO7eanoa25U0NUwGMy_secret_MIVHZVOHOByIuQyxzs8H",
    "created": "2024-05-03T11:36:55.259Z",
    "currency": "USD",
    "customer_id": "StripeCustomer",
    "customer": {
        "id": "StripeCustomer",
        "name": "John Doe",
        "email": "guest@example.com",
        "phone": "999999999",
        "phone_country_code": "+1"
    },
    "description": null,
    "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": "1234",
            "card_type": null,
            "card_network": null,
            "card_issuer": null,
            "card_issuing_country": null,
            "card_isin": "403000",
            "card_extended_bin": "40300000",
            "card_exp_month": "10",
            "card_exp_year": "2024",
            "card_holder_name": "Sundari Doe",
            "payment_checks": null,
            "authentication_data": null
        },
        "billing": null
    },
    "payment_token": null,
    "shipping": null,
    "billing": {
        "address": {
            "city": null,
            "country": null,
            "line1": null,
            "line2": null,
            "line3": null,
            "zip": null,
            "state": null,
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": null,
        "email": null
    },
    "order_details": null,
    "email": "guest@example.com",
    "name": "John Doe",
    "phone": "999999999",
    "return_url": null,
    "authentication_type": "no_three_ds",
    "statement_descriptor_name": null,
    "statement_descriptor_suffix": null,
    "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": "StripeCustomer",
        "created_at": 1714736215,
        "expires": 1714739815,
        "secret": "epk_ec99b66693a14bf180eba0f525c07cd0"
    },
    "manual_retry_allowed": false,
    "connector_transaction_id": "10004725",
    "frm_message": null,
    "metadata": null,
    "connector_metadata": null,
    "feature_metadata": null,
    "reference_id": "pay_7KsO7eanoa25U0NUwGMy_1",
    "payment_link": null,
    "profile_id": "pro_l8ERwD92l71RbPpGZZz9",
    "surcharge_details": null,
    "attempt_count": 1,
    "merchant_decision": null,
    "merchant_connector_id": "mca_ybl21De1o5q31x82RpEj",
    "incremental_authorization_allowed": null,
    "authorization_count": null,
    "incremental_authorizations": null,
    "external_authentication_details": null,
    "external_3ds_authentication_attempted": false,
    "expires_on": "2024-05-03T11:51:55.258Z",
    "fingerprint": null,
    "browser_info": {
        "language": "nl-NL",
        "time_zone": 0,
        "ip_address": "127.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": "2024-05-03T11:36:57.592Z"
}
```

- Refunds:
Request:
```
curl --location 'http://localhost:8080/refunds' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: API_KEY_HERE' \
--data '{
  "payment_id": "pay_Bf0CmzVjSJCBVt5e6n3m",
  "reason": "Customer returned product",
  "refund_type": "instant",
  "metadata": {
    "udf1": "value1",
    "new_customer": "true",
    "login_date": "2019-09-10T10:11:12Z"
  }
}'
```

Response:
```
{
    "refund_id": "ref_ksDchUYhgBlvAYz2maZ2",
    "payment_id": "pay_Bf0CmzVjSJCBVt5e6n3m",
    "amount": 2500,
    "currency": "USD",
    "status": "succeeded",
    "reason": "Customer returned product",
    "metadata": {
        "udf1": "value1",
        "new_customer": "true",
        "login_date": "2019-09-10T10:11:12Z"
    },
    "error_message": null,
    "error_code": null,
    "created_at": "2024-05-03T11:38:14.960Z",
    "updated_at": "2024-05-03T11:38:14.960Z",
    "connector": "bambora",
    "profile_id": "pro_l8ERwD92l71RbPpGZZz9",
    "merchant_connector_id": "mca_ybl21De1o5q31x82RpEj"
}
```

## 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`
- [x] I reviewed the submitted code
- [ ] I added unit tests for my changes where possible



- Payments (Manual):
Request:
```
curl --location 'http://localhost:8080/payments' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: API_KEY_HERE' \
--data '{
  "amount": 2500,
  "currency": "USD",
  "confirm": true,
  "customer_id": "StripeCustomer",
  "capture_method": "manual",
  "authentication_type": "no_three_ds",
  "payment_method": "card",
  "payment_method_type": "credit",
  "payment_method_data": {
    "card": {
      "card_number": "4030000010001234",
      "card_exp_month": "10",
      "card_exp_year": "2024",
      "card_holder_name": "Sundari Doe",
      "card_cvc": "123"
    }
  },
  "billing": {
    "address": {
      "first_name": "joseph",
      "last_name": "Doe"
    }
  },
  "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": "127.0.0.1"
  }
}'
```
Response:
```
{
    "payment_id": "pay_LKthlJrz33C1pr55C7ib",
    "merchant_id": "merchant_1714730521",
    "status": "requires_capture",
    "amount": 2500,
    "net_amount": 2500,
    "amount_capturable": 2500,
    "amount_received": null,
    "connector": "bambora",
    "client_secret": "pay_LKthlJrz33C1pr55C7ib_secret_BaVLQyDPAxLkJFEXfCXD",
    "created": "2024-05-03T11:30:29.586Z",
    "currency": "USD",
    "customer_id": "StripeCustomer",
    "customer": {
        "id": "StripeCustomer",
        "name": "John Doe",
        "email": "guest@example.com",
        "phone": "999999999",
        "phone_country_code": "+1"
    },
    "description": null,
    "refunds": null,
    "disputes": null,
    "mandate_id": null,
    "mandate_data": null,
    "setup_future_usage": null,
    "off_session": null,
    "capture_on": null,
    "capture_method": "manual",
    "payment_method": "card",
    "payment_method_data": {
        "card": {
            "last4": "1234",
            "card_type": null,
            "card_network": null,
            "card_issuer": null,
            "card_issuing_country": null,
            "card_isin": "403000",
            "card_extended_bin": "40300000",
            "card_exp_month": "10",
            "card_exp_year": "2024",
            "card_holder_name": "Sundari Doe",
            "payment_checks": null,
            "authentication_data": null
        },
        "billing": null
    },
    "payment_token": null,
    "shipping": null,
    "billing": {
        "address": {
            "city": null,
            "country": null,
            "line1": null,
            "line2": null,
            "line3": null,
            "zip": null,
            "state": null,
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": null,
        "email": null
    },
    "order_details": null,
    "email": "guest@example.com",
    "name": "John Doe",
    "phone": "999999999",
    "return_url": null,
    "authentication_type": "no_three_ds",
    "statement_descriptor_name": null,
    "statement_descriptor_suffix": null,
    "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": "StripeCustomer",
        "created_at": 1714735829,
        "expires": 1714739429,
        "secret": "epk_74a8cad9f3c64a229b4236f6999b8c67"
    },
    "manual_retry_allowed": false,
    "connector_transaction_id": "10004723",
    "frm_message": null,
    "metadata": null,
    "connector_metadata": null,
    "feature_metadata": null,
    "reference_id": "pay_LKthlJrz33C1pr55C7ib_1",
    "payment_link": null,
    "profile_id": "pro_l8ERwD92l71RbPpGZZz9",
    "surcharge_details": null,
    "attempt_count": 1,
    "merchant_decision": null,
    "merchant_connector_id": "mca_ybl21De1o5q31x82RpEj",
    "incremental_authorization_allowed": null,
    "authorization_count": null,
    "incremental_authorizations": null,
    "external_authentication_details": null,
    "external_3ds_authentication_attempted": false,
    "expires_on": "2024-05-03T11:45:29.586Z",
    "fingerprint": null,
    "browser_info": {
        "language": "nl-NL",
        "time_zone": 0,
        "ip_address": "127.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": "2024-05-03T11:30:31.543Z"
}
```

- Capture:
Request:
```
curl --location 'http://localhost:8080/payments/pay_Bnr8RRNohtyOwlEvTOjg/capture' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: API_KEY_HERE' \
--data '{
  "statement_descriptor_name": "Joseph",
  "statement_descriptor_suffix": "JS"
}'
```

Response:
```
{
    "payment_id": "pay_Bnr8RRNohtyOwlEvTOjg",
    "merchant_id": "merchant_1714730521",
    "status": "succeeded",
    "amount": 2500,
    "net_amount": 2500,
    "amount_capturable": 0,
    "amount_received": 2500,
    "connector": "bambora",
    "client_secret": "pay_Bnr8RRNohtyOwlEvTOjg_secret_F7JoawvBWk3zzTJ9o3a8",
    "created": "2024-05-03T11:27:21.382Z",
    "currency": "USD",
    "customer_id": "StripeCustomer",
    "customer": {
        "id": "StripeCustomer",
        "name": "John Doe",
        "email": "guest@example.com",
        "phone": "999999999",
        "phone_country_code": "+1"
    },
    "description": null,
    "refunds": null,
    "disputes": null,
    "mandate_id": null,
    "mandate_data": null,
    "setup_future_usage": null,
    "off_session": null,
    "capture_on": null,
    "capture_method": "manual",
    "payment_method": "card",
    "payment_method_data": {
        "card": {
            "last4": "1234",
            "card_type": null,
            "card_network": null,
            "card_issuer": null,
            "card_issuing_country": null,
            "card_isin": "403000",
            "card_extended_bin": "40300000",
            "card_exp_month": "10",
            "card_exp_year": "2024",
            "card_holder_name": "Sundari Doe",
            "payment_checks": null,
            "authentication_data": null
        },
        "billing": null
    },
    "payment_token": null,
    "shipping": null,
    "billing": {
        "address": {
            "city": null,
            "country": null,
            "line1": null,
            "line2": null,
            "line3": null,
            "zip": null,
            "state": null,
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": null,
        "email": null
    },
    "order_details": null,
    "email": "guest@example.com",
    "name": "John Doe",
    "phone": "999999999",
    "return_url": null,
    "authentication_type": "no_three_ds",
    "statement_descriptor_name": null,
    "statement_descriptor_suffix": null,
    "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": null,
    "manual_retry_allowed": false,
    "connector_transaction_id": "10004714",
    "frm_message": null,
    "metadata": null,
    "connector_metadata": null,
    "feature_metadata": null,
    "reference_id": "pay_Bnr8RRNohtyOwlEvTOjg_1",
    "payment_link": null,
    "profile_id": "pro_l8ERwD92l71RbPpGZZz9",
    "surcharge_details": null,
    "attempt_count": 1,
    "merchant_decision": null,
    "merchant_connector_id": "mca_ybl21De1o5q31x82RpEj",
    "incremental_authorization_allowed": null,
    "authorization_count": null,
    "incremental_authorizations": null,
    "external_authentication_details": null,
    "external_3ds_authentication_attempted": false,
    "expires_on": "2024-05-03T11:42:21.382Z",
    "fingerprint": null,
    "browser_info": {
        "language": "nl-NL",
        "time_zone": 0,
        "ip_address": "127.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": "2024-05-03T11:27:32.674Z"
}
```

- Payments (Automatic Capture):
Request:
```
curl --location 'http://localhost:8080/payments' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: API_KEY_HERE' \
--data '{
  "amount": 2500,
  "currency": "USD",
  "confirm": true,
  "customer_id": "StripeCustomer",
  "capture_method": "automatic",
  "authentication_type": "no_three_ds",
  "payment_method": "card",
  "payment_method_type": "credit",
  "payment_method_data": {
    "card": {
      "card_number": "4030000010001234",
      "card_exp_month": "10",
      "card_exp_year": "2024",
      "card_holder_name": "Sundari Doe",
      "card_cvc": "123"
    }
  },
  "billing": {
    "address": {
      "first_name": "joseph",
      "last_name": "Doe"
    }
  },
  "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": "127.0.0.1"
  }
}'
```
Response:
```
{
    "payment_id": "pay_7KsO7eanoa25U0NUwGMy",
    "merchant_id": "merchant_1714730521",
    "status": "succeeded",
    "amount": 2500,
    "net_amount": 2500,
    "amount_capturable": 0,
    "amount_received": 2500,
    "connector": "bambora",
    "client_secret": "pay_7KsO7eanoa25U0NUwGMy_secret_MIVHZVOHOByIuQyxzs8H",
    "created": "2024-05-03T11:36:55.259Z",
    "currency": "USD",
    "customer_id": "StripeCustomer",
    "customer": {
        "id": "StripeCustomer",
        "name": "John Doe",
        "email": "guest@example.com",
        "phone": "999999999",
        "phone_country_code": "+1"
    },
    "description": null,
    "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": "1234",
            "card_type": null,
            "card_network": null,
            "card_issuer": null,
            "card_issuing_country": null,
            "card_isin": "403000",
            "card_extended_bin": "40300000",
            "card_exp_month": "10",
            "card_exp_year": "2024",
            "card_holder_name": "Sundari Doe",
            "payment_checks": null,
            "authentication_data": null
        },
        "billing": null
    },
    "payment_token": null,
    "shipping": null,
    "billing": {
        "address": {
            "city": null,
            "country": null,
            "line1": null,
            "line2": null,
            "line3": null,
            "zip": null,
            "state": null,
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": null,
        "email": null
    },
    "order_details": null,
    "email": "guest@example.com",
    "name": "John Doe",
    "phone": "999999999",
    "return_url": null,
    "authentication_type": "no_three_ds",
    "statement_descriptor_name": null,
    "statement_descriptor_suffix": null,
    "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": "StripeCustomer",
        "created_at": 1714736215,
        "expires": 1714739815,
        "secret": "epk_ec99b66693a14bf180eba0f525c07cd0"
    },
    "manual_retry_allowed": false,
    "connector_transaction_id": "10004725",
    "frm_message": null,
    "metadata": null,
    "connector_metadata": null,
    "feature_metadata": null,
    "reference_id": "pay_7KsO7eanoa25U0NUwGMy_1",
    "payment_link": null,
    "profile_id": "pro_l8ERwD92l71RbPpGZZz9",
    "surcharge_details": null,
    "attempt_count": 1,
    "merchant_decision": null,
    "merchant_connector_id": "mca_ybl21De1o5q31x82RpEj",
    "incremental_authorization_allowed": null,
    "authorization_count": null,
    "incremental_authorizations": null,
    "external_authentication_details": null,
    "external_3ds_authentication_attempted": false,
    "expires_on": "2024-05-03T11:51:55.258Z",
    "fingerprint": null,
    "browser_info": {
        "language": "nl-NL",
        "time_zone": 0,
        "ip_address": "127.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": "2024-05-03T11:36:57.592Z"
}
```

- Refunds:
Request:
```
curl --location 'http://localhost:8080/refunds' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: API_KEY_HERE' \
--data '{
  "payment_id": "pay_Bf0CmzVjSJCBVt5e6n3m",
  "reason": "Customer returned product",
  "refund_type": "instant",
  "metadata": {
    "udf1": "value1",
    "new_customer": "true",
    "login_date": "2019-09-10T10:11:12Z"
  }
}'
```

Response:
```
{
    "refund_id": "ref_ksDchUYhgBlvAYz2maZ2",
    "payment_id": "pay_Bf0CmzVjSJCBVt5e6n3m",
    "amount": 2500,
    "currency": "USD",
    "status": "succeeded",
    "reason": "Customer returned product",
    "metadata": {
        "udf1": "value1",
        "new_customer": "true",
        "login_date": "2019-09-10T10:11:12Z"
    },
    "error_message": null,
    "error_code": null,
    "created_at": "2024-05-03T11:38:14.960Z",
    "updated_at": "2024-05-03T11:38:14.960Z",
    "connector": "bambora",
    "profile_id": "pro_l8ERwD92l71RbPpGZZz9",
    "merchant_connector_id": "mca_ybl21De1o5q31x82RpEj"
}
```
