Skip to content

Commit 8dd380a

Browse files
feat(connector): [BANKOFAMERICA] Implement Google Pay (#2940)
1 parent 9519157 commit 8dd380a

File tree

1 file changed

+210
-46
lines changed

1 file changed

+210
-46
lines changed

crates/router/src/connector/bankofamerica/transformers.rs

Lines changed: 210 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use api_models::payments;
2+
use base64::Engine;
23
use common_utils::pii;
34
use masking::Secret;
45
use serde::{Deserialize, Serialize};
@@ -87,6 +88,7 @@ pub struct BankOfAmericaPaymentsRequest {
8788
#[serde(rename_all = "camelCase")]
8889
pub struct ProcessingInformation {
8990
capture: bool,
91+
payment_solution: Option<String>,
9092
}
9193

9294
#[derive(Debug, Serialize)]
@@ -97,10 +99,24 @@ pub struct CaptureOptions {
9799
}
98100

99101
#[derive(Debug, Serialize)]
100-
pub struct PaymentInformation {
102+
#[serde(rename_all = "camelCase")]
103+
pub struct CardPaymentInformation {
101104
card: Card,
102105
}
103106

107+
#[derive(Debug, Serialize)]
108+
#[serde(rename_all = "camelCase")]
109+
pub struct GooglePayPaymentInformation {
110+
fluid_data: FluidData,
111+
}
112+
113+
#[derive(Debug, Serialize)]
114+
#[serde(untagged)]
115+
pub enum PaymentInformation {
116+
Cards(CardPaymentInformation),
117+
GooglePay(GooglePayPaymentInformation),
118+
}
119+
104120
#[derive(Debug, Serialize)]
105121
#[serde(rename_all = "camelCase")]
106122
pub struct Card {
@@ -112,6 +128,12 @@ pub struct Card {
112128
card_type: Option<String>,
113129
}
114130

131+
#[derive(Debug, Serialize)]
132+
#[serde(rename_all = "camelCase")]
133+
pub struct FluidData {
134+
value: Secret<String>,
135+
}
136+
115137
#[derive(Debug, Serialize)]
116138
#[serde(rename_all = "camelCase")]
117139
pub struct OrderInformationWithBill {
@@ -177,12 +199,165 @@ impl From<CardIssuer> for String {
177199
}
178200
}
179201

202+
#[derive(Debug, Serialize)]
203+
pub enum PaymentSolution {
204+
ApplePay,
205+
GooglePay,
206+
}
207+
208+
impl From<PaymentSolution> for String {
209+
fn from(solution: PaymentSolution) -> Self {
210+
let payment_solution = match solution {
211+
PaymentSolution::ApplePay => "001",
212+
PaymentSolution::GooglePay => "012",
213+
};
214+
payment_solution.to_string()
215+
}
216+
}
217+
218+
impl
219+
From<(
220+
&BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>,
221+
BillTo,
222+
)> for OrderInformationWithBill
223+
{
224+
fn from(
225+
(item, bill_to): (
226+
&BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>,
227+
BillTo,
228+
),
229+
) -> Self {
230+
Self {
231+
amount_details: Amount {
232+
total_amount: item.amount.to_owned(),
233+
currency: item.router_data.request.currency,
234+
},
235+
bill_to,
236+
}
237+
}
238+
}
239+
240+
impl
241+
From<(
242+
&BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>,
243+
Option<PaymentSolution>,
244+
)> for ProcessingInformation
245+
{
246+
fn from(
247+
(item, solution): (
248+
&BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>,
249+
Option<PaymentSolution>,
250+
),
251+
) -> Self {
252+
Self {
253+
capture: matches!(
254+
item.router_data.request.capture_method,
255+
Some(enums::CaptureMethod::Automatic) | None
256+
),
257+
payment_solution: solution.map(String::from),
258+
}
259+
}
260+
}
261+
262+
impl From<&BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>>
263+
for ClientReferenceInformation
264+
{
265+
fn from(item: &BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>) -> Self {
266+
Self {
267+
code: Some(item.router_data.connector_request_reference_id.clone()),
268+
}
269+
}
270+
}
271+
180272
#[derive(Debug, Deserialize, Serialize)]
181273
#[serde(rename_all = "camelCase")]
182274
pub struct ClientReferenceInformation {
183275
code: Option<String>,
184276
}
185277

278+
impl
279+
TryFrom<(
280+
&BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>,
281+
payments::Card,
282+
)> for BankOfAmericaPaymentsRequest
283+
{
284+
type Error = error_stack::Report<errors::ConnectorError>;
285+
fn try_from(
286+
(item, ccard): (
287+
&BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>,
288+
payments::Card,
289+
),
290+
) -> Result<Self, Self::Error> {
291+
let email = item.router_data.request.get_email()?;
292+
let bill_to = build_bill_to(item.router_data.get_billing()?, email)?;
293+
let order_information = OrderInformationWithBill::from((item, bill_to));
294+
295+
let card_issuer = ccard.get_card_issuer();
296+
let card_type = match card_issuer {
297+
Ok(issuer) => Some(String::from(issuer)),
298+
Err(_) => None,
299+
};
300+
301+
let payment_information = PaymentInformation::Cards(CardPaymentInformation {
302+
card: Card {
303+
number: ccard.card_number,
304+
expiration_month: ccard.card_exp_month,
305+
expiration_year: ccard.card_exp_year,
306+
security_code: ccard.card_cvc,
307+
card_type,
308+
},
309+
});
310+
311+
let processing_information = ProcessingInformation::from((item, None));
312+
let client_reference_information = ClientReferenceInformation::from(item);
313+
314+
Ok(Self {
315+
processing_information,
316+
payment_information,
317+
order_information,
318+
client_reference_information,
319+
})
320+
}
321+
}
322+
323+
impl
324+
TryFrom<(
325+
&BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>,
326+
payments::GooglePayWalletData,
327+
)> for BankOfAmericaPaymentsRequest
328+
{
329+
type Error = error_stack::Report<errors::ConnectorError>;
330+
fn try_from(
331+
(item, google_pay_data): (
332+
&BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>,
333+
payments::GooglePayWalletData,
334+
),
335+
) -> Result<Self, Self::Error> {
336+
let email = item.router_data.request.get_email()?;
337+
let bill_to = build_bill_to(item.router_data.get_billing()?, email)?;
338+
let order_information = OrderInformationWithBill::from((item, bill_to));
339+
340+
let payment_information = PaymentInformation::GooglePay(GooglePayPaymentInformation {
341+
fluid_data: FluidData {
342+
value: Secret::from(
343+
consts::BASE64_ENGINE.encode(google_pay_data.tokenization_data.token),
344+
),
345+
},
346+
});
347+
348+
let processing_information =
349+
ProcessingInformation::from((item, Some(PaymentSolution::GooglePay)));
350+
let client_reference_information = ClientReferenceInformation::from(item);
351+
352+
Ok(Self {
353+
processing_information,
354+
payment_information,
355+
order_information,
356+
client_reference_information,
357+
})
358+
}
359+
}
360+
186361
impl TryFrom<&BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>>
187362
for BankOfAmericaPaymentsRequest
188363
{
@@ -191,52 +366,41 @@ impl TryFrom<&BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>>
191366
item: &BankOfAmericaRouterData<&types::PaymentsAuthorizeRouterData>,
192367
) -> Result<Self, Self::Error> {
193368
match item.router_data.request.payment_method_data.clone() {
194-
api::PaymentMethodData::Card(ccard) => {
195-
let email = item.router_data.request.get_email()?;
196-
let bill_to = build_bill_to(item.router_data.get_billing()?, email)?;
197-
198-
let order_information = OrderInformationWithBill {
199-
amount_details: Amount {
200-
total_amount: item.amount.to_owned(),
201-
currency: item.router_data.request.currency,
202-
},
203-
bill_to,
204-
};
205-
let card_issuer = ccard.get_card_issuer();
206-
let card_type = match card_issuer {
207-
Ok(issuer) => Some(String::from(issuer)),
208-
Err(_) => None,
209-
};
210-
let payment_information = PaymentInformation {
211-
card: Card {
212-
number: ccard.card_number,
213-
expiration_month: ccard.card_exp_month,
214-
expiration_year: ccard.card_exp_year,
215-
security_code: ccard.card_cvc,
216-
card_type,
217-
},
218-
};
219-
220-
let processing_information = ProcessingInformation {
221-
capture: matches!(
222-
item.router_data.request.capture_method,
223-
Some(enums::CaptureMethod::Automatic) | None
224-
),
225-
};
226-
227-
let client_reference_information = ClientReferenceInformation {
228-
code: Some(item.router_data.connector_request_reference_id.clone()),
229-
};
230-
231-
Ok(Self {
232-
processing_information,
233-
payment_information,
234-
order_information,
235-
client_reference_information,
236-
})
237-
}
369+
payments::PaymentMethodData::Card(ccard) => Self::try_from((item, ccard)),
370+
payments::PaymentMethodData::Wallet(wallet_data) => match wallet_data {
371+
payments::WalletData::GooglePay(google_pay_data) => {
372+
Self::try_from((item, google_pay_data))
373+
}
374+
payments::WalletData::AliPayQr(_)
375+
| payments::WalletData::AliPayRedirect(_)
376+
| payments::WalletData::AliPayHkRedirect(_)
377+
| payments::WalletData::MomoRedirect(_)
378+
| payments::WalletData::KakaoPayRedirect(_)
379+
| payments::WalletData::GoPayRedirect(_)
380+
| payments::WalletData::GcashRedirect(_)
381+
| payments::WalletData::ApplePay(_)
382+
| payments::WalletData::ApplePayRedirect(_)
383+
| payments::WalletData::ApplePayThirdPartySdk(_)
384+
| payments::WalletData::DanaRedirect {}
385+
| payments::WalletData::GooglePayRedirect(_)
386+
| payments::WalletData::GooglePayThirdPartySdk(_)
387+
| payments::WalletData::MbWayRedirect(_)
388+
| payments::WalletData::MobilePayRedirect(_)
389+
| payments::WalletData::PaypalRedirect(_)
390+
| payments::WalletData::PaypalSdk(_)
391+
| payments::WalletData::SamsungPay(_)
392+
| payments::WalletData::TwintRedirect {}
393+
| payments::WalletData::VippsRedirect {}
394+
| payments::WalletData::TouchNGoRedirect(_)
395+
| payments::WalletData::WeChatPayRedirect(_)
396+
| payments::WalletData::WeChatPayQr(_)
397+
| payments::WalletData::CashappQr(_)
398+
| payments::WalletData::SwishQr(_) => Err(errors::ConnectorError::NotImplemented(
399+
utils::get_unimplemented_payment_method_error_message("Bank of America"),
400+
)
401+
.into()),
402+
},
238403
payments::PaymentMethodData::CardRedirect(_)
239-
| payments::PaymentMethodData::Wallet(_)
240404
| payments::PaymentMethodData::PayLater(_)
241405
| payments::PaymentMethodData::BankRedirect(_)
242406
| payments::PaymentMethodData::BankDebit(_)

0 commit comments

Comments
 (0)