mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-11-02 04:04:43 +08:00
feat(router): Add Smart Routing to route payments efficiently (#2665)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: shashank_attarde <shashank.attarde@juspay.in> Co-authored-by: Aprabhat19 <amishaprabhat@gmail.com> Co-authored-by: Amisha Prabhat <55580080+Aprabhat19@users.noreply.github.com>
This commit is contained in:
@ -1,6 +1,8 @@
|
||||
use std::str::FromStr;
|
||||
|
||||
use api_models::{
|
||||
admin::{self as admin_types},
|
||||
enums as api_enums,
|
||||
enums as api_enums, routing as routing_types,
|
||||
};
|
||||
use common_utils::{
|
||||
crypto::{generate_cryptographically_secure_random_string, OptionalSecretValue},
|
||||
@ -18,6 +20,7 @@ use crate::{
|
||||
core::{
|
||||
errors::{self, RouterResponse, RouterResult, StorageErrorExt},
|
||||
payments::helpers,
|
||||
routing::helpers as routing_helpers,
|
||||
utils as core_utils,
|
||||
},
|
||||
db::StorageInterface,
|
||||
@ -89,7 +92,7 @@ pub async fn create_merchant_account(
|
||||
.transpose()?;
|
||||
|
||||
if let Some(ref routing_algorithm) = req.routing_algorithm {
|
||||
let _: api::RoutingAlgorithm = routing_algorithm
|
||||
let _: api_models::routing::RoutingAlgorithm = routing_algorithm
|
||||
.clone()
|
||||
.parse_value("RoutingAlgorithm")
|
||||
.change_context(errors::ApiErrorResponse::InvalidDataValue {
|
||||
@ -178,7 +181,10 @@ pub async fn create_merchant_account(
|
||||
.await?,
|
||||
return_url: req.return_url.map(|a| a.to_string()),
|
||||
webhook_details,
|
||||
routing_algorithm: req.routing_algorithm,
|
||||
routing_algorithm: Some(serde_json::json!({
|
||||
"algorithm_id": null,
|
||||
"timestamp": 0
|
||||
})),
|
||||
sub_merchants_enabled: req.sub_merchants_enabled,
|
||||
parent_merchant_id,
|
||||
enable_payment_response_hash,
|
||||
@ -470,7 +476,7 @@ pub async fn merchant_account_update(
|
||||
}
|
||||
|
||||
if let Some(ref routing_algorithm) = req.routing_algorithm {
|
||||
let _: api::RoutingAlgorithm = routing_algorithm
|
||||
let _: api_models::routing::RoutingAlgorithm = routing_algorithm
|
||||
.clone()
|
||||
.parse_value("RoutingAlgorithm")
|
||||
.change_context(errors::ApiErrorResponse::InvalidDataValue {
|
||||
@ -756,6 +762,9 @@ pub async fn create_payment_connector(
|
||||
)
|
||||
.await?;
|
||||
|
||||
let routable_connector =
|
||||
api_enums::RoutableConnectors::from_str(&req.connector_name.to_string()).ok();
|
||||
|
||||
let business_profile = state
|
||||
.store
|
||||
.find_business_profile_by_profile_id(&profile_id)
|
||||
@ -828,6 +837,37 @@ pub async fn create_payment_connector(
|
||||
|
||||
let frm_configs = get_frm_config_as_secret(req.frm_configs);
|
||||
|
||||
// The purpose of this merchant account update is just to update the
|
||||
// merchant account `modified_at` field for KGraph cache invalidation
|
||||
let merchant_account_update = storage::MerchantAccountUpdate::Update {
|
||||
merchant_name: None,
|
||||
merchant_details: None,
|
||||
return_url: None,
|
||||
webhook_details: None,
|
||||
sub_merchants_enabled: None,
|
||||
parent_merchant_id: None,
|
||||
enable_payment_response_hash: None,
|
||||
locker_id: None,
|
||||
payment_response_hash_key: None,
|
||||
primary_business_details: None,
|
||||
metadata: None,
|
||||
publishable_key: None,
|
||||
redirect_to_merchant_with_http_post: None,
|
||||
routing_algorithm: None,
|
||||
intent_fulfillment_time: None,
|
||||
frm_routing_algorithm: None,
|
||||
payout_routing_algorithm: None,
|
||||
default_profile: None,
|
||||
payment_link_config: None,
|
||||
};
|
||||
|
||||
state
|
||||
.store
|
||||
.update_specific_fields_in_merchant(merchant_id, merchant_account_update, &key_store)
|
||||
.await
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("error updating the merchant account when creating payment connector")?;
|
||||
|
||||
let merchant_connector_account = domain::MerchantConnectorAccount {
|
||||
merchant_id: merchant_id.to_string(),
|
||||
connector_type: req.connector_type,
|
||||
@ -852,7 +892,7 @@ pub async fn create_payment_connector(
|
||||
connector_label: Some(connector_label),
|
||||
business_country: req.business_country,
|
||||
business_label: req.business_label.clone(),
|
||||
business_sub_label: req.business_sub_label,
|
||||
business_sub_label: req.business_sub_label.clone(),
|
||||
created_at: common_utils::date_time::now(),
|
||||
modified_at: common_utils::date_time::now(),
|
||||
id: None,
|
||||
@ -873,6 +913,9 @@ pub async fn create_payment_connector(
|
||||
pm_auth_config: req.pm_auth_config.clone(),
|
||||
};
|
||||
|
||||
let mut default_routing_config =
|
||||
routing_helpers::get_merchant_default_config(&*state.store, merchant_id).await?;
|
||||
|
||||
let mca = state
|
||||
.store
|
||||
.insert_merchant_connector_account(merchant_connector_account, &key_store)
|
||||
@ -884,6 +927,28 @@ pub async fn create_payment_connector(
|
||||
},
|
||||
)?;
|
||||
|
||||
if let Some(routable_connector_val) = routable_connector {
|
||||
let choice = routing_types::RoutableConnectorChoice {
|
||||
#[cfg(feature = "backwards_compatibility")]
|
||||
choice_kind: routing_types::RoutableChoiceKind::FullStruct,
|
||||
connector: routable_connector_val,
|
||||
#[cfg(feature = "connector_choice_mca_id")]
|
||||
merchant_connector_id: Some(mca.merchant_connector_id.clone()),
|
||||
#[cfg(not(feature = "connector_choice_mca_id"))]
|
||||
sub_label: req.business_sub_label,
|
||||
};
|
||||
|
||||
if !default_routing_config.contains(&choice) {
|
||||
default_routing_config.push(choice);
|
||||
routing_helpers::update_merchant_default_config(
|
||||
&*state.store,
|
||||
merchant_id,
|
||||
default_routing_config,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
|
||||
metrics::MCA_CREATE.add(
|
||||
&metrics::CONTEXT,
|
||||
1,
|
||||
@ -1248,7 +1313,7 @@ pub async fn create_business_profile(
|
||||
.to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?;
|
||||
|
||||
if let Some(ref routing_algorithm) = request.routing_algorithm {
|
||||
let _: api::RoutingAlgorithm = routing_algorithm
|
||||
let _: api_models::routing::RoutingAlgorithm = routing_algorithm
|
||||
.clone()
|
||||
.parse_value("RoutingAlgorithm")
|
||||
.change_context(errors::ApiErrorResponse::InvalidDataValue {
|
||||
@ -1360,7 +1425,7 @@ pub async fn update_business_profile(
|
||||
.transpose()?;
|
||||
|
||||
if let Some(ref routing_algorithm) = request.routing_algorithm {
|
||||
let _: api::RoutingAlgorithm = routing_algorithm
|
||||
let _: api_models::routing::RoutingAlgorithm = routing_algorithm
|
||||
.clone()
|
||||
.parse_value("RoutingAlgorithm")
|
||||
.change_context(errors::ApiErrorResponse::InvalidDataValue {
|
||||
|
||||
Reference in New Issue
Block a user