mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-30 01:27:31 +08:00
revert: connector_label in webhook url is reverted back to connector_name (#1779)
This commit is contained in:
@ -70,6 +70,29 @@ impl MerchantConnectorAccount {
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(skip(conn))]
|
||||||
|
pub async fn find_by_merchant_id_connector_name(
|
||||||
|
conn: &PgPooledConn,
|
||||||
|
merchant_id: &str,
|
||||||
|
connector_name: &str,
|
||||||
|
) -> StorageResult<Vec<Self>> {
|
||||||
|
generics::generic_filter::<
|
||||||
|
<Self as HasTable>::Table,
|
||||||
|
_,
|
||||||
|
<<Self as HasTable>::Table as Table>::PrimaryKey,
|
||||||
|
_,
|
||||||
|
>(
|
||||||
|
conn,
|
||||||
|
dsl::merchant_id
|
||||||
|
.eq(merchant_id.to_owned())
|
||||||
|
.and(dsl::connector_name.eq(connector_name.to_owned())),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
#[instrument(skip(conn))]
|
#[instrument(skip(conn))]
|
||||||
pub async fn find_by_merchant_id_merchant_connector_id(
|
pub async fn find_by_merchant_id_merchant_connector_id(
|
||||||
conn: &PgPooledConn,
|
conn: &PgPooledConn,
|
||||||
|
|||||||
@ -101,7 +101,7 @@ impl Webhooks {
|
|||||||
web::scope("/webhooks")
|
web::scope("/webhooks")
|
||||||
.app_data(web::Data::new(config))
|
.app_data(web::Data::new(config))
|
||||||
.service(
|
.service(
|
||||||
web::resource("/{merchant_id}/{connector_label}")
|
web::resource("/{merchant_id}/{connector_name}")
|
||||||
.route(
|
.route(
|
||||||
web::post().to(webhooks::receive_incoming_webhook::<StripeOutgoingWebhook>),
|
web::post().to(webhooks::receive_incoming_webhook::<StripeOutgoingWebhook>),
|
||||||
)
|
)
|
||||||
|
|||||||
@ -630,18 +630,9 @@ pub async fn webhooks_core<W: types::OutgoingWebhookType>(
|
|||||||
req: &actix_web::HttpRequest,
|
req: &actix_web::HttpRequest,
|
||||||
merchant_account: domain::MerchantAccount,
|
merchant_account: domain::MerchantAccount,
|
||||||
key_store: domain::MerchantKeyStore,
|
key_store: domain::MerchantKeyStore,
|
||||||
connector_label: &str,
|
connector_name: &str,
|
||||||
body: actix_web::web::Bytes,
|
body: actix_web::web::Bytes,
|
||||||
) -> RouterResponse<serde_json::Value> {
|
) -> RouterResponse<serde_json::Value> {
|
||||||
let connector_name = connector_label
|
|
||||||
.split('_') //connector_name will be the first string after splitting connector_label
|
|
||||||
.next()
|
|
||||||
.ok_or(errors::ApiErrorResponse::InvalidDataValue {
|
|
||||||
field_name: "connector_label",
|
|
||||||
})
|
|
||||||
.into_report()
|
|
||||||
.attach_printable("Failed to infer connector_name from connector_label")?;
|
|
||||||
|
|
||||||
metrics::WEBHOOK_INCOMING_COUNT.add(
|
metrics::WEBHOOK_INCOMING_COUNT.add(
|
||||||
&metrics::CONTEXT,
|
&metrics::CONTEXT,
|
||||||
1,
|
1,
|
||||||
@ -688,7 +679,7 @@ pub async fn webhooks_core<W: types::OutgoingWebhookType>(
|
|||||||
|
|
||||||
let process_webhook_further = utils::lookup_webhook_event(
|
let process_webhook_further = utils::lookup_webhook_event(
|
||||||
&*state.store,
|
&*state.store,
|
||||||
connector_label,
|
connector_name,
|
||||||
&merchant_account.merchant_id,
|
&merchant_account.merchant_id,
|
||||||
&event_type,
|
&event_type,
|
||||||
)
|
)
|
||||||
@ -704,7 +695,7 @@ pub async fn webhooks_core<W: types::OutgoingWebhookType>(
|
|||||||
&*state.store,
|
&*state.store,
|
||||||
&request_details,
|
&request_details,
|
||||||
&merchant_account.merchant_id,
|
&merchant_account.merchant_id,
|
||||||
connector_label,
|
connector_name,
|
||||||
&key_store,
|
&key_store,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
|||||||
@ -1,4 +1,7 @@
|
|||||||
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
use common_utils::ext_traits::{AsyncExt, ByteSliceExt, Encode};
|
use common_utils::ext_traits::{AsyncExt, ByteSliceExt, Encode};
|
||||||
|
use diesel_models::errors as storage_errors;
|
||||||
use error_stack::{IntoReport, ResultExt};
|
use error_stack::{IntoReport, ResultExt};
|
||||||
|
|
||||||
use super::{MockDb, Store};
|
use super::{MockDb, Store};
|
||||||
@ -119,6 +122,13 @@ where
|
|||||||
key_store: &domain::MerchantKeyStore,
|
key_store: &domain::MerchantKeyStore,
|
||||||
) -> CustomResult<domain::MerchantConnectorAccount, errors::StorageError>;
|
) -> CustomResult<domain::MerchantConnectorAccount, errors::StorageError>;
|
||||||
|
|
||||||
|
async fn find_merchant_connector_account_by_merchant_id_connector_name(
|
||||||
|
&self,
|
||||||
|
merchant_id: &str,
|
||||||
|
connector_name: &str,
|
||||||
|
key_store: &domain::MerchantKeyStore,
|
||||||
|
) -> CustomResult<domain::MerchantConnectorAccount, errors::StorageError>;
|
||||||
|
|
||||||
async fn insert_merchant_connector_account(
|
async fn insert_merchant_connector_account(
|
||||||
&self,
|
&self,
|
||||||
t: domain::MerchantConnectorAccount,
|
t: domain::MerchantConnectorAccount,
|
||||||
@ -200,6 +210,53 @@ impl MerchantConnectorAccountInterface for Store {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn find_merchant_connector_account_by_merchant_id_connector_name(
|
||||||
|
&self,
|
||||||
|
merchant_id: &str,
|
||||||
|
connector_name: &str,
|
||||||
|
key_store: &domain::MerchantKeyStore,
|
||||||
|
) -> CustomResult<domain::MerchantConnectorAccount, errors::StorageError> {
|
||||||
|
let find_call = || async {
|
||||||
|
let conn = connection::pg_connection_read(self).await?;
|
||||||
|
storage::MerchantConnectorAccount::find_by_merchant_id_connector_name(
|
||||||
|
&conn,
|
||||||
|
merchant_id,
|
||||||
|
connector_name,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.map_err(Into::into)
|
||||||
|
.into_report()
|
||||||
|
};
|
||||||
|
let mca_list = find_call().await?;
|
||||||
|
match mca_list.len().cmp(&1) {
|
||||||
|
Ordering::Less => {
|
||||||
|
Err(errors::StorageError::ValueNotFound("MerchantConnectorAccount".into()).into())
|
||||||
|
.attach_printable(format!(
|
||||||
|
"No records found for {} and {}",
|
||||||
|
merchant_id, connector_name
|
||||||
|
))
|
||||||
|
}
|
||||||
|
Ordering::Greater => Err(errors::StorageError::DatabaseError(
|
||||||
|
storage_errors::DatabaseError::Others.into(),
|
||||||
|
))
|
||||||
|
.into_report()
|
||||||
|
.attach_printable(format!(
|
||||||
|
"Found multiple records for {} and {}",
|
||||||
|
merchant_id, connector_name
|
||||||
|
)),
|
||||||
|
Ordering::Equal => match mca_list.first() {
|
||||||
|
Some(mca) => mca
|
||||||
|
.to_owned()
|
||||||
|
.convert(key_store.key.get_inner())
|
||||||
|
.await
|
||||||
|
.change_context(errors::StorageError::DeserializationFailed),
|
||||||
|
None => Err(
|
||||||
|
errors::StorageError::ValueNotFound("MerchantConnectorAccount".into()).into(),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async fn find_by_merchant_connector_account_merchant_id_merchant_connector_id(
|
async fn find_by_merchant_connector_account_merchant_id_merchant_connector_id(
|
||||||
&self,
|
&self,
|
||||||
merchant_id: &str,
|
merchant_id: &str,
|
||||||
@ -377,7 +434,7 @@ impl MerchantConnectorAccountInterface for MockDb {
|
|||||||
.await
|
.await
|
||||||
.iter()
|
.iter()
|
||||||
.find(|account| {
|
.find(|account| {
|
||||||
account.merchant_id == merchant_id && account.connector_name == connector
|
account.merchant_id == merchant_id && account.connector_label == connector
|
||||||
})
|
})
|
||||||
.cloned()
|
.cloned()
|
||||||
.async_map(|account| async {
|
.async_map(|account| async {
|
||||||
@ -398,6 +455,51 @@ impl MerchantConnectorAccountInterface for MockDb {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn find_merchant_connector_account_by_merchant_id_connector_name(
|
||||||
|
&self,
|
||||||
|
merchant_id: &str,
|
||||||
|
connector_name: &str,
|
||||||
|
key_store: &domain::MerchantKeyStore,
|
||||||
|
) -> CustomResult<domain::MerchantConnectorAccount, errors::StorageError> {
|
||||||
|
let mca_list = self
|
||||||
|
.merchant_connector_accounts
|
||||||
|
.lock()
|
||||||
|
.await
|
||||||
|
.iter()
|
||||||
|
.filter(|account| {
|
||||||
|
account.merchant_id == merchant_id && account.connector_name == connector_name
|
||||||
|
})
|
||||||
|
.cloned()
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
match mca_list.len().cmp(&1) {
|
||||||
|
Ordering::Less => {
|
||||||
|
Err(errors::StorageError::ValueNotFound("MerchantConnectorAccount".into()).into())
|
||||||
|
.attach_printable(format!(
|
||||||
|
"No records found for {} and {}",
|
||||||
|
merchant_id, connector_name
|
||||||
|
))
|
||||||
|
}
|
||||||
|
Ordering::Greater => Err(errors::StorageError::DatabaseError(
|
||||||
|
storage_errors::DatabaseError::Others.into(),
|
||||||
|
))
|
||||||
|
.into_report()
|
||||||
|
.attach_printable(format!(
|
||||||
|
"Found multiple records for {} and {}",
|
||||||
|
merchant_id, connector_name
|
||||||
|
)),
|
||||||
|
Ordering::Equal => match mca_list.first() {
|
||||||
|
Some(mca) => mca
|
||||||
|
.to_owned()
|
||||||
|
.convert(key_store.key.get_inner())
|
||||||
|
.await
|
||||||
|
.change_context(errors::StorageError::DeserializationFailed),
|
||||||
|
None => Err(
|
||||||
|
errors::StorageError::ValueNotFound("MerchantConnectorAccount".into()).into(),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async fn find_by_merchant_connector_account_merchant_id_merchant_connector_id(
|
async fn find_by_merchant_connector_account_merchant_id_merchant_connector_id(
|
||||||
&self,
|
&self,
|
||||||
merchant_id: &str,
|
merchant_id: &str,
|
||||||
|
|||||||
@ -410,7 +410,7 @@ impl Webhooks {
|
|||||||
web::scope("/webhooks")
|
web::scope("/webhooks")
|
||||||
.app_data(web::Data::new(config))
|
.app_data(web::Data::new(config))
|
||||||
.service(
|
.service(
|
||||||
web::resource("/{merchant_id}/{connector_label}")
|
web::resource("/{merchant_id}/{connector_name}")
|
||||||
.route(
|
.route(
|
||||||
web::post().to(receive_incoming_webhook::<webhook_type::OutgoingWebhook>),
|
web::post().to(receive_incoming_webhook::<webhook_type::OutgoingWebhook>),
|
||||||
)
|
)
|
||||||
|
|||||||
@ -15,7 +15,7 @@ pub async fn receive_incoming_webhook<W: types::OutgoingWebhookType>(
|
|||||||
path: web::Path<(String, String)>,
|
path: web::Path<(String, String)>,
|
||||||
) -> impl Responder {
|
) -> impl Responder {
|
||||||
let flow = Flow::IncomingWebhookReceive;
|
let flow = Flow::IncomingWebhookReceive;
|
||||||
let (merchant_id, connector_label) = path.into_inner();
|
let (merchant_id, connector_name) = path.into_inner();
|
||||||
|
|
||||||
api::server_wrap(
|
api::server_wrap(
|
||||||
flow,
|
flow,
|
||||||
@ -28,7 +28,7 @@ pub async fn receive_incoming_webhook<W: types::OutgoingWebhookType>(
|
|||||||
&req,
|
&req,
|
||||||
auth.merchant_account,
|
auth.merchant_account,
|
||||||
auth.key_store,
|
auth.key_store,
|
||||||
&connector_label,
|
&connector_name,
|
||||||
body,
|
body,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|||||||
@ -11,7 +11,7 @@ use super::ConnectorCommon;
|
|||||||
use crate::{
|
use crate::{
|
||||||
core::errors::{self, CustomResult},
|
core::errors::{self, CustomResult},
|
||||||
db::StorageInterface,
|
db::StorageInterface,
|
||||||
services,
|
logger, services,
|
||||||
types::domain,
|
types::domain,
|
||||||
utils::crypto,
|
utils::crypto,
|
||||||
};
|
};
|
||||||
@ -79,32 +79,28 @@ pub trait IncomingWebhook: ConnectorCommon + Sync {
|
|||||||
&self,
|
&self,
|
||||||
db: &dyn StorageInterface,
|
db: &dyn StorageInterface,
|
||||||
merchant_id: &str,
|
merchant_id: &str,
|
||||||
connector_label: &str,
|
connector_name: &str,
|
||||||
key_store: &domain::MerchantKeyStore,
|
key_store: &domain::MerchantKeyStore,
|
||||||
) -> CustomResult<Vec<u8>, errors::ConnectorError> {
|
) -> CustomResult<Vec<u8>, errors::ConnectorError> {
|
||||||
let debug_suffix = format!(
|
let debug_suffix = format!(
|
||||||
"For merchant_id: {}, and connector_label: {}",
|
"For merchant_id: {}, and connector_name: {}",
|
||||||
merchant_id, connector_label
|
merchant_id, connector_name
|
||||||
);
|
);
|
||||||
let merchant_connector_webhook_details = db
|
let default_secret = "default_secret".to_string();
|
||||||
.find_merchant_connector_account_by_merchant_id_connector_label(
|
let merchant_connector_account_result = db
|
||||||
|
.find_merchant_connector_account_by_merchant_id_connector_name(
|
||||||
merchant_id,
|
merchant_id,
|
||||||
connector_label,
|
connector_name,
|
||||||
key_store,
|
key_store,
|
||||||
)
|
)
|
||||||
.await
|
.await;
|
||||||
.change_context(errors::ConnectorError::WebhookSourceVerificationFailed)
|
|
||||||
.attach_printable_lazy(|| {
|
|
||||||
format!(
|
|
||||||
"Fetch merchant_webhook_secret from MCA table failed {}",
|
|
||||||
debug_suffix
|
|
||||||
)
|
|
||||||
})?
|
|
||||||
.connector_webhook_details;
|
|
||||||
|
|
||||||
let merchant_secret = match merchant_connector_webhook_details {
|
let merchant_secret = match merchant_connector_account_result {
|
||||||
|
Ok(mca) => match mca.connector_webhook_details {
|
||||||
Some(merchant_connector_webhook_details) => merchant_connector_webhook_details
|
Some(merchant_connector_webhook_details) => merchant_connector_webhook_details
|
||||||
.parse_value::<MerchantConnectorWebhookDetails>("MerchantConnectorWebhookDetails")
|
.parse_value::<MerchantConnectorWebhookDetails>(
|
||||||
|
"MerchantConnectorWebhookDetails",
|
||||||
|
)
|
||||||
.change_context_lazy(|| errors::ConnectorError::WebhookSourceVerificationFailed)
|
.change_context_lazy(|| errors::ConnectorError::WebhookSourceVerificationFailed)
|
||||||
.attach_printable_lazy(|| {
|
.attach_printable_lazy(|| {
|
||||||
format!(
|
format!(
|
||||||
@ -114,8 +110,18 @@ pub trait IncomingWebhook: ConnectorCommon + Sync {
|
|||||||
})?
|
})?
|
||||||
.merchant_secret
|
.merchant_secret
|
||||||
.expose(),
|
.expose(),
|
||||||
None => "default_secret".to_string(),
|
None => default_secret,
|
||||||
|
},
|
||||||
|
Err(err) => {
|
||||||
|
logger::error!(
|
||||||
|
"Failed to fetch merchant_secret for source verification {}",
|
||||||
|
debug_suffix
|
||||||
|
);
|
||||||
|
logger::error!("DB error = {:?}", err);
|
||||||
|
default_secret
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//need to fetch merchant secret from config table with caching in future for enhanced performance
|
//need to fetch merchant secret from config table with caching in future for enhanced performance
|
||||||
|
|
||||||
//If merchant has not set the secret for webhook source verification, "default_secret" is returned.
|
//If merchant has not set the secret for webhook source verification, "default_secret" is returned.
|
||||||
|
|||||||
Reference in New Issue
Block a user