mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-11-01 11:06:50 +08:00
fix(connector): [BANKOFAMERICA] Remove cards 3ds flow (#5294)
This commit is contained in:
@ -12,7 +12,6 @@ use time::OffsetDateTime;
|
||||
use transformers as bankofamerica;
|
||||
use url::Url;
|
||||
|
||||
use super::utils::{PaymentsAuthorizeRequestData, PaymentsSetupMandateRequestData, RouterData};
|
||||
use crate::{
|
||||
configs::settings,
|
||||
connector::{
|
||||
@ -53,8 +52,6 @@ impl api::Refund for Bankofamerica {}
|
||||
impl api::RefundExecute for Bankofamerica {}
|
||||
impl api::RefundSync for Bankofamerica {}
|
||||
impl api::PaymentToken for Bankofamerica {}
|
||||
impl api::PaymentsPreProcessing for Bankofamerica {}
|
||||
impl api::PaymentsCompleteAuthorize for Bankofamerica {}
|
||||
|
||||
impl Bankofamerica {
|
||||
pub fn generate_digest(&self, payload: &[u8]) -> String {
|
||||
@ -339,33 +336,18 @@ impl
|
||||
}
|
||||
fn get_url(
|
||||
&self,
|
||||
req: &types::SetupMandateRouterData,
|
||||
_req: &types::SetupMandateRouterData,
|
||||
connectors: &settings::Connectors,
|
||||
) -> CustomResult<String, errors::ConnectorError> {
|
||||
if req.is_three_ds() && req.request.is_card() {
|
||||
Ok(format!(
|
||||
"{}risk/v1/authentication-setups",
|
||||
self.base_url(connectors)
|
||||
))
|
||||
} else {
|
||||
Ok(format!("{}pts/v2/payments/", self.base_url(connectors)))
|
||||
}
|
||||
Ok(format!("{}pts/v2/payments/", self.base_url(connectors)))
|
||||
}
|
||||
fn get_request_body(
|
||||
&self,
|
||||
req: &types::SetupMandateRouterData,
|
||||
_connectors: &settings::Connectors,
|
||||
) -> CustomResult<RequestContent, errors::ConnectorError> {
|
||||
if req.is_three_ds() && req.request.is_card() {
|
||||
let connector_req = bankofamerica::BankOfAmericaAuthSetupRequest::try_from((
|
||||
&req.request.payment_method_data,
|
||||
req.connector_request_reference_id.clone(),
|
||||
))?;
|
||||
Ok(RequestContent::Json(Box::new(connector_req)))
|
||||
} else {
|
||||
let connector_req = bankofamerica::BankOfAmericaPaymentsRequest::try_from(req)?;
|
||||
Ok(RequestContent::Json(Box::new(connector_req)))
|
||||
}
|
||||
let connector_req = bankofamerica::BankOfAmericaPaymentsRequest::try_from(req)?;
|
||||
Ok(RequestContent::Json(Box::new(connector_req)))
|
||||
}
|
||||
|
||||
fn build_request(
|
||||
@ -395,33 +377,19 @@ impl
|
||||
event_builder: Option<&mut ConnectorEvent>,
|
||||
res: Response,
|
||||
) -> CustomResult<types::SetupMandateRouterData, errors::ConnectorError> {
|
||||
if data.is_three_ds() && data.request.is_card() {
|
||||
let response: bankofamerica::BankOfAmericaAuthSetupResponse = res
|
||||
.response
|
||||
.parse_struct("Bankofamerica AuthSetupResponse")
|
||||
.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,
|
||||
})
|
||||
} else {
|
||||
let response: bankofamerica::BankOfAmericaSetupMandatesResponse = res
|
||||
.response
|
||||
.parse_struct("BankOfAmericaSetupMandatesResponse")
|
||||
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
|
||||
let response: bankofamerica::BankOfAmericaSetupMandatesResponse = res
|
||||
.response
|
||||
.parse_struct("BankOfAmericaSetupMandatesResponse")
|
||||
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
|
||||
|
||||
event_builder.map(|i| i.set_response_body(&response));
|
||||
router_env::logger::info!(connector_response=?response);
|
||||
event_builder.map(|i| i.set_response_body(&response));
|
||||
router_env::logger::info!(connector_response=?response);
|
||||
|
||||
types::RouterData::try_from(types::ResponseRouterData {
|
||||
response,
|
||||
data: data.clone(),
|
||||
http_code: res.status_code,
|
||||
})
|
||||
}
|
||||
types::RouterData::try_from(types::ResponseRouterData {
|
||||
response,
|
||||
data: data.clone(),
|
||||
http_code: res.status_code,
|
||||
})
|
||||
}
|
||||
|
||||
fn get_error_response(
|
||||
@ -465,117 +433,6 @@ impl
|
||||
}
|
||||
}
|
||||
|
||||
impl
|
||||
ConnectorIntegration<
|
||||
api::PreProcessing,
|
||||
types::PaymentsPreProcessingData,
|
||||
types::PaymentsResponseData,
|
||||
> for Bankofamerica
|
||||
{
|
||||
fn get_headers(
|
||||
&self,
|
||||
req: &types::PaymentsPreProcessingRouterData,
|
||||
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::PaymentsPreProcessingRouterData,
|
||||
connectors: &settings::Connectors,
|
||||
) -> CustomResult<String, errors::ConnectorError> {
|
||||
let redirect_response = req.request.redirect_response.clone().ok_or(
|
||||
errors::ConnectorError::MissingRequiredField {
|
||||
field_name: "redirect_response",
|
||||
},
|
||||
)?;
|
||||
match redirect_response.params {
|
||||
Some(param) if !param.clone().peek().is_empty() => Ok(format!(
|
||||
"{}risk/v1/authentications",
|
||||
self.base_url(connectors)
|
||||
)),
|
||||
Some(_) | None => Ok(format!(
|
||||
"{}risk/v1/authentication-results",
|
||||
self.base_url(connectors)
|
||||
)),
|
||||
}
|
||||
}
|
||||
fn get_request_body(
|
||||
&self,
|
||||
req: &types::PaymentsPreProcessingRouterData,
|
||||
_connectors: &settings::Connectors,
|
||||
) -> CustomResult<RequestContent, errors::ConnectorError> {
|
||||
let connector_router_data = bankofamerica::BankOfAmericaRouterData::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,
|
||||
))?;
|
||||
let connector_req =
|
||||
bankofamerica::BankOfAmericaPreProcessingRequest::try_from(&connector_router_data)?;
|
||||
Ok(RequestContent::Json(Box::new(connector_req)))
|
||||
}
|
||||
fn build_request(
|
||||
&self,
|
||||
req: &types::PaymentsPreProcessingRouterData,
|
||||
connectors: &settings::Connectors,
|
||||
) -> CustomResult<Option<services::Request>, errors::ConnectorError> {
|
||||
Ok(Some(
|
||||
services::RequestBuilder::new()
|
||||
.method(services::Method::Post)
|
||||
.url(&types::PaymentsPreProcessingType::get_url(
|
||||
self, req, connectors,
|
||||
)?)
|
||||
.attach_default_headers()
|
||||
.headers(types::PaymentsPreProcessingType::get_headers(
|
||||
self, req, connectors,
|
||||
)?)
|
||||
.set_body(types::PaymentsPreProcessingType::get_request_body(
|
||||
self, req, connectors,
|
||||
)?)
|
||||
.build(),
|
||||
))
|
||||
}
|
||||
|
||||
fn handle_response(
|
||||
&self,
|
||||
data: &types::PaymentsPreProcessingRouterData,
|
||||
event_builder: Option<&mut ConnectorEvent>,
|
||||
res: Response,
|
||||
) -> CustomResult<types::PaymentsPreProcessingRouterData, errors::ConnectorError> {
|
||||
let response: bankofamerica::BankOfAmericaPreProcessingResponse = res
|
||||
.response
|
||||
.parse_struct("BankOfAmerica AuthEnrollmentResponse")
|
||||
.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>
|
||||
for Bankofamerica
|
||||
{
|
||||
@ -593,17 +450,13 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
|
||||
|
||||
fn get_url(
|
||||
&self,
|
||||
req: &types::PaymentsAuthorizeRouterData,
|
||||
_req: &types::PaymentsAuthorizeRouterData,
|
||||
connectors: &settings::Connectors,
|
||||
) -> CustomResult<String, errors::ConnectorError> {
|
||||
if req.is_three_ds() && req.request.is_card() {
|
||||
Ok(format!(
|
||||
"{}risk/v1/authentication-setups",
|
||||
self.base_url(connectors)
|
||||
))
|
||||
} else {
|
||||
Ok(format!("{}pts/v2/payments/", self.base_url(connectors)))
|
||||
}
|
||||
Ok(format!(
|
||||
"{}pts/v2/payments/",
|
||||
ConnectorCommon::base_url(self, connectors)
|
||||
))
|
||||
}
|
||||
|
||||
fn get_request_body(
|
||||
@ -617,17 +470,9 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
|
||||
req.request.amount,
|
||||
req,
|
||||
))?;
|
||||
if req.is_three_ds() && req.request.is_card() {
|
||||
let connector_req = bankofamerica::BankOfAmericaAuthSetupRequest::try_from((
|
||||
&req.request.payment_method_data,
|
||||
req.connector_request_reference_id.clone(),
|
||||
))?;
|
||||
Ok(RequestContent::Json(Box::new(connector_req)))
|
||||
} else {
|
||||
let connector_req =
|
||||
bankofamerica::BankOfAmericaPaymentsRequest::try_from(&connector_router_data)?;
|
||||
Ok(RequestContent::Json(Box::new(connector_req)))
|
||||
}
|
||||
let connector_req =
|
||||
bankofamerica::BankOfAmericaPaymentsRequest::try_from(&connector_router_data)?;
|
||||
Ok(RequestContent::Json(Box::new(connector_req)))
|
||||
}
|
||||
|
||||
fn build_request(
|
||||
@ -658,144 +503,9 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
|
||||
event_builder: Option<&mut ConnectorEvent>,
|
||||
res: Response,
|
||||
) -> CustomResult<types::PaymentsAuthorizeRouterData, errors::ConnectorError> {
|
||||
if data.is_three_ds() && data.request.is_card() {
|
||||
let response: bankofamerica::BankOfAmericaAuthSetupResponse = res
|
||||
.response
|
||||
.parse_struct("Bankofamerica AuthSetupResponse")
|
||||
.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,
|
||||
})
|
||||
} else {
|
||||
let response: bankofamerica::BankOfAmericaPaymentsResponse = res
|
||||
.response
|
||||
.parse_struct("Bankofamerica PaymentResponse")
|
||||
.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)
|
||||
}
|
||||
|
||||
fn get_5xx_error_response(
|
||||
&self,
|
||||
res: Response,
|
||||
event_builder: Option<&mut ConnectorEvent>,
|
||||
) -> CustomResult<ErrorResponse, errors::ConnectorError> {
|
||||
let response: bankofamerica::BankOfAmericaServerErrorResponse = res
|
||||
.response
|
||||
.parse_struct("BankOfAmericaServerErrorResponse")
|
||||
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
|
||||
|
||||
event_builder.map(|event| event.set_response_body(&response));
|
||||
router_env::logger::info!(error_response=?response);
|
||||
|
||||
let attempt_status = match response.reason {
|
||||
Some(reason) => match reason {
|
||||
transformers::Reason::SystemError => Some(enums::AttemptStatus::Failure),
|
||||
transformers::Reason::ServerTimeout | transformers::Reason::ServiceTimeout => None,
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
Ok(ErrorResponse {
|
||||
status_code: res.status_code,
|
||||
reason: response.status.clone(),
|
||||
code: response.status.unwrap_or(consts::NO_ERROR_CODE.to_string()),
|
||||
message: response
|
||||
.message
|
||||
.unwrap_or(consts::NO_ERROR_MESSAGE.to_string()),
|
||||
attempt_status,
|
||||
connector_transaction_id: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl
|
||||
ConnectorIntegration<
|
||||
api::CompleteAuthorize,
|
||||
types::CompleteAuthorizeData,
|
||||
types::PaymentsResponseData,
|
||||
> for Bankofamerica
|
||||
{
|
||||
fn get_headers(
|
||||
&self,
|
||||
req: &types::PaymentsCompleteAuthorizeRouterData,
|
||||
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::PaymentsCompleteAuthorizeRouterData,
|
||||
connectors: &settings::Connectors,
|
||||
) -> CustomResult<String, errors::ConnectorError> {
|
||||
Ok(format!("{}pts/v2/payments/", self.base_url(connectors)))
|
||||
}
|
||||
fn get_request_body(
|
||||
&self,
|
||||
req: &types::PaymentsCompleteAuthorizeRouterData,
|
||||
_connectors: &settings::Connectors,
|
||||
) -> CustomResult<RequestContent, errors::ConnectorError> {
|
||||
let connector_router_data = bankofamerica::BankOfAmericaRouterData::try_from((
|
||||
&self.get_currency_unit(),
|
||||
req.request.currency,
|
||||
req.request.amount,
|
||||
req,
|
||||
))?;
|
||||
let connector_req =
|
||||
bankofamerica::BankOfAmericaPaymentsRequest::try_from(&connector_router_data)?;
|
||||
Ok(RequestContent::Json(Box::new(connector_req)))
|
||||
}
|
||||
fn build_request(
|
||||
&self,
|
||||
req: &types::PaymentsCompleteAuthorizeRouterData,
|
||||
connectors: &settings::Connectors,
|
||||
) -> CustomResult<Option<services::Request>, errors::ConnectorError> {
|
||||
Ok(Some(
|
||||
services::RequestBuilder::new()
|
||||
.method(services::Method::Post)
|
||||
.url(&types::PaymentsCompleteAuthorizeType::get_url(
|
||||
self, req, connectors,
|
||||
)?)
|
||||
.attach_default_headers()
|
||||
.headers(types::PaymentsCompleteAuthorizeType::get_headers(
|
||||
self, req, connectors,
|
||||
)?)
|
||||
.set_body(types::PaymentsCompleteAuthorizeType::get_request_body(
|
||||
self, req, connectors,
|
||||
)?)
|
||||
.build(),
|
||||
))
|
||||
}
|
||||
|
||||
fn handle_response(
|
||||
&self,
|
||||
data: &types::PaymentsCompleteAuthorizeRouterData,
|
||||
event_builder: Option<&mut ConnectorEvent>,
|
||||
res: Response,
|
||||
) -> CustomResult<types::PaymentsCompleteAuthorizeRouterData, errors::ConnectorError> {
|
||||
let response: bankofamerica::BankOfAmericaPaymentsResponse = res
|
||||
.response
|
||||
.parse_struct("BankOfAmerica PaymentResponse")
|
||||
.parse_struct("Bankofamerica PaymentResponse")
|
||||
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
|
||||
event_builder.map(|i| i.set_response_body(&response));
|
||||
router_env::logger::info!(connector_response=?response);
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
use api_models::payments;
|
||||
use base64::Engine;
|
||||
use common_utils::{ext_traits::ValueExt, pii};
|
||||
use error_stack::ResultExt;
|
||||
use common_utils::pii;
|
||||
use masking::{ExposeInterface, PeekInterface, Secret};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
@ -9,13 +8,11 @@ use serde_json::Value;
|
||||
use crate::{
|
||||
connector::utils::{
|
||||
self, AddressDetailsData, ApplePayDecrypt, CardData, CardIssuer,
|
||||
PaymentsAuthorizeRequestData, PaymentsCompleteAuthorizeRequestData,
|
||||
PaymentsPreProcessingData, PaymentsSetupMandateRequestData, PaymentsSyncRequestData,
|
||||
PaymentsAuthorizeRequestData, PaymentsSetupMandateRequestData, PaymentsSyncRequestData,
|
||||
RecurringMandateData, RouterData,
|
||||
},
|
||||
consts,
|
||||
core::errors,
|
||||
services,
|
||||
types::{
|
||||
self,
|
||||
api::{self, enums as api_enums},
|
||||
@ -578,28 +575,6 @@ impl
|
||||
}
|
||||
}
|
||||
|
||||
impl
|
||||
From<(
|
||||
&BankOfAmericaRouterData<&types::PaymentsCompleteAuthorizeRouterData>,
|
||||
BillTo,
|
||||
)> for OrderInformationWithBill
|
||||
{
|
||||
fn from(
|
||||
(item, bill_to): (
|
||||
&BankOfAmericaRouterData<&types::PaymentsCompleteAuthorizeRouterData>,
|
||||
BillTo,
|
||||
),
|
||||
) -> Self {
|
||||
Self {
|
||||
amount_details: Amount {
|
||||
total_amount: item.amount.to_owned(),
|
||||
currency: item.router_data.request.currency,
|
||||
},
|
||||
bill_to: Some(bill_to),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl
|
||||
TryFrom<(
|
||||
&BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>,
|
||||
@ -678,67 +653,6 @@ impl
|
||||
}
|
||||
}
|
||||
|
||||
impl
|
||||
From<(
|
||||
&BankOfAmericaRouterData<&types::PaymentsCompleteAuthorizeRouterData>,
|
||||
Option<PaymentSolution>,
|
||||
&BankOfAmericaConsumerAuthValidateResponse,
|
||||
)> for ProcessingInformation
|
||||
{
|
||||
fn from(
|
||||
(item, solution, three_ds_data): (
|
||||
&BankOfAmericaRouterData<&types::PaymentsCompleteAuthorizeRouterData>,
|
||||
Option<PaymentSolution>,
|
||||
&BankOfAmericaConsumerAuthValidateResponse,
|
||||
),
|
||||
) -> Self {
|
||||
let (action_list, action_token_types, authorization_options) =
|
||||
if is_customer_initiated_mandate_payment(&item.router_data.request) {
|
||||
(
|
||||
Some(vec![BankOfAmericaActionsList::TokenCreate]),
|
||||
Some(vec![
|
||||
BankOfAmericaActionsTokenType::PaymentInstrument,
|
||||
BankOfAmericaActionsTokenType::Customer,
|
||||
]),
|
||||
Some(BankOfAmericaAuthorizationOptions {
|
||||
initiator: Some(BankOfAmericaPaymentInitiator {
|
||||
initiator_type: Some(BankOfAmericaPaymentInitiatorTypes::Customer),
|
||||
credential_stored_on_file: Some(true),
|
||||
stored_credential_used: None,
|
||||
}),
|
||||
merchant_intitiated_transaction: None,
|
||||
}),
|
||||
)
|
||||
} else {
|
||||
(None, None, None)
|
||||
};
|
||||
|
||||
let is_setup_mandate_payment = is_setup_mandate_payment(&item.router_data.request);
|
||||
|
||||
let capture = if is_setup_mandate_payment {
|
||||
Some(false)
|
||||
} else {
|
||||
Some(matches!(
|
||||
item.router_data.request.capture_method,
|
||||
Some(enums::CaptureMethod::Automatic) | None
|
||||
))
|
||||
};
|
||||
|
||||
Self {
|
||||
capture,
|
||||
payment_solution: solution.map(String::from),
|
||||
action_list,
|
||||
action_token_types,
|
||||
authorization_options,
|
||||
capture_options: None,
|
||||
commerce_indicator: three_ds_data
|
||||
.indicator
|
||||
.to_owned()
|
||||
.unwrap_or(String::from("internet")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>>
|
||||
for ClientReferenceInformation
|
||||
{
|
||||
@ -749,16 +663,6 @@ impl From<&BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>>
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&BankOfAmericaRouterData<&types::PaymentsCompleteAuthorizeRouterData>>
|
||||
for ClientReferenceInformation
|
||||
{
|
||||
fn from(item: &BankOfAmericaRouterData<&types::PaymentsCompleteAuthorizeRouterData>) -> Self {
|
||||
Self {
|
||||
code: Some(item.router_data.connector_request_reference_id.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&types::SetupMandateRouterData> for ClientReferenceInformation {
|
||||
fn from(item: &types::SetupMandateRouterData) -> Self {
|
||||
Self {
|
||||
@ -894,71 +798,6 @@ pub struct Avs {
|
||||
code_raw: Option<String>,
|
||||
}
|
||||
|
||||
impl
|
||||
TryFrom<(
|
||||
&BankOfAmericaRouterData<&types::PaymentsCompleteAuthorizeRouterData>,
|
||||
domain::Card,
|
||||
)> for BankOfAmericaPaymentsRequest
|
||||
{
|
||||
type Error = error_stack::Report<errors::ConnectorError>;
|
||||
fn try_from(
|
||||
(item, ccard): (
|
||||
&BankOfAmericaRouterData<&types::PaymentsCompleteAuthorizeRouterData>,
|
||||
domain::Card,
|
||||
),
|
||||
) -> Result<Self, Self::Error> {
|
||||
let email = item.router_data.request.get_email()?;
|
||||
let bill_to = build_bill_to(item.router_data.get_optional_billing(), email)?;
|
||||
let order_information = OrderInformationWithBill::from((item, bill_to));
|
||||
|
||||
let payment_information = PaymentInformation::try_from(&ccard)?;
|
||||
let client_reference_information = ClientReferenceInformation::from(item);
|
||||
|
||||
let three_ds_info: BankOfAmericaThreeDSMetadata = item
|
||||
.router_data
|
||||
.request
|
||||
.connector_meta
|
||||
.clone()
|
||||
.ok_or(errors::ConnectorError::MissingRequiredField {
|
||||
field_name: "connector_meta",
|
||||
})?
|
||||
.parse_value("BankOfAmericaThreeDSMetadata")
|
||||
.change_context(errors::ConnectorError::InvalidConnectorConfig {
|
||||
config: "metadata",
|
||||
})?;
|
||||
|
||||
let processing_information =
|
||||
ProcessingInformation::from((item, None, &three_ds_info.three_ds_data));
|
||||
|
||||
let consumer_authentication_information = Some(BankOfAmericaConsumerAuthInformation {
|
||||
ucaf_collection_indicator: three_ds_info.three_ds_data.ucaf_collection_indicator,
|
||||
cavv: three_ds_info.three_ds_data.cavv,
|
||||
ucaf_authentication_data: three_ds_info.three_ds_data.ucaf_authentication_data,
|
||||
xid: three_ds_info.three_ds_data.xid,
|
||||
directory_server_transaction_id: three_ds_info
|
||||
.three_ds_data
|
||||
.directory_server_transaction_id,
|
||||
specification_version: three_ds_info.three_ds_data.specification_version,
|
||||
});
|
||||
|
||||
let merchant_defined_information = item
|
||||
.router_data
|
||||
.request
|
||||
.metadata
|
||||
.clone()
|
||||
.map(Vec::<MerchantDefinedInformation>::foreign_from);
|
||||
|
||||
Ok(Self {
|
||||
processing_information,
|
||||
payment_information,
|
||||
order_information,
|
||||
client_reference_information,
|
||||
consumer_authentication_information,
|
||||
merchant_defined_information,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl
|
||||
TryFrom<(
|
||||
&BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>,
|
||||
@ -1245,53 +1084,6 @@ impl TryFrom<&BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>>
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct BankOfAmericaAuthSetupRequest {
|
||||
payment_information: PaymentInformation,
|
||||
client_reference_information: ClientReferenceInformation,
|
||||
}
|
||||
|
||||
impl TryFrom<(&domain::PaymentMethodData, String)> for BankOfAmericaAuthSetupRequest {
|
||||
type Error = error_stack::Report<errors::ConnectorError>;
|
||||
fn try_from(
|
||||
(payment_method_data, connector_request_reference_id): (&domain::PaymentMethodData, String),
|
||||
) -> Result<Self, Self::Error> {
|
||||
match payment_method_data.clone() {
|
||||
domain::PaymentMethodData::Card(ccard) => {
|
||||
let payment_information = PaymentInformation::try_from(&ccard)?;
|
||||
let client_reference_information = ClientReferenceInformation {
|
||||
code: Some(connector_request_reference_id),
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
payment_information,
|
||||
client_reference_information,
|
||||
})
|
||||
}
|
||||
domain::PaymentMethodData::Wallet(_)
|
||||
| domain::PaymentMethodData::CardRedirect(_)
|
||||
| domain::PaymentMethodData::PayLater(_)
|
||||
| domain::PaymentMethodData::BankRedirect(_)
|
||||
| domain::PaymentMethodData::BankDebit(_)
|
||||
| domain::PaymentMethodData::BankTransfer(_)
|
||||
| domain::PaymentMethodData::Crypto(_)
|
||||
| domain::PaymentMethodData::MandatePayment
|
||||
| domain::PaymentMethodData::Reward
|
||||
| domain::PaymentMethodData::RealTimePayment(_)
|
||||
| domain::PaymentMethodData::Upi(_)
|
||||
| domain::PaymentMethodData::Voucher(_)
|
||||
| domain::PaymentMethodData::GiftCard(_)
|
||||
| domain::PaymentMethodData::CardToken(_) => {
|
||||
Err(errors::ConnectorError::NotImplemented(
|
||||
utils::get_unimplemented_payment_method_error_message("Bank Of America"),
|
||||
)
|
||||
.into())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl
|
||||
TryFrom<(
|
||||
&BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>,
|
||||
@ -1399,39 +1191,6 @@ impl ForeignFrom<(BankofamericaPaymentStatus, bool)> for enums::AttemptStatus {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct BankOfAmericaConsumerAuthInformationResponse {
|
||||
access_token: Secret<String>,
|
||||
device_data_collection_url: Secret<String>,
|
||||
reference_id: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ClientAuthSetupInfoResponse {
|
||||
id: String,
|
||||
client_reference_information: ClientReferenceInformation,
|
||||
consumer_authentication_information: BankOfAmericaConsumerAuthInformationResponse,
|
||||
processor_information: Option<ClientProcessorInformation>,
|
||||
processing_information: Option<ProcessingInformationResponse>,
|
||||
payment_account_information: Option<PaymentAccountInformation>,
|
||||
payment_information: Option<PaymentInformationResponse>,
|
||||
payment_insights_information: Option<PaymentInsightsInformation>,
|
||||
risk_information: Option<ClientRiskInformation>,
|
||||
token_information: Option<BankOfAmericaTokenInformation>,
|
||||
error_information: Option<BankOfAmericaErrorInformation>,
|
||||
issuer_information: Option<IssuerInformation>,
|
||||
reconciliation_id: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum BankOfAmericaAuthSetupResponse {
|
||||
ClientAuthSetupInfo(Box<ClientAuthSetupInfoResponse>),
|
||||
ErrorInformation(Box<BankOfAmericaErrorInformationResponse>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum BankOfAmericaPaymentsResponse {
|
||||
@ -1745,533 +1504,6 @@ fn get_payment_response(
|
||||
}
|
||||
}
|
||||
|
||||
impl<F, T>
|
||||
TryFrom<
|
||||
types::ResponseRouterData<
|
||||
F,
|
||||
BankOfAmericaAuthSetupResponse,
|
||||
T,
|
||||
types::PaymentsResponseData,
|
||||
>,
|
||||
> for types::RouterData<F, T, types::PaymentsResponseData>
|
||||
{
|
||||
type Error = error_stack::Report<errors::ConnectorError>;
|
||||
fn try_from(
|
||||
item: types::ResponseRouterData<
|
||||
F,
|
||||
BankOfAmericaAuthSetupResponse,
|
||||
T,
|
||||
types::PaymentsResponseData,
|
||||
>,
|
||||
) -> Result<Self, Self::Error> {
|
||||
match item.response {
|
||||
BankOfAmericaAuthSetupResponse::ClientAuthSetupInfo(info_response) => Ok(Self {
|
||||
status: enums::AttemptStatus::AuthenticationPending,
|
||||
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::NoResponseId,
|
||||
redirection_data: Some(services::RedirectForm::CybersourceAuthSetup {
|
||||
access_token: info_response
|
||||
.consumer_authentication_information
|
||||
.access_token
|
||||
.expose(),
|
||||
ddc_url: info_response
|
||||
.consumer_authentication_information
|
||||
.device_data_collection_url
|
||||
.expose(),
|
||||
reference_id: info_response
|
||||
.consumer_authentication_information
|
||||
.reference_id,
|
||||
}),
|
||||
mandate_reference: None,
|
||||
connector_metadata: None,
|
||||
network_txn_id: None,
|
||||
connector_response_reference_id: Some(
|
||||
info_response
|
||||
.client_reference_information
|
||||
.code
|
||||
.unwrap_or(info_response.id.clone()),
|
||||
),
|
||||
incremental_authorization_allowed: None,
|
||||
charge_id: None,
|
||||
}),
|
||||
..item.data
|
||||
}),
|
||||
BankOfAmericaAuthSetupResponse::ErrorInformation(error_response) => {
|
||||
let detailed_error_info =
|
||||
error_response
|
||||
.error_information
|
||||
.to_owned()
|
||||
.details
|
||||
.map(|error_details| {
|
||||
error_details
|
||||
.iter()
|
||||
.map(|details| format!("{} : {}", details.field, details.reason))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
});
|
||||
|
||||
let reason = get_error_reason(
|
||||
error_response.error_information.message,
|
||||
detailed_error_info,
|
||||
None,
|
||||
);
|
||||
|
||||
Ok(Self {
|
||||
response: Err(types::ErrorResponse {
|
||||
code: error_response
|
||||
.error_information
|
||||
.reason
|
||||
.clone()
|
||||
.unwrap_or(consts::NO_ERROR_CODE.to_string()),
|
||||
message: error_response
|
||||
.error_information
|
||||
.reason
|
||||
.unwrap_or(consts::NO_ERROR_MESSAGE.to_string()),
|
||||
reason,
|
||||
status_code: item.http_code,
|
||||
attempt_status: None,
|
||||
connector_transaction_id: Some(error_response.id.clone()),
|
||||
}),
|
||||
status: enums::AttemptStatus::AuthenticationFailed,
|
||||
..item.data
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct BankOfAmericaConsumerAuthInformationRequest {
|
||||
return_url: String,
|
||||
reference_id: String,
|
||||
}
|
||||
#[derive(Debug, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct BankOfAmericaAuthEnrollmentRequest {
|
||||
payment_information: PaymentInformation,
|
||||
client_reference_information: ClientReferenceInformation,
|
||||
consumer_authentication_information: BankOfAmericaConsumerAuthInformationRequest,
|
||||
order_information: OrderInformationWithBill,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct BankOfAmericaRedirectionAuthResponse {
|
||||
pub transaction_id: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct BankOfAmericaConsumerAuthInformationValidateRequest {
|
||||
authentication_transaction_id: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct BankOfAmericaAuthValidateRequest {
|
||||
payment_information: PaymentInformation,
|
||||
client_reference_information: ClientReferenceInformation,
|
||||
consumer_authentication_information: BankOfAmericaConsumerAuthInformationValidateRequest,
|
||||
order_information: OrderInformation,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum BankOfAmericaPreProcessingRequest {
|
||||
AuthEnrollment(Box<BankOfAmericaAuthEnrollmentRequest>),
|
||||
AuthValidate(Box<BankOfAmericaAuthValidateRequest>),
|
||||
}
|
||||
|
||||
impl TryFrom<&BankOfAmericaRouterData<&types::PaymentsPreProcessingRouterData>>
|
||||
for BankOfAmericaPreProcessingRequest
|
||||
{
|
||||
type Error = error_stack::Report<errors::ConnectorError>;
|
||||
fn try_from(
|
||||
item: &BankOfAmericaRouterData<&types::PaymentsPreProcessingRouterData>,
|
||||
) -> Result<Self, Self::Error> {
|
||||
let client_reference_information = ClientReferenceInformation {
|
||||
code: Some(item.router_data.connector_request_reference_id.clone()),
|
||||
};
|
||||
let payment_method_data = item.router_data.request.payment_method_data.clone().ok_or(
|
||||
errors::ConnectorError::MissingConnectorRedirectionPayload {
|
||||
field_name: "payment_method_data",
|
||||
},
|
||||
)?;
|
||||
let payment_information = match payment_method_data {
|
||||
domain::PaymentMethodData::Card(ccard) => PaymentInformation::try_from(&ccard),
|
||||
domain::PaymentMethodData::Wallet(_)
|
||||
| domain::PaymentMethodData::CardRedirect(_)
|
||||
| domain::PaymentMethodData::PayLater(_)
|
||||
| domain::PaymentMethodData::BankRedirect(_)
|
||||
| domain::PaymentMethodData::BankDebit(_)
|
||||
| domain::PaymentMethodData::BankTransfer(_)
|
||||
| domain::PaymentMethodData::Crypto(_)
|
||||
| domain::PaymentMethodData::MandatePayment
|
||||
| domain::PaymentMethodData::Reward
|
||||
| domain::PaymentMethodData::RealTimePayment(_)
|
||||
| domain::PaymentMethodData::Upi(_)
|
||||
| domain::PaymentMethodData::Voucher(_)
|
||||
| domain::PaymentMethodData::GiftCard(_)
|
||||
| domain::PaymentMethodData::CardToken(_) => {
|
||||
Err(errors::ConnectorError::NotImplemented(
|
||||
utils::get_unimplemented_payment_method_error_message("BankOfAmerica"),
|
||||
)
|
||||
.into())
|
||||
}
|
||||
}?;
|
||||
|
||||
let redirect_response = item.router_data.request.redirect_response.clone().ok_or(
|
||||
errors::ConnectorError::MissingRequiredField {
|
||||
field_name: "redirect_response",
|
||||
},
|
||||
)?;
|
||||
|
||||
let amount_details = Amount {
|
||||
total_amount: item.amount.clone(),
|
||||
currency: item.router_data.request.currency.ok_or(
|
||||
errors::ConnectorError::MissingRequiredField {
|
||||
field_name: "currency",
|
||||
},
|
||||
)?,
|
||||
};
|
||||
|
||||
match redirect_response.params {
|
||||
Some(param) if !param.clone().peek().is_empty() => {
|
||||
let reference_id = param
|
||||
.clone()
|
||||
.peek()
|
||||
.split_once('=')
|
||||
.ok_or(errors::ConnectorError::MissingConnectorRedirectionPayload {
|
||||
field_name: "request.redirect_response.params.reference_id",
|
||||
})?
|
||||
.1
|
||||
.to_string();
|
||||
let email = item.router_data.request.get_email()?;
|
||||
let bill_to = build_bill_to(item.router_data.get_optional_billing(), email)?;
|
||||
let order_information = OrderInformationWithBill {
|
||||
amount_details,
|
||||
bill_to: Some(bill_to),
|
||||
};
|
||||
Ok(Self::AuthEnrollment(Box::new(
|
||||
BankOfAmericaAuthEnrollmentRequest {
|
||||
payment_information,
|
||||
client_reference_information,
|
||||
consumer_authentication_information:
|
||||
BankOfAmericaConsumerAuthInformationRequest {
|
||||
return_url: item
|
||||
.router_data
|
||||
.request
|
||||
.get_complete_authorize_url()?,
|
||||
reference_id,
|
||||
},
|
||||
order_information,
|
||||
},
|
||||
)))
|
||||
}
|
||||
Some(_) | None => {
|
||||
let redirect_payload: BankOfAmericaRedirectionAuthResponse = redirect_response
|
||||
.payload
|
||||
.ok_or(errors::ConnectorError::MissingConnectorRedirectionPayload {
|
||||
field_name: "request.redirect_response.payload",
|
||||
})?
|
||||
.peek()
|
||||
.clone()
|
||||
.parse_value("BankOfAmericaRedirectionAuthResponse")
|
||||
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
|
||||
let order_information = OrderInformation { amount_details };
|
||||
Ok(Self::AuthValidate(Box::new(
|
||||
BankOfAmericaAuthValidateRequest {
|
||||
payment_information,
|
||||
client_reference_information,
|
||||
consumer_authentication_information:
|
||||
BankOfAmericaConsumerAuthInformationValidateRequest {
|
||||
authentication_transaction_id: redirect_payload.transaction_id,
|
||||
},
|
||||
order_information,
|
||||
},
|
||||
)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&BankOfAmericaRouterData<&types::PaymentsCompleteAuthorizeRouterData>>
|
||||
for BankOfAmericaPaymentsRequest
|
||||
{
|
||||
type Error = error_stack::Report<errors::ConnectorError>;
|
||||
fn try_from(
|
||||
item: &BankOfAmericaRouterData<&types::PaymentsCompleteAuthorizeRouterData>,
|
||||
) -> Result<Self, Self::Error> {
|
||||
let payment_method_data = item.router_data.request.payment_method_data.clone().ok_or(
|
||||
errors::ConnectorError::MissingRequiredField {
|
||||
field_name: "payment_method_data",
|
||||
},
|
||||
)?;
|
||||
match payment_method_data {
|
||||
domain::PaymentMethodData::Card(ccard) => Self::try_from((item, ccard)),
|
||||
domain::PaymentMethodData::Wallet(_)
|
||||
| domain::PaymentMethodData::CardRedirect(_)
|
||||
| domain::PaymentMethodData::PayLater(_)
|
||||
| domain::PaymentMethodData::BankRedirect(_)
|
||||
| domain::PaymentMethodData::BankDebit(_)
|
||||
| domain::PaymentMethodData::BankTransfer(_)
|
||||
| domain::PaymentMethodData::Crypto(_)
|
||||
| domain::PaymentMethodData::MandatePayment
|
||||
| domain::PaymentMethodData::Reward
|
||||
| domain::PaymentMethodData::RealTimePayment(_)
|
||||
| domain::PaymentMethodData::Upi(_)
|
||||
| domain::PaymentMethodData::Voucher(_)
|
||||
| domain::PaymentMethodData::GiftCard(_)
|
||||
| domain::PaymentMethodData::CardToken(_) => {
|
||||
Err(errors::ConnectorError::NotImplemented(
|
||||
utils::get_unimplemented_payment_method_error_message("BankOfAmerica"),
|
||||
)
|
||||
.into())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||
pub enum BankOfAmericaAuthEnrollmentStatus {
|
||||
PendingAuthentication,
|
||||
AuthenticationSuccessful,
|
||||
AuthenticationFailed,
|
||||
}
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct BankOfAmericaConsumerAuthValidateResponse {
|
||||
ucaf_collection_indicator: Option<String>,
|
||||
cavv: Option<String>,
|
||||
ucaf_authentication_data: Option<Secret<String>>,
|
||||
xid: Option<String>,
|
||||
specification_version: Option<String>,
|
||||
directory_server_transaction_id: Option<Secret<String>>,
|
||||
indicator: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct BankOfAmericaThreeDSMetadata {
|
||||
three_ds_data: BankOfAmericaConsumerAuthValidateResponse,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct BankOfAmericaConsumerAuthInformationEnrollmentResponse {
|
||||
access_token: Option<Secret<String>>,
|
||||
step_up_url: Option<String>,
|
||||
//Added to segregate the three_ds_data in a separate struct
|
||||
#[serde(flatten)]
|
||||
validate_response: BankOfAmericaConsumerAuthValidateResponse,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ClientAuthCheckInfoResponse {
|
||||
id: String,
|
||||
client_reference_information: ClientReferenceInformation,
|
||||
consumer_authentication_information: BankOfAmericaConsumerAuthInformationEnrollmentResponse,
|
||||
status: BankOfAmericaAuthEnrollmentStatus,
|
||||
error_information: Option<BankOfAmericaErrorInformation>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum BankOfAmericaPreProcessingResponse {
|
||||
ClientAuthCheckInfo(Box<ClientAuthCheckInfoResponse>),
|
||||
ErrorInformation(Box<BankOfAmericaErrorInformationResponse>),
|
||||
}
|
||||
|
||||
impl From<BankOfAmericaAuthEnrollmentStatus> for enums::AttemptStatus {
|
||||
fn from(item: BankOfAmericaAuthEnrollmentStatus) -> Self {
|
||||
match item {
|
||||
BankOfAmericaAuthEnrollmentStatus::PendingAuthentication => Self::AuthenticationPending,
|
||||
BankOfAmericaAuthEnrollmentStatus::AuthenticationSuccessful => {
|
||||
Self::AuthenticationSuccessful
|
||||
}
|
||||
BankOfAmericaAuthEnrollmentStatus::AuthenticationFailed => Self::AuthenticationFailed,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<F>
|
||||
TryFrom<
|
||||
types::ResponseRouterData<
|
||||
F,
|
||||
BankOfAmericaPreProcessingResponse,
|
||||
types::PaymentsPreProcessingData,
|
||||
types::PaymentsResponseData,
|
||||
>,
|
||||
> for types::RouterData<F, types::PaymentsPreProcessingData, types::PaymentsResponseData>
|
||||
{
|
||||
type Error = error_stack::Report<errors::ConnectorError>;
|
||||
fn try_from(
|
||||
item: types::ResponseRouterData<
|
||||
F,
|
||||
BankOfAmericaPreProcessingResponse,
|
||||
types::PaymentsPreProcessingData,
|
||||
types::PaymentsResponseData,
|
||||
>,
|
||||
) -> Result<Self, Self::Error> {
|
||||
match item.response {
|
||||
BankOfAmericaPreProcessingResponse::ClientAuthCheckInfo(info_response) => {
|
||||
let status = enums::AttemptStatus::from(info_response.status);
|
||||
let risk_info: Option<ClientRiskInformation> = None;
|
||||
if utils::is_payment_failure(status) {
|
||||
let response = Err(types::ErrorResponse::foreign_from((
|
||||
&info_response.error_information,
|
||||
&risk_info,
|
||||
Some(status),
|
||||
item.http_code,
|
||||
info_response.id.clone(),
|
||||
)));
|
||||
|
||||
Ok(Self {
|
||||
status,
|
||||
response,
|
||||
..item.data
|
||||
})
|
||||
} else {
|
||||
let connector_response_reference_id = Some(
|
||||
info_response
|
||||
.client_reference_information
|
||||
.code
|
||||
.unwrap_or(info_response.id.clone()),
|
||||
);
|
||||
|
||||
let redirection_data = match (
|
||||
info_response
|
||||
.consumer_authentication_information
|
||||
.access_token
|
||||
.map(|access_token| access_token.expose()),
|
||||
info_response
|
||||
.consumer_authentication_information
|
||||
.step_up_url,
|
||||
) {
|
||||
(Some(access_token), Some(step_up_url)) => {
|
||||
Some(services::RedirectForm::CybersourceConsumerAuth {
|
||||
access_token,
|
||||
step_up_url,
|
||||
})
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
let three_ds_data = serde_json::to_value(
|
||||
info_response
|
||||
.consumer_authentication_information
|
||||
.validate_response,
|
||||
)
|
||||
.change_context(errors::ConnectorError::ResponseHandlingFailed)?;
|
||||
Ok(Self {
|
||||
status,
|
||||
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::NoResponseId,
|
||||
redirection_data,
|
||||
mandate_reference: None,
|
||||
connector_metadata: Some(serde_json::json!({
|
||||
"three_ds_data": three_ds_data
|
||||
})),
|
||||
network_txn_id: None,
|
||||
connector_response_reference_id,
|
||||
incremental_authorization_allowed: None,
|
||||
charge_id: None,
|
||||
}),
|
||||
..item.data
|
||||
})
|
||||
}
|
||||
}
|
||||
BankOfAmericaPreProcessingResponse::ErrorInformation(error_response) => {
|
||||
let response = Err(types::ErrorResponse::foreign_from((
|
||||
&*error_response,
|
||||
item.http_code,
|
||||
)));
|
||||
Ok(Self {
|
||||
response,
|
||||
status: enums::AttemptStatus::AuthenticationFailed,
|
||||
..item.data
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<F>
|
||||
TryFrom<
|
||||
types::ResponseRouterData<
|
||||
F,
|
||||
BankOfAmericaPaymentsResponse,
|
||||
types::CompleteAuthorizeData,
|
||||
types::PaymentsResponseData,
|
||||
>,
|
||||
> for types::RouterData<F, types::CompleteAuthorizeData, types::PaymentsResponseData>
|
||||
{
|
||||
type Error = error_stack::Report<errors::ConnectorError>;
|
||||
fn try_from(
|
||||
item: types::ResponseRouterData<
|
||||
F,
|
||||
BankOfAmericaPaymentsResponse,
|
||||
types::CompleteAuthorizeData,
|
||||
types::PaymentsResponseData,
|
||||
>,
|
||||
) -> Result<Self, Self::Error> {
|
||||
match item.response {
|
||||
BankOfAmericaPaymentsResponse::ClientReferenceInformation(info_response) => {
|
||||
let status = enums::AttemptStatus::foreign_from((
|
||||
info_response.status.clone(),
|
||||
item.data.request.is_auto_capture()?
|
||||
|| is_setup_mandate_payment(&item.data.request),
|
||||
));
|
||||
let response = get_payment_response((&info_response, status, item.http_code));
|
||||
let connector_response = match item.data.payment_method {
|
||||
common_enums::PaymentMethod::Card => info_response
|
||||
.processor_information
|
||||
.as_ref()
|
||||
.and_then(|processor_information| {
|
||||
info_response
|
||||
.consumer_authentication_information
|
||||
.as_ref()
|
||||
.map(|consumer_auth_information| {
|
||||
types::AdditionalPaymentMethodConnectorResponse::foreign_from((
|
||||
processor_information,
|
||||
consumer_auth_information,
|
||||
))
|
||||
})
|
||||
})
|
||||
.map(types::ConnectorResponseData::with_additional_payment_method_data),
|
||||
common_enums::PaymentMethod::CardRedirect
|
||||
| common_enums::PaymentMethod::PayLater
|
||||
| common_enums::PaymentMethod::Wallet
|
||||
| common_enums::PaymentMethod::BankRedirect
|
||||
| common_enums::PaymentMethod::BankTransfer
|
||||
| common_enums::PaymentMethod::Crypto
|
||||
| common_enums::PaymentMethod::BankDebit
|
||||
| common_enums::PaymentMethod::Reward
|
||||
| common_enums::PaymentMethod::RealTimePayment
|
||||
| common_enums::PaymentMethod::Upi
|
||||
| common_enums::PaymentMethod::Voucher
|
||||
| common_enums::PaymentMethod::GiftCard => None,
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
status,
|
||||
response,
|
||||
connector_response,
|
||||
..item.data
|
||||
})
|
||||
}
|
||||
BankOfAmericaPaymentsResponse::ErrorInformation(ref error_response) => {
|
||||
Ok(Self::foreign_from((
|
||||
&*error_response.clone(),
|
||||
item,
|
||||
Some(enums::AttemptStatus::Failure),
|
||||
)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<F>
|
||||
TryFrom<
|
||||
types::ResponseRouterData<
|
||||
@ -3318,17 +2550,6 @@ fn get_commerce_indicator(network: Option<String>) -> String {
|
||||
.to_string()
|
||||
}
|
||||
|
||||
fn is_setup_mandate_payment(item: &types::CompleteAuthorizeData) -> bool {
|
||||
matches!(item.amount, 0) && is_customer_initiated_mandate_payment(item)
|
||||
}
|
||||
|
||||
fn is_customer_initiated_mandate_payment(item: &types::CompleteAuthorizeData) -> bool {
|
||||
item.setup_future_usage.map_or(false, |future_usage| {
|
||||
matches!(future_usage, common_enums::FutureUsage::OffSession)
|
||||
})
|
||||
// add check for customer_acceptance
|
||||
}
|
||||
|
||||
pub fn get_error_reason(
|
||||
error_info: Option<String>,
|
||||
detailed_error_info: Option<String>,
|
||||
|
||||
@ -1975,8 +1975,7 @@ where
|
||||
router_data = router_data.preprocessing_steps(state, connector).await?;
|
||||
|
||||
(router_data, false)
|
||||
} else if (connector.connector_name == router_types::Connector::Cybersource
|
||||
|| connector.connector_name == router_types::Connector::Bankofamerica)
|
||||
} else if connector.connector_name == router_types::Connector::Cybersource
|
||||
&& is_operation_complete_authorize(&operation)
|
||||
&& router_data.auth_type == storage_enums::AuthenticationType::ThreeDs
|
||||
{
|
||||
|
||||
@ -166,6 +166,7 @@ default_imp_for_complete_authorize!(
|
||||
connector::Aci,
|
||||
connector::Adyen,
|
||||
connector::Bamboraapac,
|
||||
connector::Bankofamerica,
|
||||
connector::Billwerk,
|
||||
connector::Bitpay,
|
||||
connector::Boku,
|
||||
@ -987,6 +988,7 @@ default_imp_for_pre_processing_steps!(
|
||||
connector::Authorizedotnet,
|
||||
connector::Bambora,
|
||||
connector::Bamboraapac,
|
||||
connector::Bankofamerica,
|
||||
connector::Billwerk,
|
||||
connector::Bitpay,
|
||||
connector::Bluesnap,
|
||||
|
||||
Reference in New Issue
Block a user