refactor(core): introduce an interface to switch between old and new connector integration implementations on the connectors (#5013)

Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
This commit is contained in:
Hrithikesh
2024-06-24 15:10:34 +05:30
committed by GitHub
parent b87840595d
commit e658899c14
103 changed files with 2153 additions and 683 deletions

View File

@ -1,5 +1,6 @@
use common_utils::ext_traits::ValueExt;
use error_stack::ResultExt;
use hyperswitch_domain_models::router_data_v2::ExternalAuthenticationFlowData;
use crate::{
consts,
@ -241,11 +242,16 @@ where
Res: std::fmt::Debug + Clone + 'static,
F: std::fmt::Debug + Clone + 'static,
dyn api::Connector + Sync: services::api::ConnectorIntegration<F, Req, Res>,
dyn api::ConnectorV2 + Sync:
services::api::ConnectorIntegrationV2<F, ExternalAuthenticationFlowData, Req, Res>,
{
let connector_data =
api::AuthenticationConnectorData::get_connector_by_name(&authentication_connector_name)?;
let connector_integration: services::BoxedConnectorIntegration<'_, F, Req, Res> =
connector_data.connector.get_connector_integration();
let connector_integration: services::BoxedExternalAuthenticationConnectorIntegrationInterface<
F,
Req,
Res,
> = connector_data.connector.get_connector_integration();
let router_data = execute_connector_processing_step(
state,
connector_integration,

View File

@ -110,8 +110,7 @@ pub async fn accept_dispute(
api::GetToken::Connector,
dispute.merchant_connector_id.clone(),
)?;
let connector_integration: services::BoxedConnectorIntegration<
'_,
let connector_integration: services::BoxedDisputeConnectorIntegrationInterface<
api::Accept,
AcceptDisputeRequestData,
AcceptDisputeResponse,
@ -225,8 +224,7 @@ pub async fn submit_evidence(
dispute.merchant_connector_id.clone(),
)?;
let connector_integration: services::BoxedConnectorIntegration<
'_,
let connector_integration: services::BoxedDisputeConnectorIntegrationInterface<
api::Evidence,
SubmitEvidenceRequestData,
SubmitEvidenceResponse,
@ -262,52 +260,53 @@ pub async fn submit_evidence(
reason: err.reason,
})?;
//Defend Dispute Optionally if connector expects to defend / submit evidence in a separate api call
let (dispute_status, connector_status) =
if connector_data.connector_name.requires_defend_dispute() {
let connector_integration_defend_dispute: services::BoxedConnectorIntegration<
'_,
let (dispute_status, connector_status) = if connector_data
.connector_name
.requires_defend_dispute()
{
let connector_integration_defend_dispute: services::BoxedDisputeConnectorIntegrationInterface<
api::Defend,
DefendDisputeRequestData,
DefendDisputeResponse,
> = connector_data.connector.get_connector_integration();
let defend_dispute_router_data = core_utils::construct_defend_dispute_router_data(
&state,
&payment_intent,
&payment_attempt,
&merchant_account,
&key_store,
&dispute,
)
.await?;
let defend_response = services::execute_connector_processing_step(
&state,
connector_integration_defend_dispute,
&defend_dispute_router_data,
payments::CallConnectorAction::Trigger,
None,
)
.await
.to_dispute_failed_response()
.attach_printable("Failed while calling defend dispute connector api")?;
let defend_dispute_response = defend_response.response.map_err(|err| {
errors::ApiErrorResponse::ExternalConnectorError {
code: err.code,
message: err.message,
connector: dispute.connector.clone(),
status_code: err.status_code,
reason: err.reason,
}
})?;
(
defend_dispute_response.dispute_status,
defend_dispute_response.connector_status,
)
} else {
(
submit_evidence_response.dispute_status,
submit_evidence_response.connector_status,
)
};
let defend_dispute_router_data = core_utils::construct_defend_dispute_router_data(
&state,
&payment_intent,
&payment_attempt,
&merchant_account,
&key_store,
&dispute,
)
.await?;
let defend_response = services::execute_connector_processing_step(
&state,
connector_integration_defend_dispute,
&defend_dispute_router_data,
payments::CallConnectorAction::Trigger,
None,
)
.await
.to_dispute_failed_response()
.attach_printable("Failed while calling defend dispute connector api")?;
let defend_dispute_response = defend_response.response.map_err(|err| {
errors::ApiErrorResponse::ExternalConnectorError {
code: err.code,
message: err.message,
connector: dispute.connector.clone(),
status_code: err.status_code,
reason: err.reason,
}
})?;
(
defend_dispute_response.dispute_status,
defend_dispute_response.connector_status,
)
} else {
(
submit_evidence_response.dispute_status,
submit_evidence_response.connector_status,
)
};
let update_dispute = diesel_models::dispute::DisputeUpdate::StatusUpdate {
dispute_status,
connector_status,

View File

@ -131,8 +131,7 @@ pub async fn retrieve_file_from_connector(
api::GetToken::Connector,
file_metadata.merchant_connector_id.clone(),
)?;
let connector_integration: services::BoxedConnectorIntegration<
'_,
let connector_integration: services::BoxedFilesConnectorIntegrationInterface<
api::Retrieve,
types::RetrieveFileRequestData,
types::RetrieveFileResponse,
@ -279,8 +278,7 @@ pub async fn upload_and_get_provider_provider_file_id_profile_id(
.await
.change_context(errors::ApiErrorResponse::PaymentNotFound)?;
let connector_integration: services::BoxedConnectorIntegration<
'_,
let connector_integration: services::BoxedFilesConnectorIntegrationInterface<
api::Upload,
types::UploadFileRequestData,
types::UploadFileResponse,

View File

@ -723,8 +723,7 @@ pub async fn make_fulfillment_api_call(
.await
.change_context(errors::ApiErrorResponse::PaymentNotFound)?;
let connector_data = FraudCheckConnectorData::get_connector_by_name(&fraud_check.frm_name)?;
let connector_integration: services::BoxedConnectorIntegration<
'_,
let connector_integration: services::BoxedFrmConnectorIntegrationInterface<
Fulfillment,
frm_types::FraudCheckFulfillmentData,
frm_types::FraudCheckResponseData,

View File

@ -163,8 +163,7 @@ pub async fn decide_frm_flow<'a, 'b>(
call_connector_action: payments::CallConnectorAction,
_merchant_account: &domain::MerchantAccount,
) -> RouterResult<FrmCheckoutRouterData> {
let connector_integration: services::BoxedConnectorIntegration<
'_,
let connector_integration: services::BoxedFrmConnectorIntegrationInterface<
frm_api::Checkout,
FraudCheckCheckoutData,
FraudCheckResponseData,

View File

@ -135,8 +135,7 @@ pub async fn decide_frm_flow<'a, 'b>(
call_connector_action: payments::CallConnectorAction,
_merchant_account: &domain::MerchantAccount,
) -> RouterResult<FrmRecordReturnRouterData> {
let connector_integration: services::BoxedConnectorIntegration<
'_,
let connector_integration: services::BoxedFrmConnectorIntegrationInterface<
RecordReturn,
FraudCheckRecordReturnData,
FraudCheckResponseData,

View File

@ -144,8 +144,7 @@ pub async fn decide_frm_flow<'a, 'b>(
call_connector_action: payments::CallConnectorAction,
_merchant_account: &domain::MerchantAccount,
) -> RouterResult<FrmSaleRouterData> {
let connector_integration: services::BoxedConnectorIntegration<
'_,
let connector_integration: services::BoxedFrmConnectorIntegrationInterface<
frm_api::Sale,
FraudCheckSaleData,
FraudCheckResponseData,

View File

@ -148,8 +148,7 @@ pub async fn decide_frm_flow<'a, 'b>(
call_connector_action: payments::CallConnectorAction,
_merchant_account: &domain::MerchantAccount,
) -> RouterResult<FrmTransactionRouterData> {
let connector_integration: services::BoxedConnectorIntegration<
'_,
let connector_integration: services::BoxedFrmConnectorIntegrationInterface<
frm_api::Transaction,
FraudCheckTransactionData,
FraudCheckResponseData,

View File

@ -103,8 +103,7 @@ pub async fn revoke_mandate(
GetToken::Connector,
mandate.merchant_connector_id.clone(),
)?;
let connector_integration: services::BoxedConnectorIntegration<
'_,
let connector_integration: services::BoxedMandateRevokeConnectorIntegrationInterface<
types::api::MandateRevoke,
types::MandateRevokeRequestData,
types::MandateRevokeResponseData,

View File

@ -79,10 +79,10 @@ use crate::{
db::StorageInterface,
logger,
routes::{app::ReqState, metrics, payment_methods::ParentPaymentMethodToken, SessionState},
services::{self, api::Authenticate},
services::{self, api::Authenticate, ConnectorRedirectResponse},
types::{
self as router_types,
api::{self, authentication, ConnectorCallType},
api::{self, authentication, ConnectorCallType, ConnectorCommon},
domain,
storage::{self, enums as storage_enums, payment_attempt::PaymentAttemptExt},
transformers::{ForeignInto, ForeignTryInto},

View File

@ -200,8 +200,7 @@ pub async fn refresh_connector_auth(
types::AccessToken,
>,
) -> RouterResult<Result<types::AccessToken, types::ErrorResponse>> {
let connector_integration: services::BoxedConnectorIntegration<
'_,
let connector_integration: services::BoxedAccessTokenConnectorIntegrationInterface<
api_types::AccessTokenAuth,
types::AccessTokenRequestData,
types::AccessToken,

View File

@ -18,8 +18,7 @@ pub async fn create_connector_customer<F: Clone, T: Clone>(
router_data: &types::RouterData<F, T, types::PaymentsResponseData>,
customer_request_data: types::ConnectorCustomerData,
) -> RouterResult<Option<String>> {
let connector_integration: services::BoxedConnectorIntegration<
'_,
let connector_integration: services::BoxedPaymentConnectorIntegrationInterface<
api::CreateConnectorCustomer,
types::ConnectorCustomerData,
types::PaymentsResponseData,

View File

@ -14,6 +14,7 @@ use crate::{
logger,
routes::{metrics, SessionState},
services,
services::api::ConnectorValidation,
types::{self, api, domain, storage, transformers::ForeignFrom},
};
@ -65,8 +66,7 @@ impl Feature<api::Authorize, types::PaymentsAuthorizeData> for types::PaymentsAu
connector_request: Option<services::Request>,
_business_profile: &storage::business_profile::BusinessProfile,
) -> RouterResult<Self> {
let connector_integration: services::BoxedConnectorIntegration<
'_,
let connector_integration: services::BoxedPaymentConnectorIntegrationInterface<
api::Authorize,
types::PaymentsAuthorizeData,
types::PaymentsResponseData,
@ -111,8 +111,7 @@ impl Feature<api::Authorize, types::PaymentsAuthorizeData> for types::PaymentsAu
where
Self: Sized,
{
let connector_integration: services::BoxedConnectorIntegration<
'_,
let connector_integration: services::BoxedPaymentConnectorIntegrationInterface<
api::AuthorizeSessionToken,
types::AuthorizeSessionTokenData,
types::PaymentsResponseData,
@ -202,8 +201,7 @@ impl Feature<api::Authorize, types::PaymentsAuthorizeData> for types::PaymentsAu
.to_payment_failed_response()?;
}
let connector_integration: services::BoxedConnectorIntegration<
'_,
let connector_integration: services::BoxedPaymentConnectorIntegrationInterface<
api::Authorize,
types::PaymentsAuthorizeData,
types::PaymentsResponseData,
@ -300,8 +298,7 @@ pub async fn authorize_preprocessing_steps<F: Clone>(
connector: &api::ConnectorData,
) -> RouterResult<types::RouterData<F, types::PaymentsAuthorizeData, types::PaymentsResponseData>> {
if confirm {
let connector_integration: services::BoxedConnectorIntegration<
'_,
let connector_integration: services::BoxedPaymentConnectorIntegrationInterface<
api::PreProcessing,
types::PaymentsPreProcessingData,
types::PaymentsResponseData,

View File

@ -59,8 +59,7 @@ impl Feature<api::Void, types::PaymentsCancelData>
&add_attributes([("connector", connector.connector_name.to_string())]),
);
let connector_integration: services::BoxedConnectorIntegration<
'_,
let connector_integration: services::BoxedPaymentConnectorIntegrationInterface<
api::Void,
types::PaymentsCancelData,
types::PaymentsResponseData,
@ -98,8 +97,7 @@ impl Feature<api::Void, types::PaymentsCancelData>
) -> RouterResult<(Option<services::Request>, bool)> {
let request = match call_connector_action {
payments::CallConnectorAction::Trigger => {
let connector_integration: services::BoxedConnectorIntegration<
'_,
let connector_integration: services::BoxedPaymentConnectorIntegrationInterface<
api::Void,
types::PaymentsCancelData,
types::PaymentsResponseData,

View File

@ -53,8 +53,7 @@ impl Feature<api::Capture, types::PaymentsCaptureData>
connector_request: Option<services::Request>,
_business_profile: &storage::business_profile::BusinessProfile,
) -> RouterResult<Self> {
let connector_integration: services::BoxedConnectorIntegration<
'_,
let connector_integration: services::BoxedPaymentConnectorIntegrationInterface<
api::Capture,
types::PaymentsCaptureData,
types::PaymentsResponseData,
@ -92,8 +91,7 @@ impl Feature<api::Capture, types::PaymentsCaptureData>
) -> RouterResult<(Option<services::Request>, bool)> {
let request = match call_connector_action {
payments::CallConnectorAction::Trigger => {
let connector_integration: services::BoxedConnectorIntegration<
'_,
let connector_integration: services::BoxedPaymentConnectorIntegrationInterface<
api::Capture,
types::PaymentsCaptureData,
types::PaymentsResponseData,

View File

@ -67,8 +67,7 @@ impl Feature<api::CompleteAuthorize, types::CompleteAuthorizeData>
connector_request: Option<services::Request>,
_business_profile: &storage::business_profile::BusinessProfile,
) -> RouterResult<Self> {
let connector_integration: services::BoxedConnectorIntegration<
'_,
let connector_integration: services::BoxedPaymentConnectorIntegrationInterface<
api::CompleteAuthorize,
types::CompleteAuthorizeData,
types::PaymentsResponseData,
@ -128,8 +127,7 @@ impl Feature<api::CompleteAuthorize, types::CompleteAuthorizeData>
) -> RouterResult<(Option<services::Request>, bool)> {
let request = match call_connector_action {
payments::CallConnectorAction::Trigger => {
let connector_integration: services::BoxedConnectorIntegration<
'_,
let connector_integration: services::BoxedPaymentConnectorIntegrationInterface<
api::CompleteAuthorize,
types::CompleteAuthorizeData,
types::PaymentsResponseData,
@ -161,8 +159,7 @@ pub async fn complete_authorize_preprocessing_steps<F: Clone>(
connector: &api::ConnectorData,
) -> RouterResult<types::RouterData<F, types::CompleteAuthorizeData, types::PaymentsResponseData>> {
if confirm {
let connector_integration: services::BoxedConnectorIntegration<
'_,
let connector_integration: services::BoxedPaymentConnectorIntegrationInterface<
api::PreProcessing,
types::PaymentsPreProcessingData,
types::PaymentsResponseData,

View File

@ -60,8 +60,7 @@ impl Feature<api::IncrementalAuthorization, types::PaymentsIncrementalAuthorizat
connector_request: Option<services::Request>,
_business_profile: &storage::business_profile::BusinessProfile,
) -> RouterResult<Self> {
let connector_integration: services::BoxedConnectorIntegration<
'_,
let connector_integration: services::BoxedPaymentConnectorIntegrationInterface<
api::IncrementalAuthorization,
types::PaymentsIncrementalAuthorizationData,
types::PaymentsResponseData,
@ -99,8 +98,7 @@ impl Feature<api::IncrementalAuthorization, types::PaymentsIncrementalAuthorizat
) -> RouterResult<(Option<services::Request>, bool)> {
let request = match call_connector_action {
payments::CallConnectorAction::Trigger => {
let connector_integration: services::BoxedConnectorIntegration<
'_,
let connector_integration: services::BoxedPaymentConnectorIntegrationInterface<
api::IncrementalAuthorization,
types::PaymentsIncrementalAuthorizationData,
types::PaymentsResponseData,

View File

@ -9,7 +9,7 @@ use crate::{
payments::{self, access_token, helpers, transformers, PaymentData},
},
routes::SessionState,
services::{self, logger},
services::{self, api::ConnectorValidation, logger},
types::{self, api, domain, storage},
};
@ -56,8 +56,7 @@ impl Feature<api::PSync, types::PaymentsSyncData>
connector_request: Option<services::Request>,
_business_profile: &storage::business_profile::BusinessProfile,
) -> RouterResult<Self> {
let connector_integration: services::BoxedConnectorIntegration<
'_,
let connector_integration: services::BoxedPaymentConnectorIntegrationInterface<
api::PSync,
types::PaymentsSyncData,
types::PaymentsResponseData,
@ -129,8 +128,7 @@ impl Feature<api::PSync, types::PaymentsSyncData>
);
return Ok((None, false));
}
let connector_integration: services::BoxedConnectorIntegration<
'_,
let connector_integration: services::BoxedPaymentConnectorIntegrationInterface<
api::PSync,
types::PaymentsSyncData,
types::PaymentsResponseData,
@ -157,8 +155,7 @@ where
_state: &SessionState,
_pending_connector_capture_id_list: Vec<String>,
_call_connector_action: payments::CallConnectorAction,
_connector_integration: services::BoxedConnectorIntegration<
'_,
_connector_integration: services::BoxedPaymentConnectorIntegrationInterface<
api::PSync,
types::PaymentsSyncData,
types::PaymentsResponseData,
@ -175,8 +172,7 @@ impl RouterDataPSync
state: &SessionState,
pending_connector_capture_id_list: Vec<String>,
call_connector_action: payments::CallConnectorAction,
connector_integration: services::BoxedConnectorIntegration<
'_,
connector_integration: services::BoxedPaymentConnectorIntegrationInterface<
api::PSync,
types::PaymentsSyncData,
types::PaymentsResponseData,
@ -187,7 +183,7 @@ impl RouterDataPSync
// webhook consume flow, only call connector once. Since there will only be a single event in every webhook
let resp = services::execute_connector_processing_step(
state,
connector_integration.clone(),
connector_integration,
self,
call_connector_action.clone(),
None,
@ -205,7 +201,7 @@ impl RouterDataPSync
types::ResponseId::ConnectorTransactionId(connector_capture_id.clone());
let resp = services::execute_connector_processing_step(
state,
connector_integration.clone(),
connector_integration.clone_box(),
&cloned_router_data,
call_connector_action.clone(),
None,

View File

@ -706,8 +706,7 @@ impl RouterDataSession for types::PaymentsSessionRouterData {
create_paypal_sdk_session_token(state, self, connector, business_profile)
}
api::GetToken::Connector => {
let connector_integration: services::BoxedConnectorIntegration<
'_,
let connector_integration: services::BoxedPaymentConnectorIntegrationInterface<
api::Session,
types::PaymentsSessionData,
types::PaymentsResponseData,

View File

@ -57,8 +57,7 @@ impl Feature<api::SetupMandate, types::SetupMandateRequestData> for types::Setup
connector_request: Option<services::Request>,
_business_profile: &storage::business_profile::BusinessProfile,
) -> RouterResult<Self> {
let connector_integration: services::BoxedConnectorIntegration<
'_,
let connector_integration: services::BoxedPaymentConnectorIntegrationInterface<
api::SetupMandate,
types::SetupMandateRequestData,
types::PaymentsResponseData,
@ -126,8 +125,7 @@ impl Feature<api::SetupMandate, types::SetupMandateRequestData> for types::Setup
) -> RouterResult<(Option<services::Request>, bool)> {
match call_connector_action {
payments::CallConnectorAction::Trigger => {
let connector_integration: services::BoxedConnectorIntegration<
'_,
let connector_integration: services::BoxedPaymentConnectorIntegrationInterface<
api::SetupMandate,
types::SetupMandateRequestData,
types::PaymentsResponseData,

View File

@ -771,8 +771,7 @@ pub async fn add_payment_method_token<F: Clone, T: types::Tokenizable + Clone>(
match tokenization_action {
payments::TokenizationAction::TokenizeInConnector
| payments::TokenizationAction::TokenizeInConnectorAndApplepayPreDecrypt(_) => {
let connector_integration: services::BoxedConnectorIntegration<
'_,
let connector_integration: services::BoxedPaymentConnectorIntegrationInterface<
api::PaymentMethodToken,
types::PaymentMethodTokenizationData,
types::PaymentsResponseData,

View File

@ -26,7 +26,9 @@ use crate::{
routes::{metrics, SessionState},
services::{self, RedirectForm},
types::{
self, api, domain,
self, api,
api::ConnectorTransactionId,
domain,
storage::{self, enums},
transformers::{ForeignFrom, ForeignInto, ForeignTryFrom},
MultipleCaptureRequestData,
@ -1382,7 +1384,7 @@ impl<F: Clone> TryFrom<PaymentAdditionalData<'_, F>>
}
}
impl api::ConnectorTransactionId for Helcim {
impl ConnectorTransactionId for Helcim {
fn connector_transaction_id(
&self,
payment_attempt: storage::PaymentAttempt,
@ -1397,7 +1399,7 @@ impl api::ConnectorTransactionId for Helcim {
}
}
impl api::ConnectorTransactionId for Nexinets {
impl ConnectorTransactionId for Nexinets {
fn connector_transaction_id(
&self,
payment_attempt: storage::PaymentAttempt,

View File

@ -1021,8 +1021,7 @@ pub async fn create_recipient(
.await?;
// 2. Fetch connector integration details
let connector_integration: services::BoxedConnectorIntegration<
'_,
let connector_integration: services::BoxedPayoutConnectorIntegrationInterface<
api::PoRecipient,
types::PayoutsData,
types::PayoutsResponseData,
@ -1031,7 +1030,7 @@ pub async fn create_recipient(
// 3. Call connector service
let router_resp = services::execute_connector_processing_step(
state,
connector_integration.to_owned(),
connector_integration,
&router_data,
payments::CallConnectorAction::Trigger,
None,
@ -1188,8 +1187,7 @@ pub async fn check_payout_eligibility(
.await?;
// 2. Fetch connector integration details
let connector_integration: services::BoxedConnectorIntegration<
'_,
let connector_integration: services::BoxedPayoutConnectorIntegrationInterface<
api::PoEligibility,
types::PayoutsData,
types::PayoutsResponseData,
@ -1374,8 +1372,7 @@ pub async fn create_payout(
.await?;
// 3. Fetch connector integration details
let connector_integration: services::BoxedConnectorIntegration<
'_,
let connector_integration: services::BoxedPayoutConnectorIntegrationInterface<
api::PoCreate,
types::PayoutsData,
types::PayoutsResponseData,
@ -1484,8 +1481,7 @@ async fn complete_payout_quote_steps_if_required<F>(
{
let quote_router_data =
types::PayoutsRouterData::foreign_from((router_data, router_data.request.clone()));
let connector_integration: services::BoxedConnectorIntegration<
'_,
let connector_integration: services::BoxedPayoutConnectorIntegrationInterface<
api::PoQuote,
types::PayoutsData,
types::PayoutsResponseData,
@ -1557,8 +1553,7 @@ pub async fn create_recipient_disburse_account(
.await?;
// 2. Fetch connector integration details
let connector_integration: services::BoxedConnectorIntegration<
'_,
let connector_integration: services::BoxedPayoutConnectorIntegrationInterface<
api::PoRecipientAccount,
types::PayoutsData,
types::PayoutsResponseData,
@ -1643,8 +1638,7 @@ pub async fn cancel_payout(
.await?;
// 2. Fetch connector integration details
let connector_integration: services::BoxedConnectorIntegration<
'_,
let connector_integration: services::BoxedPayoutConnectorIntegrationInterface<
api::PoCancel,
types::PayoutsData,
types::PayoutsResponseData,
@ -1759,8 +1753,7 @@ pub async fn fulfill_payout(
.await?;
// 3. Fetch connector integration details
let connector_integration: services::BoxedConnectorIntegration<
'_,
let connector_integration: services::BoxedPayoutConnectorIntegrationInterface<
api::PoFulfill,
types::PayoutsData,
types::PayoutsResponseData,

View File

@ -55,6 +55,8 @@ pub async fn add_access_token_for_payout<F: Clone + 'static>(
router_data: &types::PayoutsRouterData<F>,
payout_type: Option<enums::PayoutType>,
) -> RouterResult<types::AddAccessTokenResult> {
use crate::types::api::ConnectorCommon;
if connector
.connector_name
.supports_access_token_for_payout(payout_type)
@ -142,8 +144,7 @@ pub async fn refresh_connector_auth(
types::AccessToken,
>,
) -> RouterResult<Result<types::AccessToken, types::ErrorResponse>> {
let connector_integration: services::BoxedConnectorIntegration<
'_,
let connector_integration: services::BoxedAccessTokenConnectorIntegrationInterface<
api_types::AccessTokenAuth,
types::AccessTokenRequestData,
types::AccessToken,

View File

@ -207,8 +207,7 @@ pub async fn trigger_refund_to_gateway(
let router_data_res = if !(add_access_token_result.connector_supports_access_token
&& router_data.access_token.is_none())
{
let connector_integration: services::BoxedConnectorIntegration<
'_,
let connector_integration: services::BoxedRefundConnectorIntegrationInterface<
api::Execute,
types::RefundsData,
types::RefundsResponseData,
@ -491,8 +490,7 @@ pub async fn sync_refund_with_gateway(
let router_data_res = if !(add_access_token_result.connector_supports_access_token
&& router_data.access_token.is_none())
{
let connector_integration: services::BoxedConnectorIntegration<
'_,
let connector_integration: services::BoxedRefundConnectorIntegrationInterface<
api::RSync,
types::RefundsData,
types::RefundsResponseData,

View File

@ -40,7 +40,7 @@ pub async fn verify_connector_credentials(
connector::Stripe::verify(
&state,
types::VerifyConnectorData {
connector: *boxed_connector.connector,
connector: boxed_connector.connector,
connector_auth: req.connector_account_details.foreign_into(),
card_details,
},
@ -50,7 +50,7 @@ pub async fn verify_connector_credentials(
Connector::Paypal => connector::Paypal::get_access_token(
&state,
types::VerifyConnectorData {
connector: *boxed_connector.connector,
connector: boxed_connector.connector,
connector_auth: req.connector_account_details.foreign_into(),
card_details,
},

View File

@ -27,9 +27,12 @@ use crate::{
app::{ReqState, SessionStateInfo},
lock_utils, SessionState,
},
services::{self, authentication as auth},
services::{
self, authentication as auth, connector_integration_interface::ConnectorEnum,
ConnectorValidation,
},
types::{
api::{self, mandates::MandateResponseExt},
api::{self, mandates::MandateResponseExt, ConnectorCommon, IncomingWebhook},
domain,
storage::{self, enums},
transformers::{ForeignFrom, ForeignInto, ForeignTryFrom},
@ -374,7 +377,7 @@ async fn incoming_webhooks_core<W: types::OutgoingWebhookType>(
key_store,
webhook_details,
source_verified,
connector,
&connector,
&request_details,
event_type,
))
@ -416,7 +419,7 @@ async fn incoming_webhooks_core<W: types::OutgoingWebhookType>(
source_verified,
event_type,
&request_details,
connector,
&connector,
object_ref_id,
business_profile,
merchant_connector_account,
@ -968,7 +971,7 @@ async fn external_authentication_incoming_webhook_flow(
source_verified: bool,
event_type: webhooks::IncomingWebhookEvent,
request_details: &api::IncomingWebhookRequestDetails<'_>,
connector: &(dyn api::Connector + Sync),
connector: &ConnectorEnum,
object_ref_id: api::ObjectReferenceId,
business_profile: diesel_models::business_profile::BusinessProfile,
merchant_connector_account: domain::MerchantConnectorAccount,
@ -1342,7 +1345,7 @@ async fn disputes_incoming_webhook_flow(
key_store: domain::MerchantKeyStore,
webhook_details: api::IncomingWebhookDetails,
source_verified: bool,
connector: &(dyn api::Connector + Sync),
connector: &ConnectorEnum,
request_details: &api::IncomingWebhookRequestDetails<'_>,
event_type: webhooks::IncomingWebhookEvent,
) -> CustomResult<WebhookResponseTracker, errors::ApiErrorResponse> {
@ -1535,7 +1538,7 @@ fn get_connector_by_connector_name(
state: &SessionState,
connector_name: &str,
merchant_connector_id: Option<String>,
) -> CustomResult<(&'static (dyn api::Connector + Sync), String), errors::ApiErrorResponse> {
) -> CustomResult<(ConnectorEnum, String), errors::ApiErrorResponse> {
let authentication_connector =
api_models::enums::convert_authentication_connector(connector_name);
#[cfg(feature = "frm")]
@ -1545,7 +1548,7 @@ fn get_connector_by_connector_name(
let frm_connector_data =
api::FraudCheckConnectorData::get_connector_by_name(connector_name)?;
return Ok((
*frm_connector_data.connector,
frm_connector_data.connector,
frm_connector_data.connector_name.to_string(),
));
}
@ -1574,7 +1577,7 @@ fn get_connector_by_connector_name(
connector_data.connector_name.to_string(),
)
};
Ok((*connector, connector_name))
Ok((connector, connector_name))
}
/// This function fetches the merchant connector account ( if the url used is /{merchant_connector_id})
@ -1587,7 +1590,7 @@ async fn fetch_optional_mca_and_connector(
) -> CustomResult<
(
Option<domain::MerchantConnectorAccount>,
&'static (dyn api::Connector + Sync),
ConnectorEnum,
String,
),
errors::ApiErrorResponse,

View File

@ -1,6 +1,10 @@
pub mod api;
pub mod authentication;
pub mod authorization;
pub mod connector_integration_interface;
pub mod conversion_impls;
#[cfg(feature = "email")]
pub mod email;
pub mod encryption;
#[cfg(feature = "olap")]
pub mod jwt;
@ -10,9 +14,6 @@ pub mod pm_auth;
#[cfg(feature = "recon")]
pub mod recon;
#[cfg(feature = "email")]
pub mod email;
use std::sync::Arc;
use error_stack::ResultExt;

View File

@ -24,6 +24,7 @@ use common_utils::{
request::RequestContent,
};
use error_stack::{report, Report, ResultExt};
use hyperswitch_domain_models::router_data_v2::flow_common_types as common_types;
pub use hyperswitch_domain_models::router_response_types::RedirectForm;
pub use hyperswitch_interfaces::{
api::{
@ -40,7 +41,10 @@ use serde_json::json;
use tera::{Context, Tera};
use self::request::{HeaderExt, RequestBuilderExt};
use super::authentication::AuthenticateAndFetch;
use super::{
authentication::AuthenticateAndFetch,
connector_integration_interface::BoxedConnectorIntegrationInterface,
};
use crate::{
configs::Settings,
consts,
@ -58,6 +62,7 @@ use crate::{
app::{AppStateInfo, ReqState, SessionStateInfo},
metrics, AppState, SessionState,
},
services::connector_integration_interface::RouterDataConversion,
types::{
self,
api::{self, ConnectorCommon},
@ -65,6 +70,29 @@ use crate::{
},
};
pub type BoxedPaymentConnectorIntegrationInterface<T, Req, Resp> =
BoxedConnectorIntegrationInterface<T, common_types::PaymentFlowData, Req, Resp>;
pub type BoxedRefundConnectorIntegrationInterface<T, Req, Resp> =
BoxedConnectorIntegrationInterface<T, common_types::RefundFlowData, Req, Resp>;
#[cfg(feature = "frm")]
pub type BoxedFrmConnectorIntegrationInterface<T, Req, Resp> =
BoxedConnectorIntegrationInterface<T, common_types::FrmFlowData, Req, Resp>;
pub type BoxedDisputeConnectorIntegrationInterface<T, Req, Resp> =
BoxedConnectorIntegrationInterface<T, common_types::DisputesFlowData, Req, Resp>;
pub type BoxedMandateRevokeConnectorIntegrationInterface<T, Req, Resp> =
BoxedConnectorIntegrationInterface<T, common_types::MandateRevokeFlowData, Req, Resp>;
#[cfg(feature = "payouts")]
pub type BoxedPayoutConnectorIntegrationInterface<T, Req, Resp> =
BoxedConnectorIntegrationInterface<T, common_types::PayoutFlowData, Req, Resp>;
pub type BoxedWebhookSourceVerificationConnectorIntegrationInterface<T, Req, Resp> =
BoxedConnectorIntegrationInterface<T, common_types::WebhookSourceVerifyData, Req, Resp>;
pub type BoxedExternalAuthenticationConnectorIntegrationInterface<T, Req, Resp> =
BoxedConnectorIntegrationInterface<T, common_types::ExternalAuthenticationFlowData, Req, Resp>;
pub type BoxedAccessTokenConnectorIntegrationInterface<T, Req, Resp> =
BoxedConnectorIntegrationInterface<T, common_types::AccessTokenFlowData, Req, Resp>;
pub type BoxedFilesConnectorIntegrationInterface<T, Req, Resp> =
BoxedConnectorIntegrationInterface<T, common_types::FilesFlowData, Req, Resp>;
pub trait ConnectorValidation: ConnectorCommon {
fn validate_capture_method(
&self,
@ -128,11 +156,12 @@ pub async fn execute_connector_processing_step<
'b,
'a,
T,
ResourceCommonData: Clone + RouterDataConversion<T, Req, Resp> + 'static,
Req: Debug + Clone + 'static,
Resp: Debug + Clone + 'static,
>(
state: &'b SessionState,
connector_integration: BoxedConnectorIntegration<'a, T, Req, Resp>,
connector_integration: BoxedConnectorIntegrationInterface<T, ResourceCommonData, Req, Resp>,
req: &'b types::RouterData<T, Req, Resp>,
call_connector_action: payments::CallConnectorAction,
connector_request: Option<Request>,

View File

@ -0,0 +1,660 @@
use common_utils::{crypto, errors::CustomResult, request::Request};
use hyperswitch_domain_models::{router_data::RouterData, router_data_v2::RouterDataV2};
use hyperswitch_interfaces::connector_integration_v2::ConnectorIntegrationV2;
use super::{BoxedConnectorIntegrationV2, ConnectorValidation};
use crate::{
core::payments,
errors,
events::connector_api_logs::ConnectorEvent,
routes::app::StorageInterface,
services::{
api as services_api, BoxedConnectorIntegration, CaptureSyncMethod, ConnectorIntegration,
ConnectorRedirectResponse, PaymentAction,
},
settings::Connectors,
types::{
self,
api::{
self, disputes, Connector, ConnectorV2, CurrencyUnit, ExternalAuthenticationPayload,
IncomingWebhookEvent, IncomingWebhookRequestDetails, ObjectReferenceId,
},
domain,
},
};
pub trait RouterDataConversion<T, Req: Clone, Resp: Clone> {
fn from_old_router_data(
old_router_data: &RouterData<T, Req, Resp>,
) -> CustomResult<RouterDataV2<T, Self, Req, Resp>, errors::ConnectorError>
where
Self: Sized;
fn to_old_router_data(
new_router_data: RouterDataV2<T, Self, Req, Resp>,
) -> CustomResult<RouterData<T, Req, Resp>, errors::ConnectorError>
where
Self: Sized;
}
#[derive(Clone)]
pub enum ConnectorEnum {
Old(api::BoxedConnector),
New(api::BoxedConnectorV2),
}
#[derive(Clone)]
pub enum ConnectorIntegrationEnum<'a, F, ResourceCommonData, Req, Resp> {
Old(BoxedConnectorIntegration<'a, F, Req, Resp>),
New(BoxedConnectorIntegrationV2<'a, F, ResourceCommonData, Req, Resp>),
}
pub type BoxedConnectorIntegrationInterface<F, ResourceCommonData, Req, Resp> =
Box<dyn ConnectorIntegrationInterface<F, ResourceCommonData, Req, Resp> + Send + Sync>;
impl ConnectorEnum {
pub fn get_connector_integration<F, ResourceCommonData, Req, Resp>(
&self,
) -> BoxedConnectorIntegrationInterface<F, ResourceCommonData, Req, Resp>
where
dyn Connector + Sync: ConnectorIntegration<F, Req, Resp>,
dyn ConnectorV2 + Sync: ConnectorIntegrationV2<F, ResourceCommonData, Req, Resp>,
ResourceCommonData: RouterDataConversion<F, Req, Resp> + Clone + 'static,
F: Clone + 'static,
Req: Clone + 'static,
Resp: Clone + 'static,
{
match self {
Self::Old(old_integration) => Box::new(ConnectorIntegrationEnum::Old(
old_integration.get_connector_integration(),
)),
Self::New(new_integration) => Box::new(ConnectorIntegrationEnum::New(
new_integration.get_connector_integration_v2(),
)),
}
}
pub fn validate_file_upload(
&self,
purpose: api::FilePurpose,
file_size: i32,
file_type: mime::Mime,
) -> CustomResult<(), errors::ConnectorError> {
match self {
Self::Old(connector) => connector.validate_file_upload(purpose, file_size, file_type),
Self::New(connector) => {
connector.validate_file_upload_v2(purpose, file_size, file_type)
}
}
}
}
#[async_trait::async_trait]
impl api::IncomingWebhook for ConnectorEnum {
fn get_webhook_body_decoding_algorithm(
&self,
request: &IncomingWebhookRequestDetails<'_>,
) -> CustomResult<Box<dyn crypto::DecodeMessage + Send>, errors::ConnectorError> {
match self {
Self::Old(connector) => connector.get_webhook_body_decoding_algorithm(request),
Self::New(connector) => connector.get_webhook_body_decoding_algorithm(request),
}
}
async fn get_webhook_body_decoding_merchant_secret(
&self,
db: &dyn StorageInterface,
merchant_id: &str,
) -> CustomResult<Vec<u8>, errors::ConnectorError> {
match self {
Self::Old(connector) => {
connector
.get_webhook_body_decoding_merchant_secret(db, merchant_id)
.await
}
Self::New(connector) => {
connector
.get_webhook_body_decoding_merchant_secret(db, merchant_id)
.await
}
}
}
fn get_webhook_body_decoding_message(
&self,
request: &IncomingWebhookRequestDetails<'_>,
) -> CustomResult<Vec<u8>, errors::ConnectorError> {
match self {
Self::Old(connector) => connector.get_webhook_body_decoding_message(request),
Self::New(connector) => connector.get_webhook_body_decoding_message(request),
}
}
async fn decode_webhook_body(
&self,
db: &dyn StorageInterface,
request: &IncomingWebhookRequestDetails<'_>,
merchant_id: &str,
) -> CustomResult<Vec<u8>, errors::ConnectorError> {
match self {
Self::Old(connector) => {
connector
.decode_webhook_body(db, request, merchant_id)
.await
}
Self::New(connector) => {
connector
.decode_webhook_body(db, request, merchant_id)
.await
}
}
}
fn get_webhook_source_verification_algorithm(
&self,
request: &IncomingWebhookRequestDetails<'_>,
) -> CustomResult<Box<dyn crypto::VerifySignature + Send>, errors::ConnectorError> {
match self {
Self::Old(connector) => connector.get_webhook_source_verification_algorithm(request),
Self::New(connector) => connector.get_webhook_source_verification_algorithm(request),
}
}
async fn get_webhook_source_verification_merchant_secret(
&self,
merchant_account: &domain::MerchantAccount,
connector_name: &str,
merchant_connector_account: domain::MerchantConnectorAccount,
) -> CustomResult<api_models::webhooks::ConnectorWebhookSecrets, errors::ConnectorError> {
match self {
Self::Old(connector) => {
connector
.get_webhook_source_verification_merchant_secret(
merchant_account,
connector_name,
merchant_connector_account,
)
.await
}
Self::New(connector) => {
connector
.get_webhook_source_verification_merchant_secret(
merchant_account,
connector_name,
merchant_connector_account,
)
.await
}
}
}
fn get_webhook_source_verification_signature(
&self,
request: &IncomingWebhookRequestDetails<'_>,
connector_webhook_secrets: &api_models::webhooks::ConnectorWebhookSecrets,
) -> CustomResult<Vec<u8>, errors::ConnectorError> {
match self {
Self::Old(connector) => connector
.get_webhook_source_verification_signature(request, connector_webhook_secrets),
Self::New(connector) => connector
.get_webhook_source_verification_signature(request, connector_webhook_secrets),
}
}
fn get_webhook_source_verification_message(
&self,
request: &IncomingWebhookRequestDetails<'_>,
merchant_id: &str,
connector_webhook_secrets: &api_models::webhooks::ConnectorWebhookSecrets,
) -> CustomResult<Vec<u8>, errors::ConnectorError> {
match self {
Self::Old(connector) => connector.get_webhook_source_verification_message(
request,
merchant_id,
connector_webhook_secrets,
),
Self::New(connector) => connector.get_webhook_source_verification_message(
request,
merchant_id,
connector_webhook_secrets,
),
}
}
async fn verify_webhook_source_verification_call(
&self,
state: &crate::routes::SessionState,
merchant_account: &domain::MerchantAccount,
merchant_connector_account: domain::MerchantConnectorAccount,
connector_name: &str,
request_details: &IncomingWebhookRequestDetails<'_>,
) -> CustomResult<bool, errors::ConnectorError> {
match self {
Self::Old(connector) => {
connector
.verify_webhook_source_verification_call(
state,
merchant_account,
merchant_connector_account,
connector_name,
request_details,
)
.await
}
Self::New(connector) => {
connector
.verify_webhook_source_verification_call(
state,
merchant_account,
merchant_connector_account,
connector_name,
request_details,
)
.await
}
}
}
async fn verify_webhook_source(
&self,
request: &IncomingWebhookRequestDetails<'_>,
merchant_account: &domain::MerchantAccount,
merchant_connector_account: domain::MerchantConnectorAccount,
connector_name: &str,
) -> CustomResult<bool, errors::ConnectorError> {
match self {
Self::Old(connector) => {
connector
.verify_webhook_source(
request,
merchant_account,
merchant_connector_account,
connector_name,
)
.await
}
Self::New(connector) => {
connector
.verify_webhook_source(
request,
merchant_account,
merchant_connector_account,
connector_name,
)
.await
}
}
}
fn get_webhook_object_reference_id(
&self,
request: &IncomingWebhookRequestDetails<'_>,
) -> CustomResult<ObjectReferenceId, errors::ConnectorError> {
match self {
Self::Old(connector) => connector.get_webhook_object_reference_id(request),
Self::New(connector) => connector.get_webhook_object_reference_id(request),
}
}
fn get_webhook_event_type(
&self,
request: &IncomingWebhookRequestDetails<'_>,
) -> CustomResult<IncomingWebhookEvent, errors::ConnectorError> {
match self {
Self::Old(connector) => connector.get_webhook_event_type(request),
Self::New(connector) => connector.get_webhook_event_type(request),
}
}
fn get_webhook_resource_object(
&self,
request: &IncomingWebhookRequestDetails<'_>,
) -> CustomResult<Box<dyn masking::ErasedMaskSerialize>, errors::ConnectorError> {
match self {
Self::Old(connector) => connector.get_webhook_resource_object(request),
Self::New(connector) => connector.get_webhook_resource_object(request),
}
}
fn get_webhook_api_response(
&self,
request: &IncomingWebhookRequestDetails<'_>,
) -> CustomResult<services_api::ApplicationResponse<serde_json::Value>, errors::ConnectorError>
{
match self {
Self::Old(connector) => connector.get_webhook_api_response(request),
Self::New(connector) => connector.get_webhook_api_response(request),
}
}
fn get_dispute_details(
&self,
request: &IncomingWebhookRequestDetails<'_>,
) -> CustomResult<disputes::DisputePayload, errors::ConnectorError> {
match self {
Self::Old(connector) => connector.get_dispute_details(request),
Self::New(connector) => connector.get_dispute_details(request),
}
}
fn get_external_authentication_details(
&self,
request: &IncomingWebhookRequestDetails<'_>,
) -> CustomResult<ExternalAuthenticationPayload, errors::ConnectorError> {
match self {
Self::Old(connector) => connector.get_external_authentication_details(request),
Self::New(connector) => connector.get_external_authentication_details(request),
}
}
}
impl api::ConnectorTransactionId for ConnectorEnum {
fn connector_transaction_id(
&self,
payment_attempt: hyperswitch_domain_models::payments::payment_attempt::PaymentAttempt,
) -> Result<Option<String>, errors::ApiErrorResponse> {
match self {
Self::Old(connector) => connector.connector_transaction_id(payment_attempt),
Self::New(connector) => connector.connector_transaction_id(payment_attempt),
}
}
}
impl ConnectorRedirectResponse for ConnectorEnum {
fn get_flow_type(
&self,
query_params: &str,
json_payload: Option<serde_json::Value>,
action: PaymentAction,
) -> CustomResult<payments::CallConnectorAction, errors::ConnectorError> {
match self {
Self::Old(connector) => connector.get_flow_type(query_params, json_payload, action),
Self::New(connector) => connector.get_flow_type(query_params, json_payload, action),
}
}
}
impl ConnectorValidation for ConnectorEnum {
fn validate_capture_method(
&self,
capture_method: Option<common_enums::CaptureMethod>,
pmt: Option<common_enums::PaymentMethodType>,
) -> CustomResult<(), errors::ConnectorError> {
match self {
Self::Old(connector) => connector.validate_capture_method(capture_method, pmt),
Self::New(connector) => connector.validate_capture_method(capture_method, pmt),
}
}
fn validate_mandate_payment(
&self,
pm_type: Option<common_enums::PaymentMethodType>,
pm_data: domain::payments::PaymentMethodData,
) -> CustomResult<(), errors::ConnectorError> {
match self {
Self::Old(connector) => connector.validate_mandate_payment(pm_type, pm_data),
Self::New(connector) => connector.validate_mandate_payment(pm_type, pm_data),
}
}
fn validate_psync_reference_id(
&self,
data: &types::PaymentsSyncRouterData,
) -> CustomResult<(), errors::ConnectorError> {
match self {
Self::Old(connector) => connector.validate_psync_reference_id(data),
Self::New(connector) => connector.validate_psync_reference_id(data),
}
}
fn is_webhook_source_verification_mandatory(&self) -> bool {
match self {
Self::Old(connector) => connector.is_webhook_source_verification_mandatory(),
Self::New(connector) => connector.is_webhook_source_verification_mandatory(),
}
}
}
impl api::ConnectorCommon for ConnectorEnum {
fn id(&self) -> &'static str {
match self {
Self::Old(connector) => connector.id(),
Self::New(connector) => connector.id(),
}
}
fn get_currency_unit(&self) -> CurrencyUnit {
match self {
Self::Old(connector) => connector.get_currency_unit(),
Self::New(connector) => connector.get_currency_unit(),
}
}
fn get_auth_header(
&self,
auth_type: &types::ConnectorAuthType,
) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
match self {
Self::Old(connector) => connector.get_auth_header(auth_type),
Self::New(connector) => connector.get_auth_header(auth_type),
}
}
fn common_get_content_type(&self) -> &'static str {
match self {
Self::Old(connector) => connector.common_get_content_type(),
Self::New(connector) => connector.common_get_content_type(),
}
}
fn base_url<'a>(&self, connectors: &'a Connectors) -> &'a str {
match self {
Self::Old(connector) => connector.base_url(connectors),
Self::New(connector) => connector.base_url(connectors),
}
}
fn build_error_response(
&self,
res: types::Response,
event_builder: Option<&mut ConnectorEvent>,
) -> CustomResult<types::ErrorResponse, errors::ConnectorError> {
match self {
Self::Old(connector) => connector.build_error_response(res, event_builder),
Self::New(connector) => connector.build_error_response(res, event_builder),
}
}
}
impl<T, ResourceCommonData, Req, Resp> api::ConnectorCommon
for ConnectorIntegrationEnum<'_, T, ResourceCommonData, Req, Resp>
{
fn id(&self) -> &'static str {
match self {
ConnectorIntegrationEnum::Old(old_integration) => old_integration.id(),
ConnectorIntegrationEnum::New(new_integration) => new_integration.id(),
}
}
fn get_currency_unit(&self) -> CurrencyUnit {
match self {
ConnectorIntegrationEnum::Old(old_integration) => old_integration.get_currency_unit(),
ConnectorIntegrationEnum::New(new_integration) => new_integration.get_currency_unit(),
}
}
fn get_auth_header(
&self,
auth_type: &types::ConnectorAuthType,
) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
match self {
ConnectorIntegrationEnum::Old(old_integration) => {
old_integration.get_auth_header(auth_type)
}
ConnectorIntegrationEnum::New(new_integration) => {
new_integration.get_auth_header(auth_type)
}
}
}
fn common_get_content_type(&self) -> &'static str {
match self {
ConnectorIntegrationEnum::Old(old_integration) => {
old_integration.common_get_content_type()
}
ConnectorIntegrationEnum::New(new_integration) => {
new_integration.common_get_content_type()
}
}
}
fn base_url<'a>(&self, connectors: &'a Connectors) -> &'a str {
match self {
ConnectorIntegrationEnum::Old(old_integration) => old_integration.base_url(connectors),
ConnectorIntegrationEnum::New(new_integration) => new_integration.base_url(connectors),
}
}
fn build_error_response(
&self,
res: types::Response,
event_builder: Option<&mut ConnectorEvent>,
) -> CustomResult<types::ErrorResponse, errors::ConnectorError> {
match self {
ConnectorIntegrationEnum::Old(old_integration) => {
old_integration.build_error_response(res, event_builder)
}
ConnectorIntegrationEnum::New(new_integration) => {
new_integration.build_error_response(res, event_builder)
}
}
}
}
pub trait ConnectorIntegrationInterface<F, ResourceCommonData, Req, Resp>: Send + Sync {
fn clone_box(
&self,
) -> Box<dyn ConnectorIntegrationInterface<F, ResourceCommonData, Req, Resp> + Send + Sync>;
fn get_multiple_capture_sync_method(
&self,
) -> CustomResult<CaptureSyncMethod, errors::ConnectorError>;
fn build_request(
&self,
req: &RouterData<F, Req, Resp>,
_connectors: &Connectors,
) -> CustomResult<Option<Request>, errors::ConnectorError>;
fn handle_response(
&self,
data: &RouterData<F, Req, Resp>,
event_builder: Option<&mut ConnectorEvent>,
_res: types::Response,
) -> CustomResult<RouterData<F, Req, Resp>, errors::ConnectorError>
where
F: Clone,
Req: Clone,
Resp: Clone;
fn get_error_response(
&self,
res: types::Response,
event_builder: Option<&mut ConnectorEvent>,
) -> CustomResult<types::ErrorResponse, errors::ConnectorError>;
fn get_5xx_error_response(
&self,
res: types::Response,
event_builder: Option<&mut ConnectorEvent>,
) -> CustomResult<types::ErrorResponse, errors::ConnectorError>;
}
impl<T: 'static, ResourceCommonData: 'static, Req: 'static, Resp: 'static>
ConnectorIntegrationInterface<T, ResourceCommonData, Req, Resp>
for ConnectorIntegrationEnum<'static, T, ResourceCommonData, Req, Resp>
where
ResourceCommonData: RouterDataConversion<T, Req, Resp> + Clone,
T: Clone,
Req: Clone,
Resp: Clone,
{
fn get_multiple_capture_sync_method(
&self,
) -> CustomResult<CaptureSyncMethod, errors::ConnectorError> {
match self {
ConnectorIntegrationEnum::Old(old_integration) => {
old_integration.get_multiple_capture_sync_method()
}
ConnectorIntegrationEnum::New(new_integration) => {
new_integration.get_multiple_capture_sync_method()
}
}
}
fn build_request(
&self,
req: &RouterData<T, Req, Resp>,
connectors: &Connectors,
) -> CustomResult<Option<Request>, errors::ConnectorError> {
match self {
ConnectorIntegrationEnum::Old(old_integration) => {
old_integration.build_request(req, connectors)
}
ConnectorIntegrationEnum::New(new_integration) => {
let new_router_data = ResourceCommonData::from_old_router_data(req)?;
new_integration.build_request_v2(&new_router_data, connectors)
}
}
}
fn handle_response(
&self,
data: &RouterData<T, Req, Resp>,
event_builder: Option<&mut ConnectorEvent>,
res: types::Response,
) -> CustomResult<RouterData<T, Req, Resp>, errors::ConnectorError>
where
T: Clone,
Req: Clone,
Resp: Clone,
{
match self {
ConnectorIntegrationEnum::Old(old_integration) => {
old_integration.handle_response(data, event_builder, res)
}
ConnectorIntegrationEnum::New(new_integration) => {
let new_router_data = ResourceCommonData::from_old_router_data(data)?;
new_integration
.handle_response_v2(&new_router_data, event_builder, res)
.map(ResourceCommonData::to_old_router_data)?
}
}
}
fn get_error_response(
&self,
res: types::Response,
event_builder: Option<&mut ConnectorEvent>,
) -> CustomResult<types::ErrorResponse, errors::ConnectorError> {
match self {
ConnectorIntegrationEnum::Old(old_integration) => {
old_integration.get_error_response(res, event_builder)
}
ConnectorIntegrationEnum::New(new_integration) => {
new_integration.get_error_response_v2(res, event_builder)
}
}
}
fn get_5xx_error_response(
&self,
res: types::Response,
event_builder: Option<&mut ConnectorEvent>,
) -> CustomResult<types::ErrorResponse, errors::ConnectorError> {
match self {
ConnectorIntegrationEnum::Old(old_integration) => {
old_integration.get_5xx_error_response(res, event_builder)
}
ConnectorIntegrationEnum::New(new_integration) => {
new_integration.get_5xx_error_response(res, event_builder)
}
}
}
fn clone_box(
&self,
) -> Box<dyn ConnectorIntegrationInterface<T, ResourceCommonData, Req, Resp> + Send + Sync>
{
Box::new(self.clone())
}
}

View File

@ -0,0 +1,678 @@
#[cfg(feature = "frm")]
use hyperswitch_domain_models::router_data_v2::flow_common_types::FrmFlowData;
#[cfg(feature = "payouts")]
use hyperswitch_domain_models::router_data_v2::flow_common_types::PayoutFlowData;
use hyperswitch_domain_models::{
payment_address::PaymentAddress,
router_data::{self, RouterData},
router_data_v2::{
flow_common_types::{
AccessTokenFlowData, DisputesFlowData, ExternalAuthenticationFlowData, FilesFlowData,
MandateRevokeFlowData, PaymentFlowData, RefundFlowData, WebhookSourceVerifyData,
},
RouterDataV2,
},
};
use super::connector_integration_interface::RouterDataConversion;
use crate::errors;
fn get_irrelevant_id_string(id_name: &str, flow_name: &str) -> String {
format!("irrelevant {id_name} in {flow_name} flow")
}
fn get_default_router_data<F, Req, Resp>(
flow_name: &str,
request: Req,
response: Result<Resp, router_data::ErrorResponse>,
) -> RouterData<F, Req, Resp> {
RouterData {
flow: std::marker::PhantomData,
merchant_id: get_irrelevant_id_string("merchant_id", flow_name),
customer_id: None,
connector_customer: None,
connector: get_irrelevant_id_string("connector", flow_name),
payment_id: get_irrelevant_id_string("payment_id", flow_name),
attempt_id: get_irrelevant_id_string("attempt_id", flow_name),
status: common_enums::AttemptStatus::default(),
payment_method: common_enums::PaymentMethod::default(),
connector_auth_type: router_data::ConnectorAuthType::default(),
description: None,
return_url: None,
address: PaymentAddress::default(),
auth_type: common_enums::AuthenticationType::default(),
connector_meta_data: None,
connector_wallets_details: None,
amount_captured: None,
access_token: None,
session_token: None,
reference_id: None,
payment_method_token: None,
recurring_mandate_payment_data: None,
preprocessing_id: None,
payment_method_balance: None,
connector_api_version: None,
request,
response,
connector_request_reference_id: get_irrelevant_id_string(
"connector_request_reference_id",
flow_name,
),
#[cfg(feature = "payouts")]
payout_method_data: None,
#[cfg(feature = "payouts")]
quote_id: None,
test_mode: None,
connector_http_status_code: None,
external_latency: None,
apple_pay_flow: None,
frm_metadata: None,
dispute_id: None,
refund_id: None,
connector_response: None,
payment_method_status: None,
minor_amount_captured: None,
}
}
impl<T, Req: Clone, Resp: Clone> RouterDataConversion<T, Req, Resp> for AccessTokenFlowData {
fn from_old_router_data(
old_router_data: &RouterData<T, Req, Resp>,
) -> errors::CustomResult<RouterDataV2<T, Self, Req, Resp>, errors::ConnectorError>
where
Self: Sized,
{
let resource_common_data = Self {};
Ok(RouterDataV2 {
flow: std::marker::PhantomData,
resource_common_data,
connector_auth_type: old_router_data.connector_auth_type.clone(),
request: old_router_data.request.clone(),
response: old_router_data.response.clone(),
})
}
fn to_old_router_data(
new_router_data: RouterDataV2<T, Self, Req, Resp>,
) -> errors::CustomResult<RouterData<T, Req, Resp>, errors::ConnectorError>
where
Self: Sized,
{
let Self {} = new_router_data.resource_common_data;
let request = new_router_data.request.clone();
let response = new_router_data.response.clone();
let router_data = get_default_router_data("access token", request, response);
Ok(router_data)
}
}
impl<T, Req: Clone, Resp: Clone> RouterDataConversion<T, Req, Resp> for PaymentFlowData {
fn from_old_router_data(
old_router_data: &RouterData<T, Req, Resp>,
) -> errors::CustomResult<RouterDataV2<T, Self, Req, Resp>, errors::ConnectorError>
where
Self: Sized,
{
let resource_common_data = Self {
merchant_id: old_router_data.merchant_id.clone(),
customer_id: old_router_data.customer_id.clone(),
connector_customer: old_router_data.connector_customer.clone(),
payment_id: old_router_data.payment_id.clone(),
attempt_id: old_router_data.attempt_id.clone(),
status: old_router_data.status,
payment_method: old_router_data.payment_method,
description: old_router_data.description.clone(),
return_url: old_router_data.return_url.clone(),
address: old_router_data.address.clone(),
auth_type: old_router_data.auth_type,
connector_meta_data: old_router_data.connector_meta_data.clone(),
amount_captured: old_router_data.amount_captured,
minor_amount_captured: old_router_data.minor_amount_captured,
access_token: old_router_data.access_token.clone(),
session_token: old_router_data.session_token.clone(),
reference_id: old_router_data.reference_id.clone(),
payment_method_token: old_router_data.payment_method_token.clone(),
recurring_mandate_payment_data: old_router_data.recurring_mandate_payment_data.clone(),
preprocessing_id: old_router_data.preprocessing_id.clone(),
payment_method_balance: old_router_data.payment_method_balance.clone(),
connector_api_version: old_router_data.connector_api_version.clone(),
connector_request_reference_id: old_router_data.connector_request_reference_id.clone(),
test_mode: old_router_data.test_mode,
connector_http_status_code: old_router_data.connector_http_status_code,
external_latency: old_router_data.external_latency,
apple_pay_flow: old_router_data.apple_pay_flow.clone(),
connector_response: old_router_data.connector_response.clone(),
payment_method_status: old_router_data.payment_method_status,
};
Ok(RouterDataV2 {
flow: std::marker::PhantomData,
resource_common_data,
connector_auth_type: old_router_data.connector_auth_type.clone(),
request: old_router_data.request.clone(),
response: old_router_data.response.clone(),
})
}
fn to_old_router_data(
new_router_data: RouterDataV2<T, Self, Req, Resp>,
) -> errors::CustomResult<RouterData<T, Req, Resp>, errors::ConnectorError>
where
Self: Sized,
{
let Self {
merchant_id,
customer_id,
connector_customer,
payment_id,
attempt_id,
status,
payment_method,
description,
return_url,
address,
auth_type,
connector_meta_data,
amount_captured,
minor_amount_captured,
access_token,
session_token,
reference_id,
payment_method_token,
recurring_mandate_payment_data,
preprocessing_id,
payment_method_balance,
connector_api_version,
connector_request_reference_id,
test_mode,
connector_http_status_code,
external_latency,
apple_pay_flow,
connector_response,
payment_method_status,
} = new_router_data.resource_common_data;
let mut router_data =
get_default_router_data("payment", new_router_data.request, new_router_data.response);
router_data.merchant_id = merchant_id;
router_data.customer_id = customer_id;
router_data.connector_customer = connector_customer;
router_data.payment_id = payment_id;
router_data.attempt_id = attempt_id;
router_data.status = status;
router_data.payment_method = payment_method;
router_data.description = description;
router_data.return_url = return_url;
router_data.address = address;
router_data.auth_type = auth_type;
router_data.connector_meta_data = connector_meta_data;
router_data.amount_captured = amount_captured;
router_data.minor_amount_captured = minor_amount_captured;
router_data.access_token = access_token;
router_data.session_token = session_token;
router_data.reference_id = reference_id;
router_data.payment_method_token = payment_method_token;
router_data.recurring_mandate_payment_data = recurring_mandate_payment_data;
router_data.preprocessing_id = preprocessing_id;
router_data.payment_method_balance = payment_method_balance;
router_data.connector_api_version = connector_api_version;
router_data.connector_request_reference_id = connector_request_reference_id;
router_data.test_mode = test_mode;
router_data.connector_http_status_code = connector_http_status_code;
router_data.external_latency = external_latency;
router_data.apple_pay_flow = apple_pay_flow;
router_data.connector_response = connector_response;
router_data.payment_method_status = payment_method_status;
Ok(router_data)
}
}
impl<T, Req: Clone, Resp: Clone> RouterDataConversion<T, Req, Resp> for RefundFlowData {
fn from_old_router_data(
old_router_data: &RouterData<T, Req, Resp>,
) -> errors::CustomResult<RouterDataV2<T, Self, Req, Resp>, errors::ConnectorError>
where
Self: Sized,
{
let resource_common_data = Self {
merchant_id: old_router_data.merchant_id.clone(),
customer_id: old_router_data.customer_id.clone(),
payment_id: old_router_data.payment_id.clone(),
attempt_id: old_router_data.attempt_id.clone(),
status: old_router_data.status,
payment_method: old_router_data.payment_method,
return_url: old_router_data.return_url.clone(),
connector_meta_data: old_router_data.connector_meta_data.clone(),
amount_captured: old_router_data.amount_captured,
minor_amount_captured: old_router_data.minor_amount_captured,
connector_request_reference_id: old_router_data.connector_request_reference_id.clone(),
refund_id: old_router_data.refund_id.clone().ok_or(
errors::ConnectorError::MissingRequiredField {
field_name: "refund_id",
},
)?,
};
Ok(RouterDataV2 {
flow: std::marker::PhantomData,
resource_common_data,
connector_auth_type: old_router_data.connector_auth_type.clone(),
request: old_router_data.request.clone(),
response: old_router_data.response.clone(),
})
}
fn to_old_router_data(
new_router_data: RouterDataV2<T, Self, Req, Resp>,
) -> errors::CustomResult<RouterData<T, Req, Resp>, errors::ConnectorError>
where
Self: Sized,
{
let Self {
merchant_id,
customer_id,
payment_id,
attempt_id,
status,
payment_method,
return_url,
connector_meta_data,
amount_captured,
minor_amount_captured,
connector_request_reference_id,
refund_id,
} = new_router_data.resource_common_data;
let mut router_data =
get_default_router_data("refund", new_router_data.request, new_router_data.response);
router_data.merchant_id = merchant_id;
router_data.customer_id = customer_id;
router_data.payment_id = payment_id;
router_data.attempt_id = attempt_id;
router_data.status = status;
router_data.payment_method = payment_method;
router_data.return_url = return_url;
router_data.connector_meta_data = connector_meta_data;
router_data.amount_captured = amount_captured;
router_data.minor_amount_captured = minor_amount_captured;
router_data.connector_request_reference_id = connector_request_reference_id;
router_data.refund_id = Some(refund_id);
Ok(router_data)
}
}
impl<T, Req: Clone, Resp: Clone> RouterDataConversion<T, Req, Resp> for DisputesFlowData {
fn from_old_router_data(
old_router_data: &RouterData<T, Req, Resp>,
) -> errors::CustomResult<RouterDataV2<T, Self, Req, Resp>, errors::ConnectorError>
where
Self: Sized,
{
let resource_common_data = Self {
merchant_id: old_router_data.merchant_id.clone(),
payment_id: old_router_data.payment_id.clone(),
attempt_id: old_router_data.attempt_id.clone(),
payment_method: old_router_data.payment_method,
return_url: old_router_data.return_url.clone(),
connector_meta_data: old_router_data.connector_meta_data.clone(),
amount_captured: old_router_data.amount_captured,
minor_amount_captured: old_router_data.minor_amount_captured,
connector_request_reference_id: old_router_data.connector_request_reference_id.clone(),
dispute_id: old_router_data.dispute_id.clone().ok_or(
errors::ConnectorError::MissingRequiredField {
field_name: "dispute_id",
},
)?,
};
Ok(RouterDataV2 {
flow: std::marker::PhantomData,
resource_common_data,
connector_auth_type: old_router_data.connector_auth_type.clone(),
request: old_router_data.request.clone(),
response: old_router_data.response.clone(),
})
}
fn to_old_router_data(
new_router_data: RouterDataV2<T, Self, Req, Resp>,
) -> errors::CustomResult<RouterData<T, Req, Resp>, errors::ConnectorError>
where
Self: Sized,
{
let Self {
merchant_id,
payment_id,
attempt_id,
payment_method,
return_url,
connector_meta_data,
amount_captured,
minor_amount_captured,
connector_request_reference_id,
dispute_id,
} = new_router_data.resource_common_data;
let mut router_data = get_default_router_data(
"Disputes",
new_router_data.request,
new_router_data.response,
);
router_data.merchant_id = merchant_id;
router_data.payment_id = payment_id;
router_data.attempt_id = attempt_id;
router_data.payment_method = payment_method;
router_data.return_url = return_url;
router_data.connector_meta_data = connector_meta_data;
router_data.amount_captured = amount_captured;
router_data.minor_amount_captured = minor_amount_captured;
router_data.connector_request_reference_id = connector_request_reference_id;
router_data.dispute_id = Some(dispute_id);
Ok(router_data)
}
}
#[cfg(feature = "frm")]
impl<T, Req: Clone, Resp: Clone> RouterDataConversion<T, Req, Resp> for FrmFlowData {
fn from_old_router_data(
old_router_data: &RouterData<T, Req, Resp>,
) -> errors::CustomResult<RouterDataV2<T, Self, Req, Resp>, errors::ConnectorError>
where
Self: Sized,
{
let resource_common_data = Self {
merchant_id: old_router_data.merchant_id.clone(),
payment_id: old_router_data.payment_id.clone(),
attempt_id: old_router_data.attempt_id.clone(),
payment_method: old_router_data.payment_method,
connector_request_reference_id: old_router_data.connector_request_reference_id.clone(),
return_url: old_router_data.return_url.clone(),
auth_type: old_router_data.auth_type,
connector_wallets_details: old_router_data.connector_wallets_details.clone(),
connector_meta_data: old_router_data.connector_meta_data.clone(),
amount_captured: old_router_data.amount_captured,
minor_amount_captured: old_router_data.minor_amount_captured,
};
Ok(RouterDataV2 {
flow: std::marker::PhantomData,
resource_common_data,
connector_auth_type: old_router_data.connector_auth_type.clone(),
request: old_router_data.request.clone(),
response: old_router_data.response.clone(),
})
}
fn to_old_router_data(
new_router_data: RouterDataV2<T, Self, Req, Resp>,
) -> errors::CustomResult<RouterData<T, Req, Resp>, errors::ConnectorError>
where
Self: Sized,
{
let Self {
merchant_id,
payment_id,
attempt_id,
payment_method,
connector_request_reference_id,
return_url,
auth_type,
connector_wallets_details,
connector_meta_data,
amount_captured,
minor_amount_captured,
} = new_router_data.resource_common_data;
let mut router_data =
get_default_router_data("frm", new_router_data.request, new_router_data.response);
router_data.merchant_id = merchant_id;
router_data.payment_id = payment_id;
router_data.attempt_id = attempt_id;
router_data.payment_method = payment_method;
router_data.connector_request_reference_id = connector_request_reference_id;
router_data.return_url = return_url;
router_data.auth_type = auth_type;
router_data.connector_wallets_details = connector_wallets_details;
router_data.connector_meta_data = connector_meta_data;
router_data.amount_captured = amount_captured;
router_data.minor_amount_captured = minor_amount_captured;
Ok(router_data)
}
}
impl<T, Req: Clone, Resp: Clone> RouterDataConversion<T, Req, Resp> for FilesFlowData {
fn from_old_router_data(
old_router_data: &RouterData<T, Req, Resp>,
) -> errors::CustomResult<RouterDataV2<T, Self, Req, Resp>, errors::ConnectorError>
where
Self: Sized,
{
let resource_common_data = Self {
merchant_id: old_router_data.merchant_id.clone(),
payment_id: old_router_data.payment_id.clone(),
attempt_id: old_router_data.attempt_id.clone(),
return_url: old_router_data.return_url.clone(),
connector_meta_data: old_router_data.connector_meta_data.clone(),
connector_request_reference_id: old_router_data.connector_request_reference_id.clone(),
};
Ok(RouterDataV2 {
flow: std::marker::PhantomData,
resource_common_data,
connector_auth_type: old_router_data.connector_auth_type.clone(),
request: old_router_data.request.clone(),
response: old_router_data.response.clone(),
})
}
fn to_old_router_data(
new_router_data: RouterDataV2<T, Self, Req, Resp>,
) -> errors::CustomResult<RouterData<T, Req, Resp>, errors::ConnectorError>
where
Self: Sized,
{
let Self {
merchant_id,
payment_id,
attempt_id,
return_url,
connector_meta_data,
connector_request_reference_id,
} = new_router_data.resource_common_data;
let mut router_data =
get_default_router_data("files", new_router_data.request, new_router_data.response);
router_data.merchant_id = merchant_id;
router_data.payment_id = payment_id;
router_data.attempt_id = attempt_id;
router_data.return_url = return_url;
router_data.connector_meta_data = connector_meta_data;
router_data.connector_request_reference_id = connector_request_reference_id;
Ok(router_data)
}
}
impl<T, Req: Clone, Resp: Clone> RouterDataConversion<T, Req, Resp> for WebhookSourceVerifyData {
fn from_old_router_data(
old_router_data: &RouterData<T, Req, Resp>,
) -> errors::CustomResult<RouterDataV2<T, Self, Req, Resp>, errors::ConnectorError>
where
Self: Sized,
{
let resource_common_data = Self {
merchant_id: old_router_data.merchant_id.clone(),
};
Ok(RouterDataV2 {
flow: std::marker::PhantomData,
resource_common_data,
connector_auth_type: old_router_data.connector_auth_type.clone(),
request: old_router_data.request.clone(),
response: old_router_data.response.clone(),
})
}
fn to_old_router_data(
new_router_data: RouterDataV2<T, Self, Req, Resp>,
) -> errors::CustomResult<RouterData<T, Req, Resp>, errors::ConnectorError>
where
Self: Sized,
{
let Self { merchant_id } = new_router_data.resource_common_data;
let mut router_data = get_default_router_data(
"webhook source verify",
new_router_data.request,
new_router_data.response,
);
router_data.merchant_id = merchant_id;
Ok(router_data)
}
}
impl<T, Req: Clone, Resp: Clone> RouterDataConversion<T, Req, Resp> for MandateRevokeFlowData {
fn from_old_router_data(
old_router_data: &RouterData<T, Req, Resp>,
) -> errors::CustomResult<RouterDataV2<T, Self, Req, Resp>, errors::ConnectorError>
where
Self: Sized,
{
let resource_common_data = Self {
merchant_id: old_router_data.merchant_id.clone(),
customer_id: old_router_data.customer_id.clone().ok_or(
errors::ConnectorError::MissingRequiredField {
field_name: "customer_id",
},
)?,
payment_id: Some(old_router_data.payment_id.clone()),
};
Ok(RouterDataV2 {
flow: std::marker::PhantomData,
resource_common_data,
connector_auth_type: old_router_data.connector_auth_type.clone(),
request: old_router_data.request.clone(),
response: old_router_data.response.clone(),
})
}
fn to_old_router_data(
new_router_data: RouterDataV2<T, Self, Req, Resp>,
) -> errors::CustomResult<RouterData<T, Req, Resp>, errors::ConnectorError>
where
Self: Sized,
{
let Self {
merchant_id,
customer_id,
payment_id,
} = new_router_data.resource_common_data;
let mut router_data = get_default_router_data(
"mandate revoke",
new_router_data.request,
new_router_data.response,
);
router_data.merchant_id = merchant_id;
router_data.customer_id = Some(customer_id);
router_data.payment_id =
payment_id.unwrap_or_else(|| get_irrelevant_id_string("payment_id", "mandate revoke"));
Ok(router_data)
}
}
#[cfg(feature = "payouts")]
impl<T, Req: Clone, Resp: Clone> RouterDataConversion<T, Req, Resp> for PayoutFlowData {
fn from_old_router_data(
old_router_data: &RouterData<T, Req, Resp>,
) -> errors::CustomResult<RouterDataV2<T, Self, Req, Resp>, errors::ConnectorError>
where
Self: Sized,
{
let resource_common_data = Self {
merchant_id: old_router_data.merchant_id.clone(),
customer_id: old_router_data.customer_id.clone(),
connector_customer: old_router_data.connector_customer.clone(),
return_url: old_router_data.return_url.clone(),
address: old_router_data.address.clone(),
connector_meta_data: old_router_data.connector_meta_data.clone(),
connector_wallets_details: old_router_data.connector_wallets_details.clone(),
connector_request_reference_id: old_router_data.connector_request_reference_id.clone(),
payout_method_data: old_router_data.payout_method_data.clone(),
quote_id: old_router_data.quote_id.clone(),
};
Ok(RouterDataV2 {
flow: std::marker::PhantomData,
resource_common_data,
connector_auth_type: old_router_data.connector_auth_type.clone(),
request: old_router_data.request.clone(),
response: old_router_data.response.clone(),
})
}
fn to_old_router_data(
new_router_data: RouterDataV2<T, Self, Req, Resp>,
) -> errors::CustomResult<RouterData<T, Req, Resp>, errors::ConnectorError>
where
Self: Sized,
{
let Self {
merchant_id,
customer_id,
connector_customer,
return_url,
address,
connector_meta_data,
connector_wallets_details,
connector_request_reference_id,
payout_method_data,
quote_id,
} = new_router_data.resource_common_data;
let mut router_data =
get_default_router_data("payout", new_router_data.request, new_router_data.response);
router_data.merchant_id = merchant_id;
router_data.customer_id = customer_id;
router_data.connector_customer = connector_customer;
router_data.return_url = return_url;
router_data.address = address;
router_data.connector_meta_data = connector_meta_data;
router_data.connector_wallets_details = connector_wallets_details;
router_data.connector_request_reference_id = connector_request_reference_id;
router_data.payout_method_data = payout_method_data;
router_data.quote_id = quote_id;
Ok(router_data)
}
}
impl<T, Req: Clone, Resp: Clone> RouterDataConversion<T, Req, Resp>
for ExternalAuthenticationFlowData
{
fn from_old_router_data(
old_router_data: &RouterData<T, Req, Resp>,
) -> errors::CustomResult<RouterDataV2<T, Self, Req, Resp>, errors::ConnectorError>
where
Self: Sized,
{
let resource_common_data = Self {
merchant_id: old_router_data.merchant_id.clone(),
connector_meta_data: old_router_data.connector_meta_data.clone(),
address: old_router_data.address.clone(),
};
Ok(RouterDataV2 {
flow: std::marker::PhantomData,
resource_common_data,
connector_auth_type: old_router_data.connector_auth_type.clone(),
request: old_router_data.request.clone(),
response: old_router_data.response.clone(),
})
}
fn to_old_router_data(
new_router_data: RouterDataV2<T, Self, Req, Resp>,
) -> errors::CustomResult<RouterData<T, Req, Resp>, errors::ConnectorError>
where
Self: Sized,
{
let Self {
merchant_id,
connector_meta_data,
address,
} = new_router_data.resource_common_data;
let mut router_data = get_default_router_data(
"external authentication",
new_router_data.request,
new_router_data.response,
);
router_data.merchant_id = merchant_id;
router_data.connector_meta_data = connector_meta_data;
router_data.address = address;
Ok(router_data)
}
}

View File

@ -22,6 +22,8 @@ pub use api_models::{enums::Connector, mandates};
#[cfg(feature = "payouts")]
pub use api_models::{enums::PayoutConnectors, payouts as payout_types};
pub use common_utils::{pii, pii::Email, request::RequestContent, types::MinorUnit};
#[cfg(feature = "frm")]
pub use hyperswitch_domain_models::router_data_v2::FrmFlowData;
pub use hyperswitch_domain_models::{
payment_address::PaymentAddress,
router_data::{
@ -31,7 +33,7 @@ pub use hyperswitch_domain_models::{
},
router_data_v2::{
AccessTokenFlowData, DisputesFlowData, ExternalAuthenticationFlowData, FilesFlowData,
FrmFlowData, MandateRevokeFlowData, PaymentFlowData, RefundFlowData, RouterDataV2,
MandateRevokeFlowData, PaymentFlowData, RefundFlowData, RouterDataV2,
WebhookSourceVerifyData,
},
router_request_types::{

View File

@ -61,8 +61,8 @@ use crate::{
payments::types as payments_types,
},
services::{
ConnectorIntegration, ConnectorIntegrationV2, ConnectorRedirectResponse,
ConnectorValidation,
connector_integration_interface::ConnectorEnum, ConnectorIntegration,
ConnectorIntegrationV2, ConnectorRedirectResponse, ConnectorValidation,
},
types::{self, api::enums as api_enums},
};
@ -167,10 +167,6 @@ pub trait Connector:
{
}
pub struct Re;
pub struct Pe;
impl<
T: Refund
+ RefundV2
@ -200,7 +196,44 @@ impl<
{
}
type BoxedConnector = Box<&'static (dyn Connector + Sync)>;
pub trait ConnectorV2:
Send
+ RefundV2
+ PaymentV2
+ ConnectorRedirectResponse
+ IncomingWebhook
+ ConnectorAccessTokenV2
+ DisputeV2
+ FileUploadV2
+ ConnectorTransactionId
+ PayoutsV2
+ ConnectorVerifyWebhookSourceV2
+ FraudCheckV2
+ ConnectorMandateRevokeV2
+ ExternalAuthenticationV2
{
}
impl<
T: RefundV2
+ PaymentV2
+ ConnectorRedirectResponse
+ Send
+ IncomingWebhook
+ ConnectorAccessTokenV2
+ DisputeV2
+ FileUploadV2
+ ConnectorTransactionId
+ PayoutsV2
+ ConnectorVerifyWebhookSourceV2
+ FraudCheckV2
+ ConnectorMandateRevokeV2
+ ExternalAuthenticationV2,
> ConnectorV2 for T
{
}
pub type BoxedConnector = Box<&'static (dyn Connector + Sync)>;
pub type BoxedConnectorV2 = Box<&'static (dyn ConnectorV2 + Sync)>;
// Normal flow will call the connector and follow the flow specific operations (capture, authorize)
// SessionTokenFromMetadata will avoid calling the connector instead create the session token ( for sdk )
@ -217,7 +250,7 @@ pub enum GetToken {
/// the support for connector name is retained
#[derive(Clone)]
pub struct ConnectorData {
pub connector: BoxedConnector,
pub connector: ConnectorEnum,
pub connector_name: types::Connector,
pub get_token: GetToken,
pub merchant_connector_id: Option<String>,
@ -308,86 +341,153 @@ impl ConnectorData {
pub fn convert_connector(
_connectors: &Connectors,
connector_name: &str,
) -> CustomResult<BoxedConnector, errors::ApiErrorResponse> {
) -> CustomResult<ConnectorEnum, errors::ApiErrorResponse> {
match enums::Connector::from_str(connector_name) {
Ok(name) => match name {
enums::Connector::Aci => Ok(Box::new(&connector::Aci)),
enums::Connector::Adyen => Ok(Box::new(&connector::Adyen)),
enums::Connector::Adyenplatform => Ok(Box::new(&connector::Adyenplatform)),
enums::Connector::Airwallex => Ok(Box::new(&connector::Airwallex)),
enums::Connector::Authorizedotnet => Ok(Box::new(&connector::Authorizedotnet)),
enums::Connector::Bambora => Ok(Box::new(&connector::Bambora)),
enums::Connector::Bankofamerica => Ok(Box::new(&connector::Bankofamerica)),
enums::Connector::Billwerk => Ok(Box::new(&connector::Billwerk)),
enums::Connector::Bitpay => Ok(Box::new(&connector::Bitpay)),
enums::Connector::Bluesnap => Ok(Box::new(connector::Bluesnap::new())),
enums::Connector::Boku => Ok(Box::new(&connector::Boku)),
enums::Connector::Braintree => Ok(Box::new(&connector::Braintree)),
enums::Connector::Cashtocode => Ok(Box::new(&connector::Cashtocode)),
enums::Connector::Checkout => Ok(Box::new(&connector::Checkout)),
enums::Connector::Coinbase => Ok(Box::new(&connector::Coinbase)),
enums::Connector::Cryptopay => Ok(Box::new(connector::Cryptopay::new())),
enums::Connector::Cybersource => Ok(Box::new(&connector::Cybersource)),
// enums::Connector::Datatrans => Ok(Box::new(&connector::Datatrans)), added as template code for future use
enums::Connector::Dlocal => Ok(Box::new(&connector::Dlocal)),
enums::Connector::Aci => Ok(ConnectorEnum::Old(Box::new(&connector::Aci))),
enums::Connector::Adyen => Ok(ConnectorEnum::Old(Box::new(&connector::Adyen))),
enums::Connector::Adyenplatform => {
Ok(ConnectorEnum::Old(Box::new(&connector::Adyenplatform)))
}
enums::Connector::Airwallex => {
Ok(ConnectorEnum::Old(Box::new(&connector::Airwallex)))
}
enums::Connector::Authorizedotnet => {
Ok(ConnectorEnum::Old(Box::new(&connector::Authorizedotnet)))
}
enums::Connector::Bambora => Ok(ConnectorEnum::Old(Box::new(&connector::Bambora))),
enums::Connector::Bankofamerica => {
Ok(ConnectorEnum::Old(Box::new(&connector::Bankofamerica)))
}
enums::Connector::Billwerk => {
Ok(ConnectorEnum::Old(Box::new(&connector::Billwerk)))
}
enums::Connector::Bitpay => Ok(ConnectorEnum::Old(Box::new(&connector::Bitpay))),
enums::Connector::Bluesnap => {
Ok(ConnectorEnum::Old(Box::new(connector::Bluesnap::new())))
}
enums::Connector::Boku => Ok(ConnectorEnum::Old(Box::new(&connector::Boku))),
enums::Connector::Braintree => {
Ok(ConnectorEnum::Old(Box::new(&connector::Braintree)))
}
enums::Connector::Cashtocode => {
Ok(ConnectorEnum::Old(Box::new(&connector::Cashtocode)))
}
enums::Connector::Checkout => {
Ok(ConnectorEnum::Old(Box::new(&connector::Checkout)))
}
enums::Connector::Coinbase => {
Ok(ConnectorEnum::Old(Box::new(&connector::Coinbase)))
}
enums::Connector::Cryptopay => {
Ok(ConnectorEnum::Old(Box::new(connector::Cryptopay::new())))
}
enums::Connector::Cybersource => {
Ok(ConnectorEnum::Old(Box::new(&connector::Cybersource)))
}
enums::Connector::Dlocal => Ok(ConnectorEnum::Old(Box::new(&connector::Dlocal))),
#[cfg(feature = "dummy_connector")]
enums::Connector::DummyConnector1 => Ok(Box::new(&connector::DummyConnector::<1>)),
enums::Connector::DummyConnector1 => Ok(ConnectorEnum::Old(Box::new(
&connector::DummyConnector::<1>,
))),
#[cfg(feature = "dummy_connector")]
enums::Connector::DummyConnector2 => Ok(Box::new(&connector::DummyConnector::<2>)),
enums::Connector::DummyConnector2 => Ok(ConnectorEnum::Old(Box::new(
&connector::DummyConnector::<2>,
))),
#[cfg(feature = "dummy_connector")]
enums::Connector::DummyConnector3 => Ok(Box::new(&connector::DummyConnector::<3>)),
enums::Connector::DummyConnector3 => Ok(ConnectorEnum::Old(Box::new(
&connector::DummyConnector::<3>,
))),
#[cfg(feature = "dummy_connector")]
enums::Connector::DummyConnector4 => Ok(Box::new(&connector::DummyConnector::<4>)),
enums::Connector::DummyConnector4 => Ok(ConnectorEnum::Old(Box::new(
&connector::DummyConnector::<4>,
))),
#[cfg(feature = "dummy_connector")]
enums::Connector::DummyConnector5 => Ok(Box::new(&connector::DummyConnector::<5>)),
enums::Connector::DummyConnector5 => Ok(ConnectorEnum::Old(Box::new(
&connector::DummyConnector::<5>,
))),
#[cfg(feature = "dummy_connector")]
enums::Connector::DummyConnector6 => Ok(Box::new(&connector::DummyConnector::<6>)),
enums::Connector::DummyConnector6 => Ok(ConnectorEnum::Old(Box::new(
&connector::DummyConnector::<6>,
))),
#[cfg(feature = "dummy_connector")]
enums::Connector::DummyConnector7 => Ok(Box::new(&connector::DummyConnector::<7>)),
enums::Connector::Ebanx => Ok(Box::new(&connector::Ebanx)),
enums::Connector::Fiserv => Ok(Box::new(&connector::Fiserv)),
enums::Connector::Forte => Ok(Box::new(&connector::Forte)),
enums::Connector::Globalpay => Ok(Box::new(&connector::Globalpay)),
enums::Connector::Globepay => Ok(Box::new(&connector::Globepay)),
enums::Connector::Gocardless => Ok(Box::new(&connector::Gocardless)),
enums::Connector::Helcim => Ok(Box::new(&connector::Helcim)),
enums::Connector::Iatapay => Ok(Box::new(&connector::Iatapay)),
enums::Connector::Klarna => Ok(Box::new(&connector::Klarna)),
enums::Connector::Mifinity => Ok(Box::new(&connector::Mifinity)),
enums::Connector::Mollie => Ok(Box::new(&connector::Mollie)),
enums::Connector::Nmi => Ok(Box::new(connector::Nmi::new())),
enums::Connector::Noon => Ok(Box::new(connector::Noon::new())),
enums::Connector::Nuvei => Ok(Box::new(&connector::Nuvei)),
enums::Connector::Opennode => Ok(Box::new(&connector::Opennode)),
// "payeezy" => Ok(Box::new(&connector::Payeezy)), As psync and rsync are not supported by this connector, it is added as template code for future usage
enums::Connector::Payme => Ok(Box::new(&connector::Payme)),
enums::Connector::Payone => Ok(Box::new(&connector::Payone)),
enums::Connector::Payu => Ok(Box::new(&connector::Payu)),
enums::Connector::Placetopay => Ok(Box::new(&connector::Placetopay)),
enums::Connector::Powertranz => Ok(Box::new(&connector::Powertranz)),
enums::Connector::Prophetpay => Ok(Box::new(&connector::Prophetpay)),
enums::Connector::Rapyd => Ok(Box::new(&connector::Rapyd)),
enums::Connector::Shift4 => Ok(Box::new(&connector::Shift4)),
enums::Connector::Square => Ok(Box::new(&connector::Square)),
enums::Connector::Stax => Ok(Box::new(&connector::Stax)),
enums::Connector::Stripe => Ok(Box::new(connector::Stripe::new())),
enums::Connector::Wise => Ok(Box::new(&connector::Wise)),
enums::Connector::Worldline => Ok(Box::new(&connector::Worldline)),
enums::Connector::Worldpay => Ok(Box::new(&connector::Worldpay)),
enums::Connector::Multisafepay => Ok(Box::new(&connector::Multisafepay)),
enums::Connector::Nexinets => Ok(Box::new(&connector::Nexinets)),
enums::Connector::Paypal => Ok(Box::new(&connector::Paypal)),
enums::Connector::Trustpay => Ok(Box::new(&connector::Trustpay)),
enums::Connector::Tsys => Ok(Box::new(&connector::Tsys)),
enums::Connector::Volt => Ok(Box::new(&connector::Volt)),
enums::Connector::Zen => Ok(Box::new(&connector::Zen)),
enums::Connector::Zsl => Ok(Box::new(&connector::Zsl)),
enums::Connector::DummyConnector7 => Ok(ConnectorEnum::Old(Box::new(
&connector::DummyConnector::<7>,
))),
enums::Connector::Ebanx => Ok(ConnectorEnum::Old(Box::new(&connector::Ebanx))),
enums::Connector::Fiserv => Ok(ConnectorEnum::Old(Box::new(&connector::Fiserv))),
enums::Connector::Forte => Ok(ConnectorEnum::Old(Box::new(&connector::Forte))),
enums::Connector::Globalpay => {
Ok(ConnectorEnum::Old(Box::new(&connector::Globalpay)))
}
enums::Connector::Globepay => {
Ok(ConnectorEnum::Old(Box::new(&connector::Globepay)))
}
enums::Connector::Gocardless => {
Ok(ConnectorEnum::Old(Box::new(&connector::Gocardless)))
}
enums::Connector::Helcim => Ok(ConnectorEnum::Old(Box::new(&connector::Helcim))),
enums::Connector::Iatapay => Ok(ConnectorEnum::Old(Box::new(&connector::Iatapay))),
enums::Connector::Klarna => Ok(ConnectorEnum::Old(Box::new(&connector::Klarna))),
enums::Connector::Mollie => Ok(ConnectorEnum::Old(Box::new(&connector::Mollie))),
enums::Connector::Nmi => Ok(ConnectorEnum::Old(Box::new(connector::Nmi::new()))),
enums::Connector::Noon => Ok(ConnectorEnum::Old(Box::new(connector::Noon::new()))),
enums::Connector::Nuvei => Ok(ConnectorEnum::Old(Box::new(&connector::Nuvei))),
enums::Connector::Opennode => {
Ok(ConnectorEnum::Old(Box::new(&connector::Opennode)))
}
// "payeezy" => Ok(ConnectorIntegrationEnum::Old(Box::new(&connector::Payeezy)), As psync and rsync are not supported by this connector, it is added as template code for future usage
enums::Connector::Payme => Ok(ConnectorEnum::Old(Box::new(&connector::Payme))),
enums::Connector::Payone => Ok(ConnectorEnum::Old(Box::new(&connector::Payone))),
enums::Connector::Payu => Ok(ConnectorEnum::Old(Box::new(&connector::Payu))),
enums::Connector::Placetopay => {
Ok(ConnectorEnum::Old(Box::new(&connector::Placetopay)))
}
enums::Connector::Powertranz => {
Ok(ConnectorEnum::Old(Box::new(&connector::Powertranz)))
}
enums::Connector::Prophetpay => {
Ok(ConnectorEnum::Old(Box::new(&connector::Prophetpay)))
}
enums::Connector::Rapyd => Ok(ConnectorEnum::Old(Box::new(&connector::Rapyd))),
enums::Connector::Shift4 => Ok(ConnectorEnum::Old(Box::new(&connector::Shift4))),
enums::Connector::Square => Ok(ConnectorEnum::Old(Box::new(&connector::Square))),
enums::Connector::Stax => Ok(ConnectorEnum::Old(Box::new(&connector::Stax))),
enums::Connector::Stripe => {
Ok(ConnectorEnum::Old(Box::new(connector::Stripe::new())))
}
enums::Connector::Wise => Ok(ConnectorEnum::Old(Box::new(&connector::Wise))),
enums::Connector::Worldline => {
Ok(ConnectorEnum::Old(Box::new(&connector::Worldline)))
}
enums::Connector::Worldpay => {
Ok(ConnectorEnum::Old(Box::new(&connector::Worldpay)))
}
enums::Connector::Mifinity => {
Ok(ConnectorEnum::Old(Box::new(&connector::Mifinity)))
}
enums::Connector::Multisafepay => {
Ok(ConnectorEnum::Old(Box::new(&connector::Multisafepay)))
}
enums::Connector::Netcetera => {
Ok(ConnectorEnum::Old(Box::new(&connector::Netcetera)))
}
enums::Connector::Nexinets => {
Ok(ConnectorEnum::Old(Box::new(&connector::Nexinets)))
}
enums::Connector::Paypal => Ok(ConnectorEnum::Old(Box::new(&connector::Paypal))),
enums::Connector::Trustpay => {
Ok(ConnectorEnum::Old(Box::new(&connector::Trustpay)))
}
enums::Connector::Tsys => Ok(ConnectorEnum::Old(Box::new(&connector::Tsys))),
enums::Connector::Volt => Ok(ConnectorEnum::Old(Box::new(&connector::Volt))),
enums::Connector::Zen => Ok(ConnectorEnum::Old(Box::new(&connector::Zen))),
enums::Connector::Zsl => Ok(ConnectorEnum::Old(Box::new(&connector::Zsl))),
enums::Connector::Signifyd
| enums::Connector::Plaid
| enums::Connector::Riskified
| enums::Connector::Threedsecureio
| enums::Connector::Gpayments
| enums::Connector::Netcetera => {
| enums::Connector::Threedsecureio => {
Err(report!(errors::ConnectorError::InvalidConnectorName)
.attach_printable(format!("invalid connector name: {connector_name}")))
.change_context(errors::ApiErrorResponse::InternalServerError)

View File

@ -9,7 +9,6 @@ pub use super::authentication_v2::{
ConnectorAuthenticationV2, ConnectorPostAuthenticationV2, ConnectorPreAuthenticationV2,
ConnectorPreAuthenticationVersionCallV2, ExternalAuthenticationV2,
};
use super::BoxedConnector;
use crate::core::errors;
#[derive(Debug, Clone)]
@ -23,7 +22,10 @@ pub struct Authentication;
#[derive(Debug, Clone)]
pub struct PostAuthentication;
use crate::{connector, services, types, types::storage};
use crate::{
connector, services, services::connector_integration_interface::ConnectorEnum, types,
types::storage,
};
#[derive(Clone, serde::Deserialize, Debug, serde::Serialize)]
pub struct AcquirerDetails {
@ -126,7 +128,7 @@ pub trait ExternalAuthentication:
#[derive(Clone)]
pub struct AuthenticationConnectorData {
pub connector: BoxedConnector,
pub connector: ConnectorEnum,
pub connector_name: enums::AuthenticationConnectors,
}
@ -144,13 +146,17 @@ impl AuthenticationConnectorData {
fn convert_connector(
connector_name: enums::AuthenticationConnectors,
) -> CustomResult<BoxedConnector, errors::ApiErrorResponse> {
) -> CustomResult<ConnectorEnum, errors::ApiErrorResponse> {
match connector_name {
enums::AuthenticationConnectors::Threedsecureio => {
Ok(Box::new(&connector::Threedsecureio))
Ok(ConnectorEnum::Old(Box::new(&connector::Threedsecureio)))
}
enums::AuthenticationConnectors::Netcetera => {
Ok(ConnectorEnum::Old(Box::new(&connector::Netcetera)))
}
enums::AuthenticationConnectors::Gpayments => {
Ok(ConnectorEnum::Old(Box::new(&connector::Gpayments)))
}
enums::AuthenticationConnectors::Netcetera => Ok(Box::new(&connector::Netcetera)),
enums::AuthenticationConnectors::Gpayments => Ok(Box::new(&connector::Gpayments)),
}
}
}

View File

@ -11,11 +11,11 @@ pub use super::fraud_check_v2::{
FraudCheckCheckoutV2, FraudCheckFulfillmentV2, FraudCheckRecordReturnV2, FraudCheckSaleV2,
FraudCheckTransactionV2, FraudCheckV2,
};
use super::{BoxedConnector, ConnectorData, SessionConnectorData};
use super::{ConnectorData, SessionConnectorData};
use crate::{
connector,
core::errors,
services::api,
services::{api, connector_integration_interface::ConnectorEnum},
types::fraud_check::{
FraudCheckCheckoutData, FraudCheckFulfillmentData, FraudCheckRecordReturnData,
FraudCheckResponseData, FraudCheckSaleData, FraudCheckTransactionData,
@ -49,7 +49,7 @@ pub trait FraudCheckRecordReturn:
#[derive(Clone)]
pub struct FraudCheckConnectorData {
pub connector: BoxedConnector,
pub connector: ConnectorEnum,
pub connector_name: enums::FrmConnectors,
}
pub enum ConnectorCallType {
@ -74,10 +74,14 @@ impl FraudCheckConnectorData {
fn convert_connector(
connector_name: enums::FrmConnectors,
) -> CustomResult<BoxedConnector, errors::ApiErrorResponse> {
) -> CustomResult<ConnectorEnum, errors::ApiErrorResponse> {
match connector_name {
enums::FrmConnectors::Signifyd => Ok(Box::new(&connector::Signifyd)),
enums::FrmConnectors::Riskified => Ok(Box::new(&connector::Riskified)),
enums::FrmConnectors::Signifyd => {
Ok(ConnectorEnum::Old(Box::new(&connector::Signifyd)))
}
enums::FrmConnectors::Riskified => {
Ok(ConnectorEnum::Old(Box::new(&connector::Riskified)))
}
}
}
}

View File

@ -5,15 +5,17 @@ use error_stack::ResultExt;
use crate::{
consts,
core::errors,
services,
services::ConnectorIntegration,
types::{self, api, domain, storage::enums as storage_enums},
services::{
self,
connector_integration_interface::{BoxedConnectorIntegrationInterface, ConnectorEnum},
},
types::{self, api, api::ConnectorCommon, domain, storage::enums as storage_enums},
SessionState,
};
#[derive(Clone)]
pub struct VerifyConnectorData {
pub connector: &'static (dyn api::Connector + Sync),
pub connector: ConnectorEnum,
pub connector_auth: types::ConnectorAuthType,
pub card_details: domain::Card,
}
@ -124,6 +126,7 @@ pub trait VerifyConnector {
let request = connector_data
.connector
.get_connector_integration()
.build_request(&router_data, &state.conf.connectors)
.change_context(errors::ApiErrorResponse::InvalidRequestData {
message: "Payment request cannot be built".to_string(),
@ -140,9 +143,13 @@ pub trait VerifyConnector {
Err(error_response) => {
Self::handle_payment_error_response::<
api::Authorize,
types::PaymentFlowData,
types::PaymentsAuthorizeData,
types::PaymentsResponseData,
>(connector_data.connector, error_response)
>(
connector_data.connector.get_connector_integration(),
error_response,
)
.await
}
}
@ -157,13 +164,11 @@ pub trait VerifyConnector {
Ok(None)
}
async fn handle_payment_error_response<F, R1, R2>(
connector: &(dyn api::Connector + Sync),
async fn handle_payment_error_response<F, ResourceCommonData, Req, Resp>(
// connector: &(dyn api::Connector + Sync),
connector: BoxedConnectorIntegrationInterface<F, ResourceCommonData, Req, Resp>,
error_response: types::Response,
) -> errors::RouterResponse<()>
where
dyn api::Connector + Sync: ConnectorIntegration<F, R1, R2>,
{
) -> errors::RouterResponse<()> {
let error = connector
.get_error_response(error_response, None)
.change_context(errors::ApiErrorResponse::InternalServerError)?;
@ -173,13 +178,10 @@ pub trait VerifyConnector {
.into())
}
async fn handle_access_token_error_response<F, R1, R2>(
connector: &(dyn api::Connector + Sync),
async fn handle_access_token_error_response<F, ResourceCommonData, Req, Resp>(
connector: BoxedConnectorIntegrationInterface<F, ResourceCommonData, Req, Resp>,
error_response: types::Response,
) -> errors::RouterResult<Option<types::AccessToken>>
where
dyn api::Connector + Sync: ConnectorIntegration<F, R1, R2>,
{
) -> errors::RouterResult<Option<types::AccessToken>> {
let error = connector
.get_error_response(error_response, None)
.change_context(errors::ApiErrorResponse::InternalServerError)?;

View File

@ -21,6 +21,7 @@ impl VerifyConnector for connector::Paypal {
let request = connector_data
.connector
.get_connector_integration()
.build_request(&router_data, &state.conf.connectors)
.change_context(errors::ApiErrorResponse::InvalidRequestData {
message: "Payment request cannot be built".to_string(),
@ -35,6 +36,7 @@ impl VerifyConnector for connector::Paypal {
Ok(res) => Some(
connector_data
.connector
.get_connector_integration()
.handle_response(&router_data, None, res)
.change_context(errors::ApiErrorResponse::InternalServerError)?
.response
@ -44,9 +46,13 @@ impl VerifyConnector for connector::Paypal {
Err(response_data) => {
Self::handle_access_token_error_response::<
api::AccessTokenAuth,
types::AccessTokenFlowData,
types::AccessTokenRequestData,
types::AccessToken,
>(connector_data.connector, response_data)
>(
connector_data.connector.get_connector_integration(),
response_data,
)
.await
}
}

View File

@ -3,21 +3,16 @@ use router_env::env;
use super::VerifyConnector;
use crate::{
connector,
core::errors,
services::{self, ConnectorIntegration},
types,
connector, core::errors, services, types,
types::api::verify_connector::BoxedConnectorIntegrationInterface,
};
#[async_trait::async_trait]
impl VerifyConnector for connector::Stripe {
async fn handle_payment_error_response<F, R1, R2>(
connector: &(dyn types::api::Connector + Sync),
async fn handle_payment_error_response<F, ResourceCommonData, Req, Resp>(
connector: BoxedConnectorIntegrationInterface<F, ResourceCommonData, Req, Resp>,
error_response: types::Response,
) -> errors::RouterResponse<()>
where
dyn types::api::Connector + Sync: ConnectorIntegration<F, R1, R2>,
{
) -> errors::RouterResponse<()> {
let error = connector
.get_error_response(error_response, None)
.change_context(errors::ApiErrorResponse::InternalServerError)?;

View File

@ -160,8 +160,7 @@ pub trait IncomingWebhook: ConnectorCommon + Sync {
)
.change_context(errors::ConnectorError::WebhookSourceVerificationFailed)
.attach_printable("invalid connector name received in payment attempt")?;
let connector_integration: services::BoxedConnectorIntegration<
'_,
let connector_integration: services::BoxedWebhookSourceVerificationConnectorIntegrationInterface<
types::api::VerifyWebhookSource,
types::VerifyWebhookSourceRequestData,
types::VerifyWebhookSourceResponseData,

View File

@ -26,7 +26,7 @@ pub async fn generate_access_token(state: SessionState) -> RouterResult<types::A
connector::Paypal::get_access_token(
&state,
verify_connector_types::VerifyConnectorData {
connector: *boxed_connector,
connector: boxed_connector,
connector_auth,
card_details: verify_connector_utils::get_test_card_details(connector)?.ok_or(
ApiErrorResponse::FlowNotSupported {