feat(connector): [STRIPE] Added Connector Tokenization Flow for Cards (#8248)

Co-authored-by: Sayak Bhattacharya <sayak.b@Sayak-Bhattacharya-G092THXJ34.local>
This commit is contained in:
Sayak Bhattacharya
2025-06-07 19:46:13 +05:30
committed by GitHub
parent a88eebdec7
commit 8129260238
8 changed files with 223 additions and 131 deletions

View File

@ -263,6 +263,23 @@ impl ConnectorIntegration<CreateConnectorCustomer, ConnectorCustomerData, Paymen
.to_string() .to_string()
.into(), .into(),
)]; )];
if let Some(common_types::payments::SplitPaymentsRequest::StripeSplitPayment(
stripe_split_payment,
)) = &req.request.split_payments
{
if stripe_split_payment.charge_type
== PaymentChargeType::Stripe(StripeChargeType::Direct)
{
let mut customer_account_header = vec![(
STRIPE_COMPATIBLE_CONNECT_ACCOUNT.to_string(),
stripe_split_payment
.transfer_account_id
.clone()
.into_masked(),
)];
header.append(&mut customer_account_header);
}
}
let mut api_key = self.get_auth_header(&req.connector_auth_type)?; let mut api_key = self.get_auth_header(&req.connector_auth_type)?;
header.append(&mut api_key); header.append(&mut api_key);
Ok(header) Ok(header)
@ -389,6 +406,23 @@ impl ConnectorIntegration<PaymentMethodToken, PaymentMethodTokenizationData, Pay
CONTENT_TYPE.to_string(), CONTENT_TYPE.to_string(),
TokenizationType::get_content_type(self).to_string().into(), TokenizationType::get_content_type(self).to_string().into(),
)]; )];
if let Some(common_types::payments::SplitPaymentsRequest::StripeSplitPayment(
stripe_split_payment,
)) = &req.request.split_payments
{
if stripe_split_payment.charge_type
== PaymentChargeType::Stripe(StripeChargeType::Direct)
{
let mut customer_account_header = vec![(
STRIPE_COMPATIBLE_CONNECT_ACCOUNT.to_string(),
stripe_split_payment
.transfer_account_id
.clone()
.into_masked(),
)];
header.append(&mut customer_account_header);
}
}
let mut api_key = self.get_auth_header(&req.connector_auth_type)?; let mut api_key = self.get_auth_header(&req.connector_auth_type)?;
header.append(&mut api_key); header.append(&mut api_key);
Ok(header) Ok(header)
@ -400,9 +434,19 @@ impl ConnectorIntegration<PaymentMethodToken, PaymentMethodTokenizationData, Pay
fn get_url( fn get_url(
&self, &self,
_req: &TokenizationRouterData, req: &TokenizationRouterData,
connectors: &Connectors, connectors: &Connectors,
) -> CustomResult<String, ConnectorError> { ) -> CustomResult<String, ConnectorError> {
if matches!(
req.request.split_payments,
Some(common_types::payments::SplitPaymentsRequest::StripeSplitPayment(_))
) {
return Ok(format!(
"{}{}",
self.base_url(connectors),
"v1/payment_methods"
));
}
Ok(format!("{}{}", self.base_url(connectors), "v1/tokens")) Ok(format!("{}{}", self.base_url(connectors), "v1/tokens"))
} }
@ -526,7 +570,6 @@ impl ConnectorIntegration<Capture, PaymentsCaptureData, PaymentsResponseData> fo
connectors: &Connectors, connectors: &Connectors,
) -> CustomResult<String, ConnectorError> { ) -> CustomResult<String, ConnectorError> {
let id = req.request.connector_transaction_id.as_str(); let id = req.request.connector_transaction_id.as_str();
Ok(format!( Ok(format!(
"{}{}/{}/capture", "{}{}/{}/capture",
self.base_url(connectors), self.base_url(connectors),

View File

@ -37,7 +37,7 @@ use hyperswitch_domain_models::{
}, },
}; };
use hyperswitch_interfaces::{consts, errors::ConnectorError}; use hyperswitch_interfaces::{consts, errors::ConnectorError};
use masking::{ExposeInterface, ExposeOptionInterface, Mask, Maskable, PeekInterface, Secret}; use masking::{ExposeInterface, Mask, Maskable, PeekInterface, Secret};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_json::Value; use serde_json::Value;
use time::PrimitiveDateTime; use time::PrimitiveDateTime;
@ -170,7 +170,7 @@ pub struct PaymentIntentRequest {
pub meta_data: HashMap<String, String>, pub meta_data: HashMap<String, String>,
pub return_url: String, pub return_url: String,
pub confirm: bool, pub confirm: bool,
pub payment_method: Option<String>, pub payment_method: Option<Secret<String>>,
pub customer: Option<Secret<String>>, pub customer: Option<Secret<String>>,
#[serde(flatten)] #[serde(flatten)]
pub setup_mandate_details: Option<StripeMandateRequest>, pub setup_mandate_details: Option<StripeMandateRequest>,
@ -486,9 +486,28 @@ pub enum StripePaymentMethodData {
BankTransfer(StripeBankTransferData), BankTransfer(StripeBankTransferData),
} }
#[derive(Debug, Clone, Default, Eq, PartialEq, Serialize)]
pub struct StripeBillingAddressCardToken {
#[serde(rename = "billing_details[name]")]
pub name: Option<Secret<String>>,
#[serde(rename = "billing_details[email]")]
pub email: Option<Email>,
#[serde(rename = "billing_details[phone]")]
pub phone: Option<Secret<String>>,
#[serde(rename = "billing_details[address][line1]")]
pub address_line1: Option<Secret<String>>,
#[serde(rename = "billing_details[address][line2]")]
pub address_line2: Option<Secret<String>>,
#[serde(rename = "billing_details[address][state]")]
pub state: Option<Secret<String>>,
#[serde(rename = "billing_details[address][city]")]
pub city: Option<String>,
}
// Struct to call the Stripe tokens API to create a PSP token for the card details provided // Struct to call the Stripe tokens API to create a PSP token for the card details provided
#[derive(Debug, Eq, PartialEq, Serialize)] #[derive(Debug, Eq, PartialEq, Serialize)]
pub struct StripeCardToken { pub struct StripeCardToken {
#[serde(rename = "type")]
pub payment_method_type: Option<StripePaymentMethodType>,
#[serde(rename = "card[number]")] #[serde(rename = "card[number]")]
pub token_card_number: cards::CardNumber, pub token_card_number: cards::CardNumber,
#[serde(rename = "card[exp_month]")] #[serde(rename = "card[exp_month]")]
@ -497,6 +516,8 @@ pub struct StripeCardToken {
pub token_card_exp_year: Secret<String>, pub token_card_exp_year: Secret<String>,
#[serde(rename = "card[cvc]")] #[serde(rename = "card[cvc]")]
pub token_card_cvc: Secret<String>, pub token_card_cvc: Secret<String>,
#[serde(flatten)]
pub billing: StripeBillingAddressCardToken,
} }
#[derive(Debug, Eq, PartialEq, Serialize)] #[derive(Debug, Eq, PartialEq, Serialize)]
@ -1642,80 +1663,51 @@ impl TryFrom<(&PaymentsAuthorizeRouterData, MinorUnit)> for PaymentIntentRequest
type Error = error_stack::Report<ConnectorError>; type Error = error_stack::Report<ConnectorError>;
fn try_from(data: (&PaymentsAuthorizeRouterData, MinorUnit)) -> Result<Self, Self::Error> { fn try_from(data: (&PaymentsAuthorizeRouterData, MinorUnit)) -> Result<Self, Self::Error> {
let item = data.0; let item = data.0;
let payment_method_token = match &item.request.split_payments {
Some(common_types::payments::SplitPaymentsRequest::StripeSplitPayment(_)) => {
match item.payment_method_token.clone() {
Some(PaymentMethodToken::Token(secret)) => Some(secret),
_ => None,
}
}
_ => None,
};
let amount = data.1; let amount = data.1;
let order_id = item.connector_request_reference_id.clone(); let order_id = item.connector_request_reference_id.clone();
let shipping_address = match item.get_optional_shipping() { let shipping_address = if payment_method_token.is_some() {
Some(shipping_details) => { None
let shipping_address = shipping_details.address.as_ref(); } else {
shipping_address.and_then(|shipping_detail| { Some(StripeShippingAddress {
shipping_detail city: item.get_optional_shipping_city(),
.first_name country: item.get_optional_shipping_country(),
.as_ref() line1: item.get_optional_shipping_line1(),
.map(|first_name| StripeShippingAddress { line2: item.get_optional_shipping_line2(),
city: shipping_address.and_then(|a| a.city.clone()), zip: item.get_optional_shipping_zip(),
country: shipping_address.and_then(|a| a.country), state: item.get_optional_shipping_state(),
line1: shipping_address.and_then(|a| a.line1.clone()), name: item.get_optional_shipping_full_name(),
line2: shipping_address.and_then(|a| a.line2.clone()), phone: item.get_optional_shipping_phone_number(),
zip: shipping_address.and_then(|a| a.zip.clone()),
state: shipping_address.and_then(|a| a.state.clone()),
name: format!(
"{} {}",
first_name.clone().expose(),
shipping_detail
.last_name
.clone()
.expose_option()
.unwrap_or_default()
)
.into(),
phone: shipping_details.phone.as_ref().map(|p| {
format!(
"{}{}",
p.country_code.clone().unwrap_or_default(),
p.number.clone().expose_option().unwrap_or_default()
)
.into()
}),
}) })
})
}
None => None,
}; };
let billing_address = match item.get_optional_billing() { let billing_address = if payment_method_token.is_some() {
Some(billing_details) => { None
let billing_address = billing_details.address.as_ref(); } else {
StripeBillingAddress { Some(StripeBillingAddress {
city: billing_address.and_then(|a| a.city.clone()), city: item.get_optional_billing_city(),
country: billing_address.and_then(|a| a.country), country: item.get_optional_billing_country(),
address_line1: billing_address.and_then(|a| a.line1.clone()), address_line1: item.get_optional_billing_line1(),
address_line2: billing_address.and_then(|a| a.line2.clone()), address_line2: item.get_optional_billing_line2(),
zip_code: billing_address.and_then(|a| a.zip.clone()), zip_code: item.get_optional_billing_zip(),
state: billing_address.and_then(|a| a.state.clone()), state: item.get_optional_billing_state(),
name: billing_address.and_then(|a| { name: item.get_optional_billing_full_name(),
a.first_name.as_ref().map(|first_name| { email: item.get_optional_billing_email(),
format!( phone: item.get_optional_billing_phone_number(),
"{} {}",
first_name.clone().expose(),
a.last_name.clone().expose_option().unwrap_or_default()
)
.into()
}) })
}),
email: billing_details.email.clone(),
phone: billing_details.phone.as_ref().map(|p| {
format!(
"{}{}",
p.country_code.clone().unwrap_or_default(),
p.number.clone().expose_option().unwrap_or_default()
)
.into()
}),
}
}
None => StripeBillingAddress::default(),
}; };
let mut payment_method_options = None; let mut payment_method_options = None;
let ( let (
@ -1724,7 +1716,9 @@ impl TryFrom<(&PaymentsAuthorizeRouterData, MinorUnit)> for PaymentIntentRequest
billing_address, billing_address,
payment_method_types, payment_method_types,
setup_future_usage, setup_future_usage,
) = { ) = if payment_method_token.is_some() {
(None, None, StripeBillingAddress::default(), None, None)
} else {
match item match item
.request .request
.mandate_id .mandate_id
@ -1812,7 +1806,11 @@ impl TryFrom<(&PaymentsAuthorizeRouterData, MinorUnit)> for PaymentIntentRequest
&item.request, &item.request,
), ),
), ),
billing_address, billing_address.ok_or_else(|| {
ConnectorError::MissingRequiredField {
field_name: "billing_address",
}
})?,
)?; )?;
validate_shipping_address_against_payment_method( validate_shipping_address_against_payment_method(
@ -1831,6 +1829,7 @@ impl TryFrom<(&PaymentsAuthorizeRouterData, MinorUnit)> for PaymentIntentRequest
} }
}; };
if payment_method_token.is_none() {
payment_data = match item.request.payment_method_data { payment_data = match item.request.payment_method_data {
PaymentMethodData::Wallet(WalletData::ApplePay(_)) => { PaymentMethodData::Wallet(WalletData::ApplePay(_)) => {
let payment_method_token = item let payment_method_token = item
@ -1863,6 +1862,9 @@ impl TryFrom<(&PaymentsAuthorizeRouterData, MinorUnit)> for PaymentIntentRequest
)) ))
} }
_ => payment_data, _ => payment_data,
}
} else {
payment_data = None
}; };
let setup_mandate_details = item let setup_mandate_details = item
@ -1932,7 +1934,7 @@ impl TryFrom<(&PaymentsAuthorizeRouterData, MinorUnit)> for PaymentIntentRequest
// We pass browser_info only when payment_data exists. // We pass browser_info only when payment_data exists.
// Hence, we're pass Null during recurring payments as payment_method_data[type] is not passed // Hence, we're pass Null during recurring payments as payment_method_data[type] is not passed
let browser_info = if payment_data.is_some() { let browser_info = if payment_data.is_some() && payment_method_token.is_none() {
item.request item.request
.browser_info .browser_info
.clone() .clone()
@ -1941,11 +1943,10 @@ impl TryFrom<(&PaymentsAuthorizeRouterData, MinorUnit)> for PaymentIntentRequest
None None
}; };
let (charges, customer) = match &item.request.split_payments { let charges = match &item.request.split_payments {
Some(common_types::payments::SplitPaymentsRequest::StripeSplitPayment( Some(common_types::payments::SplitPaymentsRequest::StripeSplitPayment(
stripe_split_payment, stripe_split_payment,
)) => { )) => match &stripe_split_payment.charge_type {
let charges = match &stripe_split_payment.charge_type {
PaymentChargeType::Stripe(charge_type) => match charge_type { PaymentChargeType::Stripe(charge_type) => match charge_type {
StripeChargeType::Direct => Some(IntentCharges { StripeChargeType::Direct => Some(IntentCharges {
application_fee_amount: stripe_split_payment.application_fees, application_fee_amount: stripe_split_payment.application_fees,
@ -1958,14 +1959,24 @@ impl TryFrom<(&PaymentsAuthorizeRouterData, MinorUnit)> for PaymentIntentRequest
), ),
}), }),
}, },
}; },
(charges, None)
}
Some(common_types::payments::SplitPaymentsRequest::AdyenSplitPayment(_)) Some(common_types::payments::SplitPaymentsRequest::AdyenSplitPayment(_))
| Some(common_types::payments::SplitPaymentsRequest::XenditSplitPayment(_)) | Some(common_types::payments::SplitPaymentsRequest::XenditSplitPayment(_))
| None => (None, item.connector_customer.to_owned().map(Secret::new)), | None => None,
}; };
let pm = match (payment_method, payment_method_token.clone()) {
(Some(method), _) => Some(Secret::new(method)),
(None, Some(token)) => Some(token),
(None, None) => None,
};
let customer_id = item.connector_customer.clone().ok_or_else(|| {
ConnectorError::MissingRequiredField {
field_name: "connector_customer",
}
})?;
Ok(Self { Ok(Self {
amount, //hopefully we don't loose some cents here amount, //hopefully we don't loose some cents here
currency: item.request.currency.to_string(), //we need to copy the value and not transfer ownership currency: item.request.currency.to_string(), //we need to copy the value and not transfer ownership
@ -1984,8 +1995,8 @@ impl TryFrom<(&PaymentsAuthorizeRouterData, MinorUnit)> for PaymentIntentRequest
capture_method: StripeCaptureMethod::from(item.request.capture_method), capture_method: StripeCaptureMethod::from(item.request.capture_method),
payment_data, payment_data,
payment_method_options, payment_method_options,
payment_method, payment_method: pm,
customer, customer: Some(Secret::new(customer_id)),
setup_mandate_details, setup_mandate_details,
off_session: item.request.off_session, off_session: item.request.off_session,
setup_future_usage, setup_future_usage,
@ -2076,14 +2087,26 @@ impl TryFrom<&SetupMandateRouterData> for SetupIntentRequest {
impl TryFrom<&TokenizationRouterData> for TokenRequest { impl TryFrom<&TokenizationRouterData> for TokenRequest {
type Error = error_stack::Report<ConnectorError>; type Error = error_stack::Report<ConnectorError>;
fn try_from(item: &TokenizationRouterData) -> Result<Self, Self::Error> { fn try_from(item: &TokenizationRouterData) -> Result<Self, Self::Error> {
let billing_address = StripeBillingAddressCardToken {
name: item.get_optional_billing_full_name(),
email: item.get_optional_billing_email(),
phone: item.get_optional_billing_phone_number(),
address_line1: item.get_optional_billing_line1(),
address_line2: item.get_optional_billing_line2(),
city: item.get_optional_billing_city(),
state: item.get_optional_billing_state(),
};
// Card flow for tokenization is handled separately because of API contact difference // Card flow for tokenization is handled separately because of API contact difference
let request_payment_data = match &item.request.payment_method_data { let request_payment_data = match &item.request.payment_method_data {
PaymentMethodData::Card(card_details) => { PaymentMethodData::Card(card_details) => {
StripePaymentMethodData::CardToken(StripeCardToken { StripePaymentMethodData::CardToken(StripeCardToken {
payment_method_type: Some(StripePaymentMethodType::Card),
token_card_number: card_details.card_number.clone(), token_card_number: card_details.card_number.clone(),
token_card_exp_month: card_details.card_exp_month.clone(), token_card_exp_month: card_details.card_exp_month.clone(),
token_card_exp_year: card_details.card_exp_year.clone(), token_card_exp_year: card_details.card_exp_year.clone(),
token_card_cvc: card_details.card_cvc.clone(), token_card_cvc: card_details.card_cvc.clone(),
billing: billing_address,
}) })
} }
_ => { _ => {
@ -3327,7 +3350,7 @@ pub struct StripeShippingAddress {
#[serde(rename = "shipping[address][state]")] #[serde(rename = "shipping[address][state]")]
pub state: Option<Secret<String>>, pub state: Option<Secret<String>>,
#[serde(rename = "shipping[name]")] #[serde(rename = "shipping[name]")]
pub name: Secret<String>, pub name: Option<Secret<String>>,
#[serde(rename = "shipping[phone]")] #[serde(rename = "shipping[phone]")]
pub phone: Option<Secret<String>>, pub phone: Option<Secret<String>>,
} }
@ -3593,10 +3616,9 @@ impl<F, T> TryFrom<ResponseRouterData<F, StripeTokenResponse, T, PaymentsRespons
fn try_from( fn try_from(
item: ResponseRouterData<F, StripeTokenResponse, T, PaymentsResponseData>, item: ResponseRouterData<F, StripeTokenResponse, T, PaymentsResponseData>,
) -> Result<Self, Self::Error> { ) -> Result<Self, Self::Error> {
let token = item.response.id.clone().expose();
Ok(Self { Ok(Self {
response: Ok(PaymentsResponseData::TokenizationResponse { response: Ok(PaymentsResponseData::TokenizationResponse { token }),
token: item.response.id.expose(),
}),
..item.data ..item.data
}) })
} }
@ -4392,7 +4414,7 @@ mod test_validate_shipping_address_against_payment_method {
zip: Option<String>, zip: Option<String>,
) -> StripeShippingAddress { ) -> StripeShippingAddress {
StripeShippingAddress { StripeShippingAddress {
name: Secret::new(name), name: Some(Secret::new(name)),
line1: line1.map(Secret::new), line1: line1.map(Secret::new),
country, country,
zip: zip.map(Secret::new), zip: zip.map(Secret::new),

View File

@ -177,6 +177,7 @@ pub struct ConnectorCustomerData {
pub name: Option<Secret<String>>, pub name: Option<Secret<String>>,
pub preprocessing_id: Option<String>, pub preprocessing_id: Option<String>,
pub payment_method_data: Option<PaymentMethodData>, pub payment_method_data: Option<PaymentMethodData>,
pub split_payments: Option<common_types::payments::SplitPaymentsRequest>,
} }
impl TryFrom<SetupMandateRequestData> for ConnectorCustomerData { impl TryFrom<SetupMandateRequestData> for ConnectorCustomerData {
@ -189,6 +190,7 @@ impl TryFrom<SetupMandateRequestData> for ConnectorCustomerData {
phone: None, phone: None,
name: None, name: None,
preprocessing_id: None, preprocessing_id: None,
split_payments: None,
}) })
} }
} }
@ -213,6 +215,7 @@ impl
phone: None, phone: None,
name: data.request.customer_name.clone(), name: data.request.customer_name.clone(),
preprocessing_id: data.preprocessing_id.clone(), preprocessing_id: data.preprocessing_id.clone(),
split_payments: data.request.split_payments.clone(),
}) })
} }
} }
@ -236,6 +239,7 @@ impl TryFrom<&RouterData<flows::Session, PaymentsSessionData, response_types::Pa
phone: None, phone: None,
name: data.request.customer_name.clone(), name: data.request.customer_name.clone(),
preprocessing_id: data.preprocessing_id.clone(), preprocessing_id: data.preprocessing_id.clone(),
split_payments: None,
}) })
} }
} }
@ -246,6 +250,7 @@ pub struct PaymentMethodTokenizationData {
pub browser_info: Option<BrowserInformation>, pub browser_info: Option<BrowserInformation>,
pub currency: storage_enums::Currency, pub currency: storage_enums::Currency,
pub amount: Option<i64>, pub amount: Option<i64>,
pub split_payments: Option<common_types::payments::SplitPaymentsRequest>,
} }
impl TryFrom<SetupMandateRequestData> for PaymentMethodTokenizationData { impl TryFrom<SetupMandateRequestData> for PaymentMethodTokenizationData {
@ -257,6 +262,7 @@ impl TryFrom<SetupMandateRequestData> for PaymentMethodTokenizationData {
browser_info: None, browser_info: None,
currency: data.currency, currency: data.currency,
amount: data.amount, amount: data.amount,
split_payments: None,
}) })
} }
} }
@ -271,6 +277,7 @@ impl<F> From<&RouterData<F, PaymentsAuthorizeData, response_types::PaymentsRespo
browser_info: None, browser_info: None,
currency: data.request.currency, currency: data.request.currency,
amount: Some(data.request.amount), amount: Some(data.request.amount),
split_payments: data.request.split_payments.clone(),
} }
} }
} }
@ -284,6 +291,7 @@ impl TryFrom<PaymentsAuthorizeData> for PaymentMethodTokenizationData {
browser_info: data.browser_info, browser_info: data.browser_info,
currency: data.currency, currency: data.currency,
amount: Some(data.amount), amount: Some(data.amount),
split_payments: data.split_payments.clone(),
}) })
} }
} }
@ -302,6 +310,7 @@ impl TryFrom<CompleteAuthorizeData> for PaymentMethodTokenizationData {
browser_info: data.browser_info, browser_info: data.browser_info,
currency: data.currency, currency: data.currency,
amount: Some(data.amount), amount: Some(data.amount),
split_payments: None,
}) })
} }
} }

View File

@ -3227,6 +3227,7 @@ async fn create_single_use_tokenization_flow(
browser_info: None, browser_info: None,
currency: api_models::enums::Currency::default(), currency: api_models::enums::Currency::default(),
amount: None, amount: None,
split_payments: None,
}; };
let payment_method_session_address = types::PaymentAddress::new( let payment_method_session_address = types::PaymentAddress::new(

View File

@ -5241,6 +5241,7 @@ async fn decide_payment_method_tokenize_action(
state: &SessionState, state: &SessionState,
connector_name: &str, connector_name: &str,
payment_method: storage::enums::PaymentMethod, payment_method: storage::enums::PaymentMethod,
payment_intent_data: payments::PaymentIntent,
pm_parent_token: Option<&str>, pm_parent_token: Option<&str>,
is_connector_tokenization_enabled: bool, is_connector_tokenization_enabled: bool,
apple_pay_flow: Option<domain::ApplePayFlow>, apple_pay_flow: Option<domain::ApplePayFlow>,
@ -5276,6 +5277,11 @@ async fn decide_payment_method_tokenize_action(
} }
} }
} }
} else if matches!(
payment_intent_data.split_payments,
Some(common_types::payments::SplitPaymentsRequest::StripeSplitPayment(_))
) {
Ok(TokenizationAction::TokenizeInConnector)
} else { } else {
match pm_parent_token { match pm_parent_token {
None => Ok(match (is_connector_tokenization_enabled, apple_pay_flow) { None => Ok(match (is_connector_tokenization_enabled, apple_pay_flow) {
@ -5445,6 +5451,7 @@ where
state, state,
&connector, &connector,
payment_method, payment_method,
payment_data.get_payment_intent().clone(),
payment_data.get_token(), payment_data.get_token(),
is_connector_tokenization_enabled, is_connector_tokenization_enabled,
apple_pay_flow, apple_pay_flow,

View File

@ -67,6 +67,7 @@ fn token_details() -> Option<types::PaymentMethodTokenizationData> {
browser_info: None, browser_info: None,
amount: None, amount: None,
currency: enums::Currency::USD, currency: enums::Currency::USD,
split_payments: None,
}) })
} }
@ -440,6 +441,7 @@ async fn should_fail_payment_for_incorrect_cvc() {
browser_info: None, browser_info: None,
amount: None, amount: None,
currency: enums::Currency::USD, currency: enums::Currency::USD,
split_payments: None,
}), }),
get_default_payment_info(None), get_default_payment_info(None),
) )
@ -471,6 +473,7 @@ async fn should_fail_payment_for_invalid_exp_month() {
browser_info: None, browser_info: None,
amount: None, amount: None,
currency: enums::Currency::USD, currency: enums::Currency::USD,
split_payments: None,
}), }),
get_default_payment_info(None), get_default_payment_info(None),
) )
@ -502,6 +505,7 @@ async fn should_fail_payment_for_incorrect_expiry_year() {
browser_info: None, browser_info: None,
amount: None, amount: None,
currency: enums::Currency::USD, currency: enums::Currency::USD,
split_payments: None,
}), }),
get_default_payment_info(None), get_default_payment_info(None),
) )

View File

@ -72,6 +72,7 @@ fn token_details() -> Option<types::PaymentMethodTokenizationData> {
browser_info: None, browser_info: None,
amount: None, amount: None,
currency: enums::Currency::USD, currency: enums::Currency::USD,
split_payments: None,
}) })
} }
@ -482,6 +483,7 @@ async fn should_fail_payment_for_incorrect_cvc() {
browser_info: None, browser_info: None,
amount: None, amount: None,
currency: enums::Currency::USD, currency: enums::Currency::USD,
split_payments: None,
}), }),
get_default_payment_info(connector_customer_id, None), get_default_payment_info(connector_customer_id, None),
) )
@ -520,6 +522,7 @@ async fn should_fail_payment_for_invalid_exp_month() {
browser_info: None, browser_info: None,
amount: None, amount: None,
currency: enums::Currency::USD, currency: enums::Currency::USD,
split_payments: None,
}), }),
get_default_payment_info(connector_customer_id, None), get_default_payment_info(connector_customer_id, None),
) )
@ -558,6 +561,7 @@ async fn should_fail_payment_for_incorrect_expiry_year() {
browser_info: None, browser_info: None,
amount: None, amount: None,
currency: enums::Currency::USD, currency: enums::Currency::USD,
split_payments: None,
}), }),
get_default_payment_info(connector_customer_id, None), get_default_payment_info(connector_customer_id, None),
) )

View File

@ -1107,6 +1107,7 @@ impl Default for CustomerType {
phone: None, phone: None,
name: None, name: None,
preprocessing_id: None, preprocessing_id: None,
split_payments: None,
}; };
Self(data) Self(data)
} }
@ -1119,6 +1120,7 @@ impl Default for TokenType {
browser_info: None, browser_info: None,
amount: Some(100), amount: Some(100),
currency: enums::Currency::USD, currency: enums::Currency::USD,
split_payments: None,
}; };
Self(data) Self(data)
} }