From a0ffaa7a3eb48c0cbb18e2eafff4289bc45aa425 Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Sun, 9 Feb 2025 12:36:37 +0530 Subject: [PATCH 01/83] add template code for stripebilling --- config/config.example.toml | 2 + config/deployments/integration_test.toml | 1 + config/deployments/production.toml | 1 + config/deployments/sandbox.toml | 1 + config/development.toml | 2 + config/docker_compose.toml | 2 + crates/common_enums/src/connector_enums.rs | 4 + .../hyperswitch_connectors/src/connectors.rs | 3 +- .../src/connectors/stripebilling.rs | 556 ++++++++++++++++++ .../connectors/stripebilling/transformers.rs | 232 ++++++++ .../src/default_implementations.rs | 35 ++ .../src/default_implementations_v2.rs | 22 + crates/hyperswitch_interfaces/src/configs.rs | 1 + crates/router/src/connector.rs | 3 +- .../connector_integration_v2_impls.rs | 3 + crates/router/src/core/payments/flows.rs | 3 + crates/router/src/types/api.rs | 1 + crates/router/src/types/transformers.rs | 1 + crates/router/tests/connectors/main.rs | 1 + .../router/tests/connectors/sample_auth.toml | 3 + .../router/tests/connectors/stripebilling.rs | 421 +++++++++++++ crates/test_utils/src/connector_auth.rs | 3 +- loadtest/config/development.toml | 2 + scripts/add_connector.sh | 2 +- 24 files changed, 1301 insertions(+), 4 deletions(-) create mode 100644 crates/hyperswitch_connectors/src/connectors/stripebilling.rs create mode 100644 crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs create mode 100644 crates/router/tests/connectors/stripebilling.rs diff --git a/config/config.example.toml b/config/config.example.toml index 16b5ef6c3a1..c2627ac5ac8 100644 --- a/config/config.example.toml +++ b/config/config.example.toml @@ -260,6 +260,7 @@ square.base_url = "https://connect.squareupsandbox.com/" square.secondary_base_url = "https://pci-connect.squareupsandbox.com/" stax.base_url = "https://apiprod.fattlabs.com/" stripe.base_url = "https://api.stripe.com/" +stripebilling.base_url = "https://api.stripe.com/" taxjar.base_url = "https://api.sandbox.taxjar.com/v2/" threedsecureio.base_url = "https://service.sandbox.3dsecure.io" thunes.base_url = "https://api.limonetikqualif.com/" @@ -331,6 +332,7 @@ cards = [ "square", "stax", "stripe", + "stripebilling", "threedsecureio", "thunes", "worldpay", diff --git a/config/deployments/integration_test.toml b/config/deployments/integration_test.toml index 01e74f36542..802173e026c 100644 --- a/config/deployments/integration_test.toml +++ b/config/deployments/integration_test.toml @@ -106,6 +106,7 @@ square.secondary_base_url = "https://pci-connect.squareupsandbox.com/" stax.base_url = "https://apiprod.fattlabs.com/" stripe.base_url = "https://api.stripe.com/" stripe.base_url_file_upload = "https://files.stripe.com/" +stripebilling.base_url = "https://api.stripe.com/" taxjar.base_url = "https://api.sandbox.taxjar.com/v2/" thunes.base_url = "https://api.limonetikqualif.com/" trustpay.base_url = "https://test-tpgw.trustpay.eu/" diff --git a/config/deployments/production.toml b/config/deployments/production.toml index e52d1a1f91a..f9840e1d64f 100644 --- a/config/deployments/production.toml +++ b/config/deployments/production.toml @@ -110,6 +110,7 @@ square.secondary_base_url = "https://pci-connect.squareupsandbox.com/" stax.base_url = "https://apiprod.fattlabs.com/" stripe.base_url = "https://api.stripe.com/" stripe.base_url_file_upload = "https://files.stripe.com/" +stripebilling.base_url = "https://api.stripe.com/" taxjar.base_url = "https://api.taxjar.com/v2/" thunes.base_url = "https://api.limonetik.com/" trustpay.base_url = "https://tpgw.trustpay.eu/" diff --git a/config/deployments/sandbox.toml b/config/deployments/sandbox.toml index 548f4aead63..64716866885 100644 --- a/config/deployments/sandbox.toml +++ b/config/deployments/sandbox.toml @@ -110,6 +110,7 @@ square.secondary_base_url = "https://pci-connect.squareupsandbox.com/" stax.base_url = "https://apiprod.fattlabs.com/" stripe.base_url = "https://api.stripe.com/" stripe.base_url_file_upload = "https://files.stripe.com/" +stripebilling.base_url = "https://api.stripe.com/" taxjar.base_url = "https://api.sandbox.taxjar.com/v2/" thunes.base_url = "https://api.limonetikqualif.com/" trustpay.base_url = "https://test-tpgw.trustpay.eu/" diff --git a/config/development.toml b/config/development.toml index fc7a9427d8c..ee4730bdee6 100644 --- a/config/development.toml +++ b/config/development.toml @@ -158,6 +158,7 @@ cards = [ "square", "stax", "stripe", + "stripebilling", "taxjar", "threedsecureio", "thunes", @@ -280,6 +281,7 @@ square.base_url = "https://connect.squareupsandbox.com/" square.secondary_base_url = "https://pci-connect.squareupsandbox.com/" stax.base_url = "https://apiprod.fattlabs.com/" stripe.base_url = "https://api.stripe.com/" +stripebilling.base_url = "https://api.stripe.com/" taxjar.base_url = "https://api.sandbox.taxjar.com/v2/" threedsecureio.base_url = "https://service.sandbox.3dsecure.io" thunes.base_url = "https://api.limonetikqualif.com/" diff --git a/config/docker_compose.toml b/config/docker_compose.toml index 060093550e9..6503ae6d56d 100644 --- a/config/docker_compose.toml +++ b/config/docker_compose.toml @@ -192,6 +192,7 @@ square.base_url = "https://connect.squareupsandbox.com/" square.secondary_base_url = "https://pci-connect.squareupsandbox.com/" stax.base_url = "https://apiprod.fattlabs.com/" stripe.base_url = "https://api.stripe.com/" +stripebilling.base_url = "https://api.stripe.com/" taxjar.base_url = "https://api.sandbox.taxjar.com/v2/" threedsecureio.base_url = "https://service.sandbox.3dsecure.io" thunes.base_url = "https://api.limonetikqualif.com/" @@ -285,6 +286,7 @@ cards = [ "square", "stax", "stripe", + "stripebilling", "taxjar", "threedsecureio", "thunes", diff --git a/crates/common_enums/src/connector_enums.rs b/crates/common_enums/src/connector_enums.rs index a0e606e0741..108b456aa23 100644 --- a/crates/common_enums/src/connector_enums.rs +++ b/crates/common_enums/src/connector_enums.rs @@ -120,6 +120,7 @@ pub enum RoutableConnectors { Square, Stax, Stripe, + //Stripebilling, // Taxjar, Trustpay, // Thunes @@ -256,6 +257,7 @@ pub enum Connector { Square, Stax, Stripe, + // Stripebilling, Taxjar, Threedsecureio, //Thunes, @@ -397,6 +399,7 @@ impl Connector { | Self::Shift4 | Self::Square | Self::Stax + // | Self::Stripebilling | Self::Taxjar // | Self::Thunes | Self::Trustpay @@ -530,6 +533,7 @@ impl From for Connector { RoutableConnectors::Square => Self::Square, RoutableConnectors::Stax => Self::Stax, RoutableConnectors::Stripe => Self::Stripe, + // RoutableConnectors::Stripebilling => Self::Stripebilling, RoutableConnectors::Trustpay => Self::Trustpay, RoutableConnectors::Tsys => Self::Tsys, RoutableConnectors::Volt => Self::Volt, diff --git a/crates/hyperswitch_connectors/src/connectors.rs b/crates/hyperswitch_connectors/src/connectors.rs index 58e6d9c7e5d..53b11613c5f 100644 --- a/crates/hyperswitch_connectors/src/connectors.rs +++ b/crates/hyperswitch_connectors/src/connectors.rs @@ -53,6 +53,7 @@ pub mod razorpay; pub mod redsys; pub mod shift4; pub mod square; +pub mod stripebilling; pub mod stax; pub mod taxjar; pub mod thunes; @@ -79,7 +80,7 @@ pub use self::{ multisafepay::Multisafepay, nexinets::Nexinets, nexixpay::Nexixpay, nomupay::Nomupay, novalnet::Novalnet, nuvei::Nuvei, paybox::Paybox, payeezy::Payeezy, payu::Payu, placetopay::Placetopay, powertranz::Powertranz, prophetpay::Prophetpay, rapyd::Rapyd, - razorpay::Razorpay, redsys::Redsys, shift4::Shift4, square::Square, stax::Stax, taxjar::Taxjar, + razorpay::Razorpay, redsys::Redsys, shift4::Shift4, square::Square, stax::Stax,stripebilling::Stripebilling, taxjar::Taxjar, thunes::Thunes, tsys::Tsys, unified_authentication_service::UnifiedAuthenticationService, volt::Volt, wellsfargo::Wellsfargo, worldline::Worldline, worldpay::Worldpay, xendit::Xendit, zen::Zen, zsl::Zsl, diff --git a/crates/hyperswitch_connectors/src/connectors/stripebilling.rs b/crates/hyperswitch_connectors/src/connectors/stripebilling.rs new file mode 100644 index 00000000000..b94d69f161e --- /dev/null +++ b/crates/hyperswitch_connectors/src/connectors/stripebilling.rs @@ -0,0 +1,556 @@ +pub mod transformers; + +use error_stack::{report, ResultExt}; +use masking::{ExposeInterface, Mask}; + +use common_utils::{ + errors::CustomResult, + ext_traits::BytesExt, + types::{AmountConvertor, StringMinorUnit, StringMinorUnitForConnector}, + request::{Method, Request, RequestBuilder, RequestContent}, +}; + +use hyperswitch_domain_models::{ + router_data::{AccessToken, ConnectorAuthType, ErrorResponse, RouterData}, + router_flow_types::{ + access_token_auth::AccessTokenAuth, + payments::{ + Authorize, Capture, PSync, PaymentMethodToken, Session, + SetupMandate, Void, + }, + refunds::{Execute, RSync}, + }, + router_request_types::{ + AccessTokenRequestData, PaymentMethodTokenizationData, + PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, PaymentsSessionData, + PaymentsSyncData, RefundsData, SetupMandateRequestData, + }, + router_response_types::{PaymentsResponseData, RefundsResponseData}, + types::{ + PaymentsAuthorizeRouterData, + PaymentsCaptureRouterData, PaymentsSyncRouterData, RefundSyncRouterData, RefundsRouterData, + }, +}; +use hyperswitch_interfaces::{ + api::{self, ConnectorCommon, ConnectorCommonExt, ConnectorIntegration, ConnectorValidation, ConnectorSpecifications}, + configs::Connectors, + errors, + events::connector_api_logs::ConnectorEvent, + types::{self, Response}, + webhooks, +}; +use crate::{ + constants::headers, + types::ResponseRouterData, + utils, +}; + +use transformers as stripebilling; + +#[derive(Clone)] +pub struct Stripebilling { + amount_converter: &'static (dyn AmountConvertor + Sync) +} + +impl Stripebilling { + pub fn new() -> &'static Self { + &Self { + amount_converter: &StringMinorUnitForConnector + } + } +} + +impl api::Payment for Stripebilling {} +impl api::PaymentSession for Stripebilling {} +impl api::ConnectorAccessToken for Stripebilling {} +impl api::MandateSetup for Stripebilling {} +impl api::PaymentAuthorize for Stripebilling {} +impl api::PaymentSync for Stripebilling {} +impl api::PaymentCapture for Stripebilling {} +impl api::PaymentVoid for Stripebilling {} +impl api::Refund for Stripebilling {} +impl api::RefundExecute for Stripebilling {} +impl api::RefundSync for Stripebilling {} +impl api::PaymentToken for Stripebilling {} + +impl + ConnectorIntegration< + PaymentMethodToken, + PaymentMethodTokenizationData, + PaymentsResponseData, + > for Stripebilling +{ + // Not Implemented (R) +} + +impl ConnectorCommonExt for Stripebilling +where + Self: ConnectorIntegration,{ + fn build_headers( + &self, + req: &RouterData, + _connectors: &Connectors, + ) -> CustomResult)>, errors::ConnectorError> { + let mut header = vec![( + headers::CONTENT_TYPE.to_string(), + self.get_content_type().to_string().into(), + )]; + let mut api_key = self.get_auth_header(&req.connector_auth_type)?; + header.append(&mut api_key); + Ok(header) + } +} + +impl ConnectorCommon for Stripebilling { + fn id(&self) -> &'static str { + "stripebilling" + } + + fn get_currency_unit(&self) -> api::CurrencyUnit { + todo!() + // TODO! Check connector documentation, on which unit they are processing the currency. + // If the connector accepts amount in lower unit ( i.e cents for USD) then return api::CurrencyUnit::Minor, + // if connector accepts amount in base unit (i.e dollars for USD) then return api::CurrencyUnit::Base + } + + fn common_get_content_type(&self) -> &'static str { + "application/json" + } + + fn base_url<'a>(&self, connectors: &'a Connectors) -> &'a str { + connectors.stripebilling.base_url.as_ref() + } + + fn get_auth_header(&self, auth_type:&ConnectorAuthType)-> CustomResult)>,errors::ConnectorError> { + let auth = stripebilling::StripebillingAuthType::try_from(auth_type) + .change_context(errors::ConnectorError::FailedToObtainAuthType)?; + Ok(vec![(headers::AUTHORIZATION.to_string(), auth.api_key.expose().into_masked())]) + } + + fn build_error_response( + &self, + res: Response, + event_builder: Option<&mut ConnectorEvent>, + ) -> CustomResult { + let response: stripebilling::StripebillingErrorResponse = res + .response + .parse_struct("StripebillingErrorResponse") + .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; + + event_builder.map(|i| i.set_response_body(&response)); + router_env::logger::info!(connector_response=?response); + + Ok(ErrorResponse { + status_code: res.status_code, + code: response.code, + message: response.message, + reason: response.reason, + attempt_status: None, + connector_transaction_id: None, + }) + } +} + +impl ConnectorValidation for Stripebilling +{ + //TODO: implement functions when support enabled +} + +impl + ConnectorIntegration< + Session, + PaymentsSessionData, + PaymentsResponseData, + > for Stripebilling +{ + //TODO: implement sessions flow +} + +impl ConnectorIntegration + for Stripebilling +{ +} + +impl + ConnectorIntegration< + SetupMandate, + SetupMandateRequestData, + PaymentsResponseData, + > for Stripebilling +{ +} + +impl + ConnectorIntegration< + Authorize, + PaymentsAuthorizeData, + PaymentsResponseData, + > for Stripebilling { + fn get_headers(&self, req: &PaymentsAuthorizeRouterData, connectors: &Connectors,) -> CustomResult)>,errors::ConnectorError> { + self.build_headers(req, connectors) + } + + fn get_content_type(&self) -> &'static str { + self.common_get_content_type() + } + + fn get_url(&self, _req: &PaymentsAuthorizeRouterData, _connectors: &Connectors,) -> CustomResult { + Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into()) + } + + fn get_request_body(&self, req: &PaymentsAuthorizeRouterData, _connectors: &Connectors,) -> CustomResult { + let amount = utils::convert_amount( + self.amount_converter, + req.request.minor_amount, + req.request.currency, + )?; + + let connector_router_data = + stripebilling::StripebillingRouterData::from(( + amount, + req, + )); + let connector_req = stripebilling::StripebillingPaymentsRequest::try_from(&connector_router_data)?; + Ok(RequestContent::Json(Box::new(connector_req))) + } + + fn build_request( + &self, + req: &PaymentsAuthorizeRouterData, + connectors: &Connectors, + ) -> CustomResult, errors::ConnectorError> { + Ok(Some( + RequestBuilder::new() + .method(Method::Post) + .url(&types::PaymentsAuthorizeType::get_url( + self, req, connectors, + )?) + .attach_default_headers() + .headers(types::PaymentsAuthorizeType::get_headers( + self, req, connectors, + )?) + .set_body(types::PaymentsAuthorizeType::get_request_body(self, req, connectors)?) + .build(), + )) + } + + fn handle_response( + &self, + data: &PaymentsAuthorizeRouterData, + event_builder: Option<&mut ConnectorEvent>, + res: Response, + ) -> CustomResult { + let response: stripebilling::StripebillingPaymentsResponse = res.response.parse_struct("Stripebilling PaymentsAuthorizeResponse").change_context(errors::ConnectorError::ResponseDeserializationFailed)?; + event_builder.map(|i| i.set_response_body(&response)); + router_env::logger::info!(connector_response=?response); + RouterData::try_from(ResponseRouterData { + response, + data: data.clone(), + http_code: res.status_code, + }) + } + + fn get_error_response(&self, res: Response, event_builder: Option<&mut ConnectorEvent>) -> CustomResult { + self.build_error_response(res, event_builder) + } +} + +impl + ConnectorIntegration + for Stripebilling +{ + fn get_headers( + &self, + req: &PaymentsSyncRouterData, + connectors: &Connectors, + ) -> CustomResult)>, errors::ConnectorError> { + self.build_headers(req, connectors) + } + + fn get_content_type(&self) -> &'static str { + self.common_get_content_type() + } + + fn get_url( + &self, + _req: &PaymentsSyncRouterData, + _connectors: &Connectors, + ) -> CustomResult { + Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into()) + } + + fn build_request( + &self, + req: &PaymentsSyncRouterData, + connectors: &Connectors, + ) -> CustomResult, errors::ConnectorError> { + Ok(Some( + RequestBuilder::new() + .method(Method::Get) + .url(&types::PaymentsSyncType::get_url(self, req, connectors)?) + .attach_default_headers() + .headers(types::PaymentsSyncType::get_headers(self, req, connectors)?) + .build(), + )) + } + + fn handle_response( + &self, + data: &PaymentsSyncRouterData, + event_builder: Option<&mut ConnectorEvent>, + res: Response, + ) -> CustomResult { + let response: stripebilling:: StripebillingPaymentsResponse = res + .response + .parse_struct("stripebilling PaymentsSyncResponse") + .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; + event_builder.map(|i| i.set_response_body(&response)); + router_env::logger::info!(connector_response=?response); + RouterData::try_from(ResponseRouterData { + response, + data: data.clone(), + http_code: res.status_code, + }) + } + + fn get_error_response( + &self, + res: Response, + event_builder: Option<&mut ConnectorEvent> + ) -> CustomResult { + self.build_error_response(res, event_builder) + } +} + +impl + ConnectorIntegration< + Capture, + PaymentsCaptureData, + PaymentsResponseData, + > for Stripebilling +{ + fn get_headers( + &self, + req: &PaymentsCaptureRouterData, + connectors: &Connectors, + ) -> CustomResult)>, errors::ConnectorError> { + self.build_headers(req, connectors) + } + + fn get_content_type(&self) -> &'static str { + self.common_get_content_type() + } + + fn get_url( + &self, + _req: &PaymentsCaptureRouterData, + _connectors: &Connectors, + ) -> CustomResult { + Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into()) + } + + fn get_request_body( + &self, + _req: &PaymentsCaptureRouterData, + _connectors: &Connectors, + ) -> CustomResult { + Err(errors::ConnectorError::NotImplemented("get_request_body method".to_string()).into()) + } + + fn build_request( + &self, + req: &PaymentsCaptureRouterData, + connectors: &Connectors, + ) -> CustomResult, errors::ConnectorError> { + Ok(Some( + RequestBuilder::new() + .method(Method::Post) + .url(&types::PaymentsCaptureType::get_url(self, req, connectors)?) + .attach_default_headers() + .headers(types::PaymentsCaptureType::get_headers( + self, req, connectors, + )?) + .set_body(types::PaymentsCaptureType::get_request_body(self, req, connectors)?) + .build(), + )) + } + + fn handle_response( + &self, + data: &PaymentsCaptureRouterData, + event_builder: Option<&mut ConnectorEvent>, + res: Response, + ) -> CustomResult { + let response: stripebilling::StripebillingPaymentsResponse = res + .response + .parse_struct("Stripebilling PaymentsCaptureResponse") + .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; + event_builder.map(|i| i.set_response_body(&response)); + router_env::logger::info!(connector_response=?response); + RouterData::try_from(ResponseRouterData { + response, + data: data.clone(), + http_code: res.status_code, + }) + } + + fn get_error_response( + &self, + res: Response, + event_builder: Option<&mut ConnectorEvent> + ) -> CustomResult { + self.build_error_response(res, event_builder) + } +} + +impl + ConnectorIntegration< + Void, + PaymentsCancelData, + PaymentsResponseData, + > for Stripebilling +{} + +impl + ConnectorIntegration< + Execute, + RefundsData, + RefundsResponseData, + > for Stripebilling { + fn get_headers(&self, req: &RefundsRouterData, connectors: &Connectors,) -> CustomResult)>,errors::ConnectorError> { + self.build_headers(req, connectors) + } + + fn get_content_type(&self) -> &'static str { + self.common_get_content_type() + } + + fn get_url(&self, _req: &RefundsRouterData, _connectors: &Connectors,) -> CustomResult { + Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into()) + } + + fn get_request_body(&self, req: &RefundsRouterData, _connectors: &Connectors,) -> CustomResult { + let refund_amount = utils::convert_amount( + self.amount_converter, + req.request.minor_refund_amount, + req.request.currency, + )?; + + let connector_router_data = + stripebilling::StripebillingRouterData::from(( + refund_amount, + req, + )); + let connector_req = stripebilling::StripebillingRefundRequest::try_from(&connector_router_data)?; + Ok(RequestContent::Json(Box::new(connector_req))) + } + + fn build_request(&self, req: &RefundsRouterData, connectors: &Connectors,) -> CustomResult,errors::ConnectorError> { + let request = RequestBuilder::new() + .method(Method::Post) + .url(&types::RefundExecuteType::get_url(self, req, connectors)?) + .attach_default_headers() + .headers(types::RefundExecuteType::get_headers(self, req, connectors)?) + .set_body(types::RefundExecuteType::get_request_body(self, req, connectors)?) + .build(); + Ok(Some(request)) + } + + fn handle_response( + &self, + data: &RefundsRouterData, + event_builder: Option<&mut ConnectorEvent>, + res: Response, + ) -> CustomResult,errors::ConnectorError> { + let response: stripebilling::RefundResponse = res.response.parse_struct("stripebilling RefundResponse").change_context(errors::ConnectorError::ResponseDeserializationFailed)?; + event_builder.map(|i| i.set_response_body(&response)); + router_env::logger::info!(connector_response=?response); + RouterData::try_from(ResponseRouterData { + response, + data: data.clone(), + http_code: res.status_code, + }) + } + + fn get_error_response(&self, res: Response, event_builder: Option<&mut ConnectorEvent>) -> CustomResult { + self.build_error_response(res, event_builder) + } +} + +impl + ConnectorIntegration for Stripebilling { + fn get_headers(&self, req: &RefundSyncRouterData,connectors: &Connectors,) -> CustomResult)>,errors::ConnectorError> { + self.build_headers(req, connectors) + } + + fn get_content_type(&self) -> &'static str { + self.common_get_content_type() + } + + fn get_url(&self, _req: &RefundSyncRouterData,_connectors: &Connectors,) -> CustomResult { + Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into()) + } + + fn build_request( + &self, + req: &RefundSyncRouterData, + connectors: &Connectors, + ) -> CustomResult, errors::ConnectorError> { + Ok(Some( + RequestBuilder::new() + .method(Method::Get) + .url(&types::RefundSyncType::get_url(self, req, connectors)?) + .attach_default_headers() + .headers(types::RefundSyncType::get_headers(self, req, connectors)?) + .set_body(types::RefundSyncType::get_request_body(self, req, connectors)?) + .build(), + )) + } + + fn handle_response( + &self, + data: &RefundSyncRouterData, + event_builder: Option<&mut ConnectorEvent>, + res: Response, + ) -> CustomResult { + let response: stripebilling::RefundResponse = res.response.parse_struct("stripebilling RefundSyncResponse").change_context(errors::ConnectorError::ResponseDeserializationFailed)?; + event_builder.map(|i| i.set_response_body(&response)); + router_env::logger::info!(connector_response=?response); + RouterData::try_from(ResponseRouterData { + response, + data: data.clone(), + http_code: res.status_code, + }) + } + + fn get_error_response(&self, res: Response, event_builder: Option<&mut ConnectorEvent>) -> CustomResult { + self.build_error_response(res, event_builder) + } +} + +#[async_trait::async_trait] +impl webhooks::IncomingWebhook for Stripebilling { + fn get_webhook_object_reference_id( + &self, + _request: &webhooks::IncomingWebhookRequestDetails<'_>, + ) -> CustomResult { + Err(report!(errors::ConnectorError::WebhooksNotImplemented)) + } + + fn get_webhook_event_type( + &self, + _request: &webhooks::IncomingWebhookRequestDetails<'_>, + ) -> CustomResult { + Err(report!(errors::ConnectorError::WebhooksNotImplemented)) + } + + fn get_webhook_resource_object( + &self, + _request: &webhooks::IncomingWebhookRequestDetails<'_>, + ) -> CustomResult, errors::ConnectorError> { + Err(report!(errors::ConnectorError::WebhooksNotImplemented)) + } +} + +impl ConnectorSpecifications for Stripebilling {} + diff --git a/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs b/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs new file mode 100644 index 00000000000..77d8a4beb92 --- /dev/null +++ b/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs @@ -0,0 +1,232 @@ +use common_enums::enums; +use serde::{Deserialize, Serialize}; +use masking::Secret; +use common_utils::types::{StringMinorUnit}; +use hyperswitch_domain_models::{ + payment_method_data::PaymentMethodData, + router_data::{ConnectorAuthType, RouterData}, + router_flow_types::refunds::{Execute, RSync}, + router_request_types::ResponseId, + router_response_types::{PaymentsResponseData, RefundsResponseData}, + types::{PaymentsAuthorizeRouterData, RefundsRouterData}, +}; +use hyperswitch_interfaces::errors; +use crate::{ + types::{RefundsResponseRouterData, ResponseRouterData}, + utils::PaymentsAuthorizeRequestData, +}; + +//TODO: Fill the struct with respective fields +pub struct StripebillingRouterData { + pub amount: StringMinorUnit, // The type of amount that a connector accepts, for example, String, i64, f64, etc. + pub router_data: T, +} + +impl + From<( + StringMinorUnit, + T, + )> for StripebillingRouterData +{ + fn from( + (amount, item): ( + StringMinorUnit, + T, + ), + ) -> Self { + //Todo : use utils to convert the amount to the type of amount that a connector accepts + Self { + amount, + router_data: item, + } + } +} + +//TODO: Fill the struct with respective fields +#[derive(Default, Debug, Serialize, PartialEq)] +pub struct StripebillingPaymentsRequest { + amount: StringMinorUnit, + card: StripebillingCard +} + +#[derive(Default, Debug, Serialize, Eq, PartialEq)] +pub struct StripebillingCard { + number: cards::CardNumber, + expiry_month: Secret, + expiry_year: Secret, + cvc: Secret, + complete: bool, +} + +impl TryFrom<&StripebillingRouterData<&PaymentsAuthorizeRouterData>> for StripebillingPaymentsRequest { + type Error = error_stack::Report; + fn try_from(item: &StripebillingRouterData<&PaymentsAuthorizeRouterData>) -> Result { + match item.router_data.request.payment_method_data.clone() { + PaymentMethodData::Card(req_card) => { + let card = StripebillingCard { + number: req_card.card_number, + expiry_month: req_card.card_exp_month, + expiry_year: req_card.card_exp_year, + cvc: req_card.card_cvc, + complete: item.router_data.request.is_auto_capture()?, + }; + Ok(Self { + amount: item.amount.clone(), + card, + }) + } + _ => Err(errors::ConnectorError::NotImplemented("Payment method".to_string()).into()), + } + } +} + +//TODO: Fill the struct with respective fields +// Auth Struct +pub struct StripebillingAuthType { + pub(super) api_key: Secret +} + +impl TryFrom<&ConnectorAuthType> for StripebillingAuthType { + type Error = error_stack::Report; + fn try_from(auth_type: &ConnectorAuthType) -> Result { + match auth_type { + ConnectorAuthType::HeaderKey { api_key } => Ok(Self { + api_key: api_key.to_owned(), + }), + _ => Err(errors::ConnectorError::FailedToObtainAuthType.into()), + } + } +} +// PaymentsResponse +//TODO: Append the remaining status flags +#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)] +#[serde(rename_all = "lowercase")] +pub enum StripebillingPaymentStatus { + Succeeded, + Failed, + #[default] + Processing, +} + +impl From for common_enums::AttemptStatus { + fn from(item: StripebillingPaymentStatus) -> Self { + match item { + StripebillingPaymentStatus::Succeeded => Self::Charged, + StripebillingPaymentStatus::Failed => Self::Failure, + StripebillingPaymentStatus::Processing => Self::Authorizing, + } + } +} + +//TODO: Fill the struct with respective fields +#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)] +pub struct StripebillingPaymentsResponse { + status: StripebillingPaymentStatus, + id: String, +} + +impl TryFrom> for RouterData { + type Error = error_stack::Report; + fn try_from(item: ResponseRouterData) -> Result { + Ok(Self { + status: common_enums::AttemptStatus::from(item.response.status), + response: Ok(PaymentsResponseData::TransactionResponse { + resource_id: ResponseId::ConnectorTransactionId(item.response.id), + redirection_data: Box::new(None), + mandate_reference: Box::new(None), + connector_metadata: None, + network_txn_id: None, + connector_response_reference_id: None, + incremental_authorization_allowed: None, + charge_id: None, + }), + ..item.data + }) + } +} + +//TODO: Fill the struct with respective fields +// REFUND : +// Type definition for RefundRequest +#[derive(Default, Debug, Serialize)] +pub struct StripebillingRefundRequest { + pub amount: StringMinorUnit +} + +impl TryFrom<&StripebillingRouterData<&RefundsRouterData>> for StripebillingRefundRequest { + type Error = error_stack::Report; + fn try_from(item: &StripebillingRouterData<&RefundsRouterData>) -> Result { + Ok(Self { + amount: item.amount.to_owned(), + }) + } +} + +// Type definition for Refund Response + +#[allow(dead_code)] +#[derive(Debug, Serialize, Default, Deserialize, Clone)] +pub enum RefundStatus { + Succeeded, + Failed, + #[default] + Processing, +} + +impl From for enums::RefundStatus { + fn from(item: RefundStatus) -> Self { + match item { + RefundStatus::Succeeded => Self::Success, + RefundStatus::Failed => Self::Failure, + RefundStatus::Processing => Self::Pending, + //TODO: Review mapping + } + } +} + +//TODO: Fill the struct with respective fields +#[derive(Default, Debug, Clone, Serialize, Deserialize)] +pub struct RefundResponse { + id: String, + status: RefundStatus +} + +impl TryFrom> + for RefundsRouterData +{ + type Error = error_stack::Report; + fn try_from( + item: RefundsResponseRouterData, + ) -> Result { + Ok(Self { + response: Ok(RefundsResponseData { + connector_refund_id: item.response.id.to_string(), + refund_status: enums::RefundStatus::from(item.response.status), + }), + ..item.data + }) + } +} + +impl TryFrom> for RefundsRouterData +{ + type Error = error_stack::Report; + fn try_from(item: RefundsResponseRouterData) -> Result { + Ok(Self { + response: Ok(RefundsResponseData { + connector_refund_id: item.response.id.to_string(), + refund_status: enums::RefundStatus::from(item.response.status), + }), + ..item.data + }) + } + } + +//TODO: Fill the struct with respective fields +#[derive(Default, Debug, Serialize, Deserialize, PartialEq)] +pub struct StripebillingErrorResponse { + pub status_code: u16, + pub code: String, + pub message: String, + pub reason: Option, +} diff --git a/crates/hyperswitch_connectors/src/default_implementations.rs b/crates/hyperswitch_connectors/src/default_implementations.rs index f34b09e8f35..b6004fba705 100644 --- a/crates/hyperswitch_connectors/src/default_implementations.rs +++ b/crates/hyperswitch_connectors/src/default_implementations.rs @@ -148,6 +148,7 @@ default_imp_for_authorize_session_token!( connectors::Redsys, connectors::Shift4, connectors::Stax, + connectors::Stripebilling, connectors::Taxjar, connectors::UnifiedAuthenticationService, connectors::Volt, @@ -232,6 +233,7 @@ default_imp_for_calculate_tax!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Thunes, connectors::Tsys, connectors::UnifiedAuthenticationService, @@ -296,6 +298,7 @@ default_imp_for_session_update!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Mifinity, connectors::Mollie, @@ -380,6 +383,7 @@ default_imp_for_post_session_tokens!( connectors::Redsys, connectors::Shift4, connectors::Stax, + connectors::Stripebilling, connectors::Taxjar, connectors::Mifinity, connectors::Mollie, @@ -470,6 +474,7 @@ default_imp_for_complete_authorize!( connectors::Redsys, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -553,6 +558,7 @@ default_imp_for_incremental_authorization!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -635,6 +641,7 @@ default_imp_for_create_customer!( connectors::Redsys, connectors::Shift4, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -712,6 +719,7 @@ default_imp_for_connector_redirect_response!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -788,6 +796,7 @@ default_imp_for_pre_processing_steps!( connectors::Redsys, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -873,6 +882,7 @@ default_imp_for_post_processing_steps!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -958,6 +968,7 @@ default_imp_for_approve!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -1043,6 +1054,7 @@ default_imp_for_reject!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -1128,6 +1140,7 @@ default_imp_for_webhook_source_verification!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -1214,6 +1227,7 @@ default_imp_for_accept_dispute!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -1299,6 +1313,7 @@ default_imp_for_submit_evidence!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -1384,6 +1399,7 @@ default_imp_for_defend_dispute!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -1478,6 +1494,7 @@ default_imp_for_file_upload!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -1555,6 +1572,7 @@ default_imp_for_payouts!( connectors::Shift4, connectors::Square, connectors::Stax, + connectors::Stripebilling, connectors::Taxjar, connectors::Tsys, connectors::UnifiedAuthenticationService, @@ -1641,6 +1659,7 @@ default_imp_for_payouts_create!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -1728,6 +1747,7 @@ default_imp_for_payouts_retrieve!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -1815,6 +1835,7 @@ default_imp_for_payouts_eligibility!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -1901,6 +1922,7 @@ default_imp_for_payouts_fulfill!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -1988,6 +2010,7 @@ default_imp_for_payouts_cancel!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -2075,6 +2098,7 @@ default_imp_for_payouts_quote!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -2162,6 +2186,7 @@ default_imp_for_payouts_recipient!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -2249,6 +2274,7 @@ default_imp_for_payouts_recipient_account!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -2336,6 +2362,7 @@ default_imp_for_frm_sale!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -2423,6 +2450,7 @@ default_imp_for_frm_checkout!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -2510,6 +2538,7 @@ default_imp_for_frm_transaction!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -2597,6 +2626,7 @@ default_imp_for_frm_fulfillment!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -2684,6 +2714,7 @@ default_imp_for_frm_record_return!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -2767,6 +2798,7 @@ default_imp_for_revoking_mandates!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -2852,6 +2884,7 @@ default_imp_for_uas_pre_authentication!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -2935,6 +2968,7 @@ default_imp_for_uas_post_authentication!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -3018,6 +3052,7 @@ default_imp_for_uas_authentication!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, diff --git a/crates/hyperswitch_connectors/src/default_implementations_v2.rs b/crates/hyperswitch_connectors/src/default_implementations_v2.rs index d0241967acb..e6fa69f0a7b 100644 --- a/crates/hyperswitch_connectors/src/default_implementations_v2.rs +++ b/crates/hyperswitch_connectors/src/default_implementations_v2.rs @@ -260,6 +260,7 @@ default_imp_for_new_connector_integration_payment!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -346,6 +347,7 @@ default_imp_for_new_connector_integration_refund!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -427,6 +429,7 @@ default_imp_for_new_connector_integration_connector_access_token!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -513,6 +516,7 @@ default_imp_for_new_connector_integration_accept_dispute!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -598,6 +602,7 @@ default_imp_for_new_connector_integration_submit_evidence!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -684,6 +689,7 @@ default_imp_for_new_connector_integration_defend_dispute!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -780,6 +786,7 @@ default_imp_for_new_connector_integration_file_upload!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -868,6 +875,7 @@ default_imp_for_new_connector_integration_payouts_create!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -956,6 +964,7 @@ default_imp_for_new_connector_integration_payouts_eligibility!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -1044,6 +1053,7 @@ default_imp_for_new_connector_integration_payouts_fulfill!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -1132,6 +1142,7 @@ default_imp_for_new_connector_integration_payouts_cancel!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -1220,6 +1231,7 @@ default_imp_for_new_connector_integration_payouts_quote!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -1308,6 +1320,7 @@ default_imp_for_new_connector_integration_payouts_recipient!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -1396,6 +1409,7 @@ default_imp_for_new_connector_integration_payouts_sync!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -1484,6 +1498,7 @@ default_imp_for_new_connector_integration_payouts_recipient_account!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -1570,6 +1585,7 @@ default_imp_for_new_connector_integration_webhook_source_verification!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -1658,6 +1674,7 @@ default_imp_for_new_connector_integration_frm_sale!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -1746,6 +1763,7 @@ default_imp_for_new_connector_integration_frm_checkout!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -1834,6 +1852,7 @@ default_imp_for_new_connector_integration_frm_transaction!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -1922,6 +1941,7 @@ default_imp_for_new_connector_integration_frm_fulfillment!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -2010,6 +2030,7 @@ default_imp_for_new_connector_integration_frm_record_return!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -2095,6 +2116,7 @@ default_imp_for_new_connector_integration_revoking_mandates!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, diff --git a/crates/hyperswitch_interfaces/src/configs.rs b/crates/hyperswitch_interfaces/src/configs.rs index ecb3aea102a..13a2afbd486 100644 --- a/crates/hyperswitch_interfaces/src/configs.rs +++ b/crates/hyperswitch_interfaces/src/configs.rs @@ -85,6 +85,7 @@ pub struct Connectors { pub square: ConnectorParams, pub stax: ConnectorParams, pub stripe: ConnectorParamsWithFileUploadUrl, + pub stripebilling: ConnectorParams, pub taxjar: ConnectorParams, pub threedsecureio: ConnectorParams, pub thunes: ConnectorParams, diff --git a/crates/router/src/connector.rs b/crates/router/src/connector.rs index e6767fbb08b..28e5f3affea 100644 --- a/crates/router/src/connector.rs +++ b/crates/router/src/connector.rs @@ -44,7 +44,8 @@ pub use hyperswitch_connectors::connectors::{ paybox::Paybox, payeezy, payeezy::Payeezy, payu, payu::Payu, placetopay, placetopay::Placetopay, powertranz, powertranz::Powertranz, prophetpay, prophetpay::Prophetpay, rapyd, rapyd::Rapyd, razorpay, razorpay::Razorpay, redsys, redsys::Redsys, shift4, - shift4::Shift4, square, square::Square, stax, stax::Stax, taxjar, taxjar::Taxjar, thunes, + shift4::Shift4, square, square::Square, stax, stax::Stax, taxjar, stripebilling,stripebilling::Stripebilling, + taxjar::Taxjar, thunes, thunes::Thunes, tsys, tsys::Tsys, unified_authentication_service, unified_authentication_service::UnifiedAuthenticationService, volt, volt::Volt, wellsfargo, wellsfargo::Wellsfargo, worldline, worldline::Worldline, worldpay, worldpay::Worldpay, xendit, diff --git a/crates/router/src/core/payments/connector_integration_v2_impls.rs b/crates/router/src/core/payments/connector_integration_v2_impls.rs index 7a43ec1a189..19fc1b86de6 100644 --- a/crates/router/src/core/payments/connector_integration_v2_impls.rs +++ b/crates/router/src/core/payments/connector_integration_v2_impls.rs @@ -1038,6 +1038,7 @@ default_imp_for_new_connector_integration_payouts!( connector::Square, connector::Stax, connector::Stripe, + connector::Stripebilling, connector::Shift4, connector::Taxjar, connector::Trustpay, @@ -1502,6 +1503,7 @@ default_imp_for_new_connector_integration_frm!( connector::Square, connector::Stax, connector::Stripe, + connector::Stripebilling, connector::Shift4, connector::Taxjar, connector::Trustpay, @@ -1879,6 +1881,7 @@ default_imp_for_new_connector_integration_connector_authentication!( connector::Square, connector::Stax, connector::Stripe, + connector::Stripebilling, connector::Shift4, connector::Taxjar, connector::Trustpay, diff --git a/crates/router/src/core/payments/flows.rs b/crates/router/src/core/payments/flows.rs index 6728d51558c..f1b56c5c612 100644 --- a/crates/router/src/core/payments/flows.rs +++ b/crates/router/src/core/payments/flows.rs @@ -462,6 +462,7 @@ default_imp_for_connector_request_id!( connector::Square, connector::Stax, connector::Stripe, + connector::Stripebilling, connector::Taxjar, connector::Threedsecureio, connector::Trustpay, @@ -1419,6 +1420,7 @@ default_imp_for_fraud_check!( connector::Square, connector::Stax, connector::Stripe, + connector::Stripebilling, connector::Taxjar, connector::Threedsecureio, connector::Trustpay, @@ -1954,6 +1956,7 @@ default_imp_for_connector_authentication!( connector::Square, connector::Stax, connector::Stripe, + connector::Stripebilling, connector::Taxjar, connector::Trustpay, connector::Tsys, diff --git a/crates/router/src/types/api.rs b/crates/router/src/types/api.rs index addb34eb973..91634d79bc5 100644 --- a/crates/router/src/types/api.rs +++ b/crates/router/src/types/api.rs @@ -506,6 +506,7 @@ impl ConnectorData { enums::Connector::Stripe => { Ok(ConnectorEnum::Old(Box::new(connector::Stripe::new()))) } + // enums::Connector::Stripebilling => Ok(ConnectorEnum::Old(Box::new(connector::Stripebilling))), enums::Connector::Wise => Ok(ConnectorEnum::Old(Box::new(connector::Wise::new()))), enums::Connector::Worldline => { Ok(ConnectorEnum::Old(Box::new(&connector::Worldline))) diff --git a/crates/router/src/types/transformers.rs b/crates/router/src/types/transformers.rs index 3e81d939c14..3cba3db3019 100644 --- a/crates/router/src/types/transformers.rs +++ b/crates/router/src/types/transformers.rs @@ -302,6 +302,7 @@ impl ForeignTryFrom 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::Taxjar => Self::Taxjar, // api_enums::Connector::Thunes => Self::Thunes, api_enums::Connector::Trustpay => Self::Trustpay, diff --git a/crates/router/tests/connectors/main.rs b/crates/router/tests/connectors/main.rs index 19f0b9f9b2c..44887b0b186 100644 --- a/crates/router/tests/connectors/main.rs +++ b/crates/router/tests/connectors/main.rs @@ -80,6 +80,7 @@ mod shift4; mod square; mod stax; mod stripe; +mod stripebilling; mod taxjar; mod trustpay; mod tsys; diff --git a/crates/router/tests/connectors/sample_auth.toml b/crates/router/tests/connectors/sample_auth.toml index 44c178f3a3b..b2c52e80e60 100644 --- a/crates/router/tests/connectors/sample_auth.toml +++ b/crates/router/tests/connectors/sample_auth.toml @@ -307,4 +307,7 @@ api_key="API Key" api_key="API Key" [chargebee] +api_key= "API Key" + +[stripebilling] api_key= "API Key" \ No newline at end of file diff --git a/crates/router/tests/connectors/stripebilling.rs b/crates/router/tests/connectors/stripebilling.rs new file mode 100644 index 00000000000..8fccb9cb885 --- /dev/null +++ b/crates/router/tests/connectors/stripebilling.rs @@ -0,0 +1,421 @@ +use hyperswitch_domain_models::payment_method_data::{Card, PaymentMethodData}; +use masking::Secret; +use router::types::{self, api, storage::enums}; +use test_utils::connector_auth; + +use crate::utils::{self, ConnectorActions}; + +#[derive(Clone, Copy)] +struct StripebillingTest; +impl ConnectorActions for StripebillingTest {} +impl utils::Connector for StripebillingTest { + fn get_data(&self) -> api::ConnectorData { + use router::connector::Stripebilling; + utils::construct_connector_data_old( + Box::new(Stripebilling::new()), + types::Connector::Plaid, + api::GetToken::Connector, + None, + ) + } + + fn get_auth_token(&self) -> types::ConnectorAuthType { + utils::to_connector_auth_type( + connector_auth::ConnectorAuthentication::new() + .stripebilling + .expect("Missing connector authentication configuration") + .into(), + ) + } + + fn get_name(&self) -> String { + "stripebilling".to_string() + } +} + +static CONNECTOR: StripebillingTest = StripebillingTest {}; + +fn get_default_payment_info() -> Option { + None +} + +fn payment_method_details() -> Option { + None +} + +// Cards Positive Tests +// Creates a payment using the manual capture flow (Non 3DS). +#[actix_web::test] +async fn should_only_authorize_payment() { + let response = CONNECTOR + .authorize_payment(payment_method_details(), get_default_payment_info()) + .await + .expect("Authorize payment response"); + assert_eq!(response.status, enums::AttemptStatus::Authorized); +} + +// Captures a payment using the manual capture flow (Non 3DS). +#[actix_web::test] +async fn should_capture_authorized_payment() { + let response = CONNECTOR + .authorize_and_capture_payment(payment_method_details(), None, get_default_payment_info()) + .await + .expect("Capture payment response"); + assert_eq!(response.status, enums::AttemptStatus::Charged); +} + +// Partially captures a payment using the manual capture flow (Non 3DS). +#[actix_web::test] +async fn should_partially_capture_authorized_payment() { + let response = CONNECTOR + .authorize_and_capture_payment( + payment_method_details(), + Some(types::PaymentsCaptureData { + amount_to_capture: 50, + ..utils::PaymentCaptureType::default().0 + }), + get_default_payment_info(), + ) + .await + .expect("Capture payment response"); + assert_eq!(response.status, enums::AttemptStatus::Charged); +} + +// Synchronizes a payment using the manual capture flow (Non 3DS). +#[actix_web::test] +async fn should_sync_authorized_payment() { + let authorize_response = CONNECTOR + .authorize_payment(payment_method_details(), get_default_payment_info()) + .await + .expect("Authorize payment response"); + let txn_id = utils::get_connector_transaction_id(authorize_response.response); + let response = CONNECTOR + .psync_retry_till_status_matches( + enums::AttemptStatus::Authorized, + Some(types::PaymentsSyncData { + connector_transaction_id: types::ResponseId::ConnectorTransactionId( + txn_id.unwrap(), + ), + ..Default::default() + }), + get_default_payment_info(), + ) + .await + .expect("PSync response"); + assert_eq!(response.status, enums::AttemptStatus::Authorized,); +} + +// Voids a payment using the manual capture flow (Non 3DS). +#[actix_web::test] +async fn should_void_authorized_payment() { + let response = CONNECTOR + .authorize_and_void_payment( + payment_method_details(), + Some(types::PaymentsCancelData { + connector_transaction_id: String::from(""), + cancellation_reason: Some("requested_by_customer".to_string()), + ..Default::default() + }), + get_default_payment_info(), + ) + .await + .expect("Void payment response"); + assert_eq!(response.status, enums::AttemptStatus::Voided); +} + +// Refunds a payment using the manual capture flow (Non 3DS). +#[actix_web::test] +async fn should_refund_manually_captured_payment() { + let response = CONNECTOR + .capture_payment_and_refund( + payment_method_details(), + None, + None, + get_default_payment_info(), + ) + .await + .unwrap(); + assert_eq!( + response.response.unwrap().refund_status, + enums::RefundStatus::Success, + ); +} + +// Partially refunds a payment using the manual capture flow (Non 3DS). +#[actix_web::test] +async fn should_partially_refund_manually_captured_payment() { + let response = CONNECTOR + .capture_payment_and_refund( + payment_method_details(), + None, + Some(types::RefundsData { + refund_amount: 50, + ..utils::PaymentRefundType::default().0 + }), + get_default_payment_info(), + ) + .await + .unwrap(); + assert_eq!( + response.response.unwrap().refund_status, + enums::RefundStatus::Success, + ); +} + +// Synchronizes a refund using the manual capture flow (Non 3DS). +#[actix_web::test] +async fn should_sync_manually_captured_refund() { + let refund_response = CONNECTOR + .capture_payment_and_refund( + payment_method_details(), + None, + None, + get_default_payment_info(), + ) + .await + .unwrap(); + let response = CONNECTOR + .rsync_retry_till_status_matches( + enums::RefundStatus::Success, + refund_response.response.unwrap().connector_refund_id, + None, + get_default_payment_info(), + ) + .await + .unwrap(); + assert_eq!( + response.response.unwrap().refund_status, + enums::RefundStatus::Success, + ); +} + +// Creates a payment using the automatic capture flow (Non 3DS). +#[actix_web::test] +async fn should_make_payment() { + let authorize_response = CONNECTOR + .make_payment(payment_method_details(), get_default_payment_info()) + .await + .unwrap(); + assert_eq!(authorize_response.status, enums::AttemptStatus::Charged); +} + +// Synchronizes a payment using the automatic capture flow (Non 3DS). +#[actix_web::test] +async fn should_sync_auto_captured_payment() { + let authorize_response = CONNECTOR + .make_payment(payment_method_details(), get_default_payment_info()) + .await + .unwrap(); + assert_eq!(authorize_response.status, enums::AttemptStatus::Charged); + let txn_id = utils::get_connector_transaction_id(authorize_response.response); + assert_ne!(txn_id, None, "Empty connector transaction id"); + let response = CONNECTOR + .psync_retry_till_status_matches( + enums::AttemptStatus::Charged, + Some(types::PaymentsSyncData { + connector_transaction_id: types::ResponseId::ConnectorTransactionId( + txn_id.unwrap(), + ), + capture_method: Some(enums::CaptureMethod::Automatic), + ..Default::default() + }), + get_default_payment_info(), + ) + .await + .unwrap(); + assert_eq!(response.status, enums::AttemptStatus::Charged,); +} + +// Refunds a payment using the automatic capture flow (Non 3DS). +#[actix_web::test] +async fn should_refund_auto_captured_payment() { + let response = CONNECTOR + .make_payment_and_refund(payment_method_details(), None, get_default_payment_info()) + .await + .unwrap(); + assert_eq!( + response.response.unwrap().refund_status, + enums::RefundStatus::Success, + ); +} + +// Partially refunds a payment using the automatic capture flow (Non 3DS). +#[actix_web::test] +async fn should_partially_refund_succeeded_payment() { + let refund_response = CONNECTOR + .make_payment_and_refund( + payment_method_details(), + Some(types::RefundsData { + refund_amount: 50, + ..utils::PaymentRefundType::default().0 + }), + get_default_payment_info(), + ) + .await + .unwrap(); + assert_eq!( + refund_response.response.unwrap().refund_status, + enums::RefundStatus::Success, + ); +} + +// Creates multiple refunds against a payment using the automatic capture flow (Non 3DS). +#[actix_web::test] +async fn should_refund_succeeded_payment_multiple_times() { + CONNECTOR + .make_payment_and_multiple_refund( + payment_method_details(), + Some(types::RefundsData { + refund_amount: 50, + ..utils::PaymentRefundType::default().0 + }), + get_default_payment_info(), + ) + .await; +} + +// Synchronizes a refund using the automatic capture flow (Non 3DS). +#[actix_web::test] +async fn should_sync_refund() { + let refund_response = CONNECTOR + .make_payment_and_refund(payment_method_details(), None, get_default_payment_info()) + .await + .unwrap(); + let response = CONNECTOR + .rsync_retry_till_status_matches( + enums::RefundStatus::Success, + refund_response.response.unwrap().connector_refund_id, + None, + get_default_payment_info(), + ) + .await + .unwrap(); + assert_eq!( + response.response.unwrap().refund_status, + enums::RefundStatus::Success, + ); +} + +// Cards Negative scenarios +// Creates a payment with incorrect CVC. +#[actix_web::test] +async fn should_fail_payment_for_incorrect_cvc() { + let response = CONNECTOR + .make_payment( + Some(types::PaymentsAuthorizeData { + payment_method_data: PaymentMethodData::Card(Card { + card_cvc: Secret::new("12345".to_string()), + ..utils::CCardType::default().0 + }), + ..utils::PaymentAuthorizeType::default().0 + }), + get_default_payment_info(), + ) + .await + .unwrap(); + assert_eq!( + response.response.unwrap_err().message, + "Your card's security code is invalid.".to_string(), + ); +} + +// Creates a payment with incorrect expiry month. +#[actix_web::test] +async fn should_fail_payment_for_invalid_exp_month() { + let response = CONNECTOR + .make_payment( + Some(types::PaymentsAuthorizeData { + payment_method_data: PaymentMethodData::Card(Card { + card_exp_month: Secret::new("20".to_string()), + ..utils::CCardType::default().0 + }), + ..utils::PaymentAuthorizeType::default().0 + }), + get_default_payment_info(), + ) + .await + .unwrap(); + assert_eq!( + response.response.unwrap_err().message, + "Your card's expiration month is invalid.".to_string(), + ); +} + +// Creates a payment with incorrect expiry year. +#[actix_web::test] +async fn should_fail_payment_for_incorrect_expiry_year() { + let response = CONNECTOR + .make_payment( + Some(types::PaymentsAuthorizeData { + payment_method_data: PaymentMethodData::Card(Card { + card_exp_year: Secret::new("2000".to_string()), + ..utils::CCardType::default().0 + }), + ..utils::PaymentAuthorizeType::default().0 + }), + get_default_payment_info(), + ) + .await + .unwrap(); + assert_eq!( + response.response.unwrap_err().message, + "Your card's expiration year is invalid.".to_string(), + ); +} + +// Voids a payment using automatic capture flow (Non 3DS). +#[actix_web::test] +async fn should_fail_void_payment_for_auto_capture() { + let authorize_response = CONNECTOR + .make_payment(payment_method_details(), get_default_payment_info()) + .await + .unwrap(); + assert_eq!(authorize_response.status, enums::AttemptStatus::Charged); + let txn_id = utils::get_connector_transaction_id(authorize_response.response); + assert_ne!(txn_id, None, "Empty connector transaction id"); + let void_response = CONNECTOR + .void_payment(txn_id.unwrap(), None, get_default_payment_info()) + .await + .unwrap(); + assert_eq!( + void_response.response.unwrap_err().message, + "You cannot cancel this PaymentIntent because it has a status of succeeded." + ); +} + +// Captures a payment using invalid connector payment id. +#[actix_web::test] +async fn should_fail_capture_for_invalid_payment() { + let capture_response = CONNECTOR + .capture_payment("123456789".to_string(), None, get_default_payment_info()) + .await + .unwrap(); + assert_eq!( + capture_response.response.unwrap_err().message, + String::from("No such payment_intent: '123456789'") + ); +} + +// Refunds a payment with refund amount higher than payment amount. +#[actix_web::test] +async fn should_fail_for_refund_amount_higher_than_payment_amount() { + let response = CONNECTOR + .make_payment_and_refund( + payment_method_details(), + Some(types::RefundsData { + refund_amount: 150, + ..utils::PaymentRefundType::default().0 + }), + get_default_payment_info(), + ) + .await + .unwrap(); + assert_eq!( + response.response.unwrap_err().message, + "Refund amount (₹1.50) is greater than charge amount (₹1.00)", + ); +} + +// Connector dependent test cases goes here + +// [#478]: add unit tests for non 3DS, wallets & webhooks in connector tests diff --git a/crates/test_utils/src/connector_auth.rs b/crates/test_utils/src/connector_auth.rs index 0a3aa4bcff0..4dd574b8f9a 100644 --- a/crates/test_utils/src/connector_auth.rs +++ b/crates/test_utils/src/connector_auth.rs @@ -83,7 +83,8 @@ pub struct ConnectorAuthentication { pub shift4: Option, pub square: Option, pub stax: Option, - pub stripe: Option, + pub stripe: Option, + pub stripebilling: Option, pub taxjar: Option, pub threedsecureio: Option, pub thunes: Option, diff --git a/loadtest/config/development.toml b/loadtest/config/development.toml index f0f44fc207d..bf43996dd41 100644 --- a/loadtest/config/development.toml +++ b/loadtest/config/development.toml @@ -158,6 +158,7 @@ square.base_url = "https://connect.squareupsandbox.com/" square.secondary_base_url = "https://pci-connect.squareupsandbox.com/" stax.base_url = "https://apiprod.fattlabs.com/" stripe.base_url = "https://api.stripe.com/" +stripebilling.base_url = "https://api.stripe.com/" taxjar.base_url = "https://api.sandbox.taxjar.com/v2/" threedsecureio.base_url = "https://service.sandbox.3dsecure.io" thunes.base_url = "https://api.limonetikqualif.com/" @@ -250,6 +251,7 @@ cards = [ "square", "stax", "stripe", + "stripebilling", "taxjar", "threedsecureio", "thunes", diff --git a/scripts/add_connector.sh b/scripts/add_connector.sh index 8dee6cd21f9..7abacbc5fbb 100755 --- a/scripts/add_connector.sh +++ b/scripts/add_connector.sh @@ -6,7 +6,7 @@ function find_prev_connector() { git checkout $self cp $self $self.tmp # Add new connector to existing list and sort it - connectors=(aci adyen adyenplatform airwallex amazonpay applepay authorizedotnet bambora bamboraapac bankofamerica billwerk bitpay bluesnap boku braintree cashtocode chargebee checkout coinbase coingate cryptopay cybersource datatrans deutschebank digitalvirgo dlocal dummyconnector ebanx elavon fiserv fiservemea fiuu forte globalpay globepay gocardless gpayments helcim iatapay inespay itaubank jpmorgan klarna mifinity mollie multisafepay netcetera nexinets nexixpay nomupay noon novalnet nuvei opayo opennode paybox payeezy payme payone paypal payu placetopay plaid powertranz prophetpay rapyd razorpay redsys shift4 square stax stripe taxjar threedsecureio thunes trustpay tsys unified_authentication_service volt wellsfargo wellsfargopayout wise worldline worldpay xendit zsl "$1") + connectors=(aci adyen adyenplatform airwallex amazonpay applepay authorizedotnet bambora bamboraapac bankofamerica billwerk bitpay bluesnap boku braintree cashtocode chargebee checkout coinbase coingate cryptopay cybersource datatrans deutschebank digitalvirgo dlocal dummyconnector ebanx elavon fiserv fiservemea fiuu forte globalpay globepay gocardless gpayments helcim iatapay inespay itaubank jpmorgan klarna mifinity mollie multisafepay netcetera nexinets nexixpay nomupay noon novalnet nuvei opayo opennode paybox payeezy payme payone paypal payu placetopay plaid powertranz prophetpay rapyd razorpay redsys shift4 square stax stripe stripebilling taxjar threedsecureio thunes trustpay tsys unified_authentication_service volt wellsfargo wellsfargopayout wise worldline worldpay xendit zsl "$1") IFS=$'\n' sorted=($(sort <<<"${connectors[*]}")); unset IFS res="$(echo ${sorted[@]})" sed -i'' -e "s/^ connectors=.*/ connectors=($res \"\$1\")/" $self.tmp From bb432a5c41a74c658a26242f8de9a33fdcefcdc9 Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Sun, 9 Feb 2025 12:55:59 +0530 Subject: [PATCH 02/83] add logic instead of todo in template code --- .../hyperswitch_connectors/src/connectors/stripebilling.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/crates/hyperswitch_connectors/src/connectors/stripebilling.rs b/crates/hyperswitch_connectors/src/connectors/stripebilling.rs index b94d69f161e..58f6bc2eb80 100644 --- a/crates/hyperswitch_connectors/src/connectors/stripebilling.rs +++ b/crates/hyperswitch_connectors/src/connectors/stripebilling.rs @@ -107,10 +107,7 @@ impl ConnectorCommon for Stripebilling { } fn get_currency_unit(&self) -> api::CurrencyUnit { - todo!() - // TODO! Check connector documentation, on which unit they are processing the currency. - // If the connector accepts amount in lower unit ( i.e cents for USD) then return api::CurrencyUnit::Minor, - // if connector accepts amount in base unit (i.e dollars for USD) then return api::CurrencyUnit::Base + api::CurrencyUnit::Minor } fn common_get_content_type(&self) -> &'static str { From 4555023d8b0c335ef7f378312ff62bbd5ff9ade5 Mon Sep 17 00:00:00 2001 From: "hyperswitch-bot[bot]" <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Date: Sun, 9 Feb 2025 07:27:47 +0000 Subject: [PATCH 03/83] chore: run formatter --- .../hyperswitch_connectors/src/connectors.rs | 11 +- .../src/connectors/stripebilling.rs | 264 ++++++++++-------- .../connectors/stripebilling/transformers.rs | 70 ++--- .../src/default_implementations.rs | 70 ++--- .../src/default_implementations_v2.rs | 44 +-- crates/hyperswitch_interfaces/src/configs.rs | 2 +- crates/router/src/connector.rs | 11 +- crates/router/src/types/api.rs | 2 +- crates/router/src/types/transformers.rs | 2 +- crates/test_utils/src/connector_auth.rs | 4 +- 10 files changed, 250 insertions(+), 230 deletions(-) diff --git a/crates/hyperswitch_connectors/src/connectors.rs b/crates/hyperswitch_connectors/src/connectors.rs index 53b11613c5f..2247b7b585f 100644 --- a/crates/hyperswitch_connectors/src/connectors.rs +++ b/crates/hyperswitch_connectors/src/connectors.rs @@ -53,8 +53,8 @@ pub mod razorpay; pub mod redsys; pub mod shift4; pub mod square; -pub mod stripebilling; pub mod stax; +pub mod stripebilling; pub mod taxjar; pub mod thunes; pub mod tsys; @@ -80,8 +80,9 @@ pub use self::{ multisafepay::Multisafepay, nexinets::Nexinets, nexixpay::Nexixpay, nomupay::Nomupay, novalnet::Novalnet, nuvei::Nuvei, paybox::Paybox, payeezy::Payeezy, payu::Payu, placetopay::Placetopay, powertranz::Powertranz, prophetpay::Prophetpay, rapyd::Rapyd, - razorpay::Razorpay, redsys::Redsys, shift4::Shift4, square::Square, stax::Stax,stripebilling::Stripebilling, taxjar::Taxjar, - thunes::Thunes, tsys::Tsys, unified_authentication_service::UnifiedAuthenticationService, - volt::Volt, wellsfargo::Wellsfargo, worldline::Worldline, worldpay::Worldpay, xendit::Xendit, - zen::Zen, zsl::Zsl, + razorpay::Razorpay, redsys::Redsys, shift4::Shift4, square::Square, stax::Stax, + stripebilling::Stripebilling, taxjar::Taxjar, thunes::Thunes, tsys::Tsys, + unified_authentication_service::UnifiedAuthenticationService, volt::Volt, + wellsfargo::Wellsfargo, worldline::Worldline, worldpay::Worldpay, xendit::Xendit, zen::Zen, + zsl::Zsl, }; diff --git a/crates/hyperswitch_connectors/src/connectors/stripebilling.rs b/crates/hyperswitch_connectors/src/connectors/stripebilling.rs index 58f6bc2eb80..e05fb8b8e33 100644 --- a/crates/hyperswitch_connectors/src/connectors/stripebilling.rs +++ b/crates/hyperswitch_connectors/src/connectors/stripebilling.rs @@ -1,61 +1,55 @@ pub mod transformers; -use error_stack::{report, ResultExt}; -use masking::{ExposeInterface, Mask}; - use common_utils::{ errors::CustomResult, ext_traits::BytesExt, - types::{AmountConvertor, StringMinorUnit, StringMinorUnitForConnector}, request::{Method, Request, RequestBuilder, RequestContent}, + types::{AmountConvertor, StringMinorUnit, StringMinorUnitForConnector}, }; - +use error_stack::{report, ResultExt}; use hyperswitch_domain_models::{ router_data::{AccessToken, ConnectorAuthType, ErrorResponse, RouterData}, router_flow_types::{ access_token_auth::AccessTokenAuth, - payments::{ - Authorize, Capture, PSync, PaymentMethodToken, Session, - SetupMandate, Void, - }, + payments::{Authorize, Capture, PSync, PaymentMethodToken, Session, SetupMandate, Void}, refunds::{Execute, RSync}, }, router_request_types::{ - AccessTokenRequestData, PaymentMethodTokenizationData, - PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, PaymentsSessionData, - PaymentsSyncData, RefundsData, SetupMandateRequestData, + AccessTokenRequestData, PaymentMethodTokenizationData, PaymentsAuthorizeData, + PaymentsCancelData, PaymentsCaptureData, PaymentsSessionData, PaymentsSyncData, + RefundsData, SetupMandateRequestData, }, router_response_types::{PaymentsResponseData, RefundsResponseData}, types::{ - PaymentsAuthorizeRouterData, - PaymentsCaptureRouterData, PaymentsSyncRouterData, RefundSyncRouterData, RefundsRouterData, + PaymentsAuthorizeRouterData, PaymentsCaptureRouterData, PaymentsSyncRouterData, + RefundSyncRouterData, RefundsRouterData, }, }; use hyperswitch_interfaces::{ - api::{self, ConnectorCommon, ConnectorCommonExt, ConnectorIntegration, ConnectorValidation, ConnectorSpecifications}, + api::{ + self, ConnectorCommon, ConnectorCommonExt, ConnectorIntegration, ConnectorSpecifications, + ConnectorValidation, + }, configs::Connectors, errors, events::connector_api_logs::ConnectorEvent, types::{self, Response}, webhooks, }; -use crate::{ - constants::headers, - types::ResponseRouterData, - utils, -}; - +use masking::{ExposeInterface, Mask}; use transformers as stripebilling; +use crate::{constants::headers, types::ResponseRouterData, utils}; + #[derive(Clone)] pub struct Stripebilling { - amount_converter: &'static (dyn AmountConvertor + Sync) + amount_converter: &'static (dyn AmountConvertor + Sync), } impl Stripebilling { pub fn new() -> &'static Self { &Self { - amount_converter: &StringMinorUnitForConnector + amount_converter: &StringMinorUnitForConnector, } } } @@ -73,19 +67,16 @@ impl api::RefundExecute for Stripebilling {} impl api::RefundSync for Stripebilling {} impl api::PaymentToken for Stripebilling {} -impl - ConnectorIntegration< - PaymentMethodToken, - PaymentMethodTokenizationData, - PaymentsResponseData, - > for Stripebilling +impl ConnectorIntegration + for Stripebilling { // Not Implemented (R) } impl ConnectorCommonExt for Stripebilling where - Self: ConnectorIntegration,{ + Self: ConnectorIntegration, +{ fn build_headers( &self, req: &RouterData, @@ -118,10 +109,16 @@ impl ConnectorCommon for Stripebilling { connectors.stripebilling.base_url.as_ref() } - fn get_auth_header(&self, auth_type:&ConnectorAuthType)-> CustomResult)>,errors::ConnectorError> { - let auth = stripebilling::StripebillingAuthType::try_from(auth_type) + fn get_auth_header( + &self, + auth_type: &ConnectorAuthType, + ) -> CustomResult)>, errors::ConnectorError> { + let auth = stripebilling::StripebillingAuthType::try_from(auth_type) .change_context(errors::ConnectorError::FailedToObtainAuthType)?; - Ok(vec![(headers::AUTHORIZATION.to_string(), auth.api_key.expose().into_masked())]) + Ok(vec![( + headers::AUTHORIZATION.to_string(), + auth.api_key.expose().into_masked(), + )]) } fn build_error_response( @@ -148,42 +145,29 @@ impl ConnectorCommon for Stripebilling { } } -impl ConnectorValidation for Stripebilling -{ +impl ConnectorValidation for Stripebilling { //TODO: implement functions when support enabled } -impl - ConnectorIntegration< - Session, - PaymentsSessionData, - PaymentsResponseData, - > for Stripebilling -{ +impl ConnectorIntegration for Stripebilling { //TODO: implement sessions flow } -impl ConnectorIntegration +impl ConnectorIntegration for Stripebilling {} + +impl ConnectorIntegration for Stripebilling { } -impl - ConnectorIntegration< - SetupMandate, - SetupMandateRequestData, - PaymentsResponseData, - > for Stripebilling +impl ConnectorIntegration + for Stripebilling { -} - -impl - ConnectorIntegration< - Authorize, - PaymentsAuthorizeData, - PaymentsResponseData, - > for Stripebilling { - fn get_headers(&self, req: &PaymentsAuthorizeRouterData, connectors: &Connectors,) -> CustomResult)>,errors::ConnectorError> { + fn get_headers( + &self, + req: &PaymentsAuthorizeRouterData, + connectors: &Connectors, + ) -> CustomResult)>, errors::ConnectorError> { self.build_headers(req, connectors) } @@ -191,23 +175,28 @@ impl self.common_get_content_type() } - fn get_url(&self, _req: &PaymentsAuthorizeRouterData, _connectors: &Connectors,) -> CustomResult { + fn get_url( + &self, + _req: &PaymentsAuthorizeRouterData, + _connectors: &Connectors, + ) -> CustomResult { Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into()) } - fn get_request_body(&self, req: &PaymentsAuthorizeRouterData, _connectors: &Connectors,) -> CustomResult { + fn get_request_body( + &self, + req: &PaymentsAuthorizeRouterData, + _connectors: &Connectors, + ) -> CustomResult { let amount = utils::convert_amount( self.amount_converter, req.request.minor_amount, req.request.currency, )?; - let connector_router_data = - stripebilling::StripebillingRouterData::from(( - amount, - req, - )); - let connector_req = stripebilling::StripebillingPaymentsRequest::try_from(&connector_router_data)?; + let connector_router_data = stripebilling::StripebillingRouterData::from((amount, req)); + let connector_req = + stripebilling::StripebillingPaymentsRequest::try_from(&connector_router_data)?; Ok(RequestContent::Json(Box::new(connector_req))) } @@ -226,7 +215,9 @@ impl .headers(types::PaymentsAuthorizeType::get_headers( self, req, connectors, )?) - .set_body(types::PaymentsAuthorizeType::get_request_body(self, req, connectors)?) + .set_body(types::PaymentsAuthorizeType::get_request_body( + self, req, connectors, + )?) .build(), )) } @@ -236,8 +227,11 @@ impl data: &PaymentsAuthorizeRouterData, event_builder: Option<&mut ConnectorEvent>, res: Response, - ) -> CustomResult { - let response: stripebilling::StripebillingPaymentsResponse = res.response.parse_struct("Stripebilling PaymentsAuthorizeResponse").change_context(errors::ConnectorError::ResponseDeserializationFailed)?; + ) -> CustomResult { + let response: stripebilling::StripebillingPaymentsResponse = res + .response + .parse_struct("Stripebilling PaymentsAuthorizeResponse") + .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; event_builder.map(|i| i.set_response_body(&response)); router_env::logger::info!(connector_response=?response); RouterData::try_from(ResponseRouterData { @@ -247,15 +241,16 @@ impl }) } - fn get_error_response(&self, res: Response, event_builder: Option<&mut ConnectorEvent>) -> CustomResult { + fn get_error_response( + &self, + res: Response, + event_builder: Option<&mut ConnectorEvent>, + ) -> CustomResult { self.build_error_response(res, event_builder) } } -impl - ConnectorIntegration - for Stripebilling -{ +impl ConnectorIntegration for Stripebilling { fn get_headers( &self, req: &PaymentsSyncRouterData, @@ -297,7 +292,7 @@ impl event_builder: Option<&mut ConnectorEvent>, res: Response, ) -> CustomResult { - let response: stripebilling:: StripebillingPaymentsResponse = res + let response: stripebilling::StripebillingPaymentsResponse = res .response .parse_struct("stripebilling PaymentsSyncResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; @@ -313,19 +308,13 @@ impl fn get_error_response( &self, res: Response, - event_builder: Option<&mut ConnectorEvent> + event_builder: Option<&mut ConnectorEvent>, ) -> CustomResult { self.build_error_response(res, event_builder) } } -impl - ConnectorIntegration< - Capture, - PaymentsCaptureData, - PaymentsResponseData, - > for Stripebilling -{ +impl ConnectorIntegration for Stripebilling { fn get_headers( &self, req: &PaymentsCaptureRouterData, @@ -367,7 +356,9 @@ impl .headers(types::PaymentsCaptureType::get_headers( self, req, connectors, )?) - .set_body(types::PaymentsCaptureType::get_request_body(self, req, connectors)?) + .set_body(types::PaymentsCaptureType::get_request_body( + self, req, connectors, + )?) .build(), )) } @@ -394,27 +385,20 @@ impl fn get_error_response( &self, res: Response, - event_builder: Option<&mut ConnectorEvent> + event_builder: Option<&mut ConnectorEvent>, ) -> CustomResult { self.build_error_response(res, event_builder) } } -impl - ConnectorIntegration< - Void, - PaymentsCancelData, - PaymentsResponseData, - > for Stripebilling -{} - -impl - ConnectorIntegration< - Execute, - RefundsData, - RefundsResponseData, - > for Stripebilling { - fn get_headers(&self, req: &RefundsRouterData, connectors: &Connectors,) -> CustomResult)>,errors::ConnectorError> { +impl ConnectorIntegration for Stripebilling {} + +impl ConnectorIntegration for Stripebilling { + fn get_headers( + &self, + req: &RefundsRouterData, + connectors: &Connectors, + ) -> CustomResult)>, errors::ConnectorError> { self.build_headers(req, connectors) } @@ -422,11 +406,19 @@ impl self.common_get_content_type() } - fn get_url(&self, _req: &RefundsRouterData, _connectors: &Connectors,) -> CustomResult { + fn get_url( + &self, + _req: &RefundsRouterData, + _connectors: &Connectors, + ) -> CustomResult { Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into()) } - fn get_request_body(&self, req: &RefundsRouterData, _connectors: &Connectors,) -> CustomResult { + fn get_request_body( + &self, + req: &RefundsRouterData, + _connectors: &Connectors, + ) -> CustomResult { let refund_amount = utils::convert_amount( self.amount_converter, req.request.minor_refund_amount, @@ -434,21 +426,27 @@ impl )?; let connector_router_data = - stripebilling::StripebillingRouterData::from(( - refund_amount, - req, - )); - let connector_req = stripebilling::StripebillingRefundRequest::try_from(&connector_router_data)?; + stripebilling::StripebillingRouterData::from((refund_amount, req)); + let connector_req = + stripebilling::StripebillingRefundRequest::try_from(&connector_router_data)?; Ok(RequestContent::Json(Box::new(connector_req))) } - fn build_request(&self, req: &RefundsRouterData, connectors: &Connectors,) -> CustomResult,errors::ConnectorError> { + fn build_request( + &self, + req: &RefundsRouterData, + connectors: &Connectors, + ) -> CustomResult, errors::ConnectorError> { let request = RequestBuilder::new() .method(Method::Post) .url(&types::RefundExecuteType::get_url(self, req, connectors)?) .attach_default_headers() - .headers(types::RefundExecuteType::get_headers(self, req, connectors)?) - .set_body(types::RefundExecuteType::get_request_body(self, req, connectors)?) + .headers(types::RefundExecuteType::get_headers( + self, req, connectors, + )?) + .set_body(types::RefundExecuteType::get_request_body( + self, req, connectors, + )?) .build(); Ok(Some(request)) } @@ -458,8 +456,11 @@ impl data: &RefundsRouterData, event_builder: Option<&mut ConnectorEvent>, res: Response, - ) -> CustomResult,errors::ConnectorError> { - let response: stripebilling::RefundResponse = res.response.parse_struct("stripebilling RefundResponse").change_context(errors::ConnectorError::ResponseDeserializationFailed)?; + ) -> CustomResult, errors::ConnectorError> { + let response: stripebilling::RefundResponse = res + .response + .parse_struct("stripebilling RefundResponse") + .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; event_builder.map(|i| i.set_response_body(&response)); router_env::logger::info!(connector_response=?response); RouterData::try_from(ResponseRouterData { @@ -469,14 +470,21 @@ impl }) } - fn get_error_response(&self, res: Response, event_builder: Option<&mut ConnectorEvent>) -> CustomResult { + fn get_error_response( + &self, + res: Response, + event_builder: Option<&mut ConnectorEvent>, + ) -> CustomResult { self.build_error_response(res, event_builder) } } -impl - ConnectorIntegration for Stripebilling { - fn get_headers(&self, req: &RefundSyncRouterData,connectors: &Connectors,) -> CustomResult)>,errors::ConnectorError> { +impl ConnectorIntegration for Stripebilling { + fn get_headers( + &self, + req: &RefundSyncRouterData, + connectors: &Connectors, + ) -> CustomResult)>, errors::ConnectorError> { self.build_headers(req, connectors) } @@ -484,7 +492,11 @@ impl self.common_get_content_type() } - fn get_url(&self, _req: &RefundSyncRouterData,_connectors: &Connectors,) -> CustomResult { + fn get_url( + &self, + _req: &RefundSyncRouterData, + _connectors: &Connectors, + ) -> CustomResult { Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into()) } @@ -499,7 +511,9 @@ impl .url(&types::RefundSyncType::get_url(self, req, connectors)?) .attach_default_headers() .headers(types::RefundSyncType::get_headers(self, req, connectors)?) - .set_body(types::RefundSyncType::get_request_body(self, req, connectors)?) + .set_body(types::RefundSyncType::get_request_body( + self, req, connectors, + )?) .build(), )) } @@ -509,8 +523,11 @@ impl data: &RefundSyncRouterData, event_builder: Option<&mut ConnectorEvent>, res: Response, - ) -> CustomResult { - let response: stripebilling::RefundResponse = res.response.parse_struct("stripebilling RefundSyncResponse").change_context(errors::ConnectorError::ResponseDeserializationFailed)?; + ) -> CustomResult { + let response: stripebilling::RefundResponse = res + .response + .parse_struct("stripebilling RefundSyncResponse") + .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; event_builder.map(|i| i.set_response_body(&response)); router_env::logger::info!(connector_response=?response); RouterData::try_from(ResponseRouterData { @@ -520,7 +537,11 @@ impl }) } - fn get_error_response(&self, res: Response, event_builder: Option<&mut ConnectorEvent>) -> CustomResult { + fn get_error_response( + &self, + res: Response, + event_builder: Option<&mut ConnectorEvent>, + ) -> CustomResult { self.build_error_response(res, event_builder) } } @@ -550,4 +571,3 @@ impl webhooks::IncomingWebhook for Stripebilling { } impl ConnectorSpecifications for Stripebilling {} - diff --git a/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs b/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs index 77d8a4beb92..e720a0a48c4 100644 --- a/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs @@ -1,7 +1,5 @@ use common_enums::enums; -use serde::{Deserialize, Serialize}; -use masking::Secret; -use common_utils::types::{StringMinorUnit}; +use common_utils::types::StringMinorUnit; use hyperswitch_domain_models::{ payment_method_data::PaymentMethodData, router_data::{ConnectorAuthType, RouterData}, @@ -11,6 +9,9 @@ use hyperswitch_domain_models::{ types::{PaymentsAuthorizeRouterData, RefundsRouterData}, }; use hyperswitch_interfaces::errors; +use masking::Secret; +use serde::{Deserialize, Serialize}; + use crate::{ types::{RefundsResponseRouterData, ResponseRouterData}, utils::PaymentsAuthorizeRequestData, @@ -22,19 +23,9 @@ pub struct StripebillingRouterData { pub router_data: T, } -impl - From<( - StringMinorUnit, - T, - )> for StripebillingRouterData -{ - fn from( - (amount, item): ( - StringMinorUnit, - T, - ), - ) -> Self { - //Todo : use utils to convert the amount to the type of amount that a connector accepts +impl From<(StringMinorUnit, T)> for StripebillingRouterData { + fn from((amount, item): (StringMinorUnit, T)) -> Self { + //Todo : use utils to convert the amount to the type of amount that a connector accepts Self { amount, router_data: item, @@ -46,7 +37,7 @@ impl #[derive(Default, Debug, Serialize, PartialEq)] pub struct StripebillingPaymentsRequest { amount: StringMinorUnit, - card: StripebillingCard + card: StripebillingCard, } #[derive(Default, Debug, Serialize, Eq, PartialEq)] @@ -58,9 +49,13 @@ pub struct StripebillingCard { complete: bool, } -impl TryFrom<&StripebillingRouterData<&PaymentsAuthorizeRouterData>> for StripebillingPaymentsRequest { +impl TryFrom<&StripebillingRouterData<&PaymentsAuthorizeRouterData>> + for StripebillingPaymentsRequest +{ type Error = error_stack::Report; - fn try_from(item: &StripebillingRouterData<&PaymentsAuthorizeRouterData>) -> Result { + fn try_from( + item: &StripebillingRouterData<&PaymentsAuthorizeRouterData>, + ) -> Result { match item.router_data.request.payment_method_data.clone() { PaymentMethodData::Card(req_card) => { let card = StripebillingCard { @@ -83,10 +78,10 @@ impl TryFrom<&StripebillingRouterData<&PaymentsAuthorizeRouterData>> for Stripeb //TODO: Fill the struct with respective fields // Auth Struct pub struct StripebillingAuthType { - pub(super) api_key: Secret + pub(super) api_key: Secret, } -impl TryFrom<&ConnectorAuthType> for StripebillingAuthType { +impl TryFrom<&ConnectorAuthType> for StripebillingAuthType { type Error = error_stack::Report; fn try_from(auth_type: &ConnectorAuthType) -> Result { match auth_type { @@ -125,9 +120,13 @@ pub struct StripebillingPaymentsResponse { id: String, } -impl TryFrom> for RouterData { +impl TryFrom> + for RouterData +{ type Error = error_stack::Report; - fn try_from(item: ResponseRouterData) -> Result { + fn try_from( + item: ResponseRouterData, + ) -> Result { Ok(Self { status: common_enums::AttemptStatus::from(item.response.status), response: Ok(PaymentsResponseData::TransactionResponse { @@ -150,12 +149,14 @@ impl TryFrom TryFrom<&StripebillingRouterData<&RefundsRouterData>> for StripebillingRefundRequest { type Error = error_stack::Report; - fn try_from(item: &StripebillingRouterData<&RefundsRouterData>) -> Result { + fn try_from( + item: &StripebillingRouterData<&RefundsRouterData>, + ) -> Result { Ok(Self { amount: item.amount.to_owned(), }) @@ -188,12 +189,10 @@ impl From for enums::RefundStatus { #[derive(Default, Debug, Clone, Serialize, Deserialize)] pub struct RefundResponse { id: String, - status: RefundStatus + status: RefundStatus, } -impl TryFrom> - for RefundsRouterData -{ +impl TryFrom> for RefundsRouterData { type Error = error_stack::Report; fn try_from( item: RefundsResponseRouterData, @@ -208,10 +207,11 @@ impl TryFrom> } } -impl TryFrom> for RefundsRouterData -{ - type Error = error_stack::Report; - fn try_from(item: RefundsResponseRouterData) -> Result { +impl TryFrom> for RefundsRouterData { + type Error = error_stack::Report; + fn try_from( + item: RefundsResponseRouterData, + ) -> Result { Ok(Self { response: Ok(RefundsResponseData { connector_refund_id: item.response.id.to_string(), @@ -219,8 +219,8 @@ impl TryFrom> for RefundsRouter }), ..item.data }) - } - } + } +} //TODO: Fill the struct with respective fields #[derive(Default, Debug, Serialize, Deserialize, PartialEq)] diff --git a/crates/hyperswitch_connectors/src/default_implementations.rs b/crates/hyperswitch_connectors/src/default_implementations.rs index b6004fba705..56f0780ba4e 100644 --- a/crates/hyperswitch_connectors/src/default_implementations.rs +++ b/crates/hyperswitch_connectors/src/default_implementations.rs @@ -148,7 +148,7 @@ default_imp_for_authorize_session_token!( connectors::Redsys, connectors::Shift4, connectors::Stax, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::UnifiedAuthenticationService, connectors::Volt, @@ -233,7 +233,7 @@ default_imp_for_calculate_tax!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Thunes, connectors::Tsys, connectors::UnifiedAuthenticationService, @@ -298,7 +298,7 @@ default_imp_for_session_update!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Mifinity, connectors::Mollie, @@ -383,7 +383,7 @@ default_imp_for_post_session_tokens!( connectors::Redsys, connectors::Shift4, connectors::Stax, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Mifinity, connectors::Mollie, @@ -474,7 +474,7 @@ default_imp_for_complete_authorize!( connectors::Redsys, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -558,7 +558,7 @@ default_imp_for_incremental_authorization!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -641,7 +641,7 @@ default_imp_for_create_customer!( connectors::Redsys, connectors::Shift4, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -719,7 +719,7 @@ default_imp_for_connector_redirect_response!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -796,7 +796,7 @@ default_imp_for_pre_processing_steps!( connectors::Redsys, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -882,7 +882,7 @@ default_imp_for_post_processing_steps!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -968,7 +968,7 @@ default_imp_for_approve!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -1054,7 +1054,7 @@ default_imp_for_reject!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -1140,7 +1140,7 @@ default_imp_for_webhook_source_verification!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -1227,7 +1227,7 @@ default_imp_for_accept_dispute!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -1313,7 +1313,7 @@ default_imp_for_submit_evidence!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -1399,7 +1399,7 @@ default_imp_for_defend_dispute!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -1494,7 +1494,7 @@ default_imp_for_file_upload!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -1572,7 +1572,7 @@ default_imp_for_payouts!( connectors::Shift4, connectors::Square, connectors::Stax, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Tsys, connectors::UnifiedAuthenticationService, @@ -1659,7 +1659,7 @@ default_imp_for_payouts_create!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -1747,7 +1747,7 @@ default_imp_for_payouts_retrieve!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -1835,7 +1835,7 @@ default_imp_for_payouts_eligibility!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -1922,7 +1922,7 @@ default_imp_for_payouts_fulfill!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -2010,7 +2010,7 @@ default_imp_for_payouts_cancel!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -2098,7 +2098,7 @@ default_imp_for_payouts_quote!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -2186,7 +2186,7 @@ default_imp_for_payouts_recipient!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -2274,7 +2274,7 @@ default_imp_for_payouts_recipient_account!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -2362,7 +2362,7 @@ default_imp_for_frm_sale!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -2450,7 +2450,7 @@ default_imp_for_frm_checkout!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -2538,7 +2538,7 @@ default_imp_for_frm_transaction!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -2626,7 +2626,7 @@ default_imp_for_frm_fulfillment!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -2714,7 +2714,7 @@ default_imp_for_frm_record_return!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -2798,7 +2798,7 @@ default_imp_for_revoking_mandates!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -2884,7 +2884,7 @@ default_imp_for_uas_pre_authentication!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -2968,7 +2968,7 @@ default_imp_for_uas_post_authentication!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -3052,7 +3052,7 @@ default_imp_for_uas_authentication!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, diff --git a/crates/hyperswitch_connectors/src/default_implementations_v2.rs b/crates/hyperswitch_connectors/src/default_implementations_v2.rs index e6fa69f0a7b..aba2c258d85 100644 --- a/crates/hyperswitch_connectors/src/default_implementations_v2.rs +++ b/crates/hyperswitch_connectors/src/default_implementations_v2.rs @@ -260,7 +260,7 @@ default_imp_for_new_connector_integration_payment!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -347,7 +347,7 @@ default_imp_for_new_connector_integration_refund!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -429,7 +429,7 @@ default_imp_for_new_connector_integration_connector_access_token!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -516,7 +516,7 @@ default_imp_for_new_connector_integration_accept_dispute!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -602,7 +602,7 @@ default_imp_for_new_connector_integration_submit_evidence!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -689,7 +689,7 @@ default_imp_for_new_connector_integration_defend_dispute!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -786,7 +786,7 @@ default_imp_for_new_connector_integration_file_upload!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -875,7 +875,7 @@ default_imp_for_new_connector_integration_payouts_create!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -964,7 +964,7 @@ default_imp_for_new_connector_integration_payouts_eligibility!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -1053,7 +1053,7 @@ default_imp_for_new_connector_integration_payouts_fulfill!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -1142,7 +1142,7 @@ default_imp_for_new_connector_integration_payouts_cancel!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -1231,7 +1231,7 @@ default_imp_for_new_connector_integration_payouts_quote!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -1320,7 +1320,7 @@ default_imp_for_new_connector_integration_payouts_recipient!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -1409,7 +1409,7 @@ default_imp_for_new_connector_integration_payouts_sync!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -1498,7 +1498,7 @@ default_imp_for_new_connector_integration_payouts_recipient_account!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -1585,7 +1585,7 @@ default_imp_for_new_connector_integration_webhook_source_verification!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -1674,7 +1674,7 @@ default_imp_for_new_connector_integration_frm_sale!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -1763,7 +1763,7 @@ default_imp_for_new_connector_integration_frm_checkout!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -1852,7 +1852,7 @@ default_imp_for_new_connector_integration_frm_transaction!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -1941,7 +1941,7 @@ default_imp_for_new_connector_integration_frm_fulfillment!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -2030,7 +2030,7 @@ default_imp_for_new_connector_integration_frm_record_return!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, @@ -2116,7 +2116,7 @@ default_imp_for_new_connector_integration_revoking_mandates!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, diff --git a/crates/hyperswitch_interfaces/src/configs.rs b/crates/hyperswitch_interfaces/src/configs.rs index 13a2afbd486..9c7f68130b3 100644 --- a/crates/hyperswitch_interfaces/src/configs.rs +++ b/crates/hyperswitch_interfaces/src/configs.rs @@ -85,7 +85,7 @@ pub struct Connectors { pub square: ConnectorParams, pub stax: ConnectorParams, pub stripe: ConnectorParamsWithFileUploadUrl, - pub stripebilling: ConnectorParams, + pub stripebilling: ConnectorParams, pub taxjar: ConnectorParams, pub threedsecureio: ConnectorParams, pub thunes: ConnectorParams, diff --git a/crates/router/src/connector.rs b/crates/router/src/connector.rs index 28e5f3affea..905968a6e68 100644 --- a/crates/router/src/connector.rs +++ b/crates/router/src/connector.rs @@ -44,12 +44,11 @@ pub use hyperswitch_connectors::connectors::{ paybox::Paybox, payeezy, payeezy::Payeezy, payu, payu::Payu, placetopay, placetopay::Placetopay, powertranz, powertranz::Powertranz, prophetpay, prophetpay::Prophetpay, rapyd, rapyd::Rapyd, razorpay, razorpay::Razorpay, redsys, redsys::Redsys, shift4, - shift4::Shift4, square, square::Square, stax, stax::Stax, taxjar, stripebilling,stripebilling::Stripebilling, - taxjar::Taxjar, thunes, - thunes::Thunes, tsys, tsys::Tsys, unified_authentication_service, - unified_authentication_service::UnifiedAuthenticationService, volt, volt::Volt, wellsfargo, - wellsfargo::Wellsfargo, worldline, worldline::Worldline, worldpay, worldpay::Worldpay, xendit, - xendit::Xendit, zen, zen::Zen, zsl, zsl::Zsl, + shift4::Shift4, square, square::Square, stax, stax::Stax, stripebilling, + stripebilling::Stripebilling, taxjar, taxjar::Taxjar, thunes, thunes::Thunes, tsys, tsys::Tsys, + unified_authentication_service, unified_authentication_service::UnifiedAuthenticationService, + volt, volt::Volt, wellsfargo, wellsfargo::Wellsfargo, worldline, worldline::Worldline, + worldpay, worldpay::Worldpay, xendit, xendit::Xendit, zen, zen::Zen, zsl, zsl::Zsl, }; #[cfg(feature = "dummy_connector")] diff --git a/crates/router/src/types/api.rs b/crates/router/src/types/api.rs index 91634d79bc5..b0990fba23d 100644 --- a/crates/router/src/types/api.rs +++ b/crates/router/src/types/api.rs @@ -506,7 +506,7 @@ impl ConnectorData { enums::Connector::Stripe => { Ok(ConnectorEnum::Old(Box::new(connector::Stripe::new()))) } - // enums::Connector::Stripebilling => Ok(ConnectorEnum::Old(Box::new(connector::Stripebilling))), + // enums::Connector::Stripebilling => Ok(ConnectorEnum::Old(Box::new(connector::Stripebilling))), enums::Connector::Wise => Ok(ConnectorEnum::Old(Box::new(connector::Wise::new()))), enums::Connector::Worldline => { Ok(ConnectorEnum::Old(Box::new(&connector::Worldline))) diff --git a/crates/router/src/types/transformers.rs b/crates/router/src/types/transformers.rs index 3cba3db3019..62e00b5980b 100644 --- a/crates/router/src/types/transformers.rs +++ b/crates/router/src/types/transformers.rs @@ -302,7 +302,7 @@ impl ForeignTryFrom 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, diff --git a/crates/test_utils/src/connector_auth.rs b/crates/test_utils/src/connector_auth.rs index 4dd574b8f9a..9af9b793227 100644 --- a/crates/test_utils/src/connector_auth.rs +++ b/crates/test_utils/src/connector_auth.rs @@ -83,8 +83,8 @@ pub struct ConnectorAuthentication { pub shift4: Option, pub square: Option, pub stax: Option, - pub stripe: Option, - pub stripebilling: Option, + pub stripe: Option, + pub stripebilling: Option, pub taxjar: Option, pub threedsecureio: Option, pub thunes: Option, From 2ad25d7aefa456f16b6745da46ce11a47ff7c759 Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Thu, 13 Feb 2025 21:38:18 +0530 Subject: [PATCH 04/83] fixes errors --- crates/hyperswitch_connectors/src/connectors.rs | 2 +- .../src/connectors/stripebilling/transformers.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/hyperswitch_connectors/src/connectors.rs b/crates/hyperswitch_connectors/src/connectors.rs index 33e0dc22595..0de2c883f30 100644 --- a/crates/hyperswitch_connectors/src/connectors.rs +++ b/crates/hyperswitch_connectors/src/connectors.rs @@ -83,7 +83,7 @@ pub use self::{ nexinets::Nexinets, nexixpay::Nexixpay, nomupay::Nomupay, novalnet::Novalnet, nuvei::Nuvei, paybox::Paybox, payeezy::Payeezy, payu::Payu, placetopay::Placetopay, powertranz::Powertranz, prophetpay::Prophetpay, rapyd::Rapyd, razorpay::Razorpay, redsys::Redsys, shift4::Shift4, - square::Square, stax::Stax, stripebilling::Stripebilling taxjar::Taxjar, thunes::Thunes, tsys::Tsys, + square::Square, stax::Stax, stripebilling::Stripebilling,taxjar::Taxjar, thunes::Thunes, tsys::Tsys, unified_authentication_service::UnifiedAuthenticationService, volt::Volt, wellsfargo::Wellsfargo, worldline::Worldline, worldpay::Worldpay, xendit::Xendit, zen::Zen, zsl::Zsl, diff --git a/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs b/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs index e720a0a48c4..dcaa2474639 100644 --- a/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs @@ -137,7 +137,7 @@ impl TryFrom Date: Thu, 13 Feb 2025 16:09:25 +0000 Subject: [PATCH 05/83] chore: run formatter --- crates/hyperswitch_connectors/src/connectors.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/hyperswitch_connectors/src/connectors.rs b/crates/hyperswitch_connectors/src/connectors.rs index 0de2c883f30..5ee6a519307 100644 --- a/crates/hyperswitch_connectors/src/connectors.rs +++ b/crates/hyperswitch_connectors/src/connectors.rs @@ -83,8 +83,8 @@ pub use self::{ nexinets::Nexinets, nexixpay::Nexixpay, nomupay::Nomupay, novalnet::Novalnet, nuvei::Nuvei, paybox::Paybox, payeezy::Payeezy, payu::Payu, placetopay::Placetopay, powertranz::Powertranz, prophetpay::Prophetpay, rapyd::Rapyd, razorpay::Razorpay, redsys::Redsys, shift4::Shift4, - square::Square, stax::Stax, stripebilling::Stripebilling,taxjar::Taxjar, thunes::Thunes, tsys::Tsys, - unified_authentication_service::UnifiedAuthenticationService, volt::Volt, + square::Square, stax::Stax, stripebilling::Stripebilling, taxjar::Taxjar, thunes::Thunes, + tsys::Tsys, unified_authentication_service::UnifiedAuthenticationService, volt::Volt, wellsfargo::Wellsfargo, worldline::Worldline, worldpay::Worldpay, xendit::Xendit, zen::Zen, zsl::Zsl, }; From 4412b10e348bb72d4abd3d46fd7e75d946007df7 Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Mon, 24 Feb 2025 14:02:39 +0530 Subject: [PATCH 06/83] resolved error in default implementation --- crates/hyperswitch_connectors/src/default_implementations.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/hyperswitch_connectors/src/default_implementations.rs b/crates/hyperswitch_connectors/src/default_implementations.rs index b4701d4db55..bd668eefe28 100644 --- a/crates/hyperswitch_connectors/src/default_implementations.rs +++ b/crates/hyperswitch_connectors/src/default_implementations.rs @@ -3210,6 +3210,7 @@ default_imp_for_uas_authentication_confirmation!( connectors::Shift4, connectors::Stax, connectors::Square, + connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Tsys, From d6c7f7a4914a58d7d21040c6be33074bdc6d69fa Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Thu, 27 Feb 2025 18:31:18 +0530 Subject: [PATCH 07/83] additional api call flow for revenue recovery --- config/config.example.toml | 3 + config/development.toml | 3 + config/docker_compose.toml | 3 + .../src/default_implementations.rs | 94 ++++++++++++++++++- .../src/router_data_v2/flow_common_types.rs | 2 + .../src/router_flow_types/webhooks.rs | 3 + .../src/router_request_types.rs | 5 + .../src/router_response_types.rs | 32 +++++++ crates/hyperswitch_domain_models/src/types.rs | 20 ++-- crates/hyperswitch_interfaces/src/api.rs | 32 +++++-- crates/hyperswitch_interfaces/src/types.rs | 11 ++- .../src/configs/secrets_transformers.rs | 1 + crates/router/src/configs/settings.rs | 7 ++ crates/router/src/core/payments/flows.rs | 54 ++++++++++- crates/router/src/services/api.rs | 3 + crates/router/src/types.rs | 4 +- crates/router/src/types/api.rs | 11 ++- 17 files changed, 258 insertions(+), 30 deletions(-) diff --git a/config/config.example.toml b/config/config.example.toml index e0a118efae9..7c79974b79e 100644 --- a/config/config.example.toml +++ b/config/config.example.toml @@ -833,3 +833,6 @@ entity_logo_url = "https://example.com/logo.svg" # Logo URL of the entity to be foreground_color = "#000000" # Foreground color of email text primary_color = "#006DF9" # Primary color of email body background_color = "#FFFFFF" # Background color of email body + +[additonal_recovery_details_call] +connectors_with_additional_revenue_recovery_details_call = "" # List of connectors which has additional revenue recovery details api-call \ No newline at end of file diff --git a/config/development.toml b/config/development.toml index 3c157eccdf0..03b7da9fee6 100644 --- a/config/development.toml +++ b/config/development.toml @@ -681,6 +681,9 @@ connectors_with_delayed_session_response = "trustpay,payme" [webhook_source_verification_call] connectors_with_webhook_source_verification_call = "paypal" +[additonal_recovery_details_call] +connectors_with_additional_revenue_recovery_details_call = "" + [mandates.supported_payment_methods] bank_debit.ach = { connector_list = "gocardless,adyen,stripe" } bank_debit.becs = { connector_list = "gocardless,stripe,adyen" } diff --git a/config/docker_compose.toml b/config/docker_compose.toml index 4c21651451a..38f1f6f5ee4 100644 --- a/config/docker_compose.toml +++ b/config/docker_compose.toml @@ -314,6 +314,9 @@ connectors_with_delayed_session_response = "trustpay,payme" [webhook_source_verification_call] connectors_with_webhook_source_verification_call = "paypal" +[additonal_recovery_details_call] +connectors_with_additional_revenue_recovery_details_call = "" + [scheduler] stream = "SCHEDULER_STREAM" diff --git a/crates/hyperswitch_connectors/src/default_implementations.rs b/crates/hyperswitch_connectors/src/default_implementations.rs index bd668eefe28..990bb8443c2 100644 --- a/crates/hyperswitch_connectors/src/default_implementations.rs +++ b/crates/hyperswitch_connectors/src/default_implementations.rs @@ -33,7 +33,7 @@ use hyperswitch_domain_models::{ PreProcessing, Reject, SdkSessionUpdate, }, webhooks::VerifyWebhookSource, - Authenticate, AuthenticationConfirmation, PostAuthenticate, PreAuthenticate, + Authenticate, AuthenticationConfirmation, PostAuthenticate, PreAuthenticate, GetAdditionalRevenueRecoveryDetails }, router_request_types::{ unified_authentication_service::{ @@ -47,11 +47,13 @@ use hyperswitch_domain_models::{ PaymentsPostSessionTokensData, PaymentsPreProcessingData, PaymentsRejectData, PaymentsTaxCalculationData, RetrieveFileRequestData, SdkPaymentsSessionUpdateData, SubmitEvidenceRequestData, UploadFileRequestData, VerifyWebhookSourceRequestData, + AdditionalRevenueRecoveryDetailsRequestData }, router_response_types::{ AcceptDisputeResponse, DefendDisputeResponse, MandateRevokeResponseData, PaymentsResponseData, RetrieveFileResponse, SubmitEvidenceResponse, TaxCalculationResponseData, UploadFileResponse, VerifyWebhookSourceResponseData, + AdditionalRevenueRecoveryDetailsResponseData }, }; #[cfg(feature = "frm")] @@ -77,7 +79,7 @@ use hyperswitch_interfaces::{ }, ConnectorIntegration, ConnectorMandateRevoke, ConnectorRedirectResponse, UasAuthentication, UasAuthenticationConfirmation, UasPostAuthentication, UasPreAuthentication, - UnifiedAuthenticationService, + UnifiedAuthenticationService }, errors::ConnectorError, }; @@ -3222,3 +3224,91 @@ default_imp_for_uas_authentication_confirmation!( connectors::Zen, connectors::Zsl ); + + +macro_rules! default_imp_for_additional_revenue_recovery_call { + ($($path:ident::$connector:ident),*) => { + $( impl api::ConnectorAdditionalRevenueRecoveryDetailsCall for $path::$connector {} + impl + ConnectorIntegration< + GetAdditionalRevenueRecoveryDetails, + AdditionalRevenueRecoveryDetailsRequestData, + AdditionalRevenueRecoveryDetailsResponseData + > for $path::$connector + {} + )* + }; +} + +default_imp_for_additional_revenue_recovery_call!( + connectors::Aci, + connectors::Airwallex, + connectors::Amazonpay, + connectors::Bambora, + connectors::Bamboraapac, + connectors::Bankofamerica, + connectors::Billwerk, + connectors::Bluesnap, + connectors::Bitpay, + connectors::Braintree, + connectors::Boku, + connectors::Cashtocode, + connectors::Chargebee, + connectors::Coinbase, + connectors::Coingate, + connectors::Cryptopay, + connectors::CtpMastercard, + connectors::Cybersource, + connectors::Datatrans, + connectors::Deutschebank, + connectors::Digitalvirgo, + connectors::Dlocal, + connectors::Elavon, + connectors::Fiserv, + connectors::Fiservemea, + connectors::Fiuu, + connectors::Forte, + connectors::Getnet, + connectors::Globalpay, + connectors::Globepay, + connectors::Gocardless, + connectors::Helcim, + connectors::Iatapay, + connectors::Inespay, + connectors::Itaubank, + connectors::Jpmorgan, + connectors::Klarna, + connectors::Nomupay, + connectors::Novalnet, + connectors::Nexinets, + connectors::Nexixpay, + connectors::Nuvei, + connectors::Payeezy, + connectors::Payu, + connectors::Powertranz, + connectors::Prophetpay, + connectors::Mifinity, + connectors::Mollie, + connectors::Moneris, + connectors::Multisafepay, + connectors::Paybox, + connectors::Placetopay, + connectors::Rapyd, + connectors::Razorpay, + connectors::Redsys, + connectors::Shift4, + connectors::Stax, + connectors::Square, + connectors::Stripebilling, + connectors::Taxjar, + connectors::Thunes, + connectors::Tsys, + connectors::UnifiedAuthenticationService, + connectors::Worldline, + connectors::Worldpay, + connectors::Wellsfargo, + connectors::Volt, + connectors::Xendit, + connectors::Zen, + connectors::Zsl +); diff --git a/crates/hyperswitch_domain_models/src/router_data_v2/flow_common_types.rs b/crates/hyperswitch_domain_models/src/router_data_v2/flow_common_types.rs index 47b2134bc19..209472b79a2 100644 --- a/crates/hyperswitch_domain_models/src/router_data_v2/flow_common_types.rs +++ b/crates/hyperswitch_domain_models/src/router_data_v2/flow_common_types.rs @@ -149,3 +149,5 @@ pub struct UasFlowData { pub authenticate_by: String, pub source_authentication_id: String, } + +pub struct AdditionalRevenueRecoveryCallFlowCommonData; diff --git a/crates/hyperswitch_domain_models/src/router_flow_types/webhooks.rs b/crates/hyperswitch_domain_models/src/router_flow_types/webhooks.rs index c7f155fa166..a27e7615a07 100644 --- a/crates/hyperswitch_domain_models/src/router_flow_types/webhooks.rs +++ b/crates/hyperswitch_domain_models/src/router_flow_types/webhooks.rs @@ -19,3 +19,6 @@ impl ConnectorNetworkTxnId { &self.0 } } + +#[derive(Debug, Clone)] +pub struct GetAdditionalRevenueRecoveryDetails; diff --git a/crates/hyperswitch_domain_models/src/router_request_types.rs b/crates/hyperswitch_domain_models/src/router_request_types.rs index 071a77aa7bd..2665b2f44ba 100644 --- a/crates/hyperswitch_domain_models/src/router_request_types.rs +++ b/crates/hyperswitch_domain_models/src/router_request_types.rs @@ -913,3 +913,8 @@ pub struct SetupMandateRequestData { pub minor_amount: Option, pub shipping_cost: Option, } + +#[derive(Debug, Clone)] +pub struct AdditionalRevenueRecoveryDetailsRequestData{ + pub transaction_id : String, +} diff --git a/crates/hyperswitch_domain_models/src/router_response_types.rs b/crates/hyperswitch_domain_models/src/router_response_types.rs index 86589ad6801..40cf11fb7f4 100644 --- a/crates/hyperswitch_domain_models/src/router_response_types.rs +++ b/crates/hyperswitch_domain_models/src/router_response_types.rs @@ -1,6 +1,7 @@ pub mod disputes; pub mod fraud_check; use std::collections::HashMap; +use time::PrimitiveDateTime; use common_utils::{request::Method, types::MinorUnit}; pub use disputes::{AcceptDisputeResponse, DefendDisputeResponse, SubmitEvidenceResponse}; @@ -603,3 +604,34 @@ impl SupportedPaymentMethodsExt for SupportedPaymentMethods { } } } + + +#[derive(Debug, Clone, serde::Deserialize,serde::Serialize)] +pub struct AdditionalRevenueRecoveryDetailsResponseData { + /// transaction amount against invoice, accepted in minor unit. + pub amount: MinorUnit, + /// currency of the transaction + pub currency: common_enums::enums::Currency, + /// merchant reference id at billing connector. ex: invoice_id + pub merchant_reference_id: common_utils::id_type::PaymentReferenceId, + /// transaction id reference at payment connector + pub connector_transaction_id: Option, + /// error code sent by billing connector. + pub error_code: Option, + /// error message sent by billing connector. + pub error_message: Option, + /// mandate token at payment processor end. + pub processor_payment_method_token: Option, + /// customer id at payment connector for which mandate is attached. + pub connector_customer_id: Option, + /// Payment gateway identifier id at billing processor. + pub connector_account_reference_id: Option, + /// timestamp at which transaction has been created at billing connector + pub transaction_created_at: Option, + /// transaction status at billing connector equivalent to payment attempt status. + pub status: common_enums::enums::AttemptStatus, + /// payment method of payment attempt. + pub payment_method_type: common_enums::enums::PaymentMethod, + /// payment method sub type of the payment attempt. + pub payment_method_sub_type: common_enums::enums::PaymentMethodType, +} diff --git a/crates/hyperswitch_domain_models/src/types.rs b/crates/hyperswitch_domain_models/src/types.rs index a774dda3c95..d190bafc03a 100644 --- a/crates/hyperswitch_domain_models/src/types.rs +++ b/crates/hyperswitch_domain_models/src/types.rs @@ -3,28 +3,17 @@ pub use diesel_models::types::OrderDetailsWithAmount; use crate::{ router_data::{AccessToken, RouterData}, router_flow_types::{ - mandate_revoke::MandateRevoke, AccessTokenAuth, Authenticate, AuthenticationConfirmation, - Authorize, AuthorizeSessionToken, CalculateTax, Capture, CompleteAuthorize, - CreateConnectorCustomer, Execute, IncrementalAuthorization, PSync, PaymentMethodToken, - PostAuthenticate, PostSessionTokens, PreAuthenticate, PreProcessing, RSync, Session, - SetupMandate, Void, + mandate_revoke::MandateRevoke, AccessTokenAuth, Authenticate, AuthenticationConfirmation, Authorize, AuthorizeSessionToken, CalculateTax, Capture, CompleteAuthorize, CreateConnectorCustomer, Execute, GetAdditionalRevenueRecoveryDetails, IncrementalAuthorization, PSync, PaymentMethodToken, PostAuthenticate, PostSessionTokens, PreAuthenticate, PreProcessing, RSync, Session, SetupMandate, Void }, router_request_types::{ unified_authentication_service::{ UasAuthenticationRequestData, UasAuthenticationResponseData, UasConfirmationRequestData, UasPostAuthenticationRequestData, UasPreAuthenticationRequestData, - }, - AccessTokenRequestData, AuthorizeSessionTokenData, CompleteAuthorizeData, - ConnectorCustomerData, MandateRevokeRequestData, PaymentMethodTokenizationData, - PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, - PaymentsIncrementalAuthorizationData, PaymentsPostSessionTokensData, - PaymentsPreProcessingData, PaymentsSessionData, PaymentsSyncData, - PaymentsTaxCalculationData, RefundsData, SetupMandateRequestData, + }, AccessTokenRequestData, AdditionalRevenueRecoveryDetailsRequestData, AuthorizeSessionTokenData, CompleteAuthorizeData, ConnectorCustomerData, MandateRevokeRequestData, PaymentMethodTokenizationData, PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, PaymentsIncrementalAuthorizationData, PaymentsPostSessionTokensData, PaymentsPreProcessingData, PaymentsSessionData, PaymentsSyncData, PaymentsTaxCalculationData, RefundsData, SetupMandateRequestData }, router_response_types::{ - MandateRevokeResponseData, PaymentsResponseData, RefundsResponseData, - TaxCalculationResponseData, + AdditionalRevenueRecoveryDetailsResponseData, MandateRevokeResponseData, PaymentsResponseData, RefundsResponseData, TaxCalculationResponseData }, }; #[cfg(feature = "payouts")] @@ -81,3 +70,6 @@ pub type PayoutsRouterData = RouterData; pub type UasAuthenticationRouterData = RouterData; + +pub type AdditionalRevenueRecoveryDetailsRouterData = + RouterData; diff --git a/crates/hyperswitch_interfaces/src/api.rs b/crates/hyperswitch_interfaces/src/api.rs index 35a3da46330..544468e9c33 100644 --- a/crates/hyperswitch_interfaces/src/api.rs +++ b/crates/hyperswitch_interfaces/src/api.rs @@ -30,24 +30,21 @@ use hyperswitch_domain_models::{ payment_method_data::PaymentMethodData, router_data::{AccessToken, ConnectorAuthType, ErrorResponse, RouterData}, router_data_v2::{ - flow_common_types::WebhookSourceVerifyData, AccessTokenFlowData, MandateRevokeFlowData, + flow_common_types::{AdditionalRevenueRecoveryCallFlowCommonData, WebhookSourceVerifyData}, AccessTokenFlowData, MandateRevokeFlowData, UasFlowData, }, router_flow_types::{ - mandate_revoke::MandateRevoke, AccessTokenAuth, Authenticate, AuthenticationConfirmation, - PostAuthenticate, PreAuthenticate, VerifyWebhookSource, + mandate_revoke::MandateRevoke, AccessTokenAuth, Authenticate, AuthenticationConfirmation, GetAdditionalRevenueRecoveryDetails, PostAuthenticate, PreAuthenticate, VerifyWebhookSource }, router_request_types::{ unified_authentication_service::{ UasAuthenticationRequestData, UasAuthenticationResponseData, UasConfirmationRequestData, UasPostAuthenticationRequestData, UasPreAuthenticationRequestData, - }, - AccessTokenRequestData, MandateRevokeRequestData, VerifyWebhookSourceRequestData, + }, AccessTokenRequestData, AdditionalRevenueRecoveryDetailsRequestData, MandateRevokeRequestData, VerifyWebhookSourceRequestData }, router_response_types::{ - ConnectorInfo, MandateRevokeResponseData, PaymentMethodDetails, SupportedPaymentMethods, - VerifyWebhookSourceResponseData, + AdditionalRevenueRecoveryDetailsResponseData, ConnectorInfo, MandateRevokeResponseData, PaymentMethodDetails, SupportedPaymentMethods, VerifyWebhookSourceResponseData }, }; use masking::Maskable; @@ -370,6 +367,27 @@ pub trait ConnectorVerifyWebhookSourceV2: { } +/// trait ConnectorAdditionalRevenueRecoveryDetailsCall +pub trait ConnectorAdditionalRevenueRecoveryDetailsCall: + ConnectorIntegration< + GetAdditionalRevenueRecoveryDetails, + AdditionalRevenueRecoveryDetailsRequestData, + AdditionalRevenueRecoveryDetailsResponseData +> +{ +} + +/// trait ConnectorAdditionalRevenueRecoveryDetailsCallV2 +pub trait ConnectorAdditionalRevenueRecoveryDetailsCallV2 : + ConnectorIntegrationV2< + GetAdditionalRevenueRecoveryDetails, + AdditionalRevenueRecoveryCallFlowCommonData, + AdditionalRevenueRecoveryDetailsRequestData, + AdditionalRevenueRecoveryDetailsResponseData +> +{ +} + /// trait UnifiedAuthenticationService pub trait UnifiedAuthenticationService: ConnectorCommon diff --git a/crates/hyperswitch_interfaces/src/types.rs b/crates/hyperswitch_interfaces/src/types.rs index d7c7360a2db..c82553c4ce8 100644 --- a/crates/hyperswitch_interfaces/src/types.rs +++ b/crates/hyperswitch_interfaces/src/types.rs @@ -17,7 +17,7 @@ use hyperswitch_domain_models::{ unified_authentication_service::{ Authenticate, AuthenticationConfirmation, PostAuthenticate, PreAuthenticate, }, - webhooks::VerifyWebhookSource, + webhooks::{VerifyWebhookSource,GetAdditionalRevenueRecoveryDetails}, }, router_request_types::{ unified_authentication_service::{ @@ -33,11 +33,13 @@ use hyperswitch_domain_models::{ PaymentsSessionData, PaymentsSyncData, PaymentsTaxCalculationData, RefundsData, RetrieveFileRequestData, SdkPaymentsSessionUpdateData, SetupMandateRequestData, SubmitEvidenceRequestData, UploadFileRequestData, VerifyWebhookSourceRequestData, + AdditionalRevenueRecoveryDetailsRequestData }, router_response_types::{ AcceptDisputeResponse, DefendDisputeResponse, MandateRevokeResponseData, PaymentsResponseData, RefundsResponseData, RetrieveFileResponse, SubmitEvidenceResponse, TaxCalculationResponseData, UploadFileResponse, VerifyWebhookSourceResponseData, + AdditionalRevenueRecoveryDetailsResponseData }, }; #[cfg(feature = "payouts")] @@ -222,3 +224,10 @@ pub type UasAuthenticationType = dyn ConnectorIntegration< UasAuthenticationRequestData, UasAuthenticationResponseData, >; + +///Type alias for `ConnectorIntegration` +pub type AdditionalRevenueRecoveryCallType = dyn ConnectorIntegration< + GetAdditionalRevenueRecoveryDetails, + AdditionalRevenueRecoveryDetailsRequestData, + AdditionalRevenueRecoveryDetailsResponseData +>; \ No newline at end of file diff --git a/crates/router/src/configs/secrets_transformers.rs b/crates/router/src/configs/secrets_transformers.rs index 65ac6adf5bc..58accadfc51 100644 --- a/crates/router/src/configs/secrets_transformers.rs +++ b/crates/router/src/configs/secrets_transformers.rs @@ -506,6 +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, + additonal_recovery_details_call : conf.additonal_recovery_details_call, payment_method_auth, connector_request_reference_id_config: conf.connector_request_reference_id_config, #[cfg(feature = "payouts")] diff --git a/crates/router/src/configs/settings.rs b/crates/router/src/configs/settings.rs index 91ef78a68d5..65ab99c928d 100644 --- a/crates/router/src/configs/settings.rs +++ b/crates/router/src/configs/settings.rs @@ -96,6 +96,7 @@ pub struct Settings { pub required_fields: RequiredFields, pub delayed_session_response: DelayedSessionConfig, pub webhook_source_verification_call: WebhookSourceVerificationCall, + pub additonal_recovery_details_call : GetAdditionalRecoveryDetailsCall, pub payment_method_auth: SecretStateContainer, pub connector_request_reference_id_config: ConnectorRequestReferenceIdConfig, #[cfg(feature = "payouts")] @@ -847,6 +848,12 @@ pub struct WebhookSourceVerificationCall { pub connectors_with_webhook_source_verification_call: HashSet, } +#[derive(Debug, Deserialize, Clone, Default)] +pub struct GetAdditionalRecoveryDetailsCall{ + #[serde(deserialize_with = "deserialize_hashset")] + pub connectors_with_additional_revenue_recovery_details_call : HashSet +} + #[derive(Debug, Deserialize, Clone, Default)] pub struct ApplePayDecryptConfig { pub apple_pay_ppc: Secret, diff --git a/crates/router/src/core/payments/flows.rs b/crates/router/src/core/payments/flows.rs index f85d6220e0b..8243b1cf675 100644 --- a/crates/router/src/core/payments/flows.rs +++ b/crates/router/src/core/payments/flows.rs @@ -15,7 +15,7 @@ use async_trait::async_trait; use hyperswitch_domain_models::{ mandates::CustomerAcceptance, router_flow_types::{ - Authenticate, AuthenticationConfirmation, PostAuthenticate, PreAuthenticate, + Authenticate, AuthenticationConfirmation, PostAuthenticate, PreAuthenticate, GetAdditionalRevenueRecoveryDetails }, router_request_types::PaymentsCaptureData, }; @@ -2492,3 +2492,55 @@ fn handle_post_capture_response( } } } + +macro_rules! default_imp_for_additional_revenue_recovery_call { + ($($path:ident::$connector:ident),*) => { + $( impl api::ConnectorAdditionalRevenueRecoveryDetailsCall for $path::$connector {} + impl + services::ConnectorIntegration< + GetAdditionalRevenueRecoveryDetails, + types::AdditionalRevenueRecoveryDetailsRequestData, + types::AdditionalRevenueRecoveryDetailsResponseData, + > for $path::$connector + {} + )* + }; +} + +#[cfg(feature = "dummy_connector")] +impl api::ConnectorAdditionalRevenueRecoveryDetailsCall for connector::DummyConnector {} +#[cfg(feature = "dummy_connector")] +impl + services::ConnectorIntegration< + GetAdditionalRevenueRecoveryDetails, + types::AdditionalRevenueRecoveryDetailsRequestData, + types::AdditionalRevenueRecoveryDetailsResponseData, + > for connector::DummyConnector +{ +} + +default_imp_for_additional_revenue_recovery_call!( + connector::Adyen, + connector::Adyenplatform, + connector::Authorizedotnet, + connector::Checkout, + connector::Ebanx, + connector::Gpayments, + connector::Netcetera, + connector::Nmi, + connector::Noon, + connector::Opayo, + connector::Opennode, + connector::Payme, + connector::Payone, + connector::Paypal, + connector::Plaid, + connector::Riskified, + connector::Signifyd, + connector::Stripe, + connector::Threedsecureio, + connector::Trustpay, + connector::Wellsfargopayout, + connector::Wise +); + diff --git a/crates/router/src/services/api.rs b/crates/router/src/services/api.rs index 8095907eca8..95abb002ac2 100644 --- a/crates/router/src/services/api.rs +++ b/crates/router/src/services/api.rs @@ -108,6 +108,9 @@ pub type BoxedFilesConnectorIntegrationInterface = pub type BoxedUnifiedAuthenticationServiceInterface = BoxedConnectorIntegrationInterface; +pub type BoxedGetAdditionalRecoveryRecoveryDetailsIntegrationInterface = + BoxedConnectorIntegrationInterface; + /// Handle the flow by interacting with connector module /// `connector_request` is applicable only in case if the `CallConnectorAction` is `Trigger` /// In other cases, It will be created if required, even if it is not passed diff --git a/crates/router/src/types.rs b/crates/router/src/types.rs index 7bfbc22d05e..2eadf90d1b9 100644 --- a/crates/router/src/types.rs +++ b/crates/router/src/types.rs @@ -73,14 +73,14 @@ pub use hyperswitch_domain_models::{ PaymentsSessionData, PaymentsSyncData, PaymentsTaxCalculationData, RefundsData, ResponseId, RetrieveFileRequestData, SdkPaymentsSessionUpdateData, SetupMandateRequestData, SplitRefundsRequest, SubmitEvidenceRequestData, SyncRequestType, UploadFileRequestData, - VerifyWebhookSourceRequestData, + VerifyWebhookSourceRequestData, AdditionalRevenueRecoveryDetailsRequestData }, router_response_types::{ AcceptDisputeResponse, CaptureSyncResponse, DefendDisputeResponse, MandateReference, MandateRevokeResponseData, PaymentsResponseData, PreprocessingResponseId, RefundsResponseData, RetrieveFileResponse, SubmitEvidenceResponse, TaxCalculationResponseData, UploadFileResponse, VerifyWebhookSourceResponseData, - VerifyWebhookStatus, + VerifyWebhookStatus, AdditionalRevenueRecoveryDetailsResponseData }, }; #[cfg(feature = "payouts")] diff --git a/crates/router/src/types/api.rs b/crates/router/src/types/api.rs index bc5c3750cfe..155615c8540 100644 --- a/crates/router/src/types/api.rs +++ b/crates/router/src/types/api.rs @@ -48,7 +48,7 @@ pub use hyperswitch_domain_models::router_flow_types::{ pub use hyperswitch_interfaces::api::{ ConnectorAccessToken, ConnectorAccessTokenV2, ConnectorCommon, ConnectorCommonExt, ConnectorMandateRevoke, ConnectorMandateRevokeV2, ConnectorVerifyWebhookSource, - ConnectorVerifyWebhookSourceV2, CurrencyUnit, + ConnectorVerifyWebhookSourceV2, CurrencyUnit, ConnectorAdditionalRevenueRecoveryDetailsCall,ConnectorAdditionalRevenueRecoveryDetailsCallV2 }; use hyperswitch_interfaces::api::{UnifiedAuthenticationService, UnifiedAuthenticationServiceV2}; @@ -108,6 +108,7 @@ pub trait Connector: + ExternalAuthentication + TaxCalculation + UnifiedAuthenticationService + + ConnectorAdditionalRevenueRecoveryDetailsCall { } @@ -127,7 +128,9 @@ impl< + ConnectorMandateRevoke + ExternalAuthentication + TaxCalculation - + UnifiedAuthenticationService, + + UnifiedAuthenticationService + + ConnectorAdditionalRevenueRecoveryDetailsCall + > Connector for T { } @@ -148,6 +151,7 @@ pub trait ConnectorV2: + ConnectorMandateRevokeV2 + ExternalAuthenticationV2 + UnifiedAuthenticationServiceV2 + + ConnectorAdditionalRevenueRecoveryDetailsCallV2 { } impl< @@ -165,7 +169,8 @@ impl< + FraudCheckV2 + ConnectorMandateRevokeV2 + ExternalAuthenticationV2 - + UnifiedAuthenticationServiceV2, + + UnifiedAuthenticationServiceV2 + +ConnectorAdditionalRevenueRecoveryDetailsCallV2, > ConnectorV2 for T { } From ccfcff37c85994bdaeef81f15874f9a8cfbbbc7f Mon Sep 17 00:00:00 2001 From: "hyperswitch-bot[bot]" <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Date: Thu, 27 Feb 2025 13:27:58 +0000 Subject: [PATCH 08/83] chore: run formatter --- crates/hyperswitch_connectors/src/connectors.rs | 5 +++-- crates/router/src/connector.rs | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/crates/hyperswitch_connectors/src/connectors.rs b/crates/hyperswitch_connectors/src/connectors.rs index 74e99d93fcd..bf815d5c2ca 100644 --- a/crates/hyperswitch_connectors/src/connectors.rs +++ b/crates/hyperswitch_connectors/src/connectors.rs @@ -84,8 +84,9 @@ pub use self::{ nexinets::Nexinets, nexixpay::Nexixpay, nomupay::Nomupay, novalnet::Novalnet, nuvei::Nuvei, paybox::Paybox, payeezy::Payeezy, paystack::Paystack, payu::Payu, placetopay::Placetopay, powertranz::Powertranz, prophetpay::Prophetpay, rapyd::Rapyd, razorpay::Razorpay, - redsys::Redsys, shift4::Shift4, square::Square, stax::Stax,stripebilling::Stripebilling, taxjar::Taxjar, thunes::Thunes, - tsys::Tsys, unified_authentication_service::UnifiedAuthenticationService, volt::Volt, + redsys::Redsys, shift4::Shift4, square::Square, stax::Stax, stripebilling::Stripebilling, + taxjar::Taxjar, thunes::Thunes, tsys::Tsys, + unified_authentication_service::UnifiedAuthenticationService, volt::Volt, wellsfargo::Wellsfargo, worldline::Worldline, worldpay::Worldpay, xendit::Xendit, zen::Zen, zsl::Zsl, }; diff --git a/crates/router/src/connector.rs b/crates/router/src/connector.rs index 9c6987aa8b7..c4720f60ff6 100644 --- a/crates/router/src/connector.rs +++ b/crates/router/src/connector.rs @@ -44,8 +44,9 @@ pub use hyperswitch_connectors::connectors::{ nuvei::Nuvei, paybox, paybox::Paybox, payeezy, payeezy::Payeezy, paystack, paystack::Paystack, payu, payu::Payu, placetopay, placetopay::Placetopay, powertranz, powertranz::Powertranz, prophetpay, prophetpay::Prophetpay, rapyd, rapyd::Rapyd, razorpay, razorpay::Razorpay, redsys, - redsys::Redsys, shift4, shift4::Shift4, square, square::Square, stax, stax::Stax, stripebilling, - stripebilling::Stripebilling, taxjar, taxjar::Taxjar, thunes, thunes::Thunes, tsys, tsys::Tsys, unified_authentication_service, + redsys::Redsys, shift4, shift4::Shift4, square, square::Square, stax, stax::Stax, + stripebilling, stripebilling::Stripebilling, taxjar, taxjar::Taxjar, thunes, thunes::Thunes, + tsys, tsys::Tsys, unified_authentication_service, unified_authentication_service::UnifiedAuthenticationService, volt, volt::Volt, wellsfargo, wellsfargo::Wellsfargo, worldline, worldline::Worldline, worldpay, worldpay::Worldpay, xendit, xendit::Xendit, zen, zen::Zen, zsl, zsl::Zsl, From edbe0bd846afeaabaf2d1a0df9a697d330d0532e Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Mon, 3 Mar 2025 14:09:15 +0530 Subject: [PATCH 09/83] add incoming webhook support and recovery invoice flow --- .../src/connectors/stripebilling.rs | 103 ++++++++++++ .../connectors/stripebilling/transformers.rs | 149 +++++++++++++++++- crates/hyperswitch_connectors/src/utils.rs | 14 +- 3 files changed, 264 insertions(+), 2 deletions(-) diff --git a/crates/hyperswitch_connectors/src/connectors/stripebilling.rs b/crates/hyperswitch_connectors/src/connectors/stripebilling.rs index e05fb8b8e33..8201a151e29 100644 --- a/crates/hyperswitch_connectors/src/connectors/stripebilling.rs +++ b/crates/hyperswitch_connectors/src/connectors/stripebilling.rs @@ -6,6 +6,7 @@ use common_utils::{ request::{Method, Request, RequestBuilder, RequestContent}, types::{AmountConvertor, StringMinorUnit, StringMinorUnitForConnector}, }; +use std::collections::HashMap; use error_stack::{report, ResultExt}; use hyperswitch_domain_models::{ router_data::{AccessToken, ConnectorAuthType, ErrorResponse, RouterData}, @@ -548,13 +549,86 @@ impl ConnectorIntegration for Stripebil #[async_trait::async_trait] impl webhooks::IncomingWebhook for Stripebilling { + fn get_webhook_source_verification_algorithm( + &self, + _request: &webhooks::IncomingWebhookRequestDetails<'_>, + ) -> CustomResult, errors::ConnectorError> { + Ok(Box::new(common_utils::crypto::HmacSha256)) + } + + fn get_webhook_source_verification_signature( + &self, + request: &webhooks::IncomingWebhookRequestDetails<'_>, + _connector_webhook_secrets: &api_models::webhooks::ConnectorWebhookSecrets, + ) -> CustomResult, errors::ConnectorError> { + //signature contains the timestamp and the signature and signature will have the versions we need only v1 + //handled where the signature is needed + let mut header_hashmap = get_signature_elements_from_header(request.headers)?; + let signature = header_hashmap.remove("v1").ok_or(errors::ConnectorError::WebhookSignatureNotFound)?; + hex::decode(signature).change_context(errors::ConnectorError::WebhookSignatureNotFound) + } + + fn get_webhook_source_verification_message( + &self, + request : &webhooks::IncomingWebhookRequestDetails<'_>, + _merchant_id : &common_utils::id_type::MerchantId, + _connector_webhook_secrets : &api_models::webhooks::ConnectorWebhookSecrets + )->CustomResult,errors::ConnectorError>{ + let mut header_hashmap = get_signature_elements_from_header(request.headers)?; + let timestamp = header_hashmap.remove("t").ok_or(errors::ConnectorError::WebhookSignatureNotFound)?; + Ok(format!( + "{}.{}", + String::from_utf8_lossy(×tamp), + String::from_utf8_lossy(request.body) + ).into_bytes()) + } + + #[cfg(all(feature = "revenue_recovery", feature = "v2"))] + fn get_webhook_object_reference_id( + &self, + request: &webhooks::IncomingWebhookRequestDetails<'_>, + ) -> CustomResult { + // for stripebilling we need an additional call to fetch the recovery required data . So instead of Invoice Id we sent ChargeId + let webhook = stripebilling::StripebillingWebhookBody::get_webhook_object_from_body(request.body) + .change_context(errors::ConnectorError::WebhookReferenceIdNotFound)?; + Ok(api_models::webhooks::ObjectReferenceId::PaymentId( + api_models::payments::PaymentIdType::ConnectorTransactionId( + webhook.data.object.charge, + ), + )) + } + + #[cfg(any(feature = "v1", not(all(feature = "revenue_recovery", feature = "v2"))))] fn get_webhook_object_reference_id( &self, _request: &webhooks::IncomingWebhookRequestDetails<'_>, ) -> CustomResult { Err(report!(errors::ConnectorError::WebhooksNotImplemented)) } + #[cfg(all(feature = "revenue_recovery", feature = "v2"))] + fn get_webhook_event_type( + &self, + request: &webhooks::IncomingWebhookRequestDetails<'_>, + ) -> CustomResult { + + let webhook = stripebilling::StripebillingWebhookBody::get_webhook_object_from_body(request.body) + .change_context(errors::ConnectorError::WebhookEventTypeNotFound)?; + + let event = match webhook.event_type { + stripebilling::StripebillingEventType::PaymentSucceeded => { + api_models::webhooks::IncomingWebhookEvent::RecoveryPaymentSuccess + } + stripebilling::StripebillingEventType::PaymentFailed => { + api_models::webhooks::IncomingWebhookEvent::RecoveryPaymentFailure + } + stripebilling::StripebillingEventType::InvoiceDeleted => { + api_models::webhooks::IncomingWebhookEvent::RecoveryInvoiceCancel + } + }; + Ok(event) + } + #[cfg(any(feature = "v1", not(all(feature = "revenue_recovery", feature = "v2"))))] fn get_webhook_event_type( &self, _request: &webhooks::IncomingWebhookRequestDetails<'_>, @@ -562,12 +636,41 @@ impl webhooks::IncomingWebhook for Stripebilling { Err(report!(errors::ConnectorError::WebhooksNotImplemented)) } + + #[cfg(any(feature = "v1", not(all(feature = "revenue_recovery", feature = "v2"))))] fn get_webhook_resource_object( &self, _request: &webhooks::IncomingWebhookRequestDetails<'_>, ) -> CustomResult, errors::ConnectorError> { Err(report!(errors::ConnectorError::WebhooksNotImplemented)) } + + #[cfg(all(feature = "revenue_recovery", feature = "v2"))] + fn get_webhook_resource_object( + &self, + request: &webhooks::IncomingWebhookRequestDetails<'_>, + ) -> CustomResult, errors::ConnectorError> { + let webhook = + stripebilling::StripebillingInvoiceBody::get_invoice_webhook_data_from_body(request.body) + .change_context(errors::ConnectorError::WebhookResourceObjectNotFound)?; + Ok(Box::new(webhook)) + } +} + +fn get_signature_elements_from_header( + headers : &actix_web::http::header::HeaderMap +) -> CustomResult>, errors::ConnectorError>{ + let security_header = headers.get("stripe-signature").ok_or(errors::ConnectorError::WebhookSignatureNotFound)?; + let security_header_str = security_header.to_str().change_context(errors::ConnectorError::WebhookSignatureNotFound)?; + let header_parts = security_header_str.split(',').collect::>(); + let mut header_hashmap : HashMap> = HashMap::with_capacity(header_parts.len()); + + for header_part in header_parts{ + let (header_key,header_value) = header_part.split_once('=').ok_or(errors::ConnectorError::WebhookSignatureNotFound)?; + header_hashmap.insert(header_key.to_string(),header_value.bytes().collect()); + } + + Ok(header_hashmap) } impl ConnectorSpecifications for Stripebilling {} diff --git a/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs b/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs index dcaa2474639..582f691103f 100644 --- a/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs @@ -11,11 +11,17 @@ use hyperswitch_domain_models::{ use hyperswitch_interfaces::errors; use masking::Secret; use serde::{Deserialize, Serialize}; +use error_stack::ResultExt; +#[cfg(all(feature = "revenue_recovery", feature = "v2"))] +use hyperswitch_domain_models::revenue_recovery; +#[cfg(feature="v2")] +use std::str::FromStr; use crate::{ types::{RefundsResponseRouterData, ResponseRouterData}, - utils::PaymentsAuthorizeRequestData, + utils::{PaymentsAuthorizeRequestData,convert_uppercase}, }; +use common_utils::{errors::CustomResult,ext_traits::ByteSliceExt}; //TODO: Fill the struct with respective fields pub struct StripebillingRouterData { @@ -230,3 +236,144 @@ pub struct StripebillingErrorResponse { pub message: String, pub reason: Option, } + + +#[derive(Debug,Serialize,Deserialize)] +pub struct StripebillingWebhookBody { + #[serde(rename = "type")] + pub event_type : StripebillingEventType, + pub data : StripebillingWebhookData +} + +#[derive(Debug,Serialize,Deserialize)] +pub struct StripebillingInvoiceBody { + #[serde(rename = "type")] + pub event_type : StripebillingEventType, + pub data : StripebillingInvoiceData +} + + +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "snake_case")] +pub enum StripebillingEventType { + #[serde(rename="invoice.paid")] + PaymentSucceeded, + #[serde(rename="invoice.payment_failed")] + PaymentFailed, + #[serde(rename="invoice.voided")] + InvoiceDeleted +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct StripebillingWebhookData { + pub object : StripebillingWebhookObject +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct StripebillingInvoiceData { + pub object : StripebillingWebhookObject +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct StripebillingWebhookObject{ + #[serde(rename="id")] + pub invoice_id : String, + #[serde(deserialize_with="convert_uppercase")] + pub currency : enums::Currency, + pub customer : String, + #[serde(rename="amount_remaining")] + pub amount : common_utils::types::MinorUnit, + pub charge : String +} + +#[derive(Debug,Serialize,Deserialize)] +pub struct StripebillingInvoiceObject{ + #[serde(rename="id")] + pub invoice_id : String, + #[serde(deserialize_with="convert_uppercase")] + pub currency : enums::Currency, + #[serde(rename="amount_remaining")] + pub amount : common_utils::types::MinorUnit, +} + + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct StripePaymentMethodDetails{ + #[serde(rename="type")] + pub type_of_payment_method : StripebillingPaymentMethod, + #[serde(rename="card")] + pub card_funding_type : StripeCardFundingTypeDetails, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +#[serde(rename_all="snake_case")] +pub enum StripebillingPaymentMethod { + Card, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct StripeCardFundingTypeDetails{ + pub funding : StripebillingFundingTypes +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +#[serde(rename="snake_case")] +pub enum StripebillingFundingTypes { + #[serde(rename="credit")] + Credit, + #[serde(rename="debit")] + Debit, + #[serde(rename="prepaid")] + Prepaid, + #[serde(rename="unknown")] + Unknown +} + +#[derive(Serialize, Deserialize, Debug,Clone)] +#[serde(rename_all = "snake_case")] +pub enum StripebillingChargeStatus{ + Succeeded, + Failed, + Pending +} + + +impl StripebillingWebhookBody { + pub fn get_webhook_object_from_body( + body: &[u8], + ) -> CustomResult { + let webhook_body: Self = body + .parse_struct::("StripebillingWebhookBody") + .change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?; + + Ok(webhook_body) + } +} + + +impl StripebillingInvoiceBody { + pub fn get_invoice_webhook_data_from_body( + body: &[u8], + ) -> CustomResult { + let webhook_body = body + .parse_struct::("StripebillingInvoiceBody") + .change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?; + Ok(webhook_body) + } +} + +#[cfg(all(feature = "revenue_recovery", feature = "v2"))] +impl TryFrom for revenue_recovery::RevenueRecoveryInvoiceData { + type Error = error_stack::Report; + fn try_from(item: StripebillingInvoiceBody) -> Result { + let merchant_reference_id = + common_utils::id_type::PaymentReferenceId::from_str(&item.data.object.invoice_id) + .change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?; + Ok(Self { + amount: item.data.object.amount, + currency: item.data.object.currency, + merchant_reference_id, + }) + } +} + diff --git a/crates/hyperswitch_connectors/src/utils.rs b/crates/hyperswitch_connectors/src/utils.rs index 05657216d9d..b236d594555 100644 --- a/crates/hyperswitch_connectors/src/utils.rs +++ b/crates/hyperswitch_connectors/src/utils.rs @@ -56,9 +56,10 @@ use masking::{ExposeInterface, PeekInterface, Secret}; use once_cell::sync::Lazy; use regex::Regex; use router_env::logger; -use serde::Serializer; +use serde::{Serializer,Deserialize}; use serde_json::Value; use time::PrimitiveDateTime; +use std::str::FromStr; use crate::{constants::UNSUPPORTED_ERROR_MESSAGE, types::RefreshTokenRouterData}; @@ -5662,3 +5663,14 @@ impl NetworkTokenData for payment_method_data::NetworkTokenData { self.cryptogram.clone() } } + +pub fn convert_uppercase<'de, D, T>(v: D) -> Result +where + D: serde::Deserializer<'de>, + T: FromStr, + ::Err: std::fmt::Debug + std::fmt::Display + std::error::Error, +{ + use serde::de::Error; + let output = <&str>::deserialize(v)?; + output.to_uppercase().parse::().map_err(D::Error::custom) +} From 3295979b3e78867825e3da5117602e1ddaded39b Mon Sep 17 00:00:00 2001 From: "hyperswitch-bot[bot]" <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Date: Mon, 3 Mar 2025 08:56:19 +0000 Subject: [PATCH 10/83] chore: run formatter --- .../src/default_implementations.rs | 22 +++---- .../src/router_request_types.rs | 4 +- .../src/router_response_types.rs | 57 +++++++++---------- crates/hyperswitch_domain_models/src/types.rs | 24 ++++++-- crates/hyperswitch_interfaces/src/api.rs | 27 +++++---- crates/hyperswitch_interfaces/src/types.rs | 18 +++--- .../src/configs/secrets_transformers.rs | 2 +- crates/router/src/configs/settings.rs | 6 +- crates/router/src/core/payments/flows.rs | 9 ++- crates/router/src/services/api.rs | 9 ++- crates/router/src/types.rs | 15 ++--- crates/router/src/types/api.rs | 10 ++-- 12 files changed, 115 insertions(+), 88 deletions(-) diff --git a/crates/hyperswitch_connectors/src/default_implementations.rs b/crates/hyperswitch_connectors/src/default_implementations.rs index 990bb8443c2..2d082667402 100644 --- a/crates/hyperswitch_connectors/src/default_implementations.rs +++ b/crates/hyperswitch_connectors/src/default_implementations.rs @@ -33,7 +33,8 @@ use hyperswitch_domain_models::{ PreProcessing, Reject, SdkSessionUpdate, }, webhooks::VerifyWebhookSource, - Authenticate, AuthenticationConfirmation, PostAuthenticate, PreAuthenticate, GetAdditionalRevenueRecoveryDetails + Authenticate, AuthenticationConfirmation, GetAdditionalRevenueRecoveryDetails, + PostAuthenticate, PreAuthenticate, }, router_request_types::{ unified_authentication_service::{ @@ -41,19 +42,19 @@ use hyperswitch_domain_models::{ UasConfirmationRequestData, UasPostAuthenticationRequestData, UasPreAuthenticationRequestData, }, - AcceptDisputeRequestData, AuthorizeSessionTokenData, CompleteAuthorizeData, - ConnectorCustomerData, DefendDisputeRequestData, MandateRevokeRequestData, - PaymentsApproveData, PaymentsIncrementalAuthorizationData, PaymentsPostProcessingData, + AcceptDisputeRequestData, AdditionalRevenueRecoveryDetailsRequestData, + AuthorizeSessionTokenData, CompleteAuthorizeData, ConnectorCustomerData, + DefendDisputeRequestData, MandateRevokeRequestData, PaymentsApproveData, + PaymentsIncrementalAuthorizationData, PaymentsPostProcessingData, PaymentsPostSessionTokensData, PaymentsPreProcessingData, PaymentsRejectData, PaymentsTaxCalculationData, RetrieveFileRequestData, SdkPaymentsSessionUpdateData, SubmitEvidenceRequestData, UploadFileRequestData, VerifyWebhookSourceRequestData, - AdditionalRevenueRecoveryDetailsRequestData }, router_response_types::{ - AcceptDisputeResponse, DefendDisputeResponse, MandateRevokeResponseData, - PaymentsResponseData, RetrieveFileResponse, SubmitEvidenceResponse, - TaxCalculationResponseData, UploadFileResponse, VerifyWebhookSourceResponseData, - AdditionalRevenueRecoveryDetailsResponseData + AcceptDisputeResponse, AdditionalRevenueRecoveryDetailsResponseData, DefendDisputeResponse, + MandateRevokeResponseData, PaymentsResponseData, RetrieveFileResponse, + SubmitEvidenceResponse, TaxCalculationResponseData, UploadFileResponse, + VerifyWebhookSourceResponseData, }, }; #[cfg(feature = "frm")] @@ -79,7 +80,7 @@ use hyperswitch_interfaces::{ }, ConnectorIntegration, ConnectorMandateRevoke, ConnectorRedirectResponse, UasAuthentication, UasAuthenticationConfirmation, UasPostAuthentication, UasPreAuthentication, - UnifiedAuthenticationService + UnifiedAuthenticationService, }, errors::ConnectorError, }; @@ -3225,7 +3226,6 @@ default_imp_for_uas_authentication_confirmation!( connectors::Zsl ); - macro_rules! default_imp_for_additional_revenue_recovery_call { ($($path:ident::$connector:ident),*) => { $( impl api::ConnectorAdditionalRevenueRecoveryDetailsCall for $path::$connector {} diff --git a/crates/hyperswitch_domain_models/src/router_request_types.rs b/crates/hyperswitch_domain_models/src/router_request_types.rs index 2665b2f44ba..9d60519c241 100644 --- a/crates/hyperswitch_domain_models/src/router_request_types.rs +++ b/crates/hyperswitch_domain_models/src/router_request_types.rs @@ -915,6 +915,6 @@ pub struct SetupMandateRequestData { } #[derive(Debug, Clone)] -pub struct AdditionalRevenueRecoveryDetailsRequestData{ - pub transaction_id : String, +pub struct AdditionalRevenueRecoveryDetailsRequestData { + pub transaction_id: String, } diff --git a/crates/hyperswitch_domain_models/src/router_response_types.rs b/crates/hyperswitch_domain_models/src/router_response_types.rs index 40cf11fb7f4..1fab175c86c 100644 --- a/crates/hyperswitch_domain_models/src/router_response_types.rs +++ b/crates/hyperswitch_domain_models/src/router_response_types.rs @@ -1,10 +1,10 @@ pub mod disputes; pub mod fraud_check; use std::collections::HashMap; -use time::PrimitiveDateTime; use common_utils::{request::Method, types::MinorUnit}; pub use disputes::{AcceptDisputeResponse, DefendDisputeResponse, SubmitEvidenceResponse}; +use time::PrimitiveDateTime; use crate::{ errors::api_error_response::ApiErrorResponse, @@ -605,33 +605,32 @@ impl SupportedPaymentMethodsExt for SupportedPaymentMethods { } } - -#[derive(Debug, Clone, serde::Deserialize,serde::Serialize)] +#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] pub struct AdditionalRevenueRecoveryDetailsResponseData { - /// transaction amount against invoice, accepted in minor unit. - pub amount: MinorUnit, - /// currency of the transaction - pub currency: common_enums::enums::Currency, - /// merchant reference id at billing connector. ex: invoice_id - pub merchant_reference_id: common_utils::id_type::PaymentReferenceId, - /// transaction id reference at payment connector - pub connector_transaction_id: Option, - /// error code sent by billing connector. - pub error_code: Option, - /// error message sent by billing connector. - pub error_message: Option, - /// mandate token at payment processor end. - pub processor_payment_method_token: Option, - /// customer id at payment connector for which mandate is attached. - pub connector_customer_id: Option, - /// Payment gateway identifier id at billing processor. - pub connector_account_reference_id: Option, - /// timestamp at which transaction has been created at billing connector - pub transaction_created_at: Option, - /// transaction status at billing connector equivalent to payment attempt status. - pub status: common_enums::enums::AttemptStatus, - /// payment method of payment attempt. - pub payment_method_type: common_enums::enums::PaymentMethod, - /// payment method sub type of the payment attempt. - pub payment_method_sub_type: common_enums::enums::PaymentMethodType, + /// transaction amount against invoice, accepted in minor unit. + pub amount: MinorUnit, + /// currency of the transaction + pub currency: common_enums::enums::Currency, + /// merchant reference id at billing connector. ex: invoice_id + pub merchant_reference_id: common_utils::id_type::PaymentReferenceId, + /// transaction id reference at payment connector + pub connector_transaction_id: Option, + /// error code sent by billing connector. + pub error_code: Option, + /// error message sent by billing connector. + pub error_message: Option, + /// mandate token at payment processor end. + pub processor_payment_method_token: Option, + /// customer id at payment connector for which mandate is attached. + pub connector_customer_id: Option, + /// Payment gateway identifier id at billing processor. + pub connector_account_reference_id: Option, + /// timestamp at which transaction has been created at billing connector + pub transaction_created_at: Option, + /// transaction status at billing connector equivalent to payment attempt status. + pub status: common_enums::enums::AttemptStatus, + /// payment method of payment attempt. + pub payment_method_type: common_enums::enums::PaymentMethod, + /// payment method sub type of the payment attempt. + pub payment_method_sub_type: common_enums::enums::PaymentMethodType, } diff --git a/crates/hyperswitch_domain_models/src/types.rs b/crates/hyperswitch_domain_models/src/types.rs index d190bafc03a..2e73f696566 100644 --- a/crates/hyperswitch_domain_models/src/types.rs +++ b/crates/hyperswitch_domain_models/src/types.rs @@ -3,17 +3,28 @@ pub use diesel_models::types::OrderDetailsWithAmount; use crate::{ router_data::{AccessToken, RouterData}, router_flow_types::{ - mandate_revoke::MandateRevoke, AccessTokenAuth, Authenticate, AuthenticationConfirmation, Authorize, AuthorizeSessionToken, CalculateTax, Capture, CompleteAuthorize, CreateConnectorCustomer, Execute, GetAdditionalRevenueRecoveryDetails, IncrementalAuthorization, PSync, PaymentMethodToken, PostAuthenticate, PostSessionTokens, PreAuthenticate, PreProcessing, RSync, Session, SetupMandate, Void + mandate_revoke::MandateRevoke, AccessTokenAuth, Authenticate, AuthenticationConfirmation, + Authorize, AuthorizeSessionToken, CalculateTax, Capture, CompleteAuthorize, + CreateConnectorCustomer, Execute, GetAdditionalRevenueRecoveryDetails, + IncrementalAuthorization, PSync, PaymentMethodToken, PostAuthenticate, PostSessionTokens, + PreAuthenticate, PreProcessing, RSync, Session, SetupMandate, Void, }, router_request_types::{ unified_authentication_service::{ UasAuthenticationRequestData, UasAuthenticationResponseData, UasConfirmationRequestData, UasPostAuthenticationRequestData, UasPreAuthenticationRequestData, - }, AccessTokenRequestData, AdditionalRevenueRecoveryDetailsRequestData, AuthorizeSessionTokenData, CompleteAuthorizeData, ConnectorCustomerData, MandateRevokeRequestData, PaymentMethodTokenizationData, PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, PaymentsIncrementalAuthorizationData, PaymentsPostSessionTokensData, PaymentsPreProcessingData, PaymentsSessionData, PaymentsSyncData, PaymentsTaxCalculationData, RefundsData, SetupMandateRequestData + }, + AccessTokenRequestData, AdditionalRevenueRecoveryDetailsRequestData, + AuthorizeSessionTokenData, CompleteAuthorizeData, ConnectorCustomerData, + MandateRevokeRequestData, PaymentMethodTokenizationData, PaymentsAuthorizeData, + PaymentsCancelData, PaymentsCaptureData, PaymentsIncrementalAuthorizationData, + PaymentsPostSessionTokensData, PaymentsPreProcessingData, PaymentsSessionData, + PaymentsSyncData, PaymentsTaxCalculationData, RefundsData, SetupMandateRequestData, }, router_response_types::{ - AdditionalRevenueRecoveryDetailsResponseData, MandateRevokeResponseData, PaymentsResponseData, RefundsResponseData, TaxCalculationResponseData + AdditionalRevenueRecoveryDetailsResponseData, MandateRevokeResponseData, + PaymentsResponseData, RefundsResponseData, TaxCalculationResponseData, }, }; #[cfg(feature = "payouts")] @@ -71,5 +82,8 @@ pub type PayoutsRouterData = RouterData; pub type UasAuthenticationRouterData = RouterData; -pub type AdditionalRevenueRecoveryDetailsRouterData = - RouterData; +pub type AdditionalRevenueRecoveryDetailsRouterData = RouterData< + GetAdditionalRevenueRecoveryDetails, + AdditionalRevenueRecoveryDetailsRequestData, + AdditionalRevenueRecoveryDetailsResponseData, +>; diff --git a/crates/hyperswitch_interfaces/src/api.rs b/crates/hyperswitch_interfaces/src/api.rs index 544468e9c33..a0c159ea637 100644 --- a/crates/hyperswitch_interfaces/src/api.rs +++ b/crates/hyperswitch_interfaces/src/api.rs @@ -30,21 +30,26 @@ use hyperswitch_domain_models::{ payment_method_data::PaymentMethodData, router_data::{AccessToken, ConnectorAuthType, ErrorResponse, RouterData}, router_data_v2::{ - flow_common_types::{AdditionalRevenueRecoveryCallFlowCommonData, WebhookSourceVerifyData}, AccessTokenFlowData, MandateRevokeFlowData, - UasFlowData, + flow_common_types::{AdditionalRevenueRecoveryCallFlowCommonData, WebhookSourceVerifyData}, + AccessTokenFlowData, MandateRevokeFlowData, UasFlowData, }, router_flow_types::{ - mandate_revoke::MandateRevoke, AccessTokenAuth, Authenticate, AuthenticationConfirmation, GetAdditionalRevenueRecoveryDetails, PostAuthenticate, PreAuthenticate, VerifyWebhookSource + mandate_revoke::MandateRevoke, AccessTokenAuth, Authenticate, AuthenticationConfirmation, + GetAdditionalRevenueRecoveryDetails, PostAuthenticate, PreAuthenticate, + VerifyWebhookSource, }, router_request_types::{ unified_authentication_service::{ UasAuthenticationRequestData, UasAuthenticationResponseData, UasConfirmationRequestData, UasPostAuthenticationRequestData, UasPreAuthenticationRequestData, - }, AccessTokenRequestData, AdditionalRevenueRecoveryDetailsRequestData, MandateRevokeRequestData, VerifyWebhookSourceRequestData + }, + AccessTokenRequestData, AdditionalRevenueRecoveryDetailsRequestData, + MandateRevokeRequestData, VerifyWebhookSourceRequestData, }, router_response_types::{ - AdditionalRevenueRecoveryDetailsResponseData, ConnectorInfo, MandateRevokeResponseData, PaymentMethodDetails, SupportedPaymentMethods, VerifyWebhookSourceResponseData + AdditionalRevenueRecoveryDetailsResponseData, ConnectorInfo, MandateRevokeResponseData, + PaymentMethodDetails, SupportedPaymentMethods, VerifyWebhookSourceResponseData, }, }; use masking::Maskable; @@ -368,24 +373,24 @@ pub trait ConnectorVerifyWebhookSourceV2: } /// trait ConnectorAdditionalRevenueRecoveryDetailsCall -pub trait ConnectorAdditionalRevenueRecoveryDetailsCall: +pub trait ConnectorAdditionalRevenueRecoveryDetailsCall: ConnectorIntegration< GetAdditionalRevenueRecoveryDetails, AdditionalRevenueRecoveryDetailsRequestData, - AdditionalRevenueRecoveryDetailsResponseData + AdditionalRevenueRecoveryDetailsResponseData, > -{ +{ } /// trait ConnectorAdditionalRevenueRecoveryDetailsCallV2 -pub trait ConnectorAdditionalRevenueRecoveryDetailsCallV2 : +pub trait ConnectorAdditionalRevenueRecoveryDetailsCallV2: ConnectorIntegrationV2< GetAdditionalRevenueRecoveryDetails, AdditionalRevenueRecoveryCallFlowCommonData, AdditionalRevenueRecoveryDetailsRequestData, - AdditionalRevenueRecoveryDetailsResponseData + AdditionalRevenueRecoveryDetailsResponseData, > -{ +{ } /// trait UnifiedAuthenticationService diff --git a/crates/hyperswitch_interfaces/src/types.rs b/crates/hyperswitch_interfaces/src/types.rs index c82553c4ce8..75d075e8c39 100644 --- a/crates/hyperswitch_interfaces/src/types.rs +++ b/crates/hyperswitch_interfaces/src/types.rs @@ -17,7 +17,7 @@ use hyperswitch_domain_models::{ unified_authentication_service::{ Authenticate, AuthenticationConfirmation, PostAuthenticate, PreAuthenticate, }, - webhooks::{VerifyWebhookSource,GetAdditionalRevenueRecoveryDetails}, + webhooks::{GetAdditionalRevenueRecoveryDetails, VerifyWebhookSource}, }, router_request_types::{ unified_authentication_service::{ @@ -25,7 +25,8 @@ use hyperswitch_domain_models::{ UasConfirmationRequestData, UasPostAuthenticationRequestData, UasPreAuthenticationRequestData, }, - AcceptDisputeRequestData, AccessTokenRequestData, AuthorizeSessionTokenData, + AcceptDisputeRequestData, AccessTokenRequestData, + AdditionalRevenueRecoveryDetailsRequestData, AuthorizeSessionTokenData, CompleteAuthorizeData, ConnectorCustomerData, DefendDisputeRequestData, MandateRevokeRequestData, PaymentMethodTokenizationData, PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, PaymentsIncrementalAuthorizationData, @@ -33,13 +34,12 @@ use hyperswitch_domain_models::{ PaymentsSessionData, PaymentsSyncData, PaymentsTaxCalculationData, RefundsData, RetrieveFileRequestData, SdkPaymentsSessionUpdateData, SetupMandateRequestData, SubmitEvidenceRequestData, UploadFileRequestData, VerifyWebhookSourceRequestData, - AdditionalRevenueRecoveryDetailsRequestData }, router_response_types::{ - AcceptDisputeResponse, DefendDisputeResponse, MandateRevokeResponseData, - PaymentsResponseData, RefundsResponseData, RetrieveFileResponse, SubmitEvidenceResponse, - TaxCalculationResponseData, UploadFileResponse, VerifyWebhookSourceResponseData, - AdditionalRevenueRecoveryDetailsResponseData + AcceptDisputeResponse, AdditionalRevenueRecoveryDetailsResponseData, DefendDisputeResponse, + MandateRevokeResponseData, PaymentsResponseData, RefundsResponseData, RetrieveFileResponse, + SubmitEvidenceResponse, TaxCalculationResponseData, UploadFileResponse, + VerifyWebhookSourceResponseData, }, }; #[cfg(feature = "payouts")] @@ -229,5 +229,5 @@ pub type UasAuthenticationType = dyn ConnectorIntegration< pub type AdditionalRevenueRecoveryCallType = dyn ConnectorIntegration< GetAdditionalRevenueRecoveryDetails, AdditionalRevenueRecoveryDetailsRequestData, - AdditionalRevenueRecoveryDetailsResponseData ->; \ No newline at end of file + AdditionalRevenueRecoveryDetailsResponseData, +>; diff --git a/crates/router/src/configs/secrets_transformers.rs b/crates/router/src/configs/secrets_transformers.rs index 58accadfc51..7c006e0e358 100644 --- a/crates/router/src/configs/secrets_transformers.rs +++ b/crates/router/src/configs/secrets_transformers.rs @@ -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, - additonal_recovery_details_call : conf.additonal_recovery_details_call, + additonal_recovery_details_call: conf.additonal_recovery_details_call, payment_method_auth, connector_request_reference_id_config: conf.connector_request_reference_id_config, #[cfg(feature = "payouts")] diff --git a/crates/router/src/configs/settings.rs b/crates/router/src/configs/settings.rs index 65ab99c928d..91dec21af79 100644 --- a/crates/router/src/configs/settings.rs +++ b/crates/router/src/configs/settings.rs @@ -96,7 +96,7 @@ pub struct Settings { pub required_fields: RequiredFields, pub delayed_session_response: DelayedSessionConfig, pub webhook_source_verification_call: WebhookSourceVerificationCall, - pub additonal_recovery_details_call : GetAdditionalRecoveryDetailsCall, + pub additonal_recovery_details_call: GetAdditionalRecoveryDetailsCall, pub payment_method_auth: SecretStateContainer, pub connector_request_reference_id_config: ConnectorRequestReferenceIdConfig, #[cfg(feature = "payouts")] @@ -849,9 +849,9 @@ pub struct WebhookSourceVerificationCall { } #[derive(Debug, Deserialize, Clone, Default)] -pub struct GetAdditionalRecoveryDetailsCall{ +pub struct GetAdditionalRecoveryDetailsCall { #[serde(deserialize_with = "deserialize_hashset")] - pub connectors_with_additional_revenue_recovery_details_call : HashSet + pub connectors_with_additional_revenue_recovery_details_call: HashSet, } #[derive(Debug, Deserialize, Clone, Default)] diff --git a/crates/router/src/core/payments/flows.rs b/crates/router/src/core/payments/flows.rs index 8243b1cf675..bfb2963d066 100644 --- a/crates/router/src/core/payments/flows.rs +++ b/crates/router/src/core/payments/flows.rs @@ -15,7 +15,8 @@ use async_trait::async_trait; use hyperswitch_domain_models::{ mandates::CustomerAcceptance, router_flow_types::{ - Authenticate, AuthenticationConfirmation, PostAuthenticate, PreAuthenticate, GetAdditionalRevenueRecoveryDetails + Authenticate, AuthenticationConfirmation, GetAdditionalRevenueRecoveryDetails, + PostAuthenticate, PreAuthenticate, }, router_request_types::PaymentsCaptureData, }; @@ -2508,7 +2509,10 @@ macro_rules! default_imp_for_additional_revenue_recovery_call { } #[cfg(feature = "dummy_connector")] -impl api::ConnectorAdditionalRevenueRecoveryDetailsCall for connector::DummyConnector {} +impl api::ConnectorAdditionalRevenueRecoveryDetailsCall + for connector::DummyConnector +{ +} #[cfg(feature = "dummy_connector")] impl services::ConnectorIntegration< @@ -2543,4 +2547,3 @@ default_imp_for_additional_revenue_recovery_call!( connector::Wellsfargopayout, connector::Wise ); - diff --git a/crates/router/src/services/api.rs b/crates/router/src/services/api.rs index 95abb002ac2..cf7a0aa85c0 100644 --- a/crates/router/src/services/api.rs +++ b/crates/router/src/services/api.rs @@ -108,8 +108,13 @@ pub type BoxedFilesConnectorIntegrationInterface = pub type BoxedUnifiedAuthenticationServiceInterface = BoxedConnectorIntegrationInterface; -pub type BoxedGetAdditionalRecoveryRecoveryDetailsIntegrationInterface = - BoxedConnectorIntegrationInterface; +pub type BoxedGetAdditionalRecoveryRecoveryDetailsIntegrationInterface = + BoxedConnectorIntegrationInterface< + T, + common_types::AdditionalRevenueRecoveryCallFlowCommonData, + Req, + Res, + >; /// Handle the flow by interacting with connector module /// `connector_request` is applicable only in case if the `CallConnectorAction` is `Trigger` diff --git a/crates/router/src/types.rs b/crates/router/src/types.rs index 2eadf90d1b9..11242119cba 100644 --- a/crates/router/src/types.rs +++ b/crates/router/src/types.rs @@ -62,8 +62,9 @@ pub use hyperswitch_domain_models::{ UasConfirmationRequestData, UasPostAuthenticationRequestData, UasPreAuthenticationRequestData, }, - AcceptDisputeRequestData, AccessTokenRequestData, AuthorizeSessionTokenData, - BrowserInformation, ChargeRefunds, ChargeRefundsOptions, CompleteAuthorizeData, + AcceptDisputeRequestData, AccessTokenRequestData, + AdditionalRevenueRecoveryDetailsRequestData, AuthorizeSessionTokenData, BrowserInformation, + ChargeRefunds, ChargeRefundsOptions, CompleteAuthorizeData, CompleteAuthorizeRedirectResponse, ConnectorCustomerData, DefendDisputeRequestData, DestinationChargeRefund, DirectChargeRefund, MandateRevokeRequestData, MultipleCaptureRequestData, PaymentMethodTokenizationData, PaymentsApproveData, @@ -73,14 +74,14 @@ pub use hyperswitch_domain_models::{ PaymentsSessionData, PaymentsSyncData, PaymentsTaxCalculationData, RefundsData, ResponseId, RetrieveFileRequestData, SdkPaymentsSessionUpdateData, SetupMandateRequestData, SplitRefundsRequest, SubmitEvidenceRequestData, SyncRequestType, UploadFileRequestData, - VerifyWebhookSourceRequestData, AdditionalRevenueRecoveryDetailsRequestData + VerifyWebhookSourceRequestData, }, router_response_types::{ - AcceptDisputeResponse, CaptureSyncResponse, DefendDisputeResponse, MandateReference, - MandateRevokeResponseData, PaymentsResponseData, PreprocessingResponseId, - RefundsResponseData, RetrieveFileResponse, SubmitEvidenceResponse, + AcceptDisputeResponse, AdditionalRevenueRecoveryDetailsResponseData, CaptureSyncResponse, + DefendDisputeResponse, MandateReference, MandateRevokeResponseData, PaymentsResponseData, + PreprocessingResponseId, RefundsResponseData, RetrieveFileResponse, SubmitEvidenceResponse, TaxCalculationResponseData, UploadFileResponse, VerifyWebhookSourceResponseData, - VerifyWebhookStatus, AdditionalRevenueRecoveryDetailsResponseData + VerifyWebhookStatus, }, }; #[cfg(feature = "payouts")] diff --git a/crates/router/src/types/api.rs b/crates/router/src/types/api.rs index 155615c8540..a412140d6e8 100644 --- a/crates/router/src/types/api.rs +++ b/crates/router/src/types/api.rs @@ -46,9 +46,10 @@ pub use hyperswitch_domain_models::router_flow_types::{ webhooks::VerifyWebhookSource, }; pub use hyperswitch_interfaces::api::{ - ConnectorAccessToken, ConnectorAccessTokenV2, ConnectorCommon, ConnectorCommonExt, + ConnectorAccessToken, ConnectorAccessTokenV2, ConnectorAdditionalRevenueRecoveryDetailsCall, + ConnectorAdditionalRevenueRecoveryDetailsCallV2, ConnectorCommon, ConnectorCommonExt, ConnectorMandateRevoke, ConnectorMandateRevokeV2, ConnectorVerifyWebhookSource, - ConnectorVerifyWebhookSourceV2, CurrencyUnit, ConnectorAdditionalRevenueRecoveryDetailsCall,ConnectorAdditionalRevenueRecoveryDetailsCallV2 + ConnectorVerifyWebhookSourceV2, CurrencyUnit, }; use hyperswitch_interfaces::api::{UnifiedAuthenticationService, UnifiedAuthenticationServiceV2}; @@ -129,8 +130,7 @@ impl< + ExternalAuthentication + TaxCalculation + UnifiedAuthenticationService - + ConnectorAdditionalRevenueRecoveryDetailsCall - + + ConnectorAdditionalRevenueRecoveryDetailsCall, > Connector for T { } @@ -170,7 +170,7 @@ impl< + ConnectorMandateRevokeV2 + ExternalAuthenticationV2 + UnifiedAuthenticationServiceV2 - +ConnectorAdditionalRevenueRecoveryDetailsCallV2, + + ConnectorAdditionalRevenueRecoveryDetailsCallV2, > ConnectorV2 for T { } From 0d5a8ea826171ab7399c533085a330d9b4aa047e Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Mon, 3 Mar 2025 14:46:46 +0530 Subject: [PATCH 11/83] changes in name of the flow in config files --- config/config.example.toml | 2 +- config/development.toml | 2 +- config/docker_compose.toml | 2 +- crates/router/src/configs/secrets_transformers.rs | 2 +- crates/router/src/configs/settings.rs | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/config/config.example.toml b/config/config.example.toml index 7c79974b79e..8497223ae44 100644 --- a/config/config.example.toml +++ b/config/config.example.toml @@ -834,5 +834,5 @@ foreground_color = "#000000" # Foreground color of email tex primary_color = "#006DF9" # Primary color of email body background_color = "#FFFFFF" # Background color of email body -[additonal_recovery_details_call] +[additonal_revenue_recovery_details_call] connectors_with_additional_revenue_recovery_details_call = "" # List of connectors which has additional revenue recovery details api-call \ No newline at end of file diff --git a/config/development.toml b/config/development.toml index 03b7da9fee6..62beec7ef49 100644 --- a/config/development.toml +++ b/config/development.toml @@ -681,7 +681,7 @@ connectors_with_delayed_session_response = "trustpay,payme" [webhook_source_verification_call] connectors_with_webhook_source_verification_call = "paypal" -[additonal_recovery_details_call] +[additonal_revenue_recovery_details_call] connectors_with_additional_revenue_recovery_details_call = "" [mandates.supported_payment_methods] diff --git a/config/docker_compose.toml b/config/docker_compose.toml index 38f1f6f5ee4..5edec7170c7 100644 --- a/config/docker_compose.toml +++ b/config/docker_compose.toml @@ -314,7 +314,7 @@ connectors_with_delayed_session_response = "trustpay,payme" [webhook_source_verification_call] connectors_with_webhook_source_verification_call = "paypal" -[additonal_recovery_details_call] +[additonal_revenue_recovery_details_call] connectors_with_additional_revenue_recovery_details_call = "" [scheduler] diff --git a/crates/router/src/configs/secrets_transformers.rs b/crates/router/src/configs/secrets_transformers.rs index 7c006e0e358..f4f2e2d3eb9 100644 --- a/crates/router/src/configs/secrets_transformers.rs +++ b/crates/router/src/configs/secrets_transformers.rs @@ -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, - additonal_recovery_details_call: conf.additonal_recovery_details_call, + additonal_revenue_recovery_details_call : conf.additonal_revenue_recovery_details_call, payment_method_auth, connector_request_reference_id_config: conf.connector_request_reference_id_config, #[cfg(feature = "payouts")] diff --git a/crates/router/src/configs/settings.rs b/crates/router/src/configs/settings.rs index 91dec21af79..966a6418bd9 100644 --- a/crates/router/src/configs/settings.rs +++ b/crates/router/src/configs/settings.rs @@ -96,7 +96,7 @@ pub struct Settings { pub required_fields: RequiredFields, pub delayed_session_response: DelayedSessionConfig, pub webhook_source_verification_call: WebhookSourceVerificationCall, - pub additonal_recovery_details_call: GetAdditionalRecoveryDetailsCall, + pub additonal_revenue_recovery_details_call : GetAdditionalRevenueRecoveryDetailsCall, pub payment_method_auth: SecretStateContainer, pub connector_request_reference_id_config: ConnectorRequestReferenceIdConfig, #[cfg(feature = "payouts")] @@ -849,7 +849,7 @@ pub struct WebhookSourceVerificationCall { } #[derive(Debug, Deserialize, Clone, Default)] -pub struct GetAdditionalRecoveryDetailsCall { +pub struct GetAdditionalRevenueRecoveryDetailsCall{ #[serde(deserialize_with = "deserialize_hashset")] pub connectors_with_additional_revenue_recovery_details_call: HashSet, } From 1ad246418a5c1d268e8a8817ca906226aca49049 Mon Sep 17 00:00:00 2001 From: "hyperswitch-bot[bot]" <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Date: Mon, 3 Mar 2025 09:34:49 +0000 Subject: [PATCH 12/83] chore: run formatter --- crates/router/src/configs/secrets_transformers.rs | 2 +- crates/router/src/configs/settings.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/router/src/configs/secrets_transformers.rs b/crates/router/src/configs/secrets_transformers.rs index f4f2e2d3eb9..dcb9fe45cfe 100644 --- a/crates/router/src/configs/secrets_transformers.rs +++ b/crates/router/src/configs/secrets_transformers.rs @@ -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, - additonal_revenue_recovery_details_call : conf.additonal_revenue_recovery_details_call, + additonal_revenue_recovery_details_call: conf.additonal_revenue_recovery_details_call, payment_method_auth, connector_request_reference_id_config: conf.connector_request_reference_id_config, #[cfg(feature = "payouts")] diff --git a/crates/router/src/configs/settings.rs b/crates/router/src/configs/settings.rs index 966a6418bd9..c2d70aec1ce 100644 --- a/crates/router/src/configs/settings.rs +++ b/crates/router/src/configs/settings.rs @@ -96,7 +96,7 @@ pub struct Settings { pub required_fields: RequiredFields, pub delayed_session_response: DelayedSessionConfig, pub webhook_source_verification_call: WebhookSourceVerificationCall, - pub additonal_revenue_recovery_details_call : GetAdditionalRevenueRecoveryDetailsCall, + pub additonal_revenue_recovery_details_call: GetAdditionalRevenueRecoveryDetailsCall, pub payment_method_auth: SecretStateContainer, pub connector_request_reference_id_config: ConnectorRequestReferenceIdConfig, #[cfg(feature = "payouts")] @@ -849,7 +849,7 @@ pub struct WebhookSourceVerificationCall { } #[derive(Debug, Deserialize, Clone, Default)] -pub struct GetAdditionalRevenueRecoveryDetailsCall{ +pub struct GetAdditionalRevenueRecoveryDetailsCall { #[serde(deserialize_with = "deserialize_hashset")] pub connectors_with_additional_revenue_recovery_details_call: HashSet, } From 24dd8cf7efc708cd417bdcf53a979e9cfe195a3b Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Mon, 3 Mar 2025 15:35:37 +0530 Subject: [PATCH 13/83] cargo.toml changes in par with main --- crates/hyperswitch_connectors/Cargo.toml | 1 + crates/router/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/hyperswitch_connectors/Cargo.toml b/crates/hyperswitch_connectors/Cargo.toml index 915b87a9189..f69a38577b4 100644 --- a/crates/hyperswitch_connectors/Cargo.toml +++ b/crates/hyperswitch_connectors/Cargo.toml @@ -10,6 +10,7 @@ frm = ["hyperswitch_domain_models/frm", "hyperswitch_interfaces/frm"] payouts = ["hyperswitch_domain_models/payouts", "api_models/payouts", "hyperswitch_interfaces/payouts"] v1 = ["api_models/v1", "hyperswitch_domain_models/v1", "common_utils/v1"] v2 = ["api_models/v2", "hyperswitch_domain_models/v2", "common_utils/v2"] +revenue_recovery = [] [dependencies] actix-http = "3.6.0" diff --git a/crates/router/Cargo.toml b/crates/router/Cargo.toml index 8197670acf3..287dd3e347d 100644 --- a/crates/router/Cargo.toml +++ b/crates/router/Cargo.toml @@ -38,7 +38,7 @@ v1 = ["common_default", "api_models/v1", "diesel_models/v1", "hyperswitch_domain customer_v2 = ["api_models/customer_v2", "diesel_models/customer_v2", "hyperswitch_domain_models/customer_v2", "storage_impl/customer_v2"] payment_methods_v2 = ["api_models/payment_methods_v2", "diesel_models/payment_methods_v2", "hyperswitch_domain_models/payment_methods_v2", "storage_impl/payment_methods_v2", "common_utils/payment_methods_v2"] dynamic_routing = ["external_services/dynamic_routing", "storage_impl/dynamic_routing", "api_models/dynamic_routing"] -revenue_recovery =["api_models/revenue_recovery","hyperswitch_interfaces/revenue_recovery","hyperswitch_domain_models/revenue_recovery"] +revenue_recovery =["api_models/revenue_recovery","hyperswitch_interfaces/revenue_recovery","hyperswitch_domain_models/revenue_recovery","hyperswitch_connectors/revenue_recovery"] # Partial Auth # The feature reduces the overhead of the router authenticating the merchant for every request, and trusts on `x-merchant-id` header to be present in the request. From 966ce1b4a82eeef8357b75d253c9bbe9dc5b4036 Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Mon, 3 Mar 2025 15:47:48 +0530 Subject: [PATCH 14/83] add paystack in deafult implememtation additional call flow --- crates/router/src/core/payments/flows.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/router/src/core/payments/flows.rs b/crates/router/src/core/payments/flows.rs index b8a60b8b88e..761b31e8331 100644 --- a/crates/router/src/core/payments/flows.rs +++ b/crates/router/src/core/payments/flows.rs @@ -2541,6 +2541,7 @@ default_imp_for_additional_revenue_recovery_call!( connector::Payme, connector::Payone, connector::Paypal, + connector::Paystack, connector::Plaid, connector::Riskified, connector::Signifyd, From 4a34e07bf19c34287e91dfb0138d3b68c767d6ce Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Mon, 3 Mar 2025 17:27:15 +0530 Subject: [PATCH 15/83] added paystack connector in default implementation --- crates/hyperswitch_connectors/src/default_implementations.rs | 1 + crates/router/src/core/payments/flows.rs | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/hyperswitch_connectors/src/default_implementations.rs b/crates/hyperswitch_connectors/src/default_implementations.rs index dc0646fa7af..b5ac46213fe 100644 --- a/crates/hyperswitch_connectors/src/default_implementations.rs +++ b/crates/hyperswitch_connectors/src/default_implementations.rs @@ -3319,6 +3319,7 @@ default_imp_for_additional_revenue_recovery_call!( connectors::Multisafepay, connectors::Paybox, connectors::Placetopay, + connectors::Paystack, connectors::Rapyd, connectors::Razorpay, connectors::Redsys, diff --git a/crates/router/src/core/payments/flows.rs b/crates/router/src/core/payments/flows.rs index 761b31e8331..b8a60b8b88e 100644 --- a/crates/router/src/core/payments/flows.rs +++ b/crates/router/src/core/payments/flows.rs @@ -2541,7 +2541,6 @@ default_imp_for_additional_revenue_recovery_call!( connector::Payme, connector::Payone, connector::Paypal, - connector::Paystack, connector::Plaid, connector::Riskified, connector::Signifyd, From e10b589a9d53e11e8019147391be7737d4408cfb Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Mon, 3 Mar 2025 17:34:35 +0530 Subject: [PATCH 16/83] add debug and clone trait to Additional Revenue Recovery Flow Common Data --- .../src/router_data_v2/flow_common_types.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/hyperswitch_domain_models/src/router_data_v2/flow_common_types.rs b/crates/hyperswitch_domain_models/src/router_data_v2/flow_common_types.rs index 209472b79a2..2134dc03a44 100644 --- a/crates/hyperswitch_domain_models/src/router_data_v2/flow_common_types.rs +++ b/crates/hyperswitch_domain_models/src/router_data_v2/flow_common_types.rs @@ -150,4 +150,6 @@ pub struct UasFlowData { pub source_authentication_id: String, } + +#[derive(Debug, Clone)] pub struct AdditionalRevenueRecoveryCallFlowCommonData; From 145a6d9896eef2e0996f12da52a34bc37728690f Mon Sep 17 00:00:00 2001 From: "hyperswitch-bot[bot]" <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Date: Mon, 3 Mar 2025 12:05:51 +0000 Subject: [PATCH 17/83] chore: run formatter --- .../src/router_data_v2/flow_common_types.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/hyperswitch_domain_models/src/router_data_v2/flow_common_types.rs b/crates/hyperswitch_domain_models/src/router_data_v2/flow_common_types.rs index 2134dc03a44..f46b0036a3c 100644 --- a/crates/hyperswitch_domain_models/src/router_data_v2/flow_common_types.rs +++ b/crates/hyperswitch_domain_models/src/router_data_v2/flow_common_types.rs @@ -150,6 +150,5 @@ pub struct UasFlowData { pub source_authentication_id: String, } - #[derive(Debug, Clone)] pub struct AdditionalRevenueRecoveryCallFlowCommonData; From 2cc26beafdabea5d6b2a3dfc6b3d6736f513faa1 Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Mon, 3 Mar 2025 18:06:30 +0530 Subject: [PATCH 18/83] resolve spell check --- config/config.example.toml | 2 +- config/development.toml | 2 +- config/docker_compose.toml | 2 +- crates/router/src/configs/secrets_transformers.rs | 2 +- crates/router/src/configs/settings.rs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/config/config.example.toml b/config/config.example.toml index fbfdc4886dd..0168c1e6a93 100644 --- a/config/config.example.toml +++ b/config/config.example.toml @@ -883,5 +883,5 @@ foreground_color = "#000000" # Foreground color of email tex primary_color = "#006DF9" # Primary color of email body background_color = "#FFFFFF" # Background color of email body -[additonal_revenue_recovery_details_call] +[additional_revenue_recovery_details_call] connectors_with_additional_revenue_recovery_details_call = "" # List of connectors which has additional revenue recovery details api-call \ No newline at end of file diff --git a/config/development.toml b/config/development.toml index 062b8631d2d..ed589fab427 100644 --- a/config/development.toml +++ b/config/development.toml @@ -723,7 +723,7 @@ connectors_with_delayed_session_response = "trustpay,payme" [webhook_source_verification_call] connectors_with_webhook_source_verification_call = "paypal" -[additonal_revenue_recovery_details_call] +[additional_revenue_recovery_details_call] connectors_with_additional_revenue_recovery_details_call = "" [mandates.supported_payment_methods] diff --git a/config/docker_compose.toml b/config/docker_compose.toml index e0494f1c474..d7f0174e885 100644 --- a/config/docker_compose.toml +++ b/config/docker_compose.toml @@ -315,7 +315,7 @@ connectors_with_delayed_session_response = "trustpay,payme" [webhook_source_verification_call] connectors_with_webhook_source_verification_call = "paypal" -[additonal_revenue_recovery_details_call] +[additional_revenue_recovery_details_call] connectors_with_additional_revenue_recovery_details_call = "" [scheduler] diff --git a/crates/router/src/configs/secrets_transformers.rs b/crates/router/src/configs/secrets_transformers.rs index dcb9fe45cfe..8904322d1be 100644 --- a/crates/router/src/configs/secrets_transformers.rs +++ b/crates/router/src/configs/secrets_transformers.rs @@ -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, - additonal_revenue_recovery_details_call: conf.additonal_revenue_recovery_details_call, + additional_revenue_recovery_details_call: conf.additional_revenue_recovery_details_call, payment_method_auth, connector_request_reference_id_config: conf.connector_request_reference_id_config, #[cfg(feature = "payouts")] diff --git a/crates/router/src/configs/settings.rs b/crates/router/src/configs/settings.rs index c2d70aec1ce..6234f45851f 100644 --- a/crates/router/src/configs/settings.rs +++ b/crates/router/src/configs/settings.rs @@ -96,7 +96,7 @@ pub struct Settings { pub required_fields: RequiredFields, pub delayed_session_response: DelayedSessionConfig, pub webhook_source_verification_call: WebhookSourceVerificationCall, - pub additonal_revenue_recovery_details_call: GetAdditionalRevenueRecoveryDetailsCall, + pub additional_revenue_recovery_details_call: GetAdditionalRevenueRecoveryDetailsCall, pub payment_method_auth: SecretStateContainer, pub connector_request_reference_id_config: ConnectorRequestReferenceIdConfig, #[cfg(feature = "payouts")] From 70a430fb168fdd70e4e616b245f2d077eec3d9d1 Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Mon, 3 Mar 2025 18:50:16 +0530 Subject: [PATCH 19/83] add stripebilling in configs --- config/config.example.toml | 2 +- config/development.toml | 2 +- config/docker_compose.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/config/config.example.toml b/config/config.example.toml index 0168c1e6a93..49f305a65a5 100644 --- a/config/config.example.toml +++ b/config/config.example.toml @@ -884,4 +884,4 @@ primary_color = "#006DF9" # Primary color of email body background_color = "#FFFFFF" # Background color of email body [additional_revenue_recovery_details_call] -connectors_with_additional_revenue_recovery_details_call = "" # List of connectors which has additional revenue recovery details api-call \ No newline at end of file +connectors_with_additional_revenue_recovery_details_call = "stripebilling" # List of connectors which has additional revenue recovery details api-call \ No newline at end of file diff --git a/config/development.toml b/config/development.toml index ed589fab427..0f51bf30170 100644 --- a/config/development.toml +++ b/config/development.toml @@ -724,7 +724,7 @@ connectors_with_delayed_session_response = "trustpay,payme" connectors_with_webhook_source_verification_call = "paypal" [additional_revenue_recovery_details_call] -connectors_with_additional_revenue_recovery_details_call = "" +connectors_with_additional_revenue_recovery_details_call = "stripebilling" [mandates.supported_payment_methods] bank_debit.ach = { connector_list = "gocardless,adyen,stripe" } diff --git a/config/docker_compose.toml b/config/docker_compose.toml index d7f0174e885..1986f25517f 100644 --- a/config/docker_compose.toml +++ b/config/docker_compose.toml @@ -316,7 +316,7 @@ connectors_with_delayed_session_response = "trustpay,payme" connectors_with_webhook_source_verification_call = "paypal" [additional_revenue_recovery_details_call] -connectors_with_additional_revenue_recovery_details_call = "" +connectors_with_additional_revenue_recovery_details_call = "stripebilling" [scheduler] stream = "SCHEDULER_STREAM" From c9ae685a02654ab3c84b5cf102eb50e13006b98a Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Tue, 4 Mar 2025 11:32:40 +0530 Subject: [PATCH 20/83] refactor: rename Additional Revenue Recovery related types and traits --- .../src/default_implementations.rs | 10 ++++---- .../src/router_data_v2/flow_common_types.rs | 2 +- .../src/router_request_types.rs | 2 +- .../src/router_response_types.rs | 2 +- crates/hyperswitch_domain_models/src/types.rs | 8 +++---- crates/hyperswitch_interfaces/src/api.rs | 24 +++++++++---------- crates/hyperswitch_interfaces/src/types.rs | 10 ++++---- .../src/configs/secrets_transformers.rs | 2 +- crates/router/src/configs/settings.rs | 2 +- crates/router/src/core/payments/flows.rs | 12 +++++----- crates/router/src/services/api.rs | 2 +- crates/router/src/types.rs | 4 ++-- crates/router/src/types/api.rs | 12 +++++----- 13 files changed, 46 insertions(+), 46 deletions(-) diff --git a/crates/hyperswitch_connectors/src/default_implementations.rs b/crates/hyperswitch_connectors/src/default_implementations.rs index b5ac46213fe..b3bbb3307a8 100644 --- a/crates/hyperswitch_connectors/src/default_implementations.rs +++ b/crates/hyperswitch_connectors/src/default_implementations.rs @@ -42,7 +42,7 @@ use hyperswitch_domain_models::{ UasConfirmationRequestData, UasPostAuthenticationRequestData, UasPreAuthenticationRequestData, }, - AcceptDisputeRequestData, AdditionalRevenueRecoveryDetailsRequestData, + AcceptDisputeRequestData, GetAdditionalRevenueRecoveryRequestData, AuthorizeSessionTokenData, CompleteAuthorizeData, ConnectorCustomerData, DefendDisputeRequestData, MandateRevokeRequestData, PaymentsApproveData, PaymentsIncrementalAuthorizationData, PaymentsPostProcessingData, @@ -51,7 +51,7 @@ use hyperswitch_domain_models::{ SubmitEvidenceRequestData, UploadFileRequestData, VerifyWebhookSourceRequestData, }, router_response_types::{ - AcceptDisputeResponse, AdditionalRevenueRecoveryDetailsResponseData, DefendDisputeResponse, + AcceptDisputeResponse, GetAdditionalRevenueRecoveryResponseData, DefendDisputeResponse, MandateRevokeResponseData, PaymentsResponseData, RetrieveFileResponse, SubmitEvidenceResponse, TaxCalculationResponseData, UploadFileResponse, VerifyWebhookSourceResponseData, @@ -3254,12 +3254,12 @@ default_imp_for_uas_authentication_confirmation!( macro_rules! default_imp_for_additional_revenue_recovery_call { ($($path:ident::$connector:ident),*) => { - $( impl api::ConnectorAdditionalRevenueRecoveryDetailsCall for $path::$connector {} + $( impl api::AdditionalRevenueRecovery for $path::$connector {} impl ConnectorIntegration< GetAdditionalRevenueRecoveryDetails, - AdditionalRevenueRecoveryDetailsRequestData, - AdditionalRevenueRecoveryDetailsResponseData + GetAdditionalRevenueRecoveryRequestData, + GetAdditionalRevenueRecoveryResponseData > for $path::$connector {} )* diff --git a/crates/hyperswitch_domain_models/src/router_data_v2/flow_common_types.rs b/crates/hyperswitch_domain_models/src/router_data_v2/flow_common_types.rs index f46b0036a3c..40d0b5557cc 100644 --- a/crates/hyperswitch_domain_models/src/router_data_v2/flow_common_types.rs +++ b/crates/hyperswitch_domain_models/src/router_data_v2/flow_common_types.rs @@ -151,4 +151,4 @@ pub struct UasFlowData { } #[derive(Debug, Clone)] -pub struct AdditionalRevenueRecoveryCallFlowCommonData; +pub struct GetAdditionalRevenueRecoveryFlowCommonData; diff --git a/crates/hyperswitch_domain_models/src/router_request_types.rs b/crates/hyperswitch_domain_models/src/router_request_types.rs index 9d60519c241..2a0f7675b7d 100644 --- a/crates/hyperswitch_domain_models/src/router_request_types.rs +++ b/crates/hyperswitch_domain_models/src/router_request_types.rs @@ -915,6 +915,6 @@ pub struct SetupMandateRequestData { } #[derive(Debug, Clone)] -pub struct AdditionalRevenueRecoveryDetailsRequestData { +pub struct GetAdditionalRevenueRecoveryRequestData { pub transaction_id: String, } diff --git a/crates/hyperswitch_domain_models/src/router_response_types.rs b/crates/hyperswitch_domain_models/src/router_response_types.rs index 2df88ea9cc0..b35f2d89163 100644 --- a/crates/hyperswitch_domain_models/src/router_response_types.rs +++ b/crates/hyperswitch_domain_models/src/router_response_types.rs @@ -606,7 +606,7 @@ impl SupportedPaymentMethodsExt for SupportedPaymentMethods { } #[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] -pub struct AdditionalRevenueRecoveryDetailsResponseData { +pub struct GetAdditionalRevenueRecoveryResponseData { /// transaction amount against invoice, accepted in minor unit. pub amount: MinorUnit, /// currency of the transaction diff --git a/crates/hyperswitch_domain_models/src/types.rs b/crates/hyperswitch_domain_models/src/types.rs index 2e73f696566..6920d2b78d4 100644 --- a/crates/hyperswitch_domain_models/src/types.rs +++ b/crates/hyperswitch_domain_models/src/types.rs @@ -15,7 +15,7 @@ use crate::{ UasConfirmationRequestData, UasPostAuthenticationRequestData, UasPreAuthenticationRequestData, }, - AccessTokenRequestData, AdditionalRevenueRecoveryDetailsRequestData, + AccessTokenRequestData, GetAdditionalRevenueRecoveryRequestData, AuthorizeSessionTokenData, CompleteAuthorizeData, ConnectorCustomerData, MandateRevokeRequestData, PaymentMethodTokenizationData, PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, PaymentsIncrementalAuthorizationData, @@ -23,7 +23,7 @@ use crate::{ PaymentsSyncData, PaymentsTaxCalculationData, RefundsData, SetupMandateRequestData, }, router_response_types::{ - AdditionalRevenueRecoveryDetailsResponseData, MandateRevokeResponseData, + GetAdditionalRevenueRecoveryResponseData, MandateRevokeResponseData, PaymentsResponseData, RefundsResponseData, TaxCalculationResponseData, }, }; @@ -84,6 +84,6 @@ pub type UasAuthenticationRouterData = pub type AdditionalRevenueRecoveryDetailsRouterData = RouterData< GetAdditionalRevenueRecoveryDetails, - AdditionalRevenueRecoveryDetailsRequestData, - AdditionalRevenueRecoveryDetailsResponseData, + GetAdditionalRevenueRecoveryRequestData, + GetAdditionalRevenueRecoveryResponseData, >; diff --git a/crates/hyperswitch_interfaces/src/api.rs b/crates/hyperswitch_interfaces/src/api.rs index a0c159ea637..904ad41ae7e 100644 --- a/crates/hyperswitch_interfaces/src/api.rs +++ b/crates/hyperswitch_interfaces/src/api.rs @@ -30,7 +30,7 @@ use hyperswitch_domain_models::{ payment_method_data::PaymentMethodData, router_data::{AccessToken, ConnectorAuthType, ErrorResponse, RouterData}, router_data_v2::{ - flow_common_types::{AdditionalRevenueRecoveryCallFlowCommonData, WebhookSourceVerifyData}, + flow_common_types::{GetAdditionalRevenueRecoveryFlowCommonData, WebhookSourceVerifyData}, AccessTokenFlowData, MandateRevokeFlowData, UasFlowData, }, router_flow_types::{ @@ -44,11 +44,11 @@ use hyperswitch_domain_models::{ UasConfirmationRequestData, UasPostAuthenticationRequestData, UasPreAuthenticationRequestData, }, - AccessTokenRequestData, AdditionalRevenueRecoveryDetailsRequestData, + AccessTokenRequestData, GetAdditionalRevenueRecoveryRequestData, MandateRevokeRequestData, VerifyWebhookSourceRequestData, }, router_response_types::{ - AdditionalRevenueRecoveryDetailsResponseData, ConnectorInfo, MandateRevokeResponseData, + GetAdditionalRevenueRecoveryResponseData, ConnectorInfo, MandateRevokeResponseData, PaymentMethodDetails, SupportedPaymentMethods, VerifyWebhookSourceResponseData, }, }; @@ -372,23 +372,23 @@ pub trait ConnectorVerifyWebhookSourceV2: { } -/// trait ConnectorAdditionalRevenueRecoveryDetailsCall -pub trait ConnectorAdditionalRevenueRecoveryDetailsCall: +/// trait AdditionalRevenueRecovery +pub trait AdditionalRevenueRecovery: ConnectorIntegration< GetAdditionalRevenueRecoveryDetails, - AdditionalRevenueRecoveryDetailsRequestData, - AdditionalRevenueRecoveryDetailsResponseData, + GetAdditionalRevenueRecoveryRequestData, + GetAdditionalRevenueRecoveryResponseData, > { } -/// trait ConnectorAdditionalRevenueRecoveryDetailsCallV2 -pub trait ConnectorAdditionalRevenueRecoveryDetailsCallV2: +/// trait AdditionalRevenueRecoveryV2 +pub trait AdditionalRevenueRecoveryV2: ConnectorIntegrationV2< GetAdditionalRevenueRecoveryDetails, - AdditionalRevenueRecoveryCallFlowCommonData, - AdditionalRevenueRecoveryDetailsRequestData, - AdditionalRevenueRecoveryDetailsResponseData, + GetAdditionalRevenueRecoveryFlowCommonData, + GetAdditionalRevenueRecoveryRequestData, + GetAdditionalRevenueRecoveryResponseData, > { } diff --git a/crates/hyperswitch_interfaces/src/types.rs b/crates/hyperswitch_interfaces/src/types.rs index 75d075e8c39..4a8dab63d9d 100644 --- a/crates/hyperswitch_interfaces/src/types.rs +++ b/crates/hyperswitch_interfaces/src/types.rs @@ -26,7 +26,7 @@ use hyperswitch_domain_models::{ UasPreAuthenticationRequestData, }, AcceptDisputeRequestData, AccessTokenRequestData, - AdditionalRevenueRecoveryDetailsRequestData, AuthorizeSessionTokenData, + GetAdditionalRevenueRecoveryRequestData, AuthorizeSessionTokenData, CompleteAuthorizeData, ConnectorCustomerData, DefendDisputeRequestData, MandateRevokeRequestData, PaymentMethodTokenizationData, PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, PaymentsIncrementalAuthorizationData, @@ -36,7 +36,7 @@ use hyperswitch_domain_models::{ SubmitEvidenceRequestData, UploadFileRequestData, VerifyWebhookSourceRequestData, }, router_response_types::{ - AcceptDisputeResponse, AdditionalRevenueRecoveryDetailsResponseData, DefendDisputeResponse, + AcceptDisputeResponse, GetAdditionalRevenueRecoveryResponseData, DefendDisputeResponse, MandateRevokeResponseData, PaymentsResponseData, RefundsResponseData, RetrieveFileResponse, SubmitEvidenceResponse, TaxCalculationResponseData, UploadFileResponse, VerifyWebhookSourceResponseData, @@ -225,9 +225,9 @@ pub type UasAuthenticationType = dyn ConnectorIntegration< UasAuthenticationResponseData, >; -///Type alias for `ConnectorIntegration` +/// Type alias for `ConnectorIntegration` pub type AdditionalRevenueRecoveryCallType = dyn ConnectorIntegration< GetAdditionalRevenueRecoveryDetails, - AdditionalRevenueRecoveryDetailsRequestData, - AdditionalRevenueRecoveryDetailsResponseData, + GetAdditionalRevenueRecoveryRequestData, + GetAdditionalRevenueRecoveryResponseData, >; diff --git a/crates/router/src/configs/secrets_transformers.rs b/crates/router/src/configs/secrets_transformers.rs index 8904322d1be..2c28e6f1402 100644 --- a/crates/router/src/configs/secrets_transformers.rs +++ b/crates/router/src/configs/secrets_transformers.rs @@ -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, + // additional_revenue_recovery_details_call: conf.additional_revenue_recovery_details_call, payment_method_auth, connector_request_reference_id_config: conf.connector_request_reference_id_config, #[cfg(feature = "payouts")] diff --git a/crates/router/src/configs/settings.rs b/crates/router/src/configs/settings.rs index 6234f45851f..605b4b576f3 100644 --- a/crates/router/src/configs/settings.rs +++ b/crates/router/src/configs/settings.rs @@ -96,7 +96,7 @@ pub struct Settings { pub required_fields: RequiredFields, pub delayed_session_response: DelayedSessionConfig, pub webhook_source_verification_call: WebhookSourceVerificationCall, - pub additional_revenue_recovery_details_call: GetAdditionalRevenueRecoveryDetailsCall, + // pub additional_revenue_recovery_details_call: GetAdditionalRevenueRecoveryDetailsCall, pub payment_method_auth: SecretStateContainer, pub connector_request_reference_id_config: ConnectorRequestReferenceIdConfig, #[cfg(feature = "payouts")] diff --git a/crates/router/src/core/payments/flows.rs b/crates/router/src/core/payments/flows.rs index b8a60b8b88e..6238148f7da 100644 --- a/crates/router/src/core/payments/flows.rs +++ b/crates/router/src/core/payments/flows.rs @@ -2499,12 +2499,12 @@ fn handle_post_capture_response( macro_rules! default_imp_for_additional_revenue_recovery_call { ($($path:ident::$connector:ident),*) => { - $( impl api::ConnectorAdditionalRevenueRecoveryDetailsCall for $path::$connector {} + $( impl api::AdditionalRevenueRecovery for $path::$connector {} impl services::ConnectorIntegration< GetAdditionalRevenueRecoveryDetails, - types::AdditionalRevenueRecoveryDetailsRequestData, - types::AdditionalRevenueRecoveryDetailsResponseData, + types::GetAdditionalRevenueRecoveryRequestData, + types::GetAdditionalRevenueRecoveryResponseData, > for $path::$connector {} )* @@ -2512,7 +2512,7 @@ macro_rules! default_imp_for_additional_revenue_recovery_call { } #[cfg(feature = "dummy_connector")] -impl api::ConnectorAdditionalRevenueRecoveryDetailsCall +impl api::AdditionalRevenueRecovery for connector::DummyConnector { } @@ -2520,8 +2520,8 @@ impl api::ConnectorAdditionalRevenueRecoveryDetailsCall impl services::ConnectorIntegration< GetAdditionalRevenueRecoveryDetails, - types::AdditionalRevenueRecoveryDetailsRequestData, - types::AdditionalRevenueRecoveryDetailsResponseData, + types::GetAdditionalRevenueRecoveryRequestData, + types::GetAdditionalRevenueRecoveryResponseData, > for connector::DummyConnector { } diff --git a/crates/router/src/services/api.rs b/crates/router/src/services/api.rs index cf7a0aa85c0..c59c5e84b41 100644 --- a/crates/router/src/services/api.rs +++ b/crates/router/src/services/api.rs @@ -111,7 +111,7 @@ pub type BoxedUnifiedAuthenticationServiceInterface = pub type BoxedGetAdditionalRecoveryRecoveryDetailsIntegrationInterface = BoxedConnectorIntegrationInterface< T, - common_types::AdditionalRevenueRecoveryCallFlowCommonData, + common_types::GetAdditionalRevenueRecoveryFlowCommonData, Req, Res, >; diff --git a/crates/router/src/types.rs b/crates/router/src/types.rs index 11242119cba..989d7db2d3a 100644 --- a/crates/router/src/types.rs +++ b/crates/router/src/types.rs @@ -63,7 +63,7 @@ pub use hyperswitch_domain_models::{ UasPreAuthenticationRequestData, }, AcceptDisputeRequestData, AccessTokenRequestData, - AdditionalRevenueRecoveryDetailsRequestData, AuthorizeSessionTokenData, BrowserInformation, + GetAdditionalRevenueRecoveryRequestData, AuthorizeSessionTokenData, BrowserInformation, ChargeRefunds, ChargeRefundsOptions, CompleteAuthorizeData, CompleteAuthorizeRedirectResponse, ConnectorCustomerData, DefendDisputeRequestData, DestinationChargeRefund, DirectChargeRefund, MandateRevokeRequestData, @@ -77,7 +77,7 @@ pub use hyperswitch_domain_models::{ VerifyWebhookSourceRequestData, }, router_response_types::{ - AcceptDisputeResponse, AdditionalRevenueRecoveryDetailsResponseData, CaptureSyncResponse, + AcceptDisputeResponse, GetAdditionalRevenueRecoveryResponseData, CaptureSyncResponse, DefendDisputeResponse, MandateReference, MandateRevokeResponseData, PaymentsResponseData, PreprocessingResponseId, RefundsResponseData, RetrieveFileResponse, SubmitEvidenceResponse, TaxCalculationResponseData, UploadFileResponse, VerifyWebhookSourceResponseData, diff --git a/crates/router/src/types/api.rs b/crates/router/src/types/api.rs index 1ab81c001df..a0ee97c18bb 100644 --- a/crates/router/src/types/api.rs +++ b/crates/router/src/types/api.rs @@ -46,8 +46,8 @@ pub use hyperswitch_domain_models::router_flow_types::{ webhooks::VerifyWebhookSource, }; pub use hyperswitch_interfaces::api::{ - ConnectorAccessToken, ConnectorAccessTokenV2, ConnectorAdditionalRevenueRecoveryDetailsCall, - ConnectorAdditionalRevenueRecoveryDetailsCallV2, ConnectorCommon, ConnectorCommonExt, + ConnectorAccessToken, ConnectorAccessTokenV2, AdditionalRevenueRecovery, + AdditionalRevenueRecoveryV2, ConnectorCommon, ConnectorCommonExt, ConnectorMandateRevoke, ConnectorMandateRevokeV2, ConnectorVerifyWebhookSource, ConnectorVerifyWebhookSourceV2, CurrencyUnit, }; @@ -109,7 +109,7 @@ pub trait Connector: + ExternalAuthentication + TaxCalculation + UnifiedAuthenticationService - + ConnectorAdditionalRevenueRecoveryDetailsCall + + AdditionalRevenueRecovery { } @@ -130,7 +130,7 @@ impl< + ExternalAuthentication + TaxCalculation + UnifiedAuthenticationService - + ConnectorAdditionalRevenueRecoveryDetailsCall, + + AdditionalRevenueRecovery, > Connector for T { } @@ -151,7 +151,7 @@ pub trait ConnectorV2: + ConnectorMandateRevokeV2 + ExternalAuthenticationV2 + UnifiedAuthenticationServiceV2 - + ConnectorAdditionalRevenueRecoveryDetailsCallV2 + + AdditionalRevenueRecoveryV2 { } impl< @@ -170,7 +170,7 @@ impl< + ConnectorMandateRevokeV2 + ExternalAuthenticationV2 + UnifiedAuthenticationServiceV2 - + ConnectorAdditionalRevenueRecoveryDetailsCallV2, + + AdditionalRevenueRecoveryV2, > ConnectorV2 for T { } From 524cce11daf58703c79c50bc2d042f26e5ed3286 Mon Sep 17 00:00:00 2001 From: "hyperswitch-bot[bot]" <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Date: Tue, 4 Mar 2025 06:33:36 +0000 Subject: [PATCH 21/83] chore: run formatter --- .../src/default_implementations.rs | 16 +++++++------- crates/hyperswitch_domain_models/src/types.rs | 16 +++++++------- crates/hyperswitch_interfaces/src/api.rs | 6 +++--- crates/hyperswitch_interfaces/src/types.rs | 18 ++++++++-------- crates/router/src/core/payments/flows.rs | 5 +---- crates/router/src/types.rs | 21 +++++++++---------- crates/router/src/types/api.rs | 8 +++---- 7 files changed, 43 insertions(+), 47 deletions(-) diff --git a/crates/hyperswitch_connectors/src/default_implementations.rs b/crates/hyperswitch_connectors/src/default_implementations.rs index b3bbb3307a8..a2a42bcc988 100644 --- a/crates/hyperswitch_connectors/src/default_implementations.rs +++ b/crates/hyperswitch_connectors/src/default_implementations.rs @@ -42,16 +42,16 @@ use hyperswitch_domain_models::{ UasConfirmationRequestData, UasPostAuthenticationRequestData, UasPreAuthenticationRequestData, }, - AcceptDisputeRequestData, GetAdditionalRevenueRecoveryRequestData, - AuthorizeSessionTokenData, CompleteAuthorizeData, ConnectorCustomerData, - DefendDisputeRequestData, MandateRevokeRequestData, PaymentsApproveData, - PaymentsIncrementalAuthorizationData, PaymentsPostProcessingData, - PaymentsPostSessionTokensData, PaymentsPreProcessingData, PaymentsRejectData, - PaymentsTaxCalculationData, RetrieveFileRequestData, SdkPaymentsSessionUpdateData, - SubmitEvidenceRequestData, UploadFileRequestData, VerifyWebhookSourceRequestData, + AcceptDisputeRequestData, AuthorizeSessionTokenData, CompleteAuthorizeData, + ConnectorCustomerData, DefendDisputeRequestData, GetAdditionalRevenueRecoveryRequestData, + MandateRevokeRequestData, PaymentsApproveData, PaymentsIncrementalAuthorizationData, + PaymentsPostProcessingData, PaymentsPostSessionTokensData, PaymentsPreProcessingData, + PaymentsRejectData, PaymentsTaxCalculationData, RetrieveFileRequestData, + SdkPaymentsSessionUpdateData, SubmitEvidenceRequestData, UploadFileRequestData, + VerifyWebhookSourceRequestData, }, router_response_types::{ - AcceptDisputeResponse, GetAdditionalRevenueRecoveryResponseData, DefendDisputeResponse, + AcceptDisputeResponse, DefendDisputeResponse, GetAdditionalRevenueRecoveryResponseData, MandateRevokeResponseData, PaymentsResponseData, RetrieveFileResponse, SubmitEvidenceResponse, TaxCalculationResponseData, UploadFileResponse, VerifyWebhookSourceResponseData, diff --git a/crates/hyperswitch_domain_models/src/types.rs b/crates/hyperswitch_domain_models/src/types.rs index 6920d2b78d4..be4d85bf3dc 100644 --- a/crates/hyperswitch_domain_models/src/types.rs +++ b/crates/hyperswitch_domain_models/src/types.rs @@ -15,16 +15,16 @@ use crate::{ UasConfirmationRequestData, UasPostAuthenticationRequestData, UasPreAuthenticationRequestData, }, - AccessTokenRequestData, GetAdditionalRevenueRecoveryRequestData, - AuthorizeSessionTokenData, CompleteAuthorizeData, ConnectorCustomerData, - MandateRevokeRequestData, PaymentMethodTokenizationData, PaymentsAuthorizeData, - PaymentsCancelData, PaymentsCaptureData, PaymentsIncrementalAuthorizationData, - PaymentsPostSessionTokensData, PaymentsPreProcessingData, PaymentsSessionData, - PaymentsSyncData, PaymentsTaxCalculationData, RefundsData, SetupMandateRequestData, + AccessTokenRequestData, AuthorizeSessionTokenData, CompleteAuthorizeData, + ConnectorCustomerData, GetAdditionalRevenueRecoveryRequestData, MandateRevokeRequestData, + PaymentMethodTokenizationData, PaymentsAuthorizeData, PaymentsCancelData, + PaymentsCaptureData, PaymentsIncrementalAuthorizationData, PaymentsPostSessionTokensData, + PaymentsPreProcessingData, PaymentsSessionData, PaymentsSyncData, + PaymentsTaxCalculationData, RefundsData, SetupMandateRequestData, }, router_response_types::{ - GetAdditionalRevenueRecoveryResponseData, MandateRevokeResponseData, - PaymentsResponseData, RefundsResponseData, TaxCalculationResponseData, + GetAdditionalRevenueRecoveryResponseData, MandateRevokeResponseData, PaymentsResponseData, + RefundsResponseData, TaxCalculationResponseData, }, }; #[cfg(feature = "payouts")] diff --git a/crates/hyperswitch_interfaces/src/api.rs b/crates/hyperswitch_interfaces/src/api.rs index 904ad41ae7e..8900f89fbb4 100644 --- a/crates/hyperswitch_interfaces/src/api.rs +++ b/crates/hyperswitch_interfaces/src/api.rs @@ -44,11 +44,11 @@ use hyperswitch_domain_models::{ UasConfirmationRequestData, UasPostAuthenticationRequestData, UasPreAuthenticationRequestData, }, - AccessTokenRequestData, GetAdditionalRevenueRecoveryRequestData, - MandateRevokeRequestData, VerifyWebhookSourceRequestData, + AccessTokenRequestData, GetAdditionalRevenueRecoveryRequestData, MandateRevokeRequestData, + VerifyWebhookSourceRequestData, }, router_response_types::{ - GetAdditionalRevenueRecoveryResponseData, ConnectorInfo, MandateRevokeResponseData, + ConnectorInfo, GetAdditionalRevenueRecoveryResponseData, MandateRevokeResponseData, PaymentMethodDetails, SupportedPaymentMethods, VerifyWebhookSourceResponseData, }, }; diff --git a/crates/hyperswitch_interfaces/src/types.rs b/crates/hyperswitch_interfaces/src/types.rs index 4a8dab63d9d..8b353b3836a 100644 --- a/crates/hyperswitch_interfaces/src/types.rs +++ b/crates/hyperswitch_interfaces/src/types.rs @@ -25,18 +25,18 @@ use hyperswitch_domain_models::{ UasConfirmationRequestData, UasPostAuthenticationRequestData, UasPreAuthenticationRequestData, }, - AcceptDisputeRequestData, AccessTokenRequestData, - GetAdditionalRevenueRecoveryRequestData, AuthorizeSessionTokenData, + AcceptDisputeRequestData, AccessTokenRequestData, AuthorizeSessionTokenData, CompleteAuthorizeData, ConnectorCustomerData, DefendDisputeRequestData, - MandateRevokeRequestData, PaymentMethodTokenizationData, PaymentsAuthorizeData, - PaymentsCancelData, PaymentsCaptureData, PaymentsIncrementalAuthorizationData, - PaymentsPostProcessingData, PaymentsPostSessionTokensData, PaymentsPreProcessingData, - PaymentsSessionData, PaymentsSyncData, PaymentsTaxCalculationData, RefundsData, - RetrieveFileRequestData, SdkPaymentsSessionUpdateData, SetupMandateRequestData, - SubmitEvidenceRequestData, UploadFileRequestData, VerifyWebhookSourceRequestData, + GetAdditionalRevenueRecoveryRequestData, MandateRevokeRequestData, + PaymentMethodTokenizationData, PaymentsAuthorizeData, PaymentsCancelData, + PaymentsCaptureData, PaymentsIncrementalAuthorizationData, PaymentsPostProcessingData, + PaymentsPostSessionTokensData, PaymentsPreProcessingData, PaymentsSessionData, + PaymentsSyncData, PaymentsTaxCalculationData, RefundsData, RetrieveFileRequestData, + SdkPaymentsSessionUpdateData, SetupMandateRequestData, SubmitEvidenceRequestData, + UploadFileRequestData, VerifyWebhookSourceRequestData, }, router_response_types::{ - AcceptDisputeResponse, GetAdditionalRevenueRecoveryResponseData, DefendDisputeResponse, + AcceptDisputeResponse, DefendDisputeResponse, GetAdditionalRevenueRecoveryResponseData, MandateRevokeResponseData, PaymentsResponseData, RefundsResponseData, RetrieveFileResponse, SubmitEvidenceResponse, TaxCalculationResponseData, UploadFileResponse, VerifyWebhookSourceResponseData, diff --git a/crates/router/src/core/payments/flows.rs b/crates/router/src/core/payments/flows.rs index 6238148f7da..2bdceca3409 100644 --- a/crates/router/src/core/payments/flows.rs +++ b/crates/router/src/core/payments/flows.rs @@ -2512,10 +2512,7 @@ macro_rules! default_imp_for_additional_revenue_recovery_call { } #[cfg(feature = "dummy_connector")] -impl api::AdditionalRevenueRecovery - for connector::DummyConnector -{ -} +impl api::AdditionalRevenueRecovery for connector::DummyConnector {} #[cfg(feature = "dummy_connector")] impl services::ConnectorIntegration< diff --git a/crates/router/src/types.rs b/crates/router/src/types.rs index 989d7db2d3a..5786c4404cc 100644 --- a/crates/router/src/types.rs +++ b/crates/router/src/types.rs @@ -62,13 +62,12 @@ pub use hyperswitch_domain_models::{ UasConfirmationRequestData, UasPostAuthenticationRequestData, UasPreAuthenticationRequestData, }, - AcceptDisputeRequestData, AccessTokenRequestData, - GetAdditionalRevenueRecoveryRequestData, AuthorizeSessionTokenData, BrowserInformation, - ChargeRefunds, ChargeRefundsOptions, CompleteAuthorizeData, + AcceptDisputeRequestData, AccessTokenRequestData, AuthorizeSessionTokenData, + BrowserInformation, ChargeRefunds, ChargeRefundsOptions, CompleteAuthorizeData, CompleteAuthorizeRedirectResponse, ConnectorCustomerData, DefendDisputeRequestData, - DestinationChargeRefund, DirectChargeRefund, MandateRevokeRequestData, - MultipleCaptureRequestData, PaymentMethodTokenizationData, PaymentsApproveData, - PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, + DestinationChargeRefund, DirectChargeRefund, GetAdditionalRevenueRecoveryRequestData, + MandateRevokeRequestData, MultipleCaptureRequestData, PaymentMethodTokenizationData, + PaymentsApproveData, PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, PaymentsIncrementalAuthorizationData, PaymentsPostProcessingData, PaymentsPostSessionTokensData, PaymentsPreProcessingData, PaymentsRejectData, PaymentsSessionData, PaymentsSyncData, PaymentsTaxCalculationData, RefundsData, ResponseId, @@ -77,11 +76,11 @@ pub use hyperswitch_domain_models::{ VerifyWebhookSourceRequestData, }, router_response_types::{ - AcceptDisputeResponse, GetAdditionalRevenueRecoveryResponseData, CaptureSyncResponse, - DefendDisputeResponse, MandateReference, MandateRevokeResponseData, PaymentsResponseData, - PreprocessingResponseId, RefundsResponseData, RetrieveFileResponse, SubmitEvidenceResponse, - TaxCalculationResponseData, UploadFileResponse, VerifyWebhookSourceResponseData, - VerifyWebhookStatus, + AcceptDisputeResponse, CaptureSyncResponse, DefendDisputeResponse, + GetAdditionalRevenueRecoveryResponseData, MandateReference, MandateRevokeResponseData, + PaymentsResponseData, PreprocessingResponseId, RefundsResponseData, RetrieveFileResponse, + SubmitEvidenceResponse, TaxCalculationResponseData, UploadFileResponse, + VerifyWebhookSourceResponseData, VerifyWebhookStatus, }, }; #[cfg(feature = "payouts")] diff --git a/crates/router/src/types/api.rs b/crates/router/src/types/api.rs index a0ee97c18bb..a20d7d587ab 100644 --- a/crates/router/src/types/api.rs +++ b/crates/router/src/types/api.rs @@ -46,10 +46,10 @@ pub use hyperswitch_domain_models::router_flow_types::{ webhooks::VerifyWebhookSource, }; pub use hyperswitch_interfaces::api::{ - ConnectorAccessToken, ConnectorAccessTokenV2, AdditionalRevenueRecovery, - AdditionalRevenueRecoveryV2, ConnectorCommon, ConnectorCommonExt, - ConnectorMandateRevoke, ConnectorMandateRevokeV2, ConnectorVerifyWebhookSource, - ConnectorVerifyWebhookSourceV2, CurrencyUnit, + AdditionalRevenueRecovery, AdditionalRevenueRecoveryV2, ConnectorAccessToken, + ConnectorAccessTokenV2, ConnectorCommon, ConnectorCommonExt, ConnectorMandateRevoke, + ConnectorMandateRevokeV2, ConnectorVerifyWebhookSource, ConnectorVerifyWebhookSourceV2, + CurrencyUnit, }; use hyperswitch_interfaces::api::{UnifiedAuthenticationService, UnifiedAuthenticationServiceV2}; From 66132cba258f09ba7b3c0298078c727a84896bfc Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Tue, 4 Mar 2025 13:40:01 +0530 Subject: [PATCH 22/83] refactor: reorganize revenue recovery module structure --- .../src/default_implementations.rs | 17 +++++----- .../src/router_flow_types.rs | 2 ++ .../src/router_flow_types/revenue_recovery.rs | 2 ++ .../src/router_flow_types/webhooks.rs | 2 -- .../src/router_request_types.rs | 5 +-- .../router_request_types/revenue_recovery.rs | 5 +++ .../src/router_response_types.rs | 31 +------------------ .../router_response_types/revenue_recovery.rs | 31 +++++++++++++++++++ crates/hyperswitch_domain_models/src/types.rs | 17 +++++----- crates/hyperswitch_interfaces/src/api.rs | 7 +++-- crates/hyperswitch_interfaces/src/types.rs | 20 +++++------- crates/router/Cargo.toml | 2 +- crates/router/src/types.rs | 19 +++++++----- 13 files changed, 83 insertions(+), 77 deletions(-) create mode 100644 crates/hyperswitch_domain_models/src/router_flow_types/revenue_recovery.rs create mode 100644 crates/hyperswitch_domain_models/src/router_request_types/revenue_recovery.rs create mode 100644 crates/hyperswitch_domain_models/src/router_response_types/revenue_recovery.rs diff --git a/crates/hyperswitch_connectors/src/default_implementations.rs b/crates/hyperswitch_connectors/src/default_implementations.rs index a2a42bcc988..6044657a76d 100644 --- a/crates/hyperswitch_connectors/src/default_implementations.rs +++ b/crates/hyperswitch_connectors/src/default_implementations.rs @@ -37,21 +37,22 @@ use hyperswitch_domain_models::{ PostAuthenticate, PreAuthenticate, }, router_request_types::{ + revenue_recovery::GetAdditionalRevenueRecoveryRequestData, unified_authentication_service::{ UasAuthenticationRequestData, UasAuthenticationResponseData, UasConfirmationRequestData, UasPostAuthenticationRequestData, UasPreAuthenticationRequestData, }, - AcceptDisputeRequestData, AuthorizeSessionTokenData, CompleteAuthorizeData, - ConnectorCustomerData, DefendDisputeRequestData, GetAdditionalRevenueRecoveryRequestData, - MandateRevokeRequestData, PaymentsApproveData, PaymentsIncrementalAuthorizationData, - PaymentsPostProcessingData, PaymentsPostSessionTokensData, PaymentsPreProcessingData, - PaymentsRejectData, PaymentsTaxCalculationData, RetrieveFileRequestData, - SdkPaymentsSessionUpdateData, SubmitEvidenceRequestData, UploadFileRequestData, - VerifyWebhookSourceRequestData, + AcceptDisputeRequestData,AuthorizeSessionTokenData, CompleteAuthorizeData, ConnectorCustomerData, + DefendDisputeRequestData, MandateRevokeRequestData, PaymentsApproveData, + PaymentsIncrementalAuthorizationData, PaymentsPostProcessingData, + PaymentsPostSessionTokensData, PaymentsPreProcessingData, PaymentsRejectData, + PaymentsTaxCalculationData, RetrieveFileRequestData, SdkPaymentsSessionUpdateData, + SubmitEvidenceRequestData, UploadFileRequestData, VerifyWebhookSourceRequestData, }, router_response_types::{ - AcceptDisputeResponse, DefendDisputeResponse, GetAdditionalRevenueRecoveryResponseData, + revenue_recovery::GetAdditionalRevenueRecoveryResponseData, + AcceptDisputeResponse, DefendDisputeResponse, MandateRevokeResponseData, PaymentsResponseData, RetrieveFileResponse, SubmitEvidenceResponse, TaxCalculationResponseData, UploadFileResponse, VerifyWebhookSourceResponseData, diff --git a/crates/hyperswitch_domain_models/src/router_flow_types.rs b/crates/hyperswitch_domain_models/src/router_flow_types.rs index bdd7691b681..ba41abb3939 100644 --- a/crates/hyperswitch_domain_models/src/router_flow_types.rs +++ b/crates/hyperswitch_domain_models/src/router_flow_types.rs @@ -8,6 +8,7 @@ pub mod payouts; pub mod refunds; pub mod unified_authentication_service; pub mod webhooks; +pub mod revenue_recovery; pub use access_token_auth::*; pub use dispute::*; @@ -18,3 +19,4 @@ pub use payouts::*; pub use refunds::*; pub use unified_authentication_service::*; pub use webhooks::*; +pub use revenue_recovery::*; diff --git a/crates/hyperswitch_domain_models/src/router_flow_types/revenue_recovery.rs b/crates/hyperswitch_domain_models/src/router_flow_types/revenue_recovery.rs new file mode 100644 index 00000000000..b5059adf4f8 --- /dev/null +++ b/crates/hyperswitch_domain_models/src/router_flow_types/revenue_recovery.rs @@ -0,0 +1,2 @@ +#[derive(Debug, Clone)] +pub struct GetAdditionalRevenueRecoveryDetails; \ No newline at end of file diff --git a/crates/hyperswitch_domain_models/src/router_flow_types/webhooks.rs b/crates/hyperswitch_domain_models/src/router_flow_types/webhooks.rs index a27e7615a07..c5fe91b8464 100644 --- a/crates/hyperswitch_domain_models/src/router_flow_types/webhooks.rs +++ b/crates/hyperswitch_domain_models/src/router_flow_types/webhooks.rs @@ -20,5 +20,3 @@ impl ConnectorNetworkTxnId { } } -#[derive(Debug, Clone)] -pub struct GetAdditionalRevenueRecoveryDetails; diff --git a/crates/hyperswitch_domain_models/src/router_request_types.rs b/crates/hyperswitch_domain_models/src/router_request_types.rs index 2a0f7675b7d..dfcf7849af3 100644 --- a/crates/hyperswitch_domain_models/src/router_request_types.rs +++ b/crates/hyperswitch_domain_models/src/router_request_types.rs @@ -1,6 +1,7 @@ pub mod authentication; pub mod fraud_check; pub mod unified_authentication_service; +pub mod revenue_recovery; use api_models::payments::{AdditionalPaymentData, RequestSurchargeDetails}; use common_utils::{consts, errors, ext_traits::OptionExt, id_type, pii, types::MinorUnit}; use diesel_models::{enums as storage_enums, types::OrderDetailsWithAmount}; @@ -914,7 +915,3 @@ pub struct SetupMandateRequestData { pub shipping_cost: Option, } -#[derive(Debug, Clone)] -pub struct GetAdditionalRevenueRecoveryRequestData { - pub transaction_id: String, -} diff --git a/crates/hyperswitch_domain_models/src/router_request_types/revenue_recovery.rs b/crates/hyperswitch_domain_models/src/router_request_types/revenue_recovery.rs new file mode 100644 index 00000000000..89d227334c2 --- /dev/null +++ b/crates/hyperswitch_domain_models/src/router_request_types/revenue_recovery.rs @@ -0,0 +1,5 @@ +#[derive(Debug, Clone)] +pub struct GetAdditionalRevenueRecoveryRequestData { + // stripe charge id for additional call + pub charge_id: Option, +} diff --git a/crates/hyperswitch_domain_models/src/router_response_types.rs b/crates/hyperswitch_domain_models/src/router_response_types.rs index b35f2d89163..15e923c7517 100644 --- a/crates/hyperswitch_domain_models/src/router_response_types.rs +++ b/crates/hyperswitch_domain_models/src/router_response_types.rs @@ -1,10 +1,10 @@ pub mod disputes; pub mod fraud_check; +pub mod revenue_recovery; use std::collections::HashMap; use common_utils::{request::Method, types::MinorUnit}; pub use disputes::{AcceptDisputeResponse, DefendDisputeResponse, SubmitEvidenceResponse}; -use time::PrimitiveDateTime; use crate::{ errors::api_error_response::ApiErrorResponse, @@ -605,32 +605,3 @@ impl SupportedPaymentMethodsExt for SupportedPaymentMethods { } } -#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] -pub struct GetAdditionalRevenueRecoveryResponseData { - /// transaction amount against invoice, accepted in minor unit. - pub amount: MinorUnit, - /// currency of the transaction - pub currency: common_enums::enums::Currency, - /// merchant reference id at billing connector. ex: invoice_id - pub merchant_reference_id: common_utils::id_type::PaymentReferenceId, - /// transaction id reference at payment connector - pub connector_transaction_id: Option, - /// error code sent by billing connector. - pub error_code: Option, - /// error message sent by billing connector. - pub error_message: Option, - /// mandate token at payment processor end. - pub processor_payment_method_token: Option, - /// customer id at payment connector for which mandate is attached. - pub connector_customer_id: Option, - /// Payment gateway identifier id at billing processor. - pub connector_account_reference_id: Option, - /// timestamp at which transaction has been created at billing connector - pub transaction_created_at: Option, - /// transaction status at billing connector equivalent to payment attempt status. - pub status: common_enums::enums::AttemptStatus, - /// payment method of payment attempt. - pub payment_method_type: common_enums::enums::PaymentMethod, - /// payment method sub type of the payment attempt. - pub payment_method_sub_type: common_enums::enums::PaymentMethodType, -} diff --git a/crates/hyperswitch_domain_models/src/router_response_types/revenue_recovery.rs b/crates/hyperswitch_domain_models/src/router_response_types/revenue_recovery.rs new file mode 100644 index 00000000000..144a4c18934 --- /dev/null +++ b/crates/hyperswitch_domain_models/src/router_response_types/revenue_recovery.rs @@ -0,0 +1,31 @@ +use common_utils::types::MinorUnit; +use time::PrimitiveDateTime; +#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] +pub struct GetAdditionalRevenueRecoveryResponseData { + /// transaction amount against invoice, accepted in minor unit. + pub amount: MinorUnit, + /// currency of the transaction + pub currency: common_enums::enums::Currency, + /// merchant reference id at billing connector. ex: invoice_id + pub merchant_reference_id: common_utils::id_type::PaymentReferenceId, + /// transaction id reference at payment connector + pub connector_transaction_id: Option, + /// error code sent by billing connector. + pub error_code: Option, + /// error message sent by billing connector. + pub error_message: Option, + /// mandate token at payment processor end. + pub processor_payment_method_token: Option, + /// customer id at payment connector for which mandate is attached. + pub connector_customer_id: Option, + /// Payment gateway identifier id at billing processor. + pub connector_account_reference_id: Option, + /// timestamp at which transaction has been created at billing connector + pub transaction_created_at: Option, + /// transaction status at billing connector equivalent to payment attempt status. + pub status: common_enums::enums::AttemptStatus, + /// payment method of payment attempt. + pub payment_method_type: common_enums::enums::PaymentMethod, + /// payment method sub type of the payment attempt. + pub payment_method_sub_type: common_enums::enums::PaymentMethodType, +} \ No newline at end of file diff --git a/crates/hyperswitch_domain_models/src/types.rs b/crates/hyperswitch_domain_models/src/types.rs index be4d85bf3dc..408f22da89e 100644 --- a/crates/hyperswitch_domain_models/src/types.rs +++ b/crates/hyperswitch_domain_models/src/types.rs @@ -15,16 +15,17 @@ use crate::{ UasConfirmationRequestData, UasPostAuthenticationRequestData, UasPreAuthenticationRequestData, }, - AccessTokenRequestData, AuthorizeSessionTokenData, CompleteAuthorizeData, - ConnectorCustomerData, GetAdditionalRevenueRecoveryRequestData, MandateRevokeRequestData, - PaymentMethodTokenizationData, PaymentsAuthorizeData, PaymentsCancelData, - PaymentsCaptureData, PaymentsIncrementalAuthorizationData, PaymentsPostSessionTokensData, - PaymentsPreProcessingData, PaymentsSessionData, PaymentsSyncData, - PaymentsTaxCalculationData, RefundsData, SetupMandateRequestData, + revenue_recovery::GetAdditionalRevenueRecoveryRequestData, + AccessTokenRequestData, + AuthorizeSessionTokenData, CompleteAuthorizeData, ConnectorCustomerData, + MandateRevokeRequestData, PaymentMethodTokenizationData, PaymentsAuthorizeData, + PaymentsCancelData, PaymentsCaptureData, PaymentsIncrementalAuthorizationData, + PaymentsPostSessionTokensData, PaymentsPreProcessingData, PaymentsSessionData, + PaymentsSyncData, PaymentsTaxCalculationData, RefundsData, SetupMandateRequestData, }, router_response_types::{ - GetAdditionalRevenueRecoveryResponseData, MandateRevokeResponseData, PaymentsResponseData, - RefundsResponseData, TaxCalculationResponseData, + revenue_recovery::GetAdditionalRevenueRecoveryResponseData, MandateRevokeResponseData, + PaymentsResponseData, RefundsResponseData, TaxCalculationResponseData, }, }; #[cfg(feature = "payouts")] diff --git a/crates/hyperswitch_interfaces/src/api.rs b/crates/hyperswitch_interfaces/src/api.rs index 8900f89fbb4..9ab0628717f 100644 --- a/crates/hyperswitch_interfaces/src/api.rs +++ b/crates/hyperswitch_interfaces/src/api.rs @@ -39,16 +39,17 @@ use hyperswitch_domain_models::{ VerifyWebhookSource, }, router_request_types::{ + revenue_recovery::GetAdditionalRevenueRecoveryRequestData, unified_authentication_service::{ UasAuthenticationRequestData, UasAuthenticationResponseData, UasConfirmationRequestData, UasPostAuthenticationRequestData, UasPreAuthenticationRequestData, }, - AccessTokenRequestData, GetAdditionalRevenueRecoveryRequestData, MandateRevokeRequestData, - VerifyWebhookSourceRequestData, + AccessTokenRequestData, + MandateRevokeRequestData, VerifyWebhookSourceRequestData, }, router_response_types::{ - ConnectorInfo, GetAdditionalRevenueRecoveryResponseData, MandateRevokeResponseData, + revenue_recovery::GetAdditionalRevenueRecoveryResponseData, ConnectorInfo, MandateRevokeResponseData, PaymentMethodDetails, SupportedPaymentMethods, VerifyWebhookSourceResponseData, }, }; diff --git a/crates/hyperswitch_interfaces/src/types.rs b/crates/hyperswitch_interfaces/src/types.rs index 8b353b3836a..effbb81ef06 100644 --- a/crates/hyperswitch_interfaces/src/types.rs +++ b/crates/hyperswitch_interfaces/src/types.rs @@ -3,31 +3,24 @@ use hyperswitch_domain_models::{ router_data::AccessToken, router_flow_types::{ - access_token_auth::AccessTokenAuth, - dispute::{Accept, Defend, Evidence}, - files::{Retrieve, Upload}, - mandate_revoke::MandateRevoke, - payments::{ + access_token_auth::AccessTokenAuth, dispute::{Accept, Defend, Evidence}, files::{Retrieve, Upload}, mandate_revoke::MandateRevoke, payments::{ Authorize, AuthorizeSessionToken, Balance, CalculateTax, Capture, CompleteAuthorize, CreateConnectorCustomer, IncrementalAuthorization, InitPayment, PSync, PaymentMethodToken, PostProcessing, PostSessionTokens, PreProcessing, SdkSessionUpdate, Session, SetupMandate, Void, - }, - refunds::{Execute, RSync}, - unified_authentication_service::{ + }, refunds::{Execute, RSync}, unified_authentication_service::{ Authenticate, AuthenticationConfirmation, PostAuthenticate, PreAuthenticate, - }, - webhooks::{GetAdditionalRevenueRecoveryDetails, VerifyWebhookSource}, + }, webhooks:: VerifyWebhookSource,revenue_recovery::GetAdditionalRevenueRecoveryDetails, }, router_request_types::{ + revenue_recovery::GetAdditionalRevenueRecoveryRequestData, unified_authentication_service::{ UasAuthenticationRequestData, UasAuthenticationResponseData, UasConfirmationRequestData, UasPostAuthenticationRequestData, UasPreAuthenticationRequestData, }, AcceptDisputeRequestData, AccessTokenRequestData, AuthorizeSessionTokenData, - CompleteAuthorizeData, ConnectorCustomerData, DefendDisputeRequestData, - GetAdditionalRevenueRecoveryRequestData, MandateRevokeRequestData, + CompleteAuthorizeData, ConnectorCustomerData, DefendDisputeRequestData, MandateRevokeRequestData, PaymentMethodTokenizationData, PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, PaymentsIncrementalAuthorizationData, PaymentsPostProcessingData, PaymentsPostSessionTokensData, PaymentsPreProcessingData, PaymentsSessionData, @@ -36,7 +29,8 @@ use hyperswitch_domain_models::{ UploadFileRequestData, VerifyWebhookSourceRequestData, }, router_response_types::{ - AcceptDisputeResponse, DefendDisputeResponse, GetAdditionalRevenueRecoveryResponseData, + revenue_recovery::GetAdditionalRevenueRecoveryResponseData, + AcceptDisputeResponse, DefendDisputeResponse, MandateRevokeResponseData, PaymentsResponseData, RefundsResponseData, RetrieveFileResponse, SubmitEvidenceResponse, TaxCalculationResponseData, UploadFileResponse, VerifyWebhookSourceResponseData, diff --git a/crates/router/Cargo.toml b/crates/router/Cargo.toml index 5d552ea4e6f..b398a437841 100644 --- a/crates/router/Cargo.toml +++ b/crates/router/Cargo.toml @@ -9,7 +9,7 @@ readme = "README.md" license.workspace = true [features] -default = ["common_default", "v1"] +default = ["common_default", "v2"] common_default = ["kv_store", "stripe", "oltp", "olap", "accounts_cache", "dummy_connector", "payouts", "payout_retry", "retry", "frm", "tls", "partial-auth", "km_forward_x_request_id"] olap = ["hyperswitch_domain_models/olap", "storage_impl/olap", "scheduler/olap", "api_models/olap", "dep:analytics"] tls = ["actix-web/rustls-0_22"] diff --git a/crates/router/src/types.rs b/crates/router/src/types.rs index 5786c4404cc..1537ca83e89 100644 --- a/crates/router/src/types.rs +++ b/crates/router/src/types.rs @@ -57,15 +57,17 @@ pub use hyperswitch_domain_models::{ WebhookSourceVerifyData, }, router_request_types::{ + revenue_recovery::GetAdditionalRevenueRecoveryRequestData, unified_authentication_service::{ UasAuthenticationRequestData, UasAuthenticationResponseData, UasConfirmationRequestData, UasPostAuthenticationRequestData, UasPreAuthenticationRequestData, }, - AcceptDisputeRequestData, AccessTokenRequestData, AuthorizeSessionTokenData, - BrowserInformation, ChargeRefunds, ChargeRefundsOptions, CompleteAuthorizeData, + AcceptDisputeRequestData, AccessTokenRequestData, + AuthorizeSessionTokenData, BrowserInformation, + ChargeRefunds, ChargeRefundsOptions, CompleteAuthorizeData, CompleteAuthorizeRedirectResponse, ConnectorCustomerData, DefendDisputeRequestData, - DestinationChargeRefund, DirectChargeRefund, GetAdditionalRevenueRecoveryRequestData, + DestinationChargeRefund, DirectChargeRefund, MandateRevokeRequestData, MultipleCaptureRequestData, PaymentMethodTokenizationData, PaymentsApproveData, PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, PaymentsIncrementalAuthorizationData, PaymentsPostProcessingData, @@ -76,11 +78,12 @@ pub use hyperswitch_domain_models::{ VerifyWebhookSourceRequestData, }, router_response_types::{ - AcceptDisputeResponse, CaptureSyncResponse, DefendDisputeResponse, - GetAdditionalRevenueRecoveryResponseData, MandateReference, MandateRevokeResponseData, - PaymentsResponseData, PreprocessingResponseId, RefundsResponseData, RetrieveFileResponse, - SubmitEvidenceResponse, TaxCalculationResponseData, UploadFileResponse, - VerifyWebhookSourceResponseData, VerifyWebhookStatus, + revenue_recovery::GetAdditionalRevenueRecoveryResponseData, + AcceptDisputeResponse, CaptureSyncResponse, + DefendDisputeResponse, MandateReference, MandateRevokeResponseData, PaymentsResponseData, + PreprocessingResponseId, RefundsResponseData, RetrieveFileResponse, SubmitEvidenceResponse, + TaxCalculationResponseData, UploadFileResponse, VerifyWebhookSourceResponseData, + VerifyWebhookStatus, }, }; #[cfg(feature = "payouts")] From fc01f6cf9399a6f1beba82b810862ad07b35cbe9 Mon Sep 17 00:00:00 2001 From: "hyperswitch-bot[bot]" <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Date: Tue, 4 Mar 2025 08:25:58 +0000 Subject: [PATCH 23/83] chore: run formatter --- .../src/default_implementations.rs | 15 ++++--- .../src/router_flow_types.rs | 4 +- .../src/router_flow_types/revenue_recovery.rs | 2 +- .../src/router_flow_types/webhooks.rs | 1 - .../src/router_request_types.rs | 3 +- .../src/router_response_types.rs | 1 - .../router_response_types/revenue_recovery.rs | 2 +- crates/hyperswitch_domain_models/src/types.rs | 14 +++---- crates/hyperswitch_interfaces/src/api.rs | 8 ++-- crates/hyperswitch_interfaces/src/types.rs | 39 +++++++++++-------- crates/router/src/types.rs | 22 +++++------ 11 files changed, 56 insertions(+), 55 deletions(-) diff --git a/crates/hyperswitch_connectors/src/default_implementations.rs b/crates/hyperswitch_connectors/src/default_implementations.rs index 6044657a76d..9e087fb1e84 100644 --- a/crates/hyperswitch_connectors/src/default_implementations.rs +++ b/crates/hyperswitch_connectors/src/default_implementations.rs @@ -43,19 +43,18 @@ use hyperswitch_domain_models::{ UasConfirmationRequestData, UasPostAuthenticationRequestData, UasPreAuthenticationRequestData, }, - AcceptDisputeRequestData,AuthorizeSessionTokenData, CompleteAuthorizeData, ConnectorCustomerData, - DefendDisputeRequestData, MandateRevokeRequestData, PaymentsApproveData, - PaymentsIncrementalAuthorizationData, PaymentsPostProcessingData, + AcceptDisputeRequestData, AuthorizeSessionTokenData, CompleteAuthorizeData, + ConnectorCustomerData, DefendDisputeRequestData, MandateRevokeRequestData, + PaymentsApproveData, PaymentsIncrementalAuthorizationData, PaymentsPostProcessingData, PaymentsPostSessionTokensData, PaymentsPreProcessingData, PaymentsRejectData, PaymentsTaxCalculationData, RetrieveFileRequestData, SdkPaymentsSessionUpdateData, SubmitEvidenceRequestData, UploadFileRequestData, VerifyWebhookSourceRequestData, }, router_response_types::{ - revenue_recovery::GetAdditionalRevenueRecoveryResponseData, - AcceptDisputeResponse, DefendDisputeResponse, - MandateRevokeResponseData, PaymentsResponseData, RetrieveFileResponse, - SubmitEvidenceResponse, TaxCalculationResponseData, UploadFileResponse, - VerifyWebhookSourceResponseData, + revenue_recovery::GetAdditionalRevenueRecoveryResponseData, AcceptDisputeResponse, + DefendDisputeResponse, MandateRevokeResponseData, PaymentsResponseData, + RetrieveFileResponse, SubmitEvidenceResponse, TaxCalculationResponseData, + UploadFileResponse, VerifyWebhookSourceResponseData, }, }; #[cfg(feature = "frm")] diff --git a/crates/hyperswitch_domain_models/src/router_flow_types.rs b/crates/hyperswitch_domain_models/src/router_flow_types.rs index ba41abb3939..da91162c6f3 100644 --- a/crates/hyperswitch_domain_models/src/router_flow_types.rs +++ b/crates/hyperswitch_domain_models/src/router_flow_types.rs @@ -6,9 +6,9 @@ pub mod mandate_revoke; pub mod payments; pub mod payouts; pub mod refunds; +pub mod revenue_recovery; pub mod unified_authentication_service; pub mod webhooks; -pub mod revenue_recovery; pub use access_token_auth::*; pub use dispute::*; @@ -17,6 +17,6 @@ pub use fraud_check::*; pub use payments::*; pub use payouts::*; pub use refunds::*; +pub use revenue_recovery::*; pub use unified_authentication_service::*; pub use webhooks::*; -pub use revenue_recovery::*; diff --git a/crates/hyperswitch_domain_models/src/router_flow_types/revenue_recovery.rs b/crates/hyperswitch_domain_models/src/router_flow_types/revenue_recovery.rs index b5059adf4f8..afd3790a607 100644 --- a/crates/hyperswitch_domain_models/src/router_flow_types/revenue_recovery.rs +++ b/crates/hyperswitch_domain_models/src/router_flow_types/revenue_recovery.rs @@ -1,2 +1,2 @@ #[derive(Debug, Clone)] -pub struct GetAdditionalRevenueRecoveryDetails; \ No newline at end of file +pub struct GetAdditionalRevenueRecoveryDetails; diff --git a/crates/hyperswitch_domain_models/src/router_flow_types/webhooks.rs b/crates/hyperswitch_domain_models/src/router_flow_types/webhooks.rs index c5fe91b8464..c7f155fa166 100644 --- a/crates/hyperswitch_domain_models/src/router_flow_types/webhooks.rs +++ b/crates/hyperswitch_domain_models/src/router_flow_types/webhooks.rs @@ -19,4 +19,3 @@ impl ConnectorNetworkTxnId { &self.0 } } - diff --git a/crates/hyperswitch_domain_models/src/router_request_types.rs b/crates/hyperswitch_domain_models/src/router_request_types.rs index dfcf7849af3..cc1028c1126 100644 --- a/crates/hyperswitch_domain_models/src/router_request_types.rs +++ b/crates/hyperswitch_domain_models/src/router_request_types.rs @@ -1,7 +1,7 @@ pub mod authentication; pub mod fraud_check; -pub mod unified_authentication_service; pub mod revenue_recovery; +pub mod unified_authentication_service; use api_models::payments::{AdditionalPaymentData, RequestSurchargeDetails}; use common_utils::{consts, errors, ext_traits::OptionExt, id_type, pii, types::MinorUnit}; use diesel_models::{enums as storage_enums, types::OrderDetailsWithAmount}; @@ -914,4 +914,3 @@ pub struct SetupMandateRequestData { pub minor_amount: Option, pub shipping_cost: Option, } - diff --git a/crates/hyperswitch_domain_models/src/router_response_types.rs b/crates/hyperswitch_domain_models/src/router_response_types.rs index 15e923c7517..3d58c1546d5 100644 --- a/crates/hyperswitch_domain_models/src/router_response_types.rs +++ b/crates/hyperswitch_domain_models/src/router_response_types.rs @@ -604,4 +604,3 @@ impl SupportedPaymentMethodsExt for SupportedPaymentMethods { } } } - diff --git a/crates/hyperswitch_domain_models/src/router_response_types/revenue_recovery.rs b/crates/hyperswitch_domain_models/src/router_response_types/revenue_recovery.rs index 144a4c18934..7be9d9c9502 100644 --- a/crates/hyperswitch_domain_models/src/router_response_types/revenue_recovery.rs +++ b/crates/hyperswitch_domain_models/src/router_response_types/revenue_recovery.rs @@ -28,4 +28,4 @@ pub struct GetAdditionalRevenueRecoveryResponseData { pub payment_method_type: common_enums::enums::PaymentMethod, /// payment method sub type of the payment attempt. pub payment_method_sub_type: common_enums::enums::PaymentMethodType, -} \ No newline at end of file +} diff --git a/crates/hyperswitch_domain_models/src/types.rs b/crates/hyperswitch_domain_models/src/types.rs index 408f22da89e..e907038ff6e 100644 --- a/crates/hyperswitch_domain_models/src/types.rs +++ b/crates/hyperswitch_domain_models/src/types.rs @@ -10,18 +10,18 @@ use crate::{ PreAuthenticate, PreProcessing, RSync, Session, SetupMandate, Void, }, router_request_types::{ + revenue_recovery::GetAdditionalRevenueRecoveryRequestData, unified_authentication_service::{ UasAuthenticationRequestData, UasAuthenticationResponseData, UasConfirmationRequestData, UasPostAuthenticationRequestData, UasPreAuthenticationRequestData, }, - revenue_recovery::GetAdditionalRevenueRecoveryRequestData, - AccessTokenRequestData, - AuthorizeSessionTokenData, CompleteAuthorizeData, ConnectorCustomerData, - MandateRevokeRequestData, PaymentMethodTokenizationData, PaymentsAuthorizeData, - PaymentsCancelData, PaymentsCaptureData, PaymentsIncrementalAuthorizationData, - PaymentsPostSessionTokensData, PaymentsPreProcessingData, PaymentsSessionData, - PaymentsSyncData, PaymentsTaxCalculationData, RefundsData, SetupMandateRequestData, + AccessTokenRequestData, AuthorizeSessionTokenData, CompleteAuthorizeData, + ConnectorCustomerData, MandateRevokeRequestData, PaymentMethodTokenizationData, + PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, + PaymentsIncrementalAuthorizationData, PaymentsPostSessionTokensData, + PaymentsPreProcessingData, PaymentsSessionData, PaymentsSyncData, + PaymentsTaxCalculationData, RefundsData, SetupMandateRequestData, }, router_response_types::{ revenue_recovery::GetAdditionalRevenueRecoveryResponseData, MandateRevokeResponseData, diff --git a/crates/hyperswitch_interfaces/src/api.rs b/crates/hyperswitch_interfaces/src/api.rs index 9ab0628717f..d1038af28b5 100644 --- a/crates/hyperswitch_interfaces/src/api.rs +++ b/crates/hyperswitch_interfaces/src/api.rs @@ -45,12 +45,12 @@ use hyperswitch_domain_models::{ UasConfirmationRequestData, UasPostAuthenticationRequestData, UasPreAuthenticationRequestData, }, - AccessTokenRequestData, - MandateRevokeRequestData, VerifyWebhookSourceRequestData, + AccessTokenRequestData, MandateRevokeRequestData, VerifyWebhookSourceRequestData, }, router_response_types::{ - revenue_recovery::GetAdditionalRevenueRecoveryResponseData, ConnectorInfo, MandateRevokeResponseData, - PaymentMethodDetails, SupportedPaymentMethods, VerifyWebhookSourceResponseData, + revenue_recovery::GetAdditionalRevenueRecoveryResponseData, ConnectorInfo, + MandateRevokeResponseData, PaymentMethodDetails, SupportedPaymentMethods, + VerifyWebhookSourceResponseData, }, }; use masking::Maskable; diff --git a/crates/hyperswitch_interfaces/src/types.rs b/crates/hyperswitch_interfaces/src/types.rs index effbb81ef06..45bd3ddc28b 100644 --- a/crates/hyperswitch_interfaces/src/types.rs +++ b/crates/hyperswitch_interfaces/src/types.rs @@ -3,37 +3,44 @@ use hyperswitch_domain_models::{ router_data::AccessToken, router_flow_types::{ - access_token_auth::AccessTokenAuth, dispute::{Accept, Defend, Evidence}, files::{Retrieve, Upload}, mandate_revoke::MandateRevoke, payments::{ + access_token_auth::AccessTokenAuth, + dispute::{Accept, Defend, Evidence}, + files::{Retrieve, Upload}, + mandate_revoke::MandateRevoke, + payments::{ Authorize, AuthorizeSessionToken, Balance, CalculateTax, Capture, CompleteAuthorize, CreateConnectorCustomer, IncrementalAuthorization, InitPayment, PSync, PaymentMethodToken, PostProcessing, PostSessionTokens, PreProcessing, SdkSessionUpdate, Session, SetupMandate, Void, - }, refunds::{Execute, RSync}, unified_authentication_service::{ + }, + refunds::{Execute, RSync}, + revenue_recovery::GetAdditionalRevenueRecoveryDetails, + unified_authentication_service::{ Authenticate, AuthenticationConfirmation, PostAuthenticate, PreAuthenticate, - }, webhooks:: VerifyWebhookSource,revenue_recovery::GetAdditionalRevenueRecoveryDetails, + }, + webhooks::VerifyWebhookSource, }, router_request_types::{ - revenue_recovery::GetAdditionalRevenueRecoveryRequestData, + revenue_recovery::GetAdditionalRevenueRecoveryRequestData, unified_authentication_service::{ UasAuthenticationRequestData, UasAuthenticationResponseData, UasConfirmationRequestData, UasPostAuthenticationRequestData, UasPreAuthenticationRequestData, }, AcceptDisputeRequestData, AccessTokenRequestData, AuthorizeSessionTokenData, - CompleteAuthorizeData, ConnectorCustomerData, DefendDisputeRequestData, MandateRevokeRequestData, - PaymentMethodTokenizationData, PaymentsAuthorizeData, PaymentsCancelData, - PaymentsCaptureData, PaymentsIncrementalAuthorizationData, PaymentsPostProcessingData, - PaymentsPostSessionTokensData, PaymentsPreProcessingData, PaymentsSessionData, - PaymentsSyncData, PaymentsTaxCalculationData, RefundsData, RetrieveFileRequestData, - SdkPaymentsSessionUpdateData, SetupMandateRequestData, SubmitEvidenceRequestData, - UploadFileRequestData, VerifyWebhookSourceRequestData, + CompleteAuthorizeData, ConnectorCustomerData, DefendDisputeRequestData, + MandateRevokeRequestData, PaymentMethodTokenizationData, PaymentsAuthorizeData, + PaymentsCancelData, PaymentsCaptureData, PaymentsIncrementalAuthorizationData, + PaymentsPostProcessingData, PaymentsPostSessionTokensData, PaymentsPreProcessingData, + PaymentsSessionData, PaymentsSyncData, PaymentsTaxCalculationData, RefundsData, + RetrieveFileRequestData, SdkPaymentsSessionUpdateData, SetupMandateRequestData, + SubmitEvidenceRequestData, UploadFileRequestData, VerifyWebhookSourceRequestData, }, router_response_types::{ - revenue_recovery::GetAdditionalRevenueRecoveryResponseData, - AcceptDisputeResponse, DefendDisputeResponse, - MandateRevokeResponseData, PaymentsResponseData, RefundsResponseData, RetrieveFileResponse, - SubmitEvidenceResponse, TaxCalculationResponseData, UploadFileResponse, - VerifyWebhookSourceResponseData, + revenue_recovery::GetAdditionalRevenueRecoveryResponseData, AcceptDisputeResponse, + DefendDisputeResponse, MandateRevokeResponseData, PaymentsResponseData, + RefundsResponseData, RetrieveFileResponse, SubmitEvidenceResponse, + TaxCalculationResponseData, UploadFileResponse, VerifyWebhookSourceResponseData, }, }; #[cfg(feature = "payouts")] diff --git a/crates/router/src/types.rs b/crates/router/src/types.rs index 1537ca83e89..1dcd12df197 100644 --- a/crates/router/src/types.rs +++ b/crates/router/src/types.rs @@ -63,13 +63,12 @@ pub use hyperswitch_domain_models::{ UasConfirmationRequestData, UasPostAuthenticationRequestData, UasPreAuthenticationRequestData, }, - AcceptDisputeRequestData, AccessTokenRequestData, - AuthorizeSessionTokenData, BrowserInformation, - ChargeRefunds, ChargeRefundsOptions, CompleteAuthorizeData, + AcceptDisputeRequestData, AccessTokenRequestData, AuthorizeSessionTokenData, + BrowserInformation, ChargeRefunds, ChargeRefundsOptions, CompleteAuthorizeData, CompleteAuthorizeRedirectResponse, ConnectorCustomerData, DefendDisputeRequestData, - DestinationChargeRefund, DirectChargeRefund, - MandateRevokeRequestData, MultipleCaptureRequestData, PaymentMethodTokenizationData, - PaymentsApproveData, PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, + DestinationChargeRefund, DirectChargeRefund, MandateRevokeRequestData, + MultipleCaptureRequestData, PaymentMethodTokenizationData, PaymentsApproveData, + PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, PaymentsIncrementalAuthorizationData, PaymentsPostProcessingData, PaymentsPostSessionTokensData, PaymentsPreProcessingData, PaymentsRejectData, PaymentsSessionData, PaymentsSyncData, PaymentsTaxCalculationData, RefundsData, ResponseId, @@ -78,12 +77,11 @@ pub use hyperswitch_domain_models::{ VerifyWebhookSourceRequestData, }, router_response_types::{ - revenue_recovery::GetAdditionalRevenueRecoveryResponseData, - AcceptDisputeResponse, CaptureSyncResponse, - DefendDisputeResponse, MandateReference, MandateRevokeResponseData, PaymentsResponseData, - PreprocessingResponseId, RefundsResponseData, RetrieveFileResponse, SubmitEvidenceResponse, - TaxCalculationResponseData, UploadFileResponse, VerifyWebhookSourceResponseData, - VerifyWebhookStatus, + revenue_recovery::GetAdditionalRevenueRecoveryResponseData, AcceptDisputeResponse, + CaptureSyncResponse, DefendDisputeResponse, MandateReference, MandateRevokeResponseData, + PaymentsResponseData, PreprocessingResponseId, RefundsResponseData, RetrieveFileResponse, + SubmitEvidenceResponse, TaxCalculationResponseData, UploadFileResponse, + VerifyWebhookSourceResponseData, VerifyWebhookStatus, }, }; #[cfg(feature = "payouts")] From 51e6dcdd41d43095bb3775cef10be519bbeff506 Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Tue, 4 Mar 2025 14:13:37 +0530 Subject: [PATCH 24/83] change v2 to v1 --- crates/router/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/router/Cargo.toml b/crates/router/Cargo.toml index b398a437841..5d552ea4e6f 100644 --- a/crates/router/Cargo.toml +++ b/crates/router/Cargo.toml @@ -9,7 +9,7 @@ readme = "README.md" license.workspace = true [features] -default = ["common_default", "v2"] +default = ["common_default", "v1"] common_default = ["kv_store", "stripe", "oltp", "olap", "accounts_cache", "dummy_connector", "payouts", "payout_retry", "retry", "frm", "tls", "partial-auth", "km_forward_x_request_id"] olap = ["hyperswitch_domain_models/olap", "storage_impl/olap", "scheduler/olap", "api_models/olap", "dep:analytics"] tls = ["actix-web/rustls-0_22"] From 2cd73be2d7b6c3e9ef2c51fc438222855c899469 Mon Sep 17 00:00:00 2001 From: "hyperswitch-bot[bot]" <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Date: Tue, 4 Mar 2025 08:47:22 +0000 Subject: [PATCH 25/83] chore: run formatter --- .../src/connectors/stripebilling.rs | 70 +++++----- .../connectors/stripebilling/transformers.rs | 122 ++++++++---------- crates/hyperswitch_connectors/src/utils.rs | 8 +- 3 files changed, 103 insertions(+), 97 deletions(-) diff --git a/crates/hyperswitch_connectors/src/connectors/stripebilling.rs b/crates/hyperswitch_connectors/src/connectors/stripebilling.rs index 8201a151e29..b9787948026 100644 --- a/crates/hyperswitch_connectors/src/connectors/stripebilling.rs +++ b/crates/hyperswitch_connectors/src/connectors/stripebilling.rs @@ -1,12 +1,13 @@ pub mod transformers; +use std::collections::HashMap; + use common_utils::{ errors::CustomResult, ext_traits::BytesExt, request::{Method, Request, RequestBuilder, RequestContent}, types::{AmountConvertor, StringMinorUnit, StringMinorUnitForConnector}, }; -use std::collections::HashMap; use error_stack::{report, ResultExt}; use hyperswitch_domain_models::{ router_data::{AccessToken, ConnectorAuthType, ErrorResponse, RouterData}, @@ -552,7 +553,8 @@ impl webhooks::IncomingWebhook for Stripebilling { fn get_webhook_source_verification_algorithm( &self, _request: &webhooks::IncomingWebhookRequestDetails<'_>, - ) -> CustomResult, errors::ConnectorError> { + ) -> CustomResult, errors::ConnectorError> + { Ok(Box::new(common_utils::crypto::HmacSha256)) } @@ -564,23 +566,28 @@ impl webhooks::IncomingWebhook for Stripebilling { //signature contains the timestamp and the signature and signature will have the versions we need only v1 //handled where the signature is needed let mut header_hashmap = get_signature_elements_from_header(request.headers)?; - let signature = header_hashmap.remove("v1").ok_or(errors::ConnectorError::WebhookSignatureNotFound)?; + let signature = header_hashmap + .remove("v1") + .ok_or(errors::ConnectorError::WebhookSignatureNotFound)?; hex::decode(signature).change_context(errors::ConnectorError::WebhookSignatureNotFound) } fn get_webhook_source_verification_message( &self, - request : &webhooks::IncomingWebhookRequestDetails<'_>, - _merchant_id : &common_utils::id_type::MerchantId, - _connector_webhook_secrets : &api_models::webhooks::ConnectorWebhookSecrets - )->CustomResult,errors::ConnectorError>{ + request: &webhooks::IncomingWebhookRequestDetails<'_>, + _merchant_id: &common_utils::id_type::MerchantId, + _connector_webhook_secrets: &api_models::webhooks::ConnectorWebhookSecrets, + ) -> CustomResult, errors::ConnectorError> { let mut header_hashmap = get_signature_elements_from_header(request.headers)?; - let timestamp = header_hashmap.remove("t").ok_or(errors::ConnectorError::WebhookSignatureNotFound)?; + let timestamp = header_hashmap + .remove("t") + .ok_or(errors::ConnectorError::WebhookSignatureNotFound)?; Ok(format!( "{}.{}", String::from_utf8_lossy(×tamp), String::from_utf8_lossy(request.body) - ).into_bytes()) + ) + .into_bytes()) } #[cfg(all(feature = "revenue_recovery", feature = "v2"))] @@ -589,12 +596,11 @@ impl webhooks::IncomingWebhook for Stripebilling { request: &webhooks::IncomingWebhookRequestDetails<'_>, ) -> CustomResult { // for stripebilling we need an additional call to fetch the recovery required data . So instead of Invoice Id we sent ChargeId - let webhook = stripebilling::StripebillingWebhookBody::get_webhook_object_from_body(request.body) - .change_context(errors::ConnectorError::WebhookReferenceIdNotFound)?; + let webhook = + stripebilling::StripebillingWebhookBody::get_webhook_object_from_body(request.body) + .change_context(errors::ConnectorError::WebhookReferenceIdNotFound)?; Ok(api_models::webhooks::ObjectReferenceId::PaymentId( - api_models::payments::PaymentIdType::ConnectorTransactionId( - webhook.data.object.charge, - ), + api_models::payments::PaymentIdType::ConnectorTransactionId(webhook.data.object.charge), )) } @@ -610,9 +616,9 @@ impl webhooks::IncomingWebhook for Stripebilling { &self, request: &webhooks::IncomingWebhookRequestDetails<'_>, ) -> CustomResult { - - let webhook = stripebilling::StripebillingWebhookBody::get_webhook_object_from_body(request.body) - .change_context(errors::ConnectorError::WebhookEventTypeNotFound)?; + let webhook = + stripebilling::StripebillingWebhookBody::get_webhook_object_from_body(request.body) + .change_context(errors::ConnectorError::WebhookEventTypeNotFound)?; let event = match webhook.event_type { stripebilling::StripebillingEventType::PaymentSucceeded => { @@ -636,7 +642,6 @@ impl webhooks::IncomingWebhook for Stripebilling { Err(report!(errors::ConnectorError::WebhooksNotImplemented)) } - #[cfg(any(feature = "v1", not(all(feature = "revenue_recovery", feature = "v2"))))] fn get_webhook_resource_object( &self, @@ -650,24 +655,31 @@ impl webhooks::IncomingWebhook for Stripebilling { &self, request: &webhooks::IncomingWebhookRequestDetails<'_>, ) -> CustomResult, errors::ConnectorError> { - let webhook = - stripebilling::StripebillingInvoiceBody::get_invoice_webhook_data_from_body(request.body) - .change_context(errors::ConnectorError::WebhookResourceObjectNotFound)?; + let webhook = stripebilling::StripebillingInvoiceBody::get_invoice_webhook_data_from_body( + request.body, + ) + .change_context(errors::ConnectorError::WebhookResourceObjectNotFound)?; Ok(Box::new(webhook)) } } fn get_signature_elements_from_header( - headers : &actix_web::http::header::HeaderMap -) -> CustomResult>, errors::ConnectorError>{ - let security_header = headers.get("stripe-signature").ok_or(errors::ConnectorError::WebhookSignatureNotFound)?; - let security_header_str = security_header.to_str().change_context(errors::ConnectorError::WebhookSignatureNotFound)?; + headers: &actix_web::http::header::HeaderMap, +) -> CustomResult>, errors::ConnectorError> { + let security_header = headers + .get("stripe-signature") + .ok_or(errors::ConnectorError::WebhookSignatureNotFound)?; + let security_header_str = security_header + .to_str() + .change_context(errors::ConnectorError::WebhookSignatureNotFound)?; let header_parts = security_header_str.split(',').collect::>(); - let mut header_hashmap : HashMap> = HashMap::with_capacity(header_parts.len()); + let mut header_hashmap: HashMap> = HashMap::with_capacity(header_parts.len()); - for header_part in header_parts{ - let (header_key,header_value) = header_part.split_once('=').ok_or(errors::ConnectorError::WebhookSignatureNotFound)?; - header_hashmap.insert(header_key.to_string(),header_value.bytes().collect()); + for header_part in header_parts { + let (header_key, header_value) = header_part + .split_once('=') + .ok_or(errors::ConnectorError::WebhookSignatureNotFound)?; + header_hashmap.insert(header_key.to_string(), header_value.bytes().collect()); } Ok(header_hashmap) diff --git a/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs b/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs index 582f691103f..201592a05c3 100644 --- a/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs @@ -1,5 +1,11 @@ +#[cfg(feature = "v2")] +use std::str::FromStr; + use common_enums::enums; -use common_utils::types::StringMinorUnit; +use common_utils::{errors::CustomResult, ext_traits::ByteSliceExt, types::StringMinorUnit}; +use error_stack::ResultExt; +#[cfg(all(feature = "revenue_recovery", feature = "v2"))] +use hyperswitch_domain_models::revenue_recovery; use hyperswitch_domain_models::{ payment_method_data::PaymentMethodData, router_data::{ConnectorAuthType, RouterData}, @@ -11,17 +17,11 @@ use hyperswitch_domain_models::{ use hyperswitch_interfaces::errors; use masking::Secret; use serde::{Deserialize, Serialize}; -use error_stack::ResultExt; -#[cfg(all(feature = "revenue_recovery", feature = "v2"))] -use hyperswitch_domain_models::revenue_recovery; -#[cfg(feature="v2")] -use std::str::FromStr; use crate::{ types::{RefundsResponseRouterData, ResponseRouterData}, - utils::{PaymentsAuthorizeRequestData,convert_uppercase}, + utils::{convert_uppercase, PaymentsAuthorizeRequestData}, }; -use common_utils::{errors::CustomResult,ext_traits::ByteSliceExt}; //TODO: Fill the struct with respective fields pub struct StripebillingRouterData { @@ -237,111 +237,105 @@ pub struct StripebillingErrorResponse { pub reason: Option, } - -#[derive(Debug,Serialize,Deserialize)] +#[derive(Debug, Serialize, Deserialize)] pub struct StripebillingWebhookBody { #[serde(rename = "type")] - pub event_type : StripebillingEventType, - pub data : StripebillingWebhookData + pub event_type: StripebillingEventType, + pub data: StripebillingWebhookData, } -#[derive(Debug,Serialize,Deserialize)] +#[derive(Debug, Serialize, Deserialize)] pub struct StripebillingInvoiceBody { #[serde(rename = "type")] - pub event_type : StripebillingEventType, - pub data : StripebillingInvoiceData + pub event_type: StripebillingEventType, + pub data: StripebillingInvoiceData, } - #[derive(Serialize, Deserialize, Debug)] #[serde(rename_all = "snake_case")] pub enum StripebillingEventType { - #[serde(rename="invoice.paid")] + #[serde(rename = "invoice.paid")] PaymentSucceeded, - #[serde(rename="invoice.payment_failed")] + #[serde(rename = "invoice.payment_failed")] PaymentFailed, - #[serde(rename="invoice.voided")] - InvoiceDeleted + #[serde(rename = "invoice.voided")] + InvoiceDeleted, } #[derive(Serialize, Deserialize, Debug)] pub struct StripebillingWebhookData { - pub object : StripebillingWebhookObject + pub object: StripebillingWebhookObject, } #[derive(Serialize, Deserialize, Debug)] pub struct StripebillingInvoiceData { - pub object : StripebillingWebhookObject + pub object: StripebillingWebhookObject, } #[derive(Serialize, Deserialize, Debug)] -pub struct StripebillingWebhookObject{ - #[serde(rename="id")] - pub invoice_id : String, - #[serde(deserialize_with="convert_uppercase")] - pub currency : enums::Currency, - pub customer : String, - #[serde(rename="amount_remaining")] - pub amount : common_utils::types::MinorUnit, - pub charge : String +pub struct StripebillingWebhookObject { + #[serde(rename = "id")] + pub invoice_id: String, + #[serde(deserialize_with = "convert_uppercase")] + pub currency: enums::Currency, + pub customer: String, + #[serde(rename = "amount_remaining")] + pub amount: common_utils::types::MinorUnit, + pub charge: String, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct StripebillingInvoiceObject { + #[serde(rename = "id")] + pub invoice_id: String, + #[serde(deserialize_with = "convert_uppercase")] + pub currency: enums::Currency, + #[serde(rename = "amount_remaining")] + pub amount: common_utils::types::MinorUnit, } -#[derive(Debug,Serialize,Deserialize)] -pub struct StripebillingInvoiceObject{ - #[serde(rename="id")] - pub invoice_id : String, - #[serde(deserialize_with="convert_uppercase")] - pub currency : enums::Currency, - #[serde(rename="amount_remaining")] - pub amount : common_utils::types::MinorUnit, -} - - #[derive(Serialize, Deserialize, Debug, Clone)] -pub struct StripePaymentMethodDetails{ - #[serde(rename="type")] - pub type_of_payment_method : StripebillingPaymentMethod, - #[serde(rename="card")] - pub card_funding_type : StripeCardFundingTypeDetails, +pub struct StripePaymentMethodDetails { + #[serde(rename = "type")] + pub type_of_payment_method: StripebillingPaymentMethod, + #[serde(rename = "card")] + pub card_funding_type: StripeCardFundingTypeDetails, } #[derive(Serialize, Deserialize, Debug, Clone)] -#[serde(rename_all="snake_case")] +#[serde(rename_all = "snake_case")] pub enum StripebillingPaymentMethod { Card, } #[derive(Serialize, Deserialize, Debug, Clone)] -pub struct StripeCardFundingTypeDetails{ - pub funding : StripebillingFundingTypes +pub struct StripeCardFundingTypeDetails { + pub funding: StripebillingFundingTypes, } #[derive(Serialize, Deserialize, Debug, Clone)] -#[serde(rename="snake_case")] +#[serde(rename = "snake_case")] pub enum StripebillingFundingTypes { - #[serde(rename="credit")] + #[serde(rename = "credit")] Credit, - #[serde(rename="debit")] + #[serde(rename = "debit")] Debit, - #[serde(rename="prepaid")] + #[serde(rename = "prepaid")] Prepaid, - #[serde(rename="unknown")] - Unknown + #[serde(rename = "unknown")] + Unknown, } -#[derive(Serialize, Deserialize, Debug,Clone)] +#[derive(Serialize, Deserialize, Debug, Clone)] #[serde(rename_all = "snake_case")] -pub enum StripebillingChargeStatus{ +pub enum StripebillingChargeStatus { Succeeded, Failed, - Pending + Pending, } - impl StripebillingWebhookBody { - pub fn get_webhook_object_from_body( - body: &[u8], - ) -> CustomResult { + pub fn get_webhook_object_from_body(body: &[u8]) -> CustomResult { let webhook_body: Self = body .parse_struct::("StripebillingWebhookBody") .change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?; @@ -350,7 +344,6 @@ impl StripebillingWebhookBody { } } - impl StripebillingInvoiceBody { pub fn get_invoice_webhook_data_from_body( body: &[u8], @@ -376,4 +369,3 @@ impl TryFrom for revenue_recovery::RevenueRecoveryInvo }) } } - diff --git a/crates/hyperswitch_connectors/src/utils.rs b/crates/hyperswitch_connectors/src/utils.rs index ff00f50525f..97f827c2f4f 100644 --- a/crates/hyperswitch_connectors/src/utils.rs +++ b/crates/hyperswitch_connectors/src/utils.rs @@ -1,4 +1,7 @@ -use std::collections::{HashMap, HashSet}; +use std::{ + collections::{HashMap, HashSet}, + str::FromStr, +}; use api_models::payments; #[cfg(feature = "payouts")] @@ -57,10 +60,9 @@ use masking::{ExposeInterface, PeekInterface, Secret}; use once_cell::sync::Lazy; use regex::Regex; use router_env::logger; -use serde::{Serializer,Deserialize}; +use serde::{Deserialize, Serializer}; use serde_json::Value; use time::PrimitiveDateTime; -use std::str::FromStr; use crate::{constants::UNSUPPORTED_ERROR_MESSAGE, types::RefreshTokenRouterData}; From e5b83146904d2377b771208ca9394eb6bd26c739 Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Tue, 4 Mar 2025 14:32:07 +0530 Subject: [PATCH 26/83] refactor: update additional revenue recovery call implementations for unified authentication service connector --- .../src/default_implementations.rs | 9 ++++++++- crates/router/src/core/payments/flows.rs | 9 +-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/crates/hyperswitch_connectors/src/default_implementations.rs b/crates/hyperswitch_connectors/src/default_implementations.rs index f9448858415..ddc5c5855bd 100644 --- a/crates/hyperswitch_connectors/src/default_implementations.rs +++ b/crates/hyperswitch_connectors/src/default_implementations.rs @@ -3508,6 +3508,7 @@ default_imp_for_additional_revenue_recovery_call!( connectors::Aci, connectors::Airwallex, connectors::Amazonpay, + connectors::Authorizedotnet, connectors::Bambora, connectors::Bamboraapac, connectors::Bankofamerica, @@ -3518,6 +3519,7 @@ default_imp_for_additional_revenue_recovery_call!( connectors::Boku, connectors::Cashtocode, connectors::Chargebee, + connectors::Checkout, connectors::Coinbase, connectors::Coingate, connectors::Cryptopay, @@ -3543,11 +3545,15 @@ default_imp_for_additional_revenue_recovery_call!( connectors::Jpmorgan, connectors::Klarna, connectors::Nomupay, + connectors::Noon, connectors::Novalnet, connectors::Nexinets, connectors::Nexixpay, connectors::Nuvei, + connectors::Opayo, + connectors::Opennode, connectors::Payeezy, + connectors::Paystack, connectors::Payu, connectors::Powertranz, connectors::Prophetpay, @@ -3556,8 +3562,8 @@ default_imp_for_additional_revenue_recovery_call!( connectors::Moneris, connectors::Multisafepay, connectors::Paybox, + connectors::Payme, connectors::Placetopay, - connectors::Paystack, connectors::Rapyd, connectors::Razorpay, connectors::Redsys, @@ -3567,6 +3573,7 @@ default_imp_for_additional_revenue_recovery_call!( connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, + connectors::Trustpay, connectors::Tsys, connectors::UnifiedAuthenticationService, connectors::Worldline, diff --git a/crates/router/src/core/payments/flows.rs b/crates/router/src/core/payments/flows.rs index 17951b8f406..302bca9fb26 100644 --- a/crates/router/src/core/payments/flows.rs +++ b/crates/router/src/core/payments/flows.rs @@ -2286,18 +2286,12 @@ impl } default_imp_for_additional_revenue_recovery_call!( - connector::Adyen, connector::Adyenplatform, - connector::Authorizedotnet, - connector::Checkout, + connector::Adyen, connector::Ebanx, connector::Gpayments, connector::Netcetera, connector::Nmi, - connector::Noon, - connector::Opayo, - connector::Opennode, - connector::Payme, connector::Payone, connector::Paypal, connector::Plaid, @@ -2305,7 +2299,6 @@ default_imp_for_additional_revenue_recovery_call!( connector::Signifyd, connector::Stripe, connector::Threedsecureio, - connector::Trustpay, connector::Wellsfargopayout, connector::Wise ); From 25855cc2fe949c196e8497db86bd00d5cf7441fd Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Tue, 4 Mar 2025 16:53:06 +0530 Subject: [PATCH 27/83] refactor: add RevenueRecovery trait and update related implementations --- .../src/default_implementations.rs | 4 ++- crates/hyperswitch_interfaces/src/api.rs | 31 +++---------------- .../src/api/revenue_recovery.rs | 28 +++++++++++++++++ .../src/api/revenue_recovery_v2.rs | 28 +++++++++++++++++ crates/router/src/core/payments/flows.rs | 4 ++- crates/router/src/types/api.rs | 11 ++++--- 6 files changed, 73 insertions(+), 33 deletions(-) create mode 100644 crates/hyperswitch_interfaces/src/api/revenue_recovery.rs create mode 100644 crates/hyperswitch_interfaces/src/api/revenue_recovery_v2.rs diff --git a/crates/hyperswitch_connectors/src/default_implementations.rs b/crates/hyperswitch_connectors/src/default_implementations.rs index ddc5c5855bd..3a77af8c53e 100644 --- a/crates/hyperswitch_connectors/src/default_implementations.rs +++ b/crates/hyperswitch_connectors/src/default_implementations.rs @@ -78,6 +78,7 @@ use hyperswitch_interfaces::{ PaymentSessionUpdate, PaymentsCompleteAuthorize, PaymentsPostProcessing, PaymentsPreProcessing, TaxCalculation, }, + revenue_recovery::{AdditionalRevenueRecovery,RevenueRecovery}, ConnectorIntegration, ConnectorMandateRevoke, ConnectorRedirectResponse, UasAuthentication, UasAuthenticationConfirmation, UasPostAuthentication, UasPreAuthentication, UnifiedAuthenticationService, @@ -3492,7 +3493,8 @@ default_imp_for_uas_authentication_confirmation!( macro_rules! default_imp_for_additional_revenue_recovery_call { ($($path:ident::$connector:ident),*) => { - $( impl api::AdditionalRevenueRecovery for $path::$connector {} + $( impl RevenueRecovery for $path::$connector {} + impl AdditionalRevenueRecovery for $path::$connector {} impl ConnectorIntegration< GetAdditionalRevenueRecoveryDetails, diff --git a/crates/hyperswitch_interfaces/src/api.rs b/crates/hyperswitch_interfaces/src/api.rs index d1038af28b5..6dd585fbe49 100644 --- a/crates/hyperswitch_interfaces/src/api.rs +++ b/crates/hyperswitch_interfaces/src/api.rs @@ -16,6 +16,8 @@ pub mod payouts; pub mod payouts_v2; pub mod refunds; pub mod refunds_v2; +pub mod revenue_recovery; +pub mod revenue_recovery_v2; use common_enums::{ enums::{CallConnectorAction, CaptureMethod, EventClass, PaymentAction, PaymentMethodType}, @@ -30,16 +32,15 @@ use hyperswitch_domain_models::{ payment_method_data::PaymentMethodData, router_data::{AccessToken, ConnectorAuthType, ErrorResponse, RouterData}, router_data_v2::{ - flow_common_types::{GetAdditionalRevenueRecoveryFlowCommonData, WebhookSourceVerifyData}, + flow_common_types:: WebhookSourceVerifyData, AccessTokenFlowData, MandateRevokeFlowData, UasFlowData, }, router_flow_types::{ mandate_revoke::MandateRevoke, AccessTokenAuth, Authenticate, AuthenticationConfirmation, - GetAdditionalRevenueRecoveryDetails, PostAuthenticate, PreAuthenticate, + PostAuthenticate, PreAuthenticate, VerifyWebhookSource, }, router_request_types::{ - revenue_recovery::GetAdditionalRevenueRecoveryRequestData, unified_authentication_service::{ UasAuthenticationRequestData, UasAuthenticationResponseData, UasConfirmationRequestData, UasPostAuthenticationRequestData, @@ -48,8 +49,7 @@ use hyperswitch_domain_models::{ AccessTokenRequestData, MandateRevokeRequestData, VerifyWebhookSourceRequestData, }, router_response_types::{ - revenue_recovery::GetAdditionalRevenueRecoveryResponseData, ConnectorInfo, - MandateRevokeResponseData, PaymentMethodDetails, SupportedPaymentMethods, + ConnectorInfo,MandateRevokeResponseData, PaymentMethodDetails, SupportedPaymentMethods, VerifyWebhookSourceResponseData, }, }; @@ -373,27 +373,6 @@ pub trait ConnectorVerifyWebhookSourceV2: { } -/// trait AdditionalRevenueRecovery -pub trait AdditionalRevenueRecovery: - ConnectorIntegration< - GetAdditionalRevenueRecoveryDetails, - GetAdditionalRevenueRecoveryRequestData, - GetAdditionalRevenueRecoveryResponseData, -> -{ -} - -/// trait AdditionalRevenueRecoveryV2 -pub trait AdditionalRevenueRecoveryV2: - ConnectorIntegrationV2< - GetAdditionalRevenueRecoveryDetails, - GetAdditionalRevenueRecoveryFlowCommonData, - GetAdditionalRevenueRecoveryRequestData, - GetAdditionalRevenueRecoveryResponseData, -> -{ -} - /// trait UnifiedAuthenticationService pub trait UnifiedAuthenticationService: ConnectorCommon diff --git a/crates/hyperswitch_interfaces/src/api/revenue_recovery.rs b/crates/hyperswitch_interfaces/src/api/revenue_recovery.rs new file mode 100644 index 00000000000..9b2bd805a42 --- /dev/null +++ b/crates/hyperswitch_interfaces/src/api/revenue_recovery.rs @@ -0,0 +1,28 @@ +//! Revenue Recovery Interface + + +use hyperswitch_domain_models::{ + router_flow_types::GetAdditionalRevenueRecoveryDetails, + router_request_types::revenue_recovery::GetAdditionalRevenueRecoveryRequestData, + router_response_types::revenue_recovery::GetAdditionalRevenueRecoveryResponseData +}; + +use super::{ConnectorCommon, ConnectorIntegration}; +/// trait RevenueRecovery +pub trait RevenueRecovery : + ConnectorCommon + +AdditionalRevenueRecovery +{ + +} + + +/// trait AdditionalRevenueRecovery +pub trait AdditionalRevenueRecovery: + ConnectorIntegration< + GetAdditionalRevenueRecoveryDetails, + GetAdditionalRevenueRecoveryRequestData, + GetAdditionalRevenueRecoveryResponseData, +> +{ +} \ No newline at end of file diff --git a/crates/hyperswitch_interfaces/src/api/revenue_recovery_v2.rs b/crates/hyperswitch_interfaces/src/api/revenue_recovery_v2.rs new file mode 100644 index 00000000000..fadf1340636 --- /dev/null +++ b/crates/hyperswitch_interfaces/src/api/revenue_recovery_v2.rs @@ -0,0 +1,28 @@ +//! Revenue Recovery Interface V2 + +use hyperswitch_domain_models::{ + router_data_v2::flow_common_types::GetAdditionalRevenueRecoveryFlowCommonData, + router_flow_types::GetAdditionalRevenueRecoveryDetails, + router_request_types::revenue_recovery::GetAdditionalRevenueRecoveryRequestData, + router_response_types::revenue_recovery::GetAdditionalRevenueRecoveryResponseData +}; + +use crate::connector_integration_v2::ConnectorIntegrationV2; + +/// trait RevenueRecoveryV2 +pub trait RevenueRecoveryV2 : + AdditionalRevenueRecoveryV2 +{ +} + + +/// trait AdditionalRevenueRecoveryV2 +pub trait AdditionalRevenueRecoveryV2: + ConnectorIntegrationV2< + GetAdditionalRevenueRecoveryDetails, + GetAdditionalRevenueRecoveryFlowCommonData, + GetAdditionalRevenueRecoveryRequestData, + GetAdditionalRevenueRecoveryResponseData, +> +{ +} \ No newline at end of file diff --git a/crates/router/src/core/payments/flows.rs b/crates/router/src/core/payments/flows.rs index 302bca9fb26..e7be1c11d92 100644 --- a/crates/router/src/core/payments/flows.rs +++ b/crates/router/src/core/payments/flows.rs @@ -2261,7 +2261,8 @@ fn handle_post_capture_response( macro_rules! default_imp_for_additional_revenue_recovery_call { ($($path:ident::$connector:ident),*) => { - $( impl api::AdditionalRevenueRecovery for $path::$connector {} + $( impl api::RevenueRecovery for $path::$connector {} + impl api::AdditionalRevenueRecovery for $path::$connector {} impl services::ConnectorIntegration< GetAdditionalRevenueRecoveryDetails, @@ -2274,6 +2275,7 @@ macro_rules! default_imp_for_additional_revenue_recovery_call { } #[cfg(feature = "dummy_connector")] +impl api::RevenueRecovery for connector::DummyConnector {} impl api::AdditionalRevenueRecovery for connector::DummyConnector {} #[cfg(feature = "dummy_connector")] impl diff --git a/crates/router/src/types/api.rs b/crates/router/src/types/api.rs index a20d7d587ab..9216f66f34b 100644 --- a/crates/router/src/types/api.rs +++ b/crates/router/src/types/api.rs @@ -46,7 +46,8 @@ pub use hyperswitch_domain_models::router_flow_types::{ webhooks::VerifyWebhookSource, }; pub use hyperswitch_interfaces::api::{ - AdditionalRevenueRecovery, AdditionalRevenueRecoveryV2, ConnectorAccessToken, + revenue_recovery::{RevenueRecovery,AdditionalRevenueRecovery}, + revenue_recovery_v2::RevenueRecoveryV2, ConnectorAccessToken, ConnectorAccessTokenV2, ConnectorCommon, ConnectorCommonExt, ConnectorMandateRevoke, ConnectorMandateRevokeV2, ConnectorVerifyWebhookSource, ConnectorVerifyWebhookSourceV2, CurrencyUnit, @@ -109,7 +110,7 @@ pub trait Connector: + ExternalAuthentication + TaxCalculation + UnifiedAuthenticationService - + AdditionalRevenueRecovery + + RevenueRecovery { } @@ -130,7 +131,7 @@ impl< + ExternalAuthentication + TaxCalculation + UnifiedAuthenticationService - + AdditionalRevenueRecovery, + + RevenueRecovery, > Connector for T { } @@ -151,7 +152,7 @@ pub trait ConnectorV2: + ConnectorMandateRevokeV2 + ExternalAuthenticationV2 + UnifiedAuthenticationServiceV2 - + AdditionalRevenueRecoveryV2 + + RevenueRecoveryV2 { } impl< @@ -170,7 +171,7 @@ impl< + ConnectorMandateRevokeV2 + ExternalAuthenticationV2 + UnifiedAuthenticationServiceV2 - + AdditionalRevenueRecoveryV2, + + RevenueRecoveryV2, > ConnectorV2 for T { } From ad1e7ddf6937210896bad87718dcd235ea9f99ef Mon Sep 17 00:00:00 2001 From: "hyperswitch-bot[bot]" <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Date: Tue, 4 Mar 2025 12:10:31 +0000 Subject: [PATCH 28/83] chore: run formatter --- .../src/default_implementations.rs | 2 +- crates/hyperswitch_interfaces/src/api.rs | 9 ++++----- .../src/api/revenue_recovery.rs | 17 +++++------------ .../src/api/revenue_recovery_v2.rs | 16 ++++++---------- crates/router/src/types/api.rs | 10 +++++----- 5 files changed, 21 insertions(+), 33 deletions(-) diff --git a/crates/hyperswitch_connectors/src/default_implementations.rs b/crates/hyperswitch_connectors/src/default_implementations.rs index 3a77af8c53e..010c444cbbf 100644 --- a/crates/hyperswitch_connectors/src/default_implementations.rs +++ b/crates/hyperswitch_connectors/src/default_implementations.rs @@ -78,7 +78,7 @@ use hyperswitch_interfaces::{ PaymentSessionUpdate, PaymentsCompleteAuthorize, PaymentsPostProcessing, PaymentsPreProcessing, TaxCalculation, }, - revenue_recovery::{AdditionalRevenueRecovery,RevenueRecovery}, + revenue_recovery::{AdditionalRevenueRecovery, RevenueRecovery}, ConnectorIntegration, ConnectorMandateRevoke, ConnectorRedirectResponse, UasAuthentication, UasAuthenticationConfirmation, UasPostAuthentication, UasPreAuthentication, UnifiedAuthenticationService, diff --git a/crates/hyperswitch_interfaces/src/api.rs b/crates/hyperswitch_interfaces/src/api.rs index 6dd585fbe49..b70d326feb6 100644 --- a/crates/hyperswitch_interfaces/src/api.rs +++ b/crates/hyperswitch_interfaces/src/api.rs @@ -32,13 +32,12 @@ use hyperswitch_domain_models::{ payment_method_data::PaymentMethodData, router_data::{AccessToken, ConnectorAuthType, ErrorResponse, RouterData}, router_data_v2::{ - flow_common_types:: WebhookSourceVerifyData, - AccessTokenFlowData, MandateRevokeFlowData, UasFlowData, + flow_common_types::WebhookSourceVerifyData, AccessTokenFlowData, MandateRevokeFlowData, + UasFlowData, }, router_flow_types::{ mandate_revoke::MandateRevoke, AccessTokenAuth, Authenticate, AuthenticationConfirmation, - PostAuthenticate, PreAuthenticate, - VerifyWebhookSource, + PostAuthenticate, PreAuthenticate, VerifyWebhookSource, }, router_request_types::{ unified_authentication_service::{ @@ -49,7 +48,7 @@ use hyperswitch_domain_models::{ AccessTokenRequestData, MandateRevokeRequestData, VerifyWebhookSourceRequestData, }, router_response_types::{ - ConnectorInfo,MandateRevokeResponseData, PaymentMethodDetails, SupportedPaymentMethods, + ConnectorInfo, MandateRevokeResponseData, PaymentMethodDetails, SupportedPaymentMethods, VerifyWebhookSourceResponseData, }, }; diff --git a/crates/hyperswitch_interfaces/src/api/revenue_recovery.rs b/crates/hyperswitch_interfaces/src/api/revenue_recovery.rs index 9b2bd805a42..bd0f6923575 100644 --- a/crates/hyperswitch_interfaces/src/api/revenue_recovery.rs +++ b/crates/hyperswitch_interfaces/src/api/revenue_recovery.rs @@ -1,21 +1,14 @@ //! Revenue Recovery Interface - use hyperswitch_domain_models::{ - router_flow_types::GetAdditionalRevenueRecoveryDetails, - router_request_types::revenue_recovery::GetAdditionalRevenueRecoveryRequestData, - router_response_types::revenue_recovery::GetAdditionalRevenueRecoveryResponseData + router_flow_types::GetAdditionalRevenueRecoveryDetails, + router_request_types::revenue_recovery::GetAdditionalRevenueRecoveryRequestData, + router_response_types::revenue_recovery::GetAdditionalRevenueRecoveryResponseData, }; use super::{ConnectorCommon, ConnectorIntegration}; /// trait RevenueRecovery -pub trait RevenueRecovery : - ConnectorCommon - +AdditionalRevenueRecovery -{ - -} - +pub trait RevenueRecovery: ConnectorCommon + AdditionalRevenueRecovery {} /// trait AdditionalRevenueRecovery pub trait AdditionalRevenueRecovery: @@ -25,4 +18,4 @@ pub trait AdditionalRevenueRecovery: GetAdditionalRevenueRecoveryResponseData, > { -} \ No newline at end of file +} diff --git a/crates/hyperswitch_interfaces/src/api/revenue_recovery_v2.rs b/crates/hyperswitch_interfaces/src/api/revenue_recovery_v2.rs index fadf1340636..74da15d74a5 100644 --- a/crates/hyperswitch_interfaces/src/api/revenue_recovery_v2.rs +++ b/crates/hyperswitch_interfaces/src/api/revenue_recovery_v2.rs @@ -1,20 +1,16 @@ //! Revenue Recovery Interface V2 use hyperswitch_domain_models::{ - router_data_v2::flow_common_types::GetAdditionalRevenueRecoveryFlowCommonData, - router_flow_types::GetAdditionalRevenueRecoveryDetails, - router_request_types::revenue_recovery::GetAdditionalRevenueRecoveryRequestData, - router_response_types::revenue_recovery::GetAdditionalRevenueRecoveryResponseData + router_data_v2::flow_common_types::GetAdditionalRevenueRecoveryFlowCommonData, + router_flow_types::GetAdditionalRevenueRecoveryDetails, + router_request_types::revenue_recovery::GetAdditionalRevenueRecoveryRequestData, + router_response_types::revenue_recovery::GetAdditionalRevenueRecoveryResponseData, }; use crate::connector_integration_v2::ConnectorIntegrationV2; /// trait RevenueRecoveryV2 -pub trait RevenueRecoveryV2 : - AdditionalRevenueRecoveryV2 -{ -} - +pub trait RevenueRecoveryV2: AdditionalRevenueRecoveryV2 {} /// trait AdditionalRevenueRecoveryV2 pub trait AdditionalRevenueRecoveryV2: @@ -25,4 +21,4 @@ pub trait AdditionalRevenueRecoveryV2: GetAdditionalRevenueRecoveryResponseData, > { -} \ No newline at end of file +} diff --git a/crates/router/src/types/api.rs b/crates/router/src/types/api.rs index 9216f66f34b..fb8bd474928 100644 --- a/crates/router/src/types/api.rs +++ b/crates/router/src/types/api.rs @@ -46,11 +46,11 @@ pub use hyperswitch_domain_models::router_flow_types::{ webhooks::VerifyWebhookSource, }; pub use hyperswitch_interfaces::api::{ - revenue_recovery::{RevenueRecovery,AdditionalRevenueRecovery}, - revenue_recovery_v2::RevenueRecoveryV2, ConnectorAccessToken, - ConnectorAccessTokenV2, ConnectorCommon, ConnectorCommonExt, ConnectorMandateRevoke, - ConnectorMandateRevokeV2, ConnectorVerifyWebhookSource, ConnectorVerifyWebhookSourceV2, - CurrencyUnit, + revenue_recovery::{AdditionalRevenueRecovery, RevenueRecovery}, + revenue_recovery_v2::RevenueRecoveryV2, + ConnectorAccessToken, ConnectorAccessTokenV2, ConnectorCommon, ConnectorCommonExt, + ConnectorMandateRevoke, ConnectorMandateRevokeV2, ConnectorVerifyWebhookSource, + ConnectorVerifyWebhookSourceV2, CurrencyUnit, }; use hyperswitch_interfaces::api::{UnifiedAuthenticationService, UnifiedAuthenticationServiceV2}; From 7c05cb5b44e92925f5d693c55fee04083ae53560 Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Tue, 4 Mar 2025 18:13:26 +0530 Subject: [PATCH 29/83] refactor: update revenue recovery request data structure --- .../src/router_request_types/revenue_recovery.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/hyperswitch_domain_models/src/router_request_types/revenue_recovery.rs b/crates/hyperswitch_domain_models/src/router_request_types/revenue_recovery.rs index 89d227334c2..408e466ba4e 100644 --- a/crates/hyperswitch_domain_models/src/router_request_types/revenue_recovery.rs +++ b/crates/hyperswitch_domain_models/src/router_request_types/revenue_recovery.rs @@ -1,5 +1,5 @@ #[derive(Debug, Clone)] pub struct GetAdditionalRevenueRecoveryRequestData { - // stripe charge id for additional call - pub charge_id: Option, + /// unique id for making additional revenue recovery call + pub additional_revenue_recovery_id: String, } From 8cd127d6b0a0340b4f07dcd61cec5c335af4eac1 Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Wed, 5 Mar 2025 13:07:29 +0530 Subject: [PATCH 30/83] refactor: add necessary changes for connector to be enabled and reolved comments --- crates/connector_configs/src/connector.rs | 2 ++ .../src/connectors/stripebilling.rs | 2 +- .../src/connectors/stripebilling/transformers.rs | 12 ++++++------ crates/router/src/core/admin.rs | 4 ++++ crates/router/src/types/api.rs | 4 +++- 5 files changed, 16 insertions(+), 8 deletions(-) diff --git a/crates/connector_configs/src/connector.rs b/crates/connector_configs/src/connector.rs index 8920e39b5bd..fb6e962a668 100644 --- a/crates/connector_configs/src/connector.rs +++ b/crates/connector_configs/src/connector.rs @@ -234,6 +234,7 @@ pub struct ConnectorConfig { pub stripe: Option, #[cfg(feature = "payouts")] pub stripe_payout: Option, + // pub stripebilling : Option, pub signifyd: Option, pub trustpay: Option, pub threedsecureio: Option, @@ -401,6 +402,7 @@ impl ConnectorConfig { Connector::Square => Ok(connector_data.square), Connector::Stax => Ok(connector_data.stax), Connector::Stripe => Ok(connector_data.stripe), + // Connector::Stripebilling => Ok(connector_data.stripebilling), Connector::Trustpay => Ok(connector_data.trustpay), Connector::Threedsecureio => Ok(connector_data.threedsecureio), Connector::Taxjar => Ok(connector_data.taxjar), diff --git a/crates/hyperswitch_connectors/src/connectors/stripebilling.rs b/crates/hyperswitch_connectors/src/connectors/stripebilling.rs index b9787948026..dd2d8f54952 100644 --- a/crates/hyperswitch_connectors/src/connectors/stripebilling.rs +++ b/crates/hyperswitch_connectors/src/connectors/stripebilling.rs @@ -595,7 +595,7 @@ impl webhooks::IncomingWebhook for Stripebilling { &self, request: &webhooks::IncomingWebhookRequestDetails<'_>, ) -> CustomResult { - // for stripebilling we need an additional call to fetch the recovery required data . So instead of Invoice Id we sent ChargeId + // For Stripe billing, we need an additional call to fetch the required recovery data. So, instead of the Invoice ID, we send the Charge ID. let webhook = stripebilling::StripebillingWebhookBody::get_webhook_object_from_body(request.body) .change_context(errors::ConnectorError::WebhookReferenceIdNotFound)?; diff --git a/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs b/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs index 201592a05c3..b184f989a42 100644 --- a/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs @@ -100,7 +100,7 @@ impl TryFrom<&ConnectorAuthType> for StripebillingAuthType { } // PaymentsResponse //TODO: Append the remaining status flags -#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)] +#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Copy)] #[serde(rename_all = "lowercase")] pub enum StripebillingPaymentStatus { Succeeded, @@ -172,7 +172,7 @@ impl TryFrom<&StripebillingRouterData<&RefundsRouterData>> for Stripebilli // Type definition for Refund Response #[allow(dead_code)] -#[derive(Debug, Serialize, Default, Deserialize, Clone)] +#[derive(Debug, Serialize, Default, Deserialize, Clone, Copy)] pub enum RefundStatus { Succeeded, Failed, @@ -251,7 +251,7 @@ pub struct StripebillingInvoiceBody { pub data: StripebillingInvoiceData, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, Clone, Copy)] #[serde(rename_all = "snake_case")] pub enum StripebillingEventType { #[serde(rename = "invoice.paid")] @@ -302,7 +302,7 @@ pub struct StripePaymentMethodDetails { pub card_funding_type: StripeCardFundingTypeDetails, } -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, Copy)] #[serde(rename_all = "snake_case")] pub enum StripebillingPaymentMethod { Card, @@ -313,7 +313,7 @@ pub struct StripeCardFundingTypeDetails { pub funding: StripebillingFundingTypes, } -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, Copy)] #[serde(rename = "snake_case")] pub enum StripebillingFundingTypes { #[serde(rename = "credit")] @@ -326,7 +326,7 @@ pub enum StripebillingFundingTypes { Unknown, } -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, Copy)] #[serde(rename_all = "snake_case")] pub enum StripebillingChargeStatus { Succeeded, diff --git a/crates/router/src/core/admin.rs b/crates/router/src/core/admin.rs index 157b8570522..724afc39018 100644 --- a/crates/router/src/core/admin.rs +++ b/crates/router/src/core/admin.rs @@ -1549,6 +1549,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::Trustpay => { trustpay::transformers::TrustpayAuthType::try_from(self.auth_type)?; Ok(()) diff --git a/crates/router/src/types/api.rs b/crates/router/src/types/api.rs index a20d7d587ab..429539f4215 100644 --- a/crates/router/src/types/api.rs +++ b/crates/router/src/types/api.rs @@ -524,7 +524,9 @@ impl ConnectorData { enums::Connector::Stripe => { Ok(ConnectorEnum::Old(Box::new(connector::Stripe::new()))) } - // enums::Connector::Stripebilling => Ok(ConnectorEnum::Old(Box::new(connector::Stripebilling))), + // 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))) From 80ac277908acdd16095c46ca04a317368884942c Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Wed, 5 Mar 2025 13:11:43 +0530 Subject: [PATCH 31/83] removed unnecessary comments --- crates/hyperswitch_connectors/src/connectors/stripebilling.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/hyperswitch_connectors/src/connectors/stripebilling.rs b/crates/hyperswitch_connectors/src/connectors/stripebilling.rs index dd2d8f54952..fd4aabbab6c 100644 --- a/crates/hyperswitch_connectors/src/connectors/stripebilling.rs +++ b/crates/hyperswitch_connectors/src/connectors/stripebilling.rs @@ -563,8 +563,7 @@ impl webhooks::IncomingWebhook for Stripebilling { request: &webhooks::IncomingWebhookRequestDetails<'_>, _connector_webhook_secrets: &api_models::webhooks::ConnectorWebhookSecrets, ) -> CustomResult, errors::ConnectorError> { - //signature contains the timestamp and the signature and signature will have the versions we need only v1 - //handled where the signature is needed + let mut header_hashmap = get_signature_elements_from_header(request.headers)?; let signature = header_hashmap .remove("v1") From 738c251b9236870655b8fe282da050c757307c98 Mon Sep 17 00:00:00 2001 From: "hyperswitch-bot[bot]" <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Date: Wed, 5 Mar 2025 07:45:38 +0000 Subject: [PATCH 32/83] chore: run formatter --- crates/hyperswitch_connectors/src/connectors/stripebilling.rs | 1 - crates/router/src/types/api.rs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/hyperswitch_connectors/src/connectors/stripebilling.rs b/crates/hyperswitch_connectors/src/connectors/stripebilling.rs index fd4aabbab6c..3e20af62ff8 100644 --- a/crates/hyperswitch_connectors/src/connectors/stripebilling.rs +++ b/crates/hyperswitch_connectors/src/connectors/stripebilling.rs @@ -563,7 +563,6 @@ impl webhooks::IncomingWebhook for Stripebilling { request: &webhooks::IncomingWebhookRequestDetails<'_>, _connector_webhook_secrets: &api_models::webhooks::ConnectorWebhookSecrets, ) -> CustomResult, errors::ConnectorError> { - let mut header_hashmap = get_signature_elements_from_header(request.headers)?; let signature = header_hashmap .remove("v1") diff --git a/crates/router/src/types/api.rs b/crates/router/src/types/api.rs index 429539f4215..d520f0e14a0 100644 --- a/crates/router/src/types/api.rs +++ b/crates/router/src/types/api.rs @@ -524,7 +524,7 @@ impl ConnectorData { enums::Connector::Stripe => { Ok(ConnectorEnum::Old(Box::new(connector::Stripe::new()))) } - // enums::Connector::Stripebilling =>{ + // enums::Connector::Stripebilling =>{ // Ok(ConnectorEnum::Old(Box::new(connector::Stripebilling::new()))) // }, enums::Connector::Wise => Ok(ConnectorEnum::Old(Box::new(connector::Wise::new()))), From 968ba54ba2fb854d5ff4d3eef051ab5f2cd25a83 Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Wed, 5 Mar 2025 16:19:58 +0530 Subject: [PATCH 33/83] feat: Add Stripebilling revenue recovery support and additional details retrieval --- .../src/connectors/stripebilling.rs | 138 ++++++++++++- .../connectors/stripebilling/transformers.rs | 183 ++++++++++++++---- .../src/default_implementations.rs | 2 +- crates/hyperswitch_interfaces/src/api.rs | 2 +- .../src/core/webhooks/recovery_incoming.rs | 138 ++++++++++++- 5 files changed, 414 insertions(+), 49 deletions(-) diff --git a/crates/hyperswitch_connectors/src/connectors/stripebilling.rs b/crates/hyperswitch_connectors/src/connectors/stripebilling.rs index 3e20af62ff8..e183bc46d7c 100644 --- a/crates/hyperswitch_connectors/src/connectors/stripebilling.rs +++ b/crates/hyperswitch_connectors/src/connectors/stripebilling.rs @@ -15,17 +15,20 @@ use hyperswitch_domain_models::{ access_token_auth::AccessTokenAuth, payments::{Authorize, Capture, PSync, PaymentMethodToken, Session, SetupMandate, Void}, refunds::{Execute, RSync}, + revenue_recovery::GetAdditionalRevenueRecoveryDetails }, router_request_types::{ + revenue_recovery::GetAdditionalRevenueRecoveryRequestData, AccessTokenRequestData, PaymentMethodTokenizationData, PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, PaymentsSessionData, PaymentsSyncData, RefundsData, SetupMandateRequestData, }, - router_response_types::{PaymentsResponseData, RefundsResponseData}, + router_response_types::{revenue_recovery::GetAdditionalRevenueRecoveryResponseData,PaymentsResponseData, RefundsResponseData}, types::{ PaymentsAuthorizeRouterData, PaymentsCaptureRouterData, PaymentsSyncRouterData, - RefundSyncRouterData, RefundsRouterData, + RefundSyncRouterData, RefundsRouterData, AdditionalRevenueRecoveryDetailsRouterData }, + revenue_recovery }; use hyperswitch_interfaces::{ api::{ @@ -40,7 +43,6 @@ use hyperswitch_interfaces::{ }; use masking::{ExposeInterface, Mask}; use transformers as stripebilling; - use crate::{constants::headers, types::ResponseRouterData, utils}; #[derive(Clone)] @@ -68,6 +70,8 @@ impl api::Refund for Stripebilling {} impl api::RefundExecute for Stripebilling {} impl api::RefundSync for Stripebilling {} impl api::PaymentToken for Stripebilling {} +impl api::RevenueRecovery for Stripebilling {} +impl api::AdditionalRevenueRecovery for Stripebilling {} impl ConnectorIntegration for Stripebilling @@ -548,6 +552,115 @@ impl ConnectorIntegration for Stripebil } } +impl + ConnectorIntegration< + GetAdditionalRevenueRecoveryDetails, + GetAdditionalRevenueRecoveryRequestData, + GetAdditionalRevenueRecoveryResponseData +> for Stripebilling +{ + fn get_headers( + &self, + req: &AdditionalRevenueRecoveryDetailsRouterData, + connectors: &Connectors, + ) -> CustomResult)>, errors::ConnectorError> { + self.build_headers(req, connectors) + } + + fn get_content_type(&self) -> &'static str { + self.common_get_content_type() + } + + fn get_url( + &self, + req: &AdditionalRevenueRecoveryDetailsRouterData, + connectors: &Connectors, + ) -> CustomResult { + Ok(format!( + "{}v1/charges/{}", + self.base_url(connectors), + req.request.additional_revenue_recovery_id + )) + } + + fn build_request( + &self, + req: &AdditionalRevenueRecoveryDetailsRouterData, + connectors: &Connectors, + ) -> CustomResult, errors::ConnectorError> { + let request = RequestBuilder::new() + .method(Method::Get) + .url(&types::AdditionalRevenueRecoveryCallType::get_url(self,req, connectors)?) + .attach_default_headers() + .headers(types::AdditionalRevenueRecoveryCallType::get_headers(self,req,connectors)?) + .build(); + Ok(Some(request)) + } + + + fn handle_response( + &self, + data: &AdditionalRevenueRecoveryDetailsRouterData, + event_builder: Option<&mut ConnectorEvent>, + res: Response, + ) -> CustomResult + { + let response : stripebilling::StripebillingRecoveryDetailsData = res + .response + .parse_struct::("StripebillingRecoveryDetailsData") + .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; + + event_builder.map(|i| i.set_response_body(&response)); + router_env::logger::info!(connector_response=?response); + + AdditionalRevenueRecoveryDetailsRouterData::try_from( ResponseRouterData { + response, + data: data.clone(), + http_code: res.status_code, + }) + + } + + fn get_error_response( + &self, + res: Response, + event_builder: Option<&mut ConnectorEvent>, + ) -> CustomResult { + self.build_error_response(res,event_builder) + } + + fn get_5xx_error_response( + &self, + res: Response, + event_builder: Option<&mut ConnectorEvent>, + ) -> CustomResult { + event_builder.map(|event| event.set_error(serde_json::json!({"error": res.response.escape_ascii().to_string(), "status_code": res.status_code}))); + let error_message = match res.status_code { + 500 => "internal_server_error", + 501 => "not_implemented", + 502 => "bad_gateway", + 503 => "service_unavailable", + 504 => "gateway_timeout", + 505 => "http_version_not_supported", + 506 => "variant_also_negotiates", + 507 => "insufficient_storage", + 508 => "loop_detected", + 510 => "not_extended", + 511 => "network_authentication_required", + _ => "unknown_error", + }; + Ok(ErrorResponse { + code: res.status_code.to_string(), + message: error_message.to_string(), + reason: String::from_utf8(res.response.to_vec()).ok(), + status_code: res.status_code, + attempt_status: None, + connector_transaction_id: None, + }) + } + +} + #[async_trait::async_trait] impl webhooks::IncomingWebhook for Stripebilling { fn get_webhook_source_verification_algorithm( @@ -659,6 +772,25 @@ impl webhooks::IncomingWebhook for Stripebilling { .change_context(errors::ConnectorError::WebhookResourceObjectNotFound)?; Ok(Box::new(webhook)) } + + #[cfg(all(feature = "revenue_recovery", feature = "v2"))] + fn get_revenue_recovery_attempt_details( + &self, + _request: &webhooks::IncomingWebhookRequestDetails<'_>, + ) -> CustomResult { + // since stripe requires an additional call we dont need to implement this function beacuse we get the recovery data from additional call itself + Err(report!(errors::ConnectorError::WebhooksNotImplemented)) + } + #[cfg(all(feature = "revenue_recovery", feature = "v2"))] + fn get_revenue_recovery_invoice_details( + &self, + request: &webhooks::IncomingWebhookRequestDetails<'_>, + ) -> CustomResult { + let webhook = + stripebilling::StripebillingInvoiceBody::get_invoice_webhook_data_from_body(request.body)?; + revenue_recovery::RevenueRecoveryInvoiceData::try_from(webhook) + } + } fn get_signature_elements_from_header( diff --git a/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs b/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs index b184f989a42..547ef40ae0c 100644 --- a/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs @@ -1,5 +1,6 @@ #[cfg(feature = "v2")] use std::str::FromStr; +use time::PrimitiveDateTime; use common_enums::enums; use common_utils::{errors::CustomResult, ext_traits::ByteSliceExt, types::StringMinorUnit}; @@ -9,10 +10,10 @@ use hyperswitch_domain_models::revenue_recovery; use hyperswitch_domain_models::{ payment_method_data::PaymentMethodData, router_data::{ConnectorAuthType, RouterData}, - router_flow_types::refunds::{Execute, RSync}, - router_request_types::ResponseId, - router_response_types::{PaymentsResponseData, RefundsResponseData}, - types::{PaymentsAuthorizeRouterData, RefundsRouterData}, + router_flow_types::{revenue_recovery::GetAdditionalRevenueRecoveryDetails,refunds::{Execute, RSync}}, + router_request_types::{ResponseId,revenue_recovery::GetAdditionalRevenueRecoveryRequestData}, + router_response_types::{PaymentsResponseData, RefundsResponseData,revenue_recovery::GetAdditionalRevenueRecoveryResponseData}, + types::{PaymentsAuthorizeRouterData, RefundsRouterData,AdditionalRevenueRecoveryDetailsRouterData}, }; use hyperswitch_interfaces::errors; use masking::Secret; @@ -294,45 +295,6 @@ pub struct StripebillingInvoiceObject { pub amount: common_utils::types::MinorUnit, } -#[derive(Serialize, Deserialize, Debug, Clone)] -pub struct StripePaymentMethodDetails { - #[serde(rename = "type")] - pub type_of_payment_method: StripebillingPaymentMethod, - #[serde(rename = "card")] - pub card_funding_type: StripeCardFundingTypeDetails, -} - -#[derive(Serialize, Deserialize, Debug, Clone, Copy)] -#[serde(rename_all = "snake_case")] -pub enum StripebillingPaymentMethod { - Card, -} - -#[derive(Serialize, Deserialize, Debug, Clone)] -pub struct StripeCardFundingTypeDetails { - pub funding: StripebillingFundingTypes, -} - -#[derive(Serialize, Deserialize, Debug, Clone, Copy)] -#[serde(rename = "snake_case")] -pub enum StripebillingFundingTypes { - #[serde(rename = "credit")] - Credit, - #[serde(rename = "debit")] - Debit, - #[serde(rename = "prepaid")] - Prepaid, - #[serde(rename = "unknown")] - Unknown, -} - -#[derive(Serialize, Deserialize, Debug, Clone, Copy)] -#[serde(rename_all = "snake_case")] -pub enum StripebillingChargeStatus { - Succeeded, - Failed, - Pending, -} impl StripebillingWebhookBody { pub fn get_webhook_object_from_body(body: &[u8]) -> CustomResult { @@ -369,3 +331,138 @@ impl TryFrom for revenue_recovery::RevenueRecoveryInvo }) } } + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct StripebillingRecoveryDetailsData { + #[serde(rename="id")] + pub charge_id : String, + pub status : StripebillingChargeStatus, + pub amount : common_utils::types::MinorUnit, + #[serde(deserialize_with = "convert_uppercase")] + pub currency : enums::Currency, + pub customer : String, + pub payment_method : String, + pub failure_code : String, + pub failure_message : String, + #[serde(with = "common_utils::custom_serde::timestamp")] + pub created : PrimitiveDateTime, + pub payment_method_details : StripePaymentMethodDetails, + #[serde(rename="invoice")] + pub invoice_id : String +} + + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct StripePaymentMethodDetails{ + #[serde(rename="type")] + pub type_of_payment_method : StripebillingPaymentMethod, + #[serde(rename="card")] + pub card_funding_type : StripeCardFundingTypeDetails, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +#[serde(rename_all="snake_case")] +pub enum StripebillingPaymentMethod { + Card, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct StripeCardFundingTypeDetails{ + pub funding : StripebillingFundingTypes +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +#[serde(rename="snake_case")] +pub enum StripebillingFundingTypes { + #[serde(rename="credit")] + Credit, + #[serde(rename="debit")] + Debit, + #[serde(rename="prepaid")] + Prepaid, + #[serde(rename="unknown")] + Unknown +} + +#[derive(Serialize, Deserialize, Debug,Clone)] +#[serde(rename_all = "snake_case")] +pub enum StripebillingChargeStatus{ + Succeeded, + Failed, + Pending +} + +impl TryFrom< + ResponseRouterData< + GetAdditionalRevenueRecoveryDetails, + StripebillingRecoveryDetailsData, + GetAdditionalRevenueRecoveryRequestData, + GetAdditionalRevenueRecoveryResponseData + >> + for AdditionalRevenueRecoveryDetailsRouterData +{ + type Error = error_stack::Report; + fn try_from(item: ResponseRouterData< + GetAdditionalRevenueRecoveryDetails, + StripebillingRecoveryDetailsData, + GetAdditionalRevenueRecoveryRequestData, + GetAdditionalRevenueRecoveryResponseData + > + ) -> Result { + let merchant_reference_id = + common_utils::id_type::PaymentReferenceId::from_str(&item.response.invoice_id) + .change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?; + let connector_transaction_id = Some(common_utils::types::ConnectorTransactionId::from(item + .response + .charge_id)); + + Ok(Self { + response: Ok(GetAdditionalRevenueRecoveryResponseData { + status: item.response.status.into(), + amount : item.response.amount, + currency : item.response.currency, + merchant_reference_id, + connector_account_reference_id : Some("Stripe".to_string()), + connector_transaction_id , + error_code : Some(item.response.failure_code), + error_message : Some(item.response.failure_message), + processor_payment_method_token : Some(item.response.payment_method), + connector_customer_id : Some(item.response.customer), + transaction_created_at : Some(item.response.created), + payment_method_sub_type: common_enums::PaymentMethodType::from(item.response.payment_method_details.card_funding_type.funding), + payment_method_type : common_enums::PaymentMethod::from(item.response.payment_method_details.type_of_payment_method) + }), + ..item.data + }) + } +} + +impl From for enums::AttemptStatus { + fn from(status: StripebillingChargeStatus) -> Self { + match status { + StripebillingChargeStatus::Succeeded => Self::Charged, + StripebillingChargeStatus::Failed + | StripebillingChargeStatus::Pending=> Self::Pending, + } + } +} + +impl From for common_enums::PaymentMethodType { + fn from(funding : StripebillingFundingTypes) -> Self { + match funding { + StripebillingFundingTypes::Credit => common_enums::PaymentMethodType::Credit, + StripebillingFundingTypes::Debit + | StripebillingFundingTypes::Prepaid + | StripebillingFundingTypes::Unknown => common_enums::PaymentMethodType::Debit + + } + } +} + +impl From for common_enums::PaymentMethod { + fn from(method : StripebillingPaymentMethod) -> Self { + match method { + StripebillingPaymentMethod::Card => common_enums::PaymentMethod::Card, + } + } +} \ No newline at end of file diff --git a/crates/hyperswitch_connectors/src/default_implementations.rs b/crates/hyperswitch_connectors/src/default_implementations.rs index 010c444cbbf..50d7770c090 100644 --- a/crates/hyperswitch_connectors/src/default_implementations.rs +++ b/crates/hyperswitch_connectors/src/default_implementations.rs @@ -3572,7 +3572,7 @@ default_imp_for_additional_revenue_recovery_call!( connectors::Shift4, connectors::Stax, connectors::Square, - connectors::Stripebilling, + // connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Trustpay, diff --git a/crates/hyperswitch_interfaces/src/api.rs b/crates/hyperswitch_interfaces/src/api.rs index b70d326feb6..f4384653db3 100644 --- a/crates/hyperswitch_interfaces/src/api.rs +++ b/crates/hyperswitch_interfaces/src/api.rs @@ -57,7 +57,7 @@ use serde_json::json; #[cfg(feature = "payouts")] pub use self::payouts::*; -pub use self::{payments::*, refunds::*}; +pub use self::{payments::*, refunds::*,revenue_recovery::*}; use crate::{ configs::Connectors, connector_integration_v2::ConnectorIntegrationV2, consts, errors, events::connector_api_logs::ConnectorEvent, metrics, types, diff --git a/crates/router/src/core/webhooks/recovery_incoming.rs b/crates/router/src/core/webhooks/recovery_incoming.rs index b87311c0be0..fc51c543e1d 100644 --- a/crates/router/src/core/webhooks/recovery_incoming.rs +++ b/crates/router/src/core/webhooks/recovery_incoming.rs @@ -1,7 +1,7 @@ use api_models::webhooks; use common_utils::ext_traits::AsyncExt; use error_stack::{report, ResultExt}; -use hyperswitch_domain_models::revenue_recovery; +use hyperswitch_domain_models::{revenue_recovery, router_request_types::revenue_recovery::GetAdditionalRevenueRecoveryRequestData}; use hyperswitch_interfaces::webhooks as interface_webhooks; use router_env::{instrument, tracing}; @@ -38,6 +38,8 @@ pub async fn recovery_incoming_webhook_flow( )) })?; + // let connectors_with_additional_recovery_details_call = &state.conf.additonal_recovery_details_call; + let invoice_details = RevenueRecoveryInvoice( interface_webhooks::IncomingWebhook::get_revenue_recovery_invoice_details( connector, @@ -308,3 +310,137 @@ impl RevenueRecoveryAttempt { todo!() } } + +// async fn handle_additional_recovery_details_call( +// connector: &connector_integration_interface::ConnectorEnum, +// state: &SessionState, +// merchant_account: &domain::MerchantAccount, +// merchant_connector_account: MerchantConnectorAccount, +// connector_name: &str, +// id : &str +// ) -> CustomResult { + +// let connector_data = ConnectorData::get_connector_by_name( +// &state.conf.connectors, +// connector_name, +// GetToken::Connector, +// None, +// ) +// .change_context(errors::ConnectorError::WebhookSourceVerificationFailed) +// .attach_printable("invalid connector name received in payment attempt")?; + + +// let connector_integration: services::BoxedGetAdditionalRecoveryDetailsIntegrationInterface< +// GetRecoveryDetails, +// GetRecoveryDetailsRequestData, +// GetRecoveryDetailsResponseData, +// > = connector.get_connector_integration(); + +// let router_data = RevenueRecoveryAttempt::construct_router_data_for_additional_call( +// state, +// connector_name, +// merchant_connector_account, +// merchant_account, +// id, +// ) +// .await +// .change_context(errors::ConnectorError::RequestEncodingFailed) +// .attach_printable("Failed while constructing additional recovery details call router data")?; + +// let response = services::execute_connector_processing_step( +// state, +// connector_integration, +// &router_data, +// payments::CallConnectorAction::Trigger, +// None, +// ) +// .await?; + +// let recovery_details = response +// .response; + +// match recovery_details { +// Ok(response)=> Ok(response), +// _=> Ok(GetRecoveryDetailsResponseData{ +// payment_method : None, +// status: None, +// payment_method_details : None, +// payment_processor_error_code : None, +// payment_processor_error_message : None, +// created_at : None +// }) +// } + +// } + +// async fn construct_router_data_for_additional_call( +// state: &SessionState, +// connector_name: &str, +// merchant_connector_account: MerchantConnectorAccount, +// merchant_account: &domain::MerchantAccount, +// id: &str, +// ) -> CustomResult{ +// let auth_type: types::ConnectorAuthType = +// helpers::MerchantConnectorAccountType::DbVal(Box::new(merchant_connector_account.clone())) +// .get_connector_account_details() +// .parse_value("ConnectorAuthType") +// .change_context(errors::ApiErrorResponse::InternalServerError)?; + + +// let router_data = types::RouterData { +// flow: PhantomData, +// merchant_id: merchant_account.get_id().clone(), +// connector: connector_name.to_string(), +// customer_id: None, +// tenant_id: state.tenant.tenant_id.clone(), +// payment_id: common_utils::id_type::PaymentId::get_irrelevant_id("source_verification_flow") +// .get_string_repr() +// .to_owned(), +// attempt_id: IRRELEVANT_ATTEMPT_ID_IN_SOURCE_VERIFICATION_FLOW.to_string(), +// status: diesel_models::enums::AttemptStatus::default(), +// payment_method: diesel_models::enums::PaymentMethod::default(), +// connector_auth_type: auth_type, +// description: None, +// address: PaymentAddress::default(), +// auth_type: diesel_models::enums::AuthenticationType::default(), +// connector_meta_data: None, +// connector_wallets_details: None, +// amount_captured: None, +// minor_amount_captured: None, +// request : GetAdditionalRevenueRecoveryRequestData{ +// additional_revenue_recovery_id : invoice_details.connector_transaction_id.clone().unwrap() +// }, +// response: Err(types::ErrorResponse::default()), +// access_token: None, +// session_token: None, +// reference_id: None, +// payment_method_token: None, +// connector_customer: None, +// recurring_mandate_payment_data: None, +// preprocessing_id: None, +// connector_request_reference_id: +// IRRELEVANT_CONNECTOR_REQUEST_REFERENCE_ID_IN_SOURCE_VERIFICATION_FLOW.to_string(), +// #[cfg(feature = "payouts")] +// payout_method_data: None, +// #[cfg(feature = "payouts")] +// quote_id: None, +// test_mode: None, +// payment_method_balance: None, +// payment_method_status: None, +// connector_api_version: None, +// connector_http_status_code: None, +// external_latency: None, +// apple_pay_flow: None, +// frm_metadata: None, +// refund_id: None, +// dispute_id: None, +// connector_response: None, +// integrity_check: Ok(()), +// additional_merchant_data: None, +// header_payload: None, +// connector_mandate_request_reference_id: None, +// authentication_id: None, +// psd2_sca_exemption_type: None, +// }; +// Ok(router_data) +// } From 5bf5bf10d0ee1d1d9e36597d5b8f9a202345b676 Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Wed, 5 Mar 2025 17:20:37 +0530 Subject: [PATCH 34/83] feat(connector): add Recurly to additional revenue recovery call --- crates/hyperswitch_connectors/src/default_implementations.rs | 1 + crates/router/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/hyperswitch_connectors/src/default_implementations.rs b/crates/hyperswitch_connectors/src/default_implementations.rs index 3d4126c22a8..69b75dabf33 100644 --- a/crates/hyperswitch_connectors/src/default_implementations.rs +++ b/crates/hyperswitch_connectors/src/default_implementations.rs @@ -3604,6 +3604,7 @@ default_imp_for_additional_revenue_recovery_call!( connectors::Placetopay, connectors::Rapyd, connectors::Razorpay, + connectors::Recurly, connectors::Redsys, connectors::Shift4, connectors::Stax, diff --git a/crates/router/Cargo.toml b/crates/router/Cargo.toml index 5d552ea4e6f..1e45219597f 100644 --- a/crates/router/Cargo.toml +++ b/crates/router/Cargo.toml @@ -33,7 +33,7 @@ payouts = ["api_models/payouts", "common_enums/payouts", "hyperswitch_connectors payout_retry = ["payouts"] recon = ["email", "api_models/recon"] retry = [] -v2 = ["customer_v2", "payment_methods_v2", "common_default", "api_models/v2", "diesel_models/v2", "hyperswitch_domain_models/v2", "storage_impl/v2", "kgraph_utils/v2", "common_utils/v2", "hyperswitch_connectors/v2","hyperswitch_interfaces/v2", "common_types/v2"] +v2 = ["customer_v2", "payment_methods_v2", "common_default", "api_models/v2", "diesel_models/v2", "hyperswitch_domain_models/v2", "storage_impl/v2", "kgraph_utils/v2", "common_utils/v2", "hyperswitch_connectors/v2","hyperswitch_interfaces/v2", "common_types/v2","revenue_recovery"] v1 = ["common_default", "api_models/v1", "diesel_models/v1", "hyperswitch_domain_models/v1", "storage_impl/v1", "hyperswitch_interfaces/v1", "kgraph_utils/v1", "common_utils/v1", "hyperswitch_connectors/v1", "common_types/v1"] customer_v2 = ["api_models/customer_v2", "diesel_models/customer_v2", "hyperswitch_domain_models/customer_v2", "storage_impl/customer_v2"] payment_methods_v2 = ["api_models/payment_methods_v2", "diesel_models/payment_methods_v2", "hyperswitch_domain_models/payment_methods_v2", "storage_impl/payment_methods_v2", "common_utils/payment_methods_v2"] From 11f4ae4aad6b0dc02f239b1f83b23e1a82a22fe2 Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Fri, 7 Mar 2025 19:39:24 +0530 Subject: [PATCH 35/83] feat(connector): Enable Stripebilling webhook support with additional revenue recovery details retrieval and recovery flow --- crates/api_models/src/webhooks.rs | 8 + crates/common_enums/src/connector_enums.rs | 8 +- crates/connector_configs/src/connector.rs | 4 +- .../src/connectors/stripebilling.rs | 46 ++- .../connectors/stripebilling/transformers.rs | 33 +- .../src/default_implementations.rs | 114 +++++- .../src/revenue_recovery.rs | 28 ++ crates/hyperswitch_domain_models/src/types.rs | 11 +- .../src/api/revenue_recovery.rs | 11 +- crates/router/Cargo.toml | 2 +- .../src/configs/secrets_transformers.rs | 2 +- crates/router/src/configs/settings.rs | 2 +- crates/router/src/core/admin.rs | 8 +- crates/router/src/core/errors.rs | 2 + crates/router/src/core/payments/flows.rs | 41 +- .../router/src/core/webhooks/incoming_v2.rs | 3 + .../src/core/webhooks/recovery_incoming.rs | 375 +++++++++++------- .../router/src/services/conversion_impls.rs | 41 +- crates/router/src/types/api.rs | 6 +- crates/router/src/types/transformers.rs | 2 +- 20 files changed, 534 insertions(+), 213 deletions(-) diff --git a/crates/api_models/src/webhooks.rs b/crates/api_models/src/webhooks.rs index d5404d57aa3..951fcbfc0fb 100644 --- a/crates/api_models/src/webhooks.rs +++ b/crates/api_models/src/webhooks.rs @@ -253,6 +253,8 @@ pub enum ObjectReferenceId { PayoutId(PayoutIdType), #[cfg(all(feature = "revenue_recovery", feature = "v2"))] InvoiceId(InvoiceIdType), + #[cfg(all(feature="revenue_recovery",feature="v2"))] + AdditionalRevenueRecoveryId(AdditionalRevenueRecoveryIdType) } #[cfg(all(feature = "revenue_recovery", feature = "v2"))] @@ -261,6 +263,12 @@ pub enum InvoiceIdType { ConnectorInvoiceId(String), } +#[cfg(all(feature = "revenue_recovery", feature = "v2"))] +#[derive(Clone)] +pub enum AdditionalRevenueRecoveryIdType { + AdditionalRevenueRecoveryCallId(String), +} + pub struct IncomingWebhookDetails { pub object_reference_id: ObjectReferenceId, pub resource_object: Vec, diff --git a/crates/common_enums/src/connector_enums.rs b/crates/common_enums/src/connector_enums.rs index 65fa444175e..a6620d4d440 100644 --- a/crates/common_enums/src/connector_enums.rs +++ b/crates/common_enums/src/connector_enums.rs @@ -124,7 +124,7 @@ pub enum RoutableConnectors { Square, Stax, Stripe, - //Stripebilling, + Stripebilling, // Taxjar, Trustpay, // Thunes @@ -266,7 +266,7 @@ pub enum Connector { Square, Stax, Stripe, - // Stripebilling, + Stripebilling, Taxjar, Threedsecureio, //Thunes, @@ -415,7 +415,7 @@ impl Connector { | Self::Shift4 | Self::Square | Self::Stax - // | Self::Stripebilling + | Self::Stripebilling | Self::Taxjar // | Self::Thunes | Self::Trustpay @@ -553,7 +553,7 @@ impl From for Connector { RoutableConnectors::Square => Self::Square, RoutableConnectors::Stax => Self::Stax, RoutableConnectors::Stripe => Self::Stripe, - // RoutableConnectors::Stripebilling => Self::Stripebilling, + RoutableConnectors::Stripebilling => Self::Stripebilling, RoutableConnectors::Trustpay => Self::Trustpay, RoutableConnectors::Tsys => Self::Tsys, RoutableConnectors::Volt => Self::Volt, diff --git a/crates/connector_configs/src/connector.rs b/crates/connector_configs/src/connector.rs index fb6e962a668..2bae363e276 100644 --- a/crates/connector_configs/src/connector.rs +++ b/crates/connector_configs/src/connector.rs @@ -234,7 +234,7 @@ pub struct ConnectorConfig { pub stripe: Option, #[cfg(feature = "payouts")] pub stripe_payout: Option, - // pub stripebilling : Option, + pub stripebilling : Option, pub signifyd: Option, pub trustpay: Option, pub threedsecureio: Option, @@ -402,7 +402,7 @@ impl ConnectorConfig { Connector::Square => Ok(connector_data.square), Connector::Stax => Ok(connector_data.stax), Connector::Stripe => Ok(connector_data.stripe), - // Connector::Stripebilling => Ok(connector_data.stripebilling), + Connector::Stripebilling => Ok(connector_data.stripebilling), Connector::Trustpay => Ok(connector_data.trustpay), Connector::Threedsecureio => Ok(connector_data.threedsecureio), Connector::Taxjar => Ok(connector_data.taxjar), diff --git a/crates/hyperswitch_connectors/src/connectors/stripebilling.rs b/crates/hyperswitch_connectors/src/connectors/stripebilling.rs index e183bc46d7c..5f0f7274ab3 100644 --- a/crates/hyperswitch_connectors/src/connectors/stripebilling.rs +++ b/crates/hyperswitch_connectors/src/connectors/stripebilling.rs @@ -15,21 +15,30 @@ use hyperswitch_domain_models::{ access_token_auth::AccessTokenAuth, payments::{Authorize, Capture, PSync, PaymentMethodToken, Session, SetupMandate, Void}, refunds::{Execute, RSync}, - revenue_recovery::GetAdditionalRevenueRecoveryDetails }, router_request_types::{ - revenue_recovery::GetAdditionalRevenueRecoveryRequestData, AccessTokenRequestData, PaymentMethodTokenizationData, PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, PaymentsSessionData, PaymentsSyncData, RefundsData, SetupMandateRequestData, }, - router_response_types::{revenue_recovery::GetAdditionalRevenueRecoveryResponseData,PaymentsResponseData, RefundsResponseData}, + router_response_types::{PaymentsResponseData, RefundsResponseData}, types::{ PaymentsAuthorizeRouterData, PaymentsCaptureRouterData, PaymentsSyncRouterData, - RefundSyncRouterData, RefundsRouterData, AdditionalRevenueRecoveryDetailsRouterData - }, - revenue_recovery + RefundSyncRouterData, RefundsRouterData + } +}; +use stripebilling::auth_headers; +use masking::PeekInterface; + +#[cfg(all(feature="v2",feature="revenue_recovery"))] +use hyperswitch_domain_models::{ + router_flow_types::revenue_recovery::GetAdditionalRevenueRecoveryDetails, + router_request_types::revenue_recovery::GetAdditionalRevenueRecoveryRequestData, + router_response_types::revenue_recovery::GetAdditionalRevenueRecoveryResponseData, + types::AdditionalRevenueRecoveryDetailsRouterData }; +#[cfg(all(feature="v2",feature="revenue_recovery"))] +use hyperswitch_domain_models::revenue_recovery; use hyperswitch_interfaces::{ api::{ self, ConnectorCommon, ConnectorCommonExt, ConnectorIntegration, ConnectorSpecifications, @@ -41,7 +50,9 @@ use hyperswitch_interfaces::{ types::{self, Response}, webhooks, }; -use masking::{ExposeInterface, Mask}; +use masking::Mask; +#[cfg(all(feature="v2",feature="revenue_recovery"))] +use masking::ExposeInterface; use transformers as stripebilling; use crate::{constants::headers, types::ResponseRouterData, utils}; @@ -70,7 +81,7 @@ impl api::Refund for Stripebilling {} impl api::RefundExecute for Stripebilling {} impl api::RefundSync for Stripebilling {} impl api::PaymentToken for Stripebilling {} -impl api::RevenueRecovery for Stripebilling {} +#[cfg(all(feature="v2",feature="revenue_recovery"))] impl api::AdditionalRevenueRecovery for Stripebilling {} impl ConnectorIntegration @@ -121,10 +132,16 @@ impl ConnectorCommon for Stripebilling { ) -> CustomResult)>, errors::ConnectorError> { let auth = stripebilling::StripebillingAuthType::try_from(auth_type) .change_context(errors::ConnectorError::FailedToObtainAuthType)?; - Ok(vec![( - headers::AUTHORIZATION.to_string(), - auth.api_key.expose().into_masked(), - )]) + Ok(vec![ + ( + headers::AUTHORIZATION.to_string(), + format!("Bearer {}", auth.api_key.peek()).into_masked(), + ), + ( + auth_headers::STRIPE_API_VERSION.to_string(), + auth_headers::STRIPE_VERSION.to_string().into_masked(), + ), + ]) } fn build_error_response( @@ -552,6 +569,7 @@ impl ConnectorIntegration for Stripebil } } +#[cfg(all(feature="v2",feature="revenue_recovery"))] impl ConnectorIntegration< GetAdditionalRevenueRecoveryDetails, @@ -710,8 +728,8 @@ impl webhooks::IncomingWebhook for Stripebilling { let webhook = stripebilling::StripebillingWebhookBody::get_webhook_object_from_body(request.body) .change_context(errors::ConnectorError::WebhookReferenceIdNotFound)?; - Ok(api_models::webhooks::ObjectReferenceId::PaymentId( - api_models::payments::PaymentIdType::ConnectorTransactionId(webhook.data.object.charge), + Ok(api_models::webhooks::ObjectReferenceId::AdditionalRevenueRecoveryId( + api_models::webhooks::AdditionalRevenueRecoveryIdType::AdditionalRevenueRecoveryCallId(webhook.data.object.charge), )) } diff --git a/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs b/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs index 547ef40ae0c..2738683769f 100644 --- a/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs @@ -10,11 +10,19 @@ use hyperswitch_domain_models::revenue_recovery; use hyperswitch_domain_models::{ payment_method_data::PaymentMethodData, router_data::{ConnectorAuthType, RouterData}, - router_flow_types::{revenue_recovery::GetAdditionalRevenueRecoveryDetails,refunds::{Execute, RSync}}, - router_request_types::{ResponseId,revenue_recovery::GetAdditionalRevenueRecoveryRequestData}, - router_response_types::{PaymentsResponseData, RefundsResponseData,revenue_recovery::GetAdditionalRevenueRecoveryResponseData}, - types::{PaymentsAuthorizeRouterData, RefundsRouterData,AdditionalRevenueRecoveryDetailsRouterData}, + router_flow_types::refunds::{Execute, RSync}, + router_request_types::ResponseId, + router_response_types::{PaymentsResponseData, RefundsResponseData}, + types::{PaymentsAuthorizeRouterData, RefundsRouterData}, }; +#[cfg(all(feature="v2",feature="revenue_recovery"))] +use hyperswitch_domain_models::{ + router_flow_types::revenue_recovery::GetAdditionalRevenueRecoveryDetails, + router_request_types::revenue_recovery::GetAdditionalRevenueRecoveryRequestData, + router_response_types::revenue_recovery::GetAdditionalRevenueRecoveryResponseData, + types::AdditionalRevenueRecoveryDetailsRouterData +}; + use hyperswitch_interfaces::errors; use masking::Secret; use serde::{Deserialize, Serialize}; @@ -24,6 +32,11 @@ use crate::{ utils::{convert_uppercase, PaymentsAuthorizeRequestData}, }; +pub mod auth_headers { + pub const STRIPE_API_VERSION: &str = "stripe-version"; + pub const STRIPE_VERSION: &str = "2022-11-15"; +} + //TODO: Fill the struct with respective fields pub struct StripebillingRouterData { pub amount: StringMinorUnit, // The type of amount that a connector accepts, for example, String, i64, f64, etc. @@ -301,7 +314,7 @@ impl StripebillingWebhookBody { let webhook_body: Self = body .parse_struct::("StripebillingWebhookBody") .change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?; - + Ok(webhook_body) } } @@ -392,6 +405,7 @@ pub enum StripebillingChargeStatus{ Pending } +#[cfg(all(feature="v2",feature="revenue_recovery"))] impl TryFrom< ResponseRouterData< GetAdditionalRevenueRecoveryDetails, @@ -437,6 +451,7 @@ impl TryFrom< } } +#[cfg(all(feature="v2",feature="revenue_recovery"))] impl From for enums::AttemptStatus { fn from(status: StripebillingChargeStatus) -> Self { match status { @@ -447,22 +462,24 @@ impl From for enums::AttemptStatus { } } +#[cfg(all(feature="v2",feature="revenue_recovery"))] impl From for common_enums::PaymentMethodType { fn from(funding : StripebillingFundingTypes) -> Self { match funding { - StripebillingFundingTypes::Credit => common_enums::PaymentMethodType::Credit, + StripebillingFundingTypes::Credit => Self::Credit, StripebillingFundingTypes::Debit | StripebillingFundingTypes::Prepaid - | StripebillingFundingTypes::Unknown => common_enums::PaymentMethodType::Debit + | StripebillingFundingTypes::Unknown => Self::Debit } } } +#[cfg(all(feature="v2",feature="revenue_recovery"))] impl From for common_enums::PaymentMethod { fn from(method : StripebillingPaymentMethod) -> Self { match method { - StripebillingPaymentMethod::Card => common_enums::PaymentMethod::Card, + StripebillingPaymentMethod::Card => Self::Card, } } } \ No newline at end of file diff --git a/crates/hyperswitch_connectors/src/default_implementations.rs b/crates/hyperswitch_connectors/src/default_implementations.rs index 00f70bfcef8..fe137ad856e 100644 --- a/crates/hyperswitch_connectors/src/default_implementations.rs +++ b/crates/hyperswitch_connectors/src/default_implementations.rs @@ -33,11 +33,10 @@ use hyperswitch_domain_models::{ PreProcessing, Reject, SdkSessionUpdate, }, webhooks::VerifyWebhookSource, - Authenticate, AuthenticationConfirmation, GetAdditionalRevenueRecoveryDetails, + Authenticate, AuthenticationConfirmation, PostAuthenticate, PreAuthenticate, }, router_request_types::{ - revenue_recovery::GetAdditionalRevenueRecoveryRequestData, unified_authentication_service::{ UasAuthenticationRequestData, UasAuthenticationResponseData, UasConfirmationRequestData, UasPostAuthenticationRequestData, @@ -51,12 +50,21 @@ use hyperswitch_domain_models::{ SubmitEvidenceRequestData, UploadFileRequestData, VerifyWebhookSourceRequestData, }, router_response_types::{ - revenue_recovery::GetAdditionalRevenueRecoveryResponseData, AcceptDisputeResponse, + AcceptDisputeResponse, DefendDisputeResponse, MandateRevokeResponseData, PaymentsResponseData, RetrieveFileResponse, SubmitEvidenceResponse, TaxCalculationResponseData, UploadFileResponse, VerifyWebhookSourceResponseData, }, }; + +#[cfg(all(feature="v2",feature="revenue_recovery"))] +use hyperswitch_domain_models::{ + router_flow_types::revenue_recovery::GetAdditionalRevenueRecoveryDetails, + router_request_types::revenue_recovery::GetAdditionalRevenueRecoveryRequestData, + router_response_types::revenue_recovery::GetAdditionalRevenueRecoveryResponseData, + types::AdditionalRevenueRecoveryDetailsRouterData +}; + #[cfg(feature = "frm")] use hyperswitch_interfaces::api::fraud_check::{ FraudCheckCheckout, FraudCheckFulfillment, FraudCheckRecordReturn, FraudCheckSale, @@ -78,14 +86,17 @@ use hyperswitch_interfaces::{ PaymentSessionUpdate, PaymentsCompleteAuthorize, PaymentsPostProcessing, PaymentsPreProcessing, TaxCalculation, }, - revenue_recovery::{AdditionalRevenueRecovery, RevenueRecovery}, ConnectorIntegration, ConnectorMandateRevoke, ConnectorRedirectResponse, UasAuthentication, UasAuthenticationConfirmation, UasPostAuthentication, UasPreAuthentication, UnifiedAuthenticationService, }, errors::ConnectorError, + api::RevenueRecovery, }; +#[cfg(all(feature="v2",feature="revenue_recovery"))] +use hyperswitch_interfaces::api::revenue_recovery::AdditionalRevenueRecovery; + macro_rules! default_imp_for_authorize_session_token { ($($path:ident::$connector:ident),*) => { $( impl PaymentAuthorizeSessionToken for $path::$connector {} @@ -3527,10 +3538,99 @@ default_imp_for_uas_authentication_confirmation!( connectors::Zsl ); -macro_rules! default_imp_for_additional_revenue_recovery_call { +macro_rules! default_imp_for_revenue_recovery { ($($path:ident::$connector:ident),*) => { $( impl RevenueRecovery for $path::$connector {} - impl AdditionalRevenueRecovery for $path::$connector {} + )* + }; +} + +default_imp_for_revenue_recovery!{ + connectors::Aci, + connectors::Airwallex, + connectors::Amazonpay, + connectors::Authorizedotnet, + connectors::Bambora, + connectors::Bamboraapac, + connectors::Bankofamerica, + connectors::Billwerk, + connectors::Bluesnap, + connectors::Bitpay, + connectors::Braintree, + connectors::Boku, + connectors::Cashtocode, + connectors::Chargebee, + connectors::Checkout, + connectors::Coinbase, + connectors::Coingate, + connectors::Cryptopay, + connectors::CtpMastercard, + connectors::Cybersource, + connectors::Datatrans, + connectors::Deutschebank, + connectors::Digitalvirgo, + connectors::Dlocal, + connectors::Elavon, + connectors::Fiserv, + connectors::Fiservemea, + connectors::Fiuu, + connectors::Forte, + connectors::Getnet, + connectors::Globalpay, + connectors::Globepay, + connectors::Gocardless, + connectors::Helcim, + connectors::Iatapay, + connectors::Inespay, + connectors::Itaubank, + connectors::Jpmorgan, + connectors::Klarna, + connectors::Nomupay, + connectors::Noon, + connectors::Novalnet, + connectors::Nexinets, + connectors::Nexixpay, + connectors::Nuvei, + connectors::Opayo, + connectors::Opennode, + connectors::Payeezy, + connectors::Paystack, + connectors::Payu, + connectors::Powertranz, + connectors::Prophetpay, + connectors::Mifinity, + connectors::Mollie, + connectors::Moneris, + connectors::Multisafepay, + connectors::Paybox, + connectors::Payme, + connectors::Placetopay, + connectors::Rapyd, + connectors::Razorpay, + connectors::Recurly, + connectors::Redsys, + connectors::Shift4, + connectors::Stax, + connectors::Square, + connectors::Stripebilling, + connectors::Taxjar, + connectors::Thunes, + connectors::Trustpay, + connectors::Tsys, + connectors::UnifiedAuthenticationService, + connectors::Worldline, + connectors::Worldpay, + connectors::Wellsfargo, + connectors::Volt, + connectors::Xendit, + connectors::Zen, + connectors::Zsl +} + +#[cfg(all(feature="v2",feature="revenue_recovery"))] +macro_rules! default_imp_for_additional_revenue_recovery_call { + ($($path:ident::$connector:ident),*) => { + $( impl AdditionalRevenueRecovery for $path::$connector {} impl ConnectorIntegration< GetAdditionalRevenueRecoveryDetails, @@ -3542,6 +3642,7 @@ macro_rules! default_imp_for_additional_revenue_recovery_call { }; } +#[cfg(all(feature="v2",feature="revenue_recovery"))] default_imp_for_additional_revenue_recovery_call!( connectors::Aci, connectors::Airwallex, @@ -3609,7 +3710,6 @@ default_imp_for_additional_revenue_recovery_call!( connectors::Shift4, connectors::Stax, connectors::Square, - // connectors::Stripebilling, connectors::Taxjar, connectors::Thunes, connectors::Trustpay, diff --git a/crates/hyperswitch_domain_models/src/revenue_recovery.rs b/crates/hyperswitch_domain_models/src/revenue_recovery.rs index 8467189d27a..efdc053c4eb 100644 --- a/crates/hyperswitch_domain_models/src/revenue_recovery.rs +++ b/crates/hyperswitch_domain_models/src/revenue_recovery.rs @@ -1,6 +1,8 @@ use api_models::webhooks; use time::PrimitiveDateTime; +use crate::router_response_types::revenue_recovery::GetAdditionalRevenueRecoveryResponseData; + /// Recovery payload is unified struct constructed from billing connectors #[derive(Debug)] pub struct RevenueRecoveryAttemptData { @@ -188,3 +190,29 @@ impl From<&RevenueRecoveryInvoiceData> for api_models::payments::PaymentsCreateI } } } + +impl From for RevenueRecoveryInvoiceData { + fn from(data: GetAdditionalRevenueRecoveryResponseData)-> Self{ + Self { amount: data.amount, currency: data.currency, merchant_reference_id: data.merchant_reference_id } + } +} + +impl From for RevenueRecoveryAttemptData{ + fn from(data: GetAdditionalRevenueRecoveryResponseData)-> Self { + Self { + amount: data.amount, + currency: data.currency, + merchant_reference_id: data.merchant_reference_id, + connector_transaction_id: data.connector_transaction_id, + error_code: data.error_code, + error_message: data.error_message, + processor_payment_method_token: data.processor_payment_method_token, + connector_customer_id: data.connector_customer_id, + connector_account_reference_id: data.connector_account_reference_id, + transaction_created_at: data.transaction_created_at, + status: data.status, + payment_method_type: data.payment_method_type, + payment_method_sub_type: data.payment_method_sub_type + } + } +} \ No newline at end of file diff --git a/crates/hyperswitch_domain_models/src/types.rs b/crates/hyperswitch_domain_models/src/types.rs index e907038ff6e..78486a82b25 100644 --- a/crates/hyperswitch_domain_models/src/types.rs +++ b/crates/hyperswitch_domain_models/src/types.rs @@ -1,14 +1,12 @@ pub use diesel_models::types::OrderDetailsWithAmount; - use crate::{ - router_data::{AccessToken, RouterData}, - router_flow_types::{ + router_data::{AccessToken, RouterData}, router_flow_types::{ mandate_revoke::MandateRevoke, AccessTokenAuth, Authenticate, AuthenticationConfirmation, Authorize, AuthorizeSessionToken, CalculateTax, Capture, CompleteAuthorize, CreateConnectorCustomer, Execute, GetAdditionalRevenueRecoveryDetails, IncrementalAuthorization, PSync, PaymentMethodToken, PostAuthenticate, PostSessionTokens, PreAuthenticate, PreProcessing, RSync, Session, SetupMandate, Void, - }, + }, router_request_types::{ revenue_recovery::GetAdditionalRevenueRecoveryRequestData, unified_authentication_service::{ @@ -22,12 +20,13 @@ use crate::{ PaymentsIncrementalAuthorizationData, PaymentsPostSessionTokensData, PaymentsPreProcessingData, PaymentsSessionData, PaymentsSyncData, PaymentsTaxCalculationData, RefundsData, SetupMandateRequestData, - }, + }, router_response_types::{ revenue_recovery::GetAdditionalRevenueRecoveryResponseData, MandateRevokeResponseData, PaymentsResponseData, RefundsResponseData, TaxCalculationResponseData, - }, + } }; + #[cfg(feature = "payouts")] pub use crate::{router_request_types::PayoutsData, router_response_types::PayoutsResponseData}; diff --git a/crates/hyperswitch_interfaces/src/api/revenue_recovery.rs b/crates/hyperswitch_interfaces/src/api/revenue_recovery.rs index bd0f6923575..5e600a41b9d 100644 --- a/crates/hyperswitch_interfaces/src/api/revenue_recovery.rs +++ b/crates/hyperswitch_interfaces/src/api/revenue_recovery.rs @@ -6,7 +6,12 @@ use hyperswitch_domain_models::{ router_response_types::revenue_recovery::GetAdditionalRevenueRecoveryResponseData, }; -use super::{ConnectorCommon, ConnectorIntegration}; +use super::ConnectorIntegration; + +#[cfg(all(feature="v2",feature="revenue_recovery"))] +use super::ConnectorCommon; + +#[cfg(all(feature="v2",feature="revenue_recovery"))] /// trait RevenueRecovery pub trait RevenueRecovery: ConnectorCommon + AdditionalRevenueRecovery {} @@ -19,3 +24,7 @@ pub trait AdditionalRevenueRecovery: > { } + +#[cfg(not(all(feature="v2",feature="revenue_recovery")))] +/// trait RevenueRecovery +pub trait RevenueRecovery {} diff --git a/crates/router/Cargo.toml b/crates/router/Cargo.toml index 1e45219597f..6537c268591 100644 --- a/crates/router/Cargo.toml +++ b/crates/router/Cargo.toml @@ -9,7 +9,7 @@ readme = "README.md" license.workspace = true [features] -default = ["common_default", "v1"] +default = ["common_default", "v2"] common_default = ["kv_store", "stripe", "oltp", "olap", "accounts_cache", "dummy_connector", "payouts", "payout_retry", "retry", "frm", "tls", "partial-auth", "km_forward_x_request_id"] olap = ["hyperswitch_domain_models/olap", "storage_impl/olap", "scheduler/olap", "api_models/olap", "dep:analytics"] tls = ["actix-web/rustls-0_22"] diff --git a/crates/router/src/configs/secrets_transformers.rs b/crates/router/src/configs/secrets_transformers.rs index 2c28e6f1402..8904322d1be 100644 --- a/crates/router/src/configs/secrets_transformers.rs +++ b/crates/router/src/configs/secrets_transformers.rs @@ -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, + additional_revenue_recovery_details_call: conf.additional_revenue_recovery_details_call, payment_method_auth, connector_request_reference_id_config: conf.connector_request_reference_id_config, #[cfg(feature = "payouts")] diff --git a/crates/router/src/configs/settings.rs b/crates/router/src/configs/settings.rs index 605b4b576f3..a5f833e3047 100644 --- a/crates/router/src/configs/settings.rs +++ b/crates/router/src/configs/settings.rs @@ -96,7 +96,7 @@ pub struct Settings { pub required_fields: RequiredFields, pub delayed_session_response: DelayedSessionConfig, pub webhook_source_verification_call: WebhookSourceVerificationCall, - // pub additional_revenue_recovery_details_call: GetAdditionalRevenueRecoveryDetailsCall, + pub additional_revenue_recovery_details_call: GetAdditionalRevenueRecoveryDetailsCall, pub payment_method_auth: SecretStateContainer, pub connector_request_reference_id_config: ConnectorRequestReferenceIdConfig, #[cfg(feature = "payouts")] diff --git a/crates/router/src/core/admin.rs b/crates/router/src/core/admin.rs index 724afc39018..0072d003cad 100644 --- a/crates/router/src/core/admin.rs +++ b/crates/router/src/core/admin.rs @@ -1549,10 +1549,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(()) diff --git a/crates/router/src/core/errors.rs b/crates/router/src/core/errors.rs index 215f262ea8b..04540fbce1c 100644 --- a/crates/router/src/core/errors.rs +++ b/crates/router/src/core/errors.rs @@ -463,4 +463,6 @@ pub enum RevenueRecoveryError { PaymentIntentCreateFailed, #[error("Source verification failed for billing connector")] WebhookAuthenticationFailed, + #[error("Additional Revenue Recovery Call Failed")] + AdditionalRevenueRecoveryCallFailed, } diff --git a/crates/router/src/core/payments/flows.rs b/crates/router/src/core/payments/flows.rs index 937de63f5fc..56fd8479baa 100644 --- a/crates/router/src/core/payments/flows.rs +++ b/crates/router/src/core/payments/flows.rs @@ -15,7 +15,7 @@ use async_trait::async_trait; use hyperswitch_domain_models::{ mandates::CustomerAcceptance, router_flow_types::{ - Authenticate, AuthenticationConfirmation, GetAdditionalRevenueRecoveryDetails, + Authenticate, AuthenticationConfirmation, PostAuthenticate, PreAuthenticate, }, router_request_types::PaymentsCaptureData, @@ -24,6 +24,8 @@ use hyperswitch_interfaces::api::{ payouts::Payouts, UasAuthentication, UasAuthenticationConfirmation, UasPostAuthentication, UasPreAuthentication, UnifiedAuthenticationService, }; +#[cfg(all(feature="v2",feature="revenue_recovery"))] +use hyperswitch_domain_models::router_flow_types::GetAdditionalRevenueRecoveryDetails; #[cfg(feature = "frm")] use crate::types::fraud_check as frm_types; @@ -2262,10 +2264,38 @@ fn handle_post_capture_response( } } -macro_rules! default_imp_for_additional_revenue_recovery_call { +macro_rules! default_imp_for_revenue_recovery { ($($path:ident::$connector:ident),*) => { $( impl api::RevenueRecovery for $path::$connector {} - impl api::AdditionalRevenueRecovery for $path::$connector {} + )* + }; +} + +#[cfg(feature = "dummy_connector")] +impl api::RevenueRecovery for connector::DummyConnector {} + +default_imp_for_revenue_recovery!{ + connector::Adyenplatform, + connector::Adyen, + connector::Ebanx, + connector::Gpayments, + connector::Netcetera, + connector::Nmi, + connector::Payone, + connector::Paypal, + 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, @@ -2276,10 +2306,10 @@ macro_rules! default_imp_for_additional_revenue_recovery_call { )* }; } - +#[cfg(all(feature="v2",feature="revenue_recovery"))] #[cfg(feature = "dummy_connector")] -impl api::RevenueRecovery for connector::DummyConnector {} impl api::AdditionalRevenueRecovery for connector::DummyConnector {} +#[cfg(all(feature="v2",feature="revenue_recovery"))] #[cfg(feature = "dummy_connector")] impl services::ConnectorIntegration< @@ -2290,6 +2320,7 @@ impl { } +#[cfg(all(feature="v2",feature="revenue_recovery"))] default_imp_for_additional_revenue_recovery_call!( connector::Adyenplatform, connector::Adyen, diff --git a/crates/router/src/core/webhooks/incoming_v2.rs b/crates/router/src/core/webhooks/incoming_v2.rs index f67eb5c15c1..11dcea09c3f 100644 --- a/crates/router/src/core/webhooks/incoming_v2.rs +++ b/crates/router/src/core/webhooks/incoming_v2.rs @@ -361,9 +361,12 @@ async fn incoming_webhooks_core( webhook_details, source_verified, &connector, + &merchant_connector_account, + &connector_name, &request_details, event_type, req_state, + &object_ref_id )) .await .change_context(errors::ApiErrorResponse::WebhookProcessingFailure) diff --git a/crates/router/src/core/webhooks/recovery_incoming.rs b/crates/router/src/core/webhooks/recovery_incoming.rs index fc51c543e1d..f99250b46e4 100644 --- a/crates/router/src/core/webhooks/recovery_incoming.rs +++ b/crates/router/src/core/webhooks/recovery_incoming.rs @@ -1,18 +1,25 @@ use api_models::webhooks; use common_utils::ext_traits::AsyncExt; use error_stack::{report, ResultExt}; -use hyperswitch_domain_models::{revenue_recovery, router_request_types::revenue_recovery::GetAdditionalRevenueRecoveryRequestData}; -use hyperswitch_interfaces::webhooks as interface_webhooks; +use hyperswitch_domain_models::{revenue_recovery, router_flow_types::GetAdditionalRevenueRecoveryDetails, router_request_types::revenue_recovery::GetAdditionalRevenueRecoveryRequestData, router_response_types::revenue_recovery::GetAdditionalRevenueRecoveryResponseData, types::AdditionalRevenueRecoveryDetailsRouterData}; use router_env::{instrument, tracing}; +use hyperswitch_interfaces::webhooks as interface_webhooks; +use crate::types; +use std::marker::PhantomData; +use common_utils::ext_traits::ValueExt; +use std::str::FromStr; use crate::{ core::{ errors::{self, CustomResult}, - payments, + payments::{self,helpers}, }, routes::{app::ReqState, SessionState}, services::{self, connector_integration_interface}, - types::{api, domain}, + types::{ + api::{self,ConnectorData,GetToken}, + domain + }, }; #[allow(clippy::too_many_arguments)] @@ -25,29 +32,77 @@ 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, + merchant_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, + object_ref_id : &webhooks::ObjectReferenceId ) -> CustomResult { - // Source verification is necessary for revenue recovery webhooks flow since We don't have payment intent/attempt object created before in our system. + // 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 connectors_with_additional_recovery_details_call = &state.conf.additonal_recovery_details_call; + let connectors_with_additional_recovery_details_call = &state.conf.additional_revenue_recovery_details_call; - 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 recovery_details = + if connectors_with_additional_recovery_details_call + .connectors_with_additional_revenue_recovery_details_call + .contains(&connector) + { + + let additional_revenue_recovery_id = match object_ref_id { + webhooks::ObjectReferenceId::AdditionalRevenueRecoveryId( + webhooks::AdditionalRevenueRecoveryIdType::AdditionalRevenueRecoveryCallId(ref id) + ) => Some(id.as_str()), + _ => None, + }; + + let additional_call_response = handle_additional_recovery_details_call( + connector_enum, + &state, + &merchant_account, + merchant_connector_account, + connector_name, + additional_revenue_recovery_id.unwrap_or("fake_id") + ).await?; + + Some(additional_call_response) + + } else { + None + }; + + let invoice_details = match recovery_details.clone() { + Some(data)=> { + RevenueRecoveryInvoice( + revenue_recovery::RevenueRecoveryInvoiceData::from(data.clone()) + ) + }, + None => + { + RevenueRecoveryInvoice( + 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")?, + ) + } + }; + // Fetch the intent using merchant reference id, if not found create new intent. let payment_intent = invoice_details .get_payment_intent( @@ -72,15 +127,28 @@ 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)?, - ); + let invoice_transaction_details = match recovery_details.clone() { + Some(data) => + { + RevenueRecoveryAttempt( + revenue_recovery::RevenueRecoveryAttemptData::from(data) + ) + } + None => + { + RevenueRecoveryAttempt( + interface_webhooks::IncomingWebhook::get_revenue_recovery_attempt_details( + connector_enum, + request_details, + ) + .change_context(errors::RevenueRecoveryError::TransactionWebhookProcessingFailed)?, + ) + } + }; + invoice_transaction_details .get_payment_attempt( @@ -311,136 +379,139 @@ impl RevenueRecoveryAttempt { } } -// async fn handle_additional_recovery_details_call( -// connector: &connector_integration_interface::ConnectorEnum, -// state: &SessionState, -// merchant_account: &domain::MerchantAccount, -// merchant_connector_account: MerchantConnectorAccount, -// connector_name: &str, -// id : &str -// ) -> CustomResult { - -// let connector_data = ConnectorData::get_connector_by_name( -// &state.conf.connectors, -// connector_name, -// GetToken::Connector, -// None, -// ) -// .change_context(errors::ConnectorError::WebhookSourceVerificationFailed) -// .attach_printable("invalid connector name received in payment attempt")?; - - -// let connector_integration: services::BoxedGetAdditionalRecoveryDetailsIntegrationInterface< -// GetRecoveryDetails, -// GetRecoveryDetailsRequestData, -// GetRecoveryDetailsResponseData, -// > = connector.get_connector_integration(); - -// let router_data = RevenueRecoveryAttempt::construct_router_data_for_additional_call( -// state, -// connector_name, -// merchant_connector_account, -// merchant_account, -// id, -// ) -// .await -// .change_context(errors::ConnectorError::RequestEncodingFailed) -// .attach_printable("Failed while constructing additional recovery details call router data")?; - -// let response = services::execute_connector_processing_step( -// state, -// connector_integration, -// &router_data, -// payments::CallConnectorAction::Trigger, -// None, -// ) -// .await?; - -// let recovery_details = response -// .response; - -// match recovery_details { -// Ok(response)=> Ok(response), -// _=> Ok(GetRecoveryDetailsResponseData{ -// payment_method : None, -// status: None, -// payment_method_details : None, -// payment_processor_error_code : None, -// payment_processor_error_message : None, -// created_at : None -// }) -// } - -// } - -// async fn construct_router_data_for_additional_call( -// state: &SessionState, -// connector_name: &str, -// merchant_connector_account: MerchantConnectorAccount, -// merchant_account: &domain::MerchantAccount, -// id: &str, -// ) -> CustomResult{ -// let auth_type: types::ConnectorAuthType = -// helpers::MerchantConnectorAccountType::DbVal(Box::new(merchant_connector_account.clone())) -// .get_connector_account_details() -// .parse_value("ConnectorAuthType") -// .change_context(errors::ApiErrorResponse::InternalServerError)?; +async fn handle_additional_recovery_details_call( + connector: &connector_integration_interface::ConnectorEnum, + state: &SessionState, + merchant_account: &domain::MerchantAccount, + merchant_connector_account: &hyperswitch_domain_models::merchant_connector_account::MerchantConnectorAccount, + connector_name: &str, + id : &str +) -> CustomResult { + + let connector_data = ConnectorData::get_connector_by_name( + &state.conf.connectors, + connector_name, + GetToken::Connector, + None, + ) + .change_context(errors::RevenueRecoveryError::AdditionalRevenueRecoveryCallFailed) + .attach_printable("invalid connector name received in payment attempt")?; + + + let connector_integration: services::BoxedGetAdditionalRecoveryRecoveryDetailsIntegrationInterface< + GetAdditionalRevenueRecoveryDetails, + GetAdditionalRevenueRecoveryRequestData, + GetAdditionalRevenueRecoveryResponseData + > = connector_data.connector.get_connector_integration(); + + let router_data = construct_router_data_for_additional_call( + state, + connector_name, + merchant_connector_account, + merchant_account, + id, + ) + .await + .change_context(errors::RevenueRecoveryError::AdditionalRevenueRecoveryCallFailed) + .attach_printable("Failed while constructing additional recovery details call router data")?; + + let response = services::execute_connector_processing_step( + state, + connector_integration, + &router_data, + payments::CallConnectorAction::Trigger, + None, + ) + .await + .change_context(errors::RevenueRecoveryError::AdditionalRevenueRecoveryCallFailed) + .attach_printable("Failed while calling the API")?; + + let additional_recovery_details = match response.response { + Ok(response) => Ok(response), + error @ Err(_) => { + router_env::logger::error!(?error); + Err(errors::RevenueRecoveryError::AdditionalRevenueRecoveryCallFailed) + .attach_printable("failed to fetch payment intent recovery webhook flow") + } + }?; + Ok(additional_recovery_details) +} + +const IRRELEVANT_ATTEMPT_ID_IN_ADDITIONAL_REVENUE_RECOVERY_CALL_FLOW: &str = + "irrelevant_attempt_id_in_additional_revenue_recovery_flow"; + +const IRRELEVANT_CONNECTOR_REQUEST_REFERENCE_ID_IN_ADDITIONAL_REVENUE_RECOVERY_CALL: &str = +"irrelevant_connector_request_reference_id_in_additional_revenue_recovery_flow"; + +async fn construct_router_data_for_additional_call( + state: &SessionState, + connector_name: &str, + merchant_connector_account: &hyperswitch_domain_models::merchant_connector_account::MerchantConnectorAccount, + merchant_account: &domain::MerchantAccount, + additional_revenue_recovery_id: &str, +) -> CustomResult{ + + 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::AdditionalRevenueRecoveryCallFailed)?; -// let router_data = types::RouterData { -// flow: PhantomData, -// merchant_id: merchant_account.get_id().clone(), -// connector: connector_name.to_string(), -// customer_id: None, -// tenant_id: state.tenant.tenant_id.clone(), -// payment_id: common_utils::id_type::PaymentId::get_irrelevant_id("source_verification_flow") -// .get_string_repr() -// .to_owned(), -// attempt_id: IRRELEVANT_ATTEMPT_ID_IN_SOURCE_VERIFICATION_FLOW.to_string(), -// status: diesel_models::enums::AttemptStatus::default(), -// payment_method: diesel_models::enums::PaymentMethod::default(), -// connector_auth_type: auth_type, -// description: None, -// address: PaymentAddress::default(), -// auth_type: diesel_models::enums::AuthenticationType::default(), -// connector_meta_data: None, -// connector_wallets_details: None, -// amount_captured: None, -// minor_amount_captured: None, -// request : GetAdditionalRevenueRecoveryRequestData{ -// additional_revenue_recovery_id : invoice_details.connector_transaction_id.clone().unwrap() -// }, -// response: Err(types::ErrorResponse::default()), -// access_token: None, -// session_token: None, -// reference_id: None, -// payment_method_token: None, -// connector_customer: None, -// recurring_mandate_payment_data: None, -// preprocessing_id: None, -// connector_request_reference_id: -// IRRELEVANT_CONNECTOR_REQUEST_REFERENCE_ID_IN_SOURCE_VERIFICATION_FLOW.to_string(), -// #[cfg(feature = "payouts")] -// payout_method_data: None, -// #[cfg(feature = "payouts")] -// quote_id: None, -// test_mode: None, -// payment_method_balance: None, -// payment_method_status: None, -// connector_api_version: None, -// connector_http_status_code: None, -// external_latency: None, -// apple_pay_flow: None, -// frm_metadata: None, -// refund_id: None, -// dispute_id: None, -// connector_response: None, -// integrity_check: Ok(()), -// additional_merchant_data: None, -// header_payload: None, -// connector_mandate_request_reference_id: None, -// authentication_id: None, -// psd2_sca_exemption_type: None, -// }; -// Ok(router_data) -// } + let router_data = types::RouterData { + flow: PhantomData, + merchant_id: merchant_account.get_id().clone(), + connector: connector_name.to_string(), + customer_id: None, + tenant_id: state.tenant.tenant_id.clone(), + payment_id: common_utils::id_type::PaymentId::get_irrelevant_id("additional revenue recovery details call flow") + .get_string_repr() + .to_owned(), + attempt_id: IRRELEVANT_ATTEMPT_ID_IN_ADDITIONAL_REVENUE_RECOVERY_CALL_FLOW.to_string(), + status: diesel_models::enums::AttemptStatus::default(), + payment_method: diesel_models::enums::PaymentMethod::default(), + connector_auth_type: auth_type, + description: None, + address: hyperswitch_domain_models::payment_address::PaymentAddress::default(), + auth_type: diesel_models::enums::AuthenticationType::default(), + connector_meta_data: None, + connector_wallets_details: None, + amount_captured: None, + minor_amount_captured: None, + request : GetAdditionalRevenueRecoveryRequestData{ + additional_revenue_recovery_id : additional_revenue_recovery_id.to_string() + }, + response: Err(types::ErrorResponse::default()), + access_token: None, + session_token: None, + reference_id: None, + payment_method_token: None, + connector_customer: None, + recurring_mandate_payment_data: None, + preprocessing_id: None, + connector_request_reference_id: + IRRELEVANT_CONNECTOR_REQUEST_REFERENCE_ID_IN_ADDITIONAL_REVENUE_RECOVERY_CALL.to_string(), + #[cfg(feature = "payouts")] + payout_method_data: None, + #[cfg(feature = "payouts")] + quote_id: None, + test_mode: None, + payment_method_balance: None, + payment_method_status: None, + connector_api_version: None, + connector_http_status_code: None, + external_latency: None, + apple_pay_flow: None, + frm_metadata: None, + refund_id: None, + dispute_id: None, + connector_response: None, + integrity_check: Ok(()), + additional_merchant_data: None, + header_payload: None, + connector_mandate_request_reference_id: None, + authentication_id: None, + psd2_sca_exemption_type: None, + }; + Ok(router_data) +} \ No newline at end of file diff --git a/crates/router/src/services/conversion_impls.rs b/crates/router/src/services/conversion_impls.rs index 8572add041e..22867b00056 100644 --- a/crates/router/src/services/conversion_impls.rs +++ b/crates/router/src/services/conversion_impls.rs @@ -9,9 +9,7 @@ use hyperswitch_domain_models::{ router_data::{self, RouterData}, router_data_v2::{ flow_common_types::{ - AccessTokenFlowData, DisputesFlowData, ExternalAuthenticationFlowData, FilesFlowData, - MandateRevokeFlowData, PaymentFlowData, RefundFlowData, UasFlowData, - WebhookSourceVerifyData, + AccessTokenFlowData, DisputesFlowData, ExternalAuthenticationFlowData, FilesFlowData, GetAdditionalRevenueRecoveryFlowCommonData, MandateRevokeFlowData, PaymentFlowData, RefundFlowData, UasFlowData, WebhookSourceVerifyData }, RouterDataV2, }, @@ -763,3 +761,40 @@ impl RouterDataConversion for UasFlowD Ok(router_data) } } + +impl RouterDataConversion for GetAdditionalRevenueRecoveryFlowCommonData { + + fn from_old_router_data( + old_router_data: &RouterData, + ) -> errors::CustomResult, errors::ConnectorError> + where + Self: Sized + { + let resource_common_data = Self{}; + Ok(RouterDataV2{ + flow : std::marker::PhantomData, + tenant_id: old_router_data.tenant_id.clone(), + 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, + ) -> errors::CustomResult, errors::ConnectorError> + where + Self: Sized + { + let router_data = get_default_router_data( + new_router_data.tenant_id.clone(), + "getadditionalrecoverydetails", + new_router_data.request, + new_router_data.response, + ); + Ok(router_data) + + } + +} diff --git a/crates/router/src/types/api.rs b/crates/router/src/types/api.rs index 5407fc39153..48d596c9f24 100644 --- a/crates/router/src/types/api.rs +++ b/crates/router/src/types/api.rs @@ -526,9 +526,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))) diff --git a/crates/router/src/types/transformers.rs b/crates/router/src/types/transformers.rs index 6ab4111f4b7..f6a49115267 100644 --- a/crates/router/src/types/transformers.rs +++ b/crates/router/src/types/transformers.rs @@ -306,7 +306,7 @@ impl ForeignTryFrom 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, From 44cf2c4980e10b0efc5942d456346915e67720fa Mon Sep 17 00:00:00 2001 From: "hyperswitch-bot[bot]" <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Date: Fri, 7 Mar 2025 14:20:08 +0000 Subject: [PATCH 36/83] chore: run formatter --- crates/api_models/src/webhooks.rs | 4 +- crates/connector_configs/src/connector.rs | 2 +- .../src/connectors/stripebilling.rs | 75 ++++---- .../connectors/stripebilling/transformers.rs | 170 +++++++++--------- .../src/default_implementations.rs | 44 ++--- .../src/revenue_recovery.rs | 42 +++-- crates/hyperswitch_domain_models/src/types.rs | 11 +- crates/hyperswitch_interfaces/src/api.rs | 2 +- .../src/api/revenue_recovery.rs | 9 +- crates/router/src/configs/settings.rs | 2 +- crates/router/src/core/payments/flows.rs | 19 +- .../router/src/core/webhooks/incoming_v2.rs | 2 +- .../src/core/webhooks/recovery_incoming.rs | 144 +++++++-------- .../router/src/services/conversion_impls.rs | 35 ++-- crates/router/src/types/api.rs | 6 +- 15 files changed, 279 insertions(+), 288 deletions(-) diff --git a/crates/api_models/src/webhooks.rs b/crates/api_models/src/webhooks.rs index 951fcbfc0fb..0df98739c5a 100644 --- a/crates/api_models/src/webhooks.rs +++ b/crates/api_models/src/webhooks.rs @@ -253,8 +253,8 @@ pub enum ObjectReferenceId { PayoutId(PayoutIdType), #[cfg(all(feature = "revenue_recovery", feature = "v2"))] InvoiceId(InvoiceIdType), - #[cfg(all(feature="revenue_recovery",feature="v2"))] - AdditionalRevenueRecoveryId(AdditionalRevenueRecoveryIdType) + #[cfg(all(feature = "revenue_recovery", feature = "v2"))] + AdditionalRevenueRecoveryId(AdditionalRevenueRecoveryIdType), } #[cfg(all(feature = "revenue_recovery", feature = "v2"))] diff --git a/crates/connector_configs/src/connector.rs b/crates/connector_configs/src/connector.rs index 2bae363e276..a5fe74eb47c 100644 --- a/crates/connector_configs/src/connector.rs +++ b/crates/connector_configs/src/connector.rs @@ -234,7 +234,7 @@ pub struct ConnectorConfig { pub stripe: Option, #[cfg(feature = "payouts")] pub stripe_payout: Option, - pub stripebilling : Option, + pub stripebilling: Option, pub signifyd: Option, pub trustpay: Option, pub threedsecureio: Option, diff --git a/crates/hyperswitch_connectors/src/connectors/stripebilling.rs b/crates/hyperswitch_connectors/src/connectors/stripebilling.rs index 5f0f7274ab3..3452d2be85c 100644 --- a/crates/hyperswitch_connectors/src/connectors/stripebilling.rs +++ b/crates/hyperswitch_connectors/src/connectors/stripebilling.rs @@ -9,6 +9,8 @@ use common_utils::{ types::{AmountConvertor, StringMinorUnit, StringMinorUnitForConnector}, }; use error_stack::{report, ResultExt}; +#[cfg(all(feature = "v2", feature = "revenue_recovery"))] +use hyperswitch_domain_models::revenue_recovery; use hyperswitch_domain_models::{ router_data::{AccessToken, ConnectorAuthType, ErrorResponse, RouterData}, router_flow_types::{ @@ -24,21 +26,16 @@ use hyperswitch_domain_models::{ router_response_types::{PaymentsResponseData, RefundsResponseData}, types::{ PaymentsAuthorizeRouterData, PaymentsCaptureRouterData, PaymentsSyncRouterData, - RefundSyncRouterData, RefundsRouterData - } + RefundSyncRouterData, RefundsRouterData, + }, }; -use stripebilling::auth_headers; -use masking::PeekInterface; - -#[cfg(all(feature="v2",feature="revenue_recovery"))] +#[cfg(all(feature = "v2", feature = "revenue_recovery"))] use hyperswitch_domain_models::{ router_flow_types::revenue_recovery::GetAdditionalRevenueRecoveryDetails, router_request_types::revenue_recovery::GetAdditionalRevenueRecoveryRequestData, router_response_types::revenue_recovery::GetAdditionalRevenueRecoveryResponseData, - types::AdditionalRevenueRecoveryDetailsRouterData + types::AdditionalRevenueRecoveryDetailsRouterData, }; -#[cfg(all(feature="v2",feature="revenue_recovery"))] -use hyperswitch_domain_models::revenue_recovery; use hyperswitch_interfaces::{ api::{ self, ConnectorCommon, ConnectorCommonExt, ConnectorIntegration, ConnectorSpecifications, @@ -50,10 +47,12 @@ use hyperswitch_interfaces::{ types::{self, Response}, webhooks, }; -use masking::Mask; -#[cfg(all(feature="v2",feature="revenue_recovery"))] +#[cfg(all(feature = "v2", feature = "revenue_recovery"))] use masking::ExposeInterface; +use masking::{Mask, PeekInterface}; +use stripebilling::auth_headers; use transformers as stripebilling; + use crate::{constants::headers, types::ResponseRouterData, utils}; #[derive(Clone)] @@ -81,7 +80,7 @@ impl api::Refund for Stripebilling {} impl api::RefundExecute for Stripebilling {} impl api::RefundSync for Stripebilling {} impl api::PaymentToken for Stripebilling {} -#[cfg(all(feature="v2",feature="revenue_recovery"))] +#[cfg(all(feature = "v2", feature = "revenue_recovery"))] impl api::AdditionalRevenueRecovery for Stripebilling {} impl ConnectorIntegration @@ -569,13 +568,13 @@ impl ConnectorIntegration for Stripebil } } -#[cfg(all(feature="v2",feature="revenue_recovery"))] +#[cfg(all(feature = "v2", feature = "revenue_recovery"))] impl ConnectorIntegration< - GetAdditionalRevenueRecoveryDetails, - GetAdditionalRevenueRecoveryRequestData, - GetAdditionalRevenueRecoveryResponseData -> for Stripebilling + GetAdditionalRevenueRecoveryDetails, + GetAdditionalRevenueRecoveryRequestData, + GetAdditionalRevenueRecoveryResponseData, + > for Stripebilling { fn get_headers( &self, @@ -608,35 +607,38 @@ impl ) -> CustomResult, errors::ConnectorError> { let request = RequestBuilder::new() .method(Method::Get) - .url(&types::AdditionalRevenueRecoveryCallType::get_url(self,req, connectors)?) + .url(&types::AdditionalRevenueRecoveryCallType::get_url( + self, req, connectors, + )?) .attach_default_headers() - .headers(types::AdditionalRevenueRecoveryCallType::get_headers(self,req,connectors)?) + .headers(types::AdditionalRevenueRecoveryCallType::get_headers( + self, req, connectors, + )?) .build(); Ok(Some(request)) } - fn handle_response( &self, data: &AdditionalRevenueRecoveryDetailsRouterData, event_builder: Option<&mut ConnectorEvent>, res: Response, - ) -> CustomResult - { - let response : stripebilling::StripebillingRecoveryDetailsData = res + ) -> CustomResult { + let response: stripebilling::StripebillingRecoveryDetailsData = res .response - .parse_struct::("StripebillingRecoveryDetailsData") + .parse_struct::( + "StripebillingRecoveryDetailsData", + ) .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; - event_builder.map(|i| i.set_response_body(&response)); - router_env::logger::info!(connector_response=?response); + event_builder.map(|i| i.set_response_body(&response)); + router_env::logger::info!(connector_response=?response); - AdditionalRevenueRecoveryDetailsRouterData::try_from( ResponseRouterData { - response, - data: data.clone(), - http_code: res.status_code, - }) - + AdditionalRevenueRecoveryDetailsRouterData::try_from(ResponseRouterData { + response, + data: data.clone(), + http_code: res.status_code, + }) } fn get_error_response( @@ -644,7 +646,7 @@ impl res: Response, event_builder: Option<&mut ConnectorEvent>, ) -> CustomResult { - self.build_error_response(res,event_builder) + self.build_error_response(res, event_builder) } fn get_5xx_error_response( @@ -676,7 +678,6 @@ impl connector_transaction_id: None, }) } - } #[async_trait::async_trait] @@ -804,11 +805,11 @@ impl webhooks::IncomingWebhook for Stripebilling { &self, request: &webhooks::IncomingWebhookRequestDetails<'_>, ) -> CustomResult { - let webhook = - stripebilling::StripebillingInvoiceBody::get_invoice_webhook_data_from_body(request.body)?; + let webhook = stripebilling::StripebillingInvoiceBody::get_invoice_webhook_data_from_body( + request.body, + )?; revenue_recovery::RevenueRecoveryInvoiceData::try_from(webhook) } - } fn get_signature_elements_from_header( diff --git a/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs b/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs index 2738683769f..b45ee65adcf 100644 --- a/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs @@ -1,6 +1,5 @@ #[cfg(feature = "v2")] use std::str::FromStr; -use time::PrimitiveDateTime; use common_enums::enums; use common_utils::{errors::CustomResult, ext_traits::ByteSliceExt, types::StringMinorUnit}; @@ -15,17 +14,17 @@ use hyperswitch_domain_models::{ router_response_types::{PaymentsResponseData, RefundsResponseData}, types::{PaymentsAuthorizeRouterData, RefundsRouterData}, }; -#[cfg(all(feature="v2",feature="revenue_recovery"))] +#[cfg(all(feature = "v2", feature = "revenue_recovery"))] use hyperswitch_domain_models::{ router_flow_types::revenue_recovery::GetAdditionalRevenueRecoveryDetails, router_request_types::revenue_recovery::GetAdditionalRevenueRecoveryRequestData, router_response_types::revenue_recovery::GetAdditionalRevenueRecoveryResponseData, - types::AdditionalRevenueRecoveryDetailsRouterData + types::AdditionalRevenueRecoveryDetailsRouterData, }; - use hyperswitch_interfaces::errors; use masking::Secret; use serde::{Deserialize, Serialize}; +use time::PrimitiveDateTime; use crate::{ types::{RefundsResponseRouterData, ResponseRouterData}, @@ -308,13 +307,12 @@ pub struct StripebillingInvoiceObject { pub amount: common_utils::types::MinorUnit, } - impl StripebillingWebhookBody { pub fn get_webhook_object_from_body(body: &[u8]) -> CustomResult { let webhook_body: Self = body .parse_struct::("StripebillingWebhookBody") .change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?; - + Ok(webhook_body) } } @@ -347,139 +345,145 @@ impl TryFrom for revenue_recovery::RevenueRecoveryInvo #[derive(Serialize, Deserialize, Debug, Clone)] pub struct StripebillingRecoveryDetailsData { - #[serde(rename="id")] - pub charge_id : String, - pub status : StripebillingChargeStatus, - pub amount : common_utils::types::MinorUnit, + #[serde(rename = "id")] + pub charge_id: String, + pub status: StripebillingChargeStatus, + pub amount: common_utils::types::MinorUnit, #[serde(deserialize_with = "convert_uppercase")] - pub currency : enums::Currency, - pub customer : String, - pub payment_method : String, - pub failure_code : String, - pub failure_message : String, + pub currency: enums::Currency, + pub customer: String, + pub payment_method: String, + pub failure_code: String, + pub failure_message: String, #[serde(with = "common_utils::custom_serde::timestamp")] - pub created : PrimitiveDateTime, - pub payment_method_details : StripePaymentMethodDetails, - #[serde(rename="invoice")] - pub invoice_id : String + pub created: PrimitiveDateTime, + pub payment_method_details: StripePaymentMethodDetails, + #[serde(rename = "invoice")] + pub invoice_id: String, } - #[derive(Serialize, Deserialize, Debug, Clone)] -pub struct StripePaymentMethodDetails{ - #[serde(rename="type")] - pub type_of_payment_method : StripebillingPaymentMethod, - #[serde(rename="card")] - pub card_funding_type : StripeCardFundingTypeDetails, +pub struct StripePaymentMethodDetails { + #[serde(rename = "type")] + pub type_of_payment_method: StripebillingPaymentMethod, + #[serde(rename = "card")] + pub card_funding_type: StripeCardFundingTypeDetails, } #[derive(Serialize, Deserialize, Debug, Clone)] -#[serde(rename_all="snake_case")] +#[serde(rename_all = "snake_case")] pub enum StripebillingPaymentMethod { Card, } #[derive(Serialize, Deserialize, Debug, Clone)] -pub struct StripeCardFundingTypeDetails{ - pub funding : StripebillingFundingTypes +pub struct StripeCardFundingTypeDetails { + pub funding: StripebillingFundingTypes, } #[derive(Serialize, Deserialize, Debug, Clone)] -#[serde(rename="snake_case")] +#[serde(rename = "snake_case")] pub enum StripebillingFundingTypes { - #[serde(rename="credit")] + #[serde(rename = "credit")] Credit, - #[serde(rename="debit")] + #[serde(rename = "debit")] Debit, - #[serde(rename="prepaid")] + #[serde(rename = "prepaid")] Prepaid, - #[serde(rename="unknown")] - Unknown + #[serde(rename = "unknown")] + Unknown, } -#[derive(Serialize, Deserialize, Debug,Clone)] +#[derive(Serialize, Deserialize, Debug, Clone)] #[serde(rename_all = "snake_case")] -pub enum StripebillingChargeStatus{ +pub enum StripebillingChargeStatus { Succeeded, Failed, - Pending -} - -#[cfg(all(feature="v2",feature="revenue_recovery"))] -impl TryFrom< - ResponseRouterData< - GetAdditionalRevenueRecoveryDetails, - StripebillingRecoveryDetailsData, - GetAdditionalRevenueRecoveryRequestData, - GetAdditionalRevenueRecoveryResponseData - >> - for AdditionalRevenueRecoveryDetailsRouterData + Pending, +} + +#[cfg(all(feature = "v2", feature = "revenue_recovery"))] +impl + TryFrom< + ResponseRouterData< + GetAdditionalRevenueRecoveryDetails, + StripebillingRecoveryDetailsData, + GetAdditionalRevenueRecoveryRequestData, + GetAdditionalRevenueRecoveryResponseData, + >, + > for AdditionalRevenueRecoveryDetailsRouterData { type Error = error_stack::Report; - fn try_from(item: ResponseRouterData< - GetAdditionalRevenueRecoveryDetails, - StripebillingRecoveryDetailsData, - GetAdditionalRevenueRecoveryRequestData, - GetAdditionalRevenueRecoveryResponseData - > - ) -> Result { - let merchant_reference_id = + fn try_from( + item: ResponseRouterData< + GetAdditionalRevenueRecoveryDetails, + StripebillingRecoveryDetailsData, + GetAdditionalRevenueRecoveryRequestData, + GetAdditionalRevenueRecoveryResponseData, + >, + ) -> Result { + let merchant_reference_id = common_utils::id_type::PaymentReferenceId::from_str(&item.response.invoice_id) - .change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?; - let connector_transaction_id = Some(common_utils::types::ConnectorTransactionId::from(item - .response - .charge_id)); - + .change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?; + let connector_transaction_id = Some(common_utils::types::ConnectorTransactionId::from( + item.response.charge_id, + )); + Ok(Self { response: Ok(GetAdditionalRevenueRecoveryResponseData { status: item.response.status.into(), - amount : item.response.amount, - currency : item.response.currency, + amount: item.response.amount, + currency: item.response.currency, merchant_reference_id, - connector_account_reference_id : Some("Stripe".to_string()), - connector_transaction_id , - error_code : Some(item.response.failure_code), - error_message : Some(item.response.failure_message), - processor_payment_method_token : Some(item.response.payment_method), - connector_customer_id : Some(item.response.customer), - transaction_created_at : Some(item.response.created), - payment_method_sub_type: common_enums::PaymentMethodType::from(item.response.payment_method_details.card_funding_type.funding), - payment_method_type : common_enums::PaymentMethod::from(item.response.payment_method_details.type_of_payment_method) + connector_account_reference_id: Some("Stripe".to_string()), + connector_transaction_id, + error_code: Some(item.response.failure_code), + error_message: Some(item.response.failure_message), + processor_payment_method_token: Some(item.response.payment_method), + connector_customer_id: Some(item.response.customer), + transaction_created_at: Some(item.response.created), + payment_method_sub_type: common_enums::PaymentMethodType::from( + item.response + .payment_method_details + .card_funding_type + .funding, + ), + payment_method_type: common_enums::PaymentMethod::from( + item.response.payment_method_details.type_of_payment_method, + ), }), ..item.data }) } } -#[cfg(all(feature="v2",feature="revenue_recovery"))] +#[cfg(all(feature = "v2", feature = "revenue_recovery"))] impl From for enums::AttemptStatus { fn from(status: StripebillingChargeStatus) -> Self { match status { StripebillingChargeStatus::Succeeded => Self::Charged, - StripebillingChargeStatus::Failed - | StripebillingChargeStatus::Pending=> Self::Pending, + StripebillingChargeStatus::Failed | StripebillingChargeStatus::Pending => Self::Pending, } } } -#[cfg(all(feature="v2",feature="revenue_recovery"))] +#[cfg(all(feature = "v2", feature = "revenue_recovery"))] impl From for common_enums::PaymentMethodType { - fn from(funding : StripebillingFundingTypes) -> Self { + fn from(funding: StripebillingFundingTypes) -> Self { match funding { StripebillingFundingTypes::Credit => Self::Credit, - StripebillingFundingTypes::Debit + StripebillingFundingTypes::Debit | StripebillingFundingTypes::Prepaid - | StripebillingFundingTypes::Unknown => Self::Debit - + | StripebillingFundingTypes::Unknown => Self::Debit, } } } -#[cfg(all(feature="v2",feature="revenue_recovery"))] +#[cfg(all(feature = "v2", feature = "revenue_recovery"))] impl From for common_enums::PaymentMethod { - fn from(method : StripebillingPaymentMethod) -> Self { + fn from(method: StripebillingPaymentMethod) -> Self { match method { StripebillingPaymentMethod::Card => Self::Card, } } -} \ No newline at end of file +} diff --git a/crates/hyperswitch_connectors/src/default_implementations.rs b/crates/hyperswitch_connectors/src/default_implementations.rs index fe137ad856e..6afa113e1b2 100644 --- a/crates/hyperswitch_connectors/src/default_implementations.rs +++ b/crates/hyperswitch_connectors/src/default_implementations.rs @@ -22,6 +22,13 @@ use hyperswitch_domain_models::{ router_request_types::PayoutsData, router_response_types::PayoutsResponseData, }; +#[cfg(all(feature = "v2", feature = "revenue_recovery"))] +use hyperswitch_domain_models::{ + router_flow_types::revenue_recovery::GetAdditionalRevenueRecoveryDetails, + router_request_types::revenue_recovery::GetAdditionalRevenueRecoveryRequestData, + router_response_types::revenue_recovery::GetAdditionalRevenueRecoveryResponseData, + types::AdditionalRevenueRecoveryDetailsRouterData, +}; use hyperswitch_domain_models::{ router_flow_types::{ dispute::{Accept, Defend, Evidence}, @@ -33,8 +40,7 @@ use hyperswitch_domain_models::{ PreProcessing, Reject, SdkSessionUpdate, }, webhooks::VerifyWebhookSource, - Authenticate, AuthenticationConfirmation, - PostAuthenticate, PreAuthenticate, + Authenticate, AuthenticationConfirmation, PostAuthenticate, PreAuthenticate, }, router_request_types::{ unified_authentication_service::{ @@ -50,21 +56,11 @@ use hyperswitch_domain_models::{ SubmitEvidenceRequestData, UploadFileRequestData, VerifyWebhookSourceRequestData, }, router_response_types::{ - AcceptDisputeResponse, - DefendDisputeResponse, MandateRevokeResponseData, PaymentsResponseData, - RetrieveFileResponse, SubmitEvidenceResponse, TaxCalculationResponseData, - UploadFileResponse, VerifyWebhookSourceResponseData, + AcceptDisputeResponse, DefendDisputeResponse, MandateRevokeResponseData, + PaymentsResponseData, RetrieveFileResponse, SubmitEvidenceResponse, + TaxCalculationResponseData, UploadFileResponse, VerifyWebhookSourceResponseData, }, }; - -#[cfg(all(feature="v2",feature="revenue_recovery"))] -use hyperswitch_domain_models::{ - router_flow_types::revenue_recovery::GetAdditionalRevenueRecoveryDetails, - router_request_types::revenue_recovery::GetAdditionalRevenueRecoveryRequestData, - router_response_types::revenue_recovery::GetAdditionalRevenueRecoveryResponseData, - types::AdditionalRevenueRecoveryDetailsRouterData -}; - #[cfg(feature = "frm")] use hyperswitch_interfaces::api::fraud_check::{ FraudCheckCheckout, FraudCheckFulfillment, FraudCheckRecordReturn, FraudCheckSale, @@ -75,6 +71,8 @@ use hyperswitch_interfaces::api::payouts::{ PayoutCancel, PayoutCreate, PayoutEligibility, PayoutFulfill, PayoutQuote, PayoutRecipient, PayoutRecipientAccount, PayoutSync, }; +#[cfg(all(feature = "v2", feature = "revenue_recovery"))] +use hyperswitch_interfaces::api::revenue_recovery::AdditionalRevenueRecovery; use hyperswitch_interfaces::{ api::{ self, @@ -86,17 +84,13 @@ use hyperswitch_interfaces::{ PaymentSessionUpdate, PaymentsCompleteAuthorize, PaymentsPostProcessing, PaymentsPreProcessing, TaxCalculation, }, - ConnectorIntegration, ConnectorMandateRevoke, ConnectorRedirectResponse, UasAuthentication, - UasAuthenticationConfirmation, UasPostAuthentication, UasPreAuthentication, - UnifiedAuthenticationService, + ConnectorIntegration, ConnectorMandateRevoke, ConnectorRedirectResponse, RevenueRecovery, + UasAuthentication, UasAuthenticationConfirmation, UasPostAuthentication, + UasPreAuthentication, UnifiedAuthenticationService, }, errors::ConnectorError, - api::RevenueRecovery, }; -#[cfg(all(feature="v2",feature="revenue_recovery"))] -use hyperswitch_interfaces::api::revenue_recovery::AdditionalRevenueRecovery; - macro_rules! default_imp_for_authorize_session_token { ($($path:ident::$connector:ident),*) => { $( impl PaymentAuthorizeSessionToken for $path::$connector {} @@ -3545,7 +3539,7 @@ macro_rules! default_imp_for_revenue_recovery { }; } -default_imp_for_revenue_recovery!{ +default_imp_for_revenue_recovery! { connectors::Aci, connectors::Airwallex, connectors::Amazonpay, @@ -3627,7 +3621,7 @@ default_imp_for_revenue_recovery!{ connectors::Zsl } -#[cfg(all(feature="v2",feature="revenue_recovery"))] +#[cfg(all(feature = "v2", feature = "revenue_recovery"))] macro_rules! default_imp_for_additional_revenue_recovery_call { ($($path:ident::$connector:ident),*) => { $( impl AdditionalRevenueRecovery for $path::$connector {} @@ -3642,7 +3636,7 @@ macro_rules! default_imp_for_additional_revenue_recovery_call { }; } -#[cfg(all(feature="v2",feature="revenue_recovery"))] +#[cfg(all(feature = "v2", feature = "revenue_recovery"))] default_imp_for_additional_revenue_recovery_call!( connectors::Aci, connectors::Airwallex, diff --git a/crates/hyperswitch_domain_models/src/revenue_recovery.rs b/crates/hyperswitch_domain_models/src/revenue_recovery.rs index efdc053c4eb..4a9717a1692 100644 --- a/crates/hyperswitch_domain_models/src/revenue_recovery.rs +++ b/crates/hyperswitch_domain_models/src/revenue_recovery.rs @@ -192,27 +192,31 @@ impl From<&RevenueRecoveryInvoiceData> for api_models::payments::PaymentsCreateI } impl From for RevenueRecoveryInvoiceData { - fn from(data: GetAdditionalRevenueRecoveryResponseData)-> Self{ - Self { amount: data.amount, currency: data.currency, merchant_reference_id: data.merchant_reference_id } + fn from(data: GetAdditionalRevenueRecoveryResponseData) -> Self { + Self { + amount: data.amount, + currency: data.currency, + merchant_reference_id: data.merchant_reference_id, + } } } -impl From for RevenueRecoveryAttemptData{ - fn from(data: GetAdditionalRevenueRecoveryResponseData)-> Self { - Self { - amount: data.amount, - currency: data.currency, - merchant_reference_id: data.merchant_reference_id, - connector_transaction_id: data.connector_transaction_id, - error_code: data.error_code, - error_message: data.error_message, - processor_payment_method_token: data.processor_payment_method_token, - connector_customer_id: data.connector_customer_id, - connector_account_reference_id: data.connector_account_reference_id, - transaction_created_at: data.transaction_created_at, - status: data.status, - payment_method_type: data.payment_method_type, - payment_method_sub_type: data.payment_method_sub_type +impl From for RevenueRecoveryAttemptData { + fn from(data: GetAdditionalRevenueRecoveryResponseData) -> Self { + Self { + amount: data.amount, + currency: data.currency, + merchant_reference_id: data.merchant_reference_id, + connector_transaction_id: data.connector_transaction_id, + error_code: data.error_code, + error_message: data.error_message, + processor_payment_method_token: data.processor_payment_method_token, + connector_customer_id: data.connector_customer_id, + connector_account_reference_id: data.connector_account_reference_id, + transaction_created_at: data.transaction_created_at, + status: data.status, + payment_method_type: data.payment_method_type, + payment_method_sub_type: data.payment_method_sub_type, } } -} \ No newline at end of file +} diff --git a/crates/hyperswitch_domain_models/src/types.rs b/crates/hyperswitch_domain_models/src/types.rs index 78486a82b25..e907038ff6e 100644 --- a/crates/hyperswitch_domain_models/src/types.rs +++ b/crates/hyperswitch_domain_models/src/types.rs @@ -1,12 +1,14 @@ pub use diesel_models::types::OrderDetailsWithAmount; + use crate::{ - router_data::{AccessToken, RouterData}, router_flow_types::{ + router_data::{AccessToken, RouterData}, + router_flow_types::{ mandate_revoke::MandateRevoke, AccessTokenAuth, Authenticate, AuthenticationConfirmation, Authorize, AuthorizeSessionToken, CalculateTax, Capture, CompleteAuthorize, CreateConnectorCustomer, Execute, GetAdditionalRevenueRecoveryDetails, IncrementalAuthorization, PSync, PaymentMethodToken, PostAuthenticate, PostSessionTokens, PreAuthenticate, PreProcessing, RSync, Session, SetupMandate, Void, - }, + }, router_request_types::{ revenue_recovery::GetAdditionalRevenueRecoveryRequestData, unified_authentication_service::{ @@ -20,13 +22,12 @@ use crate::{ PaymentsIncrementalAuthorizationData, PaymentsPostSessionTokensData, PaymentsPreProcessingData, PaymentsSessionData, PaymentsSyncData, PaymentsTaxCalculationData, RefundsData, SetupMandateRequestData, - }, + }, router_response_types::{ revenue_recovery::GetAdditionalRevenueRecoveryResponseData, MandateRevokeResponseData, PaymentsResponseData, RefundsResponseData, TaxCalculationResponseData, - } + }, }; - #[cfg(feature = "payouts")] pub use crate::{router_request_types::PayoutsData, router_response_types::PayoutsResponseData}; diff --git a/crates/hyperswitch_interfaces/src/api.rs b/crates/hyperswitch_interfaces/src/api.rs index f4384653db3..e5f9978ae42 100644 --- a/crates/hyperswitch_interfaces/src/api.rs +++ b/crates/hyperswitch_interfaces/src/api.rs @@ -57,7 +57,7 @@ use serde_json::json; #[cfg(feature = "payouts")] pub use self::payouts::*; -pub use self::{payments::*, refunds::*,revenue_recovery::*}; +pub use self::{payments::*, refunds::*, revenue_recovery::*}; use crate::{ configs::Connectors, connector_integration_v2::ConnectorIntegrationV2, consts, errors, events::connector_api_logs::ConnectorEvent, metrics, types, diff --git a/crates/hyperswitch_interfaces/src/api/revenue_recovery.rs b/crates/hyperswitch_interfaces/src/api/revenue_recovery.rs index 5e600a41b9d..c598f620341 100644 --- a/crates/hyperswitch_interfaces/src/api/revenue_recovery.rs +++ b/crates/hyperswitch_interfaces/src/api/revenue_recovery.rs @@ -6,12 +6,11 @@ use hyperswitch_domain_models::{ router_response_types::revenue_recovery::GetAdditionalRevenueRecoveryResponseData, }; -use super::ConnectorIntegration; - -#[cfg(all(feature="v2",feature="revenue_recovery"))] +#[cfg(all(feature = "v2", feature = "revenue_recovery"))] use super::ConnectorCommon; +use super::ConnectorIntegration; -#[cfg(all(feature="v2",feature="revenue_recovery"))] +#[cfg(all(feature = "v2", feature = "revenue_recovery"))] /// trait RevenueRecovery pub trait RevenueRecovery: ConnectorCommon + AdditionalRevenueRecovery {} @@ -25,6 +24,6 @@ pub trait AdditionalRevenueRecovery: { } -#[cfg(not(all(feature="v2",feature="revenue_recovery")))] +#[cfg(not(all(feature = "v2", feature = "revenue_recovery")))] /// trait RevenueRecovery pub trait RevenueRecovery {} diff --git a/crates/router/src/configs/settings.rs b/crates/router/src/configs/settings.rs index a5f833e3047..6234f45851f 100644 --- a/crates/router/src/configs/settings.rs +++ b/crates/router/src/configs/settings.rs @@ -96,7 +96,7 @@ pub struct Settings { pub required_fields: RequiredFields, pub delayed_session_response: DelayedSessionConfig, pub webhook_source_verification_call: WebhookSourceVerificationCall, - pub additional_revenue_recovery_details_call: GetAdditionalRevenueRecoveryDetailsCall, + pub additional_revenue_recovery_details_call: GetAdditionalRevenueRecoveryDetailsCall, pub payment_method_auth: SecretStateContainer, pub connector_request_reference_id_config: ConnectorRequestReferenceIdConfig, #[cfg(feature = "payouts")] diff --git a/crates/router/src/core/payments/flows.rs b/crates/router/src/core/payments/flows.rs index 56fd8479baa..37040b0c090 100644 --- a/crates/router/src/core/payments/flows.rs +++ b/crates/router/src/core/payments/flows.rs @@ -12,11 +12,12 @@ pub mod session_update_flow; pub mod setup_mandate_flow; use async_trait::async_trait; +#[cfg(all(feature = "v2", feature = "revenue_recovery"))] +use hyperswitch_domain_models::router_flow_types::GetAdditionalRevenueRecoveryDetails; use hyperswitch_domain_models::{ mandates::CustomerAcceptance, router_flow_types::{ - Authenticate, AuthenticationConfirmation, - PostAuthenticate, PreAuthenticate, + Authenticate, AuthenticationConfirmation, PostAuthenticate, PreAuthenticate, }, router_request_types::PaymentsCaptureData, }; @@ -24,8 +25,6 @@ use hyperswitch_interfaces::api::{ payouts::Payouts, UasAuthentication, UasAuthenticationConfirmation, UasPostAuthentication, UasPreAuthentication, UnifiedAuthenticationService, }; -#[cfg(all(feature="v2",feature="revenue_recovery"))] -use hyperswitch_domain_models::router_flow_types::GetAdditionalRevenueRecoveryDetails; #[cfg(feature = "frm")] use crate::types::fraud_check as frm_types; @@ -2274,7 +2273,7 @@ macro_rules! default_imp_for_revenue_recovery { #[cfg(feature = "dummy_connector")] impl api::RevenueRecovery for connector::DummyConnector {} -default_imp_for_revenue_recovery!{ +default_imp_for_revenue_recovery! { connector::Adyenplatform, connector::Adyen, connector::Ebanx, @@ -2290,9 +2289,9 @@ default_imp_for_revenue_recovery!{ connector::Threedsecureio, connector::Wellsfargopayout, connector::Wise -} +} -#[cfg(all(feature="v2",feature="revenue_recovery"))] +#[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 {} @@ -2306,10 +2305,10 @@ macro_rules! default_imp_for_additional_revenue_recovery_call { )* }; } -#[cfg(all(feature="v2",feature="revenue_recovery"))] +#[cfg(all(feature = "v2", feature = "revenue_recovery"))] #[cfg(feature = "dummy_connector")] impl api::AdditionalRevenueRecovery for connector::DummyConnector {} -#[cfg(all(feature="v2",feature="revenue_recovery"))] +#[cfg(all(feature = "v2", feature = "revenue_recovery"))] #[cfg(feature = "dummy_connector")] impl services::ConnectorIntegration< @@ -2320,7 +2319,7 @@ impl { } -#[cfg(all(feature="v2",feature="revenue_recovery"))] +#[cfg(all(feature = "v2", feature = "revenue_recovery"))] default_imp_for_additional_revenue_recovery_call!( connector::Adyenplatform, connector::Adyen, diff --git a/crates/router/src/core/webhooks/incoming_v2.rs b/crates/router/src/core/webhooks/incoming_v2.rs index 11dcea09c3f..47beb39214b 100644 --- a/crates/router/src/core/webhooks/incoming_v2.rs +++ b/crates/router/src/core/webhooks/incoming_v2.rs @@ -366,7 +366,7 @@ async fn incoming_webhooks_core( &request_details, event_type, req_state, - &object_ref_id + &object_ref_id, )) .await .change_context(errors::ApiErrorResponse::WebhookProcessingFailure) diff --git a/crates/router/src/core/webhooks/recovery_incoming.rs b/crates/router/src/core/webhooks/recovery_incoming.rs index f99250b46e4..83cabf50a2f 100644 --- a/crates/router/src/core/webhooks/recovery_incoming.rs +++ b/crates/router/src/core/webhooks/recovery_incoming.rs @@ -1,24 +1,28 @@ +use std::{marker::PhantomData, str::FromStr}; + use api_models::webhooks; -use common_utils::ext_traits::AsyncExt; +use common_utils::ext_traits::{AsyncExt, ValueExt}; use error_stack::{report, ResultExt}; -use hyperswitch_domain_models::{revenue_recovery, router_flow_types::GetAdditionalRevenueRecoveryDetails, router_request_types::revenue_recovery::GetAdditionalRevenueRecoveryRequestData, router_response_types::revenue_recovery::GetAdditionalRevenueRecoveryResponseData, types::AdditionalRevenueRecoveryDetailsRouterData}; -use router_env::{instrument, tracing}; +use hyperswitch_domain_models::{ + revenue_recovery, router_flow_types::GetAdditionalRevenueRecoveryDetails, + router_request_types::revenue_recovery::GetAdditionalRevenueRecoveryRequestData, + router_response_types::revenue_recovery::GetAdditionalRevenueRecoveryResponseData, + types::AdditionalRevenueRecoveryDetailsRouterData, +}; use hyperswitch_interfaces::webhooks as interface_webhooks; -use crate::types; -use std::marker::PhantomData; -use common_utils::ext_traits::ValueExt; -use std::str::FromStr; +use router_env::{instrument, tracing}; use crate::{ core::{ errors::{self, CustomResult}, - payments::{self,helpers}, + payments::{self, helpers}, }, routes::{app::ReqState, SessionState}, services::{self, connector_integration_interface}, + types, types::{ - api::{self,ConnectorData,GetToken}, - domain + api::{self, ConnectorData, GetToken}, + domain, }, }; @@ -34,13 +38,12 @@ pub async fn recovery_incoming_webhook_flow( source_verified: bool, connector_enum: &connector_integration_interface::ConnectorEnum, merchant_connector_account: &hyperswitch_domain_models::merchant_connector_account::MerchantConnectorAccount, - connector_name : &str, + connector_name: &str, request_details: &hyperswitch_interfaces::webhooks::IncomingWebhookRequestDetails<'_>, event_type: webhooks::IncomingWebhookEvent, req_state: ReqState, - object_ref_id : &webhooks::ObjectReferenceId + object_ref_id: &webhooks::ObjectReferenceId, ) -> CustomResult { - // 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!( @@ -48,59 +51,51 @@ pub async fn recovery_incoming_webhook_flow( )) })?; - let connectors_with_additional_recovery_details_call = &state.conf.additional_revenue_recovery_details_call; + let connectors_with_additional_recovery_details_call = + &state.conf.additional_revenue_recovery_details_call; let connector = api_models::enums::Connector::from_str(connector_name) .change_context(errors::RevenueRecoveryError::InvoiceWebhookProcessingFailed) - .attach_printable_lazy(|| { - format!("unable to parse connector name {connector_name:?}") - })?; + .attach_printable_lazy(|| format!("unable to parse connector name {connector_name:?}"))?; - let recovery_details = - if connectors_with_additional_recovery_details_call + let recovery_details = if connectors_with_additional_recovery_details_call .connectors_with_additional_revenue_recovery_details_call .contains(&connector) - { - - let additional_revenue_recovery_id = match object_ref_id { - webhooks::ObjectReferenceId::AdditionalRevenueRecoveryId( - webhooks::AdditionalRevenueRecoveryIdType::AdditionalRevenueRecoveryCallId(ref id) - ) => Some(id.as_str()), - _ => None, - }; + { + let additional_revenue_recovery_id = match object_ref_id { + webhooks::ObjectReferenceId::AdditionalRevenueRecoveryId( + webhooks::AdditionalRevenueRecoveryIdType::AdditionalRevenueRecoveryCallId(ref id), + ) => Some(id.as_str()), + _ => None, + }; - let additional_call_response = handle_additional_recovery_details_call( - connector_enum, - &state, - &merchant_account, - merchant_connector_account, - connector_name, - additional_revenue_recovery_id.unwrap_or("fake_id") - ).await?; - - Some(additional_call_response) + let additional_call_response = handle_additional_recovery_details_call( + connector_enum, + &state, + &merchant_account, + merchant_connector_account, + connector_name, + additional_revenue_recovery_id.unwrap_or("fake_id"), + ) + .await?; + + Some(additional_call_response) + } else { + None + }; - } else { - None - }; - let invoice_details = match recovery_details.clone() { - Some(data)=> { - RevenueRecoveryInvoice( - revenue_recovery::RevenueRecoveryInvoiceData::from(data.clone()) - ) - }, - None => - { - RevenueRecoveryInvoice( + Some(data) => RevenueRecoveryInvoice(revenue_recovery::RevenueRecoveryInvoiceData::from( + data.clone(), + )), + None => RevenueRecoveryInvoice( 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")?, - ) - } + ), }; // Fetch the intent using merchant reference id, if not found create new intent. @@ -127,29 +122,23 @@ pub async fn recovery_incoming_webhook_flow( }) .await?; - let payment_attempt = match event_type.is_recovery_transaction_event() { true => { let invoice_transaction_details = match recovery_details.clone() { - Some(data) => - { - RevenueRecoveryAttempt( - revenue_recovery::RevenueRecoveryAttemptData::from(data) - ) + Some(data) => { + RevenueRecoveryAttempt(revenue_recovery::RevenueRecoveryAttemptData::from(data)) } - None => - { - RevenueRecoveryAttempt( + None => RevenueRecoveryAttempt( interface_webhooks::IncomingWebhook::get_revenue_recovery_attempt_details( connector_enum, request_details, ) - .change_context(errors::RevenueRecoveryError::TransactionWebhookProcessingFailed)?, - ) - } + .change_context( + errors::RevenueRecoveryError::TransactionWebhookProcessingFailed, + )?, + ), }; - invoice_transaction_details .get_payment_attempt( &state, @@ -385,9 +374,8 @@ async fn handle_additional_recovery_details_call( merchant_account: &domain::MerchantAccount, merchant_connector_account: &hyperswitch_domain_models::merchant_connector_account::MerchantConnectorAccount, connector_name: &str, - id : &str + id: &str, ) -> CustomResult { - let connector_data = ConnectorData::get_connector_by_name( &state.conf.connectors, connector_name, @@ -397,7 +385,6 @@ async fn handle_additional_recovery_details_call( .change_context(errors::RevenueRecoveryError::AdditionalRevenueRecoveryCallFailed) .attach_printable("invalid connector name received in payment attempt")?; - let connector_integration: services::BoxedGetAdditionalRecoveryRecoveryDetailsIntegrationInterface< GetAdditionalRevenueRecoveryDetails, GetAdditionalRevenueRecoveryRequestData, @@ -441,7 +428,7 @@ const IRRELEVANT_ATTEMPT_ID_IN_ADDITIONAL_REVENUE_RECOVERY_CALL_FLOW: &str = "irrelevant_attempt_id_in_additional_revenue_recovery_flow"; const IRRELEVANT_CONNECTOR_REQUEST_REFERENCE_ID_IN_ADDITIONAL_REVENUE_RECOVERY_CALL: &str = -"irrelevant_connector_request_reference_id_in_additional_revenue_recovery_flow"; + "irrelevant_connector_request_reference_id_in_additional_revenue_recovery_flow"; async fn construct_router_data_for_additional_call( state: &SessionState, @@ -449,14 +436,12 @@ async fn construct_router_data_for_additional_call( merchant_connector_account: &hyperswitch_domain_models::merchant_connector_account::MerchantConnectorAccount, merchant_account: &domain::MerchantAccount, additional_revenue_recovery_id: &str, -) -> CustomResult{ - +) -> CustomResult { 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::AdditionalRevenueRecoveryCallFailed)?; - let router_data = types::RouterData { flow: PhantomData, @@ -464,9 +449,11 @@ async fn construct_router_data_for_additional_call( connector: connector_name.to_string(), customer_id: None, tenant_id: state.tenant.tenant_id.clone(), - payment_id: common_utils::id_type::PaymentId::get_irrelevant_id("additional revenue recovery details call flow") - .get_string_repr() - .to_owned(), + payment_id: common_utils::id_type::PaymentId::get_irrelevant_id( + "additional revenue recovery details call flow", + ) + .get_string_repr() + .to_owned(), attempt_id: IRRELEVANT_ATTEMPT_ID_IN_ADDITIONAL_REVENUE_RECOVERY_CALL_FLOW.to_string(), status: diesel_models::enums::AttemptStatus::default(), payment_method: diesel_models::enums::PaymentMethod::default(), @@ -478,8 +465,8 @@ async fn construct_router_data_for_additional_call( connector_wallets_details: None, amount_captured: None, minor_amount_captured: None, - request : GetAdditionalRevenueRecoveryRequestData{ - additional_revenue_recovery_id : additional_revenue_recovery_id.to_string() + request: GetAdditionalRevenueRecoveryRequestData { + additional_revenue_recovery_id: additional_revenue_recovery_id.to_string(), }, response: Err(types::ErrorResponse::default()), access_token: None, @@ -490,7 +477,8 @@ async fn construct_router_data_for_additional_call( recurring_mandate_payment_data: None, preprocessing_id: None, connector_request_reference_id: - IRRELEVANT_CONNECTOR_REQUEST_REFERENCE_ID_IN_ADDITIONAL_REVENUE_RECOVERY_CALL.to_string(), + IRRELEVANT_CONNECTOR_REQUEST_REFERENCE_ID_IN_ADDITIONAL_REVENUE_RECOVERY_CALL + .to_string(), #[cfg(feature = "payouts")] payout_method_data: None, #[cfg(feature = "payouts")] @@ -514,4 +502,4 @@ async fn construct_router_data_for_additional_call( psd2_sca_exemption_type: None, }; Ok(router_data) -} \ No newline at end of file +} diff --git a/crates/router/src/services/conversion_impls.rs b/crates/router/src/services/conversion_impls.rs index 22867b00056..007e1a91334 100644 --- a/crates/router/src/services/conversion_impls.rs +++ b/crates/router/src/services/conversion_impls.rs @@ -9,7 +9,9 @@ use hyperswitch_domain_models::{ router_data::{self, RouterData}, router_data_v2::{ flow_common_types::{ - AccessTokenFlowData, DisputesFlowData, ExternalAuthenticationFlowData, FilesFlowData, GetAdditionalRevenueRecoveryFlowCommonData, MandateRevokeFlowData, PaymentFlowData, RefundFlowData, UasFlowData, WebhookSourceVerifyData + AccessTokenFlowData, DisputesFlowData, ExternalAuthenticationFlowData, FilesFlowData, + GetAdditionalRevenueRecoveryFlowCommonData, MandateRevokeFlowData, PaymentFlowData, + RefundFlowData, UasFlowData, WebhookSourceVerifyData, }, RouterDataV2, }, @@ -762,30 +764,31 @@ impl RouterDataConversion for UasFlowD } } -impl RouterDataConversion for GetAdditionalRevenueRecoveryFlowCommonData { - +impl RouterDataConversion + for GetAdditionalRevenueRecoveryFlowCommonData +{ fn from_old_router_data( old_router_data: &RouterData, ) -> errors::CustomResult, errors::ConnectorError> where - Self: Sized + Self: Sized, { - let resource_common_data = Self{}; - Ok(RouterDataV2{ - flow : std::marker::PhantomData, - tenant_id: old_router_data.tenant_id.clone(), - 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(), - }) + let resource_common_data = Self {}; + Ok(RouterDataV2 { + flow: std::marker::PhantomData, + tenant_id: old_router_data.tenant_id.clone(), + 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, ) -> errors::CustomResult, errors::ConnectorError> where - Self: Sized + Self: Sized, { let router_data = get_default_router_data( new_router_data.tenant_id.clone(), @@ -794,7 +797,5 @@ impl RouterDataConversion for GetAddit new_router_data.response, ); Ok(router_data) - - } - + } } diff --git a/crates/router/src/types/api.rs b/crates/router/src/types/api.rs index 48d596c9f24..1a05ea068ab 100644 --- a/crates/router/src/types/api.rs +++ b/crates/router/src/types/api.rs @@ -526,9 +526,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))) From ec4aa4313c93cd21334de6214a4497bb8eae05f7 Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Fri, 7 Mar 2025 19:51:12 +0530 Subject: [PATCH 37/83] Switch default feature from v2 to v1 --- crates/router/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/router/Cargo.toml b/crates/router/Cargo.toml index 6537c268591..1e45219597f 100644 --- a/crates/router/Cargo.toml +++ b/crates/router/Cargo.toml @@ -9,7 +9,7 @@ readme = "README.md" license.workspace = true [features] -default = ["common_default", "v2"] +default = ["common_default", "v1"] common_default = ["kv_store", "stripe", "oltp", "olap", "accounts_cache", "dummy_connector", "payouts", "payout_retry", "retry", "frm", "tls", "partial-auth", "km_forward_x_request_id"] olap = ["hyperswitch_domain_models/olap", "storage_impl/olap", "scheduler/olap", "api_models/olap", "dep:analytics"] tls = ["actix-web/rustls-0_22"] From b1a2f3aa8124da429ca979628d6c06b9e28447c1 Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Mon, 10 Mar 2025 17:22:26 +0530 Subject: [PATCH 38/83] Adds Hipay and Juspaythreedsserver to revenue recovery flow --- .../connectors/stripebilling/transformers.rs | 6 ++--- .../src/default_implementations.rs | 3 ++- .../router_response_types/revenue_recovery.rs | 6 ++--- crates/router/src/core/errors.rs | 4 ++-- .../src/core/webhooks/recovery_incoming.rs | 22 ++++++++++--------- 5 files changed, 22 insertions(+), 19 deletions(-) diff --git a/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs b/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs index b45ee65adcf..240d44dbd04 100644 --- a/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs @@ -435,12 +435,12 @@ impl amount: item.response.amount, currency: item.response.currency, merchant_reference_id, - connector_account_reference_id: Some("Stripe".to_string()), + connector_account_reference_id: "stripebilling".to_string(), connector_transaction_id, error_code: Some(item.response.failure_code), error_message: Some(item.response.failure_message), - processor_payment_method_token: Some(item.response.payment_method), - connector_customer_id: Some(item.response.customer), + processor_payment_method_token: item.response.payment_method, + connector_customer_id: item.response.customer, transaction_created_at: Some(item.response.created), payment_method_sub_type: common_enums::PaymentMethodType::from( item.response diff --git a/crates/hyperswitch_connectors/src/default_implementations.rs b/crates/hyperswitch_connectors/src/default_implementations.rs index aea36c6e3ea..85ca7429239 100644 --- a/crates/hyperswitch_connectors/src/default_implementations.rs +++ b/crates/hyperswitch_connectors/src/default_implementations.rs @@ -27,7 +27,6 @@ use hyperswitch_domain_models::{ router_flow_types::revenue_recovery::GetAdditionalRevenueRecoveryDetails, router_request_types::revenue_recovery::GetAdditionalRevenueRecoveryRequestData, router_response_types::revenue_recovery::GetAdditionalRevenueRecoveryResponseData, - types::AdditionalRevenueRecoveryDetailsRouterData, }; use hyperswitch_domain_models::{ router_flow_types::{ @@ -3742,9 +3741,11 @@ default_imp_for_additional_revenue_recovery_call!( connectors::Globepay, connectors::Gocardless, connectors::Helcim, + connectors::Hipay, connectors::Iatapay, connectors::Inespay, connectors::Itaubank, + connectors::Juspaythreedsserver, connectors::Jpmorgan, connectors::Klarna, connectors::Nomupay, diff --git a/crates/hyperswitch_domain_models/src/router_response_types/revenue_recovery.rs b/crates/hyperswitch_domain_models/src/router_response_types/revenue_recovery.rs index 7be9d9c9502..bf589471425 100644 --- a/crates/hyperswitch_domain_models/src/router_response_types/revenue_recovery.rs +++ b/crates/hyperswitch_domain_models/src/router_response_types/revenue_recovery.rs @@ -15,11 +15,11 @@ pub struct GetAdditionalRevenueRecoveryResponseData { /// error message sent by billing connector. pub error_message: Option, /// mandate token at payment processor end. - pub processor_payment_method_token: Option, + pub processor_payment_method_token: String, /// customer id at payment connector for which mandate is attached. - pub connector_customer_id: Option, + pub connector_customer_id: String, /// Payment gateway identifier id at billing processor. - pub connector_account_reference_id: Option, + pub connector_account_reference_id: String, /// timestamp at which transaction has been created at billing connector pub transaction_created_at: Option, /// transaction status at billing connector equivalent to payment attempt status. diff --git a/crates/router/src/core/errors.rs b/crates/router/src/core/errors.rs index 6a1500b8913..f0c02b24832 100644 --- a/crates/router/src/core/errors.rs +++ b/crates/router/src/core/errors.rs @@ -483,8 +483,8 @@ pub enum RevenueRecoveryError { PaymentIntentCreateFailed, #[error("Source verification failed for billing connector")] WebhookAuthenticationFailed, - #[error("Payment merchant connector account not found using acccount reference id")] + #[error("Payment merchant connector account not found using account reference id")] PaymentMerchantConnectorAccountNotFound, - #[error("Additional Revenue Recovery Call Failed")] + #[error("Additional revenue recovery call failed")] AdditionalRevenueRecoveryCallFailed, } diff --git a/crates/router/src/core/webhooks/recovery_incoming.rs b/crates/router/src/core/webhooks/recovery_incoming.rs index 028382fa687..fe7dafe2611 100644 --- a/crates/router/src/core/webhooks/recovery_incoming.rs +++ b/crates/router/src/core/webhooks/recovery_incoming.rs @@ -37,13 +37,12 @@ pub async fn recovery_incoming_webhook_flow( _webhook_details: api::IncomingWebhookDetails, source_verified: bool, connector_enum: &connector_integration_interface::ConnectorEnum, - merchant_connector_account: &hyperswitch_domain_models::merchant_connector_account::MerchantConnectorAccount, + 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, object_ref_id: &webhooks::ObjectReferenceId, - billing_connector_account: domain::MerchantConnectorAccount, ) -> CustomResult { // 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, || { @@ -71,10 +70,9 @@ pub async fn recovery_incoming_webhook_flow( }; let additional_call_response = handle_additional_recovery_details_call( - connector_enum, &state, &merchant_account, - merchant_connector_account, + &billing_connector_account, connector_name, additional_revenue_recovery_id.unwrap_or("fake_id"), ) @@ -213,7 +211,6 @@ pub async fn recovery_incoming_webhook_flow( } } } - pub struct RevenueRecoveryInvoice(revenue_recovery::RevenueRecoveryInvoiceData); pub struct RevenueRecoveryAttempt(revenue_recovery::RevenueRecoveryAttemptData); @@ -470,10 +467,15 @@ impl RevenueRecoveryAttempt { key_store: &domain::MerchantKeyStore, billing_connector_account: &domain::MerchantConnectorAccount, ) -> CustomResult, errors::RevenueRecoveryError> { - let payment_merchant_connector_account_id = billing_connector_account - .get_payment_merchant_connector_account_id_using_account_reference_id( - self.0.connector_account_reference_id.clone(), - ); + let payment_merchant_connector_account_id = match self.0.connector_account_reference_id.clone() == "stripebilling".to_string() { + true => Some(billing_connector_account.get_id()), + false => { + billing_connector_account + .get_payment_merchant_connector_account_id_using_account_reference_id( + self.0.connector_account_reference_id.clone(), + ) + } + }; let db = &*state.store; let key_manager_state = &(state).into(); let payment_merchant_connector_account = payment_merchant_connector_account_id @@ -493,7 +495,6 @@ impl RevenueRecoveryAttempt { } async fn handle_additional_recovery_details_call( - connector: &connector_integration_interface::ConnectorEnum, state: &SessionState, merchant_account: &domain::MerchantAccount, merchant_connector_account: &hyperswitch_domain_models::merchant_connector_account::MerchantConnectorAccount, @@ -627,3 +628,4 @@ async fn construct_router_data_for_additional_call( }; Ok(router_data) } + From 8c5f05d18aa73800753e8c1bfe0cb3270a7042fb Mon Sep 17 00:00:00 2001 From: "hyperswitch-bot[bot]" <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Date: Mon, 10 Mar 2025 12:04:51 +0000 Subject: [PATCH 39/83] chore: run formatter --- .../src/core/webhooks/recovery_incoming.rs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/crates/router/src/core/webhooks/recovery_incoming.rs b/crates/router/src/core/webhooks/recovery_incoming.rs index fe7dafe2611..49d54406010 100644 --- a/crates/router/src/core/webhooks/recovery_incoming.rs +++ b/crates/router/src/core/webhooks/recovery_incoming.rs @@ -467,15 +467,14 @@ impl RevenueRecoveryAttempt { key_store: &domain::MerchantKeyStore, billing_connector_account: &domain::MerchantConnectorAccount, ) -> CustomResult, errors::RevenueRecoveryError> { - let payment_merchant_connector_account_id = match self.0.connector_account_reference_id.clone() == "stripebilling".to_string() { - true => Some(billing_connector_account.get_id()), - false => { - billing_connector_account - .get_payment_merchant_connector_account_id_using_account_reference_id( - self.0.connector_account_reference_id.clone(), - ) - } - }; + let payment_merchant_connector_account_id = + match self.0.connector_account_reference_id.clone() == "stripebilling".to_string() { + true => Some(billing_connector_account.get_id()), + false => billing_connector_account + .get_payment_merchant_connector_account_id_using_account_reference_id( + self.0.connector_account_reference_id.clone(), + ), + }; let db = &*state.store; let key_manager_state = &(state).into(); let payment_merchant_connector_account = payment_merchant_connector_account_id @@ -628,4 +627,3 @@ async fn construct_router_data_for_additional_call( }; Ok(router_data) } - From 55347ff388af3eef4125a99c2fc37fb44cac266d Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Tue, 11 Mar 2025 18:03:41 +0530 Subject: [PATCH 40/83] resolve stripebilling payment mca issue --- crates/router/src/core/webhooks/recovery_incoming.rs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/crates/router/src/core/webhooks/recovery_incoming.rs b/crates/router/src/core/webhooks/recovery_incoming.rs index 49d54406010..5a94f0f4e3c 100644 --- a/crates/router/src/core/webhooks/recovery_incoming.rs +++ b/crates/router/src/core/webhooks/recovery_incoming.rs @@ -467,14 +467,10 @@ impl RevenueRecoveryAttempt { key_store: &domain::MerchantKeyStore, billing_connector_account: &domain::MerchantConnectorAccount, ) -> CustomResult, errors::RevenueRecoveryError> { - let payment_merchant_connector_account_id = - match self.0.connector_account_reference_id.clone() == "stripebilling".to_string() { - true => Some(billing_connector_account.get_id()), - false => billing_connector_account - .get_payment_merchant_connector_account_id_using_account_reference_id( - self.0.connector_account_reference_id.clone(), - ), - }; + let payment_merchant_connector_account_id = billing_connector_account + .get_payment_merchant_connector_account_id_using_account_reference_id( + self.0.connector_account_reference_id.clone(), + ); let db = &*state.store; let key_manager_state = &(state).into(); let payment_merchant_connector_account = payment_merchant_connector_account_id From c234e270efab5d70cfe532ddae0ef306ac85301c Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Wed, 12 Mar 2025 15:49:41 +0530 Subject: [PATCH 41/83] resolve spell check --- crates/hyperswitch_connectors/src/connectors/stripebilling.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/hyperswitch_connectors/src/connectors/stripebilling.rs b/crates/hyperswitch_connectors/src/connectors/stripebilling.rs index 3452d2be85c..ad455154c71 100644 --- a/crates/hyperswitch_connectors/src/connectors/stripebilling.rs +++ b/crates/hyperswitch_connectors/src/connectors/stripebilling.rs @@ -797,7 +797,7 @@ impl webhooks::IncomingWebhook for Stripebilling { &self, _request: &webhooks::IncomingWebhookRequestDetails<'_>, ) -> CustomResult { - // since stripe requires an additional call we dont need to implement this function beacuse we get the recovery data from additional call itself + // since stripe requires an additional call we dont need to implement this function because we get the recovery data from additional call itself Err(report!(errors::ConnectorError::WebhooksNotImplemented)) } #[cfg(all(feature = "revenue_recovery", feature = "v2"))] From 9fe1b4e86dfb9d0131fdeb1642a5b73555c53a64 Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Thu, 13 Mar 2025 13:13:46 +0530 Subject: [PATCH 42/83] refactor hanging functions in recoevry_incoming --- .../src/connectors/stripebilling.rs | 30 -- .../connectors/stripebilling/transformers.rs | 9 +- .../src/core/webhooks/recovery_incoming.rs | 324 ++++++++++-------- 3 files changed, 186 insertions(+), 177 deletions(-) diff --git a/crates/hyperswitch_connectors/src/connectors/stripebilling.rs b/crates/hyperswitch_connectors/src/connectors/stripebilling.rs index ad455154c71..3a812e075fc 100644 --- a/crates/hyperswitch_connectors/src/connectors/stripebilling.rs +++ b/crates/hyperswitch_connectors/src/connectors/stripebilling.rs @@ -648,36 +648,6 @@ impl ) -> CustomResult { self.build_error_response(res, event_builder) } - - fn get_5xx_error_response( - &self, - res: Response, - event_builder: Option<&mut ConnectorEvent>, - ) -> CustomResult { - event_builder.map(|event| event.set_error(serde_json::json!({"error": res.response.escape_ascii().to_string(), "status_code": res.status_code}))); - let error_message = match res.status_code { - 500 => "internal_server_error", - 501 => "not_implemented", - 502 => "bad_gateway", - 503 => "service_unavailable", - 504 => "gateway_timeout", - 505 => "http_version_not_supported", - 506 => "variant_also_negotiates", - 507 => "insufficient_storage", - 508 => "loop_detected", - 510 => "not_extended", - 511 => "network_authentication_required", - _ => "unknown_error", - }; - Ok(ErrorResponse { - code: res.status_code.to_string(), - message: error_message.to_string(), - reason: String::from_utf8(res.response.to_vec()).ok(), - status_code: res.status_code, - attempt_status: None, - connector_transaction_id: None, - }) - } } #[async_trait::async_trait] diff --git a/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs b/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs index 240d44dbd04..b20e06d945b 100644 --- a/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs @@ -402,6 +402,12 @@ pub enum StripebillingChargeStatus { Pending, } +#[cfg(all(feature = "v2", feature = "revenue_recovery"))] +// This is the default hard coded mca Id to find the stripe account associated with the stripe biliing +// Context : Since we dont have the concept of connector_reference_id in stripebilling because payments always go through stripe. +// While creating stripebilling we will hard code the stripe mca id to string "stripebilling" in mca featrue metadata. So we have to pass the same as account_reference_id here in response. +const MCA_ID_IDENTIFIER_FOR_STRIPE_IN_STRIPEBILLING_MCA_FEAATURE_METADATA: &str = "stripebilling"; + #[cfg(all(feature = "v2", feature = "revenue_recovery"))] impl TryFrom< @@ -435,7 +441,8 @@ impl amount: item.response.amount, currency: item.response.currency, merchant_reference_id, - connector_account_reference_id: "stripebilling".to_string(), + connector_account_reference_id: + MCA_ID_IDENTIFIER_FOR_STRIPE_IN_STRIPEBILLING_MCA_FEAATURE_METADATA.to_string(), connector_transaction_id, error_code: Some(item.response.failure_code), error_message: Some(item.response.failure_message), diff --git a/crates/router/src/core/webhooks/recovery_incoming.rs b/crates/router/src/core/webhooks/recovery_incoming.rs index 5a94f0f4e3c..fcc375d0348 100644 --- a/crates/router/src/core/webhooks/recovery_incoming.rs +++ b/crates/router/src/core/webhooks/recovery_incoming.rs @@ -69,25 +69,25 @@ pub async fn recovery_incoming_webhook_flow( _ => None, }; - let additional_call_response = handle_additional_recovery_details_call( - &state, - &merchant_account, - &billing_connector_account, - connector_name, - additional_revenue_recovery_id.unwrap_or("fake_id"), - ) - .await?; + let additional_call_response = + AdditionalRevenueRecoveryResponse::handle_additional_recovery_details_call( + &state, + &merchant_account, + &billing_connector_account, + connector_name, + additional_revenue_recovery_id.unwrap_or("fake_id"), + ) + .await? + .get_additional_revenue_recovery_call_response(); Some(additional_call_response) } else { None }; - let invoice_details = match recovery_details.clone() { - Some(data) => RevenueRecoveryInvoice(revenue_recovery::RevenueRecoveryInvoiceData::from( - data.clone(), - )), - None => RevenueRecoveryInvoice( + // 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 fetchs from Incoming webhook + let invoice_details = recovery_details.clone().map_or( + RevenueRecoveryInvoice( interface_webhooks::IncomingWebhook::get_revenue_recovery_invoice_details( connector_enum, request_details, @@ -95,7 +95,12 @@ pub async fn recovery_incoming_webhook_flow( .change_context(errors::RevenueRecoveryError::InvoiceWebhookProcessingFailed) .attach_printable("Failed while getting revenue recovery invoice details")?, ), - }; + |data| { + RevenueRecoveryInvoice(revenue_recovery::RevenueRecoveryInvoiceData::from( + data.clone(), + )) + }, + ); // Fetch the intent using merchant reference id, if not found create new intent. let payment_intent = invoice_details @@ -123,20 +128,25 @@ pub async fn recovery_incoming_webhook_flow( let payment_attempt = match event_type.is_recovery_transaction_event() { true => { - let invoice_transaction_details = match recovery_details.clone() { - Some(data) => { - RevenueRecoveryAttempt(revenue_recovery::RevenueRecoveryAttemptData::from(data)) - } - None => RevenueRecoveryAttempt( + // 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 fetchs from Incoming webhook + let invoice_transaction_details = recovery_details.map_or( + RevenueRecoveryAttempt( 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", )?, ), - }; + |data| { + RevenueRecoveryAttempt(revenue_recovery::RevenueRecoveryAttemptData::from(data)) + }, + ); + // 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( @@ -489,137 +499,159 @@ impl RevenueRecoveryAttempt { } } -async fn handle_additional_recovery_details_call( - state: &SessionState, - merchant_account: &domain::MerchantAccount, - merchant_connector_account: &hyperswitch_domain_models::merchant_connector_account::MerchantConnectorAccount, - connector_name: &str, - id: &str, -) -> CustomResult { - let connector_data = ConnectorData::get_connector_by_name( - &state.conf.connectors, - connector_name, - GetToken::Connector, - None, - ) - .change_context(errors::RevenueRecoveryError::AdditionalRevenueRecoveryCallFailed) - .attach_printable("invalid connector name received in payment attempt")?; - - let connector_integration: services::BoxedGetAdditionalRecoveryRecoveryDetailsIntegrationInterface< - GetAdditionalRevenueRecoveryDetails, - GetAdditionalRevenueRecoveryRequestData, - GetAdditionalRevenueRecoveryResponseData - > = connector_data.connector.get_connector_integration(); - - let router_data = construct_router_data_for_additional_call( - state, - connector_name, - merchant_connector_account, - merchant_account, - id, - ) - .await - .change_context(errors::RevenueRecoveryError::AdditionalRevenueRecoveryCallFailed) - .attach_printable("Failed while constructing additional recovery details call router data")?; - - let response = services::execute_connector_processing_step( - state, - connector_integration, - &router_data, - payments::CallConnectorAction::Trigger, - None, - ) - .await - .change_context(errors::RevenueRecoveryError::AdditionalRevenueRecoveryCallFailed) - .attach_printable("Failed while calling the API")?; - - let additional_recovery_details = match response.response { - Ok(response) => Ok(response), - error @ Err(_) => { - router_env::logger::error!(?error); - Err(errors::RevenueRecoveryError::AdditionalRevenueRecoveryCallFailed) - .attach_printable("failed to fetch payment intent recovery webhook flow") - } - }?; - Ok(additional_recovery_details) -} - const IRRELEVANT_ATTEMPT_ID_IN_ADDITIONAL_REVENUE_RECOVERY_CALL_FLOW: &str = "irrelevant_attempt_id_in_additional_revenue_recovery_flow"; const IRRELEVANT_CONNECTOR_REQUEST_REFERENCE_ID_IN_ADDITIONAL_REVENUE_RECOVERY_CALL: &str = "irrelevant_connector_request_reference_id_in_additional_revenue_recovery_flow"; -async fn construct_router_data_for_additional_call( - state: &SessionState, - connector_name: &str, - merchant_connector_account: &hyperswitch_domain_models::merchant_connector_account::MerchantConnectorAccount, - merchant_account: &domain::MerchantAccount, - additional_revenue_recovery_id: &str, -) -> CustomResult { - 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::AdditionalRevenueRecoveryCallFailed)?; - - let router_data = types::RouterData { - flow: PhantomData, - merchant_id: merchant_account.get_id().clone(), - connector: connector_name.to_string(), - customer_id: None, - tenant_id: state.tenant.tenant_id.clone(), - payment_id: common_utils::id_type::PaymentId::get_irrelevant_id( - "additional revenue recovery details call flow", +pub struct AdditionalRevenueRecoveryResponse(GetAdditionalRevenueRecoveryResponseData); +pub struct AdditionalRevenueRecoveryRouterData(AdditionalRevenueRecoveryDetailsRouterData); + +impl AdditionalRevenueRecoveryResponse { + async fn handle_additional_recovery_details_call( + state: &SessionState, + merchant_account: &domain::MerchantAccount, + merchant_connector_account: &hyperswitch_domain_models::merchant_connector_account::MerchantConnectorAccount, + connector_name: &str, + id: &str, + ) -> CustomResult { + let connector_data = ConnectorData::get_connector_by_name( + &state.conf.connectors, + connector_name, + GetToken::Connector, + None, ) - .get_string_repr() - .to_owned(), - attempt_id: IRRELEVANT_ATTEMPT_ID_IN_ADDITIONAL_REVENUE_RECOVERY_CALL_FLOW.to_string(), - status: diesel_models::enums::AttemptStatus::default(), - payment_method: diesel_models::enums::PaymentMethod::default(), - connector_auth_type: auth_type, - description: None, - address: hyperswitch_domain_models::payment_address::PaymentAddress::default(), - auth_type: diesel_models::enums::AuthenticationType::default(), - connector_meta_data: None, - connector_wallets_details: None, - amount_captured: None, - minor_amount_captured: None, - request: GetAdditionalRevenueRecoveryRequestData { - additional_revenue_recovery_id: additional_revenue_recovery_id.to_string(), - }, - response: Err(types::ErrorResponse::default()), - access_token: None, - session_token: None, - reference_id: None, - payment_method_token: None, - connector_customer: None, - recurring_mandate_payment_data: None, - preprocessing_id: None, - connector_request_reference_id: - IRRELEVANT_CONNECTOR_REQUEST_REFERENCE_ID_IN_ADDITIONAL_REVENUE_RECOVERY_CALL - .to_string(), - #[cfg(feature = "payouts")] - payout_method_data: None, - #[cfg(feature = "payouts")] - quote_id: None, - test_mode: None, - payment_method_balance: None, - payment_method_status: None, - connector_api_version: None, - connector_http_status_code: None, - external_latency: None, - apple_pay_flow: None, - frm_metadata: None, - refund_id: None, - dispute_id: None, - connector_response: None, - integrity_check: Ok(()), - additional_merchant_data: None, - header_payload: None, - connector_mandate_request_reference_id: None, - authentication_id: None, - psd2_sca_exemption_type: None, - }; - Ok(router_data) + .change_context(errors::RevenueRecoveryError::AdditionalRevenueRecoveryCallFailed) + .attach_printable("invalid connector name received in payment attempt")?; + + let connector_integration: services::BoxedGetAdditionalRecoveryRecoveryDetailsIntegrationInterface< + GetAdditionalRevenueRecoveryDetails, + GetAdditionalRevenueRecoveryRequestData, + GetAdditionalRevenueRecoveryResponseData + > = connector_data.connector.get_connector_integration(); + + let router_data = + AdditionalRevenueRecoveryRouterData::construct_router_data_for_additional_call( + state, + connector_name, + merchant_connector_account, + merchant_account, + id, + ) + .await + .change_context(errors::RevenueRecoveryError::AdditionalRevenueRecoveryCallFailed) + .attach_printable( + "Failed while constructing additional recovery details call router data", + )? + .get_additional_call_router_data(); + + let response = services::execute_connector_processing_step( + state, + connector_integration, + &router_data, + payments::CallConnectorAction::Trigger, + None, + ) + .await + .change_context(errors::RevenueRecoveryError::AdditionalRevenueRecoveryCallFailed) + .attach_printable("Failed while fetching additional revenue recovery details")?; + + let additional_recovery_details = match response.response { + Ok(response) => Ok(response), + error @ Err(_) => { + router_env::logger::error!(?error); + Err(errors::RevenueRecoveryError::AdditionalRevenueRecoveryCallFailed) + .attach_printable("Failed while fetching additional revenue recovery details") + } + }?; + Ok(Self(additional_recovery_details)) + } + + fn get_additional_revenue_recovery_call_response( + self, + ) -> GetAdditionalRevenueRecoveryResponseData { + self.0 + } +} + +impl AdditionalRevenueRecoveryRouterData { + async fn construct_router_data_for_additional_call( + state: &SessionState, + connector_name: &str, + merchant_connector_account: &hyperswitch_domain_models::merchant_connector_account::MerchantConnectorAccount, + merchant_account: &domain::MerchantAccount, + additional_revenue_recovery_id: &str, + ) -> CustomResult { + 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::AdditionalRevenueRecoveryCallFailed)?; + + let router_data = types::RouterData { + flow: PhantomData, + merchant_id: merchant_account.get_id().clone(), + connector: connector_name.to_string(), + customer_id: None, + tenant_id: state.tenant.tenant_id.clone(), + payment_id: common_utils::id_type::PaymentId::get_irrelevant_id( + "additional revenue recovery details call flow", + ) + .get_string_repr() + .to_owned(), + attempt_id: IRRELEVANT_ATTEMPT_ID_IN_ADDITIONAL_REVENUE_RECOVERY_CALL_FLOW.to_string(), + status: diesel_models::enums::AttemptStatus::default(), + payment_method: diesel_models::enums::PaymentMethod::default(), + connector_auth_type: auth_type, + description: None, + address: hyperswitch_domain_models::payment_address::PaymentAddress::default(), + auth_type: diesel_models::enums::AuthenticationType::default(), + connector_meta_data: None, + connector_wallets_details: None, + amount_captured: None, + minor_amount_captured: None, + request: GetAdditionalRevenueRecoveryRequestData { + additional_revenue_recovery_id: additional_revenue_recovery_id.to_string(), + }, + response: Err(types::ErrorResponse::default()), + access_token: None, + session_token: None, + reference_id: None, + payment_method_token: None, + connector_customer: None, + recurring_mandate_payment_data: None, + preprocessing_id: None, + connector_request_reference_id: + IRRELEVANT_CONNECTOR_REQUEST_REFERENCE_ID_IN_ADDITIONAL_REVENUE_RECOVERY_CALL + .to_string(), + #[cfg(feature = "payouts")] + payout_method_data: None, + #[cfg(feature = "payouts")] + quote_id: None, + test_mode: None, + payment_method_balance: None, + payment_method_status: None, + connector_api_version: None, + connector_http_status_code: None, + external_latency: None, + apple_pay_flow: None, + frm_metadata: None, + refund_id: None, + dispute_id: None, + connector_response: None, + integrity_check: Ok(()), + additional_merchant_data: None, + header_payload: None, + connector_mandate_request_reference_id: None, + authentication_id: None, + psd2_sca_exemption_type: None, + }; + Ok(Self(router_data)) + } + + fn get_additional_call_router_data(self) -> AdditionalRevenueRecoveryDetailsRouterData { + self.0 + } } From 663bb0d305b4c83c18681ed0571c7fd5fb3b56a5 Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Thu, 13 Mar 2025 13:16:14 +0530 Subject: [PATCH 43/83] spell check resolve --- crates/router/src/core/webhooks/recovery_incoming.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/router/src/core/webhooks/recovery_incoming.rs b/crates/router/src/core/webhooks/recovery_incoming.rs index fcc375d0348..b6a6d375e69 100644 --- a/crates/router/src/core/webhooks/recovery_incoming.rs +++ b/crates/router/src/core/webhooks/recovery_incoming.rs @@ -85,7 +85,7 @@ pub async fn recovery_incoming_webhook_flow( None }; - // 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 fetchs from Incoming webhook + // 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 = recovery_details.clone().map_or( RevenueRecoveryInvoice( interface_webhooks::IncomingWebhook::get_revenue_recovery_invoice_details( From ff80f84f80eea89de2f653a9139d5406445c2890 Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Thu, 13 Mar 2025 13:17:38 +0530 Subject: [PATCH 44/83] spell check resolve --- crates/router/src/core/webhooks/recovery_incoming.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/router/src/core/webhooks/recovery_incoming.rs b/crates/router/src/core/webhooks/recovery_incoming.rs index b6a6d375e69..fb4c862063a 100644 --- a/crates/router/src/core/webhooks/recovery_incoming.rs +++ b/crates/router/src/core/webhooks/recovery_incoming.rs @@ -128,7 +128,7 @@ pub async fn recovery_incoming_webhook_flow( let payment_attempt = match event_type.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 fetchs from Incoming webhook + // 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 = recovery_details.map_or( RevenueRecoveryAttempt( interface_webhooks::IncomingWebhook::get_revenue_recovery_attempt_details( From 398c61ebaa70f430ef9ca6419a1277fdd2699dff Mon Sep 17 00:00:00 2001 From: "hyperswitch-bot[bot]" <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Date: Thu, 13 Mar 2025 09:07:45 +0000 Subject: [PATCH 45/83] chore: run formatter --- .../src/default_implementations.rs | 18 +++++++++++++----- crates/router/src/core/payments/flows.rs | 4 +++- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/crates/hyperswitch_connectors/src/default_implementations.rs b/crates/hyperswitch_connectors/src/default_implementations.rs index 985bda6c7e5..a1324f10cc9 100644 --- a/crates/hyperswitch_connectors/src/default_implementations.rs +++ b/crates/hyperswitch_connectors/src/default_implementations.rs @@ -24,9 +24,15 @@ use hyperswitch_domain_models::{ }; #[cfg(all(feature = "v2", feature = "revenue_recovery"))] use hyperswitch_domain_models::{ - router_flow_types::revenue_recovery::{GetAdditionalRevenueRecoveryDetails,RecoveryRecordBack}, - router_request_types::revenue_recovery::{GetAdditionalRevenueRecoveryRequestData,RevenueRecoveryRecordBackRequest}, - router_response_types::revenue_recovery::{GetAdditionalRevenueRecoveryResponseData,RevenueRecoveryRecordBackResponse}, + router_flow_types::revenue_recovery::{ + GetAdditionalRevenueRecoveryDetails, RecoveryRecordBack, + }, + router_request_types::revenue_recovery::{ + GetAdditionalRevenueRecoveryRequestData, RevenueRecoveryRecordBackRequest, + }, + router_response_types::revenue_recovery::{ + GetAdditionalRevenueRecoveryResponseData, RevenueRecoveryRecordBackResponse, + }, }; use hyperswitch_domain_models::{ router_flow_types::{ @@ -71,7 +77,9 @@ use hyperswitch_interfaces::api::payouts::{ PayoutRecipientAccount, PayoutSync, }; #[cfg(all(feature = "v2", feature = "revenue_recovery"))] -use hyperswitch_interfaces::api::revenue_recovery::{AdditionalRevenueRecovery,RevenueRecoveryRecordBack}; +use hyperswitch_interfaces::api::revenue_recovery::{ + AdditionalRevenueRecovery, RevenueRecoveryRecordBack, +}; use hyperswitch_interfaces::{ api::{ self, @@ -3887,4 +3895,4 @@ default_imp_for_revenue_recovery_record_back!( connectors::Xendit, connectors::Zen, connectors::Zsl -); \ No newline at end of file +); diff --git a/crates/router/src/core/payments/flows.rs b/crates/router/src/core/payments/flows.rs index f1c931f767d..2f24a7785f4 100644 --- a/crates/router/src/core/payments/flows.rs +++ b/crates/router/src/core/payments/flows.rs @@ -13,7 +13,9 @@ pub mod setup_mandate_flow; use async_trait::async_trait; #[cfg(all(feature = "v2", feature = "revenue_recovery"))] -use hyperswitch_domain_models::router_flow_types::{GetAdditionalRevenueRecoveryDetails,RecoveryRecordBack}; +use hyperswitch_domain_models::router_flow_types::{ + GetAdditionalRevenueRecoveryDetails, RecoveryRecordBack, +}; use hyperswitch_domain_models::{ mandates::CustomerAcceptance, router_flow_types::{ From 2f7d5afefeea6c57250c2d6e4029d1a87cde4fee Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Thu, 13 Mar 2025 14:56:28 +0530 Subject: [PATCH 46/83] feat(revenue_recovery): derive Debug and Clone for GetAdditionalRevenueRecoveryDetails struct --- .../src/router_flow_types/revenue_recovery.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/hyperswitch_domain_models/src/router_flow_types/revenue_recovery.rs b/crates/hyperswitch_domain_models/src/router_flow_types/revenue_recovery.rs index c6583811bca..7257ac32f05 100644 --- a/crates/hyperswitch_domain_models/src/router_flow_types/revenue_recovery.rs +++ b/crates/hyperswitch_domain_models/src/router_flow_types/revenue_recovery.rs @@ -1,2 +1,3 @@ +#[derive(Debug,Clone)] pub struct GetAdditionalRevenueRecoveryDetails; pub struct RecoveryRecordBack; From d1f79e22a803c28c0adfcd8e6134d1968e1b5a3c Mon Sep 17 00:00:00 2001 From: "hyperswitch-bot[bot]" <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Date: Thu, 13 Mar 2025 10:39:59 +0000 Subject: [PATCH 47/83] chore: run formatter --- .../src/router_flow_types/revenue_recovery.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/hyperswitch_domain_models/src/router_flow_types/revenue_recovery.rs b/crates/hyperswitch_domain_models/src/router_flow_types/revenue_recovery.rs index 7257ac32f05..3902fd76452 100644 --- a/crates/hyperswitch_domain_models/src/router_flow_types/revenue_recovery.rs +++ b/crates/hyperswitch_domain_models/src/router_flow_types/revenue_recovery.rs @@ -1,3 +1,3 @@ -#[derive(Debug,Clone)] +#[derive(Debug, Clone)] pub struct GetAdditionalRevenueRecoveryDetails; pub struct RecoveryRecordBack; From be2855b3c3d4a792a8d282c91bae10ee7d97b661 Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Thu, 13 Mar 2025 18:38:45 +0530 Subject: [PATCH 48/83] solved the errors in the flow --- .../src/core/webhooks/recovery_incoming.rs | 51 ++++++++++--------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/crates/router/src/core/webhooks/recovery_incoming.rs b/crates/router/src/core/webhooks/recovery_incoming.rs index fb4c862063a..85e0e6f3328 100644 --- a/crates/router/src/core/webhooks/recovery_incoming.rs +++ b/crates/router/src/core/webhooks/recovery_incoming.rs @@ -86,8 +86,11 @@ pub async fn recovery_incoming_webhook_flow( }; // 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 = recovery_details.clone().map_or( - RevenueRecoveryInvoice( + let invoice_details = match recovery_details.clone() { + Some(data) => RevenueRecoveryInvoice( + revenue_recovery::RevenueRecoveryInvoiceData::from(data.clone()), + ), + None => RevenueRecoveryInvoice( interface_webhooks::IncomingWebhook::get_revenue_recovery_invoice_details( connector_enum, request_details, @@ -95,12 +98,8 @@ pub async fn recovery_incoming_webhook_flow( .change_context(errors::RevenueRecoveryError::InvoiceWebhookProcessingFailed) .attach_printable("Failed while getting revenue recovery invoice details")?, ), - |data| { - RevenueRecoveryInvoice(revenue_recovery::RevenueRecoveryInvoiceData::from( - data.clone(), - )) - }, - ); + }; + // Fetch the intent using merchant reference id, if not found create new intent. let payment_intent = invoice_details @@ -128,24 +127,26 @@ pub async fn recovery_incoming_webhook_flow( let payment_attempt = match event_type.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 = recovery_details.map_or( - RevenueRecoveryAttempt( - 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", - )?, - ), - |data| { + + let invoice_transaction_details = match recovery_details.clone() { + Some(data)=> { RevenueRecoveryAttempt(revenue_recovery::RevenueRecoveryAttemptData::from(data)) }, - ); + None => { + RevenueRecoveryAttempt( + 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", + )?, + ) + } + }; // Find the payment merchant connector ID at the top level to avoid multiple DB calls. let payment_merchant_connector_account = invoice_transaction_details @@ -221,7 +222,9 @@ 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 { From 439da0b7e1dac35a208c487928cb12262bdde39f Mon Sep 17 00:00:00 2001 From: "hyperswitch-bot[bot]" <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Date: Thu, 13 Mar 2025 13:13:58 +0000 Subject: [PATCH 49/83] chore: run formatter --- .../src/core/webhooks/recovery_incoming.rs | 36 +++++++++---------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/crates/router/src/core/webhooks/recovery_incoming.rs b/crates/router/src/core/webhooks/recovery_incoming.rs index 85e0e6f3328..7bf0a828225 100644 --- a/crates/router/src/core/webhooks/recovery_incoming.rs +++ b/crates/router/src/core/webhooks/recovery_incoming.rs @@ -87,9 +87,9 @@ pub async fn recovery_incoming_webhook_flow( // 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 = match recovery_details.clone() { - Some(data) => RevenueRecoveryInvoice( - revenue_recovery::RevenueRecoveryInvoiceData::from(data.clone()), - ), + Some(data) => RevenueRecoveryInvoice(revenue_recovery::RevenueRecoveryInvoiceData::from( + data.clone(), + )), None => RevenueRecoveryInvoice( interface_webhooks::IncomingWebhook::get_revenue_recovery_invoice_details( connector_enum, @@ -100,7 +100,6 @@ pub async fn recovery_incoming_webhook_flow( ), }; - // Fetch the intent using merchant reference id, if not found create new intent. let payment_intent = invoice_details .get_payment_intent( @@ -127,25 +126,22 @@ pub async fn recovery_incoming_webhook_flow( let payment_attempt = match event_type.is_recovery_transaction_event() { true => { - let invoice_transaction_details = match recovery_details.clone() { - Some(data)=> { + Some(data) => { RevenueRecoveryAttempt(revenue_recovery::RevenueRecoveryAttemptData::from(data)) - }, - None => { - RevenueRecoveryAttempt( - 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", - )?, - ) } + None => RevenueRecoveryAttempt( + 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", + )?, + ), }; // Find the payment merchant connector ID at the top level to avoid multiple DB calls. From c86fb352f5b12614d155867753a023c3b562b58f Mon Sep 17 00:00:00 2001 From: "hyperswitch-bot[bot]" <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Date: Thu, 13 Mar 2025 14:37:19 +0000 Subject: [PATCH 50/83] chore: run formatter --- crates/router/src/core/webhooks/recovery_incoming.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/crates/router/src/core/webhooks/recovery_incoming.rs b/crates/router/src/core/webhooks/recovery_incoming.rs index a21037ca4d5..67638327798 100644 --- a/crates/router/src/core/webhooks/recovery_incoming.rs +++ b/crates/router/src/core/webhooks/recovery_incoming.rs @@ -1,12 +1,15 @@ use std::{marker::PhantomData, str::FromStr}; use api_models::{payments as api_payments, webhooks}; -use common_utils::{ext_traits::{AsyncExt,ValueExt}, 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, router_flow_types::GetAdditionalRevenueRecoveryDetails, + errors::api_error_response, revenue_recovery, + router_flow_types::GetAdditionalRevenueRecoveryDetails, router_request_types::revenue_recovery::GetAdditionalRevenueRecoveryRequestData, router_response_types::revenue_recovery::GetAdditionalRevenueRecoveryResponseData, types::AdditionalRevenueRecoveryDetailsRouterData, @@ -26,7 +29,8 @@ use crate::{ types::{ self, api::{self, ConnectorData, GetToken}, - domain, storage::passive_churn_recovery as storage_churn_recovery, + domain, + storage::passive_churn_recovery as storage_churn_recovery, }, workflows::passive_churn_recovery_workflow, }; From 9c330c43fdb76aa2b5a44e07fcb8d165d1e10950 Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Mon, 17 Mar 2025 13:58:11 +0530 Subject: [PATCH 51/83] refactor: update failure_code and failure_message to be optional; remove unused funding type and charge status variants --- .../connectors/stripebilling/transformers.rs | 16 +- crates/router/src/core/payments/flows.rs | 2 - .../src/core/webhooks/recovery_incoming.rs | 163 +----------------- 3 files changed, 11 insertions(+), 170 deletions(-) diff --git a/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs b/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs index b20e06d945b..2b1559ddd90 100644 --- a/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs @@ -353,8 +353,8 @@ pub struct StripebillingRecoveryDetailsData { pub currency: enums::Currency, pub customer: String, pub payment_method: String, - pub failure_code: String, - pub failure_message: String, + pub failure_code: Option, + pub failure_message: Option, #[serde(with = "common_utils::custom_serde::timestamp")] pub created: PrimitiveDateTime, pub payment_method_details: StripePaymentMethodDetails, @@ -390,8 +390,6 @@ pub enum StripebillingFundingTypes { Debit, #[serde(rename = "prepaid")] Prepaid, - #[serde(rename = "unknown")] - Unknown, } #[derive(Serialize, Deserialize, Debug, Clone)] @@ -399,7 +397,6 @@ pub enum StripebillingFundingTypes { pub enum StripebillingChargeStatus { Succeeded, Failed, - Pending, } #[cfg(all(feature = "v2", feature = "revenue_recovery"))] @@ -444,8 +441,8 @@ impl connector_account_reference_id: MCA_ID_IDENTIFIER_FOR_STRIPE_IN_STRIPEBILLING_MCA_FEAATURE_METADATA.to_string(), connector_transaction_id, - error_code: Some(item.response.failure_code), - error_message: Some(item.response.failure_message), + error_code: item.response.failure_code, + error_message: item.response.failure_message, processor_payment_method_token: item.response.payment_method, connector_customer_id: item.response.customer, transaction_created_at: Some(item.response.created), @@ -469,7 +466,7 @@ impl From for enums::AttemptStatus { fn from(status: StripebillingChargeStatus) -> Self { match status { StripebillingChargeStatus::Succeeded => Self::Charged, - StripebillingChargeStatus::Failed | StripebillingChargeStatus::Pending => Self::Pending, + StripebillingChargeStatus::Failed => Self::Failure, } } } @@ -480,8 +477,7 @@ impl From for common_enums::PaymentMethodType { match funding { StripebillingFundingTypes::Credit => Self::Credit, StripebillingFundingTypes::Debit - | StripebillingFundingTypes::Prepaid - | StripebillingFundingTypes::Unknown => Self::Debit, + | StripebillingFundingTypes::Prepaid => Self::Debit, } } } diff --git a/crates/router/src/core/payments/flows.rs b/crates/router/src/core/payments/flows.rs index 28d059217ac..db147b6b2d6 100644 --- a/crates/router/src/core/payments/flows.rs +++ b/crates/router/src/core/payments/flows.rs @@ -2321,13 +2321,11 @@ impl #[cfg(all(feature = "v2", feature = "revenue_recovery"))] default_imp_for_revenue_recovery_record_back!( connector::Adyenplatform, - connector::Adyen, connector::Ebanx, connector::Gpayments, connector::Netcetera, connector::Nmi, connector::Payone, - connector::Paypal, connector::Plaid, connector::Riskified, connector::Signifyd, diff --git a/crates/router/src/core/webhooks/recovery_incoming.rs b/crates/router/src/core/webhooks/recovery_incoming.rs index 67638327798..83a0cb0148c 100644 --- a/crates/router/src/core/webhooks/recovery_incoming.rs +++ b/crates/router/src/core/webhooks/recovery_incoming.rs @@ -109,6 +109,8 @@ pub async fn recovery_incoming_webhook_flow( ), }; + println!("{:?}",invoice_details); + // Fetch the intent using merchant reference id, if not found create new intent. let payment_intent = invoice_details .get_payment_intent( @@ -153,6 +155,8 @@ pub async fn recovery_incoming_webhook_flow( ), }; + println!("{:?}",invoice_transaction_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( @@ -749,161 +753,4 @@ impl AdditionalRevenueRecoveryRouterData { fn get_additional_call_router_data(self) -> AdditionalRevenueRecoveryDetailsRouterData { self.0 } -} - -const IRRELEVANT_ATTEMPT_ID_IN_ADDITIONAL_REVENUE_RECOVERY_CALL_FLOW: &str = - "irrelevant_attempt_id_in_additional_revenue_recovery_flow"; - -const IRRELEVANT_CONNECTOR_REQUEST_REFERENCE_ID_IN_ADDITIONAL_REVENUE_RECOVERY_CALL: &str = - "irrelevant_connector_request_reference_id_in_additional_revenue_recovery_flow"; - -pub struct AdditionalRevenueRecoveryResponse(GetAdditionalRevenueRecoveryResponseData); -pub struct AdditionalRevenueRecoveryRouterData(AdditionalRevenueRecoveryDetailsRouterData); - -impl AdditionalRevenueRecoveryResponse { - async fn handle_additional_recovery_details_call( - state: &SessionState, - merchant_account: &domain::MerchantAccount, - merchant_connector_account: &hyperswitch_domain_models::merchant_connector_account::MerchantConnectorAccount, - connector_name: &str, - id: &str, - ) -> CustomResult { - let connector_data = ConnectorData::get_connector_by_name( - &state.conf.connectors, - connector_name, - GetToken::Connector, - None, - ) - .change_context(errors::RevenueRecoveryError::AdditionalRevenueRecoveryCallFailed) - .attach_printable("invalid connector name received in payment attempt")?; - - let connector_integration: services::BoxedGetAdditionalRecoveryRecoveryDetailsIntegrationInterface< - GetAdditionalRevenueRecoveryDetails, - GetAdditionalRevenueRecoveryRequestData, - GetAdditionalRevenueRecoveryResponseData - > = connector_data.connector.get_connector_integration(); - - let router_data = - AdditionalRevenueRecoveryRouterData::construct_router_data_for_additional_call( - state, - connector_name, - merchant_connector_account, - merchant_account, - id, - ) - .await - .change_context(errors::RevenueRecoveryError::AdditionalRevenueRecoveryCallFailed) - .attach_printable( - "Failed while constructing additional recovery details call router data", - )? - .get_additional_call_router_data(); - - let response = services::execute_connector_processing_step( - state, - connector_integration, - &router_data, - payments::CallConnectorAction::Trigger, - None, - ) - .await - .change_context(errors::RevenueRecoveryError::AdditionalRevenueRecoveryCallFailed) - .attach_printable("Failed while fetching additional revenue recovery details")?; - - let additional_recovery_details = match response.response { - Ok(response) => Ok(response), - error @ Err(_) => { - router_env::logger::error!(?error); - Err(errors::RevenueRecoveryError::AdditionalRevenueRecoveryCallFailed) - .attach_printable("Failed while fetching additional revenue recovery details") - } - }?; - Ok(Self(additional_recovery_details)) - } - - fn get_additional_revenue_recovery_call_response( - self, - ) -> GetAdditionalRevenueRecoveryResponseData { - self.0 - } -} - -impl AdditionalRevenueRecoveryRouterData { - async fn construct_router_data_for_additional_call( - state: &SessionState, - connector_name: &str, - merchant_connector_account: &hyperswitch_domain_models::merchant_connector_account::MerchantConnectorAccount, - merchant_account: &domain::MerchantAccount, - additional_revenue_recovery_id: &str, - ) -> CustomResult { - 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::AdditionalRevenueRecoveryCallFailed)?; - - let router_data = types::RouterData { - flow: PhantomData, - merchant_id: merchant_account.get_id().clone(), - connector: connector_name.to_string(), - customer_id: None, - tenant_id: state.tenant.tenant_id.clone(), - payment_id: common_utils::id_type::PaymentId::get_irrelevant_id( - "additional revenue recovery details call flow", - ) - .get_string_repr() - .to_owned(), - attempt_id: IRRELEVANT_ATTEMPT_ID_IN_ADDITIONAL_REVENUE_RECOVERY_CALL_FLOW.to_string(), - status: diesel_models::enums::AttemptStatus::default(), - payment_method: diesel_models::enums::PaymentMethod::default(), - connector_auth_type: auth_type, - description: None, - address: hyperswitch_domain_models::payment_address::PaymentAddress::default(), - auth_type: diesel_models::enums::AuthenticationType::default(), - connector_meta_data: None, - connector_wallets_details: None, - amount_captured: None, - minor_amount_captured: None, - request: GetAdditionalRevenueRecoveryRequestData { - additional_revenue_recovery_id: additional_revenue_recovery_id.to_string(), - }, - response: Err(types::ErrorResponse::default()), - access_token: None, - session_token: None, - reference_id: None, - payment_method_token: None, - connector_customer: None, - recurring_mandate_payment_data: None, - preprocessing_id: None, - connector_request_reference_id: - IRRELEVANT_CONNECTOR_REQUEST_REFERENCE_ID_IN_ADDITIONAL_REVENUE_RECOVERY_CALL - .to_string(), - #[cfg(feature = "payouts")] - payout_method_data: None, - #[cfg(feature = "payouts")] - quote_id: None, - test_mode: None, - payment_method_balance: None, - payment_method_status: None, - connector_api_version: None, - connector_http_status_code: None, - external_latency: None, - apple_pay_flow: None, - frm_metadata: None, - refund_id: None, - dispute_id: None, - connector_response: None, - integrity_check: Ok(()), - additional_merchant_data: None, - header_payload: None, - connector_mandate_request_reference_id: None, - authentication_id: None, - psd2_sca_exemption_type: None, - }; - Ok(Self(router_data)) - } - - fn get_additional_call_router_data(self) -> AdditionalRevenueRecoveryDetailsRouterData { - self.0 - } -} +} \ No newline at end of file From effae0bd3cb8fdf14cf4e97350bcd89e01d3db16 Mon Sep 17 00:00:00 2001 From: "hyperswitch-bot[bot]" <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Date: Mon, 17 Mar 2025 08:34:20 +0000 Subject: [PATCH 52/83] chore: run formatter --- .../src/connectors/stripebilling/transformers.rs | 3 +-- crates/router/src/core/webhooks/recovery_incoming.rs | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs b/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs index 2b1559ddd90..93d25fe1eb0 100644 --- a/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs @@ -476,8 +476,7 @@ impl From for common_enums::PaymentMethodType { fn from(funding: StripebillingFundingTypes) -> Self { match funding { StripebillingFundingTypes::Credit => Self::Credit, - StripebillingFundingTypes::Debit - | StripebillingFundingTypes::Prepaid => Self::Debit, + StripebillingFundingTypes::Debit | StripebillingFundingTypes::Prepaid => Self::Debit, } } } diff --git a/crates/router/src/core/webhooks/recovery_incoming.rs b/crates/router/src/core/webhooks/recovery_incoming.rs index 83a0cb0148c..3d826e19146 100644 --- a/crates/router/src/core/webhooks/recovery_incoming.rs +++ b/crates/router/src/core/webhooks/recovery_incoming.rs @@ -109,7 +109,7 @@ pub async fn recovery_incoming_webhook_flow( ), }; - println!("{:?}",invoice_details); + println!("{:?}", invoice_details); // Fetch the intent using merchant reference id, if not found create new intent. let payment_intent = invoice_details @@ -155,7 +155,7 @@ pub async fn recovery_incoming_webhook_flow( ), }; - println!("{:?}",invoice_transaction_details); + println!("{:?}", invoice_transaction_details); // Find the payment merchant connector ID at the top level to avoid multiple DB calls. let payment_merchant_connector_account = invoice_transaction_details @@ -753,4 +753,4 @@ impl AdditionalRevenueRecoveryRouterData { fn get_additional_call_router_data(self) -> AdditionalRevenueRecoveryDetailsRouterData { self.0 } -} \ No newline at end of file +} From 77bb4bf403f7a63cf7a6c1be36765f8f1d680253 Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Mon, 17 Mar 2025 14:21:02 +0530 Subject: [PATCH 53/83] remove print statements --- crates/router/src/core/webhooks/recovery_incoming.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/crates/router/src/core/webhooks/recovery_incoming.rs b/crates/router/src/core/webhooks/recovery_incoming.rs index 3d826e19146..a6ecfacdfdf 100644 --- a/crates/router/src/core/webhooks/recovery_incoming.rs +++ b/crates/router/src/core/webhooks/recovery_incoming.rs @@ -109,8 +109,6 @@ pub async fn recovery_incoming_webhook_flow( ), }; - println!("{:?}", invoice_details); - // Fetch the intent using merchant reference id, if not found create new intent. let payment_intent = invoice_details .get_payment_intent( @@ -155,7 +153,6 @@ pub async fn recovery_incoming_webhook_flow( ), }; - println!("{:?}", invoice_transaction_details); // Find the payment merchant connector ID at the top level to avoid multiple DB calls. let payment_merchant_connector_account = invoice_transaction_details From 06540607228b2b859a2c364987574a4bef24c9f1 Mon Sep 17 00:00:00 2001 From: "hyperswitch-bot[bot]" <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Date: Mon, 17 Mar 2025 09:46:33 +0000 Subject: [PATCH 54/83] chore: run formatter --- crates/router/src/core/webhooks/recovery_incoming.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/router/src/core/webhooks/recovery_incoming.rs b/crates/router/src/core/webhooks/recovery_incoming.rs index a6ecfacdfdf..83d20c13940 100644 --- a/crates/router/src/core/webhooks/recovery_incoming.rs +++ b/crates/router/src/core/webhooks/recovery_incoming.rs @@ -153,7 +153,6 @@ pub async fn recovery_incoming_webhook_flow( ), }; - // 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( From ab5a21e67a68f7a29f034ae1f66d96ce68bd761a Mon Sep 17 00:00:00 2001 From: "hyperswitch-bot[bot]" <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Date: Mon, 17 Mar 2025 15:59:05 +0000 Subject: [PATCH 55/83] chore: run formatter --- .../src/connectors/stripebilling.rs | 2 - .../connectors/stripebilling/transformers.rs | 38 +++++++++++++++---- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/crates/hyperswitch_connectors/src/connectors/stripebilling.rs b/crates/hyperswitch_connectors/src/connectors/stripebilling.rs index e6fc388f94d..087701e4312 100644 --- a/crates/hyperswitch_connectors/src/connectors/stripebilling.rs +++ b/crates/hyperswitch_connectors/src/connectors/stripebilling.rs @@ -2,8 +2,6 @@ pub mod transformers; use std::collections::HashMap; -use std::collections::HashMap; - use common_utils::{ errors::CustomResult, ext_traits::BytesExt, diff --git a/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs b/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs index d9772cf765c..c18000bf882 100644 --- a/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs @@ -1,6 +1,5 @@ #[cfg(feature = "v2")] use std::str::FromStr; - #[cfg(feature = "v2")] use std::str::FromStr; @@ -9,8 +8,6 @@ use common_utils::{errors::CustomResult, ext_traits::ByteSliceExt, types::String use error_stack::ResultExt; #[cfg(all(feature = "revenue_recovery", feature = "v2"))] use hyperswitch_domain_models::revenue_recovery; -use common_utils::{errors::CustomResult, ext_traits::ByteSliceExt, types::StringMinorUnit}; -use error_stack::ResultExt; #[cfg(all(feature = "revenue_recovery", feature = "v2"))] use hyperswitch_domain_models::revenue_recovery; use hyperswitch_domain_models::{ @@ -36,7 +33,6 @@ use time::PrimitiveDateTime; use crate::{ types::{RefundsResponseRouterData, ResponseRouterData}, utils::{convert_uppercase, PaymentsAuthorizeRequestData}, - utils::{convert_uppercase, PaymentsAuthorizeRequestData}, }; pub mod auth_headers { @@ -121,8 +117,22 @@ impl TryFrom<&ConnectorAuthType> for StripebillingAuthType { } // PaymentsResponse //TODO: Append the remaining status flags -#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Copy)] -#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Copy)] +#[derive( + Debug, + Clone, + Default, + Serialize, + Deserialize, + PartialEq, + Copy, + Debug, + Clone, + Default, + Serialize, + Deserialize, + PartialEq, + Copy, +)] #[serde(rename_all = "lowercase")] pub enum StripebillingPaymentStatus { Succeeded, @@ -194,8 +204,20 @@ impl TryFrom<&StripebillingRouterData<&RefundsRouterData>> for Stripebilli // Type definition for Refund Response #[allow(dead_code)] -#[derive(Debug, Serialize, Default, Deserialize, Clone, Copy)] -#[derive(Debug, Serialize, Default, Deserialize, Clone, Copy)] +#[derive( + Debug, + Serialize, + Default, + Deserialize, + Clone, + Copy, + Debug, + Serialize, + Default, + Deserialize, + Clone, + Copy, +)] pub enum RefundStatus { Succeeded, Failed, From 0e53ec7b356b970217f2301526867d63306f8c35 Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Mon, 17 Mar 2025 21:36:01 +0530 Subject: [PATCH 56/83] resolve merge errors --- .../connectors/stripebilling/transformers.rs | 39 ++----------------- 1 file changed, 3 insertions(+), 36 deletions(-) diff --git a/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs b/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs index c18000bf882..eaba93a125e 100644 --- a/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs @@ -1,15 +1,10 @@ #[cfg(feature = "v2")] use std::str::FromStr; -#[cfg(feature = "v2")] -use std::str::FromStr; - use common_enums::enums; -use common_utils::{errors::CustomResult, ext_traits::ByteSliceExt, types::StringMinorUnit}; +use common_utils::{ext_traits::ByteSliceExt,errors::CustomResult,types::StringMinorUnit}; use error_stack::ResultExt; #[cfg(all(feature = "revenue_recovery", feature = "v2"))] use hyperswitch_domain_models::revenue_recovery; -#[cfg(all(feature = "revenue_recovery", feature = "v2"))] -use hyperswitch_domain_models::revenue_recovery; use hyperswitch_domain_models::{ payment_method_data::PaymentMethodData, router_data::{ConnectorAuthType, RouterData}, @@ -117,22 +112,7 @@ impl TryFrom<&ConnectorAuthType> for StripebillingAuthType { } // PaymentsResponse //TODO: Append the remaining status flags -#[derive( - Debug, - Clone, - Default, - Serialize, - Deserialize, - PartialEq, - Copy, - Debug, - Clone, - Default, - Serialize, - Deserialize, - PartialEq, - Copy, -)] +#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Copy)] #[serde(rename_all = "lowercase")] pub enum StripebillingPaymentStatus { Succeeded, @@ -204,20 +184,7 @@ impl TryFrom<&StripebillingRouterData<&RefundsRouterData>> for Stripebilli // Type definition for Refund Response #[allow(dead_code)] -#[derive( - Debug, - Serialize, - Default, - Deserialize, - Clone, - Copy, - Debug, - Serialize, - Default, - Deserialize, - Clone, - Copy, -)] +#[derive(Debug, Serialize, Default, Deserialize, Clone, Copy)] pub enum RefundStatus { Succeeded, Failed, From 10034e24cdf7ac496c8c590778aacf45f3bcadff Mon Sep 17 00:00:00 2001 From: "hyperswitch-bot[bot]" <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Date: Mon, 17 Mar 2025 16:07:16 +0000 Subject: [PATCH 57/83] chore: run formatter --- .../src/connectors/stripebilling/transformers.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs b/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs index eaba93a125e..93d25fe1eb0 100644 --- a/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs @@ -1,7 +1,8 @@ #[cfg(feature = "v2")] use std::str::FromStr; + use common_enums::enums; -use common_utils::{ext_traits::ByteSliceExt,errors::CustomResult,types::StringMinorUnit}; +use common_utils::{errors::CustomResult, ext_traits::ByteSliceExt, types::StringMinorUnit}; use error_stack::ResultExt; #[cfg(all(feature = "revenue_recovery", feature = "v2"))] use hyperswitch_domain_models::revenue_recovery; From ad85e5f3c1c7fca16605e480b1b53432ed606257 Mon Sep 17 00:00:00 2001 From: "hyperswitch-bot[bot]" <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Date: Tue, 18 Mar 2025 13:47:44 +0000 Subject: [PATCH 58/83] chore: run formatter --- crates/hyperswitch_connectors/src/default_implementations.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/hyperswitch_connectors/src/default_implementations.rs b/crates/hyperswitch_connectors/src/default_implementations.rs index ff7f5167175..3a3599189af 100644 --- a/crates/hyperswitch_connectors/src/default_implementations.rs +++ b/crates/hyperswitch_connectors/src/default_implementations.rs @@ -3953,4 +3953,3 @@ default_imp_for_revenue_recovery_record_back!( connectors::Zen, connectors::Zsl ); - From b947288b54067a6c387fa665573314129200d21d Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Tue, 18 Mar 2025 21:46:53 +0530 Subject: [PATCH 59/83] resolve clippy errors --- crates/hyperswitch_connectors/src/default_implementations.rs | 1 - crates/router/src/core/webhooks/recovery_incoming.rs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/hyperswitch_connectors/src/default_implementations.rs b/crates/hyperswitch_connectors/src/default_implementations.rs index 3a3599189af..f97570ebf51 100644 --- a/crates/hyperswitch_connectors/src/default_implementations.rs +++ b/crates/hyperswitch_connectors/src/default_implementations.rs @@ -3883,7 +3883,6 @@ default_imp_for_revenue_recovery_record_back!( connectors::Braintree, connectors::Boku, connectors::Cashtocode, - connectors::Chargebee, connectors::Checkout, connectors::Coinbase, connectors::Coingate, diff --git a/crates/router/src/core/webhooks/recovery_incoming.rs b/crates/router/src/core/webhooks/recovery_incoming.rs index 83d20c13940..b2ddb9e7042 100644 --- a/crates/router/src/core/webhooks/recovery_incoming.rs +++ b/crates/router/src/core/webhooks/recovery_incoming.rs @@ -691,7 +691,7 @@ impl AdditionalRevenueRecoveryRouterData { connector: connector_name.to_string(), customer_id: None, tenant_id: state.tenant.tenant_id.clone(), - payment_id: common_utils::id_type::PaymentId::get_irrelevant_id( + payment_id: id_type::PaymentId::get_irrelevant_id( "additional revenue recovery details call flow", ) .get_string_repr() From 7ba0527a13cb1fe96d399ed99fe2f376f49e7baa Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Wed, 19 Mar 2025 19:03:39 +0530 Subject: [PATCH 60/83] Simplify webhook event handling and improve data cloning in revenue recovery --- .../src/connectors/stripebilling.rs | 24 ----- .../connectors/stripebilling/transformers.rs | 25 ++--- .../src/revenue_recovery.rs | 24 ++--- .../src/core/webhooks/recovery_incoming.rs | 95 ++++++++++--------- 4 files changed, 78 insertions(+), 90 deletions(-) diff --git a/crates/hyperswitch_connectors/src/connectors/stripebilling.rs b/crates/hyperswitch_connectors/src/connectors/stripebilling.rs index 087701e4312..4bb1ee67f10 100644 --- a/crates/hyperswitch_connectors/src/connectors/stripebilling.rs +++ b/crates/hyperswitch_connectors/src/connectors/stripebilling.rs @@ -713,30 +713,7 @@ impl webhooks::IncomingWebhook for Stripebilling { ) -> CustomResult { Err(report!(errors::ConnectorError::WebhooksNotImplemented)) } - #[cfg(all(feature = "revenue_recovery", feature = "v2"))] - fn get_webhook_event_type( - &self, - request: &webhooks::IncomingWebhookRequestDetails<'_>, - ) -> CustomResult { - let webhook = - stripebilling::StripebillingWebhookBody::get_webhook_object_from_body(request.body) - .change_context(errors::ConnectorError::WebhookEventTypeNotFound)?; - - let event = match webhook.event_type { - stripebilling::StripebillingEventType::PaymentSucceeded => { - api_models::webhooks::IncomingWebhookEvent::RecoveryPaymentSuccess - } - stripebilling::StripebillingEventType::PaymentFailed => { - api_models::webhooks::IncomingWebhookEvent::RecoveryPaymentFailure - } - stripebilling::StripebillingEventType::InvoiceDeleted => { - api_models::webhooks::IncomingWebhookEvent::RecoveryInvoiceCancel - } - }; - Ok(event) - } - #[cfg(any(feature = "v1", not(all(feature = "revenue_recovery", feature = "v2"))))] #[cfg(all(feature = "revenue_recovery", feature = "v2"))] fn get_webhook_event_type( &self, @@ -768,7 +745,6 @@ impl webhooks::IncomingWebhook for Stripebilling { Err(report!(errors::ConnectorError::WebhooksNotImplemented)) } - #[cfg(any(feature = "v1", not(all(feature = "revenue_recovery", feature = "v2"))))] #[cfg(any(feature = "v1", not(all(feature = "revenue_recovery", feature = "v2"))))] fn get_webhook_resource_object( &self, diff --git a/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs b/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs index 93d25fe1eb0..4788c237c79 100644 --- a/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs @@ -2,6 +2,8 @@ use std::str::FromStr; use common_enums::enums; +#[cfg(feature = "v2")] +use common_utils::id_type; use common_utils::{errors::CustomResult, ext_traits::ByteSliceExt, types::StringMinorUnit}; use error_stack::ResultExt; #[cfg(all(feature = "revenue_recovery", feature = "v2"))] @@ -333,7 +335,7 @@ impl TryFrom for revenue_recovery::RevenueRecoveryInvo type Error = error_stack::Report; fn try_from(item: StripebillingInvoiceBody) -> Result { let merchant_reference_id = - common_utils::id_type::PaymentReferenceId::from_str(&item.data.object.invoice_id) + id_type::PaymentReferenceId::from_str(&item.data.object.invoice_id) .change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?; Ok(Self { amount: item.data.object.amount, @@ -370,7 +372,7 @@ pub struct StripePaymentMethodDetails { pub card_funding_type: StripeCardFundingTypeDetails, } -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, Copy)] #[serde(rename_all = "snake_case")] pub enum StripebillingPaymentMethod { Card, @@ -381,18 +383,16 @@ pub struct StripeCardFundingTypeDetails { pub funding: StripebillingFundingTypes, } -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, Copy)] #[serde(rename = "snake_case")] pub enum StripebillingFundingTypes { #[serde(rename = "credit")] Credit, #[serde(rename = "debit")] Debit, - #[serde(rename = "prepaid")] - Prepaid, } -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, Copy)] #[serde(rename_all = "snake_case")] pub enum StripebillingChargeStatus { Succeeded, @@ -402,7 +402,7 @@ pub enum StripebillingChargeStatus { #[cfg(all(feature = "v2", feature = "revenue_recovery"))] // This is the default hard coded mca Id to find the stripe account associated with the stripe biliing // Context : Since we dont have the concept of connector_reference_id in stripebilling because payments always go through stripe. -// While creating stripebilling we will hard code the stripe mca id to string "stripebilling" in mca featrue metadata. So we have to pass the same as account_reference_id here in response. +// While creating stripebilling we will hard code the stripe account id to string "stripebilling" in mca featrue metadata. So we have to pass the same as account_reference_id here in response. const MCA_ID_IDENTIFIER_FOR_STRIPE_IN_STRIPEBILLING_MCA_FEAATURE_METADATA: &str = "stripebilling"; #[cfg(all(feature = "v2", feature = "revenue_recovery"))] @@ -425,9 +425,12 @@ impl GetAdditionalRevenueRecoveryResponseData, >, ) -> Result { - let merchant_reference_id = - common_utils::id_type::PaymentReferenceId::from_str(&item.response.invoice_id) - .change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?; + let merchant_reference_id = id_type::PaymentReferenceId::from_str( + &item.response.invoice_id, + ) + .change_context(errors::ConnectorError::MissingRequiredField { + field_name: "invoice_id", + })?; let connector_transaction_id = Some(common_utils::types::ConnectorTransactionId::from( item.response.charge_id, )); @@ -476,7 +479,7 @@ impl From for common_enums::PaymentMethodType { fn from(funding: StripebillingFundingTypes) -> Self { match funding { StripebillingFundingTypes::Credit => Self::Credit, - StripebillingFundingTypes::Debit | StripebillingFundingTypes::Prepaid => Self::Debit, + StripebillingFundingTypes::Debit => Self::Debit, } } } diff --git a/crates/hyperswitch_domain_models/src/revenue_recovery.rs b/crates/hyperswitch_domain_models/src/revenue_recovery.rs index f1fcc5313f4..6139764ac6c 100644 --- a/crates/hyperswitch_domain_models/src/revenue_recovery.rs +++ b/crates/hyperswitch_domain_models/src/revenue_recovery.rs @@ -193,28 +193,28 @@ impl From<&RevenueRecoveryInvoiceData> for api_payments::PaymentsCreateIntentReq } } -impl From for RevenueRecoveryInvoiceData { - fn from(data: GetAdditionalRevenueRecoveryResponseData) -> Self { +impl From<&GetAdditionalRevenueRecoveryResponseData> for RevenueRecoveryInvoiceData { + fn from(data: &GetAdditionalRevenueRecoveryResponseData) -> Self { Self { amount: data.amount, currency: data.currency, - merchant_reference_id: data.merchant_reference_id, + merchant_reference_id: data.merchant_reference_id.clone(), } } } -impl From for RevenueRecoveryAttemptData { - fn from(data: GetAdditionalRevenueRecoveryResponseData) -> Self { +impl From<&GetAdditionalRevenueRecoveryResponseData> for RevenueRecoveryAttemptData { + fn from(data: &GetAdditionalRevenueRecoveryResponseData) -> Self { Self { amount: data.amount, currency: data.currency, - merchant_reference_id: data.merchant_reference_id, - connector_transaction_id: data.connector_transaction_id, - error_code: data.error_code, - error_message: data.error_message, - processor_payment_method_token: data.processor_payment_method_token, - connector_customer_id: data.connector_customer_id, - connector_account_reference_id: data.connector_account_reference_id, + merchant_reference_id: data.merchant_reference_id.clone(), + connector_transaction_id: data.connector_transaction_id.clone(), + error_code: data.error_code.clone(), + error_message: data.error_message.clone(), + processor_payment_method_token: data.processor_payment_method_token.clone(), + connector_customer_id: data.connector_customer_id.clone(), + connector_account_reference_id: data.connector_account_reference_id.clone(), transaction_created_at: data.transaction_created_at, status: data.status, payment_method_type: data.payment_method_type, diff --git a/crates/router/src/core/webhooks/recovery_incoming.rs b/crates/router/src/core/webhooks/recovery_incoming.rs index b2ddb9e7042..f36a0827052 100644 --- a/crates/router/src/core/webhooks/recovery_incoming.rs +++ b/crates/router/src/core/webhooks/recovery_incoming.rs @@ -67,47 +67,52 @@ pub async fn recovery_incoming_webhook_flow( .change_context(errors::RevenueRecoveryError::InvoiceWebhookProcessingFailed) .attach_printable_lazy(|| format!("unable to parse connector name {connector_name:?}"))?; - let recovery_details = if connectors_with_additional_recovery_details_call + let recovery_details = match connectors_with_additional_recovery_details_call .connectors_with_additional_revenue_recovery_details_call .contains(&connector) { - let additional_revenue_recovery_id = match object_ref_id { - webhooks::ObjectReferenceId::AdditionalRevenueRecoveryId( - webhooks::AdditionalRevenueRecoveryIdType::AdditionalRevenueRecoveryCallId(ref id), - ) => Some(id.as_str()), - _ => None, - }; - - let additional_call_response = - AdditionalRevenueRecoveryResponse::handle_additional_recovery_details_call( - &state, - &merchant_account, - &billing_connector_account, - connector_name, - additional_revenue_recovery_id.unwrap_or("fake_id"), - ) - .await? - .get_additional_revenue_recovery_call_response(); - - Some(additional_call_response) - } else { - None + true => { + let additional_revenue_recovery_id = match object_ref_id { + webhooks::ObjectReferenceId::AdditionalRevenueRecoveryId( + webhooks::AdditionalRevenueRecoveryIdType::AdditionalRevenueRecoveryCallId( + ref id, + ), + ) => Ok(id.as_str()), + _ => Err(errors::RevenueRecoveryError::AdditionalRevenueRecoveryCallFailed), + }?; + + let additional_call_response = + AdditionalRevenueRecoveryResponse::handle_additional_recovery_details_call( + &state, + &merchant_account, + &billing_connector_account, + connector_name, + additional_revenue_recovery_id, + ) + .await? + .inner(); + Some(additional_call_response) + } + false => None, }; // 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 = match recovery_details.clone() { - Some(data) => RevenueRecoveryInvoice(revenue_recovery::RevenueRecoveryInvoiceData::from( - data.clone(), - )), - None => RevenueRecoveryInvoice( + let invoice_details = recovery_details + .as_ref() + .map(|data| { + Ok(RevenueRecoveryInvoice( + revenue_recovery::RevenueRecoveryInvoiceData::from(data), + )) + }) + .unwrap_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")?, - ), - }; + .attach_printable("Failed while getting revenue recovery invoice details") + .map(RevenueRecoveryInvoice) + })?; // Fetch the intent using merchant reference id, if not found create new intent. let payment_intent = invoice_details @@ -135,11 +140,15 @@ pub async fn recovery_incoming_webhook_flow( let payment_attempt = match event_type.is_recovery_transaction_event() { true => { - let invoice_transaction_details = match recovery_details.clone() { - Some(data) => { - RevenueRecoveryAttempt(revenue_recovery::RevenueRecoveryAttemptData::from(data)) - } - None => RevenueRecoveryAttempt( + // 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 = recovery_details + .as_ref() + .map(|data| { + Ok(RevenueRecoveryAttempt( + revenue_recovery::RevenueRecoveryAttemptData::from(data), + )) + }) + .unwrap_or_else(|| { interface_webhooks::IncomingWebhook::get_revenue_recovery_attempt_details( connector_enum, request_details, @@ -149,9 +158,11 @@ pub async fn recovery_incoming_webhook_flow( ) .attach_printable( "Failed to get recovery attempt details from the billing connector", - )?, - ), - }; + ) + .map(RevenueRecoveryAttempt) + })?; + + println!("{:?}", invoice_transaction_details); // Find the payment merchant connector ID at the top level to avoid multiple DB calls. let payment_merchant_connector_account = invoice_transaction_details @@ -639,7 +650,7 @@ impl AdditionalRevenueRecoveryResponse { .attach_printable( "Failed while constructing additional recovery details call router data", )? - .get_additional_call_router_data(); + .inner(); let response = services::execute_connector_processing_step( state, @@ -663,9 +674,7 @@ impl AdditionalRevenueRecoveryResponse { Ok(Self(additional_recovery_details)) } - fn get_additional_revenue_recovery_call_response( - self, - ) -> GetAdditionalRevenueRecoveryResponseData { + fn inner(self) -> GetAdditionalRevenueRecoveryResponseData { self.0 } } @@ -746,7 +755,7 @@ impl AdditionalRevenueRecoveryRouterData { Ok(Self(router_data)) } - fn get_additional_call_router_data(self) -> AdditionalRevenueRecoveryDetailsRouterData { + fn inner(self) -> AdditionalRevenueRecoveryDetailsRouterData { self.0 } } From 64d00ed9ff024fc2d2e9cec856823acfb05d7a1b Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Wed, 19 Mar 2025 21:32:44 +0530 Subject: [PATCH 61/83] remove print statement --- crates/router/src/core/webhooks/recovery_incoming.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/router/src/core/webhooks/recovery_incoming.rs b/crates/router/src/core/webhooks/recovery_incoming.rs index f36a0827052..ab1478c9d12 100644 --- a/crates/router/src/core/webhooks/recovery_incoming.rs +++ b/crates/router/src/core/webhooks/recovery_incoming.rs @@ -162,8 +162,6 @@ pub async fn recovery_incoming_webhook_flow( .map(RevenueRecoveryAttempt) })?; - println!("{:?}", invoice_transaction_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( From 7f6dd292a1f01052e890b02280b72d8d651479cf Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Thu, 20 Mar 2025 13:23:17 +0530 Subject: [PATCH 62/83] refactor match statments --- .../src/core/webhooks/recovery_incoming.rs | 79 +++++++++++-------- 1 file changed, 45 insertions(+), 34 deletions(-) diff --git a/crates/router/src/core/webhooks/recovery_incoming.rs b/crates/router/src/core/webhooks/recovery_incoming.rs index ab1478c9d12..ddc2b6924d5 100644 --- a/crates/router/src/core/webhooks/recovery_incoming.rs +++ b/crates/router/src/core/webhooks/recovery_incoming.rs @@ -72,14 +72,8 @@ pub async fn recovery_incoming_webhook_flow( .contains(&connector) { true => { - let additional_revenue_recovery_id = match object_ref_id { - webhooks::ObjectReferenceId::AdditionalRevenueRecoveryId( - webhooks::AdditionalRevenueRecoveryIdType::AdditionalRevenueRecoveryCallId( - ref id, - ), - ) => Ok(id.as_str()), - _ => Err(errors::RevenueRecoveryError::AdditionalRevenueRecoveryCallFailed), - }?; + + let additional_revenue_recovery_id = ObjectReferenceIdTuple(object_ref_id.clone()).get_additional_revenue_recovery_id_as_string()?; let additional_call_response = AdditionalRevenueRecoveryResponse::handle_additional_recovery_details_call( @@ -87,7 +81,7 @@ pub async fn recovery_incoming_webhook_flow( &merchant_account, &billing_connector_account, connector_name, - additional_revenue_recovery_id, + &additional_revenue_recovery_id, ) .await? .inner(); @@ -97,23 +91,25 @@ pub async fn recovery_incoming_webhook_flow( }; // 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 = recovery_details .as_ref() - .map(|data| { - Ok(RevenueRecoveryInvoice( - revenue_recovery::RevenueRecoveryInvoiceData::from(data), - )) - }) - .unwrap_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) - })?; - + .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(RevenueRecoveryInvoice( + revenue_recovery::RevenueRecoveryInvoiceData::from(data), + )) + } + )?; // Fetch the intent using merchant reference id, if not found create new intent. let payment_intent = invoice_details .get_payment_intent( @@ -141,14 +137,9 @@ pub async fn recovery_incoming_webhook_flow( let payment_attempt = match event_type.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 = recovery_details - .as_ref() - .map(|data| { - Ok(RevenueRecoveryAttempt( - revenue_recovery::RevenueRecoveryAttemptData::from(data), - )) - }) - .unwrap_or_else(|| { + + let invoice_transaction_details = recovery_details.as_ref().map_or_else( + || { interface_webhooks::IncomingWebhook::get_revenue_recovery_attempt_details( connector_enum, request_details, @@ -160,8 +151,14 @@ pub async fn recovery_incoming_webhook_flow( "Failed to get recovery attempt details from the billing connector", ) .map(RevenueRecoveryAttempt) - })?; - + }, + |data| { + Ok(RevenueRecoveryAttempt( + revenue_recovery::RevenueRecoveryAttemptData::from(data), + )) + } + )?; + // 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( @@ -757,3 +754,17 @@ impl AdditionalRevenueRecoveryRouterData { self.0 } } + +pub struct ObjectReferenceIdTuple(webhooks::ObjectReferenceId); + +impl ObjectReferenceIdTuple { + pub fn get_additional_revenue_recovery_id_as_string(self)-> Result{ + match self.0.clone() { + webhooks::ObjectReferenceId::AdditionalRevenueRecoveryId( + webhooks::AdditionalRevenueRecoveryIdType::AdditionalRevenueRecoveryCallId(data) + ) => Ok(data), + _ => Err(errors::RevenueRecoveryError::AdditionalRevenueRecoveryCallFailed) + } + } + +} From 7ef279fc076a9737a609514cda8e863ab7589bbb Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Thu, 20 Mar 2025 13:23:50 +0530 Subject: [PATCH 63/83] format code --- .../src/core/webhooks/recovery_incoming.rs | 51 +++++++++---------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/crates/router/src/core/webhooks/recovery_incoming.rs b/crates/router/src/core/webhooks/recovery_incoming.rs index ddc2b6924d5..a9d4e0746b8 100644 --- a/crates/router/src/core/webhooks/recovery_incoming.rs +++ b/crates/router/src/core/webhooks/recovery_incoming.rs @@ -72,8 +72,8 @@ pub async fn recovery_incoming_webhook_flow( .contains(&connector) { true => { - - let additional_revenue_recovery_id = ObjectReferenceIdTuple(object_ref_id.clone()).get_additional_revenue_recovery_id_as_string()?; + let additional_revenue_recovery_id = ObjectReferenceIdTuple(object_ref_id.clone()) + .get_additional_revenue_recovery_id_as_string()?; let additional_call_response = AdditionalRevenueRecoveryResponse::handle_additional_recovery_details_call( @@ -92,24 +92,22 @@ pub async fn recovery_incoming_webhook_flow( // 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 = recovery_details - .as_ref() - .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(RevenueRecoveryInvoice( - revenue_recovery::RevenueRecoveryInvoiceData::from(data), - )) - } - )?; + let invoice_details = recovery_details.as_ref().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(RevenueRecoveryInvoice( + revenue_recovery::RevenueRecoveryInvoiceData::from(data), + )) + }, + )?; // Fetch the intent using merchant reference id, if not found create new intent. let payment_intent = invoice_details .get_payment_intent( @@ -156,9 +154,9 @@ pub async fn recovery_incoming_webhook_flow( Ok(RevenueRecoveryAttempt( revenue_recovery::RevenueRecoveryAttemptData::from(data), )) - } + }, )?; - + // 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( @@ -758,13 +756,14 @@ impl AdditionalRevenueRecoveryRouterData { pub struct ObjectReferenceIdTuple(webhooks::ObjectReferenceId); impl ObjectReferenceIdTuple { - pub fn get_additional_revenue_recovery_id_as_string(self)-> Result{ + pub fn get_additional_revenue_recovery_id_as_string( + self, + ) -> Result { match self.0.clone() { webhooks::ObjectReferenceId::AdditionalRevenueRecoveryId( - webhooks::AdditionalRevenueRecoveryIdType::AdditionalRevenueRecoveryCallId(data) + webhooks::AdditionalRevenueRecoveryIdType::AdditionalRevenueRecoveryCallId(data), ) => Ok(data), - _ => Err(errors::RevenueRecoveryError::AdditionalRevenueRecoveryCallFailed) + _ => Err(errors::RevenueRecoveryError::AdditionalRevenueRecoveryCallFailed), } } - } From 8e5b5f1171c872dda307e02b0e184df4b7df5df9 Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Thu, 20 Mar 2025 14:17:59 +0530 Subject: [PATCH 64/83] refactor object reference id tuple implementation to object reference d file --- crates/api_models/src/webhooks.rs | 18 ++++++++++++++ .../src/core/webhooks/recovery_incoming.rs | 24 ++++++------------- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/crates/api_models/src/webhooks.rs b/crates/api_models/src/webhooks.rs index 0df98739c5a..8931aeb1566 100644 --- a/crates/api_models/src/webhooks.rs +++ b/crates/api_models/src/webhooks.rs @@ -269,6 +269,24 @@ pub enum AdditionalRevenueRecoveryIdType { AdditionalRevenueRecoveryCallId(String), } +#[cfg(all(feature = "revenue_recovery", feature = "v2"))] +impl ObjectReferenceId { + pub fn get_additional_revenue_recovery_id_as_string( + self, + ) -> Result { + match self { + Self::AdditionalRevenueRecoveryId( + AdditionalRevenueRecoveryIdType::AdditionalRevenueRecoveryCallId(data), + ) => Ok(data), + _ => Err( + common_utils::errors::ValidationError::IncorrectValueProvided { + field_name: "AdditionalRevenueRecoveryId is null", + }, + ), + } + } +} + pub struct IncomingWebhookDetails { pub object_reference_id: ObjectReferenceId, pub resource_object: Vec, diff --git a/crates/router/src/core/webhooks/recovery_incoming.rs b/crates/router/src/core/webhooks/recovery_incoming.rs index a9d4e0746b8..f17310538ba 100644 --- a/crates/router/src/core/webhooks/recovery_incoming.rs +++ b/crates/router/src/core/webhooks/recovery_incoming.rs @@ -72,8 +72,13 @@ pub async fn recovery_incoming_webhook_flow( .contains(&connector) { true => { - let additional_revenue_recovery_id = ObjectReferenceIdTuple(object_ref_id.clone()) - .get_additional_revenue_recovery_id_as_string()?; + let additional_revenue_recovery_id = object_ref_id + .clone() + .get_additional_revenue_recovery_id_as_string() + .change_context(errors::RevenueRecoveryError::AdditionalRevenueRecoveryCallFailed) + .attach_printable( + "Cannot get additional revenue reovery id from object reference id", + )?; let additional_call_response = AdditionalRevenueRecoveryResponse::handle_additional_recovery_details_call( @@ -752,18 +757,3 @@ impl AdditionalRevenueRecoveryRouterData { self.0 } } - -pub struct ObjectReferenceIdTuple(webhooks::ObjectReferenceId); - -impl ObjectReferenceIdTuple { - pub fn get_additional_revenue_recovery_id_as_string( - self, - ) -> Result { - match self.0.clone() { - webhooks::ObjectReferenceId::AdditionalRevenueRecoveryId( - webhooks::AdditionalRevenueRecoveryIdType::AdditionalRevenueRecoveryCallId(data), - ) => Ok(data), - _ => Err(errors::RevenueRecoveryError::AdditionalRevenueRecoveryCallFailed), - } - } -} From 8ae6fb7eaf269d71056648e3af92aaa8ccfcbc36 Mon Sep 17 00:00:00 2001 From: "hyperswitch-bot[bot]" <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Date: Thu, 20 Mar 2025 13:33:14 +0000 Subject: [PATCH 65/83] docs(openapi): re-generate OpenAPI specification --- api-reference-v2/openapi_spec.json | 11 +++++++++++ api-reference/openapi_spec.json | 11 +++++++++++ 2 files changed, 22 insertions(+) diff --git a/api-reference-v2/openapi_spec.json b/api-reference-v2/openapi_spec.json index 0ae089c5ea0..184b5ef15f7 100644 --- a/api-reference-v2/openapi_spec.json +++ b/api-reference-v2/openapi_spec.json @@ -7671,6 +7671,7 @@ "square", "stax", "stripe", + "stripebilling", "taxjar", "threedsecureio", "trustpay", @@ -8365,10 +8366,12 @@ "CAD", "CDF", "CHF", + "CLF", "CLP", "CNY", "COP", "CRC", + "CUC", "CUP", "CVE", "CZK", @@ -8464,6 +8467,7 @@ "SOS", "SRD", "SSP", + "STD", "STN", "SVC", "SYP", @@ -9969,6 +9973,12 @@ } } }, + { + "type": "string", + "enum": [ + "user_social_security_number" + ] + }, { "type": "string", "enum": [ @@ -20472,6 +20482,7 @@ "square", "stax", "stripe", + "stripebilling", "trustpay", "tsys", "volt", diff --git a/api-reference/openapi_spec.json b/api-reference/openapi_spec.json index fa4ce7ae5eb..56a24927665 100644 --- a/api-reference/openapi_spec.json +++ b/api-reference/openapi_spec.json @@ -9770,6 +9770,7 @@ "square", "stax", "stripe", + "stripebilling", "taxjar", "threedsecureio", "trustpay", @@ -10493,10 +10494,12 @@ "CAD", "CDF", "CHF", + "CLF", "CLP", "CNY", "COP", "CRC", + "CUC", "CUP", "CVE", "CZK", @@ -10592,6 +10595,7 @@ "SOS", "SRD", "SSP", + "STD", "STN", "SVC", "SYP", @@ -12170,6 +12174,12 @@ } } }, + { + "type": "string", + "enum": [ + "user_social_security_number" + ] + }, { "type": "string", "enum": [ @@ -24900,6 +24910,7 @@ "square", "stax", "stripe", + "stripebilling", "trustpay", "tsys", "volt", From 640c69008be64b1188f5f3333eaa34dccd2db60c Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Fri, 21 Mar 2025 19:38:41 +0530 Subject: [PATCH 66/83] reduced match statements --- crates/api_models/src/webhooks.rs | 35 ++++++++++- .../src/core/webhooks/recovery_incoming.rs | 58 ++++++++++--------- 2 files changed, 64 insertions(+), 29 deletions(-) diff --git a/crates/api_models/src/webhooks.rs b/crates/api_models/src/webhooks.rs index 8931aeb1566..bad35ba477c 100644 --- a/crates/api_models/src/webhooks.rs +++ b/crates/api_models/src/webhooks.rs @@ -278,11 +278,42 @@ impl ObjectReferenceId { Self::AdditionalRevenueRecoveryId( AdditionalRevenueRecoveryIdType::AdditionalRevenueRecoveryCallId(data), ) => Ok(data), - _ => Err( + Self::PaymentId(_) => Err( common_utils::errors::ValidationError::IncorrectValueProvided { - field_name: "AdditionalRevenueRecoveryId is null", + field_name: "AdditionalRevenueRecoveryId is required but received PaymentId", }, ), + Self::RefundId(_) => Err( + common_utils::errors::ValidationError::IncorrectValueProvided { + field_name: "AdditionalRevenueRecoveryId is required but received RefundId", + }, + ), + Self::MandateId(_) => Err( + common_utils::errors::ValidationError::IncorrectValueProvided { + field_name: "AdditionalRevenueRecoveryId is required but received MandateId", + }, + ), + Self::ExternalAuthenticationID(_) => Err( + common_utils::errors::ValidationError::IncorrectValueProvided { + field_name: "AdditionalRevenueRecoveryId is required but received ExternalAuthenticationID", + }, + ), + #[cfg(feature = "payouts")] + Self::PayoutId(_) => Err( + common_utils::errors::ValidationError::IncorrectValueProvided { + field_name: "AdditionalRevenueRecoveryId is required but received PayoutId", + }, + ), + Self::InvoiceId(_) => Err( + common_utils::errors::ValidationError::IncorrectValueProvided { + field_name: "AdditionalRevenueRecoveryId is required but received InvoiceId", + }, + ), + // Self::AdditionalRevenueRecoveryId(variant) => Err( + // common_utils::errors::ValidationError::IncorrectValueProvided { + // field_name: format!("AdditionalRevenueRecoveryId of type AdditionalRevenueRecoveryCallId is required but received {:?}", variant).as_str(), + // }, + // ) } } } diff --git a/crates/router/src/core/webhooks/recovery_incoming.rs b/crates/router/src/core/webhooks/recovery_incoming.rs index f17310538ba..395526adc45 100644 --- a/crates/router/src/core/webhooks/recovery_incoming.rs +++ b/crates/router/src/core/webhooks/recovery_incoming.rs @@ -67,33 +67,37 @@ pub async fn recovery_incoming_webhook_flow( .change_context(errors::RevenueRecoveryError::InvoiceWebhookProcessingFailed) .attach_printable_lazy(|| format!("unable to parse connector name {connector_name:?}"))?; - let recovery_details = match connectors_with_additional_recovery_details_call - .connectors_with_additional_revenue_recovery_details_call - .contains(&connector) - { - true => { - let additional_revenue_recovery_id = object_ref_id - .clone() - .get_additional_revenue_recovery_id_as_string() - .change_context(errors::RevenueRecoveryError::AdditionalRevenueRecoveryCallFailed) - .attach_printable( - "Cannot get additional revenue reovery id from object reference id", - )?; - - let additional_call_response = - AdditionalRevenueRecoveryResponse::handle_additional_recovery_details_call( - &state, - &merchant_account, - &billing_connector_account, - connector_name, - &additional_revenue_recovery_id, - ) - .await? - .inner(); - Some(additional_call_response) + let recovery_details = connectors_with_additional_recovery_details_call + .connectors_with_additional_revenue_recovery_details_call + .contains(&connector) + .then(|| { + object_ref_id + .clone() + .get_additional_revenue_recovery_id_as_string() + .change_context(errors::RevenueRecoveryError::AdditionalRevenueRecoveryCallFailed) + .attach_printable( + "Cannot get additional revenue recovery id from object reference id", + ) + }) + .transpose()? + .async_map(|id|{ + let state_ref = &state; + let merchant_account_ref = &merchant_account; + let billing_connector_account_ref = &billing_connector_account; + let connector_name_ref = &connector_name; + async move { + AdditionalRevenueRecoveryResponse::handle_additional_recovery_details_call( + state_ref, + merchant_account_ref, + billing_connector_account_ref, + connector_name_ref, + id.as_str(), //id is moved here, since it is an owned value. + ).await + .map(|response| response.inner()) } - false => None, - }; + } + ).await + .transpose()?; // 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 @@ -138,9 +142,9 @@ pub async fn recovery_incoming_webhook_flow( .await?; let payment_attempt = match event_type.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 = recovery_details.as_ref().map_or_else( || { interface_webhooks::IncomingWebhook::get_revenue_recovery_attempt_details( From ca9211121c2f6f43c9f427670b206b617a312106 Mon Sep 17 00:00:00 2001 From: "hyperswitch-bot[bot]" <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Date: Fri, 21 Mar 2025 14:09:54 +0000 Subject: [PATCH 67/83] chore: run formatter --- .../src/core/webhooks/recovery_incoming.rs | 62 +++++++++---------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/crates/router/src/core/webhooks/recovery_incoming.rs b/crates/router/src/core/webhooks/recovery_incoming.rs index 395526adc45..205bd6e9207 100644 --- a/crates/router/src/core/webhooks/recovery_incoming.rs +++ b/crates/router/src/core/webhooks/recovery_incoming.rs @@ -68,36 +68,37 @@ pub async fn recovery_incoming_webhook_flow( .attach_printable_lazy(|| format!("unable to parse connector name {connector_name:?}"))?; let recovery_details = connectors_with_additional_recovery_details_call - .connectors_with_additional_revenue_recovery_details_call - .contains(&connector) - .then(|| { - object_ref_id - .clone() - .get_additional_revenue_recovery_id_as_string() - .change_context(errors::RevenueRecoveryError::AdditionalRevenueRecoveryCallFailed) - .attach_printable( - "Cannot get additional revenue recovery id from object reference id", - ) - }) - .transpose()? - .async_map(|id|{ - let state_ref = &state; - let merchant_account_ref = &merchant_account; - let billing_connector_account_ref = &billing_connector_account; - let connector_name_ref = &connector_name; - async move { - AdditionalRevenueRecoveryResponse::handle_additional_recovery_details_call( - state_ref, - merchant_account_ref, - billing_connector_account_ref, - connector_name_ref, - id.as_str(), //id is moved here, since it is an owned value. - ).await - .map(|response| response.inner()) - } - } - ).await - .transpose()?; + .connectors_with_additional_revenue_recovery_details_call + .contains(&connector) + .then(|| { + object_ref_id + .clone() + .get_additional_revenue_recovery_id_as_string() + .change_context(errors::RevenueRecoveryError::AdditionalRevenueRecoveryCallFailed) + .attach_printable( + "Cannot get additional revenue recovery id from object reference id", + ) + }) + .transpose()? + .async_map(|id| { + let state_ref = &state; + let merchant_account_ref = &merchant_account; + let billing_connector_account_ref = &billing_connector_account; + let connector_name_ref = &connector_name; + async move { + AdditionalRevenueRecoveryResponse::handle_additional_recovery_details_call( + state_ref, + merchant_account_ref, + billing_connector_account_ref, + connector_name_ref, + id.as_str(), //id is moved here, since it is an owned value. + ) + .await + .map(|response| response.inner()) + } + }) + .await + .transpose()?; // 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 @@ -142,7 +143,6 @@ pub async fn recovery_incoming_webhook_flow( .await?; let payment_attempt = match event_type.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 = recovery_details.as_ref().map_or_else( From 3da0b3dcafdce2c64e83bfa20f0a6e24fa729e82 Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Fri, 21 Mar 2025 20:04:20 +0530 Subject: [PATCH 68/83] specific import resolve --- crates/router/src/core/webhooks/recovery_incoming.rs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/crates/router/src/core/webhooks/recovery_incoming.rs b/crates/router/src/core/webhooks/recovery_incoming.rs index 205bd6e9207..b007fbd3451 100644 --- a/crates/router/src/core/webhooks/recovery_incoming.rs +++ b/crates/router/src/core/webhooks/recovery_incoming.rs @@ -26,12 +26,7 @@ use crate::{ db::StorageInterface, routes::{app::ReqState, metrics, SessionState}, services::{self, connector_integration_interface}, - types::{ - self, - api::{self, ConnectorData, GetToken}, - domain, - storage::passive_churn_recovery as storage_churn_recovery, - }, + types::{self, api, domain, storage::passive_churn_recovery as storage_churn_recovery}, workflows::passive_churn_recovery_workflow, }; @@ -624,10 +619,10 @@ impl AdditionalRevenueRecoveryResponse { connector_name: &str, id: &str, ) -> CustomResult { - let connector_data = ConnectorData::get_connector_by_name( + let connector_data = api::ConnectorData::get_connector_by_name( &state.conf.connectors, connector_name, - GetToken::Connector, + api::GetToken::Connector, None, ) .change_context(errors::RevenueRecoveryError::AdditionalRevenueRecoveryCallFailed) From 404d5fb31aacb227b42d061810999cc1fe6670e9 Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Mon, 24 Mar 2025 00:59:31 +0530 Subject: [PATCH 69/83] use router data v2 and converts it into v1 while calling --- .../src/core/webhooks/recovery_incoming.rs | 148 ++++++++++-------- .../router/src/services/conversion_impls.rs | 7 +- 2 files changed, 87 insertions(+), 68 deletions(-) diff --git a/crates/router/src/core/webhooks/recovery_incoming.rs b/crates/router/src/core/webhooks/recovery_incoming.rs index b007fbd3451..e1edc0c17c4 100644 --- a/crates/router/src/core/webhooks/recovery_incoming.rs +++ b/crates/router/src/core/webhooks/recovery_incoming.rs @@ -8,15 +8,12 @@ use common_utils::{ 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, - router_flow_types::GetAdditionalRevenueRecoveryDetails, - router_request_types::revenue_recovery::GetAdditionalRevenueRecoveryRequestData, - router_response_types::revenue_recovery::GetAdditionalRevenueRecoveryResponseData, - types::AdditionalRevenueRecoveryDetailsRouterData, + errors::api_error_response, revenue_recovery, router_data_v2::flow_common_types::GetAdditionalRevenueRecoveryFlowCommonData, router_flow_types::GetAdditionalRevenueRecoveryDetails, router_request_types::revenue_recovery::GetAdditionalRevenueRecoveryRequestData, router_response_types::revenue_recovery::GetAdditionalRevenueRecoveryResponseData, types::AdditionalRevenueRecoveryDetailsRouterData }; use hyperswitch_interfaces::webhooks as interface_webhooks; use router_env::{instrument, tracing}; use serde_with::rust::unwrap_or_skip; +use crate::services::connector_integration_interface::RouterDataConversion; use crate::{ core::{ @@ -202,6 +199,72 @@ pub async fn recovery_incoming_webhook_flow( false => None, }; + // let payment_attempt = event_type.is_recovery_transaction_event().then( + // || { + // recovery_details.as_ref().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(RevenueRecoveryAttempt( + // revenue_recovery::RevenueRecoveryAttemptData::from(data), + // )) + // }, + // ) + // } + // ). + // transpose()? + // .async_map(|invoice_transaction_details| async { + + // // 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?, + // ) + // }).await; + let attempt_triggered_by = payment_attempt .as_ref() .and_then(revenue_recovery::RecoveryPaymentAttempt::get_attempt_triggered_by); @@ -602,12 +665,6 @@ impl RevenueRecoveryAttempt { } } -const IRRELEVANT_ATTEMPT_ID_IN_ADDITIONAL_REVENUE_RECOVERY_CALL_FLOW: &str = - "irrelevant_attempt_id_in_additional_revenue_recovery_flow"; - -const IRRELEVANT_CONNECTOR_REQUEST_REFERENCE_ID_IN_ADDITIONAL_REVENUE_RECOVERY_CALL: &str = - "irrelevant_connector_request_reference_id_in_additional_revenue_recovery_flow"; - pub struct AdditionalRevenueRecoveryResponse(GetAdditionalRevenueRecoveryResponseData); pub struct AdditionalRevenueRecoveryRouterData(AdditionalRevenueRecoveryDetailsRouterData); @@ -691,68 +748,27 @@ impl AdditionalRevenueRecoveryRouterData { .parse_value("ConnectorAuthType") .change_context(errors::RevenueRecoveryError::AdditionalRevenueRecoveryCallFailed)?; - let router_data = types::RouterData { - flow: PhantomData, - merchant_id: merchant_account.get_id().clone(), - connector: connector_name.to_string(), - customer_id: None, - tenant_id: state.tenant.tenant_id.clone(), - payment_id: id_type::PaymentId::get_irrelevant_id( - "additional revenue recovery details call flow", - ) - .get_string_repr() - .to_owned(), - attempt_id: IRRELEVANT_ATTEMPT_ID_IN_ADDITIONAL_REVENUE_RECOVERY_CALL_FLOW.to_string(), - status: diesel_models::enums::AttemptStatus::default(), - payment_method: diesel_models::enums::PaymentMethod::default(), + let router_data = types::RouterDataV2{ + flow: PhantomData::, + tenant_id : state.tenant.tenant_id.clone(), + resource_common_data: GetAdditionalRevenueRecoveryFlowCommonData, connector_auth_type: auth_type, - description: None, - address: hyperswitch_domain_models::payment_address::PaymentAddress::default(), - auth_type: diesel_models::enums::AuthenticationType::default(), - connector_meta_data: None, - connector_wallets_details: None, - amount_captured: None, - minor_amount_captured: None, - request: GetAdditionalRevenueRecoveryRequestData { + request : GetAdditionalRevenueRecoveryRequestData { additional_revenue_recovery_id: additional_revenue_recovery_id.to_string(), }, - response: Err(types::ErrorResponse::default()), - access_token: None, - session_token: None, - reference_id: None, - payment_method_token: None, - connector_customer: None, - recurring_mandate_payment_data: None, - preprocessing_id: None, - connector_request_reference_id: - IRRELEVANT_CONNECTOR_REQUEST_REFERENCE_ID_IN_ADDITIONAL_REVENUE_RECOVERY_CALL - .to_string(), - #[cfg(feature = "payouts")] - payout_method_data: None, - #[cfg(feature = "payouts")] - quote_id: None, - test_mode: None, - payment_method_balance: None, - payment_method_status: None, - connector_api_version: None, - connector_http_status_code: None, - external_latency: None, - apple_pay_flow: None, - frm_metadata: None, - refund_id: None, - dispute_id: None, - connector_response: None, - integrity_check: Ok(()), - additional_merchant_data: None, - header_payload: None, - connector_mandate_request_reference_id: None, - authentication_id: None, - psd2_sca_exemption_type: None, + response: Err(types::ErrorResponse::default()) }; - Ok(Self(router_data)) + + let old_router_data = GetAdditionalRevenueRecoveryFlowCommonData::to_old_router_data(router_data) + .change_context(errors::RevenueRecoveryError::AdditionalRevenueRecoveryCallFailed) + .attach_printable("Cannot construct router data for making the additional call")?; + + Ok(Self(old_router_data)) + } fn inner(self) -> AdditionalRevenueRecoveryDetailsRouterData { self.0 } + } diff --git a/crates/router/src/services/conversion_impls.rs b/crates/router/src/services/conversion_impls.rs index 71ac0e883de..e7a34d0cae8 100644 --- a/crates/router/src/services/conversion_impls.rs +++ b/crates/router/src/services/conversion_impls.rs @@ -828,10 +828,13 @@ impl RouterDataConversion { let router_data = get_default_router_data( new_router_data.tenant_id.clone(), - "getadditionalrecoverydetails", + "getadditionalreenuerecoverydetails", new_router_data.request, new_router_data.response, ); - Ok(router_data) + Ok(RouterData{ + connector_auth_type : new_router_data.connector_auth_type.clone(), + ..router_data + }) } } From d4a64e2d19fb08bdefacf83902645444a9abec78 Mon Sep 17 00:00:00 2001 From: "hyperswitch-bot[bot]" <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Date: Sun, 23 Mar 2025 19:30:21 +0000 Subject: [PATCH 70/83] chore: run formatter --- .../src/core/webhooks/recovery_incoming.rs | 32 +++++++++++-------- .../router/src/services/conversion_impls.rs | 4 +-- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/crates/router/src/core/webhooks/recovery_incoming.rs b/crates/router/src/core/webhooks/recovery_incoming.rs index e1edc0c17c4..d125c2edb66 100644 --- a/crates/router/src/core/webhooks/recovery_incoming.rs +++ b/crates/router/src/core/webhooks/recovery_incoming.rs @@ -8,12 +8,16 @@ use common_utils::{ 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, router_data_v2::flow_common_types::GetAdditionalRevenueRecoveryFlowCommonData, router_flow_types::GetAdditionalRevenueRecoveryDetails, router_request_types::revenue_recovery::GetAdditionalRevenueRecoveryRequestData, router_response_types::revenue_recovery::GetAdditionalRevenueRecoveryResponseData, types::AdditionalRevenueRecoveryDetailsRouterData + errors::api_error_response, revenue_recovery, + router_data_v2::flow_common_types::GetAdditionalRevenueRecoveryFlowCommonData, + router_flow_types::GetAdditionalRevenueRecoveryDetails, + router_request_types::revenue_recovery::GetAdditionalRevenueRecoveryRequestData, + router_response_types::revenue_recovery::GetAdditionalRevenueRecoveryResponseData, + types::AdditionalRevenueRecoveryDetailsRouterData, }; use hyperswitch_interfaces::webhooks as interface_webhooks; use router_env::{instrument, tracing}; use serde_with::rust::unwrap_or_skip; -use crate::services::connector_integration_interface::RouterDataConversion; use crate::{ core::{ @@ -22,7 +26,10 @@ use crate::{ }, db::StorageInterface, routes::{app::ReqState, metrics, SessionState}, - services::{self, connector_integration_interface}, + services::{ + self, connector_integration_interface, + connector_integration_interface::RouterDataConversion, + }, types::{self, api, domain, storage::passive_churn_recovery as storage_churn_recovery}, workflows::passive_churn_recovery_workflow, }; @@ -200,7 +207,7 @@ pub async fn recovery_incoming_webhook_flow( }; // let payment_attempt = event_type.is_recovery_transaction_event().then( - // || { + // || { // recovery_details.as_ref().map_or_else( // || { // interface_webhooks::IncomingWebhook::get_revenue_recovery_attempt_details( @@ -748,27 +755,26 @@ impl AdditionalRevenueRecoveryRouterData { .parse_value("ConnectorAuthType") .change_context(errors::RevenueRecoveryError::AdditionalRevenueRecoveryCallFailed)?; - let router_data = types::RouterDataV2{ + let router_data = types::RouterDataV2 { flow: PhantomData::, - tenant_id : state.tenant.tenant_id.clone(), + tenant_id: state.tenant.tenant_id.clone(), resource_common_data: GetAdditionalRevenueRecoveryFlowCommonData, connector_auth_type: auth_type, - request : GetAdditionalRevenueRecoveryRequestData { + request: GetAdditionalRevenueRecoveryRequestData { additional_revenue_recovery_id: additional_revenue_recovery_id.to_string(), }, - response: Err(types::ErrorResponse::default()) + response: Err(types::ErrorResponse::default()), }; - let old_router_data = GetAdditionalRevenueRecoveryFlowCommonData::to_old_router_data(router_data) - .change_context(errors::RevenueRecoveryError::AdditionalRevenueRecoveryCallFailed) - .attach_printable("Cannot construct router data for making the additional call")?; + let old_router_data = + GetAdditionalRevenueRecoveryFlowCommonData::to_old_router_data(router_data) + .change_context(errors::RevenueRecoveryError::AdditionalRevenueRecoveryCallFailed) + .attach_printable("Cannot construct router data for making the additional call")?; Ok(Self(old_router_data)) - } fn inner(self) -> AdditionalRevenueRecoveryDetailsRouterData { self.0 } - } diff --git a/crates/router/src/services/conversion_impls.rs b/crates/router/src/services/conversion_impls.rs index e7a34d0cae8..b371fc35a4e 100644 --- a/crates/router/src/services/conversion_impls.rs +++ b/crates/router/src/services/conversion_impls.rs @@ -832,8 +832,8 @@ impl RouterDataConversion new_router_data.request, new_router_data.response, ); - Ok(RouterData{ - connector_auth_type : new_router_data.connector_auth_type.clone(), + Ok(RouterData { + connector_auth_type: new_router_data.connector_auth_type.clone(), ..router_data }) } From bb63b04676ba5a8518737e6902e64734e062aa71 Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Mon, 24 Mar 2025 12:26:23 +0530 Subject: [PATCH 71/83] refactor minor changes --- .../src/core/webhooks/recovery_incoming.rs | 71 +------------------ 1 file changed, 1 insertion(+), 70 deletions(-) diff --git a/crates/router/src/core/webhooks/recovery_incoming.rs b/crates/router/src/core/webhooks/recovery_incoming.rs index d125c2edb66..78ef5749abc 100644 --- a/crates/router/src/core/webhooks/recovery_incoming.rs +++ b/crates/router/src/core/webhooks/recovery_incoming.rs @@ -141,8 +141,7 @@ pub async fn recovery_incoming_webhook_flow( }) .await?; - let payment_attempt = match event_type.is_recovery_transaction_event() { - true => { + let payment_attempt = if event_type.is_recovery_transaction_event() { // 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 = recovery_details.as_ref().map_or_else( || { @@ -202,76 +201,8 @@ pub async fn recovery_incoming_webhook_flow( }) .await?, ) - } - false => None, }; - // let payment_attempt = event_type.is_recovery_transaction_event().then( - // || { - // recovery_details.as_ref().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(RevenueRecoveryAttempt( - // revenue_recovery::RevenueRecoveryAttemptData::from(data), - // )) - // }, - // ) - // } - // ). - // transpose()? - // .async_map(|invoice_transaction_details| async { - - // // 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?, - // ) - // }).await; - let attempt_triggered_by = payment_attempt .as_ref() .and_then(revenue_recovery::RecoveryPaymentAttempt::get_attempt_triggered_by); From 756edcba9b3e154e2a835ffdbce3028491560c34 Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Mon, 24 Mar 2025 12:34:15 +0530 Subject: [PATCH 72/83] formatter --- .../src/core/webhooks/recovery_incoming.rs | 106 +++++++++--------- 1 file changed, 51 insertions(+), 55 deletions(-) diff --git a/crates/router/src/core/webhooks/recovery_incoming.rs b/crates/router/src/core/webhooks/recovery_incoming.rs index 78ef5749abc..496be6d3f26 100644 --- a/crates/router/src/core/webhooks/recovery_incoming.rs +++ b/crates/router/src/core/webhooks/recovery_incoming.rs @@ -142,65 +142,61 @@ pub async fn recovery_incoming_webhook_flow( .await?; let payment_attempt = if event_type.is_recovery_transaction_event() { - // 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 = recovery_details.as_ref().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(RevenueRecoveryAttempt( - revenue_recovery::RevenueRecoveryAttemptData::from(data), - )) - }, - )?; + // 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 = recovery_details.as_ref().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(RevenueRecoveryAttempt( + revenue_recovery::RevenueRecoveryAttemptData::from(data), + )) + }, + )?; + + // 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?; - // 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( + Some( + invoice_transaction_details + .get_payment_attempt( &state, + &req_state, + &merchant_account, + &business_profile, &key_store, - &billing_connector_account, + payment_intent.payment_id.clone(), ) - .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?, - ) + .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?, + ) + } else { + None }; let attempt_triggered_by = payment_attempt From 2b14293ee05110f9255641099d7c9723b732cfe8 Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Mon, 24 Mar 2025 13:45:16 +0530 Subject: [PATCH 73/83] format code --- .../src/connectors/stripebilling.rs | 14 ++++++++++---- .../src/connectors/stripebilling/transformers.rs | 14 ++++++++++---- .../src/revenue_recovery.rs | 2 +- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/crates/hyperswitch_connectors/src/connectors/stripebilling.rs b/crates/hyperswitch_connectors/src/connectors/stripebilling.rs index 4231628cc5b..43247810f0c 100644 --- a/crates/hyperswitch_connectors/src/connectors/stripebilling.rs +++ b/crates/hyperswitch_connectors/src/connectors/stripebilling.rs @@ -31,10 +31,16 @@ use hyperswitch_domain_models::{ }; #[cfg(all(feature = "v2", feature = "revenue_recovery"))] use hyperswitch_domain_models::{ - router_flow_types::revenue_recovery::{GetAdditionalRevenueRecoveryDetails,RecoveryRecordBack}, - router_request_types::revenue_recovery::{GetAdditionalRevenueRecoveryRequestData,RevenueRecoveryRecordBackRequest}, - router_response_types::revenue_recovery::{GetAdditionalRevenueRecoveryResponseData,RevenueRecoveryRecordBackResponse}, - types::{AdditionalRevenueRecoveryDetailsRouterData,RevenueRecoveryRecordBackRouterData}, + router_flow_types::revenue_recovery::{ + GetAdditionalRevenueRecoveryDetails, RecoveryRecordBack, + }, + router_request_types::revenue_recovery::{ + GetAdditionalRevenueRecoveryRequestData, RevenueRecoveryRecordBackRequest, + }, + router_response_types::revenue_recovery::{ + GetAdditionalRevenueRecoveryResponseData, RevenueRecoveryRecordBackResponse, + }, + types::{AdditionalRevenueRecoveryDetailsRouterData, RevenueRecoveryRecordBackRouterData}, }; use hyperswitch_interfaces::{ api::{ diff --git a/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs b/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs index 51fe8a40dbe..f4e4735ffe7 100644 --- a/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs @@ -18,10 +18,16 @@ use hyperswitch_domain_models::{ }; #[cfg(all(feature = "v2", feature = "revenue_recovery"))] use hyperswitch_domain_models::{ - router_flow_types::revenue_recovery::{GetAdditionalRevenueRecoveryDetails,RecoveryRecordBack}, - router_request_types::revenue_recovery::{GetAdditionalRevenueRecoveryRequestData,RevenueRecoveryRecordBackRequest}, - router_response_types::revenue_recovery::{GetAdditionalRevenueRecoveryResponseData,RevenueRecoveryRecordBackResponse}, - types::{AdditionalRevenueRecoveryDetailsRouterData,RevenueRecoveryRecordBackRouterData}, + router_flow_types::revenue_recovery::{ + GetAdditionalRevenueRecoveryDetails, RecoveryRecordBack, + }, + router_request_types::revenue_recovery::{ + GetAdditionalRevenueRecoveryRequestData, RevenueRecoveryRecordBackRequest, + }, + router_response_types::revenue_recovery::{ + GetAdditionalRevenueRecoveryResponseData, RevenueRecoveryRecordBackResponse, + }, + types::{AdditionalRevenueRecoveryDetailsRouterData, RevenueRecoveryRecordBackRouterData}, }; use hyperswitch_interfaces::errors; use masking::Secret; diff --git a/crates/hyperswitch_domain_models/src/revenue_recovery.rs b/crates/hyperswitch_domain_models/src/revenue_recovery.rs index 6bd90c961e8..e474df17f6e 100644 --- a/crates/hyperswitch_domain_models/src/revenue_recovery.rs +++ b/crates/hyperswitch_domain_models/src/revenue_recovery.rs @@ -218,7 +218,7 @@ impl From<&GetAdditionalRevenueRecoveryResponseData> for RevenueRecoveryAttemptD transaction_created_at: data.transaction_created_at, status: data.status, payment_method_type: data.payment_method_type, - payment_method_sub_type: data.payment_method_sub_type, + payment_method_sub_type: Some(data.payment_method_sub_type), } } } From 8a107d851971446bed90a1e2e9aeafd3256d9aed Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Mon, 24 Mar 2025 14:26:35 +0530 Subject: [PATCH 74/83] handle other additional revenue recovery id types --- crates/api_models/src/webhooks.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/api_models/src/webhooks.rs b/crates/api_models/src/webhooks.rs index bad35ba477c..48be7f6e6b2 100644 --- a/crates/api_models/src/webhooks.rs +++ b/crates/api_models/src/webhooks.rs @@ -309,11 +309,11 @@ impl ObjectReferenceId { field_name: "AdditionalRevenueRecoveryId is required but received InvoiceId", }, ), - // Self::AdditionalRevenueRecoveryId(variant) => Err( - // common_utils::errors::ValidationError::IncorrectValueProvided { - // field_name: format!("AdditionalRevenueRecoveryId of type AdditionalRevenueRecoveryCallId is required but received {:?}", variant).as_str(), - // }, - // ) + Self::AdditionalRevenueRecoveryId(_) => Err( + common_utils::errors::ValidationError::IncorrectValueProvided { + field_name: "AdditionalRevenueRecoveryId of type AdditionalRevenueRecoveryCallId is required but received other variant", + }, + ) } } } From 59fd0666e74b927de8f1cd1e4dad5a24b7b42028 Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Tue, 25 Mar 2025 14:15:50 +0530 Subject: [PATCH 75/83] remove unnecesssary comment --- crates/router/src/core/webhooks/recovery_incoming.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/router/src/core/webhooks/recovery_incoming.rs b/crates/router/src/core/webhooks/recovery_incoming.rs index 496be6d3f26..585f61aaa2f 100644 --- a/crates/router/src/core/webhooks/recovery_incoming.rs +++ b/crates/router/src/core/webhooks/recovery_incoming.rs @@ -90,7 +90,7 @@ pub async fn recovery_incoming_webhook_flow( merchant_account_ref, billing_connector_account_ref, connector_name_ref, - id.as_str(), //id is moved here, since it is an owned value. + id.as_str(), ) .await .map(|response| response.inner()) From 76ca75bfeda1f93ae4815b2d969c7aa0bccd5586 Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Wed, 26 Mar 2025 17:47:50 +0530 Subject: [PATCH 76/83] refactor(webhooks): remove AdditionalRevenueRecoveryId and update related logic --- crates/api_models/src/webhooks.rs | 35 +- .../src/connectors/stripebilling.rs | 4 +- .../src/core/webhooks/recovery_incoming.rs | 356 +++++++++++------- 3 files changed, 240 insertions(+), 155 deletions(-) diff --git a/crates/api_models/src/webhooks.rs b/crates/api_models/src/webhooks.rs index 48be7f6e6b2..aa26f55fa75 100644 --- a/crates/api_models/src/webhooks.rs +++ b/crates/api_models/src/webhooks.rs @@ -253,8 +253,6 @@ pub enum ObjectReferenceId { PayoutId(PayoutIdType), #[cfg(all(feature = "revenue_recovery", feature = "v2"))] InvoiceId(InvoiceIdType), - #[cfg(all(feature = "revenue_recovery", feature = "v2"))] - AdditionalRevenueRecoveryId(AdditionalRevenueRecoveryIdType), } #[cfg(all(feature = "revenue_recovery", feature = "v2"))] @@ -263,55 +261,44 @@ pub enum InvoiceIdType { ConnectorInvoiceId(String), } -#[cfg(all(feature = "revenue_recovery", feature = "v2"))] -#[derive(Clone)] -pub enum AdditionalRevenueRecoveryIdType { - AdditionalRevenueRecoveryCallId(String), -} - #[cfg(all(feature = "revenue_recovery", feature = "v2"))] impl ObjectReferenceId { - pub fn get_additional_revenue_recovery_id_as_string( + pub fn get_connector_transaction_id_as_string( self, ) -> Result { match self { - Self::AdditionalRevenueRecoveryId( - AdditionalRevenueRecoveryIdType::AdditionalRevenueRecoveryCallId(data), - ) => Ok(data), - Self::PaymentId(_) => Err( + Self::PaymentId( + payments::PaymentIdType::ConnectorTransactionId(id) + ) => Ok(id), + Self::PaymentId(_)=>Err( common_utils::errors::ValidationError::IncorrectValueProvided { - field_name: "AdditionalRevenueRecoveryId is required but received PaymentId", + field_name: "ConnectorTransactionId variant of PaymentId is required but received otherr variant", }, ), Self::RefundId(_) => Err( common_utils::errors::ValidationError::IncorrectValueProvided { - field_name: "AdditionalRevenueRecoveryId is required but received RefundId", + field_name: "PaymentId is required but received RefundId", }, ), Self::MandateId(_) => Err( common_utils::errors::ValidationError::IncorrectValueProvided { - field_name: "AdditionalRevenueRecoveryId is required but received MandateId", + field_name: "PaymentId is required but received MandateId", }, ), Self::ExternalAuthenticationID(_) => Err( common_utils::errors::ValidationError::IncorrectValueProvided { - field_name: "AdditionalRevenueRecoveryId is required but received ExternalAuthenticationID", + field_name: "PaymentId is required but received ExternalAuthenticationID", }, ), #[cfg(feature = "payouts")] Self::PayoutId(_) => Err( common_utils::errors::ValidationError::IncorrectValueProvided { - field_name: "AdditionalRevenueRecoveryId is required but received PayoutId", + field_name: "PaymentId is required but received PayoutId", }, ), Self::InvoiceId(_) => Err( common_utils::errors::ValidationError::IncorrectValueProvided { - field_name: "AdditionalRevenueRecoveryId is required but received InvoiceId", - }, - ), - Self::AdditionalRevenueRecoveryId(_) => Err( - common_utils::errors::ValidationError::IncorrectValueProvided { - field_name: "AdditionalRevenueRecoveryId of type AdditionalRevenueRecoveryCallId is required but received other variant", + field_name: "PaymentId is required but received InvoiceId", }, ) } diff --git a/crates/hyperswitch_connectors/src/connectors/stripebilling.rs b/crates/hyperswitch_connectors/src/connectors/stripebilling.rs index 43247810f0c..304776a3ed1 100644 --- a/crates/hyperswitch_connectors/src/connectors/stripebilling.rs +++ b/crates/hyperswitch_connectors/src/connectors/stripebilling.rs @@ -801,8 +801,8 @@ impl webhooks::IncomingWebhook for Stripebilling { let webhook = stripebilling::StripebillingWebhookBody::get_webhook_object_from_body(request.body) .change_context(errors::ConnectorError::WebhookReferenceIdNotFound)?; - Ok(api_models::webhooks::ObjectReferenceId::AdditionalRevenueRecoveryId( - api_models::webhooks::AdditionalRevenueRecoveryIdType::AdditionalRevenueRecoveryCallId(webhook.data.object.charge), + Ok(api_models::webhooks::ObjectReferenceId::PaymentId( + api_models::payments::PaymentIdType::ConnectorTransactionId(webhook.data.object.charge), )) } diff --git a/crates/router/src/core/webhooks/recovery_incoming.rs b/crates/router/src/core/webhooks/recovery_incoming.rs index 585f61aaa2f..ca09f3b6814 100644 --- a/crates/router/src/core/webhooks/recovery_incoming.rs +++ b/crates/router/src/core/webhooks/recovery_incoming.rs @@ -8,14 +8,15 @@ use common_utils::{ 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, - router_data_v2::flow_common_types::GetAdditionalRevenueRecoveryFlowCommonData, - router_flow_types::GetAdditionalRevenueRecoveryDetails, - router_request_types::revenue_recovery::GetAdditionalRevenueRecoveryRequestData, - router_response_types::revenue_recovery::GetAdditionalRevenueRecoveryResponseData, + 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::AdditionalRevenueRecoveryDetailsRouterData, }; -use hyperswitch_interfaces::webhooks as interface_webhooks; +use hyperswitch_interfaces::{api::RevenueRecovery, webhooks as interface_webhooks}; use router_env::{instrument, tracing}; use serde_with::rust::unwrap_or_skip; @@ -24,11 +25,11 @@ use crate::{ errors::{self, CustomResult}, payments::{self, helpers}, }, - db::StorageInterface, + db::{errors::RevenueRecoveryError, StorageInterface}, routes::{app::ReqState, metrics, SessionState}, services::{ - self, connector_integration_interface, - connector_integration_interface::RouterDataConversion, + self, + connector_integration_interface::{self, RouterDataConversion}, }, types::{self, api, domain, storage::passive_churn_recovery as storage_churn_recovery}, workflows::passive_churn_recovery_workflow, @@ -59,64 +60,37 @@ pub async fn recovery_incoming_webhook_flow( )) })?; - let connectors_with_additional_recovery_details_call = - &state.conf.additional_revenue_recovery_details_call; - let connector = api_models::enums::Connector::from_str(connector_name) .change_context(errors::RevenueRecoveryError::InvoiceWebhookProcessingFailed) .attach_printable_lazy(|| format!("unable to parse connector name {connector_name:?}"))?; - let recovery_details = connectors_with_additional_recovery_details_call - .connectors_with_additional_revenue_recovery_details_call - .contains(&connector) - .then(|| { - object_ref_id - .clone() - .get_additional_revenue_recovery_id_as_string() - .change_context(errors::RevenueRecoveryError::AdditionalRevenueRecoveryCallFailed) - .attach_printable( - "Cannot get additional revenue recovery id from object reference id", - ) - }) - .transpose()? - .async_map(|id| { - let state_ref = &state; - let merchant_account_ref = &merchant_account; - let billing_connector_account_ref = &billing_connector_account; - let connector_name_ref = &connector_name; - async move { - AdditionalRevenueRecoveryResponse::handle_additional_recovery_details_call( - state_ref, - merchant_account_ref, - billing_connector_account_ref, - connector_name_ref, - id.as_str(), - ) - .await - .map(|response| response.inner()) - } - }) - .await - .transpose()?; + let billing_connectors_which_require_payment_api_call = + &state.conf.additional_revenue_recovery_details_call; + + let should_billing_connector_payment_api_called = + billing_connectors_which_require_payment_api_call + .connectors_with_additional_revenue_recovery_details_call + .contains(&connector); + + let billing_connector_payment_details = + AdditionalRevenueRecoveryResponse::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 = recovery_details.as_ref().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(RevenueRecoveryInvoice( - revenue_recovery::RevenueRecoveryInvoiceData::from(data), - )) - }, + 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( @@ -141,63 +115,23 @@ pub async fn recovery_incoming_webhook_flow( }) .await?; - let payment_attempt = if event_type.is_recovery_transaction_event() { - // 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 = recovery_details.as_ref().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(RevenueRecoveryAttempt( - revenue_recovery::RevenueRecoveryAttemptData::from(data), - )) - }, - )?; - // 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?, - ) - } else { - 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() @@ -250,6 +184,31 @@ pub struct RevenueRecoveryInvoice(revenue_recovery::RevenueRecoveryInvoiceData); 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::GetAdditionalRevenueRecoveryResponseData, + >, + ) -> CustomResult { + 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, @@ -311,12 +270,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(), @@ -347,6 +306,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::GetAdditionalRevenueRecoveryResponseData, + >, + ) -> CustomResult { + 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, @@ -358,13 +344,13 @@ impl RevenueRecoveryAttempt { ) -> CustomResult, 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(), @@ -522,6 +508,77 @@ 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::GetAdditionalRevenueRecoveryResponseData, + >, + request_details: &hyperswitch_interfaces::webhooks::IncomingWebhookRequestDetails<'_>, + merchant_account: &domain::MerchantAccount, + business_profile: &domain::Profile, + payment_intent: &revenue_recovery::RecoveryPaymentIntent + ) -> CustomResult, 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, @@ -599,7 +656,9 @@ impl RevenueRecoveryAttempt { } } -pub struct AdditionalRevenueRecoveryResponse(GetAdditionalRevenueRecoveryResponseData); +pub struct AdditionalRevenueRecoveryResponse( + revenue_recovery_response::GetAdditionalRevenueRecoveryResponseData, +); pub struct AdditionalRevenueRecoveryRouterData(AdditionalRevenueRecoveryDetailsRouterData); impl AdditionalRevenueRecoveryResponse { @@ -620,9 +679,9 @@ impl AdditionalRevenueRecoveryResponse { .attach_printable("invalid connector name received in payment attempt")?; let connector_integration: services::BoxedGetAdditionalRecoveryRecoveryDetailsIntegrationInterface< - GetAdditionalRevenueRecoveryDetails, - GetAdditionalRevenueRecoveryRequestData, - GetAdditionalRevenueRecoveryResponseData + router_flow_types::GetAdditionalRevenueRecoveryDetails, + revenue_recovery_request::GetAdditionalRevenueRecoveryRequestData, + revenue_recovery_response::GetAdditionalRevenueRecoveryResponseData > = connector_data.connector.get_connector_integration(); let router_data = @@ -662,7 +721,44 @@ impl AdditionalRevenueRecoveryResponse { Ok(Self(additional_recovery_details)) } - fn inner(self) -> GetAdditionalRevenueRecoveryResponseData { + 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, + 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::AdditionalRevenueRecoveryCallFailed, + ) + .attach_printable("Billing connector Payments api call failed")?; + let billing_connector_payment_details = + Self::handle_additional_recovery_details_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::GetAdditionalRevenueRecoveryResponseData { self.0 } } @@ -683,20 +779,22 @@ impl AdditionalRevenueRecoveryRouterData { .change_context(errors::RevenueRecoveryError::AdditionalRevenueRecoveryCallFailed)?; let router_data = types::RouterDataV2 { - flow: PhantomData::, + flow: PhantomData::, tenant_id: state.tenant.tenant_id.clone(), - resource_common_data: GetAdditionalRevenueRecoveryFlowCommonData, + resource_common_data: flow_common_types::GetAdditionalRevenueRecoveryFlowCommonData, connector_auth_type: auth_type, - request: GetAdditionalRevenueRecoveryRequestData { + request: revenue_recovery_request::GetAdditionalRevenueRecoveryRequestData { additional_revenue_recovery_id: additional_revenue_recovery_id.to_string(), }, response: Err(types::ErrorResponse::default()), }; let old_router_data = - GetAdditionalRevenueRecoveryFlowCommonData::to_old_router_data(router_data) - .change_context(errors::RevenueRecoveryError::AdditionalRevenueRecoveryCallFailed) - .attach_printable("Cannot construct router data for making the additional call")?; + flow_common_types::GetAdditionalRevenueRecoveryFlowCommonData::to_old_router_data( + router_data, + ) + .change_context(errors::RevenueRecoveryError::AdditionalRevenueRecoveryCallFailed) + .attach_printable("Cannot construct router data for making the additional call")?; Ok(Self(old_router_data)) } From b391c2d089e381d94fa2e309043e4d7e81cd7552 Mon Sep 17 00:00:00 2001 From: "hyperswitch-bot[bot]" <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Date: Wed, 26 Mar 2025 12:28:52 +0000 Subject: [PATCH 77/83] chore: run formatter --- .../src/core/webhooks/recovery_incoming.rs | 29 ++++++++----------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/crates/router/src/core/webhooks/recovery_incoming.rs b/crates/router/src/core/webhooks/recovery_incoming.rs index ca09f3b6814..fc2138b5901 100644 --- a/crates/router/src/core/webhooks/recovery_incoming.rs +++ b/crates/router/src/core/webhooks/recovery_incoming.rs @@ -8,11 +8,8 @@ use common_utils::{ 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, - router_data_v2::flow_common_types, - router_flow_types, - router_request_types::revenue_recovery as revenue_recovery_request, + 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::AdditionalRevenueRecoveryDetailsRouterData, }; @@ -115,7 +112,6 @@ pub async fn recovery_incoming_webhook_flow( }) .await?; - let is_event_recovery_transaction_event = event_type.is_recovery_transaction_event(); let payment_attempt = RevenueRecoveryAttempt::get_recovery_payment_attempt( @@ -129,7 +125,7 @@ pub async fn recovery_incoming_webhook_flow( request_details, &merchant_account, &business_profile, - &payment_intent + &payment_intent, ) .await?; @@ -522,17 +518,17 @@ impl RevenueRecoveryAttempt { request_details: &hyperswitch_interfaces::webhooks::IncomingWebhookRequestDetails<'_>, merchant_account: &domain::MerchantAccount, business_profile: &domain::Profile, - payment_intent: &revenue_recovery::RecoveryPaymentIntent - ) -> CustomResult, errors::RevenueRecoveryError> { + payment_intent: &revenue_recovery::RecoveryPaymentIntent, + ) -> CustomResult, 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, - )?; + 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 @@ -569,14 +565,13 @@ impl RevenueRecoveryAttempt { ) .await }) - .await? + .await?, ) } false => None, }; Ok(recovery_payment_attempt) - } async fn insert_execute_pcr_task( From 38678ce2a3c81469d31f2476fa10330be523b9c9 Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Wed, 26 Mar 2025 19:07:36 +0530 Subject: [PATCH 78/83] resolve conficts --- crates/common_enums/src/connector_enums.rs | 1 + .../src/default_implementations.rs | 6 +- .../src/default_implementations_v2.rs | 106 +++++++++++++++++- crates/hyperswitch_interfaces/src/api.rs | 4 +- .../src/connector_integration_v2.rs | 4 +- .../src/conversion_impls.rs | 4 +- 6 files changed, 112 insertions(+), 13 deletions(-) diff --git a/crates/common_enums/src/connector_enums.rs b/crates/common_enums/src/connector_enums.rs index a3e3d72c259..f6f7a699cb9 100644 --- a/crates/common_enums/src/connector_enums.rs +++ b/crates/common_enums/src/connector_enums.rs @@ -681,6 +681,7 @@ impl TryFrom for RoutableConnectors { Connector::Square => Ok(Self::Square), Connector::Stax => Ok(Self::Stax), Connector::Stripe => Ok(Self::Stripe), + Connector::Stripebilling => Ok(Self::Stripebilling), Connector::Trustpay => Ok(Self::Trustpay), Connector::Tsys => Ok(Self::Tsys), Connector::Volt => Ok(Self::Volt), diff --git a/crates/hyperswitch_connectors/src/default_implementations.rs b/crates/hyperswitch_connectors/src/default_implementations.rs index f345f91f18c..5bec9ea847f 100644 --- a/crates/hyperswitch_connectors/src/default_implementations.rs +++ b/crates/hyperswitch_connectors/src/default_implementations.rs @@ -100,9 +100,9 @@ use hyperswitch_interfaces::{ PaymentSessionUpdate, PaymentsCompleteAuthorize, PaymentsPostProcessing, PaymentsPreProcessing, TaxCalculation, }, - ConnectorIntegration, ConnectorMandateRevoke, ConnectorRedirectResponse, RevenueRecovery, - UasAuthentication, UasAuthenticationConfirmation, UasPostAuthentication, - UasPreAuthentication, UnifiedAuthenticationService, + ConnectorIntegration, ConnectorMandateRevoke, ConnectorRedirectResponse, + ConnectorTransactionId, RevenueRecovery, UasAuthentication, UasAuthenticationConfirmation, + UasPostAuthentication, UasPreAuthentication, UnifiedAuthenticationService, }, errors::ConnectorError, }; diff --git a/crates/hyperswitch_connectors/src/default_implementations_v2.rs b/crates/hyperswitch_connectors/src/default_implementations_v2.rs index 864f9e44986..f0bb522fae5 100644 --- a/crates/hyperswitch_connectors/src/default_implementations_v2.rs +++ b/crates/hyperswitch_connectors/src/default_implementations_v2.rs @@ -2,7 +2,8 @@ use hyperswitch_domain_models::{ router_data::AccessToken, router_data_v2::{ flow_common_types::{ - DisputesFlowData, MandateRevokeFlowData, PaymentFlowData, RefundFlowData, + DisputesFlowData, GetAdditionalRevenueRecoveryFlowCommonData, MandateRevokeFlowData, + PaymentFlowData, RefundFlowData, RevenueRecoveryRecordBackData, WebhookSourceVerifyData, }, AccessTokenFlowData, ExternalAuthenticationFlowData, FilesFlowData, @@ -21,14 +22,19 @@ use hyperswitch_domain_models::{ SetupMandate, Void, }, refunds::{Execute, RSync}, + revenue_recovery::{GetAdditionalRevenueRecoveryDetails, RecoveryRecordBack}, webhooks::VerifyWebhookSource, AccessTokenAuth, }, router_request_types::{ - authentication, AcceptDisputeRequestData, AccessTokenRequestData, - AuthorizeSessionTokenData, CompleteAuthorizeData, ConnectorCustomerData, - DefendDisputeRequestData, MandateRevokeRequestData, PaymentMethodTokenizationData, - PaymentsApproveData, PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, + authentication, + revenue_recovery::{ + GetAdditionalRevenueRecoveryRequestData, RevenueRecoveryRecordBackRequest, + }, + AcceptDisputeRequestData, AccessTokenRequestData, AuthorizeSessionTokenData, + CompleteAuthorizeData, ConnectorCustomerData, DefendDisputeRequestData, + MandateRevokeRequestData, PaymentMethodTokenizationData, PaymentsApproveData, + PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, PaymentsIncrementalAuthorizationData, PaymentsPostProcessingData, PaymentsPostSessionTokensData, PaymentsPreProcessingData, PaymentsRejectData, PaymentsSessionData, PaymentsSyncData, PaymentsTaxCalculationData, RefundsData, @@ -36,6 +42,9 @@ use hyperswitch_domain_models::{ SubmitEvidenceRequestData, UploadFileRequestData, VerifyWebhookSourceRequestData, }, router_response_types::{ + revenue_recovery::{ + GetAdditionalRevenueRecoveryResponseData, RevenueRecoveryRecordBackResponse, + }, AcceptDisputeResponse, AuthenticationResponseData, DefendDisputeResponse, MandateRevokeResponseData, PaymentsResponseData, RefundsResponseData, RetrieveFileResponse, SubmitEvidenceResponse, TaxCalculationResponseData, UploadFileResponse, @@ -88,6 +97,9 @@ use hyperswitch_interfaces::{ PaymentsPostProcessingV2, PaymentsPreProcessingV2, TaxCalculationV2, }, refunds_v2::{RefundExecuteV2, RefundSyncV2, RefundV2}, + revenue_recovery_v2::{ + AdditionalRevenueRecoveryV2, RevenueRecoveryRecordBackV2, RevenueRecoveryV2, + }, ConnectorAccessTokenV2, ConnectorMandateRevokeV2, ConnectorVerifyWebhookSourceV2, }, connector_integration_v2::ConnectorIntegrationV2, @@ -2636,3 +2648,87 @@ default_imp_for_new_connector_integration_connector_authentication!( connectors::Zen, connectors::Zsl ); + +macro_rules! default_imp_for_new_connector_integration_revenue_recovery { + ($($path:ident::$connector:ident),*) => { + $( impl RevenueRecoveryV2 for $path::$connector {} + impl AdditionalRevenueRecoveryV2 for $path::$connector {} + impl RevenueRecoveryRecordBackV2 for $path::$connector {} + impl + ConnectorIntegrationV2< + RecoveryRecordBack, + RevenueRecoveryRecordBackData, + RevenueRecoveryRecordBackRequest, + RevenueRecoveryRecordBackResponse, + > for $path::$connector + {} + impl + ConnectorIntegrationV2< + GetAdditionalRevenueRecoveryDetails, + GetAdditionalRevenueRecoveryFlowCommonData, + GetAdditionalRevenueRecoveryRequestData, + GetAdditionalRevenueRecoveryResponseData, + > for $path::$connector + {} + )* + }; +} + +default_imp_for_new_connector_integration_revenue_recovery!( + connectors::Airwallex, + connectors::Amazonpay, + connectors::Bambora, + connectors::Bamboraapac, + connectors::Billwerk, + connectors::Bitpay, + connectors::Bluesnap, + connectors::Boku, + connectors::Cashtocode, + connectors::Coinbase, + connectors::Cryptopay, + connectors::CtpMastercard, + connectors::Datatrans, + connectors::Deutschebank, + connectors::Digitalvirgo, + connectors::Dlocal, + connectors::Elavon, + connectors::Fiserv, + connectors::Fiservemea, + connectors::Fiuu, + connectors::Forte, + connectors::Globepay, + connectors::Gocardless, + connectors::Helcim, + connectors::Hipay, + connectors::Inespay, + connectors::Jpmorgan, + connectors::Juspaythreedsserver, + connectors::Nomupay, + connectors::Novalnet, + connectors::Nexinets, + connectors::Nexixpay, + connectors::Paybox, + connectors::Payeezy, + connectors::Payu, + connectors::Placetopay, + connectors::Powertranz, + connectors::Prophetpay, + connectors::Mollie, + connectors::Multisafepay, + connectors::Rapyd, + connectors::Razorpay, + connectors::Redsys, + connectors::Shift4, + connectors::Stax, + connectors::Square, + connectors::Taxjar, + connectors::Thunes, + connectors::Tsys, + connectors::UnifiedAuthenticationService, + connectors::Worldline, + connectors::Volt, + connectors::Worldpay, + connectors::Xendit, + connectors::Zen, + connectors::Zsl +); diff --git a/crates/hyperswitch_interfaces/src/api.rs b/crates/hyperswitch_interfaces/src/api.rs index 348b3f0f125..b02b876a2cd 100644 --- a/crates/hyperswitch_interfaces/src/api.rs +++ b/crates/hyperswitch_interfaces/src/api.rs @@ -73,8 +73,8 @@ pub use self::payouts::*; pub use self::payouts_v2::*; pub use self::{payments::*, refunds::*, revenue_recovery::*}; use crate::{ - api::revenue_recovery::RevenueRecovery, connector_integration_v2::ConnectorIntegrationV2, - consts, errors, events::connector_api_logs::ConnectorEvent, metrics, types, webhooks, + connector_integration_v2::ConnectorIntegrationV2, consts, errors, + events::connector_api_logs::ConnectorEvent, metrics, types, webhooks, }; /// Connector trait diff --git a/crates/hyperswitch_interfaces/src/connector_integration_v2.rs b/crates/hyperswitch_interfaces/src/connector_integration_v2.rs index 47a6588a37d..e8d994b35bb 100644 --- a/crates/hyperswitch_interfaces/src/connector_integration_v2.rs +++ b/crates/hyperswitch_interfaces/src/connector_integration_v2.rs @@ -32,6 +32,7 @@ pub trait ConnectorV2: + api::ConnectorMandateRevokeV2 + api::authentication_v2::ExternalAuthenticationV2 + api::UnifiedAuthenticationServiceV2 + + api::revenue_recovery_v2::RevenueRecoveryV2 { } impl< @@ -49,7 +50,8 @@ impl< + api::FraudCheckV2 + api::ConnectorMandateRevokeV2 + api::authentication_v2::ExternalAuthenticationV2 - + api::UnifiedAuthenticationServiceV2, + + api::UnifiedAuthenticationServiceV2 + + api::revenue_recovery_v2::RevenueRecoveryV2, > ConnectorV2 for T { } diff --git a/crates/hyperswitch_interfaces/src/conversion_impls.rs b/crates/hyperswitch_interfaces/src/conversion_impls.rs index e9ee7fc2aa5..23fb229ba37 100644 --- a/crates/hyperswitch_interfaces/src/conversion_impls.rs +++ b/crates/hyperswitch_interfaces/src/conversion_impls.rs @@ -804,7 +804,7 @@ impl RouterDataConversion { fn from_old_router_data( old_router_data: &RouterData, - ) -> errors::CustomResult, errors::ConnectorError> + ) -> CustomResult, ConnectorError> where Self: Sized, { @@ -821,7 +821,7 @@ impl RouterDataConversion fn to_old_router_data( new_router_data: RouterDataV2, - ) -> errors::CustomResult, errors::ConnectorError> + ) -> CustomResult, ConnectorError> where Self: Sized, { From cd846e1d7241fdf7ecb8edcdc1d37fceac685bcf Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Thu, 27 Mar 2025 14:58:47 +0530 Subject: [PATCH 79/83] change additional revenue recovery to billing conenctor payment sync --- config/config.example.toml | 4 +- config/development.toml | 4 +- config/docker_compose.toml | 4 +- .../src/connectors/stripebilling.rs | 58 ++++++------- .../connectors/stripebilling/transformers.rs | 46 +++++----- .../src/default_implementations.rs | 23 ++--- .../src/default_implementations_v2.rs | 34 ++++---- .../src/revenue_recovery.rs | 10 +-- .../src/router_data_v2/flow_common_types.rs | 2 +- .../src/router_flow_types/revenue_recovery.rs | 2 +- .../router_request_types/revenue_recovery.rs | 6 +- .../router_response_types/revenue_recovery.rs | 2 +- crates/hyperswitch_domain_models/src/types.rs | 14 +-- crates/hyperswitch_interfaces/src/api.rs | 6 +- .../src/api/revenue_recovery.rs | 18 ++-- .../src/api/revenue_recovery_v2.rs | 24 +++--- .../src/conversion_impls.rs | 6 +- crates/hyperswitch_interfaces/src/types.rs | 16 ++-- .../src/configs/secrets_transformers.rs | 2 +- crates/router/src/configs/settings.rs | 6 +- crates/router/src/core/errors.rs | 2 +- crates/router/src/core/payments/flows.rs | 22 ++--- .../src/core/webhooks/recovery_incoming.rs | 86 +++++++++---------- crates/router/src/services/api.rs | 4 +- crates/router/src/types.rs | 4 +- crates/router/src/types/api.rs | 2 +- 26 files changed, 198 insertions(+), 209 deletions(-) diff --git a/config/config.example.toml b/config/config.example.toml index c373cabac05..f812012ab2c 100644 --- a/config/config.example.toml +++ b/config/config.example.toml @@ -949,5 +949,5 @@ foreground_color = "#000000" # Foreground color of email tex primary_color = "#006DF9" # Primary color of email body background_color = "#FFFFFF" # Background color of email body -[additional_revenue_recovery_details_call] -connectors_with_additional_revenue_recovery_details_call = "stripebilling" # List of connectors which has additional revenue recovery details api-call +[billing_connectors_payment_sync] +billing_connectors_which_require_payment_sync = "stripebilling" # List of connectors which has additional revenue recovery details api-call diff --git a/config/development.toml b/config/development.toml index a61785cd821..ad623845d54 100644 --- a/config/development.toml +++ b/config/development.toml @@ -792,8 +792,8 @@ connectors_with_delayed_session_response = "trustpay,payme" [webhook_source_verification_call] connectors_with_webhook_source_verification_call = "paypal" -[additional_revenue_recovery_details_call] -connectors_with_additional_revenue_recovery_details_call = "stripebilling" +[billing_connectors_payment_sync] +billing_connectors_which_require_payment_sync = "stripebilling" [mandates.supported_payment_methods] bank_debit.ach = { connector_list = "gocardless,adyen,stripe" } diff --git a/config/docker_compose.toml b/config/docker_compose.toml index 0676ffa5e28..debbfedb08a 100644 --- a/config/docker_compose.toml +++ b/config/docker_compose.toml @@ -323,8 +323,8 @@ connectors_with_delayed_session_response = "trustpay,payme" [webhook_source_verification_call] connectors_with_webhook_source_verification_call = "paypal" -[additional_revenue_recovery_details_call] -connectors_with_additional_revenue_recovery_details_call = "stripebilling" +[billing_connectors_payment_sync] +billing_connectors_which_require_payment_sync = "stripebilling" [scheduler] stream = "SCHEDULER_STREAM" diff --git a/crates/hyperswitch_connectors/src/connectors/stripebilling.rs b/crates/hyperswitch_connectors/src/connectors/stripebilling.rs index 304776a3ed1..b159ed22d61 100644 --- a/crates/hyperswitch_connectors/src/connectors/stripebilling.rs +++ b/crates/hyperswitch_connectors/src/connectors/stripebilling.rs @@ -31,16 +31,10 @@ use hyperswitch_domain_models::{ }; #[cfg(all(feature = "v2", feature = "revenue_recovery"))] use hyperswitch_domain_models::{ - router_flow_types::revenue_recovery::{ - GetAdditionalRevenueRecoveryDetails, RecoveryRecordBack, - }, - router_request_types::revenue_recovery::{ - GetAdditionalRevenueRecoveryRequestData, RevenueRecoveryRecordBackRequest, - }, - router_response_types::revenue_recovery::{ - GetAdditionalRevenueRecoveryResponseData, RevenueRecoveryRecordBackResponse, - }, - types::{AdditionalRevenueRecoveryDetailsRouterData, RevenueRecoveryRecordBackRouterData}, + router_flow_types::revenue_recovery as recovery_router_flows, + router_request_types::revenue_recovery as recovery_request_types, + router_response_types::revenue_recovery as recovery_response_types, + types as recovery_router_data_types, }; use hyperswitch_interfaces::{ api::{ @@ -89,7 +83,7 @@ impl api::PaymentToken for Stripebilling {} #[cfg(all(feature = "revenue_recovery", feature = "v2"))] impl api::revenue_recovery::RevenueRecoveryRecordBack for Stripebilling {} #[cfg(all(feature = "v2", feature = "revenue_recovery"))] -impl api::AdditionalRevenueRecovery for Stripebilling {} +impl api::revenue_recovery::BillingConnectorPaymentsSyncIntegration for Stripebilling {} impl ConnectorIntegration for Stripebilling @@ -581,14 +575,14 @@ impl ConnectorIntegration for Stripebil #[cfg(all(feature = "v2", feature = "revenue_recovery"))] impl ConnectorIntegration< - GetAdditionalRevenueRecoveryDetails, - GetAdditionalRevenueRecoveryRequestData, - GetAdditionalRevenueRecoveryResponseData, + recovery_router_flows::BillingConnectorPaymentsSync, + recovery_request_types::BillingConnectorPaymentsSyncRequest, + recovery_response_types::BillingConnectorPaymentsSyncResponse, > for Stripebilling { fn get_headers( &self, - req: &AdditionalRevenueRecoveryDetailsRouterData, + req: &recovery_router_data_types::BillingConnectorPaymentsSyncRouterData, connectors: &Connectors, ) -> CustomResult)>, errors::ConnectorError> { self.build_headers(req, connectors) @@ -600,28 +594,28 @@ impl fn get_url( &self, - req: &AdditionalRevenueRecoveryDetailsRouterData, + req: &recovery_router_data_types::BillingConnectorPaymentsSyncRouterData, connectors: &Connectors, ) -> CustomResult { Ok(format!( "{}v1/charges/{}", self.base_url(connectors), - req.request.additional_revenue_recovery_id + req.request.billing_connector_psync_id )) } fn build_request( &self, - req: &AdditionalRevenueRecoveryDetailsRouterData, + req: &recovery_router_data_types::BillingConnectorPaymentsSyncRouterData, connectors: &Connectors, ) -> CustomResult, errors::ConnectorError> { let request = RequestBuilder::new() .method(Method::Get) - .url(&types::AdditionalRevenueRecoveryCallType::get_url( + .url(&types::BillingConnectorPaymentsSyncType::get_url( self, req, connectors, )?) .attach_default_headers() - .headers(types::AdditionalRevenueRecoveryCallType::get_headers( + .headers(types::BillingConnectorPaymentsSyncType::get_headers( self, req, connectors, )?) .build(); @@ -630,10 +624,10 @@ impl fn handle_response( &self, - data: &AdditionalRevenueRecoveryDetailsRouterData, + data: &recovery_router_data_types::BillingConnectorPaymentsSyncRouterData, event_builder: Option<&mut ConnectorEvent>, res: Response, - ) -> CustomResult { + ) -> CustomResult { let response: stripebilling::StripebillingRecoveryDetailsData = res .response .parse_struct::( @@ -644,7 +638,7 @@ impl event_builder.map(|i| i.set_response_body(&response)); router_env::logger::info!(connector_response=?response); - AdditionalRevenueRecoveryDetailsRouterData::try_from(ResponseRouterData { + recovery_router_data_types::BillingConnectorPaymentsSyncRouterData::try_from(ResponseRouterData { response, data: data.clone(), http_code: res.status_code, @@ -663,14 +657,14 @@ impl #[cfg(all(feature = "v2", feature = "revenue_recovery"))] impl ConnectorIntegration< - RecoveryRecordBack, - RevenueRecoveryRecordBackRequest, - RevenueRecoveryRecordBackResponse, + recovery_router_flows::RecoveryRecordBack, + recovery_request_types::RevenueRecoveryRecordBackRequest, + recovery_response_types::RevenueRecoveryRecordBackResponse, > for Stripebilling { fn get_headers( &self, - req: &RevenueRecoveryRecordBackRouterData, + req: &recovery_router_data_types::RevenueRecoveryRecordBackRouterData, connectors: &Connectors, ) -> CustomResult)>, errors::ConnectorError> { self.build_headers(req, connectors) @@ -682,7 +676,7 @@ impl fn get_url( &self, - req: &RevenueRecoveryRecordBackRouterData, + req: &recovery_router_data_types::RevenueRecoveryRecordBackRouterData, connectors: &Connectors, ) -> CustomResult { let invoice_id = req @@ -705,7 +699,7 @@ impl fn build_request( &self, - req: &RevenueRecoveryRecordBackRouterData, + req: &recovery_router_data_types::RevenueRecoveryRecordBackRouterData, connectors: &Connectors, ) -> CustomResult, errors::ConnectorError> { Ok(Some( @@ -724,10 +718,10 @@ impl fn handle_response( &self, - data: &RevenueRecoveryRecordBackRouterData, + data: &recovery_router_data_types::RevenueRecoveryRecordBackRouterData, event_builder: Option<&mut ConnectorEvent>, res: Response, - ) -> CustomResult { + ) -> CustomResult { let response = res .response .parse_struct::( @@ -736,7 +730,7 @@ impl .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; event_builder.map(|i| i.set_response_body(&response)); router_env::logger::info!(connector_response=?response); - RevenueRecoveryRecordBackRouterData::try_from(ResponseRouterData { + recovery_router_data_types::RevenueRecoveryRecordBackRouterData::try_from(ResponseRouterData { response, data: data.clone(), http_code: res.status_code, diff --git a/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs b/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs index f4e4735ffe7..fce4dc7c806 100644 --- a/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs @@ -18,16 +18,10 @@ use hyperswitch_domain_models::{ }; #[cfg(all(feature = "v2", feature = "revenue_recovery"))] use hyperswitch_domain_models::{ - router_flow_types::revenue_recovery::{ - GetAdditionalRevenueRecoveryDetails, RecoveryRecordBack, - }, - router_request_types::revenue_recovery::{ - GetAdditionalRevenueRecoveryRequestData, RevenueRecoveryRecordBackRequest, - }, - router_response_types::revenue_recovery::{ - GetAdditionalRevenueRecoveryResponseData, RevenueRecoveryRecordBackResponse, - }, - types::{AdditionalRevenueRecoveryDetailsRouterData, RevenueRecoveryRecordBackRouterData}, + router_flow_types::revenue_recovery as recovery_router_flows, + router_request_types::revenue_recovery as recovery_request_types, + router_response_types::revenue_recovery as recovery_response_types, + types as recovery_router_data_types, }; use hyperswitch_interfaces::errors; use masking::Secret; @@ -415,20 +409,20 @@ const MCA_ID_IDENTIFIER_FOR_STRIPE_IN_STRIPEBILLING_MCA_FEAATURE_METADATA: &str impl TryFrom< ResponseRouterData< - GetAdditionalRevenueRecoveryDetails, + recovery_router_flows::BillingConnectorPaymentsSync, StripebillingRecoveryDetailsData, - GetAdditionalRevenueRecoveryRequestData, - GetAdditionalRevenueRecoveryResponseData, + recovery_request_types::BillingConnectorPaymentsSyncRequest, + recovery_response_types::BillingConnectorPaymentsSyncResponse, >, - > for AdditionalRevenueRecoveryDetailsRouterData + > for recovery_router_data_types::BillingConnectorPaymentsSyncRouterData { type Error = error_stack::Report; fn try_from( item: ResponseRouterData< - GetAdditionalRevenueRecoveryDetails, + recovery_router_flows::BillingConnectorPaymentsSync, StripebillingRecoveryDetailsData, - GetAdditionalRevenueRecoveryRequestData, - GetAdditionalRevenueRecoveryResponseData, + recovery_request_types::BillingConnectorPaymentsSyncRequest, + recovery_response_types::BillingConnectorPaymentsSyncResponse, >, ) -> Result { let merchant_reference_id = id_type::PaymentReferenceId::from_str( @@ -442,7 +436,7 @@ impl )); Ok(Self { - response: Ok(GetAdditionalRevenueRecoveryResponseData { + response: Ok(recovery_response_types::BillingConnectorPaymentsSyncResponse { status: item.response.status.into(), amount: item.response.amount, currency: item.response.currency, @@ -508,24 +502,24 @@ pub struct StripebillingRecordBackResponse { impl TryFrom< ResponseRouterData< - RecoveryRecordBack, + recovery_router_flows::RecoveryRecordBack, StripebillingRecordBackResponse, - RevenueRecoveryRecordBackRequest, - RevenueRecoveryRecordBackResponse, + recovery_request_types::RevenueRecoveryRecordBackRequest, + recovery_response_types::RevenueRecoveryRecordBackResponse, >, - > for RevenueRecoveryRecordBackRouterData + > for recovery_router_data_types::RevenueRecoveryRecordBackRouterData { type Error = error_stack::Report; fn try_from( item: ResponseRouterData< - RecoveryRecordBack, + recovery_router_flows::RecoveryRecordBack, StripebillingRecordBackResponse, - RevenueRecoveryRecordBackRequest, - RevenueRecoveryRecordBackResponse, + recovery_request_types::RevenueRecoveryRecordBackRequest, + recovery_response_types::RevenueRecoveryRecordBackResponse, >, ) -> Result { Ok(Self { - response: Ok(RevenueRecoveryRecordBackResponse { + response: Ok(recovery_response_types::RevenueRecoveryRecordBackResponse { merchant_reference_id: id_type::PaymentReferenceId::from_str( item.response.id.as_str(), ) diff --git a/crates/hyperswitch_connectors/src/default_implementations.rs b/crates/hyperswitch_connectors/src/default_implementations.rs index 5bec9ea847f..2ca3f112130 100644 --- a/crates/hyperswitch_connectors/src/default_implementations.rs +++ b/crates/hyperswitch_connectors/src/default_implementations.rs @@ -25,13 +25,13 @@ use hyperswitch_domain_models::{ #[cfg(all(feature = "v2", feature = "revenue_recovery"))] use hyperswitch_domain_models::{ router_flow_types::revenue_recovery::{ - GetAdditionalRevenueRecoveryDetails, RecoveryRecordBack, + BillingConnectorPaymentsSync, RecoveryRecordBack, }, router_request_types::revenue_recovery::{ - GetAdditionalRevenueRecoveryRequestData, RevenueRecoveryRecordBackRequest, + BillingConnectorPaymentsSyncRequest, RevenueRecoveryRecordBackRequest, }, router_response_types::revenue_recovery::{ - GetAdditionalRevenueRecoveryResponseData, RevenueRecoveryRecordBackResponse, + BillingConnectorPaymentsSyncResponse, RevenueRecoveryRecordBackResponse, }, }; use hyperswitch_domain_models::{ @@ -83,7 +83,7 @@ use hyperswitch_interfaces::api::payouts::{ }; #[cfg(all(feature = "v2", feature = "revenue_recovery"))] use hyperswitch_interfaces::api::revenue_recovery::{ - AdditionalRevenueRecovery, RevenueRecoveryRecordBack, + BillingConnectorPaymentsSyncIntegration, RevenueRecoveryRecordBack, }; use hyperswitch_interfaces::{ api::{ @@ -101,8 +101,9 @@ use hyperswitch_interfaces::{ PaymentsPreProcessing, TaxCalculation, }, ConnectorIntegration, ConnectorMandateRevoke, ConnectorRedirectResponse, - ConnectorTransactionId, RevenueRecovery, UasAuthentication, UasAuthenticationConfirmation, + ConnectorTransactionId, UasAuthentication, UasAuthenticationConfirmation, UasPostAuthentication, UasPreAuthentication, UnifiedAuthenticationService, + revenue_recovery::RevenueRecovery }, errors::ConnectorError, }; @@ -4069,14 +4070,14 @@ default_imp_for_revenue_recovery! { } #[cfg(all(feature = "v2", feature = "revenue_recovery"))] -macro_rules! default_imp_for_additional_revenue_recovery_call { +macro_rules! default_imp_for_billing_connector_payment_sync { ($($path:ident::$connector:ident),*) => { - $( impl AdditionalRevenueRecovery for $path::$connector {} + $( impl BillingConnectorPaymentsSyncIntegration for $path::$connector {} impl ConnectorIntegration< - GetAdditionalRevenueRecoveryDetails, - GetAdditionalRevenueRecoveryRequestData, - GetAdditionalRevenueRecoveryResponseData + BillingConnectorPaymentsSync, + BillingConnectorPaymentsSyncRequest, + BillingConnectorPaymentsSyncResponse > for $path::$connector {} )* @@ -4084,7 +4085,7 @@ macro_rules! default_imp_for_additional_revenue_recovery_call { } #[cfg(all(feature = "v2", feature = "revenue_recovery"))] -default_imp_for_additional_revenue_recovery_call!( +default_imp_for_billing_connector_payment_sync!( connectors::Aci, connectors::Adyen, connectors::Airwallex, diff --git a/crates/hyperswitch_connectors/src/default_implementations_v2.rs b/crates/hyperswitch_connectors/src/default_implementations_v2.rs index f0bb522fae5..45a87433bfa 100644 --- a/crates/hyperswitch_connectors/src/default_implementations_v2.rs +++ b/crates/hyperswitch_connectors/src/default_implementations_v2.rs @@ -2,7 +2,7 @@ use hyperswitch_domain_models::{ router_data::AccessToken, router_data_v2::{ flow_common_types::{ - DisputesFlowData, GetAdditionalRevenueRecoveryFlowCommonData, MandateRevokeFlowData, + DisputesFlowData, BillingConnectorPaymentsSyncFlowData, MandateRevokeFlowData, PaymentFlowData, RefundFlowData, RevenueRecoveryRecordBackData, WebhookSourceVerifyData, }, @@ -22,14 +22,14 @@ use hyperswitch_domain_models::{ SetupMandate, Void, }, refunds::{Execute, RSync}, - revenue_recovery::{GetAdditionalRevenueRecoveryDetails, RecoveryRecordBack}, + revenue_recovery::{BillingConnectorPaymentsSync, RecoveryRecordBack}, webhooks::VerifyWebhookSource, AccessTokenAuth, }, router_request_types::{ authentication, revenue_recovery::{ - GetAdditionalRevenueRecoveryRequestData, RevenueRecoveryRecordBackRequest, + BillingConnectorPaymentsSyncRequest, RevenueRecoveryRecordBackRequest, }, AcceptDisputeRequestData, AccessTokenRequestData, AuthorizeSessionTokenData, CompleteAuthorizeData, ConnectorCustomerData, DefendDisputeRequestData, @@ -43,7 +43,7 @@ use hyperswitch_domain_models::{ }, router_response_types::{ revenue_recovery::{ - GetAdditionalRevenueRecoveryResponseData, RevenueRecoveryRecordBackResponse, + BillingConnectorPaymentsSyncResponse, RevenueRecoveryRecordBackResponse, }, AcceptDisputeResponse, AuthenticationResponseData, DefendDisputeResponse, MandateRevokeResponseData, PaymentsResponseData, RefundsResponseData, RetrieveFileResponse, @@ -98,7 +98,7 @@ use hyperswitch_interfaces::{ }, refunds_v2::{RefundExecuteV2, RefundSyncV2, RefundV2}, revenue_recovery_v2::{ - AdditionalRevenueRecoveryV2, RevenueRecoveryRecordBackV2, RevenueRecoveryV2, + BillingConnectorPaymentsSyncIntegrationV2, RevenueRecoveryRecordBackV2, RevenueRecoveryV2, }, ConnectorAccessTokenV2, ConnectorMandateRevokeV2, ConnectorVerifyWebhookSourceV2, }, @@ -2651,8 +2651,8 @@ default_imp_for_new_connector_integration_connector_authentication!( macro_rules! default_imp_for_new_connector_integration_revenue_recovery { ($($path:ident::$connector:ident),*) => { - $( impl RevenueRecoveryV2 for $path::$connector {} - impl AdditionalRevenueRecoveryV2 for $path::$connector {} + $( impl RevenueRecoveryV2 for $path::$connector {} + impl BillingConnectorPaymentsSyncIntegrationV2 for $path::$connector {} impl RevenueRecoveryRecordBackV2 for $path::$connector {} impl ConnectorIntegrationV2< @@ -2660,16 +2660,16 @@ macro_rules! default_imp_for_new_connector_integration_revenue_recovery { RevenueRecoveryRecordBackData, RevenueRecoveryRecordBackRequest, RevenueRecoveryRecordBackResponse, - > for $path::$connector - {} - impl - ConnectorIntegrationV2< - GetAdditionalRevenueRecoveryDetails, - GetAdditionalRevenueRecoveryFlowCommonData, - GetAdditionalRevenueRecoveryRequestData, - GetAdditionalRevenueRecoveryResponseData, - > for $path::$connector - {} + > for $path::$connector + {} + impl + ConnectorIntegrationV2< + BillingConnectorPaymentsSync, + BillingConnectorPaymentsSyncFlowData, + BillingConnectorPaymentsSyncRequest, + BillingConnectorPaymentsSyncResponse, + > for $path::$connector + {} )* }; } diff --git a/crates/hyperswitch_domain_models/src/revenue_recovery.rs b/crates/hyperswitch_domain_models/src/revenue_recovery.rs index e474df17f6e..238e84873f3 100644 --- a/crates/hyperswitch_domain_models/src/revenue_recovery.rs +++ b/crates/hyperswitch_domain_models/src/revenue_recovery.rs @@ -3,7 +3,7 @@ use common_enums::enums as common_enums; use common_utils::{id_type, types as util_types}; use time::PrimitiveDateTime; -use crate::router_response_types::revenue_recovery::GetAdditionalRevenueRecoveryResponseData; +use crate::router_response_types::revenue_recovery::BillingConnectorPaymentsSyncResponse; /// Recovery payload is unified struct constructed from billing connectors #[derive(Debug)] @@ -193,8 +193,8 @@ impl From<&RevenueRecoveryInvoiceData> for api_payments::PaymentsCreateIntentReq } } -impl From<&GetAdditionalRevenueRecoveryResponseData> for RevenueRecoveryInvoiceData { - fn from(data: &GetAdditionalRevenueRecoveryResponseData) -> Self { +impl From<&BillingConnectorPaymentsSyncResponse> for RevenueRecoveryInvoiceData { + fn from(data: &BillingConnectorPaymentsSyncResponse) -> Self { Self { amount: data.amount, currency: data.currency, @@ -203,8 +203,8 @@ impl From<&GetAdditionalRevenueRecoveryResponseData> for RevenueRecoveryInvoiceD } } -impl From<&GetAdditionalRevenueRecoveryResponseData> for RevenueRecoveryAttemptData { - fn from(data: &GetAdditionalRevenueRecoveryResponseData) -> Self { +impl From<&BillingConnectorPaymentsSyncResponse> for RevenueRecoveryAttemptData { + fn from(data: &BillingConnectorPaymentsSyncResponse) -> Self { Self { amount: data.amount, currency: data.currency, diff --git a/crates/hyperswitch_domain_models/src/router_data_v2/flow_common_types.rs b/crates/hyperswitch_domain_models/src/router_data_v2/flow_common_types.rs index 16ffcb21b79..2e689d78449 100644 --- a/crates/hyperswitch_domain_models/src/router_data_v2/flow_common_types.rs +++ b/crates/hyperswitch_domain_models/src/router_data_v2/flow_common_types.rs @@ -154,4 +154,4 @@ pub struct UasFlowData { } #[derive(Debug, Clone)] -pub struct GetAdditionalRevenueRecoveryFlowCommonData; +pub struct BillingConnectorPaymentsSyncFlowData; diff --git a/crates/hyperswitch_domain_models/src/router_flow_types/revenue_recovery.rs b/crates/hyperswitch_domain_models/src/router_flow_types/revenue_recovery.rs index 3793ea309e9..56d240614f1 100644 --- a/crates/hyperswitch_domain_models/src/router_flow_types/revenue_recovery.rs +++ b/crates/hyperswitch_domain_models/src/router_flow_types/revenue_recovery.rs @@ -1,4 +1,4 @@ #[derive(Debug, Clone)] -pub struct GetAdditionalRevenueRecoveryDetails; +pub struct BillingConnectorPaymentsSync; #[derive(Debug, Clone)] pub struct RecoveryRecordBack; diff --git a/crates/hyperswitch_domain_models/src/router_request_types/revenue_recovery.rs b/crates/hyperswitch_domain_models/src/router_request_types/revenue_recovery.rs index e1b958f2ec7..a39d27f14f1 100644 --- a/crates/hyperswitch_domain_models/src/router_request_types/revenue_recovery.rs +++ b/crates/hyperswitch_domain_models/src/router_request_types/revenue_recovery.rs @@ -1,9 +1,9 @@ use common_enums::enums; #[derive(Debug, Clone)] -pub struct GetAdditionalRevenueRecoveryRequestData { - /// unique id for making additional revenue recovery call - pub additional_revenue_recovery_id: String, +pub struct BillingConnectorPaymentsSyncRequest { + /// unique id for making billing connector psync call + pub billing_connector_psync_id: String, } #[derive(Debug, Clone)] diff --git a/crates/hyperswitch_domain_models/src/router_response_types/revenue_recovery.rs b/crates/hyperswitch_domain_models/src/router_response_types/revenue_recovery.rs index fc2cf34b792..5f79ff70012 100644 --- a/crates/hyperswitch_domain_models/src/router_response_types/revenue_recovery.rs +++ b/crates/hyperswitch_domain_models/src/router_response_types/revenue_recovery.rs @@ -1,7 +1,7 @@ use common_utils::types::MinorUnit; use time::PrimitiveDateTime; #[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] -pub struct GetAdditionalRevenueRecoveryResponseData { +pub struct BillingConnectorPaymentsSyncResponse { /// transaction amount against invoice, accepted in minor unit. pub amount: MinorUnit, /// currency of the transaction diff --git a/crates/hyperswitch_domain_models/src/types.rs b/crates/hyperswitch_domain_models/src/types.rs index b3dde94269b..c7b0a34adbf 100644 --- a/crates/hyperswitch_domain_models/src/types.rs +++ b/crates/hyperswitch_domain_models/src/types.rs @@ -6,13 +6,13 @@ use crate::{ mandate_revoke::MandateRevoke, revenue_recovery::RecoveryRecordBack, AccessTokenAuth, Authenticate, AuthenticationConfirmation, Authorize, AuthorizeSessionToken, CalculateTax, Capture, CompleteAuthorize, CreateConnectorCustomer, Execute, - GetAdditionalRevenueRecoveryDetails, IncrementalAuthorization, PSync, PaymentMethodToken, + BillingConnectorPaymentsSync, IncrementalAuthorization, PSync, PaymentMethodToken, PostAuthenticate, PostSessionTokens, PreAuthenticate, PreProcessing, RSync, SdkSessionUpdate, Session, SetupMandate, VerifyWebhookSource, Void, }, router_request_types::{ revenue_recovery::{ - GetAdditionalRevenueRecoveryRequestData, RevenueRecoveryRecordBackRequest, + BillingConnectorPaymentsSyncRequest, RevenueRecoveryRecordBackRequest, }, unified_authentication_service::{ UasAuthenticationRequestData, UasAuthenticationResponseData, @@ -29,7 +29,7 @@ use crate::{ }, router_response_types::{ revenue_recovery::{ - GetAdditionalRevenueRecoveryResponseData, RevenueRecoveryRecordBackResponse, + BillingConnectorPaymentsSyncResponse, RevenueRecoveryRecordBackResponse, }, MandateRevokeResponseData, PaymentsResponseData, RefundsResponseData, TaxCalculationResponseData, VerifyWebhookSourceResponseData, @@ -104,8 +104,8 @@ pub type RevenueRecoveryRecordBackRouterData = RouterData< pub type UasAuthenticationRouterData = RouterData; -pub type AdditionalRevenueRecoveryDetailsRouterData = RouterData< - GetAdditionalRevenueRecoveryDetails, - GetAdditionalRevenueRecoveryRequestData, - GetAdditionalRevenueRecoveryResponseData, +pub type BillingConnectorPaymentsSyncRouterData = RouterData< + BillingConnectorPaymentsSync, + BillingConnectorPaymentsSyncRequest, + BillingConnectorPaymentsSyncResponse, >; diff --git a/crates/hyperswitch_interfaces/src/api.rs b/crates/hyperswitch_interfaces/src/api.rs index b02b876a2cd..37a49f47c70 100644 --- a/crates/hyperswitch_interfaces/src/api.rs +++ b/crates/hyperswitch_interfaces/src/api.rs @@ -71,7 +71,7 @@ pub use self::fraud_check_v2::*; pub use self::payouts::*; #[cfg(feature = "payouts")] pub use self::payouts_v2::*; -pub use self::{payments::*, refunds::*, revenue_recovery::*}; +pub use self::{payments::*, refunds::*}; use crate::{ connector_integration_v2::ConnectorIntegrationV2, consts, errors, events::connector_api_logs::ConnectorEvent, metrics, types, webhooks, @@ -95,7 +95,7 @@ pub trait Connector: + authentication::ExternalAuthentication + TaxCalculation + UnifiedAuthenticationService - + RevenueRecovery + + revenue_recovery::RevenueRecovery { } @@ -116,7 +116,7 @@ impl< + authentication::ExternalAuthentication + TaxCalculation + UnifiedAuthenticationService - + RevenueRecovery, + + revenue_recovery::RevenueRecovery, > Connector for T { } diff --git a/crates/hyperswitch_interfaces/src/api/revenue_recovery.rs b/crates/hyperswitch_interfaces/src/api/revenue_recovery.rs index 5d86c515d56..6bf882159a3 100644 --- a/crates/hyperswitch_interfaces/src/api/revenue_recovery.rs +++ b/crates/hyperswitch_interfaces/src/api/revenue_recovery.rs @@ -1,12 +1,12 @@ //! Revenue Recovery Interface use hyperswitch_domain_models::{ - router_flow_types::{GetAdditionalRevenueRecoveryDetails, RecoveryRecordBack}, + router_flow_types::{BillingConnectorPaymentsSync, RecoveryRecordBack}, router_request_types::revenue_recovery::{ - GetAdditionalRevenueRecoveryRequestData, RevenueRecoveryRecordBackRequest, + BillingConnectorPaymentsSyncRequest, RevenueRecoveryRecordBackRequest, }, router_response_types::revenue_recovery::{ - GetAdditionalRevenueRecoveryResponseData, RevenueRecoveryRecordBackResponse, + BillingConnectorPaymentsSyncResponse, RevenueRecoveryRecordBackResponse, }, }; @@ -17,16 +17,16 @@ use super::ConnectorIntegration; /// trait RevenueRecovery #[cfg(all(feature = "v2", feature = "revenue_recovery"))] pub trait RevenueRecovery: - ConnectorCommon + AdditionalRevenueRecovery + RevenueRecoveryRecordBack + ConnectorCommon + BillingConnectorPaymentsSyncIntegration + RevenueRecoveryRecordBack { } -/// trait AdditionalRevenueRecovery -pub trait AdditionalRevenueRecovery: +/// trait BillingConnectorPaymentsSyncIntegration +pub trait BillingConnectorPaymentsSyncIntegration: ConnectorIntegration< - GetAdditionalRevenueRecoveryDetails, - GetAdditionalRevenueRecoveryRequestData, - GetAdditionalRevenueRecoveryResponseData, + BillingConnectorPaymentsSync, + BillingConnectorPaymentsSyncRequest, + BillingConnectorPaymentsSyncResponse, > { } diff --git a/crates/hyperswitch_interfaces/src/api/revenue_recovery_v2.rs b/crates/hyperswitch_interfaces/src/api/revenue_recovery_v2.rs index 6ae59dd6fb4..08b62d19937 100644 --- a/crates/hyperswitch_interfaces/src/api/revenue_recovery_v2.rs +++ b/crates/hyperswitch_interfaces/src/api/revenue_recovery_v2.rs @@ -2,34 +2,34 @@ use hyperswitch_domain_models::{ router_data_v2::flow_common_types::{ - GetAdditionalRevenueRecoveryFlowCommonData, RevenueRecoveryRecordBackData, + BillingConnectorPaymentsSyncFlowData, RevenueRecoveryRecordBackData, }, - router_flow_types::{GetAdditionalRevenueRecoveryDetails, RecoveryRecordBack}, + router_flow_types::{BillingConnectorPaymentsSync, RecoveryRecordBack}, router_request_types::revenue_recovery::{ - GetAdditionalRevenueRecoveryRequestData, RevenueRecoveryRecordBackRequest, + BillingConnectorPaymentsSyncRequest, RevenueRecoveryRecordBackRequest, }, router_response_types::revenue_recovery::{ - GetAdditionalRevenueRecoveryResponseData, RevenueRecoveryRecordBackResponse, + BillingConnectorPaymentsSyncResponse, RevenueRecoveryRecordBackResponse, }, }; use crate::connector_integration_v2::ConnectorIntegrationV2; /// trait RevenueRecoveryV2 -pub trait RevenueRecoveryV2: AdditionalRevenueRecoveryV2 + RevenueRecoveryRecordBackV2 {} +pub trait RevenueRecoveryV2: BillingConnectorPaymentsSyncIntegrationV2 + RevenueRecoveryRecordBackV2 {} -/// trait AdditionalRevenueRecoveryV2 -pub trait AdditionalRevenueRecoveryV2: +/// trait BillingConnectorPaymentsSyncIntegrationV2 +pub trait BillingConnectorPaymentsSyncIntegrationV2: ConnectorIntegrationV2< - GetAdditionalRevenueRecoveryDetails, - GetAdditionalRevenueRecoveryFlowCommonData, - GetAdditionalRevenueRecoveryRequestData, - GetAdditionalRevenueRecoveryResponseData, + BillingConnectorPaymentsSync, + BillingConnectorPaymentsSyncFlowData, + BillingConnectorPaymentsSyncRequest, + BillingConnectorPaymentsSyncResponse, > { } -/// trait ConnectorAdditionalRevenueRecoveryDetailsCallV2 +/// trait RevenueRecoveryRecordBackV2 pub trait RevenueRecoveryRecordBackV2: ConnectorIntegrationV2< RecoveryRecordBack, diff --git a/crates/hyperswitch_interfaces/src/conversion_impls.rs b/crates/hyperswitch_interfaces/src/conversion_impls.rs index 23fb229ba37..0fd4d025ced 100644 --- a/crates/hyperswitch_interfaces/src/conversion_impls.rs +++ b/crates/hyperswitch_interfaces/src/conversion_impls.rs @@ -10,7 +10,7 @@ use hyperswitch_domain_models::{ router_data_v2::{ flow_common_types::{ AccessTokenFlowData, DisputesFlowData, ExternalAuthenticationFlowData, FilesFlowData, - GetAdditionalRevenueRecoveryFlowCommonData, MandateRevokeFlowData, PaymentFlowData, + BillingConnectorPaymentsSyncFlowData, MandateRevokeFlowData, PaymentFlowData, RefundFlowData, RevenueRecoveryRecordBackData, UasFlowData, WebhookSourceVerifyData, }, RouterDataV2, @@ -800,7 +800,7 @@ impl RouterDataConversion for UasFlowD } impl RouterDataConversion - for GetAdditionalRevenueRecoveryFlowCommonData + for BillingConnectorPaymentsSyncFlowData { fn from_old_router_data( old_router_data: &RouterData, @@ -827,7 +827,7 @@ impl RouterDataConversion { let router_data = get_default_router_data( new_router_data.tenant_id.clone(), - "getadditionalrevenuerecoverydetails", + "BillingConnectorPaymentsSync", new_router_data.request, new_router_data.response, ); diff --git a/crates/hyperswitch_interfaces/src/types.rs b/crates/hyperswitch_interfaces/src/types.rs index e5c6e1a81d7..223500d2626 100644 --- a/crates/hyperswitch_interfaces/src/types.rs +++ b/crates/hyperswitch_interfaces/src/types.rs @@ -14,7 +14,7 @@ use hyperswitch_domain_models::{ Session, SetupMandate, Void, }, refunds::{Execute, RSync}, - revenue_recovery::{GetAdditionalRevenueRecoveryDetails, RecoveryRecordBack}, + revenue_recovery::{BillingConnectorPaymentsSync, RecoveryRecordBack}, unified_authentication_service::{ Authenticate, AuthenticationConfirmation, PostAuthenticate, PreAuthenticate, }, @@ -22,7 +22,7 @@ use hyperswitch_domain_models::{ }, router_request_types::{ revenue_recovery::{ - GetAdditionalRevenueRecoveryRequestData, RevenueRecoveryRecordBackRequest, + BillingConnectorPaymentsSyncRequest, RevenueRecoveryRecordBackRequest, }, unified_authentication_service::{ UasAuthenticationRequestData, UasAuthenticationResponseData, @@ -40,7 +40,7 @@ use hyperswitch_domain_models::{ }, router_response_types::{ revenue_recovery::{ - GetAdditionalRevenueRecoveryResponseData, RevenueRecoveryRecordBackResponse, + BillingConnectorPaymentsSyncResponse, RevenueRecoveryRecordBackResponse, }, AcceptDisputeResponse, DefendDisputeResponse, MandateRevokeResponseData, PaymentsResponseData, RefundsResponseData, RetrieveFileResponse, SubmitEvidenceResponse, @@ -237,9 +237,9 @@ pub type RevenueRecoveryRecordBackType = dyn ConnectorIntegration< RevenueRecoveryRecordBackResponse, >; -/// Type alias for `ConnectorIntegration` -pub type AdditionalRevenueRecoveryCallType = dyn ConnectorIntegration< - GetAdditionalRevenueRecoveryDetails, - GetAdditionalRevenueRecoveryRequestData, - GetAdditionalRevenueRecoveryResponseData, +/// Type alias for `ConnectorIntegration` +pub type BillingConnectorPaymentsSyncType = dyn ConnectorIntegration< + BillingConnectorPaymentsSync, + BillingConnectorPaymentsSyncRequest, + BillingConnectorPaymentsSyncResponse, >; diff --git a/crates/router/src/configs/secrets_transformers.rs b/crates/router/src/configs/secrets_transformers.rs index 8904322d1be..c59b8471344 100644 --- a/crates/router/src/configs/secrets_transformers.rs +++ b/crates/router/src/configs/secrets_transformers.rs @@ -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")] diff --git a/crates/router/src/configs/settings.rs b/crates/router/src/configs/settings.rs index 939af49b6ed..a4c454ec196 100644 --- a/crates/router/src/configs/settings.rs +++ b/crates/router/src/configs/settings.rs @@ -96,7 +96,7 @@ pub struct Settings { 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, 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, + pub billing_connectors_which_require_payment_sync: HashSet, } #[derive(Debug, Deserialize, Clone, Default)] diff --git a/crates/router/src/core/errors.rs b/crates/router/src/core/errors.rs index 0781da4fe9b..25b1aa79aea 100644 --- a/crates/router/src/core/errors.rs +++ b/crates/router/src/core/errors.rs @@ -499,5 +499,5 @@ pub enum RevenueRecoveryError { #[error("Failed to get the response from process tracker")] ProcessTrackerResponseError, #[error("Additional revenue recovery call failed")] - AdditionalRevenueRecoveryCallFailed, + BillingConnectorPaymentsSyncFailed, } diff --git a/crates/router/src/core/payments/flows.rs b/crates/router/src/core/payments/flows.rs index 6dcaf51139a..6a7d80ab192 100644 --- a/crates/router/src/core/payments/flows.rs +++ b/crates/router/src/core/payments/flows.rs @@ -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::{ - GetAdditionalRevenueRecoveryDetails, RecoveryRecordBack, + BillingConnectorPaymentsSync, RecoveryRecordBack, }; use hyperswitch_domain_models::{ mandates::CustomerAcceptance, @@ -2004,14 +2004,14 @@ default_imp_for_revenue_recovery! { } #[cfg(all(feature = "v2", feature = "revenue_recovery"))] -macro_rules! default_imp_for_additional_revenue_recovery_call { +macro_rules! default_imp_for_billing_connector_payment_sync { ($($path:ident::$connector:ident),*) => { - $( impl api::AdditionalRevenueRecovery for $path::$connector {} + $( impl api::BillingConnectorPaymentsSyncIntegration for $path::$connector {} impl services::ConnectorIntegration< - GetAdditionalRevenueRecoveryDetails, - types::GetAdditionalRevenueRecoveryRequestData, - types::GetAdditionalRevenueRecoveryResponseData, + BillingConnectorPaymentsSync, + types::BillingConnectorPaymentsSyncRequest, + types::BillingConnectorPaymentsSyncResponse, > for $path::$connector {} )* @@ -2019,20 +2019,20 @@ macro_rules! default_imp_for_additional_revenue_recovery_call { } #[cfg(all(feature = "v2", feature = "revenue_recovery"))] #[cfg(feature = "dummy_connector")] -impl api::AdditionalRevenueRecovery for connector::DummyConnector {} +impl api::BillingConnectorPaymentsSyncIntegration for connector::DummyConnector {} #[cfg(all(feature = "v2", feature = "revenue_recovery"))] #[cfg(feature = "dummy_connector")] impl services::ConnectorIntegration< - GetAdditionalRevenueRecoveryDetails, - types::GetAdditionalRevenueRecoveryRequestData, - types::GetAdditionalRevenueRecoveryResponseData, + BillingConnectorPaymentsSync, + types::BillingConnectorPaymentsSyncRequest, + types::BillingConnectorPaymentsSyncResponse, > for connector::DummyConnector { } #[cfg(all(feature = "v2", feature = "revenue_recovery"))] -default_imp_for_additional_revenue_recovery_call!( +default_imp_for_billing_connector_payment_sync!( connector::Adyenplatform, connector::Ebanx, connector::Gpayments, diff --git a/crates/router/src/core/webhooks/recovery_incoming.rs b/crates/router/src/core/webhooks/recovery_incoming.rs index fc2138b5901..71fdf3debcc 100644 --- a/crates/router/src/core/webhooks/recovery_incoming.rs +++ b/crates/router/src/core/webhooks/recovery_incoming.rs @@ -11,9 +11,9 @@ 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::AdditionalRevenueRecoveryDetailsRouterData, + types as router_types, }; -use hyperswitch_interfaces::{api::RevenueRecovery, webhooks as interface_webhooks}; +use hyperswitch_interfaces::webhooks as interface_webhooks; use router_env::{instrument, tracing}; use serde_with::rust::unwrap_or_skip; @@ -61,16 +61,16 @@ pub async fn recovery_incoming_webhook_flow( .change_context(errors::RevenueRecoveryError::InvoiceWebhookProcessingFailed) .attach_printable_lazy(|| format!("unable to parse connector name {connector_name:?}"))?; - let billing_connectors_which_require_payment_api_call = - &state.conf.additional_revenue_recovery_details_call; + let billing_connectors_with_payment_sync_call = + &state.conf.billing_connectors_payment_sync; let should_billing_connector_payment_api_called = - billing_connectors_which_require_payment_api_call - .connectors_with_additional_revenue_recovery_details_call + billing_connectors_with_payment_sync_call + .billing_connectors_which_require_payment_sync .contains(&connector); let billing_connector_payment_details = - AdditionalRevenueRecoveryResponse::get_billing_connector_payment_details( + BillingConnectorPaymentsSyncResponseData::get_billing_connector_payment_details( should_billing_connector_payment_api_called, &state, &merchant_account, @@ -184,7 +184,7 @@ impl RevenueRecoveryInvoice { connector_enum: &connector_integration_interface::ConnectorEnum, request_details: &hyperswitch_interfaces::webhooks::IncomingWebhookRequestDetails<'_>, billing_connector_payment_details: Option< - &revenue_recovery_response::GetAdditionalRevenueRecoveryResponseData, + &revenue_recovery_response::BillingConnectorPaymentsSyncResponse, >, ) -> CustomResult { billing_connector_payment_details.map_or_else( @@ -306,7 +306,7 @@ impl RevenueRecoveryAttempt { connector_enum: &connector_integration_interface::ConnectorEnum, request_details: &hyperswitch_interfaces::webhooks::IncomingWebhookRequestDetails<'_>, billing_connector_payment_details: Option< - &revenue_recovery_response::GetAdditionalRevenueRecoveryResponseData, + &revenue_recovery_response::BillingConnectorPaymentsSyncResponse, >, ) -> CustomResult { billing_connector_payment_details.map_or_else( @@ -513,7 +513,7 @@ impl RevenueRecoveryAttempt { connector_enum: &connector_integration_interface::ConnectorEnum, req_state: &ReqState, billing_connector_payment_details: Option< - &revenue_recovery_response::GetAdditionalRevenueRecoveryResponseData, + &revenue_recovery_response::BillingConnectorPaymentsSyncResponse, >, request_details: &hyperswitch_interfaces::webhooks::IncomingWebhookRequestDetails<'_>, merchant_account: &domain::MerchantAccount, @@ -651,13 +651,13 @@ impl RevenueRecoveryAttempt { } } -pub struct AdditionalRevenueRecoveryResponse( - revenue_recovery_response::GetAdditionalRevenueRecoveryResponseData, +pub struct BillingConnectorPaymentsSyncResponseData( + revenue_recovery_response::BillingConnectorPaymentsSyncResponse, ); -pub struct AdditionalRevenueRecoveryRouterData(AdditionalRevenueRecoveryDetailsRouterData); +pub struct BillingConnectorPaymentsSyncFlowRouterData(router_types::BillingConnectorPaymentsSyncRouterData); -impl AdditionalRevenueRecoveryResponse { - async fn handle_additional_recovery_details_call( +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, @@ -670,17 +670,17 @@ impl AdditionalRevenueRecoveryResponse { api::GetToken::Connector, None, ) - .change_context(errors::RevenueRecoveryError::AdditionalRevenueRecoveryCallFailed) + .change_context(errors::RevenueRecoveryError::BillingConnectorPaymentsSyncFailed) .attach_printable("invalid connector name received in payment attempt")?; - let connector_integration: services::BoxedGetAdditionalRecoveryRecoveryDetailsIntegrationInterface< - router_flow_types::GetAdditionalRevenueRecoveryDetails, - revenue_recovery_request::GetAdditionalRevenueRecoveryRequestData, - revenue_recovery_response::GetAdditionalRevenueRecoveryResponseData + 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 = - AdditionalRevenueRecoveryRouterData::construct_router_data_for_additional_call( + BillingConnectorPaymentsSyncFlowRouterData::construct_router_data_for_billing_connector_payment_sync_call( state, connector_name, merchant_connector_account, @@ -688,9 +688,9 @@ impl AdditionalRevenueRecoveryResponse { id, ) .await - .change_context(errors::RevenueRecoveryError::AdditionalRevenueRecoveryCallFailed) + .change_context(errors::RevenueRecoveryError::BillingConnectorPaymentsSyncFailed) .attach_printable( - "Failed while constructing additional recovery details call router data", + "Failed while constructing router data for billing connector psync call", )? .inner(); @@ -702,15 +702,15 @@ impl AdditionalRevenueRecoveryResponse { None, ) .await - .change_context(errors::RevenueRecoveryError::AdditionalRevenueRecoveryCallFailed) - .attach_printable("Failed while fetching additional revenue recovery details")?; + .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::AdditionalRevenueRecoveryCallFailed) - .attach_printable("Failed while fetching additional revenue recovery details") + Err(errors::RevenueRecoveryError::BillingConnectorPaymentsSyncFailed) + .attach_printable("Failed while fetching billing connector payment details") } }?; Ok(Self(additional_recovery_details)) @@ -724,7 +724,7 @@ impl AdditionalRevenueRecoveryResponse { connector_name: &str, object_ref_id: &webhooks::ObjectReferenceId, ) -> CustomResult< - Option, + Option, errors::RevenueRecoveryError, > { let response_data = match should_billing_connector_payment_api_called { @@ -733,11 +733,11 @@ impl AdditionalRevenueRecoveryResponse { .clone() .get_connector_transaction_id_as_string() .change_context( - errors::RevenueRecoveryError::AdditionalRevenueRecoveryCallFailed, + errors::RevenueRecoveryError::BillingConnectorPaymentsSyncFailed, ) .attach_printable("Billing connector Payments api call failed")?; let billing_connector_payment_details = - Self::handle_additional_recovery_details_call( + Self::handle_billing_connector_payment_sync_call( state, merchant_account, billing_connector_account, @@ -753,48 +753,48 @@ impl AdditionalRevenueRecoveryResponse { Ok(response_data) } - fn inner(self) -> revenue_recovery_response::GetAdditionalRevenueRecoveryResponseData { + fn inner(self) -> revenue_recovery_response::BillingConnectorPaymentsSyncResponse { self.0 } } -impl AdditionalRevenueRecoveryRouterData { - async fn construct_router_data_for_additional_call( +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, - additional_revenue_recovery_id: &str, + billing_connector_psync_id: &str, ) -> CustomResult { 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::AdditionalRevenueRecoveryCallFailed)?; + .change_context(errors::RevenueRecoveryError::BillingConnectorPaymentsSyncFailed)?; let router_data = types::RouterDataV2 { - flow: PhantomData::, + flow: PhantomData::, tenant_id: state.tenant.tenant_id.clone(), - resource_common_data: flow_common_types::GetAdditionalRevenueRecoveryFlowCommonData, + resource_common_data: flow_common_types::BillingConnectorPaymentsSyncFlowData, connector_auth_type: auth_type, - request: revenue_recovery_request::GetAdditionalRevenueRecoveryRequestData { - additional_revenue_recovery_id: additional_revenue_recovery_id.to_string(), + 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::GetAdditionalRevenueRecoveryFlowCommonData::to_old_router_data( + flow_common_types::BillingConnectorPaymentsSyncFlowData::to_old_router_data( router_data, ) - .change_context(errors::RevenueRecoveryError::AdditionalRevenueRecoveryCallFailed) - .attach_printable("Cannot construct router data for making the additional call")?; + .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) -> AdditionalRevenueRecoveryDetailsRouterData { + fn inner(self) -> router_types::BillingConnectorPaymentsSyncRouterData { self.0 } } diff --git a/crates/router/src/services/api.rs b/crates/router/src/services/api.rs index e8af5b3b773..a69070826f2 100644 --- a/crates/router/src/services/api.rs +++ b/crates/router/src/services/api.rs @@ -110,10 +110,10 @@ pub type BoxedRevenueRecoveryRecordBackInterface = pub type BoxedUnifiedAuthenticationServiceInterface = BoxedConnectorIntegrationInterface; -pub type BoxedGetAdditionalRecoveryRecoveryDetailsIntegrationInterface = +pub type BoxedBillingConnectorPaymentsSyncIntegrationInterface = BoxedConnectorIntegrationInterface< T, - common_types::GetAdditionalRevenueRecoveryFlowCommonData, + common_types::BillingConnectorPaymentsSyncFlowData, Req, Res, >; diff --git a/crates/router/src/types.rs b/crates/router/src/types.rs index ff9eef080a6..42bf4241241 100644 --- a/crates/router/src/types.rs +++ b/crates/router/src/types.rs @@ -58,7 +58,7 @@ pub use hyperswitch_domain_models::{ }, router_request_types::{ revenue_recovery::{ - GetAdditionalRevenueRecoveryRequestData, RevenueRecoveryRecordBackRequest, + BillingConnectorPaymentsSyncRequest, RevenueRecoveryRecordBackRequest, }, unified_authentication_service::{ UasAuthenticationRequestData, UasAuthenticationResponseData, @@ -80,7 +80,7 @@ pub use hyperswitch_domain_models::{ }, router_response_types::{ revenue_recovery::{ - GetAdditionalRevenueRecoveryResponseData, RevenueRecoveryRecordBackResponse, + BillingConnectorPaymentsSyncResponse, RevenueRecoveryRecordBackResponse, }, AcceptDisputeResponse, CaptureSyncResponse, DefendDisputeResponse, MandateReference, MandateRevokeResponseData, PaymentsResponseData, PreprocessingResponseId, diff --git a/crates/router/src/types/api.rs b/crates/router/src/types/api.rs index 76b3702beb4..3629d1f364e 100644 --- a/crates/router/src/types/api.rs +++ b/crates/router/src/types/api.rs @@ -56,7 +56,7 @@ 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, From 7006f1dc8f27473f27ce4f6c4efe71bc9e3b29d6 Mon Sep 17 00:00:00 2001 From: "hyperswitch-bot[bot]" <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Date: Thu, 27 Mar 2025 09:30:28 +0000 Subject: [PATCH 80/83] chore: run formatter --- .../src/connectors/stripebilling.rs | 34 ++++++++----- .../connectors/stripebilling/transformers.rs | 49 ++++++++++--------- .../src/default_implementations.rs | 6 +-- .../src/default_implementations_v2.rs | 9 ++-- crates/hyperswitch_domain_models/src/types.rs | 10 ++-- .../src/api/revenue_recovery_v2.rs | 5 +- .../src/conversion_impls.rs | 4 +- crates/hyperswitch_interfaces/src/types.rs | 4 +- .../src/core/webhooks/recovery_incoming.rs | 27 +++++----- crates/router/src/types.rs | 4 +- crates/router/src/types/api.rs | 4 +- 11 files changed, 83 insertions(+), 73 deletions(-) diff --git a/crates/hyperswitch_connectors/src/connectors/stripebilling.rs b/crates/hyperswitch_connectors/src/connectors/stripebilling.rs index b159ed22d61..721e22485bf 100644 --- a/crates/hyperswitch_connectors/src/connectors/stripebilling.rs +++ b/crates/hyperswitch_connectors/src/connectors/stripebilling.rs @@ -627,7 +627,10 @@ impl data: &recovery_router_data_types::BillingConnectorPaymentsSyncRouterData, event_builder: Option<&mut ConnectorEvent>, res: Response, - ) -> CustomResult { + ) -> CustomResult< + recovery_router_data_types::BillingConnectorPaymentsSyncRouterData, + errors::ConnectorError, + > { let response: stripebilling::StripebillingRecoveryDetailsData = res .response .parse_struct::( @@ -638,11 +641,13 @@ impl event_builder.map(|i| i.set_response_body(&response)); router_env::logger::info!(connector_response=?response); - recovery_router_data_types::BillingConnectorPaymentsSyncRouterData::try_from(ResponseRouterData { - response, - data: data.clone(), - http_code: res.status_code, - }) + recovery_router_data_types::BillingConnectorPaymentsSyncRouterData::try_from( + ResponseRouterData { + response, + data: data.clone(), + http_code: res.status_code, + }, + ) } fn get_error_response( @@ -721,7 +726,10 @@ impl data: &recovery_router_data_types::RevenueRecoveryRecordBackRouterData, event_builder: Option<&mut ConnectorEvent>, res: Response, - ) -> CustomResult { + ) -> CustomResult< + recovery_router_data_types::RevenueRecoveryRecordBackRouterData, + errors::ConnectorError, + > { let response = res .response .parse_struct::( @@ -730,11 +738,13 @@ impl .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; event_builder.map(|i| i.set_response_body(&response)); router_env::logger::info!(connector_response=?response); - recovery_router_data_types::RevenueRecoveryRecordBackRouterData::try_from(ResponseRouterData { - response, - data: data.clone(), - http_code: res.status_code, - }) + recovery_router_data_types::RevenueRecoveryRecordBackRouterData::try_from( + ResponseRouterData { + response, + data: data.clone(), + http_code: res.status_code, + }, + ) } fn get_error_response( diff --git a/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs b/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs index fce4dc7c806..7fdbace5184 100644 --- a/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/stripebilling/transformers.rs @@ -436,29 +436,32 @@ impl )); Ok(Self { - response: Ok(recovery_response_types::BillingConnectorPaymentsSyncResponse { - status: item.response.status.into(), - amount: item.response.amount, - currency: item.response.currency, - merchant_reference_id, - connector_account_reference_id: - MCA_ID_IDENTIFIER_FOR_STRIPE_IN_STRIPEBILLING_MCA_FEAATURE_METADATA.to_string(), - connector_transaction_id, - error_code: item.response.failure_code, - error_message: item.response.failure_message, - processor_payment_method_token: item.response.payment_method, - connector_customer_id: item.response.customer, - transaction_created_at: Some(item.response.created), - payment_method_sub_type: common_enums::PaymentMethodType::from( - item.response - .payment_method_details - .card_funding_type - .funding, - ), - payment_method_type: common_enums::PaymentMethod::from( - item.response.payment_method_details.type_of_payment_method, - ), - }), + response: Ok( + recovery_response_types::BillingConnectorPaymentsSyncResponse { + status: item.response.status.into(), + amount: item.response.amount, + currency: item.response.currency, + merchant_reference_id, + connector_account_reference_id: + MCA_ID_IDENTIFIER_FOR_STRIPE_IN_STRIPEBILLING_MCA_FEAATURE_METADATA + .to_string(), + connector_transaction_id, + error_code: item.response.failure_code, + error_message: item.response.failure_message, + processor_payment_method_token: item.response.payment_method, + connector_customer_id: item.response.customer, + transaction_created_at: Some(item.response.created), + payment_method_sub_type: common_enums::PaymentMethodType::from( + item.response + .payment_method_details + .card_funding_type + .funding, + ), + payment_method_type: common_enums::PaymentMethod::from( + item.response.payment_method_details.type_of_payment_method, + ), + }, + ), ..item.data }) } diff --git a/crates/hyperswitch_connectors/src/default_implementations.rs b/crates/hyperswitch_connectors/src/default_implementations.rs index 2ca3f112130..a68f0720765 100644 --- a/crates/hyperswitch_connectors/src/default_implementations.rs +++ b/crates/hyperswitch_connectors/src/default_implementations.rs @@ -24,9 +24,7 @@ use hyperswitch_domain_models::{ }; #[cfg(all(feature = "v2", feature = "revenue_recovery"))] use hyperswitch_domain_models::{ - router_flow_types::revenue_recovery::{ - BillingConnectorPaymentsSync, RecoveryRecordBack, - }, + router_flow_types::revenue_recovery::{BillingConnectorPaymentsSync, RecoveryRecordBack}, router_request_types::revenue_recovery::{ BillingConnectorPaymentsSyncRequest, RevenueRecoveryRecordBackRequest, }, @@ -100,10 +98,10 @@ use hyperswitch_interfaces::{ PaymentSessionUpdate, PaymentsCompleteAuthorize, PaymentsPostProcessing, PaymentsPreProcessing, TaxCalculation, }, + revenue_recovery::RevenueRecovery, ConnectorIntegration, ConnectorMandateRevoke, ConnectorRedirectResponse, ConnectorTransactionId, UasAuthentication, UasAuthenticationConfirmation, UasPostAuthentication, UasPreAuthentication, UnifiedAuthenticationService, - revenue_recovery::RevenueRecovery }, errors::ConnectorError, }; diff --git a/crates/hyperswitch_connectors/src/default_implementations_v2.rs b/crates/hyperswitch_connectors/src/default_implementations_v2.rs index 45a87433bfa..c27008b7a5b 100644 --- a/crates/hyperswitch_connectors/src/default_implementations_v2.rs +++ b/crates/hyperswitch_connectors/src/default_implementations_v2.rs @@ -2,7 +2,7 @@ use hyperswitch_domain_models::{ router_data::AccessToken, router_data_v2::{ flow_common_types::{ - DisputesFlowData, BillingConnectorPaymentsSyncFlowData, MandateRevokeFlowData, + BillingConnectorPaymentsSyncFlowData, DisputesFlowData, MandateRevokeFlowData, PaymentFlowData, RefundFlowData, RevenueRecoveryRecordBackData, WebhookSourceVerifyData, }, @@ -28,9 +28,7 @@ use hyperswitch_domain_models::{ }, router_request_types::{ authentication, - revenue_recovery::{ - BillingConnectorPaymentsSyncRequest, RevenueRecoveryRecordBackRequest, - }, + revenue_recovery::{BillingConnectorPaymentsSyncRequest, RevenueRecoveryRecordBackRequest}, AcceptDisputeRequestData, AccessTokenRequestData, AuthorizeSessionTokenData, CompleteAuthorizeData, ConnectorCustomerData, DefendDisputeRequestData, MandateRevokeRequestData, PaymentMethodTokenizationData, PaymentsApproveData, @@ -98,7 +96,8 @@ use hyperswitch_interfaces::{ }, refunds_v2::{RefundExecuteV2, RefundSyncV2, RefundV2}, revenue_recovery_v2::{ - BillingConnectorPaymentsSyncIntegrationV2, RevenueRecoveryRecordBackV2, RevenueRecoveryV2, + BillingConnectorPaymentsSyncIntegrationV2, RevenueRecoveryRecordBackV2, + RevenueRecoveryV2, }, ConnectorAccessTokenV2, ConnectorMandateRevokeV2, ConnectorVerifyWebhookSourceV2, }, diff --git a/crates/hyperswitch_domain_models/src/types.rs b/crates/hyperswitch_domain_models/src/types.rs index c7b0a34adbf..691fde0de93 100644 --- a/crates/hyperswitch_domain_models/src/types.rs +++ b/crates/hyperswitch_domain_models/src/types.rs @@ -4,16 +4,14 @@ use crate::{ router_data::{AccessToken, RouterData}, router_flow_types::{ mandate_revoke::MandateRevoke, revenue_recovery::RecoveryRecordBack, AccessTokenAuth, - Authenticate, AuthenticationConfirmation, Authorize, AuthorizeSessionToken, CalculateTax, - Capture, CompleteAuthorize, CreateConnectorCustomer, Execute, - BillingConnectorPaymentsSync, IncrementalAuthorization, PSync, PaymentMethodToken, + Authenticate, AuthenticationConfirmation, Authorize, AuthorizeSessionToken, + BillingConnectorPaymentsSync, CalculateTax, Capture, CompleteAuthorize, + CreateConnectorCustomer, Execute, IncrementalAuthorization, PSync, PaymentMethodToken, PostAuthenticate, PostSessionTokens, PreAuthenticate, PreProcessing, RSync, SdkSessionUpdate, Session, SetupMandate, VerifyWebhookSource, Void, }, router_request_types::{ - revenue_recovery::{ - BillingConnectorPaymentsSyncRequest, RevenueRecoveryRecordBackRequest, - }, + revenue_recovery::{BillingConnectorPaymentsSyncRequest, RevenueRecoveryRecordBackRequest}, unified_authentication_service::{ UasAuthenticationRequestData, UasAuthenticationResponseData, UasConfirmationRequestData, UasPostAuthenticationRequestData, diff --git a/crates/hyperswitch_interfaces/src/api/revenue_recovery_v2.rs b/crates/hyperswitch_interfaces/src/api/revenue_recovery_v2.rs index 08b62d19937..1fca496ea72 100644 --- a/crates/hyperswitch_interfaces/src/api/revenue_recovery_v2.rs +++ b/crates/hyperswitch_interfaces/src/api/revenue_recovery_v2.rs @@ -16,7 +16,10 @@ use hyperswitch_domain_models::{ use crate::connector_integration_v2::ConnectorIntegrationV2; /// trait RevenueRecoveryV2 -pub trait RevenueRecoveryV2: BillingConnectorPaymentsSyncIntegrationV2 + RevenueRecoveryRecordBackV2 {} +pub trait RevenueRecoveryV2: + BillingConnectorPaymentsSyncIntegrationV2 + RevenueRecoveryRecordBackV2 +{ +} /// trait BillingConnectorPaymentsSyncIntegrationV2 pub trait BillingConnectorPaymentsSyncIntegrationV2: diff --git a/crates/hyperswitch_interfaces/src/conversion_impls.rs b/crates/hyperswitch_interfaces/src/conversion_impls.rs index 0fd4d025ced..2163d6f468c 100644 --- a/crates/hyperswitch_interfaces/src/conversion_impls.rs +++ b/crates/hyperswitch_interfaces/src/conversion_impls.rs @@ -9,8 +9,8 @@ use hyperswitch_domain_models::{ router_data::{self, RouterData}, router_data_v2::{ flow_common_types::{ - AccessTokenFlowData, DisputesFlowData, ExternalAuthenticationFlowData, FilesFlowData, - BillingConnectorPaymentsSyncFlowData, MandateRevokeFlowData, PaymentFlowData, + AccessTokenFlowData, BillingConnectorPaymentsSyncFlowData, DisputesFlowData, + ExternalAuthenticationFlowData, FilesFlowData, MandateRevokeFlowData, PaymentFlowData, RefundFlowData, RevenueRecoveryRecordBackData, UasFlowData, WebhookSourceVerifyData, }, RouterDataV2, diff --git a/crates/hyperswitch_interfaces/src/types.rs b/crates/hyperswitch_interfaces/src/types.rs index 223500d2626..8e33d5bc15e 100644 --- a/crates/hyperswitch_interfaces/src/types.rs +++ b/crates/hyperswitch_interfaces/src/types.rs @@ -21,9 +21,7 @@ use hyperswitch_domain_models::{ webhooks::VerifyWebhookSource, }, router_request_types::{ - revenue_recovery::{ - BillingConnectorPaymentsSyncRequest, RevenueRecoveryRecordBackRequest, - }, + revenue_recovery::{BillingConnectorPaymentsSyncRequest, RevenueRecoveryRecordBackRequest}, unified_authentication_service::{ UasAuthenticationRequestData, UasAuthenticationResponseData, UasConfirmationRequestData, UasPostAuthenticationRequestData, diff --git a/crates/router/src/core/webhooks/recovery_incoming.rs b/crates/router/src/core/webhooks/recovery_incoming.rs index 71fdf3debcc..3ed82b5f4f5 100644 --- a/crates/router/src/core/webhooks/recovery_incoming.rs +++ b/crates/router/src/core/webhooks/recovery_incoming.rs @@ -10,8 +10,7 @@ use error_stack::{report, ResultExt}; 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, + 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}; @@ -61,13 +60,11 @@ pub async fn recovery_incoming_webhook_flow( .change_context(errors::RevenueRecoveryError::InvoiceWebhookProcessingFailed) .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 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 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( @@ -654,7 +651,9 @@ impl RevenueRecoveryAttempt { pub struct BillingConnectorPaymentsSyncResponseData( revenue_recovery_response::BillingConnectorPaymentsSyncResponse, ); -pub struct BillingConnectorPaymentsSyncFlowRouterData(router_types::BillingConnectorPaymentsSyncRouterData); +pub struct BillingConnectorPaymentsSyncFlowRouterData( + router_types::BillingConnectorPaymentsSyncRouterData, +); impl BillingConnectorPaymentsSyncResponseData { async fn handle_billing_connector_payment_sync_call( @@ -674,9 +673,9 @@ impl BillingConnectorPaymentsSyncResponseData { .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 + router_flow_types::BillingConnectorPaymentsSync, + revenue_recovery_request::BillingConnectorPaymentsSyncRequest, + revenue_recovery_response::BillingConnectorPaymentsSyncResponse, > = connector_data.connector.get_connector_integration(); let router_data = @@ -789,7 +788,9 @@ impl BillingConnectorPaymentsSyncFlowRouterData { router_data, ) .change_context(errors::RevenueRecoveryError::BillingConnectorPaymentsSyncFailed) - .attach_printable("Cannot construct router data for making the billing connector payments api call")?; + .attach_printable( + "Cannot construct router data for making the billing connector payments api call", + )?; Ok(Self(old_router_data)) } diff --git a/crates/router/src/types.rs b/crates/router/src/types.rs index 42bf4241241..b71d8042297 100644 --- a/crates/router/src/types.rs +++ b/crates/router/src/types.rs @@ -57,9 +57,7 @@ pub use hyperswitch_domain_models::{ WebhookSourceVerifyData, }, router_request_types::{ - revenue_recovery::{ - BillingConnectorPaymentsSyncRequest, RevenueRecoveryRecordBackRequest, - }, + revenue_recovery::{BillingConnectorPaymentsSyncRequest, RevenueRecoveryRecordBackRequest}, unified_authentication_service::{ UasAuthenticationRequestData, UasAuthenticationResponseData, UasConfirmationRequestData, UasPostAuthenticationRequestData, diff --git a/crates/router/src/types/api.rs b/crates/router/src/types/api.rs index 3629d1f364e..0275066bf4a 100644 --- a/crates/router/src/types/api.rs +++ b/crates/router/src/types/api.rs @@ -56,7 +56,9 @@ pub use hyperswitch_interfaces::{ ConnectorPreAuthenticationVersionCallV2, ExternalAuthenticationV2, }, fraud_check::FraudCheck, - revenue_recovery::{ BillingConnectorPaymentsSyncIntegration, RevenueRecovery, RevenueRecoveryRecordBack}, + revenue_recovery::{ + BillingConnectorPaymentsSyncIntegration, RevenueRecovery, RevenueRecoveryRecordBack, + }, revenue_recovery_v2::RevenueRecoveryV2, BoxedConnector, Connector, ConnectorAccessToken, ConnectorAccessTokenV2, ConnectorCommon, ConnectorCommonExt, ConnectorMandateRevoke, ConnectorMandateRevokeV2, From 8364cb161d397ebf1cd9b86acd016f451f15d2d3 Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Thu, 27 Mar 2025 15:08:16 +0530 Subject: [PATCH 81/83] comment change --- config/config.example.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/config.example.toml b/config/config.example.toml index f812012ab2c..b84640fd13e 100644 --- a/config/config.example.toml +++ b/config/config.example.toml @@ -950,4 +950,4 @@ primary_color = "#006DF9" # Primary color of email body background_color = "#FFFFFF" # Background color of email body [billing_connectors_payment_sync] -billing_connectors_which_require_payment_sync = "stripebilling" # List of connectors which has additional revenue recovery details api-call +billing_connectors_which_require_payment_sync = "stripebilling" # List of billing connectors which has payment sync api call From dfe7a20dc29c92f768a613a8c7d279c2844490b6 Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Thu, 27 Mar 2025 22:25:32 +0530 Subject: [PATCH 82/83] resolve merge conflicts --- crates/router/src/core/webhooks/recovery_incoming.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/crates/router/src/core/webhooks/recovery_incoming.rs b/crates/router/src/core/webhooks/recovery_incoming.rs index f171ce2655e..1bd8e83fa1e 100644 --- a/crates/router/src/core/webhooks/recovery_incoming.rs +++ b/crates/router/src/core/webhooks/recovery_incoming.rs @@ -23,8 +23,11 @@ use crate::{ }, db::{errors::RevenueRecoveryError, StorageInterface}, routes::{app::ReqState, metrics, SessionState}, - services::{self, connector_integration_interface::{self, RouterDataConversion},}, - 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, }; From bd578f29b5bcd6413ac3281f92725a84118f2321 Mon Sep 17 00:00:00 2001 From: Nishanth Challa Date: Thu, 27 Mar 2025 22:30:22 +0530 Subject: [PATCH 83/83] spell check resolve --- crates/router/src/core/errors.rs | 2 +- crates/router/src/core/revenue_recovery.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/router/src/core/errors.rs b/crates/router/src/core/errors.rs index 25b1aa79aea..532a662dda1 100644 --- a/crates/router/src/core/errors.rs +++ b/crates/router/src/core/errors.rs @@ -498,6 +498,6 @@ pub enum RevenueRecoveryError { ProcessTrackerCreationError, #[error("Failed to get the response from process tracker")] ProcessTrackerResponseError, - #[error("Additional revenue recovery call failed")] + #[error("Billing connector psync call failed")] BillingConnectorPaymentsSyncFailed, } diff --git a/crates/router/src/core/revenue_recovery.rs b/crates/router/src/core/revenue_recovery.rs index b5d5e7a6cd6..039dceb5f8f 100644 --- a/crates/router/src/core/revenue_recovery.rs +++ b/crates/router/src/core/revenue_recovery.rs @@ -263,7 +263,7 @@ pub async fn retrieve_revenue_recovery_process_tracker( .find_process_by_id(&process_tracker_id_for_psync) .await .map_err(|e| { - logger::error!("Error while retreiving psync task : {:?}", e); + logger::error!("Error while retrieving psync task : {:?}", e); }) .ok() .flatten();