mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-29 00:49:42 +08:00
feat(router): add generic merchant static routing config (#362)
This commit is contained in:
@ -32,12 +32,8 @@ pub struct CreateMerchantAccount {
|
||||
/// Webhook related details
|
||||
pub webhook_details: Option<WebhookDetails>,
|
||||
|
||||
/// The routing algorithm to be used to process the incoming request from merchant to outgoing payment processor or payment method. The default is 'Custom'
|
||||
#[schema(value_type = Option<RoutingAlgorithm>, max_length = 255, example = "custom")]
|
||||
pub routing_algorithm: Option<api_enums::RoutingAlgorithm>,
|
||||
|
||||
/// The custom routing rules to be used for various payment methods and conditions
|
||||
pub custom_routing_rules: Option<Vec<CustomRoutingRules>>,
|
||||
/// The routing algorithm to be used for routing payments to desired connectors
|
||||
pub routing_algorithm: Option<serde_json::Value>,
|
||||
|
||||
/// A boolean value to indicate if the merchant is a sub-merchant under a master or a parent merchant. By default, its value is false.
|
||||
#[schema(default = false, example = false)]
|
||||
@ -113,6 +109,12 @@ pub struct MerchantDetails {
|
||||
pub address: Option<AddressDetails>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[serde(tag = "type", content = "data", rename_all = "snake_case")]
|
||||
pub enum RoutingAlgorithm {
|
||||
Single(api_enums::RoutableConnectors),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, ToSchema, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct WebhookDetails {
|
||||
@ -145,70 +147,6 @@ pub struct WebhookDetails {
|
||||
pub payment_failed_enabled: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Default, Clone, Debug, Deserialize, ToSchema, Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct CustomRoutingRules {
|
||||
/// The List of payment methods to include for this routing rule
|
||||
#[schema(value_type = Option<Vec<PaymentMethodType>>, example = json!(["card", "upi"]))]
|
||||
pub payment_methods_incl: Option<Vec<api_enums::PaymentMethodType>>,
|
||||
|
||||
/// The List of payment methods to exclude for this routing rule. If there is conflict between include and exclude lists, include list overrides the exclude list.
|
||||
#[schema(value_type = Option<Vec<PaymentMethodType>>, example = json!(["card", "upi"]))]
|
||||
pub payment_methods_excl: Option<Vec<api_enums::PaymentMethodType>>,
|
||||
|
||||
/// The List of payment method types to include for this routing rule
|
||||
#[schema(value_type = Option<Vec<PaymentMethodSubType>>, example = json!(["credit_card", "debit_card"]))]
|
||||
pub payment_method_types_incl: Option<Vec<api_enums::PaymentMethodSubType>>,
|
||||
|
||||
/// The List of payment method types to exclude for this routing rule. If there is conflict between include and exclude lists, include list overrides the exclude list.
|
||||
#[schema(value_type = Option<Vec<PaymentMethodSubType>>, example = json!(["credit_card", "debit_card"]))]
|
||||
pub payment_method_types_excl: Option<Vec<api_enums::PaymentMethodSubType>>,
|
||||
|
||||
/// The List of payment method issuers to include for this routing rule
|
||||
#[schema(example = json!(["Citibank", "JPMorgan"]))]
|
||||
pub payment_method_issuers_incl: Option<Vec<String>>,
|
||||
|
||||
/// The List of payment method issuers to exclude for this routing rule. If there is conflict between include and exclude lists, include list overrides the exclude list.
|
||||
#[schema(example = json!(["Citibank", "JPMorgan"]))]
|
||||
pub payment_method_issuers_excl: Option<Vec<String>>,
|
||||
|
||||
/// The List of countries to include for this routing rule
|
||||
#[schema(example = json!(["US", "UK"]))]
|
||||
pub countries_incl: Option<Vec<String>>,
|
||||
|
||||
/// The List of countries to exclude for this routing rule. If there is conflict between include and exclude lists, include list overrides the exclude list.
|
||||
#[schema(example = json!(["US", "UK"]))]
|
||||
pub countries_excl: Option<Vec<String>>,
|
||||
|
||||
/// The List of currencies to include for this routing rule
|
||||
#[schema(value_type = Option<Vec<Currency>>, example = json!(["EUR","USD"]))]
|
||||
pub currencies_incl: Option<Vec<api_enums::Currency>>,
|
||||
|
||||
/// The List of currencies to exclude for this routing rule. If there is conflict between include and exclude lists, include list overrides the exclude list.
|
||||
#[schema(value_type = Option<Vec<Currency>>, example = json!(["EUR","USD"]))]
|
||||
pub currencies_excl: Option<Vec<api_enums::Currency>>,
|
||||
|
||||
/// List of Metadata Filter keys to apply for the Routing Rule. The filters are presented as 2 arrays of keys and value. This property contains all the keys.
|
||||
#[schema(example = json!(["platform","Category"]))]
|
||||
pub metadata_filters_keys: Option<Vec<String>>,
|
||||
|
||||
/// List of Metadata Filters to apply for the Routing Rule. The filters are presented as 2 arrays of keys and value. This property contains all the values.
|
||||
#[schema(example = json!(["android", "Category_Electronics"]))]
|
||||
pub metadata_filters_values: Option<Vec<String>>,
|
||||
|
||||
/// The pecking order of payment connectors (or processors) to be used for routing. The first connector in the array will be attempted for routing. If it fails, the second connector will be used till the list is exhausted.
|
||||
#[schema(example = json!([ "stripe", "adyen", "brain_tree"]))]
|
||||
pub connectors_pecking_order: Option<Vec<String>>,
|
||||
|
||||
///An Array of Connectors (as Keys) with the associated percentage of traffic to be routed through the given connector (Expressed as an array of values)
|
||||
#[schema(example = json!([ "stripe", "adyen", "brain_tree"]))]
|
||||
pub connectors_traffic_weightage_key: Option<Vec<String>>,
|
||||
|
||||
/// An Array of Weightage (expressed in percentage) that needs to be associated with the respective connectors (Expressed as an array of keys)
|
||||
#[schema(example = json!([ 50, 30, 20 ]))]
|
||||
pub connectors_traffic_weightage_value: Option<Vec<i32>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct DeleteResponse {
|
||||
pub merchant_id: String,
|
||||
|
||||
@ -527,6 +527,37 @@ pub enum Connector {
|
||||
Worldpay,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Clone,
|
||||
Copy,
|
||||
Debug,
|
||||
Eq,
|
||||
PartialEq,
|
||||
serde::Serialize,
|
||||
serde::Deserialize,
|
||||
strum::Display,
|
||||
strum::EnumString,
|
||||
frunk::LabelledGeneric,
|
||||
)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum RoutableConnectors {
|
||||
Aci,
|
||||
Adyen,
|
||||
Authorizedotnet,
|
||||
Braintree,
|
||||
Checkout,
|
||||
Cybersource,
|
||||
Fiserv,
|
||||
Globalpay,
|
||||
Klarna,
|
||||
Payu,
|
||||
Shift4,
|
||||
Stripe,
|
||||
Worldline,
|
||||
Worldpay,
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum SupportedWallets {
|
||||
|
||||
@ -44,11 +44,16 @@ pub async fn create_merchant_account(
|
||||
.change_context(errors::ApiErrorResponse::InvalidDataValue {
|
||||
field_name: "webhook details",
|
||||
})?;
|
||||
let custom_routing_rules =
|
||||
utils::Encode::<api::CustomRoutingRules>::encode_to_value(&req.custom_routing_rules)
|
||||
|
||||
if let Some(ref routing_algorithm) = req.routing_algorithm {
|
||||
let _: api::RoutingAlgorithm = routing_algorithm
|
||||
.clone()
|
||||
.parse_value("RoutingAlgorithm")
|
||||
.change_context(errors::ApiErrorResponse::InvalidDataValue {
|
||||
field_name: "custom routing rules",
|
||||
})?;
|
||||
field_name: "routing_algorithm",
|
||||
})
|
||||
.attach_printable("Invalid routing algorithm given")?;
|
||||
}
|
||||
|
||||
let merchant_account = storage::MerchantAccountNew {
|
||||
merchant_id: req.merchant_id,
|
||||
@ -57,8 +62,7 @@ pub async fn create_merchant_account(
|
||||
merchant_details: Some(merchant_details),
|
||||
return_url: req.return_url,
|
||||
webhook_details: Some(webhook_details),
|
||||
routing_algorithm: req.routing_algorithm.map(ForeignInto::foreign_into),
|
||||
custom_routing_rules: Some(custom_routing_rules),
|
||||
routing_algorithm: req.routing_algorithm,
|
||||
sub_merchants_enabled: req.sub_merchants_enabled,
|
||||
parent_merchant_id: get_parent_merchant(
|
||||
db,
|
||||
@ -99,13 +103,6 @@ pub async fn get_merchant_account(
|
||||
.webhook_details
|
||||
.parse_value("WebhookDetails")
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)?;
|
||||
let vec_val = merchant_account
|
||||
.custom_routing_rules
|
||||
.parse_value("CustomRoutingRulesVector")
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)?;
|
||||
let custom_routing_rules = serde_json::Value::Array(vec_val)
|
||||
.parse_value("CustomRoutingRules")
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)?;
|
||||
let response = api::MerchantAccountResponse {
|
||||
merchant_id: req.merchant_id,
|
||||
merchant_name: merchant_account.merchant_name,
|
||||
@ -113,10 +110,7 @@ pub async fn get_merchant_account(
|
||||
merchant_details,
|
||||
return_url: merchant_account.return_url,
|
||||
webhook_details,
|
||||
routing_algorithm: merchant_account
|
||||
.routing_algorithm
|
||||
.map(ForeignInto::foreign_into),
|
||||
custom_routing_rules,
|
||||
routing_algorithm: merchant_account.routing_algorithm,
|
||||
sub_merchants_enabled: merchant_account.sub_merchants_enabled,
|
||||
parent_merchant_id: merchant_account.parent_merchant_id,
|
||||
enable_payment_response_hash: Some(merchant_account.enable_payment_response_hash),
|
||||
@ -142,6 +136,7 @@ pub async fn merchant_account_update(
|
||||
.map_err(|error| {
|
||||
error.to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)
|
||||
})?;
|
||||
|
||||
if &req.merchant_id != merchant_id {
|
||||
Err(report!(errors::ValidationError::IncorrectValueProvided {
|
||||
field_name: "parent_merchant_id"
|
||||
@ -153,6 +148,17 @@ pub async fn merchant_account_update(
|
||||
field_name: "parent_merchant_id",
|
||||
}))?;
|
||||
}
|
||||
|
||||
if let Some(ref routing_algorithm) = req.routing_algorithm {
|
||||
let _: api::RoutingAlgorithm = routing_algorithm
|
||||
.clone()
|
||||
.parse_value("RoutingAlgorithm")
|
||||
.change_context(errors::ApiErrorResponse::InvalidDataValue {
|
||||
field_name: "routing_algorithm",
|
||||
})
|
||||
.attach_printable("Invalid routing algorithm given")?;
|
||||
}
|
||||
|
||||
let mut response = req.clone();
|
||||
let updated_merchant_account = storage::MerchantAccountUpdate::Update {
|
||||
merchant_id: merchant_id.to_string(),
|
||||
@ -181,18 +187,7 @@ pub async fn merchant_account_update(
|
||||
},
|
||||
routing_algorithm: req
|
||||
.routing_algorithm
|
||||
.map(ForeignInto::foreign_into)
|
||||
.or(merchant_account.routing_algorithm),
|
||||
custom_routing_rules: if req.custom_routing_rules.is_some() {
|
||||
Some(
|
||||
utils::Encode::<api::CustomRoutingRules>::encode_to_value(
|
||||
&req.custom_routing_rules,
|
||||
)
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)?,
|
||||
)
|
||||
} else {
|
||||
merchant_account.custom_routing_rules.to_owned()
|
||||
},
|
||||
.or_else(|| merchant_account.routing_algorithm.clone()),
|
||||
sub_merchants_enabled: req
|
||||
.sub_merchants_enabled
|
||||
.or(merchant_account.sub_merchants_enabled),
|
||||
|
||||
@ -102,10 +102,13 @@ where
|
||||
.get_connector(&merchant_account, state, &req)
|
||||
.await?;
|
||||
|
||||
if let api::ConnectorCallType::Single(ref connector) = connector_details {
|
||||
payment_data.payment_attempt.connector =
|
||||
Some(connector.connector_name.to_owned().to_string());
|
||||
}
|
||||
let connector_details = route_connector(
|
||||
state,
|
||||
&merchant_account,
|
||||
&mut payment_data,
|
||||
connector_details,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let (operation, mut payment_data) = operation
|
||||
.to_update_tracker()?
|
||||
@ -149,6 +152,34 @@ where
|
||||
)
|
||||
.await?
|
||||
}
|
||||
api::ConnectorCallType::Routing => {
|
||||
let connector = payment_data
|
||||
.payment_attempt
|
||||
.connector
|
||||
.clone()
|
||||
.get_required_value("connector")
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("No connector selected for routing")?;
|
||||
|
||||
let connector_data = api::ConnectorData::get_connector_by_name(
|
||||
&state.conf.connectors,
|
||||
&connector,
|
||||
api::GetToken::Connector,
|
||||
)
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)?;
|
||||
|
||||
call_connector_service(
|
||||
state,
|
||||
&merchant_account,
|
||||
&validate_result.payment_id,
|
||||
connector_data,
|
||||
&operation,
|
||||
payment_data,
|
||||
&customer,
|
||||
call_connector_action,
|
||||
)
|
||||
.await?
|
||||
}
|
||||
};
|
||||
vault::Vault::delete_locker_payment_method_by_lookup_key(state, &payment_data.token).await
|
||||
}
|
||||
@ -605,3 +636,48 @@ pub async fn add_process_sync_task(
|
||||
db.insert_process(process_tracker_entry).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn route_connector<F>(
|
||||
state: &AppState,
|
||||
merchant_account: &storage::MerchantAccount,
|
||||
payment_data: &mut PaymentData<F>,
|
||||
connector_call_type: api::ConnectorCallType,
|
||||
) -> RouterResult<api::ConnectorCallType>
|
||||
where
|
||||
F: Send + Clone,
|
||||
{
|
||||
match connector_call_type {
|
||||
api::ConnectorCallType::Single(connector) => {
|
||||
payment_data.payment_attempt.connector = Some(connector.connector_name.to_string());
|
||||
|
||||
Ok(api::ConnectorCallType::Single(connector))
|
||||
}
|
||||
|
||||
api::ConnectorCallType::Routing => {
|
||||
let routing_algorithm: api::RoutingAlgorithm = merchant_account
|
||||
.routing_algorithm
|
||||
.clone()
|
||||
.parse_value("RoutingAlgorithm")
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Could not decode merchant routing rules")?;
|
||||
|
||||
let connector_name = match routing_algorithm {
|
||||
api::RoutingAlgorithm::Single(conn) => conn.to_string(),
|
||||
};
|
||||
|
||||
let connector_data = api::ConnectorData::get_connector_by_name(
|
||||
&state.conf.connectors,
|
||||
&connector_name,
|
||||
api::GetToken::Connector,
|
||||
)
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Routing algorithm gave invalid connector")?;
|
||||
|
||||
payment_data.payment_attempt.connector = Some(connector_name);
|
||||
|
||||
Ok(api::ConnectorCallType::Single(connector_data))
|
||||
}
|
||||
|
||||
call_type @ api::ConnectorCallType::Multiple(_) => Ok(call_type),
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,7 +23,6 @@ use crate::{
|
||||
scheduler::{metrics, workflows::payment_sync},
|
||||
services,
|
||||
types::{
|
||||
self,
|
||||
api::{self, enums as api_enums, CustomerAcceptanceExt, MandateValidationFieldsExt},
|
||||
storage::{self, enums as storage_enums, ephemeral_key},
|
||||
transformers::ForeignInto,
|
||||
@ -594,7 +593,6 @@ pub async fn get_customer_from_details(
|
||||
}
|
||||
|
||||
pub async fn get_connector_default(
|
||||
merchant_account: &storage::MerchantAccount,
|
||||
state: &AppState,
|
||||
request_connector: Option<api_enums::Connector>,
|
||||
) -> CustomResult<api::ConnectorCallType, errors::ApiErrorResponse> {
|
||||
@ -607,41 +605,7 @@ pub async fn get_connector_default(
|
||||
)?;
|
||||
Ok(api::ConnectorCallType::Single(connector_data))
|
||||
} else {
|
||||
let vec_val: Vec<serde_json::Value> = merchant_account
|
||||
.custom_routing_rules
|
||||
.clone()
|
||||
.parse_value("CustomRoutingRulesVec")
|
||||
.change_context(errors::ConnectorError::RoutingRulesParsingError)
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)?;
|
||||
let custom_routing_rules: api::CustomRoutingRules = vec_val
|
||||
.into_iter()
|
||||
.next()
|
||||
.parse_value("CustomRoutingRules")
|
||||
.change_context(errors::ConnectorError::RoutingRulesParsingError)
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)?;
|
||||
let connector_names = custom_routing_rules
|
||||
.connectors_pecking_order
|
||||
.unwrap_or_else(|| vec!["stripe".to_string()]);
|
||||
|
||||
//use routing rules if configured by merchant else query MCA as per PM
|
||||
let connector_list: types::ConnectorsList = types::ConnectorsList {
|
||||
connectors: connector_names,
|
||||
};
|
||||
|
||||
let connector_name = connector_list
|
||||
.connectors
|
||||
.first()
|
||||
.get_required_value("connectors")
|
||||
.change_context(errors::ConnectorError::FailedToObtainPreferredConnector)
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)?
|
||||
.as_str();
|
||||
|
||||
let connector_data = api::ConnectorData::get_connector_by_name(
|
||||
connectors,
|
||||
connector_name,
|
||||
api::GetToken::Connector,
|
||||
)?;
|
||||
Ok(api::ConnectorCallType::Single(connector_data))
|
||||
Ok(api::ConnectorCallType::Routing)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -189,11 +189,11 @@ where
|
||||
|
||||
async fn get_connector<'a>(
|
||||
&'a self,
|
||||
merchant_account: &storage::MerchantAccount,
|
||||
_merchant_account: &storage::MerchantAccount,
|
||||
state: &AppState,
|
||||
_request: &api::PaymentsRetrieveRequest,
|
||||
) -> CustomResult<api::ConnectorCallType, errors::ApiErrorResponse> {
|
||||
helpers::get_connector_default(merchant_account, state, None).await
|
||||
helpers::get_connector_default(state, None).await
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
@ -255,11 +255,11 @@ where
|
||||
|
||||
async fn get_connector<'a>(
|
||||
&'a self,
|
||||
merchant_account: &storage::MerchantAccount,
|
||||
_merchant_account: &storage::MerchantAccount,
|
||||
state: &AppState,
|
||||
_request: &api::PaymentsCaptureRequest,
|
||||
) -> CustomResult<api::ConnectorCallType, errors::ApiErrorResponse> {
|
||||
helpers::get_connector_default(merchant_account, state, None).await
|
||||
helpers::get_connector_default(state, None).await
|
||||
}
|
||||
}
|
||||
|
||||
@ -309,10 +309,10 @@ where
|
||||
|
||||
async fn get_connector<'a>(
|
||||
&'a self,
|
||||
merchant_account: &storage::MerchantAccount,
|
||||
_merchant_account: &storage::MerchantAccount,
|
||||
state: &AppState,
|
||||
_request: &api::PaymentsCancelRequest,
|
||||
) -> CustomResult<api::ConnectorCallType, errors::ApiErrorResponse> {
|
||||
helpers::get_connector_default(merchant_account, state, None).await
|
||||
helpers::get_connector_default(state, None).await
|
||||
}
|
||||
}
|
||||
|
||||
@ -250,11 +250,11 @@ impl<F: Clone + Send> Domain<F, api::PaymentsRequest> for PaymentConfirm {
|
||||
|
||||
async fn get_connector<'a>(
|
||||
&'a self,
|
||||
merchant_account: &storage::MerchantAccount,
|
||||
_merchant_account: &storage::MerchantAccount,
|
||||
state: &AppState,
|
||||
request: &api::PaymentsRequest,
|
||||
) -> CustomResult<api::ConnectorCallType, errors::ApiErrorResponse> {
|
||||
helpers::get_connector_default(merchant_account, state, request.connector).await
|
||||
helpers::get_connector_default(state, request.connector).await
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -254,11 +254,11 @@ impl<F: Clone + Send> Domain<F, api::PaymentsRequest> for PaymentCreate {
|
||||
|
||||
async fn get_connector<'a>(
|
||||
&'a self,
|
||||
merchant_account: &storage::MerchantAccount,
|
||||
_merchant_account: &storage::MerchantAccount,
|
||||
state: &AppState,
|
||||
request: &api::PaymentsRequest,
|
||||
) -> CustomResult<api::ConnectorCallType, errors::ApiErrorResponse> {
|
||||
helpers::get_connector_default(merchant_account, state, request.connector).await
|
||||
helpers::get_connector_default(state, request.connector).await
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -250,11 +250,11 @@ where
|
||||
|
||||
async fn get_connector<'a>(
|
||||
&'a self,
|
||||
merchant_account: &storage::MerchantAccount,
|
||||
_merchant_account: &storage::MerchantAccount,
|
||||
state: &AppState,
|
||||
_request: &api::VerifyRequest,
|
||||
) -> CustomResult<api::ConnectorCallType, errors::ApiErrorResponse> {
|
||||
helpers::get_connector_default(merchant_account, state, None).await
|
||||
helpers::get_connector_default(state, None).await
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -246,10 +246,10 @@ where
|
||||
|
||||
async fn get_connector<'a>(
|
||||
&'a self,
|
||||
merchant_account: &storage::MerchantAccount,
|
||||
_merchant_account: &storage::MerchantAccount,
|
||||
state: &AppState,
|
||||
_request: &api::PaymentsStartRequest,
|
||||
) -> CustomResult<api::ConnectorCallType, errors::ApiErrorResponse> {
|
||||
helpers::get_connector_default(merchant_account, state, None).await
|
||||
helpers::get_connector_default(state, None).await
|
||||
}
|
||||
}
|
||||
|
||||
@ -98,11 +98,11 @@ impl<F: Clone + Send> Domain<F, api::PaymentsRequest> for PaymentStatus {
|
||||
|
||||
async fn get_connector<'a>(
|
||||
&'a self,
|
||||
merchant_account: &storage::MerchantAccount,
|
||||
_merchant_account: &storage::MerchantAccount,
|
||||
state: &AppState,
|
||||
_request: &api::PaymentsRequest,
|
||||
) -> CustomResult<api::ConnectorCallType, errors::ApiErrorResponse> {
|
||||
helpers::get_connector_default(merchant_account, state, None).await
|
||||
helpers::get_connector_default(state, None).await
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -267,11 +267,11 @@ impl<F: Clone + Send> Domain<F, api::PaymentsRequest> for PaymentUpdate {
|
||||
|
||||
async fn get_connector<'a>(
|
||||
&'a self,
|
||||
merchant_account: &storage::MerchantAccount,
|
||||
_merchant_account: &storage::MerchantAccount,
|
||||
state: &AppState,
|
||||
_request: &api::PaymentsRequest,
|
||||
) -> CustomResult<api::ConnectorCallType, errors::ApiErrorResponse> {
|
||||
helpers::get_connector_default(merchant_account, state, None).await
|
||||
helpers::get_connector_default(state, None).await
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -138,7 +138,6 @@ impl MerchantAccountInterface for MockDb {
|
||||
merchant_details: merchant_account.merchant_details,
|
||||
webhook_details: merchant_account.webhook_details,
|
||||
routing_algorithm: merchant_account.routing_algorithm,
|
||||
custom_routing_rules: merchant_account.custom_routing_rules,
|
||||
sub_merchants_enabled: merchant_account.sub_merchants_enabled,
|
||||
parent_merchant_id: merchant_account.parent_merchant_id,
|
||||
publishable_key: merchant_account.publishable_key,
|
||||
|
||||
@ -53,7 +53,6 @@ Never share your secret api keys. Keep them guarded and secure.
|
||||
crate::types::api::refunds::RefundResponse,
|
||||
crate::types::api::refunds::RefundStatus,
|
||||
crate::types::api::admin::CreateMerchantAccount,
|
||||
crate::types::api::admin::CustomRoutingRules,
|
||||
api_models::enums::RoutingAlgorithm,
|
||||
api_models::enums::PaymentMethodType,
|
||||
api_models::enums::PaymentMethodSubType,
|
||||
|
||||
@ -105,8 +105,9 @@ pub struct ConnectorData {
|
||||
}
|
||||
|
||||
pub enum ConnectorCallType {
|
||||
Single(ConnectorData),
|
||||
Routing,
|
||||
Multiple(Vec<ConnectorData>),
|
||||
Single(ConnectorData),
|
||||
}
|
||||
|
||||
impl ConnectorCallType {
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
pub use api_models::admin::{
|
||||
CreateMerchantAccount, CustomRoutingRules, DeleteMcaResponse, DeleteResponse,
|
||||
MerchantConnectorId, MerchantDetails, MerchantId, PaymentConnectorCreate, PaymentMethods,
|
||||
WebhookDetails,
|
||||
CreateMerchantAccount, DeleteMcaResponse, DeleteResponse, MerchantConnectorId, MerchantDetails,
|
||||
MerchantId, PaymentConnectorCreate, PaymentMethods, RoutingAlgorithm, WebhookDetails,
|
||||
};
|
||||
|
||||
//use serde::{Serialize, Deserialize};
|
||||
|
||||
@ -276,12 +276,9 @@ async fn payments_create_core() {
|
||||
|
||||
let state = routes::AppState::with_storage(conf, StorageImpl::PostgresqlTest).await;
|
||||
|
||||
let mut merchant_account = services::authenticate_by_api_key(&*state.store, "MySecretApiKey")
|
||||
let merchant_account = services::authenticate_by_api_key(&*state.store, "MySecretApiKey")
|
||||
.await
|
||||
.unwrap();
|
||||
merchant_account.custom_routing_rules = Some(serde_json::json!([
|
||||
crate::api::CustomRoutingRules::default()
|
||||
]));
|
||||
|
||||
let req = api::PaymentsRequest {
|
||||
payment_id: Some(api::PaymentIdType::PaymentIntentId(
|
||||
@ -436,12 +433,9 @@ async fn payments_create_core_adyen_no_redirect() {
|
||||
let merchant_id = "arunraj".to_string();
|
||||
let payment_id = "pay_mbabizu24mvu3mela5njyhpit10".to_string();
|
||||
|
||||
let mut merchant_account = services::authenticate_by_api_key(&*state.store, "321")
|
||||
let merchant_account = services::authenticate_by_api_key(&*state.store, "321")
|
||||
.await
|
||||
.unwrap();
|
||||
merchant_account.custom_routing_rules = Some(serde_json::json!([
|
||||
crate::api::CustomRoutingRules::default()
|
||||
]));
|
||||
|
||||
let req = api::PaymentsRequest {
|
||||
payment_id: Some(api::PaymentIdType::PaymentIntentId(payment_id.clone())),
|
||||
|
||||
@ -37,12 +37,9 @@ async fn payments_create_core() {
|
||||
|
||||
let state = routes::AppState::with_storage(conf, StorageImpl::PostgresqlTest).await;
|
||||
|
||||
let mut merchant_account = services::authenticate_by_api_key(&*state.store, "MySecretApiKey")
|
||||
let merchant_account = services::authenticate_by_api_key(&*state.store, "MySecretApiKey")
|
||||
.await
|
||||
.unwrap();
|
||||
merchant_account.custom_routing_rules = Some(serde_json::json!([
|
||||
crate::api::CustomRoutingRules::default()
|
||||
]));
|
||||
|
||||
let req = api::PaymentsRequest {
|
||||
payment_id: Some(api::PaymentIdType::PaymentIntentId(
|
||||
|
||||
@ -16,13 +16,12 @@ pub struct MerchantAccount {
|
||||
pub merchant_name: Option<String>,
|
||||
pub merchant_details: Option<serde_json::Value>,
|
||||
pub webhook_details: Option<serde_json::Value>,
|
||||
pub routing_algorithm: Option<storage_enums::RoutingAlgorithm>,
|
||||
pub custom_routing_rules: Option<serde_json::Value>,
|
||||
pub sub_merchants_enabled: Option<bool>,
|
||||
pub parent_merchant_id: Option<String>,
|
||||
pub publishable_key: Option<String>,
|
||||
pub storage_scheme: storage_enums::MerchantStorageScheme,
|
||||
pub locker_id: Option<String>,
|
||||
pub routing_algorithm: Option<serde_json::Value>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Insertable, router_derive::DebugAsDisplay)]
|
||||
@ -34,8 +33,6 @@ pub struct MerchantAccountNew {
|
||||
pub merchant_details: Option<serde_json::Value>,
|
||||
pub return_url: Option<String>,
|
||||
pub webhook_details: Option<serde_json::Value>,
|
||||
pub routing_algorithm: Option<storage_enums::RoutingAlgorithm>,
|
||||
pub custom_routing_rules: Option<serde_json::Value>,
|
||||
pub sub_merchants_enabled: Option<bool>,
|
||||
pub parent_merchant_id: Option<String>,
|
||||
pub enable_payment_response_hash: Option<bool>,
|
||||
@ -43,6 +40,7 @@ pub struct MerchantAccountNew {
|
||||
pub redirect_to_merchant_with_http_post: Option<bool>,
|
||||
pub publishable_key: Option<String>,
|
||||
pub locker_id: Option<String>,
|
||||
pub routing_algorithm: Option<serde_json::Value>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -54,8 +52,6 @@ pub enum MerchantAccountUpdate {
|
||||
merchant_details: Option<serde_json::Value>,
|
||||
return_url: Option<String>,
|
||||
webhook_details: Option<serde_json::Value>,
|
||||
routing_algorithm: Option<storage_enums::RoutingAlgorithm>,
|
||||
custom_routing_rules: Option<serde_json::Value>,
|
||||
sub_merchants_enabled: Option<bool>,
|
||||
parent_merchant_id: Option<String>,
|
||||
enable_payment_response_hash: Option<bool>,
|
||||
@ -63,6 +59,7 @@ pub enum MerchantAccountUpdate {
|
||||
redirect_to_merchant_with_http_post: Option<bool>,
|
||||
publishable_key: Option<String>,
|
||||
locker_id: Option<String>,
|
||||
routing_algorithm: Option<serde_json::Value>,
|
||||
},
|
||||
}
|
||||
|
||||
@ -75,8 +72,6 @@ pub struct MerchantAccountUpdateInternal {
|
||||
merchant_details: Option<serde_json::Value>,
|
||||
return_url: Option<String>,
|
||||
webhook_details: Option<serde_json::Value>,
|
||||
routing_algorithm: Option<storage_enums::RoutingAlgorithm>,
|
||||
custom_routing_rules: Option<serde_json::Value>,
|
||||
sub_merchants_enabled: Option<bool>,
|
||||
parent_merchant_id: Option<String>,
|
||||
enable_payment_response_hash: Option<bool>,
|
||||
@ -84,6 +79,7 @@ pub struct MerchantAccountUpdateInternal {
|
||||
redirect_to_merchant_with_http_post: Option<bool>,
|
||||
publishable_key: Option<String>,
|
||||
locker_id: Option<String>,
|
||||
routing_algorithm: Option<serde_json::Value>,
|
||||
}
|
||||
|
||||
impl From<MerchantAccountUpdate> for MerchantAccountUpdateInternal {
|
||||
@ -97,7 +93,6 @@ impl From<MerchantAccountUpdate> for MerchantAccountUpdateInternal {
|
||||
return_url,
|
||||
webhook_details,
|
||||
routing_algorithm,
|
||||
custom_routing_rules,
|
||||
sub_merchants_enabled,
|
||||
parent_merchant_id,
|
||||
enable_payment_response_hash,
|
||||
@ -113,7 +108,6 @@ impl From<MerchantAccountUpdate> for MerchantAccountUpdateInternal {
|
||||
return_url,
|
||||
webhook_details,
|
||||
routing_algorithm,
|
||||
custom_routing_rules,
|
||||
sub_merchants_enabled,
|
||||
parent_merchant_id,
|
||||
enable_payment_response_hash,
|
||||
|
||||
@ -153,13 +153,12 @@ diesel::table! {
|
||||
merchant_name -> Nullable<Varchar>,
|
||||
merchant_details -> Nullable<Json>,
|
||||
webhook_details -> Nullable<Json>,
|
||||
routing_algorithm -> Nullable<RoutingAlgorithm>,
|
||||
custom_routing_rules -> Nullable<Json>,
|
||||
sub_merchants_enabled -> Nullable<Bool>,
|
||||
parent_merchant_id -> Nullable<Varchar>,
|
||||
publishable_key -> Nullable<Varchar>,
|
||||
storage_scheme -> MerchantStorageScheme,
|
||||
locker_id -> Nullable<Varchar>,
|
||||
routing_algorithm -> Nullable<Json>,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,11 @@
|
||||
-- This file should undo anything in `up.sql`
|
||||
CREATE TYPE "RoutingAlgorithm" AS ENUM (
|
||||
'round_robin',
|
||||
'max_conversion',
|
||||
'min_cost',
|
||||
'custom'
|
||||
);
|
||||
|
||||
ALTER TABLE merchant_account DROP COLUMN routing_algorithm;
|
||||
ALTER TABLE merchant_account ADD COLUMN custom_routing_rules JSON;
|
||||
ALTER TABLE merchant_account ADD COLUMN routing_algorithm "RoutingAlgorithm";
|
||||
@ -0,0 +1,5 @@
|
||||
-- Your SQL goes here
|
||||
ALTER TABLE merchant_account DROP COLUMN routing_algorithm;
|
||||
ALTER TABLE merchant_account DROP COLUMN custom_routing_rules;
|
||||
ALTER TABLE merchant_account ADD COLUMN routing_algorithm JSON;
|
||||
DROP TYPE "RoutingAlgorithm";
|
||||
Reference in New Issue
Block a user