Skip to content
207 changes: 161 additions & 46 deletions crates/router/src/connector/bankofamerica/transformers.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use api_models::payments;
use base64::Engine;
use common_utils::pii;
use masking::Secret;
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -87,6 +88,7 @@ pub struct BankOfAmericaPaymentsRequest {
#[serde(rename_all = "camelCase")]
pub struct ProcessingInformation {
capture: bool,
payment_solution: Option<String>,
}

#[derive(Debug, Serialize)]
Expand All @@ -97,8 +99,10 @@ pub struct CaptureOptions {
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct PaymentInformation {
card: Card,
card: Option<Card>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Create enum for PaymentInformation, one for card and one for fluid data

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

fluid_data: Option<FluidData>,
}

#[derive(Debug, Serialize)]
Expand All @@ -112,6 +116,12 @@ pub struct Card {
card_type: Option<String>,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct FluidData {
value: Secret<String>,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct OrderInformationWithBill {
Expand Down Expand Up @@ -183,6 +193,122 @@ pub struct ClientReferenceInformation {
code: Option<String>,
}

impl
TryFrom<(
&BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>,
payments::Card,
)> for BankOfAmericaPaymentsRequest
{
type Error = error_stack::Report<errors::ConnectorError>;
fn try_from(
value: (
&BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>,
payments::Card,
),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
value: (
&BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>,
payments::Card,
),
(item, ccard): (
&BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>,
payments::Card,
),

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

) -> Result<Self, Self::Error> {
let (item, ccard) = value;
let email = item.router_data.request.get_email()?;
let bill_to = build_bill_to(item.router_data.get_billing()?, email)?;

let order_information = OrderInformationWithBill {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Handle this with From impl so redundant code can be reduced

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

amount_details: Amount {
total_amount: item.amount.to_owned(),
currency: item.router_data.request.currency,
},
bill_to,
};
let card_issuer = ccard.get_card_issuer();
let card_type = match card_issuer {
Ok(issuer) => Some(String::from(issuer)),
Err(_) => None,
};
let payment_information = PaymentInformation {
card: Some(Card {
number: ccard.card_number,
expiration_month: ccard.card_exp_month,
expiration_year: ccard.card_exp_year,
security_code: ccard.card_cvc,
card_type,
}),
fluid_data: None,
};

let processing_information = ProcessingInformation {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use From implementation

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

capture: matches!(
item.router_data.request.capture_method,
Some(enums::CaptureMethod::Automatic) | None
),
payment_solution: None,
};

let client_reference_information = ClientReferenceInformation {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use From impl

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

code: Some(item.router_data.connector_request_reference_id.clone()),
};

Ok(Self {
processing_information,
payment_information,
order_information,
client_reference_information,
})
}
}

impl
TryFrom<(
&BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>,
payments::GooglePayWalletData,
)> for BankOfAmericaPaymentsRequest
{
type Error = error_stack::Report<errors::ConnectorError>;
fn try_from(
value: (
&BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>,
payments::GooglePayWalletData,
),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
value: (
&BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>,
payments::GooglePayWalletData,
),
(item, google_pay_data): (
&BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>,
payments::GooglePayWalletData,
),

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

) -> Result<Self, Self::Error> {
let (item, google_pay_data) = value;
let email = item.router_data.request.get_email()?;
let bill_to = build_bill_to(item.router_data.get_billing()?, email)?;

let order_information = OrderInformationWithBill {
amount_details: Amount {
total_amount: item.amount.to_owned(),
currency: item.router_data.request.currency,
},
bill_to,
};

let payment_information = PaymentInformation {
card: None,
fluid_data: Some(FluidData {
value: Secret::from(
consts::BASE64_ENGINE.encode(google_pay_data.tokenization_data.token),
),
}),
};

let processing_information = ProcessingInformation {
capture: matches!(
item.router_data.request.capture_method,
Some(enums::CaptureMethod::Automatic) | None
),
payment_solution: Some("012".to_string()),
};

let client_reference_information = ClientReferenceInformation {
code: Some(item.router_data.connector_request_reference_id.clone()),
};

Ok(Self {
processing_information,
payment_information,
order_information,
client_reference_information,
})
}
}

impl TryFrom<&BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>>
for BankOfAmericaPaymentsRequest
{
Expand All @@ -191,52 +317,41 @@ impl TryFrom<&BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>>
item: &BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>,
) -> Result<Self, Self::Error> {
match item.router_data.request.payment_method_data.clone() {
api::PaymentMethodData::Card(ccard) => {
let email = item.router_data.request.get_email()?;
let bill_to = build_bill_to(item.router_data.get_billing()?, email)?;

let order_information = OrderInformationWithBill {
amount_details: Amount {
total_amount: item.amount.to_owned(),
currency: item.router_data.request.currency,
},
bill_to,
};
let card_issuer = ccard.get_card_issuer();
let card_type = match card_issuer {
Ok(issuer) => Some(String::from(issuer)),
Err(_) => None,
};
let payment_information = PaymentInformation {
card: Card {
number: ccard.card_number,
expiration_month: ccard.card_exp_month,
expiration_year: ccard.card_exp_year,
security_code: ccard.card_cvc,
card_type,
},
};

let processing_information = ProcessingInformation {
capture: matches!(
item.router_data.request.capture_method,
Some(enums::CaptureMethod::Automatic) | None
),
};

let client_reference_information = ClientReferenceInformation {
code: Some(item.router_data.connector_request_reference_id.clone()),
};

Ok(Self {
processing_information,
payment_information,
order_information,
client_reference_information,
})
}
payments::PaymentMethodData::Card(ccard) => Self::try_from((item, ccard)),
payments::PaymentMethodData::Wallet(wallet_data) => match wallet_data {
payments::WalletData::GooglePay(google_pay_data) => {
Self::try_from((item, google_pay_data))
}
payments::WalletData::AliPayQr(_)
| payments::WalletData::AliPayRedirect(_)
| payments::WalletData::AliPayHkRedirect(_)
| payments::WalletData::MomoRedirect(_)
| payments::WalletData::KakaoPayRedirect(_)
| payments::WalletData::GoPayRedirect(_)
| payments::WalletData::GcashRedirect(_)
| payments::WalletData::ApplePay(_)
| payments::WalletData::ApplePayRedirect(_)
| payments::WalletData::ApplePayThirdPartySdk(_)
| payments::WalletData::DanaRedirect {}
| payments::WalletData::GooglePayRedirect(_)
| payments::WalletData::GooglePayThirdPartySdk(_)
| payments::WalletData::MbWayRedirect(_)
| payments::WalletData::MobilePayRedirect(_)
| payments::WalletData::PaypalRedirect(_)
| payments::WalletData::PaypalSdk(_)
| payments::WalletData::SamsungPay(_)
| payments::WalletData::TwintRedirect {}
| payments::WalletData::VippsRedirect {}
| payments::WalletData::TouchNGoRedirect(_)
| payments::WalletData::WeChatPayRedirect(_)
| payments::WalletData::WeChatPayQr(_)
| payments::WalletData::CashappQr(_)
| payments::WalletData::SwishQr(_) => Err(errors::ConnectorError::NotImplemented(
utils::get_unimplemented_payment_method_error_message("Bank of America"),
)
.into()),
},
payments::PaymentMethodData::CardRedirect(_)
| payments::PaymentMethodData::Wallet(_)
| payments::PaymentMethodData::PayLater(_)
| payments::PaymentMethodData::BankRedirect(_)
| payments::PaymentMethodData::BankDebit(_)
Expand Down