Bug: [FIX]: [PAYOUTS] add should_continue flag for propagating error for each call



Paypal requires creation of access token before payment/payouts in its flow.
In Access token flow, we do get error response
```
PaypalAccessTokenErrorResponse { error: \"invalid_client\", error_description: \"Client Authentication failed\" }
```
The error response gets updated on router data but we don’t do a early return based on this condition thus this gets overwritten by payout’s response.
In this case, even if access token is not generated (null), it still goes to payout create flow and fails at connector service with missing value (5xx) (edited) 
diff --git a/crates/router/src/core/payouts.rs b/crates/router/src/core/payouts.rs
index 86d9e2c1e64..437c6c50096 100644
--- a/crates/router/src/core/payouts.rs
+++ b/crates/router/src/core/payouts.rs
@@ -1656,29 +1656,35 @@ pub async fn create_payout(
     )
     .await?;
 
-    // 3. Fetch connector integration details
-    let connector_integration: services::BoxedPayoutConnectorIntegrationInterface<
-        api::PoCreate,
-        types::PayoutsData,
-        types::PayoutsResponseData,
-    > = connector_data.connector.get_connector_integration();
-
-    // 4. Execute pretasks
-    complete_payout_quote_steps_if_required(state, connector_data, &mut router_data).await?;
+    // 3. Execute pretasks
+    if helpers::should_continue_payout(&router_data) {
+        complete_payout_quote_steps_if_required(state, connector_data, &mut router_data).await?;
+    };
 
-    // 5. Call connector service
-    let router_data_resp = services::execute_connector_processing_step(
-        state,
-        connector_integration,
-        &router_data,
-        payments::CallConnectorAction::Trigger,
-        None,
-        None,
-    )
-    .await
-    .to_payout_failed_response()?;
+    // 4. Call connector service
+    let router_data_resp = match helpers::should_continue_payout(&router_data) {
+        true => {
+            let connector_integration: services::BoxedPayoutConnectorIntegrationInterface<
+                api::PoCreate,
+                types::PayoutsData,
+                types::PayoutsResponseData,
+            > = connector_data.connector.get_connector_integration();
+
+            services::execute_connector_processing_step(
+                state,
+                connector_integration,
+                &router_data,
+                payments::CallConnectorAction::Trigger,
+                None,
+                None,
+            )
+            .await
+            .to_payout_failed_response()?
+        }
+        false => router_data,
+    };
 
-    // 6. Process data returned by the connector
+    // 5. Process data returned by the connector
     let db = &*state.store;
     match router_data_resp.response {
         Ok(payout_response_data) => {
@@ -1880,26 +1886,30 @@ pub async fn create_payout_retrieve(
     )
     .await?;
 
-    // 3. Fetch connector integration details
-    let connector_integration: services::BoxedPayoutConnectorIntegrationInterface<
-        api::PoSync,
-        types::PayoutsData,
-        types::PayoutsResponseData,
-    > = connector_data.connector.get_connector_integration();
-
-    // 4. Call connector service
-    let router_data_resp = services::execute_connector_processing_step(
-        state,
-        connector_integration,
-        &router_data,
-        payments::CallConnectorAction::Trigger,
-        None,
-        None,
-    )
-    .await
-    .to_payout_failed_response()?;
+    // 3. Call connector service
+    let router_data_resp = match helpers::should_continue_payout(&router_data) {
+        true => {
+            let connector_integration: services::BoxedPayoutConnectorIntegrationInterface<
+                api::PoSync,
+                types::PayoutsData,
+                types::PayoutsResponseData,
+            > = connector_data.connector.get_connector_integration();
+
+            services::execute_connector_processing_step(
+                state,
+                connector_integration,
+                &router_data,
+                payments::CallConnectorAction::Trigger,
+                None,
+                None,
+            )
+            .await
+            .to_payout_failed_response()?
+        }
+        false => router_data,
+    };
 
-    // 5. Process data returned by the connector
+    // 4. Process data returned by the connector
     update_retrieve_payout_tracker(state, merchant_context, payout_data, &router_data_resp).await?;
 
     Ok(())
@@ -2383,26 +2393,30 @@ pub async fn fulfill_payout(
     )
     .await?;
 
-    // 3. Fetch connector integration details
-    let connector_integration: services::BoxedPayoutConnectorIntegrationInterface<
-        api::PoFulfill,
-        types::PayoutsData,
-        types::PayoutsResponseData,
-    > = connector_data.connector.get_connector_integration();
-
-    // 4. Call connector service
-    let router_data_resp = services::execute_connector_processing_step(
-        state,
-        connector_integration,
-        &router_data,
-        payments::CallConnectorAction::Trigger,
-        None,
-        None,
-    )
-    .await
-    .to_payout_failed_response()?;
+    // 3. Call connector service
+    let router_data_resp = match helpers::should_continue_payout(&router_data) {
+        true => {
+            let connector_integration: services::BoxedPayoutConnectorIntegrationInterface<
+                api::PoFulfill,
+                types::PayoutsData,
+                types::PayoutsResponseData,
+            > = connector_data.connector.get_connector_integration();
+
+            services::execute_connector_processing_step(
+                state,
+                connector_integration,
+                &router_data,
+                payments::CallConnectorAction::Trigger,
+                None,
+                None,
+            )
+            .await
+            .to_payout_failed_response()?
+        }
+        false => router_data,
+    };
 
-    // 5. Process data returned by the connector
+    // 4. Process data returned by the connector
     let db = &*state.store;
     match router_data_resp.response {
         Ok(payout_response_data) => {
diff --git a/crates/router/src/core/payouts/helpers.rs b/crates/router/src/core/payouts/helpers.rs
index 00bcc7a26f6..a1d6b4747d8 100644
--- a/crates/router/src/core/payouts/helpers.rs
+++ b/crates/router/src/core/payouts/helpers.rs
@@ -38,6 +38,7 @@ use crate::{
     routes::{metrics, SessionState},
     services,
     types::{
+        self as router_types,
         api::{self, enums as api_enums},
         domain::{self, types::AsyncLift},
         storage,
@@ -1637,3 +1638,9 @@ pub async fn resolve_billing_address_for_payout(
         (None, None, None) => Ok((None, None)),
     }
 }
+
+pub fn should_continue_payout<F: Clone + 'static>(
+    router_data: &router_types::PayoutsRouterData<F>,
+) -> bool {
+    router_data.response.is_ok()
+}

## 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 -->
Paypal requires creation of access token before payment/payouts in its flow.
In Access token flow, we do get error response
```
PaypalAccessTokenErrorResponse { error: \"invalid_client\", error_description: \"Client Authentication failed\" }
```
The error response gets updated on router data but we don’t do a early return based on this condition thus this gets overwritten by payout’s response.
In this case, even if access token is not generated (null), it still goes to payout create flow and fails at connector service with missing value (5xx) (edited)
### 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).
-->


## 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 an MCA (Paypal payout) with `incorrect credentials`
- Create a Paypal Payout
```
curl --location '{{baseUrl}}/payouts/create' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key:{{api_key}}' \
--data-raw '{
    "amount": 1,
    "currency": "EUR",
    "customer_id": "payout_customer",
    "email": "payout_customer@example.com",
    "name": "John Doe",
    "phone": "999999999",
    "phone_country_code": "+65",
    "description": "Its my first payout request",
    "payout_type": "wallet",
    "payout_method_data": {
        "wallet": {
            "paypal": {
                "email": "sk.sakil@juspay.in"
            }
        }
    },
    "billing": {
        "address": {
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "city": "San Fransico",
            "state": "NY",
            "zip": "94122",
            "country": "US",
            "first_name": "John",
            "last_name": "Doe"
        },
        "phone": {
            "number": "8056594427",
            "country_code": "+91"
        }
    },
    "entity_type": "NaturalPerson",
    "recurring": false,
    "metadata": {
        "ref": "123"
    },
    "confirm": true,
    "auto_fulfill": true
}'
```
It should give out an 2xx with failed response:
```
{
    "payout_id": "payout_OCfkeZ0BRP1TvVBCbqJS",
    "merchant_id": "merchant_1758740236",
    "merchant_order_reference_id": null,
    "amount": 1,
    "currency": "EUR",
    "connector": "paypal",
    "payout_type": "wallet",
    "payout_method_data": {
        "wallet": {
            "email": "sk******@juspay.in",
            "telephone_number": null,
            "paypal_id": null
        }
    },
    "billing": {
        "address": {
            "city": "San Fransico",
            "country": "US",
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "zip": "94122",
            "state": "NY",
            "first_name": "John",
            "last_name": "Doe",
            "origin_zip": null
        },
        "phone": {
            "number": "8056594427",
            "country_code": "+91"
        },
        "email": null
    },
    "auto_fulfill": true,
    "customer_id": "payout_customer",
    "customer": {
        "id": "payout_customer",
        "name": "John Doe",
        "email": "payout_customer@example.com",
        "phone": "999999999",
        "phone_country_code": "+65"
    },
    "client_secret": "payout_payout_OCfkeZ0BRP1TvVBCbqJS_secret_odzX4yMLCWleZmuNb9sh",
    "return_url": null,
    "business_country": null,
    "business_label": null,
    "description": "Its my first payout request",
    "entity_type": "NaturalPerson",
    "recurring": false,
    "metadata": {
        "ref": "123"
    },
    "merchant_connector_id": "mca_jWza4o9JclyqVqh3maid",
    "status": "failed",
    "error_message": "invalid_client",
    "error_code": "invalid_client",
    "profile_id": "pro_yOBs0ZV2FcCS8k3ZEbCM",
    "created": "2025-09-24T18:58:12.868Z",
    "connector_transaction_id": null,
    "priority": null,
    "payout_link": null,
    "email": "payout_customer@example.com",
    "name": "John Doe",
    "phone": "999999999",
    "phone_country_code": "+65",
    "unified_code": "UE_9000",
    "unified_message": "Something went wrong",
    "payout_method_id": null
}
```

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