Skip to content

Commit

Permalink
feat(connector): [BANKOFAMERICA] Implement Google Pay (#2940)
Browse files Browse the repository at this point in the history
  • Loading branch information
deepanshu-iiitu committed Dec 20, 2023
1 parent b3ead39 commit e363c2e
Showing 1 changed file with 210 additions and 46 deletions.
256 changes: 210 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,165 @@ impl From<CardIssuer> for String {
}
}

#[derive(Debug, Serialize)]
pub enum PaymentSolution {
ApplePay,
GooglePay,
}

impl From<PaymentSolution> for String {
fn from(solution: PaymentSolution) -> Self {
let payment_solution = match solution {
PaymentSolution::ApplePay => "001",
PaymentSolution::GooglePay => "012",
};
payment_solution.to_string()
}
}

impl
From<(
&BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>,
BillTo,
)> for OrderInformationWithBill
{
fn from(
(item, bill_to): (
&BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>,
BillTo,
),
) -> Self {
Self {
amount_details: Amount {
total_amount: item.amount.to_owned(),
currency: item.router_data.request.currency,
},
bill_to,
}
}
}

impl
From<(
&BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>,
Option<PaymentSolution>,
)> for ProcessingInformation
{
fn from(
(item, solution): (
&BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>,
Option<PaymentSolution>,
),
) -> Self {
Self {
capture: matches!(
item.router_data.request.capture_method,
Some(enums::CaptureMethod::Automatic) | None
),
payment_solution: solution.map(String::from),
}
}
}

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(
(item, ccard): (
&BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>,
payments::Card,
),
) -> Result<Self, Self::Error> {
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(
(item, google_pay_data): (
&BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>,
payments::GooglePayWalletData,
),
) -> Result<Self, Self::Error> {
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 processing_information =
ProcessingInformation::from((item, Some(PaymentSolution::GooglePay)));
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 +366,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

0 comments on commit e363c2e

Please sign in to comment.