mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-11-02 04:04:43 +08:00
refactor(core): use business_profile to read merchant configs (#2729)
This commit is contained in:
@ -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
|
||||||
|
|||||||
@ -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,
|
||||||
)
|
)
|
||||||
|
|||||||
@ -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()
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user