Bug: [ENHANCEMENT] add validation for return_url for Payment Links



HyperSwitch should always validate the presence of return_url during payment link creation as it is a required field in payment link flows.
diff --git a/crates/router/src/core/payments/helpers.rs b/crates/router/src/core/payments/helpers.rs
index bdf7e9ec83f..e606291b8db 100644
--- a/crates/router/src/core/payments/helpers.rs
+++ b/crates/router/src/core/payments/helpers.rs
@@ -6338,16 +6338,19 @@ pub fn get_key_params_for_surcharge_details(
 }
 
 pub fn validate_payment_link_request(
-    confirm: Option<bool>,
+    request: &api::PaymentsRequest,
 ) -> Result<(), errors::ApiErrorResponse> {
-    if let Some(cnf) = confirm {
-        if !cnf {
-            return Ok(());
-        } else {
-            return Err(errors::ApiErrorResponse::InvalidRequestData {
-                message: "cannot confirm a payment while creating a payment link".to_string(),
-            });
-        }
+    #[cfg(feature = "v1")]
+    if request.confirm == Some(true) {
+        return Err(errors::ApiErrorResponse::InvalidRequestData {
+            message: "cannot confirm a payment while creating a payment link".to_string(),
+        });
+    }
+
+    if request.return_url.is_none() {
+        return Err(errors::ApiErrorResponse::InvalidRequestData {
+            message: "return_url must be sent while creating a payment link".to_string(),
+        });
     }
     Ok(())
 }
diff --git a/crates/router/src/core/payments/operations/payment_create.rs b/crates/router/src/core/payments/operations/payment_create.rs
index 801c6844f9b..f1b15be199e 100644
--- a/crates/router/src/core/payments/operations/payment_create.rs
+++ b/crates/router/src/core/payments/operations/payment_create.rs
@@ -979,7 +979,7 @@ impl<F: Send + Clone + Sync> ValidateRequest<F, api::PaymentsRequest, PaymentDat
 
         if let Some(payment_link) = &request.payment_link {
             if *payment_link {
-                helpers::validate_payment_link_request(request.confirm)?;
+                helpers::validate_payment_link_request(request)?;
             }
         };
 

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

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

## Description
This PR adds a validation for `return_url` when creating payment links. Return URL must be a required parameter as payment links is client side facing and needs to be redirected to an end URL post payment completion.


### 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
This PR fixes a bug in the payment links flow which allowed creating payment links without validating presence of `return_url`. This allows merchants to be careful of payment link integration.

## How did you test it?
<details>
    <summary>1. Create a payment link without return_url in the payments create request</summary>

cURL

    curl --location --request POST 'http://localhost:8080/payments' \
        --header 'Content-Type: application/json' \
        --header 'Accept: application/json' \
        --header 'api-key: dev_ddmeaxUlgRPHkcqtmZZm5nGMRhejMxXijYCnsp070Oqn2y4lrfUNBCb9UmedwgMt' \
        --data-raw '{"customer_id":"cus_ttQVCva9zDC2q8jfJaiy","profile_id":"pro_510ieWUUX4pc0bUWmBW3","customer_acceptance":{"acceptance_type":"online","accepted_at":"1963-05-03T04:07:52.723Z","online":{"ip_address":"127.0.0.1","user_agent":"amet irure esse"}},"amount":10,"currency":"EUR","payment_link":true,"capture_method":"automatic","billing":{"address":{"line1":"1467","line2":"Harrison Street","line3":"Harrison Street","city":"San Fransico","state":"CA","zip":"94122","country":"HK","first_name":"John","last_name":"Doe"},"phone":{"number":"8056594427","country_code":"+91"},"email":"random@juspay.in"}}'

Response

    {
        "error": {
            "type": "invalid_request",
            "message": "return_url must be sent while creating a payment link",
            "code": "IR_06"
        }
    }

</details>

<details>
    <summary>2. Create a payment link with return_url in the payments create request</summary>

cURL

    curl --location --request POST 'http://localhost:8080/payments' \
        --header 'Content-Type: application/json' \
        --header 'Accept: application/json' \
        --header 'api-key: dev_ddmeaxUlgRPHkcqtmZZm5nGMRhejMxXijYCnsp070Oqn2y4lrfUNBCb9UmedwgMt' \
        --data-raw '{"customer_id":"cus_ttQVCva9zDC2q8jfJaiy","profile_id":"pro_510ieWUUX4pc0bUWmBW3","customer_acceptance":{"acceptance_type":"online","accepted_at":"1963-05-03T04:07:52.723Z","online":{"ip_address":"127.0.0.1","user_agent":"amet irure esse"}},"amount":10,"currency":"EUR","payment_link":true,"capture_method":"automatic","billing":{"address":{"line1":"1467","line2":"Harrison Street","line3":"Harrison Street","city":"San Fransico","state":"CA","zip":"94122","country":"HK","first_name":"John","last_name":"Doe"},"phone":{"number":"8056594427","country_code":"+91"},"email":"random@juspay.in"},"return_url":"https://example.com"}'

Response

   {"payment_id":"pay_jqWIxxAzZ55ObDFPUi3u","merchant_id":"merchant_1744368926","status":"requires_payment_method","amount":10,"net_amount":10,"shipping_cost":null,"amount_capturable":10,"amount_received":null,"connector":null,"client_secret":"pay_jqWIxxAzZ55ObDFPUi3u_secret_R696m3FdANBfOlBHs7e3","created":"2025-04-11T15:32:20.593Z","currency":"EUR","customer_id":"cus_ttQVCva9zDC2q8jfJaiy","customer":{"id":"cus_ttQVCva9zDC2q8jfJaiy","name":null,"email":null,"phone":null,"phone_country_code":null},"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":null,"payment_method_data":null,"payment_token":null,"shipping":null,"billing":{"address":{"city":"San Fransico","country":"HK","line1":"1467","line2":"Harrison Street","line3":"Harrison Street","zip":"94122","state":"CA","first_name":"John","last_name":"Doe"},"phone":{"number":"8056594427","country_code":"+91"},"email":"random@juspay.in"},"order_details":null,"email":null,"name":null,"phone":null,"return_url":"https://example.com/","authentication_type":null,"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":null,"connector_label":null,"business_country":null,"business_label":"default","business_sub_label":null,"allowed_payment_method_types":null,"ephemeral_key":{"customer_id":"cus_ttQVCva9zDC2q8jfJaiy","created_at":1744385540,"expires":1744389140,"secret":"epk_4687716462814249b8cad4ebb30c18a3"},"manual_retry_allowed":null,"connector_transaction_id":null,"frm_message":null,"metadata":null,"connector_metadata":null,"feature_metadata":null,"reference_id":null,"payment_link":{"link":"http://localhost:8080/payment_link/merchant_1744368926/pay_jqWIxxAzZ55ObDFPUi3u?locale=en","secure_link":null,"payment_link_id":"plink_2tsEloeZ8SeUXyOQfRsu"},"profile_id":"pro_510ieWUUX4pc0bUWmBW3","surcharge_details":null,"attempt_count":1,"merchant_decision":null,"merchant_connector_id":null,"incremental_authorization_allowed":null,"authorization_count":null,"incremental_authorizations":null,"external_authentication_details":null,"external_3ds_authentication_attempted":false,"expires_on":"2025-04-11T15:47:20.588Z","fingerprint":null,"browser_info":null,"payment_method_id":null,"payment_method_status":null,"updated":"2025-04-11T15:32:20.612Z","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":null,"force_3ds_challenge":false,"force_3ds_challenge_trigger":false,"issuer_error_code":null,"issuer_error_message":null}

</details>



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