diff --git a/crates/connector_configs/toml/development.toml b/crates/connector_configs/toml/development.toml index 61d748634227..d9e7ec58f755 100644 --- a/crates/connector_configs/toml/development.toml +++ b/crates/connector_configs/toml/development.toml @@ -398,26 +398,9 @@ merchant_secret="Source verification key" payment_method_type = "CartesBancaires" [[bambora.debit]] payment_method_type = "UnionPay" -[[bambora.wallet]] - payment_method_type = "apple_pay" -[[bambora.wallet]] - payment_method_type = "paypal" [bambora.connector_auth.BodyKey] api_key="Passcode" key1="Merchant Id" -[bambora.connector_webhook_details] -merchant_secret="Source verification key" -[bambora.metadata.apple_pay.session_token_data] -certificate="Merchant Certificate (Base64 Encoded)" -certificate_keys="Merchant PrivateKey (Base64 Encoded)" -merchant_identifier="Apple Merchant Identifier" -display_name="Display Name" -initiative="Domain" -initiative_context="Domain Name" -[bambora.metadata.apple_pay.payment_request_data] -supported_networks=["visa","masterCard","amex","discover"] -merchant_capabilities=["supports3DS"] -label="apple" [bankofamerica] [[bankofamerica.credit]] diff --git a/crates/connector_configs/toml/production.toml b/crates/connector_configs/toml/production.toml index 10cd9d6f7cf3..202bce64c1fd 100644 --- a/crates/connector_configs/toml/production.toml +++ b/crates/connector_configs/toml/production.toml @@ -416,27 +416,9 @@ merchant_config_currency="Currency" payment_method_type = "CartesBancaires" [[bambora.debit]] payment_method_type = "UnionPay" -[[bambora.wallet]] - payment_method_type = "apple_pay" -[[bambora.wallet]] - payment_method_type = "paypal" [bambora.connector_auth.BodyKey] api_key="Passcode" key1="Merchant Id" -[bambora.connector_webhook_details] -merchant_secret="Source verification key" - -[bambora.metadata.apple_pay.session_token_data] -certificate="Merchant Certificate (Base64 Encoded)" -certificate_keys="Merchant PrivateKey (Base64 Encoded)" -merchant_identifier="Apple Merchant Identifier" -display_name="Display Name" -initiative="Domain" -initiative_context="Domain Name" -[bambora.metadata.apple_pay.payment_request_data] -supported_networks=["visa","masterCard","amex","discover"] -merchant_capabilities=["supports3DS"] -label="apple" [bankofamerica] [[bankofamerica.credit]] diff --git a/crates/connector_configs/toml/sandbox.toml b/crates/connector_configs/toml/sandbox.toml index 7f4935d48879..450e14d1080a 100644 --- a/crates/connector_configs/toml/sandbox.toml +++ b/crates/connector_configs/toml/sandbox.toml @@ -398,26 +398,9 @@ merchant_secret="Source verification key" payment_method_type = "CartesBancaires" [[bambora.debit]] payment_method_type = "UnionPay" -[[bambora.wallet]] - payment_method_type = "apple_pay" -[[bambora.wallet]] - payment_method_type = "paypal" [bambora.connector_auth.BodyKey] api_key="Passcode" key1="Merchant Id" -[bambora.connector_webhook_details] -merchant_secret="Source verification key" -[bambora.metadata.apple_pay.session_token_data] -certificate="Merchant Certificate (Base64 Encoded)" -certificate_keys="Merchant PrivateKey (Base64 Encoded)" -merchant_identifier="Apple Merchant Identifier" -display_name="Display Name" -initiative="Domain" -initiative_context="Domain Name" -[bambora.metadata.apple_pay.payment_request_data] -supported_networks=["visa","masterCard","amex","discover"] -merchant_capabilities=["supports3DS"] -label="apple" [bankofamerica] [[bankofamerica.credit]] diff --git a/crates/router/src/connector/bambora.rs b/crates/router/src/connector/bambora.rs index 7ff352416cd8..684c5ddc1ce1 100644 --- a/crates/router/src/connector/bambora.rs +++ b/crates/router/src/connector/bambora.rs @@ -10,10 +10,7 @@ use transformers as bambora; use super::utils::RefundsRequestData; use crate::{ configs::settings, - connector::{ - utils as connector_utils, - utils::{to_connector_meta, PaymentsAuthorizeRequestData, PaymentsSyncRequestData}, - }, + connector::{utils as connector_utils, utils::to_connector_meta}, core::{ errors::{self, CustomResult}, payments, @@ -36,6 +33,20 @@ use crate::{ #[derive(Debug, Clone)] pub struct Bambora; +impl api::Payment for Bambora {} +impl api::PaymentToken for Bambora {} +impl api::PaymentAuthorize for Bambora {} +impl api::PaymentVoid for Bambora {} +impl api::MandateSetup for Bambora {} +impl api::ConnectorAccessToken for Bambora {} +impl api::PaymentSync for Bambora {} +impl api::PaymentCapture for Bambora {} +impl api::PaymentSession for Bambora {} +impl api::Refund for Bambora {} +impl api::RefundExecute for Bambora {} +impl api::RefundSync for Bambora {} +impl api::PaymentsCompleteAuthorize for Bambora {} + impl ConnectorCommonExt for Bambora where Self: ConnectorIntegration, @@ -102,8 +113,9 @@ impl ConnectorCommon for Bambora { Ok(ErrorResponse { status_code: res.status_code, code: response.code.to_string(), - message: response.message, - reason: Some(serde_json::to_string(&response.details).unwrap_or_default()), + message: serde_json::to_string(&response.details) + .unwrap_or(crate::consts::NO_ERROR_MESSAGE.to_string()), + reason: Some(response.message), attempt_status: None, connector_transaction_id: None, }) @@ -126,10 +138,6 @@ impl ConnectorValidation for Bambora { } } -impl api::Payment for Bambora {} - -impl api::PaymentToken for Bambora {} - impl ConnectorIntegration< api::PaymentMethodToken, @@ -140,7 +148,17 @@ impl // Not Implemented (R) } -impl api::MandateSetup for Bambora {} +impl ConnectorIntegration + for Bambora +{ +} + +impl ConnectorIntegration + for Bambora +{ + //TODO: implement sessions flow +} + impl ConnectorIntegration< api::SetupMandate, @@ -164,14 +182,12 @@ impl } } -impl api::PaymentVoid for Bambora {} - -impl ConnectorIntegration +impl ConnectorIntegration for Bambora { fn get_headers( &self, - req: &types::PaymentsCancelRouterData, + req: &types::PaymentsAuthorizeRouterData, connectors: &settings::Connectors, ) -> CustomResult)>, errors::ConnectorError> { self.build_headers(req, connectors) @@ -183,82 +199,68 @@ impl ConnectorIntegration CustomResult { - let connector_payment_id = req.request.connector_transaction_id.clone(); - Ok(format!( - "{}/v1/payments/{}{}", - self.base_url(connectors), - connector_payment_id, - "/void" - )) + Ok(format!("{}{}", self.base_url(connectors), "/v1/payments")) } fn get_request_body( &self, - req: &types::PaymentsCancelRouterData, + req: &types::PaymentsAuthorizeRouterData, _connectors: &settings::Connectors, ) -> CustomResult { let connector_router_data = bambora::BamboraRouterData::try_from(( &self.get_currency_unit(), - req.request - .currency - .ok_or(errors::ConnectorError::MissingRequiredField { - field_name: "Currency", - })?, - req.request - .amount - .ok_or(errors::ConnectorError::MissingRequiredField { - field_name: "Amount", - })?, + req.request.currency, + req.request.amount, req, ))?; - let connector_req = bambora::BamboraVoidRequest::try_from(connector_router_data)?; - + let connector_req = bambora::BamboraPaymentsRequest::try_from(connector_router_data)?; Ok(RequestContent::Json(Box::new(connector_req))) } fn build_request( &self, - req: &types::PaymentsCancelRouterData, + req: &types::PaymentsAuthorizeRouterData, connectors: &settings::Connectors, ) -> CustomResult, errors::ConnectorError> { Ok(Some( services::RequestBuilder::new() .method(services::Method::Post) - .url(&types::PaymentsVoidType::get_url(self, req, connectors)?) + .url(&types::PaymentsAuthorizeType::get_url( + self, req, connectors, + )?) .attach_default_headers() - .headers(types::PaymentsVoidType::get_headers(self, req, connectors)?) - .set_body(self.get_request_body(req, connectors)?) + .headers(types::PaymentsAuthorizeType::get_headers( + self, req, connectors, + )?) + .set_body(types::PaymentsAuthorizeType::get_request_body( + self, req, connectors, + )?) .build(), )) } fn handle_response( &self, - data: &types::PaymentsCancelRouterData, + data: &types::PaymentsAuthorizeRouterData, event_builder: Option<&mut ConnectorEvent>, res: Response, - ) -> CustomResult { + ) -> CustomResult { let response: bambora::BamboraResponse = res .response - .parse_struct("bambora PaymentsResponse") + .parse_struct("PaymentIntentResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; - event_builder.map(|i| i.set_response_body(&response)); router_env::logger::info!(connector_response=?response); - types::RouterData::try_from(( - types::ResponseRouterData { - response, - data: data.clone(), - http_code: res.status_code, - }, - bambora::PaymentFlow::Void, - )) - .change_context(errors::ConnectorError::ResponseHandlingFailed) + types::RouterData::try_from(types::ResponseRouterData { + response, + data: data.clone(), + http_code: res.status_code, + }) } fn get_error_response( @@ -270,14 +272,99 @@ impl ConnectorIntegration - for Bambora +impl + ConnectorIntegration< + api::CompleteAuthorize, + types::CompleteAuthorizeData, + types::PaymentsResponseData, + > for Bambora { + fn get_headers( + &self, + req: &types::PaymentsCompleteAuthorizeRouterData, + connectors: &settings::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: &types::PaymentsCompleteAuthorizeRouterData, + connectors: &settings::Connectors, + ) -> CustomResult { + let meta: bambora::BamboraMeta = to_connector_meta(req.request.connector_meta.clone())?; + Ok(format!( + "{}/v1/payments/{}{}", + self.base_url(connectors), + meta.three_d_session_data, + "/continue" + )) + } + + fn get_request_body( + &self, + req: &types::PaymentsCompleteAuthorizeRouterData, + _connectors: &settings::Connectors, + ) -> CustomResult { + let connector_req = bambora::BamboraThreedsContinueRequest::try_from(&req.request)?; + + Ok(RequestContent::Json(Box::new(connector_req))) + } + + fn build_request( + &self, + req: &types::PaymentsCompleteAuthorizeRouterData, + connectors: &settings::Connectors, + ) -> CustomResult, errors::ConnectorError> { + let request = services::RequestBuilder::new() + .method(services::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(); + Ok(Some(request)) + } + + fn handle_response( + &self, + data: &types::PaymentsCompleteAuthorizeRouterData, + event_builder: Option<&mut ConnectorEvent>, + res: Response, + ) -> CustomResult { + let response: bambora::BamboraPaymentsResponse = res + .response + .parse_struct("BamboraPaymentsResponse") + .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; + event_builder.map(|i| i.set_response_body(&response)); + router_env::logger::info!(connector_response=?response); + + types::RouterData::try_from(types::ResponseRouterData { + response, + data: data.clone(), + http_code: res.status_code, + }) + .change_context(errors::ConnectorError::ResponseHandlingFailed) + } + + fn get_error_response( + &self, + res: Response, + event_builder: Option<&mut ConnectorEvent>, + ) -> CustomResult { + self.build_error_response(res, event_builder) + } } -impl api::PaymentSync for Bambora {} impl ConnectorIntegration for Bambora { @@ -304,10 +391,8 @@ impl ConnectorIntegration, res: Response, ) -> CustomResult { - let response: bambora::BamboraResponse = res + let response: bambora::BamboraPaymentsResponse = res .response .parse_struct("bambora PaymentsResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; @@ -348,19 +433,15 @@ impl ConnectorIntegration for Bambora { @@ -382,11 +463,9 @@ impl ConnectorIntegration CustomResult { Ok(format!( - "{}{}{}{}", + "{}/v1/payments/{}/completions", self.base_url(connectors), - "/v1/payments/", req.request.connector_transaction_id, - "/completions" )) } @@ -431,7 +510,7 @@ impl ConnectorIntegration, res: Response, ) -> CustomResult { - let response: bambora::BamboraResponse = res + let response: bambora::BamboraPaymentsResponse = res .response .parse_struct("Bambora PaymentsResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; @@ -439,14 +518,11 @@ impl ConnectorIntegration - for Bambora -{ - //TODO: implement sessions flow -} - -impl api::PaymentAuthorize for Bambora {} - -impl ConnectorIntegration +impl ConnectorIntegration for Bambora { fn get_headers( &self, - req: &types::PaymentsAuthorizeRouterData, + req: &types::PaymentsCancelRouterData, connectors: &settings::Connectors, ) -> CustomResult)>, errors::ConnectorError> { self.build_headers(req, connectors) @@ -486,72 +552,77 @@ impl ConnectorIntegration CustomResult { - Ok(format!("{}{}", self.base_url(connectors), "/v1/payments")) + let connector_payment_id = req.request.connector_transaction_id.clone(); + Ok(format!( + "{}/v1/payments/{}/void", + self.base_url(connectors), + connector_payment_id, + )) } fn get_request_body( &self, - req: &types::PaymentsAuthorizeRouterData, + req: &types::PaymentsCancelRouterData, _connectors: &settings::Connectors, ) -> CustomResult { let connector_router_data = bambora::BamboraRouterData::try_from(( &self.get_currency_unit(), - req.request.currency, - req.request.amount, + req.request + .currency + .ok_or(errors::ConnectorError::MissingRequiredField { + field_name: "Currency", + })?, + req.request + .amount + .ok_or(errors::ConnectorError::MissingRequiredField { + field_name: "Amount", + })?, req, ))?; - let connector_req = bambora::BamboraPaymentsRequest::try_from(connector_router_data)?; + let connector_req = bambora::BamboraVoidRequest::try_from(connector_router_data)?; Ok(RequestContent::Json(Box::new(connector_req))) } fn build_request( &self, - req: &types::PaymentsAuthorizeRouterData, + req: &types::PaymentsCancelRouterData, connectors: &settings::Connectors, ) -> CustomResult, errors::ConnectorError> { Ok(Some( services::RequestBuilder::new() .method(services::Method::Post) - .url(&types::PaymentsAuthorizeType::get_url( - self, req, connectors, - )?) + .url(&types::PaymentsVoidType::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, - )?) + .headers(types::PaymentsVoidType::get_headers(self, req, connectors)?) + .set_body(self.get_request_body(req, connectors)?) .build(), )) } fn handle_response( &self, - data: &types::PaymentsAuthorizeRouterData, + data: &types::PaymentsCancelRouterData, event_builder: Option<&mut ConnectorEvent>, res: Response, - ) -> CustomResult { - let response: bambora::BamboraResponse = res + ) -> CustomResult { + let response: bambora::BamboraPaymentsResponse = res .response - .parse_struct("PaymentIntentResponse") + .parse_struct("bambora PaymentsResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; + event_builder.map(|i| i.set_response_body(&response)); router_env::logger::info!(connector_response=?response); - types::RouterData::try_from(( - types::ResponseRouterData { - response, - data: data.clone(), - http_code: res.status_code, - }, - get_payment_flow(data.request.is_auto_capture()?), - )) + types::RouterData::try_from(types::ResponseRouterData { + response, + data: data.clone(), + http_code: res.status_code, + }) .change_context(errors::ConnectorError::ResponseHandlingFailed) } @@ -564,9 +635,22 @@ impl ConnectorIntegration, + action: services::PaymentAction, + ) -> CustomResult { + match action { + services::PaymentAction::PSync + | services::PaymentAction::CompleteAuthorize + | services::PaymentAction::PaymentAuthenticateCompleteAuthorize => { + Ok(payments::CallConnectorAction::Trigger) + } + } + } +} impl ConnectorIntegration for Bambora @@ -590,11 +674,9 @@ impl ConnectorIntegration CustomResult { let connector_payment_id = req.request.connector_transaction_id.clone(); Ok(format!( - "{}{}{}{}", + "{}/v1/payments/{}/returns", self.base_url(connectors), - "/v1/payments/", connector_payment_id, - "/returns" )) } @@ -684,9 +766,8 @@ impl ConnectorIntegration bambora::PaymentFlow { - if is_auto_capture { - bambora::PaymentFlow::Capture - } else { - bambora::PaymentFlow::Authorize - } -} - -impl services::ConnectorRedirectResponse for Bambora { - fn get_flow_type( - &self, - _query_params: &str, - _json_payload: Option, - action: services::PaymentAction, - ) -> CustomResult { - match action { - services::PaymentAction::PSync - | services::PaymentAction::CompleteAuthorize - | services::PaymentAction::PaymentAuthenticateCompleteAuthorize => { - Ok(payments::CallConnectorAction::Trigger) - } - } - } -} - -impl api::PaymentsCompleteAuthorize for Bambora {} - -impl - ConnectorIntegration< - api::CompleteAuthorize, - types::CompleteAuthorizeData, - types::PaymentsResponseData, - > for Bambora -{ - fn get_headers( - &self, - req: &types::PaymentsCompleteAuthorizeRouterData, - connectors: &settings::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: &types::PaymentsCompleteAuthorizeRouterData, - connectors: &settings::Connectors, - ) -> CustomResult { - let meta: bambora::BamboraMeta = to_connector_meta(req.request.connector_meta.clone())?; - Ok(format!( - "{}/v1/payments/{}{}", - self.base_url(connectors), - meta.three_d_session_data, - "/continue" - )) - } - - fn get_request_body( - &self, - req: &types::PaymentsCompleteAuthorizeRouterData, - _connectors: &settings::Connectors, - ) -> CustomResult { - let connector_req = bambora::BamboraThreedsContinueRequest::try_from(&req.request)?; - - Ok(RequestContent::Json(Box::new(connector_req))) - } - - fn build_request( - &self, - req: &types::PaymentsCompleteAuthorizeRouterData, - connectors: &settings::Connectors, - ) -> CustomResult, errors::ConnectorError> { - let request = services::RequestBuilder::new() - .method(services::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(); - Ok(Some(request)) - } - - fn handle_response( - &self, - data: &types::PaymentsCompleteAuthorizeRouterData, - event_builder: Option<&mut ConnectorEvent>, - res: Response, - ) -> CustomResult { - let response: bambora::BamboraResponse = res - .response - .parse_struct("Bambora PaymentsResponse") - .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; - event_builder.map(|i| i.set_response_body(&response)); - router_env::logger::info!(connector_response=?response); - - types::RouterData::try_from(( - types::ResponseRouterData { - response, - data: data.clone(), - http_code: res.status_code, - }, - bambora::PaymentFlow::Capture, - )) - .change_context(errors::ConnectorError::ResponseHandlingFailed) - } - - fn get_error_response( - &self, - res: Response, - event_builder: Option<&mut ConnectorEvent>, - ) -> CustomResult { - self.build_error_response(res, event_builder) - } -} diff --git a/crates/router/src/connector/bambora/transformers.rs b/crates/router/src/connector/bambora/transformers.rs index 77c91af709db..61ed8bd1ee47 100644 --- a/crates/router/src/connector/bambora/transformers.rs +++ b/crates/router/src/connector/bambora/transformers.rs @@ -7,7 +7,8 @@ use serde::{Deserialize, Deserializer, Serialize}; use crate::{ connector::utils::{ AddressDetailsData, BrowserInformationData, CardData as OtherCardData, - PaymentsAuthorizeRequestData, RouterData, + PaymentsAuthorizeRequestData, PaymentsCompleteAuthorizeRequestData, + PaymentsSyncRequestData, RouterData, }, consts, core::errors, @@ -135,16 +136,24 @@ impl TryFrom> for Bambora ) -> Result { match item.router_data.request.payment_method_data.clone() { domain::PaymentMethodData::Card(req_card) => { - let three_ds = match item.router_data.auth_type { - enums::AuthenticationType::ThreeDs => Some(ThreeDSecure { - enabled: true, - browser: get_browser_info(item.router_data)?, - version: Some(2), - auth_required: Some(true), - }), - enums::AuthenticationType::NoThreeDs => None, + let (three_ds, customer_ip) = match item.router_data.auth_type { + enums::AuthenticationType::ThreeDs => ( + Some(ThreeDSecure { + enabled: true, + browser: get_browser_info(item.router_data)?, + version: Some(2), + auth_required: Some(true), + }), + Some( + item.router_data + .request + .get_browser_info()? + .get_ip_address()?, + ), + ), + enums::AuthenticationType::NoThreeDs => (None, None), }; - let bambora_card = BamboraCard { + let card = BamboraCard { name: item.router_data.get_billing_address()?.get_full_name()?, expiry_year: req_card.get_card_expiry_year_2_digit()?, number: req_card.card_number, @@ -153,19 +162,31 @@ impl TryFrom> for Bambora three_d_secure: three_ds, complete: item.router_data.request.is_auto_capture()?, }; - let browser_info = item.router_data.request.get_browser_info()?; + Ok(Self { order_number: item.router_data.connector_request_reference_id.clone(), amount: item.amount, payment_method: PaymentMethod::Card, - card: bambora_card, - customer_ip: browser_info - .ip_address - .map(|ip_address| Secret::new(format!("{ip_address}"))), + card, + customer_ip, term_url: item.router_data.request.complete_authorize_url.clone(), }) } - _ => Err(errors::ConnectorError::NotImplemented("Payment methods".to_string()).into()), + domain::PaymentMethodData::CardRedirect(_) + | domain::PaymentMethodData::Wallet(_) + | domain::PaymentMethodData::PayLater(_) + | domain::PaymentMethodData::BankRedirect(_) + | domain::PaymentMethodData::BankDebit(_) + | domain::PaymentMethodData::BankTransfer(_) + | domain::PaymentMethodData::Crypto(_) + | domain::PaymentMethodData::MandatePayment + | domain::PaymentMethodData::Reward + | domain::PaymentMethodData::Upi(_) + | domain::PaymentMethodData::Voucher(_) + | domain::PaymentMethodData::GiftCard(_) + | domain::PaymentMethodData::CardToken(_) => { + Err(errors::ConnectorError::NotImplemented("Payment methods".to_string()).into()) + } } } } @@ -200,87 +221,6 @@ impl TryFrom<&types::ConnectorAuthType> for BamboraAuthType { } } -pub enum PaymentFlow { - Authorize, - Capture, - Void, -} - -// PaymentsResponse -impl - TryFrom<( - types::ResponseRouterData, - PaymentFlow, - )> for types::RouterData -{ - type Error = error_stack::Report; - fn try_from( - data: ( - types::ResponseRouterData, - PaymentFlow, - ), - ) -> Result { - let flow = data.1; - let item = data.0; - match item.response { - BamboraResponse::NormalTransaction(pg_response) => Ok(Self { - status: match pg_response.approved.as_str() { - "0" => match flow { - PaymentFlow::Authorize => enums::AttemptStatus::AuthorizationFailed, - PaymentFlow::Capture => enums::AttemptStatus::Failure, - PaymentFlow::Void => enums::AttemptStatus::VoidFailed, - }, - "1" => match flow { - PaymentFlow::Authorize => enums::AttemptStatus::Authorized, - PaymentFlow::Capture => enums::AttemptStatus::Charged, - PaymentFlow::Void => enums::AttemptStatus::Voided, - }, - &_ => Err(errors::ConnectorError::ResponseDeserializationFailed)?, - }, - response: Ok(types::PaymentsResponseData::TransactionResponse { - resource_id: types::ResponseId::ConnectorTransactionId( - pg_response.id.to_string(), - ), - redirection_data: None, - mandate_reference: None, - connector_metadata: None, - network_txn_id: None, - connector_response_reference_id: Some(pg_response.order_number.to_string()), - incremental_authorization_allowed: None, - }), - ..item.data - }), - - BamboraResponse::ThreeDsResponse(response) => { - let value = url::form_urlencoded::parse(response.contents.as_bytes()) - .map(|(key, val)| [key, val].concat()) - .collect(); - let redirection_data = Some(services::RedirectForm::Html { html_data: value }); - Ok(Self { - status: enums::AttemptStatus::AuthenticationPending, - response: Ok(types::PaymentsResponseData::TransactionResponse { - resource_id: types::ResponseId::NoResponseId, - redirection_data, - mandate_reference: None, - connector_metadata: Some( - serde_json::to_value(BamboraMeta { - three_d_session_data: response.three_d_session_data.expose(), - }) - .change_context(errors::ConnectorError::ResponseHandlingFailed)?, - ), - network_txn_id: None, - connector_response_reference_id: Some( - item.data.connector_request_reference_id.to_string(), - ), - incremental_authorization_allowed: None, - }), - ..item.data - }) - } - } - } -} - fn str_or_i32<'de, D>(deserializer: D) -> Result where D: Deserializer<'de>, @@ -444,7 +384,7 @@ pub enum PaymentMethod { // Capture #[derive(Default, Debug, Clone, Serialize, PartialEq)] pub struct BamboraPaymentsCaptureRequest { - amount: Option, + amount: f64, payment_method: PaymentMethod, } @@ -456,12 +396,269 @@ impl TryFrom> item: BamboraRouterData<&types::PaymentsCaptureRouterData>, ) -> Result { Ok(Self { - amount: Some(item.amount), + amount: item.amount, payment_method: PaymentMethod::Card, }) } } +impl + TryFrom< + types::ResponseRouterData< + F, + BamboraResponse, + types::PaymentsAuthorizeData, + types::PaymentsResponseData, + >, + > for types::RouterData +{ + type Error = error_stack::Report; + fn try_from( + item: types::ResponseRouterData< + F, + BamboraResponse, + types::PaymentsAuthorizeData, + types::PaymentsResponseData, + >, + ) -> Result { + match item.response { + BamboraResponse::NormalTransaction(pg_response) => Ok(Self { + status: if pg_response.approved.as_str() == "1" { + match item.data.request.is_auto_capture()? { + true => enums::AttemptStatus::Charged, + false => enums::AttemptStatus::Authorized, + } + } else { + match item.data.request.is_auto_capture()? { + true => enums::AttemptStatus::Failure, + false => enums::AttemptStatus::AuthorizationFailed, + } + }, + response: Ok(types::PaymentsResponseData::TransactionResponse { + resource_id: types::ResponseId::ConnectorTransactionId( + pg_response.id.to_string(), + ), + redirection_data: None, + mandate_reference: None, + connector_metadata: None, + network_txn_id: None, + connector_response_reference_id: Some(pg_response.order_number.to_string()), + incremental_authorization_allowed: None, + }), + ..item.data + }), + + BamboraResponse::ThreeDsResponse(response) => { + let value = url::form_urlencoded::parse(response.contents.as_bytes()) + .map(|(key, val)| [key, val].concat()) + .collect(); + let redirection_data = Some(services::RedirectForm::Html { html_data: value }); + Ok(Self { + status: enums::AttemptStatus::AuthenticationPending, + response: Ok(types::PaymentsResponseData::TransactionResponse { + resource_id: types::ResponseId::NoResponseId, + redirection_data, + mandate_reference: None, + connector_metadata: Some( + serde_json::to_value(BamboraMeta { + three_d_session_data: response.three_d_session_data.expose(), + }) + .change_context(errors::ConnectorError::ResponseHandlingFailed)?, + ), + network_txn_id: None, + connector_response_reference_id: Some( + item.data.connector_request_reference_id.to_string(), + ), + incremental_authorization_allowed: None, + }), + ..item.data + }) + } + } + } +} + +impl + TryFrom< + types::ResponseRouterData< + F, + BamboraPaymentsResponse, + types::CompleteAuthorizeData, + types::PaymentsResponseData, + >, + > for types::RouterData +{ + type Error = error_stack::Report; + fn try_from( + item: types::ResponseRouterData< + F, + BamboraPaymentsResponse, + types::CompleteAuthorizeData, + types::PaymentsResponseData, + >, + ) -> Result { + Ok(Self { + status: if item.response.approved.as_str() == "1" { + match item.data.request.is_auto_capture()? { + true => enums::AttemptStatus::Charged, + false => enums::AttemptStatus::Authorized, + } + } else { + match item.data.request.is_auto_capture()? { + true => enums::AttemptStatus::Failure, + false => enums::AttemptStatus::AuthorizationFailed, + } + }, + response: Ok(types::PaymentsResponseData::TransactionResponse { + resource_id: types::ResponseId::ConnectorTransactionId( + item.response.id.to_string(), + ), + redirection_data: None, + mandate_reference: None, + connector_metadata: None, + network_txn_id: None, + connector_response_reference_id: Some(item.response.order_number.to_string()), + incremental_authorization_allowed: None, + }), + ..item.data + }) + } +} + +impl + TryFrom< + types::ResponseRouterData< + F, + BamboraPaymentsResponse, + types::PaymentsSyncData, + types::PaymentsResponseData, + >, + > for types::RouterData +{ + type Error = error_stack::Report; + fn try_from( + item: types::ResponseRouterData< + F, + BamboraPaymentsResponse, + types::PaymentsSyncData, + types::PaymentsResponseData, + >, + ) -> Result { + Ok(Self { + status: match item.data.request.is_auto_capture()? { + true => { + if item.response.approved.as_str() == "1" { + enums::AttemptStatus::Charged + } else { + enums::AttemptStatus::Failure + } + } + false => { + if item.response.approved.as_str() == "1" { + enums::AttemptStatus::Authorized + } else { + enums::AttemptStatus::AuthorizationFailed + } + } + }, + response: Ok(types::PaymentsResponseData::TransactionResponse { + resource_id: types::ResponseId::ConnectorTransactionId( + item.response.id.to_string(), + ), + redirection_data: None, + mandate_reference: None, + connector_metadata: None, + network_txn_id: None, + connector_response_reference_id: Some(item.response.order_number.to_string()), + incremental_authorization_allowed: None, + }), + ..item.data + }) + } +} + +impl + TryFrom< + types::ResponseRouterData< + F, + BamboraPaymentsResponse, + types::PaymentsCaptureData, + types::PaymentsResponseData, + >, + > for types::RouterData +{ + type Error = error_stack::Report; + fn try_from( + item: types::ResponseRouterData< + F, + BamboraPaymentsResponse, + types::PaymentsCaptureData, + types::PaymentsResponseData, + >, + ) -> Result { + Ok(Self { + status: if item.response.approved.as_str() == "1" { + enums::AttemptStatus::Charged + } else { + enums::AttemptStatus::Failure + }, + response: Ok(types::PaymentsResponseData::TransactionResponse { + resource_id: types::ResponseId::ConnectorTransactionId( + item.response.id.to_string(), + ), + redirection_data: None, + mandate_reference: None, + connector_metadata: None, + network_txn_id: None, + connector_response_reference_id: Some(item.response.order_number.to_string()), + incremental_authorization_allowed: None, + }), + ..item.data + }) + } +} + +impl + TryFrom< + types::ResponseRouterData< + F, + BamboraPaymentsResponse, + types::PaymentsCancelData, + types::PaymentsResponseData, + >, + > for types::RouterData +{ + type Error = error_stack::Report; + fn try_from( + item: types::ResponseRouterData< + F, + BamboraPaymentsResponse, + types::PaymentsCancelData, + types::PaymentsResponseData, + >, + ) -> Result { + Ok(Self { + status: if item.response.approved.as_str() == "1" { + enums::AttemptStatus::Voided + } else { + enums::AttemptStatus::VoidFailed + }, + response: Ok(types::PaymentsResponseData::TransactionResponse { + resource_id: types::ResponseId::ConnectorTransactionId( + item.response.id.to_string(), + ), + redirection_data: None, + mandate_reference: None, + connector_metadata: None, + network_txn_id: None, + connector_response_reference_id: Some(item.response.order_number.to_string()), + incremental_authorization_allowed: None, + }), + ..item.data + }) + } +} + // REFUND : // Type definition for RefundRequest #[derive(Default, Debug, Serialize)] @@ -537,10 +734,10 @@ impl TryFrom> fn try_from( item: types::RefundsResponseRouterData, ) -> Result { - let refund_status = match item.response.approved.as_str() { - "0" => enums::RefundStatus::Failure, - "1" => enums::RefundStatus::Success, - &_ => Err(errors::ConnectorError::ResponseDeserializationFailed)?, + let refund_status = if item.response.approved.as_str() == "1" { + enums::RefundStatus::Success + } else { + enums::RefundStatus::Failure }; Ok(Self { response: Ok(types::RefundsResponseData { @@ -559,10 +756,10 @@ impl TryFrom> fn try_from( item: types::RefundsResponseRouterData, ) -> Result { - let refund_status = match item.response.approved.as_str() { - "0" => enums::RefundStatus::Failure, - "1" => enums::RefundStatus::Success, - &_ => Err(errors::ConnectorError::ResponseDeserializationFailed)?, + let refund_status = if item.response.approved.as_str() == "1" { + enums::RefundStatus::Success + } else { + enums::RefundStatus::Failure }; Ok(Self { response: Ok(types::RefundsResponseData {