diff --git a/api-reference/v1/openapi_spec_v1.json b/api-reference/v1/openapi_spec_v1.json index 038c3326d7..8b74a0621e 100644 --- a/api-reference/v1/openapi_spec_v1.json +++ b/api-reference/v1/openapi_spec_v1.json @@ -11222,6 +11222,7 @@ "bluesnap", "boku", "braintree", + "breadpay", "cashtocode", "celero", "chargebee", @@ -19179,6 +19180,17 @@ "type": "object" } } + }, + { + "type": "object", + "required": [ + "breadpay_redirect" + ], + "properties": { + "breadpay_redirect": { + "type": "object" + } + } } ] }, @@ -20962,6 +20974,7 @@ "boleto", "bca_bank_transfer", "bni_va", + "breadpay", "bri_va", "card_redirect", "cimb_va", @@ -28349,6 +28362,7 @@ "bluesnap", "boku", "braintree", + "breadpay", "cashtocode", "celero", "chargebee", diff --git a/api-reference/v2/openapi_spec_v2.json b/api-reference/v2/openapi_spec_v2.json index 8dc81cdc9a..ca5b4e8b5b 100644 --- a/api-reference/v2/openapi_spec_v2.json +++ b/api-reference/v2/openapi_spec_v2.json @@ -8237,6 +8237,7 @@ "bluesnap", "boku", "braintree", + "breadpay", "cashtocode", "celero", "chargebee", @@ -15488,6 +15489,17 @@ "type": "object" } } + }, + { + "type": "object", + "required": [ + "breadpay_redirect" + ], + "properties": { + "breadpay_redirect": { + "type": "object" + } + } } ] }, @@ -17811,6 +17823,7 @@ "boleto", "bca_bank_transfer", "bni_va", + "breadpay", "bri_va", "card_redirect", "cimb_va", @@ -22863,6 +22876,7 @@ "bluesnap", "boku", "braintree", + "breadpay", "cashtocode", "celero", "chargebee", diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs index 6cddf9430b..12256b5b8c 100644 --- a/crates/api_models/src/payments.rs +++ b/crates/api_models/src/payments.rs @@ -2184,6 +2184,7 @@ pub enum PayLaterData { /// For Alma Redirection as PayLater Option AlmaRedirect {}, AtomeRedirect {}, + BreadpayRedirect {}, } impl GetAddressFromPaymentMethodData for PayLaterData { @@ -2224,7 +2225,8 @@ impl GetAddressFromPaymentMethodData for PayLaterData { | Self::AlmaRedirect {} | Self::KlarnaSdk { .. } | Self::AffirmRedirect {} - | Self::AtomeRedirect {} => None, + | Self::AtomeRedirect {} + | Self::BreadpayRedirect {} => None, } } } @@ -2694,6 +2696,7 @@ impl GetPaymentMethodType for PayLaterData { Self::WalleyRedirect {} => api_enums::PaymentMethodType::Walley, Self::AlmaRedirect {} => api_enums::PaymentMethodType::Alma, Self::AtomeRedirect {} => api_enums::PaymentMethodType::Atome, + Self::BreadpayRedirect {} => api_enums::PaymentMethodType::Breadpay, } } } diff --git a/crates/common_enums/src/connector_enums.rs b/crates/common_enums/src/connector_enums.rs index cb5195925c..1f216dc5ee 100644 --- a/crates/common_enums/src/connector_enums.rs +++ b/crates/common_enums/src/connector_enums.rs @@ -74,6 +74,7 @@ pub enum RoutableConnectors { Bluesnap, Boku, Braintree, + Breadpay, Cashtocode, Celero, Chargebee, @@ -235,6 +236,7 @@ pub enum Connector { Bluesnap, Boku, Braintree, + Breadpay, Cashtocode, Celero, Chargebee, @@ -423,6 +425,7 @@ impl Connector { | Self::Bluesnap | Self::Boku | Self::Braintree + | Self::Breadpay | Self::Cashtocode | Self::Celero | Self::Chargebee @@ -589,6 +592,7 @@ impl From for Connector { RoutableConnectors::Bluesnap => Self::Bluesnap, RoutableConnectors::Boku => Self::Boku, RoutableConnectors::Braintree => Self::Braintree, + RoutableConnectors::Breadpay => Self::Breadpay, RoutableConnectors::Cashtocode => Self::Cashtocode, RoutableConnectors::Celero => Self::Celero, RoutableConnectors::Chargebee => Self::Chargebee, @@ -713,6 +717,7 @@ impl TryFrom for RoutableConnectors { Connector::Bluesnap => Ok(Self::Bluesnap), Connector::Boku => Ok(Self::Boku), Connector::Braintree => Ok(Self::Braintree), + Connector::Breadpay => Ok(Self::Breadpay), Connector::Cashtocode => Ok(Self::Cashtocode), Connector::Celero => Ok(Self::Celero), Connector::Chargebee => Ok(Self::Chargebee), diff --git a/crates/common_enums/src/enums.rs b/crates/common_enums/src/enums.rs index 9ff5fc24ab..c589d4aee0 100644 --- a/crates/common_enums/src/enums.rs +++ b/crates/common_enums/src/enums.rs @@ -1892,6 +1892,7 @@ pub enum PaymentMethodType { Boleto, BcaBankTransfer, BniVa, + Breadpay, BriVa, #[cfg(feature = "v2")] Card, @@ -2012,6 +2013,7 @@ impl PaymentMethodType { Self::Boleto => "Boleto Bancário", Self::BcaBankTransfer => "BCA Bank Transfer", Self::BniVa => "BNI Virtual Account", + Self::Breadpay => "Breadpay", Self::BriVa => "BRI Virtual Account", Self::CardRedirect => "Card Redirect", Self::CimbVa => "CIMB Virtual Account", diff --git a/crates/common_enums/src/transformers.rs b/crates/common_enums/src/transformers.rs index 992ab9e159..0dcef36ac9 100644 --- a/crates/common_enums/src/transformers.rs +++ b/crates/common_enums/src/transformers.rs @@ -1810,6 +1810,7 @@ impl From for PaymentMethod { PaymentMethodType::BcaBankTransfer => Self::BankTransfer, PaymentMethodType::Becs => Self::BankDebit, PaymentMethodType::BniVa => Self::BankTransfer, + PaymentMethodType::Breadpay => Self::PayLater, PaymentMethodType::BriVa => Self::BankTransfer, PaymentMethodType::Benefit => Self::CardRedirect, PaymentMethodType::Bizum => Self::BankRedirect, diff --git a/crates/connector_configs/src/connector.rs b/crates/connector_configs/src/connector.rs index b6f992db1b..d369836b22 100644 --- a/crates/connector_configs/src/connector.rs +++ b/crates/connector_configs/src/connector.rs @@ -388,6 +388,7 @@ impl ConnectorConfig { Connector::Bluesnap => Ok(connector_data.bluesnap), Connector::Boku => Ok(connector_data.boku), Connector::Braintree => Ok(connector_data.braintree), + Connector::Breadpay => Ok(connector_data.breadpay), Connector::Cashtocode => Ok(connector_data.cashtocode), Connector::Celero => Ok(connector_data.celero), Connector::Chargebee => Ok(connector_data.chargebee), diff --git a/crates/connector_configs/toml/development.toml b/crates/connector_configs/toml/development.toml index d8510f03b1..bb27fb4369 100644 --- a/crates/connector_configs/toml/development.toml +++ b/crates/connector_configs/toml/development.toml @@ -6372,6 +6372,6 @@ api_key = "API Key" api_key = "API Key" [breadpay] -[breadpay.connector_auth.HeaderKey] +[breadpay.connector_auth.BodyKey] api_key = "API Key" - +key1 = "API Secret" diff --git a/crates/connector_configs/toml/production.toml b/crates/connector_configs/toml/production.toml index 6f487b523e..c11d6accdd 100644 --- a/crates/connector_configs/toml/production.toml +++ b/crates/connector_configs/toml/production.toml @@ -4983,6 +4983,6 @@ api_key = "API Key" api_key = "API Key" [breadpay] -[breadpay.connector_auth.HeaderKey] +[breadpay.connector_auth.BodyKey] api_key = "API Key" - +key1 = "API Secret" diff --git a/crates/connector_configs/toml/sandbox.toml b/crates/connector_configs/toml/sandbox.toml index 93f12a8072..20cd88623c 100644 --- a/crates/connector_configs/toml/sandbox.toml +++ b/crates/connector_configs/toml/sandbox.toml @@ -6351,6 +6351,6 @@ api_key = "API Key" api_key = "API Key" [breadpay] -[breadpay.connector_auth.HeaderKey] +[breadpay.connector_auth.BodyKey] api_key = "API Key" - +key1 = "API Secret" diff --git a/crates/euclid/src/frontend/dir/enums.rs b/crates/euclid/src/frontend/dir/enums.rs index ee13b1d456..677a3068ee 100644 --- a/crates/euclid/src/frontend/dir/enums.rs +++ b/crates/euclid/src/frontend/dir/enums.rs @@ -56,6 +56,7 @@ pub enum PayLaterType { PayBright, Walley, Atome, + Breadpay, } #[derive( diff --git a/crates/euclid/src/frontend/dir/lowering.rs b/crates/euclid/src/frontend/dir/lowering.rs index f496226b0a..d0e8477336 100644 --- a/crates/euclid/src/frontend/dir/lowering.rs +++ b/crates/euclid/src/frontend/dir/lowering.rs @@ -32,6 +32,7 @@ impl From for global_enums::PaymentMethodType { enums::PayLaterType::PayBright => Self::PayBright, enums::PayLaterType::Walley => Self::Walley, enums::PayLaterType::Atome => Self::Atome, + enums::PayLaterType::Breadpay => Self::Breadpay, } } } diff --git a/crates/euclid/src/frontend/dir/transformers.rs b/crates/euclid/src/frontend/dir/transformers.rs index a70ddc75cc..757616b797 100644 --- a/crates/euclid/src/frontend/dir/transformers.rs +++ b/crates/euclid/src/frontend/dir/transformers.rs @@ -103,6 +103,7 @@ impl IntoDirValue for (global_enums::PaymentMethodType, global_enums::PaymentMet global_enums::PaymentMethodType::PayBright => Ok(dirval!(PayLaterType = PayBright)), global_enums::PaymentMethodType::Walley => Ok(dirval!(PayLaterType = Walley)), + global_enums::PaymentMethodType::Breadpay => Ok(dirval!(PayLaterType = Breadpay)), global_enums::PaymentMethodType::Przelewy24 => { Ok(dirval!(BankRedirectType = Przelewy24)) } diff --git a/crates/hyperswitch_connectors/src/connectors/adyen.rs b/crates/hyperswitch_connectors/src/connectors/adyen.rs index d71b252f59..18ab4b876b 100644 --- a/crates/hyperswitch_connectors/src/connectors/adyen.rs +++ b/crates/hyperswitch_connectors/src/connectors/adyen.rs @@ -304,6 +304,7 @@ impl ConnectorValidation for Adyen { } }, PaymentMethodType::AmazonPay + | PaymentMethodType::Breadpay | PaymentMethodType::Paysera | PaymentMethodType::Skrill | PaymentMethodType::CardRedirect diff --git a/crates/hyperswitch_connectors/src/connectors/adyen/transformers.rs b/crates/hyperswitch_connectors/src/connectors/adyen/transformers.rs index 5299d43562..f8c8ed4d5a 100644 --- a/crates/hyperswitch_connectors/src/connectors/adyen/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/adyen/transformers.rs @@ -2428,10 +2428,12 @@ impl check_required_field(billing_address, "billing")?; Ok(AdyenPaymentMethod::Atome) } - PayLaterData::KlarnaSdk { .. } => Err(errors::ConnectorError::NotImplemented( - utils::get_unimplemented_payment_method_error_message("Adyen"), - ) - .into()), + PayLaterData::KlarnaSdk { .. } | PayLaterData::BreadpayRedirect {} => { + Err(errors::ConnectorError::NotImplemented( + utils::get_unimplemented_payment_method_error_message("Adyen"), + ) + .into()) + } } } } diff --git a/crates/hyperswitch_connectors/src/connectors/breadpay.rs b/crates/hyperswitch_connectors/src/connectors/breadpay.rs index c65cb5e23a..f87ee84eda 100644 --- a/crates/hyperswitch_connectors/src/connectors/breadpay.rs +++ b/crates/hyperswitch_connectors/src/connectors/breadpay.rs @@ -2,8 +2,10 @@ pub mod transformers; use std::sync::LazyLock; -use common_enums::enums; +use base64::Engine; +use common_enums::{enums, CallConnectorAction, PaymentAction}; use common_utils::{ + consts::BASE64_ENGINE, errors::CustomResult, ext_traits::BytesExt, request::{Method, Request, RequestBuilder, RequestContent}, @@ -11,30 +13,32 @@ use common_utils::{ }; use error_stack::{report, ResultExt}; use hyperswitch_domain_models::{ - payment_method_data::PaymentMethodData, router_data::{AccessToken, ConnectorAuthType, ErrorResponse, RouterData}, router_flow_types::{ access_token_auth::AccessTokenAuth, payments::{Authorize, Capture, PSync, PaymentMethodToken, Session, SetupMandate, Void}, refunds::{Execute, RSync}, + CompleteAuthorize, }, router_request_types::{ - AccessTokenRequestData, PaymentMethodTokenizationData, PaymentsAuthorizeData, - PaymentsCancelData, PaymentsCaptureData, PaymentsSessionData, PaymentsSyncData, - RefundsData, SetupMandateRequestData, + AccessTokenRequestData, CompleteAuthorizeData, PaymentMethodTokenizationData, + PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, PaymentsSessionData, + PaymentsSyncData, RefundsData, SetupMandateRequestData, }, router_response_types::{ - ConnectorInfo, PaymentsResponseData, RefundsResponseData, SupportedPaymentMethods, + ConnectorInfo, PaymentMethodDetails, PaymentsResponseData, RefundsResponseData, + SupportedPaymentMethods, SupportedPaymentMethodsExt, }, types::{ - PaymentsAuthorizeRouterData, PaymentsCaptureRouterData, PaymentsSyncRouterData, - RefundSyncRouterData, RefundsRouterData, + PaymentsAuthorizeRouterData, PaymentsCancelRouterData, PaymentsCaptureRouterData, + PaymentsCompleteAuthorizeRouterData, PaymentsSyncRouterData, RefundSyncRouterData, + RefundsRouterData, }, }; use hyperswitch_interfaces::{ api::{ - self, ConnectorCommon, ConnectorCommonExt, ConnectorIntegration, ConnectorSpecifications, - ConnectorValidation, + self, ConnectorCommon, ConnectorCommonExt, ConnectorIntegration, ConnectorRedirectResponse, + ConnectorSpecifications, ConnectorValidation, }, configs::Connectors, errors, @@ -42,10 +46,18 @@ use hyperswitch_interfaces::{ types::{self, Response}, webhooks, }; -use masking::{ExposeInterface, Mask}; -use transformers as breadpay; +use masking::{ExposeInterface, Mask, Maskable, PeekInterface}; +use transformers::{ + self as breadpay, BreadpayTransactionRequest, BreadpayTransactionResponse, + BreadpayTransactionType, +}; -use crate::{constants::headers, types::ResponseRouterData, utils}; +use crate::{ + connectors::breadpay::transformers::CallBackResponse, + constants::headers, + types::ResponseRouterData, + utils::{self, PaymentsCompleteAuthorizeRequestData}, +}; #[derive(Clone)] pub struct Breadpay { @@ -62,6 +74,7 @@ impl Breadpay { impl api::Payment for Breadpay {} impl api::PaymentSession for Breadpay {} +impl api::PaymentsCompleteAuthorize for Breadpay {} impl api::ConnectorAccessToken for Breadpay {} impl api::MandateSetup for Breadpay {} impl api::PaymentAuthorize for Breadpay {} @@ -87,7 +100,7 @@ where &self, req: &RouterData, _connectors: &Connectors, - ) -> CustomResult)>, errors::ConnectorError> { + ) -> CustomResult)>, errors::ConnectorError> { let mut header = vec![( headers::CONTENT_TYPE.to_string(), self.get_content_type().to_string().into(), @@ -121,12 +134,17 @@ impl ConnectorCommon for Breadpay { fn get_auth_header( &self, auth_type: &ConnectorAuthType, - ) -> CustomResult)>, errors::ConnectorError> { + ) -> CustomResult)>, errors::ConnectorError> { let auth = breadpay::BreadpayAuthType::try_from(auth_type) .change_context(errors::ConnectorError::FailedToObtainAuthType)?; + let encoded_api_key = BASE64_ENGINE.encode(format!( + "{}:{}", + auth.api_key.peek(), + auth.api_secret.peek() + )); Ok(vec![( headers::AUTHORIZATION.to_string(), - auth.api_key.expose().into_masked(), + format!("Basic {encoded_api_key}").into_masked(), )]) } @@ -145,9 +163,9 @@ impl ConnectorCommon for Breadpay { Ok(ErrorResponse { status_code: res.status_code, - code: response.code, - message: response.message, - reason: response.reason, + code: response.error_type.clone(), + message: response.description.clone(), + reason: Some(response.description), attempt_status: None, connector_transaction_id: None, network_advice_code: None, @@ -157,31 +175,7 @@ impl ConnectorCommon for Breadpay { } } -impl ConnectorValidation for Breadpay { - fn validate_mandate_payment( - &self, - _pm_type: Option, - pm_data: PaymentMethodData, - ) -> CustomResult<(), errors::ConnectorError> { - match pm_data { - PaymentMethodData::Card(_) => Err(errors::ConnectorError::NotImplemented( - "validate_mandate_payment does not support cards".to_string(), - ) - .into()), - _ => Ok(()), - } - } - - fn validate_psync_reference_id( - &self, - _data: &PaymentsSyncData, - _is_three_ds: bool, - _status: enums::AttemptStatus, - _connector_meta_data: Option, - ) -> CustomResult<(), errors::ConnectorError> { - Ok(()) - } -} +impl ConnectorValidation for Breadpay {} impl ConnectorIntegration for Breadpay { //TODO: implement sessions flow @@ -199,7 +193,7 @@ impl ConnectorIntegration CustomResult)>, errors::ConnectorError> { + ) -> CustomResult)>, errors::ConnectorError> { self.build_headers(req, connectors) } @@ -210,9 +204,9 @@ impl ConnectorIntegration CustomResult { - Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into()) + Ok(format!("{}{}", self.base_url(connectors), "/carts")) } fn get_request_body( @@ -227,7 +221,7 @@ impl ConnectorIntegration CustomResult { let response: breadpay::BreadpayPaymentsResponse = res .response - .parse_struct("Breadpay PaymentsAuthorizeResponse") + .parse_struct("Breadpay BreadpayPaymentsResponse") + .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 Breadpay +{ + fn get_headers( + &self, + req: &PaymentsCompleteAuthorizeRouterData, + connectors: &Connectors, + ) -> CustomResult)>, errors::ConnectorError> { + self.build_headers(req, connectors) + } + + fn get_content_type(&self) -> &'static str { + self.common_get_content_type() + } + + fn get_request_body( + &self, + req: &PaymentsCompleteAuthorizeRouterData, + _connectors: &Connectors, + ) -> CustomResult { + let transaction_type = if req.request.is_auto_capture()? { + BreadpayTransactionType::Settle + } else { + BreadpayTransactionType::Authorize + }; + let connector_req = BreadpayTransactionRequest { transaction_type }; + Ok(RequestContent::Json(Box::new(connector_req))) + } + + fn get_url( + &self, + req: &PaymentsCompleteAuthorizeRouterData, + connectors: &Connectors, + ) -> CustomResult { + let redirect_response = req.request.redirect_response.clone().ok_or( + errors::ConnectorError::MissingRequiredField { + field_name: "redirect_response", + }, + )?; + let redirect_payload = redirect_response + .payload + .ok_or(errors::ConnectorError::MissingConnectorRedirectionPayload { + field_name: "request.redirect_response.payload", + })? + .expose(); + let call_back_response: CallBackResponse = serde_json::from_value::( + redirect_payload.clone(), + ) + .change_context(errors::ConnectorError::MissingConnectorRedirectionPayload { + field_name: "redirection_payload", + })?; + + Ok(format!( + "{}{}{}", + self.base_url(connectors), + "/transactions/actions", + call_back_response.transaction_id + )) + } + + fn build_request( + &self, + req: &PaymentsCompleteAuthorizeRouterData, + connectors: &Connectors, + ) -> CustomResult, errors::ConnectorError> { + Ok(Some( + RequestBuilder::new() + .method(Method::Post) + .url(&types::PaymentsCompleteAuthorizeType::get_url( + self, req, connectors, + )?) + .headers(types::PaymentsCompleteAuthorizeType::get_headers( + self, req, connectors, + )?) + .set_body(types::PaymentsCompleteAuthorizeType::get_request_body( + self, req, connectors, + )?) + .build(), + )) + } + + fn handle_response( + &self, + data: &PaymentsCompleteAuthorizeRouterData, + event_builder: Option<&mut ConnectorEvent>, + res: Response, + ) -> CustomResult { + let response: BreadpayTransactionResponse = res + .response + .parse_struct("BreadpayTransactionResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; event_builder.map(|i| i.set_response_body(&response)); router_env::logger::info!(connector_response=?response); @@ -286,7 +389,7 @@ impl ConnectorIntegration for Bre &self, req: &PaymentsSyncRouterData, connectors: &Connectors, - ) -> CustomResult)>, errors::ConnectorError> { + ) -> CustomResult)>, errors::ConnectorError> { self.build_headers(req, connectors) } @@ -296,10 +399,18 @@ impl ConnectorIntegration for Bre fn get_url( &self, - _req: &PaymentsSyncRouterData, - _connectors: &Connectors, + req: &PaymentsSyncRouterData, + connectors: &Connectors, ) -> CustomResult { - Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into()) + Ok(format!( + "{}{}{}", + self.base_url(connectors), + "/transactions", + req.request + .connector_transaction_id + .get_connector_transaction_id() + .change_context(errors::ConnectorError::MissingConnectorTransactionID)? + )) } fn build_request( @@ -323,9 +434,9 @@ impl ConnectorIntegration for Bre event_builder: Option<&mut ConnectorEvent>, res: Response, ) -> CustomResult { - let response: breadpay::BreadpayPaymentsResponse = res + let response: BreadpayTransactionResponse = res .response - .parse_struct("breadpay PaymentsSyncResponse") + .parse_struct("BreadpayTransactionResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; event_builder.map(|i| i.set_response_body(&response)); router_env::logger::info!(connector_response=?response); @@ -350,7 +461,7 @@ impl ConnectorIntegration fo &self, req: &PaymentsCaptureRouterData, connectors: &Connectors, - ) -> CustomResult)>, errors::ConnectorError> { + ) -> CustomResult)>, errors::ConnectorError> { self.build_headers(req, connectors) } @@ -360,10 +471,15 @@ impl ConnectorIntegration fo fn get_url( &self, - _req: &PaymentsCaptureRouterData, - _connectors: &Connectors, + req: &PaymentsCaptureRouterData, + connectors: &Connectors, ) -> CustomResult { - Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into()) + Ok(format!( + "{}{}{}", + self.base_url(connectors), + "/transactions/actions", + req.request.connector_transaction_id + )) } fn get_request_body( @@ -371,7 +487,10 @@ impl ConnectorIntegration fo _req: &PaymentsCaptureRouterData, _connectors: &Connectors, ) -> CustomResult { - Err(errors::ConnectorError::NotImplemented("get_request_body method".to_string()).into()) + let connector_req = BreadpayTransactionRequest { + transaction_type: BreadpayTransactionType::Settle, + }; + Ok(RequestContent::Json(Box::new(connector_req))) } fn build_request( @@ -400,9 +519,9 @@ impl ConnectorIntegration fo event_builder: Option<&mut ConnectorEvent>, res: Response, ) -> CustomResult { - let response: breadpay::BreadpayPaymentsResponse = res + let response: BreadpayTransactionResponse = res .response - .parse_struct("Breadpay PaymentsCaptureResponse") + .parse_struct("BreadpayTransactionResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; event_builder.map(|i| i.set_response_body(&response)); router_env::logger::info!(connector_response=?response); @@ -422,14 +541,95 @@ impl ConnectorIntegration fo } } -impl ConnectorIntegration for Breadpay {} +impl ConnectorIntegration for Breadpay { + fn get_headers( + &self, + req: &PaymentsCancelRouterData, + 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: &PaymentsCancelRouterData, + connectors: &Connectors, + ) -> CustomResult { + Ok(format!( + "{}{}{}", + self.base_url(connectors), + "/transactions/actions", + req.request.connector_transaction_id + )) + } + + fn get_request_body( + &self, + _req: &PaymentsCancelRouterData, + _connectors: &Connectors, + ) -> CustomResult { + let connector_req = BreadpayTransactionRequest { + transaction_type: BreadpayTransactionType::Cancel, + }; + Ok(RequestContent::Json(Box::new(connector_req))) + } + + fn build_request( + &self, + req: &PaymentsCancelRouterData, + connectors: &Connectors, + ) -> CustomResult, errors::ConnectorError> { + Ok(Some( + RequestBuilder::new() + .method(Method::Post) + .url(&types::PaymentsVoidType::get_url(self, req, connectors)?) + .attach_default_headers() + .headers(types::PaymentsVoidType::get_headers(self, req, connectors)?) + .set_body(types::PaymentsVoidType::get_request_body( + self, req, connectors, + )?) + .build(), + )) + } + + fn handle_response( + &self, + data: &PaymentsCancelRouterData, + event_builder: Option<&mut ConnectorEvent>, + res: Response, + ) -> CustomResult { + let response: BreadpayTransactionResponse = res + .response + .parse_struct("BreadpayTransactionResponse") + .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 Breadpay { fn get_headers( &self, req: &RefundsRouterData, connectors: &Connectors, - ) -> CustomResult)>, errors::ConnectorError> { + ) -> CustomResult)>, errors::ConnectorError> { self.build_headers(req, connectors) } @@ -513,7 +713,7 @@ impl ConnectorIntegration for Breadpay &self, req: &RefundSyncRouterData, connectors: &Connectors, - ) -> CustomResult)>, errors::ConnectorError> { + ) -> CustomResult)>, errors::ConnectorError> { self.build_headers(req, connectors) } @@ -600,7 +800,28 @@ impl webhooks::IncomingWebhook for Breadpay { } static BREADPAY_SUPPORTED_PAYMENT_METHODS: LazyLock = - LazyLock::new(SupportedPaymentMethods::new); + LazyLock::new(|| { + let supported_capture_methods = vec![ + enums::CaptureMethod::Automatic, + enums::CaptureMethod::Manual, + enums::CaptureMethod::SequentialAutomatic, + ]; + + let mut breadpay_supported_payment_methods = SupportedPaymentMethods::new(); + + breadpay_supported_payment_methods.add( + enums::PaymentMethod::PayLater, + enums::PaymentMethodType::Breadpay, + PaymentMethodDetails { + mandates: enums::FeatureStatus::NotSupported, + refunds: enums::FeatureStatus::Supported, + supported_capture_methods, + specific_features: None, + }, + ); + + breadpay_supported_payment_methods + }); static BREADPAY_CONNECTOR_INFO: ConnectorInfo = ConnectorInfo { display_name: "Breadpay", @@ -623,3 +844,20 @@ impl ConnectorSpecifications for Breadpay { Some(&BREADPAY_SUPPORTED_WEBHOOK_FLOWS) } } + +impl ConnectorRedirectResponse for Breadpay { + fn get_flow_type( + &self, + _query_params: &str, + _json_payload: Option, + action: PaymentAction, + ) -> CustomResult { + match action { + PaymentAction::PSync + | PaymentAction::CompleteAuthorize + | PaymentAction::PaymentAuthenticateCompleteAuthorize => { + Ok(CallConnectorAction::Trigger) + } + } + } +} diff --git a/crates/hyperswitch_connectors/src/connectors/breadpay/transformers.rs b/crates/hyperswitch_connectors/src/connectors/breadpay/transformers.rs index 4460030ba2..a62881ca6d 100644 --- a/crates/hyperswitch_connectors/src/connectors/breadpay/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/breadpay/transformers.rs @@ -1,20 +1,22 @@ use common_enums::enums; -use common_utils::types::StringMinorUnit; +use common_utils::{request::Method, 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}, + router_response_types::{PaymentsResponseData, RedirectForm, RefundsResponseData}, types::{PaymentsAuthorizeRouterData, RefundsRouterData}, }; use hyperswitch_interfaces::errors; use masking::Secret; use serde::{Deserialize, Serialize}; -use crate::types::{RefundsResponseRouterData, ResponseRouterData}; +use crate::{ + types::{RefundsResponseRouterData, ResponseRouterData}, + utils::{self, PaymentsAuthorizeRequestData}, +}; -//TODO: Fill the struct with respective fields pub struct BreadpayRouterData { pub amount: StringMinorUnit, // The type of amount that a connector accepts, for example, String, i64, f64, etc. pub router_data: T, @@ -22,7 +24,6 @@ pub struct BreadpayRouterData { impl From<(StringMinorUnit, T)> for BreadpayRouterData { 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, @@ -30,93 +31,167 @@ impl From<(StringMinorUnit, T)> for BreadpayRouterData { } } -//TODO: Fill the struct with respective fields -#[derive(Default, Debug, Serialize, PartialEq)] -pub struct BreadpayPaymentsRequest { - amount: StringMinorUnit, - card: BreadpayCard, +#[derive(Debug, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct BreadpayCartRequest { + custom_total: StringMinorUnit, + options: Option, } -#[derive(Default, Debug, Serialize, Eq, PartialEq)] -pub struct BreadpayCard { - number: cards::CardNumber, - expiry_month: Secret, - expiry_year: Secret, - cvc: Secret, - complete: bool, +#[derive(Debug, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct BreadpayCartOptions { + order_ref: Option, + complete_url: String, + callback_url: String, + // billing_contact: Option, } -impl TryFrom<&BreadpayRouterData<&PaymentsAuthorizeRouterData>> for BreadpayPaymentsRequest { +// #[derive(Debug, Serialize)] +// #[serde(rename_all = "camelCase")] +// pub struct BillingContact { +// first_name: Secret, +// last_name: Secret, +// email: Option, +// address: Secret, +// city: Secret, +// state: Secret, +// } + +impl TryFrom<&BreadpayRouterData<&PaymentsAuthorizeRouterData>> for BreadpayCartRequest { type Error = error_stack::Report; fn try_from( item: &BreadpayRouterData<&PaymentsAuthorizeRouterData>, ) -> Result { - match item.router_data.request.payment_method_data.clone() { - PaymentMethodData::Card(_) => Err(errors::ConnectorError::NotImplemented( - "Card payment method not implemented".to_string(), + let request = match item.router_data.request.payment_method_data.clone() { + PaymentMethodData::PayLater(pay_later_data) => match pay_later_data{ + hyperswitch_domain_models::payment_method_data::PayLaterData::BreadpayRedirect { } => { + // let billing_contact = BillingContact { + // first_name: item.router_data.get_billing_first_name()?, + // last_name: item.router_data.get_billing_last_name()?, + // email: item.router_data.get_optional_billing_email(), + // address: item.router_data.get_billing_line1()?, + // city: item.router_data.get_billing_city()?.into(), + // state: item.router_data.get_billing_state()?, + // }; + let options = Some({ + BreadpayCartOptions { + order_ref: item.router_data.request.merchant_order_reference_id.clone(), + complete_url: item.router_data.request.get_complete_authorize_url()?, + callback_url: item.router_data.request.get_router_return_url()? + // billing_contact: Some(billing_contact) + } + }); + Self{ + custom_total: item.amount.clone(), + options, + } + }, + hyperswitch_domain_models::payment_method_data::PayLaterData::KlarnaRedirect { } | + hyperswitch_domain_models::payment_method_data::PayLaterData::WalleyRedirect { } | + hyperswitch_domain_models::payment_method_data::PayLaterData::KlarnaSdk { .. } | + hyperswitch_domain_models::payment_method_data::PayLaterData::AffirmRedirect { } | + hyperswitch_domain_models::payment_method_data::PayLaterData::AfterpayClearpayRedirect { } | + hyperswitch_domain_models::payment_method_data::PayLaterData::PayBrightRedirect { } | + hyperswitch_domain_models::payment_method_data::PayLaterData::AlmaRedirect { } | + hyperswitch_domain_models::payment_method_data::PayLaterData::AtomeRedirect { } => { + Err(errors::ConnectorError::NotImplemented( + utils::get_unimplemented_payment_method_error_message("breadpay"), + )) + }?, + }, + PaymentMethodData::Card(_) + | PaymentMethodData::CardDetailsForNetworkTransactionId( + _, ) - .into()), - _ => Err(errors::ConnectorError::NotImplemented("Payment method".to_string()).into()), - } + | PaymentMethodData::CardRedirect(_) + | PaymentMethodData::Wallet(_) + | PaymentMethodData::BankRedirect(_) + | PaymentMethodData::BankDebit(_) + | PaymentMethodData::BankTransfer(_) + | PaymentMethodData::Crypto(_) + | PaymentMethodData::MandatePayment + | PaymentMethodData::Reward + | PaymentMethodData::RealTimePayment(_) + | PaymentMethodData::Upi(_) + | PaymentMethodData::Voucher(_) + | PaymentMethodData::GiftCard(_) + | PaymentMethodData::CardToken(_) + | PaymentMethodData::OpenBanking(_) + | PaymentMethodData::NetworkToken(_) + | PaymentMethodData::MobilePayment(_) => { + Err(errors::ConnectorError::NotImplemented( + utils::get_unimplemented_payment_method_error_message("breadpay"), + )) + }? + }; + Ok(request) } } -//TODO: Fill the struct with respective fields +#[derive(Debug, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct BreadpayTransactionRequest { + #[serde(rename = "type")] + pub transaction_type: BreadpayTransactionType, +} + +#[derive(Debug, Serialize)] +pub enum BreadpayTransactionType { + Authorize, + Settle, + Cancel, + Refund, +} + // Auth Struct pub struct BreadpayAuthType { pub(super) api_key: Secret, + pub(super) api_secret: Secret, } impl TryFrom<&ConnectorAuthType> for BreadpayAuthType { type Error = error_stack::Report; fn try_from(auth_type: &ConnectorAuthType) -> Result { match auth_type { - ConnectorAuthType::HeaderKey { api_key } => Ok(Self { + ConnectorAuthType::BodyKey { api_key, key1 } => Ok(Self { api_key: api_key.to_owned(), + api_secret: key1.to_owned(), }), _ => Err(errors::ConnectorError::FailedToObtainAuthType.into()), } } } -// PaymentsResponse -//TODO: Append the remaining status flags -#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq)] -#[serde(rename_all = "lowercase")] -pub enum BreadpayPaymentStatus { - Succeeded, - Failed, - #[default] - Processing, + +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct BreadpayTransactionResponse { + status: TransactionStatus, + bread_transactin_id: String, + merchant_order_id: String, } -impl From for common_enums::AttemptStatus { - fn from(item: BreadpayPaymentStatus) -> Self { - match item { - BreadpayPaymentStatus::Succeeded => Self::Charged, - BreadpayPaymentStatus::Failed => Self::Failure, - BreadpayPaymentStatus::Processing => Self::Authorizing, - } - } +#[derive(Debug, Clone, Deserialize, Serialize)] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +pub enum TransactionStatus { + Pending, + Canceled, + Refunded, + Expired, + Authorized, + Settled, } -//TODO: Fill the struct with respective fields -#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)] -pub struct BreadpayPaymentsResponse { - status: BreadpayPaymentStatus, - id: String, -} - -impl TryFrom> +impl TryFrom> for RouterData { type Error = error_stack::Report; fn try_from( - item: ResponseRouterData, + item: ResponseRouterData, ) -> Result { Ok(Self { - status: common_enums::AttemptStatus::from(item.response.status), + status: enums::AttemptStatus::from(item.response.status.clone()), response: Ok(PaymentsResponseData::TransactionResponse { - resource_id: ResponseId::ConnectorTransactionId(item.response.id), + resource_id: ResponseId::ConnectorTransactionId(item.response.bread_transactin_id), redirection_data: Box::new(None), mandate_reference: Box::new(None), connector_metadata: None, @@ -130,12 +205,65 @@ impl TryFrom for enums::AttemptStatus { + fn from(item: TransactionStatus) -> Self { + match item { + TransactionStatus::Pending => Self::Pending, + TransactionStatus::Authorized => Self::Authorized, + TransactionStatus::Canceled => Self::Voided, + TransactionStatus::Refunded => Self::AutoRefunded, + TransactionStatus::Expired => Self::Failure, + TransactionStatus::Settled => Self::Charged, + } + } +} + +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct BreadpayPaymentsResponse { + url: url::Url, +} + +impl TryFrom> + for RouterData +{ + type Error = error_stack::Report; + fn try_from( + item: ResponseRouterData, + ) -> Result { + Ok(Self { + // As per documentation, the first call is cart creation where we don't get any status only get the customer redirection url. + status: common_enums::AttemptStatus::AuthenticationPending, + response: Ok(PaymentsResponseData::TransactionResponse { + resource_id: ResponseId::NoResponseId, + redirection_data: Box::new(Some(RedirectForm::from(( + item.response.url, + Method::Get, + )))), + mandate_reference: Box::new(None), + connector_metadata: None, + network_txn_id: None, + connector_response_reference_id: None, + incremental_authorization_allowed: None, + charges: None, + }), + ..item.data + }) + } +} + +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct CallBackResponse { + pub transaction_id: String, + pub order_ref: String, +} + // REFUND : // Type definition for RefundRequest -#[derive(Default, Debug, Serialize)] +#[derive(Debug, Serialize)] pub struct BreadpayRefundRequest { pub amount: StringMinorUnit, + #[serde(rename = "type")] + pub transaction_type: BreadpayTransactionType, } impl TryFrom<&BreadpayRouterData<&RefundsRouterData>> for BreadpayRefundRequest { @@ -143,6 +271,7 @@ impl TryFrom<&BreadpayRouterData<&RefundsRouterData>> for BreadpayRefundRe fn try_from(item: &BreadpayRouterData<&RefundsRouterData>) -> Result { Ok(Self { amount: item.amount.to_owned(), + transaction_type: BreadpayTransactionType::Refund, }) } } @@ -206,14 +335,12 @@ impl TryFrom> for RefundsRouter } } -//TODO: Fill the struct with respective fields -#[derive(Default, Debug, Serialize, Deserialize, PartialEq)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct BreadpayErrorResponse { - pub status_code: u16, - pub code: String, - pub message: String, - pub reason: Option, - pub network_advice_code: Option, - pub network_decline_code: Option, - pub network_error_message: Option, + /// Human-readable error description + pub description: String, + + /// Error type classification + #[serde(rename = "type")] + pub error_type: String, } diff --git a/crates/hyperswitch_connectors/src/connectors/klarna.rs b/crates/hyperswitch_connectors/src/connectors/klarna.rs index 58909d4881..4adec86a57 100644 --- a/crates/hyperswitch_connectors/src/connectors/klarna.rs +++ b/crates/hyperswitch_connectors/src/connectors/klarna.rs @@ -646,7 +646,8 @@ impl ConnectorIntegration Err(error_stack::report!(errors::ConnectorError::NotSupported { message: payment_method_type.to_string(), connector: "klarna", @@ -767,7 +768,8 @@ impl ConnectorIntegration Err(error_stack::report!(errors::ConnectorError::NotSupported { message: payment_method_type.to_string(), connector: "klarna", @@ -894,7 +896,8 @@ impl ConnectorIntegration Err(error_stack::report!(errors::ConnectorError::NotSupported { message: payment_method_type.to_string(), connector: "klarna", @@ -1014,6 +1017,7 @@ impl ConnectorIntegration Err(error_stack::report!(errors::ConnectorError::NotSupported { diff --git a/crates/hyperswitch_connectors/src/connectors/multisafepay/transformers.rs b/crates/hyperswitch_connectors/src/connectors/multisafepay/transformers.rs index 9f21a3f260..2739836a22 100644 --- a/crates/hyperswitch_connectors/src/connectors/multisafepay/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/multisafepay/transformers.rs @@ -801,7 +801,8 @@ impl TryFrom<&MultisafepayRouterData<&types::PaymentsAuthorizeRouterData>> | PayLaterData::PayBrightRedirect {} | PayLaterData::WalleyRedirect {} | PayLaterData::AlmaRedirect {} - | PayLaterData::AtomeRedirect {} => { + | PayLaterData::AtomeRedirect {} + | PayLaterData::BreadpayRedirect {} => { Err(errors::ConnectorError::NotImplemented( utils::get_unimplemented_payment_method_error_message( "multisafepay", diff --git a/crates/hyperswitch_connectors/src/connectors/nuvei/transformers.rs b/crates/hyperswitch_connectors/src/connectors/nuvei/transformers.rs index bc1ed7753b..986d7ec7f0 100644 --- a/crates/hyperswitch_connectors/src/connectors/nuvei/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/nuvei/transformers.rs @@ -1010,7 +1010,8 @@ where | PayLaterData::PayBrightRedirect {} | PayLaterData::WalleyRedirect {} | PayLaterData::AlmaRedirect {} - | PayLaterData::AtomeRedirect {} => Err(errors::ConnectorError::NotImplemented( + | PayLaterData::AtomeRedirect {} + | PayLaterData::BreadpayRedirect {} => Err(errors::ConnectorError::NotImplemented( utils::get_unimplemented_payment_method_error_message("nuvei"), ) .into()), diff --git a/crates/hyperswitch_connectors/src/connectors/paypal/transformers.rs b/crates/hyperswitch_connectors/src/connectors/paypal/transformers.rs index cc6c7ba3d1..289fee48d9 100644 --- a/crates/hyperswitch_connectors/src/connectors/paypal/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/paypal/transformers.rs @@ -1264,7 +1264,8 @@ impl TryFrom<&PaypalRouterData<&PaymentsAuthorizeRouterData>> for PaypalPayments | enums::PaymentMethodType::Mifinity | enums::PaymentMethodType::Paze | enums::PaymentMethodType::IndonesianBankTransfer - | enums::PaymentMethodType::RevolutPay => { + | enums::PaymentMethodType::RevolutPay + | enums::PaymentMethodType::Breadpay => { Err(errors::ConnectorError::NotImplemented( utils::get_unimplemented_payment_method_error_message("paypal"), )) @@ -1321,7 +1322,8 @@ impl TryFrom<&PayLaterData> for PaypalPaymentsRequest { | PayLaterData::PayBrightRedirect {} | PayLaterData::WalleyRedirect {} | PayLaterData::AlmaRedirect {} - | PayLaterData::AtomeRedirect {} => Err(errors::ConnectorError::NotImplemented( + | PayLaterData::AtomeRedirect {} + | PayLaterData::BreadpayRedirect {} => Err(errors::ConnectorError::NotImplemented( utils::get_unimplemented_payment_method_error_message("Paypal"), ) .into()), diff --git a/crates/hyperswitch_connectors/src/connectors/shift4/transformers.rs b/crates/hyperswitch_connectors/src/connectors/shift4/transformers.rs index 5eec6440bd..b66edc9bf7 100644 --- a/crates/hyperswitch_connectors/src/connectors/shift4/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/shift4/transformers.rs @@ -296,7 +296,8 @@ impl TryFrom<&PayLaterData> for PaymentMethodType { | PayLaterData::WalleyRedirect { .. } | PayLaterData::AlmaRedirect { .. } | PayLaterData::AtomeRedirect { .. } - | PayLaterData::KlarnaSdk { .. } => Err(errors::ConnectorError::NotImplemented( + | PayLaterData::KlarnaSdk { .. } + | PayLaterData::BreadpayRedirect { .. } => Err(errors::ConnectorError::NotImplemented( utils::get_unimplemented_payment_method_error_message("Shift4"), ) .into()), diff --git a/crates/hyperswitch_connectors/src/connectors/square/transformers.rs b/crates/hyperswitch_connectors/src/connectors/square/transformers.rs index 8014ca0f23..fb6a345899 100644 --- a/crates/hyperswitch_connectors/src/connectors/square/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/square/transformers.rs @@ -89,9 +89,12 @@ impl TryFrom<(&types::TokenizationRouterData, PayLaterData)> for SquareTokenRequ | PayLaterData::PayBrightRedirect { .. } | PayLaterData::WalleyRedirect { .. } | PayLaterData::AlmaRedirect { .. } - | PayLaterData::AtomeRedirect { .. } => Err(errors::ConnectorError::NotImplemented( - utils::get_unimplemented_payment_method_error_message("Square"), - ))?, + | PayLaterData::AtomeRedirect { .. } + | PayLaterData::BreadpayRedirect { .. } => { + Err(errors::ConnectorError::NotImplemented( + utils::get_unimplemented_payment_method_error_message("Square"), + ))? + } } } } diff --git a/crates/hyperswitch_connectors/src/connectors/stripe/transformers.rs b/crates/hyperswitch_connectors/src/connectors/stripe/transformers.rs index 9f18717025..d566b0548d 100644 --- a/crates/hyperswitch_connectors/src/connectors/stripe/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/stripe/transformers.rs @@ -833,7 +833,8 @@ impl TryFrom for StripePaymentMethodType { | enums::PaymentMethodType::PromptPay | enums::PaymentMethodType::VietQr | enums::PaymentMethodType::IndonesianBankTransfer - | enums::PaymentMethodType::Mifinity => Err(ConnectorError::NotImplemented( + | enums::PaymentMethodType::Mifinity + | enums::PaymentMethodType::Breadpay => Err(ConnectorError::NotImplemented( get_unimplemented_payment_method_error_message("stripe"), ) .into()), @@ -1068,7 +1069,8 @@ impl TryFrom<&PayLaterData> for StripePaymentMethodType { | PayLaterData::PayBrightRedirect {} | PayLaterData::WalleyRedirect {} | PayLaterData::AlmaRedirect {} - | PayLaterData::AtomeRedirect {} => Err(ConnectorError::NotImplemented( + | PayLaterData::AtomeRedirect {} + | PayLaterData::BreadpayRedirect {} => Err(ConnectorError::NotImplemented( get_unimplemented_payment_method_error_message("stripe"), )), } diff --git a/crates/hyperswitch_connectors/src/connectors/zen/transformers.rs b/crates/hyperswitch_connectors/src/connectors/zen/transformers.rs index b017f4b229..9af9745f2e 100644 --- a/crates/hyperswitch_connectors/src/connectors/zen/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/zen/transformers.rs @@ -765,7 +765,8 @@ impl TryFrom<&PayLaterData> for ZenPaymentsRequest { | PayLaterData::PayBrightRedirect {} | PayLaterData::WalleyRedirect {} | PayLaterData::AlmaRedirect {} - | PayLaterData::AtomeRedirect {} => Err(errors::ConnectorError::NotImplemented( + | PayLaterData::AtomeRedirect {} + | PayLaterData::BreadpayRedirect {} => Err(errors::ConnectorError::NotImplemented( utils::get_unimplemented_payment_method_error_message("Zen"), ) .into()), diff --git a/crates/hyperswitch_connectors/src/default_implementations.rs b/crates/hyperswitch_connectors/src/default_implementations.rs index c43658a0c1..6780e0366a 100644 --- a/crates/hyperswitch_connectors/src/default_implementations.rs +++ b/crates/hyperswitch_connectors/src/default_implementations.rs @@ -956,7 +956,6 @@ default_imp_for_complete_authorize!( connectors::Bitpay, connectors::Blackhawknetwork, connectors::Boku, - connectors::Breadpay, connectors::Cashtocode, connectors::Celero, connectors::Chargebee, @@ -1333,7 +1332,6 @@ default_imp_for_connector_redirect_response!( connectors::Bankofamerica, connectors::Barclaycard, connectors::Boku, - connectors::Breadpay, connectors::Cashtocode, connectors::Celero, connectors::Chargebee, diff --git a/crates/hyperswitch_connectors/src/utils.rs b/crates/hyperswitch_connectors/src/utils.rs index af78996422..f210b01ff7 100644 --- a/crates/hyperswitch_connectors/src/utils.rs +++ b/crates/hyperswitch_connectors/src/utils.rs @@ -5474,6 +5474,7 @@ pub enum PaymentMethodDataType { WalleyRedirect, AlmaRedirect, AtomeRedirect, + Breadpay, BancontactCard, Bizum, Blik, @@ -5610,6 +5611,7 @@ impl From for PaymentMethodDataType { payment_method_data::PayLaterData::WalleyRedirect {} => Self::WalleyRedirect, payment_method_data::PayLaterData::AlmaRedirect {} => Self::AlmaRedirect, payment_method_data::PayLaterData::AtomeRedirect {} => Self::AtomeRedirect, + payment_method_data::PayLaterData::BreadpayRedirect {} => Self::Breadpay, }, PaymentMethodData::BankRedirect(bank_redirect_data) => match bank_redirect_data { payment_method_data::BankRedirectData::BancontactCard { .. } => { diff --git a/crates/hyperswitch_domain_models/src/payment_method_data.rs b/crates/hyperswitch_domain_models/src/payment_method_data.rs index 14b1d3dc87..bea70f4d54 100644 --- a/crates/hyperswitch_domain_models/src/payment_method_data.rs +++ b/crates/hyperswitch_domain_models/src/payment_method_data.rs @@ -234,6 +234,7 @@ pub enum PayLaterData { WalleyRedirect {}, AlmaRedirect {}, AtomeRedirect {}, + BreadpayRedirect {}, } #[derive(Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize)] @@ -1188,6 +1189,7 @@ impl From for PayLaterData { api_models::payments::PayLaterData::WalleyRedirect {} => Self::WalleyRedirect {}, api_models::payments::PayLaterData::AlmaRedirect {} => Self::AlmaRedirect {}, api_models::payments::PayLaterData::AtomeRedirect {} => Self::AtomeRedirect {}, + api_models::payments::PayLaterData::BreadpayRedirect {} => Self::BreadpayRedirect {}, } } } @@ -1884,6 +1886,7 @@ impl GetPaymentMethodType for PayLaterData { Self::WalleyRedirect {} => api_enums::PaymentMethodType::Walley, Self::AlmaRedirect {} => api_enums::PaymentMethodType::Alma, Self::AtomeRedirect {} => api_enums::PaymentMethodType::Atome, + Self::BreadpayRedirect {} => api_enums::PaymentMethodType::Breadpay, } } } diff --git a/crates/kgraph_utils/src/mca.rs b/crates/kgraph_utils/src/mca.rs index 3eb5b2c904..4c648f8e5d 100644 --- a/crates/kgraph_utils/src/mca.rs +++ b/crates/kgraph_utils/src/mca.rs @@ -116,6 +116,7 @@ fn get_dir_value_payment_method( } api_enums::PaymentMethodType::BniVa => Ok(dirval!(BankTransferType = BniVa)), api_enums::PaymentMethodType::BriVa => Ok(dirval!(BankTransferType = BriVa)), + api_enums::PaymentMethodType::Breadpay => Ok(dirval!(PayLaterType = Breadpay)), api_enums::PaymentMethodType::CimbVa => Ok(dirval!(BankTransferType = CimbVa)), api_enums::PaymentMethodType::DanamonVa => Ok(dirval!(BankTransferType = DanamonVa)), api_enums::PaymentMethodType::Indomaret => Ok(dirval!(VoucherType = Indomaret)), diff --git a/crates/kgraph_utils/src/transformers.rs b/crates/kgraph_utils/src/transformers.rs index 9928f730a2..d9a9aee272 100644 --- a/crates/kgraph_utils/src/transformers.rs +++ b/crates/kgraph_utils/src/transformers.rs @@ -225,12 +225,11 @@ impl IntoDirValue for (api_enums::PaymentMethodType, api_enums::PaymentMethod) { api_enums::PaymentMethodType::Swish => Ok(dirval!(WalletType = Swish)), api_enums::PaymentMethodType::Trustly => Ok(dirval!(BankRedirectType = Trustly)), api_enums::PaymentMethodType::Bizum => Ok(dirval!(BankRedirectType = Bizum)), - api_enums::PaymentMethodType::PayBright => Ok(dirval!(PayLaterType = PayBright)), api_enums::PaymentMethodType::Walley => Ok(dirval!(PayLaterType = Walley)), + api_enums::PaymentMethodType::Breadpay => Ok(dirval!(PayLaterType = Breadpay)), api_enums::PaymentMethodType::Przelewy24 => Ok(dirval!(BankRedirectType = Przelewy24)), api_enums::PaymentMethodType::WeChatPay => Ok(dirval!(WalletType = WeChatPay)), - api_enums::PaymentMethodType::ClassicReward => Ok(dirval!(RewardType = ClassicReward)), api_enums::PaymentMethodType::Evoucher => Ok(dirval!(RewardType = Evoucher)), api_enums::PaymentMethodType::UpiCollect => Ok(dirval!(UpiType = UpiCollect)), diff --git a/crates/payment_methods/src/helpers.rs b/crates/payment_methods/src/helpers.rs index be03256167..d4188b228a 100644 --- a/crates/payment_methods/src/helpers.rs +++ b/crates/payment_methods/src/helpers.rs @@ -98,6 +98,7 @@ pub fn validate_payment_method_type_against_payment_method( | api_enums::PaymentMethodType::PayBright | api_enums::PaymentMethodType::Atome | api_enums::PaymentMethodType::Walley + | api_enums::PaymentMethodType::Breadpay ), api_enums::PaymentMethod::Wallet => matches!( payment_method_type, diff --git a/crates/router/src/connector/utils.rs b/crates/router/src/connector/utils.rs index cb0a2cc3d0..525a9d678a 100644 --- a/crates/router/src/connector/utils.rs +++ b/crates/router/src/connector/utils.rs @@ -2460,6 +2460,7 @@ pub enum PaymentMethodDataType { WalleyRedirect, AlmaRedirect, AtomeRedirect, + BreadpayRedirect, BancontactCard, Bizum, Blik, @@ -2595,6 +2596,7 @@ impl From for PaymentMethodDataType { domain::payments::PayLaterData::WalleyRedirect {} => Self::WalleyRedirect, domain::payments::PayLaterData::AlmaRedirect {} => Self::AlmaRedirect, domain::payments::PayLaterData::AtomeRedirect {} => Self::AtomeRedirect, + domain::payments::PayLaterData::BreadpayRedirect {} => Self::BreadpayRedirect, }, domain::payments::PaymentMethodData::BankRedirect(bank_redirect_data) => { match bank_redirect_data { diff --git a/crates/router/src/core/connector_validation.rs b/crates/router/src/core/connector_validation.rs index f04edb139f..b442e832a2 100644 --- a/crates/router/src/core/connector_validation.rs +++ b/crates/router/src/core/connector_validation.rs @@ -134,6 +134,10 @@ impl ConnectorAuthTypeAndMetadataValidation<'_> { braintree::transformers::BraintreeMeta::try_from(self.connector_meta_data)?; Ok(()) } + api_enums::Connector::Breadpay => { + breadpay::transformers::BreadpayAuthType::try_from(self.auth_type)?; + Ok(()) + } api_enums::Connector::Cashtocode => { cashtocode::transformers::CashtocodeAuthType::try_from(self.auth_type)?; Ok(()) diff --git a/crates/router/src/types/api/connector_mapping.rs b/crates/router/src/types/api/connector_mapping.rs index e80d75a7ec..b4150b9544 100644 --- a/crates/router/src/types/api/connector_mapping.rs +++ b/crates/router/src/types/api/connector_mapping.rs @@ -148,6 +148,9 @@ impl ConnectorData { enums::Connector::Braintree => { Ok(ConnectorEnum::Old(Box::new(connector::Braintree::new()))) } + enums::Connector::Breadpay => { + Ok(ConnectorEnum::Old(Box::new(connector::Breadpay::new()))) + } enums::Connector::Cashtocode => { Ok(ConnectorEnum::Old(Box::new(connector::Cashtocode::new()))) } diff --git a/crates/router/src/types/connector_transformers.rs b/crates/router/src/types/connector_transformers.rs index 47cdf592aa..c6a01ce084 100644 --- a/crates/router/src/types/connector_transformers.rs +++ b/crates/router/src/types/connector_transformers.rs @@ -24,6 +24,7 @@ impl ForeignTryFrom for common_enums::RoutableConnectors { api_enums::Connector::Bluesnap => Self::Bluesnap, api_enums::Connector::Boku => Self::Boku, api_enums::Connector::Braintree => Self::Braintree, + api_enums::Connector::Breadpay => Self::Breadpay, api_enums::Connector::Cashtocode => Self::Cashtocode, api_enums::Connector::Celero => Self::Celero, api_enums::Connector::Chargebee => Self::Chargebee, diff --git a/crates/router/src/types/transformers.rs b/crates/router/src/types/transformers.rs index 5004186e84..5cd1c3d3bd 100644 --- a/crates/router/src/types/transformers.rs +++ b/crates/router/src/types/transformers.rs @@ -297,7 +297,8 @@ impl ForeignFrom for api_enums::PaymentMethod { | api_enums::PaymentMethodType::Klarna | api_enums::PaymentMethodType::PayBright | api_enums::PaymentMethodType::Atome - | api_enums::PaymentMethodType::Walley => Self::PayLater, + | api_enums::PaymentMethodType::Walley + | api_enums::PaymentMethodType::Breadpay => Self::PayLater, api_enums::PaymentMethodType::Giropay | api_enums::PaymentMethodType::Ideal | api_enums::PaymentMethodType::Sofort