Skip to content
246 changes: 200 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,10 +99,24 @@ pub struct CaptureOptions {
}

#[derive(Debug, Serialize)]
pub struct PaymentInformation {
#[serde(rename_all = "camelCase")]
pub struct CardPaymentInformation {
card: Card,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct GooglePayPaymentInformation {
fluid_data: FluidData,
}

#[derive(Debug, Serialize)]
#[serde(untagged)]
pub enum PaymentInformation {
Cards(CardPaymentInformation),
GooglePay(GooglePayPaymentInformation),
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Card {
Expand All @@ -112,6 +128,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 @@ -177,12 +199,155 @@ impl From<CardIssuer> for String {
}
}

impl
From<(
&BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>,
BillTo,
)> for OrderInformationWithBill
{
fn from(
value: (
&BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>,
BillTo,
),
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>,
BillTo,
),
(item, bill_to): (
&BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>,
BillTo,
),

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

) -> Self {
let (item, bill_to) = value;
Self {
amount_details: Amount {
total_amount: item.amount.to_owned(),
currency: item.router_data.request.currency,
},
bill_to,
}
}
}

impl
From<(
&BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>,
Option<String>,
)> for ProcessingInformation
{
fn from(
value: (
&BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>,
Option<String>,
),
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>,
Option<String>,
),
(item, payment_solution): (
&BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>,
Option<String>,
),

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

) -> Self {
let (item, payment_solution) = value;
Self {
capture: matches!(
item.router_data.request.capture_method,
Some(enums::CaptureMethod::Automatic) | None
),
payment_solution,
}
}
}

impl From<&BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>>
for ClientReferenceInformation
{
fn from(item: &BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>) -> Self {
Self {
code: Some(item.router_data.connector_request_reference_id.clone()),
}
}
}

#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
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::from((item, 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::Cards(CardPaymentInformation {
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::from((item, None));
let client_reference_information = ClientReferenceInformation::from(item);

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::from((item, bill_to));

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

let payment_solution = Some("012".to_string());
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's have this as enum, which will be useful while implementing applepay

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

let processing_information = ProcessingInformation::from((item, payment_solution));
let client_reference_information = ClientReferenceInformation::from(item);

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

impl TryFrom<&BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>>
for BankOfAmericaPaymentsRequest
{
Expand All @@ -191,52 +356,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