refactor(core): use business_profile to read merchant configs (#2729)

This commit is contained in:
Narayan Bhat
2023-10-31 13:14:45 +05:30
committed by GitHub
parent 9d9fc2a8c5
commit 8c85173ecd
6 changed files with 163 additions and 26 deletions

View File

@ -1,4 +1,7 @@
use api_models::{admin as admin_types, enums as api_enums}; use api_models::{
admin::{self as admin_types},
enums as api_enums,
};
use common_utils::{ use common_utils::{
crypto::{generate_cryptographically_secure_random_string, OptionalSecretValue}, crypto::{generate_cryptographically_secure_random_string, OptionalSecretValue},
date_time, date_time,
@ -6,6 +9,7 @@ use common_utils::{
pii, pii,
}; };
use error_stack::{report, FutureExt, ResultExt}; use error_stack::{report, FutureExt, ResultExt};
use futures::future::try_join_all;
use masking::{PeekInterface, Secret}; use masking::{PeekInterface, Secret};
use uuid::Uuid; use uuid::Uuid;
@ -379,6 +383,66 @@ pub async fn create_business_profile_from_business_labels(
Ok(()) Ok(())
} }
/// For backwards compatibility
/// If any of the fields of merchant account are updated, then update these fields in business profiles
pub async fn update_business_profile_cascade(
state: AppState,
merchant_account_update: api::MerchantAccountUpdate,
merchant_id: String,
) -> RouterResult<()> {
if merchant_account_update.return_url.is_some()
|| merchant_account_update.webhook_details.is_some()
|| merchant_account_update
.enable_payment_response_hash
.is_some()
|| merchant_account_update
.redirect_to_merchant_with_http_post
.is_some()
{
// Update these fields in all the business profiles
let business_profiles = state
.store
.list_business_profile_by_merchant_id(&merchant_id)
.await
.to_not_found_response(errors::ApiErrorResponse::BusinessProfileNotFound {
id: merchant_id.to_string(),
})?;
let business_profile_update = admin_types::BusinessProfileUpdate {
profile_name: None,
return_url: merchant_account_update.return_url,
enable_payment_response_hash: merchant_account_update.enable_payment_response_hash,
payment_response_hash_key: merchant_account_update.payment_response_hash_key,
redirect_to_merchant_with_http_post: merchant_account_update
.redirect_to_merchant_with_http_post,
webhook_details: merchant_account_update.webhook_details,
metadata: None,
routing_algorithm: None,
intent_fulfillment_time: None,
frm_routing_algorithm: None,
payout_routing_algorithm: None,
applepay_verified_domains: None,
};
let update_futures = business_profiles.iter().map(|business_profile| async {
let profile_id = &business_profile.profile_id;
update_business_profile(
state.clone(),
profile_id,
&merchant_id,
business_profile_update.clone(),
)
.await
});
try_join_all(update_futures).await?;
}
Ok(())
}
pub async fn merchant_account_update( pub async fn merchant_account_update(
state: AppState, state: AppState,
merchant_id: &String, merchant_id: &String,
@ -431,6 +495,7 @@ pub async fn merchant_account_update(
// In order to support backwards compatibility, if a business_labels are passed in the update // In order to support backwards compatibility, if a business_labels are passed in the update
// call, then create new business_profiles with the profile_name as business_label // call, then create new business_profiles with the profile_name as business_label
req.primary_business_details req.primary_business_details
.clone()
.async_map(|primary_business_details| async { .async_map(|primary_business_details| async {
let _ = create_business_profile_from_business_labels( let _ = create_business_profile_from_business_labels(
db, db,
@ -444,10 +509,10 @@ pub async fn merchant_account_update(
let key = key_store.key.get_inner().peek(); let key = key_store.key.get_inner().peek();
let business_profile_id_update = if let Some(profile_id) = req.default_profile { let business_profile_id_update = if let Some(ref profile_id) = req.default_profile {
if !profile_id.is_empty_after_trim() { if !profile_id.is_empty_after_trim() {
// Validate whether profile_id passed in request is valid and is linked to the merchant // Validate whether profile_id passed in request is valid and is linked to the merchant
core_utils::validate_and_get_business_profile(db, Some(&profile_id), merchant_id) core_utils::validate_and_get_business_profile(db, Some(profile_id), merchant_id)
.await? .await?
.map(|business_profile| Some(business_profile.profile_id)) .map(|business_profile| Some(business_profile.profile_id))
} else { } else {
@ -458,6 +523,9 @@ pub async fn merchant_account_update(
None None
}; };
// Update the business profile, This is for backwards compatibility
update_business_profile_cascade(state.clone(), req.clone(), merchant_id.to_string()).await?;
let updated_merchant_account = storage::MerchantAccountUpdate::Update { let updated_merchant_account = storage::MerchantAccountUpdate::Update {
merchant_name: req merchant_name: req
.merchant_name .merchant_name

View File

@ -345,7 +345,7 @@ pub trait PaymentRedirectFlow<Ctx: PaymentMethodRetrieve>: Sync {
fn generate_response( fn generate_response(
&self, &self,
payments_response: api_models::payments::PaymentsResponse, payments_response: api_models::payments::PaymentsResponse,
merchant_account: router_types::domain::MerchantAccount, business_profile: diesel_models::business_profile::BusinessProfile,
payment_id: String, payment_id: String,
connector: String, connector: String,
) -> RouterResult<api::RedirectionResponse>; ) -> RouterResult<api::RedirectionResponse>;
@ -418,8 +418,21 @@ pub trait PaymentRedirectFlow<Ctx: PaymentMethodRetrieve>: Sync {
.attach_printable("Failed to get the response in json"), .attach_printable("Failed to get the response in json"),
}?; }?;
let profile_id = payments_response
.profile_id
.as_ref()
.get_required_value("profile_id")?;
let business_profile = state
.store
.find_business_profile_by_profile_id(profile_id)
.await
.to_not_found_response(errors::ApiErrorResponse::BusinessProfileNotFound {
id: profile_id.to_string(),
})?;
let result = let result =
self.generate_response(payments_response, merchant_account, resource_id, connector)?; self.generate_response(payments_response, business_profile, resource_id, connector)?;
Ok(services::ApplicationResponse::JsonForRedirection(result)) Ok(services::ApplicationResponse::JsonForRedirection(result))
} }
@ -469,7 +482,7 @@ impl<Ctx: PaymentMethodRetrieve> PaymentRedirectFlow<Ctx> for PaymentRedirectCom
fn generate_response( fn generate_response(
&self, &self,
payments_response: api_models::payments::PaymentsResponse, payments_response: api_models::payments::PaymentsResponse,
merchant_account: router_types::domain::MerchantAccount, business_profile: diesel_models::business_profile::BusinessProfile,
payment_id: String, payment_id: String,
connector: String, connector: String,
) -> RouterResult<api::RedirectionResponse> { ) -> RouterResult<api::RedirectionResponse> {
@ -506,7 +519,7 @@ impl<Ctx: PaymentMethodRetrieve> PaymentRedirectFlow<Ctx> for PaymentRedirectCom
| api_models::enums::IntentStatus::Failed | api_models::enums::IntentStatus::Failed
| api_models::enums::IntentStatus::Cancelled | api_models::enums::IntentStatus::RequiresCapture| api_models::enums::IntentStatus::Processing=> helpers::get_handle_response_url( | api_models::enums::IntentStatus::Cancelled | api_models::enums::IntentStatus::RequiresCapture| api_models::enums::IntentStatus::Processing=> helpers::get_handle_response_url(
payment_id, payment_id,
&merchant_account, &business_profile,
payments_response, payments_response,
connector, connector,
), ),
@ -560,13 +573,13 @@ impl<Ctx: PaymentMethodRetrieve> PaymentRedirectFlow<Ctx> for PaymentRedirectSyn
fn generate_response( fn generate_response(
&self, &self,
payments_response: api_models::payments::PaymentsResponse, payments_response: api_models::payments::PaymentsResponse,
merchant_account: router_types::domain::MerchantAccount, business_profile: diesel_models::business_profile::BusinessProfile,
payment_id: String, payment_id: String,
connector: String, connector: String,
) -> RouterResult<api::RedirectionResponse> { ) -> RouterResult<api::RedirectionResponse> {
helpers::get_handle_response_url( helpers::get_handle_response_url(
payment_id, payment_id,
&merchant_account, &business_profile,
payments_response, payments_response,
connector, connector,
) )

View File

@ -1891,7 +1891,7 @@ pub(super) fn validate_payment_list_request_for_joins(
pub fn get_handle_response_url( pub fn get_handle_response_url(
payment_id: String, payment_id: String,
merchant_account: &domain::MerchantAccount, business_profile: &diesel_models::business_profile::BusinessProfile,
response: api::PaymentsResponse, response: api::PaymentsResponse,
connector: String, connector: String,
) -> RouterResult<api::RedirectionResponse> { ) -> RouterResult<api::RedirectionResponse> {
@ -1900,7 +1900,7 @@ pub fn get_handle_response_url(
let redirection_response = make_pg_redirect_response(payment_id, &response, connector); let redirection_response = make_pg_redirect_response(payment_id, &response, connector);
let return_url = make_merchant_url_with_response( let return_url = make_merchant_url_with_response(
merchant_account, business_profile,
redirection_response, redirection_response,
payments_return_url, payments_return_url,
response.client_secret.as_ref(), response.client_secret.as_ref(),
@ -1908,11 +1908,11 @@ pub fn get_handle_response_url(
) )
.attach_printable("Failed to make merchant url with response")?; .attach_printable("Failed to make merchant url with response")?;
make_url_with_signature(&return_url, merchant_account) make_url_with_signature(&return_url, business_profile)
} }
pub fn make_merchant_url_with_response( pub fn make_merchant_url_with_response(
merchant_account: &domain::MerchantAccount, business_profile: &diesel_models::business_profile::BusinessProfile,
redirection_response: api::PgRedirectResponse, redirection_response: api::PgRedirectResponse,
request_return_url: Option<&String>, request_return_url: Option<&String>,
client_secret: Option<&masking::Secret<String>>, client_secret: Option<&masking::Secret<String>>,
@ -1920,7 +1920,7 @@ pub fn make_merchant_url_with_response(
) -> RouterResult<String> { ) -> RouterResult<String> {
// take return url if provided in the request else use merchant return url // take return url if provided in the request else use merchant return url
let url = request_return_url let url = request_return_url
.or(merchant_account.return_url.as_ref()) .or(business_profile.return_url.as_ref())
.get_required_value("return_url")?; .get_required_value("return_url")?;
let status_check = redirection_response.status; let status_check = redirection_response.status;
@ -1930,7 +1930,7 @@ pub fn make_merchant_url_with_response(
.into_report() .into_report()
.attach_printable("Expected client secret to be `Some`")?; .attach_printable("Expected client secret to be `Some`")?;
let merchant_url_with_response = if merchant_account.redirect_to_merchant_with_http_post { let merchant_url_with_response = if business_profile.redirect_to_merchant_with_http_post {
url::Url::parse_with_params( url::Url::parse_with_params(
url, url,
&[ &[
@ -2024,7 +2024,7 @@ pub fn make_pg_redirect_response(
pub fn make_url_with_signature( pub fn make_url_with_signature(
redirect_url: &str, redirect_url: &str,
merchant_account: &domain::MerchantAccount, business_profile: &diesel_models::business_profile::BusinessProfile,
) -> RouterResult<api::RedirectionResponse> { ) -> RouterResult<api::RedirectionResponse> {
let mut url = url::Url::parse(redirect_url) let mut url = url::Url::parse(redirect_url)
.into_report() .into_report()
@ -2034,8 +2034,8 @@ pub fn make_url_with_signature(
let mut base_url = url.clone(); let mut base_url = url.clone();
base_url.query_pairs_mut().clear(); base_url.query_pairs_mut().clear();
let url = if merchant_account.enable_payment_response_hash { let url = if business_profile.enable_payment_response_hash {
let key = merchant_account let key = business_profile
.payment_response_hash_key .payment_response_hash_key
.as_ref() .as_ref()
.get_required_value("payment_response_hash_key")?; .get_required_value("payment_response_hash_key")?;
@ -2063,7 +2063,7 @@ pub fn make_url_with_signature(
return_url: base_url.to_string(), return_url: base_url.to_string(),
params: parameters, params: parameters,
return_url_with_query_params: url.to_string(), return_url_with_query_params: url.to_string(),
http_method: if merchant_account.redirect_to_merchant_with_http_post { http_method: if business_profile.redirect_to_merchant_with_http_post {
services::Method::Post.to_string() services::Method::Post.to_string()
} else { } else {
services::Method::Get.to_string() services::Method::Get.to_string()

View File

@ -46,6 +46,7 @@ pub async fn payments_incoming_webhook_flow<
>( >(
state: AppState, state: AppState,
merchant_account: domain::MerchantAccount, merchant_account: domain::MerchantAccount,
business_profile: diesel_models::business_profile::BusinessProfile,
key_store: domain::MerchantKeyStore, key_store: domain::MerchantKeyStore,
webhook_details: api::IncomingWebhookDetails, webhook_details: api::IncomingWebhookDetails,
source_verified: bool, source_verified: bool,
@ -156,6 +157,7 @@ pub async fn payments_incoming_webhook_flow<
create_event_and_trigger_outgoing_webhook::<W>( create_event_and_trigger_outgoing_webhook::<W>(
state, state,
merchant_account, merchant_account,
business_profile,
outgoing_event_type, outgoing_event_type,
enums::EventClass::Payments, enums::EventClass::Payments,
None, None,
@ -178,9 +180,11 @@ pub async fn payments_incoming_webhook_flow<
} }
#[instrument(skip_all)] #[instrument(skip_all)]
#[allow(clippy::too_many_arguments)]
pub async fn refunds_incoming_webhook_flow<W: types::OutgoingWebhookType>( pub async fn refunds_incoming_webhook_flow<W: types::OutgoingWebhookType>(
state: AppState, state: AppState,
merchant_account: domain::MerchantAccount, merchant_account: domain::MerchantAccount,
business_profile: diesel_models::business_profile::BusinessProfile,
key_store: domain::MerchantKeyStore, key_store: domain::MerchantKeyStore,
webhook_details: api::IncomingWebhookDetails, webhook_details: api::IncomingWebhookDetails,
connector_name: &str, connector_name: &str,
@ -269,6 +273,7 @@ pub async fn refunds_incoming_webhook_flow<W: types::OutgoingWebhookType>(
create_event_and_trigger_outgoing_webhook::<W>( create_event_and_trigger_outgoing_webhook::<W>(
state, state,
merchant_account, merchant_account,
business_profile,
outgoing_event_type, outgoing_event_type,
enums::EventClass::Refunds, enums::EventClass::Refunds,
None, None,
@ -404,6 +409,7 @@ pub async fn get_or_update_dispute_object(
pub async fn mandates_incoming_webhook_flow<W: types::OutgoingWebhookType>( pub async fn mandates_incoming_webhook_flow<W: types::OutgoingWebhookType>(
state: AppState, state: AppState,
merchant_account: domain::MerchantAccount, merchant_account: domain::MerchantAccount,
business_profile: diesel_models::business_profile::BusinessProfile,
webhook_details: api::IncomingWebhookDetails, webhook_details: api::IncomingWebhookDetails,
source_verified: bool, source_verified: bool,
event_type: api_models::webhooks::IncomingWebhookEvent, event_type: api_models::webhooks::IncomingWebhookEvent,
@ -455,6 +461,7 @@ pub async fn mandates_incoming_webhook_flow<W: types::OutgoingWebhookType>(
create_event_and_trigger_outgoing_webhook::<W>( create_event_and_trigger_outgoing_webhook::<W>(
state, state,
merchant_account, merchant_account,
business_profile,
outgoing_event_type, outgoing_event_type,
enums::EventClass::Mandates, enums::EventClass::Mandates,
None, None,
@ -474,10 +481,12 @@ pub async fn mandates_incoming_webhook_flow<W: types::OutgoingWebhookType>(
} }
} }
#[allow(clippy::too_many_arguments)]
#[instrument(skip_all)] #[instrument(skip_all)]
pub async fn disputes_incoming_webhook_flow<W: types::OutgoingWebhookType>( pub async fn disputes_incoming_webhook_flow<W: types::OutgoingWebhookType>(
state: AppState, state: AppState,
merchant_account: domain::MerchantAccount, merchant_account: domain::MerchantAccount,
business_profile: diesel_models::business_profile::BusinessProfile,
webhook_details: api::IncomingWebhookDetails, webhook_details: api::IncomingWebhookDetails,
source_verified: bool, source_verified: bool,
connector: &(dyn api::Connector + Sync), connector: &(dyn api::Connector + Sync),
@ -518,6 +527,7 @@ pub async fn disputes_incoming_webhook_flow<W: types::OutgoingWebhookType>(
create_event_and_trigger_outgoing_webhook::<W>( create_event_and_trigger_outgoing_webhook::<W>(
state, state,
merchant_account, merchant_account,
business_profile,
event_type, event_type,
enums::EventClass::Disputes, enums::EventClass::Disputes,
None, None,
@ -541,6 +551,7 @@ pub async fn disputes_incoming_webhook_flow<W: types::OutgoingWebhookType>(
async fn bank_transfer_webhook_flow<W: types::OutgoingWebhookType, Ctx: PaymentMethodRetrieve>( async fn bank_transfer_webhook_flow<W: types::OutgoingWebhookType, Ctx: PaymentMethodRetrieve>(
state: AppState, state: AppState,
merchant_account: domain::MerchantAccount, merchant_account: domain::MerchantAccount,
business_profile: diesel_models::business_profile::BusinessProfile,
key_store: domain::MerchantKeyStore, key_store: domain::MerchantKeyStore,
webhook_details: api::IncomingWebhookDetails, webhook_details: api::IncomingWebhookDetails,
source_verified: bool, source_verified: bool,
@ -594,6 +605,7 @@ async fn bank_transfer_webhook_flow<W: types::OutgoingWebhookType, Ctx: PaymentM
create_event_and_trigger_outgoing_webhook::<W>( create_event_and_trigger_outgoing_webhook::<W>(
state, state,
merchant_account, merchant_account,
business_profile,
outgoing_event_type, outgoing_event_type,
enums::EventClass::Payments, enums::EventClass::Payments,
None, None,
@ -618,6 +630,7 @@ async fn bank_transfer_webhook_flow<W: types::OutgoingWebhookType, Ctx: PaymentM
pub async fn create_event_and_trigger_appropriate_outgoing_webhook( pub async fn create_event_and_trigger_appropriate_outgoing_webhook(
state: AppState, state: AppState,
merchant_account: domain::MerchantAccount, merchant_account: domain::MerchantAccount,
business_profile: diesel_models::business_profile::BusinessProfile,
event_type: enums::EventType, event_type: enums::EventType,
event_class: enums::EventClass, event_class: enums::EventClass,
intent_reference_id: Option<String>, intent_reference_id: Option<String>,
@ -631,6 +644,7 @@ pub async fn create_event_and_trigger_appropriate_outgoing_webhook(
create_event_and_trigger_outgoing_webhook::<stripe_webhooks::StripeOutgoingWebhook>( create_event_and_trigger_outgoing_webhook::<stripe_webhooks::StripeOutgoingWebhook>(
state.clone(), state.clone(),
merchant_account, merchant_account,
business_profile,
event_type, event_type,
event_class, event_class,
intent_reference_id, intent_reference_id,
@ -644,6 +658,7 @@ pub async fn create_event_and_trigger_appropriate_outgoing_webhook(
create_event_and_trigger_outgoing_webhook::<api_models::webhooks::OutgoingWebhook>( create_event_and_trigger_outgoing_webhook::<api_models::webhooks::OutgoingWebhook>(
state.clone(), state.clone(),
merchant_account, merchant_account,
business_profile,
event_type, event_type,
event_class, event_class,
intent_reference_id, intent_reference_id,
@ -661,6 +676,7 @@ pub async fn create_event_and_trigger_appropriate_outgoing_webhook(
pub async fn create_event_and_trigger_outgoing_webhook<W: types::OutgoingWebhookType>( pub async fn create_event_and_trigger_outgoing_webhook<W: types::OutgoingWebhookType>(
state: AppState, state: AppState,
merchant_account: domain::MerchantAccount, merchant_account: domain::MerchantAccount,
business_profile: diesel_models::business_profile::BusinessProfile,
event_type: enums::EventType, event_type: enums::EventType,
event_class: enums::EventClass, event_class: enums::EventClass,
intent_reference_id: Option<String>, intent_reference_id: Option<String>,
@ -709,7 +725,7 @@ pub async fn create_event_and_trigger_outgoing_webhook<W: types::OutgoingWebhook
// may have an actix arbiter // may have an actix arbiter
tokio::spawn(async move { tokio::spawn(async move {
let result = let result =
trigger_webhook_to_merchant::<W>(merchant_account, outgoing_webhook, &state).await; trigger_webhook_to_merchant::<W>(business_profile, outgoing_webhook, &state).await;
if let Err(e) = result { if let Err(e) = result {
logger::error!(?e); logger::error!(?e);
@ -721,11 +737,11 @@ pub async fn create_event_and_trigger_outgoing_webhook<W: types::OutgoingWebhook
} }
pub async fn trigger_webhook_to_merchant<W: types::OutgoingWebhookType>( pub async fn trigger_webhook_to_merchant<W: types::OutgoingWebhookType>(
merchant_account: domain::MerchantAccount, business_profile: diesel_models::business_profile::BusinessProfile,
webhook: api::OutgoingWebhook, webhook: api::OutgoingWebhook,
state: &AppState, state: &AppState,
) -> CustomResult<(), errors::WebhooksFlowError> { ) -> CustomResult<(), errors::WebhooksFlowError> {
let webhook_details_json = merchant_account let webhook_details_json = business_profile
.webhook_details .webhook_details
.get_required_value("webhook_details") .get_required_value("webhook_details")
.change_context(errors::WebhooksFlowError::MerchantWebhookDetailsNotFound)?; .change_context(errors::WebhooksFlowError::MerchantWebhookDetailsNotFound)?;
@ -746,7 +762,7 @@ pub async fn trigger_webhook_to_merchant<W: types::OutgoingWebhookType>(
let transformed_outgoing_webhook = W::from(webhook); let transformed_outgoing_webhook = W::from(webhook);
let outgoing_webhooks_signature = transformed_outgoing_webhook let outgoing_webhooks_signature = transformed_outgoing_webhook
.get_outgoing_webhooks_signature(merchant_account.payment_response_hash_key.clone())?; .get_outgoing_webhooks_signature(business_profile.payment_response_hash_key.clone())?;
let transformed_outgoing_webhook_string = router_types::RequestBody::log_and_get_request_body( let transformed_outgoing_webhook_string = router_types::RequestBody::log_and_get_request_body(
&transformed_outgoing_webhook, &transformed_outgoing_webhook,
@ -782,7 +798,7 @@ pub async fn trigger_webhook_to_merchant<W: types::OutgoingWebhookType>(
1, 1,
&[metrics::KeyValue::new( &[metrics::KeyValue::new(
MERCHANT_ID, MERCHANT_ID,
merchant_account.merchant_id.clone(), business_profile.merchant_id.clone(),
)], )],
); );
logger::debug!(outgoing_webhook_response=?response); logger::debug!(outgoing_webhook_response=?response);
@ -799,7 +815,7 @@ pub async fn trigger_webhook_to_merchant<W: types::OutgoingWebhookType>(
1, 1,
&[metrics::KeyValue::new( &[metrics::KeyValue::new(
MERCHANT_ID, MERCHANT_ID,
merchant_account.merchant_id.clone(), business_profile.merchant_id.clone(),
)], )],
); );
let update_event = storage::EventUpdate::UpdateWebhookNotified { let update_event = storage::EventUpdate::UpdateWebhookNotified {
@ -816,7 +832,7 @@ pub async fn trigger_webhook_to_merchant<W: types::OutgoingWebhookType>(
1, 1,
&[metrics::KeyValue::new( &[metrics::KeyValue::new(
MERCHANT_ID, MERCHANT_ID,
merchant_account.merchant_id.clone(), business_profile.merchant_id.clone(),
)], )],
); );
// [#217]: Schedule webhook for retry. // [#217]: Schedule webhook for retry.
@ -1048,10 +1064,26 @@ pub async fn webhooks_core<W: types::OutgoingWebhookType, Ctx: PaymentMethodRetr
)?, )?,
}; };
let profile_id = merchant_connector_account
.profile_id
.as_ref()
.get_required_value("profile_id")
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Could not find profile_id in merchant connector account")?;
let business_profile = state
.store
.find_business_profile_by_profile_id(profile_id)
.await
.to_not_found_response(errors::ApiErrorResponse::BusinessProfileNotFound {
id: profile_id.to_string(),
})?;
match flow_type { match flow_type {
api::WebhookFlow::Payment => payments_incoming_webhook_flow::<W, Ctx>( api::WebhookFlow::Payment => payments_incoming_webhook_flow::<W, Ctx>(
state.clone(), state.clone(),
merchant_account, merchant_account,
business_profile,
key_store, key_store,
webhook_details, webhook_details,
source_verified, source_verified,
@ -1062,6 +1094,7 @@ pub async fn webhooks_core<W: types::OutgoingWebhookType, Ctx: PaymentMethodRetr
api::WebhookFlow::Refund => refunds_incoming_webhook_flow::<W>( api::WebhookFlow::Refund => refunds_incoming_webhook_flow::<W>(
state.clone(), state.clone(),
merchant_account, merchant_account,
business_profile,
key_store, key_store,
webhook_details, webhook_details,
connector_name.as_str(), connector_name.as_str(),
@ -1074,6 +1107,7 @@ pub async fn webhooks_core<W: types::OutgoingWebhookType, Ctx: PaymentMethodRetr
api::WebhookFlow::Dispute => disputes_incoming_webhook_flow::<W>( api::WebhookFlow::Dispute => disputes_incoming_webhook_flow::<W>(
state.clone(), state.clone(),
merchant_account, merchant_account,
business_profile,
webhook_details, webhook_details,
source_verified, source_verified,
*connector, *connector,
@ -1086,6 +1120,7 @@ pub async fn webhooks_core<W: types::OutgoingWebhookType, Ctx: PaymentMethodRetr
api::WebhookFlow::BankTransfer => bank_transfer_webhook_flow::<W, Ctx>( api::WebhookFlow::BankTransfer => bank_transfer_webhook_flow::<W, Ctx>(
state.clone(), state.clone(),
merchant_account, merchant_account,
business_profile,
key_store, key_store,
webhook_details, webhook_details,
source_verified, source_verified,
@ -1098,6 +1133,7 @@ pub async fn webhooks_core<W: types::OutgoingWebhookType, Ctx: PaymentMethodRetr
api::WebhookFlow::Mandate => mandates_incoming_webhook_flow::<W>( api::WebhookFlow::Mandate => mandates_incoming_webhook_flow::<W>(
state.clone(), state.clone(),
merchant_account, merchant_account,
business_profile,
webhook_details, webhook_details,
source_verified, source_verified,
event_type, event_type,

View File

@ -699,6 +699,7 @@ impl ForeignTryFrom<enums::IntentStatus> for enums::EventType {
pub async fn trigger_payments_webhook<F, Req, Op>( pub async fn trigger_payments_webhook<F, Req, Op>(
merchant_account: domain::MerchantAccount, merchant_account: domain::MerchantAccount,
business_profile: diesel_models::business_profile::BusinessProfile,
payment_data: crate::core::payments::PaymentData<F>, payment_data: crate::core::payments::PaymentData<F>,
req: Option<Req>, req: Option<Req>,
customer: Option<domain::Customer>, customer: Option<domain::Customer>,
@ -753,6 +754,7 @@ where
webhooks_core::create_event_and_trigger_appropriate_outgoing_webhook( webhooks_core::create_event_and_trigger_appropriate_outgoing_webhook(
state.clone(), state.clone(),
merchant_account, merchant_account,
business_profile,
event_type, event_type,
diesel_models::enums::EventClass::Payments, diesel_models::enums::EventClass::Payments,
None, None,

View File

@ -149,10 +149,28 @@ impl ProcessTrackerWorkflow<AppState> for PaymentsSyncWorkflow {
.await .await
.to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?; .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?;
let profile_id = payment_data
.payment_intent
.profile_id
.as_ref()
.get_required_value("profile_id")
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Could not find profile_id in payment intent")?;
let business_profile = db
.find_business_profile_by_profile_id(profile_id)
.await
.to_not_found_response(
errors::ApiErrorResponse::BusinessProfileNotFound {
id: profile_id.to_string(),
},
)?;
// Trigger the outgoing webhook to notify the merchant about failed payment // Trigger the outgoing webhook to notify the merchant about failed payment
let operation = operations::PaymentStatus; let operation = operations::PaymentStatus;
utils::trigger_payments_webhook::<_, api_models::payments::PaymentsRequest, _>( utils::trigger_payments_webhook::<_, api_models::payments::PaymentsRequest, _>(
merchant_account, merchant_account,
business_profile,
payment_data, payment_data,
None, None,
customer, customer,