feat(connector): Add recovery support for stripebilling (#7461)

Co-authored-by: Nishanth Challa <nishanth.challa@Nishanth-Challa-C0WGKCFHLF.local>
Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
Co-authored-by: Aniket Burman <93077964+aniketburman014@users.noreply.github.com>
This commit is contained in:
CHALLA NISHANTH BABU
2025-04-02 12:48:19 +05:30
committed by GitHub
parent 7358b3a3b9
commit cfe226943d
34 changed files with 1252 additions and 528 deletions

View File

@ -506,7 +506,7 @@ pub(crate) async fn fetch_raw_secrets(
required_fields: conf.required_fields,
delayed_session_response: conf.delayed_session_response,
webhook_source_verification_call: conf.webhook_source_verification_call,
// additional_revenue_recovery_details_call: conf.additional_revenue_recovery_details_call,
billing_connectors_payment_sync: conf.billing_connectors_payment_sync,
payment_method_auth,
connector_request_reference_id_config: conf.connector_request_reference_id_config,
#[cfg(feature = "payouts")]

View File

@ -96,7 +96,7 @@ pub struct Settings<S: SecretState> {
pub required_fields: RequiredFields,
pub delayed_session_response: DelayedSessionConfig,
pub webhook_source_verification_call: WebhookSourceVerificationCall,
// pub additional_revenue_recovery_details_call: GetAdditionalRevenueRecoveryDetailsCall,
pub billing_connectors_payment_sync: BillingConnectorPaymentsSyncCall,
pub payment_method_auth: SecretStateContainer<PaymentMethodAuth, S>,
pub connector_request_reference_id_config: ConnectorRequestReferenceIdConfig,
#[cfg(feature = "payouts")]
@ -848,9 +848,9 @@ pub struct WebhookSourceVerificationCall {
}
#[derive(Debug, Deserialize, Clone, Default)]
pub struct GetAdditionalRevenueRecoveryDetailsCall {
pub struct BillingConnectorPaymentsSyncCall {
#[serde(deserialize_with = "deserialize_hashset")]
pub connectors_with_additional_revenue_recovery_details_call: HashSet<enums::Connector>,
pub billing_connectors_which_require_payment_sync: HashSet<enums::Connector>,
}
#[derive(Debug, Deserialize, Clone, Default)]

View File

@ -1573,10 +1573,10 @@ impl ConnectorAuthTypeAndMetadataValidation<'_> {
stripe::transformers::StripeAuthType::try_from(self.auth_type)?;
Ok(())
}
// api_enums::Connector::Stripebilling => {
// stripebilling::transformers::StripebillingAuthType::try_from(self.auth_type)?;
// Ok(())
// }
api_enums::Connector::Stripebilling => {
stripebilling::transformers::StripebillingAuthType::try_from(self.auth_type)?;
Ok(())
}
api_enums::Connector::Trustpay => {
trustpay::transformers::TrustpayAuthType::try_from(self.auth_type)?;
Ok(())

View File

@ -498,4 +498,6 @@ pub enum RevenueRecoveryError {
ProcessTrackerCreationError,
#[error("Failed to get the response from process tracker")]
ProcessTrackerResponseError,
#[error("Billing connector psync call failed")]
BillingConnectorPaymentsSyncFailed,
}

View File

@ -14,7 +14,7 @@ pub mod setup_mandate_flow;
use async_trait::async_trait;
#[cfg(all(feature = "v2", feature = "revenue_recovery"))]
use hyperswitch_domain_models::router_flow_types::{
revenue_recovery::RecoveryRecordBack, GetAdditionalRevenueRecoveryDetails,
BillingConnectorPaymentsSync, RecoveryRecordBack,
};
use hyperswitch_domain_models::{
mandates::CustomerAcceptance,
@ -1979,6 +1979,77 @@ fn handle_post_capture_response(
}
}
macro_rules! default_imp_for_revenue_recovery {
($($path:ident::$connector:ident),*) => {
$( impl api::RevenueRecovery for $path::$connector {}
)*
};
}
#[cfg(feature = "dummy_connector")]
impl<const T: u8> api::RevenueRecovery for connector::DummyConnector<T> {}
default_imp_for_revenue_recovery! {
connector::Adyenplatform,
connector::Ebanx,
connector::Gpayments,
connector::Netcetera,
connector::Nmi,
connector::Payone,
connector::Plaid,
connector::Riskified,
connector::Signifyd,
connector::Stripe,
connector::Threedsecureio,
connector::Wellsfargopayout,
connector::Wise
}
#[cfg(all(feature = "v2", feature = "revenue_recovery"))]
macro_rules! default_imp_for_billing_connector_payment_sync {
($($path:ident::$connector:ident),*) => {
$( impl api::BillingConnectorPaymentsSyncIntegration for $path::$connector {}
impl
services::ConnectorIntegration<
BillingConnectorPaymentsSync,
types::BillingConnectorPaymentsSyncRequest,
types::BillingConnectorPaymentsSyncResponse,
> for $path::$connector
{}
)*
};
}
#[cfg(all(feature = "v2", feature = "revenue_recovery"))]
#[cfg(feature = "dummy_connector")]
impl<const T: u8> api::BillingConnectorPaymentsSyncIntegration for connector::DummyConnector<T> {}
#[cfg(all(feature = "v2", feature = "revenue_recovery"))]
#[cfg(feature = "dummy_connector")]
impl<const T: u8>
services::ConnectorIntegration<
BillingConnectorPaymentsSync,
types::BillingConnectorPaymentsSyncRequest,
types::BillingConnectorPaymentsSyncResponse,
> for connector::DummyConnector<T>
{
}
#[cfg(all(feature = "v2", feature = "revenue_recovery"))]
default_imp_for_billing_connector_payment_sync!(
connector::Adyenplatform,
connector::Ebanx,
connector::Gpayments,
connector::Netcetera,
connector::Nmi,
connector::Payone,
connector::Plaid,
connector::Riskified,
connector::Signifyd,
connector::Stripe,
connector::Threedsecureio,
connector::Wellsfargopayout,
connector::Wise
);
#[cfg(all(feature = "v2", feature = "revenue_recovery"))]
macro_rules! default_imp_for_revenue_recovery_record_back {
($($path:ident::$connector:ident),*) => {
@ -1994,7 +2065,6 @@ macro_rules! default_imp_for_revenue_recovery_record_back {
)*
};
}
#[cfg(all(feature = "v2", feature = "revenue_recovery"))]
#[cfg(feature = "dummy_connector")]
impl<const T: u8> api::RevenueRecoveryRecordBack for connector::DummyConnector<T> {}
@ -2024,76 +2094,3 @@ default_imp_for_revenue_recovery_record_back!(
connector::Wellsfargopayout,
connector::Wise
);
macro_rules! default_imp_for_revenue_recovery {
($($path:ident::$connector:ident),*) => {
$( impl api::RevenueRecovery for $path::$connector {}
)*
};
}
#[cfg(feature = "dummy_connector")]
impl<const T: u8> api::RevenueRecovery for connector::DummyConnector<T> {}
default_imp_for_revenue_recovery! {
connector::Adyenplatform,
connector::Ebanx,
connector::Gpayments,
connector::Netcetera,
connector::Nmi,
connector::Payone,
connector::Plaid,
connector::Riskified,
connector::Signifyd,
connector::Stripe,
connector::Threedsecureio,
connector::Wellsfargopayout,
connector::Wise
}
#[cfg(all(feature = "v2", feature = "revenue_recovery"))]
macro_rules! default_imp_for_additional_revenue_recovery_call {
($($path:ident::$connector:ident),*) => {
$(
impl api::AdditionalRevenueRecovery for $path::$connector {}
impl
services::ConnectorIntegration<
GetAdditionalRevenueRecoveryDetails,
types::GetAdditionalRevenueRecoveryRequestData,
types::GetAdditionalRevenueRecoveryResponseData,
> for $path::$connector
{}
)*
};
}
#[cfg(all(feature = "v2", feature = "revenue_recovery"))]
#[cfg(feature = "dummy_connector")]
impl<const T: u8> api::AdditionalRevenueRecovery for connector::DummyConnector<T> {}
#[cfg(all(feature = "v2", feature = "revenue_recovery"))]
#[cfg(feature = "dummy_connector")]
impl<const T: u8>
services::ConnectorIntegration<
GetAdditionalRevenueRecoveryDetails,
types::GetAdditionalRevenueRecoveryRequestData,
types::GetAdditionalRevenueRecoveryResponseData,
> for connector::DummyConnector<T>
{
}
#[cfg(all(feature = "v2", feature = "revenue_recovery"))]
default_imp_for_additional_revenue_recovery_call!(
connector::Adyenplatform,
connector::Ebanx,
connector::Gpayments,
connector::Netcetera,
connector::Nmi,
connector::Payone,
connector::Plaid,
connector::Riskified,
connector::Signifyd,
connector::Stripe,
connector::Threedsecureio,
connector::Wellsfargopayout,
connector::Wise
);

View File

@ -361,10 +361,12 @@ async fn incoming_webhooks_core<W: types::OutgoingWebhookType>(
webhook_details,
source_verified,
&connector,
merchant_connector_account,
&connector_name,
&request_details,
event_type,
req_state,
merchant_connector_account,
&object_ref_id,
))
.await
.change_context(errors::ApiErrorResponse::WebhookProcessingFailure)

View File

@ -1,8 +1,17 @@
use std::{marker::PhantomData, str::FromStr};
use api_models::{payments as api_payments, webhooks};
use common_utils::{ext_traits::AsyncExt, id_type};
use common_utils::{
ext_traits::{AsyncExt, ValueExt},
id_type,
};
use diesel_models::{process_tracker as storage, schema::process_tracker::retry_count};
use error_stack::{report, ResultExt};
use hyperswitch_domain_models::{errors::api_error_response, revenue_recovery};
use hyperswitch_domain_models::{
errors::api_error_response, revenue_recovery, router_data_v2::flow_common_types,
router_flow_types, router_request_types::revenue_recovery as revenue_recovery_request,
router_response_types::revenue_recovery as revenue_recovery_response, types as router_types,
};
use hyperswitch_interfaces::webhooks as interface_webhooks;
use router_env::{instrument, tracing};
use serde_with::rust::unwrap_or_skip;
@ -10,12 +19,15 @@ use serde_with::rust::unwrap_or_skip;
use crate::{
core::{
errors::{self, CustomResult},
payments,
payments::{self, helpers},
},
db::StorageInterface,
db::{errors::RevenueRecoveryError, StorageInterface},
routes::{app::ReqState, metrics, SessionState},
services::{self, connector_integration_interface},
types::{api, domain, storage::revenue_recovery as storage_churn_recovery},
services::{
self,
connector_integration_interface::{self, RouterDataConversion},
},
types::{self, api, domain, storage::revenue_recovery as storage_churn_recovery},
workflows::revenue_recovery as revenue_recovery_flow,
};
@ -29,28 +41,50 @@ pub async fn recovery_incoming_webhook_flow(
key_store: domain::MerchantKeyStore,
_webhook_details: api::IncomingWebhookDetails,
source_verified: bool,
connector: &connector_integration_interface::ConnectorEnum,
connector_enum: &connector_integration_interface::ConnectorEnum,
billing_connector_account: hyperswitch_domain_models::merchant_connector_account::MerchantConnectorAccount,
connector_name: &str,
request_details: &hyperswitch_interfaces::webhooks::IncomingWebhookRequestDetails<'_>,
event_type: webhooks::IncomingWebhookEvent,
req_state: ReqState,
billing_connector_account: domain::MerchantConnectorAccount,
object_ref_id: &webhooks::ObjectReferenceId,
) -> CustomResult<webhooks::WebhookResponseTracker, errors::RevenueRecoveryError> {
// Source verification is necessary for revenue recovery webhooks flow since We don't have payment intent/attempt object created before in our system.
common_utils::fp_utils::when(!source_verified, || {
Err(report!(
errors::RevenueRecoveryError::WebhookAuthenticationFailed
))
})?;
let invoice_details = RevenueRecoveryInvoice(
interface_webhooks::IncomingWebhook::get_revenue_recovery_invoice_details(
connector,
request_details,
)
let connector = api_models::enums::Connector::from_str(connector_name)
.change_context(errors::RevenueRecoveryError::InvoiceWebhookProcessingFailed)
.attach_printable("Failed while getting revenue recovery invoice details")?,
);
.attach_printable_lazy(|| format!("unable to parse connector name {connector_name:?}"))?;
let billing_connectors_with_payment_sync_call = &state.conf.billing_connectors_payment_sync;
let should_billing_connector_payment_api_called = billing_connectors_with_payment_sync_call
.billing_connectors_which_require_payment_sync
.contains(&connector);
let billing_connector_payment_details =
BillingConnectorPaymentsSyncResponseData::get_billing_connector_payment_details(
should_billing_connector_payment_api_called,
&state,
&merchant_account,
&billing_connector_account,
connector_name,
object_ref_id,
)
.await?;
// Checks whether we have data in recovery_details , If its there then it will use the data and convert it into required from or else fetches from Incoming webhook
let invoice_details = RevenueRecoveryInvoice::get_recovery_invoice_details(
connector_enum,
request_details,
billing_connector_payment_details.as_ref(),
)?;
// Fetch the intent using merchant reference id, if not found create new intent.
let payment_intent = invoice_details
.get_payment_intent(
@ -75,55 +109,22 @@ pub async fn recovery_incoming_webhook_flow(
})
.await?;
let payment_attempt = match event_type.is_recovery_transaction_event() {
true => {
let invoice_transaction_details = RevenueRecoveryAttempt(
interface_webhooks::IncomingWebhook::get_revenue_recovery_attempt_details(
connector,
request_details,
)
.change_context(errors::RevenueRecoveryError::TransactionWebhookProcessingFailed)?,
);
// Find the payment merchant connector ID at the top level to avoid multiple DB calls.
let payment_merchant_connector_account = invoice_transaction_details
.find_payment_merchant_connector_account(
&state,
&key_store,
&billing_connector_account,
)
.await?;
let is_event_recovery_transaction_event = event_type.is_recovery_transaction_event();
Some(
invoice_transaction_details
.get_payment_attempt(
&state,
&req_state,
&merchant_account,
&business_profile,
&key_store,
payment_intent.payment_id.clone(),
)
.await
.transpose()
.async_unwrap_or_else(|| async {
invoice_transaction_details
.record_payment_attempt(
&state,
&req_state,
&merchant_account,
&business_profile,
&key_store,
payment_intent.payment_id.clone(),
&billing_connector_account.id,
payment_merchant_connector_account,
)
.await
})
.await?,
)
}
false => None,
};
let payment_attempt = RevenueRecoveryAttempt::get_recovery_payment_attempt(
is_event_recovery_transaction_event,
&billing_connector_account,
&state,
&key_store,
connector_enum,
&req_state,
billing_connector_payment_details.as_ref(),
request_details,
&merchant_account,
&business_profile,
&payment_intent,
)
.await?;
let attempt_triggered_by = payment_attempt
.as_ref()
@ -170,11 +171,37 @@ pub async fn recovery_incoming_webhook_flow(
}
}
}
#[derive(Debug)]
pub struct RevenueRecoveryInvoice(revenue_recovery::RevenueRecoveryInvoiceData);
#[derive(Debug)]
pub struct RevenueRecoveryAttempt(revenue_recovery::RevenueRecoveryAttemptData);
impl RevenueRecoveryInvoice {
fn get_recovery_invoice_details(
connector_enum: &connector_integration_interface::ConnectorEnum,
request_details: &hyperswitch_interfaces::webhooks::IncomingWebhookRequestDetails<'_>,
billing_connector_payment_details: Option<
&revenue_recovery_response::BillingConnectorPaymentsSyncResponse,
>,
) -> CustomResult<Self, errors::RevenueRecoveryError> {
billing_connector_payment_details.map_or_else(
|| {
interface_webhooks::IncomingWebhook::get_revenue_recovery_invoice_details(
connector_enum,
request_details,
)
.change_context(errors::RevenueRecoveryError::InvoiceWebhookProcessingFailed)
.attach_printable("Failed while getting revenue recovery invoice details")
.map(RevenueRecoveryInvoice)
},
|data| {
Ok(Self(revenue_recovery::RevenueRecoveryInvoiceData::from(
data,
)))
},
)
}
async fn get_payment_intent(
&self,
state: &SessionState,
@ -236,12 +263,12 @@ impl RevenueRecoveryInvoice {
let global_payment_id = id_type::GlobalPaymentId::generate(&state.conf.cell_information.id);
let create_intent_response = Box::pin(payments::payments_intent_core::<
hyperswitch_domain_models::router_flow_types::payments::PaymentCreateIntent,
router_flow_types::payments::PaymentCreateIntent,
api_payments::PaymentsIntentResponse,
_,
_,
hyperswitch_domain_models::payments::PaymentIntentData<
hyperswitch_domain_models::router_flow_types::payments::PaymentCreateIntent,
router_flow_types::payments::PaymentCreateIntent,
>,
>(
state.clone(),
@ -272,6 +299,33 @@ impl RevenueRecoveryInvoice {
}
impl RevenueRecoveryAttempt {
fn get_recovery_invoice_transaction_details(
connector_enum: &connector_integration_interface::ConnectorEnum,
request_details: &hyperswitch_interfaces::webhooks::IncomingWebhookRequestDetails<'_>,
billing_connector_payment_details: Option<
&revenue_recovery_response::BillingConnectorPaymentsSyncResponse,
>,
) -> CustomResult<Self, errors::RevenueRecoveryError> {
billing_connector_payment_details.map_or_else(
|| {
interface_webhooks::IncomingWebhook::get_revenue_recovery_attempt_details(
connector_enum,
request_details,
)
.change_context(errors::RevenueRecoveryError::TransactionWebhookProcessingFailed)
.attach_printable(
"Failed to get recovery attempt details from the billing connector",
)
.map(RevenueRecoveryAttempt)
},
|data| {
Ok(Self(revenue_recovery::RevenueRecoveryAttemptData::from(
data,
)))
},
)
}
async fn get_payment_attempt(
&self,
state: &SessionState,
@ -283,13 +337,13 @@ impl RevenueRecoveryAttempt {
) -> CustomResult<Option<revenue_recovery::RecoveryPaymentAttempt>, errors::RevenueRecoveryError>
{
let attempt_response = Box::pin(payments::payments_core::<
hyperswitch_domain_models::router_flow_types::payments::PSync,
router_flow_types::payments::PSync,
api_payments::PaymentsResponse,
_,
_,
_,
hyperswitch_domain_models::payments::PaymentStatusData<
hyperswitch_domain_models::router_flow_types::payments::PSync,
router_flow_types::payments::PSync,
>,
>(
state.clone(),
@ -447,6 +501,76 @@ impl RevenueRecoveryAttempt {
Ok(payment_merchant_connector_account)
}
#[allow(clippy::too_many_arguments)]
async fn get_recovery_payment_attempt(
is_recovery_transaction_event: bool,
billing_connector_account: &domain::MerchantConnectorAccount,
state: &SessionState,
key_store: &domain::MerchantKeyStore,
connector_enum: &connector_integration_interface::ConnectorEnum,
req_state: &ReqState,
billing_connector_payment_details: Option<
&revenue_recovery_response::BillingConnectorPaymentsSyncResponse,
>,
request_details: &hyperswitch_interfaces::webhooks::IncomingWebhookRequestDetails<'_>,
merchant_account: &domain::MerchantAccount,
business_profile: &domain::Profile,
payment_intent: &revenue_recovery::RecoveryPaymentIntent,
) -> CustomResult<Option<revenue_recovery::RecoveryPaymentAttempt>, errors::RevenueRecoveryError>
{
let recovery_payment_attempt = match is_recovery_transaction_event {
true => {
// Checks whether we have data in recovery_details , If its there then it will use the data and convert it into required from or else fetches from Incoming webhook
let invoice_transaction_details = Self::get_recovery_invoice_transaction_details(
connector_enum,
request_details,
billing_connector_payment_details,
)?;
// Find the payment merchant connector ID at the top level to avoid multiple DB calls.
let payment_merchant_connector_account = invoice_transaction_details
.find_payment_merchant_connector_account(
state,
key_store,
billing_connector_account,
)
.await?;
Some(
invoice_transaction_details
.get_payment_attempt(
state,
req_state,
merchant_account,
business_profile,
key_store,
payment_intent.payment_id.clone(),
)
.await
.transpose()
.async_unwrap_or_else(|| async {
invoice_transaction_details
.record_payment_attempt(
state,
req_state,
merchant_account,
business_profile,
key_store,
payment_intent.payment_id.clone(),
&billing_connector_account.id,
payment_merchant_connector_account,
)
.await
})
.await?,
)
}
false => None,
};
Ok(recovery_payment_attempt)
}
async fn insert_execute_pcr_task(
db: &dyn StorageInterface,
merchant_id: id_type::MerchantId,
@ -522,3 +646,155 @@ impl RevenueRecoveryAttempt {
})
}
}
pub struct BillingConnectorPaymentsSyncResponseData(
revenue_recovery_response::BillingConnectorPaymentsSyncResponse,
);
pub struct BillingConnectorPaymentsSyncFlowRouterData(
router_types::BillingConnectorPaymentsSyncRouterData,
);
impl BillingConnectorPaymentsSyncResponseData {
async fn handle_billing_connector_payment_sync_call(
state: &SessionState,
merchant_account: &domain::MerchantAccount,
merchant_connector_account: &hyperswitch_domain_models::merchant_connector_account::MerchantConnectorAccount,
connector_name: &str,
id: &str,
) -> CustomResult<Self, errors::RevenueRecoveryError> {
let connector_data = api::ConnectorData::get_connector_by_name(
&state.conf.connectors,
connector_name,
api::GetToken::Connector,
None,
)
.change_context(errors::RevenueRecoveryError::BillingConnectorPaymentsSyncFailed)
.attach_printable("invalid connector name received in payment attempt")?;
let connector_integration: services::BoxedBillingConnectorPaymentsSyncIntegrationInterface<
router_flow_types::BillingConnectorPaymentsSync,
revenue_recovery_request::BillingConnectorPaymentsSyncRequest,
revenue_recovery_response::BillingConnectorPaymentsSyncResponse,
> = connector_data.connector.get_connector_integration();
let router_data =
BillingConnectorPaymentsSyncFlowRouterData::construct_router_data_for_billing_connector_payment_sync_call(
state,
connector_name,
merchant_connector_account,
merchant_account,
id,
)
.await
.change_context(errors::RevenueRecoveryError::BillingConnectorPaymentsSyncFailed)
.attach_printable(
"Failed while constructing router data for billing connector psync call",
)?
.inner();
let response = services::execute_connector_processing_step(
state,
connector_integration,
&router_data,
payments::CallConnectorAction::Trigger,
None,
)
.await
.change_context(errors::RevenueRecoveryError::BillingConnectorPaymentsSyncFailed)
.attach_printable("Failed while fetching billing connector payment details")?;
let additional_recovery_details = match response.response {
Ok(response) => Ok(response),
error @ Err(_) => {
router_env::logger::error!(?error);
Err(errors::RevenueRecoveryError::BillingConnectorPaymentsSyncFailed)
.attach_printable("Failed while fetching billing connector payment details")
}
}?;
Ok(Self(additional_recovery_details))
}
async fn get_billing_connector_payment_details(
should_billing_connector_payment_api_called: bool,
state: &SessionState,
merchant_account: &domain::MerchantAccount,
billing_connector_account: &hyperswitch_domain_models::merchant_connector_account::MerchantConnectorAccount,
connector_name: &str,
object_ref_id: &webhooks::ObjectReferenceId,
) -> CustomResult<
Option<revenue_recovery_response::BillingConnectorPaymentsSyncResponse>,
errors::RevenueRecoveryError,
> {
let response_data = match should_billing_connector_payment_api_called {
true => {
let billing_connector_transaction_id = object_ref_id
.clone()
.get_connector_transaction_id_as_string()
.change_context(
errors::RevenueRecoveryError::BillingConnectorPaymentsSyncFailed,
)
.attach_printable("Billing connector Payments api call failed")?;
let billing_connector_payment_details =
Self::handle_billing_connector_payment_sync_call(
state,
merchant_account,
billing_connector_account,
connector_name,
&billing_connector_transaction_id,
)
.await?;
Some(billing_connector_payment_details.inner())
}
false => None,
};
Ok(response_data)
}
fn inner(self) -> revenue_recovery_response::BillingConnectorPaymentsSyncResponse {
self.0
}
}
impl BillingConnectorPaymentsSyncFlowRouterData {
async fn construct_router_data_for_billing_connector_payment_sync_call(
state: &SessionState,
connector_name: &str,
merchant_connector_account: &hyperswitch_domain_models::merchant_connector_account::MerchantConnectorAccount,
merchant_account: &domain::MerchantAccount,
billing_connector_psync_id: &str,
) -> CustomResult<Self, errors::RevenueRecoveryError> {
let auth_type: types::ConnectorAuthType = helpers::MerchantConnectorAccountType::DbVal(
Box::new(merchant_connector_account.clone()),
)
.get_connector_account_details()
.parse_value("ConnectorAuthType")
.change_context(errors::RevenueRecoveryError::BillingConnectorPaymentsSyncFailed)?;
let router_data = types::RouterDataV2 {
flow: PhantomData::<router_flow_types::BillingConnectorPaymentsSync>,
tenant_id: state.tenant.tenant_id.clone(),
resource_common_data: flow_common_types::BillingConnectorPaymentsSyncFlowData,
connector_auth_type: auth_type,
request: revenue_recovery_request::BillingConnectorPaymentsSyncRequest {
billing_connector_psync_id: billing_connector_psync_id.to_string(),
},
response: Err(types::ErrorResponse::default()),
};
let old_router_data =
flow_common_types::BillingConnectorPaymentsSyncFlowData::to_old_router_data(
router_data,
)
.change_context(errors::RevenueRecoveryError::BillingConnectorPaymentsSyncFailed)
.attach_printable(
"Cannot construct router data for making the billing connector payments api call",
)?;
Ok(Self(old_router_data))
}
fn inner(self) -> router_types::BillingConnectorPaymentsSyncRouterData {
self.0
}
}

View File

@ -110,10 +110,10 @@ pub type BoxedRevenueRecoveryRecordBackInterface<T, Req, Res> =
pub type BoxedUnifiedAuthenticationServiceInterface<T, Req, Resp> =
BoxedConnectorIntegrationInterface<T, common_types::UasFlowData, Req, Resp>;
pub type BoxedGetAdditionalRecoveryRecoveryDetailsIntegrationInterface<T, Req, Res> =
pub type BoxedBillingConnectorPaymentsSyncIntegrationInterface<T, Req, Res> =
BoxedConnectorIntegrationInterface<
T,
common_types::GetAdditionalRevenueRecoveryFlowCommonData,
common_types::BillingConnectorPaymentsSyncFlowData,
Req,
Res,
>;

View File

@ -57,9 +57,7 @@ pub use hyperswitch_domain_models::{
WebhookSourceVerifyData,
},
router_request_types::{
revenue_recovery::{
GetAdditionalRevenueRecoveryRequestData, RevenueRecoveryRecordBackRequest,
},
revenue_recovery::{BillingConnectorPaymentsSyncRequest, RevenueRecoveryRecordBackRequest},
unified_authentication_service::{
UasAuthenticationRequestData, UasAuthenticationResponseData,
UasConfirmationRequestData, UasPostAuthenticationRequestData,
@ -80,7 +78,7 @@ pub use hyperswitch_domain_models::{
},
router_response_types::{
revenue_recovery::{
GetAdditionalRevenueRecoveryResponseData, RevenueRecoveryRecordBackResponse,
BillingConnectorPaymentsSyncResponse, RevenueRecoveryRecordBackResponse,
},
AcceptDisputeResponse, CaptureSyncResponse, DefendDisputeResponse, MandateReference,
MandateRevokeResponseData, PaymentsResponseData, PreprocessingResponseId,

View File

@ -56,7 +56,9 @@ pub use hyperswitch_interfaces::{
ConnectorPreAuthenticationVersionCallV2, ExternalAuthenticationV2,
},
fraud_check::FraudCheck,
revenue_recovery::{AdditionalRevenueRecovery, RevenueRecovery, RevenueRecoveryRecordBack},
revenue_recovery::{
BillingConnectorPaymentsSyncIntegration, RevenueRecovery, RevenueRecoveryRecordBack,
},
revenue_recovery_v2::RevenueRecoveryV2,
BoxedConnector, Connector, ConnectorAccessToken, ConnectorAccessTokenV2, ConnectorCommon,
ConnectorCommonExt, ConnectorMandateRevoke, ConnectorMandateRevokeV2,
@ -505,9 +507,9 @@ impl ConnectorData {
enums::Connector::Stripe => {
Ok(ConnectorEnum::Old(Box::new(connector::Stripe::new())))
}
// enums::Connector::Stripebilling =>{
// Ok(ConnectorEnum::Old(Box::new(connector::Stripebilling::new())))
// },
enums::Connector::Stripebilling => Ok(ConnectorEnum::Old(Box::new(
connector::Stripebilling::new(),
))),
enums::Connector::Wise => Ok(ConnectorEnum::Old(Box::new(connector::Wise::new()))),
enums::Connector::Worldline => {
Ok(ConnectorEnum::Old(Box::new(&connector::Worldline)))

View File

@ -318,7 +318,7 @@ impl ForeignTryFrom<api_enums::Connector> for common_enums::RoutableConnectors {
api_enums::Connector::Square => Self::Square,
api_enums::Connector::Stax => Self::Stax,
api_enums::Connector::Stripe => Self::Stripe,
// api_enums::Connector::Stripebilling => Self::Stripebilling,
api_enums::Connector::Stripebilling => Self::Stripebilling,
// api_enums::Connector::Taxjar => Self::Taxjar,
// api_enums::Connector::Thunes => Self::Thunes,
api_enums::Connector::Trustpay => Self::Trustpay,