Skip to content

feat(routing): add profile config to switch between HS routing and DE routing result#8350

Merged
likhinbopanna merged 43 commits intomainfrom
routing-result-switch
Jun 20, 2025
Merged

feat(routing): add profile config to switch between HS routing and DE routing result#8350
likhinbopanna merged 43 commits intomainfrom
routing-result-switch

Conversation

@jagan-jaya
Copy link
Contributor

@jagan-jaya jagan-jaya commented Jun 16, 2025

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

Description

This pull request introduces a new field, routing_result_source, across various structs and enums in the codebase to specify the source of routing decision results. This field allows for flexibility in choosing between Hyperswitch's inbuilt routing engine and an external decision engine. The changes span multiple modules, including API models, database models, and domain models.

Also, while creating the routing rule decision engine rule_id will be prefilled with the hyperswitch rule_id, so both systems will have the same id

Additional Changes

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

Motivation and Context

Add profile-level config to choose between Hyperswitch routing result and Decision engine routing result

How did you test it?

  1. Create a merchant account, API key, profile, connector
2. Create Routing Rule

Request

curl --location 'http://localhost:8080/routing' \
--header 'X-Profile-Id: pro_Wt98jyZeU8jaQ3cr9zDP' \
--header 'api-key: dev_yUplJwLqvtAJiqOMmiamv78Xj9k1DkaEK3kxRExy4baMX4tsSVpEm55eTohlaifG' \
--data '{
    "name": "Rule Based Routing-2025-05-07",
    "description": "This is a rule based routing created at Wed, 07 May 2025 13:03:39 GMT",
    "profile_id": "pro_Wt98jyZeU8jaQ3cr9zDP",
    "algorithm": {
        "type": "advanced",
        "data": {
            "defaultSelection": {
                "type": "priority",
                "data": []
            },
            "metadata": {},
            "rules": [
                {
                    "name": "rule_1",
                    "connectorSelection": {
                        "type": "priority",
                        "data": [
                            {
                                "connector": "cybersource",
                                "merchant_connector_id": "mca_EU1XaLVDXZumYK8r3ft7"
                            }
                        ]
                    },
                    "statements": [
                        {
                            "condition": [
                                {
                                    "lhs": "billing_country",
                                    "comparison": "equal",
                                    "value": {
                                        "type": "enum_variant",
                                        "value": "India"
                                    },
                                    "metadata": {}
                                }
                            ],
                            "nested": null
                        }
                    ]
                }
            ]
        }
    }
}'

Response

{
    "id": "routing_rFQyeEY3ujqyjtjJIlDB",
    "profile_id": "pro_Wt98jyZeU8jaQ3cr9zDP",
    "name": "Rule Based Routing-2025-05-07",
    "kind": "advanced",
    "description": "This is a rule based routing created at Wed, 07 May 2025 13:03:39 GMT",
    "created_at": 1750082560,
    "modified_at": 1750082560,
    "algorithm_for": "payment",
    "decision_engine_routing_id": "routing_rFQyeEY3ujqyjtjJIlDB"
}
3. List Routing Rules

Request

  curl --location 'http://localhost:8080/configs/' \
  --header 'Content-Type: application/json' \
  --header 'Accept: application/json' \
  --header 'api-key: test_admin' \
  --data '{
      "key": "routing_result_source_pro_Wt98jyZeU8jaQ3cr9zDP",
      "value": "decision_engine"
  }'

Response

 {
     key: "routing_result_source_pro_Wt98jyZeU8jaQ3cr9zDP",
     value: "decision_engine" 
 }

Rules are getting fetched from hyperswitch
Screenshot 2025-06-16 at 7 35 55 PM

4. Change Profile config to use decision engine result directly

Request

curl --location 'http://localhost:8080/account/merchant_1750082519/business_profile/pro_Wt98jyZeU8jaQ3cr9zDP' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: dev_j1154b6pVqBwC32eFEcQDZDIBKGGEBT3zh3VMi3cWUpFcurnQqBD2SDLXmFbaJem' \
--data '{
        "dynamic_routing_algorithm": {
            "routing_result_source": "decision_engine"
        }
    }'

Response

{
    "merchant_id": "merchant_1750082519",
    "profile_id": "pro_Wt98jyZeU8jaQ3cr9zDP",
    "profile_name": "1750082525",
    "return_url": "https://google.com/success",
    "enable_payment_response_hash": true,
    "payment_response_hash_key": "MkZkTPS7BIusBLHYEmQCKB0FaGiTkTsASUBTQCfuEuGwCRrN9zso4M0qIOKValbF",
    "redirect_to_merchant_with_http_post": false,
    "webhook_details": {
        "webhook_version": "1.0.1",
        "webhook_username": "ekart_retail",
        "webhook_password": "password_ekart@123",
        "webhook_url": null,
        "payment_created_enabled": true,
        "payment_succeeded_enabled": true,
        "payment_failed_enabled": true
    },
    "metadata": null,
    "routing_algorithm": null,
    "intent_fulfillment_time": 900,
    "frm_routing_algorithm": null,
    "payout_routing_algorithm": null,
    "applepay_verified_domains": null,
    "session_expiry": 900,
    "payment_link_config": null,
    "authentication_connector_details": null,
    "use_billing_as_payment_method_billing": true,
    "extended_card_info_config": null,
    "collect_shipping_details_from_wallet_connector": false,
    "collect_billing_details_from_wallet_connector": false,
    "always_collect_shipping_details_from_wallet_connector": false,
    "always_collect_billing_details_from_wallet_connector": false,
    "is_connector_agnostic_mit_enabled": false,
    "payout_link_config": null,
    "outgoing_webhook_custom_http_headers": null,
    "tax_connector_id": null,
    "is_tax_connector_enabled": false,
    "is_network_tokenization_enabled": false,
    "is_auto_retries_enabled": false,
    "max_auto_retries_enabled": null,
    "always_request_extended_authorization": null,
    "is_click_to_pay_enabled": false,
    "authentication_product_ids": null,
    "card_testing_guard_config": {
        "card_ip_blocking_status": "disabled",
        "card_ip_blocking_threshold": 3,
        "guest_user_card_blocking_status": "disabled",
        "guest_user_card_blocking_threshold": 10,
        "customer_id_blocking_status": "disabled",
        "customer_id_blocking_threshold": 5,
        "card_testing_guard_expiry": 3600
    },
    "is_clear_pan_retries_enabled": false,
    "force_3ds_challenge": false,
    "is_debit_routing_enabled": false,
    "merchant_business_country": null,
    "is_pre_network_tokenization_enabled": false,
    "acquirer_configs": null,
    "is_iframe_redirection_enabled": null,
    "merchant_category_code": null
}
5. List Routing Rules again This time result from the decision engine should be used to return results

Request

curl --location 'http://localhost:8080/routing/list/profile?limit=100' \
--header 'sec-ch-ua-platform: "macOS"' \
--header 'Referer: https://app.hyperswitch.io/dashboard/routing' \
--header 'sec-ch-ua: "Chromium";v="136", "Google Chrome";v="136", "Not.A/Brand";v="99"' \
--header 'X-Profile-Id: pro_Wt98jyZeU8jaQ3cr9zDP' \
--header 'sec-ch-ua-mobile: ?0' \
--header 'api-key: dev_yUplJwLqvtAJiqOMmiamv78Xj9k1DkaEK3kxRExy4baMX4tsSVpEm55eTohlaifG' \
--header 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36' \
--header 'Content-Type: application/json'

Response

  [
      {
          "id": "routing_rFQyeEY3ujqyjtjJIlDB",
          "profile_id": "pro_Wt98jyZeU8jaQ3cr9zDP",
          "name": "Rule Based Routing-2025-05-07",
          "kind": "advanced",
          "description": "This is a rule based routing created at Wed, 07 May 2025 13:03:39 GMT",
          "created_at": 1750082560,
          "modified_at": 1750082560,
          "algorithm_for": "payment",
          "decision_engine_routing_id": null
      }
  ]
Screenshot 2025-06-16 at 7 37 57 PM

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

@semanticdiff-com
Copy link

semanticdiff-com bot commented Jun 16, 2025

Review changes with  SemanticDiff

Changed Files
File Status
  crates/router/src/core/payments/routing.rs  72% smaller
  crates/router/src/core/routing.rs  32% smaller
  crates/router/src/core/payments/routing/utils.rs  8% smaller
  crates/hyperswitch_domain_models/src/business_profile.rs  6% smaller
  crates/router/src/core/routing/helpers.rs  1% smaller
  crates/api_models/src/open_router.rs  0% smaller
  crates/api_models/src/routing.rs  0% smaller

@hyperswitch-bot hyperswitch-bot bot added the M-database-changes Metadata: This PR involves database schema changes label Jun 16, 2025
@jagan-jaya jagan-jaya linked an issue Jun 16, 2025 that may be closed by this pull request
@jagan-jaya jagan-jaya marked this pull request as ready for review June 16, 2025 14:12
@jagan-jaya jagan-jaya requested review from a team as code owners June 16, 2025 14:12
@jagan-jaya jagan-jaya self-assigned this Jun 17, 2025
@hyperswitch-bot hyperswitch-bot bot removed the M-database-changes Metadata: This PR involves database schema changes label Jun 17, 2025
@likhinbopanna likhinbopanna added this pull request to the merge queue Jun 20, 2025
Merged via the queue into main with commit a721d90 Jun 20, 2025
16 of 20 checks passed
@likhinbopanna likhinbopanna deleted the routing-result-switch branch June 20, 2025 13:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Create a profile level config to switch between routing engine

4 participants