mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-29 00:49:42 +08:00
feat(core): [Stripe] add bank debits payment method to stripe (#906)
This commit is contained in:
@ -409,11 +409,14 @@ pub enum PaymentExperience {
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum PaymentMethodType {
|
||||
Ach,
|
||||
Affirm,
|
||||
AfterpayClearpay,
|
||||
AliPay,
|
||||
ApplePay,
|
||||
Bacs,
|
||||
BancontactCard,
|
||||
Becs,
|
||||
Blik,
|
||||
Credit,
|
||||
CryptoCurrency,
|
||||
@ -432,6 +435,7 @@ pub enum PaymentMethodType {
|
||||
PayBright,
|
||||
Paypal,
|
||||
Przelewy24,
|
||||
Sepa,
|
||||
Sofort,
|
||||
Swish,
|
||||
Trustly,
|
||||
@ -463,6 +467,7 @@ pub enum PaymentMethod {
|
||||
Wallet,
|
||||
BankRedirect,
|
||||
Crypto,
|
||||
BankDebit,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
|
||||
@ -462,13 +462,57 @@ pub enum PayLaterData {
|
||||
Walley {},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize, ToSchema)]
|
||||
#[derive(serde::Deserialize, serde::Serialize, Debug, Clone, ToSchema, Eq, PartialEq)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum BankDebitData {
|
||||
/// Payment Method data for Ach bank debit
|
||||
AchBankDebit {
|
||||
/// Billing details for bank debit
|
||||
billing_details: BankDebitBilling,
|
||||
/// Account number for ach bank debit payment
|
||||
#[schema(value_type = String, example = "000123456789")]
|
||||
account_number: Secret<String>,
|
||||
/// Routing number for ach bank debit payment
|
||||
#[schema(value_type = String, example = "110000000")]
|
||||
routing_number: Secret<String>,
|
||||
},
|
||||
SepaBankDebit {
|
||||
/// Billing details for bank debit
|
||||
billing_details: BankDebitBilling,
|
||||
/// International bank account number (iban) for SEPA
|
||||
#[schema(value_type = String, example = "DE89370400440532013000")]
|
||||
iban: Secret<String>,
|
||||
},
|
||||
BecsBankDebit {
|
||||
/// Billing details for bank debit
|
||||
billing_details: BankDebitBilling,
|
||||
/// Account number for Becs payment method
|
||||
#[schema(value_type = String, example = "000123456")]
|
||||
account_number: Secret<String>,
|
||||
/// Bank-State-Branch (bsb) number
|
||||
#[schema(value_type = String, example = "000000")]
|
||||
bsb_number: Secret<String>,
|
||||
},
|
||||
BacsBankDebit {
|
||||
/// Billing details for bank debit
|
||||
billing_details: BankDebitBilling,
|
||||
/// Account number for Bacs payment method
|
||||
#[schema(value_type = String, example = "00012345")]
|
||||
account_number: Secret<String>,
|
||||
/// Sort code for Bacs payment method
|
||||
#[schema(value_type = String, example = "108800")]
|
||||
sort_code: Secret<String>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize, ToSchema)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum PaymentMethodData {
|
||||
Card(Card),
|
||||
Wallet(WalletData),
|
||||
PayLater(PayLaterData),
|
||||
BankRedirect(BankRedirectData),
|
||||
BankDebit(BankDebitData),
|
||||
Crypto(CryptoData),
|
||||
}
|
||||
|
||||
@ -485,6 +529,7 @@ pub enum AdditionalPaymentData {
|
||||
Wallet {},
|
||||
PayLater {},
|
||||
Crypto {},
|
||||
BankDebit {},
|
||||
}
|
||||
|
||||
impl From<&PaymentMethodData> for AdditionalPaymentData {
|
||||
@ -509,6 +554,7 @@ impl From<&PaymentMethodData> for AdditionalPaymentData {
|
||||
PaymentMethodData::Wallet(_) => Self::Wallet {},
|
||||
PaymentMethodData::PayLater(_) => Self::PayLater {},
|
||||
PaymentMethodData::Crypto(_) => Self::Crypto {},
|
||||
PaymentMethodData::BankDebit(_) => Self::BankDebit {},
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -607,6 +653,18 @@ pub struct BankRedirectBilling {
|
||||
pub billing_name: Secret<String>,
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize, serde::Serialize, Debug, Clone, ToSchema, Eq, PartialEq)]
|
||||
pub struct BankDebitBilling {
|
||||
/// The billing name for bank debits
|
||||
#[schema(value_type = String, example = "John Doe")]
|
||||
pub name: Secret<String>,
|
||||
/// The billing email for bank debits
|
||||
#[schema(value_type = String, example = "example@example.com")]
|
||||
pub email: Secret<String, pii::Email>,
|
||||
/// The billing address for bank debits
|
||||
pub address: Option<AddressDetails>,
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum WalletData {
|
||||
@ -722,6 +780,7 @@ pub enum PaymentMethodDataResponse {
|
||||
Paypal,
|
||||
BankRedirect(BankRedirectData),
|
||||
Crypto(CryptoData),
|
||||
BankDebit(BankDebitData),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, ToSchema)]
|
||||
@ -1137,7 +1196,7 @@ pub struct PaymentListResponse {
|
||||
pub data: Vec<PaymentsResponse>,
|
||||
}
|
||||
|
||||
#[derive(Setter, Clone, Default, Debug, Eq, PartialEq, serde::Serialize)]
|
||||
#[derive(Setter, Clone, Default, Debug, serde::Serialize)]
|
||||
pub struct VerifyResponse {
|
||||
pub verify_id: Option<String>,
|
||||
pub merchant_id: Option<String>,
|
||||
@ -1262,6 +1321,7 @@ impl From<PaymentMethodData> for PaymentMethodDataResponse {
|
||||
Self::BankRedirect(bank_redirect_data)
|
||||
}
|
||||
PaymentMethodData::Crypto(crpto_data) => Self::Crypto(crpto_data),
|
||||
PaymentMethodData::BankDebit(bank_debit_data) => Self::BankDebit(bank_debit_data),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -111,11 +111,14 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for AciPaymentsRequest {
|
||||
api::PaymentMethodData::PayLater(_) => PaymentDetails::Klarna,
|
||||
api::PaymentMethodData::Wallet(_) => PaymentDetails::Wallet,
|
||||
api::PaymentMethodData::BankRedirect(_) => PaymentDetails::BankRedirect,
|
||||
api::PaymentMethodData::Crypto(_) => Err(errors::ConnectorError::NotSupported {
|
||||
payment_method: format!("{:?}", item.payment_method),
|
||||
connector: "Aci",
|
||||
payment_experience: api_models::enums::PaymentExperience::RedirectToUrl.to_string(),
|
||||
})?,
|
||||
api::PaymentMethodData::Crypto(_) | api::PaymentMethodData::BankDebit(_) => {
|
||||
Err(errors::ConnectorError::NotSupported {
|
||||
payment_method: format!("{:?}", item.payment_method),
|
||||
connector: "Aci",
|
||||
payment_experience: api_models::enums::PaymentExperience::RedirectToUrl
|
||||
.to_string(),
|
||||
})?
|
||||
}
|
||||
};
|
||||
|
||||
let auth = AciAuthType::try_from(&item.connector_auth_type)?;
|
||||
|
||||
@ -87,11 +87,14 @@ impl TryFrom<api_models::payments::PaymentMethodData> for PaymentDetails {
|
||||
api::PaymentMethodData::PayLater(_) => Ok(Self::Klarna),
|
||||
api::PaymentMethodData::Wallet(_) => Ok(Self::Wallet),
|
||||
api::PaymentMethodData::BankRedirect(_) => Ok(Self::BankRedirect),
|
||||
api::PaymentMethodData::Crypto(_) => Err(errors::ConnectorError::NotSupported {
|
||||
payment_method: format!("{value:?}"),
|
||||
connector: "AuthorizeDotNet",
|
||||
payment_experience: api_models::enums::PaymentExperience::RedirectToUrl.to_string(),
|
||||
})?,
|
||||
api::PaymentMethodData::Crypto(_) | api::PaymentMethodData::BankDebit(_) => {
|
||||
Err(errors::ConnectorError::NotSupported {
|
||||
payment_method: format!("{value:?}"),
|
||||
connector: "AuthorizeDotNet",
|
||||
payment_experience: api_models::enums::PaymentExperience::RedirectToUrl
|
||||
.to_string(),
|
||||
})?
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
use api_models::{self, enums as api_enums, payments};
|
||||
use base64::Engine;
|
||||
use common_utils::{fp_utils, pii::Email};
|
||||
use common_utils::{fp_utils, pii};
|
||||
use error_stack::{IntoReport, ResultExt};
|
||||
use masking::ExposeInterface;
|
||||
use masking::{ExposeInterface, ExposeOptionInterface, Secret};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use url::Url;
|
||||
use uuid::Uuid;
|
||||
@ -10,7 +10,6 @@ use uuid::Uuid;
|
||||
use crate::{
|
||||
consts,
|
||||
core::errors,
|
||||
pii::{self, ExposeOptionInterface, Secret},
|
||||
services,
|
||||
types::{self, api, storage::enums},
|
||||
utils::OptionExt,
|
||||
@ -63,6 +62,22 @@ pub enum Auth3ds {
|
||||
Any,
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Serialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum StripeMandateType {
|
||||
Online,
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Serialize)]
|
||||
pub struct StripeMandateRequest {
|
||||
#[serde(rename = "mandate_data[customer_acceptance][type]")]
|
||||
pub mandate_type: StripeMandateType,
|
||||
#[serde(rename = "mandate_data[customer_acceptance][online][ip_address]")]
|
||||
pub ip_address: Secret<String, pii::IpAddress>,
|
||||
#[serde(rename = "mandate_data[customer_acceptance][online][user_agent]")]
|
||||
pub user_agent: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Serialize)]
|
||||
pub struct PaymentIntentRequest {
|
||||
pub amount: i64, //amount in cents, hence passed as integer
|
||||
@ -78,6 +93,8 @@ pub struct PaymentIntentRequest {
|
||||
pub return_url: String,
|
||||
pub confirm: bool,
|
||||
pub mandate: Option<String>,
|
||||
#[serde(flatten)]
|
||||
pub setup_mandate_details: Option<StripeMandateRequest>,
|
||||
pub description: Option<String>,
|
||||
#[serde(flatten)]
|
||||
pub shipping: StripeShippingAddress,
|
||||
@ -198,6 +215,47 @@ pub struct StripeBankRedirectData {
|
||||
pub bank_specific_data: Option<BankSpecificData>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Serialize)]
|
||||
#[serde(tag = "payment_method_data[type]")]
|
||||
pub enum BankDebitData {
|
||||
#[serde(rename = "us_bank_account")]
|
||||
Ach {
|
||||
#[serde(rename = "payment_method_data[us_bank_account][account_holder_type]")]
|
||||
account_holder_type: String,
|
||||
#[serde(rename = "payment_method_data[us_bank_account][account_number]")]
|
||||
account_number: Secret<String>,
|
||||
#[serde(rename = "payment_method_data[us_bank_account][routing_number]")]
|
||||
routing_number: Secret<String>,
|
||||
},
|
||||
#[serde(rename = "sepa_debit")]
|
||||
Sepa {
|
||||
#[serde(rename = "payment_method_data[sepa_debit][iban]")]
|
||||
iban: Secret<String>,
|
||||
},
|
||||
#[serde(rename = "au_becs_debit")]
|
||||
Becs {
|
||||
#[serde(rename = "payment_method_data[au_becs_debit][account_number]")]
|
||||
account_number: Secret<String>,
|
||||
#[serde(rename = "payment_method_data[au_becs_debit][bsb_number]")]
|
||||
bsb_number: Secret<String>,
|
||||
},
|
||||
#[serde(rename = "bacs_debit")]
|
||||
Bacs {
|
||||
#[serde(rename = "payment_method_data[bacs_debit][account_number]")]
|
||||
account_number: Secret<String>,
|
||||
#[serde(rename = "payment_method_data[bacs_debit][sort_code]")]
|
||||
sort_code: Secret<String>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Serialize)]
|
||||
pub struct StripeBankDebitData {
|
||||
#[serde(rename = "payment_method_types[]")]
|
||||
pub payment_method_types: StripePaymentMethodType,
|
||||
#[serde(flatten)]
|
||||
pub bank_specific_data: BankDebitData,
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Serialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum StripePaymentMethodData {
|
||||
@ -205,6 +263,7 @@ pub enum StripePaymentMethodData {
|
||||
PayLater(StripePayLaterData),
|
||||
Wallet(StripeWallet),
|
||||
BankRedirect(StripeBankRedirectData),
|
||||
BankDebit(StripeBankDebitData),
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Serialize)]
|
||||
@ -230,7 +289,7 @@ pub struct ApplepayPayment {
|
||||
pub payment_method_types: StripePaymentMethodType,
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Serialize, Clone)]
|
||||
#[derive(Debug, Eq, PartialEq, Serialize, Clone, Copy)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum StripePaymentMethodType {
|
||||
Card,
|
||||
@ -242,6 +301,14 @@ pub enum StripePaymentMethodType {
|
||||
Ideal,
|
||||
Sofort,
|
||||
ApplePay,
|
||||
#[serde(rename = "us_bank_account")]
|
||||
Ach,
|
||||
#[serde(rename = "sepa_debit")]
|
||||
Sepa,
|
||||
#[serde(rename = "au_becs_debit")]
|
||||
Becs,
|
||||
#[serde(rename = "bacs_debit")]
|
||||
Bacs,
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Serialize, Clone)]
|
||||
@ -472,6 +539,35 @@ impl TryFrom<(&api_models::payments::PayLaterData, StripePaymentMethodType)>
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&payments::BankDebitBilling> for StripeBillingAddress {
|
||||
fn from(item: &payments::BankDebitBilling) -> Self {
|
||||
Self {
|
||||
email: Some(item.email.to_owned()),
|
||||
country: item
|
||||
.address
|
||||
.as_ref()
|
||||
.and_then(|address| address.country.to_owned()),
|
||||
name: Some(item.name.to_owned()),
|
||||
city: item
|
||||
.address
|
||||
.as_ref()
|
||||
.and_then(|address| address.city.to_owned()),
|
||||
address_line1: item
|
||||
.address
|
||||
.as_ref()
|
||||
.and_then(|address| address.line1.to_owned()),
|
||||
address_line2: item
|
||||
.address
|
||||
.as_ref()
|
||||
.and_then(|address| address.line2.to_owned()),
|
||||
zip_code: item
|
||||
.address
|
||||
.as_ref()
|
||||
.and_then(|address| address.zip.to_owned()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&payments::BankRedirectData> for StripeBillingAddress {
|
||||
type Error = errors::ConnectorError;
|
||||
|
||||
@ -514,6 +610,64 @@ fn get_bank_specific_data(
|
||||
}
|
||||
}
|
||||
|
||||
fn get_bank_debit_data(
|
||||
bank_debit_data: &payments::BankDebitData,
|
||||
) -> (StripePaymentMethodType, BankDebitData, StripeBillingAddress) {
|
||||
match bank_debit_data {
|
||||
payments::BankDebitData::AchBankDebit {
|
||||
billing_details,
|
||||
account_number,
|
||||
routing_number,
|
||||
} => {
|
||||
let ach_data = BankDebitData::Ach {
|
||||
account_holder_type: "individual".to_string(),
|
||||
account_number: account_number.to_owned(),
|
||||
routing_number: routing_number.to_owned(),
|
||||
};
|
||||
|
||||
let billing_data = StripeBillingAddress::from(billing_details);
|
||||
(StripePaymentMethodType::Ach, ach_data, billing_data)
|
||||
}
|
||||
payments::BankDebitData::SepaBankDebit {
|
||||
billing_details,
|
||||
iban,
|
||||
} => {
|
||||
let sepa_data = BankDebitData::Sepa {
|
||||
iban: iban.to_owned(),
|
||||
};
|
||||
|
||||
let billing_data = StripeBillingAddress::from(billing_details);
|
||||
(StripePaymentMethodType::Sepa, sepa_data, billing_data)
|
||||
}
|
||||
payments::BankDebitData::BecsBankDebit {
|
||||
billing_details,
|
||||
account_number,
|
||||
bsb_number,
|
||||
} => {
|
||||
let becs_data = BankDebitData::Becs {
|
||||
account_number: account_number.to_owned(),
|
||||
bsb_number: bsb_number.to_owned(),
|
||||
};
|
||||
|
||||
let billing_data = StripeBillingAddress::from(billing_details);
|
||||
(StripePaymentMethodType::Becs, becs_data, billing_data)
|
||||
}
|
||||
payments::BankDebitData::BacsBankDebit {
|
||||
billing_details,
|
||||
account_number,
|
||||
sort_code,
|
||||
} => {
|
||||
let bacs_data = BankDebitData::Bacs {
|
||||
account_number: account_number.to_owned(),
|
||||
sort_code: sort_code.to_owned(),
|
||||
};
|
||||
|
||||
let billing_data = StripeBillingAddress::from(billing_details);
|
||||
(StripePaymentMethodType::Bacs, bacs_data, billing_data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn create_stripe_payment_method(
|
||||
pm_type: Option<&enums::PaymentMethodType>,
|
||||
experience: Option<&enums::PaymentExperience>,
|
||||
@ -558,13 +712,12 @@ fn create_stripe_payment_method(
|
||||
|
||||
let stripe_pm_type = infer_stripe_pay_later_type(pm_type, pm_experience)?;
|
||||
|
||||
let billing_address =
|
||||
StripeBillingAddress::try_from((pay_later_data, stripe_pm_type.clone()))?;
|
||||
let billing_address = StripeBillingAddress::try_from((pay_later_data, stripe_pm_type))?;
|
||||
|
||||
Ok((
|
||||
StripePaymentMethodData::PayLater(StripePayLaterData {
|
||||
payment_method_types: stripe_pm_type.clone(),
|
||||
payment_method_data_type: stripe_pm_type.clone(),
|
||||
payment_method_types: stripe_pm_type,
|
||||
payment_method_data_type: stripe_pm_type,
|
||||
}),
|
||||
stripe_pm_type,
|
||||
billing_address,
|
||||
@ -577,8 +730,8 @@ fn create_stripe_payment_method(
|
||||
let bank_name = get_bank_name(&pm_type, bank_redirect_data)?;
|
||||
Ok((
|
||||
StripePaymentMethodData::BankRedirect(StripeBankRedirectData {
|
||||
payment_method_types: pm_type.clone(),
|
||||
payment_method_data_type: pm_type.clone(),
|
||||
payment_method_types: pm_type,
|
||||
payment_method_data_type: pm_type,
|
||||
bank_name,
|
||||
bank_specific_data,
|
||||
}),
|
||||
@ -609,6 +762,16 @@ fn create_stripe_payment_method(
|
||||
)
|
||||
.into()),
|
||||
},
|
||||
payments::PaymentMethodData::BankDebit(bank_debit_data) => {
|
||||
let (pm_type, bank_debit_data, billing_address) = get_bank_debit_data(bank_debit_data);
|
||||
|
||||
let pm_data = StripePaymentMethodData::BankDebit(StripeBankDebitData {
|
||||
payment_method_types: pm_type,
|
||||
bank_specific_data: bank_debit_data,
|
||||
});
|
||||
|
||||
Ok((pm_data, pm_type, billing_address))
|
||||
}
|
||||
_ => Err(errors::ConnectorError::NotImplemented(
|
||||
"stripe does not support this payment method".to_string(),
|
||||
)
|
||||
@ -694,6 +857,22 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for PaymentIntentRequest {
|
||||
_ => payment_data,
|
||||
};
|
||||
|
||||
let setup_mandate_details =
|
||||
item.request
|
||||
.setup_mandate_details
|
||||
.as_ref()
|
||||
.and_then(|mandate_details| {
|
||||
mandate_details
|
||||
.customer_acceptance
|
||||
.online
|
||||
.as_ref()
|
||||
.map(|online_details| StripeMandateRequest {
|
||||
mandate_type: StripeMandateType::Online,
|
||||
ip_address: online_details.ip_address.to_owned(),
|
||||
user_agent: online_details.user_agent.to_owned(),
|
||||
})
|
||||
});
|
||||
|
||||
Ok(Self {
|
||||
amount: item.request.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
|
||||
@ -715,6 +894,7 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for PaymentIntentRequest {
|
||||
capture_method: StripeCaptureMethod::from(item.request.capture_method),
|
||||
payment_data,
|
||||
mandate,
|
||||
setup_mandate_details,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -881,12 +1061,9 @@ impl<F, T>
|
||||
fn try_from(
|
||||
item: types::ResponseRouterData<F, PaymentIntentResponse, T, types::PaymentsResponseData>,
|
||||
) -> Result<Self, Self::Error> {
|
||||
let redirection_data =
|
||||
item.response
|
||||
.next_action
|
||||
.map(|StripeNextActionResponse::RedirectToUrl(response)| {
|
||||
services::RedirectForm::from((response.url, services::Method::Get))
|
||||
});
|
||||
let redirection_data = item.response.next_action.map(|next_action_response| {
|
||||
services::RedirectForm::from((next_action_response.get_url(), services::Method::Get))
|
||||
});
|
||||
|
||||
let mandate_reference =
|
||||
item.response
|
||||
@ -929,11 +1106,16 @@ impl<F, T>
|
||||
types::PaymentsResponseData,
|
||||
>,
|
||||
) -> Result<Self, Self::Error> {
|
||||
let redirection_data = item.response.next_action.as_ref().map(
|
||||
|StripeNextActionResponse::RedirectToUrl(response)| {
|
||||
services::RedirectForm::from((response.url.clone(), services::Method::Get))
|
||||
},
|
||||
);
|
||||
let redirection_data = item
|
||||
.response
|
||||
.next_action
|
||||
.as_ref()
|
||||
.map(|next_action_response| {
|
||||
services::RedirectForm::from((
|
||||
next_action_response.get_url(),
|
||||
services::Method::Get,
|
||||
))
|
||||
});
|
||||
|
||||
let mandate_reference =
|
||||
item.response
|
||||
@ -949,7 +1131,11 @@ impl<F, T>
|
||||
| StripePaymentMethodOptions::Eps {}
|
||||
| StripePaymentMethodOptions::Giropay {}
|
||||
| StripePaymentMethodOptions::Ideal {}
|
||||
| StripePaymentMethodOptions::Sofort {} => None,
|
||||
| StripePaymentMethodOptions::Sofort {}
|
||||
| StripePaymentMethodOptions::Ach {}
|
||||
| StripePaymentMethodOptions::Bacs {}
|
||||
| StripePaymentMethodOptions::Becs {}
|
||||
| StripePaymentMethodOptions::Sepa {} => None,
|
||||
});
|
||||
|
||||
let error_res =
|
||||
@ -990,12 +1176,9 @@ impl<F, T>
|
||||
fn try_from(
|
||||
item: types::ResponseRouterData<F, SetupIntentResponse, T, types::PaymentsResponseData>,
|
||||
) -> Result<Self, Self::Error> {
|
||||
let redirection_data =
|
||||
item.response
|
||||
.next_action
|
||||
.map(|StripeNextActionResponse::RedirectToUrl(response)| {
|
||||
services::RedirectForm::from((response.url, services::Method::Get))
|
||||
});
|
||||
let redirection_data = item.response.next_action.map(|next_action_response| {
|
||||
services::RedirectForm::from((next_action_response.get_url(), services::Method::Get))
|
||||
});
|
||||
|
||||
let mandate_reference =
|
||||
item.response
|
||||
@ -1024,6 +1207,18 @@ impl<F, T>
|
||||
#[serde(rename_all = "snake_case", remote = "Self")]
|
||||
pub enum StripeNextActionResponse {
|
||||
RedirectToUrl(StripeRedirectToUrlResponse),
|
||||
VerifyWithMicrodeposits(StripeVerifyWithMicroDepositsResponse),
|
||||
}
|
||||
|
||||
impl StripeNextActionResponse {
|
||||
fn get_url(&self) -> Url {
|
||||
match self {
|
||||
Self::RedirectToUrl(redirect_to_url) => redirect_to_url.url.to_owned(),
|
||||
Self::VerifyWithMicrodeposits(verify_with_microdeposits) => {
|
||||
verify_with_microdeposits.hosted_verification_url.to_owned()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This impl is required because Stripe's response is of the below format, which is externally
|
||||
@ -1052,6 +1247,11 @@ pub struct StripeRedirectToUrlResponse {
|
||||
url: Url,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Deserialize)]
|
||||
pub struct StripeVerifyWithMicroDepositsResponse {
|
||||
hosted_verification_url: Url,
|
||||
}
|
||||
|
||||
// REFUND :
|
||||
// Type definition for Stripe RefundRequest
|
||||
|
||||
@ -1189,11 +1389,19 @@ pub struct StripeShippingAddress {
|
||||
#[derive(Debug, Default, Eq, PartialEq, Serialize)]
|
||||
pub struct StripeBillingAddress {
|
||||
#[serde(rename = "payment_method_data[billing_details][email]")]
|
||||
pub email: Option<Secret<String, Email>>,
|
||||
pub email: Option<Secret<String, pii::Email>>,
|
||||
#[serde(rename = "payment_method_data[billing_details][address][country]")]
|
||||
pub country: Option<api_enums::CountryCode>,
|
||||
#[serde(rename = "payment_method_data[billing_details][name]")]
|
||||
pub name: Option<Secret<String>>,
|
||||
#[serde(rename = "payment_method_data[billing_details][address][city]")]
|
||||
pub city: Option<String>,
|
||||
#[serde(rename = "payment_method_data[billing_details][address][line1]")]
|
||||
pub address_line1: Option<Secret<String>>,
|
||||
#[serde(rename = "payment_method_data[billing_details][address][line2]")]
|
||||
pub address_line2: Option<Secret<String>>,
|
||||
#[serde(rename = "payment_method_data[billing_details][address][postal_code]")]
|
||||
pub zip_code: Option<Secret<String>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, serde::Deserialize, Eq, PartialEq)]
|
||||
@ -1233,6 +1441,14 @@ pub enum StripePaymentMethodOptions {
|
||||
Giropay {},
|
||||
Ideal {},
|
||||
Sofort {},
|
||||
#[serde(rename = "us_bank_account")]
|
||||
Ach {},
|
||||
#[serde(rename = "sepa_debit")]
|
||||
Sepa {},
|
||||
#[serde(rename = "au_becs_debit")]
|
||||
Becs {},
|
||||
#[serde(rename = "bacs_debit")]
|
||||
Bacs {},
|
||||
}
|
||||
// #[derive(Deserialize, Debug, Clone, Eq, PartialEq)]
|
||||
// pub struct Card
|
||||
@ -1373,12 +1589,12 @@ impl
|
||||
}
|
||||
})),
|
||||
api::PaymentMethodData::PayLater(_) => Ok(Self::PayLater(StripePayLaterData {
|
||||
payment_method_types: pm_type.clone(),
|
||||
payment_method_types: pm_type,
|
||||
payment_method_data_type: pm_type,
|
||||
})),
|
||||
api::PaymentMethodData::BankRedirect(_) => {
|
||||
Ok(Self::BankRedirect(StripeBankRedirectData {
|
||||
payment_method_types: pm_type.clone(),
|
||||
payment_method_types: pm_type,
|
||||
payment_method_data_type: pm_type,
|
||||
bank_name: None,
|
||||
bank_specific_data: None,
|
||||
@ -1403,6 +1619,14 @@ impl
|
||||
}
|
||||
_ => Err(errors::ConnectorError::InvalidWallet.into()),
|
||||
},
|
||||
api::PaymentMethodData::BankDebit(bank_debit_data) => {
|
||||
let (pm_type, bank_data, _) = get_bank_debit_data(&bank_debit_data);
|
||||
|
||||
Ok(Self::BankDebit(StripeBankDebitData {
|
||||
payment_method_types: pm_type,
|
||||
bank_specific_data: bank_data,
|
||||
}))
|
||||
}
|
||||
api::PaymentMethodData::Crypto(_) => Err(errors::ConnectorError::NotSupported {
|
||||
payment_method: format!("{pm_type:?}"),
|
||||
connector: "Stripe",
|
||||
|
||||
@ -802,6 +802,7 @@ pub async fn make_pm_data<'a, F: Clone, R>(
|
||||
(pm @ Some(api::PaymentMethodData::PayLater(_)), _) => Ok(pm.to_owned()),
|
||||
(pm @ Some(api::PaymentMethodData::BankRedirect(_)), _) => Ok(pm.to_owned()),
|
||||
(pm @ Some(api::PaymentMethodData::Crypto(_)), _) => Ok(pm.to_owned()),
|
||||
(pm @ Some(api::PaymentMethodData::BankDebit(_)), _) => Ok(pm.to_owned()),
|
||||
(pm_opt @ Some(pm @ api::PaymentMethodData::Wallet(_)), _) => {
|
||||
let token = vault::Vault::store_payment_method_data_in_locker(
|
||||
state,
|
||||
|
||||
@ -155,6 +155,7 @@ Never share your secret api keys. Keep them guarded and secure.
|
||||
api_models::payments::Address,
|
||||
api_models::payments::BankRedirectData,
|
||||
api_models::payments::BankRedirectBilling,
|
||||
api_models::payments::BankRedirectBilling,
|
||||
api_models::payments::OrderDetails,
|
||||
api_models::payments::NextActionType,
|
||||
api_models::payments::Metadata,
|
||||
|
||||
@ -456,6 +456,7 @@ pub enum PaymentMethod {
|
||||
Wallet,
|
||||
BankRedirect,
|
||||
Crypto,
|
||||
BankDebit,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
@ -612,11 +613,14 @@ pub enum MandateStatus {
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum PaymentMethodType {
|
||||
Ach,
|
||||
Affirm,
|
||||
AfterpayClearpay,
|
||||
AliPay,
|
||||
ApplePay,
|
||||
Bacs,
|
||||
BancontactCard,
|
||||
Becs,
|
||||
Blik,
|
||||
Credit,
|
||||
CryptoCurrency,
|
||||
@ -635,6 +639,7 @@ pub enum PaymentMethodType {
|
||||
PayBright,
|
||||
Paypal,
|
||||
Przelewy24,
|
||||
Sepa,
|
||||
Sofort,
|
||||
Swish,
|
||||
Trustly,
|
||||
|
||||
Reference in New Issue
Block a user