Skip to content

Commit

Permalink
feat(connector): [CYBERSOURCE] Implement Apple Pay
Browse files Browse the repository at this point in the history
  • Loading branch information
deepanshu-iiitu committed Dec 16, 2023
1 parent ca16b29 commit e4987f5
Show file tree
Hide file tree
Showing 2 changed files with 165 additions and 3 deletions.
87 changes: 87 additions & 0 deletions crates/router/src/configs/defaults.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4707,6 +4707,93 @@ impl Default for super::settings::RequiredFields {
),
common: HashMap::new(),
}
),
(
enums::Connector::Cybersource,
RequiredFieldFinal {
mandate: HashMap::new(),
non_mandate: HashMap::from(
[
(
"email".to_string(),
RequiredFieldInfo {
required_field: "email".to_string(),
display_name: "email".to_string(),
field_type: enums::FieldType::UserEmailAddress,
value: None,
}
),
(
"billing.address.first_name".to_string(),
RequiredFieldInfo {
required_field: "billing.address.first_name".to_string(),
display_name: "billing_first_name".to_string(),
field_type: enums::FieldType::UserBillingName,
value: None,
}
),
(
"billing.address.last_name".to_string(),
RequiredFieldInfo {
required_field: "billing.address.last_name".to_string(),
display_name: "billing_last_name".to_string(),
field_type: enums::FieldType::UserBillingName,
value: None,
}
),
(
"billing.address.city".to_string(),
RequiredFieldInfo {
required_field: "billing.address.city".to_string(),
display_name: "city".to_string(),
field_type: enums::FieldType::UserAddressCity,
value: None,
}
),
(
"billing.address.state".to_string(),
RequiredFieldInfo {
required_field: "billing.address.state".to_string(),
display_name: "state".to_string(),
field_type: enums::FieldType::UserAddressState,
value: None,
}
),
(
"billing.address.zip".to_string(),
RequiredFieldInfo {
required_field: "billing.address.zip".to_string(),
display_name: "zip".to_string(),
field_type: enums::FieldType::UserAddressPincode,
value: None,
}
),
(
"billing.address.country".to_string(),
RequiredFieldInfo {
required_field: "billing.address.country".to_string(),
display_name: "country".to_string(),
field_type: enums::FieldType::UserAddressCountry{
options: vec![
"ALL".to_string(),
]
},
value: None,
}
),
(
"billing.address.line1".to_string(),
RequiredFieldInfo {
required_field: "billing.address.line1".to_string(),
display_name: "line1".to_string(),
field_type: enums::FieldType::UserAddressLine1,
value: None,
}
),
]
),
common: HashMap::new(),
}
)
]),
},
Expand Down
81 changes: 78 additions & 3 deletions crates/router/src/connector/cybersource/transformers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize};

use crate::{
connector::utils::{
self, AddressDetailsData, CardData, PaymentsAuthorizeRequestData,
self, AddressDetailsData, ApplePayDecrypt, CardData, PaymentsAuthorizeRequestData,
PaymentsSetupMandateRequestData, PaymentsSyncRequestData, RouterData,
},
consts,
Expand All @@ -16,6 +16,7 @@ use crate::{
api::{self, enums as api_enums},
storage::enums,
transformers::ForeignFrom,
ApplePayPredecryptData,
},
};

Expand Down Expand Up @@ -207,6 +208,22 @@ pub struct CardPaymentInformation {
instrument_identifier: Option<CybersoucreInstrumentIdentifier>,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct TokenizedCard {
number: Secret<String>,
expiration_month: Secret<String>,
expiration_year: Secret<String>,
cryptogram: Secret<String>,
transaction_type: TransactionType,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ApplePayPaymentInformation {
tokenized_card: TokenizedCard,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct FluidData {
Expand All @@ -224,6 +241,7 @@ pub struct GooglePayPaymentInformation {
pub enum PaymentInformation {
Cards(CardPaymentInformation),
GooglePay(GooglePayPaymentInformation),
ApplePay(ApplePayPaymentInformation),
}

#[derive(Debug, Clone, Serialize, Deserialize)]
Expand Down Expand Up @@ -295,6 +313,12 @@ pub enum PaymentSolution {
GooglePay,
}

#[derive(Debug, Serialize)]
pub enum TransactionType {
#[serde(rename = "1")]
ApplePay,
}

impl From<PaymentSolution> for String {
fn from(solution: PaymentSolution) -> Self {
let payment_solution = match solution {
Expand Down Expand Up @@ -478,6 +502,47 @@ impl
}
}

impl
TryFrom<(
&CybersourceRouterData<&types::PaymentsAuthorizeRouterData>,
Box<ApplePayPredecryptData>,
)> for CybersourcePaymentsRequest
{
type Error = error_stack::Report<errors::ConnectorError>;
fn try_from(
(item, apple_pay_data): (
&CybersourceRouterData<&types::PaymentsAuthorizeRouterData>,
Box<ApplePayPredecryptData>,
),
) -> 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 processing_information =
ProcessingInformation::from((item, Some(PaymentSolution::ApplePay)));
let client_reference_information = ClientReferenceInformation::from(item);
let expiration_month = apple_pay_data.get_expiry_month()?;
let expiration_year = apple_pay_data.get_four_digit_expiry_year()?;

let payment_information = PaymentInformation::ApplePay(ApplePayPaymentInformation {
tokenized_card: TokenizedCard {
number: apple_pay_data.application_primary_account_number,
cryptogram: apple_pay_data.payment_data.online_payment_cryptogram,
transaction_type: TransactionType::ApplePay,
expiration_year,
expiration_month,
},
});

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

impl
TryFrom<(
&CybersourceRouterData<&types::PaymentsAuthorizeRouterData>,
Expand Down Expand Up @@ -526,11 +591,21 @@ impl TryFrom<&CybersourceRouterData<&types::PaymentsAuthorizeRouterData>>
match item.router_data.request.payment_method_data.clone() {
payments::PaymentMethodData::Card(ccard) => Self::try_from((item, ccard)),
payments::PaymentMethodData::Wallet(wallet_data) => match wallet_data {
payments::WalletData::ApplePay(_) => {
let payment_method_token = item.router_data.get_payment_method_token()?;
match payment_method_token {
types::PaymentMethodToken::ApplePayDecrypt(decrypt_data) => {
Self::try_from((item, decrypt_data))
}
types::PaymentMethodToken::Token(_) => {
Err(errors::ConnectorError::InvalidWalletToken)?
}
}
}
payments::WalletData::GooglePay(google_pay_data) => {
Self::try_from((item, google_pay_data))
}
payments::WalletData::ApplePay(_)
| payments::WalletData::AliPayQr(_)
payments::WalletData::AliPayQr(_)
| payments::WalletData::AliPayRedirect(_)
| payments::WalletData::AliPayHkRedirect(_)
| payments::WalletData::MomoRedirect(_)
Expand Down

0 comments on commit e4987f5

Please sign in to comment.