feat(connector): [Zen] Add Latam Payment Methods (#1670)

Co-authored-by: swangi-kumari <swangi.12015941@lpu.in>
Co-authored-by: Narayan Bhat <48803246+Narayanbhat166@users.noreply.github.com>
This commit is contained in:
SamraatBansal
2023-07-27 00:54:45 +05:30
committed by GitHub
parent 38f14b9f39
commit 4df67adb9b
21 changed files with 494 additions and 30 deletions

Binary file not shown.

View File

@ -198,6 +198,7 @@ trustpay.base_url = "https://test-tpgw.trustpay.eu/"
tsys.base_url = "https://stagegw.transnox.com/"
trustpay.base_url_bank_redirects = "https://aapi.trustpay.eu/"
zen.base_url = "https://api.zen-test.com/"
zen.secondary_base_url = "https://secure.zen-test.com/"
# Bank redirect configs for allowed banks through online_banking_czech_republic payment method
[bank_config.online_banking_czech_republic]
@ -218,7 +219,7 @@ stripe = { banks = "alior_bank,bank_millennium,bank_nowy_bfg_sa,bank_pekao_sa,ba
# This data is used to call respective connectors for wallets and cards
[connectors.supported]
wallets = ["klarna", "braintree", "applepay"]
rewards = ["cashtocode"]
rewards = ["cashtocode", "zen"]
cards = [
"adyen",
"authorizedotnet",
@ -325,6 +326,18 @@ online_banking_thailand = {country = "TH", currency = "THB"}
touch_n_go = {country = "MY", currency = "MYR"}
atome = {country = "MY,SG", currency = "MYR,SGD"}
[pm_filters.zen]
credit = { not_available_flows = { capture_method = "manual" } }
debit = { not_available_flows = { capture_method = "manual" } }
boleto = { country = "BR", currency = "BRL" }
efecty = { country = "CO", currency = "COP" }
multibanco = { country = "PT", currency = "EUR" }
pago_efectivo = { country = "PE", currency = "PEN" }
pse = { country = "CO", currency = "COP" }
pix = { country = "BR", currency = "BRL" }
red_compra = { country = "CL", currency = "CLP" }
red_pagos = { country = "UY", currency = "UYU" }
[bank_config.online_banking_fpx]
adyen.banks = "affin_bank,agro_bank,alliance_bank,am_bank,bank_islam,bank_muamalat,bank_rakyat,bank_simpanan_nasional,cimb_bank,hong_leong_bank,hsbc_bank,kuwait_finance_house,may_bank,ocbc_bank,public_bank,rhb_bank,standard_chartered_bank,uob_bank"

View File

@ -52,7 +52,7 @@ tunnel_private_key = ""
[connectors.supported]
wallets = ["klarna", "braintree", "applepay"]
rewards = ["cashtocode",]
rewards = ["cashtocode", "zen"]
cards = [
"aci",
"adyen",
@ -162,7 +162,7 @@ trustpay.base_url = "https://test-tpgw.trustpay.eu/"
tsys.base_url = "https://stagegw.transnox.com/"
trustpay.base_url_bank_redirects = "https://aapi.trustpay.eu/"
zen.base_url = "https://api.zen-test.com/"
zen.secondary_base_url = "https://secure.zen.com/"
zen.secondary_base_url = "https://secure.zen-test.com/"
[scheduler]
stream = "SCHEDULER_STREAM"
@ -276,6 +276,14 @@ debit = { not_available_flows = { capture_method = "manual" } }
[pm_filters.zen]
credit = { not_available_flows = { capture_method = "manual" } }
debit = { not_available_flows = { capture_method = "manual" } }
boleto = { country = "BR", currency = "BRL" }
efecty = { country = "CO", currency = "COP" }
multibanco = { country = "PT", currency = "EUR" }
pago_efectivo = { country = "PE", currency = "PEN" }
pse = { country = "CO", currency = "COP" }
pix = { country = "BR", currency = "BRL" }
red_compra = { country = "CL", currency = "CLP" }
red_pagos = { country = "UY", currency = "UYU" }
[pm_filters.aci]
credit = { not_available_flows = { capture_method = "manual" } }

View File

@ -120,11 +120,12 @@ trustpay.base_url = "https://test-tpgw.trustpay.eu/"
tsys.base_url = "https://stagegw.transnox.com/"
trustpay.base_url_bank_redirects = "https://aapi.trustpay.eu/"
zen.base_url = "https://api.zen-test.com/"
zen.secondary_base_url = "https://secure.zen-test.com/"
[connectors.supported]
wallets = ["klarna", "braintree", "applepay"]
rewards = ["cashtocode",]
rewards = ["cashtocode", "zen"]
cards = [
"aci",
"adyen",
@ -208,6 +209,18 @@ online_banking_thailand = {country = "TH", currency = "THB"}
touch_n_go = {country = "MY", currency = "MYR"}
atome = {country = "MY,SG", currency = "MYR,SGD"}
[pm_filters.zen]
credit = { not_available_flows = { capture_method = "manual" } }
debit = { not_available_flows = { capture_method = "manual" } }
boleto = { country = "BR", currency = "BRL" }
efecty = { country = "CO", currency = "COP" }
multibanco = { country = "PT", currency = "EUR" }
pago_efectivo = { country = "PE", currency = "PEN" }
pse = { country = "CO", currency = "COP" }
pix = { country = "BR", currency = "BRL" }
red_compra = { country = "CL", currency = "CLP" }
red_pagos = { country = "UY", currency = "UYU" }
[bank_config.online_banking_fpx]
adyen.banks = "affin_bank,agro_bank,alliance_bank,am_bank,bank_islam,bank_muamalat,bank_rakyat,bank_simpanan_nasional,cimb_bank,hong_leong_bank,hsbc_bank,kuwait_finance_house,may_bank,ocbc_bank,public_bank,rhb_bank,standard_chartered_bank,uob_bank"

View File

@ -721,6 +721,7 @@ pub enum PaymentMethodData {
MandatePayment,
Reward(RewardData),
Upi(UpiData),
Voucher(VoucherData),
GiftCard(Box<GiftCardData>),
}
@ -764,6 +765,7 @@ pub enum AdditionalPaymentData {
MandatePayment {},
Reward {},
Upi {},
Voucher {},
GiftCard {},
}
@ -964,6 +966,8 @@ pub enum BankTransferData {
/// The billing details for Multibanco
billing_details: MultibancoBillingDetails,
},
Pix {},
Pse {},
}
#[derive(serde::Deserialize, serde::Serialize, Debug, Clone, ToSchema, Eq, PartialEq)]
@ -1177,6 +1181,23 @@ pub struct RewardData {
pub merchant_id: String,
}
#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct BoletoVoucherData {
/// The shopper's social security number
#[schema(value_type = Option<String>)]
social_security_number: Option<Secret<String>>,
}
#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, serde::Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum VoucherData {
Boleto(Box<BoletoVoucherData>),
Efecty,
PagoEfectivo,
RedCompra,
RedPagos,
}
#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum PaymentMethodDataResponse {
@ -1192,6 +1213,7 @@ pub enum PaymentMethodDataResponse {
MandatePayment,
Reward,
Upi,
Voucher,
GiftCard,
}
@ -1875,6 +1897,7 @@ impl From<AdditionalPaymentData> for PaymentMethodDataResponse {
AdditionalPaymentData::Reward {} => Self::Reward,
AdditionalPaymentData::Upi {} => Self::Upi,
AdditionalPaymentData::BankTransfer {} => Self::BankTransfer,
AdditionalPaymentData::Voucher {} => Self::Voucher,
AdditionalPaymentData::GiftCard {} => Self::GiftCard,
}
}

View File

@ -176,6 +176,7 @@ pub enum Currency {
BBD,
BDT,
BHD,
BIF,
BMD,
BND,
BOB,
@ -185,11 +186,13 @@ pub enum Currency {
BZD,
CAD,
CHF,
CLP,
CNY,
COP,
CRC,
CUP,
CZK,
DJF,
DKK,
DOP,
DZD,
@ -201,6 +204,7 @@ pub enum Currency {
GHS,
GIP,
GMD,
GNF,
GTQ,
GYD,
HKD,
@ -217,6 +221,7 @@ pub enum Currency {
KES,
KGS,
KHR,
KMF,
KRW,
KWD,
KYD,
@ -228,6 +233,7 @@ pub enum Currency {
LSL,
MAD,
MDL,
MGA,
MKD,
MMK,
MNT,
@ -249,9 +255,11 @@ pub enum Currency {
PHP,
PKR,
PLN,
PYG,
QAR,
RON,
RUB,
RWF,
SAR,
SCR,
SEK,
@ -266,11 +274,16 @@ pub enum Currency {
TTD,
TWD,
TZS,
UGX,
#[default]
USD,
UYU,
UZS,
VND,
VUV,
XAF,
XOF,
XPF,
YER,
ZAR,
}
@ -289,6 +302,7 @@ impl Currency {
Self::BBD => "052",
Self::BDT => "050",
Self::BHD => "048",
Self::BIF => "108",
Self::BMD => "060",
Self::BND => "096",
Self::BOB => "068",
@ -298,10 +312,12 @@ impl Currency {
Self::BZD => "084",
Self::CAD => "124",
Self::CHF => "756",
Self::CLP => "152",
Self::COP => "170",
Self::CRC => "188",
Self::CUP => "192",
Self::CZK => "203",
Self::DJF => "262",
Self::DKK => "208",
Self::DOP => "214",
Self::DZD => "012",
@ -313,6 +329,7 @@ impl Currency {
Self::GHS => "936",
Self::GIP => "292",
Self::GMD => "270",
Self::GNF => "324",
Self::GTQ => "320",
Self::GYD => "328",
Self::HKD => "344",
@ -329,6 +346,7 @@ impl Currency {
Self::KES => "404",
Self::KGS => "417",
Self::KHR => "116",
Self::KMF => "174",
Self::KRW => "410",
Self::KWD => "414",
Self::KYD => "136",
@ -340,6 +358,7 @@ impl Currency {
Self::LSL => "426",
Self::MAD => "504",
Self::MDL => "498",
Self::MGA => "969",
Self::MKD => "807",
Self::MMK => "104",
Self::MNT => "496",
@ -361,10 +380,12 @@ impl Currency {
Self::PHP => "608",
Self::PKR => "586",
Self::PLN => "985",
Self::PYG => "600",
Self::QAR => "634",
Self::RON => "946",
Self::CNY => "156",
Self::RUB => "643",
Self::RWF => "646",
Self::SAR => "682",
Self::SCR => "690",
Self::SEK => "752",
@ -379,10 +400,15 @@ impl Currency {
Self::TTD => "780",
Self::TWD => "901",
Self::TZS => "834",
Self::UGX => "800",
Self::USD => "840",
Self::UYU => "858",
Self::UZS => "860",
Self::VND => "704",
Self::VUV => "548",
Self::XAF => "950",
Self::XOF => "952",
Self::XPF => "953",
Self::YER => "886",
Self::ZAR => "710",
}
@ -390,7 +416,22 @@ impl Currency {
pub fn is_zero_decimal_currency(self) -> bool {
match self {
Self::JPY | Self::KRW => true,
Self::BIF
| Self::CLP
| Self::DJF
| Self::GNF
| Self::JPY
| Self::KMF
| Self::KRW
| Self::MGA
| Self::PYG
| Self::RWF
| Self::UGX
| Self::VND
| Self::VUV
| Self::XAF
| Self::XOF
| Self::XPF => true,
Self::AED
| Self::ALL
| Self::AMD
@ -493,7 +534,6 @@ impl Currency {
| Self::USD
| Self::UYU
| Self::UZS
| Self::VND
| Self::YER
| Self::ZAR => false,
}
@ -512,6 +552,7 @@ impl Currency {
| Self::AZN
| Self::BBD
| Self::BDT
| Self::BIF
| Self::BMD
| Self::BND
| Self::BOB
@ -521,11 +562,13 @@ impl Currency {
| Self::BZD
| Self::CAD
| Self::CHF
| Self::CLP
| Self::CNY
| Self::COP
| Self::CRC
| Self::CUP
| Self::CZK
| Self::DJF
| Self::DKK
| Self::DOP
| Self::DZD
@ -537,6 +580,7 @@ impl Currency {
| Self::GHS
| Self::GIP
| Self::GMD
| Self::GNF
| Self::GTQ
| Self::GYD
| Self::HKD
@ -552,6 +596,7 @@ impl Currency {
| Self::KES
| Self::KGS
| Self::KHR
| Self::KMF
| Self::KRW
| Self::KYD
| Self::KZT
@ -562,6 +607,7 @@ impl Currency {
| Self::LSL
| Self::MAD
| Self::MDL
| Self::MGA
| Self::MKD
| Self::MMK
| Self::MNT
@ -582,9 +628,11 @@ impl Currency {
| Self::PHP
| Self::PKR
| Self::PLN
| Self::PYG
| Self::QAR
| Self::RON
| Self::RUB
| Self::RWF
| Self::SAR
| Self::SCR
| Self::SEK
@ -599,10 +647,15 @@ impl Currency {
| Self::TTD
| Self::TWD
| Self::TZS
| Self::UGX
| Self::USD
| Self::UYU
| Self::UZS
| Self::VND
| Self::VUV
| Self::XAF
| Self::XPF
| Self::XOF
| Self::YER
| Self::ZAR => false,
}
@ -783,14 +836,16 @@ pub enum PaymentMethodType {
Bacs,
BancontactCard,
Becs,
Blik,
Bizum,
Blik,
Boleto,
#[serde(rename = "classic")]
ClassicReward,
Credit,
CryptoCurrency,
Dana,
Debit,
Efecty,
Eps,
Evoucher,
Giropay,
@ -811,9 +866,14 @@ pub enum PaymentMethodType {
OnlineBankingFpx,
OnlineBankingPoland,
OnlineBankingSlovakia,
PagoEfectivo,
PayBright,
Paypal,
Pix,
Przelewy24,
Pse,
RedCompra,
RedPagos,
SamsungPay,
Sepa,
Sofort,
@ -857,6 +917,7 @@ pub enum PaymentMethod {
BankDebit,
Reward,
Upi,
Voucher,
}
#[derive(

View File

@ -1572,6 +1572,8 @@ impl From<PaymentMethodType> for PaymentMethod {
PaymentMethodType::OnlineBankingThailand => Self::BankRedirect,
PaymentMethodType::OnlineBankingPoland => Self::BankRedirect,
PaymentMethodType::OnlineBankingSlovakia => Self::BankRedirect,
PaymentMethodType::Pix => Self::BankTransfer,
PaymentMethodType::Pse => Self::BankTransfer,
PaymentMethodType::PayBright => Self::PayLater,
PaymentMethodType::Paypal => Self::Wallet,
PaymentMethodType::Przelewy24 => Self::BankRedirect,
@ -1587,6 +1589,11 @@ impl From<PaymentMethodType> for PaymentMethod {
PaymentMethodType::WeChatPay => Self::Wallet,
PaymentMethodType::TouchNGo => Self::Wallet,
PaymentMethodType::Atome => Self::PayLater,
PaymentMethodType::Boleto => Self::Voucher,
PaymentMethodType::Efecty => Self::Voucher,
PaymentMethodType::PagoEfectivo => Self::Voucher,
PaymentMethodType::RedCompra => Self::Voucher,
PaymentMethodType::RedPagos => Self::Voucher,
}
}
}

View File

@ -371,7 +371,8 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for AciPaymentsRequest {
| api::PaymentMethodData::BankTransfer(_)
| api::PaymentMethodData::Reward(_)
| api::PaymentMethodData::GiftCard(_)
| api::PaymentMethodData::Upi(_) => Err(errors::ConnectorError::NotSupported {
| api::PaymentMethodData::Upi(_)
| api::PaymentMethodData::Voucher(_) => Err(errors::ConnectorError::NotSupported {
message: format!("{:?}", item.payment_method),
connector: "Aci",
payment_experience: api_models::enums::PaymentExperience::RedirectToUrl.to_string(),

View File

@ -167,7 +167,8 @@ impl TryFrom<&PaymentMethodData> for SalePaymentMethod {
| PaymentMethodData::MandatePayment
| PaymentMethodData::Reward(_)
| PaymentMethodData::GiftCard(_)
| PaymentMethodData::Upi(_) => {
| PaymentMethodData::Upi(_)
| api::PaymentMethodData::Voucher(_) => {
Err(errors::ConnectorError::NotImplemented("Payment methods".to_string()).into())
}
}

View File

@ -1232,6 +1232,10 @@ fn create_stripe_payment_method(
billing_details,
))
}
payments::BankTransferData::Pix {} | payments::BankTransferData::Pse {} => Err(
errors::ConnectorError::NotImplemented("this payment method".to_string())
.into(),
),
}
}
_ => Err(errors::ConnectorError::NotImplemented(
@ -2900,13 +2904,17 @@ impl
payment_method_type: StripePaymentMethodType::CustomerBalance,
})),
)),
payments::BankTransferData::Pix {} | payments::BankTransferData::Pse {} => Err(
errors::ConnectorError::NotImplemented("payment method".to_string()).into(),
),
}
}
api::PaymentMethodData::MandatePayment
| api::PaymentMethodData::Crypto(_)
| api::PaymentMethodData::Reward(_)
| api::PaymentMethodData::GiftCard(_)
| api::PaymentMethodData::Upi(_) => Err(errors::ConnectorError::NotSupported {
| api::PaymentMethodData::Upi(_)
| api::PaymentMethodData::Voucher(_) => Err(errors::ConnectorError::NotSupported {
message: format!("{pm_type:?}"),
connector: "Stripe",
payment_experience: api_models::enums::PaymentExperience::RedirectToUrl.to_string(),

View File

@ -41,7 +41,7 @@ pub struct ApiRequest {
payment_channel: ZenPaymentChannels,
amount: String,
currency: enums::Currency,
payment_specific_data: ZenPaymentData,
payment_specific_data: ZenPaymentSpecificData,
customer: ZenCustomerDetails,
custom_ipn_url: String,
items: Vec<ZenItemObject>,
@ -75,6 +75,14 @@ pub enum ZenPaymentChannels {
PclCard,
PclGooglepay,
PclApplepay,
PclBoacompraBoleto,
PclBoacompraEfecty,
PclBoacompraMultibanco,
PclBoacompraPagoefectivo,
PclBoacompraPix,
PclBoacompraPse,
PclBoacompraRedcompra,
PclBoacompraRedpagos,
}
#[derive(Debug, Serialize)]
@ -84,6 +92,13 @@ pub struct ZenCustomerDetails {
ip: Secret<String, pii::IpAddress>,
}
#[derive(Debug, Serialize)]
#[serde(untagged)]
pub enum ZenPaymentSpecificData {
ZenOnetimePayment(Box<ZenPaymentData>),
ZenGeneralPayment(ZenGeneralPaymentData),
}
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ZenPaymentData {
@ -98,6 +113,14 @@ pub struct ZenPaymentData {
return_verify_url: Option<String>,
}
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ZenGeneralPaymentData {
#[serde(rename = "type")]
payment_type: ZenPaymentTypes,
return_url: String,
}
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ZenBrowserDetails {
@ -116,6 +139,7 @@ pub struct ZenBrowserDetails {
#[serde(rename_all = "snake_case")]
pub enum ZenPaymentTypes {
Onetime,
General,
}
#[derive(Debug, Serialize)]
@ -155,19 +179,21 @@ impl TryFrom<(&types::PaymentsAuthorizeRouterData, &Card)> for ZenPaymentsReques
let ip = browser_info.get_ip_address()?;
let browser_details = get_browser_details(&browser_info)?;
let amount = utils::to_currency_base_unit(item.request.amount, item.request.currency)?;
let payment_specific_data = ZenPaymentData {
let payment_specific_data =
ZenPaymentSpecificData::ZenOnetimePayment(Box::new(ZenPaymentData {
browser_details,
//Connector Specific for cards
payment_type: ZenPaymentTypes::Onetime,
token: None,
card: Some(ZenCardDetails {
number: ccard.card_number.clone(),
expiry_date: ccard.get_card_expiry_month_year_2_digit_with_delimiter("".to_owned()),
expiry_date: ccard
.get_card_expiry_month_year_2_digit_with_delimiter("".to_owned()),
cvv: ccard.card_cvc.clone(),
}),
descriptor: item.get_description()?.chars().take(24).collect(),
return_verify_url: item.request.router_return_url.clone(),
};
}));
Ok(Self::ApiRequest(Box::new(ApiRequest {
merchant_transaction_id: item.attempt_id.clone(),
payment_channel: ZenPaymentChannels::PclCard,
@ -181,6 +207,108 @@ impl TryFrom<(&types::PaymentsAuthorizeRouterData, &Card)> for ZenPaymentsReques
}
}
impl
TryFrom<(
&types::PaymentsAuthorizeRouterData,
&api_models::payments::VoucherData,
)> for ZenPaymentsRequest
{
type Error = error_stack::Report<errors::ConnectorError>;
fn try_from(
value: (
&types::PaymentsAuthorizeRouterData,
&api_models::payments::VoucherData,
),
) -> Result<Self, Self::Error> {
let (item, voucher_data) = value;
let browser_info = item.request.get_browser_info()?;
let ip = browser_info.get_ip_address()?;
let amount = utils::to_currency_base_unit_with_zero_decimal_check(
item.request.amount,
item.request.currency,
)?;
let payment_specific_data =
ZenPaymentSpecificData::ZenGeneralPayment(ZenGeneralPaymentData {
//Connector Specific for Latam Methods
payment_type: ZenPaymentTypes::General,
return_url: item.request.get_router_return_url()?,
});
let payment_channel = match voucher_data {
api_models::payments::VoucherData::Boleto { .. } => {
ZenPaymentChannels::PclBoacompraBoleto
}
api_models::payments::VoucherData::Efecty => ZenPaymentChannels::PclBoacompraEfecty,
api_models::payments::VoucherData::PagoEfectivo => {
ZenPaymentChannels::PclBoacompraPagoefectivo
}
api_models::payments::VoucherData::RedCompra => {
ZenPaymentChannels::PclBoacompraRedcompra
}
api_models::payments::VoucherData::RedPagos => ZenPaymentChannels::PclBoacompraRedpagos,
};
Ok(Self::ApiRequest(Box::new(ApiRequest {
merchant_transaction_id: item.attempt_id.clone(),
payment_channel,
currency: item.request.currency,
payment_specific_data,
customer: get_customer(item, ip)?,
custom_ipn_url: item.request.get_webhook_url()?,
items: get_item_object(item, amount.clone())?,
amount,
})))
}
}
impl
TryFrom<(
&types::PaymentsAuthorizeRouterData,
&Box<api_models::payments::BankTransferData>,
)> for ZenPaymentsRequest
{
type Error = error_stack::Report<errors::ConnectorError>;
fn try_from(
value: (
&types::PaymentsAuthorizeRouterData,
&Box<api_models::payments::BankTransferData>,
),
) -> Result<Self, Self::Error> {
let (item, bank_transfer_data) = value;
let browser_info = item.request.get_browser_info()?;
let ip = browser_info.get_ip_address()?;
let amount = utils::to_currency_base_unit(item.request.amount, item.request.currency)?;
let payment_specific_data =
ZenPaymentSpecificData::ZenGeneralPayment(ZenGeneralPaymentData {
//Connector Specific for Latam Methods
payment_type: ZenPaymentTypes::General,
return_url: item.request.get_router_return_url()?,
});
let payment_channel = match **bank_transfer_data {
api_models::payments::BankTransferData::MultibancoBankTransfer { .. } => {
ZenPaymentChannels::PclBoacompraMultibanco
}
api_models::payments::BankTransferData::Pix { .. } => {
ZenPaymentChannels::PclBoacompraPix
}
api_models::payments::BankTransferData::Pse { .. } => {
ZenPaymentChannels::PclBoacompraPse
}
_ => Err(errors::ConnectorError::NotImplemented(
"payment method".to_string(),
))?,
};
Ok(Self::ApiRequest(Box::new(ApiRequest {
merchant_transaction_id: item.attempt_id.clone(),
payment_channel,
currency: item.request.currency,
payment_specific_data,
customer: get_customer(item, ip)?,
custom_ipn_url: item.request.get_webhook_url()?,
items: get_item_object(item, amount.clone())?,
amount,
})))
}
}
/*
impl TryFrom<(&types::PaymentsAuthorizeRouterData, &GooglePayWalletData)> for ZenPaymentsRequest {
type Error = error_stack::Report<errors::ConnectorError>;
@ -339,6 +467,14 @@ fn get_signature_data(checkout_request: &CheckoutRequest) -> String {
ZenPaymentChannels::PclCard => "pcl_card",
ZenPaymentChannels::PclGooglepay => "pcl_googlepay",
ZenPaymentChannels::PclApplepay => "pcl_applepay",
ZenPaymentChannels::PclBoacompraBoleto => "pcl_boacompra_boleto",
ZenPaymentChannels::PclBoacompraEfecty => "pcl_boacompra_efecty",
ZenPaymentChannels::PclBoacompraMultibanco => "pcl_boacompra_multibanco",
ZenPaymentChannels::PclBoacompraPagoefectivo => "pcl_boacompra_pagoefectivo",
ZenPaymentChannels::PclBoacompraPix => "pcl_boacompra_pix",
ZenPaymentChannels::PclBoacompraPse => "pcl_boacompra_pse",
ZenPaymentChannels::PclBoacompraRedcompra => "pcl_boacompra_redcompra",
ZenPaymentChannels::PclBoacompraRedpagos => "pcl_boacompra_redpagos",
};
let mut signature_data = vec![
format!("amount={}", checkout_request.amount),
@ -402,7 +538,10 @@ fn get_item_object(
Ok(ZenItemObject {
name: data.product_name.clone(),
quantity: data.quantity,
price: utils::to_currency_base_unit(data.amount, item.request.currency)?,
price: utils::to_currency_base_unit_with_zero_decimal_check(
data.amount,
item.request.currency,
)?,
line_amount_total: (f64::from(data.quantity)
* utils::to_currency_base_unit_asf64(data.amount, item.request.currency)?)
.to_string(),
@ -458,6 +597,12 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for ZenPaymentsRequest {
api_models::payments::PaymentMethodData::Wallet(wallet_data) => {
Self::try_from((item, wallet_data))
}
api_models::payments::PaymentMethodData::Voucher(voucher_data) => {
Self::try_from((item, voucher_data))
}
api_models::payments::PaymentMethodData::BankTransfer(bank_transfer_data) => {
Self::try_from((item, bank_transfer_data))
}
_ => Err(errors::ConnectorError::NotImplemented(
"payment method".to_string(),
))?,

View File

@ -838,7 +838,9 @@ where
let router_data_and_should_continue_payment = match payment_data.payment_method_data.clone() {
Some(api_models::payments::PaymentMethodData::BankTransfer(data)) => match data.deref() {
api_models::payments::BankTransferData::AchBankTransfer { .. }
| api_models::payments::BankTransferData::MultibancoBankTransfer { .. } => {
| api_models::payments::BankTransferData::MultibancoBankTransfer { .. }
if connector.connector_name == types::Connector::Stripe =>
{
if payment_data.payment_attempt.preprocessing_step_id.is_none() {
(
router_data.preprocessing_steps(state, connector).await?,

View File

@ -1278,6 +1278,7 @@ pub async fn make_pm_data<'a, F: Clone, R>(
(pm @ Some(api::PaymentMethodData::Crypto(_)), _) => Ok(pm.to_owned()),
(pm @ Some(api::PaymentMethodData::BankDebit(_)), _) => Ok(pm.to_owned()),
(pm @ Some(api::PaymentMethodData::Upi(_)), _) => Ok(pm.to_owned()),
(pm @ Some(api::PaymentMethodData::Voucher(_)), _) => Ok(pm.to_owned()),
(pm @ Some(api::PaymentMethodData::Reward(_)), _) => Ok(pm.to_owned()),
(pm @ Some(api::PaymentMethodData::GiftCard(_)), _) => Ok(pm.to_owned()),
(pm_opt @ Some(pm @ api::PaymentMethodData::BankTransfer(_)), _) => {
@ -2624,6 +2625,9 @@ pub async fn get_additional_payment_data(
api_models::payments::PaymentMethodData::Upi(_) => {
api_models::payments::AdditionalPaymentData::Upi {}
}
api_models::payments::PaymentMethodData::Voucher(_) => {
api_models::payments::AdditionalPaymentData::Voucher {}
}
api_models::payments::PaymentMethodData::GiftCard(_) => {
api_models::payments::AdditionalPaymentData::GiftCard {}
}

View File

@ -193,6 +193,8 @@ Never share your secret api keys. Keep them guarded and secure.
api_models::payments::CryptoData,
api_models::payments::RewardData,
api_models::payments::UpiData,
api_models::payments::VoucherData,
api_models::payments::BoletoVoucherData,
api_models::payments::Address,
api_models::payments::BankRedirectData,
api_models::payments::BankRedirectBilling,

View File

@ -218,7 +218,14 @@ impl ForeignFrom<api_enums::PaymentMethodType> for api_enums::PaymentMethod {
}
api_enums::PaymentMethodType::Evoucher
| api_enums::PaymentMethodType::ClassicReward => Self::Reward,
api_enums::PaymentMethodType::Multibanco => Self::BankTransfer,
api_enums::PaymentMethodType::Boleto
| api_enums::PaymentMethodType::Efecty
| api_enums::PaymentMethodType::PagoEfectivo
| api_enums::PaymentMethodType::RedCompra
| api_enums::PaymentMethodType::RedPagos => Self::Voucher,
api_enums::PaymentMethodType::Multibanco
| api_enums::PaymentMethodType::Pix
| api_enums::PaymentMethodType::Pse => Self::BankTransfer,
}
}
}

View File

@ -71,3 +71,4 @@ mod worldline;
mod worldline_ui;
mod worldpay;
mod zen;
mod zen_ui;

View File

@ -0,0 +1,37 @@
use serial_test::serial;
use thirtyfour::{prelude::*, WebDriver};
use crate::{selenium::*, tester};
struct ZenSeleniumTest;
impl SeleniumTest for ZenSeleniumTest {
fn get_connector_name(&self) -> String {
"zen".to_string()
}
}
async fn should_make_zen_3ds_payment(web_driver: WebDriver) -> Result<(), WebDriverError> {
let mycon = ZenSeleniumTest {};
mycon
.make_redirection_payment(
web_driver,
vec![
Event::Trigger(Trigger::Goto(&format!("{CHEKOUT_BASE_URL}/saved/201"))),
Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))),
Event::Trigger(Trigger::Sleep(10)), //url gets updated only after some time, so need this timeout to solve the issue
Event::Trigger(Trigger::SwitchFrame(By::Name("cko-3ds2-iframe"))),
Event::Trigger(Trigger::SendKeys(By::Id("password"), "Checkout1!")),
Event::Trigger(Trigger::Click(By::Id("txtButton"))),
Event::Assert(Assert::IsPresent("succeeded")),
],
)
.await?;
Ok(())
}
#[test]
#[serial]
fn should_make_zen_3ds_payment_test() {
tester!(should_make_zen_3ds_payment);
}

View File

@ -107,10 +107,11 @@ tsys.base_url = "https://stagegw.transnox.com/"
wise.base_url = "https://api.sandbox.transferwise.tech/"
trustpay.base_url_bank_redirects = "https://aapi.trustpay.eu/"
zen.base_url = "https://api.zen-test.com/"
zen.secondary_base_url = "https://secure.zen-test.com/"
[connectors.supported]
wallets = ["klarna", "braintree", "applepay"]
rewards = ["cashtocode",]
rewards = ["cashtocode", "zen"]
cards = [
"aci",
"adyen",
@ -156,6 +157,18 @@ cards = [
"zen",
]
[pm_filters.zen]
credit = { not_available_flows = { capture_method = "manual" } }
debit = { not_available_flows = { capture_method = "manual" } }
boleto = { country = "BR", currency = "BRL" }
efecty = { country = "CO", currency = "COP" }
multibanco = { country = "PT", currency = "EUR" }
pago_efectivo = { country = "PE", currency = "PEN" }
pse = { country = "CO", currency = "COP" }
pix = { country = "BR", currency = "BRL" }
red_compra = { country = "CL", currency = "CLP" }
red_pagos = { country = "UY", currency = "UYU" }
#tokenization configuration which describe token lifetime and payment method for specific connector
[tokenization]
stripe = { long_lived_token = false, payment_method = "wallet", payment_method_type = { type = "disable_only", list = "google_pay" } }

View File

@ -0,0 +1 @@
SELECT 1;

View File

@ -0,0 +1,14 @@
-- Your SQL goes here
ALTER TYPE "Currency" ADD VALUE IF NOT EXISTS 'BIF' AFTER 'BHD';
ALTER TYPE "Currency" ADD VALUE IF NOT EXISTS 'CLP' AFTER 'CHF';
ALTER TYPE "Currency" ADD VALUE IF NOT EXISTS 'DJF' AFTER 'CZK';
ALTER TYPE "Currency" ADD VALUE IF NOT EXISTS 'GNF' AFTER 'GMD';
ALTER TYPE "Currency" ADD VALUE IF NOT EXISTS 'KMF' AFTER 'KHR';
ALTER TYPE "Currency" ADD VALUE IF NOT EXISTS 'MGA' AFTER 'MDL';
ALTER TYPE "Currency" ADD VALUE IF NOT EXISTS 'PYG' AFTER 'PLN';
ALTER TYPE "Currency" ADD VALUE IF NOT EXISTS 'RWF' AFTER 'RUB';
ALTER TYPE "Currency" ADD VALUE IF NOT EXISTS 'UGX' AFTER 'TZS';
ALTER TYPE "Currency" ADD VALUE IF NOT EXISTS 'VUV' AFTER 'VND';
ALTER TYPE "Currency" ADD VALUE IF NOT EXISTS 'XAF' AFTER 'VUV';
ALTER TYPE "Currency" ADD VALUE IF NOT EXISTS 'XOF' AFTER 'XAF';
ALTER TYPE "Currency" ADD VALUE IF NOT EXISTS 'XPF' AFTER 'XOF';

View File

@ -3197,6 +3197,28 @@
}
}
}
},
{
"type": "object",
"required": [
"pix"
],
"properties": {
"pix": {
"type": "object"
}
}
},
{
"type": "object",
"required": [
"pse"
],
"properties": {
"pse": {
"type": "object"
}
}
}
]
},
@ -3266,6 +3288,16 @@
}
]
},
"BoletoVoucherData": {
"type": "object",
"properties": {
"social_security_number": {
"type": "string",
"description": "The shopper's social security number",
"nullable": true
}
}
},
"CaptureMethod": {
"type": "string",
"enum": [
@ -3849,6 +3881,7 @@
"BBD",
"BDT",
"BHD",
"BIF",
"BMD",
"BND",
"BOB",
@ -3858,11 +3891,13 @@
"BZD",
"CAD",
"CHF",
"CLP",
"CNY",
"COP",
"CRC",
"CUP",
"CZK",
"DJF",
"DKK",
"DOP",
"DZD",
@ -3874,6 +3909,7 @@
"GHS",
"GIP",
"GMD",
"GNF",
"GTQ",
"GYD",
"HKD",
@ -3890,6 +3926,7 @@
"KES",
"KGS",
"KHR",
"KMF",
"KRW",
"KWD",
"KYD",
@ -3901,6 +3938,7 @@
"LSL",
"MAD",
"MDL",
"MGA",
"MKD",
"MMK",
"MNT",
@ -3922,9 +3960,11 @@
"PHP",
"PKR",
"PLN",
"PYG",
"QAR",
"RON",
"RUB",
"RWF",
"SAR",
"SCR",
"SEK",
@ -3939,10 +3979,15 @@
"TTD",
"TWD",
"TZS",
"UGX",
"USD",
"UYU",
"UZS",
"VND",
"VUV",
"XAF",
"XOF",
"XPF",
"YER",
"ZAR"
]
@ -6928,7 +6973,8 @@
"crypto",
"bank_debit",
"reward",
"upi"
"upi",
"voucher"
]
},
"PaymentMethodCreate": {
@ -7096,6 +7142,17 @@
}
}
},
{
"type": "object",
"required": [
"voucher"
],
"properties": {
"voucher": {
"$ref": "#/components/schemas/VoucherData"
}
}
},
{
"type": "object",
"required": [
@ -7298,13 +7355,15 @@
"bacs",
"bancontact_card",
"becs",
"blik",
"bizum",
"blik",
"boleto",
"classic",
"credit",
"crypto_currency",
"dana",
"debit",
"efecty",
"eps",
"evoucher",
"giropay",
@ -7325,9 +7384,14 @@
"online_banking_fpx",
"online_banking_poland",
"online_banking_slovakia",
"pago_efectivo",
"pay_bright",
"paypal",
"pix",
"przelewy24",
"pse",
"red_compra",
"red_pagos",
"samsung_pay",
"sepa",
"sofort",
@ -9900,6 +9964,45 @@
}
}
},
"VoucherData": {
"oneOf": [
{
"type": "object",
"required": [
"boleto"
],
"properties": {
"boleto": {
"$ref": "#/components/schemas/BoletoVoucherData"
}
}
},
{
"type": "string",
"enum": [
"efecty"
]
},
{
"type": "string",
"enum": [
"pago_efectivo"
]
},
{
"type": "string",
"enum": [
"red_compra"
]
},
{
"type": "string",
"enum": [
"red_pagos"
]
}
]
},
"WalletData": {
"oneOf": [
{