mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-11-01 11:06:50 +08:00
feat: SEPA and BACS bank transfers through stripe (#930)
This commit is contained in:
committed by
GitHub
parent
53aa5ac92d
commit
cf000599dd
@ -205,6 +205,8 @@ pub struct ResponsePaymentMethodTypes {
|
|||||||
|
|
||||||
/// The Bank debit payment method information, if applicable for a payment method type.
|
/// The Bank debit payment method information, if applicable for a payment method type.
|
||||||
pub bank_debits: Option<BankDebitTypes>,
|
pub bank_debits: Option<BankDebitTypes>,
|
||||||
|
/// The Bank transfer payment method information, if applicable for a payment method type.
|
||||||
|
pub bank_transfers: Option<BankTransferTypes>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize, ToSchema)]
|
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize, ToSchema)]
|
||||||
@ -217,6 +219,13 @@ pub struct ResponsePaymentMethodsEnabled {
|
|||||||
pub payment_method_types: Vec<ResponsePaymentMethodTypes>,
|
pub payment_method_types: Vec<ResponsePaymentMethodTypes>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema, PartialEq, Eq)]
|
||||||
|
pub struct BankTransferTypes {
|
||||||
|
/// The list of eligible connectors for a given payment experience
|
||||||
|
#[schema(example = json!(["stripe", "adyen"]))]
|
||||||
|
pub eligible_connectors: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct ResponsePaymentMethodIntermediate {
|
pub struct ResponsePaymentMethodIntermediate {
|
||||||
pub payment_method_type: api_enums::PaymentMethodType,
|
pub payment_method_type: api_enums::PaymentMethodType,
|
||||||
|
|||||||
@ -724,13 +724,14 @@ pub enum BankRedirectData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
#[derive(Debug, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
pub struct AchBankTransferData {
|
pub struct AchBillingDetails {
|
||||||
pub billing_details: AchBillingDetails,
|
pub email: Email,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
#[derive(Debug, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
pub struct AchBillingDetails {
|
pub struct SepaAndBacsBillingDetails {
|
||||||
pub email: Email,
|
pub email: Email,
|
||||||
|
pub name: Secret<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize, ToSchema)]
|
#[derive(Debug, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize, ToSchema)]
|
||||||
@ -757,7 +758,16 @@ pub struct BankRedirectBilling {
|
|||||||
#[derive(Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)]
|
#[derive(Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
pub enum BankTransferData {
|
pub enum BankTransferData {
|
||||||
AchBankTransfer(AchBankTransferData),
|
AchBankTransfer {
|
||||||
|
billing_details: AchBillingDetails,
|
||||||
|
},
|
||||||
|
SepaBankTransfer {
|
||||||
|
billing_details: SepaAndBacsBillingDetails,
|
||||||
|
country: api_enums::CountryAlpha2,
|
||||||
|
},
|
||||||
|
BacsBankTransfer {
|
||||||
|
billing_details: SepaAndBacsBillingDetails,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Deserialize, serde::Serialize, Debug, Clone, ToSchema, Eq, PartialEq)]
|
#[derive(serde::Deserialize, serde::Serialize, Debug, Clone, ToSchema, Eq, PartialEq)]
|
||||||
@ -878,6 +888,7 @@ pub struct CardResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize)]
|
#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
pub enum PaymentMethodDataResponse {
|
pub enum PaymentMethodDataResponse {
|
||||||
#[serde(rename = "card")]
|
#[serde(rename = "card")]
|
||||||
Card(CardResponse),
|
Card(CardResponse),
|
||||||
@ -1071,10 +1082,34 @@ pub struct NextAction {
|
|||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
|
||||||
pub struct NextStepsRequirements {
|
pub struct NextStepsRequirements {
|
||||||
pub ach_credit_transfer: AchTransfer,
|
#[serde(flatten)]
|
||||||
|
pub bank_transfer_instructions: BankTransferInstructions,
|
||||||
pub receiver: ReceiverDetails,
|
pub receiver: ReceiverDetails,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
pub enum BankTransferInstructions {
|
||||||
|
AchCreditTransfer(Box<AchTransfer>),
|
||||||
|
SepaBankInstructions(Box<SepaBankTransferInstructions>),
|
||||||
|
BacsBankInstructions(Box<BacsBankTransferInstructions>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
|
pub struct SepaBankTransferInstructions {
|
||||||
|
pub account_holder_name: Secret<String>,
|
||||||
|
pub bic: Secret<String>,
|
||||||
|
pub country: String,
|
||||||
|
pub iban: Secret<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||||
|
pub struct BacsBankTransferInstructions {
|
||||||
|
pub account_holder_name: Secret<String>,
|
||||||
|
pub account_number: Secret<String>,
|
||||||
|
pub sort_code: Secret<String>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
|
||||||
pub struct AchTransfer {
|
pub struct AchTransfer {
|
||||||
pub account_number: Secret<String>,
|
pub account_number: Secret<String>,
|
||||||
@ -1085,8 +1120,9 @@ pub struct AchTransfer {
|
|||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
|
||||||
pub struct ReceiverDetails {
|
pub struct ReceiverDetails {
|
||||||
pub amount_received: i64,
|
amount_received: i64,
|
||||||
pub amount_charged: i64,
|
amount_charged: Option<i64>,
|
||||||
|
amount_remaining: Option<i64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Setter, Clone, Default, Debug, Eq, PartialEq, serde::Serialize, ToSchema)]
|
#[derive(Setter, Clone, Default, Debug, Eq, PartialEq, serde::Serialize, ToSchema)]
|
||||||
|
|||||||
@ -10,6 +10,7 @@ pub enum IncomingWebhookEvent {
|
|||||||
PaymentIntentFailure,
|
PaymentIntentFailure,
|
||||||
PaymentIntentSuccess,
|
PaymentIntentSuccess,
|
||||||
PaymentIntentProcessing,
|
PaymentIntentProcessing,
|
||||||
|
PaymentIntentPartiallyFunded,
|
||||||
PaymentActionRequired,
|
PaymentActionRequired,
|
||||||
EventNotSupported,
|
EventNotSupported,
|
||||||
SourceChargeable,
|
SourceChargeable,
|
||||||
@ -45,6 +46,7 @@ impl From<IncomingWebhookEvent> for WebhookFlow {
|
|||||||
IncomingWebhookEvent::PaymentIntentSuccess => Self::Payment,
|
IncomingWebhookEvent::PaymentIntentSuccess => Self::Payment,
|
||||||
IncomingWebhookEvent::PaymentIntentProcessing => Self::Payment,
|
IncomingWebhookEvent::PaymentIntentProcessing => Self::Payment,
|
||||||
IncomingWebhookEvent::PaymentActionRequired => Self::Payment,
|
IncomingWebhookEvent::PaymentActionRequired => Self::Payment,
|
||||||
|
IncomingWebhookEvent::PaymentIntentPartiallyFunded => Self::Payment,
|
||||||
IncomingWebhookEvent::EventNotSupported => Self::ReturnResponse,
|
IncomingWebhookEvent::EventNotSupported => Self::ReturnResponse,
|
||||||
IncomingWebhookEvent::RefundSuccess => Self::Refund,
|
IncomingWebhookEvent::RefundSuccess => Self::Refund,
|
||||||
IncomingWebhookEvent::RefundFailure => Self::Refund,
|
IncomingWebhookEvent::RefundFailure => Self::Refund,
|
||||||
|
|||||||
@ -686,9 +686,14 @@ impl
|
|||||||
match &req.request.payment_method_data {
|
match &req.request.payment_method_data {
|
||||||
api_models::payments::PaymentMethodData::BankTransfer(bank_transfer_data) => {
|
api_models::payments::PaymentMethodData::BankTransfer(bank_transfer_data) => {
|
||||||
match bank_transfer_data.deref() {
|
match bank_transfer_data.deref() {
|
||||||
api_models::payments::BankTransferData::AchBankTransfer(_) => {
|
api_models::payments::BankTransferData::AchBankTransfer { .. } => {
|
||||||
Ok(format!("{}{}", self.base_url(connectors), "v1/charges"))
|
Ok(format!("{}{}", self.base_url(connectors), "v1/charges"))
|
||||||
}
|
}
|
||||||
|
_ => Ok(format!(
|
||||||
|
"{}{}",
|
||||||
|
self.base_url(connectors),
|
||||||
|
"v1/payment_intents"
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => Ok(format!(
|
_ => Ok(format!(
|
||||||
@ -1682,9 +1687,6 @@ impl api::IncomingWebhook for Stripe {
|
|||||||
stripe::WebhookEventType::SourceChargeable => {
|
stripe::WebhookEventType::SourceChargeable => {
|
||||||
api::IncomingWebhookEvent::SourceChargeable
|
api::IncomingWebhookEvent::SourceChargeable
|
||||||
}
|
}
|
||||||
stripe::WebhookEventType::SourceTransactionCreated => {
|
|
||||||
api::IncomingWebhookEvent::SourceTransactionCreated
|
|
||||||
}
|
|
||||||
stripe::WebhookEventType::ChargeSucceeded => api::IncomingWebhookEvent::ChargeSucceeded,
|
stripe::WebhookEventType::ChargeSucceeded => api::IncomingWebhookEvent::ChargeSucceeded,
|
||||||
stripe::WebhookEventType::DisputeCreated => api::IncomingWebhookEvent::DisputeOpened,
|
stripe::WebhookEventType::DisputeCreated => api::IncomingWebhookEvent::DisputeOpened,
|
||||||
stripe::WebhookEventType::DisputeClosed => api::IncomingWebhookEvent::DisputeCancelled,
|
stripe::WebhookEventType::DisputeClosed => api::IncomingWebhookEvent::DisputeCancelled,
|
||||||
@ -1695,6 +1697,12 @@ impl api::IncomingWebhook for Stripe {
|
|||||||
.status
|
.status
|
||||||
.ok_or(errors::ConnectorError::WebhookEventTypeNotFound)?,
|
.ok_or(errors::ConnectorError::WebhookEventTypeNotFound)?,
|
||||||
)?,
|
)?,
|
||||||
|
stripe::WebhookEventType::PaymentIntentPartiallyFunded => {
|
||||||
|
api::IncomingWebhookEvent::PaymentIntentPartiallyFunded
|
||||||
|
}
|
||||||
|
stripe::WebhookEventType::PaymentIntentRequiresAction => {
|
||||||
|
api::IncomingWebhookEvent::PaymentActionRequired
|
||||||
|
}
|
||||||
_ => Err(errors::ConnectorError::WebhookEventTypeNotFound).into_report()?,
|
_ => Err(errors::ConnectorError::WebhookEventTypeNotFound).into_report()?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,7 +15,7 @@ use url::Url;
|
|||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
collect_missing_value_keys, consts,
|
collect_missing_value_keys, connector, consts,
|
||||||
core::errors,
|
core::errors,
|
||||||
services,
|
services,
|
||||||
types::{self, api, storage::enums, transformers::ForeignFrom},
|
types::{self, api, storage::enums, transformers::ForeignFrom},
|
||||||
@ -286,6 +286,61 @@ pub struct StripeBankRedirectData {
|
|||||||
pub bank_specific_data: Option<BankSpecificData>,
|
pub bank_specific_data: Option<BankSpecificData>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Eq, PartialEq, Serialize)]
|
||||||
|
pub struct AchBankTransferData {
|
||||||
|
#[serde(rename = "owner[email]")]
|
||||||
|
pub email: Email,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Eq, PartialEq, Serialize)]
|
||||||
|
pub struct BacsBankTransferData {
|
||||||
|
#[serde(rename = "payment_method_data[type]")]
|
||||||
|
pub payment_method_data_type: StripePaymentMethodType,
|
||||||
|
#[serde(rename = "payment_method_options[customer_balance][bank_transfer][type]")]
|
||||||
|
pub bank_transfer_type: BankTransferType,
|
||||||
|
#[serde(rename = "payment_method_options[customer_balance][funding_type]")]
|
||||||
|
pub balance_funding_type: BankTransferType,
|
||||||
|
#[serde(rename = "payment_method_types[0]")]
|
||||||
|
pub payment_method_type: StripePaymentMethodType,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Eq, PartialEq, Serialize)]
|
||||||
|
pub struct SepaBankTransferData {
|
||||||
|
#[serde(rename = "payment_method_data[type]")]
|
||||||
|
pub payment_method_data_type: StripePaymentMethodType,
|
||||||
|
#[serde(rename = "payment_method_options[customer_balance][bank_transfer][type]")]
|
||||||
|
pub bank_transfer_type: BankTransferType,
|
||||||
|
#[serde(rename = "payment_method_options[customer_balance][funding_type]")]
|
||||||
|
pub balance_funding_type: BankTransferType,
|
||||||
|
#[serde(rename = "payment_method_types[0]")]
|
||||||
|
pub payment_method_type: StripePaymentMethodType,
|
||||||
|
#[serde(
|
||||||
|
rename = "payment_method_options[customer_balance][bank_transfer][eu_bank_transfer][country]"
|
||||||
|
)]
|
||||||
|
pub country: api_models::enums::CountryAlpha2,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Eq, PartialEq, Serialize)]
|
||||||
|
pub struct StripeAchSourceRequest {
|
||||||
|
#[serde(rename = "type")]
|
||||||
|
pub transfer_type: StripePaymentMethodType,
|
||||||
|
#[serde(flatten)]
|
||||||
|
pub payment_method_data: AchBankTransferData,
|
||||||
|
pub currency: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove untagged when Deserialize is added
|
||||||
|
#[derive(Debug, Eq, PartialEq, Serialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum StripePaymentMethodData {
|
||||||
|
Card(StripeCardData),
|
||||||
|
PayLater(StripePayLaterData),
|
||||||
|
Wallet(StripeWallet),
|
||||||
|
BankRedirect(StripeBankRedirectData),
|
||||||
|
BankDebit(StripeBankDebitData),
|
||||||
|
BankTransfer(StripeBankTransferData),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Serialize)]
|
#[derive(Debug, Eq, PartialEq, Serialize)]
|
||||||
#[serde(tag = "payment_method_data[type]")]
|
#[serde(tag = "payment_method_data[type]")]
|
||||||
pub enum BankDebitData {
|
pub enum BankDebitData {
|
||||||
@ -332,24 +387,12 @@ pub struct BankTransferData {
|
|||||||
pub email: Email,
|
pub email: Email,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Serialize)]
|
|
||||||
pub struct StripeAchSourceRequest {
|
|
||||||
#[serde(rename = "type")]
|
|
||||||
pub transfer_type: StripePaymentMethodType,
|
|
||||||
#[serde(rename = "owner[email]")]
|
|
||||||
pub email: Email,
|
|
||||||
pub currency: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Serialize)]
|
#[derive(Debug, Eq, PartialEq, Serialize)]
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
pub enum StripePaymentMethodData {
|
pub enum StripeBankTransferData {
|
||||||
Card(StripeCardData),
|
AchBankTransfer(Box<AchBankTransferData>),
|
||||||
PayLater(StripePayLaterData),
|
SepaBankTransfer(Box<SepaBankTransferData>),
|
||||||
Wallet(StripeWallet),
|
BacsBankTransfers(Box<BacsBankTransferData>),
|
||||||
BankRedirect(StripeBankRedirectData),
|
|
||||||
BankDebit(StripeBankDebitData),
|
|
||||||
AchBankTransfer(BankTransferData),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Serialize)]
|
#[derive(Debug, Eq, PartialEq, Serialize)]
|
||||||
@ -445,6 +488,16 @@ pub enum StripePaymentMethodType {
|
|||||||
Alipay,
|
Alipay,
|
||||||
#[serde(rename = "p24")]
|
#[serde(rename = "p24")]
|
||||||
Przelewy24,
|
Przelewy24,
|
||||||
|
CustomerBalance,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Eq, PartialEq, Serialize, Clone)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
pub enum BankTransferType {
|
||||||
|
GbBankTransfer,
|
||||||
|
EuBankTransfer,
|
||||||
|
#[serde(rename = "bank_transfer")]
|
||||||
|
BankTransfers,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Serialize, Clone)]
|
#[derive(Debug, Eq, PartialEq, Serialize, Clone)]
|
||||||
@ -1011,13 +1064,63 @@ fn create_stripe_payment_method(
|
|||||||
}
|
}
|
||||||
payments::PaymentMethodData::BankTransfer(bank_transfer_data) => {
|
payments::PaymentMethodData::BankTransfer(bank_transfer_data) => {
|
||||||
match bank_transfer_data.deref() {
|
match bank_transfer_data.deref() {
|
||||||
payments::BankTransferData::AchBankTransfer(ach_bank_transfer_data) => Ok((
|
payments::BankTransferData::AchBankTransfer { billing_details } => Ok((
|
||||||
StripePaymentMethodData::AchBankTransfer(BankTransferData {
|
StripePaymentMethodData::BankTransfer(StripeBankTransferData::AchBankTransfer(
|
||||||
email: ach_bank_transfer_data.billing_details.email.to_owned(),
|
Box::new(AchBankTransferData {
|
||||||
}),
|
email: billing_details.email.to_owned(),
|
||||||
|
}),
|
||||||
|
)),
|
||||||
StripePaymentMethodType::AchCreditTransfer,
|
StripePaymentMethodType::AchCreditTransfer,
|
||||||
StripeBillingAddress::default(),
|
StripeBillingAddress::default(),
|
||||||
)),
|
)),
|
||||||
|
payments::BankTransferData::SepaBankTransfer {
|
||||||
|
billing_details,
|
||||||
|
country,
|
||||||
|
} => {
|
||||||
|
let billing_details = StripeBillingAddress {
|
||||||
|
email: Some(billing_details.email.clone()),
|
||||||
|
name: Some(billing_details.name.clone()),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
Ok((
|
||||||
|
StripePaymentMethodData::BankTransfer(
|
||||||
|
StripeBankTransferData::SepaBankTransfer(Box::new(
|
||||||
|
SepaBankTransferData {
|
||||||
|
payment_method_data_type:
|
||||||
|
StripePaymentMethodType::CustomerBalance,
|
||||||
|
bank_transfer_type: BankTransferType::EuBankTransfer,
|
||||||
|
balance_funding_type: BankTransferType::BankTransfers,
|
||||||
|
payment_method_type: StripePaymentMethodType::CustomerBalance,
|
||||||
|
country: country.to_owned(),
|
||||||
|
},
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
StripePaymentMethodType::CustomerBalance,
|
||||||
|
billing_details,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
payments::BankTransferData::BacsBankTransfer { billing_details } => {
|
||||||
|
let billing_details = StripeBillingAddress {
|
||||||
|
email: Some(billing_details.email.clone()),
|
||||||
|
name: Some(billing_details.name.clone()),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
Ok((
|
||||||
|
StripePaymentMethodData::BankTransfer(
|
||||||
|
StripeBankTransferData::BacsBankTransfers(Box::new(
|
||||||
|
BacsBankTransferData {
|
||||||
|
payment_method_data_type:
|
||||||
|
StripePaymentMethodType::CustomerBalance,
|
||||||
|
bank_transfer_type: BankTransferType::GbBankTransfer,
|
||||||
|
balance_funding_type: BankTransferType::BankTransfers,
|
||||||
|
payment_method_type: StripePaymentMethodType::CustomerBalance,
|
||||||
|
},
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
StripePaymentMethodType::CustomerBalance,
|
||||||
|
billing_details,
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => Err(errors::ConnectorError::NotImplemented(
|
_ => Err(errors::ConnectorError::NotImplemented(
|
||||||
@ -1336,6 +1439,20 @@ pub struct AchReceiverDetails {
|
|||||||
pub amount_charged: i64,
|
pub amount_charged: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[serde_with::skip_serializing_none]
|
||||||
|
#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
|
||||||
|
pub struct SepaAndBacsBankTransferInstructions {
|
||||||
|
pub bacs_bank_instructions: Option<BacsFinancialDetails>,
|
||||||
|
pub sepa_bank_instructions: Option<SepaFinancialDetails>,
|
||||||
|
pub receiver: SepaAndBacsReceiver,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
|
||||||
|
pub struct SepaAndBacsReceiver {
|
||||||
|
pub amount_received: i64,
|
||||||
|
pub amount_remaining: i64,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Eq, PartialEq, Deserialize)]
|
#[derive(Debug, Default, Eq, PartialEq, Deserialize)]
|
||||||
pub struct PaymentSyncResponse {
|
pub struct PaymentSyncResponse {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
@ -1455,7 +1572,8 @@ impl ForeignFrom<(Option<StripePaymentMethodOptions>, String)> for types::Mandat
|
|||||||
| StripePaymentMethodOptions::Alipay {}
|
| StripePaymentMethodOptions::Alipay {}
|
||||||
| StripePaymentMethodOptions::Sepa {}
|
| StripePaymentMethodOptions::Sepa {}
|
||||||
| StripePaymentMethodOptions::Bancontact {}
|
| StripePaymentMethodOptions::Bancontact {}
|
||||||
| StripePaymentMethodOptions::Przelewy24 {} => None,
|
| StripePaymentMethodOptions::Przelewy24 {}
|
||||||
|
| StripePaymentMethodOptions::CustomerBalance {} => None,
|
||||||
}),
|
}),
|
||||||
payment_method_id: Some(payment_method_id),
|
payment_method_id: Some(payment_method_id),
|
||||||
}
|
}
|
||||||
@ -1470,9 +1588,12 @@ impl<F, T>
|
|||||||
fn try_from(
|
fn try_from(
|
||||||
item: types::ResponseRouterData<F, PaymentIntentResponse, T, types::PaymentsResponseData>,
|
item: types::ResponseRouterData<F, PaymentIntentResponse, T, types::PaymentsResponseData>,
|
||||||
) -> Result<Self, Self::Error> {
|
) -> Result<Self, Self::Error> {
|
||||||
let redirection_data = item.response.next_action.map(|next_action_response| {
|
let redirect_data = item.response.next_action.clone();
|
||||||
services::RedirectForm::from((next_action_response.get_url(), services::Method::Get))
|
let redirection_data = redirect_data
|
||||||
});
|
.and_then(|redirection_data| redirection_data.get_url())
|
||||||
|
.map(|redirection_url| {
|
||||||
|
services::RedirectForm::from((redirection_url, services::Method::Get))
|
||||||
|
});
|
||||||
|
|
||||||
let mandate_reference = item.response.payment_method.map(|pm| {
|
let mandate_reference = item.response.payment_method.map(|pm| {
|
||||||
types::MandateReference::foreign_from((item.response.payment_method_options, pm))
|
types::MandateReference::foreign_from((item.response.payment_method_options, pm))
|
||||||
@ -1501,6 +1622,34 @@ impl<F, T>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_connector_metadata(
|
||||||
|
next_action: Option<&StripeNextActionResponse>,
|
||||||
|
amount: i64,
|
||||||
|
) -> CustomResult<Option<serde_json::Value>, errors::ConnectorError> {
|
||||||
|
let next_action_response = next_action
|
||||||
|
.and_then(|next_action_response| match next_action_response {
|
||||||
|
StripeNextActionResponse::DisplayBankTransferInstructions(response) => {
|
||||||
|
Some(SepaAndBacsBankTransferInstructions {
|
||||||
|
sepa_bank_instructions: response.financial_addresses[0].iban.to_owned(),
|
||||||
|
bacs_bank_instructions: response.financial_addresses[0]
|
||||||
|
.sort_code
|
||||||
|
.to_owned(),
|
||||||
|
receiver: SepaAndBacsReceiver {
|
||||||
|
amount_received: amount - response.amount_remaining,
|
||||||
|
amount_remaining: response.amount_remaining,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}).map(|response| {
|
||||||
|
common_utils::ext_traits::Encode::<SepaAndBacsBankTransferInstructions>::encode_to_value(
|
||||||
|
&response,
|
||||||
|
)
|
||||||
|
.change_context(errors::ConnectorError::ResponseHandlingFailed)
|
||||||
|
}).transpose()?;
|
||||||
|
Ok(next_action_response)
|
||||||
|
}
|
||||||
|
|
||||||
impl<F, T>
|
impl<F, T>
|
||||||
TryFrom<types::ResponseRouterData<F, PaymentIntentSyncResponse, T, types::PaymentsResponseData>>
|
TryFrom<types::ResponseRouterData<F, PaymentIntentSyncResponse, T, types::PaymentsResponseData>>
|
||||||
for types::RouterData<F, T, types::PaymentsResponseData>
|
for types::RouterData<F, T, types::PaymentsResponseData>
|
||||||
@ -1514,15 +1663,11 @@ impl<F, T>
|
|||||||
types::PaymentsResponseData,
|
types::PaymentsResponseData,
|
||||||
>,
|
>,
|
||||||
) -> Result<Self, Self::Error> {
|
) -> Result<Self, Self::Error> {
|
||||||
let redirection_data = item
|
let redirect_data = item.response.next_action.clone();
|
||||||
.response
|
let redirection_data = redirect_data
|
||||||
.next_action
|
.and_then(|redirection_data| redirection_data.get_url())
|
||||||
.as_ref()
|
.map(|redirection_url| {
|
||||||
.map(|next_action_response| {
|
services::RedirectForm::from((redirection_url, services::Method::Get))
|
||||||
services::RedirectForm::from((
|
|
||||||
next_action_response.get_url(),
|
|
||||||
services::Method::Get,
|
|
||||||
))
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let mandate_reference = item.response.payment_method.clone().map(|pm| {
|
let mandate_reference = item.response.payment_method.clone().map(|pm| {
|
||||||
@ -1542,12 +1687,15 @@ impl<F, T>
|
|||||||
status_code: item.http_code,
|
status_code: item.http_code,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let connector_metadata =
|
||||||
|
get_connector_metadata(item.response.next_action.as_ref(), item.response.amount)?;
|
||||||
|
|
||||||
let response = error_res.map_or(
|
let response = error_res.map_or(
|
||||||
Ok(types::PaymentsResponseData::TransactionResponse {
|
Ok(types::PaymentsResponseData::TransactionResponse {
|
||||||
resource_id: types::ResponseId::ConnectorTransactionId(item.response.id.clone()),
|
resource_id: types::ResponseId::ConnectorTransactionId(item.response.id.clone()),
|
||||||
redirection_data,
|
redirection_data,
|
||||||
mandate_reference,
|
mandate_reference,
|
||||||
connector_metadata: None,
|
connector_metadata,
|
||||||
network_txn_id: None,
|
network_txn_id: None,
|
||||||
}),
|
}),
|
||||||
Err,
|
Err,
|
||||||
@ -1570,9 +1718,12 @@ impl<F, T>
|
|||||||
fn try_from(
|
fn try_from(
|
||||||
item: types::ResponseRouterData<F, SetupIntentResponse, T, types::PaymentsResponseData>,
|
item: types::ResponseRouterData<F, SetupIntentResponse, T, types::PaymentsResponseData>,
|
||||||
) -> Result<Self, Self::Error> {
|
) -> Result<Self, Self::Error> {
|
||||||
let redirection_data = item.response.next_action.map(|next_action_response| {
|
let redirect_data = item.response.next_action.clone();
|
||||||
services::RedirectForm::from((next_action_response.get_url(), services::Method::Get))
|
let redirection_data = redirect_data
|
||||||
});
|
.and_then(|redirection_data| redirection_data.get_url())
|
||||||
|
.map(|redirection_url| {
|
||||||
|
services::RedirectForm::from((redirection_url, services::Method::Get))
|
||||||
|
});
|
||||||
|
|
||||||
let mandate_reference = item.response.payment_method.map(|pm| {
|
let mandate_reference = item.response.payment_method.map(|pm| {
|
||||||
types::MandateReference::foreign_from((item.response.payment_method_options, pm))
|
types::MandateReference::foreign_from((item.response.payment_method_options, pm))
|
||||||
@ -1616,18 +1767,20 @@ pub enum StripeNextActionResponse {
|
|||||||
AlipayHandleRedirect(StripeRedirectToUrlResponse),
|
AlipayHandleRedirect(StripeRedirectToUrlResponse),
|
||||||
VerifyWithMicrodeposits(StripeVerifyWithMicroDepositsResponse),
|
VerifyWithMicrodeposits(StripeVerifyWithMicroDepositsResponse),
|
||||||
WechatPayDisplayQrCode(StripeRedirectToQr),
|
WechatPayDisplayQrCode(StripeRedirectToQr),
|
||||||
|
DisplayBankTransferInstructions(StripeBankTransferDetails),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StripeNextActionResponse {
|
impl StripeNextActionResponse {
|
||||||
fn get_url(&self) -> Url {
|
fn get_url(&self) -> Option<Url> {
|
||||||
match self {
|
match self {
|
||||||
Self::RedirectToUrl(redirect_to_url) | Self::AlipayHandleRedirect(redirect_to_url) => {
|
Self::RedirectToUrl(redirect_to_url) | Self::AlipayHandleRedirect(redirect_to_url) => {
|
||||||
redirect_to_url.url.to_owned()
|
Some(redirect_to_url.url.to_owned())
|
||||||
}
|
}
|
||||||
Self::WechatPayDisplayQrCode(redirect_to_url) => redirect_to_url.data.to_owned(),
|
Self::WechatPayDisplayQrCode(redirect_to_url) => Some(redirect_to_url.data.to_owned()),
|
||||||
Self::VerifyWithMicrodeposits(verify_with_microdeposits) => {
|
Self::VerifyWithMicrodeposits(verify_with_microdeposits) => {
|
||||||
verify_with_microdeposits.hosted_verification_url.to_owned()
|
Some(verify_with_microdeposits.hosted_verification_url.to_owned())
|
||||||
}
|
}
|
||||||
|
Self::DisplayBankTransferInstructions(_) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1668,6 +1821,41 @@ pub struct StripeVerifyWithMicroDepositsResponse {
|
|||||||
hosted_verification_url: Url,
|
hosted_verification_url: Url,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
|
||||||
|
pub struct StripeBankTransferDetails {
|
||||||
|
pub amount_remaining: i64,
|
||||||
|
pub currency: String,
|
||||||
|
pub financial_addresses: Vec<StripeFinanicalInformation>,
|
||||||
|
pub hosted_instructions_url: Option<String>,
|
||||||
|
pub reference: Option<String>,
|
||||||
|
#[serde(rename = "type")]
|
||||||
|
pub bank_transfer_type: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
|
||||||
|
pub struct StripeFinanicalInformation {
|
||||||
|
pub iban: Option<SepaFinancialDetails>,
|
||||||
|
pub sort_code: Option<BacsFinancialDetails>,
|
||||||
|
pub supported_networks: Vec<String>,
|
||||||
|
#[serde(rename = "type")]
|
||||||
|
pub financial_info_type: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
|
||||||
|
pub struct SepaFinancialDetails {
|
||||||
|
pub account_holder_name: String,
|
||||||
|
pub bic: String,
|
||||||
|
pub country: String,
|
||||||
|
pub iban: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
|
||||||
|
pub struct BacsFinancialDetails {
|
||||||
|
pub account_holder_name: String,
|
||||||
|
pub account_number: String,
|
||||||
|
pub sort_code: String,
|
||||||
|
}
|
||||||
|
|
||||||
// REFUND :
|
// REFUND :
|
||||||
// Type definition for Stripe RefundRequest
|
// Type definition for Stripe RefundRequest
|
||||||
|
|
||||||
@ -1872,6 +2060,7 @@ pub enum StripePaymentMethodOptions {
|
|||||||
Alipay {},
|
Alipay {},
|
||||||
#[serde(rename = "p24")]
|
#[serde(rename = "p24")]
|
||||||
Przelewy24 {},
|
Przelewy24 {},
|
||||||
|
CustomerBalance {},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
|
||||||
@ -1916,14 +2105,9 @@ impl TryFrom<&types::PaymentsPreProcessingRouterData> for StripeAchSourceRequest
|
|||||||
fn try_from(item: &types::PaymentsPreProcessingRouterData) -> Result<Self, Self::Error> {
|
fn try_from(item: &types::PaymentsPreProcessingRouterData) -> Result<Self, Self::Error> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
transfer_type: StripePaymentMethodType::AchCreditTransfer,
|
transfer_type: StripePaymentMethodType::AchCreditTransfer,
|
||||||
email: item
|
payment_method_data: AchBankTransferData {
|
||||||
.request
|
email: connector::utils::PaymentsPreProcessingData::get_email(&item.request)?,
|
||||||
.email
|
},
|
||||||
.clone()
|
|
||||||
.get_required_value("email")
|
|
||||||
.change_context(errors::ConnectorError::MissingRequiredField {
|
|
||||||
field_name: "email",
|
|
||||||
})?,
|
|
||||||
currency: item
|
currency: item
|
||||||
.request
|
.request
|
||||||
.currency
|
.currency
|
||||||
@ -2006,7 +2190,7 @@ impl<F, T> TryFrom<types::ResponseRouterData<F, ChargesResponse, T, types::Payme
|
|||||||
common_utils::ext_traits::Encode::<StripeSourceResponse>::encode_to_value(
|
common_utils::ext_traits::Encode::<StripeSourceResponse>::encode_to_value(
|
||||||
&connector_source_response.source,
|
&connector_source_response.source,
|
||||||
)
|
)
|
||||||
.change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?;
|
.change_context(errors::ConnectorError::ResponseHandlingFailed)?;
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
status: enums::AttemptStatus::from(item.response.status),
|
status: enums::AttemptStatus::from(item.response.status),
|
||||||
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
||||||
@ -2185,6 +2369,8 @@ pub enum WebhookEventType {
|
|||||||
SourceChargeable,
|
SourceChargeable,
|
||||||
#[serde(rename = "source.transaction.created")]
|
#[serde(rename = "source.transaction.created")]
|
||||||
SourceTransactionCreated,
|
SourceTransactionCreated,
|
||||||
|
#[serde(rename = "payment_intent.partially_funded")]
|
||||||
|
PaymentIntentPartiallyFunded,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, strum::Display, Deserialize, PartialEq)]
|
#[derive(Debug, Serialize, strum::Display, Deserialize, PartialEq)]
|
||||||
@ -2303,11 +2489,32 @@ impl
|
|||||||
}
|
}
|
||||||
api::PaymentMethodData::BankTransfer(bank_transfer_data) => {
|
api::PaymentMethodData::BankTransfer(bank_transfer_data) => {
|
||||||
match bank_transfer_data.deref() {
|
match bank_transfer_data.deref() {
|
||||||
payments::BankTransferData::AchBankTransfer(ach_bank_transfer_data) => {
|
payments::BankTransferData::AchBankTransfer { billing_details } => {
|
||||||
Ok(Self::AchBankTransfer(BankTransferData {
|
Ok(Self::BankTransfer(StripeBankTransferData::AchBankTransfer(
|
||||||
email: ach_bank_transfer_data.billing_details.email.to_owned(),
|
Box::new(AchBankTransferData {
|
||||||
}))
|
email: billing_details.email.to_owned(),
|
||||||
|
}),
|
||||||
|
)))
|
||||||
}
|
}
|
||||||
|
payments::BankTransferData::SepaBankTransfer { country, .. } => Ok(
|
||||||
|
Self::BankTransfer(StripeBankTransferData::SepaBankTransfer(Box::new(
|
||||||
|
SepaBankTransferData {
|
||||||
|
payment_method_data_type: StripePaymentMethodType::CustomerBalance,
|
||||||
|
bank_transfer_type: BankTransferType::EuBankTransfer,
|
||||||
|
balance_funding_type: BankTransferType::BankTransfers,
|
||||||
|
payment_method_type: StripePaymentMethodType::CustomerBalance,
|
||||||
|
country: country.to_owned(),
|
||||||
|
},
|
||||||
|
))),
|
||||||
|
),
|
||||||
|
payments::BankTransferData::BacsBankTransfer { .. } => Ok(Self::BankTransfer(
|
||||||
|
StripeBankTransferData::BacsBankTransfers(Box::new(BacsBankTransferData {
|
||||||
|
payment_method_data_type: StripePaymentMethodType::CustomerBalance,
|
||||||
|
bank_transfer_type: BankTransferType::GbBankTransfer,
|
||||||
|
balance_funding_type: BankTransferType::BankTransfers,
|
||||||
|
payment_method_type: StripePaymentMethodType::CustomerBalance,
|
||||||
|
})),
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
api::PaymentMethodData::MandatePayment | api::PaymentMethodData::Crypto(_) => {
|
api::PaymentMethodData::MandatePayment | api::PaymentMethodData::Crypto(_) => {
|
||||||
@ -2326,35 +2533,58 @@ impl
|
|||||||
pub struct StripeGpayToken {
|
pub struct StripeGpayToken {
|
||||||
pub id: String,
|
pub id: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_bank_transfer_request_data(
|
pub fn get_bank_transfer_request_data(
|
||||||
req: &types::PaymentsAuthorizeRouterData,
|
req: &types::PaymentsAuthorizeRouterData,
|
||||||
bank_transfer_data: &api_models::payments::BankTransferData,
|
bank_transfer_data: &api_models::payments::BankTransferData,
|
||||||
) -> CustomResult<Option<String>, errors::ConnectorError> {
|
) -> CustomResult<Option<String>, errors::ConnectorError> {
|
||||||
match bank_transfer_data {
|
match bank_transfer_data {
|
||||||
api_models::payments::BankTransferData::AchBankTransfer(_) => {
|
api_models::payments::BankTransferData::AchBankTransfer { .. } => {
|
||||||
let req = ChargesRequest::try_from(req)?;
|
let req = ChargesRequest::try_from(req)?;
|
||||||
let request = utils::Encode::<ChargesRequest>::url_encode(&req)
|
let request = utils::Encode::<ChargesRequest>::url_encode(&req)
|
||||||
.change_context(errors::ConnectorError::RequestEncodingFailed)?;
|
.change_context(errors::ConnectorError::RequestEncodingFailed)?;
|
||||||
Ok(Some(request))
|
Ok(Some(request))
|
||||||
}
|
}
|
||||||
|
_ => {
|
||||||
|
let req = PaymentIntentRequest::try_from(req)?;
|
||||||
|
let request = utils::Encode::<PaymentIntentRequest>::url_encode(&req)
|
||||||
|
.change_context(errors::ConnectorError::RequestEncodingFailed)?;
|
||||||
|
Ok(Some(request))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_bank_transfer_authorize_response(
|
pub fn get_bank_transfer_authorize_response(
|
||||||
data: &types::PaymentsAuthorizeRouterData,
|
data: &types::PaymentsAuthorizeRouterData,
|
||||||
res: types::Response,
|
res: types::Response,
|
||||||
_bank_transfer_data: &api_models::payments::BankTransferData,
|
bank_transfer_data: &api_models::payments::BankTransferData,
|
||||||
) -> CustomResult<types::PaymentsAuthorizeRouterData, errors::ConnectorError> {
|
) -> CustomResult<types::PaymentsAuthorizeRouterData, errors::ConnectorError> {
|
||||||
let response: ChargesResponse = res
|
match bank_transfer_data {
|
||||||
.response
|
api_models::payments::BankTransferData::AchBankTransfer { .. } => {
|
||||||
.parse_struct("ChargesResponse")
|
let response: ChargesResponse = res
|
||||||
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
|
.response
|
||||||
|
.parse_struct("ChargesResponse")
|
||||||
|
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
|
||||||
|
|
||||||
types::RouterData::try_from(types::ResponseRouterData {
|
types::RouterData::try_from(types::ResponseRouterData {
|
||||||
response,
|
response,
|
||||||
data: data.clone(),
|
data: data.clone(),
|
||||||
http_code: res.status_code,
|
http_code: res.status_code,
|
||||||
})
|
})
|
||||||
.change_context(errors::ConnectorError::ResponseHandlingFailed)
|
}
|
||||||
|
_ => {
|
||||||
|
let response: PaymentIntentResponse = res
|
||||||
|
.response
|
||||||
|
.parse_struct("PaymentIntentResponse")
|
||||||
|
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
|
||||||
|
|
||||||
|
types::RouterData::try_from(types::ResponseRouterData {
|
||||||
|
response,
|
||||||
|
data: data.clone(),
|
||||||
|
http_code: res.status_code,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn construct_file_upload_request(
|
pub fn construct_file_upload_request(
|
||||||
|
|||||||
@ -159,6 +159,16 @@ impl<Flow, Request, Response> RouterData for types::RouterData<Flow, Request, Re
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait PaymentsPreProcessingData {
|
||||||
|
fn get_email(&self) -> Result<Email, Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PaymentsPreProcessingData for types::PaymentsPreProcessingData {
|
||||||
|
fn get_email(&self) -> Result<Email, Error> {
|
||||||
|
self.email.clone().ok_or_else(missing_field_err("email"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait PaymentsAuthorizeRequestData {
|
pub trait PaymentsAuthorizeRequestData {
|
||||||
fn is_auto_capture(&self) -> Result<bool, Error>;
|
fn is_auto_capture(&self) -> Result<bool, Error>;
|
||||||
fn get_email(&self) -> Result<Email, Error>;
|
fn get_email(&self) -> Result<Email, Error>;
|
||||||
|
|||||||
@ -881,6 +881,9 @@ pub async fn list_payment_methods(
|
|||||||
let mut bank_debits_consolidated_hm =
|
let mut bank_debits_consolidated_hm =
|
||||||
HashMap::<api_enums::PaymentMethodType, Vec<String>>::new();
|
HashMap::<api_enums::PaymentMethodType, Vec<String>>::new();
|
||||||
|
|
||||||
|
let mut bank_transfer_consolidated_hm =
|
||||||
|
HashMap::<api_enums::PaymentMethodType, Vec<String>>::new();
|
||||||
|
|
||||||
for element in response.clone() {
|
for element in response.clone() {
|
||||||
let payment_method = element.payment_method;
|
let payment_method = element.payment_method;
|
||||||
let payment_method_type = element.payment_method_type;
|
let payment_method_type = element.payment_method_type;
|
||||||
@ -982,6 +985,17 @@ pub async fn list_payment_methods(
|
|||||||
bank_debits_consolidated_hm.insert(element.payment_method_type, vec![connector]);
|
bank_debits_consolidated_hm.insert(element.payment_method_type, vec![connector]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if element.payment_method == api_enums::PaymentMethod::BankTransfer {
|
||||||
|
let connector = element.connector.clone();
|
||||||
|
if let Some(vector_of_connectors) =
|
||||||
|
bank_transfer_consolidated_hm.get_mut(&element.payment_method_type)
|
||||||
|
{
|
||||||
|
vector_of_connectors.push(connector);
|
||||||
|
} else {
|
||||||
|
bank_transfer_consolidated_hm.insert(element.payment_method_type, vec![connector]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut payment_method_responses: Vec<ResponsePaymentMethodsEnabled> = vec![];
|
let mut payment_method_responses: Vec<ResponsePaymentMethodsEnabled> = vec![];
|
||||||
@ -1002,6 +1016,7 @@ pub async fn list_payment_methods(
|
|||||||
card_networks: None,
|
card_networks: None,
|
||||||
bank_names: None,
|
bank_names: None,
|
||||||
bank_debits: None,
|
bank_debits: None,
|
||||||
|
bank_transfers: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1028,6 +1043,7 @@ pub async fn list_payment_methods(
|
|||||||
payment_experience: None,
|
payment_experience: None,
|
||||||
bank_names: None,
|
bank_names: None,
|
||||||
bank_debits: None,
|
bank_debits: None,
|
||||||
|
bank_transfers: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1050,6 +1066,7 @@ pub async fn list_payment_methods(
|
|||||||
payment_experience: None,
|
payment_experience: None,
|
||||||
card_networks: None,
|
card_networks: None,
|
||||||
bank_debits: None,
|
bank_debits: None,
|
||||||
|
bank_transfers: None,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -1073,8 +1090,9 @@ pub async fn list_payment_methods(
|
|||||||
payment_experience: None,
|
payment_experience: None,
|
||||||
card_networks: None,
|
card_networks: None,
|
||||||
bank_debits: Some(api_models::payment_methods::BankDebitTypes {
|
bank_debits: Some(api_models::payment_methods::BankDebitTypes {
|
||||||
eligible_connectors: connectors,
|
eligible_connectors: connectors.clone(),
|
||||||
}),
|
}),
|
||||||
|
bank_transfers: None,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -1086,6 +1104,32 @@ pub async fn list_payment_methods(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut bank_transfer_payment_method_types = vec![];
|
||||||
|
|
||||||
|
for key in bank_transfer_consolidated_hm.iter() {
|
||||||
|
let payment_method_type = *key.0;
|
||||||
|
let connectors = key.1.clone();
|
||||||
|
bank_transfer_payment_method_types.push({
|
||||||
|
ResponsePaymentMethodTypes {
|
||||||
|
payment_method_type,
|
||||||
|
bank_names: None,
|
||||||
|
payment_experience: None,
|
||||||
|
card_networks: None,
|
||||||
|
bank_debits: None,
|
||||||
|
bank_transfers: Some(api_models::payment_methods::BankTransferTypes {
|
||||||
|
eligible_connectors: connectors,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if !bank_transfer_payment_method_types.is_empty() {
|
||||||
|
payment_method_responses.push(ResponsePaymentMethodsEnabled {
|
||||||
|
payment_method: api_enums::PaymentMethod::BankTransfer,
|
||||||
|
payment_method_types: bank_transfer_payment_method_types,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
response
|
response
|
||||||
.is_empty()
|
.is_empty()
|
||||||
.then(|| Err(report!(errors::ApiErrorResponse::PaymentMethodNotFound)))
|
.then(|| Err(report!(errors::ApiErrorResponse::PaymentMethodNotFound)))
|
||||||
|
|||||||
@ -691,7 +691,7 @@ where
|
|||||||
//TODO: For ACH transfers, if preprocessing_step is not required for connectors encountered in future, add the check
|
//TODO: For ACH transfers, if preprocessing_step is not required for connectors encountered in future, add the check
|
||||||
let router_data_and_should_continue_payment = match payment_data.payment_method_data.clone() {
|
let router_data_and_should_continue_payment = match payment_data.payment_method_data.clone() {
|
||||||
Some(api_models::payments::PaymentMethodData::BankTransfer(data)) => match data.deref() {
|
Some(api_models::payments::PaymentMethodData::BankTransfer(data)) => match data.deref() {
|
||||||
api_models::payments::BankTransferData::AchBankTransfer(_) => {
|
api_models::payments::BankTransferData::AchBankTransfer { .. } => {
|
||||||
if payment_data.payment_attempt.preprocessing_step_id.is_none() {
|
if payment_data.payment_attempt.preprocessing_step_id.is_none() {
|
||||||
(
|
(
|
||||||
router_data.preprocessing_steps(state, connector).await?,
|
router_data.preprocessing_steps(state, connector).await?,
|
||||||
@ -701,6 +701,7 @@ where
|
|||||||
(router_data, should_continue_payment)
|
(router_data, should_continue_payment)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_ => (router_data, should_continue_payment),
|
||||||
},
|
},
|
||||||
_ => (router_data, should_continue_payment),
|
_ => (router_data, should_continue_payment),
|
||||||
};
|
};
|
||||||
|
|||||||
@ -218,7 +218,8 @@ impl ForeignTryFrom<api_enums::IntentStatus> for storage_enums::EventType {
|
|||||||
api_enums::IntentStatus::Succeeded => Ok(Self::PaymentSucceeded),
|
api_enums::IntentStatus::Succeeded => Ok(Self::PaymentSucceeded),
|
||||||
api_enums::IntentStatus::Failed => Ok(Self::PaymentFailed),
|
api_enums::IntentStatus::Failed => Ok(Self::PaymentFailed),
|
||||||
api_enums::IntentStatus::Processing => Ok(Self::PaymentProcessing),
|
api_enums::IntentStatus::Processing => Ok(Self::PaymentProcessing),
|
||||||
api_enums::IntentStatus::RequiresMerchantAction => Ok(Self::ActionRequired),
|
api_enums::IntentStatus::RequiresMerchantAction
|
||||||
|
| api_enums::IntentStatus::RequiresCustomerAction => Ok(Self::ActionRequired),
|
||||||
_ => Err(errors::ValidationError::IncorrectValueProvided {
|
_ => Err(errors::ValidationError::IncorrectValueProvided {
|
||||||
field_name: "intent_status",
|
field_name: "intent_status",
|
||||||
}),
|
}),
|
||||||
|
|||||||
Reference in New Issue
Block a user