-
Notifications
You must be signed in to change notification settings - Fork 3.9k
feat(connector): [Barclaycard] Add Google Pay Payment Method #8786
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
+437
−51
Merged
Changes from 3 commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
e1aee65
feat(barclaycard): add google pay payment method
767a381
Merge remote-tracking branch 'origin/main' into barclaycard-google-pa…
ffb2734
fix clippy errors
9b5fb8e
add WASM changes for Google Pay and refactor bill_to function
fca6992
fix clippy error
39d5f11
Merge remote-tracking branch 'origin/main' into barclaycard-google-pa…
b1a5d58
fix clippy error
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,8 @@ | ||
use base64::Engine; | ||
use common_enums::enums; | ||
use common_utils::pii; | ||
use common_utils::{consts, pii}; | ||
use hyperswitch_domain_models::{ | ||
payment_method_data::PaymentMethodData, | ||
payment_method_data::{GooglePayWalletData, PaymentMethodData, WalletData}, | ||
router_data::{ | ||
AdditionalPaymentMethodConnectorResponse, ConnectorAuthType, ConnectorResponseData, | ||
ErrorResponse, RouterData, | ||
|
@@ -99,6 +100,7 @@ pub struct BarclaycardPaymentsRequest { | |
pub struct ProcessingInformation { | ||
commerce_indicator: String, | ||
capture: Option<bool>, | ||
payment_solution: Option<String>, | ||
} | ||
|
||
#[derive(Debug, Serialize)] | ||
|
@@ -125,10 +127,17 @@ 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(Box<CardPaymentInformation>), | ||
GooglePay(Box<GooglePayPaymentInformation>), | ||
} | ||
|
||
#[derive(Debug, Serialize)] | ||
|
@@ -142,6 +151,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 { | ||
|
@@ -161,53 +176,60 @@ pub struct Amount { | |
pub struct BillTo { | ||
first_name: Option<Secret<String>>, | ||
last_name: Option<Secret<String>>, | ||
address1: Option<Secret<String>>, | ||
locality: Option<String>, | ||
address1: Secret<String>, | ||
locality: String, | ||
#[serde(skip_serializing_if = "Option::is_none")] | ||
administrative_area: Option<Secret<String>>, | ||
#[serde(skip_serializing_if = "Option::is_none")] | ||
postal_code: Option<Secret<String>>, | ||
country: Option<enums::CountryAlpha2>, | ||
country: enums::CountryAlpha2, | ||
email: pii::Email, | ||
} | ||
|
||
fn build_bill_to( | ||
address_details: Option<&hyperswitch_domain_models::address::Address>, | ||
email: pii::Email, | ||
) -> Result<BillTo, error_stack::Report<errors::ConnectorError>> { | ||
let default_address = BillTo { | ||
first_name: None, | ||
last_name: None, | ||
address1: None, | ||
locality: None, | ||
administrative_area: None, | ||
postal_code: None, | ||
country: None, | ||
email: email.clone(), | ||
}; | ||
|
||
Ok(address_details | ||
.and_then(|addr| { | ||
addr.address.as_ref().map(|addr| { | ||
let administrative_area = addr.to_state_code_as_optional().unwrap_or_else(|_| { | ||
addr.state | ||
.clone() | ||
.map(|state| Secret::new(format!("{:.20}", state.expose()))) | ||
}); | ||
|
||
BillTo { | ||
first_name: addr.first_name.clone(), | ||
last_name: addr.last_name.clone(), | ||
address1: addr.line1.clone(), | ||
locality: addr.city.clone(), | ||
administrative_area, | ||
postal_code: addr.zip.clone(), | ||
country: addr.country, | ||
email, | ||
} | ||
}) | ||
}) | ||
.unwrap_or(default_address)) | ||
let addr = address_details | ||
.and_then(|addr| addr.address.as_ref()) | ||
.ok_or_else(|| errors::ConnectorError::MissingRequiredField { | ||
field_name: "billing_address_details", | ||
})?; | ||
|
||
let administrative_area = addr.to_state_code_as_optional().unwrap_or_else(|_| { | ||
addr.state | ||
.clone() | ||
.map(|state| Secret::new(format!("{:.20}", state.expose()))) | ||
}); | ||
|
||
let address1 = | ||
addr.line1 | ||
.clone() | ||
.ok_or_else(|| errors::ConnectorError::MissingRequiredField { | ||
field_name: "billing_address.line1", | ||
})?; | ||
let locality = | ||
addr.city | ||
.clone() | ||
.ok_or_else(|| errors::ConnectorError::MissingRequiredField { | ||
field_name: "billing_address.city", | ||
})?; | ||
let country = addr | ||
.country | ||
.ok_or_else(|| errors::ConnectorError::MissingRequiredField { | ||
field_name: "billing_address.country", | ||
})?; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use utils here from crates/hyperswitch_connectors/src/utils.rs |
||
|
||
Ok(BillTo { | ||
first_name: addr.first_name.clone(), | ||
last_name: addr.last_name.clone(), | ||
address1, | ||
locality, | ||
administrative_area, | ||
postal_code: addr.zip.clone(), | ||
country, | ||
email, | ||
}) | ||
} | ||
|
||
fn get_barclaycard_card_type(card_network: common_enums::CardNetwork) -> Option<&'static str> { | ||
|
@@ -231,6 +253,20 @@ fn get_barclaycard_card_type(card_network: common_enums::CardNetwork) -> Option< | |
} | ||
} | ||
|
||
#[derive(Debug, Serialize)] | ||
pub enum PaymentSolution { | ||
GooglePay, | ||
} | ||
|
||
impl From<PaymentSolution> for String { | ||
fn from(solution: PaymentSolution) -> Self { | ||
let payment_solution = match solution { | ||
PaymentSolution::GooglePay => "012", | ||
}; | ||
payment_solution.to_string() | ||
} | ||
} | ||
|
||
impl | ||
From<( | ||
&BarclaycardRouterData<&PaymentsAuthorizeRouterData>, | ||
|
@@ -256,14 +292,16 @@ impl | |
impl | ||
TryFrom<( | ||
&BarclaycardRouterData<&PaymentsAuthorizeRouterData>, | ||
Option<PaymentSolution>, | ||
Option<String>, | ||
)> for ProcessingInformation | ||
{ | ||
type Error = error_stack::Report<errors::ConnectorError>; | ||
|
||
fn try_from( | ||
(item, network): ( | ||
(item, solution, network): ( | ||
&BarclaycardRouterData<&PaymentsAuthorizeRouterData>, | ||
Option<PaymentSolution>, | ||
Option<String>, | ||
), | ||
) -> Result<Self, Self::Error> { | ||
|
@@ -274,6 +312,7 @@ impl | |
item.router_data.request.capture_method, | ||
Some(enums::CaptureMethod::Automatic) | None | ||
)), | ||
payment_solution: solution.map(String::from), | ||
commerce_indicator, | ||
}) | ||
} | ||
|
@@ -435,7 +474,45 @@ impl | |
let bill_to = build_bill_to(item.router_data.get_optional_billing(), email)?; | ||
let order_information = OrderInformationWithBill::from((item, Some(bill_to))); | ||
let payment_information = PaymentInformation::try_from(&ccard)?; | ||
let processing_information = ProcessingInformation::try_from((item, None))?; | ||
let processing_information = ProcessingInformation::try_from((item, None, None))?; | ||
let client_reference_information = ClientReferenceInformation::from(item); | ||
let merchant_defined_information = item | ||
.router_data | ||
.request | ||
.metadata | ||
.clone() | ||
.map(convert_metadata_to_merchant_defined_info); | ||
|
||
Ok(Self { | ||
processing_information, | ||
payment_information, | ||
order_information, | ||
client_reference_information, | ||
merchant_defined_information, | ||
consumer_authentication_information: None, | ||
}) | ||
} | ||
} | ||
|
||
impl | ||
TryFrom<( | ||
&BarclaycardRouterData<&PaymentsAuthorizeRouterData>, | ||
GooglePayWalletData, | ||
)> for BarclaycardPaymentsRequest | ||
{ | ||
type Error = error_stack::Report<errors::ConnectorError>; | ||
fn try_from( | ||
(item, google_pay_data): ( | ||
&BarclaycardRouterData<&PaymentsAuthorizeRouterData>, | ||
GooglePayWalletData, | ||
), | ||
) -> 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, Some(bill_to))); | ||
let payment_information = PaymentInformation::from(&google_pay_data); | ||
let processing_information = | ||
ProcessingInformation::try_from((item, Some(PaymentSolution::GooglePay), None))?; | ||
let client_reference_information = ClientReferenceInformation::from(item); | ||
let merchant_defined_information = item | ||
.router_data | ||
|
@@ -462,8 +539,44 @@ impl TryFrom<&BarclaycardRouterData<&PaymentsAuthorizeRouterData>> for Barclayca | |
) -> Result<Self, Self::Error> { | ||
match item.router_data.request.payment_method_data.clone() { | ||
PaymentMethodData::Card(ccard) => Self::try_from((item, ccard)), | ||
PaymentMethodData::Wallet(_) | ||
| PaymentMethodData::MandatePayment | ||
PaymentMethodData::Wallet(wallet_data) => match wallet_data { | ||
WalletData::GooglePay(google_pay_data) => Self::try_from((item, google_pay_data)), | ||
WalletData::AliPayQr(_) | ||
| WalletData::AliPayRedirect(_) | ||
| WalletData::AliPayHkRedirect(_) | ||
| WalletData::AmazonPayRedirect(_) | ||
| WalletData::ApplePay(_) | ||
| WalletData::MomoRedirect(_) | ||
| WalletData::KakaoPayRedirect(_) | ||
| WalletData::GoPayRedirect(_) | ||
| WalletData::GcashRedirect(_) | ||
| WalletData::ApplePayRedirect(_) | ||
| WalletData::ApplePayThirdPartySdk(_) | ||
| WalletData::DanaRedirect {} | ||
| WalletData::GooglePayRedirect(_) | ||
| WalletData::GooglePayThirdPartySdk(_) | ||
| WalletData::MbWayRedirect(_) | ||
| WalletData::MobilePayRedirect(_) | ||
| WalletData::PaypalRedirect(_) | ||
| WalletData::PaypalSdk(_) | ||
| WalletData::Paze(_) | ||
| WalletData::RevolutPay(_) | ||
| WalletData::SamsungPay(_) | ||
| WalletData::TwintRedirect {} | ||
| WalletData::VippsRedirect {} | ||
| WalletData::TouchNGoRedirect(_) | ||
| WalletData::WeChatPayRedirect(_) | ||
| WalletData::WeChatPayQr(_) | ||
| WalletData::CashappQr(_) | ||
| WalletData::SwishQr(_) | ||
| WalletData::Paysera(_) | ||
| WalletData::Skrill(_) | ||
| WalletData::Mifinity(_) => Err(errors::ConnectorError::NotImplemented( | ||
utils::get_unimplemented_payment_method_error_message("Barclaycard"), | ||
) | ||
.into()), | ||
}, | ||
PaymentMethodData::MandatePayment | ||
| PaymentMethodData::CardRedirect(_) | ||
| PaymentMethodData::PayLater(_) | ||
| PaymentMethodData::BankRedirect(_) | ||
|
@@ -1575,6 +1688,18 @@ impl TryFrom<&hyperswitch_domain_models::payment_method_data::Card> for PaymentI | |
} | ||
} | ||
|
||
impl From<&GooglePayWalletData> for PaymentInformation { | ||
fn from(google_pay_data: &GooglePayWalletData) -> Self { | ||
Self::GooglePay(Box::new(GooglePayPaymentInformation { | ||
fluid_data: FluidData { | ||
value: Secret::from( | ||
consts::BASE64_ENGINE.encode(google_pay_data.tokenization_data.token.clone()), | ||
), | ||
}, | ||
})) | ||
} | ||
} | ||
|
||
fn get_commerce_indicator(network: Option<String>) -> String { | ||
match network { | ||
Some(card_network) => match card_network.to_lowercase().as_str() { | ||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dashboard changes for google pay via barclays?