Skip to content

Commit

Permalink
feat: SEPA and BACS bank transfers through stripe (#930)
Browse files Browse the repository at this point in the history
  • Loading branch information
Sangamesh26 authored May 19, 2023
1 parent 53aa5ac commit cf00059
Show file tree
Hide file tree
Showing 9 changed files with 423 additions and 82 deletions.
9 changes: 9 additions & 0 deletions crates/api_models/src/payment_methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,8 @@ pub struct ResponsePaymentMethodTypes {

/// The Bank debit payment method information, if applicable for a payment method type.
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)]
Expand All @@ -217,6 +219,13 @@ pub struct ResponsePaymentMethodsEnabled {
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)]
pub struct ResponsePaymentMethodIntermediate {
pub payment_method_type: api_enums::PaymentMethodType,
Expand Down
50 changes: 43 additions & 7 deletions crates/api_models/src/payments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -724,13 +724,14 @@ pub enum BankRedirectData {
}

#[derive(Debug, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
pub struct AchBankTransferData {
pub billing_details: AchBillingDetails,
pub struct AchBillingDetails {
pub email: Email,
}

#[derive(Debug, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
pub struct AchBillingDetails {
pub struct SepaAndBacsBillingDetails {
pub email: Email,
pub name: Secret<String>,
}

#[derive(Debug, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize, ToSchema)]
Expand All @@ -757,7 +758,16 @@ pub struct BankRedirectBilling {
#[derive(Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)]
#[serde(rename_all = "snake_case")]
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)]
Expand Down Expand Up @@ -878,6 +888,7 @@ pub struct CardResponse {
}

#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize)]
#[serde(rename_all = "snake_case")]
pub enum PaymentMethodDataResponse {
#[serde(rename = "card")]
Card(CardResponse),
Expand Down Expand Up @@ -1071,10 +1082,34 @@ pub struct NextAction {

#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct NextStepsRequirements {
pub ach_credit_transfer: AchTransfer,
#[serde(flatten)]
pub bank_transfer_instructions: BankTransferInstructions,
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)]
pub struct AchTransfer {
pub account_number: Secret<String>,
Expand All @@ -1085,8 +1120,9 @@ pub struct AchTransfer {

#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct ReceiverDetails {
pub amount_received: i64,
pub amount_charged: i64,
amount_received: i64,
amount_charged: Option<i64>,
amount_remaining: Option<i64>,
}

#[derive(Setter, Clone, Default, Debug, Eq, PartialEq, serde::Serialize, ToSchema)]
Expand Down
2 changes: 2 additions & 0 deletions crates/api_models/src/webhooks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pub enum IncomingWebhookEvent {
PaymentIntentFailure,
PaymentIntentSuccess,
PaymentIntentProcessing,
PaymentIntentPartiallyFunded,
PaymentActionRequired,
EventNotSupported,
SourceChargeable,
Expand Down Expand Up @@ -45,6 +46,7 @@ impl From<IncomingWebhookEvent> for WebhookFlow {
IncomingWebhookEvent::PaymentIntentSuccess => Self::Payment,
IncomingWebhookEvent::PaymentIntentProcessing => Self::Payment,
IncomingWebhookEvent::PaymentActionRequired => Self::Payment,
IncomingWebhookEvent::PaymentIntentPartiallyFunded => Self::Payment,
IncomingWebhookEvent::EventNotSupported => Self::ReturnResponse,
IncomingWebhookEvent::RefundSuccess => Self::Refund,
IncomingWebhookEvent::RefundFailure => Self::Refund,
Expand Down
16 changes: 12 additions & 4 deletions crates/router/src/connector/stripe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -686,9 +686,14 @@ impl
match &req.request.payment_method_data {
api_models::payments::PaymentMethodData::BankTransfer(bank_transfer_data) => {
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/payment_intents"
)),
}
}
_ => Ok(format!(
Expand Down Expand Up @@ -1682,9 +1687,6 @@ impl api::IncomingWebhook for Stripe {
stripe::WebhookEventType::SourceChargeable => {
api::IncomingWebhookEvent::SourceChargeable
}
stripe::WebhookEventType::SourceTransactionCreated => {
api::IncomingWebhookEvent::SourceTransactionCreated
}
stripe::WebhookEventType::ChargeSucceeded => api::IncomingWebhookEvent::ChargeSucceeded,
stripe::WebhookEventType::DisputeCreated => api::IncomingWebhookEvent::DisputeOpened,
stripe::WebhookEventType::DisputeClosed => api::IncomingWebhookEvent::DisputeCancelled,
Expand All @@ -1695,6 +1697,12 @@ impl api::IncomingWebhook for Stripe {
.status
.ok_or(errors::ConnectorError::WebhookEventTypeNotFound)?,
)?,
stripe::WebhookEventType::PaymentIntentPartiallyFunded => {
api::IncomingWebhookEvent::PaymentIntentPartiallyFunded
}
stripe::WebhookEventType::PaymentIntentRequiresAction => {
api::IncomingWebhookEvent::PaymentActionRequired
}
_ => Err(errors::ConnectorError::WebhookEventTypeNotFound).into_report()?,
})
}
Expand Down
Loading

0 comments on commit cf00059

Please sign in to comment.