diff --git a/crates/api_models/src/admin.rs b/crates/api_models/src/admin.rs index f2ef1a1784..4bfa64671d 100644 --- a/crates/api_models/src/admin.rs +++ b/crates/api_models/src/admin.rs @@ -372,6 +372,17 @@ pub struct MerchantConnectorCreate { /// You can specify up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. Metadata is useful for storing additional, structured information on an object. #[schema(value_type = Option,max_length = 255,example = json!({ "city": "NY", "unit": "245" }))] pub metadata: Option, + /// contains the frm configs for the merchant connector + #[schema(example = json!([ + { + "frm_enabled_pms" : ["card"], + "frm_enabled_pm_types" : ["credit"], + "frm_enabled_gateways" : ["stripe"], + "frm_action": "cancel_txn", + "frm_preferred_flow_type" : "pre" + } + ]))] + pub frm_configs: Option, /// Business Country of the connector #[schema(example = "US")] @@ -465,6 +476,18 @@ pub struct MerchantConnectorResponse { /// Business Sub label of the merchant #[schema(example = "chase")] pub business_sub_label: Option, + + /// contains the frm configs for the merchant connector + #[schema(example = json!([ + { + "frm_enabled_pms" : ["card"], + "frm_enabled_pm_types" : ["credit"], + "frm_enabled_gateways" : ["stripe"], + "frm_action": "cancel_txn", + "frm_preferred_flow_type" : "pre" + } + ]))] + pub frm_configs: Option, } /// Create a new Merchant Connector for the merchant account. The connector could be a payment processor / facilitator / acquirer or specialized services like Fraud / Accounting etc." @@ -522,8 +545,30 @@ pub struct MerchantConnectorUpdate { /// You can specify up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. Metadata is useful for storing additional, structured information on an object. #[schema(value_type = Option,max_length = 255,example = json!({ "city": "NY", "unit": "245" }))] pub metadata: Option, + + /// contains the frm configs for the merchant connector + #[schema(example = json!([ + { + "frm_enabled_pms" : ["card"], + "frm_enabled_pm_types" : ["credit"], + "frm_enabled_gateways" : ["stripe"], + "frm_action": "cancel_txn", + "frm_preferred_flow_type" : "pre" + } + ]))] + pub frm_configs: Option, } +///Details of FrmConfigs are mentioned here... it should be passed in payment connector create api call, and stored in merchant_connector_table +#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)] +#[serde(deny_unknown_fields)] +pub struct FrmConfigs { + pub frm_enabled_pms: Option>, + pub frm_enabled_pm_types: Option>, + pub frm_enabled_gateways: Option>, + pub frm_action: api_enums::FrmAction, //What should be the action if FRM declines the txn (autorefund/cancel txn/manual review) + pub frm_preferred_flow_type: api_enums::FrmPreferredFlowTypes, +} /// Details of all the payment methods enabled for the connector for the given merchant account #[derive(Debug, Clone, Serialize, Deserialize, ToSchema)] #[serde(deny_unknown_fields)] diff --git a/crates/api_models/src/enums.rs b/crates/api_models/src/enums.rs index ced971d415..6c6bf24de2 100644 --- a/crates/api_models/src/enums.rs +++ b/crates/api_models/src/enums.rs @@ -842,6 +842,40 @@ pub enum DisputeStatus { DisputeLost, } +#[derive( + Clone, + Debug, + serde::Deserialize, + serde::Serialize, + strum::Display, + strum::EnumString, + frunk::LabelledGeneric, + ToSchema, +)] +#[strum(serialize_all = "snake_case")] +#[serde(rename_all = "snake_case")] +pub enum FrmAction { + CancelTxn, + AutoRefund, + ManualReview, +} + +#[derive( + Clone, + Debug, + serde::Deserialize, + serde::Serialize, + strum::Display, + strum::EnumString, + frunk::LabelledGeneric, + ToSchema, +)] +#[strum(serialize_all = "snake_case")] +#[serde(rename_all = "snake_case")] +pub enum FrmPreferredFlowTypes { + Pre, + Post, +} #[derive(Debug, Eq, PartialEq, Clone, serde::Serialize, serde::Deserialize)] pub struct UnresolvedResponseReason { pub code: String, diff --git a/crates/router/src/core/admin.rs b/crates/router/src/core/admin.rs index 1e4859ddb8..21d55b6237 100644 --- a/crates/router/src/core/admin.rs +++ b/crates/router/src/core/admin.rs @@ -1,6 +1,7 @@ use api_models::admin::PrimaryBusinessDetails; use common_utils::ext_traits::ValueExt; use error_stack::{report, FutureExt, IntoReport, ResultExt}; +use masking::Secret; //PeekInterface use storage_models::{enums, merchant_account}; use uuid::Uuid; @@ -401,7 +402,15 @@ pub async fn create_payment_connector( field_name: "connector_account_details".to_string(), expected_format: "auth_type and api_key".to_string(), })?; - + let frm_configs = match req.frm_configs { + Some(frm_value) => { + let configs_for_frm_value: serde_json::Value = + utils::Encode::::encode_to_value(&frm_value) + .change_context(errors::ApiErrorResponse::ConfigNotFound)?; + Some(Secret::new(configs_for_frm_value)) + } + None => None, + }; let merchant_connector_account = storage::MerchantConnectorAccountNew { merchant_id: Some(merchant_id.to_string()), connector_type: Some(req.connector_type.foreign_into()), @@ -412,6 +421,7 @@ pub async fn create_payment_connector( test_mode: req.test_mode, disabled: req.disabled, metadata: req.metadata, + frm_configs, connector_label: connector_label.clone(), business_country, business_label, @@ -516,7 +526,15 @@ pub async fn update_payment_connector( }) .collect::>() }); - + let frm_configs = match req.frm_configs.as_ref() { + Some(frm_value) => { + let configs_for_frm_value: serde_json::Value = + utils::Encode::::encode_to_value(&frm_value) + .change_context(errors::ApiErrorResponse::ConfigNotFound)?; + Some(Secret::new(configs_for_frm_value)) + } + None => None, + }; let payment_connector = storage::MerchantConnectorAccountUpdate::Update { merchant_id: Some(merchant_id.to_string()), connector_type: Some(req.connector_type.foreign_into()), @@ -526,6 +544,7 @@ pub async fn update_payment_connector( test_mode: req.test_mode, disabled: req.disabled, metadata: req.metadata, + frm_configs, }; let updated_mca = db diff --git a/crates/router/src/core/payments/flows/authorize_flow.rs b/crates/router/src/core/payments/flows/authorize_flow.rs index 3a21420daf..6d3de0212b 100644 --- a/crates/router/src/core/payments/flows/authorize_flow.rs +++ b/crates/router/src/core/payments/flows/authorize_flow.rs @@ -50,7 +50,6 @@ impl .await } } - #[async_trait] impl Feature for types::PaymentsAuthorizeRouterData { async fn decide_flows<'a>( diff --git a/crates/router/src/db/merchant_connector_account.rs b/crates/router/src/db/merchant_connector_account.rs index 363a48681b..63413efe5e 100644 --- a/crates/router/src/db/merchant_connector_account.rs +++ b/crates/router/src/db/merchant_connector_account.rs @@ -287,6 +287,7 @@ impl MerchantConnectorAccountInterface for MockDb { merchant_connector_id: t.merchant_connector_id, payment_methods_enabled: t.payment_methods_enabled, metadata: t.metadata, + frm_configs: t.frm_configs, connector_type: t .connector_type .unwrap_or(crate::types::storage::enums::ConnectorType::FinOperations), diff --git a/crates/router/src/types/transformers.rs b/crates/router/src/types/transformers.rs index 92f0f8f2d8..2b7b393783 100644 --- a/crates/router/src/types/transformers.rs +++ b/crates/router/src/types/transformers.rs @@ -1,7 +1,7 @@ use api_models::enums as api_enums; use common_utils::ext_traits::ValueExt; use error_stack::ResultExt; -use masking::Secret; +use masking::{PeekInterface, Secret}; use storage_models::enums as storage_enums; use crate::{ @@ -535,7 +535,20 @@ impl ForeignTryFrom None, }; - + let frm_configs = match item.frm_configs { + Some(frm_value) => { + let configs_for_frm : api_models::admin::FrmConfigs = frm_value + .peek() + .clone() + .parse_value("FrmConfigs") + .change_context(errors::ApiErrorResponse::InvalidDataFormat { + field_name: "frm_configs".to_string(), + expected_format: "\"frm_configs\" : { \"frm_enabled_pms\" : [\"card\"], \"frm_enabled_pm_types\" : [\"credit\"], \"frm_enabled_gateways\" : [\"stripe\"], \"frm_action\": \"cancel_txn\", \"frm_preferred_flow_type\" : \"pre\" }".to_string(), + })?; + Some(configs_for_frm) + } + None => None, + }; Ok(Self { connector_type: item.connector_type.foreign_into(), connector_name: item.connector_name, @@ -549,6 +562,7 @@ impl ForeignTryFrom>, pub connector_type: storage_enums::ConnectorType, pub metadata: Option, + pub frm_configs: Option>, //Option pub connector_label: String, pub business_country: storage_enums::CountryCode, pub business_label: String, @@ -46,6 +47,7 @@ pub struct MerchantConnectorAccountNew { pub merchant_connector_id: String, pub payment_methods_enabled: Option>, pub metadata: Option, + pub frm_configs: Option>, pub connector_label: String, pub business_country: storage_enums::CountryCode, pub business_label: String, @@ -63,6 +65,7 @@ pub enum MerchantConnectorAccountUpdate { merchant_connector_id: Option, payment_methods_enabled: Option>, metadata: Option, + frm_configs: Option>, }, } #[derive(Clone, Debug, Default, AsChangeset, router_derive::DebugAsDisplay)] @@ -76,6 +79,7 @@ pub struct MerchantConnectorAccountUpdateInternal { merchant_connector_id: Option, payment_methods_enabled: Option>, metadata: Option, + frm_configs: Option>, } impl From for MerchantConnectorAccountUpdateInternal { @@ -90,6 +94,7 @@ impl From for MerchantConnectorAccountUpdateInte merchant_connector_id, payment_methods_enabled, metadata, + frm_configs, } => Self { merchant_id, connector_type, @@ -99,6 +104,7 @@ impl From for MerchantConnectorAccountUpdateInte merchant_connector_id, payment_methods_enabled, metadata, + frm_configs, }, } } diff --git a/crates/storage_models/src/schema.rs b/crates/storage_models/src/schema.rs index 4932246edc..118464b87e 100644 --- a/crates/storage_models/src/schema.rs +++ b/crates/storage_models/src/schema.rs @@ -243,6 +243,7 @@ diesel::table! { payment_methods_enabled -> Nullable>>, connector_type -> ConnectorType, metadata -> Nullable, + frm_configs -> Nullable, connector_label -> Varchar, business_country -> CountryCode, business_label -> Varchar, diff --git a/migrations/2023-04-03-082335_update_mca_frm_configs/down.sql b/migrations/2023-04-03-082335_update_mca_frm_configs/down.sql new file mode 100644 index 0000000000..411ea83d84 --- /dev/null +++ b/migrations/2023-04-03-082335_update_mca_frm_configs/down.sql @@ -0,0 +1 @@ +ALTER TABLE "merchant_connector_account" DROP COLUMN frm_configs; \ No newline at end of file diff --git a/migrations/2023-04-03-082335_update_mca_frm_configs/up.sql b/migrations/2023-04-03-082335_update_mca_frm_configs/up.sql new file mode 100644 index 0000000000..72d5e7e237 --- /dev/null +++ b/migrations/2023-04-03-082335_update_mca_frm_configs/up.sql @@ -0,0 +1 @@ +ALTER TABLE "merchant_connector_account" ADD COLUMN frm_configs jsonb; \ No newline at end of file