diff --git a/crates/api_models/src/admin.rs b/crates/api_models/src/admin.rs index 9194ac5167..fe32965377 100644 --- a/crates/api_models/src/admin.rs +++ b/crates/api_models/src/admin.rs @@ -69,7 +69,7 @@ pub struct MerchantAccountCreate { /// 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, example = r#"{ "city": "NY", "unit": "245" }"#)] - pub metadata: Option, + pub metadata: Option, /// API key that will be used for server side API access #[schema(example = "AH3423bkjbkjdsfbkj")] @@ -96,6 +96,13 @@ pub struct MerchantAccountCreate { pub organization_id: Option, } +#[derive(Clone, Debug, Deserialize, Serialize, ToSchema)] +pub struct MerchantAccountMetadata { + pub compatible_connector: Option, + + #[serde(flatten)] + pub data: Option, +} #[derive(Clone, Debug, Deserialize, ToSchema)] #[serde(deny_unknown_fields)] pub struct MerchantAccountUpdate { diff --git a/crates/router/src/compatibility/stripe/customers.rs b/crates/router/src/compatibility/stripe/customers.rs index 0f90b1b001..0a2cc27f37 100644 --- a/crates/router/src/compatibility/stripe/customers.rs +++ b/crates/router/src/compatibility/stripe/customers.rs @@ -30,7 +30,7 @@ pub async fn customer_create( let flow = Flow::CustomersCreate; - wrap::compatibility_api_wrap::< + Box::pin(wrap::compatibility_api_wrap::< _, _, _, @@ -48,7 +48,7 @@ pub async fn customer_create( customers::create_customer(&*state.store, auth.merchant_account, auth.key_store, req) }, &auth::ApiKeyAuth, - ) + )) .await } @@ -64,7 +64,7 @@ pub async fn customer_retrieve( let flow = Flow::CustomersRetrieve; - wrap::compatibility_api_wrap::< + Box::pin(wrap::compatibility_api_wrap::< _, _, _, @@ -82,7 +82,7 @@ pub async fn customer_retrieve( customers::retrieve_customer(&*state.store, auth.merchant_account, auth.key_store, req) }, &auth::ApiKeyAuth, - ) + )) .await } @@ -107,7 +107,7 @@ pub async fn customer_update( let flow = Flow::CustomersUpdate; - wrap::compatibility_api_wrap::< + Box::pin(wrap::compatibility_api_wrap::< _, _, _, @@ -125,7 +125,7 @@ pub async fn customer_update( customers::update_customer(&*state.store, auth.merchant_account, req, auth.key_store) }, &auth::ApiKeyAuth, - ) + )) .await } @@ -141,7 +141,7 @@ pub async fn customer_delete( let flow = Flow::CustomersDelete; - wrap::compatibility_api_wrap::< + Box::pin(wrap::compatibility_api_wrap::< _, _, _, @@ -159,7 +159,7 @@ pub async fn customer_delete( customers::delete_customer(state, auth.merchant_account, req, auth.key_store) }, &auth::ApiKeyAuth, - ) + )) .await } @@ -174,7 +174,7 @@ pub async fn list_customer_payment_method_api( let customer_id = path.into_inner(); let flow = Flow::CustomerPaymentMethodsList; - wrap::compatibility_api_wrap::< + Box::pin(wrap::compatibility_api_wrap::< _, _, _, @@ -198,6 +198,6 @@ pub async fn list_customer_payment_method_api( ) }, &auth::ApiKeyAuth, - ) + )) .await } diff --git a/crates/router/src/compatibility/stripe/payment_intents.rs b/crates/router/src/compatibility/stripe/payment_intents.rs index 10e52bfa59..2132717464 100644 --- a/crates/router/src/compatibility/stripe/payment_intents.rs +++ b/crates/router/src/compatibility/stripe/payment_intents.rs @@ -35,7 +35,7 @@ pub async fn payment_intents_create( let flow = Flow::PaymentsCreate; - wrap::compatibility_api_wrap::< + Box::pin(wrap::compatibility_api_wrap::< _, _, _, @@ -61,7 +61,7 @@ pub async fn payment_intents_create( ) }, &auth::ApiKeyAuth, - ) + )) .await } @@ -91,7 +91,7 @@ pub async fn payment_intents_retrieve( let flow = Flow::PaymentsRetrieve; - wrap::compatibility_api_wrap::< + Box::pin(wrap::compatibility_api_wrap::< _, _, _, @@ -117,7 +117,7 @@ pub async fn payment_intents_retrieve( ) }, &*auth_type, - ) + )) .await } @@ -152,7 +152,7 @@ pub async fn payment_intents_retrieve_with_gateway_creds( let flow = Flow::PaymentsRetrieve; - wrap::compatibility_api_wrap::< + Box::pin(wrap::compatibility_api_wrap::< _, _, _, @@ -178,7 +178,7 @@ pub async fn payment_intents_retrieve_with_gateway_creds( ) }, &*auth_type, - ) + )) .await } @@ -214,7 +214,7 @@ pub async fn payment_intents_update( let flow = Flow::PaymentsUpdate; - wrap::compatibility_api_wrap::< + Box::pin(wrap::compatibility_api_wrap::< _, _, _, @@ -240,7 +240,7 @@ pub async fn payment_intents_update( ) }, &*auth_type, - ) + )) .await } @@ -278,7 +278,7 @@ pub async fn payment_intents_confirm( let flow = Flow::PaymentsConfirm; - wrap::compatibility_api_wrap::< + Box::pin(wrap::compatibility_api_wrap::< _, _, _, @@ -304,7 +304,7 @@ pub async fn payment_intents_confirm( ) }, &*auth_type, - ) + )) .await } @@ -332,7 +332,7 @@ pub async fn payment_intents_capture( let flow = Flow::PaymentsCapture; - wrap::compatibility_api_wrap::< + Box::pin(wrap::compatibility_api_wrap::< _, _, _, @@ -358,7 +358,7 @@ pub async fn payment_intents_capture( ) }, &auth::ApiKeyAuth, - ) + )) .await } @@ -390,7 +390,7 @@ pub async fn payment_intents_cancel( let flow = Flow::PaymentsCancel; - wrap::compatibility_api_wrap::< + Box::pin(wrap::compatibility_api_wrap::< _, _, _, @@ -416,7 +416,7 @@ pub async fn payment_intents_cancel( ) }, &*auth_type, - ) + )) .await } @@ -434,7 +434,7 @@ pub async fn payment_intent_list( let flow = Flow::PaymentsList; - wrap::compatibility_api_wrap::< + Box::pin(wrap::compatibility_api_wrap::< _, _, _, @@ -450,6 +450,6 @@ pub async fn payment_intent_list( payload, |state, auth, req| payments::list_payments(&*state.store, auth.merchant_account, req), &auth::ApiKeyAuth, - ) + )) .await } diff --git a/crates/router/src/compatibility/stripe/refunds.rs b/crates/router/src/compatibility/stripe/refunds.rs index 39b7785cd1..55de7b6bb5 100644 --- a/crates/router/src/compatibility/stripe/refunds.rs +++ b/crates/router/src/compatibility/stripe/refunds.rs @@ -31,7 +31,7 @@ pub async fn refund_create( let flow = Flow::RefundsCreate; - wrap::compatibility_api_wrap::< + Box::pin(wrap::compatibility_api_wrap::< _, _, _, @@ -49,7 +49,7 @@ pub async fn refund_create( refunds::refund_create_core(state, auth.merchant_account, auth.key_store, req) }, &auth::ApiKeyAuth, - ) + )) .await } @@ -70,7 +70,7 @@ pub async fn refund_retrieve_with_gateway_creds( let flow = Flow::RefundsRetrieve; - wrap::compatibility_api_wrap::< + Box::pin(wrap::compatibility_api_wrap::< _, _, _, @@ -94,7 +94,7 @@ pub async fn refund_retrieve_with_gateway_creds( ) }, &auth::ApiKeyAuth, - ) + )) .await } @@ -112,7 +112,7 @@ pub async fn refund_retrieve( let flow = Flow::RefundsRetrieve; - wrap::compatibility_api_wrap::< + Box::pin(wrap::compatibility_api_wrap::< _, _, _, @@ -136,7 +136,7 @@ pub async fn refund_retrieve( ) }, &auth::ApiKeyAuth, - ) + )) .await } @@ -152,7 +152,7 @@ pub async fn refund_update( let create_refund_update_req: refund_types::RefundUpdateRequest = payload.into(); let flow = Flow::RefundsUpdate; - wrap::compatibility_api_wrap::< + Box::pin(wrap::compatibility_api_wrap::< _, _, _, @@ -170,6 +170,6 @@ pub async fn refund_update( refunds::refund_update_core(&*state.store, auth.merchant_account, &refund_id, req) }, &auth::ApiKeyAuth, - ) + )) .await } diff --git a/crates/router/src/compatibility/stripe/setup_intents.rs b/crates/router/src/compatibility/stripe/setup_intents.rs index 71e0f7ebbc..119f67148a 100644 --- a/crates/router/src/compatibility/stripe/setup_intents.rs +++ b/crates/router/src/compatibility/stripe/setup_intents.rs @@ -39,7 +39,7 @@ pub async fn setup_intents_create( let flow = Flow::PaymentsCreate; - wrap::compatibility_api_wrap::< + Box::pin(wrap::compatibility_api_wrap::< _, _, _, @@ -65,7 +65,7 @@ pub async fn setup_intents_create( ) }, &auth::ApiKeyAuth, - ) + )) .await } @@ -95,7 +95,7 @@ pub async fn setup_intents_retrieve( let flow = Flow::PaymentsRetrieve; - wrap::compatibility_api_wrap::< + Box::pin(wrap::compatibility_api_wrap::< _, _, _, @@ -121,7 +121,7 @@ pub async fn setup_intents_retrieve( ) }, &*auth_type, - ) + )) .await } @@ -158,7 +158,7 @@ pub async fn setup_intents_update( let flow = Flow::PaymentsUpdate; - wrap::compatibility_api_wrap::< + Box::pin(wrap::compatibility_api_wrap::< _, _, _, @@ -184,7 +184,7 @@ pub async fn setup_intents_update( ) }, &*auth_type, - ) + )) .await } @@ -222,7 +222,7 @@ pub async fn setup_intents_confirm( let flow = Flow::PaymentsConfirm; - wrap::compatibility_api_wrap::< + Box::pin(wrap::compatibility_api_wrap::< _, _, _, @@ -248,6 +248,6 @@ pub async fn setup_intents_confirm( ) }, &*auth_type, - ) + )) .await } diff --git a/crates/router/src/core/admin.rs b/crates/router/src/core/admin.rs index d0d460036b..d318a29d24 100644 --- a/crates/router/src/core/admin.rs +++ b/crates/router/src/core/admin.rs @@ -1,4 +1,4 @@ -use api_models::{admin::PrimaryBusinessDetails, enums as api_enums}; +use api_models::{admin as admin_types, enums as api_enums}; use common_utils::{ crypto::{generate_cryptographically_secure_random_string, OptionalSecretValue}, date_time, @@ -51,12 +51,13 @@ pub async fn create_merchant_account( let publishable_key = Some(create_merchant_publishable_key()); - let primary_business_details = utils::Encode::>::encode_to_value( - &req.primary_business_details.unwrap_or_default(), - ) - .change_context(errors::ApiErrorResponse::InvalidDataValue { - field_name: "primary_business_details", - })?; + let primary_business_details = + utils::Encode::>::encode_to_value( + &req.primary_business_details.unwrap_or_default(), + ) + .change_context(errors::ApiErrorResponse::InvalidDataValue { + field_name: "primary_business_details", + })?; let merchant_details: OptionalSecretValue = req.merchant_details @@ -117,7 +118,17 @@ pub async fn create_merchant_account( &key_store, ) .await?; - + let metadata = req + .metadata + .as_ref() + .map(|meta| { + utils::Encode::::encode_to_value(meta) + .change_context(errors::ApiErrorResponse::InvalidDataValue { + field_name: "metadata", + }) + }) + .transpose()? + .map(Secret::new); let merchant_account = async { Ok(domain::MerchantAccount { merchant_id: req.merchant_id, @@ -140,7 +151,7 @@ pub async fn create_merchant_account( .unwrap_or_default(), publishable_key, locker_id: req.locker_id, - metadata: req.metadata, + metadata, storage_scheme: MerchantStorageScheme::PostgresOnly, primary_business_details, created_at: date_time::now(), @@ -231,10 +242,12 @@ pub async fn merchant_account_update( .primary_business_details .as_ref() .map(|primary_business_details| { - utils::Encode::>::encode_to_value(primary_business_details) - .change_context(errors::ApiErrorResponse::InvalidDataValue { - field_name: "primary_business_details", - }) + utils::Encode::>::encode_to_value( + primary_business_details, + ) + .change_context(errors::ApiErrorResponse::InvalidDataValue { + field_name: "primary_business_details", + }) }) .transpose()?; diff --git a/crates/router/src/core/webhooks.rs b/crates/router/src/core/webhooks.rs index a5399c61f3..a26d4db3e4 100644 --- a/crates/router/src/core/webhooks.rs +++ b/crates/router/src/core/webhooks.rs @@ -7,6 +7,8 @@ use masking::ExposeInterface; use router_env::{instrument, tracing}; use super::{errors::StorageErrorExt, metrics}; +#[cfg(feature = "stripe")] +use crate::compatibility::stripe::webhooks as stripe_webhooks; use crate::{ consts, core::{ @@ -477,6 +479,49 @@ async fn bank_transfer_webhook_flow( Ok(()) } +#[allow(clippy::too_many_arguments)] +#[instrument(skip_all)] +pub async fn create_event_and_trigger_appropriate_outgoing_webhook( + state: AppState, + merchant_account: domain::MerchantAccount, + event_type: enums::EventType, + event_class: enums::EventClass, + intent_reference_id: Option, + primary_object_id: String, + primary_object_type: enums::EventObjectType, + content: api::OutgoingWebhookContent, +) -> CustomResult<(), errors::ApiErrorResponse> { + match merchant_account.get_compatible_connector() { + #[cfg(feature = "stripe")] + Some(api_models::enums::Connector::Stripe) => { + create_event_and_trigger_outgoing_webhook::( + state.clone(), + merchant_account, + event_type, + event_class, + intent_reference_id, + primary_object_id, + primary_object_type, + content, + ) + .await + } + _ => { + create_event_and_trigger_outgoing_webhook::( + state.clone(), + merchant_account, + event_type, + event_class, + intent_reference_id, + primary_object_id, + primary_object_type, + content, + ) + .await + } + } +} + #[allow(clippy::too_many_arguments)] #[instrument(skip_all)] pub async fn create_event_and_trigger_outgoing_webhook( diff --git a/crates/router/src/types/domain/merchant_account.rs b/crates/router/src/types/domain/merchant_account.rs index 30710218e7..1f089f4271 100644 --- a/crates/router/src/types/domain/merchant_account.rs +++ b/crates/router/src/types/domain/merchant_account.rs @@ -1,11 +1,14 @@ use common_utils::{ crypto::{OptionalEncryptableName, OptionalEncryptableValue}, - date_time, pii, + date_time, + ext_traits::ValueExt, + pii, }; use data_models::MerchantStorageScheme; use diesel_models::{encryption::Encryption, merchant_account::MerchantAccountUpdateInternal}; use error_stack::ResultExt; use masking::{PeekInterface, Secret}; +use router_env::logger; use storage_impl::DataModelExt; use crate::{ @@ -236,3 +239,16 @@ impl super::behaviour::Conversion for MerchantAccount { }) } } + +impl MerchantAccount { + pub fn get_compatible_connector(&self) -> Option { + let metadata: Option = + self.metadata.as_ref().and_then(|meta| { + meta.clone() + .parse_value("MerchantAccountMetadata") + .map_err(|err| logger::error!("Failed to deserialize {:?}", err)) + .ok() + }); + metadata.and_then(|a| a.compatible_connector) + } +}