mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-29 09:07:09 +08:00
Call multiple connectors (#90)
This commit is contained in:
@ -25,6 +25,7 @@ use crate::{
|
||||
payments,
|
||||
},
|
||||
db::StorageInterface,
|
||||
logger,
|
||||
pii::Email,
|
||||
routes::AppState,
|
||||
scheduler::utils as pt_utils,
|
||||
@ -296,16 +297,17 @@ where
|
||||
let router_data = payment_data
|
||||
.construct_router_data(state, connector.connector.id(), merchant_account)
|
||||
.await?;
|
||||
let (res, payment_data) = router_data
|
||||
|
||||
let res = router_data
|
||||
.decide_flows(
|
||||
state,
|
||||
connector,
|
||||
customer,
|
||||
payment_data,
|
||||
call_connector_action,
|
||||
merchant_account.storage_scheme,
|
||||
)
|
||||
.await;
|
||||
|
||||
let response = helpers::amap(res, |response| async {
|
||||
let operation = helpers::response_operation::<F, Req>();
|
||||
let payment_data = operation
|
||||
@ -329,6 +331,84 @@ where
|
||||
Ok(response)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
async fn call_multiple_connectors_service<F, Op, Req>(
|
||||
state: &AppState,
|
||||
merchant_account: &storage::MerchantAccount,
|
||||
connectors: Vec<api::ConnectorData>,
|
||||
_operation: &Op,
|
||||
mut payment_data: PaymentData<F>,
|
||||
customer: &Option<storage::Customer>,
|
||||
) -> RouterResult<PaymentData<F>>
|
||||
where
|
||||
Op: Debug,
|
||||
F: Send + Clone,
|
||||
|
||||
// To create connector flow specific interface data
|
||||
PaymentData<F>: ConstructFlowSpecificData<F, Req, types::PaymentsResponseData>,
|
||||
types::RouterData<F, Req, types::PaymentsResponseData>: Feature<F, Req>,
|
||||
|
||||
// To construct connector flow specific api
|
||||
dyn api::Connector: services::api::ConnectorIntegration<F, Req, types::PaymentsResponseData>,
|
||||
|
||||
// To perform router related operation for PaymentResponse
|
||||
PaymentResponse: Operation<F, Req>,
|
||||
{
|
||||
let call_connectors_start_time = Instant::now();
|
||||
let mut router_data_list = Vec::with_capacity(connectors.len());
|
||||
|
||||
for connector in connectors {
|
||||
let connector_id = connector.connector.id();
|
||||
let router_data = payment_data
|
||||
.construct_router_data(state, connector_id, merchant_account)
|
||||
.await?;
|
||||
|
||||
router_data_list.push((connector, router_data));
|
||||
}
|
||||
|
||||
for (connector, router_data) in router_data_list {
|
||||
let connector_name = connector.connector_name.to_owned().to_string();
|
||||
let res = router_data
|
||||
.decide_flows(
|
||||
state,
|
||||
connector,
|
||||
customer,
|
||||
CallConnectorAction::Trigger,
|
||||
merchant_account.storage_scheme,
|
||||
)
|
||||
.await?;
|
||||
|
||||
match res.response {
|
||||
Ok(connector_response) => {
|
||||
if let types::PaymentsResponseData::SessionResponse { session_token } =
|
||||
connector_response
|
||||
{
|
||||
payment_data
|
||||
.sessions_token
|
||||
.push(types::ConnectorSessionToken {
|
||||
connector_name,
|
||||
session_token,
|
||||
});
|
||||
}
|
||||
}
|
||||
Err(connector_error) => {
|
||||
logger::debug!(
|
||||
"sessions_connector_error {} {:?}",
|
||||
connector_name,
|
||||
connector_error
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let call_connectors_end_time = Instant::now();
|
||||
let call_connectors_duration =
|
||||
call_connectors_end_time.saturating_duration_since(call_connectors_start_time);
|
||||
tracing::info!(duration = format!("Duration taken: {}", call_connectors_duration.as_millis()));
|
||||
|
||||
Ok(payment_data)
|
||||
}
|
||||
|
||||
pub enum CallConnectorAction {
|
||||
Trigger,
|
||||
Avoid,
|
||||
@ -361,6 +441,7 @@ where
|
||||
pub force_sync: Option<bool>,
|
||||
pub payment_method_data: Option<api::PaymentMethod>,
|
||||
pub refunds: Vec<storage::Refund>,
|
||||
pub sessions_token: Vec<types::ConnectorSessionToken>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
||||
@ -7,7 +7,6 @@ mod verfiy_flow;
|
||||
|
||||
use async_trait::async_trait;
|
||||
|
||||
use super::PaymentData;
|
||||
use crate::{
|
||||
core::{errors::RouterResult, payments},
|
||||
routes::AppState,
|
||||
@ -35,10 +34,9 @@ pub trait Feature<F, T> {
|
||||
state: &AppState,
|
||||
connector: api::ConnectorData,
|
||||
maybe_customer: &Option<storage::Customer>,
|
||||
payment_data: PaymentData<F>,
|
||||
call_connector_action: payments::CallConnectorAction,
|
||||
storage_scheme: enums::MerchantStorageScheme,
|
||||
) -> (RouterResult<Self>, PaymentData<F>)
|
||||
) -> RouterResult<Self>
|
||||
where
|
||||
Self: std::marker::Sized,
|
||||
F: Clone,
|
||||
|
||||
@ -57,17 +57,9 @@ impl Feature<api::Authorize, types::PaymentsAuthorizeData> for types::PaymentsAu
|
||||
state: &AppState,
|
||||
connector: api::ConnectorData,
|
||||
customer: &Option<storage::Customer>,
|
||||
payment_data: PaymentData<api::Authorize>,
|
||||
call_connector_action: payments::CallConnectorAction,
|
||||
storage_scheme: storage_enums::MerchantStorageScheme,
|
||||
) -> (RouterResult<Self>, PaymentData<api::Authorize>)
|
||||
where
|
||||
dyn api::Connector: services::ConnectorIntegration<
|
||||
api::Authorize,
|
||||
types::PaymentsAuthorizeData,
|
||||
types::PaymentsResponseData,
|
||||
>,
|
||||
{
|
||||
) -> RouterResult<Self> {
|
||||
let resp = self
|
||||
.decide_flow(
|
||||
state,
|
||||
@ -81,7 +73,7 @@ impl Feature<api::Authorize, types::PaymentsAuthorizeData> for types::PaymentsAu
|
||||
|
||||
metrics::PAYMENT_COUNT.add(&metrics::CONTEXT, 1, &[]); // Metrics
|
||||
|
||||
(resp, payment_data)
|
||||
resp
|
||||
}
|
||||
}
|
||||
|
||||
@ -94,14 +86,7 @@ impl PaymentsAuthorizeRouterData {
|
||||
confirm: Option<bool>,
|
||||
call_connector_action: payments::CallConnectorAction,
|
||||
_storage_scheme: storage_enums::MerchantStorageScheme,
|
||||
) -> RouterResult<PaymentsAuthorizeRouterData>
|
||||
where
|
||||
dyn api::Connector + Sync: services::ConnectorIntegration<
|
||||
api::Authorize,
|
||||
PaymentsAuthorizeData,
|
||||
PaymentsResponseData,
|
||||
>,
|
||||
{
|
||||
) -> RouterResult<PaymentsAuthorizeRouterData> {
|
||||
match confirm {
|
||||
Some(true) => {
|
||||
let connector_integration: services::BoxedConnectorIntegration<
|
||||
|
||||
@ -44,28 +44,17 @@ impl Feature<api::Void, types::PaymentsCancelData>
|
||||
state: &AppState,
|
||||
connector: api::ConnectorData,
|
||||
customer: &Option<storage::Customer>,
|
||||
payment_data: PaymentData<api::Void>,
|
||||
call_connector_action: payments::CallConnectorAction,
|
||||
_storage_scheme: enums::MerchantStorageScheme,
|
||||
) -> (RouterResult<Self>, PaymentData<api::Void>)
|
||||
where
|
||||
dyn api::Connector: services::ConnectorIntegration<
|
||||
api::Void,
|
||||
types::PaymentsCancelData,
|
||||
types::PaymentsResponseData,
|
||||
>,
|
||||
{
|
||||
let resp = self
|
||||
.decide_flow(
|
||||
) -> RouterResult<Self> {
|
||||
self.decide_flow(
|
||||
state,
|
||||
connector,
|
||||
customer,
|
||||
Some(true),
|
||||
call_connector_action,
|
||||
)
|
||||
.await;
|
||||
|
||||
(resp, payment_data)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,14 +67,7 @@ impl PaymentsCancelRouterData {
|
||||
_maybe_customer: &Option<storage::Customer>,
|
||||
_confirm: Option<bool>,
|
||||
call_connector_action: payments::CallConnectorAction,
|
||||
) -> RouterResult<PaymentsCancelRouterData>
|
||||
where
|
||||
dyn api::Connector + Sync: services::ConnectorIntegration<
|
||||
api::Void,
|
||||
types::PaymentsCancelData,
|
||||
PaymentsResponseData,
|
||||
>,
|
||||
{
|
||||
) -> RouterResult<PaymentsCancelRouterData> {
|
||||
let connector_integration: services::BoxedConnectorIntegration<
|
||||
api::Void,
|
||||
types::PaymentsCancelData,
|
||||
|
||||
@ -45,28 +45,17 @@ impl Feature<api::Capture, types::PaymentsCaptureData>
|
||||
state: &AppState,
|
||||
connector: api::ConnectorData,
|
||||
customer: &Option<storage::Customer>,
|
||||
payment_data: PaymentData<api::Capture>,
|
||||
call_connector_action: payments::CallConnectorAction,
|
||||
_storage_scheme: enums::MerchantStorageScheme,
|
||||
) -> (RouterResult<Self>, PaymentData<api::Capture>)
|
||||
where
|
||||
dyn api::Connector: services::ConnectorIntegration<
|
||||
api::Capture,
|
||||
types::PaymentsCaptureData,
|
||||
types::PaymentsResponseData,
|
||||
>,
|
||||
{
|
||||
let resp = self
|
||||
.decide_flow(
|
||||
) -> RouterResult<Self> {
|
||||
self.decide_flow(
|
||||
state,
|
||||
connector,
|
||||
customer,
|
||||
Some(true),
|
||||
call_connector_action,
|
||||
)
|
||||
.await;
|
||||
|
||||
(resp, payment_data)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,11 +68,7 @@ impl PaymentsCaptureRouterData {
|
||||
_maybe_customer: &Option<storage::Customer>,
|
||||
_confirm: Option<bool>,
|
||||
call_connector_action: payments::CallConnectorAction,
|
||||
) -> RouterResult<PaymentsCaptureRouterData>
|
||||
where
|
||||
dyn api::Connector + Sync:
|
||||
services::ConnectorIntegration<api::Capture, PaymentsCaptureData, PaymentsResponseData>,
|
||||
{
|
||||
) -> RouterResult<PaymentsCaptureRouterData> {
|
||||
let connector_integration: services::BoxedConnectorIntegration<
|
||||
api::Capture,
|
||||
PaymentsCaptureData,
|
||||
|
||||
@ -46,28 +46,17 @@ impl Feature<api::PSync, types::PaymentsSyncData>
|
||||
state: &AppState,
|
||||
connector: api::ConnectorData,
|
||||
customer: &Option<storage::Customer>,
|
||||
payment_data: PaymentData<api::PSync>,
|
||||
call_connector_action: payments::CallConnectorAction,
|
||||
_storage_scheme: enums::MerchantStorageScheme,
|
||||
) -> (RouterResult<Self>, PaymentData<api::PSync>)
|
||||
where
|
||||
dyn api::Connector: services::ConnectorIntegration<
|
||||
api::PSync,
|
||||
types::PaymentsSyncData,
|
||||
types::PaymentsResponseData,
|
||||
>,
|
||||
{
|
||||
let resp = self
|
||||
.decide_flow(
|
||||
) -> RouterResult<Self> {
|
||||
self.decide_flow(
|
||||
state,
|
||||
connector,
|
||||
customer,
|
||||
Some(true),
|
||||
call_connector_action,
|
||||
)
|
||||
.await;
|
||||
|
||||
(resp, payment_data)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,11 +68,7 @@ impl PaymentsSyncRouterData {
|
||||
_maybe_customer: &Option<storage::Customer>,
|
||||
_confirm: Option<bool>,
|
||||
call_connector_action: payments::CallConnectorAction,
|
||||
) -> RouterResult<PaymentsSyncRouterData>
|
||||
where
|
||||
dyn api::Connector + Sync:
|
||||
services::ConnectorIntegration<api::PSync, PaymentsSyncData, PaymentsResponseData>,
|
||||
{
|
||||
) -> RouterResult<PaymentsSyncRouterData> {
|
||||
let connector_integration: services::BoxedConnectorIntegration<
|
||||
api::PSync,
|
||||
PaymentsSyncData,
|
||||
|
||||
@ -41,21 +41,17 @@ impl Feature<api::Session, types::PaymentsSessionData> for types::PaymentsSessio
|
||||
state: &routes::AppState,
|
||||
connector: api::ConnectorData,
|
||||
customer: &Option<storage::Customer>,
|
||||
payment_data: PaymentData<api::Session>,
|
||||
call_connector_action: payments::CallConnectorAction,
|
||||
_storage_schema: enums::MerchantStorageScheme,
|
||||
) -> (RouterResult<Self>, PaymentData<api::Session>) {
|
||||
let resp = self
|
||||
.decide_flow(
|
||||
) -> RouterResult<Self> {
|
||||
self.decide_flow(
|
||||
state,
|
||||
connector,
|
||||
customer,
|
||||
Some(true),
|
||||
call_connector_action,
|
||||
)
|
||||
.await;
|
||||
|
||||
(resp, payment_data)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,14 +63,7 @@ impl types::PaymentsSessionRouterData {
|
||||
_customer: &Option<storage::Customer>,
|
||||
_confirm: Option<bool>,
|
||||
call_connector_action: payments::CallConnectorAction,
|
||||
) -> RouterResult<types::PaymentsSessionRouterData>
|
||||
where
|
||||
dyn api::Connector + Sync: services::ConnectorIntegration<
|
||||
api::Session,
|
||||
types::PaymentsSessionData,
|
||||
types::PaymentsResponseData,
|
||||
>,
|
||||
{
|
||||
) -> RouterResult<types::PaymentsSessionRouterData> {
|
||||
let connector_integration: services::BoxedConnectorIntegration<
|
||||
api::Session,
|
||||
types::PaymentsSessionData,
|
||||
|
||||
@ -45,19 +45,10 @@ impl Feature<api::Verify, types::VerifyRequestData> for types::VerifyRouterData
|
||||
state: &AppState,
|
||||
connector: api::ConnectorData,
|
||||
customer: &Option<storage::Customer>,
|
||||
payment_data: PaymentData<api::Verify>,
|
||||
call_connector_action: payments::CallConnectorAction,
|
||||
storage_scheme: enums::MerchantStorageScheme,
|
||||
) -> (RouterResult<Self>, PaymentData<api::Verify>)
|
||||
where
|
||||
dyn api::Connector: services::ConnectorIntegration<
|
||||
api::Verify,
|
||||
types::VerifyRequestData,
|
||||
types::PaymentsResponseData,
|
||||
>,
|
||||
{
|
||||
let resp = self
|
||||
.decide_flow(
|
||||
) -> RouterResult<Self> {
|
||||
self.decide_flow(
|
||||
state,
|
||||
connector,
|
||||
customer,
|
||||
@ -65,9 +56,7 @@ impl Feature<api::Verify, types::VerifyRequestData> for types::VerifyRouterData
|
||||
call_connector_action,
|
||||
storage_scheme,
|
||||
)
|
||||
.await;
|
||||
|
||||
(resp, payment_data)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,14 +69,7 @@ impl types::VerifyRouterData {
|
||||
confirm: Option<bool>,
|
||||
call_connector_action: payments::CallConnectorAction,
|
||||
_storage_scheme: enums::MerchantStorageScheme,
|
||||
) -> RouterResult<Self>
|
||||
where
|
||||
dyn api::Connector + Sync: services::ConnectorIntegration<
|
||||
api::Verify,
|
||||
types::VerifyRequestData,
|
||||
types::PaymentsResponseData,
|
||||
>,
|
||||
{
|
||||
) -> RouterResult<Self> {
|
||||
match confirm {
|
||||
Some(true) => {
|
||||
let connector_integration: services::BoxedConnectorIntegration<
|
||||
|
||||
@ -106,6 +106,7 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsCancelRequest>
|
||||
force_sync: None,
|
||||
refunds: vec![],
|
||||
connector_response,
|
||||
sessions_token: vec![],
|
||||
},
|
||||
None,
|
||||
)),
|
||||
|
||||
@ -134,6 +134,7 @@ impl<F: Send + Clone> GetTracker<F, payments::PaymentData<F>, api::PaymentsCaptu
|
||||
payment_method_data: None,
|
||||
refunds: vec![],
|
||||
connector_response,
|
||||
sessions_token: vec![],
|
||||
},
|
||||
None,
|
||||
))
|
||||
|
||||
@ -151,6 +151,7 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa
|
||||
payment_method_data: request.payment_method_data.clone(),
|
||||
force_sync: None,
|
||||
refunds: vec![],
|
||||
sessions_token: vec![],
|
||||
},
|
||||
Some(CustomerDetails {
|
||||
customer_id: request.customer_id.clone(),
|
||||
|
||||
@ -192,6 +192,7 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa
|
||||
refunds: vec![],
|
||||
force_sync: None,
|
||||
connector_response,
|
||||
sessions_token: vec![],
|
||||
},
|
||||
Some(CustomerDetails {
|
||||
customer_id: request.customer_id.clone(),
|
||||
|
||||
@ -145,6 +145,7 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::VerifyRequest> for Paym
|
||||
address: types::PaymentAddress::default(),
|
||||
force_sync: None,
|
||||
refunds: vec![],
|
||||
sessions_token: vec![],
|
||||
},
|
||||
Some(payments::CustomerDetails {
|
||||
customer_id: request.customer_id.clone(),
|
||||
|
||||
@ -131,6 +131,7 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsSessionRequest>
|
||||
payment_method_data: None,
|
||||
force_sync: None,
|
||||
refunds: vec![],
|
||||
sessions_token: vec![],
|
||||
connector_response,
|
||||
},
|
||||
None,
|
||||
|
||||
@ -137,6 +137,7 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsStartRequest> f
|
||||
payment_method_data: None,
|
||||
force_sync: None,
|
||||
refunds: vec![],
|
||||
sessions_token: vec![],
|
||||
},
|
||||
Some(customer_details),
|
||||
)),
|
||||
|
||||
@ -209,6 +209,7 @@ async fn get_tracker_for_sync<
|
||||
payment_method_data: None,
|
||||
force_sync: Some(request.force_sync),
|
||||
refunds,
|
||||
sessions_token: vec![],
|
||||
},
|
||||
None,
|
||||
))
|
||||
|
||||
@ -156,6 +156,7 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa
|
||||
force_sync: None,
|
||||
refunds: vec![],
|
||||
connector_response,
|
||||
sessions_token: vec![],
|
||||
},
|
||||
Some(CustomerDetails {
|
||||
customer_id: request.customer_id.clone(),
|
||||
|
||||
@ -122,6 +122,12 @@ pub struct PaymentsSessionData {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ConnectorSessionToken {
|
||||
pub connector_name: String,
|
||||
pub session_token: String,
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize, Debug)]
|
||||
pub struct PaymentsSessionResponseData {
|
||||
pub client_token: Option<String>,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user