Bug: Refactor: make the mca_id optional for PPT mandate flow



## Description
<!-- Describe your changes in detail -->
This refactor will make `mca_id` as optional in request and will completely remove the connector_name field, So the updation will make this request :
```
"recurring_details": {
        "type": "processor_payment_token",
        "data": {
            "processor_payment_token": "pm_1Psh0bD5R7gDAGffspOhjKxn",
            "connector": "adyen",
            "merchant_connector_id": "mca_KcjKmhxEzSacoksdT5rN"
        }
    },
```

into:
```
"recurring_details": {
        "type": "processor_payment_token",
        "data": {
            "processor_payment_token": "pm_1Psh0bD5R7gDAGffspOhjKxn"
        }
    },
```
Now listing the flows on how it will work:
First of all it is to be worked out after a routing rule is configured regarding ppt payments,
> So if proxy is to be used (considering maximum simultaneous connector as 1) then a specific routing rule needs to be created.
> Which will be something like 
```
If `payment_type `---->  `ppt_mandate` 
then 
`Connnector` ----> `Bambora`
```
> This will insure ppt payments will be routed through Bambora connector.
> Once all payments of Bambora is transactioned. The rule can be modified for another connector use-case.

> Now for the cases where simultaneously more than one connector is needed to make payment, the optional `mca_id` can be used. Which will automatically fetch the connector details and route the payment.

How the flow works:
1. First it will check for the mca_id
> If there it will go through the mca_id's connector
2. If not it will go accordingly to the routing configured:
> if ppt_routing is configured then the payment will go with the appropriate connector and succeed.
> else the payment will go to the default fallback connector and fail.

## Test
1. create a merchant account.
2. create api_key.
3. create mca (stripe).
4. create a routing rule:
```
curl --location 'http://127.0.0.1:8080/routing' \
--header 'Content-Type: application/json' \
--header 'api-key: xxxxxxxxx' \
--data '{
    "name": "advanced config",
    "description": "It is my ADVANCED config",
    "profile_id": "pro_6WR6UUG3NEdZ19EHCOU7",
    "algorithm": {
        "type": "advanced",
        "data": {
            "defaultSelection": {
                "type": "priority",
                "data": [
                ]
            },
            "rules": [
                {
                    "name": "stripe first",
                    "connectorSelection": {
                        "type": "priority",
                        "data": [
                            {
                                "connector": "stripe",
                                "merchant_connector_id": "mca_KcjKmhxEzSacoksdT5rN"
                            }
                        ]
                    },
                    "statements": [
                        {
                            "condition": [
                                {
                                    "lhs": "payment_type",
                                    "comparison": "equal",
                                    "value": {
                                        "type": "enum_variant",
                                        "value": "ppt_mandate"
                                    },
                                    "metadata": {}
                                }
                            ],
                            "nested": null
                        }
                    ]
                }
            ],
            "metadata": {}
        }
    }
}'
```
5.(optional only for testing / only for generating the ppt token): Create a setup mandate payment
```
curl --location 'http://localhost:8080/payments' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: xxxxxx' \
--data-raw '{
    "amount": 0,
    "currency": "USD",
    "confirm": true,
    "capture_method": "automatic",
    "capture_on": "2022-09-10T10:11:12Z",
    "customer_id": "cus_fvkFoCfd9bgmvFhGVoyz",
    "description": "Its my first payment request",
    "authentication_type": "no_three_ds",
    "return_url": "https://google.com",
    "setup_future_usage": "off_session",
    "off_session": true,
    "shipping": {
        "address": {
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "city": "San Fransico",
            "state": "California",
            "zip": "94122",
            "country": "US",
            "first_name": "John",
            "last_name": "Doe"
        }
    },
    "statement_descriptor_name": "joseph",
    "statement_descriptor_suffix": "JS",
    "metadata": {
        "udf1": "value1",
        "new_customer": "true",
        "login_date": "2019-09-10T10:11:12Z"
    },
    "payment_type": "setup_mandate",
    "payment_method": "card",
    "payment_method_type": "credit",
    "payment_method_data": {
        "card": {
            "card_number": "4242424242424242",
            "card_exp_month": "02",
            "card_exp_year": "26",
            "card_holder_name": "Joseph Doe",
            "card_cvc": "999"
        }
    },
    "billing": {
        "address": {
            "line1": "8th block",
            "line2": "8th block",
            "line3": "8th block",
            "city": "Bengaluru",
            "state": "Karnataka",
            "zip": "560095",
            "country": "IN",
            "first_name": "Sakil",
            "last_name": "Mostak"
        }
    },
    "customer_acceptance": {
        "acceptance_type": "online"
    }
}'
```
6.(optional only for testing / only for generating the ppt token): query the `payment_method's` table with the `pm_id` and not the `connector_mandate_id`, as this is our ppt token.

7. Create a ppt payment :
```
curl --location 'http://localhost:8080/payments' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: xxxxx' \
--data '{
    "amount": 499,
    "currency": "USD",
    "capture_method": "automatic",
    "profile_id": "pro_6WR6UUG3NEdZ19EHCOU7",
    "customer_id": "cus_fvkFoCfd9bgmvFhGVoyz",
    "off_session": true,
    "confirm": true,
    "recurring_details": {
        "type": "processor_payment_token",
        "data": {
            "processor_payment_token": "pm_1Psh0bD5R7gDAGffspOhjKxn"
        }
    },
    "payment_method": "card",
    "authentication_type": "no_three_ds"
}'
```

8.(optional flow) Create a ppt payment with mca_id:
```
curl --location 'http://localhost:8080/payments' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: xxxxx' \
--data '{
    "amount": 499,
    "currency": "USD",
    "capture_method": "automatic",
    "profile_id": "pro_6WR6UUG3NEdZ19EHCOU7",
    "customer_id": "cus_fvkFoCfd9bgmvFhGVoyz",
    "off_session": true,
    "confirm": true,
    "recurring_details": {
        "type": "processor_payment_token",
        "data": {
            "processor_payment_token": "pm_1Psh0bD5R7gDAGffspOhjKxn",
            "merchant_connector_id": "mca_KcjKmhxEzSacoksdT5rN"
        }
    },
    "payment_method": "card",
    "authentication_type": "no_three_ds"
}'
```

Things to note:
1. The payment should go throught the connector configured in the rule based routing.
2. The payment should succeed.



diff --git a/api-reference-v2/openapi_spec.json b/api-reference-v2/openapi_spec.json
index 6882e823905..ed591af7a6c 100644
--- a/api-reference-v2/openapi_spec.json
+++ b/api-reference-v2/openapi_spec.json
@@ -16052,19 +16052,15 @@
         "type": "object",
         "description": "Processor payment token for MIT payments where payment_method_data is not available",
         "required": [
-          "processor_payment_token",
-          "connector",
-          "merchant_connector_id"
+          "processor_payment_token"
         ],
         "properties": {
           "processor_payment_token": {
             "type": "string"
           },
-          "connector": {
-            "$ref": "#/components/schemas/Connector"
-          },
           "merchant_connector_id": {
-            "type": "string"
+            "type": "string",
+            "nullable": true
           }
         }
       },
diff --git a/crates/api_models/src/mandates.rs b/crates/api_models/src/mandates.rs
index 44a83319424..fe5b053b180 100644
--- a/crates/api_models/src/mandates.rs
+++ b/crates/api_models/src/mandates.rs
@@ -127,8 +127,6 @@ pub enum RecurringDetails {
 #[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema, PartialEq, Eq)]
 pub struct ProcessorPaymentToken {
     pub processor_payment_token: String,
-    #[schema(value_type = Connector, example = "stripe")]
-    pub connector: api_enums::Connector,
-    #[schema(value_type = String)]
-    pub merchant_connector_id: common_utils::id_type::MerchantConnectorAccountId,
+    #[schema(value_type = Option<String>)]
+    pub merchant_connector_id: Option<common_utils::id_type::MerchantConnectorAccountId>,
 }
diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs
index 1af097114fb..75fe544ae5e 100644
--- a/crates/router/src/core/payments.rs
+++ b/crates/router/src/core/payments.rs
@@ -3809,6 +3809,30 @@ pub async fn decide_multiplex_connector_for_normal_or_recurring_payment<F: Clone
 
             Ok(ConnectorCallType::PreDetermined(chosen_connector_data))
         }
+        (
+            None,
+            None,
+            Some(RecurringDetails::ProcessorPaymentToken(_token)),
+            Some(true),
+            Some(api::MandateTransactionType::RecurringMandateTransaction),
+        ) => {
+            if let Some(connector) = connectors.first() {
+                routing_data.routed_through = Some(connector.connector_name.clone().to_string());
+                routing_data
+                    .merchant_connector_id
+                    .clone_from(&connector.merchant_connector_id);
+                Ok(ConnectorCallType::PreDetermined(api::ConnectorData {
+                    connector: connector.connector.clone(),
+                    connector_name: connector.connector_name,
+                    get_token: connector.get_token.clone(),
+                    merchant_connector_id: connector.merchant_connector_id.clone(),
+                }))
+            } else {
+                logger::error!("no eligible connector found for the ppt_mandate payment");
+                Err(errors::ApiErrorResponse::IncorrectPaymentMethodConfiguration.into())
+            }
+        }
+
         _ => {
             helpers::override_setup_future_usage_to_on_session(&*state.store, payment_data).await?;
 
diff --git a/crates/router/src/core/payments/helpers.rs b/crates/router/src/core/payments/helpers.rs
index 52e439a2e47..34fb2e954ba 100644
--- a/crates/router/src/core/payments/helpers.rs
+++ b/crates/router/src/core/payments/helpers.rs
@@ -420,73 +420,108 @@ pub async fn get_token_pm_type_mandate_details(
         ),
         Some(api::MandateTransactionType::RecurringMandateTransaction) => {
             match &request.recurring_details {
-                Some(recurring_details) => match recurring_details {
-                    RecurringDetails::ProcessorPaymentToken(processor_payment_token) => (
-                        None,
-                        request.payment_method,
-                        None,
-                        None,
-                        None,
-                        Some(payments::MandateConnectorDetails {
-                            connector: processor_payment_token.connector.to_string(),
-                            merchant_connector_id: Some(
-                                processor_payment_token.merchant_connector_id.clone(),
-                            ),
-                        }),
-                        None,
-                    ),
-                    RecurringDetails::MandateId(mandate_id) => {
-                        let mandate_generic_data = get_token_for_recurring_mandate(
-                            state,
-                            request,
-                            merchant_account,
-                            merchant_key_store,
-                            mandate_id.to_owned(),
-                        )
-                        .await?;
+                Some(recurring_details) => {
+                    match recurring_details {
+                        RecurringDetails::ProcessorPaymentToken(processor_payment_token) => {
+                            if let Some(mca_id) = &processor_payment_token.merchant_connector_id {
+                                let db = &*state.store;
+                                let key_manager_state = &state.into();
+
+                                #[cfg(all(
+                                any(feature = "v1", feature = "v2"),
+                                not(feature = "merchant_connector_account_v2")
+                            ))]
+                            let connector_name = db
+                                .find_by_merchant_connector_account_merchant_id_merchant_connector_id(
+                                    key_manager_state,
+                                    merchant_account.get_id(),
+                                    mca_id,
+                                    merchant_key_store,
+                                )
+                                .await
+                                .to_not_found_response(errors::ApiErrorResponse::MerchantConnectorAccountNotFound {
+                                    id: mca_id.clone().get_string_repr().to_string(),
+                                })?.connector_name;
 
-                        (
-                            mandate_generic_data.token,
-                            mandate_generic_data.payment_method,
-                            mandate_generic_data
-                                .payment_method_type
-                                .or(request.payment_method_type),
-                            None,
-                            mandate_generic_data.recurring_mandate_payment_data,
-                            mandate_generic_data.mandate_connector,
-                            mandate_generic_data.payment_method_info,
-                        )
-                    }
-                    RecurringDetails::PaymentMethodId(payment_method_id) => {
-                        let payment_method_info = state
-                            .store
-                            .find_payment_method(payment_method_id, merchant_account.storage_scheme)
-                            .await
-                            .to_not_found_response(
-                                errors::ApiErrorResponse::PaymentMethodNotFound,
+                                #[cfg(all(feature = "v2", feature = "merchant_connector_account_v2"))]
+                            let connector_name = db
+                                .find_merchant_connector_account_by_id(key_manager_state, &mca_id, &merchant_key_store)
+                                .await
+                                .to_not_found_response(errors::ApiErrorResponse::MerchantConnectorAccountNotFound {
+                                    id: mca_id.clone().get_string_repr().to_string(),
+                                })?.connector_name;
+                                (
+                                    None,
+                                    request.payment_method,
+                                    None,
+                                    None,
+                                    None,
+                                    Some(payments::MandateConnectorDetails {
+                                        connector: connector_name,
+                                        merchant_connector_id: Some(mca_id.clone()),
+                                    }),
+                                    None,
+                                )
+                            } else {
+                                (None, request.payment_method, None, None, None, None, None)
+                            }
+                        }
+                        RecurringDetails::MandateId(mandate_id) => {
+                            let mandate_generic_data = get_token_for_recurring_mandate(
+                                state,
+                                request,
+                                merchant_account,
+                                merchant_key_store,
+                                mandate_id.to_owned(),
+                            )
+                            .await?;
+
+                            (
+                                mandate_generic_data.token,
+                                mandate_generic_data.payment_method,
+                                mandate_generic_data
+                                    .payment_method_type
+                                    .or(request.payment_method_type),
+                                None,
+                                mandate_generic_data.recurring_mandate_payment_data,
+                                mandate_generic_data.mandate_connector,
+                                mandate_generic_data.payment_method_info,
+                            )
+                        }
+                        RecurringDetails::PaymentMethodId(payment_method_id) => {
+                            let payment_method_info = state
+                                .store
+                                .find_payment_method(
+                                    payment_method_id,
+                                    merchant_account.storage_scheme,
+                                )
+                                .await
+                                .to_not_found_response(
+                                    errors::ApiErrorResponse::PaymentMethodNotFound,
+                                )?;
+                            let customer_id = request
+                                .get_customer_id()
+                                .get_required_value("customer_id")?;
+
+                            verify_mandate_details_for_recurring_payments(
+                                &payment_method_info.merchant_id,
+                                merchant_account.get_id(),
+                                &payment_method_info.customer_id,
+                                customer_id,
                             )?;
-                        let customer_id = request
-                            .get_customer_id()
-                            .get_required_value("customer_id")?;
-
-                        verify_mandate_details_for_recurring_payments(
-                            &payment_method_info.merchant_id,
-                            merchant_account.get_id(),
-                            &payment_method_info.customer_id,
-                            customer_id,
-                        )?;
 
-                        (
-                            None,
-                            payment_method_info.payment_method,
-                            payment_method_info.payment_method_type,
-                            None,
-                            None,
-                            None,
-                            Some(payment_method_info),
-                        )
+                            (
+                                None,
+                                payment_method_info.payment_method,
+                                payment_method_info.payment_method_type,
+                                None,
+                                None,
+                                None,
+                                Some(payment_method_info),
+                            )
+                        }
                     }
-                },
+                }
                 None => {
                     if let Some(mandate_id) = request.mandate_id.clone() {
                         let mandate_generic_data = get_token_for_recurring_mandate(

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

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

## Description
<!-- Describe your changes in detail -->
This refactor will make `mca_id` as optional in request and will completely remove the connector_name field, So the updation will make this request :
```
"recurring_details": {
        "type": "processor_payment_token",
        "data": {
            "processor_payment_token": "pm_1Psh0bD5R7gDAGffspOhjKxn",
            "connector": "adyen",
            "merchant_connector_id": "mca_KcjKmhxEzSacoksdT5rN"
        }
    },
```

into:
```
"recurring_details": {
        "type": "processor_payment_token",
        "data": {
            "processor_payment_token": "pm_1Psh0bD5R7gDAGffspOhjKxn"
        }
    },
```
Now listing the flows on how it will work:
First of all it is to be worked out after a routing rule is configured regarding ppt payments,
> So if proxy is to be used (considering maximum simultaneous connector as 1) then a specific routing rule needs to be created.
> Which will be something like 
```
If `payment_type `---->  `ppt_mandate` 
then 
`Connnector` ----> `Bambora`
```
> This will insure ppt payments will be routed through Bambora connector.
> Once all payments of Bambora is transactioned. The rule can be modified for another connector use-case.

> Now for the cases where simultaneously more than one connector is needed to make payment, the optional `mca_id` can be used. Which will automatically fetch the connector details and route the payment.

How the flow works:
1. First it will check for the mca_id
> If there it will go through the mca_id's connector
2. If not it will go accordingly to the routing configured:
> if ppt_routing is configured then the payment will go with the appropriate connector and succeed.
> else the payment will go to the default fallback connector and fail.

### Additional Changes

- [x] 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`
4. `crates/router/src/configs`
5. `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).
-->
For better user experience.

## 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)?
-->
1. create a merchant account.
2. create api_key.
3. create mca (stripe).
4. create a routing rule:
```
curl --location 'http://127.0.0.1:8080/routing' \
--header 'Content-Type: application/json' \
--header 'api-key: xxxxxxxxx' \
--data '{
    "name": "advanced config",
    "description": "It is my ADVANCED config",
    "profile_id": "pro_6WR6UUG3NEdZ19EHCOU7",
    "algorithm": {
        "type": "advanced",
        "data": {
            "defaultSelection": {
                "type": "priority",
                "data": [
                ]
            },
            "rules": [
                {
                    "name": "stripe first",
                    "connectorSelection": {
                        "type": "priority",
                        "data": [
                            {
                                "connector": "stripe",
                                "merchant_connector_id": "mca_KcjKmhxEzSacoksdT5rN"
                            }
                        ]
                    },
                    "statements": [
                        {
                            "condition": [
                                {
                                    "lhs": "payment_type",
                                    "comparison": "equal",
                                    "value": {
                                        "type": "enum_variant",
                                        "value": "ppt_mandate"
                                    },
                                    "metadata": {}
                                }
                            ],
                            "nested": null
                        }
                    ]
                }
            ],
            "metadata": {}
        }
    }
}'
```
5.(optional only for testing / only for generating the ppt token): Create a setup mandate payment
```
curl --location 'http://localhost:8080/payments' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: xxxxxx' \
--data-raw '{
    "amount": 0,
    "currency": "USD",
    "confirm": true,
    "capture_method": "automatic",
    "capture_on": "2022-09-10T10:11:12Z",
    "customer_id": "cus_fvkFoCfd9bgmvFhGVoyz",
    "description": "Its my first payment request",
    "authentication_type": "no_three_ds",
    "return_url": "https://google.com",
    "setup_future_usage": "off_session",
    "off_session": true,
    "shipping": {
        "address": {
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "city": "San Fransico",
            "state": "California",
            "zip": "94122",
            "country": "US",
            "first_name": "John",
            "last_name": "Doe"
        }
    },
    "statement_descriptor_name": "joseph",
    "statement_descriptor_suffix": "JS",
    "metadata": {
        "udf1": "value1",
        "new_customer": "true",
        "login_date": "2019-09-10T10:11:12Z"
    },
    "payment_type": "setup_mandate",
    "payment_method": "card",
    "payment_method_type": "credit",
    "payment_method_data": {
        "card": {
            "card_number": "4242424242424242",
            "card_exp_month": "02",
            "card_exp_year": "26",
            "card_holder_name": "Joseph Doe",
            "card_cvc": "999"
        }
    },
    "billing": {
        "address": {
            "line1": "8th block",
            "line2": "8th block",
            "line3": "8th block",
            "city": "Bengaluru",
            "state": "Karnataka",
            "zip": "560095",
            "country": "IN",
            "first_name": "Sakil",
            "last_name": "Mostak"
        }
    },
    "customer_acceptance": {
        "acceptance_type": "online"
    }
}'
```
6.(optional only for testing / only for generating the ppt token): query the `payment_method's` table with the `pm_id` and get the `connector_mandate_id`, as this is our ppt token.

7. Create a ppt payment :
```
curl --location 'http://localhost:8080/payments' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: xxxxx' \
--data '{
    "amount": 499,
    "currency": "USD",
    "capture_method": "automatic",
    "profile_id": "pro_6WR6UUG3NEdZ19EHCOU7",
    "customer_id": "cus_fvkFoCfd9bgmvFhGVoyz",
    "off_session": true,
    "confirm": true,
    "recurring_details": {
        "type": "processor_payment_token",
        "data": {
            "processor_payment_token": "pm_1Psh0bD5R7gDAGffspOhjKxn"
        }
    },
    "payment_method": "card",
    "authentication_type": "no_three_ds"
}'
```

8.(optional flow) Create a ppt payment with mca_id:
```
curl --location 'http://localhost:8080/payments' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: xxxxx' \
--data '{
    "amount": 499,
    "currency": "USD",
    "capture_method": "automatic",
    "profile_id": "pro_6WR6UUG3NEdZ19EHCOU7",
    "customer_id": "cus_fvkFoCfd9bgmvFhGVoyz",
    "off_session": true,
    "confirm": true,
    "recurring_details": {
        "type": "processor_payment_token",
        "data": {
            "processor_payment_token": "pm_1Psh0bD5R7gDAGffspOhjKxn",
            "merchant_connector_id": "mca_KcjKmhxEzSacoksdT5rN"
        }
    },
    "payment_method": "card",
    "authentication_type": "no_three_ds"
}'
```

Things to note:
1. The payment should go throught the connector configured in the rule based routing.
2. The payment should succeed.




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