Skip to content

Conversation

swangi-kumari
Copy link
Contributor

@swangi-kumari swangi-kumari commented Jun 2, 2025

Type of Change

  • Bugfix
  • New feature
  • Enhancement
  • Refactoring
  • Dependency updates
  • Documentation
  • CI/CD

Description

  • Accept merchant_connector_credentials in the Request Body of payments and psync
  • Add a new POST endpoint payments_status_with_gateway_creds
  • Add merchant_reference_id in payments response

Additional Changes

  • This PR modifies the API contract
  • This PR modifies the database schema
  • This PR modifies application configuration/environment variables

Motivation and Context

How did you test it?

  1. Create a Iatapay UPI Collect Payment using merchant_connector_details in request
curl --location 'http://localhost:8080/v2/payments' \
--header 'x-profile-id: pro_0kVhEGeBzYWrYTKjPNsu' \
--header 'Content-Type: application/json' \
--header 'Authorization: api-key=_' \
--data-raw '{
    "amount_details": {
        "currency": "INR",
        "order_amount": 5000
    },
    "merchant_connector_details": {
        "connector_name": "iatapay",
        "merchant_connector_creds": {
            "auth_type": "SignatureKey",
            "api_secret": "_",
            "api_key": "_",
            "key1": "_"
        }
    },
    "merchant_reference_id": "12345_pay_01970c787911748861401",
    "payment_method_data": {
        "upi": {
            "upi_collect": {
                "vpa_id": "successtest@iata"
            }
        },
        "billing": {
            "phone": {
                "number": "8056594427",
                "country_code": "+91"
            },
            "email": "[email protected]"
        }
    },
    "payment_method_subtype": "upi_collect",
    "payment_method_type": "upi"
}'

Response


    "id": "12345_pay_01973043e4f07320a2fb3fa247d53663",
    "status": "requires_customer_action",
    "amount": {
        "order_amount": 5000,
        "currency": "INR",
        "shipping_cost": null,
        "order_tax_amount": null,
        "external_tax_calculation": "skip",
        "surcharge_calculation": "skip",
        "surcharge_amount": null,
        "tax_on_surcharge": null,
        "net_amount": 5000,
        "amount_to_capture": null,
        "amount_capturable": 0,
        "amount_captured": null
    },
    "customer_id": null,
    "connector": "iatapay",
    "created": "2025-06-02T10:50:45.360Z",
    "payment_method_data": {
        "billing": {
            "address": null,
            "phone": {
                "number": "8056594427",
                "country_code": "+91"
            },
            "email": "[email protected]"
        }
    },
    "payment_method_type": "upi",
    "payment_method_subtype": "upi_collect",
    "connector_transaction_id": "PXABN7QEGDQE6",
    "connector_reference_id": null,
    "merchant_connector_id": null,
    "browser_info": null,
    "error": null,
    "shipping": null,
    "billing": null,
    "attempts": null,
    "connector_token_details": null,
    "payment_method_id": null,
    "next_action": {
        "type": "redirect_to_url",
        "redirect_to_url": "http://localhost:8080/v2/payments/12345_pay_01973043e4f07320a2fb3fa247d53663/start-redirection?publishable_key=pk_dev_5dd7e3043d9a4d88a2c8d2939b3f9f25&profile_id=pro_0kVhEGeBzYWrYTKjPNsu"
    },
    "return_url": "https://google.com/success",
    "authentication_type": null,
    "authentication_type_applied": "no_three_ds",
    "is_iframe_redirection_enabled": null,
    "merchant_reference_id": "12345_pay_01970c787911748934115"
}

Complete the payment using redirection url. use successtest@iata upi for testing

  1. Do a post Psync call with merchant_connector_details in request
curl --location 'http://localhost:8080/v2/payments/12345_pay_01973047de457891be56cf7b828a964e' \
--header 'x-profile-id: pro_0kVhEGeBzYWrYTKjPNsu' \
--header 'Content-Type: application/json' \
--header 'Authorization: api-key=_' \
--data '{
    "merchant_connector_details": {
        "connector_name": "iatapay",
        "merchant_connector_creds": {
            "auth_type": "SignatureKey",
            "api_secret": "_",
            "api_key": "_",
            "key1": "_"
        }
    },
    "force_sync" : true
}'

Response

{
    "id": "12345_pay_01973047de457891be56cf7b828a964e",
    "status": "succeeded",
    "amount": {
        "order_amount": 5000,
        "currency": "INR",
        "shipping_cost": null,
        "order_tax_amount": null,
        "external_tax_calculation": "skip",
        "surcharge_calculation": "skip",
        "surcharge_amount": null,
        "tax_on_surcharge": null,
        "net_amount": 5000,
        "amount_to_capture": null,
        "amount_capturable": 0,
        "amount_captured": 5000
    },
    "customer_id": null,
    "connector": "iatapay",
    "created": "2025-06-02T10:55:05.797Z",
    "payment_method_data": {
        "billing": {
            "address": null,
            "phone": {
                "number": "8056594427",
                "country_code": "+91"
            },
            "email": "[email protected]"
        }
    },
    "payment_method_type": "upi",
    "payment_method_subtype": "upi_collect",
    "connector_transaction_id": "P18ISDL9I3LI3",
    "connector_reference_id": null,
    "merchant_connector_id": null,
    "browser_info": null,
    "error": null,
    "shipping": null,
    "billing": null,
    "attempts": null,
    "connector_token_details": null,
    "payment_method_id": null,
    "next_action": null,
    "return_url": "https://google.com/success",
    "authentication_type": null,
    "authentication_type_applied": null,
    "is_iframe_redirection_enabled": null,
    "merchant_reference_id": "12345_pay_01970c787911748934115"
    
}

Checklist

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

Summary by CodeRabbit

  • New Features

    • Added support for providing merchant connector details directly in payment requests and responses, enabling enhanced gateway credential handling.
    • Introduced new request and response fields for merchant connector details and merchant reference IDs to improve idempotency and tracking.
    • Added new endpoints and request types for retrieving payment status with gateway credentials.
  • Improvements

    • Updated multiple APIs and flows to support both merchant connector account and direct connector details, increasing flexibility in integration scenarios.
    • Enhanced OpenAPI documentation to include new payment request types and connector detail structures.
  • Bug Fixes

    • Improved handling of optional merchant connector IDs in payment flows to prevent errors when details are provided directly.
  • Refactor

    • Unified and streamlined how merchant connector account information is passed and processed across payment, vault, and payout flows.
    • Updated function signatures and internal logic to consistently support the new merchant connector details abstraction.

@swangi-kumari swangi-kumari self-assigned this Jun 2, 2025
@swangi-kumari swangi-kumari requested review from a team as code owners June 2, 2025 05:41
Copy link

semanticdiff-com bot commented Jun 2, 2025

Review changes with  SemanticDiff

Changed Files
File Status
  crates/router/src/core/payments/operations/proxy_payments_intent.rs  93% smaller
  crates/router/src/routes/app.rs  84% smaller
  crates/router/src/core/payment_methods.rs  75% smaller
  crates/router/src/core/payment_methods/vault.rs  71% smaller
  crates/router/src/core/payments/customers.rs  62% smaller
  crates/router/src/core/payments/transformers.rs  52% smaller
  crates/hyperswitch_domain_models/src/payments.rs  45% smaller
  crates/hyperswitch_domain_models/src/customer.rs  42% smaller
  crates/router/src/core/payments/operations/payment_confirm_intent.rs  40% smaller
  crates/router/src/core/payments/helpers.rs  18% smaller
  crates/router/src/core/payments.rs  17% smaller
  crates/openapi/src/openapi_v2.rs  7% smaller
  api-reference/v2/openapi_spec_v2.json  2% smaller
  crates/router/src/routes/payments.rs  1% smaller
  crates/api_models/src/payments.rs  0% smaller
  crates/hyperswitch_domain_models/src/merchant_connector_account.rs  0% smaller
  crates/hyperswitch_domain_models/src/payments/payment_attempt.rs  0% smaller
  crates/hyperswitch_domain_models/src/revenue_recovery.rs  0% smaller
  crates/router/src/core/fraud_check/flows/checkout_flow.rs  0% smaller
  crates/router/src/core/fraud_check/flows/record_return.rs  0% smaller
  crates/router/src/core/fraud_check/flows/sale_flow.rs  0% smaller
  crates/router/src/core/fraud_check/flows/transaction_flow.rs  0% smaller
  crates/router/src/core/payments/flows.rs  0% smaller
  crates/router/src/core/payments/flows/approve_flow.rs  0% smaller
  crates/router/src/core/payments/flows/authorize_flow.rs  0% smaller
  crates/router/src/core/payments/flows/cancel_flow.rs  0% smaller
  crates/router/src/core/payments/flows/capture_flow.rs  0% smaller
  crates/router/src/core/payments/flows/complete_authorize_flow.rs  0% smaller
  crates/router/src/core/payments/flows/incremental_authorization_flow.rs  0% smaller
  crates/router/src/core/payments/flows/post_session_tokens_flow.rs  0% smaller
  crates/router/src/core/payments/flows/psync_flow.rs  0% smaller
  crates/router/src/core/payments/flows/reject_flow.rs  0% smaller
  crates/router/src/core/payments/flows/session_flow.rs  0% smaller
  crates/router/src/core/payments/flows/session_update_flow.rs  0% smaller
  crates/router/src/core/payments/flows/setup_mandate_flow.rs  0% smaller
  crates/router/src/core/payments/flows/update_metadata_flow.rs  0% smaller
  crates/router/src/core/payments/operations.rs  0% smaller
  crates/router/src/core/payments/operations/payment_get.rs  0% smaller
  crates/router/src/core/payments/vault_session.rs Unsupported file format
  crates/router/src/core/payouts/helpers.rs  0% smaller
  crates/router/src/core/revenue_recovery.rs  0% smaller
  crates/router/src/core/revenue_recovery/api.rs  0% smaller
  crates/router/src/core/utils.rs  0% smaller
  crates/router/src/core/webhooks/incoming_v2.rs  0% smaller
  crates/router/src/core/webhooks/recovery_incoming.rs  0% smaller

@swangi-kumari swangi-kumari requested a review from a team as a code owner June 2, 2025 10:47
@swangi-kumari swangi-kumari added the A-core Area: Core flows label Jun 2, 2025
@swangi-kumari swangi-kumari changed the title feat(core): add merchant_connector_details in payments flow feat(core): accept merchant_connector_details in Payments and Psync flow Jun 3, 2025
@swangi-kumari swangi-kumari requested a review from a team as a code owner June 5, 2025 12:06
Copy link

coderabbitai bot commented Jun 10, 2025

Walkthrough

This update introduces a new abstraction, MerchantConnectorAccountTypeDetails, to unify handling of merchant connector account information, supporting both database and direct credential flows. Multiple payment and status request/response models are extended to optionally carry merchant_connector_details. Numerous APIs, flows, and helper functions are refactored to use the new enum, and new endpoints and OpenAPI schema entries are added to support payment status retrieval with gateway credentials.

Changes

Files/Areas Change Summary
api_models::payments.rs Added merchant_connector_details and merchant_reference_id fields to payment structs; introduced MerchantConnectorDetails, PaymentsRetrieveRequestWithMerchantConnectorDetails, and PaymentsStatusRequest; updated conversions and trait impls.
hyperswitch_domain_models::merchant_connector_account.rs Introduced MerchantConnectorAccountTypeDetails enum with methods to abstract over connector account sources.
hyperswitch_domain_models::customer.rs, payments.rs, payouts/helpers.rs Updated methods to accept MerchantConnectorAccountTypeDetails instead of just account ID; adjusted logic accordingly.
hyperswitch_domain_models::payments/payment_attempt.rs Made merchant_connector_id optional in PaymentAttemptUpdate::ConfirmIntent.
hyperswitch_domain_models::revenue_recovery.rs Set merchant_connector_details to None in payment intent request conversion.
common_utils::id_type/merchant.rs Added FromStr implementation for MerchantId.
openapi/src/openapi_v2.rs Added new payment-related types to OpenAPI schema components.
router/src/core/payments/helpers.rs Added get_connector_data_from_request; simplified get_merchant_connector_account_v2 to only DB fetch; removed Redis logic.
router/src/core/payments/operations.rs, operations/payment_confirm_intent.rs, operations/payment_get.rs Added/implemented get_connector_from_request to fetch connector data from request for v2 flows.
router/src/core/payments.rs Added internal_payments_operation_core and internal_call_connector_service for v2; refactored flows to use new enum and helpers; extended session getters.
router/src/core/payments/transformers.rs Refactored payment router data construction functions to accept/use MerchantConnectorAccountTypeDetails; updated webhook URL and customer ID logic.
router/src/core/payments/flows/*.rs, core/fraud_check/flows/*.rs Changed construct_router_data and related signatures to use MerchantConnectorAccountTypeDetails.
router/src/core/payment_methods.rs, core/payment_methods/vault.rs, core/payments/vault_session.rs, core/utils.rs Updated vaulting and session-related flows to use MerchantConnectorAccountTypeDetails; adjusted helper usage and signatures.
router/src/core/revenue_recovery/api.rs, core/webhooks/incoming_v2.rs, core/webhooks/recovery_incoming.rs Added/propagated merchant_connector_details: None in relevant requests and tracking data.
router/src/routes/payments.rs, routes/app.rs Changed status handler to use new request types; added POST endpoint for payment status with gateway credentials.

Sequence Diagram(s)

Payment Status Retrieval with Gateway Credentials (New POST Flow)

sequenceDiagram
    participant Client
    participant Router (payments_status_with_gateway_creds)
    participant Core (payments_core)
    participant Domain Logic
    participant Store/DB

    Client->>Router: POST /v2/payments/{id} with PaymentsRetrieveRequestWithMerchantConnectorDetails
    Router->>Core: Call payments_core with request (includes merchant_connector_details)
    Core->>Domain Logic: get_connector_from_request (extract connector from merchant_connector_details)
    Domain Logic->>Core: Return ConnectorData
    Core->>Store/DB: Fetch payment data as needed
    Core->>Router: Return payment status response
    Router->>Client: Respond with payment status
Loading

Unified Handling of Merchant Connector Account Details

sequenceDiagram
    participant PaymentFlow
    participant AccountTypeDetails (enum)
    participant DB
    participant DirectCreds

    PaymentFlow->>AccountTypeDetails: Needs connector details
    alt Variant: MerchantConnectorAccount
        AccountTypeDetails->>DB: Fetch details by account ID
        DB-->>AccountTypeDetails: Return account details
    else Variant: MerchantConnectorDetails
        AccountTypeDetails->>DirectCreds: Use provided credentials
    end
    AccountTypeDetails-->>PaymentFlow: Return connector details
Loading

Poem

Oh, what a hop, what a leap, what a bound!
New connectors and flows in the payment playground.
With details in hand, and credentials in tow,
The rabbit ensures every payment will flow.
Gateway or DB, the enum decides—
In the lush fields of code, where abstraction abides!
🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 12

🔭 Outside diff range comments (3)
crates/router/src/core/payments/flows/psync_flow.rs (1)

91-99: ⚠️ Potential issue

Parameter type mismatch will fail to compile

get_merchant_recipient_data still takes
&_helpers::MerchantConnectorAccountType, while the preceding construct_router_data
method (and the global type migration) now use
&domain::MerchantConnectorAccountTypeDetails.

These two method signatures must be consistent with the trait definition;
otherwise the impl will not compile under --all-features.

-        _merchant_connector_account: &helpers::MerchantConnectorAccountType,
+        _merchant_connector_account: &domain::MerchantConnectorAccountTypeDetails,
crates/router/src/routes/payments.rs (1)

955-3055: 🛠️ Refactor suggestion

Significant code duplication and complex authentication logic detected.

This new handler duplicates substantial logic from the existing payment_status handler. The core payment processing logic (lines 3021-3048) is nearly identical, and the authentication selection logic is complex and inconsistent with patterns used elsewhere in the file.

Refactor to reduce duplication:

Extract the common payment status logic into a shared helper function:

+async fn handle_payment_status_core<T>(
+    state: app::SessionState,
+    req_state: ReqState,
+    auth: auth::AuthenticationData,
+    global_payment_id: common_utils::id_type::GlobalPaymentId,
+    request: payment_types::PaymentsRetrieveRequest,
+    header_payload: HeaderPayload,
+) -> errors::RouterResponse<api_models::payments::PaymentsResponse> {
+    let operation = payments::operations::PaymentGet;
+    let merchant_context = domain::MerchantContext::NormalMerchant(Box::new(
+        domain::Context(auth.merchant_account, auth.key_store),
+    ));
+    Box::pin(payments::payments_core::<
+        api_types::PSync,
+        api_models::payments::PaymentsResponse,
+        _,
+        _,
+        _,
+        PaymentStatusData<api_types::PSync>,
+    >(
+        state,
+        req_state,
+        merchant_context,
+        auth.profile,
+        operation,
+        request,
+        global_payment_id,
+        payments::CallConnectorAction::Trigger,
+        header_payload,
+    ))
+    .await
+}

Simplify authentication logic:

Consider extracting the authentication selection logic into a helper function to ensure consistency across handlers and reduce complexity.

crates/router/src/core/payments/operations/payment_confirm_intent.rs (1)

262-273: 🛠️ Refactor suggestion

merchant_connector_details cloned but never validated

merchant_connector_details is copied into PaymentConfirmData, yet no validation (connector name present, credential formats, mutually-exclusive fields) happens here. Invalid JSON will propagate until hitting deeper layers with less helpful error messages.

Consider validating the struct right after extraction to surface deterministic, user-friendly errors.

♻️ Duplicate comments (1)
crates/router/src/core/payment_methods/vault.rs (1)

1737-1747: Duplicate boxed-account allocation

The deletion path repeats the boxing pattern discussed above; refactor alongside retrieval to keep memory profile lean.

🧹 Nitpick comments (21)
crates/router/src/core/payments/flows/session_update_flow.rs (1)

60-60: Implement the v2 construct_router_data function.

The todo!() placeholder indicates that the v2 implementation for session update flow is incomplete. This needs to be implemented before the v2 feature can be used in production.

Do you want me to help implement this function or create an issue to track this work?

crates/router/src/core/payments/flows/complete_authorize_flow.rs (1)

73-73: Complete the v2 implementation for complete authorize flow.

The function remains unimplemented with a todo!() placeholder. This needs to be completed to enable v2 complete authorize functionality.

Would you like me to help implement this function based on the v1 implementation pattern?

crates/router/src/core/payments/flows/cancel_flow.rs (1)

29-29: Implement the cancel flow v2 functionality.

The todo!() placeholder indicates incomplete implementation. The cancel flow needs to be implemented for v2 to support merchant connector details.

Do you need assistance implementing the v2 cancel flow logic?

crates/router/src/core/payments/flows/approve_flow.rs (1)

30-30: Complete the approve flow v2 implementation.

The function body contains only a todo!() placeholder. This needs to be implemented to enable v2 approve flow functionality with merchant connector details.

Would you like me to help create a tracking issue for implementing this function?

crates/router/src/core/fraud_check/flows/record_return.rs (1)

41-41: Implement fraud check record return v2 functionality.

The todo!() placeholder indicates that the v2 implementation for fraud check record return is incomplete. Note that this function requires both v2 and customer_v2 feature flags.

Do you want me to help implement this function or track it as technical debt?

crates/router/src/core/payments/operations/payment_get.rs (1)

5-6: Unused import payme

The new use hyperswitch_connectors::connectors::payme; line is not referenced anywhere
in this module, which will trigger unused_imports warnings (and possibly a build
failure if #![deny(warnings)] is enabled).

-#[cfg(feature = "v2")]
-use hyperswitch_connectors::connectors::payme;
+// remove – not used
crates/router/src/routes/payments.rs (1)

2995-3014: Authentication logic is overly complex and inconsistent with other handlers.

The conditional authentication selection logic here is more complex than similar handlers in this file. Most other handlers use simpler patterns like direct auth::auth_type() calls or straightforward conditional logic.

Consider simplifying to match the pattern used in other handlers:

-    let auth_type = if state.conf.merchant_id_auth.merchant_id_auth_enabled {
-        &auth::MerchantIdAuth
-    } else {
-        match env::which() {
-            env::Env::Production => &auth::V2ApiKeyAuth {
-                is_connected_allowed: false,
-                is_platform_allowed: false,
-            },
-            _ => auth::auth_type(
-                &auth::V2ApiKeyAuth {
-                    is_connected_allowed: false,
-                    is_platform_allowed: false,
-                },
-                &auth::JWTAuth {
-                    permission: Permission::ProfilePaymentWrite,
-                },
-                req.headers(),
-            ),
-        }
-    };
+    let auth_type = if state.conf.merchant_id_auth.merchant_id_auth_enabled {
+        &auth::MerchantIdAuth
+    } else {
+        auth::auth_type(
+            &auth::V2ApiKeyAuth {
+                is_connected_allowed: false,
+                is_platform_allowed: false,
+            },
+            &auth::JWTAuth {
+                permission: Permission::ProfilePaymentWrite,
+            },
+            req.headers(),
+        )
+    };

This removes the environment-specific logic and makes the authentication selection more predictable.

crates/router/src/core/payments/customers.rs (1)

163-182: Unnecessary async marker inflates call-stack

update_connector_customer_in_customers is declared async but performs no .await inside either match arm; the whole body is fully synchronous. Compiling this as async causes an extra state-machine to be generated for every call and forces callers to .await needlessly.

-#[instrument]
-pub async fn update_connector_customer_in_customers(
+#\[instrument]
+pub fn update_connector_customer_in_customers(

Switching to a plain function will reduce allocations and simplify the call-graph.

crates/router/src/core/payments/operations/payment_confirm_intent.rs (1)

492-506: Duplicate “get_connector_from_request” implementation – factor into shared helper

This block is identical to the implementation in payment_get.rs. To avoid future drift, pull it into a small helper (e.g. helpers::set_connector_from_request) and call it from both places.

crates/router/src/core/payment_methods/vault.rs (3)

1390-1391: Pass MerchantConnectorAccountTypeDetails by reference to avoid moves

The function now takes merchant_connector_account by value but subsequently borrows it multiple times; this forces an unnecessary move (and Box allocation upstream). Accepting &MerchantConnectorAccountTypeDetails keeps the call-site simpler and zero-copy:

-    merchant_connector_account: domain::MerchantConnectorAccountTypeDetails,
+    merchant_connector_account: &domain::MerchantConnectorAccountTypeDetails,

You’ll then drop the leading & when passing it further down.


1566-1576: Redundant Box allocation

Wrapping the fetched MCA in Box::new(...) just to fit the enum variant inflates the heap and complicates ownership:

domain::MerchantConnectorAccountTypeDetails::MerchantConnectorAccount(
    Box::new(account),
)

If the enum does not strictly need a boxed value, make the variant hold the struct directly; otherwise obtain a boxed account once at the helper and reuse it.


1634-1635: Same by-value issue as retrieve – please switch to reference

delete_payment_method_data_from_vault_external moved to by-value as well; same reasoning as earlier applies here.

crates/router/src/core/payments/helpers.rs (1)

1605-1626: Consider taking a non-optional parameter if always required

The function takes Option<api_models::payments::MerchantConnectorDetails> but immediately returns an error if it's None. If this parameter is always required, consider changing the signature to take a non-optional parameter to make the API clearer.

 #[cfg(feature = "v2")]
 pub async fn get_connector_data_from_request(
     state: &SessionState,
-    req: Option<api_models::payments::MerchantConnectorDetails>,
+    req: api_models::payments::MerchantConnectorDetails,
 ) -> CustomResult<api::ConnectorData, errors::ApiErrorResponse> {
-    let connector = req
-        .as_ref()
-        .map(|connector_details| connector_details.connector_name.to_string())
-        .ok_or(errors::ApiErrorResponse::MissingRequiredField {
-            field_name: "merchant_connector_details",
-        })?;
+    let connector = req.connector_name.to_string();
     let connector_data: api::ConnectorData = api::ConnectorData::get_connector_by_name(
         &state.conf.connectors,
         &connector,
         api::GetToken::Connector,
         None,
     )
     .change_context(errors::ApiErrorResponse::InternalServerError)
     .attach_printable("Invalid connector name received")?;
     Ok(connector_data)
 }
crates/hyperswitch_domain_models/src/merchant_connector_account.rs (1)

145-161: Consider consolidating duplicate ID retrieval logic.

Both get_id and get_mca_id methods implement similar logic for the MerchantConnectorAccount variant. The get_id method directly accesses the id field while get_mca_id calls the get_id() method.

Consider having get_id delegate to get_mca_id for consistency:

 pub fn get_id(&self) -> Option<id_type::MerchantConnectorAccountId> {
-    match self {
-        Self::MerchantConnectorAccount(merchant_connector_account) => {
-            Some(merchant_connector_account.id.clone())
-        }
-        Self::MerchantConnectorDetails(_) => None,
-    }
+    self.get_mca_id()
 }
crates/api_models/src/payments.rs (1)

279-287:

❓ Verification inconclusive

Consider security implications of accepting connector credentials in API requests

The MerchantConnectorDetails struct accepts connector credentials directly in API requests. While the credentials are wrapped in pii::SecretSerdeValue, ensure that:

  1. These credentials are properly validated and authenticated
  2. Audit logs appropriately handle these sensitive fields
  3. The credentials are not persisted in request logs

Run the following script to check how these credentials are handled in the codebase:


🏁 Script executed:

#!/bin/bash
# Description: Verify security handling of merchant_connector_creds

# Check validation of merchant_connector_details
echo "=== Checking validation of merchant_connector_details ==="
rg -A 10 "merchant_connector_details" --type rust | grep -E "(validate|verify|check|auth)"

# Check if credentials are logged
echo -e "\n=== Checking if credentials might be logged ==="
rg -A 5 "(log|trace|debug|info|warn|error).*merchant_connector" --type rust

# Check how pii::SecretSerdeValue is handled
echo -e "\n=== Checking SecretSerdeValue handling ==="
rg -A 5 "SecretSerdeValue" --type rust | head -50

Length of output: 13696


Double-check security handling of MerchantConnectorDetails

Our search didn’t reveal any explicit validation or logging redaction for the merchant_connector_creds field wrapped in pii::SecretSerdeValue. Please verify that:

  • Credentials are validated/authenticated against the connector before use (e.g. in payment_complete_authorize in crates/router/src/core/payments/operations/payment_complete_authorize.rs).
  • All logs (error, warn, info, debug, trace) redact or omit the raw SecretSerdeValue—no credentials should end up in request logs.
  • Audit trails record when credentials are used without ever persisting or exposing the secret.
  • The mapping from merchant_connector_creds to creds_identifier correctly handles and discards the raw secret after validation.
crates/router/src/core/payments/vault_session.rs (3)

79-87: Unnecessary DB round-trip when external_vault_source is None

helpers::get_merchant_connector_account_v2 is invoked even when external_vault_source is None.
If the vault profile doesn’t configure a dedicated connector, the extra query returns the default MCA anyway – costing an extra DB hit on every request.

if is_external_vault_sdk_enabled {
-    let external_vault_source = profile
-        .external_vault_connector_details
-        .as_ref()
-        .map(|details| &details.vault_connector_id);
-
-    let merchant_connector_account =
-        domain::MerchantConnectorAccountTypeDetails::MerchantConnectorAccount(Box::new(
-            helpers::get_merchant_connector_account_v2(
-                state,
-                merchant_context.get_merchant_key_store(),
-                external_vault_source,
-            )
-            .await?,
-        ));
+    let Some(vault_connector_id) = profile
+        .external_vault_connector_details
+        .as_ref()
+        .map(|d| &d.vault_connector_id)
+    else {
+        // No dedicated vault connector configured – nothing to populate.
+        return Ok(());
+    };
+
+    let merchant_connector_account = domain::MerchantConnectorAccountTypeDetails::MerchantConnectorAccount(
+        Box::new(
+            helpers::get_merchant_connector_account_v2(
+                state,
+                merchant_context.get_merchant_key_store(),
+                Some(vault_connector_id),
+            )
+            .await?,
+        ),
+    );

This short-circuit avoids an extra query when a vault connector isn’t explicitly configured.


223-237: More explicit error response would aid client debugging

All parsing failures of connector auth collapse into InternalServerError.
Consider distinguishing between “invalid credentials” (4xx) and “unexpected parsing failure” (5xx) to help API consumers act on configuration errors quicker.

Example:

-.map_err(|err| {
-    err.change_context(errors::ApiErrorResponse::InternalServerError)
+.map_err(|err| {
+    err.change_context(errors::ApiErrorResponse::InvalidDataFormat) // 422

288-299: Minor: avoid cloning large enum instances

merchant_connector_account_type is passed as &… throughout, but converted into owned values in deep calls (e.g., get_mca_id, construct_vault_router_data).
Implementing Copy/Clone-free helpers that return borrowed data (Option<&str>) would save heap allocations for every vault call.

crates/router/src/core/payments.rs (3)

325-399: Struct-destructuring is brittle – add .. to future-proof the pattern

operations::GetTrackerResponse is destructured without ...
The moment a new field is appended to the struct, this line will break compilation.

-let operations::GetTrackerResponse { mut payment_data } = get_tracker_response;
+let operations::GetTrackerResponse { mut payment_data, .. } = get_tracker_response;

While you’re here, consider renaming the boxed variable (operation) to avoid shadowing the parameter — that would improve readability.


3586-3595: Repeated MCA retrieval – extract into a helper

The block that wraps the MCA in MerchantConnectorAccountTypeDetails::MerchantConnectorAccount appears verbatim in several places. Extracting it into a small helper (e.g. build_mca_details(state, merchant_context, id).await?) would reduce duplication and potential drift.


4358-4373: Duplicate MCA retrieval – candidate for DRYing up

Same retrieval logic as in the single-connector path. Centralising this into a helper would keep the multiconnector and single-connector flows in sync automatically.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a88eebd and e0b9b9c.

📒 Files selected for processing (44)
  • crates/api_models/src/payments.rs (8 hunks)
  • crates/common_utils/src/id_type/merchant.rs (2 hunks)
  • crates/hyperswitch_domain_models/src/customer.rs (2 hunks)
  • crates/hyperswitch_domain_models/src/merchant_connector_account.rs (1 hunks)
  • crates/hyperswitch_domain_models/src/payments.rs (4 hunks)
  • crates/hyperswitch_domain_models/src/payments/payment_attempt.rs (2 hunks)
  • crates/hyperswitch_domain_models/src/revenue_recovery.rs (1 hunks)
  • crates/openapi/src/openapi_v2.rs (1 hunks)
  • crates/router/src/core/fraud_check/flows/checkout_flow.rs (1 hunks)
  • crates/router/src/core/fraud_check/flows/record_return.rs (1 hunks)
  • crates/router/src/core/fraud_check/flows/sale_flow.rs (1 hunks)
  • crates/router/src/core/fraud_check/flows/transaction_flow.rs (1 hunks)
  • crates/router/src/core/payment_methods.rs (3 hunks)
  • crates/router/src/core/payment_methods/vault.rs (4 hunks)
  • crates/router/src/core/payments.rs (19 hunks)
  • crates/router/src/core/payments/customers.rs (2 hunks)
  • crates/router/src/core/payments/flows.rs (1 hunks)
  • crates/router/src/core/payments/flows/approve_flow.rs (1 hunks)
  • crates/router/src/core/payments/flows/authorize_flow.rs (1 hunks)
  • crates/router/src/core/payments/flows/cancel_flow.rs (1 hunks)
  • crates/router/src/core/payments/flows/capture_flow.rs (1 hunks)
  • crates/router/src/core/payments/flows/complete_authorize_flow.rs (1 hunks)
  • crates/router/src/core/payments/flows/incremental_authorization_flow.rs (1 hunks)
  • crates/router/src/core/payments/flows/post_session_tokens_flow.rs (1 hunks)
  • crates/router/src/core/payments/flows/psync_flow.rs (1 hunks)
  • crates/router/src/core/payments/flows/reject_flow.rs (1 hunks)
  • crates/router/src/core/payments/flows/session_flow.rs (1 hunks)
  • crates/router/src/core/payments/flows/session_update_flow.rs (1 hunks)
  • crates/router/src/core/payments/flows/setup_mandate_flow.rs (1 hunks)
  • crates/router/src/core/payments/flows/update_metadata_flow.rs (1 hunks)
  • crates/router/src/core/payments/helpers.rs (3 hunks)
  • crates/router/src/core/payments/operations.rs (1 hunks)
  • crates/router/src/core/payments/operations/payment_confirm_intent.rs (7 hunks)
  • crates/router/src/core/payments/operations/payment_get.rs (3 hunks)
  • crates/router/src/core/payments/operations/proxy_payments_intent.rs (2 hunks)
  • crates/router/src/core/payments/transformers.rs (12 hunks)
  • crates/router/src/core/payments/vault_session.rs (8 hunks)
  • crates/router/src/core/payouts/helpers.rs (1 hunks)
  • crates/router/src/core/revenue_recovery/api.rs (1 hunks)
  • crates/router/src/core/utils.rs (1 hunks)
  • crates/router/src/core/webhooks/incoming_v2.rs (2 hunks)
  • crates/router/src/core/webhooks/recovery_incoming.rs (1 hunks)
  • crates/router/src/routes/app.rs (1 hunks)
  • crates/router/src/routes/payments.rs (3 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (6)
crates/router/src/routes/app.rs (2)
crates/router/src/routes/payments.rs (18)
  • payments (147-153)
  • payments (218-224)
  • payments (344-350)
  • payments (401-408)
  • payments (483-490)
  • payments (560-567)
  • payments (683-690)
  • payments (743-750)
  • payments (876-883)
  • payments (940-947)
  • payments (1006-1013)
  • payments (1067-1074)
  • payments (1346-1353)
  • payments (1397-1404)
  • payments (1766-1773)
  • payments (1837-1844)
  • payment_status (2868-2953)
  • payments_status_with_gateway_creds (2957-3054)
crates/openapi/src/routes/payments.rs (1)
  • payment_status (783-783)
crates/common_utils/src/id_type/merchant.rs (2)
crates/common_utils/src/id_type/payment.rs (1)
  • from_str (93-96)
crates/common_utils/src/id_type/profile.rs (1)
  • from_str (29-32)
crates/router/src/core/payments/operations.rs (2)
crates/router/src/core/payments/operations/payment_confirm_intent.rs (1)
  • get_connector_from_request (492-506)
crates/router/src/core/payments/operations/payment_get.rs (1)
  • get_connector_from_request (349-366)
crates/router/src/core/payments/operations/payment_confirm_intent.rs (3)
crates/router/src/core/payments/operations.rs (1)
  • get_connector_from_request (295-303)
crates/router/src/core/payments/operations/payment_get.rs (1)
  • get_connector_from_request (349-366)
crates/router/src/core/payments/helpers.rs (1)
  • get_connector_data_from_request (1606-1625)
crates/hyperswitch_domain_models/src/merchant_connector_account.rs (2)
crates/router/src/core/payments/helpers.rs (6)
  • get_connector_account_details (3935-3940)
  • is_disabled (3949-3956)
  • get_metadata (3928-3933)
  • get_mca_id (3971-3976)
  • get_connector_name (3979-3984)
  • get_connector_name (3987-3992)
crates/diesel_models/src/merchant_connector_account.rs (2)
  • get_id (62-64)
  • get_id (108-110)
crates/router/src/routes/payments.rs (4)
crates/api_models/src/payments.rs (5)
  • default (1907-1909)
  • default (4292-4294)
  • new (790-801)
  • new (1793-1807)
  • new (1846-1851)
crates/router/src/core/payments.rs (9)
  • state (6673-6679)
  • payments_core (1709-1771)
  • payments_core (2154-2251)
  • payments_core (2333-2340)
  • payments_core (2353-2360)
  • payments_core (2578-2585)
  • payments_core (2745-2745)
  • payments_core (3081-3088)
  • payments_core (3120-3120)
crates/router/src/services/api.rs (1)
  • server_wrap (732-922)
crates/router/src/services/authentication.rs (2)
  • auth_type (4393-4404)
  • new (1907-1909)
🔇 Additional comments (74)
crates/router/src/core/revenue_recovery/api.rs (1)

35-35: LGTM: Consistent addition of merchant_connector_details field.

The explicit initialization to None maintains backward compatibility while supporting the new merchant connector details feature in the API. This is appropriate for revenue recovery flows that rely on existing database configurations.

crates/hyperswitch_domain_models/src/revenue_recovery.rs (1)

214-214: LGTM: Consistent field addition in domain model conversion.

The addition of merchant_connector_details: None in the conversion from RevenueRecoveryInvoiceData to PaymentsCreateIntentRequest maintains compatibility with the updated API structure while preserving existing behavior.

crates/router/src/core/webhooks/recovery_incoming.rs (1)

490-490: LGTM: Consistent field initialization in webhook processing.

The addition of merchant_connector_details: None to the PaymentsRetrieveRequest construction maintains existing webhook processing behavior while supporting the updated API structure.

crates/router/src/core/payments/operations/proxy_payments_intent.rs (2)

264-264: LGTM: Consistent field addition to PaymentConfirmData.

The initialization of merchant_connector_details: None follows the established pattern and maintains existing proxy payment behavior while supporting the new API structure.


365-373: LGTM: Appropriate handling of optional merchant_connector_id.

The wrapping of merchant_connector_id in Some() reflects the type change to optional as part of the new MerchantConnectorAccountTypeDetails abstraction. The error handling logic remains consistent while properly handling the optional nature of the field.

crates/router/src/core/payments/flows/incremental_authorization_flow.rs (1)

56-61: Flag incomplete implementation.

The parameter type change to domain::MerchantConnectorAccountTypeDetails aligns with the new abstraction, but the todo!() implementation indicates incomplete functionality.

Please confirm whether this incremental authorization flow is currently used in production, and if so, provide a timeline for completing the implementation. Incomplete implementations in production code paths could lead to runtime panics.

crates/common_utils/src/id_type/merchant.rs (2)

6-6: LGTM: Import addition is appropriate.

The addition of str::FromStr import supports the new trait implementation.


41-48: LGTM: Consistent implementation following established patterns.

The FromStr implementation follows the exact same pattern used by other ID types in the codebase (PaymentId, ProfileId), using Cow::Owned and delegating to the existing try_from logic. This enables string-based parsing of merchant identifiers, which aligns with the PR objective of supporting merchant connector details in payment flows.

crates/router/src/core/payments/flows.rs (1)

78-78: LGTM: Type update aligns with merchant connector abstraction refactor.

The parameter type change from MerchantConnectorAccountType to MerchantConnectorAccountTypeDetails is consistent with the broader refactoring effort to unify handling of merchant connector account information, supporting both database and direct credential flows as mentioned in the PR objectives.

crates/router/src/routes/app.rs (1)

663-667: LGTM! Clean implementation of dual HTTP method support.

The routing configuration correctly adds POST method support alongside the existing GET method for payment status retrieval. This follows RESTful design patterns where:

  • GET method uses query parameters for simple status checks
  • POST method accepts JSON payload with merchant connector details

The implementation aligns with the PR objective of supporting merchant_connector_details in the Payments and Psync flow.

crates/router/src/core/webhooks/incoming_v2.rs (1)

477-477: LGTM - Correct field initialization for webhook flows.

The initialization of merchant_connector_details: None is appropriate for webhook handling, as incoming webhooks don't typically carry merchant connector credentials. The changes correctly integrate with the new field addition to payment request and response structures.

Also applies to: 682-682

crates/router/src/core/fraud_check/flows/sale_flow.rs (1)

34-34: Parameter type update aligns with merchant connector abstraction.

The change from &domain::MerchantConnectorAccount to &domain::MerchantConnectorAccountTypeDetails is consistent with the broader refactoring to use the new enum abstraction that supports both database-backed accounts and direct merchant connector details.

crates/router/src/core/payments/flows/authorize_flow.rs (1)

43-43: Parameter type update supports enhanced connector account handling.

The migration to &domain::MerchantConnectorAccountTypeDetails enables the authorize flow to handle both traditional database-backed merchant connector accounts and direct merchant connector details from API requests, supporting the new payment flow flexibility.

crates/router/src/core/fraud_check/flows/transaction_flow.rs (1)

39-39: Consistent parameter type migration for fraud check flows.

The update to &domain::MerchantConnectorAccountTypeDetails maintains consistency with the broader refactoring effort to support the new merchant connector account abstraction across all payment and fraud check flows.

crates/router/src/core/payments/flows/reject_flow.rs (1)

52-52: Parameter type update completes flow consistency.

The change to &domain::MerchantConnectorAccountTypeDetails ensures the reject flow follows the same parameter type pattern as other payment flows, supporting the unified merchant connector account abstraction.

crates/openapi/src/openapi_v2.rs (1)

424-426: LGTM: OpenAPI schema additions align with PR objectives.

The addition of these three new payment-related models to the OpenAPI schema correctly exposes the new merchant connector details functionality. This ensures proper API documentation for the enhanced payment flows.

crates/router/src/core/payments/flows/update_metadata_flow.rs (1)

55-55: Parameter type update aligns with merchant connector details refactor.

The change from &helpers::MerchantConnectorAccountType to &domain::MerchantConnectorAccountTypeDetails is consistent with the broader refactor to support the new merchant connector details abstraction. This signature change prepares the v2 flow for the new enum type.

crates/router/src/core/payments/flows/post_session_tokens_flow.rs (1)

56-56: Parameter type update consistent with refactor pattern.

This parameter type change from &helpers::MerchantConnectorAccountType to &domain::MerchantConnectorAccountTypeDetails follows the same pattern as other flow implementations, ensuring consistency across the v2 payment flows.

crates/router/src/core/payments/operations.rs (1)

294-303: New method supports v2 connector data extraction from requests.

The addition of get_connector_from_request method to the Domain trait enables v2 payment flows to extract connector data directly from requests containing merchant_connector_details. The default implementation provides clear error messaging for unimplemented operations.

Based on the relevant code snippets, concrete implementations already exist in specific operations like payment_confirm_intent.rs and payment_get.rs that properly extract connector data and update payment attempts.

crates/router/src/core/payments/flows/capture_flow.rs (1)

69-69: Parameter type change aligns with merchant connector details abstraction.

The update from &domain::MerchantConnectorAccount to &domain::MerchantConnectorAccountTypeDetails in the v2 capture flow implementation is consistent with the broader refactor to support the new merchant connector details enum abstraction. This enables the capture flow to work with both traditional merchant connector accounts and new merchant connector credentials.

crates/router/src/core/payments/flows/setup_mandate_flow.rs (1)

79-79:

✅ Verification successful

LGTM! Parameter type correctly updated for v2 implementation.

The change from &domain::MerchantConnectorAccount to &domain::MerchantConnectorAccountTypeDetails correctly aligns with the new abstraction that supports both database-backed merchant connector accounts and direct merchant connector credentials from API requests.

Let me verify that this change is consistent with other payment flow files that were part of this refactor:


🏁 Script executed:

#!/bin/bash
# Description: Verify parameter type consistency across payment flow files
# Expected: All v2 construct_router_data methods should use MerchantConnectorAccountTypeDetails

echo "Checking parameter types in construct_router_data methods across payment flows..."
fd ".*_flow\.rs$" crates/router/src/core/payments/flows/ --exec grep -l "construct_router_data" {} \; | while read file; do
    echo "=== $file ==="
    rg -A 10 "async fn construct_router_data" "$file" | rg "merchant_connector_account:"
done

Length of output: 6112


Consistent v2 construct_router_data Parameters Confirmed

All payment-flow implementations under the v2 feature flag now uniformly accept
&domain::MerchantConnectorAccountTypeDetails for the merchant_connector_account parameter. No discrepancies were found across *_flow.rs files.

crates/hyperswitch_domain_models/src/payments/payment_attempt.rs (2)

1756-1756: LGTM: Field optionality correctly implements flexible connector handling.

Making merchant_connector_id optional in the ConfirmIntent variant aligns with the PR objective to support both database-backed merchant connector accounts and direct credential flows. This change enables the new MerchantConnectorAccountTypeDetails abstraction.


2551-2551: LGTM: Conversion logic correctly handles optional field.

The direct assignment of merchant_connector_id is appropriate since the field is now optional in the source enum variant. This eliminates the need to wrap an already-optional value in Some().

crates/router/src/core/payments/flows/session_update_flow.rs (1)

56-56: Type change aligns with the merchant connector refactor.

The parameter type change from &domain::MerchantConnectorAccount to &domain::MerchantConnectorAccountTypeDetails is consistent with the broader refactor to support both database-backed and API-provided merchant connector credentials.

crates/router/src/core/payments/flows/complete_authorize_flow.rs (1)

63-63: Type change is consistent with the refactor pattern.

The parameter type update to &domain::MerchantConnectorAccountTypeDetails follows the same pattern as other payment flows and supports the new merchant connector details functionality.

crates/router/src/core/payments/flows/cancel_flow.rs (1)

25-25: Parameter type update follows established pattern.

The change to &domain::MerchantConnectorAccountTypeDetails is consistent with the merchant connector account refactor across all payment flows.

crates/router/src/core/payments/flows/approve_flow.rs (1)

26-26: Type signature update aligns with refactor goals.

The parameter type change to &domain::MerchantConnectorAccountTypeDetails maintains consistency with the merchant connector account handling refactor.

crates/router/src/core/fraud_check/flows/record_return.rs (1)

36-36: Fraud check flow updated consistently with payment flows.

The parameter type change to &domain::MerchantConnectorAccountTypeDetails extends the merchant connector account refactor to fraud check flows, maintaining consistency across the codebase.

crates/hyperswitch_domain_models/src/customer.rs (2)

23-24: LGTM: Clean import addition for the new enum type.

The conditional import is properly scoped under the appropriate feature flags.


104-118: LGTM: Correct implementation of enum pattern matching.

The method properly handles both variants of MerchantConnectorAccountTypeDetails:

  • For MerchantConnectorAccount: Maintains existing logic to lookup connector customer ID
  • For MerchantConnectorDetails: Returns None, which is appropriate since direct credentials don't have stored connector customer mappings

The pattern matching is exhaustive and follows Rust best practices.

crates/router/src/core/payments/flows/session_flow.rs (1)

43-43: LGTM: Signature update aligns with enum refactor.

The parameter type change from &helpers::MerchantConnectorAccountType to &domain::MerchantConnectorAccountTypeDetails is consistent with the broader refactor to support both database-backed accounts and direct merchant connector credentials.

crates/router/src/core/payouts/helpers.rs (1)

1036-1036: LGTM! Parameter type change aligns with the refactoring objectives.

The parameter type change from id_type::MerchantConnectorAccountId to domain::MerchantConnectorAccountTypeDetails correctly supports the new feature for accepting dynamic merchant connector credentials while maintaining the same function logic. This change is appropriately scoped to the v2 + customer_v2 features and is consistent with the broader refactoring described in the PR objectives.

crates/router/src/core/utils.rs (1)

2043-2054: API type migration looks correct but double-check the return type of get_connector_account_details()

You switched from the legacy parse-then-convert path to directly using the value returned by
get_connector_account_details(), assuming it is already a types::ConnectorAuthType.

If that helper still returns a serde_json::Value (or a raw string) in any variant, the implicit
conversion you dropped will break at runtime. Please confirm the signature:

fn get_connector_account_details(&self) -> CustomResult<types::ConnectorAuthType /* ? */>

If the function still returns a generic Value, you need to restore the parse_value::<ConnectorAuthType> step.

crates/router/src/core/payments/operations/payment_get.rs (1)

238-248: Good addition: persisting merchant_connector_details in PaymentStatusData

Persisting the cloned merchant_connector_details ensures downstream flows
(e.g. PSync, Vault) can retrieve connector data without re-parsing the request.
Nice catch.

crates/hyperswitch_domain_models/src/payments.rs (5)

5-5: LGTM: Import addition is correctly used.

The new import for MerchantConnectorDetails is properly utilized in the struct field definitions below.


45-47: LGTM: Import updates align with the refactor.

The addition of MerchantConnectorAccountTypeDetails import is consistent with the broader codebase refactor to support the new enum abstraction.


860-860: LGTM: Consistent field addition for payment confirmation flow.

The merchant_connector_details field addition to PaymentConfirmData aligns with the PR objective to support direct credential passing in payment flows.


868-880: LGTM: Well-implemented polymorphic logic for connector customer ID retrieval.

The updated method correctly handles both enum variants:

  • For stored accounts (MerchantConnectorAccount), it maintains existing logic to retrieve connector customer ID from customer or feature metadata
  • For direct credentials (MerchantConnectorDetails), it appropriately returns None since there wouldn't be a pre-existing connector customer ID

This implementation maintains backward compatibility while supporting the new direct credential flow.


913-913: LGTM: Consistent field addition for payment status flow.

The merchant_connector_details field addition to PaymentStatusData is consistent with the same field added to PaymentConfirmData, ensuring uniform support across both payment and psync flows as intended.

crates/router/src/core/fraud_check/flows/checkout_flow.rs (1)

38-38: LGTM: Parameter type update aligns with codebase refactor.

The parameter type change from &domain::MerchantConnectorAccount to &domain::MerchantConnectorAccountTypeDetails is consistent with the broader refactor to use the new enum abstraction. Since this function is marked as todo!(), this change appropriately prepares the signature for future implementation.

crates/router/src/core/payment_methods.rs (3)

1878-1878: LGTM! Type parameter update aligns with unified merchant connector account handling.

This change correctly updates the function parameter to use the new MerchantConnectorAccountTypeDetails abstraction, which is part of the broader refactoring to unify merchant connector account handling across the codebase.


1981-1991: LGTM! Correct implementation of the new merchant connector account abstraction.

The change properly:

  • Uses the new get_merchant_connector_account_v2 helper function
  • Wraps the result in MerchantConnectorAccountTypeDetails::MerchantConnectorAccount(Box::new(...)) enum variant
  • Maintains the same error handling and context attachment

This correctly implements the unified merchant connector account handling pattern.


2952-2952: LGTM! Appropriate field addition for zero-auth payments.

Setting merchant_connector_details: None for zero-auth payments is correct since these payments are typically used for payment method validation rather than actual processing, and specific merchant connector details may not be required in this context.

crates/router/src/routes/payments.rs (1)

871-890:

✅ Verification successful

Verify field mapping completeness in payload transformation.

The transformation from PaymentsStatusRequest to PaymentsRetrieveRequest only maps specific fields (force_sync, expand_attempts, param, all_keys_required) while using ..Default::default() for others. Ensure that no critical fields are being inadvertently omitted in this conversion.


🏁 Script executed:

#!/bin/bash
# Description: Compare field definitions between PaymentsStatusRequest and PaymentsRetrieveRequest
# to ensure no important fields are missing from the mapping

# Search for PaymentsStatusRequest field definitions
echo "=== PaymentsStatusRequest fields ==="
ast-grep --pattern 'struct PaymentsStatusRequest {
  $$$
}'

echo -e "\n=== PaymentsRetrieveRequest fields ==="
ast-grep --pattern 'struct PaymentsRetrieveRequest {
  $$$
}'

echo -e "\n=== Check for merchant_connector_details usage ==="
rg -A 3 -B 3 "merchant_connector_details" --type rust

Length of output: 54971


🏁 Script executed:

#!/bin/bash
# Locate the struct definitions to compare their fields

echo "=== PaymentsStatusRequest definition ==="
rg -n "struct PaymentsStatusRequest" -A 20 crates/api_models/src/payments.rs

echo -e "\n=== PaymentsRetrieveRequest definition ==="
rg -n "struct PaymentsRetrieveRequest" -A 20 crates/api_models/src/payments.rs

Length of output: 4955


🏁 Script executed:

#!/bin/bash
# Extract the mapping of PaymentsStatusRequest into the internal request
echo "=== Mapping PaymentsStatusRequest to internal payload ==="
rg -n "PaymentsStatusRequest" -C 10 crates/router/src/routes/payments.rs

# Also inspect where PaymentsRetrieveRequest is constructed for the status handler
echo -e "\n=== Construction of PaymentsRetrieveRequest in status handler ==="
rg -n "PaymentsRetrieveRequest" -C 10 crates/router/src/routes/payments.rs

Length of output: 6424


Field mapping is correct and intentional.

The payment_status handler uses PaymentsStatusRequest, which only defines force_sync, expand_attempts, param, and all_keys_required. All other fields (including merchant_connector_details) correctly default to None. The new payments_status_with_gateway_creds endpoint explicitly handles merchant_connector_details via its own request type. No changes needed.

crates/router/src/core/payments/customers.rs (1)

107-131: Risk of silently skipping customer-creation for credential-based connections

For the MerchantConnectorDetails variant the function hard-codes (false, None), i.e. it never calls the connector even if that connector appears in connector_customer.connector_list.
If any connector still mandates a customer object while being driven by runtime credentials, this branch will suppress the create-customer call and you’ll hit connector-side validation errors at run-time.

Please double-check business requirements; if customer-creation may still be required with direct credentials, consider keeping the existing logic and falling back only when the connector explicitly states it is unnecessary.

crates/router/src/core/payments/operations/payment_confirm_intent.rs (1)

152-154: Inconsistent identifier type between get_trackers and callers

payment_id switched to &id_type::GlobalPaymentId. Verify every caller (handlers, tests, cron jobs) now passes a GlobalPaymentId; older code paths that still send a plain PaymentId will fail to compile.

crates/router/src/core/payments/helpers.rs (1)

7344-7363:

❓ Verification inconclusive

Verify the impact of removing Redis caching and credential lookup

The get_merchant_connector_account_v2 function has been significantly simplified by removing:

  1. Redis caching functionality
  2. Credential identifier-based lookup
  3. merchant_id and creds_identifier parameters

This is a breaking change that could impact performance if the Redis cache was providing significant benefits. Please ensure that:

  1. This simplification is intentional
  2. Any code that depended on the removed functionality has been updated
  3. The performance impact has been evaluated

🏁 Script executed:

#!/bin/bash
# Check for any remaining usages of the old function signature with merchant_id or creds_identifier
rg -A 5 "get_merchant_connector_account_v2.*merchant_id|get_merchant_connector_account_v2.*creds_identifier"

# Check for any code that might be expecting the Redis caching behavior
rg -A 10 "get_merchant_connector_account_v2" | grep -i "redis\|cache"

Length of output: 180


Verify removal of Redis caching and credential‐lookup
Our search across the repo found no remaining calls to get_merchant_connector_account_v2 using the old merchant_id/creds_identifier signature, nor any references to Redis or “cache” around its call sites. It appears all invocations have been updated to the new, simplified version.

Please confirm that:

  • Removing Redis caching and the credential-identifier lookup is intentional.
  • Any code that depended on the old behavior has been updated or deprecated.
  • You’ve evaluated the performance impact of dropping the cache (e.g., via benchmarks or metrics).
crates/hyperswitch_domain_models/src/merchant_connector_account.rs (6)

96-101: LGTM: Well-designed enum abstraction.

The enum provides a clean polymorphic interface over two different representations of merchant connector account details. Using Box<MerchantConnectorAccount> is good for performance, avoiding expensive copying of large structs.


105-125: LGTM: Consistent connector account details parsing.

The method properly handles both variants with consistent error handling using parse_value("ConnectorAuthType"). The use of peek() for the MerchantConnectorAccount variant is appropriate for v2 implementation.


127-134: LGTM: Appropriate disabled status handling.

The logic correctly returns the actual disabled status for MerchantConnectorAccount and defaults to false for MerchantConnectorDetails, which is reasonable since dynamically provided credentials shouldn't be considered disabled.


136-143: LGTM: Metadata handling is appropriate.

Correctly returns metadata for MerchantConnectorAccount and None for MerchantConnectorDetails, which is expected since dynamically provided connector details don't include metadata.


163-170: LGTM: Connector name retrieval is properly implemented.

The method appropriately returns the connector name only for the MerchantConnectorAccount variant, which makes sense since MerchantConnectorDetails doesn't contain this information.


172-180: LGTM: Inner database access method is well-designed.

This method provides safe access to the underlying MerchantConnectorAccount when available, returning None for the MerchantConnectorDetails variant. This is useful for operations that specifically require database-backed account information.

crates/router/src/core/payments/transformers.rs (5)

186-186: LGTM: Parameter type change is consistent across all functions.

The parameter type change from &domain::MerchantConnectorAccount to &domain::MerchantConnectorAccountTypeDetails is consistently applied across all the payment router data construction functions. This aligns with the PR objective of introducing the new abstraction to support both database and direct credential flows.

Also applies to: 412-412, 575-575, 699-699, 881-881


226-235: Correct conditional webhook URL generation logic.

The webhook URL generation is properly conditioned based on the enum variant:

  • Generates webhook URL only for MerchantConnectorAccount (database entities)
  • Returns None for MerchantConnectorDetails (ephemeral request data)

This is the correct behavior since webhook URLs are only relevant for persisted connector accounts, not for direct connector credentials passed in API requests.

Also applies to: 922-931


906-906: Method signature update aligns with new enum type.

The call to customer.get_connector_customer_id(merchant_connector_account) now passes the entire MerchantConnectorAccountTypeDetails enum instead of just an ID. This suggests the method signature was properly updated to handle both enum variants and extract the appropriate identifier based on the variant type.


1848-1848: Simplified merchant_connector_id handling is appropriate.

The removal of error handling around .get_required_value() and direct cloning of merchant_connector_id suggests this field is now properly optional at the model level. This simplification aligns with making the field optional to support scenarios where merchant connector details are provided directly in the request rather than referenced by ID.

Also applies to: 1903-1903


1914-1914: Addition of merchant_reference_id in responses supports PR objectives.

The inclusion of merchant_reference_id in the PaymentsResponse aligns with the PR objective of including this field in payment responses. This provides better traceability and supports the merchant's own reference system for payments.

Also applies to: 2009-2009

crates/api_models/src/payments.rs (1)

5796-5802: LGTM! Good addition for payment idempotency

The merchant_reference_id field is well-documented with appropriate schema constraints (min/max length of 30) and a clear example.

crates/router/src/core/payments/vault_session.rs (3)

136-174: Parameter type updated – please cascade unit-test coverage

The signature now accepts &MerchantConnectorAccountTypeDetails, broadening the surface to handle both DB-backed and request-supplied credentials.
Current unit tests only cover the DB MCA variant. Add tests exercising the new MerchantConnectorDetails path (e.g., missing MCA ID, auth parsing) to prevent regressions.


331-332: Security footnote – runtime token selection

get_mca_id() returns None for request-supplied credentials. Ensure the downstream get_connector_by_name gracefully falls back to global connector tokens and never picks up an unrelated MCA’s token set.


193-198:

❌ Incorrect review comment

Possible error silently ignored from update_connector_customer_in_customers

The result of update_connector_customer_in_customers is assigned without ?.
If the helper returns Result<…>, the error would be swallowed and wrapped in Ok(customer_update), changing the function’s return type and masking failures.

-let customer_update = customers::update_connector_customer_in_customers(
+let customer_update = customers::update_connector_customer_in_customers(
     merchant_connector_account_type,
     customer.as_ref(),
     connector_customer_id.clone(),
-)
-.await;
+)
+.await?;

Please confirm the helper’s signature and propagate errors if applicable.


🏁 Script executed:

#!/bin/bash
# Verify the actual return type of the helper.
rg -n "fn update_connector_customer_in_customers" -A3 -B1

Length of output: 959


🏁 Script executed:

#!/bin/bash
# Display the update_connector_customer_in_customers function signatures with return types
sed -n '130,200p' crates/router/src/core/payments/customers.rs

Length of output: 2336


Helper returns Option, not Result
The update_connector_customer_in_customers function’s signature is

pub async fn update_connector_customer_in_customers(...) -> Option<storage::CustomerUpdate>

Since it returns an Option rather than a Result, there is no error to propagate with ?. The existing .await call correctly yields an Option<…>, and no change is needed here.

Likely an incorrect or invalid review comment.

crates/router/src/core/payments.rs (12)

1960-1964: Addition looks good

merchant_connector_details is now explicitly initialised – good defensive default.


1983-1987: LGTM

Consistent initialisation of the new field.


1993-1997: LGTM

Same as above – consistent defaulting.


2210-2241: Op must be Clone – confirm trait bounds

operation.clone() is invoked twice, but the generic bounds of Op in this scope are not visible here.
If Op: Clone is not already enforced in the function signature, the code will fail to compile.

Please verify that the payments_core signature (or a higher-level bound) includes:

Op: Clone + /* existing bounds */

2873-2877: Looks good

New field set to None; keeps behaviour unchanged for the legacy flow.


4008-4014: Runtime failure possible – merchant_connector_details is mandatory

get_merchant_connector_details() is unwrapped with ok_or_else, but earlier implementations of the trait return todo!() or None.
Unless every concrete D used in this path provides the field, the request will crash with a 500.

Verify all implementers or provide a graceful error at validation time.


4865-4865: Signature update looks correct

Parameter updated to the enum wrapper – keeps the call-site consistent.


4886-4898: Confirm get_id() is implemented for the enum

merchant_connector_account.get_id() is invoked.
Ensure the new MerchantConnectorAccountTypeDetails enum provides this method for all variants, or compilation will fail.

If not, add:

impl MerchantConnectorAccountTypeDetails {
    pub fn get_id(&self) -> &str { /* match &self { … } */ }
}

4918-4922: LGTM

Passing the enum variant downstream keeps the customer update logic isolated.


9394-9398: Implementation looks correct

Returns the cloned details – matches the trait contract.


9675-9679: Implementation looks correct

Same as above for the status flow – good.


9927-9929: Setter fix is correct

Directly assigning to payment_attempt.connector prevents the earlier panic.

Copy link
Contributor

@hrithikesh026 hrithikesh026 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please generate open api spec

@swangi-kumari swangi-kumari removed request for a team June 16, 2025 06:45
sahkal
sahkal previously approved these changes Jun 16, 2025
Sakilmostak
Sakilmostak previously approved these changes Jun 16, 2025
@Sakilmostak
Copy link
Contributor

Payment-method changes looks good!

Comment on lines +5645 to +5647
/// These are the query params that are sent in case of redirect response.
/// These can be ingested by the connector to take necessary actions.
pub param: Option<String>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Can we come up with a better name for this field maybe?

Comment on lines +2990 to +3005
match env::which() {
env::Env::Production => &auth::V2ApiKeyAuth {
is_connected_allowed: false,
is_platform_allowed: false,
},
_ => auth::auth_type(
&auth::V2ApiKeyAuth {
is_connected_allowed: false,
is_platform_allowed: false,
},
&auth::JWTAuth {
permission: Permission::ProfilePaymentWrite,
},
req.headers(),
),
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Do we need JWT auth here at all?

@hyperswitch-bot hyperswitch-bot bot added the M-api-contract-changes Metadata: This PR involves API contract changes label Jun 17, 2025
@likhinbopanna likhinbopanna added this pull request to the merge queue Jun 17, 2025
Merged via the queue into main with commit b8b1960 Jun 17, 2025
15 of 20 checks passed
@likhinbopanna likhinbopanna deleted the v2-tunnel branch June 17, 2025 15:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-core Area: Core flows M-api-contract-changes Metadata: This PR involves API contract changes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants