fix(webhooks): send stripe compatible webhooks for stripe compatible merchants (#1986)

This commit is contained in:
Abhishek Marrivagu
2023-08-23 16:24:18 +05:30
committed by GitHub
parent 698677263b
commit 36631ad97b
8 changed files with 138 additions and 57 deletions

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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::<Vec<PrimaryBusinessDetails>>::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::<Vec<admin_types::PrimaryBusinessDetails>>::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::<admin_types::MerchantAccountMetadata>::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::<Vec<PrimaryBusinessDetails>>::encode_to_value(primary_business_details)
.change_context(errors::ApiErrorResponse::InvalidDataValue {
field_name: "primary_business_details",
})
utils::Encode::<Vec<admin_types::PrimaryBusinessDetails>>::encode_to_value(
primary_business_details,
)
.change_context(errors::ApiErrorResponse::InvalidDataValue {
field_name: "primary_business_details",
})
})
.transpose()?;

View File

@ -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<W: types::OutgoingWebhookType>(
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<String>,
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::<stripe_webhooks::StripeOutgoingWebhook>(
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::<api_models::webhooks::OutgoingWebhook>(
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<W: types::OutgoingWebhookType>(

View File

@ -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<api_models::enums::Connector> {
let metadata: Option<api_models::admin::MerchantAccountMetadata> =
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)
}
}