mirror of
				https://github.com/juspay/hyperswitch.git
				synced 2025-10-31 18:17:13 +08:00 
			
		
		
		
	feat(connector): [Bambora APAC] add mandate flow (#5376)
This commit is contained in:
		| @ -186,7 +186,7 @@ airwallex.base_url = "https://api-demo.airwallex.com/" | |||||||
| applepay.base_url = "https://apple-pay-gateway.apple.com/" | applepay.base_url = "https://apple-pay-gateway.apple.com/" | ||||||
| authorizedotnet.base_url = "https://apitest.authorize.net/xml/v1/request.api" | authorizedotnet.base_url = "https://apitest.authorize.net/xml/v1/request.api" | ||||||
| bambora.base_url = "https://api.na.bambora.com" | bambora.base_url = "https://api.na.bambora.com" | ||||||
| bamboraapac.base_url = "https://demo.bambora.co.nz/interface/api/dts.asmx" | bamboraapac.base_url = "https://demo.ippayments.com.au/interface/api" | ||||||
| bankofamerica.base_url = "https://apitest.merchant-services.bankofamerica.com/" | bankofamerica.base_url = "https://apitest.merchant-services.bankofamerica.com/" | ||||||
| billwerk.base_url = "https://api.reepay.com/" | billwerk.base_url = "https://api.reepay.com/" | ||||||
| billwerk.secondary_base_url = "https://card.reepay.com/" | billwerk.secondary_base_url = "https://card.reepay.com/" | ||||||
|  | |||||||
| @ -26,7 +26,7 @@ airwallex.base_url = "https://api-demo.airwallex.com/" | |||||||
| applepay.base_url = "https://apple-pay-gateway.apple.com/" | applepay.base_url = "https://apple-pay-gateway.apple.com/" | ||||||
| authorizedotnet.base_url = "https://apitest.authorize.net/xml/v1/request.api" | authorizedotnet.base_url = "https://apitest.authorize.net/xml/v1/request.api" | ||||||
| bambora.base_url = "https://api.na.bambora.com" | bambora.base_url = "https://api.na.bambora.com" | ||||||
| bamboraapac.base_url = "https://demo.ippayments.com.au/interface/api/dts.asmx" | bamboraapac.base_url = "https://demo.ippayments.com.au/interface/api" | ||||||
| bankofamerica.base_url = "https://apitest.merchant-services.bankofamerica.com/" | bankofamerica.base_url = "https://apitest.merchant-services.bankofamerica.com/" | ||||||
| billwerk.base_url = "https://api.reepay.com/" | billwerk.base_url = "https://api.reepay.com/" | ||||||
| billwerk.secondary_base_url = "https://card.reepay.com/" | billwerk.secondary_base_url = "https://card.reepay.com/" | ||||||
|  | |||||||
| @ -30,7 +30,7 @@ airwallex.base_url = "https://api-demo.airwallex.com/" | |||||||
| applepay.base_url = "https://apple-pay-gateway.apple.com/" | applepay.base_url = "https://apple-pay-gateway.apple.com/" | ||||||
| authorizedotnet.base_url = "https://apitest.authorize.net/xml/v1/request.api" | authorizedotnet.base_url = "https://apitest.authorize.net/xml/v1/request.api" | ||||||
| bambora.base_url = "https://api.na.bambora.com" | bambora.base_url = "https://api.na.bambora.com" | ||||||
| bamboraapac.base_url = "https://demo.ippayments.com.au/interface/api/dts.asmx" | bamboraapac.base_url = "https://demo.ippayments.com.au/interface/api" | ||||||
| bankofamerica.base_url = "https://apitest.merchant-services.bankofamerica.com/" | bankofamerica.base_url = "https://apitest.merchant-services.bankofamerica.com/" | ||||||
| billwerk.base_url = "https://api.reepay.com/" | billwerk.base_url = "https://api.reepay.com/" | ||||||
| billwerk.secondary_base_url = "https://card.reepay.com/" | billwerk.secondary_base_url = "https://card.reepay.com/" | ||||||
|  | |||||||
| @ -182,7 +182,7 @@ airwallex.base_url = "https://api-demo.airwallex.com/" | |||||||
| applepay.base_url = "https://apple-pay-gateway.apple.com/" | applepay.base_url = "https://apple-pay-gateway.apple.com/" | ||||||
| authorizedotnet.base_url = "https://apitest.authorize.net/xml/v1/request.api" | authorizedotnet.base_url = "https://apitest.authorize.net/xml/v1/request.api" | ||||||
| bambora.base_url = "https://api.na.bambora.com" | bambora.base_url = "https://api.na.bambora.com" | ||||||
| bamboraapac.base_url = "https://demo.ippayments.com.au/interface/api/dts.asmx" | bamboraapac.base_url = "https://demo.ippayments.com.au/interface/api" | ||||||
| bankofamerica.base_url = "https://apitest.merchant-services.bankofamerica.com/" | bankofamerica.base_url = "https://apitest.merchant-services.bankofamerica.com/" | ||||||
| billwerk.base_url = "https://api.reepay.com/" | billwerk.base_url = "https://api.reepay.com/" | ||||||
| billwerk.secondary_base_url = "https://card.reepay.com/" | billwerk.secondary_base_url = "https://card.reepay.com/" | ||||||
|  | |||||||
| @ -115,7 +115,7 @@ airwallex.base_url = "https://api-demo.airwallex.com/" | |||||||
| applepay.base_url = "https://apple-pay-gateway.apple.com/" | applepay.base_url = "https://apple-pay-gateway.apple.com/" | ||||||
| authorizedotnet.base_url = "https://apitest.authorize.net/xml/v1/request.api" | authorizedotnet.base_url = "https://apitest.authorize.net/xml/v1/request.api" | ||||||
| bambora.base_url = "https://api.na.bambora.com" | bambora.base_url = "https://api.na.bambora.com" | ||||||
| bamboraapac.base_url = "https://demo.bambora.co.nz/interface/api/dts.asmx" | bamboraapac.base_url = "https://demo.ippayments.com.au/interface/api" | ||||||
| bankofamerica.base_url = "https://apitest.merchant-services.bankofamerica.com/" | bankofamerica.base_url = "https://apitest.merchant-services.bankofamerica.com/" | ||||||
| billwerk.base_url = "https://api.reepay.com/" | billwerk.base_url = "https://api.reepay.com/" | ||||||
| billwerk.secondary_base_url = "https://card.reepay.com/" | billwerk.secondary_base_url = "https://card.reepay.com/" | ||||||
|  | |||||||
| @ -92,6 +92,22 @@ impl ConnectorValidation for Bamboraapac { | |||||||
|             ), |             ), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     fn validate_mandate_payment( | ||||||
|  |         &self, | ||||||
|  |         _pm_type: Option<enums::PaymentMethodType>, | ||||||
|  |         pm_data: types::domain::payments::PaymentMethodData, | ||||||
|  |     ) -> CustomResult<(), errors::ConnectorError> { | ||||||
|  |         let connector = self.id(); | ||||||
|  |         match pm_data { | ||||||
|  |             types::domain::payments::PaymentMethodData::Card(_) => Ok(()), | ||||||
|  |             _ => Err(errors::ConnectorError::NotSupported { | ||||||
|  |                 message: "mandate payment".to_string(), | ||||||
|  |                 connector, | ||||||
|  |             } | ||||||
|  |             .into()), | ||||||
|  |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| impl ConnectorCommon for Bamboraapac { | impl ConnectorCommon for Bamboraapac { | ||||||
| @ -167,6 +183,85 @@ impl | |||||||
|         types::PaymentsResponseData, |         types::PaymentsResponseData, | ||||||
|     > for Bamboraapac |     > for Bamboraapac | ||||||
| { | { | ||||||
|  |     fn get_headers( | ||||||
|  |         &self, | ||||||
|  |         req: &types::SetupMandateRouterData, | ||||||
|  |         connectors: &settings::Connectors, | ||||||
|  |     ) -> CustomResult<Vec<(String, request::Maskable<String>)>, 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::SetupMandateRouterData, | ||||||
|  |         connectors: &settings::Connectors, | ||||||
|  |     ) -> CustomResult<String, errors::ConnectorError> { | ||||||
|  |         Ok(format!("{}/sipp.asmx", self.base_url(connectors))) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fn get_request_body( | ||||||
|  |         &self, | ||||||
|  |         req: &types::SetupMandateRouterData, | ||||||
|  |         _connectors: &settings::Connectors, | ||||||
|  |     ) -> CustomResult<RequestContent, errors::ConnectorError> { | ||||||
|  |         let connector_req = bamboraapac::get_setup_mandate_body(req)?; | ||||||
|  |  | ||||||
|  |         Ok(RequestContent::RawBytes(connector_req)) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fn build_request( | ||||||
|  |         &self, | ||||||
|  |         req: &types::SetupMandateRouterData, | ||||||
|  |         connectors: &settings::Connectors, | ||||||
|  |     ) -> CustomResult<Option<services::Request>, errors::ConnectorError> { | ||||||
|  |         Ok(Some( | ||||||
|  |             services::RequestBuilder::new() | ||||||
|  |                 .method(services::Method::Post) | ||||||
|  |                 .url(&types::SetupMandateType::get_url(self, req, connectors)?) | ||||||
|  |                 .attach_default_headers() | ||||||
|  |                 .headers(types::SetupMandateType::get_headers(self, req, connectors)?) | ||||||
|  |                 .set_body(types::SetupMandateType::get_request_body( | ||||||
|  |                     self, req, connectors, | ||||||
|  |                 )?) | ||||||
|  |                 .build(), | ||||||
|  |         )) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fn handle_response( | ||||||
|  |         &self, | ||||||
|  |         data: &types::SetupMandateRouterData, | ||||||
|  |         event_builder: Option<&mut ConnectorEvent>, | ||||||
|  |         res: Response, | ||||||
|  |     ) -> CustomResult<types::SetupMandateRouterData, errors::ConnectorError> { | ||||||
|  |         let response_data = html_to_xml_string_conversion( | ||||||
|  |             String::from_utf8(res.response.to_vec()) | ||||||
|  |                 .change_context(errors::ConnectorError::ResponseDeserializationFailed)?, | ||||||
|  |         ); | ||||||
|  |  | ||||||
|  |         let response = response_data | ||||||
|  |             .parse_xml::<bamboraapac::BamboraapacMandateResponse>() | ||||||
|  |             .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, | ||||||
|  |         }) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fn get_error_response( | ||||||
|  |         &self, | ||||||
|  |         res: Response, | ||||||
|  |         event_builder: Option<&mut ConnectorEvent>, | ||||||
|  |     ) -> CustomResult<ErrorResponse, errors::ConnectorError> { | ||||||
|  |         self.build_error_response(res, event_builder) | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::PaymentsResponseData> | impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::PaymentsResponseData> | ||||||
| @ -189,7 +284,7 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P | |||||||
|         _req: &types::PaymentsAuthorizeRouterData, |         _req: &types::PaymentsAuthorizeRouterData, | ||||||
|         connectors: &settings::Connectors, |         connectors: &settings::Connectors, | ||||||
|     ) -> CustomResult<String, errors::ConnectorError> { |     ) -> CustomResult<String, errors::ConnectorError> { | ||||||
|         Ok(self.base_url(connectors).to_string()) |         Ok(format!("{}/dts.asmx", self.base_url(connectors))) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn get_request_body( |     fn get_request_body( | ||||||
| @ -284,7 +379,7 @@ impl ConnectorIntegration<api::PSync, types::PaymentsSyncData, types::PaymentsRe | |||||||
|         _req: &types::PaymentsSyncRouterData, |         _req: &types::PaymentsSyncRouterData, | ||||||
|         connectors: &settings::Connectors, |         connectors: &settings::Connectors, | ||||||
|     ) -> CustomResult<String, errors::ConnectorError> { |     ) -> CustomResult<String, errors::ConnectorError> { | ||||||
|         Ok(self.base_url(connectors).to_string()) |         Ok(format!("{}/dts.asmx", self.base_url(connectors))) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn get_request_body( |     fn get_request_body( | ||||||
| @ -368,7 +463,7 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme | |||||||
|         _req: &types::PaymentsCaptureRouterData, |         _req: &types::PaymentsCaptureRouterData, | ||||||
|         connectors: &settings::Connectors, |         connectors: &settings::Connectors, | ||||||
|     ) -> CustomResult<String, errors::ConnectorError> { |     ) -> CustomResult<String, errors::ConnectorError> { | ||||||
|         Ok(self.base_url(connectors).to_string()) |         Ok(format!("{}/dts.asmx", self.base_url(connectors))) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn get_request_body( |     fn get_request_body( | ||||||
| @ -467,7 +562,7 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon | |||||||
|         _req: &types::RefundExecuteRouterData, |         _req: &types::RefundExecuteRouterData, | ||||||
|         connectors: &settings::Connectors, |         connectors: &settings::Connectors, | ||||||
|     ) -> CustomResult<String, errors::ConnectorError> { |     ) -> CustomResult<String, errors::ConnectorError> { | ||||||
|         Ok(self.base_url(connectors).to_string()) |         Ok(format!("{}/dts.asmx", self.base_url(connectors))) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn get_request_body( |     fn get_request_body( | ||||||
| @ -560,7 +655,7 @@ impl ConnectorIntegration<api::RSync, types::RefundsData, types::RefundsResponse | |||||||
|         _req: &types::RefundSyncRouterData, |         _req: &types::RefundSyncRouterData, | ||||||
|         connectors: &settings::Connectors, |         connectors: &settings::Connectors, | ||||||
|     ) -> CustomResult<String, errors::ConnectorError> { |     ) -> CustomResult<String, errors::ConnectorError> { | ||||||
|         Ok(self.base_url(connectors).to_string()) |         Ok(format!("{}/dts.asmx", self.base_url(connectors))) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn get_request_body( |     fn get_request_body( | ||||||
|  | |||||||
| @ -5,7 +5,7 @@ use masking::{PeekInterface, Secret}; | |||||||
| use serde::{Deserialize, Serialize}; | use serde::{Deserialize, Serialize}; | ||||||
|  |  | ||||||
| use crate::{ | use crate::{ | ||||||
|     connector::utils::{self, CardData, RouterData}, |     connector::utils::{self, CardData, PaymentsAuthorizeRequestData, RouterData}, | ||||||
|     core::errors, |     core::errors, | ||||||
|     types::{self, domain, storage::enums, transformers::ForeignFrom}, |     types::{self, domain, storage::enums, transformers::ForeignFrom}, | ||||||
| }; | }; | ||||||
| @ -94,6 +94,25 @@ fn get_card_data(req: &types::PaymentsAuthorizeRouterData) -> Result<String, Err | |||||||
|     let card_holder_name = req.get_billing_full_name()?; |     let card_holder_name = req.get_billing_full_name()?; | ||||||
|     let card_data = match &req.request.payment_method_data { |     let card_data = match &req.request.payment_method_data { | ||||||
|         domain::PaymentMethodData::Card(card) => { |         domain::PaymentMethodData::Card(card) => { | ||||||
|  |             if req.request.setup_future_usage == Some(enums::FutureUsage::OffSession) { | ||||||
|  |                 format!( | ||||||
|  |                     r#" | ||||||
|  |                     <CreditCard Registered="False"> | ||||||
|  |                         <TokeniseAlgorithmID>2</TokeniseAlgorithmID> | ||||||
|  |                         <CardNumber>{}</CardNumber> | ||||||
|  |                         <ExpM>{}</ExpM> | ||||||
|  |                         <ExpY>{}</ExpY> | ||||||
|  |                         <CVN>{}</CVN> | ||||||
|  |                         <CardHolderName>{}</CardHolderName> | ||||||
|  |                     </CreditCard> | ||||||
|  |                 "#, | ||||||
|  |                     card.card_number.get_card_no(), | ||||||
|  |                     card.card_exp_month.peek(), | ||||||
|  |                     card.get_expiry_year_4_digit().peek(), | ||||||
|  |                     card.card_cvc.peek(), | ||||||
|  |                     card_holder_name.peek(), | ||||||
|  |                 ) | ||||||
|  |             } else { | ||||||
|                 format!( |                 format!( | ||||||
|                     r#" |                     r#" | ||||||
|                     <CreditCard Registered="False"> |                     <CreditCard Registered="False"> | ||||||
| @ -111,6 +130,18 @@ fn get_card_data(req: &types::PaymentsAuthorizeRouterData) -> Result<String, Err | |||||||
|                     card_holder_name.peek(), |                     card_holder_name.peek(), | ||||||
|                 ) |                 ) | ||||||
|             } |             } | ||||||
|  |         } | ||||||
|  |         domain::PaymentMethodData::MandatePayment => { | ||||||
|  |             format!( | ||||||
|  |                 r#" | ||||||
|  |                 <CreditCard> | ||||||
|  |                 <TokeniseAlgorithmID>2</TokeniseAlgorithmID> | ||||||
|  |                 <CardNumber>{}</CardNumber> | ||||||
|  |                 </CreditCard> | ||||||
|  |             "#, | ||||||
|  |                 req.request.get_connector_mandate_id()? | ||||||
|  |             ) | ||||||
|  |         } | ||||||
|         _ => { |         _ => { | ||||||
|             return Err(errors::ConnectorError::NotImplemented( |             return Err(errors::ConnectorError::NotImplemented( | ||||||
|                 utils::get_unimplemented_payment_method_error_message("Bambora APAC"), |                 utils::get_unimplemented_payment_method_error_message("Bambora APAC"), | ||||||
| @ -182,6 +213,7 @@ pub struct SubmitSinglePaymentResult { | |||||||
| pub struct PaymentResponse { | pub struct PaymentResponse { | ||||||
|     response_code: u8, |     response_code: u8, | ||||||
|     receipt: String, |     receipt: String, | ||||||
|  |     credit_card_token: Option<String>, | ||||||
|     declined_code: Option<String>, |     declined_code: Option<String>, | ||||||
|     declined_message: Option<String>, |     declined_message: Option<String>, | ||||||
| } | } | ||||||
| @ -234,6 +266,23 @@ impl<F> | |||||||
|             .submit_single_payment_result |             .submit_single_payment_result | ||||||
|             .response |             .response | ||||||
|             .receipt; |             .receipt; | ||||||
|  |  | ||||||
|  |         let mandate_reference = | ||||||
|  |             if item.data.request.setup_future_usage == Some(enums::FutureUsage::OffSession) { | ||||||
|  |                 let connector_mandate_id = item | ||||||
|  |                     .response | ||||||
|  |                     .body | ||||||
|  |                     .submit_single_payment_response | ||||||
|  |                     .submit_single_payment_result | ||||||
|  |                     .response | ||||||
|  |                     .credit_card_token; | ||||||
|  |                 Some(types::MandateReference { | ||||||
|  |                     connector_mandate_id, | ||||||
|  |                     payment_method_id: None, | ||||||
|  |                 }) | ||||||
|  |             } else { | ||||||
|  |                 None | ||||||
|  |             }; | ||||||
|         // transaction approved |         // transaction approved | ||||||
|         if response_code == 0 { |         if response_code == 0 { | ||||||
|             Ok(Self { |             Ok(Self { | ||||||
| @ -243,7 +292,7 @@ impl<F> | |||||||
|                         connector_transaction_id.to_owned(), |                         connector_transaction_id.to_owned(), | ||||||
|                     ), |                     ), | ||||||
|                     redirection_data: None, |                     redirection_data: None, | ||||||
|                     mandate_reference: None, |                     mandate_reference, | ||||||
|                     connector_metadata: None, |                     connector_metadata: None, | ||||||
|                     network_txn_id: None, |                     network_txn_id: None, | ||||||
|                     connector_response_reference_id: Some(connector_transaction_id), |                     connector_response_reference_id: Some(connector_transaction_id), | ||||||
| @ -288,6 +337,159 @@ impl<F> | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | pub fn get_setup_mandate_body(req: &types::SetupMandateRouterData) -> Result<Vec<u8>, Error> { | ||||||
|  |     let card_holder_name = req.get_billing_full_name()?; | ||||||
|  |     let auth_details = BamboraapacAuthType::try_from(&req.connector_auth_type)?; | ||||||
|  |     let body = match &req.request.payment_method_data { | ||||||
|  |         domain::PaymentMethodData::Card(card) => { | ||||||
|  |             format!( | ||||||
|  |                 r#" | ||||||
|  |                 <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" | ||||||
|  |                 xmlns:sipp="http://www.ippayments.com.au/interface/api/sipp"> | ||||||
|  |                 <soapenv:Header/> | ||||||
|  |                 <soapenv:Body> | ||||||
|  |                     <sipp:TokeniseCreditCard> | ||||||
|  |                         <sipp:tokeniseCreditCardXML> | ||||||
|  |                             <![CDATA[ | ||||||
|  |                                 <TokeniseCreditCard> | ||||||
|  |                                     <CardNumber>{}</CardNumber>  | ||||||
|  |                                     <ExpM>{}</ExpM> | ||||||
|  |                                     <ExpY>{}</ExpY> | ||||||
|  |                                     <CardHolderName>{}</CardHolderName> | ||||||
|  |                                     <TokeniseAlgorithmID>2</TokeniseAlgorithmID> | ||||||
|  |                                     <UserName>{}</UserName>  | ||||||
|  |                                     <Password>{}</Password> | ||||||
|  |                                 </TokeniseCreditCard> | ||||||
|  |                             ]]> | ||||||
|  |                         </sipp:tokeniseCreditCardXML> | ||||||
|  |                     </sipp:TokeniseCreditCard> | ||||||
|  |                 </soapenv:Body> | ||||||
|  |                 </soapenv:Envelope> | ||||||
|  |                 "#, | ||||||
|  |                 card.card_number.get_card_no(), | ||||||
|  |                 card.card_exp_month.peek(), | ||||||
|  |                 card.get_expiry_year_4_digit().peek(), | ||||||
|  |                 card_holder_name.peek(), | ||||||
|  |                 auth_details.username.peek(), | ||||||
|  |                 auth_details.password.peek(), | ||||||
|  |             ) | ||||||
|  |         } | ||||||
|  |         _ => { | ||||||
|  |             return Err(errors::ConnectorError::NotImplemented( | ||||||
|  |                 utils::get_unimplemented_payment_method_error_message("Bambora APAC"), | ||||||
|  |             ))?; | ||||||
|  |         } | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     Ok(body.as_bytes().to_vec()) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #[derive(Debug, Clone, Serialize, Deserialize)] | ||||||
|  | #[serde(rename = "Envelope")] | ||||||
|  | #[serde(rename_all = "PascalCase")] | ||||||
|  | pub struct BamboraapacMandateResponse { | ||||||
|  |     body: MandateBodyResponse, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #[derive(Debug, Clone, Serialize, Deserialize)] | ||||||
|  | #[serde(rename_all = "PascalCase")] | ||||||
|  | pub struct MandateBodyResponse { | ||||||
|  |     tokenise_credit_card_response: TokeniseCreditCardResponse, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #[derive(Debug, Clone, Serialize, Deserialize)] | ||||||
|  | #[serde(rename_all = "PascalCase")] | ||||||
|  | pub struct TokeniseCreditCardResponse { | ||||||
|  |     tokenise_credit_card_result: TokeniseCreditCardResult, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #[derive(Debug, Clone, Serialize, Deserialize)] | ||||||
|  | #[serde(rename_all = "PascalCase")] | ||||||
|  | pub struct TokeniseCreditCardResult { | ||||||
|  |     tokenise_credit_card_response: MandateResponseBody, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #[derive(Debug, Clone, Serialize, Deserialize)] | ||||||
|  | #[serde(rename_all = "PascalCase")] | ||||||
|  | pub struct MandateResponseBody { | ||||||
|  |     return_value: u8, | ||||||
|  |     token: Option<String>, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | impl<F> | ||||||
|  |     TryFrom< | ||||||
|  |         types::ResponseRouterData< | ||||||
|  |             F, | ||||||
|  |             BamboraapacMandateResponse, | ||||||
|  |             types::SetupMandateRequestData, | ||||||
|  |             types::PaymentsResponseData, | ||||||
|  |         >, | ||||||
|  |     > for types::RouterData<F, types::SetupMandateRequestData, types::PaymentsResponseData> | ||||||
|  | { | ||||||
|  |     type Error = error_stack::Report<errors::ConnectorError>; | ||||||
|  |     fn try_from( | ||||||
|  |         item: types::ResponseRouterData< | ||||||
|  |             F, | ||||||
|  |             BamboraapacMandateResponse, | ||||||
|  |             types::SetupMandateRequestData, | ||||||
|  |             types::PaymentsResponseData, | ||||||
|  |         >, | ||||||
|  |     ) -> Result<Self, Self::Error> { | ||||||
|  |         let response_code = item | ||||||
|  |             .response | ||||||
|  |             .body | ||||||
|  |             .tokenise_credit_card_response | ||||||
|  |             .tokenise_credit_card_result | ||||||
|  |             .tokenise_credit_card_response | ||||||
|  |             .return_value; | ||||||
|  |  | ||||||
|  |         let connector_mandate_id = item | ||||||
|  |             .response | ||||||
|  |             .body | ||||||
|  |             .tokenise_credit_card_response | ||||||
|  |             .tokenise_credit_card_result | ||||||
|  |             .tokenise_credit_card_response | ||||||
|  |             .token | ||||||
|  |             .ok_or(errors::ConnectorError::MissingConnectorMandateID)?; | ||||||
|  |  | ||||||
|  |         // transaction approved | ||||||
|  |         if response_code == 0 { | ||||||
|  |             Ok(Self { | ||||||
|  |                 status: enums::AttemptStatus::Charged, | ||||||
|  |                 response: Ok(types::PaymentsResponseData::TransactionResponse { | ||||||
|  |                     resource_id: types::ResponseId::NoResponseId, | ||||||
|  |                     redirection_data: None, | ||||||
|  |                     mandate_reference: Some(types::MandateReference { | ||||||
|  |                         connector_mandate_id: Some(connector_mandate_id), | ||||||
|  |                         payment_method_id: None, | ||||||
|  |                     }), | ||||||
|  |                     connector_metadata: None, | ||||||
|  |                     network_txn_id: None, | ||||||
|  |                     connector_response_reference_id: None, | ||||||
|  |                     incremental_authorization_allowed: None, | ||||||
|  |                     charge_id: None, | ||||||
|  |                 }), | ||||||
|  |                 ..item.data | ||||||
|  |             }) | ||||||
|  |         } | ||||||
|  |         // transaction failed | ||||||
|  |         else { | ||||||
|  |             Ok(Self { | ||||||
|  |                 status: enums::AttemptStatus::Failure, | ||||||
|  |                 response: Err(types::ErrorResponse { | ||||||
|  |                     status_code: item.http_code, | ||||||
|  |                     code: consts::NO_ERROR_CODE.to_string(), | ||||||
|  |                     message: consts::NO_ERROR_MESSAGE.to_string(), | ||||||
|  |                     reason: None, | ||||||
|  |                     attempt_status: None, | ||||||
|  |                     connector_transaction_id: None, | ||||||
|  |                 }), | ||||||
|  |                 ..item.data | ||||||
|  |             }) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| // capture body in soap format | // capture body in soap format | ||||||
| pub fn get_capture_body( | pub fn get_capture_body( | ||||||
|     req: &BamboraapacRouterData<&types::PaymentsCaptureRouterData>, |     req: &BamboraapacRouterData<&types::PaymentsCaptureRouterData>, | ||||||
|  | |||||||
| @ -80,7 +80,7 @@ airwallex.base_url = "https://api-demo.airwallex.com/" | |||||||
| applepay.base_url = "https://apple-pay-gateway.apple.com/" | applepay.base_url = "https://apple-pay-gateway.apple.com/" | ||||||
| authorizedotnet.base_url = "https://apitest.authorize.net/xml/v1/request.api" | authorizedotnet.base_url = "https://apitest.authorize.net/xml/v1/request.api" | ||||||
| bambora.base_url = "https://api.na.bambora.com" | bambora.base_url = "https://api.na.bambora.com" | ||||||
| bamboraapac.base_url = "https://demo.ippayments.com.au/interface/api/dts.asmx" | bamboraapac.base_url = "https://demo.ippayments.com.au/interface/api" | ||||||
| bankofamerica.base_url = "https://apitest.merchant-services.bankofamerica.com/" | bankofamerica.base_url = "https://apitest.merchant-services.bankofamerica.com/" | ||||||
| billwerk.base_url = "https://api.reepay.com/" | billwerk.base_url = "https://api.reepay.com/" | ||||||
| billwerk.secondary_base_url = "https://card.reepay.com/" | billwerk.secondary_base_url = "https://card.reepay.com/" | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 Sakil Mostak
					Sakil Mostak